diff --git a/NEWS b/NEWS index ba0ccc3d..f3fa3547 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,27 @@ This file lists notable changes in each release. For the full history of all changes, see ChangeLog. +2019-11-20: v1.90.0 release + +This release updates the core of the library to use GLib routines and Gio +style APIs. While the API both for library users remain similar in most +ways, there are some changes and all users will need to be ported. + +A large motivation for the in-depth changes was the requirement to add +new API to support sensors that store the prints on the sensor. This +support is already used by the new synaptics driver, which will support +the current generation of the Prometheus MIS (match-in-sensor) chipset +by Synaptics (USB ID 06cb:00bd). + +The current codebase is considered stable at this point. However, due to +the lack of wider testing it is only released as a 1.90.0 release which +can be considered a beta-release for 2.0. + +With the rewrite, it is now also possible to support devices that are not +connected through USB (e.g. I2C). Another major improvement is that the +library has now a test suite, testing both the library core and allowing +tests of the drivers using umockdev. + 2019-08-08: v1.0 release * Library: - Add guards to the public API and require GLib 2.50 diff --git a/demo/gtk-libfprint-test.c b/demo/gtk-libfprint-test.c index d0dd0c1e..c6dd90e2 100644 --- a/demo/gtk-libfprint-test.c +++ b/demo/gtk-libfprint-test.c @@ -22,34 +22,36 @@ #include #include -#include "loop.h" - -typedef GtkApplication LibfprintDemo; +typedef GtkApplication LibfprintDemo; typedef GtkApplicationClass LibfprintDemoClass; G_DEFINE_TYPE (LibfprintDemo, libfprint_demo, GTK_TYPE_APPLICATION) typedef enum { - IMAGE_DISPLAY_NONE = 0, - IMAGE_DISPLAY_MINUTIAE = 1 << 0, - IMAGE_DISPLAY_BINARY = 1 << 1 + IMAGE_DISPLAY_NONE = 0, + IMAGE_DISPLAY_MINUTIAE = 1 << 0, + IMAGE_DISPLAY_BINARY = 1 << 1 } ImageDisplayFlags; -typedef struct { - GtkApplicationWindow parent_instance; +typedef struct +{ + GtkApplicationWindow parent_instance; - GtkWidget *header_bar; - GtkWidget *mode_stack; - GtkWidget *capture_button; - GtkWidget *capture_image; - GtkWidget *spinner; - GtkWidget *instructions; + GtkWidget *header_bar; + GtkWidget *mode_stack; + GtkWidget *capture_button; + GtkWidget *cancel_button; + GtkWidget *capture_image; + GtkWidget *spinner; + GtkWidget *instructions; - struct fp_dscv_dev *ddev; - struct fp_dev *dev; + GCancellable *cancellable; - struct fp_img *img; - ImageDisplayFlags img_flags; + gboolean opened; + FpDevice *dev; + + FpImage *img; + ImageDisplayFlags img_flags; } LibfprintDemoWindow; typedef GtkApplicationWindowClass LibfprintDemoWindowClass; @@ -57,467 +59,506 @@ typedef GtkApplicationWindowClass LibfprintDemoWindowClass; G_DEFINE_TYPE (LibfprintDemoWindow, libfprint_demo_window, GTK_TYPE_APPLICATION_WINDOW) typedef enum { - EMPTY_MODE, - NOIMAGING_MODE, - CAPTURE_MODE, - SPINNER_MODE, - ERROR_MODE + EMPTY_MODE, + NOIMAGING_MODE, + CAPTURE_MODE, + SPINNER_MODE, + ERROR_MODE, + RETRY_MODE } LibfprintDemoMode; static void libfprint_demo_set_mode (LibfprintDemoWindow *win, - LibfprintDemoMode mode); - -static void -pixbuf_destroy (guchar *pixels, gpointer data) -{ - if (pixels == NULL) - return; - g_free (pixels); -} + LibfprintDemoMode mode); static unsigned char * -img_to_rgbdata (struct fp_img *img, - int width, - int height) +img_to_rgbdata (const guint8 *imgdata, + int width, + int height) { - int size = width * height; - unsigned char *imgdata = fp_img_get_data (img); - unsigned char *rgbdata = g_malloc (size * 3); - size_t i; - size_t rgb_offset = 0; + int size = width * height; + guint8 *rgbdata = g_malloc (size * 3); + size_t i; + size_t rgb_offset = 0; - for (i = 0; i < size; i++) { - unsigned char pixel = imgdata[i]; + for (i = 0; i < size; i++) + { + guint8 pixel = imgdata[i]; - rgbdata[rgb_offset++] = pixel; - rgbdata[rgb_offset++] = pixel; - rgbdata[rgb_offset++] = pixel; - } + rgbdata[rgb_offset++] = pixel; + rgbdata[rgb_offset++] = pixel; + rgbdata[rgb_offset++] = pixel; + } - return rgbdata; + return rgbdata; } static void -plot_minutiae (unsigned char *rgbdata, - int width, - int height, - struct fp_minutia **minlist, - int nr_minutiae) +plot_minutiae (unsigned char *rgbdata, + int width, + int height, + GPtrArray *minutiae) { - int i; + int i; + #define write_pixel(num) do { \ - rgbdata[((num) * 3)] = 0xff; \ - rgbdata[((num) * 3) + 1] = 0; \ - rgbdata[((num) * 3) + 2] = 0; \ - } while(0) + rgbdata[((num) * 3)] = 0xff; \ + rgbdata[((num) * 3) + 1] = 0; \ + rgbdata[((num) * 3) + 2] = 0; \ + } while(0) - for (i = 0; i < nr_minutiae; i++) { - struct fp_minutia *min = minlist[i]; - int x, y; - size_t pixel_offset; + for (i = 0; i < minutiae->len; i++) + { + struct fp_minutia *min = g_ptr_array_index (minutiae, i); + int x, y; + size_t pixel_offset; - fp_minutia_get_coords(min, &x, &y); - pixel_offset = (y * width) + x; - write_pixel(pixel_offset - 2); - write_pixel(pixel_offset - 1); - write_pixel(pixel_offset); - write_pixel(pixel_offset + 1); - write_pixel(pixel_offset + 2); + fp_minutia_get_coords (min, &x, &y); + pixel_offset = (y * width) + x; + write_pixel (pixel_offset - 2); + write_pixel (pixel_offset - 1); + write_pixel (pixel_offset); + write_pixel (pixel_offset + 1); + write_pixel (pixel_offset + 2); - write_pixel(pixel_offset - (width * 2)); - write_pixel(pixel_offset - (width * 1) - 1); - write_pixel(pixel_offset - (width * 1)); - write_pixel(pixel_offset - (width * 1) + 1); - write_pixel(pixel_offset + (width * 1) - 1); - write_pixel(pixel_offset + (width * 1)); - write_pixel(pixel_offset + (width * 1) + 1); - write_pixel(pixel_offset + (width * 2)); - } + write_pixel (pixel_offset - (width * 2)); + write_pixel (pixel_offset - (width * 1) - 1); + write_pixel (pixel_offset - (width * 1)); + write_pixel (pixel_offset - (width * 1) + 1); + write_pixel (pixel_offset + (width * 1) - 1); + write_pixel (pixel_offset + (width * 1)); + write_pixel (pixel_offset + (width * 1) + 1); + write_pixel (pixel_offset + (width * 2)); + } } static GdkPixbuf * -img_to_pixbuf (struct fp_img *img, - ImageDisplayFlags flags) +img_to_pixbuf (FpImage *img, + ImageDisplayFlags flags) { - int width; - int height; - unsigned char *rgbdata; + int width; + int height; + const guint8 *data; + unsigned char *rgbdata; - width = fp_img_get_width (img); - height = fp_img_get_height (img); + width = fp_image_get_width (img); + height = fp_image_get_height (img); - if (flags & IMAGE_DISPLAY_BINARY) { - struct fp_img *binary; - binary = fp_img_binarize (img); - rgbdata = img_to_rgbdata (binary, width, height); - fp_img_free (binary); - } else { - rgbdata = img_to_rgbdata (img, width, height); - } + if (flags & IMAGE_DISPLAY_BINARY) + data = fp_image_get_binarized (img, NULL); + else + data = fp_image_get_data (img, NULL); - if (flags & IMAGE_DISPLAY_MINUTIAE) { - struct fp_minutia **minlist; - int nr_minutiae; + if (!data) + return NULL; - minlist = fp_img_get_minutiae (img, &nr_minutiae); - plot_minutiae (rgbdata, width, height, minlist, nr_minutiae); - } + rgbdata = img_to_rgbdata (data, width, height); - return gdk_pixbuf_new_from_data (rgbdata, GDK_COLORSPACE_RGB, - FALSE, 8, width, height, - width * 3, pixbuf_destroy, - NULL); + if (flags & IMAGE_DISPLAY_MINUTIAE) + { + GPtrArray *minutiae; + + minutiae = fp_image_get_minutiae (img); + plot_minutiae (rgbdata, width, height, minutiae); + } + + return gdk_pixbuf_new_from_data (rgbdata, GDK_COLORSPACE_RGB, + FALSE, 8, width, height, + width * 3, (GdkPixbufDestroyNotify) g_free, + NULL); } static void update_image (LibfprintDemoWindow *win) { - GdkPixbuf *pixbuf; + GdkPixbuf *pixbuf; - if (win->img == NULL) { - gtk_image_clear (GTK_IMAGE (win->capture_image)); - return; - } + if (win->img == NULL) + { + gtk_image_clear (GTK_IMAGE (win->capture_image)); + return; + } - g_debug ("Updating image, minutiae %s, binary mode %s", - win->img_flags & IMAGE_DISPLAY_MINUTIAE ? "shown" : "hidden", - win->img_flags & IMAGE_DISPLAY_BINARY ? "on" : "off"); - pixbuf = img_to_pixbuf (win->img, win->img_flags); - gtk_image_set_from_pixbuf (GTK_IMAGE (win->capture_image), pixbuf); - g_object_unref (pixbuf); + g_debug ("Updating image, minutiae %s, binary mode %s", + win->img_flags & IMAGE_DISPLAY_MINUTIAE ? "shown" : "hidden", + win->img_flags & IMAGE_DISPLAY_BINARY ? "on" : "off"); + pixbuf = img_to_pixbuf (win->img, win->img_flags); + gtk_image_set_from_pixbuf (GTK_IMAGE (win->capture_image), pixbuf); + g_object_unref (pixbuf); } static void libfprint_demo_set_spinner_label (LibfprintDemoWindow *win, - const char *message) + const char *message) { - char *label; + char *label; - label = g_strdup_printf ("%s", message); - gtk_label_set_markup (GTK_LABEL (win->instructions), label); - g_free (label); + label = g_strdup_printf ("%s", message); + gtk_label_set_markup (GTK_LABEL (win->instructions), label); + g_free (label); } static void libfprint_demo_set_capture_label (LibfprintDemoWindow *win) { - struct fp_driver *drv; - enum fp_scan_type scan_type; - const char *message; + FpScanType scan_type; + const char *message; - drv = fp_dscv_dev_get_driver (win->ddev); - scan_type = fp_driver_get_scan_type(drv); + scan_type = fp_device_get_scan_type (win->dev); - switch (scan_type) { - case FP_SCAN_TYPE_PRESS: - message = "Place your finger on the fingerprint reader"; - break; - case FP_SCAN_TYPE_SWIPE: - message = "Swipe your finger across the fingerprint reader"; - break; - default: - g_assert_not_reached (); - } + switch (scan_type) + { + case FP_SCAN_TYPE_PRESS: + message = "Place your finger on the fingerprint reader"; + break; - libfprint_demo_set_spinner_label (win, message); + case FP_SCAN_TYPE_SWIPE: + message = "Swipe your finger across the fingerprint reader"; + break; + + default: + g_assert_not_reached (); + } + + libfprint_demo_set_spinner_label (win, message); } static void -dev_capture_start_cb (struct fp_dev *dev, - int result, - struct fp_img *img, - void *user_data) +dev_capture_start_cb (FpDevice *dev, + GAsyncResult *res, + void *user_data) { - LibfprintDemoWindow *win = user_data; + g_autoptr(GError) error = NULL; + LibfprintDemoWindow *win = user_data; + FpImage *image = NULL; - if (result < 0) { - libfprint_demo_set_mode (win, ERROR_MODE); - return; - } + g_clear_object (&win->cancellable); - fp_async_capture_stop (dev, NULL, NULL); + image = fp_device_capture_finish (dev, res, &error); + if (!image) + { + g_warning ("Error capturing data: %s", error->message); + if (error->domain == FP_DEVICE_RETRY || + g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + libfprint_demo_set_mode (win, RETRY_MODE); + else + libfprint_demo_set_mode (win, ERROR_MODE); + return; + } - win->img = img; - update_image (win); + g_clear_object (&win->img); + win->img = image; + update_image (win); - libfprint_demo_set_mode (win, CAPTURE_MODE); + libfprint_demo_set_mode (win, CAPTURE_MODE); } static void -dev_open_cb (struct fp_dev *dev, int status, void *user_data) +dev_start_capture (LibfprintDemoWindow *win) { - LibfprintDemoWindow *win = user_data; - int r; + libfprint_demo_set_capture_label (win); - if (status < 0) { - libfprint_demo_set_mode (win, ERROR_MODE); - return; - } + fp_device_capture (win->dev, TRUE, win->cancellable, (GAsyncReadyCallback) dev_capture_start_cb, win); +} - libfprint_demo_set_capture_label (win); +static void +dev_open_cb (FpDevice *dev, GAsyncResult *res, void *user_data) +{ + LibfprintDemoWindow *win = user_data; - win->dev = dev; - r = fp_async_capture_start (win->dev, FALSE, dev_capture_start_cb, user_data); - if (r < 0) { - g_warning ("fp_async_capture_start failed: %d", r); - libfprint_demo_set_mode (win, ERROR_MODE); - return; - } + g_autoptr(GError) error = NULL; + + if (!fp_device_open_finish (dev, res, &error)) + { + g_warning ("Failed to open device: %s", error->message); + libfprint_demo_set_mode (win, ERROR_MODE); + return; + } + + dev_start_capture (win); } static void activate_capture (GSimpleAction *action, - GVariant *parameter, - gpointer user_data) + GVariant *parameter, + gpointer user_data) { - LibfprintDemoWindow *win = user_data; - int r; + LibfprintDemoWindow *win = user_data; - libfprint_demo_set_mode (win, SPINNER_MODE); - g_clear_pointer (&win->img, fp_img_free); + libfprint_demo_set_mode (win, SPINNER_MODE); + g_clear_pointer (&win->img, g_object_unref); - if (win->dev != NULL) { - dev_open_cb (win->dev, 0, user_data); - return; - } + g_clear_object (&win->cancellable); + win->cancellable = g_cancellable_new (); - libfprint_demo_set_spinner_label (win, "Opening fingerprint reader"); + if (win->opened) + { + dev_start_capture (win); + return; + } - r = fp_async_dev_open (win->ddev, dev_open_cb, user_data); - if (r < 0) { - g_warning ("fp_async_dev_open failed: %d", r); - libfprint_demo_set_mode (win, ERROR_MODE); - return; - } + libfprint_demo_set_spinner_label (win, "Opening fingerprint reader"); + + win->opened = TRUE; + fp_device_open (win->dev, win->cancellable, (GAsyncReadyCallback) dev_open_cb, user_data); +} + +static void +cancel_capture (GSimpleAction *action, + GVariant *parameter, + gpointer user_data) +{ + LibfprintDemoWindow *win = user_data; + + g_debug ("cancelling %p", win->cancellable); + + if (win->cancellable) + g_cancellable_cancel (win->cancellable); } static void activate_quit (GSimpleAction *action, - GVariant *parameter, - gpointer user_data) + GVariant *parameter, + gpointer user_data) { - GtkApplication *app = user_data; - GtkWidget *win; - GList *list, *next; + GtkApplication *app = user_data; + GtkWidget *win; + GList *list, *next; - list = gtk_application_get_windows (app); - while (list) - { - win = list->data; - next = list->next; + list = gtk_application_get_windows (app); + while (list) + { + win = list->data; + next = list->next; - gtk_widget_destroy (GTK_WIDGET (win)); + gtk_widget_destroy (GTK_WIDGET (win)); - list = next; - } + list = next; + } } static void activate_show_minutiae (GSimpleAction *action, - GVariant *parameter, - gpointer user_data) + GVariant *parameter, + gpointer user_data) { - LibfprintDemoWindow *win = user_data; - GVariant *state; - gboolean new_state; + LibfprintDemoWindow *win = user_data; + GVariant *state; + gboolean new_state; - state = g_action_get_state (G_ACTION (action)); - new_state = !g_variant_get_boolean (state); - g_action_change_state (G_ACTION (action), g_variant_new_boolean (new_state)); - g_variant_unref (state); + state = g_action_get_state (G_ACTION (action)); + new_state = !g_variant_get_boolean (state); + g_action_change_state (G_ACTION (action), g_variant_new_boolean (new_state)); + g_variant_unref (state); - if (new_state) - win->img_flags |= IMAGE_DISPLAY_MINUTIAE; - else - win->img_flags &= ~IMAGE_DISPLAY_MINUTIAE; + if (new_state) + win->img_flags |= IMAGE_DISPLAY_MINUTIAE; + else + win->img_flags &= ~IMAGE_DISPLAY_MINUTIAE; - update_image (win); + update_image (win); } static void activate_show_binary (GSimpleAction *action, - GVariant *parameter, - gpointer user_data) + GVariant *parameter, + gpointer user_data) { - LibfprintDemoWindow *win = user_data; - GVariant *state; - gboolean new_state; + LibfprintDemoWindow *win = user_data; + GVariant *state; + gboolean new_state; - state = g_action_get_state (G_ACTION (action)); - new_state = !g_variant_get_boolean (state); - g_action_change_state (G_ACTION (action), g_variant_new_boolean (new_state)); - g_variant_unref (state); + state = g_action_get_state (G_ACTION (action)); + new_state = !g_variant_get_boolean (state); + g_action_change_state (G_ACTION (action), g_variant_new_boolean (new_state)); + g_variant_unref (state); - if (new_state) - win->img_flags |= IMAGE_DISPLAY_BINARY; - else - win->img_flags &= ~IMAGE_DISPLAY_BINARY; + if (new_state) + win->img_flags |= IMAGE_DISPLAY_BINARY; + else + win->img_flags &= ~IMAGE_DISPLAY_BINARY; - update_image (win); + update_image (win); } static void change_show_minutiae_state (GSimpleAction *action, - GVariant *state, - gpointer user_data) + GVariant *state, + gpointer user_data) { - g_simple_action_set_state (action, state); + g_simple_action_set_state (action, state); } static void change_show_binary_state (GSimpleAction *action, - GVariant *state, - gpointer user_data) + GVariant *state, + gpointer user_data) { - g_simple_action_set_state (action, state); + g_simple_action_set_state (action, state); } static GActionEntry app_entries[] = { - { "quit", activate_quit, NULL, NULL, NULL }, + { "quit", activate_quit, NULL, NULL, NULL }, }; static GActionEntry win_entries[] = { - { "show-minutiae", activate_show_minutiae, NULL, "false", change_show_minutiae_state }, - { "show-binary", activate_show_binary, NULL, "false", change_show_binary_state }, - { "capture", activate_capture, NULL, NULL, NULL } + { "show-minutiae", activate_show_minutiae, NULL, "false", change_show_minutiae_state }, + { "show-binary", activate_show_binary, NULL, "false", change_show_binary_state }, + { "capture", activate_capture, NULL, NULL, NULL }, + { "cancel", cancel_capture, NULL, NULL, NULL } }; static void activate (GApplication *app) { - LibfprintDemoWindow *window; + LibfprintDemoWindow *window; - window = g_object_new (libfprint_demo_window_get_type (), - "application", app, - NULL); - gtk_widget_show (GTK_WIDGET (window)); + window = g_object_new (libfprint_demo_window_get_type (), + "application", app, + NULL); + gtk_widget_show (GTK_WIDGET (window)); } static void libfprint_demo_set_mode (LibfprintDemoWindow *win, - LibfprintDemoMode mode) + LibfprintDemoMode mode) { - struct fp_driver *drv; - char *title; + char *title; - switch (mode) { - case EMPTY_MODE: - gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "empty-mode"); - gtk_widget_set_sensitive (win->capture_button, FALSE); - gtk_spinner_stop (GTK_SPINNER (win->spinner)); - break; - case NOIMAGING_MODE: - gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "noimaging-mode"); - gtk_widget_set_sensitive (win->capture_button, FALSE); - gtk_spinner_stop (GTK_SPINNER (win->spinner)); - break; - case CAPTURE_MODE: - gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "capture-mode"); - gtk_widget_set_sensitive (win->capture_button, TRUE); + switch (mode) + { + case EMPTY_MODE: + gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "empty-mode"); + gtk_widget_set_sensitive (win->capture_button, FALSE); + gtk_widget_set_sensitive (win->cancel_button, FALSE); + gtk_spinner_stop (GTK_SPINNER (win->spinner)); + break; - drv = fp_dscv_dev_get_driver (win->ddev); - title = g_strdup_printf ("%s Test", fp_driver_get_full_name (drv)); - gtk_header_bar_set_title (GTK_HEADER_BAR (win->header_bar), title); - g_free (title); + case NOIMAGING_MODE: + gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "noimaging-mode"); + gtk_widget_set_sensitive (win->capture_button, FALSE); + gtk_widget_set_sensitive (win->cancel_button, FALSE); + gtk_spinner_stop (GTK_SPINNER (win->spinner)); + break; - gtk_spinner_stop (GTK_SPINNER (win->spinner)); - break; - case SPINNER_MODE: - gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "spinner-mode"); - gtk_widget_set_sensitive (win->capture_button, FALSE); - gtk_spinner_start (GTK_SPINNER (win->spinner)); - break; - case ERROR_MODE: - gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "error-mode"); - gtk_widget_set_sensitive (win->capture_button, FALSE); - gtk_spinner_stop (GTK_SPINNER (win->spinner)); - break; - default: - g_assert_not_reached (); - } + case CAPTURE_MODE: + gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "capture-mode"); + gtk_widget_set_sensitive (win->capture_button, TRUE); + gtk_widget_set_sensitive (win->cancel_button, FALSE); + + title = g_strdup_printf ("%s Test", fp_device_get_name (win->dev)); + gtk_header_bar_set_title (GTK_HEADER_BAR (win->header_bar), title); + g_free (title); + + gtk_spinner_stop (GTK_SPINNER (win->spinner)); + break; + + case SPINNER_MODE: + gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "spinner-mode"); + gtk_widget_set_sensitive (win->capture_button, FALSE); + gtk_widget_set_sensitive (win->cancel_button, TRUE); + gtk_spinner_start (GTK_SPINNER (win->spinner)); + break; + + case ERROR_MODE: + gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "error-mode"); + gtk_widget_set_sensitive (win->capture_button, FALSE); + gtk_widget_set_sensitive (win->cancel_button, FALSE); + gtk_spinner_stop (GTK_SPINNER (win->spinner)); + break; + + case RETRY_MODE: + gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "retry-mode"); + gtk_widget_set_sensitive (win->capture_button, TRUE); + gtk_widget_set_sensitive (win->cancel_button, FALSE); + gtk_spinner_stop (GTK_SPINNER (win->spinner)); + break; + + default: + g_assert_not_reached (); + } } static void libfprint_demo_init (LibfprintDemo *app) { - g_action_map_add_action_entries (G_ACTION_MAP (app), - app_entries, G_N_ELEMENTS (app_entries), - app); + g_action_map_add_action_entries (G_ACTION_MAP (app), + app_entries, G_N_ELEMENTS (app_entries), + app); } static void libfprint_demo_class_init (LibfprintDemoClass *class) { - GApplicationClass *app_class = G_APPLICATION_CLASS (class); + GApplicationClass *app_class = G_APPLICATION_CLASS (class); - app_class->activate = activate; + app_class->activate = activate; } static void libfprint_demo_window_init (LibfprintDemoWindow *window) { - struct fp_dscv_dev **discovered_devs; + FpContext *ctx; + GPtrArray *devices; - gtk_widget_init_template (GTK_WIDGET (window)); - gtk_window_set_default_size (GTK_WINDOW (window), 700, 500); + gtk_widget_init_template (GTK_WIDGET (window)); + gtk_window_set_default_size (GTK_WINDOW (window), 700, 500); - g_action_map_add_action_entries (G_ACTION_MAP (window), - win_entries, G_N_ELEMENTS (win_entries), - window); + g_action_map_add_action_entries (G_ACTION_MAP (window), + win_entries, G_N_ELEMENTS (win_entries), + window); - if (fp_init () < 0) { - libfprint_demo_set_mode (window, ERROR_MODE); - return; - } + ctx = fp_context_new (); - setup_pollfds (); + devices = fp_context_get_devices (ctx); + if (!devices) + { + libfprint_demo_set_mode (window, ERROR_MODE); + return; + } - discovered_devs = fp_discover_devs(); - if (!discovered_devs) { - libfprint_demo_set_mode (window, ERROR_MODE); - return; - } + /* Empty list? */ + if (devices->len == 0) + { + libfprint_demo_set_mode (window, EMPTY_MODE); + return; + } - /* Empty list? */ - if (discovered_devs[0] == NULL) { - fp_dscv_devs_free (discovered_devs); - libfprint_demo_set_mode (window, EMPTY_MODE); - return; - } + if (!fp_device_supports_capture (g_ptr_array_index (devices, 0))) + { + libfprint_demo_set_mode (window, NOIMAGING_MODE); + return; + } - if (!fp_driver_supports_imaging(fp_dscv_dev_get_driver(discovered_devs[0]))) { - libfprint_demo_set_mode (window, NOIMAGING_MODE); - return; - } - - window->ddev = discovered_devs[0]; - libfprint_demo_set_mode (window, CAPTURE_MODE); + window->dev = g_object_ref (g_ptr_array_index (devices, 0)); + libfprint_demo_set_mode (window, CAPTURE_MODE); } static void libfprint_demo_window_class_init (LibfprintDemoWindowClass *class) { - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); - gtk_widget_class_set_template_from_resource (widget_class, "/libfprint_demo/gtk-libfprint-test.ui"); - gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, header_bar); - gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, mode_stack); - gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, capture_button); - gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, capture_image); - gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, spinner); - gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, instructions); + gtk_widget_class_set_template_from_resource (widget_class, "/libfprint_demo/gtk-libfprint-test.ui"); + gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, header_bar); + gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, mode_stack); + gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, capture_button); + gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, cancel_button); + gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, capture_image); + gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, spinner); + gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, instructions); - //FIXME setup dispose + //FIXME setup dispose } -int main (int argc, char **argv) +int +main (int argc, char **argv) { - GtkApplication *app; + GtkApplication *app; - app = GTK_APPLICATION (g_object_new (libfprint_demo_get_type (), - "application-id", "org.freedesktop.libfprint.Demo", - "flags", G_APPLICATION_FLAGS_NONE, - NULL)); + app = GTK_APPLICATION (g_object_new (libfprint_demo_get_type (), + "application-id", "org.freedesktop.libfprint.Demo", + "flags", G_APPLICATION_FLAGS_NONE, + NULL)); - return g_application_run (G_APPLICATION (app), 0, NULL); + return g_application_run (G_APPLICATION (app), 0, NULL); } diff --git a/demo/gtk-libfprint-test.ui b/demo/gtk-libfprint-test.ui index 0691620d..d83b826d 100644 --- a/demo/gtk-libfprint-test.ui +++ b/demo/gtk-libfprint-test.ui @@ -1,5 +1,5 @@ - + diff --git a/demo/loop.c b/demo/loop.c deleted file mode 100644 index 81dd62ef..00000000 --- a/demo/loop.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * fprint D-Bus daemon - * Copyright (C) 2008 Daniel Drake - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" - -#include -#include - -#include -#include - -#include "loop.h" - -struct fdsource { - GSource source; - GSList *pollfds; -}; - -static gboolean source_prepare(GSource *source, gint *timeout) -{ - int r; - struct timeval tv; - - r = fp_get_next_timeout(&tv); - if (r == 0) { - *timeout = -1; - return FALSE; - } - - if (!timerisset(&tv)) - return TRUE; - - *timeout = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); - return FALSE; -} - -static gboolean source_check(GSource *source) -{ - struct fdsource *_fdsource = (struct fdsource *) source; - GSList *l; - struct timeval tv; - int r; - - if (!_fdsource->pollfds) - return FALSE; - - for (l = _fdsource->pollfds; l != NULL; l = l->next) { - GPollFD *pollfd = l->data; - - if (pollfd->revents) - return TRUE; - } - - r = fp_get_next_timeout(&tv); - if (r == 1 && !timerisset(&tv)) - return TRUE; - - return FALSE; -} - -static gboolean source_dispatch(GSource *source, GSourceFunc callback, - gpointer data) -{ - struct timeval zerotimeout = { - .tv_sec = 0, - .tv_usec = 0, - }; - - /* FIXME error handling */ - fp_handle_events_timeout(&zerotimeout); - - /* FIXME whats the return value used for? */ - return TRUE; -} - -static void source_finalize(GSource *source) -{ - struct fdsource *_fdsource = (struct fdsource *) source; - GSList *l; - - if (!_fdsource->pollfds) - return; - - for (l = _fdsource->pollfds; l != NULL; l = l->next) { - GPollFD *pollfd = l->data; - - g_source_remove_poll((GSource *) _fdsource, pollfd); - g_slice_free(GPollFD, pollfd); - _fdsource->pollfds = g_slist_delete_link(_fdsource->pollfds, l); - } - - g_slist_free(_fdsource->pollfds); -} - -static GSourceFuncs sourcefuncs = { - .prepare = source_prepare, - .check = source_check, - .dispatch = source_dispatch, - .finalize = source_finalize, -}; - -static struct fdsource *fdsource = NULL; - -static void pollfd_add(int fd, short events) -{ - GPollFD *pollfd; - - pollfd = g_slice_new(GPollFD); - pollfd->fd = fd; - pollfd->events = 0; - pollfd->revents = 0; - if (events & POLLIN) - pollfd->events |= G_IO_IN; - if (events & POLLOUT) - pollfd->events |= G_IO_OUT; - - fdsource->pollfds = g_slist_prepend(fdsource->pollfds, pollfd); - g_source_add_poll((GSource *) fdsource, pollfd); -} - -static void pollfd_added_cb(int fd, short events) -{ - g_debug("now monitoring fd %d", fd); - pollfd_add(fd, events); -} - -static void pollfd_removed_cb(int fd) -{ - GSList *l; - - g_debug("no longer monitoring fd %d", fd); - - if (!fdsource->pollfds) { - g_debug("cannot remove from list as list is empty?"); - return; - } - - for (l = fdsource->pollfds; l != NULL; l = l->next) { - GPollFD *pollfd = l->data; - - if (pollfd->fd != fd) - continue; - - g_source_remove_poll((GSource *) fdsource, pollfd); - g_slice_free(GPollFD, pollfd); - fdsource->pollfds = g_slist_delete_link(fdsource->pollfds, l); - return; - } - - g_error("couldn't find fd %d in list\n", fd); -} - -int setup_pollfds(void) -{ - ssize_t numfds; - size_t i; - struct fp_pollfd *fpfds; - GSource *gsource; - - gsource = g_source_new(&sourcefuncs, sizeof(struct fdsource)); - fdsource = (struct fdsource *) gsource; - fdsource->pollfds = NULL; - - numfds = fp_get_pollfds(&fpfds); - if (numfds < 0) { - if (fpfds) - free(fpfds); - return (int) numfds; - } else if (numfds > 0) { - for (i = 0; i < numfds; i++) { - struct fp_pollfd *fpfd = &fpfds[i]; - pollfd_add(fpfd->fd, fpfd->events); - } - } - - free(fpfds); - fp_set_pollfd_notifiers(pollfd_added_cb, pollfd_removed_cb); - g_source_attach(gsource, NULL); - return 0; -} diff --git a/demo/loop.h b/demo/loop.h deleted file mode 100644 index 0266bfbd..00000000 --- a/demo/loop.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2008 Daniel Drake - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef POLL_H - -#define POLL_H - -int setup_pollfds(void); - -#endif - diff --git a/demo/meson.build b/demo/meson.build index 1f0b537d..ceca56d4 100644 --- a/demo/meson.build +++ b/demo/meson.build @@ -7,7 +7,7 @@ bindir = join_paths(prefix, get_option('bindir')) datadir = join_paths(prefix, get_option('datadir')) executable('gtk-libfprint-test', - [ 'gtk-libfprint-test.c', 'loop.c', 'loop.h', gtk_test_resources ], + [ 'gtk-libfprint-test.c', gtk_test_resources ], dependencies: [ libfprint_dep, gtk_dep ], include_directories: [ root_inc, diff --git a/demo/org.freedesktop.libfprint.Demo.json b/demo/org.freedesktop.libfprint.Demo.json index cbb4046f..7429670e 100644 --- a/demo/org.freedesktop.libfprint.Demo.json +++ b/demo/org.freedesktop.libfprint.Demo.json @@ -1,7 +1,7 @@ { "app-id": "org.freedesktop.libfprint.Demo", "runtime": "org.gnome.Platform", - "runtime-version": "master", + "runtime-version": "3.32", "sdk": "org.gnome.Sdk", "command": "gtk-libfprint-test", "finish-args": [ @@ -32,18 +32,30 @@ } ], "post-install": [ - "install -Dm644 COPYING /app/share/licenses/libusb/COPYING" + "install -Dm644 COPYING /app/share/licenses/libgusb/COPYING" + ] + }, + { + "name": "libgusb", + "buildsystem": "meson", + "config-opts": [ "-Dtests=false", "-Dvapi=false", "-Ddocs=false", "-Dintrospection=false" ], + "sources": [ + { + "type": "archive", + "url": "https://github.com/hughsie/libgusb/archive/0.3.0.tar.gz", + "sha256": "b36310f8405d5fd68f6caf4a829f7ab4c627b38fd3d02a139d411fce0f3a49f1" + } ] }, { "name": "libfprint", "buildsystem": "meson", - "config-opts": [ "-Dudev_rules=false", "-Dx11-examples=false", "-Dgtk-examples=true" ], + "config-opts": [ "-Dudev_rules=false", "-Dx11-examples=false", "-Dgtk-examples=true", "-Ddrivers=all" ], "sources": [ { "type": "git", "url": "https://gitlab.freedesktop.org/libfprint/libfprint.git", - "branch": "wip/hadess/gtk-example" + "branch": "wip/benzea/v2" } ] } diff --git a/doc/advanced-topics.xml b/doc/advanced-topics.xml index 5af6f717..18a12897 100644 --- a/doc/advanced-topics.xml +++ b/doc/advanced-topics.xml @@ -60,21 +60,18 @@ In summary, libfprint represents fingerprints in several internal structures and each representation will offer you a way of determining the - driver ID and devtype of the print in + driver and device ID of the print in question. Prints are only compatible if the driver ID and devtypes match. libfprint does offer you some "is this print compatible?" helper functions, so you don't have to worry about these details too much. - - Driver IDs + + Driver - Each driver is assigned a unique ID by the project maintainer. These - assignments are - - documented in the sources and will never change. + Each driver is assigned a unique string identifier by the project maintainer. @@ -89,22 +86,23 @@ - - Device types + + Device ID - Internally, the driver behind a device assigns a 32-bit - devtype identifier to the device. This cannot be used as a unique - ID for a specific device as many devices under the same range may share - the same devtype. The devtype may even be 0 in all cases. + Internally, the behind a device assigns a string identifier to the device + This cannot be used as a unique ID for a specific device as many devices + under the same range may share the same devtype. The device ID may even + be the same string in all cases. It is guaranteed to have a non-zero length + and be a valid file name. It defaults to "0". - The only reason you may be interested in retrieving the devtype for a + The only reason you may be interested in retrieving the device ID for a device is for the purpose of checking if some print data is compatible - with a device. libfprint uses the devtype as one way of checking that the + with a device. libfprint uses the device ID as one way of checking that the print you are verifying is compatible with the device in question - the - devtypes must be equal. This effectively allows drivers to support more + device ID must be equal. This effectively allows drivers to support more than one type of device where the data from each one is not compatible with the other. Note that libfprint does provide you with helper functions to determine whether a print is compatible with a device, so under most diff --git a/doc/getting-started.xml b/doc/getting-started.xml index 8ed8592b..369e5639 100644 --- a/doc/getting-started.xml +++ b/doc/getting-started.xml @@ -13,12 +13,12 @@ Usually the first thing you want to do is determine which fingerprint - devices are present. This is done through device discovery. + devices are present. This is done using the FpContext object. Once you have found a device you would like to operate, you should open it. - Refer to device operations. This section also details enrollment, + Refer to device operations. This section also details enrollment, image capture, and verification. diff --git a/doc/libfprint-docs.xml b/doc/libfprint-docs.xml index 3ef995b7..b866aab0 100644 --- a/doc/libfprint-docs.xml +++ b/doc/libfprint-docs.xml @@ -25,41 +25,43 @@ Library API Documentation - - - - - - - - - + + + + + Writing Drivers - - Logging, and async machinery - - - + + Device methods for drivers + + - - Device and driver structures - - - - + + USB and State Machine helpers + + + Image manipulation - + - + + Print handling + + + + + Listing drivers + + diff --git a/doc/libfprint-sections.txt b/doc/libfprint-sections.txt index 556ea723..0abe584d 100644 --- a/doc/libfprint-sections.txt +++ b/doc/libfprint-sections.txt @@ -1,146 +1,191 @@ -
-fprint.h -events -Initialisation and events handling -LIBFPRINT_DEPRECATED -fp_set_debug -fp_init -fp_exit -fp_pollfd -fp_handle_events_timeout -fp_handle_events -fp_get_next_timeout -fp_get_pollfds -fp_pollfd_added_cb -fp_pollfd_removed_cb -fp_set_pollfd_notifiers +drivers_api +
-fprint.h -discovery -Device discovery -fp_dscv_dev -fp_discover_devs -fp_dscv_devs_free -fp_dscv_dev_get_driver -fp_dscv_dev_get_devtype -fp_dscv_dev_get_driver_id -fp_dscv_dev_supports_print_data -fp_dscv_dev_supports_dscv_print -fp_dscv_dev_for_print_data -fp_dscv_dev_for_dscv_print +fp-context +FpContext +FP_TYPE_CONTEXT +FpContextClass +fp_context_new +fp_context_enumerate +fp_context_get_devices +FpContext
-fprint.h -drv -fp_driver -fp_driver_get_name -fp_driver_get_full_name -fp_driver_get_driver_id -fp_driver_get_scan_type -fp_driver_supports_imaging +fp-device +FP_TYPE_DEVICE +FP_DEVICE_RETRY +FP_DEVICE_ERROR +FpDeviceType +FpScanType +FpDeviceRetry +FpDeviceError +fp_device_retry_quark +fp_device_error_quark +FpEnrollProgress +fp_device_get_driver +fp_device_get_device_id +fp_device_get_name +fp_device_get_scan_type +fp_device_get_nr_enroll_stages +fp_device_has_storage +fp_device_supports_identify +fp_device_supports_capture +fp_device_open +fp_device_close +fp_device_enroll +fp_device_verify +fp_device_identify +fp_device_capture +fp_device_delete_print +fp_device_list_prints +fp_device_open_finish +fp_device_close_finish +fp_device_enroll_finish +fp_device_verify_finish +fp_device_identify_finish +fp_device_capture_finish +fp_device_delete_print_finish +fp_device_list_prints_finish +fp_device_open_sync +fp_device_close_sync +fp_device_enroll_sync +fp_device_verify_sync +fp_device_identify_sync +fp_device_capture_sync +fp_device_delete_print_sync +fp_device_list_prints_sync +FpDevice
-fprint.h -dev -fp_dev -fp_scan_type -fp_capture_result -fp_enroll_result -fp_verify_result - -fp_dev_get_driver -fp_dev_get_nr_enroll_stages -fp_dev_get_devtype -fp_dev_supports_print_data -fp_dev_supports_imaging -fp_dev_supports_identification -fp_dev_supports_dscv_print -fp_dev_get_img_width -fp_dev_get_img_height - -fp_operation_stop_cb -fp_img_operation_cb -fp_dev_open_cb -fp_enroll_stage_cb -fp_identify_cb - -fp_dev_open -fp_async_dev_open - -fp_dev_close -fp_async_dev_close - -fp_enroll_finger -fp_enroll_finger_img -fp_async_enroll_start -fp_async_enroll_stop - -fp_verify_finger -fp_verify_finger_img -fp_async_verify_start -fp_async_verify_stop - -fp_identify_finger -fp_identify_finger_img -fp_async_identify_start -fp_async_identify_stop - -fp_dev_img_capture -fp_async_capture_start -fp_async_capture_stop -
- -
-fprint.h -print_data -fp_finger -fp_print_data -fp_print_data_get_data -fp_print_data_from_data -fp_print_data_save -fp_print_data_load -fp_print_data_delete -fp_print_data_from_dscv_print -fp_print_data_free -fp_print_data_get_driver_id -fp_print_data_get_devtype -
- -
-fprint.h -dscv_print -fp_dscv_print -fp_discover_prints -fp_dscv_prints_free -fp_dscv_print_get_driver_id -fp_dscv_print_get_devtype -fp_dscv_print_get_finger -fp_dscv_print_delete -
- -
-fprint.h -img -fp_img -fp_minutia -fp_img_free -fp_img_get_height -fp_img_get_width -fp_img_get_data -fp_img_save_to_file -fp_img_standardize -fp_img_binarize -fp_img_get_minutiae +fp-image +FP_TYPE_IMAGE +FpMinutia +fp_image_new +fp_image_get_width +fp_image_get_height +fp_image_get_ppmm +fp_image_get_minutiae +fp_image_detect_minutiae +fp_image_detect_minutiae_finish +fp_image_get_data +fp_image_get_binarized fp_minutia_get_coords +FpImage +
+ +
+fp-image-device +FP_TYPE_IMAGE_DEVICE +FpImageDevice +
+ +
+fp-print +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 +fp_print_get_image +fp_print_get_finger +fp_print_get_username +fp_print_get_description +fp_print_get_enroll_date +fp_print_set_finger +fp_print_set_username +fp_print_set_description +fp_print_set_enroll_date +fp_print_compatible +fp_print_equal +fp_print_serialize +fp_print_deserialize +
+ +
+fpi-assembling +fpi_frame +fpi_frame_asmbl_ctx +fpi_do_movement_estimation +fpi_assemble_frames +fpi_line_asmbl_ctx +fpi_assemble_lines +
+ +
+fpi-context +fpi_get_driver_types +
+ +
+fpi-device +FpDeviceClass +FpTimeoutFunc +FpDeviceAction +FpIdEntry +fpi_device_get_usb_device +fpi_device_get_virtual_env +fpi_device_get_current_action +fpi_device_retry_new +fpi_device_error_new +fpi_device_retry_new_msg +fpi_device_error_new_msg +fpi_device_get_driver_data +fpi_device_get_enroll_data +fpi_device_get_capture_data +fpi_device_get_verify_data +fpi_device_get_identify_data +fpi_device_get_delete_data +fpi_device_get_cancellable +fpi_device_action_is_cancelled +fpi_device_add_timeout +fpi_device_set_nr_enroll_stages +fpi_device_set_scan_type +fpi_device_action_error +fpi_device_probe_complete +fpi_device_open_complete +fpi_device_close_complete +fpi_device_enroll_complete +fpi_device_verify_complete +fpi_device_identify_complete +fpi_device_capture_complete +fpi_device_delete_complete +fpi_device_enroll_progress +
+ +
+fpi-image +FpiImageFlags +FpImage +fpi_std_sq_dev +fpi_mean_sq_diff_norm +fpi_image_resize +
+ +
+fpi-image-device +FpImageDevice +FpImageDeviceState +FpImageDeviceClass +fpi_image_device_session_error +fpi_image_device_open_complete +fpi_image_device_close_complete +fpi_image_device_activate_complete +fpi_image_device_deactivate_complete +fpi_image_device_report_finger_status +fpi_image_device_image_captured +fpi_image_device_retry_scan
-fpi-log.h fpi-log fp_dbg fp_info @@ -151,121 +196,58 @@ BUG
-fpi-ssm.h -fpi-ssm -fpi_ssm -ssm_completed_fn -ssm_handler_fn +fpi-print +FpPrintType +FpiMatchResult +fpi_print_add_print +fpi_print_set_type +fpi_print_set_device_stored +fpi_print_add_from_image +fpi_print_bz3_match +
+
+fpi-ssm +FpiSsmCompletedCallback +FpiSsmHandlerCallback fpi_ssm_new fpi_ssm_free fpi_ssm_start fpi_ssm_start_subsm - fpi_ssm_next_state -fpi_ssm_next_state_timeout_cb fpi_ssm_jump_to_state fpi_ssm_mark_completed fpi_ssm_mark_failed -fpi_ssm_get_user_data +fpi_ssm_set_data +fpi_ssm_get_data 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
-fpi-poll.h -fpi-poll -fpi_timeout -fpi_timeout_fn -fpi_timeout_add -fpi_timeout_set_name -fpi_timeout_cancel +fpi-usb-transfer +FPI_USB_ENDPOINT_IN +FPI_USB_ENDPOINT_OUT +FpiUsbTransferCallback +FpiTransferType +FpiUsbTransfer +fpi_usb_transfer_new +fpi_usb_transfer_ref +fpi_usb_transfer_unref +fpi_usb_transfer_set_short_error +fpi_usb_transfer_fill_bulk +fpi_usb_transfer_fill_bulk_full +fpi_usb_transfer_fill_control +fpi_usb_transfer_fill_interrupt +fpi_usb_transfer_fill_interrupt_full +fpi_usb_transfer_submit +fpi_usb_transfer_submit_sync + +FPI_TYPE_USB_TRANSFER +fpi_usb_transfer_get_type
-
-fpi-dev.h -fpi-dev -fp_img_dev - -FP_DEV -FP_IMG_DEV -fp_dev_set_instance_data -FP_INSTANCE_DATA - -fpi_dev_get_usb_dev -fpi_dev_get_verify_data -fpi_dev_set_nr_enroll_stages -
- -
-fpi-dev-img.h -fpi-dev-img -fp_imgdev_action -fp_imgdev_state -fp_imgdev_enroll_state - -fpi_imgdev_abort_scan -fpi_imgdev_activate_complete -fpi_imgdev_close_complete -fpi_imgdev_deactivate_complete -fpi_imgdev_get_action -fpi_imgdev_get_action_result -fpi_imgdev_get_action_state -fpi_imgdev_image_captured -fpi_imgdev_open_complete -fpi_imgdev_report_finger_status -fpi_imgdev_session_error -fpi_imgdev_set_action_result -
- -
-fpi-core.h -fpi-core -usb_id -fp_driver_type -
- -
-fpi-core.h -fpi-core-img -FpiImgDriverFlags -fp_img_driver -
- -
-fpi-img.h -fpi-img -FpiImgFlags - -fpi_img_new -fpi_img_new_for_imgdev -fpi_img_realloc -fpi_img_resize - -fpi_std_sq_dev -fpi_mean_sq_diff_norm -
- -
-fpi-assembling.h -fpi-assembling -fpi_frame -fpi_frame_asmbl_ctx -fpi_line_asmbl_ctx - -fpi_do_movement_estimation -fpi_assemble_frames -fpi_assemble_lines -
- -
-fpi-usb.h -fpi-usb -fpi_usb_transfer - -fpi_usb_transfer_cb_fn -fpi_usb_alloc -fpi_usb_fill_bulk_transfer -fpi_usb_submit_transfer -fpi_usb_cancel_transfer -
diff --git a/doc/libfprint-sections.txt-new-manual b/doc/libfprint-sections.txt-new-manual new file mode 100644 index 00000000..857425b9 --- /dev/null +++ b/doc/libfprint-sections.txt-new-manual @@ -0,0 +1,118 @@ + +
+fprint.h +context +Device discovery and hotplugging +FP_TYPE_CONTEXT +FpContext +fp_context_new +fp_context_enumerate +fp_context_get_devices +
+ + +
+fprint.h +device +Device +FP_TYPE_DEVICE +FpDevice +FpDeviceType +FpScanType +FpDeviceRetry +FpDeviceError +FP_DEVICE_ERROR +FP_DEVICE_RETRY +fp_device_get_driver +fp_device_get_device_id +fp_device_get_name +fp_device_get_scan_type + +fp_device_open +fp_device_open_finish +fp_device_open_sync + +fp_device_close +fp_device_close_finish +fp_device_close_sync + +fp_device_enroll +fp_device_enroll_finish +fp_device_enroll_sync + +fp_device_identify +fp_device_identify_finish +fp_device_identify_sync + +fp_device_capture +fp_device_capture_finish +fp_device_capture_sync + +fp_device_verify +fp_device_verify_finish +fp_device_verify_sync + +_fp_device_get_cancellable +
+ + +
+fprint.h +print +Fingerprint handling +FpPrint +fp_print_new +
+ + +
+fprint.h +image +Image handling +FP_TYPE_IMAGE +FpImage +fp_image_new +fp_image_detect_minutiae +fp_image_detect_minutiae_finish +fp_image_device_new +fp_image_get_binarized +fp_image_get_data +fp_image_get_height +fp_image_get_minutiae +fp_image_get_ppmm +fp_image_get_width +
+ + +
+internal-image-device +drivers_api.h +Base class for image devices +FpImageDevice +FpImageDeviceClass +FpImageDeviceState +
+ +
+internal-usb-transfers +drivers_api.h +USB Transfers +FpUsbTransfer +fp_usb_transfer_fill_bulk +fp_usb_transfer_fill_bulk_full +fp_usb_transfer_fill_control +fp_usb_transfer_fill_interrupt +fp_usb_transfer_fill_interrupt_full +fp_usb_transfer_get_type +fp_usb_transfer_new +fp_usb_transfer_ref +fp_usb_transfer_set_short_error +fp_usb_transfer_submit +fp_usb_transfer_submit_sync +fp_usb_transfer_unref +FpUsbTransferCallback +FP_USB_ENDPOINT_IN +FP_USB_ENDPOINT_OUT +
+ + diff --git a/doc/meson.build b/doc/meson.build index 37d515d8..54186677 100644 --- a/doc/meson.build +++ b/doc/meson.build @@ -2,41 +2,13 @@ subdir('xml') private_headers = [ 'config.h', - - 'aeslib.h', - 'assembling.h', - 'fp_internal.h', 'nbis-helpers.h', - 'fpi-async.h', - 'fpi-data.h', + 'fprint.h', + 'fp_internal.h', - # Drivers - 'aes1660.h', - 'aes2501.h', - 'aes2550.h', - 'aes2660.h', - 'aes3k.h', - 'aesx660.h', - 'driver_ids.h', - 'elan.h', - 'upek_proto.h', - 'upeksonly.h', - 'upektc.h', - 'upektc_img.h', - 'vfs0050.h', - 'vfs301_proto_fragments.h', - 'vfs301_proto.h', - 'vfs5011_proto.h', - - # NBIS - 'morph.h', - 'sunrast.h', - 'bozorth.h', - 'defs.h', - 'log.h', - 'bz_array.h', - 'lfs.h', - 'mytime.h', + # Subdirectories to ignore + 'drivers', + 'nbis', ] html_images = [ @@ -59,6 +31,7 @@ gnome.gtkdoc('libfprint', content_files: content_files, expand_content_files: expand_content_files, scan_args: [ + #'--rebuild-sections', '--ignore-decorators=API_EXPORTED', '--ignore-headers=' + ' '.join(private_headers), ], diff --git a/examples/cpp-test.cpp b/examples/cpp-test.cpp index 12936132..a0eb2ed7 100644 --- a/examples/cpp-test.cpp +++ b/examples/cpp-test.cpp @@ -6,6 +6,10 @@ int main (int argc, char **argv) { - fp_init (); + FpContext *ctx; + + ctx = fp_context_new (); + g_object_unref (ctx); + return 0; } diff --git a/examples/enroll.c b/examples/enroll.c index 9814f68e..159ffbc0 100644 --- a/examples/enroll.c +++ b/examples/enroll.c @@ -1,7 +1,8 @@ /* * Example fingerprint enrollment program - * Enrolls your right index finger and saves the print to disk + * Enrolls your choosen finger and saves the print to disk * Copyright (C) 2007 Daniel Drake + * Copyright (C) 2019 Marco Trevisan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,141 +20,177 @@ */ #include -#include -#include - #include #include "storage.h" +#include "utilities.h" -struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs) +typedef struct _EnrollData { - struct fp_dscv_dev *ddev = discovered_devs[0]; - struct fp_driver *drv; - if (!ddev) - return NULL; - - drv = fp_dscv_dev_get_driver(ddev); - printf("Found device claimed by %s driver\n", fp_driver_get_full_name(drv)); - return ddev; -} + GMainLoop *loop; + FpFinger finger; + int ret_value; +} EnrollData; -struct fp_print_data *enroll(struct fp_dev *dev) { - struct fp_print_data *enrolled_print = NULL; - int r; - - printf("You will need to successfully scan your finger %d times to " - "complete the process.\n", fp_dev_get_nr_enroll_stages(dev)); - - do { - struct fp_img *img = NULL; - - printf("\nScan your finger now.\n"); - - r = fp_enroll_finger_img(dev, &enrolled_print, &img); - if (img) { - fp_img_save_to_file(img, "enrolled.pgm"); - printf("Wrote scanned image to enrolled.pgm\n"); - fp_img_free(img); - } - if (r < 0) { - printf("Enroll failed with error %d\n", r); - return NULL; - } - - switch (r) { - case FP_ENROLL_COMPLETE: - printf("Enroll complete!\n"); - break; - case FP_ENROLL_FAIL: - printf("Enroll failed, something wen't wrong :(\n"); - return NULL; - case FP_ENROLL_PASS: - printf("Enroll stage passed. Yay!\n"); - break; - case FP_ENROLL_RETRY: - printf("Didn't quite catch that. Please try again.\n"); - break; - case FP_ENROLL_RETRY_TOO_SHORT: - printf("Your swipe was too short, please try again.\n"); - break; - case FP_ENROLL_RETRY_CENTER_FINGER: - printf("Didn't catch that, please center your finger on the " - "sensor and try again.\n"); - break; - case FP_ENROLL_RETRY_REMOVE_FINGER: - printf("Scan failed, please remove your finger and then try " - "again.\n"); - break; - } - } while (r != FP_ENROLL_COMPLETE); - - if (!enrolled_print) { - fprintf(stderr, "Enroll complete but no print?\n"); - return NULL; - } - - printf("Enrollment completed!\n\n"); - return enrolled_print; -} - -int main(void) +static void +enroll_data_free (EnrollData *enroll_data) { - int r = 1; - struct fp_dscv_dev *ddev; - struct fp_dscv_dev **discovered_devs; - struct fp_dev *dev; - struct fp_print_data *data; + g_main_loop_unref (enroll_data->loop); + g_free (enroll_data); +} +G_DEFINE_AUTOPTR_CLEANUP_FUNC (EnrollData, enroll_data_free) - printf("This program will enroll your right index finger, " - "unconditionally overwriting any right-index print that was enrolled " - "previously. If you want to continue, press enter, otherwise hit " - "Ctrl+C\n"); - getchar(); +static void +on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data) +{ + EnrollData *enroll_data = user_data; - setenv ("G_MESSAGES_DEBUG", "all", 0); - setenv ("LIBUSB_DEBUG", "3", 0); + g_autoptr(GError) error = NULL; - r = fp_init(); - if (r < 0) { - fprintf(stderr, "Failed to initialize libfprint\n"); - exit(1); - } + fp_device_close_finish (dev, res, &error); - discovered_devs = fp_discover_devs(); - if (!discovered_devs) { - fprintf(stderr, "Could not discover devices\n"); - goto out; - } + if (error) + g_warning ("Failed closing device %s\n", error->message); - ddev = discover_device(discovered_devs); - if (!ddev) { - fprintf(stderr, "No devices detected.\n"); - goto out; - } - - dev = fp_dev_open(ddev); - fp_dscv_devs_free(discovered_devs); - if (!dev) { - fprintf(stderr, "Could not open device.\n"); - goto out; - } - - printf("Opened device. It's now time to enroll your finger.\n\n"); - data = enroll(dev); - if (!data) - goto out_close; - - r = print_data_save(data, RIGHT_INDEX); - if (r < 0) - fprintf(stderr, "Data save failed, code %d\n", r); - - fp_print_data_free(data); -out_close: - fp_dev_close(dev); -out: - fp_exit(); - return r; + g_main_loop_quit (enroll_data->loop); } +static void +on_enroll_completed (FpDevice *dev, GAsyncResult *res, void *user_data) +{ + EnrollData *enroll_data = user_data; + g_autoptr(FpPrint) print = NULL; + g_autoptr(GError) error = NULL; + + print = fp_device_enroll_finish (dev, res, &error); + + if (!error) + { + enroll_data->ret_value = EXIT_SUCCESS; + + if (!fp_device_has_storage (dev)) + { + 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 + { + g_warning ("Enroll failed with error %s\n", error->message); + } + + fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed, + enroll_data); +} + +static void +on_enroll_progress (FpDevice *device, + gint completed_stages, + FpPrint *print, + gpointer user_data, + GError *error) +{ + if (error) + { + g_warning ("Enroll stage %d of %d failed with error %s", + completed_stages, + fp_device_get_nr_enroll_stages (device), + error->message); + return; + } + + if (fp_device_supports_capture (device) && + print_image_save (print, "enrolled.pgm")) + printf ("Wrote scanned image to enrolled.pgm\n"); + + printf ("Enroll stage %d of %d passed. Yay!\n", completed_stages, + fp_device_get_nr_enroll_stages (device)); +} + +static void +on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data) +{ + EnrollData *enroll_data = user_data; + FpPrint *print_template; + + g_autoptr(GError) error = NULL; + + if (!fp_device_open_finish (dev, res, &error)) + { + g_warning ("Failed to open device: %s", error->message); + g_main_loop_quit (enroll_data->loop); + return; + } + + printf ("Opened device. It's now time to enroll your finger.\n\n"); + printf ("You will need to successfully scan your %s finger %d times to " + "complete the process.\n\n", finger_to_string (enroll_data->finger), + fp_device_get_nr_enroll_stages (dev)); + printf ("Scan your finger now.\n"); + + print_template = print_create_template (dev, enroll_data->finger); + fp_device_enroll (dev, print_template, NULL, on_enroll_progress, NULL, + NULL, (GAsyncReadyCallback) on_enroll_completed, + enroll_data); +} + +int +main (void) +{ + g_autoptr(FpContext) ctx = NULL; + g_autoptr(EnrollData) enroll_data = NULL; + GPtrArray *devices; + FpDevice *dev; + FpFinger finger; + + g_print ("This program will enroll the selected finger, unconditionally " + "overwriting any print for the same finger that was enrolled " + "previously. If you want to continue, press enter, otherwise hit " + "Ctrl+C\n"); + getchar (); + + g_print ("Choose the finger to enroll:\n"); + finger = finger_chooser (); + + if (finger == FP_FINGER_UNKNOWN) + { + g_warning ("Unknown finger selected"); + return EXIT_FAILURE; + } + + setenv ("G_MESSAGES_DEBUG", "all", 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; + } + + enroll_data = g_new0 (EnrollData, 1); + enroll_data->finger = finger; + enroll_data->ret_value = EXIT_FAILURE; + enroll_data->loop = g_main_loop_new (NULL, FALSE); + + fp_device_open (dev, NULL, (GAsyncReadyCallback) on_device_opened, + enroll_data); + + g_main_loop_run (enroll_data->loop); + + return enroll_data->ret_value; +} diff --git a/examples/img_capture.c b/examples/img_capture.c deleted file mode 100644 index c65c73d0..00000000 --- a/examples/img_capture.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Example libfprint image capture program - * Copyright (C) 2007 Daniel Drake - * - * 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 -#include - -#include - -struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs) -{ - struct fp_dscv_dev *ddev = discovered_devs[0]; - struct fp_driver *drv; - if (!ddev) - return NULL; - - drv = fp_dscv_dev_get_driver(ddev); - printf("Found device claimed by %s driver\n", fp_driver_get_full_name(drv)); - return ddev; -} - -int main(void) -{ - int r = 1; - struct fp_dscv_dev *ddev; - struct fp_dscv_dev **discovered_devs; - struct fp_dev *dev; - struct fp_img *img = NULL; - - setenv ("G_MESSAGES_DEBUG", "all", 0); - setenv ("LIBUSB_DEBUG", "3", 0); - - r = fp_init(); - if (r < 0) { - fprintf(stderr, "Failed to initialize libfprint\n"); - exit(1); - } - - discovered_devs = fp_discover_devs(); - if (!discovered_devs) { - fprintf(stderr, "Could not discover devices\n"); - goto out; - } - - ddev = discover_device(discovered_devs); - if (!ddev) { - fp_dscv_devs_free(discovered_devs); - fprintf(stderr, "No devices detected.\n"); - goto out; - } - - dev = fp_dev_open(ddev); - fp_dscv_devs_free(discovered_devs); - if (!dev) { - fprintf(stderr, "Could not open device.\n"); - goto out; - } - - if (!fp_dev_supports_imaging(dev)) { - fprintf(stderr, "this device does not have imaging capabilities.\n"); - goto out_close; - } - - printf("Opened device. It's now time to scan your finger.\n\n"); - - r = fp_dev_img_capture(dev, 0, &img); - if (r) { - fprintf(stderr, "image capture failed, code %d\n", r); - goto out_close; - } - - r = fp_img_save_to_file(img, "finger.pgm"); - if (r) { - fprintf(stderr, "img save failed, code %d\n", r); - goto out_close; - } - - fp_img_standardize(img); - r = fp_img_save_to_file(img, "finger_standardized.pgm"); - fp_img_free(img); - if (r) { - fprintf(stderr, "standardized img save failed, code %d\n", r); - goto out_close; - } - - r = 0; -out_close: - fp_dev_close(dev); -out: - fp_exit(); - return r; -} - diff --git a/examples/img_capture_continuous.c b/examples/img_capture_continuous.c deleted file mode 100644 index f5b5f028..00000000 --- a/examples/img_capture_continuous.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Example libfprint continuous image capture program - * Copyright (C) 2007 Daniel Drake - * - * 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 -#include -#include - -#include -#include -#include -#include - -#define FORMAT 0x32595559 - -static int adaptor = -1; -static char *framebuffer = NULL; - -static Display *display = NULL; -static Window window=(Window)NULL; -static XvImage *xv_image = NULL; -static XvAdaptorInfo *info; -static GC gc; -static int connection = -1; - -/* based on macro by Bart Nabbe */ -#define GREY2YUV(grey, y, u, v)\ - y = (9798*grey + 19235*grey + 3736*grey) / 32768;\ - u = (-4784*grey - 9437*grey + 14221*grey) / 32768 + 128;\ - v = (20218*grey - 16941*grey - 3277*grey) / 32768 + 128;\ - y = y < 0 ? 0 : y;\ - u = u < 0 ? 0 : u;\ - v = v < 0 ? 0 : v;\ - y = y > 255 ? 255 : y;\ - u = u > 255 ? 255 : u;\ - v = v > 255 ? 255 : v - -static void grey2yuy2 (unsigned char *grey, char *YUV, int num) { - int i, j; - int y0, y1, u0, u1, v0, v1; - uint64_t gval; - - for (i = 0, j = 0; i < num; i += 2, j += 4) - { - gval = grey[i]; - GREY2YUV (gval, y0, u0 , v0); - gval = grey[i + 1]; - GREY2YUV (gval, y1, u1 , v1); - YUV[j + 0] = y0; - YUV[j + 1] = (u0+u1)/2; - YUV[j + 2] = y1; - YUV[j + 3] = (v0+v1)/2; - } -} - -static void display_frame(struct fp_img *img) -{ - int width = fp_img_get_width(img); - int height = fp_img_get_height(img); - unsigned char *data = fp_img_get_data(img); - - if (adaptor < 0) - return; - - grey2yuy2(data, framebuffer, width * height); - xv_image = XvCreateImage(display, info[adaptor].base_id, FORMAT, - framebuffer, width, height); - XvPutImage(display, info[adaptor].base_id, window, gc, xv_image, - 0, 0, width, height, 0, 0, width, height); -} - -static void QueryXv(void) -{ - unsigned int num_adaptors; - int num_formats; - XvImageFormatValues *formats = NULL; - int i,j; - char xv_name[5]; - - XvQueryAdaptors(display, DefaultRootWindow(display), &num_adaptors, - &info); - - for(i = 0; i < num_adaptors; i++) { - formats = XvListImageFormats(display, info[i].base_id, - &num_formats); - for(j = 0; j < num_formats; j++) { - xv_name[4] = 0; - memcpy(xv_name, &formats[j].id, 4); - if(formats[j].id == FORMAT) { - printf("using Xv format 0x%x %s %s\n", - formats[j].id, xv_name, - (formats[j].format==XvPacked) - ? "packed" : "planar"); - if (adaptor < 0) - adaptor = i; - } - } - } - XFree(formats); - if (adaptor < 0) - printf("No suitable Xv adaptor found\n"); -} - -struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs) -{ - struct fp_dscv_dev *ddev = discovered_devs[0]; - struct fp_driver *drv; - if (!ddev) - return NULL; - - drv = fp_dscv_dev_get_driver(ddev); - printf("Found device claimed by %s driver\n", fp_driver_get_full_name(drv)); - return ddev; -} - -int main(void) -{ - int r = 1; - XEvent xev; - XGCValues xgcv; - long background=0x010203; - struct fp_dscv_dev *ddev; - struct fp_dscv_dev **discovered_devs; - struct fp_dev *dev; - int img_width; - int img_height; - int standardize = 0; - - setenv ("G_MESSAGES_DEBUG", "all", 0); - setenv ("LIBUSB_DEBUG", "3", 0); - - r = fp_init(); - if (r < 0) { - fprintf(stderr, "Failed to initialize libfprint\n"); - exit(1); - } - - discovered_devs = fp_discover_devs(); - if (!discovered_devs) { - fprintf(stderr, "Could not discover devices\n"); - goto out; - } - - ddev = discover_device(discovered_devs); - if (!ddev) { - fprintf(stderr, "No devices detected.\n"); - goto out; - } - - dev = fp_dev_open(ddev); - fp_dscv_devs_free(discovered_devs); - if (!dev) { - fprintf(stderr, "Could not open device.\n"); - goto out; - } - - if (!fp_dev_supports_imaging(dev)) { - fprintf(stderr, "this device does not have imaging capabilities.\n"); - goto out_close; - } - - img_width = fp_dev_get_img_width(dev); - img_height = fp_dev_get_img_height(dev); - if (img_width <= 0 || img_height <= 0) { - fprintf(stderr, "this device returns images with variable dimensions," - " this example does not support that.\n"); - goto out_close; - } - framebuffer = malloc(img_width * img_height * 2); - if (!framebuffer) - goto out_close; - - /* make the window */ - display = XOpenDisplay(getenv("DISPLAY")); - if(display == NULL) { - fprintf(stderr,"Could not open display \"%s\"\n", - getenv("DISPLAY")); - goto out_close; - } - - QueryXv(); - - if (adaptor < 0) - goto out_close; - - window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0, - img_width, img_height, 0, - WhitePixel(display, DefaultScreen(display)), background); - - XSelectInput(display, window, StructureNotifyMask | KeyPressMask); - XMapWindow(display, window); - connection = ConnectionNumber(display); - - gc = XCreateGC(display, window, 0, &xgcv); - - printf("Press S to toggle standardized mode, Q to quit\n"); - - while (1) { /* event loop */ - struct fp_img *img; - - r = fp_dev_img_capture(dev, 1, &img); - if (r) { - fprintf(stderr, "image capture failed, code %d\n", r); - goto out_close; - } - if (standardize) - fp_img_standardize(img); - - display_frame(img); - fp_img_free(img); - XFlush(display); - - while (XPending(display) > 0) { - XNextEvent(display, &xev); - if (xev.type != KeyPress) - continue; - - switch (XKeycodeToKeysym(display, xev.xkey.keycode, 0)) { - case XK_q: - case XK_Q: - r = 0; - goto out_close; - break; - case XK_s: - case XK_S: - standardize = !standardize; - break; - } - } /* XPending */ - } - - r = 0; -out_close: - if (framebuffer) - free(framebuffer); - fp_dev_close(dev); - if ((void *) window != NULL) - XUnmapWindow(display, window); - if (display != NULL) - XFlush(display); -out: - fp_exit(); - return r; -} - - diff --git a/examples/manage-prints.c b/examples/manage-prints.c new file mode 100644 index 00000000..b865af75 --- /dev/null +++ b/examples/manage-prints.c @@ -0,0 +1,279 @@ +/* + * Example fingerprint device prints listing and deletion + * Enrolls your right index finger and saves the print to disk + * Copyright (C) 2019 Marco Trevisan + * + * 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 + +#include +#include "utilities.h" + +typedef struct _ListData +{ + GMainLoop *loop; + int ret_value; + GList *to_delete; + gboolean any_failed; +} ListData; + +static void +list_data_free (ListData *list_data) +{ + g_list_free_full (list_data->to_delete, g_object_unref); + g_main_loop_unref (list_data->loop); + g_free (list_data); +} +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ListData, list_data_free) + +static void +on_device_closed (FpDevice *dev, + GAsyncResult *res, + gpointer user_data) +{ + ListData *list_data = user_data; + + g_autoptr(GError) error = NULL; + + fp_device_close_finish (dev, res, &error); + + if (error) + g_warning ("Failed closing device %s\n", error->message); + + g_main_loop_quit (list_data->loop); +} + +typedef struct _DeleteData +{ + ListData *list_data; + FpPrint *print; +} DeleteData; + +static void +delete_data_free (DeleteData *delete_data) +{ + g_object_unref (delete_data->print); + g_free (delete_data); +} +G_DEFINE_AUTOPTR_CLEANUP_FUNC (DeleteData, delete_data_free); + +static void on_print_deleted (FpDevice *dev, + GAsyncResult *res, + gpointer user_data); + +static void +delete_next_print (FpDevice *dev, + ListData *list_data) +{ + FpPrint *print; + + g_assert_nonnull (list_data->to_delete); + print = list_data->to_delete->data; + + g_debug ("Deleting print %s\n", fp_print_get_description (print)); + fp_device_delete_print (dev, print, NULL, + (GAsyncReadyCallback) on_print_deleted, list_data); +} + +static void +on_print_deleted (FpDevice *dev, + GAsyncResult *res, + gpointer user_data) +{ + ListData *list_data = user_data; + + g_autoptr(GError) error = NULL; + g_autoptr(FpPrint) print = NULL; + GList *deleted_link; + + fp_device_delete_print_finish (dev, res, &error); + + deleted_link = list_data->to_delete; + print = g_steal_pointer (&deleted_link->data); + list_data->to_delete = g_list_delete_link (list_data->to_delete, deleted_link); + + if (error) + { + g_warning ("Failed to remove print %s: %s", + fp_print_get_description (print), error->message); + list_data->any_failed = TRUE; + } + else + { + g_debug ("Deleted print %s from device", fp_print_get_description (print)); + } + + if (list_data->to_delete != NULL) + { + delete_next_print (dev, list_data); + } + else + { + if (!list_data->any_failed) + list_data->ret_value = EXIT_SUCCESS; + + fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed, + list_data); + } +} + +static void +on_list_completed (FpDevice *dev, + GAsyncResult *res, + gpointer user_data) +{ + ListData *list_data = user_data; + + g_autoptr(GPtrArray) prints = NULL; + g_autoptr(GError) error = NULL; + + prints = fp_device_list_prints_finish (dev, res, &error); + + if (!error) + { + guint i; + char buf[128]; + + g_print ("Device contains %u prints\n", prints->len); + + for (i = 0; i < prints->len; ++i) + { + FpPrint * print = prints->pdata[i]; + + g_date_strftime (buf, G_N_ELEMENTS (buf), "%Y-%m-%d", + fp_print_get_enroll_date (print)); + g_print ("[%d] Print of %s finger for username %s, enrolled " + "on %s. Description: %s\n", i + 1, + finger_to_string (fp_print_get_finger (print)), + fp_print_get_username (print), buf, + fp_print_get_description (print)); + } + + if (prints->len) + { + gint64 idx = 0; + + g_print ("Want to delete saved print? [/A/n]\n> "); + if (fgets (buf, 3, stdin)) + idx = g_ascii_strtoll (buf, NULL, 10); + + if (idx > 0 && idx <= prints->len) + { + FpPrint *print = prints->pdata[idx - 1]; + list_data->to_delete = g_list_prepend (list_data->to_delete, + g_object_ref (print)); + } + else if (buf[0] == 'A') + { + for (i = 0; i < prints->len; ++i) + { + FpPrint *print = prints->pdata[i]; + list_data->to_delete = g_list_prepend (list_data->to_delete, + g_object_ref (print)); + } + } + else + { + if (buf[0] == 'n' || buf[0] == 'N') + list_data->ret_value = EXIT_SUCCESS; + else + g_warning ("Invalid finger selected"); + + fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed, + list_data); + } + } + + if (list_data->to_delete) + delete_next_print (dev, list_data); + else + fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed, + list_data); + } + else + { + g_warning ("Getting prints failed with error %s", error->message); + g_main_loop_quit (list_data->loop); + } +} + +static void +on_device_opened (FpDevice *dev, + GAsyncResult *res, + gpointer user_data) +{ + ListData *list_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); + g_main_loop_quit (list_data->loop); + return; + } + + if (!fp_device_has_storage (dev)) + { + g_warning ("Device %s doesn't support storage", fp_device_get_name (dev)); + g_main_loop_quit (list_data->loop); + return; + } + + fp_device_list_prints (dev, NULL, + (GAsyncReadyCallback) on_list_completed, list_data); + +} + +int +main (void) +{ + g_autoptr(FpContext) ctx = NULL; + g_autoptr(ListData) list_data = NULL; + GPtrArray *devices; + FpDevice *dev; + + g_print ("This program will report the prints saved in device\n"); + + setenv ("G_MESSAGES_DEBUG", "all", 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; + } + + list_data = g_new0 (ListData, 1); + list_data->ret_value = EXIT_FAILURE; + list_data->loop = g_main_loop_new (NULL, FALSE); + + fp_device_open (dev, NULL, (GAsyncReadyCallback) on_device_opened, list_data); + + g_main_loop_run (list_data->loop); + + return list_data->ret_value; +} diff --git a/examples/meson.build b/examples/meson.build index 7596be64..5cd3d835 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -1,8 +1,8 @@ -examples = [ 'verify_live', 'enroll', 'verify', 'img_capture' ] +examples = [ 'enroll', 'verify', 'manage-prints' ] foreach example: examples executable(example, - [example + '.c', 'storage.c'], + [example + '.c', 'storage.c', 'utilities.c'], dependencies: [libfprint_dep, glib_dep], include_directories: [ root_inc, @@ -17,13 +17,3 @@ executable('cpp-test', root_inc, ], c_args: common_cflags) - -if get_option('x11-examples') - executable('img_capture_continuous', - 'img_capture_continuous.c', - dependencies: [ libfprint_dep, xv_dep, x11_dep ], - include_directories: [ - root_inc, - ], - c_args: common_cflags) -endif diff --git a/examples/prints/README b/examples/prints/README new file mode 100644 index 00000000..977d7066 --- /dev/null +++ b/examples/prints/README @@ -0,0 +1,3 @@ +These are example images from NIST and are in the public domain. + +The PNG files have been generated by using the greyscale data as a mask. diff --git a/examples/prints/arch.jpg b/examples/prints/arch.jpg new file mode 100644 index 00000000..b87e285c Binary files /dev/null and b/examples/prints/arch.jpg differ diff --git a/examples/prints/arch.png b/examples/prints/arch.png new file mode 100644 index 00000000..f8c9b4de Binary files /dev/null and b/examples/prints/arch.png differ diff --git a/examples/prints/loop-right.jpg b/examples/prints/loop-right.jpg new file mode 100644 index 00000000..126b90e0 Binary files /dev/null and b/examples/prints/loop-right.jpg differ diff --git a/examples/prints/loop-right.png b/examples/prints/loop-right.png new file mode 100644 index 00000000..93177ddd Binary files /dev/null and b/examples/prints/loop-right.png differ diff --git a/examples/prints/tented_arch.jpg b/examples/prints/tented_arch.jpg new file mode 100644 index 00000000..e73f7ccf Binary files /dev/null and b/examples/prints/tented_arch.jpg differ diff --git a/examples/prints/tented_arch.png b/examples/prints/tented_arch.png new file mode 100644 index 00000000..c524a1fc Binary files /dev/null and b/examples/prints/tented_arch.png differ diff --git a/examples/prints/whorl.jpg b/examples/prints/whorl.jpg new file mode 100644 index 00000000..96c79ba3 Binary files /dev/null and b/examples/prints/whorl.jpg differ diff --git a/examples/prints/whorl.png b/examples/prints/whorl.png new file mode 100644 index 00000000..9e7e7c4b Binary files /dev/null and b/examples/prints/whorl.png differ diff --git a/examples/sendvirtimg.py b/examples/sendvirtimg.py new file mode 100755 index 00000000..eb5263be --- /dev/null +++ b/examples/sendvirtimg.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 + +# This script can be used together with the virtual_imgdev to simulate an +# image based fingerprint reader. +# +# To use, set the FP_VIRTUAL_IMAGE environment variable for both the +# libfprint using program (e.g. fprintd) and this script. +# +# Usually this would work by adding it into the systemd unit file. The +# best way of doing so is to create +# /etc/systemd/system/fprintd.service.d/fprintd-test.conf +# +# [Service] +# RuntimeDirectory=fprint +# Environment=FP_VIRTUAL_IMAGE=/run/fprint/virtimg_sock +# Environment=G_MESSAGES_DEBUG=all +# ReadWritePaths=$RUNTIME_DIR +# +# After that run: +# +# systemctl daemon-reload +# systemctl restart fprintd.service +# +# You may also need to disable selinux. +# +# Then run this script with e.g. +# FP_VIRTUAL_IMAGE=/run/fprint/virtimg_sock ./sendvirtimg.py prints/whorl.png + + + +import cairo +import sys +import os +import socket +import struct + +if len(sys.argv) != 2: + sys.stderr.write('You need to pass a PNG with an alpha channel!\n') + sys.exit(1) + +# Just copied from the C file, we could also use the introspection data for +# this. Also, most of them do *not* make any sense. +commands = { + 'retry' : struct.pack('ii', -1, 0), + 'retry-too-short' : struct.pack('ii', -1, 1), + 'retry-center-finger' : struct.pack('ii', -1, 2), + 'retry-remove-finger' : struct.pack('ii', -1, 3), + + 'error' : struct.pack('ii', -2, 0), + 'error-not-supported' : struct.pack('ii', -2, 1), + 'error-not-open' : struct.pack('ii', -2, 2), + 'error-already-open' : struct.pack('ii', -2, 3), + 'error-busy' : struct.pack('ii', -2, 4), + 'error-proto' : struct.pack('ii', -2, 5), + 'error-data-invalid' : struct.pack('ii', -2, 6), + 'error-data-not-found' : struct.pack('ii', -2, 7), + 'error-data-full' : struct.pack('ii', -2, 8), +} + + +if sys.argv[1] in commands: + command = commands[sys.argv[1]] +else: + png = cairo.ImageSurface.create_from_png(sys.argv[1]) + + # Cairo wants 4 byte aligned rows, so just add a few pixel if necessary + w = png.get_width() + h = png.get_height() + w = (w + 3) // 4 * 4 + h = (h + 3) // 4 * 4 + img = cairo.ImageSurface(cairo.Format.A8, w, h) + cr = cairo.Context(img) + + cr.set_source_rgba(1, 1, 1, 1) + cr.paint() + + cr.set_source_rgba(0, 0, 0, 0) + cr.set_operator(cairo.OPERATOR_SOURCE) + + cr.set_source_surface(png) + cr.paint() + + mem = img.get_data() + mem = mem.tobytes() + assert len(mem) == img.get_width() * img.get_height() + + command = struct.pack('ii', img.get_width(), img.get_height()) + command += mem + + + +def write_dbg_img(): + dbg_img_rgb = cairo.ImageSurface(cairo.Format.RGB24, img.get_width(), img.get_height()) + dbg_cr = cairo.Context(dbg_img_rgb) + dbg_cr.set_source_rgb(0, 0, 0) + dbg_cr.paint() + dbg_cr.set_source_rgb(1, 1, 1) + dbg_cr.mask_surface(img, 0, 0) + + dbg_img_rgb.write_to_png('/tmp/test.png') + +#write_dbg_img() + +# Send image through socket +sockaddr = os.environ['FP_VIRTUAL_IMAGE'] + +sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) +sock.connect(sockaddr) + +sock.sendall(command) + diff --git a/examples/storage.c b/examples/storage.c index aa399e0f..932163e0 100644 --- a/examples/storage.c +++ b/examples/storage.c @@ -2,6 +2,7 @@ * Trivial storage driver for example programs * * Copyright (C) 2019 Benjamin Berg + * Copyright (C) 2019 Marco Trevisan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,119 +19,208 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include +#include + +#include #include #include #include -#include - #define STORAGE_FILE "test-storage.variant" static char * -get_print_data_descriptor (struct fp_print_data *data, struct fp_dev *dev, enum fp_finger finger) +get_print_data_descriptor (FpPrint *print, FpDevice *dev, FpFinger finger) { - gint drv_id; - gint devtype; + const char *driver; + const char *dev_id; - if (data) { - drv_id = fp_print_data_get_driver_id (data); - devtype = fp_print_data_get_devtype (data); - } else { - drv_id = fp_driver_get_driver_id(fp_dev_get_driver (dev)); - devtype = fp_dev_get_devtype (dev); - } + if (print) + { + driver = fp_print_get_driver (print); + dev_id = fp_print_get_device_id (print); + } + else + { + driver = fp_device_get_driver (dev); + dev_id = fp_device_get_device_id (dev); + } - return g_strdup_printf("%x/%08x/%x", - drv_id, - devtype, - finger); + return g_strdup_printf ("%s/%s/%x", + driver, + dev_id, + finger); } -static GVariantDict* -load_data(void) +static GVariantDict * +load_data (void) { - GVariantDict *res; - GVariant *var; - gchar *contents = NULL; - gssize length = 0; + GVariantDict *res; + GVariant *var; + g_autofree gchar *contents = NULL; + gssize length = 0; - if (!g_file_get_contents (STORAGE_FILE, &contents, &length, NULL)) { - g_warning ("Error loading storage, assuming it is empty"); - return g_variant_dict_new(NULL); - } + if (!g_file_get_contents (STORAGE_FILE, &contents, &length, NULL)) + { + g_warning ("Error loading storage, assuming it is empty"); + return g_variant_dict_new (NULL); + } - var = g_variant_new_from_data (G_VARIANT_TYPE_VARDICT, contents, length, FALSE, NULL, NULL); + var = g_variant_new_from_data (G_VARIANT_TYPE_VARDICT, contents, length, FALSE, NULL, NULL); - res = g_variant_dict_new(var); - g_variant_unref(var); - return res; + res = g_variant_dict_new (var); + g_variant_unref (var); + return res; } static int -save_data(GVariant *data) +save_data (GVariant *data) { - const gchar *contents = NULL; - gsize length; + const gchar *contents = NULL; + gsize length; - length = g_variant_get_size(data); - contents = (gchar*) g_variant_get_data (data); + length = g_variant_get_size (data); + contents = (gchar *) g_variant_get_data (data); - if (!g_file_set_contents (STORAGE_FILE, contents, length, NULL)) { - g_warning ("Error saving storage,!"); - return -1; - } + if (!g_file_set_contents (STORAGE_FILE, contents, length, NULL)) + { + g_warning ("Error saving storage,!"); + return -1; + } - g_variant_ref_sink(data); - g_variant_unref(data); + g_variant_ref_sink (data); + g_variant_unref (data); - return 0; + return 0; } int -print_data_save(struct fp_print_data *fp_data, enum fp_finger finger) +print_data_save (FpPrint *print, FpFinger finger) { - gchar *descr = get_print_data_descriptor (fp_data, NULL, finger); - GVariantDict *dict; - GVariant *val; - guchar *data; - gsize size; - int res; + g_autofree gchar *descr = get_print_data_descriptor (print, NULL, finger); - dict = load_data(); + g_autoptr(GError) error = NULL; + g_autoptr(GVariantDict) dict = NULL; + g_autofree guchar *data = NULL; + GVariant *val; + gsize size; + int res; - size = fp_print_data_get_data(fp_data, &data); - val = g_variant_new_fixed_array (G_VARIANT_TYPE("y"), data, size, 1); - g_variant_dict_insert_value (dict, descr, val); + dict = load_data (); - res = save_data(g_variant_dict_end(dict)); - g_variant_dict_unref(dict); + fp_print_serialize (print, &data, &size, &error); + if (error) + { + g_warning ("Error serializing data: %s", error->message); + return -1; + } + val = g_variant_new_fixed_array (G_VARIANT_TYPE ("y"), data, size, 1); + g_variant_dict_insert_value (dict, descr, val); - return res; + res = save_data (g_variant_dict_end (dict)); + + return res; } -struct fp_print_data* -print_data_load(struct fp_dev *dev, enum fp_finger finger) +FpPrint * +print_data_load (FpDevice *dev, FpFinger finger) { - gchar *descr = get_print_data_descriptor (NULL, dev, finger); - GVariantDict *dict; - guchar *stored_data; - gsize stored_len; - GVariant *val; - struct fp_print_data *res = NULL; + g_autofree gchar *descr = get_print_data_descriptor (NULL, dev, finger); - dict = load_data(); - val = g_variant_dict_lookup_value (dict, descr, G_VARIANT_TYPE ("ay")); + g_autoptr(GVariant) val = NULL; + g_autoptr(GVariantDict) dict = NULL; + g_autofree guchar *stored_data = NULL; + gsize stored_len; - if (val) { - stored_data = (guchar*) g_variant_get_fixed_array (val, &stored_len, 1); - res = fp_print_data_from_data(stored_data, stored_len); + dict = load_data (); + val = g_variant_dict_lookup_value (dict, descr, G_VARIANT_TYPE ("ay")); - g_variant_unref(val); - } + if (val) + { + FpPrint *print; + g_autoptr(GError) error = NULL; - g_variant_dict_unref(dict); - g_free(descr); + stored_data = (guchar *) g_variant_get_fixed_array (val, &stored_len, 1); + print = fp_print_deserialize (stored_data, stored_len, &error); - return res; + if (error) + g_warning ("Error deserializing data: %s", error->message); + + return print; + } + + return NULL; +} + +FpPrint * +print_create_template (FpDevice *dev, FpFinger finger) +{ + g_autoptr(GDateTime) datetime = NULL; + FpPrint *template = NULL; + GDate *date = NULL; + gint year, month, day; + + template = fp_print_new (dev); + fp_print_set_finger (template, finger); + fp_print_set_username (template, g_get_user_name ()); + datetime = g_date_time_new_now_local (); + g_date_time_get_ymd (datetime, &year, &month, &day); + date = g_date_new_dmy (day, month, year); + fp_print_set_enroll_date (template, date); + g_date_free (date); + + return template; +} + + +static gboolean +save_image_to_pgm (FpImage *img, const char *path) +{ + FILE *fd = fopen (path, "w"); + size_t write_size; + const guchar *data = fp_image_get_data (img, &write_size); + int r; + + if (!fd) + { + g_warning ("could not open '%s' for writing: %d", path, errno); + return FALSE; + } + + r = fprintf (fd, "P5 %d %d 255\n", + fp_image_get_width (img), fp_image_get_height (img)); + if (r < 0) + { + fclose (fd); + g_critical ("pgm header write failed, error %d", r); + return FALSE; + } + + r = fwrite (data, 1, write_size, fd); + if (r < write_size) + { + fclose (fd); + g_critical ("short write (%d)", r); + return FALSE; + } + + fclose (fd); + g_debug ("written to '%s'", path); + + return TRUE; +} + +gboolean +print_image_save (FpPrint *print, const char *path) +{ + g_autoptr(FpImage) img = NULL; + + g_return_val_if_fail (FP_IS_PRINT (print), FALSE); + g_return_val_if_fail (path != NULL, FALSE); + + img = fp_print_get_image (print); + + if (img) + return save_image_to_pgm (img, path); + + return FALSE; } diff --git a/examples/storage.h b/examples/storage.h index fc86813e..bcbd0090 100644 --- a/examples/storage.h +++ b/examples/storage.h @@ -21,7 +21,14 @@ #ifndef __STORAGE_H #define __STORAGE_H -int print_data_save(struct fp_print_data *fp_data, enum fp_finger finger); -struct fp_print_data* print_data_load(struct fp_dev *dev, enum fp_finger finger); + +int print_data_save (FpPrint *print, + FpFinger finger); +FpPrint * print_data_load (FpDevice *dev, + FpFinger finger); +FpPrint * print_create_template (FpDevice *dev, + FpFinger finger); +gboolean print_image_save (FpPrint *print, + const char *path); #endif /* __STORAGE_H */ diff --git a/examples/utilities.c b/examples/utilities.c new file mode 100644 index 00000000..379ad0ab --- /dev/null +++ b/examples/utilities.c @@ -0,0 +1,135 @@ +/* + * Utilities for example programs + * + * Copyright (C) 2019 Marco Trevisan + * + * 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 +#include + +#include "utilities.h" + +FpDevice * +discover_device (GPtrArray * devices) +{ + FpDevice *dev; + int i; + + if (!devices->len) + return NULL; + + if (devices->len == 1) + { + i = 0; + } + else + { + g_print ("Multiple devices found, choose one\n"); + + for (i = 0; i < devices->len; ++i) + { + dev = g_ptr_array_index (devices, i); + g_print ("[%d] %s (%s) - driver %s\n", i, + fp_device_get_device_id (dev), fp_device_get_name (dev), + fp_device_get_driver (dev)); + } + + g_print ("> "); + if (!scanf ("%d%*c", &i)) + return NULL; + + if (i < 0 || i >= devices->len) + return NULL; + } + + dev = g_ptr_array_index (devices, i); + g_print ("Selected device %s (%s) claimed by %s driver\n", + fp_device_get_device_id (dev), fp_device_get_name (dev), + fp_device_get_driver (dev)); + + return dev; +} + +const char * +finger_to_string (FpFinger finger) +{ + switch (finger) + { + case FP_FINGER_LEFT_THUMB: + return "left thumb"; + + case FP_FINGER_LEFT_INDEX: + return "left index"; + + case FP_FINGER_LEFT_MIDDLE: + return "left middle"; + + case FP_FINGER_LEFT_RING: + return "left ring"; + + case FP_FINGER_LEFT_LITTLE: + return "left little"; + + case FP_FINGER_RIGHT_THUMB: + return "right thumb"; + + case FP_FINGER_RIGHT_INDEX: + return "right index"; + + case FP_FINGER_RIGHT_MIDDLE: + return "right middle"; + + case FP_FINGER_RIGHT_RING: + return "right ring"; + + case FP_FINGER_RIGHT_LITTLE: + return "right little"; + + default: + return "unknown"; + } +} + +FpFinger +finger_chooser (void) +{ + int i; + const FpFinger all_fingers[] = { + FP_FINGER_LEFT_THUMB, + FP_FINGER_LEFT_INDEX, + FP_FINGER_LEFT_MIDDLE, + FP_FINGER_LEFT_RING, + FP_FINGER_LEFT_LITTLE, + FP_FINGER_RIGHT_THUMB, + FP_FINGER_RIGHT_INDEX, + FP_FINGER_RIGHT_MIDDLE, + FP_FINGER_RIGHT_RING, + FP_FINGER_RIGHT_LITTLE, + }; + + for (i = all_fingers[0]; i <= G_N_ELEMENTS (all_fingers); ++i) + g_print (" [%d] %s\n", (i - all_fingers[0]), finger_to_string (i)); + + g_print ("> "); + if (!scanf ("%d%*c", &i)) + return FP_FINGER_UNKNOWN; + + if (i < 0 || i >= G_N_ELEMENTS (all_fingers)) + return FP_FINGER_UNKNOWN; + + return all_fingers[i]; +} diff --git a/examples/utilities.h b/examples/utilities.h new file mode 100644 index 00000000..7e436acf --- /dev/null +++ b/examples/utilities.h @@ -0,0 +1,28 @@ +/* + * Trivial storage driver for example programs + * + * Copyright (C) 2019 Marco Trevisan + * + * 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 + */ + +#ifndef __UTILITIES_H +#define __UTILITIES_H + +FpDevice * discover_device (GPtrArray *devices); +FpFinger finger_chooser (void); +const char * finger_to_string (FpFinger finger); + +#endif /* __UTILITIES_H */ diff --git a/examples/verify.c b/examples/verify.c index 38b925c5..89a9b2c6 100644 --- a/examples/verify.c +++ b/examples/verify.c @@ -1,7 +1,8 @@ /* - * Example fingerprint verification program, which verifies the right index + * Example fingerprint verification program, which verifies the * finger which has been previously enrolled to disk. * Copyright (C) 2007 Daniel Drake + * Copyright (C) 2019 Marco Trevisan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,131 +20,242 @@ */ #include -#include -#include - #include #include "storage.h" +#include "utilities.h" -struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs) +typedef struct _VerifyData { - struct fp_dscv_dev *ddev = discovered_devs[0]; - struct fp_driver *drv; - if (!ddev) - return NULL; - - drv = fp_dscv_dev_get_driver(ddev); - printf("Found device claimed by %s driver\n", fp_driver_get_full_name(drv)); - return ddev; + GMainLoop *loop; + FpFinger finger; + int ret_value; +} VerifyData; + +static void +verify_data_free (VerifyData *verify_data) +{ + g_main_loop_unref (verify_data->loop); + g_free (verify_data); +} +G_DEFINE_AUTOPTR_CLEANUP_FUNC (VerifyData, verify_data_free) + +static void +on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data) +{ + VerifyData *verify_data = user_data; + + g_autoptr(GError) error = NULL; + + fp_device_close_finish (dev, res, &error); + + if (error) + g_warning ("Failed closing device %s\n", error->message); + + g_main_loop_quit (verify_data->loop); } -int verify(struct fp_dev *dev, struct fp_print_data *data) +static void start_verification (FpDevice *dev, + VerifyData *verify_data); + +static void +on_verify_completed (FpDevice *dev, GAsyncResult *res, void *user_data) { - int r; + VerifyData *verify_data = user_data; - do { - struct fp_img *img = NULL; + g_autoptr(FpPrint) print = NULL; + g_autoptr(GError) error = NULL; + char buffer[20]; + gboolean match; - sleep(1); - printf("\nScan your finger now.\n"); - r = fp_verify_finger_img(dev, data, &img); - if (img) { - fp_img_save_to_file(img, "verify.pgm"); - printf("Wrote scanned image to verify.pgm\n"); - fp_img_free(img); - } - if (r < 0) { - printf("verification failed with error %d :(\n", r); - return r; - } - switch (r) { - case FP_VERIFY_NO_MATCH: - printf("NO MATCH!\n"); - return 0; - case FP_VERIFY_MATCH: - printf("MATCH!\n"); - return 0; - case FP_VERIFY_RETRY: - printf("Scan didn't quite work. Please try again.\n"); - break; - case FP_VERIFY_RETRY_TOO_SHORT: - printf("Swipe was too short, please try again.\n"); - break; - case FP_VERIFY_RETRY_CENTER_FINGER: - printf("Please center your finger on the sensor and try again.\n"); - break; - case FP_VERIFY_RETRY_REMOVE_FINGER: - printf("Please remove finger from the sensor and try again.\n"); - break; - } - } while (1); + if (!fp_device_verify_finish (dev, res, &match, &print, &error)) + { + g_warning ("Failed to verify print: %s", error->message); + g_main_loop_quit (verify_data->loop); + return; + } + + if (match) + { + g_print ("MATCH!\n"); + if (fp_device_supports_capture (dev) && + print_image_save (print, "verify.pgm")) + g_print ("Print image saved as verify.pgm"); + + verify_data->ret_value = EXIT_SUCCESS; + } + else + { + g_print ("NO MATCH!\n"); + verify_data->ret_value = EXIT_FAILURE; + } + + g_print ("Verify again? [Y/n]? "); + if (fgets (buffer, sizeof (buffer), stdin) && + (buffer[0] == 'Y' || buffer[0] == 'y')) + { + start_verification (dev, verify_data); + return; + } + + fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed, + verify_data); } -int main(void) +static void +on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data) { - int r = 1; - struct fp_dscv_dev *ddev; - struct fp_dscv_dev **discovered_devs; - struct fp_dev *dev; - struct fp_print_data *data; + VerifyData *verify_data = user_data; - setenv ("G_MESSAGES_DEBUG", "all", 0); - setenv ("LIBUSB_DEBUG", "3", 0); + g_autoptr(GPtrArray) prints = NULL; + g_autoptr(GError) error = NULL; - r = fp_init(); - if (r < 0) { - fprintf(stderr, "Failed to initialize libfprint\n"); - exit(1); - } + prints = fp_device_list_prints_finish (dev, res, &error); - discovered_devs = fp_discover_devs(); - if (!discovered_devs) { - fprintf(stderr, "Could not discover devices\n"); - goto out; - } + if (!error) + { + FpPrint *verify_print = NULL; + guint i; - ddev = discover_device(discovered_devs); - if (!ddev) { - fprintf(stderr, "No devices detected.\n"); - goto out; - } + if (!prints->len) + g_warning ("No prints saved on device"); - dev = fp_dev_open(ddev); - fp_dscv_devs_free(discovered_devs); - if (!dev) { - fprintf(stderr, "Could not open device.\n"); - goto out; - } + for (i = 0; i < prints->len; ++i) + { + FpPrint *print = prints->pdata[i]; - printf("Opened device. Loading previously enrolled right index finger " - "data...\n"); + if (fp_print_get_finger (print) == verify_data->finger && + g_strcmp0 (fp_print_get_username (print), g_get_user_name ()) == 0) + { + if (!verify_print || + (g_date_compare (fp_print_get_enroll_date (print), + fp_print_get_enroll_date (verify_print)) >= 0)) + verify_print = print; + } + } - data = print_data_load(dev, RIGHT_INDEX); - if (!data) { - fprintf(stderr, "Failed to load fingerprint, error %d\n", r); - fprintf(stderr, "Did you remember to enroll your right index finger " - "first?\n"); - goto out_close; - } + if (!verify_print) + { + g_warning ("Did you remember to enroll your %s finger first?", + finger_to_string (verify_data->finger)); + g_main_loop_quit (verify_data->loop); + return; + } - printf("Print loaded. Time to verify!\n"); - do { - char buffer[20]; + g_debug ("Comparing print with %s", + fp_print_get_description (verify_print)); - verify(dev, data); - printf("Verify again? [Y/n]? "); - fgets(buffer, sizeof(buffer), stdin); - if (buffer[0] != '\n' && buffer[0] != 'y' && buffer[0] != 'Y') - break; - } while (1); - - fp_print_data_free(data); -out_close: - fp_dev_close(dev); -out: - fp_exit(); - return r; + g_print ("Print loaded. Time to verify!\n"); + fp_device_verify (dev, verify_print, NULL, + (GAsyncReadyCallback) on_verify_completed, + verify_data); + } + else + { + g_warning ("Loading prints failed with error %s", error->message); + g_main_loop_quit (verify_data->loop); + } } +static void +start_verification (FpDevice *dev, VerifyData *verify_data) +{ + g_print ("Choose the finger to verify:\n"); + verify_data->finger = finger_chooser (); + if (verify_data->finger == FP_FINGER_UNKNOWN) + { + g_warning ("Unknown finger selected"); + verify_data->ret_value = EXIT_FAILURE; + g_main_loop_quit (verify_data->loop); + return; + } + + 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, + verify_data); + } + else + { + g_print ("Loading previously enrolled %s finger data...\n", + finger_to_string (verify_data->finger)); + g_autoptr(FpPrint) verify_print; + + 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)); + g_main_loop_quit (verify_data->loop); + return; + } + + g_print ("Print loaded. Time to verify!\n"); + fp_device_verify (dev, verify_print, NULL, + (GAsyncReadyCallback) on_verify_completed, + verify_data); + } +} + +static void +on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data) +{ + VerifyData *verify_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); + g_main_loop_quit (verify_data->loop); + return; + } + + g_print ("Opened device. "); + + start_verification (dev, verify_data); +} + +int +main (void) +{ + g_autoptr(FpContext) ctx = NULL; + g_autoptr(VerifyData) verify_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; + } + + verify_data = g_new0 (VerifyData, 1); + verify_data->ret_value = EXIT_FAILURE; + verify_data->loop = g_main_loop_new (NULL, FALSE); + + fp_device_open (dev, NULL, (GAsyncReadyCallback) on_device_opened, + verify_data); + + g_main_loop_run (verify_data->loop); + + return verify_data->ret_value; +} diff --git a/examples/verify_live.c b/examples/verify_live.c deleted file mode 100644 index 4c02ff2f..00000000 --- a/examples/verify_live.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Example fingerprint verification program - * Copyright (C) 2007 Daniel Drake - * - * 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 -#include -#include - -#include - -struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs) -{ - struct fp_dscv_dev *ddev = discovered_devs[0]; - struct fp_driver *drv; - if (!ddev) - return NULL; - - drv = fp_dscv_dev_get_driver(ddev); - printf("Found device claimed by %s driver\n", fp_driver_get_full_name(drv)); - return ddev; -} - -struct fp_print_data *enroll(struct fp_dev *dev) { - struct fp_print_data *enrolled_print = NULL; - int r; - - printf("You will need to successfully scan your finger %d times to " - "complete the process.\n", fp_dev_get_nr_enroll_stages(dev)); - - do { - printf("\nScan your finger now.\n"); - r = fp_enroll_finger(dev, &enrolled_print); - if (r < 0) { - printf("Enroll failed with error %d\n", r); - return NULL; - } - switch (r) { - case FP_ENROLL_COMPLETE: - printf("Enroll complete!\n"); - break; - case FP_ENROLL_FAIL: - printf("Enroll failed, something wen't wrong :(\n"); - return NULL; - case FP_ENROLL_PASS: - printf("Enroll stage passed. Yay!\n"); - break; - case FP_ENROLL_RETRY: - printf("Didn't quite catch that. Please try again.\n"); - break; - case FP_ENROLL_RETRY_TOO_SHORT: - printf("Your swipe was too short, please try again.\n"); - break; - case FP_ENROLL_RETRY_CENTER_FINGER: - printf("Didn't catch that, please center your finger on the " - "sensor and try again.\n"); - break; - case FP_ENROLL_RETRY_REMOVE_FINGER: - printf("Scan failed, please remove your finger and then try " - "again.\n"); - break; - } - } while (r != FP_ENROLL_COMPLETE); - - if (!enrolled_print) { - fprintf(stderr, "Enroll complete but no print?\n"); - return NULL; - } - - printf("Enrollment completed!\n\n"); - return enrolled_print; -} - -int verify(struct fp_dev *dev, struct fp_print_data *data) -{ - int r; - - do { - sleep(1); - printf("\nScan your finger now.\n"); - r = fp_verify_finger(dev, data); - if (r < 0) { - printf("verification failed with error %d :(\n", r); - return r; - } - switch (r) { - case FP_VERIFY_NO_MATCH: - printf("NO MATCH!\n"); - return 0; - case FP_VERIFY_MATCH: - printf("MATCH!\n"); - return 0; - case FP_VERIFY_RETRY: - printf("Scan didn't quite work. Please try again.\n"); - break; - case FP_VERIFY_RETRY_TOO_SHORT: - printf("Swipe was too short, please try again.\n"); - break; - case FP_VERIFY_RETRY_CENTER_FINGER: - printf("Please center your finger on the sensor and try again.\n"); - break; - case FP_VERIFY_RETRY_REMOVE_FINGER: - printf("Please remove finger from the sensor and try again.\n"); - break; - } - } while (1); -} - -int main(void) -{ - int r = 1; - struct fp_dscv_dev *ddev; - struct fp_dscv_dev **discovered_devs; - struct fp_dev *dev; - struct fp_print_data *data; - - setenv ("G_MESSAGES_DEBUG", "all", 0); - setenv ("LIBUSB_DEBUG", "3", 0); - - r = fp_init(); - if (r < 0) { - fprintf(stderr, "Failed to initialize libfprint\n"); - exit(1); - } - - discovered_devs = fp_discover_devs(); - if (!discovered_devs) { - fprintf(stderr, "Could not discover devices\n"); - goto out; - } - - ddev = discover_device(discovered_devs); - if (!ddev) { - fprintf(stderr, "No devices detected.\n"); - goto out; - } - - dev = fp_dev_open(ddev); - fp_dscv_devs_free(discovered_devs); - if (!dev) { - fprintf(stderr, "Could not open device.\n"); - goto out; - } - - printf("Opened device. It's now time to enroll your finger.\n\n"); - data = enroll(dev); - if (!data) - goto out_close; - - - printf("Normally we'd save that print to disk, and recall it at some " - "point later when we want to authenticate the user who just " - "enrolled. In the interests of demonstration, we'll authenticate " - "that user immediately.\n"); - - do { - char buffer[20]; - - verify(dev, data); - printf("Verify again? [Y/n]? "); - fgets(buffer, sizeof(buffer), stdin); - if (buffer[0] != '\n' && buffer[0] != 'y' && buffer[0] != 'Y') - break; - } while (1); - - fp_print_data_free(data); -out_close: - fp_dev_close(dev); -out: - fp_exit(); - return r; -} - - diff --git a/libfprint/drivers/aes1610.c b/libfprint/drivers/aes1610.c index df5b5695..c9742e9c 100644 --- a/libfprint/drivers/aes1610.c +++ b/libfprint/drivers/aes1610.c @@ -28,24 +28,25 @@ #include "drivers_api.h" #include "aeslib.h" -static void start_capture(struct fp_img_dev *dev); -static void complete_deactivation(struct fp_img_dev *dev); -static int adjust_gain(unsigned char *buffer, int status); +static void start_capture (FpImageDevice *dev); +static void complete_deactivation (FpImageDevice *dev); +static int adjust_gain (unsigned char *buffer, + int status); -#define FIRST_AES1610_REG 0x1B -#define LAST_AES1610_REG 0xFF +#define FIRST_AES1610_REG 0x1B +#define LAST_AES1610_REG 0xFF #define GAIN_STATUS_FIRST 1 #define GAIN_STATUS_NORMAL 2 /* FIXME these need checking */ -#define EP_IN (1 | LIBUSB_ENDPOINT_IN) -#define EP_OUT (2 | LIBUSB_ENDPOINT_OUT) +#define EP_IN (1 | FPI_USB_ENDPOINT_IN) +#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT) #define BULK_TIMEOUT 4000 -#define FINGER_DETECTION_LEN 19 -#define STRIP_CAPTURE_LEN 665 +#define FINGER_DETECTION_LEN 19 +#define STRIP_CAPTURE_LEN 665 /* * The AES1610 is an imaging device using a swipe-type sensor. It samples @@ -59,346 +60,352 @@ static int adjust_gain(unsigned char *buffer, int status); * images returned from this driver vary in height. */ -#define FRAME_WIDTH 128 -#define FRAME_HEIGHT 8 -#define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT) -#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2)) +#define FRAME_WIDTH 128 +#define FRAME_HEIGHT 8 +#define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT) +#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2)) /* maximum number of frames to read during a scan */ /* FIXME reduce substantially */ -#define MAX_FRAMES 350 +#define MAX_FRAMES 350 /****** GENERAL FUNCTIONS ******/ -struct aes1610_dev { - uint8_t read_regs_retry_count; - GSList *strips; - size_t strips_len; - gboolean deactivating; - uint8_t blanks_count; +struct _FpiDeviceAes1610 +{ + FpImageDevice parent; + + guint8 read_regs_retry_count; + GSList *strips; + gsize strips_len; + gboolean deactivating; + guint8 blanks_count; }; +G_DECLARE_FINAL_TYPE (FpiDeviceAes1610, fpi_device_aes1610, FPI, DEVICE_AES1610, + FpImageDevice); +G_DEFINE_TYPE (FpiDeviceAes1610, fpi_device_aes1610, FP_TYPE_IMAGE_DEVICE); static struct fpi_frame_asmbl_ctx assembling_ctx = { - .frame_width = FRAME_WIDTH, - .frame_height = FRAME_HEIGHT, - .image_width = IMAGE_WIDTH, - .get_pixel = aes_get_pixel, + .frame_width = FRAME_WIDTH, + .frame_height = FRAME_HEIGHT, + .image_width = IMAGE_WIDTH, + .get_pixel = aes_get_pixel, }; -typedef void (*aes1610_read_regs_cb)(struct fp_img_dev *dev, int status, - unsigned char *regs, void *user_data); +typedef void (*aes1610_read_regs_cb)(FpImageDevice *dev, + int status, + unsigned char *regs, + void *user_data); -struct aes1610_read_regs { - struct fp_img_dev *dev; - aes1610_read_regs_cb callback; - struct aes_regwrite *regwrite; - void *user_data; +struct aes1610_read_regs +{ + FpImageDevice *dev; + aes1610_read_regs_cb callback; + struct aes_regwrite *regwrite; + void *user_data; }; /* FIXME: what to do here? */ -static void stub_capture_stop_cb(struct fp_img_dev *dev, int result, void *user_data) +static void +stub_capture_stop_cb (FpImageDevice *dev, GError *error, + void *user_data) { - + if (error) + { + fp_warn ("Error stopping capture: %s", error->message); + g_error_free (error); + } } /* check that read succeeded but ignore all data */ -static void generic_ignore_data_cb(struct libusb_transfer *transfer) +static void +generic_ignore_data_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) - fpi_ssm_mark_failed(ssm, -EIO); - else if (transfer->length != transfer->actual_length) - fpi_ssm_mark_failed(ssm, -EPROTO); - else - fpi_ssm_next_state(ssm); - - g_free(transfer->buffer); - libusb_free_transfer(transfer); + if (error) + fpi_ssm_mark_failed (transfer->ssm, error); + else + fpi_ssm_next_state (transfer->ssm); } -static void generic_write_regv_cb(struct fp_img_dev *dev, int result, - void *user_data) +static void +generic_write_regv_cb (FpImageDevice *dev, GError *error, + void *user_data) { - fpi_ssm *ssm = user_data; - if (result == 0) - fpi_ssm_next_state(ssm); - else - fpi_ssm_mark_failed(ssm, result); + FpiSsm *ssm = user_data; + + if (!error) + fpi_ssm_next_state (ssm); + else + fpi_ssm_mark_failed (ssm, error); } /* read the specified number of bytes from the IN endpoint but throw them * away, then increment the SSM */ -static void generic_read_ignore_data(fpi_ssm *ssm, struct fp_dev *dev, size_t bytes) +static void +generic_read_ignore_data (FpiSsm *ssm, FpDevice *dev, + size_t bytes) { - struct libusb_transfer *transfer = fpi_usb_alloc(); - unsigned char *data; - int r; + FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev); + unsigned char *data; - data = g_malloc(bytes); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(dev), EP_IN, data, bytes, - generic_ignore_data_cb, ssm, BULK_TIMEOUT); - - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(data); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } + data = g_malloc (bytes); + fpi_usb_transfer_fill_bulk_full (transfer, EP_IN, data, bytes, NULL); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + generic_ignore_data_cb, NULL); + fpi_usb_transfer_unref (transfer); } /****** FINGER PRESENCE DETECTION ******/ static const struct aes_regwrite finger_det_reqs[] = { - { 0x80, 0x01 }, - { 0x80, 0x12 }, - { 0x85, 0x00 }, - { 0x8A, 0x00 }, - { 0x8B, 0x0E }, - { 0x8C, 0x90 }, - { 0x8D, 0x83 }, - { 0x8E, 0x07 }, - { 0x8F, 0x07 }, - { 0x96, 0x00 }, - { 0x97, 0x48 }, - { 0xA1, 0x00 }, - { 0xA2, 0x50 }, - { 0xA6, 0xE4 }, - { 0xAD, 0x08 }, - { 0xAE, 0x5B }, - { 0xAF, 0x54 }, - { 0xB1, 0x28 }, - { 0xB5, 0xAB }, - { 0xB6, 0x0E }, - { 0x1B, 0x2D }, - { 0x81, 0x04 } + { 0x80, 0x01 }, + { 0x80, 0x12 }, + { 0x85, 0x00 }, + { 0x8A, 0x00 }, + { 0x8B, 0x0E }, + { 0x8C, 0x90 }, + { 0x8D, 0x83 }, + { 0x8E, 0x07 }, + { 0x8F, 0x07 }, + { 0x96, 0x00 }, + { 0x97, 0x48 }, + { 0xA1, 0x00 }, + { 0xA2, 0x50 }, + { 0xA6, 0xE4 }, + { 0xAD, 0x08 }, + { 0xAE, 0x5B }, + { 0xAF, 0x54 }, + { 0xB1, 0x28 }, + { 0xB5, 0xAB }, + { 0xB6, 0x0E }, + { 0x1B, 0x2D }, + { 0x81, 0x04 } }; -static void start_finger_detection(struct fp_img_dev *dev); +static void start_finger_detection (FpImageDevice *dev); -static void finger_det_data_cb(struct libusb_transfer *transfer) +static void +finger_det_data_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - struct fp_img_dev *dev = transfer->user_data; - unsigned char *data = transfer->buffer; - int i; - int sum = 0; + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + unsigned char *data = transfer->buffer; + int i; + int sum = 0; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fpi_imgdev_session_error(dev, -EIO); - goto out; - } else if (transfer->length != transfer->actual_length) { - fpi_imgdev_session_error(dev, -EPROTO); - goto out; - } + if (error) + { + fpi_image_device_session_error (dev, error); + return; + } - /* examine histogram to determine finger presence */ - for (i = 3; i < 17; i++) - sum += (data[i] & 0xf) + (data[i] >> 4); - if (sum > 20) { - /* reset default gain */ - adjust_gain(data,GAIN_STATUS_FIRST); - /* finger present, start capturing */ - fpi_imgdev_report_finger_status(dev, TRUE); - start_capture(dev); - } else { - /* no finger, poll for a new histogram */ - start_finger_detection(dev); - } - -out: - g_free(data); - libusb_free_transfer(transfer); + /* examine histogram to determine finger presence */ + for (i = 3; i < 17; i++) + sum += (data[i] & 0xf) + (data[i] >> 4); + if (sum > 20) + { + /* reset default gain */ + adjust_gain (data, GAIN_STATUS_FIRST); + /* finger present, start capturing */ + fpi_image_device_report_finger_status (dev, TRUE); + start_capture (dev); + } + else + { + /* no finger, poll for a new histogram */ + start_finger_detection (dev); + } } -static void finger_det_reqs_cb(struct fp_img_dev *dev, int result, void *user_data) +static void +finger_det_reqs_cb (FpImageDevice *dev, GError *error, + void *user_data) { - struct libusb_transfer *transfer; - unsigned char *data; - int r; + FpiUsbTransfer *transfer; - if (result) { - fpi_imgdev_session_error(dev, result); - return; - } - - transfer = fpi_usb_alloc(); - data = g_malloc(FINGER_DETECTION_LEN); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, FINGER_DETECTION_LEN, - finger_det_data_cb, dev, BULK_TIMEOUT); - - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(data); - libusb_free_transfer(transfer); - fpi_imgdev_session_error(dev, r); - } + if (error) + { + fpi_image_device_session_error (dev, error); + return; + } + transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); + fpi_usb_transfer_fill_bulk (transfer, EP_IN, FINGER_DETECTION_LEN); + transfer->short_is_error = TRUE; + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + finger_det_data_cb, NULL); + fpi_usb_transfer_unref (transfer); } -static void start_finger_detection(struct fp_img_dev *dev) +static void +start_finger_detection (FpImageDevice *dev) { - struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (dev); - if (aesdev->deactivating) { - complete_deactivation(dev); - return; - } + if (self->deactivating) + { + complete_deactivation (dev); + return; + } - aes_write_regv(dev, finger_det_reqs, G_N_ELEMENTS(finger_det_reqs), finger_det_reqs_cb, NULL); + aes_write_regv (dev, finger_det_reqs, G_N_ELEMENTS (finger_det_reqs), finger_det_reqs_cb, NULL); } /****** CAPTURE ******/ static struct aes_regwrite capture_reqs[] = { - { 0x80, 0x01 }, - { 0x80, 0x12 }, - { 0x84, 0x01 }, - { 0x85, 0x00 }, - { 0x89, 0x64 }, - { 0x8A, 0x00 }, - { 0x8B, 0x0E }, - { 0x8C, 0x90 }, - { 0xBE, 0x23 }, - { 0x29, 0x04 }, - { 0x2A, 0xFF }, - { 0x96, 0x00 }, - { 0x98, 0x03 }, - { 0x99, 0x00 }, - { 0x9C, 0xA5 }, - { 0x9D, 0x40 }, - { 0x9E, 0xC6 }, - { 0x9F, 0x8E }, - { 0xA2, 0x50 }, - { 0xA3, 0xF0 }, - { 0xAD, 0x08 }, - { 0xBD, 0x4F }, - { 0xAF, 0x54 }, - { 0xB1, 0x08 }, - { 0xB5, 0xAB }, - { 0x1B, 0x2D }, - { 0xB6, 0x4E }, - { 0xB8, 0x70 }, - { 0x2B, 0xB3 }, - { 0x2C, 0x5D }, - { 0x2D, 0x98 }, - { 0x2E, 0xB0 }, - { 0x2F, 0x20 }, - { 0xA2, 0xD0 }, - { 0x1D, 0x21 }, - { 0x1E, 0xBE }, - { 0x1C, 0x00 }, - { 0x1D, 0x30 }, - { 0x1E, 0x29 }, - { 0x1C, 0x01 }, - { 0x1D, 0x00 }, - { 0x1E, 0x9E }, - { 0x1C, 0x02 }, - { 0x1D, 0x30 }, - { 0x1E, 0xBB }, - { 0x1C, 0x03 }, - { 0x1D, 0x00 }, - { 0x1E, 0x9D }, - { 0x1C, 0x04 }, - { 0x1D, 0x22 }, - { 0x1E, 0xFF }, - { 0x1C, 0x05 }, - { 0x1D, 0x1B }, - { 0x1E, 0x4E }, - { 0x1C, 0x06 }, - { 0x1D, 0x16 }, - { 0x1E, 0x28 }, - { 0x1C, 0x07 }, - { 0x1D, 0x22 }, - { 0x1E, 0xFF }, - { 0x1C, 0x08 }, - { 0x1D, 0x15 }, - { 0x1E, 0xF1 }, - { 0x1C, 0x09 }, - { 0x1D, 0x30 }, - { 0x1E, 0xD5 }, - { 0x1C, 0x0A }, - { 0x1D, 0x00 }, - { 0x1E, 0x9E }, - { 0x1C, 0x0B }, - { 0x1D, 0x17 }, - { 0x1E, 0x9D }, - { 0x1C, 0x0C }, - { 0x1D, 0x28 }, - { 0x1E, 0xD7 }, - { 0x1C, 0x0D }, - { 0x1D, 0x17 }, - { 0x1E, 0xD7 }, - { 0x1C, 0x0E }, - { 0x1D, 0x0A }, - { 0x1E, 0xCB }, - { 0x1C, 0x0F }, - { 0x1D, 0x24 }, - { 0x1E, 0x14 }, - { 0x1C, 0x10 }, - { 0x1D, 0x17 }, - { 0x1E, 0x85 }, - { 0x1C, 0x11 }, - { 0x1D, 0x15 }, - { 0x1E, 0x71 }, - { 0x1C, 0x12 }, - { 0x1D, 0x2B }, - { 0x1E, 0x36 }, - { 0x1C, 0x13 }, - { 0x1D, 0x12 }, - { 0x1E, 0x06 }, - { 0x1C, 0x14 }, - { 0x1D, 0x30 }, - { 0x1E, 0x97 }, - { 0x1C, 0x15 }, - { 0x1D, 0x21 }, - { 0x1E, 0x32 }, - { 0x1C, 0x16 }, - { 0x1D, 0x06 }, - { 0x1E, 0xE6 }, - { 0x1C, 0x17 }, - { 0x1D, 0x16 }, - { 0x1E, 0x06 }, - { 0x1C, 0x18 }, - { 0x1D, 0x30 }, - { 0x1E, 0x01 }, - { 0x1C, 0x19 }, - { 0x1D, 0x21 }, - { 0x1E, 0x37 }, - { 0x1C, 0x1A }, - { 0x1D, 0x00 }, - { 0x1E, 0x08 }, - { 0x1C, 0x1B }, - { 0x1D, 0x80 }, - { 0x1E, 0xD5 }, - { 0xA2, 0x50 }, - { 0xA2, 0x50 }, - { 0x81, 0x01 } + { 0x80, 0x01 }, + { 0x80, 0x12 }, + { 0x84, 0x01 }, + { 0x85, 0x00 }, + { 0x89, 0x64 }, + { 0x8A, 0x00 }, + { 0x8B, 0x0E }, + { 0x8C, 0x90 }, + { 0xBE, 0x23 }, + { 0x29, 0x04 }, + { 0x2A, 0xFF }, + { 0x96, 0x00 }, + { 0x98, 0x03 }, + { 0x99, 0x00 }, + { 0x9C, 0xA5 }, + { 0x9D, 0x40 }, + { 0x9E, 0xC6 }, + { 0x9F, 0x8E }, + { 0xA2, 0x50 }, + { 0xA3, 0xF0 }, + { 0xAD, 0x08 }, + { 0xBD, 0x4F }, + { 0xAF, 0x54 }, + { 0xB1, 0x08 }, + { 0xB5, 0xAB }, + { 0x1B, 0x2D }, + { 0xB6, 0x4E }, + { 0xB8, 0x70 }, + { 0x2B, 0xB3 }, + { 0x2C, 0x5D }, + { 0x2D, 0x98 }, + { 0x2E, 0xB0 }, + { 0x2F, 0x20 }, + { 0xA2, 0xD0 }, + { 0x1D, 0x21 }, + { 0x1E, 0xBE }, + { 0x1C, 0x00 }, + { 0x1D, 0x30 }, + { 0x1E, 0x29 }, + { 0x1C, 0x01 }, + { 0x1D, 0x00 }, + { 0x1E, 0x9E }, + { 0x1C, 0x02 }, + { 0x1D, 0x30 }, + { 0x1E, 0xBB }, + { 0x1C, 0x03 }, + { 0x1D, 0x00 }, + { 0x1E, 0x9D }, + { 0x1C, 0x04 }, + { 0x1D, 0x22 }, + { 0x1E, 0xFF }, + { 0x1C, 0x05 }, + { 0x1D, 0x1B }, + { 0x1E, 0x4E }, + { 0x1C, 0x06 }, + { 0x1D, 0x16 }, + { 0x1E, 0x28 }, + { 0x1C, 0x07 }, + { 0x1D, 0x22 }, + { 0x1E, 0xFF }, + { 0x1C, 0x08 }, + { 0x1D, 0x15 }, + { 0x1E, 0xF1 }, + { 0x1C, 0x09 }, + { 0x1D, 0x30 }, + { 0x1E, 0xD5 }, + { 0x1C, 0x0A }, + { 0x1D, 0x00 }, + { 0x1E, 0x9E }, + { 0x1C, 0x0B }, + { 0x1D, 0x17 }, + { 0x1E, 0x9D }, + { 0x1C, 0x0C }, + { 0x1D, 0x28 }, + { 0x1E, 0xD7 }, + { 0x1C, 0x0D }, + { 0x1D, 0x17 }, + { 0x1E, 0xD7 }, + { 0x1C, 0x0E }, + { 0x1D, 0x0A }, + { 0x1E, 0xCB }, + { 0x1C, 0x0F }, + { 0x1D, 0x24 }, + { 0x1E, 0x14 }, + { 0x1C, 0x10 }, + { 0x1D, 0x17 }, + { 0x1E, 0x85 }, + { 0x1C, 0x11 }, + { 0x1D, 0x15 }, + { 0x1E, 0x71 }, + { 0x1C, 0x12 }, + { 0x1D, 0x2B }, + { 0x1E, 0x36 }, + { 0x1C, 0x13 }, + { 0x1D, 0x12 }, + { 0x1E, 0x06 }, + { 0x1C, 0x14 }, + { 0x1D, 0x30 }, + { 0x1E, 0x97 }, + { 0x1C, 0x15 }, + { 0x1D, 0x21 }, + { 0x1E, 0x32 }, + { 0x1C, 0x16 }, + { 0x1D, 0x06 }, + { 0x1E, 0xE6 }, + { 0x1C, 0x17 }, + { 0x1D, 0x16 }, + { 0x1E, 0x06 }, + { 0x1C, 0x18 }, + { 0x1D, 0x30 }, + { 0x1E, 0x01 }, + { 0x1C, 0x19 }, + { 0x1D, 0x21 }, + { 0x1E, 0x37 }, + { 0x1C, 0x1A }, + { 0x1D, 0x00 }, + { 0x1E, 0x08 }, + { 0x1C, 0x1B }, + { 0x1D, 0x80 }, + { 0x1E, 0xD5 }, + { 0xA2, 0x50 }, + { 0xA2, 0x50 }, + { 0x81, 0x01 } }; static struct aes_regwrite strip_scan_reqs[] = { - { 0xBE, 0x23 }, - { 0x29, 0x04 }, - { 0x2A, 0xFF }, - { 0xBD, 0x4F }, - { 0xFF, 0x00 } + { 0xBE, 0x23 }, + { 0x29, 0x04 }, + { 0x2A, 0xFF }, + { 0xBD, 0x4F }, + { 0xFF, 0x00 } }; static const struct aes_regwrite capture_stop[] = { - { 0x81,0x00 } + { 0x81, 0x00 } }; /* * The different possible values for 0xBE register */ static unsigned char list_BE_values[10] = { - 0x23, 0x43, 0x63, 0x64, 0x65, 0x67, 0x6A, 0x6B + 0x23, 0x43, 0x63, 0x64, 0x65, 0x67, 0x6A, 0x6B }; /* * The different possible values for 0xBD register */ static unsigned char list_BD_values[10] = { - 0x28, 0x2b, 0x30, 0x3b, 0x45, 0x49, 0x4B + 0x28, 0x2b, 0x30, 0x3b, 0x45, 0x49, 0x4B }; /* @@ -406,129 +413,141 @@ static unsigned char list_BD_values[10] = { * 0xbd, 0xbe, 0x29 and 0x2A registers are affected * Returns 0 if no problem occurred * TODO: This is a basic support for gain. It needs testing/tweaking. */ -static int adjust_gain(unsigned char *buffer, int status) +static int +adjust_gain (unsigned char *buffer, int status) { - // The position in the array of possible values for 0xBE and 0xBD registers - static int pos_list_BE = 0; - static int pos_list_BD = 0; + // The position in the array of possible values for 0xBE and 0xBD registers + static int pos_list_BE = 0; + static int pos_list_BD = 0; - // This is the first adjustment (we begin acquisition) - // We adjust strip_scan_reqs for future strips and capture_reqs that is sent just after this step - if (status == GAIN_STATUS_FIRST) { - if (buffer[1] > 0x78) { // maximum gain needed - strip_scan_reqs[0].value = 0x6B; - strip_scan_reqs[1].value = 0x06; - strip_scan_reqs[2].value = 0x35; - strip_scan_reqs[3].value = 0x4B; - } - else if (buffer[1] > 0x55) { - strip_scan_reqs[0].value = 0x63; - strip_scan_reqs[1].value = 0x15; - strip_scan_reqs[2].value = 0x35; - strip_scan_reqs[3].value = 0x3b; - } - else if (buffer[1] > 0x40 || buffer[16] > 0x19) { - strip_scan_reqs[0].value = 0x43; - strip_scan_reqs[1].value = 0x13; - strip_scan_reqs[2].value = 0x35; - strip_scan_reqs[3].value = 0x30; - } - else { // minimum gain needed - strip_scan_reqs[0].value = 0x23; - strip_scan_reqs[1].value = 0x07; - strip_scan_reqs[2].value = 0x35; - strip_scan_reqs[3].value = 0x28; - } + // This is the first adjustment (we begin acquisition) + // We adjust strip_scan_reqs for future strips and capture_reqs that is sent just after this step + if (status == GAIN_STATUS_FIRST) + { + if (buffer[1] > 0x78) // maximum gain needed + { + strip_scan_reqs[0].value = 0x6B; + strip_scan_reqs[1].value = 0x06; + strip_scan_reqs[2].value = 0x35; + strip_scan_reqs[3].value = 0x4B; + } + else if (buffer[1] > 0x55) + { + strip_scan_reqs[0].value = 0x63; + strip_scan_reqs[1].value = 0x15; + strip_scan_reqs[2].value = 0x35; + strip_scan_reqs[3].value = 0x3b; + } + else if (buffer[1] > 0x40 || buffer[16] > 0x19) + { + strip_scan_reqs[0].value = 0x43; + strip_scan_reqs[1].value = 0x13; + strip_scan_reqs[2].value = 0x35; + strip_scan_reqs[3].value = 0x30; + } + else // minimum gain needed + { + strip_scan_reqs[0].value = 0x23; + strip_scan_reqs[1].value = 0x07; + strip_scan_reqs[2].value = 0x35; + strip_scan_reqs[3].value = 0x28; + } - // Now copy this values in capture_reqs - capture_reqs[8].value = strip_scan_reqs[0].value; - capture_reqs[9].value = strip_scan_reqs[1].value; - capture_reqs[10].value = strip_scan_reqs[2].value; - capture_reqs[21].value = strip_scan_reqs[3].value; + // Now copy this values in capture_reqs + capture_reqs[8].value = strip_scan_reqs[0].value; + capture_reqs[9].value = strip_scan_reqs[1].value; + capture_reqs[10].value = strip_scan_reqs[2].value; + capture_reqs[21].value = strip_scan_reqs[3].value; - fp_dbg("first gain: %x %x %x %x %x %x %x %x", strip_scan_reqs[0].reg, strip_scan_reqs[0].value, strip_scan_reqs[1].reg, strip_scan_reqs[1].value, strip_scan_reqs[2].reg, strip_scan_reqs[2].value, strip_scan_reqs[3].reg, strip_scan_reqs[3].value); - } + fp_dbg ("first gain: %x %x %x %x %x %x %x %x", strip_scan_reqs[0].reg, strip_scan_reqs[0].value, strip_scan_reqs[1].reg, strip_scan_reqs[1].value, strip_scan_reqs[2].reg, strip_scan_reqs[2].value, strip_scan_reqs[3].reg, strip_scan_reqs[3].value); + } + // Every 2/3 strips + // We try to soften big changes of the gain (at least for 0xBE and 0xBD + // FIXME: This softenning will need testing and tweaking too + else if (status == GAIN_STATUS_NORMAL) + { + if (buffer[514] > 0x78) // maximum gain needed + { + if (pos_list_BE < 7) + pos_list_BE++; - // Every 2/3 strips - // We try to soften big changes of the gain (at least for 0xBE and 0xBD - // FIXME: This softenning will need testing and tweaking too - else if (status == GAIN_STATUS_NORMAL) { - if (buffer[514] > 0x78) { // maximum gain needed - if (pos_list_BE < 7) - pos_list_BE++; + if (pos_list_BD < 6) + pos_list_BD++; - if (pos_list_BD < 6) - pos_list_BD++; + strip_scan_reqs[1].value = 0x04; + strip_scan_reqs[2].value = 0x35; + } + else if (buffer[514] > 0x55) + { + if (pos_list_BE < 2) + pos_list_BE++; + else if (pos_list_BE > 2) + pos_list_BE--; - strip_scan_reqs[1].value = 0x04; - strip_scan_reqs[2].value = 0x35; - } - else if (buffer[514] > 0x55) { - if (pos_list_BE < 2) - pos_list_BE++; - else if (pos_list_BE > 2) - pos_list_BE--; + if (pos_list_BD < 2) + pos_list_BD++; + else if (pos_list_BD > 2) + pos_list_BD--; - if (pos_list_BD < 2) - pos_list_BD++; - else if (pos_list_BD > 2) - pos_list_BD--; + strip_scan_reqs[1].value = 0x15; + strip_scan_reqs[2].value = 0x35; + } + else if (buffer[514] > 0x40 || buffer[529] > 0x19) + { + if (pos_list_BE < 1) + pos_list_BE++; + else if (pos_list_BE > 1) + pos_list_BE--; - strip_scan_reqs[1].value = 0x15; - strip_scan_reqs[2].value = 0x35; - } - else if (buffer[514] > 0x40 || buffer[529] > 0x19) { - if (pos_list_BE < 1) - pos_list_BE++; - else if (pos_list_BE > 1) - pos_list_BE--; + if (pos_list_BD < 1) + pos_list_BD++; + else if (pos_list_BD > 1) + pos_list_BD--; - if (pos_list_BD < 1) - pos_list_BD++; - else if (pos_list_BD > 1) - pos_list_BD--; + strip_scan_reqs[1].value = 0x13; + strip_scan_reqs[2].value = 0x35; + } + else // minimum gain needed + { + if (pos_list_BE > 0) + pos_list_BE--; - strip_scan_reqs[1].value = 0x13; - strip_scan_reqs[2].value = 0x35; - } - else { // minimum gain needed - if (pos_list_BE > 0) - pos_list_BE--; + if (pos_list_BD > 0) + pos_list_BD--; - if (pos_list_BD > 0) - pos_list_BD--; + strip_scan_reqs[1].value = 0x07; + strip_scan_reqs[2].value = 0x35; + } - strip_scan_reqs[1].value = 0x07; - strip_scan_reqs[2].value = 0x35; - } + strip_scan_reqs[0].value = list_BE_values[pos_list_BE]; + strip_scan_reqs[3].value = list_BD_values[pos_list_BD]; - strip_scan_reqs[0].value = list_BE_values[pos_list_BE]; - strip_scan_reqs[3].value = list_BD_values[pos_list_BD]; + fp_dbg ("gain: %x %x %x %x %x %x %x %x", strip_scan_reqs[0].reg, strip_scan_reqs[0].value, strip_scan_reqs[1].reg, strip_scan_reqs[1].value, strip_scan_reqs[2].reg, strip_scan_reqs[2].value, strip_scan_reqs[3].reg, strip_scan_reqs[3].value); + } + // Unknown status + else + { + fp_err ("Unexpected gain status."); + return 1; + } - fp_dbg("gain: %x %x %x %x %x %x %x %x", strip_scan_reqs[0].reg, strip_scan_reqs[0].value, strip_scan_reqs[1].reg, strip_scan_reqs[1].value, strip_scan_reqs[2].reg, strip_scan_reqs[2].value, strip_scan_reqs[3].reg, strip_scan_reqs[3].value); - } - // Unknown status - else { - fp_err("Unexpected gain status."); - return 1; - } - - return 0; + return 0; } /* * Restore the default gain values */ -static void restore_gain(void) +static void +restore_gain (void) { - strip_scan_reqs[0].value = list_BE_values[0]; - strip_scan_reqs[1].value = 0x04; - strip_scan_reqs[2].value = 0xFF; - strip_scan_reqs[3].value = list_BD_values[0]; + strip_scan_reqs[0].value = list_BE_values[0]; + strip_scan_reqs[1].value = 0x04; + strip_scan_reqs[2].value = 0xFF; + strip_scan_reqs[3].value = list_BD_values[0]; - capture_reqs[8].value = list_BE_values[0]; - capture_reqs[9].value = 0x04; - capture_reqs[10].value = 0xFF; - capture_reqs[21].value = list_BD_values[0]; + capture_reqs[8].value = list_BE_values[0]; + capture_reqs[9].value = 0x04; + capture_reqs[10].value = 0xFF; + capture_reqs[21].value = list_BD_values[0]; } @@ -538,300 +557,319 @@ static void restore_gain(void) * report lack of finger presence, and move to finger detection */ enum capture_states { - CAPTURE_WRITE_REQS, - CAPTURE_READ_DATA, - CAPTURE_REQUEST_STRIP, - CAPTURE_READ_STRIP, - CAPTURE_NUM_STATES, + CAPTURE_WRITE_REQS, + CAPTURE_READ_DATA, + CAPTURE_REQUEST_STRIP, + CAPTURE_READ_STRIP, + CAPTURE_NUM_STATES, }; -static void capture_read_strip_cb(struct libusb_transfer *transfer) +static void +capture_read_strip_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - unsigned char *stripdata; - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - unsigned char *data = transfer->buffer; - int sum, i; + unsigned char *stripdata; + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (dev); + unsigned char *data = transfer->buffer; + gint sum, i; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fpi_ssm_mark_failed(ssm, -EIO); - goto out; - } else if (transfer->length != transfer->actual_length) { - fpi_ssm_mark_failed(ssm, -EPROTO); - goto out; - } + if (error) + { + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } - /* FIXME: would preallocating strip buffers be a decent optimization? */ + /* FIXME: would preallocating strip buffers be a decent optimization? */ - sum = 0; - for (i = 516; i < 530; i++) - { - /* histogram[i] = number of pixels of value i - Only the pixel values from 10 to 15 are used to detect finger. */ - sum += data[i]; - } + sum = 0; + for (i = 516; i < 530; i++) + /* histogram[i] = number of pixels of value i + Only the pixel values from 10 to 15 are used to detect finger. */ + sum += data[i]; - if (sum > 0) { - /* FIXME: would preallocating strip buffers be a decent optimization? */ - struct fpi_frame *stripe = g_malloc(FRAME_WIDTH * (FRAME_HEIGHT / 2) + sizeof(struct fpi_frame)); - stripe->delta_x = 0; - stripe->delta_y = 0; - stripdata = stripe->data; - memcpy(stripdata, data + 1, FRAME_WIDTH * (FRAME_HEIGHT / 2)); - aesdev->strips = g_slist_prepend(aesdev->strips, stripe); - aesdev->strips_len++; - aesdev->blanks_count = 0; - } + fp_dbg ("sum=%d", sum); + if (sum > 0) + { + /* FIXME: would preallocating strip buffers be a decent optimization? */ + struct fpi_frame *stripe = g_malloc (FRAME_WIDTH * (FRAME_HEIGHT / 2) + sizeof (struct fpi_frame)); + stripe->delta_x = 0; + stripe->delta_y = 0; + stripdata = stripe->data; + memcpy (stripdata, data + 1, FRAME_WIDTH * (FRAME_HEIGHT / 2)); + self->strips = g_slist_prepend (self->strips, stripe); + self->strips_len++; + self->blanks_count = 0; + } + else + { + /* FIXME: 0 might be too low as a threshold */ + /* FIXME: sometimes we get 0 in the middle of a scan, should we wait for + * a few consecutive zeroes? */ - if (sum < 0) { - fpi_ssm_mark_failed(ssm, sum); - goto out; - } - fp_dbg("sum=%d", sum); + /* sum cannot be negative, so is 0 */ + self->blanks_count++; + fp_dbg ("got blank frame"); + } - /* FIXME: 0 might be too low as a threshold */ - /* FIXME: sometimes we get 0 in the middle of a scan, should we wait for - * a few consecutive zeroes? */ - /* If sum is 0 for a reasonable # of frames, finger has been removed */ - if (sum == 0) { - aesdev->blanks_count++; - fp_dbg("got blank frame"); - } + /* use histogram data above for gain calibration (0xbd, 0xbe, 0x29 and 0x2A ) */ + adjust_gain (data, GAIN_STATUS_NORMAL); - /* use histogram data above for gain calibration (0xbd, 0xbe, 0x29 and 0x2A ) */ - adjust_gain(data, GAIN_STATUS_NORMAL); + /* stop capturing if MAX_FRAMES is reached */ + if (self->blanks_count > 10 || g_slist_length (self->strips) >= MAX_FRAMES) + { + FpImage *img; - /* stop capturing if MAX_FRAMES is reached */ - if (aesdev->blanks_count > 10 || g_slist_length(aesdev->strips) >= MAX_FRAMES) { - struct fp_img *img; + fp_dbg ("sending stop capture.... blanks=%d frames=%d", + self->blanks_count, g_slist_length (self->strips)); + /* send stop capture bits */ + aes_write_regv (dev, capture_stop, G_N_ELEMENTS (capture_stop), stub_capture_stop_cb, NULL); + self->strips = g_slist_reverse (self->strips); + fpi_do_movement_estimation (&assembling_ctx, self->strips); + img = fpi_assemble_frames (&assembling_ctx, self->strips); - fp_dbg("sending stop capture.... blanks=%d frames=%d", aesdev->blanks_count, g_slist_length(aesdev->strips)); - /* send stop capture bits */ - aes_write_regv(dev, capture_stop, G_N_ELEMENTS(capture_stop), stub_capture_stop_cb, NULL); - aesdev->strips = g_slist_reverse(aesdev->strips); - fpi_do_movement_estimation(&assembling_ctx, aesdev->strips, aesdev->strips_len); - img = fpi_assemble_frames(&assembling_ctx, aesdev->strips, aesdev->strips_len); - img->flags |= FP_IMG_PARTIAL; - g_slist_free_full(aesdev->strips, g_free); - aesdev->strips = NULL; - aesdev->strips_len = 0; - aesdev->blanks_count = 0; - fpi_imgdev_image_captured(dev, img); - fpi_imgdev_report_finger_status(dev, FALSE); - /* marking machine complete will re-trigger finger detection loop */ - fpi_ssm_mark_completed(ssm); - /* Acquisition finished: restore default gain values */ - restore_gain(); - } else { - /* obtain next strip */ - fpi_ssm_jump_to_state(ssm, CAPTURE_REQUEST_STRIP); - } - -out: - g_free(data); - libusb_free_transfer(transfer); + g_slist_free_full (self->strips, g_free); + self->strips = NULL; + self->strips_len = 0; + self->blanks_count = 0; + fpi_image_device_image_captured (dev, img); + fpi_image_device_report_finger_status (dev, FALSE); + /* marking machine complete will re-trigger finger detection loop */ + fpi_ssm_mark_completed (transfer->ssm); + /* Acquisition finished: restore default gain values */ + restore_gain (); + } + else + { + /* obtain next strip */ + fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_REQUEST_STRIP); + } } -static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +capture_run_state (FpiSsm *ssm, FpDevice *_dev) { - struct fp_img_dev *dev = user_data; - struct aes1610_dev *aesdev = FP_INSTANCE_DATA(_dev); - int r; + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (_dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case CAPTURE_WRITE_REQS: - fp_dbg("write reqs"); - aes_write_regv(dev, capture_reqs, G_N_ELEMENTS(capture_reqs), - generic_write_regv_cb, ssm); - break; - case CAPTURE_READ_DATA: - fp_dbg("read data"); - generic_read_ignore_data(ssm, _dev, STRIP_CAPTURE_LEN); - break; - case CAPTURE_REQUEST_STRIP: - fp_dbg("request strip"); - if (aesdev->deactivating) - fpi_ssm_mark_completed(ssm); - else - aes_write_regv(dev, strip_scan_reqs, G_N_ELEMENTS(strip_scan_reqs), - generic_write_regv_cb, ssm); - break; - case CAPTURE_READ_STRIP: ; - struct libusb_transfer *transfer = fpi_usb_alloc(); - unsigned char *data; + switch (fpi_ssm_get_cur_state (ssm)) + { + case CAPTURE_WRITE_REQS: + fp_dbg ("write reqs"); + aes_write_regv (dev, capture_reqs, G_N_ELEMENTS (capture_reqs), + generic_write_regv_cb, ssm); + break; - data = g_malloc(STRIP_CAPTURE_LEN); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, STRIP_CAPTURE_LEN, - capture_read_strip_cb, ssm, BULK_TIMEOUT); + case CAPTURE_READ_DATA: + fp_dbg ("read data"); + generic_read_ignore_data (ssm, _dev, STRIP_CAPTURE_LEN); + break; - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(data); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } - break; - }; + case CAPTURE_REQUEST_STRIP: + fp_dbg ("request strip"); + if (self->deactivating) + fpi_ssm_mark_completed (ssm); + else + aes_write_regv (dev, strip_scan_reqs, G_N_ELEMENTS (strip_scan_reqs), + generic_write_regv_cb, ssm); + break; + + case CAPTURE_READ_STRIP:; + FpiUsbTransfer *transfer = fpi_usb_transfer_new (_dev); + + fpi_usb_transfer_fill_bulk (transfer, EP_IN, STRIP_CAPTURE_LEN); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + capture_read_strip_cb, NULL); + fpi_usb_transfer_unref (transfer); + break; + } + ; } -static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { - struct fp_img_dev *dev = user_data; - struct aes1610_dev *aesdev = FP_INSTANCE_DATA(_dev); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (_dev); - G_DEBUG_HERE(); - if (aesdev->deactivating) - complete_deactivation(dev); - else if (fpi_ssm_get_error(ssm)) - fpi_imgdev_session_error(dev, fpi_ssm_get_error(ssm)); - else - start_finger_detection(dev); - fpi_ssm_free(ssm); + G_DEBUG_HERE (); + if (self->deactivating) + { + complete_deactivation (dev); + if (error) + g_error_free (error); + } + else if (error) + { + fpi_image_device_session_error (dev, error); + } + else + { + start_finger_detection (dev); + } + fpi_ssm_free (ssm); } -static void start_capture(struct fp_img_dev *dev) +static void +start_capture (FpImageDevice *dev) { - struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_ssm *ssm; + FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (dev); + FpiSsm *ssm; - if (aesdev->deactivating) { - complete_deactivation(dev); - return; - } + if (self->deactivating) + { + complete_deactivation (dev); + return; + } - ssm = fpi_ssm_new(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev); - G_DEBUG_HERE(); - fpi_ssm_start(ssm, capture_sm_complete); + ssm = fpi_ssm_new (FP_DEVICE (dev), capture_run_state, + CAPTURE_NUM_STATES); + G_DEBUG_HERE (); + fpi_ssm_start (ssm, capture_sm_complete); } /****** INITIALIZATION/DEINITIALIZATION ******/ static const struct aes_regwrite init[] = { - { 0x82, 0x00 } + { 0x82, 0x00 } }; /* -static const struct aes_regwrite stop_reader[] = { - { 0xFF, 0x00 } -}; -*/ + static const struct aes_regwrite stop_reader[] = { + { 0xFF, 0x00 } + }; + */ enum activate_states { - WRITE_INIT, - ACTIVATE_NUM_STATES, + WRITE_INIT, + ACTIVATE_NUM_STATES, }; -static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +activate_run_state (FpiSsm *ssm, FpDevice *_dev) { - struct fp_img_dev *dev = user_data; + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); - /* activation on aes1610 seems much more straightforward compared to aes2501 */ - /* verify there's anything missing here */ - switch (fpi_ssm_get_cur_state(ssm)) { - case WRITE_INIT: - fp_dbg("write init"); - aes_write_regv(dev, init, G_N_ELEMENTS(init), generic_write_regv_cb, ssm); - break; - } + /* activation on aes1610 seems much more straightforward compared to aes2501 */ + /* verify there's anything missing here */ + switch (fpi_ssm_get_cur_state (ssm)) + { + case WRITE_INIT: + fp_dbg ("write init"); + aes_write_regv (dev, init, G_N_ELEMENTS (init), generic_write_regv_cb, ssm); + break; + } } /* jump to finger detection */ -static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { - struct fp_img_dev *dev = user_data; - fp_dbg("status %d", fpi_ssm_get_error(ssm)); - fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm)); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); - if (!fpi_ssm_get_error(ssm)) - start_finger_detection(dev); - fpi_ssm_free(ssm); + fpi_image_device_activate_complete (dev, error); + + if (!error) + start_finger_detection (dev); + fpi_ssm_free (ssm); } -static int dev_activate(struct fp_img_dev *dev) +static void +dev_activate (FpImageDevice *dev) { - struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, - ACTIVATE_NUM_STATES, dev); - aesdev->read_regs_retry_count = 0; - fpi_ssm_start(ssm, activate_sm_complete); - return 0; + FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (dev); + FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), activate_run_state, + ACTIVATE_NUM_STATES); + + self->read_regs_retry_count = 0; + fpi_ssm_start (ssm, activate_sm_complete); } -static void dev_deactivate(struct fp_img_dev *dev) +static void +dev_deactivate (FpImageDevice *dev) { - struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - /* FIXME: audit cancellation points, probably need more, specifically - * in error handling paths? */ - aesdev->deactivating = TRUE; + FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (dev); + + /* FIXME: audit cancellation points, probably need more, specifically + * in error handling paths? */ + self->deactivating = TRUE; } -static void complete_deactivation(struct fp_img_dev *dev) +static void +complete_deactivation (FpImageDevice *dev) { - struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - G_DEBUG_HERE(); + FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (dev); - /* FIXME: if we're in the middle of a scan, we should cancel the scan. - * maybe we can do this with a master reset, unconditionally? */ + G_DEBUG_HERE (); - aesdev->deactivating = FALSE; - g_slist_free(aesdev->strips); - aesdev->strips = NULL; - aesdev->strips_len = 0; - aesdev->blanks_count = 0; - fpi_imgdev_deactivate_complete(dev); + /* FIXME: if we're in the middle of a scan, we should cancel the scan. + * maybe we can do this with a master reset, unconditionally? */ + + self->deactivating = FALSE; + g_slist_free (self->strips); + self->strips = NULL; + self->strips_len = 0; + self->blanks_count = 0; + fpi_image_device_deactivate_complete (dev, NULL); } -static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) +static void +dev_init (FpImageDevice *dev) { - /* FIXME check endpoints */ - int r; - struct aes1610_dev *aesdev; + GError *error = NULL; - r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - if (r < 0) { - fp_err("could not claim interface 0: %s", libusb_error_name(r)); - return r; - } + /* FIXME check endpoints */ - aesdev = g_malloc0(sizeof(struct aes1610_dev)); - fp_dev_set_instance_data(FP_DEV(dev), aesdev); - fpi_imgdev_open_complete(dev, 0); - return 0; + if (!g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error)) + { + fpi_image_device_open_complete (dev, error); + return; + } + + fpi_image_device_open_complete (dev, NULL); } -static void dev_deinit(struct fp_img_dev *dev) +static void +dev_deinit (FpImageDevice *dev) { - struct aes1610_dev *aesdev; - aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - g_free(aesdev); - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - fpi_imgdev_close_complete(dev); + GError *error = NULL; + + g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), + 0, 0, &error); + fpi_image_device_close_complete (dev, error); } -static const struct usb_id id_table[] = { - { .vendor = 0x08ff, .product = 0x1600 }, /* AES1600 */ - { 0, 0, 0, }, +static const FpIdEntry id_table[] = { + { .vid = 0x08ff, .pid = 0x1600, },/* AES1600 */ + { .vid = 0, .pid = 0, .driver_data = 0 }, }; -struct fp_img_driver aes1610_driver = { - .driver = { - .id = AES1610_ID, - .name = FP_COMPONENT, - .full_name = "AuthenTec AES1610", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_SWIPE, - }, - .flags = 0, - .img_height = -1, - .img_width = IMAGE_WIDTH, +static void +fpi_device_aes1610_init (FpiDeviceAes1610 *self) +{ +} +static void +fpi_device_aes1610_class_init (FpiDeviceAes1610Class *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); - .bz3_threshold = 20, + dev_class->id = "aes1610"; + dev_class->full_name = "AuthenTec AES1610"; + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->id_table = id_table; + dev_class->scan_type = FP_SCAN_TYPE_SWIPE; - .open = dev_init, - .close = dev_deinit, - .activate = dev_activate, - .deactivate = dev_deactivate, -}; + img_class->img_open = dev_init; + img_class->img_close = dev_deinit; + img_class->activate = dev_activate; + img_class->deactivate = dev_deactivate; + img_class->bz3_threshold = 20; + + img_class->img_width = IMAGE_WIDTH; + img_class->img_height = -1; +} diff --git a/libfprint/drivers/aes1660.c b/libfprint/drivers/aes1660.c index f27b9bf9..93da6967 100644 --- a/libfprint/drivers/aes1660.c +++ b/libfprint/drivers/aes1660.c @@ -25,88 +25,71 @@ #include "aes1660.h" #define FRAME_WIDTH 128 -#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2)) +#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2)) + +struct _FpiDeviceAes1660 +{ + FpiDeviceAesX660 parent; +}; +G_DECLARE_FINAL_TYPE (FpiDeviceAes1660, fpi_device_aes1660, FPI, + DEVICE_AES1660, FpiDeviceAesX660); +G_DEFINE_TYPE (FpiDeviceAes1660, fpi_device_aes1660, FPI_TYPE_DEVICE_AES_X660); static struct fpi_frame_asmbl_ctx assembling_ctx = { - .frame_width = FRAME_WIDTH, - .frame_height = AESX660_FRAME_HEIGHT, - .image_width = IMAGE_WIDTH, - .get_pixel = aes_get_pixel, + .frame_width = FRAME_WIDTH, + .frame_height = AESX660_FRAME_HEIGHT, + .image_width = IMAGE_WIDTH, + .get_pixel = aes_get_pixel, }; -static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) +static const FpIdEntry id_table[] = { + { .vid = 0x08ff, .pid = 0x1660, }, + { .vid = 0x08ff, .pid = 0x1680, }, + { .vid = 0x08ff, .pid = 0x1681, }, + { .vid = 0x08ff, .pid = 0x1682, }, + { .vid = 0x08ff, .pid = 0x1683, }, + { .vid = 0x08ff, .pid = 0x1684, }, + { .vid = 0x08ff, .pid = 0x1685, }, + { .vid = 0x08ff, .pid = 0x1686, }, + { .vid = 0x08ff, .pid = 0x1687, }, + { .vid = 0x08ff, .pid = 0x1688, }, + { .vid = 0x08ff, .pid = 0x1689, }, + { .vid = 0x08ff, .pid = 0x168a, }, + { .vid = 0x08ff, .pid = 0x168b, }, + { .vid = 0x08ff, .pid = 0x168c, }, + { .vid = 0x08ff, .pid = 0x168d, }, + { .vid = 0x08ff, .pid = 0x168e, }, + { .vid = 0x08ff, .pid = 0x168f, }, + { .vid = 0, .pid = 0, .driver_data = 0 }, +}; + +static void +fpi_device_aes1660_init (FpiDeviceAes1660 *self) { - /* TODO check that device has endpoints we're using */ - int r; - struct aesX660_dev *aesdev; - - r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - if (r < 0) { - fp_err("could not claim interface 0: %s", libusb_error_name(r)); - return r; - } - - aesdev = g_malloc0(sizeof(struct aesX660_dev)); - fp_dev_set_instance_data(FP_DEV(dev), aesdev); - aesdev->buffer = g_malloc0(AES1660_FRAME_SIZE + AESX660_HEADER_SIZE); - aesdev->init_seqs[0] = aes1660_init_1; - aesdev->init_seqs_len[0] = G_N_ELEMENTS(aes1660_init_1); - aesdev->init_seqs[1] = aes1660_init_2; - aesdev->init_seqs_len[1] = G_N_ELEMENTS(aes1660_init_2); - aesdev->start_imaging_cmd = (unsigned char *)aes1660_start_imaging_cmd; - aesdev->start_imaging_cmd_len = sizeof(aes1660_start_imaging_cmd); - aesdev->assembling_ctx = &assembling_ctx; - aesdev->extra_img_flags = FP_IMG_PARTIAL; - - fpi_imgdev_open_complete(dev, 0); - return 0; } - -static void dev_deinit(struct fp_img_dev *dev) +static void +fpi_device_aes1660_class_init (FpiDeviceAes1660Class *klass) { - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - g_free(aesdev->buffer); - g_free(aesdev); - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - fpi_imgdev_close_complete(dev); + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); + FpiDeviceAesX660Class *aes_class = FPI_DEVICE_AES_X660_CLASS (klass); + + dev_class->id = "aes1660"; + dev_class->full_name = "AuthenTec AES1660"; + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->id_table = id_table; + dev_class->scan_type = FP_SCAN_TYPE_SWIPE; + + img_class->bz3_threshold = 20; + + img_class->img_width = FRAME_WIDTH + FRAME_WIDTH / 2; + img_class->img_height = -1; + + aes_class->init_seqs[0] = aes1660_init_1; + aes_class->init_seqs_len[0] = G_N_ELEMENTS (aes1660_init_1); + aes_class->init_seqs[1] = aes1660_init_2; + aes_class->init_seqs_len[1] = G_N_ELEMENTS (aes1660_init_2); + aes_class->start_imaging_cmd = (unsigned char *) aes1660_start_imaging_cmd; + aes_class->start_imaging_cmd_len = sizeof (aes1660_start_imaging_cmd); + aes_class->assembling_ctx = &assembling_ctx; } - -static const struct usb_id id_table[] = { - { .vendor = 0x08ff, .product = 0x1660 }, - { .vendor = 0x08ff, .product = 0x1680 }, - { .vendor = 0x08ff, .product = 0x1681 }, - { .vendor = 0x08ff, .product = 0x1682 }, - { .vendor = 0x08ff, .product = 0x1683 }, - { .vendor = 0x08ff, .product = 0x1684 }, - { .vendor = 0x08ff, .product = 0x1685 }, - { .vendor = 0x08ff, .product = 0x1686 }, - { .vendor = 0x08ff, .product = 0x1687 }, - { .vendor = 0x08ff, .product = 0x1688 }, - { .vendor = 0x08ff, .product = 0x1689 }, - { .vendor = 0x08ff, .product = 0x168a }, - { .vendor = 0x08ff, .product = 0x168b }, - { .vendor = 0x08ff, .product = 0x168c }, - { .vendor = 0x08ff, .product = 0x168d }, - { .vendor = 0x08ff, .product = 0x168e }, - { .vendor = 0x08ff, .product = 0x168f }, - { 0, 0, 0, }, -}; - -struct fp_img_driver aes1660_driver = { - .driver = { - .id = AES1660_ID, - .name = FP_COMPONENT, - .full_name = "AuthenTec AES1660", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_SWIPE, - }, - .flags = 0, - .img_height = -1, - .img_width = FRAME_WIDTH + FRAME_WIDTH / 2, - .bz3_threshold = 20, - - .open = dev_init, - .close = dev_deinit, - .activate = aesX660_dev_activate, - .deactivate = aesX660_dev_deactivate, -}; diff --git a/libfprint/drivers/aes1660.h b/libfprint/drivers/aes1660.h index ccfb0bce..55a94e20 100644 --- a/libfprint/drivers/aes1660.h +++ b/libfprint/drivers/aes1660.h @@ -29,912 +29,912 @@ /* INIT1 */ static const unsigned char pkt107[] = { -0x44, 0x02, 0x00, 0x04, 0x00, -0x0d, 0x23, -0x42, 0xca, 0x00, -0x00, 0x20, 0x23, -0xff, 0x3f, 0x1d, 0xc1, 0x2e, 0xa3, 0xbf, 0xc2, -0x2e, 0x00, 0xdf, 0xff, 0x2d, 0x02, 0x5a, 0xbf, -0x22, 0xc1, 0x2e, 0xa3, 0xbf, 0x02, 0xcf, 0x0f, -0x1c, 0x10, 0x18, 0x26, 0x83, 0xc8, 0x46, 0x00, -0x5b, 0x01, 0x0c, 0xa2, 0x32, 0xa8, 0xcf, 0xf1, -0x1c, 0x0c, 0x18, 0xa8, 0xaf, 0xaf, 0x31, 0x0a, -0x3a, 0x5d, 0xcf, 0x30, 0x1c, 0x05, 0x55, 0x5d, -0x41, 0x03, 0x5b, 0x5d, 0xcf, 0xfc, 0x1c, 0x01, -0x18, 0x5d, 0xaf, 0x02, 0x43, 0x00, 0x2e, 0x09, -0x5a, 0x0c, 0xef, 0x56, 0xaf, 0x2e, 0x23, 0x02, -0x2e, 0x0b, 0x87, 0x83, 0x23, 0x84, 0x23, 0x81, -0x23, 0x82, 0x23, 0x24, 0x23, 0x0a, 0xef, 0xbf, -0x22, 0x00, 0x2e, 0xa9, 0x8b, 0x57, 0x23, 0x3c, -0x23, 0xf9, 0x34, 0x6b, 0x81, 0x64, 0xef, 0x64, -0xaf, 0x09, 0x88, 0xdf, 0xef, 0x27, 0xff, 0xd6, -0xaf, 0xd7, 0xbf, 0x46, 0xef, 0x46, 0xaf, 0x2a, -0xef, 0x2a, 0xaf, 0x05, 0x81, 0x05, 0x27, 0x10, -0xef, 0x99, 0xaf, 0x9b, 0xaf, 0x04, 0xaf, 0x3d, -0x23, 0x44, 0xef, 0x20, 0xff, 0x1a, 0x27, 0x05, -0xef, 0x27, 0xff, 0x06, 0x27, 0x05, 0x27, 0x9c, -0xcf, 0xdf, 0x96, 0xfe, 0xef, 0x27, 0xff, 0x19, -0x27, 0x65, 0xdf, 0xe1, 0x22, 0x1c, 0x55, 0xe0, -0x97, 0xbf, 0x03, 0x19, 0x5e, 0xfe, 0x0c, 0x9f, -0x22, 0x0f, 0xff, 0xe1, 0x22, 0x10, 0x55, 0x20, -0x00, 0x0e, 0x52, 0x82, 0x03, 0x03, 0x53 + 0x44, 0x02, 0x00, 0x04, 0x00, + 0x0d, 0x23, + 0x42, 0xca, 0x00, + 0x00, 0x20, 0x23, + 0xff, 0x3f, 0x1d, 0xc1, 0x2e, 0xa3, 0xbf, 0xc2, + 0x2e, 0x00, 0xdf, 0xff, 0x2d, 0x02, 0x5a, 0xbf, + 0x22, 0xc1, 0x2e, 0xa3, 0xbf, 0x02, 0xcf, 0x0f, + 0x1c, 0x10, 0x18, 0x26, 0x83, 0xc8, 0x46, 0x00, + 0x5b, 0x01, 0x0c, 0xa2, 0x32, 0xa8, 0xcf, 0xf1, + 0x1c, 0x0c, 0x18, 0xa8, 0xaf, 0xaf, 0x31, 0x0a, + 0x3a, 0x5d, 0xcf, 0x30, 0x1c, 0x05, 0x55, 0x5d, + 0x41, 0x03, 0x5b, 0x5d, 0xcf, 0xfc, 0x1c, 0x01, + 0x18, 0x5d, 0xaf, 0x02, 0x43, 0x00, 0x2e, 0x09, + 0x5a, 0x0c, 0xef, 0x56, 0xaf, 0x2e, 0x23, 0x02, + 0x2e, 0x0b, 0x87, 0x83, 0x23, 0x84, 0x23, 0x81, + 0x23, 0x82, 0x23, 0x24, 0x23, 0x0a, 0xef, 0xbf, + 0x22, 0x00, 0x2e, 0xa9, 0x8b, 0x57, 0x23, 0x3c, + 0x23, 0xf9, 0x34, 0x6b, 0x81, 0x64, 0xef, 0x64, + 0xaf, 0x09, 0x88, 0xdf, 0xef, 0x27, 0xff, 0xd6, + 0xaf, 0xd7, 0xbf, 0x46, 0xef, 0x46, 0xaf, 0x2a, + 0xef, 0x2a, 0xaf, 0x05, 0x81, 0x05, 0x27, 0x10, + 0xef, 0x99, 0xaf, 0x9b, 0xaf, 0x04, 0xaf, 0x3d, + 0x23, 0x44, 0xef, 0x20, 0xff, 0x1a, 0x27, 0x05, + 0xef, 0x27, 0xff, 0x06, 0x27, 0x05, 0x27, 0x9c, + 0xcf, 0xdf, 0x96, 0xfe, 0xef, 0x27, 0xff, 0x19, + 0x27, 0x65, 0xdf, 0xe1, 0x22, 0x1c, 0x55, 0xe0, + 0x97, 0xbf, 0x03, 0x19, 0x5e, 0xfe, 0x0c, 0x9f, + 0x22, 0x0f, 0xff, 0xe1, 0x22, 0x10, 0x55, 0x20, + 0x00, 0x0e, 0x52, 0x82, 0x03, 0x03, 0x53 }; static const unsigned char pkt112[] = { -0x42, 0xca, 0x00, -0x64, 0x20, 0xfe, 0x0d, 0x7f, -0x20, 0xf6, 0x55, 0x08, 0x50, 0x5f, 0x90, 0x82, -0x01, 0x1f, 0x90, 0xc1, 0x97, 0xa0, 0x01, 0x82, -0x01, 0xdf, 0x21, 0x80, 0x03, 0x00, 0x5e, 0x3f, -0x20, 0x29, 0xbf, 0x03, 0x0c, 0x05, 0x27, 0x01, -0x0c, 0x10, 0xff, 0x29, 0xbf, 0x05, 0x27, 0x9a, -0xcf, 0xdf, 0x96, 0xe0, 0xef, 0x27, 0xff, 0x19, -0x27, 0xfe, 0x0c, 0x9f, 0x22, 0x00, 0xff, 0xe1, -0x22, 0x10, 0x55, 0x20, 0x00, 0x0e, 0x52, 0x82, -0x03, 0x03, 0x53, 0x02, 0x0d, 0x3f, 0x20, 0x0f, -0x1f, 0xf5, 0x55, 0x5f, 0x90, 0x82, 0x01, 0x1f, -0x90, 0xc1, 0x97, 0xa0, 0x01, 0x82, 0x01, 0xdf, -0x21, 0x80, 0x03, 0x02, 0x5e, 0x7f, 0x20, 0x00, -0x53, 0xbf, 0x22, 0x29, 0xcf, 0xbf, 0x03, 0x01, -0x5e, 0x5f, 0x20, 0xdf, 0x9f, 0x28, 0xbf, 0x03, -0x0c, 0x05, 0x27, 0x24, 0xcf, 0x10, 0xdf, 0xbf, -0x01, 0x06, 0x1e, 0xe1, 0x2f, 0xe6, 0x5c, 0xdf, -0x2d, 0x00, 0x5b, 0x9f, 0x22, 0xdf, 0x96, 0xc8, -0xef, 0x20, 0xff, 0x1d, 0x00, 0x00, 0x13, 0x1a, -0x27, 0x07, 0x27, 0x9b, 0x22, 0xdf, 0x96, 0xbb, -0xcf, 0x1a, 0x88, 0xbb, 0xcf, 0x1b, 0x88, 0x01, -0x0f, 0xbc, 0xcf, 0x15, 0x88, 0xbc, 0xcf, 0x16, -0x88, 0x01, 0x0f, 0xbd, 0xcf, 0x10, 0x88, 0xbd, -0xcf, 0x11, 0x88, 0x01, 0x0f, 0xbe, 0xcf, 0x0b, -0x88, 0xbe, 0xcf, 0x0c, 0x88, 0x01, 0x0c, 0xdd, -0x97, 0x25, 0xaf, 0x05, 0x27 + 0x42, 0xca, 0x00, + 0x64, 0x20, 0xfe, 0x0d, 0x7f, + 0x20, 0xf6, 0x55, 0x08, 0x50, 0x5f, 0x90, 0x82, + 0x01, 0x1f, 0x90, 0xc1, 0x97, 0xa0, 0x01, 0x82, + 0x01, 0xdf, 0x21, 0x80, 0x03, 0x00, 0x5e, 0x3f, + 0x20, 0x29, 0xbf, 0x03, 0x0c, 0x05, 0x27, 0x01, + 0x0c, 0x10, 0xff, 0x29, 0xbf, 0x05, 0x27, 0x9a, + 0xcf, 0xdf, 0x96, 0xe0, 0xef, 0x27, 0xff, 0x19, + 0x27, 0xfe, 0x0c, 0x9f, 0x22, 0x00, 0xff, 0xe1, + 0x22, 0x10, 0x55, 0x20, 0x00, 0x0e, 0x52, 0x82, + 0x03, 0x03, 0x53, 0x02, 0x0d, 0x3f, 0x20, 0x0f, + 0x1f, 0xf5, 0x55, 0x5f, 0x90, 0x82, 0x01, 0x1f, + 0x90, 0xc1, 0x97, 0xa0, 0x01, 0x82, 0x01, 0xdf, + 0x21, 0x80, 0x03, 0x02, 0x5e, 0x7f, 0x20, 0x00, + 0x53, 0xbf, 0x22, 0x29, 0xcf, 0xbf, 0x03, 0x01, + 0x5e, 0x5f, 0x20, 0xdf, 0x9f, 0x28, 0xbf, 0x03, + 0x0c, 0x05, 0x27, 0x24, 0xcf, 0x10, 0xdf, 0xbf, + 0x01, 0x06, 0x1e, 0xe1, 0x2f, 0xe6, 0x5c, 0xdf, + 0x2d, 0x00, 0x5b, 0x9f, 0x22, 0xdf, 0x96, 0xc8, + 0xef, 0x20, 0xff, 0x1d, 0x00, 0x00, 0x13, 0x1a, + 0x27, 0x07, 0x27, 0x9b, 0x22, 0xdf, 0x96, 0xbb, + 0xcf, 0x1a, 0x88, 0xbb, 0xcf, 0x1b, 0x88, 0x01, + 0x0f, 0xbc, 0xcf, 0x15, 0x88, 0xbc, 0xcf, 0x16, + 0x88, 0x01, 0x0f, 0xbd, 0xcf, 0x10, 0x88, 0xbd, + 0xcf, 0x11, 0x88, 0x01, 0x0f, 0xbe, 0xcf, 0x0b, + 0x88, 0xbe, 0xcf, 0x0c, 0x88, 0x01, 0x0c, 0xdd, + 0x97, 0x25, 0xaf, 0x05, 0x27 }; static const unsigned char pkt116[] = { -0x42, 0xca, 0x00, -0xc8, 0x20, 0xff, 0x00, 0xab, -0x00, 0x72, 0x00, 0x4c, 0x00, 0x33, 0x00, 0x22, -0x00, 0x09, 0x88, 0xbf, 0x9d, 0x05, 0x27, 0x09, -0x27, 0x05, 0x88, 0xff, 0x97, 0x09, 0x27, 0xf6, -0x9f, 0x5f, 0x02, 0xbf, 0x9d, 0x05, 0x27, 0x0f, -0x1c, 0xc0, 0x9f, 0x8a, 0x80, 0x80, 0x10, 0x00, -0x13, 0x0f, 0x1d, 0xc1, 0x03, 0x00, 0x5f, 0x7f, -0x90, 0x05, 0x27, 0x53, 0x80, 0x2b, 0x0d, 0x05, -0x27, 0x9f, 0x22, 0x8f, 0xaf, 0x67, 0x2e, 0xe0, -0xdf, 0x04, 0x1e, 0x00, 0x52, 0x8f, 0x30, 0x67, -0x2e, 0xe1, 0xdf, 0xdf, 0x22, 0x00, 0x54, 0x8f, -0x30, 0x67, 0x2e, 0xfe, 0xdf, 0x04, 0x1e, 0x00, -0x52, 0x8f, 0x31, 0x67, 0x2e, 0xff, 0xdf, 0xdf, -0x22, 0x00, 0x54, 0x8f, 0x31, 0x8f, 0xcf, 0x03, -0x1c, 0x03, 0x1e, 0x00, 0x55, 0x0c, 0x27, 0x0d, -0x27, 0x4a, 0xcf, 0xdf, 0x96, 0x10, 0xcf, 0x5f, -0xdf, 0xbf, 0x03, 0x02, 0x5f, 0x5f, 0xcf, 0x10, -0xaf, 0x04, 0x50, 0x5e, 0xdf, 0xbf, 0x03, 0x01, -0x53, 0x5e, 0xcf, 0x10, 0xaf, 0x46, 0x88, 0x01, -0x2e, 0x1e, 0x80, 0xdd, 0x97, 0x0a, 0x40, 0x1c, -0x5a, 0x37, 0x43, 0x0b, 0x5b, 0xe2, 0xcf, 0x0f, -0x1c, 0x06, 0x1e, 0x07, 0x52, 0x62, 0xdf, 0x18, -0x1f, 0x07, 0x53, 0x04, 0x16, 0xe2, 0xaf, 0x04, -0x11, 0x62, 0xbf, 0x02, 0x50, 0x62, 0xcf, 0xdf, -0x22, 0x0e, 0x54, 0x0e, 0x88, 0x62, 0xdf, 0xbf, -0x03, 0x04, 0x53, 0x62, 0xaf + 0x42, 0xca, 0x00, + 0xc8, 0x20, 0xff, 0x00, 0xab, + 0x00, 0x72, 0x00, 0x4c, 0x00, 0x33, 0x00, 0x22, + 0x00, 0x09, 0x88, 0xbf, 0x9d, 0x05, 0x27, 0x09, + 0x27, 0x05, 0x88, 0xff, 0x97, 0x09, 0x27, 0xf6, + 0x9f, 0x5f, 0x02, 0xbf, 0x9d, 0x05, 0x27, 0x0f, + 0x1c, 0xc0, 0x9f, 0x8a, 0x80, 0x80, 0x10, 0x00, + 0x13, 0x0f, 0x1d, 0xc1, 0x03, 0x00, 0x5f, 0x7f, + 0x90, 0x05, 0x27, 0x53, 0x80, 0x2b, 0x0d, 0x05, + 0x27, 0x9f, 0x22, 0x8f, 0xaf, 0x67, 0x2e, 0xe0, + 0xdf, 0x04, 0x1e, 0x00, 0x52, 0x8f, 0x30, 0x67, + 0x2e, 0xe1, 0xdf, 0xdf, 0x22, 0x00, 0x54, 0x8f, + 0x30, 0x67, 0x2e, 0xfe, 0xdf, 0x04, 0x1e, 0x00, + 0x52, 0x8f, 0x31, 0x67, 0x2e, 0xff, 0xdf, 0xdf, + 0x22, 0x00, 0x54, 0x8f, 0x31, 0x8f, 0xcf, 0x03, + 0x1c, 0x03, 0x1e, 0x00, 0x55, 0x0c, 0x27, 0x0d, + 0x27, 0x4a, 0xcf, 0xdf, 0x96, 0x10, 0xcf, 0x5f, + 0xdf, 0xbf, 0x03, 0x02, 0x5f, 0x5f, 0xcf, 0x10, + 0xaf, 0x04, 0x50, 0x5e, 0xdf, 0xbf, 0x03, 0x01, + 0x53, 0x5e, 0xcf, 0x10, 0xaf, 0x46, 0x88, 0x01, + 0x2e, 0x1e, 0x80, 0xdd, 0x97, 0x0a, 0x40, 0x1c, + 0x5a, 0x37, 0x43, 0x0b, 0x5b, 0xe2, 0xcf, 0x0f, + 0x1c, 0x06, 0x1e, 0x07, 0x52, 0x62, 0xdf, 0x18, + 0x1f, 0x07, 0x53, 0x04, 0x16, 0xe2, 0xaf, 0x04, + 0x11, 0x62, 0xbf, 0x02, 0x50, 0x62, 0xcf, 0xdf, + 0x22, 0x0e, 0x54, 0x0e, 0x88, 0x62, 0xdf, 0xbf, + 0x03, 0x04, 0x53, 0x62, 0xaf }; static const unsigned char pkt120[] = { -0x42, 0xca, 0x00, -0x2c, 0x21, 0xdf, 0x01, 0xe2, -0xcf, 0x3f, 0x00, 0xe2, 0xaf, 0x0e, 0x88, 0x4a, -0xdf, 0x3f, 0x00, 0x4a, 0xaf, 0x00, 0x2e, 0xc4, -0x8d, 0x05, 0x27, 0xff, 0xef, 0x4a, 0xdf, 0xbf, -0x01, 0x0a, 0x88, 0xa1, 0x27, 0x5f, 0x21, 0x7f, -0x20, 0xfb, 0x55, 0x05, 0x27, 0x62, 0xcf, 0x03, -0x88, 0x1f, 0x22, 0x7f, 0x20, 0xfc, 0x55, 0x05, -0x27, 0x10, 0xdf, 0x02, 0x1f, 0x02, 0x5e, 0x04, -0xff, 0x00, 0x2e, 0x0a, 0x50, 0x05, 0x1f, 0x02, -0x5e, 0x03, 0xff, 0x00, 0x2e, 0x05, 0x50, 0x06, -0x1f, 0x02, 0x5e, 0x02, 0xff, 0x00, 0x2e, 0x00, -0x50, 0x01, 0xff, 0x05, 0x27, 0x10, 0xcf, 0x60, -0xff, 0x3f, 0x00, 0x21, 0xff, 0x00, 0x13, 0x1a, -0x27, 0x07, 0x27, 0x05, 0x27, 0x01, 0x00, 0x02, -0x57, 0x42, 0x87, 0x52, 0x80, 0x92, 0x81, 0xd2, -0x6c, 0xe2, 0x80, 0xf2, 0x80, 0xf6, 0x7b, 0xfa, -0x7e, 0xfe, 0x8b, 0xf9, 0x45, 0x04, 0x5a, 0x40, -0xef, 0xf9, 0x44, 0x03, 0x5b, 0x80, 0xef, 0x01, -0x50, 0x41, 0x2e, 0x7e, 0xdf, 0x4d, 0xaf, 0x05, -0x27, 0x28, 0xff, 0x54, 0xef, 0x19, 0x27, 0x4d, -0x26, 0xe0, 0x2f, 0xfb, 0x54, 0x27, 0xff, 0xe0, -0xef, 0x1b, 0x27, 0x10, 0xef, 0x06, 0xaf, 0xfc, -0x97, 0xfc, 0x9f, 0x1c, 0x82, 0x1c, 0x82, 0x1a, -0x27, 0x4d, 0xdf, 0x6d, 0x80, 0x5f, 0x9f, 0x06, -0x25, 0xf5, 0x55, 0x05, 0x27, 0x26, 0x1f, 0x00, -0x5f, 0xbf, 0x22, 0xff, 0x96 + 0x42, 0xca, 0x00, + 0x2c, 0x21, 0xdf, 0x01, 0xe2, + 0xcf, 0x3f, 0x00, 0xe2, 0xaf, 0x0e, 0x88, 0x4a, + 0xdf, 0x3f, 0x00, 0x4a, 0xaf, 0x00, 0x2e, 0xc4, + 0x8d, 0x05, 0x27, 0xff, 0xef, 0x4a, 0xdf, 0xbf, + 0x01, 0x0a, 0x88, 0xa1, 0x27, 0x5f, 0x21, 0x7f, + 0x20, 0xfb, 0x55, 0x05, 0x27, 0x62, 0xcf, 0x03, + 0x88, 0x1f, 0x22, 0x7f, 0x20, 0xfc, 0x55, 0x05, + 0x27, 0x10, 0xdf, 0x02, 0x1f, 0x02, 0x5e, 0x04, + 0xff, 0x00, 0x2e, 0x0a, 0x50, 0x05, 0x1f, 0x02, + 0x5e, 0x03, 0xff, 0x00, 0x2e, 0x05, 0x50, 0x06, + 0x1f, 0x02, 0x5e, 0x02, 0xff, 0x00, 0x2e, 0x00, + 0x50, 0x01, 0xff, 0x05, 0x27, 0x10, 0xcf, 0x60, + 0xff, 0x3f, 0x00, 0x21, 0xff, 0x00, 0x13, 0x1a, + 0x27, 0x07, 0x27, 0x05, 0x27, 0x01, 0x00, 0x02, + 0x57, 0x42, 0x87, 0x52, 0x80, 0x92, 0x81, 0xd2, + 0x6c, 0xe2, 0x80, 0xf2, 0x80, 0xf6, 0x7b, 0xfa, + 0x7e, 0xfe, 0x8b, 0xf9, 0x45, 0x04, 0x5a, 0x40, + 0xef, 0xf9, 0x44, 0x03, 0x5b, 0x80, 0xef, 0x01, + 0x50, 0x41, 0x2e, 0x7e, 0xdf, 0x4d, 0xaf, 0x05, + 0x27, 0x28, 0xff, 0x54, 0xef, 0x19, 0x27, 0x4d, + 0x26, 0xe0, 0x2f, 0xfb, 0x54, 0x27, 0xff, 0xe0, + 0xef, 0x1b, 0x27, 0x10, 0xef, 0x06, 0xaf, 0xfc, + 0x97, 0xfc, 0x9f, 0x1c, 0x82, 0x1c, 0x82, 0x1a, + 0x27, 0x4d, 0xdf, 0x6d, 0x80, 0x5f, 0x9f, 0x06, + 0x25, 0xf5, 0x55, 0x05, 0x27, 0x26, 0x1f, 0x00, + 0x5f, 0xbf, 0x22, 0xff, 0x96 }; static const unsigned char pkt124[] = { -0x42, 0xac, 0x00, -0x90, 0x21, 0x99, 0xef, 0x21, -0xff, 0x1d, 0x00, 0x00, 0x13, 0x1a, 0x27, 0x07, -0x27, 0x1a, 0x27, 0xd6, 0x97, 0x05, 0x27, 0xa3, -0x01, 0xa4, 0x01, 0xa3, 0x01, 0x2e, 0x00, 0xb0, -0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb4, -0x00, 0xb5, 0x00, 0xb6, 0x00, 0xb7, 0x00, 0xb8, -0x00, 0xb9, 0x00, 0xba, 0x00, 0x56, 0x00, 0xae, -0x00, 0x54, 0x01, 0x44, 0x01, 0x55, 0x01, 0x44, -0x01, 0xbb, 0x00, 0xbc, 0x00, 0xbd, 0x00, 0xbe, -0x00, 0x83, 0x00, 0x84, 0x00, 0x81, 0x00, 0x82, -0x00, 0x24, 0x00, 0x44, 0x01, 0xdb, 0x00, 0xdc, -0x00, 0xdd, 0x00, 0xde, 0x00, 0x04, 0x00, 0x9b, -0x00, 0x99, 0x00, 0x9e, 0x00, 0x10, 0xef, 0xe6, -0x81, 0x65, 0xaf, 0x10, 0xef, 0xe6, 0x81, 0x9c, -0xaf, 0x10, 0xef, 0xe6, 0x81, 0x9a, 0xaf, 0x05, -0x27, 0xe5, 0x31, 0x1d, 0x81, 0xe5, 0x39, 0x05, -0x27, 0xc8, 0x46, 0x0b, 0x5b, 0xd3, 0x45, 0xfd, -0x5a, 0xd3, 0x45, 0xfb, 0x5a, 0xd3, 0x45, 0xf9, -0x5a, 0x41, 0x2e, 0xa1, 0xdf, 0x9f, 0x28, 0x41, -0x2e, 0xa1, 0xbf, 0x00, 0x88, 0x05, 0x27, 0x9f, -0x22, 0xbf, 0x22, 0x1f, 0x20, 0xfd, 0x53, 0x3f, -0x20, 0x14, 0x1f, 0xfa, 0x55, 0x05, 0x27 + 0x42, 0xac, 0x00, + 0x90, 0x21, 0x99, 0xef, 0x21, + 0xff, 0x1d, 0x00, 0x00, 0x13, 0x1a, 0x27, 0x07, + 0x27, 0x1a, 0x27, 0xd6, 0x97, 0x05, 0x27, 0xa3, + 0x01, 0xa4, 0x01, 0xa3, 0x01, 0x2e, 0x00, 0xb0, + 0x00, 0xb1, 0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb4, + 0x00, 0xb5, 0x00, 0xb6, 0x00, 0xb7, 0x00, 0xb8, + 0x00, 0xb9, 0x00, 0xba, 0x00, 0x56, 0x00, 0xae, + 0x00, 0x54, 0x01, 0x44, 0x01, 0x55, 0x01, 0x44, + 0x01, 0xbb, 0x00, 0xbc, 0x00, 0xbd, 0x00, 0xbe, + 0x00, 0x83, 0x00, 0x84, 0x00, 0x81, 0x00, 0x82, + 0x00, 0x24, 0x00, 0x44, 0x01, 0xdb, 0x00, 0xdc, + 0x00, 0xdd, 0x00, 0xde, 0x00, 0x04, 0x00, 0x9b, + 0x00, 0x99, 0x00, 0x9e, 0x00, 0x10, 0xef, 0xe6, + 0x81, 0x65, 0xaf, 0x10, 0xef, 0xe6, 0x81, 0x9c, + 0xaf, 0x10, 0xef, 0xe6, 0x81, 0x9a, 0xaf, 0x05, + 0x27, 0xe5, 0x31, 0x1d, 0x81, 0xe5, 0x39, 0x05, + 0x27, 0xc8, 0x46, 0x0b, 0x5b, 0xd3, 0x45, 0xfd, + 0x5a, 0xd3, 0x45, 0xfb, 0x5a, 0xd3, 0x45, 0xf9, + 0x5a, 0x41, 0x2e, 0xa1, 0xdf, 0x9f, 0x28, 0x41, + 0x2e, 0xa1, 0xbf, 0x00, 0x88, 0x05, 0x27, 0x9f, + 0x22, 0xbf, 0x22, 0x1f, 0x20, 0xfd, 0x53, 0x3f, + 0x20, 0x14, 0x1f, 0xfa, 0x55, 0x05, 0x27 }; static const unsigned char pkt128[] = { -0x42, 0xca, 0x00, -0xe5, 0x21, 0x25, 0x85, 0x01, -0x1e, 0x17, 0x55, 0xdc, 0x8a, 0x41, 0x2e, 0x53, -0xdf, 0xc1, 0x2e, 0x79, 0xdf, 0xff, 0x96, 0xdf, -0x96, 0x41, 0x2e, 0x55, 0xdf, 0xc1, 0x2e, 0x78, -0xdf, 0x9d, 0x01, 0x5d, 0x01, 0xff, 0x22, 0x00, -0x54, 0xff, 0xef, 0x2e, 0xaf, 0x05, 0x27, 0x07, -0x80, 0x9f, 0x22, 0xff, 0xaf, 0x00, 0x2e, 0x5d, -0x89, 0x05, 0x27, 0x03, 0x1e, 0x3c, 0x55, 0xaf, -0x8a, 0xa1, 0xcf, 0xfe, 0x1c, 0xa1, 0xaf, 0x05, -0x81, 0x47, 0x81, 0x76, 0x88, 0xff, 0x96, 0xdf, -0x96, 0xa1, 0xcf, 0x01, 0x18, 0xa1, 0xaf, 0x05, -0x81, 0x64, 0xef, 0xbf, 0x22, 0xbd, 0x80, 0x47, -0x81, 0x6b, 0x88, 0xff, 0x96, 0xdf, 0x96, 0x9b, -0x22, 0x14, 0x1e, 0x03, 0x53, 0xff, 0x22, 0x01, -0x55, 0x00, 0x20, 0x0a, 0x50, 0xc3, 0x97, 0xc4, -0x9f, 0x81, 0x01, 0x42, 0x01, 0x03, 0x52, 0xfa, -0x1e, 0x03, 0x53, 0xff, 0x22, 0x01, 0x55, 0x00, -0x20, 0xf2, 0x50, 0x00, 0x2e, 0xf0, 0x8b, 0x03, -0xcf, 0x7f, 0x1c, 0xff, 0xaf, 0x05, 0xef, 0xff, -0xaf, 0x00, 0xef, 0xff, 0xaf, 0xdd, 0x97, 0xff, -0xaf, 0xc2, 0x97, 0xff, 0xaf, 0xc3, 0x97, 0xff, -0xaf, 0xc0, 0x97, 0xff, 0xaf, 0xc1, 0x97, 0xff, -0xaf, 0x04, 0x0c, 0x00, 0x2e, 0x5d, 0x89, 0x05, -0x27, 0x06, 0x1e, 0x00, 0x55, 0x0f, 0x27, 0x0a, -0x1e, 0x07, 0x55, 0x00, 0x88, 0x66, 0x76, 0x3b, -0x30, 0x07, 0x35, 0xff, 0xff + 0x42, 0xca, 0x00, + 0xe5, 0x21, 0x25, 0x85, 0x01, + 0x1e, 0x17, 0x55, 0xdc, 0x8a, 0x41, 0x2e, 0x53, + 0xdf, 0xc1, 0x2e, 0x79, 0xdf, 0xff, 0x96, 0xdf, + 0x96, 0x41, 0x2e, 0x55, 0xdf, 0xc1, 0x2e, 0x78, + 0xdf, 0x9d, 0x01, 0x5d, 0x01, 0xff, 0x22, 0x00, + 0x54, 0xff, 0xef, 0x2e, 0xaf, 0x05, 0x27, 0x07, + 0x80, 0x9f, 0x22, 0xff, 0xaf, 0x00, 0x2e, 0x5d, + 0x89, 0x05, 0x27, 0x03, 0x1e, 0x3c, 0x55, 0xaf, + 0x8a, 0xa1, 0xcf, 0xfe, 0x1c, 0xa1, 0xaf, 0x05, + 0x81, 0x47, 0x81, 0x76, 0x88, 0xff, 0x96, 0xdf, + 0x96, 0xa1, 0xcf, 0x01, 0x18, 0xa1, 0xaf, 0x05, + 0x81, 0x64, 0xef, 0xbf, 0x22, 0xbd, 0x80, 0x47, + 0x81, 0x6b, 0x88, 0xff, 0x96, 0xdf, 0x96, 0x9b, + 0x22, 0x14, 0x1e, 0x03, 0x53, 0xff, 0x22, 0x01, + 0x55, 0x00, 0x20, 0x0a, 0x50, 0xc3, 0x97, 0xc4, + 0x9f, 0x81, 0x01, 0x42, 0x01, 0x03, 0x52, 0xfa, + 0x1e, 0x03, 0x53, 0xff, 0x22, 0x01, 0x55, 0x00, + 0x20, 0xf2, 0x50, 0x00, 0x2e, 0xf0, 0x8b, 0x03, + 0xcf, 0x7f, 0x1c, 0xff, 0xaf, 0x05, 0xef, 0xff, + 0xaf, 0x00, 0xef, 0xff, 0xaf, 0xdd, 0x97, 0xff, + 0xaf, 0xc2, 0x97, 0xff, 0xaf, 0xc3, 0x97, 0xff, + 0xaf, 0xc0, 0x97, 0xff, 0xaf, 0xc1, 0x97, 0xff, + 0xaf, 0x04, 0x0c, 0x00, 0x2e, 0x5d, 0x89, 0x05, + 0x27, 0x06, 0x1e, 0x00, 0x55, 0x0f, 0x27, 0x0a, + 0x1e, 0x07, 0x55, 0x00, 0x88, 0x66, 0x76, 0x3b, + 0x30, 0x07, 0x35, 0xff, 0xff }; static const unsigned char pkt133[] = { -0x42, 0xc2, 0x00, -0x49, 0x22, 0xc2, 0xbf, 0x0d, -0x27, 0x0c, 0x27, 0x0d, 0x1e, 0x02, 0x55, 0x28, -0x85, 0xf5, 0x5b, 0x7b, 0x76, 0x12, 0x1e, 0x07, -0x55, 0xdc, 0xef, 0x05, 0xff, 0x1a, 0x27, 0x56, -0xdf, 0x3f, 0x20, 0x6d, 0x80, 0x3c, 0xaf, 0x05, -0x27, 0x13, 0x1e, 0x01, 0x55, 0x3c, 0x23, 0x05, -0x27, 0x23, 0x1e, 0x0c, 0x55, 0x00, 0xef, 0x02, -0xff, 0x19, 0x27, 0xbf, 0x22, 0x20, 0xef, 0x7f, -0x9f, 0x5f, 0x20, 0xfc, 0x55, 0xf0, 0x81, 0x9f, -0x22, 0x41, 0x2e, 0xa3, 0xbf, 0x05, 0x27, 0x30, -0x1e, 0x0e, 0x55, 0x7e, 0xef, 0xff, 0xaf, 0x02, -0xef, 0xff, 0xaf, 0x00, 0xef, 0xff, 0xaf, 0xff, -0xef, 0x17, 0xff, 0x1a, 0x27, 0x07, 0x27, 0xff, -0xaf, 0xff, 0xbf, 0x00, 0x2e, 0x5d, 0x89, 0x05, -0x27, 0xcb, 0x74, 0xc9, 0xcf, 0xf3, 0x1c, 0x04, -0x18, 0xc9, 0xaf, 0x39, 0x81, 0x10, 0xff, 0xff, -0xef, 0xc1, 0x2e, 0x7c, 0xbf, 0x41, 0x2e, 0x7b, -0xbf, 0x02, 0xef, 0x41, 0x2e, 0x7a, 0xbf, 0xc9, -0x31, 0x18, 0xef, 0xc0, 0xaf, 0x04, 0x27, 0x41, -0x2e, 0x7a, 0xdf, 0xdf, 0x2d, 0x08, 0x5b, 0x01, -0xef, 0x41, 0x2e, 0x7a, 0xbf, 0xc0, 0x23, 0x18, -0xef, 0xc1, 0xaf, 0xcb, 0xcf, 0xcc, 0xdf, 0x05, -0x27, 0xc9, 0x30, 0x01, 0xef, 0x41, 0x2e, 0x7a, -0xbf, 0xc0, 0x23, 0x18, 0xef, 0xc1, 0xaf, 0x9f, -0x22, 0xbf, 0x22, 0x05, 0x27 + 0x42, 0xc2, 0x00, + 0x49, 0x22, 0xc2, 0xbf, 0x0d, + 0x27, 0x0c, 0x27, 0x0d, 0x1e, 0x02, 0x55, 0x28, + 0x85, 0xf5, 0x5b, 0x7b, 0x76, 0x12, 0x1e, 0x07, + 0x55, 0xdc, 0xef, 0x05, 0xff, 0x1a, 0x27, 0x56, + 0xdf, 0x3f, 0x20, 0x6d, 0x80, 0x3c, 0xaf, 0x05, + 0x27, 0x13, 0x1e, 0x01, 0x55, 0x3c, 0x23, 0x05, + 0x27, 0x23, 0x1e, 0x0c, 0x55, 0x00, 0xef, 0x02, + 0xff, 0x19, 0x27, 0xbf, 0x22, 0x20, 0xef, 0x7f, + 0x9f, 0x5f, 0x20, 0xfc, 0x55, 0xf0, 0x81, 0x9f, + 0x22, 0x41, 0x2e, 0xa3, 0xbf, 0x05, 0x27, 0x30, + 0x1e, 0x0e, 0x55, 0x7e, 0xef, 0xff, 0xaf, 0x02, + 0xef, 0xff, 0xaf, 0x00, 0xef, 0xff, 0xaf, 0xff, + 0xef, 0x17, 0xff, 0x1a, 0x27, 0x07, 0x27, 0xff, + 0xaf, 0xff, 0xbf, 0x00, 0x2e, 0x5d, 0x89, 0x05, + 0x27, 0xcb, 0x74, 0xc9, 0xcf, 0xf3, 0x1c, 0x04, + 0x18, 0xc9, 0xaf, 0x39, 0x81, 0x10, 0xff, 0xff, + 0xef, 0xc1, 0x2e, 0x7c, 0xbf, 0x41, 0x2e, 0x7b, + 0xbf, 0x02, 0xef, 0x41, 0x2e, 0x7a, 0xbf, 0xc9, + 0x31, 0x18, 0xef, 0xc0, 0xaf, 0x04, 0x27, 0x41, + 0x2e, 0x7a, 0xdf, 0xdf, 0x2d, 0x08, 0x5b, 0x01, + 0xef, 0x41, 0x2e, 0x7a, 0xbf, 0xc0, 0x23, 0x18, + 0xef, 0xc1, 0xaf, 0xcb, 0xcf, 0xcc, 0xdf, 0x05, + 0x27, 0xc9, 0x30, 0x01, 0xef, 0x41, 0x2e, 0x7a, + 0xbf, 0xc0, 0x23, 0x18, 0xef, 0xc1, 0xaf, 0x9f, + 0x22, 0xbf, 0x22, 0x05, 0x27 }; static const unsigned char pkt136[] = { -0x42, 0xca, 0x00, -0xa9, 0x22, 0x25, 0x85, 0x44, -0x1e, 0x01, 0x55, 0xe2, 0x2f, 0x7d, 0x50, 0x49, -0x1e, 0x02, 0x55, 0xe2, 0x2f, 0x79, 0x50, 0x05, -0x27, 0x4a, 0x1e, 0x01, 0x55, 0xe2, 0x2f, 0x74, -0x50, 0x4e, 0x1e, 0x01, 0x55, 0x00, 0x2e, 0xbb, -0x79, 0x4f, 0x1e, 0x00, 0x55, 0x7d, 0x78, 0x55, -0x1e, 0x00, 0x55, 0x05, 0x27, 0x58, 0x1e, 0x0d, -0x55, 0x02, 0x44, 0x01, 0x5a, 0x00, 0x2e, 0x07, -0x78, 0xfe, 0xcf, 0x75, 0xaf, 0xfe, 0xdf, 0x76, -0xbf, 0x41, 0x2e, 0xa4, 0xdf, 0xdf, 0x29, 0x41, -0x2e, 0xa4, 0xbf, 0x05, 0x27, 0x59, 0x1e, 0x02, -0x55, 0xfe, 0xcf, 0x10, 0xaf, 0x2b, 0x7e, 0x63, -0x1e, 0x1a, 0x55, 0x28, 0x85, 0xe2, 0x2f, 0x50, -0x5b, 0x0c, 0xef, 0x20, 0x80, 0xe2, 0x2f, 0x4c, -0x5a, 0xf0, 0xef, 0x00, 0xff, 0x19, 0x27, 0x08, -0xef, 0x06, 0xaf, 0xfe, 0xcf, 0x5f, 0x9f, 0x06, -0x25, 0xfb, 0x55, 0xfe, 0xcf, 0xfe, 0xcf, 0x41, -0x2e, 0x40, 0xbf, 0xfe, 0xcf, 0x41, 0x2e, 0x41, -0xbf, 0xfe, 0xcf, 0x41, 0x2e, 0x42, 0xbf, 0x05, -0x27, 0x64, 0x1e, 0x31, 0x55, 0xb0, 0xef, 0x00, -0xff, 0x19, 0x27, 0x0b, 0xef, 0x06, 0xaf, 0xfe, -0xcf, 0x5f, 0x9f, 0x06, 0x25, 0xfb, 0x55, 0xfe, -0xcf, 0x56, 0xaf, 0xfe, 0xcf, 0xae, 0xdf, 0x1f, -0x1c, 0xe0, 0x1d, 0x5f, 0x02, 0xae, 0xbf, 0xfe, -0xcf, 0x41, 0x2e, 0x54, 0xbf, 0xfe, 0xcf, 0x41, -0x2e, 0x77, 0xbf, 0xfe, 0xcf + 0x42, 0xca, 0x00, + 0xa9, 0x22, 0x25, 0x85, 0x44, + 0x1e, 0x01, 0x55, 0xe2, 0x2f, 0x7d, 0x50, 0x49, + 0x1e, 0x02, 0x55, 0xe2, 0x2f, 0x79, 0x50, 0x05, + 0x27, 0x4a, 0x1e, 0x01, 0x55, 0xe2, 0x2f, 0x74, + 0x50, 0x4e, 0x1e, 0x01, 0x55, 0x00, 0x2e, 0xbb, + 0x79, 0x4f, 0x1e, 0x00, 0x55, 0x7d, 0x78, 0x55, + 0x1e, 0x00, 0x55, 0x05, 0x27, 0x58, 0x1e, 0x0d, + 0x55, 0x02, 0x44, 0x01, 0x5a, 0x00, 0x2e, 0x07, + 0x78, 0xfe, 0xcf, 0x75, 0xaf, 0xfe, 0xdf, 0x76, + 0xbf, 0x41, 0x2e, 0xa4, 0xdf, 0xdf, 0x29, 0x41, + 0x2e, 0xa4, 0xbf, 0x05, 0x27, 0x59, 0x1e, 0x02, + 0x55, 0xfe, 0xcf, 0x10, 0xaf, 0x2b, 0x7e, 0x63, + 0x1e, 0x1a, 0x55, 0x28, 0x85, 0xe2, 0x2f, 0x50, + 0x5b, 0x0c, 0xef, 0x20, 0x80, 0xe2, 0x2f, 0x4c, + 0x5a, 0xf0, 0xef, 0x00, 0xff, 0x19, 0x27, 0x08, + 0xef, 0x06, 0xaf, 0xfe, 0xcf, 0x5f, 0x9f, 0x06, + 0x25, 0xfb, 0x55, 0xfe, 0xcf, 0xfe, 0xcf, 0x41, + 0x2e, 0x40, 0xbf, 0xfe, 0xcf, 0x41, 0x2e, 0x41, + 0xbf, 0xfe, 0xcf, 0x41, 0x2e, 0x42, 0xbf, 0x05, + 0x27, 0x64, 0x1e, 0x31, 0x55, 0xb0, 0xef, 0x00, + 0xff, 0x19, 0x27, 0x0b, 0xef, 0x06, 0xaf, 0xfe, + 0xcf, 0x5f, 0x9f, 0x06, 0x25, 0xfb, 0x55, 0xfe, + 0xcf, 0x56, 0xaf, 0xfe, 0xcf, 0xae, 0xdf, 0x1f, + 0x1c, 0xe0, 0x1d, 0x5f, 0x02, 0xae, 0xbf, 0xfe, + 0xcf, 0x41, 0x2e, 0x54, 0xbf, 0xfe, 0xcf, 0x41, + 0x2e, 0x77, 0xbf, 0xfe, 0xcf }; static const unsigned char pkt140[] = { -0x42, 0xca, 0x00, -0x0d, 0x23, 0x41, 0x2e, 0x55, -0xbf, 0xfe, 0xcf, 0x41, 0x2e, 0x78, 0xbf, 0xfe, -0xcf, 0xbb, 0xaf, 0xfe, 0xcf, 0xbc, 0xaf, 0xfe, -0xcf, 0xbd, 0xaf, 0xfe, 0xcf, 0xbe, 0xaf, 0xfe, -0xcf, 0x83, 0xaf, 0xfe, 0xcf, 0x84, 0xaf, 0xfe, -0xcf, 0x81, 0xaf, 0xfe, 0xcf, 0x82, 0xaf, 0xfe, -0xcf, 0x24, 0xaf, 0xfe, 0xcf, 0x02, 0x33, 0x05, -0x27, 0x66, 0x1e, 0x0b, 0x55, 0x60, 0xef, 0x21, -0xff, 0x1a, 0x27, 0x0b, 0xef, 0x06, 0xaf, 0xfe, -0xcf, 0xfe, 0xdf, 0x06, 0x27, 0x01, 0x0e, 0x06, -0x25, 0xf9, 0x55, 0x05, 0x27, 0x35, 0x74, 0xff, -0x96, 0xc6, 0x2e, 0x01, 0xdf, 0x3f, 0x2c, 0xdd, -0x9f, 0x05, 0x27, 0x01, 0xef, 0x20, 0x80, 0xe1, -0x2f, 0xeb, 0x5a, 0xfe, 0xcf, 0xdf, 0x22, 0xe7, -0x2f, 0x1e, 0x54, 0x01, 0xff, 0x05, 0xef, 0xff, -0x96, 0xdf, 0x96, 0x2d, 0xff, 0x8d, 0xef, 0x19, -0x27, 0x03, 0xcf, 0x7f, 0x1c, 0x5f, 0x9f, 0xdd, -0x97, 0x5f, 0x9f, 0xdd, 0x97, 0x5f, 0x9f, 0x05, -0xef, 0x06, 0xaf, 0x9f, 0x22, 0x5f, 0x9f, 0x06, -0x25, 0xfc, 0x55, 0x5f, 0x9f, 0x06, 0x25, 0xfc, -0x55, 0x20, 0xef, 0x08, 0xaf, 0x09, 0x23, 0x00, -0x2e, 0xd1, 0x8d, 0x67, 0x81, 0x03, 0xef, 0xfc, -0xaf, 0x86, 0xef, 0xaa, 0xaf, 0x08, 0xef, 0xe3, -0xaf, 0x9f, 0x22, 0xe2, 0xaf, 0x21, 0xef, 0x41, -0x2e, 0x47, 0xbf, 0x27, 0xef, 0xf4, 0xaf, 0x28, -0xff, 0xa7, 0xef, 0xe1, 0xbf + 0x42, 0xca, 0x00, + 0x0d, 0x23, 0x41, 0x2e, 0x55, + 0xbf, 0xfe, 0xcf, 0x41, 0x2e, 0x78, 0xbf, 0xfe, + 0xcf, 0xbb, 0xaf, 0xfe, 0xcf, 0xbc, 0xaf, 0xfe, + 0xcf, 0xbd, 0xaf, 0xfe, 0xcf, 0xbe, 0xaf, 0xfe, + 0xcf, 0x83, 0xaf, 0xfe, 0xcf, 0x84, 0xaf, 0xfe, + 0xcf, 0x81, 0xaf, 0xfe, 0xcf, 0x82, 0xaf, 0xfe, + 0xcf, 0x24, 0xaf, 0xfe, 0xcf, 0x02, 0x33, 0x05, + 0x27, 0x66, 0x1e, 0x0b, 0x55, 0x60, 0xef, 0x21, + 0xff, 0x1a, 0x27, 0x0b, 0xef, 0x06, 0xaf, 0xfe, + 0xcf, 0xfe, 0xdf, 0x06, 0x27, 0x01, 0x0e, 0x06, + 0x25, 0xf9, 0x55, 0x05, 0x27, 0x35, 0x74, 0xff, + 0x96, 0xc6, 0x2e, 0x01, 0xdf, 0x3f, 0x2c, 0xdd, + 0x9f, 0x05, 0x27, 0x01, 0xef, 0x20, 0x80, 0xe1, + 0x2f, 0xeb, 0x5a, 0xfe, 0xcf, 0xdf, 0x22, 0xe7, + 0x2f, 0x1e, 0x54, 0x01, 0xff, 0x05, 0xef, 0xff, + 0x96, 0xdf, 0x96, 0x2d, 0xff, 0x8d, 0xef, 0x19, + 0x27, 0x03, 0xcf, 0x7f, 0x1c, 0x5f, 0x9f, 0xdd, + 0x97, 0x5f, 0x9f, 0xdd, 0x97, 0x5f, 0x9f, 0x05, + 0xef, 0x06, 0xaf, 0x9f, 0x22, 0x5f, 0x9f, 0x06, + 0x25, 0xfc, 0x55, 0x5f, 0x9f, 0x06, 0x25, 0xfc, + 0x55, 0x20, 0xef, 0x08, 0xaf, 0x09, 0x23, 0x00, + 0x2e, 0xd1, 0x8d, 0x67, 0x81, 0x03, 0xef, 0xfc, + 0xaf, 0x86, 0xef, 0xaa, 0xaf, 0x08, 0xef, 0xe3, + 0xaf, 0x9f, 0x22, 0xe2, 0xaf, 0x21, 0xef, 0x41, + 0x2e, 0x47, 0xbf, 0x27, 0xef, 0xf4, 0xaf, 0x28, + 0xff, 0xa7, 0xef, 0xe1, 0xbf }; static const unsigned char pkt144[] = { -0x42, 0x88, 0x00, -0x71, 0x23, 0xe0, 0xaf, 0x08, -0xef, 0x10, 0xaf, 0x8c, 0x8d, 0x05, 0x81, 0x01, -0x2e, 0x54, 0x80, 0x01, 0x2e, 0x56, 0x80, 0x9b, -0x22, 0x9b, 0x22, 0x2d, 0xff, 0x95, 0xef, 0x19, -0x27, 0x28, 0xff, 0xa7, 0xef, 0x1a, 0x27, 0x80, -0xef, 0x06, 0xaf, 0xdc, 0x97, 0x5f, 0x9f, 0xdf, -0x22, 0x01, 0x54, 0x00, 0x2e, 0x66, 0x8a, 0x06, -0x25, 0xf7, 0x55, 0x2d, 0xff, 0x91, 0xef, 0x19, -0x27, 0xdd, 0x97, 0xdd, 0x9f, 0x5f, 0x9f, 0x7f, -0x9f, 0xfd, 0x0d, 0xdf, 0x22, 0x01, 0x55, 0xff, -0x22, 0x01, 0x54, 0x01, 0xef, 0x1f, 0x98, 0x2f, -0xef, 0x41, 0x2e, 0x47, 0xbf, 0x11, 0xef, 0xf4, -0xaf, 0x28, 0xff, 0xa7, 0xef, 0xe1, 0xbf, 0xe0, -0xaf, 0x01, 0x2e, 0x54, 0x80, 0x01, 0x2e, 0x56, -0x80, 0x9b, 0x22, 0x9b, 0x22, 0x2e, 0xff, 0x15, -0xef, 0x19, 0x27, 0x28, 0xff, 0xa7, 0xef, 0x1a, -0x27, 0x80, 0xef, 0x06, 0xaf, 0x00, 0x2e, 0x3c, -0x8a, 0x05, 0x27 + 0x42, 0x88, 0x00, + 0x71, 0x23, 0xe0, 0xaf, 0x08, + 0xef, 0x10, 0xaf, 0x8c, 0x8d, 0x05, 0x81, 0x01, + 0x2e, 0x54, 0x80, 0x01, 0x2e, 0x56, 0x80, 0x9b, + 0x22, 0x9b, 0x22, 0x2d, 0xff, 0x95, 0xef, 0x19, + 0x27, 0x28, 0xff, 0xa7, 0xef, 0x1a, 0x27, 0x80, + 0xef, 0x06, 0xaf, 0xdc, 0x97, 0x5f, 0x9f, 0xdf, + 0x22, 0x01, 0x54, 0x00, 0x2e, 0x66, 0x8a, 0x06, + 0x25, 0xf7, 0x55, 0x2d, 0xff, 0x91, 0xef, 0x19, + 0x27, 0xdd, 0x97, 0xdd, 0x9f, 0x5f, 0x9f, 0x7f, + 0x9f, 0xfd, 0x0d, 0xdf, 0x22, 0x01, 0x55, 0xff, + 0x22, 0x01, 0x54, 0x01, 0xef, 0x1f, 0x98, 0x2f, + 0xef, 0x41, 0x2e, 0x47, 0xbf, 0x11, 0xef, 0xf4, + 0xaf, 0x28, 0xff, 0xa7, 0xef, 0xe1, 0xbf, 0xe0, + 0xaf, 0x01, 0x2e, 0x54, 0x80, 0x01, 0x2e, 0x56, + 0x80, 0x9b, 0x22, 0x9b, 0x22, 0x2e, 0xff, 0x15, + 0xef, 0x19, 0x27, 0x28, 0xff, 0xa7, 0xef, 0x1a, + 0x27, 0x80, 0xef, 0x06, 0xaf, 0x00, 0x2e, 0x3c, + 0x8a, 0x05, 0x27 }; static const unsigned char pkt148[] = { -0x42, 0xca, 0x00, -0xb4, 0x23, 0x37, 0xcf, 0xdf, -0x96, 0x08, 0xcf, 0xdf, 0x96, 0x3d, 0xcf, 0xdf, -0x96, 0x00, 0x2e, 0xd4, 0x8d, 0xdd, 0x97, 0x3d, -0xaf, 0xdd, 0x97, 0x08, 0xaf, 0xdd, 0x97, 0x37, -0xaf, 0x03, 0xcf, 0x51, 0x1e, 0x00, 0x55, 0x44, -0x8b, 0xa0, 0xcf, 0xbf, 0x1c, 0xa0, 0xaf, 0x05, -0x81, 0xfb, 0x39, 0x08, 0x45, 0x00, 0x5a, 0xfb, -0x31, 0x0a, 0x42, 0x00, 0x5b, 0xa2, 0x39, 0x02, -0xcf, 0x5c, 0xaf, 0xe1, 0xef, 0x40, 0x2e, 0x95, -0xbf, 0x9f, 0x22, 0x25, 0xaf, 0x69, 0xaf, 0x6a, -0xaf, 0x16, 0xaf, 0x40, 0x2e, 0x96, 0xbf, 0x29, -0xaf, 0x02, 0x47, 0x06, 0x5a, 0x0a, 0x41, 0x04, -0x5a, 0x0a, 0xdf, 0x30, 0x1d, 0x30, 0x1f, 0x00, -0x54, 0x01, 0xef, 0x44, 0xaf, 0x09, 0xef, 0x60, -0xaf, 0x0a, 0x40, 0x06, 0x5a, 0x10, 0xcf, 0x27, -0xaf, 0xe2, 0x23, 0x6e, 0x23, 0x08, 0xef, 0xe3, -0xaf, 0x6f, 0xaf, 0x0d, 0x8d, 0x5d, 0xcf, 0x30, -0x1c, 0x00, 0x1e, 0x07, 0x55, 0xf8, 0xcf, 0x5f, -0x2b, 0x9f, 0x29, 0xf8, 0xaf, 0xa1, 0xcf, 0xc1, -0x1c, 0xa1, 0xaf, 0x09, 0x50, 0x10, 0x1e, 0x07, -0x55, 0xf8, 0xcf, 0x5f, 0x29, 0x9f, 0x2b, 0xf8, -0xaf, 0xa1, 0xcf, 0xc1, 0x1c, 0x08, 0x18, 0xa1, -0xaf, 0x41, 0x2e, 0xa4, 0xdf, 0xdf, 0x2d, 0x04, -0x5b, 0x75, 0xcf, 0xf4, 0xaf, 0x76, 0xcf, 0xf5, -0xaf, 0x00, 0x50, 0x0f, 0x88, 0xe2, 0x23, 0x08, -0xef, 0xe3, 0xaf, 0x81, 0x82 + 0x42, 0xca, 0x00, + 0xb4, 0x23, 0x37, 0xcf, 0xdf, + 0x96, 0x08, 0xcf, 0xdf, 0x96, 0x3d, 0xcf, 0xdf, + 0x96, 0x00, 0x2e, 0xd4, 0x8d, 0xdd, 0x97, 0x3d, + 0xaf, 0xdd, 0x97, 0x08, 0xaf, 0xdd, 0x97, 0x37, + 0xaf, 0x03, 0xcf, 0x51, 0x1e, 0x00, 0x55, 0x44, + 0x8b, 0xa0, 0xcf, 0xbf, 0x1c, 0xa0, 0xaf, 0x05, + 0x81, 0xfb, 0x39, 0x08, 0x45, 0x00, 0x5a, 0xfb, + 0x31, 0x0a, 0x42, 0x00, 0x5b, 0xa2, 0x39, 0x02, + 0xcf, 0x5c, 0xaf, 0xe1, 0xef, 0x40, 0x2e, 0x95, + 0xbf, 0x9f, 0x22, 0x25, 0xaf, 0x69, 0xaf, 0x6a, + 0xaf, 0x16, 0xaf, 0x40, 0x2e, 0x96, 0xbf, 0x29, + 0xaf, 0x02, 0x47, 0x06, 0x5a, 0x0a, 0x41, 0x04, + 0x5a, 0x0a, 0xdf, 0x30, 0x1d, 0x30, 0x1f, 0x00, + 0x54, 0x01, 0xef, 0x44, 0xaf, 0x09, 0xef, 0x60, + 0xaf, 0x0a, 0x40, 0x06, 0x5a, 0x10, 0xcf, 0x27, + 0xaf, 0xe2, 0x23, 0x6e, 0x23, 0x08, 0xef, 0xe3, + 0xaf, 0x6f, 0xaf, 0x0d, 0x8d, 0x5d, 0xcf, 0x30, + 0x1c, 0x00, 0x1e, 0x07, 0x55, 0xf8, 0xcf, 0x5f, + 0x2b, 0x9f, 0x29, 0xf8, 0xaf, 0xa1, 0xcf, 0xc1, + 0x1c, 0xa1, 0xaf, 0x09, 0x50, 0x10, 0x1e, 0x07, + 0x55, 0xf8, 0xcf, 0x5f, 0x29, 0x9f, 0x2b, 0xf8, + 0xaf, 0xa1, 0xcf, 0xc1, 0x1c, 0x08, 0x18, 0xa1, + 0xaf, 0x41, 0x2e, 0xa4, 0xdf, 0xdf, 0x2d, 0x04, + 0x5b, 0x75, 0xcf, 0xf4, 0xaf, 0x76, 0xcf, 0xf5, + 0xaf, 0x00, 0x50, 0x0f, 0x88, 0xe2, 0x23, 0x08, + 0xef, 0xe3, 0xaf, 0x81, 0x82 }; static const unsigned char pkt152[] = { -0x42, 0x24, 0x00, -0x18, 0x24, 0x4d, 0xaf, 0xdf, -0x96, 0x64, 0xdf, 0x93, 0x82, 0x93, 0xbf, 0xdd, -0x97, 0x77, 0xff, 0x93, 0x82, 0x94, 0xbf, 0x9e, -0x23, 0xe4, 0x23, 0x05, 0x27, 0x14, 0xef, 0xf4, -0xaf, 0x00, 0xef, 0xf5, 0xaf, 0x05, 0x27 + 0x42, 0x24, 0x00, + 0x18, 0x24, 0x4d, 0xaf, 0xdf, + 0x96, 0x64, 0xdf, 0x93, 0x82, 0x93, 0xbf, 0xdd, + 0x97, 0x77, 0xff, 0x93, 0x82, 0x94, 0xbf, 0x9e, + 0x23, 0xe4, 0x23, 0x05, 0x27, 0x14, 0xef, 0xf4, + 0xaf, 0x00, 0xef, 0xf5, 0xaf, 0x05, 0x27 }; static const unsigned char pkt156[] = { -0x42, 0xca, 0x00, -0x29, 0x24, 0xfe, 0xcf, 0x58, -0xaf, 0xfe, 0xcf, 0xfe, 0xdf, 0x00, 0x2e, 0xa9, -0x8b, 0xfe, 0xcf, 0x3c, 0xaf, 0x07, 0x3d, 0x58, -0x40, 0x4a, 0x5a, 0x3c, 0x26, 0x48, 0x55, 0x37, -0x45, 0x46, 0x5a, 0xe0, 0x88, 0x44, 0x5a, 0x77, -0x88, 0x00, 0x2e, 0xd1, 0x8b, 0xfe, 0xef, 0x16, -0x80, 0x02, 0xcf, 0xdf, 0x96, 0x61, 0xef, 0xc0, -0xaf, 0x04, 0x27, 0xc1, 0x46, 0x04, 0x5b, 0xc0, -0x3e, 0x40, 0xef, 0xc1, 0xaf, 0x01, 0x2e, 0x94, -0x84, 0xd0, 0x41, 0x06, 0x5b, 0x2d, 0x88, 0xf3, -0x5b, 0x6c, 0x86, 0xdd, 0x97, 0x1f, 0x2d, 0x05, -0x5b, 0x03, 0x50, 0x01, 0x0c, 0x02, 0xcf, 0xc0, -0x1c, 0x00, 0x55, 0x05, 0x88, 0xc0, 0x23, 0x20, -0xef, 0xc1, 0xaf, 0x00, 0x2e, 0xf0, 0x8b, 0x05, -0x27, 0x9b, 0x22, 0x37, 0x45, 0x05, 0x5a, 0x41, -0x2e, 0x52, 0xdf, 0xdf, 0x2d, 0x04, 0x5b, 0x00, -0x28, 0x02, 0x50, 0x3b, 0x43, 0x00, 0x5b, 0x00, -0x28, 0xd3, 0xdf, 0xc6, 0x2e, 0x15, 0xbf, 0xd3, -0x3c, 0x40, 0xef, 0x09, 0x80, 0xdd, 0x97, 0xff, -0xaf, 0x00, 0x2e, 0x5d, 0x89, 0xc6, 0x2e, 0x15, -0xdf, 0x10, 0x1d, 0xd3, 0xcf, 0x3f, 0x02, 0xd3, -0xaf, 0x05, 0x27, 0xc1, 0x83, 0x07, 0x45, 0x05, -0x27, 0x3d, 0x23, 0x07, 0x3d, 0x02, 0xcf, 0xdf, -0x96, 0x2e, 0x88, 0x26, 0x88, 0xfe, 0xef, 0x16, -0x80, 0x05, 0xef, 0xc0, 0xaf, 0x04, 0x27, 0xd0, -0x41, 0x02, 0x5b, 0xee, 0x8f + 0x42, 0xca, 0x00, + 0x29, 0x24, 0xfe, 0xcf, 0x58, + 0xaf, 0xfe, 0xcf, 0xfe, 0xdf, 0x00, 0x2e, 0xa9, + 0x8b, 0xfe, 0xcf, 0x3c, 0xaf, 0x07, 0x3d, 0x58, + 0x40, 0x4a, 0x5a, 0x3c, 0x26, 0x48, 0x55, 0x37, + 0x45, 0x46, 0x5a, 0xe0, 0x88, 0x44, 0x5a, 0x77, + 0x88, 0x00, 0x2e, 0xd1, 0x8b, 0xfe, 0xef, 0x16, + 0x80, 0x02, 0xcf, 0xdf, 0x96, 0x61, 0xef, 0xc0, + 0xaf, 0x04, 0x27, 0xc1, 0x46, 0x04, 0x5b, 0xc0, + 0x3e, 0x40, 0xef, 0xc1, 0xaf, 0x01, 0x2e, 0x94, + 0x84, 0xd0, 0x41, 0x06, 0x5b, 0x2d, 0x88, 0xf3, + 0x5b, 0x6c, 0x86, 0xdd, 0x97, 0x1f, 0x2d, 0x05, + 0x5b, 0x03, 0x50, 0x01, 0x0c, 0x02, 0xcf, 0xc0, + 0x1c, 0x00, 0x55, 0x05, 0x88, 0xc0, 0x23, 0x20, + 0xef, 0xc1, 0xaf, 0x00, 0x2e, 0xf0, 0x8b, 0x05, + 0x27, 0x9b, 0x22, 0x37, 0x45, 0x05, 0x5a, 0x41, + 0x2e, 0x52, 0xdf, 0xdf, 0x2d, 0x04, 0x5b, 0x00, + 0x28, 0x02, 0x50, 0x3b, 0x43, 0x00, 0x5b, 0x00, + 0x28, 0xd3, 0xdf, 0xc6, 0x2e, 0x15, 0xbf, 0xd3, + 0x3c, 0x40, 0xef, 0x09, 0x80, 0xdd, 0x97, 0xff, + 0xaf, 0x00, 0x2e, 0x5d, 0x89, 0xc6, 0x2e, 0x15, + 0xdf, 0x10, 0x1d, 0xd3, 0xcf, 0x3f, 0x02, 0xd3, + 0xaf, 0x05, 0x27, 0xc1, 0x83, 0x07, 0x45, 0x05, + 0x27, 0x3d, 0x23, 0x07, 0x3d, 0x02, 0xcf, 0xdf, + 0x96, 0x2e, 0x88, 0x26, 0x88, 0xfe, 0xef, 0x16, + 0x80, 0x05, 0xef, 0xc0, 0xaf, 0x04, 0x27, 0xd0, + 0x41, 0x02, 0x5b, 0xee, 0x8f }; static const unsigned char pkt160[] = { -0x42, 0xca, 0x00, -0x8d, 0x24, 0xfa, 0x5b, 0xbf, -0x50, 0x31, 0x82, 0x04, 0xef, 0xc1, 0xaf, 0x9b, -0x22, 0x41, 0x88, 0xdd, 0x97, 0xdf, 0x22, 0x02, -0x55, 0x58, 0x40, 0x02, 0x5a, 0x09, 0x50, 0x58, -0x40, 0x07, 0x5a, 0xdd, 0x97, 0x1f, 0x2d, 0xb8, -0x5a, 0x7a, 0x88, 0xb7, 0x5b, 0x9b, 0x22, 0xc7, -0x8f, 0xb4, 0x50, 0x75, 0x88, 0xdc, 0x5b, 0xb7, -0x8f, 0x58, 0x41, 0x01, 0x5b, 0x01, 0x0c, 0xad, -0x7f, 0xd6, 0x50, 0x41, 0x2e, 0x52, 0xdf, 0xed, -0x1c, 0x04, 0x18, 0x41, 0x2e, 0x52, 0xbf, 0x05, -0x27, 0x00, 0x2e, 0xb9, 0x8b, 0xae, 0xdf, 0xe0, -0x19, 0xae, 0xbf, 0x57, 0x40, 0x00, 0x5b, 0xa1, -0x32, 0x57, 0x43, 0x00, 0x5b, 0xae, 0x3f, 0x05, -0x81, 0x05, 0x27, 0x41, 0x2e, 0x52, 0xdf, 0x03, -0x18, 0x41, 0x2e, 0x52, 0xbf, 0x05, 0x27, 0xd3, -0xdf, 0xff, 0x96, 0x9b, 0x22, 0x0b, 0x88, 0xd3, -0x3c, 0x07, 0x80, 0xdd, 0x97, 0xff, 0xaf, 0x00, -0x2e, 0x5d, 0x89, 0xdd, 0x9f, 0x10, 0x1d, 0xd3, -0xcf, 0x3f, 0x02, 0xd3, 0xaf, 0x05, 0x27, 0x37, -0x45, 0x0e, 0x5a, 0x40, 0x88, 0x0c, 0x5a, 0xd7, -0x8f, 0x00, 0x2e, 0xd7, 0x8b, 0x00, 0x2e, 0xeb, -0x8b, 0x41, 0x2e, 0x52, 0xdf, 0xdf, 0x2d, 0x00, -0x5b, 0x00, 0x28, 0x00, 0x2e, 0xf0, 0x8b, 0x05, -0x27, 0xf9, 0xcf, 0xdf, 0x96, 0xf9, 0x3d, 0x00, -0x2e, 0xd1, 0x8d, 0x28, 0xff, 0xa7, 0xef, 0xe1, -0xbf, 0xe0, 0xaf, 0x09, 0xef + 0x42, 0xca, 0x00, + 0x8d, 0x24, 0xfa, 0x5b, 0xbf, + 0x50, 0x31, 0x82, 0x04, 0xef, 0xc1, 0xaf, 0x9b, + 0x22, 0x41, 0x88, 0xdd, 0x97, 0xdf, 0x22, 0x02, + 0x55, 0x58, 0x40, 0x02, 0x5a, 0x09, 0x50, 0x58, + 0x40, 0x07, 0x5a, 0xdd, 0x97, 0x1f, 0x2d, 0xb8, + 0x5a, 0x7a, 0x88, 0xb7, 0x5b, 0x9b, 0x22, 0xc7, + 0x8f, 0xb4, 0x50, 0x75, 0x88, 0xdc, 0x5b, 0xb7, + 0x8f, 0x58, 0x41, 0x01, 0x5b, 0x01, 0x0c, 0xad, + 0x7f, 0xd6, 0x50, 0x41, 0x2e, 0x52, 0xdf, 0xed, + 0x1c, 0x04, 0x18, 0x41, 0x2e, 0x52, 0xbf, 0x05, + 0x27, 0x00, 0x2e, 0xb9, 0x8b, 0xae, 0xdf, 0xe0, + 0x19, 0xae, 0xbf, 0x57, 0x40, 0x00, 0x5b, 0xa1, + 0x32, 0x57, 0x43, 0x00, 0x5b, 0xae, 0x3f, 0x05, + 0x81, 0x05, 0x27, 0x41, 0x2e, 0x52, 0xdf, 0x03, + 0x18, 0x41, 0x2e, 0x52, 0xbf, 0x05, 0x27, 0xd3, + 0xdf, 0xff, 0x96, 0x9b, 0x22, 0x0b, 0x88, 0xd3, + 0x3c, 0x07, 0x80, 0xdd, 0x97, 0xff, 0xaf, 0x00, + 0x2e, 0x5d, 0x89, 0xdd, 0x9f, 0x10, 0x1d, 0xd3, + 0xcf, 0x3f, 0x02, 0xd3, 0xaf, 0x05, 0x27, 0x37, + 0x45, 0x0e, 0x5a, 0x40, 0x88, 0x0c, 0x5a, 0xd7, + 0x8f, 0x00, 0x2e, 0xd7, 0x8b, 0x00, 0x2e, 0xeb, + 0x8b, 0x41, 0x2e, 0x52, 0xdf, 0xdf, 0x2d, 0x00, + 0x5b, 0x00, 0x28, 0x00, 0x2e, 0xf0, 0x8b, 0x05, + 0x27, 0xf9, 0xcf, 0xdf, 0x96, 0xf9, 0x3d, 0x00, + 0x2e, 0xd1, 0x8d, 0x28, 0xff, 0xa7, 0xef, 0xe1, + 0xbf, 0xe0, 0xaf, 0x09, 0xef }; static const unsigned char pkt164[] = { -0x42, 0x6c, 0x00, -0xf1, 0x24, 0x10, 0xaf, 0x0e, -0x8c, 0x05, 0x81, 0x01, 0x2e, 0x54, 0x80, 0x01, -0x2e, 0x56, 0x80, 0x20, 0x82, 0x7b, 0x8c, 0x37, -0x82, 0x26, 0x37, 0x00, 0x5a, 0x0c, 0x50, 0xff, -0x96, 0xdf, 0x96, 0x79, 0xcf, 0x7a, 0xdf, 0xff, -0x96, 0xdf, 0x96, 0xc2, 0x97, 0xc3, 0x9f, 0x9d, -0x01, 0x5d, 0x01, 0x07, 0x53, 0xdd, 0x97, 0xdd, -0x9f, 0x79, 0xaf, 0x7a, 0xbf, 0x3b, 0x3b, 0xdd, -0x97, 0xf9, 0xaf, 0x05, 0x27, 0xff, 0x22, 0x01, -0x55, 0x32, 0x1e, 0xf3, 0x5f, 0x02, 0x0c, 0xf6, -0x8f, 0x3b, 0x33, 0x00, 0x28, 0x05, 0x27, 0x0d, -0x27, 0x3c, 0x26, 0x07, 0x54, 0x3c, 0xcf, 0x3d, -0xdf, 0x3f, 0x20, 0x3d, 0xbf, 0xdf, 0x03, 0x01, -0x52, 0x3d, 0x23, 0x0c, 0x27, 0x0d, 0x27 + 0x42, 0x6c, 0x00, + 0xf1, 0x24, 0x10, 0xaf, 0x0e, + 0x8c, 0x05, 0x81, 0x01, 0x2e, 0x54, 0x80, 0x01, + 0x2e, 0x56, 0x80, 0x20, 0x82, 0x7b, 0x8c, 0x37, + 0x82, 0x26, 0x37, 0x00, 0x5a, 0x0c, 0x50, 0xff, + 0x96, 0xdf, 0x96, 0x79, 0xcf, 0x7a, 0xdf, 0xff, + 0x96, 0xdf, 0x96, 0xc2, 0x97, 0xc3, 0x9f, 0x9d, + 0x01, 0x5d, 0x01, 0x07, 0x53, 0xdd, 0x97, 0xdd, + 0x9f, 0x79, 0xaf, 0x7a, 0xbf, 0x3b, 0x3b, 0xdd, + 0x97, 0xf9, 0xaf, 0x05, 0x27, 0xff, 0x22, 0x01, + 0x55, 0x32, 0x1e, 0xf3, 0x5f, 0x02, 0x0c, 0xf6, + 0x8f, 0x3b, 0x33, 0x00, 0x28, 0x05, 0x27, 0x0d, + 0x27, 0x3c, 0x26, 0x07, 0x54, 0x3c, 0xcf, 0x3d, + 0xdf, 0x3f, 0x20, 0x3d, 0xbf, 0xdf, 0x03, 0x01, + 0x52, 0x3d, 0x23, 0x0c, 0x27, 0x0d, 0x27 }; static const unsigned char pkt168[] = { -0x42, 0x50, 0x00, -0x26, 0x25, 0x08, 0x44, 0x12, -0x5a, 0x07, 0x40, 0x01, 0x5b, 0x4f, 0x80, 0x00, -0x50, 0x53, 0x80, 0x27, 0x0d, 0x25, 0xcf, 0x1f, -0x98, 0x29, 0xcf, 0x09, 0x27, 0x28, 0xdf, 0x3f, -0x02, 0x5f, 0x98, 0x62, 0xcf, 0xdf, 0x98, 0xd9, -0x0d, 0x02, 0x0d, 0x00, 0x2e, 0xd5, 0x7f, 0x05, -0x27, 0x01, 0x0d, 0x41, 0x2e, 0x56, 0xdf, 0x5f, -0x9f, 0x41, 0x2e, 0x57, 0xdf, 0x5f, 0x9f, 0x41, -0x2e, 0x58, 0xdf, 0x5f, 0x9f, 0x41, 0x2e, 0x59, -0xdf, 0x5f, 0x9f, 0x06, 0x0d, 0x3b, 0xcf, 0x5f, -0x9f, 0x05, 0x27 + 0x42, 0x50, 0x00, + 0x26, 0x25, 0x08, 0x44, 0x12, + 0x5a, 0x07, 0x40, 0x01, 0x5b, 0x4f, 0x80, 0x00, + 0x50, 0x53, 0x80, 0x27, 0x0d, 0x25, 0xcf, 0x1f, + 0x98, 0x29, 0xcf, 0x09, 0x27, 0x28, 0xdf, 0x3f, + 0x02, 0x5f, 0x98, 0x62, 0xcf, 0xdf, 0x98, 0xd9, + 0x0d, 0x02, 0x0d, 0x00, 0x2e, 0xd5, 0x7f, 0x05, + 0x27, 0x01, 0x0d, 0x41, 0x2e, 0x56, 0xdf, 0x5f, + 0x9f, 0x41, 0x2e, 0x57, 0xdf, 0x5f, 0x9f, 0x41, + 0x2e, 0x58, 0xdf, 0x5f, 0x9f, 0x41, 0x2e, 0x59, + 0xdf, 0x5f, 0x9f, 0x06, 0x0d, 0x3b, 0xcf, 0x5f, + 0x9f, 0x05, 0x27 }; static const unsigned char pkt172[] = { -0x42, 0xca, 0x00, -0x4d, 0x25, 0x9b, 0x22, 0xbb, -0x89, 0x22, 0x88, 0x75, 0x88, 0x14, 0x86, 0x2b, -0x86, 0x2b, 0x86, 0x2b, 0x86, 0x2b, 0x86, 0xa0, -0x88, 0x2e, 0x89, 0x24, 0x89, 0x02, 0x33, 0x07, -0x80, 0xdd, 0x97, 0xff, 0xaf, 0x00, 0x2e, 0x5d, -0x89, 0x05, 0x27, 0x6c, 0xcf, 0x6d, 0xdf, 0xbf, -0x01, 0x6c, 0xaf, 0x6d, 0x26, 0x00, 0x2e, 0x33, -0x55, 0x00, 0x2e, 0x4e, 0x50, 0xdf, 0x96, 0xff, -0x96, 0x32, 0xff, 0x07, 0xef, 0x91, 0x81, 0x7f, -0x20, 0xfb, 0x55, 0xdd, 0x9f, 0xdd, 0x97, 0x05, -0x27, 0x9f, 0x22, 0x6b, 0xaf, 0x00, 0x2e, 0x6e, -0x8f, 0x00, 0xef, 0x41, 0x2e, 0x44, 0xbf, 0x7f, -0xef, 0x41, 0x2e, 0x45, 0xbf, 0x80, 0xef, 0x0a, -0xaf, 0x00, 0x2e, 0xd1, 0x8d, 0x88, 0x82, 0x8c, -0x82, 0x6b, 0xcf, 0x10, 0xaf, 0x02, 0x2e, 0x02, -0x81, 0x40, 0xef, 0x6d, 0xaf, 0x80, 0xef, 0x6c, -0xaf, 0x00, 0x2e, 0xc4, 0x8d, 0x05, 0x81, 0x01, -0x2e, 0x54, 0x80, 0x01, 0x2e, 0x56, 0x80, 0x7f, -0x89, 0xff, 0x2f, 0xca, 0x5a, 0x6c, 0xcf, 0x6d, -0xdf, 0x3f, 0x00, 0x6c, 0xaf, 0x6d, 0x26, 0x03, -0x54, 0x6d, 0xdf, 0x16, 0x82, 0x6d, 0xbf, 0xeb, -0x50, 0x6b, 0xcf, 0x08, 0x1e, 0x11, 0x5f, 0x6c, -0x24, 0x02, 0x53, 0xff, 0xef, 0x6c, 0xaf, 0x10, -0x50, 0x6c, 0x24, 0x02, 0x53, 0xff, 0xef, 0x6c, -0xaf, 0x0b, 0x50, 0x6b, 0xcf, 0x0a, 0x1e, 0x08, -0x55, 0x6c, 0x24, 0x02, 0x53 + 0x42, 0xca, 0x00, + 0x4d, 0x25, 0x9b, 0x22, 0xbb, + 0x89, 0x22, 0x88, 0x75, 0x88, 0x14, 0x86, 0x2b, + 0x86, 0x2b, 0x86, 0x2b, 0x86, 0x2b, 0x86, 0xa0, + 0x88, 0x2e, 0x89, 0x24, 0x89, 0x02, 0x33, 0x07, + 0x80, 0xdd, 0x97, 0xff, 0xaf, 0x00, 0x2e, 0x5d, + 0x89, 0x05, 0x27, 0x6c, 0xcf, 0x6d, 0xdf, 0xbf, + 0x01, 0x6c, 0xaf, 0x6d, 0x26, 0x00, 0x2e, 0x33, + 0x55, 0x00, 0x2e, 0x4e, 0x50, 0xdf, 0x96, 0xff, + 0x96, 0x32, 0xff, 0x07, 0xef, 0x91, 0x81, 0x7f, + 0x20, 0xfb, 0x55, 0xdd, 0x9f, 0xdd, 0x97, 0x05, + 0x27, 0x9f, 0x22, 0x6b, 0xaf, 0x00, 0x2e, 0x6e, + 0x8f, 0x00, 0xef, 0x41, 0x2e, 0x44, 0xbf, 0x7f, + 0xef, 0x41, 0x2e, 0x45, 0xbf, 0x80, 0xef, 0x0a, + 0xaf, 0x00, 0x2e, 0xd1, 0x8d, 0x88, 0x82, 0x8c, + 0x82, 0x6b, 0xcf, 0x10, 0xaf, 0x02, 0x2e, 0x02, + 0x81, 0x40, 0xef, 0x6d, 0xaf, 0x80, 0xef, 0x6c, + 0xaf, 0x00, 0x2e, 0xc4, 0x8d, 0x05, 0x81, 0x01, + 0x2e, 0x54, 0x80, 0x01, 0x2e, 0x56, 0x80, 0x7f, + 0x89, 0xff, 0x2f, 0xca, 0x5a, 0x6c, 0xcf, 0x6d, + 0xdf, 0x3f, 0x00, 0x6c, 0xaf, 0x6d, 0x26, 0x03, + 0x54, 0x6d, 0xdf, 0x16, 0x82, 0x6d, 0xbf, 0xeb, + 0x50, 0x6b, 0xcf, 0x08, 0x1e, 0x11, 0x5f, 0x6c, + 0x24, 0x02, 0x53, 0xff, 0xef, 0x6c, 0xaf, 0x10, + 0x50, 0x6c, 0x24, 0x02, 0x53, 0xff, 0xef, 0x6c, + 0xaf, 0x0b, 0x50, 0x6b, 0xcf, 0x0a, 0x1e, 0x08, + 0x55, 0x6c, 0x24, 0x02, 0x53 }; static const unsigned char pkt176[] = { -0x42, 0xca, 0x00, -0xb1, 0x25, 0xff, 0xef, 0x6c, -0xaf, 0x03, 0x50, 0x6c, 0x24, 0x01, 0x53, 0xff, -0xef, 0x6c, 0xaf, 0x6b, 0xcf, 0xdf, 0x96, 0xb0, -0xef, 0x00, 0xff, 0x1d, 0x00, 0x00, 0x13, 0x1b, -0x27, 0x6c, 0xcf, 0x9f, 0x9d, 0x6b, 0xcf, 0x1f, -0x20, 0x6b, 0xaf, 0x0a, 0x1e, 0xbc, 0x5f, 0x05, -0x27, 0x0c, 0xef, 0x41, 0x2e, 0x76, 0xbf, 0x10, -0xef, 0x6d, 0xaf, 0xae, 0xcf, 0xe0, 0x1c, 0xae, -0xaf, 0x0b, 0x78, 0xcb, 0xcf, 0xcc, 0xdf, 0x0a, -0x1f, 0x07, 0x52, 0x01, 0x5e, 0x00, 0x1e, 0x04, -0x5f, 0xae, 0xcf, 0x6d, 0xdf, 0xbf, 0x01, 0xae, -0xaf, 0x03, 0x78, 0xae, 0xcf, 0x6d, 0xdf, 0x3f, -0x00, 0xae, 0xaf, 0x16, 0x82, 0x6d, 0xbf, 0x05, -0x81, 0x64, 0xef, 0xbf, 0x22, 0xbd, 0x80, 0x34, -0x81, 0x53, 0x81, 0x6d, 0x26, 0xe5, 0x55, 0xcb, -0xcf, 0xcc, 0xdf, 0x0a, 0x1f, 0x02, 0x5e, 0x04, -0x52, 0x00, 0x1e, 0x02, 0x5f, 0xae, 0xcf, 0x5f, -0x20, 0xae, 0xaf, 0x00, 0xef, 0x41, 0x2e, 0x76, -0xbf, 0x05, 0x27, 0x00, 0x2e, 0x6e, 0x8f, 0x02, -0x2e, 0x6b, 0x81, 0x00, 0x2e, 0xd1, 0x8d, 0x73, -0x23, 0x0a, 0xef, 0x10, 0xaf, 0x02, 0x2e, 0x02, -0x81, 0x80, 0xef, 0x00, 0x2e, 0xc4, 0x8d, 0x05, -0x81, 0x08, 0xef, 0x06, 0xaf, 0x01, 0x2e, 0x54, -0x80, 0x01, 0x2e, 0x56, 0x80, 0x06, 0x25, 0xf9, -0x55, 0xb3, 0x88, 0x40, 0xcf, 0xe0, 0xaf, 0x41, -0xdf, 0xe1, 0xbf, 0x41, 0x2e + 0x42, 0xca, 0x00, + 0xb1, 0x25, 0xff, 0xef, 0x6c, + 0xaf, 0x03, 0x50, 0x6c, 0x24, 0x01, 0x53, 0xff, + 0xef, 0x6c, 0xaf, 0x6b, 0xcf, 0xdf, 0x96, 0xb0, + 0xef, 0x00, 0xff, 0x1d, 0x00, 0x00, 0x13, 0x1b, + 0x27, 0x6c, 0xcf, 0x9f, 0x9d, 0x6b, 0xcf, 0x1f, + 0x20, 0x6b, 0xaf, 0x0a, 0x1e, 0xbc, 0x5f, 0x05, + 0x27, 0x0c, 0xef, 0x41, 0x2e, 0x76, 0xbf, 0x10, + 0xef, 0x6d, 0xaf, 0xae, 0xcf, 0xe0, 0x1c, 0xae, + 0xaf, 0x0b, 0x78, 0xcb, 0xcf, 0xcc, 0xdf, 0x0a, + 0x1f, 0x07, 0x52, 0x01, 0x5e, 0x00, 0x1e, 0x04, + 0x5f, 0xae, 0xcf, 0x6d, 0xdf, 0xbf, 0x01, 0xae, + 0xaf, 0x03, 0x78, 0xae, 0xcf, 0x6d, 0xdf, 0x3f, + 0x00, 0xae, 0xaf, 0x16, 0x82, 0x6d, 0xbf, 0x05, + 0x81, 0x64, 0xef, 0xbf, 0x22, 0xbd, 0x80, 0x34, + 0x81, 0x53, 0x81, 0x6d, 0x26, 0xe5, 0x55, 0xcb, + 0xcf, 0xcc, 0xdf, 0x0a, 0x1f, 0x02, 0x5e, 0x04, + 0x52, 0x00, 0x1e, 0x02, 0x5f, 0xae, 0xcf, 0x5f, + 0x20, 0xae, 0xaf, 0x00, 0xef, 0x41, 0x2e, 0x76, + 0xbf, 0x05, 0x27, 0x00, 0x2e, 0x6e, 0x8f, 0x02, + 0x2e, 0x6b, 0x81, 0x00, 0x2e, 0xd1, 0x8d, 0x73, + 0x23, 0x0a, 0xef, 0x10, 0xaf, 0x02, 0x2e, 0x02, + 0x81, 0x80, 0xef, 0x00, 0x2e, 0xc4, 0x8d, 0x05, + 0x81, 0x08, 0xef, 0x06, 0xaf, 0x01, 0x2e, 0x54, + 0x80, 0x01, 0x2e, 0x56, 0x80, 0x06, 0x25, 0xf9, + 0x55, 0xb3, 0x88, 0x40, 0xcf, 0xe0, 0xaf, 0x41, + 0xdf, 0xe1, 0xbf, 0x41, 0x2e }; static const unsigned char pkt180[] = { -0x42, 0xca, 0x00, -0x15, 0x26, 0x4e, 0xdf, 0xf7, -0x1c, 0x41, 0x2e, 0x4e, 0xbf, 0x01, 0x2e, 0x54, -0x80, 0x01, 0x2e, 0x56, 0x80, 0x4f, 0x82, 0x40, -0x2e, 0x8f, 0xdf, 0xdf, 0x22, 0xed, 0x55, 0x30, -0x88, 0x4e, 0x23, 0x4e, 0xcf, 0x31, 0x88, 0x37, -0x88, 0x3f, 0x9f, 0x4e, 0xcf, 0x2d, 0x88, 0x39, -0x88, 0x1f, 0x9f, 0x4e, 0x24, 0x4e, 0xcf, 0x04, -0x1e, 0xf3, 0x55, 0xf8, 0x0f, 0x08, 0xef, 0x06, -0xaf, 0xf6, 0x97, 0xbc, 0x03, 0x01, 0x5f, 0xff, -0x0f, 0xfc, 0x97, 0x06, 0x25, 0xf9, 0x55, 0xf8, -0x0f, 0x08, 0xff, 0x06, 0xbf, 0xf6, 0x9f, 0xdf, -0x01, 0xa1, 0x27, 0x7f, 0x21, 0x3f, 0x9f, 0x06, -0x25, 0xf8, 0x55, 0xf8, 0x0f, 0x04, 0xef, 0x06, -0xaf, 0xbb, 0xef, 0x00, 0xff, 0x1a, 0x27, 0xfc, -0x9f, 0xfc, 0x97, 0x09, 0x27, 0x5f, 0x02, 0x3f, -0x97, 0x06, 0x25, 0xf8, 0x55, 0x81, 0xcf, 0x24, -0xaf, 0x05, 0x27, 0x54, 0xef, 0x28, 0xff, 0x1b, -0x27, 0x05, 0x27, 0xdf, 0x96, 0x40, 0xcf, 0x41, -0xdf, 0x1d, 0x00, 0x00, 0x13, 0x19, 0x27, 0x05, -0x27, 0x0f, 0xff, 0x0b, 0x88, 0x40, 0x10, 0x00, -0x13, 0x8e, 0x81, 0x05, 0x27, 0xf0, 0xff, 0x05, -0x88, 0x04, 0x11, 0x3f, 0x22, 0xff, 0x97, 0x09, -0x27, 0x0f, 0x1c, 0x05, 0x27, 0xff, 0x96, 0x9b, -0x22, 0x9b, 0x22, 0x80, 0xef, 0x06, 0xaf, 0xe0, -0x97, 0x02, 0x03, 0xbf, 0x22, 0x00, 0x00, 0xc1, -0x00, 0x1f, 0x90, 0x7f, 0x90 + 0x42, 0xca, 0x00, + 0x15, 0x26, 0x4e, 0xdf, 0xf7, + 0x1c, 0x41, 0x2e, 0x4e, 0xbf, 0x01, 0x2e, 0x54, + 0x80, 0x01, 0x2e, 0x56, 0x80, 0x4f, 0x82, 0x40, + 0x2e, 0x8f, 0xdf, 0xdf, 0x22, 0xed, 0x55, 0x30, + 0x88, 0x4e, 0x23, 0x4e, 0xcf, 0x31, 0x88, 0x37, + 0x88, 0x3f, 0x9f, 0x4e, 0xcf, 0x2d, 0x88, 0x39, + 0x88, 0x1f, 0x9f, 0x4e, 0x24, 0x4e, 0xcf, 0x04, + 0x1e, 0xf3, 0x55, 0xf8, 0x0f, 0x08, 0xef, 0x06, + 0xaf, 0xf6, 0x97, 0xbc, 0x03, 0x01, 0x5f, 0xff, + 0x0f, 0xfc, 0x97, 0x06, 0x25, 0xf9, 0x55, 0xf8, + 0x0f, 0x08, 0xff, 0x06, 0xbf, 0xf6, 0x9f, 0xdf, + 0x01, 0xa1, 0x27, 0x7f, 0x21, 0x3f, 0x9f, 0x06, + 0x25, 0xf8, 0x55, 0xf8, 0x0f, 0x04, 0xef, 0x06, + 0xaf, 0xbb, 0xef, 0x00, 0xff, 0x1a, 0x27, 0xfc, + 0x9f, 0xfc, 0x97, 0x09, 0x27, 0x5f, 0x02, 0x3f, + 0x97, 0x06, 0x25, 0xf8, 0x55, 0x81, 0xcf, 0x24, + 0xaf, 0x05, 0x27, 0x54, 0xef, 0x28, 0xff, 0x1b, + 0x27, 0x05, 0x27, 0xdf, 0x96, 0x40, 0xcf, 0x41, + 0xdf, 0x1d, 0x00, 0x00, 0x13, 0x19, 0x27, 0x05, + 0x27, 0x0f, 0xff, 0x0b, 0x88, 0x40, 0x10, 0x00, + 0x13, 0x8e, 0x81, 0x05, 0x27, 0xf0, 0xff, 0x05, + 0x88, 0x04, 0x11, 0x3f, 0x22, 0xff, 0x97, 0x09, + 0x27, 0x0f, 0x1c, 0x05, 0x27, 0xff, 0x96, 0x9b, + 0x22, 0x9b, 0x22, 0x80, 0xef, 0x06, 0xaf, 0xe0, + 0x97, 0x02, 0x03, 0xbf, 0x22, 0x00, 0x00, 0xc1, + 0x00, 0x1f, 0x90, 0x7f, 0x90 }; static const unsigned char pkt184[] = { -0x42, 0xca, 0x00, -0x79, 0x26, 0x04, 0x0d, 0x06, -0x25, 0xf5, 0x55, 0x03, 0x0c, 0x05, 0x27, 0x04, -0xef, 0x10, 0xaf, 0x02, 0x2e, 0x02, 0x81, 0x05, -0x81, 0xf7, 0xef, 0x16, 0x80, 0x6b, 0x81, 0x05, -0x27, 0x73, 0x23, 0x08, 0xef, 0x0b, 0xaf, 0x02, -0x2e, 0x6b, 0x81, 0x00, 0x2e, 0x6e, 0x8f, 0x00, -0x2e, 0xd1, 0x8d, 0x0a, 0xef, 0x10, 0xaf, 0x02, -0x2e, 0x02, 0x81, 0x88, 0x82, 0x02, 0x2e, 0x9f, -0x80, 0x80, 0xef, 0x00, 0x2e, 0xc4, 0x8d, 0x05, -0x81, 0x0b, 0xcf, 0x06, 0xaf, 0x01, 0x2e, 0x54, -0x80, 0x01, 0x2e, 0x56, 0x80, 0x06, 0x25, 0xf9, -0x55, 0x1f, 0x88, 0x20, 0x82, 0x02, 0x2e, 0x76, -0x81, 0xf7, 0xef, 0x16, 0x80, 0x81, 0xcf, 0x72, -0xaf, 0x02, 0x2e, 0x6b, 0x81, 0x02, 0x2e, 0xc0, -0x81, 0x08, 0xef, 0x02, 0x2e, 0x51, 0x80, 0x08, -0xef, 0x02, 0x2e, 0x7a, 0x80, 0x01, 0x2e, 0x89, -0x81, 0x2d, 0xcf, 0xdf, 0x96, 0x2c, 0xcf, 0xdf, -0x96, 0x2a, 0xcf, 0x2b, 0xdf, 0x9d, 0x01, 0x5d, -0x01, 0x83, 0xaf, 0x84, 0xbf, 0xc8, 0xef, 0x0b, -0xaf, 0x05, 0x27, 0x0a, 0xef, 0x73, 0x43, 0x02, -0x5b, 0x73, 0xcf, 0x09, 0x27, 0x0f, 0x1c, 0x81, -0xaf, 0x73, 0xcf, 0x09, 0x27, 0x30, 0x1c, 0xfc, -0xdf, 0xcf, 0x1d, 0x5f, 0x02, 0xfc, 0xbf, 0x81, -0xcf, 0x10, 0xaf, 0x02, 0x2e, 0x02, 0x81, 0x88, -0x82, 0x02, 0x2e, 0x9f, 0x80, 0x40, 0xef, 0x6b, -0xaf, 0x80, 0xef, 0x82, 0xaf + 0x42, 0xca, 0x00, + 0x79, 0x26, 0x04, 0x0d, 0x06, + 0x25, 0xf5, 0x55, 0x03, 0x0c, 0x05, 0x27, 0x04, + 0xef, 0x10, 0xaf, 0x02, 0x2e, 0x02, 0x81, 0x05, + 0x81, 0xf7, 0xef, 0x16, 0x80, 0x6b, 0x81, 0x05, + 0x27, 0x73, 0x23, 0x08, 0xef, 0x0b, 0xaf, 0x02, + 0x2e, 0x6b, 0x81, 0x00, 0x2e, 0x6e, 0x8f, 0x00, + 0x2e, 0xd1, 0x8d, 0x0a, 0xef, 0x10, 0xaf, 0x02, + 0x2e, 0x02, 0x81, 0x88, 0x82, 0x02, 0x2e, 0x9f, + 0x80, 0x80, 0xef, 0x00, 0x2e, 0xc4, 0x8d, 0x05, + 0x81, 0x0b, 0xcf, 0x06, 0xaf, 0x01, 0x2e, 0x54, + 0x80, 0x01, 0x2e, 0x56, 0x80, 0x06, 0x25, 0xf9, + 0x55, 0x1f, 0x88, 0x20, 0x82, 0x02, 0x2e, 0x76, + 0x81, 0xf7, 0xef, 0x16, 0x80, 0x81, 0xcf, 0x72, + 0xaf, 0x02, 0x2e, 0x6b, 0x81, 0x02, 0x2e, 0xc0, + 0x81, 0x08, 0xef, 0x02, 0x2e, 0x51, 0x80, 0x08, + 0xef, 0x02, 0x2e, 0x7a, 0x80, 0x01, 0x2e, 0x89, + 0x81, 0x2d, 0xcf, 0xdf, 0x96, 0x2c, 0xcf, 0xdf, + 0x96, 0x2a, 0xcf, 0x2b, 0xdf, 0x9d, 0x01, 0x5d, + 0x01, 0x83, 0xaf, 0x84, 0xbf, 0xc8, 0xef, 0x0b, + 0xaf, 0x05, 0x27, 0x0a, 0xef, 0x73, 0x43, 0x02, + 0x5b, 0x73, 0xcf, 0x09, 0x27, 0x0f, 0x1c, 0x81, + 0xaf, 0x73, 0xcf, 0x09, 0x27, 0x30, 0x1c, 0xfc, + 0xdf, 0xcf, 0x1d, 0x5f, 0x02, 0xfc, 0xbf, 0x81, + 0xcf, 0x10, 0xaf, 0x02, 0x2e, 0x02, 0x81, 0x88, + 0x82, 0x02, 0x2e, 0x9f, 0x80, 0x40, 0xef, 0x6b, + 0xaf, 0x80, 0xef, 0x82, 0xaf }; static const unsigned char pkt188[] = { -0x42, 0x9a, 0x00, -0xdd, 0x26, 0x00, 0x2e, 0xc4, -0x8d, 0x05, 0x81, 0x01, 0x2e, 0x54, 0x80, 0x01, -0x2e, 0x56, 0x80, 0x20, 0x82, 0x02, 0x2e, 0xe6, -0x80, 0x0a, 0x5b, 0x73, 0x43, 0x18, 0x5a, 0x81, -0xcf, 0x5e, 0xdf, 0xbf, 0x03, 0x14, 0x5f, 0x5f, -0x20, 0x81, 0xaf, 0xdf, 0x22, 0x10, 0x54, 0xde, -0x50, 0x40, 0x2e, 0x8f, 0xdf, 0x1f, 0x2c, 0x0c, -0x5a, 0x5f, 0x2c, 0x09, 0x5b, 0x82, 0xcf, 0x6b, -0xdf, 0x3f, 0x00, 0x82, 0xaf, 0x6b, 0x26, 0xe8, -0x54, 0x6b, 0xdf, 0x16, 0x82, 0x6b, 0xbf, 0xd9, -0x50, 0x05, 0x27, 0x82, 0xcf, 0x6b, 0xdf, 0xbf, -0x01, 0x82, 0xaf, 0x6b, 0x26, 0xf4, 0x55, 0xdc, -0x50, 0x88, 0x82, 0x8c, 0x82, 0x9f, 0x22, 0xbb, -0xaf, 0xbc, 0xaf, 0xbd, 0xaf, 0xbe, 0xaf, 0x05, -0x27, 0xf9, 0x44, 0x08, 0x5a, 0xc1, 0x2e, 0x81, -0xdf, 0x01, 0x1f, 0x0e, 0x52, 0x0c, 0x5e, 0xc1, -0x2e, 0x80, 0xdf, 0xfe, 0x1f, 0x09, 0x52, 0xc1, -0x2e, 0x81, 0xdf, 0x03, 0x1f, 0x05, 0x52, 0x03, -0x5e, 0xc1, 0x2e, 0x80, 0xdf, 0xfc, 0x1f, 0x00, -0x52, 0x0c, 0x27, 0x0d, 0x27 + 0x42, 0x9a, 0x00, + 0xdd, 0x26, 0x00, 0x2e, 0xc4, + 0x8d, 0x05, 0x81, 0x01, 0x2e, 0x54, 0x80, 0x01, + 0x2e, 0x56, 0x80, 0x20, 0x82, 0x02, 0x2e, 0xe6, + 0x80, 0x0a, 0x5b, 0x73, 0x43, 0x18, 0x5a, 0x81, + 0xcf, 0x5e, 0xdf, 0xbf, 0x03, 0x14, 0x5f, 0x5f, + 0x20, 0x81, 0xaf, 0xdf, 0x22, 0x10, 0x54, 0xde, + 0x50, 0x40, 0x2e, 0x8f, 0xdf, 0x1f, 0x2c, 0x0c, + 0x5a, 0x5f, 0x2c, 0x09, 0x5b, 0x82, 0xcf, 0x6b, + 0xdf, 0x3f, 0x00, 0x82, 0xaf, 0x6b, 0x26, 0xe8, + 0x54, 0x6b, 0xdf, 0x16, 0x82, 0x6b, 0xbf, 0xd9, + 0x50, 0x05, 0x27, 0x82, 0xcf, 0x6b, 0xdf, 0xbf, + 0x01, 0x82, 0xaf, 0x6b, 0x26, 0xf4, 0x55, 0xdc, + 0x50, 0x88, 0x82, 0x8c, 0x82, 0x9f, 0x22, 0xbb, + 0xaf, 0xbc, 0xaf, 0xbd, 0xaf, 0xbe, 0xaf, 0x05, + 0x27, 0xf9, 0x44, 0x08, 0x5a, 0xc1, 0x2e, 0x81, + 0xdf, 0x01, 0x1f, 0x0e, 0x52, 0x0c, 0x5e, 0xc1, + 0x2e, 0x80, 0xdf, 0xfe, 0x1f, 0x09, 0x52, 0xc1, + 0x2e, 0x81, 0xdf, 0x03, 0x1f, 0x05, 0x52, 0x03, + 0x5e, 0xc1, 0x2e, 0x80, 0xdf, 0xfc, 0x1f, 0x00, + 0x52, 0x0c, 0x27, 0x0d, 0x27 }; static const unsigned char pkt192[] = { -0x42, 0x7e, 0x00, -0x29, 0x27, 0x53, 0x80, 0x01, -0x0d, 0xf5, 0x97, 0xff, 0x0d, 0x1f, 0x99, 0x49, -0xcf, 0x5f, 0x99, 0x08, 0x44, 0x00, 0x2e, 0x32, -0x5a, 0x0b, 0x0d, 0x44, 0xcf, 0x0c, 0x41, 0x00, -0x5b, 0x1f, 0x20, 0x44, 0xaf, 0x5f, 0x9f, 0x04, -0x0d, 0x11, 0xcf, 0x5f, 0x9f, 0x12, 0xcf, 0x5f, -0x9f, 0x1c, 0xcf, 0x5f, 0x9f, 0x1d, 0xcf, 0x5f, -0x9f, 0x4d, 0xcf, 0x5f, 0x9f, 0x49, 0xcf, 0x5f, -0x9f, 0x06, 0x0d, 0xe0, 0x97, 0x0f, 0x1c, 0x5f, -0x9f, 0x0a, 0xcf, 0x5f, 0x9f, 0x09, 0xcf, 0x5f, -0x9f, 0x78, 0xcf, 0x5f, 0x9f, 0x9f, 0xcf, 0x5f, -0x9f, 0x92, 0xcf, 0x5f, 0x9f, 0x19, 0xcf, 0x5f, -0x9f, 0x02, 0x0d, 0x85, 0xcf, 0x5f, 0x9f, 0x44, -0xdf, 0x02, 0x2e, 0x8c, 0x81, 0x5f, 0x9f, 0x4d, -0xcf, 0x5f, 0x9f, 0x01, 0x0d, 0x6a, 0xcf, 0x09, -0x27, 0x69, 0xdf, 0x3f, 0x02, 0x5f, 0x9f, 0x05, -0x27 + 0x42, 0x7e, 0x00, + 0x29, 0x27, 0x53, 0x80, 0x01, + 0x0d, 0xf5, 0x97, 0xff, 0x0d, 0x1f, 0x99, 0x49, + 0xcf, 0x5f, 0x99, 0x08, 0x44, 0x00, 0x2e, 0x32, + 0x5a, 0x0b, 0x0d, 0x44, 0xcf, 0x0c, 0x41, 0x00, + 0x5b, 0x1f, 0x20, 0x44, 0xaf, 0x5f, 0x9f, 0x04, + 0x0d, 0x11, 0xcf, 0x5f, 0x9f, 0x12, 0xcf, 0x5f, + 0x9f, 0x1c, 0xcf, 0x5f, 0x9f, 0x1d, 0xcf, 0x5f, + 0x9f, 0x4d, 0xcf, 0x5f, 0x9f, 0x49, 0xcf, 0x5f, + 0x9f, 0x06, 0x0d, 0xe0, 0x97, 0x0f, 0x1c, 0x5f, + 0x9f, 0x0a, 0xcf, 0x5f, 0x9f, 0x09, 0xcf, 0x5f, + 0x9f, 0x78, 0xcf, 0x5f, 0x9f, 0x9f, 0xcf, 0x5f, + 0x9f, 0x92, 0xcf, 0x5f, 0x9f, 0x19, 0xcf, 0x5f, + 0x9f, 0x02, 0x0d, 0x85, 0xcf, 0x5f, 0x9f, 0x44, + 0xdf, 0x02, 0x2e, 0x8c, 0x81, 0x5f, 0x9f, 0x4d, + 0xcf, 0x5f, 0x9f, 0x01, 0x0d, 0x6a, 0xcf, 0x09, + 0x27, 0x69, 0xdf, 0x3f, 0x02, 0x5f, 0x9f, 0x05, + 0x27 }; static const unsigned char pkt196[] = { -0x42, 0xca, 0x00, -0x67, 0x27, 0x00, 0x2e, 0xf5, -0x88, 0x39, 0x81, 0x84, 0x88, 0x05, 0xcf, 0xdf, -0x22, 0x33, 0x55, 0x04, 0xcf, 0x2a, 0x1e, 0x30, -0x55, 0xfe, 0xdf, 0xfe, 0xcf, 0x00, 0x1f, 0x1b, -0x55, 0x00, 0x1e, 0x0d, 0x54, 0xc6, 0x2e, 0x00, -0xdf, 0x3f, 0x20, 0xbf, 0x03, 0x14, 0x55, 0xc6, -0x2e, 0x01, 0xdf, 0x3f, 0x2c, 0x10, 0x5b, 0x46, -0x2e, 0x00, 0xbf, 0x00, 0x2e, 0xdb, 0x88, 0x09, -0x78, 0x00, 0xef, 0x46, 0x2e, 0x00, 0xbf, 0x46, -0x2e, 0x01, 0xdf, 0x1f, 0x28, 0x46, 0x2e, 0x01, -0xbf, 0x00, 0x2e, 0xbc, 0x88, 0x13, 0x88, 0x05, -0x27, 0x46, 0x2e, 0x01, 0xdf, 0x1f, 0x2a, 0x46, -0x2e, 0x01, 0xbf, 0x41, 0x2e, 0xb6, 0xdf, 0x01, -0xff, 0xab, 0xef, 0x19, 0x27, 0x42, 0xff, 0x7f, -0x98, 0x9f, 0x98, 0x24, 0x28, 0x2a, 0x85, 0x24, -0x2a, 0x05, 0x27, 0x2c, 0x85, 0x05, 0x27, 0xfd, -0x0c, 0x00, 0x2e, 0xab, 0x88, 0x14, 0xef, 0x00, -0x2e, 0xef, 0x88, 0x32, 0x88, 0x3a, 0x88, 0x34, -0x88, 0x38, 0x88, 0x32, 0x88, 0x36, 0x88, 0x30, -0x88, 0x34, 0x88, 0x2e, 0x88, 0x32, 0x88, 0x46, -0x2e, 0x00, 0xdf, 0x1f, 0x9f, 0xe2, 0xef, 0x1f, -0x90, 0xe0, 0xff, 0x7f, 0x90, 0x0e, 0xef, 0x00, -0x2e, 0xe7, 0x88, 0x80, 0xef, 0x1f, 0x9f, 0x9f, -0x22, 0x1f, 0x9f, 0x1f, 0x9f, 0x1f, 0x9f, 0x1f, -0x9f, 0x1f, 0x9f, 0x1f, 0x9f, 0x01, 0xef, 0x1f, -0x9f, 0xb8, 0xef, 0x1f, 0x9f + 0x42, 0xca, 0x00, + 0x67, 0x27, 0x00, 0x2e, 0xf5, + 0x88, 0x39, 0x81, 0x84, 0x88, 0x05, 0xcf, 0xdf, + 0x22, 0x33, 0x55, 0x04, 0xcf, 0x2a, 0x1e, 0x30, + 0x55, 0xfe, 0xdf, 0xfe, 0xcf, 0x00, 0x1f, 0x1b, + 0x55, 0x00, 0x1e, 0x0d, 0x54, 0xc6, 0x2e, 0x00, + 0xdf, 0x3f, 0x20, 0xbf, 0x03, 0x14, 0x55, 0xc6, + 0x2e, 0x01, 0xdf, 0x3f, 0x2c, 0x10, 0x5b, 0x46, + 0x2e, 0x00, 0xbf, 0x00, 0x2e, 0xdb, 0x88, 0x09, + 0x78, 0x00, 0xef, 0x46, 0x2e, 0x00, 0xbf, 0x46, + 0x2e, 0x01, 0xdf, 0x1f, 0x28, 0x46, 0x2e, 0x01, + 0xbf, 0x00, 0x2e, 0xbc, 0x88, 0x13, 0x88, 0x05, + 0x27, 0x46, 0x2e, 0x01, 0xdf, 0x1f, 0x2a, 0x46, + 0x2e, 0x01, 0xbf, 0x41, 0x2e, 0xb6, 0xdf, 0x01, + 0xff, 0xab, 0xef, 0x19, 0x27, 0x42, 0xff, 0x7f, + 0x98, 0x9f, 0x98, 0x24, 0x28, 0x2a, 0x85, 0x24, + 0x2a, 0x05, 0x27, 0x2c, 0x85, 0x05, 0x27, 0xfd, + 0x0c, 0x00, 0x2e, 0xab, 0x88, 0x14, 0xef, 0x00, + 0x2e, 0xef, 0x88, 0x32, 0x88, 0x3a, 0x88, 0x34, + 0x88, 0x38, 0x88, 0x32, 0x88, 0x36, 0x88, 0x30, + 0x88, 0x34, 0x88, 0x2e, 0x88, 0x32, 0x88, 0x46, + 0x2e, 0x00, 0xdf, 0x1f, 0x9f, 0xe2, 0xef, 0x1f, + 0x90, 0xe0, 0xff, 0x7f, 0x90, 0x0e, 0xef, 0x00, + 0x2e, 0xe7, 0x88, 0x80, 0xef, 0x1f, 0x9f, 0x9f, + 0x22, 0x1f, 0x9f, 0x1f, 0x9f, 0x1f, 0x9f, 0x1f, + 0x9f, 0x1f, 0x9f, 0x1f, 0x9f, 0x01, 0xef, 0x1f, + 0x9f, 0xb8, 0xef, 0x1f, 0x9f }; static const unsigned char pkt200[] = { -0x42, 0x66, 0x00, -0xcb, 0x27, 0x00, 0x2e, 0xab, -0x88, 0x40, 0xef, 0xfc, 0x9f, 0x5f, 0x20, 0xfc, -0x55, 0x03, 0x0c, 0x01, 0x2e, 0x6e, 0x86, 0x01, -0x2e, 0x05, 0x86, 0x00, 0x2e, 0xb5, 0x88, 0x00, -0x2e, 0xb1, 0x88, 0x14, 0xef, 0x00, 0x2e, 0xb7, -0x88, 0x05, 0x27, 0x40, 0xef, 0x28, 0xff, 0x1a, -0x27, 0x05, 0x27, 0x16, 0x27, 0x04, 0x10, 0x00, -0x13, 0x1a, 0x27, 0x05, 0x27, 0xd9, 0x9f, 0x3f, -0x9f, 0xd8, 0x9f, 0x3f, 0x9f, 0xd7, 0x9f, 0x3f, -0x9f, 0xd6, 0x9f, 0x3f, 0x9f, 0x05, 0x27, 0x7f, -0xef, 0x28, 0xff, 0x46, 0x2e, 0x1d, 0xbf, 0xc6, -0x2e, 0x1c, 0xbf, 0x93, 0xef, 0x28, 0xff, 0x46, -0x2e, 0x1f, 0xbf, 0xc6, 0x2e, 0x1e, 0xbf, 0x05, -0x27 + 0x42, 0x66, 0x00, + 0xcb, 0x27, 0x00, 0x2e, 0xab, + 0x88, 0x40, 0xef, 0xfc, 0x9f, 0x5f, 0x20, 0xfc, + 0x55, 0x03, 0x0c, 0x01, 0x2e, 0x6e, 0x86, 0x01, + 0x2e, 0x05, 0x86, 0x00, 0x2e, 0xb5, 0x88, 0x00, + 0x2e, 0xb1, 0x88, 0x14, 0xef, 0x00, 0x2e, 0xb7, + 0x88, 0x05, 0x27, 0x40, 0xef, 0x28, 0xff, 0x1a, + 0x27, 0x05, 0x27, 0x16, 0x27, 0x04, 0x10, 0x00, + 0x13, 0x1a, 0x27, 0x05, 0x27, 0xd9, 0x9f, 0x3f, + 0x9f, 0xd8, 0x9f, 0x3f, 0x9f, 0xd7, 0x9f, 0x3f, + 0x9f, 0xd6, 0x9f, 0x3f, 0x9f, 0x05, 0x27, 0x7f, + 0xef, 0x28, 0xff, 0x46, 0x2e, 0x1d, 0xbf, 0xc6, + 0x2e, 0x1c, 0xbf, 0x93, 0xef, 0x28, 0xff, 0x46, + 0x2e, 0x1f, 0xbf, 0xc6, 0x2e, 0x1e, 0xbf, 0x05, + 0x27 }; static const unsigned char pkt204[] = { -0x42, 0xca, 0x00, -0xfd, 0x27, 0xfd, 0x0c, 0x00, -0x2e, 0xf5, 0x88, 0x0d, 0x84, 0x05, 0xcf, 0xdf, -0x22, 0x00, 0x2e, 0x98, 0x55, 0x04, 0xcf, 0x14, -0x1e, 0x00, 0x2e, 0x94, 0x55, 0x00, 0x2e, 0xab, -0x88, 0xbb, 0xef, 0x1f, 0x90, 0x91, 0xff, 0x7f, -0x90, 0x14, 0xef, 0x00, 0x2e, 0xe7, 0x88, 0x14, -0xef, 0x00, 0x2e, 0xef, 0x88, 0x33, 0xef, 0x1f, -0x90, 0x71, 0xff, 0x7f, 0x90, 0x18, 0xef, 0x00, -0x2e, 0xe7, 0x88, 0x00, 0x2e, 0xab, 0x88, 0x40, -0xef, 0xfc, 0x9f, 0x5f, 0x20, 0xfc, 0x55, 0x01, -0x2e, 0x6e, 0x86, 0x01, 0x2e, 0x05, 0x86, 0x00, -0x2e, 0xab, 0x88, 0x7a, 0x88, 0x0a, 0xef, 0x00, -0x2e, 0xb7, 0x88, 0x76, 0x88, 0x00, 0xff, 0x80, -0xef, 0x19, 0x27, 0x0a, 0xef, 0xdc, 0x9f, 0x7f, -0x9f, 0x5f, 0x20, 0xfb, 0x55, 0x0d, 0x84, 0x6c, -0x88, 0x0a, 0xef, 0x00, 0x2e, 0xb7, 0x88, 0x68, -0x88, 0x0a, 0xef, 0xdc, 0x9f, 0x7f, 0x9f, 0x5f, -0x20, 0xfb, 0x55, 0x5e, 0x88, 0xa4, 0x8f, 0x9e, -0x8f, 0xa2, 0x8f, 0x9c, 0x8f, 0xa0, 0x8f, 0x9a, -0x8f, 0x9e, 0x8f, 0x98, 0x8f, 0x9c, 0x8f, 0x9d, -0xef, 0x1f, 0x90, 0xda, 0xff, 0x7f, 0x90, 0x0f, -0xef, 0x00, 0x2e, 0xe7, 0x88, 0x80, 0xef, 0x1f, -0x9f, 0x9f, 0x22, 0x1f, 0x9f, 0x1f, 0x9f, 0x1f, -0x9f, 0x1f, 0x9f, 0x1f, 0x9f, 0x1f, 0x9f, 0x03, -0xef, 0x1f, 0x9f, 0xb8, 0xef, 0x1f, 0x9f, 0x00, -0x2e, 0xab, 0x88, 0x40, 0xef + 0x42, 0xca, 0x00, + 0xfd, 0x27, 0xfd, 0x0c, 0x00, + 0x2e, 0xf5, 0x88, 0x0d, 0x84, 0x05, 0xcf, 0xdf, + 0x22, 0x00, 0x2e, 0x98, 0x55, 0x04, 0xcf, 0x14, + 0x1e, 0x00, 0x2e, 0x94, 0x55, 0x00, 0x2e, 0xab, + 0x88, 0xbb, 0xef, 0x1f, 0x90, 0x91, 0xff, 0x7f, + 0x90, 0x14, 0xef, 0x00, 0x2e, 0xe7, 0x88, 0x14, + 0xef, 0x00, 0x2e, 0xef, 0x88, 0x33, 0xef, 0x1f, + 0x90, 0x71, 0xff, 0x7f, 0x90, 0x18, 0xef, 0x00, + 0x2e, 0xe7, 0x88, 0x00, 0x2e, 0xab, 0x88, 0x40, + 0xef, 0xfc, 0x9f, 0x5f, 0x20, 0xfc, 0x55, 0x01, + 0x2e, 0x6e, 0x86, 0x01, 0x2e, 0x05, 0x86, 0x00, + 0x2e, 0xab, 0x88, 0x7a, 0x88, 0x0a, 0xef, 0x00, + 0x2e, 0xb7, 0x88, 0x76, 0x88, 0x00, 0xff, 0x80, + 0xef, 0x19, 0x27, 0x0a, 0xef, 0xdc, 0x9f, 0x7f, + 0x9f, 0x5f, 0x20, 0xfb, 0x55, 0x0d, 0x84, 0x6c, + 0x88, 0x0a, 0xef, 0x00, 0x2e, 0xb7, 0x88, 0x68, + 0x88, 0x0a, 0xef, 0xdc, 0x9f, 0x7f, 0x9f, 0x5f, + 0x20, 0xfb, 0x55, 0x5e, 0x88, 0xa4, 0x8f, 0x9e, + 0x8f, 0xa2, 0x8f, 0x9c, 0x8f, 0xa0, 0x8f, 0x9a, + 0x8f, 0x9e, 0x8f, 0x98, 0x8f, 0x9c, 0x8f, 0x9d, + 0xef, 0x1f, 0x90, 0xda, 0xff, 0x7f, 0x90, 0x0f, + 0xef, 0x00, 0x2e, 0xe7, 0x88, 0x80, 0xef, 0x1f, + 0x9f, 0x9f, 0x22, 0x1f, 0x9f, 0x1f, 0x9f, 0x1f, + 0x9f, 0x1f, 0x9f, 0x1f, 0x9f, 0x1f, 0x9f, 0x03, + 0xef, 0x1f, 0x9f, 0xb8, 0xef, 0x1f, 0x9f, 0x00, + 0x2e, 0xab, 0x88, 0x40, 0xef }; static const unsigned char pkt208[] = { -0x42, 0xca, 0x00, -0x61, 0x28, 0xfc, 0x9f, 0x5f, -0x20, 0xfc, 0x55, 0x01, 0x2e, 0x05, 0x86, 0x00, -0x2e, 0xb5, 0x88, 0x72, 0x88, 0x7c, 0x8f, 0x76, -0x8f, 0x7a, 0x8f, 0x74, 0x8f, 0x78, 0x8f, 0x72, -0x8f, 0x76, 0x8f, 0x70, 0x8f, 0x74, 0x8f, 0x68, -0x88, 0x14, 0xef, 0xfc, 0x9f, 0x5f, 0x20, 0xfc, -0x55, 0x01, 0xff, 0xab, 0xef, 0x19, 0x27, 0x60, -0x88, 0x11, 0xff, 0xbf, 0x90, 0x51, 0xff, 0xc2, -0x97, 0xdf, 0x01, 0x7f, 0x98, 0xfc, 0x9f, 0xbf, -0x98, 0x24, 0x28, 0xc2, 0x9f, 0x7f, 0x20, 0xbf, -0x90, 0xf4, 0x55, 0x24, 0x2a, 0x1d, 0x88, 0x72, -0xef, 0xff, 0xaf, 0x14, 0xef, 0xff, 0xaf, 0x00, -0xef, 0xff, 0xaf, 0x00, 0xff, 0x80, 0xef, 0x19, -0x27, 0x14, 0xff, 0xfd, 0x97, 0xff, 0xaf, 0x7f, -0x20, 0xfb, 0x55, 0x00, 0x2e, 0x5f, 0x89, 0x03, -0x0c, 0x02, 0x2e, 0xdd, 0x81, 0x05, 0x27, 0x2c, -0x85, 0x05, 0x27, 0x40, 0xef, 0x28, 0xff, 0x1a, -0x27, 0x05, 0x27, 0x02, 0xef, 0x06, 0xff, 0x1a, -0x27, 0x05, 0x27, 0x01, 0xff, 0xab, 0xef, 0x19, -0x27, 0x08, 0xef, 0x1f, 0x98, 0xe4, 0x29, 0x00, -0xff, 0xff, 0x96, 0x20, 0xff, 0xff, 0x96, 0x00, -0xff, 0xff, 0x96, 0x40, 0xff, 0xff, 0x96, 0x00, -0xff, 0xff, 0x96, 0x60, 0xff, 0xff, 0x96, 0x00, -0xff, 0xff, 0x96, 0x00, 0xff, 0xff, 0x96, 0x01, -0xff, 0xff, 0x96, 0x20, 0xff, 0xff, 0x96, 0x00, -0xff, 0xff, 0x96, 0x02, 0xff + 0x42, 0xca, 0x00, + 0x61, 0x28, 0xfc, 0x9f, 0x5f, + 0x20, 0xfc, 0x55, 0x01, 0x2e, 0x05, 0x86, 0x00, + 0x2e, 0xb5, 0x88, 0x72, 0x88, 0x7c, 0x8f, 0x76, + 0x8f, 0x7a, 0x8f, 0x74, 0x8f, 0x78, 0x8f, 0x72, + 0x8f, 0x76, 0x8f, 0x70, 0x8f, 0x74, 0x8f, 0x68, + 0x88, 0x14, 0xef, 0xfc, 0x9f, 0x5f, 0x20, 0xfc, + 0x55, 0x01, 0xff, 0xab, 0xef, 0x19, 0x27, 0x60, + 0x88, 0x11, 0xff, 0xbf, 0x90, 0x51, 0xff, 0xc2, + 0x97, 0xdf, 0x01, 0x7f, 0x98, 0xfc, 0x9f, 0xbf, + 0x98, 0x24, 0x28, 0xc2, 0x9f, 0x7f, 0x20, 0xbf, + 0x90, 0xf4, 0x55, 0x24, 0x2a, 0x1d, 0x88, 0x72, + 0xef, 0xff, 0xaf, 0x14, 0xef, 0xff, 0xaf, 0x00, + 0xef, 0xff, 0xaf, 0x00, 0xff, 0x80, 0xef, 0x19, + 0x27, 0x14, 0xff, 0xfd, 0x97, 0xff, 0xaf, 0x7f, + 0x20, 0xfb, 0x55, 0x00, 0x2e, 0x5f, 0x89, 0x03, + 0x0c, 0x02, 0x2e, 0xdd, 0x81, 0x05, 0x27, 0x2c, + 0x85, 0x05, 0x27, 0x40, 0xef, 0x28, 0xff, 0x1a, + 0x27, 0x05, 0x27, 0x02, 0xef, 0x06, 0xff, 0x1a, + 0x27, 0x05, 0x27, 0x01, 0xff, 0xab, 0xef, 0x19, + 0x27, 0x08, 0xef, 0x1f, 0x98, 0xe4, 0x29, 0x00, + 0xff, 0xff, 0x96, 0x20, 0xff, 0xff, 0x96, 0x00, + 0xff, 0xff, 0x96, 0x40, 0xff, 0xff, 0x96, 0x00, + 0xff, 0xff, 0x96, 0x60, 0xff, 0xff, 0x96, 0x00, + 0xff, 0xff, 0x96, 0x00, 0xff, 0xff, 0x96, 0x01, + 0xff, 0xff, 0x96, 0x20, 0xff, 0xff, 0x96, 0x00, + 0xff, 0xff, 0x96, 0x02, 0xff }; static const unsigned char pkt212[] = { -0x42, 0x38, 0x00, -0xc5, 0x28, 0xff, 0x96, 0x02, -0xff, 0xff, 0x96, 0x82, 0xff, 0xff, 0x96, 0x02, -0xff, 0xff, 0x96, 0x05, 0x88, 0x46, 0x2e, 0x01, -0xdf, 0x9f, 0x28, 0x46, 0x2e, 0x01, 0xbf, 0x05, -0x27, 0x0f, 0xef, 0x5f, 0x98, 0xdd, 0x9f, 0xbf, -0x98, 0x24, 0x28, 0x5f, 0x20, 0xf9, 0x55, 0x24, -0x2a, 0x05, 0x27, 0x7f, 0xef, 0x28, 0xff, 0x1b, -0x27, 0x05, 0x27 + 0x42, 0x38, 0x00, + 0xc5, 0x28, 0xff, 0x96, 0x02, + 0xff, 0xff, 0x96, 0x82, 0xff, 0xff, 0x96, 0x02, + 0xff, 0xff, 0x96, 0x05, 0x88, 0x46, 0x2e, 0x01, + 0xdf, 0x9f, 0x28, 0x46, 0x2e, 0x01, 0xbf, 0x05, + 0x27, 0x0f, 0xef, 0x5f, 0x98, 0xdd, 0x9f, 0xbf, + 0x98, 0x24, 0x28, 0x5f, 0x20, 0xf9, 0x55, 0x24, + 0x2a, 0x05, 0x27, 0x7f, 0xef, 0x28, 0xff, 0x1b, + 0x27, 0x05, 0x27 }; static const unsigned char pkt216[] = { -0x42, 0xca, 0x00, -0xe0, 0x28, 0xe1, 0x97, 0xe2, -0x9f, 0x46, 0x2e, 0x28, 0xbf, 0xc6, 0x2e, 0x29, -0xbf, 0xad, 0x88, 0x0a, 0x5b, 0xe9, 0x97, 0xea, -0x9f, 0x4f, 0xaf, 0x50, 0xbf, 0x46, 0x2e, 0x28, -0xdf, 0xc6, 0x2e, 0x29, 0xdf, 0x10, 0x10, 0x00, -0x13, 0x01, 0x78, 0x03, 0x10, 0x00, 0x13, 0xff, -0x96, 0xdf, 0x96, 0xd6, 0xcf, 0xd7, 0xdf, 0x0f, -0x1d, 0x01, 0x10, 0x00, 0x13, 0xff, 0x96, 0xdf, -0x96, 0xc8, 0xdf, 0xc7, 0xcf, 0x1f, 0x1d, 0xff, -0x96, 0xdf, 0x96, 0xc2, 0x97, 0xc3, 0x9f, 0x9d, -0x01, 0x5d, 0x01, 0xf5, 0x52, 0xc3, 0x03, 0x02, -0x5e, 0xf2, 0x52, 0x82, 0x03, 0xf0, 0x52, 0x02, -0x0c, 0xf8, 0x43, 0x03, 0x5b, 0x08, 0x44, 0x01, -0x5a, 0x00, 0x2e, 0xf3, 0x8f, 0x7f, 0x88, 0x6d, -0x5b, 0x41, 0x2e, 0xaf, 0xdf, 0xdf, 0x29, 0x41, -0x2e, 0xaf, 0xbf, 0x46, 0x2e, 0x28, 0xdf, 0xc6, -0x2e, 0x29, 0xdf, 0x03, 0x16, 0x00, 0x15, 0x46, -0x2e, 0x28, 0xbf, 0xc6, 0x2e, 0x29, 0xbf, 0x15, -0x27, 0xff, 0x96, 0xdf, 0x96, 0x8d, 0x88, 0x94, -0x88, 0xcd, 0x88, 0x01, 0xff, 0xab, 0xef, 0x19, -0x27, 0x6b, 0x88, 0xbf, 0x22, 0x3f, 0x98, 0x05, -0xff, 0x7f, 0x98, 0xdd, 0x9f, 0xbf, 0x98, 0x24, -0x28, 0x04, 0xff, 0x7f, 0x98, 0xdd, 0x9f, 0xbf, -0x98, 0x24, 0x28, 0x66, 0xff, 0xbf, 0x99, 0x12, -0xff, 0x7f, 0x99, 0xdd, 0x97, 0xdd, 0x9f, 0x19, -0x27, 0xe0, 0x97, 0xff, 0xaf + 0x42, 0xca, 0x00, + 0xe0, 0x28, 0xe1, 0x97, 0xe2, + 0x9f, 0x46, 0x2e, 0x28, 0xbf, 0xc6, 0x2e, 0x29, + 0xbf, 0xad, 0x88, 0x0a, 0x5b, 0xe9, 0x97, 0xea, + 0x9f, 0x4f, 0xaf, 0x50, 0xbf, 0x46, 0x2e, 0x28, + 0xdf, 0xc6, 0x2e, 0x29, 0xdf, 0x10, 0x10, 0x00, + 0x13, 0x01, 0x78, 0x03, 0x10, 0x00, 0x13, 0xff, + 0x96, 0xdf, 0x96, 0xd6, 0xcf, 0xd7, 0xdf, 0x0f, + 0x1d, 0x01, 0x10, 0x00, 0x13, 0xff, 0x96, 0xdf, + 0x96, 0xc8, 0xdf, 0xc7, 0xcf, 0x1f, 0x1d, 0xff, + 0x96, 0xdf, 0x96, 0xc2, 0x97, 0xc3, 0x9f, 0x9d, + 0x01, 0x5d, 0x01, 0xf5, 0x52, 0xc3, 0x03, 0x02, + 0x5e, 0xf2, 0x52, 0x82, 0x03, 0xf0, 0x52, 0x02, + 0x0c, 0xf8, 0x43, 0x03, 0x5b, 0x08, 0x44, 0x01, + 0x5a, 0x00, 0x2e, 0xf3, 0x8f, 0x7f, 0x88, 0x6d, + 0x5b, 0x41, 0x2e, 0xaf, 0xdf, 0xdf, 0x29, 0x41, + 0x2e, 0xaf, 0xbf, 0x46, 0x2e, 0x28, 0xdf, 0xc6, + 0x2e, 0x29, 0xdf, 0x03, 0x16, 0x00, 0x15, 0x46, + 0x2e, 0x28, 0xbf, 0xc6, 0x2e, 0x29, 0xbf, 0x15, + 0x27, 0xff, 0x96, 0xdf, 0x96, 0x8d, 0x88, 0x94, + 0x88, 0xcd, 0x88, 0x01, 0xff, 0xab, 0xef, 0x19, + 0x27, 0x6b, 0x88, 0xbf, 0x22, 0x3f, 0x98, 0x05, + 0xff, 0x7f, 0x98, 0xdd, 0x9f, 0xbf, 0x98, 0x24, + 0x28, 0x04, 0xff, 0x7f, 0x98, 0xdd, 0x9f, 0xbf, + 0x98, 0x24, 0x28, 0x66, 0xff, 0xbf, 0x99, 0x12, + 0xff, 0x7f, 0x99, 0xdd, 0x97, 0xdd, 0x9f, 0x19, + 0x27, 0xe0, 0x97, 0xff, 0xaf }; static const unsigned char pkt220[] = { -0x42, 0xca, 0x00, -0x44, 0x29, 0x46, 0x2e, 0x28, -0xdf, 0xc6, 0x2e, 0x29, 0xdf, 0x13, 0x10, 0x00, -0x13, 0xff, 0xaf, 0xff, 0xbf, 0xe3, 0x97, 0xff, -0xaf, 0xe4, 0x97, 0xff, 0xaf, 0xe5, 0x97, 0xff, -0xaf, 0xef, 0x88, 0x06, 0x0d, 0xdd, 0x97, 0xdd, -0x9f, 0x46, 0x2e, 0x28, 0xdf, 0xc6, 0x2e, 0x29, -0xdf, 0x06, 0xaf, 0x4e, 0xbf, 0xff, 0x22, 0x11, -0x54, 0x15, 0x27, 0x1a, 0x27, 0x01, 0xff, 0xab, -0xef, 0x19, 0x27, 0xdc, 0x97, 0xdf, 0x99, 0x28, -0x28, 0x0f, 0x27, 0x68, 0x2c, 0xfd, 0x5b, 0xe9, -0x97, 0xff, 0xaf, 0x6a, 0x28, 0x06, 0x25, 0xf4, -0x53, 0x4e, 0x25, 0xf2, 0x55, 0xdc, 0x97, 0xdf, -0x99, 0x28, 0x28, 0x0f, 0x27, 0x68, 0x2c, 0xfd, -0x5b, 0xe9, 0x97, 0xff, 0xaf, 0x6a, 0x28, 0x06, -0x25, 0xf4, 0x55, 0x41, 0x2e, 0xaf, 0xdf, 0xdf, -0x2b, 0x41, 0x2e, 0xaf, 0xbf, 0xbf, 0x22, 0xbf, -0x99, 0x7f, 0x99, 0x05, 0x27, 0xdd, 0x97, 0xdd, -0x9f, 0x06, 0xaf, 0x4e, 0xbf, 0xff, 0x22, 0x05, -0x54, 0xfd, 0x97, 0xff, 0xaf, 0x06, 0x25, 0xfb, -0x53, 0x4e, 0x25, 0xf9, 0x55, 0xfd, 0x97, 0xff, -0xaf, 0x06, 0x25, 0xfb, 0x55, 0x05, 0x27, 0xff, -0x96, 0xc6, 0x2e, 0x01, 0xdf, 0xbf, 0x2c, 0xdd, -0x9f, 0x05, 0x27, 0xc6, 0x2e, 0x28, 0xdf, 0x0f, -0x1d, 0x04, 0x55, 0x0b, 0x88, 0xff, 0x96, 0x10, -0xef, 0xdf, 0x96, 0x06, 0x50, 0x06, 0x88, 0x3f, -0x20, 0xff, 0x96, 0xc6, 0x2e + 0x42, 0xca, 0x00, + 0x44, 0x29, 0x46, 0x2e, 0x28, + 0xdf, 0xc6, 0x2e, 0x29, 0xdf, 0x13, 0x10, 0x00, + 0x13, 0xff, 0xaf, 0xff, 0xbf, 0xe3, 0x97, 0xff, + 0xaf, 0xe4, 0x97, 0xff, 0xaf, 0xe5, 0x97, 0xff, + 0xaf, 0xef, 0x88, 0x06, 0x0d, 0xdd, 0x97, 0xdd, + 0x9f, 0x46, 0x2e, 0x28, 0xdf, 0xc6, 0x2e, 0x29, + 0xdf, 0x06, 0xaf, 0x4e, 0xbf, 0xff, 0x22, 0x11, + 0x54, 0x15, 0x27, 0x1a, 0x27, 0x01, 0xff, 0xab, + 0xef, 0x19, 0x27, 0xdc, 0x97, 0xdf, 0x99, 0x28, + 0x28, 0x0f, 0x27, 0x68, 0x2c, 0xfd, 0x5b, 0xe9, + 0x97, 0xff, 0xaf, 0x6a, 0x28, 0x06, 0x25, 0xf4, + 0x53, 0x4e, 0x25, 0xf2, 0x55, 0xdc, 0x97, 0xdf, + 0x99, 0x28, 0x28, 0x0f, 0x27, 0x68, 0x2c, 0xfd, + 0x5b, 0xe9, 0x97, 0xff, 0xaf, 0x6a, 0x28, 0x06, + 0x25, 0xf4, 0x55, 0x41, 0x2e, 0xaf, 0xdf, 0xdf, + 0x2b, 0x41, 0x2e, 0xaf, 0xbf, 0xbf, 0x22, 0xbf, + 0x99, 0x7f, 0x99, 0x05, 0x27, 0xdd, 0x97, 0xdd, + 0x9f, 0x06, 0xaf, 0x4e, 0xbf, 0xff, 0x22, 0x05, + 0x54, 0xfd, 0x97, 0xff, 0xaf, 0x06, 0x25, 0xfb, + 0x53, 0x4e, 0x25, 0xf9, 0x55, 0xfd, 0x97, 0xff, + 0xaf, 0x06, 0x25, 0xfb, 0x55, 0x05, 0x27, 0xff, + 0x96, 0xc6, 0x2e, 0x01, 0xdf, 0xbf, 0x2c, 0xdd, + 0x9f, 0x05, 0x27, 0xc6, 0x2e, 0x28, 0xdf, 0x0f, + 0x1d, 0x04, 0x55, 0x0b, 0x88, 0xff, 0x96, 0x10, + 0xef, 0xdf, 0x96, 0x06, 0x50, 0x06, 0x88, 0x3f, + 0x20, 0xff, 0x96, 0xc6, 0x2e }; static const unsigned char pkt224[] = { -0x42, 0xca, 0x00, -0xa8, 0x29, 0x28, 0xdf, 0x0f, -0x1d, 0xff, 0x96, 0x05, 0x27, 0x46, 0x2e, 0x28, -0xdf, 0xf0, 0x1c, 0x09, 0x27, 0xdf, 0x9f, 0x46, -0x2e, 0x29, 0xdf, 0x0f, 0x1c, 0x09, 0x27, 0x5f, -0x02, 0x05, 0x27, 0x78, 0x88, 0x6f, 0x88, 0x0a, -0xef, 0xdc, 0x9f, 0x3f, 0x9f, 0x5f, 0x20, 0xfb, -0x55, 0x05, 0x27, 0x9f, 0x22, 0x41, 0x2e, 0xab, -0xbf, 0x50, 0xef, 0xdf, 0x96, 0x3a, 0xef, 0xdf, -0x96, 0x29, 0x88, 0x68, 0x88, 0x0a, 0xef, 0xfc, -0x9f, 0xc1, 0x2e, 0xad, 0xbf, 0xc1, 0x2e, 0xac, -0xdf, 0x3f, 0x20, 0xc1, 0x2e, 0xac, 0xbf, 0x6a, -0x88, 0x5f, 0x20, 0xf4, 0x55, 0x5b, 0xef, 0xdf, -0x96, 0x50, 0xcf, 0xdf, 0x96, 0x17, 0x88, 0x5c, -0xef, 0xdf, 0x96, 0x4f, 0xcf, 0xdf, 0x96, 0x12, -0x88, 0x5d, 0xef, 0xdf, 0x96, 0x9f, 0x22, 0xdf, -0x96, 0x0d, 0x88, 0x5e, 0xef, 0xdf, 0x96, 0x46, -0x2e, 0x29, 0xdf, 0xdf, 0x96, 0x07, 0x88, 0x5f, -0xef, 0xdf, 0x96, 0x46, 0x2e, 0x28, 0xdf, 0xdf, -0x96, 0x01, 0x88, 0x0f, 0x27, 0x05, 0x27, 0xdd, -0x97, 0x41, 0x2e, 0xad, 0xbf, 0xdd, 0x97, 0x41, -0x2e, 0xac, 0xbf, 0x44, 0x88, 0x05, 0x27, 0x9f, -0x22, 0x41, 0x2e, 0xab, 0xbf, 0x10, 0xef, 0xdf, -0x96, 0x02, 0xef, 0xdf, 0x96, 0xef, 0x8f, 0x2e, -0x88, 0x0a, 0xef, 0xfc, 0x9f, 0xc1, 0x2e, 0xad, -0xbf, 0xc1, 0x2e, 0xac, 0xdf, 0x3f, 0x20, 0xc1, -0x2e, 0xac, 0xbf, 0x30, 0x88 + 0x42, 0xca, 0x00, + 0xa8, 0x29, 0x28, 0xdf, 0x0f, + 0x1d, 0xff, 0x96, 0x05, 0x27, 0x46, 0x2e, 0x28, + 0xdf, 0xf0, 0x1c, 0x09, 0x27, 0xdf, 0x9f, 0x46, + 0x2e, 0x29, 0xdf, 0x0f, 0x1c, 0x09, 0x27, 0x5f, + 0x02, 0x05, 0x27, 0x78, 0x88, 0x6f, 0x88, 0x0a, + 0xef, 0xdc, 0x9f, 0x3f, 0x9f, 0x5f, 0x20, 0xfb, + 0x55, 0x05, 0x27, 0x9f, 0x22, 0x41, 0x2e, 0xab, + 0xbf, 0x50, 0xef, 0xdf, 0x96, 0x3a, 0xef, 0xdf, + 0x96, 0x29, 0x88, 0x68, 0x88, 0x0a, 0xef, 0xfc, + 0x9f, 0xc1, 0x2e, 0xad, 0xbf, 0xc1, 0x2e, 0xac, + 0xdf, 0x3f, 0x20, 0xc1, 0x2e, 0xac, 0xbf, 0x6a, + 0x88, 0x5f, 0x20, 0xf4, 0x55, 0x5b, 0xef, 0xdf, + 0x96, 0x50, 0xcf, 0xdf, 0x96, 0x17, 0x88, 0x5c, + 0xef, 0xdf, 0x96, 0x4f, 0xcf, 0xdf, 0x96, 0x12, + 0x88, 0x5d, 0xef, 0xdf, 0x96, 0x9f, 0x22, 0xdf, + 0x96, 0x0d, 0x88, 0x5e, 0xef, 0xdf, 0x96, 0x46, + 0x2e, 0x29, 0xdf, 0xdf, 0x96, 0x07, 0x88, 0x5f, + 0xef, 0xdf, 0x96, 0x46, 0x2e, 0x28, 0xdf, 0xdf, + 0x96, 0x01, 0x88, 0x0f, 0x27, 0x05, 0x27, 0xdd, + 0x97, 0x41, 0x2e, 0xad, 0xbf, 0xdd, 0x97, 0x41, + 0x2e, 0xac, 0xbf, 0x44, 0x88, 0x05, 0x27, 0x9f, + 0x22, 0x41, 0x2e, 0xab, 0xbf, 0x10, 0xef, 0xdf, + 0x96, 0x02, 0xef, 0xdf, 0x96, 0xef, 0x8f, 0x2e, + 0x88, 0x0a, 0xef, 0xfc, 0x9f, 0xc1, 0x2e, 0xad, + 0xbf, 0xc1, 0x2e, 0xac, 0xdf, 0x3f, 0x20, 0xc1, + 0x2e, 0xac, 0xbf, 0x30, 0x88 }; static const unsigned char pkt228[] = { -0x42, 0x9a, 0x00, -0x0c, 0x2a, 0x5f, 0x20, 0xf4, -0x55, 0x1b, 0xef, 0xdf, 0x96, 0x50, 0xcf, 0xdf, -0x96, 0xdd, 0x8f, 0x1c, 0xef, 0xdf, 0x96, 0x4f, -0xcf, 0xdf, 0x96, 0xd8, 0x8f, 0x1d, 0xef, 0xdf, -0x96, 0x9f, 0x22, 0xdf, 0x96, 0xd3, 0x8f, 0x1e, -0xef, 0xdf, 0x96, 0x9f, 0x22, 0xdf, 0x96, 0xce, -0x8f, 0x1f, 0xef, 0xdf, 0x96, 0x01, 0xef, 0xdf, -0x96, 0xc9, 0x8f, 0x0f, 0x27, 0x05, 0x27, 0x02, -0xef, 0x06, 0xff, 0x1a, 0x27, 0x05, 0x27, 0x02, -0xef, 0x06, 0xff, 0x1a, 0x27, 0x05, 0x27, 0xdf, -0x96, 0xff, 0x96, 0x7b, 0xef, 0x00, 0xff, 0x1b, -0x27, 0xdd, 0x9f, 0xdd, 0x97, 0x05, 0x27, 0x01, -0xff, 0xab, 0xef, 0x1b, 0x27, 0x05, 0x27, 0xdf, -0x96, 0x81, 0xef, 0x41, 0x2e, 0xaf, 0xbf, 0xdd, -0x97, 0x05, 0x27, 0x3a, 0xef, 0xff, 0xaf, 0xea, -0x8f, 0x0a, 0xef, 0xfc, 0x9f, 0xff, 0xbf, 0x5f, -0x20, 0xfb, 0x55, 0x50, 0xcf, 0xff, 0xaf, 0x4f, -0xcf, 0xff, 0xaf, 0x9f, 0x22, 0xff, 0xaf, 0x46, -0x2e, 0x29, 0xdf, 0xff, 0xaf, 0x46, 0x2e, 0x28, -0xdf, 0xff, 0xaf, 0x05, 0x27 + 0x42, 0x9a, 0x00, + 0x0c, 0x2a, 0x5f, 0x20, 0xf4, + 0x55, 0x1b, 0xef, 0xdf, 0x96, 0x50, 0xcf, 0xdf, + 0x96, 0xdd, 0x8f, 0x1c, 0xef, 0xdf, 0x96, 0x4f, + 0xcf, 0xdf, 0x96, 0xd8, 0x8f, 0x1d, 0xef, 0xdf, + 0x96, 0x9f, 0x22, 0xdf, 0x96, 0xd3, 0x8f, 0x1e, + 0xef, 0xdf, 0x96, 0x9f, 0x22, 0xdf, 0x96, 0xce, + 0x8f, 0x1f, 0xef, 0xdf, 0x96, 0x01, 0xef, 0xdf, + 0x96, 0xc9, 0x8f, 0x0f, 0x27, 0x05, 0x27, 0x02, + 0xef, 0x06, 0xff, 0x1a, 0x27, 0x05, 0x27, 0x02, + 0xef, 0x06, 0xff, 0x1a, 0x27, 0x05, 0x27, 0xdf, + 0x96, 0xff, 0x96, 0x7b, 0xef, 0x00, 0xff, 0x1b, + 0x27, 0xdd, 0x9f, 0xdd, 0x97, 0x05, 0x27, 0x01, + 0xff, 0xab, 0xef, 0x1b, 0x27, 0x05, 0x27, 0xdf, + 0x96, 0x81, 0xef, 0x41, 0x2e, 0xaf, 0xbf, 0xdd, + 0x97, 0x05, 0x27, 0x3a, 0xef, 0xff, 0xaf, 0xea, + 0x8f, 0x0a, 0xef, 0xfc, 0x9f, 0xff, 0xbf, 0x5f, + 0x20, 0xfb, 0x55, 0x50, 0xcf, 0xff, 0xaf, 0x4f, + 0xcf, 0xff, 0xaf, 0x9f, 0x22, 0xff, 0xaf, 0x46, + 0x2e, 0x29, 0xdf, 0xff, 0xaf, 0x46, 0x2e, 0x28, + 0xdf, 0xff, 0xaf, 0x05, 0x27 }; static const unsigned char pkt232[] = { -0x42, 0x18, 0x00, -0x58, 0x2a, 0xd3, 0x45, 0x03, -0x5a, 0x0f, 0x27, 0xd3, 0x45, 0x00, 0x5a, 0x05, -0x27, 0xd0, 0x41, 0xf7, 0x5b, 0xc1, 0x83, 0xf5, -0x50, 0x05, 0x27 + 0x42, 0x18, 0x00, + 0x58, 0x2a, 0xd3, 0x45, 0x03, + 0x5a, 0x0f, 0x27, 0xd3, 0x45, 0x00, 0x5a, 0x05, + 0x27, 0xd0, 0x41, 0xf7, 0x5b, 0xc1, 0x83, 0xf5, + 0x50, 0x05, 0x27 }; static const unsigned char pkt236[] = { -0x42, 0x22, 0x00, -0x63, 0x2a, 0xc8, 0x46, 0x0c, -0x5b, 0xd3, 0x45, 0xfd, 0x5a, 0xd3, 0x45, 0xfb, -0x5a, 0xd3, 0x45, 0xf9, 0x5a, 0x41, 0x2e, 0xa1, -0xdf, 0x9f, 0x28, 0x41, 0x2e, 0xa1, 0xbf, 0x02, -0x2e, 0xdd, 0x81, 0x05, 0x27 + 0x42, 0x22, 0x00, + 0x63, 0x2a, 0xc8, 0x46, 0x0c, + 0x5b, 0xd3, 0x45, 0xfd, 0x5a, 0xd3, 0x45, 0xfb, + 0x5a, 0xd3, 0x45, 0xf9, 0x5a, 0x41, 0x2e, 0xa1, + 0xdf, 0x9f, 0x28, 0x41, 0x2e, 0xa1, 0xbf, 0x02, + 0x2e, 0xdd, 0x81, 0x05, 0x27 }; static const unsigned char pkt240[] = { -0x42, 0x50, 0x00, -0x73, 0x2a, 0x07, 0x3d, 0x02, -0x5b, 0x6c, 0x86, 0xc2, 0x23, 0xd3, 0x3c, 0x02, -0x44, 0xd8, 0x2f, 0x1d, 0x5a, 0x02, 0x45, 0xd8, -0x2f, 0x7e, 0x5b, 0x58, 0x23, 0x3c, 0x26, 0x02, -0x55, 0x02, 0x2e, 0x31, 0x84, 0x01, 0x50, 0x02, -0x2e, 0x80, 0x84, 0x07, 0x45, 0xea, 0x5a, 0x41, -0x2e, 0x53, 0xdf, 0xc1, 0x2e, 0x79, 0xdf, 0xff, -0x96, 0xdf, 0x96, 0x41, 0x2e, 0x55, 0xdf, 0xc1, -0x2e, 0x78, 0xdf, 0x9d, 0x01, 0x5d, 0x01, 0xff, -0x22, 0x00, 0x54, 0xff, 0xef, 0x2e, 0xaf, 0xd8, -0x2f, 0x62, 0x50 + 0x42, 0x50, 0x00, + 0x73, 0x2a, 0x07, 0x3d, 0x02, + 0x5b, 0x6c, 0x86, 0xc2, 0x23, 0xd3, 0x3c, 0x02, + 0x44, 0xd8, 0x2f, 0x1d, 0x5a, 0x02, 0x45, 0xd8, + 0x2f, 0x7e, 0x5b, 0x58, 0x23, 0x3c, 0x26, 0x02, + 0x55, 0x02, 0x2e, 0x31, 0x84, 0x01, 0x50, 0x02, + 0x2e, 0x80, 0x84, 0x07, 0x45, 0xea, 0x5a, 0x41, + 0x2e, 0x53, 0xdf, 0xc1, 0x2e, 0x79, 0xdf, 0xff, + 0x96, 0xdf, 0x96, 0x41, 0x2e, 0x55, 0xdf, 0xc1, + 0x2e, 0x78, 0xdf, 0x9d, 0x01, 0x5d, 0x01, 0xff, + 0x22, 0x00, 0x54, 0xff, 0xef, 0x2e, 0xaf, 0xd8, + 0x2f, 0x62, 0x50 }; static const unsigned char pkt244[] = { -0x67, 0x05, 0x00, 0x00, 0x02, 0x2e, 0x00, 0x70, -0x67, 0x05, 0x00, 0x01, 0x02, 0x2e, 0xe5, 0x71, -0x67, 0x05, 0x00, 0x02, 0x02, 0x2e, 0xa9, 0x72, -0x67, 0x05, 0x00, 0x08, 0x02, 0x2e, 0xb4, 0x73, -0x67, 0x05, 0x00, 0x07, 0x02, 0x2e, 0x29, 0x74, -0x67, 0x05, 0x00, 0x0d, 0x02, 0x2e, 0x26, 0x75, -0x67, 0x05, 0x00, 0x03, 0x02, 0x2e, 0x4d, 0x75, -0x67, 0x05, 0x00, 0x0e, 0x02, 0x2e, 0x29, 0x77, -0x5a, 0x05, 0x00, 0x00, 0xaa, 0x08, 0x67, 0x27, -0x5a, 0x05, 0x00, 0x01, 0xf4, 0x08, 0xfd, 0x27, -0x67, 0x05, 0x00, 0x09, 0x02, 0x2e, 0xe0, 0x78, -0x5a, 0x05, 0x00, 0x02, 0x82, 0x09, 0x58, 0x2a, -0x5a, 0x05, 0x00, 0x03, 0x78, 0x09, 0x63, 0x2a, -0x5a, 0x05, 0x00, 0x04, 0xe1, 0x02, 0x73, 0x2a, -0x0d, -0x42, 0x04, 0x00, 0x73, 0x2a, 0x07, 0x3d + 0x67, 0x05, 0x00, 0x00, 0x02, 0x2e, 0x00, 0x70, + 0x67, 0x05, 0x00, 0x01, 0x02, 0x2e, 0xe5, 0x71, + 0x67, 0x05, 0x00, 0x02, 0x02, 0x2e, 0xa9, 0x72, + 0x67, 0x05, 0x00, 0x08, 0x02, 0x2e, 0xb4, 0x73, + 0x67, 0x05, 0x00, 0x07, 0x02, 0x2e, 0x29, 0x74, + 0x67, 0x05, 0x00, 0x0d, 0x02, 0x2e, 0x26, 0x75, + 0x67, 0x05, 0x00, 0x03, 0x02, 0x2e, 0x4d, 0x75, + 0x67, 0x05, 0x00, 0x0e, 0x02, 0x2e, 0x29, 0x77, + 0x5a, 0x05, 0x00, 0x00, 0xaa, 0x08, 0x67, 0x27, + 0x5a, 0x05, 0x00, 0x01, 0xf4, 0x08, 0xfd, 0x27, + 0x67, 0x05, 0x00, 0x09, 0x02, 0x2e, 0xe0, 0x78, + 0x5a, 0x05, 0x00, 0x02, 0x82, 0x09, 0x58, 0x2a, + 0x5a, 0x05, 0x00, 0x03, 0x78, 0x09, 0x63, 0x2a, + 0x5a, 0x05, 0x00, 0x04, 0xe1, 0x02, 0x73, 0x2a, + 0x0d, + 0x42, 0x04, 0x00, 0x73, 0x2a, 0x07, 0x3d }; struct aesX660_cmd aes1660_init_1[] = { - { .cmd = pkt107, .len = sizeof(pkt107) }, - { .cmd = pkt112, .len = sizeof(pkt112) }, - { .cmd = pkt116, .len = sizeof(pkt116) }, - { .cmd = pkt120, .len = sizeof(pkt120) }, - { .cmd = pkt124, .len = sizeof(pkt124) }, - { .cmd = pkt128, .len = sizeof(pkt128) }, - { .cmd = pkt133, .len = sizeof(pkt133) }, - { .cmd = pkt136, .len = sizeof(pkt136) }, - { .cmd = pkt140, .len = sizeof(pkt140) }, - { .cmd = pkt144, .len = sizeof(pkt144) }, - { .cmd = pkt148, .len = sizeof(pkt148) }, - { .cmd = pkt152, .len = sizeof(pkt152) }, - { .cmd = pkt156, .len = sizeof(pkt156) }, - { .cmd = pkt160, .len = sizeof(pkt160) }, - { .cmd = pkt164, .len = sizeof(pkt164) }, - { .cmd = pkt168, .len = sizeof(pkt168) }, - { .cmd = pkt172, .len = sizeof(pkt172) }, - { .cmd = pkt176, .len = sizeof(pkt176) }, - { .cmd = pkt180, .len = sizeof(pkt180) }, - { .cmd = pkt184, .len = sizeof(pkt184) }, - { .cmd = pkt188, .len = sizeof(pkt188) }, - { .cmd = pkt192, .len = sizeof(pkt192) }, - { .cmd = pkt196, .len = sizeof(pkt196) }, - { .cmd = pkt200, .len = sizeof(pkt200) }, - { .cmd = pkt204, .len = sizeof(pkt204) }, - { .cmd = pkt208, .len = sizeof(pkt208) }, - { .cmd = pkt212, .len = sizeof(pkt212) }, - { .cmd = pkt216, .len = sizeof(pkt216) }, - { .cmd = pkt220, .len = sizeof(pkt220) }, - { .cmd = pkt224, .len = sizeof(pkt224) }, - { .cmd = pkt228, .len = sizeof(pkt228) }, - { .cmd = pkt232, .len = sizeof(pkt232) }, - { .cmd = pkt236, .len = sizeof(pkt236) }, - { .cmd = pkt240, .len = sizeof(pkt240) }, - { .cmd = pkt244, .len = sizeof(pkt244) }, + { .cmd = pkt107, .len = sizeof (pkt107) }, + { .cmd = pkt112, .len = sizeof (pkt112) }, + { .cmd = pkt116, .len = sizeof (pkt116) }, + { .cmd = pkt120, .len = sizeof (pkt120) }, + { .cmd = pkt124, .len = sizeof (pkt124) }, + { .cmd = pkt128, .len = sizeof (pkt128) }, + { .cmd = pkt133, .len = sizeof (pkt133) }, + { .cmd = pkt136, .len = sizeof (pkt136) }, + { .cmd = pkt140, .len = sizeof (pkt140) }, + { .cmd = pkt144, .len = sizeof (pkt144) }, + { .cmd = pkt148, .len = sizeof (pkt148) }, + { .cmd = pkt152, .len = sizeof (pkt152) }, + { .cmd = pkt156, .len = sizeof (pkt156) }, + { .cmd = pkt160, .len = sizeof (pkt160) }, + { .cmd = pkt164, .len = sizeof (pkt164) }, + { .cmd = pkt168, .len = sizeof (pkt168) }, + { .cmd = pkt172, .len = sizeof (pkt172) }, + { .cmd = pkt176, .len = sizeof (pkt176) }, + { .cmd = pkt180, .len = sizeof (pkt180) }, + { .cmd = pkt184, .len = sizeof (pkt184) }, + { .cmd = pkt188, .len = sizeof (pkt188) }, + { .cmd = pkt192, .len = sizeof (pkt192) }, + { .cmd = pkt196, .len = sizeof (pkt196) }, + { .cmd = pkt200, .len = sizeof (pkt200) }, + { .cmd = pkt204, .len = sizeof (pkt204) }, + { .cmd = pkt208, .len = sizeof (pkt208) }, + { .cmd = pkt212, .len = sizeof (pkt212) }, + { .cmd = pkt216, .len = sizeof (pkt216) }, + { .cmd = pkt220, .len = sizeof (pkt220) }, + { .cmd = pkt224, .len = sizeof (pkt224) }, + { .cmd = pkt228, .len = sizeof (pkt228) }, + { .cmd = pkt232, .len = sizeof (pkt232) }, + { .cmd = pkt236, .len = sizeof (pkt236) }, + { .cmd = pkt240, .len = sizeof (pkt240) }, + { .cmd = pkt244, .len = sizeof (pkt244) }, }; /* INIT1 is over, 0x07 cmd returns @@ -944,1034 +944,1034 @@ struct aesX660_cmd aes1660_init_1[] = { /* Second init sequence * INIT2 */ static const unsigned char pkt433[] = { -0x0d, -0x23, -0x42, 0xca, 0x00, -0x00, 0x20, 0x23, -0xff, 0x3f, 0x1d, 0x40, 0x19, 0xc1, 0x2e, 0xa3, -0xbf, 0xc2, 0x2e, 0x00, 0xdf, 0xff, 0x2d, 0x02, -0x5a, 0xbf, 0x22, 0xc1, 0x2e, 0xa3, 0xbf, 0x02, -0xcf, 0x0f, 0x1c, 0x10, 0x18, 0x26, 0x83, 0xc8, -0x46, 0x00, 0x5b, 0x01, 0x0c, 0x57, 0x23, 0x3c, -0x23, 0xf9, 0x34, 0x6b, 0x81, 0x64, 0xef, 0x64, -0xaf, 0xdf, 0xef, 0x27, 0xff, 0xd6, 0xaf, 0xd7, -0xbf, 0x46, 0xef, 0x46, 0xaf, 0x2a, 0xef, 0x2a, -0xaf, 0x05, 0x81, 0x05, 0x27, 0x9c, 0xcf, 0xdf, -0x96, 0xfe, 0xef, 0x27, 0xff, 0x19, 0x27, 0x65, -0xdf, 0xe1, 0x22, 0x1c, 0x55, 0xe0, 0x97, 0xbf, -0x03, 0x19, 0x5e, 0xfe, 0x0c, 0x9f, 0x22, 0x0f, -0xff, 0xe1, 0x22, 0x10, 0x55, 0x20, 0x00, 0x0e, -0x52, 0x82, 0x03, 0x03, 0x53, 0xfe, 0x0d, 0x7f, -0x20, 0xf6, 0x55, 0x08, 0x50, 0x5f, 0x90, 0x82, -0x01, 0x1f, 0x90, 0xc1, 0x97, 0xa0, 0x01, 0x82, -0x01, 0xdf, 0x21, 0x80, 0x03, 0x00, 0x5e, 0x3f, -0x20, 0x29, 0xbf, 0x03, 0x0c, 0x05, 0x27, 0x01, -0x0c, 0x10, 0xff, 0x29, 0xbf, 0x05, 0x27, 0x9a, -0xcf, 0xdf, 0x96, 0xe0, 0xef, 0x27, 0xff, 0x19, -0x27, 0xfe, 0x0c, 0x9f, 0x22, 0x00, 0xff, 0xe1, -0x22, 0x10, 0x55, 0x20, 0x00, 0x0e, 0x52, 0x82, -0x03, 0x03, 0x53, 0x02, 0x0d, 0x3f, 0x20, 0x0f, -0x1f, 0xf5, 0x55, 0x5f, 0x90, 0x82, 0x01, 0x1f, -0x90, 0xc1, 0x97, 0xa0, 0x01, 0x82, 0x01 + 0x0d, + 0x23, + 0x42, 0xca, 0x00, + 0x00, 0x20, 0x23, + 0xff, 0x3f, 0x1d, 0x40, 0x19, 0xc1, 0x2e, 0xa3, + 0xbf, 0xc2, 0x2e, 0x00, 0xdf, 0xff, 0x2d, 0x02, + 0x5a, 0xbf, 0x22, 0xc1, 0x2e, 0xa3, 0xbf, 0x02, + 0xcf, 0x0f, 0x1c, 0x10, 0x18, 0x26, 0x83, 0xc8, + 0x46, 0x00, 0x5b, 0x01, 0x0c, 0x57, 0x23, 0x3c, + 0x23, 0xf9, 0x34, 0x6b, 0x81, 0x64, 0xef, 0x64, + 0xaf, 0xdf, 0xef, 0x27, 0xff, 0xd6, 0xaf, 0xd7, + 0xbf, 0x46, 0xef, 0x46, 0xaf, 0x2a, 0xef, 0x2a, + 0xaf, 0x05, 0x81, 0x05, 0x27, 0x9c, 0xcf, 0xdf, + 0x96, 0xfe, 0xef, 0x27, 0xff, 0x19, 0x27, 0x65, + 0xdf, 0xe1, 0x22, 0x1c, 0x55, 0xe0, 0x97, 0xbf, + 0x03, 0x19, 0x5e, 0xfe, 0x0c, 0x9f, 0x22, 0x0f, + 0xff, 0xe1, 0x22, 0x10, 0x55, 0x20, 0x00, 0x0e, + 0x52, 0x82, 0x03, 0x03, 0x53, 0xfe, 0x0d, 0x7f, + 0x20, 0xf6, 0x55, 0x08, 0x50, 0x5f, 0x90, 0x82, + 0x01, 0x1f, 0x90, 0xc1, 0x97, 0xa0, 0x01, 0x82, + 0x01, 0xdf, 0x21, 0x80, 0x03, 0x00, 0x5e, 0x3f, + 0x20, 0x29, 0xbf, 0x03, 0x0c, 0x05, 0x27, 0x01, + 0x0c, 0x10, 0xff, 0x29, 0xbf, 0x05, 0x27, 0x9a, + 0xcf, 0xdf, 0x96, 0xe0, 0xef, 0x27, 0xff, 0x19, + 0x27, 0xfe, 0x0c, 0x9f, 0x22, 0x00, 0xff, 0xe1, + 0x22, 0x10, 0x55, 0x20, 0x00, 0x0e, 0x52, 0x82, + 0x03, 0x03, 0x53, 0x02, 0x0d, 0x3f, 0x20, 0x0f, + 0x1f, 0xf5, 0x55, 0x5f, 0x90, 0x82, 0x01, 0x1f, + 0x90, 0xc1, 0x97, 0xa0, 0x01, 0x82, 0x01 }; static const unsigned char pkt440[] = { -0x42, 0xca, 0x00, -0x64, 0x20, 0xdf, 0x21, 0x80, -0x03, 0x02, 0x5e, 0x7f, 0x20, 0x00, 0x53, 0xbf, -0x22, 0x29, 0xcf, 0xbf, 0x03, 0x01, 0x5e, 0x5f, -0x20, 0xdf, 0x9f, 0x28, 0xbf, 0x03, 0x0c, 0x05, -0x27, 0x24, 0xcf, 0x10, 0xdf, 0xbf, 0x01, 0x06, -0x1e, 0xe2, 0x2f, 0x13, 0x5c, 0xdf, 0x2d, 0x00, -0x5b, 0x9f, 0x22, 0xdf, 0x96, 0x9b, 0xef, 0x20, -0xff, 0x1d, 0x00, 0x00, 0x13, 0x1a, 0x27, 0x07, -0x27, 0x9b, 0x22, 0xdf, 0x96, 0xbb, 0xcf, 0x1a, -0x88, 0xbb, 0xcf, 0x1b, 0x88, 0x01, 0x0f, 0xbc, -0xcf, 0x15, 0x88, 0xbc, 0xcf, 0x16, 0x88, 0x01, -0x0f, 0xbd, 0xcf, 0x10, 0x88, 0xbd, 0xcf, 0x11, -0x88, 0x01, 0x0f, 0xbe, 0xcf, 0x0b, 0x88, 0xbe, -0xcf, 0x0c, 0x88, 0x01, 0x0c, 0xdd, 0x97, 0x25, -0xaf, 0x05, 0x27, 0xff, 0x00, 0xab, 0x00, 0x72, -0x00, 0x4c, 0x00, 0x33, 0x00, 0x22, 0x00, 0x09, -0x88, 0xbf, 0x9d, 0x05, 0x27, 0x09, 0x27, 0x05, -0x88, 0xff, 0x97, 0x09, 0x27, 0xf6, 0x9f, 0x5f, -0x02, 0xbf, 0x9d, 0x05, 0x27, 0x0f, 0x1c, 0xc0, -0x9f, 0x8a, 0x80, 0x80, 0x10, 0x00, 0x13, 0x0f, -0x1d, 0xc1, 0x03, 0x00, 0x5f, 0x7f, 0x90, 0x05, -0x27, 0x53, 0x80, 0x2b, 0x0d, 0x05, 0x27, 0x9f, -0x22, 0x8f, 0xaf, 0x67, 0x2e, 0xe0, 0xdf, 0x04, -0x1e, 0x00, 0x52, 0x8f, 0x30, 0x67, 0x2e, 0xe1, -0xdf, 0xdf, 0x22, 0x00, 0x54, 0x8f, 0x30, 0x67, -0x2e, 0xfe, 0xdf, 0x04, 0x1e + 0x42, 0xca, 0x00, + 0x64, 0x20, 0xdf, 0x21, 0x80, + 0x03, 0x02, 0x5e, 0x7f, 0x20, 0x00, 0x53, 0xbf, + 0x22, 0x29, 0xcf, 0xbf, 0x03, 0x01, 0x5e, 0x5f, + 0x20, 0xdf, 0x9f, 0x28, 0xbf, 0x03, 0x0c, 0x05, + 0x27, 0x24, 0xcf, 0x10, 0xdf, 0xbf, 0x01, 0x06, + 0x1e, 0xe2, 0x2f, 0x13, 0x5c, 0xdf, 0x2d, 0x00, + 0x5b, 0x9f, 0x22, 0xdf, 0x96, 0x9b, 0xef, 0x20, + 0xff, 0x1d, 0x00, 0x00, 0x13, 0x1a, 0x27, 0x07, + 0x27, 0x9b, 0x22, 0xdf, 0x96, 0xbb, 0xcf, 0x1a, + 0x88, 0xbb, 0xcf, 0x1b, 0x88, 0x01, 0x0f, 0xbc, + 0xcf, 0x15, 0x88, 0xbc, 0xcf, 0x16, 0x88, 0x01, + 0x0f, 0xbd, 0xcf, 0x10, 0x88, 0xbd, 0xcf, 0x11, + 0x88, 0x01, 0x0f, 0xbe, 0xcf, 0x0b, 0x88, 0xbe, + 0xcf, 0x0c, 0x88, 0x01, 0x0c, 0xdd, 0x97, 0x25, + 0xaf, 0x05, 0x27, 0xff, 0x00, 0xab, 0x00, 0x72, + 0x00, 0x4c, 0x00, 0x33, 0x00, 0x22, 0x00, 0x09, + 0x88, 0xbf, 0x9d, 0x05, 0x27, 0x09, 0x27, 0x05, + 0x88, 0xff, 0x97, 0x09, 0x27, 0xf6, 0x9f, 0x5f, + 0x02, 0xbf, 0x9d, 0x05, 0x27, 0x0f, 0x1c, 0xc0, + 0x9f, 0x8a, 0x80, 0x80, 0x10, 0x00, 0x13, 0x0f, + 0x1d, 0xc1, 0x03, 0x00, 0x5f, 0x7f, 0x90, 0x05, + 0x27, 0x53, 0x80, 0x2b, 0x0d, 0x05, 0x27, 0x9f, + 0x22, 0x8f, 0xaf, 0x67, 0x2e, 0xe0, 0xdf, 0x04, + 0x1e, 0x00, 0x52, 0x8f, 0x30, 0x67, 0x2e, 0xe1, + 0xdf, 0xdf, 0x22, 0x00, 0x54, 0x8f, 0x30, 0x67, + 0x2e, 0xfe, 0xdf, 0x04, 0x1e }; static const unsigned char pkt444[] = { -0x42, 0xca, 0x00, -0xc8, 0x20, 0x00, 0x52, 0x8f, -0x31, 0x67, 0x2e, 0xff, 0xdf, 0xdf, 0x22, 0x00, -0x54, 0x8f, 0x31, 0x8f, 0xcf, 0x03, 0x1c, 0x03, -0x1e, 0x00, 0x55, 0x0c, 0x27, 0x0d, 0x27, 0x4a, -0xcf, 0xdf, 0x96, 0x10, 0xcf, 0x5f, 0xdf, 0xbf, -0x03, 0x02, 0x5f, 0x5f, 0xcf, 0x10, 0xaf, 0x04, -0x50, 0x5e, 0xdf, 0xbf, 0x03, 0x01, 0x53, 0x5e, -0xcf, 0x10, 0xaf, 0x46, 0x88, 0x01, 0x2e, 0x1e, -0x80, 0xdd, 0x97, 0x0a, 0x40, 0x1c, 0x5a, 0x37, -0x43, 0x0b, 0x5b, 0xe2, 0xcf, 0x0f, 0x1c, 0x06, -0x1e, 0x07, 0x52, 0x62, 0xdf, 0x18, 0x1f, 0x07, -0x53, 0x04, 0x16, 0xe2, 0xaf, 0x04, 0x11, 0x62, -0xbf, 0x02, 0x50, 0x62, 0xcf, 0xdf, 0x22, 0x0e, -0x54, 0x0e, 0x88, 0x62, 0xdf, 0xbf, 0x03, 0x04, -0x53, 0x62, 0xaf, 0xdf, 0x01, 0xe2, 0xcf, 0x3f, -0x00, 0xe2, 0xaf, 0x0e, 0x88, 0x4a, 0xdf, 0x3f, -0x00, 0x4a, 0xaf, 0x00, 0x2e, 0xc4, 0x8d, 0x05, -0x27, 0xff, 0xef, 0x4a, 0xdf, 0xbf, 0x01, 0x0a, -0x88, 0xa1, 0x27, 0x5f, 0x21, 0x7f, 0x20, 0xfb, -0x55, 0x05, 0x27, 0x62, 0xcf, 0x03, 0x88, 0x1f, -0x22, 0x7f, 0x20, 0xfc, 0x55, 0x05, 0x27, 0x10, -0xdf, 0x02, 0x1f, 0x02, 0x5e, 0x04, 0xff, 0x00, -0x2e, 0x0a, 0x50, 0x05, 0x1f, 0x02, 0x5e, 0x03, -0xff, 0x00, 0x2e, 0x05, 0x50, 0x06, 0x1f, 0x02, -0x5e, 0x02, 0xff, 0x00, 0x2e, 0x00, 0x50, 0x01, -0xff, 0x05, 0x27, 0x10, 0xcf + 0x42, 0xca, 0x00, + 0xc8, 0x20, 0x00, 0x52, 0x8f, + 0x31, 0x67, 0x2e, 0xff, 0xdf, 0xdf, 0x22, 0x00, + 0x54, 0x8f, 0x31, 0x8f, 0xcf, 0x03, 0x1c, 0x03, + 0x1e, 0x00, 0x55, 0x0c, 0x27, 0x0d, 0x27, 0x4a, + 0xcf, 0xdf, 0x96, 0x10, 0xcf, 0x5f, 0xdf, 0xbf, + 0x03, 0x02, 0x5f, 0x5f, 0xcf, 0x10, 0xaf, 0x04, + 0x50, 0x5e, 0xdf, 0xbf, 0x03, 0x01, 0x53, 0x5e, + 0xcf, 0x10, 0xaf, 0x46, 0x88, 0x01, 0x2e, 0x1e, + 0x80, 0xdd, 0x97, 0x0a, 0x40, 0x1c, 0x5a, 0x37, + 0x43, 0x0b, 0x5b, 0xe2, 0xcf, 0x0f, 0x1c, 0x06, + 0x1e, 0x07, 0x52, 0x62, 0xdf, 0x18, 0x1f, 0x07, + 0x53, 0x04, 0x16, 0xe2, 0xaf, 0x04, 0x11, 0x62, + 0xbf, 0x02, 0x50, 0x62, 0xcf, 0xdf, 0x22, 0x0e, + 0x54, 0x0e, 0x88, 0x62, 0xdf, 0xbf, 0x03, 0x04, + 0x53, 0x62, 0xaf, 0xdf, 0x01, 0xe2, 0xcf, 0x3f, + 0x00, 0xe2, 0xaf, 0x0e, 0x88, 0x4a, 0xdf, 0x3f, + 0x00, 0x4a, 0xaf, 0x00, 0x2e, 0xc4, 0x8d, 0x05, + 0x27, 0xff, 0xef, 0x4a, 0xdf, 0xbf, 0x01, 0x0a, + 0x88, 0xa1, 0x27, 0x5f, 0x21, 0x7f, 0x20, 0xfb, + 0x55, 0x05, 0x27, 0x62, 0xcf, 0x03, 0x88, 0x1f, + 0x22, 0x7f, 0x20, 0xfc, 0x55, 0x05, 0x27, 0x10, + 0xdf, 0x02, 0x1f, 0x02, 0x5e, 0x04, 0xff, 0x00, + 0x2e, 0x0a, 0x50, 0x05, 0x1f, 0x02, 0x5e, 0x03, + 0xff, 0x00, 0x2e, 0x05, 0x50, 0x06, 0x1f, 0x02, + 0x5e, 0x02, 0xff, 0x00, 0x2e, 0x00, 0x50, 0x01, + 0xff, 0x05, 0x27, 0x10, 0xcf }; static const unsigned char pkt448[] = { -0x42, 0xca, 0x00, -0x2c, 0x21, 0x33, 0xff, 0x3f, -0x00, 0x21, 0xff, 0x00, 0x13, 0x1a, 0x27, 0x07, -0x27, 0x05, 0x27, 0x01, 0x00, 0x02, 0x57, 0x42, -0x87, 0x52, 0x80, 0x92, 0x81, 0xd2, 0x6c, 0xe2, -0x80, 0xf2, 0x80, 0xf6, 0x7b, 0xfa, 0x7e, 0xfe, -0x8b, 0xf9, 0x45, 0x04, 0x5a, 0x40, 0xef, 0xf9, -0x44, 0x03, 0x5b, 0x80, 0xef, 0x01, 0x50, 0x41, -0x2e, 0x7e, 0xdf, 0x4d, 0xaf, 0x05, 0x27, 0x28, -0xff, 0x54, 0xef, 0x19, 0x27, 0x4d, 0x26, 0xe1, -0x2f, 0x28, 0x54, 0x27, 0xff, 0xe0, 0xef, 0x1b, -0x27, 0x10, 0xef, 0x06, 0xaf, 0xfc, 0x97, 0xfc, -0x9f, 0x1c, 0x82, 0x1c, 0x82, 0x1a, 0x27, 0x4d, -0xdf, 0x6d, 0x80, 0x5f, 0x9f, 0x06, 0x25, 0xf5, -0x55, 0x05, 0x27, 0x26, 0x1f, 0x00, 0x5f, 0xbf, -0x22, 0xff, 0x96, 0x6c, 0xef, 0x21, 0xff, 0x1d, -0x00, 0x00, 0x13, 0x1a, 0x27, 0x07, 0x27, 0x1a, -0x27, 0xd6, 0x97, 0x05, 0x27, 0xa3, 0x01, 0xa4, -0x01, 0xa3, 0x01, 0x2e, 0x00, 0xb0, 0x00, 0xb1, -0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb4, 0x00, 0xb5, -0x00, 0xb6, 0x00, 0xb7, 0x00, 0xb8, 0x00, 0xb9, -0x00, 0xba, 0x00, 0x56, 0x00, 0xae, 0x00, 0x54, -0x01, 0x44, 0x01, 0x55, 0x01, 0x44, 0x01, 0xbb, -0x00, 0xbc, 0x00, 0xbd, 0x00, 0xbe, 0x00, 0x83, -0x00, 0x84, 0x00, 0x81, 0x00, 0x82, 0x00, 0x24, -0x00, 0x44, 0x01, 0xdb, 0x00, 0xdc, 0x00, 0xdd, -0x00, 0xde, 0x00, 0x04, 0x00 + 0x42, 0xca, 0x00, + 0x2c, 0x21, 0x33, 0xff, 0x3f, + 0x00, 0x21, 0xff, 0x00, 0x13, 0x1a, 0x27, 0x07, + 0x27, 0x05, 0x27, 0x01, 0x00, 0x02, 0x57, 0x42, + 0x87, 0x52, 0x80, 0x92, 0x81, 0xd2, 0x6c, 0xe2, + 0x80, 0xf2, 0x80, 0xf6, 0x7b, 0xfa, 0x7e, 0xfe, + 0x8b, 0xf9, 0x45, 0x04, 0x5a, 0x40, 0xef, 0xf9, + 0x44, 0x03, 0x5b, 0x80, 0xef, 0x01, 0x50, 0x41, + 0x2e, 0x7e, 0xdf, 0x4d, 0xaf, 0x05, 0x27, 0x28, + 0xff, 0x54, 0xef, 0x19, 0x27, 0x4d, 0x26, 0xe1, + 0x2f, 0x28, 0x54, 0x27, 0xff, 0xe0, 0xef, 0x1b, + 0x27, 0x10, 0xef, 0x06, 0xaf, 0xfc, 0x97, 0xfc, + 0x9f, 0x1c, 0x82, 0x1c, 0x82, 0x1a, 0x27, 0x4d, + 0xdf, 0x6d, 0x80, 0x5f, 0x9f, 0x06, 0x25, 0xf5, + 0x55, 0x05, 0x27, 0x26, 0x1f, 0x00, 0x5f, 0xbf, + 0x22, 0xff, 0x96, 0x6c, 0xef, 0x21, 0xff, 0x1d, + 0x00, 0x00, 0x13, 0x1a, 0x27, 0x07, 0x27, 0x1a, + 0x27, 0xd6, 0x97, 0x05, 0x27, 0xa3, 0x01, 0xa4, + 0x01, 0xa3, 0x01, 0x2e, 0x00, 0xb0, 0x00, 0xb1, + 0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb4, 0x00, 0xb5, + 0x00, 0xb6, 0x00, 0xb7, 0x00, 0xb8, 0x00, 0xb9, + 0x00, 0xba, 0x00, 0x56, 0x00, 0xae, 0x00, 0x54, + 0x01, 0x44, 0x01, 0x55, 0x01, 0x44, 0x01, 0xbb, + 0x00, 0xbc, 0x00, 0xbd, 0x00, 0xbe, 0x00, 0x83, + 0x00, 0x84, 0x00, 0x81, 0x00, 0x82, 0x00, 0x24, + 0x00, 0x44, 0x01, 0xdb, 0x00, 0xdc, 0x00, 0xdd, + 0x00, 0xde, 0x00, 0x04, 0x00 }; static const unsigned char pkt452[] = { -0x42, 0x52, 0x00, -0x90, 0x21, 0x9b, 0x00, 0x99, -0x00, 0x9e, 0x00, 0x10, 0xef, 0xe6, 0x81, 0x65, -0xaf, 0x10, 0xef, 0xe6, 0x81, 0x9c, 0xaf, 0x10, -0xef, 0xe6, 0x81, 0x9a, 0xaf, 0x05, 0x27, 0xe5, -0x31, 0x1d, 0x81, 0xe5, 0x39, 0x05, 0x27, 0xc8, -0x46, 0x0b, 0x5b, 0xd3, 0x45, 0xfd, 0x5a, 0xd3, -0x45, 0xfb, 0x5a, 0xd3, 0x45, 0xf9, 0x5a, 0x41, -0x2e, 0xa1, 0xdf, 0x9f, 0x28, 0x41, 0x2e, 0xa1, -0xbf, 0x00, 0x88, 0x05, 0x27, 0x9f, 0x22, 0xbf, -0x22, 0x1f, 0x20, 0xfd, 0x53, 0x3f, 0x20, 0x14, -0x1f, 0xfa, 0x55, 0x05, 0x27 + 0x42, 0x52, 0x00, + 0x90, 0x21, 0x9b, 0x00, 0x99, + 0x00, 0x9e, 0x00, 0x10, 0xef, 0xe6, 0x81, 0x65, + 0xaf, 0x10, 0xef, 0xe6, 0x81, 0x9c, 0xaf, 0x10, + 0xef, 0xe6, 0x81, 0x9a, 0xaf, 0x05, 0x27, 0xe5, + 0x31, 0x1d, 0x81, 0xe5, 0x39, 0x05, 0x27, 0xc8, + 0x46, 0x0b, 0x5b, 0xd3, 0x45, 0xfd, 0x5a, 0xd3, + 0x45, 0xfb, 0x5a, 0xd3, 0x45, 0xf9, 0x5a, 0x41, + 0x2e, 0xa1, 0xdf, 0x9f, 0x28, 0x41, 0x2e, 0xa1, + 0xbf, 0x00, 0x88, 0x05, 0x27, 0x9f, 0x22, 0xbf, + 0x22, 0x1f, 0x20, 0xfd, 0x53, 0x3f, 0x20, 0x14, + 0x1f, 0xfa, 0x55, 0x05, 0x27 }; static const unsigned char pkt456[] = { -0x42, 0xca, 0x00, -0xb8, 0x21, 0x25, 0x85, 0x01, -0x1e, 0x17, 0x55, 0x1b, 0x8a, 0x41, 0x2e, 0x53, -0xdf, 0xc1, 0x2e, 0x79, 0xdf, 0xff, 0x96, 0xdf, -0x96, 0x41, 0x2e, 0x55, 0xdf, 0xc1, 0x2e, 0x78, -0xdf, 0x9d, 0x01, 0x5d, 0x01, 0xff, 0x22, 0x00, -0x54, 0xff, 0xef, 0x2e, 0xaf, 0x05, 0x27, 0x07, -0x80, 0x9f, 0x22, 0xff, 0xaf, 0x00, 0x2e, 0x5d, -0x89, 0x05, 0x27, 0x06, 0x1e, 0x01, 0x55, 0x0f, -0x27, 0x01, 0x70, 0x0a, 0x1e, 0x0a, 0x55, 0x00, -0x88, 0x66, 0x76, 0x02, 0x46, 0x00, 0x5b, 0x08, -0x3b, 0x3b, 0x30, 0x07, 0x35, 0xff, 0xff, 0xc2, -0xbf, 0x0d, 0x27, 0x0c, 0x27, 0x0d, 0x1e, 0x02, -0x55, 0x28, 0x85, 0xf2, 0x5b, 0x7b, 0x76, 0x12, -0x1e, 0x07, 0x55, 0xdc, 0xef, 0x05, 0xff, 0x1a, -0x27, 0x56, 0xdf, 0x3f, 0x20, 0x6d, 0x80, 0x3c, -0xaf, 0x05, 0x27, 0x13, 0x1e, 0x01, 0x55, 0x3c, -0x23, 0x05, 0x27, 0x1f, 0x1e, 0x06, 0x55, 0x37, -0x35, 0x08, 0xef, 0x40, 0x2e, 0xf0, 0xbf, 0x40, -0x2e, 0xf6, 0xbf, 0x05, 0x27, 0x20, 0x1e, 0x06, -0x55, 0x37, 0x3d, 0x16, 0xef, 0x40, 0x2e, 0xf0, -0xbf, 0x40, 0x2e, 0xf6, 0xbf, 0x05, 0x27, 0x22, -0x1e, 0x19, 0x55, 0x21, 0xef, 0x08, 0xaf, 0x09, -0x23, 0x01, 0xef, 0x0b, 0xaf, 0x31, 0xef, 0x0a, -0xaf, 0x81, 0xcf, 0x10, 0xaf, 0xbf, 0x8e, 0x82, -0xcf, 0x4a, 0xaf, 0x00, 0x2e, 0xc4, 0x8d, 0x08, -0xef, 0x9b, 0xaf, 0x99, 0xaf + 0x42, 0xca, 0x00, + 0xb8, 0x21, 0x25, 0x85, 0x01, + 0x1e, 0x17, 0x55, 0x1b, 0x8a, 0x41, 0x2e, 0x53, + 0xdf, 0xc1, 0x2e, 0x79, 0xdf, 0xff, 0x96, 0xdf, + 0x96, 0x41, 0x2e, 0x55, 0xdf, 0xc1, 0x2e, 0x78, + 0xdf, 0x9d, 0x01, 0x5d, 0x01, 0xff, 0x22, 0x00, + 0x54, 0xff, 0xef, 0x2e, 0xaf, 0x05, 0x27, 0x07, + 0x80, 0x9f, 0x22, 0xff, 0xaf, 0x00, 0x2e, 0x5d, + 0x89, 0x05, 0x27, 0x06, 0x1e, 0x01, 0x55, 0x0f, + 0x27, 0x01, 0x70, 0x0a, 0x1e, 0x0a, 0x55, 0x00, + 0x88, 0x66, 0x76, 0x02, 0x46, 0x00, 0x5b, 0x08, + 0x3b, 0x3b, 0x30, 0x07, 0x35, 0xff, 0xff, 0xc2, + 0xbf, 0x0d, 0x27, 0x0c, 0x27, 0x0d, 0x1e, 0x02, + 0x55, 0x28, 0x85, 0xf2, 0x5b, 0x7b, 0x76, 0x12, + 0x1e, 0x07, 0x55, 0xdc, 0xef, 0x05, 0xff, 0x1a, + 0x27, 0x56, 0xdf, 0x3f, 0x20, 0x6d, 0x80, 0x3c, + 0xaf, 0x05, 0x27, 0x13, 0x1e, 0x01, 0x55, 0x3c, + 0x23, 0x05, 0x27, 0x1f, 0x1e, 0x06, 0x55, 0x37, + 0x35, 0x08, 0xef, 0x40, 0x2e, 0xf0, 0xbf, 0x40, + 0x2e, 0xf6, 0xbf, 0x05, 0x27, 0x20, 0x1e, 0x06, + 0x55, 0x37, 0x3d, 0x16, 0xef, 0x40, 0x2e, 0xf0, + 0xbf, 0x40, 0x2e, 0xf6, 0xbf, 0x05, 0x27, 0x22, + 0x1e, 0x19, 0x55, 0x21, 0xef, 0x08, 0xaf, 0x09, + 0x23, 0x01, 0xef, 0x0b, 0xaf, 0x31, 0xef, 0x0a, + 0xaf, 0x81, 0xcf, 0x10, 0xaf, 0xbf, 0x8e, 0x82, + 0xcf, 0x4a, 0xaf, 0x00, 0x2e, 0xc4, 0x8d, 0x08, + 0xef, 0x9b, 0xaf, 0x99, 0xaf }; static const unsigned char pkt460[] = { -0x42, 0x34, 0x00, -0x1c, 0x22, 0x02, 0xcf, 0x0f, -0x1c, 0x40, 0x18, 0x37, 0x31, 0x02, 0xaf, 0xe2, -0x23, 0x08, 0xef, 0xe3, 0xaf, 0x05, 0x27, 0x23, -0x1e, 0x0c, 0x55, 0x00, 0xef, 0x02, 0xff, 0x19, -0x27, 0xbf, 0x22, 0x20, 0xef, 0x7f, 0x9f, 0x5f, -0x20, 0xfc, 0x55, 0xf0, 0x81, 0x9f, 0x22, 0x41, -0x2e, 0xa3, 0xbf, 0x05, 0x27, 0xcb, 0x74 + 0x42, 0x34, 0x00, + 0x1c, 0x22, 0x02, 0xcf, 0x0f, + 0x1c, 0x40, 0x18, 0x37, 0x31, 0x02, 0xaf, 0xe2, + 0x23, 0x08, 0xef, 0xe3, 0xaf, 0x05, 0x27, 0x23, + 0x1e, 0x0c, 0x55, 0x00, 0xef, 0x02, 0xff, 0x19, + 0x27, 0xbf, 0x22, 0x20, 0xef, 0x7f, 0x9f, 0x5f, + 0x20, 0xfc, 0x55, 0xf0, 0x81, 0x9f, 0x22, 0x41, + 0x2e, 0xa3, 0xbf, 0x05, 0x27, 0xcb, 0x74 }; static const unsigned char pkt464[] = { -0x42, 0xca, 0x00, -0x35, 0x22, 0x25, 0x85, 0x44, -0x1e, 0x01, 0x55, 0xe2, 0x2f, 0xf1, 0x50, 0x49, -0x1e, 0x0d, 0x55, 0x37, 0x39, 0x01, 0xef, 0x72, -0x88, 0x00, 0x2e, 0x45, 0x8d, 0x6b, 0x81, 0x08, -0x42, 0x03, 0x5b, 0x3d, 0x23, 0x9f, 0x22, 0x00, -0x2e, 0xb2, 0x8b, 0xd3, 0x3b, 0x05, 0x27, 0x4a, -0x1e, 0x01, 0x55, 0xe2, 0x2f, 0xdd, 0x50, 0x4e, -0x1e, 0x01, 0x55, 0x00, 0x2e, 0xbb, 0x79, 0x55, -0x1e, 0x16, 0x55, 0x28, 0x85, 0xe2, 0x2f, 0xd4, -0x5b, 0x07, 0xef, 0x20, 0x80, 0xe2, 0x2f, 0xd0, -0x5a, 0xfe, 0xcf, 0x0a, 0xaf, 0xfe, 0xcf, 0xfe, -0xcf, 0x41, 0x2e, 0x44, 0xbf, 0xfe, 0xcf, 0x41, -0x2e, 0x45, 0xbf, 0xfe, 0xcf, 0x52, 0xaf, 0xfe, -0xcf, 0x53, 0xaf, 0xfe, 0xcf, 0x5a, 0xaf, 0x05, -0x27, 0x58, 0x1e, 0x0d, 0x55, 0x02, 0x44, 0x01, -0x5a, 0x00, 0x2e, 0x07, 0x78, 0xfe, 0xcf, 0x75, -0xaf, 0xfe, 0xdf, 0x76, 0xbf, 0x41, 0x2e, 0xa4, -0xdf, 0xdf, 0x29, 0x41, 0x2e, 0xa4, 0xbf, 0x05, -0x27, 0x59, 0x1e, 0x02, 0x55, 0xfe, 0xcf, 0x10, -0xaf, 0x54, 0x7e, 0x63, 0x1e, 0x1a, 0x55, 0x28, -0x85, 0xe2, 0x2f, 0xa6, 0x5b, 0x0c, 0xef, 0x20, -0x80, 0xe2, 0x2f, 0xa2, 0x5a, 0xf0, 0xef, 0x00, -0xff, 0x19, 0x27, 0x08, 0xef, 0x06, 0xaf, 0xfe, -0xcf, 0x5f, 0x9f, 0x06, 0x25, 0xfb, 0x55, 0xfe, -0xcf, 0xfe, 0xcf, 0x41, 0x2e, 0x40, 0xbf, 0xfe, -0xcf, 0x41, 0x2e, 0x41, 0xbf + 0x42, 0xca, 0x00, + 0x35, 0x22, 0x25, 0x85, 0x44, + 0x1e, 0x01, 0x55, 0xe2, 0x2f, 0xf1, 0x50, 0x49, + 0x1e, 0x0d, 0x55, 0x37, 0x39, 0x01, 0xef, 0x72, + 0x88, 0x00, 0x2e, 0x45, 0x8d, 0x6b, 0x81, 0x08, + 0x42, 0x03, 0x5b, 0x3d, 0x23, 0x9f, 0x22, 0x00, + 0x2e, 0xb2, 0x8b, 0xd3, 0x3b, 0x05, 0x27, 0x4a, + 0x1e, 0x01, 0x55, 0xe2, 0x2f, 0xdd, 0x50, 0x4e, + 0x1e, 0x01, 0x55, 0x00, 0x2e, 0xbb, 0x79, 0x55, + 0x1e, 0x16, 0x55, 0x28, 0x85, 0xe2, 0x2f, 0xd4, + 0x5b, 0x07, 0xef, 0x20, 0x80, 0xe2, 0x2f, 0xd0, + 0x5a, 0xfe, 0xcf, 0x0a, 0xaf, 0xfe, 0xcf, 0xfe, + 0xcf, 0x41, 0x2e, 0x44, 0xbf, 0xfe, 0xcf, 0x41, + 0x2e, 0x45, 0xbf, 0xfe, 0xcf, 0x52, 0xaf, 0xfe, + 0xcf, 0x53, 0xaf, 0xfe, 0xcf, 0x5a, 0xaf, 0x05, + 0x27, 0x58, 0x1e, 0x0d, 0x55, 0x02, 0x44, 0x01, + 0x5a, 0x00, 0x2e, 0x07, 0x78, 0xfe, 0xcf, 0x75, + 0xaf, 0xfe, 0xdf, 0x76, 0xbf, 0x41, 0x2e, 0xa4, + 0xdf, 0xdf, 0x29, 0x41, 0x2e, 0xa4, 0xbf, 0x05, + 0x27, 0x59, 0x1e, 0x02, 0x55, 0xfe, 0xcf, 0x10, + 0xaf, 0x54, 0x7e, 0x63, 0x1e, 0x1a, 0x55, 0x28, + 0x85, 0xe2, 0x2f, 0xa6, 0x5b, 0x0c, 0xef, 0x20, + 0x80, 0xe2, 0x2f, 0xa2, 0x5a, 0xf0, 0xef, 0x00, + 0xff, 0x19, 0x27, 0x08, 0xef, 0x06, 0xaf, 0xfe, + 0xcf, 0x5f, 0x9f, 0x06, 0x25, 0xfb, 0x55, 0xfe, + 0xcf, 0xfe, 0xcf, 0x41, 0x2e, 0x40, 0xbf, 0xfe, + 0xcf, 0x41, 0x2e, 0x41, 0xbf }; static const unsigned char pkt468[] = { -0x42, 0x46, 0x00, -0x99, 0x22, 0xfe, 0xcf, 0x41, -0x2e, 0x42, 0xbf, 0x05, 0x27, 0x66, 0x1e, 0x0b, -0x55, 0x33, 0xef, 0x21, 0xff, 0x1a, 0x27, 0x0b, -0xef, 0x06, 0xaf, 0xfe, 0xcf, 0xfe, 0xdf, 0x06, -0x27, 0x01, 0x0e, 0x06, 0x25, 0xf9, 0x55, 0x05, -0x27, 0x35, 0x74, 0xff, 0x96, 0xc6, 0x2e, 0x01, -0xdf, 0x3f, 0x2c, 0xdd, 0x9f, 0x05, 0x27, 0xf9, -0x35, 0xc1, 0x2e, 0x4e, 0xdf, 0x0f, 0x1d, 0x09, -0x27, 0x5f, 0x02, 0xc1, 0x2e, 0x4e, 0xbf, 0x05, -0x27 + 0x42, 0x46, 0x00, + 0x99, 0x22, 0xfe, 0xcf, 0x41, + 0x2e, 0x42, 0xbf, 0x05, 0x27, 0x66, 0x1e, 0x0b, + 0x55, 0x33, 0xef, 0x21, 0xff, 0x1a, 0x27, 0x0b, + 0xef, 0x06, 0xaf, 0xfe, 0xcf, 0xfe, 0xdf, 0x06, + 0x27, 0x01, 0x0e, 0x06, 0x25, 0xf9, 0x55, 0x05, + 0x27, 0x35, 0x74, 0xff, 0x96, 0xc6, 0x2e, 0x01, + 0xdf, 0x3f, 0x2c, 0xdd, 0x9f, 0x05, 0x27, 0xf9, + 0x35, 0xc1, 0x2e, 0x4e, 0xdf, 0x0f, 0x1d, 0x09, + 0x27, 0x5f, 0x02, 0xc1, 0x2e, 0x4e, 0xbf, 0x05, + 0x27 }; static const unsigned char pkt472[] = { -0x42, 0xca, 0x00, -0xbb, 0x22, 0x09, 0x46, 0x0b, -0x5b, 0x08, 0x31, 0xf2, 0xcf, 0x0b, 0xaf, 0x15, -0xef, 0xf4, 0xaf, 0x30, 0xef, 0x0a, 0xaf, 0x44, -0xef, 0xfa, 0xaf, 0x10, 0xef, 0xf8, 0xaf, 0x5c, -0x88, 0x37, 0xcf, 0xdf, 0x96, 0x08, 0xcf, 0xdf, -0x96, 0x3d, 0xcf, 0xdf, 0x96, 0x00, 0x2e, 0xd4, -0x8d, 0xdd, 0x97, 0x3d, 0xaf, 0xdd, 0x97, 0x08, -0xaf, 0xdd, 0x97, 0x37, 0xaf, 0xa0, 0xcf, 0xbf, -0x1c, 0xa0, 0xaf, 0x05, 0x81, 0xfb, 0x39, 0x08, -0x45, 0x00, 0x5a, 0xfb, 0x31, 0x0a, 0x42, 0x00, -0x5b, 0xa2, 0x39, 0x02, 0xcf, 0x5c, 0xaf, 0xe1, -0xef, 0x40, 0x2e, 0x95, 0xbf, 0x9f, 0x22, 0x25, -0xaf, 0x69, 0xaf, 0x6a, 0xaf, 0x16, 0xaf, 0x40, -0x2e, 0x96, 0xbf, 0x29, 0xaf, 0x02, 0x47, 0x06, -0x5a, 0x0a, 0x41, 0x04, 0x5a, 0x0a, 0xdf, 0x30, -0x1d, 0x30, 0x1f, 0x00, 0x54, 0x01, 0xef, 0x44, -0xaf, 0x09, 0xef, 0x60, 0xaf, 0x08, 0x45, 0x0a, -0x40, 0x06, 0x5a, 0x10, 0xcf, 0x27, 0xaf, 0xe2, -0x23, 0x6e, 0x23, 0x08, 0xef, 0xe3, 0xaf, 0x6f, -0xaf, 0xce, 0x8d, 0x5d, 0xcf, 0x30, 0x1c, 0x00, -0x1e, 0x07, 0x55, 0xf8, 0xcf, 0x5f, 0x2b, 0x9f, -0x29, 0xf8, 0xaf, 0xa1, 0xcf, 0xc1, 0x1c, 0xa1, -0xaf, 0x09, 0x50, 0x10, 0x1e, 0x07, 0x55, 0xf8, -0xcf, 0x5f, 0x29, 0x9f, 0x2b, 0xf8, 0xaf, 0xa1, -0xcf, 0xc1, 0x1c, 0x08, 0x18, 0xa1, 0xaf, 0x41, -0x2e, 0xa4, 0xdf, 0xdf, 0x2d + 0x42, 0xca, 0x00, + 0xbb, 0x22, 0x09, 0x46, 0x0b, + 0x5b, 0x08, 0x31, 0xf2, 0xcf, 0x0b, 0xaf, 0x15, + 0xef, 0xf4, 0xaf, 0x30, 0xef, 0x0a, 0xaf, 0x44, + 0xef, 0xfa, 0xaf, 0x10, 0xef, 0xf8, 0xaf, 0x5c, + 0x88, 0x37, 0xcf, 0xdf, 0x96, 0x08, 0xcf, 0xdf, + 0x96, 0x3d, 0xcf, 0xdf, 0x96, 0x00, 0x2e, 0xd4, + 0x8d, 0xdd, 0x97, 0x3d, 0xaf, 0xdd, 0x97, 0x08, + 0xaf, 0xdd, 0x97, 0x37, 0xaf, 0xa0, 0xcf, 0xbf, + 0x1c, 0xa0, 0xaf, 0x05, 0x81, 0xfb, 0x39, 0x08, + 0x45, 0x00, 0x5a, 0xfb, 0x31, 0x0a, 0x42, 0x00, + 0x5b, 0xa2, 0x39, 0x02, 0xcf, 0x5c, 0xaf, 0xe1, + 0xef, 0x40, 0x2e, 0x95, 0xbf, 0x9f, 0x22, 0x25, + 0xaf, 0x69, 0xaf, 0x6a, 0xaf, 0x16, 0xaf, 0x40, + 0x2e, 0x96, 0xbf, 0x29, 0xaf, 0x02, 0x47, 0x06, + 0x5a, 0x0a, 0x41, 0x04, 0x5a, 0x0a, 0xdf, 0x30, + 0x1d, 0x30, 0x1f, 0x00, 0x54, 0x01, 0xef, 0x44, + 0xaf, 0x09, 0xef, 0x60, 0xaf, 0x08, 0x45, 0x0a, + 0x40, 0x06, 0x5a, 0x10, 0xcf, 0x27, 0xaf, 0xe2, + 0x23, 0x6e, 0x23, 0x08, 0xef, 0xe3, 0xaf, 0x6f, + 0xaf, 0xce, 0x8d, 0x5d, 0xcf, 0x30, 0x1c, 0x00, + 0x1e, 0x07, 0x55, 0xf8, 0xcf, 0x5f, 0x2b, 0x9f, + 0x29, 0xf8, 0xaf, 0xa1, 0xcf, 0xc1, 0x1c, 0xa1, + 0xaf, 0x09, 0x50, 0x10, 0x1e, 0x07, 0x55, 0xf8, + 0xcf, 0x5f, 0x29, 0x9f, 0x2b, 0xf8, 0xaf, 0xa1, + 0xcf, 0xc1, 0x1c, 0x08, 0x18, 0xa1, 0xaf, 0x41, + 0x2e, 0xa4, 0xdf, 0xdf, 0x2d }; static const unsigned char pkt476[] = { -0x42, 0x3a, 0x00, -0x1f, 0x23, 0x04, 0x5b, 0x75, -0xcf, 0xf4, 0xaf, 0x76, 0xcf, 0xf5, 0xaf, 0x00, -0x50, 0x0f, 0x88, 0xe2, 0x23, 0x08, 0xef, 0xe3, -0xaf, 0x81, 0x82, 0x4d, 0xaf, 0xdf, 0x96, 0x64, -0xdf, 0x93, 0x82, 0x93, 0xbf, 0xdd, 0x97, 0x77, -0xff, 0x93, 0x82, 0x94, 0xbf, 0x9e, 0x23, 0xe4, -0x23, 0x05, 0x27, 0x14, 0xef, 0xf4, 0xaf, 0x00, -0xef, 0xf5, 0xaf, 0x05, 0x27 + 0x42, 0x3a, 0x00, + 0x1f, 0x23, 0x04, 0x5b, 0x75, + 0xcf, 0xf4, 0xaf, 0x76, 0xcf, 0xf5, 0xaf, 0x00, + 0x50, 0x0f, 0x88, 0xe2, 0x23, 0x08, 0xef, 0xe3, + 0xaf, 0x81, 0x82, 0x4d, 0xaf, 0xdf, 0x96, 0x64, + 0xdf, 0x93, 0x82, 0x93, 0xbf, 0xdd, 0x97, 0x77, + 0xff, 0x93, 0x82, 0x94, 0xbf, 0x9e, 0x23, 0xe4, + 0x23, 0x05, 0x27, 0x14, 0xef, 0xf4, 0xaf, 0x00, + 0xef, 0xf5, 0xaf, 0x05, 0x27 }; static const unsigned char pkt480[] = { -0x42, 0xca, 0x00, -0x3b, 0x23, 0xfe, 0xcf, 0x58, -0xaf, 0xfe, 0xcf, 0xfe, 0xdf, 0x00, 0x2e, 0xa9, -0x8b, 0xfe, 0xcf, 0x3c, 0xaf, 0x07, 0x3d, 0x58, -0x40, 0x4a, 0x5a, 0x3c, 0x26, 0x48, 0x55, 0x37, -0x45, 0x46, 0x5a, 0xe0, 0x88, 0x44, 0x5a, 0x77, -0x88, 0x00, 0x2e, 0xd1, 0x8b, 0xfe, 0xef, 0x16, -0x80, 0x02, 0xcf, 0xdf, 0x96, 0x61, 0xef, 0xc0, -0xaf, 0x04, 0x27, 0xc1, 0x46, 0x04, 0x5b, 0xc0, -0x3e, 0x40, 0xef, 0xc1, 0xaf, 0x01, 0x2e, 0x94, -0x84, 0xd0, 0x41, 0x06, 0x5b, 0x2d, 0x88, 0xf3, -0x5b, 0x6c, 0x86, 0xdd, 0x97, 0x1f, 0x2d, 0x05, -0x5b, 0x03, 0x50, 0x01, 0x0c, 0x02, 0xcf, 0xc0, -0x1c, 0x00, 0x55, 0x05, 0x88, 0xc0, 0x23, 0x20, -0xef, 0xc1, 0xaf, 0x00, 0x2e, 0xf0, 0x8b, 0x05, -0x27, 0x9b, 0x22, 0x37, 0x45, 0x05, 0x5a, 0x41, -0x2e, 0x52, 0xdf, 0xdf, 0x2d, 0x04, 0x5b, 0x00, -0x28, 0x02, 0x50, 0x3b, 0x43, 0x00, 0x5b, 0x00, -0x28, 0xd3, 0xdf, 0xc6, 0x2e, 0x15, 0xbf, 0xd3, -0x3c, 0x40, 0xef, 0x09, 0x80, 0xdd, 0x97, 0xff, -0xaf, 0x00, 0x2e, 0x5d, 0x89, 0xc6, 0x2e, 0x15, -0xdf, 0x10, 0x1d, 0xd3, 0xcf, 0x3f, 0x02, 0xd3, -0xaf, 0x05, 0x27, 0xc1, 0x83, 0x07, 0x45, 0x05, -0x27, 0x3d, 0x23, 0x07, 0x3d, 0x02, 0xcf, 0xdf, -0x96, 0x2e, 0x88, 0x26, 0x88, 0xfe, 0xef, 0x16, -0x80, 0x05, 0xef, 0xc0, 0xaf, 0x04, 0x27, 0xd0, -0x41, 0x02, 0x5b, 0xee, 0x8f + 0x42, 0xca, 0x00, + 0x3b, 0x23, 0xfe, 0xcf, 0x58, + 0xaf, 0xfe, 0xcf, 0xfe, 0xdf, 0x00, 0x2e, 0xa9, + 0x8b, 0xfe, 0xcf, 0x3c, 0xaf, 0x07, 0x3d, 0x58, + 0x40, 0x4a, 0x5a, 0x3c, 0x26, 0x48, 0x55, 0x37, + 0x45, 0x46, 0x5a, 0xe0, 0x88, 0x44, 0x5a, 0x77, + 0x88, 0x00, 0x2e, 0xd1, 0x8b, 0xfe, 0xef, 0x16, + 0x80, 0x02, 0xcf, 0xdf, 0x96, 0x61, 0xef, 0xc0, + 0xaf, 0x04, 0x27, 0xc1, 0x46, 0x04, 0x5b, 0xc0, + 0x3e, 0x40, 0xef, 0xc1, 0xaf, 0x01, 0x2e, 0x94, + 0x84, 0xd0, 0x41, 0x06, 0x5b, 0x2d, 0x88, 0xf3, + 0x5b, 0x6c, 0x86, 0xdd, 0x97, 0x1f, 0x2d, 0x05, + 0x5b, 0x03, 0x50, 0x01, 0x0c, 0x02, 0xcf, 0xc0, + 0x1c, 0x00, 0x55, 0x05, 0x88, 0xc0, 0x23, 0x20, + 0xef, 0xc1, 0xaf, 0x00, 0x2e, 0xf0, 0x8b, 0x05, + 0x27, 0x9b, 0x22, 0x37, 0x45, 0x05, 0x5a, 0x41, + 0x2e, 0x52, 0xdf, 0xdf, 0x2d, 0x04, 0x5b, 0x00, + 0x28, 0x02, 0x50, 0x3b, 0x43, 0x00, 0x5b, 0x00, + 0x28, 0xd3, 0xdf, 0xc6, 0x2e, 0x15, 0xbf, 0xd3, + 0x3c, 0x40, 0xef, 0x09, 0x80, 0xdd, 0x97, 0xff, + 0xaf, 0x00, 0x2e, 0x5d, 0x89, 0xc6, 0x2e, 0x15, + 0xdf, 0x10, 0x1d, 0xd3, 0xcf, 0x3f, 0x02, 0xd3, + 0xaf, 0x05, 0x27, 0xc1, 0x83, 0x07, 0x45, 0x05, + 0x27, 0x3d, 0x23, 0x07, 0x3d, 0x02, 0xcf, 0xdf, + 0x96, 0x2e, 0x88, 0x26, 0x88, 0xfe, 0xef, 0x16, + 0x80, 0x05, 0xef, 0xc0, 0xaf, 0x04, 0x27, 0xd0, + 0x41, 0x02, 0x5b, 0xee, 0x8f }; static const unsigned char pkt484[] = { -0x42, 0xca, 0x00, -0x9f, 0x23, 0xfa, 0x5b, 0xbf, -0x50, 0x31, 0x82, 0x04, 0xef, 0xc1, 0xaf, 0x9b, -0x22, 0x41, 0x88, 0xdd, 0x97, 0xdf, 0x22, 0x02, -0x55, 0x58, 0x40, 0x02, 0x5a, 0x09, 0x50, 0x58, -0x40, 0x07, 0x5a, 0xdd, 0x97, 0x1f, 0x2d, 0xb8, -0x5a, 0x7a, 0x88, 0xb7, 0x5b, 0x9b, 0x22, 0xc7, -0x8f, 0xb4, 0x50, 0x75, 0x88, 0xdc, 0x5b, 0xb7, -0x8f, 0x58, 0x41, 0x01, 0x5b, 0x01, 0x0c, 0xad, -0x7f, 0xd6, 0x50, 0x41, 0x2e, 0x52, 0xdf, 0xed, -0x1c, 0x04, 0x18, 0x41, 0x2e, 0x52, 0xbf, 0x05, -0x27, 0x00, 0x2e, 0xb9, 0x8b, 0xae, 0xdf, 0xe0, -0x19, 0xae, 0xbf, 0x57, 0x40, 0x00, 0x5b, 0xa1, -0x32, 0x57, 0x43, 0x00, 0x5b, 0xae, 0x3f, 0x05, -0x81, 0x05, 0x27, 0x41, 0x2e, 0x52, 0xdf, 0x03, -0x18, 0x41, 0x2e, 0x52, 0xbf, 0x05, 0x27, 0xd3, -0xdf, 0xff, 0x96, 0x9b, 0x22, 0x0b, 0x88, 0xd3, -0x3c, 0x07, 0x80, 0xdd, 0x97, 0xff, 0xaf, 0x00, -0x2e, 0x5d, 0x89, 0xdd, 0x9f, 0x10, 0x1d, 0xd3, -0xcf, 0x3f, 0x02, 0xd3, 0xaf, 0x05, 0x27, 0x37, -0x45, 0x0e, 0x5a, 0x40, 0x88, 0x0c, 0x5a, 0xd7, -0x8f, 0x00, 0x2e, 0xd7, 0x8b, 0x00, 0x2e, 0xeb, -0x8b, 0x41, 0x2e, 0x52, 0xdf, 0xdf, 0x2d, 0x00, -0x5b, 0x00, 0x28, 0x00, 0x2e, 0xf0, 0x8b, 0x05, -0x27, 0xf9, 0xcf, 0xdf, 0x96, 0xf9, 0x3d, 0x00, -0x2e, 0xd1, 0x8d, 0x28, 0xff, 0xa7, 0xef, 0xe1, -0xbf, 0xe0, 0xaf, 0x09, 0xef + 0x42, 0xca, 0x00, + 0x9f, 0x23, 0xfa, 0x5b, 0xbf, + 0x50, 0x31, 0x82, 0x04, 0xef, 0xc1, 0xaf, 0x9b, + 0x22, 0x41, 0x88, 0xdd, 0x97, 0xdf, 0x22, 0x02, + 0x55, 0x58, 0x40, 0x02, 0x5a, 0x09, 0x50, 0x58, + 0x40, 0x07, 0x5a, 0xdd, 0x97, 0x1f, 0x2d, 0xb8, + 0x5a, 0x7a, 0x88, 0xb7, 0x5b, 0x9b, 0x22, 0xc7, + 0x8f, 0xb4, 0x50, 0x75, 0x88, 0xdc, 0x5b, 0xb7, + 0x8f, 0x58, 0x41, 0x01, 0x5b, 0x01, 0x0c, 0xad, + 0x7f, 0xd6, 0x50, 0x41, 0x2e, 0x52, 0xdf, 0xed, + 0x1c, 0x04, 0x18, 0x41, 0x2e, 0x52, 0xbf, 0x05, + 0x27, 0x00, 0x2e, 0xb9, 0x8b, 0xae, 0xdf, 0xe0, + 0x19, 0xae, 0xbf, 0x57, 0x40, 0x00, 0x5b, 0xa1, + 0x32, 0x57, 0x43, 0x00, 0x5b, 0xae, 0x3f, 0x05, + 0x81, 0x05, 0x27, 0x41, 0x2e, 0x52, 0xdf, 0x03, + 0x18, 0x41, 0x2e, 0x52, 0xbf, 0x05, 0x27, 0xd3, + 0xdf, 0xff, 0x96, 0x9b, 0x22, 0x0b, 0x88, 0xd3, + 0x3c, 0x07, 0x80, 0xdd, 0x97, 0xff, 0xaf, 0x00, + 0x2e, 0x5d, 0x89, 0xdd, 0x9f, 0x10, 0x1d, 0xd3, + 0xcf, 0x3f, 0x02, 0xd3, 0xaf, 0x05, 0x27, 0x37, + 0x45, 0x0e, 0x5a, 0x40, 0x88, 0x0c, 0x5a, 0xd7, + 0x8f, 0x00, 0x2e, 0xd7, 0x8b, 0x00, 0x2e, 0xeb, + 0x8b, 0x41, 0x2e, 0x52, 0xdf, 0xdf, 0x2d, 0x00, + 0x5b, 0x00, 0x28, 0x00, 0x2e, 0xf0, 0x8b, 0x05, + 0x27, 0xf9, 0xcf, 0xdf, 0x96, 0xf9, 0x3d, 0x00, + 0x2e, 0xd1, 0x8d, 0x28, 0xff, 0xa7, 0xef, 0xe1, + 0xbf, 0xe0, 0xaf, 0x09, 0xef }; static const unsigned char pkt488[] = { -0x42, 0x6c, 0x00, -0x03, 0x24, 0x10, 0xaf, 0xcf, -0x8c, 0x05, 0x81, 0x01, 0x2e, 0x54, 0x80, 0x01, -0x2e, 0x56, 0x80, 0x20, 0x82, 0x3c, 0x8d, 0x37, -0x82, 0x26, 0x37, 0x00, 0x5a, 0x0c, 0x50, 0xff, -0x96, 0xdf, 0x96, 0x79, 0xcf, 0x7a, 0xdf, 0xff, -0x96, 0xdf, 0x96, 0xc2, 0x97, 0xc3, 0x9f, 0x9d, -0x01, 0x5d, 0x01, 0x07, 0x53, 0xdd, 0x97, 0xdd, -0x9f, 0x79, 0xaf, 0x7a, 0xbf, 0x3b, 0x3b, 0xdd, -0x97, 0xf9, 0xaf, 0x05, 0x27, 0xff, 0x22, 0x01, -0x55, 0x32, 0x1e, 0xf3, 0x5f, 0x02, 0x0c, 0xf6, -0x8f, 0x3b, 0x33, 0x00, 0x28, 0x05, 0x27, 0x0d, -0x27, 0x3c, 0x26, 0x07, 0x54, 0x3c, 0xcf, 0x3d, -0xdf, 0x3f, 0x20, 0x3d, 0xbf, 0xdf, 0x03, 0x01, -0x52, 0x3d, 0x23, 0x0c, 0x27, 0x0d, 0x27 + 0x42, 0x6c, 0x00, + 0x03, 0x24, 0x10, 0xaf, 0xcf, + 0x8c, 0x05, 0x81, 0x01, 0x2e, 0x54, 0x80, 0x01, + 0x2e, 0x56, 0x80, 0x20, 0x82, 0x3c, 0x8d, 0x37, + 0x82, 0x26, 0x37, 0x00, 0x5a, 0x0c, 0x50, 0xff, + 0x96, 0xdf, 0x96, 0x79, 0xcf, 0x7a, 0xdf, 0xff, + 0x96, 0xdf, 0x96, 0xc2, 0x97, 0xc3, 0x9f, 0x9d, + 0x01, 0x5d, 0x01, 0x07, 0x53, 0xdd, 0x97, 0xdd, + 0x9f, 0x79, 0xaf, 0x7a, 0xbf, 0x3b, 0x3b, 0xdd, + 0x97, 0xf9, 0xaf, 0x05, 0x27, 0xff, 0x22, 0x01, + 0x55, 0x32, 0x1e, 0xf3, 0x5f, 0x02, 0x0c, 0xf6, + 0x8f, 0x3b, 0x33, 0x00, 0x28, 0x05, 0x27, 0x0d, + 0x27, 0x3c, 0x26, 0x07, 0x54, 0x3c, 0xcf, 0x3d, + 0xdf, 0x3f, 0x20, 0x3d, 0xbf, 0xdf, 0x03, 0x01, + 0x52, 0x3d, 0x23, 0x0c, 0x27, 0x0d, 0x27 }; static const unsigned char pkt492[] = { -0x42, 0x9c, 0x00, -0x38, 0x24, 0x08, 0x44, 0x12, -0x5a, 0x07, 0x40, 0x01, 0x5b, 0x4f, 0x80, 0x00, -0x50, 0x53, 0x80, 0x27, 0x0d, 0x25, 0xcf, 0x1f, -0x98, 0x29, 0xcf, 0x09, 0x27, 0x28, 0xdf, 0x3f, -0x02, 0x5f, 0x98, 0x62, 0xcf, 0xdf, 0x98, 0xd9, -0x0d, 0x02, 0x0d, 0x00, 0x2e, 0xd5, 0x7f, 0x05, -0x27, 0x08, 0x44, 0x22, 0x5a, 0x07, 0x40, 0x01, -0x5b, 0x4f, 0x80, 0x00, 0x50, 0x53, 0x80, 0x0b, -0x0d, 0x07, 0x40, 0x1b, 0x5a, 0x44, 0xcf, 0x1f, -0x20, 0x44, 0xaf, 0x5f, 0x9f, 0xc1, 0x2e, 0x57, -0xdf, 0xff, 0x96, 0x41, 0x2e, 0x56, 0xdf, 0xdf, -0x96, 0x41, 0x2e, 0x58, 0xdf, 0xc1, 0x2e, 0x59, -0xdf, 0x9d, 0x01, 0x5d, 0x01, 0xff, 0x96, 0xdf, -0x96, 0x40, 0x2e, 0x59, 0xdf, 0x5f, 0x9f, 0x50, -0xdf, 0x7f, 0x9f, 0x1d, 0x00, 0xdd, 0x00, 0x5f, -0x9f, 0x7f, 0x9f, 0x05, 0x27, 0x01, 0x0d, 0x41, -0x2e, 0x56, 0xdf, 0x5f, 0x9f, 0x41, 0x2e, 0x57, -0xdf, 0x5f, 0x9f, 0x41, 0x2e, 0x58, 0xdf, 0x5f, -0x9f, 0x41, 0x2e, 0x59, 0xdf, 0x5f, 0x9f, 0x06, -0x0d, 0x3b, 0xcf, 0x5f, 0x9f, 0x05, 0x27 + 0x42, 0x9c, 0x00, + 0x38, 0x24, 0x08, 0x44, 0x12, + 0x5a, 0x07, 0x40, 0x01, 0x5b, 0x4f, 0x80, 0x00, + 0x50, 0x53, 0x80, 0x27, 0x0d, 0x25, 0xcf, 0x1f, + 0x98, 0x29, 0xcf, 0x09, 0x27, 0x28, 0xdf, 0x3f, + 0x02, 0x5f, 0x98, 0x62, 0xcf, 0xdf, 0x98, 0xd9, + 0x0d, 0x02, 0x0d, 0x00, 0x2e, 0xd5, 0x7f, 0x05, + 0x27, 0x08, 0x44, 0x22, 0x5a, 0x07, 0x40, 0x01, + 0x5b, 0x4f, 0x80, 0x00, 0x50, 0x53, 0x80, 0x0b, + 0x0d, 0x07, 0x40, 0x1b, 0x5a, 0x44, 0xcf, 0x1f, + 0x20, 0x44, 0xaf, 0x5f, 0x9f, 0xc1, 0x2e, 0x57, + 0xdf, 0xff, 0x96, 0x41, 0x2e, 0x56, 0xdf, 0xdf, + 0x96, 0x41, 0x2e, 0x58, 0xdf, 0xc1, 0x2e, 0x59, + 0xdf, 0x9d, 0x01, 0x5d, 0x01, 0xff, 0x96, 0xdf, + 0x96, 0x40, 0x2e, 0x59, 0xdf, 0x5f, 0x9f, 0x50, + 0xdf, 0x7f, 0x9f, 0x1d, 0x00, 0xdd, 0x00, 0x5f, + 0x9f, 0x7f, 0x9f, 0x05, 0x27, 0x01, 0x0d, 0x41, + 0x2e, 0x56, 0xdf, 0x5f, 0x9f, 0x41, 0x2e, 0x57, + 0xdf, 0x5f, 0x9f, 0x41, 0x2e, 0x58, 0xdf, 0x5f, + 0x9f, 0x41, 0x2e, 0x59, 0xdf, 0x5f, 0x9f, 0x06, + 0x0d, 0x3b, 0xcf, 0x5f, 0x9f, 0x05, 0x27 }; static const unsigned char pkt496[] = { -0x42, 0xca, 0x00, -0x85, 0x24, 0x02, 0x2e, 0x23, -0x80, 0x02, 0x2e, 0x4c, 0x80, 0x99, 0x88, 0x37, -0x41, 0xdd, 0x2f, 0xc1, 0x5a, 0x0a, 0x40, 0x11, -0x5a, 0x1f, 0x88, 0x41, 0x88, 0x4d, 0x88, 0x37, -0x42, 0x08, 0x5a, 0x09, 0x46, 0x0a, 0x5b, 0x23, -0x26, 0x08, 0x55, 0x22, 0xcf, 0xc6, 0x1e, 0x09, -0x52, 0x10, 0xcf, 0x27, 0xaf, 0x6e, 0x23, 0x08, -0xef, 0x6f, 0xaf, 0x62, 0x23, 0x6e, 0x26, 0x00, -0x55, 0x6e, 0x24, 0x05, 0x27, 0x67, 0x2e, 0xff, -0xdf, 0xdf, 0x22, 0x00, 0x2e, 0x25, 0x55, 0x67, -0x2e, 0xfe, 0xdf, 0xdf, 0x22, 0x00, 0x2e, 0x20, -0x55, 0x05, 0x27, 0x61, 0x23, 0x67, 0x2e, 0xff, -0xdf, 0xdf, 0x22, 0x00, 0x2e, 0x19, 0x55, 0x67, -0x2e, 0xfe, 0xdf, 0x65, 0xdf, 0xbf, 0x03, 0x00, -0x2e, 0x13, 0x5e, 0x3b, 0x43, 0x01, 0x5a, 0x3b, -0x41, 0x0e, 0x5a, 0x29, 0xdf, 0xff, 0x96, 0x25, -0xdf, 0x5d, 0x00, 0x10, 0x1f, 0x00, 0x2e, 0x08, -0x53, 0x07, 0x1f, 0x05, 0x53, 0x61, 0x24, 0x3b, -0x41, 0x02, 0x5a, 0x03, 0x1f, 0x00, 0x53, 0x61, -0x24, 0x05, 0x27, 0xff, 0xef, 0x61, 0xaf, 0x05, -0x27, 0x3b, 0x43, 0x09, 0x5b, 0x28, 0xdf, 0x6e, -0xbf, 0x70, 0xef, 0xbf, 0x22, 0x1a, 0x27, 0x29, -0xdf, 0x6e, 0xcf, 0xdf, 0x01, 0x6d, 0x80, 0x6f, -0xaf, 0x05, 0x27, 0x62, 0x26, 0x01, 0x54, 0x61, -0x47, 0x1d, 0x5b, 0x10, 0xdf, 0x27, 0xbf, 0x61, -0xcf, 0xdf, 0x22, 0x18, 0x54 + 0x42, 0xca, 0x00, + 0x85, 0x24, 0x02, 0x2e, 0x23, + 0x80, 0x02, 0x2e, 0x4c, 0x80, 0x99, 0x88, 0x37, + 0x41, 0xdd, 0x2f, 0xc1, 0x5a, 0x0a, 0x40, 0x11, + 0x5a, 0x1f, 0x88, 0x41, 0x88, 0x4d, 0x88, 0x37, + 0x42, 0x08, 0x5a, 0x09, 0x46, 0x0a, 0x5b, 0x23, + 0x26, 0x08, 0x55, 0x22, 0xcf, 0xc6, 0x1e, 0x09, + 0x52, 0x10, 0xcf, 0x27, 0xaf, 0x6e, 0x23, 0x08, + 0xef, 0x6f, 0xaf, 0x62, 0x23, 0x6e, 0x26, 0x00, + 0x55, 0x6e, 0x24, 0x05, 0x27, 0x67, 0x2e, 0xff, + 0xdf, 0xdf, 0x22, 0x00, 0x2e, 0x25, 0x55, 0x67, + 0x2e, 0xfe, 0xdf, 0xdf, 0x22, 0x00, 0x2e, 0x20, + 0x55, 0x05, 0x27, 0x61, 0x23, 0x67, 0x2e, 0xff, + 0xdf, 0xdf, 0x22, 0x00, 0x2e, 0x19, 0x55, 0x67, + 0x2e, 0xfe, 0xdf, 0x65, 0xdf, 0xbf, 0x03, 0x00, + 0x2e, 0x13, 0x5e, 0x3b, 0x43, 0x01, 0x5a, 0x3b, + 0x41, 0x0e, 0x5a, 0x29, 0xdf, 0xff, 0x96, 0x25, + 0xdf, 0x5d, 0x00, 0x10, 0x1f, 0x00, 0x2e, 0x08, + 0x53, 0x07, 0x1f, 0x05, 0x53, 0x61, 0x24, 0x3b, + 0x41, 0x02, 0x5a, 0x03, 0x1f, 0x00, 0x53, 0x61, + 0x24, 0x05, 0x27, 0xff, 0xef, 0x61, 0xaf, 0x05, + 0x27, 0x3b, 0x43, 0x09, 0x5b, 0x28, 0xdf, 0x6e, + 0xbf, 0x70, 0xef, 0xbf, 0x22, 0x1a, 0x27, 0x29, + 0xdf, 0x6e, 0xcf, 0xdf, 0x01, 0x6d, 0x80, 0x6f, + 0xaf, 0x05, 0x27, 0x62, 0x26, 0x01, 0x54, 0x61, + 0x47, 0x1d, 0x5b, 0x10, 0xdf, 0x27, 0xbf, 0x61, + 0xcf, 0xdf, 0x22, 0x18, 0x54 }; static const unsigned char pkt500[] = { -0x42, 0xca, 0x00, -0xe9, 0x24, 0x5f, 0x00, 0x00, -0x57, 0xbf, 0x22, 0x5f, 0xcf, 0xdf, 0x03, 0x00, -0x5f, 0x5f, 0xdf, 0x27, 0xbf, 0x61, 0xcf, 0xdf, -0x2d, 0x00, 0x2e, 0x19, 0x5a, 0x26, 0x88, 0xdf, -0x96, 0x6e, 0xdf, 0x09, 0x88, 0x6e, 0xbf, 0xc0, -0x97, 0x62, 0xdf, 0x05, 0x88, 0x62, 0xbf, 0x6f, -0xdf, 0xdd, 0x97, 0x06, 0x88, 0x6f, 0xaf, 0x05, -0x27, 0x8a, 0x80, 0x20, 0x10, 0x00, 0x13, 0x1c, -0x82, 0x05, 0x27, 0xdf, 0x96, 0x9f, 0x22, 0xd9, -0x81, 0x1a, 0x27, 0xdd, 0x9f, 0x6d, 0x80, 0x05, -0x27, 0x0c, 0x88, 0xdf, 0x96, 0x6f, 0xdf, 0xef, -0x8f, 0x6f, 0xbf, 0x6e, 0xdf, 0xc0, 0x97, 0xf0, -0x8f, 0x6e, 0xaf, 0x62, 0xdf, 0xdd, 0x97, 0xec, -0x8f, 0x62, 0xaf, 0x05, 0x27, 0x27, 0xcf, 0x61, -0x47, 0x00, 0x5b, 0x1f, 0x20, 0x09, 0x8c, 0xff, -0x97, 0x05, 0x27, 0x28, 0xdf, 0x06, 0x88, 0x2d, -0xbf, 0x2c, 0xaf, 0x29, 0xdf, 0x02, 0x88, 0x2b, -0xbf, 0x2a, 0xaf, 0x05, 0x27, 0xff, 0x96, 0x72, -0xcf, 0x01, 0x16, 0xdf, 0x96, 0x57, 0xef, 0x25, -0xff, 0x1d, 0x00, 0x00, 0x13, 0x1a, 0x27, 0x07, -0x27, 0xff, 0x96, 0xc1, 0x9f, 0x3f, 0x22, 0x01, -0x11, 0x8a, 0x80, 0xff, 0x96, 0xdf, 0x96, 0xc2, -0x97, 0xc3, 0x9f, 0x3f, 0x22, 0x01, 0x11, 0x8a, -0x80, 0x01, 0x00, 0xdf, 0x9f, 0xc0, 0x97, 0x04, -0x0c, 0xff, 0x96, 0xdf, 0x96, 0x72, 0xcf, 0x07, -0x1e, 0x04, 0x53, 0x03, 0x1e + 0x42, 0xca, 0x00, + 0xe9, 0x24, 0x5f, 0x00, 0x00, + 0x57, 0xbf, 0x22, 0x5f, 0xcf, 0xdf, 0x03, 0x00, + 0x5f, 0x5f, 0xdf, 0x27, 0xbf, 0x61, 0xcf, 0xdf, + 0x2d, 0x00, 0x2e, 0x19, 0x5a, 0x26, 0x88, 0xdf, + 0x96, 0x6e, 0xdf, 0x09, 0x88, 0x6e, 0xbf, 0xc0, + 0x97, 0x62, 0xdf, 0x05, 0x88, 0x62, 0xbf, 0x6f, + 0xdf, 0xdd, 0x97, 0x06, 0x88, 0x6f, 0xaf, 0x05, + 0x27, 0x8a, 0x80, 0x20, 0x10, 0x00, 0x13, 0x1c, + 0x82, 0x05, 0x27, 0xdf, 0x96, 0x9f, 0x22, 0xd9, + 0x81, 0x1a, 0x27, 0xdd, 0x9f, 0x6d, 0x80, 0x05, + 0x27, 0x0c, 0x88, 0xdf, 0x96, 0x6f, 0xdf, 0xef, + 0x8f, 0x6f, 0xbf, 0x6e, 0xdf, 0xc0, 0x97, 0xf0, + 0x8f, 0x6e, 0xaf, 0x62, 0xdf, 0xdd, 0x97, 0xec, + 0x8f, 0x62, 0xaf, 0x05, 0x27, 0x27, 0xcf, 0x61, + 0x47, 0x00, 0x5b, 0x1f, 0x20, 0x09, 0x8c, 0xff, + 0x97, 0x05, 0x27, 0x28, 0xdf, 0x06, 0x88, 0x2d, + 0xbf, 0x2c, 0xaf, 0x29, 0xdf, 0x02, 0x88, 0x2b, + 0xbf, 0x2a, 0xaf, 0x05, 0x27, 0xff, 0x96, 0x72, + 0xcf, 0x01, 0x16, 0xdf, 0x96, 0x57, 0xef, 0x25, + 0xff, 0x1d, 0x00, 0x00, 0x13, 0x1a, 0x27, 0x07, + 0x27, 0xff, 0x96, 0xc1, 0x9f, 0x3f, 0x22, 0x01, + 0x11, 0x8a, 0x80, 0xff, 0x96, 0xdf, 0x96, 0xc2, + 0x97, 0xc3, 0x9f, 0x3f, 0x22, 0x01, 0x11, 0x8a, + 0x80, 0x01, 0x00, 0xdf, 0x9f, 0xc0, 0x97, 0x04, + 0x0c, 0xff, 0x96, 0xdf, 0x96, 0x72, 0xcf, 0x07, + 0x1e, 0x04, 0x53, 0x03, 0x1e }; static const unsigned char pkt504[] = { -0x42, 0x2a, 0x00, -0x4d, 0x25, 0x04, 0x53, 0xdd, -0x97, 0xdd, 0x9f, 0x05, 0x27, 0x00, 0x88, 0xd8, -0x71, 0xdd, 0x97, 0xdd, 0x9f, 0xd8, 0x81, 0x05, -0x27, 0x00, 0x04, 0x00, 0x02, 0x4e, 0x07, 0x8e, -0x03, 0x19, 0x02, 0x0c, 0x01, 0x32, 0x04, 0x1c, -0x02, 0x0e, 0x01, 0x87, 0x00 + 0x42, 0x2a, 0x00, + 0x4d, 0x25, 0x04, 0x53, 0xdd, + 0x97, 0xdd, 0x9f, 0x05, 0x27, 0x00, 0x88, 0xd8, + 0x71, 0xdd, 0x97, 0xdd, 0x9f, 0xd8, 0x81, 0x05, + 0x27, 0x00, 0x04, 0x00, 0x02, 0x4e, 0x07, 0x8e, + 0x03, 0x19, 0x02, 0x0c, 0x01, 0x32, 0x04, 0x1c, + 0x02, 0x0e, 0x01, 0x87, 0x00 }; static const unsigned char pkt508[] = { -0x42, 0x8c, 0x00, -0x61, 0x25, 0x53, 0x80, 0x01, -0x0d, 0xf5, 0x97, 0xff, 0x0d, 0x1f, 0x99, 0x49, -0xcf, 0x5f, 0x99, 0x08, 0x44, 0x00, 0x2e, 0x39, -0x5a, 0x0b, 0x0d, 0x44, 0xcf, 0x0c, 0x41, 0x00, -0x5b, 0x1f, 0x20, 0x44, 0xaf, 0x5f, 0x9f, 0x04, -0x0d, 0x47, 0xcf, 0x5f, 0x9f, 0x48, 0xcf, 0x5f, -0x9f, 0x1c, 0xcf, 0x5f, 0x9f, 0x1d, 0xcf, 0x5f, -0x9f, 0x1e, 0xcf, 0x5f, 0x9f, 0x49, 0xcf, 0x5f, -0x9f, 0x06, 0x0d, 0xe0, 0x97, 0x0f, 0x1c, 0x5f, -0x9f, 0x0a, 0xcf, 0x5f, 0x9f, 0x09, 0xcf, 0x5f, -0x9f, 0x2a, 0xcf, 0x5f, 0x9f, 0x2b, 0xcf, 0x5f, -0x9f, 0x2c, 0xcf, 0x5f, 0x9f, 0x2d, 0xcf, 0x5f, -0x9f, 0x02, 0x0d, 0x16, 0xcf, 0x5f, 0x9f, 0x44, -0xdf, 0x02, 0x2e, 0x5f, 0x81, 0x5f, 0x9f, 0x4d, -0xcf, 0x5f, 0x9f, 0x09, 0x46, 0x04, 0x5b, 0x90, -0xcf, 0x5f, 0x9f, 0x91, 0xcf, 0x5f, 0x9f, 0x05, -0x50, 0x01, 0x0d, 0x6a, 0xcf, 0x09, 0x27, 0x69, -0xdf, 0x3f, 0x02, 0x5f, 0x9f, 0x05, 0x27 + 0x42, 0x8c, 0x00, + 0x61, 0x25, 0x53, 0x80, 0x01, + 0x0d, 0xf5, 0x97, 0xff, 0x0d, 0x1f, 0x99, 0x49, + 0xcf, 0x5f, 0x99, 0x08, 0x44, 0x00, 0x2e, 0x39, + 0x5a, 0x0b, 0x0d, 0x44, 0xcf, 0x0c, 0x41, 0x00, + 0x5b, 0x1f, 0x20, 0x44, 0xaf, 0x5f, 0x9f, 0x04, + 0x0d, 0x47, 0xcf, 0x5f, 0x9f, 0x48, 0xcf, 0x5f, + 0x9f, 0x1c, 0xcf, 0x5f, 0x9f, 0x1d, 0xcf, 0x5f, + 0x9f, 0x1e, 0xcf, 0x5f, 0x9f, 0x49, 0xcf, 0x5f, + 0x9f, 0x06, 0x0d, 0xe0, 0x97, 0x0f, 0x1c, 0x5f, + 0x9f, 0x0a, 0xcf, 0x5f, 0x9f, 0x09, 0xcf, 0x5f, + 0x9f, 0x2a, 0xcf, 0x5f, 0x9f, 0x2b, 0xcf, 0x5f, + 0x9f, 0x2c, 0xcf, 0x5f, 0x9f, 0x2d, 0xcf, 0x5f, + 0x9f, 0x02, 0x0d, 0x16, 0xcf, 0x5f, 0x9f, 0x44, + 0xdf, 0x02, 0x2e, 0x5f, 0x81, 0x5f, 0x9f, 0x4d, + 0xcf, 0x5f, 0x9f, 0x09, 0x46, 0x04, 0x5b, 0x90, + 0xcf, 0x5f, 0x9f, 0x91, 0xcf, 0x5f, 0x9f, 0x05, + 0x50, 0x01, 0x0d, 0x6a, 0xcf, 0x09, 0x27, 0x69, + 0xdf, 0x3f, 0x02, 0x5f, 0x9f, 0x05, 0x27 }; static const unsigned char pkt512[] = { -0x42, 0xca, 0x00, -0xa6, 0x25, 0x5c, 0x46, 0x00, -0x5b, 0xfb, 0x31, 0x2d, 0x8a, 0xa9, 0x89, 0xbe, -0x89, 0x06, 0x8a, 0x18, 0x89, 0x18, 0x89, 0x40, -0xcf, 0x41, 0xdf, 0x45, 0xaf, 0x46, 0xbf, 0x07, -0x38, 0x01, 0x5b, 0x01, 0x2e, 0xb7, 0x80, 0x3b, -0x40, 0x00, 0x2e, 0x42, 0x5b, 0x5c, 0x47, 0x00, -0x5a, 0xad, 0x89, 0x09, 0x46, 0x00, 0x5b, 0x75, -0x8d, 0xc9, 0x30, 0x41, 0x2e, 0x7a, 0xdf, 0x1f, -0x28, 0x41, 0x2e, 0x7a, 0xbf, 0xfb, 0x39, 0xfa, -0x33, 0xc8, 0x46, 0x10, 0x5b, 0xd0, 0x46, 0xfd, -0x5b, 0xd3, 0x45, 0xfd, 0x5a, 0xd3, 0x45, 0xfb, -0x5a, 0xd3, 0x45, 0xf9, 0x5a, 0xd3, 0x3c, 0x41, -0x2e, 0xa1, 0xdf, 0x9f, 0x28, 0x41, 0x2e, 0xa1, -0xbf, 0x02, 0x2e, 0xb0, 0x81, 0x0c, 0x78, 0x64, -0x81, 0xd3, 0x45, 0xe9, 0x5a, 0xd3, 0x3c, 0xc8, -0xcf, 0xdf, 0x22, 0x02, 0x55, 0xc7, 0xcf, 0xdf, -0x22, 0x02, 0x54, 0xd3, 0x33, 0xd3, 0x31, 0x64, -0x81, 0xf7, 0xef, 0x16, 0x80, 0xf8, 0xcf, 0x9f, -0x1c, 0xf8, 0xaf, 0xfb, 0x39, 0xfa, 0x33, 0x5c, -0x47, 0x03, 0x5a, 0x08, 0x43, 0xdc, 0x2f, 0xec, -0x5a, 0x02, 0x50, 0x3d, 0x23, 0xdc, 0x2f, 0xe8, -0x50, 0x02, 0xcf, 0x0f, 0x1c, 0x10, 0x18, 0x02, -0xaf, 0xe1, 0x72, 0x5c, 0x46, 0x01, 0x5a, 0x01, -0x2e, 0xcd, 0x80, 0xd0, 0x41, 0x00, 0x5b, 0xc1, -0x83, 0x52, 0x26, 0xe6, 0x2f, 0xbd, 0x55, 0x53, -0x26, 0xe6, 0x2f, 0xba, 0x55 + 0x42, 0xca, 0x00, + 0xa6, 0x25, 0x5c, 0x46, 0x00, + 0x5b, 0xfb, 0x31, 0x2d, 0x8a, 0xa9, 0x89, 0xbe, + 0x89, 0x06, 0x8a, 0x18, 0x89, 0x18, 0x89, 0x40, + 0xcf, 0x41, 0xdf, 0x45, 0xaf, 0x46, 0xbf, 0x07, + 0x38, 0x01, 0x5b, 0x01, 0x2e, 0xb7, 0x80, 0x3b, + 0x40, 0x00, 0x2e, 0x42, 0x5b, 0x5c, 0x47, 0x00, + 0x5a, 0xad, 0x89, 0x09, 0x46, 0x00, 0x5b, 0x75, + 0x8d, 0xc9, 0x30, 0x41, 0x2e, 0x7a, 0xdf, 0x1f, + 0x28, 0x41, 0x2e, 0x7a, 0xbf, 0xfb, 0x39, 0xfa, + 0x33, 0xc8, 0x46, 0x10, 0x5b, 0xd0, 0x46, 0xfd, + 0x5b, 0xd3, 0x45, 0xfd, 0x5a, 0xd3, 0x45, 0xfb, + 0x5a, 0xd3, 0x45, 0xf9, 0x5a, 0xd3, 0x3c, 0x41, + 0x2e, 0xa1, 0xdf, 0x9f, 0x28, 0x41, 0x2e, 0xa1, + 0xbf, 0x02, 0x2e, 0xb0, 0x81, 0x0c, 0x78, 0x64, + 0x81, 0xd3, 0x45, 0xe9, 0x5a, 0xd3, 0x3c, 0xc8, + 0xcf, 0xdf, 0x22, 0x02, 0x55, 0xc7, 0xcf, 0xdf, + 0x22, 0x02, 0x54, 0xd3, 0x33, 0xd3, 0x31, 0x64, + 0x81, 0xf7, 0xef, 0x16, 0x80, 0xf8, 0xcf, 0x9f, + 0x1c, 0xf8, 0xaf, 0xfb, 0x39, 0xfa, 0x33, 0x5c, + 0x47, 0x03, 0x5a, 0x08, 0x43, 0xdc, 0x2f, 0xec, + 0x5a, 0x02, 0x50, 0x3d, 0x23, 0xdc, 0x2f, 0xe8, + 0x50, 0x02, 0xcf, 0x0f, 0x1c, 0x10, 0x18, 0x02, + 0xaf, 0xe1, 0x72, 0x5c, 0x46, 0x01, 0x5a, 0x01, + 0x2e, 0xcd, 0x80, 0xd0, 0x41, 0x00, 0x5b, 0xc1, + 0x83, 0x52, 0x26, 0xe6, 0x2f, 0xbd, 0x55, 0x53, + 0x26, 0xe6, 0x2f, 0xba, 0x55 }; static const unsigned char pkt516[] = { -0x42, 0xca, 0x00, -0x0a, 0x26, 0x07, 0x3a, 0x00, -0x2e, 0x38, 0x7c, 0x02, 0x2e, 0x49, 0x81, 0x45, -0xcf, 0x46, 0xdf, 0x19, 0x27, 0xef, 0x88, 0x02, -0x89, 0x05, 0x27, 0x12, 0x82, 0x05, 0x27, 0x41, -0x8a, 0x10, 0x5b, 0x49, 0xef, 0xff, 0xaf, 0x05, -0xef, 0xff, 0xaf, 0x9f, 0x22, 0xff, 0xaf, 0x10, -0xef, 0xff, 0xaf, 0x22, 0xcf, 0xff, 0xaf, 0x23, -0xcf, 0xff, 0xaf, 0x9f, 0x22, 0xff, 0xaf, 0xff, -0xaf, 0x02, 0x2e, 0xa1, 0x81, 0x0c, 0x40, 0x29, -0x5b, 0x4a, 0x80, 0x0d, 0x34, 0x10, 0x5a, 0x49, -0xcf, 0x5f, 0x9d, 0x49, 0x38, 0x53, 0x80, 0x49, -0xcf, 0x5f, 0x9d, 0x4a, 0x80, 0x9f, 0x22, 0x1f, -0x9c, 0x5f, 0x9c, 0x1e, 0xcf, 0x1f, 0x9d, 0x48, -0xcf, 0x1d, 0xdf, 0xdf, 0x01, 0x9f, 0x22, 0x11, -0x50, 0xbb, 0x88, 0xf5, 0x97, 0x49, 0xaf, 0xd4, -0x89, 0x49, 0xcf, 0xf7, 0x1c, 0x5f, 0x9d, 0x44, -0xdf, 0x3f, 0x20, 0x44, 0xbf, 0xff, 0x9a, 0x02, -0x2e, 0x5f, 0x81, 0x20, 0x0d, 0x9f, 0x99, 0xe0, -0x0d, 0x1c, 0xcf, 0x1d, 0xdf, 0x9f, 0x9c, 0xff, -0x9c, 0x00, 0x2e, 0xe9, 0x8f, 0x0c, 0x41, 0x01, -0x5b, 0x00, 0x2e, 0xeb, 0x8f, 0x0c, 0x42, 0x04, -0x5b, 0xe4, 0x40, 0x01, 0x5a, 0xe4, 0x3a, 0x00, -0x50, 0xe4, 0x32, 0x0c, 0x43, 0x04, 0x5b, 0xe4, -0x42, 0x01, 0x5a, 0xe4, 0x30, 0x00, 0x50, 0xe4, -0x38, 0x0c, 0x44, 0x10, 0x5b, 0x18, 0x23, 0x1a, -0x23, 0x1b, 0x23, 0xe4, 0x42 + 0x42, 0xca, 0x00, + 0x0a, 0x26, 0x07, 0x3a, 0x00, + 0x2e, 0x38, 0x7c, 0x02, 0x2e, 0x49, 0x81, 0x45, + 0xcf, 0x46, 0xdf, 0x19, 0x27, 0xef, 0x88, 0x02, + 0x89, 0x05, 0x27, 0x12, 0x82, 0x05, 0x27, 0x41, + 0x8a, 0x10, 0x5b, 0x49, 0xef, 0xff, 0xaf, 0x05, + 0xef, 0xff, 0xaf, 0x9f, 0x22, 0xff, 0xaf, 0x10, + 0xef, 0xff, 0xaf, 0x22, 0xcf, 0xff, 0xaf, 0x23, + 0xcf, 0xff, 0xaf, 0x9f, 0x22, 0xff, 0xaf, 0xff, + 0xaf, 0x02, 0x2e, 0xa1, 0x81, 0x0c, 0x40, 0x29, + 0x5b, 0x4a, 0x80, 0x0d, 0x34, 0x10, 0x5a, 0x49, + 0xcf, 0x5f, 0x9d, 0x49, 0x38, 0x53, 0x80, 0x49, + 0xcf, 0x5f, 0x9d, 0x4a, 0x80, 0x9f, 0x22, 0x1f, + 0x9c, 0x5f, 0x9c, 0x1e, 0xcf, 0x1f, 0x9d, 0x48, + 0xcf, 0x1d, 0xdf, 0xdf, 0x01, 0x9f, 0x22, 0x11, + 0x50, 0xbb, 0x88, 0xf5, 0x97, 0x49, 0xaf, 0xd4, + 0x89, 0x49, 0xcf, 0xf7, 0x1c, 0x5f, 0x9d, 0x44, + 0xdf, 0x3f, 0x20, 0x44, 0xbf, 0xff, 0x9a, 0x02, + 0x2e, 0x5f, 0x81, 0x20, 0x0d, 0x9f, 0x99, 0xe0, + 0x0d, 0x1c, 0xcf, 0x1d, 0xdf, 0x9f, 0x9c, 0xff, + 0x9c, 0x00, 0x2e, 0xe9, 0x8f, 0x0c, 0x41, 0x01, + 0x5b, 0x00, 0x2e, 0xeb, 0x8f, 0x0c, 0x42, 0x04, + 0x5b, 0xe4, 0x40, 0x01, 0x5a, 0xe4, 0x3a, 0x00, + 0x50, 0xe4, 0x32, 0x0c, 0x43, 0x04, 0x5b, 0xe4, + 0x42, 0x01, 0x5a, 0xe4, 0x30, 0x00, 0x50, 0xe4, + 0x38, 0x0c, 0x44, 0x10, 0x5b, 0x18, 0x23, 0x1a, + 0x23, 0x1b, 0x23, 0xe4, 0x42 }; static const unsigned char pkt520[] = { -0x42, 0xca, 0x00, -0x6e, 0x26, 0x01, 0x5a, 0xe4, -0x38, 0x00, 0x50, 0xe4, 0x30, 0x4a, 0x80, 0x2b, -0x0d, 0x02, 0x2e, 0x9d, 0x81, 0xe4, 0x42, 0x01, -0x5a, 0xe4, 0x30, 0x00, 0x50, 0xe4, 0x38, 0x0c, -0x45, 0x00, 0x5b, 0x0f, 0x88, 0x0c, 0x46, 0x01, -0x5a, 0x01, 0x2e, 0xb7, 0x80, 0x0c, 0x43, 0x05, -0x5b, 0x0c, 0x45, 0x03, 0x5b, 0x0d, 0x45, 0x01, -0x5b, 0x0d, 0x37, 0x05, 0x27, 0x0c, 0x40, 0x00, -0x5b, 0x0d, 0x3f, 0x05, 0x27, 0x60, 0xcf, 0x0f, -0x1c, 0xdf, 0x9f, 0x0c, 0x1c, 0x12, 0x82, 0x03, -0x1d, 0x19, 0x82, 0x5f, 0x02, 0x60, 0xcf, 0xf0, -0x1c, 0x3f, 0x02, 0x60, 0xaf, 0x05, 0x27, 0x28, -0xff, 0x64, 0xef, 0x19, 0x27, 0x01, 0xff, 0x5a, -0xef, 0x1b, 0x27, 0x06, 0xef, 0x06, 0xaf, 0xfc, -0x97, 0x5f, 0x9f, 0x06, 0x25, 0xfb, 0x55, 0x05, -0x27, 0x10, 0xcf, 0x72, 0xaf, 0x0a, 0x40, 0x13, -0x5a, 0x27, 0xcf, 0x10, 0xaf, 0x07, 0x43, 0x08, -0x5b, 0x3b, 0x31, 0x02, 0x5b, 0x3b, 0x36, 0x3b, -0x43, 0x03, 0x5b, 0x6e, 0xcf, 0xe2, 0xaf, 0x6f, -0xcf, 0xe3, 0xaf, 0x02, 0x2e, 0xd5, 0x80, 0x07, -0x40, 0x02, 0x5a, 0x61, 0x26, 0x00, 0x55, 0x07, -0x33, 0x88, 0x82, 0x02, 0x43, 0xdb, 0x2f, 0xc7, -0x5b, 0x02, 0x2e, 0x72, 0x80, 0x05, 0x27, 0x05, -0x27, 0x05, 0x27, 0x0c, 0xcf, 0x03, 0x1c, 0x0b, -0x55, 0x0c, 0xcf, 0x0c, 0x1c, 0x0c, 0x1e, 0x07, -0x54, 0x08, 0x1e, 0x03, 0x55 + 0x42, 0xca, 0x00, + 0x6e, 0x26, 0x01, 0x5a, 0xe4, + 0x38, 0x00, 0x50, 0xe4, 0x30, 0x4a, 0x80, 0x2b, + 0x0d, 0x02, 0x2e, 0x9d, 0x81, 0xe4, 0x42, 0x01, + 0x5a, 0xe4, 0x30, 0x00, 0x50, 0xe4, 0x38, 0x0c, + 0x45, 0x00, 0x5b, 0x0f, 0x88, 0x0c, 0x46, 0x01, + 0x5a, 0x01, 0x2e, 0xb7, 0x80, 0x0c, 0x43, 0x05, + 0x5b, 0x0c, 0x45, 0x03, 0x5b, 0x0d, 0x45, 0x01, + 0x5b, 0x0d, 0x37, 0x05, 0x27, 0x0c, 0x40, 0x00, + 0x5b, 0x0d, 0x3f, 0x05, 0x27, 0x60, 0xcf, 0x0f, + 0x1c, 0xdf, 0x9f, 0x0c, 0x1c, 0x12, 0x82, 0x03, + 0x1d, 0x19, 0x82, 0x5f, 0x02, 0x60, 0xcf, 0xf0, + 0x1c, 0x3f, 0x02, 0x60, 0xaf, 0x05, 0x27, 0x28, + 0xff, 0x64, 0xef, 0x19, 0x27, 0x01, 0xff, 0x5a, + 0xef, 0x1b, 0x27, 0x06, 0xef, 0x06, 0xaf, 0xfc, + 0x97, 0x5f, 0x9f, 0x06, 0x25, 0xfb, 0x55, 0x05, + 0x27, 0x10, 0xcf, 0x72, 0xaf, 0x0a, 0x40, 0x13, + 0x5a, 0x27, 0xcf, 0x10, 0xaf, 0x07, 0x43, 0x08, + 0x5b, 0x3b, 0x31, 0x02, 0x5b, 0x3b, 0x36, 0x3b, + 0x43, 0x03, 0x5b, 0x6e, 0xcf, 0xe2, 0xaf, 0x6f, + 0xcf, 0xe3, 0xaf, 0x02, 0x2e, 0xd5, 0x80, 0x07, + 0x40, 0x02, 0x5a, 0x61, 0x26, 0x00, 0x55, 0x07, + 0x33, 0x88, 0x82, 0x02, 0x43, 0xdb, 0x2f, 0xc7, + 0x5b, 0x02, 0x2e, 0x72, 0x80, 0x05, 0x27, 0x05, + 0x27, 0x05, 0x27, 0x0c, 0xcf, 0x03, 0x1c, 0x0b, + 0x55, 0x0c, 0xcf, 0x0c, 0x1c, 0x0c, 0x1e, 0x07, + 0x54, 0x08, 0x1e, 0x03, 0x55 }; static const unsigned char pkt524[] = { -0x42, 0xca, 0x00, -0xd2, 0x26, 0x0c, 0x45, 0x01, -0x5b, 0x0d, 0x44, 0x01, 0x5b, 0x0e, 0x33, 0x05, -0x27, 0x0e, 0x3b, 0x05, 0x27, 0x0d, 0xcf, 0x06, -0x1c, 0x09, 0x55, 0x09, 0x46, 0x04, 0x5b, 0x15, -0x88, 0x02, 0x5a, 0xf2, 0xcf, 0x0b, 0xaf, 0x10, -0x50, 0x02, 0xef, 0x0c, 0xaf, 0x0d, 0x50, 0x0a, -0x41, 0x0b, 0x5b, 0x0c, 0x39, 0x0c, 0x46, 0x03, -0x5b, 0x4a, 0x80, 0x0e, 0x88, 0x29, 0x89, 0x00, -0x50, 0x0c, 0x31, 0x0c, 0x38, 0x01, 0x5b, 0x0d, -0x3f, 0x0d, 0x34, 0x05, 0x27, 0x23, 0x26, 0x02, -0x55, 0x22, 0xcf, 0xc8, 0x1e, 0x00, 0x5f, 0x0c, -0x27, 0x0d, 0x27, 0xf0, 0x97, 0x47, 0xaf, 0xf1, -0x97, 0x48, 0xaf, 0x05, 0x27, 0x46, 0x80, 0x08, -0x46, 0x0f, 0x5a, 0xde, 0xef, 0x5f, 0x9f, 0x10, -0xef, 0x5f, 0x9f, 0x00, 0xef, 0x5f, 0x9f, 0x28, -0xff, 0x54, 0xef, 0x1b, 0x27, 0x10, 0xef, 0x06, -0xaf, 0xfc, 0x97, 0x5f, 0x9f, 0x06, 0x25, 0xfb, -0x55, 0x62, 0x80, 0x05, 0x27, 0x46, 0x80, 0x08, -0x47, 0xfb, 0x5a, 0xdf, 0xef, 0x5f, 0x9f, 0x06, -0xef, 0x5f, 0x9f, 0x00, 0xef, 0x5f, 0x9f, 0x28, -0xff, 0x64, 0xef, 0x1b, 0x27, 0x06, 0xef, 0x06, -0xaf, 0xea, 0x50, 0x28, 0xff, 0x64, 0xef, 0x19, -0x27, 0x0f, 0xef, 0x6b, 0xdf, 0xff, 0x96, 0xbf, -0x22, 0xff, 0x96, 0x7b, 0x00, 0xc1, 0x03, 0x6b, -0xbf, 0x0c, 0x53, 0xdf, 0x96, 0xc2, 0x97, 0xbf, -0x01, 0x5f, 0x90, 0xdd, 0x97 + 0x42, 0xca, 0x00, + 0xd2, 0x26, 0x0c, 0x45, 0x01, + 0x5b, 0x0d, 0x44, 0x01, 0x5b, 0x0e, 0x33, 0x05, + 0x27, 0x0e, 0x3b, 0x05, 0x27, 0x0d, 0xcf, 0x06, + 0x1c, 0x09, 0x55, 0x09, 0x46, 0x04, 0x5b, 0x15, + 0x88, 0x02, 0x5a, 0xf2, 0xcf, 0x0b, 0xaf, 0x10, + 0x50, 0x02, 0xef, 0x0c, 0xaf, 0x0d, 0x50, 0x0a, + 0x41, 0x0b, 0x5b, 0x0c, 0x39, 0x0c, 0x46, 0x03, + 0x5b, 0x4a, 0x80, 0x0e, 0x88, 0x29, 0x89, 0x00, + 0x50, 0x0c, 0x31, 0x0c, 0x38, 0x01, 0x5b, 0x0d, + 0x3f, 0x0d, 0x34, 0x05, 0x27, 0x23, 0x26, 0x02, + 0x55, 0x22, 0xcf, 0xc8, 0x1e, 0x00, 0x5f, 0x0c, + 0x27, 0x0d, 0x27, 0xf0, 0x97, 0x47, 0xaf, 0xf1, + 0x97, 0x48, 0xaf, 0x05, 0x27, 0x46, 0x80, 0x08, + 0x46, 0x0f, 0x5a, 0xde, 0xef, 0x5f, 0x9f, 0x10, + 0xef, 0x5f, 0x9f, 0x00, 0xef, 0x5f, 0x9f, 0x28, + 0xff, 0x54, 0xef, 0x1b, 0x27, 0x10, 0xef, 0x06, + 0xaf, 0xfc, 0x97, 0x5f, 0x9f, 0x06, 0x25, 0xfb, + 0x55, 0x62, 0x80, 0x05, 0x27, 0x46, 0x80, 0x08, + 0x47, 0xfb, 0x5a, 0xdf, 0xef, 0x5f, 0x9f, 0x06, + 0xef, 0x5f, 0x9f, 0x00, 0xef, 0x5f, 0x9f, 0x28, + 0xff, 0x64, 0xef, 0x1b, 0x27, 0x06, 0xef, 0x06, + 0xaf, 0xea, 0x50, 0x28, 0xff, 0x64, 0xef, 0x19, + 0x27, 0x0f, 0xef, 0x6b, 0xdf, 0xff, 0x96, 0xbf, + 0x22, 0xff, 0x96, 0x7b, 0x00, 0xc1, 0x03, 0x6b, + 0xbf, 0x0c, 0x53, 0xdf, 0x96, 0xc2, 0x97, 0xbf, + 0x01, 0x5f, 0x90, 0xdd, 0x97 }; static const unsigned char pkt528[] = { -0x42, 0xca, 0x00, -0x36, 0x27, 0x5f, 0x20, 0x02, -0x1e, 0xf3, 0x53, 0x02, 0xef, 0x01, 0x0c, 0xdd, -0x9f, 0x6b, 0xbf, 0x15, 0x50, 0xdf, 0x96, 0xc2, -0x97, 0xdf, 0x01, 0xc1, 0x03, 0x05, 0x52, 0xdd, -0x97, 0x1f, 0x20, 0x6b, 0xdf, 0xe0, 0x01, 0x6b, -0xbf, 0x00, 0x50, 0xdd, 0x97, 0x02, 0x0c, 0x6b, -0xdf, 0x28, 0x1f, 0x01, 0x53, 0x28, 0xff, 0x6b, -0xbf, 0x68, 0x1f, 0x01, 0x5f, 0x68, 0xff, 0x6b, -0xbf, 0x05, 0x27, 0x01, 0x81, 0x50, 0x8f, 0xf1, -0x88, 0x05, 0x81, 0x00, 0x2e, 0x32, 0x8d, 0x01, -0x2e, 0x06, 0x80, 0x00, 0x2e, 0xd8, 0x8e, 0x5c, -0x47, 0x02, 0x5b, 0x00, 0x2e, 0x16, 0x8f, 0x01, -0x50, 0x00, 0x2e, 0x14, 0x8f, 0x08, 0xef, 0x0f, -0x80, 0x01, 0x2e, 0x54, 0x80, 0x05, 0x27, 0x07, -0x40, 0x01, 0x5b, 0x54, 0x23, 0x18, 0x50, 0x9c, -0x8e, 0x0d, 0xcf, 0x06, 0x1c, 0x08, 0x54, 0x14, -0x88, 0x02, 0x2e, 0x9d, 0x81, 0x01, 0x2e, 0x50, -0x82, 0x4f, 0x8f, 0x68, 0x88, 0x01, 0x2e, 0x44, -0x84, 0x5c, 0x8f, 0x54, 0x88, 0x09, 0x46, 0x02, -0x5b, 0x37, 0x82, 0x90, 0xaf, 0x91, 0xbf, 0x00, -0x2e, 0xe6, 0x8f, 0x90, 0x8e, 0x0c, 0x3e, 0xed, -0x5a, 0x05, 0x27, 0x37, 0x82, 0x4a, 0x82, 0x1c, -0x82, 0x1c, 0x82, 0x9d, 0xbf, 0xff, 0x97, 0x08, -0x10, 0x09, 0x27, 0x0f, 0x1c, 0x5c, 0x46, 0x03, -0x5b, 0x02, 0x1e, 0x04, 0x53, 0x02, 0xef, 0x02, -0x50, 0x03, 0x1e, 0x00, 0x53 + 0x42, 0xca, 0x00, + 0x36, 0x27, 0x5f, 0x20, 0x02, + 0x1e, 0xf3, 0x53, 0x02, 0xef, 0x01, 0x0c, 0xdd, + 0x9f, 0x6b, 0xbf, 0x15, 0x50, 0xdf, 0x96, 0xc2, + 0x97, 0xdf, 0x01, 0xc1, 0x03, 0x05, 0x52, 0xdd, + 0x97, 0x1f, 0x20, 0x6b, 0xdf, 0xe0, 0x01, 0x6b, + 0xbf, 0x00, 0x50, 0xdd, 0x97, 0x02, 0x0c, 0x6b, + 0xdf, 0x28, 0x1f, 0x01, 0x53, 0x28, 0xff, 0x6b, + 0xbf, 0x68, 0x1f, 0x01, 0x5f, 0x68, 0xff, 0x6b, + 0xbf, 0x05, 0x27, 0x01, 0x81, 0x50, 0x8f, 0xf1, + 0x88, 0x05, 0x81, 0x00, 0x2e, 0x32, 0x8d, 0x01, + 0x2e, 0x06, 0x80, 0x00, 0x2e, 0xd8, 0x8e, 0x5c, + 0x47, 0x02, 0x5b, 0x00, 0x2e, 0x16, 0x8f, 0x01, + 0x50, 0x00, 0x2e, 0x14, 0x8f, 0x08, 0xef, 0x0f, + 0x80, 0x01, 0x2e, 0x54, 0x80, 0x05, 0x27, 0x07, + 0x40, 0x01, 0x5b, 0x54, 0x23, 0x18, 0x50, 0x9c, + 0x8e, 0x0d, 0xcf, 0x06, 0x1c, 0x08, 0x54, 0x14, + 0x88, 0x02, 0x2e, 0x9d, 0x81, 0x01, 0x2e, 0x50, + 0x82, 0x4f, 0x8f, 0x68, 0x88, 0x01, 0x2e, 0x44, + 0x84, 0x5c, 0x8f, 0x54, 0x88, 0x09, 0x46, 0x02, + 0x5b, 0x37, 0x82, 0x90, 0xaf, 0x91, 0xbf, 0x00, + 0x2e, 0xe6, 0x8f, 0x90, 0x8e, 0x0c, 0x3e, 0xed, + 0x5a, 0x05, 0x27, 0x37, 0x82, 0x4a, 0x82, 0x1c, + 0x82, 0x1c, 0x82, 0x9d, 0xbf, 0xff, 0x97, 0x08, + 0x10, 0x09, 0x27, 0x0f, 0x1c, 0x5c, 0x46, 0x03, + 0x5b, 0x02, 0x1e, 0x04, 0x53, 0x02, 0xef, 0x02, + 0x50, 0x03, 0x1e, 0x00, 0x53 }; static const unsigned char pkt532[] = { -0x42, 0xca, 0x00, -0x9a, 0x27, 0x03, 0xef, 0x69, -0xaf, 0x53, 0x80, 0x1b, 0x0d, 0xe1, 0x97, 0x0f, -0x1c, 0x69, 0xdf, 0xdf, 0x01, 0x00, 0x53, 0x00, -0xff, 0xe0, 0x97, 0x8a, 0x80, 0x04, 0x10, 0x11, -0x82, 0x0f, 0x1e, 0x00, 0x5f, 0x0f, 0xef, 0x6a, -0xaf, 0xc1, 0x2e, 0x47, 0xdf, 0xf0, 0x1d, 0x5f, -0x02, 0xc1, 0x2e, 0x47, 0xbf, 0x10, 0x0d, 0x05, -0x27, 0x01, 0x2e, 0x56, 0x80, 0xf7, 0xef, 0x16, -0x80, 0x66, 0x80, 0x20, 0x82, 0xdf, 0x8e, 0x02, -0x2e, 0x3e, 0x81, 0x02, 0x2e, 0x93, 0x81, 0x00, -0x2e, 0xb4, 0x8e, 0x5c, 0x47, 0x09, 0x5b, 0x6c, -0x38, 0x3b, 0x43, 0x00, 0x5b, 0x6c, 0x30, 0x41, -0x2e, 0x71, 0xdf, 0xc1, 0x2e, 0x72, 0xdf, 0xbf, -0x03, 0x01, 0x55, 0x00, 0x2e, 0xc7, 0x8e, 0x67, -0x8c, 0x01, 0x2e, 0xcd, 0x80, 0x05, 0x27, 0x3b, -0x40, 0x01, 0x5b, 0x02, 0xef, 0x0c, 0xaf, 0x05, -0x27, 0x52, 0xcf, 0xcb, 0xaf, 0x53, 0xdf, 0xcc, -0xbf, 0xdf, 0x22, 0x01, 0x55, 0xff, 0x22, 0x01, -0x54, 0x0e, 0xef, 0xc9, 0xaf, 0x05, 0x27, 0x0e, -0xcf, 0x6e, 0x1c, 0x49, 0xdf, 0x10, 0x1d, 0x3f, -0x02, 0x49, 0xaf, 0x0d, 0x44, 0x06, 0x5a, 0x0a, -0x41, 0x03, 0x5b, 0x49, 0x43, 0x02, 0x5a, 0x48, -0x26, 0x00, 0x55, 0x49, 0x30, 0x9f, 0x2c, 0x05, -0x5a, 0xdf, 0x2c, 0x4c, 0x5a, 0x0e, 0x41, 0x15, -0x5b, 0x0c, 0x46, 0x13, 0x5a, 0x9f, 0x22, 0x1c, -0xaf, 0x21, 0xaf, 0x45, 0x88 + 0x42, 0xca, 0x00, + 0x9a, 0x27, 0x03, 0xef, 0x69, + 0xaf, 0x53, 0x80, 0x1b, 0x0d, 0xe1, 0x97, 0x0f, + 0x1c, 0x69, 0xdf, 0xdf, 0x01, 0x00, 0x53, 0x00, + 0xff, 0xe0, 0x97, 0x8a, 0x80, 0x04, 0x10, 0x11, + 0x82, 0x0f, 0x1e, 0x00, 0x5f, 0x0f, 0xef, 0x6a, + 0xaf, 0xc1, 0x2e, 0x47, 0xdf, 0xf0, 0x1d, 0x5f, + 0x02, 0xc1, 0x2e, 0x47, 0xbf, 0x10, 0x0d, 0x05, + 0x27, 0x01, 0x2e, 0x56, 0x80, 0xf7, 0xef, 0x16, + 0x80, 0x66, 0x80, 0x20, 0x82, 0xdf, 0x8e, 0x02, + 0x2e, 0x3e, 0x81, 0x02, 0x2e, 0x93, 0x81, 0x00, + 0x2e, 0xb4, 0x8e, 0x5c, 0x47, 0x09, 0x5b, 0x6c, + 0x38, 0x3b, 0x43, 0x00, 0x5b, 0x6c, 0x30, 0x41, + 0x2e, 0x71, 0xdf, 0xc1, 0x2e, 0x72, 0xdf, 0xbf, + 0x03, 0x01, 0x55, 0x00, 0x2e, 0xc7, 0x8e, 0x67, + 0x8c, 0x01, 0x2e, 0xcd, 0x80, 0x05, 0x27, 0x3b, + 0x40, 0x01, 0x5b, 0x02, 0xef, 0x0c, 0xaf, 0x05, + 0x27, 0x52, 0xcf, 0xcb, 0xaf, 0x53, 0xdf, 0xcc, + 0xbf, 0xdf, 0x22, 0x01, 0x55, 0xff, 0x22, 0x01, + 0x54, 0x0e, 0xef, 0xc9, 0xaf, 0x05, 0x27, 0x0e, + 0xcf, 0x6e, 0x1c, 0x49, 0xdf, 0x10, 0x1d, 0x3f, + 0x02, 0x49, 0xaf, 0x0d, 0x44, 0x06, 0x5a, 0x0a, + 0x41, 0x03, 0x5b, 0x49, 0x43, 0x02, 0x5a, 0x48, + 0x26, 0x00, 0x55, 0x49, 0x30, 0x9f, 0x2c, 0x05, + 0x5a, 0xdf, 0x2c, 0x4c, 0x5a, 0x0e, 0x41, 0x15, + 0x5b, 0x0c, 0x46, 0x13, 0x5a, 0x9f, 0x22, 0x1c, + 0xaf, 0x21, 0xaf, 0x45, 0x88 }; static const unsigned char pkt536[] = { -0x42, 0xca, 0x00, -0xfe, 0x27, 0x03, 0x5a, 0x9f, -0x2c, 0x05, 0x5a, 0x9f, 0x22, 0x04, 0x50, 0x9f, -0x22, 0x0e, 0x3e, 0x0e, 0x3d, 0x00, 0x5b, 0x5f, -0xef, 0x1d, 0xaf, 0x49, 0xcf, 0x87, 0x1c, 0x01, -0x18, 0x49, 0xaf, 0x34, 0x50, 0x20, 0x26, 0x08, -0x55, 0x1f, 0xcf, 0x48, 0xdf, 0xff, 0x2d, 0x00, -0x5b, 0xff, 0x21, 0x3f, 0x00, 0x00, 0x53, 0xff, -0xef, 0x1f, 0xaf, 0x47, 0xdf, 0x1c, 0xcf, 0x3f, -0x00, 0x1c, 0xaf, 0x1d, 0xcf, 0x48, 0xdf, 0x3f, -0x00, 0x1d, 0xaf, 0xff, 0x22, 0x1f, 0x54, 0xff, -0x2d, 0x03, 0x5b, 0xff, 0x1e, 0x19, 0x5b, 0x60, -0x10, 0x02, 0x50, 0x60, 0x1e, 0x0a, 0x52, 0x60, -0x16, 0x1d, 0xaf, 0x49, 0x30, 0x49, 0x3c, 0x12, -0x5b, 0x21, 0xcf, 0x47, 0xdf, 0x3f, 0x00, 0x1c, -0xaf, 0x21, 0x23, 0x0c, 0x50, 0x59, 0x1e, 0x0a, -0x52, 0x49, 0x34, 0x01, 0x5a, 0x21, 0x23, 0x06, -0x50, 0x21, 0xcf, 0x47, 0xdf, 0x3f, 0x00, 0x21, -0xaf, 0x01, 0x50, 0x06, 0x1e, 0xf4, 0x5f, 0x05, -0x27, 0x0d, 0xcf, 0x06, 0x1c, 0x06, 0x1e, 0x00, -0x54, 0x0d, 0x27, 0x0c, 0x27, 0x09, 0x46, 0x0c, -0x5b, 0xa8, 0x8e, 0x07, 0x52, 0x0f, 0xcf, 0x01, -0x16, 0x02, 0x53, 0x02, 0x2e, 0x36, 0x83, 0x04, -0x50, 0xf4, 0xaf, 0x02, 0x50, 0xf2, 0xcf, 0x02, -0x10, 0x0f, 0xaf, 0x05, 0x27, 0x5a, 0xcf, 0xdf, -0x22, 0x10, 0x54, 0x3e, 0xdf, 0x3f, 0x20, 0x3f, -0x1f, 0x0a, 0x52, 0xbf, 0x22 + 0x42, 0xca, 0x00, + 0xfe, 0x27, 0x03, 0x5a, 0x9f, + 0x2c, 0x05, 0x5a, 0x9f, 0x22, 0x04, 0x50, 0x9f, + 0x22, 0x0e, 0x3e, 0x0e, 0x3d, 0x00, 0x5b, 0x5f, + 0xef, 0x1d, 0xaf, 0x49, 0xcf, 0x87, 0x1c, 0x01, + 0x18, 0x49, 0xaf, 0x34, 0x50, 0x20, 0x26, 0x08, + 0x55, 0x1f, 0xcf, 0x48, 0xdf, 0xff, 0x2d, 0x00, + 0x5b, 0xff, 0x21, 0x3f, 0x00, 0x00, 0x53, 0xff, + 0xef, 0x1f, 0xaf, 0x47, 0xdf, 0x1c, 0xcf, 0x3f, + 0x00, 0x1c, 0xaf, 0x1d, 0xcf, 0x48, 0xdf, 0x3f, + 0x00, 0x1d, 0xaf, 0xff, 0x22, 0x1f, 0x54, 0xff, + 0x2d, 0x03, 0x5b, 0xff, 0x1e, 0x19, 0x5b, 0x60, + 0x10, 0x02, 0x50, 0x60, 0x1e, 0x0a, 0x52, 0x60, + 0x16, 0x1d, 0xaf, 0x49, 0x30, 0x49, 0x3c, 0x12, + 0x5b, 0x21, 0xcf, 0x47, 0xdf, 0x3f, 0x00, 0x1c, + 0xaf, 0x21, 0x23, 0x0c, 0x50, 0x59, 0x1e, 0x0a, + 0x52, 0x49, 0x34, 0x01, 0x5a, 0x21, 0x23, 0x06, + 0x50, 0x21, 0xcf, 0x47, 0xdf, 0x3f, 0x00, 0x21, + 0xaf, 0x01, 0x50, 0x06, 0x1e, 0xf4, 0x5f, 0x05, + 0x27, 0x0d, 0xcf, 0x06, 0x1c, 0x06, 0x1e, 0x00, + 0x54, 0x0d, 0x27, 0x0c, 0x27, 0x09, 0x46, 0x0c, + 0x5b, 0xa8, 0x8e, 0x07, 0x52, 0x0f, 0xcf, 0x01, + 0x16, 0x02, 0x53, 0x02, 0x2e, 0x36, 0x83, 0x04, + 0x50, 0xf4, 0xaf, 0x02, 0x50, 0xf2, 0xcf, 0x02, + 0x10, 0x0f, 0xaf, 0x05, 0x27, 0x5a, 0xcf, 0xdf, + 0x22, 0x10, 0x54, 0x3e, 0xdf, 0x3f, 0x20, 0x3f, + 0x1f, 0x0a, 0x52, 0xbf, 0x22 }; static const unsigned char pkt540[] = { -0x42, 0x50, 0x00, -0x62, 0x28, 0x3e, 0xbf, 0x3d, -0xdf, 0x3f, 0x20, 0xdf, 0x03, 0x02, 0x52, 0xbf, -0x22, 0x3d, 0xbf, 0x0c, 0x27, 0x3d, 0xbf, 0x0d, -0x27, 0x3e, 0xbf, 0x0d, 0x27, 0x0d, 0x27, 0x0f, -0x1c, 0x69, 0xdf, 0xdf, 0x01, 0x00, 0x53, 0x00, -0xff, 0x05, 0x27, 0x37, 0x82, 0x4a, 0x82, 0x1c, -0x82, 0x1c, 0x82, 0x9d, 0xbf, 0xff, 0x97, 0x08, -0x10, 0x09, 0x27, 0x0f, 0x1c, 0x5c, 0x46, 0x03, -0x5b, 0x02, 0x1e, 0x04, 0x53, 0x02, 0xef, 0x02, -0x50, 0x03, 0x1e, 0x00, 0x53, 0x03, 0xef, 0x69, -0xaf, 0x05, 0x27 + 0x42, 0x50, 0x00, + 0x62, 0x28, 0x3e, 0xbf, 0x3d, + 0xdf, 0x3f, 0x20, 0xdf, 0x03, 0x02, 0x52, 0xbf, + 0x22, 0x3d, 0xbf, 0x0c, 0x27, 0x3d, 0xbf, 0x0d, + 0x27, 0x3e, 0xbf, 0x0d, 0x27, 0x0d, 0x27, 0x0f, + 0x1c, 0x69, 0xdf, 0xdf, 0x01, 0x00, 0x53, 0x00, + 0xff, 0x05, 0x27, 0x37, 0x82, 0x4a, 0x82, 0x1c, + 0x82, 0x1c, 0x82, 0x9d, 0xbf, 0xff, 0x97, 0x08, + 0x10, 0x09, 0x27, 0x0f, 0x1c, 0x5c, 0x46, 0x03, + 0x5b, 0x02, 0x1e, 0x04, 0x53, 0x02, 0xef, 0x02, + 0x50, 0x03, 0x1e, 0x00, 0x53, 0x03, 0xef, 0x69, + 0xaf, 0x05, 0x27 }; static const unsigned char pkt544[] = { -0x42, 0xca, 0x00, -0x89, 0x28, 0x0c, 0x42, 0x00, -0x5b, 0x18, 0x23, 0x0c, 0x23, 0x0e, 0xcf, 0xe0, -0x1c, 0x0e, 0xaf, 0x0a, 0x40, 0x02, 0x5a, 0x3b, -0x46, 0x00, 0x5a, 0x05, 0x27, 0x37, 0x43, 0xfc, -0x5b, 0x08, 0xef, 0x0c, 0xaf, 0x0d, 0x40, 0x0a, -0x5a, 0xee, 0xcf, 0x64, 0x1e, 0x01, 0x5e, 0x0c, -0x3b, 0x05, 0x27, 0x0d, 0x30, 0x0c, 0x35, 0xbf, -0x22, 0xc0, 0x2e, 0x96, 0xbf, 0x05, 0x27, 0x0e, -0x45, 0x01, 0x5b, 0x07, 0x88, 0x00, 0x50, 0x0e, -0x88, 0x0d, 0x41, 0x1f, 0x5a, 0x0d, 0x42, 0x11, -0x5a, 0xd6, 0x78, 0x51, 0x88, 0x19, 0xcf, 0xfe, -0x1e, 0x03, 0x5c, 0x0e, 0x3d, 0x0d, 0x39, 0x0d, -0x3b, 0x0c, 0x27, 0x0d, 0x27, 0x64, 0x88, 0x19, -0xcf, 0x02, 0x1e, 0xfa, 0x5a, 0x0e, 0x3e, 0x0d, -0x3a, 0x0d, 0x33, 0x0c, 0x27, 0xe4, 0x37, 0x04, -0x89, 0xe4, 0x3f, 0x01, 0x2e, 0xef, 0x82, 0x0d, -0x45, 0x54, 0x5b, 0x18, 0xcf, 0xdf, 0x22, 0x67, -0x54, 0x0d, 0x3b, 0x4f, 0x78, 0xf9, 0x88, 0x01, -0x2e, 0xef, 0x82, 0x0d, 0x42, 0x06, 0x5a, 0x0d, -0x45, 0x48, 0x5b, 0x18, 0xcf, 0xdf, 0x22, 0x5b, -0x54, 0x0d, 0x33, 0x43, 0x78, 0x15, 0xcf, 0x1a, -0xaf, 0xe4, 0x37, 0xea, 0x88, 0x15, 0xcf, 0x1b, -0xaf, 0xe4, 0x3f, 0x0d, 0xcf, 0x60, 0x1c, 0xdf, -0x22, 0x00, 0x55, 0x63, 0x78, 0x16, 0xcf, 0x13, -0xdf, 0x2a, 0x1e, 0x02, 0x5f, 0x2a, 0x1f, 0x00, -0x5f, 0x5c, 0x78, 0xbf, 0x03 + 0x42, 0xca, 0x00, + 0x89, 0x28, 0x0c, 0x42, 0x00, + 0x5b, 0x18, 0x23, 0x0c, 0x23, 0x0e, 0xcf, 0xe0, + 0x1c, 0x0e, 0xaf, 0x0a, 0x40, 0x02, 0x5a, 0x3b, + 0x46, 0x00, 0x5a, 0x05, 0x27, 0x37, 0x43, 0xfc, + 0x5b, 0x08, 0xef, 0x0c, 0xaf, 0x0d, 0x40, 0x0a, + 0x5a, 0xee, 0xcf, 0x64, 0x1e, 0x01, 0x5e, 0x0c, + 0x3b, 0x05, 0x27, 0x0d, 0x30, 0x0c, 0x35, 0xbf, + 0x22, 0xc0, 0x2e, 0x96, 0xbf, 0x05, 0x27, 0x0e, + 0x45, 0x01, 0x5b, 0x07, 0x88, 0x00, 0x50, 0x0e, + 0x88, 0x0d, 0x41, 0x1f, 0x5a, 0x0d, 0x42, 0x11, + 0x5a, 0xd6, 0x78, 0x51, 0x88, 0x19, 0xcf, 0xfe, + 0x1e, 0x03, 0x5c, 0x0e, 0x3d, 0x0d, 0x39, 0x0d, + 0x3b, 0x0c, 0x27, 0x0d, 0x27, 0x64, 0x88, 0x19, + 0xcf, 0x02, 0x1e, 0xfa, 0x5a, 0x0e, 0x3e, 0x0d, + 0x3a, 0x0d, 0x33, 0x0c, 0x27, 0xe4, 0x37, 0x04, + 0x89, 0xe4, 0x3f, 0x01, 0x2e, 0xef, 0x82, 0x0d, + 0x45, 0x54, 0x5b, 0x18, 0xcf, 0xdf, 0x22, 0x67, + 0x54, 0x0d, 0x3b, 0x4f, 0x78, 0xf9, 0x88, 0x01, + 0x2e, 0xef, 0x82, 0x0d, 0x42, 0x06, 0x5a, 0x0d, + 0x45, 0x48, 0x5b, 0x18, 0xcf, 0xdf, 0x22, 0x5b, + 0x54, 0x0d, 0x33, 0x43, 0x78, 0x15, 0xcf, 0x1a, + 0xaf, 0xe4, 0x37, 0xea, 0x88, 0x15, 0xcf, 0x1b, + 0xaf, 0xe4, 0x3f, 0x0d, 0xcf, 0x60, 0x1c, 0xdf, + 0x22, 0x00, 0x55, 0x63, 0x78, 0x16, 0xcf, 0x13, + 0xdf, 0x2a, 0x1e, 0x02, 0x5f, 0x2a, 0x1f, 0x00, + 0x5f, 0x5c, 0x78, 0xbf, 0x03 }; static const unsigned char pkt548[] = { -0x42, 0xca, 0x00, -0xed, 0x28, 0x44, 0x54, 0x1d, -0x52, 0x01, 0x2e, 0xef, 0x82, 0x9f, 0x22, 0x1a, -0xaf, 0x18, 0xcf, 0x12, 0xdf, 0xbf, 0x03, 0x00, -0x53, 0x24, 0x50, 0x09, 0x88, 0x01, 0x2e, 0xe3, -0x82, 0x9f, 0x22, 0x1b, 0xaf, 0xb1, 0x8f, 0x1d, -0x78, 0x0e, 0xcf, 0x9f, 0x1c, 0x0e, 0xaf, 0x05, -0x27, 0x0e, 0xcf, 0x5f, 0x2d, 0x05, 0x5a, 0x9f, -0x2b, 0x5f, 0x29, 0x0e, 0xaf, 0x5f, 0xff, 0x1d, -0xbf, 0x1c, 0x23, 0x05, 0x27, 0x9f, 0x22, 0x1b, -0xaf, 0x18, 0xcf, 0xdf, 0x22, 0x0a, 0x54, 0x18, -0xcf, 0x12, 0xdf, 0xbf, 0x03, 0x00, 0x53, 0x05, -0x50, 0x06, 0x88, 0x01, 0x2e, 0xe9, 0x82, 0x9f, -0x22, 0x1a, 0xaf, 0x9b, 0x8f, 0x09, 0x88, 0x05, -0x27, 0x0e, 0xcf, 0x9f, 0x2d, 0x04, 0x5a, 0x9f, -0x29, 0x5f, 0x2b, 0x0e, 0xaf, 0x1d, 0x23, 0x1c, -0x23, 0x05, 0x27, 0x0d, 0x45, 0x1e, 0x5b, 0x8e, -0x88, 0x18, 0xcf, 0x12, 0xdf, 0xbf, 0x03, 0x57, -0x53, 0x0d, 0x44, 0x02, 0x5b, 0x0c, 0x35, 0x0c, -0x78, 0x85, 0x88, 0x17, 0xcf, 0xdf, 0x22, 0x08, -0x55, 0x18, 0xcf, 0xdf, 0x22, 0x05, 0x55, 0x0a, -0x88, 0x0e, 0x3b, 0x0c, 0xdf, 0x24, 0x19, 0x0c, -0xbf, 0x05, 0x27, 0x11, 0xcf, 0xff, 0x1e, 0x01, -0x54, 0x1f, 0x20, 0x11, 0xaf, 0x05, 0x27, 0x1a, -0x23, 0x1b, 0x23, 0x05, 0x27, 0xfb, 0x8f, 0x0b, -0x88, 0x6d, 0x88, 0xf6, 0x8e, 0x34, 0x5a, 0x0a, -0xcf, 0xc0, 0x1c, 0xc0, 0x1e + 0x42, 0xca, 0x00, + 0xed, 0x28, 0x44, 0x54, 0x1d, + 0x52, 0x01, 0x2e, 0xef, 0x82, 0x9f, 0x22, 0x1a, + 0xaf, 0x18, 0xcf, 0x12, 0xdf, 0xbf, 0x03, 0x00, + 0x53, 0x24, 0x50, 0x09, 0x88, 0x01, 0x2e, 0xe3, + 0x82, 0x9f, 0x22, 0x1b, 0xaf, 0xb1, 0x8f, 0x1d, + 0x78, 0x0e, 0xcf, 0x9f, 0x1c, 0x0e, 0xaf, 0x05, + 0x27, 0x0e, 0xcf, 0x5f, 0x2d, 0x05, 0x5a, 0x9f, + 0x2b, 0x5f, 0x29, 0x0e, 0xaf, 0x5f, 0xff, 0x1d, + 0xbf, 0x1c, 0x23, 0x05, 0x27, 0x9f, 0x22, 0x1b, + 0xaf, 0x18, 0xcf, 0xdf, 0x22, 0x0a, 0x54, 0x18, + 0xcf, 0x12, 0xdf, 0xbf, 0x03, 0x00, 0x53, 0x05, + 0x50, 0x06, 0x88, 0x01, 0x2e, 0xe9, 0x82, 0x9f, + 0x22, 0x1a, 0xaf, 0x9b, 0x8f, 0x09, 0x88, 0x05, + 0x27, 0x0e, 0xcf, 0x9f, 0x2d, 0x04, 0x5a, 0x9f, + 0x29, 0x5f, 0x2b, 0x0e, 0xaf, 0x1d, 0x23, 0x1c, + 0x23, 0x05, 0x27, 0x0d, 0x45, 0x1e, 0x5b, 0x8e, + 0x88, 0x18, 0xcf, 0x12, 0xdf, 0xbf, 0x03, 0x57, + 0x53, 0x0d, 0x44, 0x02, 0x5b, 0x0c, 0x35, 0x0c, + 0x78, 0x85, 0x88, 0x17, 0xcf, 0xdf, 0x22, 0x08, + 0x55, 0x18, 0xcf, 0xdf, 0x22, 0x05, 0x55, 0x0a, + 0x88, 0x0e, 0x3b, 0x0c, 0xdf, 0x24, 0x19, 0x0c, + 0xbf, 0x05, 0x27, 0x11, 0xcf, 0xff, 0x1e, 0x01, + 0x54, 0x1f, 0x20, 0x11, 0xaf, 0x05, 0x27, 0x1a, + 0x23, 0x1b, 0x23, 0x05, 0x27, 0xfb, 0x8f, 0x0b, + 0x88, 0x6d, 0x88, 0xf6, 0x8e, 0x34, 0x5a, 0x0a, + 0xcf, 0xc0, 0x1c, 0xc0, 0x1e }; static const unsigned char pkt552[] = { -0x42, 0xca, 0x00, -0x51, 0x29, 0x0d, 0x55, 0x9f, -0x22, 0x1f, 0xaf, 0x20, 0xaf, 0x19, 0xaf, 0x1b, -0x78, 0x0e, 0xcf, 0x05, 0x18, 0x0e, 0xaf, 0x9f, -0x22, 0x47, 0xaf, 0x48, 0xaf, 0x17, 0xaf, 0x18, -0xaf, 0x05, 0x27, 0x20, 0xcf, 0xdf, 0x22, 0x05, -0x54, 0x05, 0x1e, 0x19, 0x55, 0x1f, 0xdf, 0x80, -0x1f, 0x16, 0x5e, 0x02, 0x78, 0x1f, 0xdf, 0x10, -0x1f, 0x12, 0x5e, 0x9f, 0x22, 0x20, 0xaf, 0x1f, -0xaf, 0x0a, 0xcf, 0xc0, 0x1c, 0x80, 0x1e, 0x0a, -0x55, 0x0d, 0x41, 0x01, 0x5a, 0x0e, 0x35, 0x00, -0x50, 0x0e, 0x36, 0x0d, 0xcf, 0x06, 0x18, 0x0d, -0xaf, 0x0e, 0x31, 0x9f, 0x22, 0x19, 0xaf, 0x03, -0x78, 0x1f, 0x20, 0x06, 0x1e, 0x00, 0x5e, 0x20, -0xaf, 0x0d, 0x47, 0x01, 0x5b, 0x01, 0x2e, 0xa2, -0x73, 0x0d, 0x44, 0x0b, 0x5a, 0x0d, 0xcf, 0x06, -0x1c, 0x08, 0x54, 0x0c, 0x30, 0x48, 0xcf, 0xdf, -0x2d, 0x02, 0x5a, 0x9f, 0x22, 0x1d, 0xaf, 0x01, -0x50, 0x5f, 0xef, 0x1d, 0xaf, 0x0c, 0x31, 0x0d, -0x45, 0x11, 0x5b, 0x0a, 0xcf, 0x30, 0x1c, 0x0c, -0x55, 0x0d, 0xcf, 0x06, 0x1c, 0x06, 0x1e, 0x0b, -0x54, 0x11, 0xcf, 0x07, 0x1e, 0x02, 0x53, 0x04, -0xef, 0x12, 0xaf, 0x04, 0x78, 0x05, 0xef, 0x12, -0xaf, 0x01, 0x78, 0x01, 0xef, 0x12, 0xaf, 0x18, -0x23, 0x9f, 0x22, 0x11, 0xaf, 0x0d, 0xcf, 0x1f, -0x1c, 0x0d, 0xaf, 0x0c, 0xdf, 0x24, 0x19, 0x0c, -0xbf, 0x0a, 0xdf, 0x30, 0x1d + 0x42, 0xca, 0x00, + 0x51, 0x29, 0x0d, 0x55, 0x9f, + 0x22, 0x1f, 0xaf, 0x20, 0xaf, 0x19, 0xaf, 0x1b, + 0x78, 0x0e, 0xcf, 0x05, 0x18, 0x0e, 0xaf, 0x9f, + 0x22, 0x47, 0xaf, 0x48, 0xaf, 0x17, 0xaf, 0x18, + 0xaf, 0x05, 0x27, 0x20, 0xcf, 0xdf, 0x22, 0x05, + 0x54, 0x05, 0x1e, 0x19, 0x55, 0x1f, 0xdf, 0x80, + 0x1f, 0x16, 0x5e, 0x02, 0x78, 0x1f, 0xdf, 0x10, + 0x1f, 0x12, 0x5e, 0x9f, 0x22, 0x20, 0xaf, 0x1f, + 0xaf, 0x0a, 0xcf, 0xc0, 0x1c, 0x80, 0x1e, 0x0a, + 0x55, 0x0d, 0x41, 0x01, 0x5a, 0x0e, 0x35, 0x00, + 0x50, 0x0e, 0x36, 0x0d, 0xcf, 0x06, 0x18, 0x0d, + 0xaf, 0x0e, 0x31, 0x9f, 0x22, 0x19, 0xaf, 0x03, + 0x78, 0x1f, 0x20, 0x06, 0x1e, 0x00, 0x5e, 0x20, + 0xaf, 0x0d, 0x47, 0x01, 0x5b, 0x01, 0x2e, 0xa2, + 0x73, 0x0d, 0x44, 0x0b, 0x5a, 0x0d, 0xcf, 0x06, + 0x1c, 0x08, 0x54, 0x0c, 0x30, 0x48, 0xcf, 0xdf, + 0x2d, 0x02, 0x5a, 0x9f, 0x22, 0x1d, 0xaf, 0x01, + 0x50, 0x5f, 0xef, 0x1d, 0xaf, 0x0c, 0x31, 0x0d, + 0x45, 0x11, 0x5b, 0x0a, 0xcf, 0x30, 0x1c, 0x0c, + 0x55, 0x0d, 0xcf, 0x06, 0x1c, 0x06, 0x1e, 0x0b, + 0x54, 0x11, 0xcf, 0x07, 0x1e, 0x02, 0x53, 0x04, + 0xef, 0x12, 0xaf, 0x04, 0x78, 0x05, 0xef, 0x12, + 0xaf, 0x01, 0x78, 0x01, 0xef, 0x12, 0xaf, 0x18, + 0x23, 0x9f, 0x22, 0x11, 0xaf, 0x0d, 0xcf, 0x1f, + 0x1c, 0x0d, 0xaf, 0x0c, 0xdf, 0x24, 0x19, 0x0c, + 0xbf, 0x0a, 0xdf, 0x30, 0x1d }; static const unsigned char pkt556[] = { -0x42, 0x46, 0x00, -0xb5, 0x29, 0x20, 0x1f, 0x01, -0x55, 0xf9, 0x1c, 0x0d, 0xaf, 0x05, 0x27, 0x17, -0xdf, 0xff, 0x21, 0x47, 0xbf, 0x18, 0xdf, 0x84, -0x8e, 0x02, 0x5b, 0x0e, 0x46, 0x03, 0x5a, 0x01, -0x78, 0x0d, 0x43, 0x00, 0x5a, 0xff, 0x21, 0x48, -0xbf, 0x05, 0x27, 0x14, 0x23, 0x15, 0x23, 0xff, -0xef, 0x13, 0xaf, 0x01, 0x2e, 0x00, 0x83, 0x0d, -0x3e, 0x13, 0xcf, 0x46, 0xff, 0xbf, 0x03, 0x00, -0x53, 0x0d, 0x36, 0x05, 0x27, 0x05, 0x27, 0x05, -0x27 + 0x42, 0x46, 0x00, + 0xb5, 0x29, 0x20, 0x1f, 0x01, + 0x55, 0xf9, 0x1c, 0x0d, 0xaf, 0x05, 0x27, 0x17, + 0xdf, 0xff, 0x21, 0x47, 0xbf, 0x18, 0xdf, 0x84, + 0x8e, 0x02, 0x5b, 0x0e, 0x46, 0x03, 0x5a, 0x01, + 0x78, 0x0d, 0x43, 0x00, 0x5a, 0xff, 0x21, 0x48, + 0xbf, 0x05, 0x27, 0x14, 0x23, 0x15, 0x23, 0xff, + 0xef, 0x13, 0xaf, 0x01, 0x2e, 0x00, 0x83, 0x0d, + 0x3e, 0x13, 0xcf, 0x46, 0xff, 0xbf, 0x03, 0x00, + 0x53, 0x0d, 0x36, 0x05, 0x27, 0x05, 0x27, 0x05, + 0x27 }; static const unsigned char pkt560[] = { -0x42, 0xca, 0x00, -0xd7, 0x29, 0xe1, 0x97, 0xe2, -0x9f, 0x46, 0x2e, 0x28, 0xbf, 0xc6, 0x2e, 0x29, -0xbf, 0xad, 0x88, 0x0a, 0x5b, 0xe9, 0x97, 0xea, -0x9f, 0x4f, 0xaf, 0x50, 0xbf, 0x46, 0x2e, 0x28, -0xdf, 0xc6, 0x2e, 0x29, 0xdf, 0x10, 0x10, 0x00, -0x13, 0x01, 0x78, 0x03, 0x10, 0x00, 0x13, 0xff, -0x96, 0xdf, 0x96, 0xd6, 0xcf, 0xd7, 0xdf, 0x0f, -0x1d, 0x01, 0x10, 0x00, 0x13, 0xff, 0x96, 0xdf, -0x96, 0xc8, 0xdf, 0xc7, 0xcf, 0x1f, 0x1d, 0xff, -0x96, 0xdf, 0x96, 0xc2, 0x97, 0xc3, 0x9f, 0x9d, -0x01, 0x5d, 0x01, 0xf5, 0x52, 0xc3, 0x03, 0x02, -0x5e, 0xf2, 0x52, 0x82, 0x03, 0xf0, 0x52, 0x02, -0x0c, 0xf8, 0x43, 0x03, 0x5b, 0x08, 0x44, 0x01, -0x5a, 0x00, 0x2e, 0xf3, 0x8f, 0x7f, 0x88, 0x6d, -0x5b, 0x41, 0x2e, 0xaf, 0xdf, 0xdf, 0x29, 0x41, -0x2e, 0xaf, 0xbf, 0x46, 0x2e, 0x28, 0xdf, 0xc6, -0x2e, 0x29, 0xdf, 0x03, 0x16, 0x00, 0x15, 0x46, -0x2e, 0x28, 0xbf, 0xc6, 0x2e, 0x29, 0xbf, 0x15, -0x27, 0xff, 0x96, 0xdf, 0x96, 0x8d, 0x88, 0x94, -0x88, 0xcd, 0x88, 0x01, 0xff, 0xab, 0xef, 0x19, -0x27, 0x6b, 0x88, 0xbf, 0x22, 0x3f, 0x98, 0x05, -0xff, 0x7f, 0x98, 0xdd, 0x9f, 0xbf, 0x98, 0x24, -0x28, 0x04, 0xff, 0x7f, 0x98, 0xdd, 0x9f, 0xbf, -0x98, 0x24, 0x28, 0x66, 0xff, 0xbf, 0x99, 0x12, -0xff, 0x7f, 0x99, 0xdd, 0x97, 0xdd, 0x9f, 0x19, -0x27, 0xe0, 0x97, 0xff, 0xaf + 0x42, 0xca, 0x00, + 0xd7, 0x29, 0xe1, 0x97, 0xe2, + 0x9f, 0x46, 0x2e, 0x28, 0xbf, 0xc6, 0x2e, 0x29, + 0xbf, 0xad, 0x88, 0x0a, 0x5b, 0xe9, 0x97, 0xea, + 0x9f, 0x4f, 0xaf, 0x50, 0xbf, 0x46, 0x2e, 0x28, + 0xdf, 0xc6, 0x2e, 0x29, 0xdf, 0x10, 0x10, 0x00, + 0x13, 0x01, 0x78, 0x03, 0x10, 0x00, 0x13, 0xff, + 0x96, 0xdf, 0x96, 0xd6, 0xcf, 0xd7, 0xdf, 0x0f, + 0x1d, 0x01, 0x10, 0x00, 0x13, 0xff, 0x96, 0xdf, + 0x96, 0xc8, 0xdf, 0xc7, 0xcf, 0x1f, 0x1d, 0xff, + 0x96, 0xdf, 0x96, 0xc2, 0x97, 0xc3, 0x9f, 0x9d, + 0x01, 0x5d, 0x01, 0xf5, 0x52, 0xc3, 0x03, 0x02, + 0x5e, 0xf2, 0x52, 0x82, 0x03, 0xf0, 0x52, 0x02, + 0x0c, 0xf8, 0x43, 0x03, 0x5b, 0x08, 0x44, 0x01, + 0x5a, 0x00, 0x2e, 0xf3, 0x8f, 0x7f, 0x88, 0x6d, + 0x5b, 0x41, 0x2e, 0xaf, 0xdf, 0xdf, 0x29, 0x41, + 0x2e, 0xaf, 0xbf, 0x46, 0x2e, 0x28, 0xdf, 0xc6, + 0x2e, 0x29, 0xdf, 0x03, 0x16, 0x00, 0x15, 0x46, + 0x2e, 0x28, 0xbf, 0xc6, 0x2e, 0x29, 0xbf, 0x15, + 0x27, 0xff, 0x96, 0xdf, 0x96, 0x8d, 0x88, 0x94, + 0x88, 0xcd, 0x88, 0x01, 0xff, 0xab, 0xef, 0x19, + 0x27, 0x6b, 0x88, 0xbf, 0x22, 0x3f, 0x98, 0x05, + 0xff, 0x7f, 0x98, 0xdd, 0x9f, 0xbf, 0x98, 0x24, + 0x28, 0x04, 0xff, 0x7f, 0x98, 0xdd, 0x9f, 0xbf, + 0x98, 0x24, 0x28, 0x66, 0xff, 0xbf, 0x99, 0x12, + 0xff, 0x7f, 0x99, 0xdd, 0x97, 0xdd, 0x9f, 0x19, + 0x27, 0xe0, 0x97, 0xff, 0xaf }; static const unsigned char pkt564[] = { -0x42, 0xca, 0x00, -0x3b, 0x2a, 0x46, 0x2e, 0x28, -0xdf, 0xc6, 0x2e, 0x29, 0xdf, 0x13, 0x10, 0x00, -0x13, 0xff, 0xaf, 0xff, 0xbf, 0xe3, 0x97, 0xff, -0xaf, 0xe4, 0x97, 0xff, 0xaf, 0xe5, 0x97, 0xff, -0xaf, 0xef, 0x88, 0x06, 0x0d, 0xdd, 0x97, 0xdd, -0x9f, 0x46, 0x2e, 0x28, 0xdf, 0xc6, 0x2e, 0x29, -0xdf, 0x06, 0xaf, 0x4e, 0xbf, 0xff, 0x22, 0x11, -0x54, 0x15, 0x27, 0x1a, 0x27, 0x01, 0xff, 0xab, -0xef, 0x19, 0x27, 0xdc, 0x97, 0xdf, 0x99, 0x28, -0x28, 0x0f, 0x27, 0x68, 0x2c, 0xfd, 0x5b, 0xe9, -0x97, 0xff, 0xaf, 0x6a, 0x28, 0x06, 0x25, 0xf4, -0x53, 0x4e, 0x25, 0xf2, 0x55, 0xdc, 0x97, 0xdf, -0x99, 0x28, 0x28, 0x0f, 0x27, 0x68, 0x2c, 0xfd, -0x5b, 0xe9, 0x97, 0xff, 0xaf, 0x6a, 0x28, 0x06, -0x25, 0xf4, 0x55, 0x41, 0x2e, 0xaf, 0xdf, 0xdf, -0x2b, 0x41, 0x2e, 0xaf, 0xbf, 0xbf, 0x22, 0xbf, -0x99, 0x7f, 0x99, 0x05, 0x27, 0xdd, 0x97, 0xdd, -0x9f, 0x06, 0xaf, 0x4e, 0xbf, 0xff, 0x22, 0x05, -0x54, 0xfd, 0x97, 0xff, 0xaf, 0x06, 0x25, 0xfb, -0x53, 0x4e, 0x25, 0xf9, 0x55, 0xfd, 0x97, 0xff, -0xaf, 0x06, 0x25, 0xfb, 0x55, 0x05, 0x27, 0xff, -0x96, 0xc6, 0x2e, 0x01, 0xdf, 0xbf, 0x2c, 0xdd, -0x9f, 0x05, 0x27, 0xc6, 0x2e, 0x28, 0xdf, 0x0f, -0x1d, 0x04, 0x55, 0x0b, 0x88, 0xff, 0x96, 0x10, -0xef, 0xdf, 0x96, 0x06, 0x50, 0x06, 0x88, 0x3f, -0x20, 0xff, 0x96, 0xc6, 0x2e + 0x42, 0xca, 0x00, + 0x3b, 0x2a, 0x46, 0x2e, 0x28, + 0xdf, 0xc6, 0x2e, 0x29, 0xdf, 0x13, 0x10, 0x00, + 0x13, 0xff, 0xaf, 0xff, 0xbf, 0xe3, 0x97, 0xff, + 0xaf, 0xe4, 0x97, 0xff, 0xaf, 0xe5, 0x97, 0xff, + 0xaf, 0xef, 0x88, 0x06, 0x0d, 0xdd, 0x97, 0xdd, + 0x9f, 0x46, 0x2e, 0x28, 0xdf, 0xc6, 0x2e, 0x29, + 0xdf, 0x06, 0xaf, 0x4e, 0xbf, 0xff, 0x22, 0x11, + 0x54, 0x15, 0x27, 0x1a, 0x27, 0x01, 0xff, 0xab, + 0xef, 0x19, 0x27, 0xdc, 0x97, 0xdf, 0x99, 0x28, + 0x28, 0x0f, 0x27, 0x68, 0x2c, 0xfd, 0x5b, 0xe9, + 0x97, 0xff, 0xaf, 0x6a, 0x28, 0x06, 0x25, 0xf4, + 0x53, 0x4e, 0x25, 0xf2, 0x55, 0xdc, 0x97, 0xdf, + 0x99, 0x28, 0x28, 0x0f, 0x27, 0x68, 0x2c, 0xfd, + 0x5b, 0xe9, 0x97, 0xff, 0xaf, 0x6a, 0x28, 0x06, + 0x25, 0xf4, 0x55, 0x41, 0x2e, 0xaf, 0xdf, 0xdf, + 0x2b, 0x41, 0x2e, 0xaf, 0xbf, 0xbf, 0x22, 0xbf, + 0x99, 0x7f, 0x99, 0x05, 0x27, 0xdd, 0x97, 0xdd, + 0x9f, 0x06, 0xaf, 0x4e, 0xbf, 0xff, 0x22, 0x05, + 0x54, 0xfd, 0x97, 0xff, 0xaf, 0x06, 0x25, 0xfb, + 0x53, 0x4e, 0x25, 0xf9, 0x55, 0xfd, 0x97, 0xff, + 0xaf, 0x06, 0x25, 0xfb, 0x55, 0x05, 0x27, 0xff, + 0x96, 0xc6, 0x2e, 0x01, 0xdf, 0xbf, 0x2c, 0xdd, + 0x9f, 0x05, 0x27, 0xc6, 0x2e, 0x28, 0xdf, 0x0f, + 0x1d, 0x04, 0x55, 0x0b, 0x88, 0xff, 0x96, 0x10, + 0xef, 0xdf, 0x96, 0x06, 0x50, 0x06, 0x88, 0x3f, + 0x20, 0xff, 0x96, 0xc6, 0x2e }; static const unsigned char pkt568[] = { -0x42, 0xca, 0x00, -0x9f, 0x2a, 0x28, 0xdf, 0x0f, -0x1d, 0xff, 0x96, 0x05, 0x27, 0x46, 0x2e, 0x28, -0xdf, 0xf0, 0x1c, 0x09, 0x27, 0xdf, 0x9f, 0x46, -0x2e, 0x29, 0xdf, 0x0f, 0x1c, 0x09, 0x27, 0x5f, -0x02, 0x05, 0x27, 0x78, 0x88, 0x6f, 0x88, 0x0a, -0xef, 0xdc, 0x9f, 0x3f, 0x9f, 0x5f, 0x20, 0xfb, -0x55, 0x05, 0x27, 0x9f, 0x22, 0x41, 0x2e, 0xab, -0xbf, 0x50, 0xef, 0xdf, 0x96, 0x3a, 0xef, 0xdf, -0x96, 0x29, 0x88, 0x68, 0x88, 0x0a, 0xef, 0xfc, -0x9f, 0xc1, 0x2e, 0xad, 0xbf, 0xc1, 0x2e, 0xac, -0xdf, 0x3f, 0x20, 0xc1, 0x2e, 0xac, 0xbf, 0x6a, -0x88, 0x5f, 0x20, 0xf4, 0x55, 0x5b, 0xef, 0xdf, -0x96, 0x50, 0xcf, 0xdf, 0x96, 0x17, 0x88, 0x5c, -0xef, 0xdf, 0x96, 0x4f, 0xcf, 0xdf, 0x96, 0x12, -0x88, 0x5d, 0xef, 0xdf, 0x96, 0x9f, 0x22, 0xdf, -0x96, 0x0d, 0x88, 0x5e, 0xef, 0xdf, 0x96, 0x46, -0x2e, 0x29, 0xdf, 0xdf, 0x96, 0x07, 0x88, 0x5f, -0xef, 0xdf, 0x96, 0x46, 0x2e, 0x28, 0xdf, 0xdf, -0x96, 0x01, 0x88, 0x0f, 0x27, 0x05, 0x27, 0xdd, -0x97, 0x41, 0x2e, 0xad, 0xbf, 0xdd, 0x97, 0x41, -0x2e, 0xac, 0xbf, 0x44, 0x88, 0x05, 0x27, 0x9f, -0x22, 0x41, 0x2e, 0xab, 0xbf, 0x10, 0xef, 0xdf, -0x96, 0x02, 0xef, 0xdf, 0x96, 0xef, 0x8f, 0x2e, -0x88, 0x0a, 0xef, 0xfc, 0x9f, 0xc1, 0x2e, 0xad, -0xbf, 0xc1, 0x2e, 0xac, 0xdf, 0x3f, 0x20, 0xc1, -0x2e, 0xac, 0xbf, 0x30, 0x88 + 0x42, 0xca, 0x00, + 0x9f, 0x2a, 0x28, 0xdf, 0x0f, + 0x1d, 0xff, 0x96, 0x05, 0x27, 0x46, 0x2e, 0x28, + 0xdf, 0xf0, 0x1c, 0x09, 0x27, 0xdf, 0x9f, 0x46, + 0x2e, 0x29, 0xdf, 0x0f, 0x1c, 0x09, 0x27, 0x5f, + 0x02, 0x05, 0x27, 0x78, 0x88, 0x6f, 0x88, 0x0a, + 0xef, 0xdc, 0x9f, 0x3f, 0x9f, 0x5f, 0x20, 0xfb, + 0x55, 0x05, 0x27, 0x9f, 0x22, 0x41, 0x2e, 0xab, + 0xbf, 0x50, 0xef, 0xdf, 0x96, 0x3a, 0xef, 0xdf, + 0x96, 0x29, 0x88, 0x68, 0x88, 0x0a, 0xef, 0xfc, + 0x9f, 0xc1, 0x2e, 0xad, 0xbf, 0xc1, 0x2e, 0xac, + 0xdf, 0x3f, 0x20, 0xc1, 0x2e, 0xac, 0xbf, 0x6a, + 0x88, 0x5f, 0x20, 0xf4, 0x55, 0x5b, 0xef, 0xdf, + 0x96, 0x50, 0xcf, 0xdf, 0x96, 0x17, 0x88, 0x5c, + 0xef, 0xdf, 0x96, 0x4f, 0xcf, 0xdf, 0x96, 0x12, + 0x88, 0x5d, 0xef, 0xdf, 0x96, 0x9f, 0x22, 0xdf, + 0x96, 0x0d, 0x88, 0x5e, 0xef, 0xdf, 0x96, 0x46, + 0x2e, 0x29, 0xdf, 0xdf, 0x96, 0x07, 0x88, 0x5f, + 0xef, 0xdf, 0x96, 0x46, 0x2e, 0x28, 0xdf, 0xdf, + 0x96, 0x01, 0x88, 0x0f, 0x27, 0x05, 0x27, 0xdd, + 0x97, 0x41, 0x2e, 0xad, 0xbf, 0xdd, 0x97, 0x41, + 0x2e, 0xac, 0xbf, 0x44, 0x88, 0x05, 0x27, 0x9f, + 0x22, 0x41, 0x2e, 0xab, 0xbf, 0x10, 0xef, 0xdf, + 0x96, 0x02, 0xef, 0xdf, 0x96, 0xef, 0x8f, 0x2e, + 0x88, 0x0a, 0xef, 0xfc, 0x9f, 0xc1, 0x2e, 0xad, + 0xbf, 0xc1, 0x2e, 0xac, 0xdf, 0x3f, 0x20, 0xc1, + 0x2e, 0xac, 0xbf, 0x30, 0x88 }; static const unsigned char pkt572[] = { -0x42, 0x9a, 0x00, -0x03, 0x2b, 0x5f, 0x20, 0xf4, -0x55, 0x1b, 0xef, 0xdf, 0x96, 0x50, 0xcf, 0xdf, -0x96, 0xdd, 0x8f, 0x1c, 0xef, 0xdf, 0x96, 0x4f, -0xcf, 0xdf, 0x96, 0xd8, 0x8f, 0x1d, 0xef, 0xdf, -0x96, 0x9f, 0x22, 0xdf, 0x96, 0xd3, 0x8f, 0x1e, -0xef, 0xdf, 0x96, 0x9f, 0x22, 0xdf, 0x96, 0xce, -0x8f, 0x1f, 0xef, 0xdf, 0x96, 0x01, 0xef, 0xdf, -0x96, 0xc9, 0x8f, 0x0f, 0x27, 0x05, 0x27, 0x02, -0xef, 0x06, 0xff, 0x1a, 0x27, 0x05, 0x27, 0x02, -0xef, 0x06, 0xff, 0x1a, 0x27, 0x05, 0x27, 0xdf, -0x96, 0xff, 0x96, 0x7b, 0xef, 0x00, 0xff, 0x1b, -0x27, 0xdd, 0x9f, 0xdd, 0x97, 0x05, 0x27, 0x01, -0xff, 0xab, 0xef, 0x1b, 0x27, 0x05, 0x27, 0xdf, -0x96, 0x81, 0xef, 0x41, 0x2e, 0xaf, 0xbf, 0xdd, -0x97, 0x05, 0x27, 0x3a, 0xef, 0xff, 0xaf, 0xea, -0x8f, 0x0a, 0xef, 0xfc, 0x9f, 0xff, 0xbf, 0x5f, -0x20, 0xfb, 0x55, 0x50, 0xcf, 0xff, 0xaf, 0x4f, -0xcf, 0xff, 0xaf, 0x9f, 0x22, 0xff, 0xaf, 0x46, -0x2e, 0x29, 0xdf, 0xff, 0xaf, 0x46, 0x2e, 0x28, -0xdf, 0xff, 0xaf, 0x05, 0x27 + 0x42, 0x9a, 0x00, + 0x03, 0x2b, 0x5f, 0x20, 0xf4, + 0x55, 0x1b, 0xef, 0xdf, 0x96, 0x50, 0xcf, 0xdf, + 0x96, 0xdd, 0x8f, 0x1c, 0xef, 0xdf, 0x96, 0x4f, + 0xcf, 0xdf, 0x96, 0xd8, 0x8f, 0x1d, 0xef, 0xdf, + 0x96, 0x9f, 0x22, 0xdf, 0x96, 0xd3, 0x8f, 0x1e, + 0xef, 0xdf, 0x96, 0x9f, 0x22, 0xdf, 0x96, 0xce, + 0x8f, 0x1f, 0xef, 0xdf, 0x96, 0x01, 0xef, 0xdf, + 0x96, 0xc9, 0x8f, 0x0f, 0x27, 0x05, 0x27, 0x02, + 0xef, 0x06, 0xff, 0x1a, 0x27, 0x05, 0x27, 0x02, + 0xef, 0x06, 0xff, 0x1a, 0x27, 0x05, 0x27, 0xdf, + 0x96, 0xff, 0x96, 0x7b, 0xef, 0x00, 0xff, 0x1b, + 0x27, 0xdd, 0x9f, 0xdd, 0x97, 0x05, 0x27, 0x01, + 0xff, 0xab, 0xef, 0x1b, 0x27, 0x05, 0x27, 0xdf, + 0x96, 0x81, 0xef, 0x41, 0x2e, 0xaf, 0xbf, 0xdd, + 0x97, 0x05, 0x27, 0x3a, 0xef, 0xff, 0xaf, 0xea, + 0x8f, 0x0a, 0xef, 0xfc, 0x9f, 0xff, 0xbf, 0x5f, + 0x20, 0xfb, 0x55, 0x50, 0xcf, 0xff, 0xaf, 0x4f, + 0xcf, 0xff, 0xaf, 0x9f, 0x22, 0xff, 0xaf, 0x46, + 0x2e, 0x29, 0xdf, 0xff, 0xaf, 0x46, 0x2e, 0x28, + 0xdf, 0xff, 0xaf, 0x05, 0x27 }; static const unsigned char pkt576[] = { -0x42, 0x1a, 0x00, -0x4f, 0x2b, 0x09, 0x43, 0x04, -0x5b, 0x00, 0xef, 0xf8, 0xaf, 0x32, 0xef, 0xfa, -0xaf, 0x03, 0x50, 0x01, 0xef, 0xf8, 0xaf, 0x42, -0xef, 0xfa, 0xaf, 0x05, 0x27 + 0x42, 0x1a, 0x00, + 0x4f, 0x2b, 0x09, 0x43, 0x04, + 0x5b, 0x00, 0xef, 0xf8, 0xaf, 0x32, 0xef, 0xfa, + 0xaf, 0x03, 0x50, 0x01, 0xef, 0xf8, 0xaf, 0x42, + 0xef, 0xfa, 0xaf, 0x05, 0x27 }; static const unsigned char pkt580[] = { -0x42, 0x18, 0x00, -0x5b, 0x2b, 0xd3, 0x45, 0x03, -0x5a, 0x0f, 0x27, 0xd3, 0x45, 0x00, 0x5a, 0x05, -0x27, 0xd0, 0x41, 0xf7, 0x5b, 0xc1, 0x83, 0xf5, -0x50, 0x05, 0x27 + 0x42, 0x18, 0x00, + 0x5b, 0x2b, 0xd3, 0x45, 0x03, + 0x5a, 0x0f, 0x27, 0xd3, 0x45, 0x00, 0x5a, 0x05, + 0x27, 0xd0, 0x41, 0xf7, 0x5b, 0xc1, 0x83, 0xf5, + 0x50, 0x05, 0x27 }; static const unsigned char pkt584[] = { -0x42, 0x22, 0x00, -0x66, 0x2b, 0xc8, 0x46, 0x0c, -0x5b, 0xd3, 0x45, 0xfd, 0x5a, 0xd3, 0x45, 0xfb, -0x5a, 0xd3, 0x45, 0xf9, 0x5a, 0x41, 0x2e, 0xa1, -0xdf, 0x9f, 0x28, 0x41, 0x2e, 0xa1, 0xbf, 0x02, -0x2e, 0xb0, 0x81, 0x05, 0x27 + 0x42, 0x22, 0x00, + 0x66, 0x2b, 0xc8, 0x46, 0x0c, + 0x5b, 0xd3, 0x45, 0xfd, 0x5a, 0xd3, 0x45, 0xfb, + 0x5a, 0xd3, 0x45, 0xf9, 0x5a, 0x41, 0x2e, 0xa1, + 0xdf, 0x9f, 0x28, 0x41, 0x2e, 0xa1, 0xbf, 0x02, + 0x2e, 0xb0, 0x81, 0x05, 0x27 }; static const unsigned char pkt588[] = { -0x42, 0x0e, 0x00, -0x76, 0x2b, 0x00, 0x19, 0xe9, -0x2f, 0xe3, 0x55, 0xdf, 0x2d, 0xe9, 0x2f, 0xd0, -0x50 + 0x42, 0x0e, 0x00, + 0x76, 0x2b, 0x00, 0x19, 0xe9, + 0x2f, 0xe3, 0x55, 0xdf, 0x2d, 0xe9, 0x2f, 0xd0, + 0x50 }; static const unsigned char pkt592[] = { -0x42, 0x0e, 0x00, -0x7c, 0x2b, 0x00, 0x19, 0xe9, -0x2f, 0xb5, 0x55, 0xdf, 0x2d, 0xe9, 0x2f, 0xa2, -0x50 + 0x42, 0x0e, 0x00, + 0x7c, 0x2b, 0x00, 0x19, 0xe9, + 0x2f, 0xb5, 0x55, 0xdf, 0x2d, 0xe9, 0x2f, 0xa2, + 0x50 }; static const unsigned char pkt596[] = { -0x42, 0x0e, 0x00, -0x82, 0x2b, 0xbf, 0x03, 0xe7, -0x2f, 0xb2, 0x53, 0xec, 0xcf, 0x01, 0x2e, 0x2d, -0x73 + 0x42, 0x0e, 0x00, + 0x82, 0x2b, 0xbf, 0x03, 0xe7, + 0x2f, 0xb2, 0x53, 0xec, 0xcf, 0x01, 0x2e, 0x2d, + 0x73 }; static const unsigned char pkt600[] = { -0x42, 0x50, 0x00, -0x88, 0x2b, 0x07, 0x3d, 0x02, -0x5b, 0x6c, 0x86, 0xc2, 0x23, 0xd3, 0x3c, 0x02, -0x44, 0xd7, 0x2f, 0x08, 0x5a, 0x02, 0x45, 0xd7, -0x2f, 0x69, 0x5b, 0x58, 0x23, 0x3c, 0x26, 0x02, -0x55, 0x02, 0x2e, 0x43, 0x83, 0x01, 0x50, 0x02, -0x2e, 0x92, 0x83, 0x07, 0x45, 0xea, 0x5a, 0x41, -0x2e, 0x53, 0xdf, 0xc1, 0x2e, 0x79, 0xdf, 0xff, -0x96, 0xdf, 0x96, 0x41, 0x2e, 0x55, 0xdf, 0xc1, -0x2e, 0x78, 0xdf, 0x9d, 0x01, 0x5d, 0x01, 0xff, -0x22, 0x00, 0x54, 0xff, 0xef, 0x2e, 0xaf, 0xd7, -0x2f, 0x4d, 0x50 + 0x42, 0x50, 0x00, + 0x88, 0x2b, 0x07, 0x3d, 0x02, + 0x5b, 0x6c, 0x86, 0xc2, 0x23, 0xd3, 0x3c, 0x02, + 0x44, 0xd7, 0x2f, 0x08, 0x5a, 0x02, 0x45, 0xd7, + 0x2f, 0x69, 0x5b, 0x58, 0x23, 0x3c, 0x26, 0x02, + 0x55, 0x02, 0x2e, 0x43, 0x83, 0x01, 0x50, 0x02, + 0x2e, 0x92, 0x83, 0x07, 0x45, 0xea, 0x5a, 0x41, + 0x2e, 0x53, 0xdf, 0xc1, 0x2e, 0x79, 0xdf, 0xff, + 0x96, 0xdf, 0x96, 0x41, 0x2e, 0x55, 0xdf, 0xc1, + 0x2e, 0x78, 0xdf, 0x9d, 0x01, 0x5d, 0x01, 0xff, + 0x22, 0x00, 0x54, 0xff, 0xef, 0x2e, 0xaf, 0xd7, + 0x2f, 0x4d, 0x50 }; static const unsigned char pkt604[] = { -0x67, 0x05, 0x00, 0x00, 0x02, 0x2e, 0x00, 0x70, -0x67, 0x05, 0x00, 0x01, 0x02, 0x2e, 0xb8, 0x71, -0x67, 0x05, 0x00, 0x02, 0x02, 0x2e, 0x35, 0x72, -0x67, 0x05, 0x00, 0x08, 0x02, 0x2e, 0xbb, 0x72, -0x67, 0x05, 0x00, 0x07, 0x02, 0x2e, 0x3b, 0x73, -0x67, 0x05, 0x00, 0x0d, 0x02, 0x2e, 0x38, 0x74, -0x67, 0x05, 0x00, 0x0b, 0x02, 0x2e, 0x85, 0x74, -0x67, 0x05, 0x00, 0x0e, 0x02, 0x2e, 0x61, 0x75, -0x67, 0x05, 0x00, 0x05, 0x02, 0x2e, 0xa6, 0x75, -0x67, 0x05, 0x00, 0x0c, 0x02, 0x2e, 0x89, 0x78, -0x67, 0x05, 0x00, 0x09, 0x02, 0x2e, 0xd7, 0x79, -0x5a, 0x05, 0x00, 0x00, 0x6b, 0x01, 0x4f, 0x2b, -0x5a, 0x05, 0x00, 0x01, 0x82, 0x09, 0x5b, 0x2b, -0x5a, 0x05, 0x00, 0x02, 0x78, 0x09, 0x66, 0x2b, -0x5a, 0x05, 0x00, 0x03, 0x4c, 0x15, 0x76, 0x2b, -0x5a, 0x05, 0x00, 0x04, 0x24, 0x15, 0x7c, 0x2b, -0x5a, 0x05, 0x00, 0x05, 0x50, 0x13, 0x82, 0x2b, -0x5a, 0x05, 0x00, 0x06, 0xe1, 0x02, 0x88, 0x2b, -0x0d, -0x42, 0x04, 0x00, 0x88, 0x2b, 0x07, 0x3d + 0x67, 0x05, 0x00, 0x00, 0x02, 0x2e, 0x00, 0x70, + 0x67, 0x05, 0x00, 0x01, 0x02, 0x2e, 0xb8, 0x71, + 0x67, 0x05, 0x00, 0x02, 0x02, 0x2e, 0x35, 0x72, + 0x67, 0x05, 0x00, 0x08, 0x02, 0x2e, 0xbb, 0x72, + 0x67, 0x05, 0x00, 0x07, 0x02, 0x2e, 0x3b, 0x73, + 0x67, 0x05, 0x00, 0x0d, 0x02, 0x2e, 0x38, 0x74, + 0x67, 0x05, 0x00, 0x0b, 0x02, 0x2e, 0x85, 0x74, + 0x67, 0x05, 0x00, 0x0e, 0x02, 0x2e, 0x61, 0x75, + 0x67, 0x05, 0x00, 0x05, 0x02, 0x2e, 0xa6, 0x75, + 0x67, 0x05, 0x00, 0x0c, 0x02, 0x2e, 0x89, 0x78, + 0x67, 0x05, 0x00, 0x09, 0x02, 0x2e, 0xd7, 0x79, + 0x5a, 0x05, 0x00, 0x00, 0x6b, 0x01, 0x4f, 0x2b, + 0x5a, 0x05, 0x00, 0x01, 0x82, 0x09, 0x5b, 0x2b, + 0x5a, 0x05, 0x00, 0x02, 0x78, 0x09, 0x66, 0x2b, + 0x5a, 0x05, 0x00, 0x03, 0x4c, 0x15, 0x76, 0x2b, + 0x5a, 0x05, 0x00, 0x04, 0x24, 0x15, 0x7c, 0x2b, + 0x5a, 0x05, 0x00, 0x05, 0x50, 0x13, 0x82, 0x2b, + 0x5a, 0x05, 0x00, 0x06, 0xe1, 0x02, 0x88, 0x2b, + 0x0d, + 0x42, 0x04, 0x00, 0x88, 0x2b, 0x07, 0x3d }; struct aesX660_cmd aes1660_init_2[] = { - { .cmd = pkt433, .len = sizeof(pkt433) }, - { .cmd = pkt440, .len = sizeof(pkt440) }, - { .cmd = pkt444, .len = sizeof(pkt444) }, - { .cmd = pkt448, .len = sizeof(pkt448) }, - { .cmd = pkt452, .len = sizeof(pkt452) }, - { .cmd = pkt456, .len = sizeof(pkt456) }, - { .cmd = pkt460, .len = sizeof(pkt460) }, - { .cmd = pkt464, .len = sizeof(pkt464) }, - { .cmd = pkt468, .len = sizeof(pkt468) }, - { .cmd = pkt472, .len = sizeof(pkt472) }, - { .cmd = pkt476, .len = sizeof(pkt476) }, - { .cmd = pkt480, .len = sizeof(pkt480) }, - { .cmd = pkt484, .len = sizeof(pkt484) }, - { .cmd = pkt488, .len = sizeof(pkt488) }, - { .cmd = pkt492, .len = sizeof(pkt492) }, - { .cmd = pkt496, .len = sizeof(pkt496) }, - { .cmd = pkt500, .len = sizeof(pkt500) }, - { .cmd = pkt504, .len = sizeof(pkt504) }, - { .cmd = pkt508, .len = sizeof(pkt508) }, - { .cmd = pkt512, .len = sizeof(pkt512) }, - { .cmd = pkt516, .len = sizeof(pkt516) }, - { .cmd = pkt520, .len = sizeof(pkt520) }, - { .cmd = pkt524, .len = sizeof(pkt524) }, - { .cmd = pkt528, .len = sizeof(pkt528) }, - { .cmd = pkt532, .len = sizeof(pkt532) }, - { .cmd = pkt536, .len = sizeof(pkt536) }, - { .cmd = pkt540, .len = sizeof(pkt540) }, - { .cmd = pkt544, .len = sizeof(pkt544) }, - { .cmd = pkt548, .len = sizeof(pkt548) }, - { .cmd = pkt552, .len = sizeof(pkt552) }, - { .cmd = pkt556, .len = sizeof(pkt556) }, - { .cmd = pkt560, .len = sizeof(pkt560) }, - { .cmd = pkt564, .len = sizeof(pkt564) }, - { .cmd = pkt568, .len = sizeof(pkt568) }, - { .cmd = pkt572, .len = sizeof(pkt572) }, - { .cmd = pkt576, .len = sizeof(pkt576) }, - { .cmd = pkt580, .len = sizeof(pkt580) }, - { .cmd = pkt584, .len = sizeof(pkt584) }, - { .cmd = pkt588, .len = sizeof(pkt588) }, - { .cmd = pkt592, .len = sizeof(pkt592) }, - { .cmd = pkt596, .len = sizeof(pkt596) }, - { .cmd = pkt600, .len = sizeof(pkt600) }, - { .cmd = pkt604, .len = sizeof(pkt604) }, + { .cmd = pkt433, .len = sizeof (pkt433) }, + { .cmd = pkt440, .len = sizeof (pkt440) }, + { .cmd = pkt444, .len = sizeof (pkt444) }, + { .cmd = pkt448, .len = sizeof (pkt448) }, + { .cmd = pkt452, .len = sizeof (pkt452) }, + { .cmd = pkt456, .len = sizeof (pkt456) }, + { .cmd = pkt460, .len = sizeof (pkt460) }, + { .cmd = pkt464, .len = sizeof (pkt464) }, + { .cmd = pkt468, .len = sizeof (pkt468) }, + { .cmd = pkt472, .len = sizeof (pkt472) }, + { .cmd = pkt476, .len = sizeof (pkt476) }, + { .cmd = pkt480, .len = sizeof (pkt480) }, + { .cmd = pkt484, .len = sizeof (pkt484) }, + { .cmd = pkt488, .len = sizeof (pkt488) }, + { .cmd = pkt492, .len = sizeof (pkt492) }, + { .cmd = pkt496, .len = sizeof (pkt496) }, + { .cmd = pkt500, .len = sizeof (pkt500) }, + { .cmd = pkt504, .len = sizeof (pkt504) }, + { .cmd = pkt508, .len = sizeof (pkt508) }, + { .cmd = pkt512, .len = sizeof (pkt512) }, + { .cmd = pkt516, .len = sizeof (pkt516) }, + { .cmd = pkt520, .len = sizeof (pkt520) }, + { .cmd = pkt524, .len = sizeof (pkt524) }, + { .cmd = pkt528, .len = sizeof (pkt528) }, + { .cmd = pkt532, .len = sizeof (pkt532) }, + { .cmd = pkt536, .len = sizeof (pkt536) }, + { .cmd = pkt540, .len = sizeof (pkt540) }, + { .cmd = pkt544, .len = sizeof (pkt544) }, + { .cmd = pkt548, .len = sizeof (pkt548) }, + { .cmd = pkt552, .len = sizeof (pkt552) }, + { .cmd = pkt556, .len = sizeof (pkt556) }, + { .cmd = pkt560, .len = sizeof (pkt560) }, + { .cmd = pkt564, .len = sizeof (pkt564) }, + { .cmd = pkt568, .len = sizeof (pkt568) }, + { .cmd = pkt572, .len = sizeof (pkt572) }, + { .cmd = pkt576, .len = sizeof (pkt576) }, + { .cmd = pkt580, .len = sizeof (pkt580) }, + { .cmd = pkt584, .len = sizeof (pkt584) }, + { .cmd = pkt588, .len = sizeof (pkt588) }, + { .cmd = pkt592, .len = sizeof (pkt592) }, + { .cmd = pkt596, .len = sizeof (pkt596) }, + { .cmd = pkt600, .len = sizeof (pkt600) }, + { .cmd = pkt604, .len = sizeof (pkt604) }, }; /* INIT2 is over, 0x07 cmd returns * { 0x07, 0x05, 0x00, 0x8f, 0x16, 0x25, 0x01, 0x63 } @@ -1979,12 +1979,12 @@ struct aesX660_cmd aes1660_init_2[] = { /* This command sequence starts imaging */ static const unsigned char aes1660_start_imaging_cmd[] = { -0x13, -0x20, -0x4c, 0x01, 0x00, 0x00, -0x4b, 0x04, 0x00, 0x78, 0x56, 0x34, 0x12, -0x55, 0x07, 0x00, 0x80, 0x42, 0x00, 0x7f, 0x00, 0x00, 0x14, -0x49, 0x03, 0x00, 0x20, 0x00, 0xc8 + 0x13, + 0x20, + 0x4c, 0x01, 0x00, 0x00, + 0x4b, 0x04, 0x00, 0x78, 0x56, 0x34, 0x12, + 0x55, 0x07, 0x00, 0x80, 0x42, 0x00, 0x7f, 0x00, 0x00, 0x14, + 0x49, 0x03, 0x00, 0x20, 0x00, 0xc8 }; #endif diff --git a/libfprint/drivers/aes2501.c b/libfprint/drivers/aes2501.c index 91e02a39..fad0218e 100644 --- a/libfprint/drivers/aes2501.c +++ b/libfprint/drivers/aes2501.c @@ -27,19 +27,19 @@ #include "aeslib.h" #include "aes2501.h" -static void start_capture(struct fp_img_dev *dev); -static void complete_deactivation(struct fp_img_dev *dev); +static void start_capture (FpImageDevice *dev); +static void complete_deactivation (FpImageDevice *dev); /* FIXME these need checking */ -#define EP_IN (1 | LIBUSB_ENDPOINT_IN) -#define EP_OUT (2 | LIBUSB_ENDPOINT_OUT) +#define EP_IN (1 | FPI_USB_ENDPOINT_IN) +#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT) #define BULK_TIMEOUT 4000 -#define FINGER_DETECTION_LEN 20 -#define READ_REGS_LEN 126 -#define READ_REGS_RESP_LEN 159 -#define STRIP_CAPTURE_LEN 1705 +#define FINGER_DETECTION_LEN 20 +#define READ_REGS_LEN 126 +#define READ_REGS_RESP_LEN 159 +#define STRIP_CAPTURE_LEN 1705 /* * The AES2501 is an imaging device using a swipe-type sensor. It samples @@ -53,363 +53,345 @@ static void complete_deactivation(struct fp_img_dev *dev); * images returned from this driver vary in height. */ -#define FRAME_WIDTH 192 -#define FRAME_HEIGHT 16 -#define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT) -#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2)) +#define FRAME_WIDTH 192 +#define FRAME_HEIGHT 16 +#define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT) +#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2)) /* maximum number of frames to read during a scan */ /* FIXME reduce substantially */ -#define MAX_FRAMES 150 +#define MAX_FRAMES 150 /****** GENERAL FUNCTIONS ******/ -struct aes2501_dev { - uint8_t read_regs_retry_count; - GSList *strips; - size_t strips_len; - gboolean deactivating; - int no_finger_cnt; +struct _FpiDeviceAes2501 +{ + FpImageDevice parent; + + guint8 read_regs_retry_count; + GSList *strips; + size_t strips_len; + gboolean deactivating; + int no_finger_cnt; }; +G_DECLARE_FINAL_TYPE (FpiDeviceAes2501, fpi_device_aes2501, FPI, DEVICE_AES2501, + FpImageDevice); +G_DEFINE_TYPE (FpiDeviceAes2501, fpi_device_aes2501, FP_TYPE_IMAGE_DEVICE); static struct fpi_frame_asmbl_ctx assembling_ctx = { - .frame_width = FRAME_WIDTH, - .frame_height = FRAME_HEIGHT, - .image_width = IMAGE_WIDTH, - .get_pixel = aes_get_pixel, + .frame_width = FRAME_WIDTH, + .frame_height = FRAME_HEIGHT, + .image_width = IMAGE_WIDTH, + .get_pixel = aes_get_pixel, }; -typedef void (*aes2501_read_regs_cb)(struct fp_img_dev *dev, int status, - unsigned char *regs, void *user_data); +typedef void (*aes2501_read_regs_cb)(FpImageDevice *dev, + GError *error, + unsigned char *regs, + void *user_data); -struct aes2501_read_regs { - struct fp_img_dev *dev; - aes2501_read_regs_cb callback; - struct aes_regwrite *regwrite; - void *user_data; +struct aes2501_read_regs +{ + FpImageDevice *dev; + aes2501_read_regs_cb callback; + struct aes_regwrite *regwrite; + void *user_data; }; -static void read_regs_data_cb(struct libusb_transfer *transfer, - struct fp_dev *dev, - fpi_ssm *ssm, - void *user_data) +static void +read_regs_data_cb (FpiUsbTransfer *transfer, FpDevice *dev, + gpointer user_data, GError *error) { - struct aes2501_read_regs *rdata = user_data; - unsigned char *retdata = NULL; - int r; + struct aes2501_read_regs *rdata = user_data; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - r = -EIO; - } else if (transfer->length != transfer->actual_length) { - r = -EPROTO; - } else { - r = 0; - retdata = transfer->buffer; - } - - rdata->callback(rdata->dev, r, retdata, rdata->user_data); - g_free(rdata); + rdata->callback (rdata->dev, error, transfer->buffer, rdata->user_data); + g_free (rdata); } -static void read_regs_rq_cb(struct fp_img_dev *dev, int result, void *user_data) +static void +read_regs_rq_cb (FpImageDevice *dev, GError *error, void *user_data) { - struct aes2501_read_regs *rdata = user_data; - fpi_usb_transfer *transfer; - unsigned char *data; - int r; + struct aes2501_read_regs *rdata = user_data; + FpiUsbTransfer *transfer; - g_free(rdata->regwrite); - if (result != 0) - goto err; + g_free (rdata->regwrite); + if (error) + { + rdata->callback (dev, error, NULL, rdata->user_data); + g_free (rdata); + return; + } - data = g_malloc(READ_REGS_LEN); - transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev), - NULL, - EP_IN, - data, - READ_REGS_LEN, - read_regs_data_cb, - rdata, - BULK_TIMEOUT); - - r = fpi_usb_submit_transfer(transfer); - if (r < 0) { - result = -EIO; - goto err; - } - - return; -err: - rdata->callback(dev, result, NULL, rdata->user_data); - g_free(rdata); + transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); + transfer->short_is_error = TRUE; + fpi_usb_transfer_fill_bulk (transfer, EP_IN, READ_REGS_LEN); + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + read_regs_data_cb, rdata); + fpi_usb_transfer_unref (transfer); } -static void read_regs(struct fp_img_dev *dev, aes2501_read_regs_cb callback, - void *user_data) +static void +read_regs (FpImageDevice *dev, aes2501_read_regs_cb callback, + void *user_data) { - /* FIXME: regwrite is dynamic because of asynchronity. is this really - * required? */ - struct aes_regwrite *regwrite = g_malloc(sizeof(*regwrite)); - struct aes2501_read_regs *rdata = g_malloc(sizeof(*rdata)); + /* FIXME: regwrite is dynamic because of asynchronity. is this really + * required? */ + struct aes_regwrite *regwrite = g_malloc (sizeof (*regwrite)); + struct aes2501_read_regs *rdata = g_malloc (sizeof (*rdata)); - G_DEBUG_HERE(); - regwrite->reg = AES2501_REG_CTRL2; - regwrite->value = AES2501_CTRL2_READ_REGS; - rdata->dev = dev; - rdata->callback = callback; - rdata->user_data = user_data; - rdata->regwrite = regwrite; + G_DEBUG_HERE (); + regwrite->reg = AES2501_REG_CTRL2; + regwrite->value = AES2501_CTRL2_READ_REGS; + rdata->dev = dev; + rdata->callback = callback; + rdata->user_data = user_data; + rdata->regwrite = regwrite; - aes_write_regv(dev, (const struct aes_regwrite *) regwrite, 1, - read_regs_rq_cb, rdata); + aes_write_regv (dev, (const struct aes_regwrite *) regwrite, 1, + read_regs_rq_cb, rdata); } /* Read the value of a specific register from a register dump */ -static int regval_from_dump(unsigned char *data, uint8_t target) +static int +regval_from_dump (unsigned char *data, guint8 target) { - if (*data != FIRST_AES2501_REG) { - fp_err("not a register dump"); - return -EILSEQ; - } + if (*data != FIRST_AES2501_REG) + { + fp_err ("not a register dump"); + return -1; + } - if (!(FIRST_AES2501_REG <= target && target <= LAST_AES2501_REG)) { - fp_err("out of range"); - return -EINVAL; - } + if (!(FIRST_AES2501_REG <= target && target <= LAST_AES2501_REG)) + { + fp_err ("out of range"); + return -1; + } - target -= FIRST_AES2501_REG; - target *= 2; - return data[target + 1]; + target -= FIRST_AES2501_REG; + target *= 2; + return data[target + 1]; } -static void generic_write_regv_cb(struct fp_img_dev *dev, int result, - void *user_data) +static void +generic_write_regv_cb (FpImageDevice *dev, GError *error, + void *user_data) { - fpi_ssm *ssm = user_data; - if (result == 0) - fpi_ssm_next_state(ssm); - else - fpi_ssm_mark_failed(ssm, result); + FpiSsm *ssm = user_data; + + if (!error) + fpi_ssm_next_state (ssm); + else + fpi_ssm_mark_failed (ssm, error); } /* check that read succeeded but ignore all data */ -static void generic_ignore_data_cb(struct libusb_transfer *transfer, - struct fp_dev *dev, - fpi_ssm *ssm, - void *user_data) +static void +generic_ignore_data_cb (FpiUsbTransfer *transfer, FpDevice *dev, + gpointer user_data, GError *error) { - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) - fpi_ssm_mark_failed(ssm, -EIO); - else if (transfer->length != transfer->actual_length) - fpi_ssm_mark_failed(ssm, -EPROTO); - else - fpi_ssm_next_state(ssm); + FpiSsm *ssm = transfer->ssm; + + if (error) + fpi_ssm_mark_failed (ssm, error); + else + fpi_ssm_next_state (ssm); } /* read the specified number of bytes from the IN endpoint but throw them * away, then increment the SSM */ -static void generic_read_ignore_data(fpi_ssm *ssm, struct fp_dev *dev, size_t bytes) +static void +generic_read_ignore_data (FpiSsm *ssm, FpDevice *dev, + size_t bytes) { - fpi_usb_transfer *transfer; - unsigned char *data; - int r; + FpiUsbTransfer *transfer; - data = g_malloc(bytes); - transfer = fpi_usb_fill_bulk_transfer(dev, - ssm, - EP_IN, - data, - bytes, - generic_ignore_data_cb, - NULL, - BULK_TIMEOUT); - - r = fpi_usb_submit_transfer(transfer); - if (r < 0) - fpi_ssm_mark_failed(ssm, r); + transfer = fpi_usb_transfer_new (dev); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_fill_bulk (transfer, EP_IN, bytes); + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + generic_ignore_data_cb, NULL); + fpi_usb_transfer_unref (transfer); } /****** IMAGE PROCESSING ******/ -static int sum_histogram_values(unsigned char *data, uint8_t threshold) +static int +sum_histogram_values (unsigned char *data, guint8 threshold) { - int r = 0; - int i; - uint16_t *histogram = (uint16_t *)(data + 1); + int r = 0; + int i; + guint16 *histogram = (guint16 *) (data + 1); - if (*data != 0xde) - return -EILSEQ; + if (*data != 0xde) + return -1; - if (threshold > 0x0f) - return -EINVAL; + if (threshold > 0x0f) + return -1; - /* FIXME endianness */ - for (i = threshold; i < 16; i++) - r += histogram[i]; - - return r; + /* FIXME endianness */ + for (i = threshold; i < 16; i++) + r += histogram[i]; + + return r; } /****** FINGER PRESENCE DETECTION ******/ static const struct aes_regwrite finger_det_reqs[] = { - { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, - { AES2501_REG_EXCITCTRL, 0x40 }, - { AES2501_REG_DETCTRL, - AES2501_DETCTRL_DRATE_CONTINUOUS | AES2501_DETCTRL_SDELAY_31_MS }, - { AES2501_REG_COLSCAN, AES2501_COLSCAN_SRATE_128_US }, - { AES2501_REG_MEASDRV, AES2501_MEASDRV_MDRIVE_0_325 | AES2501_MEASDRV_MEASURE_SQUARE }, - { AES2501_REG_MEASFREQ, AES2501_MEASFREQ_2M }, - { AES2501_REG_DEMODPHASE1, DEMODPHASE_NONE }, - { AES2501_REG_DEMODPHASE2, DEMODPHASE_NONE }, - { AES2501_REG_CHANGAIN, - AES2501_CHANGAIN_STAGE2_4X | AES2501_CHANGAIN_STAGE1_16X }, - { AES2501_REG_ADREFHI, 0x44 }, - { AES2501_REG_ADREFLO, 0x34 }, - { AES2501_REG_STRTCOL, 0x16 }, - { AES2501_REG_ENDCOL, 0x16 }, - { AES2501_REG_DATFMT, AES2501_DATFMT_BIN_IMG | 0x08 }, - { AES2501_REG_TREG1, 0x70 }, - { 0xa2, 0x02 }, - { 0xa7, 0x00 }, - { AES2501_REG_TREGC, AES2501_TREGC_ENABLE }, - { AES2501_REG_TREGD, 0x1a }, - { 0, 0 }, - { AES2501_REG_CTRL1, AES2501_CTRL1_REG_UPDATE }, - { AES2501_REG_CTRL2, AES2501_CTRL2_SET_ONE_SHOT }, - { AES2501_REG_LPONT, AES2501_LPONT_MIN_VALUE }, + { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, + { AES2501_REG_EXCITCTRL, 0x40 }, + { AES2501_REG_DETCTRL, + AES2501_DETCTRL_DRATE_CONTINUOUS | AES2501_DETCTRL_SDELAY_31_MS }, + { AES2501_REG_COLSCAN, AES2501_COLSCAN_SRATE_128_US }, + { AES2501_REG_MEASDRV, AES2501_MEASDRV_MDRIVE_0_325 | AES2501_MEASDRV_MEASURE_SQUARE }, + { AES2501_REG_MEASFREQ, AES2501_MEASFREQ_2M }, + { AES2501_REG_DEMODPHASE1, DEMODPHASE_NONE }, + { AES2501_REG_DEMODPHASE2, DEMODPHASE_NONE }, + { AES2501_REG_CHANGAIN, + AES2501_CHANGAIN_STAGE2_4X | AES2501_CHANGAIN_STAGE1_16X }, + { AES2501_REG_ADREFHI, 0x44 }, + { AES2501_REG_ADREFLO, 0x34 }, + { AES2501_REG_STRTCOL, 0x16 }, + { AES2501_REG_ENDCOL, 0x16 }, + { AES2501_REG_DATFMT, AES2501_DATFMT_BIN_IMG | 0x08 }, + { AES2501_REG_TREG1, 0x70 }, + { 0xa2, 0x02 }, + { 0xa7, 0x00 }, + { AES2501_REG_TREGC, AES2501_TREGC_ENABLE }, + { AES2501_REG_TREGD, 0x1a }, + { 0, 0 }, + { AES2501_REG_CTRL1, AES2501_CTRL1_REG_UPDATE }, + { AES2501_REG_CTRL2, AES2501_CTRL2_SET_ONE_SHOT }, + { AES2501_REG_LPONT, AES2501_LPONT_MIN_VALUE }, }; -static void start_finger_detection(struct fp_img_dev *dev); +static void start_finger_detection (FpImageDevice *dev); -static void finger_det_data_cb(struct libusb_transfer *transfer, - struct fp_dev *_dev, - fpi_ssm *ssm, - void *user_data) +static void +finger_det_data_cb (FpiUsbTransfer *transfer, FpDevice *_dev, + gpointer user_data, GError *error) { - struct fp_img_dev *dev = FP_IMG_DEV(_dev); - unsigned char *data = transfer->buffer; - int i; - int sum = 0; + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + unsigned char *data = transfer->buffer; + int i; + int sum = 0; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fpi_imgdev_session_error(dev, -EIO); - return; - } else if (transfer->length != transfer->actual_length) { - fpi_imgdev_session_error(dev, -EPROTO); - return; - } + if (error) + { + fpi_image_device_session_error (dev, error); + return; + } - /* examine histogram to determine finger presence */ - for (i = 1; i < 9; i++) - sum += (data[i] & 0xf) + (data[i] >> 4); - if (sum > 20) { - /* finger present, start capturing */ - fpi_imgdev_report_finger_status(dev, TRUE); - start_capture(dev); - } else { - /* no finger, poll for a new histogram */ - start_finger_detection(dev); - } + /* examine histogram to determine finger presence */ + for (i = 1; i < 9; i++) + sum += (data[i] & 0xf) + (data[i] >> 4); + if (sum > 20) + { + /* finger present, start capturing */ + fpi_image_device_report_finger_status (dev, TRUE); + start_capture (dev); + } + else + { + /* no finger, poll for a new histogram */ + start_finger_detection (dev); + } } -static void finger_det_reqs_cb(struct fp_img_dev *dev, int result, - void *user_data) +static void +finger_det_reqs_cb (FpImageDevice *dev, GError *error, + void *user_data) { - fpi_usb_transfer *transfer; - unsigned char *data; - int r; + FpiUsbTransfer *transfer; - if (result) { - fpi_imgdev_session_error(dev, result); - return; - } + if (error) + { + fpi_image_device_session_error (dev, error); + return; + } - data = g_malloc(FINGER_DETECTION_LEN); - transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev), - NULL, - EP_IN, - data, - FINGER_DETECTION_LEN, - finger_det_data_cb, - NULL, - BULK_TIMEOUT); - - r = fpi_usb_submit_transfer(transfer); - if (r < 0) - fpi_imgdev_session_error(dev, r); + transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); + transfer->short_is_error = TRUE; + fpi_usb_transfer_fill_bulk (transfer, EP_IN, FINGER_DETECTION_LEN); + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + finger_det_data_cb, NULL); + fpi_usb_transfer_unref (transfer); } -static void start_finger_detection(struct fp_img_dev *dev) +static void +start_finger_detection (FpImageDevice *dev) { - struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - G_DEBUG_HERE(); + FpiDeviceAes2501 *self = FPI_DEVICE_AES2501 (dev); - if (aesdev->deactivating) { - complete_deactivation(dev); - return; - } + G_DEBUG_HERE (); - aes_write_regv(dev, finger_det_reqs, G_N_ELEMENTS(finger_det_reqs), - finger_det_reqs_cb, NULL); + if (self->deactivating) + { + complete_deactivation (dev); + return; + } + + aes_write_regv (dev, finger_det_reqs, G_N_ELEMENTS (finger_det_reqs), + finger_det_reqs_cb, NULL); } /****** CAPTURE ******/ static const struct aes_regwrite capture_reqs_1[] = { - { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, - { 0, 0 }, - { AES2501_REG_EXCITCTRL, 0x40 }, - { AES2501_REG_DETCTRL, - AES2501_DETCTRL_SDELAY_31_MS | AES2501_DETCTRL_DRATE_CONTINUOUS }, - { AES2501_REG_COLSCAN, AES2501_COLSCAN_SRATE_128_US }, - { AES2501_REG_DEMODPHASE2, 0x7c }, - { AES2501_REG_MEASDRV, - AES2501_MEASDRV_MEASURE_SQUARE | AES2501_MEASDRV_MDRIVE_0_325 }, - { AES2501_REG_DEMODPHASE1, 0x24 }, - { AES2501_REG_CHWORD1, 0x00 }, - { AES2501_REG_CHWORD2, 0x6c }, - { AES2501_REG_CHWORD3, 0x09 }, - { AES2501_REG_CHWORD4, 0x54 }, - { AES2501_REG_CHWORD5, 0x78 }, - { 0xa2, 0x02 }, - { 0xa7, 0x00 }, - { 0xb6, 0x26 }, - { 0xb7, 0x1a }, - { AES2501_REG_CTRL1, AES2501_CTRL1_REG_UPDATE }, - { AES2501_REG_IMAGCTRL, - AES2501_IMAGCTRL_TST_REG_ENABLE | AES2501_IMAGCTRL_HISTO_DATA_ENABLE | - AES2501_IMAGCTRL_IMG_DATA_DISABLE }, - { AES2501_REG_STRTCOL, 0x10 }, - { AES2501_REG_ENDCOL, 0x1f }, - { AES2501_REG_CHANGAIN, - AES2501_CHANGAIN_STAGE1_2X | AES2501_CHANGAIN_STAGE2_2X }, - { AES2501_REG_ADREFHI, 0x70 }, - { AES2501_REG_ADREFLO, 0x20 }, - { AES2501_REG_CTRL2, AES2501_CTRL2_SET_ONE_SHOT }, - { AES2501_REG_LPONT, AES2501_LPONT_MIN_VALUE }, + { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, + { 0, 0 }, + { AES2501_REG_EXCITCTRL, 0x40 }, + { AES2501_REG_DETCTRL, + AES2501_DETCTRL_SDELAY_31_MS | AES2501_DETCTRL_DRATE_CONTINUOUS }, + { AES2501_REG_COLSCAN, AES2501_COLSCAN_SRATE_128_US }, + { AES2501_REG_DEMODPHASE2, 0x7c }, + { AES2501_REG_MEASDRV, + AES2501_MEASDRV_MEASURE_SQUARE | AES2501_MEASDRV_MDRIVE_0_325 }, + { AES2501_REG_DEMODPHASE1, 0x24 }, + { AES2501_REG_CHWORD1, 0x00 }, + { AES2501_REG_CHWORD2, 0x6c }, + { AES2501_REG_CHWORD3, 0x09 }, + { AES2501_REG_CHWORD4, 0x54 }, + { AES2501_REG_CHWORD5, 0x78 }, + { 0xa2, 0x02 }, + { 0xa7, 0x00 }, + { 0xb6, 0x26 }, + { 0xb7, 0x1a }, + { AES2501_REG_CTRL1, AES2501_CTRL1_REG_UPDATE }, + { AES2501_REG_IMAGCTRL, + AES2501_IMAGCTRL_TST_REG_ENABLE | AES2501_IMAGCTRL_HISTO_DATA_ENABLE | + AES2501_IMAGCTRL_IMG_DATA_DISABLE }, + { AES2501_REG_STRTCOL, 0x10 }, + { AES2501_REG_ENDCOL, 0x1f }, + { AES2501_REG_CHANGAIN, + AES2501_CHANGAIN_STAGE1_2X | AES2501_CHANGAIN_STAGE2_2X }, + { AES2501_REG_ADREFHI, 0x70 }, + { AES2501_REG_ADREFLO, 0x20 }, + { AES2501_REG_CTRL2, AES2501_CTRL2_SET_ONE_SHOT }, + { AES2501_REG_LPONT, AES2501_LPONT_MIN_VALUE }, }; static const struct aes_regwrite capture_reqs_2[] = { - { AES2501_REG_IMAGCTRL, - AES2501_IMAGCTRL_TST_REG_ENABLE | AES2501_IMAGCTRL_HISTO_DATA_ENABLE | - AES2501_IMAGCTRL_IMG_DATA_DISABLE }, - { AES2501_REG_STRTCOL, 0x10 }, - { AES2501_REG_ENDCOL, 0x1f }, - { AES2501_REG_CHANGAIN, AES2501_CHANGAIN_STAGE1_16X }, - { AES2501_REG_ADREFHI, 0x70 }, - { AES2501_REG_ADREFLO, 0x20 }, - { AES2501_REG_CTRL2, AES2501_CTRL2_SET_ONE_SHOT }, + { AES2501_REG_IMAGCTRL, + AES2501_IMAGCTRL_TST_REG_ENABLE | AES2501_IMAGCTRL_HISTO_DATA_ENABLE | + AES2501_IMAGCTRL_IMG_DATA_DISABLE }, + { AES2501_REG_STRTCOL, 0x10 }, + { AES2501_REG_ENDCOL, 0x1f }, + { AES2501_REG_CHANGAIN, AES2501_CHANGAIN_STAGE1_16X }, + { AES2501_REG_ADREFHI, 0x70 }, + { AES2501_REG_ADREFLO, 0x20 }, + { AES2501_REG_CTRL2, AES2501_CTRL2_SET_ONE_SHOT }, }; static struct aes_regwrite strip_scan_reqs[] = { - { AES2501_REG_IMAGCTRL, - AES2501_IMAGCTRL_TST_REG_ENABLE | AES2501_IMAGCTRL_HISTO_DATA_ENABLE }, - { AES2501_REG_STRTCOL, 0x00 }, - { AES2501_REG_ENDCOL, 0x2f }, - { AES2501_REG_CHANGAIN, AES2501_CHANGAIN_STAGE1_16X }, - { AES2501_REG_ADREFHI, AES2501_ADREFHI_MAX_VALUE }, - { AES2501_REG_ADREFLO, 0x20 }, - { AES2501_REG_CTRL2, AES2501_CTRL2_SET_ONE_SHOT }, + { AES2501_REG_IMAGCTRL, + AES2501_IMAGCTRL_TST_REG_ENABLE | AES2501_IMAGCTRL_HISTO_DATA_ENABLE }, + { AES2501_REG_STRTCOL, 0x00 }, + { AES2501_REG_ENDCOL, 0x2f }, + { AES2501_REG_CHANGAIN, AES2501_CHANGAIN_STAGE1_16X }, + { AES2501_REG_ADREFHI, AES2501_ADREFHI_MAX_VALUE }, + { AES2501_REG_ADREFLO, 0x20 }, + { AES2501_REG_CTRL2, AES2501_CTRL2_SET_ONE_SHOT }, }; /* capture SM movement: @@ -419,459 +401,500 @@ static struct aes_regwrite strip_scan_reqs[] = { * report lack of finger presence, and move to finger detection */ enum capture_states { - CAPTURE_WRITE_REQS_1, - CAPTURE_READ_DATA_1, - CAPTURE_WRITE_REQS_2, - CAPTURE_READ_DATA_2, - CAPTURE_REQUEST_STRIP, - CAPTURE_READ_STRIP, - CAPTURE_NUM_STATES, + CAPTURE_WRITE_REQS_1, + CAPTURE_READ_DATA_1, + CAPTURE_WRITE_REQS_2, + CAPTURE_READ_DATA_2, + CAPTURE_REQUEST_STRIP, + CAPTURE_READ_STRIP, + CAPTURE_NUM_STATES, }; -static void capture_read_strip_cb(struct libusb_transfer *transfer, - struct fp_dev *_dev, - fpi_ssm *ssm, - void *user_data) +static void +capture_read_strip_cb (FpiUsbTransfer *transfer, FpDevice *_dev, + gpointer user_data, GError *error) { - unsigned char *stripdata; - struct fp_img_dev *dev = FP_IMG_DEV(_dev); - struct aes2501_dev *aesdev = FP_INSTANCE_DATA(_dev); - unsigned char *data = transfer->buffer; - int sum; - int threshold; + FpiSsm *ssm = transfer->ssm; + unsigned char *stripdata; + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceAes2501 *self = FPI_DEVICE_AES2501 (_dev); + unsigned char *data = transfer->buffer; + int sum; + int threshold; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fpi_ssm_mark_failed(ssm, -EIO); - return; - } else if (transfer->length != transfer->actual_length) { - fpi_ssm_mark_failed(ssm, -EPROTO); - return; - } + if (error) + { + fpi_ssm_mark_failed (ssm, error); + return; + } - threshold = regval_from_dump(data + 1 + 192*8 + 1 + 16*2 + 1 + 8, - AES2501_REG_DATFMT); - if (threshold < 0) { - fpi_ssm_mark_failed(ssm, threshold); - return; - } + threshold = regval_from_dump (data + 1 + 192 * 8 + 1 + 16 * 2 + 1 + 8, + AES2501_REG_DATFMT); + if (threshold < 0) + { + fpi_ssm_mark_failed (ssm, + fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); + return; + } - sum = sum_histogram_values(data + 1 + 192*8, threshold & 0x0f); - if (sum < 0) { - fpi_ssm_mark_failed(ssm, sum); - return; - } - fp_dbg("sum=%d", sum); + sum = sum_histogram_values (data + 1 + 192 * 8, threshold & 0x0f); + if (sum < 0) + { + fpi_ssm_mark_failed (ssm, + fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); + return; + } + fp_dbg ("sum=%d", sum); - if (sum < AES2501_SUM_LOW_THRESH) { - strip_scan_reqs[4].value -= 0x8; - if (strip_scan_reqs[4].value < AES2501_ADREFHI_MIN_VALUE) - strip_scan_reqs[4].value = AES2501_ADREFHI_MIN_VALUE; - } else if (sum > AES2501_SUM_HIGH_THRESH) { - strip_scan_reqs[4].value += 0x8; - if (strip_scan_reqs[4].value > AES2501_ADREFHI_MAX_VALUE) - strip_scan_reqs[4].value = AES2501_ADREFHI_MAX_VALUE; - } - fp_dbg("ADREFHI is %.2x", strip_scan_reqs[4].value); + if (sum < AES2501_SUM_LOW_THRESH) + { + strip_scan_reqs[4].value -= 0x8; + if (strip_scan_reqs[4].value < AES2501_ADREFHI_MIN_VALUE) + strip_scan_reqs[4].value = AES2501_ADREFHI_MIN_VALUE; + } + else if (sum > AES2501_SUM_HIGH_THRESH) + { + strip_scan_reqs[4].value += 0x8; + if (strip_scan_reqs[4].value > AES2501_ADREFHI_MAX_VALUE) + strip_scan_reqs[4].value = AES2501_ADREFHI_MAX_VALUE; + } + fp_dbg ("ADREFHI is %.2x", strip_scan_reqs[4].value); - /* Sum is 0, maybe finger was removed? Wait for 3 empty frames - * to ensure - */ - if (sum == 0) { - aesdev->no_finger_cnt++; - if (aesdev->no_finger_cnt == 3) { - struct fp_img *img; + /* Sum is 0, maybe finger was removed? Wait for 3 empty frames + * to ensure + */ + if (sum == 0) + { + self->no_finger_cnt++; + if (self->no_finger_cnt == 3) + { + FpImage *img; - aesdev->strips = g_slist_reverse(aesdev->strips); - fpi_do_movement_estimation(&assembling_ctx, - aesdev->strips, aesdev->strips_len); - img = fpi_assemble_frames(&assembling_ctx, - aesdev->strips, aesdev->strips_len); - img->flags |= FP_IMG_PARTIAL; - g_slist_free_full(aesdev->strips, g_free); - aesdev->strips = NULL; - aesdev->strips_len = 0; - fpi_imgdev_image_captured(dev, img); - fpi_imgdev_report_finger_status(dev, FALSE); - /* marking machine complete will re-trigger finger detection loop */ - fpi_ssm_mark_completed(ssm); - } else { - fpi_ssm_jump_to_state(ssm, CAPTURE_REQUEST_STRIP); - } - } else { - /* obtain next strip */ - /* FIXME: would preallocating strip buffers be a decent optimization? */ - struct fpi_frame *stripe = g_malloc(FRAME_WIDTH * FRAME_HEIGHT / 2 + sizeof(struct fpi_frame)); - stripe->delta_x = 0; - stripe->delta_y = 0; - stripdata = stripe->data; - memcpy(stripdata, data + 1, 192*8); - aesdev->no_finger_cnt = 0; - aesdev->strips = g_slist_prepend(aesdev->strips, stripe); - aesdev->strips_len++; + self->strips = g_slist_reverse (self->strips); + fpi_do_movement_estimation (&assembling_ctx, self->strips); + img = fpi_assemble_frames (&assembling_ctx, + self->strips); + g_slist_free_full (self->strips, g_free); + self->strips = NULL; + self->strips_len = 0; + fpi_image_device_image_captured (dev, img); + fpi_image_device_report_finger_status (dev, FALSE); + /* marking machine complete will re-trigger finger detection loop */ + fpi_ssm_mark_completed (ssm); + } + else + { + fpi_ssm_jump_to_state (ssm, CAPTURE_REQUEST_STRIP); + } + } + else + { + /* obtain next strip */ + /* FIXME: would preallocating strip buffers be a decent optimization? */ + struct fpi_frame *stripe = g_malloc (FRAME_WIDTH * FRAME_HEIGHT / 2 + sizeof (struct fpi_frame)); + stripe->delta_x = 0; + stripe->delta_y = 0; + stripdata = stripe->data; + memcpy (stripdata, data + 1, 192 * 8); + self->no_finger_cnt = 0; + self->strips = g_slist_prepend (self->strips, stripe); + self->strips_len++; - fpi_ssm_jump_to_state(ssm, CAPTURE_REQUEST_STRIP); - } + fpi_ssm_jump_to_state (ssm, CAPTURE_REQUEST_STRIP); + } } -static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +capture_run_state (FpiSsm *ssm, FpDevice *device) { - struct fp_img_dev *dev = user_data; - struct aes2501_dev *aesdev = FP_INSTANCE_DATA(_dev); - int r; + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpiDeviceAes2501 *self = FPI_DEVICE_AES2501 (device); - switch (fpi_ssm_get_cur_state(ssm)) { - case CAPTURE_WRITE_REQS_1: - aes_write_regv(dev, capture_reqs_1, G_N_ELEMENTS(capture_reqs_1), - generic_write_regv_cb, ssm); - break; - case CAPTURE_READ_DATA_1: - generic_read_ignore_data(ssm, _dev, READ_REGS_RESP_LEN); - break; - case CAPTURE_WRITE_REQS_2: - aes_write_regv(dev, capture_reqs_2, G_N_ELEMENTS(capture_reqs_2), - generic_write_regv_cb, ssm); - break; - case CAPTURE_READ_DATA_2: - generic_read_ignore_data(ssm, _dev, READ_REGS_RESP_LEN); - break; - case CAPTURE_REQUEST_STRIP: - if (aesdev->deactivating) - fpi_ssm_mark_completed(ssm); - else - aes_write_regv(dev, strip_scan_reqs, G_N_ELEMENTS(strip_scan_reqs), - generic_write_regv_cb, ssm); - break; - case CAPTURE_READ_STRIP: ; - fpi_usb_transfer *transfer; - unsigned char *data; + switch (fpi_ssm_get_cur_state (ssm)) + { + case CAPTURE_WRITE_REQS_1: + aes_write_regv (dev, capture_reqs_1, G_N_ELEMENTS (capture_reqs_1), + generic_write_regv_cb, ssm); + break; - data = g_malloc(STRIP_CAPTURE_LEN); - transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev), - ssm, - EP_IN, - data, - STRIP_CAPTURE_LEN, - capture_read_strip_cb, - NULL, - BULK_TIMEOUT); + case CAPTURE_READ_DATA_1: + generic_read_ignore_data (ssm, device, READ_REGS_RESP_LEN); + break; - r = fpi_usb_submit_transfer(transfer); - if (r < 0) - fpi_ssm_mark_failed(ssm, r); - break; - }; + case CAPTURE_WRITE_REQS_2: + aes_write_regv (dev, capture_reqs_2, G_N_ELEMENTS (capture_reqs_2), + generic_write_regv_cb, ssm); + break; + + case CAPTURE_READ_DATA_2: + generic_read_ignore_data (ssm, device, READ_REGS_RESP_LEN); + break; + + case CAPTURE_REQUEST_STRIP: + if (self->deactivating) + fpi_ssm_mark_completed (ssm); + else + aes_write_regv (dev, strip_scan_reqs, G_N_ELEMENTS (strip_scan_reqs), + generic_write_regv_cb, ssm); + break; + + case CAPTURE_READ_STRIP: { + FpiUsbTransfer *transfer; + + transfer = fpi_usb_transfer_new (device); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_fill_bulk (transfer, EP_IN, STRIP_CAPTURE_LEN); + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + capture_read_strip_cb, NULL); + fpi_usb_transfer_unref (transfer); + break; + } + } + ; } -static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { - struct fp_img_dev *dev = user_data; - struct aes2501_dev *aesdev = FP_INSTANCE_DATA(_dev); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceAes2501 *self = FPI_DEVICE_AES2501 (_dev); - G_DEBUG_HERE(); - if (aesdev->deactivating) - complete_deactivation(dev); - else if (fpi_ssm_get_error(ssm)) - fpi_imgdev_session_error(dev, fpi_ssm_get_error(ssm)); - else - start_finger_detection(dev); - fpi_ssm_free(ssm); + G_DEBUG_HERE (); + + if (self->deactivating) + { + complete_deactivation (dev); + g_clear_pointer (&error, g_error_free); + } + else if (error) + { + fpi_image_device_session_error (dev, error); + } + else + { + start_finger_detection (dev); + } + fpi_ssm_free (ssm); } -static void start_capture(struct fp_img_dev *dev) +static void +start_capture (FpImageDevice *dev) { - struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_ssm *ssm; + FpiDeviceAes2501 *self = FPI_DEVICE_AES2501 (dev); + FpiSsm *ssm; - if (aesdev->deactivating) { - complete_deactivation(dev); - return; - } + if (self->deactivating) + { + complete_deactivation (dev); + return; + } - aesdev->no_finger_cnt = 0; - /* Reset gain */ - strip_scan_reqs[4].value = AES2501_ADREFHI_MAX_VALUE; - ssm = fpi_ssm_new(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev); - G_DEBUG_HERE(); - fpi_ssm_start(ssm, capture_sm_complete); + self->no_finger_cnt = 0; + /* Reset gain */ + strip_scan_reqs[4].value = AES2501_ADREFHI_MAX_VALUE; + ssm = fpi_ssm_new (FP_DEVICE (dev), capture_run_state, + CAPTURE_NUM_STATES); + G_DEBUG_HERE (); + fpi_ssm_start (ssm, capture_sm_complete); } /****** INITIALIZATION/DEINITIALIZATION ******/ static const struct aes_regwrite init_1[] = { - { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, - { 0, 0 }, - { 0xb0, 0x27 }, /* Reserved? */ - { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, - { AES2501_REG_EXCITCTRL, 0x40 }, - { 0xff, 0x00 }, /* Reserved? */ - { 0xff, 0x00 }, /* Reserved? */ - { 0xff, 0x00 }, /* Reserved? */ - { 0xff, 0x00 }, /* Reserved? */ - { 0xff, 0x00 }, /* Reserved? */ - { 0xff, 0x00 }, /* Reserved? */ - { 0xff, 0x00 }, /* Reserved? */ - { 0xff, 0x00 }, /* Reserved? */ - { 0xff, 0x00 }, /* Reserved? */ - { 0xff, 0x00 }, /* Reserved? */ - { 0xff, 0x00 }, /* Reserved? */ - { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, - { AES2501_REG_EXCITCTRL, 0x40 }, - { AES2501_REG_DETCTRL, - AES2501_DETCTRL_DRATE_CONTINUOUS | AES2501_DETCTRL_SDELAY_31_MS }, - { AES2501_REG_COLSCAN, AES2501_COLSCAN_SRATE_128_US }, - { AES2501_REG_MEASDRV, - AES2501_MEASDRV_MDRIVE_0_325 | AES2501_MEASDRV_MEASURE_SQUARE }, - { AES2501_REG_MEASFREQ, AES2501_MEASFREQ_2M }, - { AES2501_REG_DEMODPHASE1, DEMODPHASE_NONE }, - { AES2501_REG_DEMODPHASE2, DEMODPHASE_NONE }, - { AES2501_REG_CHANGAIN, - AES2501_CHANGAIN_STAGE2_4X | AES2501_CHANGAIN_STAGE1_16X }, - { AES2501_REG_ADREFHI, 0x44 }, - { AES2501_REG_ADREFLO, 0x34 }, - { AES2501_REG_STRTCOL, 0x16 }, - { AES2501_REG_ENDCOL, 0x16 }, - { AES2501_REG_DATFMT, AES2501_DATFMT_BIN_IMG | 0x08 }, - { AES2501_REG_TREG1, 0x70 }, - { 0xa2, 0x02 }, - { 0xa7, 0x00 }, - { AES2501_REG_TREGC, AES2501_TREGC_ENABLE }, - { AES2501_REG_TREGD, 0x1a }, - { AES2501_REG_CTRL1, AES2501_CTRL1_REG_UPDATE }, - { AES2501_REG_CTRL2, AES2501_CTRL2_SET_ONE_SHOT }, - { AES2501_REG_LPONT, AES2501_LPONT_MIN_VALUE }, + { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, + { 0, 0 }, + { 0xb0, 0x27 }, /* Reserved? */ + { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, + { AES2501_REG_EXCITCTRL, 0x40 }, + { 0xff, 0x00 }, /* Reserved? */ + { 0xff, 0x00 }, /* Reserved? */ + { 0xff, 0x00 }, /* Reserved? */ + { 0xff, 0x00 }, /* Reserved? */ + { 0xff, 0x00 }, /* Reserved? */ + { 0xff, 0x00 }, /* Reserved? */ + { 0xff, 0x00 }, /* Reserved? */ + { 0xff, 0x00 }, /* Reserved? */ + { 0xff, 0x00 }, /* Reserved? */ + { 0xff, 0x00 }, /* Reserved? */ + { 0xff, 0x00 }, /* Reserved? */ + { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, + { AES2501_REG_EXCITCTRL, 0x40 }, + { AES2501_REG_DETCTRL, + AES2501_DETCTRL_DRATE_CONTINUOUS | AES2501_DETCTRL_SDELAY_31_MS }, + { AES2501_REG_COLSCAN, AES2501_COLSCAN_SRATE_128_US }, + { AES2501_REG_MEASDRV, + AES2501_MEASDRV_MDRIVE_0_325 | AES2501_MEASDRV_MEASURE_SQUARE }, + { AES2501_REG_MEASFREQ, AES2501_MEASFREQ_2M }, + { AES2501_REG_DEMODPHASE1, DEMODPHASE_NONE }, + { AES2501_REG_DEMODPHASE2, DEMODPHASE_NONE }, + { AES2501_REG_CHANGAIN, + AES2501_CHANGAIN_STAGE2_4X | AES2501_CHANGAIN_STAGE1_16X }, + { AES2501_REG_ADREFHI, 0x44 }, + { AES2501_REG_ADREFLO, 0x34 }, + { AES2501_REG_STRTCOL, 0x16 }, + { AES2501_REG_ENDCOL, 0x16 }, + { AES2501_REG_DATFMT, AES2501_DATFMT_BIN_IMG | 0x08 }, + { AES2501_REG_TREG1, 0x70 }, + { 0xa2, 0x02 }, + { 0xa7, 0x00 }, + { AES2501_REG_TREGC, AES2501_TREGC_ENABLE }, + { AES2501_REG_TREGD, 0x1a }, + { AES2501_REG_CTRL1, AES2501_CTRL1_REG_UPDATE }, + { AES2501_REG_CTRL2, AES2501_CTRL2_SET_ONE_SHOT }, + { AES2501_REG_LPONT, AES2501_LPONT_MIN_VALUE }, }; static const struct aes_regwrite init_2[] = { - { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, - { AES2501_REG_EXCITCTRL, 0x40 }, - { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, - { AES2501_REG_AUTOCALOFFSET, 0x41 }, - { AES2501_REG_EXCITCTRL, 0x42 }, - { AES2501_REG_DETCTRL, 0x53 }, - { AES2501_REG_CTRL1, AES2501_CTRL1_REG_UPDATE }, + { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, + { AES2501_REG_EXCITCTRL, 0x40 }, + { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, + { AES2501_REG_AUTOCALOFFSET, 0x41 }, + { AES2501_REG_EXCITCTRL, 0x42 }, + { AES2501_REG_DETCTRL, 0x53 }, + { AES2501_REG_CTRL1, AES2501_CTRL1_REG_UPDATE }, }; static const struct aes_regwrite init_3[] = { - { 0xff, 0x00 }, - { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, - { AES2501_REG_AUTOCALOFFSET, 0x41 }, - { AES2501_REG_EXCITCTRL, 0x42 }, - { AES2501_REG_DETCTRL, 0x53 }, - { AES2501_REG_CTRL1, AES2501_CTRL1_REG_UPDATE }, + { 0xff, 0x00 }, + { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, + { AES2501_REG_AUTOCALOFFSET, 0x41 }, + { AES2501_REG_EXCITCTRL, 0x42 }, + { AES2501_REG_DETCTRL, 0x53 }, + { AES2501_REG_CTRL1, AES2501_CTRL1_REG_UPDATE }, }; static const struct aes_regwrite init_4[] = { - { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, - { AES2501_REG_EXCITCTRL, 0x40 }, - { 0xb0, 0x27 }, - { AES2501_REG_ENDROW, 0x0a }, - { AES2501_REG_CTRL1, AES2501_CTRL1_REG_UPDATE }, - { AES2501_REG_DETCTRL, 0x45 }, - { AES2501_REG_AUTOCALOFFSET, 0x41 }, + { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, + { AES2501_REG_EXCITCTRL, 0x40 }, + { 0xb0, 0x27 }, + { AES2501_REG_ENDROW, 0x0a }, + { AES2501_REG_CTRL1, AES2501_CTRL1_REG_UPDATE }, + { AES2501_REG_DETCTRL, 0x45 }, + { AES2501_REG_AUTOCALOFFSET, 0x41 }, }; static const struct aes_regwrite init_5[] = { - { 0xb0, 0x27 }, - { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, - { AES2501_REG_EXCITCTRL, 0x40 }, - { 0xff, 0x00 }, - { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, - { AES2501_REG_EXCITCTRL, 0x40 }, - { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, - { AES2501_REG_EXCITCTRL, 0x40 }, - { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, - { AES2501_REG_EXCITCTRL, 0x40 }, - { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, - { AES2501_REG_EXCITCTRL, 0x40 }, - { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, - { AES2501_REG_EXCITCTRL, 0x40 }, - { AES2501_REG_CTRL1, AES2501_CTRL1_SCAN_RESET }, - { AES2501_REG_CTRL1, AES2501_CTRL1_SCAN_RESET }, + { 0xb0, 0x27 }, + { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, + { AES2501_REG_EXCITCTRL, 0x40 }, + { 0xff, 0x00 }, + { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, + { AES2501_REG_EXCITCTRL, 0x40 }, + { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, + { AES2501_REG_EXCITCTRL, 0x40 }, + { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, + { AES2501_REG_EXCITCTRL, 0x40 }, + { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, + { AES2501_REG_EXCITCTRL, 0x40 }, + { AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET }, + { AES2501_REG_EXCITCTRL, 0x40 }, + { AES2501_REG_CTRL1, AES2501_CTRL1_SCAN_RESET }, + { AES2501_REG_CTRL1, AES2501_CTRL1_SCAN_RESET }, }; enum activate_states { - WRITE_INIT_1, - READ_DATA_1, - WRITE_INIT_2, - READ_REGS, - WRITE_INIT_3, - WRITE_INIT_4, - WRITE_INIT_5, - ACTIVATE_NUM_STATES, + WRITE_INIT_1, + READ_DATA_1, + WRITE_INIT_2, + READ_REGS, + WRITE_INIT_3, + WRITE_INIT_4, + WRITE_INIT_5, + ACTIVATE_NUM_STATES, }; -void activate_read_regs_cb(struct fp_img_dev *dev, int status, - unsigned char *regs, void *user_data) +void +activate_read_regs_cb (FpImageDevice *dev, GError *error, + unsigned char *regs, void *user_data) { - fpi_ssm *ssm = user_data; - struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiSsm *ssm = user_data; + FpiDeviceAes2501 *self = FPI_DEVICE_AES2501 (dev); - if (status != 0) { - fpi_ssm_mark_failed(ssm, status); - } else { - fp_dbg("reg 0xaf = %x", regs[0x5f]); - if (regs[0x5f] != 0x6b || ++aesdev->read_regs_retry_count == 13) - fpi_ssm_jump_to_state(ssm, WRITE_INIT_4); - else - fpi_ssm_next_state(ssm); - } + if (error) + { + fpi_ssm_mark_failed (ssm, error); + } + else + { + fp_dbg ("reg 0xaf = %x", regs[0x5f]); + if (regs[0x5f] != 0x6b || ++self->read_regs_retry_count == 13) + fpi_ssm_jump_to_state (ssm, WRITE_INIT_4); + else + fpi_ssm_next_state (ssm); + } } -static void activate_init3_cb(struct fp_img_dev *dev, int result, - void *user_data) +static void +activate_init3_cb (FpImageDevice *dev, GError *error, + void *user_data) { - fpi_ssm *ssm = user_data; - if (result == 0) - fpi_ssm_jump_to_state(ssm, READ_REGS); - else - fpi_ssm_mark_failed(ssm, result); + FpiSsm *ssm = user_data; + + if (!error) + fpi_ssm_jump_to_state (ssm, READ_REGS); + else + fpi_ssm_mark_failed (ssm, error); } -static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +activate_run_state (FpiSsm *ssm, FpDevice *_dev) { - struct fp_img_dev *dev = user_data; + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); - /* This state machine isn't as linear as it may appear. After doing init1 - * and init2 register configuration writes, we have to poll a register - * waiting for a specific value. READ_REGS checks the register value, and - * if we're ready to move on, we jump to init4. Otherwise, we write init3 - * and then jump back to READ_REGS. In a synchronous model: + /* This state machine isn't as linear as it may appear. After doing init1 + * and init2 register configuration writes, we have to poll a register + * waiting for a specific value. READ_REGS checks the register value, and + * if we're ready to move on, we jump to init4. Otherwise, we write init3 + * and then jump back to READ_REGS. In a synchronous model: - [...] - aes_write_regv(init_2); - read_regs(into buffer); - i = 0; - while (buffer[0x5f] == 0x6b) { - aes_write_regv(init_3); - read_regs(into buffer); - if (++i == 13) - break; - } - aes_write_regv(init_4); - */ + [...] + aes_write_regv(init_2); + read_regs(into buffer); + i = 0; + while (buffer[0x5f] == 0x6b) { + aes_write_regv(init_3); + read_regs(into buffer); + if (++i == 13) + break; + } + aes_write_regv(init_4); + */ - switch (fpi_ssm_get_cur_state(ssm)) { - case WRITE_INIT_1: - aes_write_regv(dev, init_1, G_N_ELEMENTS(init_1), - generic_write_regv_cb, ssm); - break; - case READ_DATA_1: - fp_dbg("read data 1"); - generic_read_ignore_data(ssm, _dev, FINGER_DETECTION_LEN); - break; - case WRITE_INIT_2: - aes_write_regv(dev, init_2, G_N_ELEMENTS(init_2), - generic_write_regv_cb, ssm); - break; - case READ_REGS: - read_regs(dev, activate_read_regs_cb, ssm); - break; - case WRITE_INIT_3: - aes_write_regv(dev, init_3, G_N_ELEMENTS(init_3), - activate_init3_cb, ssm); - break; - case WRITE_INIT_4: - aes_write_regv(dev, init_4, G_N_ELEMENTS(init_4), - generic_write_regv_cb, ssm); - break; - case WRITE_INIT_5: - aes_write_regv(dev, init_5, G_N_ELEMENTS(init_5), - generic_write_regv_cb, ssm); - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case WRITE_INIT_1: + aes_write_regv (dev, init_1, G_N_ELEMENTS (init_1), + generic_write_regv_cb, ssm); + break; + + case READ_DATA_1: + fp_dbg ("read data 1"); + generic_read_ignore_data (ssm, _dev, FINGER_DETECTION_LEN); + break; + + case WRITE_INIT_2: + aes_write_regv (dev, init_2, G_N_ELEMENTS (init_2), + generic_write_regv_cb, ssm); + break; + + case READ_REGS: + read_regs (dev, activate_read_regs_cb, ssm); + break; + + case WRITE_INIT_3: + aes_write_regv (dev, init_3, G_N_ELEMENTS (init_3), + activate_init3_cb, ssm); + break; + + case WRITE_INIT_4: + aes_write_regv (dev, init_4, G_N_ELEMENTS (init_4), + generic_write_regv_cb, ssm); + break; + + case WRITE_INIT_5: + aes_write_regv (dev, init_5, G_N_ELEMENTS (init_5), + generic_write_regv_cb, ssm); + break; + } } -static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +activate_sm_complete (FpiSsm *ssm, FpDevice *dev, GError *error) { - struct fp_img_dev *dev = user_data; - fp_dbg("status %d", fpi_ssm_get_error(ssm)); - fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm)); + fpi_image_device_activate_complete (FP_IMAGE_DEVICE (dev), error); - if (!fpi_ssm_get_error(ssm)) - start_finger_detection(dev); - fpi_ssm_free(ssm); + if (!error) + start_finger_detection (FP_IMAGE_DEVICE (dev)); + fpi_ssm_free (ssm); } -static int dev_activate(struct fp_img_dev *dev) +static void +dev_activate (FpImageDevice *dev) { - struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, - ACTIVATE_NUM_STATES, dev); - aesdev->read_regs_retry_count = 0; - fpi_ssm_start(ssm, activate_sm_complete); - return 0; + FpiDeviceAes2501 *self = FPI_DEVICE_AES2501 (dev); + FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), activate_run_state, + ACTIVATE_NUM_STATES); + + self->read_regs_retry_count = 0; + fpi_ssm_start (ssm, activate_sm_complete); } -static void dev_deactivate(struct fp_img_dev *dev) +static void +dev_deactivate (FpImageDevice *dev) { - struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - /* FIXME: audit cancellation points, probably need more, specifically - * in error handling paths? */ - aesdev->deactivating = TRUE; + FpiDeviceAes2501 *self = FPI_DEVICE_AES2501 (dev); + + /* FIXME: audit cancellation points, probably need more, specifically + * in error handling paths? */ + self->deactivating = TRUE; } -static void complete_deactivation(struct fp_img_dev *dev) +static void +complete_deactivation (FpImageDevice *dev) { - struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - G_DEBUG_HERE(); + FpiDeviceAes2501 *self = FPI_DEVICE_AES2501 (dev); - /* FIXME: if we're in the middle of a scan, we should cancel the scan. - * maybe we can do this with a master reset, unconditionally? */ + G_DEBUG_HERE (); - aesdev->deactivating = FALSE; - g_slist_free(aesdev->strips); - aesdev->strips = NULL; - aesdev->strips_len = 0; - fpi_imgdev_deactivate_complete(dev); + /* FIXME: if we're in the middle of a scan, we should cancel the scan. + * maybe we can do this with a master reset, unconditionally? */ + + self->deactivating = FALSE; + g_slist_free (self->strips); + self->strips = NULL; + self->strips_len = 0; + fpi_image_device_deactivate_complete (dev, NULL); } -static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) +static void +dev_init (FpImageDevice *dev) { - /* FIXME check endpoints */ - int r; - struct aes2501_dev *aesdev; + GError *error = NULL; - r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - if (r < 0) { - fp_err("could not claim interface 0: %s", libusb_error_name(r)); - return r; - } + /* FIXME check endpoints */ - aesdev = g_malloc0(sizeof(struct aes2501_dev)); - fp_dev_set_instance_data(FP_DEV(dev), aesdev); - fpi_imgdev_open_complete(dev, 0); - return 0; + g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error); + fpi_image_device_open_complete (dev, error); } -static void dev_deinit(struct fp_img_dev *dev) +static void +dev_deinit (FpImageDevice *dev) { - struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - g_free(aesdev); - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - fpi_imgdev_close_complete(dev); + GError *error = NULL; + + g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), + 0, 0, &error); + fpi_image_device_close_complete (dev, error); } -static const struct usb_id id_table[] = { - { .vendor = 0x08ff, .product = 0x2500 }, /* AES2500 */ - { .vendor = 0x08ff, .product = 0x2580 }, /* AES2501 */ - { 0, 0, 0, }, +static const FpIdEntry id_table[] = { + { .vid = 0x08ff, .pid = 0x2500, },/* AES2500 */ + { .vid = 0x08ff, .pid = 0x2580, },/* AES2501 */ + { .vid = 0, .pid = 0, .driver_data = 0 }, }; -struct fp_img_driver aes2501_driver = { - .driver = { - .id = AES2501_ID, - .name = FP_COMPONENT, - .full_name = "AuthenTec AES2501", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_SWIPE, - }, - .flags = 0, - .img_height = -1, - .img_width = IMAGE_WIDTH, +static void +fpi_device_aes2501_init (FpiDeviceAes2501 *self) +{ +} +static void +fpi_device_aes2501_class_init (FpiDeviceAes2501Class *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); - .open = dev_init, - .close = dev_deinit, - .activate = dev_activate, - .deactivate = dev_deactivate, -}; + dev_class->id = "aes2501"; + dev_class->full_name = "AuthenTec AES2501"; + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->id_table = id_table; + dev_class->scan_type = FP_SCAN_TYPE_SWIPE; + img_class->img_open = dev_init; + img_class->img_close = dev_deinit; + img_class->activate = dev_activate; + img_class->deactivate = dev_deactivate; + + img_class->img_width = IMAGE_WIDTH; + img_class->img_height = -1; +} diff --git a/libfprint/drivers/aes2501.h b/libfprint/drivers/aes2501.h index 19adcc90..dc802ca8 100644 --- a/libfprint/drivers/aes2501.h +++ b/libfprint/drivers/aes2501.h @@ -23,149 +23,149 @@ #define __AES2501_H enum aes2501_regs { - AES2501_REG_CTRL1 = 0x80, - AES2501_REG_CTRL2 = 0x81, - AES2501_REG_EXCITCTRL = 0x82, /* excitation control */ - AES2501_REG_DETCTRL = 0x83, /* detect control */ - AES2501_REG_COLSCAN = 0x88, /* column scan rate register */ - AES2501_REG_MEASDRV = 0x89, /* measure drive */ - AES2501_REG_MEASFREQ = 0x8a, /* measure frequency */ - AES2501_REG_DEMODPHASE1 = 0x8d, - AES2501_REG_DEMODPHASE2 = 0x8c, - AES2501_REG_CHANGAIN = 0x8e, /* channel gain */ - AES2501_REG_ADREFHI = 0x91, /* A/D reference high */ - AES2501_REG_ADREFLO = 0x92, /* A/D reference low */ - AES2501_REG_STRTROW = 0x93, /* start row */ - AES2501_REG_ENDROW = 0x94, /* end row */ - AES2501_REG_STRTCOL = 0x95, /* start column */ - AES2501_REG_ENDCOL = 0x96, /* end column */ - AES2501_REG_DATFMT = 0x97, /* data format */ - AES2501_REG_IMAGCTRL = 0x98, /* image data */ - AES2501_REG_STAT = 0x9a, - AES2501_REG_CHWORD1 = 0x9b, /* challenge word 1 */ - AES2501_REG_CHWORD2 = 0x9c, - AES2501_REG_CHWORD3 = 0x9d, - AES2501_REG_CHWORD4 = 0x9e, - AES2501_REG_CHWORD5 = 0x9f, - AES2501_REG_TREG1 = 0xa1, /* test register 1 */ - AES2501_REG_AUTOCALOFFSET = 0xa8, - AES2501_REG_TREGC = 0xac, - AES2501_REG_TREGD = 0xad, - AES2501_REG_LPONT = 0xb4, /* low power oscillator on time */ + AES2501_REG_CTRL1 = 0x80, + AES2501_REG_CTRL2 = 0x81, + AES2501_REG_EXCITCTRL = 0x82, /* excitation control */ + AES2501_REG_DETCTRL = 0x83, /* detect control */ + AES2501_REG_COLSCAN = 0x88, /* column scan rate register */ + AES2501_REG_MEASDRV = 0x89, /* measure drive */ + AES2501_REG_MEASFREQ = 0x8a, /* measure frequency */ + AES2501_REG_DEMODPHASE1 = 0x8d, + AES2501_REG_DEMODPHASE2 = 0x8c, + AES2501_REG_CHANGAIN = 0x8e, /* channel gain */ + AES2501_REG_ADREFHI = 0x91, /* A/D reference high */ + AES2501_REG_ADREFLO = 0x92, /* A/D reference low */ + AES2501_REG_STRTROW = 0x93, /* start row */ + AES2501_REG_ENDROW = 0x94, /* end row */ + AES2501_REG_STRTCOL = 0x95, /* start column */ + AES2501_REG_ENDCOL = 0x96, /* end column */ + AES2501_REG_DATFMT = 0x97, /* data format */ + AES2501_REG_IMAGCTRL = 0x98, /* image data */ + AES2501_REG_STAT = 0x9a, + AES2501_REG_CHWORD1 = 0x9b, /* challenge word 1 */ + AES2501_REG_CHWORD2 = 0x9c, + AES2501_REG_CHWORD3 = 0x9d, + AES2501_REG_CHWORD4 = 0x9e, + AES2501_REG_CHWORD5 = 0x9f, + AES2501_REG_TREG1 = 0xa1, /* test register 1 */ + AES2501_REG_AUTOCALOFFSET = 0xa8, + AES2501_REG_TREGC = 0xac, + AES2501_REG_TREGD = 0xad, + AES2501_REG_LPONT = 0xb4, /* low power oscillator on time */ }; -#define FIRST_AES2501_REG AES2501_REG_CTRL1 -#define LAST_AES2501_REG AES2501_REG_CHWORD5 +#define FIRST_AES2501_REG AES2501_REG_CTRL1 +#define LAST_AES2501_REG AES2501_REG_CHWORD5 -#define AES2501_CTRL1_MASTER_RESET (1<<0) -#define AES2501_CTRL1_SCAN_RESET (1<<1) /* stop + restart scan sequencer */ +#define AES2501_CTRL1_MASTER_RESET (1 << 0) +#define AES2501_CTRL1_SCAN_RESET (1 << 1) /* stop + restart scan sequencer */ /* 1 = continuously updated, 0 = updated prior to starting a scan */ -#define AES2501_CTRL1_REG_UPDATE (1<<2) +#define AES2501_CTRL1_REG_UPDATE (1 << 2) /* 1 = continuous scans, 0 = single scans */ -#define AES2501_CTRL2_CONTINUOUS 0x01 -#define AES2501_CTRL2_READ_REGS 0x02 /* dump registers */ -#define AES2501_CTRL2_SET_ONE_SHOT 0x04 -#define AES2501_CTRL2_CLR_ONE_SHOT 0x08 -#define AES2501_CTRL2_READ_ID 0x10 +#define AES2501_CTRL2_CONTINUOUS 0x01 +#define AES2501_CTRL2_READ_REGS 0x02 /* dump registers */ +#define AES2501_CTRL2_SET_ONE_SHOT 0x04 +#define AES2501_CTRL2_CLR_ONE_SHOT 0x08 +#define AES2501_CTRL2_READ_ID 0x10 enum aes2501_detection_rate { - /* rate of detection cycles: */ - AES2501_DETCTRL_DRATE_CONTINUOUS = 0x00, /* continuously */ - AES2501_DETCTRL_DRATE_16_MS = 0x01, /* every 16.62ms */ - AES2501_DETCTRL_DRATE_31_MS = 0x02, /* every 31.24ms */ - AES2501_DETCTRL_DRATE_62_MS = 0x03, /* every 62.50ms */ - AES2501_DETCTRL_DRATE_125_MS = 0x04, /* every 125.0ms */ - AES2501_DETCTRL_DRATE_250_MS = 0x05, /* every 250.0ms */ - AES2501_DETCTRL_DRATE_500_MS = 0x06, /* every 500.0ms */ - AES2501_DETCTRL_DRATE_1_S = 0x07, /* every 1s */ + /* rate of detection cycles: */ + AES2501_DETCTRL_DRATE_CONTINUOUS = 0x00, /* continuously */ + AES2501_DETCTRL_DRATE_16_MS = 0x01, /* every 16.62ms */ + AES2501_DETCTRL_DRATE_31_MS = 0x02, /* every 31.24ms */ + AES2501_DETCTRL_DRATE_62_MS = 0x03, /* every 62.50ms */ + AES2501_DETCTRL_DRATE_125_MS = 0x04, /* every 125.0ms */ + AES2501_DETCTRL_DRATE_250_MS = 0x05, /* every 250.0ms */ + AES2501_DETCTRL_DRATE_500_MS = 0x06, /* every 500.0ms */ + AES2501_DETCTRL_DRATE_1_S = 0x07, /* every 1s */ }; enum aes2501_settling_delay { - AES2501_DETCTRL_SDELAY_31_MS = 0x00, /* 31.25ms */ - AES2501_DETCTRL_SSDELAY_62_MS = 0x10, /* 62.5ms */ - AES2501_DETCTRL_SSDELAY_125_MS = 0x20, /* 125ms */ - AES2501_DETCTRL_SSDELAY_250_MS = 0x30 /* 250ms */ + AES2501_DETCTRL_SDELAY_31_MS = 0x00, /* 31.25ms */ + AES2501_DETCTRL_SSDELAY_62_MS = 0x10, /* 62.5ms */ + AES2501_DETCTRL_SSDELAY_125_MS = 0x20, /* 125ms */ + AES2501_DETCTRL_SSDELAY_250_MS = 0x30 /* 250ms */ }; enum aes2501_col_scan_rate { - AES2501_COLSCAN_SRATE_32_US = 0x00, /* 32us */ - AES2501_COLSCAN_SRATE_64_US = 0x01, /* 64us */ - AES2501_COLSCAN_SRATE_128_US = 0x02, /* 128us */ - AES2501_COLSCAN_SRATE_256_US = 0x03, /* 256us */ - AES2501_COLSCAN_SRATE_512_US = 0x04, /* 512us */ - AES2501_COLSCAN_SRATE_1024_US = 0x05, /* 1024us */ - AES2501_COLSCAN_SRATE_2048_US = 0x06, /* 2048us */ + AES2501_COLSCAN_SRATE_32_US = 0x00, /* 32us */ + AES2501_COLSCAN_SRATE_64_US = 0x01, /* 64us */ + AES2501_COLSCAN_SRATE_128_US = 0x02, /* 128us */ + AES2501_COLSCAN_SRATE_256_US = 0x03, /* 256us */ + AES2501_COLSCAN_SRATE_512_US = 0x04, /* 512us */ + AES2501_COLSCAN_SRATE_1024_US = 0x05, /* 1024us */ + AES2501_COLSCAN_SRATE_2048_US = 0x06, /* 2048us */ }; enum aes2501_mesure_drive { - AES2501_MEASDRV_MDRIVE_0_325 = 0x00, /* 0.325 Vpp */ - AES2501_MEASDRV_MDRIVE_0_65 = 0x01, /* 0.65 Vpp */ - AES2501_MEASDRV_MDRIVE_1_3 = 0x02, /* 1.3 Vpp */ - AES2501_MEASDRV_MDRIVE_2_6 = 0x03 /* 2.6 Vpp */ + AES2501_MEASDRV_MDRIVE_0_325 = 0x00, /* 0.325 Vpp */ + AES2501_MEASDRV_MDRIVE_0_65 = 0x01, /* 0.65 Vpp */ + AES2501_MEASDRV_MDRIVE_1_3 = 0x02, /* 1.3 Vpp */ + AES2501_MEASDRV_MDRIVE_2_6 = 0x03 /* 2.6 Vpp */ }; /* Select (1=square | 0=sine) wave drive during measure */ -#define AES2501_MEASDRV_SQUARE 0x20 +#define AES2501_MEASDRV_SQUARE 0x20 /* 0 = use measure drive setting, 1 = when sine wave is selected */ -#define AES2501_MEASDRV_MEASURE_SQUARE 0x10 +#define AES2501_MEASDRV_MEASURE_SQUARE 0x10 enum aes2501_measure_freq { - AES2501_MEASFREQ_125K = 0x01, /* 125 kHz */ - AES2501_MEASFREQ_250K = 0x02, /* 250 kHz */ - AES2501_MEASFREQ_500K = 0x03, /* 500 kHz */ - AES2501_MEASFREQ_1M = 0x04, /* 1 MHz */ - AES2501_MEASFREQ_2M = 0x05 /* 2 MHz */ + AES2501_MEASFREQ_125K = 0x01, /* 125 kHz */ + AES2501_MEASFREQ_250K = 0x02, /* 250 kHz */ + AES2501_MEASFREQ_500K = 0x03, /* 500 kHz */ + AES2501_MEASFREQ_1M = 0x04, /* 1 MHz */ + AES2501_MEASFREQ_2M = 0x05 /* 2 MHz */ }; -#define DEMODPHASE_NONE 0x00 -#define DEMODPHASE_180_00 0x40 /* 180 degrees */ -#define DEMODPHASE_2_81 0x01 /* 2.8125 degrees */ +#define DEMODPHASE_NONE 0x00 +#define DEMODPHASE_180_00 0x40 /* 180 degrees */ +#define DEMODPHASE_2_81 0x01 /* 2.8125 degrees */ #define AES2501_REG_DEMODPHASE1 0x8d -#define DEMODPHASE_1_40 0x40 /* 1.40625 degrees */ -#define DEMODPHASE_0_02 0x01 /* 0.02197256 degrees */ +#define DEMODPHASE_1_40 0x40 /* 1.40625 degrees */ +#define DEMODPHASE_0_02 0x01 /* 0.02197256 degrees */ enum aes2501_sensor_gain1 { - AES2501_CHANGAIN_STAGE1_2X = 0x00, /* 2x */ - AES2501_CHANGAIN_STAGE1_4X = 0x01, /* 4x */ - AES2501_CHANGAIN_STAGE1_8X = 0x02, /* 8x */ - AES2501_CHANGAIN_STAGE1_16X = 0x03 /* 16x */ + AES2501_CHANGAIN_STAGE1_2X = 0x00, /* 2x */ + AES2501_CHANGAIN_STAGE1_4X = 0x01, /* 4x */ + AES2501_CHANGAIN_STAGE1_8X = 0x02, /* 8x */ + AES2501_CHANGAIN_STAGE1_16X = 0x03 /* 16x */ }; enum aes2501_sensor_gain2 { - AES2501_CHANGAIN_STAGE2_2X = 0x00, /* 2x */ - AES2501_CHANGAIN_STAGE2_4X = 0x10, /* 4x */ - AES2501_CHANGAIN_STAGE2_8X = 0x20, /* 8x */ - AES2501_CHANGAIN_STAGE2_16X = 0x30 /* 16x */ + AES2501_CHANGAIN_STAGE2_2X = 0x00, /* 2x */ + AES2501_CHANGAIN_STAGE2_4X = 0x10, /* 4x */ + AES2501_CHANGAIN_STAGE2_8X = 0x20, /* 8x */ + AES2501_CHANGAIN_STAGE2_16X = 0x30 /* 16x */ }; -#define AES2501_DATFMT_EIGHT 0x40 /* 1 = 8-bit data, 0 = 4-bit data */ -#define AES2501_DATFMT_LOW_RES 0x20 -#define AES2501_DATFMT_BIN_IMG 0x10 +#define AES2501_DATFMT_EIGHT 0x40 /* 1 = 8-bit data, 0 = 4-bit data */ +#define AES2501_DATFMT_LOW_RES 0x20 +#define AES2501_DATFMT_BIN_IMG 0x10 /* don't send image or authentication messages when imaging */ -#define AES2501_IMAGCTRL_IMG_DATA_DISABLE 0x01 +#define AES2501_IMAGCTRL_IMG_DATA_DISABLE 0x01 /* send histogram when imaging */ -#define AES2501_IMAGCTRL_HISTO_DATA_ENABLE 0x02 +#define AES2501_IMAGCTRL_HISTO_DATA_ENABLE 0x02 /* send histogram at end of each row rather than each scan */ -#define AES2501_IMAGCTRL_HISTO_EACH_ROW 0x04 +#define AES2501_IMAGCTRL_HISTO_EACH_ROW 0x04 /* send full image array rather than 64x64 center */ -#define AES2501_IMAGCTRL_HISTO_FULL_ARRAY 0x08 +#define AES2501_IMAGCTRL_HISTO_FULL_ARRAY 0x08 /* return registers before data (rather than after) */ -#define AES2501_IMAGCTRL_REG_FIRST 0x10 +#define AES2501_IMAGCTRL_REG_FIRST 0x10 /* return test registers with register dump */ -#define AES2501_IMAGCTRL_TST_REG_ENABLE 0x20 +#define AES2501_IMAGCTRL_TST_REG_ENABLE 0x20 -#define AES2501_CHWORD1_IS_FINGER 0x01 /* If set, finger is present */ +#define AES2501_CHWORD1_IS_FINGER 0x01 /* If set, finger is present */ /* Enable the reading of the register in TREGD */ -#define AES2501_TREGC_ENABLE 0x01 +#define AES2501_TREGC_ENABLE 0x01 -#define AES2501_LPONT_MIN_VALUE 0x00 /* 0 ms */ -#define AES2501_LPONT_MAX_VALUE 0x1f /* About 16 ms */ +#define AES2501_LPONT_MIN_VALUE 0x00 /* 0 ms */ +#define AES2501_LPONT_MAX_VALUE 0x1f /* About 16 ms */ #define AES2501_ADREFHI_MIN_VALUE 0x28 #define AES2501_ADREFHI_MAX_VALUE 0x58 @@ -173,4 +173,4 @@ enum aes2501_sensor_gain2 { #define AES2501_SUM_HIGH_THRESH 1000 #define AES2501_SUM_LOW_THRESH 700 -#endif /* __AES2501_H */ +#endif /* __AES2501_H */ diff --git a/libfprint/drivers/aes2550.c b/libfprint/drivers/aes2550.c index 72a86132..2abcf767 100644 --- a/libfprint/drivers/aes2550.c +++ b/libfprint/drivers/aes2550.c @@ -27,11 +27,11 @@ #include "aes2550.h" #include "aeslib.h" -static void start_capture(struct fp_img_dev *dev); -static void complete_deactivation(struct fp_img_dev *dev); +static void start_capture (FpImageDevice *dev); +static void complete_deactivation (FpImageDevice *dev); -#define EP_IN (1 | LIBUSB_ENDPOINT_IN) -#define EP_OUT (2 | LIBUSB_ENDPOINT_OUT) +#define EP_IN (1 | FPI_USB_ENDPOINT_IN) +#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT) #define BULK_TIMEOUT 4000 /* @@ -46,575 +46,580 @@ static void complete_deactivation(struct fp_img_dev *dev); * images returned from this driver vary in height. */ -#define FRAME_WIDTH 192 -#define FRAME_HEIGHT 8 -#define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT) -#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2)) +#define FRAME_WIDTH 192 +#define FRAME_HEIGHT 8 +#define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT) +#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2)) -struct aes2550_dev { - GSList *strips; - size_t strips_len; - gboolean deactivating; - int heartbeat_cnt; +struct _FpiDeviceAes2550 +{ + FpImageDevice parent; + + GSList *strips; + size_t strips_len; + gboolean deactivating; + int heartbeat_cnt; }; +G_DECLARE_FINAL_TYPE (FpiDeviceAes2550, fpi_device_aes2550, FPI, DEVICE_AES2550, + FpImageDevice); +G_DEFINE_TYPE (FpiDeviceAes2550, fpi_device_aes2550, FP_TYPE_IMAGE_DEVICE); static struct fpi_frame_asmbl_ctx assembling_ctx = { - .frame_width = FRAME_WIDTH, - .frame_height = FRAME_HEIGHT, - .image_width = IMAGE_WIDTH, - .get_pixel = aes_get_pixel, + .frame_width = FRAME_WIDTH, + .frame_height = FRAME_HEIGHT, + .image_width = IMAGE_WIDTH, + .get_pixel = aes_get_pixel, }; /****** FINGER PRESENCE DETECTION ******/ static unsigned char finger_det_reqs[] = { - 0x80, AES2550_REG80_MASTER_RESET, - 0x95, (8 << AES2550_REG95_COL_SCANNED_OFS) | (1 << AES2550_REG95_EPIX_AVG_OFS), - 0xad, 0x00, - 0xbd, (0 << AES2550_REGBD_LPO_IN_15_8_OFS), - 0xbe, (0 << AES2550_REGBE_LPO_IN_7_0_OFS), - 0xcf, AES2550_REGCF_INTERFERENCE_CHK_EN, - AES2550_CMD_HEARTBEAT, 0x00, 0x01, 0x00, /* Heart beat off */ - AES2550_CMD_RUN_FD, + 0x80, AES2550_REG80_MASTER_RESET, + 0x95, (8 << AES2550_REG95_COL_SCANNED_OFS) | (1 << AES2550_REG95_EPIX_AVG_OFS), + 0xad, 0x00, + 0xbd, (0 << AES2550_REGBD_LPO_IN_15_8_OFS), + 0xbe, (0 << AES2550_REGBE_LPO_IN_7_0_OFS), + 0xcf, AES2550_REGCF_INTERFERENCE_CHK_EN, + AES2550_CMD_HEARTBEAT, 0x00, 0x01, 0x00, /* Heart beat off */ + AES2550_CMD_RUN_FD, }; -static void start_finger_detection(struct fp_img_dev *dev); +static void start_finger_detection (FpImageDevice *dev); -static void finger_det_data_cb(struct libusb_transfer *transfer) +static void +finger_det_data_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - struct fp_img_dev *dev = transfer->user_data; - unsigned char *data = transfer->buffer; + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + unsigned char *data = transfer->buffer; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fp_dbg("data transfer status %d\n", transfer->status); - fpi_imgdev_session_error(dev, -EIO); - goto out; - } + if (error) + { + fpi_image_device_session_error (FP_IMAGE_DEVICE (device), error); + return; + } - fp_dbg("transfer completed, len: %.4x, data: %.2x %.2x", - transfer->actual_length, (int)data[0], (int)data[1]); + fp_dbg ("transfer completed, len: %.4x, data: %.2x %.2x", + (gint) transfer->actual_length, (int) data[0], (int) data[1]); - /* Check if we got 2 bytes, reg address 0x83 and its value */ - if ((transfer->actual_length >= 2) && (data[0] == 0x83) && (data[1] & AES2550_REG83_FINGER_PRESENT)) { - /* finger present, start capturing */ - fpi_imgdev_report_finger_status(dev, TRUE); - start_capture(dev); - } else { - /* no finger, poll for a new histogram */ - start_finger_detection(dev); - } -out: - g_free(data); - libusb_free_transfer(transfer); + /* Check if we got 2 bytes, reg address 0x83 and its value */ + if ((transfer->actual_length >= 2) && (data[0] == 0x83) && (data[1] & AES2550_REG83_FINGER_PRESENT)) + { + /* finger present, start capturing */ + fpi_image_device_report_finger_status (dev, TRUE); + start_capture (dev); + } + else + { + /* no finger, poll for a new histogram */ + start_finger_detection (dev); + } } -static void finger_det_reqs_cb(struct libusb_transfer *t) +static void +finger_det_reqs_cb (FpiUsbTransfer *t, FpDevice *device, + gpointer user_data, GError *error) { - struct libusb_transfer *transfer; - unsigned char *data; - int r; - struct fp_img_dev *dev = t->user_data; + FpiUsbTransfer *transfer; + FpImageDevice *dev = FP_IMAGE_DEVICE (device); - if (t->status != LIBUSB_TRANSFER_COMPLETED) { - fp_dbg("req transfer status %d\n", t->status); - fpi_imgdev_session_error(dev, -EIO); - goto exit_free_transfer; - } else if (t->length != t->actual_length) { - fp_dbg("expected %d, got %d bytes", t->length, t->actual_length); - fpi_imgdev_session_error(dev, -EPROTO); - goto exit_free_transfer; - } + if (error) + { + fpi_image_device_session_error (dev, error); + return; + } - transfer = fpi_usb_alloc(); - /* 2 bytes of result */ - data = g_malloc(AES2550_EP_IN_BUF_SIZE); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, AES2550_EP_IN_BUF_SIZE, - finger_det_data_cb, dev, BULK_TIMEOUT); - - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(data); - libusb_free_transfer(transfer); - fpi_imgdev_session_error(dev, r); - } -exit_free_transfer: - libusb_free_transfer(t); + transfer = fpi_usb_transfer_new (device); + /* 2 bytes of result */ + fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE); + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + finger_det_data_cb, NULL); + fpi_usb_transfer_unref (transfer); } -static void start_finger_detection(struct fp_img_dev *dev) +static void +start_finger_detection (FpImageDevice *dev) { - int r; - struct aes2550_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - struct libusb_transfer *transfer; - G_DEBUG_HERE(); + FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev); + FpiUsbTransfer *transfer; - if (aesdev->deactivating) { - complete_deactivation(dev); - return; - } + G_DEBUG_HERE (); - transfer = fpi_usb_alloc(); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, finger_det_reqs, - sizeof(finger_det_reqs), finger_det_reqs_cb, dev, BULK_TIMEOUT); - r = libusb_submit_transfer(transfer); - if (r < 0) { - libusb_free_transfer(transfer); - fpi_imgdev_session_error(dev, r); - } + if (self->deactivating) + { + complete_deactivation (dev); + return; + } + + transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); + transfer->short_is_error = TRUE; + fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT, finger_det_reqs, + sizeof (finger_det_reqs), NULL); + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + finger_det_reqs_cb, NULL); + fpi_usb_transfer_unref (transfer); } /****** CAPTURE ******/ static unsigned char capture_reqs[] = { - 0x80, AES2550_REG80_MASTER_RESET, - 0x80, (1 << AES2550_REG80_SENSOR_MODE_OFS) | (AES2550_REG80_HGC_ENABLE), - 0x85, AES2550_REG85_FLUSH_PER_FRAME, - 0x8f, AES2550_REG8F_AUTH_DISABLE | AES2550_REG8F_EHISTO_DISABLE, - 0xbf, AES2550_REGBF_RSR_DIR_UPDOWN_MOTION | AES2550_REGBF_RSR_LEVEL_SUPER_RSR, - 0xcf, (3 << AES2550_REGCF_INTERFERENCE_AVG_OFFS) | AES2550_REGCF_INTERFERENCE_AVG_EN, - 0xdc, (1 << AES2550_REGDC_BP_NUM_REF_SWEEP_OFS), - AES2550_CMD_HEARTBEAT, 0x00, 0x01, 0x03, /* Heart beat cmd, 3 * 16 cycles without sending image */ - AES2550_CMD_GET_ENROLL_IMG, + 0x80, AES2550_REG80_MASTER_RESET, + 0x80, (1 << AES2550_REG80_SENSOR_MODE_OFS) | (AES2550_REG80_HGC_ENABLE), + 0x85, AES2550_REG85_FLUSH_PER_FRAME, + 0x8f, AES2550_REG8F_AUTH_DISABLE | AES2550_REG8F_EHISTO_DISABLE, + 0xbf, AES2550_REGBF_RSR_DIR_UPDOWN_MOTION | AES2550_REGBF_RSR_LEVEL_SUPER_RSR, + 0xcf, (3 << AES2550_REGCF_INTERFERENCE_AVG_OFFS) | AES2550_REGCF_INTERFERENCE_AVG_EN, + 0xdc, (1 << AES2550_REGDC_BP_NUM_REF_SWEEP_OFS), + AES2550_CMD_HEARTBEAT, 0x00, 0x01, 0x03, /* Heart beat cmd, 3 * 16 cycles without sending image */ + AES2550_CMD_GET_ENROLL_IMG, }; static unsigned char capture_set_idle_reqs[] = { - 0x80, AES2550_REG80_MASTER_RESET, - AES2550_CMD_HEARTBEAT, 0x00, 0x01, 0x00, /* Heart beat off */ - AES2550_CMD_SET_IDLE_MODE, + 0x80, AES2550_REG80_MASTER_RESET, + AES2550_CMD_HEARTBEAT, 0x00, 0x01, 0x00, /* Heart beat off */ + AES2550_CMD_SET_IDLE_MODE, }; enum capture_states { - CAPTURE_WRITE_REQS, - CAPTURE_READ_DATA, - CAPTURE_SET_IDLE, - CAPTURE_NUM_STATES, + CAPTURE_WRITE_REQS, + CAPTURE_READ_DATA, + CAPTURE_SET_IDLE, + CAPTURE_NUM_STATES, }; /* Returns number of processed bytes */ -static int process_strip_data(fpi_ssm *ssm, struct fp_img_dev *dev, unsigned char *data) +static gboolean +process_strip_data (FpiSsm *ssm, FpImageDevice *dev, + unsigned char *data) { - unsigned char *stripdata; - struct aes2550_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - struct fpi_frame *stripe; - int len; + unsigned char *stripdata; + FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev); + struct fpi_frame *stripe; + int len; - if (data[0] != AES2550_EDATA_MAGIC) { - fp_dbg("Bogus magic: %.2x\n", (int)(data[0])); - return -EPROTO; - } - len = data[1] * 256 + data[2]; - if (len != (AES2550_STRIP_SIZE - 3)) { - fp_dbg("Bogus frame len: %.4x\n", len); - } - stripe = g_malloc(FRAME_WIDTH * FRAME_HEIGHT / 2 + sizeof(struct fpi_frame)); /* 4 bits per pixel */ - stripe->delta_x = (int8_t)data[6]; - stripe->delta_y = -(int8_t)data[7]; - stripdata = stripe->data; - memcpy(stripdata, data + 33, FRAME_WIDTH * FRAME_HEIGHT / 2); - aesdev->strips = g_slist_prepend(aesdev->strips, stripe); - aesdev->strips_len++; + if (data[0] != AES2550_EDATA_MAGIC) + { + fp_dbg ("Bogus magic: %.2x\n", (int) (data[0])); + return FALSE; + } + len = data[1] * 256 + data[2]; + if (len != (AES2550_STRIP_SIZE - 3)) + fp_dbg ("Bogus frame len: %.4x\n", len); + stripe = g_malloc0 (FRAME_WIDTH * FRAME_HEIGHT / 2 + sizeof (struct fpi_frame)); /* 4 bits per pixel */ + stripe->delta_x = (int8_t) data[6]; + stripe->delta_y = -(int8_t) data[7]; + stripdata = stripe->data; + memcpy (stripdata, data + 33, FRAME_WIDTH * FRAME_HEIGHT / 2); + self->strips = g_slist_prepend (self->strips, stripe); + self->strips_len++; - fp_dbg("deltas: %dx%d", stripe->delta_x, stripe->delta_y); + fp_dbg ("deltas: %dx%d", stripe->delta_x, stripe->delta_y); - return 0; + return TRUE; } -static void capture_reqs_cb(struct libusb_transfer *transfer) +static void +capture_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - - if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) && - (transfer->length == transfer->actual_length)) { - fpi_ssm_next_state(ssm); - } else { - fpi_ssm_mark_failed(ssm, -EIO); - } - libusb_free_transfer(transfer); + if (!error) + fpi_ssm_next_state (transfer->ssm); + else + fpi_ssm_mark_failed (transfer->ssm, error); } -static void capture_set_idle_reqs_cb(struct libusb_transfer *transfer) +static void +capture_set_idle_reqs_cb (FpiUsbTransfer *transfer, + FpDevice *device, gpointer user_data, + GError *error) { - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct aes2550_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev); - if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) && - (transfer->length == transfer->actual_length) && - aesdev->strips_len) { - struct fp_img *img; + if (!error && self->strips_len) + { + FpImage *img; - aesdev->strips = g_slist_reverse(aesdev->strips); - img = fpi_assemble_frames(&assembling_ctx, - aesdev->strips, aesdev->strips_len); - img->flags |= FP_IMG_PARTIAL; - g_slist_free_full(aesdev->strips, g_free); - aesdev->strips = NULL; - aesdev->strips_len = 0; - fpi_imgdev_image_captured(dev, img); - fpi_imgdev_report_finger_status(dev, FALSE); - /* marking machine complete will re-trigger finger detection loop */ - fpi_ssm_mark_completed(ssm); - } else { - fpi_ssm_mark_failed(ssm, -EIO); - } - libusb_free_transfer(transfer); + self->strips = g_slist_reverse (self->strips); + img = fpi_assemble_frames (&assembling_ctx, self->strips); + g_slist_free_full (self->strips, g_free); + self->strips = NULL; + self->strips_len = 0; + fpi_image_device_image_captured (dev, img); + fpi_image_device_report_finger_status (dev, FALSE); + /* marking machine complete will re-trigger finger detection loop */ + fpi_ssm_mark_completed (transfer->ssm); + } + else + { + if (error) + fpi_ssm_mark_failed (transfer->ssm, error); + else + fpi_ssm_mark_failed (transfer->ssm, + fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); + } } -static void capture_read_data_cb(struct libusb_transfer *transfer) +static void +capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct aes2550_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - unsigned char *data = transfer->buffer; - int r; + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev); + unsigned char *data = transfer->buffer; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fp_dbg("request is not completed, %d", transfer->status); - fpi_ssm_mark_failed(ssm, -EIO); - goto out; - } + if (error) + { + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } - fp_dbg("request completed, len: %.4x", transfer->actual_length); - if (transfer->actual_length >= 2) - fp_dbg("data: %.2x %.2x", (int)data[0], (int)data[1]); + fp_dbg ("request completed, len: %.4x", (gint) transfer->actual_length); + if (transfer->actual_length >= 2) + fp_dbg ("data: %.2x %.2x", (int) data[0], (int) data[1]); - switch (transfer->actual_length) { - case AES2550_STRIP_SIZE: - r = process_strip_data(ssm, dev, data); - if (r < 0) { - fp_dbg("Processing strip data failed: %d", r); - fpi_ssm_mark_failed(ssm, -EPROTO); - goto out; - } - aesdev->heartbeat_cnt = 0; - fpi_ssm_jump_to_state(ssm, CAPTURE_READ_DATA); - break; - case AES2550_HEARTBEAT_SIZE: - if (data[0] == AES2550_HEARTBEAT_MAGIC) { - /* No data for a long time => finger was removed or there's no movement */ - aesdev->heartbeat_cnt++; - if (aesdev->heartbeat_cnt == 3) { - /* Got 3 heartbeat message, that's enough to consider that finger was removed, - * assemble image and submit it to the library */ - fp_dbg("Got 3 heartbeats => finger removed"); - fpi_ssm_next_state(ssm); - } else { - fpi_ssm_jump_to_state(ssm, CAPTURE_READ_DATA); - } - } - break; - default: - fp_dbg("Short frame %d, skip", transfer->actual_length); - fpi_ssm_jump_to_state(ssm, CAPTURE_READ_DATA); - break; - } -out: - g_free(transfer->buffer); - libusb_free_transfer(transfer); + switch (transfer->actual_length) + { + case AES2550_STRIP_SIZE: + if (!process_strip_data (transfer->ssm, dev, data)) + { + fp_dbg ("Processing strip data failed"); + fpi_ssm_mark_failed (transfer->ssm, + fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); + return; + } + self->heartbeat_cnt = 0; + fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_READ_DATA); + break; + + case AES2550_HEARTBEAT_SIZE: + if (data[0] == AES2550_HEARTBEAT_MAGIC) + { + /* No data for a long time => finger was removed or there's no movement */ + self->heartbeat_cnt++; + if (self->heartbeat_cnt == 3) + { + /* Got 3 heartbeat message, that's enough to consider that finger was removed, + * assemble image and submit it to the library */ + fp_dbg ("Got 3 heartbeats => finger removed"); + fpi_ssm_next_state (transfer->ssm); + } + else + { + fpi_ssm_jump_to_state (transfer->ssm, + CAPTURE_READ_DATA); + } + } + break; + + default: + fp_dbg ("Short frame %d, skip", + (gint) transfer->actual_length); + fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_READ_DATA); + break; + } } -static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +capture_run_state (FpiSsm *ssm, FpDevice *dev) { - struct fp_img_dev *dev = user_data; - int r; + switch (fpi_ssm_get_cur_state (ssm)) + { + case CAPTURE_WRITE_REQS: + { + FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case CAPTURE_WRITE_REQS: - { - struct libusb_transfer *transfer = fpi_usb_alloc(); + fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT, capture_reqs, + sizeof (capture_reqs), NULL); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + capture_reqs_cb, NULL); + fpi_usb_transfer_unref (transfer); + } + break; - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, capture_reqs, - sizeof(capture_reqs), capture_reqs_cb, ssm, BULK_TIMEOUT); - r = libusb_submit_transfer(transfer); - if (r < 0) { - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, -ENOMEM); - } - } - break; - case CAPTURE_READ_DATA: - { - struct libusb_transfer *transfer = fpi_usb_alloc(); - unsigned char *data; + case CAPTURE_READ_DATA: + { + FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev); - data = g_malloc(AES2550_EP_IN_BUF_SIZE); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, AES2550_EP_IN_BUF_SIZE, - capture_read_data_cb, ssm, BULK_TIMEOUT); + fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE); + transfer->ssm = ssm; + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + capture_read_data_cb, NULL); + fpi_usb_transfer_unref (transfer); + } + break; - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(data); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } - } - break; - case CAPTURE_SET_IDLE: - { - struct libusb_transfer *transfer = fpi_usb_alloc(); + case CAPTURE_SET_IDLE: + { + FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, capture_set_idle_reqs, - sizeof(capture_set_idle_reqs), capture_set_idle_reqs_cb, ssm, BULK_TIMEOUT); - r = libusb_submit_transfer(transfer); - if (r < 0) { - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, -ENOMEM); - } - } - break; - }; + fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT, + capture_set_idle_reqs, + sizeof (capture_set_idle_reqs), + NULL); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + capture_set_idle_reqs_cb, NULL); + fpi_usb_transfer_unref (transfer); + } + break; + } + ; } -static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { - struct fp_img_dev *dev = user_data; - struct aes2550_dev *aesdev = FP_INSTANCE_DATA(_dev); + FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (_dev); + FpImageDevice *dev = FP_IMAGE_DEVICE (self); - fp_dbg("Capture completed"); - if (aesdev->deactivating) - complete_deactivation(dev); - else if (fpi_ssm_get_error(ssm)) - fpi_imgdev_session_error(dev, fpi_ssm_get_error(ssm)); - else - start_finger_detection(dev); - fpi_ssm_free(ssm); + fp_dbg ("Capture completed"); + + if (self->deactivating) + { + complete_deactivation (dev); + g_clear_pointer (&error, g_error_free); + } + else if (error) + { + fpi_image_device_session_error (dev, error); + } + else + { + start_finger_detection (dev); + } + fpi_ssm_free (ssm); } -static void start_capture(struct fp_img_dev *dev) +static void +start_capture (FpImageDevice *dev) { - struct aes2550_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_ssm *ssm; + FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev); + FpiSsm *ssm; - if (aesdev->deactivating) { - complete_deactivation(dev); - return; - } + if (self->deactivating) + { + complete_deactivation (dev); + return; + } - aesdev->heartbeat_cnt = 0; - ssm = fpi_ssm_new(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev); - G_DEBUG_HERE(); - fpi_ssm_start(ssm, capture_sm_complete); + self->heartbeat_cnt = 0; + ssm = fpi_ssm_new (FP_DEVICE (dev), capture_run_state, CAPTURE_NUM_STATES); + G_DEBUG_HERE (); + fpi_ssm_start (ssm, capture_sm_complete); } /****** INITIALIZATION/DEINITIALIZATION ******/ static unsigned char init_reqs[] = { - 0x80, AES2550_REG80_MASTER_RESET, /* Master reset */ - 0x80, (1 << AES2550_REG80_SENSOR_MODE_OFS) | (AES2550_REG80_FORCE_FINGER_PRESENT), - 0x85, AES2550_REG85_FLUSH_PER_FRAME, - 0xa8, AES2550_REGA8_DIG_BIT_EN, - 0x81, AES2550_REG81_NSHOT, + 0x80, AES2550_REG80_MASTER_RESET, /* Master reset */ + 0x80, (1 << AES2550_REG80_SENSOR_MODE_OFS) | (AES2550_REG80_FORCE_FINGER_PRESENT), + 0x85, AES2550_REG85_FLUSH_PER_FRAME, + 0xa8, AES2550_REGA8_DIG_BIT_EN, + 0x81, AES2550_REG81_NSHOT, }; static unsigned char calibrate_reqs[] = { - 0x80, AES2550_REG80_MASTER_RESET, /* Master reset */ - AES2550_CMD_CALIBRATE, - AES2550_CMD_READ_CALIBRATION_DATA, + 0x80, AES2550_REG80_MASTER_RESET, /* Master reset */ + AES2550_CMD_CALIBRATE, + AES2550_CMD_READ_CALIBRATION_DATA, }; enum activate_states { - WRITE_INIT, - READ_DATA, - CALIBRATE, - READ_CALIB_TABLE, - ACTIVATE_NUM_STATES, + WRITE_INIT, + READ_DATA, + CALIBRATE, + READ_CALIB_TABLE, + ACTIVATE_NUM_STATES, }; -static void init_reqs_cb(struct libusb_transfer *transfer) +static void +init_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - - if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) && - (transfer->length == transfer->actual_length)) { - fpi_ssm_next_state(ssm); - } else { - fpi_ssm_mark_failed(ssm, -EIO); - } - libusb_free_transfer(transfer); + if (!error) + fpi_ssm_next_state (transfer->ssm); + else + fpi_ssm_mark_failed (transfer->ssm, error); } -static void init_read_data_cb(struct libusb_transfer *transfer) +static void +init_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - - if (transfer->status == LIBUSB_TRANSFER_COMPLETED) { - fpi_ssm_next_state(ssm); - } else { - fpi_ssm_mark_failed(ssm, -EIO); - } - g_free(transfer->buffer); - libusb_free_transfer(transfer); + if (!error) + fpi_ssm_next_state (transfer->ssm); + else + fpi_ssm_mark_failed (transfer->ssm, error); } /* TODO: use calibration table, datasheet is rather terse on that * need more info for implementation */ -static void calibrate_read_data_cb(struct libusb_transfer *transfer) +static void +calibrate_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - - if (transfer->status == LIBUSB_TRANSFER_COMPLETED) { - fpi_ssm_next_state(ssm); - } else { - fpi_ssm_mark_failed(ssm, -EIO); - } - g_free(transfer->buffer); - libusb_free_transfer(transfer); + if (!error) + fpi_ssm_next_state (transfer->ssm); + else + fpi_ssm_mark_failed (transfer->ssm, error); } -static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +activate_run_state (FpiSsm *ssm, FpDevice *dev) { - struct fp_img_dev *dev = user_data; - int r; + switch (fpi_ssm_get_cur_state (ssm)) + { + case WRITE_INIT: + { + FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case WRITE_INIT: - { - struct libusb_transfer *transfer = fpi_usb_alloc(); + fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT, init_reqs, + sizeof (init_reqs), NULL); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + init_reqs_cb, NULL); + fpi_usb_transfer_unref (transfer); + } + break; - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, init_reqs, - sizeof(init_reqs), init_reqs_cb, ssm, BULK_TIMEOUT); - r = libusb_submit_transfer(transfer); - if (r < 0) { - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, -ENOMEM); - } - } - break; - case READ_DATA: - { - struct libusb_transfer *transfer = fpi_usb_alloc(); - unsigned char *data; + case READ_DATA: + { + FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev); - data = g_malloc(AES2550_EP_IN_BUF_SIZE); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, AES2550_EP_IN_BUF_SIZE, - init_read_data_cb, ssm, BULK_TIMEOUT); + fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE); + transfer->ssm = ssm; + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + init_read_data_cb, NULL); + fpi_usb_transfer_unref (transfer); + } + break; - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(data); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } - } - break; - case CALIBRATE: - { - struct libusb_transfer *transfer = fpi_usb_alloc(); + case CALIBRATE: + { + FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, calibrate_reqs, - sizeof(calibrate_reqs), init_reqs_cb, ssm, BULK_TIMEOUT); - r = libusb_submit_transfer(transfer); - if (r < 0) { - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, -ENOMEM); - } - } - break; - case READ_CALIB_TABLE: - { - struct libusb_transfer *transfer = fpi_usb_alloc(); - unsigned char *data; + fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT, + calibrate_reqs, + sizeof (calibrate_reqs), NULL); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + init_reqs_cb, NULL); + fpi_usb_transfer_unref (transfer); + } + break; - data = g_malloc(AES2550_EP_IN_BUF_SIZE); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, AES2550_EP_IN_BUF_SIZE, - calibrate_read_data_cb, ssm, BULK_TIMEOUT); + case READ_CALIB_TABLE: + { + FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev); - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(data); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } - } - break; - } + fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE); + transfer->ssm = ssm; + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + calibrate_read_data_cb, NULL); + fpi_usb_transfer_unref (transfer); + } + break; + } } -static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { - struct fp_img_dev *dev = user_data; - fp_dbg("status %d", fpi_ssm_get_error(ssm)); - fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm)); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); - if (!fpi_ssm_get_error(ssm)) - start_finger_detection(dev); - fpi_ssm_free(ssm); + fpi_image_device_activate_complete (dev, error); + + if (!error) + start_finger_detection (dev); + fpi_ssm_free (ssm); } -static int dev_activate(struct fp_img_dev *dev) +static void +dev_activate (FpImageDevice *dev) { - fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, - ACTIVATE_NUM_STATES, dev); - fpi_ssm_start(ssm, activate_sm_complete); - return 0; + FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), activate_run_state, + ACTIVATE_NUM_STATES); + + fpi_ssm_start (ssm, activate_sm_complete); } -static void dev_deactivate(struct fp_img_dev *dev) +static void +dev_deactivate (FpImageDevice *dev) { - struct aes2550_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev); - aesdev->deactivating = TRUE; + self->deactivating = TRUE; } -static void complete_deactivation(struct fp_img_dev *dev) +static void +complete_deactivation (FpImageDevice *dev) { - struct aes2550_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - G_DEBUG_HERE(); + FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev); - aesdev->deactivating = FALSE; - g_slist_free(aesdev->strips); - aesdev->strips = NULL; - aesdev->strips_len = 0; - fpi_imgdev_deactivate_complete(dev); + G_DEBUG_HERE (); + + self->deactivating = FALSE; + g_slist_free (self->strips); + self->strips = NULL; + self->strips_len = 0; + fpi_image_device_deactivate_complete (dev, NULL); } -static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) +static void +dev_init (FpImageDevice *dev) { - /* TODO check that device has endpoints we're using */ - int r; - struct aes2550_dev *aes2550_dev; + GError *error = NULL; - r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - if (r < 0) { - fp_err("could not claim interface 0: %s", libusb_error_name(r)); - return r; - } + /* TODO check that device has endpoints we're using */ - aes2550_dev = g_malloc0(sizeof(struct aes2550_dev)); - fp_dev_set_instance_data(FP_DEV(dev), aes2550_dev); - fpi_imgdev_open_complete(dev, 0); - return 0; + g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error); + + fpi_image_device_open_complete (dev, error); } -static void dev_deinit(struct fp_img_dev *dev) +static void +dev_deinit (FpImageDevice *dev) { - struct aes2550_dev *aesdev; - aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - g_free(aesdev); - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - fpi_imgdev_close_complete(dev); + GError *error = NULL; + + g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), + 0, 0, &error); + fpi_image_device_close_complete (dev, error); } -static const struct usb_id id_table[] = { - { .vendor = 0x08ff, .product = 0x2550 }, /* AES2550 */ - { .vendor = 0x08ff, .product = 0x2810 }, /* AES2810 */ - { 0, 0, 0, }, +static const FpIdEntry id_table[] = { + { .vid = 0x08ff, .pid = 0x2550, },/* AES2550 */ + { .vid = 0x08ff, .pid = 0x2810, },/* AES2810 */ + { .vid = 0, .pid = 0, .driver_data = 0 }, }; -struct fp_img_driver aes2550_driver = { - .driver = { - .id = AES2550_ID, - .name = FP_COMPONENT, - .full_name = "AuthenTec AES2550/AES2810", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_SWIPE, - }, - .flags = 0, - .img_height = -1, - .img_width = FRAME_WIDTH + FRAME_WIDTH / 2, +static void +fpi_device_aes2550_init (FpiDeviceAes2550 *self) +{ +} +static void +fpi_device_aes2550_class_init (FpiDeviceAes2550Class *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); - .open = dev_init, - .close = dev_deinit, - .activate = dev_activate, - .deactivate = dev_deactivate, -}; + dev_class->id = "aes2550"; + dev_class->full_name = "AuthenTec AES2550/AES2810"; + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->id_table = id_table; + dev_class->scan_type = FP_SCAN_TYPE_SWIPE; + + img_class->img_open = dev_init; + img_class->img_close = dev_deinit; + img_class->activate = dev_activate; + img_class->deactivate = dev_deactivate; + + img_class->img_width = FRAME_WIDTH + FRAME_WIDTH / 2; + img_class->img_height = -1; +} diff --git a/libfprint/drivers/aes2550.h b/libfprint/drivers/aes2550.h index cd1e22d3..8e4ca173 100644 --- a/libfprint/drivers/aes2550.h +++ b/libfprint/drivers/aes2550.h @@ -22,93 +22,93 @@ /* Registers bits */ -#define AES2550_REG80_MASTER_RESET (1 << 0) -#define AES2550_REG80_FORCE_FINGER_PRESENT (1 << 1) -#define AES2550_REG80_LPO_START (1 << 2) -#define AES2550_REG80_HGC_ENABLE (1 << 3) -#define AES2550_REG80_SENSOR_MODE_OFS (4) -#define AES2550_REG80_AUTO_RESTART_FD (1 << 6) -#define AES2550_REG80_EXT_REG_ENABLE (1 << 7) +#define AES2550_REG80_MASTER_RESET (1 << 0) +#define AES2550_REG80_FORCE_FINGER_PRESENT (1 << 1) +#define AES2550_REG80_LPO_START (1 << 2) +#define AES2550_REG80_HGC_ENABLE (1 << 3) +#define AES2550_REG80_SENSOR_MODE_OFS (4) +#define AES2550_REG80_AUTO_RESTART_FD (1 << 6) +#define AES2550_REG80_EXT_REG_ENABLE (1 << 7) -#define AES2550_REG81_CONT_SCAN (1 << 0) -#define AES2550_REG81_READ_REG (1 << 1) -#define AES2550_REG81_NSHOT (1 << 2) -#define AES2550_REG81_RUN_FD (1 << 3) -#define AES2550_REG81_READ_ID (1 << 4) -#define AES2550_REG81_RUN_CAL (1 << 5) -#define AES2550_REG81_RUN_TIMER (1 << 6) -#define AES2550_REG81_RUN_BIST (1 << 7) +#define AES2550_REG81_CONT_SCAN (1 << 0) +#define AES2550_REG81_READ_REG (1 << 1) +#define AES2550_REG81_NSHOT (1 << 2) +#define AES2550_REG81_RUN_FD (1 << 3) +#define AES2550_REG81_READ_ID (1 << 4) +#define AES2550_REG81_RUN_CAL (1 << 5) +#define AES2550_REG81_RUN_TIMER (1 << 6) +#define AES2550_REG81_RUN_BIST (1 << 7) -#define AES2550_REG83_FINGER_PRESENT (1 << 7) +#define AES2550_REG83_FINGER_PRESENT (1 << 7) -#define AES2550_REG85_FLUSH_PER_FRAME (1 << 7) +#define AES2550_REG85_FLUSH_PER_FRAME (1 << 7) -#define AES2550_REG8F_EDATA_DISABLE (1 << 1) -#define AES2550_REG8F_AUTH_DISABLE (1 << 2) -#define AES2550_REG8F_EHISTO_DISABLE (1 << 3) -#define AES2550_REG8F_HISTO64 (1 << 4) -#define AES2550_REG8F_SINGLE_REG_ENABLE (1 << 6) +#define AES2550_REG8F_EDATA_DISABLE (1 << 1) +#define AES2550_REG8F_AUTH_DISABLE (1 << 2) +#define AES2550_REG8F_EHISTO_DISABLE (1 << 3) +#define AES2550_REG8F_HISTO64 (1 << 4) +#define AES2550_REG8F_SINGLE_REG_ENABLE (1 << 6) -#define AES2550_REG95_COL_SCANNED_OFS (0) -#define AES2550_REG95_EPIX_AVG_OFS (4) +#define AES2550_REG95_COL_SCANNED_OFS (0) +#define AES2550_REG95_EPIX_AVG_OFS (4) -#define AES2550_REGA8_DIG_BIT_DATA_OFS (0) -#define AES2550_REGA8_DIG_BIT_EN (1 << 4) -#define AES2550_REGA8_FIXED_BIT_DATA (1 << 5) -#define AES2550_REGA8_INVERT_BIT_DATA (1 << 6) +#define AES2550_REGA8_DIG_BIT_DATA_OFS (0) +#define AES2550_REGA8_DIG_BIT_EN (1 << 4) +#define AES2550_REGA8_FIXED_BIT_DATA (1 << 5) +#define AES2550_REGA8_INVERT_BIT_DATA (1 << 6) -#define AES2550_REGAD_LPFD_AVG_OFS (0) -#define AES2550_REGAD_DETECT_FGROFF (1 << 4) -#define AES2550_REGAD_ADVRANGE_2V (1 << 6) +#define AES2550_REGAD_LPFD_AVG_OFS (0) +#define AES2550_REGAD_DETECT_FGROFF (1 << 4) +#define AES2550_REGAD_ADVRANGE_2V (1 << 6) -#define AES2550_REGB1_ATE_CONT_IMAGE (1 << 1) -#define AES2550_REGB1_ANALOG_RESET (1 << 2) -#define AES2550_REGB1_ANALOG_PD (1 << 3) -#define AES2550_REGB1_TEST_EMBD_WORD (1 << 4) -#define AES2550_REGB1_ORIG_EMBD_WORD (1 << 5) -#define AES2550_REGB1_RESET_UHSM (1 << 6) -#define AES2550_REGB1_RESET_SENSOR (1 << 7) +#define AES2550_REGB1_ATE_CONT_IMAGE (1 << 1) +#define AES2550_REGB1_ANALOG_RESET (1 << 2) +#define AES2550_REGB1_ANALOG_PD (1 << 3) +#define AES2550_REGB1_TEST_EMBD_WORD (1 << 4) +#define AES2550_REGB1_ORIG_EMBD_WORD (1 << 5) +#define AES2550_REGB1_RESET_UHSM (1 << 6) +#define AES2550_REGB1_RESET_SENSOR (1 << 7) -#define AES2550_REGBD_LPO_IN_15_8_OFS (0) -#define AES2550_REGBE_LPO_IN_7_0_OFS (0) +#define AES2550_REGBD_LPO_IN_15_8_OFS (0) +#define AES2550_REGBE_LPO_IN_7_0_OFS (0) -#define AES2550_REGBF_RSR_LEVEL_DISABLED (0 << 0) -#define AES2550_REGBF_RSR_LEVEL_LEADING_RSR (1 << 0) -#define AES2550_REGBF_RSR_LEVEL_SIMPLE_RSR (2 << 0) -#define AES2550_REGBF_RSR_LEVEL_SUPER_RSR (3 << 0) -#define AES2550_REGBF_RSR_DIR_DOWN_MOTION (0 << 2) -#define AES2550_REGBF_RSR_DIR_UP_MOTION (1 << 2) -#define AES2550_REGBF_RSR_DIR_UPDOWN_MOTION (2 << 2) -#define AES2550_REGBF_NOISE_FLOOR_MODE (1 << 4) -#define AES2550_REGBF_QUADRATURE_MODE (1 << 5) +#define AES2550_REGBF_RSR_LEVEL_DISABLED (0 << 0) +#define AES2550_REGBF_RSR_LEVEL_LEADING_RSR (1 << 0) +#define AES2550_REGBF_RSR_LEVEL_SIMPLE_RSR (2 << 0) +#define AES2550_REGBF_RSR_LEVEL_SUPER_RSR (3 << 0) +#define AES2550_REGBF_RSR_DIR_DOWN_MOTION (0 << 2) +#define AES2550_REGBF_RSR_DIR_UP_MOTION (1 << 2) +#define AES2550_REGBF_RSR_DIR_UPDOWN_MOTION (2 << 2) +#define AES2550_REGBF_NOISE_FLOOR_MODE (1 << 4) +#define AES2550_REGBF_QUADRATURE_MODE (1 << 5) -#define AES2550_REGCF_INTERFERENCE_CHK_EN (1 << 0) -#define AES2550_REGCF_INTERFERENCE_AVG_EN (1 << 1) -#define AES2550_REGCF_INTERFERENCE_AVG_OFFS (4) +#define AES2550_REGCF_INTERFERENCE_CHK_EN (1 << 0) +#define AES2550_REGCF_INTERFERENCE_AVG_EN (1 << 1) +#define AES2550_REGCF_INTERFERENCE_AVG_OFFS (4) -#define AES2550_REGDC_BP_NUM_REF_SWEEP_OFS (0) -#define AES2550_REGDC_DEBUG_CTRL2_OFS (3) +#define AES2550_REGDC_BP_NUM_REF_SWEEP_OFS (0) +#define AES2550_REGDC_DEBUG_CTRL2_OFS (3) -#define AES2550_REGDD_DEBUG_CTRL1_OFS (0) +#define AES2550_REGDD_DEBUG_CTRL1_OFS (0) /* Commands */ enum aes2550_cmds { - AES2550_CMD_SET_IDLE_MODE = 0x00, - AES2550_CMD_RUN_FD = 0x01, - AES2550_CMD_GET_ENROLL_IMG = 0x02, - AES2550_CMD_CALIBRATE = 0x06, - AES2550_CMD_READ_CALIBRATION_DATA = 0x10, - AES2550_CMD_HEARTBEAT = 0x70, + AES2550_CMD_SET_IDLE_MODE = 0x00, + AES2550_CMD_RUN_FD = 0x01, + AES2550_CMD_GET_ENROLL_IMG = 0x02, + AES2550_CMD_CALIBRATE = 0x06, + AES2550_CMD_READ_CALIBRATION_DATA = 0x10, + AES2550_CMD_HEARTBEAT = 0x70, }; /* Messages */ -#define AES2550_STRIP_SIZE (0x31e + 3) -#define AES2550_HEARTBEAT_SIZE (4 + 3) -#define AES2550_EDATA_MAGIC 0xe0 -#define AES2550_HEARTBEAT_MAGIC 0xdb +#define AES2550_STRIP_SIZE (0x31e + 3) +#define AES2550_HEARTBEAT_SIZE (4 + 3) +#define AES2550_EDATA_MAGIC 0xe0 +#define AES2550_HEARTBEAT_MAGIC 0xdb -#define AES2550_EP_IN_BUF_SIZE 8192 +#define AES2550_EP_IN_BUF_SIZE 8192 #endif diff --git a/libfprint/drivers/aes2660.c b/libfprint/drivers/aes2660.c index de380e7a..fb5aa7e1 100644 --- a/libfprint/drivers/aes2660.c +++ b/libfprint/drivers/aes2660.c @@ -25,90 +25,73 @@ #include "aes2660.h" #define FRAME_WIDTH 192 -#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2)) +#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2)) + +struct _FpiDeviceAes2660 +{ + FpiDeviceAesX660 parent; +}; +G_DECLARE_FINAL_TYPE (FpiDeviceAes2660, fpi_device_aes2660, FPI, + DEVICE_AES2660, FpiDeviceAesX660); +G_DEFINE_TYPE (FpiDeviceAes2660, fpi_device_aes2660, FPI_TYPE_DEVICE_AES_X660); static struct fpi_frame_asmbl_ctx assembling_ctx = { - .frame_width = FRAME_WIDTH, - .frame_height = AESX660_FRAME_HEIGHT, - .image_width = IMAGE_WIDTH, - .get_pixel = aes_get_pixel, + .frame_width = FRAME_WIDTH, + .frame_height = AESX660_FRAME_HEIGHT, + .image_width = IMAGE_WIDTH, + .get_pixel = aes_get_pixel, }; -static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) +static const FpIdEntry id_table[] = { + { .vid = 0x08ff, .pid = 0x2660, }, + { .vid = 0x08ff, .pid = 0x2680, }, + { .vid = 0x08ff, .pid = 0x2681, }, + { .vid = 0x08ff, .pid = 0x2682, }, + { .vid = 0x08ff, .pid = 0x2683, }, + { .vid = 0x08ff, .pid = 0x2684, }, + { .vid = 0x08ff, .pid = 0x2685, }, + { .vid = 0x08ff, .pid = 0x2686, }, + { .vid = 0x08ff, .pid = 0x2687, }, + { .vid = 0x08ff, .pid = 0x2688, }, + { .vid = 0x08ff, .pid = 0x2689, }, + { .vid = 0x08ff, .pid = 0x268a, }, + { .vid = 0x08ff, .pid = 0x268b, }, + { .vid = 0x08ff, .pid = 0x268c, }, + { .vid = 0x08ff, .pid = 0x268d, }, + { .vid = 0x08ff, .pid = 0x268e, }, + { .vid = 0x08ff, .pid = 0x268f, }, + { .vid = 0x08ff, .pid = 0x2691, }, + { .vid = 0, .pid = 0, .driver_data = 0 }, +}; + +static void +fpi_device_aes2660_init (FpiDeviceAes2660 *self) { - /* TODO check that device has endpoints we're using */ - int r; - struct aesX660_dev *aesdev; - - r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - if (r < 0) { - fp_err("could not claim interface 0: %s", libusb_error_name(r)); - return r; - } - - aesdev = g_malloc0(sizeof(struct aesX660_dev)); - fp_dev_set_instance_data(FP_DEV(dev), aesdev); - aesdev->buffer = g_malloc0(AES2660_FRAME_SIZE + AESX660_HEADER_SIZE); - /* No scaling for AES2660 */ - aesdev->init_seqs[0] = aes2660_init_1; - aesdev->init_seqs_len[0] = G_N_ELEMENTS(aes2660_init_1); - aesdev->init_seqs[1] = aes2660_init_2; - aesdev->init_seqs_len[1] = G_N_ELEMENTS(aes2660_init_2); - aesdev->start_imaging_cmd = (unsigned char *)aes2660_start_imaging_cmd; - aesdev->start_imaging_cmd_len = sizeof(aes2660_start_imaging_cmd); - aesdev->assembling_ctx = &assembling_ctx; - aesdev->extra_img_flags = FP_IMG_PARTIAL; - - fpi_imgdev_open_complete(dev, 0); - return 0; } -static void dev_deinit(struct fp_img_dev *dev) +static void +fpi_device_aes2660_class_init (FpiDeviceAes2660Class *klass) { - struct aesX660_dev *aesdev; - aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - g_free(aesdev->buffer); - g_free(aesdev); - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - fpi_imgdev_close_complete(dev); + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); + FpiDeviceAesX660Class *aes_class = FPI_DEVICE_AES_X660_CLASS (klass); + + dev_class->id = "aes2660"; + dev_class->full_name = "AuthenTec AES2660"; + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->id_table = id_table; + dev_class->scan_type = FP_SCAN_TYPE_SWIPE; + + img_class->bz3_threshold = 20; + + img_class->img_width = FRAME_WIDTH + FRAME_WIDTH / 2; + img_class->img_height = -1; + + aes_class->init_seqs[0] = aes2660_init_1; + aes_class->init_seqs_len[0] = G_N_ELEMENTS (aes2660_init_1); + aes_class->init_seqs[1] = aes2660_init_2; + aes_class->init_seqs_len[1] = G_N_ELEMENTS (aes2660_init_2); + aes_class->start_imaging_cmd = (unsigned char *) aes2660_start_imaging_cmd; + aes_class->start_imaging_cmd_len = sizeof (aes2660_start_imaging_cmd); + aes_class->assembling_ctx = &assembling_ctx; } - -static const struct usb_id id_table[] = { - { .vendor = 0x08ff, .product = 0x2660 }, - { .vendor = 0x08ff, .product = 0x2680 }, - { .vendor = 0x08ff, .product = 0x2681 }, - { .vendor = 0x08ff, .product = 0x2682 }, - { .vendor = 0x08ff, .product = 0x2683 }, - { .vendor = 0x08ff, .product = 0x2684 }, - { .vendor = 0x08ff, .product = 0x2685 }, - { .vendor = 0x08ff, .product = 0x2686 }, - { .vendor = 0x08ff, .product = 0x2687 }, - { .vendor = 0x08ff, .product = 0x2688 }, - { .vendor = 0x08ff, .product = 0x2689 }, - { .vendor = 0x08ff, .product = 0x268a }, - { .vendor = 0x08ff, .product = 0x268b }, - { .vendor = 0x08ff, .product = 0x268c }, - { .vendor = 0x08ff, .product = 0x268d }, - { .vendor = 0x08ff, .product = 0x268e }, - { .vendor = 0x08ff, .product = 0x268f }, - { .vendor = 0x08ff, .product = 0x2691 }, - { 0, 0, 0, }, -}; - -struct fp_img_driver aes2660_driver = { - .driver = { - .id = AES2660_ID, - .name = FP_COMPONENT, - .full_name = "AuthenTec AES2660", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_SWIPE, - }, - .flags = 0, - .img_height = -1, - .img_width = FRAME_WIDTH + FRAME_WIDTH / 2, - - .open = dev_init, - .close = dev_deinit, - .activate = aesX660_dev_activate, - .deactivate = aesX660_dev_deactivate, -}; diff --git a/libfprint/drivers/aes2660.h b/libfprint/drivers/aes2660.h index c85bb0a3..d59f4be2 100644 --- a/libfprint/drivers/aes2660.h +++ b/libfprint/drivers/aes2660.h @@ -29,1936 +29,1936 @@ /* INIT1 */ static const unsigned char pkt13[] = { -0x44, 0x02, 0x00, 0x04, 0x00, -0x0d, -0x23, -0x42, 0xca, 0x00, -0x00, 0x20, 0x7f, /* .#B... . */ -0x97, 0x37, 0xcf, 0xdf, 0x96, 0x26, 0xcf, 0xdf, /* .7...&.. */ -0x96, 0xff, 0x96, 0x9f, 0x22, 0x6d, 0x2e, 0x6a, /* ...."m.j */ -0xbf, 0x62, 0x23, 0x23, 0x83, 0xdd, 0x97, 0x26, /* .b##...& */ -0xaf, 0xdd, 0x97, 0x37, 0xaf, 0xa9, 0xcf, 0x70, /* ...7...p */ -0x18, 0xa9, 0xaf, 0x02, 0xef, 0x5d, 0xaf, 0xc5, /* .....].. */ -0xef, 0x2f, 0xff, 0xff, 0x96, 0xdf, 0x96, 0x69, /* ./.....i */ -0xef, 0x20, 0xff, 0xff, 0x96, 0xdf, 0x96, 0x1a, /* . ...... */ -0x27, 0x0b, 0xef, 0x06, 0xaf, 0xf1, 0x81, 0x3a, /* '......: */ -0xff, 0x3f, 0x1d, 0xc1, 0x2e, 0xa3, 0xbf, 0xc2, /* .?...... */ -0x2e, 0x00, 0xdf, 0xff, 0x2d, 0x02, 0x5a, 0xbf, /* ....-.Z. */ -0x22, 0xc1, 0x2e, 0xa3, 0xbf, 0x3c, 0x23, 0x57, /* "....<#W */ -0x23, 0x02, 0x2e, 0x30, 0x80, 0x05, 0x27, 0x12, /* #..0..'. */ -0xef, 0x99, 0xaf, 0x10, 0xef, 0x9b, 0xaf, 0x10, /* ........ */ -0xef, 0x55, 0xaf, 0x3d, 0x23, 0x30, 0xef, 0x20, /* .U.=#0. */ -0xff, 0x1a, 0x27, 0x05, 0xef, 0x27, 0xff, 0x06, /* ..'..'.. */ -0x27, 0x05, 0x27, 0x3f, 0x80, 0x2b, 0x0d, 0x05, /* '.'?.+.. */ -0x27, 0xe5, 0x31, 0x05, 0x81, 0xe5, 0x39, 0x05, /* '.1...9. */ -0x27, 0xc8, 0x46, 0x0e, 0x5b, 0xd3, 0x45, 0xfd, /* '.F.[.E. */ -0x5a, 0x0f, 0x27, 0xd3, 0x45, 0xfa, 0x5a, 0x0f, /* Z.'.E.Z. */ -0x27, 0xd3, 0x45, 0xf7, 0x5a, 0x41, 0x2e, 0xa1, /* '.E.ZA.. */ -0xdf, 0x9f, 0x28, 0x41, 0x2e, 0xa1, 0xbf, 0x02, /* ..(A.... */ -0x2e, 0x57, 0x80, 0x05, 0x27, 0x9f, 0x22, 0xbf, /* .W..'.". */ -0x22, 0x1f, 0x20, 0xfd, 0x53, 0x3f, 0x20, 0x14, /* ". .S? . */ -0x1f, 0xfa, 0x55, 0x05, 0x27, 0x10, 0xef, 0xd0, /* ..U.'... */ -0x81, 0x65, 0xaf, 0x10, 0xef, 0xd0, 0x81 /* .e..... */ + 0x44, 0x02, 0x00, 0x04, 0x00, + 0x0d, + 0x23, + 0x42, 0xca, 0x00, + 0x00, 0x20, 0x7f, /* .#B... . */ + 0x97, 0x37, 0xcf, 0xdf, 0x96, 0x26, 0xcf, 0xdf, /* .7...&.. */ + 0x96, 0xff, 0x96, 0x9f, 0x22, 0x6d, 0x2e, 0x6a, /* ...."m.j */ + 0xbf, 0x62, 0x23, 0x23, 0x83, 0xdd, 0x97, 0x26, /* .b##...& */ + 0xaf, 0xdd, 0x97, 0x37, 0xaf, 0xa9, 0xcf, 0x70, /* ...7...p */ + 0x18, 0xa9, 0xaf, 0x02, 0xef, 0x5d, 0xaf, 0xc5, /* .....].. */ + 0xef, 0x2f, 0xff, 0xff, 0x96, 0xdf, 0x96, 0x69, /* ./.....i */ + 0xef, 0x20, 0xff, 0xff, 0x96, 0xdf, 0x96, 0x1a, /* . ...... */ + 0x27, 0x0b, 0xef, 0x06, 0xaf, 0xf1, 0x81, 0x3a, /* '......: */ + 0xff, 0x3f, 0x1d, 0xc1, 0x2e, 0xa3, 0xbf, 0xc2, /* .?...... */ + 0x2e, 0x00, 0xdf, 0xff, 0x2d, 0x02, 0x5a, 0xbf, /* ....-.Z. */ + 0x22, 0xc1, 0x2e, 0xa3, 0xbf, 0x3c, 0x23, 0x57, /* "....<#W */ + 0x23, 0x02, 0x2e, 0x30, 0x80, 0x05, 0x27, 0x12, /* #..0..'. */ + 0xef, 0x99, 0xaf, 0x10, 0xef, 0x9b, 0xaf, 0x10, /* ........ */ + 0xef, 0x55, 0xaf, 0x3d, 0x23, 0x30, 0xef, 0x20, /* .U.=#0. */ + 0xff, 0x1a, 0x27, 0x05, 0xef, 0x27, 0xff, 0x06, /* ..'..'.. */ + 0x27, 0x05, 0x27, 0x3f, 0x80, 0x2b, 0x0d, 0x05, /* '.'?.+.. */ + 0x27, 0xe5, 0x31, 0x05, 0x81, 0xe5, 0x39, 0x05, /* '.1...9. */ + 0x27, 0xc8, 0x46, 0x0e, 0x5b, 0xd3, 0x45, 0xfd, /* '.F.[.E. */ + 0x5a, 0x0f, 0x27, 0xd3, 0x45, 0xfa, 0x5a, 0x0f, /* Z.'.E.Z. */ + 0x27, 0xd3, 0x45, 0xf7, 0x5a, 0x41, 0x2e, 0xa1, /* '.E.ZA.. */ + 0xdf, 0x9f, 0x28, 0x41, 0x2e, 0xa1, 0xbf, 0x02, /* ..(A.... */ + 0x2e, 0x57, 0x80, 0x05, 0x27, 0x9f, 0x22, 0xbf, /* .W..'.". */ + 0x22, 0x1f, 0x20, 0xfd, 0x53, 0x3f, 0x20, 0x14, /* ". .S? . */ + 0x1f, 0xfa, 0x55, 0x05, 0x27, 0x10, 0xef, 0xd0, /* ..U.'... */ + 0x81, 0x65, 0xaf, 0x10, 0xef, 0xd0, 0x81 /* .e..... */ }; static const unsigned char pkt15[] = { -0x42, 0x48, 0x00, -0x64, 0x20, 0x9c, 0xaf, 0x10, /* BH.d ... */ -0xef, 0xd0, 0x81, 0x9a, 0xaf, 0x05, 0x27, 0x11, /* ......'. */ -0x00, 0x51, 0x87, 0x91, 0x81, 0xd1, 0x6c, 0xd2, /* .Q....l. */ -0x75, 0xe2, 0x80, 0xf2, 0x80, 0xf0, 0x57, 0xf4, /* u.....W. */ -0x7b, 0xf8, 0x7e, 0xfc, 0x8b, 0x10, 0xcf, 0x7c, /* {.~....| */ -0xff, 0x3f, 0x00, 0x20, 0xff, 0x00, 0x13, 0x1a, /* .?. .... */ -0x27, 0x07, 0x27, 0x05, 0x27, 0x01, 0x00, 0x11, /* '.'.'... */ -0x00, 0x21, 0x00, 0x31, 0x00, 0x31, 0x01, 0x32, /* .!.1.1.2 */ -0x01, 0x33, 0x01, 0x33, 0x03, 0x43, 0x03, 0x53, /* .3.3.C.S */ -0x03, 0x63, 0x03 /* .c. */ + 0x42, 0x48, 0x00, + 0x64, 0x20, 0x9c, 0xaf, 0x10, /* BH.d ... */ + 0xef, 0xd0, 0x81, 0x9a, 0xaf, 0x05, 0x27, 0x11, /* ......'. */ + 0x00, 0x51, 0x87, 0x91, 0x81, 0xd1, 0x6c, 0xd2, /* .Q....l. */ + 0x75, 0xe2, 0x80, 0xf2, 0x80, 0xf0, 0x57, 0xf4, /* u.....W. */ + 0x7b, 0xf8, 0x7e, 0xfc, 0x8b, 0x10, 0xcf, 0x7c, /* {.~....| */ + 0xff, 0x3f, 0x00, 0x20, 0xff, 0x00, 0x13, 0x1a, /* .?. .... */ + 0x27, 0x07, 0x27, 0x05, 0x27, 0x01, 0x00, 0x11, /* '.'.'... */ + 0x00, 0x21, 0x00, 0x31, 0x00, 0x31, 0x01, 0x32, /* .!.1.1.2 */ + 0x01, 0x33, 0x01, 0x33, 0x03, 0x43, 0x03, 0x53, /* .3.3.C.S */ + 0x03, 0x63, 0x03 /* .c. */ }; static const unsigned char pkt17[] = { -0x42, 0xca, 0x00, -0x87, 0x20, 0x51, 0x85, 0x44, /* B... Q.D */ -0x1e, 0x03, 0x55, 0xc8, 0x46, 0x01, 0x5b, 0xe4, /* ..U.F.[. */ -0x2f, 0xc9, 0x50, 0x49, 0x1e, 0x16, 0x55, 0xe4, /* /.PI..U. */ -0x2f, 0xc5, 0x50, 0x02, 0xef, 0x02, 0x2e, 0x62, /* /.P....b */ -0x82, 0xfe, 0xcf, 0x08, 0xaf, 0xfe, 0xcf, 0x09, /* ........ */ -0xaf, 0xfe, 0xcf, 0x0b, 0xaf, 0x55, 0x81, 0x02, /* .....U.. */ -0xcf, 0x0f, 0x1c, 0x40, 0x18, 0x08, 0x42, 0x00, /* ...@..B. */ -0x5b, 0x20, 0x18, 0x3d, 0x23, 0x02, 0xaf, 0x10, /* [ .=#... */ -0xef, 0x55, 0xaf, 0x05, 0x27, 0x4a, 0x1e, 0x01, /* .U..'J.. */ -0x55, 0xe4, 0x2f, 0xac, 0x50, 0x4e, 0x1e, 0x01, /* U./.PN.. */ -0x55, 0x00, 0x2e, 0x0d, 0x7b, 0x4f, 0x1e, 0x01, /* U...{O.. */ -0x55, 0x02, 0x2e, 0xbd, 0x71, 0x51, 0x1e, 0x1a, /* U...qQ.. */ -0x55, 0xf9, 0xcf, 0x67, 0xaf, 0xcf, 0x1c, 0xf9, /* U..g.... */ -0xaf, 0xff, 0x86, 0xbf, 0x22, 0x09, 0xbf, 0xfe, /* ...."... */ -0xdf, 0x00, 0x2e, 0xd7, 0x8b, 0x01, 0xef, 0x3b, /* .......; */ -0xaf, 0x01, 0x2e, 0x63, 0x84, 0x3b, 0x80, 0x3b, /* ...c.;.; */ -0xcf, 0x1f, 0x99, 0x01, 0x2e, 0x07, 0x85, 0x00, /* ........ */ -0x2e, 0xa7, 0x8a, 0xbf, 0x22, 0xc1, 0x2e, 0x49, /* ...."..I */ -0xbf, 0x67, 0xcf, 0xf9, 0xaf, 0x05, 0x27, 0x54, /* .g....'T */ -0x1e, 0x32, 0x55, 0x04, 0xef, 0x20, 0x80, 0xe4, /* .2U.. .. */ -0x2f, 0x81, 0x5a, 0x23, 0x81, 0xfe, 0xcf, 0xfe, /* /.Z#.... */ -0xdf, 0xff, 0x96, 0xdf, 0x96, 0xfe, 0xcf, 0xfe, /* ........ */ -0xdf, 0xff, 0x96, 0xdf, 0x96, 0xdf, 0x22, 0x01, /* ......". */ -0x55, 0xff, 0x22, 0x06, 0x54, 0xc1, 0x97, 0x83, /* U.".T... */ -0x03, 0x0e, 0x52, 0x02, 0x5e, 0xc0, 0x97, 0x82, /* ..R.^... */ -0x03, 0x0a, 0x52, 0xc2, 0x97 /* ..R.. */ + 0x42, 0xca, 0x00, + 0x87, 0x20, 0x51, 0x85, 0x44, /* B... Q.D */ + 0x1e, 0x03, 0x55, 0xc8, 0x46, 0x01, 0x5b, 0xe4, /* ..U.F.[. */ + 0x2f, 0xc9, 0x50, 0x49, 0x1e, 0x16, 0x55, 0xe4, /* /.PI..U. */ + 0x2f, 0xc5, 0x50, 0x02, 0xef, 0x02, 0x2e, 0x62, /* /.P....b */ + 0x82, 0xfe, 0xcf, 0x08, 0xaf, 0xfe, 0xcf, 0x09, /* ........ */ + 0xaf, 0xfe, 0xcf, 0x0b, 0xaf, 0x55, 0x81, 0x02, /* .....U.. */ + 0xcf, 0x0f, 0x1c, 0x40, 0x18, 0x08, 0x42, 0x00, /* ...@..B. */ + 0x5b, 0x20, 0x18, 0x3d, 0x23, 0x02, 0xaf, 0x10, /* [ .=#... */ + 0xef, 0x55, 0xaf, 0x05, 0x27, 0x4a, 0x1e, 0x01, /* .U..'J.. */ + 0x55, 0xe4, 0x2f, 0xac, 0x50, 0x4e, 0x1e, 0x01, /* U./.PN.. */ + 0x55, 0x00, 0x2e, 0x0d, 0x7b, 0x4f, 0x1e, 0x01, /* U...{O.. */ + 0x55, 0x02, 0x2e, 0xbd, 0x71, 0x51, 0x1e, 0x1a, /* U...qQ.. */ + 0x55, 0xf9, 0xcf, 0x67, 0xaf, 0xcf, 0x1c, 0xf9, /* U..g.... */ + 0xaf, 0xff, 0x86, 0xbf, 0x22, 0x09, 0xbf, 0xfe, /* ...."... */ + 0xdf, 0x00, 0x2e, 0xd7, 0x8b, 0x01, 0xef, 0x3b, /* .......; */ + 0xaf, 0x01, 0x2e, 0x63, 0x84, 0x3b, 0x80, 0x3b, /* ...c.;.; */ + 0xcf, 0x1f, 0x99, 0x01, 0x2e, 0x07, 0x85, 0x00, /* ........ */ + 0x2e, 0xa7, 0x8a, 0xbf, 0x22, 0xc1, 0x2e, 0x49, /* ...."..I */ + 0xbf, 0x67, 0xcf, 0xf9, 0xaf, 0x05, 0x27, 0x54, /* .g....'T */ + 0x1e, 0x32, 0x55, 0x04, 0xef, 0x20, 0x80, 0xe4, /* .2U.. .. */ + 0x2f, 0x81, 0x5a, 0x23, 0x81, 0xfe, 0xcf, 0xfe, /* /.Z#.... */ + 0xdf, 0xff, 0x96, 0xdf, 0x96, 0xfe, 0xcf, 0xfe, /* ........ */ + 0xdf, 0xff, 0x96, 0xdf, 0x96, 0xdf, 0x22, 0x01, /* ......". */ + 0x55, 0xff, 0x22, 0x06, 0x54, 0xc1, 0x97, 0x83, /* U.".T... */ + 0x03, 0x0e, 0x52, 0x02, 0x5e, 0xc0, 0x97, 0x82, /* ..R.^... */ + 0x03, 0x0a, 0x52, 0xc2, 0x97 /* ..R.. */ }; static const unsigned char pkt19[] = { -0x42, 0xca, 0x00, -0xeb, 0x20, 0xc3, 0x9f, 0xcd, /* B... ... */ -0x80, 0x07, 0x80, 0x00, 0xef, 0xff, 0xaf, 0x00, /* ........ */ -0x2e, 0xa7, 0x8a, 0x04, 0x0c, 0x29, 0x81, 0x05, /* .....).. */ -0x27, 0xc0, 0x97, 0xc1, 0x9f, 0xcd, 0x80, 0x07, /* '....... */ -0x80, 0x01, 0xef, 0xff, 0xaf, 0x00, 0x2e, 0xa9, /* ........ */ -0x8a, 0xc2, 0x97, 0xc3, 0x9f, 0x80, 0x01, 0x41, /* .......A */ -0x01, 0x9f, 0x90, 0xff, 0x90, 0x02, 0x2e, 0xe3, /* ........ */ -0x70, 0x55, 0x1e, 0x16, 0x55, 0x54, 0x85, 0xe4, /* pU..UT.. */ -0x2f, 0x4d, 0x5b, 0x07, 0xef, 0x20, 0x80, 0xe4, /* /M[.. .. */ -0x2f, 0x49, 0x5a, 0xfe, 0xcf, 0x0a, 0xaf, 0xfe, /* /IZ..... */ -0xcf, 0xfe, 0xcf, 0x41, 0x2e, 0x44, 0xbf, 0xfe, /* ...A.D.. */ -0xcf, 0x41, 0x2e, 0x45, 0xbf, 0xfe, 0xcf, 0x52, /* .A.E...R */ -0xaf, 0xfe, 0xcf, 0x53, 0xaf, 0xfe, 0xcf, 0x5a, /* ...S...Z */ -0xaf, 0x05, 0x27, 0x58, 0x1e, 0x0d, 0x55, 0x02, /* ..'X..U. */ -0x44, 0x01, 0x5a, 0x00, 0x2e, 0x54, 0x79, 0xfe, /* D.Z..Ty. */ -0xcf, 0x75, 0xaf, 0xfe, 0xdf, 0x76, 0xbf, 0x41, /* .u...v.A */ -0x2e, 0xa4, 0xdf, 0xdf, 0x29, 0x41, 0x2e, 0xa4, /* ....)A.. */ -0xbf, 0x05, 0x27, 0x59, 0x1e, 0x03, 0x55, 0xfe, /* ..'Y..U. */ -0xcf, 0x10, 0xaf, 0x01, 0x2e, 0x94, 0x76, 0x63, /* ......vc */ -0x1e, 0x1a, 0x55, 0x54, 0x85, 0xe4, 0x2f, 0x1e, /* ..UT../. */ -0x5b, 0x0c, 0xef, 0x20, 0x80, 0xe4, 0x2f, 0x1a, /* [.. ../. */ -0x5a, 0xf0, 0xef, 0x00, 0xff, 0x19, 0x27, 0x08, /* Z.....'. */ -0xef, 0x06, 0xaf, 0xfe, 0xcf, 0x5f, 0x9f, 0x06, /* ....._.. */ -0x25, 0xfb, 0x55, 0xfe, 0xcf, 0xfe, 0xcf, 0x41, /* %.U....A */ -0x2e, 0x40, 0xbf, 0xfe, 0xcf, 0x41, 0x2e, 0x41, /* .@...A.A */ -0xbf, 0xfe, 0xcf, 0x41, 0x2e /* ...A. */ + 0x42, 0xca, 0x00, + 0xeb, 0x20, 0xc3, 0x9f, 0xcd, /* B... ... */ + 0x80, 0x07, 0x80, 0x00, 0xef, 0xff, 0xaf, 0x00, /* ........ */ + 0x2e, 0xa7, 0x8a, 0x04, 0x0c, 0x29, 0x81, 0x05, /* .....).. */ + 0x27, 0xc0, 0x97, 0xc1, 0x9f, 0xcd, 0x80, 0x07, /* '....... */ + 0x80, 0x01, 0xef, 0xff, 0xaf, 0x00, 0x2e, 0xa9, /* ........ */ + 0x8a, 0xc2, 0x97, 0xc3, 0x9f, 0x80, 0x01, 0x41, /* .......A */ + 0x01, 0x9f, 0x90, 0xff, 0x90, 0x02, 0x2e, 0xe3, /* ........ */ + 0x70, 0x55, 0x1e, 0x16, 0x55, 0x54, 0x85, 0xe4, /* pU..UT.. */ + 0x2f, 0x4d, 0x5b, 0x07, 0xef, 0x20, 0x80, 0xe4, /* /M[.. .. */ + 0x2f, 0x49, 0x5a, 0xfe, 0xcf, 0x0a, 0xaf, 0xfe, /* /IZ..... */ + 0xcf, 0xfe, 0xcf, 0x41, 0x2e, 0x44, 0xbf, 0xfe, /* ...A.D.. */ + 0xcf, 0x41, 0x2e, 0x45, 0xbf, 0xfe, 0xcf, 0x52, /* .A.E...R */ + 0xaf, 0xfe, 0xcf, 0x53, 0xaf, 0xfe, 0xcf, 0x5a, /* ...S...Z */ + 0xaf, 0x05, 0x27, 0x58, 0x1e, 0x0d, 0x55, 0x02, /* ..'X..U. */ + 0x44, 0x01, 0x5a, 0x00, 0x2e, 0x54, 0x79, 0xfe, /* D.Z..Ty. */ + 0xcf, 0x75, 0xaf, 0xfe, 0xdf, 0x76, 0xbf, 0x41, /* .u...v.A */ + 0x2e, 0xa4, 0xdf, 0xdf, 0x29, 0x41, 0x2e, 0xa4, /* ....)A.. */ + 0xbf, 0x05, 0x27, 0x59, 0x1e, 0x03, 0x55, 0xfe, /* ..'Y..U. */ + 0xcf, 0x10, 0xaf, 0x01, 0x2e, 0x94, 0x76, 0x63, /* ......vc */ + 0x1e, 0x1a, 0x55, 0x54, 0x85, 0xe4, 0x2f, 0x1e, /* ..UT../. */ + 0x5b, 0x0c, 0xef, 0x20, 0x80, 0xe4, 0x2f, 0x1a, /* [.. ../. */ + 0x5a, 0xf0, 0xef, 0x00, 0xff, 0x19, 0x27, 0x08, /* Z.....'. */ + 0xef, 0x06, 0xaf, 0xfe, 0xcf, 0x5f, 0x9f, 0x06, /* ....._.. */ + 0x25, 0xfb, 0x55, 0xfe, 0xcf, 0xfe, 0xcf, 0x41, /* %.U....A */ + 0x2e, 0x40, 0xbf, 0xfe, 0xcf, 0x41, 0x2e, 0x41, /* .@...A.A */ + 0xbf, 0xfe, 0xcf, 0x41, 0x2e /* ...A. */ }; static const unsigned char pkt21[] = { -0x42, 0xca, 0x00, -0x4f, 0x21, 0x42, 0xbf, 0x05, /* B..O!B.. */ -0x27, 0x64, 0x1e, 0x31, 0x55, 0xb0, 0xef, 0x00, /* 'd.1U... */ -0xff, 0x19, 0x27, 0x0b, 0xef, 0x06, 0xaf, 0xfe, /* ..'..... */ -0xcf, 0x5f, 0x9f, 0x06, 0x25, 0xfb, 0x55, 0xfe, /* ._..%.U. */ -0xcf, 0x56, 0xaf, 0xfe, 0xcf, 0xae, 0xdf, 0x1f, /* .V...... */ -0x1c, 0xe0, 0x1d, 0x5f, 0x02, 0xae, 0xbf, 0xfe, /* ..._.... */ -0xcf, 0x41, 0x2e, 0x54, 0xbf, 0xfe, 0xcf, 0x41, /* .A.T...A */ -0x2e, 0x77, 0xbf, 0xfe, 0xcf, 0x41, 0x2e, 0x55, /* .w...A.U */ -0xbf, 0xfe, 0xcf, 0x41, 0x2e, 0x78, 0xbf, 0xfe, /* ...A.x.. */ -0xcf, 0xbb, 0xaf, 0xfe, 0xcf, 0xbc, 0xaf, 0xfe, /* ........ */ -0xcf, 0xbd, 0xaf, 0xfe, 0xcf, 0xbe, 0xaf, 0xfe, /* ........ */ -0xcf, 0x83, 0xaf, 0xfe, 0xcf, 0x84, 0xaf, 0xfe, /* ........ */ -0xcf, 0x81, 0xaf, 0xfe, 0xcf, 0x82, 0xaf, 0xfe, /* ........ */ -0xcf, 0x24, 0xaf, 0xfe, 0xcf, 0x02, 0x33, 0x05, /* .$....3. */ -0x27, 0x66, 0x1e, 0x0b, 0x55, 0xc5, 0xef, 0x2f, /* 'f..U../ */ -0xff, 0x1a, 0x27, 0x0b, 0xef, 0x06, 0xaf, 0xfe, /* ..'..... */ -0xcf, 0xfe, 0xdf, 0x06, 0x27, 0x01, 0x0e, 0x06, /* ....'... */ -0x25, 0xf9, 0x55, 0x05, 0x27, 0x73, 0x1e, 0x02, /* %.U.'s.. */ -0x55, 0x02, 0x2e, 0x5a, 0x88, 0x05, 0x27, 0x7d, /* U..Z..'} */ -0x1e, 0x0c, 0x55, 0x02, 0x2e, 0xb7, 0x81, 0xe3, /* ..U..... */ -0x2f, 0xb9, 0x5a, 0xfe, 0xcf, 0xfe, 0xdf, 0x1b, /* /.Z..... */ -0x27, 0xfe, 0xcf, 0x36, 0x03, 0xfe, 0xdf, 0x3f, /* '..6...? */ -0x02, 0x9f, 0x9d, 0x05, 0x27, 0x7e, 0x1e, 0x0c, /* ....'~.. */ -0x55, 0x02, 0x2e, 0xb7, 0x81, 0xe3, 0x2f, 0xaa, /* U...../. */ -0x5a, 0xfe, 0xcf, 0xfe, 0xdf, 0x1b, 0x27, 0x07, /* Z.....'. */ -0x80, 0xf6, 0x97, 0xff, 0xaf /* ..... */ + 0x42, 0xca, 0x00, + 0x4f, 0x21, 0x42, 0xbf, 0x05, /* B..O!B.. */ + 0x27, 0x64, 0x1e, 0x31, 0x55, 0xb0, 0xef, 0x00, /* 'd.1U... */ + 0xff, 0x19, 0x27, 0x0b, 0xef, 0x06, 0xaf, 0xfe, /* ..'..... */ + 0xcf, 0x5f, 0x9f, 0x06, 0x25, 0xfb, 0x55, 0xfe, /* ._..%.U. */ + 0xcf, 0x56, 0xaf, 0xfe, 0xcf, 0xae, 0xdf, 0x1f, /* .V...... */ + 0x1c, 0xe0, 0x1d, 0x5f, 0x02, 0xae, 0xbf, 0xfe, /* ..._.... */ + 0xcf, 0x41, 0x2e, 0x54, 0xbf, 0xfe, 0xcf, 0x41, /* .A.T...A */ + 0x2e, 0x77, 0xbf, 0xfe, 0xcf, 0x41, 0x2e, 0x55, /* .w...A.U */ + 0xbf, 0xfe, 0xcf, 0x41, 0x2e, 0x78, 0xbf, 0xfe, /* ...A.x.. */ + 0xcf, 0xbb, 0xaf, 0xfe, 0xcf, 0xbc, 0xaf, 0xfe, /* ........ */ + 0xcf, 0xbd, 0xaf, 0xfe, 0xcf, 0xbe, 0xaf, 0xfe, /* ........ */ + 0xcf, 0x83, 0xaf, 0xfe, 0xcf, 0x84, 0xaf, 0xfe, /* ........ */ + 0xcf, 0x81, 0xaf, 0xfe, 0xcf, 0x82, 0xaf, 0xfe, /* ........ */ + 0xcf, 0x24, 0xaf, 0xfe, 0xcf, 0x02, 0x33, 0x05, /* .$....3. */ + 0x27, 0x66, 0x1e, 0x0b, 0x55, 0xc5, 0xef, 0x2f, /* 'f..U../ */ + 0xff, 0x1a, 0x27, 0x0b, 0xef, 0x06, 0xaf, 0xfe, /* ..'..... */ + 0xcf, 0xfe, 0xdf, 0x06, 0x27, 0x01, 0x0e, 0x06, /* ....'... */ + 0x25, 0xf9, 0x55, 0x05, 0x27, 0x73, 0x1e, 0x02, /* %.U.'s.. */ + 0x55, 0x02, 0x2e, 0x5a, 0x88, 0x05, 0x27, 0x7d, /* U..Z..'} */ + 0x1e, 0x0c, 0x55, 0x02, 0x2e, 0xb7, 0x81, 0xe3, /* ..U..... */ + 0x2f, 0xb9, 0x5a, 0xfe, 0xcf, 0xfe, 0xdf, 0x1b, /* /.Z..... */ + 0x27, 0xfe, 0xcf, 0x36, 0x03, 0xfe, 0xdf, 0x3f, /* '..6...? */ + 0x02, 0x9f, 0x9d, 0x05, 0x27, 0x7e, 0x1e, 0x0c, /* ....'~.. */ + 0x55, 0x02, 0x2e, 0xb7, 0x81, 0xe3, 0x2f, 0xaa, /* U...../. */ + 0x5a, 0xfe, 0xcf, 0xfe, 0xdf, 0x1b, 0x27, 0x07, /* Z.....'. */ + 0x80, 0xf6, 0x97, 0xff, 0xaf /* ..... */ }; static const unsigned char pkt23[] = { -0x42, 0xca, 0x00, -0xb3, 0x21, 0x00, 0x2e, 0xa7, /* B...!... */ -0x8a, 0x05, 0x27, 0x61, 0x74, 0xff, 0x96, 0xc6, /* ..'at... */ -0x2e, 0x01, 0xdf, 0x3f, 0x2c, 0xdd, 0x9f, 0x05, /* ...?,... */ -0x27, 0x01, 0xef, 0x20, 0x80, 0xe3, 0x2f, 0x96, /* '.. ../. */ -0x5a, 0xfe, 0xcf, 0xdf, 0x22, 0xe9, 0x2f, 0xf0, /* Z..."./. */ -0x54, 0x01, 0xff, 0x85, 0xef, 0xff, 0x96, 0xdf, /* T....... */ -0x96, 0x34, 0xff, 0x8d, 0xef, 0x19, 0x27, 0x03, /* .4....'. */ -0xcf, 0x7f, 0x1c, 0x5f, 0x9f, 0xdd, 0x97, 0x5f, /* ..._..._ */ -0x9f, 0xdd, 0x97, 0x5f, 0x9f, 0x05, 0xef, 0x06, /* ..._.... */ -0xaf, 0x9f, 0x22, 0x5f, 0x9f, 0x06, 0x25, 0xfc, /* .."_..%. */ -0x55, 0x5f, 0x9f, 0x06, 0x25, 0xfc, 0x55, 0x20, /* U_..%.U */ -0xef, 0x08, 0xaf, 0x09, 0x23, 0x01, 0x2e, 0x06, /* ....#... */ -0x82, 0x51, 0x81, 0x03, 0xef, 0xfc, 0xaf, 0x84, /* .Q...... */ -0xef, 0xaa, 0xaf, 0x08, 0xef, 0xe3, 0xaf, 0x9f, /* ........ */ -0x22, 0xe2, 0xaf, 0x21, 0xef, 0x41, 0x2e, 0x47, /* "..!.A.G */ -0xbf, 0x27, 0xef, 0xf4, 0xaf, 0x2d, 0xff, 0xa7, /* .'...-.. */ -0xef, 0xe1, 0xbf, 0xe0, 0xaf, 0x08, 0xef, 0x10, /* ........ */ -0xaf, 0x01, 0x2e, 0x94, 0x86, 0xed, 0x80, 0x01, /* ........ */ -0x2e, 0x18, 0x87, 0x01, 0x2e, 0x1a, 0x87, 0x9b, /* ........ */ -0x22, 0x9b, 0x22, 0x34, 0xff, 0x95, 0xef, 0x19, /* "."4.... */ -0x27, 0x2d, 0xff, 0xa7, 0xef, 0x1a, 0x27, 0xc0, /* '-....'. */ -0xef, 0x06, 0xaf, 0xdc, 0x97, 0x5f, 0x9f, 0x06, /* ....._.. */ -0xdf, 0xc0, 0x1f, 0x03, 0x54, 0xdf, 0x22, 0x01, /* ....T.". */ -0x54, 0x00, 0x2e, 0xb9, 0x8b, 0x06, 0x25, 0xf4, /* T.....%. */ -0x55, 0x34, 0xff, 0x91, 0xef, 0x19, 0x27, 0xdd, /* U4....'. */ -0x97, 0xdd, 0x9f, 0x5f, 0x9f /* ..._. */ + 0x42, 0xca, 0x00, + 0xb3, 0x21, 0x00, 0x2e, 0xa7, /* B...!... */ + 0x8a, 0x05, 0x27, 0x61, 0x74, 0xff, 0x96, 0xc6, /* ..'at... */ + 0x2e, 0x01, 0xdf, 0x3f, 0x2c, 0xdd, 0x9f, 0x05, /* ...?,... */ + 0x27, 0x01, 0xef, 0x20, 0x80, 0xe3, 0x2f, 0x96, /* '.. ../. */ + 0x5a, 0xfe, 0xcf, 0xdf, 0x22, 0xe9, 0x2f, 0xf0, /* Z..."./. */ + 0x54, 0x01, 0xff, 0x85, 0xef, 0xff, 0x96, 0xdf, /* T....... */ + 0x96, 0x34, 0xff, 0x8d, 0xef, 0x19, 0x27, 0x03, /* .4....'. */ + 0xcf, 0x7f, 0x1c, 0x5f, 0x9f, 0xdd, 0x97, 0x5f, /* ..._..._ */ + 0x9f, 0xdd, 0x97, 0x5f, 0x9f, 0x05, 0xef, 0x06, /* ..._.... */ + 0xaf, 0x9f, 0x22, 0x5f, 0x9f, 0x06, 0x25, 0xfc, /* .."_..%. */ + 0x55, 0x5f, 0x9f, 0x06, 0x25, 0xfc, 0x55, 0x20, /* U_..%.U */ + 0xef, 0x08, 0xaf, 0x09, 0x23, 0x01, 0x2e, 0x06, /* ....#... */ + 0x82, 0x51, 0x81, 0x03, 0xef, 0xfc, 0xaf, 0x84, /* .Q...... */ + 0xef, 0xaa, 0xaf, 0x08, 0xef, 0xe3, 0xaf, 0x9f, /* ........ */ + 0x22, 0xe2, 0xaf, 0x21, 0xef, 0x41, 0x2e, 0x47, /* "..!.A.G */ + 0xbf, 0x27, 0xef, 0xf4, 0xaf, 0x2d, 0xff, 0xa7, /* .'...-.. */ + 0xef, 0xe1, 0xbf, 0xe0, 0xaf, 0x08, 0xef, 0x10, /* ........ */ + 0xaf, 0x01, 0x2e, 0x94, 0x86, 0xed, 0x80, 0x01, /* ........ */ + 0x2e, 0x18, 0x87, 0x01, 0x2e, 0x1a, 0x87, 0x9b, /* ........ */ + 0x22, 0x9b, 0x22, 0x34, 0xff, 0x95, 0xef, 0x19, /* "."4.... */ + 0x27, 0x2d, 0xff, 0xa7, 0xef, 0x1a, 0x27, 0xc0, /* '-....'. */ + 0xef, 0x06, 0xaf, 0xdc, 0x97, 0x5f, 0x9f, 0x06, /* ....._.. */ + 0xdf, 0xc0, 0x1f, 0x03, 0x54, 0xdf, 0x22, 0x01, /* ....T.". */ + 0x54, 0x00, 0x2e, 0xb9, 0x8b, 0x06, 0x25, 0xf4, /* T.....%. */ + 0x55, 0x34, 0xff, 0x91, 0xef, 0x19, 0x27, 0xdd, /* U4....'. */ + 0x97, 0xdd, 0x9f, 0x5f, 0x9f /* ..._. */ }; static const unsigned char pkt25[] = { -0x42, 0xb2, 0x00, -0x17, 0x22, 0x7f, 0x9f, 0xfd, /* B..."... */ -0x0d, 0xdf, 0x22, 0x01, 0x55, 0xff, 0x22, 0x01, /* ..".U.". */ -0x54, 0x01, 0xef, 0x1f, 0x98, 0x2f, 0xef, 0x41, /* T..../.A */ -0x2e, 0x47, 0xbf, 0x11, 0xef, 0xf4, 0xaf, 0x2d, /* .G.....- */ -0xff, 0xa7, 0xef, 0xe1, 0xbf, 0xe0, 0xaf, 0x01, /* ........ */ -0x2e, 0x18, 0x87, 0x01, 0x2e, 0x1a, 0x87, 0x9b, /* ........ */ -0x22, 0x9b, 0x22, 0x35, 0xff, 0x55, 0xef, 0x19, /* "."5.U.. */ -0x27, 0x2d, 0xff, 0xa7, 0xef, 0x1a, 0x27, 0xc0, /* '-....'. */ -0xef, 0x06, 0xaf, 0xdc, 0x97, 0xff, 0x1a, 0x5f, /* ......._ */ -0x9f, 0x06, 0xdf, 0xc0, 0x1f, 0x03, 0x54, 0xdf, /* ......T. */ -0x22, 0x01, 0x54, 0x00, 0x2e, 0xb9, 0x8b, 0x06, /* ".T..... */ -0x25, 0xf3, 0x55, 0x34, 0xff, 0x93, 0xef, 0x19, /* %.U4.... */ -0x27, 0xdd, 0x97, 0xdd, 0x9f, 0x5f, 0x9f, 0x7f, /* '...._.. */ -0x9f, 0xfb, 0x0d, 0xdf, 0x22, 0x01, 0x54, 0x01, /* ....".T. */ -0xef, 0x1f, 0x98, 0xff, 0x22, 0x01, 0x54, 0x01, /* ....".T. */ -0xef, 0x1f, 0x98, 0x34, 0xff, 0x8d, 0xef, 0x19, /* ...4.... */ -0x27, 0x01, 0x2e, 0x0c, 0x85, 0x00, 0x2e, 0xa7, /* '....... */ -0x8a, 0x55, 0x81, 0x02, 0xef, 0xfc, 0xaf, 0x88, /* .U...... */ -0xef, 0xaa, 0xaf, 0x00, 0xef, 0x41, 0x2e, 0x47, /* .....A.G */ -0xbf, 0x05, 0x27, 0xf9, 0x35, 0xc1, 0x2e, 0x4e, /* ..'.5..N */ -0xdf, 0x0f, 0x1d, 0x09, 0x27, 0x5f, 0x02, 0xc1, /* ....'_.. */ -0x2e, 0x4e, 0xbf, 0x05, 0x27, 0x9f, 0x22, 0x02, /* .N..'.". */ -0x2e, 0xa6, 0x85, 0x05, 0x27 /* ....' */ + 0x42, 0xb2, 0x00, + 0x17, 0x22, 0x7f, 0x9f, 0xfd, /* B..."... */ + 0x0d, 0xdf, 0x22, 0x01, 0x55, 0xff, 0x22, 0x01, /* ..".U.". */ + 0x54, 0x01, 0xef, 0x1f, 0x98, 0x2f, 0xef, 0x41, /* T..../.A */ + 0x2e, 0x47, 0xbf, 0x11, 0xef, 0xf4, 0xaf, 0x2d, /* .G.....- */ + 0xff, 0xa7, 0xef, 0xe1, 0xbf, 0xe0, 0xaf, 0x01, /* ........ */ + 0x2e, 0x18, 0x87, 0x01, 0x2e, 0x1a, 0x87, 0x9b, /* ........ */ + 0x22, 0x9b, 0x22, 0x35, 0xff, 0x55, 0xef, 0x19, /* "."5.U.. */ + 0x27, 0x2d, 0xff, 0xa7, 0xef, 0x1a, 0x27, 0xc0, /* '-....'. */ + 0xef, 0x06, 0xaf, 0xdc, 0x97, 0xff, 0x1a, 0x5f, /* ......._ */ + 0x9f, 0x06, 0xdf, 0xc0, 0x1f, 0x03, 0x54, 0xdf, /* ......T. */ + 0x22, 0x01, 0x54, 0x00, 0x2e, 0xb9, 0x8b, 0x06, /* ".T..... */ + 0x25, 0xf3, 0x55, 0x34, 0xff, 0x93, 0xef, 0x19, /* %.U4.... */ + 0x27, 0xdd, 0x97, 0xdd, 0x9f, 0x5f, 0x9f, 0x7f, /* '...._.. */ + 0x9f, 0xfb, 0x0d, 0xdf, 0x22, 0x01, 0x54, 0x01, /* ....".T. */ + 0xef, 0x1f, 0x98, 0xff, 0x22, 0x01, 0x54, 0x01, /* ....".T. */ + 0xef, 0x1f, 0x98, 0x34, 0xff, 0x8d, 0xef, 0x19, /* ...4.... */ + 0x27, 0x01, 0x2e, 0x0c, 0x85, 0x00, 0x2e, 0xa7, /* '....... */ + 0x8a, 0x55, 0x81, 0x02, 0xef, 0xfc, 0xaf, 0x88, /* .U...... */ + 0xef, 0xaa, 0xaf, 0x00, 0xef, 0x41, 0x2e, 0x47, /* .....A.G */ + 0xbf, 0x05, 0x27, 0xf9, 0x35, 0xc1, 0x2e, 0x4e, /* ..'.5..N */ + 0xdf, 0x0f, 0x1d, 0x09, 0x27, 0x5f, 0x02, 0xc1, /* ....'_.. */ + 0x2e, 0x4e, 0xbf, 0x05, 0x27, 0x9f, 0x22, 0x02, /* .N..'.". */ + 0x2e, 0xa6, 0x85, 0x05, 0x27 /* ....' */ }; static const unsigned char pkt27[] = { -0x42, 0xca, 0x00, -0x6f, 0x22, 0x51, 0x85, 0x01, /* B..o"Q.. */ -0x1e, 0x38, 0x55, 0x26, 0x40, 0x12, 0x5b, 0x26, /* .8U&@.[& */ -0x42, 0x2e, 0x5a, 0x26, 0x41, 0x0e, 0x5a, 0x26, /* B.Z&A.Z& */ -0xcf, 0x40, 0x1a, 0x26, 0xaf, 0x9f, 0x2d, 0x27, /* .@.&..-' */ -0x5a, 0x07, 0x80, 0x01, 0xef, 0xff, 0xaf, 0x26, /* Z......& */ -0x43, 0x01, 0x5b, 0x74, 0x25, 0x00, 0x55, 0x26, /* C.[t%.U& */ -0x32, 0x00, 0x2e, 0xa7, 0x7a, 0x02, 0x2e, 0xc0, /* 2...z... */ -0x85, 0x26, 0x40, 0x08, 0x5b, 0x41, 0x2e, 0x52, /* .&@.[A.R */ -0xdf, 0xdf, 0x2d, 0x04, 0x5b, 0x26, 0x43, 0x01, /* ..-.[&C. */ -0x5b, 0x74, 0x25, 0x00, 0x55, 0x26, 0x32, 0x41, /* [t%.U&2A */ -0x2e, 0x53, 0xdf, 0xc1, 0x2e, 0x79, 0xdf, 0xff, /* .S...y.. */ -0x96, 0xdf, 0x96, 0x41, 0x2e, 0x55, 0xdf, 0xc1, /* ...A.U.. */ -0x2e, 0x78, 0xdf, 0x9d, 0x01, 0x5d, 0x01, 0xff, /* .x...].. */ -0x22, 0x00, 0x54, 0xff, 0xef, 0x2e, 0xaf, 0x05, /* ".T..... */ -0x27, 0x07, 0x80, 0x9f, 0x22, 0xff, 0xaf, 0x00, /* '..."... */ -0x2e, 0xa7, 0x8a, 0x05, 0x27, 0x03, 0x1e, 0x3f, /* ....'..? */ -0x55, 0x02, 0x2e, 0xad, 0x85, 0xa1, 0xcf, 0xfe, /* U....... */ -0x1c, 0xa1, 0xaf, 0xed, 0x80, 0x31, 0x81, 0x02, /* .....1.. */ -0x2e, 0x51, 0x83, 0xff, 0x96, 0xdf, 0x96, 0xa1, /* .Q...... */ -0xcf, 0x01, 0x18, 0xa1, 0xaf, 0xed, 0x80, 0x64, /* .......d */ -0xef, 0xbf, 0x22, 0xa9, 0x80, 0x31, 0x81, 0x02, /* .."..1.. */ -0x2e, 0x51, 0x83, 0xff, 0x96, 0xdf, 0x96, 0x9b, /* .Q...... */ -0x22, 0x14, 0x1e, 0x03, 0x53, 0xff, 0x22, 0x01, /* "...S.". */ -0x55, 0x00, 0x20, 0x0a, 0x50, 0xc3, 0x97, 0xc4, /* U. .P... */ -0x9f, 0x81, 0x01, 0x42, 0x01, 0x03, 0x52, 0xfa, /* ...B..R. */ -0x1e, 0x03, 0x53, 0xff, 0x22 /* ..S." */ + 0x42, 0xca, 0x00, + 0x6f, 0x22, 0x51, 0x85, 0x01, /* B..o"Q.. */ + 0x1e, 0x38, 0x55, 0x26, 0x40, 0x12, 0x5b, 0x26, /* .8U&@.[& */ + 0x42, 0x2e, 0x5a, 0x26, 0x41, 0x0e, 0x5a, 0x26, /* B.Z&A.Z& */ + 0xcf, 0x40, 0x1a, 0x26, 0xaf, 0x9f, 0x2d, 0x27, /* .@.&..-' */ + 0x5a, 0x07, 0x80, 0x01, 0xef, 0xff, 0xaf, 0x26, /* Z......& */ + 0x43, 0x01, 0x5b, 0x74, 0x25, 0x00, 0x55, 0x26, /* C.[t%.U& */ + 0x32, 0x00, 0x2e, 0xa7, 0x7a, 0x02, 0x2e, 0xc0, /* 2...z... */ + 0x85, 0x26, 0x40, 0x08, 0x5b, 0x41, 0x2e, 0x52, /* .&@.[A.R */ + 0xdf, 0xdf, 0x2d, 0x04, 0x5b, 0x26, 0x43, 0x01, /* ..-.[&C. */ + 0x5b, 0x74, 0x25, 0x00, 0x55, 0x26, 0x32, 0x41, /* [t%.U&2A */ + 0x2e, 0x53, 0xdf, 0xc1, 0x2e, 0x79, 0xdf, 0xff, /* .S...y.. */ + 0x96, 0xdf, 0x96, 0x41, 0x2e, 0x55, 0xdf, 0xc1, /* ...A.U.. */ + 0x2e, 0x78, 0xdf, 0x9d, 0x01, 0x5d, 0x01, 0xff, /* .x...].. */ + 0x22, 0x00, 0x54, 0xff, 0xef, 0x2e, 0xaf, 0x05, /* ".T..... */ + 0x27, 0x07, 0x80, 0x9f, 0x22, 0xff, 0xaf, 0x00, /* '..."... */ + 0x2e, 0xa7, 0x8a, 0x05, 0x27, 0x03, 0x1e, 0x3f, /* ....'..? */ + 0x55, 0x02, 0x2e, 0xad, 0x85, 0xa1, 0xcf, 0xfe, /* U....... */ + 0x1c, 0xa1, 0xaf, 0xed, 0x80, 0x31, 0x81, 0x02, /* .....1.. */ + 0x2e, 0x51, 0x83, 0xff, 0x96, 0xdf, 0x96, 0xa1, /* .Q...... */ + 0xcf, 0x01, 0x18, 0xa1, 0xaf, 0xed, 0x80, 0x64, /* .......d */ + 0xef, 0xbf, 0x22, 0xa9, 0x80, 0x31, 0x81, 0x02, /* .."..1.. */ + 0x2e, 0x51, 0x83, 0xff, 0x96, 0xdf, 0x96, 0x9b, /* .Q...... */ + 0x22, 0x14, 0x1e, 0x03, 0x53, 0xff, 0x22, 0x01, /* "...S.". */ + 0x55, 0x00, 0x20, 0x0a, 0x50, 0xc3, 0x97, 0xc4, /* U. .P... */ + 0x9f, 0x81, 0x01, 0x42, 0x01, 0x03, 0x52, 0xfa, /* ...B..R. */ + 0x1e, 0x03, 0x53, 0xff, 0x22 /* ..S." */ }; static const unsigned char pkt29[] = { -0x42, 0xca, 0x00, -0xd3, 0x22, 0x01, 0x55, 0x00, /* B...".U. */ -0x20, 0xf2, 0x50, 0x00, 0x2e, 0xd8, 0x8d, 0x03, /* .P..... */ -0xcf, 0x7f, 0x1c, 0xff, 0xaf, 0x05, 0xef, 0xff, /* ........ */ -0xaf, 0x00, 0xef, 0xff, 0xaf, 0xdd, 0x97, 0xff, /* ........ */ -0xaf, 0xc2, 0x97, 0xff, 0xaf, 0xc3, 0x97, 0xff, /* ........ */ -0xaf, 0xc0, 0x97, 0xff, 0xaf, 0xc1, 0x97, 0xff, /* ........ */ -0xaf, 0x04, 0x0c, 0x00, 0x2e, 0xa7, 0x8a, 0x05, /* ........ */ -0x27, 0x06, 0x1e, 0x01, 0x55, 0x0f, 0x27, 0x0f, /* '...U.'. */ -0x27, 0x0a, 0x1e, 0x08, 0x55, 0x02, 0x2e, 0xf6, /* '...U... */ -0x82, 0xa8, 0x77, 0x3b, 0x30, 0x07, 0x35, 0xff, /* ..w;0.5. */ -0xff, 0xc2, 0xbf, 0x0d, 0x27, 0x0c, 0x27, 0x0d, /* ....'.'. */ -0x1e, 0x02, 0x55, 0x54, 0x85, 0xf5, 0x5b, 0xbd, /* ..UT..[. */ -0x77, 0x12, 0x1e, 0x07, 0x55, 0xdc, 0xef, 0x05, /* w...U... */ -0xff, 0x1a, 0x27, 0x56, 0xdf, 0x3f, 0x20, 0x59, /* ..'V.? Y */ -0x80, 0x3c, 0xaf, 0x05, 0x27, 0x13, 0x1e, 0x01, /* .<..'... */ -0x55, 0x3c, 0x23, 0x05, 0x27, 0x1f, 0x1e, 0x06, /* U<#.'... */ -0x55, 0x37, 0x35, 0x08, 0xef, 0x40, 0x2e, 0xf0, /* U75..@.. */ -0xbf, 0x40, 0x2e, 0xf6, 0xbf, 0x05, 0x27, 0x20, /* .@....' */ -0x1e, 0x06, 0x55, 0x37, 0x3d, 0x16, 0xef, 0x40, /* ..U7=..@ */ -0x2e, 0xf0, 0xbf, 0x40, 0x2e, 0xf6, 0xbf, 0x05, /* ...@.... */ -0x27, 0x2e, 0x1e, 0x0c, 0x55, 0x02, 0x2e, 0x57, /* '...U..W */ -0x80, 0x41, 0x2e, 0xa1, 0xdf, 0xdf, 0x2a, 0x41, /* .A....*A */ -0x2e, 0xa1, 0xbf, 0x02, 0x2e, 0x57, 0x80, 0x9b, /* .....W.. */ -0x22, 0xdf, 0x2f, 0xd3, 0x50, 0x05, 0x27, 0x2f, /* "./.P.'/ */ -0x1e, 0x0c, 0x55, 0x02, 0x2e, 0x57, 0x80, 0x41, /* ..U..W.A */ -0x2e, 0xa1, 0xdf, 0xdf, 0x2a /* ....* */ + 0x42, 0xca, 0x00, + 0xd3, 0x22, 0x01, 0x55, 0x00, /* B...".U. */ + 0x20, 0xf2, 0x50, 0x00, 0x2e, 0xd8, 0x8d, 0x03, /* .P..... */ + 0xcf, 0x7f, 0x1c, 0xff, 0xaf, 0x05, 0xef, 0xff, /* ........ */ + 0xaf, 0x00, 0xef, 0xff, 0xaf, 0xdd, 0x97, 0xff, /* ........ */ + 0xaf, 0xc2, 0x97, 0xff, 0xaf, 0xc3, 0x97, 0xff, /* ........ */ + 0xaf, 0xc0, 0x97, 0xff, 0xaf, 0xc1, 0x97, 0xff, /* ........ */ + 0xaf, 0x04, 0x0c, 0x00, 0x2e, 0xa7, 0x8a, 0x05, /* ........ */ + 0x27, 0x06, 0x1e, 0x01, 0x55, 0x0f, 0x27, 0x0f, /* '...U.'. */ + 0x27, 0x0a, 0x1e, 0x08, 0x55, 0x02, 0x2e, 0xf6, /* '...U... */ + 0x82, 0xa8, 0x77, 0x3b, 0x30, 0x07, 0x35, 0xff, /* ..w;0.5. */ + 0xff, 0xc2, 0xbf, 0x0d, 0x27, 0x0c, 0x27, 0x0d, /* ....'.'. */ + 0x1e, 0x02, 0x55, 0x54, 0x85, 0xf5, 0x5b, 0xbd, /* ..UT..[. */ + 0x77, 0x12, 0x1e, 0x07, 0x55, 0xdc, 0xef, 0x05, /* w...U... */ + 0xff, 0x1a, 0x27, 0x56, 0xdf, 0x3f, 0x20, 0x59, /* ..'V.? Y */ + 0x80, 0x3c, 0xaf, 0x05, 0x27, 0x13, 0x1e, 0x01, /* .<..'... */ + 0x55, 0x3c, 0x23, 0x05, 0x27, 0x1f, 0x1e, 0x06, /* U<#.'... */ + 0x55, 0x37, 0x35, 0x08, 0xef, 0x40, 0x2e, 0xf0, /* U75..@.. */ + 0xbf, 0x40, 0x2e, 0xf6, 0xbf, 0x05, 0x27, 0x20, /* .@....' */ + 0x1e, 0x06, 0x55, 0x37, 0x3d, 0x16, 0xef, 0x40, /* ..U7=..@ */ + 0x2e, 0xf0, 0xbf, 0x40, 0x2e, 0xf6, 0xbf, 0x05, /* ...@.... */ + 0x27, 0x2e, 0x1e, 0x0c, 0x55, 0x02, 0x2e, 0x57, /* '...U..W */ + 0x80, 0x41, 0x2e, 0xa1, 0xdf, 0xdf, 0x2a, 0x41, /* .A....*A */ + 0x2e, 0xa1, 0xbf, 0x02, 0x2e, 0x57, 0x80, 0x9b, /* .....W.. */ + 0x22, 0xdf, 0x2f, 0xd3, 0x50, 0x05, 0x27, 0x2f, /* "./.P.'/ */ + 0x1e, 0x0c, 0x55, 0x02, 0x2e, 0x57, 0x80, 0x41, /* ..U..W.A */ + 0x2e, 0xa1, 0xdf, 0xdf, 0x2a /* ....* */ }; static const unsigned char pkt31[] = { -0x42, 0x88, 0x00, -0x37, 0x23, 0x41, 0x2e, 0xa1, /* B..7#A.. */ -0xbf, 0x02, 0x2e, 0x57, 0x80, 0x08, 0x18, 0x41, /* ...W...A */ -0x2e, 0xa1, 0xbf, 0x05, 0x27, 0x30, 0x1e, 0x0e, /* ....'0.. */ -0x55, 0x7e, 0xef, 0xff, 0xaf, 0x02, 0xef, 0xff, /* U~...... */ -0xaf, 0x00, 0xef, 0xff, 0xaf, 0xff, 0xef, 0x1f, /* ........ */ -0xff, 0x1a, 0x27, 0x07, 0x27, 0xff, 0xaf, 0xff, /* ..'.'... */ -0xbf, 0x00, 0x2e, 0xa7, 0x8a, 0x05, 0x27, 0xf7, /* ......'. */ -0x74, 0xc9, 0xcf, 0xf3, 0x1c, 0x04, 0x18, 0xc9, /* t....... */ -0xaf, 0x23, 0x81, 0x10, 0xff, 0xff, 0xef, 0xc1, /* .#...... */ -0x2e, 0x7c, 0xbf, 0x41, 0x2e, 0x7b, 0xbf, 0x02, /* .|.A.{.. */ -0xef, 0x41, 0x2e, 0x7a, 0xbf, 0xc9, 0x31, 0x18, /* .A.z..1. */ -0xef, 0xc0, 0xaf, 0x04, 0x27, 0x41, 0x2e, 0x7a, /* ....'A.z */ -0xdf, 0xdf, 0x2d, 0x08, 0x5b, 0x01, 0xef, 0x41, /* ..-.[..A */ -0x2e, 0x7a, 0xbf, 0xc0, 0x23, 0x18, 0xef, 0xc1, /* .z..#... */ -0xaf, 0xcb, 0xcf, 0xcc, 0xdf, 0x05, 0x27, 0xc9, /* ......'. */ -0x30, 0x01, 0xef, 0x41, 0x2e, 0x7a, 0xbf, 0xc0, /* 0..A.z.. */ -0x23, 0x18, 0xef, 0xc1, 0xaf, 0x9f, 0x22, 0xbf, /* #.....". */ -0x22, 0x05, 0x27 /* ".' */ + 0x42, 0x88, 0x00, + 0x37, 0x23, 0x41, 0x2e, 0xa1, /* B..7#A.. */ + 0xbf, 0x02, 0x2e, 0x57, 0x80, 0x08, 0x18, 0x41, /* ...W...A */ + 0x2e, 0xa1, 0xbf, 0x05, 0x27, 0x30, 0x1e, 0x0e, /* ....'0.. */ + 0x55, 0x7e, 0xef, 0xff, 0xaf, 0x02, 0xef, 0xff, /* U~...... */ + 0xaf, 0x00, 0xef, 0xff, 0xaf, 0xff, 0xef, 0x1f, /* ........ */ + 0xff, 0x1a, 0x27, 0x07, 0x27, 0xff, 0xaf, 0xff, /* ..'.'... */ + 0xbf, 0x00, 0x2e, 0xa7, 0x8a, 0x05, 0x27, 0xf7, /* ......'. */ + 0x74, 0xc9, 0xcf, 0xf3, 0x1c, 0x04, 0x18, 0xc9, /* t....... */ + 0xaf, 0x23, 0x81, 0x10, 0xff, 0xff, 0xef, 0xc1, /* .#...... */ + 0x2e, 0x7c, 0xbf, 0x41, 0x2e, 0x7b, 0xbf, 0x02, /* .|.A.{.. */ + 0xef, 0x41, 0x2e, 0x7a, 0xbf, 0xc9, 0x31, 0x18, /* .A.z..1. */ + 0xef, 0xc0, 0xaf, 0x04, 0x27, 0x41, 0x2e, 0x7a, /* ....'A.z */ + 0xdf, 0xdf, 0x2d, 0x08, 0x5b, 0x01, 0xef, 0x41, /* ..-.[..A */ + 0x2e, 0x7a, 0xbf, 0xc0, 0x23, 0x18, 0xef, 0xc1, /* .z..#... */ + 0xaf, 0xcb, 0xcf, 0xcc, 0xdf, 0x05, 0x27, 0xc9, /* ......'. */ + 0x30, 0x01, 0xef, 0x41, 0x2e, 0x7a, 0xbf, 0xc0, /* 0..A.z.. */ + 0x23, 0x18, 0xef, 0xc1, 0xaf, 0x9f, 0x22, 0xbf, /* #.....". */ + 0x22, 0x05, 0x27 /* ".' */ }; static const unsigned char pkt33[] = { -0x42, 0xca, 0x00, -0x7a, 0x23, 0x9b, 0x22, 0xff, /* B..z#.". */ -0x86, 0x02, 0x2e, 0x96, 0x83, 0xc2, 0x85, 0x00, /* ........ */ -0xef, 0x41, 0x2e, 0x76, 0xbf, 0x56, 0x87, 0x02, /* .A.v.V.. */ -0x2e, 0xed, 0x83, 0x78, 0x86, 0x02, 0x33, 0x07, /* ...x..3. */ -0x80, 0xdd, 0x97, 0xff, 0xaf, 0x00, 0x2e, 0xa7, /* ........ */ -0x8a, 0x05, 0x27, 0x6c, 0xcf, 0x6d, 0xdf, 0xbf, /* ..'l.m.. */ -0x01, 0x6c, 0xaf, 0x6d, 0x26, 0x00, 0x2e, 0x2c, /* .l.m&.., */ -0x55, 0x00, 0x2e, 0x47, 0x50, 0x9f, 0x22, 0x6b, /* U..GP."k */ -0xaf, 0x62, 0xaf, 0x6d, 0x2e, 0x6a, 0xbf, 0x01, /* .b.m.j.. */ -0x2e, 0x3f, 0x84, 0x00, 0xef, 0x41, 0x2e, 0x44, /* .?...A.D */ -0xbf, 0xbf, 0xef, 0x41, 0x2e, 0x45, 0xbf, 0x80, /* ...A.E.. */ -0xef, 0x0a, 0xaf, 0x01, 0x2e, 0x06, 0x82, 0x80, /* ........ */ -0x82, 0x84, 0x82, 0x6b, 0xcf, 0x10, 0xaf, 0x01, /* ...k.... */ -0x2e, 0x94, 0x86, 0x40, 0xef, 0x6d, 0xaf, 0x80, /* ...@.m.. */ -0xef, 0x6c, 0xaf, 0x01, 0x2e, 0xf9, 0x81, 0xed, /* .l...... */ -0x80, 0x01, 0x2e, 0x18, 0x87, 0x01, 0x2e, 0x1a, /* ........ */ -0x87, 0x07, 0x87, 0xff, 0x2f, 0xd1, 0x5a, 0x6c, /* ..../.Zl */ -0xcf, 0x6d, 0xdf, 0x3f, 0x00, 0x6c, 0xaf, 0x6d, /* .m.?.l.m */ -0x26, 0x03, 0x54, 0x6d, 0xdf, 0x0c, 0x82, 0x6d, /* &.Tm...m */ -0xbf, 0xeb, 0x50, 0x6b, 0xcf, 0x08, 0x1e, 0x11, /* ..Pk.... */ -0x5f, 0x6c, 0x24, 0x02, 0x53, 0xff, 0xef, 0x6c, /* _l$.S..l */ -0xaf, 0x10, 0x50, 0x6c, 0x24, 0x02, 0x53, 0xff, /* ..Pl$.S. */ -0xef, 0x6c, 0xaf, 0x0b, 0x50, 0x6b, 0xcf, 0x0a, /* .l..Pk.. */ -0x1e, 0x08, 0x55, 0x6c, 0x24, 0x02, 0x53, 0xff, /* ..Ul$.S. */ -0xef, 0x6c, 0xaf, 0x03, 0x50, 0x6c, 0x24, 0x01, /* .l..Pl$. */ -0x53, 0xff, 0xef, 0x6c, 0xaf /* S..l. */ + 0x42, 0xca, 0x00, + 0x7a, 0x23, 0x9b, 0x22, 0xff, /* B..z#.". */ + 0x86, 0x02, 0x2e, 0x96, 0x83, 0xc2, 0x85, 0x00, /* ........ */ + 0xef, 0x41, 0x2e, 0x76, 0xbf, 0x56, 0x87, 0x02, /* .A.v.V.. */ + 0x2e, 0xed, 0x83, 0x78, 0x86, 0x02, 0x33, 0x07, /* ...x..3. */ + 0x80, 0xdd, 0x97, 0xff, 0xaf, 0x00, 0x2e, 0xa7, /* ........ */ + 0x8a, 0x05, 0x27, 0x6c, 0xcf, 0x6d, 0xdf, 0xbf, /* ..'l.m.. */ + 0x01, 0x6c, 0xaf, 0x6d, 0x26, 0x00, 0x2e, 0x2c, /* .l.m&.., */ + 0x55, 0x00, 0x2e, 0x47, 0x50, 0x9f, 0x22, 0x6b, /* U..GP."k */ + 0xaf, 0x62, 0xaf, 0x6d, 0x2e, 0x6a, 0xbf, 0x01, /* .b.m.j.. */ + 0x2e, 0x3f, 0x84, 0x00, 0xef, 0x41, 0x2e, 0x44, /* .?...A.D */ + 0xbf, 0xbf, 0xef, 0x41, 0x2e, 0x45, 0xbf, 0x80, /* ...A.E.. */ + 0xef, 0x0a, 0xaf, 0x01, 0x2e, 0x06, 0x82, 0x80, /* ........ */ + 0x82, 0x84, 0x82, 0x6b, 0xcf, 0x10, 0xaf, 0x01, /* ...k.... */ + 0x2e, 0x94, 0x86, 0x40, 0xef, 0x6d, 0xaf, 0x80, /* ...@.m.. */ + 0xef, 0x6c, 0xaf, 0x01, 0x2e, 0xf9, 0x81, 0xed, /* .l...... */ + 0x80, 0x01, 0x2e, 0x18, 0x87, 0x01, 0x2e, 0x1a, /* ........ */ + 0x87, 0x07, 0x87, 0xff, 0x2f, 0xd1, 0x5a, 0x6c, /* ..../.Zl */ + 0xcf, 0x6d, 0xdf, 0x3f, 0x00, 0x6c, 0xaf, 0x6d, /* .m.?.l.m */ + 0x26, 0x03, 0x54, 0x6d, 0xdf, 0x0c, 0x82, 0x6d, /* &.Tm...m */ + 0xbf, 0xeb, 0x50, 0x6b, 0xcf, 0x08, 0x1e, 0x11, /* ..Pk.... */ + 0x5f, 0x6c, 0x24, 0x02, 0x53, 0xff, 0xef, 0x6c, /* _l$.S..l */ + 0xaf, 0x10, 0x50, 0x6c, 0x24, 0x02, 0x53, 0xff, /* ..Pl$.S. */ + 0xef, 0x6c, 0xaf, 0x0b, 0x50, 0x6b, 0xcf, 0x0a, /* .l..Pk.. */ + 0x1e, 0x08, 0x55, 0x6c, 0x24, 0x02, 0x53, 0xff, /* ..Ul$.S. */ + 0xef, 0x6c, 0xaf, 0x03, 0x50, 0x6c, 0x24, 0x01, /* .l..Pl$. */ + 0x53, 0xff, 0xef, 0x6c, 0xaf /* S..l. */ }; static const unsigned char pkt35[] = { -0x42, 0xca, 0x00, -0xde, 0x23, 0x6b, 0xcf, 0xdf, /* B...#k.. */ -0x96, 0xb0, 0xef, 0x00, 0xff, 0x1d, 0x00, 0x00, /* ........ */ -0x13, 0x1b, 0x27, 0x6c, 0xcf, 0x9f, 0x9d, 0x6b, /* ..'l...k */ -0xcf, 0x1f, 0x20, 0x6b, 0xaf, 0x0a, 0x1e, 0xbc, /* .. k.... */ -0x5f, 0x05, 0x27, 0x01, 0x2e, 0x3f, 0x84, 0x55, /* _.'..?.U */ -0x82, 0x01, 0x2e, 0x06, 0x82, 0x73, 0x23, 0x0a, /* .....s#. */ -0xef, 0x10, 0xaf, 0x01, 0x2e, 0x94, 0x86, 0x80, /* ........ */ -0xef, 0x01, 0x2e, 0xf9, 0x81, 0xed, 0x80, 0x08, /* ........ */ -0xef, 0x06, 0xaf, 0x01, 0x2e, 0x18, 0x87, 0x01, /* ........ */ -0x2e, 0x1a, 0x87, 0x06, 0x25, 0xf9, 0x55, 0x02, /* ....%.U. */ -0x2e, 0x52, 0x84, 0x4e, 0x23, 0x40, 0xcf, 0xe0, /* .R.N#@.. */ -0xaf, 0x41, 0xdf, 0xe1, 0xbf, 0x41, 0x2e, 0x4e, /* .A...A.N */ -0xdf, 0xf7, 0x1c, 0x41, 0x2e, 0x4e, 0xbf, 0x01, /* ...A.N.. */ -0x2e, 0x18, 0x87, 0x01, 0x2e, 0x1a, 0x87, 0x45, /* .......E */ -0x82, 0x4e, 0x24, 0x4e, 0xcf, 0x20, 0x1e, 0x03, /* .N$N. .. */ -0x55, 0x01, 0xef, 0x1f, 0x90, 0x02, 0x2e, 0x87, /* U....... */ -0x73, 0x40, 0x2e, 0x8f, 0xdf, 0xdf, 0x22, 0xe5, /* s@....". */ -0x55, 0x4e, 0x86, 0x4e, 0x23, 0x4e, 0xcf, 0x52, /* UN.N#N.R */ -0x86, 0x59, 0x86, 0x3f, 0x9f, 0x4e, 0xcf, 0x52, /* .Y.?.N.R */ -0x86, 0x5f, 0x86, 0x1f, 0x9f, 0x4e, 0x24, 0x4e, /* ._...N$N */ -0xcf, 0x04, 0x1e, 0xf3, 0x55, 0xf8, 0x0f, 0x08, /* ....U... */ -0xef, 0x06, 0xaf, 0xf6, 0x97, 0xbc, 0x03, 0x01, /* ........ */ -0x5f, 0xff, 0x0f, 0xfc, 0x97, 0x06, 0x25, 0xf9, /* _.....%. */ -0x55, 0xf8, 0x0f, 0x08, 0xff, 0x06, 0xbf, 0xf6, /* U....... */ -0x9f, 0xdf, 0x01, 0xa1, 0x27, 0x7f, 0x21, 0x3f, /* ....'.!? */ -0x9f, 0x06, 0x25, 0xf8, 0x55 /* ..%.U */ + 0x42, 0xca, 0x00, + 0xde, 0x23, 0x6b, 0xcf, 0xdf, /* B...#k.. */ + 0x96, 0xb0, 0xef, 0x00, 0xff, 0x1d, 0x00, 0x00, /* ........ */ + 0x13, 0x1b, 0x27, 0x6c, 0xcf, 0x9f, 0x9d, 0x6b, /* ..'l...k */ + 0xcf, 0x1f, 0x20, 0x6b, 0xaf, 0x0a, 0x1e, 0xbc, /* .. k.... */ + 0x5f, 0x05, 0x27, 0x01, 0x2e, 0x3f, 0x84, 0x55, /* _.'..?.U */ + 0x82, 0x01, 0x2e, 0x06, 0x82, 0x73, 0x23, 0x0a, /* .....s#. */ + 0xef, 0x10, 0xaf, 0x01, 0x2e, 0x94, 0x86, 0x80, /* ........ */ + 0xef, 0x01, 0x2e, 0xf9, 0x81, 0xed, 0x80, 0x08, /* ........ */ + 0xef, 0x06, 0xaf, 0x01, 0x2e, 0x18, 0x87, 0x01, /* ........ */ + 0x2e, 0x1a, 0x87, 0x06, 0x25, 0xf9, 0x55, 0x02, /* ....%.U. */ + 0x2e, 0x52, 0x84, 0x4e, 0x23, 0x40, 0xcf, 0xe0, /* .R.N#@.. */ + 0xaf, 0x41, 0xdf, 0xe1, 0xbf, 0x41, 0x2e, 0x4e, /* .A...A.N */ + 0xdf, 0xf7, 0x1c, 0x41, 0x2e, 0x4e, 0xbf, 0x01, /* ...A.N.. */ + 0x2e, 0x18, 0x87, 0x01, 0x2e, 0x1a, 0x87, 0x45, /* .......E */ + 0x82, 0x4e, 0x24, 0x4e, 0xcf, 0x20, 0x1e, 0x03, /* .N$N. .. */ + 0x55, 0x01, 0xef, 0x1f, 0x90, 0x02, 0x2e, 0x87, /* U....... */ + 0x73, 0x40, 0x2e, 0x8f, 0xdf, 0xdf, 0x22, 0xe5, /* s@....". */ + 0x55, 0x4e, 0x86, 0x4e, 0x23, 0x4e, 0xcf, 0x52, /* UN.N#N.R */ + 0x86, 0x59, 0x86, 0x3f, 0x9f, 0x4e, 0xcf, 0x52, /* .Y.?.N.R */ + 0x86, 0x5f, 0x86, 0x1f, 0x9f, 0x4e, 0x24, 0x4e, /* ._...N$N */ + 0xcf, 0x04, 0x1e, 0xf3, 0x55, 0xf8, 0x0f, 0x08, /* ....U... */ + 0xef, 0x06, 0xaf, 0xf6, 0x97, 0xbc, 0x03, 0x01, /* ........ */ + 0x5f, 0xff, 0x0f, 0xfc, 0x97, 0x06, 0x25, 0xf9, /* _.....%. */ + 0x55, 0xf8, 0x0f, 0x08, 0xff, 0x06, 0xbf, 0xf6, /* U....... */ + 0x9f, 0xdf, 0x01, 0xa1, 0x27, 0x7f, 0x21, 0x3f, /* ....'.!? */ + 0x9f, 0x06, 0x25, 0xf8, 0x55 /* ..%.U */ }; static const unsigned char pkt37[] = { -0x42, 0xb2, 0x00, -0x42, 0x24, 0xf8, 0x0f, 0x04, /* B..B$... */ -0xef, 0x06, 0xaf, 0xbb, 0xef, 0x00, 0xff, 0x1a, /* ........ */ -0x27, 0xfc, 0x9f, 0xfc, 0x97, 0x09, 0x27, 0x5f, /* '.....'_ */ -0x02, 0x3f, 0x97, 0x06, 0x25, 0xf8, 0x55, 0x81, /* .?..%.U. */ -0xcf, 0x24, 0xaf, 0x05, 0x27, 0x0a, 0xef, 0x73, /* .$..'..s */ -0x43, 0x02, 0x5b, 0x73, 0xcf, 0x09, 0x27, 0x0f, /* C.[s..'. */ -0x1c, 0x81, 0xaf, 0x73, 0xcf, 0x09, 0x27, 0x30, /* ...s..'0 */ -0x1c, 0xfc, 0xdf, 0xcf, 0x1d, 0x5f, 0x02, 0xfc, /* ....._.. */ -0xbf, 0x81, 0xcf, 0x10, 0xaf, 0x01, 0x2e, 0x94, /* ........ */ -0x86, 0x80, 0x82, 0x01, 0x2e, 0x34, 0x81, 0x40, /* .....4.@ */ -0xef, 0x6b, 0xaf, 0x80, 0xef, 0x82, 0xaf, 0x01, /* .k...... */ -0x2e, 0xf9, 0x81, 0xed, 0x80, 0x01, 0x2e, 0x18, /* ........ */ -0x87, 0x01, 0x2e, 0x1a, 0x87, 0x16, 0x82, 0x01, /* ........ */ -0x2e, 0x2f, 0x89, 0x0a, 0x5b, 0x73, 0x43, 0x19, /* ./..[sC. */ -0x5a, 0x81, 0xcf, 0x5e, 0xdf, 0xbf, 0x03, 0x15, /* Z..^.... */ -0x5f, 0x5f, 0x20, 0x81, 0xaf, 0xdf, 0x22, 0x11, /* __ ...". */ -0x54, 0xde, 0x50, 0x40, 0x2e, 0x8f, 0xdf, 0x1f, /* T.P@.... */ -0x2c, 0x00, 0x2e, 0x0c, 0x5a, 0x5f, 0x2c, 0x09, /* ,...Z_,. */ -0x5b, 0x82, 0xcf, 0x6b, 0xdf, 0x3f, 0x00, 0x82, /* [..k.?.. */ -0xaf, 0x6b, 0x26, 0xe7, 0x54, 0x6b, 0xdf, 0x0c, /* .k&.Tk.. */ -0x82, 0x6b, 0xbf, 0xd8, 0x50, 0x05, 0x27, 0x82, /* .k..P.'. */ -0xcf, 0x6b, 0xdf, 0xbf, 0x01, 0x82, 0xaf, 0x6b, /* .k.....k */ -0x26, 0xf4, 0x55, 0xdb, 0x50 /* &.U.P */ + 0x42, 0xb2, 0x00, + 0x42, 0x24, 0xf8, 0x0f, 0x04, /* B..B$... */ + 0xef, 0x06, 0xaf, 0xbb, 0xef, 0x00, 0xff, 0x1a, /* ........ */ + 0x27, 0xfc, 0x9f, 0xfc, 0x97, 0x09, 0x27, 0x5f, /* '.....'_ */ + 0x02, 0x3f, 0x97, 0x06, 0x25, 0xf8, 0x55, 0x81, /* .?..%.U. */ + 0xcf, 0x24, 0xaf, 0x05, 0x27, 0x0a, 0xef, 0x73, /* .$..'..s */ + 0x43, 0x02, 0x5b, 0x73, 0xcf, 0x09, 0x27, 0x0f, /* C.[s..'. */ + 0x1c, 0x81, 0xaf, 0x73, 0xcf, 0x09, 0x27, 0x30, /* ...s..'0 */ + 0x1c, 0xfc, 0xdf, 0xcf, 0x1d, 0x5f, 0x02, 0xfc, /* ....._.. */ + 0xbf, 0x81, 0xcf, 0x10, 0xaf, 0x01, 0x2e, 0x94, /* ........ */ + 0x86, 0x80, 0x82, 0x01, 0x2e, 0x34, 0x81, 0x40, /* .....4.@ */ + 0xef, 0x6b, 0xaf, 0x80, 0xef, 0x82, 0xaf, 0x01, /* .k...... */ + 0x2e, 0xf9, 0x81, 0xed, 0x80, 0x01, 0x2e, 0x18, /* ........ */ + 0x87, 0x01, 0x2e, 0x1a, 0x87, 0x16, 0x82, 0x01, /* ........ */ + 0x2e, 0x2f, 0x89, 0x0a, 0x5b, 0x73, 0x43, 0x19, /* ./..[sC. */ + 0x5a, 0x81, 0xcf, 0x5e, 0xdf, 0xbf, 0x03, 0x15, /* Z..^.... */ + 0x5f, 0x5f, 0x20, 0x81, 0xaf, 0xdf, 0x22, 0x11, /* __ ...". */ + 0x54, 0xde, 0x50, 0x40, 0x2e, 0x8f, 0xdf, 0x1f, /* T.P@.... */ + 0x2c, 0x00, 0x2e, 0x0c, 0x5a, 0x5f, 0x2c, 0x09, /* ,...Z_,. */ + 0x5b, 0x82, 0xcf, 0x6b, 0xdf, 0x3f, 0x00, 0x82, /* [..k.?.. */ + 0xaf, 0x6b, 0x26, 0xe7, 0x54, 0x6b, 0xdf, 0x0c, /* .k&.Tk.. */ + 0x82, 0x6b, 0xbf, 0xd8, 0x50, 0x05, 0x27, 0x82, /* .k..P.'. */ + 0xcf, 0x6b, 0xdf, 0xbf, 0x01, 0x82, 0xaf, 0x6b, /* .k.....k */ + 0x26, 0xf4, 0x55, 0xdb, 0x50 /* &.U.P */ }; static const unsigned char pkt39[] = { -0x42, 0xca, 0x00, -0x9a, 0x24, 0xfa, 0xcf, 0xdf, /* B...$... */ -0x96, 0x37, 0xcf, 0xdf, 0x96, 0x08, 0xcf, 0xdf, /* .7...... */ -0x96, 0x3d, 0xcf, 0xdf, 0x96, 0x77, 0xcf, 0xdf, /* .=...w.. */ -0x96, 0x01, 0x2e, 0x08, 0x82, 0xdd, 0x97, 0x77, /* .......w */ -0xaf, 0xdd, 0x97, 0x3d, 0xaf, 0xdd, 0x97, 0x08, /* ...=.... */ -0xaf, 0xdd, 0x97, 0x37, 0xaf, 0xdd, 0x97, 0xfa, /* ...7.... */ -0xaf, 0x9f, 0x22, 0x6d, 0x2e, 0x6d, 0xbf, 0xfb, /* .."m.m.. */ -0x39, 0x08, 0x45, 0x00, 0x5a, 0xfb, 0x31, 0x0a, /* 9.E.Z.1. */ -0x42, 0x00, 0x5b, 0xa2, 0x39, 0x02, 0xcf, 0x5c, /* B.[.9..\ */ -0xaf, 0xe1, 0xef, 0x95, 0xaf, 0x9f, 0x22, 0x61, /* ......"a */ -0xaf, 0x62, 0xaf, 0x69, 0xaf, 0x6a, 0xaf, 0x16, /* .b.i.j.. */ -0xaf, 0x96, 0xaf, 0x29, 0xaf, 0x28, 0xaf, 0xc1, /* ...).(.. */ -0x2e, 0x49, 0xdf, 0x3f, 0x2d, 0x03, 0x5b, 0xa0, /* .I.?-.[. */ -0xcf, 0x8f, 0x1c, 0x20, 0x18, 0xa0, 0xaf, 0xa1, /* ... .... */ -0xcf, 0xdf, 0x1c, 0xa1, 0xaf, 0xed, 0x80, 0x02, /* ........ */ -0x47, 0x06, 0x5a, 0x0a, 0x41, 0x04, 0x5a, 0x0a, /* G.Z.A.Z. */ -0xdf, 0x30, 0x1d, 0x30, 0x1f, 0x00, 0x54, 0x01, /* .0.0..T. */ -0xef, 0x44, 0xaf, 0x09, 0xef, 0x60, 0xaf, 0xa7, /* .D...`.. */ -0xef, 0x40, 0xaf, 0x2d, 0xef, 0x41, 0xaf, 0x0a, /* .@.-.A.. */ -0x40, 0x06, 0x5a, 0x10, 0xcf, 0x27, 0xaf, 0xe2, /* @.Z..'.. */ -0x23, 0x6e, 0x23, 0x08, 0xef, 0xe3, 0xaf, 0x6f, /* #n#....o */ -0xaf, 0xe2, 0x23, 0x08, 0xef, 0xe3, 0xaf, 0x79, /* ..#....y */ -0x82, 0x4d, 0xaf, 0xdf, 0x96, 0x64, 0xdf, 0x8b, /* .M...d.. */ -0x82, 0x93, 0xbf, 0xdd, 0x97, 0x77, 0xff, 0x8b, /* .....w.. */ -0x82, 0x94, 0xbf, 0x9e, 0x23, 0xe4, 0x23, 0x9f, /* ....#.#. */ -0x22, 0x6d, 0x2e, 0x6b, 0xbf /* "m.k. */ + 0x42, 0xca, 0x00, + 0x9a, 0x24, 0xfa, 0xcf, 0xdf, /* B...$... */ + 0x96, 0x37, 0xcf, 0xdf, 0x96, 0x08, 0xcf, 0xdf, /* .7...... */ + 0x96, 0x3d, 0xcf, 0xdf, 0x96, 0x77, 0xcf, 0xdf, /* .=...w.. */ + 0x96, 0x01, 0x2e, 0x08, 0x82, 0xdd, 0x97, 0x77, /* .......w */ + 0xaf, 0xdd, 0x97, 0x3d, 0xaf, 0xdd, 0x97, 0x08, /* ...=.... */ + 0xaf, 0xdd, 0x97, 0x37, 0xaf, 0xdd, 0x97, 0xfa, /* ...7.... */ + 0xaf, 0x9f, 0x22, 0x6d, 0x2e, 0x6d, 0xbf, 0xfb, /* .."m.m.. */ + 0x39, 0x08, 0x45, 0x00, 0x5a, 0xfb, 0x31, 0x0a, /* 9.E.Z.1. */ + 0x42, 0x00, 0x5b, 0xa2, 0x39, 0x02, 0xcf, 0x5c, /* B.[.9..\ */ + 0xaf, 0xe1, 0xef, 0x95, 0xaf, 0x9f, 0x22, 0x61, /* ......"a */ + 0xaf, 0x62, 0xaf, 0x69, 0xaf, 0x6a, 0xaf, 0x16, /* .b.i.j.. */ + 0xaf, 0x96, 0xaf, 0x29, 0xaf, 0x28, 0xaf, 0xc1, /* ...).(.. */ + 0x2e, 0x49, 0xdf, 0x3f, 0x2d, 0x03, 0x5b, 0xa0, /* .I.?-.[. */ + 0xcf, 0x8f, 0x1c, 0x20, 0x18, 0xa0, 0xaf, 0xa1, /* ... .... */ + 0xcf, 0xdf, 0x1c, 0xa1, 0xaf, 0xed, 0x80, 0x02, /* ........ */ + 0x47, 0x06, 0x5a, 0x0a, 0x41, 0x04, 0x5a, 0x0a, /* G.Z.A.Z. */ + 0xdf, 0x30, 0x1d, 0x30, 0x1f, 0x00, 0x54, 0x01, /* .0.0..T. */ + 0xef, 0x44, 0xaf, 0x09, 0xef, 0x60, 0xaf, 0xa7, /* .D...`.. */ + 0xef, 0x40, 0xaf, 0x2d, 0xef, 0x41, 0xaf, 0x0a, /* .@.-.A.. */ + 0x40, 0x06, 0x5a, 0x10, 0xcf, 0x27, 0xaf, 0xe2, /* @.Z..'.. */ + 0x23, 0x6e, 0x23, 0x08, 0xef, 0xe3, 0xaf, 0x6f, /* #n#....o */ + 0xaf, 0xe2, 0x23, 0x08, 0xef, 0xe3, 0xaf, 0x79, /* ..#....y */ + 0x82, 0x4d, 0xaf, 0xdf, 0x96, 0x64, 0xdf, 0x8b, /* .M...d.. */ + 0x82, 0x93, 0xbf, 0xdd, 0x97, 0x77, 0xff, 0x8b, /* .....w.. */ + 0x82, 0x94, 0xbf, 0x9e, 0x23, 0xe4, 0x23, 0x9f, /* ....#.#. */ + 0x22, 0x6d, 0x2e, 0x6b, 0xbf /* "m.k. */ }; static const unsigned char pkt41[] = { -0x42, 0x12, 0x00, -0xfe, 0x24, 0x6d, 0x2e, 0x6a, /* B...$m.j */ -0xbf, 0x6d, 0x2e, 0x6c, 0xbf, 0xa5, 0xcf, 0xf3, /* .m.l.... */ -0x1c, 0xa5, 0xaf, 0x05, 0x27 /* ....' */ + 0x42, 0x12, 0x00, + 0xfe, 0x24, 0x6d, 0x2e, 0x6a, /* B...$m.j */ + 0xbf, 0x6d, 0x2e, 0x6c, 0xbf, 0xa5, 0xcf, 0xf3, /* .m.l.... */ + 0x1c, 0xa5, 0xaf, 0x05, 0x27 /* ....' */ }; static const unsigned char pkt43[] = { -0x42, 0xca, 0x00, -0x06, 0x25, 0xfe, 0xcf, 0x58, /* B...%..X */ -0xaf, 0xfe, 0xcf, 0xfe, 0xdf, 0x02, 0x2e, 0x9d, /* ........ */ -0x85, 0xfe, 0xcf, 0x3c, 0xaf, 0x07, 0x3d, 0x58, /* ...<..=X */ -0x40, 0x4e, 0x5a, 0x3c, 0x26, 0x4c, 0x55, 0x37, /* @NZ<&LU7 */ -0x45, 0x4a, 0x5a, 0x02, 0x2e, 0x1b, 0x86, 0x47, /* EJZ....G */ -0x5a, 0x02, 0x2e, 0xad, 0x85, 0x00, 0x2e, 0xb9, /* Z....... */ -0x8d, 0xfe, 0xef, 0x16, 0x80, 0x02, 0xcf, 0xdf, /* ........ */ -0x96, 0x61, 0xef, 0xc0, 0xaf, 0x04, 0x27, 0xc1, /* .a....'. */ -0x46, 0x04, 0x5b, 0xc0, 0x3e, 0x40, 0xef, 0xc1, /* F.[.>@.. */ -0xaf, 0x01, 0x2e, 0x8d, 0x8b, 0xd0, 0x41, 0x07, /* ......A. */ -0x5b, 0x02, 0x2e, 0x5d, 0x85, 0xf2, 0x5b, 0xae, /* [..]..[. */ -0x87, 0xdd, 0x97, 0x1f, 0x2d, 0x06, 0x5b, 0x03, /* ....-.[. */ -0x50, 0x01, 0x0c, 0x02, 0xcf, 0xc0, 0x1c, 0x01, /* P....... */ -0x55, 0x02, 0x2e, 0x40, 0x85, 0xc0, 0x23, 0x20, /* U..@..# */ -0xef, 0xc1, 0xaf, 0x00, 0x2e, 0xd8, 0x8d, 0x05, /* ........ */ -0x27, 0x9b, 0x22, 0x37, 0x45, 0x05, 0x5a, 0x41, /* '."7E.ZA */ -0x2e, 0x52, 0xdf, 0xdf, 0x2d, 0x04, 0x5b, 0x00, /* .R..-.[. */ -0x28, 0x02, 0x50, 0x3b, 0x43, 0x00, 0x5b, 0x00, /* (.P;C.[. */ -0x28, 0xd3, 0xdf, 0xc6, 0x2e, 0x15, 0xbf, 0xd3, /* (....... */ -0x3c, 0x40, 0xef, 0x09, 0x80, 0xdd, 0x97, 0xff, /* <@...... */ -0xaf, 0x00, 0x2e, 0xa7, 0x8a, 0xc6, 0x2e, 0x15, /* ........ */ -0xdf, 0x10, 0x1d, 0xd3, 0xcf, 0x3f, 0x02, 0xd3, /* .....?.. */ -0xaf, 0x05, 0x27, 0xed, 0x83, 0x07, 0x45, 0x05, /* ..'...E. */ -0x27, 0x3d, 0x23, 0x07, 0x3d, 0x02, 0xcf, 0xdf, /* '=#.=... */ -0x96, 0x02, 0x2e, 0xad, 0x85, 0x02, 0x2e, 0x96, /* ........ */ -0x85, 0xfe, 0xef, 0x16, 0x80 /* ..... */ + 0x42, 0xca, 0x00, + 0x06, 0x25, 0xfe, 0xcf, 0x58, /* B...%..X */ + 0xaf, 0xfe, 0xcf, 0xfe, 0xdf, 0x02, 0x2e, 0x9d, /* ........ */ + 0x85, 0xfe, 0xcf, 0x3c, 0xaf, 0x07, 0x3d, 0x58, /* ...<..=X */ + 0x40, 0x4e, 0x5a, 0x3c, 0x26, 0x4c, 0x55, 0x37, /* @NZ<&LU7 */ + 0x45, 0x4a, 0x5a, 0x02, 0x2e, 0x1b, 0x86, 0x47, /* EJZ....G */ + 0x5a, 0x02, 0x2e, 0xad, 0x85, 0x00, 0x2e, 0xb9, /* Z....... */ + 0x8d, 0xfe, 0xef, 0x16, 0x80, 0x02, 0xcf, 0xdf, /* ........ */ + 0x96, 0x61, 0xef, 0xc0, 0xaf, 0x04, 0x27, 0xc1, /* .a....'. */ + 0x46, 0x04, 0x5b, 0xc0, 0x3e, 0x40, 0xef, 0xc1, /* F.[.>@.. */ + 0xaf, 0x01, 0x2e, 0x8d, 0x8b, 0xd0, 0x41, 0x07, /* ......A. */ + 0x5b, 0x02, 0x2e, 0x5d, 0x85, 0xf2, 0x5b, 0xae, /* [..]..[. */ + 0x87, 0xdd, 0x97, 0x1f, 0x2d, 0x06, 0x5b, 0x03, /* ....-.[. */ + 0x50, 0x01, 0x0c, 0x02, 0xcf, 0xc0, 0x1c, 0x01, /* P....... */ + 0x55, 0x02, 0x2e, 0x40, 0x85, 0xc0, 0x23, 0x20, /* U..@..# */ + 0xef, 0xc1, 0xaf, 0x00, 0x2e, 0xd8, 0x8d, 0x05, /* ........ */ + 0x27, 0x9b, 0x22, 0x37, 0x45, 0x05, 0x5a, 0x41, /* '."7E.ZA */ + 0x2e, 0x52, 0xdf, 0xdf, 0x2d, 0x04, 0x5b, 0x00, /* .R..-.[. */ + 0x28, 0x02, 0x50, 0x3b, 0x43, 0x00, 0x5b, 0x00, /* (.P;C.[. */ + 0x28, 0xd3, 0xdf, 0xc6, 0x2e, 0x15, 0xbf, 0xd3, /* (....... */ + 0x3c, 0x40, 0xef, 0x09, 0x80, 0xdd, 0x97, 0xff, /* <@...... */ + 0xaf, 0x00, 0x2e, 0xa7, 0x8a, 0xc6, 0x2e, 0x15, /* ........ */ + 0xdf, 0x10, 0x1d, 0xd3, 0xcf, 0x3f, 0x02, 0xd3, /* .....?.. */ + 0xaf, 0x05, 0x27, 0xed, 0x83, 0x07, 0x45, 0x05, /* ..'...E. */ + 0x27, 0x3d, 0x23, 0x07, 0x3d, 0x02, 0xcf, 0xdf, /* '=#.=... */ + 0x96, 0x02, 0x2e, 0xad, 0x85, 0x02, 0x2e, 0x96, /* ........ */ + 0x85, 0xfe, 0xef, 0x16, 0x80 /* ..... */ }; static const unsigned char pkt45[] = { -0x42, 0xca, 0x00, -0x6a, 0x25, 0x05, 0xef, 0xc0, /* B..j%... */ -0xaf, 0x04, 0x27, 0xd0, 0x41, 0x03, 0x5b, 0x02, /* ..'.A.[. */ -0x2e, 0x5d, 0x85, 0xf9, 0x5b, 0xbb, 0x50, 0x27, /* .]..[.P' */ -0x82, 0x04, 0xef, 0xc1, 0xaf, 0x9b, 0x22, 0x02, /* ......". */ -0x2e, 0xd1, 0x85, 0xdd, 0x97, 0xdf, 0x22, 0x02, /* ......". */ -0x55, 0x58, 0x40, 0x02, 0x5a, 0x0b, 0x50, 0x58, /* UX@.Z.PX */ -0x40, 0x09, 0x5a, 0xdd, 0x97, 0x1f, 0x2d, 0xb3, /* @.Z...-. */ -0x5a, 0x02, 0x2e, 0x1c, 0x86, 0xb2, 0x5b, 0x9b, /* Z.....[. */ -0x22, 0x02, 0x2e, 0x4c, 0x85, 0xae, 0x50, 0x02, /* "..L..P. */ -0x2e, 0x1c, 0x86, 0xd5, 0x5b, 0x02, 0x2e, 0x40, /* ....[..@ */ -0x85, 0x58, 0x41, 0x02, 0x5b, 0x01, 0x0c, 0x02, /* .XA.[... */ -0x2e, 0x3a, 0x75, 0xcd, 0x50, 0x41, 0x2e, 0x52, /* .:u.PA.R */ -0xdf, 0xed, 0x1c, 0x04, 0x18, 0x41, 0x2e, 0x52, /* .....A.R */ -0xbf, 0x05, 0x27, 0x1a, 0x27, 0x56, 0xdf, 0x59, /* ..'.'V.Y */ -0x80, 0xdf, 0x22, 0x00, 0x54, 0x01, 0x16, 0x3f, /* ..".T..? */ -0x1e, 0x00, 0x5f, 0x3f, 0xef, 0x1f, 0x22, 0x1f, /* .._?..". */ -0x22, 0xaf, 0xdf, 0x03, 0x1d, 0x5f, 0x02, 0xaf, /* "...._.. */ -0xbf, 0x05, 0x27, 0x00, 0x2e, 0xa1, 0x8d, 0xae, /* ..'..... */ -0xdf, 0xe0, 0x19, 0xae, 0xbf, 0x57, 0x40, 0x00, /* .....W@. */ -0x5b, 0xa1, 0x32, 0x57, 0x43, 0x00, 0x5b, 0xae, /* [.2WC.[. */ -0x3f, 0xed, 0x80, 0x05, 0x27, 0x41, 0x2e, 0x52, /* ?...'A.R */ -0xdf, 0x03, 0x18, 0x41, 0x2e, 0x52, 0xbf, 0x05, /* ...A.R.. */ -0x27, 0xd3, 0xdf, 0xff, 0x96, 0x9b, 0x22, 0x02, /* '.....". */ -0x2e, 0xd1, 0x85, 0xd3, 0x3c, 0x07, 0x80, 0xdd, /* ....<... */ -0x97, 0xff, 0xaf, 0x00, 0x2e, 0xa7, 0x8a, 0xdd, /* ........ */ -0x9f, 0x10, 0x1d, 0xd3, 0xcf /* ..... */ + 0x42, 0xca, 0x00, + 0x6a, 0x25, 0x05, 0xef, 0xc0, /* B..j%... */ + 0xaf, 0x04, 0x27, 0xd0, 0x41, 0x03, 0x5b, 0x02, /* ..'.A.[. */ + 0x2e, 0x5d, 0x85, 0xf9, 0x5b, 0xbb, 0x50, 0x27, /* .]..[.P' */ + 0x82, 0x04, 0xef, 0xc1, 0xaf, 0x9b, 0x22, 0x02, /* ......". */ + 0x2e, 0xd1, 0x85, 0xdd, 0x97, 0xdf, 0x22, 0x02, /* ......". */ + 0x55, 0x58, 0x40, 0x02, 0x5a, 0x0b, 0x50, 0x58, /* UX@.Z.PX */ + 0x40, 0x09, 0x5a, 0xdd, 0x97, 0x1f, 0x2d, 0xb3, /* @.Z...-. */ + 0x5a, 0x02, 0x2e, 0x1c, 0x86, 0xb2, 0x5b, 0x9b, /* Z.....[. */ + 0x22, 0x02, 0x2e, 0x4c, 0x85, 0xae, 0x50, 0x02, /* "..L..P. */ + 0x2e, 0x1c, 0x86, 0xd5, 0x5b, 0x02, 0x2e, 0x40, /* ....[..@ */ + 0x85, 0x58, 0x41, 0x02, 0x5b, 0x01, 0x0c, 0x02, /* .XA.[... */ + 0x2e, 0x3a, 0x75, 0xcd, 0x50, 0x41, 0x2e, 0x52, /* .:u.PA.R */ + 0xdf, 0xed, 0x1c, 0x04, 0x18, 0x41, 0x2e, 0x52, /* .....A.R */ + 0xbf, 0x05, 0x27, 0x1a, 0x27, 0x56, 0xdf, 0x59, /* ..'.'V.Y */ + 0x80, 0xdf, 0x22, 0x00, 0x54, 0x01, 0x16, 0x3f, /* ..".T..? */ + 0x1e, 0x00, 0x5f, 0x3f, 0xef, 0x1f, 0x22, 0x1f, /* .._?..". */ + 0x22, 0xaf, 0xdf, 0x03, 0x1d, 0x5f, 0x02, 0xaf, /* "...._.. */ + 0xbf, 0x05, 0x27, 0x00, 0x2e, 0xa1, 0x8d, 0xae, /* ..'..... */ + 0xdf, 0xe0, 0x19, 0xae, 0xbf, 0x57, 0x40, 0x00, /* .....W@. */ + 0x5b, 0xa1, 0x32, 0x57, 0x43, 0x00, 0x5b, 0xae, /* [.2WC.[. */ + 0x3f, 0xed, 0x80, 0x05, 0x27, 0x41, 0x2e, 0x52, /* ?...'A.R */ + 0xdf, 0x03, 0x18, 0x41, 0x2e, 0x52, 0xbf, 0x05, /* ...A.R.. */ + 0x27, 0xd3, 0xdf, 0xff, 0x96, 0x9b, 0x22, 0x02, /* '.....". */ + 0x2e, 0xd1, 0x85, 0xd3, 0x3c, 0x07, 0x80, 0xdd, /* ....<... */ + 0x97, 0xff, 0xaf, 0x00, 0x2e, 0xa7, 0x8a, 0xdd, /* ........ */ + 0x9f, 0x10, 0x1d, 0xd3, 0xcf /* ..... */ }; static const unsigned char pkt47[] = { -0x42, 0xb4, 0x00, -0xce, 0x25, 0x3f, 0x02, 0xd3, /* B...%?.. */ -0xaf, 0x05, 0x27, 0x37, 0x45, 0x10, 0x5a, 0x02, /* ..'7E.Z. */ -0x2e, 0x1b, 0x86, 0x0d, 0x5a, 0x02, 0x2e, 0xad, /* ....Z... */ -0x85, 0x00, 0x2e, 0xbf, 0x8d, 0x00, 0x2e, 0xd3, /* ........ */ -0x8d, 0x41, 0x2e, 0x52, 0xdf, 0xdf, 0x2d, 0x00, /* .A.R..-. */ -0x5b, 0x00, 0x28, 0x00, 0x2e, 0xd8, 0x8d, 0x05, /* [.(..... */ -0x27, 0xf9, 0xcf, 0xdf, 0x96, 0xf9, 0x3d, 0x01, /* '.....=. */ -0x2e, 0x06, 0x82, 0x2d, 0xff, 0xa7, 0xef, 0xe1, /* ...-.... */ -0xbf, 0xe0, 0xaf, 0x09, 0xef, 0x10, 0xaf, 0x01, /* ........ */ -0x2e, 0x94, 0x86, 0xed, 0x80, 0x01, 0x2e, 0x18, /* ........ */ -0x87, 0x01, 0x2e, 0x1a, 0x87, 0x00, 0x2e, 0x16, /* ........ */ -0x82, 0x5b, 0x82, 0x00, 0x2e, 0x2d, 0x82, 0x26, /* .[...-.& */ -0x37, 0x00, 0x5a, 0x0c, 0x50, 0xff, 0x96, 0xdf, /* 7.Z.P... */ -0x96, 0x79, 0xcf, 0x7a, 0xdf, 0xff, 0x96, 0xdf, /* .y.z.... */ -0x96, 0xc2, 0x97, 0xc3, 0x9f, 0x9d, 0x01, 0x5d, /* .......] */ -0x01, 0x07, 0x53, 0xdd, 0x97, 0xdd, 0x9f, 0x79, /* ..S....y */ -0xaf, 0x7a, 0xbf, 0x3b, 0x3b, 0xdd, 0x97, 0xf9, /* .z.;;... */ -0xaf, 0x05, 0x27, 0xff, 0x22, 0x01, 0x55, 0x32, /* ..'.".U2 */ -0x1e, 0xf3, 0x5f, 0x02, 0x0c, 0x02, 0x2e, 0x0e, /* .._..... */ -0x86, 0x3b, 0x33, 0x00, 0x28, 0x05, 0x27, 0x0d, /* .;3.(.'. */ -0x27, 0x3c, 0x26, 0x07, 0x54, 0x3c, 0xcf, 0x3d, /* '<&.T<.= */ -0xdf, 0x3f, 0x20, 0x3d, 0xbf, 0xdf, 0x03, 0x01, /* .? =.... */ -0x52, 0x3d, 0x23, 0x0c, 0x27, 0x0d, 0x27 /* R=#.'.' */ + 0x42, 0xb4, 0x00, + 0xce, 0x25, 0x3f, 0x02, 0xd3, /* B...%?.. */ + 0xaf, 0x05, 0x27, 0x37, 0x45, 0x10, 0x5a, 0x02, /* ..'7E.Z. */ + 0x2e, 0x1b, 0x86, 0x0d, 0x5a, 0x02, 0x2e, 0xad, /* ....Z... */ + 0x85, 0x00, 0x2e, 0xbf, 0x8d, 0x00, 0x2e, 0xd3, /* ........ */ + 0x8d, 0x41, 0x2e, 0x52, 0xdf, 0xdf, 0x2d, 0x00, /* .A.R..-. */ + 0x5b, 0x00, 0x28, 0x00, 0x2e, 0xd8, 0x8d, 0x05, /* [.(..... */ + 0x27, 0xf9, 0xcf, 0xdf, 0x96, 0xf9, 0x3d, 0x01, /* '.....=. */ + 0x2e, 0x06, 0x82, 0x2d, 0xff, 0xa7, 0xef, 0xe1, /* ...-.... */ + 0xbf, 0xe0, 0xaf, 0x09, 0xef, 0x10, 0xaf, 0x01, /* ........ */ + 0x2e, 0x94, 0x86, 0xed, 0x80, 0x01, 0x2e, 0x18, /* ........ */ + 0x87, 0x01, 0x2e, 0x1a, 0x87, 0x00, 0x2e, 0x16, /* ........ */ + 0x82, 0x5b, 0x82, 0x00, 0x2e, 0x2d, 0x82, 0x26, /* .[...-.& */ + 0x37, 0x00, 0x5a, 0x0c, 0x50, 0xff, 0x96, 0xdf, /* 7.Z.P... */ + 0x96, 0x79, 0xcf, 0x7a, 0xdf, 0xff, 0x96, 0xdf, /* .y.z.... */ + 0x96, 0xc2, 0x97, 0xc3, 0x9f, 0x9d, 0x01, 0x5d, /* .......] */ + 0x01, 0x07, 0x53, 0xdd, 0x97, 0xdd, 0x9f, 0x79, /* ..S....y */ + 0xaf, 0x7a, 0xbf, 0x3b, 0x3b, 0xdd, 0x97, 0xf9, /* .z.;;... */ + 0xaf, 0x05, 0x27, 0xff, 0x22, 0x01, 0x55, 0x32, /* ..'.".U2 */ + 0x1e, 0xf3, 0x5f, 0x02, 0x0c, 0x02, 0x2e, 0x0e, /* .._..... */ + 0x86, 0x3b, 0x33, 0x00, 0x28, 0x05, 0x27, 0x0d, /* .;3.(.'. */ + 0x27, 0x3c, 0x26, 0x07, 0x54, 0x3c, 0xcf, 0x3d, /* '<&.T<.= */ + 0xdf, 0x3f, 0x20, 0x3d, 0xbf, 0xdf, 0x03, 0x01, /* .? =.... */ + 0x52, 0x3d, 0x23, 0x0c, 0x27, 0x0d, 0x27 /* R=#.'.' */ }; static const unsigned char pkt49[] = { -0x42, 0x1a, 0x00, -0x27, 0x26, 0x09, 0x43, 0x04, /* B..'&.C. */ -0x5b, 0x00, 0xef, 0xf8, 0xaf, 0x32, 0xef, 0xfa, /* [....2.. */ -0xaf, 0x03, 0x50, 0x01, 0xef, 0xf8, 0xaf, 0x42, /* ..P....B */ -0xef, 0xfa, 0xaf, 0x05, 0x27 /* ....' */ + 0x42, 0x1a, 0x00, + 0x27, 0x26, 0x09, 0x43, 0x04, /* B..'&.C. */ + 0x5b, 0x00, 0xef, 0xf8, 0xaf, 0x32, 0xef, 0xfa, /* [....2.. */ + 0xaf, 0x03, 0x50, 0x01, 0xef, 0xf8, 0xaf, 0x42, /* ..P....B */ + 0xef, 0xfa, 0xaf, 0x05, 0x27 /* ....' */ }; static const unsigned char pkt51[] = { -0x42, 0x26, 0x00, -0x33, 0x26, 0xd3, 0x45, 0xfd, /* B&.3&.E. */ -0x5a, 0x0f, 0x27, 0xd3, 0x45, 0xfa, 0x5a, 0x0f, /* Z.'.E.Z. */ -0x27, 0xd3, 0x45, 0xf7, 0x5a, 0x0f, 0x27, 0x41, /* '.E.Z.'A */ -0x2e, 0xa1, 0xdf, 0x9f, 0x28, 0x41, 0x2e, 0xa1, /* ....(A.. */ -0xbf, 0x02, 0x2e, 0x57, 0x80, 0x00, 0x2e, 0xcb, /* ...W.... */ -0x7a /* z */ + 0x42, 0x26, 0x00, + 0x33, 0x26, 0xd3, 0x45, 0xfd, /* B&.3&.E. */ + 0x5a, 0x0f, 0x27, 0xd3, 0x45, 0xfa, 0x5a, 0x0f, /* Z.'.E.Z. */ + 0x27, 0xd3, 0x45, 0xf7, 0x5a, 0x0f, 0x27, 0x41, /* '.E.Z.'A */ + 0x2e, 0xa1, 0xdf, 0x9f, 0x28, 0x41, 0x2e, 0xa1, /* ....(A.. */ + 0xbf, 0x02, 0x2e, 0x57, 0x80, 0x00, 0x2e, 0xcb, /* ...W.... */ + 0x7a /* z */ }; static const unsigned char pkt53[] = { -0x42, 0x4e, 0x00, -0x45, 0x26, 0x07, 0x3d, 0x02, /* BN.E&.=. */ -0x5b, 0xae, 0x87, 0xc2, 0x23, 0xd3, 0x3c, 0x02, /* [...#.<. */ -0x44, 0xdc, 0x2f, 0x43, 0x5a, 0x02, 0x45, 0xdc, /* D./CZ.E. */ -0x2f, 0xa4, 0x5b, 0x58, 0x23, 0x3c, 0x26, 0x02, /* /.[X#<&. */ -0x55, 0x02, 0x2e, 0x0e, 0x85, 0x00, 0x50, 0x09, /* U.....P. */ -0x8f, 0x07, 0x45, 0xeb, 0x5a, 0x41, 0x2e, 0x53, /* ..E.ZA.S */ -0xdf, 0xc1, 0x2e, 0x79, 0xdf, 0xff, 0x96, 0xdf, /* ...y.... */ -0x96, 0x41, 0x2e, 0x55, 0xdf, 0xc1, 0x2e, 0x78, /* .A.U...x */ -0xdf, 0x9d, 0x01, 0x5d, 0x01, 0xff, 0x22, 0x00, /* ...]..". */ -0x54, 0xff, 0xef, 0x2e, 0xaf, 0xdc, 0x2f, 0x89, /* T...../. */ -0x50 /* P */ + 0x42, 0x4e, 0x00, + 0x45, 0x26, 0x07, 0x3d, 0x02, /* BN.E&.=. */ + 0x5b, 0xae, 0x87, 0xc2, 0x23, 0xd3, 0x3c, 0x02, /* [...#.<. */ + 0x44, 0xdc, 0x2f, 0x43, 0x5a, 0x02, 0x45, 0xdc, /* D./CZ.E. */ + 0x2f, 0xa4, 0x5b, 0x58, 0x23, 0x3c, 0x26, 0x02, /* /.[X#<&. */ + 0x55, 0x02, 0x2e, 0x0e, 0x85, 0x00, 0x50, 0x09, /* U.....P. */ + 0x8f, 0x07, 0x45, 0xeb, 0x5a, 0x41, 0x2e, 0x53, /* ..E.ZA.S */ + 0xdf, 0xc1, 0x2e, 0x79, 0xdf, 0xff, 0x96, 0xdf, /* ...y.... */ + 0x96, 0x41, 0x2e, 0x55, 0xdf, 0xc1, 0x2e, 0x78, /* .A.U...x */ + 0xdf, 0x9d, 0x01, 0x5d, 0x01, 0xff, 0x22, 0x00, /* ...]..". */ + 0x54, 0xff, 0xef, 0x2e, 0xaf, 0xdc, 0x2f, 0x89, /* T...../. */ + 0x50 /* P */ }; static const unsigned char pkt55[] = { -0x42, 0x86, 0x00, -0x6b, 0x26, 0xa5, 0xcf, 0xed, /* B..k&... */ -0x2e, 0x6a, 0xdf, 0xf3, 0x1c, 0x3f, 0x02, 0xa5, /* .j...?.. */ -0xaf, 0x4a, 0xcf, 0xdf, 0x96, 0x10, 0xcf, 0x5f, /* .J....._ */ -0xdf, 0xbf, 0x03, 0x02, 0x5f, 0x5f, 0xcf, 0x10, /* ....__.. */ -0xaf, 0x04, 0x50, 0x5e, 0xdf, 0xbf, 0x03, 0x01, /* ..P^.... */ -0x53, 0x5e, 0xcf, 0x10, 0xaf, 0x01, 0x2e, 0x40, /* S^.....@ */ -0x88, 0x01, 0x2e, 0xe1, 0x86, 0xdd, 0x97, 0x0a, /* ........ */ -0x40, 0x18, 0x5a, 0x62, 0xcf, 0xdf, 0x22, 0x22, /* @.Zb.."" */ -0x54, 0xed, 0x2e, 0x6a, 0xdf, 0x10, 0xef, 0x00, /* T..j.... */ -0x1f, 0x06, 0x54, 0x0c, 0xef, 0x04, 0x1f, 0x03, /* ..T..... */ -0x54, 0x0b, 0xef, 0x08, 0x1f, 0x00, 0x54, 0x05, /* T.....T. */ -0xef, 0x62, 0xdf, 0x76, 0x80, 0x12, 0x82, 0x12, /* .b.v.... */ -0x82, 0x80, 0x10, 0x01, 0x13, 0x4a, 0xcf, 0x3f, /* .....J.? */ -0x00, 0x00, 0x53, 0xff, 0xef, 0x4a, 0xdf, 0xed, /* ..S..J.. */ -0x2e, 0x6e, 0xbf, 0x4a, 0xaf, 0x6d, 0x2e, 0x6f, /* .n.J.m.o */ -0xbf, 0xdf, 0x96, 0xbf, 0x01, 0x6d, 0x2e, 0x6d, /* .....m.m */ -0xbf, 0xdd, 0x97, 0x01, 0x2e, 0xf9, 0x81, 0x05, /* ........ */ -0x27 /* ' */ + 0x42, 0x86, 0x00, + 0x6b, 0x26, 0xa5, 0xcf, 0xed, /* B..k&... */ + 0x2e, 0x6a, 0xdf, 0xf3, 0x1c, 0x3f, 0x02, 0xa5, /* .j...?.. */ + 0xaf, 0x4a, 0xcf, 0xdf, 0x96, 0x10, 0xcf, 0x5f, /* .J....._ */ + 0xdf, 0xbf, 0x03, 0x02, 0x5f, 0x5f, 0xcf, 0x10, /* ....__.. */ + 0xaf, 0x04, 0x50, 0x5e, 0xdf, 0xbf, 0x03, 0x01, /* ..P^.... */ + 0x53, 0x5e, 0xcf, 0x10, 0xaf, 0x01, 0x2e, 0x40, /* S^.....@ */ + 0x88, 0x01, 0x2e, 0xe1, 0x86, 0xdd, 0x97, 0x0a, /* ........ */ + 0x40, 0x18, 0x5a, 0x62, 0xcf, 0xdf, 0x22, 0x22, /* @.Zb.."" */ + 0x54, 0xed, 0x2e, 0x6a, 0xdf, 0x10, 0xef, 0x00, /* T..j.... */ + 0x1f, 0x06, 0x54, 0x0c, 0xef, 0x04, 0x1f, 0x03, /* ..T..... */ + 0x54, 0x0b, 0xef, 0x08, 0x1f, 0x00, 0x54, 0x05, /* T.....T. */ + 0xef, 0x62, 0xdf, 0x76, 0x80, 0x12, 0x82, 0x12, /* .b.v.... */ + 0x82, 0x80, 0x10, 0x01, 0x13, 0x4a, 0xcf, 0x3f, /* .....J.? */ + 0x00, 0x00, 0x53, 0xff, 0xef, 0x4a, 0xdf, 0xed, /* ..S..J.. */ + 0x2e, 0x6e, 0xbf, 0x4a, 0xaf, 0x6d, 0x2e, 0x6f, /* .n.J.m.o */ + 0xbf, 0xdf, 0x96, 0xbf, 0x01, 0x6d, 0x2e, 0x6d, /* .....m.m */ + 0xbf, 0xdd, 0x97, 0x01, 0x2e, 0xf9, 0x81, 0x05, /* ........ */ + 0x27 /* ' */ }; static const unsigned char pkt57[] = { -0x42, 0x16, 0x00, -0xad, 0x26, 0xd3, 0x45, 0x02, /* B...&.E. */ -0x5a, 0xd3, 0x45, 0x00, 0x5a, 0x05, 0x27, 0xd0, /* Z.E.Z.'. */ -0x41, 0xf8, 0x5b, 0xed, 0x83, 0xf6, 0x50, 0x05, /* A.[...P. */ -0x27 /* ' */ + 0x42, 0x16, 0x00, + 0xad, 0x26, 0xd3, 0x45, 0x02, /* B...&.E. */ + 0x5a, 0xd3, 0x45, 0x00, 0x5a, 0x05, 0x27, 0xd0, /* Z.E.Z.'. */ + 0x41, 0xf8, 0x5b, 0xed, 0x83, 0xf6, 0x50, 0x05, /* A.[...P. */ + 0x27 /* ' */ }; static const unsigned char pkt59[] = { -0x42, 0xca, 0x00, -0xb7, 0x26, 0xfd, 0x0c, 0x00, /* B...&... */ -0x2e, 0x3f, 0x8a, 0x39, 0x84, 0x05, 0xcf, 0xdf, /* .?.9.... */ -0x22, 0x00, 0x2e, 0xb4, 0x55, 0x04, 0xcf, 0x14, /* "...U... */ -0x1e, 0x00, 0x2e, 0xb0, 0x55, 0x00, 0x2e, 0xf5, /* ....U... */ -0x89, 0xbb, 0xef, 0x1f, 0x90, 0x91, 0xff, 0x7f, /* ........ */ -0x90, 0x14, 0xef, 0x00, 0x2e, 0x31, 0x8a, 0x14, /* .....1.. */ -0xef, 0x00, 0x2e, 0x39, 0x8a, 0x33, 0xef, 0x1f, /* ...9.3.. */ -0x90, 0x71, 0xff, 0x7f, 0x90, 0x18, 0xef, 0x00, /* .q...... */ -0x2e, 0x31, 0x8a, 0x00, 0x2e, 0xf5, 0x89, 0x40, /* .1.....@ */ -0xef, 0xfc, 0x9f, 0x5f, 0x20, 0xfc, 0x55, 0x01, /* ..._ .U. */ -0x2e, 0x67, 0x8d, 0x01, 0x2e, 0xfe, 0x8c, 0x00, /* .g...... */ -0x2e, 0xf5, 0x89, 0x02, 0x2e, 0x7a, 0x87, 0x0a, /* .....z.. */ -0xef, 0x00, 0x2e, 0x01, 0x8a, 0x02, 0x2e, 0x7a, /* .......z */ -0x87, 0x00, 0xff, 0x80, 0xef, 0x19, 0x27, 0x0a, /* ......'. */ -0xef, 0xdc, 0x9f, 0x7f, 0x9f, 0x5f, 0x20, 0xfb, /* ....._ . */ -0x55, 0x39, 0x84, 0x02, 0x2e, 0x7a, 0x87, 0x0a, /* U9...z.. */ -0xef, 0x00, 0x2e, 0x01, 0x8a, 0x02, 0x2e, 0x7a, /* .......z */ -0x87, 0x0a, 0xef, 0xdc, 0x9f, 0x7f, 0x9f, 0x5f, /* ......._ */ -0x20, 0xfb, 0x55, 0x02, 0x2e, 0x76, 0x87, 0x02, /* .U..v.. */ -0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ -0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ -0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ -0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ -0x2e, 0x44, 0x88, 0x9d, 0xef, 0x1f, 0x90, 0xda, /* .D...... */ -0xff, 0x7f, 0x90, 0x0f, 0xef, 0x00, 0x2e, 0x31, /* .......1 */ -0x8a, 0x80, 0xef, 0x1f, 0x9f /* ..... */ + 0x42, 0xca, 0x00, + 0xb7, 0x26, 0xfd, 0x0c, 0x00, /* B...&... */ + 0x2e, 0x3f, 0x8a, 0x39, 0x84, 0x05, 0xcf, 0xdf, /* .?.9.... */ + 0x22, 0x00, 0x2e, 0xb4, 0x55, 0x04, 0xcf, 0x14, /* "...U... */ + 0x1e, 0x00, 0x2e, 0xb0, 0x55, 0x00, 0x2e, 0xf5, /* ....U... */ + 0x89, 0xbb, 0xef, 0x1f, 0x90, 0x91, 0xff, 0x7f, /* ........ */ + 0x90, 0x14, 0xef, 0x00, 0x2e, 0x31, 0x8a, 0x14, /* .....1.. */ + 0xef, 0x00, 0x2e, 0x39, 0x8a, 0x33, 0xef, 0x1f, /* ...9.3.. */ + 0x90, 0x71, 0xff, 0x7f, 0x90, 0x18, 0xef, 0x00, /* .q...... */ + 0x2e, 0x31, 0x8a, 0x00, 0x2e, 0xf5, 0x89, 0x40, /* .1.....@ */ + 0xef, 0xfc, 0x9f, 0x5f, 0x20, 0xfc, 0x55, 0x01, /* ..._ .U. */ + 0x2e, 0x67, 0x8d, 0x01, 0x2e, 0xfe, 0x8c, 0x00, /* .g...... */ + 0x2e, 0xf5, 0x89, 0x02, 0x2e, 0x7a, 0x87, 0x0a, /* .....z.. */ + 0xef, 0x00, 0x2e, 0x01, 0x8a, 0x02, 0x2e, 0x7a, /* .......z */ + 0x87, 0x00, 0xff, 0x80, 0xef, 0x19, 0x27, 0x0a, /* ......'. */ + 0xef, 0xdc, 0x9f, 0x7f, 0x9f, 0x5f, 0x20, 0xfb, /* ....._ . */ + 0x55, 0x39, 0x84, 0x02, 0x2e, 0x7a, 0x87, 0x0a, /* U9...z.. */ + 0xef, 0x00, 0x2e, 0x01, 0x8a, 0x02, 0x2e, 0x7a, /* .......z */ + 0x87, 0x0a, 0xef, 0xdc, 0x9f, 0x7f, 0x9f, 0x5f, /* ......._ */ + 0x20, 0xfb, 0x55, 0x02, 0x2e, 0x76, 0x87, 0x02, /* .U..v.. */ + 0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ + 0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ + 0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ + 0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ + 0x2e, 0x44, 0x88, 0x9d, 0xef, 0x1f, 0x90, 0xda, /* .D...... */ + 0xff, 0x7f, 0x90, 0x0f, 0xef, 0x00, 0x2e, 0x31, /* .......1 */ + 0x8a, 0x80, 0xef, 0x1f, 0x9f /* ..... */ }; static const unsigned char pkt61[] = { -0x42, 0xca, 0x00, -0x1b, 0x27, 0x9f, 0x22, 0x1f, /* B...'.". */ -0x9f, 0x1f, 0x9f, 0x1f, 0x9f, 0x1f, 0x9f, 0x1f, /* ........ */ -0x9f, 0x1f, 0x9f, 0x03, 0xef, 0x1f, 0x9f, 0xb8, /* ........ */ -0xef, 0x1f, 0x9f, 0x00, 0x2e, 0xf5, 0x89, 0x40, /* .......@ */ -0xef, 0xfc, 0x9f, 0x5f, 0x20, 0xfc, 0x55, 0x01, /* ..._ .U. */ -0x2e, 0xfe, 0x8c, 0x00, 0x2e, 0xff, 0x89, 0x02, /* ........ */ -0x2e, 0xb3, 0x87, 0x02, 0x2e, 0x44, 0x88, 0x02, /* .....D.. */ -0x2e, 0x3f, 0x88, 0x02, 0x2e, 0x44, 0x88, 0x02, /* .?...D.. */ -0x2e, 0x3f, 0x88, 0x02, 0x2e, 0x44, 0x88, 0x02, /* .?...D.. */ -0x2e, 0x3f, 0x88, 0x02, 0x2e, 0x44, 0x88, 0x02, /* .?...D.. */ -0x2e, 0x3f, 0x88, 0x02, 0x2e, 0x44, 0x88, 0x02, /* .?...D.. */ -0x2e, 0xb3, 0x87, 0x14, 0xef, 0xfc, 0x9f, 0x5f, /* ......._ */ -0x20, 0xfc, 0x55, 0x01, 0xff, 0xab, 0xef, 0x19, /* .U..... */ -0x27, 0x02, 0x2e, 0xb3, 0x87, 0x11, 0xff, 0xbf, /* '....... */ -0x90, 0x51, 0xff, 0xc2, 0x97, 0xdf, 0x01, 0x7f, /* .Q...... */ -0x98, 0xfc, 0x9f, 0xbf, 0x98, 0x24, 0x28, 0xc2, /* .....$(. */ -0x9f, 0x7f, 0x20, 0xbf, 0x90, 0xf4, 0x55, 0x24, /* .. ...U$ */ -0x2a, 0x02, 0x2e, 0x7e, 0x87, 0x72, 0xef, 0xff, /* *..~.r.. */ -0xaf, 0x14, 0xef, 0xff, 0xaf, 0x00, 0xef, 0xff, /* ........ */ -0xaf, 0x00, 0xff, 0x80, 0xef, 0x19, 0x27, 0x14, /* ......'. */ -0xff, 0xfd, 0x97, 0xff, 0xaf, 0x7f, 0x20, 0xfb, /* ...... . */ -0x55, 0x00, 0x2e, 0xa9, 0x8a, 0x03, 0x0c, 0xd0, /* U....... */ -0xef, 0x07, 0xff, 0xa9, 0x80, 0x05, 0x27, 0x58, /* ......'X */ -0x85, 0x05, 0x27, 0x40, 0xef, 0x2d, 0xff, 0x1a, /* ..'@.-.. */ -0x27, 0x05, 0x27, 0x02, 0xef, 0x06, 0xff, 0x1a, /* '.'..... */ -0x27, 0x05, 0x27, 0x01, 0xff /* '.'.. */ + 0x42, 0xca, 0x00, + 0x1b, 0x27, 0x9f, 0x22, 0x1f, /* B...'.". */ + 0x9f, 0x1f, 0x9f, 0x1f, 0x9f, 0x1f, 0x9f, 0x1f, /* ........ */ + 0x9f, 0x1f, 0x9f, 0x03, 0xef, 0x1f, 0x9f, 0xb8, /* ........ */ + 0xef, 0x1f, 0x9f, 0x00, 0x2e, 0xf5, 0x89, 0x40, /* .......@ */ + 0xef, 0xfc, 0x9f, 0x5f, 0x20, 0xfc, 0x55, 0x01, /* ..._ .U. */ + 0x2e, 0xfe, 0x8c, 0x00, 0x2e, 0xff, 0x89, 0x02, /* ........ */ + 0x2e, 0xb3, 0x87, 0x02, 0x2e, 0x44, 0x88, 0x02, /* .....D.. */ + 0x2e, 0x3f, 0x88, 0x02, 0x2e, 0x44, 0x88, 0x02, /* .?...D.. */ + 0x2e, 0x3f, 0x88, 0x02, 0x2e, 0x44, 0x88, 0x02, /* .?...D.. */ + 0x2e, 0x3f, 0x88, 0x02, 0x2e, 0x44, 0x88, 0x02, /* .?...D.. */ + 0x2e, 0x3f, 0x88, 0x02, 0x2e, 0x44, 0x88, 0x02, /* .?...D.. */ + 0x2e, 0xb3, 0x87, 0x14, 0xef, 0xfc, 0x9f, 0x5f, /* ......._ */ + 0x20, 0xfc, 0x55, 0x01, 0xff, 0xab, 0xef, 0x19, /* .U..... */ + 0x27, 0x02, 0x2e, 0xb3, 0x87, 0x11, 0xff, 0xbf, /* '....... */ + 0x90, 0x51, 0xff, 0xc2, 0x97, 0xdf, 0x01, 0x7f, /* .Q...... */ + 0x98, 0xfc, 0x9f, 0xbf, 0x98, 0x24, 0x28, 0xc2, /* .....$(. */ + 0x9f, 0x7f, 0x20, 0xbf, 0x90, 0xf4, 0x55, 0x24, /* .. ...U$ */ + 0x2a, 0x02, 0x2e, 0x7e, 0x87, 0x72, 0xef, 0xff, /* *..~.r.. */ + 0xaf, 0x14, 0xef, 0xff, 0xaf, 0x00, 0xef, 0xff, /* ........ */ + 0xaf, 0x00, 0xff, 0x80, 0xef, 0x19, 0x27, 0x14, /* ......'. */ + 0xff, 0xfd, 0x97, 0xff, 0xaf, 0x7f, 0x20, 0xfb, /* ...... . */ + 0x55, 0x00, 0x2e, 0xa9, 0x8a, 0x03, 0x0c, 0xd0, /* U....... */ + 0xef, 0x07, 0xff, 0xa9, 0x80, 0x05, 0x27, 0x58, /* ......'X */ + 0x85, 0x05, 0x27, 0x40, 0xef, 0x2d, 0xff, 0x1a, /* ..'@.-.. */ + 0x27, 0x05, 0x27, 0x02, 0xef, 0x06, 0xff, 0x1a, /* '.'..... */ + 0x27, 0x05, 0x27, 0x01, 0xff /* '.'.. */ }; static const unsigned char pkt63[] = { -0x42, 0x72, 0x00, -0x7f, 0x27, 0xab, 0xef, 0x19, /* Br..'... */ -0x27, 0x08, 0xef, 0x1f, 0x98, 0xe4, 0x29, 0x00, /* '.....). */ -0xff, 0xff, 0x96, 0x20, 0xff, 0xff, 0x96, 0x00, /* ... .... */ -0xff, 0xff, 0x96, 0x40, 0xff, 0xff, 0x96, 0x00, /* ...@.... */ -0xff, 0xff, 0x96, 0x60, 0xff, 0xff, 0x96, 0x00, /* ...`.... */ -0xff, 0xff, 0x96, 0x00, 0xff, 0xff, 0x96, 0x01, /* ........ */ -0xff, 0xff, 0x96, 0x20, 0xff, 0xff, 0x96, 0x00, /* ... .... */ -0xff, 0xff, 0x96, 0x02, 0xff, 0xff, 0x96, 0x02, /* ........ */ -0xff, 0xff, 0x96, 0x82, 0xff, 0xff, 0x96, 0x02, /* ........ */ -0xff, 0xff, 0x96, 0x02, 0x2e, 0xaa, 0x87, 0x46, /* .......F */ -0x2e, 0x01, 0xdf, 0x9f, 0x28, 0x46, 0x2e, 0x01, /* ....(F.. */ -0xbf, 0x05, 0x27, 0x0f, 0xef, 0x5f, 0x98, 0xdd, /* ..'.._.. */ -0x9f, 0xbf, 0x98, 0x24, 0x28, 0x5f, 0x20, 0xf9, /* ...$(_ . */ -0x55, 0x24, 0x2a, 0x05, 0x27, 0x7f, 0xef, 0x2d, /* U$*.'..- */ -0xff, 0x1b, 0x27, 0x05, 0x27 /* ..'.' */ + 0x42, 0x72, 0x00, + 0x7f, 0x27, 0xab, 0xef, 0x19, /* Br..'... */ + 0x27, 0x08, 0xef, 0x1f, 0x98, 0xe4, 0x29, 0x00, /* '.....). */ + 0xff, 0xff, 0x96, 0x20, 0xff, 0xff, 0x96, 0x00, /* ... .... */ + 0xff, 0xff, 0x96, 0x40, 0xff, 0xff, 0x96, 0x00, /* ...@.... */ + 0xff, 0xff, 0x96, 0x60, 0xff, 0xff, 0x96, 0x00, /* ...`.... */ + 0xff, 0xff, 0x96, 0x00, 0xff, 0xff, 0x96, 0x01, /* ........ */ + 0xff, 0xff, 0x96, 0x20, 0xff, 0xff, 0x96, 0x00, /* ... .... */ + 0xff, 0xff, 0x96, 0x02, 0xff, 0xff, 0x96, 0x02, /* ........ */ + 0xff, 0xff, 0x96, 0x82, 0xff, 0xff, 0x96, 0x02, /* ........ */ + 0xff, 0xff, 0x96, 0x02, 0x2e, 0xaa, 0x87, 0x46, /* .......F */ + 0x2e, 0x01, 0xdf, 0x9f, 0x28, 0x46, 0x2e, 0x01, /* ....(F.. */ + 0xbf, 0x05, 0x27, 0x0f, 0xef, 0x5f, 0x98, 0xdd, /* ..'.._.. */ + 0x9f, 0xbf, 0x98, 0x24, 0x28, 0x5f, 0x20, 0xf9, /* ...$(_ . */ + 0x55, 0x24, 0x2a, 0x05, 0x27, 0x7f, 0xef, 0x2d, /* U$*.'..- */ + 0xff, 0x1b, 0x27, 0x05, 0x27 /* ..'.' */ }; static const unsigned char pkt65[] = { -0x42, 0xca, 0x00, -0xb7, 0x27, 0x00, 0x2e, 0x3f, /* B...'..? */ -0x8a, 0x23, 0x81, 0x02, 0x2e, 0x4d, 0x88, 0x05, /* .#...M.. */ -0xcf, 0xdf, 0x22, 0x35, 0x55, 0x04, 0xcf, 0x2a, /* .."5U..* */ -0x1e, 0x32, 0x55, 0xfe, 0xdf, 0xfe, 0xcf, 0x00, /* .2U..... */ -0x1f, 0x1d, 0x55, 0x00, 0x1e, 0x0e, 0x54, 0xc6, /* ..U...T. */ -0x2e, 0x00, 0xdf, 0x3f, 0x20, 0xbf, 0x03, 0x16, /* ...? ... */ -0x55, 0xc6, 0x2e, 0x01, 0xdf, 0x3f, 0x2c, 0x12, /* U....?,. */ -0x5b, 0x46, 0x2e, 0x00, 0xbf, 0x00, 0x2e, 0x25, /* [F.....% */ -0x8a, 0x02, 0x2e, 0xe1, 0x77, 0x00, 0xef, 0x46, /* ....w..F */ -0x2e, 0x00, 0xbf, 0x46, 0x2e, 0x01, 0xdf, 0x1f, /* ...F.... */ -0x28, 0x46, 0x2e, 0x01, 0xbf, 0x00, 0x2e, 0x06, /* (F...... */ -0x8a, 0x02, 0x2e, 0xf7, 0x87, 0x05, 0x27, 0x46, /* ......'F */ -0x2e, 0x01, 0xdf, 0x1f, 0x2a, 0x46, 0x2e, 0x01, /* ....*F.. */ -0xbf, 0x41, 0x2e, 0xb6, 0xdf, 0x01, 0xff, 0xab, /* .A...... */ -0xef, 0x19, 0x27, 0x42, 0xff, 0x7f, 0x98, 0x9f, /* ..'B.... */ -0x98, 0x24, 0x28, 0x56, 0x85, 0x24, 0x2a, 0x05, /* .$(V.$*. */ -0x27, 0x58, 0x85, 0x05, 0x27, 0xfd, 0x0c, 0x00, /* 'X..'... */ -0x2e, 0xf5, 0x89, 0x14, 0xef, 0x00, 0x2e, 0x39, /* .......9 */ -0x8a, 0x02, 0x2e, 0x3b, 0x88, 0x02, 0x2e, 0x44, /* ...;...D */ -0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, 0x2e, 0x44, /* ...?...D */ -0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, 0x2e, 0x44, /* ...?...D */ -0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, 0x2e, 0x44, /* ...?...D */ -0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, 0x2e, 0x44, /* ...?...D */ -0x88, 0x46, 0x2e, 0x00, 0xdf, 0x1f, 0x9f, 0xe2, /* .F...... */ -0xef, 0x1f, 0x90, 0xe0, 0xff, 0x7f, 0x90, 0x0e, /* ........ */ -0xef, 0x00, 0x2e, 0x31, 0x8a /* ...1. */ + 0x42, 0xca, 0x00, + 0xb7, 0x27, 0x00, 0x2e, 0x3f, /* B...'..? */ + 0x8a, 0x23, 0x81, 0x02, 0x2e, 0x4d, 0x88, 0x05, /* .#...M.. */ + 0xcf, 0xdf, 0x22, 0x35, 0x55, 0x04, 0xcf, 0x2a, /* .."5U..* */ + 0x1e, 0x32, 0x55, 0xfe, 0xdf, 0xfe, 0xcf, 0x00, /* .2U..... */ + 0x1f, 0x1d, 0x55, 0x00, 0x1e, 0x0e, 0x54, 0xc6, /* ..U...T. */ + 0x2e, 0x00, 0xdf, 0x3f, 0x20, 0xbf, 0x03, 0x16, /* ...? ... */ + 0x55, 0xc6, 0x2e, 0x01, 0xdf, 0x3f, 0x2c, 0x12, /* U....?,. */ + 0x5b, 0x46, 0x2e, 0x00, 0xbf, 0x00, 0x2e, 0x25, /* [F.....% */ + 0x8a, 0x02, 0x2e, 0xe1, 0x77, 0x00, 0xef, 0x46, /* ....w..F */ + 0x2e, 0x00, 0xbf, 0x46, 0x2e, 0x01, 0xdf, 0x1f, /* ...F.... */ + 0x28, 0x46, 0x2e, 0x01, 0xbf, 0x00, 0x2e, 0x06, /* (F...... */ + 0x8a, 0x02, 0x2e, 0xf7, 0x87, 0x05, 0x27, 0x46, /* ......'F */ + 0x2e, 0x01, 0xdf, 0x1f, 0x2a, 0x46, 0x2e, 0x01, /* ....*F.. */ + 0xbf, 0x41, 0x2e, 0xb6, 0xdf, 0x01, 0xff, 0xab, /* .A...... */ + 0xef, 0x19, 0x27, 0x42, 0xff, 0x7f, 0x98, 0x9f, /* ..'B.... */ + 0x98, 0x24, 0x28, 0x56, 0x85, 0x24, 0x2a, 0x05, /* .$(V.$*. */ + 0x27, 0x58, 0x85, 0x05, 0x27, 0xfd, 0x0c, 0x00, /* 'X..'... */ + 0x2e, 0xf5, 0x89, 0x14, 0xef, 0x00, 0x2e, 0x39, /* .......9 */ + 0x8a, 0x02, 0x2e, 0x3b, 0x88, 0x02, 0x2e, 0x44, /* ...;...D */ + 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, 0x2e, 0x44, /* ...?...D */ + 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, 0x2e, 0x44, /* ...?...D */ + 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, 0x2e, 0x44, /* ...?...D */ + 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, 0x2e, 0x44, /* ...?...D */ + 0x88, 0x46, 0x2e, 0x00, 0xdf, 0x1f, 0x9f, 0xe2, /* .F...... */ + 0xef, 0x1f, 0x90, 0xe0, 0xff, 0x7f, 0x90, 0x0e, /* ........ */ + 0xef, 0x00, 0x2e, 0x31, 0x8a /* ...1. */ }; static const unsigned char pkt67[] = { -0x42, 0xca, 0x00, -0x1b, 0x28, 0x80, 0xef, 0x1f, /* B...(... */ -0x9f, 0x9f, 0x22, 0x1f, 0x9f, 0x1f, 0x9f, 0x1f, /* .."..... */ -0x9f, 0x1f, 0x9f, 0x1f, 0x9f, 0x1f, 0x9f, 0x01, /* ........ */ -0xef, 0x1f, 0x9f, 0xb8, 0xef, 0x1f, 0x9f, 0x00, /* ........ */ -0x2e, 0xf5, 0x89, 0x40, 0xef, 0xfc, 0x9f, 0x5f, /* ...@..._ */ -0x20, 0xfc, 0x55, 0x03, 0x0c, 0x01, 0x2e, 0x67, /* .U....g */ -0x8d, 0x01, 0x2e, 0xfe, 0x8c, 0x00, 0x2e, 0xff, /* ........ */ -0x89, 0x00, 0x2e, 0xfb, 0x89, 0x14, 0xef, 0x00, /* ........ */ -0x2e, 0x01, 0x8a, 0x05, 0x27, 0x40, 0xef, 0x2d, /* ....'@.- */ -0xff, 0x1a, 0x27, 0x05, 0x27, 0x16, 0x27, 0x04, /* ..'.'.'. */ -0x10, 0x00, 0x13, 0x1a, 0x27, 0x05, 0x27, 0xd9, /* ....'.'. */ -0x9f, 0x3f, 0x9f, 0xd8, 0x9f, 0x3f, 0x9f, 0xd7, /* .?...?.. */ -0x9f, 0x3f, 0x9f, 0xd6, 0x9f, 0x3f, 0x9f, 0x05, /* .?...?.. */ -0x27, 0x7f, 0xef, 0x2d, 0xff, 0x46, 0x2e, 0x1d, /* '..-.F.. */ -0xbf, 0xc6, 0x2e, 0x1c, 0xbf, 0x93, 0xef, 0x2d, /* .......- */ -0xff, 0x46, 0x2e, 0x1f, 0xbf, 0xc6, 0x2e, 0x1e, /* .F...... */ -0xbf, 0x05, 0x27, 0x00, 0x2e, 0x3f, 0x8a, 0x23, /* ..'..?.# */ -0x81, 0x02, 0x2e, 0x4d, 0x88, 0x02, 0x2e, 0x60, /* ...M...` */ -0x89, 0x08, 0xef, 0xfe, 0xdf, 0x3f, 0x9f, 0x5f, /* .....?._ */ -0x20, 0xfb, 0x55, 0x28, 0xef, 0xfe, 0xdf, 0x5f, /* .U(..._ */ -0x20, 0xfc, 0x55, 0x00, 0x2e, 0xf5, 0x89, 0xfe, /* .U..... */ -0xdf, 0x00, 0x2e, 0xf5, 0x89, 0x14, 0xff, 0xfe, /* ........ */ -0xcf, 0x1f, 0x9f, 0x7f, 0x20, 0xfb, 0x55, 0x23, /* .... .U# */ -0xff, 0xfe, 0xcf, 0x7f, 0x20, 0xfc, 0x55, 0x02, /* .... .U. */ -0x2e, 0x64, 0x89, 0x00, 0x2e, 0xf5, 0x89, 0x14, /* .d...... */ -0xff, 0xfc, 0x97, 0x1f, 0x97 /* ..... */ + 0x42, 0xca, 0x00, + 0x1b, 0x28, 0x80, 0xef, 0x1f, /* B...(... */ + 0x9f, 0x9f, 0x22, 0x1f, 0x9f, 0x1f, 0x9f, 0x1f, /* .."..... */ + 0x9f, 0x1f, 0x9f, 0x1f, 0x9f, 0x1f, 0x9f, 0x01, /* ........ */ + 0xef, 0x1f, 0x9f, 0xb8, 0xef, 0x1f, 0x9f, 0x00, /* ........ */ + 0x2e, 0xf5, 0x89, 0x40, 0xef, 0xfc, 0x9f, 0x5f, /* ...@..._ */ + 0x20, 0xfc, 0x55, 0x03, 0x0c, 0x01, 0x2e, 0x67, /* .U....g */ + 0x8d, 0x01, 0x2e, 0xfe, 0x8c, 0x00, 0x2e, 0xff, /* ........ */ + 0x89, 0x00, 0x2e, 0xfb, 0x89, 0x14, 0xef, 0x00, /* ........ */ + 0x2e, 0x01, 0x8a, 0x05, 0x27, 0x40, 0xef, 0x2d, /* ....'@.- */ + 0xff, 0x1a, 0x27, 0x05, 0x27, 0x16, 0x27, 0x04, /* ..'.'.'. */ + 0x10, 0x00, 0x13, 0x1a, 0x27, 0x05, 0x27, 0xd9, /* ....'.'. */ + 0x9f, 0x3f, 0x9f, 0xd8, 0x9f, 0x3f, 0x9f, 0xd7, /* .?...?.. */ + 0x9f, 0x3f, 0x9f, 0xd6, 0x9f, 0x3f, 0x9f, 0x05, /* .?...?.. */ + 0x27, 0x7f, 0xef, 0x2d, 0xff, 0x46, 0x2e, 0x1d, /* '..-.F.. */ + 0xbf, 0xc6, 0x2e, 0x1c, 0xbf, 0x93, 0xef, 0x2d, /* .......- */ + 0xff, 0x46, 0x2e, 0x1f, 0xbf, 0xc6, 0x2e, 0x1e, /* .F...... */ + 0xbf, 0x05, 0x27, 0x00, 0x2e, 0x3f, 0x8a, 0x23, /* ..'..?.# */ + 0x81, 0x02, 0x2e, 0x4d, 0x88, 0x02, 0x2e, 0x60, /* ...M...` */ + 0x89, 0x08, 0xef, 0xfe, 0xdf, 0x3f, 0x9f, 0x5f, /* .....?._ */ + 0x20, 0xfb, 0x55, 0x28, 0xef, 0xfe, 0xdf, 0x5f, /* .U(..._ */ + 0x20, 0xfc, 0x55, 0x00, 0x2e, 0xf5, 0x89, 0xfe, /* .U..... */ + 0xdf, 0x00, 0x2e, 0xf5, 0x89, 0x14, 0xff, 0xfe, /* ........ */ + 0xcf, 0x1f, 0x9f, 0x7f, 0x20, 0xfb, 0x55, 0x23, /* .... .U# */ + 0xff, 0xfe, 0xcf, 0x7f, 0x20, 0xfc, 0x55, 0x02, /* .... .U. */ + 0x2e, 0x64, 0x89, 0x00, 0x2e, 0xf5, 0x89, 0x14, /* .d...... */ + 0xff, 0xfc, 0x97, 0x1f, 0x97 /* ..... */ }; static const unsigned char pkt69[] = { -0x42, 0xca, 0x00, -0x7f, 0x28, 0x7f, 0x20, 0xfb, /* B...(. . */ -0x55, 0x2c, 0xef, 0xbf, 0x22, 0x3f, 0x9f, 0x5f, /* U,.."?._ */ -0x20, 0xfc, 0x55, 0x00, 0x2e, 0xf5, 0x89, 0x40, /* .U....@ */ -0xef, 0xf6, 0x9f, 0x36, 0x1b, 0x3f, 0x9f, 0x5f, /* ...6.?._ */ -0x20, 0xfa, 0x55, 0x01, 0x2e, 0x67, 0x8d, 0x01, /* .U..g.. */ -0x2e, 0xfe, 0x8c, 0x00, 0x2e, 0xf5, 0x89, 0x02, /* ........ */ -0x2e, 0x5c, 0x89, 0xdc, 0x9f, 0x3f, 0x9f, 0xdc, /* .\...?.. */ -0x9f, 0x3f, 0x9f, 0xdc, 0x9f, 0x3f, 0x9f, 0xdc, /* .?...?.. */ -0x9f, 0x3f, 0x9f, 0xdc, 0x9f, 0x3f, 0x9f, 0xdc, /* .?...?.. */ -0x9f, 0x3f, 0x9f, 0xdc, 0x9f, 0x3f, 0x9f, 0xdc, /* .?...?.. */ -0x9f, 0x3f, 0x9f, 0x80, 0xff, 0x3f, 0x9f, 0x2f, /* .?...?./ */ -0xef, 0xbf, 0x22, 0x3f, 0x9f, 0x5f, 0x20, 0xfc, /* .."?._ . */ -0x55, 0x3f, 0x9f, 0x3f, 0x9f, 0x3f, 0x9f, 0x3f, /* U?.?.?.? */ -0x9f, 0x3f, 0x9f, 0x3f, 0x9f, 0x02, 0xff, 0x3f, /* .?.?...? */ -0x9f, 0x40, 0xff, 0x3f, 0x9f, 0x00, 0x2e, 0xf5, /* .@.?.... */ -0x89, 0x40, 0xef, 0xfc, 0x9f, 0x5f, 0x20, 0xfc, /* .@..._ . */ -0x55, 0x01, 0x2e, 0xfe, 0x8c, 0x00, 0x2e, 0xff, /* U....... */ -0x89, 0x00, 0x2e, 0xf5, 0x89, 0x14, 0xef, 0x00, /* ........ */ -0x2e, 0x01, 0x8a, 0x46, 0x2e, 0x18, 0xdf, 0xc6, /* ...F.... */ -0x2e, 0x17, 0xdf, 0x1a, 0x27, 0x02, 0x2e, 0x68, /* ....'..h */ -0x89, 0x14, 0xef, 0xfc, 0x9f, 0x5c, 0x1b, 0x3f, /* .....\.? */ -0x97, 0x5f, 0x20, 0xfa, 0x55, 0x2c, 0xef, 0x5c, /* ._ .U,.\ */ -0xff, 0x3f, 0x97, 0x5f, 0x20, 0xfc, 0x55, 0x00, /* .?._ .U. */ -0x2e, 0xff, 0x89, 0x02, 0x2e, 0x68, 0x89, 0x02, /* .....h.. */ -0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ -0x2e, 0x44, 0x88, 0x02, 0x2e /* .D... */ + 0x42, 0xca, 0x00, + 0x7f, 0x28, 0x7f, 0x20, 0xfb, /* B...(. . */ + 0x55, 0x2c, 0xef, 0xbf, 0x22, 0x3f, 0x9f, 0x5f, /* U,.."?._ */ + 0x20, 0xfc, 0x55, 0x00, 0x2e, 0xf5, 0x89, 0x40, /* .U....@ */ + 0xef, 0xf6, 0x9f, 0x36, 0x1b, 0x3f, 0x9f, 0x5f, /* ...6.?._ */ + 0x20, 0xfa, 0x55, 0x01, 0x2e, 0x67, 0x8d, 0x01, /* .U..g.. */ + 0x2e, 0xfe, 0x8c, 0x00, 0x2e, 0xf5, 0x89, 0x02, /* ........ */ + 0x2e, 0x5c, 0x89, 0xdc, 0x9f, 0x3f, 0x9f, 0xdc, /* .\...?.. */ + 0x9f, 0x3f, 0x9f, 0xdc, 0x9f, 0x3f, 0x9f, 0xdc, /* .?...?.. */ + 0x9f, 0x3f, 0x9f, 0xdc, 0x9f, 0x3f, 0x9f, 0xdc, /* .?...?.. */ + 0x9f, 0x3f, 0x9f, 0xdc, 0x9f, 0x3f, 0x9f, 0xdc, /* .?...?.. */ + 0x9f, 0x3f, 0x9f, 0x80, 0xff, 0x3f, 0x9f, 0x2f, /* .?...?./ */ + 0xef, 0xbf, 0x22, 0x3f, 0x9f, 0x5f, 0x20, 0xfc, /* .."?._ . */ + 0x55, 0x3f, 0x9f, 0x3f, 0x9f, 0x3f, 0x9f, 0x3f, /* U?.?.?.? */ + 0x9f, 0x3f, 0x9f, 0x3f, 0x9f, 0x02, 0xff, 0x3f, /* .?.?...? */ + 0x9f, 0x40, 0xff, 0x3f, 0x9f, 0x00, 0x2e, 0xf5, /* .@.?.... */ + 0x89, 0x40, 0xef, 0xfc, 0x9f, 0x5f, 0x20, 0xfc, /* .@..._ . */ + 0x55, 0x01, 0x2e, 0xfe, 0x8c, 0x00, 0x2e, 0xff, /* U....... */ + 0x89, 0x00, 0x2e, 0xf5, 0x89, 0x14, 0xef, 0x00, /* ........ */ + 0x2e, 0x01, 0x8a, 0x46, 0x2e, 0x18, 0xdf, 0xc6, /* ...F.... */ + 0x2e, 0x17, 0xdf, 0x1a, 0x27, 0x02, 0x2e, 0x68, /* ....'..h */ + 0x89, 0x14, 0xef, 0xfc, 0x9f, 0x5c, 0x1b, 0x3f, /* .....\.? */ + 0x97, 0x5f, 0x20, 0xfa, 0x55, 0x2c, 0xef, 0x5c, /* ._ .U,.\ */ + 0xff, 0x3f, 0x97, 0x5f, 0x20, 0xfc, 0x55, 0x00, /* .?._ .U. */ + 0x2e, 0xff, 0x89, 0x02, 0x2e, 0x68, 0x89, 0x02, /* .....h.. */ + 0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ + 0x2e, 0x44, 0x88, 0x02, 0x2e /* .D... */ }; static const unsigned char pkt71[] = { -0x42, 0xca, 0x00, -0xe3, 0x28, 0x3f, 0x88, 0x02, /* B...(?.. */ -0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ -0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ -0x2e, 0x44, 0x88, 0x00, 0x2e, 0xf5, 0x89, 0x40, /* .D.....@ */ -0xef, 0xfc, 0x9f, 0x5f, 0x20, 0xfc, 0x55, 0x01, /* ..._ .U. */ -0x2e, 0x67, 0x8d, 0x01, 0x2e, 0xfe, 0x8c, 0x46, /* .g.....F */ -0x2e, 0x18, 0xdf, 0xc6, 0x2e, 0x17, 0xdf, 0x1a, /* ........ */ -0x27, 0x02, 0x2e, 0x68, 0x89, 0x14, 0xef, 0xfc, /* '..h.... */ -0x9f, 0x3f, 0x97, 0x5f, 0x20, 0xfb, 0x55, 0x80, /* .?._ .U. */ -0xff, 0x3f, 0x97, 0x23, 0xef, 0xbf, 0x22, 0x3f, /* .?.#.."? */ -0x97, 0x5f, 0x20, 0xfc, 0x55, 0x3f, 0x97, 0x3f, /* ._ .U?.? */ -0x97, 0x3f, 0x97, 0x3f, 0x97, 0x3f, 0x97, 0x3f, /* .?.?.?.? */ -0x97, 0x02, 0xff, 0x3f, 0x97, 0xa0, 0xff, 0x3f, /* ...?...? */ -0x97, 0x00, 0x2e, 0xf5, 0x89, 0x40, 0xef, 0xfc, /* .....@.. */ -0x9f, 0x5f, 0x20, 0xfc, 0x55, 0x01, 0x2e, 0xfe, /* ._ .U... */ -0x8c, 0x00, 0x2e, 0xff, 0x89, 0x00, 0x2e, 0xf5, /* ........ */ -0x89, 0x14, 0xef, 0x00, 0x2e, 0x01, 0x8a, 0x00, /* ........ */ -0x2e, 0xff, 0x89, 0x02, 0x2e, 0x68, 0x89, 0x02, /* .....h.. */ -0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ -0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ -0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ -0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ -0x2e, 0x44, 0x88, 0x17, 0x27, 0x5f, 0x20, 0x1b, /* .D..'_ . */ -0x27, 0xf6, 0x97, 0x0f, 0x1c, 0x54, 0x10, 0x2d, /* '....T.- */ -0xff, 0x1b, 0x27, 0x73, 0xef, 0xff, 0xaf, 0x84, /* ..'s.... */ -0xef, 0xff, 0xaf, 0x00, 0xef /* ..... */ + 0x42, 0xca, 0x00, + 0xe3, 0x28, 0x3f, 0x88, 0x02, /* B...(?.. */ + 0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ + 0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ + 0x2e, 0x44, 0x88, 0x00, 0x2e, 0xf5, 0x89, 0x40, /* .D.....@ */ + 0xef, 0xfc, 0x9f, 0x5f, 0x20, 0xfc, 0x55, 0x01, /* ..._ .U. */ + 0x2e, 0x67, 0x8d, 0x01, 0x2e, 0xfe, 0x8c, 0x46, /* .g.....F */ + 0x2e, 0x18, 0xdf, 0xc6, 0x2e, 0x17, 0xdf, 0x1a, /* ........ */ + 0x27, 0x02, 0x2e, 0x68, 0x89, 0x14, 0xef, 0xfc, /* '..h.... */ + 0x9f, 0x3f, 0x97, 0x5f, 0x20, 0xfb, 0x55, 0x80, /* .?._ .U. */ + 0xff, 0x3f, 0x97, 0x23, 0xef, 0xbf, 0x22, 0x3f, /* .?.#.."? */ + 0x97, 0x5f, 0x20, 0xfc, 0x55, 0x3f, 0x97, 0x3f, /* ._ .U?.? */ + 0x97, 0x3f, 0x97, 0x3f, 0x97, 0x3f, 0x97, 0x3f, /* .?.?.?.? */ + 0x97, 0x02, 0xff, 0x3f, 0x97, 0xa0, 0xff, 0x3f, /* ...?...? */ + 0x97, 0x00, 0x2e, 0xf5, 0x89, 0x40, 0xef, 0xfc, /* .....@.. */ + 0x9f, 0x5f, 0x20, 0xfc, 0x55, 0x01, 0x2e, 0xfe, /* ._ .U... */ + 0x8c, 0x00, 0x2e, 0xff, 0x89, 0x00, 0x2e, 0xf5, /* ........ */ + 0x89, 0x14, 0xef, 0x00, 0x2e, 0x01, 0x8a, 0x00, /* ........ */ + 0x2e, 0xff, 0x89, 0x02, 0x2e, 0x68, 0x89, 0x02, /* .....h.. */ + 0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ + 0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ + 0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ + 0x2e, 0x44, 0x88, 0x02, 0x2e, 0x3f, 0x88, 0x02, /* .D...?.. */ + 0x2e, 0x44, 0x88, 0x17, 0x27, 0x5f, 0x20, 0x1b, /* .D..'_ . */ + 0x27, 0xf6, 0x97, 0x0f, 0x1c, 0x54, 0x10, 0x2d, /* '....T.- */ + 0xff, 0x1b, 0x27, 0x73, 0xef, 0xff, 0xaf, 0x84, /* ..'s.... */ + 0xef, 0xff, 0xaf, 0x00, 0xef /* ..... */ }; static const unsigned char pkt73[] = { -0x42, 0x4c, 0x00, -0x47, 0x29, 0xff, 0xaf, 0xfc, /* BL.G)... */ -0x97, 0xff, 0xaf, 0xfc, 0x97, 0xff, 0xaf, 0xfc, /* ........ */ -0x97, 0xff, 0xaf, 0xfc, 0x97, 0xff, 0xaf, 0x80, /* ........ */ -0xef, 0xfe, 0xdf, 0xff, 0xbf, 0x5f, 0x20, 0xfb, /* ....._ . */ -0x55, 0x10, 0xef, 0xfe, 0xdf, 0x5f, 0x20, 0xfc, /* U...._ . */ -0x55, 0x00, 0x2e, 0xa9, 0x8a, 0x05, 0x27, 0x69, /* U.....'i */ -0xef, 0x2d, 0xff, 0x1a, 0x27, 0x05, 0x27, 0x69, /* .-..'.'i */ -0xef, 0x2d, 0xff, 0x1b, 0x27, 0x05, 0x27, 0x54, /* .-..'.'T */ -0xef, 0x2d, 0xff, 0x1a, 0x27, 0x05, 0x27, 0x54, /* .-..'.'T */ -0xef, 0x2d, 0xff, 0x1b, 0x27, 0x05, 0x27 /* .-..'.' */ + 0x42, 0x4c, 0x00, + 0x47, 0x29, 0xff, 0xaf, 0xfc, /* BL.G)... */ + 0x97, 0xff, 0xaf, 0xfc, 0x97, 0xff, 0xaf, 0xfc, /* ........ */ + 0x97, 0xff, 0xaf, 0xfc, 0x97, 0xff, 0xaf, 0x80, /* ........ */ + 0xef, 0xfe, 0xdf, 0xff, 0xbf, 0x5f, 0x20, 0xfb, /* ....._ . */ + 0x55, 0x10, 0xef, 0xfe, 0xdf, 0x5f, 0x20, 0xfc, /* U...._ . */ + 0x55, 0x00, 0x2e, 0xa9, 0x8a, 0x05, 0x27, 0x69, /* U.....'i */ + 0xef, 0x2d, 0xff, 0x1a, 0x27, 0x05, 0x27, 0x69, /* .-..'.'i */ + 0xef, 0x2d, 0xff, 0x1b, 0x27, 0x05, 0x27, 0x54, /* .-..'.'T */ + 0xef, 0x2d, 0xff, 0x1a, 0x27, 0x05, 0x27, 0x54, /* .-..'.'T */ + 0xef, 0x2d, 0xff, 0x1b, 0x27, 0x05, 0x27 /* .-..'.' */ }; static const unsigned char pkt75[] = { -0x67, 0x05, 0x00, 0x00, 0x02, 0x2e, 0x00, 0x70, /* g......p */ -0x67, 0x05, 0x00, 0x02, 0x02, 0x2e, 0x87, 0x70, /* g......p */ -0x67, 0x05, 0x00, 0x01, 0x02, 0x2e, 0x6f, 0x72, /* g.....or */ -0x67, 0x05, 0x00, 0x03, 0x02, 0x2e, 0x7a, 0x73, /* g.....zs */ -0x67, 0x05, 0x00, 0x08, 0x02, 0x2e, 0x9a, 0x74, /* g......t */ -0x67, 0x05, 0x00, 0x07, 0x02, 0x2e, 0x06, 0x75, /* g......u */ -0x5a, 0x05, 0x00, 0x00, 0x55, 0x01, 0x27, 0x26, /* Z...U.'& */ -0x5a, 0x05, 0x00, 0x01, 0xc4, 0x0a, 0x33, 0x26, /* Z.....3& */ -0x5a, 0x05, 0x00, 0x02, 0xd9, 0x02, 0x45, 0x26, /* Z.....E& */ -0x5a, 0x05, 0x00, 0x03, 0x94, 0x16, 0x6b, 0x26, /* Z.....k& */ -0x5a, 0x05, 0x00, 0x04, 0xcc, 0x0a, 0xad, 0x26, /* Z......& */ -0x5a, 0x05, 0x00, 0x05, 0x3e, 0x0a, 0xb7, 0x26, /* Z...>..& */ -0x5a, 0x05, 0x00, 0x06, 0xf4, 0x09, 0xb7, 0x27, /* Z......' */ -0x0d, -0x42, 0x04, 0x00, -0x47, 0x29, 0xff, 0xaf /* .B..G).. */ + 0x67, 0x05, 0x00, 0x00, 0x02, 0x2e, 0x00, 0x70, /* g......p */ + 0x67, 0x05, 0x00, 0x02, 0x02, 0x2e, 0x87, 0x70, /* g......p */ + 0x67, 0x05, 0x00, 0x01, 0x02, 0x2e, 0x6f, 0x72, /* g.....or */ + 0x67, 0x05, 0x00, 0x03, 0x02, 0x2e, 0x7a, 0x73, /* g.....zs */ + 0x67, 0x05, 0x00, 0x08, 0x02, 0x2e, 0x9a, 0x74, /* g......t */ + 0x67, 0x05, 0x00, 0x07, 0x02, 0x2e, 0x06, 0x75, /* g......u */ + 0x5a, 0x05, 0x00, 0x00, 0x55, 0x01, 0x27, 0x26, /* Z...U.'& */ + 0x5a, 0x05, 0x00, 0x01, 0xc4, 0x0a, 0x33, 0x26, /* Z.....3& */ + 0x5a, 0x05, 0x00, 0x02, 0xd9, 0x02, 0x45, 0x26, /* Z.....E& */ + 0x5a, 0x05, 0x00, 0x03, 0x94, 0x16, 0x6b, 0x26, /* Z.....k& */ + 0x5a, 0x05, 0x00, 0x04, 0xcc, 0x0a, 0xad, 0x26, /* Z......& */ + 0x5a, 0x05, 0x00, 0x05, 0x3e, 0x0a, 0xb7, 0x26, /* Z...>..& */ + 0x5a, 0x05, 0x00, 0x06, 0xf4, 0x09, 0xb7, 0x27, /* Z......' */ + 0x0d, + 0x42, 0x04, 0x00, + 0x47, 0x29, 0xff, 0xaf /* .B..G).. */ }; /* INIT1 is over, 0x07 cmd returns * { 0x07, 0x05, 0x00, 0x91, 0x26, 0x21, 0x00, 0x3a } */ struct aesX660_cmd aes2660_init_1[] = { - { .cmd = pkt13, .len = sizeof(pkt13) }, - { .cmd = pkt15, .len = sizeof(pkt15) }, - { .cmd = pkt17, .len = sizeof(pkt17) }, - { .cmd = pkt19, .len = sizeof(pkt19) }, - { .cmd = pkt21, .len = sizeof(pkt21) }, - { .cmd = pkt23, .len = sizeof(pkt23) }, - { .cmd = pkt25, .len = sizeof(pkt25) }, - { .cmd = pkt27, .len = sizeof(pkt27) }, - { .cmd = pkt29, .len = sizeof(pkt29) }, - { .cmd = pkt31, .len = sizeof(pkt31) }, - { .cmd = pkt33, .len = sizeof(pkt33) }, - { .cmd = pkt35, .len = sizeof(pkt35) }, - { .cmd = pkt37, .len = sizeof(pkt37) }, - { .cmd = pkt39, .len = sizeof(pkt39) }, - { .cmd = pkt41, .len = sizeof(pkt41) }, - { .cmd = pkt43, .len = sizeof(pkt43) }, - { .cmd = pkt45, .len = sizeof(pkt45) }, - { .cmd = pkt47, .len = sizeof(pkt47) }, - { .cmd = pkt49, .len = sizeof(pkt49) }, - { .cmd = pkt51, .len = sizeof(pkt51) }, - { .cmd = pkt53, .len = sizeof(pkt53) }, - { .cmd = pkt55, .len = sizeof(pkt55) }, - { .cmd = pkt57, .len = sizeof(pkt57) }, - { .cmd = pkt59, .len = sizeof(pkt59) }, - { .cmd = pkt61, .len = sizeof(pkt61) }, - { .cmd = pkt63, .len = sizeof(pkt63) }, - { .cmd = pkt65, .len = sizeof(pkt65) }, - { .cmd = pkt67, .len = sizeof(pkt67) }, - { .cmd = pkt69, .len = sizeof(pkt69) }, - { .cmd = pkt71, .len = sizeof(pkt71) }, - { .cmd = pkt73, .len = sizeof(pkt73) }, - { .cmd = pkt75, .len = sizeof(pkt75) }, + { .cmd = pkt13, .len = sizeof (pkt13) }, + { .cmd = pkt15, .len = sizeof (pkt15) }, + { .cmd = pkt17, .len = sizeof (pkt17) }, + { .cmd = pkt19, .len = sizeof (pkt19) }, + { .cmd = pkt21, .len = sizeof (pkt21) }, + { .cmd = pkt23, .len = sizeof (pkt23) }, + { .cmd = pkt25, .len = sizeof (pkt25) }, + { .cmd = pkt27, .len = sizeof (pkt27) }, + { .cmd = pkt29, .len = sizeof (pkt29) }, + { .cmd = pkt31, .len = sizeof (pkt31) }, + { .cmd = pkt33, .len = sizeof (pkt33) }, + { .cmd = pkt35, .len = sizeof (pkt35) }, + { .cmd = pkt37, .len = sizeof (pkt37) }, + { .cmd = pkt39, .len = sizeof (pkt39) }, + { .cmd = pkt41, .len = sizeof (pkt41) }, + { .cmd = pkt43, .len = sizeof (pkt43) }, + { .cmd = pkt45, .len = sizeof (pkt45) }, + { .cmd = pkt47, .len = sizeof (pkt47) }, + { .cmd = pkt49, .len = sizeof (pkt49) }, + { .cmd = pkt51, .len = sizeof (pkt51) }, + { .cmd = pkt53, .len = sizeof (pkt53) }, + { .cmd = pkt55, .len = sizeof (pkt55) }, + { .cmd = pkt57, .len = sizeof (pkt57) }, + { .cmd = pkt59, .len = sizeof (pkt59) }, + { .cmd = pkt61, .len = sizeof (pkt61) }, + { .cmd = pkt63, .len = sizeof (pkt63) }, + { .cmd = pkt65, .len = sizeof (pkt65) }, + { .cmd = pkt67, .len = sizeof (pkt67) }, + { .cmd = pkt69, .len = sizeof (pkt69) }, + { .cmd = pkt71, .len = sizeof (pkt71) }, + { .cmd = pkt73, .len = sizeof (pkt73) }, + { .cmd = pkt75, .len = sizeof (pkt75) }, }; /* Second init sequence * INIT2 */ static const unsigned char pkt187[] = { -0x0d, -0x23, -0x42, 0xca, 0x00, -0x00, 0x20, 0x7f, /* .#B... . */ -0x97, 0x37, 0xcf, 0xdf, 0x96, 0x26, 0xcf, 0xdf, /* .7...&.. */ -0x96, 0xff, 0x96, 0x9f, 0x22, 0x6d, 0x2e, 0x6a, /* ...."m.j */ -0xbf, 0x62, 0x23, 0x23, 0x83, 0xdd, 0x97, 0x26, /* .b##...& */ -0xaf, 0xdd, 0x97, 0x37, 0xaf, 0xa9, 0xcf, 0x70, /* ...7...p */ -0x18, 0xa9, 0xaf, 0x02, 0xef, 0x5d, 0xaf, 0xc5, /* .....].. */ -0xef, 0x2f, 0xff, 0xff, 0x96, 0xdf, 0x96, 0x6a, /* ./.....j */ -0xef, 0x20, 0xff, 0xff, 0x96, 0xdf, 0x96, 0x1a, /* . ...... */ -0x27, 0x0b, 0xef, 0x06, 0xaf, 0xf1, 0x81, 0x3a, /* '......: */ -0xff, 0x3f, 0x1d, 0x40, 0x19, 0xc1, 0x2e, 0xa3, /* .?.@.... */ -0xbf, 0xc2, 0x2e, 0x00, 0xdf, 0xff, 0x2d, 0x02, /* ......-. */ -0x5a, 0xbf, 0x22, 0xc1, 0x2e, 0xa3, 0xbf, 0x3c, /* Z."....< */ -0x23, 0x57, 0x23, 0x02, 0x2e, 0x31, 0x80, 0x05, /* #W#..1.. */ -0x27, 0x12, 0xef, 0x99, 0xaf, 0x10, 0xef, 0x9b, /* '....... */ -0xaf, 0x10, 0xef, 0x55, 0xaf, 0x3d, 0x23, 0x31, /* ...U.=#1 */ -0xef, 0x20, 0xff, 0x1a, 0x27, 0x05, 0xef, 0x27, /* . ..'..' */ -0xff, 0x06, 0x27, 0x05, 0x27, 0x3f, 0x80, 0x2b, /* ..'.'?.+ */ -0x0d, 0x05, 0x27, 0xe5, 0x31, 0x05, 0x81, 0xe5, /* ..'.1... */ -0x39, 0x05, 0x27, 0xc8, 0x46, 0x0e, 0x5b, 0xd3, /* 9.'.F.[. */ -0x45, 0xfd, 0x5a, 0x0f, 0x27, 0xd3, 0x45, 0xfa, /* E.Z.'.E. */ -0x5a, 0x0f, 0x27, 0xd3, 0x45, 0xf7, 0x5a, 0x41, /* Z.'.E.ZA */ -0x2e, 0xa1, 0xdf, 0x9f, 0x28, 0x41, 0x2e, 0xa1, /* ....(A.. */ -0xbf, 0x02, 0x2e, 0x58, 0x80, 0x05, 0x27, 0x9f, /* ...X..'. */ -0x22, 0xbf, 0x22, 0x1f, 0x20, 0xfd, 0x53, 0x3f, /* ".". .S? */ -0x20, 0x14, 0x1f, 0xfa, 0x55, 0x05, 0x27, 0x10, /* ...U.'. */ -0xef, 0xd0, 0x81, 0x65, 0xaf, 0x10, 0xef /* ...e... */ + 0x0d, + 0x23, + 0x42, 0xca, 0x00, + 0x00, 0x20, 0x7f, /* .#B... . */ + 0x97, 0x37, 0xcf, 0xdf, 0x96, 0x26, 0xcf, 0xdf, /* .7...&.. */ + 0x96, 0xff, 0x96, 0x9f, 0x22, 0x6d, 0x2e, 0x6a, /* ...."m.j */ + 0xbf, 0x62, 0x23, 0x23, 0x83, 0xdd, 0x97, 0x26, /* .b##...& */ + 0xaf, 0xdd, 0x97, 0x37, 0xaf, 0xa9, 0xcf, 0x70, /* ...7...p */ + 0x18, 0xa9, 0xaf, 0x02, 0xef, 0x5d, 0xaf, 0xc5, /* .....].. */ + 0xef, 0x2f, 0xff, 0xff, 0x96, 0xdf, 0x96, 0x6a, /* ./.....j */ + 0xef, 0x20, 0xff, 0xff, 0x96, 0xdf, 0x96, 0x1a, /* . ...... */ + 0x27, 0x0b, 0xef, 0x06, 0xaf, 0xf1, 0x81, 0x3a, /* '......: */ + 0xff, 0x3f, 0x1d, 0x40, 0x19, 0xc1, 0x2e, 0xa3, /* .?.@.... */ + 0xbf, 0xc2, 0x2e, 0x00, 0xdf, 0xff, 0x2d, 0x02, /* ......-. */ + 0x5a, 0xbf, 0x22, 0xc1, 0x2e, 0xa3, 0xbf, 0x3c, /* Z."....< */ + 0x23, 0x57, 0x23, 0x02, 0x2e, 0x31, 0x80, 0x05, /* #W#..1.. */ + 0x27, 0x12, 0xef, 0x99, 0xaf, 0x10, 0xef, 0x9b, /* '....... */ + 0xaf, 0x10, 0xef, 0x55, 0xaf, 0x3d, 0x23, 0x31, /* ...U.=#1 */ + 0xef, 0x20, 0xff, 0x1a, 0x27, 0x05, 0xef, 0x27, /* . ..'..' */ + 0xff, 0x06, 0x27, 0x05, 0x27, 0x3f, 0x80, 0x2b, /* ..'.'?.+ */ + 0x0d, 0x05, 0x27, 0xe5, 0x31, 0x05, 0x81, 0xe5, /* ..'.1... */ + 0x39, 0x05, 0x27, 0xc8, 0x46, 0x0e, 0x5b, 0xd3, /* 9.'.F.[. */ + 0x45, 0xfd, 0x5a, 0x0f, 0x27, 0xd3, 0x45, 0xfa, /* E.Z.'.E. */ + 0x5a, 0x0f, 0x27, 0xd3, 0x45, 0xf7, 0x5a, 0x41, /* Z.'.E.ZA */ + 0x2e, 0xa1, 0xdf, 0x9f, 0x28, 0x41, 0x2e, 0xa1, /* ....(A.. */ + 0xbf, 0x02, 0x2e, 0x58, 0x80, 0x05, 0x27, 0x9f, /* ...X..'. */ + 0x22, 0xbf, 0x22, 0x1f, 0x20, 0xfd, 0x53, 0x3f, /* ".". .S? */ + 0x20, 0x14, 0x1f, 0xfa, 0x55, 0x05, 0x27, 0x10, /* ...U.'. */ + 0xef, 0xd0, 0x81, 0x65, 0xaf, 0x10, 0xef /* ...e... */ }; static const unsigned char pkt189[] = { -0x42, 0x4a, 0x00, -0x64, 0x20, 0xd0, 0x81, 0x9c, /* BJ.d ... */ -0xaf, 0x10, 0xef, 0xd0, 0x81, 0x9a, 0xaf, 0x05, /* ........ */ -0x27, 0x11, 0x00, 0x51, 0x87, 0x91, 0x81, 0xd1, /* '..Q.... */ -0x6c, 0xd2, 0x75, 0xe2, 0x80, 0xf2, 0x80, 0xf0, /* l.u..... */ -0x57, 0xf4, 0x7b, 0xf8, 0x7e, 0xfc, 0x8b, 0x10, /* W.{.~... */ -0xcf, 0x7d, 0xff, 0x3f, 0x00, 0x20, 0xff, 0x00, /* .}.?. .. */ -0x13, 0x1a, 0x27, 0x07, 0x27, 0x05, 0x27, 0x01, /* ..'.'.'. */ -0x00, 0x11, 0x00, 0x21, 0x00, 0x31, 0x00, 0x31, /* ...!.1.1 */ -0x01, 0x32, 0x01, 0x33, 0x01, 0x33, 0x03, 0x43, /* .2.3.3.C */ -0x03, 0x53, 0x03, 0x63, 0x03 /* .S.c. */ + 0x42, 0x4a, 0x00, + 0x64, 0x20, 0xd0, 0x81, 0x9c, /* BJ.d ... */ + 0xaf, 0x10, 0xef, 0xd0, 0x81, 0x9a, 0xaf, 0x05, /* ........ */ + 0x27, 0x11, 0x00, 0x51, 0x87, 0x91, 0x81, 0xd1, /* '..Q.... */ + 0x6c, 0xd2, 0x75, 0xe2, 0x80, 0xf2, 0x80, 0xf0, /* l.u..... */ + 0x57, 0xf4, 0x7b, 0xf8, 0x7e, 0xfc, 0x8b, 0x10, /* W.{.~... */ + 0xcf, 0x7d, 0xff, 0x3f, 0x00, 0x20, 0xff, 0x00, /* .}.?. .. */ + 0x13, 0x1a, 0x27, 0x07, 0x27, 0x05, 0x27, 0x01, /* ..'.'.'. */ + 0x00, 0x11, 0x00, 0x21, 0x00, 0x31, 0x00, 0x31, /* ...!.1.1 */ + 0x01, 0x32, 0x01, 0x33, 0x01, 0x33, 0x03, 0x43, /* .2.3.3.C */ + 0x03, 0x53, 0x03, 0x63, 0x03 /* .S.c. */ }; static const unsigned char pkt191[] = { -0x42, 0xca, 0x00, -0x88, 0x20, 0x51, 0x85, 0x44, /* B... Q.D */ -0x1e, 0x03, 0x55, 0xc8, 0x46, 0x01, 0x5b, 0xe4, /* ..U.F.[. */ -0x2f, 0xc8, 0x50, 0x49, 0x1e, 0x16, 0x55, 0x37, /* /.PI..U7 */ -0x39, 0x0f, 0x27, 0x02, 0xef, 0x02, 0x2e, 0x2f, /* 9.'..../ */ -0x81, 0xfe, 0xcf, 0x08, 0xaf, 0xfe, 0xcf, 0x09, /* ........ */ -0xaf, 0xfe, 0xcf, 0x0b, 0xaf, 0x55, 0x81, 0x02, /* .....U.. */ -0xcf, 0x0f, 0x1c, 0x40, 0x18, 0x08, 0x42, 0x00, /* ...@..B. */ -0x5b, 0x20, 0x18, 0x3d, 0x23, 0x02, 0xaf, 0x10, /* [ .=#... */ -0xef, 0x55, 0xaf, 0x05, 0x27, 0x4a, 0x1e, 0x01, /* .U..'J.. */ -0x55, 0xe4, 0x2f, 0xab, 0x50, 0x4e, 0x1e, 0x01, /* U./.PN.. */ -0x55, 0x00, 0x2e, 0x0d, 0x7b, 0x55, 0x1e, 0x16, /* U...{U.. */ -0x55, 0x54, 0x85, 0xe4, 0x2f, 0xa2, 0x5b, 0x07, /* UT../.[. */ -0xef, 0x20, 0x80, 0xe4, 0x2f, 0x9e, 0x5a, 0xfe, /* . ../.Z. */ -0xcf, 0x0a, 0xaf, 0xfe, 0xcf, 0xfe, 0xcf, 0x41, /* .......A */ -0x2e, 0x44, 0xbf, 0xfe, 0xcf, 0x41, 0x2e, 0x45, /* .D...A.E */ -0xbf, 0xfe, 0xcf, 0x52, 0xaf, 0xfe, 0xcf, 0x53, /* ...R...S */ -0xaf, 0xfe, 0xcf, 0x5a, 0xaf, 0x05, 0x27, 0x58, /* ...Z..'X */ -0x1e, 0x0d, 0x55, 0x02, 0x44, 0x01, 0x5a, 0x00, /* ..U.D.Z. */ -0x2e, 0x54, 0x79, 0xfe, 0xcf, 0x75, 0xaf, 0xfe, /* .Ty..u.. */ -0xdf, 0x76, 0xbf, 0x41, 0x2e, 0xa4, 0xdf, 0xdf, /* .v.A.... */ -0x29, 0x41, 0x2e, 0xa4, 0xbf, 0x05, 0x27, 0x59, /* )A....'Y */ -0x1e, 0x03, 0x55, 0xfe, 0xcf, 0x10, 0xaf, 0x01, /* ..U..... */ -0x2e, 0x94, 0x76, 0x63, 0x1e, 0x1a, 0x55, 0x54, /* ..vc..UT */ -0x85, 0xe4, 0x2f, 0x73, 0x5b, 0x0c, 0xef, 0x20, /* ../s[.. */ -0x80, 0xe4, 0x2f, 0x6f, 0x5a, 0xf0, 0xef, 0x00, /* ../oZ... */ -0xff, 0x19, 0x27, 0x08, 0xef /* ..'.. */ + 0x42, 0xca, 0x00, + 0x88, 0x20, 0x51, 0x85, 0x44, /* B... Q.D */ + 0x1e, 0x03, 0x55, 0xc8, 0x46, 0x01, 0x5b, 0xe4, /* ..U.F.[. */ + 0x2f, 0xc8, 0x50, 0x49, 0x1e, 0x16, 0x55, 0x37, /* /.PI..U7 */ + 0x39, 0x0f, 0x27, 0x02, 0xef, 0x02, 0x2e, 0x2f, /* 9.'..../ */ + 0x81, 0xfe, 0xcf, 0x08, 0xaf, 0xfe, 0xcf, 0x09, /* ........ */ + 0xaf, 0xfe, 0xcf, 0x0b, 0xaf, 0x55, 0x81, 0x02, /* .....U.. */ + 0xcf, 0x0f, 0x1c, 0x40, 0x18, 0x08, 0x42, 0x00, /* ...@..B. */ + 0x5b, 0x20, 0x18, 0x3d, 0x23, 0x02, 0xaf, 0x10, /* [ .=#... */ + 0xef, 0x55, 0xaf, 0x05, 0x27, 0x4a, 0x1e, 0x01, /* .U..'J.. */ + 0x55, 0xe4, 0x2f, 0xab, 0x50, 0x4e, 0x1e, 0x01, /* U./.PN.. */ + 0x55, 0x00, 0x2e, 0x0d, 0x7b, 0x55, 0x1e, 0x16, /* U...{U.. */ + 0x55, 0x54, 0x85, 0xe4, 0x2f, 0xa2, 0x5b, 0x07, /* UT../.[. */ + 0xef, 0x20, 0x80, 0xe4, 0x2f, 0x9e, 0x5a, 0xfe, /* . ../.Z. */ + 0xcf, 0x0a, 0xaf, 0xfe, 0xcf, 0xfe, 0xcf, 0x41, /* .......A */ + 0x2e, 0x44, 0xbf, 0xfe, 0xcf, 0x41, 0x2e, 0x45, /* .D...A.E */ + 0xbf, 0xfe, 0xcf, 0x52, 0xaf, 0xfe, 0xcf, 0x53, /* ...R...S */ + 0xaf, 0xfe, 0xcf, 0x5a, 0xaf, 0x05, 0x27, 0x58, /* ...Z..'X */ + 0x1e, 0x0d, 0x55, 0x02, 0x44, 0x01, 0x5a, 0x00, /* ..U.D.Z. */ + 0x2e, 0x54, 0x79, 0xfe, 0xcf, 0x75, 0xaf, 0xfe, /* .Ty..u.. */ + 0xdf, 0x76, 0xbf, 0x41, 0x2e, 0xa4, 0xdf, 0xdf, /* .v.A.... */ + 0x29, 0x41, 0x2e, 0xa4, 0xbf, 0x05, 0x27, 0x59, /* )A....'Y */ + 0x1e, 0x03, 0x55, 0xfe, 0xcf, 0x10, 0xaf, 0x01, /* ..U..... */ + 0x2e, 0x94, 0x76, 0x63, 0x1e, 0x1a, 0x55, 0x54, /* ..vc..UT */ + 0x85, 0xe4, 0x2f, 0x73, 0x5b, 0x0c, 0xef, 0x20, /* ../s[.. */ + 0x80, 0xe4, 0x2f, 0x6f, 0x5a, 0xf0, 0xef, 0x00, /* ../oZ... */ + 0xff, 0x19, 0x27, 0x08, 0xef /* ..'.. */ }; static const unsigned char pkt193[] = { -0x42, 0xa2, 0x00, -0xec, 0x20, 0x06, 0xaf, 0xfe, /* B... ... */ -0xcf, 0x5f, 0x9f, 0x06, 0x25, 0xfb, 0x55, 0xfe, /* ._..%.U. */ -0xcf, 0xfe, 0xcf, 0x41, 0x2e, 0x40, 0xbf, 0xfe, /* ...A.@.. */ -0xcf, 0x41, 0x2e, 0x41, 0xbf, 0xfe, 0xcf, 0x41, /* .A.A...A */ -0x2e, 0x42, 0xbf, 0x05, 0x27, 0x66, 0x1e, 0x0b, /* .B..'f.. */ -0x55, 0xc5, 0xef, 0x2f, 0xff, 0x1a, 0x27, 0x0b, /* U../..'. */ -0xef, 0x06, 0xaf, 0xfe, 0xcf, 0xfe, 0xdf, 0x06, /* ........ */ -0x27, 0x01, 0x0e, 0x06, 0x25, 0xf9, 0x55, 0x05, /* '...%.U. */ -0x27, 0x7d, 0x1e, 0x0c, 0x55, 0x02, 0x2e, 0x29, /* '}..U..) */ -0x81, 0xe4, 0x2f, 0x47, 0x5a, 0xfe, 0xcf, 0xfe, /* ../GZ... */ -0xdf, 0x1b, 0x27, 0xfe, 0xcf, 0x36, 0x03, 0xfe, /* ..'..6.. */ -0xdf, 0x3f, 0x02, 0x9f, 0x9d, 0x05, 0x27, 0x7e, /* .?....'~ */ -0x1e, 0x0c, 0x55, 0x02, 0x2e, 0x29, 0x81, 0xe4, /* ..U..).. */ -0x2f, 0x38, 0x5a, 0xfe, 0xcf, 0xfe, 0xdf, 0x1b, /* /8Z..... */ -0x27, 0x07, 0x80, 0xf6, 0x97, 0xff, 0xaf, 0x00, /* '....... */ -0x2e, 0xa7, 0x8a, 0x05, 0x27, 0x61, 0x74, 0xff, /* ....'at. */ -0x96, 0xc6, 0x2e, 0x01, 0xdf, 0x3f, 0x2c, 0xdd, /* .....?,. */ -0x9f, 0x05, 0x27, 0xf9, 0x35, 0xc1, 0x2e, 0x4e, /* ..'.5..N */ -0xdf, 0x0f, 0x1d, 0x09, 0x27, 0x5f, 0x02, 0xc1, /* ....'_.. */ -0x2e, 0x4e, 0xbf, 0x05, 0x27, 0x9f, 0x22, 0x02, /* .N..'.". */ -0x2e, 0xe7, 0x8c, 0x05, 0x27 /* ....' */ + 0x42, 0xa2, 0x00, + 0xec, 0x20, 0x06, 0xaf, 0xfe, /* B... ... */ + 0xcf, 0x5f, 0x9f, 0x06, 0x25, 0xfb, 0x55, 0xfe, /* ._..%.U. */ + 0xcf, 0xfe, 0xcf, 0x41, 0x2e, 0x40, 0xbf, 0xfe, /* ...A.@.. */ + 0xcf, 0x41, 0x2e, 0x41, 0xbf, 0xfe, 0xcf, 0x41, /* .A.A...A */ + 0x2e, 0x42, 0xbf, 0x05, 0x27, 0x66, 0x1e, 0x0b, /* .B..'f.. */ + 0x55, 0xc5, 0xef, 0x2f, 0xff, 0x1a, 0x27, 0x0b, /* U../..'. */ + 0xef, 0x06, 0xaf, 0xfe, 0xcf, 0xfe, 0xdf, 0x06, /* ........ */ + 0x27, 0x01, 0x0e, 0x06, 0x25, 0xf9, 0x55, 0x05, /* '...%.U. */ + 0x27, 0x7d, 0x1e, 0x0c, 0x55, 0x02, 0x2e, 0x29, /* '}..U..) */ + 0x81, 0xe4, 0x2f, 0x47, 0x5a, 0xfe, 0xcf, 0xfe, /* ../GZ... */ + 0xdf, 0x1b, 0x27, 0xfe, 0xcf, 0x36, 0x03, 0xfe, /* ..'..6.. */ + 0xdf, 0x3f, 0x02, 0x9f, 0x9d, 0x05, 0x27, 0x7e, /* .?....'~ */ + 0x1e, 0x0c, 0x55, 0x02, 0x2e, 0x29, 0x81, 0xe4, /* ..U..).. */ + 0x2f, 0x38, 0x5a, 0xfe, 0xcf, 0xfe, 0xdf, 0x1b, /* /8Z..... */ + 0x27, 0x07, 0x80, 0xf6, 0x97, 0xff, 0xaf, 0x00, /* '....... */ + 0x2e, 0xa7, 0x8a, 0x05, 0x27, 0x61, 0x74, 0xff, /* ....'at. */ + 0x96, 0xc6, 0x2e, 0x01, 0xdf, 0x3f, 0x2c, 0xdd, /* .....?,. */ + 0x9f, 0x05, 0x27, 0xf9, 0x35, 0xc1, 0x2e, 0x4e, /* ..'.5..N */ + 0xdf, 0x0f, 0x1d, 0x09, 0x27, 0x5f, 0x02, 0xc1, /* ....'_.. */ + 0x2e, 0x4e, 0xbf, 0x05, 0x27, 0x9f, 0x22, 0x02, /* .N..'.". */ + 0x2e, 0xe7, 0x8c, 0x05, 0x27 /* ....' */ }; static const unsigned char pkt195[] = { -0x42, 0xca, 0x00, -0x3c, 0x21, 0x51, 0x85, 0x01, /* B...Z. */ -0x27, 0x2d, 0x82, 0x40, 0x82, 0x12, 0x82, 0x12, /* '-.@.... */ -0x82, 0x9d, 0xbf, 0xff, 0x97, 0x08, 0x10, 0x09, /* ........ */ -0x27, 0x0f, 0x1c, 0x5c, 0x46, 0x03, 0x5b, 0x02, /* '..\F.[. */ -0x1e, 0x04, 0x53, 0x02, 0xef, 0x02, 0x50, 0x03, /* ..S...P. */ -0x1e, 0x00, 0x53, 0x03, 0xef, 0x69, 0xaf, 0x3f, /* ..S..i.? */ -0x80, 0x1b, 0x0d, 0xe1, 0x97, 0x0f, 0x1c, 0x69, /* .......i */ -0xdf, 0xdf, 0x01, 0x00, 0x53, 0x00, 0xff, 0xe0, /* ....S... */ -0x97, 0x76, 0x80, 0x04, 0x10, 0x07, 0x82, 0x0f, /* .v...... */ -0x1e, 0x00, 0x5f, 0x0f, 0xef, 0x6a, 0xaf, 0xc1, /* .._..j.. */ -0x2e, 0x47, 0xdf, 0xf0, 0x1d, 0x5f, 0x02, 0xc1, /* .G..._.. */ -0x2e, 0x47, 0xbf, 0x10, 0x0d, 0x05, 0x27, 0x01, /* .G....'. */ -0x2e, 0x1a, 0x87, 0xf7, 0xef, 0x16, 0x80, 0x52, /* .......R */ -0x80, 0x16, 0x82, 0x02, 0x2e, 0xb7, 0x85, 0x55, /* .......U */ -0x82, 0x02, 0x2e, 0x60, 0x80, 0x01, 0x2e, 0x84, /* ...`.... */ -0x83, 0x26, 0x40, 0x00, 0x5b, 0x3b, 0x33, 0x5c, /* .&@.[;3\ */ -0x47, 0x09, 0x5b, 0x6c, 0x38, 0x3b, 0x43, 0x00, /* G.[l8;C. */ -0x5b, 0x6c, 0x30, 0x41, 0x2e, 0x71, 0xdf, 0xc1, /* [l0A.q.. */ -0x2e, 0x72, 0xdf, 0xbf, 0x03, 0x01, 0x55, 0x01, /* .r....U. */ -0x2e, 0x98, 0x83, 0x01, 0x2e, 0x63, 0x84, 0x01, /* .....c.. */ -0x2e, 0x71, 0x87, 0x05, 0x27, 0x3b, 0x40, 0x01, /* .q..';@. */ -0x5b, 0x02, 0xef, 0x0c, 0xaf, 0x05, 0x27, 0x52, /* [.....'R */ -0xcf, 0xcb, 0xaf, 0x53, 0xdf /* ...S. */ + 0x42, 0xca, 0x00, + 0xc6, 0x26, 0x02, 0x2e, 0x22, /* B...&.." */ + 0x87, 0x09, 0x46, 0x02, 0x5b, 0x2d, 0x82, 0x90, /* ..F.[-.. */ + 0xaf, 0x91, 0xbf, 0x01, 0x2e, 0xbd, 0x84, 0x02, /* ........ */ + 0x2e, 0x14, 0x85, 0x0c, 0x3e, 0xe8, 0x5a, 0x05, /* ....>.Z. */ + 0x27, 0x2d, 0x82, 0x40, 0x82, 0x12, 0x82, 0x12, /* '-.@.... */ + 0x82, 0x9d, 0xbf, 0xff, 0x97, 0x08, 0x10, 0x09, /* ........ */ + 0x27, 0x0f, 0x1c, 0x5c, 0x46, 0x03, 0x5b, 0x02, /* '..\F.[. */ + 0x1e, 0x04, 0x53, 0x02, 0xef, 0x02, 0x50, 0x03, /* ..S...P. */ + 0x1e, 0x00, 0x53, 0x03, 0xef, 0x69, 0xaf, 0x3f, /* ..S..i.? */ + 0x80, 0x1b, 0x0d, 0xe1, 0x97, 0x0f, 0x1c, 0x69, /* .......i */ + 0xdf, 0xdf, 0x01, 0x00, 0x53, 0x00, 0xff, 0xe0, /* ....S... */ + 0x97, 0x76, 0x80, 0x04, 0x10, 0x07, 0x82, 0x0f, /* .v...... */ + 0x1e, 0x00, 0x5f, 0x0f, 0xef, 0x6a, 0xaf, 0xc1, /* .._..j.. */ + 0x2e, 0x47, 0xdf, 0xf0, 0x1d, 0x5f, 0x02, 0xc1, /* .G..._.. */ + 0x2e, 0x47, 0xbf, 0x10, 0x0d, 0x05, 0x27, 0x01, /* .G....'. */ + 0x2e, 0x1a, 0x87, 0xf7, 0xef, 0x16, 0x80, 0x52, /* .......R */ + 0x80, 0x16, 0x82, 0x02, 0x2e, 0xb7, 0x85, 0x55, /* .......U */ + 0x82, 0x02, 0x2e, 0x60, 0x80, 0x01, 0x2e, 0x84, /* ...`.... */ + 0x83, 0x26, 0x40, 0x00, 0x5b, 0x3b, 0x33, 0x5c, /* .&@.[;3\ */ + 0x47, 0x09, 0x5b, 0x6c, 0x38, 0x3b, 0x43, 0x00, /* G.[l8;C. */ + 0x5b, 0x6c, 0x30, 0x41, 0x2e, 0x71, 0xdf, 0xc1, /* [l0A.q.. */ + 0x2e, 0x72, 0xdf, 0xbf, 0x03, 0x01, 0x55, 0x01, /* .r....U. */ + 0x2e, 0x98, 0x83, 0x01, 0x2e, 0x63, 0x84, 0x01, /* .....c.. */ + 0x2e, 0x71, 0x87, 0x05, 0x27, 0x3b, 0x40, 0x01, /* .q..';@. */ + 0x5b, 0x02, 0xef, 0x0c, 0xaf, 0x05, 0x27, 0x52, /* [.....'R */ + 0xcf, 0xcb, 0xaf, 0x53, 0xdf /* ...S. */ }; static const unsigned char pkt229[] = { -0x42, 0xca, 0x00, -0x2a, 0x27, 0xcc, 0xbf, 0xdf, /* B..*'... */ -0x22, 0x01, 0x55, 0xff, 0x22, 0x01, 0x54, 0x0e, /* ".U.".T. */ -0xef, 0xc9, 0xaf, 0x05, 0x27, 0x0e, 0xcf, 0x6e, /* ....'..n */ -0x1c, 0x49, 0xdf, 0x10, 0x1d, 0x3f, 0x02, 0x49, /* .I...?.I */ -0xaf, 0x0d, 0x44, 0x06, 0x5a, 0x0a, 0x41, 0x03, /* ..D.Z.A. */ -0x5b, 0x49, 0x43, 0x02, 0x5a, 0x48, 0x26, 0x00, /* [IC.ZH&. */ -0x55, 0x49, 0x30, 0x9f, 0x2c, 0x05, 0x5a, 0xdf, /* UI0.,.Z. */ -0x2c, 0x4d, 0x5a, 0x0e, 0x41, 0x16, 0x5b, 0x0c, /* ,MZ.A.[. */ -0x46, 0x14, 0x5a, 0x9f, 0x22, 0x1c, 0xaf, 0x21, /* F.Z."..! */ -0xaf, 0x02, 0x2e, 0xb4, 0x87, 0x03, 0x5a, 0x9f, /* ......Z. */ -0x2c, 0x05, 0x5a, 0x9f, 0x22, 0x04, 0x50, 0x9f, /* ,.Z.".P. */ -0x22, 0x0e, 0x3e, 0x0e, 0x3d, 0x00, 0x5b, 0x5f, /* ".>.=.[_ */ -0xef, 0x1d, 0xaf, 0x49, 0xcf, 0x87, 0x1c, 0x01, /* ...I.... */ -0x18, 0x49, 0xaf, 0x34, 0x50, 0x20, 0x26, 0x08, /* .I.4P &. */ -0x55, 0x1f, 0xcf, 0x48, 0xdf, 0xff, 0x2d, 0x00, /* U..H..-. */ -0x5b, 0xff, 0x21, 0x3f, 0x00, 0x00, 0x53, 0xff, /* [.!?..S. */ -0xef, 0x1f, 0xaf, 0x47, 0xdf, 0x1c, 0xcf, 0x3f, /* ...G...? */ -0x00, 0x1c, 0xaf, 0x1d, 0xcf, 0x48, 0xdf, 0x3f, /* .....H.? */ -0x00, 0x1d, 0xaf, 0xff, 0x22, 0x1f, 0x54, 0xff, /* ....".T. */ -0x2d, 0x03, 0x5b, 0xff, 0x1e, 0x19, 0x5b, 0x60, /* -.[...[` */ -0x10, 0x02, 0x50, 0x60, 0x1e, 0x0a, 0x52, 0x60, /* ..P`..R` */ -0x16, 0x1d, 0xaf, 0x49, 0x30, 0x49, 0x3c, 0x12, /* ...I0I<. */ -0x5b, 0x21, 0xcf, 0x47, 0xdf, 0x3f, 0x00, 0x1c, /* [!.G.?.. */ -0xaf, 0x21, 0x23, 0x0c, 0x50, 0x59, 0x1e, 0x0a, /* .!#.PY.. */ -0x52, 0x49, 0x34, 0x01, 0x5a, 0x21, 0x23, 0x06, /* RI4.Z!#. */ -0x50, 0x21, 0xcf, 0x47, 0xdf /* P!.G. */ + 0x42, 0xca, 0x00, + 0x2a, 0x27, 0xcc, 0xbf, 0xdf, /* B..*'... */ + 0x22, 0x01, 0x55, 0xff, 0x22, 0x01, 0x54, 0x0e, /* ".U.".T. */ + 0xef, 0xc9, 0xaf, 0x05, 0x27, 0x0e, 0xcf, 0x6e, /* ....'..n */ + 0x1c, 0x49, 0xdf, 0x10, 0x1d, 0x3f, 0x02, 0x49, /* .I...?.I */ + 0xaf, 0x0d, 0x44, 0x06, 0x5a, 0x0a, 0x41, 0x03, /* ..D.Z.A. */ + 0x5b, 0x49, 0x43, 0x02, 0x5a, 0x48, 0x26, 0x00, /* [IC.ZH&. */ + 0x55, 0x49, 0x30, 0x9f, 0x2c, 0x05, 0x5a, 0xdf, /* UI0.,.Z. */ + 0x2c, 0x4d, 0x5a, 0x0e, 0x41, 0x16, 0x5b, 0x0c, /* ,MZ.A.[. */ + 0x46, 0x14, 0x5a, 0x9f, 0x22, 0x1c, 0xaf, 0x21, /* F.Z."..! */ + 0xaf, 0x02, 0x2e, 0xb4, 0x87, 0x03, 0x5a, 0x9f, /* ......Z. */ + 0x2c, 0x05, 0x5a, 0x9f, 0x22, 0x04, 0x50, 0x9f, /* ,.Z.".P. */ + 0x22, 0x0e, 0x3e, 0x0e, 0x3d, 0x00, 0x5b, 0x5f, /* ".>.=.[_ */ + 0xef, 0x1d, 0xaf, 0x49, 0xcf, 0x87, 0x1c, 0x01, /* ...I.... */ + 0x18, 0x49, 0xaf, 0x34, 0x50, 0x20, 0x26, 0x08, /* .I.4P &. */ + 0x55, 0x1f, 0xcf, 0x48, 0xdf, 0xff, 0x2d, 0x00, /* U..H..-. */ + 0x5b, 0xff, 0x21, 0x3f, 0x00, 0x00, 0x53, 0xff, /* [.!?..S. */ + 0xef, 0x1f, 0xaf, 0x47, 0xdf, 0x1c, 0xcf, 0x3f, /* ...G...? */ + 0x00, 0x1c, 0xaf, 0x1d, 0xcf, 0x48, 0xdf, 0x3f, /* .....H.? */ + 0x00, 0x1d, 0xaf, 0xff, 0x22, 0x1f, 0x54, 0xff, /* ....".T. */ + 0x2d, 0x03, 0x5b, 0xff, 0x1e, 0x19, 0x5b, 0x60, /* -.[...[` */ + 0x10, 0x02, 0x50, 0x60, 0x1e, 0x0a, 0x52, 0x60, /* ..P`..R` */ + 0x16, 0x1d, 0xaf, 0x49, 0x30, 0x49, 0x3c, 0x12, /* ...I0I<. */ + 0x5b, 0x21, 0xcf, 0x47, 0xdf, 0x3f, 0x00, 0x1c, /* [!.G.?.. */ + 0xaf, 0x21, 0x23, 0x0c, 0x50, 0x59, 0x1e, 0x0a, /* .!#.PY.. */ + 0x52, 0x49, 0x34, 0x01, 0x5a, 0x21, 0x23, 0x06, /* RI4.Z!#. */ + 0x50, 0x21, 0xcf, 0x47, 0xdf /* P!.G. */ }; static const unsigned char pkt231[] = { -0x42, 0xca, 0x00, -0x8e, 0x27, 0x3f, 0x00, 0x21, /* B...'?.! */ -0xaf, 0x01, 0x50, 0x06, 0x1e, 0xf4, 0x5f, 0x05, /* ..P..._. */ -0x27, 0x1e, 0x23, 0x0d, 0xcf, 0x06, 0x1c, 0x1a, /* '.#..... */ -0x54, 0x48, 0xcf, 0xdf, 0x2d, 0x00, 0x5b, 0xdf, /* TH..-.[. */ -0x21, 0x09, 0x27, 0x1f, 0x22, 0xbf, 0x22, 0x1a, /* !.'.".". */ -0x27, 0xc0, 0x2e, 0x96, 0xdf, 0x7f, 0x1f, 0x02, /* '....... */ -0x54, 0x3f, 0x20, 0xc0, 0x2e, 0x96, 0xbf, 0x59, /* T? ....Y */ -0x80, 0x40, 0x2e, 0x97, 0xbf, 0xc0, 0x2e, 0x95, /* .@...... */ -0xdf, 0x76, 0x80, 0x1e, 0xbf, 0x0c, 0x42, 0x02, /* .v....B. */ -0x5b, 0x9f, 0x22, 0x40, 0x2e, 0x96, 0xbf, 0x05, /* [."@.... */ -0x27, 0x0d, 0xcf, 0x06, 0x1c, 0x06, 0x1e, 0x00, /* '....... */ -0x54, 0x0d, 0x27, 0x0c, 0x27, 0x09, 0x46, 0x0d, /* T.'.'.F. */ -0x5b, 0x02, 0x2e, 0x38, 0x86, 0x07, 0x52, 0x0f, /* [..8..R. */ -0xcf, 0x01, 0x16, 0x02, 0x53, 0x02, 0x2e, 0xfe, /* ....S... */ -0x87, 0x04, 0x50, 0xf4, 0xaf, 0x02, 0x50, 0xf2, /* ..P...P. */ -0xcf, 0x02, 0x10, 0x0f, 0xaf, 0x05, 0x27, 0x5a, /* ......'Z */ -0xcf, 0xdf, 0x22, 0x10, 0x54, 0x3e, 0xdf, 0x3f, /* ..".T>.? */ -0x20, 0x3f, 0x1f, 0x0a, 0x52, 0xbf, 0x22, 0x3e, /* ?..R."> */ -0xbf, 0x3d, 0xdf, 0x3f, 0x20, 0xdf, 0x03, 0x02, /* .=.? ... */ -0x52, 0xbf, 0x22, 0x3d, 0xbf, 0x0c, 0x27, 0x3d, /* R."=..'= */ -0xbf, 0x0d, 0x27, 0x3e, 0xbf, 0x0d, 0x27, 0x0d, /* ..'>..'. */ -0x27, 0xbf, 0x22, 0x3e, 0xbf, 0x3d, 0xbf, 0x05, /* '.">.=.. */ -0x27, 0x0f, 0x1c, 0x69, 0xdf, 0xdf, 0x01, 0x00, /* '..i.... */ -0x53, 0x00, 0xff, 0x05, 0x27, 0x2d, 0x82, 0x40, /* S...'-.@ */ -0x82, 0x12, 0x82, 0x12, 0x82, 0x9d, 0xbf, 0xff, /* ........ */ -0x97, 0x08, 0x10, 0x09, 0x27 /* ....' */ + 0x42, 0xca, 0x00, + 0x8e, 0x27, 0x3f, 0x00, 0x21, /* B...'?.! */ + 0xaf, 0x01, 0x50, 0x06, 0x1e, 0xf4, 0x5f, 0x05, /* ..P..._. */ + 0x27, 0x1e, 0x23, 0x0d, 0xcf, 0x06, 0x1c, 0x1a, /* '.#..... */ + 0x54, 0x48, 0xcf, 0xdf, 0x2d, 0x00, 0x5b, 0xdf, /* TH..-.[. */ + 0x21, 0x09, 0x27, 0x1f, 0x22, 0xbf, 0x22, 0x1a, /* !.'.".". */ + 0x27, 0xc0, 0x2e, 0x96, 0xdf, 0x7f, 0x1f, 0x02, /* '....... */ + 0x54, 0x3f, 0x20, 0xc0, 0x2e, 0x96, 0xbf, 0x59, /* T? ....Y */ + 0x80, 0x40, 0x2e, 0x97, 0xbf, 0xc0, 0x2e, 0x95, /* .@...... */ + 0xdf, 0x76, 0x80, 0x1e, 0xbf, 0x0c, 0x42, 0x02, /* .v....B. */ + 0x5b, 0x9f, 0x22, 0x40, 0x2e, 0x96, 0xbf, 0x05, /* [."@.... */ + 0x27, 0x0d, 0xcf, 0x06, 0x1c, 0x06, 0x1e, 0x00, /* '....... */ + 0x54, 0x0d, 0x27, 0x0c, 0x27, 0x09, 0x46, 0x0d, /* T.'.'.F. */ + 0x5b, 0x02, 0x2e, 0x38, 0x86, 0x07, 0x52, 0x0f, /* [..8..R. */ + 0xcf, 0x01, 0x16, 0x02, 0x53, 0x02, 0x2e, 0xfe, /* ....S... */ + 0x87, 0x04, 0x50, 0xf4, 0xaf, 0x02, 0x50, 0xf2, /* ..P...P. */ + 0xcf, 0x02, 0x10, 0x0f, 0xaf, 0x05, 0x27, 0x5a, /* ......'Z */ + 0xcf, 0xdf, 0x22, 0x10, 0x54, 0x3e, 0xdf, 0x3f, /* ..".T>.? */ + 0x20, 0x3f, 0x1f, 0x0a, 0x52, 0xbf, 0x22, 0x3e, /* ?..R."> */ + 0xbf, 0x3d, 0xdf, 0x3f, 0x20, 0xdf, 0x03, 0x02, /* .=.? ... */ + 0x52, 0xbf, 0x22, 0x3d, 0xbf, 0x0c, 0x27, 0x3d, /* R."=..'= */ + 0xbf, 0x0d, 0x27, 0x3e, 0xbf, 0x0d, 0x27, 0x0d, /* ..'>..'. */ + 0x27, 0xbf, 0x22, 0x3e, 0xbf, 0x3d, 0xbf, 0x05, /* '.">.=.. */ + 0x27, 0x0f, 0x1c, 0x69, 0xdf, 0xdf, 0x01, 0x00, /* '..i.... */ + 0x53, 0x00, 0xff, 0x05, 0x27, 0x2d, 0x82, 0x40, /* S...'-.@ */ + 0x82, 0x12, 0x82, 0x12, 0x82, 0x9d, 0xbf, 0xff, /* ........ */ + 0x97, 0x08, 0x10, 0x09, 0x27 /* ....' */ }; static const unsigned char pkt233[] = { -0x42, 0x24, 0x00, -0xf2, 0x27, 0x0f, 0x1c, 0x5c, /* B$..'..\ */ -0x46, 0x03, 0x5b, 0x02, 0x1e, 0x04, 0x53, 0x02, /* F.[...S. */ -0xef, 0x02, 0x50, 0x03, 0x1e, 0x00, 0x53, 0x03, /* ..P...S. */ -0xef, 0x69, 0xaf, 0x05, 0x27, 0x14, 0xef, 0xf4, /* .i..'... */ -0xaf, 0x00, 0xef, 0xf5, 0xaf, 0x05, 0x27 /* ......' */ + 0x42, 0x24, 0x00, + 0xf2, 0x27, 0x0f, 0x1c, 0x5c, /* B$..'..\ */ + 0x46, 0x03, 0x5b, 0x02, 0x1e, 0x04, 0x53, 0x02, /* F.[...S. */ + 0xef, 0x02, 0x50, 0x03, 0x1e, 0x00, 0x53, 0x03, /* ..P...S. */ + 0xef, 0x69, 0xaf, 0x05, 0x27, 0x14, 0xef, 0xf4, /* .i..'... */ + 0xaf, 0x00, 0xef, 0xf5, 0xaf, 0x05, 0x27 /* ......' */ }; static const unsigned char pkt235[] = { -0x42, 0xca, 0x00, -0x03, 0x28, 0x0c, 0x42, 0x00, /* B...(.B. */ -0x5b, 0x18, 0x23, 0x00, 0xef, 0x0c, 0xaf, 0x0e, /* [.#..... */ -0xcf, 0xe0, 0x1c, 0x0e, 0xaf, 0x0a, 0x40, 0x02, /* ......@. */ -0x5a, 0x3b, 0x46, 0x00, 0x5a, 0x05, 0x27, 0x37, /* Z;F.Z.'7 */ -0x43, 0xfc, 0x5b, 0x08, 0xef, 0x0c, 0xaf, 0x0d, /* C.[..... */ -0x40, 0x0a, 0x5a, 0xee, 0xcf, 0x64, 0x1e, 0x01, /* @.Z..d.. */ -0x5e, 0x0c, 0x3b, 0x05, 0x27, 0x0d, 0x30, 0x0c, /* ^.;.'.0. */ -0x35, 0xbf, 0x22, 0xc0, 0x2e, 0x96, 0xbf, 0x05, /* 5."..... */ -0x27, 0x0e, 0x45, 0x02, 0x5b, 0x02, 0x2e, 0x30, /* '.E.[..0 */ -0x88, 0x01, 0x50, 0x02, 0x2e, 0x3a, 0x88, 0x0d, /* ..P..:.. */ -0x41, 0x24, 0x5a, 0x0d, 0x42, 0x14, 0x5a, 0x02, /* A$Z.B.Z. */ -0x2e, 0x2f, 0x79, 0x02, 0x2e, 0x8f, 0x88, 0x19, /* ./y..... */ -0xcf, 0xfe, 0x1e, 0x03, 0x5c, 0x0e, 0x3d, 0x0d, /* ....\.=. */ -0x39, 0x0d, 0x3b, 0x0c, 0x27, 0x0d, 0x27, 0x02, /* 9.;.'.'. */ -0x2e, 0xae, 0x88, 0x19, 0xcf, 0x02, 0x1e, 0xf9, /* ........ */ -0x5a, 0x0e, 0x3e, 0x0d, 0x3a, 0x0d, 0x33, 0x0c, /* Z.>.:.3. */ -0x27, 0xe4, 0x37, 0x02, 0x2e, 0x8b, 0x89, 0xe4, /* '.7..... */ -0x3f, 0x02, 0x2e, 0x80, 0x89, 0x0d, 0x45, 0x61, /* ?.....Ea */ -0x5b, 0x18, 0xcf, 0xdf, 0x22, 0x6b, 0x54, 0x0d, /* [..."kT. */ -0x3b, 0x02, 0x2e, 0xab, 0x78, 0x02, 0x2e, 0x8b, /* ;...x... */ -0x89, 0x02, 0x2e, 0x80, 0x89, 0x0d, 0x42, 0x07, /* ......B. */ -0x5a, 0x0d, 0x45, 0x53, 0x5b, 0x18, 0xcf, 0xdf, /* Z.ES[... */ -0x22, 0x5d, 0x54, 0x0d, 0x33, 0x02, 0x2e, 0xab, /* "]T.3... */ -0x78, 0x15, 0xcf, 0x1a, 0xaf, 0xe4, 0x37, 0x02, /* x.....7. */ -0x2e, 0x8b, 0x89, 0x15, 0xcf, 0x1b, 0xaf, 0xe4, /* ........ */ -0x3f, 0x0d, 0xcf, 0x60, 0x1c /* ?..`. */ + 0x42, 0xca, 0x00, + 0x03, 0x28, 0x0c, 0x42, 0x00, /* B...(.B. */ + 0x5b, 0x18, 0x23, 0x00, 0xef, 0x0c, 0xaf, 0x0e, /* [.#..... */ + 0xcf, 0xe0, 0x1c, 0x0e, 0xaf, 0x0a, 0x40, 0x02, /* ......@. */ + 0x5a, 0x3b, 0x46, 0x00, 0x5a, 0x05, 0x27, 0x37, /* Z;F.Z.'7 */ + 0x43, 0xfc, 0x5b, 0x08, 0xef, 0x0c, 0xaf, 0x0d, /* C.[..... */ + 0x40, 0x0a, 0x5a, 0xee, 0xcf, 0x64, 0x1e, 0x01, /* @.Z..d.. */ + 0x5e, 0x0c, 0x3b, 0x05, 0x27, 0x0d, 0x30, 0x0c, /* ^.;.'.0. */ + 0x35, 0xbf, 0x22, 0xc0, 0x2e, 0x96, 0xbf, 0x05, /* 5."..... */ + 0x27, 0x0e, 0x45, 0x02, 0x5b, 0x02, 0x2e, 0x30, /* '.E.[..0 */ + 0x88, 0x01, 0x50, 0x02, 0x2e, 0x3a, 0x88, 0x0d, /* ..P..:.. */ + 0x41, 0x24, 0x5a, 0x0d, 0x42, 0x14, 0x5a, 0x02, /* A$Z.B.Z. */ + 0x2e, 0x2f, 0x79, 0x02, 0x2e, 0x8f, 0x88, 0x19, /* ./y..... */ + 0xcf, 0xfe, 0x1e, 0x03, 0x5c, 0x0e, 0x3d, 0x0d, /* ....\.=. */ + 0x39, 0x0d, 0x3b, 0x0c, 0x27, 0x0d, 0x27, 0x02, /* 9.;.'.'. */ + 0x2e, 0xae, 0x88, 0x19, 0xcf, 0x02, 0x1e, 0xf9, /* ........ */ + 0x5a, 0x0e, 0x3e, 0x0d, 0x3a, 0x0d, 0x33, 0x0c, /* Z.>.:.3. */ + 0x27, 0xe4, 0x37, 0x02, 0x2e, 0x8b, 0x89, 0xe4, /* '.7..... */ + 0x3f, 0x02, 0x2e, 0x80, 0x89, 0x0d, 0x45, 0x61, /* ?.....Ea */ + 0x5b, 0x18, 0xcf, 0xdf, 0x22, 0x6b, 0x54, 0x0d, /* [..."kT. */ + 0x3b, 0x02, 0x2e, 0xab, 0x78, 0x02, 0x2e, 0x8b, /* ;...x... */ + 0x89, 0x02, 0x2e, 0x80, 0x89, 0x0d, 0x42, 0x07, /* ......B. */ + 0x5a, 0x0d, 0x45, 0x53, 0x5b, 0x18, 0xcf, 0xdf, /* Z.ES[... */ + 0x22, 0x5d, 0x54, 0x0d, 0x33, 0x02, 0x2e, 0xab, /* "]T.3... */ + 0x78, 0x15, 0xcf, 0x1a, 0xaf, 0xe4, 0x37, 0x02, /* x.....7. */ + 0x2e, 0x8b, 0x89, 0x15, 0xcf, 0x1b, 0xaf, 0xe4, /* ........ */ + 0x3f, 0x0d, 0xcf, 0x60, 0x1c /* ?..`. */ }; static const unsigned char pkt237[] = { -0x42, 0xca, 0x00, -0x67, 0x28, 0xdf, 0x22, 0x01, /* B..g(.". */ -0x55, 0x02, 0x2e, 0xdf, 0x78, 0x16, 0xcf, 0x13, /* U...x... */ -0xdf, 0x2a, 0x1e, 0x00, 0x2e, 0x04, 0x5f, 0x2a, /* .*...._* */ -0x1f, 0x00, 0x2e, 0x01, 0x5f, 0x02, 0x2e, 0xdf, /* ...._... */ -0x78, 0xbf, 0x03, 0x40, 0x54, 0x20, 0x52, 0x02, /* x..@T R. */ -0x2e, 0x80, 0x89, 0x9f, 0x22, 0x1a, 0xaf, 0x18, /* ...."... */ -0xcf, 0x12, 0xdf, 0xbf, 0x03, 0x00, 0x53, 0x29, /* ......S) */ -0x50, 0x02, 0x2e, 0x8f, 0x88, 0x02, 0x2e, 0x74, /* P......t */ -0x89, 0x9f, 0x22, 0x1b, 0xaf, 0x02, 0x2e, 0x2e, /* .."..... */ -0x88, 0x02, 0x2e, 0xab, 0x78, 0x0e, 0xcf, 0x9f, /* ....x... */ -0x1c, 0x0e, 0xaf, 0x05, 0x27, 0x0e, 0xcf, 0x5f, /* ....'.._ */ -0x2d, 0x05, 0x5a, 0x9f, 0x2b, 0x5f, 0x29, 0x0e, /* -.Z.+_). */ -0xaf, 0x5f, 0xff, 0x1d, 0xbf, 0x1c, 0x23, 0x05, /* ._....#. */ -0x27, 0x9f, 0x22, 0x1b, 0xaf, 0x18, 0xcf, 0xdf, /* '."..... */ -0x22, 0x0c, 0x54, 0x18, 0xcf, 0x12, 0xdf, 0xbf, /* ".T..... */ -0x03, 0x00, 0x53, 0x07, 0x50, 0x02, 0x2e, 0xae, /* ..S.P... */ -0x88, 0x02, 0x2e, 0x7a, 0x89, 0x9f, 0x22, 0x1a, /* ...z..". */ -0xaf, 0x02, 0x2e, 0x38, 0x88, 0x02, 0x2e, 0xbc, /* ...8.... */ -0x88, 0x05, 0x27, 0x0e, 0xcf, 0x9f, 0x2d, 0x05, /* ..'...-. */ -0x5a, 0x9f, 0x29, 0x5f, 0x2b, 0x0e, 0xaf, 0x00, /* Z.)_+... */ -0xff, 0x1d, 0xbf, 0x1c, 0x23, 0x05, 0x27, 0x02, /* ....#.'. */ -0x2e, 0x64, 0x89, 0x02, 0x2e, 0xc4, 0x78, 0x0d, /* .d....x. */ -0x45, 0x20, 0x5b, 0x02, 0x2e, 0x64, 0x89, 0x18, /* E [..d.. */ -0xcf, 0x12, 0xdf, 0xbf, 0x03, 0x6a, 0x53, 0x0d, /* .....jS. */ -0x44, 0x02, 0x5b, 0x0c, 0x35, 0x02, 0x2e, 0xd6, /* D.[.5... */ -0x78, 0x17, 0xcf, 0xdf, 0x22 /* x..." */ + 0x42, 0xca, 0x00, + 0x67, 0x28, 0xdf, 0x22, 0x01, /* B..g(.". */ + 0x55, 0x02, 0x2e, 0xdf, 0x78, 0x16, 0xcf, 0x13, /* U...x... */ + 0xdf, 0x2a, 0x1e, 0x00, 0x2e, 0x04, 0x5f, 0x2a, /* .*...._* */ + 0x1f, 0x00, 0x2e, 0x01, 0x5f, 0x02, 0x2e, 0xdf, /* ...._... */ + 0x78, 0xbf, 0x03, 0x40, 0x54, 0x20, 0x52, 0x02, /* x..@T R. */ + 0x2e, 0x80, 0x89, 0x9f, 0x22, 0x1a, 0xaf, 0x18, /* ...."... */ + 0xcf, 0x12, 0xdf, 0xbf, 0x03, 0x00, 0x53, 0x29, /* ......S) */ + 0x50, 0x02, 0x2e, 0x8f, 0x88, 0x02, 0x2e, 0x74, /* P......t */ + 0x89, 0x9f, 0x22, 0x1b, 0xaf, 0x02, 0x2e, 0x2e, /* .."..... */ + 0x88, 0x02, 0x2e, 0xab, 0x78, 0x0e, 0xcf, 0x9f, /* ....x... */ + 0x1c, 0x0e, 0xaf, 0x05, 0x27, 0x0e, 0xcf, 0x5f, /* ....'.._ */ + 0x2d, 0x05, 0x5a, 0x9f, 0x2b, 0x5f, 0x29, 0x0e, /* -.Z.+_). */ + 0xaf, 0x5f, 0xff, 0x1d, 0xbf, 0x1c, 0x23, 0x05, /* ._....#. */ + 0x27, 0x9f, 0x22, 0x1b, 0xaf, 0x18, 0xcf, 0xdf, /* '."..... */ + 0x22, 0x0c, 0x54, 0x18, 0xcf, 0x12, 0xdf, 0xbf, /* ".T..... */ + 0x03, 0x00, 0x53, 0x07, 0x50, 0x02, 0x2e, 0xae, /* ..S.P... */ + 0x88, 0x02, 0x2e, 0x7a, 0x89, 0x9f, 0x22, 0x1a, /* ...z..". */ + 0xaf, 0x02, 0x2e, 0x38, 0x88, 0x02, 0x2e, 0xbc, /* ...8.... */ + 0x88, 0x05, 0x27, 0x0e, 0xcf, 0x9f, 0x2d, 0x05, /* ..'...-. */ + 0x5a, 0x9f, 0x29, 0x5f, 0x2b, 0x0e, 0xaf, 0x00, /* Z.)_+... */ + 0xff, 0x1d, 0xbf, 0x1c, 0x23, 0x05, 0x27, 0x02, /* ....#.'. */ + 0x2e, 0x64, 0x89, 0x02, 0x2e, 0xc4, 0x78, 0x0d, /* .d....x. */ + 0x45, 0x20, 0x5b, 0x02, 0x2e, 0x64, 0x89, 0x18, /* E [..d.. */ + 0xcf, 0x12, 0xdf, 0xbf, 0x03, 0x6a, 0x53, 0x0d, /* .....jS. */ + 0x44, 0x02, 0x5b, 0x0c, 0x35, 0x02, 0x2e, 0xd6, /* D.[.5... */ + 0x78, 0x17, 0xcf, 0xdf, 0x22 /* x..." */ }; static const unsigned char pkt239[] = { -0x42, 0xca, 0x00, -0xcb, 0x28, 0x09, 0x55, 0x18, /* B...(.U. */ -0xcf, 0xdf, 0x22, 0x06, 0x55, 0x02, 0x2e, 0xdc, /* ..".U... */ -0x88, 0x0e, 0x3b, 0x0c, 0xdf, 0x24, 0x19, 0x0c, /* ..;..$.. */ -0xbf, 0x05, 0x27, 0x11, 0xcf, 0xff, 0x1e, 0x01, /* ..'..... */ -0x54, 0x1f, 0x20, 0x11, 0xaf, 0x05, 0x27, 0x1a, /* T. ...'. */ -0x23, 0x1b, 0x23, 0x05, 0x27, 0x02, 0x2e, 0xdc, /* #.#.'... */ -0x88, 0x02, 0x2e, 0xf2, 0x88, 0x02, 0x2e, 0x64, /* .......d */ -0x89, 0x02, 0x2e, 0xb4, 0x87, 0x37, 0x5a, 0x0a, /* .....7Z. */ -0xcf, 0xc0, 0x1c, 0xc0, 0x1e, 0x0e, 0x55, 0x9f, /* ......U. */ -0x22, 0x1f, 0xaf, 0x20, 0xaf, 0x19, 0xaf, 0x02, /* ".. .... */ -0x2e, 0x0f, 0x79, 0x0e, 0xcf, 0x05, 0x18, 0x0e, /* ..y..... */ -0xaf, 0x9f, 0x22, 0x47, 0xaf, 0x48, 0xaf, 0x17, /* .."G.H.. */ -0xaf, 0x18, 0xaf, 0x05, 0x27, 0x20, 0xcf, 0xdf, /* ....' .. */ -0x22, 0x06, 0x54, 0x05, 0x1e, 0x1b, 0x55, 0x1f, /* ".T...U. */ -0xdf, 0x80, 0x1f, 0x18, 0x5e, 0x02, 0x2e, 0x08, /* ....^... */ -0x79, 0x1f, 0xdf, 0x10, 0x1f, 0x13, 0x5e, 0x9f, /* y.....^. */ -0x22, 0x20, 0xaf, 0x1f, 0xaf, 0x0a, 0xcf, 0xc0, /* " ...... */ -0x1c, 0x80, 0x1e, 0x0a, 0x55, 0x0d, 0x41, 0x01, /* ....U.A. */ -0x5a, 0x0e, 0x35, 0x00, 0x50, 0x0e, 0x36, 0x0d, /* Z.5.P.6. */ -0xcf, 0x06, 0x18, 0x0d, 0xaf, 0x0e, 0x31, 0x9f, /* ......1. */ -0x22, 0x19, 0xaf, 0x02, 0x2e, 0x20, 0x79, 0x1f, /* ".... y. */ -0x20, 0x06, 0x1e, 0x00, 0x5e, 0x20, 0xaf, 0x0d, /* ...^ .. */ -0x47, 0x0c, 0x5b, 0x51, 0xef, 0x0c, 0xaf, 0x0e, /* G.[Q.... */ -0xcf, 0xfa, 0x1c, 0x0e, 0xaf, 0x20, 0xcf, 0xdf, /* ..... .. */ -0x22, 0x03, 0x54, 0x06, 0x1e, 0x01, 0x54, 0x5f, /* ".T...T_ */ -0x20, 0x20, 0xaf, 0x05, 0x27 /* ..' */ + 0x42, 0xca, 0x00, + 0xcb, 0x28, 0x09, 0x55, 0x18, /* B...(.U. */ + 0xcf, 0xdf, 0x22, 0x06, 0x55, 0x02, 0x2e, 0xdc, /* ..".U... */ + 0x88, 0x0e, 0x3b, 0x0c, 0xdf, 0x24, 0x19, 0x0c, /* ..;..$.. */ + 0xbf, 0x05, 0x27, 0x11, 0xcf, 0xff, 0x1e, 0x01, /* ..'..... */ + 0x54, 0x1f, 0x20, 0x11, 0xaf, 0x05, 0x27, 0x1a, /* T. ...'. */ + 0x23, 0x1b, 0x23, 0x05, 0x27, 0x02, 0x2e, 0xdc, /* #.#.'... */ + 0x88, 0x02, 0x2e, 0xf2, 0x88, 0x02, 0x2e, 0x64, /* .......d */ + 0x89, 0x02, 0x2e, 0xb4, 0x87, 0x37, 0x5a, 0x0a, /* .....7Z. */ + 0xcf, 0xc0, 0x1c, 0xc0, 0x1e, 0x0e, 0x55, 0x9f, /* ......U. */ + 0x22, 0x1f, 0xaf, 0x20, 0xaf, 0x19, 0xaf, 0x02, /* ".. .... */ + 0x2e, 0x0f, 0x79, 0x0e, 0xcf, 0x05, 0x18, 0x0e, /* ..y..... */ + 0xaf, 0x9f, 0x22, 0x47, 0xaf, 0x48, 0xaf, 0x17, /* .."G.H.. */ + 0xaf, 0x18, 0xaf, 0x05, 0x27, 0x20, 0xcf, 0xdf, /* ....' .. */ + 0x22, 0x06, 0x54, 0x05, 0x1e, 0x1b, 0x55, 0x1f, /* ".T...U. */ + 0xdf, 0x80, 0x1f, 0x18, 0x5e, 0x02, 0x2e, 0x08, /* ....^... */ + 0x79, 0x1f, 0xdf, 0x10, 0x1f, 0x13, 0x5e, 0x9f, /* y.....^. */ + 0x22, 0x20, 0xaf, 0x1f, 0xaf, 0x0a, 0xcf, 0xc0, /* " ...... */ + 0x1c, 0x80, 0x1e, 0x0a, 0x55, 0x0d, 0x41, 0x01, /* ....U.A. */ + 0x5a, 0x0e, 0x35, 0x00, 0x50, 0x0e, 0x36, 0x0d, /* Z.5.P.6. */ + 0xcf, 0x06, 0x18, 0x0d, 0xaf, 0x0e, 0x31, 0x9f, /* ......1. */ + 0x22, 0x19, 0xaf, 0x02, 0x2e, 0x20, 0x79, 0x1f, /* ".... y. */ + 0x20, 0x06, 0x1e, 0x00, 0x5e, 0x20, 0xaf, 0x0d, /* ...^ .. */ + 0x47, 0x0c, 0x5b, 0x51, 0xef, 0x0c, 0xaf, 0x0e, /* G.[Q.... */ + 0xcf, 0xfa, 0x1c, 0x0e, 0xaf, 0x20, 0xcf, 0xdf, /* ..... .. */ + 0x22, 0x03, 0x54, 0x06, 0x1e, 0x01, 0x54, 0x5f, /* ".T...T_ */ + 0x20, 0x20, 0xaf, 0x05, 0x27 /* ..' */ }; static const unsigned char pkt241[] = { -0x42, 0xca, 0x00, -0x2f, 0x29, 0x0d, 0x44, 0x0b, /* B../).D. */ -0x5a, 0x0d, 0xcf, 0x06, 0x1c, 0x08, 0x54, 0x0c, /* Z.....T. */ -0x30, 0x48, 0xcf, 0xdf, 0x2d, 0x02, 0x5a, 0x9f, /* 0H..-.Z. */ -0x22, 0x1d, 0xaf, 0x01, 0x50, 0x5f, 0xef, 0x1d, /* "...P_.. */ -0xaf, 0x0c, 0x31, 0x0d, 0x45, 0x13, 0x5b, 0x0a, /* ..1.E.[. */ -0xcf, 0x30, 0x1c, 0x0e, 0x55, 0x0d, 0xcf, 0x06, /* .0..U... */ -0x1c, 0x06, 0x1e, 0x0d, 0x54, 0x11, 0xcf, 0x07, /* ....T... */ -0x1e, 0x03, 0x53, 0x03, 0xef, 0x12, 0xaf, 0x02, /* ..S..... */ -0x2e, 0x54, 0x79, 0x05, 0xef, 0x12, 0xaf, 0x02, /* .Ty..... */ -0x2e, 0x54, 0x79, 0x01, 0xef, 0x12, 0xaf, 0x18, /* .Ty..... */ -0x23, 0x9f, 0x22, 0x11, 0xaf, 0x0d, 0xcf, 0x1f, /* #."..... */ -0x1c, 0x0d, 0xaf, 0x0c, 0xdf, 0x24, 0x19, 0x0c, /* .....$.. */ -0xbf, 0x0a, 0xdf, 0x30, 0x1d, 0x20, 0x1f, 0x01, /* ...0. .. */ -0x55, 0xf9, 0x1c, 0x0d, 0xaf, 0x05, 0x27, 0x17, /* U.....'. */ -0xdf, 0xff, 0x21, 0x47, 0xbf, 0x18, 0xdf, 0x02, /* ..!G.... */ -0x2e, 0xb4, 0x87, 0x03, 0x5b, 0x0e, 0x46, 0x04, /* ....[.F. */ -0x5a, 0x02, 0x2e, 0x71, 0x79, 0x0d, 0x43, 0x00, /* Z..qy.C. */ -0x5a, 0xff, 0x21, 0x48, 0xbf, 0x05, 0x27, 0x19, /* Z.!H..'. */ -0xcf, 0x80, 0x1e, 0x01, 0x54, 0x5f, 0x20, 0x19, /* ....T_ . */ -0xaf, 0x05, 0x27, 0x19, 0xcf, 0x7f, 0x1e, 0x01, /* ..'..... */ -0x54, 0x1f, 0x20, 0x19, 0xaf, 0x05, 0x27, 0x13, /* T. ...'. */ -0xcf, 0x16, 0xaf, 0x15, 0xcf, 0x18, 0xaf, 0x14, /* ........ */ -0xcf, 0x17, 0xaf, 0x0d, 0x3d, 0x0d, 0x46, 0x00, /* ....=.F. */ -0x5b, 0x0d, 0x35, 0x05, 0x27, 0x14, 0x23, 0x15, /* [.5.'.#. */ -0x23, 0xff, 0xef, 0x13, 0xaf, 0x02, 0x2e, 0x98, /* #....... */ -0x89, 0x0d, 0x3e, 0x13, 0xcf /* ..>.. */ + 0x42, 0xca, 0x00, + 0x2f, 0x29, 0x0d, 0x44, 0x0b, /* B../).D. */ + 0x5a, 0x0d, 0xcf, 0x06, 0x1c, 0x08, 0x54, 0x0c, /* Z.....T. */ + 0x30, 0x48, 0xcf, 0xdf, 0x2d, 0x02, 0x5a, 0x9f, /* 0H..-.Z. */ + 0x22, 0x1d, 0xaf, 0x01, 0x50, 0x5f, 0xef, 0x1d, /* "...P_.. */ + 0xaf, 0x0c, 0x31, 0x0d, 0x45, 0x13, 0x5b, 0x0a, /* ..1.E.[. */ + 0xcf, 0x30, 0x1c, 0x0e, 0x55, 0x0d, 0xcf, 0x06, /* .0..U... */ + 0x1c, 0x06, 0x1e, 0x0d, 0x54, 0x11, 0xcf, 0x07, /* ....T... */ + 0x1e, 0x03, 0x53, 0x03, 0xef, 0x12, 0xaf, 0x02, /* ..S..... */ + 0x2e, 0x54, 0x79, 0x05, 0xef, 0x12, 0xaf, 0x02, /* .Ty..... */ + 0x2e, 0x54, 0x79, 0x01, 0xef, 0x12, 0xaf, 0x18, /* .Ty..... */ + 0x23, 0x9f, 0x22, 0x11, 0xaf, 0x0d, 0xcf, 0x1f, /* #."..... */ + 0x1c, 0x0d, 0xaf, 0x0c, 0xdf, 0x24, 0x19, 0x0c, /* .....$.. */ + 0xbf, 0x0a, 0xdf, 0x30, 0x1d, 0x20, 0x1f, 0x01, /* ...0. .. */ + 0x55, 0xf9, 0x1c, 0x0d, 0xaf, 0x05, 0x27, 0x17, /* U.....'. */ + 0xdf, 0xff, 0x21, 0x47, 0xbf, 0x18, 0xdf, 0x02, /* ..!G.... */ + 0x2e, 0xb4, 0x87, 0x03, 0x5b, 0x0e, 0x46, 0x04, /* ....[.F. */ + 0x5a, 0x02, 0x2e, 0x71, 0x79, 0x0d, 0x43, 0x00, /* Z..qy.C. */ + 0x5a, 0xff, 0x21, 0x48, 0xbf, 0x05, 0x27, 0x19, /* Z.!H..'. */ + 0xcf, 0x80, 0x1e, 0x01, 0x54, 0x5f, 0x20, 0x19, /* ....T_ . */ + 0xaf, 0x05, 0x27, 0x19, 0xcf, 0x7f, 0x1e, 0x01, /* ..'..... */ + 0x54, 0x1f, 0x20, 0x19, 0xaf, 0x05, 0x27, 0x13, /* T. ...'. */ + 0xcf, 0x16, 0xaf, 0x15, 0xcf, 0x18, 0xaf, 0x14, /* ........ */ + 0xcf, 0x17, 0xaf, 0x0d, 0x3d, 0x0d, 0x46, 0x00, /* ....=.F. */ + 0x5b, 0x0d, 0x35, 0x05, 0x27, 0x14, 0x23, 0x15, /* [.5.'.#. */ + 0x23, 0xff, 0xef, 0x13, 0xaf, 0x02, 0x2e, 0x98, /* #....... */ + 0x89, 0x0d, 0x3e, 0x13, 0xcf /* ..>.. */ }; static const unsigned char pkt243[] = { -0x42, 0xc0, 0x00, -0x93, 0x29, 0x46, 0xff, 0xbf, /* B...)F.. */ -0x03, 0x00, 0x53, 0x0d, 0x36, 0x05, 0x27, 0x0d, /* ..S.6.'. */ -0xcf, 0x06, 0x1c, 0x06, 0x1e, 0x07, 0x55, 0xe4, /* ......U. */ -0x47, 0x02, 0x5a, 0x1a, 0xcf, 0x02, 0x2e, 0xa5, /* G.Z..... */ -0x79, 0x1b, 0xcf, 0x02, 0x2e, 0xa5, 0x79, 0x18, /* y.....y. */ -0xcf, 0x00, 0x1e, 0x04, 0x55, 0x5d, 0xef, 0x1b, /* ....U].. */ -0xff, 0x02, 0x2e, 0xc0, 0x79, 0x18, 0xcf, 0x01, /* ....y... */ -0x1e, 0x03, 0x55, 0x5e, 0xef, 0x1b, 0xff, 0x02, /* ..U^.... */ -0x2e, 0xc0, 0x79, 0x02, 0x1e, 0x03, 0x55, 0x61, /* ..y...Ua */ -0xef, 0x1b, 0xff, 0x02, 0x2e, 0xc0, 0x79, 0x03, /* ......y. */ -0x1e, 0x03, 0x55, 0x66, 0xef, 0x1b, 0xff, 0x02, /* ..Uf.... */ -0x2e, 0xc0, 0x79, 0x6d, 0xef, 0x1b, 0xff, 0x1a, /* ..ym.... */ -0x27, 0x07, 0x27, 0xe6, 0xaf, 0xe9, 0xbf, 0x7e, /* '.'....~ */ -0x81, 0xec, 0xcf, 0x13, 0xdf, 0xbf, 0x03, 0x19, /* ........ */ -0x54, 0x0a, 0x5e, 0x13, 0xaf, 0xe9, 0xcf, 0x0f, /* T.^..... */ -0x1c, 0x15, 0xaf, 0xe9, 0xcf, 0x09, 0x27, 0x0f, /* ......'. */ -0x1c, 0xdf, 0x2c, 0x00, 0x5b, 0xf0, 0x18, 0x14, /* ..,.[... */ -0xaf, 0x01, 0x0e, 0x07, 0x27, 0x88, 0x1f, 0xe8, /* ....'... */ -0x55, 0x0d, 0x3e, 0x13, 0xcf, 0x46, 0x1e, 0x04, /* U.>..F.. */ -0x53, 0x0d, 0x36, 0x13, 0xcf, 0x46, 0x1e, 0x00, /* S.6..F.. */ -0x5e, 0x0d, 0x36, 0x05, 0x27, 0xe9, 0xcf, 0x09, /* ^.6.'... */ -0x27, 0xdf, 0x2c, 0x00, 0x5b, 0xdf, 0x21, 0x0f, /* '.,.[.!. */ -0x1c, 0x14, 0xdf, 0xff, 0x2d, 0x00, 0x5b, 0xff, /* ....-.[. */ -0x21, 0xbf, 0x03, 0xe5, 0x53, 0xec, 0xcf, 0x02, /* !...S... */ -0x2e, 0xca, 0x79 /* ..y */ + 0x42, 0xc0, 0x00, + 0x93, 0x29, 0x46, 0xff, 0xbf, /* B...)F.. */ + 0x03, 0x00, 0x53, 0x0d, 0x36, 0x05, 0x27, 0x0d, /* ..S.6.'. */ + 0xcf, 0x06, 0x1c, 0x06, 0x1e, 0x07, 0x55, 0xe4, /* ......U. */ + 0x47, 0x02, 0x5a, 0x1a, 0xcf, 0x02, 0x2e, 0xa5, /* G.Z..... */ + 0x79, 0x1b, 0xcf, 0x02, 0x2e, 0xa5, 0x79, 0x18, /* y.....y. */ + 0xcf, 0x00, 0x1e, 0x04, 0x55, 0x5d, 0xef, 0x1b, /* ....U].. */ + 0xff, 0x02, 0x2e, 0xc0, 0x79, 0x18, 0xcf, 0x01, /* ....y... */ + 0x1e, 0x03, 0x55, 0x5e, 0xef, 0x1b, 0xff, 0x02, /* ..U^.... */ + 0x2e, 0xc0, 0x79, 0x02, 0x1e, 0x03, 0x55, 0x61, /* ..y...Ua */ + 0xef, 0x1b, 0xff, 0x02, 0x2e, 0xc0, 0x79, 0x03, /* ......y. */ + 0x1e, 0x03, 0x55, 0x66, 0xef, 0x1b, 0xff, 0x02, /* ..Uf.... */ + 0x2e, 0xc0, 0x79, 0x6d, 0xef, 0x1b, 0xff, 0x1a, /* ..ym.... */ + 0x27, 0x07, 0x27, 0xe6, 0xaf, 0xe9, 0xbf, 0x7e, /* '.'....~ */ + 0x81, 0xec, 0xcf, 0x13, 0xdf, 0xbf, 0x03, 0x19, /* ........ */ + 0x54, 0x0a, 0x5e, 0x13, 0xaf, 0xe9, 0xcf, 0x0f, /* T.^..... */ + 0x1c, 0x15, 0xaf, 0xe9, 0xcf, 0x09, 0x27, 0x0f, /* ......'. */ + 0x1c, 0xdf, 0x2c, 0x00, 0x5b, 0xf0, 0x18, 0x14, /* ..,.[... */ + 0xaf, 0x01, 0x0e, 0x07, 0x27, 0x88, 0x1f, 0xe8, /* ....'... */ + 0x55, 0x0d, 0x3e, 0x13, 0xcf, 0x46, 0x1e, 0x04, /* U.>..F.. */ + 0x53, 0x0d, 0x36, 0x13, 0xcf, 0x46, 0x1e, 0x00, /* S.6..F.. */ + 0x5e, 0x0d, 0x36, 0x05, 0x27, 0xe9, 0xcf, 0x09, /* ^.6.'... */ + 0x27, 0xdf, 0x2c, 0x00, 0x5b, 0xdf, 0x21, 0x0f, /* '.,.[.!. */ + 0x1c, 0x14, 0xdf, 0xff, 0x2d, 0x00, 0x5b, 0xff, /* ....-.[. */ + 0x21, 0xbf, 0x03, 0xe5, 0x53, 0xec, 0xcf, 0x02, /* !...S... */ + 0x2e, 0xca, 0x79 /* ..y */ }; static const unsigned char pkt245[] = { -0x42, 0x66, 0x00, -0x00, 0x2c, 0x01, 0x2e, 0x65, /* Bf..,..e */ -0x84, 0x08, 0x44, 0x2c, 0x5a, 0xff, 0x0d, 0x48, /* ..D,Z..H */ -0xef, 0x5f, 0x9a, 0x2a, 0xaf, 0x02, 0x2e, 0x75, /* ._.*...u */ -0x80, 0xdf, 0x96, 0x26, 0x40, 0x07, 0x5b, 0xa0, /* ...&@.[. */ -0xcf, 0x30, 0x1c, 0x04, 0x54, 0x20, 0x1e, 0x01, /* .0..T .. */ -0x55, 0x31, 0xff, 0x01, 0x50, 0x00, 0xff, 0x30, /* U1..P..0 */ -0x19, 0xbf, 0x9a, 0x2b, 0xbf, 0xa9, 0xcf, 0x70, /* ...+...p */ -0x1c, 0xa5, 0xdf, 0x0c, 0x1d, 0xff, 0x20, 0xff, /* ...... . */ -0x20, 0x5f, 0x02, 0xff, 0x9a, 0x2c, 0xbf, 0xdd, /* _...,.. */ -0x97, 0x1f, 0x9b, 0x2d, 0xaf, 0x29, 0xcf, 0x09, /* ...-.).. */ -0x27, 0x28, 0xdf, 0x3f, 0x02, 0x9f, 0x9c, 0x6a, /* '(.?...j */ -0xcf, 0x09, 0x27, 0x69, 0xdf, 0x3f, 0x02, 0xdf, /* ..'i.?.. */ -0x9c, 0x6d, 0x2e, 0x6d, 0xdf, 0x1f, 0x9d, 0x05, /* .m.m.... */ -0x27 /* ' */ + 0x42, 0x66, 0x00, + 0x00, 0x2c, 0x01, 0x2e, 0x65, /* Bf..,..e */ + 0x84, 0x08, 0x44, 0x2c, 0x5a, 0xff, 0x0d, 0x48, /* ..D,Z..H */ + 0xef, 0x5f, 0x9a, 0x2a, 0xaf, 0x02, 0x2e, 0x75, /* ._.*...u */ + 0x80, 0xdf, 0x96, 0x26, 0x40, 0x07, 0x5b, 0xa0, /* ...&@.[. */ + 0xcf, 0x30, 0x1c, 0x04, 0x54, 0x20, 0x1e, 0x01, /* .0..T .. */ + 0x55, 0x31, 0xff, 0x01, 0x50, 0x00, 0xff, 0x30, /* U1..P..0 */ + 0x19, 0xbf, 0x9a, 0x2b, 0xbf, 0xa9, 0xcf, 0x70, /* ...+...p */ + 0x1c, 0xa5, 0xdf, 0x0c, 0x1d, 0xff, 0x20, 0xff, /* ...... . */ + 0x20, 0x5f, 0x02, 0xff, 0x9a, 0x2c, 0xbf, 0xdd, /* _...,.. */ + 0x97, 0x1f, 0x9b, 0x2d, 0xaf, 0x29, 0xcf, 0x09, /* ...-.).. */ + 0x27, 0x28, 0xdf, 0x3f, 0x02, 0x9f, 0x9c, 0x6a, /* '(.?...j */ + 0xcf, 0x09, 0x27, 0x69, 0xdf, 0x3f, 0x02, 0xdf, /* ..'i.?.. */ + 0x9c, 0x6d, 0x2e, 0x6d, 0xdf, 0x1f, 0x9d, 0x05, /* .m.m.... */ + 0x27 /* ' */ }; static const unsigned char pkt247[] = { -0x42, 0x2c, 0x00, -0x32, 0x2c, 0x08, 0x44, 0x11, /* B,.2,.D. */ -0x5a, 0x3f, 0x80, 0x28, 0x0d, 0xe2, 0x97, 0xdf, /* Z?.(.... */ -0x96, 0xe1, 0x97, 0xdf, 0x96, 0x01, 0x2e, 0xbf, /* ........ */ -0x84, 0xfd, 0x0d, 0x29, 0xcf, 0x09, 0x27, 0x28, /* ...)..'( */ -0xdf, 0x3f, 0x02, 0x5f, 0x9f, 0xdd, 0x97, 0x5f, /* .?._..._ */ -0x9f, 0xdd, 0x97, 0x5f, 0x9f, 0x05, 0x27 /* ..._..' */ + 0x42, 0x2c, 0x00, + 0x32, 0x2c, 0x08, 0x44, 0x11, /* B,.2,.D. */ + 0x5a, 0x3f, 0x80, 0x28, 0x0d, 0xe2, 0x97, 0xdf, /* Z?.(.... */ + 0x96, 0xe1, 0x97, 0xdf, 0x96, 0x01, 0x2e, 0xbf, /* ........ */ + 0x84, 0xfd, 0x0d, 0x29, 0xcf, 0x09, 0x27, 0x28, /* ...)..'( */ + 0xdf, 0x3f, 0x02, 0x5f, 0x9f, 0xdd, 0x97, 0x5f, /* .?._..._ */ + 0x9f, 0xdd, 0x97, 0x5f, 0x9f, 0x05, 0x27 /* ..._..' */ }; static const unsigned char pkt249[] = { -0x42, 0xca, 0x00, -0x47, 0x2c, 0xfe, 0xcf, 0x58, /* B..G,..X */ -0xaf, 0xfe, 0xcf, 0xfe, 0xdf, 0x02, 0x2e, 0xde, /* ........ */ -0x8c, 0xfe, 0xcf, 0x3c, 0xaf, 0x07, 0x3d, 0x58, /* ...<..=X */ -0x40, 0x4e, 0x5a, 0x3c, 0x26, 0x4c, 0x55, 0x37, /* @NZ<&LU7 */ -0x45, 0x4a, 0x5a, 0x02, 0x2e, 0x5c, 0x8d, 0x47, /* EJZ..\.G */ -0x5a, 0x02, 0x2e, 0xee, 0x8c, 0x00, 0x2e, 0xb9, /* Z....... */ -0x8d, 0xfe, 0xef, 0x16, 0x80, 0x02, 0xcf, 0xdf, /* ........ */ -0x96, 0x61, 0xef, 0xc0, 0xaf, 0x04, 0x27, 0xc1, /* .a....'. */ -0x46, 0x04, 0x5b, 0xc0, 0x3e, 0x40, 0xef, 0xc1, /* F.[.>@.. */ -0xaf, 0x01, 0x2e, 0x8d, 0x8b, 0xd0, 0x41, 0x07, /* ......A. */ -0x5b, 0x02, 0x2e, 0x9e, 0x8c, 0xf2, 0x5b, 0xae, /* [.....[. */ -0x87, 0xdd, 0x97, 0x1f, 0x2d, 0x06, 0x5b, 0x03, /* ....-.[. */ -0x50, 0x01, 0x0c, 0x02, 0xcf, 0xc0, 0x1c, 0x01, /* P....... */ -0x55, 0x02, 0x2e, 0x81, 0x8c, 0xc0, 0x23, 0x20, /* U.....# */ -0xef, 0xc1, 0xaf, 0x00, 0x2e, 0xd8, 0x8d, 0x05, /* ........ */ -0x27, 0x9b, 0x22, 0x37, 0x45, 0x05, 0x5a, 0x41, /* '."7E.ZA */ -0x2e, 0x52, 0xdf, 0xdf, 0x2d, 0x04, 0x5b, 0x00, /* .R..-.[. */ -0x28, 0x02, 0x50, 0x3b, 0x43, 0x00, 0x5b, 0x00, /* (.P;C.[. */ -0x28, 0xd3, 0xdf, 0xc6, 0x2e, 0x15, 0xbf, 0xd3, /* (....... */ -0x3c, 0x40, 0xef, 0x09, 0x80, 0xdd, 0x97, 0xff, /* <@...... */ -0xaf, 0x00, 0x2e, 0xa7, 0x8a, 0xc6, 0x2e, 0x15, /* ........ */ -0xdf, 0x10, 0x1d, 0xd3, 0xcf, 0x3f, 0x02, 0xd3, /* .....?.. */ -0xaf, 0x05, 0x27, 0xed, 0x83, 0x07, 0x45, 0x05, /* ..'...E. */ -0x27, 0x3d, 0x23, 0x07, 0x3d, 0x02, 0xcf, 0xdf, /* '=#.=... */ -0x96, 0x02, 0x2e, 0xee, 0x8c, 0x02, 0x2e, 0xd7, /* ........ */ -0x8c, 0xfe, 0xef, 0x16, 0x80 /* ..... */ + 0x42, 0xca, 0x00, + 0x47, 0x2c, 0xfe, 0xcf, 0x58, /* B..G,..X */ + 0xaf, 0xfe, 0xcf, 0xfe, 0xdf, 0x02, 0x2e, 0xde, /* ........ */ + 0x8c, 0xfe, 0xcf, 0x3c, 0xaf, 0x07, 0x3d, 0x58, /* ...<..=X */ + 0x40, 0x4e, 0x5a, 0x3c, 0x26, 0x4c, 0x55, 0x37, /* @NZ<&LU7 */ + 0x45, 0x4a, 0x5a, 0x02, 0x2e, 0x5c, 0x8d, 0x47, /* EJZ..\.G */ + 0x5a, 0x02, 0x2e, 0xee, 0x8c, 0x00, 0x2e, 0xb9, /* Z....... */ + 0x8d, 0xfe, 0xef, 0x16, 0x80, 0x02, 0xcf, 0xdf, /* ........ */ + 0x96, 0x61, 0xef, 0xc0, 0xaf, 0x04, 0x27, 0xc1, /* .a....'. */ + 0x46, 0x04, 0x5b, 0xc0, 0x3e, 0x40, 0xef, 0xc1, /* F.[.>@.. */ + 0xaf, 0x01, 0x2e, 0x8d, 0x8b, 0xd0, 0x41, 0x07, /* ......A. */ + 0x5b, 0x02, 0x2e, 0x9e, 0x8c, 0xf2, 0x5b, 0xae, /* [.....[. */ + 0x87, 0xdd, 0x97, 0x1f, 0x2d, 0x06, 0x5b, 0x03, /* ....-.[. */ + 0x50, 0x01, 0x0c, 0x02, 0xcf, 0xc0, 0x1c, 0x01, /* P....... */ + 0x55, 0x02, 0x2e, 0x81, 0x8c, 0xc0, 0x23, 0x20, /* U.....# */ + 0xef, 0xc1, 0xaf, 0x00, 0x2e, 0xd8, 0x8d, 0x05, /* ........ */ + 0x27, 0x9b, 0x22, 0x37, 0x45, 0x05, 0x5a, 0x41, /* '."7E.ZA */ + 0x2e, 0x52, 0xdf, 0xdf, 0x2d, 0x04, 0x5b, 0x00, /* .R..-.[. */ + 0x28, 0x02, 0x50, 0x3b, 0x43, 0x00, 0x5b, 0x00, /* (.P;C.[. */ + 0x28, 0xd3, 0xdf, 0xc6, 0x2e, 0x15, 0xbf, 0xd3, /* (....... */ + 0x3c, 0x40, 0xef, 0x09, 0x80, 0xdd, 0x97, 0xff, /* <@...... */ + 0xaf, 0x00, 0x2e, 0xa7, 0x8a, 0xc6, 0x2e, 0x15, /* ........ */ + 0xdf, 0x10, 0x1d, 0xd3, 0xcf, 0x3f, 0x02, 0xd3, /* .....?.. */ + 0xaf, 0x05, 0x27, 0xed, 0x83, 0x07, 0x45, 0x05, /* ..'...E. */ + 0x27, 0x3d, 0x23, 0x07, 0x3d, 0x02, 0xcf, 0xdf, /* '=#.=... */ + 0x96, 0x02, 0x2e, 0xee, 0x8c, 0x02, 0x2e, 0xd7, /* ........ */ + 0x8c, 0xfe, 0xef, 0x16, 0x80 /* ..... */ }; static const unsigned char pkt251[] = { -0x42, 0xca, 0x00, -0xab, 0x2c, 0x05, 0xef, 0xc0, /* B...,... */ -0xaf, 0x04, 0x27, 0xd0, 0x41, 0x03, 0x5b, 0x02, /* ..'.A.[. */ -0x2e, 0x9e, 0x8c, 0xf9, 0x5b, 0xbb, 0x50, 0x27, /* ....[.P' */ -0x82, 0x04, 0xef, 0xc1, 0xaf, 0x9b, 0x22, 0x02, /* ......". */ -0x2e, 0x12, 0x8d, 0xdd, 0x97, 0xdf, 0x22, 0x02, /* ......". */ -0x55, 0x58, 0x40, 0x02, 0x5a, 0x0b, 0x50, 0x58, /* UX@.Z.PX */ -0x40, 0x09, 0x5a, 0xdd, 0x97, 0x1f, 0x2d, 0xb3, /* @.Z...-. */ -0x5a, 0x02, 0x2e, 0x5d, 0x8d, 0xb2, 0x5b, 0x9b, /* Z..]..[. */ -0x22, 0x02, 0x2e, 0x8d, 0x8c, 0xae, 0x50, 0x02, /* ".....P. */ -0x2e, 0x5d, 0x8d, 0xd5, 0x5b, 0x02, 0x2e, 0x81, /* .]..[... */ -0x8c, 0x58, 0x41, 0x02, 0x5b, 0x01, 0x0c, 0x02, /* .XA.[... */ -0x2e, 0x7b, 0x7c, 0xcd, 0x50, 0x41, 0x2e, 0x52, /* .{|.PA.R */ -0xdf, 0xed, 0x1c, 0x04, 0x18, 0x41, 0x2e, 0x52, /* .....A.R */ -0xbf, 0x05, 0x27, 0x1a, 0x27, 0x56, 0xdf, 0x59, /* ..'.'V.Y */ -0x80, 0xdf, 0x22, 0x00, 0x54, 0x01, 0x16, 0x3f, /* ..".T..? */ -0x1e, 0x00, 0x5f, 0x3f, 0xef, 0x1f, 0x22, 0x1f, /* .._?..". */ -0x22, 0xaf, 0xdf, 0x03, 0x1d, 0x5f, 0x02, 0xaf, /* "...._.. */ -0xbf, 0x05, 0x27, 0x00, 0x2e, 0xa1, 0x8d, 0xae, /* ..'..... */ -0xdf, 0xe0, 0x19, 0xae, 0xbf, 0x57, 0x40, 0x00, /* .....W@. */ -0x5b, 0xa1, 0x32, 0x57, 0x43, 0x00, 0x5b, 0xae, /* [.2WC.[. */ -0x3f, 0xed, 0x80, 0x05, 0x27, 0x41, 0x2e, 0x52, /* ?...'A.R */ -0xdf, 0x03, 0x18, 0x41, 0x2e, 0x52, 0xbf, 0x05, /* ...A.R.. */ -0x27, 0xd3, 0xdf, 0xff, 0x96, 0x9b, 0x22, 0x02, /* '.....". */ -0x2e, 0x12, 0x8d, 0xd3, 0x3c, 0x07, 0x80, 0xdd, /* ....<... */ -0x97, 0xff, 0xaf, 0x00, 0x2e, 0xa7, 0x8a, 0xdd, /* ........ */ -0x9f, 0x10, 0x1d, 0xd3, 0xcf /* ..... */ + 0x42, 0xca, 0x00, + 0xab, 0x2c, 0x05, 0xef, 0xc0, /* B...,... */ + 0xaf, 0x04, 0x27, 0xd0, 0x41, 0x03, 0x5b, 0x02, /* ..'.A.[. */ + 0x2e, 0x9e, 0x8c, 0xf9, 0x5b, 0xbb, 0x50, 0x27, /* ....[.P' */ + 0x82, 0x04, 0xef, 0xc1, 0xaf, 0x9b, 0x22, 0x02, /* ......". */ + 0x2e, 0x12, 0x8d, 0xdd, 0x97, 0xdf, 0x22, 0x02, /* ......". */ + 0x55, 0x58, 0x40, 0x02, 0x5a, 0x0b, 0x50, 0x58, /* UX@.Z.PX */ + 0x40, 0x09, 0x5a, 0xdd, 0x97, 0x1f, 0x2d, 0xb3, /* @.Z...-. */ + 0x5a, 0x02, 0x2e, 0x5d, 0x8d, 0xb2, 0x5b, 0x9b, /* Z..]..[. */ + 0x22, 0x02, 0x2e, 0x8d, 0x8c, 0xae, 0x50, 0x02, /* ".....P. */ + 0x2e, 0x5d, 0x8d, 0xd5, 0x5b, 0x02, 0x2e, 0x81, /* .]..[... */ + 0x8c, 0x58, 0x41, 0x02, 0x5b, 0x01, 0x0c, 0x02, /* .XA.[... */ + 0x2e, 0x7b, 0x7c, 0xcd, 0x50, 0x41, 0x2e, 0x52, /* .{|.PA.R */ + 0xdf, 0xed, 0x1c, 0x04, 0x18, 0x41, 0x2e, 0x52, /* .....A.R */ + 0xbf, 0x05, 0x27, 0x1a, 0x27, 0x56, 0xdf, 0x59, /* ..'.'V.Y */ + 0x80, 0xdf, 0x22, 0x00, 0x54, 0x01, 0x16, 0x3f, /* ..".T..? */ + 0x1e, 0x00, 0x5f, 0x3f, 0xef, 0x1f, 0x22, 0x1f, /* .._?..". */ + 0x22, 0xaf, 0xdf, 0x03, 0x1d, 0x5f, 0x02, 0xaf, /* "...._.. */ + 0xbf, 0x05, 0x27, 0x00, 0x2e, 0xa1, 0x8d, 0xae, /* ..'..... */ + 0xdf, 0xe0, 0x19, 0xae, 0xbf, 0x57, 0x40, 0x00, /* .....W@. */ + 0x5b, 0xa1, 0x32, 0x57, 0x43, 0x00, 0x5b, 0xae, /* [.2WC.[. */ + 0x3f, 0xed, 0x80, 0x05, 0x27, 0x41, 0x2e, 0x52, /* ?...'A.R */ + 0xdf, 0x03, 0x18, 0x41, 0x2e, 0x52, 0xbf, 0x05, /* ...A.R.. */ + 0x27, 0xd3, 0xdf, 0xff, 0x96, 0x9b, 0x22, 0x02, /* '.....". */ + 0x2e, 0x12, 0x8d, 0xd3, 0x3c, 0x07, 0x80, 0xdd, /* ....<... */ + 0x97, 0xff, 0xaf, 0x00, 0x2e, 0xa7, 0x8a, 0xdd, /* ........ */ + 0x9f, 0x10, 0x1d, 0xd3, 0xcf /* ..... */ }; static const unsigned char pkt253[] = { -0x42, 0xb4, 0x00, -0x0f, 0x2d, 0x3f, 0x02, 0xd3, /* B...-?.. */ -0xaf, 0x05, 0x27, 0x37, 0x45, 0x10, 0x5a, 0x02, /* ..'7E.Z. */ -0x2e, 0x5c, 0x8d, 0x0d, 0x5a, 0x02, 0x2e, 0xee, /* .\..Z... */ -0x8c, 0x00, 0x2e, 0xbf, 0x8d, 0x00, 0x2e, 0xd3, /* ........ */ -0x8d, 0x41, 0x2e, 0x52, 0xdf, 0xdf, 0x2d, 0x00, /* .A.R..-. */ -0x5b, 0x00, 0x28, 0x00, 0x2e, 0xd8, 0x8d, 0x05, /* [.(..... */ -0x27, 0xf9, 0xcf, 0xdf, 0x96, 0xf9, 0x3d, 0x01, /* '.....=. */ -0x2e, 0x06, 0x82, 0x2d, 0xff, 0xa7, 0xef, 0xe1, /* ...-.... */ -0xbf, 0xe0, 0xaf, 0x09, 0xef, 0x10, 0xaf, 0x01, /* ........ */ -0x2e, 0x94, 0x86, 0xed, 0x80, 0x01, 0x2e, 0x18, /* ........ */ -0x87, 0x01, 0x2e, 0x1a, 0x87, 0x00, 0x2e, 0x16, /* ........ */ -0x82, 0x5b, 0x82, 0x00, 0x2e, 0x2d, 0x82, 0x26, /* .[...-.& */ -0x37, 0x00, 0x5a, 0x0c, 0x50, 0xff, 0x96, 0xdf, /* 7.Z.P... */ -0x96, 0x79, 0xcf, 0x7a, 0xdf, 0xff, 0x96, 0xdf, /* .y.z.... */ -0x96, 0xc2, 0x97, 0xc3, 0x9f, 0x9d, 0x01, 0x5d, /* .......] */ -0x01, 0x07, 0x53, 0xdd, 0x97, 0xdd, 0x9f, 0x79, /* ..S....y */ -0xaf, 0x7a, 0xbf, 0x3b, 0x3b, 0xdd, 0x97, 0xf9, /* .z.;;... */ -0xaf, 0x05, 0x27, 0xff, 0x22, 0x01, 0x55, 0x32, /* ..'.".U2 */ -0x1e, 0xf3, 0x5f, 0x02, 0x0c, 0x02, 0x2e, 0x4f, /* .._....O */ -0x8d, 0x3b, 0x33, 0x00, 0x28, 0x05, 0x27, 0x0d, /* .;3.(.'. */ -0x27, 0x3c, 0x26, 0x07, 0x54, 0x3c, 0xcf, 0x3d, /* '<&.T<.= */ -0xdf, 0x3f, 0x20, 0x3d, 0xbf, 0xdf, 0x03, 0x01, /* .? =.... */ -0x52, 0x3d, 0x23, 0x0c, 0x27, 0x0d, 0x27 /* R=#.'.' */ + 0x42, 0xb4, 0x00, + 0x0f, 0x2d, 0x3f, 0x02, 0xd3, /* B...-?.. */ + 0xaf, 0x05, 0x27, 0x37, 0x45, 0x10, 0x5a, 0x02, /* ..'7E.Z. */ + 0x2e, 0x5c, 0x8d, 0x0d, 0x5a, 0x02, 0x2e, 0xee, /* .\..Z... */ + 0x8c, 0x00, 0x2e, 0xbf, 0x8d, 0x00, 0x2e, 0xd3, /* ........ */ + 0x8d, 0x41, 0x2e, 0x52, 0xdf, 0xdf, 0x2d, 0x00, /* .A.R..-. */ + 0x5b, 0x00, 0x28, 0x00, 0x2e, 0xd8, 0x8d, 0x05, /* [.(..... */ + 0x27, 0xf9, 0xcf, 0xdf, 0x96, 0xf9, 0x3d, 0x01, /* '.....=. */ + 0x2e, 0x06, 0x82, 0x2d, 0xff, 0xa7, 0xef, 0xe1, /* ...-.... */ + 0xbf, 0xe0, 0xaf, 0x09, 0xef, 0x10, 0xaf, 0x01, /* ........ */ + 0x2e, 0x94, 0x86, 0xed, 0x80, 0x01, 0x2e, 0x18, /* ........ */ + 0x87, 0x01, 0x2e, 0x1a, 0x87, 0x00, 0x2e, 0x16, /* ........ */ + 0x82, 0x5b, 0x82, 0x00, 0x2e, 0x2d, 0x82, 0x26, /* .[...-.& */ + 0x37, 0x00, 0x5a, 0x0c, 0x50, 0xff, 0x96, 0xdf, /* 7.Z.P... */ + 0x96, 0x79, 0xcf, 0x7a, 0xdf, 0xff, 0x96, 0xdf, /* .y.z.... */ + 0x96, 0xc2, 0x97, 0xc3, 0x9f, 0x9d, 0x01, 0x5d, /* .......] */ + 0x01, 0x07, 0x53, 0xdd, 0x97, 0xdd, 0x9f, 0x79, /* ..S....y */ + 0xaf, 0x7a, 0xbf, 0x3b, 0x3b, 0xdd, 0x97, 0xf9, /* .z.;;... */ + 0xaf, 0x05, 0x27, 0xff, 0x22, 0x01, 0x55, 0x32, /* ..'.".U2 */ + 0x1e, 0xf3, 0x5f, 0x02, 0x0c, 0x02, 0x2e, 0x4f, /* .._....O */ + 0x8d, 0x3b, 0x33, 0x00, 0x28, 0x05, 0x27, 0x0d, /* .;3.(.'. */ + 0x27, 0x3c, 0x26, 0x07, 0x54, 0x3c, 0xcf, 0x3d, /* '<&.T<.= */ + 0xdf, 0x3f, 0x20, 0x3d, 0xbf, 0xdf, 0x03, 0x01, /* .? =.... */ + 0x52, 0x3d, 0x23, 0x0c, 0x27, 0x0d, 0x27 /* R=#.'.' */ }; static const unsigned char pkt255[] = { -0x42, 0x1a, 0x00, -0x68, 0x2d, 0x09, 0x43, 0x04, /* B..h-.C. */ -0x5b, 0x00, 0xef, 0xf8, 0xaf, 0x32, 0xef, 0xfa, /* [....2.. */ -0xaf, 0x03, 0x50, 0x01, 0xef, 0xf8, 0xaf, 0x42, /* ..P....B */ -0xef, 0xfa, 0xaf, 0x05, 0x27 /* ....' */ + 0x42, 0x1a, 0x00, + 0x68, 0x2d, 0x09, 0x43, 0x04, /* B..h-.C. */ + 0x5b, 0x00, 0xef, 0xf8, 0xaf, 0x32, 0xef, 0xfa, /* [....2.. */ + 0xaf, 0x03, 0x50, 0x01, 0xef, 0xf8, 0xaf, 0x42, /* ..P....B */ + 0xef, 0xfa, 0xaf, 0x05, 0x27 /* ....' */ }; static const unsigned char pkt257[] = { -0x42, 0x26, 0x00, -0x74, 0x2d, 0xd3, 0x45, 0xfd, /* B&.t-.E. */ -0x5a, 0x0f, 0x27, 0xd3, 0x45, 0xfa, 0x5a, 0x0f, /* Z.'.E.Z. */ -0x27, 0xd3, 0x45, 0xf7, 0x5a, 0x0f, 0x27, 0x41, /* '.E.Z.'A */ -0x2e, 0xa1, 0xdf, 0x9f, 0x28, 0x41, 0x2e, 0xa1, /* ....(A.. */ -0xbf, 0x02, 0x2e, 0x58, 0x80, 0x00, 0x2e, 0xcb, /* ...X.... */ -0x7a /* z */ + 0x42, 0x26, 0x00, + 0x74, 0x2d, 0xd3, 0x45, 0xfd, /* B&.t-.E. */ + 0x5a, 0x0f, 0x27, 0xd3, 0x45, 0xfa, 0x5a, 0x0f, /* Z.'.E.Z. */ + 0x27, 0xd3, 0x45, 0xf7, 0x5a, 0x0f, 0x27, 0x41, /* '.E.Z.'A */ + 0x2e, 0xa1, 0xdf, 0x9f, 0x28, 0x41, 0x2e, 0xa1, /* ....(A.. */ + 0xbf, 0x02, 0x2e, 0x58, 0x80, 0x00, 0x2e, 0xcb, /* ...X.... */ + 0x7a /* z */ }; static const unsigned char pkt259[] = { -0x42, 0x16, 0x00, -0x86, 0x2d, 0xd3, 0x45, 0x02, /* B...-.E. */ -0x5a, 0xd3, 0x45, 0x00, 0x5a, 0x05, 0x27, 0xd0, /* Z.E.Z.'. */ -0x41, 0xf8, 0x5b, 0xed, 0x83, 0xf6, 0x50, 0x05, /* A.[...P. */ -0x27 /* ' */ + 0x42, 0x16, 0x00, + 0x86, 0x2d, 0xd3, 0x45, 0x02, /* B...-.E. */ + 0x5a, 0xd3, 0x45, 0x00, 0x5a, 0x05, 0x27, 0xd0, /* Z.E.Z.'. */ + 0x41, 0xf8, 0x5b, 0xed, 0x83, 0xf6, 0x50, 0x05, /* A.[...P. */ + 0x27 /* ' */ }; static const unsigned char pkt261[] = { -0x42, 0x4e, 0x00, -0x90, 0x2d, 0x07, 0x3d, 0x02, /* BN..-.=. */ -0x5b, 0xae, 0x87, 0xc2, 0x23, 0xd3, 0x3c, 0x02, /* [...#.<. */ -0x44, 0xd4, 0x2f, 0xf8, 0x5a, 0x02, 0x45, 0xd5, /* D./.Z.E. */ -0x2f, 0x59, 0x5b, 0x58, 0x23, 0x3c, 0x26, 0x02, /* /Y[X#<&. */ -0x55, 0x02, 0x2e, 0x4f, 0x8c, 0x00, 0x50, 0xff, /* U..O..P. */ -0x8e, 0x07, 0x45, 0xeb, 0x5a, 0x41, 0x2e, 0x53, /* ..E.ZA.S */ -0xdf, 0xc1, 0x2e, 0x79, 0xdf, 0xff, 0x96, 0xdf, /* ...y.... */ -0x96, 0x41, 0x2e, 0x55, 0xdf, 0xc1, 0x2e, 0x78, /* .A.U...x */ -0xdf, 0x9d, 0x01, 0x5d, 0x01, 0xff, 0x22, 0x00, /* ...]..". */ -0x54, 0xff, 0xef, 0x2e, 0xaf, 0xd5, 0x2f, 0x3e, /* T...../> */ -0x50 /* P */ + 0x42, 0x4e, 0x00, + 0x90, 0x2d, 0x07, 0x3d, 0x02, /* BN..-.=. */ + 0x5b, 0xae, 0x87, 0xc2, 0x23, 0xd3, 0x3c, 0x02, /* [...#.<. */ + 0x44, 0xd4, 0x2f, 0xf8, 0x5a, 0x02, 0x45, 0xd5, /* D./.Z.E. */ + 0x2f, 0x59, 0x5b, 0x58, 0x23, 0x3c, 0x26, 0x02, /* /Y[X#<&. */ + 0x55, 0x02, 0x2e, 0x4f, 0x8c, 0x00, 0x50, 0xff, /* U..O..P. */ + 0x8e, 0x07, 0x45, 0xeb, 0x5a, 0x41, 0x2e, 0x53, /* ..E.ZA.S */ + 0xdf, 0xc1, 0x2e, 0x79, 0xdf, 0xff, 0x96, 0xdf, /* ...y.... */ + 0x96, 0x41, 0x2e, 0x55, 0xdf, 0xc1, 0x2e, 0x78, /* .A.U...x */ + 0xdf, 0x9d, 0x01, 0x5d, 0x01, 0xff, 0x22, 0x00, /* ...]..". */ + 0x54, 0xff, 0xef, 0x2e, 0xaf, 0xd5, 0x2f, 0x3e, /* T...../> */ + 0x50 /* P */ }; static const unsigned char pkt263[] = { -0x42, 0xca, 0x00, -0xb6, 0x2d, 0xfa, 0xcf, 0xdf, /* B...-... */ -0x96, 0x37, 0xcf, 0xdf, 0x96, 0x08, 0xcf, 0xdf, /* .7...... */ -0x96, 0x3d, 0xcf, 0xdf, 0x96, 0x77, 0xcf, 0xdf, /* .=...w.. */ -0x96, 0x26, 0xcf, 0xdf, 0x96, 0x26, 0x23, 0x01, /* .&...&#. */ -0x2e, 0x08, 0x82, 0xdd, 0x97, 0x26, 0xaf, 0xdd, /* .....&.. */ -0x97, 0x77, 0xaf, 0xdd, 0x97, 0x3d, 0xaf, 0xdd, /* .w...=.. */ -0x97, 0x08, 0xaf, 0xdd, 0x97, 0x37, 0xaf, 0xdd, /* .....7.. */ -0x97, 0xfa, 0xaf, 0x9f, 0x22, 0x6d, 0x2e, 0x6d, /* ...."m.m */ -0xbf, 0x26, 0x40, 0x3a, 0x5b, 0x73, 0x43, 0x08, /* .&@:[sC. */ -0x5b, 0x73, 0xcf, 0x09, 0x27, 0x0f, 0x1c, 0x10, /* [s..'... */ -0xaf, 0x82, 0xcf, 0x01, 0x2e, 0xf9, 0x81, 0xed, /* ........ */ -0x80, 0x05, 0x50, 0x81, 0xcf, 0x10, 0xaf, 0x82, /* ..P..... */ -0xcf, 0x01, 0x2e, 0xf9, 0x81, 0xed, 0x80, 0xc8, /* ........ */ -0xef, 0x0f, 0xaf, 0x08, 0x31, 0x31, 0xef, 0x0a, /* ....11.. */ -0xaf, 0x9f, 0x22, 0x0d, 0xaf, 0x81, 0xcf, 0x10, /* .."..... */ -0xaf, 0x01, 0x2e, 0x94, 0x86, 0x82, 0xcf, 0x04, /* ........ */ -0x16, 0x01, 0x2e, 0xf9, 0x81, 0xed, 0x80, 0x10, /* ........ */ -0xcf, 0xb0, 0xff, 0x3f, 0x00, 0x00, 0xff, 0x00, /* ...?.... */ -0x13, 0x1a, 0x27, 0xd6, 0x97, 0x82, 0xdf, 0xbf, /* ..'..... */ -0x01, 0x6d, 0x2e, 0x6d, 0xbf, 0x74, 0xcf, 0x02, /* .m.m.t.. */ -0x1e, 0x04, 0x55, 0xa0, 0xcf, 0xcf, 0x1c, 0x10, /* ..U..... */ -0x18, 0xa0, 0xaf, 0x05, 0x50, 0x01, 0x1e, 0x04, /* ....P... */ -0x55, 0xa0, 0xcf, 0xcf, 0x1c, 0x20, 0x18, 0xa0, /* U.... .. */ -0xaf, 0xed, 0x80, 0xfb, 0x39, 0x08, 0x45, 0x00, /* ....9.E. */ -0x5a, 0xfb, 0x31, 0x0a, 0x42, 0x00, 0x5b, 0xa2, /* Z.1.B.[. */ -0x39, 0x02, 0xcf, 0x5c, 0xaf /* 9..\. */ + 0x42, 0xca, 0x00, + 0xb6, 0x2d, 0xfa, 0xcf, 0xdf, /* B...-... */ + 0x96, 0x37, 0xcf, 0xdf, 0x96, 0x08, 0xcf, 0xdf, /* .7...... */ + 0x96, 0x3d, 0xcf, 0xdf, 0x96, 0x77, 0xcf, 0xdf, /* .=...w.. */ + 0x96, 0x26, 0xcf, 0xdf, 0x96, 0x26, 0x23, 0x01, /* .&...&#. */ + 0x2e, 0x08, 0x82, 0xdd, 0x97, 0x26, 0xaf, 0xdd, /* .....&.. */ + 0x97, 0x77, 0xaf, 0xdd, 0x97, 0x3d, 0xaf, 0xdd, /* .w...=.. */ + 0x97, 0x08, 0xaf, 0xdd, 0x97, 0x37, 0xaf, 0xdd, /* .....7.. */ + 0x97, 0xfa, 0xaf, 0x9f, 0x22, 0x6d, 0x2e, 0x6d, /* ...."m.m */ + 0xbf, 0x26, 0x40, 0x3a, 0x5b, 0x73, 0x43, 0x08, /* .&@:[sC. */ + 0x5b, 0x73, 0xcf, 0x09, 0x27, 0x0f, 0x1c, 0x10, /* [s..'... */ + 0xaf, 0x82, 0xcf, 0x01, 0x2e, 0xf9, 0x81, 0xed, /* ........ */ + 0x80, 0x05, 0x50, 0x81, 0xcf, 0x10, 0xaf, 0x82, /* ..P..... */ + 0xcf, 0x01, 0x2e, 0xf9, 0x81, 0xed, 0x80, 0xc8, /* ........ */ + 0xef, 0x0f, 0xaf, 0x08, 0x31, 0x31, 0xef, 0x0a, /* ....11.. */ + 0xaf, 0x9f, 0x22, 0x0d, 0xaf, 0x81, 0xcf, 0x10, /* .."..... */ + 0xaf, 0x01, 0x2e, 0x94, 0x86, 0x82, 0xcf, 0x04, /* ........ */ + 0x16, 0x01, 0x2e, 0xf9, 0x81, 0xed, 0x80, 0x10, /* ........ */ + 0xcf, 0xb0, 0xff, 0x3f, 0x00, 0x00, 0xff, 0x00, /* ...?.... */ + 0x13, 0x1a, 0x27, 0xd6, 0x97, 0x82, 0xdf, 0xbf, /* ..'..... */ + 0x01, 0x6d, 0x2e, 0x6d, 0xbf, 0x74, 0xcf, 0x02, /* .m.m.t.. */ + 0x1e, 0x04, 0x55, 0xa0, 0xcf, 0xcf, 0x1c, 0x10, /* ..U..... */ + 0x18, 0xa0, 0xaf, 0x05, 0x50, 0x01, 0x1e, 0x04, /* ....P... */ + 0x55, 0xa0, 0xcf, 0xcf, 0x1c, 0x20, 0x18, 0xa0, /* U.... .. */ + 0xaf, 0xed, 0x80, 0xfb, 0x39, 0x08, 0x45, 0x00, /* ....9.E. */ + 0x5a, 0xfb, 0x31, 0x0a, 0x42, 0x00, 0x5b, 0xa2, /* Z.1.B.[. */ + 0x39, 0x02, 0xcf, 0x5c, 0xaf /* 9..\. */ }; static const unsigned char pkt265[] = { -0x42, 0x96, 0x00, -0x1a, 0x2e, 0xe1, 0xef, 0x95, /* B....... */ -0xaf, 0x9f, 0x22, 0x61, 0xaf, 0x62, 0xaf, 0x69, /* .."a.b.i */ -0xaf, 0x6a, 0xaf, 0x16, 0xaf, 0x96, 0xaf, 0x29, /* .j.....) */ -0xaf, 0x28, 0xaf, 0xc1, 0x2e, 0x49, 0xdf, 0x3f, /* .(...I.? */ -0x2d, 0x03, 0x5b, 0xa0, 0xcf, 0x8f, 0x1c, 0x20, /* -.[.... */ -0x18, 0xa0, 0xaf, 0xa1, 0xcf, 0xdf, 0x1c, 0xa1, /* ........ */ -0xaf, 0xed, 0x80, 0x02, 0x47, 0x06, 0x5a, 0x0a, /* ....G.Z. */ -0x41, 0x04, 0x5a, 0x0a, 0xdf, 0x30, 0x1d, 0x30, /* A.Z..0.0 */ -0x1f, 0x00, 0x54, 0x01, 0xef, 0x44, 0xaf, 0x09, /* ..T..D.. */ -0xef, 0x60, 0xaf, 0xa7, 0xef, 0x40, 0xaf, 0x2d, /* .`...@.- */ -0xef, 0x41, 0xaf, 0x0a, 0x40, 0x06, 0x5a, 0x10, /* .A..@.Z. */ -0xcf, 0x27, 0xaf, 0xe2, 0x23, 0x6e, 0x23, 0x08, /* .'..#n#. */ -0xef, 0xe3, 0xaf, 0x6f, 0xaf, 0xe2, 0x23, 0x08, /* ...o..#. */ -0xef, 0xe3, 0xaf, 0x79, 0x82, 0x4d, 0xaf, 0xdf, /* ...y.M.. */ -0x96, 0x64, 0xdf, 0x8b, 0x82, 0x93, 0xbf, 0xdd, /* .d...... */ -0x97, 0x77, 0xff, 0x8b, 0x82, 0x94, 0xbf, 0x9e, /* .w...... */ -0x23, 0xe4, 0x23, 0x9f, 0x22, 0x6d, 0x2e, 0x6b, /* #.#."m.k */ -0xbf, 0x6d, 0x2e, 0x6a, 0xbf, 0x6d, 0x2e, 0x6c, /* .m.j.m.l */ -0xbf, 0xa5, 0xcf, 0xf3, 0x1c, 0xa5, 0xaf, 0x05, /* ........ */ -0x27 /* ' */ + 0x42, 0x96, 0x00, + 0x1a, 0x2e, 0xe1, 0xef, 0x95, /* B....... */ + 0xaf, 0x9f, 0x22, 0x61, 0xaf, 0x62, 0xaf, 0x69, /* .."a.b.i */ + 0xaf, 0x6a, 0xaf, 0x16, 0xaf, 0x96, 0xaf, 0x29, /* .j.....) */ + 0xaf, 0x28, 0xaf, 0xc1, 0x2e, 0x49, 0xdf, 0x3f, /* .(...I.? */ + 0x2d, 0x03, 0x5b, 0xa0, 0xcf, 0x8f, 0x1c, 0x20, /* -.[.... */ + 0x18, 0xa0, 0xaf, 0xa1, 0xcf, 0xdf, 0x1c, 0xa1, /* ........ */ + 0xaf, 0xed, 0x80, 0x02, 0x47, 0x06, 0x5a, 0x0a, /* ....G.Z. */ + 0x41, 0x04, 0x5a, 0x0a, 0xdf, 0x30, 0x1d, 0x30, /* A.Z..0.0 */ + 0x1f, 0x00, 0x54, 0x01, 0xef, 0x44, 0xaf, 0x09, /* ..T..D.. */ + 0xef, 0x60, 0xaf, 0xa7, 0xef, 0x40, 0xaf, 0x2d, /* .`...@.- */ + 0xef, 0x41, 0xaf, 0x0a, 0x40, 0x06, 0x5a, 0x10, /* .A..@.Z. */ + 0xcf, 0x27, 0xaf, 0xe2, 0x23, 0x6e, 0x23, 0x08, /* .'..#n#. */ + 0xef, 0xe3, 0xaf, 0x6f, 0xaf, 0xe2, 0x23, 0x08, /* ...o..#. */ + 0xef, 0xe3, 0xaf, 0x79, 0x82, 0x4d, 0xaf, 0xdf, /* ...y.M.. */ + 0x96, 0x64, 0xdf, 0x8b, 0x82, 0x93, 0xbf, 0xdd, /* .d...... */ + 0x97, 0x77, 0xff, 0x8b, 0x82, 0x94, 0xbf, 0x9e, /* .w...... */ + 0x23, 0xe4, 0x23, 0x9f, 0x22, 0x6d, 0x2e, 0x6b, /* #.#."m.k */ + 0xbf, 0x6d, 0x2e, 0x6a, 0xbf, 0x6d, 0x2e, 0x6c, /* .m.j.m.l */ + 0xbf, 0xa5, 0xcf, 0xf3, 0x1c, 0xa5, 0xaf, 0x05, /* ........ */ + 0x27 /* ' */ }; static const unsigned char pkt267[] = { -0x42, 0x2c, 0x00, -0x64, 0x2e, 0xf9, 0x32, 0xf9, /* B,.d..2. */ -0x3a, 0xaf, 0xef, 0x00, 0xff, 0x1b, 0x27, 0xf6, /* :.....'. */ -0x97, 0xcf, 0xaf, 0x0f, 0xef, 0x06, 0xaf, 0xce, /* ........ */ -0x30, 0x0f, 0x27, 0x0f, 0x27, 0xfa, 0x97, 0xcf, /* 0.'.'... */ -0xaf, 0xce, 0x32, 0x06, 0x25, 0xf8, 0x55, 0xce, /* ..2.%.U. */ -0x43, 0xfd, 0x5b, 0xce, 0x31, 0x05, 0x27 /* C.[.1.' */ + 0x42, 0x2c, 0x00, + 0x64, 0x2e, 0xf9, 0x32, 0xf9, /* B,.d..2. */ + 0x3a, 0xaf, 0xef, 0x00, 0xff, 0x1b, 0x27, 0xf6, /* :.....'. */ + 0x97, 0xcf, 0xaf, 0x0f, 0xef, 0x06, 0xaf, 0xce, /* ........ */ + 0x30, 0x0f, 0x27, 0x0f, 0x27, 0xfa, 0x97, 0xcf, /* 0.'.'... */ + 0xaf, 0xce, 0x32, 0x06, 0x25, 0xf8, 0x55, 0xce, /* ..2.%.U. */ + 0x43, 0xfd, 0x5b, 0xce, 0x31, 0x05, 0x27 /* C.[.1.' */ }; static const unsigned char pkt269[] = { -0x42, 0x26, 0x00, -0x79, 0x2e, 0xbf, 0x22, 0xff, /* B&.y..". */ -0xef, 0x1b, 0x27, 0xdd, 0x97, 0xdd, 0x9f, 0x06, /* ..'..... */ -0xaf, 0x4e, 0xbf, 0xff, 0x22, 0x04, 0x54, 0xbd, /* .N..".T. */ -0x9d, 0x06, 0x25, 0xfc, 0x53, 0x4e, 0x25, 0xfa, /* ..%.SN%. */ -0x55, 0xbd, 0x9d, 0x06, 0x25, 0xfc, 0x55, 0x05, /* U...%.U. */ -0x27 /* ' */ + 0x42, 0x26, 0x00, + 0x79, 0x2e, 0xbf, 0x22, 0xff, /* B&.y..". */ + 0xef, 0x1b, 0x27, 0xdd, 0x97, 0xdd, 0x9f, 0x06, /* ..'..... */ + 0xaf, 0x4e, 0xbf, 0xff, 0x22, 0x04, 0x54, 0xbd, /* .N..".T. */ + 0x9d, 0x06, 0x25, 0xfc, 0x53, 0x4e, 0x25, 0xfa, /* ..%.SN%. */ + 0x55, 0xbd, 0x9d, 0x06, 0x25, 0xfc, 0x55, 0x05, /* U...%.U. */ + 0x27 /* ' */ }; static const unsigned char pkt271[] = { -0x42, 0x3c, 0x00, -0x8b, 0x2e, 0xbf, 0x22, 0xff, /* B<....". */ -0xef, 0x1b, 0x27, 0xdc, 0x99, 0x28, 0x28, 0x28, /* ..'..((( */ -0x2a, 0x68, 0x2c, 0xfd, 0x5b, 0xa9, 0x9d, 0x6a, /* *h,.[..j */ -0x28, 0x06, 0x25, 0xf6, 0x53, 0x4e, 0x25, 0xf4, /* (.%.SN%. */ -0x55, 0xdc, 0x99, 0x28, 0x28, 0x28, 0x2a, 0x68, /* U..(((*h */ -0x2c, 0xfd, 0x5b, 0xa9, 0x9d, 0x6a, 0x28, 0x06, /* ,.[..j(. */ -0x25, 0xf6, 0x55, 0x01, 0x2e, 0xe4, 0x85, 0xbf, /* %.U..... */ -0x22, 0xbf, 0x99, 0x7f, 0x99, 0x05, 0x27 /* ".....' */ + 0x42, 0x3c, 0x00, + 0x8b, 0x2e, 0xbf, 0x22, 0xff, /* B<....". */ + 0xef, 0x1b, 0x27, 0xdc, 0x99, 0x28, 0x28, 0x28, /* ..'..((( */ + 0x2a, 0x68, 0x2c, 0xfd, 0x5b, 0xa9, 0x9d, 0x6a, /* *h,.[..j */ + 0x28, 0x06, 0x25, 0xf6, 0x53, 0x4e, 0x25, 0xf4, /* (.%.SN%. */ + 0x55, 0xdc, 0x99, 0x28, 0x28, 0x28, 0x2a, 0x68, /* U..(((*h */ + 0x2c, 0xfd, 0x5b, 0xa9, 0x9d, 0x6a, 0x28, 0x06, /* ,.[..j(. */ + 0x25, 0xf6, 0x55, 0x01, 0x2e, 0xe4, 0x85, 0xbf, /* %.U..... */ + 0x22, 0xbf, 0x99, 0x7f, 0x99, 0x05, 0x27 /* ".....' */ }; static const unsigned char pkt273[] = { -0x67, 0x05, 0x00, 0x00, 0x02, 0x2e, 0x00, 0x70, /* g......p */ -0x67, 0x05, 0x00, 0x02, 0x02, 0x2e, 0x88, 0x70, /* g......p */ -0x67, 0x05, 0x00, 0x01, 0x02, 0x2e, 0x3c, 0x71, /* g.....data_buflen = DATA_BUFLEN; - aesdev->frame_width = FRAME_WIDTH; - aesdev->frame_size = FRAME_SIZE; - aesdev->frame_number = FRAME_NUMBER; - aesdev->enlarge_factor = ENLARGE_FACTOR; - aesdev->init_reqs = init_reqs; - aesdev->init_reqs_len = G_N_ELEMENTS(init_reqs); - fpi_imgdev_open_complete(dev, 0); - - return r; +static void +fpi_device_aes3500_init (FpiDeviceAes3500 *self) +{ } -static void dev_deinit(struct fp_img_dev *dev) +static void +fpi_device_aes3500_class_init (FpiDeviceAes3500Class *klass) { - struct aes3k_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - g_free(aesdev); - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - fpi_imgdev_close_complete(dev); + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); + FpiDeviceAes3kClass *aes_class = FPI_DEVICE_AES3K_CLASS (klass); + + dev_class->id = "aes3500"; + dev_class->full_name = "AuthenTec AES3500"; + dev_class->id_table = id_table; + + img_class->img_height = FRAME_WIDTH * ENLARGE_FACTOR; + img_class->img_width = FRAME_WIDTH * ENLARGE_FACTOR; + + aes_class->data_buflen = DATA_BUFLEN; + aes_class->frame_width = FRAME_WIDTH; + aes_class->frame_size = FRAME_SIZE; + aes_class->frame_number = FRAME_NUMBER; + aes_class->enlarge_factor = ENLARGE_FACTOR; + aes_class->init_reqs = init_reqs; + aes_class->init_reqs_len = G_N_ELEMENTS (init_reqs); } - - -static const struct usb_id id_table[] = { - { .vendor = 0x08ff, .product = 0x5731 }, - { 0, 0, 0, }, -}; - -struct fp_img_driver aes3500_driver = { - .driver = { - .id = AES3500_ID, - .name = FP_COMPONENT, - .full_name = "AuthenTec AES3500", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_PRESS, - }, - .flags = 0, - .img_height = FRAME_WIDTH * ENLARGE_FACTOR, - .img_width = FRAME_WIDTH * ENLARGE_FACTOR, - - /* temporarily lowered until image quality improves */ - .bz3_threshold = 9, - - .open = dev_init, - .close = dev_deinit, - .activate = aes3k_dev_activate, - .deactivate = aes3k_dev_deactivate, -}; - diff --git a/libfprint/drivers/aes3k.c b/libfprint/drivers/aes3k.c index ddb94c9b..f73ac026 100644 --- a/libfprint/drivers/aes3k.c +++ b/libfprint/drivers/aes3k.c @@ -40,119 +40,188 @@ #include "aeslib.h" #include "aes3k.h" -#define CTRL_TIMEOUT 1000 -#define EP_IN (1 | LIBUSB_ENDPOINT_IN) -#define EP_OUT (2 | LIBUSB_ENDPOINT_OUT) - -static void do_capture(struct fp_img_dev *dev); - -static void aes3k_assemble_image(unsigned char *input, size_t width, size_t height, - unsigned char *output) +typedef struct { - size_t row, column; + FpiUsbTransfer *img_trf; + gboolean deactivating; +} FpiDeviceAes3kPrivate; - for (column = 0; column < width; column++) { - for (row = 0; row < height; row += 2) { - output[width * row + column] = (*input & 0x0f) * 17; - output[width * (row + 1) + column] = ((*input & 0xf0) >> 4) * 17; - input++; - } - } +#define CTRL_TIMEOUT 1000 +#define EP_IN (1 | FPI_USB_ENDPOINT_IN) +#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT) + +static void do_capture (FpImageDevice *dev); + +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (FpiDeviceAes3k, fpi_device_aes3k, FP_TYPE_IMAGE_DEVICE); + +static void +aes3k_assemble_image (unsigned char *input, size_t width, size_t height, + unsigned char *output) +{ + size_t row, column; + + for (column = 0; column < width; column++) + { + for (row = 0; row < height; row += 2) + { + output[width * row + column] = (*input & 0x0f) * 17; + output[width * (row + 1) + column] = ((*input & 0xf0) >> 4) * 17; + input++; + } + } } -static void img_cb(struct libusb_transfer *transfer) +static void +img_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - struct fp_img_dev *dev = transfer->user_data; - struct aes3k_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - unsigned char *ptr = transfer->buffer; - struct fp_img *tmp; - struct fp_img *img; - int i; + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpiDeviceAes3k *self = FPI_DEVICE_AES3K (device); + FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self); + FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self); + unsigned char *ptr = transfer->buffer; + FpImage *tmp; + FpImage *img; + int i; - if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { - goto err; - } else if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fpi_imgdev_session_error(dev, -EIO); - goto err; - } else if (transfer->length != transfer->actual_length) { - fpi_imgdev_session_error(dev, -EPROTO); - goto err; - } + priv->img_trf = NULL; - fpi_imgdev_report_finger_status(dev, TRUE); + if (error) + { + if (g_error_matches (error, + G_IO_ERROR, + G_IO_ERROR_CANCELLED)) + { + /* Deactivation was completed. */ + g_error_free (error); + if (priv->deactivating) + fpi_image_device_deactivate_complete (dev, NULL); + return; + } - tmp = fpi_img_new(aesdev->frame_width * aesdev->frame_width); - tmp->width = aesdev->frame_width; - tmp->height = aesdev->frame_width; - tmp->flags = FP_IMG_COLORS_INVERTED | FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED; - for (i = 0; i < aesdev->frame_number; i++) { - fp_dbg("frame header byte %02x", *ptr); - ptr++; - aes3k_assemble_image(ptr, aesdev->frame_width, AES3K_FRAME_HEIGHT, tmp->data + (i * aesdev->frame_width * AES3K_FRAME_HEIGHT)); - ptr += aesdev->frame_size; - } + fpi_image_device_session_error (dev, error); + } - /* FIXME: this is an ugly hack to make the image big enough for NBIS - * to process reliably */ - img = fpi_img_resize(tmp, aesdev->enlarge_factor, aesdev->enlarge_factor); - fp_img_free(tmp); - fpi_imgdev_image_captured(dev, img); + fpi_image_device_report_finger_status (dev, TRUE); - /* FIXME: rather than assuming finger has gone, we should poll regs until - * it really has, then restart the capture */ - fpi_imgdev_report_finger_status(dev, FALSE); + tmp = fp_image_new (cls->frame_width, cls->frame_width); + tmp->width = cls->frame_width; + tmp->height = cls->frame_width; + tmp->flags = FPI_IMAGE_COLORS_INVERTED | FPI_IMAGE_V_FLIPPED | FPI_IMAGE_H_FLIPPED; + for (i = 0; i < cls->frame_number; i++) + { + fp_dbg ("frame header byte %02x", *ptr); + ptr++; + aes3k_assemble_image (ptr, cls->frame_width, AES3K_FRAME_HEIGHT, tmp->data + (i * cls->frame_width * AES3K_FRAME_HEIGHT)); + ptr += cls->frame_size; + } - do_capture(dev); + /* FIXME: this is an ugly hack to make the image big enough for NBIS + * to process reliably */ + img = fpi_image_resize (tmp, cls->enlarge_factor, cls->enlarge_factor); + g_object_unref (tmp); + fpi_image_device_image_captured (dev, img); -err: - g_free(transfer->buffer); - aesdev->img_trf = NULL; - libusb_free_transfer(transfer); + /* FIXME: rather than assuming finger has gone, we should poll regs until + * it really has, then restart the capture */ + fpi_image_device_report_finger_status (dev, FALSE); + + do_capture (dev); } -static void do_capture(struct fp_img_dev *dev) +static void +do_capture (FpImageDevice *dev) { - struct aes3k_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - unsigned char *data; - int r; + FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev); + FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self); + FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self); - aesdev->img_trf = fpi_usb_alloc(); - data = g_malloc(aesdev->data_buflen); - libusb_fill_bulk_transfer(aesdev->img_trf, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, - aesdev->data_buflen, img_cb, dev, 0); - - r = libusb_submit_transfer(aesdev->img_trf); - if (r < 0) { - g_free(data); - libusb_free_transfer(aesdev->img_trf); - aesdev->img_trf = NULL; - fpi_imgdev_session_error(dev, r); - } + priv->img_trf = fpi_usb_transfer_new (FP_DEVICE (dev)); + fpi_usb_transfer_fill_bulk (priv->img_trf, EP_IN, cls->data_buflen); + priv->img_trf->short_is_error = TRUE; + fpi_usb_transfer_submit (priv->img_trf, 0, + fpi_device_get_cancellable (FP_DEVICE (dev)), + img_cb, NULL); + fpi_usb_transfer_unref (priv->img_trf); } -static void init_reqs_cb(struct fp_img_dev *dev, int result, void *user_data) +static void +init_reqs_cb (FpImageDevice *dev, GError *result, void *user_data) { - fpi_imgdev_activate_complete(dev, result); - if (result == 0) - do_capture(dev); + fpi_image_device_activate_complete (dev, result); + if (!result) + do_capture (dev); } -int aes3k_dev_activate(struct fp_img_dev *dev) +static void +aes3k_dev_activate (FpImageDevice *dev) { - struct aes3k_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - aes_write_regv(dev, aesdev->init_reqs, aesdev->init_reqs_len, init_reqs_cb, NULL); - return 0; + FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev); + FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self); + FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self); + + priv->deactivating = FALSE; + aes_write_regv (dev, cls->init_reqs, cls->init_reqs_len, init_reqs_cb, NULL); } -void aes3k_dev_deactivate(struct fp_img_dev *dev) +static void +aes3k_dev_deactivate (FpImageDevice *dev) { - struct aes3k_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev); + FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self); - /* FIXME: should wait for cancellation to complete before returning - * from deactivation, otherwise app may legally exit before we've - * cleaned up */ - if (aesdev->img_trf) - libusb_cancel_transfer(aesdev->img_trf); - fpi_imgdev_deactivate_complete(dev); + priv->deactivating = TRUE; + if (priv->img_trf) + return; + fpi_image_device_deactivate_complete (dev, NULL); } +static void +fpi_device_aes3k_init (FpiDeviceAes3k *self) +{ +} + +static void +aes3k_dev_init (FpImageDevice *dev) +{ + GError *error = NULL; + + if (!g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error)) + { + fpi_image_device_open_complete (dev, error); + return; + } + + fpi_image_device_open_complete (dev, NULL); +} + +static void +aes3k_dev_deinit (FpImageDevice *dev) +{ + GError *error = NULL; + + g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), + 0, 0, &error); + fpi_image_device_close_complete (dev, error); +} + + +static void +fpi_device_aes3k_class_init (FpiDeviceAes3kClass *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); + + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->scan_type = FP_SCAN_TYPE_PRESS; + + img_class->img_open = aes3k_dev_init; + img_class->img_close = aes3k_dev_deinit; + img_class->activate = aes3k_dev_activate; + img_class->deactivate = aes3k_dev_deactivate; + + /* Extremely low due to low image quality. */ + img_class->bz3_threshold = 9; + + /* Everything else is set by the subclasses. */ +} diff --git a/libfprint/drivers/aes3k.h b/libfprint/drivers/aes3k.h index a54199d0..539f4e11 100644 --- a/libfprint/drivers/aes3k.h +++ b/libfprint/drivers/aes3k.h @@ -34,25 +34,27 @@ * */ -#ifndef __AES3K_H -#define __AES3K_H +#pragma once +#include "fpi-image-device.h" +#include "aeslib.h" -#define AES3K_FRAME_HEIGHT 16 +#define AES3K_FRAME_HEIGHT 16 -struct aes3k_dev { - struct libusb_transfer *img_trf; - size_t frame_width; /* image size = frame_width x frame_width */ - size_t frame_size; /* 4 bits/pixel: frame_width x AES3K_FRAME_HEIGHT / 2 */ - size_t frame_number; /* number of frames */ - size_t enlarge_factor; +G_DECLARE_DERIVABLE_TYPE (FpiDeviceAes3k, fpi_device_aes3k, FPI, + DEVICE_AES3K, FpImageDevice) - size_t data_buflen; /* buffer length of usb bulk transfer */ - struct aes_regwrite *init_reqs; /* initial values sent to device */ - size_t init_reqs_len; +#define FPI_TYPE_DEVICE_AES3K (fpi_device_aes3k_get_type ()) + +struct _FpiDeviceAes3kClass +{ + FpImageDeviceClass parent; + + gsize frame_width; /* image size = frame_width x frame_width */ + gsize frame_size; /* 4 bits/pixel: frame_width x AES3K_FRAME_HEIGHT / 2 */ + gsize frame_number; /* number of frames */ + gsize enlarge_factor; + + gsize data_buflen; /* buffer length of usb bulk transfer */ + struct aes_regwrite *init_reqs; /* initial values sent to device */ + gsize init_reqs_len; }; - - -int aes3k_dev_activate(struct fp_img_dev *dev); -void aes3k_dev_deactivate(struct fp_img_dev *dev); - -#endif diff --git a/libfprint/drivers/aes4000.c b/libfprint/drivers/aes4000.c index 6ea79d15..0a801f6b 100644 --- a/libfprint/drivers/aes4000.c +++ b/libfprint/drivers/aes4000.c @@ -26,155 +26,130 @@ #define FP_COMPONENT "aes4000" -#include "drivers_api.h" -#include "aeslib.h" #include "aes3k.h" -#define DATA_BUFLEN 0x1259 +#define DATA_BUFLEN 0x1259 /* image size = FRAME_WIDTH x FRAME_WIDTH */ -#define FRAME_WIDTH 96 -#define FRAME_SIZE (FRAME_WIDTH * AES3K_FRAME_HEIGHT / 2) -#define FRAME_NUMBER (FRAME_WIDTH / AES3K_FRAME_HEIGHT) -#define ENLARGE_FACTOR 3 +#define FRAME_WIDTH 96 +#define FRAME_SIZE (FRAME_WIDTH * AES3K_FRAME_HEIGHT / 2) +#define FRAME_NUMBER (FRAME_WIDTH / AES3K_FRAME_HEIGHT) +#define ENLARGE_FACTOR 3 static struct aes_regwrite init_reqs[] = { - /* master reset */ - { 0x80, 0x01 }, - { 0, 0 }, - { 0x80, 0x00 }, - { 0, 0 }, + /* master reset */ + { 0x80, 0x01 }, + { 0, 0 }, + { 0x80, 0x00 }, + { 0, 0 }, - { 0x81, 0x00 }, - { 0x80, 0x00 }, - { 0, 0 }, + { 0x81, 0x00 }, + { 0x80, 0x00 }, + { 0, 0 }, - /* scan reset */ - { 0x80, 0x02 }, - { 0, 0 }, - { 0x80, 0x00 }, - { 0, 0 }, + /* scan reset */ + { 0x80, 0x02 }, + { 0, 0 }, + { 0x80, 0x00 }, + { 0, 0 }, - /* disable register buffering */ - { 0x80, 0x04 }, - { 0, 0 }, - { 0x80, 0x00 }, - { 0, 0 }, + /* disable register buffering */ + { 0x80, 0x04 }, + { 0, 0 }, + { 0x80, 0x00 }, + { 0, 0 }, - { 0x81, 0x00 }, - { 0, 0 }, - /* windows driver reads registers now (81 02) */ - { 0x80, 0x00 }, - { 0x81, 0x00 }, + { 0x81, 0x00 }, + { 0, 0 }, + /* windows driver reads registers now (81 02) */ + { 0x80, 0x00 }, + { 0x81, 0x00 }, - /* set excitation bias current: 2mhz drive ring frequency, - * 4V drive ring voltage, 16.5mA excitation bias */ - { 0x82, 0x04 }, + /* set excitation bias current: 2mhz drive ring frequency, + * 4V drive ring voltage, 16.5mA excitation bias */ + { 0x82, 0x04 }, - /* continuously sample drive ring for finger detection, - * 62.50ms debounce delay */ - { 0x83, 0x13 }, + /* continuously sample drive ring for finger detection, + * 62.50ms debounce delay */ + { 0x83, 0x13 }, - { 0x84, 0x07 }, /* set calibration resistance to 12 kiloohms */ - { 0x85, 0x3d }, /* set calibration capacitance */ - { 0x86, 0x03 }, /* detect drive voltage */ - { 0x87, 0x01 }, /* set detection frequency to 125khz */ - { 0x88, 0x02 }, /* set column scan period */ - { 0x89, 0x02 }, /* set measure drive */ - { 0x8a, 0x33 }, /* set measure frequency and sense amplifier bias */ - { 0x8b, 0x33 }, /* set matrix pattern */ - { 0x8c, 0x0f }, /* set demodulation phase 1 */ - { 0x8d, 0x04 }, /* set demodulation phase 2 */ - { 0x8e, 0x23 }, /* set sensor gain */ - { 0x8f, 0x07 }, /* set image parameters */ - { 0x90, 0x00 }, /* carrier offset null */ - { 0x91, 0x1c }, /* set A/D reference high */ - { 0x92, 0x08 }, /* set A/D reference low */ - { 0x93, 0x00 }, /* set start row to 0 */ - { 0x94, 0x05 }, /* set end row to 5 */ - { 0x95, 0x00 }, /* set start column to 0 */ - { 0x96, 0x18 }, /* set end column to 24*4=96 */ - { 0x97, 0x04 }, /* data format and thresholds */ - { 0x98, 0x28 }, /* image data control */ - { 0x99, 0x00 }, /* disable general purpose outputs */ - { 0x9a, 0x0b }, /* set initial scan state */ - { 0x9b, 0x00 }, /* clear challenge word bits */ - { 0x9c, 0x00 }, /* clear challenge word bits */ - { 0x9d, 0x09 }, /* set some challenge word bits */ - { 0x9e, 0x53 }, /* clear challenge word bits */ - { 0x9f, 0x6b }, /* set some challenge word bits */ - { 0, 0 }, + { 0x84, 0x07 }, /* set calibration resistance to 12 kiloohms */ + { 0x85, 0x3d }, /* set calibration capacitance */ + { 0x86, 0x03 }, /* detect drive voltage */ + { 0x87, 0x01 }, /* set detection frequency to 125khz */ + { 0x88, 0x02 }, /* set column scan period */ + { 0x89, 0x02 }, /* set measure drive */ + { 0x8a, 0x33 }, /* set measure frequency and sense amplifier bias */ + { 0x8b, 0x33 }, /* set matrix pattern */ + { 0x8c, 0x0f }, /* set demodulation phase 1 */ + { 0x8d, 0x04 }, /* set demodulation phase 2 */ + { 0x8e, 0x23 }, /* set sensor gain */ + { 0x8f, 0x07 }, /* set image parameters */ + { 0x90, 0x00 }, /* carrier offset null */ + { 0x91, 0x1c }, /* set A/D reference high */ + { 0x92, 0x08 }, /* set A/D reference low */ + { 0x93, 0x00 }, /* set start row to 0 */ + { 0x94, 0x05 }, /* set end row to 5 */ + { 0x95, 0x00 }, /* set start column to 0 */ + { 0x96, 0x18 }, /* set end column to 24*4=96 */ + { 0x97, 0x04 }, /* data format and thresholds */ + { 0x98, 0x28 }, /* image data control */ + { 0x99, 0x00 }, /* disable general purpose outputs */ + { 0x9a, 0x0b }, /* set initial scan state */ + { 0x9b, 0x00 }, /* clear challenge word bits */ + { 0x9c, 0x00 }, /* clear challenge word bits */ + { 0x9d, 0x09 }, /* set some challenge word bits */ + { 0x9e, 0x53 }, /* clear challenge word bits */ + { 0x9f, 0x6b }, /* set some challenge word bits */ + { 0, 0 }, - { 0x80, 0x00 }, - { 0x81, 0x00 }, - { 0, 0 }, - { 0x81, 0x04 }, - { 0, 0 }, - { 0x81, 0x00 }, + { 0x80, 0x00 }, + { 0x81, 0x00 }, + { 0, 0 }, + { 0x81, 0x04 }, + { 0, 0 }, + { 0x81, 0x00 }, }; -static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) +struct _FpiDeviceAes4000 { - int r; - struct aes3k_dev *aesdev; + FpiDeviceAes3k parent; +}; +G_DECLARE_FINAL_TYPE (FpiDeviceAes4000, fpi_device_aes4000, FPI, + DEVICE_AES4000, FpiDeviceAes3k); +G_DEFINE_TYPE (FpiDeviceAes4000, fpi_device_aes4000, FPI_TYPE_DEVICE_AES3K); - r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - if (r < 0) { - fp_err("could not claim interface 0: %s", libusb_error_name(r)); - return r; - } - aesdev = g_malloc0(sizeof(struct aes3k_dev)); - fp_dev_set_instance_data(FP_DEV(dev), aesdev); +static const FpIdEntry id_table[] = { + { .pid = 0x08ff, .vid = 0x5501 }, + { .vid = 0, .pid = 0, .driver_data = 0 }, +}; - if (!aesdev) - return -ENOMEM; - - aesdev->data_buflen = DATA_BUFLEN; - aesdev->frame_width = FRAME_WIDTH; - aesdev->frame_size = FRAME_SIZE; - aesdev->frame_number = FRAME_NUMBER; - aesdev->enlarge_factor = ENLARGE_FACTOR; - aesdev->init_reqs = init_reqs; - aesdev->init_reqs_len = G_N_ELEMENTS(init_reqs); - fpi_imgdev_open_complete(dev, 0); - - return r; +static void +fpi_device_aes4000_init (FpiDeviceAes4000 *self) +{ } -static void dev_deinit(struct fp_img_dev *dev) +static void +fpi_device_aes4000_class_init (FpiDeviceAes4000Class *klass) { - struct aes3k_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - g_free(aesdev); - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - fpi_imgdev_close_complete(dev); + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); + FpiDeviceAes3kClass *aes_class = FPI_DEVICE_AES3K_CLASS (klass); + + dev_class->id = "aes4000"; + dev_class->full_name = "AuthenTec AES4000"; + dev_class->id_table = id_table; + + img_class->img_height = FRAME_WIDTH * ENLARGE_FACTOR; + img_class->img_width = FRAME_WIDTH * ENLARGE_FACTOR; + + aes_class->data_buflen = DATA_BUFLEN; + aes_class->frame_width = FRAME_WIDTH; + aes_class->frame_size = FRAME_SIZE; + aes_class->frame_number = FRAME_NUMBER; + aes_class->enlarge_factor = ENLARGE_FACTOR; + aes_class->init_reqs = init_reqs; + aes_class->init_reqs_len = G_N_ELEMENTS (init_reqs); } - - -static const struct usb_id id_table[] = { - { .vendor = 0x08ff, .product = 0x5501 }, - { 0, 0, 0, }, -}; - -struct fp_img_driver aes4000_driver = { - .driver = { - .id = AES4000_ID, - .name = FP_COMPONENT, - .full_name = "AuthenTec AES4000", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_PRESS, - }, - .flags = 0, - .img_height = FRAME_WIDTH * ENLARGE_FACTOR, - .img_width = FRAME_WIDTH * ENLARGE_FACTOR, - - /* temporarily lowered until image quality improves */ - .bz3_threshold = 9, - - .open = dev_init, - .close = dev_deinit, - .activate = aes3k_dev_activate, - .deactivate = aes3k_dev_deactivate, -}; - diff --git a/libfprint/drivers/aeslib.c b/libfprint/drivers/aeslib.c index 24e307ce..8f92d876 100644 --- a/libfprint/drivers/aeslib.c +++ b/libfprint/drivers/aeslib.c @@ -24,154 +24,149 @@ #include #include -#include - -#include "fpi-usb.h" +#include "fpi-usb-transfer.h" #include "fpi-assembling.h" #include "aeslib.h" -#define MAX_REGWRITES_PER_REQUEST 16 +#define MAX_REGWRITES_PER_REQUEST 16 -#define BULK_TIMEOUT 4000 -#define EP_IN (1 | LIBUSB_ENDPOINT_IN) -#define EP_OUT (2 | LIBUSB_ENDPOINT_OUT) +#define BULK_TIMEOUT 4000 +#define EP_IN (1 | FPI_USB_ENDPOINT_IN) +#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT) -struct write_regv_data { - struct fp_img_dev *imgdev; - unsigned int num_regs; - const struct aes_regwrite *regs; - unsigned int offset; - aes_write_regv_cb callback; - void *user_data; +struct write_regv_data +{ + unsigned int num_regs; + const struct aes_regwrite *regs; + unsigned int offset; + aes_write_regv_cb callback; + void *user_data; }; -static void continue_write_regv(struct write_regv_data *wdata); +static void continue_write_regv (FpImageDevice *dev, + struct write_regv_data *wdata); /* libusb bulk callback for regv write completion transfer. continues the * transaction */ -static void write_regv_trf_complete(struct libusb_transfer *transfer) +static void +write_regv_trf_complete (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - struct write_regv_data *wdata = transfer->user_data; + struct write_regv_data *wdata = user_data; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - wdata->callback(wdata->imgdev, -EIO, wdata->user_data); - g_free(wdata); - } else if (transfer->length != transfer->actual_length) { - wdata->callback(wdata->imgdev, -EPROTO, wdata->user_data); - g_free(wdata); - } else { - continue_write_regv(wdata); - } - - g_free(transfer->buffer); - libusb_free_transfer(transfer); + if (error) + { + wdata->callback (FP_IMAGE_DEVICE (device), error, wdata->user_data); + g_free (wdata); + } + else + { + continue_write_regv (FP_IMAGE_DEVICE (device), wdata); + } } /* write from wdata->offset to upper_bound (inclusive) of wdata->regs */ -static int do_write_regv(struct write_regv_data *wdata, int upper_bound) +static void +do_write_regv (FpImageDevice *dev, struct write_regv_data *wdata, int upper_bound) { - unsigned int offset = wdata->offset; - unsigned int num = upper_bound - offset + 1; - size_t alloc_size = num * 2; - unsigned char *data = g_malloc(alloc_size); - unsigned int i; - size_t data_offset = 0; - struct libusb_transfer *transfer = fpi_usb_alloc(); - int r; + unsigned int offset = wdata->offset; + unsigned int num = upper_bound - offset + 1; + size_t alloc_size = num * 2; + unsigned int i; + size_t data_offset = 0; + FpiUsbTransfer *transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); - for (i = offset; i < offset + num; i++) { - const struct aes_regwrite *regwrite = &wdata->regs[i]; - data[data_offset++] = regwrite->reg; - data[data_offset++] = regwrite->value; - } + fpi_usb_transfer_fill_bulk (transfer, EP_OUT, alloc_size); - libusb_fill_bulk_transfer(transfer, FP_DEV(wdata->imgdev)->udev, EP_OUT, data, - alloc_size, write_regv_trf_complete, wdata, BULK_TIMEOUT); - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(data); - libusb_free_transfer(transfer); - } + for (i = offset; i < offset + num; i++) + { + const struct aes_regwrite *regwrite = &wdata->regs[i]; + transfer->buffer[data_offset++] = regwrite->reg; + transfer->buffer[data_offset++] = regwrite->value; + } - return r; + transfer->short_is_error = TRUE; + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + write_regv_trf_complete, wdata); + fpi_usb_transfer_unref (transfer); } /* write the next batch of registers to be written, or if there are no more, * indicate completion to the caller */ -static void continue_write_regv(struct write_regv_data *wdata) +static void +continue_write_regv (FpImageDevice *dev, struct write_regv_data *wdata) { - unsigned int offset = wdata->offset; - unsigned int regs_remaining; - unsigned int limit; - unsigned int upper_bound; - int i; - int r; + unsigned int offset = wdata->offset; + unsigned int regs_remaining; + unsigned int limit; + unsigned int upper_bound; + int i; - /* skip all zeros and ensure there is still work to do */ - while (TRUE) { - if (offset >= wdata->num_regs) { - fp_dbg("all registers written"); - wdata->callback(wdata->imgdev, 0, wdata->user_data); - g_free(wdata); - return; - } - if (wdata->regs[offset].reg) - break; - offset++; - } + /* skip all zeros and ensure there is still work to do */ + while (TRUE) + { + if (offset >= wdata->num_regs) + { + fp_dbg ("all registers written"); + wdata->callback (dev, 0, wdata->user_data); + g_free (wdata); + return; + } + if (wdata->regs[offset].reg) + break; + offset++; + } - wdata->offset = offset; - regs_remaining = wdata->num_regs - offset; - limit = MIN(regs_remaining, MAX_REGWRITES_PER_REQUEST); - upper_bound = offset + limit - 1; + wdata->offset = offset; + regs_remaining = wdata->num_regs - offset; + limit = MIN (regs_remaining, MAX_REGWRITES_PER_REQUEST); + upper_bound = offset + limit - 1; - /* determine if we can write the entire of the regs at once, or if there - * is a zero dividing things up */ - for (i = offset; i <= upper_bound; i++) - if (!wdata->regs[i].reg) { - upper_bound = i - 1; - break; - } + /* determine if we can write the entire of the regs at once, or if there + * is a zero dividing things up */ + for (i = offset; i <= upper_bound; i++) + if (!wdata->regs[i].reg) + { + upper_bound = i - 1; + break; + } - r = do_write_regv(wdata, upper_bound); - if (r < 0) { - wdata->callback(wdata->imgdev, r, wdata->user_data); - g_free(wdata); - return; - } + do_write_regv (dev, wdata, upper_bound); - wdata->offset = upper_bound + 1; + wdata->offset = upper_bound + 1; } /* write a load of registers to the device, combining multiple writes in a * single URB up to a limit. insert writes to non-existent register 0 to force * specific groups of writes to be separated by different URBs. */ -void aes_write_regv(struct fp_img_dev *dev, const struct aes_regwrite *regs, - unsigned int num_regs, aes_write_regv_cb callback, void *user_data) +void +aes_write_regv (FpImageDevice *dev, const struct aes_regwrite *regs, + unsigned int num_regs, aes_write_regv_cb callback, + void *user_data) { - struct write_regv_data *wdata; + struct write_regv_data *wdata; - fp_dbg("write %d regs", num_regs); - wdata = g_malloc(sizeof(*wdata)); - wdata->imgdev = dev; - wdata->num_regs = num_regs; - wdata->regs = regs; - wdata->offset = 0; - wdata->callback = callback; - wdata->user_data = user_data; - continue_write_regv(wdata); + fp_dbg ("write %d regs", num_regs); + wdata = g_malloc (sizeof (*wdata)); + wdata->num_regs = num_regs; + wdata->regs = regs; + wdata->offset = 0; + wdata->callback = callback; + wdata->user_data = user_data; + continue_write_regv (dev, wdata); } -unsigned char aes_get_pixel(struct fpi_frame_asmbl_ctx *ctx, - struct fpi_frame *frame, - unsigned int x, - unsigned int y) +unsigned char +aes_get_pixel (struct fpi_frame_asmbl_ctx *ctx, + struct fpi_frame *frame, + unsigned int x, + unsigned int y) { - unsigned char ret; + unsigned char ret; - ret = frame->data[x * (ctx->frame_height >> 1) + (y >> 1)]; - ret = y % 2 ? ret >> 4 : ret & 0xf; - ret *= 17; + ret = frame->data[x * (ctx->frame_height >> 1) + (y >> 1)]; + ret = y % 2 ? ret >> 4 : ret & 0xf; + ret *= 17; - return ret; + return ret; } diff --git a/libfprint/drivers/aeslib.h b/libfprint/drivers/aeslib.h index 41cbe1ee..389b3e56 100644 --- a/libfprint/drivers/aeslib.h +++ b/libfprint/drivers/aeslib.h @@ -22,24 +22,28 @@ #include -struct aes_regwrite { - unsigned char reg; - unsigned char value; +struct aes_regwrite +{ + unsigned char reg; + unsigned char value; }; struct fpi_frame; struct fpi_frame_asmbl_ctx; -typedef void (*aes_write_regv_cb)(struct fp_img_dev *dev, int result, - void *user_data); +typedef void (*aes_write_regv_cb)(FpImageDevice *dev, + GError *error, + void *user_data); -void aes_write_regv(struct fp_img_dev *dev, const struct aes_regwrite *regs, - unsigned int num_regs, aes_write_regv_cb callback, void *user_data); +void aes_write_regv (FpImageDevice *dev, + const struct aes_regwrite *regs, + unsigned int num_regs, + aes_write_regv_cb callback, + void *user_data); -unsigned char aes_get_pixel(struct fpi_frame_asmbl_ctx *ctx, - struct fpi_frame *frame, - unsigned int x, - unsigned int y); +unsigned char aes_get_pixel (struct fpi_frame_asmbl_ctx *ctx, + struct fpi_frame *frame, + unsigned int x, + unsigned int y); #endif - diff --git a/libfprint/drivers/aesx660.c b/libfprint/drivers/aesx660.c index 47da51f5..8540a068 100644 --- a/libfprint/drivers/aesx660.c +++ b/libfprint/drivers/aesx660.c @@ -27,594 +27,732 @@ #include "aeslib.h" #include "aesx660.h" -static void start_capture(struct fp_img_dev *dev); -static void complete_deactivation(struct fp_img_dev *dev); +typedef struct +{ + GByteArray *stripe_packet; + GSList *strips; + size_t strips_len; + gboolean deactivating; + struct aesX660_cmd *init_seq; + size_t init_seq_len; + unsigned int init_cmd_idx; + unsigned int init_seq_idx; +} FpiDeviceAesX660Private; -#define EP_IN (1 | LIBUSB_ENDPOINT_IN) -#define EP_OUT (2 | LIBUSB_ENDPOINT_OUT) -#define BULK_TIMEOUT 4000 -#define FRAME_HEIGHT AESX660_FRAME_HEIGHT +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (FpiDeviceAesX660, fpi_device_aes_x660, FP_TYPE_IMAGE_DEVICE); -#define ID_LEN 8 -#define INIT_LEN 4 -#define CALIBRATE_DATA_LEN 4 -#define FINGER_DET_DATA_LEN 4 +static void start_capture (FpImageDevice *dev); +static void complete_deactivation (FpImageDevice *dev); + +#define EP_IN (1 | FPI_USB_ENDPOINT_IN) +#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT) +#define BULK_TIMEOUT 4000 +#define FRAME_HEIGHT AESX660_FRAME_HEIGHT + +#define ID_LEN 8 +#define INIT_LEN 4 +#define CALIBRATE_DATA_LEN 4 +#define FINGER_DET_DATA_LEN 4 static void -aesX660_send_cmd_timeout(fpi_ssm *ssm, - struct fp_dev *_dev, - const unsigned char *cmd, - size_t cmd_len, - libusb_transfer_cb_fn callback, - int timeout) +aesX660_send_cmd_timeout (FpiSsm *ssm, + FpDevice *_dev, + const unsigned char *cmd, + size_t cmd_len, + FpiUsbTransferCallback callback, + int timeout) { - struct fp_img_dev *dev = FP_IMG_DEV(_dev); - struct libusb_transfer *transfer = fpi_usb_alloc(); - int r; + FpiUsbTransfer *transfer = fpi_usb_transfer_new (_dev); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, - (unsigned char *)cmd, cmd_len, - callback, ssm, timeout); - r = libusb_submit_transfer(transfer); - if (r < 0) { - fp_dbg("failed to submit transfer\n"); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, -ENOMEM); - } + fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT, (unsigned char *) cmd, + cmd_len, NULL); + transfer->ssm = ssm; + fpi_usb_transfer_submit (transfer, timeout, NULL, callback, NULL); + fpi_usb_transfer_unref (transfer); } static void -aesX660_send_cmd(fpi_ssm *ssm, - struct fp_dev *dev, - const unsigned char *cmd, - size_t cmd_len, - libusb_transfer_cb_fn callback) +aesX660_send_cmd (FpiSsm *ssm, + FpDevice *dev, + const unsigned char *cmd, + size_t cmd_len, + FpiUsbTransferCallback callback) { - return aesX660_send_cmd_timeout(ssm, dev, cmd, cmd_len, callback, BULK_TIMEOUT); + return aesX660_send_cmd_timeout (ssm, dev, cmd, cmd_len, callback, BULK_TIMEOUT); } static void -aesX660_read_response(fpi_ssm *ssm, - struct fp_dev *_dev, - size_t buf_len, - libusb_transfer_cb_fn callback) +aesX660_read_response (FpiSsm *ssm, + FpDevice *_dev, + gboolean short_is_error, + gboolean cancellable, + size_t buf_len, + FpiUsbTransferCallback callback) { - struct fp_img_dev *dev = FP_IMG_DEV(_dev); - struct libusb_transfer *transfer = fpi_usb_alloc(); - unsigned char *data; - int r; + FpiUsbTransfer *transfer = fpi_usb_transfer_new (_dev); + unsigned char *data; + GCancellable *cancel = NULL; - data = g_malloc(buf_len); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, - data, buf_len, - callback, ssm, BULK_TIMEOUT); - - r = libusb_submit_transfer(transfer); - if (r < 0) { - fp_dbg("Failed to submit rx transfer: %d\n", r); - g_free(data); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } + if (cancellable) + cancel = fpi_device_get_cancellable (_dev); + 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); + fpi_usb_transfer_unref (transfer); } -static void aesX660_send_cmd_cb(struct libusb_transfer *transfer) +static void +aesX660_send_cmd_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - - if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) && - (transfer->length == transfer->actual_length)) { - fpi_ssm_next_state(ssm); - } else { - fp_dbg("tx transfer status: %d, actual_len: %.4x\n", - transfer->status, transfer->actual_length); - fpi_ssm_mark_failed(ssm, -EIO); - } - libusb_free_transfer(transfer); + if (!error) + fpi_ssm_next_state (transfer->ssm); + else + fpi_ssm_mark_failed (transfer->ssm, error); } -static void aesX660_read_calibrate_data_cb(struct libusb_transfer *transfer) +static void +aesX660_read_calibrate_data_cb (FpiUsbTransfer *transfer, + FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - unsigned char *data = transfer->buffer; + unsigned char *data = transfer->buffer; - if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) || - (transfer->length != transfer->actual_length)) { - fpi_ssm_mark_failed(ssm, -EIO); - goto out; - } - /* Calibrate response was read correctly? */ - if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_CALIBRATE_RESPONSE) { - fp_dbg("Bogus calibrate response: %.2x\n", data[0]); - fpi_ssm_mark_failed(ssm, -EPROTO); - goto out; - } + if (error) + { + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } + /* Calibrate response was read correctly? */ + if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_CALIBRATE_RESPONSE) + { + fp_dbg ("Bogus calibrate response: %.2x\n", data[0]); + fpi_ssm_mark_failed (transfer->ssm, + fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Bogus calibrate response")); + return; + } - fpi_ssm_next_state(ssm); -out: - g_free(transfer->buffer); - libusb_free_transfer(transfer); + fpi_ssm_next_state (transfer->ssm); } /****** FINGER PRESENCE DETECTION ******/ enum finger_det_states { - FINGER_DET_SEND_LED_CMD, - FINGER_DET_SEND_FD_CMD, - FINGER_DET_READ_FD_DATA, - FINGER_DET_SET_IDLE, - FINGER_DET_NUM_STATES, + FINGER_DET_SEND_LED_CMD, + FINGER_DET_SEND_FD_CMD, + FINGER_DET_READ_FD_DATA, + FINGER_DET_SET_IDLE, + FINGER_DET_NUM_STATES, }; -static void finger_det_read_fd_data_cb(struct libusb_transfer *transfer) +static void +finger_det_read_fd_data_cb (FpiUsbTransfer *transfer, + FpDevice *device, gpointer user_data, + GError *error) { - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - unsigned char *data = transfer->buffer; + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); + unsigned char *data = transfer->buffer; - aesdev->fd_data_transfer = NULL; + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + { + fpi_ssm_next_state (transfer->ssm); + return; + } - if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { - fp_dbg("Cancelling transfer...\n"); - fpi_ssm_next_state(ssm); - goto out; - } + if (error) + { + fp_dbg ("Failed to read FD data\n"); + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } - if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) || - (transfer->length != transfer->actual_length)) { - fp_dbg("Failed to read FD data\n"); - fpi_ssm_mark_failed(ssm, -EIO); - goto out; - } + if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_FINGER_DET_RESPONSE) + { + fp_dbg ("Bogus FD response: %.2x\n", data[0]); + fpi_ssm_mark_failed (transfer->ssm, + fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Bogus FD response")); + return; + } - if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_FINGER_DET_RESPONSE) { - fp_dbg("Bogus FD response: %.2x\n", data[0]); - fpi_ssm_mark_failed(ssm, -EPROTO); - goto out; - } - - if (data[AESX660_FINGER_PRESENT_OFFSET] == AESX660_FINGER_PRESENT || aesdev->deactivating) { - /* Finger present or we're deactivating... */ - fpi_ssm_next_state(ssm); - } else { - fp_dbg("Wait for finger returned %.2x as result\n", - data[AESX660_FINGER_PRESENT_OFFSET]); - fpi_ssm_jump_to_state(ssm, FINGER_DET_SEND_FD_CMD); - } -out: - g_free(data); - libusb_free_transfer(transfer); + if (data[AESX660_FINGER_PRESENT_OFFSET] == AESX660_FINGER_PRESENT || priv->deactivating) + { + /* Finger present or we're deactivating... */ + fpi_ssm_next_state (transfer->ssm); + } + else + { + fp_dbg ("Wait for finger returned %.2x as result\n", + data[AESX660_FINGER_PRESENT_OFFSET]); + fpi_ssm_jump_to_state (transfer->ssm, FINGER_DET_SEND_FD_CMD); + } } -static void finger_det_set_idle_cmd_cb(struct libusb_transfer *transfer) +static void +finger_det_set_idle_cmd_cb (FpiUsbTransfer *transfer, + FpDevice *device, gpointer user_data, + GError *error) { - fpi_ssm *ssm = transfer->user_data; - - if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) && - (transfer->length == transfer->actual_length)) { - fpi_ssm_mark_completed(ssm); - } else { - fpi_ssm_mark_failed(ssm, -EIO); - } - libusb_free_transfer(transfer); + if (!error) + fpi_ssm_mark_completed (transfer->ssm); + else + fpi_ssm_mark_failed (transfer->ssm, error); } -static void finger_det_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +finger_det_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { - struct fp_img_dev *dev = user_data; - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(_dev); - int err = fpi_ssm_get_error(ssm); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (_dev); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); - fp_dbg("Finger detection completed"); - fpi_imgdev_report_finger_status(dev, TRUE); - fpi_ssm_free(ssm); + fp_dbg ("Finger detection completed"); + fpi_image_device_report_finger_status (dev, TRUE); + fpi_ssm_free (ssm); - if (aesdev->deactivating) - complete_deactivation(dev); - else if (err) - fpi_imgdev_session_error(dev, err); - else { - fpi_imgdev_report_finger_status(dev, TRUE); - start_capture(dev); - } + if (priv->deactivating) + { + complete_deactivation (dev); + if (error) + g_error_free (error); + } + else if (error) + { + fpi_image_device_session_error (dev, error); + } + else + { + fpi_image_device_report_finger_status (dev, TRUE); + start_capture (dev); + } } -static void finger_det_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) +static void +finger_det_run_state (FpiSsm *ssm, FpDevice *dev) { - switch (fpi_ssm_get_cur_state(ssm)) { - case FINGER_DET_SEND_LED_CMD: - aesX660_send_cmd(ssm, dev, led_blink_cmd, sizeof(led_blink_cmd), - aesX660_send_cmd_cb); - break; - case FINGER_DET_SEND_FD_CMD: - aesX660_send_cmd_timeout(ssm, dev, wait_for_finger_cmd, sizeof(wait_for_finger_cmd), - aesX660_send_cmd_cb, 0); - break; - case FINGER_DET_READ_FD_DATA: - aesX660_read_response(ssm, dev, FINGER_DET_DATA_LEN, finger_det_read_fd_data_cb); - break; - case FINGER_DET_SET_IDLE: - aesX660_send_cmd(ssm, dev, set_idle_cmd, sizeof(set_idle_cmd), - finger_det_set_idle_cmd_cb); - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case FINGER_DET_SEND_LED_CMD: + aesX660_send_cmd (ssm, dev, led_blink_cmd, sizeof (led_blink_cmd), + aesX660_send_cmd_cb); + break; + + case FINGER_DET_SEND_FD_CMD: + aesX660_send_cmd_timeout (ssm, dev, wait_for_finger_cmd, sizeof (wait_for_finger_cmd), + aesX660_send_cmd_cb, 0); + break; + + case FINGER_DET_READ_FD_DATA: + aesX660_read_response (ssm, dev, TRUE, TRUE, FINGER_DET_DATA_LEN, finger_det_read_fd_data_cb); + break; + + case FINGER_DET_SET_IDLE: + aesX660_send_cmd (ssm, dev, set_idle_cmd, sizeof (set_idle_cmd), + finger_det_set_idle_cmd_cb); + break; + } } -static void start_finger_detection(struct fp_img_dev *dev) +static void +start_finger_detection (FpImageDevice *dev) { - fpi_ssm *ssm; - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); + FpiSsm *ssm; - if (aesdev->deactivating) { - complete_deactivation(dev); - return; - } + if (priv->deactivating) + { + complete_deactivation (dev); + return; + } - ssm = fpi_ssm_new(FP_DEV(dev), finger_det_run_state, FINGER_DET_NUM_STATES, dev); - fpi_ssm_start(ssm, finger_det_sm_complete); + ssm = fpi_ssm_new (FP_DEVICE (dev), finger_det_run_state, + FINGER_DET_NUM_STATES); + fpi_ssm_start (ssm, finger_det_sm_complete); } /****** CAPTURE ******/ enum capture_states { - CAPTURE_SEND_LED_CMD, - CAPTURE_SEND_CAPTURE_CMD, - CAPTURE_READ_STRIPE_DATA, - CAPTURE_SET_IDLE, - CAPTURE_NUM_STATES, + CAPTURE_SEND_LED_CMD, + CAPTURE_SEND_CAPTURE_CMD, + CAPTURE_READ_STRIPE_DATA, + CAPTURE_SET_IDLE, + CAPTURE_NUM_STATES, }; /* Returns number of processed bytes */ -static int process_stripe_data(fpi_ssm *ssm, struct fp_img_dev *dev, unsigned char *data) +static int +process_stripe_data (FpiSsm *ssm, FpiDeviceAesX660 *self, + unsigned char *data, gsize length) { - struct fpi_frame *stripe; - unsigned char *stripdata; - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); + FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self); + struct fpi_frame *stripe; + unsigned char *stripdata; - stripe = g_malloc(aesdev->assembling_ctx->frame_width * FRAME_HEIGHT / 2 + sizeof(struct fpi_frame)); /* 4 bpp */ - stripdata = stripe->data; + if (length < AESX660_IMAGE_OFFSET + cls->assembling_ctx->frame_width * FRAME_HEIGHT / 2) + { + fp_warn ("Received stripe data is too short, got %zi expected %i bytes!", + length, + AESX660_IMAGE_OFFSET + cls->assembling_ctx->frame_width * FRAME_HEIGHT / 2); + return 0; + } - fp_dbg("Processing frame %.2x %.2x", data[AESX660_IMAGE_OK_OFFSET], - data[AESX660_LAST_FRAME_OFFSET]); + stripe = g_malloc (cls->assembling_ctx->frame_width * FRAME_HEIGHT / 2 + sizeof (struct fpi_frame)); /* 4 bpp */ + stripdata = stripe->data; - stripe->delta_x = (int8_t)data[AESX660_FRAME_DELTA_X_OFFSET]; - stripe->delta_y = -(int8_t)data[AESX660_FRAME_DELTA_Y_OFFSET]; - fp_dbg("Offset to previous frame: %d %d", stripe->delta_x, stripe->delta_y); + fp_dbg ("Processing frame %.2x %.2x", data[AESX660_IMAGE_OK_OFFSET], + data[AESX660_LAST_FRAME_OFFSET]); - if (data[AESX660_IMAGE_OK_OFFSET] == AESX660_IMAGE_OK) { - memcpy(stripdata, data + AESX660_IMAGE_OFFSET, aesdev->assembling_ctx->frame_width * FRAME_HEIGHT / 2); + stripe->delta_x = (int8_t) data[AESX660_FRAME_DELTA_X_OFFSET]; + stripe->delta_y = -(int8_t) data[AESX660_FRAME_DELTA_Y_OFFSET]; + fp_dbg ("Offset to previous frame: %d %d", stripe->delta_x, stripe->delta_y); - aesdev->strips = g_slist_prepend(aesdev->strips, stripe); - aesdev->strips_len++; - return (data[AESX660_LAST_FRAME_OFFSET] & AESX660_LAST_FRAME_BIT); - } + if (data[AESX660_IMAGE_OK_OFFSET] == AESX660_IMAGE_OK) + { + memcpy (stripdata, data + AESX660_IMAGE_OFFSET, cls->assembling_ctx->frame_width * FRAME_HEIGHT / 2); - g_free(stripe); - return 0; + priv->strips = g_slist_prepend (priv->strips, stripe); + priv->strips_len++; + return data[AESX660_LAST_FRAME_OFFSET] & AESX660_LAST_FRAME_BIT; + } + + g_free (stripe); + return 0; } -static void capture_set_idle_cmd_cb(struct libusb_transfer *transfer) +static void +capture_set_idle_cmd_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); + FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self); - if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) && - (transfer->length == transfer->actual_length)) { - struct fp_img *img; + if (!error) + { + FpImage *img; - aesdev->strips = g_slist_reverse(aesdev->strips); - img = fpi_assemble_frames(aesdev->assembling_ctx, aesdev->strips, aesdev->strips_len); - img->flags |= aesdev->extra_img_flags; - g_slist_foreach(aesdev->strips, (GFunc) g_free, NULL); - g_slist_free(aesdev->strips); - aesdev->strips = NULL; - aesdev->strips_len = 0; - fpi_imgdev_image_captured(dev, img); - fpi_imgdev_report_finger_status(dev, FALSE); - fpi_ssm_mark_completed(ssm); - } else { - fpi_ssm_mark_failed(ssm, -EIO); - } - libusb_free_transfer(transfer); + priv->strips = g_slist_reverse (priv->strips); + img = fpi_assemble_frames (cls->assembling_ctx, priv->strips); + g_slist_foreach (priv->strips, (GFunc) g_free, NULL); + g_slist_free (priv->strips); + priv->strips = NULL; + priv->strips_len = 0; + fpi_image_device_image_captured (dev, img); + fpi_image_device_report_finger_status (dev, FALSE); + fpi_ssm_mark_completed (transfer->ssm); + } + else + { + fpi_ssm_mark_failed (transfer->ssm, error); + } } -static void capture_read_stripe_data_cb(struct libusb_transfer *transfer) +static void +capture_read_stripe_data_cb (FpiUsbTransfer *transfer, + FpDevice *device, gpointer user_data, + GError *error) { - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - unsigned char *data = transfer->buffer; - int finger_missing = 0; - size_t copied, actual_len = transfer->actual_length; + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); + unsigned char *data = transfer->buffer; + int finger_missing = 0; + size_t actual_length = transfer->actual_length; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fpi_ssm_mark_failed(ssm, -EIO); - goto out; - } + if (error) + { + g_byte_array_set_size (priv->stripe_packet, 0); + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } - fp_dbg("Got %lu bytes of data", actual_len); - do { - copied = MIN(aesdev->buffer_max - aesdev->buffer_size, actual_len); - memcpy(aesdev->buffer + aesdev->buffer_size, - data, - copied); - actual_len -= copied; - data += copied; - aesdev->buffer_size += copied; - fp_dbg("Copied %.4lx bytes into internal buffer", - copied); - if (aesdev->buffer_size == aesdev->buffer_max) { - if (aesdev->buffer_max == AESX660_HEADER_SIZE) { - aesdev->buffer_max = aesdev->buffer[AESX660_RESPONSE_SIZE_LSB_OFFSET] + - (aesdev->buffer[AESX660_RESPONSE_SIZE_MSB_OFFSET] << 8) + AESX660_HEADER_SIZE; - fp_dbg("Got frame, type %.2x size %.4lx", - aesdev->buffer[AESX660_RESPONSE_TYPE_OFFSET], - aesdev->buffer_max); - continue; - } else { - finger_missing |= process_stripe_data(ssm, dev, aesdev->buffer); - aesdev->buffer_max = AESX660_HEADER_SIZE; - aesdev->buffer_size = 0; - } - } - } while (actual_len); + fp_dbg ("Got %lu bytes of data", actual_length); + while (actual_length) + { + gssize payload_length; + gssize still_needed_len; + gssize copy_len; - fp_dbg("finger %s\n", finger_missing ? "missing" : "present"); + still_needed_len = MAX (0, AESX660_HEADER_SIZE - (gssize) priv->stripe_packet->len); + copy_len = MIN (actual_length, still_needed_len); + g_byte_array_append (priv->stripe_packet, data, copy_len); + data += copy_len; + actual_length -= copy_len; - if (finger_missing) { - fpi_ssm_next_state(ssm); - } else { - fpi_ssm_jump_to_state(ssm, CAPTURE_READ_STRIPE_DATA); - } -out: - g_free(transfer->buffer); - libusb_free_transfer(transfer); + /* Do we have a full header? */ + if (priv->stripe_packet->len < AESX660_HEADER_SIZE) + break; + + payload_length = priv->stripe_packet->data[AESX660_RESPONSE_SIZE_LSB_OFFSET] + + (priv->stripe_packet->data[AESX660_RESPONSE_SIZE_MSB_OFFSET] << 8); + fp_dbg ("Got frame, type %.2x payload of size %.4lx", + priv->stripe_packet->data[AESX660_RESPONSE_TYPE_OFFSET], + payload_length); + + still_needed_len = MAX (0, AESX660_HEADER_SIZE + payload_length - (gssize) priv->stripe_packet->len); + copy_len = MIN (actual_length, still_needed_len); + g_byte_array_append (priv->stripe_packet, data, copy_len); + data += copy_len; + actual_length -= copy_len; + + /* Do we have a full packet including the payload? */ + if (priv->stripe_packet->len < payload_length + AESX660_HEADER_SIZE) + break; + + finger_missing |= process_stripe_data (transfer->ssm, + self, + priv->stripe_packet->data, + priv->stripe_packet->len); + + g_byte_array_set_size (priv->stripe_packet, 0); + } + + fp_dbg ("finger %s\n", finger_missing ? "missing" : "present"); + + if (finger_missing) + fpi_ssm_next_state (transfer->ssm); + else + fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_READ_STRIPE_DATA); } -static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +capture_run_state (FpiSsm *ssm, FpDevice *_dev) { - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(_dev); + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (_dev); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); + FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self); - switch (fpi_ssm_get_cur_state(ssm)) { - case CAPTURE_SEND_LED_CMD: - aesX660_send_cmd(ssm, _dev, led_solid_cmd, sizeof(led_solid_cmd), - aesX660_send_cmd_cb); - break; - case CAPTURE_SEND_CAPTURE_CMD: - aesdev->buffer_size = 0; - aesdev->buffer_max = AESX660_HEADER_SIZE; - aesX660_send_cmd(ssm, _dev, aesdev->start_imaging_cmd, - aesdev->start_imaging_cmd_len, - aesX660_send_cmd_cb); - break; - case CAPTURE_READ_STRIPE_DATA: - aesX660_read_response(ssm, _dev, AESX660_BULK_TRANSFER_SIZE, - capture_read_stripe_data_cb); - break; - case CAPTURE_SET_IDLE: - fp_dbg("Got %lu frames\n", aesdev->strips_len); - aesX660_send_cmd(ssm, _dev, set_idle_cmd, sizeof(set_idle_cmd), - capture_set_idle_cmd_cb); - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case CAPTURE_SEND_LED_CMD: + aesX660_send_cmd (ssm, _dev, led_solid_cmd, sizeof (led_solid_cmd), + aesX660_send_cmd_cb); + break; + + case CAPTURE_SEND_CAPTURE_CMD: + g_byte_array_set_size (priv->stripe_packet, 0); + aesX660_send_cmd (ssm, _dev, cls->start_imaging_cmd, + cls->start_imaging_cmd_len, + aesX660_send_cmd_cb); + break; + + case CAPTURE_READ_STRIPE_DATA: + aesX660_read_response (ssm, _dev, FALSE, FALSE, AESX660_BULK_TRANSFER_SIZE, + capture_read_stripe_data_cb); + break; + + case CAPTURE_SET_IDLE: + fp_dbg ("Got %lu frames\n", priv->strips_len); + aesX660_send_cmd (ssm, _dev, set_idle_cmd, sizeof (set_idle_cmd), + capture_set_idle_cmd_cb); + break; + } } -static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +capture_sm_complete (FpiSsm *ssm, FpDevice *device, GError *error) { - struct fp_img_dev *dev = user_data; - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(_dev); - int err = fpi_ssm_get_error(ssm); + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); - fp_dbg("Capture completed"); - fpi_ssm_free(ssm); + fp_dbg ("Capture completed"); + fpi_ssm_free (ssm); - if (aesdev->deactivating) - complete_deactivation(dev); - else if (err) - fpi_imgdev_session_error(dev, err); - else - start_finger_detection(dev); + if (priv->deactivating) + { + complete_deactivation (FP_IMAGE_DEVICE (device)); + if (error) + g_error_free (error); + } + else if (error) + { + fpi_image_device_session_error (FP_IMAGE_DEVICE (device), error); + } + else + { + start_finger_detection (FP_IMAGE_DEVICE (device)); + } } -static void start_capture(struct fp_img_dev *dev) +static void +start_capture (FpImageDevice *dev) { - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_ssm *ssm; + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); + FpiSsm *ssm; - if (aesdev->deactivating) { - complete_deactivation(dev); - return; - } + if (priv->deactivating) + { + complete_deactivation (dev); + return; + } - ssm = fpi_ssm_new(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev); - G_DEBUG_HERE(); - fpi_ssm_start(ssm, capture_sm_complete); + ssm = fpi_ssm_new (FP_DEVICE (dev), capture_run_state, CAPTURE_NUM_STATES); + G_DEBUG_HERE (); + fpi_ssm_start (ssm, capture_sm_complete); } /****** INITIALIZATION/DEINITIALIZATION ******/ enum activate_states { - ACTIVATE_SET_IDLE, - ACTIVATE_SEND_READ_ID_CMD, - ACTIVATE_READ_ID, - ACTIVATE_SEND_CALIBRATE_CMD, - ACTIVATE_READ_CALIBRATE_DATA, - ACTIVATE_SEND_INIT_CMD, - ACTIVATE_READ_INIT_RESPONSE, - ACTIVATE_NUM_STATES, + ACTIVATE_SET_IDLE, + ACTIVATE_SEND_READ_ID_CMD, + ACTIVATE_READ_ID, + ACTIVATE_SEND_CALIBRATE_CMD, + ACTIVATE_READ_CALIBRATE_DATA, + ACTIVATE_SEND_INIT_CMD, + ACTIVATE_READ_INIT_RESPONSE, + ACTIVATE_NUM_STATES, }; -static void activate_read_id_cb(struct libusb_transfer *transfer) +static void +activate_read_id_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - unsigned char *data = transfer->buffer; + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); + FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self); + unsigned char *data = transfer->buffer; - if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) || - (transfer->length != transfer->actual_length)) { - fp_dbg("read_id cmd failed\n"); - fpi_ssm_mark_failed(ssm, -EIO); - goto out; - } - /* ID was read correctly */ - if (data[0] == 0x07) { - fp_dbg("Sensor device id: %.2x%2x, bcdDevice: %.2x.%.2x, init status: %.2x\n", - data[4], data[3], data[5], data[6], data[7]); - } else { - fp_dbg("Bogus read ID response: %.2x\n", data[AESX660_RESPONSE_TYPE_OFFSET]); - fpi_ssm_mark_failed(ssm, -EPROTO); - goto out; - } + if (error) + { + fp_dbg ("read_id cmd failed\n"); + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } + /* ID was read correctly */ + if (data[0] == 0x07) + { + fp_dbg ("Sensor device id: %.2x%2x, bcdDevice: %.2x.%.2x, init status: %.2x\n", + data[4], data[3], data[5], data[6], data[7]); + } + else + { + fp_dbg ("Bogus read ID response: %.2x\n", data[AESX660_RESPONSE_TYPE_OFFSET]); + fpi_ssm_mark_failed (transfer->ssm, + fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Bogus read ID response")); + return; + } - switch (aesdev->init_seq_idx) { - case 0: - aesdev->init_seq = aesdev->init_seqs[0]; - aesdev->init_seq_len = aesdev->init_seqs_len[0]; - aesdev->init_seq_idx = 1; - aesdev->init_cmd_idx = 0; - /* Do calibration only after 1st init sequence */ - fpi_ssm_jump_to_state(ssm, ACTIVATE_SEND_INIT_CMD); - break; - case 1: - aesdev->init_seq = aesdev->init_seqs[1]; - aesdev->init_seq_len = aesdev->init_seqs_len[1]; - aesdev->init_seq_idx = 2; - aesdev->init_cmd_idx = 0; - fpi_ssm_next_state(ssm); - break; - default: - fp_dbg("Failed to init device! init status: %.2x\n", data[7]); - fpi_ssm_mark_failed(ssm, -EPROTO); - break; + switch (priv->init_seq_idx) + { + case 0: + priv->init_seq = cls->init_seqs[0]; + priv->init_seq_len = cls->init_seqs_len[0]; + priv->init_seq_idx = 1; + priv->init_cmd_idx = 0; + /* Do calibration only after 1st init sequence */ + fpi_ssm_jump_to_state (transfer->ssm, ACTIVATE_SEND_INIT_CMD); + break; - } + case 1: + priv->init_seq = cls->init_seqs[1]; + priv->init_seq_len = cls->init_seqs_len[1]; + priv->init_seq_idx = 2; + priv->init_cmd_idx = 0; + fpi_ssm_next_state (transfer->ssm); + break; -out: - g_free(transfer->buffer); - libusb_free_transfer(transfer); + default: + fp_dbg ("Failed to init device! init status: %.2x\n", data[7]); + fpi_ssm_mark_failed (transfer->ssm, + fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Failed to init device")); + break; + } } -static void activate_read_init_cb(struct libusb_transfer *transfer) +static void +activate_read_init_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - unsigned char *data = transfer->buffer; + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); + unsigned char *data = transfer->buffer; - fp_dbg("read_init_cb\n"); + fp_dbg ("read_init_cb\n"); - if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) || - (transfer->length != transfer->actual_length)) { - fp_dbg("read_init transfer status: %d, actual_len: %d\n", transfer->status, transfer->actual_length); - fpi_ssm_mark_failed(ssm, -EIO); - goto out; - } - /* ID was read correctly */ - if (data[0] != 0x42 || data[3] != 0x01) { - fp_dbg("Bogus read init response: %.2x %.2x\n", data[0], - data[3]); - fpi_ssm_mark_failed(ssm, -EPROTO); - goto out; - } - aesdev->init_cmd_idx++; - if (aesdev->init_cmd_idx == aesdev->init_seq_len) { - if (aesdev->init_seq_idx < 2) - fpi_ssm_jump_to_state(ssm, ACTIVATE_SEND_READ_ID_CMD); - else - fpi_ssm_mark_completed(ssm); - goto out; - } + if (error) + { + fp_dbg ("read_init transfer status: %s, actual_len: %d\n", error->message, + (gint) transfer->actual_length); + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } + /* ID was read correctly */ + if (data[0] != 0x42 || data[3] != 0x01) + { + fp_dbg ("Bogus read init response: %.2x %.2x\n", data[0], + data[3]); + fpi_ssm_mark_failed (transfer->ssm, + fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Bogus read init response")); + return; + } + priv->init_cmd_idx++; + if (priv->init_cmd_idx == priv->init_seq_len) + { + if (priv->init_seq_idx < 2) + fpi_ssm_jump_to_state (transfer->ssm, + ACTIVATE_SEND_READ_ID_CMD); + else + fpi_ssm_mark_completed (transfer->ssm); + return; + } - fpi_ssm_jump_to_state(ssm, ACTIVATE_SEND_INIT_CMD); -out: - g_free(transfer->buffer); - libusb_free_transfer(transfer); + fpi_ssm_jump_to_state (transfer->ssm, ACTIVATE_SEND_INIT_CMD); } -static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +activate_run_state (FpiSsm *ssm, FpDevice *_dev) { - struct fp_img_dev *dev = user_data; - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (_dev); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); - switch (fpi_ssm_get_cur_state(ssm)) { - case ACTIVATE_SET_IDLE: - aesdev->init_seq_idx = 0; - fp_dbg("Activate: set idle\n"); - aesX660_send_cmd(ssm, _dev, set_idle_cmd, sizeof(set_idle_cmd), - aesX660_send_cmd_cb); - break; - case ACTIVATE_SEND_READ_ID_CMD: - fp_dbg("Activate: read ID\n"); - aesX660_send_cmd(ssm, _dev, read_id_cmd, sizeof(read_id_cmd), - aesX660_send_cmd_cb); - break; - case ACTIVATE_READ_ID: - aesX660_read_response(ssm, _dev, ID_LEN, activate_read_id_cb); - break; - case ACTIVATE_SEND_INIT_CMD: - fp_dbg("Activate: send init seq #%d cmd #%d\n", - aesdev->init_seq_idx, - aesdev->init_cmd_idx); - aesX660_send_cmd(ssm, _dev, - aesdev->init_seq[aesdev->init_cmd_idx].cmd, - aesdev->init_seq[aesdev->init_cmd_idx].len, - aesX660_send_cmd_cb); - break; - case ACTIVATE_READ_INIT_RESPONSE: - fp_dbg("Activate: read init response\n"); - aesX660_read_response(ssm, _dev, INIT_LEN, activate_read_init_cb); - break; - case ACTIVATE_SEND_CALIBRATE_CMD: - aesX660_send_cmd(ssm, _dev, calibrate_cmd, sizeof(calibrate_cmd), - aesX660_send_cmd_cb); - break; - case ACTIVATE_READ_CALIBRATE_DATA: - aesX660_read_response(ssm, _dev, CALIBRATE_DATA_LEN, aesX660_read_calibrate_data_cb); - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case ACTIVATE_SET_IDLE: + priv->init_seq_idx = 0; + fp_dbg ("Activate: set idle\n"); + aesX660_send_cmd (ssm, _dev, set_idle_cmd, sizeof (set_idle_cmd), + aesX660_send_cmd_cb); + break; + + case ACTIVATE_SEND_READ_ID_CMD: + fp_dbg ("Activate: read ID\n"); + aesX660_send_cmd (ssm, _dev, read_id_cmd, sizeof (read_id_cmd), + aesX660_send_cmd_cb); + break; + + case ACTIVATE_READ_ID: + aesX660_read_response (ssm, _dev, TRUE, FALSE, ID_LEN, activate_read_id_cb); + break; + + case ACTIVATE_SEND_INIT_CMD: + fp_dbg ("Activate: send init seq #%d cmd #%d\n", + priv->init_seq_idx, + priv->init_cmd_idx); + aesX660_send_cmd (ssm, _dev, + priv->init_seq[priv->init_cmd_idx].cmd, + priv->init_seq[priv->init_cmd_idx].len, + aesX660_send_cmd_cb); + break; + + case ACTIVATE_READ_INIT_RESPONSE: + fp_dbg ("Activate: read init response\n"); + aesX660_read_response (ssm, _dev, TRUE, FALSE, INIT_LEN, activate_read_init_cb); + break; + + case ACTIVATE_SEND_CALIBRATE_CMD: + aesX660_send_cmd (ssm, _dev, calibrate_cmd, sizeof (calibrate_cmd), + aesX660_send_cmd_cb); + break; + + case ACTIVATE_READ_CALIBRATE_DATA: + aesX660_read_response (ssm, _dev, TRUE, FALSE, CALIBRATE_DATA_LEN, aesX660_read_calibrate_data_cb); + break; + } } -static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { - struct fp_img_dev *dev = user_data; - int err = fpi_ssm_get_error(ssm); - fp_dbg("status %d", err); - fpi_imgdev_activate_complete(dev, err); - fpi_ssm_free(ssm); + fpi_image_device_activate_complete (FP_IMAGE_DEVICE (_dev), error); + fpi_ssm_free (ssm); - if (!err) - start_finger_detection(dev); + if (!error) + start_finger_detection (FP_IMAGE_DEVICE (_dev)); } -int aesX660_dev_activate(struct fp_img_dev *dev) +static void +aesX660_dev_activate (FpImageDevice *dev) { - fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, - ACTIVATE_NUM_STATES, dev); - fpi_ssm_start(ssm, activate_sm_complete); - return 0; + FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), activate_run_state, + ACTIVATE_NUM_STATES); + + fpi_ssm_start (ssm, activate_sm_complete); } -void aesX660_dev_deactivate(struct fp_img_dev *dev) +static void +aesX660_dev_deactivate (FpImageDevice *dev) { - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); - if (aesdev->fd_data_transfer) - libusb_cancel_transfer(aesdev->fd_data_transfer); - - aesdev->deactivating = TRUE; + priv->deactivating = TRUE; } -static void complete_deactivation(struct fp_img_dev *dev) +static void +aesX660_dev_init (FpImageDevice *dev) { - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); - G_DEBUG_HERE(); + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); + GError *error = NULL; - aesdev->deactivating = FALSE; - g_slist_free(aesdev->strips); - aesdev->strips = NULL; - aesdev->strips_len = 0; - fpi_imgdev_deactivate_complete(dev); + g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error); + + priv->stripe_packet = g_byte_array_new (); + + fpi_image_device_open_complete (dev, error); +} + +static void +aesX660_dev_deinit (FpImageDevice *dev) +{ + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); + GError *error = NULL; + + g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), + 0, 0, &error); + + g_clear_pointer (&priv->stripe_packet, g_byte_array_unref); + + fpi_image_device_close_complete (dev, error); +} + + +static void +complete_deactivation (FpImageDevice *dev) +{ + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); + + G_DEBUG_HERE (); + + priv->deactivating = FALSE; + g_slist_free (priv->strips); + priv->strips = NULL; + priv->strips_len = 0; + fpi_image_device_deactivate_complete (dev, NULL); +} + +static void +fpi_device_aes_x660_init (FpiDeviceAesX660 *self) +{ +} + +static void +fpi_device_aes_x660_class_init (FpiDeviceAesX660Class *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); + + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->scan_type = FP_SCAN_TYPE_SWIPE; + + img_class->img_open = aesX660_dev_init; + img_class->img_close = aesX660_dev_deinit; + img_class->activate = aesX660_dev_activate; + img_class->deactivate = aesX660_dev_deactivate; + + /* Everything else is set by the subclasses. */ } diff --git a/libfprint/drivers/aesx660.h b/libfprint/drivers/aesx660.h index 8d8f3501..baf36719 100644 --- a/libfprint/drivers/aesx660.h +++ b/libfprint/drivers/aesx660.h @@ -17,8 +17,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef __AESX660_H -#define __AESX660_H +#pragma once #define AESX660_HEADER_SIZE 3 #define AESX660_RESPONSE_TYPE_OFFSET 0x00 @@ -43,80 +42,70 @@ #define AESX660_FRAME_HEIGHT 8 -struct aesX660_dev { - GSList *strips; - size_t strips_len; - gboolean deactivating; - struct aesX660_cmd *init_seq; - size_t init_seq_len; - unsigned int init_cmd_idx; - unsigned int init_seq_idx; - struct libusb_transfer *fd_data_transfer; - unsigned char *buffer; - size_t buffer_size; - size_t buffer_max; +G_DECLARE_DERIVABLE_TYPE (FpiDeviceAesX660, fpi_device_aes_x660, FPI, + DEVICE_AES_X660, FpImageDevice) - /* Device-specific stuff */ - struct aesX660_cmd *init_seqs[2]; - size_t init_seqs_len[2]; - unsigned char *start_imaging_cmd; - size_t start_imaging_cmd_len; - struct fpi_frame_asmbl_ctx *assembling_ctx; - uint16_t extra_img_flags; +#define FPI_TYPE_DEVICE_AES_X660 (fpi_device_aes_x660_get_type ()) + +struct _FpiDeviceAesX660Class +{ + FpImageDeviceClass parent; + + struct aesX660_cmd *init_seqs[2]; + gsize init_seqs_len[2]; + guint8 *start_imaging_cmd; + gsize start_imaging_cmd_len; + struct fpi_frame_asmbl_ctx *assembling_ctx; }; -struct aesX660_cmd { - const unsigned char *cmd; - size_t len; +struct aesX660_cmd +{ + const guint8 *cmd; + gsize len; }; /* 0x77 cmd seems to control LED, this sequence * makes LED blink */ -static const unsigned char led_blink_cmd[] = { -0x77, 0x18, 0x00, -0x00, 0x3f, 0x00, 0xff, 0x00, -0x01, 0x01, 0x00, 0x00, 0x00, 0xf3, 0x01, 0x00, -0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0xf3, -0x01, 0x00, 0x7f +static const guint8 led_blink_cmd[] = { + 0x77, 0x18, 0x00, + 0x00, 0x3f, 0x00, 0xff, 0x00, + 0x01, 0x01, 0x00, 0x00, 0x00, 0xf3, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0xf3, + 0x01, 0x00, 0x7f }; /* This sequence makes LED light solid */ -static const unsigned char led_solid_cmd[] = { -0x77, 0x18, 0x00, 0x00, 0x3f, 0x00, 0xff, 0x00, -0x01, 0x01, 0x00, 0x00, 0x00, 0xe7, 0x03, 0x00, -0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7f +static const guint8 led_solid_cmd[] = { + 0x77, 0x18, 0x00, 0x00, 0x3f, 0x00, 0xff, 0x00, + 0x01, 0x01, 0x00, 0x00, 0x00, 0xe7, 0x03, 0x00, + 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7f }; -static const unsigned char wait_for_finger_cmd[] = { -0x20, -0x40, 0x04, 0x00, 0x02, 0x1e, 0x00, 0x32 +static const guint8 wait_for_finger_cmd[] = { + 0x20, + 0x40, 0x04, 0x00, 0x02, 0x1e, 0x00, 0x32 }; /* 0x40 cmd response * -static const unsigned char pkt1371[] = { -0x40, 0x01, 0x00, 0x01 -}; -*/ + static const guint8 pkt1371[] = { + 0x40, 0x01, 0x00, 0x01 + }; + */ -static const unsigned char set_idle_cmd[] = { - 0x0d, /* Reset or "set idle"? */ +static const guint8 set_idle_cmd[] = { + 0x0d, /* Reset or "set idle"? */ }; -static const unsigned char read_id_cmd[] = { - 0x44, 0x02, 0x00, 0x08, 0x00, /* Max transfer size is 8 */ - 0x07, /* Read ID? */ +static const guint8 read_id_cmd[] = { + 0x44, 0x02, 0x00, 0x08, 0x00, /* Max transfer size is 8 */ + 0x07, /* Read ID? */ }; -static const unsigned char calibrate_cmd[] = { - 0x44, 0x02, 0x00, 0x04, 0x00, - 0x06, +static const guint8 calibrate_cmd[] = { + 0x44, 0x02, 0x00, 0x04, 0x00, + 0x06, }; - -int aesX660_dev_activate(struct fp_img_dev *dev); -void aesX660_dev_deactivate(struct fp_img_dev *dev); - -#endif diff --git a/libfprint/drivers/driver_ids.h b/libfprint/drivers/driver_ids.h index 012a3d06..4270842d 100644 --- a/libfprint/drivers/driver_ids.h +++ b/libfprint/drivers/driver_ids.h @@ -21,27 +21,27 @@ #define __DRIVER_IDS enum { - UPEKTS_ID = 1, - URU4000_ID = 2, - AES4000_ID = 3, - AES2501_ID = 4, - UPEKTC_ID = 5, - AES1610_ID = 6, - /* FDU2000_ID = 7, */ - VCOM5S_ID = 8, - UPEKSONLY_ID = 9, - VFS101_ID = 10, - VFS301_ID = 11, - AES2550_ID = 12, - /* UPEKE2_ID = 13 */ - AES1660_ID = 14, - AES2660_ID = 15, - AES3500_ID = 16, - UPEKTC_IMG_ID = 17, - ETES603_ID = 18, - VFS5011_ID = 19, - VFS0050_ID = 20, - ELAN_ID = 21, + UPEKTS_ID = 1, + URU4000_ID = 2, + AES4000_ID = 3, + AES2501_ID = 4, + UPEKTC_ID = 5, + AES1610_ID = 6, + /* FDU2000_ID = 7, */ + VCOM5S_ID = 8, + UPEKSONLY_ID = 9, + VFS101_ID = 10, + VFS301_ID = 11, + AES2550_ID = 12, + /* UPEKE2_ID = 13 */ + AES1660_ID = 14, + AES2660_ID = 15, + AES3500_ID = 16, + UPEKTC_IMG_ID = 17, + ETES603_ID = 18, + VFS5011_ID = 19, + VFS0050_ID = 20, + ELAN_ID = 21, }; #endif diff --git a/libfprint/drivers/elan.c b/libfprint/drivers/elan.c index e9dad43e..b417a419 100644 --- a/libfprint/drivers/elan.c +++ b/libfprint/drivers/elan.c @@ -41,125 +41,128 @@ #include "drivers_api.h" #include "elan.h" -#define dbg_buf(buf, len) \ - if (len == 1) \ - fp_dbg("%02x", buf[0]); \ - else if (len == 2) \ - fp_dbg("%04x", buf[0] << 8 | buf[1]); \ - else if (len > 2) \ - fp_dbg("%04x... (%d bytes)", buf[0] << 8 | buf[1], len) - -unsigned char elan_get_pixel(struct fpi_frame_asmbl_ctx *ctx, - struct fpi_frame *frame, unsigned int x, - unsigned int y) +unsigned char +elan_get_pixel (struct fpi_frame_asmbl_ctx *ctx, + struct fpi_frame *frame, unsigned int x, + unsigned int y) { - return frame->data[x + y * ctx->frame_width]; + return frame->data[x + y * ctx->frame_width]; } static struct fpi_frame_asmbl_ctx assembling_ctx = { - .frame_width = 0, - .frame_height = 0, - .image_width = 0, - .get_pixel = elan_get_pixel, + .frame_width = 0, + .frame_height = 0, + .image_width = 0, + .get_pixel = elan_get_pixel, }; -struct elan_dev { - /* device config */ - unsigned short dev_type; - unsigned short fw_ver; - void (*process_frame) (unsigned short *raw_frame, GSList ** frames); - /* end device config */ +struct _FpiDeviceElan +{ + FpImageDevice parent; - /* commands */ - const struct elan_cmd *cmd; - int cmd_timeout; - fpi_usb_transfer *cur_transfer; - /* end commands */ + /* device config */ + unsigned short dev_type; + unsigned short fw_ver; + void (*process_frame) (unsigned short *raw_frame, + GSList ** frames); + /* end device config */ - /* state */ - enum fp_imgdev_state dev_state; - enum fp_imgdev_state 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 */ + /* commands */ + const struct elan_cmd *cmd; + int cmd_timeout; + /* end commands */ + + /* state */ + gboolean deactivating; + FpImageDeviceState dev_state; + FpImageDeviceState 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); -int cmp_short(const void *a, const void *b) +int +cmp_short (const void *a, const void *b) { - return (int)(*(short *)a - *(short *)b); + return (int) (*(short *) a - *(short *) b); } -static void elan_dev_reset(struct elan_dev *elandev) +static void +elan_dev_reset_state (FpiDeviceElan *elandev) { - G_DEBUG_HERE(); + G_DEBUG_HERE (); - BUG_ON(elandev->cur_transfer); + elandev->cmd = NULL; + elandev->cmd_timeout = ELAN_CMD_TIMEOUT; - elandev->cmd = NULL; - elandev->cmd_timeout = ELAN_CMD_TIMEOUT; + elandev->calib_status = 0; - elandev->calib_status = 0; + g_free (elandev->last_read); + elandev->last_read = NULL; - g_free(elandev->last_read); - elandev->last_read = NULL; - - g_slist_free_full(elandev->frames, g_free); - elandev->frames = NULL; - elandev->num_frames = 0; + g_slist_free_full (elandev->frames, g_free); + elandev->frames = NULL; + elandev->num_frames = 0; } -static void elan_save_frame(struct elan_dev *elandev, unsigned short *frame) +static void +elan_save_frame (FpiDeviceElan *self, unsigned short *frame) { - G_DEBUG_HERE(); + G_DEBUG_HERE (); - /* so far 3 types of readers by sensor dimensions and orientation have been - * seen in the wild: - * 1. 144x64. Raw images are in portrait orientation while readers themselves - * are placed (e.g. built into a touchpad) in landscape orientation. These - * need to be rotated before assembling. - * 2. 96x96 rotated. Like the first type but square. Likewise, need to be - * rotated before assembling. - * 3. 96x96 normal. Square and need NOT be rotated. So far there's only been - * 1 report of a 0c03 of this type. Hopefully this type can be identified - * by device id (and manufacturers don't just install the readers as they - * please). - * we also discard stripes of 'frame_margin' from bottom and top because - * assembling works bad for tall frames */ + /* so far 3 types of readers by sensor dimensions and orientation have been + * seen in the wild: + * 1. 144x64. Raw images are in portrait orientation while readers themselves + * are placed (e.g. built into a touchpad) in landscape orientation. These + * need to be rotated before assembling. + * 2. 96x96 rotated. Like the first type but square. Likewise, need to be + * rotated before assembling. + * 3. 96x96 normal. Square and need NOT be rotated. So far there's only been + * 1 report of a 0c03 of this type. Hopefully this type can be identified + * by device id (and manufacturers don't just install the readers as they + * please). + * we also discard stripes of 'frame_margin' from bottom and top because + * assembling works bad for tall frames */ - unsigned char frame_width = elandev->frame_width; - unsigned char frame_height = elandev->frame_height; - unsigned char raw_height = elandev->raw_frame_height; - unsigned char frame_margin = (raw_height - elandev->frame_height) / 2; - int frame_idx, raw_idx; + unsigned char frame_width = self->frame_width; + unsigned char frame_height = self->frame_height; + unsigned char raw_height = self->raw_frame_height; + unsigned char frame_margin = (raw_height - self->frame_height) / 2; + int frame_idx, raw_idx; - for (int y = 0; y < frame_height; y++) - for (int x = 0; x < frame_width; x++) { - if (elandev->dev_type & ELAN_NOT_ROTATED) - raw_idx = x + (y + frame_margin) * frame_width; - else - raw_idx = frame_margin + y + x * raw_height; - frame_idx = x + y * frame_width; - frame[frame_idx] = - ((unsigned short *)elandev->last_read)[raw_idx]; - } + for (int y = 0; y < frame_height; y++) + for (int x = 0; x < frame_width; x++) + { + if (self->dev_type & ELAN_NOT_ROTATED) + raw_idx = x + (y + frame_margin) * frame_width; + else + raw_idx = frame_margin + y + x * raw_height; + frame_idx = x + y * frame_width; + frame[frame_idx] = + ((unsigned short *) self->last_read)[raw_idx]; + } } -static void elan_save_background(struct elan_dev *elandev) +static void +elan_save_background (FpiDeviceElan *elandev) { - G_DEBUG_HERE(); + G_DEBUG_HERE (); - g_free(elandev->background); - elandev->background = - g_malloc(elandev->frame_width * elandev->frame_height * - sizeof(short)); - elan_save_frame(elandev, elandev->background); + g_free (elandev->background); + elandev->background = + g_malloc (elandev->frame_width * elandev->frame_height * + sizeof (short)); + elan_save_frame (elandev, elandev->background); } /* save a frame as part of the fingerprint image @@ -197,792 +200,897 @@ static void elan_save_background(struct elan_dev *elandev) * \ * ======== 0 \___> ======== 0 */ -static int elan_save_img_frame(struct elan_dev *elandev) +static int +elan_save_img_frame (FpiDeviceElan *elandev) { - G_DEBUG_HERE(); + G_DEBUG_HERE (); - unsigned int frame_size = elandev->frame_width * elandev->frame_height; - unsigned short *frame = g_malloc(frame_size * sizeof(short)); - elan_save_frame(elandev, frame); - unsigned int sum = 0; + unsigned int frame_size = elandev->frame_width * elandev->frame_height; + unsigned short *frame = g_malloc (frame_size * sizeof (short)); + elan_save_frame (elandev, frame); + unsigned int sum = 0; - for (int i = 0; i < frame_size; i++) { - if (elandev->background[i] > frame[i]) - frame[i] = 0; - else - frame[i] -= elandev->background[i]; - sum += frame[i]; - } + for (int i = 0; i < frame_size; i++) + { + if (elandev->background[i] > frame[i]) + frame[i] = 0; + else + frame[i] -= elandev->background[i]; + sum += frame[i]; + } - if (sum == 0) { - fp_dbg - ("frame darker than background; finger present during calibration?"); - return -1; - } + if (sum == 0) + { + fp_dbg + ("frame darker than background; finger present during calibration?"); + return -1; + } - elandev->frames = g_slist_prepend(elandev->frames, frame); - elandev->num_frames += 1; - return 0; -} - -static void elan_process_frame_linear(unsigned short *raw_frame, - GSList ** frames) -{ - unsigned int frame_size = - assembling_ctx.frame_width * assembling_ctx.frame_height; - struct fpi_frame *frame = - g_malloc(frame_size + sizeof(struct fpi_frame)); - - G_DEBUG_HERE(); - - unsigned short min = 0xffff, max = 0; - for (int i = 0; i < frame_size; i++) { - if (raw_frame[i] < min) - min = raw_frame[i]; - if (raw_frame[i] > max) - max = raw_frame[i]; - } - - g_assert(max != min); - - unsigned short px; - for (int i = 0; i < frame_size; i++) { - px = raw_frame[i]; - px = (px - min) * 0xff / (max - min); - frame->data[i] = (unsigned char)px; - } - - *frames = g_slist_prepend(*frames, frame); -} - -static void elan_process_frame_thirds(unsigned short *raw_frame, - GSList ** frames) -{ - G_DEBUG_HERE(); - - unsigned int frame_size = - assembling_ctx.frame_width * assembling_ctx.frame_height; - struct fpi_frame *frame = - g_malloc(frame_size + sizeof(struct fpi_frame)); - - unsigned short lvl0, lvl1, lvl2, lvl3; - unsigned short *sorted = g_malloc(frame_size * sizeof(short)); - memcpy(sorted, raw_frame, frame_size * sizeof(short)); - qsort(sorted, frame_size, sizeof(short), cmp_short); - lvl0 = sorted[0]; - lvl1 = sorted[frame_size * 3 / 10]; - lvl2 = sorted[frame_size * 65 / 100]; - lvl3 = sorted[frame_size - 1]; - g_free(sorted); - - unsigned short px; - for (int i = 0; i < frame_size; i++) { - px = raw_frame[i]; - if (lvl0 <= px && px < lvl1) - px = (px - lvl0) * 99 / (lvl1 - lvl0); - else if (lvl1 <= px && px < lvl2) - px = 99 + ((px - lvl1) * 56 / (lvl2 - lvl1)); - else // (lvl2 <= px && px <= lvl3) - px = 155 + ((px - lvl2) * 100 / (lvl3 - lvl2)); - frame->data[i] = (unsigned char)px; - } - - *frames = g_slist_prepend(*frames, frame); -} - -static void elan_submit_image(struct fp_img_dev *dev) -{ - struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); - int num_frames; - GSList *raw_frames; - GSList *frames = NULL; - struct fp_img *img; - - G_DEBUG_HERE(); - - num_frames = elandev->num_frames - ELAN_SKIP_LAST_FRAMES; - raw_frames = g_slist_nth(elandev->frames, ELAN_SKIP_LAST_FRAMES); - - assembling_ctx.frame_width = elandev->frame_width; - assembling_ctx.frame_height = elandev->frame_height; - assembling_ctx.image_width = elandev->frame_width * 3 / 2; - g_slist_foreach(raw_frames, (GFunc) elandev->process_frame, &frames); - fpi_do_movement_estimation(&assembling_ctx, frames, num_frames); - img = fpi_assemble_frames(&assembling_ctx, frames, num_frames); - - img->flags |= FP_IMG_PARTIAL; - fpi_imgdev_image_captured(dev, img); -} - -static void elan_cmd_done(fpi_ssm *ssm) -{ - G_DEBUG_HERE(); - fpi_ssm_next_state(ssm); -} - -static void elan_cmd_cb(struct libusb_transfer *transfer, - struct fp_dev *_dev, - fpi_ssm *ssm, - void *user_data) -{ - struct fp_img_dev *dev; - struct elan_dev *elandev; - - G_DEBUG_HERE(); - - if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { - fp_dbg("transfer cancelled"); - return; - } - - dev = FP_IMG_DEV(_dev); - elandev = FP_INSTANCE_DATA(_dev); - elandev->cur_transfer = NULL; - - switch (transfer->status) { - case LIBUSB_TRANSFER_COMPLETED: - if (transfer->length != transfer->actual_length) { - fp_dbg("transfer length error: expected %d, got %d", - transfer->length, transfer->actual_length); - elan_dev_reset(elandev); - fpi_ssm_mark_failed(ssm, -EPROTO); - } else if (transfer->endpoint & LIBUSB_ENDPOINT_IN) { - /* just finished receiving */ - elandev->last_read = g_memdup(transfer->buffer, transfer->actual_length); - dbg_buf(transfer->buffer, transfer->actual_length); - elan_cmd_done(ssm); - } else { - /* just finished sending */ - G_DEBUG_HERE(); - elan_cmd_read(ssm, dev); - } - break; - case LIBUSB_TRANSFER_TIMED_OUT: - fp_dbg("transfer timed out"); - fpi_ssm_mark_failed(ssm, -ETIMEDOUT); - break; - default: - fp_dbg("transfer failed: %d", transfer->status); - elan_dev_reset(elandev); - fpi_ssm_mark_failed(ssm, -EIO); - } -} - -static void elan_cmd_read(fpi_ssm *ssm, struct fp_img_dev *dev) -{ - struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); - int response_len = elandev->cmd->response_len; - unsigned char *buffer; - - G_DEBUG_HERE(); - - if (elandev->cmd->response_len == ELAN_CMD_SKIP_READ) { - fp_dbg("skipping read, not expecting anything"); - elan_cmd_done(ssm); - return; - } - - if (elandev->dev_type == ELAN_0C42) { - /* ELAN_0C42 sends an extra byte in one byte responses */ - if (elandev->cmd->response_len == 1) - response_len = 2; - } - - if (elandev->cmd->cmd == get_image_cmd.cmd) - /* raw data has 2-byte "pixels" and the frame is vertical */ - response_len = - elandev->raw_frame_height * elandev->frame_width * 2; - - g_clear_pointer(&elandev->last_read, g_free); - buffer = g_malloc(response_len); - - elandev->cur_transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev), - ssm, - elandev->cmd->response_in, - buffer, - response_len, - elan_cmd_cb, - NULL, - elandev->cmd_timeout); - int r = fpi_usb_submit_transfer(elandev->cur_transfer); - if (r < 0) - fpi_ssm_mark_failed(ssm, r); + elandev->frames = g_slist_prepend (elandev->frames, frame); + elandev->num_frames += 1; + return 0; } static void -elan_run_cmd(fpi_ssm *ssm, - struct fp_img_dev *dev, - const struct elan_cmd *cmd, - int cmd_timeout) +elan_process_frame_linear (unsigned short *raw_frame, + GSList ** frames) { - struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); + unsigned int frame_size = + assembling_ctx.frame_width * assembling_ctx.frame_height; + struct fpi_frame *frame = + g_malloc (frame_size + sizeof (struct fpi_frame)); - dbg_buf(cmd->cmd, 2); + G_DEBUG_HERE (); - elandev->cmd = cmd; - if (cmd_timeout != -1) - elandev->cmd_timeout = cmd_timeout; + unsigned short min = 0xffff, max = 0; + for (int i = 0; i < frame_size; i++) + { + if (raw_frame[i] < min) + min = raw_frame[i]; + if (raw_frame[i] > max) + max = raw_frame[i]; + } - if (cmd->devices != ELAN_ALL_DEV && !(cmd->devices & elandev->dev_type)) { - fp_dbg("skipping command 0x%x 0x%x for this device (for devices 0x%x but device is 0x%x)", - cmd->cmd[0], cmd->cmd[1], cmd->devices, elandev->dev_type); - elan_cmd_done(ssm); - return; - } + g_assert (max != min); - elandev->cur_transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev), - ssm, - ELAN_EP_CMD_OUT, - g_memdup((char *) cmd->cmd, ELAN_CMD_LEN), - ELAN_CMD_LEN, - elan_cmd_cb, - NULL, - elandev->cmd_timeout); - int r = fpi_usb_submit_transfer(elandev->cur_transfer); - if (r < 0) - fpi_ssm_mark_failed(ssm, r); + unsigned short px; + for (int i = 0; i < frame_size; i++) + { + px = raw_frame[i]; + px = (px - min) * 0xff / (max - min); + frame->data[i] = (unsigned char) px; + } + + *frames = g_slist_prepend (*frames, frame); +} + +static void +elan_process_frame_thirds (unsigned short *raw_frame, + GSList ** frames) +{ + G_DEBUG_HERE (); + + unsigned int frame_size = + assembling_ctx.frame_width * assembling_ctx.frame_height; + struct fpi_frame *frame = + g_malloc (frame_size + sizeof (struct fpi_frame)); + + unsigned short lvl0, lvl1, lvl2, lvl3; + unsigned short *sorted = g_malloc (frame_size * sizeof (short)); + memcpy (sorted, raw_frame, frame_size * sizeof (short)); + qsort (sorted, frame_size, sizeof (short), cmp_short); + lvl0 = sorted[0]; + lvl1 = sorted[frame_size * 3 / 10]; + lvl2 = sorted[frame_size * 65 / 100]; + lvl3 = sorted[frame_size - 1]; + g_free (sorted); + + unsigned short px; + for (int i = 0; i < frame_size; i++) + { + px = raw_frame[i]; + if (lvl0 <= px && px < lvl1) + px = (px - lvl0) * 99 / (lvl1 - lvl0); + else if (lvl1 <= px && px < lvl2) + px = 99 + ((px - lvl1) * 56 / (lvl2 - lvl1)); + else // (lvl2 <= px && px <= lvl3) + px = 155 + ((px - lvl2) * 100 / (lvl3 - lvl2)); + frame->data[i] = (unsigned char) px; + } + + *frames = g_slist_prepend (*frames, frame); +} + +static void +elan_submit_image (FpImageDevice *dev) +{ + FpiDeviceElan *self = FPI_DEVICE_ELAN (dev); + GSList *raw_frames; + GSList *frames = NULL; + FpImage *img; + + G_DEBUG_HERE (); + + raw_frames = g_slist_nth (self->frames, ELAN_SKIP_LAST_FRAMES); + + assembling_ctx.frame_width = self->frame_width; + assembling_ctx.frame_height = self->frame_height; + assembling_ctx.image_width = self->frame_width * 3 / 2; + g_slist_foreach (raw_frames, (GFunc) self->process_frame, &frames); + fpi_do_movement_estimation (&assembling_ctx, frames); + img = fpi_assemble_frames (&assembling_ctx, frames); + + fpi_image_device_image_captured (dev, img); +} + +static void +elan_cmd_done (FpiSsm *ssm) +{ + G_DEBUG_HERE (); + fpi_ssm_next_state (ssm); +} + +static void +elan_cmd_cb (FpiUsbTransfer *transfer, FpDevice *dev, + gpointer user_data, GError *error) +{ + FpiSsm *ssm = transfer->ssm; + FpiDeviceElan *self = FPI_DEVICE_ELAN (dev); + + G_DEBUG_HERE (); + + if (error) + { + /* XXX: In the cancellation case we used to not + * mark the SSM as failed?! */ + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } + + /* XXX: We used to reset the device in error cases! */ + if (transfer->endpoint & FPI_USB_ENDPOINT_IN) + { + /* just finished receiving */ + self->last_read = g_memdup (transfer->buffer, transfer->actual_length); + elan_cmd_done (ssm); + } + else + { + /* just finished sending */ + G_DEBUG_HERE (); + elan_cmd_read (ssm, dev); + } +} + +static void +elan_cmd_read (FpiSsm *ssm, FpDevice *dev) +{ + FpiDeviceElan *self = FPI_DEVICE_ELAN (dev); + FpiUsbTransfer *transfer; + GCancellable *cancellable = NULL; + int response_len = self->cmd->response_len; + + G_DEBUG_HERE (); + + if (self->cmd->response_len == ELAN_CMD_SKIP_READ) + { + fp_dbg ("skipping read, not expecting anything"); + elan_cmd_done (ssm); + return; + } + + if (self->dev_type == ELAN_0C42) + { + /* ELAN_0C42 sends an extra byte in one byte responses */ + if (self->cmd->response_len == 1) + response_len = 2; + } + + if (self->cmd->cmd == get_image_cmd.cmd) + /* raw data has 2-byte "pixels" and the frame is vertical */ + response_len = + self->raw_frame_height * self->frame_width * 2; + + g_clear_pointer (&self->last_read, g_free); + + transfer = fpi_usb_transfer_new (dev); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + + fpi_usb_transfer_fill_bulk (transfer, + self->cmd->response_in, + response_len); + + if (!self->cmd->never_cancel) + cancellable = fpi_device_get_cancellable (dev); + + fpi_usb_transfer_submit (transfer, self->cmd_timeout, cancellable, elan_cmd_cb, NULL); + fpi_usb_transfer_unref (transfer); +} + +static void +elan_run_cmd (FpiSsm *ssm, + FpDevice *dev, + const struct elan_cmd *cmd, + int cmd_timeout) +{ + FpiDeviceElan *self = FPI_DEVICE_ELAN (dev); + FpiUsbTransfer *transfer; + GCancellable *cancellable = NULL; + + self->cmd = cmd; + if (cmd_timeout != -1) + self->cmd_timeout = cmd_timeout; + + if (cmd->devices != ELAN_ALL_DEV && !(cmd->devices & self->dev_type)) + { + fp_dbg ("skipping command 0x%x 0x%x for this device (for devices 0x%x but device is 0x%x)", + cmd->cmd[0], cmd->cmd[1], cmd->devices, self->dev_type); + elan_cmd_done (ssm); + return; + } + + transfer = fpi_usb_transfer_new (dev); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + + fpi_usb_transfer_fill_bulk_full (transfer, + ELAN_EP_CMD_OUT, + (guint8 *) cmd->cmd, + ELAN_CMD_LEN, + NULL); + + if (!self->cmd->never_cancel) + cancellable = fpi_device_get_cancellable (dev); + + fpi_usb_transfer_submit (transfer, + self->cmd_timeout, + cancellable, + elan_cmd_cb, + NULL); + fpi_usb_transfer_unref (transfer); } enum stop_capture_states { - STOP_CAPTURE, - STOP_CAPTURE_NUM_STATES, + STOP_CAPTURE, + STOP_CAPTURE_NUM_STATES, }; -static void stop_capture_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) +static void +stop_capture_run_state (FpiSsm *ssm, FpDevice *dev) { - G_DEBUG_HERE(); + G_DEBUG_HERE (); - switch (fpi_ssm_get_cur_state(ssm)) { - case STOP_CAPTURE: - elan_run_cmd(ssm, FP_IMG_DEV(dev), &stop_cmd, ELAN_CMD_TIMEOUT); - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case STOP_CAPTURE: + elan_run_cmd (ssm, dev, &stop_cmd, + ELAN_CMD_TIMEOUT); + break; + } } -static void stop_capture_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +stop_capture_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { - struct fp_img_dev *dev = user_data; - struct elan_dev *elandev = FP_INSTANCE_DATA(_dev); - int error = fpi_ssm_get_error(ssm); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceElan *self = FPI_DEVICE_ELAN (dev); - G_DEBUG_HERE(); + G_DEBUG_HERE (); - fpi_ssm_free(ssm); + fpi_ssm_free (ssm); - if (!error) { - fpi_imgdev_report_finger_status(dev, FALSE); + /* The device is inactive at this point. */ + self->dev_state = FP_IMAGE_DEVICE_STATE_INACTIVE; - /* If verify or identify fails because of short swipe, we need to restart - * capture manually. It feels like libfprint or the application should know - * better if they want to retry, but they don't. Unless we've been asked to - * deactivate, try to re-enter the capture loop. Since state change is - * async, there's still a chance to be deactivated by another pending - * event. */ - if (elandev->dev_state_next != IMGDEV_STATE_INACTIVE) - dev_change_state(dev, IMGDEV_STATE_AWAIT_FINGER_ON); + if (self->deactivating) + { + /* Simply complete the pending deactivation. */ + self->deactivating = FALSE; + fpi_image_device_deactivate_complete (dev, error); + return; + } - } else if (error != -ECANCELED) - fpi_imgdev_abort_scan(dev, error); + if (!error) + fpi_image_device_report_finger_status (dev, FALSE); + else + /* NOTE: We cannot get a cancellation error here. */ + fpi_image_device_session_error (dev, error); } -static void elan_stop_capture(struct fp_img_dev *dev) +static void +elan_stop_capture (FpDevice *dev) { - struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceElan *self = FPI_DEVICE_ELAN (dev); - G_DEBUG_HERE(); + G_DEBUG_HERE (); - elan_dev_reset(elandev); + elan_dev_reset_state (self); - fpi_ssm *ssm = - fpi_ssm_new(FP_DEV(dev), stop_capture_run_state, - STOP_CAPTURE_NUM_STATES, dev); - fpi_ssm_start(ssm, stop_capture_complete); + FpiSsm *ssm = + fpi_ssm_new (dev, stop_capture_run_state, STOP_CAPTURE_NUM_STATES); + fpi_ssm_start (ssm, stop_capture_complete); } enum capture_states { - CAPTURE_LED_ON, - CAPTURE_WAIT_FINGER, - CAPTURE_READ_DATA, - CAPTURE_CHECK_ENOUGH_FRAMES, - CAPTURE_NUM_STATES, + CAPTURE_LED_ON, + CAPTURE_WAIT_FINGER, + CAPTURE_READ_DATA, + CAPTURE_CHECK_ENOUGH_FRAMES, + CAPTURE_NUM_STATES, }; -static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +capture_run_state (FpiSsm *ssm, FpDevice *dev) { - struct fp_img_dev *dev = user_data; - struct elan_dev *elandev = FP_INSTANCE_DATA(_dev); - int r; + FpImageDevice *idev = FP_IMAGE_DEVICE (dev); + FpiDeviceElan *self = FPI_DEVICE_ELAN (dev); + int r; - switch (fpi_ssm_get_cur_state(ssm)) { - case CAPTURE_LED_ON: - elan_run_cmd(ssm, dev, &led_on_cmd, ELAN_CMD_TIMEOUT); - break; - case CAPTURE_WAIT_FINGER: - elan_run_cmd(ssm, dev, &pre_scan_cmd, -1); - break; - case CAPTURE_READ_DATA: - /* 0x55 - finger present - * 0xff - device not calibrated (probably) */ - if (elandev->last_read && elandev->last_read[0] == 0x55) { - if (elandev->dev_state == IMGDEV_STATE_AWAIT_FINGER_ON) - fpi_imgdev_report_finger_status(dev, TRUE); - elan_run_cmd(ssm, dev, &get_image_cmd, ELAN_CMD_TIMEOUT); - } else - fpi_ssm_mark_failed(ssm, -EBADMSG); - break; - case CAPTURE_CHECK_ENOUGH_FRAMES: - r = elan_save_img_frame(elandev); - if (r < 0) - fpi_ssm_mark_failed(ssm, r); - else if (elandev->num_frames < ELAN_MAX_FRAMES) { - /* quickly stop if finger is removed */ - elandev->cmd_timeout = ELAN_FINGER_TIMEOUT; - fpi_ssm_jump_to_state(ssm, CAPTURE_WAIT_FINGER); - } else { - fpi_ssm_next_state(ssm); - } - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case CAPTURE_LED_ON: + elan_run_cmd (ssm, dev, &led_on_cmd, ELAN_CMD_TIMEOUT); + break; + + case CAPTURE_WAIT_FINGER: + elan_run_cmd (ssm, dev, &pre_scan_cmd, -1); + break; + + case CAPTURE_READ_DATA: + self->dev_state = FP_IMAGE_DEVICE_STATE_CAPTURE; + + /* 0x55 - finger present + * 0xff - device not calibrated (probably) */ + if (self->last_read && self->last_read[0] == 0x55) + { + fpi_image_device_report_finger_status (idev, TRUE); + elan_run_cmd (ssm, dev, &get_image_cmd, ELAN_CMD_TIMEOUT); + } + else + { + fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); + } + break; + + case CAPTURE_CHECK_ENOUGH_FRAMES: + r = elan_save_img_frame (self); + if (r < 0) + { + fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL)); + } + else if (self->num_frames < ELAN_MAX_FRAMES) + { + /* quickly stop if finger is removed */ + self->cmd_timeout = ELAN_FINGER_TIMEOUT; + fpi_ssm_jump_to_state (ssm, CAPTURE_WAIT_FINGER); + } + else + { + fpi_ssm_next_state (ssm); + } + break; + } } -static void capture_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +capture_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { - struct fp_img_dev *dev = user_data; - struct elan_dev *elandev = FP_INSTANCE_DATA(_dev); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceElan *self = FPI_DEVICE_ELAN (_dev); - G_DEBUG_HERE(); + G_DEBUG_HERE (); - if (fpi_ssm_get_error(ssm) == -ECANCELED) { - fpi_ssm_free(ssm); - return; - } + /* XXX: cancellation was specially handled by doing nothing! */ - /* either max frames captured or timed out waiting for the next frame */ - if (!fpi_ssm_get_error(ssm) - || (fpi_ssm_get_error(ssm) == -ETIMEDOUT - && fpi_ssm_get_cur_state(ssm) == CAPTURE_WAIT_FINGER)) - if (elandev->num_frames >= ELAN_MIN_FRAMES) - elan_submit_image(dev); - else { - fp_dbg("swipe too short: want >= %d frames, got %d", - ELAN_MIN_FRAMES, elandev->num_frames); - fpi_imgdev_abort_scan(dev, FP_VERIFY_RETRY_TOO_SHORT); - } + /* either max frames captured or timed out waiting for the next frame */ + if (!error || + (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT) && + fpi_ssm_get_cur_state (ssm) == CAPTURE_WAIT_FINGER)) + { + if (self->num_frames >= ELAN_MIN_FRAMES) + { + elan_submit_image (dev); + } + else + { + fp_dbg ("swipe too short: want >= %d frames, got %d", + ELAN_MIN_FRAMES, self->num_frames); + fpi_image_device_retry_scan (dev, FP_DEVICE_RETRY_TOO_SHORT); + } + g_clear_error (&error); + } + else + { + fpi_image_device_session_error (dev, error); + } - /* other error - * It says "...abort_scan" but reporting 1 during verification makes it - * successful! */ - else - fpi_imgdev_abort_scan(dev, fpi_ssm_get_error(ssm)); - - fpi_ssm_free(ssm); + fpi_ssm_free (ssm); } -static void elan_capture(struct fp_img_dev *dev) +static void +elan_capture (FpDevice *dev) { - struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceElan *self = FPI_DEVICE_ELAN (dev); - G_DEBUG_HERE(); + G_DEBUG_HERE (); - elan_dev_reset(elandev); - fpi_ssm *ssm = - fpi_ssm_new(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev); - fpi_ssm_start(ssm, capture_complete); + elan_dev_reset_state (self); + FpiSsm *ssm = + fpi_ssm_new (dev, capture_run_state, CAPTURE_NUM_STATES); + fpi_ssm_start (ssm, capture_complete); } /* this function needs to have elandev->background and elandev->last_read to be * the calibration mean */ -static int elan_need_calibration(struct elan_dev *elandev) +static int +elan_need_calibration (FpiDeviceElan *elandev) { - G_DEBUG_HERE(); + G_DEBUG_HERE (); - unsigned short calib_mean = - elandev->last_read[0] * 0xff + elandev->last_read[1]; - unsigned int bg_mean = 0, delta; - unsigned int frame_size = elandev->frame_width * elandev->frame_height; + unsigned short calib_mean = + elandev->last_read[0] * 0xff + elandev->last_read[1]; + unsigned int bg_mean = 0, delta; + unsigned int frame_size = elandev->frame_width * elandev->frame_height; - g_assert(frame_size != 0); + g_assert (frame_size != 0); - if (elandev->dev_type == ELAN_0C42) { - if (calib_mean > 5500 || - calib_mean < 2500) { - fp_dbg("Forcing needed recalibration"); - return 1; - } - } + if (elandev->dev_type == ELAN_0C42) + { + if (calib_mean > 5500 || + calib_mean < 2500) + { + fp_dbg ("Forcing needed recalibration"); + return 1; + } + } - for (int i = 0; i < frame_size; i++) - bg_mean += elandev->background[i]; - bg_mean /= frame_size; + for (int i = 0; i < frame_size; i++) + bg_mean += elandev->background[i]; + bg_mean /= frame_size; - delta = - bg_mean > calib_mean ? bg_mean - calib_mean : calib_mean - bg_mean; + delta = + bg_mean > calib_mean ? bg_mean - calib_mean : calib_mean - bg_mean; - fp_dbg("calibration mean: %d, bg mean: %d, delta: %d", calib_mean, - bg_mean, delta); + fp_dbg ("calibration mean: %d, bg mean: %d, delta: %d", calib_mean, + bg_mean, delta); - return delta > ELAN_CALIBRATION_MAX_DELTA ? 1 : 0; + return delta > ELAN_CALIBRATION_MAX_DELTA ? 1 : 0; } enum calibrate_states { - CALIBRATE_GET_BACKGROUND, - CALIBRATE_SAVE_BACKGROUND, - CALIBRATE_GET_MEAN, - CALIBRATE_CHECK_NEEDED, - CALIBRATE_GET_STATUS, - CALIBRATE_CHECK_STATUS, - CALIBRATE_REPEAT_STATUS, - CALIBRATE_NUM_STATES, + CALIBRATE_GET_BACKGROUND, + CALIBRATE_SAVE_BACKGROUND, + CALIBRATE_GET_MEAN, + CALIBRATE_CHECK_NEEDED, + CALIBRATE_GET_STATUS, + CALIBRATE_CHECK_STATUS, + CALIBRATE_REPEAT_STATUS, + CALIBRATE_NUM_STATES, }; -static gboolean elan_supports_calibration(struct elan_dev *elandev) +static gboolean +elan_supports_calibration (FpiDeviceElan *elandev) { - if (elandev->dev_type == ELAN_0C42) - return TRUE; + if (elandev->dev_type == ELAN_0C42) + return TRUE; - return elandev->fw_ver >= ELAN_MIN_CALIBRATION_FW; -} - -static void calibrate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) -{ - struct fp_img_dev *dev = user_data; - struct elan_dev *elandev = FP_INSTANCE_DATA(_dev); - - G_DEBUG_HERE(); - - switch (fpi_ssm_get_cur_state(ssm)) { - case CALIBRATE_GET_BACKGROUND: - elan_run_cmd(ssm, dev, &get_image_cmd, ELAN_CMD_TIMEOUT); - break; - case CALIBRATE_SAVE_BACKGROUND: - elan_save_background(elandev); - if (!elan_supports_calibration(elandev)) { - fp_dbg("FW does not support calibration"); - fpi_ssm_mark_completed(ssm); - } else - fpi_ssm_next_state(ssm); - break; - case CALIBRATE_GET_MEAN: - elan_run_cmd(ssm, dev, &get_calib_mean_cmd, ELAN_CMD_TIMEOUT); - break; - case CALIBRATE_CHECK_NEEDED: - if (elan_need_calibration(elandev)) { - elandev->calib_status = 0; - fpi_ssm_next_state(ssm); - } else - fpi_ssm_mark_completed(ssm); - break; - case CALIBRATE_GET_STATUS: - elandev->calib_atts_left -= 1; - if (elandev->calib_atts_left) - elan_run_cmd(ssm, dev, &get_calib_status_cmd, - ELAN_CMD_TIMEOUT); - else { - fp_dbg("calibration failed"); - fpi_ssm_mark_failed(ssm, -1); - } - break; - case CALIBRATE_CHECK_STATUS: - /* 0x01 - retry, 0x03 - ok - * It appears that when reading the response soon after 0x4023 the device - * can return 0x03, and only after some time (up to 100 ms) the response - * changes to 0x01. It stays that way for some time and then changes back - * to 0x03. Because of this we don't just expect 0x03, we want to see 0x01 - * first. This is to make sure that a full calibration loop has completed */ - fp_dbg("calibration status: 0x%02x", elandev->last_read[0]); - if (elandev->calib_status == 0x01 - && elandev->last_read[0] == 0x03) { - elandev->calib_status = 0x03; - fpi_ssm_jump_to_state(ssm, CALIBRATE_GET_BACKGROUND); - } else { - fpi_timeout *timeout; - - if (elandev->calib_status == 0x00 - && elandev->last_read[0] == 0x01) - elandev->calib_status = 0x01; - timeout = fpi_timeout_add(50, fpi_ssm_next_state_timeout_cb, _dev, ssm); - fpi_timeout_set_name(timeout, "calibrate_run_state"); - } - break; - case CALIBRATE_REPEAT_STATUS: - fpi_ssm_jump_to_state(ssm, CALIBRATE_GET_STATUS); - break; - } -} - -static void calibrate_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) -{ - struct fp_img_dev *dev = user_data; - - G_DEBUG_HERE(); - - - if (fpi_ssm_get_error(ssm) != -ECANCELED) - elan_capture(dev); - - fpi_ssm_free(ssm); -} - -static void elan_calibrate(struct fp_img_dev *dev) -{ - struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); - - G_DEBUG_HERE(); - - elan_dev_reset(elandev); - elandev->calib_atts_left = ELAN_CALIBRATION_ATTEMPTS; - - fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), calibrate_run_state, - CALIBRATE_NUM_STATES, dev); - fpi_ssm_start(ssm, calibrate_complete); -} - -enum activate_states { - ACTIVATE_GET_FW_VER, - ACTIVATE_SET_FW_VER, - ACTIVATE_GET_SENSOR_DIM, - ACTIVATE_SET_SENSOR_DIM, - ACTIVATE_CMD_1, - ACTIVATE_NUM_STATES, -}; - -static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) -{ - struct fp_img_dev *dev = user_data; - struct elan_dev *elandev = FP_INSTANCE_DATA(_dev); - - G_DEBUG_HERE(); - - switch (fpi_ssm_get_cur_state(ssm)) { - case ACTIVATE_GET_FW_VER: - elan_run_cmd(ssm, dev, &get_fw_ver_cmd, ELAN_CMD_TIMEOUT); - break; - case ACTIVATE_SET_FW_VER: - elandev->fw_ver = - (elandev->last_read[0] << 8 | elandev->last_read[1]); - fp_dbg("FW ver 0x%04hx", elandev->fw_ver); - fpi_ssm_next_state(ssm); - break; - case ACTIVATE_GET_SENSOR_DIM: - elan_run_cmd(ssm, dev, &get_sensor_dim_cmd, ELAN_CMD_TIMEOUT); - break; - case ACTIVATE_SET_SENSOR_DIM: - /* see elan_save_frame for details */ - if (elandev->dev_type & ELAN_NOT_ROTATED) { - elandev->frame_width = elandev->last_read[0]; - elandev->frame_height = elandev->raw_frame_height = - elandev->last_read[2]; - } else { - elandev->frame_width = elandev->last_read[2]; - elandev->frame_height = elandev->raw_frame_height = - elandev->last_read[0]; - } - /* Work-around sensors returning the sizes as zero-based index - * rather than the number of pixels. */ - if ((elandev->frame_width % 2 == 1) && - (elandev->frame_height % 2 == 1)) { - elandev->frame_width++; - elandev->frame_height++; - elandev->raw_frame_height = elandev->frame_height; - } - if (elandev->frame_height > ELAN_MAX_FRAME_HEIGHT) - elandev->frame_height = ELAN_MAX_FRAME_HEIGHT; - fp_dbg("sensor dimensions, WxH: %dx%d", elandev->frame_width, - elandev->raw_frame_height); - fpi_ssm_next_state(ssm); - break; - case ACTIVATE_CMD_1: - /* TODO: find out what this does, if we need it */ - elan_run_cmd(ssm, dev, &activate_cmd_1, ELAN_CMD_TIMEOUT); - break; - } -} - -static void activate_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) -{ - struct fp_img_dev *dev = user_data; - - G_DEBUG_HERE(); - - if (fpi_ssm_get_error(ssm) != -ECANCELED) { - fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm)); - } - - fpi_ssm_free(ssm); -} - -static void elan_activate(struct fp_img_dev *dev) -{ - struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); - - G_DEBUG_HERE(); - elan_dev_reset(elandev); - - fpi_ssm *ssm = - fpi_ssm_new(FP_DEV(dev), activate_run_state, ACTIVATE_NUM_STATES, dev); - fpi_ssm_start(ssm, activate_complete); -} - -static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) -{ - struct elan_dev *elandev; - int r; - - G_DEBUG_HERE(); - - r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - if (r < 0) { - fp_err("could not claim interface 0: %s", libusb_error_name(r)); - return r; - } - - elandev = g_malloc0(sizeof(struct elan_dev)); - fp_dev_set_instance_data(FP_DEV(dev), elandev); - - /* common params */ - elandev->dev_type = driver_data; - elandev->background = NULL; - elandev->process_frame = elan_process_frame_thirds; - - switch (driver_data) { - case ELAN_0907: - elandev->process_frame = elan_process_frame_linear; - break; - } - - fpi_imgdev_open_complete(dev, 0); - return 0; -} - -static void elan_deactivate(struct fp_img_dev *dev) -{ - G_DEBUG_HERE(); - - fpi_imgdev_deactivate_complete(dev); -} - -static void dev_deinit(struct fp_img_dev *dev) -{ - struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); - - G_DEBUG_HERE(); - - elan_dev_reset(elandev); - g_free(elandev->background); - g_free(elandev); - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - fpi_imgdev_close_complete(dev); -} - -static int dev_activate(struct fp_img_dev *dev) -{ - G_DEBUG_HERE(); - elan_activate(dev); - return 0; -} - -static void elan_change_state(struct fp_img_dev *dev) -{ - struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); - enum fp_imgdev_state next_state = elandev->dev_state_next; - - if (elandev->dev_state == next_state) { - fp_dbg("already in %d", next_state); - return; - } else - fp_dbg("changing to %d", next_state); - - switch (next_state) { - case IMGDEV_STATE_INACTIVE: - if (elandev->cur_transfer) - /* deactivation will complete in transfer callback */ - fpi_usb_cancel_transfer(elandev->cur_transfer); - else - elan_deactivate(dev); - break; - case IMGDEV_STATE_AWAIT_FINGER_ON: - /* activation completed or another enroll stage started */ - elan_calibrate(dev); - break; - case IMGDEV_STATE_CAPTURE: - /* not used */ - break; - case IMGDEV_STATE_AWAIT_FINGER_OFF: - elan_stop_capture(dev); - } - - elandev->dev_state = next_state; + return elandev->fw_ver >= ELAN_MIN_CALIBRATION_FW; } static void -elan_change_state_async(struct fp_dev *dev, - void *data) +calibrate_run_state (FpiSsm *ssm, FpDevice *dev) { - g_message ("state change dev: %p", dev); - elan_change_state(FP_IMG_DEV (dev)); + FpiDeviceElan *self = FPI_DEVICE_ELAN (dev); + + G_DEBUG_HERE (); + + switch (fpi_ssm_get_cur_state (ssm)) + { + case CALIBRATE_GET_BACKGROUND: + elan_run_cmd (ssm, dev, &get_image_cmd, ELAN_CMD_TIMEOUT); + break; + + case CALIBRATE_SAVE_BACKGROUND: + elan_save_background (self); + if (!elan_supports_calibration (self)) + { + fp_dbg ("FW does not support calibration"); + fpi_ssm_mark_completed (ssm); + } + else + { + fpi_ssm_next_state (ssm); + } + break; + + case CALIBRATE_GET_MEAN: + elan_run_cmd (ssm, dev, &get_calib_mean_cmd, ELAN_CMD_TIMEOUT); + break; + + case CALIBRATE_CHECK_NEEDED: + if (elan_need_calibration (self)) + { + self->calib_status = 0; + fpi_ssm_next_state (ssm); + } + else + { + fpi_ssm_mark_completed (ssm); + } + break; + + case CALIBRATE_GET_STATUS: + self->calib_atts_left -= 1; + if (self->calib_atts_left) + { + elan_run_cmd (ssm, dev, &get_calib_status_cmd, + ELAN_CMD_TIMEOUT); + } + else + { + fp_dbg ("calibration failed"); + fpi_ssm_mark_failed (ssm, + fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, + "Callibration failed!")); + } + break; + + case CALIBRATE_CHECK_STATUS: + /* 0x01 - retry, 0x03 - ok + * It appears that when reading the response soon after 0x4023 the device + * can return 0x03, and only after some time (up to 100 ms) the response + * changes to 0x01. It stays that way for some time and then changes back + * to 0x03. Because of this we don't just expect 0x03, we want to see 0x01 + * first. This is to make sure that a full calibration loop has completed */ + fp_dbg ("calibration status: 0x%02x", self->last_read[0]); + if (self->calib_status == 0x01 && + self->last_read[0] == 0x03) + { + self->calib_status = 0x03; + fpi_ssm_jump_to_state (ssm, CALIBRATE_GET_BACKGROUND); + } + else + { + GSource *timeout; + + if (self->calib_status == 0x00 && + self->last_read[0] == 0x01) + self->calib_status = 0x01; + timeout = fpi_device_add_timeout (dev, 50, + fpi_ssm_next_state_timeout_cb, + ssm); + g_source_set_name (timeout, "calibrate_run_state"); + } + break; + + case CALIBRATE_REPEAT_STATUS: + fpi_ssm_jump_to_state (ssm, CALIBRATE_GET_STATUS); + break; + } } -static int dev_change_state(struct fp_img_dev *dev, enum fp_imgdev_state state) +static void +calibrate_complete (FpiSsm *ssm, FpDevice *dev, GError *error) { - struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_timeout *timeout; + FpiDeviceElan *self = FPI_DEVICE_ELAN (dev); - G_DEBUG_HERE(); + G_DEBUG_HERE (); - switch (state) { - case IMGDEV_STATE_INACTIVE: - case IMGDEV_STATE_AWAIT_FINGER_ON: - case IMGDEV_STATE_AWAIT_FINGER_OFF: { - char *name; + if (error) + { + self->dev_state = FP_IMAGE_DEVICE_STATE_INACTIVE; + fpi_image_device_session_error (FP_IMAGE_DEVICE (dev), error); + } + else + { + self->dev_state = FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON; + elan_capture (dev); + } - /* schedule state change instead of calling it directly to allow all actions - * related to the previous state to complete */ - elandev->dev_state_next = state; - timeout = fpi_timeout_add(10, elan_change_state_async, FP_DEV(dev), NULL); - - name = g_strdup_printf ("dev_change_state to %d", state); - fpi_timeout_set_name(timeout, name); - g_free (name); - - break; - } - case IMGDEV_STATE_CAPTURE: - /* TODO MAYBE: split capture ssm into smaller ssms and use this state */ - elandev->dev_state = state; - elandev->dev_state_next = state; - break; - default: - fp_err("unrecognized state %d", state); - fpi_imgdev_session_error(dev, -EINVAL); - return -EINVAL; - } - - /* as of time of writing libfprint never checks the return value */ - return 0; + fpi_ssm_free (ssm); } -static void dev_deactivate(struct fp_img_dev *dev) +static void +elan_calibrate (FpDevice *dev) { - G_DEBUG_HERE(); + FpiDeviceElan *self = FPI_DEVICE_ELAN (dev); - dev_change_state(dev, IMGDEV_STATE_INACTIVE); + G_DEBUG_HERE (); + + elan_dev_reset_state (self); + self->calib_atts_left = ELAN_CALIBRATION_ATTEMPTS; + + FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), calibrate_run_state, + CALIBRATE_NUM_STATES); + fpi_ssm_start (ssm, calibrate_complete); } -struct fp_img_driver elan_driver = { - .driver = { - .id = ELAN_ID, - .name = FP_COMPONENT, - .full_name = "ElanTech Fingerprint Sensor", - .id_table = elan_id_table, - .scan_type = FP_SCAN_TYPE_SWIPE, - }, - .flags = 0, - - .bz3_threshold = 24, - - .open = dev_init, - .close = dev_deinit, - .activate = dev_activate, - .deactivate = dev_deactivate, - .change_state = dev_change_state, +enum activate_states { + ACTIVATE_GET_FW_VER, + ACTIVATE_SET_FW_VER, + ACTIVATE_GET_SENSOR_DIM, + ACTIVATE_SET_SENSOR_DIM, + ACTIVATE_CMD_1, + ACTIVATE_NUM_STATES, }; + +static void +activate_run_state (FpiSsm *ssm, FpDevice *dev) +{ + FpiDeviceElan *self = FPI_DEVICE_ELAN (dev); + + G_DEBUG_HERE (); + + switch (fpi_ssm_get_cur_state (ssm)) + { + case ACTIVATE_GET_FW_VER: + elan_run_cmd (ssm, dev, &get_fw_ver_cmd, ELAN_CMD_TIMEOUT); + break; + + case ACTIVATE_SET_FW_VER: + self->fw_ver = + (self->last_read[0] << 8 | self->last_read[1]); + fp_dbg ("FW ver 0x%04hx", self->fw_ver); + fpi_ssm_next_state (ssm); + break; + + case ACTIVATE_GET_SENSOR_DIM: + elan_run_cmd (ssm, dev, &get_sensor_dim_cmd, ELAN_CMD_TIMEOUT); + break; + + case ACTIVATE_SET_SENSOR_DIM: + /* see elan_save_frame for details */ + if (self->dev_type & ELAN_NOT_ROTATED) + { + self->frame_width = self->last_read[0]; + self->frame_height = self->raw_frame_height = + self->last_read[2]; + } + else + { + self->frame_width = self->last_read[2]; + self->frame_height = self->raw_frame_height = + self->last_read[0]; + } + /* Work-around sensors returning the sizes as zero-based index + * rather than the number of pixels. */ + if ((self->frame_width % 2 == 1) && + (self->frame_height % 2 == 1)) + { + self->frame_width++; + self->frame_height++; + self->raw_frame_height = self->frame_height; + } + if (self->frame_height > ELAN_MAX_FRAME_HEIGHT) + self->frame_height = ELAN_MAX_FRAME_HEIGHT; + fp_dbg ("sensor dimensions, WxH: %dx%d", self->frame_width, + self->raw_frame_height); + fpi_ssm_next_state (ssm); + break; + + case ACTIVATE_CMD_1: + /* TODO: find out what this does, if we need it */ + elan_run_cmd (ssm, dev, &activate_cmd_1, ELAN_CMD_TIMEOUT); + break; + } +} + +static void +activate_complete (FpiSsm *ssm, FpDevice *dev, GError *error) +{ + FpImageDevice *idev = FP_IMAGE_DEVICE (dev); + + G_DEBUG_HERE (); + + fpi_image_device_activate_complete (idev, error); + + fpi_ssm_free (ssm); +} + +static void +elan_activate (FpImageDevice *dev) +{ + FpiDeviceElan *self = FPI_DEVICE_ELAN (dev); + + G_DEBUG_HERE (); + elan_dev_reset_state (self); + + FpiSsm *ssm = + fpi_ssm_new (FP_DEVICE (dev), activate_run_state, + ACTIVATE_NUM_STATES); + fpi_ssm_start (ssm, activate_complete); +} + +static void +dev_init (FpImageDevice *dev) +{ + GError *error = NULL; + FpiDeviceElan *self; + + G_DEBUG_HERE (); + + if (!g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error)) + { + fpi_image_device_open_complete (dev, error); + return; + } + + self = FPI_DEVICE_ELAN (dev); + + /* common params */ + self->dev_type = fpi_device_get_driver_data (FP_DEVICE (dev)); + self->background = NULL; + self->process_frame = elan_process_frame_thirds; + + switch (self->dev_type) + { + case ELAN_0907: + self->process_frame = elan_process_frame_linear; + break; + } + + fpi_image_device_open_complete (dev, NULL); +} + +static void +dev_deinit (FpImageDevice *dev) +{ + GError *error = NULL; + FpiDeviceElan *self = FPI_DEVICE_ELAN (dev); + + G_DEBUG_HERE (); + + elan_dev_reset_state (self); + g_free (self->background); + g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), + 0, 0, &error); + fpi_image_device_close_complete (dev, error); +} + +static void +dev_activate (FpImageDevice *dev) +{ + G_DEBUG_HERE (); + elan_activate (dev); +} + +static void +elan_change_state (FpImageDevice *idev) +{ + FpDevice *dev = FP_DEVICE (idev); + FpiDeviceElan *self = FPI_DEVICE_ELAN (dev); + FpImageDeviceState 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) + { + break; + + case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON: + /* activation completed or another enroll stage started */ + elan_calibrate (dev); + break; + + case FP_IMAGE_DEVICE_STATE_CAPTURE: + /* not used */ + break; + + case FP_IMAGE_DEVICE_STATE_INACTIVE: + case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: + if (self->dev_state != FP_IMAGE_DEVICE_STATE_INACTIVE || + self->dev_state != FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF) + elan_stop_capture (dev); + } +} + +static void +elan_change_state_async (FpDevice *dev, + void *data) +{ + g_message ("state change dev: %p", dev); + elan_change_state (FP_IMAGE_DEVICE (dev)); +} + +static void +dev_change_state (FpImageDevice *dev, FpImageDeviceState state) +{ + FpiDeviceElan *self = FPI_DEVICE_ELAN (dev); + GSource *timeout; + + G_DEBUG_HERE (); + + /* Inactive and await finger off are equivalent for the elan driver. */ + if (state == FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF) + state = FP_IMAGE_DEVICE_STATE_INACTIVE; + + if (self->dev_state_next == state) + fp_dbg ("change to state %d already queued", state); + + switch (state) + { + case FP_IMAGE_DEVICE_STATE_INACTIVE: + case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON: + case FP_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); + + name = g_strdup_printf ("dev_change_state to %d", state); + g_source_set_name (timeout, name); + g_free (name); + + break; + } + + case FP_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 +dev_deactivate (FpImageDevice *dev) +{ + FpiDeviceElan *self = FPI_DEVICE_ELAN (dev); + + G_DEBUG_HERE (); + + if (self->dev_state == FP_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) and then ensure we will change + * to the inactive state eventually. */ + self->deactivating = TRUE; + dev_change_state (dev, FP_IMAGE_DEVICE_STATE_INACTIVE); + } +} + +static void +fpi_device_elan_init (FpiDeviceElan *self) +{ +} +static void +fpi_device_elan_class_init (FpiDeviceElanClass *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); + + dev_class->id = "elan"; + dev_class->full_name = "ElanTech Fingerprint Sensor"; + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->id_table = elan_id_table; + dev_class->scan_type = FP_SCAN_TYPE_SWIPE; + + img_class->img_open = dev_init; + img_class->img_close = dev_deinit; + img_class->activate = dev_activate; + img_class->deactivate = dev_deactivate; + img_class->change_state = dev_change_state; + + img_class->bz3_threshold = 24; +} diff --git a/libfprint/drivers/elan.h b/libfprint/drivers/elan.h index c5f0f191..169498a6 100644 --- a/libfprint/drivers/elan.h +++ b/libfprint/drivers/elan.h @@ -21,7 +21,7 @@ #ifndef __ELAN_H #define __ELAN_H -#include +#include #define ELAN_VEND_ID 0x04f3 @@ -59,9 +59,9 @@ #define ELAN_SKIP_LAST_FRAMES 2 #define ELAN_CMD_LEN 0x2 -#define ELAN_EP_CMD_OUT (0x1 | LIBUSB_ENDPOINT_OUT) -#define ELAN_EP_CMD_IN (0x3 | LIBUSB_ENDPOINT_IN) -#define ELAN_EP_IMG_IN (0x2 | LIBUSB_ENDPOINT_IN) +#define ELAN_EP_CMD_OUT (0x1 | FPI_USB_ENDPOINT_OUT) +#define ELAN_EP_CMD_IN (0x3 | FPI_USB_ENDPOINT_IN) +#define ELAN_EP_IMG_IN (0x2 | FPI_USB_ENDPOINT_IN) /* used as response length to tell the driver to skip reading response */ #define ELAN_CMD_SKIP_READ 0 @@ -71,154 +71,158 @@ #define ELAN_CMD_TIMEOUT 10000 #define ELAN_FINGER_TIMEOUT 200 -struct elan_cmd { - unsigned char cmd[ELAN_CMD_LEN]; - int response_len; - int response_in; - unsigned short devices; +struct elan_cmd +{ + unsigned char cmd[ELAN_CMD_LEN]; + int response_len; + int response_in; + unsigned short devices; + gboolean never_cancel; }; static const struct elan_cmd get_sensor_dim_cmd = { - .cmd = {0x00, 0x0c}, - .response_len = 0x4, - .response_in = ELAN_EP_CMD_IN, - .devices = ELAN_ALL_DEV, + .cmd = {0x00, 0x0c}, + .response_len = 0x4, + .response_in = ELAN_EP_CMD_IN, + .devices = ELAN_ALL_DEV, }; static const struct elan_cmd get_fw_ver_cmd = { - .cmd = {0x40, 0x19}, - .response_len = 0x2, - .response_in = ELAN_EP_CMD_IN, - .devices = ELAN_ALL_DEV, + .cmd = {0x40, 0x19}, + .response_len = 0x2, + .response_in = ELAN_EP_CMD_IN, + .devices = ELAN_ALL_DEV, }; /* unknown, returns 0x0 0x1 on 0907 */ static const struct elan_cmd activate_cmd_1 = { - .cmd = {0x40, 0x2a}, - .response_len = 0x2, - .response_in = ELAN_EP_CMD_IN, - .devices = ELAN_0907, + .cmd = {0x40, 0x2a}, + .response_len = 0x2, + .response_in = ELAN_EP_CMD_IN, + .devices = ELAN_0907, }; static const struct elan_cmd get_image_cmd = { - .cmd = {0x00, 0x09}, - /* raw frame sizes are calculated from image dimensions reported by the - * device */ - .response_len = -1, - .response_in = ELAN_EP_IMG_IN, - .devices = ELAN_ALL_DEV, + .cmd = {0x00, 0x09}, + /* raw frame sizes are calculated from image dimensions reported by the + * device */ + .response_len = -1, + .response_in = ELAN_EP_IMG_IN, + .devices = ELAN_ALL_DEV, }; static const struct elan_cmd read_sensor_status_cmd = { - .cmd = {0x40, 0x13}, - .response_len = 0x1, - .response_in = ELAN_EP_CMD_IN, - .devices = ELAN_ALL_DEV, + .cmd = {0x40, 0x13}, + .response_len = 0x1, + .response_in = ELAN_EP_CMD_IN, + .devices = ELAN_ALL_DEV, }; static const struct elan_cmd get_calib_status_cmd = { - .cmd = {0x40, 0x23}, - .response_len = 0x1, - .response_in = ELAN_EP_CMD_IN, - .devices = ELAN_ALL_DEV, + .cmd = {0x40, 0x23}, + .response_len = 0x1, + .response_in = ELAN_EP_CMD_IN, + .devices = ELAN_ALL_DEV, }; static const struct elan_cmd get_calib_mean_cmd = { - .cmd = {0x40, 0x24}, - .response_len = 0x2, - .response_in = ELAN_EP_CMD_IN, - .devices = ELAN_ALL_DEV, + .cmd = {0x40, 0x24}, + .response_len = 0x2, + .response_in = ELAN_EP_CMD_IN, + .devices = ELAN_ALL_DEV, }; static const struct elan_cmd led_on_cmd = { - .cmd = {0x40, 0x31}, - .response_len = ELAN_CMD_SKIP_READ, - .response_in = ELAN_EP_CMD_IN, - .devices = ELAN_ALL_DEV, + .cmd = {0x40, 0x31}, + .response_len = ELAN_CMD_SKIP_READ, + .response_in = ELAN_EP_CMD_IN, + .devices = ELAN_ALL_DEV, }; /* wait for finger * subsequent read will not complete until finger is placed on the reader */ static const struct elan_cmd pre_scan_cmd = { - .cmd = {0x40, 0x3f}, - .response_len = 0x1, - .response_in = ELAN_EP_CMD_IN, - .devices = ELAN_ALL_DEV, + .cmd = {0x40, 0x3f}, + .response_len = 0x1, + .response_in = ELAN_EP_CMD_IN, + .devices = ELAN_ALL_DEV, }; /* led off, stop waiting for finger */ static const struct elan_cmd stop_cmd = { - .cmd = {0x00, 0x0b}, - .response_len = ELAN_CMD_SKIP_READ, - .response_in = ELAN_EP_CMD_IN, - .devices = ELAN_ALL_DEV, + .cmd = {0x00, 0x0b}, + .response_len = ELAN_CMD_SKIP_READ, + .response_in = ELAN_EP_CMD_IN, + .devices = ELAN_ALL_DEV, + .never_cancel = TRUE, }; -static const struct usb_id elan_id_table[] = { - {.vendor = ELAN_VEND_ID,.product = 0x0903,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0907,.driver_data = ELAN_0907}, - {.vendor = ELAN_VEND_ID,.product = 0x0c01,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c02,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c03,.driver_data = ELAN_0C03}, - {.vendor = ELAN_VEND_ID,.product = 0x0c04,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c05,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c06,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c07,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c08,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c09,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c0a,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c0b,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c0c,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c0d,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c0e,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c0f,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c10,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c11,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c12,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c13,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c14,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c15,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c16,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c17,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c18,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c19,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c1a,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c1b,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c1c,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c1d,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c1e,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c1f,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c20,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c21,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c22,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c23,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c24,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c25,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c26,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c27,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c28,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c29,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c2a,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c2b,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c2c,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c2d,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c2e,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c2f,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c30,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c31,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c32,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c33,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c42,.driver_data = ELAN_0C42}, - {0, 0, 0,}, +static const FpIdEntry elan_id_table[] = { + {.vid = ELAN_VEND_ID, .pid = 0x0903, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0907, .driver_data = ELAN_0907}, + {.vid = ELAN_VEND_ID, .pid = 0x0c01, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c02, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c03, .driver_data = ELAN_0C03}, + {.vid = ELAN_VEND_ID, .pid = 0x0c04, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c05, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c06, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c07, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c08, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c09, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c0a, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c0b, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c0c, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c0d, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c0e, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c0f, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c10, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c11, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c12, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c13, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c14, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c15, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c16, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c17, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c18, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c19, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c1a, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c1b, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c1c, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c1d, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c1e, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c1f, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c20, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c21, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c22, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c23, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c24, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c25, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c26, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c27, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c28, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c29, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c2a, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c2b, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c2c, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c2d, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c2e, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c2f, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c30, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c31, .driver_data = ELAN_ALL_DEV}, + {.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 = 0, .pid = 0, .driver_data = 0}, }; -static void elan_cmd_done(fpi_ssm *ssm); -static void elan_cmd_read(fpi_ssm *ssm, struct fp_img_dev *dev); +static void elan_cmd_done (FpiSsm *ssm); +static void elan_cmd_read (FpiSsm *ssm, + FpDevice *dev); -static void elan_calibrate(struct fp_img_dev *dev); -static void elan_capture(struct fp_img_dev *dev); -static void elan_deactivate(struct fp_img_dev *dev); +static void elan_calibrate (FpDevice *dev); +static void elan_capture (FpDevice *dev); -static int dev_change_state(struct fp_img_dev *dev, enum fp_imgdev_state state); +static void dev_change_state (FpImageDevice *dev, + FpImageDeviceState state); #endif diff --git a/libfprint/drivers/etes603.c b/libfprint/drivers/etes603.c index f82fb05f..5c990dae 100644 --- a/libfprint/drivers/etes603.c +++ b/libfprint/drivers/etes603.c @@ -39,412 +39,448 @@ #include "driver_ids.h" /* libusb defines */ -#define EP_IN 0x81 -#define EP_OUT 0x02 +#define EP_IN 0x81 +#define EP_OUT 0x02 /* Note that 1000 ms is usually enough but with CMD_READ_FE could be longer * since the sensor is waiting motion. */ -#define BULK_TIMEOUT 1000 +#define BULK_TIMEOUT 1000 /* es603 defines */ -#define FRAME_WIDTH 192 /* pixels per row */ -#define FRAME_HEIGHT 4 /* number of rows */ -#define FRAME_SIZE 384 /* size in bytes (4 bits per pixels) */ -#define FE_WIDTH 256 /* pixels per row for Fly-Estimation */ -#define FE_HEIGHT 500 /* number of rows for Fly-Estimation */ -#define FE_SIZE 64000 /* size in bytes (4 bits per pixels) */ +#define FRAME_WIDTH 192 /* pixels per row */ +#define FRAME_HEIGHT 4 /* number of rows */ +#define FRAME_SIZE 384 /* size in bytes (4 bits per pixels) */ +#define FE_WIDTH 256 /* pixels per row for Fly-Estimation */ +#define FE_HEIGHT 500 /* number of rows for Fly-Estimation */ +#define FE_SIZE 64000 /* size in bytes (4 bits per pixels) */ -#define GAIN_SMALL_INIT 0x23 /* Initial small gain */ -#define VRT_MAX 0x3F /* Maximum value for VRT */ -#define VRB_MAX 0x3A /* Maximum value for VRB */ -#define DTVRT_MAX 0x3A /* Maximum value for DTVRT */ -#define DCOFFSET_MIN 0x00 /* Minimum value for DCoffset */ -#define DCOFFSET_MAX 0x35 /* Maximum value for DCoffset */ +#define GAIN_SMALL_INIT 0x23 /* Initial small gain */ +#define VRT_MAX 0x3F /* Maximum value for VRT */ +#define VRB_MAX 0x3A /* Maximum value for VRB */ +#define DTVRT_MAX 0x3A /* Maximum value for DTVRT */ +#define DCOFFSET_MIN 0x00 /* Minimum value for DCoffset */ +#define DCOFFSET_MAX 0x35 /* Maximum value for DCoffset */ /* es603 commands */ -#define CMD_READ_REG 0x01 -#define CMD_WRITE_REG 0x02 -#define CMD_READ_FRAME 0x03 /* Read the sensor area */ -#define CMD_READ_FE 0x06 /* Read a fingerprint using Fly-Estimation */ -#define CMD_20 0x20 /* ? */ -#define CMD_25 0x25 /* ? */ -#define CMD_60 0x60 /* ? */ +#define CMD_READ_REG 0x01 +#define CMD_WRITE_REG 0x02 +#define CMD_READ_FRAME 0x03 /* Read the sensor area */ +#define CMD_READ_FE 0x06 /* Read a fingerprint using Fly-Estimation */ +#define CMD_20 0x20 /* ? */ +#define CMD_25 0x25 /* ? */ +#define CMD_60 0x60 /* ? */ -#define CMD_OK 0x01 /* Command successfully executed */ +#define CMD_OK 0x01 /* Command successfully executed */ /* es603 registers */ -#define REG_MAX 0x18 /* Maximum number of registers in one message */ -#define REG_MODE_CONTROL 0x02 /* Mode control */ -#define REG_03 0x03 /* Contact register? */ -#define REG_04 0x04 /* ? */ -#define REG_10 0x10 /* MVS FRMBUF control */ -#define REG_1A 0x1A /* ? */ +#define REG_MAX 0x18 /* Maximum number of registers in one message */ +#define REG_MODE_CONTROL 0x02 /* Mode control */ +#define REG_03 0x03 /* Contact register? */ +#define REG_04 0x04 /* ? */ +#define REG_10 0x10 /* MVS FRMBUF control */ +#define REG_1A 0x1A /* ? */ /* BEGIN init sensor */ -#define REG_20 0x20 /* (def: 0x00) */ -#define REG_21 0x21 /* Small gain (def: 0x23) */ -#define REG_22 0x22 /* Normal gain (def: 0x21) */ -#define REG_23 0x23 /* Large gain (def: 0x20) */ -#define REG_24 0x24 /* (def: 0x14) */ -#define REG_25 0x25 /* (def: 0x6A) */ -#define REG_26 0x26 /* VRB again? (def: 0x00) */ -#define REG_27 0x27 /* VRT again? (def: 0x00) */ -#define REG_28 0x28 /* (def: 0x00) */ -#define REG_29 0x29 /* (def: 0xC0) */ -#define REG_2A 0x2A /* (def: 0x50) */ -#define REG_2B 0x2B /* (def: 0x50) */ -#define REG_2C 0x2C /* (def: 0x4D) */ -#define REG_2D 0x2D /* (def: 0x03) */ -#define REG_2E 0x2E /* (def: 0x06) */ -#define REG_2F 0x2F /* (def: 0x06) */ -#define REG_30 0x30 /* (def: 0x10) */ -#define REG_31 0x31 /* (def: 0x02) */ -#define REG_32 0x32 /* (def: 0x14) */ -#define REG_33 0x33 /* (def: 0x34) */ -#define REG_34 0x34 /* (def: 0x01) */ -#define REG_35 0x35 /* (def: 0x08) */ -#define REG_36 0x36 /* (def: 0x03) */ -#define REG_37 0x37 /* (def: 0x21) */ +#define REG_20 0x20 /* (def: 0x00) */ +#define REG_21 0x21 /* Small gain (def: 0x23) */ +#define REG_22 0x22 /* Normal gain (def: 0x21) */ +#define REG_23 0x23 /* Large gain (def: 0x20) */ +#define REG_24 0x24 /* (def: 0x14) */ +#define REG_25 0x25 /* (def: 0x6A) */ +#define REG_26 0x26 /* VRB again? (def: 0x00) */ +#define REG_27 0x27 /* VRT again? (def: 0x00) */ +#define REG_28 0x28 /* (def: 0x00) */ +#define REG_29 0x29 /* (def: 0xC0) */ +#define REG_2A 0x2A /* (def: 0x50) */ +#define REG_2B 0x2B /* (def: 0x50) */ +#define REG_2C 0x2C /* (def: 0x4D) */ +#define REG_2D 0x2D /* (def: 0x03) */ +#define REG_2E 0x2E /* (def: 0x06) */ +#define REG_2F 0x2F /* (def: 0x06) */ +#define REG_30 0x30 /* (def: 0x10) */ +#define REG_31 0x31 /* (def: 0x02) */ +#define REG_32 0x32 /* (def: 0x14) */ +#define REG_33 0x33 /* (def: 0x34) */ +#define REG_34 0x34 /* (def: 0x01) */ +#define REG_35 0x35 /* (def: 0x08) */ +#define REG_36 0x36 /* (def: 0x03) */ +#define REG_37 0x37 /* (def: 0x21) */ /* END init sensor */ -#define REG_ENC1 0x41 /* Encryption 1 */ -#define REG_ENC2 0x42 -#define REG_ENC3 0x43 -#define REG_ENC4 0x44 -#define REG_ENC5 0x45 -#define REG_ENC6 0x46 -#define REG_ENC7 0x47 -#define REG_ENC8 0x48 /* Encryption 8 */ +#define REG_ENC1 0x41 /* Encryption 1 */ +#define REG_ENC2 0x42 +#define REG_ENC3 0x43 +#define REG_ENC4 0x44 +#define REG_ENC5 0x45 +#define REG_ENC6 0x46 +#define REG_ENC7 0x47 +#define REG_ENC8 0x48 /* Encryption 8 */ -#define REG_50 0x50 /* ? For contact detection */ -#define REG_51 0x51 /* ? */ -#define REG_59 0x59 /* ? */ -#define REG_5A 0x5A /* ? */ -#define REG_5B 0x5B /* ? */ +#define REG_50 0x50 /* ? For contact detection */ +#define REG_51 0x51 /* ? */ +#define REG_59 0x59 /* ? */ +#define REG_5A 0x5A /* ? */ +#define REG_5B 0x5B /* ? */ -#define REG_INFO0 0x70 /* Sensor model byte0 */ -#define REG_INFO1 0x71 /* Sensor model byte1 */ -#define REG_INFO2 0x72 /* Sensor model byte2 */ -#define REG_INFO3 0x73 /* Sensor model byte3 */ +#define REG_INFO0 0x70 /* Sensor model byte0 */ +#define REG_INFO1 0x71 /* Sensor model byte1 */ +#define REG_INFO2 0x72 /* Sensor model byte2 */ +#define REG_INFO3 0x73 /* Sensor model byte3 */ -#define REG_GAIN 0xE0 -#define REG_VRT 0xE1 -#define REG_VRB 0xE2 -#define REG_DTVRT 0xE3 /* used for contact detection */ -#define REG_VCO_CONTROL 0xE5 /* 0x13 (IDLE?), 0x14 (REALTIME) */ -#define REG_DCOFFSET 0xE6 +#define REG_GAIN 0xE0 +#define REG_VRT 0xE1 +#define REG_VRB 0xE2 +#define REG_DTVRT 0xE3 /* used for contact detection */ +#define REG_VCO_CONTROL 0xE5 /* 0x13 (IDLE?), 0x14 (REALTIME) */ +#define REG_DCOFFSET 0xE6 -#define REG_F0 0xF0 /* ? init:0x00 close:0x01 */ -#define REG_F2 0xF2 /* ? init:0x00 close:0x4E */ +#define REG_F0 0xF0 /* ? init:0x00 close:0x01 */ +#define REG_F2 0xF2 /* ? init:0x00 close:0x4E */ -#define REG_MODE_SLEEP 0x30 /* Sleep mode */ -#define REG_MODE_CONTACT 0x31 /* Contact mode */ -#define REG_MODE_SENSOR 0x33 /* Sensor mode */ -#define REG_MODE_FP 0x34 /* FingerPrint mode (Fly-Estimation®) */ +#define REG_MODE_SLEEP 0x30 /* Sleep mode */ +#define REG_MODE_CONTACT 0x31 /* Contact mode */ +#define REG_MODE_SENSOR 0x33 /* Sensor mode */ +#define REG_MODE_FP 0x34 /* FingerPrint mode (Fly-Estimation®) */ -#define REG_VCO_IDLE 0x13 -#define REG_VCO_RT 0x14 /* Realtime */ +#define REG_VCO_IDLE 0x13 +#define REG_VCO_RT 0x14 /* Realtime */ /* The size of the message header is 5 plus 1 for the command. */ -#define MSG_HDR_SIZE 6 +#define MSG_HDR_SIZE 6 /* This structure must be packed because it is a the raw message sent. */ -struct egis_msg { - uint8_t magic[5]; /* out: 'EGIS' 0x09 / in: 'SIGE' 0x0A */ - uint8_t cmd; - union { - struct { - uint8_t nb; - uint8_t regs[REG_MAX]; - } egis_readreg; - struct { - uint8_t regs[REG_MAX]; - } sige_readreg; - struct { - uint8_t nb; - struct { - uint8_t reg; - uint8_t val; - } regs[REG_MAX]; - } egis_writereg; - struct { - uint8_t length_factor; - uint8_t length; - uint8_t use_gvv; - uint8_t gain; - uint8_t vrt; - uint8_t vrb; - } egis_readf; - struct { - uint8_t len[2]; - uint8_t val[3]; - } egis_readfp; - struct { - uint8_t val[5]; - } sige_misc; - uint8_t padding[0x40-6]; /* Ensure size of 0x40 */ - }; +struct egis_msg +{ + guint8 magic[5]; /* out: 'EGIS' 0x09 / in: 'SIGE' 0x0A */ + guint8 cmd; + union + { + struct + { + guint8 nb; + guint8 regs[REG_MAX]; + } egis_readreg; + struct + { + guint8 regs[REG_MAX]; + } sige_readreg; + struct + { + guint8 nb; + struct + { + guint8 reg; + guint8 val; + } regs[REG_MAX]; + } egis_writereg; + struct + { + guint8 length_factor; + guint8 length; + guint8 use_gvv; + guint8 gain; + guint8 vrt; + guint8 vrb; + } egis_readf; + struct + { + guint8 len[2]; + guint8 val[3]; + } egis_readfp; + struct + { + guint8 val[5]; + } sige_misc; + guint8 padding[0x40 - 6]; /* Ensure size of 0x40 */ + }; } __attribute__((packed)); /* Structure to keep information between asynchronous functions. */ -struct etes603_dev { - uint8_t regs[256]; - struct egis_msg *req; - size_t req_len; - struct egis_msg *ans; - size_t ans_len; +struct _FpiDeviceEtes603 +{ + FpImageDevice parent; - uint8_t *fp; - uint16_t fp_height; + guint8 regs[256]; + struct egis_msg *req; + size_t req_len; + struct egis_msg *ans; + size_t ans_len; - uint8_t tunedc_min; - uint8_t tunedc_max; + guint8 *fp; + guint16 fp_height; - /* Device parameters */ - uint8_t gain; - uint8_t dcoffset; - uint8_t vrt; - uint8_t vrb; + guint8 tunedc_min; + guint8 tunedc_max; - unsigned int is_active; + /* Device parameters */ + guint8 gain; + guint8 dcoffset; + guint8 vrt; + guint8 vrb; + + unsigned int is_active; }; +G_DECLARE_FINAL_TYPE (FpiDeviceEtes603, fpi_device_etes603, FPI, DEVICE_ETES603, + FpImageDevice); +G_DEFINE_TYPE (FpiDeviceEtes603, fpi_device_etes603, FP_TYPE_IMAGE_DEVICE); -static void m_start_fingerdetect(struct fp_img_dev *idev); +static void m_start_fingerdetect (FpImageDevice *idev); /* * Prepare the header of the message to be sent to the device. */ -static void msg_header_prepare(struct egis_msg *msg) +static void +msg_header_prepare (struct egis_msg *msg) { - msg->magic[0] = 'E'; - msg->magic[1] = 'G'; - msg->magic[2] = 'I'; - msg->magic[3] = 'S'; - msg->magic[4] = 0x09; + msg->magic[0] = 'E'; + msg->magic[1] = 'G'; + msg->magic[2] = 'I'; + msg->magic[3] = 'S'; + msg->magic[4] = 0x09; } /* * Check that the header of the received message is correct. */ -static int msg_header_check(struct egis_msg *msg) +static int +msg_header_check (struct egis_msg *msg) { - if (msg->magic[0] == 'S' && msg->magic[1] == 'I' - && msg->magic[2] == 'G' && msg->magic[3] == 'E' - && msg->magic[4] == 0x0A) - return 0; - return -1; + if (msg->magic[0] == 'S' && msg->magic[1] == 'I' && + msg->magic[2] == 'G' && msg->magic[3] == 'E' && + msg->magic[4] == 0x0A) + return 0; + return -1; } /* * Prepare message to ask for a frame. */ -static void msg_get_frame(struct etes603_dev *dev, - uint8_t use_gvv, uint8_t gain, uint8_t vrt, uint8_t vrb) +static void +msg_get_frame (FpiDeviceEtes603 *self, + guint8 use_gvv, guint8 gain, guint8 vrt, + guint8 vrb) { - struct egis_msg *msg = dev->req; - msg_header_prepare(msg); - msg->cmd = CMD_READ_FRAME; - msg->egis_readf.length_factor = 0x01; - /* length should be 0xC0 */ - msg->egis_readf.length = FRAME_WIDTH; - msg->egis_readf.use_gvv = use_gvv; - /* if use_gvv is set, gain/vrt/vrb are used */ - msg->egis_readf.gain = gain; - msg->egis_readf.vrt = vrt; - msg->egis_readf.vrb = vrb; + struct egis_msg *msg = self->req; - dev->req_len = MSG_HDR_SIZE + 6; - dev->ans_len = FRAME_SIZE; + msg_header_prepare (msg); + msg->cmd = CMD_READ_FRAME; + msg->egis_readf.length_factor = 0x01; + /* length should be 0xC0 */ + msg->egis_readf.length = FRAME_WIDTH; + msg->egis_readf.use_gvv = use_gvv; + /* if use_gvv is set, gain/vrt/vrb are used */ + msg->egis_readf.gain = gain; + msg->egis_readf.vrt = vrt; + msg->egis_readf.vrb = vrb; + + self->req_len = MSG_HDR_SIZE + 6; + self->ans_len = FRAME_SIZE; } /* * Prepare message to ask for a fingerprint frame. */ -static void msg_get_fp(struct etes603_dev *dev, uint8_t len0, uint8_t len1, - uint8_t v2, uint8_t v3, uint8_t v4) +static void +msg_get_fp (FpiDeviceEtes603 *self, guint8 len0, guint8 len1, + guint8 v2, guint8 v3, guint8 v4) { - struct egis_msg *msg = dev->req; - msg_header_prepare(msg); - msg->cmd = CMD_READ_FE; - /* Unknown values and always same on captured frames. - * 1st 2nd bytes is unsigned short for height, but only on value range - * 0x01 0xF4 (500), 0x02 0x00 (512), 0x02 0xF4 (756) are ok - */ - msg->egis_readfp.len[0] = len0; - msg->egis_readfp.len[1] = len1; - /* 3rd byte : ?? but changes frame size - * 4th byte : 0x00 -> can change width - * 5th byte : motion sensibility? - */ - msg->egis_readfp.val[0] = v2; - msg->egis_readfp.val[1] = v3; - msg->egis_readfp.val[2] = v4; + struct egis_msg *msg = self->req; - dev->req_len = MSG_HDR_SIZE + 5; - dev->ans_len = FE_SIZE; + msg_header_prepare (msg); + msg->cmd = CMD_READ_FE; + /* Unknown values and always same on captured frames. + * 1st 2nd bytes is unsigned short for height, but only on value range + * 0x01 0xF4 (500), 0x02 0x00 (512), 0x02 0xF4 (756) are ok + */ + msg->egis_readfp.len[0] = len0; + msg->egis_readfp.len[1] = len1; + /* 3rd byte : ?? but changes frame size + * 4th byte : 0x00 -> can change width + * 5th byte : motion sensibility? + */ + msg->egis_readfp.val[0] = v2; + msg->egis_readfp.val[1] = v3; + msg->egis_readfp.val[2] = v4; + + self->req_len = MSG_HDR_SIZE + 5; + self->ans_len = FE_SIZE; } /* * Prepare message to read registers from the sensor. * Variadic argument pattern: int reg, ... */ -static void msg_get_regs(struct etes603_dev *dev, int n_args, ... ) +static void +msg_get_regs (FpiDeviceEtes603 *self, int n_args, ... ) { - struct egis_msg *msg = dev->req; - va_list ap; - int i; + struct egis_msg *msg = self->req; + va_list ap; + int i; - g_assert(n_args > 0 && n_args <= REG_MAX); + g_assert (n_args > 0 && n_args <= REG_MAX); - msg_header_prepare(msg); - msg->cmd = CMD_READ_REG; - msg->egis_readreg.nb = n_args; - va_start(ap, n_args); - for (i = 0; i < n_args; i++) { - msg->egis_readreg.regs[i] = va_arg(ap, int); - } - va_end(ap); + msg_header_prepare (msg); + msg->cmd = CMD_READ_REG; + msg->egis_readreg.nb = n_args; + va_start (ap, n_args); + for (i = 0; i < n_args; i++) + msg->egis_readreg.regs[i] = va_arg (ap, int); + va_end (ap); - dev->req_len = MSG_HDR_SIZE + 1 + n_args; - dev->ans_len = MSG_HDR_SIZE + 1 + n_args; + self->req_len = MSG_HDR_SIZE + 1 + n_args; + self->ans_len = MSG_HDR_SIZE + 1 + n_args; } /* * Parse the result of read register command. */ -static int msg_parse_regs(struct etes603_dev *dev) +static int +msg_parse_regs (FpiDeviceEtes603 *dev) { - size_t i, n_args; - struct egis_msg *msg_req = dev->req; - struct egis_msg *msg_ans = dev->ans; - n_args = dev->ans_len - MSG_HDR_SIZE; + size_t i, n_args; + struct egis_msg *msg_req = dev->req; + struct egis_msg *msg_ans = dev->ans; - if (msg_header_check(msg_ans)) { - return -1; - } - if (msg_ans->cmd != CMD_OK) { - return -2; - } + n_args = dev->ans_len - MSG_HDR_SIZE; - for (i = 0; i < n_args; i++) { - int reg = msg_req->egis_readreg.regs[i]; - dev->regs[reg] = msg_ans->sige_readreg.regs[i]; - } - return 0; + if (msg_header_check (msg_ans)) + return -1; + if (msg_ans->cmd != CMD_OK) + return -2; + + for (i = 0; i < n_args; i++) + { + int reg = msg_req->egis_readreg.regs[i]; + dev->regs[reg] = msg_ans->sige_readreg.regs[i]; + } + return 0; } /* * Prepare message to write sensor's registers. * Variadic arguments are: int reg, int val, ... */ -static void msg_set_regs(struct etes603_dev *dev, int n_args, ...) +static void +msg_set_regs (FpiDeviceEtes603 *self, int n_args, ...) { - struct egis_msg *msg = dev->req; - va_list ap; - int i; + struct egis_msg *msg = self->req; + va_list ap; + int i; - g_assert(n_args != 0 && n_args % 2 == 0 && n_args <= REG_MAX * 2); + g_assert (n_args != 0 && n_args % 2 == 0 && n_args <= REG_MAX * 2); - msg_header_prepare(msg); - msg->cmd = CMD_WRITE_REG; - msg->egis_writereg.nb = n_args / 2; + msg_header_prepare (msg); + msg->cmd = CMD_WRITE_REG; + msg->egis_writereg.nb = n_args / 2; - va_start(ap, n_args); - for (i = 0; i < n_args / 2; i++) { - msg->egis_writereg.regs[i].reg = va_arg(ap, int); - msg->egis_writereg.regs[i].val = va_arg(ap, int); - } - va_end(ap); + va_start (ap, n_args); + for (i = 0; i < n_args / 2; i++) + { + msg->egis_writereg.regs[i].reg = va_arg (ap, int); + msg->egis_writereg.regs[i].val = va_arg (ap, int); + } + va_end (ap); - dev->req_len = MSG_HDR_SIZE + 1 + n_args; - dev->ans_len = MSG_HDR_SIZE + 1; + self->req_len = MSG_HDR_SIZE + 1 + n_args; + self->ans_len = MSG_HDR_SIZE + 1; } -static int msg_check_ok(struct etes603_dev *dev) +static int +msg_check_ok (FpiDeviceEtes603 *dev) { - struct egis_msg *msg = dev->ans; - if (msg_header_check(msg)) { - goto err; - } - if (msg->cmd != CMD_OK) { - goto err; - } - return 0; + struct egis_msg *msg = dev->ans; + + if (msg_header_check (msg)) + goto err; + if (msg->cmd != CMD_OK) + goto err; + return 0; err: - return -1; + return -1; } /* * Check the model of the sensor. */ -static int check_info(struct etes603_dev *dev) +static int +check_info (FpiDeviceEtes603 *dev) { - if (dev->regs[0x70] == 0x4A && dev->regs[0x71] == 0x44 - && dev->regs[0x72] == 0x49 && dev->regs[0x73] == 0x31) - return 0; - fp_err("unknown device parameters (REG_70:%02X REG_71:%02X " - "REG_FIRMWARE:%02X REG_VERSION:%02X)", - dev->regs[0x70], dev->regs[0x71], dev->regs[0x72], - dev->regs[0x73]); - return -1; + if (dev->regs[0x70] == 0x4A && dev->regs[0x71] == 0x44 && + dev->regs[0x72] == 0x49 && dev->regs[0x73] == 0x31) + return 0; + fp_err ("unknown device parameters (REG_70:%02X REG_71:%02X " + "REG_FIRMWARE:%02X REG_VERSION:%02X)", + dev->regs[0x70], dev->regs[0x71], dev->regs[0x72], + dev->regs[0x73]); + return -1; } -static void msg_get_cmd20(struct etes603_dev *dev) +static void +msg_get_cmd20 (FpiDeviceEtes603 *dev) { - struct egis_msg *msg = dev->req; - msg_header_prepare(msg); - msg->cmd = CMD_20; - dev->req_len = MSG_HDR_SIZE; + struct egis_msg *msg = dev->req; + + msg_header_prepare (msg); + msg->cmd = CMD_20; + dev->req_len = MSG_HDR_SIZE; } -static int msg_check_cmd20(struct etes603_dev *dev) +static int +msg_check_cmd20 (FpiDeviceEtes603 *dev) { - struct egis_msg *msg = dev->ans; - if (msg_header_check(msg)) { - fp_err("msg_header_check failed"); - return -1; - } - /* status or flashtype/flashinfo or ? */ - if (msg->cmd != 0x05 - || msg->sige_misc.val[0] != 0x00 - || msg->sige_misc.val[1] != 0x00) { - fp_warn("unexpected answer CMD_20 from device(%02X %02X %02X)", - msg->cmd, msg->sige_misc.val[0], msg->sige_misc.val[1]); - } + struct egis_msg *msg = dev->ans; - return 0; + if (msg_header_check (msg)) + { + fp_err ("msg_header_check failed"); + return -1; + } + /* status or flashtype/flashinfo or ? */ + if (msg->cmd != 0x05 || + msg->sige_misc.val[0] != 0x00 || + msg->sige_misc.val[1] != 0x00) + fp_warn ("unexpected answer CMD_20 from device(%02X %02X %02X)", + msg->cmd, msg->sige_misc.val[0], msg->sige_misc.val[1]); + + return 0; } -static void msg_get_cmd25(struct etes603_dev *dev) +static void +msg_get_cmd25 (FpiDeviceEtes603 *dev) { - struct egis_msg *msg = dev->req; - msg_header_prepare(msg); - msg->cmd = CMD_25; - dev->req_len = MSG_HDR_SIZE; + struct egis_msg *msg = dev->req; + + msg_header_prepare (msg); + msg->cmd = CMD_25; + dev->req_len = MSG_HDR_SIZE; } -static int msg_check_cmd25(struct etes603_dev *dev) +static int +msg_check_cmd25 (FpiDeviceEtes603 *dev) { - struct egis_msg *msg = dev->ans; - if (msg_header_check(msg)) { - fp_err("msg_header_check failed"); - goto err; - } - if (msg->cmd != CMD_OK) { - fp_err("CMD_OK failed"); - goto err; - } - /* flashtype or status or ? */ - if (msg->sige_misc.val[0] != 0x00) { - fp_warn("unexpected answer for CMD_25 (%02X)", - msg->sige_misc.val[0]); - } - return 0; + struct egis_msg *msg = dev->ans; + + if (msg_header_check (msg)) + { + fp_err ("msg_header_check failed"); + goto err; + } + if (msg->cmd != CMD_OK) + { + fp_err ("CMD_OK failed"); + goto err; + } + /* flashtype or status or ? */ + if (msg->sige_misc.val[0] != 0x00) + fp_warn ("unexpected answer for CMD_25 (%02X)", + msg->sige_misc.val[0]); + return 0; err: - return -1; + return -1; } -static void msg_set_mode_control(struct etes603_dev *dev, uint8_t mode) +static void +msg_set_mode_control (FpiDeviceEtes603 *self, guint8 mode) { - msg_set_regs(dev, 2, REG_MODE_CONTROL, mode); + msg_set_regs (self, 2, REG_MODE_CONTROL, mode); } @@ -453,1038 +489,1166 @@ static void msg_set_mode_control(struct etes603_dev *dev, uint8_t mode) /* * Return the brightness of a 4bpp frame */ -static unsigned int process_get_brightness(uint8_t *f, size_t s) +static unsigned int +process_get_brightness (guint8 *f, size_t s) { - unsigned int i, sum = 0; - for (i = 0; i < s; i++) { - sum += f[i] >> 4; - sum += f[i] & 0x0F; - } - return sum; + unsigned int i, sum = 0; + + for (i = 0; i < s; i++) + { + sum += f[i] >> 4; + sum += f[i] & 0x0F; + } + return sum; } /* * Return the histogram of a 4bpp frame */ -static void process_hist(uint8_t *f, size_t s, float stat[5]) +static void +process_hist (guint8 *f, size_t s, float stat[5]) { - float hist[16]; - float black_mean, white_mean; - int i; - /* Clean histogram */ - for (i = 0; i < 16; i++) - hist[i] = 0.0; - for (i = 0; i < s; i++) { - hist[f[i] >> 4]++; - hist[f[i] & 0x0F]++; - } - /* histogram average */ - for (i = 0; i < 16; i++) { - hist[i] = hist[i] / (s * 2); - } - /* Average black/white pixels (full black and full white pixels - * are excluded). */ - black_mean = white_mean = 0.0; - for (i = 1; i < 8; i++) - black_mean += hist[i]; - for (i = 8; i < 15; i++) - white_mean += hist[i]; - stat[0] = hist[0]; - stat[1] = black_mean; - stat[2] = black_mean+white_mean; - stat[3] = white_mean; - stat[4] = hist[15]; - fp_dbg("fullb=%6f black=%6f grey=%6f white=%6f fullw=%6f", - hist[0], black_mean, black_mean+white_mean, white_mean, - hist[15]); + float hist[16]; + float black_mean, white_mean; + int i; + + /* Clean histogram */ + for (i = 0; i < 16; i++) + hist[i] = 0.0; + for (i = 0; i < s; i++) + { + hist[f[i] >> 4]++; + hist[f[i] & 0x0F]++; + } + /* histogram average */ + for (i = 0; i < 16; i++) + hist[i] = hist[i] / (s * 2); + /* Average black/white pixels (full black and full white pixels + * are excluded). */ + black_mean = white_mean = 0.0; + for (i = 1; i < 8; i++) + black_mean += hist[i]; + for (i = 8; i < 15; i++) + white_mean += hist[i]; + stat[0] = hist[0]; + stat[1] = black_mean; + stat[2] = black_mean + white_mean; + stat[3] = white_mean; + stat[4] = hist[15]; + fp_dbg ("fullb=%6f black=%6f grey=%6f white=%6f fullw=%6f", + hist[0], black_mean, black_mean + white_mean, white_mean, + hist[15]); } /* * Return true if the frame is almost empty. */ -static int process_frame_empty(uint8_t *frame, size_t size) +static int +process_frame_empty (guint8 *frame, size_t size) { - unsigned int sum = process_get_brightness(frame, size); - /* Allow an average of 'threshold' luminosity per pixel */ - if (sum < size) - return 1; - return 0; + unsigned int sum = process_get_brightness (frame, size); + + /* Allow an average of 'threshold' luminosity per pixel */ + if (sum < size) + return 1; + return 0; } /* Transform 4 bits image to 8 bits image */ -static void process_4to8_bpp(uint8_t *input, unsigned int input_size, - uint8_t *output) +static void +process_4to8_bpp (guint8 *input, unsigned int input_size, + guint8 *output) { - unsigned int i, j = 0; - for (i = 0; i < input_size; i++, j += 2) { - /* 16 gray levels transform to 256 levels using << 4 */ - output[j] = input[i] & 0xF0; - output[j+1] = input[i] << 4; - } + unsigned int i, j = 0; + + for (i = 0; i < input_size; i++, j += 2) + { + /* 16 gray levels transform to 256 levels using << 4 */ + output[j] = input[i] & 0xF0; + output[j + 1] = input[i] << 4; + } } /* * Remove duplicated lines at the end of a fingerprint. */ -static void process_remove_fp_end(struct etes603_dev *dev) +static void +process_removefpi_end (FpiDeviceEtes603 *dev) { - unsigned int i; - /* 2 last lines with Fly-Estimation are the empty pattern. */ - uint8_t *pattern = dev->fp + (dev->fp_height - 2) * FE_WIDTH / 2; - for (i = 2; i < dev->fp_height; i+= 2) { - if (memcmp(pattern, pattern - (i * FE_WIDTH / 2), FE_WIDTH)) - break; - } - dev->fp_height -= i; - fp_dbg("Removing %d empty lines from image", i - 2); + unsigned int i; + /* 2 last lines with Fly-Estimation are the empty pattern. */ + guint8 *pattern = dev->fp + (dev->fp_height - 2) * FE_WIDTH / 2; + + for (i = 2; i < dev->fp_height; i += 2) + if (memcmp (pattern, pattern - (i * FE_WIDTH / 2), FE_WIDTH)) + break; + dev->fp_height -= i; + fp_dbg ("Removing %d empty lines from image", i - 2); } -static void reset_param(struct etes603_dev *dev) +static void +reset_param (FpiDeviceEtes603 *dev) { - dev->dcoffset = 0; - dev->vrt = 0; - dev->vrb = 0; - dev->gain = 0; + dev->dcoffset = 0; + dev->vrt = 0; + dev->vrb = 0; + dev->gain = 0; } /* Asynchronous stuff */ enum { - INIT_CHECK_INFO_REQ, - INIT_CHECK_INFO_ANS, - INIT_CMD20_REQ, - INIT_CMD20_ANS, - INIT_CMD25_REQ, - INIT_CMD25_ANS, - INIT_SENSOR_REQ, - INIT_SENSOR_ANS, - INIT_ENC_REQ, - INIT_ENC_ANS, - INIT_REGS_REQ, - INIT_REGS_ANS, - INIT_NUM_STATES + INIT_CHECK_INFO_REQ, + INIT_CHECK_INFO_ANS, + INIT_CMD20_REQ, + INIT_CMD20_ANS, + INIT_CMD25_REQ, + INIT_CMD25_ANS, + INIT_SENSOR_REQ, + INIT_SENSOR_ANS, + INIT_ENC_REQ, + INIT_ENC_ANS, + INIT_REGS_REQ, + INIT_REGS_ANS, + INIT_NUM_STATES }; enum { - TUNEDC_INIT, - TUNEDC_SET_DCOFFSET_REQ, - TUNEDC_SET_DCOFFSET_ANS, - TUNEDC_GET_FRAME_REQ, - TUNEDC_GET_FRAME_ANS, - TUNEDC_FINAL_SET_REG2122_REQ, - TUNEDC_FINAL_SET_REG2122_ANS, - TUNEDC_FINAL_SET_GAIN_REQ, - TUNEDC_FINAL_SET_GAIN_ANS, - TUNEDC_FINAL_SET_DCOFFSET_REQ, - TUNEDC_FINAL_SET_DCOFFSET_ANS, - TUNEDC_NUM_STATES + TUNEDC_INIT, + TUNEDC_SET_DCOFFSET_REQ, + TUNEDC_SET_DCOFFSET_ANS, + TUNEDC_GET_FRAME_REQ, + TUNEDC_GET_FRAME_ANS, + TUNEDC_FINAL_SET_REG2122_REQ, + TUNEDC_FINAL_SET_REG2122_ANS, + TUNEDC_FINAL_SET_GAIN_REQ, + TUNEDC_FINAL_SET_GAIN_ANS, + TUNEDC_FINAL_SET_DCOFFSET_REQ, + TUNEDC_FINAL_SET_DCOFFSET_ANS, + TUNEDC_NUM_STATES }; enum { - TUNEVRB_INIT, - TUNEVRB_GET_GAIN_REQ, - TUNEVRB_GET_GAIN_ANS, - TUNEVRB_GET_DCOFFSET_REQ, - TUNEVRB_GET_DCOFFSET_ANS, - TUNEVRB_SET_DCOFFSET_REQ, - TUNEVRB_SET_DCOFFSET_ANS, - TUNEVRB_FRAME_REQ, - TUNEVRB_FRAME_ANS, - TUNEVRB_FINAL_SET_DCOFFSET_REQ, - TUNEVRB_FINAL_SET_DCOFFSET_ANS, - TUNEVRB_FINAL_SET_REG2627_REQ, - TUNEVRB_FINAL_SET_REG2627_ANS, - TUNEVRB_FINAL_SET_GAINVRTVRB_REQ, - TUNEVRB_FINAL_SET_GAINVRTVRB_ANS, - TUNEVRB_FINAL_SET_MODE_SLEEP_REQ, - TUNEVRB_FINAL_SET_MODE_SLEEP_ANS, - TUNEVRB_NUM_STATES + TUNEVRB_INIT, + TUNEVRB_GET_GAIN_REQ, + TUNEVRB_GET_GAIN_ANS, + TUNEVRB_GET_DCOFFSET_REQ, + TUNEVRB_GET_DCOFFSET_ANS, + TUNEVRB_SET_DCOFFSET_REQ, + TUNEVRB_SET_DCOFFSET_ANS, + TUNEVRB_FRAME_REQ, + TUNEVRB_FRAME_ANS, + TUNEVRB_FINAL_SET_DCOFFSET_REQ, + TUNEVRB_FINAL_SET_DCOFFSET_ANS, + TUNEVRB_FINAL_SET_REG2627_REQ, + TUNEVRB_FINAL_SET_REG2627_ANS, + TUNEVRB_FINAL_SET_GAINVRTVRB_REQ, + TUNEVRB_FINAL_SET_GAINVRTVRB_ANS, + TUNEVRB_FINAL_SET_MODE_SLEEP_REQ, + TUNEVRB_FINAL_SET_MODE_SLEEP_ANS, + TUNEVRB_NUM_STATES }; enum { - FGR_FPA_INIT_SET_MODE_SLEEP_REQ, - FGR_FPA_INIT_SET_MODE_SLEEP_ANS, - FGR_FPA_INIT_SET_DCOFFSET_REQ, - FGR_FPA_INIT_SET_DCOFFSET_ANS, - FGR_FPA_INIT_SET_GAINVRTVRB_REQ, - FGR_FPA_INIT_SET_GAINVRTVRB_ANS, - FGR_FPA_INIT_SET_VCO_CONTROL_RT_REQ, - FGR_FPA_INIT_SET_VCO_CONTROL_RT_ANS, - FGR_FPA_INIT_SET_REG04_REQ, - FGR_FPA_INIT_SET_REG04_ANS, - FGR_FPA_INIT_SET_MODE_SENSOR_REQ, - FGR_FPA_INIT_SET_MODE_SENSOR_ANS, - FGR_FPA_GET_FRAME_REQ, - FGR_FPA_GET_FRAME_ANS, - FGR_NUM_STATES + FGR_FPA_INIT_SET_MODE_SLEEP_REQ, + FGR_FPA_INIT_SET_MODE_SLEEP_ANS, + FGR_FPA_INIT_SET_DCOFFSET_REQ, + FGR_FPA_INIT_SET_DCOFFSET_ANS, + FGR_FPA_INIT_SET_GAINVRTVRB_REQ, + FGR_FPA_INIT_SET_GAINVRTVRB_ANS, + FGR_FPA_INIT_SET_VCO_CONTROL_RT_REQ, + FGR_FPA_INIT_SET_VCO_CONTROL_RT_ANS, + FGR_FPA_INIT_SET_REG04_REQ, + FGR_FPA_INIT_SET_REG04_ANS, + FGR_FPA_INIT_SET_MODE_SENSOR_REQ, + FGR_FPA_INIT_SET_MODE_SENSOR_ANS, + FGR_FPA_GET_FRAME_REQ, + FGR_FPA_GET_FRAME_ANS, + FGR_NUM_STATES }; enum { - CAP_FP_INIT_SET_REG10_REQ, - CAP_FP_INIT_SET_REG10_ANS, - CAP_FP_INIT_SET_MODE_FP_REQ, - CAP_FP_INIT_SET_MODE_FP_ANS, - CAP_FP_GET_FP_REQ, - CAP_FP_GET_FP_ANS, - CAP_NUM_STATES + CAP_FP_INIT_SET_REG10_REQ, + CAP_FP_INIT_SET_REG10_ANS, + CAP_FP_INIT_SET_MODE_FP_REQ, + CAP_FP_INIT_SET_MODE_FP_ANS, + CAP_FP_GET_FP_REQ, + CAP_FP_GET_FP_ANS, + CAP_NUM_STATES }; enum { - EXIT_SET_REGS_REQ, - EXIT_SET_REGS_ANS, - EXIT_NUM_STATES + EXIT_SET_REGS_REQ, + EXIT_SET_REGS_ANS, + EXIT_NUM_STATES }; -static int async_tx(struct fp_img_dev *idev, unsigned int ep, void *cb, - void *cb_arg) +static void +async_tx (FpDevice *dev, unsigned int ep, void *cb, + FpiSsm *ssm) { - struct etes603_dev *dev = FP_INSTANCE_DATA(FP_DEV(idev)); - struct libusb_transfer *transfer = fpi_usb_alloc(); - unsigned char *buffer; - int length; + FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev); + FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev); + unsigned char *buffer = NULL; + int length; - if (ep == EP_OUT) { - buffer = (unsigned char *)dev->req; - length = dev->req_len; - } else if (ep == EP_IN) { - buffer = (unsigned char *)dev->ans; - length = dev->ans_len; - } else { - return -EIO; - } - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(idev)), ep, buffer, length, - cb, cb_arg, BULK_TIMEOUT); - - if (libusb_submit_transfer(transfer)) { - libusb_free_transfer(transfer); - return -EIO; - } - return 0; + if (ep == EP_OUT) + { + buffer = (unsigned char *) self->req; + length = self->req_len; + } + else if (ep == EP_IN) + { + buffer = (unsigned char *) self->ans; + length = self->ans_len; + } + else + { + g_assert_not_reached (); + } + transfer->ssm = ssm; + fpi_usb_transfer_fill_bulk_full (transfer, ep, buffer, length, NULL); + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, cb, NULL); + fpi_usb_transfer_unref (transfer); } -static void async_tx_cb(struct libusb_transfer *transfer) +static void +async_tx_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm); - struct etes603_dev *dev = FP_INSTANCE_DATA(FP_DEV(idev)); + FpImageDevice *idev = FP_IMAGE_DEVICE (device); + FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (idev); - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fp_warn("transfer is not completed (status=%d)", - transfer->status); - fpi_ssm_mark_failed(ssm, -EIO); - libusb_free_transfer(transfer); - } else { - unsigned char endpoint = transfer->endpoint; - int actual_length = transfer->actual_length; - int length = transfer->length; - /* Freeing now transfer since fpi_ssm_* functions are not - * returning directly. */ - libusb_free_transfer(transfer); - if (endpoint == EP_OUT) { - if (length != actual_length) - fp_warn("length %d != actual_length %d", - length, actual_length); - /* Chained with the answer */ - if (async_tx(idev, EP_IN, async_tx_cb, ssm)) - fpi_ssm_mark_failed(ssm, -EIO); - } else if (endpoint == EP_IN) { - dev->ans_len = actual_length; - fpi_ssm_next_state(ssm); - } - } + if (error) + { + fp_warn ("transfer is not completed (result: %s)", + error->message); + fpi_ssm_mark_failed (transfer->ssm, error); + } + else + { + unsigned char endpoint = transfer->endpoint; + int actual_length = transfer->actual_length; + int length = transfer->length; + + if (endpoint == EP_OUT) + { + if (length != actual_length) + fp_warn ("length %d != actual_length %d", + length, actual_length); + + /* Chained with the answer */ + async_tx (device, EP_IN, async_tx_cb, transfer->ssm); + } + else if (endpoint == EP_IN) + { + self->ans_len = actual_length; + fpi_ssm_next_state (transfer->ssm); + } + } } -static void m_exit_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_exit_state (FpiSsm *ssm, FpDevice *dev) { - struct fp_img_dev *idev = user_data; - struct etes603_dev *dev = FP_INSTANCE_DATA(_dev); + FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case EXIT_SET_REGS_REQ: - msg_set_regs(dev, 4, REG_VCO_CONTROL, REG_VCO_IDLE, - REG_MODE_CONTROL, REG_MODE_SLEEP); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case EXIT_SET_REGS_ANS: - if (msg_check_ok(dev)) - goto err; - fpi_ssm_mark_completed(ssm); - break; - default: - fp_err("Unknown state %d", fpi_ssm_get_cur_state(ssm)); - goto err; - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case EXIT_SET_REGS_REQ: + msg_set_regs (self, 4, REG_VCO_CONTROL, REG_VCO_IDLE, + REG_MODE_CONTROL, REG_MODE_SLEEP); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; - return; + case EXIT_SET_REGS_ANS: + if (msg_check_ok (self)) + goto err; + fpi_ssm_mark_completed (ssm); + break; + + default: + g_assert_not_reached (); + break; + } + + return; err: - fpi_ssm_mark_failed(ssm, -EIO); + fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); } -static void m_exit_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_exit_complete (FpiSsm *ssm, FpDevice *dev, GError *error) { - struct fp_img_dev *idev = user_data; + FpImageDevice *idev = FP_IMAGE_DEVICE (dev); - if (fpi_ssm_get_error(ssm)) { - fp_err("Error switching the device to idle state"); - } else { - fp_dbg("The device is now in idle state"); - } - fpi_imgdev_deactivate_complete(idev); - fpi_ssm_free(ssm); + if (error) + fp_err ("Error switching the device to idle state"); + else + fp_dbg ("The device is now in idle state"); + fpi_image_device_deactivate_complete (idev, error); + fpi_ssm_free (ssm); } -static void m_exit_start(struct fp_img_dev *idev) +static void +m_exit_start (FpImageDevice *idev) { - fpi_ssm *ssm = fpi_ssm_new(FP_DEV(idev), m_exit_state, - EXIT_NUM_STATES, idev); - fp_dbg("Switching device to idle mode"); - fpi_ssm_start(ssm, m_exit_complete); + FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (idev); + FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (idev), m_exit_state, EXIT_NUM_STATES); + + self->is_active = FALSE; + fp_dbg ("Switching device to idle mode"); + fpi_ssm_start (ssm, m_exit_complete); } -static void m_capture_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_capture_state (FpiSsm *ssm, FpDevice *dev) { - struct fp_img_dev *idev = user_data; - struct etes603_dev *dev = FP_INSTANCE_DATA(_dev); + FpImageDevice *idev = FP_IMAGE_DEVICE (dev); + FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev); - if (dev->is_active == FALSE) { - fpi_ssm_mark_completed(ssm); - return; - } + if (self->is_active == FALSE) + { + fpi_ssm_mark_completed (ssm); + return; + } - switch (fpi_ssm_get_cur_state(ssm)) { - case CAP_FP_INIT_SET_REG10_REQ: - /* Reset fingerprint */ - fp_dbg("Capturing a fingerprint..."); - memset(dev->fp, 0, FE_SIZE * 2); - dev->fp_height = 0; - msg_set_regs(dev, 2, REG_10, 0x92); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case CAP_FP_INIT_SET_REG10_ANS: - if (msg_check_ok(dev)) - goto err; - fpi_ssm_next_state(ssm); - break; - case CAP_FP_INIT_SET_MODE_FP_REQ: - msg_set_mode_control(dev, REG_MODE_FP); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case CAP_FP_INIT_SET_MODE_FP_ANS: - if (msg_check_ok(dev)) - goto err; - fp_dbg("Capturing a 1st frame..."); - fpi_ssm_next_state(ssm); - break; - case CAP_FP_GET_FP_REQ: - msg_get_fp(dev, 0x01, 0xF4, 0x02, 0x01, 0x64); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case CAP_FP_GET_FP_ANS: - memcpy(dev->fp + dev->fp_height * FE_WIDTH / 2, dev->ans, - FE_SIZE); - dev->fp_height += FE_HEIGHT; - if (dev->fp_height <= FE_HEIGHT) { - /* 2 lines are at least removed each time */ - dev->fp_height -= 2; - fp_dbg("Capturing a 2nd frame..."); - fpi_ssm_jump_to_state(ssm, CAP_FP_GET_FP_REQ); - } else { - struct fp_img *img; - unsigned int img_size; - /* Remove empty parts 2 times for the 2 frames */ - process_remove_fp_end(dev); - process_remove_fp_end(dev); - img_size = dev->fp_height * FE_WIDTH; - img = fpi_img_new(img_size); - /* Images received are white on black, so invert it. */ - /* TODO detect sweep direction */ - img->flags = FP_IMG_COLORS_INVERTED | FP_IMG_V_FLIPPED; - img->height = dev->fp_height; - process_4to8_bpp(dev->fp, img_size / 2, img->data); - fp_dbg("Sending the raw fingerprint image (%dx%d)", - img->width, img->height); - fpi_imgdev_image_captured(idev, img); - fpi_imgdev_report_finger_status(idev, FALSE); - fpi_ssm_mark_completed(ssm); - } - break; - default: - fp_err("Unknown state %d", fpi_ssm_get_cur_state(ssm)); - goto err; - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case CAP_FP_INIT_SET_REG10_REQ: + /* Reset fingerprint */ + fp_dbg ("Capturing a fingerprint..."); + memset (self->fp, 0, FE_SIZE * 2); + self->fp_height = 0; + msg_set_regs (self, 2, REG_10, 0x92); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; - return; + case CAP_FP_INIT_SET_REG10_ANS: + if (msg_check_ok (self)) + goto err; + fpi_ssm_next_state (ssm); + break; + + case CAP_FP_INIT_SET_MODE_FP_REQ: + msg_set_mode_control (self, REG_MODE_FP); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case CAP_FP_INIT_SET_MODE_FP_ANS: + if (msg_check_ok (self)) + goto err; + fp_dbg ("Capturing a 1st frame..."); + fpi_ssm_next_state (ssm); + break; + + case CAP_FP_GET_FP_REQ: + msg_get_fp (self, 0x01, 0xF4, 0x02, 0x01, 0x64); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case CAP_FP_GET_FP_ANS: + memcpy (self->fp + self->fp_height * FE_WIDTH / 2, self->ans, + FE_SIZE); + self->fp_height += FE_HEIGHT; + if (self->fp_height <= FE_HEIGHT) + { + /* 2 lines are at least removed each time */ + self->fp_height -= 2; + fp_dbg ("Capturing a 2nd frame..."); + fpi_ssm_jump_to_state (ssm, CAP_FP_GET_FP_REQ); + } + else + { + FpImage *img; + unsigned int img_size; + /* Remove empty parts 2 times for the 2 frames */ + process_removefpi_end (self); + process_removefpi_end (self); + img_size = self->fp_height * FE_WIDTH; + img = fp_image_new (FE_WIDTH, self->fp_height); + /* Images received are white on black, so invert it. */ + /* TODO detect sweep direction */ + img->flags = FPI_IMAGE_COLORS_INVERTED | FPI_IMAGE_V_FLIPPED; + img->height = self->fp_height; + process_4to8_bpp (self->fp, img_size / 2, img->data); + fp_dbg ("Sending the raw fingerprint image (%dx%d)", + img->width, img->height); + fpi_image_device_image_captured (idev, img); + fpi_image_device_report_finger_status (idev, FALSE); + fpi_ssm_mark_completed (ssm); + } + break; + + default: + g_assert_not_reached (); + break; + } + + return; err: - fpi_ssm_mark_failed(ssm, -EIO); + fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); } -static void m_capture_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_capture_complete (FpiSsm *ssm, FpDevice *dev, GError *error) { - struct fp_img_dev *idev = user_data; - struct etes603_dev *dev = FP_INSTANCE_DATA(_dev); + FpImageDevice *idev = FP_IMAGE_DEVICE (dev); + FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev); - if (fpi_ssm_get_error(ssm)) { - if (fpi_imgdev_get_action_state(idev) != IMG_ACQUIRE_STATE_DEACTIVATING) { - fp_err("Error while capturing fingerprint " - "(fpi_ssm_get_error(ssm)=%d)", fpi_ssm_get_error(ssm)); - fpi_imgdev_session_error(idev, fpi_ssm_get_error(ssm)); - } - } - fpi_ssm_free(ssm); + if (error) + { + if (self->is_active) + { + fp_err ("Error while capturing fingerprint " + "(%s)", error->message); + fpi_image_device_session_error (idev, error); + } + else + { + g_error_free (error); + } + } + fpi_ssm_free (ssm); - if (dev->is_active == TRUE) { - fp_dbg("Device is still active, restarting finger detection"); - m_start_fingerdetect(idev); - } else { - fp_dbg("And it's over."); - } + if (self->is_active == TRUE) + { + fp_dbg ("Device is still active, restarting finger detection"); + m_start_fingerdetect (idev); + } + else + { + fp_dbg ("And it's over."); + m_exit_start (idev); + } } -static void m_finger_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_finger_state (FpiSsm *ssm, FpDevice *dev) { - struct fp_img_dev *idev = user_data; - struct etes603_dev *dev = FP_INSTANCE_DATA(_dev); + FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev); - if (dev->is_active == FALSE) { - fpi_ssm_mark_completed(ssm); - return; - } + if (self->is_active == FALSE) + { + fpi_ssm_mark_completed (ssm); + return; + } - switch (fpi_ssm_get_cur_state(ssm)) { - case FGR_FPA_INIT_SET_MODE_SLEEP_REQ: - msg_set_mode_control(dev, REG_MODE_SLEEP); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case FGR_FPA_INIT_SET_MODE_SLEEP_ANS: - if (msg_check_ok(dev)) - goto err; - fpi_ssm_next_state(ssm); - break; - case FGR_FPA_INIT_SET_DCOFFSET_REQ: - msg_set_regs(dev, 2, REG_DCOFFSET, dev->dcoffset); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case FGR_FPA_INIT_SET_DCOFFSET_ANS: - if (msg_check_ok(dev)) - goto err; - fpi_ssm_next_state(ssm); - break; - case FGR_FPA_INIT_SET_GAINVRTVRB_REQ: - msg_set_regs(dev, 6, REG_GAIN, dev->gain, REG_VRT, dev->vrt, - REG_VRB, dev->vrb); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case FGR_FPA_INIT_SET_GAINVRTVRB_ANS: - if (msg_check_ok(dev)) - goto err; - fpi_ssm_next_state(ssm); - break; - case FGR_FPA_INIT_SET_VCO_CONTROL_RT_REQ: - msg_set_regs(dev, 2, REG_VCO_CONTROL, REG_VCO_RT); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case FGR_FPA_INIT_SET_VCO_CONTROL_RT_ANS: - if (msg_check_ok(dev)) - goto err; - fpi_ssm_next_state(ssm); - break; - case FGR_FPA_INIT_SET_REG04_REQ: - msg_set_regs(dev, 2, REG_04, 0x00); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case FGR_FPA_INIT_SET_REG04_ANS: - if (msg_check_ok(dev)) - goto err; - fpi_ssm_next_state(ssm); - break; - case FGR_FPA_INIT_SET_MODE_SENSOR_REQ: - msg_set_mode_control(dev, REG_MODE_SENSOR); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case FGR_FPA_INIT_SET_MODE_SENSOR_ANS: - if (msg_check_ok(dev)) - goto err; - fpi_ssm_next_state(ssm); - break; - case FGR_FPA_GET_FRAME_REQ: - msg_get_frame(dev, 0x00, 0x00, 0x00, 0x00); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case FGR_FPA_GET_FRAME_ANS: - if (process_frame_empty((uint8_t *)dev->ans, FRAME_SIZE)) { - fpi_ssm_jump_to_state(ssm, FGR_FPA_GET_FRAME_REQ); - } else { - fpi_imgdev_report_finger_status(idev, TRUE); - fpi_ssm_mark_completed(ssm); - } - break; - default: - fp_err("Unknown state %d", fpi_ssm_get_cur_state(ssm)); - goto err; - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case FGR_FPA_INIT_SET_MODE_SLEEP_REQ: + msg_set_mode_control (self, REG_MODE_SLEEP); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; - return; + case FGR_FPA_INIT_SET_MODE_SLEEP_ANS: + if (msg_check_ok (self)) + goto err; + fpi_ssm_next_state (ssm); + break; + + case FGR_FPA_INIT_SET_DCOFFSET_REQ: + msg_set_regs (self, 2, REG_DCOFFSET, self->dcoffset); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case FGR_FPA_INIT_SET_DCOFFSET_ANS: + if (msg_check_ok (self)) + goto err; + fpi_ssm_next_state (ssm); + break; + + case FGR_FPA_INIT_SET_GAINVRTVRB_REQ: + msg_set_regs (self, 6, REG_GAIN, self->gain, REG_VRT, + self->vrt, + REG_VRB, self->vrb); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case FGR_FPA_INIT_SET_GAINVRTVRB_ANS: + if (msg_check_ok (self)) + goto err; + fpi_ssm_next_state (ssm); + break; + + case FGR_FPA_INIT_SET_VCO_CONTROL_RT_REQ: + msg_set_regs (self, 2, REG_VCO_CONTROL, REG_VCO_RT); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case FGR_FPA_INIT_SET_VCO_CONTROL_RT_ANS: + if (msg_check_ok (self)) + goto err; + fpi_ssm_next_state (ssm); + break; + + case FGR_FPA_INIT_SET_REG04_REQ: + msg_set_regs (self, 2, REG_04, 0x00); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case FGR_FPA_INIT_SET_REG04_ANS: + if (msg_check_ok (self)) + goto err; + fpi_ssm_next_state (ssm); + break; + + case FGR_FPA_INIT_SET_MODE_SENSOR_REQ: + msg_set_mode_control (self, REG_MODE_SENSOR); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case FGR_FPA_INIT_SET_MODE_SENSOR_ANS: + if (msg_check_ok (self)) + goto err; + fpi_ssm_next_state (ssm); + break; + + case FGR_FPA_GET_FRAME_REQ: + msg_get_frame (self, 0x00, 0x00, 0x00, 0x00); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case FGR_FPA_GET_FRAME_ANS: + if (process_frame_empty ((guint8 *) self->ans, FRAME_SIZE)) + { + fpi_ssm_jump_to_state (ssm, FGR_FPA_GET_FRAME_REQ); + } + else + { + fpi_image_device_report_finger_status (FP_IMAGE_DEVICE (dev), TRUE); + fpi_ssm_mark_completed (ssm); + } + break; + + default: + g_assert_not_reached (); + break; + } + + return; err: - fpi_ssm_mark_failed(ssm, -EIO); + fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); } -static void m_finger_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_finger_complete (FpiSsm *ssm, FpDevice *dev, GError *error) { - struct fp_img_dev *idev = user_data; - struct etes603_dev *dev = FP_INSTANCE_DATA(_dev); + FpImageDevice *idev = FP_IMAGE_DEVICE (dev); + FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev); - if (!fpi_ssm_get_error(ssm)) { - fpi_ssm *ssm_cap; - ssm_cap = fpi_ssm_new(FP_DEV(idev), m_capture_state, - CAP_NUM_STATES, idev); - fpi_ssm_start(ssm_cap, m_capture_complete); - } else { - if (fpi_imgdev_get_action_state(idev) != IMG_ACQUIRE_STATE_DEACTIVATING) { - fp_err("Error while capturing fingerprint " - "(fpi_ssm_get_error(ssm)=%d)", fpi_ssm_get_error(ssm)); - fpi_imgdev_session_error(idev, -4); - } - dev->is_active = FALSE; - } + if (!error) + { + FpiSsm *ssm_cap; + ssm_cap = fpi_ssm_new (dev, m_capture_state, CAP_NUM_STATES); + fpi_ssm_start (ssm_cap, m_capture_complete); + } + else + { + if (self->is_active) + { + fp_err ("Error while capturing fingerprint " + "(%s)", error->message); + fpi_image_device_session_error (idev, error); + } + else + { + m_exit_start (idev); + g_error_free (error); + } + self->is_active = FALSE; + } - fpi_ssm_free(ssm); + fpi_ssm_free (ssm); } -static void m_start_fingerdetect(struct fp_img_dev *idev) +static void +m_start_fingerdetect (FpImageDevice *idev) { - fpi_ssm *ssmf; - ssmf = fpi_ssm_new(FP_DEV(idev), m_finger_state, FGR_NUM_STATES, idev); - fpi_ssm_start(ssmf, m_finger_complete); + FpiSsm *ssmf; + + ssmf = fpi_ssm_new (FP_DEVICE (idev), m_finger_state, FGR_NUM_STATES); + fpi_ssm_start (ssmf, m_finger_complete); } /* * Tune value of VRT and VRB for contrast and brightness. */ -static void m_tunevrb_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_tunevrb_state (FpiSsm *ssm, FpDevice *dev) { - struct fp_img_dev *idev = user_data; - struct etes603_dev *dev = FP_INSTANCE_DATA(_dev); - float hist[5]; + FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev); + float hist[5]; - if (dev->is_active == FALSE) { - fpi_ssm_mark_completed(ssm); - return; - } + if (self->is_active == FALSE) + { + fpi_ssm_mark_completed (ssm); + return; + } - switch (fpi_ssm_get_cur_state(ssm)) { - case TUNEVRB_INIT: - fp_dbg("Tuning of VRT/VRB"); - g_assert(dev->dcoffset); - /* VRT(reg E1)=0x0A and VRB(reg E2)=0x10 are starting values */ - dev->vrt = 0x0A; - dev->vrb = 0x10; - fpi_ssm_next_state(ssm); - break; - case TUNEVRB_GET_GAIN_REQ: - msg_get_regs(dev, 1, REG_GAIN); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case TUNEVRB_GET_GAIN_ANS: - if (msg_parse_regs(dev)) - goto err; - fpi_ssm_next_state(ssm); - break; - case TUNEVRB_GET_DCOFFSET_REQ: - msg_get_regs(dev, 1, REG_DCOFFSET); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case TUNEVRB_GET_DCOFFSET_ANS: - if (msg_parse_regs(dev)) - goto err; - fpi_ssm_next_state(ssm); - break; - case TUNEVRB_SET_DCOFFSET_REQ: - /* Reduce DCoffset by 1 to allow tuning */ - msg_set_regs(dev, 2, REG_DCOFFSET, dev->dcoffset - 1); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case TUNEVRB_SET_DCOFFSET_ANS: - if (msg_check_ok(dev)) - goto err; - fpi_ssm_next_state(ssm); - break; - case TUNEVRB_FRAME_REQ: - fp_dbg("Testing VRT=0x%02X VRB=0x%02X", dev->vrt, dev->vrb); - msg_get_frame(dev, 0x01, dev->gain, dev->vrt, dev->vrb); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case TUNEVRB_FRAME_ANS: - process_hist((uint8_t *)dev->ans, FRAME_SIZE, hist); - /* Note that this tuning could probably be improved */ - if (hist[0] + hist[1] > 0.95) { - if (dev->vrt <= 0 || dev->vrb <= 0) { - fp_dbg("Image is too dark, reducing DCOffset"); - dev->dcoffset--; - fpi_ssm_jump_to_state(ssm, TUNEVRB_INIT); - } else { - dev->vrt--; - dev->vrb--; - fpi_ssm_jump_to_state(ssm, TUNEVRB_FRAME_REQ); - } - break; - } - if (hist[4] > 0.95) { - fp_dbg("Image is too bright, increasing DCOffset"); - dev->dcoffset++; - fpi_ssm_jump_to_state(ssm, TUNEVRB_INIT); - break; - } - if (hist[4] + hist[3] > 0.4) { - if (dev->vrt >= 2 * dev->vrb - 0x0a) { - dev->vrt++; dev->vrb++; - } else { - dev->vrt++; - } - /* Check maximum for vrt/vrb */ - /* TODO if maximum is reached, leave with an error? */ - if (dev->vrt > VRT_MAX) - dev->vrt = VRT_MAX; - if (dev->vrb > VRB_MAX) - dev->vrb = VRB_MAX; - fpi_ssm_jump_to_state(ssm, TUNEVRB_FRAME_REQ); - break; - } - fpi_ssm_next_state(ssm); - break; - case TUNEVRB_FINAL_SET_DCOFFSET_REQ: - fp_dbg("-> VRT=0x%02X VRB=0x%02X", dev->vrt, dev->vrb); - /* Reset the DCOffset */ - msg_set_regs(dev, 2, REG_DCOFFSET, dev->dcoffset); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case TUNEVRB_FINAL_SET_DCOFFSET_ANS: - if (msg_check_ok(dev)) - goto err; - fpi_ssm_next_state(ssm); - break; - case TUNEVRB_FINAL_SET_REG2627_REQ: - /* In traces, REG_26/REG_27 are set. purpose? values? */ - msg_set_regs(dev, 4, REG_26, 0x11, REG_27, 0x00); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case TUNEVRB_FINAL_SET_REG2627_ANS: - if (msg_check_ok(dev)) - goto err; - fpi_ssm_next_state(ssm); - break; - case TUNEVRB_FINAL_SET_GAINVRTVRB_REQ: - /* Set Gain/VRT/VRB values found */ - msg_set_regs(dev, 6, REG_GAIN, dev->gain, REG_VRT, dev->vrt, - REG_VRB, dev->vrb); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case TUNEVRB_FINAL_SET_GAINVRTVRB_ANS: - if (msg_check_ok(dev)) - goto err; - /* In traces, Gain/VRT/VRB are read again. */ - fpi_ssm_next_state(ssm); - break; - case TUNEVRB_FINAL_SET_MODE_SLEEP_REQ: - msg_set_mode_control(dev, REG_MODE_SLEEP); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case TUNEVRB_FINAL_SET_MODE_SLEEP_ANS: - if (msg_check_ok(dev)) - goto err; - fpi_ssm_mark_completed(ssm); - break; - default: - fp_err("Unknown state %d", fpi_ssm_get_cur_state(ssm)); - goto err; - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case TUNEVRB_INIT: + fp_dbg ("Tuning of VRT/VRB"); + g_assert (self->dcoffset); + /* VRT(reg E1)=0x0A and VRB(reg E2)=0x10 are starting values */ + self->vrt = 0x0A; + self->vrb = 0x10; + fpi_ssm_next_state (ssm); + break; - return; + case TUNEVRB_GET_GAIN_REQ: + msg_get_regs (self, 1, REG_GAIN); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case TUNEVRB_GET_GAIN_ANS: + if (msg_parse_regs (self)) + goto err; + fpi_ssm_next_state (ssm); + break; + + case TUNEVRB_GET_DCOFFSET_REQ: + msg_get_regs (self, 1, REG_DCOFFSET); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case TUNEVRB_GET_DCOFFSET_ANS: + if (msg_parse_regs (self)) + goto err; + fpi_ssm_next_state (ssm); + break; + + case TUNEVRB_SET_DCOFFSET_REQ: + /* Reduce DCoffset by 1 to allow tuning */ + msg_set_regs (self, 2, REG_DCOFFSET, self->dcoffset - 1); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case TUNEVRB_SET_DCOFFSET_ANS: + if (msg_check_ok (self)) + goto err; + fpi_ssm_next_state (ssm); + break; + + case TUNEVRB_FRAME_REQ: + fp_dbg ("Testing VRT=0x%02X VRB=0x%02X", self->vrt, self->vrb); + msg_get_frame (self, 0x01, self->gain, self->vrt, self->vrb); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case TUNEVRB_FRAME_ANS: + process_hist ((guint8 *) self->ans, FRAME_SIZE, hist); + /* Note that this tuning could probably be improved */ + if (hist[0] + hist[1] > 0.95) + { + if (self->vrt <= 0 || self->vrb <= 0) + { + fp_dbg ("Image is too dark, reducing DCOffset"); + self->dcoffset--; + fpi_ssm_jump_to_state (ssm, TUNEVRB_INIT); + } + else + { + self->vrt--; + self->vrb--; + fpi_ssm_jump_to_state (ssm, TUNEVRB_FRAME_REQ); + } + break; + } + if (hist[4] > 0.95) + { + fp_dbg ("Image is too bright, increasing DCOffset"); + self->dcoffset++; + fpi_ssm_jump_to_state (ssm, TUNEVRB_INIT); + break; + } + if (hist[4] + hist[3] > 0.4) + { + if (self->vrt >= 2 * self->vrb - 0x0a) + { + self->vrt++; + self->vrb++; + } + else + { + self->vrt++; + } + /* Check maximum for vrt/vrb */ + /* TODO if maximum is reached, leave with an error? */ + if (self->vrt > VRT_MAX) + self->vrt = VRT_MAX; + if (self->vrb > VRB_MAX) + self->vrb = VRB_MAX; + fpi_ssm_jump_to_state (ssm, TUNEVRB_FRAME_REQ); + break; + } + fpi_ssm_next_state (ssm); + break; + + case TUNEVRB_FINAL_SET_DCOFFSET_REQ: + fp_dbg ("-> VRT=0x%02X VRB=0x%02X", self->vrt, self->vrb); + /* Reset the DCOffset */ + msg_set_regs (self, 2, REG_DCOFFSET, self->dcoffset); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case TUNEVRB_FINAL_SET_DCOFFSET_ANS: + if (msg_check_ok (self)) + goto err; + fpi_ssm_next_state (ssm); + break; + + case TUNEVRB_FINAL_SET_REG2627_REQ: + /* In traces, REG_26/REG_27 are set. purpose? values? */ + msg_set_regs (self, 4, REG_26, 0x11, REG_27, 0x00); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case TUNEVRB_FINAL_SET_REG2627_ANS: + if (msg_check_ok (self)) + goto err; + fpi_ssm_next_state (ssm); + break; + + case TUNEVRB_FINAL_SET_GAINVRTVRB_REQ: + /* Set Gain/VRT/VRB values found */ + msg_set_regs (self, 6, REG_GAIN, self->gain, REG_VRT, + self->vrt, + REG_VRB, self->vrb); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case TUNEVRB_FINAL_SET_GAINVRTVRB_ANS: + if (msg_check_ok (self)) + goto err; + /* In traces, Gain/VRT/VRB are read again. */ + fpi_ssm_next_state (ssm); + break; + + case TUNEVRB_FINAL_SET_MODE_SLEEP_REQ: + msg_set_mode_control (self, REG_MODE_SLEEP); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case TUNEVRB_FINAL_SET_MODE_SLEEP_ANS: + if (msg_check_ok (self)) + goto err; + fpi_ssm_mark_completed (ssm); + break; + + default: + g_assert_not_reached (); + break; + } + + return; err: - fpi_ssm_mark_failed(ssm, -EIO); + fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); } -static void m_tunevrb_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_tunevrb_complete (FpiSsm *ssm, FpDevice *dev, GError *error) { - struct fp_img_dev *idev = user_data; + FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev); + FpImageDevice *idev = FP_IMAGE_DEVICE (dev); - fpi_imgdev_activate_complete(idev, fpi_ssm_get_error(ssm) != 0); - if (!fpi_ssm_get_error(ssm)) { - fp_dbg("Tuning is done. Starting finger detection."); - m_start_fingerdetect(idev); - } else { - struct etes603_dev *dev = FP_INSTANCE_DATA(_dev); - fp_err("Error while tuning VRT"); - dev->is_active = FALSE; - reset_param(dev); - fpi_imgdev_session_error(idev, -3); - } - fpi_ssm_free(ssm); + fpi_image_device_activate_complete (idev, error); + if (!error) + { + fp_dbg ("Tuning is done. Starting finger detection."); + m_start_fingerdetect (idev); + } + + if (!self->is_active) + m_exit_start (idev); + + fpi_ssm_free (ssm); } /* * This function tunes the DCoffset value and adjusts the gain value if * required. */ -static void m_tunedc_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_tunedc_state (FpiSsm *ssm, FpDevice *dev) { - struct fp_img_dev *idev = user_data; - struct etes603_dev *dev = FP_INSTANCE_DATA(_dev); + FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev); - if (dev->is_active == FALSE) { - fpi_ssm_mark_completed(ssm); - return; - } + if (self->is_active == FALSE) + { + fpi_ssm_mark_completed (ssm); + return; + } - /* TODO To get better results, tuning could be done 3 times as in - * captured traffic to make sure that the value is correct. */ - /* The default gain should work but it may reach a DCOffset limit so in - * this case we decrease the gain. */ - switch (fpi_ssm_get_cur_state(ssm)) { - case TUNEDC_INIT: - /* reg_e0 = 0x23 is sensor normal/small gain */ - dev->gain = GAIN_SMALL_INIT; - dev->tunedc_min = DCOFFSET_MIN; - dev->tunedc_max = DCOFFSET_MAX; - fp_dbg("Tuning DCoffset"); - fpi_ssm_next_state(ssm); - break; - case TUNEDC_SET_DCOFFSET_REQ: - /* Dichotomic search to find at which value the frame becomes - * almost black. */ - dev->dcoffset = (dev->tunedc_max + dev->tunedc_min) / 2; - fp_dbg("Testing DCoffset=0x%02X Gain=0x%02X", dev->dcoffset, - dev->gain); - msg_set_regs(dev, 2, REG_DCOFFSET, dev->dcoffset); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case TUNEDC_SET_DCOFFSET_ANS: - if (msg_check_ok(dev)) - goto err; - fpi_ssm_next_state(ssm); - break; - case TUNEDC_GET_FRAME_REQ: - /* vrt:0x15 vrb:0x10 are constant in all tuning frames. */ - msg_get_frame(dev, 0x01, dev->gain, 0x15, 0x10); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case TUNEDC_GET_FRAME_ANS: - if (process_frame_empty((uint8_t *)dev->ans, FRAME_WIDTH)) - dev->tunedc_max = dev->dcoffset; - else - dev->tunedc_min = dev->dcoffset; - if (dev->tunedc_min + 1 < dev->tunedc_max) { - fpi_ssm_jump_to_state(ssm, TUNEDC_SET_DCOFFSET_REQ); - } else if (dev->tunedc_max < DCOFFSET_MAX) { - dev->dcoffset = dev->tunedc_max + 1; - fpi_ssm_next_state(ssm); - } else { - dev->gain--; - fpi_ssm_jump_to_state(ssm, TUNEDC_SET_DCOFFSET_REQ); - } - break; - case TUNEDC_FINAL_SET_REG2122_REQ: - fp_dbg("-> DCoffset=0x%02X Gain=0x%02X", dev->dcoffset, - dev->gain); - /* ??? how reg21 / reg22 are calculated */ - msg_set_regs(dev, 4, REG_21, 0x23, REG_22, 0x21); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case TUNEDC_FINAL_SET_REG2122_ANS: - if (msg_check_ok(dev)) - goto err; - fpi_ssm_next_state(ssm); - break; - case TUNEDC_FINAL_SET_GAIN_REQ: - msg_set_regs(dev, 2, REG_GAIN, dev->gain); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case TUNEDC_FINAL_SET_GAIN_ANS: - fpi_ssm_next_state(ssm); - break; - case TUNEDC_FINAL_SET_DCOFFSET_REQ: - msg_set_regs(dev, 2, REG_DCOFFSET, dev->dcoffset); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case TUNEDC_FINAL_SET_DCOFFSET_ANS: - /* In captured traffic, read GAIN, VRT, and VRB registers. */ - if (msg_check_ok(dev)) - goto err; - fpi_ssm_mark_completed(ssm); - break; - default: - fp_err("Unknown state %d", fpi_ssm_get_cur_state(ssm)); - goto err; - break; - } + /* TODO To get better results, tuning could be done 3 times as in + * captured traffic to make sure that the value is correct. */ + /* The default gain should work but it may reach a DCOffset limit so in + * this case we decrease the gain. */ + switch (fpi_ssm_get_cur_state (ssm)) + { + case TUNEDC_INIT: + /* reg_e0 = 0x23 is sensor normal/small gain */ + self->gain = GAIN_SMALL_INIT; + self->tunedc_min = DCOFFSET_MIN; + self->tunedc_max = DCOFFSET_MAX; + fp_dbg ("Tuning DCoffset"); + fpi_ssm_next_state (ssm); + break; - return; + case TUNEDC_SET_DCOFFSET_REQ: + /* Dichotomic search to find at which value the frame becomes + * almost black. */ + self->dcoffset = (self->tunedc_max + self->tunedc_min) / 2; + fp_dbg ("Testing DCoffset=0x%02X Gain=0x%02X", self->dcoffset, + self->gain); + msg_set_regs (self, 2, REG_DCOFFSET, self->dcoffset); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case TUNEDC_SET_DCOFFSET_ANS: + if (msg_check_ok (self)) + goto err; + fpi_ssm_next_state (ssm); + break; + + case TUNEDC_GET_FRAME_REQ: + /* vrt:0x15 vrb:0x10 are constant in all tuning frames. */ + msg_get_frame (self, 0x01, self->gain, 0x15, 0x10); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case TUNEDC_GET_FRAME_ANS: + if (process_frame_empty ((guint8 *) self->ans, FRAME_WIDTH)) + self->tunedc_max = self->dcoffset; + else + self->tunedc_min = self->dcoffset; + if (self->tunedc_min + 1 < self->tunedc_max) + { + fpi_ssm_jump_to_state (ssm, TUNEDC_SET_DCOFFSET_REQ); + } + else if (self->tunedc_max < DCOFFSET_MAX) + { + self->dcoffset = self->tunedc_max + 1; + fpi_ssm_next_state (ssm); + } + else + { + self->gain--; + fpi_ssm_jump_to_state (ssm, TUNEDC_SET_DCOFFSET_REQ); + } + break; + + case TUNEDC_FINAL_SET_REG2122_REQ: + fp_dbg ("-> DCoffset=0x%02X Gain=0x%02X", self->dcoffset, + self->gain); + /* ??? how reg21 / reg22 are calculated */ + msg_set_regs (self, 4, REG_21, 0x23, REG_22, 0x21); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case TUNEDC_FINAL_SET_REG2122_ANS: + if (msg_check_ok (self)) + goto err; + fpi_ssm_next_state (ssm); + break; + + case TUNEDC_FINAL_SET_GAIN_REQ: + msg_set_regs (self, 2, REG_GAIN, self->gain); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case TUNEDC_FINAL_SET_GAIN_ANS: + fpi_ssm_next_state (ssm); + break; + + case TUNEDC_FINAL_SET_DCOFFSET_REQ: + msg_set_regs (self, 2, REG_DCOFFSET, self->dcoffset); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case TUNEDC_FINAL_SET_DCOFFSET_ANS: + /* In captured traffic, read GAIN, VRT, and VRB registers. */ + if (msg_check_ok (self)) + goto err; + fpi_ssm_mark_completed (ssm); + break; + + default: + g_assert_not_reached (); + break; + } + + return; err: - fpi_ssm_mark_failed(ssm, -EIO); - + fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); } -static void m_tunedc_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_tunedc_complete (FpiSsm *ssm, FpDevice *dev, GError *error) { - struct fp_img_dev *idev = user_data; - if (!fpi_ssm_get_error(ssm)) { - fpi_ssm *ssm_tune; - ssm_tune = fpi_ssm_new(FP_DEV(idev), m_tunevrb_state, - TUNEVRB_NUM_STATES, idev); - fpi_ssm_start(ssm_tune, m_tunevrb_complete); - } else { - struct etes603_dev *dev = FP_INSTANCE_DATA(_dev); - fp_err("Error while tuning DCOFFSET"); - dev->is_active = FALSE; - reset_param(dev); - fpi_imgdev_session_error(idev, -2); - } - fpi_ssm_free(ssm); + FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev); + FpImageDevice *idev = FP_IMAGE_DEVICE (dev); + + if (!error) + { + FpiSsm *ssm_tune; + ssm_tune = fpi_ssm_new (FP_DEVICE (idev), m_tunevrb_state, + TUNEVRB_NUM_STATES); + fpi_ssm_start (ssm_tune, m_tunevrb_complete); + } + else + { + fp_err ("Error while tuning DCOFFSET"); + reset_param (FPI_DEVICE_ETES603 (dev)); + fpi_image_device_session_error (idev, error); + } + + if (!self->is_active) + m_exit_start (idev); + + fpi_ssm_free (ssm); } -static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_init_state (FpiSsm *ssm, FpDevice *dev) { - struct fp_img_dev *idev = user_data; - struct etes603_dev *dev = FP_INSTANCE_DATA(_dev); + FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev); - if (dev->is_active == FALSE) { - fpi_ssm_mark_completed(ssm); - return; - } + if (self->is_active == FALSE) + { + fpi_ssm_mark_completed (ssm); + return; + } - switch (fpi_ssm_get_cur_state(ssm)) { - case INIT_CHECK_INFO_REQ: - msg_get_regs(dev, 4, REG_INFO0, REG_INFO1, REG_INFO2, - REG_INFO3); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case INIT_CHECK_INFO_ANS: - if (msg_parse_regs(dev)) - goto err; - if (check_info(dev)) - goto err; - fpi_ssm_next_state(ssm); - break; - case INIT_CMD20_REQ: - msg_get_cmd20(dev); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case INIT_CMD20_ANS: - if (msg_check_cmd20(dev)) - goto err; - fpi_ssm_next_state(ssm); - break; - case INIT_CMD25_REQ: - msg_get_cmd25(dev); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case INIT_CMD25_ANS: - if (msg_check_cmd25(dev)) - goto err; - fpi_ssm_next_state(ssm); - break; - case INIT_SENSOR_REQ: - /* In captured traffic, those are split. */ - msg_set_regs(dev, 18, REG_MODE_CONTROL, REG_MODE_SLEEP, - REG_50, 0x0F, REG_GAIN, 0x04, REG_VRT, 0x08, - REG_VRB, 0x0D, REG_VCO_CONTROL, REG_VCO_RT, - REG_DCOFFSET, 0x36, REG_F0, 0x00, REG_F2, 0x00); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case INIT_SENSOR_ANS: - if (msg_check_ok(dev)) - goto err; - fpi_ssm_next_state(ssm); - break; - case INIT_ENC_REQ: - /* Initialize encryption registers without encryption. */ - /* Set registers from 0x41 to 0x48 (0x8 regs) */ - msg_set_regs(dev, 16, REG_ENC1, 0x12, REG_ENC2, 0x34, - REG_ENC3, 0x56, REG_ENC4, 0x78, REG_ENC5, 0x90, - REG_ENC6, 0xAB, REG_ENC7, 0xCD, REG_ENC8, 0xEF); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case INIT_ENC_ANS: - if (msg_check_ok(dev)) - goto err; - fpi_ssm_next_state(ssm); - break; - case INIT_REGS_REQ: - /* Set register from 0x20 to 0x37 (0x18 regs) */ - msg_set_regs(dev, 48, - REG_20, 0x00, REG_21, 0x23, REG_22, 0x21, REG_23, 0x20, - REG_24, 0x14, REG_25, 0x6A, REG_26, 0x00, REG_27, 0x00, - REG_28, 0x00, REG_29, 0xC0, REG_2A, 0x50, REG_2B, 0x50, - REG_2C, 0x4D, REG_2D, 0x03, REG_2E, 0x06, REG_2F, 0x06, - REG_30, 0x10, REG_31, 0x02, REG_32, 0x14, REG_33, 0x34, - REG_34, 0x01, REG_35, 0x08, REG_36, 0x03, REG_37, 0x21); - if (async_tx(idev, EP_OUT, async_tx_cb, ssm)) - goto err; - break; - case INIT_REGS_ANS: - if (msg_check_ok(dev)) - goto err; - fpi_ssm_mark_completed(ssm); - break; - default: - fp_err("Unknown state %d", fpi_ssm_get_cur_state(ssm)); - goto err; - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case INIT_CHECK_INFO_REQ: + msg_get_regs (self, 4, REG_INFO0, REG_INFO1, REG_INFO2, + REG_INFO3); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; - return; + case INIT_CHECK_INFO_ANS: + if (msg_parse_regs (self)) + goto err; + if (check_info (self)) + goto err; + fpi_ssm_next_state (ssm); + break; + + case INIT_CMD20_REQ: + msg_get_cmd20 (self); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case INIT_CMD20_ANS: + if (msg_check_cmd20 (self)) + goto err; + fpi_ssm_next_state (ssm); + break; + + case INIT_CMD25_REQ: + msg_get_cmd25 (self); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case INIT_CMD25_ANS: + if (msg_check_cmd25 (self)) + goto err; + fpi_ssm_next_state (ssm); + break; + + case INIT_SENSOR_REQ: + /* In captured traffic, those are split. */ + msg_set_regs (self, 18, REG_MODE_CONTROL, REG_MODE_SLEEP, + REG_50, 0x0F, REG_GAIN, 0x04, REG_VRT, 0x08, + REG_VRB, 0x0D, REG_VCO_CONTROL, REG_VCO_RT, + REG_DCOFFSET, 0x36, REG_F0, 0x00, REG_F2, 0x00); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case INIT_SENSOR_ANS: + if (msg_check_ok (self)) + goto err; + fpi_ssm_next_state (ssm); + break; + + case INIT_ENC_REQ: + /* Initialize encryption registers without encryption. */ + /* Set registers from 0x41 to 0x48 (0x8 regs) */ + msg_set_regs (self, 16, REG_ENC1, 0x12, REG_ENC2, 0x34, + REG_ENC3, 0x56, REG_ENC4, 0x78, REG_ENC5, 0x90, + REG_ENC6, 0xAB, REG_ENC7, 0xCD, REG_ENC8, 0xEF); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case INIT_ENC_ANS: + if (msg_check_ok (self)) + goto err; + fpi_ssm_next_state (ssm); + break; + + case INIT_REGS_REQ: + /* Set register from 0x20 to 0x37 (0x18 regs) */ + msg_set_regs (self, 48, + REG_20, 0x00, REG_21, 0x23, REG_22, 0x21, REG_23, + 0x20, + REG_24, 0x14, REG_25, 0x6A, REG_26, 0x00, REG_27, + 0x00, + REG_28, 0x00, REG_29, 0xC0, REG_2A, 0x50, REG_2B, + 0x50, + REG_2C, 0x4D, REG_2D, 0x03, REG_2E, 0x06, REG_2F, + 0x06, + REG_30, 0x10, REG_31, 0x02, REG_32, 0x14, REG_33, + 0x34, + REG_34, 0x01, REG_35, 0x08, REG_36, 0x03, REG_37, + 0x21); + async_tx (dev, EP_OUT, async_tx_cb, ssm); + break; + + case INIT_REGS_ANS: + if (msg_check_ok (self)) + goto err; + fpi_ssm_mark_completed (ssm); + break; + + default: + g_assert_not_reached (); + break; + } + + return; err: - fpi_ssm_mark_failed(ssm, -EIO); - + fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); } -static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_init_complete (FpiSsm *ssm, FpDevice *dev, GError *error) { - struct fp_img_dev *idev = user_data; - if (!fpi_ssm_get_error(ssm)) { - fpi_ssm *ssm_tune; - ssm_tune = fpi_ssm_new(FP_DEV(idev), m_tunedc_state, - TUNEDC_NUM_STATES, idev); - fpi_ssm_start(ssm_tune, m_tunedc_complete); - } else { - struct etes603_dev *dev = FP_INSTANCE_DATA(_dev); - fp_err("Error initializing the device"); - dev->is_active = FALSE; - reset_param(dev); - fpi_imgdev_session_error(idev, -1); - } - fpi_ssm_free(ssm); + FpImageDevice *idev = FP_IMAGE_DEVICE (dev); + + if (!error) + { + FpiSsm *ssm_tune; + ssm_tune = fpi_ssm_new (FP_DEVICE (idev), m_tunedc_state, + TUNEDC_NUM_STATES); + fpi_ssm_start (ssm_tune, m_tunedc_complete); + } + else + { + fp_err ("Error initializing the device"); + reset_param (FPI_DEVICE_ETES603 (dev)); + fpi_image_device_session_error (idev, error); + } + fpi_ssm_free (ssm); } -static int dev_activate(struct fp_img_dev *idev) +static void +dev_activate (FpImageDevice *idev) { - struct etes603_dev *dev = FP_INSTANCE_DATA(FP_DEV(idev)); - fpi_ssm *ssm; + FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (idev); + FpiSsm *ssm; - g_assert(dev); + g_assert (self); - /* Reset info and data */ - dev->is_active = TRUE; + /* Reset info and data */ + self->is_active = TRUE; - if (dev->dcoffset == 0) { - fp_dbg("Tuning device..."); - ssm = fpi_ssm_new(FP_DEV(idev), m_init_state, INIT_NUM_STATES, idev); - fpi_ssm_start(ssm, m_init_complete); - } else { - fp_dbg("Using previous tuning (DCOFFSET=0x%02X,VRT=0x%02X," - "VRB=0x%02X,GAIN=0x%02X).", dev->dcoffset, dev->vrt, - dev->vrb, dev->gain); - fpi_imgdev_activate_complete(idev, 0); - ssm = fpi_ssm_new(FP_DEV(idev), m_finger_state, FGR_NUM_STATES, idev); - fpi_ssm_start(ssm, m_finger_complete); - } - return 0; + if (self->dcoffset == 0) + { + fp_dbg ("Tuning device..."); + ssm = fpi_ssm_new (FP_DEVICE (idev), m_init_state, INIT_NUM_STATES); + fpi_ssm_start (ssm, m_init_complete); + } + else + { + fp_dbg ("Using previous tuning (DCOFFSET=0x%02X,VRT=0x%02X," + "VRB=0x%02X,GAIN=0x%02X).", self->dcoffset, self->vrt, + self->vrb, self->gain); + fpi_image_device_activate_complete (idev, NULL); + ssm = fpi_ssm_new (FP_DEVICE (idev), m_finger_state, FGR_NUM_STATES); + fpi_ssm_start (ssm, m_finger_complete); + } } -static void dev_deactivate(struct fp_img_dev *idev) +static void +dev_deactivate (FpImageDevice *idev) { - struct etes603_dev *dev = FP_INSTANCE_DATA(FP_DEV(idev)); + FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (idev); - fp_dbg("deactivating"); + fp_dbg ("deactivating"); - /* this can be called even if still activated. */ - if (dev->is_active == TRUE) { - dev->is_active = FALSE; - } - - m_exit_start(idev); + /* this can be called even if still activated. */ + if (self->is_active == TRUE) + self->is_active = FALSE; + else + m_exit_start (idev); } -static int dev_open(struct fp_img_dev *idev, unsigned long driver_data) +static void +dev_open (FpImageDevice *idev) { - int ret; - struct etes603_dev *dev; + GError *error = NULL; + FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (idev); - dev = g_malloc0(sizeof(struct etes603_dev)); - fp_dev_set_instance_data(FP_DEV(idev), dev); + if (!g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (idev)), 0, 0, &error)) + { + fpi_image_device_open_complete (idev, error); + return; + } - dev->req = g_malloc(sizeof(struct egis_msg)); - dev->ans = g_malloc(FE_SIZE); - dev->fp = g_malloc(FE_SIZE * 4); + self->req = g_malloc (sizeof (struct egis_msg)); + self->ans = g_malloc (FE_SIZE); + self->fp = g_malloc (FE_SIZE * 4); - ret = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(idev)), 0); - if (ret != LIBUSB_SUCCESS) { - fp_err("libusb_claim_interface failed on interface 0: %s", libusb_error_name(ret)); - return ret; - } - - fpi_imgdev_open_complete(idev, 0); - return 0; + fpi_image_device_open_complete (idev, NULL); } -static void dev_close(struct fp_img_dev *idev) +static void +dev_close (FpImageDevice *idev) { - struct etes603_dev *dev = FP_INSTANCE_DATA(FP_DEV(idev)); + GError *error = NULL; + FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (idev); - g_free(dev->req); - g_free(dev->ans); - g_free(dev->fp); - g_free(dev); + g_free (self->req); + g_free (self->ans); + g_free (self->fp); - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(idev)), 0); - fpi_imgdev_close_complete(idev); + g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (idev)), + 0, 0, &error); + fpi_image_device_close_complete (idev, error); } -static const struct usb_id id_table[] = { - /* EgisTec (aka Lightuning) ES603 */ - { .vendor = 0x1c7a, .product = 0x0603}, - { 0, 0, 0, }, +static const FpIdEntry id_table[] = { + /* EgisTec (aka Lightuning) ES603 */ + { .vid = 0x1c7a, .pid = 0x0603, }, + { .vid = 0, .pid = 0, .driver_data = 0 }, }; -struct fp_img_driver etes603_driver = { - .driver = { - .id = ETES603_ID, - .name = FP_COMPONENT, - .full_name = "EgisTec ES603", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_SWIPE, - }, - .flags = 0, - .img_height = -1, - .img_width = 256, +static void +fpi_device_etes603_init (FpiDeviceEtes603 *self) +{ +} +static void +fpi_device_etes603_class_init (FpiDeviceEtes603Class *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); - .open = dev_open, - .close = dev_close, - .activate = dev_activate, - .deactivate = dev_deactivate, -}; + dev_class->id = "etes603"; + dev_class->full_name = "EgisTec ES603"; + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->id_table = id_table; + dev_class->scan_type = FP_SCAN_TYPE_SWIPE; + img_class->img_open = dev_open; + img_class->img_close = dev_close; + img_class->activate = dev_activate; + img_class->deactivate = dev_deactivate; + + img_class->img_width = 256; + img_class->img_height = -1; +} diff --git a/libfprint/drivers/synaptics/bmkt.h b/libfprint/drivers/synaptics/bmkt.h new file mode 100644 index 00000000..67c48f2e --- /dev/null +++ b/libfprint/drivers/synaptics/bmkt.h @@ -0,0 +1,232 @@ +/* + * Synaptics MiS Fingerprint Sensor Interface + * Copyright (C) 2019 Synaptics Inc + * + * 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 + */ + +#ifndef _BMKT_H_ +#define _BMKT_H_ + +/**< User ID maximum length allowed */ +#define BMKT_MAX_USER_ID_LEN 100 +/**< Software Part Number length */ +#define BMKT_PART_NUM_LEN 10 +/**< Software supplier identification length */ +#define BMKT_SUPPLIER_ID_LEN 2 + +/**< Maximum namber of templates for storing in internal flash of the fingerprint sensor */ +#define BMKT_MAX_NUM_TEMPLATES_INTERNAL_FLASH 15 + +#include +#include "bmkt_response.h" + +/*! + ******************************************************************************* + ** Type definition for result + */ +/** No error; Operation successfully completed. */ +#define BMKT_SUCCESS 0 +/** Fingerprint system not initialized */ +#define BMKT_FP_SYSTEM_NOT_INITIALIZED 101 +/** Fingerprint system busy performing another operation */ +#define BMKT_FP_SYSTEM_BUSY 102 +/** Operation not allowed */ +#define BMKT_OPERATION_DENIED 103 +/** System ran out of memory while performing operation */ +#define BMKT_OUT_OF_MEMORY 104 +/** Corrupt message, CRC check fail or truncated message */ +#define BMKT_CORRUPT_MESSAGE 110 +/** One of the command parameters is outside the range of valid values */ +#define BMKT_INVALID_PARAM 111 +/** Unrecognized message or message with invalid message ID */ +#define BMKT_UNRECOGNIZED_MESSAGE 112 +/** Operation time out */ +#define BMKT_OP_TIME_OUT 113 +/** General error – cause of error cannot be determined */ +#define BMKT_GENERAL_ERROR 114 + +#define BMKT_SET_SECURITY_LEVEL_FAIL 120 +#define BMKT_GET_SECURITY_LEVEL_FAIL 121 + +/** Fingerprint sensor reset while operation was being performed */ +#define BMKT_SENSOR_RESET 201 +/** Fingerprint sensor malfunctioned */ +#define BMKT_SENSOR_MALFUNCTION 202 +/** Fingerprint sensor cannot be accessed despite repeated attempts */ +#define BMKT_SENSOR_TAMPERED 203 +/** + * BMKT_SENSOR_NOT_INIT: + * Fingerprint sensor module not initialized yet – not ready for use + * (different from error code 101 which indicates that the entire system + * has not been initialized) + */ +#define BMKT_SENSOR_NOT_INIT 204 +/** Number of re-pairing operations exceeded limit or re-pairing has been disabled */ +#define BMKT_OWNERSHIP_RESET_MAX_EXCEEDED 205 +/** + * BMKT_SENSOR_STIMULUS_ERROR: + * There is a finger or debris on the sensor that needs to be removed + * before issuing this command + */ +#define BMKT_SENSOR_STIMULUS_ERROR 213 +/** + * BMKT_CORRUPT_TEMPLATE_DATA: + * One of the fingerprint templates stored on flash is corrupt. + * This error code is returned in case of failure in finding a fingerprint match + * during identify or verify operations while also detecting that one or more + * fingerprint templates stored on the flash has become corrupted + */ +#define BMKT_CORRUPT_TEMPLATE_DATA 300 +/** Failed to extract features from fingerprint image acquired by sensor */ +#define BMKT_FEATURE_EXTRACT_FAIL 301 +/** Failed to generate fingerprint template */ +#define BMKT_ENROLL_FAIL 302 +/** Specified finger already enrolled for this user */ +#define BMKT_ENROLLMENT_EXISTS 303 +/** Invalid fingerprint image */ +#define BMKT_INVALID_FP_IMAGE 304 +/** No matching user fingerprint template found in database */ +#define BMKT_FP_NO_MATCH 404 +/** Fingerprint database is full */ +#define BMKT_FP_DATABASE_FULL 501 +/** Fingerprint database is empty */ +#define BMKT_FP_DATABASE_EMPTY 502 +/** Cannot access fingerprint database */ +#define BMKT_FP_DATABASE_ACCESS_FAIL 503 +/** Fingerprint template record does not exist */ +#define BMKT_FP_DATABASE_NO_RECORD_EXISTS 504 +/** Failed to read/write system parameters stored on flash */ +#define BMKT_FP_PARAM_ACCESS_FAIL 505 +/** Fingerprint is a spoof */ +#define BMKT_FP_SPOOF_ALERT 801 +/** Anti-spoof module failure */ +#define BMKT_ANTI_SPOOF_MODULE_FAIL 802 + +#define BMKT_CORRUPT_UPDATE_IMAGE 901 +#define BMKT_SYSTEM_UPDATE_FAIL 902 + +#define BMKT_EVENT_NOT_SET 1000 +#define BMKT_SENSOR_NOT_READY 1001 +#define BMKT_TIMEOUT 1002 +#define BMKT_SENSOR_RESPONSE_PENDING 1003 + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * bmkt_mode: + * Fingerprint system operational mode values level 1 + */ +typedef enum bmkt_mode { + BMKT_STATE_UNINIT = 0xFF, + BMKT_STATE_IDLE = 0x00, + BMKT_STATE_ENROLL = 0x10, + BMKT_STATE_IDENTIFY = 0x20, + BMKT_STATE_VERIFY = 0x30, + BMKT_STATE_DB_OPS = 0x40, + BMKT_STATE_SYS_TEST = 0x50, + BMKT_STATE_SYS_OPS = 0x60, +} bmkt_mode_t; + +/** + * bmkt_mode_level2: + * Fingerprint system operational mode values level 2 + */ +typedef enum bmkt_mode_level2 { + BMKT_STATE_L2_IDLE = 0x00, + BMKT_STATE_L2_STARTING = 0x11, + BMKT_STATE_L2_WAITING_FOR_FINGER = 0x12, + BMKT_STATE_L2_CAPTURE_IMAGE = 0x13, + BMKT_STATE_L2_CAPTURE_COMPLETE = 0x14, + BMKT_STATE_L2_EXTRACT_FEATURE = 0x15, + BMKT_STATE_L2_CREATE_TEMPLATE = 0x16, + BMKT_STATE_L2_READING_FROM_FLASH = 0x17, + BMKT_STATE_L2_WRITING_TO_FLASH = 0x18, + BMKT_STATE_L2_FINISHING = 0x19, + BMKT_STATE_L2_CANCELING_OP = 0x20, + BMKT_STATE_L2_MATCHING = 0x21, + BMKT_STATE_L2_TRANSMITTING_RESPONSE = 0x22, + BMKT_STATE_L2_READY_POWER_DOWN = 0xF0, +} bmkt_mode_level2_t; + +/** + * bmkt_transport_type: + * Fingerprint system transport types + */ +typedef enum bmkt_transport_type { + BMKT_TRANSPORT_TYPE_USB = 0, +} bmkt_transport_type_t; + +/** + * bmkt_usb_config: + * Structure represcontainingenting USB configuration details + */ +typedef struct bmkt_usb_config +{ + int product_id; /**< USB device product ID */ +} bmkt_usb_config_t; + +/** + * bmkt_transport_config_t: + * Union containing transport configuration details + */ +typedef union +{ + bmkt_usb_config_t usb_config; +} bmkt_transport_config_t; + +/** + * bmkt_sensor_desc_t: + * Structure containing fingerprint system description + */ +typedef struct bmkt_sensor_desc +{ + int product_id; + int flags; +} bmkt_sensor_desc_t; + +/** + * bmkt_finger_state_t: + * Finger state representation values. + */ +typedef enum { + BMKT_FINGER_STATE_UNKNOWN = 0, + BMKT_FINGER_STATE_ON_SENSOR, + BMKT_FINGER_STATE_NOT_ON_SENSOR, +} bmkt_finger_state_t; + +/** + * bmkt_finger_event_t: + * Structure containing finger state + */ +typedef struct bmkt_finger_event +{ + bmkt_finger_state_t finger_state; +} bmkt_finger_event_t; + +typedef struct bmkt_user_id +{ + uint8_t user_id_len; + uint8_t user_id[BMKT_MAX_USER_ID_LEN]; +} bmkt_user_id_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _BMKT_H_ */ diff --git a/libfprint/drivers/synaptics/bmkt_message.c b/libfprint/drivers/synaptics/bmkt_message.c new file mode 100644 index 00000000..59bd62c1 --- /dev/null +++ b/libfprint/drivers/synaptics/bmkt_message.c @@ -0,0 +1,400 @@ +/* + * Copyright (C) 2019 Synaptics Inc + * + * 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 +#include "bmkt_response.h" +#include "bmkt_message.h" + +static uint8_t +extract8 (const uint8_t *buf, int *offset) +{ + uint8_t ret = 0; + int off = 0; + + if (offset) + off = *offset; + + ret = *(buf + off); + + if (offset) + *offset += 1; + + return ret; +} + + +static int +parse_error_response (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp) +{ + if (msg_resp->payload_len != 2) + return BMKT_UNRECOGNIZED_MESSAGE; + + resp->result = (msg_resp->payload[0] << 8) | msg_resp->payload[1]; + + return BMKT_SUCCESS; +} + +static int +parse_init_ok (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp) +{ + bmkt_init_resp_t *init_resp = &resp->response.init_resp; + + if (msg_resp->payload_len != 1) + return BMKT_UNRECOGNIZED_MESSAGE; + + init_resp->finger_presence = extract8 (msg_resp->payload, NULL); + + return BMKT_SUCCESS; +} + + +static int +parse_fps_mode_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp) +{ + int offset = 0; + bmkt_fps_mode_resp_t *fps_mode_resp = &resp->response.fps_mode_resp; + + if (msg_resp->payload_len != sizeof (bmkt_fps_mode_resp_t)) + return BMKT_UNRECOGNIZED_MESSAGE; + + fps_mode_resp->mode = extract8 (msg_resp->payload, &offset); + fps_mode_resp->level2_mode = extract8 (msg_resp->payload, &offset); + fps_mode_resp->cmd_id = extract8 (msg_resp->payload, &offset); + fps_mode_resp->finger_presence = extract8 (msg_resp->payload, &offset); + + return BMKT_SUCCESS; +} + +static int +parse_enroll_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp) +{ + bmkt_enroll_resp_t *enroll_resp = &resp->response.enroll_resp; + + if (msg_resp->payload_len != 1) + return BMKT_UNRECOGNIZED_MESSAGE; + + enroll_resp->progress = extract8 (msg_resp->payload, NULL); + + return BMKT_SUCCESS; +} + +static int +parse_enroll_ok (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp) +{ + bmkt_enroll_resp_t *enroll_resp = &resp->response.enroll_resp; + + if (msg_resp->payload_len < 1 || msg_resp->payload_len > (BMKT_MAX_USER_ID_LEN + 1)) + return BMKT_UNRECOGNIZED_MESSAGE; + + enroll_resp->finger_id = msg_resp->payload[0]; + memcpy (enroll_resp->user_id, &msg_resp->payload[1], msg_resp->payload_len - 1); + + return BMKT_SUCCESS; +} + +static int +parse_auth_ok (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp) +{ + bmkt_identify_resp_t *id_resp = &resp->response.id_resp; + + if (msg_resp->payload_len < 3 || msg_resp->payload_len > (BMKT_MAX_USER_ID_LEN + 3)) + return BMKT_UNRECOGNIZED_MESSAGE; + + id_resp->match_result = (double) msg_resp->payload[0] + 0.01 * (double) msg_resp->payload[1]; + id_resp->finger_id = msg_resp->payload[2]; + memcpy (id_resp->user_id, &msg_resp->payload[3], msg_resp->payload_len - 3); + + return BMKT_SUCCESS; +} + +static int +parse_security_level_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp) +{ + bmkt_set_sec_level_resp_t *sec_level_resp = &resp->response.sec_level_resp; + + if (msg_resp->payload_len != 1) + return BMKT_UNRECOGNIZED_MESSAGE; + + sec_level_resp->sec_level = extract8 (msg_resp->payload, NULL); + + return BMKT_SUCCESS; +} + +static int +parse_del_all_users_progress_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp) +{ + bmkt_del_all_users_resp_t *del_all_users_resp = &resp->response.del_all_users_resp; + + if (msg_resp->payload_len != 1) + return BMKT_UNRECOGNIZED_MESSAGE; + + del_all_users_resp->progress = extract8 (msg_resp->payload, NULL); + + return BMKT_SUCCESS; +} + +static int +parse_db_cap_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp) +{ + bmkt_get_db_capacity_resp_t *db_cap_resp = &resp->response.db_cap_resp; + int offset = 0; + + if (msg_resp->payload_len < 2 || msg_resp->payload_len > 4) + return BMKT_UNRECOGNIZED_MESSAGE; + + db_cap_resp->total = extract8 (msg_resp->payload, &offset); + db_cap_resp->empty = extract8 (msg_resp->payload, &offset); + + if (msg_resp->payload_len == 4) + { + db_cap_resp->bad_slots = extract8 (msg_resp->payload, &offset); + db_cap_resp->corrupt_templates = extract8 (msg_resp->payload, &offset); + } + + return BMKT_SUCCESS; +} + +static int +parse_get_enrolled_fingers_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp) +{ + int offset = 0; + int i = 0; + + if (msg_resp->payload_len < 2) + return BMKT_UNRECOGNIZED_MESSAGE; + /* 2 bytes per finger so calculate the total number of fingers to process*/ + int num_fingers = (msg_resp->payload_len) / 2; + + bmkt_enrolled_fingers_resp_t *get_enrolled_fingers_resp = &resp->response.enrolled_fingers_resp; + + for (i = 0; i < num_fingers; i++) + { + get_enrolled_fingers_resp->fingers[i].finger_id = extract8 (msg_resp->payload, &offset); + get_enrolled_fingers_resp->fingers[i].template_status = extract8 (msg_resp->payload, &offset); + + } + return BMKT_SUCCESS; +} +static int +parse_get_enrolled_users_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp) +{ + int offset = 0; + int i = 0; + + /* the payload is 2 bytes + template data */ + if (msg_resp->payload_len < 2) + return BMKT_UNRECOGNIZED_MESSAGE; + + bmkt_enroll_templates_resp_t *get_enroll_templates_resp = &resp->response.enroll_templates_resp; + + get_enroll_templates_resp->total_query_messages = extract8 (msg_resp->payload, &offset); + get_enroll_templates_resp->query_sequence = extract8 (msg_resp->payload, &offset); + + int n = 0; + for (n = 0; n < BMKT_MAX_NUM_TEMPLATES_INTERNAL_FLASH; n++) + { + if (offset >= msg_resp->payload_len) + break; + get_enroll_templates_resp->templates[n].user_id_len = extract8 (msg_resp->payload, &offset) - 2; + if(get_enroll_templates_resp->templates[n].user_id_len > BMKT_MAX_USER_ID_LEN) + return BMKT_UNRECOGNIZED_MESSAGE; + get_enroll_templates_resp->templates[n].template_status = extract8 (msg_resp->payload, &offset); + get_enroll_templates_resp->templates[n].finger_id = extract8 (msg_resp->payload, &offset); + for (i = 0; i < get_enroll_templates_resp->templates[n].user_id_len; i++) + get_enroll_templates_resp->templates[n].user_id[i] = extract8 (msg_resp->payload, &offset); + get_enroll_templates_resp->templates[n].user_id[i] = '\0'; + } + + return BMKT_SUCCESS; +} + +static int +parse_get_version_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp) +{ + bmkt_get_version_resp_t *get_version_resp = &resp->response.get_version_resp; + int offset = 0; + + if (msg_resp->payload_len != 15) + return BMKT_UNRECOGNIZED_MESSAGE; + + memcpy (get_version_resp->part, msg_resp->payload, BMKT_PART_NUM_LEN); + offset += BMKT_PART_NUM_LEN; + get_version_resp->year = extract8 (msg_resp->payload, &offset); + get_version_resp->week = extract8 (msg_resp->payload, &offset); + get_version_resp->patch = extract8 (msg_resp->payload, &offset); + memcpy (get_version_resp->supplier_id, msg_resp->payload + offset, BMKT_SUPPLIER_ID_LEN); + + return BMKT_SUCCESS; +} + +int +bmkt_compose_message (uint8_t *cmd, int *cmd_len, uint8_t msg_id, uint8_t seq_num, + uint8_t payload_size, const uint8_t *payload) +{ + int message_len = BMKT_MESSAGE_HEADER_LEN + payload_size; + + if (*cmd_len < message_len) + return BMKT_OUT_OF_MEMORY; + + cmd[BMKT_MESSAGE_HEADER_ID_FIELD] = BMKT_MESSAGE_HEADER_ID; + cmd[BMKT_MESSAGE_SEQ_NUM_FIELD] = seq_num; + cmd[BMKT_MESSAGE_ID_FIELD] = msg_id; + cmd[BMKT_MESSAGE_PAYLOAD_LEN_FIELD] = payload_size; + memcpy (&cmd[BMKT_MESSAGE_PAYLOAD_FIELD], payload, payload_size); + + *cmd_len = message_len; + + return BMKT_SUCCESS; +} + +int +bmkt_parse_message_header (uint8_t *resp_buf, int resp_len, bmkt_msg_resp_t *msg_resp) +{ + if (resp_buf[BMKT_MESSAGE_HEADER_ID_FIELD] != BMKT_MESSAGE_HEADER_ID) + return BMKT_CORRUPT_MESSAGE; + + msg_resp->seq_num = resp_buf[BMKT_MESSAGE_SEQ_NUM_FIELD]; + msg_resp->msg_id = resp_buf[BMKT_MESSAGE_ID_FIELD]; + msg_resp->payload_len = resp_buf[BMKT_MESSAGE_PAYLOAD_LEN_FIELD]; + if (msg_resp->payload_len > 0) + msg_resp->payload = &resp_buf[BMKT_MESSAGE_PAYLOAD_FIELD]; + else + msg_resp->payload = NULL; + + return BMKT_SUCCESS; +} + +int +bmkt_parse_message_payload (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp) +{ + int ret = BMKT_SUCCESS; + + memset (resp, 0, sizeof (bmkt_response_t)); + + resp->response_id = msg_resp->msg_id; + + switch(msg_resp->msg_id) + { + case BMKT_RSP_CONTINUOUS_IMAGE_CAPTURE_FAIL: + case BMKT_RSP_SENSOR_MODULE_TEST_FAIL: + case BMKT_RSP_FPS_INIT_FAIL: + case BMKT_RSP_FPS_MODE_FAIL: + case BMKT_RSP_SET_SECURITY_LEVEL_FAIL: + case BMKT_RSP_GET_SECURITY_LEVEL_FAIL: + case BMKT_RSP_CANCEL_OP_FAIL: + case BMKT_RSP_ENROLL_FAIL: + case BMKT_RSP_ID_FAIL: + case BMKT_RSP_VERIFY_FAIL: + case BMKT_RSP_QUERY_FAIL: + case BMKT_RSP_DEL_USER_FP_FAIL: + case BMKT_RSP_DEL_FULL_DB_FAIL: + case BMKT_RSP_REPEAT_LAST_BMKT_RSP_FAIL: + case BMKT_RSP_POWER_DOWN_FAIL: + case BMKT_RSP_GET_VERSION_FAIL: + case BMKT_RSP_DISABLE_PAIRING_FAIL: + case BMKT_RSP_QUERY_PAIRING_FAIL: + case BMKT_RSP_SENSOR_STATUS_FAIL: + case BMKT_RSP_RETRIEVE_FINAL_RESULT_FAIL: + ret = parse_error_response (msg_resp, resp); + resp->complete = 1; + break; + + case BMKT_RSP_FPS_INIT_OK: + ret = parse_init_ok (msg_resp, resp); + resp->complete = 1; + break; + + case BMKT_RSP_CANCEL_OP_OK: + case BMKT_RSP_DEL_FULL_DB_OK: + case BMKT_RSP_DEL_USER_FP_OK: + /* responses with a payload of 0 + so the response indicates success */ + resp->result = BMKT_SUCCESS; + resp->complete = 1; + break; + + case BMKT_RSP_FPS_MODE_REPORT: + // parse_fps_mode + ret = parse_fps_mode_report (msg_resp, resp); + resp->complete = 1; + break; + + case BMKT_RSP_GET_SECURITY_LEVEL_REPORT: + case BMKT_RSP_SET_SECURITY_LEVEL_REPORT: + /* parse security level result */ + ret = parse_security_level_report (msg_resp, resp); + resp->complete = 1; + break; + + case BMKT_RSP_DELETE_PROGRESS: + ret = parse_del_all_users_progress_report (msg_resp, resp); + break; + + case BMKT_RSP_CAPTURE_COMPLETE: + resp->result = BMKT_SUCCESS; + break; + + case BMKT_RSP_ENROLL_READY: + resp->result = BMKT_SUCCESS; + break; + + case BMKT_RSP_ENROLL_REPORT: + ret = parse_enroll_report (msg_resp, resp); + break; + + case BMKT_RSP_ENROLL_OK: + resp->complete = 1; + ret = parse_enroll_ok (msg_resp, resp); + break; + + case BMKT_RSP_ID_OK: + case BMKT_RSP_VERIFY_OK: + ret = parse_auth_ok (msg_resp, resp); + resp->complete = 1; + break; + + case BMKT_RSP_GET_ENROLLED_FINGERS_REPORT: + ret = parse_get_enrolled_fingers_report (msg_resp, resp); + resp->complete = 1; + break; + + case BMKT_RSP_DATABASE_CAPACITY_REPORT: + resp->complete = 1; + ret = parse_db_cap_report (msg_resp, resp); + break; + + case BMKT_RSP_TEMPLATE_RECORDS_REPORT: + ret = parse_get_enrolled_users_report (msg_resp, resp); + break; + + case BMKT_RSP_QUERY_RESPONSE_COMPLETE: + resp->complete = 1; + break; + + case BMKT_RSP_VERSION_INFO: + ret = parse_get_version_report (msg_resp, resp); + resp->complete = 1; + break; + + case BMKT_RSP_POWER_DOWN_READY: + resp->complete = 1; + break; + } + + return ret; +} diff --git a/libfprint/drivers/synaptics/bmkt_message.h b/libfprint/drivers/synaptics/bmkt_message.h new file mode 100644 index 00000000..d41e3d2f --- /dev/null +++ b/libfprint/drivers/synaptics/bmkt_message.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2019 Synaptics Inc + * + * 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 + */ + + +#ifndef BMKT_MESSAGE_H_ +#define BMKT_MESSAGE_H_ + + +#define BMKT_MESSAGE_HEADER_ID 0xFE +#define BMKT_MESSAGE_HEADER_LEN (4) +#define BMKT_MESSAGE_CRC32_LEN (4) +#define BMKT_MESSAGE_HEADER_ID_FIELD 0 +#define BMKT_MESSAGE_SEQ_NUM_FIELD 1 +#define BMKT_MESSAGE_ID_FIELD 2 +#define BMKT_MESSAGE_PAYLOAD_LEN_FIELD 3 +#define BMKT_MESSAGE_PAYLOAD_FIELD 4 + +// Command messages +#define BMKT_CMD_CONTINUOUS_IMAGE_CAPTURE 0x01 +#define BMKT_CMD_CONTINUOUS_IMAGE_CAPTURE_STOP 0x04 +#define BMKT_CMD_SENSOR_MODULE_TEST 0x06 +#define BMKT_CMD_SENSOR_MODULE_TEST_START 0x08 +#define BMKT_CMD_NEXT_TEST_REPORT_CHUNK 0x0B +#define BMKT_CMD_FPS_INIT 0x11 +#define BMKT_CMD_GET_FPS_MODE 0x21 +#define BMKT_CMD_SET_SECURITY_LEVEL 0x31 +#define BMKT_CMD_GET_SECURITY_LEVEL 0x34 +#define BMKT_CMD_CANCEL_OP 0x41 +#define BMKT_CMD_ENROLL_USER 0x51 +#define BMKT_CMD_ENROLL_PAUSE 0x52 +#define BMKT_CMD_ENROLL_RESUME 0x53 +#define BMKT_CMD_ID_USER 0x61 +#define BMKT_CMD_VERIFY_USER 0x65 +#define BMKT_CMD_GET_TEMPLATE_RECORDS 0x71 +#define BMKT_CMD_GET_NEXT_QUERY_RESPONSE 0x72 +#define BMKT_CMD_GET_ENROLLED_FINGERS 0x73 +#define BMKT_CMD_GET_DATABASE_CAPACITY 0x74 +#define BMKT_CMD_DEL_USER_FP 0x81 +#define BMKT_CMD_DEL_FULL_DB 0x84 +#define BMKT_CMD_REPEAT_LAST_RSP 0x92 +#define BMKT_CMD_POWER_DOWN_NOTIFY 0xA1 +#define BMKT_CMD_GET_VERSION 0xB1 +#define BMKT_CMD_DISABLE_PAIRING 0xC2 +#define BMKT_CMD_QUERY_PAIRING 0xC5 +#define BMKT_CMD_SENSOR_STATUS 0xD1 +#define BMKT_CMD_ID_USER_IN_ORDER 0xE1 +#define BMKT_CMD_ID_NEXT_USER 0xE3 +#define BMKT_CMD_VERIFY_USER_IN_ORDER 0xF1 +#define BMKT_CMD_VERIFY_FINGERS_IN_ORDER 0xF2 +#define BMKT_CMD_GET_FINAL_RESULT 0xE4 + +#define BMKT_EVT_FINGER_REPORT 0x91 + +#define BMKT_EVT_FINGER_STATE_NOT_ON_SENSOR 0x00 +#define BMKT_EVT_FINGER_STATE_ON_SENSOR 0x01 + +typedef struct bmkt_msg_resp +{ + uint8_t msg_id; + uint8_t seq_num; + uint8_t payload_len; + uint8_t *payload; + int result; +} bmkt_msg_resp_t; + +int bmkt_compose_message (uint8_t *cmd, + int *cmd_len, + uint8_t msg_id, + uint8_t seq_num, + uint8_t payload_size, + const uint8_t *payload); + +int bmkt_parse_message_header (uint8_t *resp_buf, + int resp_len, + bmkt_msg_resp_t *msg_resp); +int bmkt_parse_message_payload (bmkt_msg_resp_t *msg_resp, + bmkt_response_t *resp); +#endif /* BMKT_MESSAGE_H_ */ diff --git a/libfprint/drivers/synaptics/bmkt_response.h b/libfprint/drivers/synaptics/bmkt_response.h new file mode 100644 index 00000000..cfd77033 --- /dev/null +++ b/libfprint/drivers/synaptics/bmkt_response.h @@ -0,0 +1,489 @@ +/* + * Synaptics MiS Fingerprint Sensor Response Data Interface + * Copyright (C) 2019 Synaptics Inc + * + * 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 + */ + + +#ifndef _BMKT_RESPONSE_H_ +#define _BMKT_RESPONSE_H_ + +#include "bmkt.h" + +/** List of response message IDs */ +#define BMKT_RSP_CONTINUOUS_IMAGE_CAPTURE_FAIL 0x02 +#define BMKT_RSP_CONTINUOUS_IMAGE_CAPTURE_READY 0x03 +#define BMKT_RSP_CONTINUOUS_IMAGE_CAPTURE_STOPPED 0x05 +#define BMKT_RSP_SENSOR_MODULE_TEST_READY 0x07 +#define BMKT_RSP_SENSOR_MODULE_TEST_FAIL 0x09 +#define BMKT_RSP_SENSOR_MODULE_TEST_REPORT 0x0A +#define BMKT_RSP_NEXT_TEST_REPORT_CHUNK 0x0C + +/*! \addtogroup init + * Response IDs returned by fingerprint initialization operation + * @{ + */ +/** Failed to initialize fingerprint sensor module */ +#define BMKT_RSP_FPS_INIT_FAIL 0x12 +/** Successfully initialized fingerprint sensor module */ +#define BMKT_RSP_FPS_INIT_OK 0x13 +/*! @} */ + +/*! \addtogroup mode + * Response IDs returned by get fingerprint mode operation + * @{ + */ +/** Failed to get fingerprint sensor module’s current operational mode */ +#define BMKT_RSP_FPS_MODE_FAIL 0x22 +/** + * BMKT_RSP_FPS_MODE_REPORT: + * Response containing the current operational mode of the fingerprint sensor module + *
Payload data represented in \ref bmkt_fps_mode_resp_t struct + */ +#define BMKT_RSP_FPS_MODE_REPORT 0x23 +/*! @} */ + +/*! \addtogroup setseclevel + * Response IDs returned by set security level operation + * @{ + */ +/** Failed to set fingerprint sensor module security level */ +#define BMKT_RSP_SET_SECURITY_LEVEL_FAIL 0x32 +/** + * BMKT_RSP_SET_SECURITY_LEVEL_REPORT: + * Security level of the fingerprint sensor module was set successfully + *
Contains payload data represented in \ref bmkt_set_sec_level_resp_t struct + */ +#define BMKT_RSP_SET_SECURITY_LEVEL_REPORT 0x33 +/*! @} */ + +/*! \addtogroup getseclevel + * Response IDs returned by get security level operation + * @{ + */ +/** Failed to get fingerprint sensor module security level */ +#define BMKT_RSP_GET_SECURITY_LEVEL_FAIL 0x35 +/** + * BMKT_RSP_GET_SECURITY_LEVEL_REPORT: + * Returns the current security level of the fingerprint sensor module + *
Contains payload data represented in \ref bmkt_set_sec_level_resp_t struct + */ +#define BMKT_RSP_GET_SECURITY_LEVEL_REPORT 0x36 +/*! @} */ + +/*! \addtogroup cancelop + * Response IDs returned by cancel_operation operation + * @{ + */ +/** + * BMKT_RSP_CANCEL_OP_OK: + * Successfully canceled the current operation and returned + * fingerprint sensor module to idle mode + */ +#define BMKT_RSP_CANCEL_OP_OK 0x42 +/** Failed to cancel the current operation */ +#define BMKT_RSP_CANCEL_OP_FAIL 0x43 +/*! @} */ + +/*! \addtogroup enrollment + * Response IDs returned by enrollment operation + * @{ + */ +/** + * BMKT_RSP_ENROLL_READY: + * Fingerprint enrollment session has begun and the user can place + * their finger on the sensor + */ +#define BMKT_RSP_ENROLL_READY 0x54 +/** Progress of the currently on-going fingerprint enrollment session */ +#define BMKT_RSP_ENROLL_REPORT 0x55 +/** Enrollment has been paused */ +#define BMKT_RSP_ENROLL_PAUSED 0x56 +/** Enrollment has been resume */ +#define BMKT_RSP_ENROLL_RESUMED 0x57 +/** The current enrollment session has encountered an error */ +#define BMKT_RSP_ENROLL_FAIL 0x58 +/** + * BMKT_RSP_ENROLL_OK: + * User has been successfully enrolled into the fingerprint sensor module + *
Contains payload data represented in \ref bmkt_enroll_resp_t struct + */ +#define BMKT_RSP_ENROLL_OK 0x59 + +/** + * BMKT_RSP_CAPTURE_COMPLETE: + * Fingerprint image capture is complete and it is safe for the user + * to lift their finger off the sensor + */ +#define BMKT_RSP_CAPTURE_COMPLETE 0x60 +/*! @} */ + +/*! \addtogroup identify + * Response IDs returned by identify operation. + * @{ + */ +/* Fingerprint identification session has begun */ +#define BMKT_RSP_ID_READY 0x62 +/* Identification has failed */ +#define BMKT_RSP_ID_FAIL 0x63 +/** + * BMKT_RSP_ID_OK: + * User has been successfully identified + *
Contains payload data represented in \ref bmkt_auth_resp struct + */ +#define BMKT_RSP_ID_OK 0x64 +/*! @} */ + +/*! \addtogroup verify + * Response IDs returned by identify operation. + * @{ + */ +/** Fingerprint verification session has begun */ +#define BMKT_RSP_VERIFY_READY 0x66 +/** Verification has failed */ +#define BMKT_RSP_VERIFY_FAIL 0x67 +/** + * BMKT_RSP_VERIFY_OK: + * User’s identity has been successfully verified + *
Contains payload data represented in \ref bmkt_auth_resp struct + */ +#define BMKT_RSP_VERIFY_OK 0x68 +/*! @} */ + +/** + * BMKT_RSP_TEMPLATE_RECORDS_REPORT: + * Response ID returned by get enrolled users templates record operation + *
Returns list of template records containing user IDs and corresponding finger IDs + *
Payload data represented in \ref bmkt_enroll_templates_resp_t struct + */ +#define BMKT_RSP_TEMPLATE_RECORDS_REPORT 0x75 + +/** + * BMKT_RSP_QUERY_RESPONSE_COMPLETE: + * Response ID returned by get next query response operation + *
Complete sequence of messages containing the template records query response has been sent + */ +#define BMKT_RSP_QUERY_RESPONSE_COMPLETE 0x76 + +/** + * BMKT_RSP_GET_ENROLLED_FINGERS_REPORT: + * Response ID returned by get enrolled fingers operation + *
Returns list of IDs of enrolled fingers for a specific user, + * along with template record status corresponding to each enrolled finger + *
Contains payload data represented in \ref bmkt_enrolled_fingers_resp_t struct + */ +#define BMKT_RSP_GET_ENROLLED_FINGERS_REPORT 0x77 + +/*! \addtogroup dbcapacity + * Response IDs returned by get database capacity operation + * @{ + */ +/** + * BMKT_RSP_DATABASE_CAPACITY_REPORT: + * Response specifying total capacity of fingerprint template database and + * how much free capacity is remaining along with how many templates are corrupted and + * how many bad (permanently unusable) storage slots are there. + *
Payload data represented in \ref bmkt_get_db_capacity_resp_t struct + */ +#define BMKT_RSP_DATABASE_CAPACITY_REPORT 0x78 +/** Failed to execute database query */ +#define BMKT_RSP_QUERY_FAIL 0x79 +/*! @} */ + +/*! \addtogroup deluser + * Response IDs returned by delete fingerprint of specific user operation + * @{ + */ +/** Failed to delete a user’s fingerprint template from the database */ +#define BMKT_RSP_DEL_USER_FP_FAIL 0x82 +/** + * BMKT_RSP_DEL_USER_FP_OK: + * Fingerprint template successfully deleted from the database. + * Returns the user ID and finger ID deleted. If value of finger ID is set equal to 0, + * then all fingerprint templates for that user have been deleted from the database + *
Payload data represented in \ref bmkt_del_user_resp_t struct + */ +#define BMKT_RSP_DEL_USER_FP_OK 0x83 +/*! @} */ + +/*! \addtogroup delfulldb + * Response IDs returned by delete entire fingerprint template DB operation + * @{ + */ +/** Failed to erase entire fingerprint template database */ +#define BMKT_RSP_DEL_FULL_DB_FAIL 0x85 +/** Successfully erased entire fingerprint template database */ +#define BMKT_RSP_DEL_FULL_DB_OK 0x86 +/** + * BMKT_RSP_DELETE_PROGRESS: + * Notify progress made during the on-going deletion of the full template database + *
Payload data represented in \ref bmkt_del_all_users_resp_t struct + */ +#define BMKT_RSP_DELETE_PROGRESS 0x87 +/*! @} */ + +/** + * BMKT_RSP_REPEAT_LAST_BMKT_RSP_FAIL: + * Response ID returned by repeate last response operation + *
Failed to retrieve and re-send last response + */ +#define BMKT_RSP_REPEAT_LAST_BMKT_RSP_FAIL 0x93 + +/*! \addtogroup pwrdwn + * Response IDs returned by power down notify operation + * @{ + */ +/** Fingerprint sensor module is ready to be powered down */ +#define BMKT_RSP_POWER_DOWN_READY 0xA2 +/** Failed to go into power down mode */ +#define BMKT_RSP_POWER_DOWN_FAIL 0xA3 +/*! @} */ + +/*! \addtogroup versioninfo + * Response IDs returned by get version operation + * @{ + */ +/** + * BMKT_RSP_VERSION_INFO: + * System version information of the fingerprint sensor module + *
Payload data represented in \ref bmkt_get_version_resp_t struct + */ +#define BMKT_RSP_VERSION_INFO 0xB2 +/* Failed to retrieve and send last response */ +#define BMKT_RSP_GET_VERSION_FAIL 0xB3 +/*! @} */ + +/** + * BMKT_RSP_GENERAL_ERROR: + * Not tied to a specific command-response session. + *
Could be caused by corrupt or truncated command message + */ +#define BMKT_RSP_GENERAL_ERROR 0xC1 +#define BMKT_RSP_DISABLE_PAIRING_FAIL 0xC3 +#define BMKT_RSP_DISABLE_PAIRING_OK 0xC4 +#define BMKT_RSP_QUERY_PAIRING_FAIL 0xC6 +#define BMKT_RSP_SENSOR_PAIRING_REPORT 0xC7 + +/*! \addtogroup versioninfo + * Response IDs returned by get sensor module status operation + * @{ + */ +/** + * BMKT_RSP_SENSOR_STATUS_REPORT: + * Response returning the current status of the sensor module + *
Payload data represented in bmkt_XXX struct + */ +#define BMKT_RSP_SENSOR_STATUS_REPORT 0xD2 +/** Failed to retrieve sensor status */ +#define BMKT_RSP_SENSOR_STATUS_FAIL 0xD3 +/*! @} */ + +/** + * BMKT_RSP_SEND_NEXT_USER_ID: + * Response ID returned by identify user in order operation + *
Notify to send the next batch of user IDs in the priority list + */ +#define BMKT_RSP_SEND_NEXT_USER_ID 0xE2 +/** + * BMKT_RSP_RETRIEVE_FINAL_RESULT_FAIL: + * Response IDs returned by retrieve final result operation + *
Failed to retrieve and re-send cached final result + */ +#define BMKT_RSP_RETRIEVE_FINAL_RESULT_FAIL 0xE5 + +/** + * Response payload data structure returned by sensor initialization operation. + */ +typedef struct bmkt_init_resp +{ + uint8_t finger_presence; /**< Indicates finger existence on the sensor during startup */ +} bmkt_init_resp_t; + +/** + * bmkt_enroll_resp: + * Response payload data structure returned by enrollment operation. + */ +typedef struct bmkt_enroll_resp +{ + int progress; /**< Shows current progress stutus [0-100] */ + uint8_t finger_id; /**< User's finger id [1-10] */ + uint8_t user_id[BMKT_MAX_USER_ID_LEN]; /**< User name to be enrolled */ +} bmkt_enroll_resp_t; + +/** + * bmkt_auth_resp: + * Response payload data structure returned by identify and verify operations. + */ +struct bmkt_auth_resp +{ + double match_result; /**< match result returned by matcher */ + uint8_t finger_id; /**< Matched templates's finger id */ + uint8_t user_id[BMKT_MAX_USER_ID_LEN]; /**< Matched template's user id */ +}; + +typedef struct bmkt_auth_resp bmkt_verify_resp_t; /**< Returned by verify */ +typedef struct bmkt_auth_resp bmkt_identify_resp_t; /**< Returned by identify */ + +/** + * bmkt_fps_mode_resp: + * Response payload data structure returned by get fingerprint mode operation. + */ +typedef struct bmkt_fps_mode_resp +{ + uint8_t mode; /**< One of the Level I bmkt_mode_t values */ + uint8_t level2_mode; /**< One of the Level II bmkt_mode_level2_t values */ + uint8_t cmd_id; /**< Message ID of command being executed when bmkt_get_fps_mode was called */ + uint8_t finger_presence; /**< Finger presence status value finger on sensor 1 / finger not on sensor 0 */ +} bmkt_fps_mode_resp_t; + +/** + * bmkt_get_version_resp: + * Response payload data structure returned by get version operation. + */ +typedef struct bmkt_get_version_resp +{ + uint8_t part[BMKT_PART_NUM_LEN]; /**< Software Part Number */ + uint8_t year; /**< Software Version Year */ + uint8_t week; /**< Software Version Week */ + uint8_t patch; /**< Software Version Patch Level */ + uint8_t supplier_id[BMKT_SUPPLIER_ID_LEN]; /**< Software Supplier Identification */ +} bmkt_get_version_resp_t; + +/** + * bmkt_get_db_capacity_resp: + * Response payload data structure returned by get DB capacity operation. + */ +typedef struct bmkt_get_db_capacity_resp +{ + uint8_t total; /**< Total Available Capacity: Total number of template records that can be stored */ + uint8_t empty; /**< Free Capacity: Number of template records that can still be stored */ + uint8_t bad_slots; /**< Number of bad template storage slots */ + uint8_t corrupt_templates; /**< Number of corrupt templates */ +} bmkt_get_db_capacity_resp_t; + +/** + * bmkt_sec_level: + * Security level values. + */ +typedef enum bmkt_sec_level { + BMKT_SECURITY_LEVEL_LOW = 0x10, + BMKT_SECURITY_LEVEL_MEDIUM = 0x40, + BMKT_SECURITY_LEVEL_HIGH = 0x60, +} bmkt_sec_level_t; + +/** + * bmkt_set_sec_level_resp: + * Response payload data structure returned by get/set security level operations. + */ +typedef struct bmkt_set_sec_level_resp +{ + bmkt_sec_level_t sec_level; /**< One of the bmkt_sec_level_t values */ +} bmkt_set_sec_level_resp_t; + +/** + * bmkt_del_all_users_resp: + * Response payload data structure returned by delete all enrolled users operation. + */ +typedef struct bmkt_del_all_users_resp +{ + int progress; /**< Progress indicator as a percentage */ +} bmkt_del_all_users_resp_t; + +/** + * bmkt_del_user_resp: + * Response payload data structure returned by delete enrolled user operation. + */ +typedef struct bmkt_del_user_resp +{ + int progress; /**< Progress indicator as a percentage */ +} bmkt_del_user_resp_t; + +/** + * bmkt_enroll_template: + * Structure of enrolled users template record data. + */ +typedef struct bmkt_enroll_template +{ + uint8_t user_id_len; /**< Length of user_id string */ + uint8_t template_status; /**< Template record status */ + uint8_t finger_id; /**< ID of enrolled finger */ + uint8_t user_id[BMKT_MAX_USER_ID_LEN + 1]; /**< Name of the enrolled user */ +} bmkt_enroll_template_t; + +/** + * bmkt_enroll_templates_resp: + * Response payload data structure returned by get enrolled user list operation. + */ +typedef struct bmkt_enroll_templates_resp +{ + uint8_t total_query_messages; /**< Total query response messages */ + uint8_t query_sequence; /**< Query response sequence number */ + bmkt_enroll_template_t templates[BMKT_MAX_NUM_TEMPLATES_INTERNAL_FLASH]; /**< Enrolled user template records list */ +} bmkt_enroll_templates_resp_t; + +/** + * bmkt_enrolled_fingers: + * Structure of template record status corresponding to each enrolled finger. + */ +typedef struct bmkt_enrolled_fingers +{ + uint8_t finger_id; /**< ID of enrolled finger */ + uint8_t template_status; /**< Template record status of finger_id */ +} bmkt_enrolled_fingers_t; + +/** + * bmkt_enrolled_fingers_resp: + * Response payload data structure returned by get enrolled fingers operation. + */ +typedef struct bmkt_enrolled_fingers_resp +{ + bmkt_enrolled_fingers_t fingers[10]; /**< List of enroled fingers, max number of supported fingers per user is 10 */ +} bmkt_enrolled_fingers_resp_t; + +/** + * bmkt_response_data_t: + * Union combining all response payload data types. + */ +typedef union +{ + bmkt_init_resp_t init_resp; + bmkt_enroll_resp_t enroll_resp; + bmkt_verify_resp_t verify_resp; + bmkt_identify_resp_t id_resp; + bmkt_fps_mode_resp_t fps_mode_resp; + bmkt_get_version_resp_t get_version_resp; + bmkt_get_db_capacity_resp_t db_cap_resp; + bmkt_set_sec_level_resp_t sec_level_resp; + bmkt_del_all_users_resp_t del_all_users_resp; + bmkt_enroll_templates_resp_t enroll_templates_resp; + bmkt_del_user_resp_t del_user_resp; + bmkt_enrolled_fingers_resp_t enrolled_fingers_resp; +} bmkt_response_data_t; + +/** + * bmkt_response: + * Structure to abstract different response structure types in one API + * to be used in bmkt_resp_cb_t callback function. + */ +typedef struct bmkt_response +{ + int response_id; /**< Response message ID, one of th BMKT_RSP_XXX */ + int result; /**< Operation execution result code */ + int complete; /**< Operation completion status 1: complete / 0: not completed */ + bmkt_response_data_t response; /**< Operation specific response union */ +} bmkt_response_t; + +#endif /* _BMKT_RESPONSE_H_ */ diff --git a/libfprint/drivers/synaptics/sensor.h b/libfprint/drivers/synaptics/sensor.h new file mode 100644 index 00000000..922b1dd6 --- /dev/null +++ b/libfprint/drivers/synaptics/sensor.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2019 Synaptics Inc + * + * 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 + */ + +#ifndef _SENSOR_H_ +#define _SENSOR_H_ + +#include "usb_transport.h" +#define BMKT_MAX_PENDING_SESSIONS 2 + +typedef enum bmkt_sensor_state { + BMKT_SENSOR_STATE_UNINIT = 0, + BMKT_SENSOR_STATE_IDLE, + BMKT_SENSOR_STATE_INIT, + BMKT_SENSOR_STATE_EXIT, +} bmkt_sensor_state_t; + +typedef struct bmkt_sensor_drv bmkt_sensor_drv_t; + +typedef struct bmkt_sensor_version +{ + uint32_t build_time; + uint32_t build_num; + uint8_t version_major; + uint8_t version_minor; + uint8_t target; + uint8_t product; + uint8_t silicon_rev; + uint8_t formal_release; + uint8_t platform; + uint8_t patch; + uint8_t serial_number[6]; + uint16_t security; + uint8_t iface; + uint8_t device_type; +} bmkt_sensor_version_t; + +typedef struct bmkt_sensor +{ + bmkt_usb_transport_t usb_xport; + bmkt_sensor_version_t version; + bmkt_session_ctx_t pending_sessions[BMKT_MAX_PENDING_SESSIONS]; + int empty_session_idx; + int flags; + int seq_num; + bmkt_sensor_state_t sensor_state; + bmkt_event_cb_t finger_event_cb; + void *finger_cb_ctx; + bmkt_general_error_cb_t gen_err_cb; + void *gen_err_cb_ctx; + bmkt_op_state_t op_state; +} bmkt_sensor_t; + +int bmkt_sensor_open (bmkt_sensor_t *sensor, + bmkt_general_error_cb_t err_cb, + void *err_cb_ctx); +int bmkt_sensor_close (bmkt_sensor_t *sensor); + +int bmkt_sensor_init_fps (bmkt_sensor_t *sensor); + +int bmkt_sensor_send_message (bmkt_sensor_t *sensor, + uint8_t msg_id, + uint8_t payload_size, + uint8_t *payload, + bmkt_resp_cb_t resp_cb, + void *resp_data); +int bmkt_sensor_handle_response (bmkt_sensor_t *sensor, + uint8_t *resp_buf, + int resp_len, + bmkt_msg_resp_t *msg_resp); + +int bmkt_sensor_send_async_read_command (bmkt_sensor_t *sensor); +#endif /* _SENSOR_H_ */ diff --git a/libfprint/drivers/synaptics/synaptics.c b/libfprint/drivers/synaptics/synaptics.c new file mode 100644 index 00000000..b1d73650 --- /dev/null +++ b/libfprint/drivers/synaptics/synaptics.c @@ -0,0 +1,1206 @@ +/* + * Copyright (C) 2019 Synaptics Inc + * + * 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 "synaptics" + +#include "drivers_api.h" + +#include "fpi-byte-reader.h" + +#include "synaptics.h" +#include "bmkt_message.h" + +G_DEFINE_TYPE (FpiDeviceSynaptics, fpi_device_synaptics, FP_TYPE_DEVICE) + +static const FpIdEntry id_table[] = { + { .vid = SYNAPTICS_VENDOR_ID, .pid = 0xBD, }, + + { .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */ +}; + + +static void +cmd_recieve_cb (FpiUsbTransfer *transfer, + FpDevice *device, + gpointer user_data, + GError *error) +{ + FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device); + SynCmdMsgCallback callback = user_data; + int res; + bmkt_msg_resp_t msg_resp; + bmkt_response_t resp; + + if (error) + { + /* NOTE: assumes timeout should never happen for receiving. */ + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } + + res = bmkt_parse_message_header (&transfer->buffer[SENSOR_FW_REPLY_HEADER_LEN], + transfer->actual_length - SENSOR_FW_REPLY_HEADER_LEN, + &msg_resp); + if (res != BMKT_SUCCESS) + { + g_warning ("Corrupted message received"); + fpi_ssm_mark_failed (transfer->ssm, + fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); + return; + } + + /* Special case events */ + if (msg_resp.msg_id == BMKT_EVT_FINGER_REPORT) + { + if (msg_resp.payload_len != 1) + { + g_warning ("Corrupted finger report received"); + fpi_ssm_mark_failed (transfer->ssm, + fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); + return; + } + + if (msg_resp.payload[0] == 0x01) + { + self->finger_on_sensor = TRUE; + } + else + { + self->finger_on_sensor = FALSE; + if (self->cmd_complete_on_removal) + { + fpi_ssm_mark_completed (transfer->ssm); + return; + } + } + + fp_dbg ("Finger is now %s the sensor", self->finger_on_sensor ? "on" : "off"); + + /* XXX: Call callback!?! */ + } + + res = bmkt_parse_message_payload (&msg_resp, &resp); + if (res != BMKT_SUCCESS) + { + g_warning ("Could not parse message payload: %i", res); + fpi_ssm_mark_failed (transfer->ssm, + fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); + return; + } + + /* Special cancellation handling */ + if (resp.response_id == BMKT_RSP_CANCEL_OP_OK || resp.response_id == BMKT_RSP_CANCEL_OP_FAIL) + { + if (resp.response_id == BMKT_RSP_CANCEL_OP_OK) + { + fp_dbg ("Received cancellation success resonse"); + fpi_ssm_mark_failed (transfer->ssm, + g_error_new_literal (G_IO_ERROR, + G_IO_ERROR_CANCELLED, + "Device reported cancellation of operation")); + } + else + { + fp_dbg ("Cancellation failed, this should not happen"); + fpi_ssm_mark_failed (transfer->ssm, + fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); + } + return; + } + + if (msg_resp.seq_num == 0) + { + /* XXX: Should we really abort the command on general error? + * The original code did not! */ + if (msg_resp.msg_id == BMKT_RSP_GENERAL_ERROR) + { + guint16 err; + + /* XXX: It is weird that this is big endian. */ + err = FP_READ_UINT16_BE (msg_resp.payload); + + fp_warn ("Received General Error %d from the sensor", (guint) err); + fpi_ssm_mark_failed (transfer->ssm, + fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Received general error from device")); + //fpi_ssm_jump_to_state (transfer->ssm, fpi_ssm_get_cur_state (transfer->ssm)); + return; + } + else + { + fp_dbg ("Received message with 0 sequence number 0x%02x, ignoring!", + msg_resp.msg_id); + fpi_ssm_next_state (transfer->ssm); + return; + } + } + + /* We should only ever have one command running, and the sequence num needs + * to match. */ + if (msg_resp.seq_num != self->cmd_seq_num) + { + fp_warn ("Got unexpected sequence number from device, %d instead of %d", + msg_resp.seq_num, + self->cmd_seq_num); + } + + if (callback) + callback (self, &resp, NULL); + + /* Callback may have queued a follow up command, then we need + * to restart the SSM. If not, we'll finish/wait for interrupt + * depending on resp.complete. */ + if (self->cmd_pending_transfer) + fpi_ssm_jump_to_state (transfer->ssm, SYNAPTICS_CMD_SEND_PENDING); + else if (!resp.complete) + fpi_ssm_next_state (transfer->ssm); /* SYNAPTICS_CMD_WAIT_INTERRUPT */ + else + fpi_ssm_mark_completed (transfer->ssm); +} + +static void +cmd_interrupt_cb (FpiUsbTransfer *transfer, + FpDevice *device, + gpointer user_data, + GError *error) +{ + g_debug ("interrupt transfer done"); + if (error) + { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + { + g_error_free (error); + fpi_ssm_jump_to_state (transfer->ssm, SYNAPTICS_CMD_GET_RESP); + return; + } + + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } + g_clear_pointer (&error, g_error_free); + + if (transfer->buffer[0] & USB_ASYNC_MESSAGE_PENDING || error) + fpi_ssm_next_state (transfer->ssm); + else + fpi_usb_transfer_submit (transfer, 1000, NULL, cmd_interrupt_cb, NULL); +} + +static void +synaptics_cmd_run_state (FpiSsm *ssm, + FpDevice *dev) +{ + g_autoptr(FpiUsbTransfer) transfer = NULL; + FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (dev); + + switch (fpi_ssm_get_cur_state (ssm)) + { + case SYNAPTICS_CMD_SEND_PENDING: + if (self->cmd_pending_transfer) + { + self->cmd_pending_transfer->ssm = ssm; + fpi_usb_transfer_submit (self->cmd_pending_transfer, + 1000, + NULL, + fpi_ssm_usb_transfer_cb, + NULL); + g_clear_pointer (&self->cmd_pending_transfer, fpi_usb_transfer_unref); + } + else + { + fpi_ssm_next_state (ssm); + } + break; + + case SYNAPTICS_CMD_GET_RESP: + transfer = fpi_usb_transfer_new (dev); + transfer->ssm = ssm; + fpi_usb_transfer_fill_bulk (transfer, USB_EP_REPLY, MAX_TRANSFER_LEN); + fpi_usb_transfer_submit (transfer, + 5000, + NULL, + cmd_recieve_cb, + fpi_ssm_get_data (ssm)); + + break; + + case SYNAPTICS_CMD_WAIT_INTERRUPT: + transfer = fpi_usb_transfer_new (dev); + transfer->ssm = ssm; + fpi_usb_transfer_fill_interrupt (transfer, USB_EP_INTERRUPT, USB_INTERRUPT_DATA_SIZE); + fpi_usb_transfer_submit (transfer, + 0, + self->interrupt_cancellable, + cmd_interrupt_cb, + NULL); + + break; + + case SYNAPTICS_CMD_SEND_ASYNC: + transfer = fpi_usb_transfer_new (dev); + transfer->ssm = ssm; + fpi_usb_transfer_fill_bulk (transfer, USB_EP_REQUEST, SENSOR_FW_CMD_HEADER_LEN); + transfer->buffer[0] = SENSOR_CMD_ASYNCMSG_READ; + fpi_usb_transfer_submit (transfer, + 1000, + NULL, + fpi_ssm_usb_transfer_cb, + NULL); + + break; + + case SYNAPTICS_CMD_RESTART: + fpi_ssm_jump_to_state (ssm, SYNAPTICS_CMD_SEND_PENDING); + break; + } +} + +static void +cmd_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error) +{ + FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (dev); + SynCmdMsgCallback callback = fpi_ssm_get_data (ssm); + + self->cmd_ssm = NULL; + + /* Notify about the SSM failure from here instead. */ + if (error) + { + callback (self, NULL, error); + } + else if (self->cmd_complete_on_removal) + { + callback (self, NULL, self->cmd_complete_error); + self->cmd_complete_error = NULL; + } + self->cmd_complete_on_removal = FALSE; + g_clear_pointer (&self->cmd_complete_error, g_error_free); + fpi_ssm_free (ssm); +} + +static void +cmd_forget_cb (FpiUsbTransfer *transfer, + FpDevice *device, + gpointer user_data, + GError *error) +{ + if (error) + { + g_warning ("Async command sending failed: %s", error->message); + g_error_free (error); + } + else + { + g_debug ("Async command sent successfully"); + } +} + +static void +synaptics_sensor_cmd (FpiDeviceSynaptics *self, + gint seq_num, + guint8 msg_id, + const guint8 * payload, + gssize payload_len, + SynCmdMsgCallback callback) +{ + g_autoptr(FpiUsbTransfer) transfer = NULL; + guint8 real_seq_num; + gint msg_len; + gint res; + + /* callback may be NULL in two cases: + * - seq_num == -1 + * - a state machine is already running, continued command */ + g_assert (payload || payload_len == 0); + + /* seq_num of 0 means a normal command, -1 means the current commands + * sequence number should not be udpated (i.e. second async command which + * may only be a cancellation currently). */ + if (seq_num <= 0) + { + 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; + } + else + { + real_seq_num = seq_num; + self->last_seq_num = real_seq_num; + } + g_debug ("sequence number is %d", real_seq_num); + + /* We calculate the exact length here (we could also just create a larger + * buffer instead and check the result of bmkt_compose_message. */ + msg_len = BMKT_MESSAGE_HEADER_LEN + payload_len; + + /* Send out the command */ + transfer = fpi_usb_transfer_new (FP_DEVICE (self)); + transfer->short_is_error = TRUE; + fpi_usb_transfer_fill_bulk (transfer, + USB_EP_REQUEST, + msg_len + SENSOR_FW_CMD_HEADER_LEN); + + /* MIS sensors send ACE commands encapsulated in FW commands*/ + transfer->buffer[0] = SENSOR_CMD_ACE_COMMAND; + res = bmkt_compose_message (&transfer->buffer[1], + &msg_len, msg_id, + real_seq_num, + payload_len, + payload); + g_assert (res == BMKT_SUCCESS); + g_assert (msg_len + SENSOR_FW_CMD_HEADER_LEN == transfer->length); + + /* Special case for async command sending (should only be used for + * cancellation). */ + if (seq_num == -1) + { + g_assert (callback == NULL); + + /* We just send and forget here. */ + fpi_usb_transfer_submit (transfer, 1000, NULL, cmd_forget_cb, NULL); + } + else + { + /* Command should be send using the state machine. */ + g_assert (self->cmd_pending_transfer == NULL); + + self->cmd_pending_transfer = g_steal_pointer (&transfer); + + if (self->cmd_ssm) + { + /* Continued command, we already have an SSM with a callback. + * There is nothing to do in this case, the command will be + * sent automatically. */ + g_assert (callback == NULL); + } + else + { + /* Start of a new command, create the state machine. */ + g_assert (callback != NULL); + + self->cmd_ssm = fpi_ssm_new (FP_DEVICE (self), + synaptics_cmd_run_state, + SYNAPTICS_CMD_NUM_STATES); + fpi_ssm_set_data (self->cmd_ssm, callback, NULL); + + fpi_ssm_start (self->cmd_ssm, cmd_ssm_done); + } + } +} + +static gboolean +parse_print_data (GVariant *data, + guint8 *finger, + const guint8 **user_id, + gssize *user_id_len) +{ + g_autoptr(GVariant) user_id_var = NULL; + + g_return_val_if_fail (data != NULL, FALSE); + g_return_val_if_fail (finger != NULL, FALSE); + g_return_val_if_fail (user_id != NULL, FALSE); + g_return_val_if_fail (user_id_len != NULL, FALSE); + + *user_id = NULL; + *user_id_len = 0; + + if (!g_variant_check_format_string (data, "(y@ay)", FALSE)) + return FALSE; + + g_variant_get (data, + "(y@ay)", + finger, + &user_id_var); + + *user_id = g_variant_get_fixed_array (user_id_var, user_id_len, 1); + + if (*user_id_len == 0 || *user_id_len > BMKT_MAX_USER_ID_LEN) + return FALSE; + + if (*user_id_len <= 0 || *user_id[0] == ' ') + return FALSE; + + return TRUE; +} + +static void +list_msg_cb (FpiDeviceSynaptics *self, + bmkt_response_t *resp, + GError *error) +{ + bmkt_enroll_templates_resp_t *get_enroll_templates_resp; + + if (error) + { + g_clear_pointer (&self->list_result, g_ptr_array_free); + fpi_device_list_complete (FP_DEVICE (self), NULL, error); + return; + } + + get_enroll_templates_resp = &resp->response.enroll_templates_resp; + + switch (resp->response_id) + { + case BMKT_RSP_QUERY_FAIL: + if (resp->result == BMKT_FP_DATABASE_EMPTY) + { + fp_info ("Database is empty"); + + fpi_device_list_complete (FP_DEVICE (self), + g_steal_pointer (&self->list_result), + NULL); + } + else + { + fp_info ("Failed to query enrolled users: %d", resp->result); + g_clear_pointer (&self->list_result, g_ptr_array_free); + fpi_device_list_complete (FP_DEVICE (self), + NULL, + fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, + "Failed to query enrolled users")); + } + break; + + case BMKT_RSP_QUERY_RESPONSE_COMPLETE: + fp_info ("Query complete!"); + + fpi_device_list_complete (FP_DEVICE (self), + g_steal_pointer (&self->list_result), + NULL); + + break; + + case BMKT_RSP_TEMPLATE_RECORDS_REPORT: + + 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; + + fp_info ("![query %d of %d] template %d: status=0x%x, userId=%s, fingerId=%d", + get_enroll_templates_resp->query_sequence, + get_enroll_templates_resp->total_query_messages, + n, + get_enroll_templates_resp->templates[n].template_status, + get_enroll_templates_resp->templates[n].user_id, + get_enroll_templates_resp->templates[n].finger_id); + + userid = 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, FP_PRINT_RAW); + fpi_print_set_device_stored (print, TRUE); + g_object_set (print, "fp-data", data, NULL); + g_object_set (print, "description", get_enroll_templates_resp->templates[n].user_id, NULL); + + /* The format has 24 bytes at the start and some dashes in the right places */ + if (g_str_has_prefix (userid, "FP1-") && strlen (userid) >= 24 && + userid[12] == '-' && userid[14] == '-' && userid[23] == '-') + { + g_autofree gchar *copy = g_strdup (userid); + gint32 date_ymd; + GDate *date = NULL; + gint32 finger; + gchar *username; + /* Try to parse information from the string. */ + + copy[12] = '\0'; + date_ymd = g_ascii_strtod (copy + 4, NULL); + if (date_ymd > 0) + date = g_date_new_dmy (date_ymd % 100, + (date_ymd / 100) % 100, + date_ymd / 10000); + else + date = g_date_new (); + + fp_print_set_enroll_date (print, date); + g_date_free (date); + + copy[14] = '\0'; + finger = g_ascii_strtoll (copy + 13, NULL, 16); + fp_print_set_finger (print, finger); + + /* We ignore the next chunk, it is just random data. + * Then comes the username; nobody is the default if the metadata + * is unknown */ + username = copy + 24; + if (strlen (username) > 0 && g_strcmp0 (username, "nobody") != 0) + fp_print_set_username (print, username); + } + + g_ptr_array_add (self->list_result, g_object_ref_sink (print)); + } + + synaptics_sensor_cmd (self, + self->cmd_seq_num, + BMKT_CMD_GET_NEXT_QUERY_RESPONSE, + NULL, + 0, + NULL); + + break; + } +} + +static void +list (FpDevice *device) +{ + FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device); + + G_DEBUG_HERE (); + + self->list_result = g_ptr_array_new_with_free_func (g_object_unref); + synaptics_sensor_cmd (self, 0, BMKT_CMD_GET_TEMPLATE_RECORDS, NULL, 0, list_msg_cb); +} + +static void +verify_msg_cb (FpiDeviceSynaptics *self, + bmkt_response_t *resp, + GError *error) +{ + FpDevice *device = FP_DEVICE (self); + bmkt_verify_resp_t *verify_resp; + + if (error) + { + fpi_device_verify_complete (device, FPI_MATCH_ERROR, NULL, error); + return; + } + + if (resp == NULL && self->cmd_complete_on_removal) + { + fpi_device_verify_complete (device, + GPOINTER_TO_INT (self->cmd_complete_data), + NULL, + error); + return; + } + + verify_resp = &resp->response.verify_resp; + + switch (resp->response_id) + { + case BMKT_RSP_VERIFY_READY: + fp_info ("Place Finger on the Sensor!"); + break; + + case BMKT_RSP_CAPTURE_COMPLETE: + fp_info ("Fingerprint image capture complete!"); + break; + + case BMKT_RSP_VERIFY_FAIL: + if(resp->result == BMKT_SENSOR_STIMULUS_ERROR) + { + fp_dbg ("delaying retry error until after finger removal!"); + self->cmd_complete_on_removal = TRUE; + self->cmd_complete_data = GINT_TO_POINTER (FPI_MATCH_ERROR); + self->cmd_complete_error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL); + } + else if (resp->result == BMKT_FP_NO_MATCH) + { + fp_dbg ("delaying match failure until after finger removal!"); + self->cmd_complete_on_removal = TRUE; + self->cmd_complete_data = GINT_TO_POINTER (FPI_MATCH_FAIL); + self->cmd_complete_error = NULL; + } + else if (BMKT_FP_DATABASE_NO_RECORD_EXISTS) + { + fp_info ("Print is not in database"); + fpi_device_verify_complete (device, + FPI_MATCH_ERROR, + NULL, + fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND)); + } + else + { + fp_warn ("Verify has failed: %d", resp->result); + fpi_device_verify_complete (device, FPI_MATCH_FAIL, NULL, NULL); + } + break; + + case BMKT_RSP_VERIFY_OK: + 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_complete (device, FPI_MATCH_SUCCESS, NULL, NULL); + break; + } +} + +static void +verify (FpDevice *device) +{ + FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device); + FpPrint *print = NULL; + + g_autoptr(GVariant) data = NULL; + guint8 finger; + const guint8 *user_id; + gsize user_id_len = 0; + + fpi_device_get_verify_data (device, &print); + + g_object_get (print, "fp-data", &data, NULL); + g_debug ("data is %p", data); + if (!parse_print_data (data, &finger, &user_id, &user_id_len)) + { + fpi_device_verify_complete (device, + FPI_MATCH_ERROR, + NULL, + fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID)); + return; + } + + G_DEBUG_HERE (); + + synaptics_sensor_cmd (self, 0, BMKT_CMD_VERIFY_USER, user_id, user_id_len, verify_msg_cb); +} + +static void +enroll_msg_cb (FpiDeviceSynaptics *self, + bmkt_response_t *resp, + GError *error) +{ + FpDevice *device = FP_DEVICE (self); + bmkt_enroll_resp_t *enroll_resp; + + if (error) + { + fpi_device_enroll_complete (device, NULL, error); + return; + } + + enroll_resp = &resp->response.enroll_resp; + + switch (resp->response_id) + { + case BMKT_RSP_ENROLL_READY: + { + self->enroll_stage = 0; + fp_info ("Place Finger on the Sensor!"); + break; + } + + case BMKT_RSP_CAPTURE_COMPLETE: + { + fp_info ("Fingerprint image capture complete!"); + break; + } + + case BMKT_RSP_ENROLL_REPORT: + { + gint done_stages; + fp_info ("Enrollment is %d %% ", enroll_resp->progress); + + done_stages = (enroll_resp->progress * ENROLL_SAMPLES + 99) / 100; + if (enroll_resp->progress < 100) + done_stages = MIN (done_stages, ENROLL_SAMPLES - 1); + + /* Emit a retry error if there has been no discernable + * progress. Some firmware revisions report more required + * touches. */ + if (self->enroll_stage == done_stages) + { + fpi_device_enroll_progress (device, + done_stages, + NULL, + fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL)); + } + + while (self->enroll_stage < done_stages) + { + self->enroll_stage += 1; + fpi_device_enroll_progress (device, self->enroll_stage, NULL, NULL); + } + break; + } + + case BMKT_RSP_ENROLL_PAUSED: + { + fp_info ("Enrollment has been paused!"); + break; + } + + case BMKT_RSP_ENROLL_RESUMED: + { + fp_info ("Enrollment has been resumed!"); + break; + } + + case BMKT_RSP_ENROLL_FAIL: + { + fp_info ("Enrollment has failed!: %d", resp->result); + if (resp->result == BMKT_FP_DATABASE_FULL) + { + fpi_device_enroll_complete (device, + NULL, + fpi_device_error_new (FP_DEVICE_ERROR_DATA_FULL)); + } + else + { + fpi_device_enroll_complete (device, + NULL, + fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, + "Enrollment failed")); + } + break; + } + + case BMKT_RSP_ENROLL_OK: + { + FpPrint *print = NULL; + + fp_info ("Enrollment was successful!"); + + fpi_device_get_enroll_data (device, &print); + + fpi_device_enroll_complete (device, g_object_ref (print), NULL); + break; + } + } +} + +#define TEMPLATE_ID_SIZE 20 + +static void +enroll (FpDevice *device) +{ + FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device); + FpPrint *print = NULL; + GVariant *data = NULL; + GVariant *uid = NULL; + const gchar *username; + guint finger; + g_autofree gchar *user_id; + gssize user_id_len; + g_autofree guint8 *payload = NULL; + const GDate *date; + gint y, m, d; + gint32 rand_id = 0; + + fpi_device_get_enroll_data (device, &print); + + G_DEBUG_HERE (); + + date = fp_print_get_enroll_date (print); + if (date && g_date_valid (date)) + { + y = date->year; + m = date->month; + d = date->day; + } + else + { + y = 0; + m = 0; + d = 0; + } + + username = fp_print_get_username (print); + if (!username) + username = "nobody"; + + if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0) + rand_id = 0; + else + rand_id = g_random_int (); + + user_id = g_strdup_printf ("FP1-%04d%02d%02d-%X-%08X-%s", + y, m, d, + fp_print_get_finger (print), + rand_id, + username); + + user_id_len = strlen (user_id); + user_id_len = MIN (BMKT_MAX_USER_ID_LEN, user_id_len); + + /* We currently always use finger 1 from the devices piont of view */ + finger = 1; + + uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + user_id, + user_id_len, + 1); + data = g_variant_new ("(y@ay)", + finger, + uid); + + fpi_print_set_type (print, FP_PRINT_RAW); + fpi_print_set_device_stored (print, TRUE); + g_object_set (print, "fp-data", data, NULL); + g_object_set (print, "description", user_id, NULL); + + g_debug ("user_id: %s, finger: %d", user_id, finger); + + payload = g_malloc0 (user_id_len + 2); + + /* Backup options are not supported for Prometheus */ + payload[0] = 0; + payload[1] = finger; + memcpy (payload + 2, user_id, user_id_len); + + synaptics_sensor_cmd (self, 0, BMKT_CMD_ENROLL_USER, payload, user_id_len + 2, enroll_msg_cb); +} + +static void +delete_msg_cb (FpiDeviceSynaptics *self, + bmkt_response_t *resp, + GError *error) +{ + FpDevice *device = FP_DEVICE (self); + bmkt_del_user_resp_t *del_user_resp; + + if (error) + { + fpi_device_delete_complete (device, error); + return; + } + + del_user_resp = &resp->response.del_user_resp; + + switch (resp->response_id) + { + case BMKT_RSP_DELETE_PROGRESS: + fp_info ("Deleting Enrolled Users is %d%% complete", + del_user_resp->progress); + break; + + case BMKT_RSP_DEL_USER_FP_FAIL: + fp_info ("Failed to delete enrolled user: %d", resp->result); + if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS) + fpi_device_delete_complete (device, + fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND)); + else + fpi_device_delete_complete (device, + fpi_device_error_new (FP_DEVICE_ERROR_GENERAL)); + break; + + case BMKT_RSP_DEL_USER_FP_OK: + fp_info ("Successfully deleted enrolled user"); + fpi_device_delete_complete (device, NULL); + break; + } +} + +static void +delete_print (FpDevice *device) +{ + FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device); + FpPrint *print = NULL; + + g_autoptr(GVariant) data = NULL; + guint8 finger; + const guint8 *user_id; + gsize user_id_len = 0; + g_autofree guint8 *payload = NULL; + + fpi_device_get_delete_data (device, &print); + + g_object_get (print, "fp-data", &data, NULL); + g_debug ("data is %p", data); + if (!parse_print_data (data, &finger, &user_id, &user_id_len)) + { + fpi_device_delete_complete (device, + fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID)); + return; + } + + G_DEBUG_HERE (); + + payload = g_malloc0 (1 + user_id_len); + payload[0] = finger; + memcpy (payload + 1, user_id, user_id_len); + + synaptics_sensor_cmd (self, 0, BMKT_CMD_DEL_USER_FP, payload, user_id_len + 1, delete_msg_cb); +} + +static void +dev_probe (FpDevice *device) +{ + FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device); + GUsbDevice *usb_dev; + FpiUsbTransfer *transfer; + FpiByteReader reader; + GError *error = NULL; + guint16 status; + const guint8 *data; + gboolean read_ok = TRUE; + g_autofree gchar *serial = NULL; + + G_DEBUG_HERE (); + + /* Claim usb interface */ + usb_dev = fpi_device_get_usb_device (device); + if (!g_usb_device_open (usb_dev, &error)) + { + fpi_device_probe_complete (device, NULL, NULL, error); + return; + } + + if (!g_usb_device_reset (fpi_device_get_usb_device (device), &error)) + { + fpi_device_probe_complete (device, NULL, NULL, error); + return; + } + + if (!g_usb_device_claim_interface (fpi_device_get_usb_device (device), 0, 0, &error)) + goto err_close; + + /* TODO: Do not do this synchronous. */ + transfer = fpi_usb_transfer_new (device); + fpi_usb_transfer_fill_bulk (transfer, USB_EP_REQUEST, SENSOR_FW_CMD_HEADER_LEN); + transfer->short_is_error = TRUE; + transfer->buffer[0] = SENSOR_CMD_GET_VERSION; + if (!fpi_usb_transfer_submit_sync (transfer, 1000, &error)) + goto err_close; + fpi_usb_transfer_unref (transfer); + + + transfer = fpi_usb_transfer_new (device); + fpi_usb_transfer_fill_bulk (transfer, USB_EP_REPLY, 40); + if (!fpi_usb_transfer_submit_sync (transfer, 1000, &error)) + goto err_close; + + fpi_byte_reader_init (&reader, transfer->buffer, transfer->actual_length); + + if (!fpi_byte_reader_get_uint16_le (&reader, &status)) + { + g_warning ("Transfer in response to version query was too short"); + error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO); + goto err_close; + } + if (status != 0) + { + g_warning ("Device responded with error: %d", status); + error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO); + goto err_close; + } + + read_ok &= fpi_byte_reader_get_uint32_le (&reader, &self->mis_version.build_time); + read_ok &= fpi_byte_reader_get_uint32_le (&reader, &self->mis_version.build_num); + read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.version_major); + read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.version_minor); + read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.target); + read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.product); + + read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.silicon_rev); + read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.formal_release); + read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.platform); + read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.patch); + if (fpi_byte_reader_get_data (&reader, sizeof (self->mis_version.serial_number), &data)) + memcpy (self->mis_version.serial_number, data, sizeof (self->mis_version.serial_number)); + else + read_ok = FALSE; + read_ok &= fpi_byte_reader_get_uint16_le (&reader, &self->mis_version.security); + read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.iface); + read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.device_type); + + if (!read_ok) + { + g_warning ("Transfer in response to verison query was too short"); + error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO); + goto err_close; + } + + fp_dbg ("Build Time: %d", self->mis_version.build_time); + fp_dbg ("Build Num: %d", self->mis_version.build_num); + fp_dbg ("Version: %d.%d", self->mis_version.version_major, self->mis_version.version_minor); + fp_dbg ("Target: %d", self->mis_version.target); + fp_dbg ("Product: %d", self->mis_version.product); + + fpi_usb_transfer_unref (transfer); + + /* 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"); + 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; + +err_close: + g_usb_device_close (usb_dev, NULL); + fpi_device_probe_complete (device, NULL, NULL, error); +} + +static void +fps_init_msg_cb (FpiDeviceSynaptics *self, + bmkt_response_t *resp, + GError *error) +{ + if (error) + { + fpi_device_open_complete (FP_DEVICE (self), error); + return; + } + + /* BMKT_OPERATION_DENIED is returned if the sensor is already initialized */ + if (resp->result == BMKT_SUCCESS || resp->result == BMKT_OPERATION_DENIED) + { + fpi_device_open_complete (FP_DEVICE (self), NULL); + } + else + { + g_warning ("Initializing fingerprint sensor failed with %d!", resp->result); + fpi_device_open_complete (FP_DEVICE (self), + fpi_device_error_new (FP_DEVICE_ERROR_GENERAL)); + } +} +static void +fps_deinit_cb (FpiDeviceSynaptics *self, + bmkt_response_t *resp, + GError *error) +{ + /* Release usb interface */ + g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (self)), 0, 0, &error); + + g_clear_object (&self->interrupt_cancellable); + + if (!error) + { + switch (resp->response_id) + { + case BMKT_RSP_POWER_DOWN_READY: + fp_info ("Fingerprint sensor ready to be powered down"); + break; + + case BMKT_RSP_POWER_DOWN_FAIL: + fp_info ("Failed to go to power down mode: %d", resp->result); + error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, + "Power down failed"); + + break; + } + } + fpi_device_close_complete (FP_DEVICE (self), error); +} + +static void +dev_init (FpDevice *device) +{ + FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device); + GError *error = NULL; + + G_DEBUG_HERE (); + + 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; + + synaptics_sensor_cmd (self, 0, BMKT_CMD_FPS_INIT, NULL, 0, fps_init_msg_cb); + + return; + +error: + fpi_device_open_complete (FP_DEVICE (self), error); +} + +static void +dev_exit (FpDevice *device) +{ + FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device); + + G_DEBUG_HERE (); + + synaptics_sensor_cmd (self, 0, BMKT_CMD_POWER_DOWN_NOTIFY, NULL, 0, fps_deinit_cb); +} + +static void +cancel (FpDevice *dev) +{ + FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (dev); + + /* We just send out a cancel command and hope for the best. */ + synaptics_sensor_cmd (self, -1, BMKT_CMD_CANCEL_OP, NULL, 0, NULL); + + /* Cancel any current interrupt transfer (resulting us to go into + * response reading mode again); then create a new cancellable + * for the next transfers. */ + g_cancellable_cancel (self->interrupt_cancellable); + g_clear_object (&self->interrupt_cancellable); + self->interrupt_cancellable = g_cancellable_new (); +} + +static void +fpi_device_synaptics_init (FpiDeviceSynaptics *self) +{ +} + +static void +fpi_device_synaptics_class_init (FpiDeviceSynapticsClass *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + + dev_class->id = FP_COMPONENT; + dev_class->full_name = SYNAPTICS_DRIVER_FULLNAME; + + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->scan_type = FP_SCAN_TYPE_PRESS; + dev_class->id_table = id_table; + dev_class->nr_enroll_stages = ENROLL_SAMPLES; + + dev_class->open = dev_init; + dev_class->close = dev_exit; + dev_class->probe = dev_probe; + dev_class->verify = verify; + dev_class->enroll = enroll; + dev_class->delete = delete_print; + dev_class->cancel = cancel; + dev_class->list = list; +} diff --git a/libfprint/drivers/synaptics/synaptics.h b/libfprint/drivers/synaptics/synaptics.h new file mode 100644 index 00000000..cce6be9c --- /dev/null +++ b/libfprint/drivers/synaptics/synaptics.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2019 Synaptics Inc + * + * 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 + */ + +#ifndef __synaptics_h__ +#define __synaptics_h__ + +#include "fpi-device.h" +#include "fpi-ssm.h" + +#define SYNAPTICS_VENDOR_ID 0x06cb + +G_DECLARE_FINAL_TYPE (FpiDeviceSynaptics, fpi_device_synaptics, FPI, DEVICE_SYNAPTICS, FpDevice) + + +#define MAX_TRANSFER_LEN 263 + 1 /* SPI Header */ + 2 /* VCSFW header */ + +#define USB_EP_REQUEST 0x01 +#define USB_EP_REPLY 0x81 +#define USB_EP_FINGERPRINT 0x82 +#define USB_EP_INTERRUPT 0x83 + +#define USB_ASYNC_MESSAGE_PENDING 0x4 +#define USB_INTERRUPT_DATA_SIZE 7 + +#define SENSOR_CMD_GET_VERSION 1 +#define SENSOR_CMD_ACE_COMMAND 167 +#define SENSOR_CMD_ASYNCMSG_READ 168 + +#define SENSOR_FW_CMD_HEADER_LEN 1 +#define SENSOR_FW_REPLY_HEADER_LEN 2 + + +/* Number of enroll stages */ +#define ENROLL_SAMPLES 8 + + +#define SYNAPTICS_DRIVER_FULLNAME "Synaptics Sensors" +#include "bmkt.h" +#include "bmkt_response.h" + + +typedef struct bmkt_sensor_version +{ + uint32_t build_time; + uint32_t build_num; + uint8_t version_major; + uint8_t version_minor; + uint8_t target; + uint8_t product; + uint8_t silicon_rev; + uint8_t formal_release; + uint8_t platform; + uint8_t patch; + uint8_t serial_number[6]; + uint16_t security; + uint8_t iface; + uint8_t device_type; +} bmkt_sensor_version_t; + + +struct syna_enroll_resp_data +{ + int progress; +}; +typedef enum syna_state { + SYNA_STATE_UNINIT = 0, + SYNA_STATE_IDLE, + SYNA_STATE_ENROLL, + SYNA_STATE_IDENTIFY, + SYNA_STATE_IDENTIFY_DELAY_RESULT, + SYNA_STATE_VERIFY, + SYNA_STATE_VERIFY_DELAY_RESULT, + SYNA_STATE_DELETE, +} syna_state_t; + +typedef enum { + SYNAPTICS_CMD_SEND_PENDING = 0, + SYNAPTICS_CMD_GET_RESP, + SYNAPTICS_CMD_WAIT_INTERRUPT, + SYNAPTICS_CMD_SEND_ASYNC, + SYNAPTICS_CMD_RESTART, + SYNAPTICS_CMD_NUM_STATES, +} SynapticsCmdState; + + +typedef void (*SynCmdMsgCallback) (FpiDeviceSynaptics *self, + bmkt_response_t *resp, + GError *error); + +struct _FpiDeviceSynaptics +{ + FpDevice parent; + + guint8 cmd_seq_num; + guint8 last_seq_num; + FpiSsm *cmd_ssm; + FpiUsbTransfer *cmd_pending_transfer; + gboolean cmd_complete_on_removal; + GError *cmd_complete_error; + void *cmd_complete_data; + + bmkt_sensor_version_t mis_version; + + GCancellable *interrupt_cancellable; + + gint enroll_stage; + gboolean finger_on_sensor; + GPtrArray *list_result; + + + struct syna_enroll_resp_data enroll_resp_data; + syna_state_t state; +}; + +#endif //__synaptics_h__ diff --git a/libfprint/drivers/upek_proto.c b/libfprint/drivers/upek_proto.c index 0ecc4b13..13c4d98a 100644 --- a/libfprint/drivers/upek_proto.c +++ b/libfprint/drivers/upek_proto.c @@ -21,46 +21,47 @@ #include "upek_proto.h" static const uint16_t crc_table[256] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, - 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, - 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, - 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, - 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, - 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, - 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, - 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, - 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, - 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, - 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, - 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, - 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, - 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, - 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, - 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, - 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, - 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, - 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, - 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, - 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, - 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, - 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 }; uint16_t -udf_crc(unsigned char *buffer, size_t size) +udf_crc (unsigned char *buffer, size_t size) { - uint16_t crc = 0; - while (size--) - crc = (uint16_t) ((crc << 8) ^ - crc_table[((crc >> 8) & 0x00ff) ^ *buffer++]); - return crc; + uint16_t crc = 0; + + while (size--) + crc = (uint16_t) ((crc << 8) ^ + crc_table[((crc >> 8) & 0x00ff) ^ *buffer++]); + return crc; } diff --git a/libfprint/drivers/upek_proto.h b/libfprint/drivers/upek_proto.h index 2c3a617d..9459748b 100644 --- a/libfprint/drivers/upek_proto.h +++ b/libfprint/drivers/upek_proto.h @@ -21,4 +21,5 @@ #include #include -uint16_t udf_crc(unsigned char *buffer, size_t size); +uint16_t udf_crc (unsigned char *buffer, + size_t size); diff --git a/libfprint/drivers/upeksonly.c b/libfprint/drivers/upeksonly.c index 69a79e69..76ba4e2f 100644 --- a/libfprint/drivers/upeksonly.c +++ b/libfprint/drivers/upeksonly.c @@ -28,7 +28,7 @@ #include "drivers_api.h" #include "upeksonly.h" -#define CTRL_TIMEOUT 1000 +#define CTRL_TIMEOUT 1000 #define NUM_BULK_TRANSFERS 24 #define MAX_ROWS 2048 #define MIN_ROWS 64 @@ -39,1369 +39,1526 @@ #define DIFF_THRESHOLD 13 enum { - UPEKSONLY_2016, - UPEKSONLY_1000, - UPEKSONLY_1001, -}; - -struct img_transfer_data { - int idx; - struct fp_img_dev *dev; - gboolean flying; - gboolean cancelling; + UPEKSONLY_2016, + UPEKSONLY_1000, + UPEKSONLY_1001, }; enum sonly_kill_transfers_action { - NOT_KILLING = 0, + NOT_KILLING = 0, - /* abort a SSM with an error code */ - ABORT_SSM, + /* abort a SSM with an error code */ + ABORT_SSM, - /* report an image session error */ - IMG_SESSION_ERROR, + /* report an image session error */ + IMG_SESSION_ERROR, - /* iterate a SSM to the next state */ - ITERATE_SSM, + /* iterate a SSM to the next state */ + ITERATE_SSM, - /* call a callback */ - EXEC_CALLBACK, + /* call a callback */ + EXEC_CALLBACK, }; enum sonly_fs { - AWAIT_FINGER, - FINGER_DETECTED, - FINGER_REMOVED, + AWAIT_FINGER, + FINGER_DETECTED, + FINGER_REMOVED, }; -struct sonly_dev { - gboolean capturing; - gboolean deactivating; - uint8_t read_reg_result; +struct _FpiDeviceUpeksonly +{ + FpImageDevice parent; - int dev_model; - int img_width; + gboolean capturing; + gboolean deactivating; + guint8 read_reg_result; - fpi_ssm *loopsm; - struct libusb_transfer *img_transfer[NUM_BULK_TRANSFERS]; - struct img_transfer_data *img_transfer_data; - int num_flying; + int dev_model; + int img_width; - GSList *rows; - size_t num_rows; - unsigned char *rowbuf; - int rowbuf_offset; + FpiSsm *loopsm; - int wraparounds; - int num_blank; - int num_nonblank; - enum sonly_fs finger_state; - int last_seqnum; + /* Do we really need multiple concurrent transfers? */ + GCancellable *img_cancellable; + GPtrArray *img_transfers; + int num_flying; - enum sonly_kill_transfers_action killing_transfers; - int kill_status_code; - union { - fpi_ssm *kill_ssm; - void (*kill_cb)(struct fp_img_dev *dev); - }; + GSList *rows; + size_t num_rows; + unsigned char *rowbuf; + int rowbuf_offset; + + int wraparounds; + int num_blank; + int num_nonblank; + enum sonly_fs finger_state; + int last_seqnum; + + enum sonly_kill_transfers_action killing_transfers; + GError *kill_error; + union + { + FpiSsm *kill_ssm; + void (*kill_cb)(FpImageDevice *dev); + }; + + struct fpi_line_asmbl_ctx assembling_ctx; }; +G_DECLARE_FINAL_TYPE (FpiDeviceUpeksonly, fpi_device_upeksonly, FPI, + DEVICE_UPEKSONLY, FpImageDevice); +G_DEFINE_TYPE (FpiDeviceUpeksonly, fpi_device_upeksonly, FP_TYPE_IMAGE_DEVICE); /* Calculate squared standard deviation of sum of two lines */ -static int upeksonly_get_deviation2(struct fpi_line_asmbl_ctx *ctx, - GSList *line1, GSList *line2) +static int +upeksonly_get_deviation2 (struct fpi_line_asmbl_ctx *ctx, + GSList *line1, GSList *line2) { - unsigned char *buf1 = line1->data, *buf2 = line2->data; - int res = 0, mean = 0, i; + unsigned char *buf1 = line1->data, *buf2 = line2->data; + int res = 0, mean = 0, i; - g_assert (ctx->line_width > 0); + g_assert (ctx->line_width > 0); - for (i = 0; i < ctx->line_width; i+= 2) - mean += (int)buf1[i + 1] + (int)buf2[i]; + for (i = 0; i < ctx->line_width; i += 2) + mean += (int) buf1[i + 1] + (int) buf2[i]; - mean /= (ctx->line_width / 2); + mean /= (ctx->line_width / 2); - for (i = 0; i < ctx->line_width; i+= 2) { - int dev = (int)buf1[i + 1] + (int)buf2[i] - mean; - res += dev*dev; - } + for (i = 0; i < ctx->line_width; i += 2) + { + int dev = (int) buf1[i + 1] + (int) buf2[i] - mean; + res += dev * dev; + } - return res / (ctx->line_width / 2); + return res / (ctx->line_width / 2); } -static unsigned char upeksonly_get_pixel(struct fpi_line_asmbl_ctx *ctx, - GSList *row, - unsigned x) +static unsigned char +upeksonly_get_pixel (struct fpi_line_asmbl_ctx *ctx, + GSList *row, + unsigned x) { - unsigned char *buf; - unsigned offset; + unsigned char *buf; + unsigned offset; - /* The scans from this device are rolled right by two columns */ - if (x < ctx->line_width - 2) - offset = x + 2; - else if ((x > ctx->line_width - 2) && (x < ctx->line_width)) - offset = x - (ctx->line_width - 2); - else - return 0; - /* Each 2nd pixel is shifted 2 pixels down */ - if ((!(x & 1)) && g_slist_next(row) && g_slist_next(g_slist_next(row))) - buf = g_slist_next(g_slist_next(row))->data; - else - buf = row->data; + /* The scans from this device are rolled right by two columns */ + if (x < ctx->line_width - 2) + offset = x + 2; + else if ((x > ctx->line_width - 2) && (x < ctx->line_width)) + offset = x - (ctx->line_width - 2); + else + return 0; + /* Each 2nd pixel is shifted 2 pixels down */ + if ((!(x & 1)) && g_slist_next (row) && g_slist_next (g_slist_next (row))) + buf = g_slist_next (g_slist_next (row))->data; + else + buf = row->data; - return buf[offset]; + return buf[offset]; } -static struct fpi_line_asmbl_ctx assembling_ctx = { - .max_height = 1024, - .resolution = 8, - .median_filter_size = 25, - .max_search_offset = 30, - .get_deviation = upeksonly_get_deviation2, - .get_pixel = upeksonly_get_pixel, -}; - /***** IMAGE PROCESSING *****/ -static void free_img_transfers(struct sonly_dev *sdev) +static void +free_img_transfers (FpiDeviceUpeksonly *sdev) { - int i; - for (i = 0; i < NUM_BULK_TRANSFERS; i++) { - struct libusb_transfer *transfer = sdev->img_transfer[i]; - if (!transfer) - continue; - - g_free(transfer->buffer); - libusb_free_transfer(transfer); - } - g_free(sdev->img_transfer_data); + g_cancellable_cancel (sdev->img_cancellable); + g_clear_object (&sdev->img_cancellable); + g_clear_pointer (&sdev->img_transfers, g_ptr_array_unref); } -static void last_transfer_killed(struct fp_img_dev *dev) +static void +last_transfer_killed (FpImageDevice *dev) { - struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev)); - switch (sdev->killing_transfers) { - case ABORT_SSM: - fp_dbg("abort ssm error %d", sdev->kill_status_code); - fpi_ssm_mark_failed(sdev->kill_ssm, sdev->kill_status_code); - return; - case ITERATE_SSM: - fp_dbg("iterate ssm"); - fpi_ssm_next_state(sdev->kill_ssm); - return; - case IMG_SESSION_ERROR: - fp_dbg("session error %d", sdev->kill_status_code); - fpi_imgdev_session_error(dev, sdev->kill_status_code); - return; - default: - return; - } + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev); + + switch (self->killing_transfers) + { + case ABORT_SSM: + fp_dbg ("abort ssm error %s", self->kill_error->message); + fpi_ssm_mark_failed (self->kill_ssm, g_steal_pointer (&self->kill_error)); + return; + + case ITERATE_SSM: + fp_dbg ("iterate ssm"); + fpi_ssm_next_state (self->kill_ssm); + return; + + case IMG_SESSION_ERROR: + fp_dbg ("session error %s", self->kill_error->message); + fpi_image_device_session_error (dev, g_steal_pointer (&self->kill_error)); + return; + + default: + return; + } } -static void cancel_img_transfers(struct fp_img_dev *dev) +static void +cancel_img_transfers (FpImageDevice *dev) { - struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev)); - int i; + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev); - if (sdev->num_flying == 0) { - last_transfer_killed(dev); - return; - } + g_cancellable_cancel (self->img_cancellable); - for (i = 0; i < NUM_BULK_TRANSFERS; i++) { - struct img_transfer_data *idata = &sdev->img_transfer_data[i]; - if (!idata->flying || idata->cancelling) - continue; - fp_dbg("cancelling transfer %d", i); - int r = libusb_cancel_transfer(sdev->img_transfer[i]); - if (r < 0) - fp_dbg("cancel failed error %d", r); - idata->cancelling = TRUE; - } + if (self->num_flying == 0) + last_transfer_killed (dev); } -static gboolean is_capturing(struct sonly_dev *sdev) +static gboolean +is_capturing (FpiDeviceUpeksonly *sdev) { - return sdev->num_rows < MAX_ROWS && (sdev->finger_state != FINGER_REMOVED); + return sdev->num_rows < MAX_ROWS && (sdev->finger_state != FINGER_REMOVED); } -static void handoff_img(struct fp_img_dev *dev) +static void +handoff_img (FpImageDevice *dev) { - struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev)); - struct fp_img *img; + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev); + FpImage *img; - GSList *elem = sdev->rows; + GSList *elem = self->rows; - if (!elem) { - fp_err("no rows?"); - return; - } + if (!elem) + { + fp_err ("no rows?"); + return; + } - sdev->rows = g_slist_reverse(sdev->rows); + self->rows = g_slist_reverse (self->rows); - fp_dbg("%lu rows", sdev->num_rows); - img = fpi_assemble_lines(&assembling_ctx, sdev->rows, sdev->num_rows); + fp_dbg ("%lu rows", self->num_rows); + img = fpi_assemble_lines (&self->assembling_ctx, self->rows, self->num_rows); - g_slist_free_full(sdev->rows, g_free); - sdev->rows = NULL; + g_slist_free_full (self->rows, g_free); + self->rows = NULL; - fpi_imgdev_image_captured(dev, img); - fpi_imgdev_report_finger_status(dev, FALSE); + fpi_image_device_image_captured (dev, img); + fpi_image_device_report_finger_status (dev, FALSE); - sdev->killing_transfers = ITERATE_SSM; - sdev->kill_ssm = sdev->loopsm; - cancel_img_transfers(dev); + self->killing_transfers = ITERATE_SSM; + self->kill_ssm = self->loopsm; + cancel_img_transfers (dev); } -static void row_complete(struct fp_img_dev *dev) +static void +row_complete (FpImageDevice *dev) { - struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev)); - sdev->rowbuf_offset = -1; + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev); - if (sdev->num_rows > 0) { - unsigned char *lastrow = sdev->rows->data; - int std_sq_dev, mean_sq_diff; + self->rowbuf_offset = -1; - std_sq_dev = fpi_std_sq_dev(sdev->rowbuf, sdev->img_width); - mean_sq_diff = fpi_mean_sq_diff_norm(lastrow, sdev->rowbuf, sdev->img_width); + if (self->num_rows > 0) + { + unsigned char *lastrow = self->rows->data; + int std_sq_dev, mean_sq_diff; - switch (sdev->finger_state) { - case AWAIT_FINGER: - if (sdev->deactivating) { - sdev->killing_transfers = ITERATE_SSM; - sdev->kill_ssm = sdev->loopsm; - cancel_img_transfers(dev); - } - fp_dbg("std_sq_dev: %d", std_sq_dev); - if (std_sq_dev > BLANK_THRESHOLD) { - sdev->num_nonblank++; - } else { - sdev->num_nonblank = 0; - } + std_sq_dev = fpi_std_sq_dev (self->rowbuf, self->img_width); + mean_sq_diff = fpi_mean_sq_diff_norm (lastrow, self->rowbuf, + self->img_width); - if (sdev->num_nonblank > FINGER_PRESENT_THRESHOLD) { - sdev->finger_state = FINGER_DETECTED; - fpi_imgdev_report_finger_status(dev, TRUE); - } else { - return; - } - break; - case FINGER_DETECTED: - case FINGER_REMOVED: - default: - break; - } + switch (self->finger_state) + { + case AWAIT_FINGER: + if (self->deactivating) + { + self->killing_transfers = ITERATE_SSM; + self->kill_ssm = self->loopsm; + cancel_img_transfers (dev); + } + fp_dbg ("std_sq_dev: %d", std_sq_dev); + if (std_sq_dev > BLANK_THRESHOLD) + self->num_nonblank++; + else + self->num_nonblank = 0; - if (std_sq_dev > BLANK_THRESHOLD) { - sdev->num_blank = 0; - } else { - sdev->num_blank++; - /* Don't consider the scan complete unless there's at least - * MIN_ROWS recorded or very long blank read occurred. - * - * Typical problem spot: one brief touch before starting the - * actual scan. Happens most commonly if scan is started - * from before the first joint resulting in a gap after the initial touch. - */ - if (sdev->num_blank > FINGER_REMOVED_THRESHOLD) { - sdev->finger_state = FINGER_REMOVED; - fp_dbg("detected finger removal. Blank rows: %d, Full rows: %lu", sdev->num_blank, sdev->num_rows); - handoff_img(dev); - return; - } - } - fp_dbg("mean_sq_diff: %d, std_sq_dev: %d", mean_sq_diff, std_sq_dev); - fp_dbg("num_blank: %d", sdev->num_blank); - if (mean_sq_diff < DIFF_THRESHOLD) { - return; - } - } + if (self->num_nonblank > FINGER_PRESENT_THRESHOLD) + { + self->finger_state = FINGER_DETECTED; + fpi_image_device_report_finger_status (dev, + TRUE); + } + else + { + return; + } + break; - switch (sdev->finger_state) { - case AWAIT_FINGER: - if (!sdev->num_rows) { - sdev->rows = g_slist_prepend(sdev->rows, sdev->rowbuf); - sdev->num_rows++; - } else { - return; - } - break; - case FINGER_DETECTED: - case FINGER_REMOVED: - sdev->rows = g_slist_prepend(sdev->rows, sdev->rowbuf); - sdev->num_rows++; - break; - } - sdev->rowbuf = NULL; + case FINGER_DETECTED: + case FINGER_REMOVED: + default: + break; + } - if (sdev->num_rows >= MAX_ROWS) { - fp_dbg("row limit met"); - handoff_img(dev); - } + if (std_sq_dev > BLANK_THRESHOLD) + { + self->num_blank = 0; + } + else + { + self->num_blank++; + /* Don't consider the scan complete unless there's at least + * MIN_ROWS recorded or very long blank read occurred. + * + * Typical problem spot: one brief touch before starting the + * actual scan. Happens most commonly if scan is started + * from before the first joint resulting in a gap after the initial touch. + */ + if (self->num_blank > FINGER_REMOVED_THRESHOLD) + { + self->finger_state = FINGER_REMOVED; + fp_dbg ("detected finger removal. Blank rows: %d, Full rows: %lu", + self->num_blank, self->num_rows); + handoff_img (dev); + return; + } + } + fp_dbg ("mean_sq_diff: %d, std_sq_dev: %d", mean_sq_diff, std_sq_dev); + fp_dbg ("num_blank: %d", self->num_blank); + if (mean_sq_diff < DIFF_THRESHOLD) + return; + } + + switch (self->finger_state) + { + case AWAIT_FINGER: + if (!self->num_rows) + { + self->rows = g_slist_prepend (self->rows, self->rowbuf); + self->num_rows++; + } + else + { + return; + } + break; + + case FINGER_DETECTED: + case FINGER_REMOVED: + self->rows = g_slist_prepend (self->rows, self->rowbuf); + self->num_rows++; + break; + } + self->rowbuf = NULL; + + if (self->num_rows >= MAX_ROWS) + { + fp_dbg ("row limit met"); + handoff_img (dev); + } } /* add data to row buffer */ -static void add_to_rowbuf(struct fp_img_dev *dev, unsigned char *data, int size) +static void +add_to_rowbuf (FpImageDevice *dev, unsigned char *data, int size) { - struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev); - memcpy(sdev->rowbuf + sdev->rowbuf_offset, data, size); - sdev->rowbuf_offset += size; - if (sdev->rowbuf_offset >= sdev->img_width) - row_complete(dev); + memcpy (self->rowbuf + self->rowbuf_offset, data, size); + self->rowbuf_offset += size; + if (self->rowbuf_offset >= self->img_width) + row_complete (dev); } -static void start_new_row(struct sonly_dev *sdev, unsigned char *data, int size) +static void +start_new_row (FpiDeviceUpeksonly *self, unsigned char *data, + int size) { - if (!sdev->rowbuf) - sdev->rowbuf = g_malloc(sdev->img_width); - memcpy(sdev->rowbuf, data, size); - sdev->rowbuf_offset = size; + if (!self->rowbuf) + self->rowbuf = g_malloc (self->img_width); + memcpy (self->rowbuf, data, size); + self->rowbuf_offset = size; } /* returns number of bytes left to be copied into rowbuf (capped to 62) * or -1 if we aren't capturing anything */ -static int rowbuf_remaining(struct sonly_dev *sdev) +static int +rowbuf_remaining (FpiDeviceUpeksonly *sdev) { - int r; + int r; - if (sdev->rowbuf_offset == -1) - return -1; + if (sdev->rowbuf_offset == -1) + return -1; - r = sdev->img_width - sdev->rowbuf_offset; - if (r > 62) - r = 62; - return r; + r = sdev->img_width - sdev->rowbuf_offset; + if (r > 62) + r = 62; + return r; } -static void handle_packet(struct fp_img_dev *dev, unsigned char *data) +static void +handle_packet (FpImageDevice *dev, unsigned char *data) { - struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev)); - uint16_t seqnum = data[0] << 8 | data[1]; - int abs_base_addr; - int for_rowbuf; - int next_row_addr; - int diff; - unsigned char dummy_data[62]; + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev); + guint16 seqnum = data[0] << 8 | data[1]; + int abs_base_addr; + int for_rowbuf; + int next_row_addr; + int diff; + unsigned char dummy_data[62]; - /* Init dummy data to something neutral */ - memset (dummy_data, 204, 62); + /* Init dummy data to something neutral */ + memset (dummy_data, 204, 62); - data += 2; /* skip sequence number */ - if (seqnum != sdev->last_seqnum + 1) { - if (seqnum != 0 && sdev->last_seqnum != 16383) { - int missing_data = seqnum - sdev->last_seqnum; - int i; - fp_warn("lost %d packets of data between %d and %d", missing_data, sdev->last_seqnum, seqnum ); + data += 2; /* skip sequence number */ + if (seqnum != self->last_seqnum + 1) + { + if (seqnum != 0 && self->last_seqnum != 16383) + { + int missing_data = seqnum - self->last_seqnum; + int i; + fp_warn ("lost %d packets of data between %d and %d", missing_data, + self->last_seqnum, seqnum ); - /* Minimize distortions for readers that lose a lot of packets */ - for (i =1; i < missing_data; i++) { - abs_base_addr = (sdev->last_seqnum + 1) * 62; + /* Minimize distortions for readers that lose a lot of packets */ + for (i = 1; i < missing_data; i++) + { + abs_base_addr = (self->last_seqnum + 1) * 62; - /* If possible take the replacement data from last row */ - if (sdev->num_rows > 1) { - int row_left = sdev->img_width - sdev->rowbuf_offset; - unsigned char *last_row = g_slist_nth_data (sdev->rows, 0); + /* If possible take the replacement data from last row */ + if (self->num_rows > 1) + { + int row_left = self->img_width - self->rowbuf_offset; + unsigned char *last_row = g_slist_nth_data (self->rows, + 0); - if (row_left >= 62) { - memcpy(dummy_data, last_row + sdev->rowbuf_offset, 62); - } else { - memcpy(dummy_data, last_row + sdev->rowbuf_offset, row_left); - memcpy(dummy_data + row_left, last_row , 62 - row_left); - } - } + if (row_left >= 62) + { + memcpy (dummy_data, + last_row + self->rowbuf_offset, + 62); + } + else + { + memcpy (dummy_data, + last_row + self->rowbuf_offset, + row_left); + memcpy (dummy_data + row_left, last_row, 62 - row_left); + } + } - fp_warn("adding dummy input for %d, i=%d", sdev->last_seqnum + i, i); - for_rowbuf = rowbuf_remaining(sdev); - if (for_rowbuf != -1) { - add_to_rowbuf(dev, dummy_data, for_rowbuf); - /* row boundary */ - if (for_rowbuf < 62) { - start_new_row(sdev, dummy_data + for_rowbuf, 62 - for_rowbuf); - } - } else if (abs_base_addr % sdev->img_width == 0) { - start_new_row(sdev, dummy_data, 62); - } else { - /* does the data in the packet reside on a row boundary? - * if so capture it */ - next_row_addr = ((abs_base_addr / sdev->img_width) + 1) * sdev->img_width; - diff = next_row_addr - abs_base_addr; - if (diff < 62) - start_new_row(sdev, dummy_data + diff, 62 - diff); - } - sdev->last_seqnum = sdev->last_seqnum + 1; - } - } - } - if (seqnum <= sdev->last_seqnum) { - fp_dbg("detected wraparound"); - sdev->wraparounds++; - } + fp_warn ("adding dummy input for %d, i=%d", + self->last_seqnum + i, i); + for_rowbuf = rowbuf_remaining (self); + if (for_rowbuf != -1) + { + add_to_rowbuf (dev, dummy_data, for_rowbuf); + /* row boundary */ + if (for_rowbuf < 62) + { + start_new_row (self, + dummy_data + for_rowbuf, + 62 - for_rowbuf); + } + } + else if (abs_base_addr % self->img_width == 0) + { + start_new_row (self, dummy_data, 62); + } + else + { + /* does the data in the packet reside on a row boundary? + * if so capture it */ + next_row_addr = ((abs_base_addr / self->img_width) + 1) * self->img_width; + diff = next_row_addr - abs_base_addr; + if (diff < 62) + start_new_row (self, + dummy_data + diff, + 62 - diff); + } + self->last_seqnum = self->last_seqnum + 1; + } + } + } + if (seqnum <= self->last_seqnum) + { + fp_dbg ("detected wraparound"); + self->wraparounds++; + } - sdev->last_seqnum = seqnum; - seqnum += sdev->wraparounds * 16384; - abs_base_addr = seqnum * 62; + self->last_seqnum = seqnum; + seqnum += self->wraparounds * 16384; + abs_base_addr = seqnum * 62; - /* are we already capturing a row? if so append the data to the - * row buffer */ - for_rowbuf = rowbuf_remaining(sdev); - if (for_rowbuf != -1) { - add_to_rowbuf(dev, data, for_rowbuf); - /*row boundary*/ - if (for_rowbuf < 62) { - start_new_row(sdev, data + for_rowbuf, 62 - for_rowbuf); - } - return; - } + /* are we already capturing a row? if so append the data to the + * row buffer */ + for_rowbuf = rowbuf_remaining (self); + if (for_rowbuf != -1) + { + add_to_rowbuf (dev, data, for_rowbuf); + /*row boundary*/ + if (for_rowbuf < 62) + start_new_row (self, data + for_rowbuf, + 62 - for_rowbuf); + return; + } - /* does the packet START on a boundary? if so we want it in full */ - if (abs_base_addr % sdev->img_width == 0) { - start_new_row(sdev, data, 62); - return; - } + /* does the packet START on a boundary? if so we want it in full */ + if (abs_base_addr % self->img_width == 0) + { + start_new_row (self, data, 62); + return; + } - /* does the data in the packet reside on a row boundary? - * if so capture it */ - next_row_addr = ((abs_base_addr / sdev->img_width) + 1) * sdev->img_width; - diff = next_row_addr - abs_base_addr; - if (diff < 62) - start_new_row(sdev, data + diff, 62 - diff); + /* does the data in the packet reside on a row boundary? + * if so capture it */ + next_row_addr = ((abs_base_addr / self->img_width) + 1) * self->img_width; + diff = next_row_addr - abs_base_addr; + if (diff < 62) + start_new_row (self, data + diff, 62 - diff); } -static void img_data_cb(struct libusb_transfer *transfer) +static void +img_data_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - struct img_transfer_data *idata = transfer->user_data; - struct fp_img_dev *dev = idata->dev; - struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev)); - int i; + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev); + int i; - idata->flying = FALSE; - idata->cancelling = FALSE; - sdev->num_flying--; + self->num_flying--; - if (sdev->killing_transfers) { - if (sdev->num_flying == 0) - last_transfer_killed(dev); + if (self->killing_transfers) + { + if (self->num_flying == 0) + last_transfer_killed (dev); - /* don't care about error or success if we're terminating */ - return; - } + /* don't care about error or success if we're terminating */ + g_clear_error (&error); + return; + } - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fp_warn("bad status %d, terminating session", transfer->status); - sdev->killing_transfers = IMG_SESSION_ERROR; - sdev->kill_status_code = transfer->status; - cancel_img_transfers(dev); - } + if (error) + { + fp_warn ("bad status %s, terminating session", error->message); + self->killing_transfers = IMG_SESSION_ERROR; - /* there are 64 packets in the transfer buffer - * each packet is 64 bytes in length - * the first 2 bytes are a sequence number - * then there are 62 bytes for image data - */ - for (i = 0; i < 4096; i += 64) { - if (!is_capturing(sdev)) - return; - handle_packet(dev, transfer->buffer + i); - } + /* This cannot really happen, but just in case. */ + if (!self->kill_error) + self->kill_error = error; + else + g_error_free (error); - if (is_capturing(sdev)) { - int r = libusb_submit_transfer(transfer); - if (r < 0) { - fp_warn("failed resubmit, error %d", r); - sdev->killing_transfers = IMG_SESSION_ERROR; - sdev->kill_status_code = r; - cancel_img_transfers(dev); - return; - } - sdev->num_flying++; - idata->flying = TRUE; - } + cancel_img_transfers (dev); + return; + } + + /* there are 64 packets in the transfer buffer + * each packet is 64 bytes in length + * the first 2 bytes are a sequence number + * then there are 62 bytes for image data + */ + for (i = 0; i < 4096; i += 64) + { + if (!is_capturing (self)) + return; + handle_packet (dev, transfer->buffer + i); + } + + if (is_capturing (self)) + { + fpi_usb_transfer_submit (transfer, + 0, + self->img_cancellable, + img_data_cb, + user_data); + self->num_flying++; + } } /***** STATE MACHINE HELPERS *****/ -struct write_regs_data { - fpi_ssm *ssm; - struct libusb_transfer *transfer; - const struct sonly_regwrite *regs; - size_t num_regs; - size_t regs_written; +struct write_regs_data +{ + FpDevice *dev; + FpiSsm *ssm; + FpiUsbTransfer *transfer; + const struct sonly_regwrite *regs; + size_t num_regs; + size_t regs_written; }; -static void write_regs_finished(struct write_regs_data *wrdata, int result) +static void +write_regs_finished (struct write_regs_data *wrdata, GError *error) { - g_free(wrdata->transfer->buffer); - libusb_free_transfer(wrdata->transfer); - if (result == 0) - fpi_ssm_next_state(wrdata->ssm); - else - fpi_ssm_mark_failed(wrdata->ssm, result); - g_free(wrdata); + if (!error) + fpi_ssm_next_state (wrdata->ssm); + else + fpi_ssm_mark_failed (wrdata->ssm, error); } +static void write_regs_iterate (struct write_regs_data *wrdata); -static void write_regs_iterate(struct write_regs_data *wrdata) +static void +write_regs_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - struct libusb_control_setup *setup; - const struct sonly_regwrite *regwrite; - int r; + struct write_regs_data *wrdata = user_data; - if (wrdata->regs_written >= wrdata->num_regs) { - write_regs_finished(wrdata, 0); - return; - } + if (error) + { + write_regs_finished (wrdata, error); + return; + } - regwrite = &wrdata->regs[wrdata->regs_written]; - - fp_dbg("set %02x=%02x", regwrite->reg, regwrite->value); - setup = libusb_control_transfer_get_setup(wrdata->transfer); - setup->wIndex = regwrite->reg; - wrdata->transfer->buffer[LIBUSB_CONTROL_SETUP_SIZE] = regwrite->value; - - r = libusb_submit_transfer(wrdata->transfer); - if (r < 0) - write_regs_finished(wrdata, r); -} - -static void write_regs_cb(struct libusb_transfer *transfer) -{ - struct write_regs_data *wrdata = transfer->user_data; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - write_regs_finished(wrdata, transfer->status); - return; - } - - wrdata->regs_written++; - write_regs_iterate(wrdata); + wrdata->regs_written++; + write_regs_iterate (wrdata); } static void -sm_write_regs(fpi_ssm *ssm, - struct fp_dev *dev, - const struct sonly_regwrite *regs, - size_t num_regs) +write_regs_iterate (struct write_regs_data *wrdata) { - struct write_regs_data *wrdata = g_malloc(sizeof(*wrdata)); - unsigned char *data; + FpiUsbTransfer *transfer; + const struct sonly_regwrite *regwrite; - wrdata->transfer = fpi_usb_alloc(); - data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1); - libusb_fill_control_setup(data, 0x40, 0x0c, 0, 0, 1); - libusb_fill_control_transfer(wrdata->transfer, - fpi_dev_get_usb_dev(dev), data, - write_regs_cb, wrdata, CTRL_TIMEOUT); - wrdata->transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK; + if (wrdata->regs_written >= wrdata->num_regs) + { + write_regs_finished (wrdata, NULL); + return; + } - wrdata->ssm = ssm; - wrdata->regs = regs; - wrdata->num_regs = num_regs; - wrdata->regs_written = 0; - write_regs_iterate(wrdata); + regwrite = &wrdata->regs[wrdata->regs_written]; + fp_dbg ("set %02x=%02x", regwrite->reg, regwrite->value); + + transfer = fpi_usb_transfer_new (wrdata->dev); + fpi_usb_transfer_fill_control (transfer, + G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE, + G_USB_DEVICE_REQUEST_TYPE_VENDOR, + G_USB_DEVICE_RECIPIENT_DEVICE, + 0x0c, + 0, + regwrite->reg, + 1); + transfer->short_is_error = TRUE; + transfer->ssm = wrdata->ssm; + fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, write_regs_cb, NULL); + fpi_usb_transfer_unref (transfer); + + transfer->buffer[0] = regwrite->value; } -static void sm_write_reg_cb(struct libusb_transfer *transfer) +static void +sm_write_regs (FpiSsm *ssm, + FpDevice *dev, + const struct sonly_regwrite *regs, + size_t num_regs) { - fpi_ssm *ssm = transfer->user_data; - g_free(transfer->buffer); - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) - fpi_ssm_mark_failed(ssm, -EIO); - else - fpi_ssm_next_state(ssm); + struct write_regs_data *wrdata = g_malloc (sizeof (*wrdata)); + + wrdata->ssm = ssm; + wrdata->regs = regs; + wrdata->num_regs = num_regs; + wrdata->regs_written = 0; + wrdata->dev = dev; + + write_regs_iterate (wrdata); +} + +static void +sm_write_reg_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) +{ + if (error) + fpi_ssm_mark_failed (transfer->ssm, error); + else + fpi_ssm_next_state (transfer->ssm); } static void -sm_write_reg(fpi_ssm *ssm, - struct fp_img_dev *dev, - uint8_t reg, - uint8_t value) +sm_write_reg (FpiSsm *ssm, + FpImageDevice *dev, + guint8 reg, + guint8 value) { - struct libusb_transfer *transfer = fpi_usb_alloc(); - unsigned char *data; - int r; + FpiUsbTransfer *transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); - fp_dbg("set %02x=%02x", reg, value); - data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1); - libusb_fill_control_setup(data, 0x40, 0x0c, 0, reg, 1); - libusb_fill_control_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), - data, sm_write_reg_cb, - ssm, CTRL_TIMEOUT); + fp_dbg ("set %02x=%02x", reg, value); + fpi_usb_transfer_fill_control (transfer, + G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE, + G_USB_DEVICE_REQUEST_TYPE_VENDOR, + G_USB_DEVICE_RECIPIENT_DEVICE, + 0x0c, + 0, + reg, + 1); + transfer->short_is_error = TRUE; + transfer->ssm = ssm; + fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, sm_write_reg_cb, NULL); + fpi_usb_transfer_unref (transfer); - data[LIBUSB_CONTROL_SETUP_SIZE] = value; - transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK | - LIBUSB_TRANSFER_FREE_TRANSFER; - - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(data); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } -} - -static void sm_read_reg_cb(struct libusb_transfer *transfer) -{ - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev)); - - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fpi_ssm_mark_failed(ssm, -EIO); - } else { - sdev->read_reg_result = libusb_control_transfer_get_data(transfer)[0]; - fp_dbg("read reg result = %02x", sdev->read_reg_result); - fpi_ssm_next_state(ssm); - } - - g_free(transfer->buffer); + transfer->buffer[0] = value; } static void -sm_read_reg(fpi_ssm *ssm, - struct fp_img_dev *dev, - uint8_t reg) +sm_read_reg_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - struct libusb_transfer *transfer = fpi_usb_alloc(); - unsigned char *data; - int r; + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev); - fp_dbg("read reg %02x", reg); - data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 8); - libusb_fill_control_setup(data, 0xc0, 0x0c, 0, reg, 8); - libusb_fill_control_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), - data, sm_read_reg_cb, - ssm, CTRL_TIMEOUT); - transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK | - LIBUSB_TRANSFER_FREE_TRANSFER; + if (error) + { + fpi_ssm_mark_failed (transfer->ssm, error); + } + else + { + self->read_reg_result = transfer->buffer[0]; + fp_dbg ("read reg result = %02x", self->read_reg_result); + fpi_ssm_next_state (transfer->ssm); + } - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(data); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } -} - -static void sm_await_intr_cb(struct libusb_transfer *transfer) -{ - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev)); - - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - g_free(transfer->buffer); - fpi_ssm_mark_failed(ssm, transfer->status); - return; - } - - fp_dbg("interrupt received: %02x %02x %02x %02x", - transfer->buffer[0], transfer->buffer[1], - transfer->buffer[2], transfer->buffer[3]); - g_free(transfer->buffer); - - sdev->finger_state = FINGER_DETECTED; - fpi_imgdev_report_finger_status(dev, TRUE); - fpi_ssm_next_state(ssm); + g_free (transfer->buffer); } static void -sm_await_intr(fpi_ssm *ssm, - struct fp_img_dev *dev) +sm_read_reg (FpiSsm *ssm, + FpImageDevice *dev, + guint8 reg) { - struct libusb_transfer *transfer = fpi_usb_alloc(); - unsigned char *data; - int r; + FpiUsbTransfer *transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); - G_DEBUG_HERE(); - data = g_malloc(4); - libusb_fill_interrupt_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), - 0x83, data, 4, - sm_await_intr_cb, ssm, 0); - transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK | - LIBUSB_TRANSFER_FREE_TRANSFER; + fp_dbg ("read reg %02x", reg); + fpi_usb_transfer_fill_control (transfer, + G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST, + G_USB_DEVICE_REQUEST_TYPE_VENDOR, + G_USB_DEVICE_RECIPIENT_DEVICE, + 0x0c, + 0, + reg, + 8); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_submit (transfer, + CTRL_TIMEOUT, + NULL, + sm_read_reg_cb, + NULL); + fpi_usb_transfer_unref (transfer); +} - r = libusb_submit_transfer(transfer); - if (r < 0) { - libusb_free_transfer(transfer); - g_free(data); - fpi_ssm_mark_failed(ssm, r); - } +static void +sm_await_intr_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) +{ + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev); + + if (error) + { + g_free (transfer->buffer); + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } + + 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); + fpi_ssm_next_state (transfer->ssm); +} + +static void +sm_await_intr (FpiSsm *ssm, + FpImageDevice *dev) +{ + FpiUsbTransfer *transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); + + G_DEBUG_HERE (); + + fpi_usb_transfer_fill_interrupt (transfer, 0x83, 4); + transfer->short_is_error = TRUE; + transfer->ssm = ssm; + + /* NOTE: This was changed to be cancellable with the version 2 port! */ + fpi_usb_transfer_submit (transfer, + 0, + fpi_device_get_cancellable (FP_DEVICE (dev)), + sm_await_intr_cb, + NULL); + fpi_usb_transfer_unref (transfer); } /***** AWAIT FINGER *****/ enum awfsm_2016_states { - AWFSM_2016_WRITEV_1, - AWFSM_2016_READ_01, - AWFSM_2016_WRITE_01, - AWFSM_2016_WRITEV_2, - AWFSM_2016_READ_13, - AWFSM_2016_WRITE_13, - AWFSM_2016_WRITEV_3, - AWFSM_2016_READ_07, - AWFSM_2016_WRITE_07, - AWFSM_2016_WRITEV_4, - AWFSM_2016_NUM_STATES, + AWFSM_2016_WRITEV_1, + AWFSM_2016_READ_01, + AWFSM_2016_WRITE_01, + AWFSM_2016_WRITEV_2, + AWFSM_2016_READ_13, + AWFSM_2016_WRITE_13, + AWFSM_2016_WRITEV_3, + AWFSM_2016_READ_07, + AWFSM_2016_WRITE_07, + AWFSM_2016_WRITEV_4, + AWFSM_2016_NUM_STATES, }; enum awfsm_1000_states { - AWFSM_1000_WRITEV_1, - AWFSM_1000_WRITEV_2, - AWFSM_1000_NUM_STATES, + AWFSM_1000_WRITEV_1, + AWFSM_1000_WRITEV_2, + AWFSM_1000_NUM_STATES, }; -static void awfsm_2016_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +awfsm_2016_run_state (FpiSsm *ssm, FpDevice *_dev) { - struct fp_img_dev *dev = user_data; - struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case AWFSM_2016_WRITEV_1: - sm_write_regs(ssm, _dev, awfsm_2016_writev_1, G_N_ELEMENTS(awfsm_2016_writev_1)); - break; - case AWFSM_2016_READ_01: - sm_read_reg(ssm, dev, 0x01); - break; - case AWFSM_2016_WRITE_01: - if (sdev->read_reg_result != 0xc6) - sm_write_reg(ssm, dev, 0x01, 0x46); - else - sm_write_reg(ssm, dev, 0x01, 0xc6); - break; - case AWFSM_2016_WRITEV_2: - sm_write_regs(ssm, _dev, awfsm_2016_writev_2, G_N_ELEMENTS(awfsm_2016_writev_2)); - break; - case AWFSM_2016_READ_13: - sm_read_reg(ssm, dev, 0x13); - break; - case AWFSM_2016_WRITE_13: - if (sdev->read_reg_result != 0x45) - sm_write_reg(ssm, dev, 0x13, 0x05); - else - sm_write_reg(ssm, dev, 0x13, 0x45); - break; - case AWFSM_2016_WRITEV_3: - sm_write_regs(ssm, _dev, awfsm_2016_writev_3, G_N_ELEMENTS(awfsm_2016_writev_3)); - break; - case AWFSM_2016_READ_07: - sm_read_reg(ssm, dev, 0x07); - break; - case AWFSM_2016_WRITE_07: - if (sdev->read_reg_result != 0x10 && sdev->read_reg_result != 0x90) - fp_warn("odd reg7 value %x", sdev->read_reg_result); - sm_write_reg(ssm, dev, 0x07, sdev->read_reg_result); - break; - case AWFSM_2016_WRITEV_4: - sm_write_regs(ssm, _dev, awfsm_2016_writev_4, G_N_ELEMENTS(awfsm_2016_writev_4)); - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case AWFSM_2016_WRITEV_1: + sm_write_regs (ssm, _dev, awfsm_2016_writev_1, G_N_ELEMENTS (awfsm_2016_writev_1)); + break; + + case AWFSM_2016_READ_01: + sm_read_reg (ssm, dev, 0x01); + break; + + case AWFSM_2016_WRITE_01: + if (self->read_reg_result != 0xc6) + sm_write_reg (ssm, dev, 0x01, 0x46); + else + sm_write_reg (ssm, dev, 0x01, 0xc6); + break; + + case AWFSM_2016_WRITEV_2: + sm_write_regs (ssm, _dev, awfsm_2016_writev_2, G_N_ELEMENTS (awfsm_2016_writev_2)); + break; + + case AWFSM_2016_READ_13: + sm_read_reg (ssm, dev, 0x13); + break; + + case AWFSM_2016_WRITE_13: + if (self->read_reg_result != 0x45) + sm_write_reg (ssm, dev, 0x13, 0x05); + else + sm_write_reg (ssm, dev, 0x13, 0x45); + break; + + case AWFSM_2016_WRITEV_3: + sm_write_regs (ssm, _dev, awfsm_2016_writev_3, G_N_ELEMENTS (awfsm_2016_writev_3)); + break; + + case AWFSM_2016_READ_07: + sm_read_reg (ssm, dev, 0x07); + break; + + case AWFSM_2016_WRITE_07: + if (self->read_reg_result != 0x10 && self->read_reg_result != 0x90) + fp_warn ("odd reg7 value %x", self->read_reg_result); + sm_write_reg (ssm, dev, 0x07, self->read_reg_result); + break; + + case AWFSM_2016_WRITEV_4: + sm_write_regs (ssm, _dev, awfsm_2016_writev_4, G_N_ELEMENTS (awfsm_2016_writev_4)); + break; + } } -static void awfsm_1000_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +awfsm_1000_run_state (FpiSsm *ssm, FpDevice *_dev) { - switch (fpi_ssm_get_cur_state(ssm)) { - case AWFSM_1000_WRITEV_1: - sm_write_regs(ssm, _dev, awfsm_1000_writev_1, G_N_ELEMENTS(awfsm_1000_writev_1)); - break; - case AWFSM_1000_WRITEV_2: - sm_write_regs(ssm, _dev, awfsm_1000_writev_2, G_N_ELEMENTS(awfsm_1000_writev_2)); - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case AWFSM_1000_WRITEV_1: + sm_write_regs (ssm, _dev, awfsm_1000_writev_1, G_N_ELEMENTS (awfsm_1000_writev_1)); + break; + + case AWFSM_1000_WRITEV_2: + sm_write_regs (ssm, _dev, awfsm_1000_writev_2, G_N_ELEMENTS (awfsm_1000_writev_2)); + break; + } } /***** CAPTURE MODE *****/ enum capsm_2016_states { - CAPSM_2016_INIT, - CAPSM_2016_WRITE_15, - CAPSM_2016_WRITE_30, - CAPSM_2016_FIRE_BULK, - CAPSM_2016_WRITEV, - CAPSM_2016_NUM_STATES, + CAPSM_2016_INIT, + CAPSM_2016_WRITE_15, + CAPSM_2016_WRITE_30, + CAPSM_2016_FIRE_BULK, + CAPSM_2016_WRITEV, + CAPSM_2016_NUM_STATES, }; enum capsm_1000_states { - CAPSM_1000_INIT, - CAPSM_1000_FIRE_BULK, - CAPSM_1000_WRITEV, - CAPSM_1000_NUM_STATES, + CAPSM_1000_INIT, + CAPSM_1000_FIRE_BULK, + CAPSM_1000_WRITEV, + CAPSM_1000_NUM_STATES, }; enum capsm_1001_states { - CAPSM_1001_INIT, - CAPSM_1001_FIRE_BULK, - CAPSM_1001_WRITEV_1, - CAPSM_1001_WRITEV_2, - CAPSM_1001_WRITEV_3, - CAPSM_1001_WRITEV_4, - CAPSM_1001_WRITEV_5, - CAPSM_1001_NUM_STATES, + CAPSM_1001_INIT, + CAPSM_1001_FIRE_BULK, + CAPSM_1001_WRITEV_1, + CAPSM_1001_WRITEV_2, + CAPSM_1001_WRITEV_3, + CAPSM_1001_WRITEV_4, + CAPSM_1001_WRITEV_5, + CAPSM_1001_NUM_STATES, }; static void -capsm_fire_bulk(fpi_ssm *ssm, - struct fp_dev *_dev) +capsm_fire_bulk (FpiSsm *ssm, + FpDevice *dev) { - struct fp_img_dev *dev = FP_IMG_DEV(_dev); - struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev); - int i; - for (i = 0; i < NUM_BULK_TRANSFERS; i++) { - int r = libusb_submit_transfer(sdev->img_transfer[i]); - if (r < 0) { - if (i == 0) { - /* first one failed: easy peasy */ - fpi_ssm_mark_failed(ssm, r); - return; - } + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev); + int i; - /* cancel all flying transfers, and request that the SSM - * gets aborted when the last transfer has dropped out of - * the sky */ - sdev->killing_transfers = ABORT_SSM; - sdev->kill_ssm = ssm; - sdev->kill_status_code = r; - cancel_img_transfers(dev); - return; - } - sdev->img_transfer_data[i].flying = TRUE; - sdev->num_flying++; - } - sdev->capturing = TRUE; - fpi_ssm_next_state(ssm); + g_assert (self->capturing == FALSE); + + g_clear_object (&self->img_cancellable); + self->img_cancellable = g_cancellable_new (); + for (i = 0; i < self->img_transfers->len; i++) + { + fpi_usb_transfer_submit (g_ptr_array_index (self->img_transfers, i), + 0, + self->img_cancellable, + img_data_cb, + NULL); + self->num_flying++; + } + self->capturing = TRUE; + fpi_ssm_next_state (ssm); } -static void capsm_2016_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +capsm_2016_run_state (FpiSsm *ssm, FpDevice *_dev) { - struct fp_img_dev *dev = user_data; - struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case CAPSM_2016_INIT: - sdev->rowbuf_offset = -1; - sdev->num_rows = 0; - sdev->wraparounds = -1; - sdev->num_blank = 0; - sdev->num_nonblank = 0; - sdev->finger_state = FINGER_DETECTED; - sdev->last_seqnum = 16383; - sdev->killing_transfers = 0; - fpi_ssm_next_state(ssm); - break; - case CAPSM_2016_WRITE_15: - sm_write_reg(ssm, dev, 0x15, 0x20); - break; - case CAPSM_2016_WRITE_30: - sm_write_reg(ssm, dev, 0x30, 0xe0); - break; - case CAPSM_2016_FIRE_BULK: ; - capsm_fire_bulk (ssm, _dev); - break; - case CAPSM_2016_WRITEV: - sm_write_regs(ssm, _dev, capsm_2016_writev, G_N_ELEMENTS(capsm_2016_writev)); - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case CAPSM_2016_INIT: + self->rowbuf_offset = -1; + self->num_rows = 0; + self->wraparounds = -1; + self->num_blank = 0; + self->num_nonblank = 0; + self->finger_state = FINGER_DETECTED; + self->last_seqnum = 16383; + self->killing_transfers = 0; + fpi_ssm_next_state (ssm); + break; + + case CAPSM_2016_WRITE_15: + sm_write_reg (ssm, dev, 0x15, 0x20); + break; + + case CAPSM_2016_WRITE_30: + sm_write_reg (ssm, dev, 0x30, 0xe0); + break; + + case CAPSM_2016_FIRE_BULK:; + capsm_fire_bulk (ssm, _dev); + break; + + case CAPSM_2016_WRITEV: + sm_write_regs (ssm, _dev, capsm_2016_writev, G_N_ELEMENTS (capsm_2016_writev)); + break; + } } -static void capsm_1000_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +capsm_1000_run_state (FpiSsm *ssm, FpDevice *_dev) { - struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev); + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case CAPSM_1000_INIT: - sdev->rowbuf_offset = -1; - sdev->num_rows = 0; - sdev->wraparounds = -1; - sdev->num_blank = 0; - sdev->num_nonblank = 0; - sdev->finger_state = FINGER_DETECTED; - sdev->last_seqnum = 16383; - sdev->killing_transfers = 0; - fpi_ssm_next_state(ssm); - break; - case CAPSM_1000_FIRE_BULK: ; - capsm_fire_bulk (ssm, _dev); - break; - case CAPSM_1000_WRITEV: - sm_write_regs(ssm, _dev, capsm_1000_writev, G_N_ELEMENTS(capsm_1000_writev)); - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case CAPSM_1000_INIT: + self->rowbuf_offset = -1; + self->num_rows = 0; + self->wraparounds = -1; + self->num_blank = 0; + self->num_nonblank = 0; + self->finger_state = FINGER_DETECTED; + self->last_seqnum = 16383; + self->killing_transfers = 0; + fpi_ssm_next_state (ssm); + break; + + case CAPSM_1000_FIRE_BULK:; + capsm_fire_bulk (ssm, _dev); + break; + + case CAPSM_1000_WRITEV: + sm_write_regs (ssm, _dev, capsm_1000_writev, G_N_ELEMENTS (capsm_1000_writev)); + break; + } } -static void capsm_1001_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +capsm_1001_run_state (FpiSsm *ssm, FpDevice *_dev) { - struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev); + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case CAPSM_1001_INIT: - sdev->rowbuf_offset = -1; - sdev->num_rows = 0; - sdev->wraparounds = -1; - sdev->num_blank = 0; - sdev->num_nonblank = 0; - sdev->finger_state = AWAIT_FINGER; - sdev->last_seqnum = 16383; - sdev->killing_transfers = 0; - fpi_ssm_next_state(ssm); - break; - case CAPSM_1001_FIRE_BULK: ; - capsm_fire_bulk (ssm, _dev); - break; - case CAPSM_1001_WRITEV_1: - sm_write_regs(ssm, _dev, capsm_1001_writev_1, G_N_ELEMENTS(capsm_1001_writev_1)); - break; - case CAPSM_1001_WRITEV_2: - sm_write_regs(ssm, _dev, capsm_1001_writev_2, G_N_ELEMENTS(capsm_1001_writev_2)); - break; - case CAPSM_1001_WRITEV_3: - sm_write_regs(ssm, _dev, capsm_1001_writev_3, G_N_ELEMENTS(capsm_1001_writev_3)); - break; - case CAPSM_1001_WRITEV_4: - sm_write_regs(ssm, _dev, capsm_1001_writev_4, G_N_ELEMENTS(capsm_1001_writev_4)); - break; - case CAPSM_1001_WRITEV_5: - sm_write_regs(ssm, _dev, capsm_1001_writev_5, G_N_ELEMENTS(capsm_1001_writev_5)); - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case CAPSM_1001_INIT: + self->rowbuf_offset = -1; + self->num_rows = 0; + self->wraparounds = -1; + self->num_blank = 0; + self->num_nonblank = 0; + self->finger_state = AWAIT_FINGER; + self->last_seqnum = 16383; + self->killing_transfers = 0; + fpi_ssm_next_state (ssm); + break; + + case CAPSM_1001_FIRE_BULK:; + capsm_fire_bulk (ssm, _dev); + break; + + case CAPSM_1001_WRITEV_1: + sm_write_regs (ssm, _dev, capsm_1001_writev_1, G_N_ELEMENTS (capsm_1001_writev_1)); + break; + + case CAPSM_1001_WRITEV_2: + sm_write_regs (ssm, _dev, capsm_1001_writev_2, G_N_ELEMENTS (capsm_1001_writev_2)); + break; + + case CAPSM_1001_WRITEV_3: + sm_write_regs (ssm, _dev, capsm_1001_writev_3, G_N_ELEMENTS (capsm_1001_writev_3)); + break; + + case CAPSM_1001_WRITEV_4: + sm_write_regs (ssm, _dev, capsm_1001_writev_4, G_N_ELEMENTS (capsm_1001_writev_4)); + break; + + case CAPSM_1001_WRITEV_5: + sm_write_regs (ssm, _dev, capsm_1001_writev_5, G_N_ELEMENTS (capsm_1001_writev_5)); + break; + } } /***** DEINITIALIZATION *****/ enum deinitsm_2016_states { - DEINITSM_2016_WRITEV, - DEINITSM_2016_NUM_STATES, + DEINITSM_2016_WRITEV, + DEINITSM_2016_NUM_STATES, }; enum deinitsm_1000_states { - DEINITSM_1000_WRITEV, - DEINITSM_1000_NUM_STATES, + DEINITSM_1000_WRITEV, + DEINITSM_1000_NUM_STATES, }; enum deinitsm_1001_states { - DEINITSM_1001_WRITEV, - DEINITSM_1001_NUM_STATES, + DEINITSM_1001_WRITEV, + DEINITSM_1001_NUM_STATES, }; -static void deinitsm_2016_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +deinitsm_2016_run_state (FpiSsm *ssm, FpDevice *_dev) { - switch (fpi_ssm_get_cur_state(ssm)) { - case DEINITSM_2016_WRITEV: - sm_write_regs(ssm, _dev, deinitsm_2016_writev, G_N_ELEMENTS(deinitsm_2016_writev)); - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case DEINITSM_2016_WRITEV: + sm_write_regs (ssm, _dev, deinitsm_2016_writev, G_N_ELEMENTS (deinitsm_2016_writev)); + break; + } } -static void deinitsm_1000_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +deinitsm_1000_run_state (FpiSsm *ssm, FpDevice *_dev) { - switch (fpi_ssm_get_cur_state(ssm)) { - case DEINITSM_1000_WRITEV: - sm_write_regs(ssm, _dev, deinitsm_1000_writev, G_N_ELEMENTS(deinitsm_1000_writev)); - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case DEINITSM_1000_WRITEV: + sm_write_regs (ssm, _dev, deinitsm_1000_writev, G_N_ELEMENTS (deinitsm_1000_writev)); + break; + } } -static void deinitsm_1001_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +deinitsm_1001_run_state (FpiSsm *ssm, FpDevice *_dev) { - switch (fpi_ssm_get_cur_state(ssm)) { - case DEINITSM_1001_WRITEV: - sm_write_regs(ssm, _dev, deinitsm_1001_writev, G_N_ELEMENTS(deinitsm_1001_writev)); - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case DEINITSM_1001_WRITEV: + sm_write_regs (ssm, _dev, deinitsm_1001_writev, G_N_ELEMENTS (deinitsm_1001_writev)); + break; + } } /***** INITIALIZATION *****/ enum initsm_2016_states { - INITSM_2016_WRITEV_1, - INITSM_2016_READ_09, - INITSM_2016_WRITE_09, - INITSM_2016_READ_13, - INITSM_2016_WRITE_13, - INITSM_2016_WRITE_04, - INITSM_2016_WRITE_05, - INITSM_2016_NUM_STATES, + INITSM_2016_WRITEV_1, + INITSM_2016_READ_09, + INITSM_2016_WRITE_09, + INITSM_2016_READ_13, + INITSM_2016_WRITE_13, + INITSM_2016_WRITE_04, + INITSM_2016_WRITE_05, + INITSM_2016_NUM_STATES, }; enum initsm_1000_states { - INITSM_1000_WRITEV_1, - INITSM_1000_NUM_STATES, + INITSM_1000_WRITEV_1, + INITSM_1000_NUM_STATES, }; enum initsm_1001_states { - INITSM_1001_WRITEV_1, - INITSM_1001_WRITEV_2, - INITSM_1001_WRITEV_3, - INITSM_1001_WRITEV_4, - INITSM_1001_WRITEV_5, - INITSM_1001_NUM_STATES, + INITSM_1001_WRITEV_1, + INITSM_1001_WRITEV_2, + INITSM_1001_WRITEV_3, + INITSM_1001_WRITEV_4, + INITSM_1001_WRITEV_5, + INITSM_1001_NUM_STATES, }; -static void initsm_2016_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +initsm_2016_run_state (FpiSsm *ssm, FpDevice *_dev) { - struct fp_img_dev *dev = user_data; - struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case INITSM_2016_WRITEV_1: - sm_write_regs(ssm, _dev, initsm_2016_writev_1, G_N_ELEMENTS(initsm_2016_writev_1)); - break; - case INITSM_2016_READ_09: - sm_read_reg(ssm, dev, 0x09); - break; - case INITSM_2016_WRITE_09: - sm_write_reg(ssm, dev, 0x09, sdev->read_reg_result & ~0x08); - break; - case INITSM_2016_READ_13: - sm_read_reg(ssm, dev, 0x13); - break; - case INITSM_2016_WRITE_13: - sm_write_reg(ssm, dev, 0x13, sdev->read_reg_result & ~0x10); - break; - case INITSM_2016_WRITE_04: - sm_write_reg(ssm, dev, 0x04, 0x00); - break; - case INITSM_2016_WRITE_05: - sm_write_reg(ssm, dev, 0x05, 0x00); - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case INITSM_2016_WRITEV_1: + sm_write_regs (ssm, _dev, initsm_2016_writev_1, G_N_ELEMENTS (initsm_2016_writev_1)); + break; + + case INITSM_2016_READ_09: + sm_read_reg (ssm, dev, 0x09); + break; + + case INITSM_2016_WRITE_09: + sm_write_reg (ssm, dev, 0x09, self->read_reg_result & ~0x08); + break; + + case INITSM_2016_READ_13: + sm_read_reg (ssm, dev, 0x13); + break; + + case INITSM_2016_WRITE_13: + sm_write_reg (ssm, dev, 0x13, self->read_reg_result & ~0x10); + break; + + case INITSM_2016_WRITE_04: + sm_write_reg (ssm, dev, 0x04, 0x00); + break; + + case INITSM_2016_WRITE_05: + sm_write_reg (ssm, dev, 0x05, 0x00); + break; + } } -static void initsm_1000_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +initsm_1000_run_state (FpiSsm *ssm, FpDevice *_dev) { - switch (fpi_ssm_get_cur_state(ssm)) { - case INITSM_1000_WRITEV_1: - sm_write_regs(ssm, _dev, initsm_1000_writev_1, G_N_ELEMENTS(initsm_1000_writev_1)); - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case INITSM_1000_WRITEV_1: + sm_write_regs (ssm, _dev, initsm_1000_writev_1, G_N_ELEMENTS (initsm_1000_writev_1)); + break; + } } -static void initsm_1001_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +initsm_1001_run_state (FpiSsm *ssm, FpDevice *_dev) { - switch (fpi_ssm_get_cur_state(ssm)) { - case INITSM_1001_WRITEV_1: - sm_write_regs(ssm, _dev, initsm_1001_writev_1, G_N_ELEMENTS(initsm_1001_writev_1)); - break; - case INITSM_1001_WRITEV_2: - sm_write_regs(ssm, _dev, initsm_1001_writev_2, G_N_ELEMENTS(initsm_1001_writev_2)); - break; - case INITSM_1001_WRITEV_3: - sm_write_regs(ssm, _dev, initsm_1001_writev_3, G_N_ELEMENTS(initsm_1001_writev_3)); - break; - case INITSM_1001_WRITEV_4: - sm_write_regs(ssm, _dev, initsm_1001_writev_4, G_N_ELEMENTS(initsm_1001_writev_4)); - break; - case INITSM_1001_WRITEV_5: - sm_write_regs(ssm, _dev, initsm_1001_writev_5, G_N_ELEMENTS(initsm_1001_writev_5)); - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case INITSM_1001_WRITEV_1: + sm_write_regs (ssm, _dev, initsm_1001_writev_1, G_N_ELEMENTS (initsm_1001_writev_1)); + break; + + case INITSM_1001_WRITEV_2: + sm_write_regs (ssm, _dev, initsm_1001_writev_2, G_N_ELEMENTS (initsm_1001_writev_2)); + break; + + case INITSM_1001_WRITEV_3: + sm_write_regs (ssm, _dev, initsm_1001_writev_3, G_N_ELEMENTS (initsm_1001_writev_3)); + break; + + case INITSM_1001_WRITEV_4: + sm_write_regs (ssm, _dev, initsm_1001_writev_4, G_N_ELEMENTS (initsm_1001_writev_4)); + break; + + case INITSM_1001_WRITEV_5: + sm_write_regs (ssm, _dev, initsm_1001_writev_5, G_N_ELEMENTS (initsm_1001_writev_5)); + break; + } } /***** CAPTURE LOOP *****/ enum loopsm_states { - LOOPSM_RUN_AWFSM, - LOOPSM_AWAIT_FINGER, - LOOPSM_RUN_CAPSM, - LOOPSM_CAPTURE, - LOOPSM_RUN_DEINITSM, - LOOPSM_FINAL, - LOOPSM_NUM_STATES, + LOOPSM_RUN_AWFSM, + LOOPSM_AWAIT_FINGER, + LOOPSM_RUN_CAPSM, + LOOPSM_CAPTURE, + LOOPSM_RUN_DEINITSM, + LOOPSM_FINAL, + LOOPSM_NUM_STATES, }; -static void loopsm_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +loopsm_run_state (FpiSsm *ssm, FpDevice *_dev) { - struct fp_img_dev *dev = user_data; - struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev); + + switch (fpi_ssm_get_cur_state (ssm)) + { + case LOOPSM_RUN_AWFSM:; + switch (self->dev_model) + { + case UPEKSONLY_1001: + if (self->deactivating) + fpi_ssm_mark_completed (ssm); + else + fpi_ssm_next_state (ssm); + break; + + default: + if (self->deactivating) + { + fpi_ssm_mark_completed (ssm); + } + else + { + FpiSsm *awfsm = NULL; + switch (self->dev_model) + { + case UPEKSONLY_2016: + awfsm = fpi_ssm_new (FP_DEVICE (dev), + awfsm_2016_run_state, + AWFSM_2016_NUM_STATES); + break; + + case UPEKSONLY_1000: + awfsm = fpi_ssm_new (FP_DEVICE (dev), + awfsm_1000_run_state, + AWFSM_1000_NUM_STATES); + break; + } + fpi_ssm_start_subsm (ssm, awfsm); + } + break; + } + break; + + case LOOPSM_AWAIT_FINGER: + switch (self->dev_model) + { + case UPEKSONLY_1001: + fpi_ssm_next_state (ssm); + break; + + default: + sm_await_intr (ssm, dev); + break; + } + break; + + case LOOPSM_RUN_CAPSM:; + FpiSsm *capsm = NULL; + switch (self->dev_model) + { + case UPEKSONLY_2016: + capsm = fpi_ssm_new (FP_DEVICE (dev), + capsm_2016_run_state, + CAPSM_2016_NUM_STATES); + break; + + case UPEKSONLY_1000: + capsm = fpi_ssm_new (FP_DEVICE (dev), + capsm_1000_run_state, + CAPSM_1000_NUM_STATES); + break; + + case UPEKSONLY_1001: + capsm = fpi_ssm_new (FP_DEVICE (dev), + capsm_1001_run_state, + CAPSM_1001_NUM_STATES); + break; + } + fpi_ssm_start_subsm (ssm, capsm); + break; + + case LOOPSM_CAPTURE: + break; + + case LOOPSM_RUN_DEINITSM:; + FpiSsm *deinitsm = NULL; + switch (self->dev_model) + { + case UPEKSONLY_2016: + deinitsm = fpi_ssm_new (FP_DEVICE (dev), + deinitsm_2016_run_state, + DEINITSM_2016_NUM_STATES); + break; + + case UPEKSONLY_1000: + deinitsm = fpi_ssm_new (FP_DEVICE (dev), + deinitsm_1000_run_state, + DEINITSM_1000_NUM_STATES); + break; + + case UPEKSONLY_1001: + deinitsm = fpi_ssm_new (FP_DEVICE (dev), + deinitsm_1001_run_state, + DEINITSM_1001_NUM_STATES); + break; + } + self->capturing = FALSE; + fpi_ssm_start_subsm (ssm, deinitsm); + break; + + case LOOPSM_FINAL: + fpi_ssm_jump_to_state (ssm, LOOPSM_RUN_AWFSM); + break; + } - switch (fpi_ssm_get_cur_state(ssm)) { - case LOOPSM_RUN_AWFSM: ; - switch (sdev->dev_model) { - case UPEKSONLY_1001: - if (sdev->deactivating) { - fpi_ssm_mark_completed(ssm); - } else { - fpi_ssm_next_state(ssm); - } - break; - default: - if (sdev->deactivating) { - fpi_ssm_mark_completed(ssm); - } else { - fpi_ssm *awfsm = NULL; - switch (sdev->dev_model) { - case UPEKSONLY_2016: - awfsm = fpi_ssm_new(FP_DEV(dev), awfsm_2016_run_state, - AWFSM_2016_NUM_STATES, dev); - break; - case UPEKSONLY_1000: - awfsm = fpi_ssm_new(FP_DEV(dev), awfsm_1000_run_state, - AWFSM_1000_NUM_STATES, dev); - break; - } - fpi_ssm_start_subsm(ssm, awfsm); - } - break; - } - break; - case LOOPSM_AWAIT_FINGER: - switch (sdev->dev_model) { - case UPEKSONLY_1001: - fpi_ssm_next_state(ssm); - break; - default: - sm_await_intr(ssm, dev); - break; - } - break; - case LOOPSM_RUN_CAPSM: ; - fpi_ssm *capsm = NULL; - switch (sdev->dev_model) { - case UPEKSONLY_2016: - capsm = fpi_ssm_new(FP_DEV(dev), capsm_2016_run_state, - CAPSM_2016_NUM_STATES, dev); - break; - case UPEKSONLY_1000: - capsm = fpi_ssm_new(FP_DEV(dev), capsm_1000_run_state, - CAPSM_1000_NUM_STATES, dev); - break; - case UPEKSONLY_1001: - capsm = fpi_ssm_new(FP_DEV(dev), capsm_1001_run_state, - CAPSM_1001_NUM_STATES, dev); - break; - } - fpi_ssm_start_subsm(ssm, capsm); - break; - case LOOPSM_CAPTURE: - break; - case LOOPSM_RUN_DEINITSM: ; - fpi_ssm *deinitsm = NULL; - switch (sdev->dev_model) { - case UPEKSONLY_2016: - deinitsm = fpi_ssm_new(FP_DEV(dev), deinitsm_2016_run_state, - DEINITSM_2016_NUM_STATES, dev); - break; - case UPEKSONLY_1000: - deinitsm = fpi_ssm_new(FP_DEV(dev), deinitsm_1000_run_state, - DEINITSM_1000_NUM_STATES, dev); - break; - case UPEKSONLY_1001: - deinitsm = fpi_ssm_new(FP_DEV(dev), deinitsm_1001_run_state, - DEINITSM_1001_NUM_STATES, dev); - break; - } - sdev->capturing = FALSE; - fpi_ssm_start_subsm(ssm, deinitsm); - break; - case LOOPSM_FINAL: - fpi_ssm_jump_to_state(ssm, LOOPSM_RUN_AWFSM); - break; - } - } /***** DRIVER STUFF *****/ -static void deactivate_done(struct fp_img_dev *dev) +static void +deactivate_done (FpImageDevice *dev, GError *error) { - struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev); - G_DEBUG_HERE(); - free_img_transfers(sdev); - g_free(sdev->rowbuf); - sdev->rowbuf = NULL; + G_DEBUG_HERE (); + free_img_transfers (self); + g_free (self->rowbuf); + self->rowbuf = NULL; - if (sdev->rows) { - g_slist_foreach(sdev->rows, (GFunc) g_free, NULL); - sdev->rows = NULL; - } + g_slist_free_full (self->rows, g_free); + self->rows = NULL; - fpi_imgdev_deactivate_complete(dev); + fpi_image_device_deactivate_complete (dev, error); } -static void dev_deactivate(struct fp_img_dev *dev) +static void +dev_deactivate (FpImageDevice *dev) { - struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev); - if (!sdev->capturing) { - deactivate_done(dev); - return; - } + if (!self->capturing) + { + deactivate_done (dev, NULL); + return; + } - sdev->deactivating = TRUE; - sdev->killing_transfers = ITERATE_SSM; - sdev->kill_ssm = sdev->loopsm; - cancel_img_transfers(dev); + self->deactivating = TRUE; + self->killing_transfers = ITERATE_SSM; + self->kill_ssm = self->loopsm; + cancel_img_transfers (dev); } -static void loopsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +loopsm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { - struct fp_img_dev *dev = user_data; - struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev); - int r = fpi_ssm_get_error(ssm); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev); - fpi_ssm_free(ssm); + fpi_ssm_free (ssm); - if (sdev->deactivating) { - deactivate_done(dev); - return; - } + if (self->deactivating) + { + deactivate_done (dev, error); + return; + } - if (r) { - fpi_imgdev_session_error(dev, r); - return; - } + if (error) + { + fpi_image_device_session_error (dev, error); + return; + } } -static void initsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +initsm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { - struct fp_img_dev *dev = user_data; - struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev); - int r = fpi_ssm_get_error(ssm); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev); - fpi_ssm_free(ssm); - fpi_imgdev_activate_complete(dev, r); - if (r != 0) - return; + fpi_ssm_free (ssm); + fpi_image_device_activate_complete (dev, error); + if (error) + return; - sdev->loopsm = fpi_ssm_new(FP_DEV(dev), loopsm_run_state, LOOPSM_NUM_STATES, dev); - fpi_ssm_start(sdev->loopsm, loopsm_complete); + self->loopsm = fpi_ssm_new (FP_DEVICE (dev), loopsm_run_state, + LOOPSM_NUM_STATES); + fpi_ssm_start (self->loopsm, loopsm_complete); } -static int dev_activate(struct fp_img_dev *dev) +static void +dev_activate (FpImageDevice *dev) { - struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_ssm *ssm = NULL; - int i; + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev); + FpiSsm *ssm = NULL; + int i; - sdev->deactivating = FALSE; - sdev->capturing = FALSE; + self->deactivating = FALSE; + self->capturing = FALSE; - memset(sdev->img_transfer, 0, - NUM_BULK_TRANSFERS * sizeof(struct libusb_transfer *)); - sdev->img_transfer_data = - g_malloc0(sizeof(struct img_transfer_data) * NUM_BULK_TRANSFERS); - sdev->num_flying = 0; - for (i = 0; i < NUM_BULK_TRANSFERS; i++) { - unsigned char *data; - sdev->img_transfer[i] = fpi_usb_alloc(); - sdev->img_transfer_data[i].idx = i; - sdev->img_transfer_data[i].dev = dev; - data = g_malloc(4096); - libusb_fill_bulk_transfer(sdev->img_transfer[i], fpi_dev_get_usb_dev(FP_DEV(dev)), - 0x81, data, - 4096, img_data_cb, &sdev->img_transfer_data[i], 0); - } + self->img_transfers = g_ptr_array_new_full (NUM_BULK_TRANSFERS, (GDestroyNotify) fpi_usb_transfer_unref); + self->num_flying = 0; - switch (sdev->dev_model) { - case UPEKSONLY_2016: - ssm = fpi_ssm_new(FP_DEV(dev), initsm_2016_run_state, INITSM_2016_NUM_STATES, dev); - break; - case UPEKSONLY_1000: - ssm = fpi_ssm_new(FP_DEV(dev), initsm_1000_run_state, INITSM_1000_NUM_STATES, dev); - break; - case UPEKSONLY_1001: - ssm = fpi_ssm_new(FP_DEV(dev), initsm_1001_run_state, INITSM_1001_NUM_STATES, dev); - break; - } - fpi_ssm_start(ssm, initsm_complete); - return 0; + for (i = 0; i < self->img_transfers->len; i++) + { + FpiUsbTransfer *transfer; + + transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); + fpi_usb_transfer_fill_bulk (transfer, 0x81, 4096); + + g_ptr_array_add (self->img_transfers, transfer); + } + + switch (self->dev_model) + { + case UPEKSONLY_2016: + ssm = fpi_ssm_new (FP_DEVICE (dev), initsm_2016_run_state, + INITSM_2016_NUM_STATES); + break; + + case UPEKSONLY_1000: + ssm = fpi_ssm_new (FP_DEVICE (dev), initsm_1000_run_state, + INITSM_1000_NUM_STATES); + break; + + case UPEKSONLY_1001: + ssm = fpi_ssm_new (FP_DEVICE (dev), initsm_1001_run_state, + INITSM_1001_NUM_STATES); + break; + } + fpi_ssm_start (ssm, initsm_complete); } -static int dev_init(struct fp_img_dev *dev, unsigned long driver_data); +static void dev_init (FpImageDevice *dev); -static void dev_deinit(struct fp_img_dev *dev) +static void +dev_deinit (FpImageDevice *dev) { - void *user_data; - user_data = FP_INSTANCE_DATA(FP_DEV(dev)); - g_free(user_data); - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - fpi_imgdev_close_complete(dev); + GError *error = NULL; + + g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), + 0, 0, &error); + fpi_image_device_close_complete (dev, error); } -static int dev_discover(struct libusb_device_descriptor *dsc, uint32_t *devtype) +static gint +dev_discover (GUsbDevice *usb_device) { - if (dsc->idProduct == 0x2016) { - if (dsc->bcdDevice == 1) /* Revision 1 is what we're interested in */ - return 1; - } - if (dsc->idProduct == 0x1000) { - if (dsc->bcdDevice == 0x0033) /* Looking for revision 0.33 */ - return 1; - } + guint16 pid = g_usb_device_get_pid (usb_device); + guint16 bcd = g_usb_device_get_release (usb_device); - if (dsc->idProduct == 0x1001) - return 1; + if (pid == 0x2016) + if (bcd == 1) /* Revision 1 is what we're interested in */ + return 1; + if (pid == 0x1000) + if (bcd == 0x0033) /* Looking for revision 0.33 */ + return 1; - return 0; + if (pid == 0x1001) + return 1; + + return 0; } -static const struct usb_id id_table[] = { - { .vendor = 0x147e, .product = 0x2016, .driver_data = UPEKSONLY_2016 }, - { .vendor = 0x147e, .product = 0x1000, .driver_data = UPEKSONLY_1000 }, - { .vendor = 0x147e, .product = 0x1001, .driver_data = UPEKSONLY_1001 }, - { 0, 0, 0, }, +static const FpIdEntry id_table[] = { + { .vid = 0x147e, .pid = 0x2016, .driver_data = UPEKSONLY_2016 }, + { .vid = 0x147e, .pid = 0x1000, .driver_data = UPEKSONLY_1000 }, + { .vid = 0x147e, .pid = 0x1001, .driver_data = UPEKSONLY_1001 }, + { .vid = 0, .pid = 0, .driver_data = 0 }, }; -struct fp_img_driver upeksonly_driver = { - .driver = { - .id = UPEKSONLY_ID, - .name = FP_COMPONENT, - .full_name = "UPEK TouchStrip Sensor-Only", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_SWIPE, - .discover = dev_discover, - }, - .flags = 0, - .img_width = -1, - .img_height = -1, - - .open = dev_init, - .close = dev_deinit, - .activate = dev_activate, - .deactivate = dev_deactivate, -}; - -static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) +static void +fpi_device_upeksonly_init (FpiDeviceUpeksonly *self) { - int r; - struct sonly_dev *sdev; +} +static void +fpi_device_upeksonly_class_init (FpiDeviceUpeksonlyClass *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); - r = libusb_set_configuration(fpi_dev_get_usb_dev(FP_DEV(dev)), 1); - if (r < 0) { - fp_err("could not set configuration 1"); - return r; - } + dev_class->id = "upeksonly"; + dev_class->full_name = "UPEK TouchStrip Sensor-Only"; + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->id_table = id_table; + dev_class->scan_type = FP_SCAN_TYPE_SWIPE; - r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - if (r < 0) { - fp_err("could not claim interface 0: %s", libusb_error_name(r)); - return r; - } + dev_class->usb_discover = dev_discover; - sdev = g_malloc0(sizeof(struct sonly_dev)); - fp_dev_set_instance_data(FP_DEV(dev), sdev); - sdev->dev_model = (int)driver_data; - switch (driver_data) { - case UPEKSONLY_1000: - sdev->img_width = IMG_WIDTH_1000; - upeksonly_driver.img_width = IMG_WIDTH_1000; - assembling_ctx.line_width = IMG_WIDTH_1000; - break; - case UPEKSONLY_1001: - sdev->img_width = IMG_WIDTH_1001; - upeksonly_driver.img_width = IMG_WIDTH_1001; - upeksonly_driver.bz3_threshold = 25; - assembling_ctx.line_width = IMG_WIDTH_1001; - break; - case UPEKSONLY_2016: - sdev->img_width = IMG_WIDTH_2016; - upeksonly_driver.img_width = IMG_WIDTH_2016; - assembling_ctx.line_width = IMG_WIDTH_2016; - break; - } - fpi_imgdev_open_complete(dev, 0); - return 0; + img_class->img_open = dev_init; + img_class->img_close = dev_deinit; + img_class->activate = dev_activate; + img_class->deactivate = dev_deactivate; + + img_class->img_width = -1; + img_class->img_height = -1; } +static void +dev_init (FpImageDevice *dev) +{ + GError *error = NULL; + FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev); + if (!g_usb_device_set_configuration (fpi_device_get_usb_device (FP_DEVICE (dev)), 1, &error)) + { + fp_err ("could not set configuration 1"); + fpi_image_device_open_complete (dev, error); + } + + if (!g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error)) + { + fpi_image_device_open_complete (dev, error); + return; + } + + self->assembling_ctx.max_height = 1024; + self->assembling_ctx.resolution = 8; + self->assembling_ctx.median_filter_size = 25; + self->assembling_ctx.max_search_offset = 30; + self->assembling_ctx.get_deviation = upeksonly_get_deviation2; + self->assembling_ctx.get_pixel = upeksonly_get_pixel; + + self = FPI_DEVICE_UPEKSONLY (dev); + self->dev_model = (int) fpi_device_get_driver_data (FP_DEVICE (dev)); + switch (self->dev_model) + { + case UPEKSONLY_1000: + self->img_width = IMG_WIDTH_1000; + self->assembling_ctx.line_width = IMG_WIDTH_1000; + break; + + case UPEKSONLY_1001: + self->img_width = IMG_WIDTH_1001; + self->assembling_ctx.line_width = IMG_WIDTH_1001; + + /* The sensor resolution is too low for the normal threshold. */ + fpi_image_device_set_bz3_threshold (dev, 25); + break; + + case UPEKSONLY_2016: + self->img_width = IMG_WIDTH_2016; + self->assembling_ctx.line_width = IMG_WIDTH_2016; + break; + + default: + g_assert_not_reached (); + } + fpi_image_device_open_complete (dev, NULL); +} diff --git a/libfprint/drivers/upeksonly.h b/libfprint/drivers/upeksonly.h index 4a3f72ba..611afda5 100644 --- a/libfprint/drivers/upeksonly.h +++ b/libfprint/drivers/upeksonly.h @@ -23,297 +23,298 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#define IMG_WIDTH_2016 288 -#define IMG_WIDTH_1000 288 -#define IMG_WIDTH_1001 216 +#define IMG_WIDTH_2016 288 +#define IMG_WIDTH_1000 288 +#define IMG_WIDTH_1001 216 -struct sonly_regwrite { - uint8_t reg; - uint8_t value; +struct sonly_regwrite +{ + guint8 reg; + guint8 value; }; /***** AWAIT FINGER *****/ static const struct sonly_regwrite awfsm_2016_writev_1[] = { - { 0x0a, 0x00 }, { 0x0a, 0x00 }, { 0x09, 0x20 }, { 0x03, 0x3b }, - { 0x00, 0x67 }, { 0x00, 0x67 }, + { 0x0a, 0x00 }, { 0x0a, 0x00 }, { 0x09, 0x20 }, { 0x03, 0x3b }, + { 0x00, 0x67 }, { 0x00, 0x67 }, }; static const struct sonly_regwrite awfsm_1000_writev_1[] = { - /* Initialize sensor settings */ - { 0x0a, 0x00 }, { 0x09, 0x20 }, { 0x03, 0x37 }, { 0x00, 0x5f }, - { 0x01, 0x6e }, { 0x01, 0xee }, { 0x0c, 0x13 }, { 0x0d, 0x0d }, - { 0x0e, 0x0e }, { 0x0f, 0x0d }, + /* Initialize sensor settings */ + { 0x0a, 0x00 }, { 0x09, 0x20 }, { 0x03, 0x37 }, { 0x00, 0x5f }, + { 0x01, 0x6e }, { 0x01, 0xee }, { 0x0c, 0x13 }, { 0x0d, 0x0d }, + { 0x0e, 0x0e }, { 0x0f, 0x0d }, - { 0x13, 0x05 }, { 0x13, 0x45 }, + { 0x13, 0x05 }, { 0x13, 0x45 }, - /* Initialize finger detection registers (not enabling yet) */ - { 0x30, 0xe0 }, { 0x15, 0x26 }, + /* Initialize finger detection registers (not enabling yet) */ + { 0x30, 0xe0 }, { 0x15, 0x26 }, - { 0x12, 0x01 }, { 0x20, 0x01 }, { 0x07, 0x10 }, - { 0x10, 0x00 }, { 0x11, 0xbf }, + { 0x12, 0x01 }, { 0x20, 0x01 }, { 0x07, 0x10 }, + { 0x10, 0x00 }, { 0x11, 0xbf }, }; static const struct sonly_regwrite awfsm_2016_writev_2[] = { - { 0x01, 0xc6 }, { 0x0c, 0x13 }, { 0x0d, 0x0d }, { 0x0e, 0x0e }, - { 0x0f, 0x0d }, { 0x0b, 0x00 }, + { 0x01, 0xc6 }, { 0x0c, 0x13 }, { 0x0d, 0x0d }, { 0x0e, 0x0e }, + { 0x0f, 0x0d }, { 0x0b, 0x00 }, }; static const struct sonly_regwrite awfsm_1000_writev_2[] = { - /* Enable finger detection */ - { 0x30, 0xe1 }, { 0x15, 0x06 }, { 0x15, 0x86 }, + /* Enable finger detection */ + { 0x30, 0xe1 }, { 0x15, 0x06 }, { 0x15, 0x86 }, }; static const struct sonly_regwrite awfsm_2016_writev_3[] = { - { 0x13, 0x45 }, { 0x30, 0xe0 }, { 0x12, 0x01 }, { 0x20, 0x01 }, - { 0x09, 0x20 }, { 0x0a, 0x00 }, { 0x30, 0xe0 }, { 0x20, 0x01 }, + { 0x13, 0x45 }, { 0x30, 0xe0 }, { 0x12, 0x01 }, { 0x20, 0x01 }, + { 0x09, 0x20 }, { 0x0a, 0x00 }, { 0x30, 0xe0 }, { 0x20, 0x01 }, }; static const struct sonly_regwrite awfsm_2016_writev_4[] = { - { 0x08, 0x00 }, { 0x10, 0x00 }, { 0x12, 0x01 }, { 0x11, 0xbf }, - { 0x12, 0x01 }, { 0x07, 0x10 }, { 0x07, 0x10 }, { 0x04, 0x00 },\ - { 0x05, 0x00 }, { 0x0b, 0x00 }, - - /* enter finger detection mode */ - { 0x15, 0x20 }, { 0x30, 0xe1 }, { 0x15, 0x24 }, { 0x15, 0x04 }, - { 0x15, 0x84 }, + { 0x08, 0x00 }, { 0x10, 0x00 }, { 0x12, 0x01 }, { 0x11, 0xbf }, + { 0x12, 0x01 }, { 0x07, 0x10 }, { 0x07, 0x10 }, { 0x04, 0x00 }, \ + { 0x05, 0x00 }, { 0x0b, 0x00 }, + + /* enter finger detection mode */ + { 0x15, 0x20 }, { 0x30, 0xe1 }, { 0x15, 0x24 }, { 0x15, 0x04 }, + { 0x15, 0x84 }, }; /***** CAPTURE MODE *****/ static const struct sonly_regwrite capsm_2016_writev[] = { - /* enter capture mode */ - { 0x09, 0x28 }, { 0x13, 0x55 }, { 0x0b, 0x80 }, { 0x04, 0x00 }, - { 0x05, 0x00 }, + /* enter capture mode */ + { 0x09, 0x28 }, { 0x13, 0x55 }, { 0x0b, 0x80 }, { 0x04, 0x00 }, + { 0x05, 0x00 }, }; static const struct sonly_regwrite capsm_1000_writev[] = { - { 0x08, 0x80 }, { 0x13, 0x55 }, { 0x0b, 0x80 }, /* Enter capture mode */ + { 0x08, 0x80 }, { 0x13, 0x55 }, { 0x0b, 0x80 }, /* Enter capture mode */ }; static const struct sonly_regwrite capsm_1001_writev_1[] = { - { 0x1a, 0x02 }, - { 0x4a, 0x9d }, - { 0x4e, 0x05 }, + { 0x1a, 0x02 }, + { 0x4a, 0x9d }, + { 0x4e, 0x05 }, }; static const struct sonly_regwrite capsm_1001_writev_2[] = { - { 0x4d, 0xc0 }, { 0x4e, 0x09 }, + { 0x4d, 0xc0 }, { 0x4e, 0x09 }, }; static const struct sonly_regwrite capsm_1001_writev_3[] = { - { 0x4a, 0x9c }, - { 0x1a, 0x00 }, - { 0x0b, 0x00 }, - { 0x04, 0x00 }, - { 0x05, 0x00 }, - { 0x1a, 0x02 }, - { 0x4a, 0x9d }, - { 0x4d, 0x40 }, { 0x4e, 0x09 }, + { 0x4a, 0x9c }, + { 0x1a, 0x00 }, + { 0x0b, 0x00 }, + { 0x04, 0x00 }, + { 0x05, 0x00 }, + { 0x1a, 0x02 }, + { 0x4a, 0x9d }, + { 0x4d, 0x40 }, { 0x4e, 0x09 }, }; static const struct sonly_regwrite capsm_1001_writev_4[] = { - { 0x4a, 0x9c }, - { 0x1a, 0x00 }, - { 0x1a, 0x02 }, - { 0x4a, 0x9d }, - { 0x4e, 0x08 }, + { 0x4a, 0x9c }, + { 0x1a, 0x00 }, + { 0x1a, 0x02 }, + { 0x4a, 0x9d }, + { 0x4e, 0x08 }, }; static const struct sonly_regwrite capsm_1001_writev_5[] = { - { 0x4a, 0x9c }, - { 0x1a, 0x00 }, - { 0x1a, 0x02 }, - { 0x00, 0x5f }, { 0x01, 0xee }, - { 0x03, 0x2c }, - { 0x07, 0x00 }, { 0x08, 0x00 }, { 0x09, 0x29 }, { 0x0a, 0x00 }, { 0x0b, 0x00 }, { 0x0c, 0x13 }, { 0x0d, 0x0d }, { 0x0e, 0x0e }, - { 0x0f, 0x0d }, { 0x10, 0x00 }, { 0x11, 0x8f }, { 0x12, 0x01 }, { 0x13, 0x45 }, - { 0x15, 0x26 }, - { 0x1e, 0x02 }, - { 0x20, 0x01 }, - { 0x25, 0x8f }, - { 0x27, 0x23 }, - { 0x30, 0xe0 }, - { 0x07, 0x10 }, - { 0x09, 0x21 }, - { 0x13, 0x75 }, - { 0x0b, 0x80 }, + { 0x4a, 0x9c }, + { 0x1a, 0x00 }, + { 0x1a, 0x02 }, + { 0x00, 0x5f }, { 0x01, 0xee }, + { 0x03, 0x2c }, + { 0x07, 0x00 }, { 0x08, 0x00 }, { 0x09, 0x29 }, { 0x0a, 0x00 }, { 0x0b, 0x00 }, { 0x0c, 0x13 }, { 0x0d, 0x0d }, { 0x0e, 0x0e }, + { 0x0f, 0x0d }, { 0x10, 0x00 }, { 0x11, 0x8f }, { 0x12, 0x01 }, { 0x13, 0x45 }, + { 0x15, 0x26 }, + { 0x1e, 0x02 }, + { 0x20, 0x01 }, + { 0x25, 0x8f }, + { 0x27, 0x23 }, + { 0x30, 0xe0 }, + { 0x07, 0x10 }, + { 0x09, 0x21 }, + { 0x13, 0x75 }, + { 0x0b, 0x80 }, }; /***** DEINITIALIZATION *****/ static const struct sonly_regwrite deinitsm_2016_writev[] = { - /* reset + enter low power mode */ - { 0x0b, 0x00 }, { 0x09, 0x20 }, { 0x13, 0x45 }, { 0x13, 0x45 }, + /* reset + enter low power mode */ + { 0x0b, 0x00 }, { 0x09, 0x20 }, { 0x13, 0x45 }, { 0x13, 0x45 }, }; static const struct sonly_regwrite deinitsm_1000_writev[] = { - { 0x15, 0x26 }, { 0x30, 0xe0 }, /* Disable finger detection */ + { 0x15, 0x26 }, { 0x30, 0xe0 }, /* Disable finger detection */ - { 0x0b, 0x00 }, { 0x13, 0x45 }, { 0x08, 0x00 }, /* Disable capture mode */ + { 0x0b, 0x00 }, { 0x13, 0x45 }, { 0x08, 0x00 }, /* Disable capture mode */ }; static const struct sonly_regwrite deinitsm_1001_writev[] = { - { 0x0b, 0x00 }, - { 0x13, 0x45 }, - { 0x09, 0x29 }, - { 0x1a, 0x00 }, + { 0x0b, 0x00 }, + { 0x13, 0x45 }, + { 0x09, 0x29 }, + { 0x1a, 0x00 }, }; /***** INITIALIZATION *****/ static const struct sonly_regwrite initsm_2016_writev_1[] = { - { 0x49, 0x00 }, - - /* BSAPI writes different values to register 0x3e each time. I initially - * thought this was some kind of clever authentication, but just blasting - * these sniffed values each time seems to work. */ - { 0x3e, 0x83 }, { 0x3e, 0x4f }, { 0x3e, 0x0f }, { 0x3e, 0xbf }, - { 0x3e, 0x45 }, { 0x3e, 0x35 }, { 0x3e, 0x1c }, { 0x3e, 0xae }, + { 0x49, 0x00 }, - { 0x44, 0x01 }, { 0x43, 0x06 }, { 0x43, 0x05 }, { 0x43, 0x04 }, - { 0x44, 0x00 }, { 0x0b, 0x00 }, + /* BSAPI writes different values to register 0x3e each time. I initially + * thought this was some kind of clever authentication, but just blasting + * these sniffed values each time seems to work. */ + { 0x3e, 0x83 }, { 0x3e, 0x4f }, { 0x3e, 0x0f }, { 0x3e, 0xbf }, + { 0x3e, 0x45 }, { 0x3e, 0x35 }, { 0x3e, 0x1c }, { 0x3e, 0xae }, + + { 0x44, 0x01 }, { 0x43, 0x06 }, { 0x43, 0x05 }, { 0x43, 0x04 }, + { 0x44, 0x00 }, { 0x0b, 0x00 }, }; static const struct sonly_regwrite initsm_1000_writev_1[] = { - { 0x49, 0x00 }, /* Encryption disabled */ + { 0x49, 0x00 }, /* Encryption disabled */ - /* Setting encryption key. Doesn't need to be random since we don't use any - * encryption. */ - { 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f }, - { 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f }, + /* Setting encryption key. Doesn't need to be random since we don't use any + * encryption. */ + { 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f }, + { 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f }, - { 0x04, 0x00 }, { 0x05, 0x00 }, + { 0x04, 0x00 }, { 0x05, 0x00 }, - { 0x0b, 0x00 }, { 0x08, 0x00 }, /* Initialize capture control registers */ + { 0x0b, 0x00 }, { 0x08, 0x00 }, /* Initialize capture control registers */ }; static const struct sonly_regwrite initsm_1001_writev_1[] = { - { 0x4a, 0x9d }, - { 0x4f, 0x06 }, - { 0x4f, 0x05 }, - { 0x4f, 0x04 }, - { 0x4a, 0x9c }, - { 0x3e, 0xa6 }, - { 0x3e, 0x01 }, - { 0x3e, 0x68 }, - { 0x3e, 0xfd }, - { 0x3e, 0x72 }, - { 0x3e, 0xef }, - { 0x3e, 0x5d }, - { 0x3e, 0xc5 }, - { 0x1a, 0x02 }, - { 0x4a, 0x9d }, - { 0x4c, 0x1f }, { 0x4d, 0xb8 }, { 0x4e, 0x00 }, + { 0x4a, 0x9d }, + { 0x4f, 0x06 }, + { 0x4f, 0x05 }, + { 0x4f, 0x04 }, + { 0x4a, 0x9c }, + { 0x3e, 0xa6 }, + { 0x3e, 0x01 }, + { 0x3e, 0x68 }, + { 0x3e, 0xfd }, + { 0x3e, 0x72 }, + { 0x3e, 0xef }, + { 0x3e, 0x5d }, + { 0x3e, 0xc5 }, + { 0x1a, 0x02 }, + { 0x4a, 0x9d }, + { 0x4c, 0x1f }, { 0x4d, 0xb8 }, { 0x4e, 0x00 }, }; static const struct sonly_regwrite initsm_1001_writev_2[] = { - { 0x4c, 0x03 }, { 0x4d, 0xb8 }, { 0x4e, 0x00 }, + { 0x4c, 0x03 }, { 0x4d, 0xb8 }, { 0x4e, 0x00 }, }; static const struct sonly_regwrite initsm_1001_writev_3[] = { - { 0x4a, 0x9c }, - { 0x1a, 0x00 }, - { 0x1a, 0x02 }, - { 0x4a, 0x9d }, - { 0x4c, 0xff }, { 0x4d, 0xc0 }, { 0x4e, 0x00 }, + { 0x4a, 0x9c }, + { 0x1a, 0x00 }, + { 0x1a, 0x02 }, + { 0x4a, 0x9d }, + { 0x4c, 0xff }, { 0x4d, 0xc0 }, { 0x4e, 0x00 }, }; static const struct sonly_regwrite initsm_1001_writev_4[] = { - { 0x4a, 0x9c }, - { 0x1a, 0x00 }, - { 0x09, 0x27 }, - { 0x1a, 0x02 }, - { 0x49, 0x01 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x0a }, - { 0x47, 0x00 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x0a }, - { 0x47, 0x00 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x0a }, - { 0x47, 0x00 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x02 }, - { 0x47, 0x0a }, - { 0x47, 0x00 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x47, 0x04 }, - { 0x49, 0x00 }, - { 0x3e, 0x90 }, - { 0x3e, 0xbd }, - { 0x3e, 0xbf }, - { 0x3e, 0x48 }, - { 0x3e, 0x2a }, - { 0x3e, 0xe3 }, - { 0x3e, 0xd2 }, - { 0x3e, 0x58 }, - { 0x09, 0x2f }, - { 0x1a, 0x00 }, - { 0x1a, 0x02 }, - { 0x4a, 0x9d }, - { 0x4d, 0x40 }, { 0x4e, 0x03 }, + { 0x4a, 0x9c }, + { 0x1a, 0x00 }, + { 0x09, 0x27 }, + { 0x1a, 0x02 }, + { 0x49, 0x01 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x0a }, + { 0x47, 0x00 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x0a }, + { 0x47, 0x00 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x0a }, + { 0x47, 0x00 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x02 }, + { 0x47, 0x0a }, + { 0x47, 0x00 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x47, 0x04 }, + { 0x49, 0x00 }, + { 0x3e, 0x90 }, + { 0x3e, 0xbd }, + { 0x3e, 0xbf }, + { 0x3e, 0x48 }, + { 0x3e, 0x2a }, + { 0x3e, 0xe3 }, + { 0x3e, 0xd2 }, + { 0x3e, 0x58 }, + { 0x09, 0x2f }, + { 0x1a, 0x00 }, + { 0x1a, 0x02 }, + { 0x4a, 0x9d }, + { 0x4d, 0x40 }, { 0x4e, 0x03 }, }; static const struct sonly_regwrite initsm_1001_writev_5[] = { - { 0x4a, 0x9c }, - { 0x1a, 0x00 }, + { 0x4a, 0x9c }, + { 0x1a, 0x00 }, }; diff --git a/libfprint/drivers/upektc.c b/libfprint/drivers/upektc.c index 00d9c553..ff5b49ba 100644 --- a/libfprint/drivers/upektc.c +++ b/libfprint/drivers/upektc.c @@ -23,456 +23,459 @@ #include "drivers_api.h" #include "upektc.h" -#define UPEKTC_EP_IN (2 | LIBUSB_ENDPOINT_IN) -#define UPEKTC_EP_OUT (3 | LIBUSB_ENDPOINT_OUT) -#define UPEKET_EP_IN (1 | LIBUSB_ENDPOINT_IN) -#define UPEKET_EP_OUT (2 | LIBUSB_ENDPOINT_OUT) +#define UPEKTC_EP_IN (2 | FPI_USB_ENDPOINT_IN) +#define UPEKTC_EP_OUT (3 | FPI_USB_ENDPOINT_OUT) +#define UPEKET_EP_IN (1 | FPI_USB_ENDPOINT_IN) +#define UPEKET_EP_OUT (2 | FPI_USB_ENDPOINT_OUT) #define BULK_TIMEOUT 4000 -struct upektc_dev { - gboolean deactivating; - const struct setup_cmd *setup_commands; - size_t setup_commands_len; - int ep_in; - int ep_out; - int init_idx; - int sum_threshold; +struct _FpiDeviceUpektc +{ + FpImageDevice parent; + + gboolean deactivating; + const struct setup_cmd *setup_commands; + size_t setup_commands_len; + int ep_in; + int ep_out; + int init_idx; + int sum_threshold; }; +G_DECLARE_FINAL_TYPE (FpiDeviceUpektc, fpi_device_upektc, FPI, DEVICE_UPEKTC, + FpImageDevice); +G_DEFINE_TYPE (FpiDeviceUpektc, fpi_device_upektc, FP_TYPE_IMAGE_DEVICE); enum upektc_driver_data { - UPEKTC_2015, - UPEKTC_3001, + UPEKTC_2015, + UPEKTC_3001, }; -static void start_capture(struct fp_img_dev *dev); -static void complete_deactivation(struct fp_img_dev *dev); -static void start_finger_detection(struct fp_img_dev *dev); +static void start_capture (FpImageDevice *dev); +static void complete_deactivation (FpImageDevice *dev, + GError *error); +static void start_finger_detection (FpImageDevice *dev); /****** INITIALIZATION/DEINITIALIZATION ******/ enum activate_states { - WRITE_INIT, - READ_DATA, - ACTIVATE_NUM_STATES, + WRITE_INIT, + READ_DATA, + ACTIVATE_NUM_STATES, }; static void -upektc_next_init_cmd(fpi_ssm *ssm, - struct fp_img_dev *dev) +upektc_next_init_cmd (FpiSsm *ssm, + FpImageDevice *dev) { - struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev); - upekdev->init_idx += 1; - if (upekdev->init_idx == upekdev->setup_commands_len) - fpi_ssm_mark_completed(ssm); - else - fpi_ssm_jump_to_state(ssm, WRITE_INIT); + self->init_idx += 1; + if (self->init_idx == self->setup_commands_len) + fpi_ssm_mark_completed (ssm); + else + fpi_ssm_jump_to_state (ssm, WRITE_INIT); } -static void write_init_cb(struct libusb_transfer *transfer) +static void +write_init_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev); - if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) && - (transfer->length == transfer->actual_length)) { - if (upekdev->setup_commands[upekdev->init_idx].response_len) - fpi_ssm_next_state(ssm); - else - upektc_next_init_cmd(ssm, dev); - } else { - fpi_ssm_mark_failed(ssm, -EIO); - } - libusb_free_transfer(transfer); + if (!error) + { + if (self->setup_commands[self->init_idx].response_len) + fpi_ssm_next_state (transfer->ssm); + else + upektc_next_init_cmd (transfer->ssm, dev); + } + else + { + fpi_ssm_mark_failed (transfer->ssm, error); + } } -static void read_init_data_cb(struct libusb_transfer *transfer) +static void +read_init_data_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); + FpImageDevice *dev = FP_IMAGE_DEVICE (device); - if (transfer->status == LIBUSB_TRANSFER_COMPLETED) - upektc_next_init_cmd(ssm, dev); - else - fpi_ssm_mark_failed(ssm, -EIO); - g_free(transfer->buffer); - libusb_free_transfer(transfer); + if (!error) + upektc_next_init_cmd (transfer->ssm, dev); + else + fpi_ssm_mark_failed (transfer->ssm, error); } -static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +activate_run_state (FpiSsm *ssm, FpDevice *dev) { - struct fp_img_dev *dev = user_data; - struct upektc_dev *upekdev = FP_INSTANCE_DATA(_dev); - int r; + FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case WRITE_INIT: - { - struct libusb_transfer *transfer = fpi_usb_alloc(); + switch (fpi_ssm_get_cur_state (ssm)) + { + case WRITE_INIT: + { + FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), upekdev->ep_out, - (unsigned char*)upekdev->setup_commands[upekdev->init_idx].cmd, - UPEKTC_CMD_LEN, write_init_cb, ssm, BULK_TIMEOUT); - r = libusb_submit_transfer(transfer); - if (r < 0) { - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, -ENOMEM); - } - } - break; - case READ_DATA: - { - struct libusb_transfer *transfer = fpi_usb_alloc(); - unsigned char *data; + fpi_usb_transfer_fill_bulk_full (transfer, + self->ep_out, + (unsigned char *) self->setup_commands[self->init_idx].cmd, + UPEKTC_CMD_LEN, + NULL); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + write_init_cb, NULL); + fpi_usb_transfer_unref (transfer); + } + break; - data = g_malloc(upekdev->setup_commands[upekdev->init_idx].response_len); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), upekdev->ep_in, data, - upekdev->setup_commands[upekdev->init_idx].response_len, - read_init_data_cb, ssm, BULK_TIMEOUT); + case READ_DATA: + { + FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev); - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(data); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } - } - break; - } + fpi_usb_transfer_fill_bulk (transfer, + self->ep_in, + self->setup_commands[self->init_idx].response_len); + transfer->ssm = ssm; + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + read_init_data_cb, NULL); + fpi_usb_transfer_unref (transfer); + } + break; + } } -static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { - struct fp_img_dev *dev = user_data; - fp_dbg("status %d", fpi_ssm_get_error(ssm)); - fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm)); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); - if (!fpi_ssm_get_error(ssm)) - start_finger_detection(dev); - fpi_ssm_free(ssm); + fpi_image_device_activate_complete (dev, error); + + if (!error) + start_finger_detection (dev); + fpi_ssm_free (ssm); } /****** FINGER PRESENCE DETECTION ******/ -static int finger_present(unsigned char *img, size_t len, int sum_threshold) +static int +finger_present (unsigned char *img, size_t len, int sum_threshold) { - int i, sum; + int i, sum; - sum = 0; + sum = 0; - for (i = 0; i < len; i++) { - if (img[i] < 160) { - sum++; - } - } + for (i = 0; i < len; i++) + if (img[i] < 160) + sum++; - fp_dbg("finger_present: sum is %d\n", sum); - return sum < sum_threshold ? 0 : 1; + fp_dbg ("finger_present: sum is %d\n", sum); + return sum < sum_threshold ? 0 : 1; } -static void finger_det_data_cb(struct libusb_transfer *transfer) +static void +finger_det_data_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - struct fp_img_dev *dev = transfer->user_data; - struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); - unsigned char *data = transfer->buffer; + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev); - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fp_dbg("data transfer status %d\n", transfer->status); - fpi_imgdev_session_error(dev, -EIO); - goto out; - } else if (transfer->length != transfer->actual_length) { - fp_dbg("expected %d, got %d bytes", transfer->length, - transfer->actual_length); - fpi_imgdev_session_error(dev, -EPROTO); - } + if (error) + { + fp_dbg ("data transfer status %s\n", error->message); + fpi_image_device_session_error (dev, error); + return; + } - if (finger_present(data, IMAGE_SIZE, upekdev->sum_threshold)) { - /* finger present, start capturing */ - fpi_imgdev_report_finger_status(dev, TRUE); - start_capture(dev); - } else { - /* no finger, poll for a new histogram */ - start_finger_detection(dev); - } - -out: - g_free(data); - libusb_free_transfer(transfer); + if (finger_present (transfer->buffer, IMAGE_SIZE, self->sum_threshold)) + { + /* finger present, start capturing */ + fpi_image_device_report_finger_status (dev, TRUE); + start_capture (dev); + } + else + { + /* no finger, poll for a new histogram */ + start_finger_detection (dev); + } } -static void finger_det_cmd_cb(struct libusb_transfer *t) +static void +finger_det_cmd_cb (FpiUsbTransfer *t, FpDevice *device, + gpointer user_data, GError *error) { - struct libusb_transfer *transfer; - unsigned char *data; - int r; - struct fp_img_dev *dev = t->user_data; - struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiUsbTransfer *transfer; + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev); - if (t->status != LIBUSB_TRANSFER_COMPLETED) { - fp_dbg("req transfer status %d\n", t->status); - fpi_imgdev_session_error(dev, -EIO); - goto exit_free_transfer; - } else if (t->length != t->actual_length) { - fp_dbg("expected %d, sent %d bytes", t->length, t->actual_length); - fpi_imgdev_session_error(dev, -EPROTO); - goto exit_free_transfer; - } + if (error) + { + fp_dbg ("req transfer status %s\n", error->message); + fpi_image_device_session_error (dev, error); + return; + } - transfer = fpi_usb_alloc(); - data = g_malloc(IMAGE_SIZE); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), upekdev->ep_in, data, IMAGE_SIZE, - finger_det_data_cb, dev, BULK_TIMEOUT); - - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(data); - libusb_free_transfer(transfer); - fpi_imgdev_session_error(dev, r); - } -exit_free_transfer: - libusb_free_transfer(t); + transfer = fpi_usb_transfer_new (device); + transfer->short_is_error = TRUE; + fpi_usb_transfer_fill_bulk (transfer, self->ep_in, + IMAGE_SIZE); + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + finger_det_data_cb, NULL); + fpi_usb_transfer_unref (transfer); } -static void start_finger_detection(struct fp_img_dev *dev) +static void +start_finger_detection (FpImageDevice *dev) { - int r; - struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); - struct libusb_transfer *transfer; - G_DEBUG_HERE(); + FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev); + FpiUsbTransfer *transfer; - if (upekdev->deactivating) { - complete_deactivation(dev); - return; - } + G_DEBUG_HERE (); - transfer = fpi_usb_alloc(); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), upekdev->ep_out, - (unsigned char *)scan_cmd, UPEKTC_CMD_LEN, - finger_det_cmd_cb, dev, BULK_TIMEOUT); - r = libusb_submit_transfer(transfer); - if (r < 0) { - libusb_free_transfer(transfer); - fpi_imgdev_session_error(dev, r); - } + if (self->deactivating) + { + complete_deactivation (dev, NULL); + return; + } + + transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); + transfer->short_is_error = TRUE; + fpi_usb_transfer_fill_bulk_full (transfer, self->ep_out, + (unsigned char *) scan_cmd, + UPEKTC_CMD_LEN, NULL); + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + finger_det_cmd_cb, NULL); + fpi_usb_transfer_unref (transfer); } /****** CAPTURE ******/ enum capture_states { - CAPTURE_WRITE_CMD, - CAPTURE_READ_DATA, - CAPTURE_NUM_STATES, + CAPTURE_WRITE_CMD, + CAPTURE_READ_DATA, + CAPTURE_NUM_STATES, }; -static void capture_cmd_cb(struct libusb_transfer *transfer) +static void +capture_cmd_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - - if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) && - (transfer->length == transfer->actual_length)) { - fpi_ssm_next_state(ssm); - } else { - fpi_ssm_mark_failed(ssm, -EIO); - } - libusb_free_transfer(transfer); + if (!error) + fpi_ssm_next_state (transfer->ssm); + else + fpi_ssm_mark_failed (transfer->ssm, error); } -static void capture_read_data_cb(struct libusb_transfer *transfer) +static void +capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - unsigned char *data = transfer->buffer; - struct fp_img *img; + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpImage *img; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fp_dbg("request is not completed, %d", transfer->status); - fpi_ssm_mark_failed(ssm, -EIO); - goto out; - } else if (transfer->length != transfer->actual_length) { - fp_dbg("expected %d, sent %d bytes", transfer->length, transfer->actual_length); - fpi_ssm_mark_failed(ssm, -EPROTO); - goto out; - } + if (error) + { + fp_dbg ("request is not completed, %s", error->message); + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } - img = fpi_img_new(IMAGE_SIZE); - memcpy(img->data, data, IMAGE_SIZE); - fpi_imgdev_image_captured(dev, img); - fpi_imgdev_report_finger_status(dev, FALSE); - fpi_ssm_mark_completed(ssm); -out: - g_free(transfer->buffer); - libusb_free_transfer(transfer); + img = fp_image_new (IMAGE_WIDTH, IMAGE_HEIGHT); + memcpy (img->data, transfer->buffer, IMAGE_SIZE); + fpi_image_device_image_captured (dev, img); + fpi_image_device_report_finger_status (dev, FALSE); + fpi_ssm_mark_completed (transfer->ssm); } -static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +capture_run_state (FpiSsm *ssm, FpDevice *_dev) { - struct fp_img_dev *dev = user_data; - struct upektc_dev *upekdev = FP_INSTANCE_DATA(_dev); - int r; + FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (_dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case CAPTURE_WRITE_CMD: - { - struct libusb_transfer *transfer = fpi_usb_alloc(); + switch (fpi_ssm_get_cur_state (ssm)) + { + case CAPTURE_WRITE_CMD: + { + FpiUsbTransfer *transfer = fpi_usb_transfer_new (_dev); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), upekdev->ep_out, - (unsigned char *)scan_cmd, UPEKTC_CMD_LEN, - capture_cmd_cb, ssm, BULK_TIMEOUT); - r = libusb_submit_transfer(transfer); - if (r < 0) { - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, -ENOMEM); - } - } - break; - case CAPTURE_READ_DATA: - { - struct libusb_transfer *transfer = fpi_usb_alloc(); - unsigned char *data; + fpi_usb_transfer_fill_bulk_full (transfer, self->ep_out, + (unsigned char *) scan_cmd, + UPEKTC_CMD_LEN, NULL); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + capture_cmd_cb, NULL); + fpi_usb_transfer_unref (transfer); + } + break; - data = g_malloc(IMAGE_SIZE); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), upekdev->ep_in, data, IMAGE_SIZE, - capture_read_data_cb, ssm, BULK_TIMEOUT); + case CAPTURE_READ_DATA: + { + FpiUsbTransfer *transfer = fpi_usb_transfer_new (_dev); - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(data); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } - } - break; - }; + fpi_usb_transfer_fill_bulk (transfer, self->ep_in, + IMAGE_SIZE); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + capture_read_data_cb, NULL); + fpi_usb_transfer_unref (transfer); + } + break; + } + ; } -static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { - struct fp_img_dev *dev = user_data; - struct upektc_dev *upekdev = FP_INSTANCE_DATA(_dev); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (_dev); - fp_dbg("Capture completed"); - if (upekdev->deactivating) - complete_deactivation(dev); - else if (fpi_ssm_get_error(ssm)) - fpi_imgdev_session_error(dev, fpi_ssm_get_error(ssm)); - else - start_finger_detection(dev); - fpi_ssm_free(ssm); + fp_dbg ("Capture completed"); + if (self->deactivating) + complete_deactivation (dev, error); + else if (error) + fpi_image_device_session_error (dev, error); + else + start_finger_detection (dev); + + fpi_ssm_free (ssm); } -static void start_capture(struct fp_img_dev *dev) +static void +start_capture (FpImageDevice *dev) { - struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_ssm *ssm; + FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev); + FpiSsm *ssm; - if (upekdev->deactivating) { - complete_deactivation(dev); - return; - } + if (self->deactivating) + { + complete_deactivation (dev, NULL); + return; + } - ssm = fpi_ssm_new(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev); - G_DEBUG_HERE(); - fpi_ssm_start(ssm, capture_sm_complete); + ssm = fpi_ssm_new (FP_DEVICE (dev), capture_run_state, CAPTURE_NUM_STATES); + G_DEBUG_HERE (); + fpi_ssm_start (ssm, capture_sm_complete); } -static int dev_activate(struct fp_img_dev *dev) +static void +dev_activate (FpImageDevice *dev) { - struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, - ACTIVATE_NUM_STATES, dev); - upekdev->init_idx = 0; - fpi_ssm_start(ssm, activate_sm_complete); - return 0; + FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev); + FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), activate_run_state, + ACTIVATE_NUM_STATES); + + self->init_idx = 0; + fpi_ssm_start (ssm, activate_sm_complete); } -static void dev_deactivate(struct fp_img_dev *dev) +static void +dev_deactivate (FpImageDevice *dev) { - struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev); - upekdev->deactivating = TRUE; + self->deactivating = TRUE; } -static void complete_deactivation(struct fp_img_dev *dev) +static void +complete_deactivation (FpImageDevice *dev, GError *error) { - struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); - G_DEBUG_HERE(); + FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev); - upekdev->deactivating = FALSE; - fpi_imgdev_deactivate_complete(dev); + G_DEBUG_HERE (); + + self->deactivating = FALSE; + fpi_image_device_deactivate_complete (dev, error); } -static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) +static void +dev_init (FpImageDevice *dev) { - /* TODO check that device has endpoints we're using */ - int r; - struct upektc_dev *upekdev; + GError *error = NULL; + FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev); + guint64 driver_data = fpi_device_get_driver_data (FP_DEVICE (dev)); - r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - if (r < 0) { - fp_err("could not claim interface 0: %s", libusb_error_name(r)); - return r; - } + /* TODO check that device has endpoints we're using */ - upekdev = g_malloc0(sizeof(struct upektc_dev)); - fp_dev_set_instance_data(FP_DEV(dev), upekdev); - switch (driver_data) { - case UPEKTC_2015: - upekdev->ep_in = UPEKTC_EP_IN; - upekdev->ep_out = UPEKTC_EP_OUT; - upekdev->setup_commands = upektc_setup_commands; - upekdev->setup_commands_len = G_N_ELEMENTS(upektc_setup_commands); - upekdev->sum_threshold = UPEKTC_SUM_THRESHOLD; - break; - case UPEKTC_3001: - upekdev->ep_in = UPEKET_EP_IN; - upekdev->ep_out = UPEKET_EP_OUT; - upekdev->setup_commands = upeket_setup_commands; - upekdev->setup_commands_len = G_N_ELEMENTS(upeket_setup_commands); - upekdev->sum_threshold = UPEKET_SUM_THRESHOLD; - break; - default: - fp_err("Device variant %lu is not known\n", driver_data); - g_free(upekdev); - fp_dev_set_instance_data(FP_DEV(dev), NULL); - return -ENODEV; - break; - } - fpi_imgdev_open_complete(dev, 0); - return 0; + if (!g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error)) + { + fpi_image_device_open_complete (dev, error); + return; + } + + switch (driver_data) + { + case UPEKTC_2015: + self->ep_in = UPEKTC_EP_IN; + self->ep_out = UPEKTC_EP_OUT; + self->setup_commands = upektc_setup_commands; + self->setup_commands_len = G_N_ELEMENTS (upektc_setup_commands); + self->sum_threshold = UPEKTC_SUM_THRESHOLD; + break; + + case UPEKTC_3001: + self->ep_in = UPEKET_EP_IN; + self->ep_out = UPEKET_EP_OUT; + self->setup_commands = upeket_setup_commands; + self->setup_commands_len = G_N_ELEMENTS (upeket_setup_commands); + self->sum_threshold = UPEKET_SUM_THRESHOLD; + break; + + default: + fp_err ("Device variant %lu is not known\n", driver_data); + g_assert_not_reached (); + fpi_image_device_open_complete (dev, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL)); + return; + } + fpi_image_device_open_complete (dev, NULL); } -static void dev_deinit(struct fp_img_dev *dev) +static void +dev_deinit (FpImageDevice *dev) { - void *user_data; - user_data = FP_INSTANCE_DATA(FP_DEV(dev)); - g_free(user_data); - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - fpi_imgdev_close_complete(dev); + GError *error = NULL; + + g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), + 0, 0, &error); + fpi_image_device_close_complete (dev, error); } -static const struct usb_id id_table[] = { - { .vendor = 0x0483, .product = 0x2015, .driver_data = UPEKTC_2015 }, - { .vendor = 0x147e, .product = 0x3001, .driver_data = UPEKTC_3001 }, - { 0, 0, 0, }, +static const FpIdEntry id_table[] = { + { .vid = 0x0483, .pid = 0x2015, .driver_data = UPEKTC_2015 }, + { .vid = 0x147e, .pid = 0x3001, .driver_data = UPEKTC_3001 }, + { .vid = 0, .pid = 0, .driver_data = 0 }, }; -struct fp_img_driver upektc_driver = { - .driver = { - .id = UPEKTC_ID, - .name = FP_COMPONENT, - .full_name = "UPEK TouchChip/Eikon Touch 300", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_PRESS, - }, - .flags = 0, - .img_height = IMAGE_HEIGHT, - .img_width = IMAGE_WIDTH, +static void +fpi_device_upektc_init (FpiDeviceUpektc *self) +{ +} +static void +fpi_device_upektc_class_init (FpiDeviceUpektcClass *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); - .bz3_threshold = 30, - .open = dev_init, - .close = dev_deinit, - .activate = dev_activate, - .deactivate = dev_deactivate, -}; + dev_class->id = "upektc"; + dev_class->full_name = "UPEK TouchChip/Eikon Touch 300"; + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->id_table = id_table; + dev_class->scan_type = FP_SCAN_TYPE_PRESS; + + img_class->img_open = dev_init; + img_class->img_close = dev_deinit; + img_class->activate = dev_activate; + img_class->deactivate = dev_deactivate; + + img_class->bz3_threshold = 30; + + img_class->img_width = IMAGE_WIDTH; + img_class->img_height = IMAGE_HEIGHT; +} diff --git a/libfprint/drivers/upektc.h b/libfprint/drivers/upektc.h index 143916e3..7ea919aa 100644 --- a/libfprint/drivers/upektc.h +++ b/libfprint/drivers/upektc.h @@ -29,1911 +29,1912 @@ #define UPEKTC_SUM_THRESHOLD 10000 #define UPEKET_SUM_THRESHOLD 5000 -struct setup_cmd { - unsigned char cmd[0x40]; - int response_len; +struct setup_cmd +{ + unsigned char cmd[0x40]; + int response_len; }; static const struct setup_cmd upektc_setup_commands[] = { - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0xfe, 0x00, 0x01, - 0xc0, 0xbd, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf0, 0xfd, 0x7f, 0x00, 0x60, 0xfd, 0x7f, - 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0xcc, 0xf8, 0x2f, 0x01, - 0x09, 0x48, 0xe7, 0x77, 0xf0, 0xfa, 0x2f, 0x01, - 0x09, 0x48, 0xe7, 0x77, 0xe0, 0x3a, 0xe6, 0x77 - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x00, 0x00, - 0xc8, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x58, 0xf9, 0x2f, 0x01, - 0xe9, 0x4f, 0x01, 0x10, 0xd8, 0xf8, 0x2f, 0x01, - 0x40, 0x00, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x02, 0xfe, 0x00, 0x01, 0xc0, 0xbd, 0xf0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0xfd, 0x7f - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0xf7, 0xcd, 0x00, - 0x2c, 0xf9, 0x2f, 0x01, 0x6d, 0x4f, 0x01, 0x10, - 0xac, 0xf8, 0x2f, 0x01, 0x40, 0x00, 0x00, 0x00, - 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0xfe, 0x16, 0x10, 0x03, 0xee, 0x00, 0x37, - 0x01, 0x09, 0x02, 0x0e, 0x03, 0x18, 0x03, 0x1a, - 0x03, 0x20, 0x10, 0x2f, 0x11, 0x3f, 0x12, 0x44, - 0x01, 0x01, 0x07, 0x08, 0x0c, 0x00, 0x6c, 0x6c - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, - 0x02, 0xfe, 0x16, 0x10, 0x03, 0xee, 0x00, 0x37, - 0x01, 0x09, 0x02, 0x0e, 0x03, 0x18, 0x03, 0x1a, - 0x03, 0x20, 0x10, 0x2f, 0x11, 0x3f, 0x12, 0x44, - 0x01, 0x01, 0x07, 0x08, 0x0c, 0x00, 0x6c, 0x6c, - 0x00, 0xf9, 0x2f, 0x01, 0x97, 0x40, 0x01, 0x10, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfa, 0x45, 0x03, 0x10, 0x02, 0x00, 0x00, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8b, 0x00, 0x00, 0x00, 0x3a, 0x50, 0xf9, 0x2f, - 0x01, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x88, 0xf9, 0x2f, - 0x01, 0x91, 0x99, 0x00, 0x10, 0xf8, 0x00, 0x00, - 0x00, 0xbe, 0x99, 0x00, 0x10, 0xa0, 0xa6, 0x04, - 0x10, 0x01, 0x9b, 0x00, 0x10, 0x18, 0x00, 0x00, - 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, - 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, - 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0x0d, 0xff, 0x36, - 0xdc, 0xf8, 0x2f, 0x01, 0xf1, 0x9d, 0x00, 0x10, - 0xfc, 0xf8, 0x2f, 0x01, 0x9d, 0xf8, 0x2f, 0x01, - 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x9e, 0xbf, 0x85, 0x85, 0x02, 0x05, 0x26, - 0x25, 0x4d, 0x13, 0x10, 0x00, 0x00, 0x00, 0x6c, - 0x00, 0x00, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x1f, - 0x01, 0x01, 0x09, 0x09, 0x0f, 0x00, 0x6c, 0x6c - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x0c, 0x37, 0x6a, 0x3d, - 0x73, 0x3d, 0x71, 0x0e, 0x01, 0x0e, 0x81, 0x3d, - 0x51, 0xf8, 0x2f, 0x01, 0x3a, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x9e, 0xbf, 0x85, - 0x85, 0x02, 0x05, 0x26, 0x25, 0x4d, 0x13, 0x10, - 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0xcf, 0x00, - 0x01, 0x00, 0x00, 0x1f, 0x01, 0x01, 0x09, 0x09, - 0x0f, 0x00, 0x6c, 0x6c, 0xf0, 0xf8, 0x2f, 0x01 - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, - 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8b, 0x00, 0x01, 0x7c, 0x0a, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, - 0x14, 0xf5, 0x2f, 0x01, 0xa0, 0x20, 0x14, 0x00, - 0x40, 0xf8, 0x2f, 0x01, 0x05, 0x90, 0xf6, 0x77, - 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x50, 0xf8, 0x2f, 0x01, 0x40, 0x39, 0xf4, 0x77, - 0xa8, 0x20, 0x14, 0x00, 0x1c, 0xf6, 0x2f, 0x01, - 0x2c, 0x20, 0xf4, 0x77, 0x80, 0x4d, 0xfb, 0x77 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8b, 0x00, 0x03, 0xc8, 0x3a, 0x01, 0x00, 0x00, - 0x1f, 0x01, 0x01, 0x09, 0x09, 0x0f, 0x00, 0x6c, - 0x6c, 0x6c, 0x6c, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x40, 0x40, 0x40, 0x40, 0x40, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x60, 0x62, 0x62, 0x62, 0x62, - 0x62, 0x51, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0xf9, 0x2f, 0x01, 0x4f, 0x9d, 0x00, - 0x10, 0x3a, 0x00, 0x00, 0x00, 0x04, 0xf9, 0x01 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8b, 0x00, 0x04, 0x02, 0x06, 0x0b, 0x07, 0x13, - 0x0e, 0x55, 0x56, 0x01, 0x44, 0xf8, 0x2f, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x00, - 0xc8, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x07, 0x00, 0x20, 0x00, 0x3a, 0x0e, 0x13, 0x07, - 0x0f, 0x14, 0x07, 0x10, 0x15, 0x07, 0x12, 0x16, - 0x07, 0x13, 0x17, 0x07, 0x14, 0x18, 0x07, 0x15, - 0x18, 0x07, 0x16, 0x19, 0x07, 0x17, 0x1a, 0x07, - 0x19, 0x1b, 0x07, 0x1a, 0x1c, 0x07, 0x1b, 0x1d, - 0x07, 0x1c, 0x1e, 0x07, 0x1d, 0x1f, 0x07, 0x1e, - 0x20, 0x07, 0x1f, 0x21, 0x07, 0x20, 0x22, 0x07, - 0x21, 0x23, 0x07, 0x23, 0x23, 0x07, 0x24, 0x55 - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x07, 0x00, 0x20, 0x3a, 0x26, 0x24, 0x07, 0x25, - 0x25, 0x07, 0x26, 0x25, 0x07, 0x27, 0x26, 0x07, - 0x28, 0x27, 0x07, 0x29, 0x27, 0x07, 0x2a, 0x28, - 0x07, 0x2b, 0x29, 0x07, 0x2d, 0x29, 0x07, 0x2e, - 0x2a, 0x07, 0x2f, 0x2b, 0x07, 0x30, 0x2b, 0x07, - 0x31, 0x2c, 0x07, 0x07, 0x1d, 0x1f, 0x07, 0x1e, - 0x20, 0x07, 0x1f, 0x21, 0x07, 0x20, 0x22, 0x07, - 0x21, 0x23, 0x07, 0x23, 0x23, 0x07, 0x24, 0x55 - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x06, 0x0e, 0x81, 0x0e, - 0x81, 0x09, 0x4d, 0x00, 0x07, 0x00, 0x20, 0x3a, - 0x26, 0x24, 0x07, 0x25, 0x25, 0x07, 0x26, 0x25, - 0x07, 0x27, 0x26, 0x07, 0x28, 0x27, 0x07, 0x29, - 0x27, 0x07, 0x2a, 0x28, 0x07, 0x2b, 0x29, 0x07, - 0x2d, 0x29, 0x07, 0x2e, 0x2a, 0x07, 0x2f, 0x2b, - 0x07, 0x30, 0x2b, 0x07, 0x31, 0x2c, 0x07, 0x07, - 0x1d, 0x1f, 0x07, 0x1e, 0x20, 0x07, 0x1f, 0x21 - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, - 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x85, 0x36, - 0xd8, 0xf8, 0x2f, 0x01, 0xf1, 0x9d, 0x00, 0x10, - 0xf8, 0xf8, 0x2f, 0x01, 0x99, 0xf8, 0x2f, 0x01, - 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x9e, 0xbf, 0x85, 0x85, 0x02, 0x05, 0x26, - 0x25, 0x4d, 0x10, 0x10, 0x00, 0xff, 0x81, 0x6c, - 0x00, 0x00, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x1f, - 0x01, 0x01, 0x09, 0x09, 0x0f, 0x00, 0x6c, 0x6c - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, - 0x02, 0x9e, 0xbf, 0x85, 0x85, 0x02, 0x05, 0x26, - 0x25, 0x4d, 0x10, 0x10, 0x00, 0xff, 0x81, 0x6c, - 0x00, 0x00, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x1f, - 0x01, 0x01, 0x09, 0x09, 0x0f, 0x00, 0x6c, 0x6c, - 0xec, 0xf8, 0x2f, 0x01, 0x97, 0x40, 0x01, 0x10, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfa, 0x45, 0x03, 0x10, 0x02, 0x00, 0x00, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xf7, 0xcf, 0x00, - 0x01, 0x00, 0x00, 0x1f, 0x01, 0x01, 0x09, 0x09, - 0x0f, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x40, 0x40, - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x62, - 0x62, 0x62, 0x62, 0x62, 0x51, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x00, 0x00, - 0x02, 0xf9, 0xbf, 0x85, 0x85, 0x02, 0x05, 0x26, - 0x25, 0x4d, 0x10, 0x10, 0x00, 0xff, 0x81, 0x6c, - 0x00, 0x00, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x1f, - 0x01, 0x01, 0x09, 0x09, 0x0f, 0x00, 0x6c, 0x6c, - 0x6c, 0x6c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x40, 0x40, 0x40, 0x40, 0x6c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x60, 0x62, 0x62, 0x62, 0x62, 0x62 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0xf7, 0xf4, 0x00, - 0x14, 0xf9, 0x2f, 0x01, 0x6d, 0x4f, 0x01, 0x10, - 0x94, 0xf8, 0x2f, 0x01, 0x40, 0x00, 0x00, 0x00, - 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0xf9, 0xbf, 0x85, 0x85, 0x02, 0x05, 0x26, - 0x25, 0x4d, 0x10, 0x10, 0x00, 0xff, 0x81, 0x6c, - 0x00, 0x00, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x1f, - 0x01, 0x01, 0x09, 0x09, 0x0f, 0x00, 0x6c, 0x6c - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0x20, 0x6c, 0x01, - 0x6d, 0x4f, 0x01, 0x10, 0x94, 0xf8, 0x2f, 0x01, - 0x40, 0x00, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0xf9, 0xbf, 0x85, - 0x85, 0x02, 0x05, 0x26, 0x25, 0x4d, 0x10, 0x10, - 0x00, 0xff, 0x81, 0x6c, 0x00, 0x00, 0xcf, 0x00, - 0x01, 0x00, 0x00, 0x1f, 0x01, 0x01, 0x09, 0x09, - 0x0f, 0x00, 0x6c, 0x6c, 0xe8, 0xf8, 0x2f, 0x01 - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xf9, 0x81, 0x6c, - 0x00, 0x00, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x1f, - 0x01, 0x01, 0x09, 0x09, 0x0f, 0x00, 0x6c, 0x6c, - 0xe8, 0xf8, 0x2f, 0x01, 0xec, 0xf8, 0x2f, 0x01, - 0x97, 0x40, 0x01, 0x10, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfa, 0x45, 0x03, 0x10, - 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0xf9, 0x01, 0x00, - 0x1c, 0xf9, 0x2f, 0x01, 0x6d, 0x4f, 0x01, 0x10, - 0x9c, 0xf8, 0x2f, 0x01, 0x40, 0x00, 0x00, 0x00, - 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x6c, 0xbf, 0x85, 0x85, 0x02, 0x05, 0x26, - 0x25, 0x4d, 0x10, 0x10, 0x00, 0xff, 0x81, 0x6c, - 0x00, 0x00, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x1f, - 0x01, 0x01, 0x09, 0x09, 0x0f, 0x00, 0x6c, 0x6c - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x12, 0x1c, 0x0c, 0x1b, - 0x08, 0x1a, 0x07, 0x30, 0x08, 0x09, 0x6d, 0x08, - 0x27, 0x00, 0x9e, 0x00, 0x1e, 0x23, 0x47, 0x01, - 0x40, 0x00, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x6c, 0xbf, 0x85, - 0x85, 0x02, 0x05, 0x26, 0x25, 0x4d, 0x10, 0x10, - 0x00, 0xff, 0x81, 0x6c, 0x00, 0x00, 0xcf, 0x00, - 0x01, 0x00, 0x00, 0x1f, 0x01, 0x01, 0x09, 0x09 - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, - 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0x0d, 0xff, 0x36, - 0xdc, 0xf8, 0x2f, 0x01, 0xf1, 0x9d, 0x00, 0x10, - 0xfc, 0xf8, 0x2f, 0x01, 0x9d, 0xf8, 0x2f, 0x01, - 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x1e, 0x3f, 0x05, 0x05, 0x02, 0x05, 0x26, - 0x27, 0x6d, 0x10, 0x10, 0x00, 0xff, 0x85, 0x6c, - 0x00, 0x00, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x1f, - 0x01, 0x01, 0x07, 0x08, 0x0c, 0x00, 0x6c, 0x6c - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0xcf, - 0x00, 0x01, 0x00, 0x00, 0x1f, 0x01, 0x01, 0x10, - 0xfc, 0xf8, 0x2f, 0x01, 0x9d, 0xf8, 0x2f, 0x01, - 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x1e, 0x3f, 0x05, 0x05, 0x02, 0x05, 0x26, - 0x27, 0x6d, 0x10, 0x10, 0x00, 0xff, 0x85, 0x6c, - 0x00, 0x00, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x1f, - 0x01, 0x01, 0x07, 0x08, 0x0c, 0x00, 0x6c, 0x6c - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x08, 0x0e, 0x85, 0x09, - 0xed, 0x09, 0x6d, 0x09, 0xed, 0x1e, 0x3f, 0x05, - 0x05, 0x02, 0x05, 0x26, 0x27, 0x6d, 0x10, 0x10, - 0x00, 0xff, 0x85, 0x6c, 0x00, 0x00, 0xcf, 0x00, - 0x01, 0x00, 0x00, 0x1f, 0x01, 0x01, 0x07, 0x08, - 0x0c, 0x00, 0x6c, 0x6c, 0xf0, 0xf8, 0x2f, 0x01, - 0x97, 0x40, 0x01, 0x10, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3e, 0xf9, 0x2f, 0x01 - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x6c, 0x6c, - 0xf0, 0xf8, 0x2f, 0x01, 0x97, 0x40, 0x01, 0x10, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3e, 0xf9, 0x2f, 0x01, 0x04, 0xf9, 0x2f, 0x01, - 0x97, 0x40, 0x01, 0x10, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x03, 0x10, - 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x84, 0x00, 0x00, 0x00, 0x32, 0x02, 0xa3, 0x04, - 0x10, 0x3b, 0xa3, 0x04, 0x10, 0x1a, 0xa3, 0x04, - 0x10, 0xf9, 0xa2, 0x04, 0x10, 0xd8, 0xa2, 0x00, - 0xb9, 0x19, 0xe2, 0x87, 0xba, 0x56, 0x78, 0x72, - 0x68, 0x9e, 0x7a, 0xf4, 0x65, 0x6d, 0xd9, 0xde, - 0xf6, 0x33, 0xa2, 0x04, 0x10, 0x12, 0xa2, 0x04, - 0x10, 0xf1, 0xa1, 0x04, 0x10, 0x04, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xb4, 0x2d, 0x6c, 0xe9 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x06, 0x1a, 0x07, 0x1b, - 0x08, 0x1c, 0x0c, 0x77, 0x21, 0xac, 0xe5, 0x77, - 0x00, 0x00, 0x00, 0x00, 0xaa, 0x4e, 0x01, 0x10, - 0x3c, 0x01, 0x00, 0x00, 0xc4, 0xf8, 0x2f, 0x01, - 0xdc, 0xf8, 0x2f, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0xb9, 0x19, 0xe2, 0x87, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00 - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0xcf, - 0x00, 0x01, 0x00, 0x00, 0x1f, 0x01, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0xcc, 0xf8, 0x2f, 0x01, 0x8b, 0x41, 0x01, 0x10, - 0x8c, 0xf8, 0x2f, 0x01, 0x40, 0x00, 0x00, 0x00 - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x04, 0x3d, 0x51, 0x0a, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfc, 0xf9, 0x2f, 0x01, 0x31, 0x10, 0x01, 0x10, - 0xd0, 0xf9, 0x2f, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x1a, 0x07, 0x1b, 0x08, 0x1c, 0x0c, 0xc6, 0xf8, - 0x66, 0xbc, 0xc4, 0xbe, 0x0b, 0x25, 0xc5, 0x4c, - 0xf4, 0x03, 0x10, 0x2f, 0x11, 0x3f, 0x12, 0x44 - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, - 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0x0a, 0x10, 0x36, - 0x88, 0xf9, 0x2f, 0x01, 0xf1, 0x9d, 0x00, 0x10, - 0xa8, 0xf9, 0x2f, 0x01, 0x49, 0xf9, 0x2f, 0x01, - 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x1e, 0x3f, 0x05, 0x05, 0x02, 0x05, 0x26, - 0x27, 0xed, 0x00, 0x10, 0x00, 0xff, 0x85, 0x6c, - 0x00, 0x00, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x1f, - 0x01, 0x01, 0x07, 0x08, 0x0c, 0x00, 0x6c, 0x6c - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x8b, 0x00, 0x00, 0xbc, 0x3a, 0x40, 0xd3, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xd8, 0xf4, 0x2f, 0x01, 0x80, 0x69, 0x67, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0xfd, - 0x7f, 0x00, 0x60, 0xfd, 0x7f, 0x3c, 0x01, 0x00, - 0x00, 0xa0, 0xf5, 0x2f, 0x01, 0x03, 0x01, 0x00, - 0x00, 0x9a, 0x11, 0xf4, 0x77, 0x9f, 0x11, 0xf4, - 0x77, 0x3c, 0x01, 0x00, 0x00, 0xa0, 0xf5, 0x01 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8b, 0x00, 0x00, 0xf6, 0x3a, 0x0b, 0x07, 0xa5, - 0x03, 0x2f, 0x63, 0x97, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8b, 0x00, 0x01, 0x30, 0x3a, 0x0b, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x12, 0xcd, 0xa6, 0x3c, - 0x36, 0xec, 0x6a, 0x73, 0x00, 0x64, 0x75, 0xdf, - 0x2e, 0x13, 0xec, 0xca, 0x3c, 0x03, 0x00, 0x00, - 0x06, 0xa5, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8b, 0x00, 0x01, 0x6a, 0x3a, 0x0b, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8b, 0x00, 0x01, 0xa4, 0x3a, 0x0b, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x06, 0xa5, 0x83, 0x1b, 0x8e, 0xac, 0x00, 0x00, - 0x0b, 0xa5, 0x08, 0x08, 0x03, 0x00, 0x00, 0x01, - 0x02, 0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x8d, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8b, 0x00, 0x01, 0xde, 0x3a, 0x0b, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8b, 0x00, 0x02, 0x18, 0x3a, 0x0b, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8b, 0x00, 0x02, 0x52, 0x3a, 0x0b, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8b, 0x00, 0x02, 0x8c, 0x3a, 0x0b, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8b, 0x00, 0x02, 0xc6, 0x2a, 0x0b, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x00, - 0xc8, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xf1, 0x2f, 0x01, - 0x49, 0xf9, 0x2f, 0x01, 0x3a, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x1e, 0x3f, 0x05, - 0x05, 0x02, 0x05, 0x26, 0x27, 0xed, 0x00, 0x10, - 0x00, 0xff, 0x85, 0x6c, 0x00, 0x00, 0xcf, 0x00, - 0x01, 0x00, 0x00, 0x1f, 0x01, 0x01, 0x07, 0x08, - 0x0c, 0x00, 0x6c, 0x6c, 0x9c, 0xf9, 0x2f, 0x01, - 0x97, 0x40, 0x01, 0x10, 0x03, 0x00, 0x00, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0xf1, 0x01, 0x00, - 0xb4, 0xf9, 0x2f, 0x01, 0x6d, 0x4f, 0x01, 0x10, - 0x34, 0xf9, 0x2f, 0x01, 0x40, 0x00, 0x00, 0x00, - 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x8b, 0x00, 0x01, 0x10, 0x3a, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8b, 0x00, 0x01, 0x4a, 0x2e, 0x0b, 0x06, 0xa5, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x00, - 0xc8, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xfb, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x88, 0xf9, 0x2f, 0x01, 0x97, 0x40, 0x01, 0x10, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfa, 0x45, 0x03, 0x10, 0x02, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0xfb, 0x0f, 0x00, - 0xc4, 0xf9, 0x2f, 0x01, 0x6d, 0x4f, 0x01, 0x10, - 0x44, 0xf9, 0x2f, 0x01, 0x40, 0x00, 0x00, 0x00, - 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }, - .response_len = 0x00 - } + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0xfe, 0x00, 0x01, + 0xc0, 0xbd, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0xf0, 0xfd, 0x7f, 0x00, 0x60, 0xfd, 0x7f, + 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0xcc, 0xf8, 0x2f, 0x01, + 0x09, 0x48, 0xe7, 0x77, 0xf0, 0xfa, 0x2f, 0x01, + 0x09, 0x48, 0xe7, 0x77, 0xe0, 0x3a, 0xe6, 0x77 + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x00, 0x00, + 0xc8, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x58, 0xf9, 0x2f, 0x01, + 0xe9, 0x4f, 0x01, 0x10, 0xd8, 0xf8, 0x2f, 0x01, + 0x40, 0x00, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0xfe, 0x00, 0x01, 0xc0, 0xbd, 0xf0, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0xfd, 0x7f + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0xf7, 0xcd, 0x00, + 0x2c, 0xf9, 0x2f, 0x01, 0x6d, 0x4f, 0x01, 0x10, + 0xac, 0xf8, 0x2f, 0x01, 0x40, 0x00, 0x00, 0x00, + 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0xfe, 0x16, 0x10, 0x03, 0xee, 0x00, 0x37, + 0x01, 0x09, 0x02, 0x0e, 0x03, 0x18, 0x03, 0x1a, + 0x03, 0x20, 0x10, 0x2f, 0x11, 0x3f, 0x12, 0x44, + 0x01, 0x01, 0x07, 0x08, 0x0c, 0x00, 0x6c, 0x6c + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, + 0x02, 0xfe, 0x16, 0x10, 0x03, 0xee, 0x00, 0x37, + 0x01, 0x09, 0x02, 0x0e, 0x03, 0x18, 0x03, 0x1a, + 0x03, 0x20, 0x10, 0x2f, 0x11, 0x3f, 0x12, 0x44, + 0x01, 0x01, 0x07, 0x08, 0x0c, 0x00, 0x6c, 0x6c, + 0x00, 0xf9, 0x2f, 0x01, 0x97, 0x40, 0x01, 0x10, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfa, 0x45, 0x03, 0x10, 0x02, 0x00, 0x00, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8b, 0x00, 0x00, 0x00, 0x3a, 0x50, 0xf9, 0x2f, + 0x01, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x88, 0xf9, 0x2f, + 0x01, 0x91, 0x99, 0x00, 0x10, 0xf8, 0x00, 0x00, + 0x00, 0xbe, 0x99, 0x00, 0x10, 0xa0, 0xa6, 0x04, + 0x10, 0x01, 0x9b, 0x00, 0x10, 0x18, 0x00, 0x00, + 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, + 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, + 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0x0d, 0xff, 0x36, + 0xdc, 0xf8, 0x2f, 0x01, 0xf1, 0x9d, 0x00, 0x10, + 0xfc, 0xf8, 0x2f, 0x01, 0x9d, 0xf8, 0x2f, 0x01, + 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x9e, 0xbf, 0x85, 0x85, 0x02, 0x05, 0x26, + 0x25, 0x4d, 0x13, 0x10, 0x00, 0x00, 0x00, 0x6c, + 0x00, 0x00, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x1f, + 0x01, 0x01, 0x09, 0x09, 0x0f, 0x00, 0x6c, 0x6c + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x0c, 0x37, 0x6a, 0x3d, + 0x73, 0x3d, 0x71, 0x0e, 0x01, 0x0e, 0x81, 0x3d, + 0x51, 0xf8, 0x2f, 0x01, 0x3a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x9e, 0xbf, 0x85, + 0x85, 0x02, 0x05, 0x26, 0x25, 0x4d, 0x13, 0x10, + 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0xcf, 0x00, + 0x01, 0x00, 0x00, 0x1f, 0x01, 0x01, 0x09, 0x09, + 0x0f, 0x00, 0x6c, 0x6c, 0xf0, 0xf8, 0x2f, 0x01 + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, + 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8b, 0x00, 0x01, 0x7c, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, + 0x14, 0xf5, 0x2f, 0x01, 0xa0, 0x20, 0x14, 0x00, + 0x40, 0xf8, 0x2f, 0x01, 0x05, 0x90, 0xf6, 0x77, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x50, 0xf8, 0x2f, 0x01, 0x40, 0x39, 0xf4, 0x77, + 0xa8, 0x20, 0x14, 0x00, 0x1c, 0xf6, 0x2f, 0x01, + 0x2c, 0x20, 0xf4, 0x77, 0x80, 0x4d, 0xfb, 0x77 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8b, 0x00, 0x03, 0xc8, 0x3a, 0x01, 0x00, 0x00, + 0x1f, 0x01, 0x01, 0x09, 0x09, 0x0f, 0x00, 0x6c, + 0x6c, 0x6c, 0x6c, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x6c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x62, 0x62, 0x62, 0x62, + 0x62, 0x51, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0xf9, 0x2f, 0x01, 0x4f, 0x9d, 0x00, + 0x10, 0x3a, 0x00, 0x00, 0x00, 0x04, 0xf9, 0x01 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8b, 0x00, 0x04, 0x02, 0x06, 0x0b, 0x07, 0x13, + 0x0e, 0x55, 0x56, 0x01, 0x44, 0xf8, 0x2f, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x00, + 0xc8, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x07, 0x00, 0x20, 0x00, 0x3a, 0x0e, 0x13, 0x07, + 0x0f, 0x14, 0x07, 0x10, 0x15, 0x07, 0x12, 0x16, + 0x07, 0x13, 0x17, 0x07, 0x14, 0x18, 0x07, 0x15, + 0x18, 0x07, 0x16, 0x19, 0x07, 0x17, 0x1a, 0x07, + 0x19, 0x1b, 0x07, 0x1a, 0x1c, 0x07, 0x1b, 0x1d, + 0x07, 0x1c, 0x1e, 0x07, 0x1d, 0x1f, 0x07, 0x1e, + 0x20, 0x07, 0x1f, 0x21, 0x07, 0x20, 0x22, 0x07, + 0x21, 0x23, 0x07, 0x23, 0x23, 0x07, 0x24, 0x55 + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x07, 0x00, 0x20, 0x3a, 0x26, 0x24, 0x07, 0x25, + 0x25, 0x07, 0x26, 0x25, 0x07, 0x27, 0x26, 0x07, + 0x28, 0x27, 0x07, 0x29, 0x27, 0x07, 0x2a, 0x28, + 0x07, 0x2b, 0x29, 0x07, 0x2d, 0x29, 0x07, 0x2e, + 0x2a, 0x07, 0x2f, 0x2b, 0x07, 0x30, 0x2b, 0x07, + 0x31, 0x2c, 0x07, 0x07, 0x1d, 0x1f, 0x07, 0x1e, + 0x20, 0x07, 0x1f, 0x21, 0x07, 0x20, 0x22, 0x07, + 0x21, 0x23, 0x07, 0x23, 0x23, 0x07, 0x24, 0x55 + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x06, 0x0e, 0x81, 0x0e, + 0x81, 0x09, 0x4d, 0x00, 0x07, 0x00, 0x20, 0x3a, + 0x26, 0x24, 0x07, 0x25, 0x25, 0x07, 0x26, 0x25, + 0x07, 0x27, 0x26, 0x07, 0x28, 0x27, 0x07, 0x29, + 0x27, 0x07, 0x2a, 0x28, 0x07, 0x2b, 0x29, 0x07, + 0x2d, 0x29, 0x07, 0x2e, 0x2a, 0x07, 0x2f, 0x2b, + 0x07, 0x30, 0x2b, 0x07, 0x31, 0x2c, 0x07, 0x07, + 0x1d, 0x1f, 0x07, 0x1e, 0x20, 0x07, 0x1f, 0x21 + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, + 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x85, 0x36, + 0xd8, 0xf8, 0x2f, 0x01, 0xf1, 0x9d, 0x00, 0x10, + 0xf8, 0xf8, 0x2f, 0x01, 0x99, 0xf8, 0x2f, 0x01, + 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x9e, 0xbf, 0x85, 0x85, 0x02, 0x05, 0x26, + 0x25, 0x4d, 0x10, 0x10, 0x00, 0xff, 0x81, 0x6c, + 0x00, 0x00, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x1f, + 0x01, 0x01, 0x09, 0x09, 0x0f, 0x00, 0x6c, 0x6c + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, + 0x02, 0x9e, 0xbf, 0x85, 0x85, 0x02, 0x05, 0x26, + 0x25, 0x4d, 0x10, 0x10, 0x00, 0xff, 0x81, 0x6c, + 0x00, 0x00, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x1f, + 0x01, 0x01, 0x09, 0x09, 0x0f, 0x00, 0x6c, 0x6c, + 0xec, 0xf8, 0x2f, 0x01, 0x97, 0x40, 0x01, 0x10, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfa, 0x45, 0x03, 0x10, 0x02, 0x00, 0x00, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xf7, 0xcf, 0x00, + 0x01, 0x00, 0x00, 0x1f, 0x01, 0x01, 0x09, 0x09, + 0x0f, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x62, + 0x62, 0x62, 0x62, 0x62, 0x51, 0x6c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x00, 0x00, + 0x02, 0xf9, 0xbf, 0x85, 0x85, 0x02, 0x05, 0x26, + 0x25, 0x4d, 0x10, 0x10, 0x00, 0xff, 0x81, 0x6c, + 0x00, 0x00, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x1f, + 0x01, 0x01, 0x09, 0x09, 0x0f, 0x00, 0x6c, 0x6c, + 0x6c, 0x6c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x60, 0x62, 0x62, 0x62, 0x62, 0x62 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0xf7, 0xf4, 0x00, + 0x14, 0xf9, 0x2f, 0x01, 0x6d, 0x4f, 0x01, 0x10, + 0x94, 0xf8, 0x2f, 0x01, 0x40, 0x00, 0x00, 0x00, + 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0xf9, 0xbf, 0x85, 0x85, 0x02, 0x05, 0x26, + 0x25, 0x4d, 0x10, 0x10, 0x00, 0xff, 0x81, 0x6c, + 0x00, 0x00, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x1f, + 0x01, 0x01, 0x09, 0x09, 0x0f, 0x00, 0x6c, 0x6c + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0x20, 0x6c, 0x01, + 0x6d, 0x4f, 0x01, 0x10, 0x94, 0xf8, 0x2f, 0x01, + 0x40, 0x00, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0xf9, 0xbf, 0x85, + 0x85, 0x02, 0x05, 0x26, 0x25, 0x4d, 0x10, 0x10, + 0x00, 0xff, 0x81, 0x6c, 0x00, 0x00, 0xcf, 0x00, + 0x01, 0x00, 0x00, 0x1f, 0x01, 0x01, 0x09, 0x09, + 0x0f, 0x00, 0x6c, 0x6c, 0xe8, 0xf8, 0x2f, 0x01 + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xf9, 0x81, 0x6c, + 0x00, 0x00, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x1f, + 0x01, 0x01, 0x09, 0x09, 0x0f, 0x00, 0x6c, 0x6c, + 0xe8, 0xf8, 0x2f, 0x01, 0xec, 0xf8, 0x2f, 0x01, + 0x97, 0x40, 0x01, 0x10, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfa, 0x45, 0x03, 0x10, + 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0xf9, 0x01, 0x00, + 0x1c, 0xf9, 0x2f, 0x01, 0x6d, 0x4f, 0x01, 0x10, + 0x9c, 0xf8, 0x2f, 0x01, 0x40, 0x00, 0x00, 0x00, + 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x6c, 0xbf, 0x85, 0x85, 0x02, 0x05, 0x26, + 0x25, 0x4d, 0x10, 0x10, 0x00, 0xff, 0x81, 0x6c, + 0x00, 0x00, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x1f, + 0x01, 0x01, 0x09, 0x09, 0x0f, 0x00, 0x6c, 0x6c + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x12, 0x1c, 0x0c, 0x1b, + 0x08, 0x1a, 0x07, 0x30, 0x08, 0x09, 0x6d, 0x08, + 0x27, 0x00, 0x9e, 0x00, 0x1e, 0x23, 0x47, 0x01, + 0x40, 0x00, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x6c, 0xbf, 0x85, + 0x85, 0x02, 0x05, 0x26, 0x25, 0x4d, 0x10, 0x10, + 0x00, 0xff, 0x81, 0x6c, 0x00, 0x00, 0xcf, 0x00, + 0x01, 0x00, 0x00, 0x1f, 0x01, 0x01, 0x09, 0x09 + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, + 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0x0d, 0xff, 0x36, + 0xdc, 0xf8, 0x2f, 0x01, 0xf1, 0x9d, 0x00, 0x10, + 0xfc, 0xf8, 0x2f, 0x01, 0x9d, 0xf8, 0x2f, 0x01, + 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x1e, 0x3f, 0x05, 0x05, 0x02, 0x05, 0x26, + 0x27, 0x6d, 0x10, 0x10, 0x00, 0xff, 0x85, 0x6c, + 0x00, 0x00, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x1f, + 0x01, 0x01, 0x07, 0x08, 0x0c, 0x00, 0x6c, 0x6c + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0xcf, + 0x00, 0x01, 0x00, 0x00, 0x1f, 0x01, 0x01, 0x10, + 0xfc, 0xf8, 0x2f, 0x01, 0x9d, 0xf8, 0x2f, 0x01, + 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x1e, 0x3f, 0x05, 0x05, 0x02, 0x05, 0x26, + 0x27, 0x6d, 0x10, 0x10, 0x00, 0xff, 0x85, 0x6c, + 0x00, 0x00, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x1f, + 0x01, 0x01, 0x07, 0x08, 0x0c, 0x00, 0x6c, 0x6c + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x08, 0x0e, 0x85, 0x09, + 0xed, 0x09, 0x6d, 0x09, 0xed, 0x1e, 0x3f, 0x05, + 0x05, 0x02, 0x05, 0x26, 0x27, 0x6d, 0x10, 0x10, + 0x00, 0xff, 0x85, 0x6c, 0x00, 0x00, 0xcf, 0x00, + 0x01, 0x00, 0x00, 0x1f, 0x01, 0x01, 0x07, 0x08, + 0x0c, 0x00, 0x6c, 0x6c, 0xf0, 0xf8, 0x2f, 0x01, + 0x97, 0x40, 0x01, 0x10, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0xf9, 0x2f, 0x01 + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xf3, 0x6c, 0x6c, + 0xf0, 0xf8, 0x2f, 0x01, 0x97, 0x40, 0x01, 0x10, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3e, 0xf9, 0x2f, 0x01, 0x04, 0xf9, 0x2f, 0x01, + 0x97, 0x40, 0x01, 0x10, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x03, 0x10, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x84, 0x00, 0x00, 0x00, 0x32, 0x02, 0xa3, 0x04, + 0x10, 0x3b, 0xa3, 0x04, 0x10, 0x1a, 0xa3, 0x04, + 0x10, 0xf9, 0xa2, 0x04, 0x10, 0xd8, 0xa2, 0x00, + 0xb9, 0x19, 0xe2, 0x87, 0xba, 0x56, 0x78, 0x72, + 0x68, 0x9e, 0x7a, 0xf4, 0x65, 0x6d, 0xd9, 0xde, + 0xf6, 0x33, 0xa2, 0x04, 0x10, 0x12, 0xa2, 0x04, + 0x10, 0xf1, 0xa1, 0x04, 0x10, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xb4, 0x2d, 0x6c, 0xe9 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x06, 0x1a, 0x07, 0x1b, + 0x08, 0x1c, 0x0c, 0x77, 0x21, 0xac, 0xe5, 0x77, + 0x00, 0x00, 0x00, 0x00, 0xaa, 0x4e, 0x01, 0x10, + 0x3c, 0x01, 0x00, 0x00, 0xc4, 0xf8, 0x2f, 0x01, + 0xdc, 0xf8, 0x2f, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0xb9, 0x19, 0xe2, 0x87, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00 + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0xcf, + 0x00, 0x01, 0x00, 0x00, 0x1f, 0x01, 0x01, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xcc, 0xf8, 0x2f, 0x01, 0x8b, 0x41, 0x01, 0x10, + 0x8c, 0xf8, 0x2f, 0x01, 0x40, 0x00, 0x00, 0x00 + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x04, 0x3d, 0x51, 0x0a, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0xf9, 0x2f, 0x01, 0x31, 0x10, 0x01, 0x10, + 0xd0, 0xf9, 0x2f, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x1a, 0x07, 0x1b, 0x08, 0x1c, 0x0c, 0xc6, 0xf8, + 0x66, 0xbc, 0xc4, 0xbe, 0x0b, 0x25, 0xc5, 0x4c, + 0xf4, 0x03, 0x10, 0x2f, 0x11, 0x3f, 0x12, 0x44 + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, + 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0x0a, 0x10, 0x36, + 0x88, 0xf9, 0x2f, 0x01, 0xf1, 0x9d, 0x00, 0x10, + 0xa8, 0xf9, 0x2f, 0x01, 0x49, 0xf9, 0x2f, 0x01, + 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x1e, 0x3f, 0x05, 0x05, 0x02, 0x05, 0x26, + 0x27, 0xed, 0x00, 0x10, 0x00, 0xff, 0x85, 0x6c, + 0x00, 0x00, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x1f, + 0x01, 0x01, 0x07, 0x08, 0x0c, 0x00, 0x6c, 0x6c + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x8b, 0x00, 0x00, 0xbc, 0x3a, 0x40, 0xd3, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xd8, 0xf4, 0x2f, 0x01, 0x80, 0x69, 0x67, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0xfd, + 0x7f, 0x00, 0x60, 0xfd, 0x7f, 0x3c, 0x01, 0x00, + 0x00, 0xa0, 0xf5, 0x2f, 0x01, 0x03, 0x01, 0x00, + 0x00, 0x9a, 0x11, 0xf4, 0x77, 0x9f, 0x11, 0xf4, + 0x77, 0x3c, 0x01, 0x00, 0x00, 0xa0, 0xf5, 0x01 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8b, 0x00, 0x00, 0xf6, 0x3a, 0x0b, 0x07, 0xa5, + 0x03, 0x2f, 0x63, 0x97, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8b, 0x00, 0x01, 0x30, 0x3a, 0x0b, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x12, 0xcd, 0xa6, 0x3c, + 0x36, 0xec, 0x6a, 0x73, 0x00, 0x64, 0x75, 0xdf, + 0x2e, 0x13, 0xec, 0xca, 0x3c, 0x03, 0x00, 0x00, + 0x06, 0xa5, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8b, 0x00, 0x01, 0x6a, 0x3a, 0x0b, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8b, 0x00, 0x01, 0xa4, 0x3a, 0x0b, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0xa5, 0x83, 0x1b, 0x8e, 0xac, 0x00, 0x00, + 0x0b, 0xa5, 0x08, 0x08, 0x03, 0x00, 0x00, 0x01, + 0x02, 0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x8d, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8b, 0x00, 0x01, 0xde, 0x3a, 0x0b, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8b, 0x00, 0x02, 0x18, 0x3a, 0x0b, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8b, 0x00, 0x02, 0x52, 0x3a, 0x0b, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8b, 0x00, 0x02, 0x8c, 0x3a, 0x0b, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8b, 0x00, 0x02, 0xc6, 0x2a, 0x0b, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x00, + 0xc8, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xf1, 0x2f, 0x01, + 0x49, 0xf9, 0x2f, 0x01, 0x3a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x1e, 0x3f, 0x05, + 0x05, 0x02, 0x05, 0x26, 0x27, 0xed, 0x00, 0x10, + 0x00, 0xff, 0x85, 0x6c, 0x00, 0x00, 0xcf, 0x00, + 0x01, 0x00, 0x00, 0x1f, 0x01, 0x01, 0x07, 0x08, + 0x0c, 0x00, 0x6c, 0x6c, 0x9c, 0xf9, 0x2f, 0x01, + 0x97, 0x40, 0x01, 0x10, 0x03, 0x00, 0x00, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0xf1, 0x01, 0x00, + 0xb4, 0xf9, 0x2f, 0x01, 0x6d, 0x4f, 0x01, 0x10, + 0x34, 0xf9, 0x2f, 0x01, 0x40, 0x00, 0x00, 0x00, + 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x8b, 0x00, 0x01, 0x10, 0x3a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8b, 0x00, 0x01, 0x4a, 0x2e, 0x0b, 0x06, 0xa5, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x00, + 0xc8, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xfb, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x88, 0xf9, 0x2f, 0x01, 0x97, 0x40, 0x01, 0x10, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfa, 0x45, 0x03, 0x10, 0x02, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0xfb, 0x0f, 0x00, + 0xc4, 0xf9, 0x2f, 0x01, 0x6d, 0x4f, 0x01, 0x10, + 0x44, 0xf9, 0x2f, 0x01, 0x40, 0x00, 0x00, 0x00, + 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + .response_len = 0x00 + } }; static const struct setup_cmd upeket_setup_commands[] = { - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xF3, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0xfe, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xb8, 0x00, 0x00, 0x00, 0x98, 0xf1, 0x12, 0x00, - 0x03, 0xd4, 0xa9, 0x00, 0x64, 0x00, 0x00, 0x00, - 0x14, 0x20, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x84, 0xf1, 0x12, 0x00, - 0x0c, 0x00, 0x00, 0x00, 0x90, 0xf1, 0x12, 0x00, - 0xac, 0x0d, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x90, 0xf1, 0x12, 0x00, - 0x92, 0xc5, 0xa9, 0x00, 0x48, 0xf1, 0x12, 0x00, - 0x40, 0x00, 0x00, 0x00, 0xa2, 0xc5, 0xa9, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x02, 0xfe, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xb8, 0x00, 0x00, 0x00, 0x98, 0xf1, 0x12, 0x00, - 0x03, 0xd4, 0xa9, 0x00, 0x64, 0x00, 0x00, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0xf7, 0xcd, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xf8, 0xa9, 0x00, - 0x28, 0xf1, 0x12, 0x00, 0x40, 0x00, 0x00, 0x00, - 0xbb, 0xc4, 0xa9, 0x00, 0x02, 0xfa, 0x3f, 0x05, - 0x05, 0x02, 0x05, 0x23, 0x27, 0xe5, 0x13, 0x10, - 0x08, 0xff, 0x04, 0x6c, 0xc1, 0x41, 0x1c, 0x4c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x60, 0xf1, 0x12, 0x00, 0x89, 0xae, 0xa9, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8b, 0x00, 0x00, 0x00, 0x3a, 0x8c, 0xf1, 0x12, - 0x00, 0x64, 0xa8, 0xa7, 0x00, 0x84, 0xf1, 0x12, - 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf1, 0x12, - 0x00, 0x51, 0xa6, 0xa7, 0x00, 0xf8, 0x00, 0x00, - 0x00, 0x7e, 0xa6, 0xa7, 0x00, 0x24, 0x5a, 0xac, - 0x00, 0x01, 0xf1, 0x12, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x2f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, - 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x7c, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, - 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0x0d, 0xff, 0x00, - 0x34, 0xf1, 0x12, 0x00, 0x40, 0x00, 0x00, 0x00, - 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf1, 0x12, 0x00, 0x57, 0xcc, 0xa9, 0x00, - 0x34, 0xf1, 0x12, 0x00, 0x40, 0x00, 0x00, 0x00, - 0xbd, 0xcc, 0xa9, 0x00, 0x3a, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, - 0x34, 0xf1, 0x12, 0x00, 0x3a, 0x00, 0x00, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x0a, 0x37, 0x6a, 0x3d, - 0x73, 0x3d, 0x71, 0x0e, 0x01, 0x0e, 0x81, 0x00, - 0x40, 0x00, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x12, 0x00, - 0x57, 0xcc, 0xa9, 0x00, 0x34, 0xf1, 0x12, 0x00, - 0x40, 0x00, 0x00, 0x00, 0xbd, 0xcc, 0xa9, 0x00, - 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xb8, 0x00, 0x00, 0x00, 0x34, 0xf1, 0x12, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, - 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0x3d, 0x51, 0x0e, - 0x01, 0x0e, 0x81, 0x00, 0x40, 0x00, 0x00, 0x00, - 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf1, 0x12, 0x00, 0x57, 0xcc, 0xa9, 0x00, - 0x34, 0xf1, 0x12, 0x00, 0x40, 0x00, 0x00, 0x00, - 0xbd, 0xcc, 0xa9, 0x00, 0x3a, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, - 0x34, 0xf1, 0x12, 0x00, 0x3a, 0x00, 0x00, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, - 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x04, 0x78, 0x3A, 0x34, 0x00, 0x00, - 0xC0, 0x00, 0x00, 0x00, 0x00, 0x24, 0x1A, 0x80, - 0x7C, 0x04, 0xF1, 0x12, 0x00, 0x18, 0x00, 0x00, - 0x00, 0x48, 0x00, 0x00, 0x00, 0xCC, 0xEF, 0x12, - 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xB0, 0xEF, 0x12, 0x00, 0x0C, 0x00, 0x0C, - 0x00, 0x84, 0x21, 0x15, 0x00, 0x48, 0x00, 0x00, - 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x04, 0xB2, 0x3A, 0x0B, 0x88, 0x01, - 0xB4, 0x01, 0x20, 0x91, 0x04, 0x07, 0x02, 0x24, - 0x20, 0xE2, 0x15, 0x0D, 0x10, 0x0F, 0x10, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, - 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, - 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, 0x18, 0x18, - 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x04, 0xEC, 0x3A, 0x0B, 0x1C, 0x1C, - 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D, 0x1D, - 0x1E, 0x1D, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1F, 0x1F, 0x20, - 0x20, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x20, 0x21, - 0x20, 0x21, 0x20, 0x20, 0x20, 0x21, 0x20, 0x21, - 0x20, 0x21, 0x21, 0x21, 0x21, 0x21, 0x22, 0x21, - 0x21, 0x22, 0x21, 0x22, 0x21, 0x22, 0x22, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x05, 0x26, 0x3A, 0x0B, 0x22, 0x22, - 0x22, 0x21, 0x22, 0x22, 0x22, 0x21, 0x22, 0x22, - 0x22, 0x21, 0x22, 0x21, 0x22, 0x21, 0x21, 0x21, - 0x22, 0x21, 0x21, 0x21, 0x21, 0x22, 0x22, 0x21, - 0x22, 0x22, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x20, 0x20, 0x21, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x05, 0x60, 0x3A, 0x0B, 0x1F, 0x1F, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, - 0x1F, 0x1F, 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, - 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, - 0x1E, 0x1E, 0x1E, 0x1E, 0x1D, 0x1D, 0x1D, 0x1D, - 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1C, 0x1D, 0x1D, - 0x1D, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, - 0x1B, 0x1B, 0x1C, 0x1C, 0x1B, 0x1B, 0x1B, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x05, 0x9A, 0x3A, 0x0B, 0x1B, 0x1B, - 0x1B, 0x1A, 0x1B, 0x1B, 0x1A, 0x1A, 0x1A, 0x1B, - 0x1B, 0x1B, 0x1B, 0x1A, 0x19, 0x1A, 0x1A, 0x1A, - 0x1A, 0x19, 0x1A, 0x1A, 0x1A, 0x19, 0x19, 0x19, - 0x19, 0x19, 0x19, 0x18, 0x19, 0x18, 0x18, 0x19, - 0x18, 0x17, 0x18, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x17, 0x17, 0x17, 0x16, 0x17, 0x16, 0x16, 0x15, - 0x15, 0x16, 0x15, 0x16, 0x15, 0x15, 0x14, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x05, 0xD4, 0x2C, 0x0B, 0x14, 0x15, - 0x14, 0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x6E, 0x12, 0x00, 0x2B, 0xC5, 0xA9, 0x00, - 0x64, 0x00, 0x00, 0x00, 0x7C, 0xEF, 0x12, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x01, 0x68, 0x0A, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xD0, 0xFD, 0x7F, 0xDC, 0x6D, 0x12, 0x00, - 0x2A, 0x26, 0x80, 0x7C, 0x98, 0x6D, 0x12, 0x00, - 0x00, 0x26, 0x80, 0x7C, 0xB8, 0x00, 0x00, 0x00, - 0x0C, 0x80, 0x01, 0x10, 0x90, 0x3E, 0x94, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x03, 0xB4, 0x3A, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1E, 0x1E, - 0x1E, 0x1F, 0x1F, 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, - 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, - 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, 0x1D, 0x1D, 0x1D, - 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1C, 0x1D, - 0x1D, 0x1D, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x03, 0xEE, 0x06, 0x0B, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x85, 0xB7, 0xA9, 0x00, - 0xB8, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, - 0x18, 0x70, 0x12, 0x00, 0x2B, 0xC5, 0xA9, 0x00, - 0x64, 0x00, 0x00, 0x00, 0xD4, 0xF0, 0x12, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x07, 0x00, 0x20, 0x00, 0x3a, 0x32, 0x2b, 0x07, - 0x2e, 0x29, 0x07, 0x2b, 0x27, 0x07, 0x27, 0x25, - 0x07, 0x23, 0x23, 0x07, 0x20, 0x21, 0x07, 0x1c, - 0x1d, 0x07, 0x19, 0x1a, 0x07, 0x15, 0x17, 0x07, - 0x12, 0x15, 0x07, 0x0e, 0x14, 0x07, 0x12, 0x17, - 0x07, 0x15, 0x19, 0x07, 0x19, 0x1c, 0x07, 0x1c, - 0x1f, 0x07, 0x20, 0x23, 0x07, 0x23, 0x25, 0x07, - 0x27, 0x27, 0x07, 0x2b, 0x29, 0x07, 0x2e, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x07, 0x00, 0x20, 0x3a, 0x26, 0x2b, 0x07, 0x32, - 0x2d, 0x07, 0x32, 0x2f, 0x07, 0x2e, 0x2d, 0x07, - 0x2b, 0x2b, 0x07, 0x27, 0x29, 0x07, 0x23, 0x27, - 0x07, 0x20, 0x25, 0x07, 0x1c, 0x22, 0x07, 0x19, - 0x1e, 0x07, 0x15, 0x1b, 0x07, 0x12, 0x19, 0x07, - 0x0e, 0x16, 0x07, 0x07, 0x19, 0x1c, 0x07, 0x1c, - 0x1f, 0x07, 0x20, 0x23, 0x07, 0x23, 0x25, 0x07, - 0x27, 0x27, 0x07, 0x2b, 0x29, 0x07, 0x2e, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x06, 0x0e, 0x81, 0x0e, - 0x81, 0x09, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x26, 0x00, 0x00, 0x00, 0x07, 0x00, 0x20, 0x3a, - 0x26, 0x2b, 0x07, 0x32, 0x2d, 0x07, 0x32, 0x2f, - 0x07, 0x2e, 0x2d, 0x07, 0x2b, 0x2b, 0x07, 0x27, - 0x29, 0x07, 0x23, 0x27, 0x07, 0x20, 0x25, 0x07, - 0x1c, 0x22, 0x07, 0x19, 0x1e, 0x07, 0x15, 0x1b, - 0x07, 0x12, 0x19, 0x07, 0x0e, 0x16, 0x07, 0x07, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, - 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x85, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x20, 0x3a, 0x26, 0x2b, 0x07, 0x32, - 0x2d, 0x07, 0x32, 0x2f, 0x07, 0x2e, 0x2d, 0x07, - 0x2b, 0x2b, 0x07, 0x29, 0x07, 0x23, 0x27, 0x07, - 0x20, 0x25, 0x07, 0x1c, 0x22, 0x07, 0x19, 0x1e, - 0x07, 0x15, 0x1b, 0x07, 0x12, 0x19, 0x07, 0x1f, - 0x0e, 0x16, 0x07, 0x07, 0x19, 0x1c, 0x07, 0x1c, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0x0d, 0x62, 0x62, - 0x51, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x3a, 0x41, 0x0e, 0x2b, 0x00, 0x00, 0x00, 0x00, - 0x78, 0xf1, 0x12, 0x00, 0x1a, 0xaa, 0xa7, 0x1f, - 0x00, 0x3a, 0x09, 0x00, 0x00, 0x00, 0x12, 0x41, - 0x0e, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x4c, 0xf1, 0x12, 0x00, 0x89, 0xae, - 0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0x20, 0x6C, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x20, 0x3A, 0x26, 0x2B, 0x07, 0x32, - 0x2D, 0x07, 0x32, 0x2F, 0x07, 0x2E, 0x2D, 0x07, - 0x2B, 0x2B, 0x07, 0x27, 0x29, 0x07, 0x23, 0x27, - 0x07, 0x20, 0x25, 0x07, 0x1C, 0x22, 0x07, 0x19, - 0x1E, 0x07, 0x15, 0x1B, 0x07, 0x12, 0x19, 0x07, - 0x0E, 0x16, 0x07, 0x07, 0x19, 0x1C, 0x07, 0x1C, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xF9, 0x6C, 0x6C, - 0x6C, 0x6C, 0x40, 0x40, 0x2E, 0x6D, 0x64, 0xED, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x4C, 0xF1, 0x12, 0x00, 0x89, 0xAE, 0xA9, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xE8, 0x3D, 0xAC, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x68, 0xF1, 0x12, 0x00, - 0x14, 0xAB, 0xA7, 0x00, 0x03, 0x00, 0x00, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0xF9, 0x00, 0x00, - 0x26, 0x00, 0x00, 0x00, 0x07, 0x00, 0x20, 0x3A, - 0x26, 0x2B, 0x07, 0x32, 0x2D, 0x07, 0x32, 0x2F, - 0x07, 0x2E, 0x2D, 0x07, 0x2B, 0x2B, 0x07, 0x27, - 0x29, 0x07, 0x23, 0x27, 0x07, 0x20, 0x25, 0x07, - 0x1C, 0x22, 0x07, 0x19, 0x1E, 0x07, 0x15, 0x1B, - 0x07, 0x12, 0x19, 0x07, 0x0E, 0x16, 0x07, 0x07, - 0x19, 0x1C, 0x07, 0x1C, 0xBA, 0xEC, 0x64, 0xED, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x16, 0x1C, 0x13, 0x1B, - 0x0B, 0x1A, 0x0A, 0x30, 0x08, 0x09, 0x6D, 0x08, - 0xA7, 0x00, 0x9E, 0x00, 0x1E, 0x0C, 0x08, 0x1D, - 0x04, 0x23, 0x42, 0x2F, 0x07, 0x2E, 0x2D, 0x07, - 0x2B, 0x2B, 0x07, 0x27, 0x29, 0x07, 0x23, 0x27, - 0x07, 0x20, 0x25, 0x07, 0x1C, 0x22, 0x07, 0x19, - 0x1E, 0x07, 0x15, 0x1B, 0x07, 0x12, 0x19, 0x07, - 0x0E, 0x16, 0x07, 0x07, 0x19, 0x1C, 0x07, 0x1C, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x01, 0x02, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, - 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, - 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3A, 0x3D, 0x3F, 0xFF, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0x0D, 0xFF, 0x30, - 0x08, 0x09, 0x6D, 0x08, 0xA7, 0x00, 0x9E, 0x00, - 0x1E, 0x0C, 0x08, 0x1D, 0x04, 0x23, 0x42, 0x2F, - 0x07, 0x2E, 0x2D, 0x07, 0x2B, 0x2B, 0x07, 0x27, - 0x29, 0x07, 0x23, 0x27, 0x07, 0x20, 0x25, 0x07, - 0x1C, 0x22, 0x07, 0x19, 0x1E, 0x07, 0x15, 0x1B, - 0x07, 0x12, 0x19, 0x07, 0x0E, 0x16, 0x07, 0x07, - 0x19, 0x1C, 0x07, 0x1C, 0xBA, 0xEC, 0x64, 0xED, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xF7, 0x64, 0xED, - 0x00, 0x00, 0x00, 0x00, 0x7C, 0xF1, 0x12, 0x00, - 0x1A, 0xAA, 0xA7, 0x00, 0x3A, 0x00, 0x00, 0x00, - 0x2A, 0x6D, 0x64, 0xED, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x50, 0xF1, 0x12, 0x00, - 0x89, 0xAE, 0xA9, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xE8, 0x3D, 0xAC, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xF7, 0xA9, 0x00, - 0x02, 0xFA, 0x3F, 0x05, 0x05, 0xC2, 0x85, 0xA6, - 0xA7, 0x6D, 0x10, 0x10, 0x08, 0xFF, 0x85, 0x6C, - 0x00, 0x00, 0xCF, 0x00, 0x01, 0x00, 0x00, 0x1F, - 0x01, 0x01, 0x0A, 0x0B, 0x13, 0x04, 0x6C, 0x6C, - 0x6C, 0x6C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x42, 0x6C, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x40, 0x42, 0x42, 0x42, 0x42, 0x42, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0xF7, 0xF3, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x02, 0x0D, 0xFF, 0x30, - 0x08, 0x09, 0x6D, 0x08, 0xA7, 0x00, 0x9E, 0x00, - 0x1E, 0x0C, 0x08, 0x1D, 0x04, 0x23, 0x42, 0x2F, - 0x07, 0x2E, 0x2D, 0x07, 0x2B, 0x2B, 0x07, 0x27, - 0x29, 0x07, 0x23, 0x27, 0x07, 0x20, 0x25, 0x07, - 0x1C, 0x22, 0x07, 0x19, 0x1E, 0x07, 0x15, 0x1B, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xE8, 0x3D, 0xAC, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5C, 0xF1, 0x12, 0x00, 0x14, 0xAB, 0xA7, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x5C, 0xF1, 0x12, 0x00, - 0x20, 0xAB, 0xA7, 0x00, 0x58, 0xF1, 0x12, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x99, 0xA9, 0xA7, 0x00, - 0xE8, 0x3D, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0xF0, 0x8F, 0x2F, - 0x07, 0x2E, 0x2D, 0x07, 0x2B, 0x2B, 0x07, 0x27, - 0x29, 0x07, 0x23, 0x27, 0x07, 0x20, 0x25, 0x07, - 0x1C, 0x22, 0x07, 0x19, 0x1E, 0x07, 0x15, 0x1B, - 0x07, 0x12, 0x19, 0x07, 0x82, 0xEC, 0x64, 0xED, - 0x24, 0xF1, 0x12, 0x00, 0xFA, 0xCB, 0xA9, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEA, 0x3D, 0xAC, 0x00, 0xBD, 0xCC, 0xA9, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x08, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0xCF, - 0x00, 0x01, 0x00, 0x00, 0x1F, 0x01, 0x01, 0x00, - 0x0C, 0xCF, 0xA9, 0x00, 0x74, 0x70, 0x12, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x1C, 0xCF, 0xA9, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x02, 0xF0, 0x8F, 0x2F, - 0x07, 0x2E, 0x2D, 0x07, 0x2B, 0x2B, 0x07, 0x27, - 0x29, 0x07, 0x23, 0x27, 0x07, 0x20, 0x25, 0x07, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x06, 0x0E, 0x85, 0x09, - 0xED, 0x09, 0x6D, 0x2F, 0x07, 0x2E, 0x2D, 0x07, - 0x2B, 0x2B, 0x07, 0x27, 0x29, 0x07, 0x23, 0x27, - 0x07, 0x20, 0x25, 0x07, 0x1C, 0x22, 0x07, 0x19, - 0x8A, 0xEC, 0x64, 0xED, 0x1C, 0xF1, 0x12, 0x00, - 0xFA, 0xCB, 0xA9, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x72, 0xF1, 0x12, 0x00, - 0xBD, 0xCC, 0xA9, 0x00, 0x0A, 0x00, 0x00, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x01, 0x02, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, - 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, - 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3A, 0x3D, 0x3F, 0xFF, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0x09, 0xED, 0x2F, - 0x07, 0x2E, 0x2D, 0x07, 0x2B, 0x2B, 0x07, 0x27, - 0x29, 0x07, 0x23, 0x27, 0x07, 0x20, 0x25, 0x07, - 0x1C, 0x22, 0x07, 0x19, 0x8A, 0xEC, 0x64, 0xED, - 0x1C, 0xF1, 0x12, 0x00, 0xFA, 0xCB, 0xA9, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x72, 0xF1, 0x12, 0x00, 0xBD, 0xCC, 0xA9, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0xBD, 0xCC, 0xA9, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xF3, 0x00, 0x00, - 0x8C, 0xF1, 0x12, 0x00, 0x1A, 0xAA, 0xA7, 0x00, - 0x3A, 0x00, 0x00, 0x00, 0x5A, 0x6D, 0x64, 0xED, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x60, 0xF1, 0x12, 0x00, 0x89, 0xAE, 0xA9, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xE8, 0x3D, 0xAC, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7C, 0xF1, 0x12, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x84, 0x00, 0x00, 0x00, 0x32, 0x02, 0xE0, 0xAD, - 0x00, 0xFC, 0xDF, 0xAD, 0x00, 0xDB, 0xDF, 0xAD, - 0x00, 0xBA, 0xDF, 0xAD, 0x00, 0x99, 0xDF, 0x6F, - 0x44, 0xC2, 0xE8, 0x20, 0x65, 0x73, 0x83, 0xAC, - 0xD7, 0x88, 0x6D, 0x59, 0x61, 0xE0, 0x3B, 0x3D, - 0xB7, 0xF4, 0xDE, 0xAD, 0x00, 0xD3, 0xDE, 0xAD, - 0x00, 0xB2, 0xDE, 0xAD, 0x00, 0x91, 0xDE, 0x00, - 0xA6, 0xEC, 0x64, 0xED, 0xA2, 0xEC, 0x64, 0xED, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x06, 0x1A, 0x0A, 0x1B, - 0x0B, 0x1C, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x92, 0xD5, 0x90, 0x7C, 0xBB, 0x9B, 0x80, 0x7C, - 0xB8, 0x00, 0x00, 0x00, 0xAC, 0x70, 0x12, 0x00, - 0x85, 0xB7, 0xA9, 0x00, 0xB8, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x08, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0xCF, - 0x00, 0x01, 0x00, 0x00, 0x1F, 0x01, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, - 0x4C, 0x70, 0x12, 0x00, 0xEB, 0xC4, 0xA9, 0x00, - 0x64, 0x00, 0x00, 0x00, 0x68, 0x70, 0x12, 0x00, - 0x40, 0x00, 0x00, 0x00, 0xE8, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xB0, 0x70, 0x12, 0x00, - 0x0C, 0xCF, 0xA9, 0x00, 0x68, 0x70, 0x12, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0x0D, 0x00, 0x00, - 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1F, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, - 0xD0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0xA6, 0xB5, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x94, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x28, 0x6F, 0x44, 0xC2, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x04, 0x78, 0x3A, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xD0, 0xFD, 0x7F, 0x94, 0xF0, 0x12, - 0x00, 0x2A, 0x26, 0x80, 0x7C, 0x50, 0xF0, 0x12, - 0x00, 0x00, 0x26, 0x80, 0x7C, 0x08, 0x00, 0x00, - 0x00, 0x0C, 0x80, 0x01, 0x10, 0x90, 0x3E, 0x94, - 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x00, 0x80, 0x69, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x04, 0xB2, 0x3A, 0x0B, 0x88, 0x01, - 0xB4, 0x01, 0x20, 0x91, 0x04, 0x07, 0x02, 0x24, - 0x20, 0xE2, 0x15, 0x0D, 0x10, 0x0F, 0x10, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, - 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, - 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, 0x18, 0x18, - 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x1A, 0x1A, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x04, 0xEC, 0x3A, 0x0B, 0x1C, 0x1C, - 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D, 0x1D, - 0x1E, 0x1D, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1F, 0x1F, 0x20, - 0x20, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x20, 0x21, - 0x20, 0x21, 0x20, 0x20, 0x20, 0x21, 0x20, 0x21, - 0x20, 0x21, 0x21, 0x21, 0x21, 0x21, 0x22, 0x21, - 0x21, 0x22, 0x21, 0x22, 0x21, 0x22, 0x22, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x05, 0x26, 0x3A, 0x0B, 0x22, 0x22, - 0x22, 0x21, 0x22, 0x22, 0x22, 0x21, 0x22, 0x22, - 0x22, 0x21, 0x22, 0x21, 0x22, 0x21, 0x21, 0x21, - 0x22, 0x21, 0x21, 0x21, 0x21, 0x22, 0x22, 0x21, - 0x22, 0x22, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x20, 0x20, 0x21, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x05, 0x60, 0x3A, 0x0B, 0x1F, 0x1F, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, - 0x1F, 0x1F, 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, - 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, - 0x1E, 0x1E, 0x1E, 0x1E, 0x1D, 0x1D, 0x1D, 0x1D, - 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1C, 0x1D, 0x1D, - 0x1D, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, - 0x1B, 0x1B, 0x1C, 0x1C, 0x1B, 0x1B, 0x1B, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x05, 0x9A, 0x3A, 0x0B, 0x1B, 0x1B, - 0x1B, 0x1A, 0x1B, 0x1B, 0x1A, 0x1A, 0x1A, 0x1B, - 0x1B, 0x1B, 0x1B, 0x1A, 0x19, 0x1A, 0x1A, 0x1A, - 0x1A, 0x19, 0x1A, 0x1A, 0x1A, 0x19, 0x19, 0x19, - 0x19, 0x19, 0x19, 0x18, 0x19, 0x18, 0x18, 0x19, - 0x18, 0x17, 0x18, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x17, 0x17, 0x17, 0x16, 0x17, 0x16, 0x16, 0x15, - 0x15, 0x16, 0x15, 0x16, 0x15, 0x15, 0x14, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x05, 0xD4, 0x2C, 0x0B, 0x14, 0x15, - 0x14, 0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x6F, 0x12, 0x00, 0x2B, 0xC5, 0xA9, 0x00, - 0x64, 0x00, 0x00, 0x00, 0x2C, 0xF0, 0x12, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xF7, 0x1C, 0x1C, - 0x1B, 0x1B, 0x1C, 0x1C, 0x1B, 0x1B, 0x1B, 0x1B, - 0x1B, 0x1B, 0x1B, 0x1A, 0x1B, 0x1B, 0x1A, 0x1A, - 0x1A, 0x1B, 0x1B, 0x1B, 0x1B, 0x1A, 0x19, 0x1A, - 0x1A, 0x1A, 0x1A, 0x19, 0x1A, 0x1A, 0x1A, 0x19, - 0x19, 0x19, 0x19, 0x19, 0x19, 0x18, 0x19, 0x18, - 0x18, 0x19, 0x18, 0x17, 0x18, 0x17, 0x17, 0x17, - 0x17, 0x17, 0x17, 0x17, 0x17, 0x16, 0x17, 0x16, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0xF7, 0xF3, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x04, 0x3D, 0x40, 0x0A, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x52, 0xED, 0x64, 0xED, - 0xD4, 0xF1, 0x12, 0x00, 0xFA, 0xCB, 0xA9, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x01, 0x02, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, - 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, - 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3A, 0x3D, 0x3F, 0xFF, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0x0A, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x52, 0xED, 0x64, 0xED, 0xD4, 0xF1, 0x12, 0x00, - 0xFA, 0xCB, 0xA9, 0x00, 0x03, 0x00, 0x00, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x8B, 0x00, 0x00, 0xA8, 0x3A, 0x00, 0x00, 0x00, - 0x00, 0xDC, 0x00, 0xEA, 0x00, 0x20, 0xED, 0x12, - 0x00, 0x0C, 0x00, 0x0E, 0x00, 0x00, 0xDC, 0xFD, - 0x7F, 0x20, 0xED, 0x12, 0x00, 0x05, 0x00, 0x00, - 0x00, 0xA0, 0x20, 0x15, 0x00, 0xC8, 0x00, 0x00, - 0x01, 0x43, 0x00, 0x3A, 0x00, 0x5C, 0x00, 0x44, - 0x00, 0x6F, 0x00, 0x63, 0x00, 0x75, 0x00, 0x6D, - 0x00, 0x65, 0x00, 0x6E, 0x00, 0x74, 0x00, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x00, 0xE2, 0x3A, 0x0B, 0x07, 0xA5, - 0x03, 0x2F, 0x63, 0x97, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x01, 0x1C, 0x3A, 0x0B, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x12, 0x75, 0xB3, 0x05, - 0xE2, 0xBC, 0x74, 0x68, 0xAD, 0xAC, 0x7B, 0xB1, - 0xF8, 0x52, 0xD5, 0x8F, 0xF7, 0x03, 0x00, 0x00, - 0x06, 0xA5, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x01, 0x56, 0x3A, 0x0B, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x01, 0x90, 0x3A, 0x0B, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x06, 0xA5, 0x00, 0x22, 0x8E, 0xA3, 0x00, 0x00, - 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x4C, 0xA5, 0xC8, 0xC8, 0x41, 0x50, 0x52, 0x39, - 0x07, 0x01, 0x00, 0x5F, 0x00, 0x00, 0xFF, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x01, 0xCA, 0x3A, 0x0B, 0x01, 0x48, - 0x34, 0x33, 0x00, 0x00, 0x00, 0x00, 0x76, 0x3E, - 0x84, 0x10, 0x2E, 0x48, 0x54, 0x0D, 0x98, 0x4C, - 0x14, 0x12, 0x72, 0x7A, 0x88, 0x0F, 0x9F, 0x84, - 0x98, 0x03, 0x52, 0xA6, 0xA4, 0x0A, 0x6E, 0xA8, - 0x54, 0x0C, 0x13, 0xB6, 0xE8, 0x0A, 0x77, 0xC0, - 0x94, 0x04, 0x73, 0xC6, 0x14, 0x07, 0x80, 0xCA, - 0xA8, 0x08, 0x31, 0xD2, 0x44, 0x09, 0x1E, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x02, 0x04, 0x3A, 0x0B, 0x74, 0x09, - 0x7A, 0xE4, 0x78, 0x17, 0xA5, 0xE4, 0x24, 0x09, - 0x45, 0xE8, 0x68, 0x07, 0xBA, 0xEC, 0xE8, 0x05, - 0xC2, 0xF0, 0x58, 0x16, 0x78, 0xF6, 0x98, 0x15, - 0x7C, 0xFC, 0xB8, 0x19, 0xAD, 0xFC, 0x74, 0x09, - 0x8C, 0x02, 0x39, 0x0D, 0x36, 0x06, 0x99, 0x06, - 0x9B, 0x08, 0x09, 0x0B, 0xA1, 0x0C, 0x25, 0x19, - 0x57, 0x10, 0x29, 0x05, 0x1A, 0x1C, 0x45, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x02, 0x3E, 0x3A, 0x0B, 0x55, 0x1E, - 0x69, 0x16, 0xA4, 0x24, 0xB9, 0x09, 0x1C, 0x44, - 0x55, 0x08, 0x9C, 0x44, 0xC9, 0x0B, 0x9F, 0x4A, - 0xF9, 0x19, 0x4C, 0x4C, 0xF9, 0x13, 0x5E, 0x50, - 0x09, 0x13, 0xB7, 0x6A, 0x09, 0x0A, 0x7C, 0x7A, - 0x75, 0x0F, 0x0E, 0x7E, 0x95, 0x00, 0x81, 0xA6, - 0x99, 0x0E, 0xC0, 0xAE, 0xE5, 0x19, 0xA0, 0xCC, - 0x35, 0x0D, 0x63, 0xE2, 0x85, 0x1F, 0x8E, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x02, 0x78, 0x3A, 0x0B, 0x35, 0x1D, - 0xC1, 0xE8, 0xA9, 0x0C, 0x7A, 0x06, 0xCA, 0x0E, - 0xAD, 0x12, 0xD6, 0x1C, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x02, 0xB2, 0x2A, 0x0B, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x6C, 0x12, 0x00, 0x2B, 0xC5, 0xA9, 0x00, - 0x64, 0x00, 0x00, 0x00, 0xFC, 0xEC, 0x12, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xF1, 0x42, 0x42, - 0x40, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xCE, 0x6D, 0x64, 0xED, 0x00, 0x00, 0x00, 0x00, - 0x30, 0xF2, 0x12, 0x00, 0x1A, 0xAA, 0xA7, 0x00, - 0x3A, 0x00, 0x00, 0x00, 0xF6, 0x6D, 0x64, 0xED, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0xF2, 0x12, 0x00, 0x89, 0xAE, 0xA9, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0xF1, 0x01, 0x00, - 0x1C, 0xCF, 0xA9, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x02, 0x0A, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x8B, 0x00, 0x00, 0xFC, 0x3A, 0x1E, 0xDC, 0x74, - 0x09, 0x7A, 0xE4, 0x78, 0x17, 0xA5, 0xE4, 0x24, - 0x09, 0x45, 0xE8, 0x68, 0x07, 0xBA, 0xEC, 0xE8, - 0x05, 0xC2, 0xF0, 0x58, 0x16, 0x78, 0xF6, 0x98, - 0x15, 0x7C, 0xFC, 0xB8, 0x19, 0xAD, 0xFC, 0x74, - 0x09, 0x8C, 0x02, 0x39, 0x0D, 0x36, 0x06, 0x99, - 0x06, 0x9B, 0x08, 0x09, 0x0B, 0xA1, 0x0C, 0x25, - 0x19, 0x57, 0x10, 0x29, 0x05, 0x1A, 0x1C, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x8B, 0x00, 0x01, 0x36, 0x2E, 0x0B, 0x06, 0xA5, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2B, 0xC5, 0xA9, 0x00, - 0x64, 0x00, 0x00, 0x00, 0xD8, 0xEE, 0x12, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xF0, 0xAC, 0x00, - 0xF0, 0xF1, 0x12, 0x00, 0x6A, 0xB1, 0xA7, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0xA5, 0x00, 0x01, - 0x00, 0x00, 0x12, 0x00, 0x14, 0xAB, 0xA7, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x0C, 0xF2, 0x12, 0x00, - 0x20, 0xAB, 0xA7, 0x00, 0x08, 0xF2, 0x12, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x99, 0xA9, 0xA7, 0x00, - 0xE8, 0x3D, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0xF0, 0x8F, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x52, 0xED, 0x64, 0xED, - 0xD4, 0xF1, 0x12, 0x00, 0xFA, 0xCB, 0xA9, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEA, 0x3D, 0xAC, 0x00, 0xBD, 0xCC, 0xA9, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xF7, 0x12, 0x00, - 0x88, 0xC4, 0xA9, 0x00, 0xD8, 0xF1, 0x12, 0x00, - 0x40, 0x00, 0x00, 0x00, 0xBB, 0xC4, 0xA9, 0x00, - 0x02, 0x00, 0x3F, 0x05, 0x0B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEA, 0x6D, 0x64, 0xED, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0xF2, 0x12, 0x00, - 0x89, 0xAE, 0xA9, 0x00, 0x03, 0x00, 0x00, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xF7, 0xA9, 0x00, - 0x02, 0xFA, 0x3F, 0x05, 0x0B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0xF7, 0xF3, 0x00, - 0x0C, 0xCF, 0xA9, 0x00, 0x24, 0x71, 0x12, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x1C, 0xCF, 0xA9, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x02, 0xF0, 0x8F, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x01, 0xFB, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF1, 0x12, 0x00, - 0x89, 0xAE, 0xA9, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xE8, 0x3D, 0xAC, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0C, 0xF2, 0x12, 0x00, 0x14, 0xAB, 0xA7, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x0C, 0xF2, 0x12, 0x00, - 0x20, 0xAB, 0xA7, 0x00, 0x08, 0xF2, 0x12, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0xFB, 0x0F, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x02, 0xF0, 0x8F, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x52, 0xED, 0x64, 0xED, - 0xD4, 0xF1, 0x12, 0x00, 0xFA, 0xCB, 0xA9, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x01, 0x02, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, - 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, - 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3A, 0x3D, 0x3F, 0xFF, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0x07, 0xA4, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x52, 0xED, 0x64, 0xED, - 0xD4, 0xF1, 0x12, 0x00, 0xFA, 0xCB, 0xA9, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x42, 0xED, 0x64, 0xED, - 0xE4, 0xF1, 0x12, 0x00, 0xFA, 0xCB, 0xA9, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x08, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0xCF, - 0x00, 0x01, 0x00, 0x00, 0x1F, 0x01, 0x01, 0x00, - 0xEB, 0xC4, 0xA9, 0x00, 0x64, 0x00, 0x00, 0x00, - 0x24, 0x71, 0x12, 0x00, 0x40, 0x00, 0x00, 0x00, - 0xE8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x6C, 0x71, 0x12, 0x00, 0x0C, 0xCF, 0xA9, 0x00, - 0x24, 0x71, 0x12, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x1C, 0xCF, 0xA9, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x01, 0x02, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, - 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, - 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3A, 0x3D, 0x3F, 0xFF, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x01, 0x02, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, - 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, - 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3A, 0x3D, 0x3F, 0xFF, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x21, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x36, 0xED, 0x64, 0xED, - 0xB0, 0xF1, 0x12, 0x00, 0xFA, 0xCB, 0xA9, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x06, 0xF2, 0x12, 0x00, 0xBD, 0xCC, 0xA9, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x52, 0xED, 0x64, 0xED, 0xFC, 0xF1, 0x12, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x06, 0xF2, 0x12, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x01, 0x02, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, - 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, - 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3A, 0x3D, 0x3F, 0xFF, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x01, 0x02, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, - 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, - 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3A, 0x3D, 0x3F, 0xFF, 0x00, - }, - .response_len = 0x40 - }, - { - .cmd = { - 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x36, 0xED, 0x64, 0xED, - 0xB0, 0xF1, 0x12, 0x00, 0xFA, 0xCB, 0xA9, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x06, 0xF2, 0x12, 0x00, 0xBD, 0xCC, 0xA9, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x52, 0xED, 0x64, 0xED, 0xFC, 0xF1, 0x12, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x06, 0xF2, 0x12, 0x00, - }, - .response_len = 0x00 - }, - { - .cmd = { - 0x82, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x01, 0x02, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, - 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, - 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3A, 0x3D, 0x3F, 0xFF, 0x00, - }, - .response_len = 0x40 - }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xF3, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0xfe, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xb8, 0x00, 0x00, 0x00, 0x98, 0xf1, 0x12, 0x00, + 0x03, 0xd4, 0xa9, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x14, 0x20, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x84, 0xf1, 0x12, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x90, 0xf1, 0x12, 0x00, + 0xac, 0x0d, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xf7, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x90, 0xf1, 0x12, 0x00, + 0x92, 0xc5, 0xa9, 0x00, 0x48, 0xf1, 0x12, 0x00, + 0x40, 0x00, 0x00, 0x00, 0xa2, 0xc5, 0xa9, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x02, 0xfe, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xb8, 0x00, 0x00, 0x00, 0x98, 0xf1, 0x12, 0x00, + 0x03, 0xd4, 0xa9, 0x00, 0x64, 0x00, 0x00, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0xf7, 0xcd, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xf8, 0xa9, 0x00, + 0x28, 0xf1, 0x12, 0x00, 0x40, 0x00, 0x00, 0x00, + 0xbb, 0xc4, 0xa9, 0x00, 0x02, 0xfa, 0x3f, 0x05, + 0x05, 0x02, 0x05, 0x23, 0x27, 0xe5, 0x13, 0x10, + 0x08, 0xff, 0x04, 0x6c, 0xc1, 0x41, 0x1c, 0x4c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x60, 0xf1, 0x12, 0x00, 0x89, 0xae, 0xa9, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8b, 0x00, 0x00, 0x00, 0x3a, 0x8c, 0xf1, 0x12, + 0x00, 0x64, 0xa8, 0xa7, 0x00, 0x84, 0xf1, 0x12, + 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf1, 0x12, + 0x00, 0x51, 0xa6, 0xa7, 0x00, 0xf8, 0x00, 0x00, + 0x00, 0x7e, 0xa6, 0xa7, 0x00, 0x24, 0x5a, 0xac, + 0x00, 0x01, 0xf1, 0x12, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x2f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, + 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x7c, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, + 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0x0d, 0xff, 0x00, + 0x34, 0xf1, 0x12, 0x00, 0x40, 0x00, 0x00, 0x00, + 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf1, 0x12, 0x00, 0x57, 0xcc, 0xa9, 0x00, + 0x34, 0xf1, 0x12, 0x00, 0x40, 0x00, 0x00, 0x00, + 0xbd, 0xcc, 0xa9, 0x00, 0x3a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, + 0x34, 0xf1, 0x12, 0x00, 0x3a, 0x00, 0x00, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x0a, 0x37, 0x6a, 0x3d, + 0x73, 0x3d, 0x71, 0x0e, 0x01, 0x0e, 0x81, 0x00, + 0x40, 0x00, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x12, 0x00, + 0x57, 0xcc, 0xa9, 0x00, 0x34, 0xf1, 0x12, 0x00, + 0x40, 0x00, 0x00, 0x00, 0xbd, 0xcc, 0xa9, 0x00, + 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xb8, 0x00, 0x00, 0x00, 0x34, 0xf1, 0x12, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, + 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0x3d, 0x51, 0x0e, + 0x01, 0x0e, 0x81, 0x00, 0x40, 0x00, 0x00, 0x00, + 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf1, 0x12, 0x00, 0x57, 0xcc, 0xa9, 0x00, + 0x34, 0xf1, 0x12, 0x00, 0x40, 0x00, 0x00, 0x00, + 0xbd, 0xcc, 0xa9, 0x00, 0x3a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, + 0x34, 0xf1, 0x12, 0x00, 0x3a, 0x00, 0x00, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, + 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x04, 0x78, 0x3A, 0x34, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0x00, 0x24, 0x1A, 0x80, + 0x7C, 0x04, 0xF1, 0x12, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x48, 0x00, 0x00, 0x00, 0xCC, 0xEF, 0x12, + 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xB0, 0xEF, 0x12, 0x00, 0x0C, 0x00, 0x0C, + 0x00, 0x84, 0x21, 0x15, 0x00, 0x48, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x04, 0xB2, 0x3A, 0x0B, 0x88, 0x01, + 0xB4, 0x01, 0x20, 0x91, 0x04, 0x07, 0x02, 0x24, + 0x20, 0xE2, 0x15, 0x0D, 0x10, 0x0F, 0x10, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, + 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, + 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, 0x18, 0x18, + 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x1A, 0x1A, + 0x1A, 0x1A, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x04, 0xEC, 0x3A, 0x0B, 0x1C, 0x1C, + 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D, 0x1D, + 0x1E, 0x1D, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1F, 0x1F, 0x20, + 0x20, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x20, 0x21, + 0x20, 0x21, 0x20, 0x20, 0x20, 0x21, 0x20, 0x21, + 0x20, 0x21, 0x21, 0x21, 0x21, 0x21, 0x22, 0x21, + 0x21, 0x22, 0x21, 0x22, 0x21, 0x22, 0x22, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x05, 0x26, 0x3A, 0x0B, 0x22, 0x22, + 0x22, 0x21, 0x22, 0x22, 0x22, 0x21, 0x22, 0x22, + 0x22, 0x21, 0x22, 0x21, 0x22, 0x21, 0x21, 0x21, + 0x22, 0x21, 0x21, 0x21, 0x21, 0x22, 0x22, 0x21, + 0x22, 0x22, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x20, 0x20, 0x21, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x05, 0x60, 0x3A, 0x0B, 0x1F, 0x1F, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, + 0x1F, 0x1F, 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, + 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, + 0x1E, 0x1E, 0x1E, 0x1E, 0x1D, 0x1D, 0x1D, 0x1D, + 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1C, 0x1D, 0x1D, + 0x1D, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, + 0x1B, 0x1B, 0x1C, 0x1C, 0x1B, 0x1B, 0x1B, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x05, 0x9A, 0x3A, 0x0B, 0x1B, 0x1B, + 0x1B, 0x1A, 0x1B, 0x1B, 0x1A, 0x1A, 0x1A, 0x1B, + 0x1B, 0x1B, 0x1B, 0x1A, 0x19, 0x1A, 0x1A, 0x1A, + 0x1A, 0x19, 0x1A, 0x1A, 0x1A, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x18, 0x19, 0x18, 0x18, 0x19, + 0x18, 0x17, 0x18, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x16, 0x17, 0x16, 0x16, 0x15, + 0x15, 0x16, 0x15, 0x16, 0x15, 0x15, 0x14, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x05, 0xD4, 0x2C, 0x0B, 0x14, 0x15, + 0x14, 0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x6E, 0x12, 0x00, 0x2B, 0xC5, 0xA9, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x7C, 0xEF, 0x12, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x01, 0x68, 0x0A, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xD0, 0xFD, 0x7F, 0xDC, 0x6D, 0x12, 0x00, + 0x2A, 0x26, 0x80, 0x7C, 0x98, 0x6D, 0x12, 0x00, + 0x00, 0x26, 0x80, 0x7C, 0xB8, 0x00, 0x00, 0x00, + 0x0C, 0x80, 0x01, 0x10, 0x90, 0x3E, 0x94, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x03, 0xB4, 0x3A, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1E, 0x1E, + 0x1E, 0x1F, 0x1F, 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, + 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, + 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, 0x1D, 0x1D, 0x1D, + 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1C, 0x1D, + 0x1D, 0x1D, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x03, 0xEE, 0x06, 0x0B, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0xB7, 0xA9, 0x00, + 0xB8, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, + 0x18, 0x70, 0x12, 0x00, 0x2B, 0xC5, 0xA9, 0x00, + 0x64, 0x00, 0x00, 0x00, 0xD4, 0xF0, 0x12, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x07, 0x00, 0x20, 0x00, 0x3a, 0x32, 0x2b, 0x07, + 0x2e, 0x29, 0x07, 0x2b, 0x27, 0x07, 0x27, 0x25, + 0x07, 0x23, 0x23, 0x07, 0x20, 0x21, 0x07, 0x1c, + 0x1d, 0x07, 0x19, 0x1a, 0x07, 0x15, 0x17, 0x07, + 0x12, 0x15, 0x07, 0x0e, 0x14, 0x07, 0x12, 0x17, + 0x07, 0x15, 0x19, 0x07, 0x19, 0x1c, 0x07, 0x1c, + 0x1f, 0x07, 0x20, 0x23, 0x07, 0x23, 0x25, 0x07, + 0x27, 0x27, 0x07, 0x2b, 0x29, 0x07, 0x2e, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x07, 0x00, 0x20, 0x3a, 0x26, 0x2b, 0x07, 0x32, + 0x2d, 0x07, 0x32, 0x2f, 0x07, 0x2e, 0x2d, 0x07, + 0x2b, 0x2b, 0x07, 0x27, 0x29, 0x07, 0x23, 0x27, + 0x07, 0x20, 0x25, 0x07, 0x1c, 0x22, 0x07, 0x19, + 0x1e, 0x07, 0x15, 0x1b, 0x07, 0x12, 0x19, 0x07, + 0x0e, 0x16, 0x07, 0x07, 0x19, 0x1c, 0x07, 0x1c, + 0x1f, 0x07, 0x20, 0x23, 0x07, 0x23, 0x25, 0x07, + 0x27, 0x27, 0x07, 0x2b, 0x29, 0x07, 0x2e, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x06, 0x0e, 0x81, 0x0e, + 0x81, 0x09, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x07, 0x00, 0x20, 0x3a, + 0x26, 0x2b, 0x07, 0x32, 0x2d, 0x07, 0x32, 0x2f, + 0x07, 0x2e, 0x2d, 0x07, 0x2b, 0x2b, 0x07, 0x27, + 0x29, 0x07, 0x23, 0x27, 0x07, 0x20, 0x25, 0x07, + 0x1c, 0x22, 0x07, 0x19, 0x1e, 0x07, 0x15, 0x1b, + 0x07, 0x12, 0x19, 0x07, 0x0e, 0x16, 0x07, 0x07, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x01, 0x02, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, + 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x3d, 0x3f, 0xff, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x85, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x20, 0x3a, 0x26, 0x2b, 0x07, 0x32, + 0x2d, 0x07, 0x32, 0x2f, 0x07, 0x2e, 0x2d, 0x07, + 0x2b, 0x2b, 0x07, 0x29, 0x07, 0x23, 0x27, 0x07, + 0x20, 0x25, 0x07, 0x1c, 0x22, 0x07, 0x19, 0x1e, + 0x07, 0x15, 0x1b, 0x07, 0x12, 0x19, 0x07, 0x1f, + 0x0e, 0x16, 0x07, 0x07, 0x19, 0x1c, 0x07, 0x1c, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0x0d, 0x62, 0x62, + 0x51, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x3a, 0x41, 0x0e, 0x2b, 0x00, 0x00, 0x00, 0x00, + 0x78, 0xf1, 0x12, 0x00, 0x1a, 0xaa, 0xa7, 0x1f, + 0x00, 0x3a, 0x09, 0x00, 0x00, 0x00, 0x12, 0x41, + 0x0e, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x4c, 0xf1, 0x12, 0x00, 0x89, 0xae, + 0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0x20, 0x6C, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x20, 0x3A, 0x26, 0x2B, 0x07, 0x32, + 0x2D, 0x07, 0x32, 0x2F, 0x07, 0x2E, 0x2D, 0x07, + 0x2B, 0x2B, 0x07, 0x27, 0x29, 0x07, 0x23, 0x27, + 0x07, 0x20, 0x25, 0x07, 0x1C, 0x22, 0x07, 0x19, + 0x1E, 0x07, 0x15, 0x1B, 0x07, 0x12, 0x19, 0x07, + 0x0E, 0x16, 0x07, 0x07, 0x19, 0x1C, 0x07, 0x1C, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xF9, 0x6C, 0x6C, + 0x6C, 0x6C, 0x40, 0x40, 0x2E, 0x6D, 0x64, 0xED, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x4C, 0xF1, 0x12, 0x00, 0x89, 0xAE, 0xA9, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE8, 0x3D, 0xAC, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x68, 0xF1, 0x12, 0x00, + 0x14, 0xAB, 0xA7, 0x00, 0x03, 0x00, 0x00, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0xF9, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x07, 0x00, 0x20, 0x3A, + 0x26, 0x2B, 0x07, 0x32, 0x2D, 0x07, 0x32, 0x2F, + 0x07, 0x2E, 0x2D, 0x07, 0x2B, 0x2B, 0x07, 0x27, + 0x29, 0x07, 0x23, 0x27, 0x07, 0x20, 0x25, 0x07, + 0x1C, 0x22, 0x07, 0x19, 0x1E, 0x07, 0x15, 0x1B, + 0x07, 0x12, 0x19, 0x07, 0x0E, 0x16, 0x07, 0x07, + 0x19, 0x1C, 0x07, 0x1C, 0xBA, 0xEC, 0x64, 0xED, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x16, 0x1C, 0x13, 0x1B, + 0x0B, 0x1A, 0x0A, 0x30, 0x08, 0x09, 0x6D, 0x08, + 0xA7, 0x00, 0x9E, 0x00, 0x1E, 0x0C, 0x08, 0x1D, + 0x04, 0x23, 0x42, 0x2F, 0x07, 0x2E, 0x2D, 0x07, + 0x2B, 0x2B, 0x07, 0x27, 0x29, 0x07, 0x23, 0x27, + 0x07, 0x20, 0x25, 0x07, 0x1C, 0x22, 0x07, 0x19, + 0x1E, 0x07, 0x15, 0x1B, 0x07, 0x12, 0x19, 0x07, + 0x0E, 0x16, 0x07, 0x07, 0x19, 0x1C, 0x07, 0x1C, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x01, 0x02, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, + 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3A, 0x3D, 0x3F, 0xFF, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0x0D, 0xFF, 0x30, + 0x08, 0x09, 0x6D, 0x08, 0xA7, 0x00, 0x9E, 0x00, + 0x1E, 0x0C, 0x08, 0x1D, 0x04, 0x23, 0x42, 0x2F, + 0x07, 0x2E, 0x2D, 0x07, 0x2B, 0x2B, 0x07, 0x27, + 0x29, 0x07, 0x23, 0x27, 0x07, 0x20, 0x25, 0x07, + 0x1C, 0x22, 0x07, 0x19, 0x1E, 0x07, 0x15, 0x1B, + 0x07, 0x12, 0x19, 0x07, 0x0E, 0x16, 0x07, 0x07, + 0x19, 0x1C, 0x07, 0x1C, 0xBA, 0xEC, 0x64, 0xED, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xF7, 0x64, 0xED, + 0x00, 0x00, 0x00, 0x00, 0x7C, 0xF1, 0x12, 0x00, + 0x1A, 0xAA, 0xA7, 0x00, 0x3A, 0x00, 0x00, 0x00, + 0x2A, 0x6D, 0x64, 0xED, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0xF1, 0x12, 0x00, + 0x89, 0xAE, 0xA9, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xE8, 0x3D, 0xAC, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xF7, 0xA9, 0x00, + 0x02, 0xFA, 0x3F, 0x05, 0x05, 0xC2, 0x85, 0xA6, + 0xA7, 0x6D, 0x10, 0x10, 0x08, 0xFF, 0x85, 0x6C, + 0x00, 0x00, 0xCF, 0x00, 0x01, 0x00, 0x00, 0x1F, + 0x01, 0x01, 0x0A, 0x0B, 0x13, 0x04, 0x6C, 0x6C, + 0x6C, 0x6C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x42, 0x6C, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x42, 0x42, 0x42, 0x42, 0x42, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0xF7, 0xF3, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x02, 0x0D, 0xFF, 0x30, + 0x08, 0x09, 0x6D, 0x08, 0xA7, 0x00, 0x9E, 0x00, + 0x1E, 0x0C, 0x08, 0x1D, 0x04, 0x23, 0x42, 0x2F, + 0x07, 0x2E, 0x2D, 0x07, 0x2B, 0x2B, 0x07, 0x27, + 0x29, 0x07, 0x23, 0x27, 0x07, 0x20, 0x25, 0x07, + 0x1C, 0x22, 0x07, 0x19, 0x1E, 0x07, 0x15, 0x1B, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xE8, 0x3D, 0xAC, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x5C, 0xF1, 0x12, 0x00, 0x14, 0xAB, 0xA7, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x5C, 0xF1, 0x12, 0x00, + 0x20, 0xAB, 0xA7, 0x00, 0x58, 0xF1, 0x12, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x99, 0xA9, 0xA7, 0x00, + 0xE8, 0x3D, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0xF0, 0x8F, 0x2F, + 0x07, 0x2E, 0x2D, 0x07, 0x2B, 0x2B, 0x07, 0x27, + 0x29, 0x07, 0x23, 0x27, 0x07, 0x20, 0x25, 0x07, + 0x1C, 0x22, 0x07, 0x19, 0x1E, 0x07, 0x15, 0x1B, + 0x07, 0x12, 0x19, 0x07, 0x82, 0xEC, 0x64, 0xED, + 0x24, 0xF1, 0x12, 0x00, 0xFA, 0xCB, 0xA9, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x3D, 0xAC, 0x00, 0xBD, 0xCC, 0xA9, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x08, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0xCF, + 0x00, 0x01, 0x00, 0x00, 0x1F, 0x01, 0x01, 0x00, + 0x0C, 0xCF, 0xA9, 0x00, 0x74, 0x70, 0x12, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x1C, 0xCF, 0xA9, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x02, 0xF0, 0x8F, 0x2F, + 0x07, 0x2E, 0x2D, 0x07, 0x2B, 0x2B, 0x07, 0x27, + 0x29, 0x07, 0x23, 0x27, 0x07, 0x20, 0x25, 0x07, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x06, 0x0E, 0x85, 0x09, + 0xED, 0x09, 0x6D, 0x2F, 0x07, 0x2E, 0x2D, 0x07, + 0x2B, 0x2B, 0x07, 0x27, 0x29, 0x07, 0x23, 0x27, + 0x07, 0x20, 0x25, 0x07, 0x1C, 0x22, 0x07, 0x19, + 0x8A, 0xEC, 0x64, 0xED, 0x1C, 0xF1, 0x12, 0x00, + 0xFA, 0xCB, 0xA9, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x72, 0xF1, 0x12, 0x00, + 0xBD, 0xCC, 0xA9, 0x00, 0x0A, 0x00, 0x00, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x01, 0x02, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, + 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3A, 0x3D, 0x3F, 0xFF, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0x09, 0xED, 0x2F, + 0x07, 0x2E, 0x2D, 0x07, 0x2B, 0x2B, 0x07, 0x27, + 0x29, 0x07, 0x23, 0x27, 0x07, 0x20, 0x25, 0x07, + 0x1C, 0x22, 0x07, 0x19, 0x8A, 0xEC, 0x64, 0xED, + 0x1C, 0xF1, 0x12, 0x00, 0xFA, 0xCB, 0xA9, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x72, 0xF1, 0x12, 0x00, 0xBD, 0xCC, 0xA9, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0xBD, 0xCC, 0xA9, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xF3, 0x00, 0x00, + 0x8C, 0xF1, 0x12, 0x00, 0x1A, 0xAA, 0xA7, 0x00, + 0x3A, 0x00, 0x00, 0x00, 0x5A, 0x6D, 0x64, 0xED, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x60, 0xF1, 0x12, 0x00, 0x89, 0xAE, 0xA9, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE8, 0x3D, 0xAC, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7C, 0xF1, 0x12, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x84, 0x00, 0x00, 0x00, 0x32, 0x02, 0xE0, 0xAD, + 0x00, 0xFC, 0xDF, 0xAD, 0x00, 0xDB, 0xDF, 0xAD, + 0x00, 0xBA, 0xDF, 0xAD, 0x00, 0x99, 0xDF, 0x6F, + 0x44, 0xC2, 0xE8, 0x20, 0x65, 0x73, 0x83, 0xAC, + 0xD7, 0x88, 0x6D, 0x59, 0x61, 0xE0, 0x3B, 0x3D, + 0xB7, 0xF4, 0xDE, 0xAD, 0x00, 0xD3, 0xDE, 0xAD, + 0x00, 0xB2, 0xDE, 0xAD, 0x00, 0x91, 0xDE, 0x00, + 0xA6, 0xEC, 0x64, 0xED, 0xA2, 0xEC, 0x64, 0xED, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x06, 0x1A, 0x0A, 0x1B, + 0x0B, 0x1C, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x92, 0xD5, 0x90, 0x7C, 0xBB, 0x9B, 0x80, 0x7C, + 0xB8, 0x00, 0x00, 0x00, 0xAC, 0x70, 0x12, 0x00, + 0x85, 0xB7, 0xA9, 0x00, 0xB8, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x08, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0xCF, + 0x00, 0x01, 0x00, 0x00, 0x1F, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, + 0x4C, 0x70, 0x12, 0x00, 0xEB, 0xC4, 0xA9, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x68, 0x70, 0x12, 0x00, + 0x40, 0x00, 0x00, 0x00, 0xE8, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xB0, 0x70, 0x12, 0x00, + 0x0C, 0xCF, 0xA9, 0x00, 0x68, 0x70, 0x12, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0x0D, 0x00, 0x00, + 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, + 0xD0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xA6, 0xB5, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x94, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0x6F, 0x44, 0xC2, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x04, 0x78, 0x3A, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xD0, 0xFD, 0x7F, 0x94, 0xF0, 0x12, + 0x00, 0x2A, 0x26, 0x80, 0x7C, 0x50, 0xF0, 0x12, + 0x00, 0x00, 0x26, 0x80, 0x7C, 0x08, 0x00, 0x00, + 0x00, 0x0C, 0x80, 0x01, 0x10, 0x90, 0x3E, 0x94, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x80, 0x69, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x04, 0xB2, 0x3A, 0x0B, 0x88, 0x01, + 0xB4, 0x01, 0x20, 0x91, 0x04, 0x07, 0x02, 0x24, + 0x20, 0xE2, 0x15, 0x0D, 0x10, 0x0F, 0x10, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, + 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, + 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, 0x18, 0x18, + 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x1A, 0x1A, + 0x1A, 0x1A, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x04, 0xEC, 0x3A, 0x0B, 0x1C, 0x1C, + 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D, 0x1D, + 0x1E, 0x1D, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1F, 0x1F, 0x20, + 0x20, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x20, 0x21, + 0x20, 0x21, 0x20, 0x20, 0x20, 0x21, 0x20, 0x21, + 0x20, 0x21, 0x21, 0x21, 0x21, 0x21, 0x22, 0x21, + 0x21, 0x22, 0x21, 0x22, 0x21, 0x22, 0x22, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x05, 0x26, 0x3A, 0x0B, 0x22, 0x22, + 0x22, 0x21, 0x22, 0x22, 0x22, 0x21, 0x22, 0x22, + 0x22, 0x21, 0x22, 0x21, 0x22, 0x21, 0x21, 0x21, + 0x22, 0x21, 0x21, 0x21, 0x21, 0x22, 0x22, 0x21, + 0x22, 0x22, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x20, 0x20, 0x21, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x05, 0x60, 0x3A, 0x0B, 0x1F, 0x1F, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, + 0x1F, 0x1F, 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, + 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, + 0x1E, 0x1E, 0x1E, 0x1E, 0x1D, 0x1D, 0x1D, 0x1D, + 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1C, 0x1D, 0x1D, + 0x1D, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, + 0x1B, 0x1B, 0x1C, 0x1C, 0x1B, 0x1B, 0x1B, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x05, 0x9A, 0x3A, 0x0B, 0x1B, 0x1B, + 0x1B, 0x1A, 0x1B, 0x1B, 0x1A, 0x1A, 0x1A, 0x1B, + 0x1B, 0x1B, 0x1B, 0x1A, 0x19, 0x1A, 0x1A, 0x1A, + 0x1A, 0x19, 0x1A, 0x1A, 0x1A, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x18, 0x19, 0x18, 0x18, 0x19, + 0x18, 0x17, 0x18, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x16, 0x17, 0x16, 0x16, 0x15, + 0x15, 0x16, 0x15, 0x16, 0x15, 0x15, 0x14, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x05, 0xD4, 0x2C, 0x0B, 0x14, 0x15, + 0x14, 0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x6F, 0x12, 0x00, 0x2B, 0xC5, 0xA9, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x2C, 0xF0, 0x12, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xF7, 0x1C, 0x1C, + 0x1B, 0x1B, 0x1C, 0x1C, 0x1B, 0x1B, 0x1B, 0x1B, + 0x1B, 0x1B, 0x1B, 0x1A, 0x1B, 0x1B, 0x1A, 0x1A, + 0x1A, 0x1B, 0x1B, 0x1B, 0x1B, 0x1A, 0x19, 0x1A, + 0x1A, 0x1A, 0x1A, 0x19, 0x1A, 0x1A, 0x1A, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x18, 0x19, 0x18, + 0x18, 0x19, 0x18, 0x17, 0x18, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x16, 0x17, 0x16, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0xF7, 0xF3, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x04, 0x3D, 0x40, 0x0A, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x52, 0xED, 0x64, 0xED, + 0xD4, 0xF1, 0x12, 0x00, 0xFA, 0xCB, 0xA9, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x01, 0x02, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, + 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3A, 0x3D, 0x3F, 0xFF, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0x0A, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x52, 0xED, 0x64, 0xED, 0xD4, 0xF1, 0x12, 0x00, + 0xFA, 0xCB, 0xA9, 0x00, 0x03, 0x00, 0x00, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x8B, 0x00, 0x00, 0xA8, 0x3A, 0x00, 0x00, 0x00, + 0x00, 0xDC, 0x00, 0xEA, 0x00, 0x20, 0xED, 0x12, + 0x00, 0x0C, 0x00, 0x0E, 0x00, 0x00, 0xDC, 0xFD, + 0x7F, 0x20, 0xED, 0x12, 0x00, 0x05, 0x00, 0x00, + 0x00, 0xA0, 0x20, 0x15, 0x00, 0xC8, 0x00, 0x00, + 0x01, 0x43, 0x00, 0x3A, 0x00, 0x5C, 0x00, 0x44, + 0x00, 0x6F, 0x00, 0x63, 0x00, 0x75, 0x00, 0x6D, + 0x00, 0x65, 0x00, 0x6E, 0x00, 0x74, 0x00, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x00, 0xE2, 0x3A, 0x0B, 0x07, 0xA5, + 0x03, 0x2F, 0x63, 0x97, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x01, 0x1C, 0x3A, 0x0B, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x12, 0x75, 0xB3, 0x05, + 0xE2, 0xBC, 0x74, 0x68, 0xAD, 0xAC, 0x7B, 0xB1, + 0xF8, 0x52, 0xD5, 0x8F, 0xF7, 0x03, 0x00, 0x00, + 0x06, 0xA5, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x01, 0x56, 0x3A, 0x0B, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x01, 0x90, 0x3A, 0x0B, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0xA5, 0x00, 0x22, 0x8E, 0xA3, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x4C, 0xA5, 0xC8, 0xC8, 0x41, 0x50, 0x52, 0x39, + 0x07, 0x01, 0x00, 0x5F, 0x00, 0x00, 0xFF, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x01, 0xCA, 0x3A, 0x0B, 0x01, 0x48, + 0x34, 0x33, 0x00, 0x00, 0x00, 0x00, 0x76, 0x3E, + 0x84, 0x10, 0x2E, 0x48, 0x54, 0x0D, 0x98, 0x4C, + 0x14, 0x12, 0x72, 0x7A, 0x88, 0x0F, 0x9F, 0x84, + 0x98, 0x03, 0x52, 0xA6, 0xA4, 0x0A, 0x6E, 0xA8, + 0x54, 0x0C, 0x13, 0xB6, 0xE8, 0x0A, 0x77, 0xC0, + 0x94, 0x04, 0x73, 0xC6, 0x14, 0x07, 0x80, 0xCA, + 0xA8, 0x08, 0x31, 0xD2, 0x44, 0x09, 0x1E, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x02, 0x04, 0x3A, 0x0B, 0x74, 0x09, + 0x7A, 0xE4, 0x78, 0x17, 0xA5, 0xE4, 0x24, 0x09, + 0x45, 0xE8, 0x68, 0x07, 0xBA, 0xEC, 0xE8, 0x05, + 0xC2, 0xF0, 0x58, 0x16, 0x78, 0xF6, 0x98, 0x15, + 0x7C, 0xFC, 0xB8, 0x19, 0xAD, 0xFC, 0x74, 0x09, + 0x8C, 0x02, 0x39, 0x0D, 0x36, 0x06, 0x99, 0x06, + 0x9B, 0x08, 0x09, 0x0B, 0xA1, 0x0C, 0x25, 0x19, + 0x57, 0x10, 0x29, 0x05, 0x1A, 0x1C, 0x45, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x02, 0x3E, 0x3A, 0x0B, 0x55, 0x1E, + 0x69, 0x16, 0xA4, 0x24, 0xB9, 0x09, 0x1C, 0x44, + 0x55, 0x08, 0x9C, 0x44, 0xC9, 0x0B, 0x9F, 0x4A, + 0xF9, 0x19, 0x4C, 0x4C, 0xF9, 0x13, 0x5E, 0x50, + 0x09, 0x13, 0xB7, 0x6A, 0x09, 0x0A, 0x7C, 0x7A, + 0x75, 0x0F, 0x0E, 0x7E, 0x95, 0x00, 0x81, 0xA6, + 0x99, 0x0E, 0xC0, 0xAE, 0xE5, 0x19, 0xA0, 0xCC, + 0x35, 0x0D, 0x63, 0xE2, 0x85, 0x1F, 0x8E, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x02, 0x78, 0x3A, 0x0B, 0x35, 0x1D, + 0xC1, 0xE8, 0xA9, 0x0C, 0x7A, 0x06, 0xCA, 0x0E, + 0xAD, 0x12, 0xD6, 0x1C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x02, 0xB2, 0x2A, 0x0B, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x6C, 0x12, 0x00, 0x2B, 0xC5, 0xA9, 0x00, + 0x64, 0x00, 0x00, 0x00, 0xFC, 0xEC, 0x12, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xF1, 0x42, 0x42, + 0x40, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0xCE, 0x6D, 0x64, 0xED, 0x00, 0x00, 0x00, 0x00, + 0x30, 0xF2, 0x12, 0x00, 0x1A, 0xAA, 0xA7, 0x00, + 0x3A, 0x00, 0x00, 0x00, 0xF6, 0x6D, 0x64, 0xED, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0xF2, 0x12, 0x00, 0x89, 0xAE, 0xA9, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0xF1, 0x01, 0x00, + 0x1C, 0xCF, 0xA9, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x0A, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x8B, 0x00, 0x00, 0xFC, 0x3A, 0x1E, 0xDC, 0x74, + 0x09, 0x7A, 0xE4, 0x78, 0x17, 0xA5, 0xE4, 0x24, + 0x09, 0x45, 0xE8, 0x68, 0x07, 0xBA, 0xEC, 0xE8, + 0x05, 0xC2, 0xF0, 0x58, 0x16, 0x78, 0xF6, 0x98, + 0x15, 0x7C, 0xFC, 0xB8, 0x19, 0xAD, 0xFC, 0x74, + 0x09, 0x8C, 0x02, 0x39, 0x0D, 0x36, 0x06, 0x99, + 0x06, 0x9B, 0x08, 0x09, 0x0B, 0xA1, 0x0C, 0x25, + 0x19, 0x57, 0x10, 0x29, 0x05, 0x1A, 0x1C, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x8B, 0x00, 0x01, 0x36, 0x2E, 0x0B, 0x06, 0xA5, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2B, 0xC5, 0xA9, 0x00, + 0x64, 0x00, 0x00, 0x00, 0xD8, 0xEE, 0x12, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xF0, 0xAC, 0x00, + 0xF0, 0xF1, 0x12, 0x00, 0x6A, 0xB1, 0xA7, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0xA5, 0x00, 0x01, + 0x00, 0x00, 0x12, 0x00, 0x14, 0xAB, 0xA7, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x0C, 0xF2, 0x12, 0x00, + 0x20, 0xAB, 0xA7, 0x00, 0x08, 0xF2, 0x12, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x99, 0xA9, 0xA7, 0x00, + 0xE8, 0x3D, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0xF0, 0x8F, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x52, 0xED, 0x64, 0xED, + 0xD4, 0xF1, 0x12, 0x00, 0xFA, 0xCB, 0xA9, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x3D, 0xAC, 0x00, 0xBD, 0xCC, 0xA9, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xF7, 0x12, 0x00, + 0x88, 0xC4, 0xA9, 0x00, 0xD8, 0xF1, 0x12, 0x00, + 0x40, 0x00, 0x00, 0x00, 0xBB, 0xC4, 0xA9, 0x00, + 0x02, 0x00, 0x3F, 0x05, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x6D, 0x64, 0xED, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0xF2, 0x12, 0x00, + 0x89, 0xAE, 0xA9, 0x00, 0x03, 0x00, 0x00, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xF7, 0xA9, 0x00, + 0x02, 0xFA, 0x3F, 0x05, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0xF7, 0xF3, 0x00, + 0x0C, 0xCF, 0xA9, 0x00, 0x24, 0x71, 0x12, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x1C, 0xCF, 0xA9, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x02, 0xF0, 0x8F, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x01, 0xFB, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF1, 0x12, 0x00, + 0x89, 0xAE, 0xA9, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xE8, 0x3D, 0xAC, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0C, 0xF2, 0x12, 0x00, 0x14, 0xAB, 0xA7, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x0C, 0xF2, 0x12, 0x00, + 0x20, 0xAB, 0xA7, 0x00, 0x08, 0xF2, 0x12, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0xFB, 0x0F, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x02, 0xF0, 0x8F, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x52, 0xED, 0x64, 0xED, + 0xD4, 0xF1, 0x12, 0x00, 0xFA, 0xCB, 0xA9, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x01, 0x02, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, + 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3A, 0x3D, 0x3F, 0xFF, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0x07, 0xA4, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x52, 0xED, 0x64, 0xED, + 0xD4, 0xF1, 0x12, 0x00, 0xFA, 0xCB, 0xA9, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x42, 0xED, 0x64, 0xED, + 0xE4, 0xF1, 0x12, 0x00, 0xFA, 0xCB, 0xA9, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x08, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0xCF, + 0x00, 0x01, 0x00, 0x00, 0x1F, 0x01, 0x01, 0x00, + 0xEB, 0xC4, 0xA9, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x24, 0x71, 0x12, 0x00, 0x40, 0x00, 0x00, 0x00, + 0xE8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6C, 0x71, 0x12, 0x00, 0x0C, 0xCF, 0xA9, 0x00, + 0x24, 0x71, 0x12, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x1C, 0xCF, 0xA9, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x01, 0x02, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, + 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3A, 0x3D, 0x3F, 0xFF, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x01, 0x02, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, + 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3A, 0x3D, 0x3F, 0xFF, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x21, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x36, 0xED, 0x64, 0xED, + 0xB0, 0xF1, 0x12, 0x00, 0xFA, 0xCB, 0xA9, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0xF2, 0x12, 0x00, 0xBD, 0xCC, 0xA9, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x52, 0xED, 0x64, 0xED, 0xFC, 0xF1, 0x12, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x06, 0xF2, 0x12, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x01, 0x02, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, + 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3A, 0x3D, 0x3F, 0xFF, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x01, 0x02, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, + 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3A, 0x3D, 0x3F, 0xFF, 0x00, + }, + .response_len = 0x40 + }, + { + .cmd = { + 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x36, 0xED, 0x64, 0xED, + 0xB0, 0xF1, 0x12, 0x00, 0xFA, 0xCB, 0xA9, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0xF2, 0x12, 0x00, 0xBD, 0xCC, 0xA9, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x52, 0xED, 0x64, 0xED, 0xFC, 0xF1, 0x12, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x06, 0xF2, 0x12, 0x00, + }, + .response_len = 0x00 + }, + { + .cmd = { + 0x82, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x01, 0x02, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, + 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3A, 0x3D, 0x3F, 0xFF, 0x00, + }, + .response_len = 0x40 + }, }; static const unsigned char scan_cmd[0x40] = { - 0x0e, 0x00, 0x03, 0xa8, 0x00, 0xb6, 0xbb, 0xbb, - 0xb8, 0xb7, 0xb8, 0xb5, 0xb8, 0xb9, 0xb8, 0xb9, - 0xbb, 0xbb, 0xbe, 0xbb, 0x4e, 0x16, 0xf4, 0x77, - 0xa8, 0x07, 0x32, 0x00, 0x6a, 0x16, 0xf4, 0x77, - 0x78, 0x24, 0x61, 0x00, 0xc8, 0x00, 0xec, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x3c, 0xf3, 0x2f, 0x01, - 0x05, 0x90, 0xf6, 0x77, 0x84, 0xf5, 0x2f, 0x01, - 0x05, 0x90, 0xf6, 0x00, 0xc8, 0x00, 0xec, 0x00 + 0x0e, 0x00, 0x03, 0xa8, 0x00, 0xb6, 0xbb, 0xbb, + 0xb8, 0xb7, 0xb8, 0xb5, 0xb8, 0xb9, 0xb8, 0xb9, + 0xbb, 0xbb, 0xbe, 0xbb, 0x4e, 0x16, 0xf4, 0x77, + 0xa8, 0x07, 0x32, 0x00, 0x6a, 0x16, 0xf4, 0x77, + 0x78, 0x24, 0x61, 0x00, 0xc8, 0x00, 0xec, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x3c, 0xf3, 0x2f, 0x01, + 0x05, 0x90, 0xf6, 0x77, 0x84, 0xf5, 0x2f, 0x01, + 0x05, 0x90, 0xf6, 0x00, 0xc8, 0x00, 0xec, 0x00 }; #endif diff --git a/libfprint/drivers/upektc_img.c b/libfprint/drivers/upektc_img.c index 988793dc..1e06b903 100644 --- a/libfprint/drivers/upektc_img.c +++ b/libfprint/drivers/upektc_img.c @@ -21,627 +21,686 @@ #include "drivers_api.h" #include "upek_proto.h" -#include "aeslib.h" #include "upektc_img.h" -static void start_capture(struct fp_img_dev *dev); -static void start_deactivation(struct fp_img_dev *dev); +static void start_capture (FpImageDevice *dev); +static void start_deactivation (FpImageDevice *dev); -#define EP_IN (1 | LIBUSB_ENDPOINT_IN) -#define EP_OUT (2 | LIBUSB_ENDPOINT_OUT) -#define CTRL_TIMEOUT 4000 -#define BULK_TIMEOUT 4000 +#define EP_IN (1 | FPI_USB_ENDPOINT_IN) +#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT) +#define CTRL_TIMEOUT 4000 +#define BULK_TIMEOUT 4000 -#define IMAGE_WIDTH 144 -#define IMAGE_HEIGHT 384 -#define IMAGE_SIZE (IMAGE_WIDTH * IMAGE_HEIGHT) +#define IMAGE_WIDTH 144 +#define IMAGE_HEIGHT 384 +#define IMAGE_SIZE (IMAGE_WIDTH * IMAGE_HEIGHT) -#define MAX_CMD_SIZE 64 -#define MAX_RESPONSE_SIZE 2052 -#define SHORT_RESPONSE_SIZE 64 +#define MAX_CMD_SIZE 64 +#define MAX_RESPONSE_SIZE 2052 +#define SHORT_RESPONSE_SIZE 64 -struct upektc_img_dev { - unsigned char cmd[MAX_CMD_SIZE]; - unsigned char response[MAX_RESPONSE_SIZE]; - unsigned char image_bits[IMAGE_SIZE * 2]; - unsigned char seq; - size_t image_size; - size_t response_rest; - gboolean deactivating; +struct _FpiDeviceUpektcImg +{ + FpImageDevice parent; + + unsigned char cmd[MAX_CMD_SIZE]; + unsigned char response[MAX_RESPONSE_SIZE]; + unsigned char *image_bits; + unsigned char seq; + size_t image_size; + size_t response_rest; + gboolean deactivating; }; +G_DECLARE_FINAL_TYPE (FpiDeviceUpektcImg, fpi_device_upektc_img, FPI, + DEVICE_UPEKTC_IMG, FpImageDevice); +G_DEFINE_TYPE (FpiDeviceUpektcImg, fpi_device_upektc_img, FP_TYPE_IMAGE_DEVICE); /****** HELPERS ******/ -static void upektc_img_cmd_fix_seq(unsigned char *cmd_buf, unsigned char seq) +static void +upektc_img_cmd_fix_seq (unsigned char *cmd_buf, unsigned char seq) { - uint8_t byte; + uint8_t byte; - byte = cmd_buf[5]; - byte &= 0x0f; - byte |= (seq << 4); - cmd_buf[5] = byte; -} - -static void upektc_img_cmd_update_crc(unsigned char *cmd_buf, size_t size) -{ - /* CRC does not cover Ciao prefix (4 bytes) and CRC location (2 bytes) */ - uint16_t crc = udf_crc(cmd_buf + 4, size - 6); - - cmd_buf[size - 2] = (crc & 0x00ff); - cmd_buf[size - 1] = (crc & 0xff00) >> 8; + byte = cmd_buf[5]; + byte &= 0x0f; + byte |= (seq << 4); + cmd_buf[5] = byte; } static void -upektc_img_submit_req(fpi_ssm *ssm, - struct fp_img_dev *dev, - const unsigned char *buf, - size_t buf_size, - unsigned char seq, - libusb_transfer_cb_fn cb) +upektc_img_cmd_update_crc (unsigned char *cmd_buf, size_t size) { - struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); - struct libusb_transfer *transfer = fpi_usb_alloc(); - int r; + /* CRC does not cover Ciao prefix (4 bytes) and CRC location (2 bytes) */ + uint16_t crc = udf_crc (cmd_buf + 4, size - 6); - BUG_ON(buf_size > MAX_CMD_SIZE); - - transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER; - - memcpy(upekdev->cmd, buf, buf_size); - upektc_img_cmd_fix_seq(upekdev->cmd, seq); - upektc_img_cmd_update_crc(upekdev->cmd, buf_size); - - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, upekdev->cmd, buf_size, - cb, ssm, BULK_TIMEOUT); - - r = libusb_submit_transfer(transfer); - if (r < 0) { - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } + cmd_buf[size - 2] = (crc & 0x00ff); + cmd_buf[size - 1] = (crc & 0xff00) >> 8; } static void -upektc_img_read_data(fpi_ssm *ssm, - struct fp_img_dev *dev, - size_t buf_size, - size_t buf_offset, - libusb_transfer_cb_fn cb) +upektc_img_submit_req (FpiSsm *ssm, + FpImageDevice *dev, + const unsigned char *buf, + size_t buf_size, + unsigned char seq, + FpiUsbTransferCallback cb) { - struct libusb_transfer *transfer = fpi_usb_alloc(); - struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); - int r; + FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev); + FpiUsbTransfer *transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); - BUG_ON(buf_size > MAX_RESPONSE_SIZE); + BUG_ON (buf_size > MAX_CMD_SIZE); - transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER; + memcpy (self->cmd, buf, buf_size); + upektc_img_cmd_fix_seq (self->cmd, seq); + upektc_img_cmd_update_crc (self->cmd, buf_size); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, upekdev->response + buf_offset, buf_size, - cb, ssm, BULK_TIMEOUT); + fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT, self->cmd, buf_size, + NULL); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, cb, NULL); + fpi_usb_transfer_unref (transfer); +} - r = libusb_submit_transfer(transfer); - if (r < 0) { - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } +static void +upektc_img_read_data (FpiSsm *ssm, + FpImageDevice *dev, + size_t buf_size, + size_t buf_offset, + FpiUsbTransferCallback cb) +{ + FpiUsbTransfer *transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); + FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev); + + BUG_ON (buf_offset + buf_size > MAX_RESPONSE_SIZE); + + fpi_usb_transfer_fill_bulk_full (transfer, EP_IN, + self->response + buf_offset, buf_size, + NULL); + transfer->ssm = ssm; + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, cb, NULL); + fpi_usb_transfer_unref (transfer); } /****** CAPTURE ******/ enum capture_states { - CAPTURE_INIT_CAPTURE, - CAPTURE_READ_DATA, - CAPTURE_READ_DATA_TERM, - CAPTURE_ACK_00_28, - CAPTURE_ACK_08, - CAPTURE_ACK_FRAME, - CAPTURE_ACK_00_28_TERM, - CAPTURE_NUM_STATES, + CAPTURE_INIT_CAPTURE, + CAPTURE_READ_DATA, + CAPTURE_READ_DATA_TERM, + CAPTURE_ACK_00_28, + CAPTURE_ACK_08, + CAPTURE_ACK_FRAME, + CAPTURE_ACK_00_28_TERM, + CAPTURE_NUM_STATES, }; -static void capture_reqs_cb(struct libusb_transfer *transfer) +static void +capture_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; + if (error) + { + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } + switch (fpi_ssm_get_cur_state (transfer->ssm)) + { + case CAPTURE_ACK_00_28_TERM: + fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_READ_DATA_TERM); + break; - if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) || - (transfer->length != transfer->actual_length)) { - fpi_ssm_mark_failed(ssm, -EIO); - return; - } - switch (fpi_ssm_get_cur_state(ssm)) { - case CAPTURE_ACK_00_28_TERM: - fpi_ssm_jump_to_state(ssm, CAPTURE_READ_DATA_TERM); - break; - default: - fpi_ssm_jump_to_state(ssm, CAPTURE_READ_DATA); - break; - } + default: + fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_READ_DATA); + break; + } } -static int upektc_img_process_image_frame(unsigned char *image_buf, unsigned char *cmd_res) +static int +upektc_img_process_image_frame (unsigned char *image_buf, unsigned char *cmd_res) { - int offset = 8; - int len = ((cmd_res[5] & 0x0f) << 8) | (cmd_res[6]); + int offset = 8; + int len = ((cmd_res[5] & 0x0f) << 8) | (cmd_res[6]); - len -= 1; - if (cmd_res[7] == 0x2c) { - len -= 10; - offset += 10; - } - if (cmd_res[7] == 0x20) { - len -= 4; - } - memcpy(image_buf, cmd_res + offset, len); + len -= 1; + if (cmd_res[7] == 0x2c) + { + len -= 10; + offset += 10; + } + if (cmd_res[7] == 0x20) + len -= 4; + memcpy (image_buf, cmd_res + offset, len); - return len; + return len; } -static void capture_read_data_cb(struct libusb_transfer *transfer) +static void +capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); - unsigned char *data = upekdev->response; - struct fp_img *img; - size_t response_size; + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev); + unsigned char *data = self->response; + FpImage *img; + size_t response_size; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fp_dbg("request is not completed, %d", transfer->status); - fpi_ssm_mark_failed(ssm, -EIO); - return; - } + if (error) + { + fp_dbg ("request is not completed, %s", error->message); + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } - if (upekdev->deactivating) { - fp_dbg("Deactivate requested\n"); - fpi_ssm_mark_completed(ssm); - return; - } + if (self->deactivating) + { + fp_dbg ("Deactivate requested\n"); + fpi_ssm_mark_completed (transfer->ssm); + return; + } - fp_dbg("request completed, len: %.4x", transfer->actual_length); - if (transfer->actual_length == 0) { - fpi_ssm_jump_to_state(ssm, fpi_ssm_get_cur_state(ssm)); - return; - } + fp_dbg ("request completed, len: %.4x", (gint) transfer->actual_length); + if (transfer->actual_length == 0) + { + fpi_ssm_jump_to_state (transfer->ssm, + fpi_ssm_get_cur_state (transfer->ssm)); + return; + } - if (fpi_ssm_get_cur_state(ssm) == CAPTURE_READ_DATA_TERM) { - fp_dbg("Terminating SSM\n"); - fpi_ssm_mark_completed(ssm); - return; - } + if (fpi_ssm_get_cur_state (transfer->ssm) == CAPTURE_READ_DATA_TERM) + { + fp_dbg ("Terminating SSM\n"); + fpi_ssm_mark_completed (transfer->ssm); + return; + } - if (!upekdev->response_rest) { - response_size = ((data[5] & 0x0f) << 8) + data[6]; - response_size += 9; /* 7 bytes for header, 2 for CRC */ - if (response_size > transfer->actual_length) { - fp_dbg("response_size is %lu, actual_length is %d\n", - response_size, transfer->actual_length); - fp_dbg("Waiting for rest of transfer"); - BUG_ON(upekdev->response_rest); - upekdev->response_rest = response_size - transfer->actual_length; - fpi_ssm_jump_to_state(ssm, CAPTURE_READ_DATA); - return; - } - } - upekdev->response_rest = 0; + if (!self->response_rest) + { + response_size = ((data[5] & 0x0f) << 8) + data[6]; + response_size += 9; /* 7 bytes for header, 2 for CRC */ + if (response_size > transfer->actual_length) + { + fp_dbg ("response_size is %lu, actual_length is %d\n", + response_size, (gint) transfer->actual_length); + fp_dbg ("Waiting for rest of transfer"); + BUG_ON (self->response_rest); + self->response_rest = response_size - transfer->actual_length; + fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_READ_DATA); + return; + } + } + self->response_rest = 0; - switch (data[4]) { - case 0x00: - switch (data[7]) { - /* No finger */ - case 0x28: - fp_dbg("18th byte is %.2x\n", data[18]); - switch (data[18]) { - case 0x0c: - /* no finger */ - fpi_ssm_jump_to_state(ssm, CAPTURE_ACK_00_28); - break; - case 0x00: - /* finger is present! */ - fpi_ssm_jump_to_state(ssm, CAPTURE_ACK_00_28); - break; - case 0x1e: - /* short scan */ - fp_err("short scan, aborting\n"); - fpi_imgdev_abort_scan(dev, FP_VERIFY_RETRY_TOO_SHORT); - fpi_imgdev_report_finger_status(dev, FALSE); - fpi_ssm_jump_to_state(ssm, CAPTURE_ACK_00_28_TERM); - break; - case 0x1d: - /* too much horisontal movement */ - fp_err("too much horisontal movement, aborting\n"); - fpi_imgdev_abort_scan(dev, FP_VERIFY_RETRY_CENTER_FINGER); - fpi_imgdev_report_finger_status(dev, FALSE); - fpi_ssm_jump_to_state(ssm, CAPTURE_ACK_00_28_TERM); - break; - default: - /* some error happened, cancel scan */ - fp_err("something bad happened, stop scan\n"); - fpi_imgdev_abort_scan(dev, FP_VERIFY_RETRY); - fpi_imgdev_report_finger_status(dev, FALSE); - fpi_ssm_jump_to_state(ssm, CAPTURE_ACK_00_28_TERM); - break; - } - break; - /* Image frame with additional info */ - case 0x2c: - fpi_imgdev_report_finger_status(dev, TRUE); - /* Plain image frame */ - case 0x24: - upekdev->image_size += - upektc_img_process_image_frame(upekdev->image_bits + upekdev->image_size, - data); - fpi_ssm_jump_to_state(ssm, CAPTURE_ACK_FRAME); - break; - /* Last image frame */ - case 0x20: - upekdev->image_size += - upektc_img_process_image_frame(upekdev->image_bits + upekdev->image_size, - data); - BUG_ON(upekdev->image_size != IMAGE_SIZE); - fp_dbg("Image size is %lu\n", upekdev->image_size); - img = fpi_img_new(IMAGE_SIZE); - img->flags = FP_IMG_PARTIAL; - memcpy(img->data, upekdev->image_bits, IMAGE_SIZE); - fpi_imgdev_image_captured(dev, img); - fpi_imgdev_report_finger_status(dev, FALSE); - fpi_ssm_mark_completed(ssm); - break; - default: - fp_err("Unknown response!\n"); - fpi_ssm_mark_failed(ssm, -EIO); - break; - } - break; - case 0x08: - fpi_ssm_jump_to_state(ssm, CAPTURE_ACK_08); - break; - default: - fp_err("Not handled response!\n"); - fpi_ssm_mark_failed(ssm, -EIO); - } + switch (data[4]) + { + case 0x00: + switch (data[7]) + { + /* No finger */ + case 0x28: + fp_dbg ("18th byte is %.2x\n", data[18]); + switch (data[18]) + { + case 0x0c: + /* no finger */ + fpi_ssm_jump_to_state (transfer->ssm, + CAPTURE_ACK_00_28); + break; + + case 0x00: + /* finger is present! */ + fpi_ssm_jump_to_state (transfer->ssm, + CAPTURE_ACK_00_28); + break; + + case 0x1e: + /* short scan */ + fp_err ("short scan, aborting\n"); + fpi_image_device_retry_scan (dev, + FP_DEVICE_RETRY_TOO_SHORT); + fpi_image_device_report_finger_status (dev, + FALSE); + fpi_ssm_jump_to_state (transfer->ssm, + CAPTURE_ACK_00_28_TERM); + break; + + case 0x1d: + /* too much horisontal movement */ + fp_err ("too much horisontal movement, aborting\n"); + fpi_image_device_retry_scan (dev, + FP_DEVICE_RETRY_CENTER_FINGER); + fpi_image_device_report_finger_status (dev, + FALSE); + fpi_ssm_jump_to_state (transfer->ssm, + CAPTURE_ACK_00_28_TERM); + break; + + default: + /* some error happened, cancel scan */ + fp_err ("something bad happened, stop scan\n"); + fpi_image_device_retry_scan (dev, + FP_DEVICE_RETRY); + fpi_image_device_report_finger_status (dev, + FALSE); + fpi_ssm_jump_to_state (transfer->ssm, + CAPTURE_ACK_00_28_TERM); + break; + } + break; + + /* Image frame with additional info */ + case 0x2c: + fpi_image_device_report_finger_status (dev, + TRUE); + + /* Plain image frame */ + case 0x24: + self->image_size += + upektc_img_process_image_frame (self->image_bits + self->image_size, + data); + fpi_ssm_jump_to_state (transfer->ssm, + CAPTURE_ACK_FRAME); + break; + + /* Last image frame */ + case 0x20: + self->image_size += + upektc_img_process_image_frame (self->image_bits + self->image_size, + data); + BUG_ON (self->image_size != IMAGE_SIZE); + fp_dbg ("Image size is %lu\n", + self->image_size); + img = fp_image_new (IMAGE_WIDTH, IMAGE_HEIGHT); + memcpy (img->data, self->image_bits, + IMAGE_SIZE); + fpi_image_device_image_captured (dev, img); + fpi_image_device_report_finger_status (dev, + FALSE); + fpi_ssm_mark_completed (transfer->ssm); + break; + + default: + fp_err ("Unknown response!\n"); + fpi_ssm_mark_failed (transfer->ssm, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL)); + break; + } + break; + + case 0x08: + fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_ACK_08); + break; + + default: + fp_err ("Not handled response!\n"); + fpi_ssm_mark_failed (transfer->ssm, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL)); + } } -static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +capture_run_state (FpiSsm *ssm, FpDevice *_dev) { - struct fp_img_dev *dev = user_data; - struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(_dev); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (_dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case CAPTURE_INIT_CAPTURE: - upektc_img_submit_req(ssm, dev, upek2020_init_capture, sizeof(upek2020_init_capture), - upekdev->seq, capture_reqs_cb); - upekdev->seq++; - break; - case CAPTURE_READ_DATA: - case CAPTURE_READ_DATA_TERM: - if (!upekdev->response_rest) - upektc_img_read_data(ssm, dev, SHORT_RESPONSE_SIZE, 0, capture_read_data_cb); - else - upektc_img_read_data(ssm, dev, MAX_RESPONSE_SIZE - SHORT_RESPONSE_SIZE, - SHORT_RESPONSE_SIZE, capture_read_data_cb); - break; - case CAPTURE_ACK_00_28: - case CAPTURE_ACK_00_28_TERM: - upektc_img_submit_req(ssm, dev, upek2020_ack_00_28, sizeof(upek2020_ack_00_28), - upekdev->seq, capture_reqs_cb); - upekdev->seq++; - break; - case CAPTURE_ACK_08: - upektc_img_submit_req(ssm, dev, upek2020_ack_08, sizeof(upek2020_ack_08), - 0, capture_reqs_cb); - break; - case CAPTURE_ACK_FRAME: - upektc_img_submit_req(ssm, dev, upek2020_ack_frame, sizeof(upek2020_ack_frame), - upekdev->seq, capture_reqs_cb); - upekdev->seq++; - break; - }; + switch (fpi_ssm_get_cur_state (ssm)) + { + case CAPTURE_INIT_CAPTURE: + upektc_img_submit_req (ssm, dev, upek2020_init_capture, sizeof (upek2020_init_capture), + self->seq, capture_reqs_cb); + self->seq++; + break; + + case CAPTURE_READ_DATA: + case CAPTURE_READ_DATA_TERM: + if (!self->response_rest) + upektc_img_read_data (ssm, dev, SHORT_RESPONSE_SIZE, 0, capture_read_data_cb); + else + upektc_img_read_data (ssm, dev, MAX_RESPONSE_SIZE - SHORT_RESPONSE_SIZE, + SHORT_RESPONSE_SIZE, capture_read_data_cb); + break; + + case CAPTURE_ACK_00_28: + case CAPTURE_ACK_00_28_TERM: + upektc_img_submit_req (ssm, dev, upek2020_ack_00_28, sizeof (upek2020_ack_00_28), + self->seq, capture_reqs_cb); + self->seq++; + break; + + case CAPTURE_ACK_08: + upektc_img_submit_req (ssm, dev, upek2020_ack_08, sizeof (upek2020_ack_08), + 0, capture_reqs_cb); + break; + + case CAPTURE_ACK_FRAME: + upektc_img_submit_req (ssm, dev, upek2020_ack_frame, sizeof (upek2020_ack_frame), + self->seq, capture_reqs_cb); + self->seq++; + break; + } + ; } -static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error_arg) { - struct fp_img_dev *dev = user_data; - struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(_dev); - int err = fpi_ssm_get_error(ssm); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (_dev); - fp_dbg("Capture completed, %d", err); - fpi_ssm_free(ssm); + g_autoptr(GError) error = error_arg; - if (upekdev->deactivating) - start_deactivation(dev); - else if (err) - fpi_imgdev_session_error(dev, err); - else - start_capture(dev); + fpi_ssm_free (ssm); + + /* Note: We assume that the error is a cancellation in the deactivation case */ + if (self->deactivating) + start_deactivation (dev); + else if (error) + fpi_image_device_session_error (dev, g_steal_pointer (&error)); + else + start_capture (dev); } -static void start_capture(struct fp_img_dev *dev) +static void +start_capture (FpImageDevice *dev) { - struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_ssm *ssm; + FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev); + FpiSsm *ssm; - upekdev->image_size = 0; + self->image_size = 0; - ssm = fpi_ssm_new(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev); - fpi_ssm_start(ssm, capture_sm_complete); + ssm = fpi_ssm_new (FP_DEVICE (dev), capture_run_state, + CAPTURE_NUM_STATES); + fpi_ssm_start (ssm, capture_sm_complete); } /****** INITIALIZATION/DEINITIALIZATION ******/ enum deactivate_states { - DEACTIVATE_DEINIT, - DEACTIVATE_READ_DEINIT_DATA, - DEACTIVATE_NUM_STATES, + DEACTIVATE_DEINIT, + DEACTIVATE_READ_DEINIT_DATA, + DEACTIVATE_NUM_STATES, }; -static void deactivate_reqs_cb(struct libusb_transfer *transfer) +static void +deactivate_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - - if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) && - (transfer->length == transfer->actual_length)) { - fpi_ssm_jump_to_state(ssm, CAPTURE_READ_DATA); - } else { - fpi_ssm_mark_failed(ssm, -EIO); - } + if (!error) + fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_READ_DATA); + else + fpi_ssm_mark_failed (transfer->ssm, error); } /* TODO: process response properly */ -static void deactivate_read_data_cb(struct libusb_transfer *transfer) +static void +deactivate_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - - if (transfer->status == LIBUSB_TRANSFER_COMPLETED) { - fpi_ssm_mark_completed(ssm); - } else { - fpi_ssm_mark_failed(ssm, -EIO); - } + if (!error) + fpi_ssm_mark_completed (transfer->ssm); + else + fpi_ssm_mark_failed (transfer->ssm, error); } -static void deactivate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +deactivate_run_state (FpiSsm *ssm, FpDevice *_dev) { - struct fp_img_dev *dev = user_data; - struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(_dev); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (_dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case DEACTIVATE_DEINIT: - upektc_img_submit_req(ssm, dev, upek2020_deinit, sizeof(upek2020_deinit), - upekdev->seq, deactivate_reqs_cb); - upekdev->seq++; - break; - case DEACTIVATE_READ_DEINIT_DATA: - upektc_img_read_data(ssm, dev, SHORT_RESPONSE_SIZE, 0, deactivate_read_data_cb); - break; - }; + switch (fpi_ssm_get_cur_state (ssm)) + { + case DEACTIVATE_DEINIT: + upektc_img_submit_req (ssm, dev, upek2020_deinit, sizeof (upek2020_deinit), + self->seq, deactivate_reqs_cb); + self->seq++; + break; + + case DEACTIVATE_READ_DEINIT_DATA: + upektc_img_read_data (ssm, dev, SHORT_RESPONSE_SIZE, 0, deactivate_read_data_cb); + break; + } + ; } -static void deactivate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +deactivate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { - struct fp_img_dev *dev = user_data; - struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(_dev); - int err = fpi_ssm_get_error(ssm); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (_dev); - fp_dbg("Deactivate completed"); - fpi_ssm_free(ssm); + fp_dbg ("Deactivate completed"); + fpi_ssm_free (ssm); - if (err) { - fpi_imgdev_session_error(dev, err); - return; - } - - upekdev->deactivating = FALSE; - fpi_imgdev_deactivate_complete(dev); + self->deactivating = FALSE; + fpi_image_device_deactivate_complete (dev, error); } -static void start_deactivation(struct fp_img_dev *dev) +static void +start_deactivation (FpImageDevice *dev) { - struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_ssm *ssm; + FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev); + FpiSsm *ssm; - upekdev->image_size = 0; + self->image_size = 0; - ssm = fpi_ssm_new(FP_DEV(dev), deactivate_run_state, DEACTIVATE_NUM_STATES, dev); - fpi_ssm_start(ssm, deactivate_sm_complete); + ssm = fpi_ssm_new (FP_DEVICE (dev), deactivate_run_state, + DEACTIVATE_NUM_STATES); + fpi_ssm_start (ssm, deactivate_sm_complete); } enum activate_states { - ACTIVATE_CONTROL_REQ_1, - ACTIVATE_READ_CTRL_RESP_1, - ACTIVATE_INIT_1, - ACTIVATE_READ_INIT_1_RESP, - ACTIVATE_INIT_2, - ACTIVATE_READ_INIT_2_RESP, - ACTIVATE_CONTROL_REQ_2, - ACTIVATE_READ_CTRL_RESP_2, - ACTIVATE_INIT_3, - ACTIVATE_READ_INIT_3_RESP, - ACTIVATE_INIT_4, - ACTIVATE_READ_INIT_4_RESP, - ACTIVATE_NUM_STATES, + ACTIVATE_CONTROL_REQ_1, + ACTIVATE_READ_CTRL_RESP_1, + ACTIVATE_INIT_1, + ACTIVATE_READ_INIT_1_RESP, + ACTIVATE_INIT_2, + ACTIVATE_READ_INIT_2_RESP, + ACTIVATE_CONTROL_REQ_2, + ACTIVATE_READ_CTRL_RESP_2, + ACTIVATE_INIT_3, + ACTIVATE_READ_INIT_3_RESP, + ACTIVATE_INIT_4, + ACTIVATE_READ_INIT_4_RESP, + ACTIVATE_NUM_STATES, }; -static void init_reqs_ctrl_cb(struct libusb_transfer *transfer) +static void +init_reqs_ctrl_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - - if (transfer->status == LIBUSB_TRANSFER_COMPLETED) { - fpi_ssm_next_state(ssm); - } else { - fpi_ssm_mark_failed(ssm, -EIO); - } + if (!error) + fpi_ssm_next_state (transfer->ssm); + else + fpi_ssm_mark_failed (transfer->ssm, error); } -static void init_reqs_cb(struct libusb_transfer *transfer) +static void +init_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - - if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) && - (transfer->length == transfer->actual_length)) { - fpi_ssm_next_state(ssm); - } else { - fpi_ssm_mark_failed(ssm, -EIO); - } + if (!error) + fpi_ssm_next_state (transfer->ssm); + else + fpi_ssm_mark_failed (transfer->ssm, error); } /* TODO: process response properly */ -static void init_read_data_cb(struct libusb_transfer *transfer) +static void +init_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - - if (transfer->status == LIBUSB_TRANSFER_COMPLETED) { - fpi_ssm_next_state(ssm); - } else { - fpi_ssm_mark_failed(ssm, -EIO); - } + if (!error) + fpi_ssm_next_state (transfer->ssm); + else + fpi_ssm_mark_failed (transfer->ssm, error); } -static void activate_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) +static void +activate_run_state (FpiSsm *ssm, FpDevice *dev) { - struct libusb_transfer *transfer; - struct fp_img_dev *idev = user_data; - struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(dev); - int r; + FpiUsbTransfer *transfer; + FpImageDevice *idev = FP_IMAGE_DEVICE (dev); + FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case ACTIVATE_CONTROL_REQ_1: - case ACTIVATE_CONTROL_REQ_2: - { - unsigned char *data; + switch (fpi_ssm_get_cur_state (ssm)) + { + case ACTIVATE_CONTROL_REQ_1: + case ACTIVATE_CONTROL_REQ_2: + { + transfer = fpi_usb_transfer_new (dev); - transfer = fpi_usb_alloc(); - transfer->flags |= LIBUSB_TRANSFER_FREE_BUFFER | - LIBUSB_TRANSFER_FREE_TRANSFER; + fpi_usb_transfer_fill_control (transfer, + G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE, + G_USB_DEVICE_REQUEST_TYPE_VENDOR, + G_USB_DEVICE_RECIPIENT_DEVICE, + 0x0c, 0x100, 0x0400, 1); + transfer->buffer[0] = '\0'; + transfer->ssm = ssm; + fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, + init_reqs_ctrl_cb, NULL); + fpi_usb_transfer_unref (transfer); + } + break; - data = g_malloc0(LIBUSB_CONTROL_SETUP_SIZE + 1); - libusb_fill_control_setup(data, - LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, 0x0c, 0x100, 0x0400, 1); - libusb_fill_control_transfer(transfer, fpi_dev_get_usb_dev(dev), data, - init_reqs_ctrl_cb, ssm, CTRL_TIMEOUT); - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(data); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } - } - break; - case ACTIVATE_INIT_1: - upektc_img_submit_req(ssm, idev, upek2020_init_1, sizeof(upek2020_init_1), - 0, init_reqs_cb); - break; - case ACTIVATE_INIT_2: - upektc_img_submit_req(ssm, idev, upek2020_init_2, sizeof(upek2020_init_2), - 0, init_reqs_cb); - break; - case ACTIVATE_INIT_3: - upektc_img_submit_req(ssm, idev, upek2020_init_3, sizeof(upek2020_init_3), - 0, init_reqs_cb); - break; - case ACTIVATE_INIT_4: - upektc_img_submit_req(ssm, idev, upek2020_init_4, sizeof(upek2020_init_4), - upekdev->seq, init_reqs_cb); - /* Seq should be updated after 4th init */ - upekdev->seq++; - break; - case ACTIVATE_READ_CTRL_RESP_1: - case ACTIVATE_READ_CTRL_RESP_2: - case ACTIVATE_READ_INIT_1_RESP: - case ACTIVATE_READ_INIT_2_RESP: - case ACTIVATE_READ_INIT_3_RESP: - case ACTIVATE_READ_INIT_4_RESP: - upektc_img_read_data(ssm, idev, SHORT_RESPONSE_SIZE, 0, init_read_data_cb); - break; - } + case ACTIVATE_INIT_1: + upektc_img_submit_req (ssm, idev, upek2020_init_1, sizeof (upek2020_init_1), + 0, init_reqs_cb); + break; + + case ACTIVATE_INIT_2: + upektc_img_submit_req (ssm, idev, upek2020_init_2, sizeof (upek2020_init_2), + 0, init_reqs_cb); + break; + + case ACTIVATE_INIT_3: + upektc_img_submit_req (ssm, idev, upek2020_init_3, sizeof (upek2020_init_3), + 0, init_reqs_cb); + break; + + case ACTIVATE_INIT_4: + upektc_img_submit_req (ssm, idev, upek2020_init_4, sizeof (upek2020_init_4), + self->seq, init_reqs_cb); + /* Seq should be updated after 4th init */ + self->seq++; + break; + + case ACTIVATE_READ_CTRL_RESP_1: + case ACTIVATE_READ_CTRL_RESP_2: + case ACTIVATE_READ_INIT_1_RESP: + case ACTIVATE_READ_INIT_2_RESP: + case ACTIVATE_READ_INIT_3_RESP: + case ACTIVATE_READ_INIT_4_RESP: + upektc_img_read_data (ssm, idev, SHORT_RESPONSE_SIZE, 0, init_read_data_cb); + break; + } } -static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { - struct fp_img_dev *dev = user_data; - int err = fpi_ssm_get_error(ssm); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); - fpi_ssm_free(ssm); - fp_dbg("%s status %d", __func__, err); - fpi_imgdev_activate_complete(dev, err); + fpi_ssm_free (ssm); + fpi_image_device_activate_complete (dev, error); - if (!err) - start_capture(dev); + if (!error) + start_capture (dev); } -static int dev_activate(struct fp_img_dev *dev) +static void +dev_activate (FpImageDevice *dev) { - struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, - ACTIVATE_NUM_STATES, dev); - upekdev->seq = 0; - fpi_ssm_start(ssm, activate_sm_complete); - return 0; + FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev); + FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), activate_run_state, + ACTIVATE_NUM_STATES); + + self->seq = 0; + fpi_ssm_start (ssm, activate_sm_complete); } -static void dev_deactivate(struct fp_img_dev *dev) +static void +dev_deactivate (FpImageDevice *dev) { - struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev); - upekdev->deactivating = TRUE; + self->deactivating = TRUE; } -static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) +static void +dev_init (FpImageDevice *dev) { - /* TODO check that device has endpoints we're using */ - int r; - struct upektc_img_dev *upekdev; + FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev); + GError *error = NULL; - r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - if (r < 0) { - fp_err("could not claim interface 0: %s", libusb_error_name(r)); - return r; - } + /* TODO check that device has endpoints we're using */ - upekdev = g_malloc0(sizeof(struct upektc_img_dev)); - fp_dev_set_instance_data(FP_DEV(dev), upekdev); - fpi_imgdev_open_complete(dev, 0); - return 0; + if (!g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error)) + { + fpi_image_device_open_complete (dev, error); + return; + } + + self->image_bits = g_malloc0 (IMAGE_SIZE * 2); + fpi_image_device_open_complete (dev, NULL); } -static void dev_deinit(struct fp_img_dev *dev) +static void +dev_deinit (FpImageDevice *dev) { - struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); - g_free(upekdev); - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - fpi_imgdev_close_complete(dev); + FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev); + GError *error = NULL; + + g_clear_pointer (&self->image_bits, 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); } -static int discover(struct libusb_device_descriptor *dsc, uint32_t *devtype) +static int +discover (GUsbDevice *usb_device) { - if (dsc->idProduct == 0x2020 && dsc->bcdDevice == 1) - return 1; - if (dsc->idProduct == 0x2016 && dsc->bcdDevice == 2) - return 1; + gint16 pid = g_usb_device_get_pid (usb_device); + gint16 bcd = g_usb_device_get_release (usb_device); - return 0; + if (pid == 0x2020 && bcd == 1) + return 100; + if (pid == 0x2016 && bcd == 2) + return 100; + + return 0; } -static const struct usb_id id_table[] = { - { .vendor = 0x147e, .product = 0x2016 }, - { .vendor = 0x147e, .product = 0x2020 }, - { 0, 0, 0, }, +static const FpIdEntry id_table[] = { + { .vid = 0x147e, .pid = 0x2016, }, + { .vid = 0x147e, .pid = 0x2020, }, + { .vid = 0, .pid = 0, .driver_data = 0 }, }; -struct fp_img_driver upektc_img_driver = { - .driver = { - .id = UPEKTC_IMG_ID, - .name = FP_COMPONENT, - .full_name = "Upek TouchChip Fingerprint Coprocessor", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_SWIPE, - .discover = discover, - }, - .flags = 0, - .img_height = IMAGE_HEIGHT, - .img_width = IMAGE_WIDTH, - .bz3_threshold = 20, +static void +fpi_device_upektc_img_init (FpiDeviceUpektcImg *self) +{ +} +static void +fpi_device_upektc_img_class_init (FpiDeviceUpektcImgClass *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); - .open = dev_init, - .close = dev_deinit, - .activate = dev_activate, - .deactivate = dev_deactivate, -}; + dev_class->id = "upektc_img"; + dev_class->full_name = "Upek TouchChip Fingerprint Coprocessor"; + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->id_table = id_table; + dev_class->scan_type = FP_SCAN_TYPE_SWIPE; + dev_class->usb_discover = discover; + + img_class->img_open = dev_init; + img_class->img_close = dev_deinit; + img_class->activate = dev_activate; + img_class->deactivate = dev_deactivate; + + img_class->bz3_threshold = 20; + + img_class->img_width = IMAGE_WIDTH; + img_class->img_height = IMAGE_HEIGHT; +} diff --git a/libfprint/drivers/upektc_img.h b/libfprint/drivers/upektc_img.h index 6146557e..9185aa8e 100644 --- a/libfprint/drivers/upektc_img.h +++ b/libfprint/drivers/upektc_img.h @@ -21,124 +21,124 @@ #define __UPEKTC_IMG_H static const unsigned char upek2020_init_1[] = { -'C', 'i', 'a', 'o', -0x04, -0x00, 0x0d, -0x01, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -0x01, 0x00, 0x00, 0x00, -0xda, 0xc1 + 'C', 'i', 'a', 'o', + 0x04, + 0x00, 0x0d, + 0x01, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x00, 0x00, 0x00, + 0xda, 0xc1 }; static const unsigned char upek2020_init_2[] = { -0x43, 0x69, 0x61, 0x6f, -0x07, -0x00, 0x01, -0x01, -0x3d, 0x72 + 0x43, 0x69, 0x61, 0x6f, + 0x07, + 0x00, 0x01, + 0x01, + 0x3d, 0x72 }; static const unsigned char upek2020_init_3[] = { -'C', 'i', 'a', 'o', -0x04, -0x00, 0x0d, -0x01, 0x00, 0xbc, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, -0x01, 0x00, 0x00, 0x00, -0x55, 0x2f + 'C', 'i', 'a', 'o', + 0x04, + 0x00, 0x0d, + 0x01, 0x00, 0xbc, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x00, 0x00, 0x00, + 0x55, 0x2f }; static const unsigned char upek2020_init_4[] = { -'C', 'i', 'a', 'o', -0x00, -0x00, 0x07, -0x28, 0x04, 0x00, 0x00, 0x00, 0x06, 0x04, -0xc0, 0xd6 + 'C', 'i', 'a', 'o', + 0x00, + 0x00, 0x07, + 0x28, 0x04, 0x00, 0x00, 0x00, 0x06, 0x04, + 0xc0, 0xd6 }; static const unsigned char upek2020_deinit[] = { -'C', 'i', 'a', 'o', -0x07, -0x00, 0x01, -0x01, -0x3d, -0x72 + 'C', 'i', 'a', 'o', + 0x07, + 0x00, 0x01, + 0x01, + 0x3d, + 0x72 }; static const unsigned char upek2020_init_capture[] = { -'C', 'i', 'a', 'o', -0x00, -0x00, 0x0e, /* Seq = 7, len = 0x00e */ -0x28, /* CMD = 0x28 */ -0x0b, 0x00, /* Inner len = 0x000b */ -0x00, 0x00, -0x0e, /* SUBCMD = 0x0e */ -0x02, -0xfe, 0xff, 0xff, 0xff, /* timeout = -2 = 0xfffffffe = infinite time */ -0x02, -0x00, /* Wait for acceptable finger */ -0x02, -0x14, 0x9a /* CRC */ + 'C', 'i', 'a', 'o', + 0x00, + 0x00, 0x0e, /* Seq = 7, len = 0x00e */ + 0x28, /* CMD = 0x28 */ + 0x0b, 0x00, /* Inner len = 0x000b */ + 0x00, 0x00, + 0x0e, /* SUBCMD = 0x0e */ + 0x02, + 0xfe, 0xff, 0xff, 0xff, /* timeout = -2 = 0xfffffffe = infinite time */ + 0x02, + 0x00, /* Wait for acceptable finger */ + 0x02, + 0x14, 0x9a /* CRC */ }; #if 0 static const unsigned char finger_status[] = { -'C', 'i', 'a', 'o', -0x00, -0x70, 0x14, /* Seq = 7, len = 0x014 */ -0x28, /* CMD = 0x28 */ -0x11, 0x00, /* Inner len = 0x0011 */ -0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, -0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, -0x26, 0x03, /* CRC */ -0x00, 0x00, 0x00, /* Rest is garbage */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 'C', 'i', 'a', 'o', + 0x00, + 0x70, 0x14, /* Seq = 7, len = 0x014 */ + 0x28, /* CMD = 0x28 */ + 0x11, 0x00, /* Inner len = 0x0011 */ + 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, + 0x26, 0x03, /* CRC */ + 0x00, 0x00, 0x00, /* Rest is garbage */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #endif static const unsigned char upek2020_ack_00_28[] = { -'C', 'i', 'a', 'o', -0x00, -0x80, 0x08, /* Seq = 8, len = 0x008 */ -0x28, /* CMD = 0x28 */ -0x05, 0x00, /* Inner len = 0x0005 */ -0x00, 0x00, 0x00, 0x30, 0x01, -0x6a, 0xc4 /* CRC */ + 'C', 'i', 'a', 'o', + 0x00, + 0x80, 0x08, /* Seq = 8, len = 0x008 */ + 0x28, /* CMD = 0x28 */ + 0x05, 0x00, /* Inner len = 0x0005 */ + 0x00, 0x00, 0x00, 0x30, 0x01, + 0x6a, 0xc4 /* CRC */ }; #if 0 /* No seq should be tracked here */ static const unsigned char got_finger[] = { -'C', 'i', 'a', 'o', -0x08, -0x00, 0x00, /* Seq = 0, len = 0x000 */ -0xa1, 0xa9, /* CRC */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Rest is garbage */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 'C', 'i', 'a', 'o', + 0x08, + 0x00, 0x00, /* Seq = 0, len = 0x000 */ + 0xa1, 0xa9, /* CRC */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Rest is garbage */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #endif /* No seq should be put in there */ static const unsigned char upek2020_ack_08[] = { -'C', 'i', 'a', 'o', -0x09, -0x00, 0x00, /* Seq = 0, len = 0x0 */ -0x91, 0x9e /* CRC */ + 'C', 'i', 'a', 'o', + 0x09, + 0x00, 0x00, /* Seq = 0, len = 0x0 */ + 0x91, 0x9e /* CRC */ }; static const unsigned char upek2020_ack_frame[] = { -'C', 'i', 'a', 'o', -0x00, -0x50, 0x01, /* Seq = 5, len = 0x001 */ -0x30, -0xac, 0x5b /* CRC */ + 'C', 'i', 'a', 'o', + 0x00, + 0x50, 0x01, /* Seq = 5, len = 0x001 */ + 0x30, + 0xac, 0x5b /* CRC */ }; #endif diff --git a/libfprint/drivers/upekts.c b/libfprint/drivers/upekts.c index 476ef34c..24269077 100644 --- a/libfprint/drivers/upekts.c +++ b/libfprint/drivers/upekts.c @@ -28,32 +28,36 @@ #define FP_COMPONENT "upekts" #include "drivers_api.h" -#include "fpi-async.h" #include "upek_proto.h" -#define EP_IN (1 | LIBUSB_ENDPOINT_IN) -#define EP_OUT (2 | LIBUSB_ENDPOINT_OUT) +#define EP_IN (1 | FPI_USB_ENDPOINT_IN) +#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT) #define TIMEOUT 5000 #define MSG_READ_BUF_SIZE 0x40 #define MAX_DATA_IN_READ_BUF (MSG_READ_BUF_SIZE - 9) -struct upekts_dev { - gboolean enroll_passed; - gboolean first_verify_iteration; - gboolean stop_verify; - uint8_t seq; /* FIXME: improve/automate seq handling */ +struct _FpiDeviceUpekts +{ + FpDevice parent; + + gboolean enroll_passed; + gint enroll_stage; + gboolean first_verify_iteration; + guint8 seq; /* FIXME: improve/automate seq handling */ }; - +G_DECLARE_FINAL_TYPE (FpiDeviceUpekts, fpi_device_upekts, FPI, + DEVICE_UPEKTS, FpDevice); +G_DEFINE_TYPE (FpiDeviceUpekts, fpi_device_upekts, FP_TYPE_DEVICE); /* * MESSAGE FORMAT - * + * * Messages to and from the device have the same format. * * Byte-wise: - * 'C' 'i' 'a' 'o' A B L C1 C2 + * 'C' 'i' 'a' 'o' A B L C1 C2 * * Ciao prefixes all messages. The rightmost 4 bits of B become the uppermost * 4 bits of L, and when combined with the lower 8 bits listed as 'L', L is @@ -66,7 +70,7 @@ struct upekts_dev { * with B=0 and A incremented. * * When the driver sends a command to the device, A=0 and B is used as a - * sequence counter. It starts at 0, increments by 0x10 on each command, and + * sequence counter. It starts at 0, increments by 0x10 on each command, and * wraps around. * After each command is sent, the device responds with another message * indicating completion of the command including any data that was requested. @@ -75,7 +79,7 @@ struct upekts_dev { * When the driver is sending commands as above, and when the device is * responding, the seems to follow this structure: * - * 28 L1 L2 0 0 S + * 28 L1 L2 0 0 S * * Where the length of is L-3, and S is some kind of subcommand * code. L1 is the least significant bits of L, L2 is the most significant. In @@ -87,1350 +91,1490 @@ struct upekts_dev { #define CMD_SEQ_INCREMENT 0x10 -static struct libusb_transfer *alloc_send_cmd_transfer(struct fp_dev *dev, - unsigned char seq_a, unsigned char seq_b, const unsigned char *data, - uint16_t len, libusb_transfer_cb_fn callback, void *user_data) +static FpiUsbTransfer * +alloc_send_cmd_transfer (FpDevice *dev, + unsigned char seq_a, + unsigned char seq_b, + const unsigned char *data, + guint16 len) { - struct libusb_transfer *transfer = fpi_usb_alloc(); - uint16_t crc; - const char *ciao = "Ciao"; + FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev); + guint16 crc; + const char *ciao = "Ciao"; - /* 9 bytes extra for: 4 byte 'Ciao', 1 byte A, 1 byte B | lenHI, - * 1 byte lenLO, 2 byte CRC */ - size_t urblen = len + 9; - unsigned char *buf; + /* 9 bytes extra for: 4 byte 'Ciao', 1 byte A, 1 byte B | lenHI, + * 1 byte lenLO, 2 byte CRC */ + size_t urblen = len + 9; - if (!data && len > 0) { - fp_err("len>0 but no data?"); - return NULL; - } + if (!data && len > 0) + { + fp_err ("len>0 but no data?"); + return NULL; + } - buf = g_malloc(urblen); + fpi_usb_transfer_fill_bulk (transfer, EP_OUT, urblen); - /* Write header */ - memcpy(buf, ciao, strlen(ciao)); - len = GUINT16_TO_LE(len); - buf[4] = seq_a; - buf[5] = seq_b | ((len & 0xf00) >> 8); - buf[6] = len & 0x00ff; + /* Write header */ + memcpy (transfer->buffer, ciao, strlen (ciao)); + transfer->buffer[4] = seq_a; + transfer->buffer[5] = seq_b | ((len & 0xf00) >> 8); + transfer->buffer[6] = len & 0x00ff; - /* Copy data */ - if (data) - memcpy(buf + 7, data, len); + /* Copy data */ + if (data) + memcpy (transfer->buffer + 7, data, len); - /* Append CRC */ - crc = GUINT16_TO_BE(udf_crc(buf + 4, urblen - 6)); - buf[urblen - 2] = crc >> 8; - buf[urblen - 1] = crc & 0xff; + /* Append CRC */ + crc = udf_crc (transfer->buffer + 4, urblen - 6); + transfer->buffer[urblen - 2] = crc & 0xff; + transfer->buffer[urblen - 1] = crc >> 8; - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(dev), EP_OUT, buf, urblen, - callback, user_data, TIMEOUT); - return transfer; + return transfer; } -static struct libusb_transfer *alloc_send_cmd28_transfer(struct fp_dev *dev, - unsigned char subcmd, const unsigned char *data, uint16_t innerlen, - libusb_transfer_cb_fn callback, void *user_data) +static FpiUsbTransfer * +alloc_send_cmd28_transfer (FpDevice *dev, + unsigned char subcmd, + const unsigned char *data, + guint16 innerlen) { - uint16_t _innerlen = innerlen; - size_t len = innerlen + 6; - unsigned char *buf = g_malloc0(len); - struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); - uint8_t seq = upekdev->seq + CMD_SEQ_INCREMENT; - struct libusb_transfer *ret; + guint16 _innerlen = innerlen; + size_t len = innerlen + 6; + unsigned char *buf = g_malloc0 (len); + FpiDeviceUpekts *upekdev = FPI_DEVICE_UPEKTS (dev); + guint8 seq = upekdev->seq + CMD_SEQ_INCREMENT; + FpiUsbTransfer *ret; - fp_dbg("seq=%02x subcmd=%02x with %d bytes of data", seq, subcmd, innerlen); + fp_dbg ("seq=%02x subcmd=%02x with %d bytes of data", seq, subcmd, innerlen); - _innerlen = GUINT16_TO_LE(innerlen + 3); - buf[0] = 0x28; - buf[1] = _innerlen & 0x00ff; - buf[2] = (_innerlen & 0xff00) >> 8; - buf[5] = subcmd; - memcpy(buf + 6, data, innerlen); + _innerlen = innerlen + 3; + buf[0] = 0x28; + buf[1] = _innerlen & 0x00ff; + buf[2] = (_innerlen & 0xff00) >> 8; + buf[5] = subcmd; + memcpy (buf + 6, data, innerlen); - ret = alloc_send_cmd_transfer(dev, 0, seq, buf, len, callback, user_data); - upekdev->seq = seq; + ret = alloc_send_cmd_transfer (dev, 0, seq, buf, len); + upekdev->seq = seq; - g_free(buf); - return ret; + g_free (buf); + return ret; } -static struct libusb_transfer *alloc_send_cmdresponse_transfer( - struct fp_dev *dev, unsigned char seq, const unsigned char *data, - uint8_t len, libusb_transfer_cb_fn callback, void *user_data) +static FpiUsbTransfer * +alloc_send_cmdresponse_transfer (FpDevice *dev, + unsigned char seq, + const unsigned char *data, + guint8 len) { - fp_dbg("seq=%02x len=%d", seq, len); - return alloc_send_cmd_transfer(dev, seq, 0, data, len, callback, user_data); + fp_dbg ("seq=%02x len=%d", seq, len); + return alloc_send_cmd_transfer (dev, seq, 0, data, len); } -enum read_msg_status { - READ_MSG_ERROR, - READ_MSG_CMD, - READ_MSG_RESPONSE, +enum read_msg_type { + READ_MSG_CMD, + READ_MSG_RESPONSE, }; -typedef void (*read_msg_cb_fn)(struct fp_dev *dev, enum read_msg_status status, - uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len, - void *user_data); +typedef void (*read_msg_cb_fn)(FpDevice *dev, + enum read_msg_type type, + guint8 seq, + unsigned char subcmd, + unsigned char *data, + size_t data_len, + void *user_data, + GError *error); -struct read_msg_data { - struct fp_dev *dev; - read_msg_cb_fn callback; - void *user_data; +struct read_msg_data +{ + gssize buflen; + guint8 *buffer; + read_msg_cb_fn callback; + void *user_data; }; -static int __read_msg_async(struct read_msg_data *udata); +static void __read_msg_async (FpDevice *dev, + struct read_msg_data *udata); -#define READ_MSG_DATA_CB_ERR(udata) (udata)->callback((udata)->dev, \ - READ_MSG_ERROR, 0, 0, NULL, 0, (udata)->user_data) +#define READ_MSG_DATA_CB_ERR(dev, udata, error) (udata)->callback (dev, \ + READ_MSG_CMD, 0, 0, NULL, 0, (udata)->user_data, error) -static void busy_ack_sent_cb(struct libusb_transfer *transfer) +static void +busy_ack_sent_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - struct read_msg_data *udata = transfer->user_data; + struct read_msg_data *udata = user_data; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED || - transfer->length != transfer->actual_length) { - READ_MSG_DATA_CB_ERR(udata); - g_free(udata); - } else { - int r = __read_msg_async(udata); - if (r < 0) { - READ_MSG_DATA_CB_ERR(udata); - g_free(udata); - } - } - libusb_free_transfer(transfer); + if (error) + { + READ_MSG_DATA_CB_ERR (device, udata, error); + g_free (udata->buffer); + g_free (udata); + } + else + { + __read_msg_async (device, udata); + } } -static int busy_ack_retry_read(struct read_msg_data *udata) +static void +busy_ack_retry_read (FpDevice *device, struct read_msg_data *udata) { - struct libusb_transfer *transfer; - int r; + FpiUsbTransfer *transfer; - transfer = alloc_send_cmdresponse_transfer(udata->dev, 0x09, NULL, 0, - busy_ack_sent_cb, udata); - if (!transfer) - return -ENOMEM; + transfer = alloc_send_cmdresponse_transfer (device, 0x09, NULL, 0); + transfer->short_is_error = TRUE; - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(transfer->buffer); - libusb_free_transfer(transfer); - } - return r; + fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, busy_ack_sent_cb, udata); + fpi_usb_transfer_unref (transfer); } /* Returns 0 if message was handled, 1 if it was a device-busy message, and * negative on error. */ -static int __handle_incoming_msg(struct read_msg_data *udata, - unsigned char *buf) +static void +__handle_incoming_msg (FpDevice *device, + struct read_msg_data *udata) { - uint16_t len = GUINT16_FROM_LE(((buf[5] & 0xf) << 8) | buf[6]); - uint16_t computed_crc = udf_crc(buf + 4, len + 3); - uint16_t msg_crc = GUINT16_FROM_LE((buf[len + 8] << 8) | buf[len + 7]); - unsigned char *retdata = NULL; - unsigned char code_a, code_b; + GError *error = NULL; + guint8 *buf = udata->buffer; + guint16 len = ((buf[5] & 0xf) << 8) | buf[6]; + guint16 computed_crc = udf_crc (buf + 4, len + 3); + guint16 msg_crc = (buf[len + 8] << 8) | buf[len + 7]; + unsigned char *retdata = NULL; + unsigned char code_a, code_b; - if (computed_crc != msg_crc) { - fp_err("CRC failed, got %04x expected %04x", msg_crc, computed_crc); - return -1; - } + if (computed_crc != msg_crc) + { + fp_err ("CRC failed, got %04x expected %04x", msg_crc, computed_crc); + error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "CRC check on message failed"); + goto err; + } - code_a = buf[4]; - code_b = buf[5] & 0xf0; - len = GUINT16_FROM_LE(((buf[5] & 0xf) << 8) | buf[6]); - fp_dbg("A=%02x B=%02x len=%d", code_a, code_b, len); + code_a = buf[4]; + code_b = buf[5] & 0xf0; + len = ((buf[5] & 0xf) << 8) | buf[6]; + fp_dbg ("A=%02x B=%02x len=%d", code_a, code_b, len); - if (code_a && !code_b) { - /* device sends command to driver */ - fp_dbg("cmd %x from device to driver", code_a); + if (code_a && !code_b) + { + /* device sends command to driver */ + fp_dbg ("cmd %x from device to driver", code_a); - if (code_a == 0x08) { - int r; - fp_dbg("device busy, send busy-ack"); - r = busy_ack_retry_read(udata); - return (r < 0) ? r : 1; - } + if (code_a == 0x08) + { + fp_dbg ("device busy, send busy-ack"); + busy_ack_retry_read (device, udata); + return; + } - if (len > 0) { - retdata = g_malloc(len); - memcpy(retdata, buf + 7, len); - } - udata->callback(udata->dev, READ_MSG_CMD, code_a, 0, retdata, len, - udata->user_data); - g_free(retdata); - } else if (!code_a) { - /* device sends response to a previously executed command */ - unsigned char *innerbuf = buf + 7; - unsigned char _subcmd; - uint16_t innerlen; + if (len > 0) + { + retdata = g_malloc (len); + memcpy (retdata, buf + 7, len); + } + udata->callback (device, READ_MSG_CMD, code_a, 0, retdata, len, + udata->user_data, NULL); + goto done; + } + else if (!code_a) + { + /* device sends response to a previously executed command */ + unsigned char *innerbuf = buf + 7; + unsigned char _subcmd; + guint16 innerlen; - if (len < 6) { - fp_err("cmd response too short (%d)", len); - return -1; - } - if (innerbuf[0] != 0x28) { - fp_err("cmd response without 28 byte?"); - return -1; - } + if (len < 6) + { + fp_warn ("cmd response too short (%d)", len); + error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "CMD response too short"); + goto err; + } + if (innerbuf[0] != 0x28) + { + fp_warn ("cmd response without 28 byte?"); + error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "CMD response without 0x28 byte"); + goto err; + } - /* not really sure what these 2 bytes are. on most people's hardware, - * these bytes are always 0. However, Alon Bar-Lev's hardware gives - * 0xfb 0xff during the READ28_OB initsm stage. so don't error out - * if they are different... */ - if (innerbuf[3] || innerbuf[4]) - fp_dbg("non-zero bytes in cmd response"); + /* not really sure what these 2 bytes are. on most people's hardware, + * these bytes are always 0. However, Alon Bar-Lev's hardware gives + * 0xfb 0xff during the READ28_OB initsm stage. so don't error out + * if they are different... */ + if (innerbuf[3] || innerbuf[4]) + fp_dbg ("non-zero bytes in cmd response"); - innerlen = innerbuf[1] | (innerbuf[2] << 8); - innerlen = GUINT16_FROM_LE(innerlen) - 3; - _subcmd = innerbuf[5]; - fp_dbg("device responds to subcmd %x with %d bytes", _subcmd, innerlen); - if (innerlen > 0) { - retdata = g_malloc(innerlen); - memcpy(retdata, innerbuf + 6, innerlen); - } - udata->callback(udata->dev, READ_MSG_RESPONSE, code_b, _subcmd, - retdata, innerlen, udata->user_data); - g_free(retdata); - } else { - fp_err("don't know how to handle this message"); - return -1; - } - return 0; -} - -static void read_msg_extend_cb(struct libusb_transfer *transfer) -{ - struct read_msg_data *udata = transfer->user_data; - unsigned char *buf = transfer->buffer - MSG_READ_BUF_SIZE; - int handle_result = 0; - - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fp_err("extended msg read failed, code %d", transfer->status); - goto err; - } - if (transfer->actual_length < transfer->length) { - fp_err("extended msg short read (%d/%d)", transfer->actual_length, - transfer->length); - goto err; - } - - handle_result = __handle_incoming_msg(udata, buf); - if (handle_result < 0) - goto err; - goto out; + innerlen = innerbuf[1] | (innerbuf[2] << 8); + innerlen = innerlen - 3; + _subcmd = innerbuf[5]; + fp_dbg ("device responds to subcmd %x with %d bytes", _subcmd, innerlen); + if (innerlen > 0) + { + retdata = g_malloc (innerlen); + memcpy (retdata, innerbuf + 6, innerlen); + } + udata->callback (device, READ_MSG_RESPONSE, code_b, _subcmd, + retdata, innerlen, udata->user_data, NULL); + g_free (retdata); + goto done; + } + else + { + fp_err ("don't know how to handle this message"); + error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Message cannot be processed"); + goto err; + } + g_assert_not_reached (); err: - READ_MSG_DATA_CB_ERR(udata); -out: - if (handle_result != 1) - g_free(udata); - g_free(buf); - libusb_free_transfer(transfer); + READ_MSG_DATA_CB_ERR (device, udata, error); +done: + g_free (udata->buffer); + g_free (udata); } -static void read_msg_cb(struct libusb_transfer *transfer) +static void +read_msg_extend_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - struct read_msg_data *udata = transfer->user_data; - unsigned char *data = transfer->buffer; - uint16_t len; - int handle_result = 0; + struct read_msg_data *udata = user_data; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fp_err("async msg read failed, code %d", transfer->status); - goto err; - } - if (transfer->actual_length < 9) { - fp_err("async msg read too short (%d)", transfer->actual_length); - goto err; - } + if (error) + { + fp_err ("extended msg read failed: %s", error->message); + READ_MSG_DATA_CB_ERR (device, udata, error); + g_free (udata->buffer); + g_free (udata); + return; + } - if (strncmp(data, "Ciao", 4) != 0) { - fp_err("no Ciao for you!!"); - goto err; - } + __handle_incoming_msg (device, udata); +} - len = GUINT16_FROM_LE(((data[5] & 0xf) << 8) | data[6]); - if (transfer->actual_length != MSG_READ_BUF_SIZE - && (len + 9) > transfer->actual_length) { - /* Check that the length claimed inside the message is in line with - * the amount of data that was transferred over USB. */ - fp_err("msg didn't include enough data, expected=%d recv=%d", - len + 9, transfer->actual_length); - goto err; - } +static void +read_msg_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) +{ + struct read_msg_data *udata = user_data; + guint16 len; - /* We use a 64 byte buffer for reading messages. However, sometimes - * messages are longer, in which case we have to do another USB bulk read - * to read the remainder. This is handled below. */ - if (len > MAX_DATA_IN_READ_BUF) { - int needed = len - MAX_DATA_IN_READ_BUF; - struct libusb_transfer *etransfer = fpi_usb_alloc(); - int r; + if (error) + { + fp_err ("async msg read failed: %s", error->message); + goto err; + } + if (transfer->actual_length < 9) + { + fp_err ("async msg read too short (%d)", + (gint) transfer->actual_length); + error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Packet from device was too short"); + goto err; + } - fp_dbg("didn't fit in buffer, need to extend by %d bytes", needed); - data = g_realloc((gpointer) data, MSG_READ_BUF_SIZE + needed); + if (strncmp (udata->buffer, "Ciao", 4) != 0) + { + fp_err ("no Ciao for you!!"); + error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Packet from device had incorrect header"); + goto err; + } - libusb_fill_bulk_transfer(etransfer, fpi_dev_get_usb_dev(udata->dev), EP_IN, - data + MSG_READ_BUF_SIZE, needed, read_msg_extend_cb, udata, - TIMEOUT); + len = ((udata->buffer[5] & 0xf) << 8) | udata->buffer[6]; + if (transfer->actual_length != MSG_READ_BUF_SIZE && + (len + 9) > transfer->actual_length) + { + /* Check that the length claimed inside the message is in line with + * the amount of data that was transferred over USB. */ + fp_err ("msg didn't include enough data, expected=%d recv=%d", + len + 9, (gint) transfer->actual_length); + error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Packet from device didn't include data"); + goto err; + } - r = libusb_submit_transfer(etransfer); - if (r < 0) { - fp_err("extended read submission failed"); - /* FIXME memory leak here? */ - goto err; - } - libusb_free_transfer(transfer); - return; - } + /* We use a 64 byte buffer for reading messages. However, sometimes + * messages are longer, in which case we have to do another USB bulk read + * to read the remainder. This is handled below. */ + if (len > MAX_DATA_IN_READ_BUF) + { + int needed = len - MAX_DATA_IN_READ_BUF; + FpiUsbTransfer *etransfer = fpi_usb_transfer_new (device); - handle_result = __handle_incoming_msg(udata, data); - if (handle_result < 0) - goto err; - goto out; + fp_dbg ("didn't fit in buffer, need to extend by %d bytes", needed); + udata->buffer = g_realloc ((gpointer) udata->buffer, len); + udata->buflen = len; + fpi_usb_transfer_fill_bulk_full (etransfer, EP_IN, + udata->buffer + MSG_READ_BUF_SIZE, + needed, NULL); + etransfer->short_is_error = TRUE; + fpi_usb_transfer_submit (etransfer, TIMEOUT, + NULL, + read_msg_extend_cb, udata); + fpi_usb_transfer_unref (etransfer); + return; + } + + __handle_incoming_msg (device, udata); + + return; err: - READ_MSG_DATA_CB_ERR(udata); -out: - libusb_free_transfer(transfer); - if (handle_result != 1) - g_free(udata); - g_free(data); + READ_MSG_DATA_CB_ERR (device, udata, error); + g_free (udata->buffer); + g_free (udata); } -static int __read_msg_async(struct read_msg_data *udata) +static void +__read_msg_async (FpDevice *device, struct read_msg_data *udata) { - unsigned char *buf = g_malloc(MSG_READ_BUF_SIZE); - struct libusb_transfer *transfer = fpi_usb_alloc(); - int r; + FpiUsbTransfer *transfer = fpi_usb_transfer_new (device); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(udata->dev), EP_IN, buf, - MSG_READ_BUF_SIZE, read_msg_cb, udata, TIMEOUT); - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(buf); - libusb_free_transfer(transfer); - } + if (udata->buflen != MSG_READ_BUF_SIZE) + { + udata->buffer = g_realloc (udata->buffer, MSG_READ_BUF_SIZE); + udata->buflen = MSG_READ_BUF_SIZE; + } - return r; + fpi_usb_transfer_fill_bulk_full (transfer, EP_IN, udata->buffer, udata->buflen, NULL); + fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, read_msg_cb, udata); + fpi_usb_transfer_unref (transfer); } -static int read_msg_async(struct fp_dev *dev, read_msg_cb_fn callback, - void *user_data) +static void +read_msg_async (FpDevice *dev, + read_msg_cb_fn callback, + void *user_data) { - struct read_msg_data *udata = g_malloc(sizeof(*udata)); - int r; + struct read_msg_data *udata = g_new0 (struct read_msg_data, 1); - udata->dev = dev; - udata->callback = callback; - udata->user_data = user_data; - r = __read_msg_async(udata); - if (r) - g_free(udata); - return r; + udata->buflen = 0; + udata->buffer = NULL; + udata->callback = callback; + udata->user_data = user_data; + __read_msg_async (dev, udata); } static const unsigned char init_resp03[] = { - 0x01, 0x00, 0xe8, 0x03, 0x00, 0x00, 0xff, 0x07 + 0x01, 0x00, 0xe8, 0x03, 0x00, 0x00, 0xff, 0x07 }; static const unsigned char init28_08[] = { - 0x04, 0x83, 0x00, 0x2c, 0x22, 0x23, 0x97, 0xc9, 0xa7, 0x15, 0xa0, 0x8a, - 0xab, 0x3c, 0xd0, 0xbf, 0xdb, 0xf3, 0x92, 0x6f, 0xae, 0x3b, 0x1e, 0x44, - 0xc4 + 0x04, 0x83, 0x00, 0x2c, 0x22, 0x23, 0x97, 0xc9, 0xa7, 0x15, 0xa0, 0x8a, + 0xab, 0x3c, 0xd0, 0xbf, 0xdb, 0xf3, 0x92, 0x6f, 0xae, 0x3b, 0x1e, 0x44, + 0xc4 }; static const unsigned char init28_0c[] = { - 0x04, 0x03, 0x00, 0x00, 0x00 + 0x04, 0x03, 0x00, 0x00, 0x00 }; static const unsigned char init28_0b[] = { - 0x04, 0x03, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, 0x64, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0a, - 0x00, 0x64, 0x00, 0xf4, 0x01, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00 + 0x04, 0x03, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, 0x64, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0a, + 0x00, 0x64, 0x00, 0xf4, 0x01, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00 }; /* device initialisation state machine */ enum initsm_states { - WRITE_CTRL400 = 0, - READ_MSG03, - SEND_RESP03, - READ_MSG05, - SEND28_06, - READ28_06, - SEND28_07, - READ28_07, - SEND28_08, - READ28_08, - SEND28_0C, - READ28_0C, - SEND28_0B, - READ28_0B, - INITSM_NUM_STATES, + WRITE_CTRL400 = 0, + READ_MSG03, + SEND_RESP03, + READ_MSG05, + SEND28_06, + READ28_06, + SEND28_07, + READ28_07, + SEND28_08, + READ28_08, + SEND28_0C, + READ28_0C, + SEND28_0B, + READ28_0B, + INITSM_NUM_STATES, }; static void -initsm_read_msg_response_cb(fpi_ssm *ssm, - struct fp_dev *dev, - enum read_msg_status status, - uint8_t seq, - unsigned char expect_subcmd, - unsigned char subcmd) +initsm_read_msg_response_cb (FpiSsm *ssm, + FpDevice *dev, + enum read_msg_type type, + guint8 seq, + unsigned char expect_subcmd, + unsigned char subcmd, + GError *error) { - struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); + FpiDeviceUpekts *upekdev = FPI_DEVICE_UPEKTS (dev); - if (status != READ_MSG_RESPONSE) { - fp_err("expected response, got %d seq=%x in state %d", status, seq, - fpi_ssm_get_cur_state(ssm)); - fpi_ssm_mark_failed(ssm, -1); - } else if (subcmd != expect_subcmd) { - fp_warn("expected response to subcmd 0x%02x, got response to %02x in " - "state %d", expect_subcmd, subcmd, fpi_ssm_get_cur_state(ssm)); - fpi_ssm_mark_failed(ssm, -1); - } 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, -1); - } else { - fp_dbg("state %d completed", fpi_ssm_get_cur_state(ssm)); - fpi_ssm_next_state(ssm); - } -} - -static void read28_0b_cb(struct fp_dev *dev, enum read_msg_status status, - uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len, - void *user_data) -{ - initsm_read_msg_response_cb((fpi_ssm *) user_data, dev, status, seq, - 0x0b, subcmd); -} - -static void read28_0c_cb(struct fp_dev *dev, enum read_msg_status status, - uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len, - void *user_data) -{ - initsm_read_msg_response_cb((fpi_ssm *) user_data, dev, status, seq, - 0x0c, subcmd); -} - -static void read28_08_cb(struct fp_dev *dev, enum read_msg_status status, - uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len, - void *user_data) -{ - initsm_read_msg_response_cb((fpi_ssm *) user_data, dev, status, seq, - 0x08, subcmd); -} - -static void read28_07_cb(struct fp_dev *dev, enum read_msg_status status, - uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len, - void *user_data) -{ - initsm_read_msg_response_cb((fpi_ssm *) user_data, dev, status, seq, - 0x07, subcmd); -} - -static void read28_06_cb(struct fp_dev *dev, enum read_msg_status status, - uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len, - void *user_data) -{ - initsm_read_msg_response_cb((fpi_ssm *) user_data, dev, status, seq, - 0x06, subcmd); + if (error) + { + fpi_ssm_mark_failed (ssm, error); + } + else if (type != READ_MSG_RESPONSE) + { + fp_err ("expected response, got %d seq=%x in state %d", type, seq, + fpi_ssm_get_cur_state (ssm)); + fpi_ssm_mark_failed (ssm, + fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Unexpected message type")); + } + else if (seq != upekdev->seq) + { + fp_warn ("expected response to subcmd 0x%02x, got response to %02x in " + "state %d", expect_subcmd, subcmd, + fpi_ssm_get_cur_state (ssm)); + fpi_ssm_mark_failed (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); + } } static void -initsm_read_msg_cmd_cb(fpi_ssm *ssm, - struct fp_dev *dev, - enum read_msg_status status, - uint8_t expect_seq, - uint8_t seq) +read28_0b_cb (FpDevice *dev, enum read_msg_type type, + guint8 seq, unsigned char subcmd, + unsigned char *data, size_t data_len, + void *user_data, GError *error) { - struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); - - if (status == READ_MSG_ERROR) { - fpi_ssm_mark_failed(ssm, -1); - return; - } else if (status != READ_MSG_CMD) { - fp_err("expected command, got %d seq=%x in state %d", status, seq, - fpi_ssm_get_cur_state(ssm)); - fpi_ssm_mark_failed(ssm, -1); - return; - } - upekdev->seq = seq; - if (seq != expect_seq) { - fp_err("expected seq=%x, got %x in state %d", expect_seq, seq, - fpi_ssm_get_cur_state(ssm)); - fpi_ssm_mark_failed(ssm, -1); - return; - } - - fpi_ssm_next_state(ssm); -} - -static void read_msg05_cb(struct fp_dev *dev, enum read_msg_status status, - uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len, - void *user_data) -{ - initsm_read_msg_cmd_cb((fpi_ssm *) user_data, dev, status, 5, seq); -} - -static void read_msg03_cb(struct fp_dev *dev, enum read_msg_status status, - uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len, - void *user_data) -{ - initsm_read_msg_cmd_cb((fpi_ssm *) user_data, dev, status, 3, seq); -} - -static void ctrl400_cb(struct libusb_transfer *transfer) -{ - fpi_ssm *ssm = transfer->user_data; - /* FIXME check length? */ - if (transfer->status == LIBUSB_TRANSFER_COMPLETED) - fpi_ssm_next_state(ssm); - else - fpi_ssm_mark_failed(ssm, -1); - g_free(transfer->buffer); - libusb_free_transfer(transfer); + initsm_read_msg_response_cb ((FpiSsm *) user_data, dev, type, seq, + 0x0b, subcmd, error); } static void -initsm_read_msg_handler(fpi_ssm *ssm, - struct fp_dev *dev, - read_msg_cb_fn callback) +read28_0c_cb (FpDevice *dev, enum read_msg_type type, + guint8 seq, unsigned char subcmd, + unsigned char *data, size_t data_len, + void *user_data, GError *error) { - int r = read_msg_async(dev, callback, ssm); - if (r < 0) { - fp_err("async read msg failed in state %d", fpi_ssm_get_cur_state(ssm)); - fpi_ssm_mark_failed(ssm, r); - } -} - -static void initsm_send_msg_cb(struct libusb_transfer *transfer) -{ - fpi_ssm *ssm = transfer->user_data; - if (transfer->status == LIBUSB_TRANSFER_COMPLETED - && transfer->length == transfer->actual_length) { - fp_dbg("state %d completed", fpi_ssm_get_cur_state(ssm)); - fpi_ssm_next_state(ssm); - } else { - fp_err("failed, state=%d rqlength=%d actual_length=%d", fpi_ssm_get_cur_state(ssm), - transfer->length, transfer->actual_length); - fpi_ssm_mark_failed(ssm, -1); - } - libusb_free_transfer(transfer); + initsm_read_msg_response_cb ((FpiSsm *) user_data, dev, type, seq, + 0x0c, subcmd, error); } static void -initsm_send_msg28_handler(fpi_ssm *ssm, - struct fp_dev *dev, - unsigned char subcmd, - const unsigned char *data, - uint16_t innerlen) +read28_08_cb (FpDevice *dev, enum read_msg_type type, + guint8 seq, unsigned char subcmd, + unsigned char *data, size_t data_len, + void *user_data, GError *error) { - struct libusb_transfer *transfer; - int r; - - transfer = alloc_send_cmd28_transfer(dev, subcmd, data, innerlen, - initsm_send_msg_cb, ssm); - if (!transfer) { - fpi_ssm_mark_failed(ssm, -ENOMEM); - return; - } - - r = libusb_submit_transfer(transfer); - if (r < 0) { - fp_err("urb submission failed error %d in state %d", r, fpi_ssm_get_cur_state(ssm)); - g_free(transfer->buffer); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, -EIO); - } + initsm_read_msg_response_cb ((FpiSsm *) user_data, dev, type, seq, + 0x08, subcmd, error); } -static void initsm_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) +static void +read28_07_cb (FpDevice *dev, enum read_msg_type type, + guint8 seq, unsigned char subcmd, + unsigned char *data, size_t data_len, + void *user_data, GError *error) { - struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); - struct libusb_transfer *transfer; - int r; - - switch (fpi_ssm_get_cur_state(ssm)) { - case WRITE_CTRL400: ; - unsigned char *data; - - transfer = fpi_usb_alloc(); - data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1); - libusb_fill_control_setup(data, - LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, 0x0c, 0x100, 0x0400, 1); - libusb_fill_control_transfer(transfer, fpi_dev_get_usb_dev(dev), data, - ctrl400_cb, ssm, TIMEOUT); - - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(data); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } - break; - case READ_MSG03: - initsm_read_msg_handler(ssm, dev, read_msg03_cb); - break; - case SEND_RESP03: ; - transfer = alloc_send_cmdresponse_transfer(dev, ++upekdev->seq, - init_resp03, sizeof(init_resp03), initsm_send_msg_cb, ssm); - if (!transfer) { - fpi_ssm_mark_failed(ssm, -ENOMEM); - break; - } - - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(transfer->buffer); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } - break; - case READ_MSG05: - initsm_read_msg_handler(ssm, dev, read_msg05_cb); - break; - case SEND28_06: ; - unsigned char dummy28_06 = 0x04; - upekdev->seq = 0xf0; - initsm_send_msg28_handler(ssm, dev, 0x06, &dummy28_06, 1); - break; - case READ28_06: - initsm_read_msg_handler(ssm, dev, read28_06_cb); - break; - case SEND28_07: ; - unsigned char dummy28_07 = 0x04; - initsm_send_msg28_handler(ssm, dev, 0x07, &dummy28_07, 1); - break; - case READ28_07: - initsm_read_msg_handler(ssm, dev, read28_07_cb); - break; - case SEND28_08: - initsm_send_msg28_handler(ssm, dev, 0x08, init28_08, sizeof(init28_08)); - break; - case READ28_08: - initsm_read_msg_handler(ssm, dev, read28_08_cb); - break; - case SEND28_0C: - initsm_send_msg28_handler(ssm, dev, 0x0c, init28_0c, sizeof(init28_0c)); - break; - case READ28_0C: - initsm_read_msg_handler(ssm, dev, read28_0c_cb); - break; - case SEND28_0B: - initsm_send_msg28_handler(ssm, dev, 0x0b, init28_0b, sizeof(init28_0b)); - break; - case READ28_0B: - initsm_read_msg_handler(ssm, dev, read28_0b_cb); - break; - } + initsm_read_msg_response_cb ((FpiSsm *) user_data, dev, type, seq, + 0x07, subcmd, error); } -static fpi_ssm *initsm_new(struct fp_dev *dev, - void *user_data) +static void +read28_06_cb (FpDevice *dev, enum read_msg_type type, + guint8 seq, unsigned char subcmd, + unsigned char *data, size_t data_len, + void *user_data, GError *error) { - return fpi_ssm_new(dev, initsm_run_state, INITSM_NUM_STATES, user_data); + initsm_read_msg_response_cb ((FpiSsm *) user_data, dev, type, seq, + 0x06, subcmd, error); +} + +static void +initsm_read_msg_cmd_cb (FpiSsm *ssm, + FpDevice *dev, + enum read_msg_type type, + guint8 seq, + guint8 expected_seq, + GError *error) +{ + FpiDeviceUpekts *upekdev = FPI_DEVICE_UPEKTS (dev); + + if (error) + { + fpi_ssm_mark_failed (ssm, error); + return; + } + else if (type != READ_MSG_CMD) + { + fp_err ("expected command, got %d seq=%x in state %d", type, seq, + fpi_ssm_get_cur_state (ssm)); + fpi_ssm_mark_failed (ssm, + fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Expected command but got response")); + return; + } + upekdev->seq = seq; + if (seq != expected_seq) + { + fp_err ("expected seq=%x, got %x in state %d", expected_seq, seq, + fpi_ssm_get_cur_state (ssm)); + fpi_ssm_mark_failed (ssm, + fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Got unexpected sequence number")); + return; + } + + fpi_ssm_next_state (ssm); +} + +static void +read_msg05_cb (FpDevice *dev, enum read_msg_type type, + guint8 seq, unsigned char subcmd, + unsigned char *data, size_t data_len, + void *user_data, GError *error) +{ + initsm_read_msg_cmd_cb ((FpiSsm *) user_data, dev, type, 5, seq, error); +} + +static void +read_msg03_cb (FpDevice *dev, enum read_msg_type type, + guint8 seq, unsigned char subcmd, + unsigned char *data, size_t data_len, + void *user_data, GError *error) +{ + initsm_read_msg_cmd_cb ((FpiSsm *) user_data, dev, type, 3, seq, error); +} + +static void +initsm_read_msg_handler (FpiSsm *ssm, + FpDevice *dev, + read_msg_cb_fn callback) +{ + read_msg_async (dev, callback, ssm); +} + +static void +initsm_send_msg28_handler (FpiSsm *ssm, + FpDevice *dev, + unsigned char subcmd, + const unsigned char *data, + guint16 innerlen) +{ + FpiUsbTransfer *transfer; + + transfer = alloc_send_cmd28_transfer (dev, subcmd, data, innerlen); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL); + fpi_usb_transfer_unref (transfer); +} + +static void +initsm_run_state (FpiSsm *ssm, FpDevice *dev) +{ + FpiDeviceUpekts *upekdev = FPI_DEVICE_UPEKTS (dev); + FpiUsbTransfer *transfer; + + switch (fpi_ssm_get_cur_state (ssm)) + { + case WRITE_CTRL400:; + transfer = fpi_usb_transfer_new (dev); + fpi_usb_transfer_fill_control (transfer, + G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE, + G_USB_DEVICE_REQUEST_TYPE_VENDOR, + G_USB_DEVICE_RECIPIENT_DEVICE, + 0x0c, 0x100, 0x0400, 1); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL); + fpi_usb_transfer_unref (transfer); + break; + + case READ_MSG03: + initsm_read_msg_handler (ssm, dev, read_msg03_cb); + break; + + case SEND_RESP03:; + transfer = alloc_send_cmd28_transfer (dev, ++upekdev->seq, init_resp03, sizeof (init_resp03)); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL); + fpi_usb_transfer_unref (transfer); + break; + + case READ_MSG05: + initsm_read_msg_handler (ssm, dev, read_msg05_cb); + break; + + case SEND28_06:; + unsigned char dummy28_06 = 0x04; + upekdev->seq = 0xf0; + initsm_send_msg28_handler (ssm, dev, 0x06, &dummy28_06, 1); + break; + + case READ28_06: + initsm_read_msg_handler (ssm, dev, read28_06_cb); + break; + + case SEND28_07:; + unsigned char dummy28_07 = 0x04; + initsm_send_msg28_handler (ssm, dev, 0x07, &dummy28_07, 1); + break; + + case READ28_07: + initsm_read_msg_handler (ssm, dev, read28_07_cb); + break; + + case SEND28_08: + initsm_send_msg28_handler (ssm, dev, 0x08, init28_08, sizeof (init28_08)); + break; + + case READ28_08: + initsm_read_msg_handler (ssm, dev, read28_08_cb); + break; + + case SEND28_0C: + initsm_send_msg28_handler (ssm, dev, 0x0c, init28_0c, sizeof (init28_0c)); + break; + + case READ28_0C: + initsm_read_msg_handler (ssm, dev, read28_0c_cb); + break; + + case SEND28_0B: + initsm_send_msg28_handler (ssm, dev, 0x0b, init28_0b, sizeof (init28_0b)); + break; + + case READ28_0B: + initsm_read_msg_handler (ssm, dev, read28_0b_cb); + break; + } +} + +static FpiSsm * +initsm_new (FpDevice *dev) +{ + return fpi_ssm_new (dev, initsm_run_state, INITSM_NUM_STATES); } enum deinitsm_states { - SEND_RESP07 = 0, - READ_MSG01, - DEINITSM_NUM_STATES, + SEND_RESP07 = 0, + READ_MSG01, + DEINITSM_NUM_STATES, }; -static void send_resp07_cb(struct libusb_transfer *transfer) +static void +read_msg01_cb (FpDevice *dev, enum read_msg_type type, + guint8 seq, unsigned char subcmd, + unsigned char *data, size_t data_len, + void *user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) - fpi_ssm_mark_failed(ssm, -EIO); - else if (transfer->length != transfer->actual_length) - fpi_ssm_mark_failed(ssm, -EPROTO); - else - fpi_ssm_next_state(ssm); - libusb_free_transfer(transfer); + FpiSsm *ssm = user_data; + FpiDeviceUpekts *upekdev = FPI_DEVICE_UPEKTS (dev); + + if (error) + { + fpi_ssm_mark_failed (ssm, error); + return; + } + else if (type != READ_MSG_CMD) + { + fp_err ("expected command, got %d seq=%x", type, seq); + fpi_ssm_mark_failed (ssm, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Expected command but got response")); + return; + } + upekdev->seq = seq; + if (seq != 1) + { + fp_err ("expected seq=1, got %x", seq); + fpi_ssm_mark_failed (ssm, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Got wrong sequence number")); + return; + } + + fpi_ssm_next_state (ssm); } -static void read_msg01_cb(struct fp_dev *dev, enum read_msg_status status, - uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len, - void *user_data) +static void +deinitsm_state_handler (FpiSsm *ssm, FpDevice *dev) { - fpi_ssm *ssm = user_data; - struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); + switch (fpi_ssm_get_cur_state (ssm)) + { + case SEND_RESP07:; + FpiUsbTransfer *transfer; + unsigned char dummy = 0; - if (status == READ_MSG_ERROR) { - fpi_ssm_mark_failed(ssm, -1); - return; - } else if (status != READ_MSG_CMD) { - fp_err("expected command, got %d seq=%x", status, seq); - fpi_ssm_mark_failed(ssm, -1); - return; - } - upekdev->seq = seq; - if (seq != 1) { - fp_err("expected seq=1, got %x", seq); - fpi_ssm_mark_failed(ssm, -1); - return; - } + transfer = alloc_send_cmdresponse_transfer (dev, 0x07, &dummy, 1); + transfer->short_is_error = TRUE; + transfer->ssm = ssm; + fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL); + fpi_usb_transfer_unref (transfer); + break; - fpi_ssm_next_state(ssm); + case READ_MSG01:; + read_msg_async (dev, read_msg01_cb, ssm); + break; + } } -static void deinitsm_state_handler(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) +static void +initsm_done (FpiSsm *ssm, FpDevice *dev, GError *error) { - int r; + if (error) + g_usb_device_release_interface (fpi_device_get_usb_device (dev), 0, 0, NULL); - switch (fpi_ssm_get_cur_state(ssm)) { - case SEND_RESP07: ; - struct libusb_transfer *transfer; - unsigned char dummy = 0; - - transfer = alloc_send_cmdresponse_transfer(dev, 0x07, &dummy, 1, - send_resp07_cb, ssm); - if (!transfer) { - fpi_ssm_mark_failed(ssm, -ENOMEM); - break; - } - - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(transfer->buffer); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } - break; - case READ_MSG01: ; - r = read_msg_async(dev, read_msg01_cb, ssm); - if (r < 0) - fpi_ssm_mark_failed(ssm, r); - break; - } + fpi_device_open_complete (dev, error); } -static fpi_ssm *deinitsm_new(struct fp_dev *dev) +static FpiSsm * +deinitsm_new (FpDevice *dev, void *user_data) { - return fpi_ssm_new(dev, deinitsm_state_handler, DEINITSM_NUM_STATES, NULL); + return fpi_ssm_new (dev, deinitsm_state_handler, DEINITSM_NUM_STATES); } -static int dev_init(struct fp_dev *dev, unsigned long driver_data) +static void +dev_init (FpDevice *dev) { - struct upekts_dev *upekdev = NULL; - int r; + FpiSsm *ssm; + GError *error = NULL; + FpiDeviceUpekts *upekdev = FPI_DEVICE_UPEKTS (dev); - r = libusb_claim_interface(fpi_dev_get_usb_dev(dev), 0); - if (r < 0) { - fp_err("could not claim interface 0: %s", libusb_error_name(r)); - return r; - } + if (!g_usb_device_claim_interface (fpi_device_get_usb_device (dev), 0, 0, &error)) + { + fpi_device_open_complete (dev, error); + return; + } - upekdev = g_malloc(sizeof(*upekdev)); - upekdev->seq = 0xf0; /* incremented to 0x00 before first cmd */ - fp_dev_set_instance_data(dev, upekdev); - fpi_dev_set_nr_enroll_stages(dev, 3); + upekdev->seq = 0xf0; /* incremented to 0x00 before first cmd */ - fpi_drvcb_open_complete(dev, 0); - return 0; + ssm = fpi_ssm_new (dev, initsm_run_state, INITSM_NUM_STATES); + fpi_ssm_start (ssm, initsm_done); } -static void dev_exit(struct fp_dev *dev) +static void +deinitsm_done (FpiSsm *ssm, FpDevice *dev, GError *error) { - struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); + g_usb_device_release_interface (fpi_device_get_usb_device (dev), 0, 0, NULL); - libusb_release_interface(fpi_dev_get_usb_dev(dev), 0); - g_free(upekdev); - fpi_drvcb_close_complete(dev); + fpi_device_close_complete (dev, error); +} + +static void +dev_exit (FpDevice *dev) +{ + FpiSsm *ssm; + + ssm = fpi_ssm_new (dev, deinitsm_state_handler, DEINITSM_NUM_STATES); + fpi_ssm_start (ssm, deinitsm_done); } static const unsigned char enroll_init[] = { - 0x02, 0xc0, 0xd4, 0x01, 0x00, 0x04, 0x00, 0x08 + 0x02, 0xc0, 0xd4, 0x01, 0x00, 0x04, 0x00, 0x08 }; static const unsigned char scan_comp[] = { - 0x12, 0xff, 0xff, 0xff, 0xff /* scan completion, prefixes print data */ + 0x12, 0xff, 0xff, 0xff, 0xff /* scan completion, prefixes print data */ }; /* used for enrollment and verification */ static const unsigned char poll_data[] = { 0x30, 0x01 }; enum enroll_start_sm_states { - RUN_INITSM = 0, - ENROLL_INIT, - READ_ENROLL_MSG28, - ENROLL_START_NUM_STATES, + RUN_INITSM = 0, + ENROLL_INIT, + READ_ENROLL_MSG28, + ENROLL_START_NUM_STATES, }; -/* Called when the device initialization state machine completes */ -static void enroll_start_sm_cb_initsm(fpi_ssm *initsm, struct fp_dev *_dev, void *user_data) +static void +enroll_start_sm_cb_msg28 (FpDevice *dev, + enum read_msg_type type, guint8 seq, + unsigned char subcmd, + unsigned char *data, size_t data_len, + void *user_data, + GError *error) { - fpi_ssm *enroll_start_ssm = user_data; - int error = fpi_ssm_get_error(initsm); + FpiDeviceUpekts *upekdev = FPI_DEVICE_UPEKTS (dev); + FpiSsm *ssm = user_data; - fpi_ssm_free(initsm); - if (error) - fpi_ssm_mark_failed(enroll_start_ssm, error); - else - fpi_ssm_next_state(enroll_start_ssm); + if (error) + fpi_ssm_mark_failed (ssm, error); + if (type != READ_MSG_RESPONSE) + { + fp_err ("expected response, got %d seq=%x", type, seq); + fpi_ssm_mark_failed (ssm, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Unexpected response type")); + } + else if (subcmd != 0) + { + fp_warn ("expected response to subcmd 0, got response to %02x", + subcmd); + fpi_ssm_mark_failed (ssm, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Got response to wrong subcommand")); + } + else if (seq != upekdev->seq) + { + fp_err ("expected response to cmd seq=%02x, got response to %02x", + upekdev->seq, seq); + fpi_ssm_mark_failed (ssm, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Got response with wrong sequence number")); + } + else + { + fpi_ssm_next_state (ssm); + } } -/* called when enroll init URB has completed */ -static void enroll_start_sm_cb_init(struct libusb_transfer *transfer) +static void +enroll_start_sm_run_state (FpiSsm *ssm, FpDevice *dev) { - fpi_ssm *ssm = transfer->user_data; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) - fpi_ssm_mark_failed(ssm, -EIO); - else if (transfer->length != transfer->actual_length) - fpi_ssm_mark_failed(ssm, -EPROTO); - else - fpi_ssm_next_state(ssm); - libusb_free_transfer(transfer); + switch (fpi_ssm_get_cur_state (ssm)) + { + case RUN_INITSM:; + FpiSsm *initsm = initsm_new (dev); + fpi_ssm_start_subsm (ssm, initsm); + break; + + case ENROLL_INIT:; + FpiUsbTransfer *transfer; + transfer = alloc_send_cmd28_transfer (dev, 0x02, enroll_init, sizeof (enroll_init)); + transfer->short_is_error = TRUE; + transfer->ssm = ssm; + + fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL); + fpi_usb_transfer_unref (transfer); + break; + + case READ_ENROLL_MSG28:; + /* FIXME: protocol misunderstanding here. device receives response + * to subcmd 0 after submitting subcmd 2? */ + /* actually this is probably a poll response? does the above cmd + * include a 30 01 poll somewhere? */ + read_msg_async (dev, enroll_start_sm_cb_msg28, ssm); + break; + } } -static void enroll_start_sm_cb_msg28(struct fp_dev *dev, - enum read_msg_status status, uint8_t seq, unsigned char subcmd, - unsigned char *data, size_t data_len, void *user_data) +typedef struct { - struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); - fpi_ssm *ssm = user_data; + FpPrint *print; + GError *error; +} EnrollStopData; - if (status != READ_MSG_RESPONSE) { - fp_err("expected response, got %d seq=%x", status, seq); - fpi_ssm_mark_failed(ssm, -1); - } else if (subcmd != 0) { - fp_warn("expected response to subcmd 0, got response to %02x", - subcmd); - fpi_ssm_mark_failed(ssm, -1); - } else if (seq != upekdev->seq) { - fp_err("expected response to cmd seq=%02x, got response to %02x", - upekdev->seq, seq); - fpi_ssm_mark_failed(ssm, -1); - } else { - fpi_ssm_next_state(ssm); - } +static void +enroll_stop_data_free (EnrollStopData *data) +{ + g_clear_object (&data->print); + g_clear_error (&data->error); + g_free (data); } -static void enroll_start_sm_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) +static void +enroll_stop_deinit_cb (FpiSsm *ssm, FpDevice *dev, GError *error) { - int r; + EnrollStopData *data = fpi_ssm_get_data (ssm); - switch (fpi_ssm_get_cur_state(ssm)) { - case RUN_INITSM: ; - fpi_ssm *initsm = initsm_new(dev, ssm); - fpi_ssm_start(initsm, enroll_start_sm_cb_initsm); - break; - case ENROLL_INIT: ; - struct libusb_transfer *transfer; - transfer = alloc_send_cmd28_transfer(dev, 0x02, enroll_init, - sizeof(enroll_init), enroll_start_sm_cb_init, ssm); - if (!transfer) { - fpi_ssm_mark_failed(ssm, -ENOMEM); - break; - } + /* don't really care about errors */ + if (error) + fp_warn ("Error deinitializing: %s", error->message); - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(transfer->buffer); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } - break; - case READ_ENROLL_MSG28: ; - /* FIXME: protocol misunderstanding here. device receives response - * to subcmd 0 after submitting subcmd 2? */ - /* actually this is probably a poll response? does the above cmd - * include a 30 01 poll somewhere? */ - r = read_msg_async(dev, enroll_start_sm_cb_msg28, ssm); - if (r < 0) - fpi_ssm_mark_failed(ssm, r); - break; - } + fpi_device_enroll_complete (dev, data->print, data->error); + fpi_ssm_free (ssm); } -static void enroll_iterate(struct fp_dev *dev); - -static void e_handle_resp00(struct fp_dev *dev, unsigned char *data, - size_t data_len) +static void +do_enroll_stop (FpDevice *dev, FpPrint *print, GError *error) { - struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); - unsigned char status; - int result = 0; + EnrollStopData *data = g_new0 (EnrollStopData, 1); + FpiSsm *ssm = deinitsm_new (dev, data); - if (data_len != 14) { - fp_err("received 3001 poll response of %lu bytes?", data_len); - fpi_drvcb_enroll_stage_completed(dev, -EPROTO, NULL, NULL); - return; - } + data->print = g_object_ref (print); + data->error = error; - status = data[5]; - fp_dbg("poll result = %02x", status); - - switch (status) { - case 0x0c: - case 0x0d: - case 0x0e: - case 0x26: - case 0x27: - case 0x2e: - /* if we previously completed a non-last enrollment stage, we'll - * get this code to indicate successful stage completion */ - if (upekdev->enroll_passed) { - result = FP_ENROLL_PASS; - upekdev->enroll_passed = FALSE; - } - /* otherwise it just means "no news" so we poll again */ - break; - case 0x1c: /* FIXME what does this one mean? */ - case 0x0b: /* FIXME what does this one mean? */ - case 0x23: /* FIXME what does this one mean? */ - result = FP_ENROLL_RETRY; - break; - case 0x0f: /* scan taking too long, remove finger and try again */ - result = FP_ENROLL_RETRY_REMOVE_FINGER; - break; - case 0x1e: /* swipe too short */ - result = FP_ENROLL_RETRY_TOO_SHORT; - break; - case 0x24: /* finger not centered */ - result = FP_ENROLL_RETRY_CENTER_FINGER; - break; - case 0x20: - /* finger scanned successfully */ - /* need to look at the next poll result to determine if enrollment is - * complete or not */ - upekdev->enroll_passed = 1; - break; - case 0x00: /* enrollment complete */ - /* we can now expect the enrollment data on the next poll, so we - * have nothing to do here */ - break; - default: - fp_err("unrecognised scan status code %02x", status); - result = -EPROTO; - break; - } - - if (result) { - fpi_drvcb_enroll_stage_completed(dev, result, NULL, NULL); - if (result > 0) - enroll_iterate(dev); - } else { - enroll_iterate(dev); - } - - /* FIXME: need to extend protocol research to handle the case when - * enrolment fails, e.g. you scan a different finger on each stage */ - /* FIXME: should do proper tracking of when we expect cmd0 results and - * cmd2 results and enforce it */ + fpi_ssm_start (ssm, enroll_stop_deinit_cb); + fpi_ssm_set_data (ssm, data, (GDestroyNotify) enroll_stop_data_free); } -static void e_handle_resp02(struct fp_dev *dev, unsigned char *data, - size_t data_len) +static void enroll_iterate (FpDevice *dev); + +static void +e_handle_resp00 (FpDevice *dev, unsigned char *data, + size_t data_len) { - struct fp_print_data *fdata = NULL; - struct fp_print_data_item *item = NULL; - int result = -EPROTO; + FpiDeviceUpekts *upekdev = FPI_DEVICE_UPEKTS (dev); + unsigned char status; - if (data_len < sizeof(scan_comp)) { - fp_err("fingerprint data too short (%lu bytes)", data_len); - } else if (memcmp(data, scan_comp, sizeof(scan_comp)) != 0) { - fp_err("unrecognised data prefix %x %x %x %x %x", - data[0], data[1], data[2], data[3], data[4]); - } else { - fdata = fpi_print_data_new(dev); - item = fpi_print_data_item_new(data_len - sizeof(scan_comp)); - memcpy(item->data, data + sizeof(scan_comp), - data_len - sizeof(scan_comp)); - fpi_print_data_add_item(fdata, item); + if (data_len != 14) + { + fp_err ("received 3001 poll response of %lu bytes?", data_len); + do_enroll_stop (dev, NULL, + fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "received 3001 response with wrong length")); + return; + } - result = FP_ENROLL_COMPLETE; - } + status = data[5]; + fp_dbg ("poll result = %02x", status); - fpi_drvcb_enroll_stage_completed(dev, result, fdata, NULL); + switch (status) + { + case 0x0c: + case 0x0d: + case 0x0e: + case 0x26: + case 0x27: + case 0x2e: + /* if we previously completed a non-last enrollment stage, we'll + * get this code to indicate successful stage completion */ + if (upekdev->enroll_passed) + { + upekdev->enroll_passed = FALSE; + upekdev->enroll_stage += 1; + + fpi_device_enroll_progress (dev, upekdev->enroll_stage, NULL, NULL); + } + /* otherwise it just means "no news" so we poll again */ + break; + + case 0x1c: /* FIXME what does this one mean? */ + case 0x0b: /* FIXME what does this one mean? */ + case 0x23: /* FIXME what does this one mean? */ + fpi_device_enroll_progress (dev, + upekdev->enroll_stage, + NULL, + fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL)); + break; + + case 0x0f: /* scan taking too long, remove finger and try again */ + fpi_device_enroll_progress (dev, + upekdev->enroll_stage, + NULL, + fpi_device_retry_new (FP_DEVICE_RETRY_REMOVE_FINGER)); + break; + + case 0x1e: /* swipe too short */ + fpi_device_enroll_progress (dev, + upekdev->enroll_stage, + NULL, + fpi_device_retry_new (FP_DEVICE_RETRY_TOO_SHORT)); + break; + + case 0x24: /* finger not centered */ + fpi_device_enroll_progress (dev, + upekdev->enroll_stage, + NULL, + fpi_device_retry_new (FP_DEVICE_RETRY_CENTER_FINGER)); + break; + + case 0x20: + /* finger scanned successfully */ + /* need to look at the next poll result to determine if enrollment is + * complete or not */ + upekdev->enroll_passed = TRUE; + break; + + case 0x00: /* enrollment complete */ + /* we can now expect the enrollment data on the next poll, so we + * have nothing to do here */ + break; + + default: + do_enroll_stop (dev, + NULL, + fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Unrecognised scan status code")); + /* Stop iteration. */ + return; + } + enroll_iterate (dev); + + /* FIXME: need to extend protocol research to handle the case when + * enrolment fails, e.g. you scan a different finger on each stage */ + /* FIXME: should do proper tracking of when we expect cmd0 results and + * cmd2 results and enforce it */ } -static void enroll_iterate_msg_cb(struct fp_dev *dev, - enum read_msg_status msgstat, uint8_t seq, unsigned char subcmd, - unsigned char *data, size_t data_len, void *user_data) +static void +e_handle_resp02 (FpDevice *dev, unsigned char *data, + size_t data_len) { - if (msgstat != READ_MSG_RESPONSE) { - fp_err("expected response, got %d seq=%x", msgstat, seq); - fpi_drvcb_enroll_stage_completed(dev, -EPROTO, NULL, NULL); - return; - } - if (subcmd == 0) { - e_handle_resp00(dev, data, data_len); - } else if (subcmd == 2) { - e_handle_resp02(dev, data, data_len); - } else { - fp_err("unexpected subcmd %d", subcmd); - fpi_drvcb_enroll_stage_completed(dev, -EPROTO, NULL, NULL); - } + FpPrint *print = NULL; + GError *error = NULL; + if (data_len < sizeof (scan_comp)) + { + fp_err ("fingerprint data too short (%lu bytes)", data_len); + error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, "fingerprint data too short"); + } + else if (memcmp (data, scan_comp, sizeof (scan_comp)) != 0) + { + fp_err ("unrecognised data prefix %x %x %x %x %x", + data[0], data[1], data[2], data[3], data[4]); + error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, "fingerprint data has wrong prefix"); + } + else + { + GVariant *fp_data; + print = fp_print_new (dev); + + fpi_device_get_enroll_data (dev, &print); + + fp_data = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + data + sizeof (scan_comp), + data_len - sizeof (scan_comp), + 1); + + g_object_set (print, "fp-data", fp_data, NULL); + g_object_ref (print); + } + + do_enroll_stop (dev, print, error); } -static void enroll_iterate_cmd_cb(struct libusb_transfer *transfer) +static void +enroll_iterate_msg_cb (FpDevice *dev, + enum read_msg_type msgtype, guint8 seq, + unsigned char subcmd, + unsigned char *data, size_t data_len, + void *user_data, + GError *error) { - struct fp_dev *dev = transfer->user_data; - - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fpi_drvcb_enroll_stage_completed(dev, -EIO, NULL, NULL); - } else if (transfer->length != transfer->actual_length) { - fpi_drvcb_enroll_stage_completed(dev, -EPROTO, NULL, NULL); - } else { - int r = read_msg_async(dev, enroll_iterate_msg_cb, NULL); - if (r < 0) - fpi_drvcb_enroll_stage_completed(dev, r, NULL, NULL); - } - libusb_free_transfer(transfer); + if (error) + { + do_enroll_stop (dev, NULL, error); + return; + } + else if (msgtype != READ_MSG_RESPONSE) + { + fp_err ("expected response, got %d seq=%x", msgtype, seq); + do_enroll_stop (dev, NULL, + fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Expected message response, not command")); + return; + } + if (subcmd == 0) + { + e_handle_resp00 (dev, data, data_len); + } + else if (subcmd == 2) + { + e_handle_resp02 (dev, data, data_len); + } + else + { + fp_err ("unexpected subcmd %d", subcmd); + do_enroll_stop (dev, NULL, + fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Unexpected subcommand")); + } } -static void enroll_iterate(struct fp_dev *dev) +static void +enroll_iterate_cmd_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - int r; - struct libusb_transfer *transfer = alloc_send_cmd28_transfer(dev, 0x00, - poll_data, sizeof(poll_data), enroll_iterate_cmd_cb, dev); - - if (!transfer) { - fpi_drvcb_enroll_stage_completed(dev, -ENOMEM, NULL, NULL); - return; - } - - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(transfer->buffer); - libusb_free_transfer(transfer); - fpi_drvcb_enroll_stage_completed(dev, -EIO, NULL, NULL); - } + if (error) + do_enroll_stop (device, NULL, error); + else + read_msg_async (device, enroll_iterate_msg_cb, NULL); } -static void enroll_started(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) +static void +enroll_iterate (FpDevice *dev) { - fpi_drvcb_enroll_started(dev, fpi_ssm_get_error(ssm)); + FpiUsbTransfer *transfer; - if (!fpi_ssm_get_error(ssm)) - enroll_iterate(dev); + if (fpi_device_action_is_cancelled (dev)) + { + do_enroll_stop (dev, NULL, g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED, "Cancelled")); + return; + } - fpi_ssm_free(ssm); + transfer = alloc_send_cmd28_transfer (dev, 0x00, + poll_data, sizeof (poll_data)); + transfer->short_is_error = TRUE; + + fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, enroll_iterate_cmd_cb, NULL); + fpi_usb_transfer_unref (transfer); } -static int enroll_start(struct fp_dev *dev) +static void +enroll_started (FpiSsm *ssm, FpDevice *dev, GError *error) { - struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); + if (error) + do_enroll_stop (dev, NULL, error); + else + enroll_iterate (dev); - /* do_init state machine first */ - fpi_ssm *ssm = fpi_ssm_new(dev, enroll_start_sm_run_state, - ENROLL_START_NUM_STATES, NULL); - - upekdev->enroll_passed = FALSE; - fpi_ssm_start(ssm, enroll_started); - return 0; + fpi_ssm_free (ssm); } -static void enroll_stop_deinit_cb(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) +static void +enroll (FpDevice *dev) { - /* don't really care about errors */ - fpi_drvcb_enroll_stopped(dev); - fpi_ssm_free(ssm); + FpiDeviceUpekts *upekdev = FPI_DEVICE_UPEKTS (dev); + + /* do_init state machine first */ + FpiSsm *ssm = fpi_ssm_new (dev, enroll_start_sm_run_state, + ENROLL_START_NUM_STATES); + + upekdev->enroll_passed = FALSE; + upekdev->enroll_stage = 0; + fpi_ssm_start (ssm, enroll_started); } -static int enroll_stop(struct fp_dev *dev) +typedef struct { - fpi_ssm *ssm = deinitsm_new(dev); - fpi_ssm_start(ssm, enroll_stop_deinit_cb); - return 0; + FpiMatchResult res; + GError *error; +} VerifyStopData; + +static void +verify_stop_data_free (VerifyStopData *data) +{ + g_clear_error (&data->error); + g_free (data); } -static void verify_stop_deinit_cb(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) +static void +verify_stop_deinit_cb (FpiSsm *ssm, FpDevice *dev, GError *error) { - /* don't really care about errors */ - fpi_drvcb_verify_stopped(dev); - fpi_ssm_free(ssm); + VerifyStopData *data = fpi_ssm_get_data (ssm); + + if (error) + fp_warn ("Error deinitializing: %s", error->message); + + fpi_device_verify_complete (dev, data->res, NULL, data->error); + fpi_ssm_free (ssm); } -static void do_verify_stop(struct fp_dev *dev) +static void +do_verify_stop (FpDevice *dev, FpiMatchResult res, GError *error) { - fpi_ssm *ssm = deinitsm_new(dev); - fpi_ssm_start(ssm, verify_stop_deinit_cb); + VerifyStopData *data = g_new0 (VerifyStopData, 1); + FpiSsm *ssm = deinitsm_new (dev, data); + + data->res = res; + data->error = error; + + fpi_ssm_start (ssm, verify_stop_deinit_cb); + fpi_ssm_set_data (ssm, data, (GDestroyNotify) verify_stop_data_free); } static const unsigned char verify_hdr[] = { - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc0, 0xd4, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00 + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0xd4, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00 }; enum { - VERIFY_RUN_INITSM = 0, - VERIFY_INIT, - VERIFY_NUM_STATES, + VERIFY_RUN_INITSM = 0, + VERIFY_INIT, + VERIFY_NUM_STATES, }; -/* Called when the device initialization state machine completes */ -static void verify_start_sm_cb_initsm(fpi_ssm *initsm, struct fp_dev *_dev, void *user_data) +static void +verify_start_sm_run_state (FpiSsm *ssm, FpDevice *dev) { - fpi_ssm *verify_start_ssm = user_data; - int err; + FpPrint *print; - err = fpi_ssm_get_error(initsm); - if (err) - fpi_ssm_mark_failed(verify_start_ssm, err); - else - fpi_ssm_next_state(verify_start_ssm); - fpi_ssm_free(initsm); + g_autoptr(GVariant) fp_data = NULL; + FpiUsbTransfer *transfer; + gsize data_len; + const guint8 *data; + guint8 *msg; + gsize msg_len; + + switch (fpi_ssm_get_cur_state (ssm)) + { + case VERIFY_RUN_INITSM:; + FpiSsm *initsm = initsm_new (dev); + fpi_ssm_start_subsm (ssm, initsm); + break; + + case VERIFY_INIT: + fpi_device_get_verify_data (dev, &print); + g_object_get (dev, "fp-data", &fp_data, NULL); + + data = g_variant_get_fixed_array (fp_data, &data_len, 1); + + msg_len = sizeof (verify_hdr) + data_len; + msg = g_malloc (msg_len); + + memcpy (msg, verify_hdr, sizeof (verify_hdr)); + memcpy (msg + sizeof (verify_hdr), data, data_len); + + transfer = alloc_send_cmd28_transfer (dev, 0x03, data, data_len); + + g_free (msg); + + transfer->short_is_error = TRUE; + transfer->ssm = ssm; + fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL); + fpi_usb_transfer_unref (transfer); + + break; + } } -static void verify_init_2803_cb(struct libusb_transfer *transfer) +static void verify_iterate (FpDevice *dev); + +static void +v_handle_resp00 (FpDevice *dev, unsigned char *data, + size_t data_len) { - fpi_ssm *ssm = transfer->user_data; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) - fpi_ssm_mark_failed(ssm, -EIO); - else if (transfer->length != transfer->actual_length) - fpi_ssm_mark_failed(ssm, -EPROTO); - else - fpi_ssm_next_state(ssm); - libusb_free_transfer(transfer); -} + unsigned char status; + GError *error = NULL; -static void verify_start_sm_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) -{ - int r; + if (data_len != 14) + { + fp_warn ("received 3001 poll response of %lu bytes?", data_len); + error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO); + goto out; + } - switch (fpi_ssm_get_cur_state(ssm)) { - case VERIFY_RUN_INITSM: ; - fpi_ssm *initsm = initsm_new(dev, ssm); - fpi_ssm_start(initsm, verify_start_sm_cb_initsm); - break; - case VERIFY_INIT: ; - struct fp_print_data *print = fpi_dev_get_verify_data(dev); - struct fp_print_data_item *item = fpi_print_data_get_item(print); - size_t data_len = sizeof(verify_hdr) + item->length; - unsigned char *data = g_malloc(data_len); - struct libusb_transfer *transfer; + status = data[5]; + fp_dbg ("poll result = %02x", status); - memcpy(data, verify_hdr, sizeof(verify_hdr)); - memcpy(data + sizeof(verify_hdr), item->data, item->length); - transfer = alloc_send_cmd28_transfer(dev, 0x03, data, data_len, - verify_init_2803_cb, ssm); - g_free(data); - if (!transfer) { - fpi_ssm_mark_failed(ssm, -ENOMEM); - break; - } + /* These codes indicate that we're waiting for a finger scan, so poll + * again */ + switch (status) + { + case 0x0c: /* no news, poll again */ + break; - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(transfer->buffer); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, -EIO); - } - break; - } -} + case 0x20: + fp_dbg ("processing scan for verification"); + break; -static void verify_iterate(struct fp_dev *dev); + case 0x00: + fp_dbg ("good image"); + break; -static void v_handle_resp00(struct fp_dev *dev, unsigned char *data, - size_t data_len) -{ - unsigned char status; - int r = 0; + case 0x1c: /* FIXME what does this one mean? */ + case 0x0b: /* FIXME what does this one mean? */ + case 0x23: /* FIXME what does this one mean? */ + error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL); + break; - if (data_len != 14) { - fp_err("received 3001 poll response of %lu bytes?", data_len); - r = -EPROTO; - goto out; - } + case 0x0f: /* scan taking too long, remove finger and try again */ + error = fpi_device_retry_new (FP_DEVICE_RETRY_REMOVE_FINGER); + break; - status = data[5]; - fp_dbg("poll result = %02x", status); + case 0x1e: /* swipe too short */ + error = fpi_device_retry_new (FP_DEVICE_RETRY_TOO_SHORT); + break; - /* These codes indicate that we're waiting for a finger scan, so poll - * again */ - switch (status) { - case 0x0c: /* no news, poll again */ - break; - case 0x20: - fp_dbg("processing scan for verification"); - break; - case 0x00: - fp_dbg("good image"); - break; - case 0x1c: /* FIXME what does this one mean? */ - case 0x0b: /* FIXME what does this one mean? */ - case 0x23: /* FIXME what does this one mean? */ - r = FP_VERIFY_RETRY; - break; - case 0x0f: /* scan taking too long, remove finger and try again */ - r = FP_VERIFY_RETRY_REMOVE_FINGER; - break; - case 0x1e: /* swipe too short */ - r = FP_VERIFY_RETRY_TOO_SHORT; - break; - case 0x24: /* finger not centered */ - r = FP_VERIFY_RETRY_CENTER_FINGER; - break; - default: - fp_err("unrecognised verify status code %02x", status); - r = -EPROTO; - } + case 0x24: /* finger not centered */ + error = fpi_device_retry_new (FP_DEVICE_RETRY_CENTER_FINGER); + break; + + default: + fp_err ("unrecognised verify status code %02x", status); + error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL); + } out: - if (r) - fpi_drvcb_report_verify_result(dev, r, NULL); - if (r >= 0) - verify_iterate(dev); + if (error) + do_verify_stop (dev, FPI_MATCH_ERROR, error); + else + verify_iterate (dev); } -static void v_handle_resp03(struct fp_dev *dev, unsigned char *data, - size_t data_len) +static void +v_handle_resp03 (FpDevice *dev, unsigned char *data, + size_t data_len) { - int r; + FpiMatchResult r; + GError *error = NULL; - if (data_len < 2) { - fp_err("verify result abnormally short!"); - r = -EPROTO; - } else if (data[0] != 0x12) { - fp_err("unexpected verify header byte %02x", data[0]); - r = -EPROTO; - } else if (data[1] == 0x00) { - r = FP_VERIFY_NO_MATCH; - } else if (data[1] == 0x01) { - r = FP_VERIFY_MATCH; - } else { - fp_err("unrecognised verify result %02x", data[1]); - r = -EPROTO; - } - fpi_drvcb_report_verify_result(dev, r, NULL); + if (data_len < 2) + { + fp_warn ("verify result abnormally short!"); + r = FPI_MATCH_ERROR; + error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO); + } + else if (data[0] != 0x12) + { + fp_warn ("unexpected verify header byte %02x", data[0]); + r = FPI_MATCH_ERROR; + error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO); + } + else if (data[1] == 0x00) + { + r = FPI_MATCH_FAIL; + } + else if (data[1] == 0x01) + { + r = FPI_MATCH_SUCCESS; + } + else + { + fp_warn ("unrecognised verify result %02x", data[1]); + r = FPI_MATCH_ERROR; + error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO); + } + do_verify_stop (dev, r, error); } -static void verify_rd2800_cb(struct fp_dev *dev, enum read_msg_status msgstat, - uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len, - void *user_data) +static void +verify_rd2800_cb (FpDevice *dev, enum read_msg_type msgtype, + guint8 seq, unsigned char subcmd, + unsigned char *data, size_t data_len, + void *user_data, + GError *error) { - struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); + FpiDeviceUpekts *upekdev = FPI_DEVICE_UPEKTS (dev); - if (msgstat != READ_MSG_RESPONSE) { - fp_err("expected response, got %d seq=%x", msgstat, seq); - fpi_drvcb_report_verify_result(dev, -EPROTO, NULL); - return; - } else if (seq != upekdev->seq) { - fp_err("expected response to cmd seq=%02x, got response to %02x", - upekdev->seq, seq); - fpi_drvcb_report_verify_result(dev, -EPROTO, NULL); - return; - } + if (error) + { + do_verify_stop (dev, FPI_MATCH_ERROR, error); + return; + } - if (subcmd == 0) - v_handle_resp00(dev, data, data_len); - else if (subcmd == 3) - v_handle_resp03(dev, data, data_len); - else - fpi_drvcb_report_verify_result(dev, -EPROTO, NULL); + if (msgtype != READ_MSG_RESPONSE) + { + fp_warn ("expected response, got %d seq=%x", msgtype, seq); + do_verify_stop (dev, + FPI_MATCH_ERROR, + fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Expected message response")); + return; + } + + if (seq != upekdev->seq) + { + fp_warn ("expected response to cmd seq=%02x, got response to %02x", + upekdev->seq, seq); + do_verify_stop (dev, + FPI_MATCH_ERROR, + fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Response hat wrong command sequence")); + return; + } + + if (subcmd == 0) + { + v_handle_resp00 (dev, data, data_len); + } + else if (subcmd == 3) + { + v_handle_resp03 (dev, data, data_len); + } + else + { + do_verify_stop (dev, + FPI_MATCH_ERROR, + fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Response had wrong subcommand type")); + } } -static void verify_wr2800_cb(struct libusb_transfer *transfer) +static void +verify_wr2800_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - struct fp_dev *dev = transfer->user_data; - - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fpi_drvcb_report_verify_result(dev, -EIO, NULL); - } else if (transfer->length != transfer->actual_length) { - fpi_drvcb_report_verify_result(dev, -EIO, NULL); - } else { - int r = read_msg_async(dev, verify_rd2800_cb, NULL); - if (r < 0) - fpi_drvcb_report_verify_result(dev, r, NULL); - } - libusb_free_transfer(transfer); + if (error) + { + do_verify_stop (device, + FPI_MATCH_ERROR, + error); + } + else + { + read_msg_async (device, verify_rd2800_cb, NULL); + } } -static void verify_iterate(struct fp_dev *dev) +static void +verify_iterate (FpDevice *dev) { - struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); + FpiDeviceUpekts *upekdev = FPI_DEVICE_UPEKTS (dev); - if (upekdev->stop_verify) { - do_verify_stop(dev); - return; - } + if (fpi_device_action_is_cancelled (dev)) + { + do_verify_stop (dev, FPI_MATCH_ERROR, g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED, "Cancelled")); + return; + } - /* FIXME: this doesn't flow well, should the first cmd be moved from - * verify init to here? */ - if (upekdev->first_verify_iteration) { - int r = read_msg_async(dev, verify_rd2800_cb, NULL); - upekdev->first_verify_iteration = FALSE; - if (r < 0) - fpi_drvcb_report_verify_result(dev, r, NULL); - } else { - int r; - struct libusb_transfer *transfer = alloc_send_cmd28_transfer(dev, - 0x00, poll_data, sizeof(poll_data), verify_wr2800_cb, dev); + /* FIXME: this doesn't flow well, should the first cmd be moved from + * verify init to here? */ + if (upekdev->first_verify_iteration) + { + read_msg_async (dev, verify_rd2800_cb, NULL); + upekdev->first_verify_iteration = FALSE; + } + else + { + FpiUsbTransfer *transfer = alloc_send_cmd28_transfer (dev, + 0x00, poll_data, sizeof (poll_data)); + transfer->short_is_error = TRUE; - if (!transfer) { - fpi_drvcb_report_verify_result(dev, -ENOMEM, NULL); - return; - } - - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(transfer->buffer); - libusb_free_transfer(transfer); - fpi_drvcb_report_verify_result(dev, -EIO, NULL); - } - } + fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, verify_wr2800_cb, NULL); + fpi_usb_transfer_unref (transfer); + } } -static void verify_started(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) +static void +verify_started (FpiSsm *ssm, FpDevice *dev, GError *error) { - struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); + FpiDeviceUpekts *upekdev = FPI_DEVICE_UPEKTS (dev); - fpi_drvcb_verify_started(dev, fpi_ssm_get_error(ssm)); - if (!fpi_ssm_get_error(ssm)) { - upekdev->first_verify_iteration = TRUE; - verify_iterate(dev); - } + if (error) + { + do_verify_stop (dev, FPI_MATCH_ERROR, error); + return; + } - fpi_ssm_free(ssm); + upekdev->first_verify_iteration = TRUE; + verify_iterate (dev); + + fpi_ssm_free (ssm); } -static int verify_start(struct fp_dev *dev) +static void +verify (FpDevice *dev) { - struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); - fpi_ssm *ssm = fpi_ssm_new(dev, verify_start_sm_run_state, - VERIFY_NUM_STATES, NULL); - upekdev->stop_verify = FALSE; - fpi_ssm_start(ssm, verify_started); - return 0; + FpiSsm *ssm = fpi_ssm_new (dev, verify_start_sm_run_state, VERIFY_NUM_STATES); + + fpi_ssm_start (ssm, verify_started); } -static int verify_stop(struct fp_dev *dev, gboolean iterating) -{ - struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); - - if (!iterating) - do_verify_stop(dev); - else - upekdev->stop_verify = TRUE; - return 0; -} - -static const struct usb_id id_table[] = { - { .vendor = 0x0483, .product = 0x2016 }, - { 0, 0, 0, }, /* terminating entry */ +static const FpIdEntry id_table[] = { + { .vid = 0x0483, .pid = 0x2016, }, + { .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */ }; -struct fp_driver upekts_driver = { - .id = UPEKTS_ID, - .name = FP_COMPONENT, - .full_name = "UPEK TouchStrip", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_SWIPE, - .open = dev_init, - .close = dev_exit, - .enroll_start = enroll_start, - .enroll_stop = enroll_stop, - .verify_start = verify_start, - .verify_stop = verify_stop, -}; +static void +fpi_device_upekts_init (FpiDeviceUpekts *self) +{ +} +static void +fpi_device_upekts_class_init (FpiDeviceUpektsClass *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + + dev_class->id = FP_COMPONENT; + dev_class->full_name = "UPEK TouchStrip"; + + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->scan_type = FP_SCAN_TYPE_SWIPE; + dev_class->id_table = id_table; + dev_class->nr_enroll_stages = 3; + + dev_class->open = dev_init; + dev_class->close = dev_exit; + dev_class->verify = verify; + dev_class->enroll = enroll; + /* dev_class->cancel = cancel; */ +} diff --git a/libfprint/drivers/uru4000.c b/libfprint/drivers/uru4000.c index 79c48c5b..f2484119 100644 --- a/libfprint/drivers/uru4000.c +++ b/libfprint/drivers/uru4000.c @@ -25,253 +25,189 @@ #include "drivers_api.h" -#define EP_INTR (1 | LIBUSB_ENDPOINT_IN) -#define EP_DATA (2 | LIBUSB_ENDPOINT_IN) -#define USB_RQ 0x04 -#define CTRL_IN (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN) -#define CTRL_OUT (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT) -#define CTRL_TIMEOUT 5000 -#define BULK_TIMEOUT 5000 -#define IRQ_LENGTH 64 -#define CR_LENGTH 16 +#define EP_INTR (1 | FPI_USB_ENDPOINT_IN) +#define EP_DATA (2 | FPI_USB_ENDPOINT_IN) +#define USB_RQ 0x04 +#define CTRL_IN (LIBUSB_REQUEST_TYPE_VENDOR | FPI_USB_ENDPOINT_IN) +#define CTRL_OUT (LIBUSB_REQUEST_TYPE_VENDOR | FPI_USB_ENDPOINT_OUT) +#define CTRL_TIMEOUT 5000 +#define BULK_TIMEOUT 5000 +#define IRQ_LENGTH 64 +#define CR_LENGTH 16 -#define IMAGE_HEIGHT 290 -#define IMAGE_WIDTH 384 +#define IMAGE_HEIGHT 290 +#define IMAGE_WIDTH 384 -#define ENC_THRESHOLD 5000 +#define ENC_THRESHOLD 5000 enum { - IRQDATA_SCANPWR_ON = 0x56aa, - IRQDATA_FINGER_ON = 0x0101, - IRQDATA_FINGER_OFF = 0x0200, - IRQDATA_DEATH = 0x0800, + IRQDATA_SCANPWR_ON = 0x56aa, + IRQDATA_FINGER_ON = 0x0101, + IRQDATA_FINGER_OFF = 0x0200, + IRQDATA_DEATH = 0x0800, }; enum { - REG_HWSTAT = 0x07, - REG_SCRAMBLE_DATA_INDEX = 0x33, - REG_SCRAMBLE_DATA_KEY = 0x34, - REG_MODE = 0x4e, - REG_DEVICE_INFO = 0xf0, - /* firmware starts at 0x100 */ - REG_RESPONSE = 0x2000, - REG_CHALLENGE = 0x2010, + REG_HWSTAT = 0x07, + REG_SCRAMBLE_DATA_INDEX = 0x33, + REG_SCRAMBLE_DATA_KEY = 0x34, + REG_MODE = 0x4e, + REG_DEVICE_INFO = 0xf0, + /* firmware starts at 0x100 */ + REG_RESPONSE = 0x2000, + REG_CHALLENGE = 0x2010, }; enum { - MODE_INIT = 0x00, - MODE_AWAIT_FINGER_ON = 0x10, - MODE_AWAIT_FINGER_OFF = 0x12, - MODE_CAPTURE = 0x20, - MODE_CAPTURE_AUX = 0x30, - MODE_OFF = 0x70, - MODE_READY = 0x80, + MODE_INIT = 0x00, + MODE_AWAIT_FINGER_ON = 0x10, + MODE_AWAIT_FINGER_OFF = 0x12, + MODE_CAPTURE = 0x20, + MODE_CAPTURE_AUX = 0x30, + MODE_OFF = 0x70, + MODE_READY = 0x80, }; enum { - MS_KBD, - MS_INTELLIMOUSE, - MS_STANDALONE, - MS_STANDALONE_V2, - DP_URU4000, - DP_URU4000B, + MS_KBD, + MS_INTELLIMOUSE, + MS_STANDALONE, + MS_STANDALONE_V2, + DP_URU4000, + DP_URU4000B, }; -static const struct uru4k_dev_profile { - const char *name; - gboolean auth_cr; - gboolean encryption; +static const struct uru4k_dev_profile +{ + const char *name; + gboolean auth_cr; + gboolean encryption; } uru4k_dev_info[] = { - [MS_KBD] = { - .name = "Microsoft Keyboard with Fingerprint Reader", - .auth_cr = FALSE, - }, - [MS_INTELLIMOUSE] = { - .name = "Microsoft Wireless IntelliMouse with Fingerprint Reader", - .auth_cr = FALSE, - }, - [MS_STANDALONE] = { - .name = "Microsoft Fingerprint Reader", - .auth_cr = FALSE, - }, - [MS_STANDALONE_V2] = { - .name = "Microsoft Fingerprint Reader v2", - .auth_cr = TRUE, - }, - [DP_URU4000] = { - .name = "Digital Persona U.are.U 4000", - .auth_cr = FALSE, - }, - [DP_URU4000B] = { - .name = "Digital Persona U.are.U 4000B", - .auth_cr = FALSE, - .encryption = TRUE, - }, + [MS_KBD] = { + .name = "Microsoft Keyboard with Fingerprint Reader", + .auth_cr = FALSE, + }, + [MS_INTELLIMOUSE] = { + .name = "Microsoft Wireless IntelliMouse with Fingerprint Reader", + .auth_cr = FALSE, + }, + [MS_STANDALONE] = { + .name = "Microsoft Fingerprint Reader", + .auth_cr = FALSE, + }, + [MS_STANDALONE_V2] = { + .name = "Microsoft Fingerprint Reader v2", + .auth_cr = TRUE, + }, + [DP_URU4000] = { + .name = "Digital Persona U.are.U 4000", + .auth_cr = FALSE, + }, + [DP_URU4000B] = { + .name = "Digital Persona U.are.U 4000B", + .auth_cr = FALSE, + .encryption = TRUE, + }, }; -typedef void (*irq_cb_fn)(struct fp_img_dev *dev, int status, uint16_t type, - void *user_data); -typedef void (*irqs_stopped_cb_fn)(struct fp_img_dev *dev); +typedef void (*irq_cb_fn)(FpImageDevice *dev, + GError *error, + uint16_t type, + void *user_data); +typedef void (*irqs_stopped_cb_fn)(FpImageDevice *dev); -struct uru4k_dev { - const struct uru4k_dev_profile *profile; - uint8_t interface; - enum fp_imgdev_state activate_state; - unsigned char last_reg_rd[16]; - unsigned char last_hwstat; +struct _FpiDeviceUru4000 +{ + FpImageDevice parent; - fpi_usb_transfer *irq_transfer; - fpi_usb_transfer *img_transfer; - void *img_data; - int img_data_actual_length; - uint16_t img_lines_done, img_block; - uint32_t img_enc_seed; + const struct uru4k_dev_profile *profile; + uint8_t interface; + FpImageDeviceState activate_state; + unsigned char last_reg_rd[16]; + unsigned char last_hwstat; - irq_cb_fn irq_cb; - void *irq_cb_data; - irqs_stopped_cb_fn irqs_stopped_cb; + GCancellable *irq_cancellable; + FpiUsbTransfer *img_transfer; + void *img_data; + int img_data_actual_length; + uint16_t img_lines_done, img_block; + uint32_t img_enc_seed; - int rebootpwr_ctr; - int powerup_ctr; - unsigned char powerup_hwstat; + irq_cb_fn irq_cb; + void *irq_cb_data; + irqs_stopped_cb_fn irqs_stopped_cb; - int scanpwr_irq_timeouts; - fpi_timeout *scanpwr_irq_timeout; + int rebootpwr_ctr; + int powerup_ctr; + unsigned char powerup_hwstat; - int fwfixer_offset; - unsigned char fwfixer_value; + int scanpwr_irq_timeouts; + GSource *scanpwr_irq_timeout; - CK_MECHANISM_TYPE cipher; - PK11SlotInfo *slot; - PK11SymKey *symkey; - SECItem *param; + int fwfixer_offset; + unsigned char fwfixer_value; + + CK_MECHANISM_TYPE cipher; + PK11SlotInfo *slot; + PK11SymKey *symkey; + SECItem *param; }; +G_DECLARE_FINAL_TYPE (FpiDeviceUru4000, fpi_device_uru4000, FPI, DEVICE_URU4000, + FpImageDevice); +G_DEFINE_TYPE (FpiDeviceUru4000, fpi_device_uru4000, FP_TYPE_IMAGE_DEVICE); /* For 2nd generation MS devices */ static const unsigned char crkey[] = { - 0x79, 0xac, 0x91, 0x79, 0x5c, 0xa1, 0x47, 0x8e, - 0x98, 0xe0, 0x0f, 0x3c, 0x59, 0x8f, 0x5f, 0x4b, + 0x79, 0xac, 0x91, 0x79, 0x5c, 0xa1, 0x47, 0x8e, + 0x98, 0xe0, 0x0f, 0x3c, 0x59, 0x8f, 0x5f, 0x4b, }; /***** REGISTER I/O *****/ -typedef void (*write_regs_cb_fn)(struct fp_img_dev *dev, int status, - void *user_data); - -struct write_regs_data { - struct fp_img_dev *dev; - write_regs_cb_fn callback; - void *user_data; -}; - -static void write_regs_cb(struct libusb_transfer *transfer) +static void +write_regs (FpImageDevice *dev, uint16_t first_reg, + uint16_t num_regs, unsigned char *values, + FpiUsbTransferCallback callback, + void *user_data) { - struct write_regs_data *wrdata = transfer->user_data; - struct libusb_control_setup *setup = - libusb_control_transfer_get_setup(transfer); - int r = 0; - - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) - r = -EIO; - else if (transfer->actual_length != setup->wLength) - r = -EPROTO; + FpiUsbTransfer *transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); - g_free(transfer->buffer); - libusb_free_transfer(transfer); - wrdata->callback(wrdata->dev, r, wrdata->user_data); - g_free(wrdata); + transfer->short_is_error = TRUE; + fpi_usb_transfer_fill_control (transfer, + G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE, + G_USB_DEVICE_REQUEST_TYPE_STANDARD, + G_USB_DEVICE_RECIPIENT_DEVICE, + USB_RQ, first_reg, 0, + num_regs); + memcpy (transfer->buffer, values, num_regs); + fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, callback, user_data); + fpi_usb_transfer_unref (transfer); } -static int write_regs(struct fp_img_dev *dev, uint16_t first_reg, - uint16_t num_regs, unsigned char *values, write_regs_cb_fn callback, - void *user_data) +static void +write_reg (FpImageDevice *dev, uint16_t reg, + unsigned char value, + FpiUsbTransferCallback callback, + void *user_data) { - struct write_regs_data *wrdata; - struct libusb_transfer *transfer = fpi_usb_alloc(); - unsigned char *data; - int r; - - wrdata = g_malloc(sizeof(*wrdata)); - wrdata->dev = dev; - wrdata->callback = callback; - wrdata->user_data = user_data; - - data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + num_regs); - memcpy(data + LIBUSB_CONTROL_SETUP_SIZE, values, num_regs); - libusb_fill_control_setup(data, CTRL_OUT, USB_RQ, first_reg, 0, num_regs); - libusb_fill_control_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), data, write_regs_cb, - wrdata, CTRL_TIMEOUT); - - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(wrdata); - g_free(data); - libusb_free_transfer(transfer); - } - return r; + write_regs (dev, reg, 1, &value, callback, user_data); } -static int write_reg(struct fp_img_dev *dev, uint16_t reg, - unsigned char value, write_regs_cb_fn callback, void *user_data) +static void +read_regs (FpImageDevice *dev, uint16_t first_reg, + uint16_t num_regs, + FpiUsbTransferCallback callback, + void *user_data) { - return write_regs(dev, reg, 1, &value, callback, user_data); -} + FpiUsbTransfer *transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); -typedef void (*read_regs_cb_fn)(struct fp_img_dev *dev, int status, - uint16_t num_regs, unsigned char *data, void *user_data); - -struct read_regs_data { - struct fp_img_dev *dev; - read_regs_cb_fn callback; - void *user_data; -}; - -static void read_regs_cb(struct libusb_transfer *transfer) -{ - struct read_regs_data *rrdata = transfer->user_data; - struct libusb_control_setup *setup = - libusb_control_transfer_get_setup(transfer); - unsigned char *data = NULL; - int r = 0; - - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) - r = -EIO; - else if (transfer->actual_length != setup->wLength) - r = -EPROTO; - else - data = libusb_control_transfer_get_data(transfer); - - rrdata->callback(rrdata->dev, r, transfer->actual_length, data, rrdata->user_data); - g_free(rrdata); - g_free(transfer->buffer); - libusb_free_transfer(transfer); -} - -static int read_regs(struct fp_img_dev *dev, uint16_t first_reg, - uint16_t num_regs, read_regs_cb_fn callback, void *user_data) -{ - struct read_regs_data *rrdata; - struct libusb_transfer *transfer = fpi_usb_alloc(); - unsigned char *data; - int r; - - rrdata = g_malloc(sizeof(*rrdata)); - rrdata->dev = dev; - rrdata->callback = callback; - rrdata->user_data = user_data; - - data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + num_regs); - libusb_fill_control_setup(data, CTRL_IN, USB_RQ, first_reg, 0, num_regs); - libusb_fill_control_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), data, read_regs_cb, - rrdata, CTRL_TIMEOUT); - - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(rrdata); - g_free(data); - libusb_free_transfer(transfer); - } - return r; + fpi_usb_transfer_fill_control (transfer, + G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST, + G_USB_DEVICE_REQUEST_TYPE_STANDARD, + G_USB_DEVICE_RECIPIENT_DEVICE, + USB_RQ, first_reg, 0, num_regs); + fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, callback, user_data); + fpi_usb_transfer_unref (transfer); } /* @@ -299,49 +235,49 @@ static int read_regs(struct fp_img_dev *dev, uint16_t first_reg, * an interrupt to the host. Maybe? */ -static void response_cb(struct fp_img_dev *dev, int status, void *user_data) +static void +response_cb (FpiUsbTransfer *transfer, FpDevice *dev, void *user_data, GError *error) { - fpi_ssm *ssm = user_data; - if (status == 0) - fpi_ssm_next_state(ssm); - else - fpi_ssm_mark_failed(ssm, status); + /* NOTE: We could use the SSM function instead if we attached the ssm to the transfer! */ + FpiSsm *ssm = user_data; + + if (!error) + fpi_ssm_next_state (ssm); + else + fpi_ssm_mark_failed (ssm, error); } -static void challenge_cb(struct fp_img_dev *dev, int status, - uint16_t num_regs, unsigned char *data, void *user_data) +static void +challenge_cb (FpiUsbTransfer *transfer, FpDevice *dev, void *user_data, GError *error) { - fpi_ssm *ssm = user_data; - struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev)); - unsigned char *respdata; - PK11Context *ctx; - int r, outlen; + FpiSsm *ssm = user_data; + FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev); + unsigned char respdata[CR_LENGTH]; + PK11Context *ctx; + int outlen; - r = status; - if (status != 0) { - fpi_ssm_mark_failed(ssm, status); - return; - } + if (error) + { + fpi_ssm_mark_failed (ssm, error); + return; + } - /* submit response */ - /* produce response from challenge */ - respdata = g_malloc(CR_LENGTH); - ctx = PK11_CreateContextBySymKey(urudev->cipher, CKA_ENCRYPT, - urudev->symkey, urudev->param); - if (PK11_CipherOp(ctx, respdata, &outlen, CR_LENGTH, data, CR_LENGTH) != SECSuccess - || PK11_Finalize(ctx) != SECSuccess) { - fp_err("Failed to encrypt challenge data"); - r = -ECONNABORTED; - g_free(respdata); - } - PK11_DestroyContext(ctx, PR_TRUE); + /* submit response */ + /* produce response from challenge */ + ctx = PK11_CreateContextBySymKey (self->cipher, CKA_ENCRYPT, + self->symkey, self->param); + if (PK11_CipherOp (ctx, respdata, &outlen, CR_LENGTH, transfer->buffer, CR_LENGTH) != SECSuccess || + PK11_Finalize (ctx) != SECSuccess) + { + fp_err ("Failed to encrypt challenge data"); + error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, "Failed to encrypt challenge data"); + } + PK11_DestroyContext (ctx, PR_TRUE); - if (r >= 0) { - r = write_regs(dev, REG_RESPONSE, CR_LENGTH, respdata, response_cb, ssm); - g_free(respdata); - } - if (r < 0) - fpi_ssm_mark_failed(ssm, r); + if (!error) + write_regs (FP_IMAGE_DEVICE (dev), REG_RESPONSE, CR_LENGTH, respdata, response_cb, ssm); + else + fpi_ssm_mark_failed (ssm, error); } /* @@ -350,503 +286,525 @@ static void challenge_cb(struct fp_img_dev *dev, int status, * driver. */ static void -sm_do_challenge_response(fpi_ssm *ssm, - struct fp_img_dev *dev) +sm_do_challenge_response (FpiSsm *ssm, + FpImageDevice *dev) { - int r; - - G_DEBUG_HERE(); - r = read_regs(dev, REG_CHALLENGE, CR_LENGTH, challenge_cb, ssm); - if (r < 0) - fpi_ssm_mark_failed(ssm, r); + G_DEBUG_HERE (); + read_regs (dev, REG_CHALLENGE, CR_LENGTH, challenge_cb, ssm); } /***** INTERRUPT HANDLING *****/ -#define IRQ_HANDLER_IS_RUNNING(urudev) ((urudev)->irq_transfer) +#define IRQ_HANDLER_IS_RUNNING(urudev) ((urudev)->irq_cancellable) -static int start_irq_handler(struct fp_img_dev *dev); +static void start_irq_handler (FpImageDevice *dev); -static void irq_handler(struct libusb_transfer *transfer, - struct fp_dev *_dev, - fpi_ssm *ssm, - void *user_data) +static void +irq_handler (FpiUsbTransfer *transfer, + FpDevice *dev, + void *user_data, + GError *error) { - struct fp_img_dev *dev = FP_IMG_DEV(_dev); - struct uru4k_dev *urudev = FP_INSTANCE_DATA(_dev); - unsigned char *data = transfer->buffer; - uint16_t type; - int r = 0; + FpImageDevice *imgdev = FP_IMAGE_DEVICE (dev); + FpiDeviceUru4000 *urudev = FPI_DEVICE_URU4000 (dev); + unsigned char *data = transfer->buffer; + uint16_t type; - if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { - fp_dbg("cancelled"); - if (urudev->irqs_stopped_cb) - urudev->irqs_stopped_cb(dev); - urudev->irqs_stopped_cb = NULL; - goto out; - } else if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - r = -EIO; - goto err; - } else if (transfer->actual_length != transfer->length) { - fp_err("short interrupt read? %d", transfer->actual_length); - r = -EPROTO; - goto err; - } + g_clear_object (&urudev->irq_cancellable); - type = GUINT16_FROM_BE(*((uint16_t *) data)); - fp_dbg("recv irq type %04x", type); + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + { + fp_dbg ("cancelled"); + if (urudev->irqs_stopped_cb) + urudev->irqs_stopped_cb (imgdev); + urudev->irqs_stopped_cb = NULL; + return; + } + else if (error) + { + if (urudev->irq_cb) + { + urudev->irq_cb (imgdev, error, 0, urudev->irq_cb_data); + } + else + { + fp_dbg ("ignoring interrupt error: %s", error->message); + g_clear_error (&error); + } + return; + } - /* The 0800 interrupt seems to indicate imminent failure (0 bytes transfer) - * of the next scan. It still appears on occasion. */ - if (type == IRQDATA_DEATH) - fp_warn("oh no! got the interrupt OF DEATH! expect things to go bad"); + type = GUINT16_FROM_BE (*((uint16_t *) data)); + fp_dbg ("recv irq type %04x", type); - if (urudev->irq_cb) - urudev->irq_cb(dev, 0, type, urudev->irq_cb_data); - else - fp_dbg("ignoring interrupt"); + /* The 0800 interrupt seems to indicate imminent failure (0 bytes transfer) + * of the next scan. It still appears on occasion. */ + if (type == IRQDATA_DEATH) + fp_warn ("oh no! got the interrupt OF DEATH! expect things to go bad"); - r = start_irq_handler(dev); - if (r == 0) - return; + if (urudev->irq_cb) + urudev->irq_cb (imgdev, NULL, type, urudev->irq_cb_data); + else + fp_dbg ("ignoring interrupt"); -err: - if (urudev->irq_cb) - urudev->irq_cb(dev, r, 0, urudev->irq_cb_data); -out: - urudev->irq_transfer = NULL; + start_irq_handler (imgdev); } -static int start_irq_handler(struct fp_img_dev *dev) +static void +start_irq_handler (FpImageDevice *dev) { - struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_usb_transfer *transfer; - unsigned char *data; - int r; + FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev); + FpiUsbTransfer *transfer; - data = g_malloc(IRQ_LENGTH); - transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev), - NULL, - EP_INTR, - data, - IRQ_LENGTH, - irq_handler, - NULL, - 0); - - urudev->irq_transfer = transfer; - r = fpi_usb_submit_transfer(transfer); - if (r < 0) - urudev->irq_transfer = NULL; - return r; + g_assert (self->irq_cancellable == NULL); + self->irq_cancellable = g_cancellable_new (); + transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); + transfer->ssm = NULL; + transfer->short_is_error = TRUE; + fpi_usb_transfer_fill_bulk (transfer, + EP_INTR, + IRQ_LENGTH); + fpi_usb_transfer_submit (transfer, 0, self->irq_cancellable, irq_handler, NULL); + fpi_usb_transfer_unref (transfer); } -static void stop_irq_handler(struct fp_img_dev *dev, irqs_stopped_cb_fn cb) +static void +stop_irq_handler (FpImageDevice *dev, irqs_stopped_cb_fn cb) { - struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_usb_transfer *transfer = urudev->irq_transfer; - if (transfer) { - fpi_usb_cancel_transfer(transfer); - urudev->irqs_stopped_cb = cb; - } + FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev); + + if (self->irq_cancellable) + { + g_cancellable_cancel (self->irq_cancellable); + self->irqs_stopped_cb = cb; + } } /***** STATE CHANGING *****/ -static int execute_state_change(struct fp_img_dev *dev); +static void execute_state_change (FpImageDevice *dev); -static void finger_presence_irq_cb(struct fp_img_dev *dev, int status, - uint16_t type, void *user_data) +static void +finger_presence_irq_cb (FpImageDevice *dev, + GError *error, + uint16_t type, + void *user_data) { - if (status) - fpi_imgdev_session_error(dev, status); - else if (type == IRQDATA_FINGER_ON) - fpi_imgdev_report_finger_status(dev, TRUE); - else if (type == IRQDATA_FINGER_OFF) - fpi_imgdev_report_finger_status(dev, FALSE); - else - fp_warn("ignoring unexpected interrupt %04x", type); + if (error) + fpi_image_device_session_error (dev, error); + else if (type == IRQDATA_FINGER_ON) + fpi_image_device_report_finger_status (dev, TRUE); + else if (type == IRQDATA_FINGER_OFF) + fpi_image_device_report_finger_status (dev, FALSE); + else + fp_warn ("ignoring unexpected interrupt %04x", type); } -static void change_state_write_reg_cb(struct fp_img_dev *dev, int status, - void *user_data) +static void +change_state_write_reg_cb (FpiUsbTransfer *transfer, + FpDevice *dev, + void *user_data, + GError *error) { - if (status) - fpi_imgdev_session_error(dev, status); + if (error) + fpi_image_device_session_error (FP_IMAGE_DEVICE (dev), error); } -static int dev_change_state(struct fp_img_dev *dev, enum fp_imgdev_state state) +static void +dev_change_state (FpImageDevice *dev, FpImageDeviceState state) { - struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev); - switch (state) { - case IMGDEV_STATE_INACTIVE: - case IMGDEV_STATE_AWAIT_FINGER_ON: - case IMGDEV_STATE_AWAIT_FINGER_OFF: - case IMGDEV_STATE_CAPTURE: - break; - default: - fp_err("unrecognised state %d", state); - return -EINVAL; - } + switch (state) + { + case FP_IMAGE_DEVICE_STATE_INACTIVE: + case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON: + case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: + case FP_IMAGE_DEVICE_STATE_CAPTURE: + break; - urudev->activate_state = state; - if (urudev->img_transfer != NULL) - return 0; + default: + g_assert_not_reached (); + } - return execute_state_change(dev); + self->activate_state = state; + if (self->img_transfer != NULL) + return; + + execute_state_change (dev); } /***** GENERIC STATE MACHINE HELPER FUNCTIONS *****/ -static void sm_write_reg_cb(struct fp_img_dev *dev, int result, void *user_data) +static void +sm_write_reg_cb (FpiUsbTransfer *transfer, + FpDevice *dev, + void *user_data, + GError *error) { - fpi_ssm *ssm = user_data; + FpiSsm *ssm = user_data; - if (result) - fpi_ssm_mark_failed(ssm, result); - else - fpi_ssm_next_state(ssm); + if (error) + fpi_ssm_mark_failed (ssm, error); + else + fpi_ssm_next_state (ssm); } static void -sm_write_regs(fpi_ssm *ssm, - struct fp_img_dev *dev, - uint16_t first_reg, - uint16_t num_regs, - void *data) +sm_write_regs (FpiSsm *ssm, + FpImageDevice *dev, + uint16_t first_reg, + uint16_t num_regs, + void *data) { - int r = write_regs(dev, first_reg, num_regs, data, sm_write_reg_cb, ssm); - if (r < 0) - fpi_ssm_mark_failed(ssm, r); + write_regs (dev, first_reg, num_regs, data, sm_write_reg_cb, ssm); } static void -sm_write_reg(fpi_ssm *ssm, - struct fp_img_dev *dev, - uint16_t reg, - unsigned char value) +sm_write_reg (FpiSsm *ssm, + FpImageDevice *dev, + uint16_t reg, + unsigned char value) { - sm_write_regs(ssm, dev, reg, 1, &value); -} - -static void sm_read_reg_cb(struct fp_img_dev *dev, int result, - uint16_t num_regs, unsigned char *data, void *user_data) -{ - fpi_ssm *ssm = user_data; - struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev)); - - if (result) { - fpi_ssm_mark_failed(ssm, result); - } else { - memcpy(urudev->last_reg_rd, data, num_regs); - fp_dbg("reg value %x", urudev->last_reg_rd[0]); - fpi_ssm_next_state(ssm); - } -} - -#define member_size(type, member) sizeof(((type *)0)->member) - -static void -sm_read_regs(fpi_ssm *ssm, - struct fp_img_dev *dev, - uint16_t reg, - uint16_t num_regs) -{ - int r; - - if (num_regs > member_size(struct uru4k_dev, last_reg_rd)) { - fpi_ssm_mark_failed(ssm, -EIO); - return; - } - - fp_dbg("read %d regs at %x", num_regs, reg); - r = read_regs(dev, reg, num_regs, sm_read_reg_cb, ssm); - if (r < 0) - fpi_ssm_mark_failed(ssm, r); + sm_write_regs (ssm, dev, reg, 1, &value); } static void -sm_read_reg(fpi_ssm *ssm, - struct fp_img_dev *dev, - uint16_t reg) +sm_read_reg_cb (FpiUsbTransfer *transfer, + FpDevice *dev, + void *user_data, + GError *error) { - sm_read_regs(ssm, dev, reg, 1); + FpiSsm *ssm = user_data; + FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev); + + if (error) + { + fpi_ssm_mark_failed (ssm, error); + } + else + { + memcpy (self->last_reg_rd, transfer->buffer, transfer->actual_length); + fp_dbg ("reg value %x", self->last_reg_rd[0]); + fpi_ssm_next_state (ssm); + } +} + +#define member_size(type, member) sizeof (((type *) 0)->member) + +static void +sm_read_regs (FpiSsm *ssm, + FpImageDevice *dev, + uint16_t reg, + uint16_t num_regs) +{ + g_assert (num_regs <= member_size (FpiDeviceUru4000, last_reg_rd)); + + fp_dbg ("read %d regs at %x", num_regs, reg); + read_regs (dev, reg, num_regs, sm_read_reg_cb, ssm); } static void -sm_set_hwstat(fpi_ssm *ssm, - struct fp_img_dev *dev, - unsigned char value) +sm_read_reg (FpiSsm *ssm, + FpImageDevice *dev, + uint16_t reg) { - fp_dbg("set %02x", value); - sm_write_reg(ssm, dev, REG_HWSTAT, value); + sm_read_regs (ssm, dev, reg, 1); +} + +static void +sm_set_hwstat (FpiSsm *ssm, + FpImageDevice *dev, + unsigned char value) +{ + fp_dbg ("set %02x", value); + sm_write_reg (ssm, dev, REG_HWSTAT, value); } /***** IMAGING LOOP *****/ enum imaging_states { - IMAGING_CAPTURE, - IMAGING_SEND_INDEX, - IMAGING_READ_KEY, - IMAGING_DECODE, - IMAGING_REPORT_IMAGE, - IMAGING_NUM_STATES + IMAGING_CAPTURE, + IMAGING_SEND_INDEX, + IMAGING_READ_KEY, + IMAGING_DECODE, + IMAGING_REPORT_IMAGE, + IMAGING_NUM_STATES }; -struct uru4k_image { - uint8_t unknown_00[4]; - uint16_t num_lines; - uint8_t key_number; - uint8_t unknown_07[9]; - struct { - uint8_t flags; - uint8_t num_lines; - } block_info[15]; - uint8_t unknown_2E[18]; - uint8_t data[IMAGE_HEIGHT][IMAGE_WIDTH]; -}; - -static void image_transfer_cb(struct libusb_transfer *transfer, - struct fp_dev *dev, - fpi_ssm *ssm, - void *user_data) +struct uru4k_image { - if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { - fp_dbg("cancelled"); - fpi_ssm_mark_failed(ssm, -ECANCELED); - } else if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fp_dbg("error"); - fpi_ssm_mark_failed(ssm, -EIO); - } else { - struct uru4k_dev *urudev = FP_INSTANCE_DATA(dev); + uint8_t unknown_00[4]; + uint16_t num_lines; + uint8_t key_number; + uint8_t unknown_07[9]; + struct + { + uint8_t flags; + uint8_t num_lines; + } block_info[15]; + uint8_t unknown_2E[18]; + uint8_t data[IMAGE_HEIGHT][IMAGE_WIDTH]; +}; - urudev->img_data = g_memdup(transfer->buffer, sizeof(struct uru4k_image)); - urudev->img_data_actual_length = transfer->actual_length; - fpi_ssm_next_state(ssm); - } +static void +image_transfer_cb (FpiUsbTransfer *transfer, FpDevice *dev, + gpointer user_data, GError *error) +{ + FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev); + FpiSsm *ssm = transfer->ssm; + + if (error) + { + fp_dbg ("error"); + fpi_ssm_mark_failed (ssm, error); + } + else + { + self->img_data = g_memdup (transfer->buffer, sizeof (struct uru4k_image)); + self->img_data_actual_length = transfer->actual_length; + fpi_ssm_next_state (ssm); + } } enum { - BLOCKF_CHANGE_KEY = 0x80, - BLOCKF_NO_KEY_UPDATE = 0x04, - BLOCKF_ENCRYPTED = 0x02, - BLOCKF_NOT_PRESENT = 0x01, + BLOCKF_CHANGE_KEY = 0x80, + BLOCKF_NO_KEY_UPDATE = 0x04, + BLOCKF_ENCRYPTED = 0x02, + BLOCKF_NOT_PRESENT = 0x01, }; -static uint32_t update_key(uint32_t key) +static uint32_t +update_key (uint32_t key) { - /* linear feedback shift register - * taps at bit positions 1 3 4 7 11 13 20 23 26 29 32 */ - uint32_t bit = key & 0x9248144d; - bit ^= bit << 16; - bit ^= bit << 8; - bit ^= bit << 4; - bit ^= bit << 2; - bit ^= bit << 1; - return (bit & 0x80000000) | (key >> 1); + /* linear feedback shift register + * taps at bit positions 1 3 4 7 11 13 20 23 26 29 32 */ + uint32_t bit = key & 0x9248144d; + + bit ^= bit << 16; + bit ^= bit << 8; + bit ^= bit << 4; + bit ^= bit << 2; + bit ^= bit << 1; + return (bit & 0x80000000) | (key >> 1); } -static uint32_t do_decode(uint8_t *data, int num_bytes, uint32_t key) +static uint32_t +do_decode (uint8_t *data, int num_bytes, uint32_t key) { - uint8_t xorbyte; - int i; + uint8_t xorbyte; + int i; - for (i = 0; i < num_bytes - 1; i++) { - /* calculate xor byte and update key */ - xorbyte = ((key >> 4) & 1) << 0; - xorbyte |= ((key >> 8) & 1) << 1; - xorbyte |= ((key >> 11) & 1) << 2; - xorbyte |= ((key >> 14) & 1) << 3; - xorbyte |= ((key >> 18) & 1) << 4; - xorbyte |= ((key >> 21) & 1) << 5; - xorbyte |= ((key >> 24) & 1) << 6; - xorbyte |= ((key >> 29) & 1) << 7; - key = update_key(key); + for (i = 0; i < num_bytes - 1; i++) + { + /* calculate xor byte and update key */ + xorbyte = ((key >> 4) & 1) << 0; + xorbyte |= ((key >> 8) & 1) << 1; + xorbyte |= ((key >> 11) & 1) << 2; + xorbyte |= ((key >> 14) & 1) << 3; + xorbyte |= ((key >> 18) & 1) << 4; + xorbyte |= ((key >> 21) & 1) << 5; + xorbyte |= ((key >> 24) & 1) << 6; + xorbyte |= ((key >> 29) & 1) << 7; + key = update_key (key); - /* decrypt data */ - data[i] = data[i+1] ^ xorbyte; - } + /* decrypt data */ + data[i] = data[i + 1] ^ xorbyte; + } - /* the final byte is implicitly zero */ - data[i] = 0; - return update_key(key); + /* the final byte is implicitly zero */ + data[i] = 0; + return update_key (key); } -static int calc_dev2(struct uru4k_image *img) +static int +calc_dev2 (struct uru4k_image *img) { - uint8_t *b[2] = { NULL, NULL }; - int res = 0, mean = 0, i, r, j, idx; + uint8_t *b[2] = { NULL, NULL }; + int res = 0, mean = 0, i, r, j, idx; - for (i = r = idx = 0; i < G_N_ELEMENTS(img->block_info) && idx < 2; i++) { - if (img->block_info[i].flags & BLOCKF_NOT_PRESENT) - continue; - for (j = 0; j < img->block_info[i].num_lines && idx < 2; j++) - b[idx++] = img->data[r++]; - } - if (!b[0] || !b[1]) { - fp_dbg("NULL! %p %p", b[0], b[1]); - return 0; - } - for (i = 0; i < IMAGE_WIDTH; i++) - mean += (int)b[0][i] + (int)b[1][i]; + for (i = r = idx = 0; i < G_N_ELEMENTS (img->block_info) && idx < 2; i++) + { + if (img->block_info[i].flags & BLOCKF_NOT_PRESENT) + continue; + for (j = 0; j < img->block_info[i].num_lines && idx < 2; j++) + b[idx++] = img->data[r++]; + } + if (!b[0] || !b[1]) + { + fp_dbg ("NULL! %p %p", b[0], b[1]); + return 0; + } + for (i = 0; i < IMAGE_WIDTH; i++) + mean += (int) b[0][i] + (int) b[1][i]; - mean /= IMAGE_WIDTH; + mean /= IMAGE_WIDTH; - for (i = 0; i < IMAGE_WIDTH; i++) { - int dev = (int)b[0][i] + (int)b[1][i] - mean; - res += dev * dev; - } + for (i = 0; i < IMAGE_WIDTH; i++) + { + int dev = (int) b[0][i] + (int) b[1][i] - mean; + res += dev * dev; + } - return res / IMAGE_WIDTH; + return res / IMAGE_WIDTH; } -static void imaging_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +imaging_run_state (FpiSsm *ssm, FpDevice *_dev) { - struct fp_img_dev *dev = user_data; - struct uru4k_dev *urudev = FP_INSTANCE_DATA(_dev); - struct uru4k_image *img = urudev->img_data; - struct fp_img *fpimg; - uint32_t key; - uint8_t flags, num_lines; - int i, r, to, dev2; - unsigned char buf[5]; + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (_dev); + struct uru4k_image *img = self->img_data; + FpImage *fpimg; + uint32_t key; + uint8_t flags, num_lines; + int i, r, to, dev2; + unsigned char buf[5]; - switch (fpi_ssm_get_cur_state(ssm)) { - case IMAGING_CAPTURE: - urudev->img_lines_done = 0; - urudev->img_block = 0; - r = fpi_usb_submit_transfer(urudev->img_transfer); - if (r < 0) { - urudev->img_transfer = NULL; - fpi_ssm_mark_failed(ssm, -EIO); - } - break; - case IMAGING_SEND_INDEX: - fp_dbg("hw header lines %d", img->num_lines); + switch (fpi_ssm_get_cur_state (ssm)) + { + case IMAGING_CAPTURE: + self->img_lines_done = 0; + self->img_block = 0; + fpi_usb_transfer_submit (self->img_transfer, 0, NULL, image_transfer_cb, NULL); - if (img->num_lines >= IMAGE_HEIGHT || - urudev->img_data_actual_length < img->num_lines * IMAGE_WIDTH + 64) { - fp_err("bad captured image (%d lines) or size mismatch %d < %d", - img->num_lines, - urudev->img_data_actual_length, - img->num_lines * IMAGE_WIDTH + 64); - fpi_ssm_jump_to_state(ssm, IMAGING_CAPTURE); - return; - } - if (!urudev->profile->encryption) { - dev2 = calc_dev2(img); - fp_dbg("dev2: %d", dev2); - if (dev2 < ENC_THRESHOLD) { - fpi_ssm_jump_to_state(ssm, IMAGING_REPORT_IMAGE); - return; - } - fp_info("image seems to be encrypted"); - } - buf[0] = img->key_number; - buf[1] = urudev->img_enc_seed; - buf[2] = urudev->img_enc_seed >> 8; - buf[3] = urudev->img_enc_seed >> 16; - buf[4] = urudev->img_enc_seed >> 24; - sm_write_regs(ssm, dev, REG_SCRAMBLE_DATA_INDEX, 5, buf); - break; - case IMAGING_READ_KEY: - sm_read_regs(ssm, dev, REG_SCRAMBLE_DATA_KEY, 4); - break; - case IMAGING_DECODE: - key = urudev->last_reg_rd[0]; - key |= urudev->last_reg_rd[1] << 8; - key |= urudev->last_reg_rd[2] << 16; - key |= urudev->last_reg_rd[3] << 24; - key ^= urudev->img_enc_seed; + break; - fp_dbg("encryption id %02x -> key %08x", img->key_number, key); - while (urudev->img_block < G_N_ELEMENTS(img->block_info) && - urudev->img_lines_done < img->num_lines) { - flags = img->block_info[urudev->img_block].flags; - num_lines = img->block_info[urudev->img_block].num_lines; - if (num_lines == 0) - break; + case IMAGING_SEND_INDEX: + fp_dbg ("hw header lines %d", img->num_lines); - fp_dbg("%d %02x %d", urudev->img_block, flags, num_lines); - if (flags & BLOCKF_CHANGE_KEY) { - fp_dbg("changing encryption keys.\n"); - img->block_info[urudev->img_block].flags &= ~BLOCKF_CHANGE_KEY; - img->key_number++; - urudev->img_enc_seed = rand(); - fpi_ssm_jump_to_state(ssm, IMAGING_SEND_INDEX); - return; - } - switch (flags & (BLOCKF_NO_KEY_UPDATE | BLOCKF_ENCRYPTED)) { - case BLOCKF_ENCRYPTED: - fp_dbg("decoding %d lines", num_lines); - key = do_decode(&img->data[urudev->img_lines_done][0], - IMAGE_WIDTH*num_lines, key); - break; - case 0: - fp_dbg("skipping %d lines", num_lines); - for (r = 0; r < IMAGE_WIDTH*num_lines; r++) - key = update_key(key); - break; - } - if ((flags & BLOCKF_NOT_PRESENT) == 0) - urudev->img_lines_done += num_lines; - urudev->img_block++; - } - fpi_ssm_next_state(ssm); - break; - case IMAGING_REPORT_IMAGE: - fpimg = fpi_img_new_for_imgdev(dev); + if (img->num_lines >= IMAGE_HEIGHT || + self->img_data_actual_length < img->num_lines * IMAGE_WIDTH + 64) + { + fp_err ("bad captured image (%d lines) or size mismatch %d < %d", + img->num_lines, + self->img_data_actual_length, + img->num_lines * IMAGE_WIDTH + 64); + fpi_ssm_jump_to_state (ssm, IMAGING_CAPTURE); + return; + } + if (!self->profile->encryption) + { + dev2 = calc_dev2 (img); + fp_dbg ("dev2: %d", dev2); + if (dev2 < ENC_THRESHOLD) + { + fpi_ssm_jump_to_state (ssm, IMAGING_REPORT_IMAGE); + return; + } + fp_info ("image seems to be encrypted"); + } + buf[0] = img->key_number; + buf[1] = self->img_enc_seed; + buf[2] = self->img_enc_seed >> 8; + buf[3] = self->img_enc_seed >> 16; + buf[4] = self->img_enc_seed >> 24; + sm_write_regs (ssm, dev, REG_SCRAMBLE_DATA_INDEX, 5, buf); + break; - to = r = 0; - for (i = 0; i < G_N_ELEMENTS(img->block_info) && r < img->num_lines; i++) { - flags = img->block_info[i].flags; - num_lines = img->block_info[i].num_lines; - if (num_lines == 0) - break; - memcpy(&fpimg->data[to], &img->data[r][0], - num_lines * IMAGE_WIDTH); - if (!(flags & BLOCKF_NOT_PRESENT)) - r += num_lines; - to += num_lines * IMAGE_WIDTH; - } + case IMAGING_READ_KEY: + sm_read_regs (ssm, dev, REG_SCRAMBLE_DATA_KEY, 4); + break; - fpimg->flags = FP_IMG_COLORS_INVERTED; - if (!urudev->profile->encryption) - fpimg->flags |= FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED; - fpi_imgdev_image_captured(dev, fpimg); + case IMAGING_DECODE: + key = self->last_reg_rd[0]; + key |= self->last_reg_rd[1] << 8; + key |= self->last_reg_rd[2] << 16; + key |= self->last_reg_rd[3] << 24; + key ^= self->img_enc_seed; - if (urudev->activate_state == IMGDEV_STATE_CAPTURE) - fpi_ssm_jump_to_state(ssm, IMAGING_CAPTURE); - else - fpi_ssm_mark_completed(ssm); - break; - } + fp_dbg ("encryption id %02x -> key %08x", img->key_number, key); + while (self->img_block < G_N_ELEMENTS (img->block_info) && + self->img_lines_done < img->num_lines) + { + flags = img->block_info[self->img_block].flags; + num_lines = img->block_info[self->img_block].num_lines; + if (num_lines == 0) + break; + + fp_dbg ("%d %02x %d", self->img_block, flags, + num_lines); + if (flags & BLOCKF_CHANGE_KEY) + { + fp_dbg ("changing encryption keys.\n"); + img->block_info[self->img_block].flags &= ~BLOCKF_CHANGE_KEY; + img->key_number++; + self->img_enc_seed = rand (); + fpi_ssm_jump_to_state (ssm, IMAGING_SEND_INDEX); + return; + } + switch (flags & (BLOCKF_NO_KEY_UPDATE | BLOCKF_ENCRYPTED)) + { + case BLOCKF_ENCRYPTED: + fp_dbg ("decoding %d lines", num_lines); + key = do_decode (&img->data[self->img_lines_done][0], + IMAGE_WIDTH * num_lines, key); + break; + + case 0: + fp_dbg ("skipping %d lines", num_lines); + for (r = 0; r < IMAGE_WIDTH * num_lines; r++) + key = update_key (key); + break; + } + if ((flags & BLOCKF_NOT_PRESENT) == 0) + self->img_lines_done += num_lines; + self->img_block++; + } + fpi_ssm_next_state (ssm); + break; + + case IMAGING_REPORT_IMAGE: + fpimg = fp_image_new (IMAGE_WIDTH, IMAGE_HEIGHT); + + to = r = 0; + for (i = 0; i < G_N_ELEMENTS (img->block_info) && r < img->num_lines; i++) + { + flags = img->block_info[i].flags; + num_lines = img->block_info[i].num_lines; + if (num_lines == 0) + break; + memcpy (&fpimg->data[to], &img->data[r][0], + num_lines * IMAGE_WIDTH); + if (!(flags & BLOCKF_NOT_PRESENT)) + r += num_lines; + to += num_lines * IMAGE_WIDTH; + } + + fpimg->flags = FPI_IMAGE_COLORS_INVERTED; + if (!self->profile->encryption) + fpimg->flags |= FPI_IMAGE_V_FLIPPED | FPI_IMAGE_H_FLIPPED; + fpi_image_device_image_captured (dev, fpimg); + + if (self->activate_state == FP_IMAGE_DEVICE_STATE_CAPTURE) + fpi_ssm_jump_to_state (ssm, IMAGING_CAPTURE); + else + fpi_ssm_mark_completed (ssm); + break; + } } -static void imaging_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +imaging_complete (FpiSsm *ssm, FpDevice *dev, GError *error) { - struct fp_img_dev *dev = user_data; - struct uru4k_dev *urudev = FP_INSTANCE_DATA(_dev); - int r = fpi_ssm_get_error(ssm); - fpi_ssm_free(ssm); + FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev); - /* Report error before exiting imaging loop - the error handler - * can request state change, which needs to be postponed to end of - * this function. */ - if (r) - fpi_imgdev_session_error(dev, r); + fpi_ssm_free (ssm); - /* Freed by callback or cancellation */ - urudev->img_transfer = NULL; + /* Report error before exiting imaging loop - the error handler + * can request state change, which needs to be postponed to end of + * this function. */ + if (error) + fpi_image_device_session_error (FP_IMAGE_DEVICE (dev), error); - g_free(urudev->img_data); - urudev->img_data = NULL; - urudev->img_data_actual_length = 0; + /* Freed by callback or cancellation */ + self->img_transfer = NULL; - r = execute_state_change(dev); - if (r) - fpi_imgdev_session_error(dev, r); + g_free (self->img_data); + self->img_data = NULL; + self->img_data_actual_length = 0; + + execute_state_change (FP_IMAGE_DEVICE (dev)); } /***** INITIALIZATION *****/ @@ -868,53 +826,62 @@ static void imaging_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) * and fails after 100 tries. */ enum rebootpwr_states { - REBOOTPWR_SET_HWSTAT = 0, - REBOOTPWR_GET_HWSTAT, - REBOOTPWR_CHECK_HWSTAT, - REBOOTPWR_PAUSE, - REBOOTPWR_NUM_STATES, + REBOOTPWR_SET_HWSTAT = 0, + REBOOTPWR_GET_HWSTAT, + REBOOTPWR_CHECK_HWSTAT, + REBOOTPWR_PAUSE, + REBOOTPWR_NUM_STATES, }; static void -rebootpwr_pause_cb(struct fp_dev *dev, - void *data) +rebootpwr_pause_cb (FpDevice *dev, + void *data) { - fpi_ssm *ssm = data; - struct uru4k_dev *urudev = FP_INSTANCE_DATA(dev); + FpiSsm *ssm = data; + FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev); - if (!--urudev->rebootpwr_ctr) { - fp_err("could not reboot device power"); - fpi_ssm_mark_failed(ssm, -EIO); - } else { - fpi_ssm_jump_to_state(ssm, REBOOTPWR_GET_HWSTAT); - } + if (!--self->rebootpwr_ctr) + { + fp_err ("could not reboot device power"); + fpi_ssm_mark_failed (ssm, + fpi_device_error_new_msg (FP_DEVICE_ERROR, + "Could not reboot device")); + } + else + { + fpi_ssm_jump_to_state (ssm, REBOOTPWR_GET_HWSTAT); + } } -static void rebootpwr_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +rebootpwr_run_state (FpiSsm *ssm, FpDevice *_dev) { - struct fp_img_dev *dev = user_data; - struct uru4k_dev *urudev = FP_INSTANCE_DATA(_dev); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (_dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case REBOOTPWR_SET_HWSTAT: - urudev->rebootpwr_ctr = 100; - sm_set_hwstat(ssm, dev, urudev->last_hwstat & 0xf); - break; - case REBOOTPWR_GET_HWSTAT: - sm_read_reg(ssm, dev, REG_HWSTAT); - break; - case REBOOTPWR_CHECK_HWSTAT: - urudev->last_hwstat = urudev->last_reg_rd[0]; - if (urudev->last_hwstat & 0x1) - fpi_ssm_mark_completed(ssm); - else - fpi_ssm_next_state(ssm); - break; - case REBOOTPWR_PAUSE: - if (fpi_timeout_add(10, rebootpwr_pause_cb, _dev, ssm) == NULL) - fpi_ssm_mark_failed(ssm, -ETIME); - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case REBOOTPWR_SET_HWSTAT: + self->rebootpwr_ctr = 100; + sm_set_hwstat (ssm, dev, self->last_hwstat & 0xf); + break; + + case REBOOTPWR_GET_HWSTAT: + sm_read_reg (ssm, dev, REG_HWSTAT); + break; + + case REBOOTPWR_CHECK_HWSTAT: + self->last_hwstat = self->last_reg_rd[0]; + if (self->last_hwstat & 0x1) + fpi_ssm_mark_completed (ssm); + else + fpi_ssm_next_state (ssm); + break; + + case REBOOTPWR_PAUSE: + fpi_device_add_timeout (_dev, 10, rebootpwr_pause_cb, ssm); + break; + } } /* After messing with the device firmware in its low-power state, we have to @@ -926,511 +893,586 @@ static void rebootpwr_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_da * * This is implemented as the powerup state machine below. Pseudo-code: - status = get_hwstat(); - for (i = 0; i < 100; i++) { - set_hwstat(status & 0xf); - if ((get_hwstat() & 0x80) == 0) - break; + status = get_hwstat(); + for (i = 0; i < 100; i++) { + set_hwstat(status & 0xf); + if ((get_hwstat() & 0x80) == 0) + break; - usleep(10000); - if (need_auth_cr) - auth_cr(); - } + usleep(10000); + if (need_auth_cr) + auth_cr(); + } - if (tmp & 0x80) - error("could not power up device"); + if (tmp & 0x80) + error("could not power up device"); */ enum powerup_states { - POWERUP_INIT = 0, - POWERUP_SET_HWSTAT, - POWERUP_GET_HWSTAT, - POWERUP_CHECK_HWSTAT, - POWERUP_PAUSE, - POWERUP_CHALLENGE_RESPONSE, - POWERUP_CHALLENGE_RESPONSE_SUCCESS, - POWERUP_NUM_STATES, + POWERUP_INIT = 0, + POWERUP_SET_HWSTAT, + POWERUP_GET_HWSTAT, + POWERUP_CHECK_HWSTAT, + POWERUP_PAUSE, + POWERUP_CHALLENGE_RESPONSE, + POWERUP_CHALLENGE_RESPONSE_SUCCESS, + POWERUP_NUM_STATES, }; static void -powerup_pause_cb(struct fp_dev *dev, - void *data) +powerup_pause_cb (FpDevice *dev, + void *data) { - fpi_ssm *ssm = data; - struct uru4k_dev *urudev = FP_INSTANCE_DATA(dev); + FpiSsm *ssm = data; + FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev); - if (!--urudev->powerup_ctr) { - fp_err("could not power device up"); - fpi_ssm_mark_failed(ssm, -EIO); - } else if (!urudev->profile->auth_cr) { - fpi_ssm_jump_to_state(ssm, POWERUP_SET_HWSTAT); - } else { - fpi_ssm_next_state(ssm); - } + if (!--self->powerup_ctr) + { + fp_err ("could not power device up"); + fpi_ssm_mark_failed (ssm, + fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, + "could not power device up")); + } + else if (!self->profile->auth_cr) + { + fpi_ssm_jump_to_state (ssm, POWERUP_SET_HWSTAT); + } + else + { + fpi_ssm_next_state (ssm); + } } -static void powerup_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +powerup_run_state (FpiSsm *ssm, FpDevice *_dev) { - struct fp_img_dev *dev = user_data; - struct uru4k_dev *urudev = FP_INSTANCE_DATA(_dev); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (_dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case POWERUP_INIT: - urudev->powerup_ctr = 100; - urudev->powerup_hwstat = urudev->last_hwstat & 0xf; - fpi_ssm_next_state(ssm); - break; - case POWERUP_SET_HWSTAT: - sm_set_hwstat(ssm, dev, urudev->powerup_hwstat); - break; - case POWERUP_GET_HWSTAT: - sm_read_reg(ssm, dev, REG_HWSTAT); - break; - case POWERUP_CHECK_HWSTAT: - urudev->last_hwstat = urudev->last_reg_rd[0]; - if ((urudev->last_reg_rd[0] & 0x80) == 0) - fpi_ssm_mark_completed(ssm); - else - fpi_ssm_next_state(ssm); - break; - case POWERUP_PAUSE: - if (fpi_timeout_add(10, powerup_pause_cb, _dev, ssm) == NULL) - fpi_ssm_mark_failed(ssm, -ETIME); - break; - case POWERUP_CHALLENGE_RESPONSE: - sm_do_challenge_response(ssm, dev); - break; - case POWERUP_CHALLENGE_RESPONSE_SUCCESS: - fpi_ssm_jump_to_state(ssm, POWERUP_SET_HWSTAT); - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case POWERUP_INIT: + self->powerup_ctr = 100; + self->powerup_hwstat = self->last_hwstat & 0xf; + fpi_ssm_next_state (ssm); + break; + + case POWERUP_SET_HWSTAT: + sm_set_hwstat (ssm, dev, self->powerup_hwstat); + break; + + case POWERUP_GET_HWSTAT: + sm_read_reg (ssm, dev, REG_HWSTAT); + break; + + case POWERUP_CHECK_HWSTAT: + self->last_hwstat = self->last_reg_rd[0]; + if ((self->last_reg_rd[0] & 0x80) == 0) + fpi_ssm_mark_completed (ssm); + else + fpi_ssm_next_state (ssm); + break; + + case POWERUP_PAUSE: + fpi_device_add_timeout (_dev, 10, powerup_pause_cb, ssm); + break; + + case POWERUP_CHALLENGE_RESPONSE: + sm_do_challenge_response (ssm, dev); + break; + + case POWERUP_CHALLENGE_RESPONSE_SUCCESS: + fpi_ssm_jump_to_state (ssm, POWERUP_SET_HWSTAT); + break; + } } /* * This is the main initialization state machine. As pseudo-code: - status = get_hwstat(); + status = get_hwstat(); - // correct device power state - if ((status & 0x84) == 0x84) - run_reboot_sm(); + // correct device power state + if ((status & 0x84) == 0x84) + run_reboot_sm(); - // power device down - if ((status & 0x80) == 0) - set_hwstat(status | 0x80); + // power device down + if ((status & 0x80) == 0) + set_hwstat(status | 0x80); - // power device up - run_powerup_sm(); - await_irq(IRQDATA_SCANPWR_ON); + // power device up + run_powerup_sm(); + await_irq(IRQDATA_SCANPWR_ON); */ enum init_states { - INIT_GET_HWSTAT = 0, - INIT_CHECK_HWSTAT_REBOOT, - INIT_REBOOT_POWER, - INIT_CHECK_HWSTAT_POWERDOWN, - INIT_POWERUP, - INIT_AWAIT_SCAN_POWER, - INIT_DONE, - INIT_GET_VERSION, - INIT_REPORT_VERSION, - INIT_NUM_STATES, + INIT_GET_HWSTAT = 0, + INIT_CHECK_HWSTAT_REBOOT, + INIT_REBOOT_POWER, + INIT_CHECK_HWSTAT_POWERDOWN, + INIT_POWERUP, + INIT_AWAIT_SCAN_POWER, + INIT_DONE, + INIT_GET_VERSION, + INIT_REPORT_VERSION, + INIT_NUM_STATES, }; -static void init_scanpwr_irq_cb(struct fp_img_dev *dev, int status, - uint16_t type, void *user_data) +static void +init_scanpwr_irq_cb (FpImageDevice *dev, GError *error, + uint16_t type, void *user_data) { - fpi_ssm *ssm = user_data; - struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiSsm *ssm = user_data; + FpiDeviceUru4000 *urudev = FPI_DEVICE_URU4000 (dev); - if (status) - fpi_ssm_mark_failed(ssm, status); - else if (type != IRQDATA_SCANPWR_ON) - fp_dbg("ignoring interrupt"); - else if (fpi_ssm_get_cur_state(ssm) != INIT_AWAIT_SCAN_POWER) { - fp_dbg("early scanpwr interrupt"); - urudev->scanpwr_irq_timeouts = -1; - } else { - fp_dbg("late scanpwr interrupt"); - fpi_ssm_next_state(ssm); - } + if (error) + { + fpi_ssm_mark_failed (ssm, error); + } + else if (type != IRQDATA_SCANPWR_ON) + { + fp_dbg ("ignoring interrupt"); + } + else if (fpi_ssm_get_cur_state (ssm) != INIT_AWAIT_SCAN_POWER) + { + fp_dbg ("early scanpwr interrupt"); + urudev->scanpwr_irq_timeouts = -1; + } + else + { + fp_dbg ("late scanpwr interrupt"); + fpi_ssm_next_state (ssm); + } } static void -init_scanpwr_timeout(struct fp_dev *dev, - void *user_data) +init_scanpwr_timeout (FpDevice *dev, + void *user_data) { - fpi_ssm *ssm = user_data; - struct uru4k_dev *urudev = FP_INSTANCE_DATA(dev); + FpiSsm *ssm = user_data; + FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev); - fp_warn("powerup timed out"); - urudev->irq_cb = NULL; - urudev->scanpwr_irq_timeout = NULL; + fp_warn ("powerup timed out"); + self->irq_cb = NULL; + self->scanpwr_irq_timeout = NULL; - if (++urudev->scanpwr_irq_timeouts >= 3) { - fp_err("powerup timed out 3 times, giving up"); - fpi_ssm_mark_failed(ssm, -ETIMEDOUT); - } else { - fpi_ssm_jump_to_state(ssm, INIT_GET_HWSTAT); - } + if (++self->scanpwr_irq_timeouts >= 3) + { + fp_err ("powerup timed out 3 times, giving up"); + fpi_ssm_mark_failed (ssm, + g_error_new_literal (G_USB_DEVICE_ERROR, + G_USB_DEVICE_ERROR_TIMED_OUT, + "Powerup timed out 3 times, giving up")); + } + else + { + fpi_ssm_jump_to_state (ssm, INIT_GET_HWSTAT); + } } -static void init_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +init_run_state (FpiSsm *ssm, FpDevice *_dev) { - struct fp_img_dev *dev = user_data; - struct uru4k_dev *urudev = FP_INSTANCE_DATA(_dev); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (_dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case INIT_GET_HWSTAT: - sm_read_reg(ssm, dev, REG_HWSTAT); - break; - case INIT_CHECK_HWSTAT_REBOOT: - urudev->last_hwstat = urudev->last_reg_rd[0]; - if ((urudev->last_hwstat & 0x84) == 0x84) - fpi_ssm_next_state(ssm); - else - fpi_ssm_jump_to_state(ssm, INIT_CHECK_HWSTAT_POWERDOWN); - break; - case INIT_REBOOT_POWER: ; - fpi_ssm *rebootsm = fpi_ssm_new(FP_DEV(dev), rebootpwr_run_state, - REBOOTPWR_NUM_STATES, dev); - fpi_ssm_start_subsm(ssm, rebootsm); - break; - case INIT_CHECK_HWSTAT_POWERDOWN: - if ((urudev->last_hwstat & 0x80) == 0) - sm_set_hwstat(ssm, dev, urudev->last_hwstat | 0x80); - else - fpi_ssm_next_state(ssm); - break; - case INIT_POWERUP: ; - if (!IRQ_HANDLER_IS_RUNNING(urudev)) { - fpi_ssm_mark_failed(ssm, -EIO); - break; - } - urudev->irq_cb_data = ssm; - urudev->irq_cb = init_scanpwr_irq_cb; + switch (fpi_ssm_get_cur_state (ssm)) + { + case INIT_GET_HWSTAT: + sm_read_reg (ssm, dev, REG_HWSTAT); + break; - fpi_ssm *powerupsm = fpi_ssm_new(FP_DEV(dev), powerup_run_state, - POWERUP_NUM_STATES, dev); - fpi_ssm_start_subsm(ssm, powerupsm); - break; - case INIT_AWAIT_SCAN_POWER: - if (urudev->scanpwr_irq_timeouts < 0) { - fpi_ssm_next_state(ssm); - break; - } + case INIT_CHECK_HWSTAT_REBOOT: + self->last_hwstat = self->last_reg_rd[0]; + if ((self->last_hwstat & 0x84) == 0x84) + fpi_ssm_next_state (ssm); + else + fpi_ssm_jump_to_state (ssm, INIT_CHECK_HWSTAT_POWERDOWN); + break; - /* sometimes the 56aa interrupt that we are waiting for never arrives, - * so we include this timeout loop to retry the whole process 3 times - * if we don't get an irq any time soon. */ - urudev->scanpwr_irq_timeout = fpi_timeout_add(300, - init_scanpwr_timeout, - _dev, ssm); - if (!urudev->scanpwr_irq_timeout) { - fpi_ssm_mark_failed(ssm, -ETIME); - break; - } - break; - case INIT_DONE: - if (urudev->scanpwr_irq_timeout) { - fpi_timeout_cancel(urudev->scanpwr_irq_timeout); - urudev->scanpwr_irq_timeout = NULL; - } - urudev->irq_cb_data = NULL; - urudev->irq_cb = NULL; - fpi_ssm_next_state(ssm); - break; - case INIT_GET_VERSION: - sm_read_regs(ssm, dev, REG_DEVICE_INFO, 16); - break; - case INIT_REPORT_VERSION: - /* Likely hardware revision, and firmware version. - * Not sure which is which. */ - fp_info("Versions %02x%02x and %02x%02x", - urudev->last_reg_rd[10], urudev->last_reg_rd[11], - urudev->last_reg_rd[4], urudev->last_reg_rd[5]); - fpi_ssm_mark_completed(ssm); - break; - } + case INIT_REBOOT_POWER:; + FpiSsm *rebootsm = fpi_ssm_new (FP_DEVICE (dev), + rebootpwr_run_state, + REBOOTPWR_NUM_STATES); + fpi_ssm_start_subsm (ssm, rebootsm); + break; + + case INIT_CHECK_HWSTAT_POWERDOWN: + if ((self->last_hwstat & 0x80) == 0) + sm_set_hwstat (ssm, dev, self->last_hwstat | 0x80); + else + fpi_ssm_next_state (ssm); + break; + + case INIT_POWERUP: + if (!IRQ_HANDLER_IS_RUNNING (self)) + { + fpi_ssm_mark_failed (ssm, fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, + "IRQ handler should be running but is not")); + return; + } + self->irq_cb_data = ssm; + self->irq_cb = init_scanpwr_irq_cb; + + FpiSsm *powerupsm = fpi_ssm_new (FP_DEVICE (dev), + powerup_run_state, + POWERUP_NUM_STATES); + fpi_ssm_start_subsm (ssm, powerupsm); + break; + + case INIT_AWAIT_SCAN_POWER: + if (self->scanpwr_irq_timeouts < 0) + { + fpi_ssm_next_state (ssm); + break; + } + + /* sometimes the 56aa interrupt that we are waiting for never arrives, + * so we include this timeout loop to retry the whole process 3 times + * if we don't get an irq any time soon. */ + self->scanpwr_irq_timeout = fpi_device_add_timeout (_dev, + 300, + init_scanpwr_timeout, + ssm); + break; + + case INIT_DONE: + if (self->scanpwr_irq_timeout) + { + g_source_destroy (self->scanpwr_irq_timeout); + self->scanpwr_irq_timeout = NULL; + } + self->irq_cb_data = NULL; + self->irq_cb = NULL; + fpi_ssm_next_state (ssm); + break; + + case INIT_GET_VERSION: + sm_read_regs (ssm, dev, REG_DEVICE_INFO, 16); + break; + + case INIT_REPORT_VERSION: + /* Likely hardware revision, and firmware version. + * Not sure which is which. */ + fp_info ("Versions %02x%02x and %02x%02x", + self->last_reg_rd[10], self->last_reg_rd[11], + self->last_reg_rd[4], self->last_reg_rd[5]); + fpi_ssm_mark_completed (ssm); + break; + } } -static void activate_initsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +activate_initsm_complete (FpiSsm *ssm, FpDevice *dev, GError *error) { - struct fp_img_dev *dev = user_data; - int r = fpi_ssm_get_error(ssm); - fpi_ssm_free(ssm); - - fpi_imgdev_activate_complete(dev, r); + fpi_image_device_activate_complete (FP_IMAGE_DEVICE (dev), error); } -static int dev_activate(struct fp_img_dev *dev) +static void +dev_activate (FpImageDevice *dev) { - struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_ssm *ssm; - int r; + FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev); + FpiSsm *ssm; - r = start_irq_handler(dev); - if (r < 0) - return r; + start_irq_handler (dev); - urudev->scanpwr_irq_timeouts = 0; - ssm = fpi_ssm_new(FP_DEV(dev), init_run_state, INIT_NUM_STATES, dev); - fpi_ssm_start(ssm, activate_initsm_complete); - return 0; + self->scanpwr_irq_timeouts = 0; + ssm = fpi_ssm_new (FP_DEVICE (dev), init_run_state, INIT_NUM_STATES); + fpi_ssm_start (ssm, activate_initsm_complete); } /***** DEINITIALIZATION *****/ -static void deactivate_irqs_stopped(struct fp_img_dev *dev) +static void +deactivate_irqs_stopped (FpImageDevice *dev) { - fpi_imgdev_deactivate_complete(dev); + fpi_image_device_deactivate_complete (dev, NULL); } -static void deactivate_write_reg_cb(struct fp_img_dev *dev, int status, - void *user_data) +static void +deactivate_write_reg_cb (FpiUsbTransfer *transfer, FpDevice *dev, + gpointer user_data, GError *error) { - stop_irq_handler(dev, deactivate_irqs_stopped); + stop_irq_handler (FP_IMAGE_DEVICE (dev), deactivate_irqs_stopped); } -static void dev_deactivate(struct fp_img_dev *dev) +static void +dev_deactivate (FpImageDevice *dev) { - dev_change_state(dev, IMGDEV_STATE_INACTIVE); + dev_change_state (dev, FP_IMAGE_DEVICE_STATE_INACTIVE); } -static int execute_state_change(struct fp_img_dev *dev) +static void +execute_state_change (FpImageDevice *dev) { - struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_ssm *ssm; - void *img_data; + FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev); + FpiSsm *ssm; - switch (urudev->activate_state) { - case IMGDEV_STATE_INACTIVE: - fp_dbg("deactivating"); - urudev->irq_cb = NULL; - urudev->irq_cb_data = NULL; - return write_reg(dev, REG_MODE, MODE_OFF, - deactivate_write_reg_cb, NULL); - break; + switch (self->activate_state) + { + case FP_IMAGE_DEVICE_STATE_INACTIVE: + fp_dbg ("deactivating"); + self->irq_cb = NULL; + self->irq_cb_data = NULL; + write_reg (dev, REG_MODE, MODE_OFF, + deactivate_write_reg_cb, NULL); + break; - case IMGDEV_STATE_AWAIT_FINGER_ON: - fp_dbg("wait finger on"); - if (!IRQ_HANDLER_IS_RUNNING(urudev)) - return -EIO; - urudev->irq_cb = finger_presence_irq_cb; - return write_reg(dev, REG_MODE, MODE_AWAIT_FINGER_ON, - change_state_write_reg_cb, NULL); + case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON: + fp_dbg ("wait finger on"); + if (!IRQ_HANDLER_IS_RUNNING (self)) + { + fpi_image_device_session_error (dev, + fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, + "IRQ handler should be running but is not")); + return; + } + self->irq_cb = finger_presence_irq_cb; + write_reg (dev, REG_MODE, MODE_AWAIT_FINGER_ON, + change_state_write_reg_cb, NULL); + break; - case IMGDEV_STATE_CAPTURE: - fp_dbg("starting capture"); - urudev->irq_cb = NULL; + case FP_IMAGE_DEVICE_STATE_CAPTURE: + fp_dbg ("starting capture"); + self->irq_cb = NULL; - ssm = fpi_ssm_new(FP_DEV(dev), imaging_run_state, IMAGING_NUM_STATES, dev); - img_data = g_malloc(sizeof(struct uru4k_image)); - urudev->img_enc_seed = rand(); - urudev->img_transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev), - ssm, - EP_DATA, - img_data, - sizeof(struct uru4k_image), - image_transfer_cb, - NULL, - 0); + ssm = fpi_ssm_new (FP_DEVICE (dev), imaging_run_state, + IMAGING_NUM_STATES); + self->img_enc_seed = rand (); + self->img_transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); + self->img_transfer->ssm = ssm; + self->img_transfer->short_is_error = FALSE; + fpi_usb_transfer_fill_bulk (self->img_transfer, + EP_DATA, + sizeof (struct uru4k_image)); - fpi_ssm_start(ssm, imaging_complete); + fpi_ssm_start (ssm, imaging_complete); - return write_reg(dev, REG_MODE, MODE_CAPTURE, - change_state_write_reg_cb, NULL); + write_reg (dev, REG_MODE, MODE_CAPTURE, + change_state_write_reg_cb, NULL); + break; - case IMGDEV_STATE_AWAIT_FINGER_OFF: - fp_dbg("await finger off"); - if (!IRQ_HANDLER_IS_RUNNING(urudev)) - return -EIO; - urudev->irq_cb = finger_presence_irq_cb; - return write_reg(dev, REG_MODE, MODE_AWAIT_FINGER_OFF, - change_state_write_reg_cb, NULL); - } - - return 0; + case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: + fp_dbg ("await finger off"); + if (!IRQ_HANDLER_IS_RUNNING (self)) + { + fpi_image_device_session_error (dev, + fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, + "IRQ handler should be running but is not")); + return; + } + self->irq_cb = finger_presence_irq_cb; + write_reg (dev, REG_MODE, MODE_AWAIT_FINGER_OFF, + change_state_write_reg_cb, NULL); + break; + } } /***** LIBRARY STUFF *****/ -static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) +static void +dev_init (FpImageDevice *dev) { - struct libusb_config_descriptor *config; - const struct libusb_interface *iface = NULL; - const struct libusb_interface_descriptor *iface_desc; - const struct libusb_endpoint_descriptor *ep; - struct uru4k_dev *urudev; - SECStatus rv; - SECItem item; - int i; - int r; + GError *error = NULL; + FpiDeviceUru4000 *self; - /* Find fingerprint interface */ - r = libusb_get_config_descriptor(libusb_get_device(fpi_dev_get_usb_dev(FP_DEV(dev))), 0, &config); - if (r < 0) { - fp_err("Failed to get config descriptor"); - return r; - } - for (i = 0; i < config->bNumInterfaces; i++) { - const struct libusb_interface *cur_iface = &config->interface[i]; + g_autoptr(GPtrArray) interfaces = NULL; + GUsbInterface *iface = NULL; + guint64 driver_data; + SECStatus rv; + SECItem item; + int i; - if (cur_iface->num_altsetting < 1) - continue; + interfaces = g_usb_device_get_interfaces (fpi_device_get_usb_device (FP_DEVICE (dev)), &error); + if (error) + { + fpi_image_device_open_complete (dev, error); + return; + } - iface_desc = &cur_iface->altsetting[0]; - if (iface_desc->bInterfaceClass == 255 - && iface_desc->bInterfaceSubClass == 255 - && iface_desc->bInterfaceProtocol == 255) { - iface = cur_iface; - break; - } - } + /* Find fingerprint interface; TODO: Move this into probe() */ + for (i = 0; i < interfaces->len; i++) + { + GUsbInterface *cur_iface = g_ptr_array_index (interfaces, i); - if (iface == NULL) { - fp_err("could not find interface"); - r = -ENODEV; - goto out; - } + if (g_usb_interface_get_class (cur_iface) == 255 && + g_usb_interface_get_subclass (cur_iface) == 255 && + g_usb_interface_get_protocol (cur_iface) == 255) + { + iface = cur_iface; + break; + } + } - /* Find/check endpoints */ + if (iface == NULL) + { + fp_err ("could not find interface"); + fpi_image_device_open_complete (dev, + fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, + "Could not find interface")); + return; + } - if (iface_desc->bNumEndpoints != 2) { - fp_err("found %d endpoints!?", iface_desc->bNumEndpoints); - r = -ENODEV; - goto out; - } + /* TODO: Find/check endpoints; does not seem easily possible with GUsb unfortunately! */ +#if 0 + if (iface_desc->bNumEndpoints != 2) + { + fp_err ("found %d endpoints!?", iface_desc->bNumEndpoints); + r = -ENODEV; + goto out; + } - ep = &iface_desc->endpoint[0]; - if (ep->bEndpointAddress != EP_INTR - || (ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) != - LIBUSB_TRANSFER_TYPE_INTERRUPT) { - fp_err("unrecognised interrupt endpoint"); - r = -ENODEV; - goto out; - } + ep = &iface_desc->endpoint[0]; + if (ep->bEndpointAddress != EP_INTR || + (ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) != + LIBUSB_TRANSFER_TYPE_INTERRUPT) + { + fp_err ("unrecognised interrupt endpoint"); + r = -ENODEV; + goto out; + } - ep = &iface_desc->endpoint[1]; - if (ep->bEndpointAddress != EP_DATA - || (ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) != - LIBUSB_TRANSFER_TYPE_BULK) { - fp_err("unrecognised bulk endpoint"); - r = -ENODEV; - goto out; - } + ep = &iface_desc->endpoint[1]; + if (ep->bEndpointAddress != EP_DATA || + (ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) != + LIBUSB_TRANSFER_TYPE_BULK) + { + fp_err ("unrecognised bulk endpoint"); + r = -ENODEV; + goto out; + } +#endif - /* Device looks like a supported reader */ + /* Device looks like a supported reader */ - r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), iface_desc->bInterfaceNumber); - if (r < 0) { - fp_err("interface claim failed: %s", libusb_error_name(r)); - goto out; - } + if (!g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), + g_usb_interface_get_number (iface), 0, &error)) + { + fpi_image_device_open_complete (dev, error); + return; + } - /* Disable loading p11-kit's user configuration */ - g_setenv ("P11_KIT_NO_USER_CONFIG", "1", TRUE); + /* Disable loading p11-kit's user configuration */ + g_setenv ("P11_KIT_NO_USER_CONFIG", "1", TRUE); - /* Initialise NSS early */ - rv = NSS_NoDB_Init("."); - if (rv != SECSuccess) { - fp_err("could not initialise NSS"); - goto out; - } + /* Initialise NSS early */ + rv = NSS_NoDB_Init ("."); + if (rv != SECSuccess) + { + fp_err ("could not initialise NSS"); + fpi_image_device_open_complete (dev, + fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, + "Could not initialise NSS")); + return; + } - urudev = g_malloc0(sizeof(*urudev)); - fp_dev_set_instance_data(FP_DEV(dev), urudev); + self = FPI_DEVICE_URU4000 (dev); - urudev->profile = &uru4k_dev_info[driver_data]; - urudev->interface = iface_desc->bInterfaceNumber; + driver_data = fpi_device_get_driver_data (FP_DEVICE (dev)); + self->profile = &uru4k_dev_info[driver_data]; + self->interface = g_usb_interface_get_number (iface); - /* Set up encryption */ - urudev->cipher = CKM_AES_ECB; - urudev->slot = PK11_GetBestSlot(urudev->cipher, NULL); - if (urudev->slot == NULL) { - fp_err("could not get encryption slot"); - goto out; - } - item.type = siBuffer; - item.data = (unsigned char*) crkey; - item.len = sizeof(crkey); - urudev->symkey = PK11_ImportSymKey(urudev->slot, - urudev->cipher, - PK11_OriginUnwrap, - CKA_ENCRYPT, - &item, NULL); - if (urudev->symkey == NULL) { - fp_err("failed to import key into NSS"); - PK11_FreeSlot(urudev->slot); - urudev->slot = NULL; - goto out; - } - urudev->param = PK11_ParamFromIV(urudev->cipher, NULL); + /* Set up encryption */ + self->cipher = CKM_AES_ECB; + self->slot = PK11_GetBestSlot (self->cipher, NULL); + if (self->slot == NULL) + { + fp_err ("could not get encryption slot"); + fpi_image_device_open_complete (dev, + fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, + "Could not get encryption slot")); + return; + } + item.type = siBuffer; + item.data = (unsigned char *) crkey; + item.len = sizeof (crkey); + self->symkey = PK11_ImportSymKey (self->slot, + self->cipher, + PK11_OriginUnwrap, + CKA_ENCRYPT, + &item, NULL); + if (self->symkey == NULL) + { + fp_err ("failed to import key into NSS"); + PK11_FreeSlot (self->slot); + self->slot = NULL; + fpi_image_device_open_complete (dev, + fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, + "Failed to import key into NSS")); + return; + } + self->param = PK11_ParamFromIV (self->cipher, NULL); - fpi_imgdev_open_complete(dev, 0); - -out: - libusb_free_config_descriptor(config); - return r; + fpi_image_device_open_complete (dev, NULL); } -static void dev_deinit(struct fp_img_dev *dev) +static void +dev_deinit (FpImageDevice *dev) { - struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev)); - if (urudev->symkey) - PK11_FreeSymKey (urudev->symkey); - if (urudev->param) - SECITEM_FreeItem(urudev->param, PR_TRUE); - if (urudev->slot) - PK11_FreeSlot(urudev->slot); - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), urudev->interface); - g_free(urudev); - fpi_imgdev_close_complete(dev); + GError *error = NULL; + FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev); + + if (self->symkey) + PK11_FreeSymKey (self->symkey); + if (self->param) + SECITEM_FreeItem (self->param, PR_TRUE); + if (self->slot) + PK11_FreeSlot (self->slot); + g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), + self->interface, 0, &error); + fpi_image_device_close_complete (dev, error); } -static const struct usb_id id_table[] = { - /* ms kbd with fp rdr */ - { .vendor = 0x045e, .product = 0x00bb, .driver_data = MS_KBD }, +static const FpIdEntry id_table[] = { + /* ms kbd with fp rdr */ + { .vid = 0x045e, .pid = 0x00bb, .driver_data = MS_KBD }, - /* ms intellimouse with fp rdr */ - { .vendor = 0x045e, .product = 0x00bc, .driver_data = MS_INTELLIMOUSE }, + /* ms intellimouse with fp rdr */ + { .vid = 0x045e, .pid = 0x00bc, .driver_data = MS_INTELLIMOUSE }, - /* ms fp rdr (standalone) */ - { .vendor = 0x045e, .product = 0x00bd, .driver_data = MS_STANDALONE }, + /* ms fp rdr (standalone) */ + { .vid = 0x045e, .pid = 0x00bd, .driver_data = MS_STANDALONE }, - /* ms fp rdr (standalone) v2 */ - { .vendor = 0x045e, .product = 0x00ca, .driver_data = MS_STANDALONE_V2 }, + /* ms fp rdr (standalone) v2 */ + { .vid = 0x045e, .pid = 0x00ca, .driver_data = MS_STANDALONE_V2 }, - /* dp uru4000 (standalone) */ - { .vendor = 0x05ba, .product = 0x0007, .driver_data = DP_URU4000 }, + /* dp uru4000 (standalone) */ + { .vid = 0x05ba, .pid = 0x0007, .driver_data = DP_URU4000 }, - /* dp uru4000 (keyboard) */ - { .vendor = 0x05ba, .product = 0x0008, .driver_data = DP_URU4000 }, + /* dp uru4000 (keyboard) */ + { .vid = 0x05ba, .pid = 0x0008, .driver_data = DP_URU4000 }, - /* dp uru4000b (standalone) */ - { .vendor = 0x05ba, .product = 0x000a, .driver_data = DP_URU4000B }, + /* dp uru4000b (standalone) */ + { .vid = 0x05ba, .pid = 0x000a, .driver_data = DP_URU4000B }, - /* terminating entry */ - { 0, 0, 0, }, + /* terminating entry */ + { .vid = 0, .pid = 0, .driver_data = 0 }, }; -struct fp_img_driver uru4000_driver = { - .driver = { - .id = URU4000_ID, - .name = FP_COMPONENT, - .full_name = "Digital Persona U.are.U 4000/4000B/4500", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_PRESS, - }, - .flags = FP_IMGDRV_SUPPORTS_UNCONDITIONAL_CAPTURE, - .img_height = IMAGE_HEIGHT, - .img_width = IMAGE_WIDTH, +static void +fpi_device_uru4000_init (FpiDeviceUru4000 *self) +{ +} - .open = dev_init, - .close = dev_deinit, - .activate = dev_activate, - .deactivate = dev_deactivate, - .change_state = dev_change_state, -}; +static void +fpi_device_uru4000_class_init (FpiDeviceUru4000Class *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); + dev_class->id = "uru4000"; + dev_class->full_name = "Digital Persona U.are.U 4000/4000B/4500"; + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->id_table = id_table; + dev_class->scan_type = FP_SCAN_TYPE_PRESS; + + img_class->img_open = dev_init; + img_class->img_close = dev_deinit; + img_class->activate = dev_activate; + img_class->deactivate = dev_deactivate; + img_class->change_state = dev_change_state; + + img_class->img_width = IMAGE_WIDTH; + img_class->img_height = IMAGE_HEIGHT; +} diff --git a/libfprint/drivers/vcom5s.c b/libfprint/drivers/vcom5s.c index b0c6c452..0e102528 100644 --- a/libfprint/drivers/vcom5s.c +++ b/libfprint/drivers/vcom5s.c @@ -28,120 +28,112 @@ * powerdown? does windows do anything special on exit? */ -#define CTRL_IN 0xc0 -#define CTRL_OUT 0x40 -#define CTRL_TIMEOUT 1000 -#define EP_IN (1 | LIBUSB_ENDPOINT_IN) +#define CTRL_TIMEOUT 1000 +#define EP_IN (1 | FPI_USB_ENDPOINT_IN) -#define IMG_WIDTH 300 -#define IMG_HEIGHT 288 -#define ROWS_PER_RQ 12 -#define NR_REQS (IMG_HEIGHT / ROWS_PER_RQ) -#define RQ_SIZE (IMG_WIDTH * ROWS_PER_RQ) -#define IMG_SIZE (IMG_WIDTH * IMG_HEIGHT) +#define IMG_WIDTH 300 +#define IMG_HEIGHT 288 +#define ROWS_PER_RQ 12 +#define NR_REQS (IMG_HEIGHT / ROWS_PER_RQ) +#define RQ_SIZE (IMG_WIDTH * ROWS_PER_RQ) +#define IMG_SIZE (IMG_WIDTH * IMG_HEIGHT) -struct v5s_dev { - int capture_iteration; - struct fp_img *capture_img; - gboolean loop_running; - gboolean deactivating; +struct _FpDeviceVcom5s +{ + FpImageDevice parent; + + int capture_iteration; + FpImage *capture_img; + gboolean loop_running; + gboolean deactivating; }; +G_DECLARE_FINAL_TYPE (FpDeviceVcom5s, fpi_device_vcom5s, FPI, DEVICE_VCOM5S, + FpImageDevice); +G_DEFINE_TYPE (FpDeviceVcom5s, fpi_device_vcom5s, FP_TYPE_IMAGE_DEVICE); enum v5s_regs { - /* when using gain 0x29: - * a value of 0x00 produces mostly-black image - * 0x09 destroys ridges (too white) - * 0x01 or 0x02 seem good values */ - REG_CONTRAST = 0x02, + /* when using gain 0x29: + * a value of 0x00 produces mostly-black image + * 0x09 destroys ridges (too white) + * 0x01 or 0x02 seem good values */ + REG_CONTRAST = 0x02, - /* when using contrast 0x01: - * a value of 0x00 will produce an all-black image. - * 0x29 produces a good contrast image: ridges quite dark, but some - * light grey noise as background - * 0x46 produces all-white image with grey ridges (not very dark) */ - REG_GAIN = 0x03, + /* when using contrast 0x01: + * a value of 0x00 will produce an all-black image. + * 0x29 produces a good contrast image: ridges quite dark, but some + * light grey noise as background + * 0x46 produces all-white image with grey ridges (not very dark) */ + REG_GAIN = 0x03, }; enum v5s_cmd { - /* scan one row. has parameter, at a guess this is which row to scan? */ - CMD_SCAN_ONE_ROW = 0xc0, + /* scan one row. has parameter, at a guess this is which row to scan? */ + CMD_SCAN_ONE_ROW = 0xc0, - /* scan whole image */ - CMD_SCAN = 0xc1, + /* scan whole image */ + CMD_SCAN = 0xc1, }; /***** REGISTER I/O *****/ -static void sm_write_reg_cb(struct libusb_transfer *transfer) +static void +sm_write_reg_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) - fpi_ssm_mark_failed(ssm, -EIO); - else - fpi_ssm_next_state(ssm); - - g_free(transfer->buffer); - libusb_free_transfer(transfer); + if (error) + fpi_ssm_mark_failed (transfer->ssm, error); + else + fpi_ssm_next_state (transfer->ssm); } static void -sm_write_reg(fpi_ssm *ssm, - struct fp_img_dev *dev, - unsigned char reg, - unsigned char value) +sm_write_reg (FpiSsm *ssm, + FpDevice *dev, + unsigned char reg, + unsigned char value) { - struct libusb_transfer *transfer = fpi_usb_alloc(); - unsigned char *data; - int r; - - fp_dbg("set %02x=%02x", reg, value); - data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE); - libusb_fill_control_setup(data, CTRL_OUT, reg, value, 0, 0); - libusb_fill_control_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), data, sm_write_reg_cb, - ssm, CTRL_TIMEOUT); - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(data); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } -} + FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev); -static void sm_exec_cmd_cb(struct libusb_transfer *transfer) -{ - fpi_ssm *ssm = transfer->user_data; - - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) - fpi_ssm_mark_failed(ssm, -EIO); - else - fpi_ssm_next_state(ssm); - - g_free(transfer->buffer); - libusb_free_transfer(transfer); + fp_dbg ("set %02x=%02x", reg, value); + fpi_usb_transfer_fill_control (transfer, + G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE, + G_USB_DEVICE_REQUEST_TYPE_VENDOR, + G_USB_DEVICE_RECIPIENT_DEVICE, + reg, value, 0, 0); + transfer->ssm = ssm; + fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, sm_write_reg_cb, + NULL); + fpi_usb_transfer_unref (transfer); } static void -sm_exec_cmd(fpi_ssm *ssm, - struct fp_img_dev *dev, - unsigned char cmd, - unsigned char param) +sm_exec_cmd_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - struct libusb_transfer *transfer = fpi_usb_alloc(); - unsigned char *data; - int r; + if (error) + fpi_ssm_mark_failed (transfer->ssm, error); + else + fpi_ssm_next_state (transfer->ssm); +} - fp_dbg("cmd %02x param %02x", cmd, param); - data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE); - libusb_fill_control_setup(data, CTRL_IN, cmd, param, 0, 0); - libusb_fill_control_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), data, sm_exec_cmd_cb, - ssm, CTRL_TIMEOUT); - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(data); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } +static void +sm_exec_cmd (FpiSsm *ssm, + FpDevice *dev, + unsigned char cmd, + unsigned char param) +{ + FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev); + + fp_dbg ("cmd %02x param %02x", cmd, param); + fpi_usb_transfer_fill_control (transfer, + G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST, + G_USB_DEVICE_REQUEST_TYPE_VENDOR, + G_USB_DEVICE_RECIPIENT_DEVICE, + cmd, param, 0, 0); + transfer->ssm = ssm; + fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, sm_exec_cmd_cb, + NULL); + fpi_usb_transfer_unref (transfer); } /***** FINGER DETECTION *****/ @@ -156,220 +148,244 @@ sm_exec_cmd(fpi_ssm *ssm, #define DETBOX_COL_END (DETBOX_COL_START + DETBOX_COLS) #define FINGER_PRESENCE_THRESHOLD 100 -static gboolean finger_is_present(unsigned char *data) +static gboolean +finger_is_present (unsigned char *data) { - int row; - uint16_t imgavg = 0; + int row; + guint16 imgavg = 0; - for (row = DETBOX_ROW_START; row < DETBOX_ROW_END; row++) { - unsigned char *rowdata = data + (row * IMG_WIDTH); - uint16_t rowavg = 0; - int col; + for (row = DETBOX_ROW_START; row < DETBOX_ROW_END; row++) + { + unsigned char *rowdata = data + (row * IMG_WIDTH); + guint16 rowavg = 0; + int col; - for (col = DETBOX_COL_START; col < DETBOX_COL_END; col++) - rowavg += rowdata[col]; - rowavg /= DETBOX_COLS; - imgavg += rowavg; - } - imgavg /= DETBOX_ROWS; - fp_dbg("img avg %d", imgavg); + for (col = DETBOX_COL_START; col < DETBOX_COL_END; col++) + rowavg += rowdata[col]; + rowavg /= DETBOX_COLS; + imgavg += rowavg; + } + imgavg /= DETBOX_ROWS; + fp_dbg ("img avg %d", imgavg); - return (imgavg <= FINGER_PRESENCE_THRESHOLD); + return imgavg <= FINGER_PRESENCE_THRESHOLD; } /***** IMAGE ACQUISITION *****/ -static void capture_iterate(fpi_ssm *ssm, struct fp_img_dev *dev); +static void capture_iterate (FpiSsm *ssm, + FpDevice *dev); -static void capture_cb(struct libusb_transfer *transfer) +static void +capture_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpImageDevice *imgdev = FP_IMAGE_DEVICE (device); + FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (device); - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fpi_ssm_mark_failed(ssm, -EIO); - goto out; - } + if (error) + { + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } - if (++vdev->capture_iteration == NR_REQS) { - struct fp_img *img = vdev->capture_img; - /* must clear this early, otherwise the call chain takes us into - * loopsm_complete where we would free it, when in fact we are - * supposed to be handing off this image */ - vdev->capture_img = NULL; + if (++self->capture_iteration == NR_REQS) + { + FpImage *img = self->capture_img; + /* must clear this early, otherwise the call chain takes us into + * loopsm_complete where we would free it, when in fact we are + * supposed to be handing off this image */ + self->capture_img = NULL; - fpi_imgdev_report_finger_status(dev, finger_is_present(img->data)); - fpi_imgdev_image_captured(dev, img); - fpi_ssm_next_state(ssm); - } else { - capture_iterate(ssm, dev); - } - -out: - libusb_free_transfer(transfer); + fpi_image_device_report_finger_status (imgdev, + finger_is_present (img->data)); + fpi_image_device_image_captured (imgdev, img); + fpi_ssm_next_state (transfer->ssm); + } + else + { + capture_iterate (transfer->ssm, device); + } } static void -capture_iterate(fpi_ssm *ssm, - struct fp_img_dev *dev) +capture_iterate (FpiSsm *ssm, + FpDevice *dev) { - struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); - int iteration = vdev->capture_iteration; - struct libusb_transfer *transfer = fpi_usb_alloc(); - int r; + FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev); + int iteration = self->capture_iteration; + FpiUsbTransfer *transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, - vdev->capture_img->data + (RQ_SIZE * iteration), RQ_SIZE, - capture_cb, ssm, CTRL_TIMEOUT); - transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK; - r = libusb_submit_transfer(transfer); - if (r < 0) { - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_fill_bulk_full (transfer, + EP_IN, + self->capture_img->data + (RQ_SIZE * iteration), + RQ_SIZE, + NULL); + + fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, capture_cb, NULL); + fpi_usb_transfer_unref (transfer); } static void -sm_do_capture(fpi_ssm *ssm, - struct fp_img_dev *dev) +sm_do_capture (FpiSsm *ssm, + FpDevice *dev) { - struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev); + FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (dev); - G_DEBUG_HERE(); - vdev->capture_img = fpi_img_new_for_imgdev(dev); - vdev->capture_iteration = 0; - capture_iterate(ssm, dev); + G_DEBUG_HERE (); + self->capture_img = fp_image_new (cls->img_width, cls->img_height); + self->capture_iteration = 0; + capture_iterate (ssm, dev); } /***** CAPTURE LOOP *****/ enum loop_states { - LOOP_SET_CONTRAST, - LOOP_SET_GAIN, - LOOP_CMD_SCAN, - LOOP_CAPTURE, - LOOP_CAPTURE_DONE, - LOOP_NUM_STATES, + LOOP_SET_CONTRAST, + LOOP_SET_GAIN, + LOOP_CMD_SCAN, + LOOP_CAPTURE, + LOOP_CAPTURE_DONE, + LOOP_NUM_STATES, }; -static void loop_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +loop_run_state (FpiSsm *ssm, FpDevice *dev) { - struct fp_img_dev *dev = user_data; - struct v5s_dev *vdev = FP_INSTANCE_DATA(_dev); + FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case LOOP_SET_CONTRAST: - sm_write_reg(ssm, dev, REG_CONTRAST, 0x01); - break; - case LOOP_SET_GAIN: - sm_write_reg(ssm, dev, REG_GAIN, 0x29); - break; - case LOOP_CMD_SCAN: - if (vdev->deactivating) { - fp_dbg("deactivating, marking completed"); - fpi_ssm_mark_completed(ssm); - } else - sm_exec_cmd(ssm, dev, CMD_SCAN, 0x00); - break; - case LOOP_CAPTURE: - sm_do_capture(ssm, dev); - break; - case LOOP_CAPTURE_DONE: - fpi_ssm_jump_to_state(ssm, LOOP_CMD_SCAN); - break; - } + switch (fpi_ssm_get_cur_state (ssm)) + { + case LOOP_SET_CONTRAST: + sm_write_reg (ssm, dev, REG_CONTRAST, 0x01); + break; + + case LOOP_SET_GAIN: + sm_write_reg (ssm, dev, REG_GAIN, 0x29); + break; + + case LOOP_CMD_SCAN: + if (self->deactivating) + { + fp_dbg ("deactivating, marking completed"); + fpi_ssm_mark_completed (ssm); + } + else + { + sm_exec_cmd (ssm, dev, CMD_SCAN, 0x00); + } + break; + + case LOOP_CAPTURE: + sm_do_capture (ssm, dev); + break; + + case LOOP_CAPTURE_DONE: + fpi_ssm_jump_to_state (ssm, LOOP_CMD_SCAN); + break; + + default: + g_assert_not_reached (); + } } -static void loopsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +loopsm_complete (FpiSsm *ssm, FpDevice *dev, GError *error) { - struct fp_img_dev *dev = user_data; - struct v5s_dev *vdev = FP_INSTANCE_DATA(_dev); - int r = fpi_ssm_get_error(ssm); + FpImageDevice *imgdev = FP_IMAGE_DEVICE (dev); + FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev); - fpi_ssm_free(ssm); - fp_img_free(vdev->capture_img); - vdev->capture_img = NULL; - vdev->loop_running = FALSE; + fpi_ssm_free (ssm); + g_object_unref (self->capture_img); + self->capture_img = NULL; + self->loop_running = FALSE; - if (r) - fpi_imgdev_session_error(dev, r); + if (error && !self->deactivating) + fpi_image_device_session_error (imgdev, error); + else if (error) + g_error_free (error); - if (vdev->deactivating) - fpi_imgdev_deactivate_complete(dev); + if (self->deactivating) + fpi_image_device_deactivate_complete (imgdev, NULL); } -static int dev_activate(struct fp_img_dev *dev) +static void +dev_activate (FpImageDevice *dev) { - struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), loop_run_state, - LOOP_NUM_STATES, dev); - vdev->deactivating = FALSE; - fpi_ssm_start(ssm, loopsm_complete); - vdev->loop_running = TRUE; - fpi_imgdev_activate_complete(dev, 0); - return 0; + FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev); + FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), loop_run_state, LOOP_NUM_STATES); + + self->deactivating = FALSE; + fpi_ssm_start (ssm, loopsm_complete); + self->loop_running = TRUE; + fpi_image_device_activate_complete (dev, NULL); } -static void dev_deactivate(struct fp_img_dev *dev) +static void +dev_deactivate (FpImageDevice *dev) { - struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); - if (vdev->loop_running) - vdev->deactivating = TRUE; - else - fpi_imgdev_deactivate_complete(dev); + FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev); + + if (self->loop_running) + self->deactivating = TRUE; + else + fpi_image_device_deactivate_complete (dev, NULL); } -static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) +static void +dev_init (FpImageDevice *dev) { - int r; - struct v5s_dev *v5s_dev; + GError *error = NULL; - v5s_dev = g_malloc0(sizeof(struct v5s_dev)); - fp_dev_set_instance_data(FP_DEV(dev), v5s_dev); + g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error); - r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - if (r < 0) - fp_err("could not claim interface 0: %s", libusb_error_name(r)); - - if (r == 0) - fpi_imgdev_open_complete(dev, 0); - - return r; + fpi_image_device_open_complete (dev, error); } -static void dev_deinit(struct fp_img_dev *dev) +static void +dev_deinit (FpImageDevice *dev) { - struct v5s_dev *v5s_dev; - v5s_dev = FP_INSTANCE_DATA(FP_DEV(dev)); - g_free(v5s_dev); - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - fpi_imgdev_close_complete(dev); + GError *error = NULL; + + g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), + 0, 0, &error); + + fpi_image_device_close_complete (dev, error); } -static const struct usb_id id_table[] = { - { .vendor = 0x061a, .product = 0x0110 }, - { 0, 0, 0, }, +static const FpIdEntry id_table[] = { + { .vid = 0x061a, .pid = 0x0110, }, + { .vid = 0, .pid = 0, .driver_data = 0 }, }; -struct fp_img_driver vcom5s_driver = { - .driver = { - .id = VCOM5S_ID, - .name = FP_COMPONENT, - .full_name = "Veridicom 5thSense", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_PRESS, - }, - .flags = 0, - .img_height = IMG_HEIGHT, - .img_width = IMG_WIDTH, +static void +fpi_device_vcom5s_init (FpDeviceVcom5s *self) +{ +} - .open = dev_init, - .close = dev_deinit, - .activate = dev_activate, - .deactivate = dev_deactivate, -}; +static void +fpi_device_vcom5s_class_init (FpDeviceVcom5sClass *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); + dev_class->id = "vcom5s"; + dev_class->full_name = "Veridicom 5thSense"; + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->id_table = id_table; + dev_class->scan_type = FP_SCAN_TYPE_PRESS; + + img_class->img_open = dev_init; + img_class->img_close = dev_deinit; + img_class->activate = dev_activate; + img_class->deactivate = dev_deactivate; + + img_class->img_width = IMG_WIDTH; + img_class->img_height = IMG_HEIGHT; +} diff --git a/libfprint/drivers/vfs0050.c b/libfprint/drivers/vfs0050.c index b2f8395e..4dc67827 100644 --- a/libfprint/drivers/vfs0050.c +++ b/libfprint/drivers/vfs0050.c @@ -22,770 +22,761 @@ #include "drivers_api.h" #include "vfs0050.h" +G_DEFINE_TYPE (FpDeviceVfs0050, fpi_device_vfs0050, FP_TYPE_IMAGE_DEVICE) + /* USB functions */ /* Callback for async_write */ -static void async_write_callback(struct libusb_transfer *transfer) +static void +async_write_callback (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm); + if (error) + { + fp_err ("USB write transfer: %s", error->message); + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } - int transferred = transfer->actual_length, error = - transfer->status, len = transfer->length; - - if (error != 0) { - fp_err("USB write transfer: %s", libusb_error_name(error)); - fpi_imgdev_session_error(idev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - return; - } - - if (transferred != len) { - fp_err("Written only %d of %d bytes", transferred, len); - fpi_imgdev_session_error(idev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - return; - } - - fpi_ssm_next_state(ssm); + fpi_ssm_next_state (transfer->ssm); } /* Send data to EP1, the only out endpoint */ static void -async_write(fpi_ssm *ssm, - struct fp_img_dev *dev, - void *data, - int len) +async_write (FpiSsm *ssm, + FpDevice *dev, + void *data, + int len) { - struct libusb_device_handle *usb_dev = fpi_dev_get_usb_dev(FP_DEV(dev)); - struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiUsbTransfer *transfer; - vdev->transfer = fpi_usb_alloc(); - vdev->transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER; - libusb_fill_bulk_transfer(vdev->transfer, usb_dev, 0x01, data, len, - async_write_callback, ssm, VFS_USB_TIMEOUT); - libusb_submit_transfer(vdev->transfer); + transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); + fpi_usb_transfer_fill_bulk_full (transfer, 0x01, data, len, NULL); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_submit (transfer, VFS_USB_TIMEOUT, NULL, + async_write_callback, NULL); + fpi_usb_transfer_unref (transfer); } /* Callback for async_read */ -static void async_read_callback(struct libusb_transfer *transfer) -{ - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm); - - int transferred = transfer->actual_length, error = - transfer->status, len = transfer->length; - int ep = transfer->endpoint; - - if (error != 0) { - fp_err("USB read transfer on endpoint %d: %s", ep - 0x80, - libusb_error_name(error)); - fpi_imgdev_session_error(idev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - return; - } - - if (transferred != len) { - fp_err("Received %d instead of %d bytes", transferred, len); - fpi_imgdev_session_error(idev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - return; - } - - fpi_ssm_next_state(ssm); -} - -/* Receive data from the given ep and compare with expected */ static void -async_read(fpi_ssm *ssm, - struct fp_img_dev *dev, - int ep, - void *data, - int len) +async_read_callback (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm); - struct libusb_device_handle *usb_dev = fpi_dev_get_usb_dev(FP_DEV(idev)); - struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev)); + int ep = transfer->endpoint; - ep |= LIBUSB_ENDPOINT_IN; + if (error) + { + fp_err ("USB read transfer on endpoint %d: %s", ep - 0x80, + error->message); + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } - vdev->transfer = fpi_usb_alloc(); - vdev->transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER; - - /* 0x83 is the only interrupt endpoint */ - if (ep == EP3_IN) - libusb_fill_interrupt_transfer(vdev->transfer, usb_dev, ep, data, - len, async_read_callback, ssm, - VFS_USB_TIMEOUT); - else - libusb_fill_bulk_transfer(vdev->transfer, usb_dev, ep, data, len, - async_read_callback, ssm, - VFS_USB_TIMEOUT); - libusb_submit_transfer(vdev->transfer); + fpi_ssm_next_state (transfer->ssm); } -/* Callback for async_read */ -static void async_abort_callback(struct libusb_transfer *transfer) +/* Receive data from the given ep and either discard or fill the given buffer */ +static void +async_read (FpiSsm *ssm, + FpDevice *dev, + int ep, + void *data, + int len) { - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm); + FpiUsbTransfer *transfer; + GDestroyNotify free_func = NULL; - int transferred = transfer->actual_length, error = transfer->status; - int ep = transfer->endpoint; + ep |= FPI_USB_ENDPOINT_IN; - /* In normal case endpoint is empty */ - if (error == LIBUSB_TRANSFER_TIMED_OUT) { - fpi_ssm_next_state(ssm); - return; - } + transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; - if (error != 0) { - fp_err("USB write transfer: %s", libusb_error_name(error)); - fpi_imgdev_session_error(idev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - return; - } + if (data == NULL) + { + data = g_malloc0 (len); + free_func = g_free; + } - /* Don't stop process, only print warning */ - if (transferred > 0) - fp_warn("Endpoint %d had extra %d bytes", ep - 0x80, - transferred); + /* 0x83 is the only interrupt endpoint */ + if (ep == EP3_IN) + fpi_usb_transfer_fill_interrupt_full (transfer, ep, data, len, free_func); + else + fpi_usb_transfer_fill_bulk_full (transfer, ep, data, len, free_func); - fpi_ssm_jump_to_state(ssm, fpi_ssm_get_cur_state(ssm)); + fpi_usb_transfer_submit (transfer, VFS_USB_TIMEOUT, NULL, + async_read_callback, NULL); + fpi_usb_transfer_unref (transfer); } -/* Receive data from the given ep and compare with expected */ -static void async_abort(fpi_ssm *ssm, int ep) +/* Callback for async_abort */ +static void +async_abort_callback (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm); - struct libusb_device_handle *usb_dev = fpi_dev_get_usb_dev(FP_DEV(idev)); - struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev)); + int ep = transfer->endpoint; - int len = VFS_USB_BUFFER_SIZE; - unsigned char *data = g_malloc(VFS_USB_BUFFER_SIZE); + /* In normal case endpoint is empty */ + if (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT)) + { + g_free (error); + fpi_ssm_next_state (transfer->ssm); + return; + } - ep |= LIBUSB_ENDPOINT_IN; + if (error) + { + fp_err ("USB write transfer: %s", error->message); + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } - vdev->transfer = fpi_usb_alloc(); - vdev->transfer->flags |= - LIBUSB_TRANSFER_FREE_TRANSFER | LIBUSB_TRANSFER_FREE_BUFFER; + /* Don't stop process, only print warning */ + fp_warn ("Endpoint %d had extra %zd bytes readable", ep - 0x80, + transfer->actual_length); - /* 0x83 is the only interrupt endpoint */ - if (ep == EP3_IN) - libusb_fill_interrupt_transfer(vdev->transfer, usb_dev, ep, data, - len, async_abort_callback, ssm, - VFS_USB_ABORT_TIMEOUT); - else - libusb_fill_bulk_transfer(vdev->transfer, usb_dev, ep, data, len, - async_abort_callback, ssm, - VFS_USB_ABORT_TIMEOUT); - libusb_submit_transfer(vdev->transfer); + fpi_ssm_jump_to_state (transfer->ssm, + fpi_ssm_get_cur_state (transfer->ssm)); +} + +/* Receive data from the given ep; continues to the next state once no + * more data is available. Otherwise the current state is repeated. */ +static void +async_abort (FpDevice *dev, FpiSsm *ssm, int ep) +{ + FpiUsbTransfer *transfer; + + ep |= FPI_USB_ENDPOINT_IN; + + transfer = fpi_usb_transfer_new (dev); + + /* 0x83 is the only interrupt endpoint */ + if (ep == EP3_IN) + fpi_usb_transfer_fill_interrupt (transfer, ep, VFS_USB_BUFFER_SIZE); + else + fpi_usb_transfer_fill_bulk (transfer, ep, VFS_USB_BUFFER_SIZE); + + fpi_usb_transfer_submit (transfer, VFS_USB_ABORT_TIMEOUT, NULL, + async_abort_callback, NULL); + fpi_usb_transfer_unref (transfer); } /* Image processing functions */ /* Pixel getter for fpi_assemble_lines */ -static unsigned char vfs0050_get_pixel(struct fpi_line_asmbl_ctx *ctx, - GSList * line, unsigned int x) +static unsigned char +vfs0050_get_pixel (struct fpi_line_asmbl_ctx *ctx, + GSList * line, unsigned int x) { - return ((struct vfs_line *)line->data)->data[x]; + return ((struct vfs_line *) line->data)->data[x]; } /* Deviation getter for fpi_assemble_lines */ -static int vfs0050_get_difference(struct fpi_line_asmbl_ctx *ctx, - GSList * line_list_1, GSList * line_list_2) +static int +vfs0050_get_difference (struct fpi_line_asmbl_ctx *ctx, + GSList * line_list_1, GSList * line_list_2) { - struct vfs_line *line1 = line_list_1->data; - struct vfs_line *line2 = line_list_2->data; - const int shift = (VFS_IMAGE_WIDTH - VFS_NEXT_LINE_WIDTH) / 2 - 1; - int res = 0; - for (int i = 0; i < VFS_NEXT_LINE_WIDTH; ++i) { - int x = - (int)line1->next_line_part[i] - (int)line2->data[shift + i]; - res += x * x; - } - return res; + struct vfs_line *line1 = line_list_1->data; + struct vfs_line *line2 = line_list_2->data; + const int shift = (VFS_IMAGE_WIDTH - VFS_NEXT_LINE_WIDTH) / 2 - 1; + int res = 0; + + for (int i = 0; i < VFS_NEXT_LINE_WIDTH; ++i) + { + int x = + (int) line1->next_line_part[i] - (int) line2->data[shift + i]; + res += x * x; + } + return res; } #define VFS_NOISE_THRESHOLD 40 /* Checks whether line is noise or not using hardware parameters */ -static char is_noise(struct vfs_line *line) +static char +is_noise (struct vfs_line *line) { - int val1 = line->noise_hash_1; - int val2 = line->noise_hash_2; - if (val1 > VFS_NOISE_THRESHOLD - && val1 < 256 - VFS_NOISE_THRESHOLD - && val2 > VFS_NOISE_THRESHOLD && val2 < 256 - VFS_NOISE_THRESHOLD) - return 1; - return 0; + int val1 = line->noise_hash_1; + int val2 = line->noise_hash_2; + + if (val1 > VFS_NOISE_THRESHOLD && + val1 < 256 - VFS_NOISE_THRESHOLD && + val2 > VFS_NOISE_THRESHOLD && val2 < 256 - VFS_NOISE_THRESHOLD) + return 1; + return 0; } /* Parameters for fpi_assemble_lines */ static struct fpi_line_asmbl_ctx assembling_ctx = { - .line_width = VFS_IMAGE_WIDTH, - .max_height = VFS_MAX_HEIGHT, - .resolution = 10, - .median_filter_size = 25, - .max_search_offset = 100, - .get_deviation = vfs0050_get_difference, - .get_pixel = vfs0050_get_pixel, + .line_width = VFS_IMAGE_WIDTH, + .max_height = VFS_MAX_HEIGHT, + .resolution = 10, + .median_filter_size = 25, + .max_search_offset = 100, + .get_deviation = vfs0050_get_difference, + .get_pixel = vfs0050_get_pixel, }; /* Processes image before submitting */ -static struct fp_img *prepare_image(struct vfs_dev_t *vdev) +static FpImage * +prepare_image (FpDeviceVfs0050 *vdev) { - int height = vdev->bytes / VFS_LINE_SIZE; + int height = vdev->bytes / VFS_LINE_SIZE; - /* Noise cleaning. IMHO, it works pretty well - I've not detected cases when it doesn't work or cuts a part of the finger - Noise arises at the end of scan when some water remains on the scanner */ - while (height > 0) { - if (!is_noise(vdev->lines_buffer + height - 1)) - break; - --height; - } - if (height > VFS_MAX_HEIGHT) - height = VFS_MAX_HEIGHT; + /* Noise cleaning. IMHO, it works pretty well + I've not detected cases when it doesn't work or cuts a part of the finger + Noise arises at the end of scan when some water remains on the scanner */ + while (height > 0) + { + if (!is_noise (vdev->lines_buffer + height - 1)) + break; + --height; + } + if (height > VFS_MAX_HEIGHT) + height = VFS_MAX_HEIGHT; - /* If image is not good enough */ - if (height < VFS_IMAGE_WIDTH) - return NULL; + /* If image is not good enough */ + if (height < VFS_IMAGE_WIDTH) + return NULL; - /* Building GSList */ - GSList *lines = NULL; - for (int i = height - 1; i >= 0; --i) - lines = g_slist_prepend(lines, vdev->lines_buffer + i); + /* Building GSList */ + GSList *lines = NULL; + for (int i = height - 1; i >= 0; --i) + lines = g_slist_prepend (lines, vdev->lines_buffer + i); - /* Perform line assembling */ - struct fp_img *img = fpi_assemble_lines(&assembling_ctx, lines, height); + /* Perform line assembling */ + FpImage *img = fpi_assemble_lines (&assembling_ctx, lines, height); - g_slist_free(lines); - return img; + g_slist_free (lines); + return img; } /* Processes and submits image after fingerprint received */ -static void submit_image(struct fp_img_dev *idev) +static void +submit_image (FpDeviceVfs0050 *self) { - struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev)); + FpImageDevice *idev = FP_IMAGE_DEVICE (self); - /* We were not asked to submit image actually */ - if (!vdev->active) - return; + /* We were not asked to submit image actually */ + if (!self->active) + return; - struct fp_img *img = prepare_image(vdev); + FpImage *img = prepare_image (self); - if (!img) - fpi_imgdev_abort_scan(idev, FP_VERIFY_RETRY_TOO_SHORT); - else - fpi_imgdev_image_captured(idev, img); + if (!img) + fpi_image_device_retry_scan (idev, FP_DEVICE_RETRY_TOO_SHORT); + else + fpi_image_device_image_captured (idev, img); - /* Finger not on the scanner */ - fpi_imgdev_report_finger_status(idev, 0); + /* Finger not on the scanner */ + fpi_image_device_report_finger_status (idev, FALSE); } /* Proto functions */ /* SSM loop for clear_ep2 */ static void -clear_ep2_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +clear_ep2_ssm (FpiSsm *ssm, FpDevice *dev) { - struct fp_img_dev *idev = user_data; + char command04 = 0x04; - short result; - char command04 = 0x04; + switch (fpi_ssm_get_cur_state (ssm)) + { + case SUBSM1_COMMAND_04: + async_write (ssm, dev, &command04, sizeof (command04)); + break; - switch (fpi_ssm_get_cur_state(ssm)) { - case SUBSM1_COMMAND_04: - async_write(ssm, idev, &command04, sizeof(command04)); - break; + case SUBSM1_RETURN_CODE: + async_read (ssm, dev, 1, NULL, 2); + break; - case SUBSM1_RETURN_CODE: - async_read(ssm, idev, 1, &result, sizeof(result)); - break; + case SUBSM1_ABORT_2: + async_abort (dev, ssm, 2); + break; - case SUBSM1_ABORT_2: - async_abort(ssm, 2); - break; - - default: - fp_err("Unknown SUBSM1 state"); - fpi_imgdev_session_error(idev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - } + default: + fp_err ("Unknown SUBSM1 state"); + fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); + } } /* Send command to clear EP2 */ static void -clear_ep2(fpi_ssm *ssm, - struct fp_img_dev *idev) +clear_ep2 (FpDevice *dev, + FpiSsm *ssm) { - fpi_ssm *subsm = - fpi_ssm_new(FP_DEV(idev), clear_ep2_ssm, SUBSM1_STATES, idev); - fpi_ssm_start_subsm(ssm, subsm); + FpiSsm *subsm = fpi_ssm_new (dev, clear_ep2_ssm, SUBSM1_STATES); + + fpi_ssm_start_subsm (ssm, subsm); } -static void send_control_packet_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +send_control_packet_ssm (FpiSsm *ssm, FpDevice *dev) { - struct fp_img_dev *idev = user_data; - struct vfs_dev_t *vdev = FP_INSTANCE_DATA(_dev); + FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050 (dev); - short result; - unsigned char *commit_result = NULL; + switch (fpi_ssm_get_cur_state (ssm)) + { + case SUBSM2_SEND_CONTROL: + async_write (ssm, dev, self->control_packet, + VFS_CONTROL_PACKET_SIZE); + break; - switch (fpi_ssm_get_cur_state(ssm)) { - case SUBSM2_SEND_CONTROL: - async_write(ssm, idev, vdev->control_packet, VFS_CONTROL_PACKET_SIZE); - break; + case SUBSM2_RETURN_CODE: + async_read (ssm, dev, 1, NULL, 2); + break; - case SUBSM2_RETURN_CODE: - async_read(ssm, idev, 1, &result, sizeof(result)); - break; + case SUBSM2_SEND_COMMIT: + /* next_receive_* packets could be sent only in pair */ + if (self->control_packet == next_receive_1) + { + self->control_packet = next_receive_2; + fpi_ssm_jump_to_state (ssm, SUBSM2_SEND_CONTROL); + break; + } + /* commit_out in Windows differs in each commit, but I send the same each time */ + async_write (ssm, dev, commit_out, sizeof (commit_out)); + break; - case SUBSM2_SEND_COMMIT: - /* next_receive_* packets could be sent only in pair */ - if (vdev->control_packet == next_receive_1) { - vdev->control_packet = next_receive_2; - fpi_ssm_jump_to_state(ssm, SUBSM2_SEND_CONTROL); - break; - } - /* commit_out in Windows differs in each commit, but I send the same each time */ - async_write(ssm, idev, commit_out, sizeof(commit_out)); - break; + case SUBSM2_COMMIT_RESPONSE: + async_read (ssm, dev, 1, NULL, VFS_COMMIT_RESPONSE_SIZE); + break; - case SUBSM2_COMMIT_RESPONSE: - commit_result = g_malloc(VFS_COMMIT_RESPONSE_SIZE); - async_read(ssm, idev, 1, commit_result, VFS_COMMIT_RESPONSE_SIZE); - break; + case SUBSM2_READ_EMPTY_INTERRUPT: + /* I don't know how to check result, it could be different + * NOTE: I guess this comment relates to the above read. */ + async_read (ssm, dev, 3, self->interrupt, VFS_INTERRUPT_SIZE); + break; - case SUBSM2_READ_EMPTY_INTERRUPT: - /* I don't know how to check result, it could be different */ - g_free(commit_result); + case SUBSM2_ABORT_3: + /* Check that interrupt is empty */ + if (memcmp + (self->interrupt, empty_interrupt, VFS_INTERRUPT_SIZE)) + { + fp_err ("Unknown SUBSM2 state"); + fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); + break; + } + async_abort (dev, ssm, 3); + break; - async_read(ssm, idev, 3, vdev->interrupt, VFS_INTERRUPT_SIZE); - break; + case SUBSM2_CLEAR_EP2: + /* After turn_on Windows doesn't clear EP2 */ + if (self->control_packet != turn_on) + clear_ep2 (dev, ssm); + else + fpi_ssm_next_state (ssm); + break; - case SUBSM2_ABORT_3: - /* Check that interrupt is empty */ - if (memcmp - (vdev->interrupt, empty_interrupt, VFS_INTERRUPT_SIZE)) { - fp_err("Unknown SUBSM2 state"); - fpi_imgdev_session_error(idev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - break; - } - async_abort(ssm, 3); - break; - - case SUBSM2_CLEAR_EP2: - /* After turn_on Windows doesn't clear EP2 */ - if (vdev->control_packet != turn_on) - clear_ep2(ssm, idev); - else - fpi_ssm_next_state(ssm); - break; - - default: - fp_err("Unknown SUBSM2 state"); - fpi_imgdev_session_error(idev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - } + default: + fp_err ("Unknown SUBSM2 state"); + fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); + } } /* Send device state control packet */ static void -send_control_packet(fpi_ssm *ssm, - struct fp_img_dev *idev) +send_control_packet (FpiSsm *ssm, + FpDevice *dev) { - fpi_ssm *subsm = - fpi_ssm_new(FP_DEV(idev), send_control_packet_ssm, SUBSM2_STATES, idev); - fpi_ssm_start_subsm(ssm, subsm); + FpiSsm *subsm = + fpi_ssm_new (dev, send_control_packet_ssm, SUBSM2_STATES); + + fpi_ssm_start_subsm (ssm, subsm); } /* Clears all fprint data */ -static void clear_data(struct vfs_dev_t *vdev) +static void +clear_data (FpDeviceVfs0050 *vdev) { - g_free(vdev->lines_buffer); - vdev->lines_buffer = NULL; - vdev->memory = vdev->bytes = 0; + g_free (vdev->lines_buffer); + vdev->lines_buffer = NULL; + vdev->memory = vdev->bytes = 0; } /* After receiving interrupt from EP3 */ -static void interrupt_callback(struct libusb_transfer *transfer) -{ - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm); - struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev)); - - char *interrupt = vdev->interrupt; - int error = transfer->status, transferred = transfer->actual_length; - - vdev->wait_interrupt = 0; - - /* When we have cancelled transfer, error is ok actually */ - if (!vdev->active && error == LIBUSB_TRANSFER_CANCELLED) - return; - - if (error != 0) { - fp_err("USB read interrupt transfer: %s", - libusb_error_name(error)); - fpi_imgdev_session_error(idev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - return; - } - - /* Interrupt size is VFS_INTERRUPT_SIZE bytes in all known cases */ - if (transferred != VFS_INTERRUPT_SIZE) { - fp_err("Unknown interrupt size %d", transferred); - /* Abort ssm */ - fpi_imgdev_session_error(idev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - return; - } - - /* Standard interrupts */ - if (memcmp(interrupt, interrupt1, VFS_INTERRUPT_SIZE) == 0 || - memcmp(interrupt, interrupt2, VFS_INTERRUPT_SIZE) == 0 || - memcmp(interrupt, interrupt3, VFS_INTERRUPT_SIZE) == 0) { - /* Go to the next ssm stage */ - fpi_ssm_next_state(ssm); - return; - } - - /* When finger is on the scanner before turn_on */ - if (interrupt[0] == 0x01) { - fp_warn("Finger is already on the scanner"); - - /* Go to the next ssm stage */ - fpi_ssm_next_state(ssm); - return; - } - - /* Unknown interrupt; abort the session */ - fp_err("Unknown interrupt '%02x:%02x:%02x:%02x:%02x'!", - interrupt[0] & 0xff, interrupt[1] & 0xff, interrupt[2] & 0xff, - interrupt[3] & 0xff, interrupt[4] & 0xff); - - /* Abort ssm */ - fpi_imgdev_session_error(idev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); -} - -static void receive_callback(struct libusb_transfer *transfer) -{ - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm); - struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev)); - - int transferred = transfer->actual_length, error = transfer->status; - - if (error != 0 && error != LIBUSB_TRANSFER_TIMED_OUT) { - fp_err("USB read transfer: %s", libusb_error_name(error)); - - fpi_imgdev_session_error(idev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - return; - } - - /* Check if fingerprint data is over */ - if (transferred == 0) { - fpi_ssm_next_state(ssm); - } else { - vdev->bytes += transferred; - - /* We need more data */ - fpi_ssm_jump_to_state(ssm, fpi_ssm_get_cur_state(ssm)); - } -} - -/* Stub to keep SSM alive when waiting an interrupt */ static void -wait_interrupt(struct fp_dev *dev, - void *data) +interrupt_callback (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = data; - struct vfs_dev_t *vdev = FP_INSTANCE_DATA(dev); + FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050 (device); + char *interrupt = transfer->buffer; - /* Keep sleeping while this flag is on */ - if (vdev->wait_interrupt) - fpi_ssm_jump_to_state(ssm, fpi_ssm_get_cur_state(ssm)); + /* we expect a cancellation error when the device is deactivating + * go into the SSM_CLEAR_EP2 state in that case. */ + if (!self->active && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + { + g_error_free (error); + fpi_ssm_jump_to_state (transfer->ssm, SSM_CLEAR_EP2); + return; + } + + if (error) + { + fp_err ("USB read interrupt transfer: %s", + error->message); + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } + + /* Standard interrupts */ + if (memcmp (interrupt, interrupt1, VFS_INTERRUPT_SIZE) == 0 || + memcmp (interrupt, interrupt2, VFS_INTERRUPT_SIZE) == 0 || + memcmp (interrupt, interrupt3, VFS_INTERRUPT_SIZE) == 0) + { + /* Go to the next ssm stage */ + fpi_ssm_next_state (transfer->ssm); + return; + } + + /* When finger is on the scanner before turn_on */ + if (interrupt[0] == 0x01) + { + fp_warn ("Finger is already on the scanner"); + + /* Go to the next ssm stage */ + fpi_ssm_next_state (transfer->ssm); + return; + } + + /* Unknown interrupt; abort the session */ + fp_err ("Unknown interrupt '%02x:%02x:%02x:%02x:%02x'!", + interrupt[0] & 0xff, interrupt[1] & 0xff, interrupt[2] & 0xff, + interrupt[3] & 0xff, interrupt[4] & 0xff); + + /* Abort ssm */ + fpi_ssm_mark_failed (transfer->ssm, + fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); +} + +static void +receive_callback (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) +{ + FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050 (device); + + if (error && !g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT)) + { + fp_err ("USB read transfer: %s", error->message); + + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } + if (error) + g_error_free (error); + + /* Check if fingerprint data is over */ + if (transfer->actual_length == 0) + { + fpi_ssm_next_state (transfer->ssm); + } + else + { + self->bytes += transfer->actual_length; + + /* We need more data */ + fpi_ssm_jump_to_state (transfer->ssm, + fpi_ssm_get_cur_state (transfer->ssm)); + } } /* SSM stub to prepare device to another scan after orange light was on */ static void -another_scan(struct fp_dev *dev, - void *data) +another_scan (FpDevice *dev, + void *data) { - fpi_ssm *ssm = data; - fpi_ssm_jump_to_state(ssm, SSM_TURN_ON); + FpiSsm *ssm = data; + + fpi_ssm_jump_to_state (ssm, SSM_TURN_ON); } /* Main SSM loop */ -static void activate_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +activate_ssm (FpiSsm *ssm, FpDevice *dev) { - struct fp_img_dev *idev = user_data; - struct libusb_device_handle *usb_dev = fpi_dev_get_usb_dev(FP_DEV(idev)); - struct vfs_dev_t *vdev = FP_INSTANCE_DATA(_dev); + FpImageDevice *idev = FP_IMAGE_DEVICE (dev); + FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050 (dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case SSM_INITIAL_ABORT_1: - async_abort(ssm, 1); - break; + switch (fpi_ssm_get_cur_state (ssm)) + { + case SSM_INITIAL_ABORT_1: + async_abort (dev, ssm, 1); + break; - case SSM_INITIAL_ABORT_2: - async_abort(ssm, 2); - break; + case SSM_INITIAL_ABORT_2: + async_abort (dev, ssm, 2); + break; - case SSM_INITIAL_ABORT_3: - async_abort(ssm, 3); - break; + case SSM_INITIAL_ABORT_3: + async_abort (dev, ssm, 3); + break; - case SSM_CLEAR_EP2: - clear_ep2(ssm, idev); - break; + case SSM_CLEAR_EP2: + clear_ep2 (dev, ssm); + break; - case SSM_TURN_OFF: - /* Set control_packet argument */ - vdev->control_packet = turn_off; + case SSM_TURN_OFF: + /* Set control_packet argument */ + self->control_packet = turn_off; - send_control_packet(ssm, idev); - break; + send_control_packet (ssm, dev); + break; - case SSM_TURN_ON: - if (!vdev->active) { - /* The only correct exit */ - fpi_ssm_mark_completed(ssm); + case SSM_TURN_ON: + if (!self->active) + { + /* The only correct exit */ + fpi_ssm_mark_completed (ssm); - if (vdev->need_report) { - fpi_imgdev_deactivate_complete(idev); - vdev->need_report = 0; - } - break; - } - /* Set control_packet argument */ - vdev->control_packet = turn_on; + if (self->need_report) + { + fpi_image_device_deactivate_complete (idev, + NULL); + self->need_report = 0; + } + break; + } + /* Set control_packet argument */ + self->control_packet = turn_on; - send_control_packet(ssm, idev); - break; + send_control_packet (ssm, dev); + break; - case SSM_ASK_INTERRUPT: - /* Activated, light must be blinking now */ + case SSM_ASK_INTERRUPT: { + FpiUsbTransfer *transfer; + /* Activated, light must be blinking now */ - /* If we first time here, report that activate completed */ - if (vdev->need_report) { - fpi_imgdev_activate_complete(idev, 0); - vdev->need_report = 0; - } + /* If we first time here, report that activate completed */ + if (self->need_report) + { + fpi_image_device_activate_complete (idev, NULL); + self->need_report = 0; + } - /* Asynchronously enquire an interrupt */ - vdev->transfer = fpi_usb_alloc(); - vdev->transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER; - libusb_fill_interrupt_transfer(vdev->transfer, usb_dev, 0x83, - vdev->interrupt, - VFS_INTERRUPT_SIZE, - interrupt_callback, ssm, 0); - libusb_submit_transfer(vdev->transfer); + /* Asynchronously enquire an interrupt */ + transfer = fpi_usb_transfer_new (dev); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_fill_interrupt (transfer, 0x83, VFS_INTERRUPT_SIZE); + fpi_usb_transfer_submit (transfer, + 0, + fpi_device_get_cancellable (dev), + interrupt_callback, NULL); + fpi_usb_transfer_unref (transfer); - /* This flag could be turned off only in callback function */ - vdev->wait_interrupt = 1; + /* I've put it here to be sure that data is cleared */ + clear_data (self); - /* I've put it here to be sure that data is cleared */ - clear_data(vdev); + fpi_ssm_next_state (ssm); + break; + } - fpi_ssm_next_state(ssm); - break; + case SSM_WAIT_INTERRUPT: + /* TODO: This state is unused at this point. When we + * are in this state, then a user cancellation will + * cause deactivation. In that case, the USB transfer + * is cancelled and the device is set to not be active. + * We then go into SSM_CLEAR_EP2 based on the + * cancellation. */ + break; - case SSM_WAIT_INTERRUPT: - /* Check if user had interrupted the process */ - if (!vdev->active) { - libusb_cancel_transfer(vdev->transfer); - fpi_ssm_jump_to_state(ssm, SSM_CLEAR_EP2); - break; - } + case SSM_RECEIVE_FINGER: { + FpiUsbTransfer *transfer; - if (vdev->wait_interrupt) - fpi_timeout_add(VFS_SSM_TIMEOUT, wait_interrupt, _dev, ssm); - break; + if (self->memory == 0) + { + /* Initialize fingerprint buffer */ + g_free (self->lines_buffer); + self->memory = VFS_USB_BUFFER_SIZE; + self->lines_buffer = g_malloc (self->memory); + self->bytes = 0; - case SSM_RECEIVE_FINGER: - if (vdev->memory == 0) { - /* Initialize fingerprint buffer */ - g_free(vdev->lines_buffer); - vdev->memory = VFS_USB_BUFFER_SIZE; - vdev->lines_buffer = g_malloc(vdev->memory); - vdev->bytes = 0; + /* Finger is on the scanner */ + fpi_image_device_report_finger_status (idev, TRUE); + } - /* Finger is on the scanner */ - fpi_imgdev_report_finger_status(idev, 1); - } + /* Increase buffer size while it's insufficient */ + while (self->bytes + VFS_USB_BUFFER_SIZE > self->memory) + { + self->memory <<= 1; + self->lines_buffer = + (struct vfs_line *) g_realloc (self->lines_buffer, + self->memory); + } - /* Increase buffer size while it's insufficient */ - while (vdev->bytes + VFS_USB_BUFFER_SIZE > vdev->memory) { - vdev->memory <<= 1; - vdev->lines_buffer = - (struct vfs_line *)g_realloc(vdev->lines_buffer, - vdev->memory); - } + /* Receive chunk of data */ + transfer = fpi_usb_transfer_new (dev); + fpi_usb_transfer_fill_bulk_full (transfer, 0x82, + (void *) self->lines_buffer + self->bytes, + VFS_USB_BUFFER_SIZE, NULL); + transfer->ssm = ssm; + fpi_usb_transfer_submit (transfer, VFS_USB_TIMEOUT, NULL, + receive_callback, NULL); + fpi_usb_transfer_unref (transfer); + break; + } - /* Receive chunk of data */ - vdev->transfer = fpi_usb_alloc(); - vdev->transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER; - libusb_fill_bulk_transfer(vdev->transfer, usb_dev, 0x82, - (void *)vdev->lines_buffer + - vdev->bytes, VFS_USB_BUFFER_SIZE, - receive_callback, ssm, - VFS_USB_TIMEOUT); - libusb_submit_transfer(vdev->transfer); - break; + case SSM_SUBMIT_IMAGE: + submit_image (self); + clear_data (self); - case SSM_SUBMIT_IMAGE: - submit_image(idev); - clear_data(vdev); + /* Wait for probable vdev->active changing */ + fpi_device_add_timeout (dev, VFS_SSM_TIMEOUT, + fpi_ssm_next_state_timeout_cb, ssm); + break; - /* Wait for probable vdev->active changing */ - fpi_timeout_add(VFS_SSM_TIMEOUT, fpi_ssm_next_state_timeout_cb, _dev, ssm); - break; + case SSM_NEXT_RECEIVE: + if (!self->active) + { + /* It's the last scan */ + fpi_ssm_jump_to_state (ssm, SSM_CLEAR_EP2); + break; + } - case SSM_NEXT_RECEIVE: - if (!vdev->active) { - /* It's the last scan */ - fpi_ssm_jump_to_state(ssm, SSM_CLEAR_EP2); - break; - } + /* Set control_packet argument */ + self->control_packet = next_receive_1; - /* Set control_packet argument */ - vdev->control_packet = next_receive_1; + send_control_packet (ssm, dev); + break; - send_control_packet(ssm, idev); - break; + case SSM_WAIT_ANOTHER_SCAN: + /* Orange light is on now */ + fpi_device_add_timeout (dev, VFS_SSM_ORANGE_TIMEOUT, + another_scan, ssm); + break; - case SSM_WAIT_ANOTHER_SCAN: - /* Orange light is on now */ - fpi_timeout_add(VFS_SSM_ORANGE_TIMEOUT, another_scan, _dev, ssm); - break; - - default: - fp_err("Unknown state"); - fpi_imgdev_session_error(idev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - } + default: + fp_err ("Unknown state"); + fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); + } } /* Driver functions */ /* Callback for dev_activate ssm */ -static void dev_activate_callback(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +dev_activate_callback (FpiSsm *ssm, FpDevice *dev, GError *error) { - struct vfs_dev_t *vdev = FP_INSTANCE_DATA(_dev); + FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050 (dev); - vdev->ssm_active = 0; + self->ssm_active = 0; - fpi_ssm_free(ssm); + if (error) + { + g_warning ("Unhandled device activation error: %s", error->message); + g_error_free (error); + } + + fpi_ssm_free (ssm); } /* Activate device */ -static int dev_activate(struct fp_img_dev *idev) +static void +dev_activate (FpImageDevice *idev) { - struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev)); + FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050 (idev); - /* Initialize flags */ - vdev->active = 1; - vdev->need_report = 1; - vdev->ssm_active = 1; + /* Initialize flags */ + self->active = 1; + self->need_report = 1; + self->ssm_active = 1; - fpi_ssm *ssm = fpi_ssm_new(FP_DEV(idev), activate_ssm, SSM_STATES, idev); - fpi_ssm_start(ssm, dev_activate_callback); - return 0; + FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (idev), activate_ssm, SSM_STATES); + fpi_ssm_start (ssm, dev_activate_callback); } /* Deactivate device */ -static void dev_deactivate(struct fp_img_dev *idev) +static void +dev_deactivate (FpImageDevice *idev) { - struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev)); + FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050 (idev); - if (!vdev->ssm_active) { - fpi_imgdev_deactivate_complete(idev); - return; - } + if (!self->ssm_active) + { + fpi_image_device_deactivate_complete (idev, NULL); + return; + } - /* Initialize flags */ - vdev->active = 0; - vdev->need_report = 1; + /* Initialize flags */ + self->active = 0; + self->need_report = 1; } /* Callback for dev_open ssm */ -static void dev_open_callback(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +dev_open_callback (FpiSsm *ssm, FpDevice *dev, GError *error) { - /* Notify open complete */ - fpi_imgdev_open_complete(user_data, 0); - fpi_ssm_free(ssm); + /* Notify open complete */ + fpi_image_device_open_complete (FP_IMAGE_DEVICE (dev), error); + fpi_ssm_free (ssm); } /* Open device */ -static int dev_open(struct fp_img_dev *idev, unsigned long driver_data) +static void +dev_open (FpImageDevice *idev) { - struct vfs_dev_t *vdev; + GError *error = NULL; - /* Claim usb interface */ - int error = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(idev)), 0); - if (error < 0) { - /* Interface not claimed, return error */ - fp_err("could not claim interface 0"); - return error; - } + /* Claim usb interface */ + if (!g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (idev)), 0, 0, &error)) + { + fpi_image_device_open_complete (idev, error); + return; + } - /* Initialize private structure */ - vdev = g_malloc0(sizeof(struct vfs_dev_t)); - fp_dev_set_instance_data(FP_DEV(idev), vdev); - - /* Clearing previous device state */ - fpi_ssm *ssm = fpi_ssm_new(FP_DEV(idev), activate_ssm, SSM_STATES, idev); - fpi_ssm_start(ssm, dev_open_callback); - return 0; + /* Clearing previous device state */ + FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (idev), activate_ssm, SSM_STATES); + fpi_ssm_start (ssm, dev_open_callback); } /* Close device */ -static void dev_close(struct fp_img_dev *idev) +static void +dev_close (FpImageDevice *idev) { - struct vfs_dev_t *vdev; + GError *error = NULL; + FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050 (idev); - /* Release private structure */ - vdev = FP_INSTANCE_DATA(FP_DEV(idev)); - g_free(vdev); + clear_data (self); - /* Release usb interface */ - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(idev)), 0); + /* Release usb interface */ + g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (idev)), + 0, 0, &error); - /* Notify close complete */ - fpi_imgdev_close_complete(idev); + /* Notify close complete */ + fpi_image_device_close_complete (idev, error); } /* Usb id table of device */ -static const struct usb_id id_table[] = { - {.vendor = 0x138a,.product = 0x0050}, - {0, 0, 0,}, +static const FpIdEntry id_table[] = { + {.vid = 0x138a, .pid = 0x0050, }, + {.vid = 0, .pid = 0, .driver_data = 0}, }; -/* Device driver definition */ -struct fp_img_driver vfs0050_driver = { - /* Driver specification */ - .driver = { - .id = VFS0050_ID, - .name = FP_COMPONENT, - .full_name = "Validity VFS0050", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_SWIPE, - }, +static void +fpi_device_vfs0050_init (FpDeviceVfs0050 *self) +{ +} +static void +fpi_device_vfs0050_class_init (FpDeviceVfs0050Class *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); - /* Image specification */ - .flags = 0, - .img_width = VFS_IMAGE_WIDTH, - .img_height = -1, - .bz3_threshold = 24, + dev_class->id = "vfs0050"; + dev_class->full_name = "Validity VFS0050"; + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->id_table = id_table; + dev_class->scan_type = FP_SCAN_TYPE_SWIPE; - /* Routine specification */ - .open = dev_open, - .close = dev_close, - .activate = dev_activate, - .deactivate = dev_deactivate, -}; + img_class->img_open = dev_open; + img_class->img_close = dev_close; + img_class->activate = dev_activate; + img_class->deactivate = dev_deactivate; + + img_class->bz3_threshold = 24; + + img_class->img_width = VFS_IMAGE_WIDTH; + img_class->img_height = -1; +} diff --git a/libfprint/drivers/vfs0050.h b/libfprint/drivers/vfs0050.h index 81407ddb..f4ebb177 100644 --- a/libfprint/drivers/vfs0050.h +++ b/libfprint/drivers/vfs0050.h @@ -17,6 +17,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#pragma once + +#include "fpi-image-device.h" + /* Timeout for all send/recv operations, except interrupt waiting and abort */ #define VFS_USB_TIMEOUT 100 /* Timeout for usb abort */ @@ -47,336 +51,336 @@ #define EP3_IN 0x83 /* Fingerprint horizontal line */ -struct vfs_line { - /* It must be always 0x01 */ - unsigned char _0x01; - /* It must be always 0xfe */ - unsigned char _0xfe; +struct vfs_line +{ + /* It must be always 0x01 */ + unsigned char _0x01; + /* It must be always 0xfe */ + unsigned char _0xfe; - /* line number starting from some number in Little-Endian */ - unsigned short id; + /* line number starting from some number in Little-Endian */ + unsigned short id; - /* Some hashes which are useful to detect noise */ - unsigned char noise_hash_1; - unsigned char noise_hash_2; + /* Some hashes which are useful to detect noise */ + unsigned char noise_hash_1; + unsigned char noise_hash_2; - /* The first byte of _somedata is always 0x00, the second is strange useless cyclic line number */ - unsigned short _somedata; + /* The first byte of _somedata is always 0x00, the second is strange useless cyclic line number */ + unsigned short _somedata; - /* Fingerprint image */ - unsigned char data[VFS_IMAGE_WIDTH]; + /* Fingerprint image */ + unsigned char data[VFS_IMAGE_WIDTH]; - /* Narrow fingerprint part from the center used for variable speed lines assembling */ - unsigned char next_line_part[VFS_NEXT_LINE_WIDTH]; + /* Narrow fingerprint part from the center used for variable speed lines assembling */ + unsigned char next_line_part[VFS_NEXT_LINE_WIDTH]; - /* scan_data is 0xfb except some rare cases, it's skipped */ - unsigned char scan_data[8]; -} __attribute__ ((__packed__)); + /* scan_data is 0xfb except some rare cases, it's skipped */ + unsigned char scan_data[8]; +} __attribute__((__packed__)); /* The main driver structure */ -struct vfs_dev_t { - /* One if we were asked to read fingerprint, zero otherwise */ - char active; +struct _FpDeviceVfs0050 +{ + FpImageDevice parent; - /* Control packet parameter for send_control_packet */ - unsigned char *control_packet; + /* One if we were asked to read fingerprint, zero otherwise */ + char active; - /* For dev_deactivate to check whether ssm still running or not */ - char ssm_active; + /* Control packet parameter for send_control_packet */ + unsigned char *control_packet; - /* Current async transfer */ - struct libusb_transfer *transfer; + /* For dev_deactivate to check whether ssm still running or not */ + char ssm_active; - /* Should we call fpi_imgdev_activate_complete or fpi_imgdev_deactivate_complete */ - char need_report; + /* Should we call fpi_imgdev_activate_complete or fpi_imgdev_deactivate_complete */ + char need_report; - /* Should we wait more for interrupt */ - char wait_interrupt; + /* Received fingerprint raw lines */ + struct vfs_line *lines_buffer; - /* Received fingerprint raw lines */ - struct vfs_line *lines_buffer; + /* Current number of received bytes and current memory used by data */ + int bytes, memory; - /* Current number of received bytes and current memory used by data */ - int bytes, memory; + /* USB buffer for fingerprint */ + char *usb_buffer; - /* USB buffer for fingerprint */ - char *usb_buffer; - - /* Received interrupt data */ - unsigned char interrupt[8]; + /* Received interrupt data */ + unsigned char interrupt[8]; }; +G_DECLARE_FINAL_TYPE (FpDeviceVfs0050, fpi_device_vfs0050, FPI, DEVICE_VFS0050, FpImageDevice) + /* SSM states for clear_ep2 */ enum SUBSM1 { - SUBSM1_COMMAND_04, - SUBSM1_RETURN_CODE, - SUBSM1_ABORT_2, + SUBSM1_COMMAND_04, + SUBSM1_RETURN_CODE, + SUBSM1_ABORT_2, - SUBSM1_STATES, + SUBSM1_STATES, }; /* SSM states for control */ enum SUBSM2 { - SUBSM2_SEND_CONTROL, - SUBSM2_RETURN_CODE, /* If next_receive, send another control packet */ + SUBSM2_SEND_CONTROL, + SUBSM2_RETURN_CODE, /* If next_receive, send another control packet */ - SUBSM2_SEND_COMMIT, - SUBSM2_COMMIT_RESPONSE, - SUBSM2_READ_EMPTY_INTERRUPT, - SUBSM2_ABORT_3, - SUBSM2_CLEAR_EP2, + SUBSM2_SEND_COMMIT, + SUBSM2_COMMIT_RESPONSE, + SUBSM2_READ_EMPTY_INTERRUPT, + SUBSM2_ABORT_3, + SUBSM2_CLEAR_EP2, - SUBSM2_STATES, + SUBSM2_STATES, }; /* SSM states for activate_ssm */ enum SSM_STATE { - SSM_INITIAL_ABORT_1, - SSM_INITIAL_ABORT_2, - SSM_INITIAL_ABORT_3, - SSM_CLEAR_EP2, - SSM_TURN_OFF, + SSM_INITIAL_ABORT_1, + SSM_INITIAL_ABORT_2, + SSM_INITIAL_ABORT_3, + SSM_CLEAR_EP2, + SSM_TURN_OFF, - /* Here the device is turned off; if not active, complete ssm */ - SSM_TURN_ON, + /* Here the device is turned off; if not active, complete ssm */ + SSM_TURN_ON, - SSM_ASK_INTERRUPT, - SSM_WAIT_INTERRUPT, + SSM_ASK_INTERRUPT, + SSM_WAIT_INTERRUPT, - SSM_RECEIVE_FINGER, - SSM_SUBMIT_IMAGE, + SSM_RECEIVE_FINGER, + SSM_SUBMIT_IMAGE, - /* If not active, jump to CLEAR_EP2 */ - SSM_NEXT_RECEIVE, - SSM_WAIT_ANOTHER_SCAN, - /* Jump to TURN_ON */ + /* If not active, jump to CLEAR_EP2 */ + SSM_NEXT_RECEIVE, + SSM_WAIT_ANOTHER_SCAN, + /* Jump to TURN_ON */ - SSM_STATES + SSM_STATES }; /* Blocks of data from USB sniffer */ /* Turns on the light */ static unsigned char turn_on[] = { - 0x39, 0x20, 0xBF, 0x02, 0x00, 0xF4, 0x01, 0x00, 0x00, 0x01, 0xD1, 0x00, - 0x20, 0xD1, 0xD1, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xF4, 0x01, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0xF4, 0x01, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, + 0x39, 0x20, 0xBF, 0x02, 0x00, 0xF4, 0x01, 0x00, 0x00, 0x01, 0xD1, 0x00, + 0x20, 0xD1, 0xD1, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0x01, 0x00, + 0x00, 0x01, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xF4, 0x01, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0xF4, 0x01, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, }; /* Power off */ static unsigned char turn_off[] = { - 0x39, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, + 0x39, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, }; /* Turns on orange light */ static unsigned char next_receive_1[] = { - 0x39, 0xB8, 0x0B, 0x00, 0x00, 0xB8, 0x0B, 0x00, 0x00, 0x01, 0xD1, 0x00, - 0x20, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0xB8, 0x0B, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, + 0x39, 0xB8, 0x0B, 0x00, 0x00, 0xB8, 0x0B, 0x00, 0x00, 0x01, 0xD1, 0x00, + 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0xB8, 0x0B, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, }; /* Packet directly after next_receive_1 */ static unsigned char next_receive_2[] = { - 0x39, 0xE8, 0x03, 0x00, 0x00, 0xE8, 0x03, 0x00, 0x00, 0x01, 0xD1, 0x00, - 0x20, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0xE8, 0x03, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, + 0x39, 0xE8, 0x03, 0x00, 0x00, 0xE8, 0x03, 0x00, 0x00, 0x01, 0xD1, 0x00, + 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0xE8, 0x03, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, }; /* Commit message */ static unsigned char commit_out[] = { - 0x02, 0x94, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x2C, 0x03, 0x00, - 0x30, 0x1B, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x08, 0x00, 0x20, 0x03, 0x00, 0x30, 0x3D, 0x10, 0x00, - 0x00, 0x20, 0x00, 0x08, - 0x00, 0x18, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, - 0x00, 0x24, 0x03, 0x00, - 0x30, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x28, 0x03, 0x00, - 0x30, 0x08, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x08, 0x00, 0x30, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x08, - 0x00, 0x38, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, - 0x00, 0x3C, 0x03, 0x00, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x44, 0x03, 0x00, - 0x30, 0x14, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x08, 0x00, 0x48, 0x03, 0x00, 0x30, 0x01, 0x04, 0x02, - 0x00, 0x20, 0x00, 0x08, - 0x00, 0x4C, 0x03, 0x00, 0x30, 0x01, 0x0C, 0x02, 0x00, 0x20, 0x00, 0x08, - 0x00, 0x54, 0x03, 0x00, - 0x30, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x5C, 0x03, 0x00, - 0x30, 0x90, 0x01, 0x02, - 0x00, 0x20, 0x00, 0x08, 0x00, 0x60, 0x03, 0x00, 0x30, 0x2C, 0x01, 0x19, - 0x00, 0x20, 0x00, 0x08, - 0x00, 0x64, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, - 0x00, 0x6C, 0x03, 0x00, - 0x30, 0x1E, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x70, 0x03, 0x00, - 0x30, 0x21, 0x80, 0x00, - 0x00, 0x20, 0x00, 0x08, 0x00, 0x78, 0x03, 0x00, 0x30, 0x09, 0x00, 0x02, - 0x00, 0x20, 0x00, 0x08, - 0x00, 0x7C, 0x03, 0x00, 0x30, 0x0B, 0x00, 0x19, 0x00, 0x20, 0x00, 0x08, - 0x00, 0x80, 0x03, 0x00, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x84, 0x03, 0x00, - 0x30, 0x3A, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x08, 0x00, 0x88, 0x03, 0x00, 0x30, 0x14, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x08, - 0x00, 0x8C, 0x03, 0x00, 0x30, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, - 0x00, 0x90, 0x03, 0x00, - 0x30, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x94, 0x03, 0x00, - 0x30, 0x08, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x08, 0x00, 0x98, 0x03, 0x00, 0x30, 0x00, 0x00, 0xA1, - 0x01, 0x20, 0x00, 0x08, - 0x00, 0x9C, 0x03, 0x00, 0x30, 0x00, 0x00, 0xA1, 0x01, 0x20, 0x00, 0x08, - 0x00, 0xA8, 0x03, 0x00, - 0x30, 0x64, 0x01, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0xAC, 0x03, 0x00, - 0x30, 0x64, 0x01, 0x00, - 0x00, 0x20, 0x00, 0x08, 0x00, 0xB0, 0x03, 0x00, 0x30, 0x00, 0x01, 0x00, - 0x00, 0x20, 0x00, 0x08, - 0x00, 0xB4, 0x03, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x08, - 0x00, 0xB8, 0x03, 0x00, - 0x30, 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0xBC, 0x03, 0x00, - 0x30, 0x05, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x08, 0x00, 0xC0, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x08, - 0x00, 0x84, 0x03, 0x00, 0x30, 0x3B, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, - 0x00, 0x08, 0x07, 0x00, - 0x30, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x0C, 0x07, 0x00, - 0x30, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x08, 0x00, 0x14, 0x07, 0x00, 0x30, 0x20, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x08, - 0x00, 0x1C, 0x07, 0x00, 0x30, 0x1A, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, - 0x00, 0x70, 0x0D, 0x00, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x28, 0x00, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x90, 0x00, 0x00, 0x00, 0x2B, 0xFF, 0x2B, 0xFF, 0x2B, - 0xED, 0x00, 0x00, 0x2B, - 0xFB, 0x00, 0x00, 0x2B, 0xC5, 0x00, 0x00, 0x2B, 0x05, 0x80, 0x70, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x24, 0xD3, 0x2E, 0xC0, 0x2C, 0x3B, 0x08, 0xF0, 0x3B, 0x09, 0x24, - 0xBB, 0x3B, 0x0B, 0x24, - 0xAA, 0x3B, 0x1F, 0xF8, 0x00, 0x3B, 0x3F, 0xF0, 0x00, 0x3B, 0x35, 0xC0, - 0x00, 0x38, 0x80, 0x2C, - 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x38, 0x80, 0x2C, 0x70, 0x00, - 0x00, 0x00, 0x00, 0xC0, - 0x3A, 0x80, 0x2C, 0x70, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x3B, 0x0A, 0x80, - 0x2E, 0x83, 0x24, 0xDB, - 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x2C, 0x31, 0x83, 0x2C, 0x70, - 0x00, 0x00, 0x00, 0x00, - 0xCB, 0x33, 0x1B, 0x83, 0x2C, 0x70, 0x00, 0x00, 0x00, 0x00, 0xCB, 0x31, - 0x83, 0x2C, 0x70, 0x00, - 0x00, 0x00, 0x00, 0xCB, 0x00, 0x33, 0x1E, 0x83, 0x2E, 0x25, 0xFF, 0xC4, - 0x00, 0x2F, 0x06, 0x84, - 0x2E, 0x00, 0x00, 0x10, 0x20, 0x29, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, - 0x00, 0x23, 0x00, 0x00, - 0x00, 0x21, 0x00, 0x10, 0x00, 0x48, 0x03, 0x00, 0x30, 0xFF, 0xF0, 0xFF, - 0xFF, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x21, 0x00, 0x10, 0x00, 0x4C, 0x03, 0x00, - 0x30, 0xFF, 0xF0, 0xFF, - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x21, 0x00, 0x10, - 0x00, 0x20, 0x03, 0x00, - 0x30, 0x7F, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x10, 0x00, - 0x00, 0x20, 0x00, 0x08, - 0x00, 0x24, 0x03, 0x00, 0x30, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, - 0x00, 0x1C, 0x07, 0x00, - 0x30, 0x1A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x10, 0x00, 0x20, 0x03, 0x00, - 0x30, 0xC3, 0xFF, 0xFF, - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, - 0x00, 0x80, 0x03, 0x00, - 0x30, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x84, 0x00, 0x31, 0x65, 0x77, - 0x77, 0x77, 0x78, 0x88, - 0x77, 0x77, 0x76, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x77, 0x67, - 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x67, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x77, 0x66, 0x66, - 0x66, 0x66, 0x67, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x76, 0x66, 0x56, - 0x66, 0x66, 0x56, 0x55, - 0x65, 0x66, 0x66, 0x66, 0x65, 0x66, 0x66, 0x55, 0x66, 0x66, 0x65, 0x66, - 0x76, 0x76, 0x77, 0x77, - 0x66, 0x66, 0x66, 0x76, 0x67, 0x66, 0x77, 0x67, 0x66, 0x66, 0x66, 0x56, - 0x65, 0x66, 0x65, 0x66, - 0x66, 0x55, 0x55, 0x54, 0x55, 0x65, 0x66, 0x66, 0x66, 0x76, 0x77, 0x87, - 0x88, 0x77, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x65, 0x66, 0x55, 0x55, 0x65, 0x56, 0x55, - 0x55, 0x55, 0x54, 0x45, - 0x54, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x66, 0x77, 0x77, 0x77, - 0x66, 0x26, 0x00, 0x28, - 0x00, 0xFF, 0x00, 0x0F, 0x00, 0xF0, 0xF0, 0x0F, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x30, 0x01, 0x02, - 0x00, 0x2C, 0x01, 0x28, 0x00, 0x20, 0x80, 0x00, 0x00, 0x0A, 0x00, 0x02, - 0x00, 0x0B, 0x00, 0x19, - 0x00, 0x40, 0x1F, 0x10, 0x27, 0x00, 0x0F, 0x03, 0x00, + 0x02, 0x94, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x2C, 0x03, 0x00, + 0x30, 0x1B, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x08, 0x00, 0x20, 0x03, 0x00, 0x30, 0x3D, 0x10, 0x00, + 0x00, 0x20, 0x00, 0x08, + 0x00, 0x18, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, + 0x00, 0x24, 0x03, 0x00, + 0x30, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x28, 0x03, 0x00, + 0x30, 0x08, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x08, 0x00, 0x30, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x08, + 0x00, 0x38, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, + 0x00, 0x3C, 0x03, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x44, 0x03, 0x00, + 0x30, 0x14, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x08, 0x00, 0x48, 0x03, 0x00, 0x30, 0x01, 0x04, 0x02, + 0x00, 0x20, 0x00, 0x08, + 0x00, 0x4C, 0x03, 0x00, 0x30, 0x01, 0x0C, 0x02, 0x00, 0x20, 0x00, 0x08, + 0x00, 0x54, 0x03, 0x00, + 0x30, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x5C, 0x03, 0x00, + 0x30, 0x90, 0x01, 0x02, + 0x00, 0x20, 0x00, 0x08, 0x00, 0x60, 0x03, 0x00, 0x30, 0x2C, 0x01, 0x19, + 0x00, 0x20, 0x00, 0x08, + 0x00, 0x64, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, + 0x00, 0x6C, 0x03, 0x00, + 0x30, 0x1E, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x70, 0x03, 0x00, + 0x30, 0x21, 0x80, 0x00, + 0x00, 0x20, 0x00, 0x08, 0x00, 0x78, 0x03, 0x00, 0x30, 0x09, 0x00, 0x02, + 0x00, 0x20, 0x00, 0x08, + 0x00, 0x7C, 0x03, 0x00, 0x30, 0x0B, 0x00, 0x19, 0x00, 0x20, 0x00, 0x08, + 0x00, 0x80, 0x03, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x84, 0x03, 0x00, + 0x30, 0x3A, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x08, 0x00, 0x88, 0x03, 0x00, 0x30, 0x14, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x08, + 0x00, 0x8C, 0x03, 0x00, 0x30, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, + 0x00, 0x90, 0x03, 0x00, + 0x30, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x94, 0x03, 0x00, + 0x30, 0x08, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x08, 0x00, 0x98, 0x03, 0x00, 0x30, 0x00, 0x00, 0xA1, + 0x01, 0x20, 0x00, 0x08, + 0x00, 0x9C, 0x03, 0x00, 0x30, 0x00, 0x00, 0xA1, 0x01, 0x20, 0x00, 0x08, + 0x00, 0xA8, 0x03, 0x00, + 0x30, 0x64, 0x01, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0xAC, 0x03, 0x00, + 0x30, 0x64, 0x01, 0x00, + 0x00, 0x20, 0x00, 0x08, 0x00, 0xB0, 0x03, 0x00, 0x30, 0x00, 0x01, 0x00, + 0x00, 0x20, 0x00, 0x08, + 0x00, 0xB4, 0x03, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x08, + 0x00, 0xB8, 0x03, 0x00, + 0x30, 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0xBC, 0x03, 0x00, + 0x30, 0x05, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x08, 0x00, 0xC0, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x08, + 0x00, 0x84, 0x03, 0x00, 0x30, 0x3B, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, + 0x00, 0x08, 0x07, 0x00, + 0x30, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x0C, 0x07, 0x00, + 0x30, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x08, 0x00, 0x14, 0x07, 0x00, 0x30, 0x20, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x08, + 0x00, 0x1C, 0x07, 0x00, 0x30, 0x1A, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, + 0x00, 0x70, 0x0D, 0x00, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x28, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x90, 0x00, 0x00, 0x00, 0x2B, 0xFF, 0x2B, 0xFF, 0x2B, + 0xED, 0x00, 0x00, 0x2B, + 0xFB, 0x00, 0x00, 0x2B, 0xC5, 0x00, 0x00, 0x2B, 0x05, 0x80, 0x70, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x24, 0xD3, 0x2E, 0xC0, 0x2C, 0x3B, 0x08, 0xF0, 0x3B, 0x09, 0x24, + 0xBB, 0x3B, 0x0B, 0x24, + 0xAA, 0x3B, 0x1F, 0xF8, 0x00, 0x3B, 0x3F, 0xF0, 0x00, 0x3B, 0x35, 0xC0, + 0x00, 0x38, 0x80, 0x2C, + 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x38, 0x80, 0x2C, 0x70, 0x00, + 0x00, 0x00, 0x00, 0xC0, + 0x3A, 0x80, 0x2C, 0x70, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x3B, 0x0A, 0x80, + 0x2E, 0x83, 0x24, 0xDB, + 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x2C, 0x31, 0x83, 0x2C, 0x70, + 0x00, 0x00, 0x00, 0x00, + 0xCB, 0x33, 0x1B, 0x83, 0x2C, 0x70, 0x00, 0x00, 0x00, 0x00, 0xCB, 0x31, + 0x83, 0x2C, 0x70, 0x00, + 0x00, 0x00, 0x00, 0xCB, 0x00, 0x33, 0x1E, 0x83, 0x2E, 0x25, 0xFF, 0xC4, + 0x00, 0x2F, 0x06, 0x84, + 0x2E, 0x00, 0x00, 0x10, 0x20, 0x29, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x23, 0x00, 0x00, + 0x00, 0x21, 0x00, 0x10, 0x00, 0x48, 0x03, 0x00, 0x30, 0xFF, 0xF0, 0xFF, + 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x21, 0x00, 0x10, 0x00, 0x4C, 0x03, 0x00, + 0x30, 0xFF, 0xF0, 0xFF, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x21, 0x00, 0x10, + 0x00, 0x20, 0x03, 0x00, + 0x30, 0x7F, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x10, 0x00, + 0x00, 0x20, 0x00, 0x08, + 0x00, 0x24, 0x03, 0x00, 0x30, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, + 0x00, 0x1C, 0x07, 0x00, + 0x30, 0x1A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x10, 0x00, 0x20, 0x03, 0x00, + 0x30, 0xC3, 0xFF, 0xFF, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, + 0x00, 0x80, 0x03, 0x00, + 0x30, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x84, 0x00, 0x31, 0x65, 0x77, + 0x77, 0x77, 0x78, 0x88, + 0x77, 0x77, 0x76, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x77, 0x67, + 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x67, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x77, 0x66, 0x66, + 0x66, 0x66, 0x67, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x76, 0x66, 0x56, + 0x66, 0x66, 0x56, 0x55, + 0x65, 0x66, 0x66, 0x66, 0x65, 0x66, 0x66, 0x55, 0x66, 0x66, 0x65, 0x66, + 0x76, 0x76, 0x77, 0x77, + 0x66, 0x66, 0x66, 0x76, 0x67, 0x66, 0x77, 0x67, 0x66, 0x66, 0x66, 0x56, + 0x65, 0x66, 0x65, 0x66, + 0x66, 0x55, 0x55, 0x54, 0x55, 0x65, 0x66, 0x66, 0x66, 0x76, 0x77, 0x87, + 0x88, 0x77, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x65, 0x66, 0x55, 0x55, 0x65, 0x56, 0x55, + 0x55, 0x55, 0x54, 0x45, + 0x54, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x66, 0x77, 0x77, 0x77, + 0x66, 0x26, 0x00, 0x28, + 0x00, 0xFF, 0x00, 0x0F, 0x00, 0xF0, 0xF0, 0x0F, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x30, 0x01, 0x02, + 0x00, 0x2C, 0x01, 0x28, 0x00, 0x20, 0x80, 0x00, 0x00, 0x0A, 0x00, 0x02, + 0x00, 0x0B, 0x00, 0x19, + 0x00, 0x40, 0x1F, 0x10, 0x27, 0x00, 0x0F, 0x03, 0x00, }; /* Known interrupts */ static unsigned char empty_interrupt[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, }; static unsigned char interrupt1[] = { - 0x02, 0x00, 0x0E, 0x00, 0xF0, + 0x02, 0x00, 0x0E, 0x00, 0xF0, }; static unsigned char interrupt2[] = { - 0x02, 0x04, 0x0A, 0x00, 0xF0, + 0x02, 0x04, 0x0A, 0x00, 0xF0, }; static unsigned char interrupt3[] = { - 0x02, 0x00, 0x0A, 0x00, 0xF0, + 0x02, 0x00, 0x0A, 0x00, 0xF0, }; diff --git a/libfprint/drivers/vfs101.c b/libfprint/drivers/vfs101.c index 60f0a819..37e083c7 100644 --- a/libfprint/drivers/vfs101.c +++ b/libfprint/drivers/vfs101.c @@ -22,1526 +22,1364 @@ #include "drivers_api.h" /* Input-Output usb endpoint */ -#define EP_IN(n) (n | LIBUSB_ENDPOINT_IN) -#define EP_OUT(n) (n | LIBUSB_ENDPOINT_OUT) +#define EP_IN(n) (n | FPI_USB_ENDPOINT_IN) +#define EP_OUT(n) (n | FPI_USB_ENDPOINT_OUT) /* Usb bulk timeout */ -#define BULK_TIMEOUT 100 +#define BULK_TIMEOUT 100 /* The device send back the image into block of 16 frames of 292 bytes */ -#define VFS_FRAME_SIZE 292 -#define VFS_BLOCK_SIZE 16 * VFS_FRAME_SIZE +#define VFS_FRAME_SIZE 292 +#define VFS_BLOCK_SIZE 16 * VFS_FRAME_SIZE /* Buffer height */ -#define VFS_BUFFER_HEIGHT 5000 +#define VFS_BUFFER_HEIGHT 5000 /* Buffer size */ -#define VFS_BUFFER_SIZE (VFS_BUFFER_HEIGHT * VFS_FRAME_SIZE) +#define VFS_BUFFER_SIZE (VFS_BUFFER_HEIGHT * VFS_FRAME_SIZE) /* Image width */ -#define VFS_IMG_WIDTH 200 +#define VFS_IMG_WIDTH 200 /* Maximum image height */ -#define VFS_IMG_MAX_HEIGHT 1023 +#define VFS_IMG_MAX_HEIGHT 1023 /* Minimum image height */ -#define VFS_IMG_MIN_HEIGHT 200 +#define VFS_IMG_MIN_HEIGHT 200 /* Scan level threshold */ -#define VFS_IMG_SLT_BEGIN 768 -#define VFS_IMG_SLT_END 64 -#define VFS_IMG_SLT_LINES 4 +#define VFS_IMG_SLT_BEGIN 768 +#define VFS_IMG_SLT_END 64 +#define VFS_IMG_SLT_LINES 4 /* Minimum image level */ -#define VFS_IMG_MIN_IMAGE_LEVEL 144 +#define VFS_IMG_MIN_IMAGE_LEVEL 144 /* Best image contrast */ -#define VFS_IMG_BEST_CONTRAST 128 +#define VFS_IMG_BEST_CONTRAST 128 /* Device parameters address */ -#define VFS_PAR_000E 0x000e -#define VFS_PAR_0011 0x0011 -#define VFS_PAR_THRESHOLD 0x0057 -#define VFS_PAR_STATE_3 0x005e -#define VFS_PAR_STATE_5 0x005f -#define VFS_PAR_INFO_RATE 0x0062 -#define VFS_PAR_0076 0x0076 -#define VFS_PAR_INFO_CONTRAST 0x0077 -#define VFS_PAR_0078 0x0078 +#define VFS_PAR_000E 0x000e +#define VFS_PAR_0011 0x0011 +#define VFS_PAR_THRESHOLD 0x0057 +#define VFS_PAR_STATE_3 0x005e +#define VFS_PAR_STATE_5 0x005f +#define VFS_PAR_INFO_RATE 0x0062 +#define VFS_PAR_0076 0x0076 +#define VFS_PAR_INFO_CONTRAST 0x0077 +#define VFS_PAR_0078 0x0078 /* Device regiones address */ -#define VFS_REG_IMG_EXPOSURE 0xff500e -#define VFS_REG_IMG_CONTRAST 0xff5038 +#define VFS_REG_IMG_EXPOSURE 0xff500e +#define VFS_REG_IMG_CONTRAST 0xff5038 /* Device settings */ -#define VFS_VAL_000E 0x0001 -#define VFS_VAL_0011 0x0008 -#define VFS_VAL_THRESHOLD 0x0096 -#define VFS_VAL_STATE_3 0x0064 -#define VFS_VAL_STATE_5 0x00c8 -#define VFS_VAL_INFO_RATE 0x0001 -#define VFS_VAL_0076 0x0012 -#define VFS_VAL_0078 0x2230 -#define VFS_VAL_IMG_EXPOSURE 0x21c0 +#define VFS_VAL_000E 0x0001 +#define VFS_VAL_0011 0x0008 +#define VFS_VAL_THRESHOLD 0x0096 +#define VFS_VAL_STATE_3 0x0064 +#define VFS_VAL_STATE_5 0x00c8 +#define VFS_VAL_INFO_RATE 0x0001 +#define VFS_VAL_0076 0x0012 +#define VFS_VAL_0078 0x2230 +#define VFS_VAL_IMG_EXPOSURE 0x21c0 /* Structure for Validity device */ -struct vfs101_dev +struct _FpDeviceVfs101 { - /* Action state */ - int active; + FpImageDevice parent; - /* Sequential number */ - unsigned int seqnum; + /* Action state */ + gboolean active; + gboolean deactivate; - /* Usb transfer */ - struct libusb_transfer *transfer; + /* Sequential number */ + unsigned int seqnum; - /* Buffer for input/output */ - unsigned char buffer[VFS_BUFFER_SIZE]; + /* Buffer for input/output */ + unsigned char *buffer; - /* Length of data to send or received */ - unsigned int length; + /* Length of data to send or received */ + unsigned int length; - /* Ignore usb error */ - int ignore_error; + /* Ignore usb error */ + int ignore_error; - /* Loop counter */ - int counter; + /* Loop counter */ + int counter; - /* Number of enroll stage */ - int enroll_stage; + /* Image contrast */ + int contrast; - /* Image contrast */ - int contrast; + /* Best contrast */ + int best_contrast; - /* Best contrast */ - int best_contrast; + /* Best contrast level */ + int best_clevel; - /* Best contrast level */ - int best_clevel; + /* Bottom line of image */ + int bottom; - /* Bottom line of image */ - int bottom; - - /* Image height */ - int height; + /* Image height */ + int height; }; +G_DECLARE_FINAL_TYPE (FpDeviceVfs101, fpi_device_vfs101, FPI, DEVICE_VFS101, + FpImageDevice); +G_DEFINE_TYPE (FpDeviceVfs101, fpi_device_vfs101, FP_TYPE_IMAGE_DEVICE); /* Return byte at specified position */ -static inline unsigned char byte(int position, int value) +static inline unsigned char +byte (int position, int value) { - return (value >> (position * 8)) & 0xff; + return (value >> (position * 8)) & 0xff; } /* Return sequential number */ -static inline unsigned short get_seqnum(int h, int l) +static inline unsigned short +get_seqnum (int h, int l) { - return (h<<8) | l; + return (h << 8) | l; } /* Check sequential number */ -static inline int check_seqnum(struct vfs101_dev *vdev) +static inline int +check_seqnum (FpDeviceVfs101 *vdev) { - if ((byte(0, vdev->seqnum) == vdev->buffer[0]) && - (byte(1, vdev->seqnum) == vdev->buffer[1])) - return 0; - else - return 1; + if ((byte (0, vdev->seqnum) == vdev->buffer[0]) && + (byte (1, vdev->seqnum) == vdev->buffer[1])) + return 0; + else + return 1; } /* Internal result codes */ -enum -{ - RESULT_RETRY, - RESULT_RETRY_SHORT, - RESULT_RETRY_REMOVE, - RESULT_COUNT, -}; - -/* Enroll result codes */ -static int result_codes[2][RESULT_COUNT] = -{ - { - FP_ENROLL_RETRY, - FP_ENROLL_RETRY_TOO_SHORT, - FP_ENROLL_RETRY_REMOVE_FINGER, - }, - { - FP_VERIFY_RETRY, - FP_VERIFY_RETRY_TOO_SHORT, - FP_VERIFY_RETRY_REMOVE_FINGER, - }, -}; - -/* Return result code based on current action */ -static int result_code(struct fp_img_dev *dev, int result) -{ - /* Check result value */ - if (result < 0 || result >= RESULT_COUNT) - return result; - - /* Return result code */ - if (fpi_imgdev_get_action(dev) == IMG_ACTION_ENROLL) - return result_codes[0][result]; - else - return result_codes[1][result]; +enum { + RESULT_RETRY, + RESULT_RETRY_SHORT, + RESULT_RETRY_REMOVE, + RESULT_COUNT, }; /* Dump buffer for debug */ #define dump_buffer(buf) \ - fp_dbg("%02x %02x %02x %02x %02x %02x %02x %02x", \ - buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13] \ - ) + fp_dbg ("%02x %02x %02x %02x %02x %02x %02x %02x", \ + buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13] \ + ) /* Callback of asynchronous send */ -static void async_send_cb(struct libusb_transfer *transfer) +static void +async_send_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpDeviceVfs101 *self = FPI_DEVICE_VFS101 (dev); - /* Cleanup transfer */ - vdev->transfer = NULL; + /* Skip error check if ignore_error is set */ + if (error) + { + if (!self->ignore_error) + { + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } + else + { + g_error_free (error); + fp_dbg ("Ignoring send error: %s", error->message); + } + } + /* Reset ignore_error flag */ + self->ignore_error = FALSE; - /* Skip error check if ignore_error is set */ - if (!vdev->ignore_error) - { - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) - { - /* Transfer not completed, return IO error */ - fp_err("transfer not completed, status = %d", transfer->status); - fpi_imgdev_session_error(dev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - goto out; - } + /* Dump buffer for debug */ + dump_buffer (self->buffer); - if (transfer->length != transfer->actual_length) - { - /* Data sended mismatch with expected, return protocol error */ - fp_err("length mismatch, got %d, expected %d", - transfer->actual_length, transfer->length); - fpi_imgdev_session_error(dev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - goto out; - } - } - else - /* Reset ignore_error flag */ - vdev->ignore_error = FALSE; - - /* Dump buffer for debug */ - dump_buffer(vdev->buffer); - - fpi_ssm_next_state(ssm); - -out: - libusb_free_transfer(transfer); + fpi_ssm_next_state (transfer->ssm); } /* Submit asynchronous send */ static void -async_send(fpi_ssm *ssm, - struct fp_img_dev *dev) +async_send (FpiSsm *ssm, + FpImageDevice *dev) { - struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); - int r; + FpDeviceVfs101 *self = FPI_DEVICE_VFS101 (dev); + FpiUsbTransfer *transfer; - /* Allocation of transfer */ - vdev->transfer = fpi_usb_alloc(); + transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); - /* Put sequential number into the buffer */ - vdev->seqnum++; - vdev->buffer[0] = byte(0, vdev->seqnum); - vdev->buffer[1] = byte(1, vdev->seqnum); + /* Put sequential number into the buffer */ + self->seqnum++; + self->buffer[0] = byte (0, self->seqnum); + self->buffer[1] = byte (1, self->seqnum); - /* Prepare bulk transfer */ - libusb_fill_bulk_transfer(vdev->transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT(1), vdev->buffer, vdev->length, async_send_cb, ssm, BULK_TIMEOUT); - - /* Submit transfer */ - r = libusb_submit_transfer(vdev->transfer); - if (r != 0) - { - /* Submission of transfer failed, return IO error */ - libusb_free_transfer(vdev->transfer); - fp_err("submit of usb transfer failed"); - fpi_imgdev_session_error(dev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - return; - } + /* Prepare bulk transfer */ + fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT (1), + self->buffer, self->length, NULL); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + async_send_cb, NULL); + fpi_usb_transfer_unref (transfer); } /* Callback of asynchronous recv */ -static void async_recv_cb(struct libusb_transfer *transfer) +static void +async_recv_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpDeviceVfs101 *self = FPI_DEVICE_VFS101 (dev); - /* Cleanup transfer */ - vdev->transfer = NULL; + /* Skip error check if ignore_error is set */ + if (!self->ignore_error) + { + if (error) + { + /* Transfer not completed, return IO error */ + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } - /* Skip error check if ignore_error is set */ - if (!vdev->ignore_error) - { - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) - { - /* Transfer not completed, return IO error */ - fp_err("transfer not completed, status = %d", transfer->status); - fpi_imgdev_session_error(dev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - goto out; - } + if (check_seqnum (self)) + { + /* Sequential number received mismatch, return protocol error */ + fp_err ("seqnum mismatch, got %04x, expected %04x", + get_seqnum (self->buffer[1], self->buffer[0]), + self->seqnum); + fpi_ssm_mark_failed (transfer->ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); + return; + } + } - if (check_seqnum(vdev)) - { - /* Sequential number received mismatch, return protocol error */ - fp_err("seqnum mismatch, got %04x, expected %04x", - get_seqnum(vdev->buffer[1], vdev->buffer[0]), vdev->seqnum); - fpi_imgdev_session_error(dev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - goto out; - } - } - else - /* Reset ignore_error flag */ - vdev->ignore_error = FALSE; + g_clear_pointer (&error, g_error_free); - /* Dump buffer for debug */ - dump_buffer(vdev->buffer); + /* Reset ignore_error flag */ + self->ignore_error = FALSE; - /* Set length of received data */ - vdev->length = transfer->actual_length; + /* Dump buffer for debug */ + dump_buffer (self->buffer); - fpi_ssm_next_state(ssm); + /* Set length of received data */ + self->length = transfer->actual_length; -out: - libusb_free_transfer(transfer); + fpi_ssm_next_state (transfer->ssm); } /* Submit asynchronous recv */ static void -async_recv(fpi_ssm *ssm, - struct fp_img_dev *dev) +async_recv (FpiSsm *ssm, + FpImageDevice *dev) { - struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); - int r; + FpDeviceVfs101 *self = FPI_DEVICE_VFS101 (dev); + FpiUsbTransfer *transfer; - /* Allocation of transfer */ - vdev->transfer = fpi_usb_alloc(); + /* Allocation of transfer */ + transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); - /* Prepare bulk transfer */ - libusb_fill_bulk_transfer(vdev->transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN(1), vdev->buffer, 0x0f, async_recv_cb, ssm, BULK_TIMEOUT); - - /* Submit transfer */ - r = libusb_submit_transfer(vdev->transfer); - if (r != 0) - { - /* Submission of transfer failed, free transfer and return IO error */ - libusb_free_transfer(vdev->transfer); - fp_err("submit of usb transfer failed"); - fpi_imgdev_session_error(dev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - return; - } + /* Prepare bulk transfer */ + fpi_usb_transfer_fill_bulk_full (transfer, EP_IN (1), self->buffer, + 0x0f, NULL); + transfer->ssm = ssm; + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + async_recv_cb, NULL); + fpi_usb_transfer_unref (transfer); } -static void async_load(fpi_ssm *ssm, struct fp_img_dev *dev); +static void async_load (FpiSsm *ssm, + FpImageDevice *dev); /* Callback of asynchronous load */ -static void async_load_cb(struct libusb_transfer *transfer) +static void +async_load_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpDeviceVfs101 *self = FPI_DEVICE_VFS101 (dev); - /* Cleanup transfer */ - vdev->transfer = NULL; + /* Skip error check if ignore_error is set */ + if (!self->ignore_error) + { + if (error) + { + /* Transfer not completed */ + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } - /* Skip error check if ignore_error is set */ - if (!vdev->ignore_error) - { - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) - { - /* Transfer not completed */ - fp_err("transfer not completed, status = %d, length = %d", transfer->status, vdev->length); - fpi_imgdev_session_error(dev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - goto out; - } + if (transfer->actual_length % VFS_FRAME_SIZE) + { + /* Received incomplete frame, return protocol error */ + fp_err ("received incomplete frame"); + fpi_ssm_mark_failed (transfer->ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); + return; + } + } - if (transfer->actual_length % VFS_FRAME_SIZE) - { - /* Received incomplete frame, return protocol error */ - fp_err("received incomplete frame"); - fpi_imgdev_session_error(dev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - goto out; - } - } + /* Any error has been ignored. */ + g_clear_pointer (&error, g_error_free); - /* Increase image length */ - vdev->length += transfer->actual_length; + /* Increase image length */ + self->length += transfer->actual_length; - if (transfer->actual_length == VFS_BLOCK_SIZE) - { - if ((VFS_BUFFER_SIZE - vdev->length) < VFS_BLOCK_SIZE) - { - /* Buffer full, image too large, return no memory error */ - fp_err("buffer full, image too large"); - fpi_imgdev_session_error(dev, -ENOMEM); - fpi_ssm_mark_failed(ssm, -ENOMEM); - goto out; - } - else - /* Image load not completed, submit another asynchronous load */ - async_load(ssm, dev); - } - else - { - /* Reset ignore_error flag */ - if (vdev->ignore_error) - vdev->ignore_error = FALSE; + if (transfer->actual_length == VFS_BLOCK_SIZE) + { + if ((VFS_BUFFER_SIZE - self->length) < VFS_BLOCK_SIZE) + { + /* Buffer full, image too large, return no memory error */ + fp_err ("buffer full, image too large"); + fpi_ssm_mark_failed (transfer->ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); + return; + } + else + { + /* Image load not completed, submit another asynchronous load */ + async_load (transfer->ssm, dev); + } + } + else + { + /* Reset ignore_error flag */ + self->ignore_error = FALSE; - /* Image load completed, go to next state */ - vdev->height = vdev->length / VFS_FRAME_SIZE; - fp_dbg("image loaded, height = %d", vdev->height); - fpi_ssm_next_state(ssm); - } - -out: - libusb_free_transfer(transfer); + /* Image load completed, go to next state */ + self->height = self->length / VFS_FRAME_SIZE; + fp_dbg ("image loaded, height = %d", self->height); + fpi_ssm_next_state (transfer->ssm); + } } /* Submit asynchronous load */ static void -async_load(fpi_ssm *ssm, - struct fp_img_dev *dev) +async_load (FpiSsm *ssm, + FpImageDevice *dev) { - struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); - unsigned char *buffer; - int r; + FpDeviceVfs101 *self = FPI_DEVICE_VFS101 (dev); + FpiUsbTransfer *transfer; + unsigned char *buffer; - /* Allocation of transfer */ - vdev->transfer = fpi_usb_alloc(); + /* Allocation of transfer */ + transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); - /* Append new data into the buffer */ - buffer = vdev->buffer + vdev->length; + /* Append new data into the buffer */ + buffer = self->buffer + self->length; - /* Prepare bulk transfer */ - libusb_fill_bulk_transfer(vdev->transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN(2), buffer, VFS_BLOCK_SIZE, async_load_cb, ssm, BULK_TIMEOUT); - - /* Submit transfer */ - r = libusb_submit_transfer(vdev->transfer); - if (r != 0) - { - /* Submission of transfer failed, return IO error */ - libusb_free_transfer(vdev->transfer); - fp_err("submit of usb transfer failed"); - fpi_imgdev_session_error(dev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - return; - } + /* Prepare bulk transfer */ + fpi_usb_transfer_fill_bulk_full (transfer, EP_IN (2), buffer, + VFS_BLOCK_SIZE, NULL); + transfer->ssm = ssm; + fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, + async_load_cb, NULL); + fpi_usb_transfer_unref (transfer); } /* Submit asynchronous sleep */ static void -async_sleep(unsigned int msec, - fpi_ssm *ssm, - struct fp_img_dev *dev) +async_sleep (unsigned int msec, + FpiSsm *ssm, + FpImageDevice *dev) { - if (fpi_timeout_add(msec, fpi_ssm_next_state_timeout_cb, FP_DEV(dev), ssm) == NULL) - { - /* Failed to add timeout */ - fp_err("failed to add timeout"); - fpi_imgdev_session_error(dev, -ETIME); - fpi_ssm_mark_failed(ssm, -ETIME); - } + fpi_device_add_timeout (FP_DEVICE (dev), msec, + fpi_ssm_next_state_timeout_cb, ssm); } /* Swap ssm states */ -enum -{ - M_SWAP_SEND, - M_SWAP_RECV, - M_SWAP_NUM_STATES, +enum { + M_SWAP_SEND, + M_SWAP_RECV, + M_SWAP_NUM_STATES, }; /* Exec swap sequential state machine */ -static void m_swap_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_swap_state (FpiSsm *ssm, FpDevice *dev) { - switch (fpi_ssm_get_cur_state(ssm)) - { - case M_SWAP_SEND: - /* Send data */ - async_send(ssm, user_data); - break; + switch (fpi_ssm_get_cur_state (ssm)) + { + case M_SWAP_SEND: + /* Send data */ + async_send (ssm, FP_IMAGE_DEVICE (dev)); + break; - case M_SWAP_RECV: - /* Recv response */ - async_recv(ssm, user_data); - break; - } + case M_SWAP_RECV: + /* Recv response */ + async_recv (ssm, FP_IMAGE_DEVICE (dev)); + break; + } } /* Start swap sequential state machine */ static void -m_swap(fpi_ssm *ssm, - struct fp_img_dev *dev, - unsigned char *data, - size_t length) +m_swap (FpiSsm *ssm, + FpImageDevice *dev, + unsigned char *data, + size_t length) { - struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_ssm *subsm; + FpDeviceVfs101 *self = FPI_DEVICE_VFS101 (dev); + FpiSsm *subsm; - /* Prepare data for sending */ - memcpy(vdev->buffer, data, length); - memset(vdev->buffer + length, 0, 16 - length); - vdev->length = length; + /* Prepare data for sending */ + memcpy (self->buffer, data, length); + memset (self->buffer + length, 0, 16 - length); + self->length = length; - /* Start swap ssm */ - subsm = fpi_ssm_new(FP_DEV(dev), m_swap_state, M_SWAP_NUM_STATES, dev); - fpi_ssm_start_subsm(ssm, subsm); + /* Start swap ssm */ + subsm = fpi_ssm_new (FP_DEVICE (dev), m_swap_state, M_SWAP_NUM_STATES); + fpi_ssm_start_subsm (ssm, subsm); } /* Retrieve fingerprint image */ static void -vfs_get_print(fpi_ssm *ssm, - struct fp_img_dev *dev, - unsigned int param, - int type) +vfs_get_print (FpiSsm *ssm, + FpImageDevice *dev, + unsigned int param, + int type) { - unsigned char data[2][0x0e] = { - { 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01 }, - { 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01 } - }; + unsigned char data[2][0x0e] = { + { 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01 } + }; - fp_dbg("param = %04x, type = %d", param, type); + fp_dbg ("param = %04x, type = %d", param, type); - /* Prepare data for sending */ - data[type][6] = byte(0, param); - data[type][7] = byte(1, param); + /* Prepare data for sending */ + data[type][6] = byte (0, param); + data[type][7] = byte (1, param); - /* Run swap sequential state machine */ - m_swap(ssm, dev, data[type], 0x0e); + /* Run swap sequential state machine */ + m_swap (ssm, dev, data[type], 0x0e); } /* Set a parameter value on the device */ static void -vfs_set_param(fpi_ssm *ssm, - struct fp_img_dev *dev, - unsigned int param, - unsigned int value) +vfs_set_param (FpiSsm *ssm, + FpImageDevice *dev, + unsigned int param, + unsigned int value) { - unsigned char data[0x0a] = { 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 }; + unsigned char data[0x0a] = { 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 }; - fp_dbg("param = %04x, value = %04x", param, value); + fp_dbg ("param = %04x, value = %04x", param, value); - /* Prepare data for sending */ - data[6] = byte(0, param); - data[7] = byte(1, param); - data[8] = byte(0, value); - data[9] = byte(1, value); + /* Prepare data for sending */ + data[6] = byte (0, param); + data[7] = byte (1, param); + data[8] = byte (0, value); + data[9] = byte (1, value); - /* Run swap sequential state machine */ - m_swap(ssm, dev, data, 0x0a); + /* Run swap sequential state machine */ + m_swap (ssm, dev, data, 0x0a); } /* Abort previous print */ static void -vfs_abort_print(fpi_ssm *ssm, - struct fp_img_dev *dev) +vfs_abort_print (FpiSsm *ssm, + FpImageDevice *dev) { - unsigned char data[0x06] = { 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00 }; + unsigned char data[0x06] = { 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00 }; - G_DEBUG_HERE(); + G_DEBUG_HERE (); - /* Run swap sequential state machine */ - m_swap (ssm, dev, data, 0x06); + /* Run swap sequential state machine */ + m_swap (ssm, dev, data, 0x06); } /* Poke a value on a region */ static void -vfs_poke(fpi_ssm *ssm, - struct fp_img_dev *dev, - unsigned int addr, - unsigned int value, - unsigned int size) +vfs_poke (FpiSsm *ssm, + FpImageDevice *dev, + unsigned int addr, + unsigned int value, + unsigned int size) { - unsigned char data[0x0f] = { 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + unsigned char data[0x0f] = { 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - fp_dbg("addr = %04x, value = %04x", addr, value); + fp_dbg ("addr = %04x, value = %04x", addr, value); - /* Prepare data for sending */ - data[6] = byte(0, addr); - data[7] = byte(1, addr); - data[8] = byte(2, addr); - data[9] = byte(3, addr); - data[10] = byte(0, value); - data[11] = byte(1, value); - data[12] = byte(2, value); - data[13] = byte(3, value); - data[14] = byte(0, size); + /* Prepare data for sending */ + data[6] = byte (0, addr); + data[7] = byte (1, addr); + data[8] = byte (2, addr); + data[9] = byte (3, addr); + data[10] = byte (0, value); + data[11] = byte (1, value); + data[12] = byte (2, value); + data[13] = byte (3, value); + data[14] = byte (0, size); - /* Run swap sequential state machine */ - m_swap(ssm, dev, data, 0x0f); + /* Run swap sequential state machine */ + m_swap (ssm, dev, data, 0x0f); } /* Get current finger state */ static void -vfs_get_finger_state(fpi_ssm *ssm, - struct fp_img_dev *dev) +vfs_get_finger_state (FpiSsm *ssm, + FpImageDevice *dev) { - unsigned char data[0x06] = { 0x00, 0x00, 0x00, 0x00, 0x16, 0x00 }; + unsigned char data[0x06] = { 0x00, 0x00, 0x00, 0x00, 0x16, 0x00 }; - G_DEBUG_HERE(); + G_DEBUG_HERE (); - /* Run swap sequential state machine */ - m_swap (ssm, dev, data, 0x06); + /* Run swap sequential state machine */ + m_swap (ssm, dev, data, 0x06); } /* Load raw image from reader */ static void -vfs_img_load(fpi_ssm *ssm, - struct fp_img_dev *dev) +vfs_img_load (FpiSsm *ssm, + FpImageDevice *dev) { - struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpDeviceVfs101 *self = FPI_DEVICE_VFS101 (dev); - G_DEBUG_HERE(); + G_DEBUG_HERE (); - /* Reset buffer length */ - vdev->length = 0; + /* Reset buffer length */ + self->length = 0; - /* Reset image properties */ - vdev->bottom = 0; - vdev->height = -1; + /* Reset image properties */ + self->bottom = 0; + self->height = -1; - /* Asynchronous load */ - async_load(ssm, dev); + /* Asynchronous load */ + async_load (ssm, dev); } -/* Check if action is completed */ -static int action_completed(struct fp_img_dev *dev) -{ - struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); - - if ((fpi_imgdev_get_action(dev) == IMG_ACTION_ENROLL) && - (vdev->enroll_stage < fp_dev_get_nr_enroll_stages(FP_DEV(dev)))) - /* Enroll not completed, return false */ - return FALSE; - - else if (vdev->enroll_stage < 1) - /* Action not completed, return false */ - return FALSE; - - /* Action completed, return true */ - return TRUE; -} - -#define offset(x, y) ((x) + ((y) * VFS_FRAME_SIZE)) +#define offset(x, y) ((x) + ((y) * VFS_FRAME_SIZE)) /* Screen image to remove noise and find bottom line and height of image */ -static void img_screen(struct vfs101_dev *vdev) +static void +img_screen (FpDeviceVfs101 *vdev) { - int y, x, count, top; - long int level; - int last_line = vdev->height - 1; + int y, x, count, top; + long int level; + int last_line = vdev->height - 1; - fp_dbg("image height before screen = %d", vdev->height); + fp_dbg ("image height before screen = %d", vdev->height); - count = 0; + count = 0; - /* Image returned from sensor can contain many empty lines, - * for remove these lines compare byte 282-283 (scan level information) - * with two different thresholds, one for the begin of finger image and - * one for the end. To increase stability of the code use a counter - * of lines that satisfy the threshold. - */ - for (y = last_line, top = last_line; y >= 0; y--) - { - /* Take image scan level */ - level = vdev->buffer[offset(283, y)] * 256 + - vdev->buffer[offset(282, y)]; + /* Image returned from sensor can contain many empty lines, + * for remove these lines compare byte 282-283 (scan level information) + * with two different thresholds, one for the begin of finger image and + * one for the end. To increase stability of the code use a counter + * of lines that satisfy the threshold. + */ + for (y = last_line, top = last_line; y >= 0; y--) + { + /* Take image scan level */ + level = vdev->buffer[offset (283, y)] * 256 + + vdev->buffer[offset (282, y)]; - fp_dbg("line = %d, scan level = %ld", y, level); + fp_dbg ("line = %d, scan level = %ld", y, level); - if (level >= VFS_IMG_SLT_BEGIN && top == last_line) - { - /* Begin threshold satisfied */ - if (count < VFS_IMG_SLT_LINES) - /* Increase count */ - count++; - else - { - /* Found top fingerprint line */ - top = y + VFS_IMG_SLT_LINES; - count = 0; - } - } - else if ((level < VFS_IMG_SLT_END || level >= 65535) && - top != last_line) - { - /* End threshold satisfied */ - if (count < VFS_IMG_SLT_LINES) - /* Increase count */ - count++; - else - { - /* Found bottom fingerprint line */ - vdev->bottom = y + VFS_IMG_SLT_LINES + 1; - break; - } - } - else - /* Not threshold satisfied, reset count */ - count = 0; - } + if (level >= VFS_IMG_SLT_BEGIN && top == last_line) + { + /* Begin threshold satisfied */ + if (count < VFS_IMG_SLT_LINES) + { + /* Increase count */ + count++; + } + else + { + /* Found top fingerprint line */ + top = y + VFS_IMG_SLT_LINES; + count = 0; + } + } + else if ((level < VFS_IMG_SLT_END || level >= 65535) && + top != last_line) + { + /* End threshold satisfied */ + if (count < VFS_IMG_SLT_LINES) + { + /* Increase count */ + count++; + } + else + { + /* Found bottom fingerprint line */ + vdev->bottom = y + VFS_IMG_SLT_LINES + 1; + break; + } + } + else + { + /* Not threshold satisfied, reset count */ + count = 0; + } + } - vdev->height = top - vdev->bottom + 1; + vdev->height = top - vdev->bottom + 1; - /* Check max height */ - if (vdev->height > VFS_IMG_MAX_HEIGHT) - vdev->height = VFS_IMG_MAX_HEIGHT; + /* Check max height */ + if (vdev->height > VFS_IMG_MAX_HEIGHT) + vdev->height = VFS_IMG_MAX_HEIGHT; - fp_dbg("image height after screen = %d", vdev->height); + fp_dbg ("image height after screen = %d", vdev->height); - /* Scan image and remove noise */ - for (y = vdev->bottom; y <= top; y++) - for (x = 6; x < VFS_IMG_WIDTH + 6; x++) - if (vdev->buffer[offset(x, y)] > VFS_IMG_MIN_IMAGE_LEVEL) - vdev->buffer[offset(x, y)] = 255; + /* Scan image and remove noise */ + for (y = vdev->bottom; y <= top; y++) + for (x = 6; x < VFS_IMG_WIDTH + 6; x++) + if (vdev->buffer[offset (x, y)] > VFS_IMG_MIN_IMAGE_LEVEL) + vdev->buffer[offset (x, y)] = 255; }; /* Copy image from reader buffer and put it into image data */ -static void img_copy(struct vfs101_dev *vdev, struct fp_img *img) +static void +img_copy (FpDeviceVfs101 *self, FpImage *img) { - unsigned int line; - unsigned char *img_buffer = img->data; - unsigned char *vdev_buffer = vdev->buffer + (vdev->bottom * VFS_FRAME_SIZE) + 6; + unsigned int line; + unsigned char *img_buffer = img->data; + unsigned char *vdev_buffer = self->buffer + (self->bottom * VFS_FRAME_SIZE) + 6; - for (line = 0; line < img->height; line++) - { - /* Copy image line from reader buffer to image data */ - memcpy(img_buffer, vdev_buffer, VFS_IMG_WIDTH); + for (line = 0; line < img->height; line++) + { + /* Copy image line from reader buffer to image data */ + memcpy (img_buffer, vdev_buffer, VFS_IMG_WIDTH); - /* Next line of reader buffer */ - vdev_buffer = vdev_buffer + VFS_FRAME_SIZE; + /* Next line of reader buffer */ + vdev_buffer = vdev_buffer + VFS_FRAME_SIZE; - /* Next line of image buffer */ - img_buffer = img_buffer + VFS_IMG_WIDTH; - } + /* Next line of image buffer */ + img_buffer = img_buffer + VFS_IMG_WIDTH; + } } /* Extract fingerpint image from raw data */ static void -img_extract(fpi_ssm *ssm, - struct fp_img_dev *dev) +img_extract (FpiSsm *ssm, + FpImageDevice *dev) { - struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); - struct fp_img *img; + FpDeviceVfs101 *self = FPI_DEVICE_VFS101 (dev); + FpImage *img; - /* Screen image to remove noise and find top and bottom line */ - img_screen(vdev); + /* Screen image to remove noise and find top and bottom line */ + img_screen (self); - /* Check image height */ - if (vdev->height < VFS_IMG_MIN_HEIGHT) - { - /* Image too short */ - vdev->height = 0; - return; - } + /* Check image height */ + if (self->height < VFS_IMG_MIN_HEIGHT) + { + /* Image too short */ + self->height = 0; + fpi_image_device_retry_scan (dev, FP_DEVICE_RETRY_TOO_SHORT); + return; + } - /* Fingerprint is present, load image from reader */ - fpi_imgdev_report_finger_status(dev, TRUE); + /* Create new image */ + img = fp_image_new (self->height, VFS_IMG_WIDTH); + img->width = VFS_IMG_WIDTH; + img->height = self->height; + img->flags = FPI_IMAGE_V_FLIPPED; - /* Create new image */ - img = fpi_img_new(vdev->height * VFS_IMG_WIDTH); - img->width = VFS_IMG_WIDTH; - img->height = vdev->height; - img->flags = FP_IMG_V_FLIPPED; + /* Copy data into image */ + img_copy (self, img); - /* Copy data into image */ - img_copy(vdev, img); - - /* Notify image captured */ - fpi_imgdev_image_captured(dev, img); - - /* FIXME - * What is this for? The action result, and the enroll stages should - * already be handled in fpi_imgdev_image_captured() - */ - - /* Check captured result */ - if (fpi_imgdev_get_action_result(dev) >= 0 && - fpi_imgdev_get_action_result(dev) != FP_ENROLL_RETRY && - fpi_imgdev_get_action_result(dev) != FP_VERIFY_RETRY) - { - /* Image captured, increase enroll stage */ - vdev->enroll_stage++; - - /* Check if action is completed */ - if (!action_completed(dev)) - fpi_imgdev_set_action_result(dev, FP_ENROLL_PASS); - } - else - { - /* Image capture failed */ - if (fpi_imgdev_get_action(dev) == IMG_ACTION_ENROLL) - /* Return retry */ - fpi_imgdev_set_action_result(dev, result_code(dev, RESULT_RETRY)); - else - { - /* Return no match */ - vdev->enroll_stage++; - fpi_imgdev_set_action_result(dev, FP_VERIFY_NO_MATCH); - } - } - - /* Fingerprint is removed from reader */ - fpi_imgdev_report_finger_status(dev, FALSE); + /* Notify image captured */ + fpi_image_device_image_captured (dev, img); }; /* Finger states */ -enum -{ - VFS_FINGER_EMPTY, - VFS_FINGER_PRESENT, - VFS_FINGER_UNKNOWN, +enum { + VFS_FINGER_EMPTY, + VFS_FINGER_PRESENT, + VFS_FINGER_UNKNOWN, }; /* Return finger state */ -static inline int vfs_finger_state(struct vfs101_dev *vdev) +static inline int +vfs_finger_state (FpDeviceVfs101 *vdev) { - /* Check finger state */ - switch (vdev->buffer[0x0a]) - { - case 0x00: - case 0x01: - /* Finger is empty */ - return VFS_FINGER_EMPTY; - break; + /* Check finger state */ + switch (vdev->buffer[0x0a]) + { + case 0x00: + case 0x01: + /* Finger is empty */ + return VFS_FINGER_EMPTY; + break; - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - /* Finger is present */ - return VFS_FINGER_PRESENT; - break; + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + /* Finger is present */ + return VFS_FINGER_PRESENT; + break; - default: - return VFS_FINGER_UNKNOWN; - } + default: + return VFS_FINGER_UNKNOWN; + } }; /* Check contrast of image */ -static void vfs_check_contrast(struct vfs101_dev *vdev) +static void +vfs_check_contrast (FpDeviceVfs101 *vdev) { - int y; - long int count = 0; + int y; + long int count = 0; - /* Check difference from byte 4 to byte 5 for verify contrast of image */ - for (y = 0; y < vdev->height; y++) - count = count + vdev->buffer[offset(5, y)] - vdev->buffer[offset(4, y)]; - count = count / vdev->height; + /* Check difference from byte 4 to byte 5 for verify contrast of image */ + for (y = 0; y < vdev->height; y++) + count = count + vdev->buffer[offset (5, y)] - vdev->buffer[offset (4, y)]; + count = count / vdev->height; - if (count < 16) - { - /* Contrast not valid, retry */ - vdev->contrast++; - return; - } + if (count < 16) + { + /* Contrast not valid, retry */ + vdev->contrast++; + return; + } - fp_dbg("contrast = %d, level = %ld", vdev->contrast, count); + fp_dbg ("contrast = %d, level = %ld", vdev->contrast, count); - if (labs(count - VFS_IMG_BEST_CONTRAST) < abs(vdev->best_clevel - VFS_IMG_BEST_CONTRAST)) - { - /* Better contrast found, use it */ - vdev->best_contrast = vdev->contrast; - vdev->best_clevel = count; - } + if (labs (count - VFS_IMG_BEST_CONTRAST) < abs (vdev->best_clevel - VFS_IMG_BEST_CONTRAST)) + { + /* Better contrast found, use it */ + vdev->best_contrast = vdev->contrast; + vdev->best_clevel = count; + } } /* Loop ssm states */ -enum -{ - /* Step 0 - Scan finger */ - M_LOOP_0_GET_PRINT, - M_LOOP_0_SLEEP, - M_LOOP_0_GET_STATE, - M_LOOP_0_LOAD_IMAGE, - M_LOOP_0_EXTRACT_IMAGE, - M_LOOP_0_CHECK_ACTION, +enum { + /* Step 0 - Scan finger */ + M_LOOP_0_GET_PRINT, + M_LOOP_0_SLEEP, + M_LOOP_0_GET_STATE, + M_LOOP_0_LOAD_IMAGE, + M_LOOP_0_EXTRACT_IMAGE, + M_LOOP_0_CHECK_ACTION, - /* Step 1 - Scan failed */ - M_LOOP_1_GET_STATE, - M_LOOP_1_CHECK_STATE, - M_LOOP_1_GET_PRINT, - M_LOOP_1_LOAD_IMAGE, - M_LOOP_1_LOOP, - M_LOOP_1_SLEEP, + /* Step 1 - Scan failed */ + M_LOOP_1_GET_STATE, + M_LOOP_1_CHECK_STATE, + M_LOOP_1_GET_PRINT, + M_LOOP_1_LOAD_IMAGE, + M_LOOP_1_LOOP, + M_LOOP_1_SLEEP, - /* Step 2 - Abort print */ - M_LOOP_2_ABORT_PRINT, - M_LOOP_2_LOAD_IMAGE, + /* Step 2 - Abort print */ + M_LOOP_2_ABORT_PRINT, + M_LOOP_2_LOAD_IMAGE, - /* Step 3 - Wait aborting */ - M_LOOP_3_GET_PRINT, - M_LOOP_3_LOAD_IMAGE, - M_LOOP_3_CHECK_IMAGE, - M_LOOP_3_LOOP, + /* Step 3 - Wait aborting */ + M_LOOP_3_GET_PRINT, + M_LOOP_3_LOAD_IMAGE, + M_LOOP_3_CHECK_IMAGE, + M_LOOP_3_LOOP, - /* Number of states */ - M_LOOP_NUM_STATES, + /* Number of states */ + M_LOOP_NUM_STATES, }; /* Exec loop sequential state machine */ -static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_loop_state (FpiSsm *ssm, FpDevice *_dev) { - struct fp_img_dev *dev = user_data; - struct vfs101_dev *vdev = FP_INSTANCE_DATA(_dev); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpDeviceVfs101 *self = FPI_DEVICE_VFS101 (_dev); - /* Check action state */ - if (!vdev->active) - { - /* Action not active, mark sequential state machine completed */ - fpi_ssm_mark_completed(ssm); - return; - } + /* Complete if deactivation was requested */ + if (self->deactivate) + { + fpi_ssm_mark_completed (ssm); + return; + } - switch (fpi_ssm_get_cur_state(ssm)) - { - case M_LOOP_0_GET_PRINT: - /* Send get print command to the reader */ - vfs_get_print(ssm, dev, VFS_BUFFER_HEIGHT, 1); - break; + switch (fpi_ssm_get_cur_state (ssm)) + { + case M_LOOP_0_GET_PRINT: + /* Send get print command to the reader */ + vfs_get_print (ssm, dev, VFS_BUFFER_HEIGHT, 1); + break; - case M_LOOP_0_SLEEP: - /* Wait fingerprint scanning */ - async_sleep(50, ssm, dev); - break; + case M_LOOP_0_SLEEP: + /* Wait fingerprint scanning */ + async_sleep (50, ssm, dev); + break; - case M_LOOP_0_GET_STATE: - /* Get finger state */ - vfs_get_finger_state(ssm, dev); - break; + case M_LOOP_0_GET_STATE: + /* Get finger state */ + vfs_get_finger_state (ssm, dev); + break; - case M_LOOP_0_LOAD_IMAGE: - /* Check finger state */ - switch (vfs_finger_state(vdev)) - { - case VFS_FINGER_EMPTY: - /* Finger isn't present, loop */ - fpi_ssm_jump_to_state(ssm, M_LOOP_0_SLEEP); - break; + case M_LOOP_0_LOAD_IMAGE: + /* Check finger state */ + switch (vfs_finger_state (self)) + { + case VFS_FINGER_EMPTY: + fpi_image_device_report_finger_status (dev, FALSE); - case VFS_FINGER_PRESENT: - /* Load image from reader */ - vdev->ignore_error = TRUE; - vfs_img_load(ssm, dev); - break; + /* Finger isn't present, loop */ + fpi_ssm_jump_to_state (ssm, M_LOOP_0_SLEEP); + break; - default: - /* Unknown state */ - fp_err("unknown device state 0x%02x", vdev->buffer[0x0a]); - fpi_imgdev_session_error(dev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - break; - } - break; + case VFS_FINGER_PRESENT: + fpi_image_device_report_finger_status (dev, TRUE); - case M_LOOP_0_EXTRACT_IMAGE: - /* Check if image is loaded */ - if (vdev->height > 0) - /* Fingerprint is loaded, extract image from raw data */ - img_extract(ssm, dev); + /* Load image from reader */ + self->ignore_error = TRUE; + vfs_img_load (ssm, dev); + break; - /* Wait handling image */ - async_sleep(10, ssm, dev); - break; + default: + fpi_image_device_report_finger_status (dev, FALSE); - case M_LOOP_0_CHECK_ACTION: - /* Check if action is completed */ - if (action_completed(dev)) - /* Action completed */ - fpi_ssm_mark_completed(ssm); - else - /* Action not completed */ - if (vdev->height > 0) - /* Continue loop */ - fpi_ssm_jump_to_state(ssm, M_LOOP_2_ABORT_PRINT); - else - /* Error found */ - fpi_ssm_next_state(ssm); - break; + /* Unknown state */ + fp_err ("unknown device state 0x%02x", + self->buffer[0x0a]); + fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); + break; + } + break; - case M_LOOP_1_GET_STATE: - /* Get finger state */ - vfs_get_finger_state(ssm, dev); - break; + case M_LOOP_0_EXTRACT_IMAGE: + /* Fingerprint is loaded, extract image from raw data */ + img_extract (ssm, dev); - case M_LOOP_1_CHECK_STATE: - /* Check finger state */ - if (vfs_finger_state(vdev) == VFS_FINGER_PRESENT) - { - if (vdev->counter < 20) - { - if (vdev->counter == 1) - { - /* The user should remove their finger from the scanner */ - fp_warn("finger present after scan, remove it"); - fpi_imgdev_session_error(dev, result_code(dev, RESULT_RETRY_REMOVE)); - } + /* Wait handling image */ + async_sleep (10, ssm, dev); + break; - /* Wait removing finger */ - vdev->counter++; - async_sleep(250, ssm, dev); - } - else - { - /* reach max loop counter, return protocol error */ - fp_err("finger not removed from the scanner"); - fpi_imgdev_session_error(dev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - } - } - else - { - /* Finger not present */ - if (vdev->counter == 0) - { - /* Check image height */ - if (vdev->height == 0) - { - /* Return retry to short */ - fp_warn("image too short, retry"); - fpi_imgdev_session_error(dev, result_code(dev, RESULT_RETRY_SHORT)); - } - else - { - /* Return retry result */ - fp_warn("load image failed, retry"); - fpi_imgdev_session_error(dev, result_code(dev, RESULT_RETRY)); - } - } + case M_LOOP_0_CHECK_ACTION: + /* Action not completed */ + if (self->height > 0) + /* Continue loop */ + fpi_ssm_jump_to_state (ssm, M_LOOP_2_ABORT_PRINT); + else + /* Error found */ + fpi_ssm_next_state (ssm); + break; - /* Continue */ - vdev->counter = 0; - fpi_ssm_jump_to_state(ssm, M_LOOP_1_SLEEP); - } - break; + case M_LOOP_1_GET_STATE: + /* Get finger state */ + vfs_get_finger_state (ssm, dev); + break; - case M_LOOP_1_GET_PRINT: - /* Send get print command to the reader */ - vfs_get_print(ssm, dev, VFS_BUFFER_HEIGHT, 1); - break; + case M_LOOP_1_CHECK_STATE: + /* Check finger state */ + if (vfs_finger_state (self) == VFS_FINGER_PRESENT) + { + fpi_image_device_report_finger_status (dev, TRUE); + async_sleep (250, ssm, dev); + } + else + { + /* Finger not present */ + fpi_image_device_report_finger_status (dev, FALSE); - case M_LOOP_1_LOAD_IMAGE: - /* Load image */ - vdev->ignore_error = TRUE; - vfs_img_load(ssm, dev); - break; + /* Continue */ + fpi_ssm_jump_to_state (ssm, M_LOOP_1_SLEEP); + } + break; - case M_LOOP_1_LOOP: - /* Loop */ - fpi_ssm_jump_to_state(ssm, M_LOOP_1_GET_STATE); - break; + case M_LOOP_1_GET_PRINT: + /* Send get print command to the reader */ + vfs_get_print (ssm, dev, VFS_BUFFER_HEIGHT, 1); + break; - case M_LOOP_1_SLEEP: - /* Wait fingerprint scanning */ - async_sleep(10, ssm, dev); - break; + case M_LOOP_1_LOAD_IMAGE: + /* Load image */ + self->ignore_error = TRUE; + vfs_img_load (ssm, dev); + break; - case M_LOOP_2_ABORT_PRINT: - /* Abort print command */ - vfs_abort_print(ssm, dev); - break; + case M_LOOP_1_LOOP: + /* Loop */ + fpi_ssm_jump_to_state (ssm, M_LOOP_1_GET_STATE); + break; - case M_LOOP_2_LOAD_IMAGE: - /* Load abort image */ - vdev->ignore_error = TRUE; - vfs_img_load(ssm, dev); - break; + case M_LOOP_1_SLEEP: + /* Wait fingerprint scanning */ + async_sleep (10, ssm, dev); + break; - case M_LOOP_3_GET_PRINT: - /* Get empty image */ - vfs_get_print(ssm, dev, 0x000a, 0); - break; + case M_LOOP_2_ABORT_PRINT: + /* Abort print command */ + vfs_abort_print (ssm, dev); + break; - case M_LOOP_3_LOAD_IMAGE: - /* Load abort image */ - vdev->ignore_error = TRUE; - vfs_img_load(ssm, dev); - break; + case M_LOOP_2_LOAD_IMAGE: + /* Load abort image */ + self->ignore_error = TRUE; + vfs_img_load (ssm, dev); + break; - case M_LOOP_3_CHECK_IMAGE: - if (vdev->height == 10) - { - /* Image load correctly, jump to step 0 */ - vdev->counter = 0; - fpi_ssm_jump_to_state(ssm, M_LOOP_0_GET_PRINT); - } - else if (vdev->counter < 10) - { - /* Wait aborting */ - vdev->counter++; - async_sleep(100, ssm, dev); - } - else - { - /* reach max loop counter, return protocol error */ - fp_err("waiting abort reach max loop counter"); - fpi_imgdev_session_error(dev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - } - break; + case M_LOOP_3_GET_PRINT: + /* Get empty image */ + vfs_get_print (ssm, dev, 0x000a, 0); + break; - case M_LOOP_3_LOOP: - /* Loop */ - fpi_ssm_jump_to_state(ssm, M_LOOP_3_GET_PRINT); - break; - } + case M_LOOP_3_LOAD_IMAGE: + /* Load abort image */ + self->ignore_error = TRUE; + vfs_img_load (ssm, dev); + break; + + case M_LOOP_3_CHECK_IMAGE: + if (self->height == 10) + { + /* Image load correctly, jump to step 0 */ + self->counter = 0; + fpi_ssm_jump_to_state (ssm, M_LOOP_0_GET_PRINT); + } + else if (self->counter < 10) + { + /* Wait aborting */ + self->counter++; + async_sleep (100, ssm, dev); + } + else + { + /* reach max loop counter, return protocol error */ + fp_err ("waiting abort reach max loop counter"); + fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); + } + break; + + case M_LOOP_3_LOOP: + /* Loop */ + fpi_ssm_jump_to_state (ssm, M_LOOP_3_GET_PRINT); + break; + } } /* Complete loop sequential state machine */ -static void m_loop_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_loop_complete (FpiSsm *ssm, FpDevice *dev, GError *error) { - /* Free sequential state machine */ - fpi_ssm_free(ssm); + FpDeviceVfs101 *self = FPI_DEVICE_VFS101 (dev); + + /* When the loop completes, we have (successfully) deactivated */ + if (self->active) + fpi_image_device_deactivate_complete (FP_IMAGE_DEVICE (dev), + error); + + self->active = FALSE; + + fpi_ssm_free (ssm); } /* Init ssm states */ -enum -{ - /* Step 0 - Cleanup device buffer */ - M_INIT_0_RECV_DIRTY, - M_INIT_0_ABORT_PRINT, - M_INIT_0_LOAD_IMAGE, +enum { + /* Step 0 - Cleanup device buffer */ + M_INIT_0_RECV_DIRTY, + M_INIT_0_ABORT_PRINT, + M_INIT_0_LOAD_IMAGE, - /* Step 1 - Wait aborting */ - M_INIT_1_GET_PRINT, - M_INIT_1_LOAD_IMAGE, - M_INIT_1_CHECK_IMAGE, - M_INIT_1_LOOP, + /* Step 1 - Wait aborting */ + M_INIT_1_GET_PRINT, + M_INIT_1_LOAD_IMAGE, + M_INIT_1_CHECK_IMAGE, + M_INIT_1_LOOP, - /* Step 2 - Handle unexpected finger presence */ - M_INIT_2_GET_STATE, - M_INIT_2_CHECK_STATE, - M_INIT_2_GET_PRINT, - M_INIT_2_LOAD_IMAGE, - M_INIT_2_LOOP, + /* Step 2 - Handle unexpected finger presence */ + M_INIT_2_GET_STATE, + M_INIT_2_CHECK_STATE, + M_INIT_2_GET_PRINT, + M_INIT_2_LOAD_IMAGE, + M_INIT_2_LOOP, - /* Step 3 - Set parameters */ - M_INIT_3_SET_000E, - M_INIT_3_SET_0011, - M_INIT_3_SET_0076, - M_INIT_3_SET_0078, - M_INIT_3_SET_THRESHOLD, - M_INIT_3_SET_STATE3_COUNT, - M_INIT_3_SET_STATE5_COUNT, - M_INIT_3_SET_INFO_CONTRAST, - M_INIT_3_SET_INFO_RATE, + /* Step 3 - Set parameters */ + M_INIT_3_SET_000E, + M_INIT_3_SET_0011, + M_INIT_3_SET_0076, + M_INIT_3_SET_0078, + M_INIT_3_SET_THRESHOLD, + M_INIT_3_SET_STATE3_COUNT, + M_INIT_3_SET_STATE5_COUNT, + M_INIT_3_SET_INFO_CONTRAST, + M_INIT_3_SET_INFO_RATE, - /* Step 4 - Autocalibrate contrast */ - M_INIT_4_SET_EXPOSURE, - M_INIT_4_SET_CONTRAST, - M_INIT_4_GET_PRINT, - M_INIT_4_LOAD_IMAGE, - M_INIT_4_CHECK_CONTRAST, + /* Step 4 - Autocalibrate contrast */ + M_INIT_4_SET_EXPOSURE, + M_INIT_4_SET_CONTRAST, + M_INIT_4_GET_PRINT, + M_INIT_4_LOAD_IMAGE, + M_INIT_4_CHECK_CONTRAST, - /* Step 5 - Set info line parameters */ - M_INIT_5_SET_EXPOSURE, - M_INIT_5_SET_CONTRAST, - M_INIT_5_SET_INFO_CONTRAST, - M_INIT_5_SET_INFO_RATE, + /* Step 5 - Set info line parameters */ + M_INIT_5_SET_EXPOSURE, + M_INIT_5_SET_CONTRAST, + M_INIT_5_SET_INFO_CONTRAST, + M_INIT_5_SET_INFO_RATE, - /* Number of states */ - M_INIT_NUM_STATES, + /* Number of states */ + M_INIT_NUM_STATES, }; /* Exec init sequential state machine */ -static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_init_state (FpiSsm *ssm, FpDevice *_dev) { - struct fp_img_dev *dev = user_data; - struct vfs101_dev *vdev = FP_INSTANCE_DATA(_dev); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpDeviceVfs101 *self = FPI_DEVICE_VFS101 (_dev); - /* Check action state */ - if (!vdev->active) - { - /* Action not active, mark sequential state machine completed */ - fpi_ssm_mark_completed(ssm); - return; - } + /* Mark as cancelled when activation collides with deactivation. */ + if (self->deactivate) + { + fpi_ssm_mark_failed (ssm, + g_error_new (G_IO_ERROR, + G_IO_ERROR_CANCELLED, + "Initialisation was cancelled")); + return; + } - switch (fpi_ssm_get_cur_state(ssm)) - { - case M_INIT_0_RECV_DIRTY: - /* Recv eventually dirty data */ - vdev->ignore_error = TRUE; - async_recv(ssm, dev); - break; + switch (fpi_ssm_get_cur_state (ssm)) + { + case M_INIT_0_RECV_DIRTY: + /* Recv eventually dirty data */ + self->ignore_error = TRUE; + async_recv (ssm, dev); + break; - case M_INIT_0_ABORT_PRINT: - /* Abort print command */ - vfs_abort_print(ssm, dev); - break; + case M_INIT_0_ABORT_PRINT: + /* Abort print command */ + vfs_abort_print (ssm, dev); + break; - case M_INIT_0_LOAD_IMAGE: - /* Load abort image */ - vdev->ignore_error = TRUE; - vfs_img_load(ssm, dev); - break; + case M_INIT_0_LOAD_IMAGE: + /* Load abort image */ + self->ignore_error = TRUE; + vfs_img_load (ssm, dev); + break; - case M_INIT_1_GET_PRINT: - /* Get empty image */ - vfs_get_print(ssm, dev, 0x000a, 0); - break; + case M_INIT_1_GET_PRINT: + /* Get empty image */ + vfs_get_print (ssm, dev, 0x000a, 0); + break; - case M_INIT_1_LOAD_IMAGE: - /* Load abort image */ - vdev->ignore_error = TRUE; - vfs_img_load(ssm, dev); - break; + case M_INIT_1_LOAD_IMAGE: + /* Load abort image */ + self->ignore_error = TRUE; + vfs_img_load (ssm, dev); + break; - case M_INIT_1_CHECK_IMAGE: - if (vdev->height == 10) - { - /* Image load correctly, jump to step 2 */ - vdev->counter = 0; - fpi_ssm_jump_to_state(ssm, M_INIT_2_GET_STATE); - } - else if (vdev->counter < 10) - { - /* Wait aborting */ - vdev->counter++; - async_sleep(100, ssm, dev); - } - else - { - /* reach max loop counter, return protocol error */ - fp_err("waiting abort reach max loop counter"); - fpi_imgdev_session_error(dev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - } - break; + case M_INIT_1_CHECK_IMAGE: + if (self->height == 10) + { + /* Image load correctly, jump to step 2 */ + self->counter = 0; + fpi_ssm_jump_to_state (ssm, M_INIT_2_GET_STATE); + } + else if (self->counter < 10) + { + /* Wait aborting */ + self->counter++; + async_sleep (100, ssm, dev); + } + else + { + /* reach max loop counter, return protocol error */ + fp_err ("waiting abort reach max loop counter"); + fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); + } + break; - case M_INIT_1_LOOP: - /* Loop */ - fpi_ssm_jump_to_state(ssm, M_INIT_1_GET_PRINT); - break; + case M_INIT_1_LOOP: + /* Loop */ + fpi_ssm_jump_to_state (ssm, M_INIT_1_GET_PRINT); + break; - case M_INIT_2_GET_STATE: - /* Get finger state */ - vfs_get_finger_state(ssm, dev); - break; + case M_INIT_2_GET_STATE: + /* Get finger state */ + vfs_get_finger_state (ssm, dev); + break; - case M_INIT_2_CHECK_STATE: - /* Check finger state */ - if (vfs_finger_state(vdev) == VFS_FINGER_PRESENT) - { - if (vdev->counter < 20) - { - if (vdev->counter == 2) - { - /* The user should remove their finger from the scanner */ - fp_warn("unexpected finger find, remove finger from the scanner"); - fpi_imgdev_session_error(dev, result_code(dev, RESULT_RETRY_REMOVE)); - } + case M_INIT_2_CHECK_STATE: + /* Check finger state */ + if (vfs_finger_state (self) == VFS_FINGER_PRESENT) + { + /* Wait a bit for finger removal; if it doesn't happen, prompt */ + if (self->counter < 2) + { + /* Wait removing finger */ + self->counter++; + async_sleep (250, ssm, dev); + } + else + { + /* The user should remove their finger from the scanner */ + fp_warn ("unexpected finger find, remove finger from the scanner"); + fpi_ssm_mark_failed (ssm, fpi_device_retry_new (FP_DEVICE_RETRY_REMOVE_FINGER)); + } + } + else + { + /* Finger not present */ + if (self->counter == 0) + { + /* Continue */ + fpi_ssm_jump_to_state (ssm, M_INIT_3_SET_000E); + } + else + { + /* Finger removed, jump to abort */ + self->counter = 0; + fpi_ssm_jump_to_state (ssm, M_INIT_0_ABORT_PRINT); + } + } + break; - /* Wait removing finger */ - vdev->counter++; - async_sleep(250, ssm, dev); - } - else - { - /* reach max loop counter, return protocol error */ - fp_err("finger not removed from the scanner"); - fpi_imgdev_session_error(dev, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - } - } - else - { - /* Finger not present */ - if (vdev->counter == 0) - /* Continue */ - fpi_ssm_jump_to_state(ssm, M_INIT_3_SET_000E); - else - { - /* Finger removed, jump to abort */ - vdev->counter = 0; - fpi_ssm_jump_to_state(ssm, M_INIT_0_ABORT_PRINT); - } - } - break; + case M_INIT_2_GET_PRINT: + /* Send get print command to the reader */ + vfs_get_print (ssm, dev, VFS_BUFFER_HEIGHT, 1); + break; - case M_INIT_2_GET_PRINT: - /* Send get print command to the reader */ - vfs_get_print(ssm, dev, VFS_BUFFER_HEIGHT, 1); - break; + case M_INIT_2_LOAD_IMAGE: + /* Load unexpected image */ + self->ignore_error = TRUE; + vfs_img_load (ssm, dev); + break; - case M_INIT_2_LOAD_IMAGE: - /* Load unexpected image */ - vdev->ignore_error = TRUE; - vfs_img_load(ssm, dev); - break; + case M_INIT_2_LOOP: + /* Loop */ + fpi_ssm_jump_to_state (ssm, M_INIT_2_GET_STATE); + break; - case M_INIT_2_LOOP: - /* Loop */ - fpi_ssm_jump_to_state(ssm, M_INIT_2_GET_STATE); - break; + case M_INIT_3_SET_000E: + /* Set param 0x000e, required for take image */ + vfs_set_param (ssm, dev, VFS_PAR_000E, VFS_VAL_000E); + break; - case M_INIT_3_SET_000E: - /* Set param 0x000e, required for take image */ - vfs_set_param(ssm, dev, VFS_PAR_000E, VFS_VAL_000E); - break; + case M_INIT_3_SET_0011: + /* Set param 0x0011, required for take image */ + vfs_set_param (ssm, dev, VFS_PAR_0011, VFS_VAL_0011); + break; - case M_INIT_3_SET_0011: - /* Set param 0x0011, required for take image */ - vfs_set_param(ssm, dev, VFS_PAR_0011, VFS_VAL_0011); - break; + case M_INIT_3_SET_0076: + /* Set param 0x0076, required for use info line */ + vfs_set_param (ssm, dev, VFS_PAR_0076, VFS_VAL_0076); + break; - case M_INIT_3_SET_0076: - /* Set param 0x0076, required for use info line */ - vfs_set_param(ssm, dev, VFS_PAR_0076, VFS_VAL_0076); - break; + case M_INIT_3_SET_0078: + /* Set param 0x0078, required for use info line */ + vfs_set_param (ssm, dev, VFS_PAR_0078, VFS_VAL_0078); + break; - case M_INIT_3_SET_0078: - /* Set param 0x0078, required for use info line */ - vfs_set_param(ssm, dev, VFS_PAR_0078, VFS_VAL_0078); - break; + case M_INIT_3_SET_THRESHOLD: + /* Set threshold */ + vfs_set_param (ssm, dev, VFS_PAR_THRESHOLD, VFS_VAL_THRESHOLD); + break; - case M_INIT_3_SET_THRESHOLD: - /* Set threshold */ - vfs_set_param(ssm, dev, VFS_PAR_THRESHOLD, VFS_VAL_THRESHOLD); - break; + case M_INIT_3_SET_STATE3_COUNT: + /* Set state 3 count */ + vfs_set_param (ssm, dev, VFS_PAR_STATE_3, VFS_VAL_STATE_3); + break; - case M_INIT_3_SET_STATE3_COUNT: - /* Set state 3 count */ - vfs_set_param(ssm, dev, VFS_PAR_STATE_3, VFS_VAL_STATE_3); - break; + case M_INIT_3_SET_STATE5_COUNT: + /* Set state 5 count */ + vfs_set_param (ssm, dev, VFS_PAR_STATE_5, VFS_VAL_STATE_5); + break; - case M_INIT_3_SET_STATE5_COUNT: - /* Set state 5 count */ - vfs_set_param(ssm, dev, VFS_PAR_STATE_5, VFS_VAL_STATE_5); - break; + case M_INIT_3_SET_INFO_CONTRAST: + /* Set info line contrast */ + vfs_set_param (ssm, dev, VFS_PAR_INFO_CONTRAST, 10); + break; - case M_INIT_3_SET_INFO_CONTRAST: - /* Set info line contrast */ - vfs_set_param(ssm, dev, VFS_PAR_INFO_CONTRAST, 10); - break; + case M_INIT_3_SET_INFO_RATE: + /* Set info line rate */ + vfs_set_param (ssm, dev, VFS_PAR_INFO_RATE, 32); + break; - case M_INIT_3_SET_INFO_RATE: - /* Set info line rate */ - vfs_set_param(ssm, dev, VFS_PAR_INFO_RATE, 32); - break; + case M_INIT_4_SET_EXPOSURE: + /* Set exposure level of reader */ + vfs_poke (ssm, dev, VFS_REG_IMG_EXPOSURE, 0x4000, 0x02); + self->counter = 1; + break; - case M_INIT_4_SET_EXPOSURE: - /* Set exposure level of reader */ - vfs_poke(ssm, dev, VFS_REG_IMG_EXPOSURE, 0x4000, 0x02); - vdev->counter = 1; - break; + case M_INIT_4_SET_CONTRAST: + /* Set contrast level of reader */ + vfs_poke (ssm, dev, VFS_REG_IMG_CONTRAST, self->contrast, 0x01); + break; - case M_INIT_4_SET_CONTRAST: - /* Set contrast level of reader */ - vfs_poke(ssm, dev, VFS_REG_IMG_CONTRAST, vdev->contrast, 0x01); - break; + case M_INIT_4_GET_PRINT: + /* Get empty image */ + vfs_get_print (ssm, dev, 0x000a, 0); + break; - case M_INIT_4_GET_PRINT: - /* Get empty image */ - vfs_get_print(ssm, dev, 0x000a, 0); - break; + case M_INIT_4_LOAD_IMAGE: + /* Load empty image */ + vfs_img_load (ssm, dev); + break; - case M_INIT_4_LOAD_IMAGE: - /* Load empty image */ - vfs_img_load(ssm, dev); - break; + case M_INIT_4_CHECK_CONTRAST: + /* Check contrast */ + vfs_check_contrast (self); - case M_INIT_4_CHECK_CONTRAST: - /* Check contrast */ - vfs_check_contrast(vdev); + if (self->contrast <= 6 || self->counter >= 12) + { + /* End contrast scan, continue */ + self->contrast = self->best_contrast; + self->counter = 0; + fp_dbg ("use contrast value = %d", self->contrast); + fpi_ssm_next_state (ssm); + } + else + { + /* Continue contrast scan, loop */ + self->contrast--; + self->counter++; + fpi_ssm_jump_to_state (ssm, M_INIT_4_SET_CONTRAST); + } + break; - if (vdev->contrast <= 6 || vdev->counter >= 12) - { - /* End contrast scan, continue */ - vdev->contrast = vdev->best_contrast; - vdev->counter = 0; - fp_dbg("use contrast value = %d", vdev->contrast); - fpi_ssm_next_state(ssm); - } - else - { - /* Continue contrast scan, loop */ - vdev->contrast--; - vdev->counter++; - fpi_ssm_jump_to_state(ssm, M_INIT_4_SET_CONTRAST); - } - break; + case M_INIT_5_SET_EXPOSURE: + /* Set exposure level of reader */ + vfs_poke (ssm, dev, VFS_REG_IMG_EXPOSURE, VFS_VAL_IMG_EXPOSURE, 0x02); + break; - case M_INIT_5_SET_EXPOSURE: - /* Set exposure level of reader */ - vfs_poke(ssm, dev, VFS_REG_IMG_EXPOSURE, VFS_VAL_IMG_EXPOSURE, 0x02); - break; + case M_INIT_5_SET_CONTRAST: + /* Set contrast level of reader */ + vfs_poke (ssm, dev, VFS_REG_IMG_CONTRAST, self->contrast, 0x01); + break; - case M_INIT_5_SET_CONTRAST: - /* Set contrast level of reader */ - vfs_poke(ssm, dev, VFS_REG_IMG_CONTRAST, vdev->contrast, 0x01); - break; + case M_INIT_5_SET_INFO_CONTRAST: + /* Set info line contrast */ + vfs_set_param (ssm, dev, VFS_PAR_INFO_CONTRAST, self->contrast); + break; - case M_INIT_5_SET_INFO_CONTRAST: - /* Set info line contrast */ - vfs_set_param(ssm, dev, VFS_PAR_INFO_CONTRAST, vdev->contrast); - break; - - case M_INIT_5_SET_INFO_RATE: - /* Set info line rate */ - vfs_set_param(ssm, dev, VFS_PAR_INFO_RATE, VFS_VAL_INFO_RATE); - break; - } + case M_INIT_5_SET_INFO_RATE: + /* Set info line rate */ + vfs_set_param (ssm, dev, VFS_PAR_INFO_RATE, VFS_VAL_INFO_RATE); + break; + } } /* Complete init sequential state machine */ -static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_init_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { - struct fp_img_dev *dev = user_data; - struct vfs101_dev *vdev = FP_INSTANCE_DATA(_dev); - fpi_ssm *ssm_loop; + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); - if (!fpi_ssm_get_error(ssm) && vdev->active) - { - /* Notify activate complete */ - fpi_imgdev_activate_complete(dev, 0); + /* Notify activate complete */ + fpi_image_device_activate_complete (dev, error); - /* Start loop ssm */ - ssm_loop = fpi_ssm_new(FP_DEV(dev), m_loop_state, M_LOOP_NUM_STATES, dev); - fpi_ssm_start(ssm_loop, m_loop_complete); - } + if (!error) + { + FpiSsm *ssm_loop; - /* Free sequential state machine */ - fpi_ssm_free(ssm); + /* Start loop ssm */ + ssm_loop = fpi_ssm_new (FP_DEVICE (dev), m_loop_state, M_LOOP_NUM_STATES); + fpi_ssm_start (ssm_loop, m_loop_complete); + } + + /* Free sequential state machine */ + fpi_ssm_free (ssm); } /* Activate device */ -static int dev_activate(struct fp_img_dev *dev) +static void +dev_activate (FpImageDevice *dev) { - struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_ssm *ssm; + FpDeviceVfs101 *self = FPI_DEVICE_VFS101 (dev); + FpiSsm *ssm; - /* Check if already active */ - if (vdev->active) - { - fp_err("device already activated"); - fpi_imgdev_session_error(dev, -EBUSY); - return 1; - } + /* Check if already active */ + g_assert (!self->active); - /* Set active state */ - vdev->active = TRUE; + /* Set active state */ + self->active = TRUE; + self->deactivate = FALSE; - /* Set contrast */ - vdev->contrast = 15; - vdev->best_clevel = -1; + /* Set contrast */ + self->contrast = 15; + self->best_clevel = -1; - /* Reset loop counter and enroll stage */ - vdev->counter = 0; - vdev->enroll_stage = 0; + /* Reset loop counter */ + self->counter = 0; - /* Start init ssm */ - ssm = fpi_ssm_new(FP_DEV(dev), m_init_state, M_INIT_NUM_STATES, dev); - fpi_ssm_start(ssm, m_init_complete); - - return 0; + /* Start init ssm */ + ssm = fpi_ssm_new (FP_DEVICE (dev), m_init_state, M_INIT_NUM_STATES); + fpi_ssm_start (ssm, m_init_complete); } /* Deactivate device */ -static void dev_deactivate(struct fp_img_dev *dev) +static void +dev_deactivate (FpImageDevice *dev) { - struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpDeviceVfs101 *self = FPI_DEVICE_VFS101 (dev); - /* Reset active state */ - vdev->active = FALSE; + /* Device already deactivated, likely due to an error */ + if (!self->active) + { + fpi_image_device_deactivate_complete (dev, NULL); + return; + } - /* Handle eventually existing events */ - while (vdev->transfer) - fp_handle_events(); - - /* Notify deactivate complete */ - fpi_imgdev_deactivate_complete(dev); + /* Signal deactivation, deactivation will happen from the SSM + * completion handler. */ + self->deactivate = TRUE; } /* Open device */ -static int dev_open(struct fp_img_dev *dev, unsigned long driver_data) +static void +dev_open (FpImageDevice *dev) { - struct vfs101_dev *vdev = NULL; - int r; + FpDeviceVfs101 *self = FPI_DEVICE_VFS101 (dev); + GError *error = NULL; - /* Claim usb interface */ - r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - if (r < 0) - { - /* Interface not claimed, return error */ - fp_err("could not claim interface 0: %s", libusb_error_name(r)); - return r; - } + /* Claim usb interface */ + g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error); - /* Initialize private structure */ - vdev = g_malloc0(sizeof(struct vfs101_dev)); - vdev->seqnum = -1; - fp_dev_set_instance_data(FP_DEV(dev), vdev); + /* Initialize private structure */ + self->seqnum = -1; + self->buffer = g_malloc0 (VFS_BUFFER_SIZE); - /* Notify open complete */ - fpi_imgdev_open_complete(dev, 0); - - return 0; + /* Notify open complete */ + fpi_image_device_open_complete (dev, error); } /* Close device */ -static void dev_close(struct fp_img_dev *dev) +static void +dev_close (FpImageDevice *dev) { - struct vfs101_dev *vdev; + FpDeviceVfs101 *self = FPI_DEVICE_VFS101 (dev); + GError *error = NULL; - /* Release private structure */ - vdev = FP_INSTANCE_DATA(FP_DEV(dev)); - g_free(vdev); + /* Release usb interface */ + g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), + 0, 0, &error); - /* Release usb interface */ - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); + g_clear_pointer (&self->buffer, g_free); - /* Notify close complete */ - fpi_imgdev_close_complete(dev); + /* Notify close complete */ + fpi_image_device_close_complete (dev, error); } /* Usb id table of device */ -static const struct usb_id id_table[] = -{ - { .vendor = 0x138a, .product = 0x0001 }, - { 0, 0, 0, }, +static const FpIdEntry id_table[] = { + { .vid = 0x138a, .pid = 0x0001, }, + { .vid = 0, .pid = 0, .driver_data = 0 }, }; -/* Device driver definition */ -struct fp_img_driver vfs101_driver = +static void +fpi_device_vfs101_init (FpDeviceVfs101 *self) { - /* Driver specification */ - .driver = - { - .id = VFS101_ID, - .name = FP_COMPONENT, - .full_name = "Validity VFS101", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_SWIPE, - }, +} - /* Image specification */ - .flags = 0, - .img_width = VFS_IMG_WIDTH, - .img_height = -1, - .bz3_threshold = 24, +static void +fpi_device_vfs101_class_init (FpDeviceVfs101Class *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); - /* Routine specification */ - .open = dev_open, - .close = dev_close, - .activate = dev_activate, - .deactivate = dev_deactivate, -}; + dev_class->id = "vfs101"; + dev_class->full_name = "Validity VFS101"; + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->id_table = id_table; + dev_class->scan_type = FP_SCAN_TYPE_SWIPE; + + img_class->img_open = dev_open; + img_class->img_close = dev_close; + img_class->activate = dev_activate; + img_class->deactivate = dev_deactivate; + + img_class->bz3_threshold = 24; + + img_class->img_width = VFS_IMG_WIDTH; + img_class->img_height = -1; +} diff --git a/libfprint/drivers/vfs301.c b/libfprint/drivers/vfs301.c index 94837de0..8fdac7c7 100644 --- a/libfprint/drivers/vfs301.c +++ b/libfprint/drivers/vfs301.c @@ -22,268 +22,273 @@ #define FP_COMPONENT "vfs301" #include "drivers_api.h" -#include "vfs301_proto.h" +#include "vfs301.h" + +G_DEFINE_TYPE (FpDeviceVfs301, fpi_device_vfs301, FP_TYPE_IMAGE_DEVICE) /************************** GENERIC STUFF *************************************/ /* Submit asynchronous sleep */ static void -async_sleep(unsigned int msec, - fpi_ssm *ssm, - struct fp_img_dev *dev) +async_sleep (unsigned int msec, + FpiSsm *ssm, + FpImageDevice *dev) { - /* Add timeout */ - if (fpi_timeout_add(msec, fpi_ssm_next_state_timeout_cb, FP_DEV(dev), ssm) == NULL) { - /* Failed to add timeout */ - fp_err("failed to add timeout"); - fpi_imgdev_session_error(dev, -ETIME); - fpi_ssm_mark_failed(ssm, -ETIME); - } + /* Add timeout */ + fpi_device_add_timeout (FP_DEVICE (dev), msec, + fpi_ssm_next_state_timeout_cb, ssm); } static int -submit_image(fpi_ssm *ssm, - struct fp_img_dev *dev) +submit_image (FpiSsm *ssm, + FpImageDevice *dev) { - vfs301_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); - int height; - struct fp_img *img; + FpDeviceVfs301 *self = FPI_DEVICE_VFS301 (dev); + int height; + FpImage *img; #if 0 - /* XXX: This is probably handled by libfprint automagically? */ - if (vdev->scanline_count < 20) { - fpi_ssm_jump_to_state(ssm, M_REQUEST_PRINT); - return 0; - } + /* XXX: This is probably handled by libfprint automagically? */ + if (vdev->scanline_count < 20) + { + fpi_ssm_jump_to_state (ssm, M_REQUEST_PRINT); + return 0; + } #endif - img = fpi_img_new(VFS301_FP_OUTPUT_WIDTH * vdev->scanline_count); - if (img == NULL) - return 0; + img = fp_image_new (VFS301_FP_OUTPUT_WIDTH, self->scanline_count); + if (img == NULL) + return 0; - vfs301_extract_image(vdev, img->data, &height); + vfs301_extract_image (self, img->data, &height); - /* TODO: how to detect flip? should the resulting image be - * oriented so that it is equal e.g. to a fingerprint on a paper, - * or to the finger when I look at it?) */ - img->flags = FP_IMG_COLORS_INVERTED | FP_IMG_V_FLIPPED; + /* TODO: how to detect flip? should the resulting image be + * oriented so that it is equal e.g. to a fingerprint on a paper, + * or to the finger when I look at it?) */ + img->flags = FPI_IMAGE_COLORS_INVERTED | FPI_IMAGE_V_FLIPPED; - img->width = VFS301_FP_OUTPUT_WIDTH; - img->height = height; + /* The image buffer is larger at this point, but that does not + * matter. */ + img->width = VFS301_FP_OUTPUT_WIDTH; + img->height = height; - img = fpi_img_realloc(img, img->height * img->width); - fpi_imgdev_image_captured(dev, img); + fpi_image_device_image_captured (dev, img); - return 1; + return 1; } /* Loop ssm states */ -enum -{ - /* Step 0 - Scan finger */ - M_REQUEST_PRINT, - M_WAIT_PRINT, - M_CHECK_PRINT, - M_READ_PRINT_START, - M_READ_PRINT_WAIT, - M_READ_PRINT_POLL, - M_SUBMIT_PRINT, +enum { + /* Step 0 - Scan finger */ + M_REQUEST_PRINT, + M_WAIT_PRINT, + M_CHECK_PRINT, + M_READ_PRINT_START, + M_READ_PRINT_WAIT, + M_READ_PRINT_POLL, + M_SUBMIT_PRINT, - /* Number of states */ - M_LOOP_NUM_STATES, + /* Number of states */ + M_LOOP_NUM_STATES, }; /* Exec loop sequential state machine */ -static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_loop_state (FpiSsm *ssm, FpDevice *_dev) { - struct fp_img_dev *dev = user_data; - vfs301_dev_t *vdev = FP_INSTANCE_DATA(_dev); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpDeviceVfs301 *self = FPI_DEVICE_VFS301 (_dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case M_REQUEST_PRINT: - vfs301_proto_request_fingerprint(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev); - fpi_ssm_next_state(ssm); - break; + switch (fpi_ssm_get_cur_state (ssm)) + { + case M_REQUEST_PRINT: + vfs301_proto_request_fingerprint (self); + fpi_ssm_next_state (ssm); + break; - case M_WAIT_PRINT: - /* Wait fingerprint scanning */ - async_sleep(200, ssm, dev); - break; + case M_WAIT_PRINT: + /* Wait fingerprint scanning */ + async_sleep (200, ssm, dev); + break; - case M_CHECK_PRINT: - if (!vfs301_proto_peek_event(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev)) - fpi_ssm_jump_to_state(ssm, M_WAIT_PRINT); - else - fpi_ssm_next_state(ssm); - break; + case M_CHECK_PRINT: + if (!vfs301_proto_peek_event (self)) + fpi_ssm_jump_to_state (ssm, M_WAIT_PRINT); + else + fpi_ssm_next_state (ssm); + break; - case M_READ_PRINT_START: - fpi_imgdev_report_finger_status(dev, TRUE); - vfs301_proto_process_event_start(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev); - fpi_ssm_next_state(ssm); - break; + case M_READ_PRINT_START: + fpi_image_device_report_finger_status (dev, TRUE); + vfs301_proto_process_event_start (self); + fpi_ssm_next_state (ssm); + break; - case M_READ_PRINT_WAIT: - /* Wait fingerprint scanning */ - async_sleep(200, ssm, dev); - break; + case M_READ_PRINT_WAIT: + /* Wait fingerprint scanning */ + async_sleep (200, ssm, dev); + break; - case M_READ_PRINT_POLL: - { - int rv = vfs301_proto_process_event_poll(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev); - g_assert(rv != VFS301_FAILURE); - if (rv == VFS301_ONGOING) - fpi_ssm_jump_to_state(ssm, M_READ_PRINT_WAIT); - else - fpi_ssm_next_state(ssm); - } - break; + case M_READ_PRINT_POLL: + { + int rv = vfs301_proto_process_event_poll (self); + g_assert (rv != VFS301_FAILURE); + if (rv == VFS301_ONGOING) + fpi_ssm_jump_to_state (ssm, M_READ_PRINT_WAIT); + else + fpi_ssm_next_state (ssm); + } + break; - case M_SUBMIT_PRINT: - if (submit_image(ssm, dev)) { - fpi_ssm_mark_completed(ssm); - /* NOTE: finger off is expected only after submitting image... */ - fpi_imgdev_report_finger_status(dev, FALSE); - } else { - fpi_ssm_jump_to_state(ssm, M_REQUEST_PRINT); - } - break; - } + case M_SUBMIT_PRINT: + if (submit_image (ssm, dev)) + { + fpi_ssm_mark_completed (ssm); + /* NOTE: finger off is expected only after submitting image... */ + fpi_image_device_report_finger_status (dev, FALSE); + } + else + { + fpi_ssm_jump_to_state (ssm, M_REQUEST_PRINT); + } + break; + + default: + g_assert_not_reached (); + } } /* Complete loop sequential state machine */ -static void m_loop_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_loop_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { - /* Free sequential state machine */ - fpi_ssm_free(ssm); + if (error) + { + g_warning ("State machine completed with an error: %s", error->message); + g_error_free (error); + } + /* Free sequential state machine */ + fpi_ssm_free (ssm); } /* Exec init sequential state machine */ -static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_init_state (FpiSsm *ssm, FpDevice *_dev) { - struct fp_img_dev *dev = user_data; - vfs301_dev_t *vdev = FP_INSTANCE_DATA(_dev); + FpDeviceVfs301 *self = FPI_DEVICE_VFS301 (_dev); - g_assert(fpi_ssm_get_cur_state(ssm) == 0); + g_assert (fpi_ssm_get_cur_state (ssm) == 0); - vfs301_proto_init(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev); + vfs301_proto_init (self); - fpi_ssm_mark_completed(ssm); + fpi_ssm_mark_completed (ssm); } /* Complete init sequential state machine */ -static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +m_init_complete (FpiSsm *ssm, FpDevice *dev, GError *error) { - struct fp_img_dev *dev = user_data; - fpi_ssm *ssm_loop; + FpiSsm *ssm_loop; - if (!fpi_ssm_get_error(ssm)) { - /* Notify activate complete */ - fpi_imgdev_activate_complete(dev, 0); + fpi_image_device_activate_complete (FP_IMAGE_DEVICE (dev), error); + if (!error) + { + /* Notify activate complete */ - /* Start loop ssm */ - ssm_loop = fpi_ssm_new(FP_DEV(dev), m_loop_state, M_LOOP_NUM_STATES, dev); - fpi_ssm_start(ssm_loop, m_loop_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 */ - fpi_ssm_free(ssm); + /* Free sequential state machine */ + fpi_ssm_free (ssm); } /* Activate device */ -static int dev_activate(struct fp_img_dev *dev) +static void +dev_activate (FpImageDevice *dev) { - fpi_ssm *ssm; + FpiSsm *ssm; - /* Start init ssm */ - ssm = fpi_ssm_new(FP_DEV(dev), m_init_state, 1, dev); - fpi_ssm_start(ssm, m_init_complete); - - return 0; + /* Start init ssm */ + ssm = fpi_ssm_new (FP_DEVICE (dev), m_init_state, 1); + fpi_ssm_start (ssm, m_init_complete); } /* Deactivate device */ -static void dev_deactivate(struct fp_img_dev *dev) +static void +dev_deactivate (FpImageDevice *dev) { - vfs301_dev_t *vdev; + FpDeviceVfs301 *self; - vdev = FP_INSTANCE_DATA(FP_DEV(dev)); - vfs301_proto_deinit(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev); - fpi_imgdev_deactivate_complete(dev); + self = FPI_DEVICE_VFS301 (dev); + vfs301_proto_deinit (self); + fpi_image_device_deactivate_complete (dev, NULL); } -static int dev_open(struct fp_img_dev *dev, unsigned long driver_data) +static void +dev_open (FpImageDevice *dev) { - vfs301_dev_t *vdev = NULL; - int r; + FpDeviceVfs301 *self = FPI_DEVICE_VFS301 (dev); + GError *error = NULL; - /* Claim usb interface */ - r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - if (r < 0) { - /* Interface not claimed, return error */ - fp_err("could not claim interface 0: %s", libusb_error_name(r)); - return r; - } + /* Claim usb interface */ + g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error); - /* Initialize private structure */ - vdev = g_malloc0(sizeof(vfs301_dev_t)); - fp_dev_set_instance_data(FP_DEV(dev), vdev); + /* Initialize private structure */ + self->scanline_count = 0; - vdev->scanline_buf = malloc(0); - vdev->scanline_count = 0; - - /* Notify open complete */ - fpi_imgdev_open_complete(dev, 0); - - return 0; + /* Notify open complete */ + fpi_image_device_open_complete (dev, error); } -static void dev_close(struct fp_img_dev *dev) +static void +dev_close (FpImageDevice *dev) { - vfs301_dev_t *vdev; + FpDeviceVfs301 *self = FPI_DEVICE_VFS301 (dev); + GError *error = NULL; - /* Release private structure */ - vdev = FP_INSTANCE_DATA(FP_DEV(dev)); - free(vdev->scanline_buf); - g_free(vdev); + /* Release private structure */ + g_clear_pointer (&self->scanline_buf, g_free); - /* Release usb interface */ - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); + /* Release usb interface */ + g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), + 0, 0, &error); - /* Notify close complete */ - fpi_imgdev_close_complete(dev); + /* Notify close complete */ + fpi_image_device_close_complete (dev, error); } /* Usb id table of device */ -static const struct usb_id id_table[] = -{ - { .vendor = 0x138a, .product = 0x0005 /* vfs301 */ }, - { .vendor = 0x138a, .product = 0x0008 /* vfs300 */ }, - { 0, 0, 0, }, +static const FpIdEntry id_table[] = { + { /* vfs301 */ .vid = 0x138a, .pid = 0x0005, }, + { /* vfs300 */ .vid = 0x138a, .pid = 0x0008, }, + { .vid = 0, .pid = 0, .driver_data = 0 }, }; -/* Device driver definition */ -struct fp_img_driver vfs301_driver = +static void +fpi_device_vfs301_init (FpDeviceVfs301 *self) { - /* Driver specification */ - .driver = - { - .id = VFS301_ID, - .name = FP_COMPONENT, - .full_name = "Validity VFS301", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_SWIPE, - }, +} +static void +fpi_device_vfs301_class_init (FpDeviceVfs301Class *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); - /* Image specification */ - .flags = 0, - .img_width = VFS301_FP_WIDTH, - .img_height = -1, - .bz3_threshold = 24, + dev_class->id = "vfs301"; + dev_class->full_name = "Validity VFS301"; + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->id_table = id_table; + dev_class->scan_type = FP_SCAN_TYPE_SWIPE; - /* Routine specification */ - .open = dev_open, - .close = dev_close, - .activate = dev_activate, - .deactivate = dev_deactivate, -}; + img_class->img_open = dev_open; + img_class->img_close = dev_close; + img_class->activate = dev_activate; + img_class->deactivate = dev_deactivate; + + img_class->bz3_threshold = 24; + + img_class->img_width = VFS301_FP_WIDTH; + img_class->img_height = -1; +} diff --git a/libfprint/drivers/vfs301.h b/libfprint/drivers/vfs301.h new file mode 100644 index 00000000..3ab23f94 --- /dev/null +++ b/libfprint/drivers/vfs301.h @@ -0,0 +1,142 @@ +/* + * vfs301/vfs300 fingerprint reader driver + * https://github.com/andree182/vfs301 + * + * Copyright (c) 2011-2012 Andrej Krutak + * + * 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-usb-transfer.h" +#include "fpi-image-device.h" + +enum { + VFS301_DEFAULT_WAIT_TIMEOUT = 300, + + VFS301_SEND_ENDPOINT = 0x01, + VFS301_RECEIVE_ENDPOINT_CTRL = 0x81, + VFS301_RECEIVE_ENDPOINT_DATA = 0x82 +}; + +#define VFS301_FP_RECV_LEN_1 (84032) +#define VFS301_FP_RECV_LEN_2 (84096) + +struct _FpDeviceVfs301 +{ + FpImageDevice parent; + + /* buffer to hold raw scanlines */ + unsigned char *scanline_buf; + int scanline_count; + + enum { + VFS301_ONGOING = 0, + VFS301_ENDED = 1, + VFS301_FAILURE = -1 + } recv_progress; + int recv_exp_amt; +}; + +G_DECLARE_FINAL_TYPE (FpDeviceVfs301, fpi_device_vfs301, FPI, DEVICE_VFS301, FpImageDevice) + +enum { + /* Width of the scanned data in px */ + VFS301_FP_WIDTH = 200, + + /* sizeof(fp_line_t) */ + VFS301_FP_FRAME_SIZE = 288, + /* Width of output line */ +#ifndef OUTPUT_RAW + VFS301_FP_OUTPUT_WIDTH = VFS301_FP_WIDTH, +#else + VFS301_FP_OUTPUT_WIDTH = VFS301_FP_FRAME_SIZE, +#endif + + VFS301_FP_SUM_LINES = 3, + +#ifdef SCAN_FINISH_DETECTION + /* TODO: The following changes (seen ~60 and ~80) In that + * case we'll need to calibrate this from empty data somehow... */ + VFS301_FP_SUM_MEDIAN = 60, + VFS301_FP_SUM_EMPTY_RANGE = 5, +#endif + + /* Minimum average difference between returned lines */ + VFS301_FP_LINE_DIFF_THRESHOLD = 15, + + /* Maximum waiting time for a single fingerprint frame */ + VFS301_FP_RECV_TIMEOUT = 2000 +}; + +/* Arrays of this structure is returned during the initialization as a response + * to the 0x02D0 messages. + * It seems to be always the same - what is it for? Some kind of confirmation? + */ +typedef struct +{ + unsigned char sync_0x01; + unsigned char sync_0xfe; + + unsigned char counter_lo; + unsigned char counter_hi; /* FIXME ? */ + + unsigned char flags[3]; + + unsigned char sync_0x00; + + unsigned char scan[VFS301_FP_WIDTH]; +} vfs301_init_line_t; + +typedef struct +{ + unsigned char sync_0x01; + unsigned char sync_0xfe; + + unsigned char counter_lo; + unsigned char counter_hi; + + unsigned char sync_0x08[2]; /* XXX: always? 0x08 0x08 */ + /* 0x08 | 0x18 - Looks like 0x08 marks good quality lines */ + unsigned char flag_1; + unsigned char sync_0x00; + + unsigned char scan[VFS301_FP_WIDTH]; + + /* A offsetted, stretched, inverted copy of scan... probably could + * serve finger motion speed detection? + * Seems to be subdivided to some 10B + 53B + 1B blocks */ + unsigned char mirror[64]; + + /* Some kind of sum of the scan, very low contrast */ + unsigned char sum1[2]; + unsigned char sum2[11]; + unsigned char sum3[3]; +} vfs301_line_t; + +void vfs301_proto_init (FpDeviceVfs301 *dev); +void vfs301_proto_deinit (FpDeviceVfs301 *dev); + +void vfs301_proto_request_fingerprint (FpDeviceVfs301 *dev); + +/** returns 0 if no event is ready, or 1 if there is one... */ +int vfs301_proto_peek_event (FpDeviceVfs301 *dev); +void vfs301_proto_process_event_start (FpDeviceVfs301 *dev); +int vfs301_proto_process_event_poll (FpDeviceVfs301 *dev); + +void vfs301_extract_image (FpDeviceVfs301 *vfs, + unsigned char *output, + int *output_height); diff --git a/libfprint/drivers/vfs301_proto.c b/libfprint/drivers/vfs301_proto.c index 7564f56d..5d02597f 100644 --- a/libfprint/drivers/vfs301_proto.c +++ b/libfprint/drivers/vfs301_proto.c @@ -34,598 +34,668 @@ #include #include -#include "fpi-usb.h" -#include "vfs301_proto.h" +#include "fpi-usb-transfer.h" +#include "vfs301.h" #include "vfs301_proto_fragments.h" /************************** USB STUFF *****************************************/ #ifdef DEBUG -static void usb_print_packet(int dir, int rv, const unsigned char *data, int length) +static void +usb_print_packet (int dir, GError *error, const guint8 *data, int length) { - fprintf(stderr, "%s, rv %d, len %d\n", dir ? "send" : "recv", rv, length); + fprintf (stderr, "%s, error %s, len %d\n", dir ? "send" : "recv", error ? error->message : "-", length); #ifdef PRINT_VERBOSE - int i; + int i; - for (i = 0; i < MIN(length, 128); i++) { - fprintf(stderr, "%.2X ", data[i]); - if (i % 8 == 7) - fprintf(stderr, " "); - if (i % 32 == 31) - fprintf(stderr, "\n"); - } + for (i = 0; i < MIN (length, 128); i++) + { + fprintf (stderr, "%.2X ", data[i]); + if (i % 8 == 7) + fprintf (stderr, " "); + if (i % 32 == 31) + fprintf (stderr, "\n"); + } #endif - fprintf(stderr, "\n"); + fprintf (stderr, "\n"); } #endif -static int usb_recv( - vfs301_dev_t *dev, - struct libusb_device_handle *devh, unsigned char endpoint, int max_bytes) +static void +usb_recv (FpDeviceVfs301 *dev, guint8 endpoint, int max_bytes, FpiUsbTransfer **out, GError **error) { - g_assert(max_bytes <= sizeof(dev->recv_buf)); + GError *err = NULL; + + g_autoptr(FpiUsbTransfer) transfer = NULL; + + /* XXX: This function swallows any transfer errors, that is obviously + * quite bad (it used to assert on no-error)! */ + + transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); + transfer->short_is_error = TRUE; + fpi_usb_transfer_fill_bulk (transfer, endpoint, max_bytes); + + fpi_usb_transfer_submit_sync (transfer, VFS301_DEFAULT_WAIT_TIMEOUT, &err); - int r = libusb_bulk_transfer( - devh, endpoint, - dev->recv_buf, max_bytes, - &dev->recv_len, VFS301_DEFAULT_WAIT_TIMEOUT - ); #ifdef DEBUG - usb_print_packet(0, r, dev->recv_buf, dev->recv_len); + usb_print_packet (0, err, transfer->buffer, transfer->actual_length); #endif + if (err) + { + if (!error) + g_warning ("Unhandled receive error: %s", err->message); + g_propagate_error (error, err); + } - if (r < 0) - return r; - return 0; + if (out) + *out = g_steal_pointer (&transfer); } -static int usb_send( - struct libusb_device_handle *devh, const unsigned char *data, int length) +static void +usb_send (FpDeviceVfs301 *dev, const guint8 *data, gssize length, GError **error) { - int transferred = 0; + GError *err = NULL; - int r = libusb_bulk_transfer( - devh, VFS301_SEND_ENDPOINT, - (unsigned char *)data, length, &transferred, VFS301_DEFAULT_WAIT_TIMEOUT - ); + g_autoptr(FpiUsbTransfer) transfer = NULL; + + /* XXX: This function swallows any transfer errors, that is obviously + * quite bad (it used to assert on no-error)! */ + + transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); + transfer->short_is_error = TRUE; + fpi_usb_transfer_fill_bulk_full (transfer, VFS301_SEND_ENDPOINT, (guint8 *) data, length, g_free); + + fpi_usb_transfer_submit_sync (transfer, VFS301_DEFAULT_WAIT_TIMEOUT, &err); #ifdef DEBUG - usb_print_packet(1, r, data, length); + usb_print_packet (1, err, data, length); #endif - g_assert(r == 0); - - if (r < 0) - return r; - if (transferred < length) - return r; - - return 0; + if (err) + { + g_warning ("Error while sending data, continuing anyway: %s", err->message); + g_propagate_error (error, err); + } } /************************** OUT MESSAGES GENERATION ***************************/ -static void vfs301_proto_generate_0B(int subtype, unsigned char *data, int *len) +static guint8 * +vfs301_proto_generate_0B (int subtype, gssize *len) { - *data = 0x0B; - *len = 1; - data++; + guint8 *res = g_malloc0 (39); + guint8 *data = res; - memset(data, 0, 39); - *len += 38; + *data = 0x0B; + *len = 1; + data++; - data[20] = subtype; + *len += 38; - switch (subtype) { - case 0x04: - data[34] = 0x9F; - break; - case 0x05: - data[34] = 0xAB; - len++; - break; - default: - g_assert_not_reached(); - break; - } + data[20] = subtype; + + switch (subtype) + { + case 0x04: + data[34] = 0x9F; + break; + + case 0x05: + data[34] = 0xAB; + /* NOTE: There was a len++ here, which could never do anything */ + break; + + default: + g_assert_not_reached (); + break; + } + + return res; } #define HEX_TO_INT(c) \ - (((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'A' + 10)) + (((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'A' + 10)) -static void translate_str(const char **srcL, unsigned char *data, int *len) +static guint8 * +translate_str (const char **srcL, gssize *len) { - const char *src; - unsigned char *dataOrig = data; + guint8 *res = NULL; + guint8 *dst; + const char **src_pos; + const char *src; + gssize src_len = 0; - while (*srcL != NULL) { - src = *srcL; - while (*src != '\0') { - g_assert(*src != '\0'); - g_assert(*(src +1) != '\0'); - *data = (unsigned char)((HEX_TO_INT(*src) << 4) | (HEX_TO_INT(*(src + 1)))); + for (src_pos = srcL; *src_pos; src_pos++) + { + gint tmp; - data++; - src += 2; - } + src = *src_pos; + tmp = strlen (src); + g_assert (tmp % 2 == 0); + src_len += tmp; + } - srcL++; - } + *len = src_len / 2; + res = g_malloc0 (*len); + dst = res; - *len = data - dataOrig; + for (src_pos = srcL; *src_pos; src_pos++) + for (src = *src_pos; *src; src += 2, dst += 1) + *dst = (guint8) ((HEX_TO_INT (src[0]) << 4) | (HEX_TO_INT (src[1]))); + + return res; } -static void vfs301_proto_generate(int type, int subtype, unsigned char *data, int *len) +static guint8 * +vfs301_proto_generate (int type, int subtype, gssize *len) { - switch (type) { - case 0x01: - case 0x04: - /* After cmd 0x04 is sent, a data is received on VALIDITY_RECEIVE_ENDPOINT_CTRL. - * If it is 0x0000: - * additional 64B and 224B are read from _DATA, then vfs301_next_scan_FA00 is - * sent, 0000 received from _CTRL, and then continue with wait loop - * If it is 0x1204: - * => reinit? - */ - case 0x17: - case 0x19: - case 0x1A: - *data = type; - *len = 1; - break; - case 0x0B: - vfs301_proto_generate_0B(subtype, data, len); - break; - case 0x02D0: - { - const char **dataLs[] = { - vfs301_02D0_01, - vfs301_02D0_02, - vfs301_02D0_03, - vfs301_02D0_04, - vfs301_02D0_05, - vfs301_02D0_06, - vfs301_02D0_07, - }; - g_assert((int)subtype <= (int)(sizeof(dataLs) / sizeof(dataLs[0]))); - translate_str(dataLs[subtype - 1], data, len); - } - break; - case 0x0220: - switch (subtype) { - case 1: - translate_str(vfs301_0220_01, data, len); - break; - case 2: - translate_str(vfs301_0220_02, data, len); - break; - case 3: - translate_str(vfs301_0220_03, data, len); - break; - case 0xFA00: - case 0x2C01: - case 0x5E01: - translate_str(vfs301_next_scan_template, data, len); - unsigned char *field = data + *len - (sizeof(S4_TAIL) - 1) / 2 - 4; + switch (type) + { + case 0x01: + case 0x04: + /* After cmd 0x04 is sent, a data is received on VALIDITY_RECEIVE_ENDPOINT_CTRL. + * If it is 0x0000: + * additional 64B and 224B are read from _DATA, then vfs301_next_scan_FA00 is + * sent, 0000 received from _CTRL, and then continue with wait loop + * If it is 0x1204: + * => reinit? + */ + case 0x17: + case 0x19: + case 0x1A: + { + guint8 *data = g_malloc0 (1); + *data = type; + *len = 1; + return data; + } + break; - g_assert(*field == 0xDE); - g_assert(*(field + 1) == 0xAD); - g_assert(*(field + 2) == 0xDE); - g_assert(*(field + 3) == 0xAD); + case 0x0B: + return vfs301_proto_generate_0B (subtype, len); + break; - *field = (unsigned char)((subtype >> 8) & 0xFF); - *(field + 1) = (unsigned char)(subtype & 0xFF); - *(field + 2) = *field; - *(field + 3) = *(field + 1); - break; - default: - g_assert(0); - break; - } - break; - case 0x06: - g_assert_not_reached(); - break; - default: - g_assert_not_reached(); - break; - } + case 0x02D0: + { + const char **dataLs[] = { + vfs301_02D0_01, + vfs301_02D0_02, + vfs301_02D0_03, + vfs301_02D0_04, + vfs301_02D0_05, + vfs301_02D0_06, + vfs301_02D0_07, + }; + 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: + case 0x5E01: { + guint8 *data; + guint8 *field; + + data = translate_str (vfs301_next_scan_template, len); + field = data + *len - (sizeof (S4_TAIL) - 1) / 2 - 4; + + g_assert (field >= data && field < data + *len); + g_assert (field[0] == 0xDE); + g_assert (field[1] == 0xAD); + g_assert (field[2] == 0xDE); + g_assert (field[3] == 0xAD); + + field[0] = (guint8) ((subtype >> 8) & 0xFF); + field[1] = (guint8) (subtype & 0xFF); + field[2] = field[0]; + field[3] = field[1]; + + return data; + break; + } + + default: + g_assert_not_reached (); + break; + } + break; + + case 0x06: + default: + break; + } + + g_assert_not_reached (); + *len = 0; + return NULL; } /************************** SCAN IMAGE PROCESSING *****************************/ #ifdef SCAN_FINISH_DETECTION -static int img_is_finished_scan(fp_line_t *lines, int no_lines) +static int +img_is_finished_scan (fp_line_t *lines, int no_lines) { - int i; - int j; - int rv = 1; + int i; + int j; + int rv = 1; - for (i = no_lines - VFS301_FP_SUM_LINES; i < no_lines; i++) { - /* check the line for fingerprint data */ - for (j = 0; j < sizeof(lines[i].sum2); j++) { - if (lines[i].sum2[j] > (VFS301_FP_SUM_MEDIAN + VFS301_FP_SUM_EMPTY_RANGE)) - rv = 0; - } - } + for (i = no_lines - VFS301_FP_SUM_LINES; i < no_lines; i++) + { + /* check the line for fingerprint data */ + for (j = 0; j < sizeof (lines[i].sum2); j++) + if (lines[i].sum2[j] > (VFS301_FP_SUM_MEDIAN + VFS301_FP_SUM_EMPTY_RANGE)) + rv = 0; + } - return rv; + return rv; } #endif -static int scanline_diff(const unsigned char *scanlines, int prev, int cur) +static int +scanline_diff (const guint8 *scanlines, int prev, int cur) { - const unsigned char *line1 = scanlines + prev * VFS301_FP_OUTPUT_WIDTH; - const unsigned char *line2 = scanlines + cur * VFS301_FP_OUTPUT_WIDTH; - int i; - int diff; + const guint8 *line1 = scanlines + prev * VFS301_FP_OUTPUT_WIDTH; + const guint8 *line2 = scanlines + cur * VFS301_FP_OUTPUT_WIDTH; + int i; + int diff; #ifdef OUTPUT_RAW - /* We only need the image, not the surrounding stuff. */ - line1 = ((vfs301_line_t*)line1)->scan; - line2 = ((vfs301_line_t*)line2)->scan; + /* We only need the image, not the surrounding stuff. */ + line1 = ((vfs301_line_t *) line1)->scan; + line2 = ((vfs301_line_t *) line2)->scan; #endif - /* TODO: This doesn't work too well when there are parallel lines in the - * fingerprint. */ - for (diff = 0, i = 0; i < VFS301_FP_WIDTH; i++) { - if (*line1 > *line2) - diff += *line1 - *line2; - else - diff += *line2 - *line1; + /* TODO: This doesn't work too well when there are parallel lines in the + * fingerprint. */ + for (diff = 0, i = 0; i < VFS301_FP_WIDTH; i++) + { + if (*line1 > *line2) + diff += *line1 - *line2; + else + diff += *line2 - *line1; - line1++; - line2++; - } + line1++; + line2++; + } - return ((diff / VFS301_FP_WIDTH) > VFS301_FP_LINE_DIFF_THRESHOLD); + return (diff / VFS301_FP_WIDTH) > VFS301_FP_LINE_DIFF_THRESHOLD; } /** Transform the input data to a normalized fingerprint scan */ -void vfs301_extract_image( - vfs301_dev_t *vfs, unsigned char *output, int *output_height -) +void +vfs301_extract_image (FpDeviceVfs301 *vfs, guint8 *output, int *output_height + ) { - const unsigned char *scanlines = vfs->scanline_buf; - int last_line; - int i; + const guint8 *scanlines = vfs->scanline_buf; + int last_line; + int i; - g_assert(vfs->scanline_count >= 1); + g_assert (vfs->scanline_count >= 1); - *output_height = 1; - memcpy(output, scanlines, VFS301_FP_OUTPUT_WIDTH); - last_line = 0; + *output_height = 1; + memcpy (output, scanlines, VFS301_FP_OUTPUT_WIDTH); + last_line = 0; - /* The following algorithm is quite trivial - it just picks lines that - * differ more than VFS301_FP_LINE_DIFF_THRESHOLD. - * TODO: A nicer approach would be to pick those lines and then do some kind - * of bi/tri-linear resampling to get the output (so that we don't get so - * many false edges etc.). - */ - for (i = 1; i < vfs->scanline_count; i++) { - if (scanline_diff(scanlines, last_line, i)) { - memcpy( - output + VFS301_FP_OUTPUT_WIDTH * (*output_height), - scanlines + VFS301_FP_OUTPUT_WIDTH * i, - VFS301_FP_OUTPUT_WIDTH - ); - last_line = i; - (*output_height)++; - } - } + /* The following algorithm is quite trivial - it just picks lines that + * differ more than VFS301_FP_LINE_DIFF_THRESHOLD. + * TODO: A nicer approach would be to pick those lines and then do some kind + * of bi/tri-linear resampling to get the output (so that we don't get so + * many false edges etc.). + */ + for (i = 1; i < vfs->scanline_count; i++) + { + if (scanline_diff (scanlines, last_line, i)) + { + memcpy ( + output + VFS301_FP_OUTPUT_WIDTH * (*output_height), + scanlines + VFS301_FP_OUTPUT_WIDTH * i, + VFS301_FP_OUTPUT_WIDTH + ); + last_line = i; + (*output_height)++; + } + } } -static int img_process_data( - int first_block, vfs301_dev_t *dev, const unsigned char *buf, int len -) +static int +img_process_data (int first_block, FpDeviceVfs301 *dev, const guint8 *buf, int len) { - vfs301_line_t *lines = (vfs301_line_t*)buf; - int no_lines = len / sizeof(vfs301_line_t); - int i; - /*int no_nonempty;*/ - unsigned char *cur_line; - int last_img_height; + vfs301_line_t *lines = (vfs301_line_t *) buf; + int no_lines = len / sizeof (vfs301_line_t); + int i; + /*int no_nonempty;*/ + guint8 *cur_line; + int last_img_height; + #ifdef SCAN_FINISH_DETECTION - int finished_scan; + int finished_scan; #endif - if (first_block) { - last_img_height = 0; - dev->scanline_count = no_lines; - } else { - last_img_height = dev->scanline_count; - dev->scanline_count += no_lines; - } + if (first_block) + { + last_img_height = 0; + dev->scanline_count = no_lines; + } + else + { + last_img_height = dev->scanline_count; + dev->scanline_count += no_lines; + } - dev->scanline_buf = realloc(dev->scanline_buf, dev->scanline_count * VFS301_FP_OUTPUT_WIDTH); - g_assert(dev->scanline_buf != NULL); + dev->scanline_buf = g_realloc (dev->scanline_buf, dev->scanline_count * VFS301_FP_OUTPUT_WIDTH); - for (cur_line = dev->scanline_buf + last_img_height * VFS301_FP_OUTPUT_WIDTH, i = 0; - i < no_lines; - i++, cur_line += VFS301_FP_OUTPUT_WIDTH - ) { + for (cur_line = dev->scanline_buf + last_img_height * VFS301_FP_OUTPUT_WIDTH, i = 0; + i < no_lines; + i++, cur_line += VFS301_FP_OUTPUT_WIDTH + ) + { #ifndef OUTPUT_RAW - memcpy(cur_line, lines[i].scan, VFS301_FP_OUTPUT_WIDTH); + memcpy (cur_line, lines[i].scan, VFS301_FP_OUTPUT_WIDTH); #else - memcpy(cur_line, &lines[i], VFS301_FP_OUTPUT_WIDTH); + memcpy (cur_line, &lines[i], VFS301_FP_OUTPUT_WIDTH); #endif - } + } #ifdef SCAN_FINISH_DETECTION - finished_scan = img_is_finished_scan(lines, no_lines); + finished_scan = img_is_finished_scan (lines, no_lines); - return !finished_scan; + return !finished_scan; #else /* SCAN_FINISH_DETECTION */ - return 1; /* Just continue until data is coming */ + return 1; /* Just continue until data is coming */ #endif } /************************** PROTOCOL STUFF ************************************/ -static unsigned char usb_send_buf[0x2000]; - #define USB_RECV(from, len) \ - usb_recv(dev, devh, from, len) + usb_recv (dev, from, len, NULL, NULL) #define USB_SEND(type, subtype) \ - { \ - int len; \ - vfs301_proto_generate(type, subtype, usb_send_buf, &len); \ - usb_send(devh, usb_send_buf, len); \ - } + { \ + const guint8 *data; \ + gssize len; \ + data = vfs301_proto_generate (type, subtype, &len); \ + usb_send (dev, data, len, NULL); \ + } -#define RAW_DATA(x) x, sizeof(x) +#define RAW_DATA(x) x, sizeof (x) #define IS_VFS301_FP_SEQ_START(b) ((b[0] == 0x01) && (b[1] == 0xfe)) -static int vfs301_proto_process_data(int first_block, vfs301_dev_t *dev) +static int +vfs301_proto_process_data (FpDeviceVfs301 *dev, int first_block, const guint8 *buf, gint len) { - int i; - const unsigned char *buf = dev->recv_buf; - int len = dev->recv_len; + int i; - if (first_block) { - g_assert(len >= VFS301_FP_FRAME_SIZE); + if (first_block) + { + g_assert (len >= VFS301_FP_FRAME_SIZE); - /* Skip bytes until start_sequence is found */ - for (i = 0; i < VFS301_FP_FRAME_SIZE; i++, buf++, len--) { - if (IS_VFS301_FP_SEQ_START(buf)) - break; - } - } + /* Skip bytes until start_sequence is found */ + for (i = 0; i < VFS301_FP_FRAME_SIZE; i++, buf++, len--) + if (IS_VFS301_FP_SEQ_START (buf)) + break; + } - return img_process_data(first_block, dev, buf, len); + return img_process_data (first_block, dev, buf, len); } -void vfs301_proto_request_fingerprint( - struct libusb_device_handle *devh, vfs301_dev_t *dev) +void +vfs301_proto_request_fingerprint (FpDeviceVfs301 *dev) { - USB_SEND(0x0220, 0xFA00); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 000000000000 */ + USB_SEND (0x0220, 0xFA00); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 000000000000 */ } -int vfs301_proto_peek_event( - struct libusb_device_handle *devh, vfs301_dev_t *dev) +int +vfs301_proto_peek_event (FpDeviceVfs301 *dev) { - const char no_event[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - const char got_event[] = {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00}; + g_autoptr(GError) error = NULL; + g_autoptr(FpiUsbTransfer) transfer = NULL; - USB_SEND(0x17, -1); - g_assert(USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 7) == 0); + const char no_event[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + const char got_event[] = {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00}; - if (memcmp(dev->recv_buf, no_event, sizeof(no_event)) == 0) { - return 0; - } else if (memcmp(dev->recv_buf, got_event, sizeof(no_event)) == 0) { - return 1; - } else { - g_assert_not_reached(); - } + USB_SEND (0x17, -1); + usb_recv (dev, VFS301_RECEIVE_ENDPOINT_CTRL, 7, &transfer, &error); + + /* XXX: This is obviously not a sane error handling! */ + g_assert (!error); + + if (memcmp (transfer->buffer, no_event, sizeof (no_event)) == 0) + return 0; + else if (memcmp (transfer->buffer, got_event, sizeof (no_event)) == 0) + return 1; + else + g_assert_not_reached (); } -#define VARIABLE_ORDER(a, b) \ - { \ - int _rv = a;\ - b; \ - if (_rv == -7) \ - a; \ - } +/* XXX: We sometimes need to receive data on from two endpoints at the same + * time. However, as this driver is currently all synchronous (yikes), + * we will run into timeouts randomly and need to then try again. + */ +#define PARALLEL_RECEIVE(e1, l1, e2, l2) \ + { \ + g_autoptr(GError) error = NULL; \ + usb_recv (dev, e1, l1, NULL, &error); \ + usb_recv (dev, e2, l2, NULL, NULL); \ + if (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT)) \ + usb_recv(dev, e1, l1, NULL, NULL); \ + } -static void vfs301_proto_process_event_cb(struct libusb_transfer *transfer) +static void +vfs301_proto_process_event_cb (FpiUsbTransfer *transfer, + FpDevice *device, + gpointer user_data, GError *error) { - vfs301_dev_t *dev = transfer->user_data; - struct libusb_device_handle *devh = transfer->dev_handle; + FpDeviceVfs301 *dev = user_data; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - dev->recv_progress = VFS301_FAILURE; - goto end; - } else if (transfer->actual_length < dev->recv_exp_amt) { - /* TODO: process the data anyway? */ - dev->recv_progress = VFS301_ENDED; - goto end; - } else { - dev->recv_len = transfer->actual_length; - if (!vfs301_proto_process_data(dev->recv_exp_amt == VFS301_FP_RECV_LEN_1, dev)) { - dev->recv_progress = VFS301_ENDED; - goto end; - } + if (error) + { + g_warning ("Error receiving data: %s", error->message); + g_error_free (error); + dev->recv_progress = VFS301_FAILURE; + return; + } + else if (transfer->actual_length < transfer->length) + { + /* TODO: process the data anyway? */ + dev->recv_progress = VFS301_ENDED; + return; + } + else + { + FpiUsbTransfer *new; + if (!vfs301_proto_process_data (dev, + transfer->length == VFS301_FP_RECV_LEN_1, + transfer->buffer, + transfer->actual_length)) + { + dev->recv_progress = VFS301_ENDED; + return; + } - dev->recv_exp_amt = VFS301_FP_RECV_LEN_2; - libusb_fill_bulk_transfer( - transfer, devh, VFS301_RECEIVE_ENDPOINT_DATA, - dev->recv_buf, dev->recv_exp_amt, - vfs301_proto_process_event_cb, dev, VFS301_FP_RECV_TIMEOUT); + new = fpi_usb_transfer_new (device); - if (libusb_submit_transfer(transfer) < 0) { - printf("cb::continue fail\n"); - dev->recv_progress = VFS301_FAILURE; - goto end; - } - return; - } - -end: - libusb_free_transfer(transfer); + fpi_usb_transfer_fill_bulk (new, VFS301_RECEIVE_ENDPOINT_DATA, VFS301_FP_RECV_LEN_2); + fpi_usb_transfer_submit (new, VFS301_FP_RECV_TIMEOUT, NULL, + vfs301_proto_process_event_cb, NULL); + fpi_usb_transfer_unref (new); + return; + } } -void vfs301_proto_process_event_start( - struct libusb_device_handle *devh, vfs301_dev_t *dev) +void +vfs301_proto_process_event_start (FpDeviceVfs301 *dev) { - struct libusb_transfer *transfer; + FpiUsbTransfer *transfer; - /* - * Notes: - * - * seen next_scan order: - * o FA00 - * o FA00 - * o 2C01 - * o FA00 - * o FA00 - * o 2C01 - * o FA00 - * o FA00 - * o 2C01 - * o 5E01 !? - * o FA00 - * o FA00 - * o 2C01 - * o FA00 - * o FA00 - * o 2C01 - */ - USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 64); + /* + * Notes: + * + * seen next_scan order: + * o FA00 + * o FA00 + * o 2C01 + * o FA00 + * o FA00 + * o 2C01 + * o FA00 + * o FA00 + * o 2C01 + * o 5E01 !? + * o FA00 + * o FA00 + * o 2C01 + * o FA00 + * o FA00 + * o 2C01 + */ + USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 64); - /* now read the fingerprint data, while there are some */ - transfer = fpi_usb_alloc(); - dev->recv_progress = VFS301_ONGOING; - dev->recv_exp_amt = VFS301_FP_RECV_LEN_1; + /* now read the fingerprint data, while there are some */ + transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); + dev->recv_progress = VFS301_ONGOING; - libusb_fill_bulk_transfer( - transfer, devh, VFS301_RECEIVE_ENDPOINT_DATA, - dev->recv_buf, dev->recv_exp_amt, - vfs301_proto_process_event_cb, dev, VFS301_FP_RECV_TIMEOUT); - - if (libusb_submit_transfer(transfer) < 0) { - libusb_free_transfer(transfer); - dev->recv_progress = VFS301_FAILURE; - return; - } + fpi_usb_transfer_fill_bulk (transfer, VFS301_RECEIVE_ENDPOINT_DATA, VFS301_FP_RECV_LEN_1); + fpi_usb_transfer_submit (transfer, VFS301_FP_RECV_TIMEOUT, NULL, + vfs301_proto_process_event_cb, NULL); + fpi_usb_transfer_unref (transfer); } -int /* vfs301_dev_t::recv_progress */ vfs301_proto_process_event_poll( - struct libusb_device_handle *devh, vfs301_dev_t *dev) +int +vfs301_proto_process_event_poll (FpDeviceVfs301 *dev) { - if (dev->recv_progress != VFS301_ENDED) - return dev->recv_progress; + if (dev->recv_progress != VFS301_ENDED) + return dev->recv_progress; - /* Finish the scan process... */ + /* Finish the scan process... */ - USB_SEND(0x04, -1); - /* the following may come in random order, data may not come at all, don't - * try for too long... */ - VARIABLE_ORDER( - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2), /* 1204 */ - USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 16384) - ); + USB_SEND (0x04, -1); + /* the following may come in random order, data may not come at all, don't + * try for too long... */ + PARALLEL_RECEIVE ( + VFS301_RECEIVE_ENDPOINT_CTRL, 2, /* 1204 */ + VFS301_RECEIVE_ENDPOINT_DATA, 16384 + ); - USB_SEND(0x0220, 2); - VARIABLE_ORDER( - USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 5760), /* seems to always come */ - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2) /* 0000 */ - ); + USB_SEND (0x0220, 2); + PARALLEL_RECEIVE ( + VFS301_RECEIVE_ENDPOINT_DATA, 5760, /* seems to always come */ + VFS301_RECEIVE_ENDPOINT_CTRL, 2 /* 0000 */ + ); - return dev->recv_progress; + return dev->recv_progress; } -void vfs301_proto_init(struct libusb_device_handle *devh, vfs301_dev_t *dev) +void +vfs301_proto_init (FpDeviceVfs301 *dev) { - USB_SEND(0x01, -1); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 38); - USB_SEND(0x0B, 0x04); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 6); /* 000000000000 */ - USB_SEND(0x0B, 0x05); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 7); /* 00000000000000 */ - USB_SEND(0x19, -1); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 64); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 4); /* 6BB4D0BC */ - usb_send(devh, RAW_DATA(vfs301_06_1)); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + USB_SEND (0x01, -1); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 38); + USB_SEND (0x0B, 0x04); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 6); /* 000000000000 */ + USB_SEND (0x0B, 0x05); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 7); /* 00000000000000 */ + USB_SEND (0x19, -1); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 64); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 4); /* 6BB4D0BC */ + usb_send (dev, RAW_DATA (vfs301_06_1), NULL); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - USB_SEND(0x01, -1); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 38); - USB_SEND(0x1A, -1); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - usb_send(devh, RAW_DATA(vfs301_06_2)); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - USB_SEND(0x0220, 1); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 256); - USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 32); + USB_SEND (0x01, -1); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 38); + USB_SEND (0x1A, -1); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + usb_send (dev, RAW_DATA (vfs301_06_2), NULL); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + USB_SEND (0x0220, 1); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 256); + USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 32); - USB_SEND(0x1A, -1); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - usb_send(devh, RAW_DATA(vfs301_06_3)); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + USB_SEND (0x1A, -1); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + usb_send (dev, RAW_DATA (vfs301_06_3), NULL); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - USB_SEND(0x01, -1); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 38); - USB_SEND(0x02D0, 1); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 11648); /* 56 * vfs301_init_line_t[] */ - USB_SEND(0x02D0, 2); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 53248); /* 2 * 128 * vfs301_init_line_t[] */ - USB_SEND(0x02D0, 3); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 19968); /* 96 * vfs301_init_line_t[] */ - USB_SEND(0x02D0, 4); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 5824); /* 28 * vfs301_init_line_t[] */ - USB_SEND(0x02D0, 5); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 6656); /* 32 * vfs301_init_line_t[] */ - USB_SEND(0x02D0, 6); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 6656); /* 32 * vfs301_init_line_t[] */ - USB_SEND(0x02D0, 7); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 832); - usb_send(devh, RAW_DATA(vfs301_12)); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + USB_SEND (0x01, -1); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 38); + USB_SEND (0x02D0, 1); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 11648); /* 56 * vfs301_init_line_t[] */ + USB_SEND (0x02D0, 2); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 53248); /* 2 * 128 * vfs301_init_line_t[] */ + USB_SEND (0x02D0, 3); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 19968); /* 96 * vfs301_init_line_t[] */ + USB_SEND (0x02D0, 4); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 5824); /* 28 * vfs301_init_line_t[] */ + USB_SEND (0x02D0, 5); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 6656); /* 32 * vfs301_init_line_t[] */ + USB_SEND (0x02D0, 6); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 6656); /* 32 * vfs301_init_line_t[] */ + USB_SEND (0x02D0, 7); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 832); + usb_send (dev, RAW_DATA (vfs301_12), NULL); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - USB_SEND(0x1A, -1); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - usb_send(devh, RAW_DATA(vfs301_06_2)); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - USB_SEND(0x0220, 2); - VARIABLE_ORDER( - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2), /* 0000 */ - USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 5760) - ); + USB_SEND (0x1A, -1); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + usb_send (dev, RAW_DATA (vfs301_06_2), NULL); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + USB_SEND (0x0220, 2); + PARALLEL_RECEIVE ( + VFS301_RECEIVE_ENDPOINT_CTRL, 2, /* 0000 */ + VFS301_RECEIVE_ENDPOINT_DATA, 5760 + ); - USB_SEND(0x1A, -1); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - usb_send(devh, RAW_DATA(vfs301_06_1)); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + USB_SEND (0x1A, -1); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + usb_send (dev, RAW_DATA (vfs301_06_1), NULL); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - USB_SEND(0x1A, -1); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - usb_send(devh, RAW_DATA(vfs301_06_4)); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - usb_send(devh, RAW_DATA(vfs301_24)); /* turns on white */ - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + USB_SEND (0x1A, -1); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + usb_send (dev, RAW_DATA (vfs301_06_4), NULL); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ + usb_send (dev, RAW_DATA (vfs301_24), NULL); /* turns on white */ + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - USB_SEND(0x01, -1); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 38); - USB_SEND(0x0220, 3); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2368); - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 36); - USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 5760); + USB_SEND (0x01, -1); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 38); + USB_SEND (0x0220, 3); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2368); + USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 36); + USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 5760); } -void vfs301_proto_deinit(struct libusb_device_handle *devh, vfs301_dev_t *dev) +void +vfs301_proto_deinit (FpDeviceVfs301 *dev) { } diff --git a/libfprint/drivers/vfs301_proto.h b/libfprint/drivers/vfs301_proto.h deleted file mode 100644 index 2ae587a1..00000000 --- a/libfprint/drivers/vfs301_proto.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * vfs301/vfs300 fingerprint reader driver - * https://github.com/andree182/vfs301 - * - * Copyright (c) 2011-2012 Andrej Krutak - * - * 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 - -enum { - VFS301_DEFAULT_WAIT_TIMEOUT = 300, - - VFS301_SEND_ENDPOINT = 0x01, - VFS301_RECEIVE_ENDPOINT_CTRL = 0x81, - VFS301_RECEIVE_ENDPOINT_DATA = 0x82 -}; - -#define VFS301_FP_RECV_LEN_1 (84032) -#define VFS301_FP_RECV_LEN_2 (84096) - -typedef struct { - /* buffer for received data */ - unsigned char recv_buf[0x20000]; - int recv_len; - - /* buffer to hold raw scanlines */ - unsigned char *scanline_buf; - int scanline_count; - - enum { - VFS301_ONGOING = 0, - VFS301_ENDED = 1, - VFS301_FAILURE = -1 - } recv_progress; - int recv_exp_amt; -} vfs301_dev_t; - -enum { - /* Width of the scanned data in px */ - VFS301_FP_WIDTH = 200, - - /* sizeof(fp_line_t) */ - VFS301_FP_FRAME_SIZE = 288, - /* Width of output line */ -#ifndef OUTPUT_RAW - VFS301_FP_OUTPUT_WIDTH = VFS301_FP_WIDTH, -#else - VFS301_FP_OUTPUT_WIDTH = VFS301_FP_FRAME_SIZE, -#endif - - VFS301_FP_SUM_LINES = 3, - -#ifdef SCAN_FINISH_DETECTION - /* TODO: The following changes (seen ~60 and ~80) In that - * case we'll need to calibrate this from empty data somehow... */ - VFS301_FP_SUM_MEDIAN = 60, - VFS301_FP_SUM_EMPTY_RANGE = 5, -#endif - - /* Minimum average difference between returned lines */ - VFS301_FP_LINE_DIFF_THRESHOLD = 15, - - /* Maximum waiting time for a single fingerprint frame */ - VFS301_FP_RECV_TIMEOUT = 2000 -}; - -/* Arrays of this structure is returned during the initialization as a response - * to the 0x02D0 messages. - * It seems to be always the same - what is it for? Some kind of confirmation? - */ -typedef struct { - unsigned char sync_0x01; - unsigned char sync_0xfe; - - unsigned char counter_lo; - unsigned char counter_hi; /* FIXME ? */ - - unsigned char flags[3]; - - unsigned char sync_0x00; - - unsigned char scan[VFS301_FP_WIDTH]; -} vfs301_init_line_t; - -typedef struct { - unsigned char sync_0x01; - unsigned char sync_0xfe; - - unsigned char counter_lo; - unsigned char counter_hi; - - unsigned char sync_0x08[2]; /* XXX: always? 0x08 0x08 */ - /* 0x08 | 0x18 - Looks like 0x08 marks good quality lines */ - unsigned char flag_1; - unsigned char sync_0x00; - - unsigned char scan[VFS301_FP_WIDTH]; - - /* A offsetted, stretched, inverted copy of scan... probably could - * serve finger motion speed detection? - * Seems to be subdivided to some 10B + 53B + 1B blocks */ - unsigned char mirror[64]; - - /* Some kind of sum of the scan, very low contrast */ - unsigned char sum1[2]; - unsigned char sum2[11]; - unsigned char sum3[3]; -} vfs301_line_t; - -void vfs301_proto_init(struct libusb_device_handle *devh, vfs301_dev_t *dev); -void vfs301_proto_deinit(struct libusb_device_handle *devh, vfs301_dev_t *dev); - -void vfs301_proto_request_fingerprint( - struct libusb_device_handle *devh, vfs301_dev_t *dev); - -/** returns 0 if no event is ready, or 1 if there is one... */ -int vfs301_proto_peek_event( - struct libusb_device_handle *devh, vfs301_dev_t *dev); -void vfs301_proto_process_event_start( - struct libusb_device_handle *devh, vfs301_dev_t *dev); -int vfs301_proto_process_event_poll( - struct libusb_device_handle *devh, vfs301_dev_t *dev); - -void vfs301_extract_image(vfs301_dev_t *vfs, unsigned char *output, int *output_height); diff --git a/libfprint/drivers/vfs301_proto_fragments.h b/libfprint/drivers/vfs301_proto_fragments.h index 39441a13..6decbc79 100644 --- a/libfprint/drivers/vfs301_proto_fragments.h +++ b/libfprint/drivers/vfs301_proto_fragments.h @@ -26,1118 +26,1118 @@ * I missed some block start, or split data that should be together. * It's quite challenging, this reverse engineering... :-) */ -#define __01 0x88 /* sometimes also 0x87? depending on what? */ +#define __01 0x88 /* sometimes also 0x87? depending on what? */ static const unsigned char vfs301_06_1[] = { /* 2401 B */ - 0x06, 0x00, 0x00, 0x54, 0x09, 0x00, 0x0F, 0x00, 0x60, - 0xD8, 0x0C, 0x00, 0x60, - 0xD4, 0x0C, 0x00, 0x60, - 0x18, 0x17, 0x00, 0x60, - 0x28, 0x17, 0x00, 0x60, - 0xC8, 0x0D, 0x00, 0x60, - 0x9C, 0x0B, 0x00, 0x60, - 0xD8, 0x16, 0x00, 0x60, - 0xDC, 0x16, 0x00, 0x60, - 0x00, 0x0E, 0x04, 0x30, 0xE0, 0x0C, 0x00, 0x60, - 0x07, 0x09, 0x00, 0x00, 0xFF, 0xF7, 0xFF, 0xFF, 0xCC, 0x08, 0x00, 0x60, - 0x02, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x48, 0x0D, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0xE0, 0x16, 0x00, 0x60, - 0x00, 0x12, 0x04, 0x30, 0xA5, 0xC2, 0x00, 0x00, 0xE4, 0x16, 0x00, 0x60, - 0xF0, 0x16, 0x00, 0x60, - 0x00, 0x0F, 0x04, 0x30, 0xB0, 0x0A, 0x00, 0x60, - 0x58, 0xB3, 0x04, 0x60, - 0x84, 0x05, 0x00, 0x60, - 0xA4, 0xED, 0x04, 0x60, - 0x8C, 0x04, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x60, - 0x40, 0x08, 0x00, 0x00, 0x10, 0x03, 0x02, 0x28, 0x1C, 0x0E, 0x00, 0x60, - 0x30, 0x17, 0x00, 0x60, - 0x70, 0x0E, 0x00, 0x60, + 0x06, 0x00, 0x00, 0x54, 0x09, 0x00, 0x0F, 0x00, 0x60, + 0xD8, 0x0C, 0x00, 0x60, + 0xD4, 0x0C, 0x00, 0x60, + 0x18, 0x17, 0x00, 0x60, + 0x28, 0x17, 0x00, 0x60, + 0xC8, 0x0D, 0x00, 0x60, + 0x9C, 0x0B, 0x00, 0x60, + 0xD8, 0x16, 0x00, 0x60, + 0xDC, 0x16, 0x00, 0x60, + 0x00, 0x0E, 0x04, 0x30, 0xE0, 0x0C, 0x00, 0x60, + 0x07, 0x09, 0x00, 0x00, 0xFF, 0xF7, 0xFF, 0xFF, 0xCC, 0x08, 0x00, 0x60, + 0x02, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x48, 0x0D, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0xE0, 0x16, 0x00, 0x60, + 0x00, 0x12, 0x04, 0x30, 0xA5, 0xC2, 0x00, 0x00, 0xE4, 0x16, 0x00, 0x60, + 0xF0, 0x16, 0x00, 0x60, + 0x00, 0x0F, 0x04, 0x30, 0xB0, 0x0A, 0x00, 0x60, + 0x58, 0xB3, 0x04, 0x60, + 0x84, 0x05, 0x00, 0x60, + 0xA4, 0xED, 0x04, 0x60, + 0x8C, 0x04, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x60, + 0x40, 0x08, 0x00, 0x00, 0x10, 0x03, 0x02, 0x28, 0x1C, 0x0E, 0x00, 0x60, + 0x30, 0x17, 0x00, 0x60, + 0x70, 0x0E, 0x00, 0x60, - 0xFF, 0xFF, 0xFF, 0xBF, 0xFD, 0x0C, 0x00, - 0x60, 0xF8, 0x16, 0x00, 0x60, 0xA8, 0x0B, 0x00, - 0x60, 0x08, 0x17, 0x00, 0x60, 0x18, 0x0D, 0x00, - 0x60, 0x00, 0x9E, 0x00, 0x38, 0xDC, 0x0C, 0x00, - 0x60, 0x04, 0x17, 0x00, 0x60, 0x36, 0x41, 0x00, - 0xE5, 0x59, 0x00, 0xA5, 0x65, 0x00, 0xE5, 0x5C, - 0x00, 0x25, 0x66, 0x00, 0x25, 0x58, 0x00, 0x91, - 0xC0, 0x03, 0xA1, 0xC1, 0x03, 0x0C, 0x08, 0x89, - 0x0A, 0x82, 0x49, 0x00, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x36, 0x61, 0x00, 0x0C, 0x96, 0x91, 0xC2, - 0x03, 0xB1, 0xC3, 0x03, 0x71, 0xC4, 0x03, 0xD8, - 0x1B, 0x16, 0x84, 0x07, 0xC2, 0x0D, 0x4E, 0xC0, - 0xC0, 0x74, 0xE2, 0xA0, 0x71, 0x47, 0x3E, 0x05, - 0x16, 0xDC, 0x0F, 0x47, 0xBE, 0x02, 0x16, 0x4C, - 0x13, 0xF2, 0xA4, 0x6B, 0x26, 0x1C, 0x6E, 0x82, - 0xCC, 0xFE, 0x16, 0x88, 0x07, 0x16, 0x25, 0x05, - 0xC2, 0x0D, 0x4E, 0x16, 0x2C, 0x08, 0x92, 0xCC, - 0xFE, 0x16, 0x59, 0x08, 0x60, 0xAC, 0xC0, 0x16, - 0xAA, 0x10, 0xC2, 0x2D, 0x10, 0xC2, 0x0C, 0x00, - 0xA2, 0xA4, 0x6D, 0x66, 0x6C, 0x02, 0x06, 0x03, - 0x00, 0xAD, 0x0D, 0x65, 0x3B, 0x00, 0xD1, 0xC3, - 0x03, 0xD8, 0x1D, 0x16, 0xAA, 0x07, 0x0C, 0x9C, - 0xE8, 0x07, 0x62, 0x4D, 0x4E, 0xA2, 0x5E, 0x00, - 0xC0, 0xF0, 0x74, 0x60, 0xFF, 0xC0, 0x16, 0xBF, - 0x0D, 0x0C, 0x38, 0xA1, 0xC5, 0x03, 0x91, 0xC6, - 0x03, 0x99, 0x2A, 0x82, 0x4D, 0x4E, 0x0C, 0x2A, - 0xA5, 0xC6, 0x29, 0x1D, 0xF0, 0x16, 0xCD, 0x13, - 0xE8, 0x07, 0xC2, 0xA4, 0x70, 0xC2, 0x5E, 0x00, - 0xC2, 0x0D, 0x4E, 0x06, 0xDE, 0xFF, 0x16, 0xD3, - 0xF8, 0x0C, 0x9C, 0x88, 0x07, 0x62, 0x4D, 0x4E, - 0xF2, 0x58, 0x00, 0x06, 0xE0, 0xFF, 0xC2, 0x1D, - 0x24, 0x37, 0xBC, 0x34, 0x98, 0x07, 0x62, 0x4D, - 0x4E, 0xF2, 0x59, 0x00, 0x46, 0xDD, 0xFF, 0x00, - 0x00, 0x47, 0xBE, 0x02, 0x86, 0xDD, 0xFF, 0x46, - 0x01, 0x00, 0xA2, 0x1D, 0x24, 0x16, 0x3A, 0xF7, - 0xE8, 0x07, 0xC2, 0xA4, 0x6C, 0xC2, 0x5E, 0x00, - 0x62, 0x4D, 0x4E, 0x0C, 0x9C, 0xC6, 0xD8, 0xFF, - 0x00, 0xC2, 0x0D, 0x4E, 0x06, 0xE2, 0xFF, 0x00, - 0x00, 0x16, 0x83, 0xF4, 0xFD, 0x0C, 0xF9, 0x01, - 0xC7, 0xB3, 0x03, 0x8D, 0x03, 0x89, 0x01, 0xA8, - 0xFD, 0xBD, 0x02, 0xC2, 0x21, 0x00, 0xA5, 0x80, - 0x2D, 0xB1, 0xC3, 0x03, 0xD8, 0x1B, 0xA8, 0x01, - 0xC8, 0xFD, 0xAA, 0xCC, 0xC9, 0xFD, 0xD8, 0x1B, - 0x92, 0x1D, 0x24, 0xE2, 0xA0, 0x71, 0xA0, 0x99, - 0xC0, 0x92, 0x5D, 0x24, 0x46, 0xC5, 0xFF, 0x00, - 0x00, 0xF2, 0xA0, 0x72, 0x8D, 0x03, 0x89, 0x01, - 0x40, 0xFF, 0xC0, 0x37, 0xBF, 0x03, 0x8D, 0x0F, - 0x89, 0x01, 0xBD, 0x02, 0xA2, 0x2D, 0x11, 0xC8, - 0x01, 0x4A, 0xAA, 0xE5, 0x7C, 0x2D, 0xE2, 0xA0, - 0x71, 0xC8, 0x01, 0xB1, 0xC3, 0x03, 0xCA, 0x22, - 0xC0, 0x33, 0xC0, 0xD8, 0x1B, 0xCA, 0x44, 0xC2, - 0x0D, 0x4E, 0x46, 0xB3, 0xFF, 0xA1, 0xC2, 0x03, - 0xE5, 0x70, 0x2D, 0xC6, 0xC9, 0xFF, 0xA2, 0x2D, - 0x11, 0x0C, 0x1E, 0xE2, 0x4D, 0x4E, 0x25, 0x5E, - 0x2D, 0xC1, 0xC3, 0x03, 0xC8, 0x1C, 0xBD, 0x0A, - 0xA2, 0x2C, 0x11, 0xB9, 0xBC, 0x4B, 0xAA, 0x25, - 0x5D, 0x2D, 0xD1, 0xC3, 0x03, 0xD2, 0x2D, 0x01, - 0xA2, 0x6D, 0x0C, 0xA2, 0x2D, 0x11, 0x65, 0x2E, - 0x2D, 0xB1, 0xC3, 0x03, 0xD8, 0x1B, 0x0C, 0x0E, - 0xA8, 0xBD, 0xE2, 0x6D, 0x11, 0xAC, 0xCA, 0xE5, - 0x22, 0x2D, 0xB1, 0xC3, 0x03, 0xF8, 0x1B, 0xA2, - 0x6F, 0x10, 0xD8, 0x1B, 0x92, 0x2D, 0x10, 0x16, - 0xE9, 0x04, 0x0C, 0x2C, 0x99, 0xFD, 0xD8, 0x1B, - 0x0C, 0x2A, 0xA2, 0x4D, 0x4E, 0x88, 0xBD, 0x82, - 0x5D, 0x24, 0xE2, 0xA0, 0x71, 0xC0, 0xC0, 0x74, - 0x46, 0x99, 0xFF, 0x00, 0x00, 0xC2, 0x0D, 0x4E, - 0x86, 0xFB, 0xFF, 0x00, 0x00, 0xAD, 0x09, 0x25, - 0x65, 0x2D, 0xA2, 0xA0, 0x72, 0xE5, 0x1E, 0x2D, - 0xB1, 0xC3, 0x03, 0xD8, 0x1B, 0xA2, 0x6D, 0x11, - 0xCC, 0xEA, 0x0C, 0x9C, 0x62, 0x4D, 0x4E, 0x88, - 0x07, 0xF2, 0xA4, 0x6A, 0xF2, 0x58, 0x00, 0x06, - 0x89, 0xFF, 0xC2, 0x0D, 0x4E, 0x86, 0x87, 0xFF, - 0x00, 0x0C, 0x9C, 0x62, 0x4D, 0x4E, 0xA8, 0x07, - 0x92, 0xA4, 0x6F, 0x92, 0x5A, 0x00, 0x06, 0xEC, - 0xFF, 0x36, 0x41, 0x00, 0x42, 0xC2, 0x20, 0x82, - 0xC2, 0x14, 0x91, 0xC7, 0x03, 0x8B, 0xB2, 0x7C, - 0xF3, 0x39, 0xD2, 0x49, 0x92, 0x49, 0x82, 0x89, - 0x62, 0x89, 0x52, 0x99, 0x42, 0xB9, 0x32, 0xB9, - 0x22, 0xA2, 0xC9, 0xFC, 0xA9, 0x72, 0x1D, 0xF0, - 0x00, 0x36, 0x41, 0x00, 0xA2, 0x22, 0x10, 0x16, - 0x2A, 0x00, 0x25, 0x23, 0x2D, 0xA2, 0x22, 0x11, - 0x8C, 0x1A, 0xA5, 0x22, 0x2D, 0xA8, 0xD2, 0x26, - 0x0A, 0x02, 0xE5, 0x56, 0x21, 0x1D, 0xF0, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x20, 0xA2, 0x20, 0x65, - 0xA5, 0x2A, 0xA1, 0xC3, 0x03, 0xA2, 0x2A, 0x01, - 0xA2, 0xCA, 0x14, 0x65, 0x0E, 0x2D, 0xE5, 0x95, - 0x2A, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x31, 0xC3, 0x03, 0xC8, 0x13, 0x0C, 0x05, 0x92, - 0x0C, 0x4E, 0x41, 0xC8, 0x03, 0x82, 0xC9, 0xFD, - 0x16, 0x68, 0x0B, 0x26, 0x49, 0x14, 0x21, 0xC9, - 0x03, 0x26, 0x59, 0x10, 0xA2, 0xC9, 0xFA, 0x16, - 0xFA, 0x07, 0xB2, 0xC9, 0xF9, 0x16, 0x4B, 0x0D, - 0x26, 0x89, 0x49, 0x1D, 0xF0, 0xA2, 0x2C, 0x10, - 0xE8, 0x12, 0xD8, 0x22, 0xD9, 0x03, 0xE2, 0x62, - 0x02, 0x16, 0x9A, 0x00, 0x25, 0x1C, 0x2D, 0xF8, - 0x13, 0x52, 0x6F, 0x10, 0xC8, 0x13, 0xC0, 0x20, - 0x00, 0xB2, 0xA2, 0x00, 0x81, 0xCA, 0x03, 0x82, - 0x64, 0x83, 0xA8, 0xCC, 0xA9, 0xEC, 0xE5, 0xA5, - 0x24, 0xA8, 0x13, 0x0C, 0x69, 0x92, 0x4A, 0x4E, - 0xA2, 0xA2, 0x00, 0xE5, 0x86, 0x2A, 0xA8, 0x13, - 0x8B, 0xAA, 0xA5, 0x0A, 0x00, 0xC0, 0x20, 0x00, - 0x52, 0x64, 0x80, 0x1D, 0xF0, 0xC0, 0x20, 0x00, - 0xC1, 0xCB, 0x03, 0xB2, 0x24, 0x83, 0xC0, 0x20, - 0x00, 0xC0, 0xBB, 0x10, 0xB2, 0x64, 0x83, 0x65, - 0xD5, 0x2A, 0xA8, 0x13, 0x8B, 0xAA, 0xE5, 0x06, - 0x2D, 0xA1, 0xC2, 0x03, 0x25, 0x56, 0x2D, 0x98, - 0x03, 0x16, 0xE9, 0xF8, 0x99, 0x22, 0x59, 0x03, - 0x1D, 0xF0, 0xA2, 0xCC, 0x20, 0xA5, 0x92, 0x2A, - 0x16, 0xFA, 0xF7, 0x22, 0xA0, 0x07, 0xB2, 0x0A, - 0x2C, 0xC2, 0x23, 0x01, 0x07, 0x6B, 0x02, 0x22, - 0x4C, 0x4E, 0x65, 0xA4, 0x24, 0xA8, 0x13, 0xA2, - 0xCA, 0x20, 0xE5, 0x90, 0x2A, 0x56, 0x5A, 0xFE, - 0x1D, 0xF0, 0x52, 0x63, 0x00, 0xA1, 0xCD, 0x03, - 0xB1, 0xCC, 0x03, 0xB2, 0x62, 0x02, 0x65, 0xB5, - 0x2A, 0xC0, 0x20, 0x00, 0x0C, 0x4C, 0xE1, 0xCE, - 0x03, 0xD2, 0x24, 0x83, 0xC0, 0x20, 0x00, 0xA8, - 0x13, 0xE0, 0xDD, 0x20, 0xD2, 0x64, 0x83, 0xC2, - 0x4A, 0x4E, 0xE5, 0x0C, 0x00, 0xAD, 0x02, 0xA5, - 0x9A, 0x29, 0x1D, 0xF0, 0x00, 0xA1, 0xCF, 0x03, - 0x25, 0x52, 0x2D, 0xC0, 0x20, 0x00, 0xA8, 0x13, - 0xF1, 0xD0, 0x03, 0xF2, 0x64, 0x83, 0x65, 0x1B, - 0x00, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x31, 0xC3, 0x03, 0x82, 0x23, 0x01, 0x71, 0xD1, - 0x03, 0x82, 0x28, 0x0E, 0x62, 0xA0, 0x00, 0x16, - 0x68, 0x05, 0xE5, 0x76, 0x2A, 0x4D, 0x0A, 0x16, - 0x2A, 0x05, 0xA8, 0x13, 0x52, 0x14, 0x15, 0xA8, - 0xEA, 0x57, 0xBA, 0x01, 0x5D, 0x0A, 0xB1, 0xD2, - 0x03, 0xC8, 0x24, 0x0C, 0x0D, 0xF1, 0xD3, 0x03, - 0x50, 0xE0, 0xF4, 0xE2, 0x54, 0x14, 0x52, 0xC4, - 0x10, 0xAD, 0x05, 0xE5, 0x81, 0x21, 0x62, 0x44, - 0x2C, 0xD8, 0x13, 0xC2, 0x14, 0x14, 0xB8, 0xED, - 0xC0, 0xBB, 0xC0, 0xB9, 0xED, 0xCC, 0x8B, 0x79, - 0x34, 0x0C, 0x1D, 0xD2, 0x44, 0x2C, 0xD2, 0x23, - 0x01, 0xAD, 0x05, 0xB8, 0xDD, 0x0C, 0x1C, 0x25, - 0xAD, 0x21, 0xE8, 0x13, 0xE8, 0xEE, 0x56, 0x8E, - 0xFA, 0x1D, 0xF0, 0x00, 0x00, 0xAD, 0x02, 0x65, - 0x72, 0x2A, 0x1D, 0xF0, 0x00, 0x36, 0x41, 0x00, - 0xB2, 0xC2, 0xF0, 0xA2, 0xC3, 0x20, 0xA5, 0x7F, - 0x2A, 0xA2, 0xC3, 0x14, 0xE5, 0xF3, 0x2C, 0x1D, - 0xF0, 0x36, 0x41, 0x00, 0x0C, 0x0A, 0xBD, 0x02, - 0xC1, 0xD4, 0x03, 0x65, 0x9B, 0x21, 0xA9, 0xD2, - 0x26, 0x0A, 0x05, 0x0C, 0x02, 0x1D, 0xF0, 0x00, - 0x00, 0x22, 0xA4, 0x6E, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x36, 0x41, 0x00, 0xA2, 0xA0, 0x03, 0xB1, - 0xD5, 0x03, 0xE5, 0xEA, 0x2C, 0x92, 0xA0, 0x60, - 0x81, 0xC8, 0x03, 0xB8, 0xB2, 0xA2, 0x22, 0x10, - 0xA9, 0xF2, 0xB2, 0x52, 0x26, 0xB2, 0x52, 0x25, - 0x0C, 0x8B, 0xC0, 0x20, 0x00, 0xF2, 0x28, 0x81, - 0xC0, 0x20, 0x00, 0xE8, 0xF2, 0x90, 0xFF, 0x20, - 0xF2, 0x68, 0x81, 0xE2, 0x0E, 0x00, 0xC0, 0x20, - 0x00, 0xC8, 0xF2, 0xF1, 0xD6, 0x03, 0x1B, 0xCC, - 0xE2, 0x5F, 0x80, 0xD2, 0x12, 0x25, 0xC9, 0xF2, - 0x0B, 0xDD, 0xD2, 0x52, 0x25, 0x80, 0x61, 0x00, - 0x9D, 0x08, 0xA0, 0xE4, 0x03, 0xB0, 0xAA, 0x20, - 0xA0, 0xE4, 0x13, 0x80, 0xE6, 0x13, 0x10, 0x20, - 0x00, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x61, 0x00, - 0xC0, 0x20, 0x00, 0xC1, 0xD6, 0x03, 0xF1, 0xC8, - 0x03, 0xE1, 0xC3, 0x03, 0xA2, 0x2F, 0x82, 0xB8, - 0x1E, 0x17, 0x6A, 0x14, 0x92, 0x1B, 0x26, 0x16, - 0xE9, 0x00, 0x82, 0xC9, 0xFF, 0xC0, 0x20, 0x00, - 0xD2, 0x1C, 0x80, 0xD2, 0x51, 0x00, 0x82, 0x5B, - 0x26, 0x92, 0x1B, 0x25, 0x07, 0xEA, 0x07, 0x8C, - 0xA9, 0x82, 0x0B, 0x4E, 0x26, 0x48, 0x41, 0x8C, - 0x29, 0x1D, 0xF0, 0x00, 0x00, 0x92, 0x1B, 0x26, - 0x56, 0x59, 0xFF, 0xC0, 0x20, 0x00, 0x0C, 0x5D, - 0x92, 0xAF, 0x9F, 0x82, 0x2F, 0x81, 0xC0, 0x20, - 0x00, 0x90, 0x88, 0x10, 0x82, 0x6F, 0x81, 0x7C, - 0x7F, 0xA0, 0x61, 0x00, 0xCD, 0x0A, 0xE0, 0xE4, - 0x03, 0xF0, 0xEE, 0x10, 0xE0, 0xE4, 0x13, 0xA0, - 0xE6, 0x13, 0x10, 0x20, 0x00, 0xD2, 0x4B, 0x4E, - 0xA2, 0xCB, 0x14, 0xE5, 0xE3, 0x2C, 0x1D, 0xF0, - 0x00, 0xD8, 0xFB, 0xD2, 0x0D, 0x00, 0xC0, 0x20, - 0x00, 0xA8, 0xFB, 0xD2, 0x5C, 0x80, 0x1B, 0xAA, - 0xA9, 0xFB, 0xB8, 0x1E, 0x92, 0x1B, 0x25, 0x0B, - 0x99, 0x90, 0x90, 0xF4, 0x92, 0x5B, 0x25, 0x06, - 0xE7, 0xFF, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x92, 0xA0, 0x06, 0xB1, 0xC8, 0x03, 0xC0, 0x20, - 0x00, 0x82, 0x2B, 0x82, 0x0C, 0x0A, 0x17, 0x68, - 0x0B, 0x92, 0xC9, 0xFF, 0xC0, 0x20, 0x00, 0xC2, - 0x2B, 0x80, 0x56, 0x89, 0xFE, 0xC0, 0x20, 0x00, - 0xA2, 0xC2, 0x14, 0x0C, 0x8D, 0xE2, 0xA0, 0x04, - 0xE2, 0x6B, 0x84, 0xD2, 0x42, 0x4E, 0x25, 0xDE, - 0x2C, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x31, 0xD7, 0x03, 0x21, 0xD8, 0x03, 0x22, 0x63, - 0x75, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, - 0xA1, 0xD9, 0x03, 0xB1, 0xDA, 0x03, 0xC1, 0xDB, - 0x03, 0xE5, 0x37, 0x2D, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x16, 0xA5, 0x01, 0x20, - 0x61, 0x00, 0x25, 0xA4, 0xFF, 0x20, 0xE6, 0x13, - 0x10, 0x20, 0x00, 0xA2, 0xA0, 0x00, 0x65, 0x72, - 0x29, 0xA1, 0xDC, 0x03, 0xB1, 0xDD, 0x03, 0xE5, - 0xFF, 0x2C, 0x1D, 0xF0, 0x00, 0x36, 0x41, 0x00, - 0xA1, 0xDE, 0x03, 0xB1, 0xDE, 0x03, 0x65, 0xFC, - 0x20, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, - 0xCD, 0x04, 0x81, 0xDF, 0x03, 0xBD, 0x03, 0x88, - 0x08, 0xAD, 0x02, 0xCC, 0xF8, 0x8C, 0xD3, 0xD1, - 0xC9, 0x03, 0xF1, 0xE0, 0x03, 0x98, 0x1D, 0xE8, - 0x2D, 0xE9, 0x0F, 0x92, 0x6D, 0x02, 0xE5, 0x65, - 0x29, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, - 0xC1, 0xE0, 0x03, 0xAD, 0x02, 0x98, 0x0C, 0x0C, - 0x0B, 0x8C, 0x59, 0x81, 0xC9, 0x03, 0xB9, 0x0C, - 0x99, 0x28, 0xE5, 0x70, 0x29, 0x1D, 0xF0, 0x00, - 0x00, 0x36, 0x41, 0x00, 0xD1, 0xE2, 0x03, 0x91, - 0xE3, 0x03, 0xB0, 0x82, 0x11, 0xA1, 0xE1, 0x03, - 0xB2, 0xAE, 0xF0, 0xBA, 0xAA, 0xAA, 0xA8, 0x9A, - 0x88, 0xC8, 0x0A, 0xC0, 0x20, 0x00, 0xB8, 0x7C, - 0xC0, 0x20, 0x00, 0xD0, 0xBB, 0x10, 0xB9, 0x7C, - 0x82, 0x08, 0x7F, 0x0C, 0x09, 0x8C, 0x18, 0xE5, - 0x5B, 0x21, 0x1D, 0xF0, 0x00, 0x36, 0x41, 0x00, - 0x21, 0xE4, 0x03, 0x31, 0xE5, 0x03, 0x28, 0x22, - 0x29, 0x03, 0x1D, 0xF0, 0x00, 0x36, 0x41, 0x00, - 0x21, 0xE6, 0x03, 0x88, 0x02, 0x27, 0x98, 0x02, - 0x1D, 0xF0, 0x00, 0x20, 0xA2, 0x20, 0x25, 0x08, - 0x00, 0xAD, 0x02, 0xE5, 0xC5, 0x20, 0x1D, 0xF0, - 0x00, 0x36, 0x41, 0x00, 0x20, 0x61, 0x00, 0xA1, - 0xE6, 0x03, 0xE5, 0xC4, 0x20, 0xA5, 0x0B, 0x24, - 0x20, 0xE6, 0x13, 0x10, 0x20, 0x00, 0x1D, 0xF0, - 0x00, 0x36, 0x41, 0x00, 0x41, 0xE7, 0x03, 0x21, - 0xE8, 0x03, 0xC0, 0x20, 0x00, 0x32, 0x22, 0x81, - 0x98, 0x54, 0x88, 0x34, 0x30, 0x99, 0x20, 0x99, - 0x54, 0x87, 0x83, 0x39, 0x0C, 0x1C, 0xB2, 0xA0, - 0x38, 0xA2, 0x24, 0x04, 0xC0, 0x20, 0x00, 0xB0, - 0xAA, 0x10, 0xA2, 0x62, 0x80, 0xC0, 0x20, 0x00, - 0xD2, 0x22, 0x81, 0xD0, 0xE0, 0x04, 0x07, 0xED, - 0xF3, 0xC0, 0x20, 0x00, 0xB1, 0xE9, 0x03, 0x32, - 0x62, 0x81, 0xC0, 0x20, 0x00, 0xB8, 0x0B, 0xA1, - 0xEA, 0x03, 0x1B, 0xBB, 0xB9, 0x4A, 0x4B, 0xAA, - 0xA5, 0xBD, 0x20, 0x1D, 0xF0, 0x00, 0x0C, 0x0C, - 0xC9, 0x34, 0xE5, 0xC4, 0x21, 0xC6, 0xEE, 0xFF, - 0x00, 0x36, 0x41, 0x00, 0x20, 0x61, 0x00, 0x3C, - 0x8A, 0x0C, 0x0B, 0x65, 0x08, 0x24, 0x20, 0xE6, - 0x13, 0x10, 0x20, 0x00, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x1F, 0x00, 0x00, 0x00, 0xD0, 0x0F, 0x02, - 0x60, 0xD8, 0x11, 0x02, 0x60, 0x00, 0x12, 0x02, - 0x60, 0x3C, 0x12, 0x02, 0x60, 0x54, 0x13, 0x02, - 0x60, 0x20, 0x12, 0x02, 0x60, 0xCC, 0x13, 0x02, - 0x60, 0xE0, 0x13, 0x02, 0x60, 0x00, 0x14, 0x02, - 0x60, 0x64, 0x14, 0x02, 0x60, 0x04, 0x15, 0x02, - 0x60, 0xC8, 0x16, 0x00, 0x60, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x16, 0x02, - 0x60, 0x08, 0x17, 0x00, 0x60, 0x08, 0x17, 0x00, - 0x60, 0x04, 0x17, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x00, 0xD0, 0x16, 0x00, 0x60, 0xD4, 0x16, 0x00, - 0x60, 0x2C, 0x17, 0x00, 0x60, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x0C, 0x00, - 0x60, 0xD4, 0x0C, 0x00, 0x60, 0x19, 0x30, 0x00, - 0x00, 0x40, 0x17, 0x00, 0x60, 0x10, 0x01, 0x00, - 0x00, 0xB0, 0x0A, 0x00, 0x60, 0x60, 0x15, 0x02, - 0x60, 0x34, 0x0D, 0x00, 0x60, 0x10, 0x03, 0x02, - 0x28, 0x18, 0x00, 0x02, 0x28, 0x14, 0x03, 0x02, - 0x28, 0xBC, 0x08, 0x00, 0x60, 0x94, 0x15, 0x02, - 0x60, 0xBC, 0x15, 0x02, 0x60, 0xA4, 0x05, 0x00, - 0x60, 0xD8, 0x15, 0x02, 0x60, 0xA8, 0x0B, 0x00, - 0x60, 0xF8, 0x16, 0x00, 0x60, 0xAC, 0x06, 0x00, - 0x60, 0x38, 0x16, 0x02, 0x60, 0x50, 0x16, 0x02, - 0x60, 0xD8, 0x56, 0x04, 0x60, 0x36, 0x41, 0x00, - 0x81, 0xCF, 0x05, 0xB1, 0xCD, 0x05, 0xA2, 0xA0, - 0x03, 0x91, 0xCE, 0x05, 0xA2, 0x4B, 0x00, 0x82, - 0x69, 0x00, 0xE5, 0x01, 0x00, 0xA5, 0x08, 0x00, - 0x25, 0x05, 0x00, 0x25, 0x06, 0x00, 0x25, 0x02, - 0x00, 0xA5, 0x06, 0x00, 0xA1, 0xD0, 0x05, 0xB1, - 0xD1, 0x05, 0x25, 0xDC, 0x2C, 0x1D, 0xF0, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x31, 0xD2, 0x05, 0x21, - 0xD3, 0x05, 0x22, 0x63, 0x75, 0x1D, 0xF0, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x91, 0xD4, 0x05, 0x92, - 0x09, 0x47, 0x26, 0x19, 0x04, 0x26, 0x29, 0x0C, - 0x1D, 0xF0, 0xA1, 0xD5, 0x05, 0xB1, 0xD6, 0x05, - 0xE5, 0xD6, 0x20, 0x1D, 0xF0, 0xA1, 0xD5, 0x05, - 0xB1, 0xD7, 0x05, 0x25, 0xD6, 0x20, 0x1D, 0xF0, - 0x00, 0x36, 0x41, 0x00, 0x81, 0xD9, 0x05, 0x31, - 0xD8, 0x05, 0x21, 0xDA, 0x05, 0x29, 0x43, 0x89, - 0x03, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x31, 0xDB, 0x05, 0x21, 0xDC, 0x05, 0x22, 0x63, - 0x13, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x31, 0xDD, 0x05, 0x21, 0xDE, 0x05, 0x48, 0x03, - 0x49, 0x22, 0x29, 0x03, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x91, 0xE0, 0x05, 0x21, - 0xE2, 0x05, 0x31, 0xDF, 0x05, 0x81, 0xE1, 0x05, - 0x89, 0xC3, 0x29, 0xA3, 0x99, 0xB3, 0x1D, 0xF0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x04, 0x00, 0x8C, 0x17, 0x02, - 0x60, + 0xFF, 0xFF, 0xFF, 0xBF, 0xFD, 0x0C, 0x00, + 0x60, 0xF8, 0x16, 0x00, 0x60, 0xA8, 0x0B, 0x00, + 0x60, 0x08, 0x17, 0x00, 0x60, 0x18, 0x0D, 0x00, + 0x60, 0x00, 0x9E, 0x00, 0x38, 0xDC, 0x0C, 0x00, + 0x60, 0x04, 0x17, 0x00, 0x60, 0x36, 0x41, 0x00, + 0xE5, 0x59, 0x00, 0xA5, 0x65, 0x00, 0xE5, 0x5C, + 0x00, 0x25, 0x66, 0x00, 0x25, 0x58, 0x00, 0x91, + 0xC0, 0x03, 0xA1, 0xC1, 0x03, 0x0C, 0x08, 0x89, + 0x0A, 0x82, 0x49, 0x00, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x36, 0x61, 0x00, 0x0C, 0x96, 0x91, 0xC2, + 0x03, 0xB1, 0xC3, 0x03, 0x71, 0xC4, 0x03, 0xD8, + 0x1B, 0x16, 0x84, 0x07, 0xC2, 0x0D, 0x4E, 0xC0, + 0xC0, 0x74, 0xE2, 0xA0, 0x71, 0x47, 0x3E, 0x05, + 0x16, 0xDC, 0x0F, 0x47, 0xBE, 0x02, 0x16, 0x4C, + 0x13, 0xF2, 0xA4, 0x6B, 0x26, 0x1C, 0x6E, 0x82, + 0xCC, 0xFE, 0x16, 0x88, 0x07, 0x16, 0x25, 0x05, + 0xC2, 0x0D, 0x4E, 0x16, 0x2C, 0x08, 0x92, 0xCC, + 0xFE, 0x16, 0x59, 0x08, 0x60, 0xAC, 0xC0, 0x16, + 0xAA, 0x10, 0xC2, 0x2D, 0x10, 0xC2, 0x0C, 0x00, + 0xA2, 0xA4, 0x6D, 0x66, 0x6C, 0x02, 0x06, 0x03, + 0x00, 0xAD, 0x0D, 0x65, 0x3B, 0x00, 0xD1, 0xC3, + 0x03, 0xD8, 0x1D, 0x16, 0xAA, 0x07, 0x0C, 0x9C, + 0xE8, 0x07, 0x62, 0x4D, 0x4E, 0xA2, 0x5E, 0x00, + 0xC0, 0xF0, 0x74, 0x60, 0xFF, 0xC0, 0x16, 0xBF, + 0x0D, 0x0C, 0x38, 0xA1, 0xC5, 0x03, 0x91, 0xC6, + 0x03, 0x99, 0x2A, 0x82, 0x4D, 0x4E, 0x0C, 0x2A, + 0xA5, 0xC6, 0x29, 0x1D, 0xF0, 0x16, 0xCD, 0x13, + 0xE8, 0x07, 0xC2, 0xA4, 0x70, 0xC2, 0x5E, 0x00, + 0xC2, 0x0D, 0x4E, 0x06, 0xDE, 0xFF, 0x16, 0xD3, + 0xF8, 0x0C, 0x9C, 0x88, 0x07, 0x62, 0x4D, 0x4E, + 0xF2, 0x58, 0x00, 0x06, 0xE0, 0xFF, 0xC2, 0x1D, + 0x24, 0x37, 0xBC, 0x34, 0x98, 0x07, 0x62, 0x4D, + 0x4E, 0xF2, 0x59, 0x00, 0x46, 0xDD, 0xFF, 0x00, + 0x00, 0x47, 0xBE, 0x02, 0x86, 0xDD, 0xFF, 0x46, + 0x01, 0x00, 0xA2, 0x1D, 0x24, 0x16, 0x3A, 0xF7, + 0xE8, 0x07, 0xC2, 0xA4, 0x6C, 0xC2, 0x5E, 0x00, + 0x62, 0x4D, 0x4E, 0x0C, 0x9C, 0xC6, 0xD8, 0xFF, + 0x00, 0xC2, 0x0D, 0x4E, 0x06, 0xE2, 0xFF, 0x00, + 0x00, 0x16, 0x83, 0xF4, 0xFD, 0x0C, 0xF9, 0x01, + 0xC7, 0xB3, 0x03, 0x8D, 0x03, 0x89, 0x01, 0xA8, + 0xFD, 0xBD, 0x02, 0xC2, 0x21, 0x00, 0xA5, 0x80, + 0x2D, 0xB1, 0xC3, 0x03, 0xD8, 0x1B, 0xA8, 0x01, + 0xC8, 0xFD, 0xAA, 0xCC, 0xC9, 0xFD, 0xD8, 0x1B, + 0x92, 0x1D, 0x24, 0xE2, 0xA0, 0x71, 0xA0, 0x99, + 0xC0, 0x92, 0x5D, 0x24, 0x46, 0xC5, 0xFF, 0x00, + 0x00, 0xF2, 0xA0, 0x72, 0x8D, 0x03, 0x89, 0x01, + 0x40, 0xFF, 0xC0, 0x37, 0xBF, 0x03, 0x8D, 0x0F, + 0x89, 0x01, 0xBD, 0x02, 0xA2, 0x2D, 0x11, 0xC8, + 0x01, 0x4A, 0xAA, 0xE5, 0x7C, 0x2D, 0xE2, 0xA0, + 0x71, 0xC8, 0x01, 0xB1, 0xC3, 0x03, 0xCA, 0x22, + 0xC0, 0x33, 0xC0, 0xD8, 0x1B, 0xCA, 0x44, 0xC2, + 0x0D, 0x4E, 0x46, 0xB3, 0xFF, 0xA1, 0xC2, 0x03, + 0xE5, 0x70, 0x2D, 0xC6, 0xC9, 0xFF, 0xA2, 0x2D, + 0x11, 0x0C, 0x1E, 0xE2, 0x4D, 0x4E, 0x25, 0x5E, + 0x2D, 0xC1, 0xC3, 0x03, 0xC8, 0x1C, 0xBD, 0x0A, + 0xA2, 0x2C, 0x11, 0xB9, 0xBC, 0x4B, 0xAA, 0x25, + 0x5D, 0x2D, 0xD1, 0xC3, 0x03, 0xD2, 0x2D, 0x01, + 0xA2, 0x6D, 0x0C, 0xA2, 0x2D, 0x11, 0x65, 0x2E, + 0x2D, 0xB1, 0xC3, 0x03, 0xD8, 0x1B, 0x0C, 0x0E, + 0xA8, 0xBD, 0xE2, 0x6D, 0x11, 0xAC, 0xCA, 0xE5, + 0x22, 0x2D, 0xB1, 0xC3, 0x03, 0xF8, 0x1B, 0xA2, + 0x6F, 0x10, 0xD8, 0x1B, 0x92, 0x2D, 0x10, 0x16, + 0xE9, 0x04, 0x0C, 0x2C, 0x99, 0xFD, 0xD8, 0x1B, + 0x0C, 0x2A, 0xA2, 0x4D, 0x4E, 0x88, 0xBD, 0x82, + 0x5D, 0x24, 0xE2, 0xA0, 0x71, 0xC0, 0xC0, 0x74, + 0x46, 0x99, 0xFF, 0x00, 0x00, 0xC2, 0x0D, 0x4E, + 0x86, 0xFB, 0xFF, 0x00, 0x00, 0xAD, 0x09, 0x25, + 0x65, 0x2D, 0xA2, 0xA0, 0x72, 0xE5, 0x1E, 0x2D, + 0xB1, 0xC3, 0x03, 0xD8, 0x1B, 0xA2, 0x6D, 0x11, + 0xCC, 0xEA, 0x0C, 0x9C, 0x62, 0x4D, 0x4E, 0x88, + 0x07, 0xF2, 0xA4, 0x6A, 0xF2, 0x58, 0x00, 0x06, + 0x89, 0xFF, 0xC2, 0x0D, 0x4E, 0x86, 0x87, 0xFF, + 0x00, 0x0C, 0x9C, 0x62, 0x4D, 0x4E, 0xA8, 0x07, + 0x92, 0xA4, 0x6F, 0x92, 0x5A, 0x00, 0x06, 0xEC, + 0xFF, 0x36, 0x41, 0x00, 0x42, 0xC2, 0x20, 0x82, + 0xC2, 0x14, 0x91, 0xC7, 0x03, 0x8B, 0xB2, 0x7C, + 0xF3, 0x39, 0xD2, 0x49, 0x92, 0x49, 0x82, 0x89, + 0x62, 0x89, 0x52, 0x99, 0x42, 0xB9, 0x32, 0xB9, + 0x22, 0xA2, 0xC9, 0xFC, 0xA9, 0x72, 0x1D, 0xF0, + 0x00, 0x36, 0x41, 0x00, 0xA2, 0x22, 0x10, 0x16, + 0x2A, 0x00, 0x25, 0x23, 0x2D, 0xA2, 0x22, 0x11, + 0x8C, 0x1A, 0xA5, 0x22, 0x2D, 0xA8, 0xD2, 0x26, + 0x0A, 0x02, 0xE5, 0x56, 0x21, 0x1D, 0xF0, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x20, 0xA2, 0x20, 0x65, + 0xA5, 0x2A, 0xA1, 0xC3, 0x03, 0xA2, 0x2A, 0x01, + 0xA2, 0xCA, 0x14, 0x65, 0x0E, 0x2D, 0xE5, 0x95, + 0x2A, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x31, 0xC3, 0x03, 0xC8, 0x13, 0x0C, 0x05, 0x92, + 0x0C, 0x4E, 0x41, 0xC8, 0x03, 0x82, 0xC9, 0xFD, + 0x16, 0x68, 0x0B, 0x26, 0x49, 0x14, 0x21, 0xC9, + 0x03, 0x26, 0x59, 0x10, 0xA2, 0xC9, 0xFA, 0x16, + 0xFA, 0x07, 0xB2, 0xC9, 0xF9, 0x16, 0x4B, 0x0D, + 0x26, 0x89, 0x49, 0x1D, 0xF0, 0xA2, 0x2C, 0x10, + 0xE8, 0x12, 0xD8, 0x22, 0xD9, 0x03, 0xE2, 0x62, + 0x02, 0x16, 0x9A, 0x00, 0x25, 0x1C, 0x2D, 0xF8, + 0x13, 0x52, 0x6F, 0x10, 0xC8, 0x13, 0xC0, 0x20, + 0x00, 0xB2, 0xA2, 0x00, 0x81, 0xCA, 0x03, 0x82, + 0x64, 0x83, 0xA8, 0xCC, 0xA9, 0xEC, 0xE5, 0xA5, + 0x24, 0xA8, 0x13, 0x0C, 0x69, 0x92, 0x4A, 0x4E, + 0xA2, 0xA2, 0x00, 0xE5, 0x86, 0x2A, 0xA8, 0x13, + 0x8B, 0xAA, 0xA5, 0x0A, 0x00, 0xC0, 0x20, 0x00, + 0x52, 0x64, 0x80, 0x1D, 0xF0, 0xC0, 0x20, 0x00, + 0xC1, 0xCB, 0x03, 0xB2, 0x24, 0x83, 0xC0, 0x20, + 0x00, 0xC0, 0xBB, 0x10, 0xB2, 0x64, 0x83, 0x65, + 0xD5, 0x2A, 0xA8, 0x13, 0x8B, 0xAA, 0xE5, 0x06, + 0x2D, 0xA1, 0xC2, 0x03, 0x25, 0x56, 0x2D, 0x98, + 0x03, 0x16, 0xE9, 0xF8, 0x99, 0x22, 0x59, 0x03, + 0x1D, 0xF0, 0xA2, 0xCC, 0x20, 0xA5, 0x92, 0x2A, + 0x16, 0xFA, 0xF7, 0x22, 0xA0, 0x07, 0xB2, 0x0A, + 0x2C, 0xC2, 0x23, 0x01, 0x07, 0x6B, 0x02, 0x22, + 0x4C, 0x4E, 0x65, 0xA4, 0x24, 0xA8, 0x13, 0xA2, + 0xCA, 0x20, 0xE5, 0x90, 0x2A, 0x56, 0x5A, 0xFE, + 0x1D, 0xF0, 0x52, 0x63, 0x00, 0xA1, 0xCD, 0x03, + 0xB1, 0xCC, 0x03, 0xB2, 0x62, 0x02, 0x65, 0xB5, + 0x2A, 0xC0, 0x20, 0x00, 0x0C, 0x4C, 0xE1, 0xCE, + 0x03, 0xD2, 0x24, 0x83, 0xC0, 0x20, 0x00, 0xA8, + 0x13, 0xE0, 0xDD, 0x20, 0xD2, 0x64, 0x83, 0xC2, + 0x4A, 0x4E, 0xE5, 0x0C, 0x00, 0xAD, 0x02, 0xA5, + 0x9A, 0x29, 0x1D, 0xF0, 0x00, 0xA1, 0xCF, 0x03, + 0x25, 0x52, 0x2D, 0xC0, 0x20, 0x00, 0xA8, 0x13, + 0xF1, 0xD0, 0x03, 0xF2, 0x64, 0x83, 0x65, 0x1B, + 0x00, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x31, 0xC3, 0x03, 0x82, 0x23, 0x01, 0x71, 0xD1, + 0x03, 0x82, 0x28, 0x0E, 0x62, 0xA0, 0x00, 0x16, + 0x68, 0x05, 0xE5, 0x76, 0x2A, 0x4D, 0x0A, 0x16, + 0x2A, 0x05, 0xA8, 0x13, 0x52, 0x14, 0x15, 0xA8, + 0xEA, 0x57, 0xBA, 0x01, 0x5D, 0x0A, 0xB1, 0xD2, + 0x03, 0xC8, 0x24, 0x0C, 0x0D, 0xF1, 0xD3, 0x03, + 0x50, 0xE0, 0xF4, 0xE2, 0x54, 0x14, 0x52, 0xC4, + 0x10, 0xAD, 0x05, 0xE5, 0x81, 0x21, 0x62, 0x44, + 0x2C, 0xD8, 0x13, 0xC2, 0x14, 0x14, 0xB8, 0xED, + 0xC0, 0xBB, 0xC0, 0xB9, 0xED, 0xCC, 0x8B, 0x79, + 0x34, 0x0C, 0x1D, 0xD2, 0x44, 0x2C, 0xD2, 0x23, + 0x01, 0xAD, 0x05, 0xB8, 0xDD, 0x0C, 0x1C, 0x25, + 0xAD, 0x21, 0xE8, 0x13, 0xE8, 0xEE, 0x56, 0x8E, + 0xFA, 0x1D, 0xF0, 0x00, 0x00, 0xAD, 0x02, 0x65, + 0x72, 0x2A, 0x1D, 0xF0, 0x00, 0x36, 0x41, 0x00, + 0xB2, 0xC2, 0xF0, 0xA2, 0xC3, 0x20, 0xA5, 0x7F, + 0x2A, 0xA2, 0xC3, 0x14, 0xE5, 0xF3, 0x2C, 0x1D, + 0xF0, 0x36, 0x41, 0x00, 0x0C, 0x0A, 0xBD, 0x02, + 0xC1, 0xD4, 0x03, 0x65, 0x9B, 0x21, 0xA9, 0xD2, + 0x26, 0x0A, 0x05, 0x0C, 0x02, 0x1D, 0xF0, 0x00, + 0x00, 0x22, 0xA4, 0x6E, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x36, 0x41, 0x00, 0xA2, 0xA0, 0x03, 0xB1, + 0xD5, 0x03, 0xE5, 0xEA, 0x2C, 0x92, 0xA0, 0x60, + 0x81, 0xC8, 0x03, 0xB8, 0xB2, 0xA2, 0x22, 0x10, + 0xA9, 0xF2, 0xB2, 0x52, 0x26, 0xB2, 0x52, 0x25, + 0x0C, 0x8B, 0xC0, 0x20, 0x00, 0xF2, 0x28, 0x81, + 0xC0, 0x20, 0x00, 0xE8, 0xF2, 0x90, 0xFF, 0x20, + 0xF2, 0x68, 0x81, 0xE2, 0x0E, 0x00, 0xC0, 0x20, + 0x00, 0xC8, 0xF2, 0xF1, 0xD6, 0x03, 0x1B, 0xCC, + 0xE2, 0x5F, 0x80, 0xD2, 0x12, 0x25, 0xC9, 0xF2, + 0x0B, 0xDD, 0xD2, 0x52, 0x25, 0x80, 0x61, 0x00, + 0x9D, 0x08, 0xA0, 0xE4, 0x03, 0xB0, 0xAA, 0x20, + 0xA0, 0xE4, 0x13, 0x80, 0xE6, 0x13, 0x10, 0x20, + 0x00, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x61, 0x00, + 0xC0, 0x20, 0x00, 0xC1, 0xD6, 0x03, 0xF1, 0xC8, + 0x03, 0xE1, 0xC3, 0x03, 0xA2, 0x2F, 0x82, 0xB8, + 0x1E, 0x17, 0x6A, 0x14, 0x92, 0x1B, 0x26, 0x16, + 0xE9, 0x00, 0x82, 0xC9, 0xFF, 0xC0, 0x20, 0x00, + 0xD2, 0x1C, 0x80, 0xD2, 0x51, 0x00, 0x82, 0x5B, + 0x26, 0x92, 0x1B, 0x25, 0x07, 0xEA, 0x07, 0x8C, + 0xA9, 0x82, 0x0B, 0x4E, 0x26, 0x48, 0x41, 0x8C, + 0x29, 0x1D, 0xF0, 0x00, 0x00, 0x92, 0x1B, 0x26, + 0x56, 0x59, 0xFF, 0xC0, 0x20, 0x00, 0x0C, 0x5D, + 0x92, 0xAF, 0x9F, 0x82, 0x2F, 0x81, 0xC0, 0x20, + 0x00, 0x90, 0x88, 0x10, 0x82, 0x6F, 0x81, 0x7C, + 0x7F, 0xA0, 0x61, 0x00, 0xCD, 0x0A, 0xE0, 0xE4, + 0x03, 0xF0, 0xEE, 0x10, 0xE0, 0xE4, 0x13, 0xA0, + 0xE6, 0x13, 0x10, 0x20, 0x00, 0xD2, 0x4B, 0x4E, + 0xA2, 0xCB, 0x14, 0xE5, 0xE3, 0x2C, 0x1D, 0xF0, + 0x00, 0xD8, 0xFB, 0xD2, 0x0D, 0x00, 0xC0, 0x20, + 0x00, 0xA8, 0xFB, 0xD2, 0x5C, 0x80, 0x1B, 0xAA, + 0xA9, 0xFB, 0xB8, 0x1E, 0x92, 0x1B, 0x25, 0x0B, + 0x99, 0x90, 0x90, 0xF4, 0x92, 0x5B, 0x25, 0x06, + 0xE7, 0xFF, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x92, 0xA0, 0x06, 0xB1, 0xC8, 0x03, 0xC0, 0x20, + 0x00, 0x82, 0x2B, 0x82, 0x0C, 0x0A, 0x17, 0x68, + 0x0B, 0x92, 0xC9, 0xFF, 0xC0, 0x20, 0x00, 0xC2, + 0x2B, 0x80, 0x56, 0x89, 0xFE, 0xC0, 0x20, 0x00, + 0xA2, 0xC2, 0x14, 0x0C, 0x8D, 0xE2, 0xA0, 0x04, + 0xE2, 0x6B, 0x84, 0xD2, 0x42, 0x4E, 0x25, 0xDE, + 0x2C, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x31, 0xD7, 0x03, 0x21, 0xD8, 0x03, 0x22, 0x63, + 0x75, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, + 0xA1, 0xD9, 0x03, 0xB1, 0xDA, 0x03, 0xC1, 0xDB, + 0x03, 0xE5, 0x37, 0x2D, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x16, 0xA5, 0x01, 0x20, + 0x61, 0x00, 0x25, 0xA4, 0xFF, 0x20, 0xE6, 0x13, + 0x10, 0x20, 0x00, 0xA2, 0xA0, 0x00, 0x65, 0x72, + 0x29, 0xA1, 0xDC, 0x03, 0xB1, 0xDD, 0x03, 0xE5, + 0xFF, 0x2C, 0x1D, 0xF0, 0x00, 0x36, 0x41, 0x00, + 0xA1, 0xDE, 0x03, 0xB1, 0xDE, 0x03, 0x65, 0xFC, + 0x20, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, + 0xCD, 0x04, 0x81, 0xDF, 0x03, 0xBD, 0x03, 0x88, + 0x08, 0xAD, 0x02, 0xCC, 0xF8, 0x8C, 0xD3, 0xD1, + 0xC9, 0x03, 0xF1, 0xE0, 0x03, 0x98, 0x1D, 0xE8, + 0x2D, 0xE9, 0x0F, 0x92, 0x6D, 0x02, 0xE5, 0x65, + 0x29, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, + 0xC1, 0xE0, 0x03, 0xAD, 0x02, 0x98, 0x0C, 0x0C, + 0x0B, 0x8C, 0x59, 0x81, 0xC9, 0x03, 0xB9, 0x0C, + 0x99, 0x28, 0xE5, 0x70, 0x29, 0x1D, 0xF0, 0x00, + 0x00, 0x36, 0x41, 0x00, 0xD1, 0xE2, 0x03, 0x91, + 0xE3, 0x03, 0xB0, 0x82, 0x11, 0xA1, 0xE1, 0x03, + 0xB2, 0xAE, 0xF0, 0xBA, 0xAA, 0xAA, 0xA8, 0x9A, + 0x88, 0xC8, 0x0A, 0xC0, 0x20, 0x00, 0xB8, 0x7C, + 0xC0, 0x20, 0x00, 0xD0, 0xBB, 0x10, 0xB9, 0x7C, + 0x82, 0x08, 0x7F, 0x0C, 0x09, 0x8C, 0x18, 0xE5, + 0x5B, 0x21, 0x1D, 0xF0, 0x00, 0x36, 0x41, 0x00, + 0x21, 0xE4, 0x03, 0x31, 0xE5, 0x03, 0x28, 0x22, + 0x29, 0x03, 0x1D, 0xF0, 0x00, 0x36, 0x41, 0x00, + 0x21, 0xE6, 0x03, 0x88, 0x02, 0x27, 0x98, 0x02, + 0x1D, 0xF0, 0x00, 0x20, 0xA2, 0x20, 0x25, 0x08, + 0x00, 0xAD, 0x02, 0xE5, 0xC5, 0x20, 0x1D, 0xF0, + 0x00, 0x36, 0x41, 0x00, 0x20, 0x61, 0x00, 0xA1, + 0xE6, 0x03, 0xE5, 0xC4, 0x20, 0xA5, 0x0B, 0x24, + 0x20, 0xE6, 0x13, 0x10, 0x20, 0x00, 0x1D, 0xF0, + 0x00, 0x36, 0x41, 0x00, 0x41, 0xE7, 0x03, 0x21, + 0xE8, 0x03, 0xC0, 0x20, 0x00, 0x32, 0x22, 0x81, + 0x98, 0x54, 0x88, 0x34, 0x30, 0x99, 0x20, 0x99, + 0x54, 0x87, 0x83, 0x39, 0x0C, 0x1C, 0xB2, 0xA0, + 0x38, 0xA2, 0x24, 0x04, 0xC0, 0x20, 0x00, 0xB0, + 0xAA, 0x10, 0xA2, 0x62, 0x80, 0xC0, 0x20, 0x00, + 0xD2, 0x22, 0x81, 0xD0, 0xE0, 0x04, 0x07, 0xED, + 0xF3, 0xC0, 0x20, 0x00, 0xB1, 0xE9, 0x03, 0x32, + 0x62, 0x81, 0xC0, 0x20, 0x00, 0xB8, 0x0B, 0xA1, + 0xEA, 0x03, 0x1B, 0xBB, 0xB9, 0x4A, 0x4B, 0xAA, + 0xA5, 0xBD, 0x20, 0x1D, 0xF0, 0x00, 0x0C, 0x0C, + 0xC9, 0x34, 0xE5, 0xC4, 0x21, 0xC6, 0xEE, 0xFF, + 0x00, 0x36, 0x41, 0x00, 0x20, 0x61, 0x00, 0x3C, + 0x8A, 0x0C, 0x0B, 0x65, 0x08, 0x24, 0x20, 0xE6, + 0x13, 0x10, 0x20, 0x00, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x1F, 0x00, 0x00, 0x00, 0xD0, 0x0F, 0x02, + 0x60, 0xD8, 0x11, 0x02, 0x60, 0x00, 0x12, 0x02, + 0x60, 0x3C, 0x12, 0x02, 0x60, 0x54, 0x13, 0x02, + 0x60, 0x20, 0x12, 0x02, 0x60, 0xCC, 0x13, 0x02, + 0x60, 0xE0, 0x13, 0x02, 0x60, 0x00, 0x14, 0x02, + 0x60, 0x64, 0x14, 0x02, 0x60, 0x04, 0x15, 0x02, + 0x60, 0xC8, 0x16, 0x00, 0x60, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x16, 0x02, + 0x60, 0x08, 0x17, 0x00, 0x60, 0x08, 0x17, 0x00, + 0x60, 0x04, 0x17, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x00, 0xD0, 0x16, 0x00, 0x60, 0xD4, 0x16, 0x00, + 0x60, 0x2C, 0x17, 0x00, 0x60, 0x50, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x0C, 0x00, + 0x60, 0xD4, 0x0C, 0x00, 0x60, 0x19, 0x30, 0x00, + 0x00, 0x40, 0x17, 0x00, 0x60, 0x10, 0x01, 0x00, + 0x00, 0xB0, 0x0A, 0x00, 0x60, 0x60, 0x15, 0x02, + 0x60, 0x34, 0x0D, 0x00, 0x60, 0x10, 0x03, 0x02, + 0x28, 0x18, 0x00, 0x02, 0x28, 0x14, 0x03, 0x02, + 0x28, 0xBC, 0x08, 0x00, 0x60, 0x94, 0x15, 0x02, + 0x60, 0xBC, 0x15, 0x02, 0x60, 0xA4, 0x05, 0x00, + 0x60, 0xD8, 0x15, 0x02, 0x60, 0xA8, 0x0B, 0x00, + 0x60, 0xF8, 0x16, 0x00, 0x60, 0xAC, 0x06, 0x00, + 0x60, 0x38, 0x16, 0x02, 0x60, 0x50, 0x16, 0x02, + 0x60, 0xD8, 0x56, 0x04, 0x60, 0x36, 0x41, 0x00, + 0x81, 0xCF, 0x05, 0xB1, 0xCD, 0x05, 0xA2, 0xA0, + 0x03, 0x91, 0xCE, 0x05, 0xA2, 0x4B, 0x00, 0x82, + 0x69, 0x00, 0xE5, 0x01, 0x00, 0xA5, 0x08, 0x00, + 0x25, 0x05, 0x00, 0x25, 0x06, 0x00, 0x25, 0x02, + 0x00, 0xA5, 0x06, 0x00, 0xA1, 0xD0, 0x05, 0xB1, + 0xD1, 0x05, 0x25, 0xDC, 0x2C, 0x1D, 0xF0, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x31, 0xD2, 0x05, 0x21, + 0xD3, 0x05, 0x22, 0x63, 0x75, 0x1D, 0xF0, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x91, 0xD4, 0x05, 0x92, + 0x09, 0x47, 0x26, 0x19, 0x04, 0x26, 0x29, 0x0C, + 0x1D, 0xF0, 0xA1, 0xD5, 0x05, 0xB1, 0xD6, 0x05, + 0xE5, 0xD6, 0x20, 0x1D, 0xF0, 0xA1, 0xD5, 0x05, + 0xB1, 0xD7, 0x05, 0x25, 0xD6, 0x20, 0x1D, 0xF0, + 0x00, 0x36, 0x41, 0x00, 0x81, 0xD9, 0x05, 0x31, + 0xD8, 0x05, 0x21, 0xDA, 0x05, 0x29, 0x43, 0x89, + 0x03, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x31, 0xDB, 0x05, 0x21, 0xDC, 0x05, 0x22, 0x63, + 0x13, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x31, 0xDD, 0x05, 0x21, 0xDE, 0x05, 0x48, 0x03, + 0x49, 0x22, 0x29, 0x03, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x91, 0xE0, 0x05, 0x21, + 0xE2, 0x05, 0x31, 0xDF, 0x05, 0x81, 0xE1, 0x05, + 0x89, 0xC3, 0x29, 0xA3, 0x99, 0xB3, 0x1D, 0xF0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x04, 0x00, 0x8C, 0x17, 0x02, + 0x60, }; static const unsigned char vfs301_06_2[] = { /* 1905 B */ - 0x06, 0x00, 0x00, 0x64, 0x07, 0x00, 0x0F, 0x00, - 0x60, 0xD8, 0x0C, 0x00, 0x60, 0xD4, 0x0C, 0x00, - 0x60, 0x50, 0x15, 0x00, 0x60, 0x20, 0x0E, 0x00, - 0x60, 0xFC, 0xFF, 0x00, 0x00, 0x30, 0x15, 0x00, - 0x60, 0xB0, 0x0A, 0x00, 0x60, 0x58, 0xB3, 0x04, - 0x60, 0x84, 0x05, 0x00, 0x60, 0xA4, 0xED, 0x04, - 0x60, 0x8C, 0x04, 0x00, 0x00, 0x00, 0x0F, 0x00, - 0x60, 0x60, 0x06, 0x00, 0x00, 0xA0, 0x0A, 0x00, - 0x60, 0xD0, 0x38, 0x04, 0x60, 0xB4, 0x39, 0x04, - 0x60, 0x58, 0xB4, 0x04, 0x60, 0xFC, 0x0C, 0x00, - 0x60, 0x20, 0x15, 0x00, 0x60, 0xC8, 0x0D, 0x00, - 0x60, 0x9C, 0x0B, 0x00, 0x60, 0xFC, 0x14, 0x00, - 0x60, 0xCC, 0x08, 0x00, 0x60, 0x68, 0x0A, 0x00, - 0x60, 0x4C, 0x3F, 0x04, 0x60, 0xC0, 0x0D, 0x00, - 0x60, 0x04, 0x15, 0x00, 0x60, 0x18, 0x0D, 0x00, - 0x60, 0x00, 0x9E, 0x00, 0x38, 0xDC, 0x0C, 0x00, - 0x60, 0x00, 0x15, 0x00, 0x60, 0x36, 0x41, 0x00, - 0x25, 0x37, 0x00, 0x65, 0x3A, 0x00, 0xA5, 0x4C, - 0x00, 0xE5, 0x48, 0x00, 0x65, 0x35, 0x00, 0x91, - 0xC0, 0x03, 0xA1, 0xC1, 0x03, 0x0C, 0x08, 0x89, - 0x0A, 0x82, 0x49, 0x00, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x31, 0xC2, 0x03, 0x38, - 0x03, 0x8C, 0x73, 0x88, 0x23, 0x66, 0x28, 0x03, - 0x0C, 0x39, 0x99, 0x23, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x31, 0xC3, 0x03, 0x0C, - 0x02, 0x22, 0x43, 0x00, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x36, 0x41, 0x00, 0xBD, 0x02, 0x21, 0xC2, - 0x03, 0x28, 0x02, 0x1C, 0x8C, 0xCB, 0xA2, 0xA5, - 0x8F, 0x2D, 0xD1, 0xC4, 0x03, 0x2C, 0x0B, 0x92, - 0x12, 0x11, 0x0C, 0x1C, 0xDC, 0x79, 0xA2, 0x12, - 0x0F, 0x92, 0x12, 0x0E, 0xA0, 0xA0, 0xE4, 0x90, - 0xAA, 0xC0, 0xA2, 0xCA, 0xC2, 0xA0, 0xA1, 0x21, - 0xAA, 0x99, 0x8B, 0x99, 0x92, 0x52, 0x11, 0xB2, - 0x52, 0x13, 0xC9, 0x22, 0xD0, 0xD9, 0x10, 0xD2, - 0x52, 0x11, 0x1D, 0xF0, 0x00, 0x36, 0x41, 0x00, - 0xD8, 0x22, 0x31, 0xC2, 0x03, 0x0C, 0x1E, 0x38, - 0x03, 0x0C, 0x0C, 0xAD, 0x03, 0xF2, 0x13, 0x13, - 0xB2, 0x13, 0x10, 0xF0, 0xCE, 0x83, 0xDA, 0xBB, - 0x25, 0x17, 0x00, 0x0C, 0x45, 0xA8, 0x23, 0x92, - 0x13, 0x13, 0x0C, 0x04, 0x8C, 0x69, 0x0B, 0x99, - 0x90, 0x90, 0xF4, 0x92, 0x53, 0x13, 0xF6, 0x8A, - 0x2F, 0xB1, 0xC5, 0x03, 0xB0, 0xBA, 0xA0, 0xB8, - 0x0B, 0xA0, 0x0B, 0x00, 0xC8, 0x22, 0xB2, 0x13, - 0x11, 0xAD, 0x03, 0xCA, 0xBB, 0x65, 0x21, 0x00, - 0xD2, 0x13, 0x06, 0xF1, 0xC3, 0x03, 0xD7, 0x3A, - 0x0F, 0x0C, 0x29, 0x92, 0x4F, 0x00, 0xE2, 0x13, - 0x0F, 0xE0, 0xEF, 0x04, 0x16, 0xBE, 0x10, 0x99, - 0x23, 0x0C, 0x14, 0x2D, 0x04, 0x1D, 0xF0, 0x49, - 0x23, 0x0C, 0x24, 0x06, 0xFD, 0xFF, 0xAD, 0x03, - 0xE5, 0x1B, 0x00, 0x82, 0x13, 0x09, 0xB2, 0x13, - 0x08, 0x87, 0x3A, 0x02, 0x06, 0x24, 0x00, 0xC8, - 0x22, 0xB2, 0x13, 0x11, 0xAD, 0x03, 0xCA, 0xBB, - 0x65, 0x1D, 0x00, 0xD2, 0x13, 0x07, 0xD7, 0x3A, - 0x02, 0xC6, 0x36, 0x00, 0xE2, 0x13, 0x14, 0x0B, - 0xEE, 0xE0, 0xE0, 0xF4, 0xE2, 0x53, 0x14, 0x56, - 0xEE, 0x0D, 0x0C, 0x24, 0x0C, 0x7F, 0xF9, 0x23, - 0xC6, 0xED, 0xFF, 0xAD, 0x03, 0xE5, 0x17, 0x00, - 0x82, 0x13, 0x08, 0x87, 0x3A, 0x6A, 0x59, 0x23, - 0x42, 0x53, 0x16, 0x92, 0x13, 0x0A, 0x92, 0x53, - 0x14, 0x0C, 0x04, 0x06, 0xE7, 0xFF, 0xAD, 0x03, - 0x65, 0x16, 0x00, 0xB2, 0x13, 0x08, 0xB7, 0x3A, - 0x29, 0xC2, 0x13, 0x14, 0x0B, 0xCC, 0xC0, 0xC0, - 0xF4, 0xC2, 0x53, 0x14, 0xEC, 0xBC, 0x0C, 0x6D, - 0xE2, 0x13, 0x0B, 0xE2, 0x53, 0x14, 0xD9, 0x23, - 0xC6, 0x07, 0x00, 0xDC, 0xC9, 0x59, 0x23, 0x42, - 0x53, 0x16, 0xF2, 0x13, 0x0A, 0xF2, 0x53, 0x14, - 0xC6, 0x03, 0x00, 0x0C, 0x58, 0x92, 0x13, 0x0D, - 0xA2, 0x13, 0x0C, 0xA2, 0x53, 0x14, 0x92, 0x53, - 0x15, 0x89, 0x23, 0x0C, 0x04, 0x86, 0xD4, 0xFF, - 0xB7, 0x3A, 0x05, 0xC2, 0x13, 0x0B, 0xC2, 0x53, - 0x14, 0x42, 0x53, 0x16, 0x0C, 0x04, 0x46, 0xD0, - 0xFF, 0x92, 0x13, 0x15, 0x66, 0x19, 0x09, 0x0C, - 0x34, 0x0B, 0xD9, 0xD2, 0x53, 0x15, 0x46, 0xCC, - 0xFF, 0xCC, 0x39, 0x0C, 0x14, 0x86, 0x01, 0x00, - 0x0C, 0x04, 0x0B, 0xE9, 0xE2, 0x53, 0x15, 0xC8, - 0x22, 0xB2, 0x13, 0x11, 0xAD, 0x03, 0xCA, 0xBB, - 0x65, 0x11, 0x00, 0xD2, 0x13, 0x07, 0xD7, 0xBA, - 0x10, 0xE2, 0x13, 0x14, 0x0B, 0xEE, 0xE0, 0xE0, - 0xF4, 0xE2, 0x53, 0x14, 0xE0, 0x45, 0x83, 0x06, - 0xC0, 0xFF, 0xF2, 0x13, 0x0D, 0xF2, 0x53, 0x14, - 0xC6, 0xBD, 0xFF, 0x0C, 0x39, 0x86, 0xBB, 0xFF, - 0x82, 0x13, 0x06, 0x87, 0x3A, 0x05, 0x92, 0x13, - 0x0B, 0x92, 0x53, 0x14, 0x0C, 0x04, 0x46, 0xB8, - 0xFF, 0x0C, 0x04, 0x06, 0xB7, 0xFF, 0x00, 0x00, - 0x00, 0x36, 0x61, 0x00, 0xB2, 0xA0, 0x94, 0xA2, - 0xC2, 0x34, 0x92, 0xC2, 0x54, 0x99, 0x01, 0xA9, - 0x11, 0xBC, 0xB4, 0x68, 0x11, 0x5D, 0x09, 0x1C, - 0x04, 0x72, 0x12, 0x12, 0x82, 0xA0, 0x94, 0xC0, - 0x77, 0x11, 0x7A, 0x72, 0x8A, 0x77, 0x82, 0x16, - 0x00, 0xB2, 0x07, 0x00, 0x1B, 0x77, 0xAD, 0x0B, - 0xB0, 0x88, 0xC0, 0x82, 0x56, 0x00, 0x2B, 0x66, - 0x65, 0x96, 0x2D, 0x98, 0x05, 0x0B, 0x44, 0xA0, - 0x99, 0xC0, 0x99, 0x05, 0x4B, 0x55, 0x56, 0xC4, - 0xFD, 0x98, 0x01, 0xA8, 0x11, 0xB2, 0xA0, 0x94, - 0x5D, 0x09, 0x6D, 0x0A, 0x72, 0x12, 0x12, 0x1C, - 0x04, 0xC0, 0x77, 0x11, 0x7A, 0x72, 0xBA, 0x77, - 0xD2, 0x03, 0x01, 0xE2, 0x03, 0x03, 0xC2, 0x03, - 0x02, 0xB2, 0x03, 0x00, 0xEA, 0xCC, 0xDA, 0xBB, - 0xCA, 0xBB, 0xB0, 0xB2, 0x41, 0xAD, 0x0B, 0xB2, - 0x47, 0x00, 0x82, 0x16, 0x00, 0x1B, 0x77, 0xBA, - 0x88, 0x82, 0x56, 0x00, 0x2B, 0x66, 0x65, 0x91, - 0x2D, 0x8B, 0x33, 0xF8, 0x05, 0x0B, 0x44, 0xAA, - 0xFF, 0xF9, 0x05, 0x4B, 0x55, 0x56, 0x74, 0xFC, - 0x82, 0x12, 0x12, 0x1B, 0x88, 0x80, 0x80, 0x44, - 0x82, 0x52, 0x12, 0x1D, 0xF0, 0x36, 0x41, 0x00, - 0x32, 0xC2, 0x34, 0x1C, 0x05, 0x0C, 0x04, 0xB2, - 0x13, 0x00, 0xAD, 0x0B, 0xA5, 0x8E, 0x2D, 0x2B, - 0x33, 0x0B, 0x55, 0xA0, 0x95, 0x41, 0x82, 0x22, - 0x15, 0x4B, 0x22, 0x90, 0x88, 0xC0, 0x80, 0x85, - 0x41, 0x8A, 0x44, 0x56, 0x05, 0xFE, 0x40, 0x24, - 0x41, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x1C, 0x07, 0x0C, 0x06, 0x0C, 0x05, 0xB2, 0xC3, - 0x81, 0x42, 0x03, 0x00, 0xB2, 0x0B, 0x7E, 0xC2, - 0x03, 0x01, 0x47, 0xBB, 0x0C, 0x47, 0xBC, 0x11, - 0x4D, 0x0B, 0xC7, 0xBB, 0x0C, 0x4D, 0x0C, 0xC6, - 0x01, 0x00, 0x47, 0x3C, 0x04, 0xC7, 0xBB, 0x01, - 0x4D, 0x0B, 0xAD, 0x04, 0xBD, 0x04, 0x65, 0x89, - 0x2D, 0xAA, 0x66, 0x5A, 0x54, 0x0B, 0x77, 0x4B, - 0x33, 0xB2, 0xC3, 0x81, 0x56, 0x97, 0xFC, 0xAD, - 0x05, 0xBD, 0x05, 0x25, 0x88, 0x2D, 0xD2, 0x12, - 0x16, 0xA0, 0x94, 0x41, 0x90, 0x96, 0xC0, 0xD0, - 0xCD, 0xF0, 0x90, 0x94, 0x41, 0x90, 0xE3, 0x41, - 0xC0, 0xC3, 0x21, 0xEA, 0xCC, 0xD0, 0x9C, 0x93, - 0x92, 0x52, 0x16, 0x2D, 0x09, 0x1D, 0xF0, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x31, 0xC6, 0x03, 0x21, - 0xC7, 0x03, 0x22, 0x63, 0x75, 0x1D, 0xF0, 0x00, - 0x00, 0x36, 0x41, 0x00, 0xA1, 0xC8, 0x03, 0xB1, - 0xC9, 0x03, 0xC1, 0xCA, 0x03, 0xA5, 0x5D, 0x2D, - 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x9C, 0x85, 0x20, 0x61, 0x00, 0xE5, 0xC6, 0xFF, - 0x20, 0xE6, 0x13, 0x10, 0x20, 0x00, 0x0C, 0x0A, - 0x65, 0x98, 0x29, 0xA1, 0xCB, 0x03, 0xB1, 0xCC, - 0x03, 0xA5, 0x25, 0x2D, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x0C, 0xBB, 0x31, 0xC6, - 0x03, 0x21, 0xD0, 0x03, 0x81, 0xCF, 0x03, 0x91, - 0xCD, 0x03, 0xA1, 0xCE, 0x03, 0xA9, 0xF9, 0x82, - 0x69, 0x19, 0x22, 0x63, 0x6B, 0xB2, 0x59, 0x1C, - 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x21, 0xD1, 0x03, 0x88, 0x22, 0x37, 0x68, 0x0E, - 0xA1, 0xD2, 0x03, 0xA5, 0x4D, 0x2D, 0x98, 0x22, - 0x6C, 0x7A, 0xA0, 0x99, 0x10, 0x99, 0x22, 0xE5, - 0x79, 0x22, 0x1D, 0xF0, 0x00, 0x36, 0x41, 0x00, - 0xCD, 0x04, 0xBD, 0x03, 0xAD, 0x02, 0xDD, 0x05, - 0x25, 0x0E, 0x2A, 0xAC, 0x15, 0x81, 0xD3, 0x03, - 0xA1, 0xD4, 0x03, 0x88, 0x08, 0x91, 0xD1, 0x03, - 0x82, 0x08, 0x02, 0x98, 0x29, 0xB6, 0x28, 0x06, - 0x91, 0xD5, 0x03, 0x99, 0x2A, 0x1D, 0xF0, 0x37, - 0x69, 0x05, 0x91, 0xD6, 0x03, 0x86, 0xFC, 0xFF, - 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, - 0xBD, 0x03, 0xAD, 0x02, 0xCD, 0x04, 0xDD, 0x05, - 0x1C, 0x8E, 0x25, 0x71, 0x22, 0xBC, 0x16, 0x82, - 0x12, 0x1A, 0x5A, 0xA4, 0xEC, 0xA8, 0x1C, 0x79, - 0xA7, 0x39, 0x28, 0x92, 0xA4, 0x21, 0x92, 0x52, - 0x1A, 0x06, 0x05, 0x00, 0xA1, 0xD2, 0x03, 0x25, - 0x42, 0x2D, 0xA8, 0x82, 0xE5, 0xBF, 0xFF, 0xB1, - 0xD1, 0x03, 0xA8, 0x2B, 0x30, 0xAA, 0x20, 0xA9, - 0x2B, 0xA8, 0x82, 0xA5, 0x05, 0x2D, 0x0C, 0x0B, - 0xB9, 0x82, 0x1D, 0xF0, 0x1C, 0x83, 0xA7, 0xB3, - 0xDA, 0x92, 0xA4, 0x22, 0x86, 0xF3, 0xFF, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x8C, 0x36, 0x0C, 0x03, - 0x32, 0x52, 0x1A, 0x1D, 0xF0, 0x36, 0x41, 0x00, - 0xA5, 0xB9, 0xFF, 0xAD, 0x02, 0x81, 0xD6, 0x03, - 0x89, 0x22, 0xE5, 0x8C, 0x29, 0x1D, 0xF0, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x31, 0xD7, 0x03, 0x21, - 0xD8, 0x03, 0x29, 0x13, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x81, 0xD9, 0x03, 0x30, - 0x61, 0x00, 0x88, 0x08, 0x82, 0x08, 0x10, 0x26, - 0x48, 0x07, 0xAD, 0x02, 0xA5, 0x54, 0x28, 0x06, - 0x01, 0x00, 0x0C, 0x0A, 0xE5, 0xED, 0x20, 0x30, - 0xE6, 0x13, 0x10, 0x20, 0x00, 0x1D, 0xF0, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x21, 0xDA, 0x03, 0x88, - 0x02, 0x27, 0x18, 0x09, 0xAD, 0x02, 0xE5, 0x07, - 0x00, 0xAD, 0x02, 0xE5, 0xE2, 0x20, 0x1D, 0xF0, - 0x00, 0x36, 0x41, 0x00, 0x20, 0x61, 0x00, 0xA1, - 0xDA, 0x03, 0xE5, 0xE1, 0x20, 0xA5, 0x28, 0x24, - 0x20, 0xE6, 0x13, 0x10, 0x20, 0x00, 0x1D, 0xF0, - 0x00, 0x36, 0x41, 0x00, 0x41, 0xDB, 0x03, 0x21, - 0xDC, 0x03, 0xC0, 0x20, 0x00, 0x32, 0x22, 0x81, - 0x98, 0x54, 0x88, 0x34, 0x30, 0x99, 0x20, 0x99, - 0x54, 0x87, 0x03, 0x06, 0x0C, 0x0A, 0xA9, 0x34, - 0xA5, 0xE5, 0x21, 0x0C, 0x1D, 0x3C, 0x8C, 0xB8, - 0x44, 0xC0, 0x20, 0x00, 0xC0, 0xBB, 0x10, 0xB2, - 0x62, 0x80, 0xC0, 0x20, 0x00, 0xE2, 0x22, 0x81, - 0xE0, 0xF0, 0x04, 0x07, 0xEE, 0xF3, 0xC0, 0x20, - 0x00, 0xB1, 0xDD, 0x03, 0x32, 0x62, 0x81, 0xC0, - 0x20, 0x00, 0xB8, 0x0B, 0xA1, 0xDE, 0x03, 0x1B, - 0xBB, 0xB9, 0x4A, 0x4B, 0xAA, 0x25, 0xDA, 0x20, - 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x20, 0x61, 0x00, 0x3C, 0x8A, 0x0C, 0x0B, 0xA5, - 0x25, 0x24, 0x20, 0xE6, 0x13, 0x10, 0x20, 0x00, - 0x1D, 0xF0, 0x00, 0x00, 0x00, 0xB8, 0x0F, 0x02, - 0x60, 0xC0, 0x0F, 0x02, 0x60, 0x04, 0x14, 0x02, - 0x60, 0xDC, 0x14, 0x02, 0x60, 0x04, 0x15, 0x00, - 0x60, 0x04, 0x15, 0x00, 0x60, 0x00, 0x15, 0x00, - 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xF4, 0x14, 0x00, 0x60, 0xF8, 0x14, 0x00, - 0x60, 0x50, 0x15, 0x00, 0x60, 0x94, 0x02, 0x00, - 0x00, 0x78, 0x10, 0x02, 0x60, 0x53, 0x10, 0x02, - 0x60, 0x78, 0x10, 0x02, 0x60, 0x02, 0x11, 0x02, - 0x60, 0xDD, 0x10, 0x02, 0x60, 0xC2, 0x10, 0x02, - 0x60, 0x85, 0x10, 0x02, 0x60, 0x7E, 0x10, 0x02, - 0x60, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x0C, 0x00, - 0x60, 0xD4, 0x0C, 0x00, 0x60, 0x10, 0x30, 0x02, - 0x00, 0x60, 0x15, 0x00, 0x60, 0x00, 0x01, 0x00, - 0x00, 0xB0, 0x0A, 0x00, 0x60, 0x04, 0x13, 0x02, - 0x60, 0xA0, 0x0A, 0x00, 0x60, 0xA4, 0x13, 0x02, - 0x60, 0xF8, 0x13, 0x02, 0x60, 0x6C, 0x13, 0x02, - 0x60, 0x6C, 0x06, 0x00, 0x60, 0x14, 0x10, 0x02, - 0x60, 0xF4, 0x05, 0x00, 0x60, 0x4C, 0x13, 0x02, - 0x60, 0x68, 0x0A, 0x00, 0x60, 0x28, 0x8F, 0x04, - 0x60, 0x48, 0x08, 0x00, 0x60, 0x28, 0x14, 0x02, - 0x60, 0xAC, 0x06, 0x00, 0x60, 0x68, 0x14, 0x02, - 0x60, 0x80, 0x14, 0x02, 0x60, 0xD8, 0x56, 0x04, - 0x60, 0x36, 0x41, 0x00, 0x81, 0x57, 0x05, 0xB1, - 0x55, 0x05, 0x0C, 0x3A, 0x91, 0x56, 0x05, 0xA2, - 0x4B, 0x00, 0x89, 0x09, 0xE5, 0x01, 0x00, 0xE5, - 0x05, 0x00, 0xA5, 0x06, 0x00, 0x65, 0x07, 0x00, - 0x25, 0x02, 0x00, 0xA1, 0x58, 0x05, 0xB1, 0x59, - 0x05, 0x25, 0xFA, 0x2C, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x31, 0x5A, 0x05, 0x21, - 0x5B, 0x05, 0x22, 0x63, 0x75, 0x1D, 0xF0, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x0C, 0x8F, 0xB1, 0x5A, - 0x05, 0xA1, 0x5F, 0x05, 0x91, 0x60, 0x05, 0x81, - 0x61, 0x05, 0x31, 0x62, 0x05, 0x21, 0x63, 0x05, - 0xC1, 0x5E, 0x05, 0xD1, 0x5C, 0x05, 0xE1, 0x5D, - 0x05, 0xE9, 0xFD, 0xC2, 0x6D, 0x19, 0x29, 0x83, - 0x89, 0x39, 0xA2, 0x6B, 0x6B, 0xF2, 0x5D, 0x1C, - 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x31, 0x64, 0x05, 0x21, 0x65, 0x05, 0x29, 0x13, - 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x31, 0x66, 0x05, 0x21, 0x67, 0x05, 0x22, 0x63, - 0x19, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x91, 0x69, 0x05, 0x21, 0x6B, 0x05, 0x31, 0x68, - 0x05, 0x81, 0x6A, 0x05, 0x89, 0xC3, 0x29, 0xA3, - 0x99, 0xB3, 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x04, 0x00, 0xB0, 0x15, 0x02, - 0x60, + 0x06, 0x00, 0x00, 0x64, 0x07, 0x00, 0x0F, 0x00, + 0x60, 0xD8, 0x0C, 0x00, 0x60, 0xD4, 0x0C, 0x00, + 0x60, 0x50, 0x15, 0x00, 0x60, 0x20, 0x0E, 0x00, + 0x60, 0xFC, 0xFF, 0x00, 0x00, 0x30, 0x15, 0x00, + 0x60, 0xB0, 0x0A, 0x00, 0x60, 0x58, 0xB3, 0x04, + 0x60, 0x84, 0x05, 0x00, 0x60, 0xA4, 0xED, 0x04, + 0x60, 0x8C, 0x04, 0x00, 0x00, 0x00, 0x0F, 0x00, + 0x60, 0x60, 0x06, 0x00, 0x00, 0xA0, 0x0A, 0x00, + 0x60, 0xD0, 0x38, 0x04, 0x60, 0xB4, 0x39, 0x04, + 0x60, 0x58, 0xB4, 0x04, 0x60, 0xFC, 0x0C, 0x00, + 0x60, 0x20, 0x15, 0x00, 0x60, 0xC8, 0x0D, 0x00, + 0x60, 0x9C, 0x0B, 0x00, 0x60, 0xFC, 0x14, 0x00, + 0x60, 0xCC, 0x08, 0x00, 0x60, 0x68, 0x0A, 0x00, + 0x60, 0x4C, 0x3F, 0x04, 0x60, 0xC0, 0x0D, 0x00, + 0x60, 0x04, 0x15, 0x00, 0x60, 0x18, 0x0D, 0x00, + 0x60, 0x00, 0x9E, 0x00, 0x38, 0xDC, 0x0C, 0x00, + 0x60, 0x00, 0x15, 0x00, 0x60, 0x36, 0x41, 0x00, + 0x25, 0x37, 0x00, 0x65, 0x3A, 0x00, 0xA5, 0x4C, + 0x00, 0xE5, 0x48, 0x00, 0x65, 0x35, 0x00, 0x91, + 0xC0, 0x03, 0xA1, 0xC1, 0x03, 0x0C, 0x08, 0x89, + 0x0A, 0x82, 0x49, 0x00, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x31, 0xC2, 0x03, 0x38, + 0x03, 0x8C, 0x73, 0x88, 0x23, 0x66, 0x28, 0x03, + 0x0C, 0x39, 0x99, 0x23, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x31, 0xC3, 0x03, 0x0C, + 0x02, 0x22, 0x43, 0x00, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x36, 0x41, 0x00, 0xBD, 0x02, 0x21, 0xC2, + 0x03, 0x28, 0x02, 0x1C, 0x8C, 0xCB, 0xA2, 0xA5, + 0x8F, 0x2D, 0xD1, 0xC4, 0x03, 0x2C, 0x0B, 0x92, + 0x12, 0x11, 0x0C, 0x1C, 0xDC, 0x79, 0xA2, 0x12, + 0x0F, 0x92, 0x12, 0x0E, 0xA0, 0xA0, 0xE4, 0x90, + 0xAA, 0xC0, 0xA2, 0xCA, 0xC2, 0xA0, 0xA1, 0x21, + 0xAA, 0x99, 0x8B, 0x99, 0x92, 0x52, 0x11, 0xB2, + 0x52, 0x13, 0xC9, 0x22, 0xD0, 0xD9, 0x10, 0xD2, + 0x52, 0x11, 0x1D, 0xF0, 0x00, 0x36, 0x41, 0x00, + 0xD8, 0x22, 0x31, 0xC2, 0x03, 0x0C, 0x1E, 0x38, + 0x03, 0x0C, 0x0C, 0xAD, 0x03, 0xF2, 0x13, 0x13, + 0xB2, 0x13, 0x10, 0xF0, 0xCE, 0x83, 0xDA, 0xBB, + 0x25, 0x17, 0x00, 0x0C, 0x45, 0xA8, 0x23, 0x92, + 0x13, 0x13, 0x0C, 0x04, 0x8C, 0x69, 0x0B, 0x99, + 0x90, 0x90, 0xF4, 0x92, 0x53, 0x13, 0xF6, 0x8A, + 0x2F, 0xB1, 0xC5, 0x03, 0xB0, 0xBA, 0xA0, 0xB8, + 0x0B, 0xA0, 0x0B, 0x00, 0xC8, 0x22, 0xB2, 0x13, + 0x11, 0xAD, 0x03, 0xCA, 0xBB, 0x65, 0x21, 0x00, + 0xD2, 0x13, 0x06, 0xF1, 0xC3, 0x03, 0xD7, 0x3A, + 0x0F, 0x0C, 0x29, 0x92, 0x4F, 0x00, 0xE2, 0x13, + 0x0F, 0xE0, 0xEF, 0x04, 0x16, 0xBE, 0x10, 0x99, + 0x23, 0x0C, 0x14, 0x2D, 0x04, 0x1D, 0xF0, 0x49, + 0x23, 0x0C, 0x24, 0x06, 0xFD, 0xFF, 0xAD, 0x03, + 0xE5, 0x1B, 0x00, 0x82, 0x13, 0x09, 0xB2, 0x13, + 0x08, 0x87, 0x3A, 0x02, 0x06, 0x24, 0x00, 0xC8, + 0x22, 0xB2, 0x13, 0x11, 0xAD, 0x03, 0xCA, 0xBB, + 0x65, 0x1D, 0x00, 0xD2, 0x13, 0x07, 0xD7, 0x3A, + 0x02, 0xC6, 0x36, 0x00, 0xE2, 0x13, 0x14, 0x0B, + 0xEE, 0xE0, 0xE0, 0xF4, 0xE2, 0x53, 0x14, 0x56, + 0xEE, 0x0D, 0x0C, 0x24, 0x0C, 0x7F, 0xF9, 0x23, + 0xC6, 0xED, 0xFF, 0xAD, 0x03, 0xE5, 0x17, 0x00, + 0x82, 0x13, 0x08, 0x87, 0x3A, 0x6A, 0x59, 0x23, + 0x42, 0x53, 0x16, 0x92, 0x13, 0x0A, 0x92, 0x53, + 0x14, 0x0C, 0x04, 0x06, 0xE7, 0xFF, 0xAD, 0x03, + 0x65, 0x16, 0x00, 0xB2, 0x13, 0x08, 0xB7, 0x3A, + 0x29, 0xC2, 0x13, 0x14, 0x0B, 0xCC, 0xC0, 0xC0, + 0xF4, 0xC2, 0x53, 0x14, 0xEC, 0xBC, 0x0C, 0x6D, + 0xE2, 0x13, 0x0B, 0xE2, 0x53, 0x14, 0xD9, 0x23, + 0xC6, 0x07, 0x00, 0xDC, 0xC9, 0x59, 0x23, 0x42, + 0x53, 0x16, 0xF2, 0x13, 0x0A, 0xF2, 0x53, 0x14, + 0xC6, 0x03, 0x00, 0x0C, 0x58, 0x92, 0x13, 0x0D, + 0xA2, 0x13, 0x0C, 0xA2, 0x53, 0x14, 0x92, 0x53, + 0x15, 0x89, 0x23, 0x0C, 0x04, 0x86, 0xD4, 0xFF, + 0xB7, 0x3A, 0x05, 0xC2, 0x13, 0x0B, 0xC2, 0x53, + 0x14, 0x42, 0x53, 0x16, 0x0C, 0x04, 0x46, 0xD0, + 0xFF, 0x92, 0x13, 0x15, 0x66, 0x19, 0x09, 0x0C, + 0x34, 0x0B, 0xD9, 0xD2, 0x53, 0x15, 0x46, 0xCC, + 0xFF, 0xCC, 0x39, 0x0C, 0x14, 0x86, 0x01, 0x00, + 0x0C, 0x04, 0x0B, 0xE9, 0xE2, 0x53, 0x15, 0xC8, + 0x22, 0xB2, 0x13, 0x11, 0xAD, 0x03, 0xCA, 0xBB, + 0x65, 0x11, 0x00, 0xD2, 0x13, 0x07, 0xD7, 0xBA, + 0x10, 0xE2, 0x13, 0x14, 0x0B, 0xEE, 0xE0, 0xE0, + 0xF4, 0xE2, 0x53, 0x14, 0xE0, 0x45, 0x83, 0x06, + 0xC0, 0xFF, 0xF2, 0x13, 0x0D, 0xF2, 0x53, 0x14, + 0xC6, 0xBD, 0xFF, 0x0C, 0x39, 0x86, 0xBB, 0xFF, + 0x82, 0x13, 0x06, 0x87, 0x3A, 0x05, 0x92, 0x13, + 0x0B, 0x92, 0x53, 0x14, 0x0C, 0x04, 0x46, 0xB8, + 0xFF, 0x0C, 0x04, 0x06, 0xB7, 0xFF, 0x00, 0x00, + 0x00, 0x36, 0x61, 0x00, 0xB2, 0xA0, 0x94, 0xA2, + 0xC2, 0x34, 0x92, 0xC2, 0x54, 0x99, 0x01, 0xA9, + 0x11, 0xBC, 0xB4, 0x68, 0x11, 0x5D, 0x09, 0x1C, + 0x04, 0x72, 0x12, 0x12, 0x82, 0xA0, 0x94, 0xC0, + 0x77, 0x11, 0x7A, 0x72, 0x8A, 0x77, 0x82, 0x16, + 0x00, 0xB2, 0x07, 0x00, 0x1B, 0x77, 0xAD, 0x0B, + 0xB0, 0x88, 0xC0, 0x82, 0x56, 0x00, 0x2B, 0x66, + 0x65, 0x96, 0x2D, 0x98, 0x05, 0x0B, 0x44, 0xA0, + 0x99, 0xC0, 0x99, 0x05, 0x4B, 0x55, 0x56, 0xC4, + 0xFD, 0x98, 0x01, 0xA8, 0x11, 0xB2, 0xA0, 0x94, + 0x5D, 0x09, 0x6D, 0x0A, 0x72, 0x12, 0x12, 0x1C, + 0x04, 0xC0, 0x77, 0x11, 0x7A, 0x72, 0xBA, 0x77, + 0xD2, 0x03, 0x01, 0xE2, 0x03, 0x03, 0xC2, 0x03, + 0x02, 0xB2, 0x03, 0x00, 0xEA, 0xCC, 0xDA, 0xBB, + 0xCA, 0xBB, 0xB0, 0xB2, 0x41, 0xAD, 0x0B, 0xB2, + 0x47, 0x00, 0x82, 0x16, 0x00, 0x1B, 0x77, 0xBA, + 0x88, 0x82, 0x56, 0x00, 0x2B, 0x66, 0x65, 0x91, + 0x2D, 0x8B, 0x33, 0xF8, 0x05, 0x0B, 0x44, 0xAA, + 0xFF, 0xF9, 0x05, 0x4B, 0x55, 0x56, 0x74, 0xFC, + 0x82, 0x12, 0x12, 0x1B, 0x88, 0x80, 0x80, 0x44, + 0x82, 0x52, 0x12, 0x1D, 0xF0, 0x36, 0x41, 0x00, + 0x32, 0xC2, 0x34, 0x1C, 0x05, 0x0C, 0x04, 0xB2, + 0x13, 0x00, 0xAD, 0x0B, 0xA5, 0x8E, 0x2D, 0x2B, + 0x33, 0x0B, 0x55, 0xA0, 0x95, 0x41, 0x82, 0x22, + 0x15, 0x4B, 0x22, 0x90, 0x88, 0xC0, 0x80, 0x85, + 0x41, 0x8A, 0x44, 0x56, 0x05, 0xFE, 0x40, 0x24, + 0x41, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x1C, 0x07, 0x0C, 0x06, 0x0C, 0x05, 0xB2, 0xC3, + 0x81, 0x42, 0x03, 0x00, 0xB2, 0x0B, 0x7E, 0xC2, + 0x03, 0x01, 0x47, 0xBB, 0x0C, 0x47, 0xBC, 0x11, + 0x4D, 0x0B, 0xC7, 0xBB, 0x0C, 0x4D, 0x0C, 0xC6, + 0x01, 0x00, 0x47, 0x3C, 0x04, 0xC7, 0xBB, 0x01, + 0x4D, 0x0B, 0xAD, 0x04, 0xBD, 0x04, 0x65, 0x89, + 0x2D, 0xAA, 0x66, 0x5A, 0x54, 0x0B, 0x77, 0x4B, + 0x33, 0xB2, 0xC3, 0x81, 0x56, 0x97, 0xFC, 0xAD, + 0x05, 0xBD, 0x05, 0x25, 0x88, 0x2D, 0xD2, 0x12, + 0x16, 0xA0, 0x94, 0x41, 0x90, 0x96, 0xC0, 0xD0, + 0xCD, 0xF0, 0x90, 0x94, 0x41, 0x90, 0xE3, 0x41, + 0xC0, 0xC3, 0x21, 0xEA, 0xCC, 0xD0, 0x9C, 0x93, + 0x92, 0x52, 0x16, 0x2D, 0x09, 0x1D, 0xF0, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x31, 0xC6, 0x03, 0x21, + 0xC7, 0x03, 0x22, 0x63, 0x75, 0x1D, 0xF0, 0x00, + 0x00, 0x36, 0x41, 0x00, 0xA1, 0xC8, 0x03, 0xB1, + 0xC9, 0x03, 0xC1, 0xCA, 0x03, 0xA5, 0x5D, 0x2D, + 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x9C, 0x85, 0x20, 0x61, 0x00, 0xE5, 0xC6, 0xFF, + 0x20, 0xE6, 0x13, 0x10, 0x20, 0x00, 0x0C, 0x0A, + 0x65, 0x98, 0x29, 0xA1, 0xCB, 0x03, 0xB1, 0xCC, + 0x03, 0xA5, 0x25, 0x2D, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x0C, 0xBB, 0x31, 0xC6, + 0x03, 0x21, 0xD0, 0x03, 0x81, 0xCF, 0x03, 0x91, + 0xCD, 0x03, 0xA1, 0xCE, 0x03, 0xA9, 0xF9, 0x82, + 0x69, 0x19, 0x22, 0x63, 0x6B, 0xB2, 0x59, 0x1C, + 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x21, 0xD1, 0x03, 0x88, 0x22, 0x37, 0x68, 0x0E, + 0xA1, 0xD2, 0x03, 0xA5, 0x4D, 0x2D, 0x98, 0x22, + 0x6C, 0x7A, 0xA0, 0x99, 0x10, 0x99, 0x22, 0xE5, + 0x79, 0x22, 0x1D, 0xF0, 0x00, 0x36, 0x41, 0x00, + 0xCD, 0x04, 0xBD, 0x03, 0xAD, 0x02, 0xDD, 0x05, + 0x25, 0x0E, 0x2A, 0xAC, 0x15, 0x81, 0xD3, 0x03, + 0xA1, 0xD4, 0x03, 0x88, 0x08, 0x91, 0xD1, 0x03, + 0x82, 0x08, 0x02, 0x98, 0x29, 0xB6, 0x28, 0x06, + 0x91, 0xD5, 0x03, 0x99, 0x2A, 0x1D, 0xF0, 0x37, + 0x69, 0x05, 0x91, 0xD6, 0x03, 0x86, 0xFC, 0xFF, + 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, + 0xBD, 0x03, 0xAD, 0x02, 0xCD, 0x04, 0xDD, 0x05, + 0x1C, 0x8E, 0x25, 0x71, 0x22, 0xBC, 0x16, 0x82, + 0x12, 0x1A, 0x5A, 0xA4, 0xEC, 0xA8, 0x1C, 0x79, + 0xA7, 0x39, 0x28, 0x92, 0xA4, 0x21, 0x92, 0x52, + 0x1A, 0x06, 0x05, 0x00, 0xA1, 0xD2, 0x03, 0x25, + 0x42, 0x2D, 0xA8, 0x82, 0xE5, 0xBF, 0xFF, 0xB1, + 0xD1, 0x03, 0xA8, 0x2B, 0x30, 0xAA, 0x20, 0xA9, + 0x2B, 0xA8, 0x82, 0xA5, 0x05, 0x2D, 0x0C, 0x0B, + 0xB9, 0x82, 0x1D, 0xF0, 0x1C, 0x83, 0xA7, 0xB3, + 0xDA, 0x92, 0xA4, 0x22, 0x86, 0xF3, 0xFF, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x8C, 0x36, 0x0C, 0x03, + 0x32, 0x52, 0x1A, 0x1D, 0xF0, 0x36, 0x41, 0x00, + 0xA5, 0xB9, 0xFF, 0xAD, 0x02, 0x81, 0xD6, 0x03, + 0x89, 0x22, 0xE5, 0x8C, 0x29, 0x1D, 0xF0, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x31, 0xD7, 0x03, 0x21, + 0xD8, 0x03, 0x29, 0x13, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x81, 0xD9, 0x03, 0x30, + 0x61, 0x00, 0x88, 0x08, 0x82, 0x08, 0x10, 0x26, + 0x48, 0x07, 0xAD, 0x02, 0xA5, 0x54, 0x28, 0x06, + 0x01, 0x00, 0x0C, 0x0A, 0xE5, 0xED, 0x20, 0x30, + 0xE6, 0x13, 0x10, 0x20, 0x00, 0x1D, 0xF0, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x21, 0xDA, 0x03, 0x88, + 0x02, 0x27, 0x18, 0x09, 0xAD, 0x02, 0xE5, 0x07, + 0x00, 0xAD, 0x02, 0xE5, 0xE2, 0x20, 0x1D, 0xF0, + 0x00, 0x36, 0x41, 0x00, 0x20, 0x61, 0x00, 0xA1, + 0xDA, 0x03, 0xE5, 0xE1, 0x20, 0xA5, 0x28, 0x24, + 0x20, 0xE6, 0x13, 0x10, 0x20, 0x00, 0x1D, 0xF0, + 0x00, 0x36, 0x41, 0x00, 0x41, 0xDB, 0x03, 0x21, + 0xDC, 0x03, 0xC0, 0x20, 0x00, 0x32, 0x22, 0x81, + 0x98, 0x54, 0x88, 0x34, 0x30, 0x99, 0x20, 0x99, + 0x54, 0x87, 0x03, 0x06, 0x0C, 0x0A, 0xA9, 0x34, + 0xA5, 0xE5, 0x21, 0x0C, 0x1D, 0x3C, 0x8C, 0xB8, + 0x44, 0xC0, 0x20, 0x00, 0xC0, 0xBB, 0x10, 0xB2, + 0x62, 0x80, 0xC0, 0x20, 0x00, 0xE2, 0x22, 0x81, + 0xE0, 0xF0, 0x04, 0x07, 0xEE, 0xF3, 0xC0, 0x20, + 0x00, 0xB1, 0xDD, 0x03, 0x32, 0x62, 0x81, 0xC0, + 0x20, 0x00, 0xB8, 0x0B, 0xA1, 0xDE, 0x03, 0x1B, + 0xBB, 0xB9, 0x4A, 0x4B, 0xAA, 0x25, 0xDA, 0x20, + 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x20, 0x61, 0x00, 0x3C, 0x8A, 0x0C, 0x0B, 0xA5, + 0x25, 0x24, 0x20, 0xE6, 0x13, 0x10, 0x20, 0x00, + 0x1D, 0xF0, 0x00, 0x00, 0x00, 0xB8, 0x0F, 0x02, + 0x60, 0xC0, 0x0F, 0x02, 0x60, 0x04, 0x14, 0x02, + 0x60, 0xDC, 0x14, 0x02, 0x60, 0x04, 0x15, 0x00, + 0x60, 0x04, 0x15, 0x00, 0x60, 0x00, 0x15, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xF4, 0x14, 0x00, 0x60, 0xF8, 0x14, 0x00, + 0x60, 0x50, 0x15, 0x00, 0x60, 0x94, 0x02, 0x00, + 0x00, 0x78, 0x10, 0x02, 0x60, 0x53, 0x10, 0x02, + 0x60, 0x78, 0x10, 0x02, 0x60, 0x02, 0x11, 0x02, + 0x60, 0xDD, 0x10, 0x02, 0x60, 0xC2, 0x10, 0x02, + 0x60, 0x85, 0x10, 0x02, 0x60, 0x7E, 0x10, 0x02, + 0x60, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x0C, 0x00, + 0x60, 0xD4, 0x0C, 0x00, 0x60, 0x10, 0x30, 0x02, + 0x00, 0x60, 0x15, 0x00, 0x60, 0x00, 0x01, 0x00, + 0x00, 0xB0, 0x0A, 0x00, 0x60, 0x04, 0x13, 0x02, + 0x60, 0xA0, 0x0A, 0x00, 0x60, 0xA4, 0x13, 0x02, + 0x60, 0xF8, 0x13, 0x02, 0x60, 0x6C, 0x13, 0x02, + 0x60, 0x6C, 0x06, 0x00, 0x60, 0x14, 0x10, 0x02, + 0x60, 0xF4, 0x05, 0x00, 0x60, 0x4C, 0x13, 0x02, + 0x60, 0x68, 0x0A, 0x00, 0x60, 0x28, 0x8F, 0x04, + 0x60, 0x48, 0x08, 0x00, 0x60, 0x28, 0x14, 0x02, + 0x60, 0xAC, 0x06, 0x00, 0x60, 0x68, 0x14, 0x02, + 0x60, 0x80, 0x14, 0x02, 0x60, 0xD8, 0x56, 0x04, + 0x60, 0x36, 0x41, 0x00, 0x81, 0x57, 0x05, 0xB1, + 0x55, 0x05, 0x0C, 0x3A, 0x91, 0x56, 0x05, 0xA2, + 0x4B, 0x00, 0x89, 0x09, 0xE5, 0x01, 0x00, 0xE5, + 0x05, 0x00, 0xA5, 0x06, 0x00, 0x65, 0x07, 0x00, + 0x25, 0x02, 0x00, 0xA1, 0x58, 0x05, 0xB1, 0x59, + 0x05, 0x25, 0xFA, 0x2C, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x31, 0x5A, 0x05, 0x21, + 0x5B, 0x05, 0x22, 0x63, 0x75, 0x1D, 0xF0, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x0C, 0x8F, 0xB1, 0x5A, + 0x05, 0xA1, 0x5F, 0x05, 0x91, 0x60, 0x05, 0x81, + 0x61, 0x05, 0x31, 0x62, 0x05, 0x21, 0x63, 0x05, + 0xC1, 0x5E, 0x05, 0xD1, 0x5C, 0x05, 0xE1, 0x5D, + 0x05, 0xE9, 0xFD, 0xC2, 0x6D, 0x19, 0x29, 0x83, + 0x89, 0x39, 0xA2, 0x6B, 0x6B, 0xF2, 0x5D, 0x1C, + 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x31, 0x64, 0x05, 0x21, 0x65, 0x05, 0x29, 0x13, + 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x31, 0x66, 0x05, 0x21, 0x67, 0x05, 0x22, 0x63, + 0x19, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x91, 0x69, 0x05, 0x21, 0x6B, 0x05, 0x31, 0x68, + 0x05, 0x81, 0x6A, 0x05, 0x89, 0xC3, 0x29, 0xA3, + 0x99, 0xB3, 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x04, 0x00, 0xB0, 0x15, 0x02, + 0x60, }; static const unsigned char vfs301_06_3[] = { /* 785 B */ - 0x06, 0x00, 0x00, 0x04, 0x03, 0x00, 0x0F, 0x00, - 0x60, 0xD8, 0x0C, 0x00, 0x60, 0xD4, 0x0C, 0x00, - 0x60, 0xB0, 0x0A, 0x00, 0x60, 0x58, 0xB3, 0x04, - 0x60, 0x84, 0x05, 0x00, 0x60, 0xA4, 0xED, 0x04, - 0x60, 0x8C, 0x04, 0x00, 0x00, 0xBC, 0x08, 0x00, - 0x60, 0x00, 0x0F, 0x00, 0x60, 0x50, 0x02, 0x00, - 0x00, 0xFC, 0x07, 0x00, 0x60, 0xF4, 0x8B, 0x04, - 0x60, 0xBC, 0x0D, 0x00, 0x60, 0xDC, 0x0C, 0x00, - 0x60, 0xC0, 0x0D, 0x00, 0x60, 0x40, 0x11, 0x00, - 0x60, 0x18, 0x0D, 0x00, 0x60, 0x00, 0x9E, 0x00, - 0x38, 0x3C, 0x11, 0x00, 0x60, 0x36, 0x41, 0x00, - 0xE5, 0x02, 0x00, 0x65, 0x14, 0x00, 0x25, 0x06, - 0x00, 0x25, 0x01, 0x00, 0x91, 0xC0, 0x03, 0xA1, - 0xC1, 0x03, 0x0C, 0x08, 0x89, 0x0A, 0x82, 0x49, - 0x00, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x31, 0xC2, 0x03, 0x21, 0xC3, 0x03, 0x22, 0x63, - 0x75, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, - 0xA1, 0xC4, 0x03, 0xB1, 0xC5, 0x03, 0xC1, 0xC6, - 0x03, 0xE5, 0x94, 0x2D, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x9C, 0xD5, 0x20, 0x61, - 0x00, 0x25, 0xFB, 0xFF, 0x81, 0xC7, 0x03, 0x20, - 0xE6, 0x13, 0x10, 0x20, 0x00, 0x88, 0x28, 0x0C, - 0x0A, 0xE0, 0x08, 0x00, 0xA1, 0xC8, 0x03, 0xB1, - 0xC9, 0x03, 0xA5, 0x5C, 0x2D, 0x1D, 0xF0, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x31, 0xCA, 0x03, 0x21, - 0xCB, 0x03, 0x29, 0xD3, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x41, 0xCC, 0x03, 0x88, - 0x04, 0x22, 0x08, 0xD2, 0x80, 0x22, 0xA0, 0x28, - 0x92, 0xAD, 0x02, 0xE5, 0x73, 0x2D, 0xC0, 0x20, - 0x00, 0x5D, 0x0A, 0x38, 0x0A, 0xA2, 0xC2, 0x10, - 0x25, 0x73, 0x2D, 0x88, 0x04, 0x30, 0x9A, 0x10, - 0x82, 0x28, 0x1D, 0xC0, 0x20, 0x00, 0x90, 0x88, - 0x20, 0x89, 0x05, 0xC0, 0x20, 0x00, 0x38, 0x05, - 0x7C, 0xF5, 0x50, 0x5A, 0x30, 0x30, 0x35, 0x10, - 0xCB, 0xA2, 0xE5, 0x70, 0x2D, 0x37, 0x9A, 0x29, - 0x4B, 0xA2, 0x65, 0x70, 0x2D, 0xB8, 0x04, 0xCD, - 0x0A, 0xA2, 0xC2, 0x14, 0x92, 0x2B, 0x1E, 0xC2, - 0x6B, 0x1D, 0x1B, 0x99, 0x92, 0x6B, 0x1E, 0x25, - 0x6F, 0x2D, 0xB8, 0x04, 0xD2, 0x2B, 0x1E, 0xD7, - 0xBA, 0x16, 0xA2, 0xCB, 0x64, 0x25, 0x2E, 0x2D, - 0x1D, 0xF0, 0x8B, 0xA2, 0xE5, 0x6D, 0x2D, 0xF8, - 0x04, 0x3A, 0xEA, 0xE0, 0xE5, 0x10, 0xE2, 0x6F, - 0x1D, 0x81, 0xCA, 0x03, 0x82, 0x28, 0x12, 0xE0, - 0x08, 0x00, 0xA2, 0xA0, 0x94, 0xC1, 0xCD, 0x03, - 0xB8, 0x04, 0xC0, 0x20, 0x00, 0xC8, 0x0C, 0x92, - 0x1B, 0x5D, 0xAA, 0xAB, 0xCA, 0x99, 0x92, 0x6B, - 0x28, 0xE5, 0x20, 0x21, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x81, 0xCE, 0x03, 0x30, - 0x61, 0x00, 0x88, 0x08, 0x82, 0x08, 0x10, 0x26, - 0x48, 0x07, 0xAD, 0x02, 0x25, 0x90, 0x28, 0x06, - 0x01, 0x00, 0x0C, 0x0A, 0x65, 0x29, 0x21, 0x30, - 0xE6, 0x13, 0x10, 0x20, 0x00, 0x1D, 0xF0, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x21, 0xCF, 0x03, 0x88, - 0x02, 0x27, 0x18, 0x09, 0xAD, 0x02, 0xE5, 0x07, - 0x00, 0xAD, 0x02, 0x65, 0x1E, 0x21, 0x1D, 0xF0, - 0x00, 0x36, 0x41, 0x00, 0x20, 0x61, 0x00, 0xA1, - 0xCF, 0x03, 0x65, 0x1D, 0x21, 0x25, 0x64, 0x24, - 0x20, 0xE6, 0x13, 0x10, 0x20, 0x00, 0x1D, 0xF0, - 0x00, 0x36, 0x41, 0x00, 0x41, 0xD0, 0x03, 0x21, - 0xD1, 0x03, 0xC0, 0x20, 0x00, 0x32, 0x22, 0x81, - 0x98, 0x54, 0x88, 0x34, 0x30, 0x99, 0x20, 0x99, - 0x54, 0x87, 0x03, 0x06, 0x0C, 0x0A, 0xA9, 0x34, - 0x25, 0x21, 0x22, 0x0C, 0x1D, 0x3C, 0x8C, 0xB8, - 0x44, 0xC0, 0x20, 0x00, 0xC0, 0xBB, 0x10, 0xB2, - 0x62, 0x80, 0xC0, 0x20, 0x00, 0xE2, 0x22, 0x81, - 0xE0, 0xF0, 0x04, 0x07, 0xEE, 0xF3, 0xC0, 0x20, - 0x00, 0xB1, 0xCD, 0x03, 0x32, 0x62, 0x81, 0xC0, - 0x20, 0x00, 0xB8, 0x0B, 0xA1, 0xD2, 0x03, 0x1B, - 0xBB, 0xB9, 0x4A, 0x4B, 0xAA, 0xA5, 0x15, 0x21, - 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x20, 0x61, 0x00, 0x3C, 0x8A, 0x0C, 0x0B, 0x25, - 0x61, 0x24, 0x20, 0xE6, 0x13, 0x10, 0x20, 0x00, - 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x24, 0x11, 0x02, - 0x60, 0x40, 0x11, 0x00, 0x60, 0x40, 0x11, 0x00, - 0x60, 0x3C, 0x11, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x00, 0xD8, 0x0C, 0x00, 0x60, 0xD4, 0x0C, 0x00, - 0x60, 0x12, 0x30, 0x00, 0x00, 0x50, 0x11, 0x00, - 0x60, 0xB0, 0x00, 0x00, 0x00, 0xB0, 0x0A, 0x00, - 0x60, 0x90, 0x0F, 0x02, 0x60, 0xFC, 0x07, 0x00, - 0x60, 0xC8, 0x0F, 0x02, 0x60, 0x48, 0x08, 0x00, - 0x60, 0x70, 0x10, 0x02, 0x60, 0xAC, 0x06, 0x00, - 0x60, 0xB0, 0x10, 0x02, 0x60, 0xC8, 0x10, 0x02, - 0x60, 0xD8, 0x56, 0x04, 0x60, 0x36, 0x41, 0x00, - 0x81, 0x56, 0x04, 0xB1, 0x54, 0x04, 0x0C, 0x1A, - 0x91, 0x55, 0x04, 0xA2, 0x4B, 0x00, 0x89, 0x09, - 0xA5, 0x01, 0x00, 0x65, 0x02, 0x00, 0x25, 0x03, - 0x00, 0xE5, 0x03, 0x00, 0xA1, 0x57, 0x04, 0xB1, - 0x58, 0x04, 0xA5, 0x3C, 0x2D, 0x1D, 0xF0, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x31, 0x59, 0x04, 0x21, - 0x5A, 0x04, 0x22, 0x63, 0x75, 0x1D, 0xF0, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x31, 0x5B, 0x04, 0x21, - 0x5C, 0x04, 0x29, 0xD3, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x31, 0x5D, 0x04, 0x21, - 0x5E, 0x04, 0x22, 0x63, 0x19, 0x1D, 0xF0, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x91, 0x60, 0x04, 0x21, - 0x62, 0x04, 0x31, 0x5F, 0x04, 0x81, 0x61, 0x04, - 0x89, 0xC3, 0x29, 0xA3, 0x99, 0xB3, 0x1D, 0xF0, - 0x00, 0x01, 0x00, 0x04, 0x00, 0x8C, 0x11, 0x02, - 0x60, + 0x06, 0x00, 0x00, 0x04, 0x03, 0x00, 0x0F, 0x00, + 0x60, 0xD8, 0x0C, 0x00, 0x60, 0xD4, 0x0C, 0x00, + 0x60, 0xB0, 0x0A, 0x00, 0x60, 0x58, 0xB3, 0x04, + 0x60, 0x84, 0x05, 0x00, 0x60, 0xA4, 0xED, 0x04, + 0x60, 0x8C, 0x04, 0x00, 0x00, 0xBC, 0x08, 0x00, + 0x60, 0x00, 0x0F, 0x00, 0x60, 0x50, 0x02, 0x00, + 0x00, 0xFC, 0x07, 0x00, 0x60, 0xF4, 0x8B, 0x04, + 0x60, 0xBC, 0x0D, 0x00, 0x60, 0xDC, 0x0C, 0x00, + 0x60, 0xC0, 0x0D, 0x00, 0x60, 0x40, 0x11, 0x00, + 0x60, 0x18, 0x0D, 0x00, 0x60, 0x00, 0x9E, 0x00, + 0x38, 0x3C, 0x11, 0x00, 0x60, 0x36, 0x41, 0x00, + 0xE5, 0x02, 0x00, 0x65, 0x14, 0x00, 0x25, 0x06, + 0x00, 0x25, 0x01, 0x00, 0x91, 0xC0, 0x03, 0xA1, + 0xC1, 0x03, 0x0C, 0x08, 0x89, 0x0A, 0x82, 0x49, + 0x00, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x31, 0xC2, 0x03, 0x21, 0xC3, 0x03, 0x22, 0x63, + 0x75, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, + 0xA1, 0xC4, 0x03, 0xB1, 0xC5, 0x03, 0xC1, 0xC6, + 0x03, 0xE5, 0x94, 0x2D, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x9C, 0xD5, 0x20, 0x61, + 0x00, 0x25, 0xFB, 0xFF, 0x81, 0xC7, 0x03, 0x20, + 0xE6, 0x13, 0x10, 0x20, 0x00, 0x88, 0x28, 0x0C, + 0x0A, 0xE0, 0x08, 0x00, 0xA1, 0xC8, 0x03, 0xB1, + 0xC9, 0x03, 0xA5, 0x5C, 0x2D, 0x1D, 0xF0, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x31, 0xCA, 0x03, 0x21, + 0xCB, 0x03, 0x29, 0xD3, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x41, 0xCC, 0x03, 0x88, + 0x04, 0x22, 0x08, 0xD2, 0x80, 0x22, 0xA0, 0x28, + 0x92, 0xAD, 0x02, 0xE5, 0x73, 0x2D, 0xC0, 0x20, + 0x00, 0x5D, 0x0A, 0x38, 0x0A, 0xA2, 0xC2, 0x10, + 0x25, 0x73, 0x2D, 0x88, 0x04, 0x30, 0x9A, 0x10, + 0x82, 0x28, 0x1D, 0xC0, 0x20, 0x00, 0x90, 0x88, + 0x20, 0x89, 0x05, 0xC0, 0x20, 0x00, 0x38, 0x05, + 0x7C, 0xF5, 0x50, 0x5A, 0x30, 0x30, 0x35, 0x10, + 0xCB, 0xA2, 0xE5, 0x70, 0x2D, 0x37, 0x9A, 0x29, + 0x4B, 0xA2, 0x65, 0x70, 0x2D, 0xB8, 0x04, 0xCD, + 0x0A, 0xA2, 0xC2, 0x14, 0x92, 0x2B, 0x1E, 0xC2, + 0x6B, 0x1D, 0x1B, 0x99, 0x92, 0x6B, 0x1E, 0x25, + 0x6F, 0x2D, 0xB8, 0x04, 0xD2, 0x2B, 0x1E, 0xD7, + 0xBA, 0x16, 0xA2, 0xCB, 0x64, 0x25, 0x2E, 0x2D, + 0x1D, 0xF0, 0x8B, 0xA2, 0xE5, 0x6D, 0x2D, 0xF8, + 0x04, 0x3A, 0xEA, 0xE0, 0xE5, 0x10, 0xE2, 0x6F, + 0x1D, 0x81, 0xCA, 0x03, 0x82, 0x28, 0x12, 0xE0, + 0x08, 0x00, 0xA2, 0xA0, 0x94, 0xC1, 0xCD, 0x03, + 0xB8, 0x04, 0xC0, 0x20, 0x00, 0xC8, 0x0C, 0x92, + 0x1B, 0x5D, 0xAA, 0xAB, 0xCA, 0x99, 0x92, 0x6B, + 0x28, 0xE5, 0x20, 0x21, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x81, 0xCE, 0x03, 0x30, + 0x61, 0x00, 0x88, 0x08, 0x82, 0x08, 0x10, 0x26, + 0x48, 0x07, 0xAD, 0x02, 0x25, 0x90, 0x28, 0x06, + 0x01, 0x00, 0x0C, 0x0A, 0x65, 0x29, 0x21, 0x30, + 0xE6, 0x13, 0x10, 0x20, 0x00, 0x1D, 0xF0, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x21, 0xCF, 0x03, 0x88, + 0x02, 0x27, 0x18, 0x09, 0xAD, 0x02, 0xE5, 0x07, + 0x00, 0xAD, 0x02, 0x65, 0x1E, 0x21, 0x1D, 0xF0, + 0x00, 0x36, 0x41, 0x00, 0x20, 0x61, 0x00, 0xA1, + 0xCF, 0x03, 0x65, 0x1D, 0x21, 0x25, 0x64, 0x24, + 0x20, 0xE6, 0x13, 0x10, 0x20, 0x00, 0x1D, 0xF0, + 0x00, 0x36, 0x41, 0x00, 0x41, 0xD0, 0x03, 0x21, + 0xD1, 0x03, 0xC0, 0x20, 0x00, 0x32, 0x22, 0x81, + 0x98, 0x54, 0x88, 0x34, 0x30, 0x99, 0x20, 0x99, + 0x54, 0x87, 0x03, 0x06, 0x0C, 0x0A, 0xA9, 0x34, + 0x25, 0x21, 0x22, 0x0C, 0x1D, 0x3C, 0x8C, 0xB8, + 0x44, 0xC0, 0x20, 0x00, 0xC0, 0xBB, 0x10, 0xB2, + 0x62, 0x80, 0xC0, 0x20, 0x00, 0xE2, 0x22, 0x81, + 0xE0, 0xF0, 0x04, 0x07, 0xEE, 0xF3, 0xC0, 0x20, + 0x00, 0xB1, 0xCD, 0x03, 0x32, 0x62, 0x81, 0xC0, + 0x20, 0x00, 0xB8, 0x0B, 0xA1, 0xD2, 0x03, 0x1B, + 0xBB, 0xB9, 0x4A, 0x4B, 0xAA, 0xA5, 0x15, 0x21, + 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x20, 0x61, 0x00, 0x3C, 0x8A, 0x0C, 0x0B, 0x25, + 0x61, 0x24, 0x20, 0xE6, 0x13, 0x10, 0x20, 0x00, + 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x24, 0x11, 0x02, + 0x60, 0x40, 0x11, 0x00, 0x60, 0x40, 0x11, 0x00, + 0x60, 0x3C, 0x11, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x00, 0xD8, 0x0C, 0x00, 0x60, 0xD4, 0x0C, 0x00, + 0x60, 0x12, 0x30, 0x00, 0x00, 0x50, 0x11, 0x00, + 0x60, 0xB0, 0x00, 0x00, 0x00, 0xB0, 0x0A, 0x00, + 0x60, 0x90, 0x0F, 0x02, 0x60, 0xFC, 0x07, 0x00, + 0x60, 0xC8, 0x0F, 0x02, 0x60, 0x48, 0x08, 0x00, + 0x60, 0x70, 0x10, 0x02, 0x60, 0xAC, 0x06, 0x00, + 0x60, 0xB0, 0x10, 0x02, 0x60, 0xC8, 0x10, 0x02, + 0x60, 0xD8, 0x56, 0x04, 0x60, 0x36, 0x41, 0x00, + 0x81, 0x56, 0x04, 0xB1, 0x54, 0x04, 0x0C, 0x1A, + 0x91, 0x55, 0x04, 0xA2, 0x4B, 0x00, 0x89, 0x09, + 0xA5, 0x01, 0x00, 0x65, 0x02, 0x00, 0x25, 0x03, + 0x00, 0xE5, 0x03, 0x00, 0xA1, 0x57, 0x04, 0xB1, + 0x58, 0x04, 0xA5, 0x3C, 0x2D, 0x1D, 0xF0, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x31, 0x59, 0x04, 0x21, + 0x5A, 0x04, 0x22, 0x63, 0x75, 0x1D, 0xF0, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x31, 0x5B, 0x04, 0x21, + 0x5C, 0x04, 0x29, 0xD3, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x31, 0x5D, 0x04, 0x21, + 0x5E, 0x04, 0x22, 0x63, 0x19, 0x1D, 0xF0, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x91, 0x60, 0x04, 0x21, + 0x62, 0x04, 0x31, 0x5F, 0x04, 0x81, 0x61, 0x04, + 0x89, 0xC3, 0x29, 0xA3, 0x99, 0xB3, 0x1D, 0xF0, + 0x00, 0x01, 0x00, 0x04, 0x00, 0x8C, 0x11, 0x02, + 0x60, }; static const unsigned char vfs301_06_4[] = { /* 3057 B */ - 0x06, 0x00, 0x00, 0xE4, 0x0B, 0x00, 0x0F, 0x00, - 0x60, 0xD8, 0x0C, 0x00, 0x60, 0xD4, 0x0C, 0x00, - 0x60, 0xB0, 0x0A, 0x00, 0x60, 0x58, 0xB3, 0x04, - 0x60, 0x84, 0x05, 0x00, 0x60, 0xA4, 0xED, 0x04, - 0x60, 0x8C, 0x04, 0x00, 0x00, 0x00, 0x0F, 0x00, - 0x60, 0xC0, 0x0A, 0x00, 0x00, 0xA0, 0x0A, 0x00, - 0x60, 0xD0, 0x38, 0x04, 0x60, 0xB4, 0x39, 0x04, - 0x60, 0x58, 0xB4, 0x04, 0x60, 0xFC, 0x0C, 0x00, - 0x60, 0x80, 0x19, 0x00, 0x60, 0xC8, 0x0D, 0x00, - 0x60, 0x9C, 0x0B, 0x00, 0x60, 0xF4, 0x18, 0x00, - 0x60, 0xCC, 0x08, 0x00, 0x60, 0xF8, 0x18, 0x00, - 0x60, 0xA8, 0x0B, 0x00, 0x60, 0xE4, 0x06, 0x00, - 0x60, 0x54, 0x11, 0x02, 0x60, 0xAC, 0x06, 0x00, - 0x60, 0x48, 0x11, 0x02, 0x60, 0x04, 0x19, 0x00, - 0x60, 0x80, 0x7F, 0x00, 0x38, 0x80, 0x5F, 0x00, - 0x38, 0x80, 0x3F, 0x00, 0x38, 0xDC, 0x0C, 0x00, - 0x60, 0x1C, 0x19, 0x00, 0x60, 0x2C, 0x19, 0x00, - 0x60, 0x48, 0x19, 0x00, 0x60, 0x00, 0x40, 0x00, - 0x38, 0x00, 0xA0, 0x00, 0x38, 0x68, 0x0A, 0x00, - 0x60, 0x4C, 0x3F, 0x04, 0x60, 0xC0, 0x0D, 0x00, - 0x60, 0x5C, 0x19, 0x00, 0x60, 0x18, 0x0D, 0x00, - 0x60, 0x00, 0x9E, 0x00, 0x38, 0x58, 0x19, 0x00, - 0x60, 0xB0, 0x19, 0x00, 0x60, 0x20, 0x0E, 0x00, - 0x60, 0xFC, 0xFF, 0x00, 0x00, 0x90, 0x19, 0x00, - 0x60, 0x36, 0x41, 0x00, 0x65, 0x03, 0x00, 0x25, - 0x18, 0x00, 0x65, 0x15, 0x00, 0x25, 0x06, 0x00, - 0x25, 0x54, 0x00, 0x65, 0x50, 0x00, 0x25, 0x01, - 0x00, 0x91, 0xC0, 0x03, 0xA1, 0xC1, 0x03, 0x0C, - 0x08, 0x89, 0x0A, 0x82, 0x49, 0x00, 0x1D, 0xF0, - 0x00, 0x36, 0x41, 0x00, 0x31, 0xC2, 0x03, 0x21, - 0xC3, 0x03, 0x22, 0x63, 0x75, 0x1D, 0xF0, 0x00, - 0x00, 0x36, 0x41, 0x00, 0xA1, 0xC4, 0x03, 0xB1, - 0xC5, 0x03, 0xC1, 0xC6, 0x03, 0xA5, 0x8D, 0x2D, - 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x9C, 0x85, 0x20, 0x61, 0x00, 0xA5, 0xFA, 0xFF, - 0x20, 0xE6, 0x13, 0x10, 0x20, 0x00, 0x0C, 0x0A, - 0x65, 0xC8, 0x29, 0xA1, 0xC7, 0x03, 0xB1, 0xC8, - 0x03, 0xA5, 0x55, 0x2D, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x0C, 0xBB, 0x31, 0xC2, - 0x03, 0x21, 0xCC, 0x03, 0x81, 0xCB, 0x03, 0x91, - 0xC9, 0x03, 0xA1, 0xCA, 0x03, 0xA9, 0xF9, 0x82, - 0x69, 0x19, 0x22, 0x63, 0x6B, 0xB2, 0x59, 0x1C, - 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x21, 0xCD, 0x03, 0x88, 0x22, 0x37, 0x68, 0x0E, - 0xA1, 0xCE, 0x03, 0xA5, 0x7D, 0x2D, 0x98, 0x22, - 0x6C, 0x7A, 0xA0, 0x99, 0x10, 0x99, 0x22, 0xE5, - 0xA9, 0x22, 0x1D, 0xF0, 0x00, 0x36, 0x41, 0x00, - 0xCD, 0x04, 0xBD, 0x03, 0xAD, 0x02, 0xDD, 0x05, - 0x25, 0x3E, 0x2A, 0xAC, 0x15, 0x81, 0xCF, 0x03, - 0xA1, 0xD0, 0x03, 0x88, 0x08, 0x91, 0xCD, 0x03, - 0x82, 0x08, 0x02, 0x98, 0x29, 0xB6, 0x28, 0x06, - 0x91, 0xD1, 0x03, 0x99, 0x2A, 0x1D, 0xF0, 0x37, - 0x69, 0x05, 0x91, 0xD2, 0x03, 0x86, 0xFC, 0xFF, - 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, - 0xBD, 0x03, 0xAD, 0x02, 0xCD, 0x04, 0xDD, 0x05, - 0x1C, 0x8E, 0x25, 0xA1, 0x22, 0xBC, 0x16, 0x82, - 0x12, 0x1A, 0x5A, 0xA4, 0xEC, 0xA8, 0x1C, 0x79, - 0xA7, 0x39, 0x28, 0x92, 0xA4, 0x21, 0x92, 0x52, - 0x1A, 0x06, 0x05, 0x00, 0xA1, 0xCE, 0x03, 0x25, - 0x72, 0x2D, 0xA8, 0x82, 0xA5, 0x50, 0x00, 0xB1, - 0xCD, 0x03, 0xA8, 0x2B, 0x30, 0xAA, 0x20, 0xA9, - 0x2B, 0xA8, 0x82, 0xA5, 0x35, 0x2D, 0x0C, 0x0B, - 0xB9, 0x82, 0x1D, 0xF0, 0x1C, 0x83, 0xA7, 0xB3, - 0xDA, 0x92, 0xA4, 0x22, 0x86, 0xF3, 0xFF, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x8C, 0x36, 0x0C, 0x03, - 0x32, 0x52, 0x1A, 0x1D, 0xF0, 0x36, 0x41, 0x00, - 0x65, 0x4A, 0x00, 0xAD, 0x02, 0x81, 0xD2, 0x03, - 0x89, 0x22, 0xE5, 0xBC, 0x29, 0x1D, 0xF0, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x21, 0xD3, 0x03, 0x31, - 0xD4, 0x03, 0x28, 0x22, 0x29, 0x03, 0x1D, 0xF0, - 0x00, 0x36, 0x41, 0x00, 0x21, 0xD8, 0x03, 0x31, - 0xD7, 0x03, 0x91, 0xD5, 0x03, 0x81, 0xD6, 0x03, - 0x89, 0x49, 0x29, 0x03, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x25, 0x18, 0x00, 0x1D, - 0xF0, 0x36, 0x41, 0x00, 0xA5, 0x17, 0x00, 0x65, - 0x20, 0x24, 0x1D, 0xF0, 0x00, 0x36, 0x41, 0x00, - 0xAD, 0x02, 0x65, 0xBE, 0x24, 0x65, 0x16, 0x00, - 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x61, 0xD9, 0x03, 0xCC, 0xE4, 0xA2, 0xA0, 0x76, - 0x65, 0x22, 0x2D, 0xA9, 0x36, 0xCC, 0x4A, 0xA2, - 0xA4, 0x31, 0x25, 0xB2, 0x29, 0x72, 0xA0, 0x76, - 0xD8, 0x36, 0xA2, 0xA0, 0x75, 0xAC, 0x2D, 0x4A, - 0xB3, 0xB7, 0x37, 0x0E, 0xDA, 0xA4, 0xBD, 0x02, - 0xCD, 0x03, 0x65, 0x74, 0x2D, 0xA2, 0xA0, 0x75, - 0xC6, 0x03, 0x00, 0x47, 0x3A, 0x0C, 0xDA, 0xA4, - 0xBD, 0x02, 0x40, 0xC7, 0xC0, 0x25, 0x73, 0x2D, - 0xA2, 0xA0, 0x75, 0xBC, 0x75, 0xC8, 0x36, 0x4A, - 0xB3, 0xBC, 0x1C, 0xB7, 0x3A, 0x08, 0xA2, 0xA4, - 0x05, 0x25, 0xAE, 0x29, 0x46, 0x07, 0x00, 0xB7, - 0xB7, 0x25, 0xA2, 0xA4, 0x06, 0x65, 0xAD, 0x29, - 0x46, 0x04, 0x00, 0x0C, 0x0A, 0xE5, 0xAC, 0x29, - 0xA8, 0x46, 0xB8, 0x36, 0xC2, 0xA0, 0x76, 0x25, - 0x70, 0x2D, 0xA5, 0x02, 0x00, 0xA8, 0x36, 0xE5, - 0x25, 0x2D, 0x0C, 0x0D, 0xD9, 0x36, 0x1D, 0xF0, - 0xE8, 0x46, 0x8C, 0x1E, 0xA5, 0x0D, 0x00, 0xA2, - 0xA0, 0x76, 0x25, 0x1A, 0x2D, 0xA9, 0x46, 0x56, - 0x0A, 0xFD, 0xA2, 0xA4, 0x31, 0xE5, 0xA9, 0x29, - 0x46, 0xF6, 0xFF, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x21, 0xD9, 0x03, 0x91, 0xDA, 0x03, 0xB1, 0xDB, - 0x03, 0x81, 0xDC, 0x03, 0xC0, 0x20, 0x00, 0xA2, - 0x08, 0x84, 0xC0, 0x20, 0x00, 0xD2, 0x0B, 0x84, - 0xC0, 0x20, 0x00, 0xC2, 0x09, 0x84, 0x80, 0xDD, - 0x11, 0xD0, 0xAA, 0x20, 0x00, 0xCC, 0x11, 0xC0, - 0xAA, 0x20, 0xA9, 0xE2, 0xC0, 0x20, 0x00, 0x82, - 0x08, 0x81, 0xC0, 0x20, 0x00, 0xB2, 0x0B, 0x81, - 0xC0, 0x20, 0x00, 0xA8, 0x42, 0x80, 0xBB, 0x11, - 0x92, 0x09, 0x81, 0xB0, 0x88, 0x20, 0x00, 0x99, - 0x11, 0x90, 0x88, 0x20, 0x89, 0xF2, 0xE5, 0x73, - 0x24, 0x31, 0xDD, 0x03, 0x98, 0x42, 0x0C, 0x0B, - 0xA2, 0x09, 0x70, 0x92, 0x09, 0x71, 0xB2, 0x42, - 0x14, 0x80, 0x99, 0x11, 0xA0, 0x99, 0x20, 0x16, - 0x79, 0x04, 0xC0, 0x20, 0x00, 0xB8, 0x03, 0x9A, - 0xBB, 0x0B, 0xBB, 0xB9, 0x92, 0xA1, 0xDE, 0x03, - 0xA5, 0xFF, 0x20, 0xB8, 0x42, 0xB2, 0x0B, 0x75, - 0x9C, 0x9B, 0xC0, 0x20, 0x00, 0xA1, 0xDF, 0x03, - 0xD8, 0x03, 0xB0, 0xCB, 0x11, 0xB0, 0xCC, 0xC0, - 0xB0, 0xCC, 0xA0, 0xD0, 0xCC, 0xB0, 0x0B, 0xCC, - 0xC9, 0xD2, 0x65, 0xFD, 0x20, 0xA1, 0xE0, 0x03, - 0x0C, 0x1E, 0xE2, 0x62, 0x10, 0xC0, 0x20, 0x00, - 0xD8, 0x03, 0xD2, 0x62, 0x14, 0x25, 0xFC, 0x20, - 0x1D, 0xF0, 0xC0, 0x20, 0x00, 0xB8, 0x03, 0x06, - 0xEE, 0xFF, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x21, 0xD9, 0x03, 0x88, 0x42, 0x16, 0x28, 0x08, - 0xA2, 0xC2, 0x44, 0xE5, 0xFB, 0x20, 0xB8, 0x42, - 0x92, 0x0B, 0x74, 0x26, 0x19, 0x14, 0xA2, 0xC9, - 0xFE, 0x16, 0x9A, 0x07, 0xC2, 0xC9, 0xFD, 0x16, - 0xAC, 0x06, 0xA2, 0xCB, 0x48, 0x25, 0x1A, 0x00, - 0x46, 0x01, 0x00, 0xA2, 0xCB, 0x50, 0xA5, 0x19, - 0x00, 0xA1, 0xDE, 0x03, 0x65, 0xF9, 0x20, 0xA1, - 0xDF, 0x03, 0xE5, 0xF8, 0x20, 0xE1, 0xDA, 0x03, - 0x81, 0xDB, 0x03, 0xA1, 0xDC, 0x03, 0xD8, 0xE2, - 0xC0, 0x20, 0x00, 0xD2, 0x4A, 0x84, 0xC8, 0xE2, - 0xC0, 0x20, 0x00, 0xC0, 0xC8, 0x41, 0xC2, 0x48, - 0x84, 0xB8, 0xE2, 0xC0, 0x20, 0x00, 0xB0, 0xB0, - 0xF5, 0xB2, 0x4E, 0x84, 0x98, 0xF2, 0xC0, 0x20, - 0x00, 0x92, 0x4A, 0x81, 0xF8, 0xF2, 0xC0, 0x20, - 0x00, 0xF0, 0xF8, 0x41, 0xF2, 0x48, 0x81, 0xD8, - 0xF2, 0xC0, 0x20, 0x00, 0xD0, 0xD0, 0xF5, 0xD2, - 0x4E, 0x81, 0xA8, 0x42, 0x25, 0x0F, 0x2D, 0x0C, - 0x0E, 0xE9, 0x42, 0x1D, 0xF0, 0xA2, 0xCB, 0x60, - 0xA5, 0x13, 0x00, 0x86, 0xE6, 0xFF, 0xA2, 0xCB, - 0x58, 0xE5, 0x12, 0x00, 0x46, 0xE4, 0xFF, 0x00, - 0x00, 0x36, 0x41, 0x00, 0xB1, 0xD9, 0x03, 0x0C, - 0x1D, 0x98, 0x4B, 0xA2, 0x0B, 0x14, 0xAC, 0x79, - 0xC1, 0xDD, 0x03, 0xEC, 0x4A, 0xA2, 0x09, 0x72, - 0xE2, 0x09, 0x73, 0xD2, 0x4B, 0x14, 0x80, 0x9E, - 0x11, 0xA0, 0x99, 0x20, 0xBC, 0xD9, 0xC0, 0x20, - 0x00, 0xA8, 0x0C, 0x9A, 0x9A, 0x0B, 0x99, 0x99, - 0x32, 0xD2, 0x6B, 0x10, 0xAD, 0x02, 0xA5, 0xED, - 0x20, 0x1D, 0xF0, 0x66, 0x1A, 0xF2, 0xE2, 0x09, - 0x71, 0xA2, 0x09, 0x70, 0x80, 0x9E, 0x11, 0xA0, - 0x99, 0x20, 0x0C, 0x0E, 0xE2, 0x4B, 0x14, 0x8C, - 0xA9, 0xC0, 0x20, 0x00, 0xA8, 0x0C, 0x9A, 0x9A, - 0x0B, 0x99, 0x46, 0xF4, 0xFF, 0xC0, 0x20, 0x00, - 0x98, 0x0C, 0x46, 0xF2, 0xFF, 0xC0, 0x20, 0x00, - 0x98, 0x0C, 0x46, 0xF0, 0xFF, 0x36, 0x41, 0x00, - 0x31, 0xD9, 0x03, 0xB8, 0x43, 0x92, 0x03, 0x14, - 0x16, 0xFB, 0x09, 0xFC, 0x99, 0x82, 0x0B, 0x71, - 0xA2, 0x0B, 0x70, 0x80, 0x88, 0x11, 0xA0, 0x88, - 0x20, 0xAC, 0xB8, 0xC2, 0x0B, 0x68, 0x92, 0x0B, - 0x6B, 0xA2, 0x0B, 0x6A, 0x80, 0x99, 0x11, 0xA0, - 0x99, 0x20, 0xA2, 0x0B, 0x69, 0x80, 0x99, 0x11, - 0xA0, 0x99, 0x20, 0xA2, 0x23, 0x10, 0x80, 0x99, - 0x11, 0xC0, 0x99, 0x20, 0xA7, 0x09, 0x6D, 0xA2, - 0xCB, 0x50, 0x65, 0x07, 0x00, 0xC6, 0x10, 0x00, - 0x66, 0x19, 0x40, 0xA2, 0x0B, 0x73, 0xC2, 0x0B, - 0x72, 0x80, 0xAA, 0x11, 0xC0, 0xAA, 0x20, 0xBC, - 0x1A, 0xE2, 0x0B, 0x6C, 0xC2, 0x0B, 0x6F, 0xD2, - 0x0B, 0x6E, 0x80, 0xCC, 0x11, 0xD0, 0xCC, 0x20, - 0xD2, 0x0B, 0x6D, 0x80, 0xCC, 0x11, 0xD0, 0xCC, - 0x20, 0xD2, 0x23, 0x10, 0x80, 0xCC, 0x11, 0xE0, - 0xCC, 0x20, 0xD7, 0x0C, 0x08, 0xA2, 0xCB, 0x60, - 0xA5, 0x03, 0x00, 0x46, 0x01, 0x00, 0xA2, 0xCB, - 0x58, 0xE5, 0x02, 0x00, 0xAD, 0x02, 0xD1, 0xDD, - 0x03, 0x82, 0x23, 0x10, 0x0C, 0x1F, 0xF0, 0x88, - 0x11, 0xED, 0x08, 0x80, 0xEF, 0x83, 0xE2, 0x63, - 0x10, 0xC0, 0x20, 0x00, 0xD8, 0x0D, 0xD9, 0x32, - 0xA5, 0xDF, 0x20, 0x1D, 0xF0, 0xA2, 0xCB, 0x48, - 0xA5, 0x00, 0x00, 0x46, 0xF5, 0xFF, 0x00, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x4B, 0xA2, 0x25, 0x28, - 0x2D, 0x3D, 0x0A, 0xAD, 0x02, 0xA5, 0x27, 0x2D, - 0xB1, 0xE1, 0x03, 0xC1, 0xE2, 0x03, 0xC0, 0x20, - 0x00, 0x82, 0x0B, 0x03, 0xC0, 0x20, 0x00, 0x30, - 0x88, 0x10, 0x30, 0x38, 0x41, 0x80, 0x8A, 0x20, - 0xA0, 0xA8, 0x41, 0x82, 0x4B, 0x03, 0xB2, 0xDB, - 0x20, 0xC7, 0x9B, 0xE1, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x36, 0x41, 0x00, 0xA5, 0xDF, 0xFF, 0x1D, - 0xF0, 0x36, 0x41, 0x00, 0x31, 0xE3, 0x03, 0x21, - 0xE4, 0x03, 0x29, 0x13, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x81, 0xE5, 0x03, 0x30, - 0x61, 0x00, 0x88, 0x08, 0x82, 0x08, 0x10, 0x26, - 0x48, 0x07, 0xAD, 0x02, 0x25, 0x49, 0x28, 0x06, - 0x01, 0x00, 0x0C, 0x0A, 0x65, 0xE2, 0x20, 0x30, - 0xE6, 0x13, 0x10, 0x20, 0x00, 0x1D, 0xF0, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x21, 0xE6, 0x03, 0x88, - 0x02, 0x27, 0x18, 0x09, 0xAD, 0x02, 0xE5, 0x07, - 0x00, 0xAD, 0x02, 0x65, 0xD7, 0x20, 0x1D, 0xF0, - 0x00, 0x36, 0x41, 0x00, 0x20, 0x61, 0x00, 0xA1, - 0xE6, 0x03, 0x65, 0xD6, 0x20, 0x25, 0x1D, 0x24, - 0x20, 0xE6, 0x13, 0x10, 0x20, 0x00, 0x1D, 0xF0, - 0x00, 0x36, 0x41, 0x00, 0x41, 0xE7, 0x03, 0x21, - 0xE8, 0x03, 0xC0, 0x20, 0x00, 0x32, 0x22, 0x81, - 0x98, 0x54, 0x88, 0x34, 0x30, 0x99, 0x20, 0x99, - 0x54, 0x87, 0x03, 0x06, 0x0C, 0x0A, 0xA9, 0x34, - 0x25, 0xDA, 0x21, 0x0C, 0x1D, 0x3C, 0x8C, 0xB8, - 0x44, 0xC0, 0x20, 0x00, 0xC0, 0xBB, 0x10, 0xB2, - 0x62, 0x80, 0xC0, 0x20, 0x00, 0xE2, 0x22, 0x81, - 0xE0, 0xF0, 0x04, 0x07, 0xEE, 0xF3, 0xC0, 0x20, - 0x00, 0xB1, 0xDD, 0x03, 0x32, 0x62, 0x81, 0xC0, - 0x20, 0x00, 0xB8, 0x0B, 0xA1, 0xE9, 0x03, 0x1B, - 0xBB, 0xB9, 0x4A, 0x4B, 0xAA, 0xA5, 0xCE, 0x20, - 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x20, 0x61, 0x00, 0x3C, 0x8A, 0x0C, 0x0B, 0x25, - 0x1A, 0x24, 0x20, 0xE6, 0x13, 0x10, 0x20, 0x00, - 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x31, 0xEA, 0x03, 0x38, 0x03, 0x8C, 0x73, 0x88, - 0x23, 0x66, 0x28, 0x03, 0x0C, 0x39, 0x99, 0x23, - 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x31, 0xEB, 0x03, 0x0C, 0x02, 0x22, 0x43, 0x00, - 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, - 0xBD, 0x02, 0x21, 0xEA, 0x03, 0x28, 0x02, 0x1C, - 0x8C, 0xCB, 0xA2, 0xE5, 0x2E, 0x2D, 0xD1, 0xEC, - 0x03, 0x2C, 0x0B, 0x92, 0x12, 0x11, 0x0C, 0x1C, - 0xDC, 0x79, 0xA2, 0x12, 0x0F, 0x92, 0x12, 0x0E, - 0xA0, 0xA0, 0xE4, 0x90, 0xAA, 0xC0, 0xA2, 0xCA, - 0xC2, 0xA0, 0xA1, 0x21, 0xAA, 0x99, 0x8B, 0x99, - 0x92, 0x52, 0x11, 0xB2, 0x52, 0x13, 0xC9, 0x22, - 0xD0, 0xD9, 0x10, 0xD2, 0x52, 0x11, 0x1D, 0xF0, - 0x00, 0x36, 0x41, 0x00, 0xD8, 0x22, 0x31, 0xEA, - 0x03, 0x0C, 0x1E, 0x38, 0x03, 0x0C, 0x0C, 0xAD, - 0x03, 0xF2, 0x13, 0x13, 0xB2, 0x13, 0x10, 0xF0, - 0xCE, 0x83, 0xDA, 0xBB, 0x25, 0x17, 0x00, 0x0C, - 0x45, 0xA8, 0x23, 0x92, 0x13, 0x13, 0x0C, 0x04, - 0x8C, 0x69, 0x0B, 0x99, 0x90, 0x90, 0xF4, 0x92, - 0x53, 0x13, 0xF6, 0x8A, 0x2F, 0xB1, 0xED, 0x03, - 0xB0, 0xBA, 0xA0, 0xB8, 0x0B, 0xA0, 0x0B, 0x00, - 0xC8, 0x22, 0xB2, 0x13, 0x11, 0xAD, 0x03, 0xCA, - 0xBB, 0x65, 0x21, 0x00, 0xD2, 0x13, 0x06, 0xF1, - 0xEB, 0x03, 0xD7, 0x3A, 0x0F, 0x0C, 0x29, 0x92, - 0x4F, 0x00, 0xE2, 0x13, 0x0F, 0xE0, 0xEF, 0x04, - 0x16, 0xBE, 0x10, 0x99, 0x23, 0x0C, 0x14, 0x2D, - 0x04, 0x1D, 0xF0, 0x49, 0x23, 0x0C, 0x24, 0x06, - 0xFD, 0xFF, 0xAD, 0x03, 0xE5, 0x1B, 0x00, 0x82, - 0x13, 0x09, 0xB2, 0x13, 0x08, 0x87, 0x3A, 0x02, - 0x06, 0x24, 0x00, 0xC8, 0x22, 0xB2, 0x13, 0x11, - 0xAD, 0x03, 0xCA, 0xBB, 0x65, 0x1D, 0x00, 0xD2, - 0x13, 0x07, 0xD7, 0x3A, 0x02, 0xC6, 0x36, 0x00, - 0xE2, 0x13, 0x14, 0x0B, 0xEE, 0xE0, 0xE0, 0xF4, - 0xE2, 0x53, 0x14, 0x56, 0xEE, 0x0D, 0x0C, 0x24, - 0x0C, 0x7F, 0xF9, 0x23, 0xC6, 0xED, 0xFF, 0xAD, - 0x03, 0xE5, 0x17, 0x00, 0x82, 0x13, 0x08, 0x87, - 0x3A, 0x6A, 0x59, 0x23, 0x42, 0x53, 0x16, 0x92, - 0x13, 0x0A, 0x92, 0x53, 0x14, 0x0C, 0x04, 0x06, - 0xE7, 0xFF, 0xAD, 0x03, 0x65, 0x16, 0x00, 0xB2, - 0x13, 0x08, 0xB7, 0x3A, 0x29, 0xC2, 0x13, 0x14, - 0x0B, 0xCC, 0xC0, 0xC0, 0xF4, 0xC2, 0x53, 0x14, - 0xEC, 0xBC, 0x0C, 0x6D, 0xE2, 0x13, 0x0B, 0xE2, - 0x53, 0x14, 0xD9, 0x23, 0xC6, 0x07, 0x00, 0xDC, - 0xC9, 0x59, 0x23, 0x42, 0x53, 0x16, 0xF2, 0x13, - 0x0A, 0xF2, 0x53, 0x14, 0xC6, 0x03, 0x00, 0x0C, - 0x58, 0x92, 0x13, 0x0D, 0xA2, 0x13, 0x0C, 0xA2, - 0x53, 0x14, 0x92, 0x53, 0x15, 0x89, 0x23, 0x0C, - 0x04, 0x86, 0xD4, 0xFF, 0xB7, 0x3A, 0x05, 0xC2, - 0x13, 0x0B, 0xC2, 0x53, 0x14, 0x42, 0x53, 0x16, - 0x0C, 0x04, 0x46, 0xD0, 0xFF, 0x92, 0x13, 0x15, - 0x66, 0x19, 0x09, 0x0C, 0x34, 0x0B, 0xD9, 0xD2, - 0x53, 0x15, 0x46, 0xCC, 0xFF, 0xCC, 0x39, 0x0C, - 0x14, 0x86, 0x01, 0x00, 0x0C, 0x04, 0x0B, 0xE9, - 0xE2, 0x53, 0x15, 0xC8, 0x22, 0xB2, 0x13, 0x11, - 0xAD, 0x03, 0xCA, 0xBB, 0x65, 0x11, 0x00, 0xD2, - 0x13, 0x07, 0xD7, 0xBA, 0x10, 0xE2, 0x13, 0x14, - 0x0B, 0xEE, 0xE0, 0xE0, 0xF4, 0xE2, 0x53, 0x14, - 0xE0, 0x45, 0x83, 0x06, 0xC0, 0xFF, 0xF2, 0x13, - 0x0D, 0xF2, 0x53, 0x14, 0xC6, 0xBD, 0xFF, 0x0C, - 0x39, 0x86, 0xBB, 0xFF, 0x82, 0x13, 0x06, 0x87, - 0x3A, 0x05, 0x92, 0x13, 0x0B, 0x92, 0x53, 0x14, - 0x0C, 0x04, 0x46, 0xB8, 0xFF, 0x0C, 0x04, 0x06, - 0xB7, 0xFF, 0x00, 0x00, 0x00, 0x36, 0x61, 0x00, - 0xB2, 0xA0, 0x94, 0xA2, 0xC2, 0x34, 0x92, 0xC2, - 0x54, 0x99, 0x01, 0xA9, 0x11, 0xBC, 0xB4, 0x68, - 0x11, 0x5D, 0x09, 0x1C, 0x04, 0x72, 0x12, 0x12, - 0x82, 0xA0, 0x94, 0xC0, 0x77, 0x11, 0x7A, 0x72, - 0x8A, 0x77, 0x82, 0x16, 0x00, 0xB2, 0x07, 0x00, - 0x1B, 0x77, 0xAD, 0x0B, 0xB0, 0x88, 0xC0, 0x82, - 0x56, 0x00, 0x2B, 0x66, 0xA5, 0x35, 0x2D, 0x98, - 0x05, 0x0B, 0x44, 0xA0, 0x99, 0xC0, 0x99, 0x05, - 0x4B, 0x55, 0x56, 0xC4, 0xFD, 0x98, 0x01, 0xA8, - 0x11, 0xB2, 0xA0, 0x94, 0x5D, 0x09, 0x6D, 0x0A, - 0x72, 0x12, 0x12, 0x1C, 0x04, 0xC0, 0x77, 0x11, - 0x7A, 0x72, 0xBA, 0x77, 0xD2, 0x03, 0x01, 0xE2, - 0x03, 0x03, 0xC2, 0x03, 0x02, 0xB2, 0x03, 0x00, - 0xEA, 0xCC, 0xDA, 0xBB, 0xCA, 0xBB, 0xB0, 0xB2, - 0x41, 0xAD, 0x0B, 0xB2, 0x47, 0x00, 0x82, 0x16, - 0x00, 0x1B, 0x77, 0xBA, 0x88, 0x82, 0x56, 0x00, - 0x2B, 0x66, 0xA5, 0x30, 0x2D, 0x8B, 0x33, 0xF8, - 0x05, 0x0B, 0x44, 0xAA, 0xFF, 0xF9, 0x05, 0x4B, - 0x55, 0x56, 0x74, 0xFC, 0x82, 0x12, 0x12, 0x1B, - 0x88, 0x80, 0x80, 0x44, 0x82, 0x52, 0x12, 0x1D, - 0xF0, 0x36, 0x41, 0x00, 0x32, 0xC2, 0x34, 0x1C, - 0x05, 0x0C, 0x04, 0xB2, 0x13, 0x00, 0xAD, 0x0B, - 0xE5, 0x2D, 0x2D, 0x2B, 0x33, 0x0B, 0x55, 0xA0, - 0x95, 0x41, 0x82, 0x22, 0x15, 0x4B, 0x22, 0x90, - 0x88, 0xC0, 0x80, 0x85, 0x41, 0x8A, 0x44, 0x56, - 0x05, 0xFE, 0x40, 0x24, 0x41, 0x1D, 0xF0, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x1C, 0x07, 0x0C, 0x06, - 0x0C, 0x05, 0xB2, 0xC3, 0x81, 0x42, 0x03, 0x00, - 0xB2, 0x0B, 0x7E, 0xC2, 0x03, 0x01, 0x47, 0xBB, - 0x0C, 0x47, 0xBC, 0x11, 0x4D, 0x0B, 0xC7, 0xBB, - 0x0C, 0x4D, 0x0C, 0xC6, 0x01, 0x00, 0x47, 0x3C, - 0x04, 0xC7, 0xBB, 0x01, 0x4D, 0x0B, 0xAD, 0x04, - 0xBD, 0x04, 0xA5, 0x28, 0x2D, 0xAA, 0x66, 0x5A, - 0x54, 0x0B, 0x77, 0x4B, 0x33, 0xB2, 0xC3, 0x81, - 0x56, 0x97, 0xFC, 0xAD, 0x05, 0xBD, 0x05, 0x65, - 0x27, 0x2D, 0xD2, 0x12, 0x16, 0xA0, 0x94, 0x41, - 0x90, 0x96, 0xC0, 0xD0, 0xCD, 0xF0, 0x90, 0x94, - 0x41, 0x90, 0xE3, 0x41, 0xC0, 0xC3, 0x21, 0xEA, - 0xCC, 0xD0, 0x9C, 0x93, 0x92, 0x52, 0x16, 0x2D, - 0x09, 0x1D, 0xF0, 0x00, 0x00, 0x24, 0x00, 0x00, - 0x00, 0x64, 0x11, 0x02, 0x60, 0x04, 0x11, 0x02, - 0x60, 0xEC, 0x18, 0x00, 0x60, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x13, 0x02, - 0x60, 0xC8, 0x14, 0x02, 0x60, 0xD4, 0x13, 0x02, - 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x19, 0x00, - 0x60, 0x1C, 0x19, 0x00, 0x60, 0x04, 0x19, 0x00, - 0x60, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x19, 0x00, - 0x60, 0x2C, 0x19, 0x00, 0x60, 0x08, 0x19, 0x00, - 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x48, 0x19, 0x00, 0x60, 0x48, 0x19, 0x00, - 0x60, 0x0C, 0x19, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x94, 0x15, 0x02, 0x60, 0x5C, 0x19, 0x00, - 0x60, 0x5C, 0x19, 0x00, 0x60, 0x58, 0x19, 0x00, - 0x60, 0x00, 0x00, 0x00, 0x00, 0xC4, 0x15, 0x02, - 0x60, 0xCC, 0x15, 0x02, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x6C, 0x19, 0x00, 0x60, 0x70, 0x19, 0x00, - 0x60, 0xB0, 0x19, 0x00, 0x60, 0x94, 0x02, 0x00, - 0x00, 0x84, 0x16, 0x02, 0x60, 0x5F, 0x16, 0x02, - 0x60, 0x84, 0x16, 0x02, 0x60, 0x0E, 0x17, 0x02, - 0x60, 0xE9, 0x16, 0x02, 0x60, 0xCE, 0x16, 0x02, - 0x60, 0x91, 0x16, 0x02, 0x60, 0x8A, 0x16, 0x02, - 0x60, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x0C, 0x00, - 0x60, 0xD4, 0x0C, 0x00, 0x60, 0x10, 0xB0, 0x02, - 0x00, 0xC0, 0x19, 0x00, 0x60, 0x20, 0x01, 0x00, - 0x00, 0xB0, 0x0A, 0x00, 0x60, 0x04, 0x10, 0x02, - 0x60, 0xA0, 0x0A, 0x00, 0x60, 0xA4, 0x10, 0x02, - 0x60, 0xF8, 0x10, 0x02, 0x60, 0x6C, 0x10, 0x02, - 0x60, 0x6C, 0x06, 0x00, 0x60, 0x20, 0x16, 0x02, - 0x60, 0xF4, 0x05, 0x00, 0x60, 0x4C, 0x10, 0x02, - 0x60, 0xA8, 0x0B, 0x00, 0x60, 0xF8, 0x18, 0x00, - 0x60, 0x68, 0x0A, 0x00, 0x60, 0x28, 0x8F, 0x04, - 0x60, 0x48, 0x08, 0x00, 0x60, 0xE0, 0x14, 0x02, - 0x60, 0xAC, 0x06, 0x00, 0x60, 0x20, 0x15, 0x02, - 0x60, 0x38, 0x15, 0x02, 0x60, 0xD8, 0x56, 0x04, - 0x60, 0x36, 0x41, 0x00, 0x81, 0x6F, 0x06, 0xB1, - 0x6D, 0x06, 0x0C, 0x6A, 0x91, 0x6E, 0x06, 0xA2, - 0x4B, 0x00, 0x89, 0x09, 0x25, 0x02, 0x00, 0x65, - 0x07, 0x00, 0x25, 0x09, 0x00, 0xE5, 0x07, 0x00, - 0x65, 0x02, 0x00, 0x65, 0x05, 0x00, 0xA5, 0x6E, - 0xFF, 0xA1, 0x70, 0x06, 0xB1, 0x71, 0x06, 0x65, - 0xB3, 0x2C, 0x1D, 0xF0, 0x00, 0x36, 0x41, 0x00, - 0x31, 0x72, 0x06, 0x21, 0x73, 0x06, 0x22, 0x63, - 0x75, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x0C, 0x8F, 0xB1, 0x72, 0x06, 0xA1, 0x77, 0x06, - 0x91, 0x78, 0x06, 0x81, 0x79, 0x06, 0x31, 0x7A, - 0x06, 0x21, 0x7B, 0x06, 0xC1, 0x76, 0x06, 0xD1, - 0x74, 0x06, 0xE1, 0x75, 0x06, 0xE9, 0xFD, 0xC2, - 0x6D, 0x19, 0x29, 0x83, 0x89, 0x39, 0xA2, 0x6B, - 0x6B, 0xF2, 0x5D, 0x1C, 0x1D, 0xF0, 0x00, 0x00, - 0x00, 0x36, 0x41, 0x00, 0x31, 0x7C, 0x06, 0x21, - 0x7D, 0x06, 0x48, 0x03, 0x49, 0x22, 0x29, 0x03, - 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x31, 0x7E, 0x06, 0x21, 0x7F, 0x06, 0x29, 0x13, - 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x31, 0x80, 0x06, 0x21, 0x81, 0x06, 0x22, 0x63, - 0x19, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, - 0x91, 0x83, 0x06, 0x21, 0x85, 0x06, 0x31, 0x82, - 0x06, 0x81, 0x84, 0x06, 0x89, 0xC3, 0x29, 0xA3, - 0x99, 0xB3, 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x04, 0x00, 0x18, 0x1A, 0x02, - 0x60, + 0x06, 0x00, 0x00, 0xE4, 0x0B, 0x00, 0x0F, 0x00, + 0x60, 0xD8, 0x0C, 0x00, 0x60, 0xD4, 0x0C, 0x00, + 0x60, 0xB0, 0x0A, 0x00, 0x60, 0x58, 0xB3, 0x04, + 0x60, 0x84, 0x05, 0x00, 0x60, 0xA4, 0xED, 0x04, + 0x60, 0x8C, 0x04, 0x00, 0x00, 0x00, 0x0F, 0x00, + 0x60, 0xC0, 0x0A, 0x00, 0x00, 0xA0, 0x0A, 0x00, + 0x60, 0xD0, 0x38, 0x04, 0x60, 0xB4, 0x39, 0x04, + 0x60, 0x58, 0xB4, 0x04, 0x60, 0xFC, 0x0C, 0x00, + 0x60, 0x80, 0x19, 0x00, 0x60, 0xC8, 0x0D, 0x00, + 0x60, 0x9C, 0x0B, 0x00, 0x60, 0xF4, 0x18, 0x00, + 0x60, 0xCC, 0x08, 0x00, 0x60, 0xF8, 0x18, 0x00, + 0x60, 0xA8, 0x0B, 0x00, 0x60, 0xE4, 0x06, 0x00, + 0x60, 0x54, 0x11, 0x02, 0x60, 0xAC, 0x06, 0x00, + 0x60, 0x48, 0x11, 0x02, 0x60, 0x04, 0x19, 0x00, + 0x60, 0x80, 0x7F, 0x00, 0x38, 0x80, 0x5F, 0x00, + 0x38, 0x80, 0x3F, 0x00, 0x38, 0xDC, 0x0C, 0x00, + 0x60, 0x1C, 0x19, 0x00, 0x60, 0x2C, 0x19, 0x00, + 0x60, 0x48, 0x19, 0x00, 0x60, 0x00, 0x40, 0x00, + 0x38, 0x00, 0xA0, 0x00, 0x38, 0x68, 0x0A, 0x00, + 0x60, 0x4C, 0x3F, 0x04, 0x60, 0xC0, 0x0D, 0x00, + 0x60, 0x5C, 0x19, 0x00, 0x60, 0x18, 0x0D, 0x00, + 0x60, 0x00, 0x9E, 0x00, 0x38, 0x58, 0x19, 0x00, + 0x60, 0xB0, 0x19, 0x00, 0x60, 0x20, 0x0E, 0x00, + 0x60, 0xFC, 0xFF, 0x00, 0x00, 0x90, 0x19, 0x00, + 0x60, 0x36, 0x41, 0x00, 0x65, 0x03, 0x00, 0x25, + 0x18, 0x00, 0x65, 0x15, 0x00, 0x25, 0x06, 0x00, + 0x25, 0x54, 0x00, 0x65, 0x50, 0x00, 0x25, 0x01, + 0x00, 0x91, 0xC0, 0x03, 0xA1, 0xC1, 0x03, 0x0C, + 0x08, 0x89, 0x0A, 0x82, 0x49, 0x00, 0x1D, 0xF0, + 0x00, 0x36, 0x41, 0x00, 0x31, 0xC2, 0x03, 0x21, + 0xC3, 0x03, 0x22, 0x63, 0x75, 0x1D, 0xF0, 0x00, + 0x00, 0x36, 0x41, 0x00, 0xA1, 0xC4, 0x03, 0xB1, + 0xC5, 0x03, 0xC1, 0xC6, 0x03, 0xA5, 0x8D, 0x2D, + 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x9C, 0x85, 0x20, 0x61, 0x00, 0xA5, 0xFA, 0xFF, + 0x20, 0xE6, 0x13, 0x10, 0x20, 0x00, 0x0C, 0x0A, + 0x65, 0xC8, 0x29, 0xA1, 0xC7, 0x03, 0xB1, 0xC8, + 0x03, 0xA5, 0x55, 0x2D, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x0C, 0xBB, 0x31, 0xC2, + 0x03, 0x21, 0xCC, 0x03, 0x81, 0xCB, 0x03, 0x91, + 0xC9, 0x03, 0xA1, 0xCA, 0x03, 0xA9, 0xF9, 0x82, + 0x69, 0x19, 0x22, 0x63, 0x6B, 0xB2, 0x59, 0x1C, + 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x21, 0xCD, 0x03, 0x88, 0x22, 0x37, 0x68, 0x0E, + 0xA1, 0xCE, 0x03, 0xA5, 0x7D, 0x2D, 0x98, 0x22, + 0x6C, 0x7A, 0xA0, 0x99, 0x10, 0x99, 0x22, 0xE5, + 0xA9, 0x22, 0x1D, 0xF0, 0x00, 0x36, 0x41, 0x00, + 0xCD, 0x04, 0xBD, 0x03, 0xAD, 0x02, 0xDD, 0x05, + 0x25, 0x3E, 0x2A, 0xAC, 0x15, 0x81, 0xCF, 0x03, + 0xA1, 0xD0, 0x03, 0x88, 0x08, 0x91, 0xCD, 0x03, + 0x82, 0x08, 0x02, 0x98, 0x29, 0xB6, 0x28, 0x06, + 0x91, 0xD1, 0x03, 0x99, 0x2A, 0x1D, 0xF0, 0x37, + 0x69, 0x05, 0x91, 0xD2, 0x03, 0x86, 0xFC, 0xFF, + 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, + 0xBD, 0x03, 0xAD, 0x02, 0xCD, 0x04, 0xDD, 0x05, + 0x1C, 0x8E, 0x25, 0xA1, 0x22, 0xBC, 0x16, 0x82, + 0x12, 0x1A, 0x5A, 0xA4, 0xEC, 0xA8, 0x1C, 0x79, + 0xA7, 0x39, 0x28, 0x92, 0xA4, 0x21, 0x92, 0x52, + 0x1A, 0x06, 0x05, 0x00, 0xA1, 0xCE, 0x03, 0x25, + 0x72, 0x2D, 0xA8, 0x82, 0xA5, 0x50, 0x00, 0xB1, + 0xCD, 0x03, 0xA8, 0x2B, 0x30, 0xAA, 0x20, 0xA9, + 0x2B, 0xA8, 0x82, 0xA5, 0x35, 0x2D, 0x0C, 0x0B, + 0xB9, 0x82, 0x1D, 0xF0, 0x1C, 0x83, 0xA7, 0xB3, + 0xDA, 0x92, 0xA4, 0x22, 0x86, 0xF3, 0xFF, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x8C, 0x36, 0x0C, 0x03, + 0x32, 0x52, 0x1A, 0x1D, 0xF0, 0x36, 0x41, 0x00, + 0x65, 0x4A, 0x00, 0xAD, 0x02, 0x81, 0xD2, 0x03, + 0x89, 0x22, 0xE5, 0xBC, 0x29, 0x1D, 0xF0, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x21, 0xD3, 0x03, 0x31, + 0xD4, 0x03, 0x28, 0x22, 0x29, 0x03, 0x1D, 0xF0, + 0x00, 0x36, 0x41, 0x00, 0x21, 0xD8, 0x03, 0x31, + 0xD7, 0x03, 0x91, 0xD5, 0x03, 0x81, 0xD6, 0x03, + 0x89, 0x49, 0x29, 0x03, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x25, 0x18, 0x00, 0x1D, + 0xF0, 0x36, 0x41, 0x00, 0xA5, 0x17, 0x00, 0x65, + 0x20, 0x24, 0x1D, 0xF0, 0x00, 0x36, 0x41, 0x00, + 0xAD, 0x02, 0x65, 0xBE, 0x24, 0x65, 0x16, 0x00, + 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x61, 0xD9, 0x03, 0xCC, 0xE4, 0xA2, 0xA0, 0x76, + 0x65, 0x22, 0x2D, 0xA9, 0x36, 0xCC, 0x4A, 0xA2, + 0xA4, 0x31, 0x25, 0xB2, 0x29, 0x72, 0xA0, 0x76, + 0xD8, 0x36, 0xA2, 0xA0, 0x75, 0xAC, 0x2D, 0x4A, + 0xB3, 0xB7, 0x37, 0x0E, 0xDA, 0xA4, 0xBD, 0x02, + 0xCD, 0x03, 0x65, 0x74, 0x2D, 0xA2, 0xA0, 0x75, + 0xC6, 0x03, 0x00, 0x47, 0x3A, 0x0C, 0xDA, 0xA4, + 0xBD, 0x02, 0x40, 0xC7, 0xC0, 0x25, 0x73, 0x2D, + 0xA2, 0xA0, 0x75, 0xBC, 0x75, 0xC8, 0x36, 0x4A, + 0xB3, 0xBC, 0x1C, 0xB7, 0x3A, 0x08, 0xA2, 0xA4, + 0x05, 0x25, 0xAE, 0x29, 0x46, 0x07, 0x00, 0xB7, + 0xB7, 0x25, 0xA2, 0xA4, 0x06, 0x65, 0xAD, 0x29, + 0x46, 0x04, 0x00, 0x0C, 0x0A, 0xE5, 0xAC, 0x29, + 0xA8, 0x46, 0xB8, 0x36, 0xC2, 0xA0, 0x76, 0x25, + 0x70, 0x2D, 0xA5, 0x02, 0x00, 0xA8, 0x36, 0xE5, + 0x25, 0x2D, 0x0C, 0x0D, 0xD9, 0x36, 0x1D, 0xF0, + 0xE8, 0x46, 0x8C, 0x1E, 0xA5, 0x0D, 0x00, 0xA2, + 0xA0, 0x76, 0x25, 0x1A, 0x2D, 0xA9, 0x46, 0x56, + 0x0A, 0xFD, 0xA2, 0xA4, 0x31, 0xE5, 0xA9, 0x29, + 0x46, 0xF6, 0xFF, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x21, 0xD9, 0x03, 0x91, 0xDA, 0x03, 0xB1, 0xDB, + 0x03, 0x81, 0xDC, 0x03, 0xC0, 0x20, 0x00, 0xA2, + 0x08, 0x84, 0xC0, 0x20, 0x00, 0xD2, 0x0B, 0x84, + 0xC0, 0x20, 0x00, 0xC2, 0x09, 0x84, 0x80, 0xDD, + 0x11, 0xD0, 0xAA, 0x20, 0x00, 0xCC, 0x11, 0xC0, + 0xAA, 0x20, 0xA9, 0xE2, 0xC0, 0x20, 0x00, 0x82, + 0x08, 0x81, 0xC0, 0x20, 0x00, 0xB2, 0x0B, 0x81, + 0xC0, 0x20, 0x00, 0xA8, 0x42, 0x80, 0xBB, 0x11, + 0x92, 0x09, 0x81, 0xB0, 0x88, 0x20, 0x00, 0x99, + 0x11, 0x90, 0x88, 0x20, 0x89, 0xF2, 0xE5, 0x73, + 0x24, 0x31, 0xDD, 0x03, 0x98, 0x42, 0x0C, 0x0B, + 0xA2, 0x09, 0x70, 0x92, 0x09, 0x71, 0xB2, 0x42, + 0x14, 0x80, 0x99, 0x11, 0xA0, 0x99, 0x20, 0x16, + 0x79, 0x04, 0xC0, 0x20, 0x00, 0xB8, 0x03, 0x9A, + 0xBB, 0x0B, 0xBB, 0xB9, 0x92, 0xA1, 0xDE, 0x03, + 0xA5, 0xFF, 0x20, 0xB8, 0x42, 0xB2, 0x0B, 0x75, + 0x9C, 0x9B, 0xC0, 0x20, 0x00, 0xA1, 0xDF, 0x03, + 0xD8, 0x03, 0xB0, 0xCB, 0x11, 0xB0, 0xCC, 0xC0, + 0xB0, 0xCC, 0xA0, 0xD0, 0xCC, 0xB0, 0x0B, 0xCC, + 0xC9, 0xD2, 0x65, 0xFD, 0x20, 0xA1, 0xE0, 0x03, + 0x0C, 0x1E, 0xE2, 0x62, 0x10, 0xC0, 0x20, 0x00, + 0xD8, 0x03, 0xD2, 0x62, 0x14, 0x25, 0xFC, 0x20, + 0x1D, 0xF0, 0xC0, 0x20, 0x00, 0xB8, 0x03, 0x06, + 0xEE, 0xFF, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x21, 0xD9, 0x03, 0x88, 0x42, 0x16, 0x28, 0x08, + 0xA2, 0xC2, 0x44, 0xE5, 0xFB, 0x20, 0xB8, 0x42, + 0x92, 0x0B, 0x74, 0x26, 0x19, 0x14, 0xA2, 0xC9, + 0xFE, 0x16, 0x9A, 0x07, 0xC2, 0xC9, 0xFD, 0x16, + 0xAC, 0x06, 0xA2, 0xCB, 0x48, 0x25, 0x1A, 0x00, + 0x46, 0x01, 0x00, 0xA2, 0xCB, 0x50, 0xA5, 0x19, + 0x00, 0xA1, 0xDE, 0x03, 0x65, 0xF9, 0x20, 0xA1, + 0xDF, 0x03, 0xE5, 0xF8, 0x20, 0xE1, 0xDA, 0x03, + 0x81, 0xDB, 0x03, 0xA1, 0xDC, 0x03, 0xD8, 0xE2, + 0xC0, 0x20, 0x00, 0xD2, 0x4A, 0x84, 0xC8, 0xE2, + 0xC0, 0x20, 0x00, 0xC0, 0xC8, 0x41, 0xC2, 0x48, + 0x84, 0xB8, 0xE2, 0xC0, 0x20, 0x00, 0xB0, 0xB0, + 0xF5, 0xB2, 0x4E, 0x84, 0x98, 0xF2, 0xC0, 0x20, + 0x00, 0x92, 0x4A, 0x81, 0xF8, 0xF2, 0xC0, 0x20, + 0x00, 0xF0, 0xF8, 0x41, 0xF2, 0x48, 0x81, 0xD8, + 0xF2, 0xC0, 0x20, 0x00, 0xD0, 0xD0, 0xF5, 0xD2, + 0x4E, 0x81, 0xA8, 0x42, 0x25, 0x0F, 0x2D, 0x0C, + 0x0E, 0xE9, 0x42, 0x1D, 0xF0, 0xA2, 0xCB, 0x60, + 0xA5, 0x13, 0x00, 0x86, 0xE6, 0xFF, 0xA2, 0xCB, + 0x58, 0xE5, 0x12, 0x00, 0x46, 0xE4, 0xFF, 0x00, + 0x00, 0x36, 0x41, 0x00, 0xB1, 0xD9, 0x03, 0x0C, + 0x1D, 0x98, 0x4B, 0xA2, 0x0B, 0x14, 0xAC, 0x79, + 0xC1, 0xDD, 0x03, 0xEC, 0x4A, 0xA2, 0x09, 0x72, + 0xE2, 0x09, 0x73, 0xD2, 0x4B, 0x14, 0x80, 0x9E, + 0x11, 0xA0, 0x99, 0x20, 0xBC, 0xD9, 0xC0, 0x20, + 0x00, 0xA8, 0x0C, 0x9A, 0x9A, 0x0B, 0x99, 0x99, + 0x32, 0xD2, 0x6B, 0x10, 0xAD, 0x02, 0xA5, 0xED, + 0x20, 0x1D, 0xF0, 0x66, 0x1A, 0xF2, 0xE2, 0x09, + 0x71, 0xA2, 0x09, 0x70, 0x80, 0x9E, 0x11, 0xA0, + 0x99, 0x20, 0x0C, 0x0E, 0xE2, 0x4B, 0x14, 0x8C, + 0xA9, 0xC0, 0x20, 0x00, 0xA8, 0x0C, 0x9A, 0x9A, + 0x0B, 0x99, 0x46, 0xF4, 0xFF, 0xC0, 0x20, 0x00, + 0x98, 0x0C, 0x46, 0xF2, 0xFF, 0xC0, 0x20, 0x00, + 0x98, 0x0C, 0x46, 0xF0, 0xFF, 0x36, 0x41, 0x00, + 0x31, 0xD9, 0x03, 0xB8, 0x43, 0x92, 0x03, 0x14, + 0x16, 0xFB, 0x09, 0xFC, 0x99, 0x82, 0x0B, 0x71, + 0xA2, 0x0B, 0x70, 0x80, 0x88, 0x11, 0xA0, 0x88, + 0x20, 0xAC, 0xB8, 0xC2, 0x0B, 0x68, 0x92, 0x0B, + 0x6B, 0xA2, 0x0B, 0x6A, 0x80, 0x99, 0x11, 0xA0, + 0x99, 0x20, 0xA2, 0x0B, 0x69, 0x80, 0x99, 0x11, + 0xA0, 0x99, 0x20, 0xA2, 0x23, 0x10, 0x80, 0x99, + 0x11, 0xC0, 0x99, 0x20, 0xA7, 0x09, 0x6D, 0xA2, + 0xCB, 0x50, 0x65, 0x07, 0x00, 0xC6, 0x10, 0x00, + 0x66, 0x19, 0x40, 0xA2, 0x0B, 0x73, 0xC2, 0x0B, + 0x72, 0x80, 0xAA, 0x11, 0xC0, 0xAA, 0x20, 0xBC, + 0x1A, 0xE2, 0x0B, 0x6C, 0xC2, 0x0B, 0x6F, 0xD2, + 0x0B, 0x6E, 0x80, 0xCC, 0x11, 0xD0, 0xCC, 0x20, + 0xD2, 0x0B, 0x6D, 0x80, 0xCC, 0x11, 0xD0, 0xCC, + 0x20, 0xD2, 0x23, 0x10, 0x80, 0xCC, 0x11, 0xE0, + 0xCC, 0x20, 0xD7, 0x0C, 0x08, 0xA2, 0xCB, 0x60, + 0xA5, 0x03, 0x00, 0x46, 0x01, 0x00, 0xA2, 0xCB, + 0x58, 0xE5, 0x02, 0x00, 0xAD, 0x02, 0xD1, 0xDD, + 0x03, 0x82, 0x23, 0x10, 0x0C, 0x1F, 0xF0, 0x88, + 0x11, 0xED, 0x08, 0x80, 0xEF, 0x83, 0xE2, 0x63, + 0x10, 0xC0, 0x20, 0x00, 0xD8, 0x0D, 0xD9, 0x32, + 0xA5, 0xDF, 0x20, 0x1D, 0xF0, 0xA2, 0xCB, 0x48, + 0xA5, 0x00, 0x00, 0x46, 0xF5, 0xFF, 0x00, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x4B, 0xA2, 0x25, 0x28, + 0x2D, 0x3D, 0x0A, 0xAD, 0x02, 0xA5, 0x27, 0x2D, + 0xB1, 0xE1, 0x03, 0xC1, 0xE2, 0x03, 0xC0, 0x20, + 0x00, 0x82, 0x0B, 0x03, 0xC0, 0x20, 0x00, 0x30, + 0x88, 0x10, 0x30, 0x38, 0x41, 0x80, 0x8A, 0x20, + 0xA0, 0xA8, 0x41, 0x82, 0x4B, 0x03, 0xB2, 0xDB, + 0x20, 0xC7, 0x9B, 0xE1, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x36, 0x41, 0x00, 0xA5, 0xDF, 0xFF, 0x1D, + 0xF0, 0x36, 0x41, 0x00, 0x31, 0xE3, 0x03, 0x21, + 0xE4, 0x03, 0x29, 0x13, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x81, 0xE5, 0x03, 0x30, + 0x61, 0x00, 0x88, 0x08, 0x82, 0x08, 0x10, 0x26, + 0x48, 0x07, 0xAD, 0x02, 0x25, 0x49, 0x28, 0x06, + 0x01, 0x00, 0x0C, 0x0A, 0x65, 0xE2, 0x20, 0x30, + 0xE6, 0x13, 0x10, 0x20, 0x00, 0x1D, 0xF0, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x21, 0xE6, 0x03, 0x88, + 0x02, 0x27, 0x18, 0x09, 0xAD, 0x02, 0xE5, 0x07, + 0x00, 0xAD, 0x02, 0x65, 0xD7, 0x20, 0x1D, 0xF0, + 0x00, 0x36, 0x41, 0x00, 0x20, 0x61, 0x00, 0xA1, + 0xE6, 0x03, 0x65, 0xD6, 0x20, 0x25, 0x1D, 0x24, + 0x20, 0xE6, 0x13, 0x10, 0x20, 0x00, 0x1D, 0xF0, + 0x00, 0x36, 0x41, 0x00, 0x41, 0xE7, 0x03, 0x21, + 0xE8, 0x03, 0xC0, 0x20, 0x00, 0x32, 0x22, 0x81, + 0x98, 0x54, 0x88, 0x34, 0x30, 0x99, 0x20, 0x99, + 0x54, 0x87, 0x03, 0x06, 0x0C, 0x0A, 0xA9, 0x34, + 0x25, 0xDA, 0x21, 0x0C, 0x1D, 0x3C, 0x8C, 0xB8, + 0x44, 0xC0, 0x20, 0x00, 0xC0, 0xBB, 0x10, 0xB2, + 0x62, 0x80, 0xC0, 0x20, 0x00, 0xE2, 0x22, 0x81, + 0xE0, 0xF0, 0x04, 0x07, 0xEE, 0xF3, 0xC0, 0x20, + 0x00, 0xB1, 0xDD, 0x03, 0x32, 0x62, 0x81, 0xC0, + 0x20, 0x00, 0xB8, 0x0B, 0xA1, 0xE9, 0x03, 0x1B, + 0xBB, 0xB9, 0x4A, 0x4B, 0xAA, 0xA5, 0xCE, 0x20, + 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x20, 0x61, 0x00, 0x3C, 0x8A, 0x0C, 0x0B, 0x25, + 0x1A, 0x24, 0x20, 0xE6, 0x13, 0x10, 0x20, 0x00, + 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x31, 0xEA, 0x03, 0x38, 0x03, 0x8C, 0x73, 0x88, + 0x23, 0x66, 0x28, 0x03, 0x0C, 0x39, 0x99, 0x23, + 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x31, 0xEB, 0x03, 0x0C, 0x02, 0x22, 0x43, 0x00, + 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, + 0xBD, 0x02, 0x21, 0xEA, 0x03, 0x28, 0x02, 0x1C, + 0x8C, 0xCB, 0xA2, 0xE5, 0x2E, 0x2D, 0xD1, 0xEC, + 0x03, 0x2C, 0x0B, 0x92, 0x12, 0x11, 0x0C, 0x1C, + 0xDC, 0x79, 0xA2, 0x12, 0x0F, 0x92, 0x12, 0x0E, + 0xA0, 0xA0, 0xE4, 0x90, 0xAA, 0xC0, 0xA2, 0xCA, + 0xC2, 0xA0, 0xA1, 0x21, 0xAA, 0x99, 0x8B, 0x99, + 0x92, 0x52, 0x11, 0xB2, 0x52, 0x13, 0xC9, 0x22, + 0xD0, 0xD9, 0x10, 0xD2, 0x52, 0x11, 0x1D, 0xF0, + 0x00, 0x36, 0x41, 0x00, 0xD8, 0x22, 0x31, 0xEA, + 0x03, 0x0C, 0x1E, 0x38, 0x03, 0x0C, 0x0C, 0xAD, + 0x03, 0xF2, 0x13, 0x13, 0xB2, 0x13, 0x10, 0xF0, + 0xCE, 0x83, 0xDA, 0xBB, 0x25, 0x17, 0x00, 0x0C, + 0x45, 0xA8, 0x23, 0x92, 0x13, 0x13, 0x0C, 0x04, + 0x8C, 0x69, 0x0B, 0x99, 0x90, 0x90, 0xF4, 0x92, + 0x53, 0x13, 0xF6, 0x8A, 0x2F, 0xB1, 0xED, 0x03, + 0xB0, 0xBA, 0xA0, 0xB8, 0x0B, 0xA0, 0x0B, 0x00, + 0xC8, 0x22, 0xB2, 0x13, 0x11, 0xAD, 0x03, 0xCA, + 0xBB, 0x65, 0x21, 0x00, 0xD2, 0x13, 0x06, 0xF1, + 0xEB, 0x03, 0xD7, 0x3A, 0x0F, 0x0C, 0x29, 0x92, + 0x4F, 0x00, 0xE2, 0x13, 0x0F, 0xE0, 0xEF, 0x04, + 0x16, 0xBE, 0x10, 0x99, 0x23, 0x0C, 0x14, 0x2D, + 0x04, 0x1D, 0xF0, 0x49, 0x23, 0x0C, 0x24, 0x06, + 0xFD, 0xFF, 0xAD, 0x03, 0xE5, 0x1B, 0x00, 0x82, + 0x13, 0x09, 0xB2, 0x13, 0x08, 0x87, 0x3A, 0x02, + 0x06, 0x24, 0x00, 0xC8, 0x22, 0xB2, 0x13, 0x11, + 0xAD, 0x03, 0xCA, 0xBB, 0x65, 0x1D, 0x00, 0xD2, + 0x13, 0x07, 0xD7, 0x3A, 0x02, 0xC6, 0x36, 0x00, + 0xE2, 0x13, 0x14, 0x0B, 0xEE, 0xE0, 0xE0, 0xF4, + 0xE2, 0x53, 0x14, 0x56, 0xEE, 0x0D, 0x0C, 0x24, + 0x0C, 0x7F, 0xF9, 0x23, 0xC6, 0xED, 0xFF, 0xAD, + 0x03, 0xE5, 0x17, 0x00, 0x82, 0x13, 0x08, 0x87, + 0x3A, 0x6A, 0x59, 0x23, 0x42, 0x53, 0x16, 0x92, + 0x13, 0x0A, 0x92, 0x53, 0x14, 0x0C, 0x04, 0x06, + 0xE7, 0xFF, 0xAD, 0x03, 0x65, 0x16, 0x00, 0xB2, + 0x13, 0x08, 0xB7, 0x3A, 0x29, 0xC2, 0x13, 0x14, + 0x0B, 0xCC, 0xC0, 0xC0, 0xF4, 0xC2, 0x53, 0x14, + 0xEC, 0xBC, 0x0C, 0x6D, 0xE2, 0x13, 0x0B, 0xE2, + 0x53, 0x14, 0xD9, 0x23, 0xC6, 0x07, 0x00, 0xDC, + 0xC9, 0x59, 0x23, 0x42, 0x53, 0x16, 0xF2, 0x13, + 0x0A, 0xF2, 0x53, 0x14, 0xC6, 0x03, 0x00, 0x0C, + 0x58, 0x92, 0x13, 0x0D, 0xA2, 0x13, 0x0C, 0xA2, + 0x53, 0x14, 0x92, 0x53, 0x15, 0x89, 0x23, 0x0C, + 0x04, 0x86, 0xD4, 0xFF, 0xB7, 0x3A, 0x05, 0xC2, + 0x13, 0x0B, 0xC2, 0x53, 0x14, 0x42, 0x53, 0x16, + 0x0C, 0x04, 0x46, 0xD0, 0xFF, 0x92, 0x13, 0x15, + 0x66, 0x19, 0x09, 0x0C, 0x34, 0x0B, 0xD9, 0xD2, + 0x53, 0x15, 0x46, 0xCC, 0xFF, 0xCC, 0x39, 0x0C, + 0x14, 0x86, 0x01, 0x00, 0x0C, 0x04, 0x0B, 0xE9, + 0xE2, 0x53, 0x15, 0xC8, 0x22, 0xB2, 0x13, 0x11, + 0xAD, 0x03, 0xCA, 0xBB, 0x65, 0x11, 0x00, 0xD2, + 0x13, 0x07, 0xD7, 0xBA, 0x10, 0xE2, 0x13, 0x14, + 0x0B, 0xEE, 0xE0, 0xE0, 0xF4, 0xE2, 0x53, 0x14, + 0xE0, 0x45, 0x83, 0x06, 0xC0, 0xFF, 0xF2, 0x13, + 0x0D, 0xF2, 0x53, 0x14, 0xC6, 0xBD, 0xFF, 0x0C, + 0x39, 0x86, 0xBB, 0xFF, 0x82, 0x13, 0x06, 0x87, + 0x3A, 0x05, 0x92, 0x13, 0x0B, 0x92, 0x53, 0x14, + 0x0C, 0x04, 0x46, 0xB8, 0xFF, 0x0C, 0x04, 0x06, + 0xB7, 0xFF, 0x00, 0x00, 0x00, 0x36, 0x61, 0x00, + 0xB2, 0xA0, 0x94, 0xA2, 0xC2, 0x34, 0x92, 0xC2, + 0x54, 0x99, 0x01, 0xA9, 0x11, 0xBC, 0xB4, 0x68, + 0x11, 0x5D, 0x09, 0x1C, 0x04, 0x72, 0x12, 0x12, + 0x82, 0xA0, 0x94, 0xC0, 0x77, 0x11, 0x7A, 0x72, + 0x8A, 0x77, 0x82, 0x16, 0x00, 0xB2, 0x07, 0x00, + 0x1B, 0x77, 0xAD, 0x0B, 0xB0, 0x88, 0xC0, 0x82, + 0x56, 0x00, 0x2B, 0x66, 0xA5, 0x35, 0x2D, 0x98, + 0x05, 0x0B, 0x44, 0xA0, 0x99, 0xC0, 0x99, 0x05, + 0x4B, 0x55, 0x56, 0xC4, 0xFD, 0x98, 0x01, 0xA8, + 0x11, 0xB2, 0xA0, 0x94, 0x5D, 0x09, 0x6D, 0x0A, + 0x72, 0x12, 0x12, 0x1C, 0x04, 0xC0, 0x77, 0x11, + 0x7A, 0x72, 0xBA, 0x77, 0xD2, 0x03, 0x01, 0xE2, + 0x03, 0x03, 0xC2, 0x03, 0x02, 0xB2, 0x03, 0x00, + 0xEA, 0xCC, 0xDA, 0xBB, 0xCA, 0xBB, 0xB0, 0xB2, + 0x41, 0xAD, 0x0B, 0xB2, 0x47, 0x00, 0x82, 0x16, + 0x00, 0x1B, 0x77, 0xBA, 0x88, 0x82, 0x56, 0x00, + 0x2B, 0x66, 0xA5, 0x30, 0x2D, 0x8B, 0x33, 0xF8, + 0x05, 0x0B, 0x44, 0xAA, 0xFF, 0xF9, 0x05, 0x4B, + 0x55, 0x56, 0x74, 0xFC, 0x82, 0x12, 0x12, 0x1B, + 0x88, 0x80, 0x80, 0x44, 0x82, 0x52, 0x12, 0x1D, + 0xF0, 0x36, 0x41, 0x00, 0x32, 0xC2, 0x34, 0x1C, + 0x05, 0x0C, 0x04, 0xB2, 0x13, 0x00, 0xAD, 0x0B, + 0xE5, 0x2D, 0x2D, 0x2B, 0x33, 0x0B, 0x55, 0xA0, + 0x95, 0x41, 0x82, 0x22, 0x15, 0x4B, 0x22, 0x90, + 0x88, 0xC0, 0x80, 0x85, 0x41, 0x8A, 0x44, 0x56, + 0x05, 0xFE, 0x40, 0x24, 0x41, 0x1D, 0xF0, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x1C, 0x07, 0x0C, 0x06, + 0x0C, 0x05, 0xB2, 0xC3, 0x81, 0x42, 0x03, 0x00, + 0xB2, 0x0B, 0x7E, 0xC2, 0x03, 0x01, 0x47, 0xBB, + 0x0C, 0x47, 0xBC, 0x11, 0x4D, 0x0B, 0xC7, 0xBB, + 0x0C, 0x4D, 0x0C, 0xC6, 0x01, 0x00, 0x47, 0x3C, + 0x04, 0xC7, 0xBB, 0x01, 0x4D, 0x0B, 0xAD, 0x04, + 0xBD, 0x04, 0xA5, 0x28, 0x2D, 0xAA, 0x66, 0x5A, + 0x54, 0x0B, 0x77, 0x4B, 0x33, 0xB2, 0xC3, 0x81, + 0x56, 0x97, 0xFC, 0xAD, 0x05, 0xBD, 0x05, 0x65, + 0x27, 0x2D, 0xD2, 0x12, 0x16, 0xA0, 0x94, 0x41, + 0x90, 0x96, 0xC0, 0xD0, 0xCD, 0xF0, 0x90, 0x94, + 0x41, 0x90, 0xE3, 0x41, 0xC0, 0xC3, 0x21, 0xEA, + 0xCC, 0xD0, 0x9C, 0x93, 0x92, 0x52, 0x16, 0x2D, + 0x09, 0x1D, 0xF0, 0x00, 0x00, 0x24, 0x00, 0x00, + 0x00, 0x64, 0x11, 0x02, 0x60, 0x04, 0x11, 0x02, + 0x60, 0xEC, 0x18, 0x00, 0x60, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x13, 0x02, + 0x60, 0xC8, 0x14, 0x02, 0x60, 0xD4, 0x13, 0x02, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x19, 0x00, + 0x60, 0x1C, 0x19, 0x00, 0x60, 0x04, 0x19, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x19, 0x00, + 0x60, 0x2C, 0x19, 0x00, 0x60, 0x08, 0x19, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x48, 0x19, 0x00, 0x60, 0x48, 0x19, 0x00, + 0x60, 0x0C, 0x19, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x94, 0x15, 0x02, 0x60, 0x5C, 0x19, 0x00, + 0x60, 0x5C, 0x19, 0x00, 0x60, 0x58, 0x19, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x00, 0xC4, 0x15, 0x02, + 0x60, 0xCC, 0x15, 0x02, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x6C, 0x19, 0x00, 0x60, 0x70, 0x19, 0x00, + 0x60, 0xB0, 0x19, 0x00, 0x60, 0x94, 0x02, 0x00, + 0x00, 0x84, 0x16, 0x02, 0x60, 0x5F, 0x16, 0x02, + 0x60, 0x84, 0x16, 0x02, 0x60, 0x0E, 0x17, 0x02, + 0x60, 0xE9, 0x16, 0x02, 0x60, 0xCE, 0x16, 0x02, + 0x60, 0x91, 0x16, 0x02, 0x60, 0x8A, 0x16, 0x02, + 0x60, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x0C, 0x00, + 0x60, 0xD4, 0x0C, 0x00, 0x60, 0x10, 0xB0, 0x02, + 0x00, 0xC0, 0x19, 0x00, 0x60, 0x20, 0x01, 0x00, + 0x00, 0xB0, 0x0A, 0x00, 0x60, 0x04, 0x10, 0x02, + 0x60, 0xA0, 0x0A, 0x00, 0x60, 0xA4, 0x10, 0x02, + 0x60, 0xF8, 0x10, 0x02, 0x60, 0x6C, 0x10, 0x02, + 0x60, 0x6C, 0x06, 0x00, 0x60, 0x20, 0x16, 0x02, + 0x60, 0xF4, 0x05, 0x00, 0x60, 0x4C, 0x10, 0x02, + 0x60, 0xA8, 0x0B, 0x00, 0x60, 0xF8, 0x18, 0x00, + 0x60, 0x68, 0x0A, 0x00, 0x60, 0x28, 0x8F, 0x04, + 0x60, 0x48, 0x08, 0x00, 0x60, 0xE0, 0x14, 0x02, + 0x60, 0xAC, 0x06, 0x00, 0x60, 0x20, 0x15, 0x02, + 0x60, 0x38, 0x15, 0x02, 0x60, 0xD8, 0x56, 0x04, + 0x60, 0x36, 0x41, 0x00, 0x81, 0x6F, 0x06, 0xB1, + 0x6D, 0x06, 0x0C, 0x6A, 0x91, 0x6E, 0x06, 0xA2, + 0x4B, 0x00, 0x89, 0x09, 0x25, 0x02, 0x00, 0x65, + 0x07, 0x00, 0x25, 0x09, 0x00, 0xE5, 0x07, 0x00, + 0x65, 0x02, 0x00, 0x65, 0x05, 0x00, 0xA5, 0x6E, + 0xFF, 0xA1, 0x70, 0x06, 0xB1, 0x71, 0x06, 0x65, + 0xB3, 0x2C, 0x1D, 0xF0, 0x00, 0x36, 0x41, 0x00, + 0x31, 0x72, 0x06, 0x21, 0x73, 0x06, 0x22, 0x63, + 0x75, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x0C, 0x8F, 0xB1, 0x72, 0x06, 0xA1, 0x77, 0x06, + 0x91, 0x78, 0x06, 0x81, 0x79, 0x06, 0x31, 0x7A, + 0x06, 0x21, 0x7B, 0x06, 0xC1, 0x76, 0x06, 0xD1, + 0x74, 0x06, 0xE1, 0x75, 0x06, 0xE9, 0xFD, 0xC2, + 0x6D, 0x19, 0x29, 0x83, 0x89, 0x39, 0xA2, 0x6B, + 0x6B, 0xF2, 0x5D, 0x1C, 0x1D, 0xF0, 0x00, 0x00, + 0x00, 0x36, 0x41, 0x00, 0x31, 0x7C, 0x06, 0x21, + 0x7D, 0x06, 0x48, 0x03, 0x49, 0x22, 0x29, 0x03, + 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x31, 0x7E, 0x06, 0x21, 0x7F, 0x06, 0x29, 0x13, + 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x31, 0x80, 0x06, 0x21, 0x81, 0x06, 0x22, 0x63, + 0x19, 0x1D, 0xF0, 0x00, 0x00, 0x36, 0x41, 0x00, + 0x91, 0x83, 0x06, 0x21, 0x85, 0x06, 0x31, 0x82, + 0x06, 0x81, 0x84, 0x06, 0x89, 0xC3, 0x29, 0xA3, + 0x99, 0xB3, 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x04, 0x00, 0x18, 0x1A, 0x02, + 0x60, }; static const unsigned char vfs301_12[] = { /* 57 B */ - 0x12, 0x90, 0x02, 0x00, 0x00, 0xFE, 0x03, 0x00, - 0x00, 0xFF, 0x1F, 0xFF, 0x1F, 0x00, 0x00, 0x00, - 0x00, 0xE3, 0x18, 0xD8, 0x01, 0xE3, 0x18, 0xD8, - 0x01, 0xE3, 0x18, 0xD8, 0x01, 0xE3, 0x18, 0xD8, - 0x01, 0xE3, 0x18, 0xD8, 0x01, 0x20, 0xFA, 0x80, - 0x00, 0x3F, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x03, 0x00, - 0x00, + 0x12, 0x90, 0x02, 0x00, 0x00, 0xFE, 0x03, 0x00, + 0x00, 0xFF, 0x1F, 0xFF, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0xE3, 0x18, 0xD8, 0x01, 0xE3, 0x18, 0xD8, + 0x01, 0xE3, 0x18, 0xD8, 0x01, 0xE3, 0x18, 0xD8, + 0x01, 0xE3, 0x18, 0xD8, 0x01, 0x20, 0xFA, 0x80, + 0x00, 0x3F, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x03, 0x00, + 0x00, }; static const unsigned char vfs301_24[] = { /* 119 B */ - 0x24, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, - 0x07, 0x00, 0x00, 0x00, - 0xF8, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, - 0x07, 0x00, 0x00, 0x00, - 0xF8, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, - 0x07, 0x00, 0x00, 0x00, - 0xF8, 0xFF, 0xFF, 0xFF, - 0x07, 0x00, 0x00, 0x00, - 0xF8, 0xFF, 0xFF, 0xFF, - 0x07, 0x00, 0x00, 0x00, - 0xF8, 0xFF, 0xFF, 0xFF, - 0x07, 0x00, 0x00, 0x00, - 0xF8, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* or : - * 0x00, 0xF4, 0x01, 0xF4, 0x01, 0x00, 0xB4, */ + 0x24, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x07, 0x00, 0x00, 0x00, + 0xF8, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x07, 0x00, 0x00, 0x00, + 0xF8, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x07, 0x00, 0x00, 0x00, + 0xF8, 0xFF, 0xFF, 0xFF, + 0x07, 0x00, 0x00, 0x00, + 0xF8, 0xFF, 0xFF, 0xFF, + 0x07, 0x00, 0x00, 0x00, + 0xF8, 0xFF, 0xFF, 0xFF, + 0x07, 0x00, 0x00, 0x00, + 0xF8, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* or : + * 0x00, 0xF4, 0x01, 0xF4, 0x01, 0x00, 0xB4, */ }; -#define PACKET(cmd, length, payload)\ - cmd length payload +#define PACKET(cmd, length, payload) \ + cmd length payload /* This could be some kind of poke-command. * a looks like the address; (addr << 2), stored in little endian, * b looks like some flags, value of a seems to imply value of b * c looks like the stored value */ #define S1(a, b, c) \ - PACKET("0300", "0900", a b c "04") + PACKET ("0300", "0900", a b c "04") #define S2(a) \ - PACKET("0500", "0E00", a) + PACKET ("0500", "0E00", a) #define S3(a) \ - PACKET("0A00", "0800", a a) + PACKET ("0A00", "0800", a a) #define S4_TAIL \ - "00008000" "6400F401" "00000000" "0000C780" "24004400" + "00008000" "6400F401" "00000000" "0000C780" "24004400" #define S4(a) \ - PACKET("0800", "1800", a a S4_TAIL) + PACKET ("0800", "1800", a a S4_TAIL) #define Z8() \ - "00000000" + "00000000" #define TERM() \ - PACKET("1500", "0800", "0000000020280000") + PACKET ("1500", "0800", "0000000020280000") /* NOTE: * * Reordering the S1() macros in BLOB1 (and similar) doesn't @@ -1153,1479 +1153,1479 @@ static const unsigned char vfs301_24[] = { /* 119 B */ * input lines? */ #define vfs301_0220_BLOB1 \ - S1("0420", "0430", "00000000"),\ - S1("1820", "0430", "00000000"),\ - S1("2020", "0430", "08008000"),\ - S1("2420", "0430", "0000FF01"),\ - S1("2C20", "0430", "01000000"),\ - S1("4020", "0430", "FF030000"),\ - S1("4420", "0430", "E5030000"),\ - S1("4820", "0430", "EA030000"),\ - S1("4C20", "0430", "EA030000"),\ - S1("5020", "0430", "00000400"),\ - S1("5420", "0430", "01980200"),\ - S1("0021", "0430", "00000000"),\ - S1("0421", "0430", "01000000"),\ - S1("0821", "0430", "02000000"),\ - S1("0C21", "0430", "01000000"),\ - S1("1021", "0430", "01000000"),\ - S1("1421", "0430", "01000000"),\ - S1("1821", "0430", "01000000"),\ - S1("1C21", "0430", "1F000000"),\ - S1("2021", "0430", "08000000"),\ - S1("4021", "0430", "00000000"),\ - S1("4421", "0430", "01000000"),\ - S1("4821", "0430", "02000000"),\ - S1("4C21", "0430", "01000000"),\ - S1("5021", "0430", "01000000"),\ - S1("5421", "0430", "01000000"),\ - S1("5821", "0430", "01000000"),\ - S1("5C21", "0430", "1F000000"),\ - S1("6021", "0430", "08000000"),\ - S1("8021", "0430", "30000000"),\ - S1("8421", "0430", "01000000"),\ - S1("8821", "0430", "01000000"),\ - S1("8C21", "0430", "01000000"),\ - S1("9021", "0430", "00000000"),\ - S1("9421", "0430", "01000000"),\ - S1("9821", "0430", "00000000"),\ - S1("9C21", "0430", "1F000000"),\ - S1("A021", "0430", "04000000"),\ - S1("C021", "0430", "30000000"),\ - S1("C421", "0430", "01000000"),\ - S1("C821", "0430", "01000000"),\ - S1("CC21", "0430", "01000000"),\ - S1("D021", "0430", "01000000"),\ - S1("D421", "0430", "01000000"),\ - S1("D821", "0430", "01000000"),\ - S1("DC21", "0430", "1F000000"),\ - S1("E021", "0430", "03000000"),\ - S1("A020", "0430", "EFE10000"),\ - S1("A420", "0430", "00000000"),\ - S1("A820", "0430", "FE210400"),\ - S1("B020", "0430", "00000000"),\ - S1("C420", "0430", "14000000"),\ - S1("C820", "0430", "00000000"),\ - S1("CC20", "0430", "20000000"),\ - S1("38A0", "0038", "5CA30000"),\ - S1("0000", "0038", "02000000"),\ - S1("0400", "0038", "00080000"),\ - S1("0800", "0038", "00120000"),\ - S1("0C00", "0038", "01030200"),\ - S1("1000", "0038", "01070200"),\ - S1("1400", "0038", "0C0C8A00"),\ - PACKET("0200", "8005", \ - "FFF98720" \ - "1AF88700" \ - "1AF88700" \ - "1AF88700" \ - "1AF88700" \ - "1AF88700" \ - "1AF88700" \ - /* NOTE: The following(?) 200 values specify order of fingerprint columns \ - * in vfs301_line_t::scan. */ \ - "1AF80720" \ - "1BF80720" \ - "1CF80720" \ - "1DF80720" \ - "1EF80720" \ - "1FF80720" \ - "20F80720" \ - "21F80720" \ - "22F80720" \ - "23F80720" \ - "24F80722" \ - "25F80722" \ - "26F80722" \ - "27F80722" \ - "28F80722" \ - "29F80722" \ - "2AF80722" \ - "2BF80722" \ - "2CF80722" \ - "2DF80722" \ - "2EF80722" \ - "2FF80722" \ - "30F80722" \ - "31F80722" \ - "32F80722" \ - "33F80722" \ - "34F80722" \ - "35F80722" \ - "36F80722" \ - "37F80722" \ - "38F80722" \ - "39F80722" \ - "3AF80722" \ - "3BF80722" \ - "3CF80722" \ - "3DF80722" \ - "3EF80722" \ - "3FF80722" \ - "40F80722" \ - "41F80722" \ - "42F80722" \ - "43F80722" \ - "44F80722" \ - "45F80722" \ - "46F80722" \ - "47F80722" \ - "48F80722" \ - "49F80722" \ - "4AF80722" \ - "4BF80722" \ - "4CF80722" \ - "4DF80722" \ - "4EF80722" \ - "4FF80722" \ - "50F80722" \ - "51F80722" \ - "52F80722" \ - "53F80722" \ - "54F80722" \ - "55F80722" \ - "56F80722" \ - "57F80722" \ - "58F80722" \ - "59F80722" \ - "5AF80722" \ - "5BF80722" \ - "5CF80722" \ - "5DF80722" \ - "5EF80722" \ - "5FF80722" \ - "60F80722" \ - "61F80722" \ - "62F80722" \ - "63F80722" \ - "64F80722" \ - "65F80722" \ - "66F80722" \ - "67F80722" \ - "68F80722" \ - "69F80722" \ - "6AF80722" \ - "6BF80722" \ - "6CF80722" \ - "6DF80722" \ - "6EF80722" \ - "6FF80722" \ - "70F80722" \ - "71F80722" \ - "72F80722" \ - "73F80722" \ - "74F80722" \ - "75F80722" \ - "76F80722" \ - "77F80722" \ - "78F80722" \ - "79F80722" \ - "7AF80722" \ - "7BF80722" \ - "7CF80722" \ - "7DF80722" \ - "7EF80722" \ - "7FF80722" \ - "80F80722" \ - "81F80722" \ - "82F80722" \ - "83F80722" \ - "84F80722" \ - "85F80722" \ - "86F80722" \ - "87F80722" \ - "88F80722" \ - "89F80722" \ - "8AF80722" \ - "8BF80722" \ - "8CF80722" \ - "8DF80722" \ - "8EF80722" \ - "8FF80722" \ - "90F80722" \ - "91F80722" \ - "92F80722" \ - "93F80722" \ - "94F80722" \ - "95F80722" \ - "96F80722" \ - "97F80722" \ - "98F80722" \ - "99F80722" \ - "9AF80722" \ - "9BF80722" \ - "9CF80722" \ - "9DF80722" \ - "9EF80722" \ - "9FF80722" \ - "A0F80722" \ - "A1F80722" \ - "A2F80722" \ - "A3F80722" \ - "A4F80722" \ - "A5F80722" \ - "A6F80722" \ - "A7F80722" \ - "A8F80722" \ - "A9F80722" \ - "AAF80722" \ - "ABF80722" \ - "ACF80722" \ - "ADF80722" \ - "AEF80722" \ - "AFF80722" \ - "B0F80722" \ - "B1F80722" \ - "B2F80722" \ - "B3F80722" \ - "B4F80722" \ - "B5F80722" \ - "B6F80722" \ - "B7F80722" \ - "B8F80722" \ - "B9F80722" \ - "BAF80722" \ - "BBF80722" \ - "BCF80722" \ - "BDF80722" \ - "BEF80722" \ - "BFF80722" \ - "C0F80722" \ - "C1F80722" \ - "C2F80722" \ - "C3F80722" \ - "C4F80722" \ - "C5F80722" \ - "C6F80722" \ - "C7F80722" \ - "C8F80722" \ - "C9F80722" \ - "CAF80722" \ - "CBF80722" \ - "CCF80722" \ - "CDF80722" \ - "CEF80722" \ - "CFF80722" \ - "D0F80722" \ - "D1F80722" \ - "D2F80722" \ - "D3F80722" \ - "D4F80722" \ - "D5F80722" \ - "D6F80722" \ - "D7F80722" \ - "D8F80720" \ - "D9F80720" \ - "DAF80720" \ - "DBF80720" \ - "DCF80720" \ - "DDF80720" \ - "DEF80720" \ - "DFF80720" \ - "E0F80720" \ - "E1F80720" \ - \ - "E1F80700" \ - "0BF88700" \ - "0BF88700" \ - "0BF88700" \ - "0BF88700" \ - "0BF88700" \ - /* NOTE: The following(?) 64 values specify order of fingerprint columns \ - * in vfs301_line_t::mirror. \ - * Placing Z8() instead of the value shortens the mirror section. \ - * */ \ - "0BF88700" \ - "0AF80720" \ - "09F80720" \ - "08F80720" \ - "07F80720" \ - "06F80720" \ - "05F80720" \ - "04F80720" \ - "03F80720" \ - "02F80720" \ - "01F80720" \ - "00F80720" \ - "17F90720" \ - "16F90720" \ - "15F90720" \ - "14F90720" \ - "13F90720" \ - "12F90720" \ - "11F90720" \ - "10F90720" \ - "0FF90720" \ - "0EF90720" \ - "0DF90720" \ - "0CF90720" \ - "0BF90720" \ - "0AF90720" \ - "09F90720" \ - "08F90720" \ - "07F90720" \ - "06F90720" \ - "05F90720" \ - "04F90720" \ - "03F90720" \ - "02F90720" \ - "01F90720" \ - "00F90720" \ - "FFF80720" \ - "FEF80720" \ - "FDF80720" \ - "FCF80720" \ - "FBF80720" \ - "FAF80720" \ - "F9F80720" \ - "F8F80720" \ - "F7F80720" \ - "F6F80720" \ - "F5F80720" \ - "F4F80720" \ - "F3F80720" \ - "F2F80720" \ - "F1F80720" \ - "F0F80720" \ - "EFF80720" \ - "EEF80720" \ - "EDF80720" \ - "ECF80720" \ - "EBF80720" \ - "EAF80720" \ - "E9F80720" \ - "E8F80720" \ - "E7F80720" \ - "E6F80720" \ - "E5F80720" \ - "E4F80720" \ - \ - "0BF80720" \ - "0BF80700" \ - \ - "5CF2C700" \ - "5CF2C700" \ - "5CF2C700" \ - "5CF2C700" \ - "5CF2C700" \ - "5CF24700" \ - "5CF24700" \ - "5CF24720" \ - "FFF94700" \ - "FFF94700" \ - "FFF94700" \ - "FFF94700" \ - "FFF94700" \ - "FFF94720" \ - "5CF84700" \ - "5CF84700" \ - "5CF84700" \ - "5CF84700" \ - \ - /* NOTE: The following(?) values specify order of fingerprint columns \ - * in vfs301_line_t::sum*. */ \ - "5CF84700" \ - "5CF84720" \ - "62F84700" \ - "62F84720" \ - "68F84700" \ - "68F84720" \ - "6EF84700" \ - "6EF84720" \ - "74F84700" \ - "74F84720" \ - "7AF84700" \ - "7AF84720" \ - "80F84700" \ - "80F84720" \ - "86F84700" \ - "86F84720" \ - "8CF84700" \ - "8CF84720" \ - "92F84700" \ - "92F84720" \ - "98F84720" \ - "9E844700" \ - "9E844720" \ - "9E844700" \ - \ - "FFF96700" "FFF96700" "FFF96700" "FFF96700" "FFF96720" \ - "0DF86700" "0DF86700" "0DF86700" "0DF86700" "0DF86700" \ - "0DF86720" "0DF86700" \ - Z8() Z8() Z8() Z8() Z8() Z8() Z8() Z8() Z8() Z8() Z8() Z8() \ - Z8() Z8() Z8() Z8() Z8() Z8() Z8() \ - ), \ - S3("1003181C"), \ - S1("0020", "0430", "80000000") + S1 ("0420", "0430", "00000000"), \ + S1 ("1820", "0430", "00000000"), \ + S1 ("2020", "0430", "08008000"), \ + S1 ("2420", "0430", "0000FF01"), \ + S1 ("2C20", "0430", "01000000"), \ + S1 ("4020", "0430", "FF030000"), \ + S1 ("4420", "0430", "E5030000"), \ + S1 ("4820", "0430", "EA030000"), \ + S1 ("4C20", "0430", "EA030000"), \ + S1 ("5020", "0430", "00000400"), \ + S1 ("5420", "0430", "01980200"), \ + S1 ("0021", "0430", "00000000"), \ + S1 ("0421", "0430", "01000000"), \ + S1 ("0821", "0430", "02000000"), \ + S1 ("0C21", "0430", "01000000"), \ + S1 ("1021", "0430", "01000000"), \ + S1 ("1421", "0430", "01000000"), \ + S1 ("1821", "0430", "01000000"), \ + S1 ("1C21", "0430", "1F000000"), \ + S1 ("2021", "0430", "08000000"), \ + S1 ("4021", "0430", "00000000"), \ + S1 ("4421", "0430", "01000000"), \ + S1 ("4821", "0430", "02000000"), \ + S1 ("4C21", "0430", "01000000"), \ + S1 ("5021", "0430", "01000000"), \ + S1 ("5421", "0430", "01000000"), \ + S1 ("5821", "0430", "01000000"), \ + S1 ("5C21", "0430", "1F000000"), \ + S1 ("6021", "0430", "08000000"), \ + S1 ("8021", "0430", "30000000"), \ + S1 ("8421", "0430", "01000000"), \ + S1 ("8821", "0430", "01000000"), \ + S1 ("8C21", "0430", "01000000"), \ + S1 ("9021", "0430", "00000000"), \ + S1 ("9421", "0430", "01000000"), \ + S1 ("9821", "0430", "00000000"), \ + S1 ("9C21", "0430", "1F000000"), \ + S1 ("A021", "0430", "04000000"), \ + S1 ("C021", "0430", "30000000"), \ + S1 ("C421", "0430", "01000000"), \ + S1 ("C821", "0430", "01000000"), \ + S1 ("CC21", "0430", "01000000"), \ + S1 ("D021", "0430", "01000000"), \ + S1 ("D421", "0430", "01000000"), \ + S1 ("D821", "0430", "01000000"), \ + S1 ("DC21", "0430", "1F000000"), \ + S1 ("E021", "0430", "03000000"), \ + S1 ("A020", "0430", "EFE10000"), \ + S1 ("A420", "0430", "00000000"), \ + S1 ("A820", "0430", "FE210400"), \ + S1 ("B020", "0430", "00000000"), \ + S1 ("C420", "0430", "14000000"), \ + S1 ("C820", "0430", "00000000"), \ + S1 ("CC20", "0430", "20000000"), \ + S1 ("38A0", "0038", "5CA30000"), \ + S1 ("0000", "0038", "02000000"), \ + S1 ("0400", "0038", "00080000"), \ + S1 ("0800", "0038", "00120000"), \ + S1 ("0C00", "0038", "01030200"), \ + S1 ("1000", "0038", "01070200"), \ + S1 ("1400", "0038", "0C0C8A00"), \ + PACKET ("0200", "8005", \ + "FFF98720" \ + "1AF88700" \ + "1AF88700" \ + "1AF88700" \ + "1AF88700" \ + "1AF88700" \ + "1AF88700" \ + /* NOTE: The following(?) 200 values specify order of fingerprint columns \ + * in vfs301_line_t::scan. */ \ + "1AF80720" \ + "1BF80720" \ + "1CF80720" \ + "1DF80720" \ + "1EF80720" \ + "1FF80720" \ + "20F80720" \ + "21F80720" \ + "22F80720" \ + "23F80720" \ + "24F80722" \ + "25F80722" \ + "26F80722" \ + "27F80722" \ + "28F80722" \ + "29F80722" \ + "2AF80722" \ + "2BF80722" \ + "2CF80722" \ + "2DF80722" \ + "2EF80722" \ + "2FF80722" \ + "30F80722" \ + "31F80722" \ + "32F80722" \ + "33F80722" \ + "34F80722" \ + "35F80722" \ + "36F80722" \ + "37F80722" \ + "38F80722" \ + "39F80722" \ + "3AF80722" \ + "3BF80722" \ + "3CF80722" \ + "3DF80722" \ + "3EF80722" \ + "3FF80722" \ + "40F80722" \ + "41F80722" \ + "42F80722" \ + "43F80722" \ + "44F80722" \ + "45F80722" \ + "46F80722" \ + "47F80722" \ + "48F80722" \ + "49F80722" \ + "4AF80722" \ + "4BF80722" \ + "4CF80722" \ + "4DF80722" \ + "4EF80722" \ + "4FF80722" \ + "50F80722" \ + "51F80722" \ + "52F80722" \ + "53F80722" \ + "54F80722" \ + "55F80722" \ + "56F80722" \ + "57F80722" \ + "58F80722" \ + "59F80722" \ + "5AF80722" \ + "5BF80722" \ + "5CF80722" \ + "5DF80722" \ + "5EF80722" \ + "5FF80722" \ + "60F80722" \ + "61F80722" \ + "62F80722" \ + "63F80722" \ + "64F80722" \ + "65F80722" \ + "66F80722" \ + "67F80722" \ + "68F80722" \ + "69F80722" \ + "6AF80722" \ + "6BF80722" \ + "6CF80722" \ + "6DF80722" \ + "6EF80722" \ + "6FF80722" \ + "70F80722" \ + "71F80722" \ + "72F80722" \ + "73F80722" \ + "74F80722" \ + "75F80722" \ + "76F80722" \ + "77F80722" \ + "78F80722" \ + "79F80722" \ + "7AF80722" \ + "7BF80722" \ + "7CF80722" \ + "7DF80722" \ + "7EF80722" \ + "7FF80722" \ + "80F80722" \ + "81F80722" \ + "82F80722" \ + "83F80722" \ + "84F80722" \ + "85F80722" \ + "86F80722" \ + "87F80722" \ + "88F80722" \ + "89F80722" \ + "8AF80722" \ + "8BF80722" \ + "8CF80722" \ + "8DF80722" \ + "8EF80722" \ + "8FF80722" \ + "90F80722" \ + "91F80722" \ + "92F80722" \ + "93F80722" \ + "94F80722" \ + "95F80722" \ + "96F80722" \ + "97F80722" \ + "98F80722" \ + "99F80722" \ + "9AF80722" \ + "9BF80722" \ + "9CF80722" \ + "9DF80722" \ + "9EF80722" \ + "9FF80722" \ + "A0F80722" \ + "A1F80722" \ + "A2F80722" \ + "A3F80722" \ + "A4F80722" \ + "A5F80722" \ + "A6F80722" \ + "A7F80722" \ + "A8F80722" \ + "A9F80722" \ + "AAF80722" \ + "ABF80722" \ + "ACF80722" \ + "ADF80722" \ + "AEF80722" \ + "AFF80722" \ + "B0F80722" \ + "B1F80722" \ + "B2F80722" \ + "B3F80722" \ + "B4F80722" \ + "B5F80722" \ + "B6F80722" \ + "B7F80722" \ + "B8F80722" \ + "B9F80722" \ + "BAF80722" \ + "BBF80722" \ + "BCF80722" \ + "BDF80722" \ + "BEF80722" \ + "BFF80722" \ + "C0F80722" \ + "C1F80722" \ + "C2F80722" \ + "C3F80722" \ + "C4F80722" \ + "C5F80722" \ + "C6F80722" \ + "C7F80722" \ + "C8F80722" \ + "C9F80722" \ + "CAF80722" \ + "CBF80722" \ + "CCF80722" \ + "CDF80722" \ + "CEF80722" \ + "CFF80722" \ + "D0F80722" \ + "D1F80722" \ + "D2F80722" \ + "D3F80722" \ + "D4F80722" \ + "D5F80722" \ + "D6F80722" \ + "D7F80722" \ + "D8F80720" \ + "D9F80720" \ + "DAF80720" \ + "DBF80720" \ + "DCF80720" \ + "DDF80720" \ + "DEF80720" \ + "DFF80720" \ + "E0F80720" \ + "E1F80720" \ + \ + "E1F80700" \ + "0BF88700" \ + "0BF88700" \ + "0BF88700" \ + "0BF88700" \ + "0BF88700" \ + /* NOTE: The following(?) 64 values specify order of fingerprint columns \ + * in vfs301_line_t::mirror. \ + * Placing Z8() instead of the value shortens the mirror section. \ + * */ \ + "0BF88700" \ + "0AF80720" \ + "09F80720" \ + "08F80720" \ + "07F80720" \ + "06F80720" \ + "05F80720" \ + "04F80720" \ + "03F80720" \ + "02F80720" \ + "01F80720" \ + "00F80720" \ + "17F90720" \ + "16F90720" \ + "15F90720" \ + "14F90720" \ + "13F90720" \ + "12F90720" \ + "11F90720" \ + "10F90720" \ + "0FF90720" \ + "0EF90720" \ + "0DF90720" \ + "0CF90720" \ + "0BF90720" \ + "0AF90720" \ + "09F90720" \ + "08F90720" \ + "07F90720" \ + "06F90720" \ + "05F90720" \ + "04F90720" \ + "03F90720" \ + "02F90720" \ + "01F90720" \ + "00F90720" \ + "FFF80720" \ + "FEF80720" \ + "FDF80720" \ + "FCF80720" \ + "FBF80720" \ + "FAF80720" \ + "F9F80720" \ + "F8F80720" \ + "F7F80720" \ + "F6F80720" \ + "F5F80720" \ + "F4F80720" \ + "F3F80720" \ + "F2F80720" \ + "F1F80720" \ + "F0F80720" \ + "EFF80720" \ + "EEF80720" \ + "EDF80720" \ + "ECF80720" \ + "EBF80720" \ + "EAF80720" \ + "E9F80720" \ + "E8F80720" \ + "E7F80720" \ + "E6F80720" \ + "E5F80720" \ + "E4F80720" \ + \ + "0BF80720" \ + "0BF80700" \ + \ + "5CF2C700" \ + "5CF2C700" \ + "5CF2C700" \ + "5CF2C700" \ + "5CF2C700" \ + "5CF24700" \ + "5CF24700" \ + "5CF24720" \ + "FFF94700" \ + "FFF94700" \ + "FFF94700" \ + "FFF94700" \ + "FFF94700" \ + "FFF94720" \ + "5CF84700" \ + "5CF84700" \ + "5CF84700" \ + "5CF84700" \ + \ + /* NOTE: The following(?) values specify order of fingerprint columns \ + * in vfs301_line_t::sum*. */ \ + "5CF84700" \ + "5CF84720" \ + "62F84700" \ + "62F84720" \ + "68F84700" \ + "68F84720" \ + "6EF84700" \ + "6EF84720" \ + "74F84700" \ + "74F84720" \ + "7AF84700" \ + "7AF84720" \ + "80F84700" \ + "80F84720" \ + "86F84700" \ + "86F84720" \ + "8CF84700" \ + "8CF84720" \ + "92F84700" \ + "92F84720" \ + "98F84720" \ + "9E844700" \ + "9E844720" \ + "9E844700" \ + \ + "FFF96700" "FFF96700" "FFF96700" "FFF96700" "FFF96720" \ + "0DF86700" "0DF86700" "0DF86700" "0DF86700" "0DF86700" \ + "0DF86720" "0DF86700" \ + Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () \ + Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () \ + ), \ + S3 ("1003181C"), \ + S1 ("0020", "0430", "80000000") #define vfs301_0220_BLOB2 \ - S2("0C20FF00FFFF0000000000030000"),\ - S2("1020FF00FFFF0000000000070000"),\ - S1("0421", "0430", "01000000"),\ - S1("0821", "0430", "02000000"),\ - S1("0C21", "0430", "01000000"),\ - S1("1021", "0430", "01000000"),\ - S1("1421", "0430", "01000000"),\ - S1("1821", "0430", "01000000"),\ - S1("4421", "0430", "01000000"),\ - S1("4821", "0430", "02000000"),\ - S1("4C21", "0430", "01000000"),\ - S1("5021", "0430", "01000000"),\ - S1("5421", "0430", "01000000"),\ - S1("5821", "0430", "01000000"),\ - S1("C820", "0430", "07000000"),\ - S2("1420FFFF00FF0000000000008800"),\ - S1("8421", "0430", "01000000"),\ - S1("8821", "0430", "01000000"),\ - S1("8C21", "0430", "01000000"),\ - S1("9021", "0430", "01000000"),\ - S1("9421", "0430", "01000000"),\ - S1("9821", "0430", "01000000"),\ - S1("A021", "0430", "00000000"),\ - S1("2021", "0430", "08000000"),\ - S1("6021", "0430", "08000000") + S2 ("0C20FF00FFFF0000000000030000"), \ + S2 ("1020FF00FFFF0000000000070000"), \ + S1 ("0421", "0430", "01000000"), \ + S1 ("0821", "0430", "02000000"), \ + S1 ("0C21", "0430", "01000000"), \ + S1 ("1021", "0430", "01000000"), \ + S1 ("1421", "0430", "01000000"), \ + S1 ("1821", "0430", "01000000"), \ + S1 ("4421", "0430", "01000000"), \ + S1 ("4821", "0430", "02000000"), \ + S1 ("4C21", "0430", "01000000"), \ + S1 ("5021", "0430", "01000000"), \ + S1 ("5421", "0430", "01000000"), \ + S1 ("5821", "0430", "01000000"), \ + S1 ("C820", "0430", "07000000"), \ + S2 ("1420FFFF00FF0000000000008800"), \ + S1 ("8421", "0430", "01000000"), \ + S1 ("8821", "0430", "01000000"), \ + S1 ("8C21", "0430", "01000000"), \ + S1 ("9021", "0430", "01000000"), \ + S1 ("9421", "0430", "01000000"), \ + S1 ("9821", "0430", "01000000"), \ + S1 ("A021", "0430", "00000000"), \ + S1 ("2021", "0430", "08000000"), \ + S1 ("6021", "0430", "08000000") #define vfs301_02D0_BLOB1 \ - S1("A820", "0430", "FE210000"), \ - S1("B020", "0430", "00000000"), \ - S1("C420", "0430", "14000000"), \ - S1("C820", "0430", "00000000"), \ - S1("CC20", "0430", "20000000"), \ - S1("38A0", "0038", "5CA30000"), \ - S1("0000", "0038", "02000000"), \ - S1("0400", "0038", "00080000"), \ - S1("0800", "0038", "00120000"), \ - S1("0C00", "0038", "01030200"), \ - S1("1000", "0038", "01070200"), \ - S1("1400", "0038", "0C0C8A00") + S1 ("A820", "0430", "FE210000"), \ + S1 ("B020", "0430", "00000000"), \ + S1 ("C420", "0430", "14000000"), \ + S1 ("C820", "0430", "00000000"), \ + S1 ("CC20", "0430", "20000000"), \ + S1 ("38A0", "0038", "5CA30000"), \ + S1 ("0000", "0038", "02000000"), \ + S1 ("0400", "0038", "00080000"), \ + S1 ("0800", "0038", "00120000"), \ + S1 ("0C00", "0038", "01030200"), \ + S1 ("1000", "0038", "01070200"), \ + S1 ("1400", "0038", "0C0C8A00") #define vfs301_02D0_BLOB4 \ - PACKET("1200", "0100", "01"),\ - S2("0C20FF00FFFF0000000000030000"),\ - S2("1020FF00FFFF0000000000070000"),\ - S1("0421", "0430", "01000000"),\ - S1("0821", "0430", "02000000"),\ - S1("0C21", "0430", "01000000"),\ - S1("1021", "0430", "01000000"),\ - S1("1421", "0430", "01000000"),\ - S1("1821", "0430", "01000000"),\ - S1("4421", "0430", "01000000"),\ - S1("4821", "0430", "02000000"),\ - S1("4C21", "0430", "01000000"),\ - S1("5021", "0430", "01000000"),\ - S1("5421", "0430", "01000000"),\ - S1("5821", "0430", "01000000") + PACKET ("1200", "0100", "01"), \ + S2 ("0C20FF00FFFF0000000000030000"), \ + S2 ("1020FF00FFFF0000000000070000"), \ + S1 ("0421", "0430", "01000000"), \ + S1 ("0821", "0430", "02000000"), \ + S1 ("0C21", "0430", "01000000"), \ + S1 ("1021", "0430", "01000000"), \ + S1 ("1421", "0430", "01000000"), \ + S1 ("1821", "0430", "01000000"), \ + S1 ("4421", "0430", "01000000"), \ + S1 ("4821", "0430", "02000000"), \ + S1 ("4C21", "0430", "01000000"), \ + S1 ("5021", "0430", "01000000"), \ + S1 ("5421", "0430", "01000000"), \ + S1 ("5821", "0430", "01000000") /* TODO: looks like that removing this whole packet doesn't cause * any troubles. */ -#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" \ - 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() \ - 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() \ - 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() \ - 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() \ - Z8() Z8() Z8() Z8() Z8() Z8() Z8() Z8() \ - ),\ - S3("1003181C"),\ - S1("0020", "0430", "80000000") +#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" \ + 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 () \ + 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 () \ + 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 () \ + 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 () \ + Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () \ + ), \ + S3 ("1003181C"), \ + S1 ("0020", "0430", "80000000") const char *vfs301_0220_01[] = { - "0220010100", + "0220010100", - /* NOTE: replacing this by vfs301_0220_BLOB1 seems to not cause problems */ - S1("0420", "0430", "00000000"), - S1("1820", "0430", "00000000"), - S1("2020", "0430", "08008000"), - S1("2420", "0430", "0000FF01"), - S1("2C20", "0430", "01000000"), - S1("4020", "0430", "AD010000"), - S1("4420", "0430", "AD010000"), - S1("4820", "0430", "AD010000"), - S1("4C20", "0430", "FF030000"), - S1("5020", "0430", "00005003"), - S1("5420", "0430", "013E0200"), - S1("0021", "0430", "14000000"), - S1("0421", "0430", "01000000"), - S1("0821", "0430", "01000000"), - S1("0C21", "0430", "01000000"), - S1("1021", "0430", "01000000"), - S1("1421", "0430", "01000000"), - S1("1821", "0430", "01000000"), - S1("1C21", "0430", "12000000"), - S1("2021", "0430", "04000000"), - S1("4021", "0430", "00000000"), - S1("4421", "0430", "01000000"), - S1("4821", "0430", "10000000"), - S1("4C21", "0430", "01000000"), - S1("5021", "0430", "01000000"), - S1("5421", "0430", "00000000"), - S1("5821", "0430", "01000000"), - S1("5C21", "0430", "1F000000"), - S1("6021", "0430", "0F000000"), - S1("8021", "0430", "00000000"), - S1("8421", "0430", "01000000"), - S1("8821", "0430", "10000000"), - S1("8C21", "0430", "01000000"), - S1("9021", "0430", "01000000"), - S1("9421", "0430", "00000000"), - S1("9821", "0430", "01000000"), - S1("9C21", "0430", "1F000000"), - S1("A021", "0430", "0F000000"), - S1("C021", "0430", "00000000"), - S1("C421", "0430", "01000000"), - S1("C821", "0430", "10000000"), - S1("CC21", "0430", "01000000"), - S1("D021", "0430", "01000000"), - S1("D421", "0430", "00000000"), - S1("D821", "0430", "01000000"), - S1("DC21", "0430", "1F000000"), - S1("E021", "0430", "0F000000"), - S1("A020", "0430", "EFE10000"), - S1("A420", "0430", "00000000"), - S1("A820", "0430", "FE210000"), - S1("B020", "0430", "00000000"), - S1("C420", "0430", "47000000"), - S1("C820", "0430", "00000000"), - S1("CC20", "0430", "20000000"), - S1("38A0", "0038", "5CA30000"), - S1("0000", "0038", "02000000"), - S1("0400", "0038", "00080000"), - S1("0800", "0038", "00120000"), - S1("0C00", "0038", "01030200"), - S1("1000", "0038", "01070200"), - S1("1400", "0038", "0C0C8A00"), + /* NOTE: replacing this by vfs301_0220_BLOB1 seems to not cause problems */ + S1 ("0420", "0430", "00000000"), + S1 ("1820", "0430", "00000000"), + S1 ("2020", "0430", "08008000"), + S1 ("2420", "0430", "0000FF01"), + S1 ("2C20", "0430", "01000000"), + S1 ("4020", "0430", "AD010000"), + S1 ("4420", "0430", "AD010000"), + S1 ("4820", "0430", "AD010000"), + S1 ("4C20", "0430", "FF030000"), + S1 ("5020", "0430", "00005003"), + S1 ("5420", "0430", "013E0200"), + S1 ("0021", "0430", "14000000"), + S1 ("0421", "0430", "01000000"), + S1 ("0821", "0430", "01000000"), + S1 ("0C21", "0430", "01000000"), + S1 ("1021", "0430", "01000000"), + S1 ("1421", "0430", "01000000"), + S1 ("1821", "0430", "01000000"), + S1 ("1C21", "0430", "12000000"), + S1 ("2021", "0430", "04000000"), + S1 ("4021", "0430", "00000000"), + S1 ("4421", "0430", "01000000"), + S1 ("4821", "0430", "10000000"), + S1 ("4C21", "0430", "01000000"), + S1 ("5021", "0430", "01000000"), + S1 ("5421", "0430", "00000000"), + S1 ("5821", "0430", "01000000"), + S1 ("5C21", "0430", "1F000000"), + S1 ("6021", "0430", "0F000000"), + S1 ("8021", "0430", "00000000"), + S1 ("8421", "0430", "01000000"), + S1 ("8821", "0430", "10000000"), + S1 ("8C21", "0430", "01000000"), + S1 ("9021", "0430", "01000000"), + S1 ("9421", "0430", "00000000"), + S1 ("9821", "0430", "01000000"), + S1 ("9C21", "0430", "1F000000"), + S1 ("A021", "0430", "0F000000"), + S1 ("C021", "0430", "00000000"), + S1 ("C421", "0430", "01000000"), + S1 ("C821", "0430", "10000000"), + S1 ("CC21", "0430", "01000000"), + S1 ("D021", "0430", "01000000"), + S1 ("D421", "0430", "00000000"), + S1 ("D821", "0430", "01000000"), + S1 ("DC21", "0430", "1F000000"), + S1 ("E021", "0430", "0F000000"), + S1 ("A020", "0430", "EFE10000"), + S1 ("A420", "0430", "00000000"), + S1 ("A820", "0430", "FE210000"), + S1 ("B020", "0430", "00000000"), + S1 ("C420", "0430", "47000000"), + S1 ("C820", "0430", "00000000"), + S1 ("CC20", "0430", "20000000"), + S1 ("38A0", "0038", "5CA30000"), + S1 ("0000", "0038", "02000000"), + S1 ("0400", "0038", "00080000"), + S1 ("0800", "0038", "00120000"), + S1 ("0C00", "0038", "01030200"), + S1 ("1000", "0038", "01070200"), + S1 ("1400", "0038", "0C0C8A00"), - /* TODO: looks like that removing this whole packet doesn't cause - * any troubles. */ - PACKET("0200", "8005", - "FFF98720" - "83488420" - "83488420" - "83488420" - "83488420" - "83488420" - "83488420" - "83488420" - "83488420" - "83488420" - "83488420" - "85480420" - "87480420" - "89480420" - "8B480420" - "8D480420" - "8F480420" - "91480420" - "93480420" - "95480420" - "97480420" - "99480420" - "9B480420" - "9D480420" - "9F480420" - "A1480420" - "A3480420" - "A3480400" - "855A0420" - "875A0420" - "895A0420" - "8B5A0420" - "8D5A0420" - "8F5A0420" - "915A0420" - "935A0420" - "955A0420" - "975A0420" - "995A0420" - "9B5A0420" - "9D5A0420" - "9F5A0420" - "A15A0420" - "A35A0420" - "A35A0400" - "856C0420" - "876C0420" - "896C0420" - "8B6C0420" - "8D6C0420" - "8F6C0420" - "916C0420" - "936C0420" - "956C0420" - "976C0420" - "996C0420" - "9B6C0420" - "9D6C0420" - "9F6C0420" - "A16C0420" - "A36C0420" - "A36C0400" - "86480420" - "88480420" - "8A480420" - "8C480420" - "8E480420" - "90480420" - "92480420" - "94480420" - "96480420" - "98480420" - "9A480420" - "9C480420" - "9E480420" - "A0480420" - "A2480420" - "A4480420" - "A4480400" - "865A0420" - "885A0420" - "8A5A0420" - "8C5A0420" - "8E5A0420" - "905A0420" - "925A0420" - "945A0420" - "965A0420" - "985A0420" - "9A5A0420" - "9C5A0420" - "9E5A0420" - "A05A0420" - "A25A0420" - "A45A0420" - "A45A0400" - "866C0420" - "886C0420" - "8A6C0420" - "8C6C0420" - "8E6C0420" - "906C0420" - "926C0420" - "946C0420" - "966C0420" - "986C0420" - "9A6C0420" - "9C6C0420" - "9E6C0420" - "A06C0420" - "A26C0420" - "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" - 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() - 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() - ), - S3("10035109"), - S1("0020", "0430", "80000000"), + /* TODO: looks like that removing this whole packet doesn't cause + * any troubles. */ + PACKET ("0200", "8005", + "FFF98720" + "83488420" + "83488420" + "83488420" + "83488420" + "83488420" + "83488420" + "83488420" + "83488420" + "83488420" + "83488420" + "85480420" + "87480420" + "89480420" + "8B480420" + "8D480420" + "8F480420" + "91480420" + "93480420" + "95480420" + "97480420" + "99480420" + "9B480420" + "9D480420" + "9F480420" + "A1480420" + "A3480420" + "A3480400" + "855A0420" + "875A0420" + "895A0420" + "8B5A0420" + "8D5A0420" + "8F5A0420" + "915A0420" + "935A0420" + "955A0420" + "975A0420" + "995A0420" + "9B5A0420" + "9D5A0420" + "9F5A0420" + "A15A0420" + "A35A0420" + "A35A0400" + "856C0420" + "876C0420" + "896C0420" + "8B6C0420" + "8D6C0420" + "8F6C0420" + "916C0420" + "936C0420" + "956C0420" + "976C0420" + "996C0420" + "9B6C0420" + "9D6C0420" + "9F6C0420" + "A16C0420" + "A36C0420" + "A36C0400" + "86480420" + "88480420" + "8A480420" + "8C480420" + "8E480420" + "90480420" + "92480420" + "94480420" + "96480420" + "98480420" + "9A480420" + "9C480420" + "9E480420" + "A0480420" + "A2480420" + "A4480420" + "A4480400" + "865A0420" + "885A0420" + "8A5A0420" + "8C5A0420" + "8E5A0420" + "905A0420" + "925A0420" + "945A0420" + "965A0420" + "985A0420" + "9A5A0420" + "9C5A0420" + "9E5A0420" + "A05A0420" + "A25A0420" + "A45A0420" + "A45A0400" + "866C0420" + "886C0420" + "8A6C0420" + "8C6C0420" + "8E6C0420" + "906C0420" + "926C0420" + "946C0420" + "966C0420" + "986C0420" + "9A6C0420" + "9C6C0420" + "9E6C0420" + "A06C0420" + "A26C0420" + "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" + 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 () + 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 () + ), + S3 ("10035109"), + S1 ("0020", "0430", "80000000"), - TERM(), + TERM (), - NULL + NULL }; const char *vfs301_next_scan_template[] = { - PACKET("0220", "0100", "00"), + PACKET ("0220", "0100", "00"), - vfs301_0220_BLOB1, + vfs301_0220_BLOB1, - vfs301_0220_BLOB2, + vfs301_0220_BLOB2, - TERM(), + TERM (), - S4("DEAD"), + S4 ("DEAD"), - NULL + NULL }; const char *vfs301_0220_02[] = { - "0220011400", + "0220011400", - vfs301_0220_BLOB1, + vfs301_0220_BLOB1, - vfs301_0220_BLOB2, + vfs301_0220_BLOB2, - TERM(), + TERM (), - NULL + NULL }; const char *vfs301_0220_03[] = { - "0220011400", + "0220011400", - vfs301_0220_BLOB1, + vfs301_0220_BLOB1, - "17000000", + "17000000", - vfs301_0220_BLOB2, + vfs301_0220_BLOB2, - TERM(), + TERM (), - NULL + NULL }; const char *vfs301_02D0_01[] = { - "02D0003800", + "02D0003800", - S1("0420", "0430", "00000000"), - S1("1820", "0430", "01807800"), - S1("2020", "0430", "08008000"), - S1("2420", "0430", "0000FF01"), - S1("2C20", "0430", "01000000"), - S1("4020", "0430", "FF030000"), - S1("4420", "0430", "E6030000"), - S1("4820", "0430", "E7030000"), - S1("4C20", "0430", "E8030000"), - S1("5020", "0430", "00025802"), - S1("5420", "0430", "00E20100"), - S1("0021", "0430", "00000000"), - S1("0421", "0430", "01000000"), - S1("0821", "0430", "01000000"), - S1("0C21", "0430", "01000000"), - S1("1021", "0430", "01000000"), - S1("1421", "0430", "01000000"), - S1("1821", "0430", "01000000"), - S1("1C21", "0430", "1F000000"), - S1("2021", "0430", "01000000"), - S1("4021", "0430", "00000000"), - S1("4421", "0430", "01000000"), - S1("4821", "0430", "01000000"), - S1("4C21", "0430", "01000000"), - S1("5021", "0430", "01000000"), - S1("5421", "0430", "01000000"), - S1("5821", "0430", "01000000"), - S1("5C21", "0430", "1F000000"), - S1("6021", "0430", "01000000"), - S1("8021", "0430", "00000000"), - S1("8421", "0430", "01000000"), - S1("8821", "0430", "01000000"), - S1("8C21", "0430", "01000000"), - S1("9021", "0430", "01000000"), - S1("9421", "0430", "01000000"), - S1("9821", "0430", "01000000"), - S1("9C21", "0430", "1F000000"), - S1("A021", "0430", "01000000"), - S1("C021", "0430", "00000000"), - S1("C421", "0430", "01000000"), - S1("C821", "0430", "01000000"), - S1("CC21", "0430", "01000000"), - S1("D021", "0430", "01000000"), - S1("D421", "0430", "01000000"), - S1("D821", "0430", "01000000"), - S1("DC21", "0430", "1F000000"), - S1("E021", "0430", "01000000"), - S1("A020", "0430", "EFE10000"), - S1("A420", "0430", "00000000"), - vfs301_02D0_BLOB1, - vfs301_02D0_ALIGNED_BLOB, + S1 ("0420", "0430", "00000000"), + S1 ("1820", "0430", "01807800"), + S1 ("2020", "0430", "08008000"), + S1 ("2420", "0430", "0000FF01"), + S1 ("2C20", "0430", "01000000"), + S1 ("4020", "0430", "FF030000"), + S1 ("4420", "0430", "E6030000"), + S1 ("4820", "0430", "E7030000"), + S1 ("4C20", "0430", "E8030000"), + S1 ("5020", "0430", "00025802"), + S1 ("5420", "0430", "00E20100"), + S1 ("0021", "0430", "00000000"), + S1 ("0421", "0430", "01000000"), + S1 ("0821", "0430", "01000000"), + S1 ("0C21", "0430", "01000000"), + S1 ("1021", "0430", "01000000"), + S1 ("1421", "0430", "01000000"), + S1 ("1821", "0430", "01000000"), + S1 ("1C21", "0430", "1F000000"), + S1 ("2021", "0430", "01000000"), + S1 ("4021", "0430", "00000000"), + S1 ("4421", "0430", "01000000"), + S1 ("4821", "0430", "01000000"), + S1 ("4C21", "0430", "01000000"), + S1 ("5021", "0430", "01000000"), + S1 ("5421", "0430", "01000000"), + S1 ("5821", "0430", "01000000"), + S1 ("5C21", "0430", "1F000000"), + S1 ("6021", "0430", "01000000"), + S1 ("8021", "0430", "00000000"), + S1 ("8421", "0430", "01000000"), + S1 ("8821", "0430", "01000000"), + S1 ("8C21", "0430", "01000000"), + S1 ("9021", "0430", "01000000"), + S1 ("9421", "0430", "01000000"), + S1 ("9821", "0430", "01000000"), + S1 ("9C21", "0430", "1F000000"), + S1 ("A021", "0430", "01000000"), + S1 ("C021", "0430", "00000000"), + S1 ("C421", "0430", "01000000"), + S1 ("C821", "0430", "01000000"), + S1 ("CC21", "0430", "01000000"), + S1 ("D021", "0430", "01000000"), + S1 ("D421", "0430", "01000000"), + S1 ("D821", "0430", "01000000"), + S1 ("DC21", "0430", "1F000000"), + S1 ("E021", "0430", "01000000"), + S1 ("A020", "0430", "EFE10000"), + S1 ("A420", "0430", "00000000"), + vfs301_02D0_BLOB1, + vfs301_02D0_ALIGNED_BLOB, - PACKET("0C00", "0100", "00"), - PACKET("0D00", "E800", - "C0000000080000000200000000000000" - "00000050D52200180000009CCE156100" - "0000002003000000" - "0C00003800080000FF00FFFF" - "0C00003800090000FF00FFFF" - "0C00003800020000FF00FFFF" - "0C00003800030000FF00FFFF" - "0C00003800040000FF00FFFF" - "0C00003800050000FF00FFFF" - "0C00003800060000FF00FFFF" - "0C00003800070000FF00FFFF" - "1000003800040000FF00FFFF" - "1000003800050000FF00FFFF" - "1000003800060000FF00FFFF" - "1000003800070000FF00FFFF" - "1000003800080000FF00FFFF" - "1000003800090000FF00FFFF" - "10000038000A0000FF00FFFF" - "10000038000B0000FF00FFFF"), - PACKET("0E00", "E000", - "000100010101011F010000000000FF01" - "000101010101011F010000000000FF01" - "000102010101011F010000000000FF01" - "000104010101011F010000000000FF01" - "000108010101011F010000000000FF01" - "000110010101011F010000000000FF01" - "000110010201011F010000000000FF01" - "000110010401011F010000000000FF01" - "000110010801011F010000000000FF01" - "000110011001011F010000000000FF01" - "000110011001021F010000000000FF01" - "000110011001041F010000000000FF01" - "000110011001081F010000000000FF01" - "000110011001101F010000000000FF01" - "0F000100021000010001110002000800" ), - PACKET("1200", "0100", "0E"), + PACKET ("0C00", "0100", "00"), + PACKET ("0D00", "E800", + "C0000000080000000200000000000000" + "00000050D52200180000009CCE156100" + "0000002003000000" + "0C00003800080000FF00FFFF" + "0C00003800090000FF00FFFF" + "0C00003800020000FF00FFFF" + "0C00003800030000FF00FFFF" + "0C00003800040000FF00FFFF" + "0C00003800050000FF00FFFF" + "0C00003800060000FF00FFFF" + "0C00003800070000FF00FFFF" + "1000003800040000FF00FFFF" + "1000003800050000FF00FFFF" + "1000003800060000FF00FFFF" + "1000003800070000FF00FFFF" + "1000003800080000FF00FFFF" + "1000003800090000FF00FFFF" + "10000038000A0000FF00FFFF" + "10000038000B0000FF00FFFF"), + PACKET ("0E00", "E000", + "000100010101011F010000000000FF01" + "000101010101011F010000000000FF01" + "000102010101011F010000000000FF01" + "000104010101011F010000000000FF01" + "000108010101011F010000000000FF01" + "000110010101011F010000000000FF01" + "000110010201011F010000000000FF01" + "000110010401011F010000000000FF01" + "000110010801011F010000000000FF01" + "000110011001011F010000000000FF01" + "000110011001021F010000000000FF01" + "000110011001041F010000000000FF01" + "000110011001081F010000000000FF01" + "000110011001101F010000000000FF01" + "0F000100021000010001110002000800" ), + PACKET ("1200", "0100", "0E"), - TERM(), + TERM (), - NULL + NULL }; const char *vfs301_02D0_02[] = { - "02D0000001", + "02D0000001", - S1("0420", "0430", "00000000"), - S1("1820", "0430", "01806300"), - S1("2020", "0430", "08008000"), - S1("2420", "0430", "0000FF01"), - S1("2C20", "0430", "01000000"), - S1("4020", "0430", "FF030000"), - S1("4420", "0430", "E6030000"), - S1("4820", "0430", "E7030000"), - S1("4C20", "0430", "E8030000"), - S1("5020", "0430", "00025802"), - S1("5420", "0430", "008E0100"), - S1("0021", "0430", "00000000"), - S1("0421", "0430", "00000000"), - S1("0821", "0430", "00000000"), - S1("0C21", "0430", "00000000"), - S1("1021", "0430", "00000000"), - S1("1421", "0430", "00000000"), - S1("1821", "0430", "00000000"), - S1("1C21", "0430", "1F000000"), - S1("2021", "0430", "01000000"), - S1("4021", "0430", "00000000"), - S1("4421", "0430", "00000000"), - S1("4821", "0430", "00000000"), - S1("4C21", "0430", "00000000"), - S1("5021", "0430", "00000000"), - S1("5421", "0430", "00000000"), - S1("5821", "0430", "00000000"), - S1("5C21", "0430", "1F000000"), - S1("6021", "0430", "01000000"), - S1("8021", "0430", "00000000"), - S1("8421", "0430", "00000000"), - S1("8821", "0430", "00000000"), - S1("8C21", "0430", "00000000"), - S1("9021", "0430", "00000000"), - S1("9421", "0430", "00000000"), - S1("9821", "0430", "00000000"), - S1("9C21", "0430", "1F000000"), - S1("A021", "0430", "01000000"), - S1("C021", "0430", "00000000"), - S1("C421", "0430", "00000000"), - S1("C821", "0430", "00000000"), - S1("CC21", "0430", "00000000"), - S1("D021", "0430", "00000000"), - S1("D421", "0430", "00000000"), - S1("D821", "0430", "00000000"), - S1("DC21", "0430", "1F000000"), - S1("E021", "0430", "01000000"), - S1("A020", "0430", "EFE10000"), - S1("A420", "0430", "00400000"), - vfs301_02D0_BLOB1, - vfs301_02D0_ALIGNED_BLOB, + S1 ("0420", "0430", "00000000"), + S1 ("1820", "0430", "01806300"), + S1 ("2020", "0430", "08008000"), + S1 ("2420", "0430", "0000FF01"), + S1 ("2C20", "0430", "01000000"), + S1 ("4020", "0430", "FF030000"), + S1 ("4420", "0430", "E6030000"), + S1 ("4820", "0430", "E7030000"), + S1 ("4C20", "0430", "E8030000"), + S1 ("5020", "0430", "00025802"), + S1 ("5420", "0430", "008E0100"), + S1 ("0021", "0430", "00000000"), + S1 ("0421", "0430", "00000000"), + S1 ("0821", "0430", "00000000"), + S1 ("0C21", "0430", "00000000"), + S1 ("1021", "0430", "00000000"), + S1 ("1421", "0430", "00000000"), + S1 ("1821", "0430", "00000000"), + S1 ("1C21", "0430", "1F000000"), + S1 ("2021", "0430", "01000000"), + S1 ("4021", "0430", "00000000"), + S1 ("4421", "0430", "00000000"), + S1 ("4821", "0430", "00000000"), + S1 ("4C21", "0430", "00000000"), + S1 ("5021", "0430", "00000000"), + S1 ("5421", "0430", "00000000"), + S1 ("5821", "0430", "00000000"), + S1 ("5C21", "0430", "1F000000"), + S1 ("6021", "0430", "01000000"), + S1 ("8021", "0430", "00000000"), + S1 ("8421", "0430", "00000000"), + S1 ("8821", "0430", "00000000"), + S1 ("8C21", "0430", "00000000"), + S1 ("9021", "0430", "00000000"), + S1 ("9421", "0430", "00000000"), + S1 ("9821", "0430", "00000000"), + S1 ("9C21", "0430", "1F000000"), + S1 ("A021", "0430", "01000000"), + S1 ("C021", "0430", "00000000"), + S1 ("C421", "0430", "00000000"), + S1 ("C821", "0430", "00000000"), + S1 ("CC21", "0430", "00000000"), + S1 ("D021", "0430", "00000000"), + S1 ("D421", "0430", "00000000"), + S1 ("D821", "0430", "00000000"), + S1 ("DC21", "0430", "1F000000"), + S1 ("E021", "0430", "01000000"), + S1 ("A020", "0430", "EFE10000"), + S1 ("A420", "0430", "00400000"), + vfs301_02D0_BLOB1, + vfs301_02D0_ALIGNED_BLOB, - PACKET("0C00", "0100", "03"), - PACKET("0D00", "2800", "C82004300000000001000000FF00000000FFFFFF01000000C8200430000000000000003001000000"), - PACKET("0E00", "1000", "000101010100011F0800000000000001"), - PACKET("0F00", "0100", "01"), - PACKET("1000", "0100", "01"), - PACKET("1100", "0200", "0001"), - vfs301_02D0_BLOB4, + PACKET ("0C00", "0100", "03"), + PACKET ("0D00", "2800", "C82004300000000001000000FF00000000FFFFFF01000000C8200430000000000000003001000000"), + PACKET ("0E00", "1000", "000101010100011F0800000000000001"), + PACKET ("0F00", "0100", "01"), + PACKET ("1000", "0100", "01"), + PACKET ("1100", "0200", "0001"), + vfs301_02D0_BLOB4, - TERM(), + TERM (), - NULL + NULL }; const char *vfs301_02D0_03[] = { - "02D0006000", + "02D0006000", - S1("0420", "0430", "00000000"), - S1("1820", "0430", "01806300"), - S1("2020", "0430", "08008000"), - S1("2420", "0430", "0000FF01"), - S1("2C20", "0430", "01000000"), - S1("4020", "0430", "FF030000"), - S1("4420", "0430", "E6030000"), - S1("4820", "0430", "E7030000"), - S1("4C20", "0430", "E8030000"), - S1("5020", "0430", "00025802"), - S1("5420", "0430", "008E0100"), - S1("0021", "0430", "00000000"), - S1("0421", "0430", "01000000"), - S1("0821", "0430", "01000000"), - S1("0C21", "0430", "01000000"), - S1("1021", "0430", "01000000"), - S1("1421", "0430", "01000000"), - S1("1821", "0430", "01000000"), - S1("1C21", "0430", "1F000000"), - S1("2021", "0430", "05000000"), - S1("4021", "0430", "00000000"), - S1("4421", "0430", "01000000"), - S1("4821", "0430", "01000000"), - S1("4C21", "0430", "01000000"), - S1("5021", "0430", "01000000"), - S1("5421", "0430", "01000000"), - S1("5821", "0430", "01000000"), - S1("5C21", "0430", "1F000000"), - S1("6021", "0430", "05000000"), - S1("8021", "0430", "00000000"), - S1("8421", "0430", "01000000"), - S1("8821", "0430", "01000000"), - S1("8C21", "0430", "01000000"), - S1("9021", "0430", "01000000"), - S1("9421", "0430", "01000000"), - S1("9821", "0430", "01000000"), - S1("9C21", "0430", "1F000000"), - S1("A021", "0430", "05000000"), - S1("C021", "0430", "00000000"), - S1("C421", "0430", "01000000"), - S1("C821", "0430", "01000000"), - S1("CC21", "0430", "01000000"), - S1("D021", "0430", "01000000"), - S1("D421", "0430", "01000000"), - S1("D821", "0430", "01000000"), - S1("DC21", "0430", "1F000000"), - S1("E021", "0430", "05000000"), - S1("A020", "0430", "EFE10000"), - S1("A420", "0430", "00000000"), - vfs301_02D0_BLOB1, - vfs301_02D0_ALIGNED_BLOB, + S1 ("0420", "0430", "00000000"), + S1 ("1820", "0430", "01806300"), + S1 ("2020", "0430", "08008000"), + S1 ("2420", "0430", "0000FF01"), + S1 ("2C20", "0430", "01000000"), + S1 ("4020", "0430", "FF030000"), + S1 ("4420", "0430", "E6030000"), + S1 ("4820", "0430", "E7030000"), + S1 ("4C20", "0430", "E8030000"), + S1 ("5020", "0430", "00025802"), + S1 ("5420", "0430", "008E0100"), + S1 ("0021", "0430", "00000000"), + S1 ("0421", "0430", "01000000"), + S1 ("0821", "0430", "01000000"), + S1 ("0C21", "0430", "01000000"), + S1 ("1021", "0430", "01000000"), + S1 ("1421", "0430", "01000000"), + S1 ("1821", "0430", "01000000"), + S1 ("1C21", "0430", "1F000000"), + S1 ("2021", "0430", "05000000"), + S1 ("4021", "0430", "00000000"), + S1 ("4421", "0430", "01000000"), + S1 ("4821", "0430", "01000000"), + S1 ("4C21", "0430", "01000000"), + S1 ("5021", "0430", "01000000"), + S1 ("5421", "0430", "01000000"), + S1 ("5821", "0430", "01000000"), + S1 ("5C21", "0430", "1F000000"), + S1 ("6021", "0430", "05000000"), + S1 ("8021", "0430", "00000000"), + S1 ("8421", "0430", "01000000"), + S1 ("8821", "0430", "01000000"), + S1 ("8C21", "0430", "01000000"), + S1 ("9021", "0430", "01000000"), + S1 ("9421", "0430", "01000000"), + S1 ("9821", "0430", "01000000"), + S1 ("9C21", "0430", "1F000000"), + S1 ("A021", "0430", "05000000"), + S1 ("C021", "0430", "00000000"), + S1 ("C421", "0430", "01000000"), + S1 ("C821", "0430", "01000000"), + S1 ("CC21", "0430", "01000000"), + S1 ("D021", "0430", "01000000"), + S1 ("D421", "0430", "01000000"), + S1 ("D821", "0430", "01000000"), + S1 ("DC21", "0430", "1F000000"), + S1 ("E021", "0430", "05000000"), + S1 ("A020", "0430", "EFE10000"), + S1 ("A420", "0430", "00000000"), + vfs301_02D0_BLOB1, + vfs301_02D0_ALIGNED_BLOB, - PACKET("0C00", "0100", "02"), - PACKET("0D00", "2800", "1400003800006E000000010000008F00FFFF00FF01000000000002000000010000000F0002000000"), - PACKET("0E00", "1000", "00000000000000000500000000000001"), - PACKET("0F00", "0100", "01"), - PACKET("1000", "0100", "02") - PACKET("1100", "0200", "6000"), - vfs301_02D0_BLOB4, - S1("C820", "0430", "07000000"), + PACKET ("0C00", "0100", "02"), + PACKET ("0D00", "2800", "1400003800006E000000010000008F00FFFF00FF01000000000002000000010000000F0002000000"), + PACKET ("0E00", "1000", "00000000000000000500000000000001"), + PACKET ("0F00", "0100", "01"), + PACKET ("1000", "0100", "02") + PACKET ("1100", "0200", "6000"), + vfs301_02D0_BLOB4, + S1 ("C820", "0430", "07000000"), - TERM(), + TERM (), - NULL + NULL }; const char *vfs301_02D0_04[] = { - "02D0001C00", + "02D0001C00", - S1("0420", "0430", "00000000"), - S1("1820", "0430", "01806300"), - S1("2020", "0430", "08008000"), - S1("2420", "0430", "0000FF01"), - S1("2C20", "0430", "01000000"), - S1("4020", "0430", "FF030000"), - S1("4420", "0430", "E7030000"), - S1("4820", "0430", "FF030000"), - S1("4C20", "0430", "FF030000"), - S1("5020", "0430", "00025802"), - S1("5420", "0430", "008E0100"), - S1("0021", "0430", "30000000"), - S1("0421", "0430", "01000000"), - S1("0821", "0430", "01000000"), - S1("0C21", "0430", "01000000"), - S1("1021", "0430", "01000000"), - S1("1421", "0430", "01000000"), - S1("1821", "0430", "01000000"), - S1("1C21", "0430", "1F000000"), - S1("2021", "0430", "00000000"), - S1("4021", "0430", "30000000"), - S1("4421", "0430", "01000000"), - S1("4821", "0430", "01000000"), - S1("4C21", "0430", "01000000"), - S1("5021", "0430", "01000000"), - S1("5421", "0430", "01000000"), - S1("5821", "0430", "01000000"), - S1("5C21", "0430", "1F000000"), - S1("6021", "0430", "00000000"), - S1("8021", "0430", "30000000"), - S1("8421", "0430", "01000000"), - S1("8821", "0430", "01000000"), - S1("8C21", "0430", "01000000"), - S1("9021", "0430", "01000000"), - S1("9421", "0430", "01000000"), - S1("9821", "0430", "01000000"), - S1("9C21", "0430", "1F000000"), - S1("A021", "0430", "00000000"), - S1("C021", "0430", "30000000"), - S1("C421", "0430", "01000000"), - S1("C821", "0430", "01000000"), - S1("CC21", "0430", "01000000"), - S1("D021", "0430", "01000000"), - S1("D421", "0430", "01000000"), - S1("D821", "0430", "01000000"), - S1("DC21", "0430", "1F000000"), - S1("E021", "0430", "00000000"), - S1("A020", "0430", "EFE10000"), - S1("A420", "0430", "00000000"), - vfs301_02D0_BLOB1, + S1 ("0420", "0430", "00000000"), + S1 ("1820", "0430", "01806300"), + S1 ("2020", "0430", "08008000"), + S1 ("2420", "0430", "0000FF01"), + S1 ("2C20", "0430", "01000000"), + S1 ("4020", "0430", "FF030000"), + S1 ("4420", "0430", "E7030000"), + S1 ("4820", "0430", "FF030000"), + S1 ("4C20", "0430", "FF030000"), + S1 ("5020", "0430", "00025802"), + S1 ("5420", "0430", "008E0100"), + S1 ("0021", "0430", "30000000"), + S1 ("0421", "0430", "01000000"), + S1 ("0821", "0430", "01000000"), + S1 ("0C21", "0430", "01000000"), + S1 ("1021", "0430", "01000000"), + S1 ("1421", "0430", "01000000"), + S1 ("1821", "0430", "01000000"), + S1 ("1C21", "0430", "1F000000"), + S1 ("2021", "0430", "00000000"), + S1 ("4021", "0430", "30000000"), + S1 ("4421", "0430", "01000000"), + S1 ("4821", "0430", "01000000"), + S1 ("4C21", "0430", "01000000"), + S1 ("5021", "0430", "01000000"), + S1 ("5421", "0430", "01000000"), + S1 ("5821", "0430", "01000000"), + S1 ("5C21", "0430", "1F000000"), + S1 ("6021", "0430", "00000000"), + S1 ("8021", "0430", "30000000"), + S1 ("8421", "0430", "01000000"), + S1 ("8821", "0430", "01000000"), + S1 ("8C21", "0430", "01000000"), + S1 ("9021", "0430", "01000000"), + S1 ("9421", "0430", "01000000"), + S1 ("9821", "0430", "01000000"), + S1 ("9C21", "0430", "1F000000"), + S1 ("A021", "0430", "00000000"), + S1 ("C021", "0430", "30000000"), + S1 ("C421", "0430", "01000000"), + S1 ("C821", "0430", "01000000"), + S1 ("CC21", "0430", "01000000"), + S1 ("D021", "0430", "01000000"), + S1 ("D421", "0430", "01000000"), + S1 ("D821", "0430", "01000000"), + S1 ("DC21", "0430", "1F000000"), + S1 ("E021", "0430", "00000000"), + S1 ("A020", "0430", "EFE10000"), + S1 ("A420", "0430", "00000000"), + vfs301_02D0_BLOB1, - /* TODO: looks like that removing this whole packet doesn't cause - * 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" - 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() - 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() - 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() - 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() - Z8() Z8() Z8() Z8() Z8() Z8() Z8() Z8() - ), + /* TODO: looks like that removing this whole packet doesn't cause + * 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" + 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 () + 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 () + 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 () + 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 () + Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () + ), - S3("1003181C"), - S1("0020", "0430", "80000000"), + S3 ("1003181C"), + S1 ("0020", "0430", "80000000"), - PACKET("0C00", "0100", "00"), - PACKET("0D00", "2800", "A02104300100000001000000010000000100000001000000A0210430000000000031003801000000"), - PACKET("0E00", "E000", - "00010001000100000000000000007E00" - "00010101000100000000000000007E00" - "00010101010100000000000000007E00" - "00010101010101000000000000007E00" - "00010201010101000000000000007E00" - "00010401010101000000000000007E00" - "00010801010101000000000000007E00" - "00011001010101000000000000007E00" - "00011001020101000000000000007E00" - "00011001040101000000000000007E00" - "00011001080101000000000000007E00" - "00011001100102000000000000007E00" - "00011001100104000000000000007E00" - "00011001100108000000000000007E00"), - PACKET("0F00", "0100", "01"), - PACKET("1000", "0100", "02"), - PACKET("1100", "0200", "0200"), - PACKET("1200", "0100", "0E"), - S2("0C20FF00FFFF0000000000030000"), - S2("1020FF00FFFF0000000000070000"), - S1("0421", "0430", "01000000"), - S1("0821", "0430", "02000000"), - S1("0C21", "0430", "01000000"), - S1("1021", "0430", "01000000"), - S1("1421", "0430", "01000000"), - S1("1821", "0430", "01000000"), - S1("4421", "0430", "01000000"), - S1("4821", "0430", "02000000"), - S1("4C21", "0430", "01000000"), - S1("5021", "0430", "01000000"), - S1("5421", "0430", "01000000"), - S1("5821", "0430", "01000000"), - S1("C820", "0430", "07000000"), - S2("1420FFFF00FF0000000000008800"), + PACKET ("0C00", "0100", "00"), + PACKET ("0D00", "2800", "A02104300100000001000000010000000100000001000000A0210430000000000031003801000000"), + PACKET ("0E00", "E000", + "00010001000100000000000000007E00" + "00010101000100000000000000007E00" + "00010101010100000000000000007E00" + "00010101010101000000000000007E00" + "00010201010101000000000000007E00" + "00010401010101000000000000007E00" + "00010801010101000000000000007E00" + "00011001010101000000000000007E00" + "00011001020101000000000000007E00" + "00011001040101000000000000007E00" + "00011001080101000000000000007E00" + "00011001100102000000000000007E00" + "00011001100104000000000000007E00" + "00011001100108000000000000007E00"), + PACKET ("0F00", "0100", "01"), + PACKET ("1000", "0100", "02"), + PACKET ("1100", "0200", "0200"), + PACKET ("1200", "0100", "0E"), + S2 ("0C20FF00FFFF0000000000030000"), + S2 ("1020FF00FFFF0000000000070000"), + S1 ("0421", "0430", "01000000"), + S1 ("0821", "0430", "02000000"), + S1 ("0C21", "0430", "01000000"), + S1 ("1021", "0430", "01000000"), + S1 ("1421", "0430", "01000000"), + S1 ("1821", "0430", "01000000"), + S1 ("4421", "0430", "01000000"), + S1 ("4821", "0430", "02000000"), + S1 ("4C21", "0430", "01000000"), + S1 ("5021", "0430", "01000000"), + S1 ("5421", "0430", "01000000"), + S1 ("5821", "0430", "01000000"), + S1 ("C820", "0430", "07000000"), + S2 ("1420FFFF00FF0000000000008800"), - TERM(), + TERM (), - NULL + NULL }; /* Sorry had to replace BLOB3 (was a fragment!) */ const char *vfs301_02D0_05[] = { - "02D0002000", + "02D0002000", - S1("0420", "0430", "00000000"), - S1("1820", "0430", "01806300"), - S1("2020", "0430", "08008000"), - S1("2420", "0430", "0000FF01"), - S1("2C20", "0430", "01000000"), - S1("4020", "0430", "FF030000"), - S1("4420", "0430", "E7030000"), - S1("4820", "0430", "FF030000"), - S1("4C20", "0430", "FF030000"), - S1("5020", "0430", "00025802"), - S1("5420", "0430", "008E0100"), - S1("0021", "0430", "30000000"), - S1("0421", "0430", "01000000"), - S1("0821", "0430", "01000000"), - S1("0C21", "0430", "01000000"), - S1("1021", "0430", "00000000"), - S1("1421", "0430", "01000000"), - S1("1821", "0430", "00000000"), - S1("1C21", "0430", "1F000000"), - S1("2021", "0430", "04000000"), - S1("4021", "0430", "30000000"), - S1("4421", "0430", "01000000"), - S1("4821", "0430", "01000000"), - S1("4C21", "0430", "01000000"), - S1("5021", "0430", "00000000"), - S1("5421", "0430", "01000000"), - S1("5821", "0430", "00000000"), - S1("5C21", "0430", "1F000000"), - S1("6021", "0430", "04000000"), - S1("8021", "0430", "30000000"), - S1("8421", "0430", "01000000"), - S1("8821", "0430", "01000000"), - S1("8C21", "0430", "01000000"), - S1("9021", "0430", "00000000"), - S1("9421", "0430", "01000000"), - S1("9821", "0430", "00000000"), - S1("9C21", "0430", "1F000000"), - S1("A021", "0430", "04000000"), - S1("C021", "0430", "30000000"), - S1("C421", "0430", "01000000"), - S1("C821", "0430", "01000000"), - S1("CC21", "0430", "01000000"), - S1("D021", "0430", "00000000"), - S1("D421", "0430", "01000000"), - S1("D821", "0430", "00000000"), - S1("DC21", "0430", "1F000000"), - S1("E021", "0430", "04000000"), - S1("A020", "0430", "EFE10000"), - S1("A420", "0430", "00000000"), - vfs301_02D0_BLOB1, + S1 ("0420", "0430", "00000000"), + S1 ("1820", "0430", "01806300"), + S1 ("2020", "0430", "08008000"), + S1 ("2420", "0430", "0000FF01"), + S1 ("2C20", "0430", "01000000"), + S1 ("4020", "0430", "FF030000"), + S1 ("4420", "0430", "E7030000"), + S1 ("4820", "0430", "FF030000"), + S1 ("4C20", "0430", "FF030000"), + S1 ("5020", "0430", "00025802"), + S1 ("5420", "0430", "008E0100"), + S1 ("0021", "0430", "30000000"), + S1 ("0421", "0430", "01000000"), + S1 ("0821", "0430", "01000000"), + S1 ("0C21", "0430", "01000000"), + S1 ("1021", "0430", "00000000"), + S1 ("1421", "0430", "01000000"), + S1 ("1821", "0430", "00000000"), + S1 ("1C21", "0430", "1F000000"), + S1 ("2021", "0430", "04000000"), + S1 ("4021", "0430", "30000000"), + S1 ("4421", "0430", "01000000"), + S1 ("4821", "0430", "01000000"), + S1 ("4C21", "0430", "01000000"), + S1 ("5021", "0430", "00000000"), + S1 ("5421", "0430", "01000000"), + S1 ("5821", "0430", "00000000"), + S1 ("5C21", "0430", "1F000000"), + S1 ("6021", "0430", "04000000"), + S1 ("8021", "0430", "30000000"), + S1 ("8421", "0430", "01000000"), + S1 ("8821", "0430", "01000000"), + S1 ("8C21", "0430", "01000000"), + S1 ("9021", "0430", "00000000"), + S1 ("9421", "0430", "01000000"), + S1 ("9821", "0430", "00000000"), + S1 ("9C21", "0430", "1F000000"), + S1 ("A021", "0430", "04000000"), + S1 ("C021", "0430", "30000000"), + S1 ("C421", "0430", "01000000"), + S1 ("C821", "0430", "01000000"), + S1 ("CC21", "0430", "01000000"), + S1 ("D021", "0430", "00000000"), + S1 ("D421", "0430", "01000000"), + S1 ("D821", "0430", "00000000"), + S1 ("DC21", "0430", "1F000000"), + S1 ("E021", "0430", "04000000"), + S1 ("A020", "0430", "EFE10000"), + S1 ("A420", "0430", "00000000"), + vfs301_02D0_BLOB1, - /* TODO: looks like that removing this whole packet doesn't cause - * 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" - 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() - 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() - 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() - 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() - Z8() Z8() Z8() Z8() Z8() Z8() Z8() Z8() ), + /* TODO: looks like that removing this whole packet doesn't cause + * 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" + 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 () + 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 () + 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 () + 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 () + Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 ()), - S3("1003181C"), - S1("0020", "0430", "80000000") + S3 ("1003181C"), + S1 ("0020", "0430", "80000000") - PACKET("0C00", "0100", "01"), - PACKET("0D00", "2800", "A021043000000000010000000F00000000FFFFFF01000000A0210430000000000000003001000000"), - PACKET("0E00", "1000", "00000000000000000000000000000000"), - PACKET("0F00", "0100", "01"), - PACKET("1000", "0100", "02"), - PACKET("1100", "0200", "2000"), - vfs301_02D0_BLOB4, - S1("C820", "0430", "07000000"), - S2("1420FFFF00FF0000000000008800"), - S1("8421", "0430", "01000000"), - S1("8821", "0430", "01000000"), - S1("8C21", "0430", "01000000"), - S1("9021", "0430", "01000000"), - S1("9421", "0430", "01000000"), - S1("9821", "0430", "01000000"), + PACKET ("0C00", "0100", "01"), + PACKET ("0D00", "2800", "A021043000000000010000000F00000000FFFFFF01000000A0210430000000000000003001000000"), + PACKET ("0E00", "1000", "00000000000000000000000000000000"), + PACKET ("0F00", "0100", "01"), + PACKET ("1000", "0100", "02"), + PACKET ("1100", "0200", "2000"), + vfs301_02D0_BLOB4, + S1 ("C820", "0430", "07000000"), + S2 ("1420FFFF00FF0000000000008800"), + S1 ("8421", "0430", "01000000"), + S1 ("8821", "0430", "01000000"), + S1 ("8C21", "0430", "01000000"), + S1 ("9021", "0430", "01000000"), + S1 ("9421", "0430", "01000000"), + S1 ("9821", "0430", "01000000"), - TERM(), + TERM (), - NULL + NULL }; const char *vfs301_02D0_06[] = { - "02D0002000", + "02D0002000", - S1("0420", "0430", "00000000"), - S1("1820", "0430", "01806300"), - S1("2020", "0430", "08008000"), - S1("2420", "0430", "0000FF01"), - S1("2C20", "0430", "01000000"), - S1("4020", "0430", "FF030000"), - S1("4420", "0430", "E6030000"), - S1("4820", "0430", "E7030000"), - S1("4C20", "0430", "E8030000"), - S1("5020", "0430", "00025802"), - S1("5420", "0430", "008E0100"), - S1("0021", "0430", "00000000"), - S1("0421", "0430", "01000000"), - S1("0821", "0430", "01000000"), - S1("0C21", "0430", "01000000"), - S1("1021", "0430", "01000000"), - S1("1421", "0430", "01000000"), - S1("1821", "0430", "01000000"), - S1("1C21", "0430", "1F000000"), - S1("2021", "0430", "08000000"), - S1("4021", "0430", "00000000"), - S1("4421", "0430", "01000000"), - S1("4821", "0430", "01000000"), - S1("4C21", "0430", "01000000"), - S1("5021", "0430", "01000000"), - S1("5421", "0430", "01000000"), - S1("5821", "0430", "01000000"), - S1("5C21", "0430", "1F000000"), - S1("6021", "0430", "08000000"), - S1("8021", "0430", "00000000"), - S1("8421", "0430", "01000000"), - S1("8821", "0430", "01000000"), - S1("8C21", "0430", "01000000"), - S1("9021", "0430", "01000000"), - S1("9421", "0430", "01000000"), - S1("9821", "0430", "01000000"), - S1("9C21", "0430", "1F000000"), - S1("A021", "0430", "08000000"), - S1("C021", "0430", "00000000"), - S1("C421", "0430", "01000000"), - S1("C821", "0430", "01000000"), - S1("CC21", "0430", "01000000"), - S1("D021", "0430", "01000000"), - S1("D421", "0430", "01000000"), - S1("D821", "0430", "01000000"), - S1("DC21", "0430", "1F000000"), - S1("E021", "0430", "08000000"), - S1("A020", "0430", "EFE10000"), - S1("A420", "0430", "00000000"), - vfs301_02D0_BLOB1, - vfs301_02D0_ALIGNED_BLOB, + S1 ("0420", "0430", "00000000"), + S1 ("1820", "0430", "01806300"), + S1 ("2020", "0430", "08008000"), + S1 ("2420", "0430", "0000FF01"), + S1 ("2C20", "0430", "01000000"), + S1 ("4020", "0430", "FF030000"), + S1 ("4420", "0430", "E6030000"), + S1 ("4820", "0430", "E7030000"), + S1 ("4C20", "0430", "E8030000"), + S1 ("5020", "0430", "00025802"), + S1 ("5420", "0430", "008E0100"), + S1 ("0021", "0430", "00000000"), + S1 ("0421", "0430", "01000000"), + S1 ("0821", "0430", "01000000"), + S1 ("0C21", "0430", "01000000"), + S1 ("1021", "0430", "01000000"), + S1 ("1421", "0430", "01000000"), + S1 ("1821", "0430", "01000000"), + S1 ("1C21", "0430", "1F000000"), + S1 ("2021", "0430", "08000000"), + S1 ("4021", "0430", "00000000"), + S1 ("4421", "0430", "01000000"), + S1 ("4821", "0430", "01000000"), + S1 ("4C21", "0430", "01000000"), + S1 ("5021", "0430", "01000000"), + S1 ("5421", "0430", "01000000"), + S1 ("5821", "0430", "01000000"), + S1 ("5C21", "0430", "1F000000"), + S1 ("6021", "0430", "08000000"), + S1 ("8021", "0430", "00000000"), + S1 ("8421", "0430", "01000000"), + S1 ("8821", "0430", "01000000"), + S1 ("8C21", "0430", "01000000"), + S1 ("9021", "0430", "01000000"), + S1 ("9421", "0430", "01000000"), + S1 ("9821", "0430", "01000000"), + S1 ("9C21", "0430", "1F000000"), + S1 ("A021", "0430", "08000000"), + S1 ("C021", "0430", "00000000"), + S1 ("C421", "0430", "01000000"), + S1 ("C821", "0430", "01000000"), + S1 ("CC21", "0430", "01000000"), + S1 ("D021", "0430", "01000000"), + S1 ("D421", "0430", "01000000"), + S1 ("D821", "0430", "01000000"), + S1 ("DC21", "0430", "1F000000"), + S1 ("E021", "0430", "08000000"), + S1 ("A020", "0430", "EFE10000"), + S1 ("A420", "0430", "00000000"), + vfs301_02D0_BLOB1, + vfs301_02D0_ALIGNED_BLOB, - PACKET("0C00", "0100", "01"), - PACKET("0D00", "2800", "2021043000000000010000000F00000000FFFFFF0100000020210430000000000000003001000000"), - PACKET("0E00", "1000", "00000000000000000000000000000001"), - PACKET("0F00", "0100", "01"), - PACKET("1000", "0100", "02"), - PACKET("1100", "0200", "2000"), - vfs301_02D0_BLOB4, - S1("C820", "0430", "07000000"), - S2("1420FFFF00FF0000000000008800"), - S1("8421", "0430", "01000000"), - S1("8821", "0430", "01000000"), - S1("8C21", "0430", "01000000"), - S1("9021", "0430", "01000000"), - S1("9421", "0430", "01000000"), - S1("9821", "0430", "01000000"), - S1("A021", "0430", "00000000"), + PACKET ("0C00", "0100", "01"), + PACKET ("0D00", "2800", "2021043000000000010000000F00000000FFFFFF0100000020210430000000000000003001000000"), + PACKET ("0E00", "1000", "00000000000000000000000000000001"), + PACKET ("0F00", "0100", "01"), + PACKET ("1000", "0100", "02"), + PACKET ("1100", "0200", "2000"), + vfs301_02D0_BLOB4, + S1 ("C820", "0430", "07000000"), + S2 ("1420FFFF00FF0000000000008800"), + S1 ("8421", "0430", "01000000"), + S1 ("8821", "0430", "01000000"), + S1 ("8C21", "0430", "01000000"), + S1 ("9021", "0430", "01000000"), + S1 ("9421", "0430", "01000000"), + S1 ("9821", "0430", "01000000"), + S1 ("A021", "0430", "00000000"), - TERM(), + TERM (), - NULL + NULL }; const char *vfs301_02D0_07[] = { - "02D0000400" - S3("1003181C"), - PACKET("0C00", "0100", "04"), - PACKET("0D00", "2800", "28A0003803000000020000003B000000C0FFFFFF0100000028A00038000000001047004801000000"), - PACKET("1100", "0200", "0400"), - PACKET("1300", "0400", "18000000"), - PACKET("1400", "0400", "1E000000"), + "02D0000400" + S3 ("1003181C"), + PACKET ("0C00", "0100", "04"), + PACKET ("0D00", "2800", "28A0003803000000020000003B000000C0FFFFFF0100000028A00038000000001047004801000000"), + PACKET ("1100", "0200", "0400"), + PACKET ("1300", "0400", "18000000"), + PACKET ("1400", "0400", "1E000000"), - S1("A020", "0430", "EFE10000"), - S1("08A0", "0038", "78000200"), - S1("10A0", "0038", "E3186800"), - S1("14A0", "0038", "E3186800"), - S1("18A0", "0038", "E3186800"), - S1("1CA0", "0038", "E3186800"), - S1("20A0", "0038", "E3186800"), - S1("24A0", "0038", "0CFA8000"), - S1("28A0", "0038", "00000800"), - S1("04A0", "0038", "FFFFFFFF"), + S1 ("A020", "0430", "EFE10000"), + S1 ("08A0", "0038", "78000200"), + S1 ("10A0", "0038", "E3186800"), + S1 ("14A0", "0038", "E3186800"), + S1 ("18A0", "0038", "E3186800"), + S1 ("1CA0", "0038", "E3186800"), + S1 ("20A0", "0038", "E3186800"), + S1 ("24A0", "0038", "0CFA8000"), + S1 ("28A0", "0038", "00000800"), + S1 ("04A0", "0038", "FFFFFFFF"), - vfs301_0220_BLOB2, + vfs301_0220_BLOB2, - TERM(), + TERM (), - NULL + NULL }; diff --git a/libfprint/drivers/vfs5011.c b/libfprint/drivers/vfs5011.c index c7121f9d..9eddca79 100644 --- a/libfprint/drivers/vfs5011.c +++ b/libfprint/drivers/vfs5011.c @@ -18,446 +18,455 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#define FP_COMPONENT "vfs5011" + #include "drivers_api.h" #include "vfs5011_proto.h" /* =================== sync/async USB transfer sequence ==================== */ enum { - ACTION_SEND, - ACTION_RECEIVE, + ACTION_SEND, + ACTION_RECEIVE, }; -struct usb_action { - int type; - const char *name; - int endpoint; - int size; - unsigned char *data; - int correct_reply_size; +struct usb_action +{ + int type; + const char *name; + int endpoint; + int size; + unsigned char *data; + int correct_reply_size; }; #define SEND(ENDPOINT, COMMAND) \ -{ \ - .type = ACTION_SEND, \ - .endpoint = ENDPOINT, \ - .name = #COMMAND, \ - .size = sizeof(COMMAND), \ - .data = COMMAND \ -}, + { \ + .type = ACTION_SEND, \ + .endpoint = ENDPOINT, \ + .name = #COMMAND, \ + .size = sizeof (COMMAND), \ + .data = COMMAND \ + }, #define RECV(ENDPOINT, SIZE) \ -{ \ - .type = ACTION_RECEIVE, \ - .endpoint = ENDPOINT, \ - .size = SIZE, \ - .data = NULL \ -}, + { \ + .type = ACTION_RECEIVE, \ + .endpoint = ENDPOINT, \ + .size = SIZE, \ + .data = NULL \ + }, #define RECV_CHECK(ENDPOINT, SIZE, EXPECTED) \ -{ \ - .type = ACTION_RECEIVE, \ - .endpoint = ENDPOINT, \ - .size = SIZE, \ - .data = EXPECTED, \ - .correct_reply_size = sizeof(EXPECTED) \ -}, + { \ + .type = ACTION_RECEIVE, \ + .endpoint = ENDPOINT, \ + .size = SIZE, \ + .data = EXPECTED, \ + .correct_reply_size = sizeof (EXPECTED) \ + }, -struct usbexchange_data { - int stepcount; - struct fp_img_dev *device; - struct usb_action *actions; - void *receive_buf; - int timeout; +struct usbexchange_data +{ + int stepcount; + FpImageDevice *device; + struct usb_action *actions; + void *receive_buf; + int timeout; }; -static void start_scan(struct fp_img_dev *dev); +static void start_scan (FpImageDevice *dev); -static void async_send_cb(struct libusb_transfer *transfer) +static void +async_send_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - struct usbexchange_data *data = fpi_ssm_get_user_data(ssm); - struct usb_action *action; + struct usbexchange_data *data = fpi_ssm_get_data (transfer->ssm); + struct usb_action *action; - if (fpi_ssm_get_cur_state(ssm) >= data->stepcount) { - fp_err("Radiation detected!"); - fpi_imgdev_session_error(data->device, -EINVAL); - fpi_ssm_mark_failed(ssm, -EINVAL); - goto out; - } + g_assert (!(fpi_ssm_get_cur_state (transfer->ssm) >= data->stepcount)); - action = &data->actions[fpi_ssm_get_cur_state(ssm)]; - if (action->type != ACTION_SEND) { - fp_err("Radiation detected!"); - fpi_imgdev_session_error(data->device, -EINVAL); - fpi_ssm_mark_failed(ssm, -EINVAL); - goto out; - } + action = &data->actions[fpi_ssm_get_cur_state (transfer->ssm)]; + g_assert (!(action->type != ACTION_SEND)); - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - /* Transfer not completed, return IO error */ - fp_err("transfer not completed, status = %d", transfer->status); - fpi_imgdev_session_error(data->device, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - goto out; - } - if (transfer->length != transfer->actual_length) { - /* Data sended mismatch with expected, return protocol error */ - fp_err("length mismatch, got %d, expected %d", - transfer->actual_length, transfer->length); - fpi_imgdev_session_error(data->device, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - goto out; - } + if (error) + { + /* Transfer not completed, return IO error */ + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } - /* success */ - fpi_ssm_next_state(ssm); - -out: - libusb_free_transfer(transfer); + /* success */ + fpi_ssm_next_state (transfer->ssm); } -static void async_recv_cb(struct libusb_transfer *transfer) +static void +async_recv_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - struct usbexchange_data *data = fpi_ssm_get_user_data(ssm); - struct usb_action *action; + struct usbexchange_data *data = fpi_ssm_get_data (transfer->ssm); + struct usb_action *action; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - /* Transfer not completed, return IO error */ - fp_err("transfer not completed, status = %d", transfer->status); - fpi_imgdev_session_error(data->device, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - goto out; - } + if (error) + { + /* Transfer not completed, return IO error */ + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } - if (fpi_ssm_get_cur_state(ssm) >= data->stepcount) { - fp_err("Radiation detected!"); - fpi_imgdev_session_error(data->device, -EINVAL); - fpi_ssm_mark_failed(ssm, -EINVAL); - goto out; - } + g_assert (!(fpi_ssm_get_cur_state (transfer->ssm) >= data->stepcount)); - action = &data->actions[fpi_ssm_get_cur_state(ssm)]; - if (action->type != ACTION_RECEIVE) { - fp_err("Radiation detected!"); - fpi_imgdev_session_error(data->device, -EINVAL); - fpi_ssm_mark_failed(ssm, -EINVAL); - goto out; - } + action = &data->actions[fpi_ssm_get_cur_state (transfer->ssm)]; + g_assert (!(action->type != ACTION_RECEIVE)); - if (action->data != NULL) { - if (transfer->actual_length != action->correct_reply_size) { - fp_err("Got %d bytes instead of %d", - transfer->actual_length, - action->correct_reply_size); - fpi_imgdev_session_error(data->device, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - goto out; - } - if (memcmp(transfer->buffer, action->data, - action->correct_reply_size) != 0) { - fp_dbg("Wrong reply:"); - fpi_imgdev_session_error(data->device, -EIO); - fpi_ssm_mark_failed(ssm, -EIO); - goto out; - } - } else - fp_dbg("Got %d bytes out of %d", transfer->actual_length, - transfer->length); + if (action->data != NULL) + { + if (transfer->actual_length != action->correct_reply_size) + { + fp_err ("Got %d bytes instead of %d", + (gint) transfer->actual_length, + action->correct_reply_size); + fpi_ssm_mark_failed (transfer->ssm, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL)); + return; + } + if (memcmp (transfer->buffer, action->data, + action->correct_reply_size) != 0) + { + fp_dbg ("Wrong reply:"); + fpi_ssm_mark_failed (transfer->ssm, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL)); + return; + } + } + else + { + fp_dbg ("Got %d bytes out of %d", + (gint) transfer->actual_length, + (gint) transfer->length); + } - fpi_ssm_next_state(ssm); -out: - libusb_free_transfer(transfer); + fpi_ssm_next_state (transfer->ssm); } -static void usbexchange_loop(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +usbexchange_loop (FpiSsm *ssm, FpDevice *_dev) { - struct usbexchange_data *data = user_data; - if (fpi_ssm_get_cur_state(ssm) >= data->stepcount) { - fp_err("Bug detected: state %d out of range, only %d steps", - fpi_ssm_get_cur_state(ssm), data->stepcount); - fpi_imgdev_session_error(data->device, -EINVAL); - fpi_ssm_mark_failed(ssm, -EINVAL); - return; - } + struct usbexchange_data *data = fpi_ssm_get_data (ssm); + struct usb_action *action = &data->actions[fpi_ssm_get_cur_state (ssm)]; + FpiUsbTransfer *transfer; - struct usb_action *action = &data->actions[fpi_ssm_get_cur_state(ssm)]; - struct libusb_transfer *transfer; - int ret = -EINVAL; + g_assert (fpi_ssm_get_cur_state (ssm) < data->stepcount); - switch (action->type) { - case ACTION_SEND: - fp_dbg("Sending %s", action->name); - transfer = fpi_usb_alloc(); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(data->device)), - action->endpoint, action->data, - action->size, async_send_cb, ssm, - data->timeout); - ret = libusb_submit_transfer(transfer); - break; + switch (action->type) + { + case ACTION_SEND: + fp_dbg ("Sending %s", action->name); + transfer = fpi_usb_transfer_new (_dev); + fpi_usb_transfer_fill_bulk_full (transfer, action->endpoint, + action->data, action->size, + NULL); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_submit (transfer, data->timeout, NULL, + async_send_cb, NULL); + fpi_usb_transfer_unref (transfer); + break; - case ACTION_RECEIVE: - fp_dbg("Receiving %d bytes", action->size); - transfer = fpi_usb_alloc(); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(data->device)), - action->endpoint, data->receive_buf, - action->size, async_recv_cb, ssm, - data->timeout); - ret = libusb_submit_transfer(transfer); - break; + case ACTION_RECEIVE: + fp_dbg ("Receiving %d bytes", action->size); + transfer = fpi_usb_transfer_new (_dev); + fpi_usb_transfer_fill_bulk_full (transfer, action->endpoint, + data->receive_buf, + action->size, NULL); + transfer->ssm = ssm; + fpi_usb_transfer_submit (transfer, data->timeout, NULL, + async_recv_cb, NULL); + fpi_usb_transfer_unref (transfer); + break; - default: - fp_err("Bug detected: invalid action %d", action->type); - fpi_imgdev_session_error(data->device, -EINVAL); - fpi_ssm_mark_failed(ssm, -EINVAL); - return; - } - - if (ret != 0) { - fp_err("USB transfer error: %s", strerror(ret)); - fpi_imgdev_session_error(data->device, ret); - fpi_ssm_mark_failed(ssm, ret); - } + default: + fp_err ("Bug detected: invalid action %d", action->type); + fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL)); + return; + } } -static void usb_exchange_async(fpi_ssm *ssm, - struct usbexchange_data *data) +static void +usb_exchange_async (FpiSsm *ssm, + struct usbexchange_data *data) { - fpi_ssm *subsm = fpi_ssm_new(FP_DEV(data->device), - usbexchange_loop, - data->stepcount, - data); - fpi_ssm_start_subsm(ssm, subsm); + FpiSsm *subsm = fpi_ssm_new (FP_DEVICE (data->device), + usbexchange_loop, + data->stepcount); + + fpi_ssm_set_data (subsm, data, NULL); + fpi_ssm_start_subsm (ssm, subsm); } /* ====================== utils ======================= */ /* Calculade squared standand deviation of sum of two lines */ -static int vfs5011_get_deviation2(struct fpi_line_asmbl_ctx *ctx, GSList *row1, GSList *row2) +static int +vfs5011_get_deviation2 (struct fpi_line_asmbl_ctx *ctx, GSList *row1, GSList *row2) { - unsigned char *buf1, *buf2; - int res = 0, mean = 0, i; - const int size = 64; + unsigned char *buf1, *buf2; + int res = 0, mean = 0, i; + const int size = 64; - buf1 = row1->data + 56; - buf2 = row2->data + 168; + buf1 = row1->data + 56; + buf2 = row2->data + 168; - for (i = 0; i < size; i++) - mean += (int)buf1[i] + (int)buf2[i]; + for (i = 0; i < size; i++) + mean += (int) buf1[i] + (int) buf2[i]; - mean /= size; + mean /= size; - for (i = 0; i < size; i++) { - int dev = (int)buf1[i] + (int)buf2[i] - mean; - res += dev*dev; - } + for (i = 0; i < size; i++) + { + int dev = (int) buf1[i] + (int) buf2[i] - mean; + res += dev * dev; + } - return res / size; + return res / size; } -static unsigned char vfs5011_get_pixel(struct fpi_line_asmbl_ctx *ctx, - GSList *row, - unsigned x) +static unsigned char +vfs5011_get_pixel (struct fpi_line_asmbl_ctx *ctx, + GSList *row, + unsigned x) { - unsigned char *data = row->data + 8; + unsigned char *data = row->data + 8; - return data[x]; + return data[x]; } /* ====================== main stuff ======================= */ enum { - CAPTURE_LINES = 256, - MAXLINES = 2000, - MAX_CAPTURE_LINES = 100000, + CAPTURE_LINES = 256, + MAXLINES = 2000, + MAX_CAPTURE_LINES = 100000, }; static struct fpi_line_asmbl_ctx assembling_ctx = { - .line_width = VFS5011_IMAGE_WIDTH, - .max_height = MAXLINES, - .resolution = 10, - .median_filter_size = 25, - .max_search_offset = 30, - .get_deviation = vfs5011_get_deviation2, - .get_pixel = vfs5011_get_pixel, + .line_width = VFS5011_IMAGE_WIDTH, + .max_height = MAXLINES, + .resolution = 10, + .median_filter_size = 25, + .max_search_offset = 30, + .get_deviation = vfs5011_get_deviation2, + .get_pixel = vfs5011_get_pixel, }; -struct vfs5011_data { - unsigned char *total_buffer; - unsigned char *capture_buffer; - unsigned char *row_buffer; - unsigned char *lastline; - GSList *rows; - int lines_captured, lines_recorded, empty_lines; - int max_lines_captured, max_lines_recorded; - int lines_total, lines_total_allocated; - gboolean loop_running; - gboolean deactivating; - struct usbexchange_data init_sequence; - struct libusb_transfer *flying_transfer; -}; - -enum { - DEV_ACTIVATE_REQUEST_FPRINT, - DEV_ACTIVATE_INIT_COMPLETE, - DEV_ACTIVATE_READ_DATA, - DEV_ACTIVATE_DATA_COMPLETE, - DEV_ACTIVATE_PREPARE_NEXT_CAPTURE, - DEV_ACTIVATE_NUM_STATES -}; - -enum { - DEV_OPEN_START, - DEV_OPEN_NUM_STATES -}; - -static void capture_init(struct vfs5011_data *data, int max_captured, - int max_recorded) +struct _FpDeviceVfs5011 { - fp_dbg("capture_init"); - data->lastline = NULL; - data->lines_captured = 0; - data->lines_recorded = 0; - data->empty_lines = 0; - data->lines_total = 0; - data->lines_total_allocated = 0; - data->total_buffer = NULL; - data->max_lines_captured = max_captured; - data->max_lines_recorded = max_recorded; + FpImageDevice parent; + + unsigned char *total_buffer; + unsigned char *capture_buffer; + unsigned char *row_buffer; + unsigned char *lastline; + GSList *rows; + int lines_captured, lines_recorded, empty_lines; + int max_lines_captured, max_lines_recorded; + int lines_total, lines_total_allocated; + gboolean loop_running; + gboolean deactivating; + struct usbexchange_data init_sequence; +}; + +G_DECLARE_FINAL_TYPE (FpDeviceVfs5011, fpi_device_vfs5011, FPI, DEVICE_VFS5011, + FpImageDevice); +G_DEFINE_TYPE (FpDeviceVfs5011, fpi_device_vfs5011, FP_TYPE_IMAGE_DEVICE); + +enum { + DEV_ACTIVATE_REQUEST_FPRINT, + DEV_ACTIVATE_INIT_COMPLETE, + DEV_ACTIVATE_READ_DATA, + DEV_ACTIVATE_DATA_COMPLETE, + DEV_ACTIVATE_PREPARE_NEXT_CAPTURE, + DEV_ACTIVATE_NUM_STATES +}; + +enum { + DEV_OPEN_START, + DEV_OPEN_NUM_STATES +}; + +static void +capture_init (FpDeviceVfs5011 *self, int max_captured, + int max_recorded) +{ + fp_dbg ("capture_init"); + self->lastline = NULL; + self->lines_captured = 0; + self->lines_recorded = 0; + self->empty_lines = 0; + self->lines_total = 0; + self->lines_total_allocated = 0; + self->total_buffer = NULL; + self->max_lines_captured = max_captured; + self->max_lines_recorded = max_recorded; } -static int process_chunk(struct vfs5011_data *data, int transferred) +static int +process_chunk (FpDeviceVfs5011 *self, int transferred) { - enum { - DEVIATION_THRESHOLD = 15*15, - DIFFERENCE_THRESHOLD = 600, - STOP_CHECK_LINES = 50 - }; + enum { + DEVIATION_THRESHOLD = 15 * 15, + DIFFERENCE_THRESHOLD = 600, + STOP_CHECK_LINES = 50 + }; - fp_dbg("process_chunk: got %d bytes", transferred); - int lines_captured = transferred/VFS5011_LINE_SIZE; - int i; + fp_dbg ("process_chunk: got %d bytes", transferred); + int lines_captured = transferred / VFS5011_LINE_SIZE; + int i; - for (i = 0; i < lines_captured; i++) { - unsigned char *linebuf = data->capture_buffer - + i * VFS5011_LINE_SIZE; + for (i = 0; i < lines_captured; i++) + { + unsigned char *linebuf = self->capture_buffer + + i * VFS5011_LINE_SIZE; - if (fpi_std_sq_dev(linebuf + 8, VFS5011_IMAGE_WIDTH) - < DEVIATION_THRESHOLD) { - if (data->lines_captured == 0) - continue; - else - data->empty_lines++; - } else - data->empty_lines = 0; - if (data->empty_lines >= STOP_CHECK_LINES) { - fp_dbg("process_chunk: got %d empty lines, finishing", - data->empty_lines); - return 1; - } + if (fpi_std_sq_dev (linebuf + 8, VFS5011_IMAGE_WIDTH) + < DEVIATION_THRESHOLD) + { + if (self->lines_captured == 0) + continue; + else + self->empty_lines++; + } + else + { + self->empty_lines = 0; + } + if (self->empty_lines >= STOP_CHECK_LINES) + { + fp_dbg ("process_chunk: got %d empty lines, finishing", + self->empty_lines); + return 1; + } - data->lines_captured++; - if (data->lines_captured > data->max_lines_captured) { - fp_dbg("process_chunk: captured %d lines, finishing", - data->lines_captured); - return 1; - } + self->lines_captured++; + if (self->lines_captured > self->max_lines_captured) + { + fp_dbg ("process_chunk: captured %d lines, finishing", + self->lines_captured); + return 1; + } - if ((data->lastline == NULL) - || (fpi_mean_sq_diff_norm( - data->lastline + 8, - linebuf + 8, - VFS5011_IMAGE_WIDTH) >= DIFFERENCE_THRESHOLD)) { - data->lastline = g_malloc(VFS5011_LINE_SIZE); - data->rows = g_slist_prepend(data->rows, data->lastline); - memmove(data->lastline, linebuf, VFS5011_LINE_SIZE); - data->lines_recorded++; - if (data->lines_recorded >= data->max_lines_recorded) { - fp_dbg("process_chunk: recorded %d lines, finishing", - data->lines_recorded); - return 1; - } - } - } - return 0; + if ((self->lastline == NULL) || + (fpi_mean_sq_diff_norm (self->lastline + 8, + linebuf + 8, + VFS5011_IMAGE_WIDTH) >= DIFFERENCE_THRESHOLD)) + { + self->lastline = g_malloc (VFS5011_LINE_SIZE); + self->rows = g_slist_prepend (self->rows, + self->lastline); + memmove (self->lastline, linebuf, VFS5011_LINE_SIZE); + self->lines_recorded++; + if (self->lines_recorded >= self->max_lines_recorded) + { + fp_dbg ("process_chunk: recorded %d lines, finishing", + self->lines_recorded); + return 1; + } + } + } + return 0; } static void -submit_image(fpi_ssm *ssm, - struct vfs5011_data *data, - struct fp_img_dev *dev) +submit_image (FpiSsm *ssm, + FpDeviceVfs5011 *self, + FpImageDevice *dev) { - struct fp_img *img; + FpImage *img; - if (data->lines_recorded == 0) { - /* == FP_ENROLL_RETRY_TOO_SHORT */ - fpi_imgdev_session_error(dev, FP_VERIFY_RETRY_TOO_SHORT); - return; - } + if (self->lines_recorded == 0) + { + /* == FP_ENROLL_RETRY_TOO_SHORT */ + fpi_image_device_retry_scan (dev, FP_DEVICE_RETRY_TOO_SHORT); + return; + } - g_assert (data->rows != NULL); + g_assert (self->rows != NULL); - data->rows = g_slist_reverse(data->rows); + self->rows = g_slist_reverse (self->rows); - img = fpi_assemble_lines(&assembling_ctx, data->rows, data->lines_recorded); + img = fpi_assemble_lines (&assembling_ctx, self->rows, + self->lines_recorded); - g_slist_free_full(data->rows, g_free); - data->rows = NULL; + g_slist_free_full (self->rows, g_free); + self->rows = NULL; - fp_dbg("Image captured, committing"); + fp_dbg ("Image captured, committing"); - fpi_imgdev_image_captured(dev, img); + fpi_image_device_image_captured (dev, img); } -static void chunk_capture_callback(struct libusb_transfer *transfer) +static void +chunk_capture_callback (FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = (fpi_ssm *)transfer->user_data; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct vfs5011_data *data; + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpDeviceVfs5011 *self; - data = FP_INSTANCE_DATA(FP_DEV(dev)); + self = FPI_DEVICE_VFS5011 (dev); - if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) || - (transfer->status == LIBUSB_TRANSFER_TIMED_OUT)) { + if (!error || + g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT)) + { + if (error) + g_error_free (error); - if (transfer->actual_length > 0) - fpi_imgdev_report_finger_status(dev, TRUE); + if (transfer->actual_length > 0) + fpi_image_device_report_finger_status (dev, TRUE); - if (process_chunk(data, transfer->actual_length)) - fpi_ssm_jump_to_state(ssm, DEV_ACTIVATE_DATA_COMPLETE); - else - fpi_ssm_jump_to_state(ssm, DEV_ACTIVATE_READ_DATA); - } else { - if (!data->deactivating) { - fp_err("Failed to capture data"); - fpi_ssm_mark_failed(ssm, -1); - } else { - fpi_ssm_mark_completed(ssm); - } - } - libusb_free_transfer(transfer); - data->flying_transfer = NULL; + if (process_chunk (self, transfer->actual_length)) + fpi_ssm_jump_to_state (transfer->ssm, + DEV_ACTIVATE_DATA_COMPLETE); + else + fpi_ssm_jump_to_state (transfer->ssm, + DEV_ACTIVATE_READ_DATA); + } + else + { + if (!self->deactivating) + { + fp_err ("Failed to capture data"); + fpi_ssm_mark_failed (transfer->ssm, error); + } + else + { + g_error_free (error); + fpi_ssm_mark_completed (transfer->ssm); + } + } } -static int capture_chunk_async(struct vfs5011_data *data, - libusb_device_handle *handle, int nline, - int timeout, fpi_ssm *ssm) +static void +capture_chunk_async (FpDeviceVfs5011 *self, + GUsbDevice *handle, int nline, + int timeout, FpiSsm *ssm) { - fp_dbg("capture_chunk_async: capture %d lines, already have %d", - nline, data->lines_recorded); - enum { - DEVIATION_THRESHOLD = 15*15, - DIFFERENCE_THRESHOLD = 600, - STOP_CHECK_LINES = 50 - }; + FpiUsbTransfer *transfer; - data->flying_transfer = fpi_usb_alloc(); - libusb_fill_bulk_transfer(data->flying_transfer, handle, VFS5011_IN_ENDPOINT_DATA, - data->capture_buffer, - nline * VFS5011_LINE_SIZE, - chunk_capture_callback, ssm, timeout); - return libusb_submit_transfer(data->flying_transfer); + fp_dbg ("capture_chunk_async: capture %d lines, already have %d", + nline, self->lines_recorded); + enum { + DEVIATION_THRESHOLD = 15 * 15, + DIFFERENCE_THRESHOLD = 600, + STOP_CHECK_LINES = 50 + }; + + transfer = fpi_usb_transfer_new (FP_DEVICE (self)); + fpi_usb_transfer_fill_bulk_full (transfer, + VFS5011_IN_ENDPOINT_DATA, + self->capture_buffer, + nline * VFS5011_LINE_SIZE, NULL); + transfer->ssm = ssm; + fpi_usb_transfer_submit (transfer, timeout, fpi_device_get_cancellable (FP_DEVICE (self)), + chunk_capture_callback, NULL); + fpi_usb_transfer_unref (transfer); } /* @@ -466,442 +475,435 @@ static int capture_chunk_async(struct vfs5011_data *data, * image. */ struct usb_action vfs5011_initialization[] = { - SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_01) - RECV(VFS5011_IN_ENDPOINT_CTRL, 64) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_cmd_01) + RECV (VFS5011_IN_ENDPOINT_CTRL, 64) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_19) - RECV(VFS5011_IN_ENDPOINT_CTRL, 64) - RECV(VFS5011_IN_ENDPOINT_CTRL, 64) /* B5C457F9 */ + SEND (VFS5011_OUT_ENDPOINT, vfs5011_cmd_19) + RECV (VFS5011_IN_ENDPOINT_CTRL, 64) + RECV (VFS5011_IN_ENDPOINT_CTRL, 64) /* B5C457F9 */ - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_00) - RECV(VFS5011_IN_ENDPOINT_CTRL, 64) /* 0000FFFFFFFF */ + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_00) + RECV (VFS5011_IN_ENDPOINT_CTRL, 64) /* 0000FFFFFFFF */ - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_01) - RECV(VFS5011_IN_ENDPOINT_CTRL, 64) /* 0000FFFFFFFFFF */ + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_01) + RECV (VFS5011_IN_ENDPOINT_CTRL, 64) /* 0000FFFFFFFFFF */ - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_02) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_02) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_01) - RECV(VFS5011_IN_ENDPOINT_CTRL, 64) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_cmd_01) + RECV (VFS5011_IN_ENDPOINT_CTRL, 64) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_03) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_03) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_04) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - RECV(VFS5011_IN_ENDPOINT_DATA, 256) - RECV(VFS5011_IN_ENDPOINT_DATA, 64) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_04) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + RECV (VFS5011_IN_ENDPOINT_DATA, 256) + RECV (VFS5011_IN_ENDPOINT_DATA, 64) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_05) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_05) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_01) - RECV(VFS5011_IN_ENDPOINT_CTRL, 64) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_cmd_01) + RECV (VFS5011_IN_ENDPOINT_CTRL, 64) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_06) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - RECV(VFS5011_IN_ENDPOINT_DATA, 17216) - RECV(VFS5011_IN_ENDPOINT_DATA, 32) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_06) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + RECV (VFS5011_IN_ENDPOINT_DATA, 17216) + RECV (VFS5011_IN_ENDPOINT_DATA, 32) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_07) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - RECV(VFS5011_IN_ENDPOINT_DATA, 45056) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_07) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + RECV (VFS5011_IN_ENDPOINT_DATA, 45056) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_08) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - RECV(VFS5011_IN_ENDPOINT_DATA, 16896) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_08) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + RECV (VFS5011_IN_ENDPOINT_DATA, 16896) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_09) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - RECV(VFS5011_IN_ENDPOINT_DATA, 4928) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_09) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + RECV (VFS5011_IN_ENDPOINT_DATA, 4928) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_10) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - RECV(VFS5011_IN_ENDPOINT_DATA, 5632) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_10) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + RECV (VFS5011_IN_ENDPOINT_DATA, 5632) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_11) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - RECV(VFS5011_IN_ENDPOINT_DATA, 5632) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_11) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + RECV (VFS5011_IN_ENDPOINT_DATA, 5632) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_12) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - RECV(VFS5011_IN_ENDPOINT_DATA, 3328) - RECV(VFS5011_IN_ENDPOINT_DATA, 64) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_12) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + RECV (VFS5011_IN_ENDPOINT_DATA, 3328) + RECV (VFS5011_IN_ENDPOINT_DATA, 64) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_13) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_13) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_03) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_03) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_14) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - RECV(VFS5011_IN_ENDPOINT_DATA, 4800) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_14) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + RECV (VFS5011_IN_ENDPOINT_DATA, 4800) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_02) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_02) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_27) - RECV(VFS5011_IN_ENDPOINT_CTRL, 64) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_cmd_27) + RECV (VFS5011_IN_ENDPOINT_CTRL, 64) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_15) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_15) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_16) - RECV(VFS5011_IN_ENDPOINT_CTRL, 2368) - RECV(VFS5011_IN_ENDPOINT_CTRL, 64) - RECV(VFS5011_IN_ENDPOINT_DATA, 4800) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_16) + RECV (VFS5011_IN_ENDPOINT_CTRL, 2368) + RECV (VFS5011_IN_ENDPOINT_CTRL, 64) + RECV (VFS5011_IN_ENDPOINT_DATA, 4800) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_17) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_17) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_18) - /* 0000 */ - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_init_18) + /* 0000 */ + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - /* - * Windows driver does this and it works - * But in this driver this call never returns... - * RECV(VFS5011_IN_ENDPOINT_CTRL2, 8) //00D3054000 - */ + /* + * Windows driver does this and it works + * But in this driver this call never returns... + * RECV(VFS5011_IN_ENDPOINT_CTRL2, 8) //00D3054000 + */ }; /* Initiate recording the image */ struct usb_action vfs5011_initiate_capture[] = { - SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_04) - RECV(VFS5011_IN_ENDPOINT_DATA, 64) - RECV(VFS5011_IN_ENDPOINT_DATA, 84032) - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_cmd_04) + RECV (VFS5011_IN_ENDPOINT_DATA, 64) + RECV (VFS5011_IN_ENDPOINT_DATA, 84032) + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A) - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A) + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_prepare_00) - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_prepare_00) + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A) - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A) + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_prepare_01) - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_prepare_01) + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_prepare_02) - RECV(VFS5011_IN_ENDPOINT_CTRL, 2368) - RECV(VFS5011_IN_ENDPOINT_CTRL, 64) - RECV(VFS5011_IN_ENDPOINT_DATA, 4800) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_prepare_02) + RECV (VFS5011_IN_ENDPOINT_CTRL, 2368) + RECV (VFS5011_IN_ENDPOINT_CTRL, 64) + RECV (VFS5011_IN_ENDPOINT_DATA, 4800) - SEND(VFS5011_OUT_ENDPOINT, vfs5011_prepare_03) - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) - /* - * Windows driver does this and it works - * But in this driver this call never returns... - * RECV(VFS5011_IN_ENDPOINT_CTRL2, 8); - */ + SEND (VFS5011_OUT_ENDPOINT, vfs5011_prepare_03) + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY) + /* + * Windows driver does this and it works + * But in this driver this call never returns... + * RECV(VFS5011_IN_ENDPOINT_CTRL2, 8); + */ - SEND(VFS5011_OUT_ENDPOINT, vfs5011_prepare_04) - RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 2368, VFS5011_NORMAL_CONTROL_REPLY) + SEND (VFS5011_OUT_ENDPOINT, vfs5011_prepare_04) + RECV_CHECK (VFS5011_IN_ENDPOINT_CTRL, 2368, VFS5011_NORMAL_CONTROL_REPLY) - /* - * Windows driver does this and it works - * But in this driver this call never returns... - * RECV(VFS5011_IN_ENDPOINT_CTRL2, 8); - */ + /* + * Windows driver does this and it works + * But in this driver this call never returns... + * RECV(VFS5011_IN_ENDPOINT_CTRL2, 8); + */ }; /* ====================== lifprint interface ======================= */ -static void activate_loop(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +activate_loop (FpiSsm *ssm, FpDevice *_dev) { - enum {READ_TIMEOUT = 0}; + enum {READ_TIMEOUT = 0}; - struct fp_img_dev *dev = user_data; - struct vfs5011_data *data; - int r; - fpi_timeout *timeout; + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpDeviceVfs5011 *self; - data = FP_INSTANCE_DATA(_dev); + self = FPI_DEVICE_VFS5011 (_dev); - fp_dbg("main_loop: state %d", fpi_ssm_get_cur_state(ssm)); + fp_dbg ("main_loop: state %d", fpi_ssm_get_cur_state (ssm)); - if (data->deactivating) { - fp_dbg("deactivating, marking completed"); - fpi_ssm_mark_completed(ssm); - return; - } + if (self->deactivating) + { + fp_dbg ("deactivating, marking completed"); + fpi_ssm_mark_completed (ssm); + return; + } - switch (fpi_ssm_get_cur_state(ssm)) { - case DEV_ACTIVATE_REQUEST_FPRINT: - data->init_sequence.stepcount = - G_N_ELEMENTS(vfs5011_initiate_capture); - data->init_sequence.actions = vfs5011_initiate_capture; - data->init_sequence.device = dev; - if (data->init_sequence.receive_buf == NULL) - data->init_sequence.receive_buf = - g_malloc0(VFS5011_RECEIVE_BUF_SIZE); - data->init_sequence.timeout = 1000; - usb_exchange_async(ssm, &data->init_sequence); - break; + switch (fpi_ssm_get_cur_state (ssm)) + { + case DEV_ACTIVATE_REQUEST_FPRINT: + self->init_sequence.stepcount = + G_N_ELEMENTS (vfs5011_initiate_capture); + self->init_sequence.actions = vfs5011_initiate_capture; + self->init_sequence.device = dev; + if (self->init_sequence.receive_buf == NULL) + self->init_sequence.receive_buf = + g_malloc0 (VFS5011_RECEIVE_BUF_SIZE); + self->init_sequence.timeout = 1000; + usb_exchange_async (ssm, &self->init_sequence); + break; - case DEV_ACTIVATE_INIT_COMPLETE: - if (data->init_sequence.receive_buf != NULL) - g_free(data->init_sequence.receive_buf); - data->init_sequence.receive_buf = NULL; - capture_init(data, MAX_CAPTURE_LINES, MAXLINES); - fpi_imgdev_activate_complete(dev, 0); - fpi_ssm_next_state(ssm); - break; + case DEV_ACTIVATE_INIT_COMPLETE: + if (self->init_sequence.receive_buf != NULL) + g_free (self->init_sequence.receive_buf); + self->init_sequence.receive_buf = NULL; + capture_init (self, MAX_CAPTURE_LINES, MAXLINES); + fpi_image_device_activate_complete (dev, NULL); + fpi_ssm_next_state (ssm); + break; - case DEV_ACTIVATE_READ_DATA: - r = capture_chunk_async(data, fpi_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_LINES, - READ_TIMEOUT, ssm); - if (r != 0) { - fp_err("Failed to capture data"); - fpi_imgdev_session_error(dev, r); - fpi_ssm_mark_failed(ssm, r); - } - break; + case DEV_ACTIVATE_READ_DATA: + capture_chunk_async (self, + fpi_device_get_usb_device (FP_DEVICE (dev)), + CAPTURE_LINES, + READ_TIMEOUT, ssm); + break; - case DEV_ACTIVATE_DATA_COMPLETE: - timeout = fpi_timeout_add(1, fpi_ssm_next_state_timeout_cb, _dev, ssm); + case DEV_ACTIVATE_DATA_COMPLETE: + fpi_device_add_timeout (_dev, 1, + fpi_ssm_next_state_timeout_cb, + ssm); - if (timeout == NULL) { - /* Failed to add timeout */ - fp_err("failed to add timeout"); - fpi_imgdev_session_error(dev, -1); - fpi_ssm_mark_failed(ssm, -1); - } - break; + break; - case DEV_ACTIVATE_PREPARE_NEXT_CAPTURE: - data->init_sequence.stepcount = - G_N_ELEMENTS(vfs5011_initiate_capture); - data->init_sequence.actions = vfs5011_initiate_capture; - data->init_sequence.device = dev; - if (data->init_sequence.receive_buf == NULL) - data->init_sequence.receive_buf = - g_malloc0(VFS5011_RECEIVE_BUF_SIZE); - data->init_sequence.timeout = VFS5011_DEFAULT_WAIT_TIMEOUT; - usb_exchange_async(ssm, &data->init_sequence); - break; + case DEV_ACTIVATE_PREPARE_NEXT_CAPTURE: + self->init_sequence.stepcount = + G_N_ELEMENTS (vfs5011_initiate_capture); + self->init_sequence.actions = vfs5011_initiate_capture; + self->init_sequence.device = dev; + if (self->init_sequence.receive_buf == NULL) + self->init_sequence.receive_buf = + g_malloc0 (VFS5011_RECEIVE_BUF_SIZE); + self->init_sequence.timeout = VFS5011_DEFAULT_WAIT_TIMEOUT; + usb_exchange_async (ssm, &self->init_sequence); + break; - } + } } -static void activate_loop_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +activate_loop_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { - struct fp_img_dev *dev = user_data; - struct vfs5011_data *data; - int r = fpi_ssm_get_error(ssm); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpDeviceVfs5011 *self; - data = FP_INSTANCE_DATA(_dev); + self = FPI_DEVICE_VFS5011 (_dev); - fp_dbg("finishing"); - if (data->init_sequence.receive_buf != NULL) - g_free(data->init_sequence.receive_buf); - data->init_sequence.receive_buf = NULL; - if (!data->deactivating && !r) { - submit_image(ssm, data, dev); - fpi_imgdev_report_finger_status(dev, FALSE); - } - fpi_ssm_free(ssm); + fp_dbg ("finishing"); + if (self->init_sequence.receive_buf != NULL) + g_free (self->init_sequence.receive_buf); + self->init_sequence.receive_buf = NULL; + if (!self->deactivating && !error) + { + submit_image (ssm, self, dev); + fpi_image_device_report_finger_status (dev, FALSE); + } + fpi_ssm_free (ssm); - data->loop_running = FALSE; + self->loop_running = FALSE; - if (data->deactivating) { - fpi_imgdev_deactivate_complete(dev); - } else if (r) { - fpi_imgdev_session_error(dev, r); - } else { - start_scan(dev); - } + if (self->deactivating) + fpi_image_device_deactivate_complete (dev, error); + else if (error) + fpi_image_device_session_error (dev, error); + else + start_scan (dev); } -static void open_loop(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +open_loop (FpiSsm *ssm, FpDevice *_dev) { - struct fp_img_dev *dev = user_data; - struct vfs5011_data *data; + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpDeviceVfs5011 *self; - data = FP_INSTANCE_DATA(_dev); + self = FPI_DEVICE_VFS5011 (_dev); - switch (fpi_ssm_get_cur_state(ssm)) { - case DEV_OPEN_START: - data->init_sequence.stepcount = - G_N_ELEMENTS(vfs5011_initialization); - data->init_sequence.actions = vfs5011_initialization; - data->init_sequence.device = dev; - data->init_sequence.receive_buf = - g_malloc0(VFS5011_RECEIVE_BUF_SIZE); - data->init_sequence.timeout = VFS5011_DEFAULT_WAIT_TIMEOUT; - usb_exchange_async(ssm, &data->init_sequence); - break; - }; + switch (fpi_ssm_get_cur_state (ssm)) + { + case DEV_OPEN_START: + self->init_sequence.stepcount = + G_N_ELEMENTS (vfs5011_initialization); + self->init_sequence.actions = vfs5011_initialization; + self->init_sequence.device = dev; + self->init_sequence.receive_buf = + g_malloc0 (VFS5011_RECEIVE_BUF_SIZE); + self->init_sequence.timeout = VFS5011_DEFAULT_WAIT_TIMEOUT; + usb_exchange_async (ssm, &self->init_sequence); + break; + } + ; } -static void open_loop_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +open_loop_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { - struct fp_img_dev *dev = user_data; - struct vfs5011_data *data; + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpDeviceVfs5011 *self; - data = FP_INSTANCE_DATA(_dev); - g_free(data->init_sequence.receive_buf); - data->init_sequence.receive_buf = NULL; + self = FPI_DEVICE_VFS5011 (_dev); + g_free (self->init_sequence.receive_buf); + self->init_sequence.receive_buf = NULL; - fpi_imgdev_open_complete(dev, 0); - fpi_ssm_free(ssm); + fpi_image_device_open_complete (dev, error); + fpi_ssm_free (ssm); } -static int dev_open(struct fp_img_dev *dev, unsigned long driver_data) +static void +dev_open (FpImageDevice *dev) { + FpiSsm *ssm; + GError *error = NULL; + FpDeviceVfs5011 *self; - struct vfs5011_data *data; - int r; + self = FPI_DEVICE_VFS5011 (dev); + self->capture_buffer = g_new0 (unsigned char, CAPTURE_LINES * VFS5011_LINE_SIZE); - data = (struct vfs5011_data *)g_malloc0(sizeof(*data)); - data->capture_buffer = - (unsigned char *)g_malloc0(CAPTURE_LINES * VFS5011_LINE_SIZE); - fp_dev_set_instance_data(FP_DEV(dev), data); + if (!g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error)) + { + fpi_image_device_open_complete (dev, error); + return; + } - r = libusb_reset_device(fpi_dev_get_usb_dev(FP_DEV(dev))); - if (r != 0) { - fp_err("Failed to reset the device"); - return r; - } - - r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - if (r != 0) { - fp_err("Failed to claim interface: %s", libusb_error_name(r)); - return r; - } - - fpi_ssm *ssm; - ssm = fpi_ssm_new(FP_DEV(dev), open_loop, DEV_OPEN_NUM_STATES, dev); - fpi_ssm_start(ssm, open_loop_complete); - - return 0; + ssm = fpi_ssm_new (FP_DEVICE (dev), open_loop, DEV_OPEN_NUM_STATES); + fpi_ssm_start (ssm, open_loop_complete); } -static void dev_close(struct fp_img_dev *dev) +static void +dev_close (FpImageDevice *dev) { - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - struct vfs5011_data *data; - data = FP_INSTANCE_DATA(FP_DEV(dev)); - if (data != NULL) { - g_free(data->capture_buffer); - g_slist_free_full(data->rows, g_free); - g_free(data); - } - fpi_imgdev_close_complete(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 (self->rows, g_free); + + fpi_image_device_close_complete (dev, error); } -static void start_scan(struct fp_img_dev *dev) +static void +start_scan (FpImageDevice *dev) { - struct vfs5011_data *data; - fpi_ssm *ssm; + FpDeviceVfs5011 *self; + FpiSsm *ssm; - data = FP_INSTANCE_DATA(FP_DEV(dev)); - data->loop_running = TRUE; - fp_dbg("creating ssm"); - ssm = fpi_ssm_new(FP_DEV(dev), activate_loop, DEV_ACTIVATE_NUM_STATES, dev); - fp_dbg("starting ssm"); - fpi_ssm_start(ssm, activate_loop_complete); - fp_dbg("ssm done, getting out"); + self = FPI_DEVICE_VFS5011 (dev); + self->loop_running = TRUE; + fp_dbg ("creating ssm"); + ssm = fpi_ssm_new (FP_DEVICE (dev), activate_loop, DEV_ACTIVATE_NUM_STATES); + fp_dbg ("starting ssm"); + fpi_ssm_start (ssm, activate_loop_complete); + fp_dbg ("ssm done, getting out"); } -static int dev_activate(struct fp_img_dev *dev) +static void +dev_activate (FpImageDevice *dev) { - struct vfs5011_data *data; + FpDeviceVfs5011 *self; - data = FP_INSTANCE_DATA(FP_DEV(dev)); - fp_dbg("device initialized"); - data->deactivating = FALSE; + self = FPI_DEVICE_VFS5011 (dev); + fp_dbg ("device initialized"); + self->deactivating = FALSE; - start_scan(dev); - - return 0; + start_scan (dev); } -static void dev_deactivate(struct fp_img_dev *dev) +static void +dev_deactivate (FpImageDevice *dev) { - int r; - struct vfs5011_data *data; + FpDeviceVfs5011 *self; - data = FP_INSTANCE_DATA(FP_DEV(dev)); - if (data->loop_running) { - data->deactivating = TRUE; - if (data->flying_transfer) { - r = libusb_cancel_transfer(data->flying_transfer); - if (r < 0) - fp_dbg("cancel failed error %d", r); - } - } else - fpi_imgdev_deactivate_complete(dev); + self = FPI_DEVICE_VFS5011 (dev); + if (self->loop_running) + self->deactivating = TRUE; + else + fpi_image_device_deactivate_complete (dev, NULL); } -static const struct usb_id id_table[] = { - { .vendor = 0x138a, .product = 0x0010 /* Validity device from some Toshiba laptops */ }, - { .vendor = 0x138a, .product = 0x0011 /* vfs5011 */ }, - { .vendor = 0x138a, .product = 0x0015 /* Validity device from Lenovo Preferred Pro USB Fingerprint Keyboard KUF1256 */ }, - { .vendor = 0x138a, .product = 0x0017 /* Validity device from Lenovo T440 laptops */ }, - { .vendor = 0x138a, .product = 0x0018 /* one more Validity device */ }, - { 0, 0, 0, }, +static const FpIdEntry id_table[] = { + { /* Validity device from some Toshiba laptops */ .vid = 0x138a, .pid = 0x0010, }, + { /* vfs5011 */ .vid = 0x138a, .pid = 0x0011, }, + { /* Validity device from Lenovo Preferred Pro USB Fingerprint Keyboard KUF1256 */ .vid = 0x138a, .pid = 0x0015, }, + { /* Validity device from Lenovo T440 laptops */ .vid = 0x138a, .pid = 0x0017, }, + { /* one more Validity device */ .vid = 0x138a, .pid = 0x0018, }, + { .vid = 0, .pid = 0, .driver_data = 0 }, }; -struct fp_img_driver vfs5011_driver = { - .driver = { - .id = VFS5011_ID, - .name = "vfs5011", - .full_name = "Validity VFS5011", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_SWIPE, - }, +static void +fpi_device_vfs5011_init (FpDeviceVfs5011 *self) +{ +} +static void +fpi_device_vfs5011_class_init (FpDeviceVfs5011Class *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); - .flags = 0, - .img_width = VFS5011_IMAGE_WIDTH, - .img_height = -1, - .bz3_threshold = 20, + dev_class->id = "vfs5011"; + dev_class->full_name = "Validity VFS5011"; + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->id_table = id_table; + dev_class->scan_type = FP_SCAN_TYPE_SWIPE; - .open = dev_open, - .close = dev_close, - .activate = dev_activate, - .deactivate = dev_deactivate, -}; + img_class->img_open = dev_open; + img_class->img_close = dev_close; + img_class->activate = dev_activate; + img_class->deactivate = dev_deactivate; + img_class->bz3_threshold = 20; + + img_class->img_width = VFS5011_IMAGE_WIDTH; + img_class->img_height = -1; +} diff --git a/libfprint/drivers/vfs5011_proto.h b/libfprint/drivers/vfs5011_proto.h index 8cd0ea80..f71a10f6 100644 --- a/libfprint/drivers/vfs5011_proto.h +++ b/libfprint/drivers/vfs5011_proto.h @@ -5,6182 +5,6182 @@ #define VFS5011_IMAGE_WIDTH 160 enum { - VFS5011_DEFAULT_WAIT_TIMEOUT = 3000, + VFS5011_DEFAULT_WAIT_TIMEOUT = 3000, - VFS5011_OUT_ENDPOINT = 1 | LIBUSB_ENDPOINT_OUT, - VFS5011_IN_ENDPOINT_CTRL = 1 | LIBUSB_ENDPOINT_IN, - VFS5011_IN_ENDPOINT_DATA = 2 | LIBUSB_ENDPOINT_IN, - VFS5011_IN_ENDPOINT_CTRL2 = 3 | LIBUSB_ENDPOINT_IN, + VFS5011_OUT_ENDPOINT = 1 | FPI_USB_ENDPOINT_OUT, + VFS5011_IN_ENDPOINT_CTRL = 1 | FPI_USB_ENDPOINT_IN, + VFS5011_IN_ENDPOINT_DATA = 2 | FPI_USB_ENDPOINT_IN, + VFS5011_IN_ENDPOINT_CTRL2 = 3 | FPI_USB_ENDPOINT_IN, }; enum { - VFS5011_RECEIVE_BUF_SIZE = 102400 + VFS5011_RECEIVE_BUF_SIZE = 102400 }; static unsigned char VFS5011_NORMAL_CONTROL_REPLY[] = {0x00, 0x00}; static unsigned char vfs5011_cmd_01[] = { /* 1 B */ - 0x01, + 0x01, }; static unsigned char vfs5011_cmd_19[] = { /* 1 B */ - 0x19, + 0x19, }; static unsigned char vfs5011_init_00[] = { /* 39 B */ - 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, }; static unsigned char vfs5011_init_01[] = { /* 40 B */ - 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00, 0x00, }; static unsigned char vfs5011_init_02[] = { /* 578 B */ - 0x06, 0x9C, 0xF1, 0x9D, 0x71, 0xC3, 0x13, 0xDF, - 0x5F, 0xE4, 0x7A, 0x1F, 0xC7, 0x17, 0x53, 0x9A, - 0x1A, 0xA1, 0xD7, 0xB6, 0x6E, 0xBE, 0xDF, 0x1F, - 0x9F, 0x44, 0x42, 0x22, 0xFA, 0x2A, 0x6A, 0xAB, - 0x2B, 0xF0, 0x56, 0x39, 0xE3, 0x7B, 0x53, 0x9A, - 0x1A, 0xA1, 0xDB, 0xBA, 0x62, 0xB2, 0xE4, 0x65, - 0xE5, 0xDB, 0x68, 0x04, 0x79, 0x98, 0xDE, 0x8F, - 0x23, 0xFB, 0xEC, 0xAD, 0x76, 0xCA, 0xA2, 0xEB, - 0x61, 0x38, 0xC7, 0xAB, 0x6E, 0x2E, 0x78, 0xF9, - 0x79, 0x13, 0x8A, 0xE5, 0x90, 0x22, 0x63, 0x8D, - 0x0E, 0x93, 0x25, 0x49, 0x5A, 0xC8, 0xA3, 0xD8, - 0x7E, 0xAE, 0x12, 0xF6, 0x2C, 0x1C, 0xFC, 0x48, - 0x4F, 0x0E, 0x48, 0x22, 0xFB, 0x4B, 0xCE, 0x7E, - 0xDB, 0x2D, 0x91, 0xE0, 0xC8, 0x78, 0x2E, 0xAF, - 0x2F, 0xD4, 0x03, 0x6F, 0x12, 0x59, 0xC6, 0x26, - 0x40, 0x88, 0x2E, 0x62, 0xBA, 0x06, 0x6C, 0xC9, - 0x7A, 0x84, 0x93, 0xCF, 0x14, 0x15, 0x44, 0x87, - 0xE2, 0x09, 0x97, 0xE6, 0xCE, 0x7E, 0x28, 0xA9, - 0x29, 0x53, 0xD7, 0xB8, 0xD1, 0x53, 0x30, 0x15, - 0x6E, 0x95, 0x3E, 0xA2, 0x7A, 0xCA, 0x9C, 0x1D, - 0x9D, 0xEB, 0x5F, 0x15, 0xEF, 0x48, 0x34, 0xCC, - 0xCB, 0x02, 0xA6, 0xD6, 0xA7, 0x80, 0xF2, 0x3F, - 0x7E, 0x96, 0x23, 0xAE, 0x42, 0xF1, 0x29, 0xF5, - 0xAD, 0x5A, 0x35, 0x57, 0x36, 0xAA, 0xAF, 0x97, - 0xE8, 0x1E, 0xA2, 0xD3, 0xFB, 0x4B, 0x1D, 0x9C, - 0x1C, 0x06, 0x84, 0xEB, 0x9E, 0x2C, 0xD4, 0x18, - 0x94, 0x44, 0x7E, 0x4B, 0x12, 0x91, 0xF2, 0x8B, - 0x07, 0x45, 0xDB, 0x52, 0xBB, 0x2E, 0x53, 0x63, - 0xE3, 0x38, 0xB8, 0x95, 0x4D, 0x9B, 0xCF, 0x07, - 0x05, 0xDD, 0x4C, 0xE2, 0x39, 0xAF, 0xA9, 0x51, - 0xDB, 0xAD, 0x19, 0xC8, 0x13, 0x6E, 0x0A, 0x2F, - 0xEA, 0x12, 0xB9, 0x25, 0x55, 0xB6, 0x64, 0x04, - 0x7F, 0x14, 0x6E, 0x12, 0x08, 0xFB, 0xBD, 0xBD, - 0x1D, 0xC6, 0xE2, 0x84, 0x50, 0x20, 0x60, 0xA0, - 0x90, 0xD2, 0x74, 0x8A, 0x18, 0xA4, 0xD9, 0xE9, - 0x69, 0xB2, 0x1E, 0x73, 0xAB, 0x1B, 0x7B, 0xBB, - 0x3B, 0xE0, 0x42, 0x23, 0xF9, 0x29, 0x49, 0x89, - 0x09, 0xD2, 0x4C, 0x29, 0xF1, 0x21, 0x65, 0xAC, - 0x2C, 0x97, 0x30, 0x6C, 0xB4, 0x04, 0xF4, 0x3D, - 0xBD, 0x06, 0xA0, 0xC6, 0x1E, 0xCE, 0x7E, 0xB3, - 0x33, 0x88, 0x2E, 0x43, 0x9B, 0x2B, 0x37, 0xF0, - 0x70, 0xCB, 0x91, 0xF1, 0x2B, 0xFB, 0x8B, 0x48, - 0xCA, 0x39, 0x97, 0xFB, 0x21, 0xB9, 0xCD, 0x0E, - 0x8C, 0x7F, 0x8D, 0xEC, 0x36, 0xE6, 0xEA, 0x27, - 0xA5, 0x1E, 0x40, 0x2A, 0xF2, 0x22, 0xCA, 0x07, - 0x85, 0x3E, 0xC8, 0xAE, 0x76, 0xA6, 0xF0, 0x71, - 0xF1, 0xAB, 0x6B, 0x04, 0x6D, 0xA9, 0xCA, 0x06, - 0x2C, 0x66, 0xA5, 0xCA, 0xB0, 0x4B, 0x2B, 0x62, - 0xEB, 0xD5, 0x61, 0x0D, 0xF0, 0x46, 0x26, 0xC3, - 0x44, 0x9F, 0x0C, 0x63, 0xBB, 0xAA, 0xBD, 0x7E, - 0xF2, 0x74, 0x00, 0x66, 0x2B, 0x7A, 0x62, 0xA1, - 0x07, 0x80, 0x33, 0x8D, 0x1F, 0xF7, 0x45, 0xCB, - 0x5E, 0x24, 0xEB, 0x84, 0xED, 0x27, 0x44, 0x61, - 0xFF, 0x0C, 0xA7, 0x3B, 0xE3, 0x53, 0x05, 0x84, - 0x04, 0xEE, 0x23, 0x4C, 0xB5, 0x79, 0x1A, 0xF3, - 0xA0, 0x66, 0x20, 0x4C, 0x94, 0x24, 0x72, 0xF3, - 0x73, 0x39, 0xF8, 0x97, 0xDD, 0x64, 0x54, 0xF2, - 0x6B, 0xBA, 0xAD, 0xBC, 0x67, 0x66, 0x78, 0xBB, - 0x5E, 0x6D, 0xFB, 0x8A, 0xA2, 0x74, 0x3D, 0xF5, - 0xD4, 0x72, 0xC7, 0x1A, 0xBD, 0x0E, 0x0B, 0x2C, - 0x8C, 0x4A, 0x0C, 0x60, 0xB8, 0x08, 0x5E, 0xDF, - 0x5F, 0x05, 0x33, 0x5C, 0xB5, 0x7E, 0x1D, 0xFC, - 0xFD, 0x25, 0xBA, 0x95, 0xC4, 0xA7, 0xDA, 0xEA, - 0x6A, 0xB1, 0x31, 0x1C, 0xC4, 0xE5, 0x07, 0xC4, - 0xC5, 0x9D, 0x28, 0xCD, 0x3C, 0xE9, 0x89, 0x49, - 0xD4, 0xFF, 0x7F, 0x52, 0x8A, 0x9B, 0x7F, 0xBC, - 0x8E, 0xF5, 0xCF, 0x0B, 0xD9, 0x49, 0x48, 0x88, - 0x80, 0x71, 0x7D, 0xAB, 0xEF, 0x47, 0x2B, 0xF7, - 0x7B, 0x2D, 0x79, 0x3F, 0xCF, 0xBF, 0xFF, 0x3F, - 0x6D, 0xF8, 0x42, 0xEC, 0x7F, 0xE8, 0xED, 0x42, - 0xE6, 0x1D, 0x4D, 0x32, 0xFA, 0x6A, 0x0A, 0xD7, - 0xA7, 0x7C, 0xCB, 0xA7, 0x7B, 0xCB, 0xBF, 0x71, - 0xF3, 0x48, + 0x06, 0x9C, 0xF1, 0x9D, 0x71, 0xC3, 0x13, 0xDF, + 0x5F, 0xE4, 0x7A, 0x1F, 0xC7, 0x17, 0x53, 0x9A, + 0x1A, 0xA1, 0xD7, 0xB6, 0x6E, 0xBE, 0xDF, 0x1F, + 0x9F, 0x44, 0x42, 0x22, 0xFA, 0x2A, 0x6A, 0xAB, + 0x2B, 0xF0, 0x56, 0x39, 0xE3, 0x7B, 0x53, 0x9A, + 0x1A, 0xA1, 0xDB, 0xBA, 0x62, 0xB2, 0xE4, 0x65, + 0xE5, 0xDB, 0x68, 0x04, 0x79, 0x98, 0xDE, 0x8F, + 0x23, 0xFB, 0xEC, 0xAD, 0x76, 0xCA, 0xA2, 0xEB, + 0x61, 0x38, 0xC7, 0xAB, 0x6E, 0x2E, 0x78, 0xF9, + 0x79, 0x13, 0x8A, 0xE5, 0x90, 0x22, 0x63, 0x8D, + 0x0E, 0x93, 0x25, 0x49, 0x5A, 0xC8, 0xA3, 0xD8, + 0x7E, 0xAE, 0x12, 0xF6, 0x2C, 0x1C, 0xFC, 0x48, + 0x4F, 0x0E, 0x48, 0x22, 0xFB, 0x4B, 0xCE, 0x7E, + 0xDB, 0x2D, 0x91, 0xE0, 0xC8, 0x78, 0x2E, 0xAF, + 0x2F, 0xD4, 0x03, 0x6F, 0x12, 0x59, 0xC6, 0x26, + 0x40, 0x88, 0x2E, 0x62, 0xBA, 0x06, 0x6C, 0xC9, + 0x7A, 0x84, 0x93, 0xCF, 0x14, 0x15, 0x44, 0x87, + 0xE2, 0x09, 0x97, 0xE6, 0xCE, 0x7E, 0x28, 0xA9, + 0x29, 0x53, 0xD7, 0xB8, 0xD1, 0x53, 0x30, 0x15, + 0x6E, 0x95, 0x3E, 0xA2, 0x7A, 0xCA, 0x9C, 0x1D, + 0x9D, 0xEB, 0x5F, 0x15, 0xEF, 0x48, 0x34, 0xCC, + 0xCB, 0x02, 0xA6, 0xD6, 0xA7, 0x80, 0xF2, 0x3F, + 0x7E, 0x96, 0x23, 0xAE, 0x42, 0xF1, 0x29, 0xF5, + 0xAD, 0x5A, 0x35, 0x57, 0x36, 0xAA, 0xAF, 0x97, + 0xE8, 0x1E, 0xA2, 0xD3, 0xFB, 0x4B, 0x1D, 0x9C, + 0x1C, 0x06, 0x84, 0xEB, 0x9E, 0x2C, 0xD4, 0x18, + 0x94, 0x44, 0x7E, 0x4B, 0x12, 0x91, 0xF2, 0x8B, + 0x07, 0x45, 0xDB, 0x52, 0xBB, 0x2E, 0x53, 0x63, + 0xE3, 0x38, 0xB8, 0x95, 0x4D, 0x9B, 0xCF, 0x07, + 0x05, 0xDD, 0x4C, 0xE2, 0x39, 0xAF, 0xA9, 0x51, + 0xDB, 0xAD, 0x19, 0xC8, 0x13, 0x6E, 0x0A, 0x2F, + 0xEA, 0x12, 0xB9, 0x25, 0x55, 0xB6, 0x64, 0x04, + 0x7F, 0x14, 0x6E, 0x12, 0x08, 0xFB, 0xBD, 0xBD, + 0x1D, 0xC6, 0xE2, 0x84, 0x50, 0x20, 0x60, 0xA0, + 0x90, 0xD2, 0x74, 0x8A, 0x18, 0xA4, 0xD9, 0xE9, + 0x69, 0xB2, 0x1E, 0x73, 0xAB, 0x1B, 0x7B, 0xBB, + 0x3B, 0xE0, 0x42, 0x23, 0xF9, 0x29, 0x49, 0x89, + 0x09, 0xD2, 0x4C, 0x29, 0xF1, 0x21, 0x65, 0xAC, + 0x2C, 0x97, 0x30, 0x6C, 0xB4, 0x04, 0xF4, 0x3D, + 0xBD, 0x06, 0xA0, 0xC6, 0x1E, 0xCE, 0x7E, 0xB3, + 0x33, 0x88, 0x2E, 0x43, 0x9B, 0x2B, 0x37, 0xF0, + 0x70, 0xCB, 0x91, 0xF1, 0x2B, 0xFB, 0x8B, 0x48, + 0xCA, 0x39, 0x97, 0xFB, 0x21, 0xB9, 0xCD, 0x0E, + 0x8C, 0x7F, 0x8D, 0xEC, 0x36, 0xE6, 0xEA, 0x27, + 0xA5, 0x1E, 0x40, 0x2A, 0xF2, 0x22, 0xCA, 0x07, + 0x85, 0x3E, 0xC8, 0xAE, 0x76, 0xA6, 0xF0, 0x71, + 0xF1, 0xAB, 0x6B, 0x04, 0x6D, 0xA9, 0xCA, 0x06, + 0x2C, 0x66, 0xA5, 0xCA, 0xB0, 0x4B, 0x2B, 0x62, + 0xEB, 0xD5, 0x61, 0x0D, 0xF0, 0x46, 0x26, 0xC3, + 0x44, 0x9F, 0x0C, 0x63, 0xBB, 0xAA, 0xBD, 0x7E, + 0xF2, 0x74, 0x00, 0x66, 0x2B, 0x7A, 0x62, 0xA1, + 0x07, 0x80, 0x33, 0x8D, 0x1F, 0xF7, 0x45, 0xCB, + 0x5E, 0x24, 0xEB, 0x84, 0xED, 0x27, 0x44, 0x61, + 0xFF, 0x0C, 0xA7, 0x3B, 0xE3, 0x53, 0x05, 0x84, + 0x04, 0xEE, 0x23, 0x4C, 0xB5, 0x79, 0x1A, 0xF3, + 0xA0, 0x66, 0x20, 0x4C, 0x94, 0x24, 0x72, 0xF3, + 0x73, 0x39, 0xF8, 0x97, 0xDD, 0x64, 0x54, 0xF2, + 0x6B, 0xBA, 0xAD, 0xBC, 0x67, 0x66, 0x78, 0xBB, + 0x5E, 0x6D, 0xFB, 0x8A, 0xA2, 0x74, 0x3D, 0xF5, + 0xD4, 0x72, 0xC7, 0x1A, 0xBD, 0x0E, 0x0B, 0x2C, + 0x8C, 0x4A, 0x0C, 0x60, 0xB8, 0x08, 0x5E, 0xDF, + 0x5F, 0x05, 0x33, 0x5C, 0xB5, 0x7E, 0x1D, 0xFC, + 0xFD, 0x25, 0xBA, 0x95, 0xC4, 0xA7, 0xDA, 0xEA, + 0x6A, 0xB1, 0x31, 0x1C, 0xC4, 0xE5, 0x07, 0xC4, + 0xC5, 0x9D, 0x28, 0xCD, 0x3C, 0xE9, 0x89, 0x49, + 0xD4, 0xFF, 0x7F, 0x52, 0x8A, 0x9B, 0x7F, 0xBC, + 0x8E, 0xF5, 0xCF, 0x0B, 0xD9, 0x49, 0x48, 0x88, + 0x80, 0x71, 0x7D, 0xAB, 0xEF, 0x47, 0x2B, 0xF7, + 0x7B, 0x2D, 0x79, 0x3F, 0xCF, 0xBF, 0xFF, 0x3F, + 0x6D, 0xF8, 0x42, 0xEC, 0x7F, 0xE8, 0xED, 0x42, + 0xE6, 0x1D, 0x4D, 0x32, 0xFA, 0x6A, 0x0A, 0xD7, + 0xA7, 0x7C, 0xCB, 0xA7, 0x7B, 0xCB, 0xBF, 0x71, + 0xF3, 0x48, }; static unsigned char vfs5011_cmd_1A[] = { /* 1 B */ - 0x1A, + 0x1A, }; static unsigned char vfs5011_init_03[] = { /* 2354 B */ - 0x06, 0xFE, 0x93, 0xFF, 0x03, 0xBA, 0x6A, 0xA6, - 0x26, 0x9D, 0x03, 0x66, 0xBE, 0x6E, 0x2A, 0xE3, - 0x63, 0xD8, 0xFE, 0x9B, 0x43, 0x93, 0xD7, 0x03, - 0x83, 0x38, 0x8C, 0xE0, 0x38, 0x88, 0x58, 0x94, - 0x14, 0xAF, 0xC9, 0xA2, 0x7A, 0xCA, 0x96, 0x5E, - 0xDE, 0x65, 0x27, 0x36, 0xEA, 0x3A, 0x4E, 0x82, - 0x02, 0xB9, 0x0F, 0x4B, 0x97, 0x17, 0xF7, 0x1A, - 0x9E, 0x75, 0xC3, 0x8F, 0x53, 0xD3, 0x9F, 0x7F, - 0xFB, 0x10, 0xE6, 0xAA, 0x76, 0xF6, 0x72, 0x93, - 0x17, 0xFC, 0x4A, 0x26, 0xFE, 0x76, 0x2A, 0xEA, - 0x6A, 0x89, 0x3F, 0xF3, 0x2B, 0xA3, 0xFF, 0x9F, - 0x1F, 0xFC, 0x4A, 0x06, 0xDE, 0x56, 0x38, 0xD8, - 0x58, 0xBB, 0x0D, 0x21, 0xF9, 0x71, 0x19, 0x99, - 0x19, 0xFA, 0x4C, 0x40, 0x98, 0x10, 0x78, 0xD8, - 0x58, 0xBB, 0x0D, 0xE1, 0x39, 0xB1, 0xD9, 0x99, - 0x19, 0xFA, 0x6C, 0x7E, 0xA2, 0x72, 0xC6, 0x7D, - 0xF9, 0x42, 0xF4, 0x86, 0x5A, 0xDA, 0xD2, 0x06, - 0x86, 0x3D, 0x6F, 0x08, 0xD0, 0x00, 0xD8, 0x10, - 0x90, 0x2B, 0xFD, 0xB7, 0x6B, 0xBB, 0x67, 0xA0, - 0x20, 0x9B, 0x35, 0x36, 0xEA, 0x3A, 0xA2, 0x0C, - 0x88, 0x33, 0x7D, 0x1A, 0xC2, 0x12, 0x2A, 0xFE, - 0x7E, 0xC5, 0x8C, 0x17, 0x30, 0x7F, 0xE0, 0xCF, - 0xB0, 0x94, 0x4E, 0x36, 0xEE, 0x3E, 0x5E, 0x96, - 0x16, 0xCD, 0x9F, 0xE1, 0x3B, 0xEB, 0x8B, 0x5B, - 0xDB, 0x00, 0x8A, 0xF2, 0x2A, 0xFA, 0x0E, 0xC8, - 0x48, 0xF3, 0x6D, 0x12, 0xC8, 0x18, 0x08, 0xDC, - 0x5C, 0xE7, 0x01, 0x79, 0xA1, 0x71, 0x3D, 0xF4, - 0x74, 0xCF, 0x84, 0x17, 0xCF, 0x7F, 0xE0, 0x20, - 0x5F, 0x7B, 0xFB, 0xD6, 0x0E, 0x1B, 0x65, 0xA5, - 0x00, 0xDC, 0x6A, 0xE3, 0x7E, 0xCE, 0x4B, 0xCE, - 0x68, 0x22, 0xB8, 0xD7, 0xAE, 0x33, 0x50, 0x9C, - 0x14, 0x46, 0xFA, 0x14, 0x85, 0x35, 0x48, 0x78, - 0xF8, 0x23, 0xA3, 0x8E, 0x56, 0x77, 0x39, 0xFA, - 0x76, 0xA5, 0x91, 0xB4, 0x34, 0xE1, 0x4D, 0xA8, - 0x35, 0x1E, 0x9E, 0xB3, 0x6B, 0x6A, 0x3A, 0xF9, - 0xD4, 0x0D, 0x9A, 0xD9, 0x02, 0xF4, 0x94, 0x54, - 0x1F, 0xE6, 0x5B, 0x8C, 0x72, 0xC9, 0xA3, 0xEB, - 0x69, 0x32, 0x04, 0x1C, 0x43, 0x69, 0xF9, 0x3F, - 0xBE, 0x65, 0xF6, 0xFE, 0x03, 0x9E, 0xF4, 0x29, - 0x59, 0x82, 0x02, 0x2F, 0xF7, 0x67, 0x66, 0xA6, - 0x03, 0x22, 0x6B, 0x27, 0x19, 0xBA, 0xCA, 0x2A, - 0xAA, 0x7D, 0xC1, 0x08, 0xF6, 0x63, 0xA2, 0x53, - 0xD0, 0xBA, 0x3E, 0x51, 0xAC, 0x38, 0x70, 0xAD, - 0xDD, 0x06, 0x86, 0xAB, 0x73, 0xF2, 0xA1, 0x62, - 0xC3, 0x2C, 0x99, 0xDC, 0x47, 0xEA, 0x7A, 0xBA, - 0x3A, 0xE1, 0x61, 0x4C, 0x94, 0xA6, 0xC4, 0x09, - 0x85, 0x45, 0x73, 0x9F, 0x43, 0xA5, 0xDD, 0x1A, - 0x96, 0x48, 0xF2, 0x98, 0x02, 0xA0, 0xCE, 0x12, - 0x95, 0x74, 0x86, 0x58, 0x44, 0x75, 0x27, 0xE3, - 0x63, 0x0A, 0xB7, 0xA5, 0xBF, 0x0B, 0x6A, 0x9D, - 0xA6, 0x71, 0xF0, 0x20, 0xE9, 0x64, 0x0F, 0x08, - 0x33, 0xE4, 0x6F, 0x0F, 0x11, 0xA0, 0xC0, 0x37, - 0x8B, 0x54, 0x25, 0xF2, 0x2B, 0xA6, 0xCD, 0xA0, - 0x23, 0x45, 0xF0, 0xF9, 0x99, 0x01, 0xCB, 0x6D, - 0xB7, 0x3F, 0x82, 0x99, 0x0A, 0xFE, 0x2C, 0x28, - 0x29, 0xA4, 0x85, 0x15, 0x60, 0xD5, 0x08, 0xCD, - 0x68, 0x04, 0x9A, 0xFA, 0x39, 0x5B, 0x99, 0x35, - 0x15, 0x0A, 0xFD, 0x51, 0x4F, 0x3F, 0x85, 0x97, - 0xE5, 0x23, 0x17, 0xBB, 0xA7, 0x56, 0xF6, 0xB5, - 0x74, 0x5F, 0x06, 0x9A, 0xA2, 0xF1, 0xB0, 0xFA, - 0x94, 0xBF, 0xC7, 0x38, 0x22, 0xCF, 0x2D, 0xEB, - 0x68, 0xB3, 0xC7, 0x09, 0xBD, 0xC7, 0x65, 0x67, - 0xFB, 0x5D, 0xD1, 0x71, 0x6B, 0xD7, 0xB7, 0xA5, - 0x37, 0xE5, 0x7E, 0x19, 0x16, 0x1A, 0x7B, 0xB7, - 0x15, 0xD3, 0x95, 0xF9, 0x21, 0x91, 0xC7, 0x46, - 0xC6, 0xAC, 0x2F, 0x40, 0x20, 0x9B, 0x77, 0xDC, - 0xFE, 0x84, 0x52, 0x94, 0xE7, 0xF2, 0x28, 0xC8, - 0xE5, 0x3C, 0x2F, 0xEF, 0x12, 0xBF, 0x2F, 0xEF, - 0x6F, 0xB4, 0x34, 0x19, 0xC1, 0xD0, 0x86, 0x45, - 0x74, 0x98, 0x2D, 0x8C, 0x56, 0x43, 0x75, 0x90, - 0xA1, 0x43, 0xF6, 0xBA, 0x48, 0x58, 0x99, 0x61, - 0xE2, 0xF4, 0x40, 0x89, 0x04, 0x91, 0x40, 0xBB, - 0x38, 0xC3, 0x4F, 0x83, 0x99, 0xEA, 0x9A, 0xFB, - 0x41, 0x99, 0x23, 0x4D, 0xBC, 0x0F, 0x46, 0x95, - 0x3C, 0xC4, 0x5B, 0x04, 0xF9, 0x1D, 0x58, 0x29, - 0x94, 0x4C, 0xCA, 0x9C, 0xE4, 0x96, 0x35, 0xE5, - 0xC4, 0x23, 0x96, 0xDF, 0x54, 0xC1, 0xAD, 0x64, - 0xD4, 0x35, 0x23, 0x7D, 0x66, 0xC6, 0xBD, 0xE4, - 0x4D, 0x95, 0x68, 0x37, 0x89, 0xA0, 0x36, 0x5B, - 0xD8, 0xB1, 0xA7, 0x6E, 0x9A, 0x66, 0x23, 0x41, - 0xE9, 0x93, 0x1B, 0x74, 0x1D, 0x92, 0xF1, 0xF3, - 0xB0, 0x4F, 0x5C, 0x60, 0x9D, 0x9C, 0xBD, 0x7E, - 0xCE, 0x2F, 0x39, 0xF4, 0x6C, 0xDF, 0x8D, 0x8E, - 0x2A, 0x3C, 0x89, 0xC0, 0x4A, 0xDF, 0x0E, 0x8D, - 0x0E, 0xE5, 0x69, 0xA5, 0xDC, 0x2E, 0x4D, 0x40, - 0xC3, 0xFD, 0x18, 0x51, 0x38, 0xCD, 0xAE, 0x5E, - 0xE4, 0x9F, 0x88, 0xA0, 0x7B, 0x06, 0x65, 0x40, - 0x92, 0x6C, 0x6B, 0x40, 0x9B, 0x1B, 0x41, 0x21, - 0x00, 0x9D, 0x28, 0x89, 0x52, 0xC7, 0xF5, 0x10, - 0xA0, 0x51, 0x47, 0x36, 0x1E, 0xAE, 0xF8, 0x79, - 0xF9, 0x07, 0x94, 0xF8, 0xA1, 0x58, 0x3B, 0x6A, - 0xD9, 0x01, 0x16, 0x32, 0xE9, 0xF0, 0xC9, 0x80, - 0x09, 0xCF, 0x89, 0xE5, 0x3D, 0x8D, 0xDB, 0x5A, - 0xDA, 0x30, 0xB3, 0xDC, 0x08, 0x9F, 0xC7, 0x04, - 0xD5, 0x44, 0xF1, 0x0F, 0xD4, 0x6C, 0x6E, 0x0F, - 0xFF, 0x2F, 0x10, 0x6A, 0xFA, 0x4C, 0xFD, 0x76, - 0xF5, 0x22, 0xFE, 0x9E, 0x41, 0x73, 0xDA, 0xE6, - 0x70, 0xA3, 0x1F, 0x55, 0xD4, 0x6C, 0xA1, 0x63, - 0x06, 0x1C, 0x8C, 0xCD, 0x1F, 0xB2, 0x22, 0x88, - 0x4B, 0x22, 0x87, 0xE0, 0xAA, 0x1E, 0x7E, 0xA8, - 0x13, 0xC3, 0x13, 0x06, 0xCE, 0xBC, 0xC8, 0xF4, - 0x22, 0x55, 0xE9, 0x27, 0xBC, 0x04, 0x46, 0x85, - 0x08, 0xF3, 0x64, 0x0C, 0xC9, 0x89, 0xE5, 0x2E, - 0x2C, 0xF4, 0x4F, 0xE1, 0x1A, 0x77, 0x00, 0xA8, - 0x27, 0x6E, 0xD5, 0xB9, 0x6D, 0xCF, 0xB9, 0x50, - 0xDE, 0x0E, 0x11, 0xDF, 0x4A, 0xFA, 0xDC, 0x1C, - 0x9C, 0x4B, 0xFF, 0x53, 0xAB, 0x1B, 0xD9, 0x0A, - 0x82, 0x9B, 0x48, 0x84, 0xD0, 0x7A, 0xFF, 0xD5, - 0x73, 0xB5, 0xF3, 0xF5, 0x6E, 0x0C, 0x68, 0xA8, - 0x4E, 0x88, 0x02, 0xD6, 0x2C, 0x31, 0x52, 0x77, - 0x13, 0xEE, 0xF8, 0x74, 0xD8, 0x0E, 0x70, 0x91, - 0xA0, 0x37, 0x82, 0x1C, 0xCF, 0x7F, 0x39, 0xD6, - 0x51, 0xF8, 0x05, 0x69, 0xBD, 0x07, 0xC2, 0x68, - 0xCD, 0x1A, 0x94, 0x6A, 0x91, 0xFF, 0x5F, 0xBF, - 0x3F, 0x76, 0xA5, 0x69, 0x33, 0xC0, 0xA8, 0x2E, - 0xAD, 0x76, 0x62, 0x1D, 0xC2, 0xFE, 0xE4, 0x56, - 0x92, 0x49, 0x5D, 0x22, 0xFD, 0xE8, 0x6E, 0x88, - 0x04, 0xCD, 0x66, 0xFA, 0x90, 0x33, 0x5B, 0xF1, - 0x32, 0xFF, 0x82, 0xE9, 0xF3, 0x47, 0x27, 0x25, - 0x69, 0x49, 0xE9, 0xB9, 0x66, 0x34, 0x57, 0x9A, - 0x98, 0x67, 0x50, 0x2B, 0x9D, 0x7D, 0x8F, 0x42, - 0xC2, 0x0F, 0x30, 0x50, 0x84, 0x26, 0x4D, 0x74, - 0x06, 0x90, 0x26, 0xCC, 0x04, 0xB4, 0x56, 0x5F, - 0x26, 0xAB, 0x85, 0x1C, 0x7C, 0xEE, 0x23, 0xE0, - 0x85, 0x83, 0x13, 0xDF, 0x97, 0x53, 0x38, 0x61, - 0xB7, 0x85, 0x39, 0x59, 0x8A, 0x36, 0x1A, 0x38, - 0x9B, 0x9D, 0xF9, 0x37, 0x9B, 0xF1, 0x42, 0x42, - 0xE2, 0x39, 0x2D, 0x52, 0x82, 0xD0, 0xD5, 0xB5, - 0x47, 0xC1, 0x09, 0xA7, 0x3C, 0x84, 0xF2, 0x78, - 0x0A, 0xDD, 0x05, 0x8B, 0x17, 0xA7, 0x65, 0xB6, - 0x3E, 0x00, 0x69, 0x23, 0x7D, 0x08, 0x97, 0x7A, - 0xFD, 0x2A, 0x93, 0x3F, 0xC7, 0x77, 0xB5, 0x66, - 0xEE, 0xB7, 0x64, 0xA8, 0x66, 0x4C, 0xDF, 0x7A, - 0x24, 0xD9, 0x72, 0xEE, 0x3A, 0x88, 0xAE, 0xA6, - 0xD9, 0xBA, 0x2E, 0xEF, 0x34, 0x21, 0x99, 0x7F, - 0x5F, 0x14, 0xD6, 0xDC, 0x1D, 0x8A, 0xE6, 0x2D, - 0x7F, 0x87, 0xEC, 0x42, 0x38, 0xFC, 0x56, 0x55, - 0x15, 0xEE, 0x58, 0xE6, 0x5B, 0x4B, 0x89, 0x5A, - 0xD2, 0x7B, 0x91, 0x83, 0xE7, 0x0D, 0x07, 0x24, - 0xA8, 0x1E, 0x7A, 0x58, 0x80, 0x92, 0xE1, 0x29, - 0x4C, 0x4D, 0xDD, 0x37, 0xE6, 0x56, 0x3A, 0x85, - 0x09, 0x86, 0x72, 0x5D, 0x8D, 0x57, 0x74, 0x46, - 0x82, 0x59, 0x5D, 0x22, 0xF1, 0xDD, 0xF6, 0x84, - 0x50, 0x77, 0xCD, 0x5B, 0x8F, 0xB7, 0x55, 0xD1, - 0x51, 0x6F, 0x01, 0x4B, 0x01, 0xA5, 0x39, 0x6B, - 0x22, 0x08, 0x2C, 0x14, 0x30, 0xA2, 0xC1, 0x0C, - 0xAC, 0x56, 0xE4, 0x95, 0xBD, 0x20, 0x47, 0x01, - 0x5E, 0x7A, 0x6E, 0x16, 0x32, 0x94, 0x2E, 0x06, - 0x8A, 0xD9, 0xED, 0xC5, 0x1D, 0x1B, 0xC1, 0x11, - 0x9D, 0xBC, 0x2F, 0x95, 0x6B, 0xF9, 0x8D, 0xB1, - 0x13, 0x0A, 0x4D, 0x03, 0x8F, 0xC3, 0xA5, 0xF8, - 0x87, 0x39, 0x5A, 0x10, 0xE5, 0x52, 0x74, 0x48, - 0x37, 0xEC, 0x6C, 0x41, 0x99, 0x78, 0x2D, 0xEE, - 0x36, 0xE8, 0x1C, 0xD0, 0xF8, 0x02, 0x27, 0xD5, - 0x51, 0x0A, 0x9A, 0xD5, 0x3C, 0xAA, 0x89, 0x7A, - 0x9B, 0x0A, 0xBF, 0xA2, 0x31, 0x82, 0xEE, 0x86, - 0x20, 0x98, 0x01, 0x0B, 0x50, 0xFE, 0x92, 0x21, - 0x33, 0xCD, 0xA5, 0x09, 0xF1, 0x41, 0xB3, 0x15, - 0x35, 0xDC, 0x2E, 0xC2, 0xA8, 0x1D, 0x70, 0x12, - 0x95, 0x4E, 0x48, 0x95, 0x49, 0x49, 0x81, 0xD2, - 0xF0, 0x6C, 0xDA, 0xAB, 0x83, 0x2E, 0xBE, 0x72, - 0xE1, 0x7C, 0xCA, 0xA6, 0x72, 0xF1, 0xA3, 0x27, - 0x27, 0xE1, 0xA7, 0xC7, 0x4C, 0x3E, 0x7B, 0x65, - 0x25, 0xDE, 0x68, 0xC6, 0x78, 0x68, 0xCE, 0xFD, - 0x82, 0x59, 0xD9, 0xF4, 0x2C, 0xAD, 0x80, 0x43, - 0xE2, 0x77, 0xC2, 0x87, 0x4C, 0xE1, 0x71, 0xB1, - 0x31, 0xEA, 0x6A, 0x47, 0x9F, 0xBE, 0xEB, 0x28, - 0x30, 0xE2, 0xD8, 0x1D, 0x67, 0xFE, 0x43, 0x23, - 0x03, 0xCC, 0x5C, 0x0A, 0xD0, 0x05, 0x22, 0xC3, - 0x5E, 0x75, 0xF5, 0xD8, 0x00, 0x11, 0x21, 0xE2, - 0x43, 0xD1, 0x64, 0x39, 0xD2, 0x61, 0x90, 0x1F, - 0x9C, 0xC6, 0x21, 0x4E, 0x1F, 0x86, 0xCF, 0x0C, - 0x25, 0xA7, 0x0C, 0x90, 0x48, 0xF8, 0xAE, 0x2F, - 0xAF, 0x55, 0xB1, 0xDE, 0x8E, 0x1C, 0xBB, 0x13, - 0x8E, 0xF4, 0x11, 0x7E, 0x43, 0xBE, 0xF6, 0xA7, - 0x73, 0xAB, 0xDC, 0xE5, 0x3E, 0x3F, 0x09, 0xCA, - 0xE2, 0x1B, 0x15, 0x72, 0x6A, 0x70, 0x00, 0x50, - 0x4A, 0x81, 0x87, 0x71, 0x3A, 0x13, 0x51, 0xB4, - 0xFA, 0x04, 0xAF, 0x33, 0xEB, 0x5B, 0x0D, 0x8C, - 0x0C, 0x76, 0x93, 0xFC, 0x41, 0xB6, 0xFE, 0xDF, - 0x08, 0xD0, 0x27, 0x78, 0xA3, 0x22, 0x10, 0xD3, - 0x5F, 0x88, 0xE6, 0xA9, 0x80, 0x66, 0x05, 0x72, - 0x9F, 0x66, 0x6D, 0x0E, 0x1E, 0xAA, 0x03, 0xCC, - 0xE1, 0x38, 0x0F, 0x3B, 0xE0, 0xB0, 0x4D, 0xAD, - 0xB4, 0x4C, 0x73, 0x1B, 0xA6, 0x13, 0x73, 0x02, - 0xDB, 0x03, 0x1D, 0x52, 0x86, 0x34, 0xE4, 0x8E, - 0x2E, 0x5C, 0xC9, 0xB8, 0x90, 0x2C, 0x47, 0x41, - 0x37, 0x13, 0x93, 0xBE, 0x66, 0xCA, 0x62, 0x25, - 0x37, 0xE8, 0x7F, 0x49, 0x92, 0x3F, 0xAF, 0xC2, - 0x40, 0x3E, 0x4E, 0x07, 0xF2, 0x48, 0x35, 0x05, - 0x85, 0x5E, 0xDE, 0xF3, 0x2B, 0xDA, 0xE1, 0x22, - 0x93, 0x14, 0xA1, 0x45, 0xD9, 0xE0, 0x02, 0xFB, - 0x3F, 0xF9, 0xBF, 0xD3, 0x0B, 0xBB, 0xED, 0x6C, - 0xEC, 0x95, 0xE1, 0x9D, 0x60, 0xAB, 0xEB, 0xBA, - 0x61, 0xB9, 0x87, 0x69, 0x38, 0xC1, 0xBC, 0x8C, - 0x0C, 0xD7, 0x57, 0x7A, 0xA2, 0xAF, 0xCD, 0x2C, - 0xF1, 0x29, 0xB7, 0xD9, 0x0D, 0x31, 0xDA, 0xB8, - 0x1D, 0x8C, 0x12, 0xFF, 0x79, 0xCA, 0x38, 0x3A, - 0xAA, 0xE8, 0x0C, 0xF9, 0x63, 0x5A, 0x58, 0x14, - 0x97, 0x75, 0x51, 0x20, 0x08, 0xB8, 0xEE, 0x6F, - 0xEF, 0x05, 0xEE, 0x81, 0x61, 0xD2, 0x00, 0xD3, - 0x4B, 0x9C, 0x36, 0x5D, 0x6E, 0xC4, 0x35, 0xAA, - 0x29, 0x32, 0x2F, 0x63, 0x19, 0xFA, 0x82, 0x82, - 0x22, 0xF9, 0xD7, 0xB2, 0xE8, 0x4B, 0x2D, 0x4F, - 0x0C, 0xC7, 0xEB, 0x0F, 0x5E, 0x9D, 0x18, 0xAB, - 0x0B, 0x62, 0xC7, 0xB3, 0x7C, 0x27, 0x49, 0x31, - 0x22, 0x75, 0x58, 0xBC, 0x6F, 0x72, 0x10, 0x30, - 0xB8, 0x63, 0xF8, 0x9E, 0x5B, 0x1B, 0x77, 0xB5, - 0x28, 0x03, 0x83, 0xAE, 0x76, 0xF7, 0xCA, 0x09, - 0xB1, 0x69, 0x6D, 0x13, 0xDF, 0xA7, 0x64, 0x0C, - 0xAF, 0xBE, 0xB3, 0x66, 0x1D, 0x0A, 0x51, 0xC0, - 0xE0, 0xA0, 0xD6, 0x38, 0xF3, 0x5B, 0xA2, 0xC1, - 0x56, 0xE5, 0x78, 0xD6, 0xA6, 0xE9, 0x68, 0xC8, - 0x4B, 0x68, 0x6D, 0xC1, 0x39, 0x89, 0x3B, 0xE8, - 0x70, 0x1A, 0xE6, 0x89, 0xB1, 0xDC, 0xAC, 0x9E, - 0x75, 0x0E, 0x6A, 0x55, 0x95, 0xE5, 0xA5, 0x65, - 0x47, 0xB7, 0x81, 0x2D, 0xD5, 0x65, 0xC5, 0xAF, - 0x3F, 0x46, 0x9B, 0x77, 0xE9, 0x58, 0x38, 0x5A, - 0x19, 0xD2, 0xC1, 0xC3, 0x3B, 0x4B, 0x0B, 0xCB, - 0xDA, 0x5E, 0xEB, 0x05, 0xCE, 0x78, 0x80, 0x49, - 0x6B, 0x73, 0xD5, 0x23, 0x73, 0x4A, 0x59, 0x7C, - 0x97, 0x6C, 0x52, 0xBD, 0xC8, 0x7A, 0xFA, 0x32, - 0xB2, 0x74, 0x32, 0x5E, 0x86, 0x36, 0x60, 0xE1, - 0x61, 0xF8, 0xE6, 0x75, 0x3C, 0xED, 0x8E, 0xFF, - 0x22, 0xFA, 0x7D, 0x5B, 0x80, 0x88, 0xE3, 0xE1, - 0x7A, 0xB9, 0x03, 0x42, 0x4A, 0x36, 0x76, 0x74, - 0xAF, 0x6C, 0x1A, 0x56, 0x8E, 0x9C, 0xDF, 0xBF, - 0x96, 0xF6, 0x80, 0xCC, 0x14, 0x26, 0x65, 0x05, - 0x45, 0xBE, 0x08, 0xF4, 0xA4, 0x04, 0xF6, 0x97, - 0x17, 0x5C, 0x62, 0x2E, 0x74, 0xA7, 0x67, 0x67, - 0xC7, 0x1C, 0x88, 0xC7, 0x9F, 0xEF, 0xAF, 0x6F, - 0xAF, 0x56, 0xF0, 0xDE, 0xA2, 0x12, 0x32, 0xD0, - 0x70, 0x89, 0x5C, 0xB0, 0x75, 0x35, 0x63, 0xE2, - 0x62, 0xDF, 0x5D, 0x39, 0x63, 0xD0, 0x97, 0x95, - 0x16, 0xEB, 0x3B, 0x6F, 0xBD, 0xA0, 0xC2, 0xBF, - 0x3C, 0x2A, 0x98, 0x51, 0x56, 0xC4, 0xB9, 0x89, - 0xA1, 0x29, 0x2D, 0xE1, 0xC2, 0xC2, 0x6E, 0xBE, - 0xFC, 0x64, 0xF4, 0x58, 0xA0, 0x10, 0xE2, 0x28, - 0xA4, 0xBF, 0x29, 0x45, 0x2D, 0x04, 0x74, 0x26, - 0xEC, 0x3B, 0x90, 0x0C, 0xD4, 0x64, 0x1E, 0xDF, - 0x5F, 0x84, 0x32, 0x5E, 0x86, 0x36, 0xB6, 0x7B, - 0xF9, 0x42, 0xF0, 0x9D, 0x45, 0xF5, 0x95, 0x55, - 0xD5, 0x0E, 0x14, 0x76, 0xAC, 0x7C, 0x00, 0xC0, - 0x48, 0x93, 0x58, 0x30, 0x96, 0x22, 0x7E, 0xAC, - 0x2E, 0x95, 0xBB, 0xC5, 0x1F, 0xCF, 0x03, 0xD1, - 0x53, 0xE8, 0xC2, 0xBD, 0x67, 0xB7, 0xFF, 0x2C, - 0xAE, 0x15, 0xEB, 0x93, 0x4B, 0x9B, 0xB7, 0x63, - 0xE3, 0x58, 0x9E, 0xE6, 0x3E, 0xEE, 0xBA, 0x7A, - 0xFA, 0x21, 0x97, 0xFB, 0x23, 0x93, 0xF3, 0x33, - 0xB3, 0x68, 0xDE, 0xB2, 0x6A, 0xDA, 0x92, 0x5B, - 0xDB, 0x60, 0xF2, 0x97, 0x4F, 0x9F, 0xEF, 0x1F, - 0x9D, 0x46, 0x70, 0x08, 0xD0, 0x00, 0x30, 0xF1, - 0x71, 0xAA, 0xA0, 0xCB, 0x13, 0xC3, 0x0B, 0xC6, - 0x44, 0xFF, 0x35, 0x5E, 0x86, 0x56, 0x8E, 0x43, - 0xC1, 0x7A, 0xF0, 0x94, 0x4C, 0x9C, 0xEC, 0x22, - 0xA0, 0x1B, 0x65, 0x07, 0xDD, 0x0D, 0x05, 0xD1, - 0x51, 0xEA, 0xD0, 0xB3, 0x69, 0xB9, 0xB1, 0x60, - 0xE2, 0x59, 0x57, 0x33, 0xEB, 0x3B, 0x83, 0x52, - 0xD0, 0x6B, 0xD1, 0xAF, 0x75, 0xA5, 0x45, 0x97, - 0x15, 0xAE, 0xF0, 0x9A, 0x42, 0x92, 0x1E, 0xCD, - 0x4F, 0xF4, 0x02, 0x64, 0xBC, 0x6C, 0x3A, 0xBB, - 0x3B, 0x61, 0xC8, 0xA1, 0xC8, 0x65, 0x00, 0xCC, - 0x16, 0x5C, 0xF4, 0x9D, 0xE7, 0x1C, 0x7C, 0x35, - 0xBC, 0x42, 0xF7, 0x9B, 0xA6, 0x15, 0x75, 0x10, - 0x95, 0x4E, 0x9D, 0xF9, 0x21, 0xF4, 0x90, 0x50, - 0xB5, 0x67, 0xD1, 0x58, 0x80, 0x30, 0xF1, 0x11, - 0x94, 0xFE, 0x69, 0x00, 0xFD, 0xF9, 0xBE, 0x63, - 0x13, 0xC8, 0x48, 0x65, 0xBD, 0x3C, 0x7E, 0xBB, - 0x1A, 0xE2, 0x51, 0x14, 0xDF, 0x72, 0xE2, 0x22, - 0xA2, 0x79, 0xF9, 0xD4, 0x0C, 0x8D, 0xC9, 0x0C, - 0xAD, 0x53, 0xE0, 0xA5, 0xAE, 0x03, 0x93, 0x53, - 0xD3, 0x08, 0x88, 0xA5, 0x7D, 0xFC, 0xBA, 0x7F, - 0xDE, 0x22, 0x91, 0xD4, 0x4F, 0xE2, 0x72, 0xB2, - 0x32, 0xE9, 0x69, 0x44, 0x9C, 0x1D, 0x59, 0x9C, - 0x3D, 0xCE, 0x7D, 0x38, 0x73, 0xDE, 0x4E, 0x8E, - 0x0E, 0xD5, 0x55, 0x78, 0xA0, 0x81, 0xC8, 0x0D, - 0x81, 0x52, 0x66, 0x43, 0x9B, 0x4E, 0x2F, 0xEF, - 0xCE, 0x3E, 0x8D, 0x50, 0xAE, 0x1B, 0xBA, 0x50, - 0xD5, 0xC7, 0x7A, 0xBF, 0x3C, 0x91, 0x01, 0xC1, - 0x41, 0x9A, 0x1A, 0x37, 0xEF, 0x6E, 0x22, 0xE7, - 0x46, 0xB0, 0x03, 0x46, 0x8D, 0x20, 0xB0, 0x70, - 0xF0, 0x2B, 0xAB, 0x86, 0x5E, 0x6F, 0x21, 0xE4, - 0x55, 0xAC, 0x1F, 0x52, 0xA5, 0x10, 0x59, 0xBA, - 0xB3, 0x3B, 0x90, 0x0C, 0xD4, 0x64, 0x32, 0xB3, - 0x33, 0x79, 0xFF, 0x96, 0xCF, 0x4E, 0x2B, 0x62, - 0xCB, 0x75, 0xC3, 0xAF, 0x6A, 0x2A, 0x7C, 0xFD, - 0x7D, 0x07, 0x83, 0xEA, 0x80, 0x90, 0x7C, 0x14, - 0x9E, 0x65, 0xB2, 0xDE, 0x8E, 0x14, 0xCE, 0xB4, - 0xA8, 0x6B, 0xD1, 0xA1, 0x75, 0x48, 0xCA, 0x20, - 0x88, 0x93, 0x05, 0x69, 0x63, 0x9D, 0xF1, 0xF3, - 0x38, 0xC4, 0x57, 0x3A, 0xC6, 0x56, 0xD0, 0x03, - 0x93, 0x68, 0xDE, 0xAF, 0x87, 0x37, 0x57, 0x97, - 0x17, 0xCC, 0x7A, 0x16, 0xCE, 0x7E, 0x1E, 0xDE, - 0x5E, 0x85, 0x32, 0x5E, 0x82, 0x32, 0x9E, 0x4A, - 0xC8, 0x73, + 0x06, 0xFE, 0x93, 0xFF, 0x03, 0xBA, 0x6A, 0xA6, + 0x26, 0x9D, 0x03, 0x66, 0xBE, 0x6E, 0x2A, 0xE3, + 0x63, 0xD8, 0xFE, 0x9B, 0x43, 0x93, 0xD7, 0x03, + 0x83, 0x38, 0x8C, 0xE0, 0x38, 0x88, 0x58, 0x94, + 0x14, 0xAF, 0xC9, 0xA2, 0x7A, 0xCA, 0x96, 0x5E, + 0xDE, 0x65, 0x27, 0x36, 0xEA, 0x3A, 0x4E, 0x82, + 0x02, 0xB9, 0x0F, 0x4B, 0x97, 0x17, 0xF7, 0x1A, + 0x9E, 0x75, 0xC3, 0x8F, 0x53, 0xD3, 0x9F, 0x7F, + 0xFB, 0x10, 0xE6, 0xAA, 0x76, 0xF6, 0x72, 0x93, + 0x17, 0xFC, 0x4A, 0x26, 0xFE, 0x76, 0x2A, 0xEA, + 0x6A, 0x89, 0x3F, 0xF3, 0x2B, 0xA3, 0xFF, 0x9F, + 0x1F, 0xFC, 0x4A, 0x06, 0xDE, 0x56, 0x38, 0xD8, + 0x58, 0xBB, 0x0D, 0x21, 0xF9, 0x71, 0x19, 0x99, + 0x19, 0xFA, 0x4C, 0x40, 0x98, 0x10, 0x78, 0xD8, + 0x58, 0xBB, 0x0D, 0xE1, 0x39, 0xB1, 0xD9, 0x99, + 0x19, 0xFA, 0x6C, 0x7E, 0xA2, 0x72, 0xC6, 0x7D, + 0xF9, 0x42, 0xF4, 0x86, 0x5A, 0xDA, 0xD2, 0x06, + 0x86, 0x3D, 0x6F, 0x08, 0xD0, 0x00, 0xD8, 0x10, + 0x90, 0x2B, 0xFD, 0xB7, 0x6B, 0xBB, 0x67, 0xA0, + 0x20, 0x9B, 0x35, 0x36, 0xEA, 0x3A, 0xA2, 0x0C, + 0x88, 0x33, 0x7D, 0x1A, 0xC2, 0x12, 0x2A, 0xFE, + 0x7E, 0xC5, 0x8C, 0x17, 0x30, 0x7F, 0xE0, 0xCF, + 0xB0, 0x94, 0x4E, 0x36, 0xEE, 0x3E, 0x5E, 0x96, + 0x16, 0xCD, 0x9F, 0xE1, 0x3B, 0xEB, 0x8B, 0x5B, + 0xDB, 0x00, 0x8A, 0xF2, 0x2A, 0xFA, 0x0E, 0xC8, + 0x48, 0xF3, 0x6D, 0x12, 0xC8, 0x18, 0x08, 0xDC, + 0x5C, 0xE7, 0x01, 0x79, 0xA1, 0x71, 0x3D, 0xF4, + 0x74, 0xCF, 0x84, 0x17, 0xCF, 0x7F, 0xE0, 0x20, + 0x5F, 0x7B, 0xFB, 0xD6, 0x0E, 0x1B, 0x65, 0xA5, + 0x00, 0xDC, 0x6A, 0xE3, 0x7E, 0xCE, 0x4B, 0xCE, + 0x68, 0x22, 0xB8, 0xD7, 0xAE, 0x33, 0x50, 0x9C, + 0x14, 0x46, 0xFA, 0x14, 0x85, 0x35, 0x48, 0x78, + 0xF8, 0x23, 0xA3, 0x8E, 0x56, 0x77, 0x39, 0xFA, + 0x76, 0xA5, 0x91, 0xB4, 0x34, 0xE1, 0x4D, 0xA8, + 0x35, 0x1E, 0x9E, 0xB3, 0x6B, 0x6A, 0x3A, 0xF9, + 0xD4, 0x0D, 0x9A, 0xD9, 0x02, 0xF4, 0x94, 0x54, + 0x1F, 0xE6, 0x5B, 0x8C, 0x72, 0xC9, 0xA3, 0xEB, + 0x69, 0x32, 0x04, 0x1C, 0x43, 0x69, 0xF9, 0x3F, + 0xBE, 0x65, 0xF6, 0xFE, 0x03, 0x9E, 0xF4, 0x29, + 0x59, 0x82, 0x02, 0x2F, 0xF7, 0x67, 0x66, 0xA6, + 0x03, 0x22, 0x6B, 0x27, 0x19, 0xBA, 0xCA, 0x2A, + 0xAA, 0x7D, 0xC1, 0x08, 0xF6, 0x63, 0xA2, 0x53, + 0xD0, 0xBA, 0x3E, 0x51, 0xAC, 0x38, 0x70, 0xAD, + 0xDD, 0x06, 0x86, 0xAB, 0x73, 0xF2, 0xA1, 0x62, + 0xC3, 0x2C, 0x99, 0xDC, 0x47, 0xEA, 0x7A, 0xBA, + 0x3A, 0xE1, 0x61, 0x4C, 0x94, 0xA6, 0xC4, 0x09, + 0x85, 0x45, 0x73, 0x9F, 0x43, 0xA5, 0xDD, 0x1A, + 0x96, 0x48, 0xF2, 0x98, 0x02, 0xA0, 0xCE, 0x12, + 0x95, 0x74, 0x86, 0x58, 0x44, 0x75, 0x27, 0xE3, + 0x63, 0x0A, 0xB7, 0xA5, 0xBF, 0x0B, 0x6A, 0x9D, + 0xA6, 0x71, 0xF0, 0x20, 0xE9, 0x64, 0x0F, 0x08, + 0x33, 0xE4, 0x6F, 0x0F, 0x11, 0xA0, 0xC0, 0x37, + 0x8B, 0x54, 0x25, 0xF2, 0x2B, 0xA6, 0xCD, 0xA0, + 0x23, 0x45, 0xF0, 0xF9, 0x99, 0x01, 0xCB, 0x6D, + 0xB7, 0x3F, 0x82, 0x99, 0x0A, 0xFE, 0x2C, 0x28, + 0x29, 0xA4, 0x85, 0x15, 0x60, 0xD5, 0x08, 0xCD, + 0x68, 0x04, 0x9A, 0xFA, 0x39, 0x5B, 0x99, 0x35, + 0x15, 0x0A, 0xFD, 0x51, 0x4F, 0x3F, 0x85, 0x97, + 0xE5, 0x23, 0x17, 0xBB, 0xA7, 0x56, 0xF6, 0xB5, + 0x74, 0x5F, 0x06, 0x9A, 0xA2, 0xF1, 0xB0, 0xFA, + 0x94, 0xBF, 0xC7, 0x38, 0x22, 0xCF, 0x2D, 0xEB, + 0x68, 0xB3, 0xC7, 0x09, 0xBD, 0xC7, 0x65, 0x67, + 0xFB, 0x5D, 0xD1, 0x71, 0x6B, 0xD7, 0xB7, 0xA5, + 0x37, 0xE5, 0x7E, 0x19, 0x16, 0x1A, 0x7B, 0xB7, + 0x15, 0xD3, 0x95, 0xF9, 0x21, 0x91, 0xC7, 0x46, + 0xC6, 0xAC, 0x2F, 0x40, 0x20, 0x9B, 0x77, 0xDC, + 0xFE, 0x84, 0x52, 0x94, 0xE7, 0xF2, 0x28, 0xC8, + 0xE5, 0x3C, 0x2F, 0xEF, 0x12, 0xBF, 0x2F, 0xEF, + 0x6F, 0xB4, 0x34, 0x19, 0xC1, 0xD0, 0x86, 0x45, + 0x74, 0x98, 0x2D, 0x8C, 0x56, 0x43, 0x75, 0x90, + 0xA1, 0x43, 0xF6, 0xBA, 0x48, 0x58, 0x99, 0x61, + 0xE2, 0xF4, 0x40, 0x89, 0x04, 0x91, 0x40, 0xBB, + 0x38, 0xC3, 0x4F, 0x83, 0x99, 0xEA, 0x9A, 0xFB, + 0x41, 0x99, 0x23, 0x4D, 0xBC, 0x0F, 0x46, 0x95, + 0x3C, 0xC4, 0x5B, 0x04, 0xF9, 0x1D, 0x58, 0x29, + 0x94, 0x4C, 0xCA, 0x9C, 0xE4, 0x96, 0x35, 0xE5, + 0xC4, 0x23, 0x96, 0xDF, 0x54, 0xC1, 0xAD, 0x64, + 0xD4, 0x35, 0x23, 0x7D, 0x66, 0xC6, 0xBD, 0xE4, + 0x4D, 0x95, 0x68, 0x37, 0x89, 0xA0, 0x36, 0x5B, + 0xD8, 0xB1, 0xA7, 0x6E, 0x9A, 0x66, 0x23, 0x41, + 0xE9, 0x93, 0x1B, 0x74, 0x1D, 0x92, 0xF1, 0xF3, + 0xB0, 0x4F, 0x5C, 0x60, 0x9D, 0x9C, 0xBD, 0x7E, + 0xCE, 0x2F, 0x39, 0xF4, 0x6C, 0xDF, 0x8D, 0x8E, + 0x2A, 0x3C, 0x89, 0xC0, 0x4A, 0xDF, 0x0E, 0x8D, + 0x0E, 0xE5, 0x69, 0xA5, 0xDC, 0x2E, 0x4D, 0x40, + 0xC3, 0xFD, 0x18, 0x51, 0x38, 0xCD, 0xAE, 0x5E, + 0xE4, 0x9F, 0x88, 0xA0, 0x7B, 0x06, 0x65, 0x40, + 0x92, 0x6C, 0x6B, 0x40, 0x9B, 0x1B, 0x41, 0x21, + 0x00, 0x9D, 0x28, 0x89, 0x52, 0xC7, 0xF5, 0x10, + 0xA0, 0x51, 0x47, 0x36, 0x1E, 0xAE, 0xF8, 0x79, + 0xF9, 0x07, 0x94, 0xF8, 0xA1, 0x58, 0x3B, 0x6A, + 0xD9, 0x01, 0x16, 0x32, 0xE9, 0xF0, 0xC9, 0x80, + 0x09, 0xCF, 0x89, 0xE5, 0x3D, 0x8D, 0xDB, 0x5A, + 0xDA, 0x30, 0xB3, 0xDC, 0x08, 0x9F, 0xC7, 0x04, + 0xD5, 0x44, 0xF1, 0x0F, 0xD4, 0x6C, 0x6E, 0x0F, + 0xFF, 0x2F, 0x10, 0x6A, 0xFA, 0x4C, 0xFD, 0x76, + 0xF5, 0x22, 0xFE, 0x9E, 0x41, 0x73, 0xDA, 0xE6, + 0x70, 0xA3, 0x1F, 0x55, 0xD4, 0x6C, 0xA1, 0x63, + 0x06, 0x1C, 0x8C, 0xCD, 0x1F, 0xB2, 0x22, 0x88, + 0x4B, 0x22, 0x87, 0xE0, 0xAA, 0x1E, 0x7E, 0xA8, + 0x13, 0xC3, 0x13, 0x06, 0xCE, 0xBC, 0xC8, 0xF4, + 0x22, 0x55, 0xE9, 0x27, 0xBC, 0x04, 0x46, 0x85, + 0x08, 0xF3, 0x64, 0x0C, 0xC9, 0x89, 0xE5, 0x2E, + 0x2C, 0xF4, 0x4F, 0xE1, 0x1A, 0x77, 0x00, 0xA8, + 0x27, 0x6E, 0xD5, 0xB9, 0x6D, 0xCF, 0xB9, 0x50, + 0xDE, 0x0E, 0x11, 0xDF, 0x4A, 0xFA, 0xDC, 0x1C, + 0x9C, 0x4B, 0xFF, 0x53, 0xAB, 0x1B, 0xD9, 0x0A, + 0x82, 0x9B, 0x48, 0x84, 0xD0, 0x7A, 0xFF, 0xD5, + 0x73, 0xB5, 0xF3, 0xF5, 0x6E, 0x0C, 0x68, 0xA8, + 0x4E, 0x88, 0x02, 0xD6, 0x2C, 0x31, 0x52, 0x77, + 0x13, 0xEE, 0xF8, 0x74, 0xD8, 0x0E, 0x70, 0x91, + 0xA0, 0x37, 0x82, 0x1C, 0xCF, 0x7F, 0x39, 0xD6, + 0x51, 0xF8, 0x05, 0x69, 0xBD, 0x07, 0xC2, 0x68, + 0xCD, 0x1A, 0x94, 0x6A, 0x91, 0xFF, 0x5F, 0xBF, + 0x3F, 0x76, 0xA5, 0x69, 0x33, 0xC0, 0xA8, 0x2E, + 0xAD, 0x76, 0x62, 0x1D, 0xC2, 0xFE, 0xE4, 0x56, + 0x92, 0x49, 0x5D, 0x22, 0xFD, 0xE8, 0x6E, 0x88, + 0x04, 0xCD, 0x66, 0xFA, 0x90, 0x33, 0x5B, 0xF1, + 0x32, 0xFF, 0x82, 0xE9, 0xF3, 0x47, 0x27, 0x25, + 0x69, 0x49, 0xE9, 0xB9, 0x66, 0x34, 0x57, 0x9A, + 0x98, 0x67, 0x50, 0x2B, 0x9D, 0x7D, 0x8F, 0x42, + 0xC2, 0x0F, 0x30, 0x50, 0x84, 0x26, 0x4D, 0x74, + 0x06, 0x90, 0x26, 0xCC, 0x04, 0xB4, 0x56, 0x5F, + 0x26, 0xAB, 0x85, 0x1C, 0x7C, 0xEE, 0x23, 0xE0, + 0x85, 0x83, 0x13, 0xDF, 0x97, 0x53, 0x38, 0x61, + 0xB7, 0x85, 0x39, 0x59, 0x8A, 0x36, 0x1A, 0x38, + 0x9B, 0x9D, 0xF9, 0x37, 0x9B, 0xF1, 0x42, 0x42, + 0xE2, 0x39, 0x2D, 0x52, 0x82, 0xD0, 0xD5, 0xB5, + 0x47, 0xC1, 0x09, 0xA7, 0x3C, 0x84, 0xF2, 0x78, + 0x0A, 0xDD, 0x05, 0x8B, 0x17, 0xA7, 0x65, 0xB6, + 0x3E, 0x00, 0x69, 0x23, 0x7D, 0x08, 0x97, 0x7A, + 0xFD, 0x2A, 0x93, 0x3F, 0xC7, 0x77, 0xB5, 0x66, + 0xEE, 0xB7, 0x64, 0xA8, 0x66, 0x4C, 0xDF, 0x7A, + 0x24, 0xD9, 0x72, 0xEE, 0x3A, 0x88, 0xAE, 0xA6, + 0xD9, 0xBA, 0x2E, 0xEF, 0x34, 0x21, 0x99, 0x7F, + 0x5F, 0x14, 0xD6, 0xDC, 0x1D, 0x8A, 0xE6, 0x2D, + 0x7F, 0x87, 0xEC, 0x42, 0x38, 0xFC, 0x56, 0x55, + 0x15, 0xEE, 0x58, 0xE6, 0x5B, 0x4B, 0x89, 0x5A, + 0xD2, 0x7B, 0x91, 0x83, 0xE7, 0x0D, 0x07, 0x24, + 0xA8, 0x1E, 0x7A, 0x58, 0x80, 0x92, 0xE1, 0x29, + 0x4C, 0x4D, 0xDD, 0x37, 0xE6, 0x56, 0x3A, 0x85, + 0x09, 0x86, 0x72, 0x5D, 0x8D, 0x57, 0x74, 0x46, + 0x82, 0x59, 0x5D, 0x22, 0xF1, 0xDD, 0xF6, 0x84, + 0x50, 0x77, 0xCD, 0x5B, 0x8F, 0xB7, 0x55, 0xD1, + 0x51, 0x6F, 0x01, 0x4B, 0x01, 0xA5, 0x39, 0x6B, + 0x22, 0x08, 0x2C, 0x14, 0x30, 0xA2, 0xC1, 0x0C, + 0xAC, 0x56, 0xE4, 0x95, 0xBD, 0x20, 0x47, 0x01, + 0x5E, 0x7A, 0x6E, 0x16, 0x32, 0x94, 0x2E, 0x06, + 0x8A, 0xD9, 0xED, 0xC5, 0x1D, 0x1B, 0xC1, 0x11, + 0x9D, 0xBC, 0x2F, 0x95, 0x6B, 0xF9, 0x8D, 0xB1, + 0x13, 0x0A, 0x4D, 0x03, 0x8F, 0xC3, 0xA5, 0xF8, + 0x87, 0x39, 0x5A, 0x10, 0xE5, 0x52, 0x74, 0x48, + 0x37, 0xEC, 0x6C, 0x41, 0x99, 0x78, 0x2D, 0xEE, + 0x36, 0xE8, 0x1C, 0xD0, 0xF8, 0x02, 0x27, 0xD5, + 0x51, 0x0A, 0x9A, 0xD5, 0x3C, 0xAA, 0x89, 0x7A, + 0x9B, 0x0A, 0xBF, 0xA2, 0x31, 0x82, 0xEE, 0x86, + 0x20, 0x98, 0x01, 0x0B, 0x50, 0xFE, 0x92, 0x21, + 0x33, 0xCD, 0xA5, 0x09, 0xF1, 0x41, 0xB3, 0x15, + 0x35, 0xDC, 0x2E, 0xC2, 0xA8, 0x1D, 0x70, 0x12, + 0x95, 0x4E, 0x48, 0x95, 0x49, 0x49, 0x81, 0xD2, + 0xF0, 0x6C, 0xDA, 0xAB, 0x83, 0x2E, 0xBE, 0x72, + 0xE1, 0x7C, 0xCA, 0xA6, 0x72, 0xF1, 0xA3, 0x27, + 0x27, 0xE1, 0xA7, 0xC7, 0x4C, 0x3E, 0x7B, 0x65, + 0x25, 0xDE, 0x68, 0xC6, 0x78, 0x68, 0xCE, 0xFD, + 0x82, 0x59, 0xD9, 0xF4, 0x2C, 0xAD, 0x80, 0x43, + 0xE2, 0x77, 0xC2, 0x87, 0x4C, 0xE1, 0x71, 0xB1, + 0x31, 0xEA, 0x6A, 0x47, 0x9F, 0xBE, 0xEB, 0x28, + 0x30, 0xE2, 0xD8, 0x1D, 0x67, 0xFE, 0x43, 0x23, + 0x03, 0xCC, 0x5C, 0x0A, 0xD0, 0x05, 0x22, 0xC3, + 0x5E, 0x75, 0xF5, 0xD8, 0x00, 0x11, 0x21, 0xE2, + 0x43, 0xD1, 0x64, 0x39, 0xD2, 0x61, 0x90, 0x1F, + 0x9C, 0xC6, 0x21, 0x4E, 0x1F, 0x86, 0xCF, 0x0C, + 0x25, 0xA7, 0x0C, 0x90, 0x48, 0xF8, 0xAE, 0x2F, + 0xAF, 0x55, 0xB1, 0xDE, 0x8E, 0x1C, 0xBB, 0x13, + 0x8E, 0xF4, 0x11, 0x7E, 0x43, 0xBE, 0xF6, 0xA7, + 0x73, 0xAB, 0xDC, 0xE5, 0x3E, 0x3F, 0x09, 0xCA, + 0xE2, 0x1B, 0x15, 0x72, 0x6A, 0x70, 0x00, 0x50, + 0x4A, 0x81, 0x87, 0x71, 0x3A, 0x13, 0x51, 0xB4, + 0xFA, 0x04, 0xAF, 0x33, 0xEB, 0x5B, 0x0D, 0x8C, + 0x0C, 0x76, 0x93, 0xFC, 0x41, 0xB6, 0xFE, 0xDF, + 0x08, 0xD0, 0x27, 0x78, 0xA3, 0x22, 0x10, 0xD3, + 0x5F, 0x88, 0xE6, 0xA9, 0x80, 0x66, 0x05, 0x72, + 0x9F, 0x66, 0x6D, 0x0E, 0x1E, 0xAA, 0x03, 0xCC, + 0xE1, 0x38, 0x0F, 0x3B, 0xE0, 0xB0, 0x4D, 0xAD, + 0xB4, 0x4C, 0x73, 0x1B, 0xA6, 0x13, 0x73, 0x02, + 0xDB, 0x03, 0x1D, 0x52, 0x86, 0x34, 0xE4, 0x8E, + 0x2E, 0x5C, 0xC9, 0xB8, 0x90, 0x2C, 0x47, 0x41, + 0x37, 0x13, 0x93, 0xBE, 0x66, 0xCA, 0x62, 0x25, + 0x37, 0xE8, 0x7F, 0x49, 0x92, 0x3F, 0xAF, 0xC2, + 0x40, 0x3E, 0x4E, 0x07, 0xF2, 0x48, 0x35, 0x05, + 0x85, 0x5E, 0xDE, 0xF3, 0x2B, 0xDA, 0xE1, 0x22, + 0x93, 0x14, 0xA1, 0x45, 0xD9, 0xE0, 0x02, 0xFB, + 0x3F, 0xF9, 0xBF, 0xD3, 0x0B, 0xBB, 0xED, 0x6C, + 0xEC, 0x95, 0xE1, 0x9D, 0x60, 0xAB, 0xEB, 0xBA, + 0x61, 0xB9, 0x87, 0x69, 0x38, 0xC1, 0xBC, 0x8C, + 0x0C, 0xD7, 0x57, 0x7A, 0xA2, 0xAF, 0xCD, 0x2C, + 0xF1, 0x29, 0xB7, 0xD9, 0x0D, 0x31, 0xDA, 0xB8, + 0x1D, 0x8C, 0x12, 0xFF, 0x79, 0xCA, 0x38, 0x3A, + 0xAA, 0xE8, 0x0C, 0xF9, 0x63, 0x5A, 0x58, 0x14, + 0x97, 0x75, 0x51, 0x20, 0x08, 0xB8, 0xEE, 0x6F, + 0xEF, 0x05, 0xEE, 0x81, 0x61, 0xD2, 0x00, 0xD3, + 0x4B, 0x9C, 0x36, 0x5D, 0x6E, 0xC4, 0x35, 0xAA, + 0x29, 0x32, 0x2F, 0x63, 0x19, 0xFA, 0x82, 0x82, + 0x22, 0xF9, 0xD7, 0xB2, 0xE8, 0x4B, 0x2D, 0x4F, + 0x0C, 0xC7, 0xEB, 0x0F, 0x5E, 0x9D, 0x18, 0xAB, + 0x0B, 0x62, 0xC7, 0xB3, 0x7C, 0x27, 0x49, 0x31, + 0x22, 0x75, 0x58, 0xBC, 0x6F, 0x72, 0x10, 0x30, + 0xB8, 0x63, 0xF8, 0x9E, 0x5B, 0x1B, 0x77, 0xB5, + 0x28, 0x03, 0x83, 0xAE, 0x76, 0xF7, 0xCA, 0x09, + 0xB1, 0x69, 0x6D, 0x13, 0xDF, 0xA7, 0x64, 0x0C, + 0xAF, 0xBE, 0xB3, 0x66, 0x1D, 0x0A, 0x51, 0xC0, + 0xE0, 0xA0, 0xD6, 0x38, 0xF3, 0x5B, 0xA2, 0xC1, + 0x56, 0xE5, 0x78, 0xD6, 0xA6, 0xE9, 0x68, 0xC8, + 0x4B, 0x68, 0x6D, 0xC1, 0x39, 0x89, 0x3B, 0xE8, + 0x70, 0x1A, 0xE6, 0x89, 0xB1, 0xDC, 0xAC, 0x9E, + 0x75, 0x0E, 0x6A, 0x55, 0x95, 0xE5, 0xA5, 0x65, + 0x47, 0xB7, 0x81, 0x2D, 0xD5, 0x65, 0xC5, 0xAF, + 0x3F, 0x46, 0x9B, 0x77, 0xE9, 0x58, 0x38, 0x5A, + 0x19, 0xD2, 0xC1, 0xC3, 0x3B, 0x4B, 0x0B, 0xCB, + 0xDA, 0x5E, 0xEB, 0x05, 0xCE, 0x78, 0x80, 0x49, + 0x6B, 0x73, 0xD5, 0x23, 0x73, 0x4A, 0x59, 0x7C, + 0x97, 0x6C, 0x52, 0xBD, 0xC8, 0x7A, 0xFA, 0x32, + 0xB2, 0x74, 0x32, 0x5E, 0x86, 0x36, 0x60, 0xE1, + 0x61, 0xF8, 0xE6, 0x75, 0x3C, 0xED, 0x8E, 0xFF, + 0x22, 0xFA, 0x7D, 0x5B, 0x80, 0x88, 0xE3, 0xE1, + 0x7A, 0xB9, 0x03, 0x42, 0x4A, 0x36, 0x76, 0x74, + 0xAF, 0x6C, 0x1A, 0x56, 0x8E, 0x9C, 0xDF, 0xBF, + 0x96, 0xF6, 0x80, 0xCC, 0x14, 0x26, 0x65, 0x05, + 0x45, 0xBE, 0x08, 0xF4, 0xA4, 0x04, 0xF6, 0x97, + 0x17, 0x5C, 0x62, 0x2E, 0x74, 0xA7, 0x67, 0x67, + 0xC7, 0x1C, 0x88, 0xC7, 0x9F, 0xEF, 0xAF, 0x6F, + 0xAF, 0x56, 0xF0, 0xDE, 0xA2, 0x12, 0x32, 0xD0, + 0x70, 0x89, 0x5C, 0xB0, 0x75, 0x35, 0x63, 0xE2, + 0x62, 0xDF, 0x5D, 0x39, 0x63, 0xD0, 0x97, 0x95, + 0x16, 0xEB, 0x3B, 0x6F, 0xBD, 0xA0, 0xC2, 0xBF, + 0x3C, 0x2A, 0x98, 0x51, 0x56, 0xC4, 0xB9, 0x89, + 0xA1, 0x29, 0x2D, 0xE1, 0xC2, 0xC2, 0x6E, 0xBE, + 0xFC, 0x64, 0xF4, 0x58, 0xA0, 0x10, 0xE2, 0x28, + 0xA4, 0xBF, 0x29, 0x45, 0x2D, 0x04, 0x74, 0x26, + 0xEC, 0x3B, 0x90, 0x0C, 0xD4, 0x64, 0x1E, 0xDF, + 0x5F, 0x84, 0x32, 0x5E, 0x86, 0x36, 0xB6, 0x7B, + 0xF9, 0x42, 0xF0, 0x9D, 0x45, 0xF5, 0x95, 0x55, + 0xD5, 0x0E, 0x14, 0x76, 0xAC, 0x7C, 0x00, 0xC0, + 0x48, 0x93, 0x58, 0x30, 0x96, 0x22, 0x7E, 0xAC, + 0x2E, 0x95, 0xBB, 0xC5, 0x1F, 0xCF, 0x03, 0xD1, + 0x53, 0xE8, 0xC2, 0xBD, 0x67, 0xB7, 0xFF, 0x2C, + 0xAE, 0x15, 0xEB, 0x93, 0x4B, 0x9B, 0xB7, 0x63, + 0xE3, 0x58, 0x9E, 0xE6, 0x3E, 0xEE, 0xBA, 0x7A, + 0xFA, 0x21, 0x97, 0xFB, 0x23, 0x93, 0xF3, 0x33, + 0xB3, 0x68, 0xDE, 0xB2, 0x6A, 0xDA, 0x92, 0x5B, + 0xDB, 0x60, 0xF2, 0x97, 0x4F, 0x9F, 0xEF, 0x1F, + 0x9D, 0x46, 0x70, 0x08, 0xD0, 0x00, 0x30, 0xF1, + 0x71, 0xAA, 0xA0, 0xCB, 0x13, 0xC3, 0x0B, 0xC6, + 0x44, 0xFF, 0x35, 0x5E, 0x86, 0x56, 0x8E, 0x43, + 0xC1, 0x7A, 0xF0, 0x94, 0x4C, 0x9C, 0xEC, 0x22, + 0xA0, 0x1B, 0x65, 0x07, 0xDD, 0x0D, 0x05, 0xD1, + 0x51, 0xEA, 0xD0, 0xB3, 0x69, 0xB9, 0xB1, 0x60, + 0xE2, 0x59, 0x57, 0x33, 0xEB, 0x3B, 0x83, 0x52, + 0xD0, 0x6B, 0xD1, 0xAF, 0x75, 0xA5, 0x45, 0x97, + 0x15, 0xAE, 0xF0, 0x9A, 0x42, 0x92, 0x1E, 0xCD, + 0x4F, 0xF4, 0x02, 0x64, 0xBC, 0x6C, 0x3A, 0xBB, + 0x3B, 0x61, 0xC8, 0xA1, 0xC8, 0x65, 0x00, 0xCC, + 0x16, 0x5C, 0xF4, 0x9D, 0xE7, 0x1C, 0x7C, 0x35, + 0xBC, 0x42, 0xF7, 0x9B, 0xA6, 0x15, 0x75, 0x10, + 0x95, 0x4E, 0x9D, 0xF9, 0x21, 0xF4, 0x90, 0x50, + 0xB5, 0x67, 0xD1, 0x58, 0x80, 0x30, 0xF1, 0x11, + 0x94, 0xFE, 0x69, 0x00, 0xFD, 0xF9, 0xBE, 0x63, + 0x13, 0xC8, 0x48, 0x65, 0xBD, 0x3C, 0x7E, 0xBB, + 0x1A, 0xE2, 0x51, 0x14, 0xDF, 0x72, 0xE2, 0x22, + 0xA2, 0x79, 0xF9, 0xD4, 0x0C, 0x8D, 0xC9, 0x0C, + 0xAD, 0x53, 0xE0, 0xA5, 0xAE, 0x03, 0x93, 0x53, + 0xD3, 0x08, 0x88, 0xA5, 0x7D, 0xFC, 0xBA, 0x7F, + 0xDE, 0x22, 0x91, 0xD4, 0x4F, 0xE2, 0x72, 0xB2, + 0x32, 0xE9, 0x69, 0x44, 0x9C, 0x1D, 0x59, 0x9C, + 0x3D, 0xCE, 0x7D, 0x38, 0x73, 0xDE, 0x4E, 0x8E, + 0x0E, 0xD5, 0x55, 0x78, 0xA0, 0x81, 0xC8, 0x0D, + 0x81, 0x52, 0x66, 0x43, 0x9B, 0x4E, 0x2F, 0xEF, + 0xCE, 0x3E, 0x8D, 0x50, 0xAE, 0x1B, 0xBA, 0x50, + 0xD5, 0xC7, 0x7A, 0xBF, 0x3C, 0x91, 0x01, 0xC1, + 0x41, 0x9A, 0x1A, 0x37, 0xEF, 0x6E, 0x22, 0xE7, + 0x46, 0xB0, 0x03, 0x46, 0x8D, 0x20, 0xB0, 0x70, + 0xF0, 0x2B, 0xAB, 0x86, 0x5E, 0x6F, 0x21, 0xE4, + 0x55, 0xAC, 0x1F, 0x52, 0xA5, 0x10, 0x59, 0xBA, + 0xB3, 0x3B, 0x90, 0x0C, 0xD4, 0x64, 0x32, 0xB3, + 0x33, 0x79, 0xFF, 0x96, 0xCF, 0x4E, 0x2B, 0x62, + 0xCB, 0x75, 0xC3, 0xAF, 0x6A, 0x2A, 0x7C, 0xFD, + 0x7D, 0x07, 0x83, 0xEA, 0x80, 0x90, 0x7C, 0x14, + 0x9E, 0x65, 0xB2, 0xDE, 0x8E, 0x14, 0xCE, 0xB4, + 0xA8, 0x6B, 0xD1, 0xA1, 0x75, 0x48, 0xCA, 0x20, + 0x88, 0x93, 0x05, 0x69, 0x63, 0x9D, 0xF1, 0xF3, + 0x38, 0xC4, 0x57, 0x3A, 0xC6, 0x56, 0xD0, 0x03, + 0x93, 0x68, 0xDE, 0xAF, 0x87, 0x37, 0x57, 0x97, + 0x17, 0xCC, 0x7A, 0x16, 0xCE, 0x7E, 0x1E, 0xDE, + 0x5E, 0x85, 0x32, 0x5E, 0x82, 0x32, 0x9E, 0x4A, + 0xC8, 0x73, }; static unsigned char vfs5011_init_04[] = { /* 2221 B */ - 0x02, 0x20, 0x01, 0x01, 0x00, 0x03, 0x00, 0x09, - 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, - 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xAD, 0x01, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, - 0x20, 0x04, 0x30, 0xAD, 0x01, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, - 0xAD, 0x01, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x4C, 0x20, 0x04, 0x30, 0xFF, 0x03, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, - 0x04, 0x30, 0x00, 0x00, 0x50, 0x03, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x54, 0x20, 0x04, 0x30, 0x01, - 0x3E, 0x02, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x00, 0x21, 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x08, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x0C, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x10, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x14, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x1C, 0x21, 0x04, 0x30, 0x12, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x20, 0x21, 0x04, 0x30, 0x04, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x40, 0x21, 0x04, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x44, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x48, - 0x21, 0x04, 0x30, 0x10, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x4C, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x50, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x21, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x58, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x5C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x60, 0x21, 0x04, - 0x30, 0x0F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x80, 0x21, 0x04, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x84, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x88, 0x21, 0x04, 0x30, - 0x10, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x8C, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x90, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x94, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x98, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x9C, 0x21, 0x04, - 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xA0, 0x21, 0x04, 0x30, 0x0F, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC0, - 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xC4, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xC8, 0x21, 0x04, 0x30, 0x10, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xCC, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xD0, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xD4, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xD8, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xDC, 0x21, 0x04, 0x30, 0x1F, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xE0, - 0x21, 0x04, 0x30, 0x0F, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xA0, 0x20, 0x04, 0x30, - 0xEF, 0xE1, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xA4, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA8, 0x20, - 0x04, 0x30, 0xFE, 0x21, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xC4, 0x20, 0x04, 0x30, 0x47, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, - 0x00, 0x00, 0x38, 0x00, 0x08, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, - 0x00, 0x12, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, - 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, - 0x0C, 0x8A, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, - 0xFF, 0xF9, 0x87, 0x20, 0x83, 0x48, 0x84, 0x20, - 0x83, 0x48, 0x84, 0x20, 0x83, 0x48, 0x84, 0x20, - 0x83, 0x48, 0x84, 0x20, 0x83, 0x48, 0x84, 0x20, - 0x83, 0x48, 0x84, 0x20, 0x83, 0x48, 0x84, 0x20, - 0x83, 0x48, 0x84, 0x20, 0x83, 0x48, 0x84, 0x20, - 0x83, 0x48, 0x84, 0x20, 0x85, 0x48, 0x04, 0x20, - 0x87, 0x48, 0x04, 0x20, 0x89, 0x48, 0x04, 0x20, - 0x8B, 0x48, 0x04, 0x20, 0x8D, 0x48, 0x04, 0x20, - 0x8F, 0x48, 0x04, 0x20, 0x91, 0x48, 0x04, 0x20, - 0x93, 0x48, 0x04, 0x20, 0x95, 0x48, 0x04, 0x20, - 0x97, 0x48, 0x04, 0x20, 0x99, 0x48, 0x04, 0x20, - 0x9B, 0x48, 0x04, 0x20, 0x9D, 0x48, 0x04, 0x20, - 0x9F, 0x48, 0x04, 0x20, 0xA1, 0x48, 0x04, 0x20, - 0xA3, 0x48, 0x04, 0x20, 0xA3, 0x48, 0x04, 0x00, - 0x85, 0x5A, 0x04, 0x20, 0x87, 0x5A, 0x04, 0x20, - 0x89, 0x5A, 0x04, 0x20, 0x8B, 0x5A, 0x04, 0x20, - 0x8D, 0x5A, 0x04, 0x20, 0x8F, 0x5A, 0x04, 0x20, - 0x91, 0x5A, 0x04, 0x20, 0x93, 0x5A, 0x04, 0x20, - 0x95, 0x5A, 0x04, 0x20, 0x97, 0x5A, 0x04, 0x20, - 0x99, 0x5A, 0x04, 0x20, 0x9B, 0x5A, 0x04, 0x20, - 0x9D, 0x5A, 0x04, 0x20, 0x9F, 0x5A, 0x04, 0x20, - 0xA1, 0x5A, 0x04, 0x20, 0xA3, 0x5A, 0x04, 0x20, - 0xA3, 0x5A, 0x04, 0x00, 0x85, 0x6C, 0x04, 0x20, - 0x87, 0x6C, 0x04, 0x20, 0x89, 0x6C, 0x04, 0x20, - 0x8B, 0x6C, 0x04, 0x20, 0x8D, 0x6C, 0x04, 0x20, - 0x8F, 0x6C, 0x04, 0x20, 0x91, 0x6C, 0x04, 0x20, - 0x93, 0x6C, 0x04, 0x20, 0x95, 0x6C, 0x04, 0x20, - 0x97, 0x6C, 0x04, 0x20, 0x99, 0x6C, 0x04, 0x20, - 0x9B, 0x6C, 0x04, 0x20, 0x9D, 0x6C, 0x04, 0x20, - 0x9F, 0x6C, 0x04, 0x20, 0xA1, 0x6C, 0x04, 0x20, - 0xA3, 0x6C, 0x04, 0x20, 0xA3, 0x6C, 0x04, 0x00, - 0x86, 0x48, 0x04, 0x20, 0x88, 0x48, 0x04, 0x20, - 0x8A, 0x48, 0x04, 0x20, 0x8C, 0x48, 0x04, 0x20, - 0x8E, 0x48, 0x04, 0x20, 0x90, 0x48, 0x04, 0x20, - 0x92, 0x48, 0x04, 0x20, 0xF7, 0x48, 0x04, 0x20, - 0xF9, 0x48, 0x04, 0x20, 0xFB, 0x48, 0x04, 0x20, - 0xFD, 0x48, 0x04, 0x20, 0xFF, 0x48, 0x04, 0x20, - 0x01, 0x49, 0x04, 0x20, 0x03, 0x49, 0x04, 0x20, - 0x05, 0x49, 0x04, 0x20, 0x07, 0x49, 0x04, 0x20, - 0x07, 0x49, 0x04, 0x00, 0x86, 0x5A, 0x04, 0x20, - 0x88, 0x5A, 0x04, 0x20, 0x8A, 0x5A, 0x04, 0x20, - 0x8C, 0x5A, 0x04, 0x20, 0x8E, 0x5A, 0x04, 0x20, - 0x90, 0x5A, 0x04, 0x20, 0x92, 0x5A, 0x04, 0x20, - 0xF7, 0x5A, 0x04, 0x20, 0xF9, 0x5A, 0x04, 0x20, - 0xFB, 0x5A, 0x04, 0x20, 0xFD, 0x5A, 0x04, 0x20, - 0xFF, 0x5A, 0x04, 0x20, 0x01, 0x5B, 0x04, 0x20, - 0x03, 0x5B, 0x04, 0x20, 0x05, 0x5B, 0x04, 0x20, - 0x07, 0x5B, 0x04, 0x20, 0x07, 0x5B, 0x04, 0x00, - 0x86, 0x6C, 0x04, 0x20, 0x88, 0x6C, 0x04, 0x20, - 0x8A, 0x6C, 0x04, 0x20, 0x8C, 0x6C, 0x04, 0x20, - 0x8E, 0x6C, 0x04, 0x20, 0x90, 0x6C, 0x04, 0x20, - 0x92, 0x6C, 0x04, 0x20, 0xF7, 0x6C, 0x04, 0x20, - 0xF9, 0x6C, 0x04, 0x20, 0xFB, 0x6C, 0x04, 0x20, - 0xFD, 0x6C, 0x04, 0x20, 0xFF, 0x6C, 0x04, 0x20, - 0x01, 0x6D, 0x04, 0x20, 0x03, 0x6D, 0x04, 0x20, - 0x05, 0x6D, 0x04, 0x20, 0x07, 0x6D, 0x04, 0x20, - 0x07, 0x6D, 0x04, 0x00, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, - 0x83, 0x68, 0x84, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x51, 0x09, - 0x10, 0x03, 0x51, 0x09, 0x03, 0x00, 0x09, 0x00, - 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, - 0x04, 0x15, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x28, 0x00, 0x00, + 0x02, 0x20, 0x01, 0x01, 0x00, 0x03, 0x00, 0x09, + 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, + 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xAD, 0x01, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, + 0x20, 0x04, 0x30, 0xAD, 0x01, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, + 0xAD, 0x01, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x4C, 0x20, 0x04, 0x30, 0xFF, 0x03, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, + 0x04, 0x30, 0x00, 0x00, 0x50, 0x03, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x54, 0x20, 0x04, 0x30, 0x01, + 0x3E, 0x02, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x00, 0x21, 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x08, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x0C, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x10, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x14, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x1C, 0x21, 0x04, 0x30, 0x12, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x20, 0x21, 0x04, 0x30, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x40, 0x21, 0x04, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x44, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x48, + 0x21, 0x04, 0x30, 0x10, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x4C, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x50, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x21, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x58, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x5C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x60, 0x21, 0x04, + 0x30, 0x0F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x80, 0x21, 0x04, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x84, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x88, 0x21, 0x04, 0x30, + 0x10, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x8C, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x90, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x94, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x98, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x9C, 0x21, 0x04, + 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xA0, 0x21, 0x04, 0x30, 0x0F, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC0, + 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xC4, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xC8, 0x21, 0x04, 0x30, 0x10, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xCC, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xD0, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xD4, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xD8, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xDC, 0x21, 0x04, 0x30, 0x1F, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xE0, + 0x21, 0x04, 0x30, 0x0F, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xA0, 0x20, 0x04, 0x30, + 0xEF, 0xE1, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xA4, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA8, 0x20, + 0x04, 0x30, 0xFE, 0x21, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xC4, 0x20, 0x04, 0x30, 0x47, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, + 0x00, 0x00, 0x38, 0x00, 0x08, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, + 0x00, 0x12, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, + 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, + 0x0C, 0x8A, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, + 0xFF, 0xF9, 0x87, 0x20, 0x83, 0x48, 0x84, 0x20, + 0x83, 0x48, 0x84, 0x20, 0x83, 0x48, 0x84, 0x20, + 0x83, 0x48, 0x84, 0x20, 0x83, 0x48, 0x84, 0x20, + 0x83, 0x48, 0x84, 0x20, 0x83, 0x48, 0x84, 0x20, + 0x83, 0x48, 0x84, 0x20, 0x83, 0x48, 0x84, 0x20, + 0x83, 0x48, 0x84, 0x20, 0x85, 0x48, 0x04, 0x20, + 0x87, 0x48, 0x04, 0x20, 0x89, 0x48, 0x04, 0x20, + 0x8B, 0x48, 0x04, 0x20, 0x8D, 0x48, 0x04, 0x20, + 0x8F, 0x48, 0x04, 0x20, 0x91, 0x48, 0x04, 0x20, + 0x93, 0x48, 0x04, 0x20, 0x95, 0x48, 0x04, 0x20, + 0x97, 0x48, 0x04, 0x20, 0x99, 0x48, 0x04, 0x20, + 0x9B, 0x48, 0x04, 0x20, 0x9D, 0x48, 0x04, 0x20, + 0x9F, 0x48, 0x04, 0x20, 0xA1, 0x48, 0x04, 0x20, + 0xA3, 0x48, 0x04, 0x20, 0xA3, 0x48, 0x04, 0x00, + 0x85, 0x5A, 0x04, 0x20, 0x87, 0x5A, 0x04, 0x20, + 0x89, 0x5A, 0x04, 0x20, 0x8B, 0x5A, 0x04, 0x20, + 0x8D, 0x5A, 0x04, 0x20, 0x8F, 0x5A, 0x04, 0x20, + 0x91, 0x5A, 0x04, 0x20, 0x93, 0x5A, 0x04, 0x20, + 0x95, 0x5A, 0x04, 0x20, 0x97, 0x5A, 0x04, 0x20, + 0x99, 0x5A, 0x04, 0x20, 0x9B, 0x5A, 0x04, 0x20, + 0x9D, 0x5A, 0x04, 0x20, 0x9F, 0x5A, 0x04, 0x20, + 0xA1, 0x5A, 0x04, 0x20, 0xA3, 0x5A, 0x04, 0x20, + 0xA3, 0x5A, 0x04, 0x00, 0x85, 0x6C, 0x04, 0x20, + 0x87, 0x6C, 0x04, 0x20, 0x89, 0x6C, 0x04, 0x20, + 0x8B, 0x6C, 0x04, 0x20, 0x8D, 0x6C, 0x04, 0x20, + 0x8F, 0x6C, 0x04, 0x20, 0x91, 0x6C, 0x04, 0x20, + 0x93, 0x6C, 0x04, 0x20, 0x95, 0x6C, 0x04, 0x20, + 0x97, 0x6C, 0x04, 0x20, 0x99, 0x6C, 0x04, 0x20, + 0x9B, 0x6C, 0x04, 0x20, 0x9D, 0x6C, 0x04, 0x20, + 0x9F, 0x6C, 0x04, 0x20, 0xA1, 0x6C, 0x04, 0x20, + 0xA3, 0x6C, 0x04, 0x20, 0xA3, 0x6C, 0x04, 0x00, + 0x86, 0x48, 0x04, 0x20, 0x88, 0x48, 0x04, 0x20, + 0x8A, 0x48, 0x04, 0x20, 0x8C, 0x48, 0x04, 0x20, + 0x8E, 0x48, 0x04, 0x20, 0x90, 0x48, 0x04, 0x20, + 0x92, 0x48, 0x04, 0x20, 0xF7, 0x48, 0x04, 0x20, + 0xF9, 0x48, 0x04, 0x20, 0xFB, 0x48, 0x04, 0x20, + 0xFD, 0x48, 0x04, 0x20, 0xFF, 0x48, 0x04, 0x20, + 0x01, 0x49, 0x04, 0x20, 0x03, 0x49, 0x04, 0x20, + 0x05, 0x49, 0x04, 0x20, 0x07, 0x49, 0x04, 0x20, + 0x07, 0x49, 0x04, 0x00, 0x86, 0x5A, 0x04, 0x20, + 0x88, 0x5A, 0x04, 0x20, 0x8A, 0x5A, 0x04, 0x20, + 0x8C, 0x5A, 0x04, 0x20, 0x8E, 0x5A, 0x04, 0x20, + 0x90, 0x5A, 0x04, 0x20, 0x92, 0x5A, 0x04, 0x20, + 0xF7, 0x5A, 0x04, 0x20, 0xF9, 0x5A, 0x04, 0x20, + 0xFB, 0x5A, 0x04, 0x20, 0xFD, 0x5A, 0x04, 0x20, + 0xFF, 0x5A, 0x04, 0x20, 0x01, 0x5B, 0x04, 0x20, + 0x03, 0x5B, 0x04, 0x20, 0x05, 0x5B, 0x04, 0x20, + 0x07, 0x5B, 0x04, 0x20, 0x07, 0x5B, 0x04, 0x00, + 0x86, 0x6C, 0x04, 0x20, 0x88, 0x6C, 0x04, 0x20, + 0x8A, 0x6C, 0x04, 0x20, 0x8C, 0x6C, 0x04, 0x20, + 0x8E, 0x6C, 0x04, 0x20, 0x90, 0x6C, 0x04, 0x20, + 0x92, 0x6C, 0x04, 0x20, 0xF7, 0x6C, 0x04, 0x20, + 0xF9, 0x6C, 0x04, 0x20, 0xFB, 0x6C, 0x04, 0x20, + 0xFD, 0x6C, 0x04, 0x20, 0xFF, 0x6C, 0x04, 0x20, + 0x01, 0x6D, 0x04, 0x20, 0x03, 0x6D, 0x04, 0x20, + 0x05, 0x6D, 0x04, 0x20, 0x07, 0x6D, 0x04, 0x20, + 0x07, 0x6D, 0x04, 0x00, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x83, 0x68, 0x84, 0x20, + 0x83, 0x68, 0x84, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x51, 0x09, + 0x10, 0x03, 0x51, 0x09, 0x03, 0x00, 0x09, 0x00, + 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, + 0x04, 0x15, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x28, 0x00, 0x00, }; static unsigned char vfs5011_init_05[] = { /* 2770 B */ - 0x06, 0x6B, 0x06, 0x6A, 0x76, 0xCC, 0x1C, 0xD0, - 0x50, 0xEB, 0x75, 0x10, 0xC8, 0x18, 0x5C, 0x95, - 0x15, 0xAE, 0xA8, 0xC8, 0x10, 0xC0, 0xB0, 0x7A, - 0xFA, 0x21, 0x96, 0xFA, 0x22, 0x92, 0xAE, 0x78, - 0xF8, 0x43, 0x05, 0x6E, 0xB6, 0x66, 0x62, 0xD5, - 0x51, 0xEA, 0xF0, 0xE5, 0x39, 0xE9, 0xA1, 0x19, - 0x9D, 0x26, 0x80, 0xE0, 0x38, 0xE8, 0x1C, 0xCA, - 0x4A, 0xF1, 0xBF, 0xD8, 0x00, 0xD0, 0x34, 0xD9, - 0x5D, 0xB6, 0x00, 0xF2, 0x2A, 0xA2, 0xAA, 0x7C, - 0xFC, 0x47, 0xDD, 0xB8, 0x60, 0xB0, 0xD0, 0xEF, - 0x6F, 0xB4, 0x46, 0x2C, 0xF4, 0x24, 0xBB, 0x7B, - 0x04, 0x20, 0x96, 0xC5, 0x1D, 0xAD, 0x32, 0x32, - 0x4D, 0x69, 0xDF, 0xA0, 0x7A, 0xAA, 0xB6, 0x60, - 0xE0, 0x5B, 0x89, 0xF6, 0x2C, 0xFC, 0x14, 0xC2, - 0x42, 0xF9, 0x23, 0x59, 0x81, 0x51, 0x31, 0xEF, - 0x6B, 0x80, 0x36, 0x52, 0x8A, 0x3A, 0x5A, 0x64, - 0x1B, 0xF7, 0xBD, 0xD4, 0x0C, 0xDC, 0xBC, 0x54, - 0xD0, 0x3B, 0x0D, 0x4C, 0x90, 0x10, 0x70, 0x90, - 0x14, 0xFF, 0x65, 0x29, 0xF5, 0x75, 0x55, 0xB5, - 0x31, 0xDA, 0x88, 0xC5, 0x19, 0x99, 0xF9, 0x39, - 0xB9, 0x5A, 0xD0, 0xBC, 0x64, 0xEC, 0x8C, 0xEC, - 0x6C, 0x8F, 0x05, 0xC9, 0x11, 0x99, 0xF9, 0x19, - 0x99, 0x7A, 0xC2, 0x8E, 0x56, 0xDE, 0xBE, 0x3E, - 0xBE, 0x5D, 0xE3, 0xCF, 0x17, 0x9F, 0xFF, 0x5F, - 0xDF, 0x3C, 0x82, 0x8E, 0x56, 0xDE, 0xBE, 0xFE, - 0x7E, 0x9D, 0x23, 0xCF, 0x17, 0x9F, 0xC9, 0x48, - 0xC8, 0xF6, 0x07, 0x4D, 0x04, 0x98, 0xFB, 0x9A, - 0x37, 0xEF, 0x55, 0x31, 0x60, 0xDA, 0x38, 0xB1, - 0x31, 0xF7, 0xB1, 0xDD, 0x05, 0xB5, 0xE3, 0x62, - 0xE2, 0x19, 0xCE, 0xA2, 0x5F, 0x11, 0x8E, 0x6E, - 0x08, 0xC0, 0x66, 0x2A, 0xF2, 0x4E, 0x24, 0x01, - 0xAA, 0x54, 0x43, 0x01, 0xDA, 0xDB, 0x94, 0x57, - 0xB2, 0x40, 0xDE, 0xAF, 0x87, 0x37, 0x61, 0xE0, - 0x60, 0x16, 0xA2, 0x4F, 0xA7, 0x14, 0x78, 0xB1, - 0x3A, 0x59, 0x78, 0x0C, 0xC5, 0x54, 0x05, 0xC6, - 0x8E, 0x57, 0xEA, 0x3D, 0x25, 0x55, 0x41, 0x46, - 0xDC, 0x0C, 0x71, 0x3F, 0x81, 0x3A, 0xAA, 0x8F, - 0x6B, 0x95, 0x0E, 0x68, 0xAD, 0xED, 0x90, 0xA0, - 0x20, 0xFB, 0x7B, 0x56, 0x8E, 0xAF, 0xFC, 0x3F, - 0x9E, 0x70, 0xC5, 0x98, 0x72, 0xC1, 0x20, 0xD4, - 0x57, 0x05, 0x60, 0x2E, 0x95, 0x35, 0xCC, 0x9F, - 0x02, 0x29, 0xA9, 0x84, 0x5C, 0xDD, 0x8B, 0x48, - 0xDE, 0xA7, 0x17, 0x1E, 0x49, 0xDC, 0x94, 0x57, - 0x75, 0xCC, 0x58, 0x15, 0xFA, 0x49, 0xB5, 0x7F, - 0x77, 0x96, 0xB2, 0xC4, 0x08, 0x3A, 0x72, 0xB2, - 0xA0, 0x29, 0x91, 0x1D, 0xCD, 0x7D, 0x5B, 0x9A, - 0x1A, 0xC1, 0x7B, 0x1D, 0x20, 0x5C, 0x1C, 0x79, - 0x9E, 0x45, 0x42, 0x17, 0xCC, 0xD5, 0x37, 0xFB, - 0x67, 0x34, 0x81, 0x0C, 0xEC, 0x5F, 0xCD, 0x05, - 0x50, 0x87, 0x58, 0xA4, 0x83, 0x03, 0xF2, 0x08, - 0x8B, 0xA2, 0x5C, 0xE5, 0xBC, 0x3E, 0x5D, 0x45, - 0xC6, 0xF5, 0x4D, 0xE3, 0x76, 0x11, 0xD9, 0x1A, - 0x78, 0xFE, 0x1F, 0xC1, 0x73, 0xDF, 0x7F, 0x9F, - 0x1F, 0x4C, 0x22, 0xDC, 0x2D, 0x1D, 0xEF, 0x45, - 0xE6, 0x31, 0x8E, 0x70, 0xC2, 0x50, 0xA2, 0x38, - 0xEE, 0xD5, 0x6B, 0x07, 0xC2, 0x82, 0x4A, 0x89, - 0xAB, 0xBA, 0x54, 0x5D, 0x7C, 0xEB, 0x96, 0xA6, - 0x26, 0xFD, 0x7D, 0x50, 0x88, 0xA9, 0xFE, 0x3D, - 0x3F, 0xED, 0x7F, 0x91, 0x00, 0x95, 0x50, 0xB1, - 0x31, 0x4B, 0xC6, 0xA9, 0xF0, 0x72, 0x11, 0xDD, - 0x74, 0x2D, 0xB3, 0xCD, 0x87, 0x5D, 0x39, 0x19, - 0x91, 0x4A, 0x5E, 0x92, 0xDE, 0xDF, 0x89, 0x4A, - 0x0B, 0xEC, 0x59, 0x8D, 0x5E, 0x2E, 0x6E, 0xAE, - 0xE6, 0x31, 0x15, 0x62, 0xE7, 0xFD, 0x36, 0x3C, - 0x25, 0x6C, 0xB1, 0xF5, 0x08, 0x02, 0x42, 0x9F, - 0xEF, 0x34, 0xB4, 0x99, 0x41, 0xFD, 0x88, 0x09, - 0xBE, 0x66, 0xE7, 0x69, 0x9D, 0x6A, 0xE8, 0x27, - 0x95, 0x4A, 0xDB, 0x95, 0x49, 0xDF, 0x85, 0x67, - 0xC7, 0x3D, 0xAA, 0xE4, 0x78, 0xED, 0x90, 0xA0, - 0x79, 0xE6, 0xC2, 0xAA, 0x57, 0x65, 0x01, 0xE7, - 0x6C, 0x2E, 0x08, 0xF4, 0x58, 0x7A, 0x5E, 0xB9, - 0xA3, 0xF0, 0xC6, 0x2B, 0xD2, 0xE0, 0xC4, 0x21, - 0xBC, 0x97, 0x78, 0x20, 0x4A, 0xFE, 0xB9, 0xDB, - 0x5F, 0xA1, 0xB5, 0x9D, 0x4F, 0xE4, 0x2E, 0x4E, - 0x6E, 0xC1, 0xD5, 0xFD, 0x03, 0x09, 0xC3, 0xA3, - 0x82, 0x78, 0x6C, 0x44, 0xB9, 0x14, 0x84, 0x44, - 0xC4, 0x1F, 0x9F, 0xB2, 0x6A, 0x1A, 0x5A, 0x9A, - 0x16, 0xC4, 0xF3, 0xA2, 0x79, 0xF8, 0xA2, 0x61, - 0xB0, 0x50, 0xE5, 0xFB, 0x00, 0x3A, 0x9A, 0x7A, - 0xFA, 0x69, 0x9A, 0x94, 0x6F, 0x56, 0xB6, 0x01, - 0x91, 0xCA, 0x0B, 0x76, 0x2E, 0xF8, 0x88, 0x88, - 0x28, 0xF3, 0x77, 0x38, 0x61, 0xA1, 0xA7, 0x47, - 0xB6, 0x5B, 0xEE, 0xE2, 0x7E, 0xEE, 0xBE, 0xDF, - 0x5B, 0xE1, 0x6B, 0x04, 0xEC, 0xDD, 0xB9, 0x49, - 0x78, 0xE2, 0xEC, 0x87, 0x49, 0xD1, 0xB9, 0xFB, - 0x50, 0x94, 0x15, 0x71, 0xD5, 0xE4, 0xBA, 0x79, - 0xF5, 0x64, 0x5A, 0xDE, 0x36, 0x35, 0x75, 0x55, - 0xDD, 0x06, 0x78, 0x51, 0xA8, 0x2F, 0x4C, 0x87, - 0x9B, 0x56, 0xB9, 0xDF, 0xB5, 0xC9, 0x57, 0x81, - 0xBA, 0x6B, 0x0F, 0xAF, 0x8A, 0x2C, 0xE1, 0x2D, - 0xBB, 0xDC, 0x6A, 0x20, 0xB4, 0x0C, 0xCE, 0xAE, - 0x2E, 0x50, 0x50, 0x1C, 0x06, 0x93, 0xF7, 0xF7, - 0xE7, 0x48, 0x52, 0x57, 0xA9, 0x50, 0x14, 0x71, - 0xE1, 0x3A, 0x0D, 0x53, 0x88, 0xBA, 0xF2, 0x20, - 0x40, 0x93, 0x25, 0xEB, 0x93, 0xB7, 0x6F, 0xA8, - 0xE8, 0x13, 0xA5, 0x01, 0xDF, 0xFD, 0x86, 0x1B, - 0x31, 0x41, 0x3D, 0xC8, 0x82, 0x59, 0x11, 0x34, - 0x1D, 0xE6, 0x98, 0xB1, 0x65, 0xDE, 0x3E, 0x52, - 0xD3, 0xA8, 0xBA, 0xF6, 0x0B, 0xA8, 0xC8, 0xA5, - 0x26, 0xF1, 0x4C, 0x85, 0x4F, 0xFF, 0x57, 0xD2, - 0x92, 0xD9, 0x1B, 0xEB, 0xAA, 0x3C, 0x15, 0xC2, - 0x5F, 0x74, 0x02, 0x4E, 0x96, 0xEE, 0x88, 0xFA, - 0x61, 0xE7, 0xFC, 0x92, 0x80, 0x8B, 0x52, 0xA0, - 0xC5, 0xB8, 0x2E, 0x5F, 0x77, 0xC7, 0xA7, 0x67, - 0x55, 0x2E, 0x99, 0x27, 0xFD, 0x47, 0x85, 0x47, - 0xEF, 0x34, 0x5F, 0x22, 0x7A, 0x60, 0x11, 0x71, - 0x5D, 0xA6, 0xC0, 0x06, 0xFE, 0x6B, 0x04, 0xC4, - 0xEC, 0xB5, 0x0F, 0x68, 0x15, 0xAB, 0xCB, 0x2E, - 0xE7, 0x3C, 0x86, 0xC1, 0x3C, 0x82, 0xE2, 0x3F, - 0x4F, 0x94, 0x2E, 0x48, 0xF5, 0xE8, 0xA8, 0xA0, - 0x65, 0x38, 0x54, 0xC7, 0x1F, 0xAF, 0x62, 0xA1, - 0x04, 0x36, 0x7F, 0xE1, 0x3B, 0xAD, 0x2F, 0xED, - 0x4A, 0x66, 0x6E, 0x13, 0x43, 0xC1, 0x1D, 0x55, - 0x4D, 0xD4, 0xDE, 0xFB, 0x81, 0x33, 0x59, 0x95, - 0x1E, 0x7C, 0x8F, 0x41, 0xDB, 0x4E, 0xE6, 0x63, - 0x25, 0x2E, 0x67, 0xA6, 0x7D, 0x28, 0xAE, 0x91, - 0xC3, 0x1A, 0x8A, 0x24, 0xFE, 0x69, 0xDE, 0xA2, - 0x33, 0x00, 0x84, 0x44, 0x62, 0x2A, 0x08, 0x64, - 0x5B, 0x02, 0xB6, 0xD0, 0x04, 0xBD, 0x44, 0xC1, - 0xC3, 0x5A, 0xC9, 0x6D, 0xF0, 0xC6, 0x61, 0x5E, - 0xDE, 0x05, 0xBF, 0xD9, 0xE4, 0x4A, 0x2A, 0xBC, - 0x86, 0xA1, 0x1B, 0x6D, 0xD0, 0x7E, 0x1E, 0xD2, - 0x69, 0x7F, 0xC3, 0xA3, 0x31, 0x41, 0x8A, 0xD9, - 0xF0, 0x6E, 0xDE, 0x5C, 0x7B, 0xCB, 0xA7, 0x4D, - 0xE8, 0x2E, 0x98, 0x2C, 0xB1, 0x0D, 0x23, 0x43, - 0x1D, 0x45, 0x2A, 0x03, 0x1D, 0x5F, 0xC0, 0x00, - 0x80, 0x5B, 0xDB, 0xF6, 0x2E, 0x3C, 0xFC, 0x18, - 0x49, 0xAF, 0x1A, 0x97, 0x70, 0xC3, 0x92, 0x65, - 0xE6, 0x1C, 0x90, 0xFF, 0x66, 0xE8, 0x8B, 0x8B, - 0x2B, 0xF0, 0xC4, 0x8C, 0x5A, 0x58, 0x1A, 0x53, - 0x11, 0xC9, 0x57, 0xDB, 0xB8, 0x18, 0xF8, 0xF4, - 0x65, 0x6E, 0x14, 0x68, 0x70, 0x7B, 0x3B, 0x1B, - 0x93, 0x48, 0x3E, 0x72, 0xAA, 0x36, 0xDC, 0x94, - 0xF0, 0xFA, 0x0D, 0x62, 0x08, 0x9A, 0x70, 0x72, - 0xF1, 0x0F, 0x58, 0x74, 0xAF, 0x9F, 0x33, 0xE2, - 0x82, 0x95, 0x33, 0x8F, 0xEC, 0x4C, 0xEC, 0x97, - 0x37, 0x0C, 0xB2, 0xDE, 0x1B, 0x5B, 0x0D, 0x8C, - 0x0C, 0x96, 0x16, 0x79, 0xF0, 0x72, 0x11, 0x09, - 0x8D, 0x27, 0xA6, 0xC9, 0x83, 0x1E, 0x62, 0x62, - 0xC2, 0x19, 0x2D, 0x56, 0x80, 0xF2, 0x8F, 0x19, - 0xB0, 0x62, 0x56, 0xF2, 0xD2, 0xF0, 0xBD, 0x61, - 0xAA, 0xBD, 0xCB, 0x67, 0x4B, 0x39, 0x04, 0x92, - 0x59, 0x1B, 0x3F, 0x3E, 0xFA, 0xCD, 0x81, 0x37, - 0x96, 0x74, 0xC1, 0x48, 0xCC, 0x59, 0x81, 0x45, - 0x67, 0xD7, 0x43, 0xA3, 0xC1, 0xF3, 0xB9, 0x7A, - 0x78, 0x8B, 0x3D, 0xB1, 0x61, 0xD1, 0xF7, 0x36, - 0xB6, 0x6D, 0xD7, 0xB1, 0x8C, 0xA6, 0xE6, 0xAE, - 0x8B, 0xB0, 0x0E, 0x62, 0x57, 0xED, 0x5F, 0xBB, - 0x3B, 0x52, 0xFE, 0x86, 0xFC, 0x21, 0x63, 0x71, - 0xEC, 0x61, 0x65, 0xC2, 0xE2, 0x85, 0x4E, 0x8F, - 0xD2, 0x02, 0x09, 0x67, 0x17, 0x89, 0x39, 0x99, - 0xED, 0xFB, 0x4B, 0xAC, 0xDE, 0x8B, 0x8B, 0x63, - 0xC9, 0x34, 0x3A, 0x52, 0x02, 0xE7, 0x25, 0xCE, - 0x6C, 0x25, 0xB8, 0xC8, 0xD2, 0x79, 0x4F, 0xEF, - 0xF6, 0xED, 0x3B, 0x9B, 0x83, 0xF1, 0xCA, 0x5C, - 0x4E, 0xFE, 0x54, 0xD8, 0x08, 0xB8, 0x00, 0xC4, - 0xE6, 0x2A, 0x92, 0x3C, 0xF9, 0x1F, 0xDD, 0xD7, - 0xAF, 0xD3, 0xC9, 0x2B, 0x75, 0xC5, 0xA5, 0x44, - 0xFD, 0x25, 0x21, 0x8E, 0xA9, 0xEF, 0xA4, 0x30, - 0xA6, 0x91, 0x22, 0xAB, 0x27, 0xB2, 0x1A, 0xDE, - 0xFC, 0x4B, 0xDF, 0x3F, 0x5D, 0x6F, 0x25, 0xE6, - 0xE4, 0x17, 0xA1, 0x2D, 0xFD, 0x4D, 0x6B, 0xAA, - 0x2A, 0xF1, 0x4B, 0x2D, 0x10, 0x32, 0x72, 0x3A, - 0x1F, 0x24, 0x9A, 0xF6, 0xE6, 0x52, 0x8F, 0x4D, - 0x6F, 0xD8, 0x4C, 0x88, 0x7A, 0x08, 0x74, 0xE2, - 0xC0, 0xD1, 0x6F, 0xE6, 0x67, 0xFF, 0x2E, 0xD7, - 0x54, 0x07, 0xE4, 0x20, 0xFC, 0x8E, 0x4E, 0x8E, - 0xCC, 0x4D, 0xAD, 0x73, 0xC1, 0x6D, 0xAF, 0x45, - 0xE7, 0xDC, 0x62, 0x0E, 0x04, 0x90, 0xF0, 0xC0, - 0x60, 0xBB, 0xCF, 0xBE, 0x30, 0x0C, 0xF0, 0x92, - 0x3F, 0xF8, 0xF3, 0x9D, 0x20, 0xC7, 0x8F, 0x9D, - 0x39, 0xE2, 0x32, 0x7D, 0x9B, 0xC9, 0xB4, 0x23, - 0x1F, 0xAA, 0x79, 0x5B, 0xA6, 0xEE, 0x8A, 0xE8, - 0x07, 0xFE, 0xE4, 0x92, 0xC2, 0x48, 0xA0, 0x68, - 0x08, 0xDB, 0x6D, 0x89, 0xF4, 0xA4, 0xCC, 0x0C, - 0x14, 0xCB, 0xF5, 0xCC, 0xB6, 0x6F, 0x2D, 0x0D, - 0x85, 0x5E, 0x40, 0x28, 0x52, 0xF8, 0xCF, 0x59, - 0xA3, 0x85, 0x35, 0x5A, 0x82, 0x32, 0x52, 0x33, - 0xF0, 0x28, 0x2F, 0x01, 0xDA, 0xD3, 0xE4, 0x01, - 0x3D, 0xC1, 0xAF, 0xC7, 0xDD, 0x70, 0x47, 0x0B, - 0x87, 0x41, 0x07, 0xCA, 0x57, 0xE4, 0x55, 0xD1, - 0x52, 0x50, 0x81, 0x08, 0x6A, 0xFD, 0x80, 0xB0, - 0x30, 0xEB, 0x6B, 0x46, 0x9E, 0xEF, 0xB8, 0x7B, - 0x5A, 0xBA, 0x0F, 0xDF, 0xC5, 0xF7, 0x55, 0x6B, - 0xFD, 0x6E, 0xDE, 0xD4, 0x1E, 0x85, 0x5D, 0x97, - 0xF5, 0x22, 0xB0, 0x0E, 0xDD, 0x6A, 0xA8, 0x63, - 0xE5, 0xAC, 0x11, 0x78, 0x70, 0x6A, 0xCA, 0x9D, - 0x37, 0xA5, 0xB1, 0x91, 0x61, 0x33, 0x1F, 0xFA, - 0x58, 0x88, 0x37, 0xA9, 0x7A, 0xC2, 0x50, 0xDC, - 0x7B, 0x82, 0x78, 0x32, 0xE6, 0x44, 0x39, 0x09, - 0x89, 0x52, 0xE8, 0x8E, 0xB3, 0x87, 0xC7, 0x0B, - 0x89, 0x4F, 0x09, 0xDD, 0x0F, 0x6D, 0x01, 0xE9, - 0xCB, 0x1B, 0xAA, 0x44, 0x97, 0x23, 0x99, 0xF3, - 0xD4, 0x27, 0xD7, 0x19, 0x8D, 0x15, 0x57, 0x9C, - 0x15, 0x2C, 0x96, 0xDE, 0xF4, 0x4F, 0x27, 0x15, - 0xD9, 0x25, 0x71, 0x51, 0xAC, 0x3E, 0x12, 0xF4, - 0x78, 0xB1, 0x1A, 0x86, 0x52, 0xE0, 0x9D, 0xAD, - 0x95, 0x44, 0x50, 0x30, 0xC0, 0xA2, 0xC9, 0x0E, - 0x0C, 0xDC, 0x6F, 0xD3, 0xA1, 0xD1, 0x36, 0xDC, - 0x40, 0x39, 0xC3, 0x87, 0x7D, 0xC6, 0xAF, 0x8D, - 0x01, 0xFE, 0xBA, 0xDD, 0x0D, 0x4F, 0x63, 0x84, - 0xE6, 0x71, 0xE2, 0xAC, 0x38, 0xAE, 0xC2, 0x10, - 0x8D, 0xA6, 0x1C, 0x72, 0xB7, 0xF7, 0x9B, 0x59, - 0xC4, 0xEF, 0x6F, 0x42, 0x9A, 0x0B, 0x5D, 0x9E, - 0x9C, 0x65, 0xD3, 0xFE, 0x11, 0xA2, 0x40, 0x98, - 0x4F, 0xA5, 0x21, 0x4E, 0x3A, 0xF2, 0x37, 0xCA, - 0x6F, 0x2C, 0x98, 0x56, 0xE7, 0x75, 0xB9, 0xA3, - 0xAB, 0x4A, 0x74, 0x10, 0x28, 0x90, 0xF0, 0xB8, - 0x9B, 0xA0, 0x1E, 0x72, 0x32, 0x80, 0x62, 0x81, - 0x04, 0x7D, 0xA2, 0xEC, 0xD4, 0x6C, 0x0C, 0x64, - 0xE6, 0x9F, 0x33, 0x08, 0x86, 0x5C, 0xC1, 0xA0, - 0x65, 0xBD, 0xBA, 0x92, 0x49, 0x40, 0x44, 0x21, - 0x0A, 0xF6, 0x5D, 0xC1, 0x19, 0xA9, 0xC9, 0xA8, - 0x6B, 0xB3, 0xC4, 0xEA, 0x31, 0x48, 0x7C, 0x19, - 0x33, 0xCF, 0xA1, 0xCF, 0xC5, 0x68, 0x5F, 0xC9, - 0x34, 0x11, 0xE1, 0x7B, 0x5C, 0xEC, 0xBA, 0x3B, - 0xBB, 0x6C, 0xD0, 0x9D, 0x73, 0xC0, 0xDC, 0xF0, - 0xC8, 0x11, 0x26, 0x74, 0xAF, 0xAD, 0xE6, 0x05, - 0x0D, 0x3E, 0x48, 0x9F, 0x57, 0x07, 0x6F, 0xAF, - 0x87, 0x5E, 0x4A, 0xEC, 0x6C, 0x39, 0xFE, 0x19, - 0x84, 0xAF, 0x2F, 0x02, 0xDA, 0x76, 0xCE, 0x89, - 0x9B, 0x44, 0xD3, 0xF9, 0x22, 0x8F, 0x1F, 0x72, - 0xF0, 0x0E, 0x0E, 0x47, 0xB2, 0x08, 0x75, 0x45, - 0xC5, 0x1E, 0x9E, 0xB3, 0x6B, 0x76, 0x14, 0xB1, - 0x31, 0xEA, 0x50, 0x3E, 0xFB, 0xBB, 0xED, 0x6C, - 0xEC, 0x17, 0x03, 0x4F, 0xB2, 0xE0, 0xA7, 0x56, - 0xED, 0x35, 0x1B, 0x74, 0x0C, 0x34, 0x15, 0x57, - 0x9E, 0x44, 0x50, 0x75, 0xAD, 0x36, 0xF4, 0xD1, - 0xB1, 0x4D, 0x4A, 0x11, 0xCA, 0xF8, 0x9A, 0x5F, - 0x2D, 0xF4, 0x45, 0xFB, 0x21, 0x97, 0x35, 0xF7, - 0x7F, 0x4C, 0xF9, 0x07, 0xDD, 0x69, 0x9B, 0x15, - 0x91, 0xC8, 0x30, 0x59, 0x23, 0xDD, 0xBF, 0xDF, - 0xF7, 0x6D, 0x79, 0x5B, 0x80, 0x92, 0xF0, 0x39, - 0x4B, 0xDE, 0x6F, 0xA1, 0x32, 0xA4, 0x66, 0xE8, - 0x61, 0x78, 0x80, 0xE4, 0xEE, 0x10, 0x76, 0x66, - 0x36, 0x99, 0xEF, 0x43, 0xEF, 0x9D, 0xB6, 0x51, - 0x03, 0x93, 0x0D, 0xCB, 0xCF, 0xAF, 0x1E, 0xFF, - 0xAD, 0x3D, 0xAF, 0xDE, 0xF6, 0x46, 0x10, 0x91, - 0x11, 0x07, 0xB3, 0xD3, 0x06, 0xAD, 0xAE, 0xD3, - 0x55, 0xB9, 0x3B, 0x26, 0xD5, 0x31, 0x61, 0xE5, - 0xA5, 0x65, 0x97, 0xBB, 0xE2, 0x13, 0x74, 0xD0, - 0x56, 0xA6, 0xA3, 0x1D, 0xC7, 0x77, 0x0C, 0x0E, - 0x12, 0xF1, 0xEA, 0x8B, 0x78, 0x73, 0xF1, 0x3D, - 0xBD, 0xB4, 0x0E, 0x63, 0x90, 0xEC, 0x66, 0x0C, - 0x56, 0x27, 0xC6, 0x31, 0x07, 0x6A, 0x00, 0x6D, - 0xE0, 0x86, 0x34, 0x7D, 0xC5, 0x5D, 0xF0, 0x32, - 0x0F, 0xD2, 0x68, 0x09, 0x91, 0xC0, 0xE1, 0x26, - 0xC2, 0x15, 0xB8, 0x16, 0x1C, 0xAE, 0xCE, 0x15, - 0x23, 0x28, 0x44, 0xE8, 0xE0, 0x81, 0x81, 0xDD, - 0xA3, 0x55, 0xEE, 0x10, 0xC4, 0x74, 0x3F, 0x44, - 0x54, 0x15, 0x63, 0x9F, 0xD6, 0x06, 0xFC, 0x1E, - 0x1C, 0xCB, 0x7C, 0x3B, 0x2F, 0x1F, 0xF5, 0xF5, - 0xF5, 0xAF, 0x79, 0x9F, 0x65, 0x82, 0x79, 0x5B, - 0xC6, 0xED, 0x76, 0x17, 0xD2, 0x92, 0xFE, 0x3C, - 0xA1, 0x8A, 0x0A, 0x07, 0xDF, 0xAF, 0xEF, 0x2F, - 0xEE, 0x7C, 0xC9, 0x04, 0x94, 0x27, 0x66, 0xE1, - 0x62, 0xEB, 0xFD, 0x90, 0x1A, 0xC8, 0x29, 0x29, - 0x89, 0x52, 0x76, 0x38, 0x60, 0x10, 0x50, 0x90, - 0xB0, 0xF2, 0x64, 0x9A, 0x20, 0x10, 0xB0, 0x50, - 0xD0, 0x89, 0x1B, 0xF6, 0xEE, 0x7E, 0x1E, 0x8E, - 0x86, 0x7D, 0x49, 0x41, 0x18, 0xCD, 0x8F, 0x6A, - 0xD7, 0x06, 0xA6, 0x80, 0x54, 0x5C, 0x16, 0x6F, - 0xEE, 0x39, 0x84, 0x08, 0xB1, 0x01, 0xB3, 0xD3, - 0x53, 0x59, 0xD8, 0xB7, 0xAF, 0x3F, 0x5F, 0x5D, - 0xFF, 0xA4, 0xD2, 0x9E, 0x46, 0xA6, 0x0A, 0xEA, - 0xB8, 0x7E, 0xC6, 0x68, 0xD2, 0xE2, 0x24, 0xF9, - 0x5C, 0x25, 0x33, 0xA3, 0xB9, 0x28, 0x48, 0x48, - 0xE8, 0x33, 0x77, 0x39, 0x6B, 0x2B, 0xC3, 0x42, - 0x62, 0x46, 0xE0, 0x0B, 0xCC, 0x8C, 0x2C, 0xCC, - 0x4C, 0xDC, 0xD1, 0x3F, 0xC5, 0xF9, 0x1B, 0xB7, - 0x37, 0x2E, 0x54, 0x3C, 0x33, 0xA8, 0x17, 0x86, - 0x4C, 0x94, 0xC2, 0x48, 0x83, 0x23, 0x63, 0xA3, - 0xA1, 0x5F, 0xED, 0x61, 0xB1, 0x01, 0x77, 0xBD, - 0x3A, 0xED, 0x55, 0xF8, 0x1B, 0xA8, 0xB4, 0x9C, - 0x10, 0x81, 0x4B, 0x1E, 0x06, 0x96, 0xF6, 0xE4, - 0x40, 0x1D, 0x6B, 0x27, 0xFF, 0xDF, 0x22, 0xF2, - 0xD2, 0x90, 0x06, 0xF8, 0x44, 0x72, 0xD2, 0x32, - 0xB2, 0x9B, 0x09, 0xE4, 0xFC, 0x6C, 0x0C, 0x4C, - 0x33, 0xF8, 0xBC, 0xB4, 0xED, 0x9D, 0xDD, 0x1D, - 0x4F, 0xF0, 0xC0, 0x6C, 0x94, 0x24, 0x8C, 0x40, - 0x68, 0x90, 0xD4, 0xB4, 0x6C, 0x6E, 0x02, 0xC3, - 0x81, 0x96, 0x22, 0xCE, 0xAD, 0x0C, 0x9C, 0xE7, - 0x47, 0x4E, 0xF4, 0x98, 0x82, 0x3E, 0x5F, 0x7D, - 0x9F, 0xC5, 0xF3, 0x53, 0x9A, 0xFA, 0x56, 0xB6, - 0xD3, 0xE0, 0xA9, 0x4D, 0xA6, 0x3B, 0x51, 0x19, - 0x91, 0xE7, 0x52, 0xDE, 0x0E, 0xBE, 0xC3, 0xF3, - 0x73, 0xA8, 0x12, 0x74, 0x49, 0xAD, 0xED, 0xAB, - 0xE6, 0xC2, 0xFC, 0xD5, 0xED, 0x55, 0x35, 0xE3, - 0x19, 0x3D, 0x4D, 0xC1, 0xE6, 0x56, 0x00, 0x81, - 0x01, 0x7B, 0x86, 0xE9, 0x80, 0x7C, 0x1F, 0x12, - 0x90, 0x2E, 0x70, 0x38, 0x51, 0xAF, 0xCC, 0x2C, - 0x86, 0xFD, 0xEA, 0xCB, 0x10, 0x6D, 0x0F, 0xAA, - 0xCD, 0x32, 0x35, 0x09, 0xD2, 0x42, 0x18, 0x78, - 0x3A, 0x22, 0x84, 0x49, 0xDE, 0x6D, 0x01, 0xC3, - 0x6A, 0xB2, 0x2D, 0x52, 0xA3, 0x30, 0x79, 0x8A, - 0xEF, 0xD1, 0x43, 0x9E, 0x14, 0xA7, 0xF7, 0x0D, - 0x2D, 0x34, 0x41, 0x3D, 0x44, 0xA5, 0xC6, 0xE3, - 0x87, 0x78, 0xC2, 0xA7, 0x4F, 0xC5, 0x05, 0xF7, - 0xB4, 0x7F, 0xE2, 0x17, 0xE6, 0x55, 0x1C, 0xCF, - 0xC4, 0x2C, 0xFC, 0x09, 0x25, 0x38, 0x5B, 0x29, - 0x09, 0x77, 0xED, 0xCD, 0xF0, 0x73, 0x3B, 0x5A, - 0x89, 0x51, 0x56, 0x6E, 0xB5, 0xC7, 0x64, 0x80, - 0x65, 0x5C, 0xCE, 0x13, 0x9D, 0x2E, 0x7E, 0x84, - 0xA4, 0xDE, 0x3D, 0x52, 0xB8, 0xCB, 0x8F, 0x82, - 0x01, 0x3F, 0x6A, 0x22, 0x4B, 0xA3, 0xC0, 0x30, - 0x8A, 0xF1, 0xE6, 0xDD, 0x06, 0x7B, 0x18, 0xBD, - 0xD8, 0x27, 0x20, 0x16, 0xCD, 0x4D, 0x17, 0x77, - 0x56, 0xD4, 0x61, 0xC0, 0x1B, 0x0E, 0x8A, 0x6E, - 0x5F, 0xD8, 0x6D, 0x31, 0xD3, 0xC3, 0x02, 0x99, - 0x1A, 0x0C, 0xB9, 0x70, 0x4B, 0xDF, 0x8F, 0x65, - 0x45, 0x83, 0xC5, 0xA9, 0x71, 0xC1, 0xBB, 0x7A, - 0xFA, 0x21, 0x97, 0xFB, 0x23, 0x93, 0x7F, 0xB2, - 0x30, 0x8B, 0xA9, 0xD3, 0x0B, 0xDB, 0xA6, 0x66, - 0xEC, 0x37, 0x03, 0x6B, 0x30, 0x84, 0x44, 0x97, - 0x15, 0xAE, 0x19, 0x75, 0xAD, 0x1D, 0x01, 0xD7, - 0x57, 0xEC, 0x26, 0x5C, 0x84, 0x54, 0x9C, 0x4A, - 0xCA, 0x71, 0x4F, 0x35, 0xED, 0x3D, 0xD5, 0x03, - 0x83, 0x38, 0x22, 0x58, 0x80, 0x50, 0x30, 0xF0, - 0x70, 0xAB, 0x1D, 0x71, 0xA9, 0x19, 0x79, 0xB9, - 0x39, 0xE2, 0x54, 0x38, 0xE0, 0x50, 0x30, 0xF0, - 0x70, 0xAB, 0x1D, 0x71, 0xA9, 0x19, 0x79, 0xB9, - 0x39, 0xE2, 0x54, 0x38, 0xE0, 0x50, 0x30, 0xF0, - 0x70, 0xAB, 0x1D, 0x71, 0xA9, 0x19, 0x79, 0xB9, - 0x39, 0xE2, 0x7C, 0x19, 0xC1, 0x11, 0x55, 0x9C, - 0x1C, 0xA7, 0x03, 0x5F, 0x87, 0x37, 0x97, 0x41, - 0xC1, 0x7A, 0x7C, 0x10, 0xC8, 0x78, 0x64, 0xA3, - 0x23, 0x98, 0x82, 0xE3, 0x39, 0xE9, 0x79, 0xBE, - 0x3E, 0x85, 0xC3, 0xA2, 0x78, 0xA8, 0xB8, 0x76, - 0xF4, 0x4F, 0xF1, 0x92, 0x48, 0x98, 0x44, 0x83, - 0x03, 0xB8, 0x86, 0xF9, 0x23, 0xF3, 0x3F, 0xEA, - 0x68, 0xD3, 0x53, 0x7E, 0xA6, 0x97, 0x45, 0x80, - 0xB1, 0xDA, 0x69, 0xA7, 0xDF, 0x6C, 0x9D, 0xEC, - 0x69, 0x10, 0xED, 0x81, 0xDB, 0x02, 0x62, 0xC7, - 0x46, 0x9D, 0x0E, 0x60, 0xB8, 0x2D, 0x49, 0x89, - 0xA8, 0xC0, 0x73, 0xAE, 0xC2, 0x77, 0xF2, 0xA3, - 0x04, 0xC2, 0x84, 0xE8, 0x30, 0x80, 0xD6, 0x57, - 0xD7, 0x3D, 0x3E, 0x57, 0xAE, 0xA8, 0xCD, 0x24, - 0x77, 0xB1, 0xF7, 0x9B, 0x43, 0xF3, 0xA5, 0x24, - 0xA4, 0xCE, 0xC0, 0xA9, 0x40, 0x4B, 0x2E, 0xCF, - 0xF3, 0x2D, 0x1A, 0xCC, 0x11, 0x30, 0xE7, 0x22, - 0x03, 0x61, 0xD2, 0x17, 0x16, 0x24, 0x2D, 0xFD, - 0x54, 0xAC, 0xA3, 0x56, 0x93, 0xD3, 0x85, 0x04, - 0x84, 0x6E, 0x6D, 0x04, 0xFD, 0xF0, 0x95, 0x7C, - 0x6F, 0xA9, 0xEF, 0x83, 0x5B, 0xEB, 0x8B, 0x4B, - 0xCB, 0x10, 0xA6, 0xCA, 0x12, 0xA2, 0xC2, 0x02, - 0x82, 0x59, 0xEE, 0x82, 0x5E, 0xEE, 0x76, 0xA0, - 0x22, 0x99, + 0x06, 0x6B, 0x06, 0x6A, 0x76, 0xCC, 0x1C, 0xD0, + 0x50, 0xEB, 0x75, 0x10, 0xC8, 0x18, 0x5C, 0x95, + 0x15, 0xAE, 0xA8, 0xC8, 0x10, 0xC0, 0xB0, 0x7A, + 0xFA, 0x21, 0x96, 0xFA, 0x22, 0x92, 0xAE, 0x78, + 0xF8, 0x43, 0x05, 0x6E, 0xB6, 0x66, 0x62, 0xD5, + 0x51, 0xEA, 0xF0, 0xE5, 0x39, 0xE9, 0xA1, 0x19, + 0x9D, 0x26, 0x80, 0xE0, 0x38, 0xE8, 0x1C, 0xCA, + 0x4A, 0xF1, 0xBF, 0xD8, 0x00, 0xD0, 0x34, 0xD9, + 0x5D, 0xB6, 0x00, 0xF2, 0x2A, 0xA2, 0xAA, 0x7C, + 0xFC, 0x47, 0xDD, 0xB8, 0x60, 0xB0, 0xD0, 0xEF, + 0x6F, 0xB4, 0x46, 0x2C, 0xF4, 0x24, 0xBB, 0x7B, + 0x04, 0x20, 0x96, 0xC5, 0x1D, 0xAD, 0x32, 0x32, + 0x4D, 0x69, 0xDF, 0xA0, 0x7A, 0xAA, 0xB6, 0x60, + 0xE0, 0x5B, 0x89, 0xF6, 0x2C, 0xFC, 0x14, 0xC2, + 0x42, 0xF9, 0x23, 0x59, 0x81, 0x51, 0x31, 0xEF, + 0x6B, 0x80, 0x36, 0x52, 0x8A, 0x3A, 0x5A, 0x64, + 0x1B, 0xF7, 0xBD, 0xD4, 0x0C, 0xDC, 0xBC, 0x54, + 0xD0, 0x3B, 0x0D, 0x4C, 0x90, 0x10, 0x70, 0x90, + 0x14, 0xFF, 0x65, 0x29, 0xF5, 0x75, 0x55, 0xB5, + 0x31, 0xDA, 0x88, 0xC5, 0x19, 0x99, 0xF9, 0x39, + 0xB9, 0x5A, 0xD0, 0xBC, 0x64, 0xEC, 0x8C, 0xEC, + 0x6C, 0x8F, 0x05, 0xC9, 0x11, 0x99, 0xF9, 0x19, + 0x99, 0x7A, 0xC2, 0x8E, 0x56, 0xDE, 0xBE, 0x3E, + 0xBE, 0x5D, 0xE3, 0xCF, 0x17, 0x9F, 0xFF, 0x5F, + 0xDF, 0x3C, 0x82, 0x8E, 0x56, 0xDE, 0xBE, 0xFE, + 0x7E, 0x9D, 0x23, 0xCF, 0x17, 0x9F, 0xC9, 0x48, + 0xC8, 0xF6, 0x07, 0x4D, 0x04, 0x98, 0xFB, 0x9A, + 0x37, 0xEF, 0x55, 0x31, 0x60, 0xDA, 0x38, 0xB1, + 0x31, 0xF7, 0xB1, 0xDD, 0x05, 0xB5, 0xE3, 0x62, + 0xE2, 0x19, 0xCE, 0xA2, 0x5F, 0x11, 0x8E, 0x6E, + 0x08, 0xC0, 0x66, 0x2A, 0xF2, 0x4E, 0x24, 0x01, + 0xAA, 0x54, 0x43, 0x01, 0xDA, 0xDB, 0x94, 0x57, + 0xB2, 0x40, 0xDE, 0xAF, 0x87, 0x37, 0x61, 0xE0, + 0x60, 0x16, 0xA2, 0x4F, 0xA7, 0x14, 0x78, 0xB1, + 0x3A, 0x59, 0x78, 0x0C, 0xC5, 0x54, 0x05, 0xC6, + 0x8E, 0x57, 0xEA, 0x3D, 0x25, 0x55, 0x41, 0x46, + 0xDC, 0x0C, 0x71, 0x3F, 0x81, 0x3A, 0xAA, 0x8F, + 0x6B, 0x95, 0x0E, 0x68, 0xAD, 0xED, 0x90, 0xA0, + 0x20, 0xFB, 0x7B, 0x56, 0x8E, 0xAF, 0xFC, 0x3F, + 0x9E, 0x70, 0xC5, 0x98, 0x72, 0xC1, 0x20, 0xD4, + 0x57, 0x05, 0x60, 0x2E, 0x95, 0x35, 0xCC, 0x9F, + 0x02, 0x29, 0xA9, 0x84, 0x5C, 0xDD, 0x8B, 0x48, + 0xDE, 0xA7, 0x17, 0x1E, 0x49, 0xDC, 0x94, 0x57, + 0x75, 0xCC, 0x58, 0x15, 0xFA, 0x49, 0xB5, 0x7F, + 0x77, 0x96, 0xB2, 0xC4, 0x08, 0x3A, 0x72, 0xB2, + 0xA0, 0x29, 0x91, 0x1D, 0xCD, 0x7D, 0x5B, 0x9A, + 0x1A, 0xC1, 0x7B, 0x1D, 0x20, 0x5C, 0x1C, 0x79, + 0x9E, 0x45, 0x42, 0x17, 0xCC, 0xD5, 0x37, 0xFB, + 0x67, 0x34, 0x81, 0x0C, 0xEC, 0x5F, 0xCD, 0x05, + 0x50, 0x87, 0x58, 0xA4, 0x83, 0x03, 0xF2, 0x08, + 0x8B, 0xA2, 0x5C, 0xE5, 0xBC, 0x3E, 0x5D, 0x45, + 0xC6, 0xF5, 0x4D, 0xE3, 0x76, 0x11, 0xD9, 0x1A, + 0x78, 0xFE, 0x1F, 0xC1, 0x73, 0xDF, 0x7F, 0x9F, + 0x1F, 0x4C, 0x22, 0xDC, 0x2D, 0x1D, 0xEF, 0x45, + 0xE6, 0x31, 0x8E, 0x70, 0xC2, 0x50, 0xA2, 0x38, + 0xEE, 0xD5, 0x6B, 0x07, 0xC2, 0x82, 0x4A, 0x89, + 0xAB, 0xBA, 0x54, 0x5D, 0x7C, 0xEB, 0x96, 0xA6, + 0x26, 0xFD, 0x7D, 0x50, 0x88, 0xA9, 0xFE, 0x3D, + 0x3F, 0xED, 0x7F, 0x91, 0x00, 0x95, 0x50, 0xB1, + 0x31, 0x4B, 0xC6, 0xA9, 0xF0, 0x72, 0x11, 0xDD, + 0x74, 0x2D, 0xB3, 0xCD, 0x87, 0x5D, 0x39, 0x19, + 0x91, 0x4A, 0x5E, 0x92, 0xDE, 0xDF, 0x89, 0x4A, + 0x0B, 0xEC, 0x59, 0x8D, 0x5E, 0x2E, 0x6E, 0xAE, + 0xE6, 0x31, 0x15, 0x62, 0xE7, 0xFD, 0x36, 0x3C, + 0x25, 0x6C, 0xB1, 0xF5, 0x08, 0x02, 0x42, 0x9F, + 0xEF, 0x34, 0xB4, 0x99, 0x41, 0xFD, 0x88, 0x09, + 0xBE, 0x66, 0xE7, 0x69, 0x9D, 0x6A, 0xE8, 0x27, + 0x95, 0x4A, 0xDB, 0x95, 0x49, 0xDF, 0x85, 0x67, + 0xC7, 0x3D, 0xAA, 0xE4, 0x78, 0xED, 0x90, 0xA0, + 0x79, 0xE6, 0xC2, 0xAA, 0x57, 0x65, 0x01, 0xE7, + 0x6C, 0x2E, 0x08, 0xF4, 0x58, 0x7A, 0x5E, 0xB9, + 0xA3, 0xF0, 0xC6, 0x2B, 0xD2, 0xE0, 0xC4, 0x21, + 0xBC, 0x97, 0x78, 0x20, 0x4A, 0xFE, 0xB9, 0xDB, + 0x5F, 0xA1, 0xB5, 0x9D, 0x4F, 0xE4, 0x2E, 0x4E, + 0x6E, 0xC1, 0xD5, 0xFD, 0x03, 0x09, 0xC3, 0xA3, + 0x82, 0x78, 0x6C, 0x44, 0xB9, 0x14, 0x84, 0x44, + 0xC4, 0x1F, 0x9F, 0xB2, 0x6A, 0x1A, 0x5A, 0x9A, + 0x16, 0xC4, 0xF3, 0xA2, 0x79, 0xF8, 0xA2, 0x61, + 0xB0, 0x50, 0xE5, 0xFB, 0x00, 0x3A, 0x9A, 0x7A, + 0xFA, 0x69, 0x9A, 0x94, 0x6F, 0x56, 0xB6, 0x01, + 0x91, 0xCA, 0x0B, 0x76, 0x2E, 0xF8, 0x88, 0x88, + 0x28, 0xF3, 0x77, 0x38, 0x61, 0xA1, 0xA7, 0x47, + 0xB6, 0x5B, 0xEE, 0xE2, 0x7E, 0xEE, 0xBE, 0xDF, + 0x5B, 0xE1, 0x6B, 0x04, 0xEC, 0xDD, 0xB9, 0x49, + 0x78, 0xE2, 0xEC, 0x87, 0x49, 0xD1, 0xB9, 0xFB, + 0x50, 0x94, 0x15, 0x71, 0xD5, 0xE4, 0xBA, 0x79, + 0xF5, 0x64, 0x5A, 0xDE, 0x36, 0x35, 0x75, 0x55, + 0xDD, 0x06, 0x78, 0x51, 0xA8, 0x2F, 0x4C, 0x87, + 0x9B, 0x56, 0xB9, 0xDF, 0xB5, 0xC9, 0x57, 0x81, + 0xBA, 0x6B, 0x0F, 0xAF, 0x8A, 0x2C, 0xE1, 0x2D, + 0xBB, 0xDC, 0x6A, 0x20, 0xB4, 0x0C, 0xCE, 0xAE, + 0x2E, 0x50, 0x50, 0x1C, 0x06, 0x93, 0xF7, 0xF7, + 0xE7, 0x48, 0x52, 0x57, 0xA9, 0x50, 0x14, 0x71, + 0xE1, 0x3A, 0x0D, 0x53, 0x88, 0xBA, 0xF2, 0x20, + 0x40, 0x93, 0x25, 0xEB, 0x93, 0xB7, 0x6F, 0xA8, + 0xE8, 0x13, 0xA5, 0x01, 0xDF, 0xFD, 0x86, 0x1B, + 0x31, 0x41, 0x3D, 0xC8, 0x82, 0x59, 0x11, 0x34, + 0x1D, 0xE6, 0x98, 0xB1, 0x65, 0xDE, 0x3E, 0x52, + 0xD3, 0xA8, 0xBA, 0xF6, 0x0B, 0xA8, 0xC8, 0xA5, + 0x26, 0xF1, 0x4C, 0x85, 0x4F, 0xFF, 0x57, 0xD2, + 0x92, 0xD9, 0x1B, 0xEB, 0xAA, 0x3C, 0x15, 0xC2, + 0x5F, 0x74, 0x02, 0x4E, 0x96, 0xEE, 0x88, 0xFA, + 0x61, 0xE7, 0xFC, 0x92, 0x80, 0x8B, 0x52, 0xA0, + 0xC5, 0xB8, 0x2E, 0x5F, 0x77, 0xC7, 0xA7, 0x67, + 0x55, 0x2E, 0x99, 0x27, 0xFD, 0x47, 0x85, 0x47, + 0xEF, 0x34, 0x5F, 0x22, 0x7A, 0x60, 0x11, 0x71, + 0x5D, 0xA6, 0xC0, 0x06, 0xFE, 0x6B, 0x04, 0xC4, + 0xEC, 0xB5, 0x0F, 0x68, 0x15, 0xAB, 0xCB, 0x2E, + 0xE7, 0x3C, 0x86, 0xC1, 0x3C, 0x82, 0xE2, 0x3F, + 0x4F, 0x94, 0x2E, 0x48, 0xF5, 0xE8, 0xA8, 0xA0, + 0x65, 0x38, 0x54, 0xC7, 0x1F, 0xAF, 0x62, 0xA1, + 0x04, 0x36, 0x7F, 0xE1, 0x3B, 0xAD, 0x2F, 0xED, + 0x4A, 0x66, 0x6E, 0x13, 0x43, 0xC1, 0x1D, 0x55, + 0x4D, 0xD4, 0xDE, 0xFB, 0x81, 0x33, 0x59, 0x95, + 0x1E, 0x7C, 0x8F, 0x41, 0xDB, 0x4E, 0xE6, 0x63, + 0x25, 0x2E, 0x67, 0xA6, 0x7D, 0x28, 0xAE, 0x91, + 0xC3, 0x1A, 0x8A, 0x24, 0xFE, 0x69, 0xDE, 0xA2, + 0x33, 0x00, 0x84, 0x44, 0x62, 0x2A, 0x08, 0x64, + 0x5B, 0x02, 0xB6, 0xD0, 0x04, 0xBD, 0x44, 0xC1, + 0xC3, 0x5A, 0xC9, 0x6D, 0xF0, 0xC6, 0x61, 0x5E, + 0xDE, 0x05, 0xBF, 0xD9, 0xE4, 0x4A, 0x2A, 0xBC, + 0x86, 0xA1, 0x1B, 0x6D, 0xD0, 0x7E, 0x1E, 0xD2, + 0x69, 0x7F, 0xC3, 0xA3, 0x31, 0x41, 0x8A, 0xD9, + 0xF0, 0x6E, 0xDE, 0x5C, 0x7B, 0xCB, 0xA7, 0x4D, + 0xE8, 0x2E, 0x98, 0x2C, 0xB1, 0x0D, 0x23, 0x43, + 0x1D, 0x45, 0x2A, 0x03, 0x1D, 0x5F, 0xC0, 0x00, + 0x80, 0x5B, 0xDB, 0xF6, 0x2E, 0x3C, 0xFC, 0x18, + 0x49, 0xAF, 0x1A, 0x97, 0x70, 0xC3, 0x92, 0x65, + 0xE6, 0x1C, 0x90, 0xFF, 0x66, 0xE8, 0x8B, 0x8B, + 0x2B, 0xF0, 0xC4, 0x8C, 0x5A, 0x58, 0x1A, 0x53, + 0x11, 0xC9, 0x57, 0xDB, 0xB8, 0x18, 0xF8, 0xF4, + 0x65, 0x6E, 0x14, 0x68, 0x70, 0x7B, 0x3B, 0x1B, + 0x93, 0x48, 0x3E, 0x72, 0xAA, 0x36, 0xDC, 0x94, + 0xF0, 0xFA, 0x0D, 0x62, 0x08, 0x9A, 0x70, 0x72, + 0xF1, 0x0F, 0x58, 0x74, 0xAF, 0x9F, 0x33, 0xE2, + 0x82, 0x95, 0x33, 0x8F, 0xEC, 0x4C, 0xEC, 0x97, + 0x37, 0x0C, 0xB2, 0xDE, 0x1B, 0x5B, 0x0D, 0x8C, + 0x0C, 0x96, 0x16, 0x79, 0xF0, 0x72, 0x11, 0x09, + 0x8D, 0x27, 0xA6, 0xC9, 0x83, 0x1E, 0x62, 0x62, + 0xC2, 0x19, 0x2D, 0x56, 0x80, 0xF2, 0x8F, 0x19, + 0xB0, 0x62, 0x56, 0xF2, 0xD2, 0xF0, 0xBD, 0x61, + 0xAA, 0xBD, 0xCB, 0x67, 0x4B, 0x39, 0x04, 0x92, + 0x59, 0x1B, 0x3F, 0x3E, 0xFA, 0xCD, 0x81, 0x37, + 0x96, 0x74, 0xC1, 0x48, 0xCC, 0x59, 0x81, 0x45, + 0x67, 0xD7, 0x43, 0xA3, 0xC1, 0xF3, 0xB9, 0x7A, + 0x78, 0x8B, 0x3D, 0xB1, 0x61, 0xD1, 0xF7, 0x36, + 0xB6, 0x6D, 0xD7, 0xB1, 0x8C, 0xA6, 0xE6, 0xAE, + 0x8B, 0xB0, 0x0E, 0x62, 0x57, 0xED, 0x5F, 0xBB, + 0x3B, 0x52, 0xFE, 0x86, 0xFC, 0x21, 0x63, 0x71, + 0xEC, 0x61, 0x65, 0xC2, 0xE2, 0x85, 0x4E, 0x8F, + 0xD2, 0x02, 0x09, 0x67, 0x17, 0x89, 0x39, 0x99, + 0xED, 0xFB, 0x4B, 0xAC, 0xDE, 0x8B, 0x8B, 0x63, + 0xC9, 0x34, 0x3A, 0x52, 0x02, 0xE7, 0x25, 0xCE, + 0x6C, 0x25, 0xB8, 0xC8, 0xD2, 0x79, 0x4F, 0xEF, + 0xF6, 0xED, 0x3B, 0x9B, 0x83, 0xF1, 0xCA, 0x5C, + 0x4E, 0xFE, 0x54, 0xD8, 0x08, 0xB8, 0x00, 0xC4, + 0xE6, 0x2A, 0x92, 0x3C, 0xF9, 0x1F, 0xDD, 0xD7, + 0xAF, 0xD3, 0xC9, 0x2B, 0x75, 0xC5, 0xA5, 0x44, + 0xFD, 0x25, 0x21, 0x8E, 0xA9, 0xEF, 0xA4, 0x30, + 0xA6, 0x91, 0x22, 0xAB, 0x27, 0xB2, 0x1A, 0xDE, + 0xFC, 0x4B, 0xDF, 0x3F, 0x5D, 0x6F, 0x25, 0xE6, + 0xE4, 0x17, 0xA1, 0x2D, 0xFD, 0x4D, 0x6B, 0xAA, + 0x2A, 0xF1, 0x4B, 0x2D, 0x10, 0x32, 0x72, 0x3A, + 0x1F, 0x24, 0x9A, 0xF6, 0xE6, 0x52, 0x8F, 0x4D, + 0x6F, 0xD8, 0x4C, 0x88, 0x7A, 0x08, 0x74, 0xE2, + 0xC0, 0xD1, 0x6F, 0xE6, 0x67, 0xFF, 0x2E, 0xD7, + 0x54, 0x07, 0xE4, 0x20, 0xFC, 0x8E, 0x4E, 0x8E, + 0xCC, 0x4D, 0xAD, 0x73, 0xC1, 0x6D, 0xAF, 0x45, + 0xE7, 0xDC, 0x62, 0x0E, 0x04, 0x90, 0xF0, 0xC0, + 0x60, 0xBB, 0xCF, 0xBE, 0x30, 0x0C, 0xF0, 0x92, + 0x3F, 0xF8, 0xF3, 0x9D, 0x20, 0xC7, 0x8F, 0x9D, + 0x39, 0xE2, 0x32, 0x7D, 0x9B, 0xC9, 0xB4, 0x23, + 0x1F, 0xAA, 0x79, 0x5B, 0xA6, 0xEE, 0x8A, 0xE8, + 0x07, 0xFE, 0xE4, 0x92, 0xC2, 0x48, 0xA0, 0x68, + 0x08, 0xDB, 0x6D, 0x89, 0xF4, 0xA4, 0xCC, 0x0C, + 0x14, 0xCB, 0xF5, 0xCC, 0xB6, 0x6F, 0x2D, 0x0D, + 0x85, 0x5E, 0x40, 0x28, 0x52, 0xF8, 0xCF, 0x59, + 0xA3, 0x85, 0x35, 0x5A, 0x82, 0x32, 0x52, 0x33, + 0xF0, 0x28, 0x2F, 0x01, 0xDA, 0xD3, 0xE4, 0x01, + 0x3D, 0xC1, 0xAF, 0xC7, 0xDD, 0x70, 0x47, 0x0B, + 0x87, 0x41, 0x07, 0xCA, 0x57, 0xE4, 0x55, 0xD1, + 0x52, 0x50, 0x81, 0x08, 0x6A, 0xFD, 0x80, 0xB0, + 0x30, 0xEB, 0x6B, 0x46, 0x9E, 0xEF, 0xB8, 0x7B, + 0x5A, 0xBA, 0x0F, 0xDF, 0xC5, 0xF7, 0x55, 0x6B, + 0xFD, 0x6E, 0xDE, 0xD4, 0x1E, 0x85, 0x5D, 0x97, + 0xF5, 0x22, 0xB0, 0x0E, 0xDD, 0x6A, 0xA8, 0x63, + 0xE5, 0xAC, 0x11, 0x78, 0x70, 0x6A, 0xCA, 0x9D, + 0x37, 0xA5, 0xB1, 0x91, 0x61, 0x33, 0x1F, 0xFA, + 0x58, 0x88, 0x37, 0xA9, 0x7A, 0xC2, 0x50, 0xDC, + 0x7B, 0x82, 0x78, 0x32, 0xE6, 0x44, 0x39, 0x09, + 0x89, 0x52, 0xE8, 0x8E, 0xB3, 0x87, 0xC7, 0x0B, + 0x89, 0x4F, 0x09, 0xDD, 0x0F, 0x6D, 0x01, 0xE9, + 0xCB, 0x1B, 0xAA, 0x44, 0x97, 0x23, 0x99, 0xF3, + 0xD4, 0x27, 0xD7, 0x19, 0x8D, 0x15, 0x57, 0x9C, + 0x15, 0x2C, 0x96, 0xDE, 0xF4, 0x4F, 0x27, 0x15, + 0xD9, 0x25, 0x71, 0x51, 0xAC, 0x3E, 0x12, 0xF4, + 0x78, 0xB1, 0x1A, 0x86, 0x52, 0xE0, 0x9D, 0xAD, + 0x95, 0x44, 0x50, 0x30, 0xC0, 0xA2, 0xC9, 0x0E, + 0x0C, 0xDC, 0x6F, 0xD3, 0xA1, 0xD1, 0x36, 0xDC, + 0x40, 0x39, 0xC3, 0x87, 0x7D, 0xC6, 0xAF, 0x8D, + 0x01, 0xFE, 0xBA, 0xDD, 0x0D, 0x4F, 0x63, 0x84, + 0xE6, 0x71, 0xE2, 0xAC, 0x38, 0xAE, 0xC2, 0x10, + 0x8D, 0xA6, 0x1C, 0x72, 0xB7, 0xF7, 0x9B, 0x59, + 0xC4, 0xEF, 0x6F, 0x42, 0x9A, 0x0B, 0x5D, 0x9E, + 0x9C, 0x65, 0xD3, 0xFE, 0x11, 0xA2, 0x40, 0x98, + 0x4F, 0xA5, 0x21, 0x4E, 0x3A, 0xF2, 0x37, 0xCA, + 0x6F, 0x2C, 0x98, 0x56, 0xE7, 0x75, 0xB9, 0xA3, + 0xAB, 0x4A, 0x74, 0x10, 0x28, 0x90, 0xF0, 0xB8, + 0x9B, 0xA0, 0x1E, 0x72, 0x32, 0x80, 0x62, 0x81, + 0x04, 0x7D, 0xA2, 0xEC, 0xD4, 0x6C, 0x0C, 0x64, + 0xE6, 0x9F, 0x33, 0x08, 0x86, 0x5C, 0xC1, 0xA0, + 0x65, 0xBD, 0xBA, 0x92, 0x49, 0x40, 0x44, 0x21, + 0x0A, 0xF6, 0x5D, 0xC1, 0x19, 0xA9, 0xC9, 0xA8, + 0x6B, 0xB3, 0xC4, 0xEA, 0x31, 0x48, 0x7C, 0x19, + 0x33, 0xCF, 0xA1, 0xCF, 0xC5, 0x68, 0x5F, 0xC9, + 0x34, 0x11, 0xE1, 0x7B, 0x5C, 0xEC, 0xBA, 0x3B, + 0xBB, 0x6C, 0xD0, 0x9D, 0x73, 0xC0, 0xDC, 0xF0, + 0xC8, 0x11, 0x26, 0x74, 0xAF, 0xAD, 0xE6, 0x05, + 0x0D, 0x3E, 0x48, 0x9F, 0x57, 0x07, 0x6F, 0xAF, + 0x87, 0x5E, 0x4A, 0xEC, 0x6C, 0x39, 0xFE, 0x19, + 0x84, 0xAF, 0x2F, 0x02, 0xDA, 0x76, 0xCE, 0x89, + 0x9B, 0x44, 0xD3, 0xF9, 0x22, 0x8F, 0x1F, 0x72, + 0xF0, 0x0E, 0x0E, 0x47, 0xB2, 0x08, 0x75, 0x45, + 0xC5, 0x1E, 0x9E, 0xB3, 0x6B, 0x76, 0x14, 0xB1, + 0x31, 0xEA, 0x50, 0x3E, 0xFB, 0xBB, 0xED, 0x6C, + 0xEC, 0x17, 0x03, 0x4F, 0xB2, 0xE0, 0xA7, 0x56, + 0xED, 0x35, 0x1B, 0x74, 0x0C, 0x34, 0x15, 0x57, + 0x9E, 0x44, 0x50, 0x75, 0xAD, 0x36, 0xF4, 0xD1, + 0xB1, 0x4D, 0x4A, 0x11, 0xCA, 0xF8, 0x9A, 0x5F, + 0x2D, 0xF4, 0x45, 0xFB, 0x21, 0x97, 0x35, 0xF7, + 0x7F, 0x4C, 0xF9, 0x07, 0xDD, 0x69, 0x9B, 0x15, + 0x91, 0xC8, 0x30, 0x59, 0x23, 0xDD, 0xBF, 0xDF, + 0xF7, 0x6D, 0x79, 0x5B, 0x80, 0x92, 0xF0, 0x39, + 0x4B, 0xDE, 0x6F, 0xA1, 0x32, 0xA4, 0x66, 0xE8, + 0x61, 0x78, 0x80, 0xE4, 0xEE, 0x10, 0x76, 0x66, + 0x36, 0x99, 0xEF, 0x43, 0xEF, 0x9D, 0xB6, 0x51, + 0x03, 0x93, 0x0D, 0xCB, 0xCF, 0xAF, 0x1E, 0xFF, + 0xAD, 0x3D, 0xAF, 0xDE, 0xF6, 0x46, 0x10, 0x91, + 0x11, 0x07, 0xB3, 0xD3, 0x06, 0xAD, 0xAE, 0xD3, + 0x55, 0xB9, 0x3B, 0x26, 0xD5, 0x31, 0x61, 0xE5, + 0xA5, 0x65, 0x97, 0xBB, 0xE2, 0x13, 0x74, 0xD0, + 0x56, 0xA6, 0xA3, 0x1D, 0xC7, 0x77, 0x0C, 0x0E, + 0x12, 0xF1, 0xEA, 0x8B, 0x78, 0x73, 0xF1, 0x3D, + 0xBD, 0xB4, 0x0E, 0x63, 0x90, 0xEC, 0x66, 0x0C, + 0x56, 0x27, 0xC6, 0x31, 0x07, 0x6A, 0x00, 0x6D, + 0xE0, 0x86, 0x34, 0x7D, 0xC5, 0x5D, 0xF0, 0x32, + 0x0F, 0xD2, 0x68, 0x09, 0x91, 0xC0, 0xE1, 0x26, + 0xC2, 0x15, 0xB8, 0x16, 0x1C, 0xAE, 0xCE, 0x15, + 0x23, 0x28, 0x44, 0xE8, 0xE0, 0x81, 0x81, 0xDD, + 0xA3, 0x55, 0xEE, 0x10, 0xC4, 0x74, 0x3F, 0x44, + 0x54, 0x15, 0x63, 0x9F, 0xD6, 0x06, 0xFC, 0x1E, + 0x1C, 0xCB, 0x7C, 0x3B, 0x2F, 0x1F, 0xF5, 0xF5, + 0xF5, 0xAF, 0x79, 0x9F, 0x65, 0x82, 0x79, 0x5B, + 0xC6, 0xED, 0x76, 0x17, 0xD2, 0x92, 0xFE, 0x3C, + 0xA1, 0x8A, 0x0A, 0x07, 0xDF, 0xAF, 0xEF, 0x2F, + 0xEE, 0x7C, 0xC9, 0x04, 0x94, 0x27, 0x66, 0xE1, + 0x62, 0xEB, 0xFD, 0x90, 0x1A, 0xC8, 0x29, 0x29, + 0x89, 0x52, 0x76, 0x38, 0x60, 0x10, 0x50, 0x90, + 0xB0, 0xF2, 0x64, 0x9A, 0x20, 0x10, 0xB0, 0x50, + 0xD0, 0x89, 0x1B, 0xF6, 0xEE, 0x7E, 0x1E, 0x8E, + 0x86, 0x7D, 0x49, 0x41, 0x18, 0xCD, 0x8F, 0x6A, + 0xD7, 0x06, 0xA6, 0x80, 0x54, 0x5C, 0x16, 0x6F, + 0xEE, 0x39, 0x84, 0x08, 0xB1, 0x01, 0xB3, 0xD3, + 0x53, 0x59, 0xD8, 0xB7, 0xAF, 0x3F, 0x5F, 0x5D, + 0xFF, 0xA4, 0xD2, 0x9E, 0x46, 0xA6, 0x0A, 0xEA, + 0xB8, 0x7E, 0xC6, 0x68, 0xD2, 0xE2, 0x24, 0xF9, + 0x5C, 0x25, 0x33, 0xA3, 0xB9, 0x28, 0x48, 0x48, + 0xE8, 0x33, 0x77, 0x39, 0x6B, 0x2B, 0xC3, 0x42, + 0x62, 0x46, 0xE0, 0x0B, 0xCC, 0x8C, 0x2C, 0xCC, + 0x4C, 0xDC, 0xD1, 0x3F, 0xC5, 0xF9, 0x1B, 0xB7, + 0x37, 0x2E, 0x54, 0x3C, 0x33, 0xA8, 0x17, 0x86, + 0x4C, 0x94, 0xC2, 0x48, 0x83, 0x23, 0x63, 0xA3, + 0xA1, 0x5F, 0xED, 0x61, 0xB1, 0x01, 0x77, 0xBD, + 0x3A, 0xED, 0x55, 0xF8, 0x1B, 0xA8, 0xB4, 0x9C, + 0x10, 0x81, 0x4B, 0x1E, 0x06, 0x96, 0xF6, 0xE4, + 0x40, 0x1D, 0x6B, 0x27, 0xFF, 0xDF, 0x22, 0xF2, + 0xD2, 0x90, 0x06, 0xF8, 0x44, 0x72, 0xD2, 0x32, + 0xB2, 0x9B, 0x09, 0xE4, 0xFC, 0x6C, 0x0C, 0x4C, + 0x33, 0xF8, 0xBC, 0xB4, 0xED, 0x9D, 0xDD, 0x1D, + 0x4F, 0xF0, 0xC0, 0x6C, 0x94, 0x24, 0x8C, 0x40, + 0x68, 0x90, 0xD4, 0xB4, 0x6C, 0x6E, 0x02, 0xC3, + 0x81, 0x96, 0x22, 0xCE, 0xAD, 0x0C, 0x9C, 0xE7, + 0x47, 0x4E, 0xF4, 0x98, 0x82, 0x3E, 0x5F, 0x7D, + 0x9F, 0xC5, 0xF3, 0x53, 0x9A, 0xFA, 0x56, 0xB6, + 0xD3, 0xE0, 0xA9, 0x4D, 0xA6, 0x3B, 0x51, 0x19, + 0x91, 0xE7, 0x52, 0xDE, 0x0E, 0xBE, 0xC3, 0xF3, + 0x73, 0xA8, 0x12, 0x74, 0x49, 0xAD, 0xED, 0xAB, + 0xE6, 0xC2, 0xFC, 0xD5, 0xED, 0x55, 0x35, 0xE3, + 0x19, 0x3D, 0x4D, 0xC1, 0xE6, 0x56, 0x00, 0x81, + 0x01, 0x7B, 0x86, 0xE9, 0x80, 0x7C, 0x1F, 0x12, + 0x90, 0x2E, 0x70, 0x38, 0x51, 0xAF, 0xCC, 0x2C, + 0x86, 0xFD, 0xEA, 0xCB, 0x10, 0x6D, 0x0F, 0xAA, + 0xCD, 0x32, 0x35, 0x09, 0xD2, 0x42, 0x18, 0x78, + 0x3A, 0x22, 0x84, 0x49, 0xDE, 0x6D, 0x01, 0xC3, + 0x6A, 0xB2, 0x2D, 0x52, 0xA3, 0x30, 0x79, 0x8A, + 0xEF, 0xD1, 0x43, 0x9E, 0x14, 0xA7, 0xF7, 0x0D, + 0x2D, 0x34, 0x41, 0x3D, 0x44, 0xA5, 0xC6, 0xE3, + 0x87, 0x78, 0xC2, 0xA7, 0x4F, 0xC5, 0x05, 0xF7, + 0xB4, 0x7F, 0xE2, 0x17, 0xE6, 0x55, 0x1C, 0xCF, + 0xC4, 0x2C, 0xFC, 0x09, 0x25, 0x38, 0x5B, 0x29, + 0x09, 0x77, 0xED, 0xCD, 0xF0, 0x73, 0x3B, 0x5A, + 0x89, 0x51, 0x56, 0x6E, 0xB5, 0xC7, 0x64, 0x80, + 0x65, 0x5C, 0xCE, 0x13, 0x9D, 0x2E, 0x7E, 0x84, + 0xA4, 0xDE, 0x3D, 0x52, 0xB8, 0xCB, 0x8F, 0x82, + 0x01, 0x3F, 0x6A, 0x22, 0x4B, 0xA3, 0xC0, 0x30, + 0x8A, 0xF1, 0xE6, 0xDD, 0x06, 0x7B, 0x18, 0xBD, + 0xD8, 0x27, 0x20, 0x16, 0xCD, 0x4D, 0x17, 0x77, + 0x56, 0xD4, 0x61, 0xC0, 0x1B, 0x0E, 0x8A, 0x6E, + 0x5F, 0xD8, 0x6D, 0x31, 0xD3, 0xC3, 0x02, 0x99, + 0x1A, 0x0C, 0xB9, 0x70, 0x4B, 0xDF, 0x8F, 0x65, + 0x45, 0x83, 0xC5, 0xA9, 0x71, 0xC1, 0xBB, 0x7A, + 0xFA, 0x21, 0x97, 0xFB, 0x23, 0x93, 0x7F, 0xB2, + 0x30, 0x8B, 0xA9, 0xD3, 0x0B, 0xDB, 0xA6, 0x66, + 0xEC, 0x37, 0x03, 0x6B, 0x30, 0x84, 0x44, 0x97, + 0x15, 0xAE, 0x19, 0x75, 0xAD, 0x1D, 0x01, 0xD7, + 0x57, 0xEC, 0x26, 0x5C, 0x84, 0x54, 0x9C, 0x4A, + 0xCA, 0x71, 0x4F, 0x35, 0xED, 0x3D, 0xD5, 0x03, + 0x83, 0x38, 0x22, 0x58, 0x80, 0x50, 0x30, 0xF0, + 0x70, 0xAB, 0x1D, 0x71, 0xA9, 0x19, 0x79, 0xB9, + 0x39, 0xE2, 0x54, 0x38, 0xE0, 0x50, 0x30, 0xF0, + 0x70, 0xAB, 0x1D, 0x71, 0xA9, 0x19, 0x79, 0xB9, + 0x39, 0xE2, 0x54, 0x38, 0xE0, 0x50, 0x30, 0xF0, + 0x70, 0xAB, 0x1D, 0x71, 0xA9, 0x19, 0x79, 0xB9, + 0x39, 0xE2, 0x7C, 0x19, 0xC1, 0x11, 0x55, 0x9C, + 0x1C, 0xA7, 0x03, 0x5F, 0x87, 0x37, 0x97, 0x41, + 0xC1, 0x7A, 0x7C, 0x10, 0xC8, 0x78, 0x64, 0xA3, + 0x23, 0x98, 0x82, 0xE3, 0x39, 0xE9, 0x79, 0xBE, + 0x3E, 0x85, 0xC3, 0xA2, 0x78, 0xA8, 0xB8, 0x76, + 0xF4, 0x4F, 0xF1, 0x92, 0x48, 0x98, 0x44, 0x83, + 0x03, 0xB8, 0x86, 0xF9, 0x23, 0xF3, 0x3F, 0xEA, + 0x68, 0xD3, 0x53, 0x7E, 0xA6, 0x97, 0x45, 0x80, + 0xB1, 0xDA, 0x69, 0xA7, 0xDF, 0x6C, 0x9D, 0xEC, + 0x69, 0x10, 0xED, 0x81, 0xDB, 0x02, 0x62, 0xC7, + 0x46, 0x9D, 0x0E, 0x60, 0xB8, 0x2D, 0x49, 0x89, + 0xA8, 0xC0, 0x73, 0xAE, 0xC2, 0x77, 0xF2, 0xA3, + 0x04, 0xC2, 0x84, 0xE8, 0x30, 0x80, 0xD6, 0x57, + 0xD7, 0x3D, 0x3E, 0x57, 0xAE, 0xA8, 0xCD, 0x24, + 0x77, 0xB1, 0xF7, 0x9B, 0x43, 0xF3, 0xA5, 0x24, + 0xA4, 0xCE, 0xC0, 0xA9, 0x40, 0x4B, 0x2E, 0xCF, + 0xF3, 0x2D, 0x1A, 0xCC, 0x11, 0x30, 0xE7, 0x22, + 0x03, 0x61, 0xD2, 0x17, 0x16, 0x24, 0x2D, 0xFD, + 0x54, 0xAC, 0xA3, 0x56, 0x93, 0xD3, 0x85, 0x04, + 0x84, 0x6E, 0x6D, 0x04, 0xFD, 0xF0, 0x95, 0x7C, + 0x6F, 0xA9, 0xEF, 0x83, 0x5B, 0xEB, 0x8B, 0x4B, + 0xCB, 0x10, 0xA6, 0xCA, 0x12, 0xA2, 0xC2, 0x02, + 0x82, 0x59, 0xEE, 0x82, 0x5E, 0xEE, 0x76, 0xA0, + 0x22, 0x99, }; static unsigned char vfs5011_init_06[] = { /* 2855 B */ - 0x02, 0xB0, 0x00, 0x62, 0x00, 0x03, 0x00, 0x09, - 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, - 0x04, 0x30, 0x01, 0x80, 0x64, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, - 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, - 0x20, 0x04, 0x30, 0xE6, 0x03, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, - 0xE7, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x4C, 0x20, 0x04, 0x30, 0xE8, 0x03, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, - 0x04, 0x30, 0x00, 0x92, 0x01, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, - 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x40, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x60, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x90, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xD8, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, - 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, - 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, - 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, - 0x30, 0x00, 0x02, 0xA8, 0x02, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, - 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, - 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, - 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, - 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0xFF, 0x8B, 0x07, 0x20, 0x60, 0x8A, 0x07, 0x20, - 0xFF, 0x93, 0x07, 0x20, 0x61, 0x92, 0x07, 0x20, - 0xFF, 0x9B, 0x07, 0x20, 0x62, 0x9A, 0x07, 0x20, - 0xFF, 0xA3, 0x07, 0x20, 0x63, 0xA2, 0x07, 0x20, - 0xFF, 0xAB, 0x07, 0x20, 0x64, 0xAA, 0x07, 0x20, - 0xFF, 0xB3, 0x07, 0x20, 0x65, 0xB2, 0x07, 0x20, - 0xFF, 0xBB, 0x07, 0x20, 0x66, 0xBA, 0x07, 0x20, - 0xFF, 0xC3, 0x07, 0x20, 0x67, 0xC2, 0x07, 0x20, - 0xFF, 0xCB, 0x07, 0x20, 0x68, 0xCA, 0x07, 0x20, - 0xFF, 0xD3, 0x07, 0x20, 0x69, 0xD2, 0x07, 0x20, - 0xFF, 0xDB, 0x07, 0x20, 0x6A, 0xDA, 0x07, 0x20, - 0xFF, 0xE3, 0x07, 0x20, 0x6B, 0xE2, 0x07, 0x20, - 0xFF, 0xEB, 0x07, 0x20, 0x6C, 0xEA, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x6D, 0xF2, 0x07, 0x20, - 0xFF, 0xFB, 0x07, 0x20, 0x6E, 0xFA, 0x07, 0x20, - 0xFF, 0x85, 0x07, 0x20, 0x6F, 0x84, 0x07, 0x20, - 0xFF, 0x8D, 0x07, 0x20, 0x70, 0x8C, 0x07, 0x20, - 0xFF, 0x95, 0x07, 0x20, 0x71, 0x94, 0x07, 0x20, - 0xFF, 0x9D, 0x07, 0x20, 0x72, 0x9C, 0x07, 0x20, - 0xFF, 0xA5, 0x07, 0x20, 0x73, 0xA4, 0x07, 0x20, - 0xFF, 0xAD, 0x07, 0x20, 0x74, 0xAC, 0x07, 0x20, - 0xFF, 0xB5, 0x07, 0x20, 0x75, 0xB4, 0x07, 0x20, - 0xFF, 0xBD, 0x07, 0x20, 0x76, 0xBC, 0x07, 0x20, - 0xFF, 0xC5, 0x07, 0x20, 0x77, 0xC4, 0x07, 0x20, - 0xFF, 0xCD, 0x07, 0x20, 0x78, 0xCC, 0x07, 0x20, - 0xFF, 0xD5, 0x07, 0x20, 0x79, 0xD4, 0x07, 0x20, - 0xFF, 0xDD, 0x07, 0x20, 0x7A, 0xDC, 0x07, 0x20, - 0xFF, 0xE5, 0x07, 0x20, 0x7B, 0xE4, 0x07, 0x20, - 0xFF, 0xED, 0x07, 0x20, 0x7C, 0xEC, 0x07, 0x20, - 0xFF, 0xF5, 0x07, 0x20, 0x7D, 0xF4, 0x07, 0x20, - 0xFF, 0xFD, 0x07, 0x20, 0x7E, 0xFC, 0x07, 0x20, - 0xFF, 0x87, 0x07, 0x20, 0x7F, 0x86, 0x07, 0x20, - 0xFF, 0x8F, 0x07, 0x20, 0x80, 0x8E, 0x07, 0x20, - 0xFF, 0x97, 0x07, 0x20, 0x81, 0x96, 0x07, 0x20, - 0xFF, 0x9F, 0x07, 0x20, 0x82, 0x9E, 0x07, 0x20, - 0xFF, 0xA7, 0x07, 0x20, 0x83, 0xA6, 0x07, 0x20, - 0xFF, 0xAF, 0x07, 0x20, 0x84, 0xAE, 0x07, 0x20, - 0xFF, 0xB7, 0x07, 0x20, 0x85, 0xB6, 0x07, 0x20, - 0xFF, 0xBF, 0x07, 0x20, 0x86, 0xBE, 0x07, 0x20, - 0xFF, 0xC7, 0x07, 0x20, 0x87, 0xC6, 0x07, 0x20, - 0xFF, 0xCF, 0x07, 0x20, 0x88, 0xCE, 0x07, 0x20, - 0xFF, 0xD7, 0x07, 0x20, 0x89, 0xD6, 0x07, 0x20, - 0xFF, 0xDF, 0x07, 0x20, 0x8A, 0xDE, 0x07, 0x20, - 0xFF, 0xE7, 0x07, 0x20, 0x8B, 0xE6, 0x07, 0x20, - 0xFF, 0xEF, 0x07, 0x20, 0x8C, 0xEE, 0x07, 0x20, - 0xFF, 0xF7, 0x07, 0x20, 0x8D, 0xF6, 0x07, 0x20, - 0xFF, 0xFF, 0x07, 0x20, 0x8E, 0xFE, 0x07, 0x20, - 0xFF, 0x83, 0xA7, 0x00, 0x5F, 0x82, 0xA7, 0x00, - 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, - 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, - 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, - 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, - 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, - 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, - 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, - 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, - 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, - 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, - 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, - 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, - 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, - 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, - 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, - 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, - 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, - 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, - 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, - 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, - 0xFF, 0x83, 0x27, 0x20, 0x5F, 0x82, 0x27, 0x20, - 0xFF, 0x8B, 0x27, 0x20, 0x60, 0x8A, 0x27, 0x20, - 0xFF, 0x93, 0x27, 0x20, 0x61, 0x92, 0x27, 0x20, - 0xFF, 0x9B, 0x27, 0x20, 0x62, 0x9A, 0x27, 0x20, - 0xFF, 0xA3, 0x27, 0x20, 0x63, 0xA2, 0x27, 0x20, - 0xFF, 0xAB, 0x27, 0x20, 0x64, 0xAA, 0x27, 0x20, - 0xFF, 0xB3, 0x27, 0x20, 0x65, 0xB2, 0x27, 0x20, - 0xFF, 0xBB, 0x27, 0x20, 0x66, 0xBA, 0x27, 0x20, - 0xFF, 0xC3, 0x27, 0x20, 0x67, 0xC2, 0x27, 0x20, - 0xFF, 0xCB, 0x27, 0x20, 0x68, 0xCA, 0x27, 0x20, - 0xFF, 0xD3, 0x27, 0x20, 0x69, 0xD2, 0x27, 0x20, - 0xFF, 0xDB, 0x27, 0x20, 0x6A, 0xDA, 0x27, 0x20, - 0xFF, 0xE3, 0x27, 0x20, 0x6B, 0xE2, 0x27, 0x20, - 0xFF, 0xEB, 0x27, 0x20, 0x6C, 0xEA, 0x27, 0x20, - 0xFF, 0xF3, 0x27, 0x20, 0x6D, 0xF2, 0x27, 0x20, - 0xFF, 0xFB, 0x27, 0x20, 0x6E, 0xFA, 0x27, 0x20, - 0xFF, 0x85, 0x27, 0x20, 0x6F, 0x84, 0x27, 0x20, - 0xFF, 0x8D, 0x27, 0x20, 0x70, 0x8C, 0x27, 0x20, - 0xFF, 0x95, 0x27, 0x20, 0x71, 0x94, 0x27, 0x20, - 0xFF, 0x9D, 0x27, 0x20, 0x72, 0x9C, 0x27, 0x20, - 0xFF, 0xA5, 0x27, 0x20, 0x73, 0xA4, 0x27, 0x20, - 0xFF, 0xAD, 0x27, 0x20, 0x74, 0xAC, 0x27, 0x20, - 0xFF, 0xB5, 0x27, 0x20, 0x75, 0xB4, 0x27, 0x20, - 0xFF, 0xBD, 0x27, 0x20, 0x76, 0xBC, 0x27, 0x20, - 0xFF, 0xC5, 0x27, 0x20, 0x77, 0xC4, 0x27, 0x20, - 0xFF, 0xCD, 0x27, 0x20, 0x78, 0xCC, 0x27, 0x20, - 0xFF, 0xD5, 0x27, 0x20, 0x79, 0xD4, 0x27, 0x20, - 0xFF, 0xDD, 0x27, 0x20, 0x7A, 0xDC, 0x27, 0x20, - 0xFF, 0xE5, 0x27, 0x20, 0x7B, 0xE4, 0x27, 0x20, - 0xFF, 0xED, 0x27, 0x20, 0x7C, 0xEC, 0x27, 0x20, - 0xFF, 0xF5, 0x27, 0x20, 0x7D, 0xF4, 0x27, 0x20, - 0xFF, 0xFD, 0x27, 0x20, 0x7E, 0xFC, 0x27, 0x20, - 0xFF, 0x87, 0x27, 0x20, 0x7F, 0x86, 0x27, 0x20, - 0xFF, 0x8F, 0x27, 0x20, 0x80, 0x8E, 0x27, 0x20, - 0xFF, 0x97, 0x27, 0x20, 0x81, 0x96, 0x27, 0x20, - 0xFF, 0x9F, 0x27, 0x20, 0x82, 0x9E, 0x27, 0x20, - 0xFF, 0xA7, 0x27, 0x20, 0x83, 0xA6, 0x27, 0x20, - 0xFF, 0xAF, 0x27, 0x20, 0x84, 0xAE, 0x27, 0x20, - 0xFF, 0xB7, 0x27, 0x20, 0x85, 0xB6, 0x27, 0x20, - 0xFF, 0xBF, 0x27, 0x20, 0x86, 0xBE, 0x27, 0x20, - 0xFF, 0xC7, 0x27, 0x20, 0x87, 0xC6, 0x27, 0x20, - 0xFF, 0xCF, 0x27, 0x20, 0x88, 0xCE, 0x27, 0x20, - 0xFF, 0xD7, 0x27, 0x20, 0x89, 0xD6, 0x27, 0x20, - 0xFF, 0xDF, 0x27, 0x20, 0x8A, 0xDE, 0x27, 0x20, - 0xFF, 0xE7, 0x27, 0x20, 0x8B, 0xE6, 0x27, 0x20, - 0xFF, 0xEF, 0x27, 0x20, 0x8C, 0xEE, 0x27, 0x20, - 0xFF, 0xF7, 0x27, 0x20, 0x8D, 0xF6, 0x27, 0x20, - 0xFF, 0xFF, 0x27, 0x20, 0x8E, 0xFE, 0x27, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, - 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, - 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, - 0x04, 0x0C, 0x00, 0x01, 0x00, 0x00, 0x0D, 0x00, - 0x78, 0x01, 0x50, 0x01, 0x00, 0x00, 0x0E, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x6E, - 0x00, 0x65, 0x00, 0x65, 0x00, 0x72, 0x00, 0x69, - 0x00, 0x6E, 0x00, 0x67, 0x00, 0x5C, 0x00, 0x70, - 0x00, 0x72, 0x00, 0x69, 0x00, 0x76, 0x03, 0x00, - 0x00, 0x00, 0x0C, 0x00, 0x00, 0x38, 0x00, 0x07, - 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x0C, 0x00, - 0x00, 0x38, 0x02, 0x07, 0x00, 0x00, 0xFD, 0x00, - 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x38, 0x00, 0x08, - 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x0C, 0x00, - 0x00, 0x38, 0x02, 0x08, 0x00, 0x00, 0xFD, 0x00, - 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x38, 0x00, 0x02, - 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x0C, 0x00, - 0x00, 0x38, 0x02, 0x02, 0x00, 0x00, 0xFD, 0x00, - 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x38, 0x00, 0x03, - 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x0C, 0x00, - 0x00, 0x38, 0x02, 0x03, 0x00, 0x00, 0xFD, 0x00, - 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x38, 0x00, 0x04, - 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x0C, 0x00, - 0x00, 0x38, 0x02, 0x04, 0x00, 0x00, 0xFD, 0x00, - 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x38, 0x00, 0x05, - 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x0C, 0x00, - 0x00, 0x38, 0x02, 0x05, 0x00, 0x00, 0xFD, 0x00, - 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x38, 0x00, 0x06, - 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x0C, 0x00, - 0x00, 0x38, 0x02, 0x06, 0x00, 0x00, 0xFD, 0x00, - 0xFF, 0xFF, 0x10, 0x00, 0x00, 0x38, 0x02, 0x03, - 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x10, 0x00, - 0x00, 0x38, 0x00, 0x04, 0x00, 0x00, 0xFD, 0x00, - 0xFF, 0xFF, 0x10, 0x00, 0x00, 0x38, 0x02, 0x04, - 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x10, 0x00, - 0x00, 0x38, 0x00, 0x05, 0x00, 0x00, 0xFD, 0x00, - 0xFF, 0xFF, 0x10, 0x00, 0x00, 0x38, 0x02, 0x05, - 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x10, 0x00, - 0x00, 0x38, 0x00, 0x06, 0x00, 0x00, 0xFD, 0x00, - 0xFF, 0xFF, 0x10, 0x00, 0x00, 0x38, 0x02, 0x06, - 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x10, 0x00, - 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0xFD, 0x00, - 0xFF, 0xFF, 0x10, 0x00, 0x00, 0x38, 0x02, 0x07, - 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x10, 0x00, - 0x00, 0x38, 0x00, 0x08, 0x00, 0x00, 0xFD, 0x00, - 0xFF, 0xFF, 0x10, 0x00, 0x00, 0x38, 0x02, 0x08, - 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x10, 0x00, - 0x00, 0x38, 0x00, 0x09, 0x00, 0x00, 0xFD, 0x00, - 0xFF, 0xFF, 0x10, 0x00, 0x00, 0x38, 0x02, 0x09, - 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x10, 0x00, - 0x00, 0x38, 0x00, 0x0A, 0x00, 0x00, 0xFD, 0x00, - 0xFF, 0xFF, 0x0E, 0x00, 0xE0, 0x00, 0x00, 0x01, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x1F, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, - 0x01, 0x01, 0x00, 0x01, 0x00, 0x1F, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x00, 0x1F, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, - 0x02, 0x01, 0x01, 0x01, 0x00, 0x1F, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x1F, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, - 0x02, 0x01, 0x01, 0x01, 0x01, 0x1F, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, - 0x04, 0x01, 0x01, 0x01, 0x01, 0x1F, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, - 0x04, 0x01, 0x02, 0x01, 0x01, 0x1F, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, - 0x08, 0x01, 0x02, 0x01, 0x01, 0x1F, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, - 0x08, 0x01, 0x04, 0x01, 0x01, 0x1F, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, - 0x10, 0x01, 0x04, 0x01, 0x01, 0x1F, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, - 0x10, 0x01, 0x08, 0x01, 0x01, 0x1F, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, - 0x10, 0x01, 0x08, 0x01, 0x02, 0x1F, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, - 0x10, 0x01, 0x10, 0x01, 0x02, 0x1F, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x0F, 0x00, - 0x01, 0x00, 0x02, 0x10, 0x00, 0x01, 0x00, 0x01, - 0x11, 0x00, 0x02, 0x00, 0x0E, 0x00, 0x12, 0x00, - 0x01, 0x00, 0x0E, 0x15, 0x00, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x28, 0x00, 0x00, + 0x02, 0xB0, 0x00, 0x62, 0x00, 0x03, 0x00, 0x09, + 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, + 0x04, 0x30, 0x01, 0x80, 0x64, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, + 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, + 0x20, 0x04, 0x30, 0xE6, 0x03, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, + 0xE7, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x4C, 0x20, 0x04, 0x30, 0xE8, 0x03, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, + 0x04, 0x30, 0x00, 0x92, 0x01, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, + 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x40, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x60, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x90, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xD8, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, + 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, + 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, + 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, + 0x30, 0x00, 0x02, 0xA8, 0x02, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, + 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, + 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, + 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, + 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0xFF, 0x8B, 0x07, 0x20, 0x60, 0x8A, 0x07, 0x20, + 0xFF, 0x93, 0x07, 0x20, 0x61, 0x92, 0x07, 0x20, + 0xFF, 0x9B, 0x07, 0x20, 0x62, 0x9A, 0x07, 0x20, + 0xFF, 0xA3, 0x07, 0x20, 0x63, 0xA2, 0x07, 0x20, + 0xFF, 0xAB, 0x07, 0x20, 0x64, 0xAA, 0x07, 0x20, + 0xFF, 0xB3, 0x07, 0x20, 0x65, 0xB2, 0x07, 0x20, + 0xFF, 0xBB, 0x07, 0x20, 0x66, 0xBA, 0x07, 0x20, + 0xFF, 0xC3, 0x07, 0x20, 0x67, 0xC2, 0x07, 0x20, + 0xFF, 0xCB, 0x07, 0x20, 0x68, 0xCA, 0x07, 0x20, + 0xFF, 0xD3, 0x07, 0x20, 0x69, 0xD2, 0x07, 0x20, + 0xFF, 0xDB, 0x07, 0x20, 0x6A, 0xDA, 0x07, 0x20, + 0xFF, 0xE3, 0x07, 0x20, 0x6B, 0xE2, 0x07, 0x20, + 0xFF, 0xEB, 0x07, 0x20, 0x6C, 0xEA, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x6D, 0xF2, 0x07, 0x20, + 0xFF, 0xFB, 0x07, 0x20, 0x6E, 0xFA, 0x07, 0x20, + 0xFF, 0x85, 0x07, 0x20, 0x6F, 0x84, 0x07, 0x20, + 0xFF, 0x8D, 0x07, 0x20, 0x70, 0x8C, 0x07, 0x20, + 0xFF, 0x95, 0x07, 0x20, 0x71, 0x94, 0x07, 0x20, + 0xFF, 0x9D, 0x07, 0x20, 0x72, 0x9C, 0x07, 0x20, + 0xFF, 0xA5, 0x07, 0x20, 0x73, 0xA4, 0x07, 0x20, + 0xFF, 0xAD, 0x07, 0x20, 0x74, 0xAC, 0x07, 0x20, + 0xFF, 0xB5, 0x07, 0x20, 0x75, 0xB4, 0x07, 0x20, + 0xFF, 0xBD, 0x07, 0x20, 0x76, 0xBC, 0x07, 0x20, + 0xFF, 0xC5, 0x07, 0x20, 0x77, 0xC4, 0x07, 0x20, + 0xFF, 0xCD, 0x07, 0x20, 0x78, 0xCC, 0x07, 0x20, + 0xFF, 0xD5, 0x07, 0x20, 0x79, 0xD4, 0x07, 0x20, + 0xFF, 0xDD, 0x07, 0x20, 0x7A, 0xDC, 0x07, 0x20, + 0xFF, 0xE5, 0x07, 0x20, 0x7B, 0xE4, 0x07, 0x20, + 0xFF, 0xED, 0x07, 0x20, 0x7C, 0xEC, 0x07, 0x20, + 0xFF, 0xF5, 0x07, 0x20, 0x7D, 0xF4, 0x07, 0x20, + 0xFF, 0xFD, 0x07, 0x20, 0x7E, 0xFC, 0x07, 0x20, + 0xFF, 0x87, 0x07, 0x20, 0x7F, 0x86, 0x07, 0x20, + 0xFF, 0x8F, 0x07, 0x20, 0x80, 0x8E, 0x07, 0x20, + 0xFF, 0x97, 0x07, 0x20, 0x81, 0x96, 0x07, 0x20, + 0xFF, 0x9F, 0x07, 0x20, 0x82, 0x9E, 0x07, 0x20, + 0xFF, 0xA7, 0x07, 0x20, 0x83, 0xA6, 0x07, 0x20, + 0xFF, 0xAF, 0x07, 0x20, 0x84, 0xAE, 0x07, 0x20, + 0xFF, 0xB7, 0x07, 0x20, 0x85, 0xB6, 0x07, 0x20, + 0xFF, 0xBF, 0x07, 0x20, 0x86, 0xBE, 0x07, 0x20, + 0xFF, 0xC7, 0x07, 0x20, 0x87, 0xC6, 0x07, 0x20, + 0xFF, 0xCF, 0x07, 0x20, 0x88, 0xCE, 0x07, 0x20, + 0xFF, 0xD7, 0x07, 0x20, 0x89, 0xD6, 0x07, 0x20, + 0xFF, 0xDF, 0x07, 0x20, 0x8A, 0xDE, 0x07, 0x20, + 0xFF, 0xE7, 0x07, 0x20, 0x8B, 0xE6, 0x07, 0x20, + 0xFF, 0xEF, 0x07, 0x20, 0x8C, 0xEE, 0x07, 0x20, + 0xFF, 0xF7, 0x07, 0x20, 0x8D, 0xF6, 0x07, 0x20, + 0xFF, 0xFF, 0x07, 0x20, 0x8E, 0xFE, 0x07, 0x20, + 0xFF, 0x83, 0xA7, 0x00, 0x5F, 0x82, 0xA7, 0x00, + 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, + 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, + 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, + 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, + 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, + 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, + 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, + 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, + 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, + 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, + 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, + 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, + 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, + 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, + 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, + 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, + 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, + 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, + 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, + 0xFF, 0x83, 0x27, 0x00, 0x5F, 0x82, 0x27, 0x00, + 0xFF, 0x83, 0x27, 0x20, 0x5F, 0x82, 0x27, 0x20, + 0xFF, 0x8B, 0x27, 0x20, 0x60, 0x8A, 0x27, 0x20, + 0xFF, 0x93, 0x27, 0x20, 0x61, 0x92, 0x27, 0x20, + 0xFF, 0x9B, 0x27, 0x20, 0x62, 0x9A, 0x27, 0x20, + 0xFF, 0xA3, 0x27, 0x20, 0x63, 0xA2, 0x27, 0x20, + 0xFF, 0xAB, 0x27, 0x20, 0x64, 0xAA, 0x27, 0x20, + 0xFF, 0xB3, 0x27, 0x20, 0x65, 0xB2, 0x27, 0x20, + 0xFF, 0xBB, 0x27, 0x20, 0x66, 0xBA, 0x27, 0x20, + 0xFF, 0xC3, 0x27, 0x20, 0x67, 0xC2, 0x27, 0x20, + 0xFF, 0xCB, 0x27, 0x20, 0x68, 0xCA, 0x27, 0x20, + 0xFF, 0xD3, 0x27, 0x20, 0x69, 0xD2, 0x27, 0x20, + 0xFF, 0xDB, 0x27, 0x20, 0x6A, 0xDA, 0x27, 0x20, + 0xFF, 0xE3, 0x27, 0x20, 0x6B, 0xE2, 0x27, 0x20, + 0xFF, 0xEB, 0x27, 0x20, 0x6C, 0xEA, 0x27, 0x20, + 0xFF, 0xF3, 0x27, 0x20, 0x6D, 0xF2, 0x27, 0x20, + 0xFF, 0xFB, 0x27, 0x20, 0x6E, 0xFA, 0x27, 0x20, + 0xFF, 0x85, 0x27, 0x20, 0x6F, 0x84, 0x27, 0x20, + 0xFF, 0x8D, 0x27, 0x20, 0x70, 0x8C, 0x27, 0x20, + 0xFF, 0x95, 0x27, 0x20, 0x71, 0x94, 0x27, 0x20, + 0xFF, 0x9D, 0x27, 0x20, 0x72, 0x9C, 0x27, 0x20, + 0xFF, 0xA5, 0x27, 0x20, 0x73, 0xA4, 0x27, 0x20, + 0xFF, 0xAD, 0x27, 0x20, 0x74, 0xAC, 0x27, 0x20, + 0xFF, 0xB5, 0x27, 0x20, 0x75, 0xB4, 0x27, 0x20, + 0xFF, 0xBD, 0x27, 0x20, 0x76, 0xBC, 0x27, 0x20, + 0xFF, 0xC5, 0x27, 0x20, 0x77, 0xC4, 0x27, 0x20, + 0xFF, 0xCD, 0x27, 0x20, 0x78, 0xCC, 0x27, 0x20, + 0xFF, 0xD5, 0x27, 0x20, 0x79, 0xD4, 0x27, 0x20, + 0xFF, 0xDD, 0x27, 0x20, 0x7A, 0xDC, 0x27, 0x20, + 0xFF, 0xE5, 0x27, 0x20, 0x7B, 0xE4, 0x27, 0x20, + 0xFF, 0xED, 0x27, 0x20, 0x7C, 0xEC, 0x27, 0x20, + 0xFF, 0xF5, 0x27, 0x20, 0x7D, 0xF4, 0x27, 0x20, + 0xFF, 0xFD, 0x27, 0x20, 0x7E, 0xFC, 0x27, 0x20, + 0xFF, 0x87, 0x27, 0x20, 0x7F, 0x86, 0x27, 0x20, + 0xFF, 0x8F, 0x27, 0x20, 0x80, 0x8E, 0x27, 0x20, + 0xFF, 0x97, 0x27, 0x20, 0x81, 0x96, 0x27, 0x20, + 0xFF, 0x9F, 0x27, 0x20, 0x82, 0x9E, 0x27, 0x20, + 0xFF, 0xA7, 0x27, 0x20, 0x83, 0xA6, 0x27, 0x20, + 0xFF, 0xAF, 0x27, 0x20, 0x84, 0xAE, 0x27, 0x20, + 0xFF, 0xB7, 0x27, 0x20, 0x85, 0xB6, 0x27, 0x20, + 0xFF, 0xBF, 0x27, 0x20, 0x86, 0xBE, 0x27, 0x20, + 0xFF, 0xC7, 0x27, 0x20, 0x87, 0xC6, 0x27, 0x20, + 0xFF, 0xCF, 0x27, 0x20, 0x88, 0xCE, 0x27, 0x20, + 0xFF, 0xD7, 0x27, 0x20, 0x89, 0xD6, 0x27, 0x20, + 0xFF, 0xDF, 0x27, 0x20, 0x8A, 0xDE, 0x27, 0x20, + 0xFF, 0xE7, 0x27, 0x20, 0x8B, 0xE6, 0x27, 0x20, + 0xFF, 0xEF, 0x27, 0x20, 0x8C, 0xEE, 0x27, 0x20, + 0xFF, 0xF7, 0x27, 0x20, 0x8D, 0xF6, 0x27, 0x20, + 0xFF, 0xFF, 0x27, 0x20, 0x8E, 0xFE, 0x27, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, + 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, + 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, + 0x04, 0x0C, 0x00, 0x01, 0x00, 0x00, 0x0D, 0x00, + 0x78, 0x01, 0x50, 0x01, 0x00, 0x00, 0x0E, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x6E, + 0x00, 0x65, 0x00, 0x65, 0x00, 0x72, 0x00, 0x69, + 0x00, 0x6E, 0x00, 0x67, 0x00, 0x5C, 0x00, 0x70, + 0x00, 0x72, 0x00, 0x69, 0x00, 0x76, 0x03, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x38, 0x00, 0x07, + 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x0C, 0x00, + 0x00, 0x38, 0x02, 0x07, 0x00, 0x00, 0xFD, 0x00, + 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x38, 0x00, 0x08, + 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x0C, 0x00, + 0x00, 0x38, 0x02, 0x08, 0x00, 0x00, 0xFD, 0x00, + 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x38, 0x00, 0x02, + 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x0C, 0x00, + 0x00, 0x38, 0x02, 0x02, 0x00, 0x00, 0xFD, 0x00, + 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x38, 0x00, 0x03, + 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x0C, 0x00, + 0x00, 0x38, 0x02, 0x03, 0x00, 0x00, 0xFD, 0x00, + 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x38, 0x00, 0x04, + 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x0C, 0x00, + 0x00, 0x38, 0x02, 0x04, 0x00, 0x00, 0xFD, 0x00, + 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x38, 0x00, 0x05, + 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x0C, 0x00, + 0x00, 0x38, 0x02, 0x05, 0x00, 0x00, 0xFD, 0x00, + 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x38, 0x00, 0x06, + 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x0C, 0x00, + 0x00, 0x38, 0x02, 0x06, 0x00, 0x00, 0xFD, 0x00, + 0xFF, 0xFF, 0x10, 0x00, 0x00, 0x38, 0x02, 0x03, + 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x10, 0x00, + 0x00, 0x38, 0x00, 0x04, 0x00, 0x00, 0xFD, 0x00, + 0xFF, 0xFF, 0x10, 0x00, 0x00, 0x38, 0x02, 0x04, + 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x10, 0x00, + 0x00, 0x38, 0x00, 0x05, 0x00, 0x00, 0xFD, 0x00, + 0xFF, 0xFF, 0x10, 0x00, 0x00, 0x38, 0x02, 0x05, + 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x10, 0x00, + 0x00, 0x38, 0x00, 0x06, 0x00, 0x00, 0xFD, 0x00, + 0xFF, 0xFF, 0x10, 0x00, 0x00, 0x38, 0x02, 0x06, + 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x10, 0x00, + 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0xFD, 0x00, + 0xFF, 0xFF, 0x10, 0x00, 0x00, 0x38, 0x02, 0x07, + 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x10, 0x00, + 0x00, 0x38, 0x00, 0x08, 0x00, 0x00, 0xFD, 0x00, + 0xFF, 0xFF, 0x10, 0x00, 0x00, 0x38, 0x02, 0x08, + 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x10, 0x00, + 0x00, 0x38, 0x00, 0x09, 0x00, 0x00, 0xFD, 0x00, + 0xFF, 0xFF, 0x10, 0x00, 0x00, 0x38, 0x02, 0x09, + 0x00, 0x00, 0xFD, 0x00, 0xFF, 0xFF, 0x10, 0x00, + 0x00, 0x38, 0x00, 0x0A, 0x00, 0x00, 0xFD, 0x00, + 0xFF, 0xFF, 0x0E, 0x00, 0xE0, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x1F, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, + 0x01, 0x01, 0x00, 0x01, 0x00, 0x1F, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x00, 0x1F, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x00, 0x1F, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x1F, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x1F, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, + 0x04, 0x01, 0x01, 0x01, 0x01, 0x1F, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, + 0x04, 0x01, 0x02, 0x01, 0x01, 0x1F, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, + 0x08, 0x01, 0x02, 0x01, 0x01, 0x1F, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, + 0x08, 0x01, 0x04, 0x01, 0x01, 0x1F, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, + 0x10, 0x01, 0x04, 0x01, 0x01, 0x1F, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, + 0x10, 0x01, 0x08, 0x01, 0x01, 0x1F, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, + 0x10, 0x01, 0x08, 0x01, 0x02, 0x1F, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x01, 0x02, 0x1F, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x0F, 0x00, + 0x01, 0x00, 0x02, 0x10, 0x00, 0x01, 0x00, 0x01, + 0x11, 0x00, 0x02, 0x00, 0x0E, 0x00, 0x12, 0x00, + 0x01, 0x00, 0x0E, 0x15, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x28, 0x00, 0x00, }; static unsigned char vfs5011_init_07[] = { /* 2503 B */ - 0x02, 0xB0, 0x00, 0x00, 0x01, 0x03, 0x00, 0x09, - 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, - 0x04, 0x30, 0x01, 0x80, 0x4F, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, - 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, - 0x20, 0x04, 0x30, 0xE6, 0x03, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, - 0xE7, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x4C, 0x20, 0x04, 0x30, 0xE8, 0x03, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, - 0x04, 0x30, 0x00, 0x3E, 0x01, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x04, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, - 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x18, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, - 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x40, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, - 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x54, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x60, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, - 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x90, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, - 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xCC, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xD8, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, - 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, - 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, - 0x00, 0x40, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, - 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, - 0x30, 0x00, 0x02, 0xA8, 0x02, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, - 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, - 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, - 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, - 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0xFF, 0x8B, 0x07, 0x20, 0x60, 0x8A, 0x07, 0x20, - 0xFF, 0x93, 0x07, 0x20, 0x61, 0x92, 0x07, 0x20, - 0xFF, 0x9B, 0x07, 0x20, 0x62, 0x9A, 0x07, 0x20, - 0xFF, 0xA3, 0x07, 0x20, 0x63, 0xA2, 0x07, 0x20, - 0xFF, 0xAB, 0x07, 0x20, 0x64, 0xAA, 0x07, 0x20, - 0xFF, 0xB3, 0x07, 0x20, 0x65, 0xB2, 0x07, 0x20, - 0xFF, 0xBB, 0x07, 0x20, 0x66, 0xBA, 0x07, 0x20, - 0xFF, 0xC3, 0x07, 0x20, 0x67, 0xC2, 0x07, 0x20, - 0xFF, 0xCB, 0x07, 0x20, 0x68, 0xCA, 0x07, 0x20, - 0xFF, 0xD3, 0x07, 0x20, 0x69, 0xD2, 0x07, 0x20, - 0xFF, 0xDB, 0x07, 0x20, 0x6A, 0xDA, 0x07, 0x20, - 0xFF, 0xE3, 0x07, 0x20, 0x6B, 0xE2, 0x07, 0x20, - 0xFF, 0xEB, 0x07, 0x20, 0x6C, 0xEA, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x6D, 0xF2, 0x07, 0x20, - 0xFF, 0xFB, 0x07, 0x20, 0x6E, 0xFA, 0x07, 0x20, - 0xFF, 0x85, 0x07, 0x20, 0x6F, 0x84, 0x07, 0x20, - 0xFF, 0x8D, 0x07, 0x20, 0x70, 0x8C, 0x07, 0x20, - 0xFF, 0x95, 0x07, 0x20, 0x71, 0x94, 0x07, 0x20, - 0xFF, 0x9D, 0x07, 0x20, 0x72, 0x9C, 0x07, 0x20, - 0xFF, 0xA5, 0x07, 0x20, 0x73, 0xA4, 0x07, 0x20, - 0xFF, 0xAD, 0x07, 0x20, 0x74, 0xAC, 0x07, 0x20, - 0xFF, 0xB5, 0x07, 0x20, 0x75, 0xB4, 0x07, 0x20, - 0xFF, 0xBD, 0x07, 0x20, 0x76, 0xBC, 0x07, 0x20, - 0xFF, 0xC5, 0x07, 0x20, 0x77, 0xC4, 0x07, 0x20, - 0xFF, 0xCD, 0x07, 0x20, 0x78, 0xCC, 0x07, 0x20, - 0xFF, 0xD5, 0x07, 0x20, 0x79, 0xD4, 0x07, 0x20, - 0xFF, 0xDD, 0x07, 0x20, 0x7A, 0xDC, 0x07, 0x20, - 0xFF, 0xE5, 0x07, 0x20, 0x7B, 0xE4, 0x07, 0x20, - 0xFF, 0xED, 0x07, 0x20, 0x7C, 0xEC, 0x07, 0x20, - 0xFF, 0xF5, 0x07, 0x20, 0x7D, 0xF4, 0x07, 0x20, - 0xFF, 0xFD, 0x07, 0x20, 0x7E, 0xFC, 0x07, 0x20, - 0xFF, 0x87, 0x07, 0x20, 0x7F, 0x86, 0x07, 0x20, - 0xFF, 0x8F, 0x07, 0x20, 0x80, 0x8E, 0x07, 0x20, - 0xFF, 0x97, 0x07, 0x20, 0x81, 0x96, 0x07, 0x20, - 0xFF, 0x9F, 0x07, 0x20, 0x82, 0x9E, 0x07, 0x20, - 0xFF, 0xA7, 0x07, 0x20, 0x83, 0xA6, 0x07, 0x20, - 0xFF, 0xAF, 0x07, 0x20, 0x84, 0xAE, 0x07, 0x20, - 0xFF, 0xB7, 0x07, 0x20, 0x85, 0xB6, 0x07, 0x20, - 0xFF, 0xBF, 0x07, 0x20, 0x86, 0xBE, 0x07, 0x20, - 0xFF, 0xC7, 0x07, 0x20, 0x87, 0xC6, 0x07, 0x20, - 0xFF, 0xCF, 0x07, 0x20, 0x88, 0xCE, 0x07, 0x20, - 0xFF, 0xD7, 0x07, 0x20, 0x89, 0xD6, 0x07, 0x20, - 0xFF, 0xDF, 0x07, 0x20, 0x8A, 0xDE, 0x07, 0x20, - 0xFF, 0xE7, 0x07, 0x20, 0x8B, 0xE6, 0x07, 0x20, - 0xFF, 0xEF, 0x07, 0x20, 0x8C, 0xEE, 0x07, 0x20, - 0xFF, 0xF7, 0x07, 0x20, 0x8D, 0xF6, 0x07, 0x20, - 0xFF, 0xFF, 0x07, 0x20, 0x8E, 0xFE, 0x07, 0x20, - 0xFF, 0xFF, 0x07, 0x20, 0x8E, 0xFE, 0x07, 0x20, - 0xFF, 0xF7, 0x07, 0x20, 0x8D, 0xF6, 0x07, 0x20, - 0xFF, 0xEF, 0x07, 0x20, 0x8C, 0xEE, 0x07, 0x20, - 0xFF, 0xE7, 0x07, 0x20, 0x8B, 0xE6, 0x07, 0x20, - 0xFF, 0xDF, 0x07, 0x20, 0x8A, 0xDE, 0x07, 0x20, - 0xFF, 0xD7, 0x07, 0x20, 0x89, 0xD6, 0x07, 0x20, - 0xFF, 0xCF, 0x07, 0x20, 0x88, 0xCE, 0x07, 0x20, - 0xFF, 0xC7, 0x07, 0x20, 0x87, 0xC6, 0x07, 0x20, - 0xFF, 0xBF, 0x07, 0x20, 0x86, 0xBE, 0x07, 0x20, - 0xFF, 0xB7, 0x07, 0x20, 0x85, 0xB6, 0x07, 0x20, - 0xFF, 0xAF, 0x07, 0x20, 0x84, 0xAE, 0x07, 0x20, - 0xFF, 0xA7, 0x07, 0x20, 0x83, 0xA6, 0x07, 0x20, - 0xFF, 0x9F, 0x07, 0x20, 0x82, 0x9E, 0x07, 0x20, - 0xFF, 0x97, 0x07, 0x20, 0x81, 0x96, 0x07, 0x20, - 0xFF, 0x8F, 0x07, 0x20, 0x80, 0x8E, 0x07, 0x20, - 0xFF, 0x87, 0x07, 0x20, 0x7F, 0x86, 0x07, 0x20, - 0xFF, 0xFD, 0x07, 0x20, 0x7E, 0xFC, 0x07, 0x20, - 0xFF, 0xF5, 0x07, 0x20, 0x7D, 0xF4, 0x07, 0x20, - 0xFF, 0xED, 0x07, 0x20, 0x7C, 0xEC, 0x07, 0x20, - 0xFF, 0xE5, 0x07, 0x20, 0x7B, 0xE4, 0x07, 0x20, - 0xFF, 0xDD, 0x07, 0x20, 0x7A, 0xDC, 0x07, 0x20, - 0xFF, 0xD5, 0x07, 0x20, 0x79, 0xD4, 0x07, 0x20, - 0xFF, 0xCD, 0x07, 0x20, 0x78, 0xCC, 0x07, 0x20, - 0xFF, 0xC5, 0x07, 0x20, 0x77, 0xC4, 0x07, 0x20, - 0xFF, 0xBD, 0x07, 0x20, 0x76, 0xBC, 0x07, 0x20, - 0xFF, 0xB5, 0x07, 0x20, 0x75, 0xB4, 0x07, 0x20, - 0xFF, 0xAD, 0x07, 0x20, 0x74, 0xAC, 0x07, 0x20, - 0xFF, 0xA5, 0x07, 0x20, 0x73, 0xA4, 0x07, 0x20, - 0xFF, 0x9D, 0x07, 0x20, 0x72, 0x9C, 0x07, 0x20, - 0xFF, 0x95, 0x07, 0x20, 0x71, 0x94, 0x07, 0x20, - 0xFF, 0x8D, 0x07, 0x20, 0x70, 0x8C, 0x07, 0x20, - 0xFF, 0x85, 0x07, 0x20, 0x6F, 0x84, 0x07, 0x20, - 0xFF, 0xFB, 0x07, 0x20, 0x6E, 0xFA, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x6D, 0xF2, 0x07, 0x20, - 0xFF, 0xEB, 0x07, 0x20, 0x6C, 0xEA, 0x07, 0x20, - 0xFF, 0xE3, 0x07, 0x20, 0x6B, 0xE2, 0x07, 0x20, - 0xFF, 0xDB, 0x07, 0x20, 0x6A, 0xDA, 0x07, 0x20, - 0xFF, 0xD3, 0x07, 0x20, 0x69, 0xD2, 0x07, 0x20, - 0xFF, 0xCB, 0x07, 0x20, 0x68, 0xCA, 0x07, 0x20, - 0xFF, 0xC3, 0x07, 0x20, 0x67, 0xC2, 0x07, 0x20, - 0xFF, 0xBB, 0x07, 0x20, 0x66, 0xBA, 0x07, 0x20, - 0xFF, 0xB3, 0x07, 0x20, 0x65, 0xB2, 0x07, 0x20, - 0xFF, 0xAB, 0x07, 0x20, 0x64, 0xAA, 0x07, 0x20, - 0xFF, 0xA3, 0x07, 0x20, 0x63, 0xA2, 0x07, 0x20, - 0xFF, 0x9B, 0x07, 0x20, 0x62, 0x9A, 0x07, 0x20, - 0xFF, 0x93, 0x07, 0x20, 0x61, 0x92, 0x07, 0x20, - 0xFF, 0x8B, 0x07, 0x20, 0x60, 0x8A, 0x07, 0x20, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, - 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, - 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, - 0x04, 0x0C, 0x00, 0x01, 0x00, 0x03, 0x0D, 0x00, - 0x28, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x00, - 0x00, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x1C, 0x02, 0xB0, 0x01, 0x00, - 0x00, 0x00, 0x0E, 0x00, 0x10, 0x00, 0x00, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x01, 0x1F, 0x08, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x00, - 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x00, 0x01, - 0x11, 0x00, 0x02, 0x00, 0x00, 0x01, 0x12, 0x00, - 0x01, 0x00, 0x01, 0x05, 0x00, 0x0E, 0x00, 0x0C, - 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x08, 0x00, 0x00, 0x05, 0x00, 0x0E, - 0x00, 0x10, 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, - 0x00, 0x09, 0x00, 0x04, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x08, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x0C, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x10, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x14, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x18, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x44, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x48, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x4C, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x50, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x58, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x15, 0x00, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x28, 0x00, 0x00, + 0x02, 0xB0, 0x00, 0x00, 0x01, 0x03, 0x00, 0x09, + 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, + 0x04, 0x30, 0x01, 0x80, 0x4F, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, + 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, + 0x20, 0x04, 0x30, 0xE6, 0x03, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, + 0xE7, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x4C, 0x20, 0x04, 0x30, 0xE8, 0x03, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, + 0x04, 0x30, 0x00, 0x3E, 0x01, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x04, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, + 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x18, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, + 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x40, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, + 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x54, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x60, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, + 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x90, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, + 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xCC, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xD8, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, + 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, + 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, + 0x00, 0x40, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, + 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, + 0x30, 0x00, 0x02, 0xA8, 0x02, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, + 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, + 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, + 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, + 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0xFF, 0x8B, 0x07, 0x20, 0x60, 0x8A, 0x07, 0x20, + 0xFF, 0x93, 0x07, 0x20, 0x61, 0x92, 0x07, 0x20, + 0xFF, 0x9B, 0x07, 0x20, 0x62, 0x9A, 0x07, 0x20, + 0xFF, 0xA3, 0x07, 0x20, 0x63, 0xA2, 0x07, 0x20, + 0xFF, 0xAB, 0x07, 0x20, 0x64, 0xAA, 0x07, 0x20, + 0xFF, 0xB3, 0x07, 0x20, 0x65, 0xB2, 0x07, 0x20, + 0xFF, 0xBB, 0x07, 0x20, 0x66, 0xBA, 0x07, 0x20, + 0xFF, 0xC3, 0x07, 0x20, 0x67, 0xC2, 0x07, 0x20, + 0xFF, 0xCB, 0x07, 0x20, 0x68, 0xCA, 0x07, 0x20, + 0xFF, 0xD3, 0x07, 0x20, 0x69, 0xD2, 0x07, 0x20, + 0xFF, 0xDB, 0x07, 0x20, 0x6A, 0xDA, 0x07, 0x20, + 0xFF, 0xE3, 0x07, 0x20, 0x6B, 0xE2, 0x07, 0x20, + 0xFF, 0xEB, 0x07, 0x20, 0x6C, 0xEA, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x6D, 0xF2, 0x07, 0x20, + 0xFF, 0xFB, 0x07, 0x20, 0x6E, 0xFA, 0x07, 0x20, + 0xFF, 0x85, 0x07, 0x20, 0x6F, 0x84, 0x07, 0x20, + 0xFF, 0x8D, 0x07, 0x20, 0x70, 0x8C, 0x07, 0x20, + 0xFF, 0x95, 0x07, 0x20, 0x71, 0x94, 0x07, 0x20, + 0xFF, 0x9D, 0x07, 0x20, 0x72, 0x9C, 0x07, 0x20, + 0xFF, 0xA5, 0x07, 0x20, 0x73, 0xA4, 0x07, 0x20, + 0xFF, 0xAD, 0x07, 0x20, 0x74, 0xAC, 0x07, 0x20, + 0xFF, 0xB5, 0x07, 0x20, 0x75, 0xB4, 0x07, 0x20, + 0xFF, 0xBD, 0x07, 0x20, 0x76, 0xBC, 0x07, 0x20, + 0xFF, 0xC5, 0x07, 0x20, 0x77, 0xC4, 0x07, 0x20, + 0xFF, 0xCD, 0x07, 0x20, 0x78, 0xCC, 0x07, 0x20, + 0xFF, 0xD5, 0x07, 0x20, 0x79, 0xD4, 0x07, 0x20, + 0xFF, 0xDD, 0x07, 0x20, 0x7A, 0xDC, 0x07, 0x20, + 0xFF, 0xE5, 0x07, 0x20, 0x7B, 0xE4, 0x07, 0x20, + 0xFF, 0xED, 0x07, 0x20, 0x7C, 0xEC, 0x07, 0x20, + 0xFF, 0xF5, 0x07, 0x20, 0x7D, 0xF4, 0x07, 0x20, + 0xFF, 0xFD, 0x07, 0x20, 0x7E, 0xFC, 0x07, 0x20, + 0xFF, 0x87, 0x07, 0x20, 0x7F, 0x86, 0x07, 0x20, + 0xFF, 0x8F, 0x07, 0x20, 0x80, 0x8E, 0x07, 0x20, + 0xFF, 0x97, 0x07, 0x20, 0x81, 0x96, 0x07, 0x20, + 0xFF, 0x9F, 0x07, 0x20, 0x82, 0x9E, 0x07, 0x20, + 0xFF, 0xA7, 0x07, 0x20, 0x83, 0xA6, 0x07, 0x20, + 0xFF, 0xAF, 0x07, 0x20, 0x84, 0xAE, 0x07, 0x20, + 0xFF, 0xB7, 0x07, 0x20, 0x85, 0xB6, 0x07, 0x20, + 0xFF, 0xBF, 0x07, 0x20, 0x86, 0xBE, 0x07, 0x20, + 0xFF, 0xC7, 0x07, 0x20, 0x87, 0xC6, 0x07, 0x20, + 0xFF, 0xCF, 0x07, 0x20, 0x88, 0xCE, 0x07, 0x20, + 0xFF, 0xD7, 0x07, 0x20, 0x89, 0xD6, 0x07, 0x20, + 0xFF, 0xDF, 0x07, 0x20, 0x8A, 0xDE, 0x07, 0x20, + 0xFF, 0xE7, 0x07, 0x20, 0x8B, 0xE6, 0x07, 0x20, + 0xFF, 0xEF, 0x07, 0x20, 0x8C, 0xEE, 0x07, 0x20, + 0xFF, 0xF7, 0x07, 0x20, 0x8D, 0xF6, 0x07, 0x20, + 0xFF, 0xFF, 0x07, 0x20, 0x8E, 0xFE, 0x07, 0x20, + 0xFF, 0xFF, 0x07, 0x20, 0x8E, 0xFE, 0x07, 0x20, + 0xFF, 0xF7, 0x07, 0x20, 0x8D, 0xF6, 0x07, 0x20, + 0xFF, 0xEF, 0x07, 0x20, 0x8C, 0xEE, 0x07, 0x20, + 0xFF, 0xE7, 0x07, 0x20, 0x8B, 0xE6, 0x07, 0x20, + 0xFF, 0xDF, 0x07, 0x20, 0x8A, 0xDE, 0x07, 0x20, + 0xFF, 0xD7, 0x07, 0x20, 0x89, 0xD6, 0x07, 0x20, + 0xFF, 0xCF, 0x07, 0x20, 0x88, 0xCE, 0x07, 0x20, + 0xFF, 0xC7, 0x07, 0x20, 0x87, 0xC6, 0x07, 0x20, + 0xFF, 0xBF, 0x07, 0x20, 0x86, 0xBE, 0x07, 0x20, + 0xFF, 0xB7, 0x07, 0x20, 0x85, 0xB6, 0x07, 0x20, + 0xFF, 0xAF, 0x07, 0x20, 0x84, 0xAE, 0x07, 0x20, + 0xFF, 0xA7, 0x07, 0x20, 0x83, 0xA6, 0x07, 0x20, + 0xFF, 0x9F, 0x07, 0x20, 0x82, 0x9E, 0x07, 0x20, + 0xFF, 0x97, 0x07, 0x20, 0x81, 0x96, 0x07, 0x20, + 0xFF, 0x8F, 0x07, 0x20, 0x80, 0x8E, 0x07, 0x20, + 0xFF, 0x87, 0x07, 0x20, 0x7F, 0x86, 0x07, 0x20, + 0xFF, 0xFD, 0x07, 0x20, 0x7E, 0xFC, 0x07, 0x20, + 0xFF, 0xF5, 0x07, 0x20, 0x7D, 0xF4, 0x07, 0x20, + 0xFF, 0xED, 0x07, 0x20, 0x7C, 0xEC, 0x07, 0x20, + 0xFF, 0xE5, 0x07, 0x20, 0x7B, 0xE4, 0x07, 0x20, + 0xFF, 0xDD, 0x07, 0x20, 0x7A, 0xDC, 0x07, 0x20, + 0xFF, 0xD5, 0x07, 0x20, 0x79, 0xD4, 0x07, 0x20, + 0xFF, 0xCD, 0x07, 0x20, 0x78, 0xCC, 0x07, 0x20, + 0xFF, 0xC5, 0x07, 0x20, 0x77, 0xC4, 0x07, 0x20, + 0xFF, 0xBD, 0x07, 0x20, 0x76, 0xBC, 0x07, 0x20, + 0xFF, 0xB5, 0x07, 0x20, 0x75, 0xB4, 0x07, 0x20, + 0xFF, 0xAD, 0x07, 0x20, 0x74, 0xAC, 0x07, 0x20, + 0xFF, 0xA5, 0x07, 0x20, 0x73, 0xA4, 0x07, 0x20, + 0xFF, 0x9D, 0x07, 0x20, 0x72, 0x9C, 0x07, 0x20, + 0xFF, 0x95, 0x07, 0x20, 0x71, 0x94, 0x07, 0x20, + 0xFF, 0x8D, 0x07, 0x20, 0x70, 0x8C, 0x07, 0x20, + 0xFF, 0x85, 0x07, 0x20, 0x6F, 0x84, 0x07, 0x20, + 0xFF, 0xFB, 0x07, 0x20, 0x6E, 0xFA, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x6D, 0xF2, 0x07, 0x20, + 0xFF, 0xEB, 0x07, 0x20, 0x6C, 0xEA, 0x07, 0x20, + 0xFF, 0xE3, 0x07, 0x20, 0x6B, 0xE2, 0x07, 0x20, + 0xFF, 0xDB, 0x07, 0x20, 0x6A, 0xDA, 0x07, 0x20, + 0xFF, 0xD3, 0x07, 0x20, 0x69, 0xD2, 0x07, 0x20, + 0xFF, 0xCB, 0x07, 0x20, 0x68, 0xCA, 0x07, 0x20, + 0xFF, 0xC3, 0x07, 0x20, 0x67, 0xC2, 0x07, 0x20, + 0xFF, 0xBB, 0x07, 0x20, 0x66, 0xBA, 0x07, 0x20, + 0xFF, 0xB3, 0x07, 0x20, 0x65, 0xB2, 0x07, 0x20, + 0xFF, 0xAB, 0x07, 0x20, 0x64, 0xAA, 0x07, 0x20, + 0xFF, 0xA3, 0x07, 0x20, 0x63, 0xA2, 0x07, 0x20, + 0xFF, 0x9B, 0x07, 0x20, 0x62, 0x9A, 0x07, 0x20, + 0xFF, 0x93, 0x07, 0x20, 0x61, 0x92, 0x07, 0x20, + 0xFF, 0x8B, 0x07, 0x20, 0x60, 0x8A, 0x07, 0x20, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, + 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, + 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, + 0x04, 0x0C, 0x00, 0x01, 0x00, 0x03, 0x0D, 0x00, + 0x28, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x00, + 0x00, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x1C, 0x02, 0xB0, 0x01, 0x00, + 0x00, 0x00, 0x0E, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x01, 0x01, 0x01, 0x00, 0x01, 0x1F, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x00, + 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x00, 0x01, + 0x11, 0x00, 0x02, 0x00, 0x00, 0x01, 0x12, 0x00, + 0x01, 0x00, 0x01, 0x05, 0x00, 0x0E, 0x00, 0x0C, + 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x08, 0x00, 0x00, 0x05, 0x00, 0x0E, + 0x00, 0x10, 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, + 0x00, 0x09, 0x00, 0x04, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x08, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x0C, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x10, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x14, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x18, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x44, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x48, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x4C, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x50, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x58, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x15, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x28, 0x00, 0x00, }; static unsigned char vfs5011_init_08[] = { /* 2516 B */ - 0x02, 0xB0, 0x00, 0x60, 0x00, 0x03, 0x00, 0x09, - 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, - 0x04, 0x30, 0x01, 0x80, 0x4F, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, - 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, - 0x20, 0x04, 0x30, 0xE6, 0x03, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, - 0xE7, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x4C, 0x20, 0x04, 0x30, 0xE8, 0x03, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, - 0x04, 0x30, 0x00, 0x3E, 0x01, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, - 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x05, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x40, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x60, 0x21, 0x04, 0x30, 0x05, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x90, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, - 0x30, 0x05, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xD8, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, - 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x05, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, - 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, - 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, - 0x30, 0x00, 0x02, 0xA8, 0x02, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, - 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, - 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, - 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, - 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0xFF, 0x8B, 0x07, 0x20, 0x60, 0x8A, 0x07, 0x20, - 0xFF, 0x93, 0x07, 0x20, 0x61, 0x92, 0x07, 0x20, - 0xFF, 0x9B, 0x07, 0x20, 0x62, 0x9A, 0x07, 0x20, - 0xFF, 0xA3, 0x07, 0x20, 0x63, 0xA2, 0x07, 0x20, - 0xFF, 0xAB, 0x07, 0x20, 0x64, 0xAA, 0x07, 0x20, - 0xFF, 0xB3, 0x07, 0x20, 0x65, 0xB2, 0x07, 0x20, - 0xFF, 0xBB, 0x07, 0x20, 0x66, 0xBA, 0x07, 0x20, - 0xFF, 0xC3, 0x07, 0x20, 0x67, 0xC2, 0x07, 0x20, - 0xFF, 0xCB, 0x07, 0x20, 0x68, 0xCA, 0x07, 0x20, - 0xFF, 0xD3, 0x07, 0x20, 0x69, 0xD2, 0x07, 0x20, - 0xFF, 0xDB, 0x07, 0x20, 0x6A, 0xDA, 0x07, 0x20, - 0xFF, 0xE3, 0x07, 0x20, 0x6B, 0xE2, 0x07, 0x20, - 0xFF, 0xEB, 0x07, 0x20, 0x6C, 0xEA, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x6D, 0xF2, 0x07, 0x20, - 0xFF, 0xFB, 0x07, 0x20, 0x6E, 0xFA, 0x07, 0x20, - 0xFF, 0x85, 0x07, 0x20, 0x6F, 0x84, 0x07, 0x20, - 0xFF, 0x8D, 0x07, 0x20, 0x70, 0x8C, 0x07, 0x20, - 0xFF, 0x95, 0x07, 0x20, 0x71, 0x94, 0x07, 0x20, - 0xFF, 0x9D, 0x07, 0x20, 0x72, 0x9C, 0x07, 0x20, - 0xFF, 0xA5, 0x07, 0x20, 0x73, 0xA4, 0x07, 0x20, - 0xFF, 0xAD, 0x07, 0x20, 0x74, 0xAC, 0x07, 0x20, - 0xFF, 0xB5, 0x07, 0x20, 0x75, 0xB4, 0x07, 0x20, - 0xFF, 0xBD, 0x07, 0x20, 0x76, 0xBC, 0x07, 0x20, - 0xFF, 0xC5, 0x07, 0x20, 0x77, 0xC4, 0x07, 0x20, - 0xFF, 0xCD, 0x07, 0x20, 0x78, 0xCC, 0x07, 0x20, - 0xFF, 0xD5, 0x07, 0x20, 0x79, 0xD4, 0x07, 0x20, - 0xFF, 0xDD, 0x07, 0x20, 0x7A, 0xDC, 0x07, 0x20, - 0xFF, 0xE5, 0x07, 0x20, 0x7B, 0xE4, 0x07, 0x20, - 0xFF, 0xED, 0x07, 0x20, 0x7C, 0xEC, 0x07, 0x20, - 0xFF, 0xF5, 0x07, 0x20, 0x7D, 0xF4, 0x07, 0x20, - 0xFF, 0xFD, 0x07, 0x20, 0x7E, 0xFC, 0x07, 0x20, - 0xFF, 0x87, 0x07, 0x20, 0x7F, 0x86, 0x07, 0x20, - 0xFF, 0x8F, 0x07, 0x20, 0x80, 0x8E, 0x07, 0x20, - 0xFF, 0x97, 0x07, 0x20, 0x81, 0x96, 0x07, 0x20, - 0xFF, 0x9F, 0x07, 0x20, 0x82, 0x9E, 0x07, 0x20, - 0xFF, 0xA7, 0x07, 0x20, 0x83, 0xA6, 0x07, 0x20, - 0xFF, 0xAF, 0x07, 0x20, 0x84, 0xAE, 0x07, 0x20, - 0xFF, 0xB7, 0x07, 0x20, 0x85, 0xB6, 0x07, 0x20, - 0xFF, 0xBF, 0x07, 0x20, 0x86, 0xBE, 0x07, 0x20, - 0xFF, 0xC7, 0x07, 0x20, 0x87, 0xC6, 0x07, 0x20, - 0xFF, 0xCF, 0x07, 0x20, 0x88, 0xCE, 0x07, 0x20, - 0xFF, 0xD7, 0x07, 0x20, 0x89, 0xD6, 0x07, 0x20, - 0xFF, 0xDF, 0x07, 0x20, 0x8A, 0xDE, 0x07, 0x20, - 0xFF, 0xE7, 0x07, 0x20, 0x8B, 0xE6, 0x07, 0x20, - 0xFF, 0xEF, 0x07, 0x20, 0x8C, 0xEE, 0x07, 0x20, - 0xFF, 0xF7, 0x07, 0x20, 0x8D, 0xF6, 0x07, 0x20, - 0xFF, 0xFF, 0x07, 0x20, 0x8E, 0xFE, 0x07, 0x20, - 0xFF, 0xFF, 0x07, 0x20, 0x8E, 0xFE, 0x07, 0x20, - 0xFF, 0xF7, 0x07, 0x20, 0x8D, 0xF6, 0x07, 0x20, - 0xFF, 0xEF, 0x07, 0x20, 0x8C, 0xEE, 0x07, 0x20, - 0xFF, 0xE7, 0x07, 0x20, 0x8B, 0xE6, 0x07, 0x20, - 0xFF, 0xDF, 0x07, 0x20, 0x8A, 0xDE, 0x07, 0x20, - 0xFF, 0xD7, 0x07, 0x20, 0x89, 0xD6, 0x07, 0x20, - 0xFF, 0xCF, 0x07, 0x20, 0x88, 0xCE, 0x07, 0x20, - 0xFF, 0xC7, 0x07, 0x20, 0x87, 0xC6, 0x07, 0x20, - 0xFF, 0xBF, 0x07, 0x20, 0x86, 0xBE, 0x07, 0x20, - 0xFF, 0xB7, 0x07, 0x20, 0x85, 0xB6, 0x07, 0x20, - 0xFF, 0xAF, 0x07, 0x20, 0x84, 0xAE, 0x07, 0x20, - 0xFF, 0xA7, 0x07, 0x20, 0x83, 0xA6, 0x07, 0x20, - 0xFF, 0x9F, 0x07, 0x20, 0x82, 0x9E, 0x07, 0x20, - 0xFF, 0x97, 0x07, 0x20, 0x81, 0x96, 0x07, 0x20, - 0xFF, 0x8F, 0x07, 0x20, 0x80, 0x8E, 0x07, 0x20, - 0xFF, 0x87, 0x07, 0x20, 0x7F, 0x86, 0x07, 0x20, - 0xFF, 0xFD, 0x07, 0x20, 0x7E, 0xFC, 0x07, 0x20, - 0xFF, 0xF5, 0x07, 0x20, 0x7D, 0xF4, 0x07, 0x20, - 0xFF, 0xED, 0x07, 0x20, 0x7C, 0xEC, 0x07, 0x20, - 0xFF, 0xE5, 0x07, 0x20, 0x7B, 0xE4, 0x07, 0x20, - 0xFF, 0xDD, 0x07, 0x20, 0x7A, 0xDC, 0x07, 0x20, - 0xFF, 0xD5, 0x07, 0x20, 0x79, 0xD4, 0x07, 0x20, - 0xFF, 0xCD, 0x07, 0x20, 0x78, 0xCC, 0x07, 0x20, - 0xFF, 0xC5, 0x07, 0x20, 0x77, 0xC4, 0x07, 0x20, - 0xFF, 0xBD, 0x07, 0x20, 0x76, 0xBC, 0x07, 0x20, - 0xFF, 0xB5, 0x07, 0x20, 0x75, 0xB4, 0x07, 0x20, - 0xFF, 0xAD, 0x07, 0x20, 0x74, 0xAC, 0x07, 0x20, - 0xFF, 0xA5, 0x07, 0x20, 0x73, 0xA4, 0x07, 0x20, - 0xFF, 0x9D, 0x07, 0x20, 0x72, 0x9C, 0x07, 0x20, - 0xFF, 0x95, 0x07, 0x20, 0x71, 0x94, 0x07, 0x20, - 0xFF, 0x8D, 0x07, 0x20, 0x70, 0x8C, 0x07, 0x20, - 0xFF, 0x85, 0x07, 0x20, 0x6F, 0x84, 0x07, 0x20, - 0xFF, 0xFB, 0x07, 0x20, 0x6E, 0xFA, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x6D, 0xF2, 0x07, 0x20, - 0xFF, 0xEB, 0x07, 0x20, 0x6C, 0xEA, 0x07, 0x20, - 0xFF, 0xE3, 0x07, 0x20, 0x6B, 0xE2, 0x07, 0x20, - 0xFF, 0xDB, 0x07, 0x20, 0x6A, 0xDA, 0x07, 0x20, - 0xFF, 0xD3, 0x07, 0x20, 0x69, 0xD2, 0x07, 0x20, - 0xFF, 0xCB, 0x07, 0x20, 0x68, 0xCA, 0x07, 0x20, - 0xFF, 0xC3, 0x07, 0x20, 0x67, 0xC2, 0x07, 0x20, - 0xFF, 0xBB, 0x07, 0x20, 0x66, 0xBA, 0x07, 0x20, - 0xFF, 0xB3, 0x07, 0x20, 0x65, 0xB2, 0x07, 0x20, - 0xFF, 0xAB, 0x07, 0x20, 0x64, 0xAA, 0x07, 0x20, - 0xFF, 0xA3, 0x07, 0x20, 0x63, 0xA2, 0x07, 0x20, - 0xFF, 0x9B, 0x07, 0x20, 0x62, 0x9A, 0x07, 0x20, - 0xFF, 0x93, 0x07, 0x20, 0x61, 0x92, 0x07, 0x20, - 0xFF, 0x8B, 0x07, 0x20, 0x60, 0x8A, 0x07, 0x20, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, - 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, - 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, - 0x04, 0x0C, 0x00, 0x01, 0x00, 0x02, 0x0D, 0x00, - 0x28, 0x00, 0x14, 0x00, 0x00, 0x38, 0x00, 0x00, - 0x6E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x8F, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x0E, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x00, - 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x00, 0x02, - 0x11, 0x00, 0x02, 0x00, 0x60, 0x00, 0x12, 0x00, - 0x01, 0x00, 0x01, 0x05, 0x00, 0x0E, 0x00, 0x0C, - 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x08, 0x00, 0x00, 0x05, 0x00, 0x0E, - 0x00, 0x10, 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, - 0x00, 0x09, 0x00, 0x04, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x08, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x0C, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x10, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x14, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x18, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x44, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x48, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x4C, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x50, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x58, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC8, - 0x20, 0x04, 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, - 0x15, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x28, 0x00, 0x00, + 0x02, 0xB0, 0x00, 0x60, 0x00, 0x03, 0x00, 0x09, + 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, + 0x04, 0x30, 0x01, 0x80, 0x4F, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, + 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, + 0x20, 0x04, 0x30, 0xE6, 0x03, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, + 0xE7, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x4C, 0x20, 0x04, 0x30, 0xE8, 0x03, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, + 0x04, 0x30, 0x00, 0x3E, 0x01, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, + 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x05, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x40, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x60, 0x21, 0x04, 0x30, 0x05, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x90, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, + 0x30, 0x05, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xD8, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, + 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x05, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, + 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, + 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, + 0x30, 0x00, 0x02, 0xA8, 0x02, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, + 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, + 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, + 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, + 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0xFF, 0x8B, 0x07, 0x20, 0x60, 0x8A, 0x07, 0x20, + 0xFF, 0x93, 0x07, 0x20, 0x61, 0x92, 0x07, 0x20, + 0xFF, 0x9B, 0x07, 0x20, 0x62, 0x9A, 0x07, 0x20, + 0xFF, 0xA3, 0x07, 0x20, 0x63, 0xA2, 0x07, 0x20, + 0xFF, 0xAB, 0x07, 0x20, 0x64, 0xAA, 0x07, 0x20, + 0xFF, 0xB3, 0x07, 0x20, 0x65, 0xB2, 0x07, 0x20, + 0xFF, 0xBB, 0x07, 0x20, 0x66, 0xBA, 0x07, 0x20, + 0xFF, 0xC3, 0x07, 0x20, 0x67, 0xC2, 0x07, 0x20, + 0xFF, 0xCB, 0x07, 0x20, 0x68, 0xCA, 0x07, 0x20, + 0xFF, 0xD3, 0x07, 0x20, 0x69, 0xD2, 0x07, 0x20, + 0xFF, 0xDB, 0x07, 0x20, 0x6A, 0xDA, 0x07, 0x20, + 0xFF, 0xE3, 0x07, 0x20, 0x6B, 0xE2, 0x07, 0x20, + 0xFF, 0xEB, 0x07, 0x20, 0x6C, 0xEA, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x6D, 0xF2, 0x07, 0x20, + 0xFF, 0xFB, 0x07, 0x20, 0x6E, 0xFA, 0x07, 0x20, + 0xFF, 0x85, 0x07, 0x20, 0x6F, 0x84, 0x07, 0x20, + 0xFF, 0x8D, 0x07, 0x20, 0x70, 0x8C, 0x07, 0x20, + 0xFF, 0x95, 0x07, 0x20, 0x71, 0x94, 0x07, 0x20, + 0xFF, 0x9D, 0x07, 0x20, 0x72, 0x9C, 0x07, 0x20, + 0xFF, 0xA5, 0x07, 0x20, 0x73, 0xA4, 0x07, 0x20, + 0xFF, 0xAD, 0x07, 0x20, 0x74, 0xAC, 0x07, 0x20, + 0xFF, 0xB5, 0x07, 0x20, 0x75, 0xB4, 0x07, 0x20, + 0xFF, 0xBD, 0x07, 0x20, 0x76, 0xBC, 0x07, 0x20, + 0xFF, 0xC5, 0x07, 0x20, 0x77, 0xC4, 0x07, 0x20, + 0xFF, 0xCD, 0x07, 0x20, 0x78, 0xCC, 0x07, 0x20, + 0xFF, 0xD5, 0x07, 0x20, 0x79, 0xD4, 0x07, 0x20, + 0xFF, 0xDD, 0x07, 0x20, 0x7A, 0xDC, 0x07, 0x20, + 0xFF, 0xE5, 0x07, 0x20, 0x7B, 0xE4, 0x07, 0x20, + 0xFF, 0xED, 0x07, 0x20, 0x7C, 0xEC, 0x07, 0x20, + 0xFF, 0xF5, 0x07, 0x20, 0x7D, 0xF4, 0x07, 0x20, + 0xFF, 0xFD, 0x07, 0x20, 0x7E, 0xFC, 0x07, 0x20, + 0xFF, 0x87, 0x07, 0x20, 0x7F, 0x86, 0x07, 0x20, + 0xFF, 0x8F, 0x07, 0x20, 0x80, 0x8E, 0x07, 0x20, + 0xFF, 0x97, 0x07, 0x20, 0x81, 0x96, 0x07, 0x20, + 0xFF, 0x9F, 0x07, 0x20, 0x82, 0x9E, 0x07, 0x20, + 0xFF, 0xA7, 0x07, 0x20, 0x83, 0xA6, 0x07, 0x20, + 0xFF, 0xAF, 0x07, 0x20, 0x84, 0xAE, 0x07, 0x20, + 0xFF, 0xB7, 0x07, 0x20, 0x85, 0xB6, 0x07, 0x20, + 0xFF, 0xBF, 0x07, 0x20, 0x86, 0xBE, 0x07, 0x20, + 0xFF, 0xC7, 0x07, 0x20, 0x87, 0xC6, 0x07, 0x20, + 0xFF, 0xCF, 0x07, 0x20, 0x88, 0xCE, 0x07, 0x20, + 0xFF, 0xD7, 0x07, 0x20, 0x89, 0xD6, 0x07, 0x20, + 0xFF, 0xDF, 0x07, 0x20, 0x8A, 0xDE, 0x07, 0x20, + 0xFF, 0xE7, 0x07, 0x20, 0x8B, 0xE6, 0x07, 0x20, + 0xFF, 0xEF, 0x07, 0x20, 0x8C, 0xEE, 0x07, 0x20, + 0xFF, 0xF7, 0x07, 0x20, 0x8D, 0xF6, 0x07, 0x20, + 0xFF, 0xFF, 0x07, 0x20, 0x8E, 0xFE, 0x07, 0x20, + 0xFF, 0xFF, 0x07, 0x20, 0x8E, 0xFE, 0x07, 0x20, + 0xFF, 0xF7, 0x07, 0x20, 0x8D, 0xF6, 0x07, 0x20, + 0xFF, 0xEF, 0x07, 0x20, 0x8C, 0xEE, 0x07, 0x20, + 0xFF, 0xE7, 0x07, 0x20, 0x8B, 0xE6, 0x07, 0x20, + 0xFF, 0xDF, 0x07, 0x20, 0x8A, 0xDE, 0x07, 0x20, + 0xFF, 0xD7, 0x07, 0x20, 0x89, 0xD6, 0x07, 0x20, + 0xFF, 0xCF, 0x07, 0x20, 0x88, 0xCE, 0x07, 0x20, + 0xFF, 0xC7, 0x07, 0x20, 0x87, 0xC6, 0x07, 0x20, + 0xFF, 0xBF, 0x07, 0x20, 0x86, 0xBE, 0x07, 0x20, + 0xFF, 0xB7, 0x07, 0x20, 0x85, 0xB6, 0x07, 0x20, + 0xFF, 0xAF, 0x07, 0x20, 0x84, 0xAE, 0x07, 0x20, + 0xFF, 0xA7, 0x07, 0x20, 0x83, 0xA6, 0x07, 0x20, + 0xFF, 0x9F, 0x07, 0x20, 0x82, 0x9E, 0x07, 0x20, + 0xFF, 0x97, 0x07, 0x20, 0x81, 0x96, 0x07, 0x20, + 0xFF, 0x8F, 0x07, 0x20, 0x80, 0x8E, 0x07, 0x20, + 0xFF, 0x87, 0x07, 0x20, 0x7F, 0x86, 0x07, 0x20, + 0xFF, 0xFD, 0x07, 0x20, 0x7E, 0xFC, 0x07, 0x20, + 0xFF, 0xF5, 0x07, 0x20, 0x7D, 0xF4, 0x07, 0x20, + 0xFF, 0xED, 0x07, 0x20, 0x7C, 0xEC, 0x07, 0x20, + 0xFF, 0xE5, 0x07, 0x20, 0x7B, 0xE4, 0x07, 0x20, + 0xFF, 0xDD, 0x07, 0x20, 0x7A, 0xDC, 0x07, 0x20, + 0xFF, 0xD5, 0x07, 0x20, 0x79, 0xD4, 0x07, 0x20, + 0xFF, 0xCD, 0x07, 0x20, 0x78, 0xCC, 0x07, 0x20, + 0xFF, 0xC5, 0x07, 0x20, 0x77, 0xC4, 0x07, 0x20, + 0xFF, 0xBD, 0x07, 0x20, 0x76, 0xBC, 0x07, 0x20, + 0xFF, 0xB5, 0x07, 0x20, 0x75, 0xB4, 0x07, 0x20, + 0xFF, 0xAD, 0x07, 0x20, 0x74, 0xAC, 0x07, 0x20, + 0xFF, 0xA5, 0x07, 0x20, 0x73, 0xA4, 0x07, 0x20, + 0xFF, 0x9D, 0x07, 0x20, 0x72, 0x9C, 0x07, 0x20, + 0xFF, 0x95, 0x07, 0x20, 0x71, 0x94, 0x07, 0x20, + 0xFF, 0x8D, 0x07, 0x20, 0x70, 0x8C, 0x07, 0x20, + 0xFF, 0x85, 0x07, 0x20, 0x6F, 0x84, 0x07, 0x20, + 0xFF, 0xFB, 0x07, 0x20, 0x6E, 0xFA, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x6D, 0xF2, 0x07, 0x20, + 0xFF, 0xEB, 0x07, 0x20, 0x6C, 0xEA, 0x07, 0x20, + 0xFF, 0xE3, 0x07, 0x20, 0x6B, 0xE2, 0x07, 0x20, + 0xFF, 0xDB, 0x07, 0x20, 0x6A, 0xDA, 0x07, 0x20, + 0xFF, 0xD3, 0x07, 0x20, 0x69, 0xD2, 0x07, 0x20, + 0xFF, 0xCB, 0x07, 0x20, 0x68, 0xCA, 0x07, 0x20, + 0xFF, 0xC3, 0x07, 0x20, 0x67, 0xC2, 0x07, 0x20, + 0xFF, 0xBB, 0x07, 0x20, 0x66, 0xBA, 0x07, 0x20, + 0xFF, 0xB3, 0x07, 0x20, 0x65, 0xB2, 0x07, 0x20, + 0xFF, 0xAB, 0x07, 0x20, 0x64, 0xAA, 0x07, 0x20, + 0xFF, 0xA3, 0x07, 0x20, 0x63, 0xA2, 0x07, 0x20, + 0xFF, 0x9B, 0x07, 0x20, 0x62, 0x9A, 0x07, 0x20, + 0xFF, 0x93, 0x07, 0x20, 0x61, 0x92, 0x07, 0x20, + 0xFF, 0x8B, 0x07, 0x20, 0x60, 0x8A, 0x07, 0x20, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, + 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, + 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, + 0x04, 0x0C, 0x00, 0x01, 0x00, 0x02, 0x0D, 0x00, + 0x28, 0x00, 0x14, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x6E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x8F, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x0E, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x00, + 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x00, 0x02, + 0x11, 0x00, 0x02, 0x00, 0x60, 0x00, 0x12, 0x00, + 0x01, 0x00, 0x01, 0x05, 0x00, 0x0E, 0x00, 0x0C, + 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x08, 0x00, 0x00, 0x05, 0x00, 0x0E, + 0x00, 0x10, 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, + 0x00, 0x09, 0x00, 0x04, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x08, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x0C, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x10, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x14, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x18, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x44, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x48, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x4C, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x50, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x58, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC8, + 0x20, 0x04, 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, + 0x15, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x28, 0x00, 0x00, }; static unsigned char vfs5011_init_09[] = { /* 2742 B */ - 0x02, 0xB0, 0x00, 0x1C, 0x00, 0x03, 0x00, 0x09, - 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, - 0x04, 0x30, 0x01, 0x80, 0x4F, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, - 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, - 0x20, 0x04, 0x30, 0xE7, 0x03, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, - 0xFF, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x4C, 0x20, 0x04, 0x30, 0xFF, 0x03, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, - 0x04, 0x30, 0x00, 0x3E, 0x01, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x30, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, - 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x40, 0x21, 0x04, 0x30, 0x30, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x60, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, - 0x30, 0x30, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x90, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x30, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xD8, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, - 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, - 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, - 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, - 0x30, 0x00, 0x02, 0xA8, 0x02, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, - 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, - 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, - 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, - 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, - 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, - 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, - 0x04, 0x0C, 0x00, 0x01, 0x00, 0x00, 0x0D, 0x00, - 0x28, 0x00, 0xA0, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0xA0, 0x21, 0x04, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x73, 0x00, 0x00, 0x10, 0x01, 0x00, - 0x00, 0x00, 0x0E, 0x00, 0xE0, 0x00, 0x00, 0x01, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, - 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, - 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, - 0x04, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, - 0x08, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, - 0x10, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, - 0x10, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, - 0x10, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, - 0x10, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, - 0x10, 0x01, 0x10, 0x01, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, - 0x10, 0x01, 0x10, 0x01, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, - 0x10, 0x01, 0x10, 0x01, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x0F, 0x00, - 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x00, 0x02, - 0x11, 0x00, 0x02, 0x00, 0x02, 0x00, 0x12, 0x00, - 0x01, 0x00, 0x0E, 0x05, 0x00, 0x0E, 0x00, 0x0C, - 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x08, 0x00, 0x00, 0x05, 0x00, 0x0E, - 0x00, 0x10, 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, - 0x00, 0x09, 0x00, 0x04, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x08, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x0C, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x10, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x14, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x18, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x44, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x48, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x4C, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x50, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x58, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC8, - 0x20, 0x04, 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, - 0x05, 0x00, 0x0E, 0x00, 0x14, 0x20, 0xFF, 0xFF, - 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x83, 0x00, 0x15, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x20, 0x28, 0x00, 0x00, + 0x02, 0xB0, 0x00, 0x1C, 0x00, 0x03, 0x00, 0x09, + 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, + 0x04, 0x30, 0x01, 0x80, 0x4F, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, + 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, + 0x20, 0x04, 0x30, 0xE7, 0x03, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, + 0xFF, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x4C, 0x20, 0x04, 0x30, 0xFF, 0x03, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, + 0x04, 0x30, 0x00, 0x3E, 0x01, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x30, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, + 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x40, 0x21, 0x04, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x60, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x90, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x30, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xD8, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, + 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, + 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, + 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, + 0x30, 0x00, 0x02, 0xA8, 0x02, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, + 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, + 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, + 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, + 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x80, 0xF2, 0x07, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, + 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, + 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, + 0x04, 0x0C, 0x00, 0x01, 0x00, 0x00, 0x0D, 0x00, + 0x28, 0x00, 0xA0, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0xA0, 0x21, 0x04, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x73, 0x00, 0x00, 0x10, 0x01, 0x00, + 0x00, 0x00, 0x0E, 0x00, 0xE0, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, + 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, + 0x04, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, + 0x08, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x01, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x01, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x01, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x0F, 0x00, + 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x00, 0x02, + 0x11, 0x00, 0x02, 0x00, 0x02, 0x00, 0x12, 0x00, + 0x01, 0x00, 0x0E, 0x05, 0x00, 0x0E, 0x00, 0x0C, + 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x08, 0x00, 0x00, 0x05, 0x00, 0x0E, + 0x00, 0x10, 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, + 0x00, 0x09, 0x00, 0x04, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x08, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x0C, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x10, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x14, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x18, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x44, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x48, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x4C, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x50, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x58, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC8, + 0x20, 0x04, 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, + 0x05, 0x00, 0x0E, 0x00, 0x14, 0x20, 0xFF, 0xFF, + 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x83, 0x00, 0x15, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x28, 0x00, 0x00, }; static unsigned char vfs5011_init_10[] = { /* 2612 B */ - 0x02, 0xB0, 0x00, 0x20, 0x00, 0x03, 0x00, 0x09, - 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, - 0x04, 0x30, 0x01, 0x80, 0x4F, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, - 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, - 0x20, 0x04, 0x30, 0xE7, 0x03, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, - 0xFF, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x4C, 0x20, 0x04, 0x30, 0xFF, 0x03, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, - 0x04, 0x30, 0x00, 0x3E, 0x01, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x30, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, - 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x18, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, - 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x04, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x40, 0x21, 0x04, 0x30, 0x30, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x60, 0x21, 0x04, 0x30, 0x04, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, - 0x30, 0x30, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x90, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, - 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x30, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xD8, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, - 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x04, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, - 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, - 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, - 0x30, 0x00, 0x02, 0xA8, 0x02, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, - 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, - 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, - 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, - 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, - 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, - 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, - 0x04, 0x0C, 0x00, 0x01, 0x00, 0x01, 0x0D, 0x00, - 0x28, 0x00, 0xA0, 0x21, 0x04, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, - 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x00, - 0x00, 0x00, 0xA0, 0x21, 0x04, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x1C, 0x02, 0xB0, 0x01, 0x00, - 0x00, 0x00, 0x0E, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, - 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x00, 0x02, - 0x11, 0x00, 0x02, 0x00, 0x20, 0x00, 0x12, 0x00, - 0x01, 0x00, 0x01, 0x05, 0x00, 0x0E, 0x00, 0x0C, - 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x08, 0x00, 0x00, 0x05, 0x00, 0x0E, - 0x00, 0x10, 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, - 0x00, 0x09, 0x00, 0x04, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x08, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x0C, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x10, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x14, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x18, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x44, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x48, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x4C, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x50, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x58, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC8, - 0x20, 0x04, 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, - 0x05, 0x00, 0x0E, 0x00, 0x14, 0x20, 0xFF, 0xFF, - 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x83, 0x00, 0x03, 0x00, 0x09, 0x00, 0x84, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x88, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x8C, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x90, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x94, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x98, - 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x15, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x28, 0x00, 0x00, + 0x02, 0xB0, 0x00, 0x20, 0x00, 0x03, 0x00, 0x09, + 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, + 0x04, 0x30, 0x01, 0x80, 0x4F, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, + 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, + 0x20, 0x04, 0x30, 0xE7, 0x03, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, + 0xFF, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x4C, 0x20, 0x04, 0x30, 0xFF, 0x03, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, + 0x04, 0x30, 0x00, 0x3E, 0x01, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x30, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, + 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x18, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, + 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x04, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x40, 0x21, 0x04, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x60, 0x21, 0x04, 0x30, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x90, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, + 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x30, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xD8, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, + 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x04, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, + 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, + 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, + 0x30, 0x00, 0x02, 0xA8, 0x02, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, + 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, + 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, + 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, + 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0xFF, 0xF3, 0x47, 0x20, 0x80, 0xF2, 0x47, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, + 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, + 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, + 0x04, 0x0C, 0x00, 0x01, 0x00, 0x01, 0x0D, 0x00, + 0x28, 0x00, 0xA0, 0x21, 0x04, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x00, + 0x00, 0x00, 0xA0, 0x21, 0x04, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x1C, 0x02, 0xB0, 0x01, 0x00, + 0x00, 0x00, 0x0E, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, + 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x00, 0x02, + 0x11, 0x00, 0x02, 0x00, 0x20, 0x00, 0x12, 0x00, + 0x01, 0x00, 0x01, 0x05, 0x00, 0x0E, 0x00, 0x0C, + 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x08, 0x00, 0x00, 0x05, 0x00, 0x0E, + 0x00, 0x10, 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, + 0x00, 0x09, 0x00, 0x04, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x08, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x0C, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x10, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x14, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x18, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x44, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x48, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x4C, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x50, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x58, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC8, + 0x20, 0x04, 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, + 0x05, 0x00, 0x0E, 0x00, 0x14, 0x20, 0xFF, 0xFF, + 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x83, 0x00, 0x03, 0x00, 0x09, 0x00, 0x84, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x88, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x8C, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x90, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x94, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x98, + 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x15, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x28, 0x00, 0x00, }; static unsigned char vfs5011_init_11[] = { /* 2625 B */ - 0x02, 0xB0, 0x00, 0x20, 0x00, 0x03, 0x00, 0x09, - 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, - 0x04, 0x30, 0x01, 0x80, 0x4F, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, - 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, - 0x20, 0x04, 0x30, 0xE6, 0x03, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, - 0xE7, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x4C, 0x20, 0x04, 0x30, 0xE8, 0x03, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, - 0x04, 0x30, 0x00, 0x3E, 0x01, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, - 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x08, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x40, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x60, 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x90, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, - 0x30, 0x08, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xD8, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, - 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x08, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, - 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, - 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, - 0x30, 0x00, 0x02, 0xA8, 0x02, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, - 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, - 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, - 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, - 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0xFF, 0x8B, 0x07, 0x20, 0x60, 0x8A, 0x07, 0x20, - 0xFF, 0x93, 0x07, 0x20, 0x61, 0x92, 0x07, 0x20, - 0xFF, 0x9B, 0x07, 0x20, 0x62, 0x9A, 0x07, 0x20, - 0xFF, 0xA3, 0x07, 0x20, 0x63, 0xA2, 0x07, 0x20, - 0xFF, 0xAB, 0x07, 0x20, 0x64, 0xAA, 0x07, 0x20, - 0xFF, 0xB3, 0x07, 0x20, 0x65, 0xB2, 0x07, 0x20, - 0xFF, 0xBB, 0x07, 0x20, 0x66, 0xBA, 0x07, 0x20, - 0xFF, 0xC3, 0x07, 0x20, 0x67, 0xC2, 0x07, 0x20, - 0xFF, 0xCB, 0x07, 0x20, 0x68, 0xCA, 0x07, 0x20, - 0xFF, 0xD3, 0x07, 0x20, 0x69, 0xD2, 0x07, 0x20, - 0xFF, 0xDB, 0x07, 0x20, 0x6A, 0xDA, 0x07, 0x20, - 0xFF, 0xE3, 0x07, 0x20, 0x6B, 0xE2, 0x07, 0x20, - 0xFF, 0xEB, 0x07, 0x20, 0x6C, 0xEA, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x6D, 0xF2, 0x07, 0x20, - 0xFF, 0xFB, 0x07, 0x20, 0x6E, 0xFA, 0x07, 0x20, - 0xFF, 0x85, 0x07, 0x20, 0x6F, 0x84, 0x07, 0x20, - 0xFF, 0x8D, 0x07, 0x20, 0x70, 0x8C, 0x07, 0x20, - 0xFF, 0x95, 0x07, 0x20, 0x71, 0x94, 0x07, 0x20, - 0xFF, 0x9D, 0x07, 0x20, 0x72, 0x9C, 0x07, 0x20, - 0xFF, 0xA5, 0x07, 0x20, 0x73, 0xA4, 0x07, 0x20, - 0xFF, 0xAD, 0x07, 0x20, 0x74, 0xAC, 0x07, 0x20, - 0xFF, 0xB5, 0x07, 0x20, 0x75, 0xB4, 0x07, 0x20, - 0xFF, 0xBD, 0x07, 0x20, 0x76, 0xBC, 0x07, 0x20, - 0xFF, 0xC5, 0x07, 0x20, 0x77, 0xC4, 0x07, 0x20, - 0xFF, 0xCD, 0x07, 0x20, 0x78, 0xCC, 0x07, 0x20, - 0xFF, 0xD5, 0x07, 0x20, 0x79, 0xD4, 0x07, 0x20, - 0xFF, 0xDD, 0x07, 0x20, 0x7A, 0xDC, 0x07, 0x20, - 0xFF, 0xE5, 0x07, 0x20, 0x7B, 0xE4, 0x07, 0x20, - 0xFF, 0xED, 0x07, 0x20, 0x7C, 0xEC, 0x07, 0x20, - 0xFF, 0xF5, 0x07, 0x20, 0x7D, 0xF4, 0x07, 0x20, - 0xFF, 0xFD, 0x07, 0x20, 0x7E, 0xFC, 0x07, 0x20, - 0xFF, 0x87, 0x07, 0x20, 0x7F, 0x86, 0x07, 0x20, - 0xFF, 0x8F, 0x07, 0x20, 0x80, 0x8E, 0x07, 0x20, - 0xFF, 0x97, 0x07, 0x20, 0x81, 0x96, 0x07, 0x20, - 0xFF, 0x9F, 0x07, 0x20, 0x82, 0x9E, 0x07, 0x20, - 0xFF, 0xA7, 0x07, 0x20, 0x83, 0xA6, 0x07, 0x20, - 0xFF, 0xAF, 0x07, 0x20, 0x84, 0xAE, 0x07, 0x20, - 0xFF, 0xB7, 0x07, 0x20, 0x85, 0xB6, 0x07, 0x20, - 0xFF, 0xBF, 0x07, 0x20, 0x86, 0xBE, 0x07, 0x20, - 0xFF, 0xC7, 0x07, 0x20, 0x87, 0xC6, 0x07, 0x20, - 0xFF, 0xCF, 0x07, 0x20, 0x88, 0xCE, 0x07, 0x20, - 0xFF, 0xD7, 0x07, 0x20, 0x89, 0xD6, 0x07, 0x20, - 0xFF, 0xDF, 0x07, 0x20, 0x8A, 0xDE, 0x07, 0x20, - 0xFF, 0xE7, 0x07, 0x20, 0x8B, 0xE6, 0x07, 0x20, - 0xFF, 0xEF, 0x07, 0x20, 0x8C, 0xEE, 0x07, 0x20, - 0xFF, 0xF7, 0x07, 0x20, 0x8D, 0xF6, 0x07, 0x20, - 0xFF, 0xFF, 0x07, 0x20, 0x8E, 0xFE, 0x07, 0x20, - 0xFF, 0xFF, 0x07, 0x20, 0x8E, 0xFE, 0x07, 0x20, - 0xFF, 0xF7, 0x07, 0x20, 0x8D, 0xF6, 0x07, 0x20, - 0xFF, 0xEF, 0x07, 0x20, 0x8C, 0xEE, 0x07, 0x20, - 0xFF, 0xE7, 0x07, 0x20, 0x8B, 0xE6, 0x07, 0x20, - 0xFF, 0xDF, 0x07, 0x20, 0x8A, 0xDE, 0x07, 0x20, - 0xFF, 0xD7, 0x07, 0x20, 0x89, 0xD6, 0x07, 0x20, - 0xFF, 0xCF, 0x07, 0x20, 0x88, 0xCE, 0x07, 0x20, - 0xFF, 0xC7, 0x07, 0x20, 0x87, 0xC6, 0x07, 0x20, - 0xFF, 0xBF, 0x07, 0x20, 0x86, 0xBE, 0x07, 0x20, - 0xFF, 0xB7, 0x07, 0x20, 0x85, 0xB6, 0x07, 0x20, - 0xFF, 0xAF, 0x07, 0x20, 0x84, 0xAE, 0x07, 0x20, - 0xFF, 0xA7, 0x07, 0x20, 0x83, 0xA6, 0x07, 0x20, - 0xFF, 0x9F, 0x07, 0x20, 0x82, 0x9E, 0x07, 0x20, - 0xFF, 0x97, 0x07, 0x20, 0x81, 0x96, 0x07, 0x20, - 0xFF, 0x8F, 0x07, 0x20, 0x80, 0x8E, 0x07, 0x20, - 0xFF, 0x87, 0x07, 0x20, 0x7F, 0x86, 0x07, 0x20, - 0xFF, 0xFD, 0x07, 0x20, 0x7E, 0xFC, 0x07, 0x20, - 0xFF, 0xF5, 0x07, 0x20, 0x7D, 0xF4, 0x07, 0x20, - 0xFF, 0xED, 0x07, 0x20, 0x7C, 0xEC, 0x07, 0x20, - 0xFF, 0xE5, 0x07, 0x20, 0x7B, 0xE4, 0x07, 0x20, - 0xFF, 0xDD, 0x07, 0x20, 0x7A, 0xDC, 0x07, 0x20, - 0xFF, 0xD5, 0x07, 0x20, 0x79, 0xD4, 0x07, 0x20, - 0xFF, 0xCD, 0x07, 0x20, 0x78, 0xCC, 0x07, 0x20, - 0xFF, 0xC5, 0x07, 0x20, 0x77, 0xC4, 0x07, 0x20, - 0xFF, 0xBD, 0x07, 0x20, 0x76, 0xBC, 0x07, 0x20, - 0xFF, 0xB5, 0x07, 0x20, 0x75, 0xB4, 0x07, 0x20, - 0xFF, 0xAD, 0x07, 0x20, 0x74, 0xAC, 0x07, 0x20, - 0xFF, 0xA5, 0x07, 0x20, 0x73, 0xA4, 0x07, 0x20, - 0xFF, 0x9D, 0x07, 0x20, 0x72, 0x9C, 0x07, 0x20, - 0xFF, 0x95, 0x07, 0x20, 0x71, 0x94, 0x07, 0x20, - 0xFF, 0x8D, 0x07, 0x20, 0x70, 0x8C, 0x07, 0x20, - 0xFF, 0x85, 0x07, 0x20, 0x6F, 0x84, 0x07, 0x20, - 0xFF, 0xFB, 0x07, 0x20, 0x6E, 0xFA, 0x07, 0x20, - 0xFF, 0xF3, 0x07, 0x20, 0x6D, 0xF2, 0x07, 0x20, - 0xFF, 0xEB, 0x07, 0x20, 0x6C, 0xEA, 0x07, 0x20, - 0xFF, 0xE3, 0x07, 0x20, 0x6B, 0xE2, 0x07, 0x20, - 0xFF, 0xDB, 0x07, 0x20, 0x6A, 0xDA, 0x07, 0x20, - 0xFF, 0xD3, 0x07, 0x20, 0x69, 0xD2, 0x07, 0x20, - 0xFF, 0xCB, 0x07, 0x20, 0x68, 0xCA, 0x07, 0x20, - 0xFF, 0xC3, 0x07, 0x20, 0x67, 0xC2, 0x07, 0x20, - 0xFF, 0xBB, 0x07, 0x20, 0x66, 0xBA, 0x07, 0x20, - 0xFF, 0xB3, 0x07, 0x20, 0x65, 0xB2, 0x07, 0x20, - 0xFF, 0xAB, 0x07, 0x20, 0x64, 0xAA, 0x07, 0x20, - 0xFF, 0xA3, 0x07, 0x20, 0x63, 0xA2, 0x07, 0x20, - 0xFF, 0x9B, 0x07, 0x20, 0x62, 0x9A, 0x07, 0x20, - 0xFF, 0x93, 0x07, 0x20, 0x61, 0x92, 0x07, 0x20, - 0xFF, 0x8B, 0x07, 0x20, 0x60, 0x8A, 0x07, 0x20, - 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, - 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, - 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, - 0x04, 0x0C, 0x00, 0x01, 0x00, 0x01, 0x0D, 0x00, - 0x28, 0x00, 0x20, 0x21, 0x04, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, - 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x00, - 0x00, 0x00, 0x20, 0x21, 0x04, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x1C, 0x02, 0xB0, 0x01, 0x00, - 0x00, 0x00, 0x0E, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x00, - 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x00, 0x02, - 0x11, 0x00, 0x02, 0x00, 0x20, 0x00, 0x12, 0x00, - 0x01, 0x00, 0x01, 0x05, 0x00, 0x0E, 0x00, 0x0C, - 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x08, 0x00, 0x00, 0x05, 0x00, 0x0E, - 0x00, 0x10, 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, - 0x00, 0x09, 0x00, 0x04, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x08, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x0C, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x10, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x14, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x18, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x44, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x48, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x4C, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x50, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x58, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC8, - 0x20, 0x04, 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, - 0x05, 0x00, 0x0E, 0x00, 0x14, 0x20, 0xFF, 0xFF, - 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x83, 0x00, 0x03, 0x00, 0x09, 0x00, 0x84, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x88, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x8C, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x90, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x94, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x98, - 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x15, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x28, 0x00, - 0x00, + 0x02, 0xB0, 0x00, 0x20, 0x00, 0x03, 0x00, 0x09, + 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, + 0x04, 0x30, 0x01, 0x80, 0x4F, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, + 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, + 0x20, 0x04, 0x30, 0xE6, 0x03, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, + 0xE7, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x4C, 0x20, 0x04, 0x30, 0xE8, 0x03, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, + 0x04, 0x30, 0x00, 0x3E, 0x01, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, + 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x08, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x40, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x60, 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x90, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, + 0x30, 0x08, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xD8, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, + 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x08, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, + 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, + 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, + 0x30, 0x00, 0x02, 0xA8, 0x02, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, + 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, + 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, + 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, + 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0xFF, 0x8B, 0x07, 0x20, 0x60, 0x8A, 0x07, 0x20, + 0xFF, 0x93, 0x07, 0x20, 0x61, 0x92, 0x07, 0x20, + 0xFF, 0x9B, 0x07, 0x20, 0x62, 0x9A, 0x07, 0x20, + 0xFF, 0xA3, 0x07, 0x20, 0x63, 0xA2, 0x07, 0x20, + 0xFF, 0xAB, 0x07, 0x20, 0x64, 0xAA, 0x07, 0x20, + 0xFF, 0xB3, 0x07, 0x20, 0x65, 0xB2, 0x07, 0x20, + 0xFF, 0xBB, 0x07, 0x20, 0x66, 0xBA, 0x07, 0x20, + 0xFF, 0xC3, 0x07, 0x20, 0x67, 0xC2, 0x07, 0x20, + 0xFF, 0xCB, 0x07, 0x20, 0x68, 0xCA, 0x07, 0x20, + 0xFF, 0xD3, 0x07, 0x20, 0x69, 0xD2, 0x07, 0x20, + 0xFF, 0xDB, 0x07, 0x20, 0x6A, 0xDA, 0x07, 0x20, + 0xFF, 0xE3, 0x07, 0x20, 0x6B, 0xE2, 0x07, 0x20, + 0xFF, 0xEB, 0x07, 0x20, 0x6C, 0xEA, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x6D, 0xF2, 0x07, 0x20, + 0xFF, 0xFB, 0x07, 0x20, 0x6E, 0xFA, 0x07, 0x20, + 0xFF, 0x85, 0x07, 0x20, 0x6F, 0x84, 0x07, 0x20, + 0xFF, 0x8D, 0x07, 0x20, 0x70, 0x8C, 0x07, 0x20, + 0xFF, 0x95, 0x07, 0x20, 0x71, 0x94, 0x07, 0x20, + 0xFF, 0x9D, 0x07, 0x20, 0x72, 0x9C, 0x07, 0x20, + 0xFF, 0xA5, 0x07, 0x20, 0x73, 0xA4, 0x07, 0x20, + 0xFF, 0xAD, 0x07, 0x20, 0x74, 0xAC, 0x07, 0x20, + 0xFF, 0xB5, 0x07, 0x20, 0x75, 0xB4, 0x07, 0x20, + 0xFF, 0xBD, 0x07, 0x20, 0x76, 0xBC, 0x07, 0x20, + 0xFF, 0xC5, 0x07, 0x20, 0x77, 0xC4, 0x07, 0x20, + 0xFF, 0xCD, 0x07, 0x20, 0x78, 0xCC, 0x07, 0x20, + 0xFF, 0xD5, 0x07, 0x20, 0x79, 0xD4, 0x07, 0x20, + 0xFF, 0xDD, 0x07, 0x20, 0x7A, 0xDC, 0x07, 0x20, + 0xFF, 0xE5, 0x07, 0x20, 0x7B, 0xE4, 0x07, 0x20, + 0xFF, 0xED, 0x07, 0x20, 0x7C, 0xEC, 0x07, 0x20, + 0xFF, 0xF5, 0x07, 0x20, 0x7D, 0xF4, 0x07, 0x20, + 0xFF, 0xFD, 0x07, 0x20, 0x7E, 0xFC, 0x07, 0x20, + 0xFF, 0x87, 0x07, 0x20, 0x7F, 0x86, 0x07, 0x20, + 0xFF, 0x8F, 0x07, 0x20, 0x80, 0x8E, 0x07, 0x20, + 0xFF, 0x97, 0x07, 0x20, 0x81, 0x96, 0x07, 0x20, + 0xFF, 0x9F, 0x07, 0x20, 0x82, 0x9E, 0x07, 0x20, + 0xFF, 0xA7, 0x07, 0x20, 0x83, 0xA6, 0x07, 0x20, + 0xFF, 0xAF, 0x07, 0x20, 0x84, 0xAE, 0x07, 0x20, + 0xFF, 0xB7, 0x07, 0x20, 0x85, 0xB6, 0x07, 0x20, + 0xFF, 0xBF, 0x07, 0x20, 0x86, 0xBE, 0x07, 0x20, + 0xFF, 0xC7, 0x07, 0x20, 0x87, 0xC6, 0x07, 0x20, + 0xFF, 0xCF, 0x07, 0x20, 0x88, 0xCE, 0x07, 0x20, + 0xFF, 0xD7, 0x07, 0x20, 0x89, 0xD6, 0x07, 0x20, + 0xFF, 0xDF, 0x07, 0x20, 0x8A, 0xDE, 0x07, 0x20, + 0xFF, 0xE7, 0x07, 0x20, 0x8B, 0xE6, 0x07, 0x20, + 0xFF, 0xEF, 0x07, 0x20, 0x8C, 0xEE, 0x07, 0x20, + 0xFF, 0xF7, 0x07, 0x20, 0x8D, 0xF6, 0x07, 0x20, + 0xFF, 0xFF, 0x07, 0x20, 0x8E, 0xFE, 0x07, 0x20, + 0xFF, 0xFF, 0x07, 0x20, 0x8E, 0xFE, 0x07, 0x20, + 0xFF, 0xF7, 0x07, 0x20, 0x8D, 0xF6, 0x07, 0x20, + 0xFF, 0xEF, 0x07, 0x20, 0x8C, 0xEE, 0x07, 0x20, + 0xFF, 0xE7, 0x07, 0x20, 0x8B, 0xE6, 0x07, 0x20, + 0xFF, 0xDF, 0x07, 0x20, 0x8A, 0xDE, 0x07, 0x20, + 0xFF, 0xD7, 0x07, 0x20, 0x89, 0xD6, 0x07, 0x20, + 0xFF, 0xCF, 0x07, 0x20, 0x88, 0xCE, 0x07, 0x20, + 0xFF, 0xC7, 0x07, 0x20, 0x87, 0xC6, 0x07, 0x20, + 0xFF, 0xBF, 0x07, 0x20, 0x86, 0xBE, 0x07, 0x20, + 0xFF, 0xB7, 0x07, 0x20, 0x85, 0xB6, 0x07, 0x20, + 0xFF, 0xAF, 0x07, 0x20, 0x84, 0xAE, 0x07, 0x20, + 0xFF, 0xA7, 0x07, 0x20, 0x83, 0xA6, 0x07, 0x20, + 0xFF, 0x9F, 0x07, 0x20, 0x82, 0x9E, 0x07, 0x20, + 0xFF, 0x97, 0x07, 0x20, 0x81, 0x96, 0x07, 0x20, + 0xFF, 0x8F, 0x07, 0x20, 0x80, 0x8E, 0x07, 0x20, + 0xFF, 0x87, 0x07, 0x20, 0x7F, 0x86, 0x07, 0x20, + 0xFF, 0xFD, 0x07, 0x20, 0x7E, 0xFC, 0x07, 0x20, + 0xFF, 0xF5, 0x07, 0x20, 0x7D, 0xF4, 0x07, 0x20, + 0xFF, 0xED, 0x07, 0x20, 0x7C, 0xEC, 0x07, 0x20, + 0xFF, 0xE5, 0x07, 0x20, 0x7B, 0xE4, 0x07, 0x20, + 0xFF, 0xDD, 0x07, 0x20, 0x7A, 0xDC, 0x07, 0x20, + 0xFF, 0xD5, 0x07, 0x20, 0x79, 0xD4, 0x07, 0x20, + 0xFF, 0xCD, 0x07, 0x20, 0x78, 0xCC, 0x07, 0x20, + 0xFF, 0xC5, 0x07, 0x20, 0x77, 0xC4, 0x07, 0x20, + 0xFF, 0xBD, 0x07, 0x20, 0x76, 0xBC, 0x07, 0x20, + 0xFF, 0xB5, 0x07, 0x20, 0x75, 0xB4, 0x07, 0x20, + 0xFF, 0xAD, 0x07, 0x20, 0x74, 0xAC, 0x07, 0x20, + 0xFF, 0xA5, 0x07, 0x20, 0x73, 0xA4, 0x07, 0x20, + 0xFF, 0x9D, 0x07, 0x20, 0x72, 0x9C, 0x07, 0x20, + 0xFF, 0x95, 0x07, 0x20, 0x71, 0x94, 0x07, 0x20, + 0xFF, 0x8D, 0x07, 0x20, 0x70, 0x8C, 0x07, 0x20, + 0xFF, 0x85, 0x07, 0x20, 0x6F, 0x84, 0x07, 0x20, + 0xFF, 0xFB, 0x07, 0x20, 0x6E, 0xFA, 0x07, 0x20, + 0xFF, 0xF3, 0x07, 0x20, 0x6D, 0xF2, 0x07, 0x20, + 0xFF, 0xEB, 0x07, 0x20, 0x6C, 0xEA, 0x07, 0x20, + 0xFF, 0xE3, 0x07, 0x20, 0x6B, 0xE2, 0x07, 0x20, + 0xFF, 0xDB, 0x07, 0x20, 0x6A, 0xDA, 0x07, 0x20, + 0xFF, 0xD3, 0x07, 0x20, 0x69, 0xD2, 0x07, 0x20, + 0xFF, 0xCB, 0x07, 0x20, 0x68, 0xCA, 0x07, 0x20, + 0xFF, 0xC3, 0x07, 0x20, 0x67, 0xC2, 0x07, 0x20, + 0xFF, 0xBB, 0x07, 0x20, 0x66, 0xBA, 0x07, 0x20, + 0xFF, 0xB3, 0x07, 0x20, 0x65, 0xB2, 0x07, 0x20, + 0xFF, 0xAB, 0x07, 0x20, 0x64, 0xAA, 0x07, 0x20, + 0xFF, 0xA3, 0x07, 0x20, 0x63, 0xA2, 0x07, 0x20, + 0xFF, 0x9B, 0x07, 0x20, 0x62, 0x9A, 0x07, 0x20, + 0xFF, 0x93, 0x07, 0x20, 0x61, 0x92, 0x07, 0x20, + 0xFF, 0x8B, 0x07, 0x20, 0x60, 0x8A, 0x07, 0x20, + 0xFF, 0x83, 0x07, 0x20, 0x5F, 0x82, 0x07, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, + 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, + 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, + 0x04, 0x0C, 0x00, 0x01, 0x00, 0x01, 0x0D, 0x00, + 0x28, 0x00, 0x20, 0x21, 0x04, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x00, + 0x00, 0x00, 0x20, 0x21, 0x04, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x1C, 0x02, 0xB0, 0x01, 0x00, + 0x00, 0x00, 0x0E, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x00, + 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x00, 0x02, + 0x11, 0x00, 0x02, 0x00, 0x20, 0x00, 0x12, 0x00, + 0x01, 0x00, 0x01, 0x05, 0x00, 0x0E, 0x00, 0x0C, + 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x08, 0x00, 0x00, 0x05, 0x00, 0x0E, + 0x00, 0x10, 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, + 0x00, 0x09, 0x00, 0x04, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x08, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x0C, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x10, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x14, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x18, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x44, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x48, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x4C, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x50, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x58, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC8, + 0x20, 0x04, 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, + 0x05, 0x00, 0x0E, 0x00, 0x14, 0x20, 0xFF, 0xFF, + 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x83, 0x00, 0x03, 0x00, 0x09, 0x00, 0x84, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x88, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x8C, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x90, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x94, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x98, + 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x15, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x28, 0x00, + 0x00, }; static unsigned char vfs5011_init_12[] = { /* 2666 B */ - 0x02, 0xF0, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x09, - 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, - 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, - 0x20, 0x04, 0x30, 0xE5, 0x03, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, - 0xEA, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x4C, 0x20, 0x04, 0x30, 0x0A, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, - 0x04, 0x30, 0x01, 0xDE, 0x01, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, - 0x30, 0x02, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, - 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x08, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x40, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x60, 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, - 0x30, 0x30, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x90, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, - 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x30, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xD8, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, - 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x04, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, - 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, - 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, - 0x30, 0x00, 0x00, 0x74, 0x01, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, - 0x74, 0x01, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, - 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, - 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, - 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, - 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, - 0xFF, 0xF9, 0x87, 0x20, 0xBB, 0xF8, 0x87, 0x00, - 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, - 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, - 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x07, 0x20, - 0xBA, 0xF8, 0x07, 0x20, 0xB9, 0xF8, 0x07, 0x20, - 0xB8, 0xF8, 0x07, 0x20, 0xB7, 0xF8, 0x07, 0x20, - 0xB6, 0xF8, 0x07, 0x20, 0xB5, 0xF8, 0x07, 0x20, - 0xB4, 0xF8, 0x07, 0x20, 0xB3, 0xF8, 0x07, 0x20, - 0xB2, 0xF8, 0x07, 0x20, 0xB1, 0xF8, 0x07, 0x22, - 0xB0, 0xF8, 0x07, 0x22, 0xAF, 0xF8, 0x07, 0x22, - 0xAE, 0xF8, 0x07, 0x22, 0xAD, 0xF8, 0x07, 0x22, - 0xAC, 0xF8, 0x07, 0x22, 0xAB, 0xF8, 0x07, 0x22, - 0xAA, 0xF8, 0x07, 0x22, 0xA9, 0xF8, 0x07, 0x22, - 0xA8, 0xF8, 0x07, 0x22, 0xA7, 0xF8, 0x07, 0x22, - 0xA6, 0xF8, 0x07, 0x22, 0xA5, 0xF8, 0x07, 0x22, - 0xA4, 0xF8, 0x07, 0x22, 0xA3, 0xF8, 0x07, 0x22, - 0xA2, 0xF8, 0x07, 0x22, 0xA1, 0xF8, 0x07, 0x22, - 0xA0, 0xF8, 0x07, 0x22, 0x9F, 0xF8, 0x07, 0x22, - 0x9E, 0xF8, 0x07, 0x22, 0x9D, 0xF8, 0x07, 0x22, - 0x9C, 0xF8, 0x07, 0x22, 0x9B, 0xF8, 0x07, 0x22, - 0x9A, 0xF8, 0x07, 0x22, 0x99, 0xF8, 0x07, 0x22, - 0x98, 0xF8, 0x07, 0x22, 0x97, 0xF8, 0x07, 0x22, - 0x96, 0xF8, 0x07, 0x22, 0x95, 0xF8, 0x07, 0x22, - 0x94, 0xF8, 0x07, 0x22, 0x93, 0xF8, 0x07, 0x22, - 0x92, 0xF8, 0x07, 0x22, 0x91, 0xF8, 0x07, 0x22, - 0x90, 0xF8, 0x07, 0x22, 0x8F, 0xF8, 0x07, 0x22, - 0x8E, 0xF8, 0x07, 0x22, 0x8D, 0xF8, 0x07, 0x22, - 0x8C, 0xF8, 0x07, 0x22, 0x8B, 0xF8, 0x07, 0x22, - 0x8A, 0xF8, 0x07, 0x22, 0x89, 0xF8, 0x07, 0x22, - 0x88, 0xF8, 0x07, 0x22, 0x87, 0xF8, 0x07, 0x22, - 0x86, 0xF8, 0x07, 0x22, 0x85, 0xF8, 0x07, 0x22, - 0x84, 0xF8, 0x07, 0x22, 0x83, 0xF8, 0x07, 0x22, - 0x82, 0xF8, 0x07, 0x22, 0x81, 0xF8, 0x07, 0x22, - 0x80, 0xF8, 0x07, 0x22, 0x7F, 0xF8, 0x07, 0x22, - 0x7E, 0xF8, 0x07, 0x22, 0x7D, 0xF8, 0x07, 0x22, - 0x7C, 0xF8, 0x07, 0x22, 0x7B, 0xF8, 0x07, 0x22, - 0x7A, 0xF8, 0x07, 0x22, 0x79, 0xF8, 0x07, 0x22, - 0x78, 0xF8, 0x07, 0x22, 0x77, 0xF8, 0x07, 0x22, - 0x76, 0xF8, 0x07, 0x22, 0x75, 0xF8, 0x07, 0x22, - 0x74, 0xF8, 0x07, 0x22, 0x73, 0xF8, 0x07, 0x22, - 0x72, 0xF8, 0x07, 0x22, 0x71, 0xF8, 0x07, 0x22, - 0x70, 0xF8, 0x07, 0x22, 0x6F, 0xF8, 0x07, 0x22, - 0x6E, 0xF8, 0x07, 0x22, 0x6D, 0xF8, 0x07, 0x22, - 0x6C, 0xF8, 0x07, 0x22, 0x6B, 0xF8, 0x07, 0x22, - 0x6A, 0xF8, 0x07, 0x22, 0x69, 0xF8, 0x07, 0x22, - 0x68, 0xF8, 0x07, 0x22, 0x67, 0xF8, 0x07, 0x22, - 0x66, 0xF8, 0x07, 0x22, 0x65, 0xF8, 0x07, 0x22, - 0x64, 0xF8, 0x07, 0x22, 0x63, 0xF8, 0x07, 0x22, - 0x62, 0xF8, 0x07, 0x22, 0x61, 0xF8, 0x07, 0x22, - 0x60, 0xF8, 0x07, 0x22, 0x5F, 0xF8, 0x07, 0x22, - 0x5E, 0xF8, 0x07, 0x22, 0x5D, 0xF8, 0x07, 0x22, - 0x5C, 0xF8, 0x07, 0x22, 0x5B, 0xF8, 0x07, 0x22, - 0x5A, 0xF8, 0x07, 0x22, 0x59, 0xF8, 0x07, 0x22, - 0x58, 0xF8, 0x07, 0x22, 0x57, 0xF8, 0x07, 0x22, - 0x56, 0xF8, 0x07, 0x22, 0x55, 0xF8, 0x07, 0x22, - 0x54, 0xF8, 0x07, 0x22, 0x53, 0xF8, 0x07, 0x22, - 0x52, 0xF8, 0x07, 0x22, 0x51, 0xF8, 0x07, 0x22, - 0x50, 0xF8, 0x07, 0x22, 0x4F, 0xF8, 0x07, 0x22, - 0x4E, 0xF8, 0x07, 0x22, 0x4D, 0xF8, 0x07, 0x22, - 0x4C, 0xF8, 0x07, 0x22, 0x4B, 0xF8, 0x07, 0x22, - 0x4A, 0xF8, 0x07, 0x22, 0x49, 0xF8, 0x07, 0x22, - 0x48, 0xF8, 0x07, 0x22, 0x47, 0xF8, 0x07, 0x22, - 0x46, 0xF8, 0x07, 0x22, 0x45, 0xF8, 0x07, 0x22, - 0x44, 0xF8, 0x07, 0x22, 0x43, 0xF8, 0x07, 0x22, - 0x42, 0xF8, 0x07, 0x22, 0x41, 0xF8, 0x07, 0x22, - 0x40, 0xF8, 0x07, 0x22, 0x3F, 0xF8, 0x07, 0x22, - 0x3E, 0xF8, 0x07, 0x22, 0x3D, 0xF8, 0x07, 0x22, - 0x3C, 0xF8, 0x07, 0x22, 0x3B, 0xF8, 0x07, 0x22, - 0x3A, 0xF8, 0x07, 0x22, 0x39, 0xF8, 0x07, 0x22, - 0x38, 0xF8, 0x07, 0x22, 0x37, 0xF8, 0x07, 0x22, - 0x36, 0xF8, 0x07, 0x22, 0x35, 0xF8, 0x07, 0x22, - 0x34, 0xF8, 0x07, 0x22, 0x33, 0xF8, 0x07, 0x22, - 0x32, 0xF8, 0x07, 0x22, 0x31, 0xF8, 0x07, 0x22, - 0x30, 0xF8, 0x07, 0x22, 0x2F, 0xF8, 0x07, 0x22, - 0x2E, 0xF8, 0x07, 0x22, 0x2D, 0xF8, 0x07, 0x22, - 0x2C, 0xF8, 0x07, 0x22, 0x2B, 0xF8, 0x07, 0x22, - 0x2A, 0xF8, 0x07, 0x22, 0x29, 0xF8, 0x07, 0x22, - 0x28, 0xF8, 0x07, 0x22, 0x27, 0xF8, 0x07, 0x22, - 0x26, 0xF8, 0x07, 0x22, 0x25, 0xF8, 0x07, 0x22, - 0x24, 0xF8, 0x07, 0x22, 0x23, 0xF8, 0x07, 0x20, - 0x22, 0xF8, 0x07, 0x20, 0x21, 0xF8, 0x07, 0x20, - 0x20, 0xF8, 0x07, 0x20, 0x1F, 0xF8, 0x07, 0x20, - 0x1E, 0xF8, 0x07, 0x20, 0x1D, 0xF8, 0x07, 0x20, - 0x1C, 0xF8, 0x07, 0x20, 0x1C, 0xF8, 0x07, 0x00, - 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, - 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, - 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, - 0xD8, 0xF8, 0x27, 0x20, 0xD9, 0xF8, 0x27, 0x20, - 0xDA, 0xF8, 0x27, 0x20, 0xDB, 0xF8, 0x27, 0x20, - 0xDC, 0xF8, 0x27, 0x20, 0xDD, 0xF8, 0x27, 0x20, - 0xDE, 0xF8, 0x27, 0x20, 0xDF, 0xF8, 0x27, 0x20, - 0xE0, 0xF8, 0x27, 0x20, 0xE1, 0xF8, 0x27, 0x20, - 0xE2, 0xF8, 0x27, 0x20, 0xE3, 0xF8, 0x27, 0x20, - 0xE4, 0xF8, 0x27, 0x20, 0xE5, 0xF8, 0x27, 0x20, - 0xE6, 0xF8, 0x27, 0x20, 0xE7, 0xF8, 0x27, 0x20, - 0xE8, 0xF8, 0x27, 0x20, 0xE9, 0xF8, 0x27, 0x20, - 0xEA, 0xF8, 0x27, 0x20, 0xEB, 0xF8, 0x27, 0x20, - 0xEC, 0xF8, 0x27, 0x20, 0xED, 0xF8, 0x27, 0x20, - 0xEE, 0xF8, 0x27, 0x20, 0xEF, 0xF8, 0x27, 0x20, - 0xF0, 0xF8, 0x27, 0x20, 0xF1, 0xF8, 0x27, 0x20, - 0xF2, 0xF8, 0x27, 0x20, 0xF3, 0xF8, 0x27, 0x20, - 0xF4, 0xF8, 0x27, 0x20, 0xF5, 0xF8, 0x27, 0x20, - 0xF6, 0xF8, 0x27, 0x20, 0xF7, 0xF8, 0x27, 0x20, - 0xF8, 0xF8, 0x27, 0x20, 0xF9, 0xF8, 0x27, 0x20, - 0xFA, 0xF8, 0x27, 0x20, 0xFB, 0xF8, 0x27, 0x20, - 0xFC, 0xF8, 0x27, 0x20, 0xFD, 0xF8, 0x27, 0x20, - 0xFE, 0xF8, 0x27, 0x20, 0xFF, 0xF8, 0x27, 0x20, - 0x00, 0xF9, 0x27, 0x20, 0xD7, 0xF8, 0x27, 0x20, - 0x00, 0xF8, 0x27, 0x20, 0x01, 0xF8, 0x27, 0x20, - 0x02, 0xF8, 0x27, 0x20, 0x03, 0xF8, 0x27, 0x20, - 0x04, 0xF8, 0x27, 0x20, 0x05, 0xF8, 0x27, 0x20, - 0x06, 0xF8, 0x27, 0x20, 0x07, 0xF8, 0x27, 0x20, - 0x08, 0xF8, 0x27, 0x20, 0x09, 0xF8, 0x27, 0x20, - 0x0A, 0xF8, 0x27, 0x20, 0x0B, 0xF8, 0x27, 0x20, - 0x0C, 0xF8, 0x27, 0x20, 0x0D, 0xF8, 0x27, 0x20, - 0x0E, 0xF8, 0x27, 0x20, 0x0F, 0xF8, 0x27, 0x20, - 0x10, 0xF8, 0x27, 0x20, 0x11, 0xF8, 0x27, 0x20, - 0x12, 0xF8, 0x27, 0x20, 0x13, 0xF8, 0x27, 0x20, - 0x14, 0xF8, 0x27, 0x20, 0x15, 0xF8, 0x27, 0x20, - 0x15, 0xF8, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, - 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, - 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, - 0x04, 0x0C, 0x00, 0x01, 0x00, 0x04, 0x11, 0x00, - 0x02, 0x00, 0x0E, 0x00, 0x13, 0x00, 0x04, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x0A, 0x00, - 0x08, 0x00, 0xA8, 0x00, 0xE6, 0x82, 0xA0, 0x0A, - 0x26, 0x06, 0x07, 0x00, 0x3C, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0xFF, 0xFF, 0x78, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0xA2, 0x55, 0x03, 0xD3, 0xA2, - 0x5D, 0x00, 0x18, 0xA2, 0x55, 0x03, 0xD3, 0xA2, - 0x5D, 0x00, 0x18, 0xA2, 0x55, 0x03, 0x20, 0x80, - 0x80, 0x00, 0xFF, 0x10, 0x0F, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x03, - 0x00, 0x00, 0x05, 0x00, 0x0E, 0x00, 0x0C, 0x20, - 0xFD, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x08, 0x00, 0x00, 0x05, 0x00, 0x0E, 0x00, - 0x10, 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, - 0x09, 0x00, 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x10, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x44, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x48, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x4C, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x54, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x58, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC8, 0x20, - 0x04, 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x05, - 0x00, 0x0E, 0x00, 0x14, 0x20, 0xFF, 0xFF, 0x00, - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, - 0x00, 0x03, 0x00, 0x09, 0x00, 0x84, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x88, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x8C, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x90, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x94, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x98, 0x21, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x20, 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x60, 0x21, 0x04, - 0x30, 0x08, 0x00, 0x00, 0x00, 0x04, 0x15, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x28, - 0x00, 0x00, + 0x02, 0xF0, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x09, + 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, + 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, + 0x20, 0x04, 0x30, 0xE5, 0x03, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, + 0xEA, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x4C, 0x20, 0x04, 0x30, 0x0A, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, + 0x04, 0x30, 0x01, 0xDE, 0x01, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, + 0x30, 0x02, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, + 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x08, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x40, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x60, 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x90, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, + 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x30, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xD8, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, + 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x04, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, + 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, + 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, + 0x30, 0x00, 0x00, 0x74, 0x01, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, + 0x74, 0x01, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, + 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, + 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, + 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, + 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, + 0xFF, 0xF9, 0x87, 0x20, 0xBB, 0xF8, 0x87, 0x00, + 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, + 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, + 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x07, 0x20, + 0xBA, 0xF8, 0x07, 0x20, 0xB9, 0xF8, 0x07, 0x20, + 0xB8, 0xF8, 0x07, 0x20, 0xB7, 0xF8, 0x07, 0x20, + 0xB6, 0xF8, 0x07, 0x20, 0xB5, 0xF8, 0x07, 0x20, + 0xB4, 0xF8, 0x07, 0x20, 0xB3, 0xF8, 0x07, 0x20, + 0xB2, 0xF8, 0x07, 0x20, 0xB1, 0xF8, 0x07, 0x22, + 0xB0, 0xF8, 0x07, 0x22, 0xAF, 0xF8, 0x07, 0x22, + 0xAE, 0xF8, 0x07, 0x22, 0xAD, 0xF8, 0x07, 0x22, + 0xAC, 0xF8, 0x07, 0x22, 0xAB, 0xF8, 0x07, 0x22, + 0xAA, 0xF8, 0x07, 0x22, 0xA9, 0xF8, 0x07, 0x22, + 0xA8, 0xF8, 0x07, 0x22, 0xA7, 0xF8, 0x07, 0x22, + 0xA6, 0xF8, 0x07, 0x22, 0xA5, 0xF8, 0x07, 0x22, + 0xA4, 0xF8, 0x07, 0x22, 0xA3, 0xF8, 0x07, 0x22, + 0xA2, 0xF8, 0x07, 0x22, 0xA1, 0xF8, 0x07, 0x22, + 0xA0, 0xF8, 0x07, 0x22, 0x9F, 0xF8, 0x07, 0x22, + 0x9E, 0xF8, 0x07, 0x22, 0x9D, 0xF8, 0x07, 0x22, + 0x9C, 0xF8, 0x07, 0x22, 0x9B, 0xF8, 0x07, 0x22, + 0x9A, 0xF8, 0x07, 0x22, 0x99, 0xF8, 0x07, 0x22, + 0x98, 0xF8, 0x07, 0x22, 0x97, 0xF8, 0x07, 0x22, + 0x96, 0xF8, 0x07, 0x22, 0x95, 0xF8, 0x07, 0x22, + 0x94, 0xF8, 0x07, 0x22, 0x93, 0xF8, 0x07, 0x22, + 0x92, 0xF8, 0x07, 0x22, 0x91, 0xF8, 0x07, 0x22, + 0x90, 0xF8, 0x07, 0x22, 0x8F, 0xF8, 0x07, 0x22, + 0x8E, 0xF8, 0x07, 0x22, 0x8D, 0xF8, 0x07, 0x22, + 0x8C, 0xF8, 0x07, 0x22, 0x8B, 0xF8, 0x07, 0x22, + 0x8A, 0xF8, 0x07, 0x22, 0x89, 0xF8, 0x07, 0x22, + 0x88, 0xF8, 0x07, 0x22, 0x87, 0xF8, 0x07, 0x22, + 0x86, 0xF8, 0x07, 0x22, 0x85, 0xF8, 0x07, 0x22, + 0x84, 0xF8, 0x07, 0x22, 0x83, 0xF8, 0x07, 0x22, + 0x82, 0xF8, 0x07, 0x22, 0x81, 0xF8, 0x07, 0x22, + 0x80, 0xF8, 0x07, 0x22, 0x7F, 0xF8, 0x07, 0x22, + 0x7E, 0xF8, 0x07, 0x22, 0x7D, 0xF8, 0x07, 0x22, + 0x7C, 0xF8, 0x07, 0x22, 0x7B, 0xF8, 0x07, 0x22, + 0x7A, 0xF8, 0x07, 0x22, 0x79, 0xF8, 0x07, 0x22, + 0x78, 0xF8, 0x07, 0x22, 0x77, 0xF8, 0x07, 0x22, + 0x76, 0xF8, 0x07, 0x22, 0x75, 0xF8, 0x07, 0x22, + 0x74, 0xF8, 0x07, 0x22, 0x73, 0xF8, 0x07, 0x22, + 0x72, 0xF8, 0x07, 0x22, 0x71, 0xF8, 0x07, 0x22, + 0x70, 0xF8, 0x07, 0x22, 0x6F, 0xF8, 0x07, 0x22, + 0x6E, 0xF8, 0x07, 0x22, 0x6D, 0xF8, 0x07, 0x22, + 0x6C, 0xF8, 0x07, 0x22, 0x6B, 0xF8, 0x07, 0x22, + 0x6A, 0xF8, 0x07, 0x22, 0x69, 0xF8, 0x07, 0x22, + 0x68, 0xF8, 0x07, 0x22, 0x67, 0xF8, 0x07, 0x22, + 0x66, 0xF8, 0x07, 0x22, 0x65, 0xF8, 0x07, 0x22, + 0x64, 0xF8, 0x07, 0x22, 0x63, 0xF8, 0x07, 0x22, + 0x62, 0xF8, 0x07, 0x22, 0x61, 0xF8, 0x07, 0x22, + 0x60, 0xF8, 0x07, 0x22, 0x5F, 0xF8, 0x07, 0x22, + 0x5E, 0xF8, 0x07, 0x22, 0x5D, 0xF8, 0x07, 0x22, + 0x5C, 0xF8, 0x07, 0x22, 0x5B, 0xF8, 0x07, 0x22, + 0x5A, 0xF8, 0x07, 0x22, 0x59, 0xF8, 0x07, 0x22, + 0x58, 0xF8, 0x07, 0x22, 0x57, 0xF8, 0x07, 0x22, + 0x56, 0xF8, 0x07, 0x22, 0x55, 0xF8, 0x07, 0x22, + 0x54, 0xF8, 0x07, 0x22, 0x53, 0xF8, 0x07, 0x22, + 0x52, 0xF8, 0x07, 0x22, 0x51, 0xF8, 0x07, 0x22, + 0x50, 0xF8, 0x07, 0x22, 0x4F, 0xF8, 0x07, 0x22, + 0x4E, 0xF8, 0x07, 0x22, 0x4D, 0xF8, 0x07, 0x22, + 0x4C, 0xF8, 0x07, 0x22, 0x4B, 0xF8, 0x07, 0x22, + 0x4A, 0xF8, 0x07, 0x22, 0x49, 0xF8, 0x07, 0x22, + 0x48, 0xF8, 0x07, 0x22, 0x47, 0xF8, 0x07, 0x22, + 0x46, 0xF8, 0x07, 0x22, 0x45, 0xF8, 0x07, 0x22, + 0x44, 0xF8, 0x07, 0x22, 0x43, 0xF8, 0x07, 0x22, + 0x42, 0xF8, 0x07, 0x22, 0x41, 0xF8, 0x07, 0x22, + 0x40, 0xF8, 0x07, 0x22, 0x3F, 0xF8, 0x07, 0x22, + 0x3E, 0xF8, 0x07, 0x22, 0x3D, 0xF8, 0x07, 0x22, + 0x3C, 0xF8, 0x07, 0x22, 0x3B, 0xF8, 0x07, 0x22, + 0x3A, 0xF8, 0x07, 0x22, 0x39, 0xF8, 0x07, 0x22, + 0x38, 0xF8, 0x07, 0x22, 0x37, 0xF8, 0x07, 0x22, + 0x36, 0xF8, 0x07, 0x22, 0x35, 0xF8, 0x07, 0x22, + 0x34, 0xF8, 0x07, 0x22, 0x33, 0xF8, 0x07, 0x22, + 0x32, 0xF8, 0x07, 0x22, 0x31, 0xF8, 0x07, 0x22, + 0x30, 0xF8, 0x07, 0x22, 0x2F, 0xF8, 0x07, 0x22, + 0x2E, 0xF8, 0x07, 0x22, 0x2D, 0xF8, 0x07, 0x22, + 0x2C, 0xF8, 0x07, 0x22, 0x2B, 0xF8, 0x07, 0x22, + 0x2A, 0xF8, 0x07, 0x22, 0x29, 0xF8, 0x07, 0x22, + 0x28, 0xF8, 0x07, 0x22, 0x27, 0xF8, 0x07, 0x22, + 0x26, 0xF8, 0x07, 0x22, 0x25, 0xF8, 0x07, 0x22, + 0x24, 0xF8, 0x07, 0x22, 0x23, 0xF8, 0x07, 0x20, + 0x22, 0xF8, 0x07, 0x20, 0x21, 0xF8, 0x07, 0x20, + 0x20, 0xF8, 0x07, 0x20, 0x1F, 0xF8, 0x07, 0x20, + 0x1E, 0xF8, 0x07, 0x20, 0x1D, 0xF8, 0x07, 0x20, + 0x1C, 0xF8, 0x07, 0x20, 0x1C, 0xF8, 0x07, 0x00, + 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, + 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, + 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, + 0xD8, 0xF8, 0x27, 0x20, 0xD9, 0xF8, 0x27, 0x20, + 0xDA, 0xF8, 0x27, 0x20, 0xDB, 0xF8, 0x27, 0x20, + 0xDC, 0xF8, 0x27, 0x20, 0xDD, 0xF8, 0x27, 0x20, + 0xDE, 0xF8, 0x27, 0x20, 0xDF, 0xF8, 0x27, 0x20, + 0xE0, 0xF8, 0x27, 0x20, 0xE1, 0xF8, 0x27, 0x20, + 0xE2, 0xF8, 0x27, 0x20, 0xE3, 0xF8, 0x27, 0x20, + 0xE4, 0xF8, 0x27, 0x20, 0xE5, 0xF8, 0x27, 0x20, + 0xE6, 0xF8, 0x27, 0x20, 0xE7, 0xF8, 0x27, 0x20, + 0xE8, 0xF8, 0x27, 0x20, 0xE9, 0xF8, 0x27, 0x20, + 0xEA, 0xF8, 0x27, 0x20, 0xEB, 0xF8, 0x27, 0x20, + 0xEC, 0xF8, 0x27, 0x20, 0xED, 0xF8, 0x27, 0x20, + 0xEE, 0xF8, 0x27, 0x20, 0xEF, 0xF8, 0x27, 0x20, + 0xF0, 0xF8, 0x27, 0x20, 0xF1, 0xF8, 0x27, 0x20, + 0xF2, 0xF8, 0x27, 0x20, 0xF3, 0xF8, 0x27, 0x20, + 0xF4, 0xF8, 0x27, 0x20, 0xF5, 0xF8, 0x27, 0x20, + 0xF6, 0xF8, 0x27, 0x20, 0xF7, 0xF8, 0x27, 0x20, + 0xF8, 0xF8, 0x27, 0x20, 0xF9, 0xF8, 0x27, 0x20, + 0xFA, 0xF8, 0x27, 0x20, 0xFB, 0xF8, 0x27, 0x20, + 0xFC, 0xF8, 0x27, 0x20, 0xFD, 0xF8, 0x27, 0x20, + 0xFE, 0xF8, 0x27, 0x20, 0xFF, 0xF8, 0x27, 0x20, + 0x00, 0xF9, 0x27, 0x20, 0xD7, 0xF8, 0x27, 0x20, + 0x00, 0xF8, 0x27, 0x20, 0x01, 0xF8, 0x27, 0x20, + 0x02, 0xF8, 0x27, 0x20, 0x03, 0xF8, 0x27, 0x20, + 0x04, 0xF8, 0x27, 0x20, 0x05, 0xF8, 0x27, 0x20, + 0x06, 0xF8, 0x27, 0x20, 0x07, 0xF8, 0x27, 0x20, + 0x08, 0xF8, 0x27, 0x20, 0x09, 0xF8, 0x27, 0x20, + 0x0A, 0xF8, 0x27, 0x20, 0x0B, 0xF8, 0x27, 0x20, + 0x0C, 0xF8, 0x27, 0x20, 0x0D, 0xF8, 0x27, 0x20, + 0x0E, 0xF8, 0x27, 0x20, 0x0F, 0xF8, 0x27, 0x20, + 0x10, 0xF8, 0x27, 0x20, 0x11, 0xF8, 0x27, 0x20, + 0x12, 0xF8, 0x27, 0x20, 0x13, 0xF8, 0x27, 0x20, + 0x14, 0xF8, 0x27, 0x20, 0x15, 0xF8, 0x27, 0x20, + 0x15, 0xF8, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, + 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, + 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, + 0x04, 0x0C, 0x00, 0x01, 0x00, 0x04, 0x11, 0x00, + 0x02, 0x00, 0x0E, 0x00, 0x13, 0x00, 0x04, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x0A, 0x00, + 0x08, 0x00, 0xA8, 0x00, 0xE6, 0x82, 0xA0, 0x0A, + 0x26, 0x06, 0x07, 0x00, 0x3C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0xFF, 0xFF, 0x78, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0xA2, 0x55, 0x03, 0xD3, 0xA2, + 0x5D, 0x00, 0x18, 0xA2, 0x55, 0x03, 0xD3, 0xA2, + 0x5D, 0x00, 0x18, 0xA2, 0x55, 0x03, 0x20, 0x80, + 0x80, 0x00, 0xFF, 0x10, 0x0F, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x03, + 0x00, 0x00, 0x05, 0x00, 0x0E, 0x00, 0x0C, 0x20, + 0xFD, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x08, 0x00, 0x00, 0x05, 0x00, 0x0E, 0x00, + 0x10, 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, + 0x09, 0x00, 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x10, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x44, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x48, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x4C, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x54, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x58, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC8, 0x20, + 0x04, 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x05, + 0x00, 0x0E, 0x00, 0x14, 0x20, 0xFF, 0xFF, 0x00, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, + 0x00, 0x03, 0x00, 0x09, 0x00, 0x84, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x88, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x8C, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x90, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x94, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x98, 0x21, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x20, 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x60, 0x21, 0x04, + 0x30, 0x08, 0x00, 0x00, 0x00, 0x04, 0x15, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x28, + 0x00, 0x00, }; static unsigned char vfs5011_init_13[] = { /* 57 B */ - 0x12, 0x90, 0x02, 0x00, 0x00, 0xFE, 0x03, 0x00, - 0x00, 0xFF, 0x1F, 0xFF, 0x1F, 0x00, 0x00, 0x00, - 0x00, 0x18, 0xA2, 0x55, 0x03, 0xD3, 0xA2, 0x5D, - 0x00, 0x18, 0xA2, 0x55, 0x03, 0xD3, 0xA2, 0x5D, - 0x00, 0x18, 0xA2, 0x55, 0x03, 0x20, 0xFF, 0x80, - 0x00, 0xFF, 0x04, 0x0F, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x03, 0x00, - 0x00, + 0x12, 0x90, 0x02, 0x00, 0x00, 0xFE, 0x03, 0x00, + 0x00, 0xFF, 0x1F, 0xFF, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x18, 0xA2, 0x55, 0x03, 0xD3, 0xA2, 0x5D, + 0x00, 0x18, 0xA2, 0x55, 0x03, 0xD3, 0xA2, 0x5D, + 0x00, 0x18, 0xA2, 0x55, 0x03, 0x20, 0xFF, 0x80, + 0x00, 0xFF, 0x04, 0x0F, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x03, 0x00, + 0x00, }; static unsigned char vfs5011_init_14[] = { /* 2561 B */ - 0x02, 0xF0, 0x00, 0x14, 0x00, 0x03, 0x00, 0x09, - 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, - 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, - 0x20, 0x04, 0x30, 0xE5, 0x03, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, - 0xEA, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x4C, 0x20, 0x04, 0x30, 0x0A, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, - 0x04, 0x30, 0x01, 0xDE, 0x01, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, - 0x30, 0x02, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, - 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x08, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x40, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x60, 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, - 0x30, 0x30, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x90, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, - 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x30, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xD8, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, - 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x04, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, - 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, - 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, - 0x30, 0x00, 0x00, 0x74, 0x01, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, - 0x74, 0x01, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, - 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, - 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, - 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, - 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, - 0xFF, 0xF9, 0x87, 0x20, 0xBB, 0xF8, 0x87, 0x00, - 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, - 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, - 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x07, 0x20, - 0xBA, 0xF8, 0x07, 0x20, 0xB9, 0xF8, 0x07, 0x20, - 0xB8, 0xF8, 0x07, 0x20, 0xB7, 0xF8, 0x07, 0x20, - 0xB6, 0xF8, 0x07, 0x20, 0xB5, 0xF8, 0x07, 0x20, - 0xB4, 0xF8, 0x07, 0x20, 0xB3, 0xF8, 0x07, 0x20, - 0xB2, 0xF8, 0x07, 0x20, 0xB1, 0xF8, 0x07, 0x22, - 0xB0, 0xF8, 0x07, 0x22, 0xAF, 0xF8, 0x07, 0x22, - 0xAE, 0xF8, 0x07, 0x22, 0xAD, 0xF8, 0x07, 0x22, - 0xAC, 0xF8, 0x07, 0x22, 0xAB, 0xF8, 0x07, 0x22, - 0xAA, 0xF8, 0x07, 0x22, 0xA9, 0xF8, 0x07, 0x22, - 0xA8, 0xF8, 0x07, 0x22, 0xA7, 0xF8, 0x07, 0x22, - 0xA6, 0xF8, 0x07, 0x22, 0xA5, 0xF8, 0x07, 0x22, - 0xA4, 0xF8, 0x07, 0x22, 0xA3, 0xF8, 0x07, 0x22, - 0xA2, 0xF8, 0x07, 0x22, 0xA1, 0xF8, 0x07, 0x22, - 0xA0, 0xF8, 0x07, 0x22, 0x9F, 0xF8, 0x07, 0x22, - 0x9E, 0xF8, 0x07, 0x22, 0x9D, 0xF8, 0x07, 0x22, - 0x9C, 0xF8, 0x07, 0x22, 0x9B, 0xF8, 0x07, 0x22, - 0x9A, 0xF8, 0x07, 0x22, 0x99, 0xF8, 0x07, 0x22, - 0x98, 0xF8, 0x07, 0x22, 0x97, 0xF8, 0x07, 0x22, - 0x96, 0xF8, 0x07, 0x22, 0x95, 0xF8, 0x07, 0x22, - 0x94, 0xF8, 0x07, 0x22, 0x93, 0xF8, 0x07, 0x22, - 0x92, 0xF8, 0x07, 0x22, 0x91, 0xF8, 0x07, 0x22, - 0x90, 0xF8, 0x07, 0x22, 0x8F, 0xF8, 0x07, 0x22, - 0x8E, 0xF8, 0x07, 0x22, 0x8D, 0xF8, 0x07, 0x22, - 0x8C, 0xF8, 0x07, 0x22, 0x8B, 0xF8, 0x07, 0x22, - 0x8A, 0xF8, 0x07, 0x22, 0x89, 0xF8, 0x07, 0x22, - 0x88, 0xF8, 0x07, 0x22, 0x87, 0xF8, 0x07, 0x22, - 0x86, 0xF8, 0x07, 0x22, 0x85, 0xF8, 0x07, 0x22, - 0x84, 0xF8, 0x07, 0x22, 0x83, 0xF8, 0x07, 0x22, - 0x82, 0xF8, 0x07, 0x22, 0x81, 0xF8, 0x07, 0x22, - 0x80, 0xF8, 0x07, 0x22, 0x7F, 0xF8, 0x07, 0x22, - 0x7E, 0xF8, 0x07, 0x22, 0x7D, 0xF8, 0x07, 0x22, - 0x7C, 0xF8, 0x07, 0x22, 0x7B, 0xF8, 0x07, 0x22, - 0x7A, 0xF8, 0x07, 0x22, 0x79, 0xF8, 0x07, 0x22, - 0x78, 0xF8, 0x07, 0x22, 0x77, 0xF8, 0x07, 0x22, - 0x76, 0xF8, 0x07, 0x22, 0x75, 0xF8, 0x07, 0x22, - 0x74, 0xF8, 0x07, 0x22, 0x73, 0xF8, 0x07, 0x22, - 0x72, 0xF8, 0x07, 0x22, 0x71, 0xF8, 0x07, 0x22, - 0x70, 0xF8, 0x07, 0x22, 0x6F, 0xF8, 0x07, 0x22, - 0x6E, 0xF8, 0x07, 0x22, 0x6D, 0xF8, 0x07, 0x22, - 0x6C, 0xF8, 0x07, 0x22, 0x6B, 0xF8, 0x07, 0x22, - 0x6A, 0xF8, 0x07, 0x22, 0x69, 0xF8, 0x07, 0x22, - 0x68, 0xF8, 0x07, 0x22, 0x67, 0xF8, 0x07, 0x22, - 0x66, 0xF8, 0x07, 0x22, 0x65, 0xF8, 0x07, 0x22, - 0x64, 0xF8, 0x07, 0x22, 0x63, 0xF8, 0x07, 0x22, - 0x62, 0xF8, 0x07, 0x22, 0x61, 0xF8, 0x07, 0x22, - 0x60, 0xF8, 0x07, 0x22, 0x5F, 0xF8, 0x07, 0x22, - 0x5E, 0xF8, 0x07, 0x22, 0x5D, 0xF8, 0x07, 0x22, - 0x5C, 0xF8, 0x07, 0x22, 0x5B, 0xF8, 0x07, 0x22, - 0x5A, 0xF8, 0x07, 0x22, 0x59, 0xF8, 0x07, 0x22, - 0x58, 0xF8, 0x07, 0x22, 0x57, 0xF8, 0x07, 0x22, - 0x56, 0xF8, 0x07, 0x22, 0x55, 0xF8, 0x07, 0x22, - 0x54, 0xF8, 0x07, 0x22, 0x53, 0xF8, 0x07, 0x22, - 0x52, 0xF8, 0x07, 0x22, 0x51, 0xF8, 0x07, 0x22, - 0x50, 0xF8, 0x07, 0x22, 0x4F, 0xF8, 0x07, 0x22, - 0x4E, 0xF8, 0x07, 0x22, 0x4D, 0xF8, 0x07, 0x22, - 0x4C, 0xF8, 0x07, 0x22, 0x4B, 0xF8, 0x07, 0x22, - 0x4A, 0xF8, 0x07, 0x22, 0x49, 0xF8, 0x07, 0x22, - 0x48, 0xF8, 0x07, 0x22, 0x47, 0xF8, 0x07, 0x22, - 0x46, 0xF8, 0x07, 0x22, 0x45, 0xF8, 0x07, 0x22, - 0x44, 0xF8, 0x07, 0x22, 0x43, 0xF8, 0x07, 0x22, - 0x42, 0xF8, 0x07, 0x22, 0x41, 0xF8, 0x07, 0x22, - 0x40, 0xF8, 0x07, 0x22, 0x3F, 0xF8, 0x07, 0x22, - 0x3E, 0xF8, 0x07, 0x22, 0x3D, 0xF8, 0x07, 0x22, - 0x3C, 0xF8, 0x07, 0x22, 0x3B, 0xF8, 0x07, 0x22, - 0x3A, 0xF8, 0x07, 0x22, 0x39, 0xF8, 0x07, 0x22, - 0x38, 0xF8, 0x07, 0x22, 0x37, 0xF8, 0x07, 0x22, - 0x36, 0xF8, 0x07, 0x22, 0x35, 0xF8, 0x07, 0x22, - 0x34, 0xF8, 0x07, 0x22, 0x33, 0xF8, 0x07, 0x22, - 0x32, 0xF8, 0x07, 0x22, 0x31, 0xF8, 0x07, 0x22, - 0x30, 0xF8, 0x07, 0x22, 0x2F, 0xF8, 0x07, 0x22, - 0x2E, 0xF8, 0x07, 0x22, 0x2D, 0xF8, 0x07, 0x22, - 0x2C, 0xF8, 0x07, 0x22, 0x2B, 0xF8, 0x07, 0x22, - 0x2A, 0xF8, 0x07, 0x22, 0x29, 0xF8, 0x07, 0x22, - 0x28, 0xF8, 0x07, 0x22, 0x27, 0xF8, 0x07, 0x22, - 0x26, 0xF8, 0x07, 0x22, 0x25, 0xF8, 0x07, 0x22, - 0x24, 0xF8, 0x07, 0x22, 0x23, 0xF8, 0x07, 0x20, - 0x22, 0xF8, 0x07, 0x20, 0x21, 0xF8, 0x07, 0x20, - 0x20, 0xF8, 0x07, 0x20, 0x1F, 0xF8, 0x07, 0x20, - 0x1E, 0xF8, 0x07, 0x20, 0x1D, 0xF8, 0x07, 0x20, - 0x1C, 0xF8, 0x07, 0x20, 0x1C, 0xF8, 0x07, 0x00, - 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, - 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, - 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, - 0xD8, 0xF8, 0x27, 0x20, 0xD9, 0xF8, 0x27, 0x20, - 0xDA, 0xF8, 0x27, 0x20, 0xDB, 0xF8, 0x27, 0x20, - 0xDC, 0xF8, 0x27, 0x20, 0xDD, 0xF8, 0x27, 0x20, - 0xDE, 0xF8, 0x27, 0x20, 0xDF, 0xF8, 0x27, 0x20, - 0xE0, 0xF8, 0x27, 0x20, 0xE1, 0xF8, 0x27, 0x20, - 0xE2, 0xF8, 0x27, 0x20, 0xE3, 0xF8, 0x27, 0x20, - 0xE4, 0xF8, 0x27, 0x20, 0xE5, 0xF8, 0x27, 0x20, - 0xE6, 0xF8, 0x27, 0x20, 0xE7, 0xF8, 0x27, 0x20, - 0xE8, 0xF8, 0x27, 0x20, 0xE9, 0xF8, 0x27, 0x20, - 0xEA, 0xF8, 0x27, 0x20, 0xEB, 0xF8, 0x27, 0x20, - 0xEC, 0xF8, 0x27, 0x20, 0xED, 0xF8, 0x27, 0x20, - 0xEE, 0xF8, 0x27, 0x20, 0xEF, 0xF8, 0x27, 0x20, - 0xF0, 0xF8, 0x27, 0x20, 0xF1, 0xF8, 0x27, 0x20, - 0xF2, 0xF8, 0x27, 0x20, 0xF3, 0xF8, 0x27, 0x20, - 0xF4, 0xF8, 0x27, 0x20, 0xF5, 0xF8, 0x27, 0x20, - 0xF6, 0xF8, 0x27, 0x20, 0xF7, 0xF8, 0x27, 0x20, - 0xF8, 0xF8, 0x27, 0x20, 0xF9, 0xF8, 0x27, 0x20, - 0xFA, 0xF8, 0x27, 0x20, 0xFB, 0xF8, 0x27, 0x20, - 0xFC, 0xF8, 0x27, 0x20, 0xFD, 0xF8, 0x27, 0x20, - 0xFE, 0xF8, 0x27, 0x20, 0xFF, 0xF8, 0x27, 0x20, - 0x00, 0xF9, 0x27, 0x20, 0xD7, 0xF8, 0x27, 0x20, - 0x00, 0xF8, 0x27, 0x20, 0x01, 0xF8, 0x27, 0x20, - 0x02, 0xF8, 0x27, 0x20, 0x03, 0xF8, 0x27, 0x20, - 0x04, 0xF8, 0x27, 0x20, 0x05, 0xF8, 0x27, 0x20, - 0x06, 0xF8, 0x27, 0x20, 0x07, 0xF8, 0x27, 0x20, - 0x08, 0xF8, 0x27, 0x20, 0x09, 0xF8, 0x27, 0x20, - 0x0A, 0xF8, 0x27, 0x20, 0x0B, 0xF8, 0x27, 0x20, - 0x0C, 0xF8, 0x27, 0x20, 0x0D, 0xF8, 0x27, 0x20, - 0x0E, 0xF8, 0x27, 0x20, 0x0F, 0xF8, 0x27, 0x20, - 0x10, 0xF8, 0x27, 0x20, 0x11, 0xF8, 0x27, 0x20, - 0x12, 0xF8, 0x27, 0x20, 0x13, 0xF8, 0x27, 0x20, - 0x14, 0xF8, 0x27, 0x20, 0x15, 0xF8, 0x27, 0x20, - 0x15, 0xF8, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, - 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, - 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, - 0x04, 0x05, 0x00, 0x0E, 0x00, 0x0C, 0x20, 0xFD, - 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x08, 0x00, 0x00, 0x05, 0x00, 0x0E, 0x00, 0x10, - 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x09, - 0x00, 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x10, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x4C, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x58, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, - 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, - 0x0E, 0x00, 0x14, 0x20, 0xFF, 0xFF, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, - 0x03, 0x00, 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x88, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x90, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x94, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xA0, 0x21, 0x04, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x20, - 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x60, 0x21, 0x04, 0x30, - 0x08, 0x00, 0x00, 0x00, 0x04, 0x15, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x28, 0x00, - 0x00, + 0x02, 0xF0, 0x00, 0x14, 0x00, 0x03, 0x00, 0x09, + 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, + 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, + 0x20, 0x04, 0x30, 0xE5, 0x03, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, + 0xEA, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x4C, 0x20, 0x04, 0x30, 0x0A, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, + 0x04, 0x30, 0x01, 0xDE, 0x01, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, + 0x30, 0x02, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, + 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x08, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x40, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x60, 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x90, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, + 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x30, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xD8, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, + 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x04, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, + 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, + 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, + 0x30, 0x00, 0x00, 0x74, 0x01, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, + 0x74, 0x01, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, + 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, + 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, + 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, + 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, + 0xFF, 0xF9, 0x87, 0x20, 0xBB, 0xF8, 0x87, 0x00, + 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, + 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, + 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x07, 0x20, + 0xBA, 0xF8, 0x07, 0x20, 0xB9, 0xF8, 0x07, 0x20, + 0xB8, 0xF8, 0x07, 0x20, 0xB7, 0xF8, 0x07, 0x20, + 0xB6, 0xF8, 0x07, 0x20, 0xB5, 0xF8, 0x07, 0x20, + 0xB4, 0xF8, 0x07, 0x20, 0xB3, 0xF8, 0x07, 0x20, + 0xB2, 0xF8, 0x07, 0x20, 0xB1, 0xF8, 0x07, 0x22, + 0xB0, 0xF8, 0x07, 0x22, 0xAF, 0xF8, 0x07, 0x22, + 0xAE, 0xF8, 0x07, 0x22, 0xAD, 0xF8, 0x07, 0x22, + 0xAC, 0xF8, 0x07, 0x22, 0xAB, 0xF8, 0x07, 0x22, + 0xAA, 0xF8, 0x07, 0x22, 0xA9, 0xF8, 0x07, 0x22, + 0xA8, 0xF8, 0x07, 0x22, 0xA7, 0xF8, 0x07, 0x22, + 0xA6, 0xF8, 0x07, 0x22, 0xA5, 0xF8, 0x07, 0x22, + 0xA4, 0xF8, 0x07, 0x22, 0xA3, 0xF8, 0x07, 0x22, + 0xA2, 0xF8, 0x07, 0x22, 0xA1, 0xF8, 0x07, 0x22, + 0xA0, 0xF8, 0x07, 0x22, 0x9F, 0xF8, 0x07, 0x22, + 0x9E, 0xF8, 0x07, 0x22, 0x9D, 0xF8, 0x07, 0x22, + 0x9C, 0xF8, 0x07, 0x22, 0x9B, 0xF8, 0x07, 0x22, + 0x9A, 0xF8, 0x07, 0x22, 0x99, 0xF8, 0x07, 0x22, + 0x98, 0xF8, 0x07, 0x22, 0x97, 0xF8, 0x07, 0x22, + 0x96, 0xF8, 0x07, 0x22, 0x95, 0xF8, 0x07, 0x22, + 0x94, 0xF8, 0x07, 0x22, 0x93, 0xF8, 0x07, 0x22, + 0x92, 0xF8, 0x07, 0x22, 0x91, 0xF8, 0x07, 0x22, + 0x90, 0xF8, 0x07, 0x22, 0x8F, 0xF8, 0x07, 0x22, + 0x8E, 0xF8, 0x07, 0x22, 0x8D, 0xF8, 0x07, 0x22, + 0x8C, 0xF8, 0x07, 0x22, 0x8B, 0xF8, 0x07, 0x22, + 0x8A, 0xF8, 0x07, 0x22, 0x89, 0xF8, 0x07, 0x22, + 0x88, 0xF8, 0x07, 0x22, 0x87, 0xF8, 0x07, 0x22, + 0x86, 0xF8, 0x07, 0x22, 0x85, 0xF8, 0x07, 0x22, + 0x84, 0xF8, 0x07, 0x22, 0x83, 0xF8, 0x07, 0x22, + 0x82, 0xF8, 0x07, 0x22, 0x81, 0xF8, 0x07, 0x22, + 0x80, 0xF8, 0x07, 0x22, 0x7F, 0xF8, 0x07, 0x22, + 0x7E, 0xF8, 0x07, 0x22, 0x7D, 0xF8, 0x07, 0x22, + 0x7C, 0xF8, 0x07, 0x22, 0x7B, 0xF8, 0x07, 0x22, + 0x7A, 0xF8, 0x07, 0x22, 0x79, 0xF8, 0x07, 0x22, + 0x78, 0xF8, 0x07, 0x22, 0x77, 0xF8, 0x07, 0x22, + 0x76, 0xF8, 0x07, 0x22, 0x75, 0xF8, 0x07, 0x22, + 0x74, 0xF8, 0x07, 0x22, 0x73, 0xF8, 0x07, 0x22, + 0x72, 0xF8, 0x07, 0x22, 0x71, 0xF8, 0x07, 0x22, + 0x70, 0xF8, 0x07, 0x22, 0x6F, 0xF8, 0x07, 0x22, + 0x6E, 0xF8, 0x07, 0x22, 0x6D, 0xF8, 0x07, 0x22, + 0x6C, 0xF8, 0x07, 0x22, 0x6B, 0xF8, 0x07, 0x22, + 0x6A, 0xF8, 0x07, 0x22, 0x69, 0xF8, 0x07, 0x22, + 0x68, 0xF8, 0x07, 0x22, 0x67, 0xF8, 0x07, 0x22, + 0x66, 0xF8, 0x07, 0x22, 0x65, 0xF8, 0x07, 0x22, + 0x64, 0xF8, 0x07, 0x22, 0x63, 0xF8, 0x07, 0x22, + 0x62, 0xF8, 0x07, 0x22, 0x61, 0xF8, 0x07, 0x22, + 0x60, 0xF8, 0x07, 0x22, 0x5F, 0xF8, 0x07, 0x22, + 0x5E, 0xF8, 0x07, 0x22, 0x5D, 0xF8, 0x07, 0x22, + 0x5C, 0xF8, 0x07, 0x22, 0x5B, 0xF8, 0x07, 0x22, + 0x5A, 0xF8, 0x07, 0x22, 0x59, 0xF8, 0x07, 0x22, + 0x58, 0xF8, 0x07, 0x22, 0x57, 0xF8, 0x07, 0x22, + 0x56, 0xF8, 0x07, 0x22, 0x55, 0xF8, 0x07, 0x22, + 0x54, 0xF8, 0x07, 0x22, 0x53, 0xF8, 0x07, 0x22, + 0x52, 0xF8, 0x07, 0x22, 0x51, 0xF8, 0x07, 0x22, + 0x50, 0xF8, 0x07, 0x22, 0x4F, 0xF8, 0x07, 0x22, + 0x4E, 0xF8, 0x07, 0x22, 0x4D, 0xF8, 0x07, 0x22, + 0x4C, 0xF8, 0x07, 0x22, 0x4B, 0xF8, 0x07, 0x22, + 0x4A, 0xF8, 0x07, 0x22, 0x49, 0xF8, 0x07, 0x22, + 0x48, 0xF8, 0x07, 0x22, 0x47, 0xF8, 0x07, 0x22, + 0x46, 0xF8, 0x07, 0x22, 0x45, 0xF8, 0x07, 0x22, + 0x44, 0xF8, 0x07, 0x22, 0x43, 0xF8, 0x07, 0x22, + 0x42, 0xF8, 0x07, 0x22, 0x41, 0xF8, 0x07, 0x22, + 0x40, 0xF8, 0x07, 0x22, 0x3F, 0xF8, 0x07, 0x22, + 0x3E, 0xF8, 0x07, 0x22, 0x3D, 0xF8, 0x07, 0x22, + 0x3C, 0xF8, 0x07, 0x22, 0x3B, 0xF8, 0x07, 0x22, + 0x3A, 0xF8, 0x07, 0x22, 0x39, 0xF8, 0x07, 0x22, + 0x38, 0xF8, 0x07, 0x22, 0x37, 0xF8, 0x07, 0x22, + 0x36, 0xF8, 0x07, 0x22, 0x35, 0xF8, 0x07, 0x22, + 0x34, 0xF8, 0x07, 0x22, 0x33, 0xF8, 0x07, 0x22, + 0x32, 0xF8, 0x07, 0x22, 0x31, 0xF8, 0x07, 0x22, + 0x30, 0xF8, 0x07, 0x22, 0x2F, 0xF8, 0x07, 0x22, + 0x2E, 0xF8, 0x07, 0x22, 0x2D, 0xF8, 0x07, 0x22, + 0x2C, 0xF8, 0x07, 0x22, 0x2B, 0xF8, 0x07, 0x22, + 0x2A, 0xF8, 0x07, 0x22, 0x29, 0xF8, 0x07, 0x22, + 0x28, 0xF8, 0x07, 0x22, 0x27, 0xF8, 0x07, 0x22, + 0x26, 0xF8, 0x07, 0x22, 0x25, 0xF8, 0x07, 0x22, + 0x24, 0xF8, 0x07, 0x22, 0x23, 0xF8, 0x07, 0x20, + 0x22, 0xF8, 0x07, 0x20, 0x21, 0xF8, 0x07, 0x20, + 0x20, 0xF8, 0x07, 0x20, 0x1F, 0xF8, 0x07, 0x20, + 0x1E, 0xF8, 0x07, 0x20, 0x1D, 0xF8, 0x07, 0x20, + 0x1C, 0xF8, 0x07, 0x20, 0x1C, 0xF8, 0x07, 0x00, + 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, + 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, + 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, + 0xD8, 0xF8, 0x27, 0x20, 0xD9, 0xF8, 0x27, 0x20, + 0xDA, 0xF8, 0x27, 0x20, 0xDB, 0xF8, 0x27, 0x20, + 0xDC, 0xF8, 0x27, 0x20, 0xDD, 0xF8, 0x27, 0x20, + 0xDE, 0xF8, 0x27, 0x20, 0xDF, 0xF8, 0x27, 0x20, + 0xE0, 0xF8, 0x27, 0x20, 0xE1, 0xF8, 0x27, 0x20, + 0xE2, 0xF8, 0x27, 0x20, 0xE3, 0xF8, 0x27, 0x20, + 0xE4, 0xF8, 0x27, 0x20, 0xE5, 0xF8, 0x27, 0x20, + 0xE6, 0xF8, 0x27, 0x20, 0xE7, 0xF8, 0x27, 0x20, + 0xE8, 0xF8, 0x27, 0x20, 0xE9, 0xF8, 0x27, 0x20, + 0xEA, 0xF8, 0x27, 0x20, 0xEB, 0xF8, 0x27, 0x20, + 0xEC, 0xF8, 0x27, 0x20, 0xED, 0xF8, 0x27, 0x20, + 0xEE, 0xF8, 0x27, 0x20, 0xEF, 0xF8, 0x27, 0x20, + 0xF0, 0xF8, 0x27, 0x20, 0xF1, 0xF8, 0x27, 0x20, + 0xF2, 0xF8, 0x27, 0x20, 0xF3, 0xF8, 0x27, 0x20, + 0xF4, 0xF8, 0x27, 0x20, 0xF5, 0xF8, 0x27, 0x20, + 0xF6, 0xF8, 0x27, 0x20, 0xF7, 0xF8, 0x27, 0x20, + 0xF8, 0xF8, 0x27, 0x20, 0xF9, 0xF8, 0x27, 0x20, + 0xFA, 0xF8, 0x27, 0x20, 0xFB, 0xF8, 0x27, 0x20, + 0xFC, 0xF8, 0x27, 0x20, 0xFD, 0xF8, 0x27, 0x20, + 0xFE, 0xF8, 0x27, 0x20, 0xFF, 0xF8, 0x27, 0x20, + 0x00, 0xF9, 0x27, 0x20, 0xD7, 0xF8, 0x27, 0x20, + 0x00, 0xF8, 0x27, 0x20, 0x01, 0xF8, 0x27, 0x20, + 0x02, 0xF8, 0x27, 0x20, 0x03, 0xF8, 0x27, 0x20, + 0x04, 0xF8, 0x27, 0x20, 0x05, 0xF8, 0x27, 0x20, + 0x06, 0xF8, 0x27, 0x20, 0x07, 0xF8, 0x27, 0x20, + 0x08, 0xF8, 0x27, 0x20, 0x09, 0xF8, 0x27, 0x20, + 0x0A, 0xF8, 0x27, 0x20, 0x0B, 0xF8, 0x27, 0x20, + 0x0C, 0xF8, 0x27, 0x20, 0x0D, 0xF8, 0x27, 0x20, + 0x0E, 0xF8, 0x27, 0x20, 0x0F, 0xF8, 0x27, 0x20, + 0x10, 0xF8, 0x27, 0x20, 0x11, 0xF8, 0x27, 0x20, + 0x12, 0xF8, 0x27, 0x20, 0x13, 0xF8, 0x27, 0x20, + 0x14, 0xF8, 0x27, 0x20, 0x15, 0xF8, 0x27, 0x20, + 0x15, 0xF8, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, + 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, + 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, + 0x04, 0x05, 0x00, 0x0E, 0x00, 0x0C, 0x20, 0xFD, + 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x08, 0x00, 0x00, 0x05, 0x00, 0x0E, 0x00, 0x10, + 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x09, + 0x00, 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x10, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x4C, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x58, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, + 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, + 0x0E, 0x00, 0x14, 0x20, 0xFF, 0xFF, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, + 0x03, 0x00, 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x88, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x90, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x94, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xA0, 0x21, 0x04, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x20, + 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x60, 0x21, 0x04, 0x30, + 0x08, 0x00, 0x00, 0x00, 0x04, 0x15, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x28, 0x00, + 0x00, }; static unsigned char vfs5011_cmd_27[] = { /* 1 B */ - 0x27, + 0x27, }; static unsigned char vfs5011_init_15[] = { /* 3794 B */ - 0x06, 0x6B, 0x06, 0x6A, 0x76, 0xC8, 0x18, 0xD4, - 0x54, 0xEF, 0x71, 0x14, 0xCC, 0x1C, 0x58, 0x91, - 0x11, 0xAA, 0x80, 0xF4, 0x2C, 0xFC, 0x9F, 0x5F, - 0xDF, 0x04, 0x02, 0x62, 0xBA, 0x6A, 0x5A, 0x97, - 0x17, 0xCC, 0x46, 0x22, 0xFA, 0x2A, 0xBE, 0x03, - 0x87, 0x3C, 0x9E, 0xFE, 0x26, 0xF6, 0x96, 0x7E, - 0xFA, 0x11, 0x27, 0x66, 0xBA, 0x3A, 0x5A, 0xBA, - 0x3E, 0xD5, 0x4F, 0x03, 0xDF, 0x5F, 0x7F, 0x9F, - 0x1B, 0xF0, 0xA2, 0xEF, 0x33, 0xB3, 0xD3, 0x13, - 0x93, 0x70, 0xFA, 0x96, 0x4E, 0xC6, 0xA6, 0xC6, - 0x46, 0xA5, 0x2F, 0xE3, 0x3B, 0xB3, 0xD3, 0x33, - 0xB3, 0x50, 0xE8, 0xA4, 0x7C, 0xF4, 0x94, 0x14, - 0x94, 0x77, 0xC9, 0xE5, 0x3D, 0xB5, 0xD5, 0x75, - 0xF5, 0x16, 0xA8, 0xA4, 0x7C, 0xF4, 0x94, 0xD4, - 0x54, 0xB7, 0x09, 0xE5, 0x3D, 0xB5, 0x2D, 0xF4, - 0x74, 0xCF, 0x29, 0x5C, 0x84, 0x54, 0x14, 0xAA, - 0x2E, 0x95, 0xF7, 0xE0, 0x3C, 0xEC, 0x8C, 0x52, - 0xD6, 0x3D, 0x7B, 0x0E, 0xD6, 0x06, 0x82, 0x49, - 0xC9, 0x72, 0x7C, 0x18, 0xC0, 0x10, 0x10, 0xF6, - 0x72, 0xC9, 0xC3, 0xA8, 0x70, 0xA0, 0xD8, 0x77, - 0xF3, 0x48, 0x06, 0x04, 0xD8, 0x08, 0x90, 0x5B, - 0xDB, 0x60, 0x36, 0x43, 0x9B, 0x4B, 0xD4, 0xE3, - 0x9C, 0xB8, 0xF1, 0x72, 0x55, 0x1A, 0x8E, 0x57, - 0xD7, 0x6C, 0xDA, 0xBE, 0x66, 0xD6, 0xEA, 0x3D, - 0xBF, 0x04, 0xB2, 0xCE, 0x16, 0xA6, 0x06, 0xDE, - 0x5E, 0xE5, 0xB7, 0xC3, 0x1B, 0xCB, 0x47, 0x9F, - 0x1F, 0xA4, 0x3E, 0x5B, 0x83, 0x53, 0x53, 0x8A, - 0x0A, 0xB1, 0x93, 0xF9, 0x21, 0xF1, 0x31, 0xE6, - 0x64, 0xDF, 0x95, 0xE0, 0x38, 0xE8, 0xB4, 0x6D, - 0xED, 0x56, 0x1D, 0x8E, 0x56, 0xE6, 0x79, 0xB9, - 0xC6, 0xE2, 0x62, 0x4F, 0x97, 0x02, 0x40, 0x80, - 0x65, 0xB8, 0x0E, 0x07, 0xC2, 0x72, 0x37, 0xBE, - 0x3E, 0x00, 0xF2, 0xB8, 0xF1, 0x6D, 0x0E, 0x6F, - 0xC2, 0x1A, 0xA0, 0xC4, 0x95, 0x2F, 0xCD, 0x44, - 0xC4, 0x02, 0x44, 0x28, 0xF0, 0x40, 0x16, 0x97, - 0x17, 0x7D, 0xE4, 0x8B, 0xFE, 0x4C, 0x0D, 0xE3, - 0x60, 0xFD, 0x4B, 0x27, 0x34, 0xA6, 0xCD, 0xB6, - 0x10, 0xC0, 0x7C, 0x98, 0x42, 0x72, 0x92, 0x26, - 0x21, 0x60, 0x26, 0x4C, 0x95, 0x25, 0xA0, 0x03, - 0xA6, 0x50, 0xEC, 0x9D, 0xB5, 0x05, 0x53, 0xD2, - 0x52, 0xA9, 0x7E, 0x12, 0x2F, 0x65, 0xFA, 0x1A, - 0x7C, 0xB4, 0x12, 0x5E, 0x86, 0x3A, 0x50, 0xF5, - 0x53, 0xAD, 0xBA, 0xE6, 0x3D, 0x3C, 0x6D, 0xAE, - 0xCB, 0x33, 0xAD, 0xDC, 0xF4, 0x44, 0x12, 0x93, - 0x13, 0xF9, 0x7D, 0x12, 0xEB, 0x68, 0x0B, 0xE2, - 0x21, 0xE7, 0xA1, 0xCD, 0x15, 0xA5, 0xF3, 0x72, - 0xF2, 0xAB, 0x1F, 0x7E, 0xAA, 0x01, 0xE1, 0xA1, - 0x25, 0xA8, 0x06, 0x6D, 0xB9, 0x0C, 0x60, 0xA6, - 0x64, 0xAD, 0x15, 0x65, 0xBA, 0x30, 0x14, 0x66, - 0x22, 0x78, 0xFC, 0x94, 0x4C, 0x4E, 0x25, 0x9B, - 0xD9, 0x06, 0xB1, 0xEA, 0x89, 0x35, 0x62, 0x1E, - 0x8F, 0x69, 0xD4, 0x7F, 0x1C, 0xA0, 0xFD, 0x31, - 0x77, 0xAD, 0x1B, 0x40, 0xA4, 0x10, 0xB7, 0xCC, - 0x4D, 0xAB, 0x16, 0xD7, 0x0C, 0x01, 0x62, 0x87, - 0xBF, 0x4C, 0x50, 0x5A, 0xD8, 0x3B, 0x50, 0xE7, - 0x2C, 0xB3, 0xB7, 0x1F, 0x46, 0xA0, 0x57, 0x6B, - 0x46, 0x98, 0x93, 0xFA, 0xC7, 0xC1, 0x89, 0x45, - 0xDE, 0xD7, 0xC3, 0xC3, 0xBB, 0xCF, 0xEE, 0xEE, - 0xA8, 0xB3, 0xDF, 0x61, 0x4B, 0xE6, 0x04, 0x04, - 0x40, 0xDA, 0xAC, 0x43, 0xDA, 0x9A, 0x15, 0x25, - 0x45, 0x7D, 0xEA, 0x0C, 0x3A, 0x7A, 0xD4, 0x87, - 0xC5, 0x43, 0x77, 0x1D, 0xC6, 0x76, 0xD4, 0xB6, - 0x5A, 0x4B, 0x3F, 0x91, 0x55, 0x98, 0xC2, 0xCE, - 0x8C, 0x5B, 0xED, 0x53, 0x99, 0x20, 0x6D, 0xA6, - 0xF1, 0x96, 0x21, 0x41, 0xBB, 0x16, 0x86, 0x46, - 0xC6, 0x1D, 0x9D, 0xB0, 0x68, 0x69, 0x3D, 0xFE, - 0xC6, 0x16, 0x2C, 0x2B, 0x51, 0x40, 0x40, 0x2A, - 0x01, 0xBF, 0xB3, 0xFF, 0x8A, 0x38, 0x3D, 0x51, - 0xF4, 0x32, 0x74, 0x18, 0xC0, 0x70, 0x26, 0xA7, - 0x27, 0x5D, 0xDE, 0xB1, 0xD8, 0x5E, 0x3D, 0x30, - 0xB2, 0x0C, 0xEC, 0xA5, 0xCC, 0x44, 0x27, 0xC7, - 0x6D, 0x16, 0x01, 0x5A, 0x81, 0xFC, 0x9E, 0x3B, - 0xEE, 0x10, 0x17, 0x41, 0x9A, 0x0A, 0x50, 0x30, - 0x72, 0x6A, 0xCC, 0x01, 0xE0, 0x53, 0x3F, 0xFD, - 0x54, 0x8C, 0x13, 0x6C, 0x9D, 0x0E, 0x47, 0xB4, - 0xD1, 0x59, 0xCA, 0x17, 0xF3, 0x40, 0x10, 0xEA, - 0xCA, 0xD3, 0xA6, 0xDA, 0xA3, 0x28, 0x4B, 0x6E, - 0xBC, 0x42, 0xF8, 0x9D, 0x75, 0xFF, 0x3F, 0xCD, - 0x8E, 0x45, 0xE8, 0x1D, 0xEC, 0x5F, 0x74, 0x87, - 0x61, 0x23, 0x63, 0xA2, 0x79, 0x7B, 0xBB, 0xDE, - 0x72, 0xE5, 0xB6, 0x7B, 0x8B, 0x9A, 0xC7, 0x04, - 0x35, 0xD0, 0x65, 0xCB, 0xD0, 0x44, 0x41, 0xD1, - 0x74, 0x1E, 0xE8, 0x87, 0x6F, 0xE5, 0x25, 0x44, - 0xFB, 0x23, 0xA7, 0x08, 0xF4, 0x89, 0xEA, 0xCF, - 0x1E, 0xE0, 0xE7, 0xC9, 0x12, 0x92, 0xC8, 0xA8, - 0x89, 0x13, 0xA6, 0x07, 0xDC, 0xC9, 0xFA, 0x1F, - 0x2E, 0xB1, 0x04, 0x58, 0xBA, 0xAA, 0x6B, 0xE8, - 0x6B, 0x7D, 0xC8, 0x01, 0x8B, 0x1E, 0xCF, 0x49, - 0xCA, 0x21, 0xAD, 0x61, 0x18, 0xED, 0x8E, 0x83, - 0x00, 0x3E, 0xD9, 0x90, 0x78, 0xE2, 0x22, 0xFF, - 0x8F, 0x54, 0xD4, 0xF9, 0x21, 0x10, 0x37, 0xF4, - 0xFC, 0x2F, 0x15, 0x31, 0x48, 0xB0, 0xD3, 0x36, - 0xC1, 0x32, 0x99, 0x05, 0xDD, 0x6D, 0x3B, 0xBA, - 0x3A, 0x60, 0x91, 0xFE, 0xAE, 0x16, 0xFA, 0x72, - 0x53, 0xC0, 0x75, 0xFC, 0x51, 0xC9, 0x0C, 0x38, - 0x99, 0x5F, 0x19, 0x75, 0xAD, 0x1D, 0x4B, 0xCA, - 0x4A, 0x3C, 0x88, 0x01, 0x40, 0xD2, 0x33, 0xB4, - 0x37, 0x64, 0xDA, 0x3A, 0xAA, 0xBB, 0x93, 0x50, - 0xF5, 0x5A, 0xC4, 0xB5, 0x9D, 0x2D, 0x7B, 0xFA, - 0x7A, 0x84, 0x17, 0x7B, 0x22, 0xD8, 0xBB, 0xEA, - 0x58, 0x80, 0x97, 0xB2, 0x69, 0x70, 0x49, 0x00, - 0x89, 0x4F, 0x09, 0x65, 0xBD, 0x0D, 0x5B, 0xDA, - 0x5A, 0xB0, 0x32, 0x5D, 0x89, 0x1E, 0x46, 0x85, - 0x54, 0xC4, 0x71, 0x8F, 0x54, 0xEC, 0xEE, 0x8F, - 0x7F, 0xAF, 0x90, 0xEA, 0x7A, 0xCC, 0x7D, 0xF1, - 0x72, 0xA5, 0x79, 0x19, 0xC6, 0xF4, 0x5D, 0x61, - 0xF7, 0x24, 0x98, 0xD2, 0x53, 0xEB, 0x26, 0xE4, - 0x01, 0x67, 0xF7, 0xB6, 0x64, 0xC9, 0x59, 0xF3, - 0x30, 0x59, 0xFC, 0x9B, 0xD1, 0x65, 0x05, 0xD3, - 0x68, 0xB8, 0x68, 0x7D, 0xB5, 0xC7, 0xB3, 0x8F, - 0x59, 0x2E, 0x92, 0x5C, 0xC7, 0x7F, 0x3D, 0xFE, - 0x73, 0x88, 0x1F, 0x77, 0xB2, 0xF2, 0x9E, 0x55, - 0x57, 0x8F, 0x34, 0x9A, 0x61, 0x0C, 0x7B, 0xD3, - 0x5C, 0x15, 0xAE, 0xC2, 0x16, 0xB4, 0xC2, 0x2B, - 0xA5, 0x75, 0x6A, 0xA4, 0x31, 0x81, 0xA7, 0x67, - 0xE7, 0x30, 0x84, 0x28, 0xD0, 0x60, 0xA2, 0x71, - 0xF9, 0xE0, 0x33, 0xFF, 0xAB, 0x01, 0x04, 0x22, - 0x84, 0x42, 0x04, 0x02, 0x99, 0xFB, 0x9F, 0x5F, - 0xB9, 0x7F, 0xF5, 0x21, 0xDB, 0xC6, 0xA5, 0x00, - 0x60, 0x9D, 0x8B, 0x07, 0xAB, 0x7D, 0x03, 0xE2, - 0xD3, 0x45, 0xF0, 0x6E, 0xBD, 0x0D, 0x4B, 0xA4, - 0x23, 0x8A, 0x77, 0x1B, 0xCF, 0x75, 0x30, 0x96, - 0x33, 0xE4, 0x6A, 0x94, 0x6F, 0x01, 0xA1, 0x41, - 0xC1, 0x88, 0x5B, 0x97, 0xCD, 0x3E, 0x56, 0xD0, - 0x53, 0x88, 0x9C, 0xE3, 0x3C, 0x00, 0x1A, 0xA8, - 0x6C, 0xB7, 0xA3, 0xDC, 0x03, 0x96, 0x14, 0xF2, - 0x7E, 0xB7, 0x1C, 0x80, 0xEA, 0x49, 0x21, 0x8B, - 0x48, 0x85, 0xF8, 0x93, 0x89, 0x3D, 0x5D, 0x5F, - 0x13, 0x33, 0x93, 0xC3, 0x1C, 0x4E, 0x2D, 0xE0, - 0xE2, 0x1D, 0x2A, 0x51, 0xE7, 0x07, 0xF5, 0x38, - 0xB8, 0x75, 0x4A, 0x2A, 0xFE, 0x5C, 0x37, 0x0E, - 0x7C, 0xEA, 0x5C, 0xB6, 0x7E, 0xCE, 0x2C, 0x25, - 0x5C, 0xD1, 0xFF, 0x66, 0x06, 0x94, 0x59, 0x9A, - 0x7F, 0x7D, 0xED, 0x21, 0x69, 0xAD, 0xC6, 0x9F, - 0x49, 0x7B, 0xC7, 0xA7, 0x74, 0xC8, 0xE4, 0xC6, - 0x65, 0x63, 0x07, 0xC9, 0x65, 0x0F, 0xBC, 0xBC, - 0x1C, 0xC7, 0xD3, 0xAC, 0x7C, 0x2E, 0x2B, 0x4B, - 0xB9, 0x3F, 0xF7, 0x59, 0xC2, 0x7A, 0x0C, 0x86, - 0xF4, 0x23, 0xFB, 0x75, 0xE9, 0x59, 0x9B, 0x48, - 0xC0, 0x7E, 0x13, 0x59, 0x07, 0x72, 0xED, 0x00, - 0x87, 0x50, 0xE9, 0x45, 0xBD, 0x0D, 0xCF, 0x1C, - 0x94, 0xCD, 0x1E, 0xD2, 0x1C, 0x36, 0xA5, 0x80, - 0xD9, 0x24, 0x8F, 0x13, 0xC7, 0x75, 0x53, 0x5B, - 0x24, 0x47, 0xD3, 0x12, 0xC9, 0x5C, 0xE8, 0x0E, - 0x2E, 0x65, 0xA7, 0xAD, 0x6C, 0xFB, 0x97, 0x5C, - 0x0E, 0xF6, 0x9D, 0x33, 0x49, 0x8D, 0x27, 0x24, - 0x64, 0x9F, 0x29, 0x97, 0x2A, 0x3A, 0xF8, 0x2B, - 0xA3, 0x0A, 0xE0, 0xF2, 0x96, 0x7C, 0x76, 0x55, - 0xD9, 0x6F, 0x0B, 0x29, 0xF1, 0xE3, 0x90, 0x58, - 0xBD, 0xB0, 0x20, 0xCA, 0x1B, 0xAB, 0xC7, 0x78, - 0xF4, 0x7B, 0x8F, 0xA0, 0x70, 0xAA, 0x89, 0xBB, - 0x7F, 0xA4, 0xA0, 0xDF, 0x0C, 0x20, 0x0B, 0x79, - 0xAD, 0x8A, 0x30, 0xA6, 0x72, 0x4A, 0xA8, 0x2C, - 0xAC, 0x12, 0x70, 0x3A, 0x70, 0xD4, 0x48, 0x1A, - 0x53, 0x79, 0x5D, 0x65, 0x41, 0xD3, 0xB0, 0x7D, - 0xDD, 0x27, 0x95, 0xE4, 0xCC, 0x51, 0x36, 0x70, - 0x2F, 0x0B, 0x1F, 0x67, 0x43, 0xE5, 0x5F, 0x77, - 0xFB, 0xA8, 0x9C, 0xB4, 0x6C, 0x6A, 0xB0, 0x60, - 0xEC, 0xCD, 0xDE, 0x63, 0x9D, 0x0F, 0x7B, 0x47, - 0xE5, 0xFC, 0xBB, 0xF5, 0x79, 0x35, 0x53, 0x0E, - 0x71, 0x4F, 0x29, 0x63, 0x96, 0x21, 0x07, 0x3B, - 0x44, 0x9F, 0x1F, 0x32, 0xEA, 0x0B, 0x5F, 0x9C, - 0x44, 0x9A, 0x6E, 0xA2, 0x8A, 0x70, 0x55, 0xA7, - 0x23, 0x78, 0xE8, 0xA7, 0x4E, 0xD8, 0xFB, 0x08, - 0xE9, 0x79, 0xCC, 0xD1, 0x45, 0xF6, 0x9A, 0xF2, - 0x54, 0xEC, 0x75, 0x7F, 0x24, 0x8A, 0xE6, 0x55, - 0x47, 0xB9, 0xD1, 0x7D, 0x85, 0x35, 0xC7, 0x61, - 0x41, 0xA8, 0x5A, 0xB6, 0xDC, 0x69, 0x04, 0x66, - 0xE1, 0x3A, 0x3C, 0xE1, 0x3D, 0x3D, 0xF5, 0xA6, - 0x84, 0x18, 0xAE, 0xDF, 0xF7, 0x5A, 0xCA, 0x06, - 0x95, 0x08, 0xBE, 0xD2, 0x06, 0x85, 0xD7, 0x53, - 0x53, 0x95, 0xD3, 0xB3, 0x38, 0x4A, 0x0F, 0x11, - 0x51, 0xAA, 0x1C, 0xB2, 0x0C, 0x1C, 0xBA, 0x89, - 0xF6, 0x2D, 0xAD, 0x80, 0x58, 0xD9, 0xF7, 0x34, - 0x95, 0x01, 0xB4, 0xF1, 0x3A, 0x97, 0x07, 0xC7, - 0x47, 0x9C, 0x1C, 0x31, 0xE9, 0xC8, 0x9C, 0x5F, - 0x47, 0x95, 0xAF, 0x6A, 0x10, 0x89, 0x34, 0x54, - 0x74, 0xBB, 0x2B, 0x7D, 0xA7, 0xF2, 0xD0, 0x31, - 0xAC, 0x87, 0x07, 0x2A, 0xF2, 0xE3, 0xD2, 0x11, - 0xB0, 0x21, 0x94, 0xC9, 0x23, 0x90, 0x61, 0xF1, - 0x72, 0x28, 0xCC, 0xA3, 0xF2, 0x6B, 0x22, 0xE1, - 0xC8, 0x4A, 0xE1, 0x7D, 0xA5, 0x15, 0x43, 0xC2, - 0x42, 0xB8, 0x5D, 0x32, 0x62, 0xF0, 0x57, 0xFF, - 0x62, 0x18, 0xFA, 0x95, 0x28, 0xD1, 0x99, 0xC8, - 0x1D, 0xC5, 0xB2, 0x88, 0x53, 0x52, 0x65, 0xA6, - 0x8E, 0x77, 0x79, 0x1E, 0x06, 0x1C, 0x6C, 0x3C, - 0x26, 0xED, 0xEB, 0x1D, 0x56, 0x7F, 0x3D, 0x58, - 0x11, 0xEF, 0x44, 0xD8, 0x00, 0xB0, 0xE6, 0x67, - 0xE7, 0x9D, 0x7F, 0x10, 0x2D, 0xDF, 0x97, 0xB6, - 0x6E, 0xB6, 0x41, 0x1F, 0xC4, 0x45, 0x76, 0xB5, - 0x39, 0xEE, 0x80, 0xCF, 0xE6, 0x01, 0x62, 0x15, - 0xF8, 0x01, 0x0A, 0x69, 0x79, 0xCD, 0x64, 0xAB, - 0x86, 0x5F, 0x68, 0x5D, 0x86, 0xD6, 0x2B, 0xCB, - 0xD2, 0x2A, 0x15, 0x7D, 0xC0, 0x38, 0x58, 0x29, - 0xF3, 0x2B, 0x35, 0x7A, 0xAE, 0x1C, 0xCC, 0xA6, - 0x06, 0x74, 0xE1, 0x90, 0xB8, 0x04, 0x6F, 0x69, - 0x1F, 0x3B, 0xBB, 0x96, 0x4E, 0xE2, 0x4A, 0x0D, - 0x1F, 0xC0, 0x57, 0x60, 0xBB, 0x16, 0x86, 0xEB, - 0x69, 0x97, 0xE3, 0xAA, 0x5F, 0xE5, 0x98, 0xA8, - 0x28, 0xF3, 0x73, 0x5E, 0x86, 0x47, 0x60, 0xA3, - 0xFF, 0x70, 0x4E, 0x25, 0x71, 0x89, 0x4C, 0x92, - 0x12, 0x8F, 0x38, 0x54, 0x2D, 0xD5, 0xB6, 0x53, - 0xEF, 0x1C, 0x02, 0x69, 0xBD, 0x04, 0xF6, 0x7C, - 0x64, 0x0D, 0x1B, 0x04, 0x96, 0x45, 0xE7, 0x87, - 0x73, 0xCF, 0x45, 0x3A, 0x5F, 0xED, 0x25, 0xE2, - 0xAF, 0x77, 0x8B, 0x4D, 0x37, 0x4D, 0x09, 0x6C, - 0xA9, 0x5A, 0x5E, 0x92, 0x39, 0x4F, 0x2A, 0xEA, - 0x2D, 0xCD, 0x6F, 0xBE, 0x64, 0x7C, 0x1B, 0x19, - 0x39, 0x96, 0x60, 0xC0, 0xD8, 0x22, 0xE8, 0x8A, - 0xC0, 0x3F, 0x6C, 0x43, 0xB3, 0xB1, 0x71, 0xC2, - 0xFE, 0x70, 0xA1, 0xF6, 0x26, 0x34, 0xF0, 0x35, - 0x50, 0x5A, 0xC8, 0xE2, 0x3D, 0x8D, 0x5F, 0x3F, - 0xCB, 0x77, 0x7A, 0x1E, 0x64, 0x70, 0x16, 0x33, - 0x63, 0x9C, 0xAC, 0xC3, 0x1B, 0xA7, 0xCD, 0xD5, - 0x52, 0x85, 0x2F, 0x81, 0x14, 0x3C, 0xB9, 0xB6, - 0x12, 0xEC, 0x5E, 0x32, 0x02, 0xB5, 0x37, 0xF9, - 0xE1, 0xF6, 0x0E, 0xC3, 0x53, 0xE0, 0x25, 0xDD, - 0x75, 0xB3, 0xF5, 0x99, 0x41, 0xF1, 0xA7, 0x26, - 0xA6, 0x4C, 0xBD, 0xD2, 0x32, 0x81, 0xC0, 0x5C, - 0xDF, 0x2D, 0xE8, 0x0F, 0x54, 0x76, 0xD5, 0x01, - 0x18, 0xA0, 0x8F, 0xB0, 0xE1, 0x62, 0x8B, 0x68, - 0xCA, 0xD3, 0x99, 0xDC, 0x47, 0xEA, 0x7A, 0xBA, - 0x3A, 0xE1, 0x61, 0x4C, 0x94, 0xC1, 0xB2, 0x72, - 0xEF, 0xC4, 0x44, 0x69, 0xB1, 0x0D, 0x27, 0x42, - 0xE2, 0x1B, 0x8C, 0xA7, 0x7C, 0x41, 0x2B, 0x73, - 0xF1, 0x26, 0x8A, 0x64, 0xD5, 0x42, 0x87, 0x58, - 0xFA, 0x5D, 0x37, 0x27, 0x11, 0xAD, 0xE5, 0x9D, - 0x1F, 0xC8, 0x69, 0xA7, 0x14, 0x8C, 0x5D, 0xD6, - 0x55, 0x4E, 0xD8, 0xB4, 0xFE, 0x65, 0xAD, 0xAD, - 0x0D, 0xD6, 0x10, 0xE5, 0x1D, 0x3F, 0x34, 0x5C, - 0x1C, 0xE7, 0x51, 0xCF, 0x3C, 0x24, 0x84, 0x64, - 0xE4, 0xBF, 0xF6, 0xBA, 0x90, 0x4B, 0x83, 0x83, - 0x23, 0xF8, 0x9C, 0xDB, 0xA9, 0xD9, 0x99, 0x59, - 0x39, 0x3F, 0x99, 0x27, 0x94, 0x8E, 0x2E, 0xCE, - 0x4E, 0x37, 0xAA, 0x6C, 0x74, 0xE4, 0x84, 0x84, - 0xAE, 0x65, 0x71, 0x76, 0x04, 0x15, 0x28, 0xEB, - 0xCE, 0x00, 0x94, 0xF4, 0x2F, 0x27, 0x45, 0x89, - 0x0F, 0xD8, 0x2B, 0xA7, 0x3C, 0x9D, 0xF1, 0x38, - 0x88, 0xB0, 0xF6, 0x7A, 0x4C, 0xED, 0x3D, 0x0E, - 0x2E, 0x97, 0x4E, 0x08, 0xDC, 0x73, 0xDB, 0x19, - 0x09, 0x7B, 0x3D, 0x4A, 0x0B, 0x2B, 0xDB, 0x6F, - 0x05, 0x12, 0x6E, 0xC8, 0xC2, 0x7E, 0x37, 0x75, - 0xF9, 0x08, 0x0C, 0x6C, 0x91, 0xA1, 0x49, 0x98, - 0xA8, 0xC0, 0x37, 0xE9, 0x7D, 0xE8, 0x58, 0x10, - 0xB0, 0xB3, 0x07, 0xD6, 0x06, 0x36, 0xE9, 0xAA, - 0xC0, 0xC6, 0xC0, 0x54, 0xCD, 0x8F, 0xA3, 0x49, - 0x13, 0x62, 0x56, 0x30, 0xC0, 0xC2, 0xEE, 0x07, - 0x07, 0x58, 0xAF, 0x41, 0xD3, 0x4B, 0x4D, 0xC4, - 0xFE, 0xAD, 0x19, 0xD8, 0x03, 0x39, 0xCA, 0x80, - 0xB4, 0xDD, 0x40, 0x06, 0x54, 0x6A, 0xBA, 0xC1, - 0xB1, 0xD0, 0xEE, 0x00, 0xD0, 0x47, 0xA5, 0x2C, - 0x44, 0x17, 0xA3, 0xC3, 0x10, 0x20, 0x93, 0xC3, - 0xC9, 0xE6, 0xA2, 0xE1, 0x13, 0x29, 0xA7, 0x97, - 0xE8, 0xC3, 0x8F, 0x0D, 0x17, 0xA9, 0xE3, 0xC1, - 0x4F, 0xBD, 0x8B, 0x2B, 0xE2, 0xB2, 0x1E, 0xFE, - 0xBC, 0x3A, 0xE0, 0xE9, 0x20, 0x90, 0xFC, 0x35, - 0xBE, 0x30, 0x3E, 0x50, 0x93, 0x10, 0x40, 0xB0, - 0x44, 0xAF, 0xFA, 0x66, 0x04, 0x70, 0x62, 0xCE, - 0x60, 0x5B, 0xAE, 0xD3, 0x5D, 0x58, 0xCD, 0xAF, - 0xE4, 0x2B, 0x1C, 0x2E, 0xF5, 0xD7, 0x9C, 0x79, - 0x6B, 0xDB, 0x44, 0xE8, 0x10, 0xA0, 0x48, 0x80, - 0x89, 0xD9, 0xCA, 0xF1, 0x09, 0xA4, 0x34, 0xF4, - 0x74, 0xAF, 0x2F, 0x02, 0xDA, 0x4B, 0x6C, 0xAF, - 0x87, 0x5E, 0x4A, 0xEC, 0x20, 0xB5, 0x8D, 0x6D, - 0x45, 0x9C, 0xA1, 0x67, 0x9A, 0xB9, 0xFE, 0x32, - 0xF8, 0xC1, 0xD8, 0x34, 0x3D, 0xC6, 0xA5, 0xA5, - 0x05, 0xDE, 0xAA, 0xEB, 0x87, 0xF7, 0xB7, 0x77, - 0x4F, 0x96, 0xC0, 0x60, 0xA8, 0xDA, 0xD7, 0xA3, - 0x91, 0x61, 0xF0, 0xF9, 0x29, 0xBB, 0x63, 0xA1, - 0x2D, 0xEC, 0xE8, 0xAF, 0x5F, 0x0A, 0x6D, 0x8F, - 0x12, 0x39, 0xB9, 0x94, 0x4C, 0xAD, 0x86, 0x45, - 0x05, 0xFE, 0x48, 0x66, 0x9B, 0x9F, 0x3F, 0xDF, - 0x5F, 0xB4, 0x46, 0x3A, 0xA2, 0x50, 0x10, 0x92, - 0x77, 0x18, 0xB3, 0x2F, 0xF7, 0x47, 0x11, 0x90, - 0x10, 0xC7, 0x72, 0x6C, 0x14, 0xD4, 0xE5, 0x62, - 0xE1, 0x36, 0x96, 0x42, 0x9F, 0x1F, 0xBC, 0x8C, - 0xBC, 0xC4, 0xD2, 0x6C, 0x9E, 0x04, 0xD4, 0xD8, - 0xF8, 0xF3, 0x98, 0x04, 0x06, 0x7A, 0x98, 0x54, - 0xF0, 0xCB, 0x3E, 0x43, 0xFD, 0x55, 0x09, 0x2B, - 0x81, 0x74, 0x10, 0x56, 0xBC, 0x47, 0x94, 0xB3, - 0x3E, 0xF2, 0xE6, 0x86, 0x76, 0xC6, 0xBD, 0x3D, - 0xBD, 0xD0, 0xC7, 0xDB, 0xB8, 0x18, 0xD8, 0xB8, - 0x0C, 0x67, 0x7B, 0x37, 0x4F, 0x5F, 0x4B, 0xCD, - 0x4D, 0x96, 0x2C, 0x4A, 0x20, 0x3F, 0xDF, 0x3A, - 0x43, 0x67, 0x69, 0x00, 0x62, 0x06, 0x94, 0x79, - 0xD7, 0x00, 0xAA, 0x36, 0x01, 0xA0, 0x30, 0x3E, - 0x2D, 0x34, 0xEF, 0xAD, 0x6E, 0xED, 0xBD, 0x4D, - 0xB9, 0x04, 0xF1, 0x3D, 0x6E, 0x75, 0xB0, 0xF5, - 0x52, 0x24, 0x90, 0x7D, 0xFB, 0x48, 0xE8, 0x08, - 0x88, 0xDB, 0x65, 0x80, 0x6A, 0x7F, 0x56, 0xB6, - 0x2B, 0x00, 0x80, 0xAD, 0x75, 0x44, 0x63, 0xA0, - 0x00, 0xB9, 0xFF, 0x1B, 0xCB, 0x70, 0x53, 0x13, - 0xA1, 0xEA, 0xDC, 0xE2, 0x9A, 0x58, 0x1D, 0xF7, - 0xF7, 0x4A, 0x5C, 0x40, 0xEF, 0xAF, 0xB5, 0x53, - 0x85, 0xBA, 0x08, 0x46, 0x9C, 0x0A, 0x28, 0x7B, - 0x8B, 0xD0, 0x44, 0x29, 0xD1, 0x49, 0x18, 0x92, - 0x30, 0xEB, 0x7F, 0x02, 0xFA, 0x6A, 0x3B, 0xD9, - 0x0A, 0xA1, 0x55, 0x1C, 0xEE, 0x1E, 0x3A, 0x0A, - 0xC0, 0x5D, 0xA9, 0xC1, 0x3F, 0x2E, 0x11, 0xD2, - 0xD2, 0x4D, 0xFA, 0xD6, 0x46, 0xC7, 0x01, 0xD5, - 0x59, 0x24, 0x50, 0x2F, 0xEB, 0xA9, 0xD5, 0xED, - 0xEF, 0x67, 0xA1, 0x8B, 0x51, 0xE1, 0x67, 0xB5, - 0x33, 0xE4, 0x50, 0x30, 0xE1, 0xC3, 0xF0, 0x40, - 0x60, 0x19, 0x0F, 0xCB, 0x19, 0x0B, 0x0E, 0xFC, - 0x61, 0x4A, 0xDE, 0xB0, 0x4D, 0x7B, 0xF4, 0xCB, - 0x4B, 0x90, 0x10, 0x3D, 0xE5, 0x59, 0x3B, 0xF7, - 0x72, 0xE8, 0x19, 0x76, 0xA2, 0x51, 0xF9, 0x3D, - 0x7D, 0x74, 0x52, 0xAC, 0x69, 0xB5, 0xC3, 0x5A, - 0xDD, 0x0D, 0x32, 0xDE, 0x86, 0xC2, 0x20, 0xBD, - 0x51, 0xDC, 0xE2, 0x88, 0x90, 0xD2, 0x12, 0x30, - 0x9F, 0x6E, 0x64, 0x16, 0xE8, 0x46, 0x09, 0xEF, - 0x41, 0xB6, 0x66, 0x34, 0xBB, 0x59, 0x56, 0xBC, - 0x1C, 0x55, 0x13, 0xBF, 0xFE, 0xEE, 0x2C, 0xE5, - 0x4F, 0x26, 0x99, 0xDC, 0x84, 0x9E, 0xEF, 0x9F, - 0xB5, 0x4E, 0xF4, 0x93, 0xE9, 0x04, 0x08, 0xE2, - 0xCE, 0x87, 0x38, 0x73, 0x39, 0xC3, 0x4B, 0x26, - 0xA4, 0x5A, 0x1F, 0x8C, 0x12, 0xA9, 0xC9, 0x12, - 0x2C, 0xD7, 0xC3, 0x5F, 0x47, 0x5D, 0x9D, 0xEF, - 0x00, 0xF1, 0xF7, 0x20, 0x08, 0x02, 0xC8, 0xBA, - 0x30, 0xC1, 0x95, 0xF3, 0x02, 0x32, 0xE9, 0x38, - 0x58, 0x38, 0xAE, 0x70, 0xF5, 0x29, 0x63, 0x1F, - 0x3D, 0xEC, 0x7D, 0xB3, 0x20, 0x78, 0xB5, 0x77, - 0xFB, 0x2B, 0x78, 0xFB, 0xDC, 0xA4, 0xC0, 0x2A, - 0x76, 0x3F, 0x84, 0x00, 0x74, 0x0D, 0x66, 0x5F, - 0x2D, 0xBB, 0xE5, 0x41, 0x9D, 0x07, 0xBB, 0x99, - 0x14, 0x27, 0x4D, 0xEF, 0x9A, 0x28, 0x44, 0x9F, - 0x3F, 0x66, 0x20, 0x8C, 0xC6, 0xD6, 0x24, 0xCD, - 0x67, 0x7C, 0x42, 0x8E, 0xC6, 0xEF, 0x7F, 0x25, - 0x2D, 0x74, 0xCA, 0x81, 0xDB, 0x26, 0xAE, 0xCB, - 0xA7, 0x83, 0xFD, 0x95, 0x46, 0xC5, 0xBE, 0x5C, - 0xFC, 0x07, 0xC5, 0xFF, 0x34, 0x70, 0x82, 0x6E, - 0xC7, 0x90, 0xAF, 0xC8, 0x99, 0xAB, 0xA7, 0x4E, - 0x02, 0xC1, 0x92, 0x22, 0x05, 0xA8, 0x38, 0xF8, - 0x78, 0xA3, 0x23, 0x0E, 0xD6, 0x27, 0x27, 0xE4, - 0x55, 0xEF, 0x5A, 0xBE, 0x22, 0x1B, 0xF9, 0x00, - 0xC4, 0x02, 0x44, 0x28, 0xF0, 0x40, 0x16, 0x97, - 0x17, 0x6E, 0x1A, 0x66, 0x1B, 0x98, 0xD8, 0x89, - 0x69, 0xB1, 0x8F, 0x61, 0x30, 0xC9, 0xB4, 0x84, - 0x04, 0xDF, 0x5F, 0x72, 0xAA, 0xA7, 0xC5, 0x24, - 0xC6, 0x1E, 0x80, 0xEE, 0x3A, 0x06, 0xED, 0x8F, - 0xAA, 0x73, 0xED, 0x00, 0xBB, 0x08, 0xFA, 0xF8, - 0x68, 0x2A, 0xCE, 0x3B, 0xA1, 0x98, 0x9A, 0xD6, - 0x55, 0xB7, 0x93, 0xE2, 0xCA, 0x7A, 0x2C, 0xAD, - 0x2D, 0xC7, 0x13, 0x7C, 0x9C, 0x2F, 0xFD, 0x2E, - 0xB6, 0x61, 0xCB, 0xA0, 0x93, 0x39, 0xC8, 0x56, - 0xD5, 0xCE, 0xD3, 0x9F, 0xE5, 0x06, 0x7E, 0x7E, - 0xDE, 0x05, 0x2B, 0x4E, 0x14, 0xB7, 0xD1, 0xB3, - 0xF0, 0x3B, 0x17, 0xF3, 0xA2, 0x61, 0x64, 0x88, - 0x28, 0x41, 0xE4, 0x90, 0x5F, 0x04, 0x6A, 0x12, - 0x01, 0x56, 0x7B, 0x9F, 0x4C, 0x51, 0x33, 0x13, - 0x9B, 0x40, 0xDB, 0xBD, 0x78, 0x38, 0x54, 0x96, - 0x0B, 0x20, 0xA0, 0x8D, 0x55, 0xD4, 0xD6, 0x15, - 0xAD, 0x75, 0x71, 0x0F, 0xC3, 0xBB, 0x78, 0x10, - 0xB3, 0xA2, 0xAF, 0x7A, 0x01, 0x16, 0x4D, 0xDC, - 0xFC, 0xBC, 0xCA, 0x24, 0xEF, 0x47, 0xBE, 0xDD, - 0x4A, 0xF9, 0x64, 0xCA, 0xBA, 0xF5, 0x74, 0xD0, - 0x53, 0x70, 0x75, 0xD9, 0x21, 0x91, 0x23, 0xF0, - 0x68, 0x02, 0xFF, 0x90, 0xA8, 0xC5, 0xB5, 0x87, - 0x6C, 0x17, 0x73, 0x4C, 0x8C, 0xFC, 0xBC, 0x7C, - 0x5E, 0xAE, 0x98, 0x34, 0xCC, 0x7C, 0xDC, 0xB6, - 0x26, 0x5F, 0x82, 0x6E, 0xF0, 0x41, 0x21, 0x43, - 0x00, 0xCB, 0x58, 0x13, 0xEB, 0x9B, 0xDB, 0x1B, - 0x0A, 0x8F, 0x3A, 0xD4, 0x1F, 0xA9, 0x51, 0x98, - 0xBA, 0xA2, 0x04, 0xF2, 0xA2, 0x9B, 0x88, 0x2D, - 0x89, 0x72, 0x4C, 0xA3, 0xD6, 0x64, 0xE4, 0x2C, - 0xAC, 0x6A, 0x2C, 0x40, 0x98, 0x28, 0x7E, 0xFF, - 0x7F, 0xE6, 0xF8, 0x6B, 0x22, 0xF7, 0x94, 0xE5, - 0x07, 0xDF, 0x58, 0x7F, 0xA4, 0xAC, 0xC7, 0xC5, - 0x5E, 0x9D, 0x27, 0x66, 0x6E, 0x12, 0x52, 0x50, - 0x8B, 0x48, 0x3E, 0x72, 0xAA, 0xB8, 0xFB, 0x9B, - 0xB2, 0xD2, 0xA4, 0xE8, 0x30, 0x02, 0x41, 0x21, - 0x61, 0x9A, 0x2C, 0xD0, 0x80, 0x20, 0xD2, 0xB3, - 0x33, 0x78, 0x46, 0x0A, 0x50, 0x83, 0x43, 0x43, - 0xE3, 0x38, 0xAC, 0xE3, 0xBB, 0xCB, 0x8B, 0x4B, - 0x8B, 0x72, 0xD4, 0xFA, 0x86, 0x36, 0x16, 0xF4, - 0x54, 0xAD, 0x78, 0x94, 0x51, 0x11, 0x47, 0xC6, - 0x46, 0xFB, 0x79, 0x1D, 0x47, 0xF4, 0xB3, 0xB1, - 0x32, 0xCF, 0x1F, 0x4B, 0x99, 0x84, 0xE6, 0x9B, - 0x18, 0x0E, 0xBC, 0xF5, 0xB5, 0x27, 0x5A, 0x6A, - 0x42, 0xCA, 0xCE, 0x02, 0x21, 0x21, 0x8D, 0x5D, - 0x1F, 0x87, 0x17, 0xBB, 0x43, 0xF3, 0x01, 0xCB, - 0x47, 0x5C, 0xCA, 0xA6, 0xCE, 0xE7, 0x97, 0xC5, - 0x0F, 0xD8, 0x73, 0xEF, 0x37, 0x87, 0xFD, 0x3C, - 0xBC, 0x67, 0xD1, 0xBD, 0x65, 0xD5, 0x51, 0x9C, - 0x1E, 0xA5, 0x17, 0x7A, 0xA2, 0x12, 0x72, 0xB2, - 0x32, 0xE9, 0xEF, 0x8D, 0x57, 0x87, 0xCD, 0x0F, - 0x8F, 0x54, 0xE2, 0x8E, 0x56, 0xE6, 0x66, 0xB4, - 0x36, 0x8D, 0x27, 0x4B, 0x9B, 0x2B, 0x36, 0xF2, - 0x0C, 0xD3, 0xE1, 0x9F, 0x45, 0x95, 0x81, 0x52, - 0xD0, 0x6B, 0x45, 0x3A, 0xE0, 0x30, 0xF0, 0x23, - 0xA1, 0x1A, 0x74, 0x0C, 0xD6, 0x06, 0x7E, 0xAB, - 0x29, 0x92, 0x14, 0x6E, 0xB4, 0x64, 0x30, 0xE5, - 0x67, 0xDC, 0xD2, 0xAB, 0x71, 0xA1, 0xC1, 0x01, - 0x81, 0x5A, 0x1C, 0x8F, 0xA8, 0xE7, 0x87, 0x47, - 0xC7, 0x1C, 0x5A, 0xC9, 0xEE, 0xA1, 0xC1, 0x01, - 0x81, 0x5A, 0x1C, 0x8F, 0xA8, 0xE7, 0x87, 0x47, - 0xC7, 0x1C, 0x5A, 0xC9, 0xEE, 0xA1, 0xC1, 0x01, - 0x81, 0x5A, 0x1C, 0x8F, 0xA8, 0xE7, 0x87, 0x47, - 0xC7, 0x1C, 0x5A, 0xC9, 0xEE, 0xA1, 0xC1, 0x01, - 0x81, 0x5A, 0x1C, 0x8F, 0xA8, 0xE7, 0x87, 0x47, - 0xC7, 0x1C, 0x5A, 0xC9, 0xEE, 0xA1, 0xC1, 0x01, - 0x81, 0x5A, 0x1C, 0x8F, 0xA8, 0xE7, 0x97, 0x40, - 0xC2, 0x79, 0xEB, 0x90, 0x4A, 0x9A, 0xEE, 0x36, - 0xB4, 0x0F, 0x19, 0x62, 0xB8, 0x68, 0x08, 0xC8, - 0x48, 0x93, 0x25, 0x49, 0x91, 0x21, 0x41, 0x81, - 0x01, 0xDA, 0xA0, 0xD4, 0x0C, 0xDC, 0x6C, 0xB4, - 0x34, 0x8F, 0xC1, 0xB4, 0x6C, 0xBC, 0x30, 0xF0, - 0x70, 0xAB, 0x1D, 0x71, 0xA9, 0x19, 0x78, 0xB8, - 0x38, 0xE3, 0x54, 0x38, 0xE1, 0x51, 0x30, 0xF8, - 0x38, 0xE3, 0x54, 0x39, 0xE0, 0x51, 0x70, 0xA0, - 0x24, 0xFD, 0x6A, 0x02, 0xFB, 0x4F, 0x0E, 0x4A, - 0xDA, 0x43, 0xE4, 0x99, 0x50, 0xF1, 0xD8, 0x3A, - 0x9E, 0x67, 0x98, 0xE6, 0x77, 0xD5, 0xFC, 0x6E, - 0xD7, 0x1E, 0xFD, 0x80, 0x0D, 0xAC, 0x99, 0x4C, - 0x99, 0x53, 0x4F, 0x09, 0x7B, 0xE1, 0x2B, 0x41, - 0x6B, 0x9A, 0x79, 0x40, 0xCD, 0x28, 0x1D, 0x88, - 0x5D, 0x53, 0xB0, 0x09, 0x84, 0xE1, 0x2B, 0x01, - 0x2B, 0x1E, 0x02, 0x80, 0xF2, 0xAC, 0x7A, 0x17, - 0x21, 0x17, 0x17, 0x96, 0xF8, 0xA5, 0x73, 0x6E, - 0x35, 0x33, 0x6B, 0xE9, 0xDF, 0x81, 0x3F, 0x84, - 0xEB, 0x8D, 0xE5, 0x72, 0x74, 0x3F, 0xE1, 0xCE, - 0xB5, 0x93, 0xDB, 0x49, 0x6F, 0x21, 0xBF, 0x88, - 0xB7, 0x93, 0xDB, 0x48, 0x6E, 0x21, 0xBE, 0x81, - 0xFE, 0xDA, 0x58, 0x2D, 0xF5, 0x25, 0x7D, 0xA4, - 0x24, 0x9F, 0xD5, 0xA0, 0x78, 0xA8, 0xFC, 0x3C, - 0xBC, 0x67, 0xD1, 0xBD, 0x65, 0xD5, 0xB5, 0x75, - 0xF5, 0x2E, 0x98, 0xF4, 0x2C, 0x9C, 0xFC, 0x3C, - 0xBC, 0x67, 0xF9, 0x9C, 0x44, 0x94, 0xD0, 0x19, - 0x99, 0x22, 0x84, 0x58, 0x82, 0x32, 0x52, 0x88, - 0x08, 0xB3, 0x75, 0x18, 0xC0, 0x70, 0x6C, 0xAB, - 0x2B, 0x90, 0x9A, 0xFB, 0x21, 0xF1, 0xAD, 0x65, - 0xE5, 0x5E, 0xFC, 0x9E, 0x44, 0x94, 0x38, 0xF6, - 0x74, 0xCF, 0xED, 0x87, 0x5F, 0x8F, 0x4B, 0x84, - 0x06, 0xBD, 0x4F, 0x25, 0xFD, 0x2D, 0xC1, 0x0E, - 0x8C, 0x37, 0x71, 0x04, 0xDC, 0x0C, 0xB8, 0x77, - 0xF5, 0x4E, 0x48, 0x35, 0xEF, 0x3F, 0xE7, 0x2F, - 0xAF, 0x14, 0x82, 0xFC, 0x26, 0xF6, 0x2A, 0xED, - 0x6D, 0xD6, 0x34, 0x4A, 0x90, 0x40, 0xE8, 0x3A, - 0xB8, 0x03, 0x5D, 0x37, 0xEF, 0x3F, 0x3B, 0xE3, - 0x61, 0xDA, 0x2C, 0x4A, 0x92, 0x42, 0x14, 0x95, - 0x15, 0x4F, 0x7B, 0x11, 0x78, 0x48, 0x2E, 0xF2, - 0x78, 0x32, 0x05, 0x6F, 0x15, 0xEE, 0x8E, 0xC7, - 0x4E, 0xB0, 0x04, 0x68, 0x55, 0xE1, 0x81, 0xE4, - 0x66, 0xBD, 0xEE, 0x87, 0x5F, 0x0A, 0x62, 0xA2, - 0x07, 0xDF, 0x69, 0xA0, 0x71, 0xC1, 0x00, 0x43, - 0xC5, 0xAF, 0x9D, 0xF7, 0x8A, 0x60, 0x27, 0xFA, - 0x8A, 0x51, 0xD1, 0xFC, 0x24, 0xA5, 0x40, 0x86, - 0x27, 0x7A, 0xCA, 0x8F, 0x84, 0x29, 0xB9, 0x79, - 0xF9, 0x22, 0xA2, 0x8F, 0x57, 0xD6, 0x31, 0xF7, - 0x56, 0x05, 0xB5, 0xF0, 0x6B, 0xC6, 0x56, 0x96, - 0x16, 0xCD, 0x4D, 0x60, 0xB8, 0x39, 0xDC, 0x1A, - 0xBB, 0xE9, 0x59, 0x1C, 0x57, 0xFA, 0x6A, 0xAA, - 0x2A, 0xF1, 0x71, 0x5C, 0x84, 0x15, 0xF8, 0x3E, - 0x8F, 0xD8, 0x68, 0x95, 0xC7, 0x71, 0x90, 0xDB, - 0x5D, 0x0F, 0xF0, 0xB5, 0x6E, 0xC3, 0x53, 0x93, - 0x13, 0xC8, 0x48, 0x65, 0xBD, 0x9C, 0x72, 0xB4, - 0x38, 0xEB, 0xDF, 0xFA, 0x22, 0xF7, 0x96, 0x56, - 0x77, 0x3C, 0x8C, 0x51, 0x0E, 0xB8, 0x19, 0x56, - 0xD0, 0xC2, 0x7F, 0xBA, 0x39, 0x94, 0x04, 0xC4, - 0x44, 0x9F, 0x1F, 0x32, 0xEA, 0x6B, 0x9A, 0x5C, - 0xFD, 0xB4, 0x04, 0x41, 0x8A, 0x27, 0xB7, 0x77, - 0xF7, 0x2C, 0xAC, 0x81, 0x59, 0x68, 0x9C, 0x5A, - 0xEB, 0xA3, 0x13, 0x5E, 0x13, 0xA5, 0xEC, 0x0F, - 0x06, 0x8E, 0x25, 0xB9, 0x61, 0xD1, 0x87, 0x06, - 0x86, 0xCC, 0xEC, 0x86, 0xDF, 0xF8, 0x9E, 0xD7, - 0x7E, 0xC0, 0x76, 0x1A, 0xDF, 0x9F, 0xC9, 0x48, - 0xC8, 0xB2, 0x9C, 0xF6, 0x9C, 0x8C, 0x60, 0x08, - 0x82, 0x79, 0xAE, 0xC2, 0x92, 0x08, 0xD2, 0xA8, - 0xB4, 0x77, 0xCD, 0xBD, 0x69, 0x54, 0xD6, 0x3C, - 0x94, 0x8F, 0x19, 0x75, 0x7F, 0x81, 0xED, 0xEF, - 0x24, 0xD8, 0x4B, 0x80, 0x7B, 0xEB, 0x6D, 0xBE, - 0x2E, 0xD5, 0x63, 0x12, 0x3A, 0x8A, 0xEA, 0x2A, - 0xAA, 0x71, 0xC7, 0xAB, 0x73, 0xC3, 0xA3, 0x63, - 0xE3, 0x38, 0x8F, 0xE3, 0x3F, 0x8F, 0x8B, 0x51, - 0xD3, 0x68, + 0x06, 0x6B, 0x06, 0x6A, 0x76, 0xC8, 0x18, 0xD4, + 0x54, 0xEF, 0x71, 0x14, 0xCC, 0x1C, 0x58, 0x91, + 0x11, 0xAA, 0x80, 0xF4, 0x2C, 0xFC, 0x9F, 0x5F, + 0xDF, 0x04, 0x02, 0x62, 0xBA, 0x6A, 0x5A, 0x97, + 0x17, 0xCC, 0x46, 0x22, 0xFA, 0x2A, 0xBE, 0x03, + 0x87, 0x3C, 0x9E, 0xFE, 0x26, 0xF6, 0x96, 0x7E, + 0xFA, 0x11, 0x27, 0x66, 0xBA, 0x3A, 0x5A, 0xBA, + 0x3E, 0xD5, 0x4F, 0x03, 0xDF, 0x5F, 0x7F, 0x9F, + 0x1B, 0xF0, 0xA2, 0xEF, 0x33, 0xB3, 0xD3, 0x13, + 0x93, 0x70, 0xFA, 0x96, 0x4E, 0xC6, 0xA6, 0xC6, + 0x46, 0xA5, 0x2F, 0xE3, 0x3B, 0xB3, 0xD3, 0x33, + 0xB3, 0x50, 0xE8, 0xA4, 0x7C, 0xF4, 0x94, 0x14, + 0x94, 0x77, 0xC9, 0xE5, 0x3D, 0xB5, 0xD5, 0x75, + 0xF5, 0x16, 0xA8, 0xA4, 0x7C, 0xF4, 0x94, 0xD4, + 0x54, 0xB7, 0x09, 0xE5, 0x3D, 0xB5, 0x2D, 0xF4, + 0x74, 0xCF, 0x29, 0x5C, 0x84, 0x54, 0x14, 0xAA, + 0x2E, 0x95, 0xF7, 0xE0, 0x3C, 0xEC, 0x8C, 0x52, + 0xD6, 0x3D, 0x7B, 0x0E, 0xD6, 0x06, 0x82, 0x49, + 0xC9, 0x72, 0x7C, 0x18, 0xC0, 0x10, 0x10, 0xF6, + 0x72, 0xC9, 0xC3, 0xA8, 0x70, 0xA0, 0xD8, 0x77, + 0xF3, 0x48, 0x06, 0x04, 0xD8, 0x08, 0x90, 0x5B, + 0xDB, 0x60, 0x36, 0x43, 0x9B, 0x4B, 0xD4, 0xE3, + 0x9C, 0xB8, 0xF1, 0x72, 0x55, 0x1A, 0x8E, 0x57, + 0xD7, 0x6C, 0xDA, 0xBE, 0x66, 0xD6, 0xEA, 0x3D, + 0xBF, 0x04, 0xB2, 0xCE, 0x16, 0xA6, 0x06, 0xDE, + 0x5E, 0xE5, 0xB7, 0xC3, 0x1B, 0xCB, 0x47, 0x9F, + 0x1F, 0xA4, 0x3E, 0x5B, 0x83, 0x53, 0x53, 0x8A, + 0x0A, 0xB1, 0x93, 0xF9, 0x21, 0xF1, 0x31, 0xE6, + 0x64, 0xDF, 0x95, 0xE0, 0x38, 0xE8, 0xB4, 0x6D, + 0xED, 0x56, 0x1D, 0x8E, 0x56, 0xE6, 0x79, 0xB9, + 0xC6, 0xE2, 0x62, 0x4F, 0x97, 0x02, 0x40, 0x80, + 0x65, 0xB8, 0x0E, 0x07, 0xC2, 0x72, 0x37, 0xBE, + 0x3E, 0x00, 0xF2, 0xB8, 0xF1, 0x6D, 0x0E, 0x6F, + 0xC2, 0x1A, 0xA0, 0xC4, 0x95, 0x2F, 0xCD, 0x44, + 0xC4, 0x02, 0x44, 0x28, 0xF0, 0x40, 0x16, 0x97, + 0x17, 0x7D, 0xE4, 0x8B, 0xFE, 0x4C, 0x0D, 0xE3, + 0x60, 0xFD, 0x4B, 0x27, 0x34, 0xA6, 0xCD, 0xB6, + 0x10, 0xC0, 0x7C, 0x98, 0x42, 0x72, 0x92, 0x26, + 0x21, 0x60, 0x26, 0x4C, 0x95, 0x25, 0xA0, 0x03, + 0xA6, 0x50, 0xEC, 0x9D, 0xB5, 0x05, 0x53, 0xD2, + 0x52, 0xA9, 0x7E, 0x12, 0x2F, 0x65, 0xFA, 0x1A, + 0x7C, 0xB4, 0x12, 0x5E, 0x86, 0x3A, 0x50, 0xF5, + 0x53, 0xAD, 0xBA, 0xE6, 0x3D, 0x3C, 0x6D, 0xAE, + 0xCB, 0x33, 0xAD, 0xDC, 0xF4, 0x44, 0x12, 0x93, + 0x13, 0xF9, 0x7D, 0x12, 0xEB, 0x68, 0x0B, 0xE2, + 0x21, 0xE7, 0xA1, 0xCD, 0x15, 0xA5, 0xF3, 0x72, + 0xF2, 0xAB, 0x1F, 0x7E, 0xAA, 0x01, 0xE1, 0xA1, + 0x25, 0xA8, 0x06, 0x6D, 0xB9, 0x0C, 0x60, 0xA6, + 0x64, 0xAD, 0x15, 0x65, 0xBA, 0x30, 0x14, 0x66, + 0x22, 0x78, 0xFC, 0x94, 0x4C, 0x4E, 0x25, 0x9B, + 0xD9, 0x06, 0xB1, 0xEA, 0x89, 0x35, 0x62, 0x1E, + 0x8F, 0x69, 0xD4, 0x7F, 0x1C, 0xA0, 0xFD, 0x31, + 0x77, 0xAD, 0x1B, 0x40, 0xA4, 0x10, 0xB7, 0xCC, + 0x4D, 0xAB, 0x16, 0xD7, 0x0C, 0x01, 0x62, 0x87, + 0xBF, 0x4C, 0x50, 0x5A, 0xD8, 0x3B, 0x50, 0xE7, + 0x2C, 0xB3, 0xB7, 0x1F, 0x46, 0xA0, 0x57, 0x6B, + 0x46, 0x98, 0x93, 0xFA, 0xC7, 0xC1, 0x89, 0x45, + 0xDE, 0xD7, 0xC3, 0xC3, 0xBB, 0xCF, 0xEE, 0xEE, + 0xA8, 0xB3, 0xDF, 0x61, 0x4B, 0xE6, 0x04, 0x04, + 0x40, 0xDA, 0xAC, 0x43, 0xDA, 0x9A, 0x15, 0x25, + 0x45, 0x7D, 0xEA, 0x0C, 0x3A, 0x7A, 0xD4, 0x87, + 0xC5, 0x43, 0x77, 0x1D, 0xC6, 0x76, 0xD4, 0xB6, + 0x5A, 0x4B, 0x3F, 0x91, 0x55, 0x98, 0xC2, 0xCE, + 0x8C, 0x5B, 0xED, 0x53, 0x99, 0x20, 0x6D, 0xA6, + 0xF1, 0x96, 0x21, 0x41, 0xBB, 0x16, 0x86, 0x46, + 0xC6, 0x1D, 0x9D, 0xB0, 0x68, 0x69, 0x3D, 0xFE, + 0xC6, 0x16, 0x2C, 0x2B, 0x51, 0x40, 0x40, 0x2A, + 0x01, 0xBF, 0xB3, 0xFF, 0x8A, 0x38, 0x3D, 0x51, + 0xF4, 0x32, 0x74, 0x18, 0xC0, 0x70, 0x26, 0xA7, + 0x27, 0x5D, 0xDE, 0xB1, 0xD8, 0x5E, 0x3D, 0x30, + 0xB2, 0x0C, 0xEC, 0xA5, 0xCC, 0x44, 0x27, 0xC7, + 0x6D, 0x16, 0x01, 0x5A, 0x81, 0xFC, 0x9E, 0x3B, + 0xEE, 0x10, 0x17, 0x41, 0x9A, 0x0A, 0x50, 0x30, + 0x72, 0x6A, 0xCC, 0x01, 0xE0, 0x53, 0x3F, 0xFD, + 0x54, 0x8C, 0x13, 0x6C, 0x9D, 0x0E, 0x47, 0xB4, + 0xD1, 0x59, 0xCA, 0x17, 0xF3, 0x40, 0x10, 0xEA, + 0xCA, 0xD3, 0xA6, 0xDA, 0xA3, 0x28, 0x4B, 0x6E, + 0xBC, 0x42, 0xF8, 0x9D, 0x75, 0xFF, 0x3F, 0xCD, + 0x8E, 0x45, 0xE8, 0x1D, 0xEC, 0x5F, 0x74, 0x87, + 0x61, 0x23, 0x63, 0xA2, 0x79, 0x7B, 0xBB, 0xDE, + 0x72, 0xE5, 0xB6, 0x7B, 0x8B, 0x9A, 0xC7, 0x04, + 0x35, 0xD0, 0x65, 0xCB, 0xD0, 0x44, 0x41, 0xD1, + 0x74, 0x1E, 0xE8, 0x87, 0x6F, 0xE5, 0x25, 0x44, + 0xFB, 0x23, 0xA7, 0x08, 0xF4, 0x89, 0xEA, 0xCF, + 0x1E, 0xE0, 0xE7, 0xC9, 0x12, 0x92, 0xC8, 0xA8, + 0x89, 0x13, 0xA6, 0x07, 0xDC, 0xC9, 0xFA, 0x1F, + 0x2E, 0xB1, 0x04, 0x58, 0xBA, 0xAA, 0x6B, 0xE8, + 0x6B, 0x7D, 0xC8, 0x01, 0x8B, 0x1E, 0xCF, 0x49, + 0xCA, 0x21, 0xAD, 0x61, 0x18, 0xED, 0x8E, 0x83, + 0x00, 0x3E, 0xD9, 0x90, 0x78, 0xE2, 0x22, 0xFF, + 0x8F, 0x54, 0xD4, 0xF9, 0x21, 0x10, 0x37, 0xF4, + 0xFC, 0x2F, 0x15, 0x31, 0x48, 0xB0, 0xD3, 0x36, + 0xC1, 0x32, 0x99, 0x05, 0xDD, 0x6D, 0x3B, 0xBA, + 0x3A, 0x60, 0x91, 0xFE, 0xAE, 0x16, 0xFA, 0x72, + 0x53, 0xC0, 0x75, 0xFC, 0x51, 0xC9, 0x0C, 0x38, + 0x99, 0x5F, 0x19, 0x75, 0xAD, 0x1D, 0x4B, 0xCA, + 0x4A, 0x3C, 0x88, 0x01, 0x40, 0xD2, 0x33, 0xB4, + 0x37, 0x64, 0xDA, 0x3A, 0xAA, 0xBB, 0x93, 0x50, + 0xF5, 0x5A, 0xC4, 0xB5, 0x9D, 0x2D, 0x7B, 0xFA, + 0x7A, 0x84, 0x17, 0x7B, 0x22, 0xD8, 0xBB, 0xEA, + 0x58, 0x80, 0x97, 0xB2, 0x69, 0x70, 0x49, 0x00, + 0x89, 0x4F, 0x09, 0x65, 0xBD, 0x0D, 0x5B, 0xDA, + 0x5A, 0xB0, 0x32, 0x5D, 0x89, 0x1E, 0x46, 0x85, + 0x54, 0xC4, 0x71, 0x8F, 0x54, 0xEC, 0xEE, 0x8F, + 0x7F, 0xAF, 0x90, 0xEA, 0x7A, 0xCC, 0x7D, 0xF1, + 0x72, 0xA5, 0x79, 0x19, 0xC6, 0xF4, 0x5D, 0x61, + 0xF7, 0x24, 0x98, 0xD2, 0x53, 0xEB, 0x26, 0xE4, + 0x01, 0x67, 0xF7, 0xB6, 0x64, 0xC9, 0x59, 0xF3, + 0x30, 0x59, 0xFC, 0x9B, 0xD1, 0x65, 0x05, 0xD3, + 0x68, 0xB8, 0x68, 0x7D, 0xB5, 0xC7, 0xB3, 0x8F, + 0x59, 0x2E, 0x92, 0x5C, 0xC7, 0x7F, 0x3D, 0xFE, + 0x73, 0x88, 0x1F, 0x77, 0xB2, 0xF2, 0x9E, 0x55, + 0x57, 0x8F, 0x34, 0x9A, 0x61, 0x0C, 0x7B, 0xD3, + 0x5C, 0x15, 0xAE, 0xC2, 0x16, 0xB4, 0xC2, 0x2B, + 0xA5, 0x75, 0x6A, 0xA4, 0x31, 0x81, 0xA7, 0x67, + 0xE7, 0x30, 0x84, 0x28, 0xD0, 0x60, 0xA2, 0x71, + 0xF9, 0xE0, 0x33, 0xFF, 0xAB, 0x01, 0x04, 0x22, + 0x84, 0x42, 0x04, 0x02, 0x99, 0xFB, 0x9F, 0x5F, + 0xB9, 0x7F, 0xF5, 0x21, 0xDB, 0xC6, 0xA5, 0x00, + 0x60, 0x9D, 0x8B, 0x07, 0xAB, 0x7D, 0x03, 0xE2, + 0xD3, 0x45, 0xF0, 0x6E, 0xBD, 0x0D, 0x4B, 0xA4, + 0x23, 0x8A, 0x77, 0x1B, 0xCF, 0x75, 0x30, 0x96, + 0x33, 0xE4, 0x6A, 0x94, 0x6F, 0x01, 0xA1, 0x41, + 0xC1, 0x88, 0x5B, 0x97, 0xCD, 0x3E, 0x56, 0xD0, + 0x53, 0x88, 0x9C, 0xE3, 0x3C, 0x00, 0x1A, 0xA8, + 0x6C, 0xB7, 0xA3, 0xDC, 0x03, 0x96, 0x14, 0xF2, + 0x7E, 0xB7, 0x1C, 0x80, 0xEA, 0x49, 0x21, 0x8B, + 0x48, 0x85, 0xF8, 0x93, 0x89, 0x3D, 0x5D, 0x5F, + 0x13, 0x33, 0x93, 0xC3, 0x1C, 0x4E, 0x2D, 0xE0, + 0xE2, 0x1D, 0x2A, 0x51, 0xE7, 0x07, 0xF5, 0x38, + 0xB8, 0x75, 0x4A, 0x2A, 0xFE, 0x5C, 0x37, 0x0E, + 0x7C, 0xEA, 0x5C, 0xB6, 0x7E, 0xCE, 0x2C, 0x25, + 0x5C, 0xD1, 0xFF, 0x66, 0x06, 0x94, 0x59, 0x9A, + 0x7F, 0x7D, 0xED, 0x21, 0x69, 0xAD, 0xC6, 0x9F, + 0x49, 0x7B, 0xC7, 0xA7, 0x74, 0xC8, 0xE4, 0xC6, + 0x65, 0x63, 0x07, 0xC9, 0x65, 0x0F, 0xBC, 0xBC, + 0x1C, 0xC7, 0xD3, 0xAC, 0x7C, 0x2E, 0x2B, 0x4B, + 0xB9, 0x3F, 0xF7, 0x59, 0xC2, 0x7A, 0x0C, 0x86, + 0xF4, 0x23, 0xFB, 0x75, 0xE9, 0x59, 0x9B, 0x48, + 0xC0, 0x7E, 0x13, 0x59, 0x07, 0x72, 0xED, 0x00, + 0x87, 0x50, 0xE9, 0x45, 0xBD, 0x0D, 0xCF, 0x1C, + 0x94, 0xCD, 0x1E, 0xD2, 0x1C, 0x36, 0xA5, 0x80, + 0xD9, 0x24, 0x8F, 0x13, 0xC7, 0x75, 0x53, 0x5B, + 0x24, 0x47, 0xD3, 0x12, 0xC9, 0x5C, 0xE8, 0x0E, + 0x2E, 0x65, 0xA7, 0xAD, 0x6C, 0xFB, 0x97, 0x5C, + 0x0E, 0xF6, 0x9D, 0x33, 0x49, 0x8D, 0x27, 0x24, + 0x64, 0x9F, 0x29, 0x97, 0x2A, 0x3A, 0xF8, 0x2B, + 0xA3, 0x0A, 0xE0, 0xF2, 0x96, 0x7C, 0x76, 0x55, + 0xD9, 0x6F, 0x0B, 0x29, 0xF1, 0xE3, 0x90, 0x58, + 0xBD, 0xB0, 0x20, 0xCA, 0x1B, 0xAB, 0xC7, 0x78, + 0xF4, 0x7B, 0x8F, 0xA0, 0x70, 0xAA, 0x89, 0xBB, + 0x7F, 0xA4, 0xA0, 0xDF, 0x0C, 0x20, 0x0B, 0x79, + 0xAD, 0x8A, 0x30, 0xA6, 0x72, 0x4A, 0xA8, 0x2C, + 0xAC, 0x12, 0x70, 0x3A, 0x70, 0xD4, 0x48, 0x1A, + 0x53, 0x79, 0x5D, 0x65, 0x41, 0xD3, 0xB0, 0x7D, + 0xDD, 0x27, 0x95, 0xE4, 0xCC, 0x51, 0x36, 0x70, + 0x2F, 0x0B, 0x1F, 0x67, 0x43, 0xE5, 0x5F, 0x77, + 0xFB, 0xA8, 0x9C, 0xB4, 0x6C, 0x6A, 0xB0, 0x60, + 0xEC, 0xCD, 0xDE, 0x63, 0x9D, 0x0F, 0x7B, 0x47, + 0xE5, 0xFC, 0xBB, 0xF5, 0x79, 0x35, 0x53, 0x0E, + 0x71, 0x4F, 0x29, 0x63, 0x96, 0x21, 0x07, 0x3B, + 0x44, 0x9F, 0x1F, 0x32, 0xEA, 0x0B, 0x5F, 0x9C, + 0x44, 0x9A, 0x6E, 0xA2, 0x8A, 0x70, 0x55, 0xA7, + 0x23, 0x78, 0xE8, 0xA7, 0x4E, 0xD8, 0xFB, 0x08, + 0xE9, 0x79, 0xCC, 0xD1, 0x45, 0xF6, 0x9A, 0xF2, + 0x54, 0xEC, 0x75, 0x7F, 0x24, 0x8A, 0xE6, 0x55, + 0x47, 0xB9, 0xD1, 0x7D, 0x85, 0x35, 0xC7, 0x61, + 0x41, 0xA8, 0x5A, 0xB6, 0xDC, 0x69, 0x04, 0x66, + 0xE1, 0x3A, 0x3C, 0xE1, 0x3D, 0x3D, 0xF5, 0xA6, + 0x84, 0x18, 0xAE, 0xDF, 0xF7, 0x5A, 0xCA, 0x06, + 0x95, 0x08, 0xBE, 0xD2, 0x06, 0x85, 0xD7, 0x53, + 0x53, 0x95, 0xD3, 0xB3, 0x38, 0x4A, 0x0F, 0x11, + 0x51, 0xAA, 0x1C, 0xB2, 0x0C, 0x1C, 0xBA, 0x89, + 0xF6, 0x2D, 0xAD, 0x80, 0x58, 0xD9, 0xF7, 0x34, + 0x95, 0x01, 0xB4, 0xF1, 0x3A, 0x97, 0x07, 0xC7, + 0x47, 0x9C, 0x1C, 0x31, 0xE9, 0xC8, 0x9C, 0x5F, + 0x47, 0x95, 0xAF, 0x6A, 0x10, 0x89, 0x34, 0x54, + 0x74, 0xBB, 0x2B, 0x7D, 0xA7, 0xF2, 0xD0, 0x31, + 0xAC, 0x87, 0x07, 0x2A, 0xF2, 0xE3, 0xD2, 0x11, + 0xB0, 0x21, 0x94, 0xC9, 0x23, 0x90, 0x61, 0xF1, + 0x72, 0x28, 0xCC, 0xA3, 0xF2, 0x6B, 0x22, 0xE1, + 0xC8, 0x4A, 0xE1, 0x7D, 0xA5, 0x15, 0x43, 0xC2, + 0x42, 0xB8, 0x5D, 0x32, 0x62, 0xF0, 0x57, 0xFF, + 0x62, 0x18, 0xFA, 0x95, 0x28, 0xD1, 0x99, 0xC8, + 0x1D, 0xC5, 0xB2, 0x88, 0x53, 0x52, 0x65, 0xA6, + 0x8E, 0x77, 0x79, 0x1E, 0x06, 0x1C, 0x6C, 0x3C, + 0x26, 0xED, 0xEB, 0x1D, 0x56, 0x7F, 0x3D, 0x58, + 0x11, 0xEF, 0x44, 0xD8, 0x00, 0xB0, 0xE6, 0x67, + 0xE7, 0x9D, 0x7F, 0x10, 0x2D, 0xDF, 0x97, 0xB6, + 0x6E, 0xB6, 0x41, 0x1F, 0xC4, 0x45, 0x76, 0xB5, + 0x39, 0xEE, 0x80, 0xCF, 0xE6, 0x01, 0x62, 0x15, + 0xF8, 0x01, 0x0A, 0x69, 0x79, 0xCD, 0x64, 0xAB, + 0x86, 0x5F, 0x68, 0x5D, 0x86, 0xD6, 0x2B, 0xCB, + 0xD2, 0x2A, 0x15, 0x7D, 0xC0, 0x38, 0x58, 0x29, + 0xF3, 0x2B, 0x35, 0x7A, 0xAE, 0x1C, 0xCC, 0xA6, + 0x06, 0x74, 0xE1, 0x90, 0xB8, 0x04, 0x6F, 0x69, + 0x1F, 0x3B, 0xBB, 0x96, 0x4E, 0xE2, 0x4A, 0x0D, + 0x1F, 0xC0, 0x57, 0x60, 0xBB, 0x16, 0x86, 0xEB, + 0x69, 0x97, 0xE3, 0xAA, 0x5F, 0xE5, 0x98, 0xA8, + 0x28, 0xF3, 0x73, 0x5E, 0x86, 0x47, 0x60, 0xA3, + 0xFF, 0x70, 0x4E, 0x25, 0x71, 0x89, 0x4C, 0x92, + 0x12, 0x8F, 0x38, 0x54, 0x2D, 0xD5, 0xB6, 0x53, + 0xEF, 0x1C, 0x02, 0x69, 0xBD, 0x04, 0xF6, 0x7C, + 0x64, 0x0D, 0x1B, 0x04, 0x96, 0x45, 0xE7, 0x87, + 0x73, 0xCF, 0x45, 0x3A, 0x5F, 0xED, 0x25, 0xE2, + 0xAF, 0x77, 0x8B, 0x4D, 0x37, 0x4D, 0x09, 0x6C, + 0xA9, 0x5A, 0x5E, 0x92, 0x39, 0x4F, 0x2A, 0xEA, + 0x2D, 0xCD, 0x6F, 0xBE, 0x64, 0x7C, 0x1B, 0x19, + 0x39, 0x96, 0x60, 0xC0, 0xD8, 0x22, 0xE8, 0x8A, + 0xC0, 0x3F, 0x6C, 0x43, 0xB3, 0xB1, 0x71, 0xC2, + 0xFE, 0x70, 0xA1, 0xF6, 0x26, 0x34, 0xF0, 0x35, + 0x50, 0x5A, 0xC8, 0xE2, 0x3D, 0x8D, 0x5F, 0x3F, + 0xCB, 0x77, 0x7A, 0x1E, 0x64, 0x70, 0x16, 0x33, + 0x63, 0x9C, 0xAC, 0xC3, 0x1B, 0xA7, 0xCD, 0xD5, + 0x52, 0x85, 0x2F, 0x81, 0x14, 0x3C, 0xB9, 0xB6, + 0x12, 0xEC, 0x5E, 0x32, 0x02, 0xB5, 0x37, 0xF9, + 0xE1, 0xF6, 0x0E, 0xC3, 0x53, 0xE0, 0x25, 0xDD, + 0x75, 0xB3, 0xF5, 0x99, 0x41, 0xF1, 0xA7, 0x26, + 0xA6, 0x4C, 0xBD, 0xD2, 0x32, 0x81, 0xC0, 0x5C, + 0xDF, 0x2D, 0xE8, 0x0F, 0x54, 0x76, 0xD5, 0x01, + 0x18, 0xA0, 0x8F, 0xB0, 0xE1, 0x62, 0x8B, 0x68, + 0xCA, 0xD3, 0x99, 0xDC, 0x47, 0xEA, 0x7A, 0xBA, + 0x3A, 0xE1, 0x61, 0x4C, 0x94, 0xC1, 0xB2, 0x72, + 0xEF, 0xC4, 0x44, 0x69, 0xB1, 0x0D, 0x27, 0x42, + 0xE2, 0x1B, 0x8C, 0xA7, 0x7C, 0x41, 0x2B, 0x73, + 0xF1, 0x26, 0x8A, 0x64, 0xD5, 0x42, 0x87, 0x58, + 0xFA, 0x5D, 0x37, 0x27, 0x11, 0xAD, 0xE5, 0x9D, + 0x1F, 0xC8, 0x69, 0xA7, 0x14, 0x8C, 0x5D, 0xD6, + 0x55, 0x4E, 0xD8, 0xB4, 0xFE, 0x65, 0xAD, 0xAD, + 0x0D, 0xD6, 0x10, 0xE5, 0x1D, 0x3F, 0x34, 0x5C, + 0x1C, 0xE7, 0x51, 0xCF, 0x3C, 0x24, 0x84, 0x64, + 0xE4, 0xBF, 0xF6, 0xBA, 0x90, 0x4B, 0x83, 0x83, + 0x23, 0xF8, 0x9C, 0xDB, 0xA9, 0xD9, 0x99, 0x59, + 0x39, 0x3F, 0x99, 0x27, 0x94, 0x8E, 0x2E, 0xCE, + 0x4E, 0x37, 0xAA, 0x6C, 0x74, 0xE4, 0x84, 0x84, + 0xAE, 0x65, 0x71, 0x76, 0x04, 0x15, 0x28, 0xEB, + 0xCE, 0x00, 0x94, 0xF4, 0x2F, 0x27, 0x45, 0x89, + 0x0F, 0xD8, 0x2B, 0xA7, 0x3C, 0x9D, 0xF1, 0x38, + 0x88, 0xB0, 0xF6, 0x7A, 0x4C, 0xED, 0x3D, 0x0E, + 0x2E, 0x97, 0x4E, 0x08, 0xDC, 0x73, 0xDB, 0x19, + 0x09, 0x7B, 0x3D, 0x4A, 0x0B, 0x2B, 0xDB, 0x6F, + 0x05, 0x12, 0x6E, 0xC8, 0xC2, 0x7E, 0x37, 0x75, + 0xF9, 0x08, 0x0C, 0x6C, 0x91, 0xA1, 0x49, 0x98, + 0xA8, 0xC0, 0x37, 0xE9, 0x7D, 0xE8, 0x58, 0x10, + 0xB0, 0xB3, 0x07, 0xD6, 0x06, 0x36, 0xE9, 0xAA, + 0xC0, 0xC6, 0xC0, 0x54, 0xCD, 0x8F, 0xA3, 0x49, + 0x13, 0x62, 0x56, 0x30, 0xC0, 0xC2, 0xEE, 0x07, + 0x07, 0x58, 0xAF, 0x41, 0xD3, 0x4B, 0x4D, 0xC4, + 0xFE, 0xAD, 0x19, 0xD8, 0x03, 0x39, 0xCA, 0x80, + 0xB4, 0xDD, 0x40, 0x06, 0x54, 0x6A, 0xBA, 0xC1, + 0xB1, 0xD0, 0xEE, 0x00, 0xD0, 0x47, 0xA5, 0x2C, + 0x44, 0x17, 0xA3, 0xC3, 0x10, 0x20, 0x93, 0xC3, + 0xC9, 0xE6, 0xA2, 0xE1, 0x13, 0x29, 0xA7, 0x97, + 0xE8, 0xC3, 0x8F, 0x0D, 0x17, 0xA9, 0xE3, 0xC1, + 0x4F, 0xBD, 0x8B, 0x2B, 0xE2, 0xB2, 0x1E, 0xFE, + 0xBC, 0x3A, 0xE0, 0xE9, 0x20, 0x90, 0xFC, 0x35, + 0xBE, 0x30, 0x3E, 0x50, 0x93, 0x10, 0x40, 0xB0, + 0x44, 0xAF, 0xFA, 0x66, 0x04, 0x70, 0x62, 0xCE, + 0x60, 0x5B, 0xAE, 0xD3, 0x5D, 0x58, 0xCD, 0xAF, + 0xE4, 0x2B, 0x1C, 0x2E, 0xF5, 0xD7, 0x9C, 0x79, + 0x6B, 0xDB, 0x44, 0xE8, 0x10, 0xA0, 0x48, 0x80, + 0x89, 0xD9, 0xCA, 0xF1, 0x09, 0xA4, 0x34, 0xF4, + 0x74, 0xAF, 0x2F, 0x02, 0xDA, 0x4B, 0x6C, 0xAF, + 0x87, 0x5E, 0x4A, 0xEC, 0x20, 0xB5, 0x8D, 0x6D, + 0x45, 0x9C, 0xA1, 0x67, 0x9A, 0xB9, 0xFE, 0x32, + 0xF8, 0xC1, 0xD8, 0x34, 0x3D, 0xC6, 0xA5, 0xA5, + 0x05, 0xDE, 0xAA, 0xEB, 0x87, 0xF7, 0xB7, 0x77, + 0x4F, 0x96, 0xC0, 0x60, 0xA8, 0xDA, 0xD7, 0xA3, + 0x91, 0x61, 0xF0, 0xF9, 0x29, 0xBB, 0x63, 0xA1, + 0x2D, 0xEC, 0xE8, 0xAF, 0x5F, 0x0A, 0x6D, 0x8F, + 0x12, 0x39, 0xB9, 0x94, 0x4C, 0xAD, 0x86, 0x45, + 0x05, 0xFE, 0x48, 0x66, 0x9B, 0x9F, 0x3F, 0xDF, + 0x5F, 0xB4, 0x46, 0x3A, 0xA2, 0x50, 0x10, 0x92, + 0x77, 0x18, 0xB3, 0x2F, 0xF7, 0x47, 0x11, 0x90, + 0x10, 0xC7, 0x72, 0x6C, 0x14, 0xD4, 0xE5, 0x62, + 0xE1, 0x36, 0x96, 0x42, 0x9F, 0x1F, 0xBC, 0x8C, + 0xBC, 0xC4, 0xD2, 0x6C, 0x9E, 0x04, 0xD4, 0xD8, + 0xF8, 0xF3, 0x98, 0x04, 0x06, 0x7A, 0x98, 0x54, + 0xF0, 0xCB, 0x3E, 0x43, 0xFD, 0x55, 0x09, 0x2B, + 0x81, 0x74, 0x10, 0x56, 0xBC, 0x47, 0x94, 0xB3, + 0x3E, 0xF2, 0xE6, 0x86, 0x76, 0xC6, 0xBD, 0x3D, + 0xBD, 0xD0, 0xC7, 0xDB, 0xB8, 0x18, 0xD8, 0xB8, + 0x0C, 0x67, 0x7B, 0x37, 0x4F, 0x5F, 0x4B, 0xCD, + 0x4D, 0x96, 0x2C, 0x4A, 0x20, 0x3F, 0xDF, 0x3A, + 0x43, 0x67, 0x69, 0x00, 0x62, 0x06, 0x94, 0x79, + 0xD7, 0x00, 0xAA, 0x36, 0x01, 0xA0, 0x30, 0x3E, + 0x2D, 0x34, 0xEF, 0xAD, 0x6E, 0xED, 0xBD, 0x4D, + 0xB9, 0x04, 0xF1, 0x3D, 0x6E, 0x75, 0xB0, 0xF5, + 0x52, 0x24, 0x90, 0x7D, 0xFB, 0x48, 0xE8, 0x08, + 0x88, 0xDB, 0x65, 0x80, 0x6A, 0x7F, 0x56, 0xB6, + 0x2B, 0x00, 0x80, 0xAD, 0x75, 0x44, 0x63, 0xA0, + 0x00, 0xB9, 0xFF, 0x1B, 0xCB, 0x70, 0x53, 0x13, + 0xA1, 0xEA, 0xDC, 0xE2, 0x9A, 0x58, 0x1D, 0xF7, + 0xF7, 0x4A, 0x5C, 0x40, 0xEF, 0xAF, 0xB5, 0x53, + 0x85, 0xBA, 0x08, 0x46, 0x9C, 0x0A, 0x28, 0x7B, + 0x8B, 0xD0, 0x44, 0x29, 0xD1, 0x49, 0x18, 0x92, + 0x30, 0xEB, 0x7F, 0x02, 0xFA, 0x6A, 0x3B, 0xD9, + 0x0A, 0xA1, 0x55, 0x1C, 0xEE, 0x1E, 0x3A, 0x0A, + 0xC0, 0x5D, 0xA9, 0xC1, 0x3F, 0x2E, 0x11, 0xD2, + 0xD2, 0x4D, 0xFA, 0xD6, 0x46, 0xC7, 0x01, 0xD5, + 0x59, 0x24, 0x50, 0x2F, 0xEB, 0xA9, 0xD5, 0xED, + 0xEF, 0x67, 0xA1, 0x8B, 0x51, 0xE1, 0x67, 0xB5, + 0x33, 0xE4, 0x50, 0x30, 0xE1, 0xC3, 0xF0, 0x40, + 0x60, 0x19, 0x0F, 0xCB, 0x19, 0x0B, 0x0E, 0xFC, + 0x61, 0x4A, 0xDE, 0xB0, 0x4D, 0x7B, 0xF4, 0xCB, + 0x4B, 0x90, 0x10, 0x3D, 0xE5, 0x59, 0x3B, 0xF7, + 0x72, 0xE8, 0x19, 0x76, 0xA2, 0x51, 0xF9, 0x3D, + 0x7D, 0x74, 0x52, 0xAC, 0x69, 0xB5, 0xC3, 0x5A, + 0xDD, 0x0D, 0x32, 0xDE, 0x86, 0xC2, 0x20, 0xBD, + 0x51, 0xDC, 0xE2, 0x88, 0x90, 0xD2, 0x12, 0x30, + 0x9F, 0x6E, 0x64, 0x16, 0xE8, 0x46, 0x09, 0xEF, + 0x41, 0xB6, 0x66, 0x34, 0xBB, 0x59, 0x56, 0xBC, + 0x1C, 0x55, 0x13, 0xBF, 0xFE, 0xEE, 0x2C, 0xE5, + 0x4F, 0x26, 0x99, 0xDC, 0x84, 0x9E, 0xEF, 0x9F, + 0xB5, 0x4E, 0xF4, 0x93, 0xE9, 0x04, 0x08, 0xE2, + 0xCE, 0x87, 0x38, 0x73, 0x39, 0xC3, 0x4B, 0x26, + 0xA4, 0x5A, 0x1F, 0x8C, 0x12, 0xA9, 0xC9, 0x12, + 0x2C, 0xD7, 0xC3, 0x5F, 0x47, 0x5D, 0x9D, 0xEF, + 0x00, 0xF1, 0xF7, 0x20, 0x08, 0x02, 0xC8, 0xBA, + 0x30, 0xC1, 0x95, 0xF3, 0x02, 0x32, 0xE9, 0x38, + 0x58, 0x38, 0xAE, 0x70, 0xF5, 0x29, 0x63, 0x1F, + 0x3D, 0xEC, 0x7D, 0xB3, 0x20, 0x78, 0xB5, 0x77, + 0xFB, 0x2B, 0x78, 0xFB, 0xDC, 0xA4, 0xC0, 0x2A, + 0x76, 0x3F, 0x84, 0x00, 0x74, 0x0D, 0x66, 0x5F, + 0x2D, 0xBB, 0xE5, 0x41, 0x9D, 0x07, 0xBB, 0x99, + 0x14, 0x27, 0x4D, 0xEF, 0x9A, 0x28, 0x44, 0x9F, + 0x3F, 0x66, 0x20, 0x8C, 0xC6, 0xD6, 0x24, 0xCD, + 0x67, 0x7C, 0x42, 0x8E, 0xC6, 0xEF, 0x7F, 0x25, + 0x2D, 0x74, 0xCA, 0x81, 0xDB, 0x26, 0xAE, 0xCB, + 0xA7, 0x83, 0xFD, 0x95, 0x46, 0xC5, 0xBE, 0x5C, + 0xFC, 0x07, 0xC5, 0xFF, 0x34, 0x70, 0x82, 0x6E, + 0xC7, 0x90, 0xAF, 0xC8, 0x99, 0xAB, 0xA7, 0x4E, + 0x02, 0xC1, 0x92, 0x22, 0x05, 0xA8, 0x38, 0xF8, + 0x78, 0xA3, 0x23, 0x0E, 0xD6, 0x27, 0x27, 0xE4, + 0x55, 0xEF, 0x5A, 0xBE, 0x22, 0x1B, 0xF9, 0x00, + 0xC4, 0x02, 0x44, 0x28, 0xF0, 0x40, 0x16, 0x97, + 0x17, 0x6E, 0x1A, 0x66, 0x1B, 0x98, 0xD8, 0x89, + 0x69, 0xB1, 0x8F, 0x61, 0x30, 0xC9, 0xB4, 0x84, + 0x04, 0xDF, 0x5F, 0x72, 0xAA, 0xA7, 0xC5, 0x24, + 0xC6, 0x1E, 0x80, 0xEE, 0x3A, 0x06, 0xED, 0x8F, + 0xAA, 0x73, 0xED, 0x00, 0xBB, 0x08, 0xFA, 0xF8, + 0x68, 0x2A, 0xCE, 0x3B, 0xA1, 0x98, 0x9A, 0xD6, + 0x55, 0xB7, 0x93, 0xE2, 0xCA, 0x7A, 0x2C, 0xAD, + 0x2D, 0xC7, 0x13, 0x7C, 0x9C, 0x2F, 0xFD, 0x2E, + 0xB6, 0x61, 0xCB, 0xA0, 0x93, 0x39, 0xC8, 0x56, + 0xD5, 0xCE, 0xD3, 0x9F, 0xE5, 0x06, 0x7E, 0x7E, + 0xDE, 0x05, 0x2B, 0x4E, 0x14, 0xB7, 0xD1, 0xB3, + 0xF0, 0x3B, 0x17, 0xF3, 0xA2, 0x61, 0x64, 0x88, + 0x28, 0x41, 0xE4, 0x90, 0x5F, 0x04, 0x6A, 0x12, + 0x01, 0x56, 0x7B, 0x9F, 0x4C, 0x51, 0x33, 0x13, + 0x9B, 0x40, 0xDB, 0xBD, 0x78, 0x38, 0x54, 0x96, + 0x0B, 0x20, 0xA0, 0x8D, 0x55, 0xD4, 0xD6, 0x15, + 0xAD, 0x75, 0x71, 0x0F, 0xC3, 0xBB, 0x78, 0x10, + 0xB3, 0xA2, 0xAF, 0x7A, 0x01, 0x16, 0x4D, 0xDC, + 0xFC, 0xBC, 0xCA, 0x24, 0xEF, 0x47, 0xBE, 0xDD, + 0x4A, 0xF9, 0x64, 0xCA, 0xBA, 0xF5, 0x74, 0xD0, + 0x53, 0x70, 0x75, 0xD9, 0x21, 0x91, 0x23, 0xF0, + 0x68, 0x02, 0xFF, 0x90, 0xA8, 0xC5, 0xB5, 0x87, + 0x6C, 0x17, 0x73, 0x4C, 0x8C, 0xFC, 0xBC, 0x7C, + 0x5E, 0xAE, 0x98, 0x34, 0xCC, 0x7C, 0xDC, 0xB6, + 0x26, 0x5F, 0x82, 0x6E, 0xF0, 0x41, 0x21, 0x43, + 0x00, 0xCB, 0x58, 0x13, 0xEB, 0x9B, 0xDB, 0x1B, + 0x0A, 0x8F, 0x3A, 0xD4, 0x1F, 0xA9, 0x51, 0x98, + 0xBA, 0xA2, 0x04, 0xF2, 0xA2, 0x9B, 0x88, 0x2D, + 0x89, 0x72, 0x4C, 0xA3, 0xD6, 0x64, 0xE4, 0x2C, + 0xAC, 0x6A, 0x2C, 0x40, 0x98, 0x28, 0x7E, 0xFF, + 0x7F, 0xE6, 0xF8, 0x6B, 0x22, 0xF7, 0x94, 0xE5, + 0x07, 0xDF, 0x58, 0x7F, 0xA4, 0xAC, 0xC7, 0xC5, + 0x5E, 0x9D, 0x27, 0x66, 0x6E, 0x12, 0x52, 0x50, + 0x8B, 0x48, 0x3E, 0x72, 0xAA, 0xB8, 0xFB, 0x9B, + 0xB2, 0xD2, 0xA4, 0xE8, 0x30, 0x02, 0x41, 0x21, + 0x61, 0x9A, 0x2C, 0xD0, 0x80, 0x20, 0xD2, 0xB3, + 0x33, 0x78, 0x46, 0x0A, 0x50, 0x83, 0x43, 0x43, + 0xE3, 0x38, 0xAC, 0xE3, 0xBB, 0xCB, 0x8B, 0x4B, + 0x8B, 0x72, 0xD4, 0xFA, 0x86, 0x36, 0x16, 0xF4, + 0x54, 0xAD, 0x78, 0x94, 0x51, 0x11, 0x47, 0xC6, + 0x46, 0xFB, 0x79, 0x1D, 0x47, 0xF4, 0xB3, 0xB1, + 0x32, 0xCF, 0x1F, 0x4B, 0x99, 0x84, 0xE6, 0x9B, + 0x18, 0x0E, 0xBC, 0xF5, 0xB5, 0x27, 0x5A, 0x6A, + 0x42, 0xCA, 0xCE, 0x02, 0x21, 0x21, 0x8D, 0x5D, + 0x1F, 0x87, 0x17, 0xBB, 0x43, 0xF3, 0x01, 0xCB, + 0x47, 0x5C, 0xCA, 0xA6, 0xCE, 0xE7, 0x97, 0xC5, + 0x0F, 0xD8, 0x73, 0xEF, 0x37, 0x87, 0xFD, 0x3C, + 0xBC, 0x67, 0xD1, 0xBD, 0x65, 0xD5, 0x51, 0x9C, + 0x1E, 0xA5, 0x17, 0x7A, 0xA2, 0x12, 0x72, 0xB2, + 0x32, 0xE9, 0xEF, 0x8D, 0x57, 0x87, 0xCD, 0x0F, + 0x8F, 0x54, 0xE2, 0x8E, 0x56, 0xE6, 0x66, 0xB4, + 0x36, 0x8D, 0x27, 0x4B, 0x9B, 0x2B, 0x36, 0xF2, + 0x0C, 0xD3, 0xE1, 0x9F, 0x45, 0x95, 0x81, 0x52, + 0xD0, 0x6B, 0x45, 0x3A, 0xE0, 0x30, 0xF0, 0x23, + 0xA1, 0x1A, 0x74, 0x0C, 0xD6, 0x06, 0x7E, 0xAB, + 0x29, 0x92, 0x14, 0x6E, 0xB4, 0x64, 0x30, 0xE5, + 0x67, 0xDC, 0xD2, 0xAB, 0x71, 0xA1, 0xC1, 0x01, + 0x81, 0x5A, 0x1C, 0x8F, 0xA8, 0xE7, 0x87, 0x47, + 0xC7, 0x1C, 0x5A, 0xC9, 0xEE, 0xA1, 0xC1, 0x01, + 0x81, 0x5A, 0x1C, 0x8F, 0xA8, 0xE7, 0x87, 0x47, + 0xC7, 0x1C, 0x5A, 0xC9, 0xEE, 0xA1, 0xC1, 0x01, + 0x81, 0x5A, 0x1C, 0x8F, 0xA8, 0xE7, 0x87, 0x47, + 0xC7, 0x1C, 0x5A, 0xC9, 0xEE, 0xA1, 0xC1, 0x01, + 0x81, 0x5A, 0x1C, 0x8F, 0xA8, 0xE7, 0x87, 0x47, + 0xC7, 0x1C, 0x5A, 0xC9, 0xEE, 0xA1, 0xC1, 0x01, + 0x81, 0x5A, 0x1C, 0x8F, 0xA8, 0xE7, 0x97, 0x40, + 0xC2, 0x79, 0xEB, 0x90, 0x4A, 0x9A, 0xEE, 0x36, + 0xB4, 0x0F, 0x19, 0x62, 0xB8, 0x68, 0x08, 0xC8, + 0x48, 0x93, 0x25, 0x49, 0x91, 0x21, 0x41, 0x81, + 0x01, 0xDA, 0xA0, 0xD4, 0x0C, 0xDC, 0x6C, 0xB4, + 0x34, 0x8F, 0xC1, 0xB4, 0x6C, 0xBC, 0x30, 0xF0, + 0x70, 0xAB, 0x1D, 0x71, 0xA9, 0x19, 0x78, 0xB8, + 0x38, 0xE3, 0x54, 0x38, 0xE1, 0x51, 0x30, 0xF8, + 0x38, 0xE3, 0x54, 0x39, 0xE0, 0x51, 0x70, 0xA0, + 0x24, 0xFD, 0x6A, 0x02, 0xFB, 0x4F, 0x0E, 0x4A, + 0xDA, 0x43, 0xE4, 0x99, 0x50, 0xF1, 0xD8, 0x3A, + 0x9E, 0x67, 0x98, 0xE6, 0x77, 0xD5, 0xFC, 0x6E, + 0xD7, 0x1E, 0xFD, 0x80, 0x0D, 0xAC, 0x99, 0x4C, + 0x99, 0x53, 0x4F, 0x09, 0x7B, 0xE1, 0x2B, 0x41, + 0x6B, 0x9A, 0x79, 0x40, 0xCD, 0x28, 0x1D, 0x88, + 0x5D, 0x53, 0xB0, 0x09, 0x84, 0xE1, 0x2B, 0x01, + 0x2B, 0x1E, 0x02, 0x80, 0xF2, 0xAC, 0x7A, 0x17, + 0x21, 0x17, 0x17, 0x96, 0xF8, 0xA5, 0x73, 0x6E, + 0x35, 0x33, 0x6B, 0xE9, 0xDF, 0x81, 0x3F, 0x84, + 0xEB, 0x8D, 0xE5, 0x72, 0x74, 0x3F, 0xE1, 0xCE, + 0xB5, 0x93, 0xDB, 0x49, 0x6F, 0x21, 0xBF, 0x88, + 0xB7, 0x93, 0xDB, 0x48, 0x6E, 0x21, 0xBE, 0x81, + 0xFE, 0xDA, 0x58, 0x2D, 0xF5, 0x25, 0x7D, 0xA4, + 0x24, 0x9F, 0xD5, 0xA0, 0x78, 0xA8, 0xFC, 0x3C, + 0xBC, 0x67, 0xD1, 0xBD, 0x65, 0xD5, 0xB5, 0x75, + 0xF5, 0x2E, 0x98, 0xF4, 0x2C, 0x9C, 0xFC, 0x3C, + 0xBC, 0x67, 0xF9, 0x9C, 0x44, 0x94, 0xD0, 0x19, + 0x99, 0x22, 0x84, 0x58, 0x82, 0x32, 0x52, 0x88, + 0x08, 0xB3, 0x75, 0x18, 0xC0, 0x70, 0x6C, 0xAB, + 0x2B, 0x90, 0x9A, 0xFB, 0x21, 0xF1, 0xAD, 0x65, + 0xE5, 0x5E, 0xFC, 0x9E, 0x44, 0x94, 0x38, 0xF6, + 0x74, 0xCF, 0xED, 0x87, 0x5F, 0x8F, 0x4B, 0x84, + 0x06, 0xBD, 0x4F, 0x25, 0xFD, 0x2D, 0xC1, 0x0E, + 0x8C, 0x37, 0x71, 0x04, 0xDC, 0x0C, 0xB8, 0x77, + 0xF5, 0x4E, 0x48, 0x35, 0xEF, 0x3F, 0xE7, 0x2F, + 0xAF, 0x14, 0x82, 0xFC, 0x26, 0xF6, 0x2A, 0xED, + 0x6D, 0xD6, 0x34, 0x4A, 0x90, 0x40, 0xE8, 0x3A, + 0xB8, 0x03, 0x5D, 0x37, 0xEF, 0x3F, 0x3B, 0xE3, + 0x61, 0xDA, 0x2C, 0x4A, 0x92, 0x42, 0x14, 0x95, + 0x15, 0x4F, 0x7B, 0x11, 0x78, 0x48, 0x2E, 0xF2, + 0x78, 0x32, 0x05, 0x6F, 0x15, 0xEE, 0x8E, 0xC7, + 0x4E, 0xB0, 0x04, 0x68, 0x55, 0xE1, 0x81, 0xE4, + 0x66, 0xBD, 0xEE, 0x87, 0x5F, 0x0A, 0x62, 0xA2, + 0x07, 0xDF, 0x69, 0xA0, 0x71, 0xC1, 0x00, 0x43, + 0xC5, 0xAF, 0x9D, 0xF7, 0x8A, 0x60, 0x27, 0xFA, + 0x8A, 0x51, 0xD1, 0xFC, 0x24, 0xA5, 0x40, 0x86, + 0x27, 0x7A, 0xCA, 0x8F, 0x84, 0x29, 0xB9, 0x79, + 0xF9, 0x22, 0xA2, 0x8F, 0x57, 0xD6, 0x31, 0xF7, + 0x56, 0x05, 0xB5, 0xF0, 0x6B, 0xC6, 0x56, 0x96, + 0x16, 0xCD, 0x4D, 0x60, 0xB8, 0x39, 0xDC, 0x1A, + 0xBB, 0xE9, 0x59, 0x1C, 0x57, 0xFA, 0x6A, 0xAA, + 0x2A, 0xF1, 0x71, 0x5C, 0x84, 0x15, 0xF8, 0x3E, + 0x8F, 0xD8, 0x68, 0x95, 0xC7, 0x71, 0x90, 0xDB, + 0x5D, 0x0F, 0xF0, 0xB5, 0x6E, 0xC3, 0x53, 0x93, + 0x13, 0xC8, 0x48, 0x65, 0xBD, 0x9C, 0x72, 0xB4, + 0x38, 0xEB, 0xDF, 0xFA, 0x22, 0xF7, 0x96, 0x56, + 0x77, 0x3C, 0x8C, 0x51, 0x0E, 0xB8, 0x19, 0x56, + 0xD0, 0xC2, 0x7F, 0xBA, 0x39, 0x94, 0x04, 0xC4, + 0x44, 0x9F, 0x1F, 0x32, 0xEA, 0x6B, 0x9A, 0x5C, + 0xFD, 0xB4, 0x04, 0x41, 0x8A, 0x27, 0xB7, 0x77, + 0xF7, 0x2C, 0xAC, 0x81, 0x59, 0x68, 0x9C, 0x5A, + 0xEB, 0xA3, 0x13, 0x5E, 0x13, 0xA5, 0xEC, 0x0F, + 0x06, 0x8E, 0x25, 0xB9, 0x61, 0xD1, 0x87, 0x06, + 0x86, 0xCC, 0xEC, 0x86, 0xDF, 0xF8, 0x9E, 0xD7, + 0x7E, 0xC0, 0x76, 0x1A, 0xDF, 0x9F, 0xC9, 0x48, + 0xC8, 0xB2, 0x9C, 0xF6, 0x9C, 0x8C, 0x60, 0x08, + 0x82, 0x79, 0xAE, 0xC2, 0x92, 0x08, 0xD2, 0xA8, + 0xB4, 0x77, 0xCD, 0xBD, 0x69, 0x54, 0xD6, 0x3C, + 0x94, 0x8F, 0x19, 0x75, 0x7F, 0x81, 0xED, 0xEF, + 0x24, 0xD8, 0x4B, 0x80, 0x7B, 0xEB, 0x6D, 0xBE, + 0x2E, 0xD5, 0x63, 0x12, 0x3A, 0x8A, 0xEA, 0x2A, + 0xAA, 0x71, 0xC7, 0xAB, 0x73, 0xC3, 0xA3, 0x63, + 0xE3, 0x38, 0x8F, 0xE3, 0x3F, 0x8F, 0x8B, 0x51, + 0xD3, 0x68, }; static unsigned char vfs5011_init_16[] = { /* 2565 B */ - 0x02, 0xF0, 0x00, 0x14, 0x00, 0x03, 0x00, 0x09, - 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, - 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, - 0x20, 0x04, 0x30, 0xE5, 0x03, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, - 0xEA, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x4C, 0x20, 0x04, 0x30, 0x0A, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, - 0x04, 0x30, 0x01, 0xDE, 0x01, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, - 0x30, 0x02, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, - 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x08, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x40, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x60, 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, - 0x30, 0x30, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x90, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, - 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x30, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xD8, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, - 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x04, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, - 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, - 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, - 0x30, 0x00, 0x00, 0x74, 0x01, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, - 0x74, 0x01, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, - 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, - 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, - 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, - 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, - 0xFF, 0xF9, 0x87, 0x20, 0xBB, 0xF8, 0x87, 0x00, - 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, - 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, - 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x07, 0x20, - 0xBA, 0xF8, 0x07, 0x20, 0xB9, 0xF8, 0x07, 0x20, - 0xB8, 0xF8, 0x07, 0x20, 0xB7, 0xF8, 0x07, 0x20, - 0xB6, 0xF8, 0x07, 0x20, 0xB5, 0xF8, 0x07, 0x20, - 0xB4, 0xF8, 0x07, 0x20, 0xB3, 0xF8, 0x07, 0x20, - 0xB2, 0xF8, 0x07, 0x20, 0xB1, 0xF8, 0x07, 0x22, - 0xB0, 0xF8, 0x07, 0x22, 0xAF, 0xF8, 0x07, 0x22, - 0xAE, 0xF8, 0x07, 0x22, 0xAD, 0xF8, 0x07, 0x22, - 0xAC, 0xF8, 0x07, 0x22, 0xAB, 0xF8, 0x07, 0x22, - 0xAA, 0xF8, 0x07, 0x22, 0xA9, 0xF8, 0x07, 0x22, - 0xA8, 0xF8, 0x07, 0x22, 0xA7, 0xF8, 0x07, 0x22, - 0xA6, 0xF8, 0x07, 0x22, 0xA5, 0xF8, 0x07, 0x22, - 0xA4, 0xF8, 0x07, 0x22, 0xA3, 0xF8, 0x07, 0x22, - 0xA2, 0xF8, 0x07, 0x22, 0xA1, 0xF8, 0x07, 0x22, - 0xA0, 0xF8, 0x07, 0x22, 0x9F, 0xF8, 0x07, 0x22, - 0x9E, 0xF8, 0x07, 0x22, 0x9D, 0xF8, 0x07, 0x22, - 0x9C, 0xF8, 0x07, 0x22, 0x9B, 0xF8, 0x07, 0x22, - 0x9A, 0xF8, 0x07, 0x22, 0x99, 0xF8, 0x07, 0x22, - 0x98, 0xF8, 0x07, 0x22, 0x97, 0xF8, 0x07, 0x22, - 0x96, 0xF8, 0x07, 0x22, 0x95, 0xF8, 0x07, 0x22, - 0x94, 0xF8, 0x07, 0x22, 0x93, 0xF8, 0x07, 0x22, - 0x92, 0xF8, 0x07, 0x22, 0x91, 0xF8, 0x07, 0x22, - 0x90, 0xF8, 0x07, 0x22, 0x8F, 0xF8, 0x07, 0x22, - 0x8E, 0xF8, 0x07, 0x22, 0x8D, 0xF8, 0x07, 0x22, - 0x8C, 0xF8, 0x07, 0x22, 0x8B, 0xF8, 0x07, 0x22, - 0x8A, 0xF8, 0x07, 0x22, 0x89, 0xF8, 0x07, 0x22, - 0x88, 0xF8, 0x07, 0x22, 0x87, 0xF8, 0x07, 0x22, - 0x86, 0xF8, 0x07, 0x22, 0x85, 0xF8, 0x07, 0x22, - 0x84, 0xF8, 0x07, 0x22, 0x83, 0xF8, 0x07, 0x22, - 0x82, 0xF8, 0x07, 0x22, 0x81, 0xF8, 0x07, 0x22, - 0x80, 0xF8, 0x07, 0x22, 0x7F, 0xF8, 0x07, 0x22, - 0x7E, 0xF8, 0x07, 0x22, 0x7D, 0xF8, 0x07, 0x22, - 0x7C, 0xF8, 0x07, 0x22, 0x7B, 0xF8, 0x07, 0x22, - 0x7A, 0xF8, 0x07, 0x22, 0x79, 0xF8, 0x07, 0x22, - 0x78, 0xF8, 0x07, 0x22, 0x77, 0xF8, 0x07, 0x22, - 0x76, 0xF8, 0x07, 0x22, 0x75, 0xF8, 0x07, 0x22, - 0x74, 0xF8, 0x07, 0x22, 0x73, 0xF8, 0x07, 0x22, - 0x72, 0xF8, 0x07, 0x22, 0x71, 0xF8, 0x07, 0x22, - 0x70, 0xF8, 0x07, 0x22, 0x6F, 0xF8, 0x07, 0x22, - 0x6E, 0xF8, 0x07, 0x22, 0x6D, 0xF8, 0x07, 0x22, - 0x6C, 0xF8, 0x07, 0x22, 0x6B, 0xF8, 0x07, 0x22, - 0x6A, 0xF8, 0x07, 0x22, 0x69, 0xF8, 0x07, 0x22, - 0x68, 0xF8, 0x07, 0x22, 0x67, 0xF8, 0x07, 0x22, - 0x66, 0xF8, 0x07, 0x22, 0x65, 0xF8, 0x07, 0x22, - 0x64, 0xF8, 0x07, 0x22, 0x63, 0xF8, 0x07, 0x22, - 0x62, 0xF8, 0x07, 0x22, 0x61, 0xF8, 0x07, 0x22, - 0x60, 0xF8, 0x07, 0x22, 0x5F, 0xF8, 0x07, 0x22, - 0x5E, 0xF8, 0x07, 0x22, 0x5D, 0xF8, 0x07, 0x22, - 0x5C, 0xF8, 0x07, 0x22, 0x5B, 0xF8, 0x07, 0x22, - 0x5A, 0xF8, 0x07, 0x22, 0x59, 0xF8, 0x07, 0x22, - 0x58, 0xF8, 0x07, 0x22, 0x57, 0xF8, 0x07, 0x22, - 0x56, 0xF8, 0x07, 0x22, 0x55, 0xF8, 0x07, 0x22, - 0x54, 0xF8, 0x07, 0x22, 0x53, 0xF8, 0x07, 0x22, - 0x52, 0xF8, 0x07, 0x22, 0x51, 0xF8, 0x07, 0x22, - 0x50, 0xF8, 0x07, 0x22, 0x4F, 0xF8, 0x07, 0x22, - 0x4E, 0xF8, 0x07, 0x22, 0x4D, 0xF8, 0x07, 0x22, - 0x4C, 0xF8, 0x07, 0x22, 0x4B, 0xF8, 0x07, 0x22, - 0x4A, 0xF8, 0x07, 0x22, 0x49, 0xF8, 0x07, 0x22, - 0x48, 0xF8, 0x07, 0x22, 0x47, 0xF8, 0x07, 0x22, - 0x46, 0xF8, 0x07, 0x22, 0x45, 0xF8, 0x07, 0x22, - 0x44, 0xF8, 0x07, 0x22, 0x43, 0xF8, 0x07, 0x22, - 0x42, 0xF8, 0x07, 0x22, 0x41, 0xF8, 0x07, 0x22, - 0x40, 0xF8, 0x07, 0x22, 0x3F, 0xF8, 0x07, 0x22, - 0x3E, 0xF8, 0x07, 0x22, 0x3D, 0xF8, 0x07, 0x22, - 0x3C, 0xF8, 0x07, 0x22, 0x3B, 0xF8, 0x07, 0x22, - 0x3A, 0xF8, 0x07, 0x22, 0x39, 0xF8, 0x07, 0x22, - 0x38, 0xF8, 0x07, 0x22, 0x37, 0xF8, 0x07, 0x22, - 0x36, 0xF8, 0x07, 0x22, 0x35, 0xF8, 0x07, 0x22, - 0x34, 0xF8, 0x07, 0x22, 0x33, 0xF8, 0x07, 0x22, - 0x32, 0xF8, 0x07, 0x22, 0x31, 0xF8, 0x07, 0x22, - 0x30, 0xF8, 0x07, 0x22, 0x2F, 0xF8, 0x07, 0x22, - 0x2E, 0xF8, 0x07, 0x22, 0x2D, 0xF8, 0x07, 0x22, - 0x2C, 0xF8, 0x07, 0x22, 0x2B, 0xF8, 0x07, 0x22, - 0x2A, 0xF8, 0x07, 0x22, 0x29, 0xF8, 0x07, 0x22, - 0x28, 0xF8, 0x07, 0x22, 0x27, 0xF8, 0x07, 0x22, - 0x26, 0xF8, 0x07, 0x22, 0x25, 0xF8, 0x07, 0x22, - 0x24, 0xF8, 0x07, 0x22, 0x23, 0xF8, 0x07, 0x20, - 0x22, 0xF8, 0x07, 0x20, 0x21, 0xF8, 0x07, 0x20, - 0x20, 0xF8, 0x07, 0x20, 0x1F, 0xF8, 0x07, 0x20, - 0x1E, 0xF8, 0x07, 0x20, 0x1D, 0xF8, 0x07, 0x20, - 0x1C, 0xF8, 0x07, 0x20, 0x1C, 0xF8, 0x07, 0x00, - 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, - 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, - 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, - 0xD8, 0xF8, 0x27, 0x20, 0xD9, 0xF8, 0x27, 0x20, - 0xDA, 0xF8, 0x27, 0x20, 0xDB, 0xF8, 0x27, 0x20, - 0xDC, 0xF8, 0x27, 0x20, 0xDD, 0xF8, 0x27, 0x20, - 0xDE, 0xF8, 0x27, 0x20, 0xDF, 0xF8, 0x27, 0x20, - 0xE0, 0xF8, 0x27, 0x20, 0xE1, 0xF8, 0x27, 0x20, - 0xE2, 0xF8, 0x27, 0x20, 0xE3, 0xF8, 0x27, 0x20, - 0xE4, 0xF8, 0x27, 0x20, 0xE5, 0xF8, 0x27, 0x20, - 0xE6, 0xF8, 0x27, 0x20, 0xE7, 0xF8, 0x27, 0x20, - 0xE8, 0xF8, 0x27, 0x20, 0xE9, 0xF8, 0x27, 0x20, - 0xEA, 0xF8, 0x27, 0x20, 0xEB, 0xF8, 0x27, 0x20, - 0xEC, 0xF8, 0x27, 0x20, 0xED, 0xF8, 0x27, 0x20, - 0xEE, 0xF8, 0x27, 0x20, 0xEF, 0xF8, 0x27, 0x20, - 0xF0, 0xF8, 0x27, 0x20, 0xF1, 0xF8, 0x27, 0x20, - 0xF2, 0xF8, 0x27, 0x20, 0xF3, 0xF8, 0x27, 0x20, - 0xF4, 0xF8, 0x27, 0x20, 0xF5, 0xF8, 0x27, 0x20, - 0xF6, 0xF8, 0x27, 0x20, 0xF7, 0xF8, 0x27, 0x20, - 0xF8, 0xF8, 0x27, 0x20, 0xF9, 0xF8, 0x27, 0x20, - 0xFA, 0xF8, 0x27, 0x20, 0xFB, 0xF8, 0x27, 0x20, - 0xFC, 0xF8, 0x27, 0x20, 0xFD, 0xF8, 0x27, 0x20, - 0xFE, 0xF8, 0x27, 0x20, 0xFF, 0xF8, 0x27, 0x20, - 0x00, 0xF9, 0x27, 0x20, 0xD7, 0xF8, 0x27, 0x20, - 0x00, 0xF8, 0x27, 0x20, 0x01, 0xF8, 0x27, 0x20, - 0x02, 0xF8, 0x27, 0x20, 0x03, 0xF8, 0x27, 0x20, - 0x04, 0xF8, 0x27, 0x20, 0x05, 0xF8, 0x27, 0x20, - 0x06, 0xF8, 0x27, 0x20, 0x07, 0xF8, 0x27, 0x20, - 0x08, 0xF8, 0x27, 0x20, 0x09, 0xF8, 0x27, 0x20, - 0x0A, 0xF8, 0x27, 0x20, 0x0B, 0xF8, 0x27, 0x20, - 0x0C, 0xF8, 0x27, 0x20, 0x0D, 0xF8, 0x27, 0x20, - 0x0E, 0xF8, 0x27, 0x20, 0x0F, 0xF8, 0x27, 0x20, - 0x10, 0xF8, 0x27, 0x20, 0x11, 0xF8, 0x27, 0x20, - 0x12, 0xF8, 0x27, 0x20, 0x13, 0xF8, 0x27, 0x20, - 0x14, 0xF8, 0x27, 0x20, 0x15, 0xF8, 0x27, 0x20, - 0x15, 0xF8, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, - 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, - 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, - 0x04, 0x17, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0E, - 0x00, 0x0C, 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x05, - 0x00, 0x0E, 0x00, 0x10, 0x20, 0xFD, 0x00, 0xFF, - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x03, 0x00, 0x09, 0x00, 0x04, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x08, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x0C, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x10, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x14, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xC8, 0x20, 0x04, 0x30, 0x04, 0x00, 0x00, - 0x00, 0x04, 0x05, 0x00, 0x0E, 0x00, 0x14, 0x20, - 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x83, 0x00, 0x03, 0x00, 0x09, 0x00, - 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x90, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x98, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x08, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x60, 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, - 0x04, 0x15, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x28, 0x00, 0x00, + 0x02, 0xF0, 0x00, 0x14, 0x00, 0x03, 0x00, 0x09, + 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, + 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, + 0x20, 0x04, 0x30, 0xE5, 0x03, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, + 0xEA, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x4C, 0x20, 0x04, 0x30, 0x0A, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, + 0x04, 0x30, 0x01, 0xDE, 0x01, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, + 0x30, 0x02, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, + 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x08, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x40, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x60, 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x90, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, + 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x30, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xD8, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, + 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x04, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, + 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, + 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, + 0x30, 0x00, 0x00, 0x74, 0x01, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, + 0x74, 0x01, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, + 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, + 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, + 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, + 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, + 0xFF, 0xF9, 0x87, 0x20, 0xBB, 0xF8, 0x87, 0x00, + 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, + 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, + 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x07, 0x20, + 0xBA, 0xF8, 0x07, 0x20, 0xB9, 0xF8, 0x07, 0x20, + 0xB8, 0xF8, 0x07, 0x20, 0xB7, 0xF8, 0x07, 0x20, + 0xB6, 0xF8, 0x07, 0x20, 0xB5, 0xF8, 0x07, 0x20, + 0xB4, 0xF8, 0x07, 0x20, 0xB3, 0xF8, 0x07, 0x20, + 0xB2, 0xF8, 0x07, 0x20, 0xB1, 0xF8, 0x07, 0x22, + 0xB0, 0xF8, 0x07, 0x22, 0xAF, 0xF8, 0x07, 0x22, + 0xAE, 0xF8, 0x07, 0x22, 0xAD, 0xF8, 0x07, 0x22, + 0xAC, 0xF8, 0x07, 0x22, 0xAB, 0xF8, 0x07, 0x22, + 0xAA, 0xF8, 0x07, 0x22, 0xA9, 0xF8, 0x07, 0x22, + 0xA8, 0xF8, 0x07, 0x22, 0xA7, 0xF8, 0x07, 0x22, + 0xA6, 0xF8, 0x07, 0x22, 0xA5, 0xF8, 0x07, 0x22, + 0xA4, 0xF8, 0x07, 0x22, 0xA3, 0xF8, 0x07, 0x22, + 0xA2, 0xF8, 0x07, 0x22, 0xA1, 0xF8, 0x07, 0x22, + 0xA0, 0xF8, 0x07, 0x22, 0x9F, 0xF8, 0x07, 0x22, + 0x9E, 0xF8, 0x07, 0x22, 0x9D, 0xF8, 0x07, 0x22, + 0x9C, 0xF8, 0x07, 0x22, 0x9B, 0xF8, 0x07, 0x22, + 0x9A, 0xF8, 0x07, 0x22, 0x99, 0xF8, 0x07, 0x22, + 0x98, 0xF8, 0x07, 0x22, 0x97, 0xF8, 0x07, 0x22, + 0x96, 0xF8, 0x07, 0x22, 0x95, 0xF8, 0x07, 0x22, + 0x94, 0xF8, 0x07, 0x22, 0x93, 0xF8, 0x07, 0x22, + 0x92, 0xF8, 0x07, 0x22, 0x91, 0xF8, 0x07, 0x22, + 0x90, 0xF8, 0x07, 0x22, 0x8F, 0xF8, 0x07, 0x22, + 0x8E, 0xF8, 0x07, 0x22, 0x8D, 0xF8, 0x07, 0x22, + 0x8C, 0xF8, 0x07, 0x22, 0x8B, 0xF8, 0x07, 0x22, + 0x8A, 0xF8, 0x07, 0x22, 0x89, 0xF8, 0x07, 0x22, + 0x88, 0xF8, 0x07, 0x22, 0x87, 0xF8, 0x07, 0x22, + 0x86, 0xF8, 0x07, 0x22, 0x85, 0xF8, 0x07, 0x22, + 0x84, 0xF8, 0x07, 0x22, 0x83, 0xF8, 0x07, 0x22, + 0x82, 0xF8, 0x07, 0x22, 0x81, 0xF8, 0x07, 0x22, + 0x80, 0xF8, 0x07, 0x22, 0x7F, 0xF8, 0x07, 0x22, + 0x7E, 0xF8, 0x07, 0x22, 0x7D, 0xF8, 0x07, 0x22, + 0x7C, 0xF8, 0x07, 0x22, 0x7B, 0xF8, 0x07, 0x22, + 0x7A, 0xF8, 0x07, 0x22, 0x79, 0xF8, 0x07, 0x22, + 0x78, 0xF8, 0x07, 0x22, 0x77, 0xF8, 0x07, 0x22, + 0x76, 0xF8, 0x07, 0x22, 0x75, 0xF8, 0x07, 0x22, + 0x74, 0xF8, 0x07, 0x22, 0x73, 0xF8, 0x07, 0x22, + 0x72, 0xF8, 0x07, 0x22, 0x71, 0xF8, 0x07, 0x22, + 0x70, 0xF8, 0x07, 0x22, 0x6F, 0xF8, 0x07, 0x22, + 0x6E, 0xF8, 0x07, 0x22, 0x6D, 0xF8, 0x07, 0x22, + 0x6C, 0xF8, 0x07, 0x22, 0x6B, 0xF8, 0x07, 0x22, + 0x6A, 0xF8, 0x07, 0x22, 0x69, 0xF8, 0x07, 0x22, + 0x68, 0xF8, 0x07, 0x22, 0x67, 0xF8, 0x07, 0x22, + 0x66, 0xF8, 0x07, 0x22, 0x65, 0xF8, 0x07, 0x22, + 0x64, 0xF8, 0x07, 0x22, 0x63, 0xF8, 0x07, 0x22, + 0x62, 0xF8, 0x07, 0x22, 0x61, 0xF8, 0x07, 0x22, + 0x60, 0xF8, 0x07, 0x22, 0x5F, 0xF8, 0x07, 0x22, + 0x5E, 0xF8, 0x07, 0x22, 0x5D, 0xF8, 0x07, 0x22, + 0x5C, 0xF8, 0x07, 0x22, 0x5B, 0xF8, 0x07, 0x22, + 0x5A, 0xF8, 0x07, 0x22, 0x59, 0xF8, 0x07, 0x22, + 0x58, 0xF8, 0x07, 0x22, 0x57, 0xF8, 0x07, 0x22, + 0x56, 0xF8, 0x07, 0x22, 0x55, 0xF8, 0x07, 0x22, + 0x54, 0xF8, 0x07, 0x22, 0x53, 0xF8, 0x07, 0x22, + 0x52, 0xF8, 0x07, 0x22, 0x51, 0xF8, 0x07, 0x22, + 0x50, 0xF8, 0x07, 0x22, 0x4F, 0xF8, 0x07, 0x22, + 0x4E, 0xF8, 0x07, 0x22, 0x4D, 0xF8, 0x07, 0x22, + 0x4C, 0xF8, 0x07, 0x22, 0x4B, 0xF8, 0x07, 0x22, + 0x4A, 0xF8, 0x07, 0x22, 0x49, 0xF8, 0x07, 0x22, + 0x48, 0xF8, 0x07, 0x22, 0x47, 0xF8, 0x07, 0x22, + 0x46, 0xF8, 0x07, 0x22, 0x45, 0xF8, 0x07, 0x22, + 0x44, 0xF8, 0x07, 0x22, 0x43, 0xF8, 0x07, 0x22, + 0x42, 0xF8, 0x07, 0x22, 0x41, 0xF8, 0x07, 0x22, + 0x40, 0xF8, 0x07, 0x22, 0x3F, 0xF8, 0x07, 0x22, + 0x3E, 0xF8, 0x07, 0x22, 0x3D, 0xF8, 0x07, 0x22, + 0x3C, 0xF8, 0x07, 0x22, 0x3B, 0xF8, 0x07, 0x22, + 0x3A, 0xF8, 0x07, 0x22, 0x39, 0xF8, 0x07, 0x22, + 0x38, 0xF8, 0x07, 0x22, 0x37, 0xF8, 0x07, 0x22, + 0x36, 0xF8, 0x07, 0x22, 0x35, 0xF8, 0x07, 0x22, + 0x34, 0xF8, 0x07, 0x22, 0x33, 0xF8, 0x07, 0x22, + 0x32, 0xF8, 0x07, 0x22, 0x31, 0xF8, 0x07, 0x22, + 0x30, 0xF8, 0x07, 0x22, 0x2F, 0xF8, 0x07, 0x22, + 0x2E, 0xF8, 0x07, 0x22, 0x2D, 0xF8, 0x07, 0x22, + 0x2C, 0xF8, 0x07, 0x22, 0x2B, 0xF8, 0x07, 0x22, + 0x2A, 0xF8, 0x07, 0x22, 0x29, 0xF8, 0x07, 0x22, + 0x28, 0xF8, 0x07, 0x22, 0x27, 0xF8, 0x07, 0x22, + 0x26, 0xF8, 0x07, 0x22, 0x25, 0xF8, 0x07, 0x22, + 0x24, 0xF8, 0x07, 0x22, 0x23, 0xF8, 0x07, 0x20, + 0x22, 0xF8, 0x07, 0x20, 0x21, 0xF8, 0x07, 0x20, + 0x20, 0xF8, 0x07, 0x20, 0x1F, 0xF8, 0x07, 0x20, + 0x1E, 0xF8, 0x07, 0x20, 0x1D, 0xF8, 0x07, 0x20, + 0x1C, 0xF8, 0x07, 0x20, 0x1C, 0xF8, 0x07, 0x00, + 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, + 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, + 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, + 0xD8, 0xF8, 0x27, 0x20, 0xD9, 0xF8, 0x27, 0x20, + 0xDA, 0xF8, 0x27, 0x20, 0xDB, 0xF8, 0x27, 0x20, + 0xDC, 0xF8, 0x27, 0x20, 0xDD, 0xF8, 0x27, 0x20, + 0xDE, 0xF8, 0x27, 0x20, 0xDF, 0xF8, 0x27, 0x20, + 0xE0, 0xF8, 0x27, 0x20, 0xE1, 0xF8, 0x27, 0x20, + 0xE2, 0xF8, 0x27, 0x20, 0xE3, 0xF8, 0x27, 0x20, + 0xE4, 0xF8, 0x27, 0x20, 0xE5, 0xF8, 0x27, 0x20, + 0xE6, 0xF8, 0x27, 0x20, 0xE7, 0xF8, 0x27, 0x20, + 0xE8, 0xF8, 0x27, 0x20, 0xE9, 0xF8, 0x27, 0x20, + 0xEA, 0xF8, 0x27, 0x20, 0xEB, 0xF8, 0x27, 0x20, + 0xEC, 0xF8, 0x27, 0x20, 0xED, 0xF8, 0x27, 0x20, + 0xEE, 0xF8, 0x27, 0x20, 0xEF, 0xF8, 0x27, 0x20, + 0xF0, 0xF8, 0x27, 0x20, 0xF1, 0xF8, 0x27, 0x20, + 0xF2, 0xF8, 0x27, 0x20, 0xF3, 0xF8, 0x27, 0x20, + 0xF4, 0xF8, 0x27, 0x20, 0xF5, 0xF8, 0x27, 0x20, + 0xF6, 0xF8, 0x27, 0x20, 0xF7, 0xF8, 0x27, 0x20, + 0xF8, 0xF8, 0x27, 0x20, 0xF9, 0xF8, 0x27, 0x20, + 0xFA, 0xF8, 0x27, 0x20, 0xFB, 0xF8, 0x27, 0x20, + 0xFC, 0xF8, 0x27, 0x20, 0xFD, 0xF8, 0x27, 0x20, + 0xFE, 0xF8, 0x27, 0x20, 0xFF, 0xF8, 0x27, 0x20, + 0x00, 0xF9, 0x27, 0x20, 0xD7, 0xF8, 0x27, 0x20, + 0x00, 0xF8, 0x27, 0x20, 0x01, 0xF8, 0x27, 0x20, + 0x02, 0xF8, 0x27, 0x20, 0x03, 0xF8, 0x27, 0x20, + 0x04, 0xF8, 0x27, 0x20, 0x05, 0xF8, 0x27, 0x20, + 0x06, 0xF8, 0x27, 0x20, 0x07, 0xF8, 0x27, 0x20, + 0x08, 0xF8, 0x27, 0x20, 0x09, 0xF8, 0x27, 0x20, + 0x0A, 0xF8, 0x27, 0x20, 0x0B, 0xF8, 0x27, 0x20, + 0x0C, 0xF8, 0x27, 0x20, 0x0D, 0xF8, 0x27, 0x20, + 0x0E, 0xF8, 0x27, 0x20, 0x0F, 0xF8, 0x27, 0x20, + 0x10, 0xF8, 0x27, 0x20, 0x11, 0xF8, 0x27, 0x20, + 0x12, 0xF8, 0x27, 0x20, 0x13, 0xF8, 0x27, 0x20, + 0x14, 0xF8, 0x27, 0x20, 0x15, 0xF8, 0x27, 0x20, + 0x15, 0xF8, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, + 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, + 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, + 0x04, 0x17, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0E, + 0x00, 0x0C, 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x05, + 0x00, 0x0E, 0x00, 0x10, 0x20, 0xFD, 0x00, 0xFF, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, + 0x00, 0x03, 0x00, 0x09, 0x00, 0x04, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x08, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x0C, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x10, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x14, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xC8, 0x20, 0x04, 0x30, 0x04, 0x00, 0x00, + 0x00, 0x04, 0x05, 0x00, 0x0E, 0x00, 0x14, 0x20, + 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x83, 0x00, 0x03, 0x00, 0x09, 0x00, + 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x90, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x98, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x08, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x60, 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x15, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x28, 0x00, 0x00, }; static unsigned char vfs5011_init_17[] = { /* 117 B */ - 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0xFF, 0x00, 0x00, 0xFF, 0xF4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xF4, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, 0xBF, 0x02, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xFF, 0x00, 0x00, 0xFF, 0xF4, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0xF4, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0xBF, 0x02, 0x00, }; static unsigned char vfs5011_init_18[] = { /* 2903 B */ - 0x02, 0xF0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x09, - 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, - 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, - 0x20, 0x04, 0x30, 0xE5, 0x03, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, - 0xEA, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x4C, 0x20, 0x04, 0x30, 0x0A, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, - 0x04, 0x30, 0x01, 0xDE, 0x01, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, - 0x30, 0x02, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, - 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x08, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x40, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x60, 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, - 0x30, 0x30, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x90, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, - 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x30, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xD8, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, - 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x04, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, - 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, - 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, - 0x30, 0x00, 0x00, 0x74, 0x01, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, - 0x74, 0x01, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, - 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, - 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, - 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, - 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, - 0xFF, 0xF9, 0x87, 0x20, 0xBB, 0xF8, 0x87, 0x00, - 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, - 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, - 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x07, 0x20, - 0xBA, 0xF8, 0x07, 0x20, 0xB9, 0xF8, 0x07, 0x20, - 0xB8, 0xF8, 0x07, 0x20, 0xB7, 0xF8, 0x07, 0x20, - 0xB6, 0xF8, 0x07, 0x20, 0xB5, 0xF8, 0x07, 0x20, - 0xB4, 0xF8, 0x07, 0x20, 0xB3, 0xF8, 0x07, 0x20, - 0xB2, 0xF8, 0x07, 0x20, 0xB1, 0xF8, 0x07, 0x22, - 0xB0, 0xF8, 0x07, 0x22, 0xAF, 0xF8, 0x07, 0x22, - 0xAE, 0xF8, 0x07, 0x22, 0xAD, 0xF8, 0x07, 0x22, - 0xAC, 0xF8, 0x07, 0x22, 0xAB, 0xF8, 0x07, 0x22, - 0xAA, 0xF8, 0x07, 0x22, 0xA9, 0xF8, 0x07, 0x22, - 0xA8, 0xF8, 0x07, 0x22, 0xA7, 0xF8, 0x07, 0x22, - 0xA6, 0xF8, 0x07, 0x22, 0xA5, 0xF8, 0x07, 0x22, - 0xA4, 0xF8, 0x07, 0x22, 0xA3, 0xF8, 0x07, 0x22, - 0xA2, 0xF8, 0x07, 0x22, 0xA1, 0xF8, 0x07, 0x22, - 0xA0, 0xF8, 0x07, 0x22, 0x9F, 0xF8, 0x07, 0x22, - 0x9E, 0xF8, 0x07, 0x22, 0x9D, 0xF8, 0x07, 0x22, - 0x9C, 0xF8, 0x07, 0x22, 0x9B, 0xF8, 0x07, 0x22, - 0x9A, 0xF8, 0x07, 0x22, 0x99, 0xF8, 0x07, 0x22, - 0x98, 0xF8, 0x07, 0x22, 0x97, 0xF8, 0x07, 0x22, - 0x96, 0xF8, 0x07, 0x22, 0x95, 0xF8, 0x07, 0x22, - 0x94, 0xF8, 0x07, 0x22, 0x93, 0xF8, 0x07, 0x22, - 0x92, 0xF8, 0x07, 0x22, 0x91, 0xF8, 0x07, 0x22, - 0x90, 0xF8, 0x07, 0x22, 0x8F, 0xF8, 0x07, 0x22, - 0x8E, 0xF8, 0x07, 0x22, 0x8D, 0xF8, 0x07, 0x22, - 0x8C, 0xF8, 0x07, 0x22, 0x8B, 0xF8, 0x07, 0x22, - 0x8A, 0xF8, 0x07, 0x22, 0x89, 0xF8, 0x07, 0x22, - 0x88, 0xF8, 0x07, 0x22, 0x87, 0xF8, 0x07, 0x22, - 0x86, 0xF8, 0x07, 0x22, 0x85, 0xF8, 0x07, 0x22, - 0x84, 0xF8, 0x07, 0x22, 0x83, 0xF8, 0x07, 0x22, - 0x82, 0xF8, 0x07, 0x22, 0x81, 0xF8, 0x07, 0x22, - 0x80, 0xF8, 0x07, 0x22, 0x7F, 0xF8, 0x07, 0x22, - 0x7E, 0xF8, 0x07, 0x22, 0x7D, 0xF8, 0x07, 0x22, - 0x7C, 0xF8, 0x07, 0x22, 0x7B, 0xF8, 0x07, 0x22, - 0x7A, 0xF8, 0x07, 0x22, 0x79, 0xF8, 0x07, 0x22, - 0x78, 0xF8, 0x07, 0x22, 0x77, 0xF8, 0x07, 0x22, - 0x76, 0xF8, 0x07, 0x22, 0x75, 0xF8, 0x07, 0x22, - 0x74, 0xF8, 0x07, 0x22, 0x73, 0xF8, 0x07, 0x22, - 0x72, 0xF8, 0x07, 0x22, 0x71, 0xF8, 0x07, 0x22, - 0x70, 0xF8, 0x07, 0x22, 0x6F, 0xF8, 0x07, 0x22, - 0x6E, 0xF8, 0x07, 0x22, 0x6D, 0xF8, 0x07, 0x22, - 0x6C, 0xF8, 0x07, 0x22, 0x6B, 0xF8, 0x07, 0x22, - 0x6A, 0xF8, 0x07, 0x22, 0x69, 0xF8, 0x07, 0x22, - 0x68, 0xF8, 0x07, 0x22, 0x67, 0xF8, 0x07, 0x22, - 0x66, 0xF8, 0x07, 0x22, 0x65, 0xF8, 0x07, 0x22, - 0x64, 0xF8, 0x07, 0x22, 0x63, 0xF8, 0x07, 0x22, - 0x62, 0xF8, 0x07, 0x22, 0x61, 0xF8, 0x07, 0x22, - 0x60, 0xF8, 0x07, 0x22, 0x5F, 0xF8, 0x07, 0x22, - 0x5E, 0xF8, 0x07, 0x22, 0x5D, 0xF8, 0x07, 0x22, - 0x5C, 0xF8, 0x07, 0x22, 0x5B, 0xF8, 0x07, 0x22, - 0x5A, 0xF8, 0x07, 0x22, 0x59, 0xF8, 0x07, 0x22, - 0x58, 0xF8, 0x07, 0x22, 0x57, 0xF8, 0x07, 0x22, - 0x56, 0xF8, 0x07, 0x22, 0x55, 0xF8, 0x07, 0x22, - 0x54, 0xF8, 0x07, 0x22, 0x53, 0xF8, 0x07, 0x22, - 0x52, 0xF8, 0x07, 0x22, 0x51, 0xF8, 0x07, 0x22, - 0x50, 0xF8, 0x07, 0x22, 0x4F, 0xF8, 0x07, 0x22, - 0x4E, 0xF8, 0x07, 0x22, 0x4D, 0xF8, 0x07, 0x22, - 0x4C, 0xF8, 0x07, 0x22, 0x4B, 0xF8, 0x07, 0x22, - 0x4A, 0xF8, 0x07, 0x22, 0x49, 0xF8, 0x07, 0x22, - 0x48, 0xF8, 0x07, 0x22, 0x47, 0xF8, 0x07, 0x22, - 0x46, 0xF8, 0x07, 0x22, 0x45, 0xF8, 0x07, 0x22, - 0x44, 0xF8, 0x07, 0x22, 0x43, 0xF8, 0x07, 0x22, - 0x42, 0xF8, 0x07, 0x22, 0x41, 0xF8, 0x07, 0x22, - 0x40, 0xF8, 0x07, 0x22, 0x3F, 0xF8, 0x07, 0x22, - 0x3E, 0xF8, 0x07, 0x22, 0x3D, 0xF8, 0x07, 0x22, - 0x3C, 0xF8, 0x07, 0x22, 0x3B, 0xF8, 0x07, 0x22, - 0x3A, 0xF8, 0x07, 0x22, 0x39, 0xF8, 0x07, 0x22, - 0x38, 0xF8, 0x07, 0x22, 0x37, 0xF8, 0x07, 0x22, - 0x36, 0xF8, 0x07, 0x22, 0x35, 0xF8, 0x07, 0x22, - 0x34, 0xF8, 0x07, 0x22, 0x33, 0xF8, 0x07, 0x22, - 0x32, 0xF8, 0x07, 0x22, 0x31, 0xF8, 0x07, 0x22, - 0x30, 0xF8, 0x07, 0x22, 0x2F, 0xF8, 0x07, 0x22, - 0x2E, 0xF8, 0x07, 0x22, 0x2D, 0xF8, 0x07, 0x22, - 0x2C, 0xF8, 0x07, 0x22, 0x2B, 0xF8, 0x07, 0x22, - 0x2A, 0xF8, 0x07, 0x22, 0x29, 0xF8, 0x07, 0x22, - 0x28, 0xF8, 0x07, 0x22, 0x27, 0xF8, 0x07, 0x22, - 0x26, 0xF8, 0x07, 0x22, 0x25, 0xF8, 0x07, 0x22, - 0x24, 0xF8, 0x07, 0x22, 0x23, 0xF8, 0x07, 0x20, - 0x22, 0xF8, 0x07, 0x20, 0x21, 0xF8, 0x07, 0x20, - 0x20, 0xF8, 0x07, 0x20, 0x1F, 0xF8, 0x07, 0x20, - 0x1E, 0xF8, 0x07, 0x20, 0x1D, 0xF8, 0x07, 0x20, - 0x1C, 0xF8, 0x07, 0x20, 0x1C, 0xF8, 0x07, 0x00, - 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, - 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, - 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, - 0xD8, 0xF8, 0x27, 0x20, 0xD9, 0xF8, 0x27, 0x20, - 0xDA, 0xF8, 0x27, 0x20, 0xDB, 0xF8, 0x27, 0x20, - 0xDC, 0xF8, 0x27, 0x20, 0xDD, 0xF8, 0x27, 0x20, - 0xDE, 0xF8, 0x27, 0x20, 0xDF, 0xF8, 0x27, 0x20, - 0xE0, 0xF8, 0x27, 0x20, 0xE1, 0xF8, 0x27, 0x20, - 0xE2, 0xF8, 0x27, 0x20, 0xE3, 0xF8, 0x27, 0x20, - 0xE4, 0xF8, 0x27, 0x20, 0xE5, 0xF8, 0x27, 0x20, - 0xE6, 0xF8, 0x27, 0x20, 0xE7, 0xF8, 0x27, 0x20, - 0xE8, 0xF8, 0x27, 0x20, 0xE9, 0xF8, 0x27, 0x20, - 0xEA, 0xF8, 0x27, 0x20, 0xEB, 0xF8, 0x27, 0x20, - 0xEC, 0xF8, 0x27, 0x20, 0xED, 0xF8, 0x27, 0x20, - 0xEE, 0xF8, 0x27, 0x20, 0xEF, 0xF8, 0x27, 0x20, - 0xF0, 0xF8, 0x27, 0x20, 0xF1, 0xF8, 0x27, 0x20, - 0xF2, 0xF8, 0x27, 0x20, 0xF3, 0xF8, 0x27, 0x20, - 0xF4, 0xF8, 0x27, 0x20, 0xF5, 0xF8, 0x27, 0x20, - 0xF6, 0xF8, 0x27, 0x20, 0xF7, 0xF8, 0x27, 0x20, - 0xF8, 0xF8, 0x27, 0x20, 0xF9, 0xF8, 0x27, 0x20, - 0xFA, 0xF8, 0x27, 0x20, 0xFB, 0xF8, 0x27, 0x20, - 0xFC, 0xF8, 0x27, 0x20, 0xFD, 0xF8, 0x27, 0x20, - 0xFE, 0xF8, 0x27, 0x20, 0xFF, 0xF8, 0x27, 0x20, - 0x00, 0xF9, 0x27, 0x20, 0xD7, 0xF8, 0x27, 0x20, - 0x00, 0xF8, 0x27, 0x20, 0x01, 0xF8, 0x27, 0x20, - 0x02, 0xF8, 0x27, 0x20, 0x03, 0xF8, 0x27, 0x20, - 0x04, 0xF8, 0x27, 0x20, 0x05, 0xF8, 0x27, 0x20, - 0x06, 0xF8, 0x27, 0x20, 0x07, 0xF8, 0x27, 0x20, - 0x08, 0xF8, 0x27, 0x20, 0x09, 0xF8, 0x27, 0x20, - 0x0A, 0xF8, 0x27, 0x20, 0x0B, 0xF8, 0x27, 0x20, - 0x0C, 0xF8, 0x27, 0x20, 0x0D, 0xF8, 0x27, 0x20, - 0x0E, 0xF8, 0x27, 0x20, 0x0F, 0xF8, 0x27, 0x20, - 0x10, 0xF8, 0x27, 0x20, 0x11, 0xF8, 0x27, 0x20, - 0x12, 0xF8, 0x27, 0x20, 0x13, 0xF8, 0x27, 0x20, - 0x14, 0xF8, 0x27, 0x20, 0x15, 0xF8, 0x27, 0x20, - 0x15, 0xF8, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, - 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, - 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, - 0x04, 0x05, 0x00, 0x0E, 0x00, 0x0C, 0x20, 0xFD, - 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x08, 0x00, 0x00, 0x05, 0x00, 0x0E, 0x00, 0x10, - 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x09, - 0x00, 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x10, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x4C, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x58, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, - 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, - 0x0E, 0x00, 0x14, 0x20, 0xFF, 0xFF, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, - 0x03, 0x00, 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x88, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x90, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x94, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xA0, 0x21, 0x04, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x20, - 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x60, 0x21, 0x04, 0x30, - 0x08, 0x00, 0x00, 0x00, 0x04, 0x15, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x28, 0x00, - 0x00, 0x18, 0x00, 0x52, 0x01, 0x08, 0x00, 0x05, - 0x00, 0x0A, 0x00, 0xFA, 0x00, 0x1E, 0x00, 0xC8, - 0x00, 0x00, 0x00, 0x9F, 0x00, 0x38, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x03, 0xFF, 0xF9, 0xFD, 0xFE, 0xFE, 0x00, 0xFD, - 0x02, 0x03, 0x02, 0x01, 0x01, 0xFF, 0x03, 0x06, - 0x0C, 0x08, 0x08, 0x0C, 0x06, 0x0A, 0x0B, 0x06, - 0x0B, 0x0A, 0x0C, 0x0A, 0x0A, 0x07, 0x02, 0x05, - 0x07, 0x06, 0x0A, 0x09, 0x09, 0x0C, 0x0C, 0x11, - 0x0B, 0x0D, 0x08, 0x07, 0x09, 0x09, 0x09, 0x08, - 0x06, 0x09, 0xFE, 0xFF, 0xFF, 0x01, 0x06, 0x01, - 0xFD, 0xFB, 0x00, 0x01, 0x04, 0x01, 0x02, 0x05, - 0x04, 0x00, 0x02, 0x02, 0x05, 0x07, 0x05, 0x03, - 0x05, 0x02, 0x0A, 0x06, 0x03, 0x04, 0x00, 0x01, - 0x02, 0x04, 0x01, 0x01, 0xFA, 0xF7, 0xFA, 0xF9, - 0xF6, 0xF7, 0xFD, 0xFE, 0x02, 0xFE, 0xFC, 0xF7, - 0xF9, 0xFB, 0xF7, 0xFB, 0xF5, 0xF8, 0xF8, 0xF9, - 0xEF, 0xEE, 0xF2, 0xEF, 0xF0, 0xED, 0xF2, 0xF7, - 0xF9, 0xFA, 0xF6, 0xF6, 0xF5, 0xF4, 0xF3, 0xEF, - 0xF1, 0xF5, 0xF4, 0xF1, 0xF5, 0xFA, 0xF8, 0xFA, - 0xF9, 0xFA, 0xFE, 0x01, 0x02, 0xFE, 0xFE, 0x03, - 0x01, 0xFC, 0xF9, 0xF7, 0xF6, 0xF4, 0xF9, 0xF7, - 0xF7, 0xF5, 0xF7, 0xFA, 0xFB, 0x00, 0xFC, 0xFD, - 0xFD, 0xF6, 0xF2, 0xF4, 0xED, 0xDC, 0xCE, 0xFF, - 0x05, 0x07, 0x08, 0x0E, 0x0E, 0x0F, 0x0A, 0x0C, - 0x06, 0x05, 0x05, 0xF6, 0xF2, 0xF1, 0xEF, 0xF4, - 0xF6, 0xF4, 0xF5, 0xF6, 0xF7, 0xF5, 0xF8, 0xF8, - 0xF8, 0xF2, 0xF7, 0xF3, 0xF0, 0xF3, 0xF5, 0xFD, - 0xFB, 0xFC, 0xF9, 0xF9, 0xFC, 0xFA, 0xF8, 0xFD, - 0x0B, 0x1C, 0x17, 0x13, 0x14, 0x0F, 0x0D, 0x0C, - 0x0B, 0x0B, 0x0F, 0x0C, 0x0E, 0x10, 0x0E, 0x11, - 0x12, 0x14, 0x1C, 0x1C, 0x20, 0x20, 0x24, 0xF4, - 0xF6, 0xF4, 0xF5, 0xF6, 0xF7, 0xF5, 0xF8, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x02, 0xF0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x09, + 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, + 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, + 0x20, 0x04, 0x30, 0xE5, 0x03, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, + 0xEA, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x4C, 0x20, 0x04, 0x30, 0x0A, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, + 0x04, 0x30, 0x01, 0xDE, 0x01, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, + 0x30, 0x02, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, + 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x08, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x40, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x60, 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x90, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, + 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x30, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xD8, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, + 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x04, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, + 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, + 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, + 0x30, 0x00, 0x00, 0x74, 0x01, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, + 0x74, 0x01, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, + 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, + 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, + 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, + 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, + 0xFF, 0xF9, 0x87, 0x20, 0xBB, 0xF8, 0x87, 0x00, + 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, + 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, + 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x07, 0x20, + 0xBA, 0xF8, 0x07, 0x20, 0xB9, 0xF8, 0x07, 0x20, + 0xB8, 0xF8, 0x07, 0x20, 0xB7, 0xF8, 0x07, 0x20, + 0xB6, 0xF8, 0x07, 0x20, 0xB5, 0xF8, 0x07, 0x20, + 0xB4, 0xF8, 0x07, 0x20, 0xB3, 0xF8, 0x07, 0x20, + 0xB2, 0xF8, 0x07, 0x20, 0xB1, 0xF8, 0x07, 0x22, + 0xB0, 0xF8, 0x07, 0x22, 0xAF, 0xF8, 0x07, 0x22, + 0xAE, 0xF8, 0x07, 0x22, 0xAD, 0xF8, 0x07, 0x22, + 0xAC, 0xF8, 0x07, 0x22, 0xAB, 0xF8, 0x07, 0x22, + 0xAA, 0xF8, 0x07, 0x22, 0xA9, 0xF8, 0x07, 0x22, + 0xA8, 0xF8, 0x07, 0x22, 0xA7, 0xF8, 0x07, 0x22, + 0xA6, 0xF8, 0x07, 0x22, 0xA5, 0xF8, 0x07, 0x22, + 0xA4, 0xF8, 0x07, 0x22, 0xA3, 0xF8, 0x07, 0x22, + 0xA2, 0xF8, 0x07, 0x22, 0xA1, 0xF8, 0x07, 0x22, + 0xA0, 0xF8, 0x07, 0x22, 0x9F, 0xF8, 0x07, 0x22, + 0x9E, 0xF8, 0x07, 0x22, 0x9D, 0xF8, 0x07, 0x22, + 0x9C, 0xF8, 0x07, 0x22, 0x9B, 0xF8, 0x07, 0x22, + 0x9A, 0xF8, 0x07, 0x22, 0x99, 0xF8, 0x07, 0x22, + 0x98, 0xF8, 0x07, 0x22, 0x97, 0xF8, 0x07, 0x22, + 0x96, 0xF8, 0x07, 0x22, 0x95, 0xF8, 0x07, 0x22, + 0x94, 0xF8, 0x07, 0x22, 0x93, 0xF8, 0x07, 0x22, + 0x92, 0xF8, 0x07, 0x22, 0x91, 0xF8, 0x07, 0x22, + 0x90, 0xF8, 0x07, 0x22, 0x8F, 0xF8, 0x07, 0x22, + 0x8E, 0xF8, 0x07, 0x22, 0x8D, 0xF8, 0x07, 0x22, + 0x8C, 0xF8, 0x07, 0x22, 0x8B, 0xF8, 0x07, 0x22, + 0x8A, 0xF8, 0x07, 0x22, 0x89, 0xF8, 0x07, 0x22, + 0x88, 0xF8, 0x07, 0x22, 0x87, 0xF8, 0x07, 0x22, + 0x86, 0xF8, 0x07, 0x22, 0x85, 0xF8, 0x07, 0x22, + 0x84, 0xF8, 0x07, 0x22, 0x83, 0xF8, 0x07, 0x22, + 0x82, 0xF8, 0x07, 0x22, 0x81, 0xF8, 0x07, 0x22, + 0x80, 0xF8, 0x07, 0x22, 0x7F, 0xF8, 0x07, 0x22, + 0x7E, 0xF8, 0x07, 0x22, 0x7D, 0xF8, 0x07, 0x22, + 0x7C, 0xF8, 0x07, 0x22, 0x7B, 0xF8, 0x07, 0x22, + 0x7A, 0xF8, 0x07, 0x22, 0x79, 0xF8, 0x07, 0x22, + 0x78, 0xF8, 0x07, 0x22, 0x77, 0xF8, 0x07, 0x22, + 0x76, 0xF8, 0x07, 0x22, 0x75, 0xF8, 0x07, 0x22, + 0x74, 0xF8, 0x07, 0x22, 0x73, 0xF8, 0x07, 0x22, + 0x72, 0xF8, 0x07, 0x22, 0x71, 0xF8, 0x07, 0x22, + 0x70, 0xF8, 0x07, 0x22, 0x6F, 0xF8, 0x07, 0x22, + 0x6E, 0xF8, 0x07, 0x22, 0x6D, 0xF8, 0x07, 0x22, + 0x6C, 0xF8, 0x07, 0x22, 0x6B, 0xF8, 0x07, 0x22, + 0x6A, 0xF8, 0x07, 0x22, 0x69, 0xF8, 0x07, 0x22, + 0x68, 0xF8, 0x07, 0x22, 0x67, 0xF8, 0x07, 0x22, + 0x66, 0xF8, 0x07, 0x22, 0x65, 0xF8, 0x07, 0x22, + 0x64, 0xF8, 0x07, 0x22, 0x63, 0xF8, 0x07, 0x22, + 0x62, 0xF8, 0x07, 0x22, 0x61, 0xF8, 0x07, 0x22, + 0x60, 0xF8, 0x07, 0x22, 0x5F, 0xF8, 0x07, 0x22, + 0x5E, 0xF8, 0x07, 0x22, 0x5D, 0xF8, 0x07, 0x22, + 0x5C, 0xF8, 0x07, 0x22, 0x5B, 0xF8, 0x07, 0x22, + 0x5A, 0xF8, 0x07, 0x22, 0x59, 0xF8, 0x07, 0x22, + 0x58, 0xF8, 0x07, 0x22, 0x57, 0xF8, 0x07, 0x22, + 0x56, 0xF8, 0x07, 0x22, 0x55, 0xF8, 0x07, 0x22, + 0x54, 0xF8, 0x07, 0x22, 0x53, 0xF8, 0x07, 0x22, + 0x52, 0xF8, 0x07, 0x22, 0x51, 0xF8, 0x07, 0x22, + 0x50, 0xF8, 0x07, 0x22, 0x4F, 0xF8, 0x07, 0x22, + 0x4E, 0xF8, 0x07, 0x22, 0x4D, 0xF8, 0x07, 0x22, + 0x4C, 0xF8, 0x07, 0x22, 0x4B, 0xF8, 0x07, 0x22, + 0x4A, 0xF8, 0x07, 0x22, 0x49, 0xF8, 0x07, 0x22, + 0x48, 0xF8, 0x07, 0x22, 0x47, 0xF8, 0x07, 0x22, + 0x46, 0xF8, 0x07, 0x22, 0x45, 0xF8, 0x07, 0x22, + 0x44, 0xF8, 0x07, 0x22, 0x43, 0xF8, 0x07, 0x22, + 0x42, 0xF8, 0x07, 0x22, 0x41, 0xF8, 0x07, 0x22, + 0x40, 0xF8, 0x07, 0x22, 0x3F, 0xF8, 0x07, 0x22, + 0x3E, 0xF8, 0x07, 0x22, 0x3D, 0xF8, 0x07, 0x22, + 0x3C, 0xF8, 0x07, 0x22, 0x3B, 0xF8, 0x07, 0x22, + 0x3A, 0xF8, 0x07, 0x22, 0x39, 0xF8, 0x07, 0x22, + 0x38, 0xF8, 0x07, 0x22, 0x37, 0xF8, 0x07, 0x22, + 0x36, 0xF8, 0x07, 0x22, 0x35, 0xF8, 0x07, 0x22, + 0x34, 0xF8, 0x07, 0x22, 0x33, 0xF8, 0x07, 0x22, + 0x32, 0xF8, 0x07, 0x22, 0x31, 0xF8, 0x07, 0x22, + 0x30, 0xF8, 0x07, 0x22, 0x2F, 0xF8, 0x07, 0x22, + 0x2E, 0xF8, 0x07, 0x22, 0x2D, 0xF8, 0x07, 0x22, + 0x2C, 0xF8, 0x07, 0x22, 0x2B, 0xF8, 0x07, 0x22, + 0x2A, 0xF8, 0x07, 0x22, 0x29, 0xF8, 0x07, 0x22, + 0x28, 0xF8, 0x07, 0x22, 0x27, 0xF8, 0x07, 0x22, + 0x26, 0xF8, 0x07, 0x22, 0x25, 0xF8, 0x07, 0x22, + 0x24, 0xF8, 0x07, 0x22, 0x23, 0xF8, 0x07, 0x20, + 0x22, 0xF8, 0x07, 0x20, 0x21, 0xF8, 0x07, 0x20, + 0x20, 0xF8, 0x07, 0x20, 0x1F, 0xF8, 0x07, 0x20, + 0x1E, 0xF8, 0x07, 0x20, 0x1D, 0xF8, 0x07, 0x20, + 0x1C, 0xF8, 0x07, 0x20, 0x1C, 0xF8, 0x07, 0x00, + 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, + 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, + 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, + 0xD8, 0xF8, 0x27, 0x20, 0xD9, 0xF8, 0x27, 0x20, + 0xDA, 0xF8, 0x27, 0x20, 0xDB, 0xF8, 0x27, 0x20, + 0xDC, 0xF8, 0x27, 0x20, 0xDD, 0xF8, 0x27, 0x20, + 0xDE, 0xF8, 0x27, 0x20, 0xDF, 0xF8, 0x27, 0x20, + 0xE0, 0xF8, 0x27, 0x20, 0xE1, 0xF8, 0x27, 0x20, + 0xE2, 0xF8, 0x27, 0x20, 0xE3, 0xF8, 0x27, 0x20, + 0xE4, 0xF8, 0x27, 0x20, 0xE5, 0xF8, 0x27, 0x20, + 0xE6, 0xF8, 0x27, 0x20, 0xE7, 0xF8, 0x27, 0x20, + 0xE8, 0xF8, 0x27, 0x20, 0xE9, 0xF8, 0x27, 0x20, + 0xEA, 0xF8, 0x27, 0x20, 0xEB, 0xF8, 0x27, 0x20, + 0xEC, 0xF8, 0x27, 0x20, 0xED, 0xF8, 0x27, 0x20, + 0xEE, 0xF8, 0x27, 0x20, 0xEF, 0xF8, 0x27, 0x20, + 0xF0, 0xF8, 0x27, 0x20, 0xF1, 0xF8, 0x27, 0x20, + 0xF2, 0xF8, 0x27, 0x20, 0xF3, 0xF8, 0x27, 0x20, + 0xF4, 0xF8, 0x27, 0x20, 0xF5, 0xF8, 0x27, 0x20, + 0xF6, 0xF8, 0x27, 0x20, 0xF7, 0xF8, 0x27, 0x20, + 0xF8, 0xF8, 0x27, 0x20, 0xF9, 0xF8, 0x27, 0x20, + 0xFA, 0xF8, 0x27, 0x20, 0xFB, 0xF8, 0x27, 0x20, + 0xFC, 0xF8, 0x27, 0x20, 0xFD, 0xF8, 0x27, 0x20, + 0xFE, 0xF8, 0x27, 0x20, 0xFF, 0xF8, 0x27, 0x20, + 0x00, 0xF9, 0x27, 0x20, 0xD7, 0xF8, 0x27, 0x20, + 0x00, 0xF8, 0x27, 0x20, 0x01, 0xF8, 0x27, 0x20, + 0x02, 0xF8, 0x27, 0x20, 0x03, 0xF8, 0x27, 0x20, + 0x04, 0xF8, 0x27, 0x20, 0x05, 0xF8, 0x27, 0x20, + 0x06, 0xF8, 0x27, 0x20, 0x07, 0xF8, 0x27, 0x20, + 0x08, 0xF8, 0x27, 0x20, 0x09, 0xF8, 0x27, 0x20, + 0x0A, 0xF8, 0x27, 0x20, 0x0B, 0xF8, 0x27, 0x20, + 0x0C, 0xF8, 0x27, 0x20, 0x0D, 0xF8, 0x27, 0x20, + 0x0E, 0xF8, 0x27, 0x20, 0x0F, 0xF8, 0x27, 0x20, + 0x10, 0xF8, 0x27, 0x20, 0x11, 0xF8, 0x27, 0x20, + 0x12, 0xF8, 0x27, 0x20, 0x13, 0xF8, 0x27, 0x20, + 0x14, 0xF8, 0x27, 0x20, 0x15, 0xF8, 0x27, 0x20, + 0x15, 0xF8, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, + 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, + 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, + 0x04, 0x05, 0x00, 0x0E, 0x00, 0x0C, 0x20, 0xFD, + 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x08, 0x00, 0x00, 0x05, 0x00, 0x0E, 0x00, 0x10, + 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x09, + 0x00, 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x10, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x4C, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x58, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, + 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, + 0x0E, 0x00, 0x14, 0x20, 0xFF, 0xFF, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, + 0x03, 0x00, 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x88, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x90, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x94, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xA0, 0x21, 0x04, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x20, + 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x60, 0x21, 0x04, 0x30, + 0x08, 0x00, 0x00, 0x00, 0x04, 0x15, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x28, 0x00, + 0x00, 0x18, 0x00, 0x52, 0x01, 0x08, 0x00, 0x05, + 0x00, 0x0A, 0x00, 0xFA, 0x00, 0x1E, 0x00, 0xC8, + 0x00, 0x00, 0x00, 0x9F, 0x00, 0x38, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x03, 0xFF, 0xF9, 0xFD, 0xFE, 0xFE, 0x00, 0xFD, + 0x02, 0x03, 0x02, 0x01, 0x01, 0xFF, 0x03, 0x06, + 0x0C, 0x08, 0x08, 0x0C, 0x06, 0x0A, 0x0B, 0x06, + 0x0B, 0x0A, 0x0C, 0x0A, 0x0A, 0x07, 0x02, 0x05, + 0x07, 0x06, 0x0A, 0x09, 0x09, 0x0C, 0x0C, 0x11, + 0x0B, 0x0D, 0x08, 0x07, 0x09, 0x09, 0x09, 0x08, + 0x06, 0x09, 0xFE, 0xFF, 0xFF, 0x01, 0x06, 0x01, + 0xFD, 0xFB, 0x00, 0x01, 0x04, 0x01, 0x02, 0x05, + 0x04, 0x00, 0x02, 0x02, 0x05, 0x07, 0x05, 0x03, + 0x05, 0x02, 0x0A, 0x06, 0x03, 0x04, 0x00, 0x01, + 0x02, 0x04, 0x01, 0x01, 0xFA, 0xF7, 0xFA, 0xF9, + 0xF6, 0xF7, 0xFD, 0xFE, 0x02, 0xFE, 0xFC, 0xF7, + 0xF9, 0xFB, 0xF7, 0xFB, 0xF5, 0xF8, 0xF8, 0xF9, + 0xEF, 0xEE, 0xF2, 0xEF, 0xF0, 0xED, 0xF2, 0xF7, + 0xF9, 0xFA, 0xF6, 0xF6, 0xF5, 0xF4, 0xF3, 0xEF, + 0xF1, 0xF5, 0xF4, 0xF1, 0xF5, 0xFA, 0xF8, 0xFA, + 0xF9, 0xFA, 0xFE, 0x01, 0x02, 0xFE, 0xFE, 0x03, + 0x01, 0xFC, 0xF9, 0xF7, 0xF6, 0xF4, 0xF9, 0xF7, + 0xF7, 0xF5, 0xF7, 0xFA, 0xFB, 0x00, 0xFC, 0xFD, + 0xFD, 0xF6, 0xF2, 0xF4, 0xED, 0xDC, 0xCE, 0xFF, + 0x05, 0x07, 0x08, 0x0E, 0x0E, 0x0F, 0x0A, 0x0C, + 0x06, 0x05, 0x05, 0xF6, 0xF2, 0xF1, 0xEF, 0xF4, + 0xF6, 0xF4, 0xF5, 0xF6, 0xF7, 0xF5, 0xF8, 0xF8, + 0xF8, 0xF2, 0xF7, 0xF3, 0xF0, 0xF3, 0xF5, 0xFD, + 0xFB, 0xFC, 0xF9, 0xF9, 0xFC, 0xFA, 0xF8, 0xFD, + 0x0B, 0x1C, 0x17, 0x13, 0x14, 0x0F, 0x0D, 0x0C, + 0x0B, 0x0B, 0x0F, 0x0C, 0x0E, 0x10, 0x0E, 0x11, + 0x12, 0x14, 0x1C, 0x1C, 0x20, 0x20, 0x24, 0xF4, + 0xF6, 0xF4, 0xF5, 0xF6, 0xF7, 0xF5, 0xF8, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, }; static unsigned char vfs5011_cmd_04[] = { /* 1 B */ - 0x04, + 0x04, }; static unsigned char vfs5011_prepare_00[] = { /* 578 B */ - 0x06, 0x9C, 0xF1, 0x9D, 0x71, 0xC3, 0x13, 0xDF, - 0x5F, 0xE4, 0x7A, 0x1F, 0xC7, 0x17, 0x53, 0x9A, - 0x1A, 0xA1, 0xD7, 0xB6, 0x6E, 0xBE, 0xDF, 0x1F, - 0x9F, 0x44, 0x42, 0x22, 0xFA, 0x2A, 0x6A, 0xAB, - 0x2B, 0xF0, 0x56, 0x39, 0xE3, 0x7B, 0x53, 0x9A, - 0x1A, 0xA1, 0xDB, 0xBA, 0x62, 0xB2, 0xE4, 0x65, - 0xE5, 0xDB, 0x68, 0x04, 0x79, 0x98, 0xDE, 0x8F, - 0x23, 0xFB, 0xEC, 0xAD, 0x76, 0xCA, 0xA2, 0xEB, - 0x61, 0x38, 0xC7, 0xAB, 0x6E, 0x2E, 0x78, 0xF9, - 0x79, 0x13, 0x8A, 0xE5, 0x90, 0x22, 0x63, 0x8D, - 0x0E, 0x93, 0x25, 0x49, 0x5A, 0xC8, 0xA3, 0xD8, - 0x7E, 0xAE, 0x12, 0xF6, 0x2C, 0x1C, 0xFC, 0x48, - 0x4F, 0x0E, 0x48, 0x22, 0xFB, 0x4B, 0xCE, 0x7E, - 0xDB, 0x2D, 0x91, 0xE0, 0xC8, 0x78, 0x2E, 0xAF, - 0x2F, 0xD4, 0x03, 0x6F, 0x12, 0x59, 0xC6, 0x26, - 0x40, 0x88, 0x2E, 0x62, 0xBA, 0x06, 0x6C, 0xC9, - 0x7A, 0x84, 0x93, 0xCF, 0x14, 0x15, 0x44, 0x87, - 0xE2, 0x09, 0x97, 0xE6, 0xCE, 0x7E, 0x28, 0xA9, - 0x29, 0x53, 0xD7, 0xB8, 0xD1, 0x53, 0x30, 0x15, - 0x6E, 0x95, 0x3E, 0xA2, 0x7A, 0xCA, 0x9C, 0x1D, - 0x9D, 0xEB, 0x5F, 0x15, 0xEF, 0x48, 0x34, 0xCC, - 0xCB, 0x02, 0xA6, 0xD6, 0xA7, 0x80, 0xF2, 0x3F, - 0x7E, 0x96, 0x23, 0xAE, 0x42, 0xF1, 0x29, 0xF5, - 0xAD, 0x5A, 0x35, 0x57, 0x36, 0xAA, 0xAF, 0x97, - 0xE8, 0x1E, 0xA2, 0xD3, 0xFB, 0x4B, 0x1D, 0x9C, - 0x1C, 0x06, 0x84, 0xEB, 0x9E, 0x2C, 0xD4, 0x18, - 0x94, 0x44, 0x7E, 0x4B, 0x12, 0x91, 0xF2, 0x8B, - 0x07, 0x45, 0xDB, 0x52, 0xBB, 0x2E, 0x53, 0x63, - 0xE3, 0x38, 0xB8, 0x95, 0x4D, 0x9B, 0xCF, 0x07, - 0x05, 0xDD, 0x4C, 0xE2, 0x39, 0xAF, 0xA9, 0x51, - 0xDB, 0xAD, 0x19, 0xC8, 0x13, 0x6E, 0x0A, 0x2F, - 0xEA, 0x12, 0xB9, 0x25, 0x55, 0xB6, 0x64, 0x04, - 0x7F, 0x14, 0x6E, 0x12, 0x08, 0xFB, 0xBD, 0xBD, - 0x1D, 0xC6, 0xE2, 0x84, 0x50, 0x20, 0x60, 0xA0, - 0x90, 0xD2, 0x74, 0x8A, 0x18, 0xA4, 0xD9, 0xE9, - 0x69, 0xB2, 0x1E, 0x73, 0xAB, 0x1B, 0x7B, 0xBB, - 0x3B, 0xE0, 0x42, 0x23, 0xF9, 0x29, 0x49, 0x89, - 0x09, 0xD2, 0x4C, 0x29, 0xF1, 0x21, 0x65, 0xAC, - 0x2C, 0x97, 0x30, 0x6C, 0xB4, 0x04, 0xF4, 0x3D, - 0xBD, 0x06, 0xA0, 0xC6, 0x1E, 0xCE, 0x7E, 0xB3, - 0x33, 0x88, 0x2E, 0x43, 0x9B, 0x2B, 0x37, 0xF0, - 0x70, 0xCB, 0x91, 0xF1, 0x2B, 0xFB, 0x8B, 0x48, - 0xCA, 0x39, 0x97, 0xFB, 0x21, 0xB9, 0xCD, 0x0E, - 0x8C, 0x7F, 0x8D, 0xEC, 0x36, 0xE6, 0xEA, 0x27, - 0xA5, 0x1E, 0x40, 0x2A, 0xF2, 0x22, 0xCA, 0x07, - 0x85, 0x3E, 0xC8, 0xAE, 0x76, 0xA6, 0xF0, 0x71, - 0xF1, 0xAB, 0x6B, 0x04, 0x6D, 0xA9, 0xCA, 0x06, - 0x2C, 0x66, 0xA5, 0xCA, 0xB0, 0x4B, 0x2B, 0x62, - 0xEB, 0xD5, 0x61, 0x0D, 0xF0, 0x46, 0x26, 0xC3, - 0x44, 0x9F, 0x0C, 0x63, 0xBB, 0xAA, 0xBD, 0x7E, - 0xF2, 0x74, 0x00, 0x66, 0x2B, 0x7A, 0x62, 0xA1, - 0x07, 0x80, 0x33, 0x8D, 0x1F, 0xF7, 0x45, 0xCB, - 0x5E, 0x24, 0xEB, 0x84, 0xED, 0x27, 0x44, 0x61, - 0xFF, 0x0C, 0xA7, 0x3B, 0xE3, 0x53, 0x05, 0x84, - 0x04, 0xEE, 0x23, 0x4C, 0xB5, 0x79, 0x1A, 0xF3, - 0xA0, 0x66, 0x20, 0x4C, 0x94, 0x24, 0x72, 0xF3, - 0x73, 0x39, 0xF8, 0x97, 0xDD, 0x64, 0x54, 0xF2, - 0x6B, 0xBA, 0xAD, 0xBC, 0x67, 0x66, 0x78, 0xBB, - 0x5E, 0x6D, 0xFB, 0x8A, 0xA2, 0x74, 0x3D, 0xF5, - 0xD4, 0x72, 0xC7, 0x1A, 0xBD, 0x0E, 0x0B, 0x2C, - 0x8C, 0x4A, 0x0C, 0x60, 0xB8, 0x08, 0x5E, 0xDF, - 0x5F, 0x05, 0x33, 0x5C, 0xB5, 0x7E, 0x1D, 0xFC, - 0xFD, 0x25, 0xBA, 0x95, 0xC4, 0xA7, 0xDA, 0xEA, - 0x6A, 0xB1, 0x31, 0x1C, 0xC4, 0xE5, 0x07, 0xC4, - 0xC5, 0x9D, 0x28, 0xCD, 0x3C, 0xE9, 0x89, 0x49, - 0xD4, 0xFF, 0x7F, 0x52, 0x8A, 0x9B, 0x7F, 0xBC, - 0x8E, 0xF5, 0xCF, 0x0B, 0xD9, 0x49, 0x48, 0x88, - 0x80, 0x71, 0x7D, 0xAB, 0xEF, 0x47, 0x2B, 0xF7, - 0x7B, 0x2D, 0x79, 0x3F, 0xCF, 0xBF, 0xFF, 0x3F, - 0x6D, 0xF8, 0x42, 0xEC, 0x7F, 0xE8, 0xED, 0x42, - 0xE6, 0x1D, 0x4D, 0x32, 0xFA, 0x6A, 0x0A, 0xD7, - 0xA7, 0x7C, 0xCB, 0xA7, 0x7B, 0xCB, 0xBF, 0x71, - 0xF3, 0x48, + 0x06, 0x9C, 0xF1, 0x9D, 0x71, 0xC3, 0x13, 0xDF, + 0x5F, 0xE4, 0x7A, 0x1F, 0xC7, 0x17, 0x53, 0x9A, + 0x1A, 0xA1, 0xD7, 0xB6, 0x6E, 0xBE, 0xDF, 0x1F, + 0x9F, 0x44, 0x42, 0x22, 0xFA, 0x2A, 0x6A, 0xAB, + 0x2B, 0xF0, 0x56, 0x39, 0xE3, 0x7B, 0x53, 0x9A, + 0x1A, 0xA1, 0xDB, 0xBA, 0x62, 0xB2, 0xE4, 0x65, + 0xE5, 0xDB, 0x68, 0x04, 0x79, 0x98, 0xDE, 0x8F, + 0x23, 0xFB, 0xEC, 0xAD, 0x76, 0xCA, 0xA2, 0xEB, + 0x61, 0x38, 0xC7, 0xAB, 0x6E, 0x2E, 0x78, 0xF9, + 0x79, 0x13, 0x8A, 0xE5, 0x90, 0x22, 0x63, 0x8D, + 0x0E, 0x93, 0x25, 0x49, 0x5A, 0xC8, 0xA3, 0xD8, + 0x7E, 0xAE, 0x12, 0xF6, 0x2C, 0x1C, 0xFC, 0x48, + 0x4F, 0x0E, 0x48, 0x22, 0xFB, 0x4B, 0xCE, 0x7E, + 0xDB, 0x2D, 0x91, 0xE0, 0xC8, 0x78, 0x2E, 0xAF, + 0x2F, 0xD4, 0x03, 0x6F, 0x12, 0x59, 0xC6, 0x26, + 0x40, 0x88, 0x2E, 0x62, 0xBA, 0x06, 0x6C, 0xC9, + 0x7A, 0x84, 0x93, 0xCF, 0x14, 0x15, 0x44, 0x87, + 0xE2, 0x09, 0x97, 0xE6, 0xCE, 0x7E, 0x28, 0xA9, + 0x29, 0x53, 0xD7, 0xB8, 0xD1, 0x53, 0x30, 0x15, + 0x6E, 0x95, 0x3E, 0xA2, 0x7A, 0xCA, 0x9C, 0x1D, + 0x9D, 0xEB, 0x5F, 0x15, 0xEF, 0x48, 0x34, 0xCC, + 0xCB, 0x02, 0xA6, 0xD6, 0xA7, 0x80, 0xF2, 0x3F, + 0x7E, 0x96, 0x23, 0xAE, 0x42, 0xF1, 0x29, 0xF5, + 0xAD, 0x5A, 0x35, 0x57, 0x36, 0xAA, 0xAF, 0x97, + 0xE8, 0x1E, 0xA2, 0xD3, 0xFB, 0x4B, 0x1D, 0x9C, + 0x1C, 0x06, 0x84, 0xEB, 0x9E, 0x2C, 0xD4, 0x18, + 0x94, 0x44, 0x7E, 0x4B, 0x12, 0x91, 0xF2, 0x8B, + 0x07, 0x45, 0xDB, 0x52, 0xBB, 0x2E, 0x53, 0x63, + 0xE3, 0x38, 0xB8, 0x95, 0x4D, 0x9B, 0xCF, 0x07, + 0x05, 0xDD, 0x4C, 0xE2, 0x39, 0xAF, 0xA9, 0x51, + 0xDB, 0xAD, 0x19, 0xC8, 0x13, 0x6E, 0x0A, 0x2F, + 0xEA, 0x12, 0xB9, 0x25, 0x55, 0xB6, 0x64, 0x04, + 0x7F, 0x14, 0x6E, 0x12, 0x08, 0xFB, 0xBD, 0xBD, + 0x1D, 0xC6, 0xE2, 0x84, 0x50, 0x20, 0x60, 0xA0, + 0x90, 0xD2, 0x74, 0x8A, 0x18, 0xA4, 0xD9, 0xE9, + 0x69, 0xB2, 0x1E, 0x73, 0xAB, 0x1B, 0x7B, 0xBB, + 0x3B, 0xE0, 0x42, 0x23, 0xF9, 0x29, 0x49, 0x89, + 0x09, 0xD2, 0x4C, 0x29, 0xF1, 0x21, 0x65, 0xAC, + 0x2C, 0x97, 0x30, 0x6C, 0xB4, 0x04, 0xF4, 0x3D, + 0xBD, 0x06, 0xA0, 0xC6, 0x1E, 0xCE, 0x7E, 0xB3, + 0x33, 0x88, 0x2E, 0x43, 0x9B, 0x2B, 0x37, 0xF0, + 0x70, 0xCB, 0x91, 0xF1, 0x2B, 0xFB, 0x8B, 0x48, + 0xCA, 0x39, 0x97, 0xFB, 0x21, 0xB9, 0xCD, 0x0E, + 0x8C, 0x7F, 0x8D, 0xEC, 0x36, 0xE6, 0xEA, 0x27, + 0xA5, 0x1E, 0x40, 0x2A, 0xF2, 0x22, 0xCA, 0x07, + 0x85, 0x3E, 0xC8, 0xAE, 0x76, 0xA6, 0xF0, 0x71, + 0xF1, 0xAB, 0x6B, 0x04, 0x6D, 0xA9, 0xCA, 0x06, + 0x2C, 0x66, 0xA5, 0xCA, 0xB0, 0x4B, 0x2B, 0x62, + 0xEB, 0xD5, 0x61, 0x0D, 0xF0, 0x46, 0x26, 0xC3, + 0x44, 0x9F, 0x0C, 0x63, 0xBB, 0xAA, 0xBD, 0x7E, + 0xF2, 0x74, 0x00, 0x66, 0x2B, 0x7A, 0x62, 0xA1, + 0x07, 0x80, 0x33, 0x8D, 0x1F, 0xF7, 0x45, 0xCB, + 0x5E, 0x24, 0xEB, 0x84, 0xED, 0x27, 0x44, 0x61, + 0xFF, 0x0C, 0xA7, 0x3B, 0xE3, 0x53, 0x05, 0x84, + 0x04, 0xEE, 0x23, 0x4C, 0xB5, 0x79, 0x1A, 0xF3, + 0xA0, 0x66, 0x20, 0x4C, 0x94, 0x24, 0x72, 0xF3, + 0x73, 0x39, 0xF8, 0x97, 0xDD, 0x64, 0x54, 0xF2, + 0x6B, 0xBA, 0xAD, 0xBC, 0x67, 0x66, 0x78, 0xBB, + 0x5E, 0x6D, 0xFB, 0x8A, 0xA2, 0x74, 0x3D, 0xF5, + 0xD4, 0x72, 0xC7, 0x1A, 0xBD, 0x0E, 0x0B, 0x2C, + 0x8C, 0x4A, 0x0C, 0x60, 0xB8, 0x08, 0x5E, 0xDF, + 0x5F, 0x05, 0x33, 0x5C, 0xB5, 0x7E, 0x1D, 0xFC, + 0xFD, 0x25, 0xBA, 0x95, 0xC4, 0xA7, 0xDA, 0xEA, + 0x6A, 0xB1, 0x31, 0x1C, 0xC4, 0xE5, 0x07, 0xC4, + 0xC5, 0x9D, 0x28, 0xCD, 0x3C, 0xE9, 0x89, 0x49, + 0xD4, 0xFF, 0x7F, 0x52, 0x8A, 0x9B, 0x7F, 0xBC, + 0x8E, 0xF5, 0xCF, 0x0B, 0xD9, 0x49, 0x48, 0x88, + 0x80, 0x71, 0x7D, 0xAB, 0xEF, 0x47, 0x2B, 0xF7, + 0x7B, 0x2D, 0x79, 0x3F, 0xCF, 0xBF, 0xFF, 0x3F, + 0x6D, 0xF8, 0x42, 0xEC, 0x7F, 0xE8, 0xED, 0x42, + 0xE6, 0x1D, 0x4D, 0x32, 0xFA, 0x6A, 0x0A, 0xD7, + 0xA7, 0x7C, 0xCB, 0xA7, 0x7B, 0xCB, 0xBF, 0x71, + 0xF3, 0x48, }; static unsigned char vfs5011_prepare_01[] = { /* 3794 B */ - 0x06, 0x6B, 0x06, 0x6A, 0x76, 0xC8, 0x18, 0xD4, - 0x54, 0xEF, 0x71, 0x14, 0xCC, 0x1C, 0x58, 0x91, - 0x11, 0xAA, 0x80, 0xF4, 0x2C, 0xFC, 0x9F, 0x5F, - 0xDF, 0x04, 0x02, 0x62, 0xBA, 0x6A, 0x5A, 0x97, - 0x17, 0xCC, 0x46, 0x22, 0xFA, 0x2A, 0xBE, 0x03, - 0x87, 0x3C, 0x9E, 0xFE, 0x26, 0xF6, 0x96, 0x7E, - 0xFA, 0x11, 0x27, 0x66, 0xBA, 0x3A, 0x5A, 0xBA, - 0x3E, 0xD5, 0x4F, 0x03, 0xDF, 0x5F, 0x7F, 0x9F, - 0x1B, 0xF0, 0xA2, 0xEF, 0x33, 0xB3, 0xD3, 0x13, - 0x93, 0x70, 0xFA, 0x96, 0x4E, 0xC6, 0xA6, 0xC6, - 0x46, 0xA5, 0x2F, 0xE3, 0x3B, 0xB3, 0xD3, 0x33, - 0xB3, 0x50, 0xE8, 0xA4, 0x7C, 0xF4, 0x94, 0x14, - 0x94, 0x77, 0xC9, 0xE5, 0x3D, 0xB5, 0xD5, 0x75, - 0xF5, 0x16, 0xA8, 0xA4, 0x7C, 0xF4, 0x94, 0xD4, - 0x54, 0xB7, 0x09, 0xE5, 0x3D, 0xB5, 0x2D, 0xF4, - 0x74, 0xCF, 0x29, 0x5C, 0x84, 0x54, 0x14, 0xAA, - 0x2E, 0x95, 0xF7, 0xE0, 0x3C, 0xEC, 0x8C, 0x52, - 0xD6, 0x3D, 0x7B, 0x0E, 0xD6, 0x06, 0x82, 0x49, - 0xC9, 0x72, 0x7C, 0x18, 0xC0, 0x10, 0x10, 0xF6, - 0x72, 0xC9, 0xC3, 0xA8, 0x70, 0xA0, 0xD8, 0x77, - 0xF3, 0x48, 0x06, 0x04, 0xD8, 0x08, 0x90, 0x5B, - 0xDB, 0x60, 0x36, 0x43, 0x9B, 0x4B, 0xD4, 0xE3, - 0x9C, 0xB8, 0xF1, 0x72, 0x55, 0x1A, 0x8E, 0x57, - 0xD7, 0x6C, 0xDA, 0xBE, 0x66, 0xD6, 0xEA, 0x3D, - 0xBF, 0x04, 0xB2, 0xCE, 0x16, 0xA6, 0x06, 0xDE, - 0x5E, 0xE5, 0xB7, 0xC3, 0x1B, 0xCB, 0x47, 0x9F, - 0x1F, 0xA4, 0x3E, 0x5B, 0x83, 0x53, 0x53, 0x8A, - 0x0A, 0xB1, 0x93, 0xF9, 0x21, 0xF1, 0x31, 0xE6, - 0x64, 0xDF, 0x95, 0xE0, 0x38, 0xE8, 0xB4, 0x6D, - 0xED, 0x56, 0x1D, 0x8E, 0x56, 0xE6, 0x79, 0xB9, - 0xC6, 0xE2, 0x62, 0x4F, 0x97, 0x02, 0x40, 0x80, - 0x65, 0xB8, 0x0E, 0x07, 0xC2, 0x72, 0x37, 0xBE, - 0x3E, 0x00, 0xF2, 0xB8, 0xF1, 0x6D, 0x0E, 0x6F, - 0xC2, 0x1A, 0xA0, 0xC4, 0x95, 0x2F, 0xCD, 0x44, - 0xC4, 0x02, 0x44, 0x28, 0xF0, 0x40, 0x16, 0x97, - 0x17, 0x7D, 0xE4, 0x8B, 0xFE, 0x4C, 0x0D, 0xE3, - 0x60, 0xFD, 0x4B, 0x27, 0x34, 0xA6, 0xCD, 0xB6, - 0x10, 0xC0, 0x7C, 0x98, 0x42, 0x72, 0x92, 0x26, - 0x21, 0x60, 0x26, 0x4C, 0x95, 0x25, 0xA0, 0x03, - 0xA6, 0x50, 0xEC, 0x9D, 0xB5, 0x05, 0x53, 0xD2, - 0x52, 0xA9, 0x7E, 0x12, 0x2F, 0x65, 0xFA, 0x1A, - 0x7C, 0xB4, 0x12, 0x5E, 0x86, 0x3A, 0x50, 0xF5, - 0x53, 0xAD, 0xBA, 0xE6, 0x3D, 0x3C, 0x6D, 0xAE, - 0xCB, 0x33, 0xAD, 0xDC, 0xF4, 0x44, 0x12, 0x93, - 0x13, 0xF9, 0x7D, 0x12, 0xEB, 0x68, 0x0B, 0xE2, - 0x21, 0xE7, 0xA1, 0xCD, 0x15, 0xA5, 0xF3, 0x72, - 0xF2, 0xAB, 0x1F, 0x7E, 0xAA, 0x01, 0xE1, 0xA1, - 0x25, 0xA8, 0x06, 0x6D, 0xB9, 0x0C, 0x60, 0xA6, - 0x64, 0xAD, 0x15, 0x65, 0xBA, 0x30, 0x14, 0x66, - 0x22, 0x78, 0xFC, 0x94, 0x4C, 0x4E, 0x25, 0x9B, - 0xD9, 0x06, 0xB1, 0xEA, 0x89, 0x35, 0x62, 0x1E, - 0x8F, 0x69, 0xD4, 0x7F, 0x1C, 0xA0, 0xFD, 0x31, - 0x77, 0xAD, 0x1B, 0x40, 0xA4, 0x10, 0xB7, 0xCC, - 0x4D, 0xAB, 0x16, 0xD7, 0x0C, 0x01, 0x62, 0x87, - 0xBF, 0x4C, 0x50, 0x5A, 0xD8, 0x3B, 0x50, 0xE7, - 0x2C, 0xB3, 0xB7, 0x1F, 0x46, 0xA0, 0x57, 0x6B, - 0x46, 0x98, 0x93, 0xFA, 0xC7, 0xC1, 0x89, 0x45, - 0xDE, 0xD7, 0xC3, 0xC3, 0xBB, 0xCF, 0xEE, 0xEE, - 0xA8, 0xB3, 0xDF, 0x61, 0x4B, 0xE6, 0x04, 0x04, - 0x40, 0xDA, 0xAC, 0x43, 0xDA, 0x9A, 0x15, 0x25, - 0x45, 0x7D, 0xEA, 0x0C, 0x3A, 0x7A, 0xD4, 0x87, - 0xC5, 0x43, 0x77, 0x1D, 0xC6, 0x76, 0xD4, 0xB6, - 0x5A, 0x4B, 0x3F, 0x91, 0x55, 0x98, 0xC2, 0xCE, - 0x8C, 0x5B, 0xED, 0x53, 0x99, 0x20, 0x6D, 0xA6, - 0xF1, 0x96, 0x21, 0x41, 0xBB, 0x16, 0x86, 0x46, - 0xC6, 0x1D, 0x9D, 0xB0, 0x68, 0x69, 0x3D, 0xFE, - 0xC6, 0x16, 0x2C, 0x2B, 0x51, 0x40, 0x40, 0x2A, - 0x01, 0xBF, 0xB3, 0xFF, 0x8A, 0x38, 0x3D, 0x51, - 0xF4, 0x32, 0x74, 0x18, 0xC0, 0x70, 0x26, 0xA7, - 0x27, 0x5D, 0xDE, 0xB1, 0xD8, 0x5E, 0x3D, 0x30, - 0xB2, 0x0C, 0xEC, 0xA5, 0xCC, 0x44, 0x27, 0xC7, - 0x6D, 0x16, 0x01, 0x5A, 0x81, 0xFC, 0x9E, 0x3B, - 0xEE, 0x10, 0x17, 0x41, 0x9A, 0x0A, 0x50, 0x30, - 0x72, 0x6A, 0xCC, 0x01, 0xE0, 0x53, 0x3F, 0xFD, - 0x54, 0x8C, 0x13, 0x6C, 0x9D, 0x0E, 0x47, 0xB4, - 0xD1, 0x59, 0xCA, 0x17, 0xF3, 0x40, 0x10, 0xEA, - 0xCA, 0xD3, 0xA6, 0xDA, 0xA3, 0x28, 0x4B, 0x6E, - 0xBC, 0x42, 0xF8, 0x9D, 0x75, 0xFF, 0x3F, 0xCD, - 0x8E, 0x45, 0xE8, 0x1D, 0xEC, 0x5F, 0x74, 0x87, - 0x61, 0x23, 0x63, 0xA2, 0x79, 0x7B, 0xBB, 0xDE, - 0x72, 0xE5, 0xB6, 0x7B, 0x8B, 0x9A, 0xC7, 0x04, - 0x35, 0xD0, 0x65, 0xCB, 0xD0, 0x44, 0x41, 0xD1, - 0x74, 0x1E, 0xE8, 0x87, 0x6F, 0xE5, 0x25, 0x44, - 0xFB, 0x23, 0xA7, 0x08, 0xF4, 0x89, 0xEA, 0xCF, - 0x1E, 0xE0, 0xE7, 0xC9, 0x12, 0x92, 0xC8, 0xA8, - 0x89, 0x13, 0xA6, 0x07, 0xDC, 0xC9, 0xFA, 0x1F, - 0x2E, 0xB1, 0x04, 0x58, 0xBA, 0xAA, 0x6B, 0xE8, - 0x6B, 0x7D, 0xC8, 0x01, 0x8B, 0x1E, 0xCF, 0x49, - 0xCA, 0x21, 0xAD, 0x61, 0x18, 0xED, 0x8E, 0x83, - 0x00, 0x3E, 0xD9, 0x90, 0x78, 0xE2, 0x22, 0xFF, - 0x8F, 0x54, 0xD4, 0xF9, 0x21, 0x10, 0x37, 0xF4, - 0xFC, 0x2F, 0x15, 0x31, 0x48, 0xB0, 0xD3, 0x36, - 0xC1, 0x32, 0x99, 0x05, 0xDD, 0x6D, 0x3B, 0xBA, - 0x3A, 0x60, 0x91, 0xFE, 0xAE, 0x16, 0xFA, 0x72, - 0x53, 0xC0, 0x75, 0xFC, 0x51, 0xC9, 0x0C, 0x38, - 0x99, 0x5F, 0x19, 0x75, 0xAD, 0x1D, 0x4B, 0xCA, - 0x4A, 0x3C, 0x88, 0x01, 0x40, 0xD2, 0x33, 0xB4, - 0x37, 0x64, 0xDA, 0x3A, 0xAA, 0xBB, 0x93, 0x50, - 0xF5, 0x5A, 0xC4, 0xB5, 0x9D, 0x2D, 0x7B, 0xFA, - 0x7A, 0x84, 0x17, 0x7B, 0x22, 0xD8, 0xBB, 0xEA, - 0x58, 0x80, 0x97, 0xB2, 0x69, 0x70, 0x49, 0x00, - 0x89, 0x4F, 0x09, 0x65, 0xBD, 0x0D, 0x5B, 0xDA, - 0x5A, 0xB0, 0x32, 0x5D, 0x89, 0x1E, 0x46, 0x85, - 0x54, 0xC4, 0x71, 0x8F, 0x54, 0xEC, 0xEE, 0x8F, - 0x7F, 0xAF, 0x90, 0xEA, 0x7A, 0xCC, 0x7D, 0xF1, - 0x72, 0xA5, 0x79, 0x19, 0xC6, 0xF4, 0x5D, 0x61, - 0xF7, 0x24, 0x98, 0xD2, 0x53, 0xEB, 0x26, 0xE4, - 0x01, 0x67, 0xF7, 0xB6, 0x64, 0xC9, 0x59, 0xF3, - 0x30, 0x59, 0xFC, 0x9B, 0xD1, 0x65, 0x05, 0xD3, - 0x68, 0xB8, 0x68, 0x7D, 0xB5, 0xC7, 0xB3, 0x8F, - 0x59, 0x2E, 0x92, 0x5C, 0xC7, 0x7F, 0x3D, 0xFE, - 0x73, 0x88, 0x1F, 0x77, 0xB2, 0xF2, 0x9E, 0x55, - 0x57, 0x8F, 0x34, 0x9A, 0x61, 0x0C, 0x7B, 0xD3, - 0x5C, 0x15, 0xAE, 0xC2, 0x16, 0xB4, 0xC2, 0x2B, - 0xA5, 0x75, 0x6A, 0xA4, 0x31, 0x81, 0xA7, 0x67, - 0xE7, 0x30, 0x84, 0x28, 0xD0, 0x60, 0xA2, 0x71, - 0xF9, 0xE0, 0x33, 0xFF, 0xAB, 0x01, 0x04, 0x22, - 0x84, 0x42, 0x04, 0x02, 0x99, 0xFB, 0x9F, 0x5F, - 0xB9, 0x7F, 0xF5, 0x21, 0xDB, 0xC6, 0xA5, 0x00, - 0x60, 0x9D, 0x8B, 0x07, 0xAB, 0x7D, 0x03, 0xE2, - 0xD3, 0x45, 0xF0, 0x6E, 0xBD, 0x0D, 0x4B, 0xA4, - 0x23, 0x8A, 0x77, 0x1B, 0xCF, 0x75, 0x30, 0x96, - 0x33, 0xE4, 0x6A, 0x94, 0x6F, 0x01, 0xA1, 0x41, - 0xC1, 0x88, 0x5B, 0x97, 0xCD, 0x3E, 0x56, 0xD0, - 0x53, 0x88, 0x9C, 0xE3, 0x3C, 0x00, 0x1A, 0xA8, - 0x6C, 0xB7, 0xA3, 0xDC, 0x03, 0x96, 0x14, 0xF2, - 0x7E, 0xB7, 0x1C, 0x80, 0xEA, 0x49, 0x21, 0x8B, - 0x48, 0x85, 0xF8, 0x93, 0x89, 0x3D, 0x5D, 0x5F, - 0x13, 0x33, 0x93, 0xC3, 0x1C, 0x4E, 0x2D, 0xE0, - 0xE2, 0x1D, 0x2A, 0x51, 0xE7, 0x07, 0xF5, 0x38, - 0xB8, 0x75, 0x4A, 0x2A, 0xFE, 0x5C, 0x37, 0x0E, - 0x7C, 0xEA, 0x5C, 0xB6, 0x7E, 0xCE, 0x2C, 0x25, - 0x5C, 0xD1, 0xFF, 0x66, 0x06, 0x94, 0x59, 0x9A, - 0x7F, 0x7D, 0xED, 0x21, 0x69, 0xAD, 0xC6, 0x9F, - 0x49, 0x7B, 0xC7, 0xA7, 0x74, 0xC8, 0xE4, 0xC6, - 0x65, 0x63, 0x07, 0xC9, 0x65, 0x0F, 0xBC, 0xBC, - 0x1C, 0xC7, 0xD3, 0xAC, 0x7C, 0x2E, 0x2B, 0x4B, - 0xB9, 0x3F, 0xF7, 0x59, 0xC2, 0x7A, 0x0C, 0x86, - 0xF4, 0x23, 0xFB, 0x75, 0xE9, 0x59, 0x9B, 0x48, - 0xC0, 0x7E, 0x13, 0x59, 0x07, 0x72, 0xED, 0x00, - 0x87, 0x50, 0xE9, 0x45, 0xBD, 0x0D, 0xCF, 0x1C, - 0x94, 0xCD, 0x1E, 0xD2, 0x1C, 0x36, 0xA5, 0x80, - 0xD9, 0x24, 0x8F, 0x13, 0xC7, 0x75, 0x53, 0x5B, - 0x24, 0x47, 0xD3, 0x12, 0xC9, 0x5C, 0xE8, 0x0E, - 0x2E, 0x65, 0xA7, 0xAD, 0x6C, 0xFB, 0x97, 0x5C, - 0x0E, 0xF6, 0x9D, 0x33, 0x49, 0x8D, 0x27, 0x24, - 0x64, 0x9F, 0x29, 0x97, 0x2A, 0x3A, 0xF8, 0x2B, - 0xA3, 0x0A, 0xE0, 0xF2, 0x96, 0x7C, 0x76, 0x55, - 0xD9, 0x6F, 0x0B, 0x29, 0xF1, 0xE3, 0x90, 0x58, - 0xBD, 0xB0, 0x20, 0xCA, 0x1B, 0xAB, 0xC7, 0x78, - 0xF4, 0x7B, 0x8F, 0xA0, 0x70, 0xAA, 0x89, 0xBB, - 0x7F, 0xA4, 0xA0, 0xDF, 0x0C, 0x20, 0x0B, 0x79, - 0xAD, 0x8A, 0x30, 0xA6, 0x72, 0x4A, 0xA8, 0x2C, - 0xAC, 0x12, 0x70, 0x3A, 0x70, 0xD4, 0x48, 0x1A, - 0x53, 0x79, 0x5D, 0x65, 0x41, 0xD3, 0xB0, 0x7D, - 0xDD, 0x27, 0x95, 0xE4, 0xCC, 0x51, 0x36, 0x70, - 0x2F, 0x0B, 0x1F, 0x67, 0x43, 0xE5, 0x5F, 0x77, - 0xFB, 0xA8, 0x9C, 0xB4, 0x6C, 0x6A, 0xB0, 0x60, - 0xEC, 0xCD, 0xDE, 0x63, 0x9D, 0x0F, 0x7B, 0x47, - 0xE5, 0xFC, 0xBB, 0xF5, 0x79, 0x35, 0x53, 0x0E, - 0x71, 0x4F, 0x29, 0x63, 0x96, 0x21, 0x07, 0x3B, - 0x44, 0x9F, 0x1F, 0x32, 0xEA, 0x0B, 0x5F, 0x9C, - 0x44, 0x9A, 0x6E, 0xA2, 0x8A, 0x70, 0x55, 0xA7, - 0x23, 0x78, 0xE8, 0xA7, 0x4E, 0xD8, 0xFB, 0x08, - 0xE9, 0x79, 0xCC, 0xD1, 0x45, 0xF6, 0x9A, 0xF2, - 0x54, 0xEC, 0x75, 0x7F, 0x24, 0x8A, 0xE6, 0x55, - 0x47, 0xB9, 0xD1, 0x7D, 0x85, 0x35, 0xC7, 0x61, - 0x41, 0xA8, 0x5A, 0xB6, 0xDC, 0x69, 0x04, 0x66, - 0xE1, 0x3A, 0x3C, 0xE1, 0x3D, 0x3D, 0xF5, 0xA6, - 0x84, 0x18, 0xAE, 0xDF, 0xF7, 0x5A, 0xCA, 0x06, - 0x95, 0x08, 0xBE, 0xD2, 0x06, 0x85, 0xD7, 0x53, - 0x53, 0x95, 0xD3, 0xB3, 0x38, 0x4A, 0x0F, 0x11, - 0x51, 0xAA, 0x1C, 0xB2, 0x0C, 0x1C, 0xBA, 0x89, - 0xF6, 0x2D, 0xAD, 0x80, 0x58, 0xD9, 0xF7, 0x34, - 0x95, 0x01, 0xB4, 0xF1, 0x3A, 0x97, 0x07, 0xC7, - 0x47, 0x9C, 0x1C, 0x31, 0xE9, 0xC8, 0x9C, 0x5F, - 0x47, 0x95, 0xAF, 0x6A, 0x10, 0x89, 0x34, 0x54, - 0x74, 0xBB, 0x2B, 0x7D, 0xA7, 0xF2, 0xD0, 0x31, - 0xAC, 0x87, 0x07, 0x2A, 0xF2, 0xE3, 0xD2, 0x11, - 0xB0, 0x21, 0x94, 0xC9, 0x23, 0x90, 0x61, 0xF1, - 0x72, 0x28, 0xCC, 0xA3, 0xF2, 0x6B, 0x22, 0xE1, - 0xC8, 0x4A, 0xE1, 0x7D, 0xA5, 0x15, 0x43, 0xC2, - 0x42, 0xB8, 0x5D, 0x32, 0x62, 0xF0, 0x57, 0xFF, - 0x62, 0x18, 0xFA, 0x95, 0x28, 0xD1, 0x99, 0xC8, - 0x1D, 0xC5, 0xB2, 0x88, 0x53, 0x52, 0x65, 0xA6, - 0x8E, 0x77, 0x79, 0x1E, 0x06, 0x1C, 0x6C, 0x3C, - 0x26, 0xED, 0xEB, 0x1D, 0x56, 0x7F, 0x3D, 0x58, - 0x11, 0xEF, 0x44, 0xD8, 0x00, 0xB0, 0xE6, 0x67, - 0xE7, 0x9D, 0x7F, 0x10, 0x2D, 0xDF, 0x97, 0xB6, - 0x6E, 0xB6, 0x41, 0x1F, 0xC4, 0x45, 0x76, 0xB5, - 0x39, 0xEE, 0x80, 0xCF, 0xE6, 0x01, 0x62, 0x15, - 0xF8, 0x01, 0x0A, 0x69, 0x79, 0xCD, 0x64, 0xAB, - 0x86, 0x5F, 0x68, 0x5D, 0x86, 0xD6, 0x2B, 0xCB, - 0xD2, 0x2A, 0x15, 0x7D, 0xC0, 0x38, 0x58, 0x29, - 0xF3, 0x2B, 0x35, 0x7A, 0xAE, 0x1C, 0xCC, 0xA6, - 0x06, 0x74, 0xE1, 0x90, 0xB8, 0x04, 0x6F, 0x69, - 0x1F, 0x3B, 0xBB, 0x96, 0x4E, 0xE2, 0x4A, 0x0D, - 0x1F, 0xC0, 0x57, 0x60, 0xBB, 0x16, 0x86, 0xEB, - 0x69, 0x97, 0xE3, 0xAA, 0x5F, 0xE5, 0x98, 0xA8, - 0x28, 0xF3, 0x73, 0x5E, 0x86, 0x47, 0x60, 0xA3, - 0xFF, 0x70, 0x4E, 0x25, 0x71, 0x89, 0x4C, 0x92, - 0x12, 0x8F, 0x38, 0x54, 0x2D, 0xD5, 0xB6, 0x53, - 0xEF, 0x1C, 0x02, 0x69, 0xBD, 0x04, 0xF6, 0x7C, - 0x64, 0x0D, 0x1B, 0x04, 0x96, 0x45, 0xE7, 0x87, - 0x73, 0xCF, 0x45, 0x3A, 0x5F, 0xED, 0x25, 0xE2, - 0xAF, 0x77, 0x8B, 0x4D, 0x37, 0x4D, 0x09, 0x6C, - 0xA9, 0x5A, 0x5E, 0x92, 0x39, 0x4F, 0x2A, 0xEA, - 0x2D, 0xCD, 0x6F, 0xBE, 0x64, 0x7C, 0x1B, 0x19, - 0x39, 0x96, 0x60, 0xC0, 0xD8, 0x22, 0xE8, 0x8A, - 0xC0, 0x3F, 0x6C, 0x43, 0xB3, 0xB1, 0x71, 0xC2, - 0xFE, 0x70, 0xA1, 0xF6, 0x26, 0x34, 0xF0, 0x35, - 0x50, 0x5A, 0xC8, 0xE2, 0x3D, 0x8D, 0x5F, 0x3F, - 0xCB, 0x77, 0x7A, 0x1E, 0x64, 0x70, 0x16, 0x33, - 0x63, 0x9C, 0xAC, 0xC3, 0x1B, 0xA7, 0xCD, 0xD5, - 0x52, 0x85, 0x2F, 0x81, 0x14, 0x3C, 0xB9, 0xB6, - 0x12, 0xEC, 0x5E, 0x32, 0x02, 0xB5, 0x37, 0xF9, - 0xE1, 0xF6, 0x0E, 0xC3, 0x53, 0xE0, 0x25, 0xDD, - 0x75, 0xB3, 0xF5, 0x99, 0x41, 0xF1, 0xA7, 0x26, - 0xA6, 0x4C, 0xBD, 0xD2, 0x32, 0x81, 0xC0, 0x5C, - 0xDF, 0x2D, 0xE8, 0x0F, 0x54, 0x76, 0xD5, 0x01, - 0x18, 0xA0, 0x8F, 0xB0, 0xE1, 0x62, 0x8B, 0x68, - 0xCA, 0xD3, 0x99, 0xDC, 0x47, 0xEA, 0x7A, 0xBA, - 0x3A, 0xE1, 0x61, 0x4C, 0x94, 0xC1, 0xB2, 0x72, - 0xEF, 0xC4, 0x44, 0x69, 0xB1, 0x0D, 0x27, 0x42, - 0xE2, 0x1B, 0x8C, 0xA7, 0x7C, 0x41, 0x2B, 0x73, - 0xF1, 0x26, 0x8A, 0x64, 0xD5, 0x42, 0x87, 0x58, - 0xFA, 0x5D, 0x37, 0x27, 0x11, 0xAD, 0xE5, 0x9D, - 0x1F, 0xC8, 0x69, 0xA7, 0x14, 0x8C, 0x5D, 0xD6, - 0x55, 0x4E, 0xD8, 0xB4, 0xFE, 0x65, 0xAD, 0xAD, - 0x0D, 0xD6, 0x10, 0xE5, 0x1D, 0x3F, 0x34, 0x5C, - 0x1C, 0xE7, 0x51, 0xCF, 0x3C, 0x24, 0x84, 0x64, - 0xE4, 0xBF, 0xF6, 0xBA, 0x90, 0x4B, 0x83, 0x83, - 0x23, 0xF8, 0x9C, 0xDB, 0xA9, 0xD9, 0x99, 0x59, - 0x39, 0x3F, 0x99, 0x27, 0x94, 0x8E, 0x2E, 0xCE, - 0x4E, 0x37, 0xAA, 0x6C, 0x74, 0xE4, 0x84, 0x84, - 0xAE, 0x65, 0x71, 0x76, 0x04, 0x15, 0x28, 0xEB, - 0xCE, 0x00, 0x94, 0xF4, 0x2F, 0x27, 0x45, 0x89, - 0x0F, 0xD8, 0x2B, 0xA7, 0x3C, 0x9D, 0xF1, 0x38, - 0x88, 0xB0, 0xF6, 0x7A, 0x4C, 0xED, 0x3D, 0x0E, - 0x2E, 0x97, 0x4E, 0x08, 0xDC, 0x73, 0xDB, 0x19, - 0x09, 0x7B, 0x3D, 0x4A, 0x0B, 0x2B, 0xDB, 0x6F, - 0x05, 0x12, 0x6E, 0xC8, 0xC2, 0x7E, 0x37, 0x75, - 0xF9, 0x08, 0x0C, 0x6C, 0x91, 0xA1, 0x49, 0x98, - 0xA8, 0xC0, 0x37, 0xE9, 0x7D, 0xE8, 0x58, 0x10, - 0xB0, 0xB3, 0x07, 0xD6, 0x06, 0x36, 0xE9, 0xAA, - 0xC0, 0xC6, 0xC0, 0x54, 0xCD, 0x8F, 0xA3, 0x49, - 0x13, 0x62, 0x56, 0x30, 0xC0, 0xC2, 0xEE, 0x07, - 0x07, 0x58, 0xAF, 0x41, 0xD3, 0x4B, 0x4D, 0xC4, - 0xFE, 0xAD, 0x19, 0xD8, 0x03, 0x39, 0xCA, 0x80, - 0xB4, 0xDD, 0x40, 0x06, 0x54, 0x6A, 0xBA, 0xC1, - 0xB1, 0xD0, 0xEE, 0x00, 0xD0, 0x47, 0xA5, 0x2C, - 0x44, 0x17, 0xA3, 0xC3, 0x10, 0x20, 0x93, 0xC3, - 0xC9, 0xE6, 0xA2, 0xE1, 0x13, 0x29, 0xA7, 0x97, - 0xE8, 0xC3, 0x8F, 0x0D, 0x17, 0xA9, 0xE3, 0xC1, - 0x4F, 0xBD, 0x8B, 0x2B, 0xE2, 0xB2, 0x1E, 0xFE, - 0xBC, 0x3A, 0xE0, 0xE9, 0x20, 0x90, 0xFC, 0x35, - 0xBE, 0x30, 0x3E, 0x50, 0x93, 0x10, 0x40, 0xB0, - 0x44, 0xAF, 0xFA, 0x66, 0x04, 0x70, 0x62, 0xCE, - 0x60, 0x5B, 0xAE, 0xD3, 0x5D, 0x58, 0xCD, 0xAF, - 0xE4, 0x2B, 0x1C, 0x2E, 0xF5, 0xD7, 0x9C, 0x79, - 0x6B, 0xDB, 0x44, 0xE8, 0x10, 0xA0, 0x48, 0x80, - 0x89, 0xD9, 0xCA, 0xF1, 0x09, 0xA4, 0x34, 0xF4, - 0x74, 0xAF, 0x2F, 0x02, 0xDA, 0x4B, 0x6C, 0xAF, - 0x87, 0x5E, 0x4A, 0xEC, 0x20, 0xB5, 0x8D, 0x6D, - 0x45, 0x9C, 0xA1, 0x67, 0x9A, 0xB9, 0xFE, 0x32, - 0xF8, 0xC1, 0xD8, 0x34, 0x3D, 0xC6, 0xA5, 0xA5, - 0x05, 0xDE, 0xAA, 0xEB, 0x87, 0xF7, 0xB7, 0x77, - 0x4F, 0x96, 0xC0, 0x60, 0xA8, 0xDA, 0xD7, 0xA3, - 0x91, 0x61, 0xF0, 0xF9, 0x29, 0xBB, 0x63, 0xA1, - 0x2D, 0xEC, 0xE8, 0xAF, 0x5F, 0x0A, 0x6D, 0x8F, - 0x12, 0x39, 0xB9, 0x94, 0x4C, 0xAD, 0x86, 0x45, - 0x05, 0xFE, 0x48, 0x66, 0x9B, 0x9F, 0x3F, 0xDF, - 0x5F, 0xB4, 0x46, 0x3A, 0xA2, 0x50, 0x10, 0x92, - 0x77, 0x18, 0xB3, 0x2F, 0xF7, 0x47, 0x11, 0x90, - 0x10, 0xC7, 0x72, 0x6C, 0x14, 0xD4, 0xE5, 0x62, - 0xE1, 0x36, 0x96, 0x42, 0x9F, 0x1F, 0xBC, 0x8C, - 0xBC, 0xC4, 0xD2, 0x6C, 0x9E, 0x04, 0xD4, 0xD8, - 0xF8, 0xF3, 0x98, 0x04, 0x06, 0x7A, 0x98, 0x54, - 0xF0, 0xCB, 0x3E, 0x43, 0xFD, 0x55, 0x09, 0x2B, - 0x81, 0x74, 0x10, 0x56, 0xBC, 0x47, 0x94, 0xB3, - 0x3E, 0xF2, 0xE6, 0x86, 0x76, 0xC6, 0xBD, 0x3D, - 0xBD, 0xD0, 0xC7, 0xDB, 0xB8, 0x18, 0xD8, 0xB8, - 0x0C, 0x67, 0x7B, 0x37, 0x4F, 0x5F, 0x4B, 0xCD, - 0x4D, 0x96, 0x2C, 0x4A, 0x20, 0x3F, 0xDF, 0x3A, - 0x43, 0x67, 0x69, 0x00, 0x62, 0x06, 0x94, 0x79, - 0xD7, 0x00, 0xAA, 0x36, 0x01, 0xA0, 0x30, 0x3E, - 0x2D, 0x34, 0xEF, 0xAD, 0x6E, 0xED, 0xBD, 0x4D, - 0xB9, 0x04, 0xF1, 0x3D, 0x6E, 0x75, 0xB0, 0xF5, - 0x52, 0x24, 0x90, 0x7D, 0xFB, 0x48, 0xE8, 0x08, - 0x88, 0xDB, 0x65, 0x80, 0x6A, 0x7F, 0x56, 0xB6, - 0x2B, 0x00, 0x80, 0xAD, 0x75, 0x44, 0x63, 0xA0, - 0x00, 0xB9, 0xFF, 0x1B, 0xCB, 0x70, 0x53, 0x13, - 0xA1, 0xEA, 0xDC, 0xE2, 0x9A, 0x58, 0x1D, 0xF7, - 0xF7, 0x4A, 0x5C, 0x40, 0xEF, 0xAF, 0xB5, 0x53, - 0x85, 0xBA, 0x08, 0x46, 0x9C, 0x0A, 0x28, 0x7B, - 0x8B, 0xD0, 0x44, 0x29, 0xD1, 0x49, 0x18, 0x92, - 0x30, 0xEB, 0x7F, 0x02, 0xFA, 0x6A, 0x3B, 0xD9, - 0x0A, 0xA1, 0x55, 0x1C, 0xEE, 0x1E, 0x3A, 0x0A, - 0xC0, 0x5D, 0xA9, 0xC1, 0x3F, 0x2E, 0x11, 0xD2, - 0xD2, 0x4D, 0xFA, 0xD6, 0x46, 0xC7, 0x01, 0xD5, - 0x59, 0x24, 0x50, 0x2F, 0xEB, 0xA9, 0xD5, 0xED, - 0xEF, 0x67, 0xA1, 0x8B, 0x51, 0xE1, 0x67, 0xB5, - 0x33, 0xE4, 0x50, 0x30, 0xE1, 0xC3, 0xF0, 0x40, - 0x60, 0x19, 0x0F, 0xCB, 0x19, 0x0B, 0x0E, 0xFC, - 0x61, 0x4A, 0xDE, 0xB0, 0x4D, 0x7B, 0xF4, 0xCB, - 0x4B, 0x90, 0x10, 0x3D, 0xE5, 0x59, 0x3B, 0xF7, - 0x72, 0xE8, 0x19, 0x76, 0xA2, 0x51, 0xF9, 0x3D, - 0x7D, 0x74, 0x52, 0xAC, 0x69, 0xB5, 0xC3, 0x5A, - 0xDD, 0x0D, 0x32, 0xDE, 0x86, 0xC2, 0x20, 0xBD, - 0x51, 0xDC, 0xE2, 0x88, 0x90, 0xD2, 0x12, 0x30, - 0x9F, 0x6E, 0x64, 0x16, 0xE8, 0x46, 0x09, 0xEF, - 0x41, 0xB6, 0x66, 0x34, 0xBB, 0x59, 0x56, 0xBC, - 0x1C, 0x55, 0x13, 0xBF, 0xFE, 0xEE, 0x2C, 0xE5, - 0x4F, 0x26, 0x99, 0xDC, 0x84, 0x9E, 0xEF, 0x9F, - 0xB5, 0x4E, 0xF4, 0x93, 0xE9, 0x04, 0x08, 0xE2, - 0xCE, 0x87, 0x38, 0x73, 0x39, 0xC3, 0x4B, 0x26, - 0xA4, 0x5A, 0x1F, 0x8C, 0x12, 0xA9, 0xC9, 0x12, - 0x2C, 0xD7, 0xC3, 0x5F, 0x47, 0x5D, 0x9D, 0xEF, - 0x00, 0xF1, 0xF7, 0x20, 0x08, 0x02, 0xC8, 0xBA, - 0x30, 0xC1, 0x95, 0xF3, 0x02, 0x32, 0xE9, 0x38, - 0x58, 0x38, 0xAE, 0x70, 0xF5, 0x29, 0x63, 0x1F, - 0x3D, 0xEC, 0x7D, 0xB3, 0x20, 0x78, 0xB5, 0x77, - 0xFB, 0x2B, 0x78, 0xFB, 0xDC, 0xA4, 0xC0, 0x2A, - 0x76, 0x3F, 0x84, 0x00, 0x74, 0x0D, 0x66, 0x5F, - 0x2D, 0xBB, 0xE5, 0x41, 0x9D, 0x07, 0xBB, 0x99, - 0x14, 0x27, 0x4D, 0xEF, 0x9A, 0x28, 0x44, 0x9F, - 0x3F, 0x66, 0x20, 0x8C, 0xC6, 0xD6, 0x24, 0xCD, - 0x67, 0x7C, 0x42, 0x8E, 0xC6, 0xEF, 0x7F, 0x25, - 0x2D, 0x74, 0xCA, 0x81, 0xDB, 0x26, 0xAE, 0xCB, - 0xA7, 0x83, 0xFD, 0x95, 0x46, 0xC5, 0xBE, 0x5C, - 0xFC, 0x07, 0xC5, 0xFF, 0x34, 0x70, 0x82, 0x6E, - 0xC7, 0x90, 0xAF, 0xC8, 0x99, 0xAB, 0xA7, 0x4E, - 0x02, 0xC1, 0x92, 0x22, 0x05, 0xA8, 0x38, 0xF8, - 0x78, 0xA3, 0x23, 0x0E, 0xD6, 0x27, 0x27, 0xE4, - 0x55, 0xEF, 0x5A, 0xBE, 0x22, 0x1B, 0xF9, 0x00, - 0xC4, 0x02, 0x44, 0x28, 0xF0, 0x40, 0x16, 0x97, - 0x17, 0x6E, 0x1A, 0x66, 0x1B, 0x98, 0xD8, 0x89, - 0x69, 0xB1, 0x8F, 0x61, 0x30, 0xC9, 0xB4, 0x84, - 0x04, 0xDF, 0x5F, 0x72, 0xAA, 0xA7, 0xC5, 0x24, - 0xC6, 0x1E, 0x80, 0xEE, 0x3A, 0x06, 0xED, 0x8F, - 0xAA, 0x73, 0xED, 0x00, 0xBB, 0x08, 0xFA, 0xF8, - 0x68, 0x2A, 0xCE, 0x3B, 0xA1, 0x98, 0x9A, 0xD6, - 0x55, 0xB7, 0x93, 0xE2, 0xCA, 0x7A, 0x2C, 0xAD, - 0x2D, 0xC7, 0x13, 0x7C, 0x9C, 0x2F, 0xFD, 0x2E, - 0xB6, 0x61, 0xCB, 0xA0, 0x93, 0x39, 0xC8, 0x56, - 0xD5, 0xCE, 0xD3, 0x9F, 0xE5, 0x06, 0x7E, 0x7E, - 0xDE, 0x05, 0x2B, 0x4E, 0x14, 0xB7, 0xD1, 0xB3, - 0xF0, 0x3B, 0x17, 0xF3, 0xA2, 0x61, 0x64, 0x88, - 0x28, 0x41, 0xE4, 0x90, 0x5F, 0x04, 0x6A, 0x12, - 0x01, 0x56, 0x7B, 0x9F, 0x4C, 0x51, 0x33, 0x13, - 0x9B, 0x40, 0xDB, 0xBD, 0x78, 0x38, 0x54, 0x96, - 0x0B, 0x20, 0xA0, 0x8D, 0x55, 0xD4, 0xD6, 0x15, - 0xAD, 0x75, 0x71, 0x0F, 0xC3, 0xBB, 0x78, 0x10, - 0xB3, 0xA2, 0xAF, 0x7A, 0x01, 0x16, 0x4D, 0xDC, - 0xFC, 0xBC, 0xCA, 0x24, 0xEF, 0x47, 0xBE, 0xDD, - 0x4A, 0xF9, 0x64, 0xCA, 0xBA, 0xF5, 0x74, 0xD0, - 0x53, 0x70, 0x75, 0xD9, 0x21, 0x91, 0x23, 0xF0, - 0x68, 0x02, 0xFF, 0x90, 0xA8, 0xC5, 0xB5, 0x87, - 0x6C, 0x17, 0x73, 0x4C, 0x8C, 0xFC, 0xBC, 0x7C, - 0x5E, 0xAE, 0x98, 0x34, 0xCC, 0x7C, 0xDC, 0xB6, - 0x26, 0x5F, 0x82, 0x6E, 0xF0, 0x41, 0x21, 0x43, - 0x00, 0xCB, 0x58, 0x13, 0xEB, 0x9B, 0xDB, 0x1B, - 0x0A, 0x8F, 0x3A, 0xD4, 0x1F, 0xA9, 0x51, 0x98, - 0xBA, 0xA2, 0x04, 0xF2, 0xA2, 0x9B, 0x88, 0x2D, - 0x89, 0x72, 0x4C, 0xA3, 0xD6, 0x64, 0xE4, 0x2C, - 0xAC, 0x6A, 0x2C, 0x40, 0x98, 0x28, 0x7E, 0xFF, - 0x7F, 0xE6, 0xF8, 0x6B, 0x22, 0xF7, 0x94, 0xE5, - 0x07, 0xDF, 0x58, 0x7F, 0xA4, 0xAC, 0xC7, 0xC5, - 0x5E, 0x9D, 0x27, 0x66, 0x6E, 0x12, 0x52, 0x50, - 0x8B, 0x48, 0x3E, 0x72, 0xAA, 0xB8, 0xFB, 0x9B, - 0xB2, 0xD2, 0xA4, 0xE8, 0x30, 0x02, 0x41, 0x21, - 0x61, 0x9A, 0x2C, 0xD0, 0x80, 0x20, 0xD2, 0xB3, - 0x33, 0x78, 0x46, 0x0A, 0x50, 0x83, 0x43, 0x43, - 0xE3, 0x38, 0xAC, 0xE3, 0xBB, 0xCB, 0x8B, 0x4B, - 0x8B, 0x72, 0xD4, 0xFA, 0x86, 0x36, 0x16, 0xF4, - 0x54, 0xAD, 0x78, 0x94, 0x51, 0x11, 0x47, 0xC6, - 0x46, 0xFB, 0x79, 0x1D, 0x47, 0xF4, 0xB3, 0xB1, - 0x32, 0xCF, 0x1F, 0x4B, 0x99, 0x84, 0xE6, 0x9B, - 0x18, 0x0E, 0xBC, 0xF5, 0xB5, 0x27, 0x5A, 0x6A, - 0x42, 0xCA, 0xCE, 0x02, 0x21, 0x21, 0x8D, 0x5D, - 0x1F, 0x87, 0x17, 0xBB, 0x43, 0xF3, 0x01, 0xCB, - 0x47, 0x5C, 0xCA, 0xA6, 0xCE, 0xE7, 0x97, 0xC5, - 0x0F, 0xD8, 0x73, 0xEF, 0x37, 0x87, 0xFD, 0x3C, - 0xBC, 0x67, 0xD1, 0xBD, 0x65, 0xD5, 0x51, 0x9C, - 0x1E, 0xA5, 0x17, 0x7A, 0xA2, 0x12, 0x72, 0xB2, - 0x32, 0xE9, 0xEF, 0x8D, 0x57, 0x87, 0xCD, 0x0F, - 0x8F, 0x54, 0xE2, 0x8E, 0x56, 0xE6, 0x66, 0xB4, - 0x36, 0x8D, 0x27, 0x4B, 0x9B, 0x2B, 0x36, 0xF2, - 0x0C, 0xD3, 0xE1, 0x9F, 0x45, 0x95, 0x81, 0x52, - 0xD0, 0x6B, 0x45, 0x3A, 0xE0, 0x30, 0xF0, 0x23, - 0xA1, 0x1A, 0x74, 0x0C, 0xD6, 0x06, 0x7E, 0xAB, - 0x29, 0x92, 0x14, 0x6E, 0xB4, 0x64, 0x30, 0xE5, - 0x67, 0xDC, 0xD2, 0xAB, 0x71, 0xA1, 0xC1, 0x01, - 0x81, 0x5A, 0x1C, 0x8F, 0xA8, 0xE7, 0x87, 0x47, - 0xC7, 0x1C, 0x5A, 0xC9, 0xEE, 0xA1, 0xC1, 0x01, - 0x81, 0x5A, 0x1C, 0x8F, 0xA8, 0xE7, 0x87, 0x47, - 0xC7, 0x1C, 0x5A, 0xC9, 0xEE, 0xA1, 0xC1, 0x01, - 0x81, 0x5A, 0x1C, 0x8F, 0xA8, 0xE7, 0x87, 0x47, - 0xC7, 0x1C, 0x5A, 0xC9, 0xEE, 0xA1, 0xC1, 0x01, - 0x81, 0x5A, 0x1C, 0x8F, 0xA8, 0xE7, 0x87, 0x47, - 0xC7, 0x1C, 0x5A, 0xC9, 0xEE, 0xA1, 0xC1, 0x01, - 0x81, 0x5A, 0x1C, 0x8F, 0xA8, 0xE7, 0x97, 0x40, - 0xC2, 0x79, 0xEB, 0x90, 0x4A, 0x9A, 0xEE, 0x36, - 0xB4, 0x0F, 0x19, 0x62, 0xB8, 0x68, 0x08, 0xC8, - 0x48, 0x93, 0x25, 0x49, 0x91, 0x21, 0x41, 0x81, - 0x01, 0xDA, 0xA0, 0xD4, 0x0C, 0xDC, 0x6C, 0xB4, - 0x34, 0x8F, 0xC1, 0xB4, 0x6C, 0xBC, 0x30, 0xF0, - 0x70, 0xAB, 0x1D, 0x71, 0xA9, 0x19, 0x78, 0xB8, - 0x38, 0xE3, 0x54, 0x38, 0xE1, 0x51, 0x30, 0xF8, - 0x38, 0xE3, 0x54, 0x39, 0xE0, 0x51, 0x70, 0xA0, - 0x24, 0xFD, 0x6A, 0x02, 0xFB, 0x4F, 0x0E, 0x4A, - 0xDA, 0x43, 0xE4, 0x99, 0x50, 0xF1, 0xD8, 0x3A, - 0x9E, 0x67, 0x98, 0xE6, 0x77, 0xD5, 0xFC, 0x6E, - 0xD7, 0x1E, 0xFD, 0x80, 0x0D, 0xAC, 0x99, 0x4C, - 0x99, 0x53, 0x4F, 0x09, 0x7B, 0xE1, 0x2B, 0x41, - 0x6B, 0x9A, 0x79, 0x40, 0xCD, 0x28, 0x1D, 0x88, - 0x5D, 0x53, 0xB0, 0x09, 0x84, 0xE1, 0x2B, 0x01, - 0x2B, 0x1E, 0x02, 0x80, 0xF2, 0xAC, 0x7A, 0x17, - 0x21, 0x17, 0x17, 0x96, 0xF8, 0xA5, 0x73, 0x6E, - 0x35, 0x33, 0x6B, 0xE9, 0xDF, 0x81, 0x3F, 0x84, - 0xEB, 0x8D, 0xE5, 0x72, 0x74, 0x3F, 0xE1, 0xCE, - 0xB5, 0x93, 0xDB, 0x49, 0x6F, 0x21, 0xBF, 0x88, - 0xB7, 0x93, 0xDB, 0x48, 0x6E, 0x21, 0xBE, 0x81, - 0xFE, 0xDA, 0x58, 0x2D, 0xF5, 0x25, 0x7D, 0xA4, - 0x24, 0x9F, 0xD5, 0xA0, 0x78, 0xA8, 0xFC, 0x3C, - 0xBC, 0x67, 0xD1, 0xBD, 0x65, 0xD5, 0xB5, 0x75, - 0xF5, 0x2E, 0x98, 0xF4, 0x2C, 0x9C, 0xFC, 0x3C, - 0xBC, 0x67, 0xF9, 0x9C, 0x44, 0x94, 0xD0, 0x19, - 0x99, 0x22, 0x84, 0x58, 0x82, 0x32, 0x52, 0x88, - 0x08, 0xB3, 0x75, 0x18, 0xC0, 0x70, 0x6C, 0xAB, - 0x2B, 0x90, 0x9A, 0xFB, 0x21, 0xF1, 0xAD, 0x65, - 0xE5, 0x5E, 0xFC, 0x9E, 0x44, 0x94, 0x38, 0xF6, - 0x74, 0xCF, 0xED, 0x87, 0x5F, 0x8F, 0x4B, 0x84, - 0x06, 0xBD, 0x4F, 0x25, 0xFD, 0x2D, 0xC1, 0x0E, - 0x8C, 0x37, 0x71, 0x04, 0xDC, 0x0C, 0xB8, 0x77, - 0xF5, 0x4E, 0x48, 0x35, 0xEF, 0x3F, 0xE7, 0x2F, - 0xAF, 0x14, 0x82, 0xFC, 0x26, 0xF6, 0x2A, 0xED, - 0x6D, 0xD6, 0x34, 0x4A, 0x90, 0x40, 0xE8, 0x3A, - 0xB8, 0x03, 0x5D, 0x37, 0xEF, 0x3F, 0x3B, 0xE3, - 0x61, 0xDA, 0x2C, 0x4A, 0x92, 0x42, 0x14, 0x95, - 0x15, 0x4F, 0x7B, 0x11, 0x78, 0x48, 0x2E, 0xF2, - 0x78, 0x32, 0x05, 0x6F, 0x15, 0xEE, 0x8E, 0xC7, - 0x4E, 0xB0, 0x04, 0x68, 0x55, 0xE1, 0x81, 0xE4, - 0x66, 0xBD, 0xEE, 0x87, 0x5F, 0x0A, 0x62, 0xA2, - 0x07, 0xDF, 0x69, 0xA0, 0x71, 0xC1, 0x00, 0x43, - 0xC5, 0xAF, 0x9D, 0xF7, 0x8A, 0x60, 0x27, 0xFA, - 0x8A, 0x51, 0xD1, 0xFC, 0x24, 0xA5, 0x40, 0x86, - 0x27, 0x7A, 0xCA, 0x8F, 0x84, 0x29, 0xB9, 0x79, - 0xF9, 0x22, 0xA2, 0x8F, 0x57, 0xD6, 0x31, 0xF7, - 0x56, 0x05, 0xB5, 0xF0, 0x6B, 0xC6, 0x56, 0x96, - 0x16, 0xCD, 0x4D, 0x60, 0xB8, 0x39, 0xDC, 0x1A, - 0xBB, 0xE9, 0x59, 0x1C, 0x57, 0xFA, 0x6A, 0xAA, - 0x2A, 0xF1, 0x71, 0x5C, 0x84, 0x15, 0xF8, 0x3E, - 0x8F, 0xD8, 0x68, 0x95, 0xC7, 0x71, 0x90, 0xDB, - 0x5D, 0x0F, 0xF0, 0xB5, 0x6E, 0xC3, 0x53, 0x93, - 0x13, 0xC8, 0x48, 0x65, 0xBD, 0x9C, 0x72, 0xB4, - 0x38, 0xEB, 0xDF, 0xFA, 0x22, 0xF7, 0x96, 0x56, - 0x77, 0x3C, 0x8C, 0x51, 0x0E, 0xB8, 0x19, 0x56, - 0xD0, 0xC2, 0x7F, 0xBA, 0x39, 0x94, 0x04, 0xC4, - 0x44, 0x9F, 0x1F, 0x32, 0xEA, 0x6B, 0x9A, 0x5C, - 0xFD, 0xB4, 0x04, 0x41, 0x8A, 0x27, 0xB7, 0x77, - 0xF7, 0x2C, 0xAC, 0x81, 0x59, 0x68, 0x9C, 0x5A, - 0xEB, 0xA3, 0x13, 0x5E, 0x13, 0xA5, 0xEC, 0x0F, - 0x06, 0x8E, 0x25, 0xB9, 0x61, 0xD1, 0x87, 0x06, - 0x86, 0xCC, 0xEC, 0x86, 0xDF, 0xF8, 0x9E, 0xD7, - 0x7E, 0xC0, 0x76, 0x1A, 0xDF, 0x9F, 0xC9, 0x48, - 0xC8, 0xB2, 0x9C, 0xF6, 0x9C, 0x8C, 0x60, 0x08, - 0x82, 0x79, 0xAE, 0xC2, 0x92, 0x08, 0xD2, 0xA8, - 0xB4, 0x77, 0xCD, 0xBD, 0x69, 0x54, 0xD6, 0x3C, - 0x94, 0x8F, 0x19, 0x75, 0x7F, 0x81, 0xED, 0xEF, - 0x24, 0xD8, 0x4B, 0x80, 0x7B, 0xEB, 0x6D, 0xBE, - 0x2E, 0xD5, 0x63, 0x12, 0x3A, 0x8A, 0xEA, 0x2A, - 0xAA, 0x71, 0xC7, 0xAB, 0x73, 0xC3, 0xA3, 0x63, - 0xE3, 0x38, 0x8F, 0xE3, 0x3F, 0x8F, 0x8B, 0x51, - 0xD3, 0x68, + 0x06, 0x6B, 0x06, 0x6A, 0x76, 0xC8, 0x18, 0xD4, + 0x54, 0xEF, 0x71, 0x14, 0xCC, 0x1C, 0x58, 0x91, + 0x11, 0xAA, 0x80, 0xF4, 0x2C, 0xFC, 0x9F, 0x5F, + 0xDF, 0x04, 0x02, 0x62, 0xBA, 0x6A, 0x5A, 0x97, + 0x17, 0xCC, 0x46, 0x22, 0xFA, 0x2A, 0xBE, 0x03, + 0x87, 0x3C, 0x9E, 0xFE, 0x26, 0xF6, 0x96, 0x7E, + 0xFA, 0x11, 0x27, 0x66, 0xBA, 0x3A, 0x5A, 0xBA, + 0x3E, 0xD5, 0x4F, 0x03, 0xDF, 0x5F, 0x7F, 0x9F, + 0x1B, 0xF0, 0xA2, 0xEF, 0x33, 0xB3, 0xD3, 0x13, + 0x93, 0x70, 0xFA, 0x96, 0x4E, 0xC6, 0xA6, 0xC6, + 0x46, 0xA5, 0x2F, 0xE3, 0x3B, 0xB3, 0xD3, 0x33, + 0xB3, 0x50, 0xE8, 0xA4, 0x7C, 0xF4, 0x94, 0x14, + 0x94, 0x77, 0xC9, 0xE5, 0x3D, 0xB5, 0xD5, 0x75, + 0xF5, 0x16, 0xA8, 0xA4, 0x7C, 0xF4, 0x94, 0xD4, + 0x54, 0xB7, 0x09, 0xE5, 0x3D, 0xB5, 0x2D, 0xF4, + 0x74, 0xCF, 0x29, 0x5C, 0x84, 0x54, 0x14, 0xAA, + 0x2E, 0x95, 0xF7, 0xE0, 0x3C, 0xEC, 0x8C, 0x52, + 0xD6, 0x3D, 0x7B, 0x0E, 0xD6, 0x06, 0x82, 0x49, + 0xC9, 0x72, 0x7C, 0x18, 0xC0, 0x10, 0x10, 0xF6, + 0x72, 0xC9, 0xC3, 0xA8, 0x70, 0xA0, 0xD8, 0x77, + 0xF3, 0x48, 0x06, 0x04, 0xD8, 0x08, 0x90, 0x5B, + 0xDB, 0x60, 0x36, 0x43, 0x9B, 0x4B, 0xD4, 0xE3, + 0x9C, 0xB8, 0xF1, 0x72, 0x55, 0x1A, 0x8E, 0x57, + 0xD7, 0x6C, 0xDA, 0xBE, 0x66, 0xD6, 0xEA, 0x3D, + 0xBF, 0x04, 0xB2, 0xCE, 0x16, 0xA6, 0x06, 0xDE, + 0x5E, 0xE5, 0xB7, 0xC3, 0x1B, 0xCB, 0x47, 0x9F, + 0x1F, 0xA4, 0x3E, 0x5B, 0x83, 0x53, 0x53, 0x8A, + 0x0A, 0xB1, 0x93, 0xF9, 0x21, 0xF1, 0x31, 0xE6, + 0x64, 0xDF, 0x95, 0xE0, 0x38, 0xE8, 0xB4, 0x6D, + 0xED, 0x56, 0x1D, 0x8E, 0x56, 0xE6, 0x79, 0xB9, + 0xC6, 0xE2, 0x62, 0x4F, 0x97, 0x02, 0x40, 0x80, + 0x65, 0xB8, 0x0E, 0x07, 0xC2, 0x72, 0x37, 0xBE, + 0x3E, 0x00, 0xF2, 0xB8, 0xF1, 0x6D, 0x0E, 0x6F, + 0xC2, 0x1A, 0xA0, 0xC4, 0x95, 0x2F, 0xCD, 0x44, + 0xC4, 0x02, 0x44, 0x28, 0xF0, 0x40, 0x16, 0x97, + 0x17, 0x7D, 0xE4, 0x8B, 0xFE, 0x4C, 0x0D, 0xE3, + 0x60, 0xFD, 0x4B, 0x27, 0x34, 0xA6, 0xCD, 0xB6, + 0x10, 0xC0, 0x7C, 0x98, 0x42, 0x72, 0x92, 0x26, + 0x21, 0x60, 0x26, 0x4C, 0x95, 0x25, 0xA0, 0x03, + 0xA6, 0x50, 0xEC, 0x9D, 0xB5, 0x05, 0x53, 0xD2, + 0x52, 0xA9, 0x7E, 0x12, 0x2F, 0x65, 0xFA, 0x1A, + 0x7C, 0xB4, 0x12, 0x5E, 0x86, 0x3A, 0x50, 0xF5, + 0x53, 0xAD, 0xBA, 0xE6, 0x3D, 0x3C, 0x6D, 0xAE, + 0xCB, 0x33, 0xAD, 0xDC, 0xF4, 0x44, 0x12, 0x93, + 0x13, 0xF9, 0x7D, 0x12, 0xEB, 0x68, 0x0B, 0xE2, + 0x21, 0xE7, 0xA1, 0xCD, 0x15, 0xA5, 0xF3, 0x72, + 0xF2, 0xAB, 0x1F, 0x7E, 0xAA, 0x01, 0xE1, 0xA1, + 0x25, 0xA8, 0x06, 0x6D, 0xB9, 0x0C, 0x60, 0xA6, + 0x64, 0xAD, 0x15, 0x65, 0xBA, 0x30, 0x14, 0x66, + 0x22, 0x78, 0xFC, 0x94, 0x4C, 0x4E, 0x25, 0x9B, + 0xD9, 0x06, 0xB1, 0xEA, 0x89, 0x35, 0x62, 0x1E, + 0x8F, 0x69, 0xD4, 0x7F, 0x1C, 0xA0, 0xFD, 0x31, + 0x77, 0xAD, 0x1B, 0x40, 0xA4, 0x10, 0xB7, 0xCC, + 0x4D, 0xAB, 0x16, 0xD7, 0x0C, 0x01, 0x62, 0x87, + 0xBF, 0x4C, 0x50, 0x5A, 0xD8, 0x3B, 0x50, 0xE7, + 0x2C, 0xB3, 0xB7, 0x1F, 0x46, 0xA0, 0x57, 0x6B, + 0x46, 0x98, 0x93, 0xFA, 0xC7, 0xC1, 0x89, 0x45, + 0xDE, 0xD7, 0xC3, 0xC3, 0xBB, 0xCF, 0xEE, 0xEE, + 0xA8, 0xB3, 0xDF, 0x61, 0x4B, 0xE6, 0x04, 0x04, + 0x40, 0xDA, 0xAC, 0x43, 0xDA, 0x9A, 0x15, 0x25, + 0x45, 0x7D, 0xEA, 0x0C, 0x3A, 0x7A, 0xD4, 0x87, + 0xC5, 0x43, 0x77, 0x1D, 0xC6, 0x76, 0xD4, 0xB6, + 0x5A, 0x4B, 0x3F, 0x91, 0x55, 0x98, 0xC2, 0xCE, + 0x8C, 0x5B, 0xED, 0x53, 0x99, 0x20, 0x6D, 0xA6, + 0xF1, 0x96, 0x21, 0x41, 0xBB, 0x16, 0x86, 0x46, + 0xC6, 0x1D, 0x9D, 0xB0, 0x68, 0x69, 0x3D, 0xFE, + 0xC6, 0x16, 0x2C, 0x2B, 0x51, 0x40, 0x40, 0x2A, + 0x01, 0xBF, 0xB3, 0xFF, 0x8A, 0x38, 0x3D, 0x51, + 0xF4, 0x32, 0x74, 0x18, 0xC0, 0x70, 0x26, 0xA7, + 0x27, 0x5D, 0xDE, 0xB1, 0xD8, 0x5E, 0x3D, 0x30, + 0xB2, 0x0C, 0xEC, 0xA5, 0xCC, 0x44, 0x27, 0xC7, + 0x6D, 0x16, 0x01, 0x5A, 0x81, 0xFC, 0x9E, 0x3B, + 0xEE, 0x10, 0x17, 0x41, 0x9A, 0x0A, 0x50, 0x30, + 0x72, 0x6A, 0xCC, 0x01, 0xE0, 0x53, 0x3F, 0xFD, + 0x54, 0x8C, 0x13, 0x6C, 0x9D, 0x0E, 0x47, 0xB4, + 0xD1, 0x59, 0xCA, 0x17, 0xF3, 0x40, 0x10, 0xEA, + 0xCA, 0xD3, 0xA6, 0xDA, 0xA3, 0x28, 0x4B, 0x6E, + 0xBC, 0x42, 0xF8, 0x9D, 0x75, 0xFF, 0x3F, 0xCD, + 0x8E, 0x45, 0xE8, 0x1D, 0xEC, 0x5F, 0x74, 0x87, + 0x61, 0x23, 0x63, 0xA2, 0x79, 0x7B, 0xBB, 0xDE, + 0x72, 0xE5, 0xB6, 0x7B, 0x8B, 0x9A, 0xC7, 0x04, + 0x35, 0xD0, 0x65, 0xCB, 0xD0, 0x44, 0x41, 0xD1, + 0x74, 0x1E, 0xE8, 0x87, 0x6F, 0xE5, 0x25, 0x44, + 0xFB, 0x23, 0xA7, 0x08, 0xF4, 0x89, 0xEA, 0xCF, + 0x1E, 0xE0, 0xE7, 0xC9, 0x12, 0x92, 0xC8, 0xA8, + 0x89, 0x13, 0xA6, 0x07, 0xDC, 0xC9, 0xFA, 0x1F, + 0x2E, 0xB1, 0x04, 0x58, 0xBA, 0xAA, 0x6B, 0xE8, + 0x6B, 0x7D, 0xC8, 0x01, 0x8B, 0x1E, 0xCF, 0x49, + 0xCA, 0x21, 0xAD, 0x61, 0x18, 0xED, 0x8E, 0x83, + 0x00, 0x3E, 0xD9, 0x90, 0x78, 0xE2, 0x22, 0xFF, + 0x8F, 0x54, 0xD4, 0xF9, 0x21, 0x10, 0x37, 0xF4, + 0xFC, 0x2F, 0x15, 0x31, 0x48, 0xB0, 0xD3, 0x36, + 0xC1, 0x32, 0x99, 0x05, 0xDD, 0x6D, 0x3B, 0xBA, + 0x3A, 0x60, 0x91, 0xFE, 0xAE, 0x16, 0xFA, 0x72, + 0x53, 0xC0, 0x75, 0xFC, 0x51, 0xC9, 0x0C, 0x38, + 0x99, 0x5F, 0x19, 0x75, 0xAD, 0x1D, 0x4B, 0xCA, + 0x4A, 0x3C, 0x88, 0x01, 0x40, 0xD2, 0x33, 0xB4, + 0x37, 0x64, 0xDA, 0x3A, 0xAA, 0xBB, 0x93, 0x50, + 0xF5, 0x5A, 0xC4, 0xB5, 0x9D, 0x2D, 0x7B, 0xFA, + 0x7A, 0x84, 0x17, 0x7B, 0x22, 0xD8, 0xBB, 0xEA, + 0x58, 0x80, 0x97, 0xB2, 0x69, 0x70, 0x49, 0x00, + 0x89, 0x4F, 0x09, 0x65, 0xBD, 0x0D, 0x5B, 0xDA, + 0x5A, 0xB0, 0x32, 0x5D, 0x89, 0x1E, 0x46, 0x85, + 0x54, 0xC4, 0x71, 0x8F, 0x54, 0xEC, 0xEE, 0x8F, + 0x7F, 0xAF, 0x90, 0xEA, 0x7A, 0xCC, 0x7D, 0xF1, + 0x72, 0xA5, 0x79, 0x19, 0xC6, 0xF4, 0x5D, 0x61, + 0xF7, 0x24, 0x98, 0xD2, 0x53, 0xEB, 0x26, 0xE4, + 0x01, 0x67, 0xF7, 0xB6, 0x64, 0xC9, 0x59, 0xF3, + 0x30, 0x59, 0xFC, 0x9B, 0xD1, 0x65, 0x05, 0xD3, + 0x68, 0xB8, 0x68, 0x7D, 0xB5, 0xC7, 0xB3, 0x8F, + 0x59, 0x2E, 0x92, 0x5C, 0xC7, 0x7F, 0x3D, 0xFE, + 0x73, 0x88, 0x1F, 0x77, 0xB2, 0xF2, 0x9E, 0x55, + 0x57, 0x8F, 0x34, 0x9A, 0x61, 0x0C, 0x7B, 0xD3, + 0x5C, 0x15, 0xAE, 0xC2, 0x16, 0xB4, 0xC2, 0x2B, + 0xA5, 0x75, 0x6A, 0xA4, 0x31, 0x81, 0xA7, 0x67, + 0xE7, 0x30, 0x84, 0x28, 0xD0, 0x60, 0xA2, 0x71, + 0xF9, 0xE0, 0x33, 0xFF, 0xAB, 0x01, 0x04, 0x22, + 0x84, 0x42, 0x04, 0x02, 0x99, 0xFB, 0x9F, 0x5F, + 0xB9, 0x7F, 0xF5, 0x21, 0xDB, 0xC6, 0xA5, 0x00, + 0x60, 0x9D, 0x8B, 0x07, 0xAB, 0x7D, 0x03, 0xE2, + 0xD3, 0x45, 0xF0, 0x6E, 0xBD, 0x0D, 0x4B, 0xA4, + 0x23, 0x8A, 0x77, 0x1B, 0xCF, 0x75, 0x30, 0x96, + 0x33, 0xE4, 0x6A, 0x94, 0x6F, 0x01, 0xA1, 0x41, + 0xC1, 0x88, 0x5B, 0x97, 0xCD, 0x3E, 0x56, 0xD0, + 0x53, 0x88, 0x9C, 0xE3, 0x3C, 0x00, 0x1A, 0xA8, + 0x6C, 0xB7, 0xA3, 0xDC, 0x03, 0x96, 0x14, 0xF2, + 0x7E, 0xB7, 0x1C, 0x80, 0xEA, 0x49, 0x21, 0x8B, + 0x48, 0x85, 0xF8, 0x93, 0x89, 0x3D, 0x5D, 0x5F, + 0x13, 0x33, 0x93, 0xC3, 0x1C, 0x4E, 0x2D, 0xE0, + 0xE2, 0x1D, 0x2A, 0x51, 0xE7, 0x07, 0xF5, 0x38, + 0xB8, 0x75, 0x4A, 0x2A, 0xFE, 0x5C, 0x37, 0x0E, + 0x7C, 0xEA, 0x5C, 0xB6, 0x7E, 0xCE, 0x2C, 0x25, + 0x5C, 0xD1, 0xFF, 0x66, 0x06, 0x94, 0x59, 0x9A, + 0x7F, 0x7D, 0xED, 0x21, 0x69, 0xAD, 0xC6, 0x9F, + 0x49, 0x7B, 0xC7, 0xA7, 0x74, 0xC8, 0xE4, 0xC6, + 0x65, 0x63, 0x07, 0xC9, 0x65, 0x0F, 0xBC, 0xBC, + 0x1C, 0xC7, 0xD3, 0xAC, 0x7C, 0x2E, 0x2B, 0x4B, + 0xB9, 0x3F, 0xF7, 0x59, 0xC2, 0x7A, 0x0C, 0x86, + 0xF4, 0x23, 0xFB, 0x75, 0xE9, 0x59, 0x9B, 0x48, + 0xC0, 0x7E, 0x13, 0x59, 0x07, 0x72, 0xED, 0x00, + 0x87, 0x50, 0xE9, 0x45, 0xBD, 0x0D, 0xCF, 0x1C, + 0x94, 0xCD, 0x1E, 0xD2, 0x1C, 0x36, 0xA5, 0x80, + 0xD9, 0x24, 0x8F, 0x13, 0xC7, 0x75, 0x53, 0x5B, + 0x24, 0x47, 0xD3, 0x12, 0xC9, 0x5C, 0xE8, 0x0E, + 0x2E, 0x65, 0xA7, 0xAD, 0x6C, 0xFB, 0x97, 0x5C, + 0x0E, 0xF6, 0x9D, 0x33, 0x49, 0x8D, 0x27, 0x24, + 0x64, 0x9F, 0x29, 0x97, 0x2A, 0x3A, 0xF8, 0x2B, + 0xA3, 0x0A, 0xE0, 0xF2, 0x96, 0x7C, 0x76, 0x55, + 0xD9, 0x6F, 0x0B, 0x29, 0xF1, 0xE3, 0x90, 0x58, + 0xBD, 0xB0, 0x20, 0xCA, 0x1B, 0xAB, 0xC7, 0x78, + 0xF4, 0x7B, 0x8F, 0xA0, 0x70, 0xAA, 0x89, 0xBB, + 0x7F, 0xA4, 0xA0, 0xDF, 0x0C, 0x20, 0x0B, 0x79, + 0xAD, 0x8A, 0x30, 0xA6, 0x72, 0x4A, 0xA8, 0x2C, + 0xAC, 0x12, 0x70, 0x3A, 0x70, 0xD4, 0x48, 0x1A, + 0x53, 0x79, 0x5D, 0x65, 0x41, 0xD3, 0xB0, 0x7D, + 0xDD, 0x27, 0x95, 0xE4, 0xCC, 0x51, 0x36, 0x70, + 0x2F, 0x0B, 0x1F, 0x67, 0x43, 0xE5, 0x5F, 0x77, + 0xFB, 0xA8, 0x9C, 0xB4, 0x6C, 0x6A, 0xB0, 0x60, + 0xEC, 0xCD, 0xDE, 0x63, 0x9D, 0x0F, 0x7B, 0x47, + 0xE5, 0xFC, 0xBB, 0xF5, 0x79, 0x35, 0x53, 0x0E, + 0x71, 0x4F, 0x29, 0x63, 0x96, 0x21, 0x07, 0x3B, + 0x44, 0x9F, 0x1F, 0x32, 0xEA, 0x0B, 0x5F, 0x9C, + 0x44, 0x9A, 0x6E, 0xA2, 0x8A, 0x70, 0x55, 0xA7, + 0x23, 0x78, 0xE8, 0xA7, 0x4E, 0xD8, 0xFB, 0x08, + 0xE9, 0x79, 0xCC, 0xD1, 0x45, 0xF6, 0x9A, 0xF2, + 0x54, 0xEC, 0x75, 0x7F, 0x24, 0x8A, 0xE6, 0x55, + 0x47, 0xB9, 0xD1, 0x7D, 0x85, 0x35, 0xC7, 0x61, + 0x41, 0xA8, 0x5A, 0xB6, 0xDC, 0x69, 0x04, 0x66, + 0xE1, 0x3A, 0x3C, 0xE1, 0x3D, 0x3D, 0xF5, 0xA6, + 0x84, 0x18, 0xAE, 0xDF, 0xF7, 0x5A, 0xCA, 0x06, + 0x95, 0x08, 0xBE, 0xD2, 0x06, 0x85, 0xD7, 0x53, + 0x53, 0x95, 0xD3, 0xB3, 0x38, 0x4A, 0x0F, 0x11, + 0x51, 0xAA, 0x1C, 0xB2, 0x0C, 0x1C, 0xBA, 0x89, + 0xF6, 0x2D, 0xAD, 0x80, 0x58, 0xD9, 0xF7, 0x34, + 0x95, 0x01, 0xB4, 0xF1, 0x3A, 0x97, 0x07, 0xC7, + 0x47, 0x9C, 0x1C, 0x31, 0xE9, 0xC8, 0x9C, 0x5F, + 0x47, 0x95, 0xAF, 0x6A, 0x10, 0x89, 0x34, 0x54, + 0x74, 0xBB, 0x2B, 0x7D, 0xA7, 0xF2, 0xD0, 0x31, + 0xAC, 0x87, 0x07, 0x2A, 0xF2, 0xE3, 0xD2, 0x11, + 0xB0, 0x21, 0x94, 0xC9, 0x23, 0x90, 0x61, 0xF1, + 0x72, 0x28, 0xCC, 0xA3, 0xF2, 0x6B, 0x22, 0xE1, + 0xC8, 0x4A, 0xE1, 0x7D, 0xA5, 0x15, 0x43, 0xC2, + 0x42, 0xB8, 0x5D, 0x32, 0x62, 0xF0, 0x57, 0xFF, + 0x62, 0x18, 0xFA, 0x95, 0x28, 0xD1, 0x99, 0xC8, + 0x1D, 0xC5, 0xB2, 0x88, 0x53, 0x52, 0x65, 0xA6, + 0x8E, 0x77, 0x79, 0x1E, 0x06, 0x1C, 0x6C, 0x3C, + 0x26, 0xED, 0xEB, 0x1D, 0x56, 0x7F, 0x3D, 0x58, + 0x11, 0xEF, 0x44, 0xD8, 0x00, 0xB0, 0xE6, 0x67, + 0xE7, 0x9D, 0x7F, 0x10, 0x2D, 0xDF, 0x97, 0xB6, + 0x6E, 0xB6, 0x41, 0x1F, 0xC4, 0x45, 0x76, 0xB5, + 0x39, 0xEE, 0x80, 0xCF, 0xE6, 0x01, 0x62, 0x15, + 0xF8, 0x01, 0x0A, 0x69, 0x79, 0xCD, 0x64, 0xAB, + 0x86, 0x5F, 0x68, 0x5D, 0x86, 0xD6, 0x2B, 0xCB, + 0xD2, 0x2A, 0x15, 0x7D, 0xC0, 0x38, 0x58, 0x29, + 0xF3, 0x2B, 0x35, 0x7A, 0xAE, 0x1C, 0xCC, 0xA6, + 0x06, 0x74, 0xE1, 0x90, 0xB8, 0x04, 0x6F, 0x69, + 0x1F, 0x3B, 0xBB, 0x96, 0x4E, 0xE2, 0x4A, 0x0D, + 0x1F, 0xC0, 0x57, 0x60, 0xBB, 0x16, 0x86, 0xEB, + 0x69, 0x97, 0xE3, 0xAA, 0x5F, 0xE5, 0x98, 0xA8, + 0x28, 0xF3, 0x73, 0x5E, 0x86, 0x47, 0x60, 0xA3, + 0xFF, 0x70, 0x4E, 0x25, 0x71, 0x89, 0x4C, 0x92, + 0x12, 0x8F, 0x38, 0x54, 0x2D, 0xD5, 0xB6, 0x53, + 0xEF, 0x1C, 0x02, 0x69, 0xBD, 0x04, 0xF6, 0x7C, + 0x64, 0x0D, 0x1B, 0x04, 0x96, 0x45, 0xE7, 0x87, + 0x73, 0xCF, 0x45, 0x3A, 0x5F, 0xED, 0x25, 0xE2, + 0xAF, 0x77, 0x8B, 0x4D, 0x37, 0x4D, 0x09, 0x6C, + 0xA9, 0x5A, 0x5E, 0x92, 0x39, 0x4F, 0x2A, 0xEA, + 0x2D, 0xCD, 0x6F, 0xBE, 0x64, 0x7C, 0x1B, 0x19, + 0x39, 0x96, 0x60, 0xC0, 0xD8, 0x22, 0xE8, 0x8A, + 0xC0, 0x3F, 0x6C, 0x43, 0xB3, 0xB1, 0x71, 0xC2, + 0xFE, 0x70, 0xA1, 0xF6, 0x26, 0x34, 0xF0, 0x35, + 0x50, 0x5A, 0xC8, 0xE2, 0x3D, 0x8D, 0x5F, 0x3F, + 0xCB, 0x77, 0x7A, 0x1E, 0x64, 0x70, 0x16, 0x33, + 0x63, 0x9C, 0xAC, 0xC3, 0x1B, 0xA7, 0xCD, 0xD5, + 0x52, 0x85, 0x2F, 0x81, 0x14, 0x3C, 0xB9, 0xB6, + 0x12, 0xEC, 0x5E, 0x32, 0x02, 0xB5, 0x37, 0xF9, + 0xE1, 0xF6, 0x0E, 0xC3, 0x53, 0xE0, 0x25, 0xDD, + 0x75, 0xB3, 0xF5, 0x99, 0x41, 0xF1, 0xA7, 0x26, + 0xA6, 0x4C, 0xBD, 0xD2, 0x32, 0x81, 0xC0, 0x5C, + 0xDF, 0x2D, 0xE8, 0x0F, 0x54, 0x76, 0xD5, 0x01, + 0x18, 0xA0, 0x8F, 0xB0, 0xE1, 0x62, 0x8B, 0x68, + 0xCA, 0xD3, 0x99, 0xDC, 0x47, 0xEA, 0x7A, 0xBA, + 0x3A, 0xE1, 0x61, 0x4C, 0x94, 0xC1, 0xB2, 0x72, + 0xEF, 0xC4, 0x44, 0x69, 0xB1, 0x0D, 0x27, 0x42, + 0xE2, 0x1B, 0x8C, 0xA7, 0x7C, 0x41, 0x2B, 0x73, + 0xF1, 0x26, 0x8A, 0x64, 0xD5, 0x42, 0x87, 0x58, + 0xFA, 0x5D, 0x37, 0x27, 0x11, 0xAD, 0xE5, 0x9D, + 0x1F, 0xC8, 0x69, 0xA7, 0x14, 0x8C, 0x5D, 0xD6, + 0x55, 0x4E, 0xD8, 0xB4, 0xFE, 0x65, 0xAD, 0xAD, + 0x0D, 0xD6, 0x10, 0xE5, 0x1D, 0x3F, 0x34, 0x5C, + 0x1C, 0xE7, 0x51, 0xCF, 0x3C, 0x24, 0x84, 0x64, + 0xE4, 0xBF, 0xF6, 0xBA, 0x90, 0x4B, 0x83, 0x83, + 0x23, 0xF8, 0x9C, 0xDB, 0xA9, 0xD9, 0x99, 0x59, + 0x39, 0x3F, 0x99, 0x27, 0x94, 0x8E, 0x2E, 0xCE, + 0x4E, 0x37, 0xAA, 0x6C, 0x74, 0xE4, 0x84, 0x84, + 0xAE, 0x65, 0x71, 0x76, 0x04, 0x15, 0x28, 0xEB, + 0xCE, 0x00, 0x94, 0xF4, 0x2F, 0x27, 0x45, 0x89, + 0x0F, 0xD8, 0x2B, 0xA7, 0x3C, 0x9D, 0xF1, 0x38, + 0x88, 0xB0, 0xF6, 0x7A, 0x4C, 0xED, 0x3D, 0x0E, + 0x2E, 0x97, 0x4E, 0x08, 0xDC, 0x73, 0xDB, 0x19, + 0x09, 0x7B, 0x3D, 0x4A, 0x0B, 0x2B, 0xDB, 0x6F, + 0x05, 0x12, 0x6E, 0xC8, 0xC2, 0x7E, 0x37, 0x75, + 0xF9, 0x08, 0x0C, 0x6C, 0x91, 0xA1, 0x49, 0x98, + 0xA8, 0xC0, 0x37, 0xE9, 0x7D, 0xE8, 0x58, 0x10, + 0xB0, 0xB3, 0x07, 0xD6, 0x06, 0x36, 0xE9, 0xAA, + 0xC0, 0xC6, 0xC0, 0x54, 0xCD, 0x8F, 0xA3, 0x49, + 0x13, 0x62, 0x56, 0x30, 0xC0, 0xC2, 0xEE, 0x07, + 0x07, 0x58, 0xAF, 0x41, 0xD3, 0x4B, 0x4D, 0xC4, + 0xFE, 0xAD, 0x19, 0xD8, 0x03, 0x39, 0xCA, 0x80, + 0xB4, 0xDD, 0x40, 0x06, 0x54, 0x6A, 0xBA, 0xC1, + 0xB1, 0xD0, 0xEE, 0x00, 0xD0, 0x47, 0xA5, 0x2C, + 0x44, 0x17, 0xA3, 0xC3, 0x10, 0x20, 0x93, 0xC3, + 0xC9, 0xE6, 0xA2, 0xE1, 0x13, 0x29, 0xA7, 0x97, + 0xE8, 0xC3, 0x8F, 0x0D, 0x17, 0xA9, 0xE3, 0xC1, + 0x4F, 0xBD, 0x8B, 0x2B, 0xE2, 0xB2, 0x1E, 0xFE, + 0xBC, 0x3A, 0xE0, 0xE9, 0x20, 0x90, 0xFC, 0x35, + 0xBE, 0x30, 0x3E, 0x50, 0x93, 0x10, 0x40, 0xB0, + 0x44, 0xAF, 0xFA, 0x66, 0x04, 0x70, 0x62, 0xCE, + 0x60, 0x5B, 0xAE, 0xD3, 0x5D, 0x58, 0xCD, 0xAF, + 0xE4, 0x2B, 0x1C, 0x2E, 0xF5, 0xD7, 0x9C, 0x79, + 0x6B, 0xDB, 0x44, 0xE8, 0x10, 0xA0, 0x48, 0x80, + 0x89, 0xD9, 0xCA, 0xF1, 0x09, 0xA4, 0x34, 0xF4, + 0x74, 0xAF, 0x2F, 0x02, 0xDA, 0x4B, 0x6C, 0xAF, + 0x87, 0x5E, 0x4A, 0xEC, 0x20, 0xB5, 0x8D, 0x6D, + 0x45, 0x9C, 0xA1, 0x67, 0x9A, 0xB9, 0xFE, 0x32, + 0xF8, 0xC1, 0xD8, 0x34, 0x3D, 0xC6, 0xA5, 0xA5, + 0x05, 0xDE, 0xAA, 0xEB, 0x87, 0xF7, 0xB7, 0x77, + 0x4F, 0x96, 0xC0, 0x60, 0xA8, 0xDA, 0xD7, 0xA3, + 0x91, 0x61, 0xF0, 0xF9, 0x29, 0xBB, 0x63, 0xA1, + 0x2D, 0xEC, 0xE8, 0xAF, 0x5F, 0x0A, 0x6D, 0x8F, + 0x12, 0x39, 0xB9, 0x94, 0x4C, 0xAD, 0x86, 0x45, + 0x05, 0xFE, 0x48, 0x66, 0x9B, 0x9F, 0x3F, 0xDF, + 0x5F, 0xB4, 0x46, 0x3A, 0xA2, 0x50, 0x10, 0x92, + 0x77, 0x18, 0xB3, 0x2F, 0xF7, 0x47, 0x11, 0x90, + 0x10, 0xC7, 0x72, 0x6C, 0x14, 0xD4, 0xE5, 0x62, + 0xE1, 0x36, 0x96, 0x42, 0x9F, 0x1F, 0xBC, 0x8C, + 0xBC, 0xC4, 0xD2, 0x6C, 0x9E, 0x04, 0xD4, 0xD8, + 0xF8, 0xF3, 0x98, 0x04, 0x06, 0x7A, 0x98, 0x54, + 0xF0, 0xCB, 0x3E, 0x43, 0xFD, 0x55, 0x09, 0x2B, + 0x81, 0x74, 0x10, 0x56, 0xBC, 0x47, 0x94, 0xB3, + 0x3E, 0xF2, 0xE6, 0x86, 0x76, 0xC6, 0xBD, 0x3D, + 0xBD, 0xD0, 0xC7, 0xDB, 0xB8, 0x18, 0xD8, 0xB8, + 0x0C, 0x67, 0x7B, 0x37, 0x4F, 0x5F, 0x4B, 0xCD, + 0x4D, 0x96, 0x2C, 0x4A, 0x20, 0x3F, 0xDF, 0x3A, + 0x43, 0x67, 0x69, 0x00, 0x62, 0x06, 0x94, 0x79, + 0xD7, 0x00, 0xAA, 0x36, 0x01, 0xA0, 0x30, 0x3E, + 0x2D, 0x34, 0xEF, 0xAD, 0x6E, 0xED, 0xBD, 0x4D, + 0xB9, 0x04, 0xF1, 0x3D, 0x6E, 0x75, 0xB0, 0xF5, + 0x52, 0x24, 0x90, 0x7D, 0xFB, 0x48, 0xE8, 0x08, + 0x88, 0xDB, 0x65, 0x80, 0x6A, 0x7F, 0x56, 0xB6, + 0x2B, 0x00, 0x80, 0xAD, 0x75, 0x44, 0x63, 0xA0, + 0x00, 0xB9, 0xFF, 0x1B, 0xCB, 0x70, 0x53, 0x13, + 0xA1, 0xEA, 0xDC, 0xE2, 0x9A, 0x58, 0x1D, 0xF7, + 0xF7, 0x4A, 0x5C, 0x40, 0xEF, 0xAF, 0xB5, 0x53, + 0x85, 0xBA, 0x08, 0x46, 0x9C, 0x0A, 0x28, 0x7B, + 0x8B, 0xD0, 0x44, 0x29, 0xD1, 0x49, 0x18, 0x92, + 0x30, 0xEB, 0x7F, 0x02, 0xFA, 0x6A, 0x3B, 0xD9, + 0x0A, 0xA1, 0x55, 0x1C, 0xEE, 0x1E, 0x3A, 0x0A, + 0xC0, 0x5D, 0xA9, 0xC1, 0x3F, 0x2E, 0x11, 0xD2, + 0xD2, 0x4D, 0xFA, 0xD6, 0x46, 0xC7, 0x01, 0xD5, + 0x59, 0x24, 0x50, 0x2F, 0xEB, 0xA9, 0xD5, 0xED, + 0xEF, 0x67, 0xA1, 0x8B, 0x51, 0xE1, 0x67, 0xB5, + 0x33, 0xE4, 0x50, 0x30, 0xE1, 0xC3, 0xF0, 0x40, + 0x60, 0x19, 0x0F, 0xCB, 0x19, 0x0B, 0x0E, 0xFC, + 0x61, 0x4A, 0xDE, 0xB0, 0x4D, 0x7B, 0xF4, 0xCB, + 0x4B, 0x90, 0x10, 0x3D, 0xE5, 0x59, 0x3B, 0xF7, + 0x72, 0xE8, 0x19, 0x76, 0xA2, 0x51, 0xF9, 0x3D, + 0x7D, 0x74, 0x52, 0xAC, 0x69, 0xB5, 0xC3, 0x5A, + 0xDD, 0x0D, 0x32, 0xDE, 0x86, 0xC2, 0x20, 0xBD, + 0x51, 0xDC, 0xE2, 0x88, 0x90, 0xD2, 0x12, 0x30, + 0x9F, 0x6E, 0x64, 0x16, 0xE8, 0x46, 0x09, 0xEF, + 0x41, 0xB6, 0x66, 0x34, 0xBB, 0x59, 0x56, 0xBC, + 0x1C, 0x55, 0x13, 0xBF, 0xFE, 0xEE, 0x2C, 0xE5, + 0x4F, 0x26, 0x99, 0xDC, 0x84, 0x9E, 0xEF, 0x9F, + 0xB5, 0x4E, 0xF4, 0x93, 0xE9, 0x04, 0x08, 0xE2, + 0xCE, 0x87, 0x38, 0x73, 0x39, 0xC3, 0x4B, 0x26, + 0xA4, 0x5A, 0x1F, 0x8C, 0x12, 0xA9, 0xC9, 0x12, + 0x2C, 0xD7, 0xC3, 0x5F, 0x47, 0x5D, 0x9D, 0xEF, + 0x00, 0xF1, 0xF7, 0x20, 0x08, 0x02, 0xC8, 0xBA, + 0x30, 0xC1, 0x95, 0xF3, 0x02, 0x32, 0xE9, 0x38, + 0x58, 0x38, 0xAE, 0x70, 0xF5, 0x29, 0x63, 0x1F, + 0x3D, 0xEC, 0x7D, 0xB3, 0x20, 0x78, 0xB5, 0x77, + 0xFB, 0x2B, 0x78, 0xFB, 0xDC, 0xA4, 0xC0, 0x2A, + 0x76, 0x3F, 0x84, 0x00, 0x74, 0x0D, 0x66, 0x5F, + 0x2D, 0xBB, 0xE5, 0x41, 0x9D, 0x07, 0xBB, 0x99, + 0x14, 0x27, 0x4D, 0xEF, 0x9A, 0x28, 0x44, 0x9F, + 0x3F, 0x66, 0x20, 0x8C, 0xC6, 0xD6, 0x24, 0xCD, + 0x67, 0x7C, 0x42, 0x8E, 0xC6, 0xEF, 0x7F, 0x25, + 0x2D, 0x74, 0xCA, 0x81, 0xDB, 0x26, 0xAE, 0xCB, + 0xA7, 0x83, 0xFD, 0x95, 0x46, 0xC5, 0xBE, 0x5C, + 0xFC, 0x07, 0xC5, 0xFF, 0x34, 0x70, 0x82, 0x6E, + 0xC7, 0x90, 0xAF, 0xC8, 0x99, 0xAB, 0xA7, 0x4E, + 0x02, 0xC1, 0x92, 0x22, 0x05, 0xA8, 0x38, 0xF8, + 0x78, 0xA3, 0x23, 0x0E, 0xD6, 0x27, 0x27, 0xE4, + 0x55, 0xEF, 0x5A, 0xBE, 0x22, 0x1B, 0xF9, 0x00, + 0xC4, 0x02, 0x44, 0x28, 0xF0, 0x40, 0x16, 0x97, + 0x17, 0x6E, 0x1A, 0x66, 0x1B, 0x98, 0xD8, 0x89, + 0x69, 0xB1, 0x8F, 0x61, 0x30, 0xC9, 0xB4, 0x84, + 0x04, 0xDF, 0x5F, 0x72, 0xAA, 0xA7, 0xC5, 0x24, + 0xC6, 0x1E, 0x80, 0xEE, 0x3A, 0x06, 0xED, 0x8F, + 0xAA, 0x73, 0xED, 0x00, 0xBB, 0x08, 0xFA, 0xF8, + 0x68, 0x2A, 0xCE, 0x3B, 0xA1, 0x98, 0x9A, 0xD6, + 0x55, 0xB7, 0x93, 0xE2, 0xCA, 0x7A, 0x2C, 0xAD, + 0x2D, 0xC7, 0x13, 0x7C, 0x9C, 0x2F, 0xFD, 0x2E, + 0xB6, 0x61, 0xCB, 0xA0, 0x93, 0x39, 0xC8, 0x56, + 0xD5, 0xCE, 0xD3, 0x9F, 0xE5, 0x06, 0x7E, 0x7E, + 0xDE, 0x05, 0x2B, 0x4E, 0x14, 0xB7, 0xD1, 0xB3, + 0xF0, 0x3B, 0x17, 0xF3, 0xA2, 0x61, 0x64, 0x88, + 0x28, 0x41, 0xE4, 0x90, 0x5F, 0x04, 0x6A, 0x12, + 0x01, 0x56, 0x7B, 0x9F, 0x4C, 0x51, 0x33, 0x13, + 0x9B, 0x40, 0xDB, 0xBD, 0x78, 0x38, 0x54, 0x96, + 0x0B, 0x20, 0xA0, 0x8D, 0x55, 0xD4, 0xD6, 0x15, + 0xAD, 0x75, 0x71, 0x0F, 0xC3, 0xBB, 0x78, 0x10, + 0xB3, 0xA2, 0xAF, 0x7A, 0x01, 0x16, 0x4D, 0xDC, + 0xFC, 0xBC, 0xCA, 0x24, 0xEF, 0x47, 0xBE, 0xDD, + 0x4A, 0xF9, 0x64, 0xCA, 0xBA, 0xF5, 0x74, 0xD0, + 0x53, 0x70, 0x75, 0xD9, 0x21, 0x91, 0x23, 0xF0, + 0x68, 0x02, 0xFF, 0x90, 0xA8, 0xC5, 0xB5, 0x87, + 0x6C, 0x17, 0x73, 0x4C, 0x8C, 0xFC, 0xBC, 0x7C, + 0x5E, 0xAE, 0x98, 0x34, 0xCC, 0x7C, 0xDC, 0xB6, + 0x26, 0x5F, 0x82, 0x6E, 0xF0, 0x41, 0x21, 0x43, + 0x00, 0xCB, 0x58, 0x13, 0xEB, 0x9B, 0xDB, 0x1B, + 0x0A, 0x8F, 0x3A, 0xD4, 0x1F, 0xA9, 0x51, 0x98, + 0xBA, 0xA2, 0x04, 0xF2, 0xA2, 0x9B, 0x88, 0x2D, + 0x89, 0x72, 0x4C, 0xA3, 0xD6, 0x64, 0xE4, 0x2C, + 0xAC, 0x6A, 0x2C, 0x40, 0x98, 0x28, 0x7E, 0xFF, + 0x7F, 0xE6, 0xF8, 0x6B, 0x22, 0xF7, 0x94, 0xE5, + 0x07, 0xDF, 0x58, 0x7F, 0xA4, 0xAC, 0xC7, 0xC5, + 0x5E, 0x9D, 0x27, 0x66, 0x6E, 0x12, 0x52, 0x50, + 0x8B, 0x48, 0x3E, 0x72, 0xAA, 0xB8, 0xFB, 0x9B, + 0xB2, 0xD2, 0xA4, 0xE8, 0x30, 0x02, 0x41, 0x21, + 0x61, 0x9A, 0x2C, 0xD0, 0x80, 0x20, 0xD2, 0xB3, + 0x33, 0x78, 0x46, 0x0A, 0x50, 0x83, 0x43, 0x43, + 0xE3, 0x38, 0xAC, 0xE3, 0xBB, 0xCB, 0x8B, 0x4B, + 0x8B, 0x72, 0xD4, 0xFA, 0x86, 0x36, 0x16, 0xF4, + 0x54, 0xAD, 0x78, 0x94, 0x51, 0x11, 0x47, 0xC6, + 0x46, 0xFB, 0x79, 0x1D, 0x47, 0xF4, 0xB3, 0xB1, + 0x32, 0xCF, 0x1F, 0x4B, 0x99, 0x84, 0xE6, 0x9B, + 0x18, 0x0E, 0xBC, 0xF5, 0xB5, 0x27, 0x5A, 0x6A, + 0x42, 0xCA, 0xCE, 0x02, 0x21, 0x21, 0x8D, 0x5D, + 0x1F, 0x87, 0x17, 0xBB, 0x43, 0xF3, 0x01, 0xCB, + 0x47, 0x5C, 0xCA, 0xA6, 0xCE, 0xE7, 0x97, 0xC5, + 0x0F, 0xD8, 0x73, 0xEF, 0x37, 0x87, 0xFD, 0x3C, + 0xBC, 0x67, 0xD1, 0xBD, 0x65, 0xD5, 0x51, 0x9C, + 0x1E, 0xA5, 0x17, 0x7A, 0xA2, 0x12, 0x72, 0xB2, + 0x32, 0xE9, 0xEF, 0x8D, 0x57, 0x87, 0xCD, 0x0F, + 0x8F, 0x54, 0xE2, 0x8E, 0x56, 0xE6, 0x66, 0xB4, + 0x36, 0x8D, 0x27, 0x4B, 0x9B, 0x2B, 0x36, 0xF2, + 0x0C, 0xD3, 0xE1, 0x9F, 0x45, 0x95, 0x81, 0x52, + 0xD0, 0x6B, 0x45, 0x3A, 0xE0, 0x30, 0xF0, 0x23, + 0xA1, 0x1A, 0x74, 0x0C, 0xD6, 0x06, 0x7E, 0xAB, + 0x29, 0x92, 0x14, 0x6E, 0xB4, 0x64, 0x30, 0xE5, + 0x67, 0xDC, 0xD2, 0xAB, 0x71, 0xA1, 0xC1, 0x01, + 0x81, 0x5A, 0x1C, 0x8F, 0xA8, 0xE7, 0x87, 0x47, + 0xC7, 0x1C, 0x5A, 0xC9, 0xEE, 0xA1, 0xC1, 0x01, + 0x81, 0x5A, 0x1C, 0x8F, 0xA8, 0xE7, 0x87, 0x47, + 0xC7, 0x1C, 0x5A, 0xC9, 0xEE, 0xA1, 0xC1, 0x01, + 0x81, 0x5A, 0x1C, 0x8F, 0xA8, 0xE7, 0x87, 0x47, + 0xC7, 0x1C, 0x5A, 0xC9, 0xEE, 0xA1, 0xC1, 0x01, + 0x81, 0x5A, 0x1C, 0x8F, 0xA8, 0xE7, 0x87, 0x47, + 0xC7, 0x1C, 0x5A, 0xC9, 0xEE, 0xA1, 0xC1, 0x01, + 0x81, 0x5A, 0x1C, 0x8F, 0xA8, 0xE7, 0x97, 0x40, + 0xC2, 0x79, 0xEB, 0x90, 0x4A, 0x9A, 0xEE, 0x36, + 0xB4, 0x0F, 0x19, 0x62, 0xB8, 0x68, 0x08, 0xC8, + 0x48, 0x93, 0x25, 0x49, 0x91, 0x21, 0x41, 0x81, + 0x01, 0xDA, 0xA0, 0xD4, 0x0C, 0xDC, 0x6C, 0xB4, + 0x34, 0x8F, 0xC1, 0xB4, 0x6C, 0xBC, 0x30, 0xF0, + 0x70, 0xAB, 0x1D, 0x71, 0xA9, 0x19, 0x78, 0xB8, + 0x38, 0xE3, 0x54, 0x38, 0xE1, 0x51, 0x30, 0xF8, + 0x38, 0xE3, 0x54, 0x39, 0xE0, 0x51, 0x70, 0xA0, + 0x24, 0xFD, 0x6A, 0x02, 0xFB, 0x4F, 0x0E, 0x4A, + 0xDA, 0x43, 0xE4, 0x99, 0x50, 0xF1, 0xD8, 0x3A, + 0x9E, 0x67, 0x98, 0xE6, 0x77, 0xD5, 0xFC, 0x6E, + 0xD7, 0x1E, 0xFD, 0x80, 0x0D, 0xAC, 0x99, 0x4C, + 0x99, 0x53, 0x4F, 0x09, 0x7B, 0xE1, 0x2B, 0x41, + 0x6B, 0x9A, 0x79, 0x40, 0xCD, 0x28, 0x1D, 0x88, + 0x5D, 0x53, 0xB0, 0x09, 0x84, 0xE1, 0x2B, 0x01, + 0x2B, 0x1E, 0x02, 0x80, 0xF2, 0xAC, 0x7A, 0x17, + 0x21, 0x17, 0x17, 0x96, 0xF8, 0xA5, 0x73, 0x6E, + 0x35, 0x33, 0x6B, 0xE9, 0xDF, 0x81, 0x3F, 0x84, + 0xEB, 0x8D, 0xE5, 0x72, 0x74, 0x3F, 0xE1, 0xCE, + 0xB5, 0x93, 0xDB, 0x49, 0x6F, 0x21, 0xBF, 0x88, + 0xB7, 0x93, 0xDB, 0x48, 0x6E, 0x21, 0xBE, 0x81, + 0xFE, 0xDA, 0x58, 0x2D, 0xF5, 0x25, 0x7D, 0xA4, + 0x24, 0x9F, 0xD5, 0xA0, 0x78, 0xA8, 0xFC, 0x3C, + 0xBC, 0x67, 0xD1, 0xBD, 0x65, 0xD5, 0xB5, 0x75, + 0xF5, 0x2E, 0x98, 0xF4, 0x2C, 0x9C, 0xFC, 0x3C, + 0xBC, 0x67, 0xF9, 0x9C, 0x44, 0x94, 0xD0, 0x19, + 0x99, 0x22, 0x84, 0x58, 0x82, 0x32, 0x52, 0x88, + 0x08, 0xB3, 0x75, 0x18, 0xC0, 0x70, 0x6C, 0xAB, + 0x2B, 0x90, 0x9A, 0xFB, 0x21, 0xF1, 0xAD, 0x65, + 0xE5, 0x5E, 0xFC, 0x9E, 0x44, 0x94, 0x38, 0xF6, + 0x74, 0xCF, 0xED, 0x87, 0x5F, 0x8F, 0x4B, 0x84, + 0x06, 0xBD, 0x4F, 0x25, 0xFD, 0x2D, 0xC1, 0x0E, + 0x8C, 0x37, 0x71, 0x04, 0xDC, 0x0C, 0xB8, 0x77, + 0xF5, 0x4E, 0x48, 0x35, 0xEF, 0x3F, 0xE7, 0x2F, + 0xAF, 0x14, 0x82, 0xFC, 0x26, 0xF6, 0x2A, 0xED, + 0x6D, 0xD6, 0x34, 0x4A, 0x90, 0x40, 0xE8, 0x3A, + 0xB8, 0x03, 0x5D, 0x37, 0xEF, 0x3F, 0x3B, 0xE3, + 0x61, 0xDA, 0x2C, 0x4A, 0x92, 0x42, 0x14, 0x95, + 0x15, 0x4F, 0x7B, 0x11, 0x78, 0x48, 0x2E, 0xF2, + 0x78, 0x32, 0x05, 0x6F, 0x15, 0xEE, 0x8E, 0xC7, + 0x4E, 0xB0, 0x04, 0x68, 0x55, 0xE1, 0x81, 0xE4, + 0x66, 0xBD, 0xEE, 0x87, 0x5F, 0x0A, 0x62, 0xA2, + 0x07, 0xDF, 0x69, 0xA0, 0x71, 0xC1, 0x00, 0x43, + 0xC5, 0xAF, 0x9D, 0xF7, 0x8A, 0x60, 0x27, 0xFA, + 0x8A, 0x51, 0xD1, 0xFC, 0x24, 0xA5, 0x40, 0x86, + 0x27, 0x7A, 0xCA, 0x8F, 0x84, 0x29, 0xB9, 0x79, + 0xF9, 0x22, 0xA2, 0x8F, 0x57, 0xD6, 0x31, 0xF7, + 0x56, 0x05, 0xB5, 0xF0, 0x6B, 0xC6, 0x56, 0x96, + 0x16, 0xCD, 0x4D, 0x60, 0xB8, 0x39, 0xDC, 0x1A, + 0xBB, 0xE9, 0x59, 0x1C, 0x57, 0xFA, 0x6A, 0xAA, + 0x2A, 0xF1, 0x71, 0x5C, 0x84, 0x15, 0xF8, 0x3E, + 0x8F, 0xD8, 0x68, 0x95, 0xC7, 0x71, 0x90, 0xDB, + 0x5D, 0x0F, 0xF0, 0xB5, 0x6E, 0xC3, 0x53, 0x93, + 0x13, 0xC8, 0x48, 0x65, 0xBD, 0x9C, 0x72, 0xB4, + 0x38, 0xEB, 0xDF, 0xFA, 0x22, 0xF7, 0x96, 0x56, + 0x77, 0x3C, 0x8C, 0x51, 0x0E, 0xB8, 0x19, 0x56, + 0xD0, 0xC2, 0x7F, 0xBA, 0x39, 0x94, 0x04, 0xC4, + 0x44, 0x9F, 0x1F, 0x32, 0xEA, 0x6B, 0x9A, 0x5C, + 0xFD, 0xB4, 0x04, 0x41, 0x8A, 0x27, 0xB7, 0x77, + 0xF7, 0x2C, 0xAC, 0x81, 0x59, 0x68, 0x9C, 0x5A, + 0xEB, 0xA3, 0x13, 0x5E, 0x13, 0xA5, 0xEC, 0x0F, + 0x06, 0x8E, 0x25, 0xB9, 0x61, 0xD1, 0x87, 0x06, + 0x86, 0xCC, 0xEC, 0x86, 0xDF, 0xF8, 0x9E, 0xD7, + 0x7E, 0xC0, 0x76, 0x1A, 0xDF, 0x9F, 0xC9, 0x48, + 0xC8, 0xB2, 0x9C, 0xF6, 0x9C, 0x8C, 0x60, 0x08, + 0x82, 0x79, 0xAE, 0xC2, 0x92, 0x08, 0xD2, 0xA8, + 0xB4, 0x77, 0xCD, 0xBD, 0x69, 0x54, 0xD6, 0x3C, + 0x94, 0x8F, 0x19, 0x75, 0x7F, 0x81, 0xED, 0xEF, + 0x24, 0xD8, 0x4B, 0x80, 0x7B, 0xEB, 0x6D, 0xBE, + 0x2E, 0xD5, 0x63, 0x12, 0x3A, 0x8A, 0xEA, 0x2A, + 0xAA, 0x71, 0xC7, 0xAB, 0x73, 0xC3, 0xA3, 0x63, + 0xE3, 0x38, 0x8F, 0xE3, 0x3F, 0x8F, 0x8B, 0x51, + 0xD3, 0x68, }; static unsigned char vfs5011_prepare_02[] = { /* 2565 B */ - 0x02, 0xF0, 0x00, 0x14, 0x00, 0x03, 0x00, 0x09, - 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, - 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, - 0x20, 0x04, 0x30, 0xE5, 0x03, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, - 0xEA, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x4C, 0x20, 0x04, 0x30, 0x0A, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, - 0x04, 0x30, 0x01, 0xDE, 0x01, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, - 0x30, 0x02, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, - 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x08, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x40, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x60, 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, - 0x30, 0x30, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x90, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, - 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x30, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xD8, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, - 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x04, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, - 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, - 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, - 0x30, 0x00, 0x00, 0x74, 0x01, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, - 0x74, 0x01, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, - 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, - 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, - 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, - 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, - 0xFF, 0xF9, 0x87, 0x20, 0xBB, 0xF8, 0x87, 0x00, - 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, - 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, - 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x07, 0x20, - 0xBA, 0xF8, 0x07, 0x20, 0xB9, 0xF8, 0x07, 0x20, - 0xB8, 0xF8, 0x07, 0x20, 0xB7, 0xF8, 0x07, 0x20, - 0xB6, 0xF8, 0x07, 0x20, 0xB5, 0xF8, 0x07, 0x20, - 0xB4, 0xF8, 0x07, 0x20, 0xB3, 0xF8, 0x07, 0x20, - 0xB2, 0xF8, 0x07, 0x20, 0xB1, 0xF8, 0x07, 0x22, - 0xB0, 0xF8, 0x07, 0x22, 0xAF, 0xF8, 0x07, 0x22, - 0xAE, 0xF8, 0x07, 0x22, 0xAD, 0xF8, 0x07, 0x22, - 0xAC, 0xF8, 0x07, 0x22, 0xAB, 0xF8, 0x07, 0x22, - 0xAA, 0xF8, 0x07, 0x22, 0xA9, 0xF8, 0x07, 0x22, - 0xA8, 0xF8, 0x07, 0x22, 0xA7, 0xF8, 0x07, 0x22, - 0xA6, 0xF8, 0x07, 0x22, 0xA5, 0xF8, 0x07, 0x22, - 0xA4, 0xF8, 0x07, 0x22, 0xA3, 0xF8, 0x07, 0x22, - 0xA2, 0xF8, 0x07, 0x22, 0xA1, 0xF8, 0x07, 0x22, - 0xA0, 0xF8, 0x07, 0x22, 0x9F, 0xF8, 0x07, 0x22, - 0x9E, 0xF8, 0x07, 0x22, 0x9D, 0xF8, 0x07, 0x22, - 0x9C, 0xF8, 0x07, 0x22, 0x9B, 0xF8, 0x07, 0x22, - 0x9A, 0xF8, 0x07, 0x22, 0x99, 0xF8, 0x07, 0x22, - 0x98, 0xF8, 0x07, 0x22, 0x97, 0xF8, 0x07, 0x22, - 0x96, 0xF8, 0x07, 0x22, 0x95, 0xF8, 0x07, 0x22, - 0x94, 0xF8, 0x07, 0x22, 0x93, 0xF8, 0x07, 0x22, - 0x92, 0xF8, 0x07, 0x22, 0x91, 0xF8, 0x07, 0x22, - 0x90, 0xF8, 0x07, 0x22, 0x8F, 0xF8, 0x07, 0x22, - 0x8E, 0xF8, 0x07, 0x22, 0x8D, 0xF8, 0x07, 0x22, - 0x8C, 0xF8, 0x07, 0x22, 0x8B, 0xF8, 0x07, 0x22, - 0x8A, 0xF8, 0x07, 0x22, 0x89, 0xF8, 0x07, 0x22, - 0x88, 0xF8, 0x07, 0x22, 0x87, 0xF8, 0x07, 0x22, - 0x86, 0xF8, 0x07, 0x22, 0x85, 0xF8, 0x07, 0x22, - 0x84, 0xF8, 0x07, 0x22, 0x83, 0xF8, 0x07, 0x22, - 0x82, 0xF8, 0x07, 0x22, 0x81, 0xF8, 0x07, 0x22, - 0x80, 0xF8, 0x07, 0x22, 0x7F, 0xF8, 0x07, 0x22, - 0x7E, 0xF8, 0x07, 0x22, 0x7D, 0xF8, 0x07, 0x22, - 0x7C, 0xF8, 0x07, 0x22, 0x7B, 0xF8, 0x07, 0x22, - 0x7A, 0xF8, 0x07, 0x22, 0x79, 0xF8, 0x07, 0x22, - 0x78, 0xF8, 0x07, 0x22, 0x77, 0xF8, 0x07, 0x22, - 0x76, 0xF8, 0x07, 0x22, 0x75, 0xF8, 0x07, 0x22, - 0x74, 0xF8, 0x07, 0x22, 0x73, 0xF8, 0x07, 0x22, - 0x72, 0xF8, 0x07, 0x22, 0x71, 0xF8, 0x07, 0x22, - 0x70, 0xF8, 0x07, 0x22, 0x6F, 0xF8, 0x07, 0x22, - 0x6E, 0xF8, 0x07, 0x22, 0x6D, 0xF8, 0x07, 0x22, - 0x6C, 0xF8, 0x07, 0x22, 0x6B, 0xF8, 0x07, 0x22, - 0x6A, 0xF8, 0x07, 0x22, 0x69, 0xF8, 0x07, 0x22, - 0x68, 0xF8, 0x07, 0x22, 0x67, 0xF8, 0x07, 0x22, - 0x66, 0xF8, 0x07, 0x22, 0x65, 0xF8, 0x07, 0x22, - 0x64, 0xF8, 0x07, 0x22, 0x63, 0xF8, 0x07, 0x22, - 0x62, 0xF8, 0x07, 0x22, 0x61, 0xF8, 0x07, 0x22, - 0x60, 0xF8, 0x07, 0x22, 0x5F, 0xF8, 0x07, 0x22, - 0x5E, 0xF8, 0x07, 0x22, 0x5D, 0xF8, 0x07, 0x22, - 0x5C, 0xF8, 0x07, 0x22, 0x5B, 0xF8, 0x07, 0x22, - 0x5A, 0xF8, 0x07, 0x22, 0x59, 0xF8, 0x07, 0x22, - 0x58, 0xF8, 0x07, 0x22, 0x57, 0xF8, 0x07, 0x22, - 0x56, 0xF8, 0x07, 0x22, 0x55, 0xF8, 0x07, 0x22, - 0x54, 0xF8, 0x07, 0x22, 0x53, 0xF8, 0x07, 0x22, - 0x52, 0xF8, 0x07, 0x22, 0x51, 0xF8, 0x07, 0x22, - 0x50, 0xF8, 0x07, 0x22, 0x4F, 0xF8, 0x07, 0x22, - 0x4E, 0xF8, 0x07, 0x22, 0x4D, 0xF8, 0x07, 0x22, - 0x4C, 0xF8, 0x07, 0x22, 0x4B, 0xF8, 0x07, 0x22, - 0x4A, 0xF8, 0x07, 0x22, 0x49, 0xF8, 0x07, 0x22, - 0x48, 0xF8, 0x07, 0x22, 0x47, 0xF8, 0x07, 0x22, - 0x46, 0xF8, 0x07, 0x22, 0x45, 0xF8, 0x07, 0x22, - 0x44, 0xF8, 0x07, 0x22, 0x43, 0xF8, 0x07, 0x22, - 0x42, 0xF8, 0x07, 0x22, 0x41, 0xF8, 0x07, 0x22, - 0x40, 0xF8, 0x07, 0x22, 0x3F, 0xF8, 0x07, 0x22, - 0x3E, 0xF8, 0x07, 0x22, 0x3D, 0xF8, 0x07, 0x22, - 0x3C, 0xF8, 0x07, 0x22, 0x3B, 0xF8, 0x07, 0x22, - 0x3A, 0xF8, 0x07, 0x22, 0x39, 0xF8, 0x07, 0x22, - 0x38, 0xF8, 0x07, 0x22, 0x37, 0xF8, 0x07, 0x22, - 0x36, 0xF8, 0x07, 0x22, 0x35, 0xF8, 0x07, 0x22, - 0x34, 0xF8, 0x07, 0x22, 0x33, 0xF8, 0x07, 0x22, - 0x32, 0xF8, 0x07, 0x22, 0x31, 0xF8, 0x07, 0x22, - 0x30, 0xF8, 0x07, 0x22, 0x2F, 0xF8, 0x07, 0x22, - 0x2E, 0xF8, 0x07, 0x22, 0x2D, 0xF8, 0x07, 0x22, - 0x2C, 0xF8, 0x07, 0x22, 0x2B, 0xF8, 0x07, 0x22, - 0x2A, 0xF8, 0x07, 0x22, 0x29, 0xF8, 0x07, 0x22, - 0x28, 0xF8, 0x07, 0x22, 0x27, 0xF8, 0x07, 0x22, - 0x26, 0xF8, 0x07, 0x22, 0x25, 0xF8, 0x07, 0x22, - 0x24, 0xF8, 0x07, 0x22, 0x23, 0xF8, 0x07, 0x20, - 0x22, 0xF8, 0x07, 0x20, 0x21, 0xF8, 0x07, 0x20, - 0x20, 0xF8, 0x07, 0x20, 0x1F, 0xF8, 0x07, 0x20, - 0x1E, 0xF8, 0x07, 0x20, 0x1D, 0xF8, 0x07, 0x20, - 0x1C, 0xF8, 0x07, 0x20, 0x1C, 0xF8, 0x07, 0x00, - 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, - 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, - 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, - 0xD8, 0xF8, 0x27, 0x20, 0xD9, 0xF8, 0x27, 0x20, - 0xDA, 0xF8, 0x27, 0x20, 0xDB, 0xF8, 0x27, 0x20, - 0xDC, 0xF8, 0x27, 0x20, 0xDD, 0xF8, 0x27, 0x20, - 0xDE, 0xF8, 0x27, 0x20, 0xDF, 0xF8, 0x27, 0x20, - 0xE0, 0xF8, 0x27, 0x20, 0xE1, 0xF8, 0x27, 0x20, - 0xE2, 0xF8, 0x27, 0x20, 0xE3, 0xF8, 0x27, 0x20, - 0xE4, 0xF8, 0x27, 0x20, 0xE5, 0xF8, 0x27, 0x20, - 0xE6, 0xF8, 0x27, 0x20, 0xE7, 0xF8, 0x27, 0x20, - 0xE8, 0xF8, 0x27, 0x20, 0xE9, 0xF8, 0x27, 0x20, - 0xEA, 0xF8, 0x27, 0x20, 0xEB, 0xF8, 0x27, 0x20, - 0xEC, 0xF8, 0x27, 0x20, 0xED, 0xF8, 0x27, 0x20, - 0xEE, 0xF8, 0x27, 0x20, 0xEF, 0xF8, 0x27, 0x20, - 0xF0, 0xF8, 0x27, 0x20, 0xF1, 0xF8, 0x27, 0x20, - 0xF2, 0xF8, 0x27, 0x20, 0xF3, 0xF8, 0x27, 0x20, - 0xF4, 0xF8, 0x27, 0x20, 0xF5, 0xF8, 0x27, 0x20, - 0xF6, 0xF8, 0x27, 0x20, 0xF7, 0xF8, 0x27, 0x20, - 0xF8, 0xF8, 0x27, 0x20, 0xF9, 0xF8, 0x27, 0x20, - 0xFA, 0xF8, 0x27, 0x20, 0xFB, 0xF8, 0x27, 0x20, - 0xFC, 0xF8, 0x27, 0x20, 0xFD, 0xF8, 0x27, 0x20, - 0xFE, 0xF8, 0x27, 0x20, 0xFF, 0xF8, 0x27, 0x20, - 0x00, 0xF9, 0x27, 0x20, 0xD7, 0xF8, 0x27, 0x20, - 0x00, 0xF8, 0x27, 0x20, 0x01, 0xF8, 0x27, 0x20, - 0x02, 0xF8, 0x27, 0x20, 0x03, 0xF8, 0x27, 0x20, - 0x04, 0xF8, 0x27, 0x20, 0x05, 0xF8, 0x27, 0x20, - 0x06, 0xF8, 0x27, 0x20, 0x07, 0xF8, 0x27, 0x20, - 0x08, 0xF8, 0x27, 0x20, 0x09, 0xF8, 0x27, 0x20, - 0x0A, 0xF8, 0x27, 0x20, 0x0B, 0xF8, 0x27, 0x20, - 0x0C, 0xF8, 0x27, 0x20, 0x0D, 0xF8, 0x27, 0x20, - 0x0E, 0xF8, 0x27, 0x20, 0x0F, 0xF8, 0x27, 0x20, - 0x10, 0xF8, 0x27, 0x20, 0x11, 0xF8, 0x27, 0x20, - 0x12, 0xF8, 0x27, 0x20, 0x13, 0xF8, 0x27, 0x20, - 0x14, 0xF8, 0x27, 0x20, 0x15, 0xF8, 0x27, 0x20, - 0x15, 0xF8, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, - 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, - 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, - 0x04, 0x17, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0E, - 0x00, 0x0C, 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, - 0x00, 0x0E, 0x00, 0x10, 0x20, 0xFD, 0x00, 0xFF, - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, - 0x00, 0x03, 0x00, 0x09, 0x00, 0x04, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x08, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x0C, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x10, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x14, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xC8, 0x20, 0x04, 0x30, 0x04, 0x00, 0x00, - 0x00, 0x04, 0x05, 0x00, 0x0E, 0x00, 0x14, 0x20, - 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x84, 0x00, 0x03, 0x00, 0x09, 0x00, - 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x90, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x98, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x07, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x60, 0x21, 0x04, 0x30, 0x07, 0x00, 0x00, 0x00, - 0x04, 0x15, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x28, 0x00, 0x00, + 0x02, 0xF0, 0x00, 0x14, 0x00, 0x03, 0x00, 0x09, + 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, + 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, + 0x20, 0x04, 0x30, 0xE5, 0x03, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, + 0xEA, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x4C, 0x20, 0x04, 0x30, 0x0A, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, + 0x04, 0x30, 0x01, 0xDE, 0x01, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, + 0x30, 0x02, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, + 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x08, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x40, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x60, 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x90, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, + 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x30, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xD8, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, + 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x04, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, + 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, + 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, + 0x30, 0x00, 0x00, 0x74, 0x01, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, + 0x74, 0x01, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, + 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, + 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, + 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, + 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, + 0xFF, 0xF9, 0x87, 0x20, 0xBB, 0xF8, 0x87, 0x00, + 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, + 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, + 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x07, 0x20, + 0xBA, 0xF8, 0x07, 0x20, 0xB9, 0xF8, 0x07, 0x20, + 0xB8, 0xF8, 0x07, 0x20, 0xB7, 0xF8, 0x07, 0x20, + 0xB6, 0xF8, 0x07, 0x20, 0xB5, 0xF8, 0x07, 0x20, + 0xB4, 0xF8, 0x07, 0x20, 0xB3, 0xF8, 0x07, 0x20, + 0xB2, 0xF8, 0x07, 0x20, 0xB1, 0xF8, 0x07, 0x22, + 0xB0, 0xF8, 0x07, 0x22, 0xAF, 0xF8, 0x07, 0x22, + 0xAE, 0xF8, 0x07, 0x22, 0xAD, 0xF8, 0x07, 0x22, + 0xAC, 0xF8, 0x07, 0x22, 0xAB, 0xF8, 0x07, 0x22, + 0xAA, 0xF8, 0x07, 0x22, 0xA9, 0xF8, 0x07, 0x22, + 0xA8, 0xF8, 0x07, 0x22, 0xA7, 0xF8, 0x07, 0x22, + 0xA6, 0xF8, 0x07, 0x22, 0xA5, 0xF8, 0x07, 0x22, + 0xA4, 0xF8, 0x07, 0x22, 0xA3, 0xF8, 0x07, 0x22, + 0xA2, 0xF8, 0x07, 0x22, 0xA1, 0xF8, 0x07, 0x22, + 0xA0, 0xF8, 0x07, 0x22, 0x9F, 0xF8, 0x07, 0x22, + 0x9E, 0xF8, 0x07, 0x22, 0x9D, 0xF8, 0x07, 0x22, + 0x9C, 0xF8, 0x07, 0x22, 0x9B, 0xF8, 0x07, 0x22, + 0x9A, 0xF8, 0x07, 0x22, 0x99, 0xF8, 0x07, 0x22, + 0x98, 0xF8, 0x07, 0x22, 0x97, 0xF8, 0x07, 0x22, + 0x96, 0xF8, 0x07, 0x22, 0x95, 0xF8, 0x07, 0x22, + 0x94, 0xF8, 0x07, 0x22, 0x93, 0xF8, 0x07, 0x22, + 0x92, 0xF8, 0x07, 0x22, 0x91, 0xF8, 0x07, 0x22, + 0x90, 0xF8, 0x07, 0x22, 0x8F, 0xF8, 0x07, 0x22, + 0x8E, 0xF8, 0x07, 0x22, 0x8D, 0xF8, 0x07, 0x22, + 0x8C, 0xF8, 0x07, 0x22, 0x8B, 0xF8, 0x07, 0x22, + 0x8A, 0xF8, 0x07, 0x22, 0x89, 0xF8, 0x07, 0x22, + 0x88, 0xF8, 0x07, 0x22, 0x87, 0xF8, 0x07, 0x22, + 0x86, 0xF8, 0x07, 0x22, 0x85, 0xF8, 0x07, 0x22, + 0x84, 0xF8, 0x07, 0x22, 0x83, 0xF8, 0x07, 0x22, + 0x82, 0xF8, 0x07, 0x22, 0x81, 0xF8, 0x07, 0x22, + 0x80, 0xF8, 0x07, 0x22, 0x7F, 0xF8, 0x07, 0x22, + 0x7E, 0xF8, 0x07, 0x22, 0x7D, 0xF8, 0x07, 0x22, + 0x7C, 0xF8, 0x07, 0x22, 0x7B, 0xF8, 0x07, 0x22, + 0x7A, 0xF8, 0x07, 0x22, 0x79, 0xF8, 0x07, 0x22, + 0x78, 0xF8, 0x07, 0x22, 0x77, 0xF8, 0x07, 0x22, + 0x76, 0xF8, 0x07, 0x22, 0x75, 0xF8, 0x07, 0x22, + 0x74, 0xF8, 0x07, 0x22, 0x73, 0xF8, 0x07, 0x22, + 0x72, 0xF8, 0x07, 0x22, 0x71, 0xF8, 0x07, 0x22, + 0x70, 0xF8, 0x07, 0x22, 0x6F, 0xF8, 0x07, 0x22, + 0x6E, 0xF8, 0x07, 0x22, 0x6D, 0xF8, 0x07, 0x22, + 0x6C, 0xF8, 0x07, 0x22, 0x6B, 0xF8, 0x07, 0x22, + 0x6A, 0xF8, 0x07, 0x22, 0x69, 0xF8, 0x07, 0x22, + 0x68, 0xF8, 0x07, 0x22, 0x67, 0xF8, 0x07, 0x22, + 0x66, 0xF8, 0x07, 0x22, 0x65, 0xF8, 0x07, 0x22, + 0x64, 0xF8, 0x07, 0x22, 0x63, 0xF8, 0x07, 0x22, + 0x62, 0xF8, 0x07, 0x22, 0x61, 0xF8, 0x07, 0x22, + 0x60, 0xF8, 0x07, 0x22, 0x5F, 0xF8, 0x07, 0x22, + 0x5E, 0xF8, 0x07, 0x22, 0x5D, 0xF8, 0x07, 0x22, + 0x5C, 0xF8, 0x07, 0x22, 0x5B, 0xF8, 0x07, 0x22, + 0x5A, 0xF8, 0x07, 0x22, 0x59, 0xF8, 0x07, 0x22, + 0x58, 0xF8, 0x07, 0x22, 0x57, 0xF8, 0x07, 0x22, + 0x56, 0xF8, 0x07, 0x22, 0x55, 0xF8, 0x07, 0x22, + 0x54, 0xF8, 0x07, 0x22, 0x53, 0xF8, 0x07, 0x22, + 0x52, 0xF8, 0x07, 0x22, 0x51, 0xF8, 0x07, 0x22, + 0x50, 0xF8, 0x07, 0x22, 0x4F, 0xF8, 0x07, 0x22, + 0x4E, 0xF8, 0x07, 0x22, 0x4D, 0xF8, 0x07, 0x22, + 0x4C, 0xF8, 0x07, 0x22, 0x4B, 0xF8, 0x07, 0x22, + 0x4A, 0xF8, 0x07, 0x22, 0x49, 0xF8, 0x07, 0x22, + 0x48, 0xF8, 0x07, 0x22, 0x47, 0xF8, 0x07, 0x22, + 0x46, 0xF8, 0x07, 0x22, 0x45, 0xF8, 0x07, 0x22, + 0x44, 0xF8, 0x07, 0x22, 0x43, 0xF8, 0x07, 0x22, + 0x42, 0xF8, 0x07, 0x22, 0x41, 0xF8, 0x07, 0x22, + 0x40, 0xF8, 0x07, 0x22, 0x3F, 0xF8, 0x07, 0x22, + 0x3E, 0xF8, 0x07, 0x22, 0x3D, 0xF8, 0x07, 0x22, + 0x3C, 0xF8, 0x07, 0x22, 0x3B, 0xF8, 0x07, 0x22, + 0x3A, 0xF8, 0x07, 0x22, 0x39, 0xF8, 0x07, 0x22, + 0x38, 0xF8, 0x07, 0x22, 0x37, 0xF8, 0x07, 0x22, + 0x36, 0xF8, 0x07, 0x22, 0x35, 0xF8, 0x07, 0x22, + 0x34, 0xF8, 0x07, 0x22, 0x33, 0xF8, 0x07, 0x22, + 0x32, 0xF8, 0x07, 0x22, 0x31, 0xF8, 0x07, 0x22, + 0x30, 0xF8, 0x07, 0x22, 0x2F, 0xF8, 0x07, 0x22, + 0x2E, 0xF8, 0x07, 0x22, 0x2D, 0xF8, 0x07, 0x22, + 0x2C, 0xF8, 0x07, 0x22, 0x2B, 0xF8, 0x07, 0x22, + 0x2A, 0xF8, 0x07, 0x22, 0x29, 0xF8, 0x07, 0x22, + 0x28, 0xF8, 0x07, 0x22, 0x27, 0xF8, 0x07, 0x22, + 0x26, 0xF8, 0x07, 0x22, 0x25, 0xF8, 0x07, 0x22, + 0x24, 0xF8, 0x07, 0x22, 0x23, 0xF8, 0x07, 0x20, + 0x22, 0xF8, 0x07, 0x20, 0x21, 0xF8, 0x07, 0x20, + 0x20, 0xF8, 0x07, 0x20, 0x1F, 0xF8, 0x07, 0x20, + 0x1E, 0xF8, 0x07, 0x20, 0x1D, 0xF8, 0x07, 0x20, + 0x1C, 0xF8, 0x07, 0x20, 0x1C, 0xF8, 0x07, 0x00, + 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, + 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, + 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, + 0xD8, 0xF8, 0x27, 0x20, 0xD9, 0xF8, 0x27, 0x20, + 0xDA, 0xF8, 0x27, 0x20, 0xDB, 0xF8, 0x27, 0x20, + 0xDC, 0xF8, 0x27, 0x20, 0xDD, 0xF8, 0x27, 0x20, + 0xDE, 0xF8, 0x27, 0x20, 0xDF, 0xF8, 0x27, 0x20, + 0xE0, 0xF8, 0x27, 0x20, 0xE1, 0xF8, 0x27, 0x20, + 0xE2, 0xF8, 0x27, 0x20, 0xE3, 0xF8, 0x27, 0x20, + 0xE4, 0xF8, 0x27, 0x20, 0xE5, 0xF8, 0x27, 0x20, + 0xE6, 0xF8, 0x27, 0x20, 0xE7, 0xF8, 0x27, 0x20, + 0xE8, 0xF8, 0x27, 0x20, 0xE9, 0xF8, 0x27, 0x20, + 0xEA, 0xF8, 0x27, 0x20, 0xEB, 0xF8, 0x27, 0x20, + 0xEC, 0xF8, 0x27, 0x20, 0xED, 0xF8, 0x27, 0x20, + 0xEE, 0xF8, 0x27, 0x20, 0xEF, 0xF8, 0x27, 0x20, + 0xF0, 0xF8, 0x27, 0x20, 0xF1, 0xF8, 0x27, 0x20, + 0xF2, 0xF8, 0x27, 0x20, 0xF3, 0xF8, 0x27, 0x20, + 0xF4, 0xF8, 0x27, 0x20, 0xF5, 0xF8, 0x27, 0x20, + 0xF6, 0xF8, 0x27, 0x20, 0xF7, 0xF8, 0x27, 0x20, + 0xF8, 0xF8, 0x27, 0x20, 0xF9, 0xF8, 0x27, 0x20, + 0xFA, 0xF8, 0x27, 0x20, 0xFB, 0xF8, 0x27, 0x20, + 0xFC, 0xF8, 0x27, 0x20, 0xFD, 0xF8, 0x27, 0x20, + 0xFE, 0xF8, 0x27, 0x20, 0xFF, 0xF8, 0x27, 0x20, + 0x00, 0xF9, 0x27, 0x20, 0xD7, 0xF8, 0x27, 0x20, + 0x00, 0xF8, 0x27, 0x20, 0x01, 0xF8, 0x27, 0x20, + 0x02, 0xF8, 0x27, 0x20, 0x03, 0xF8, 0x27, 0x20, + 0x04, 0xF8, 0x27, 0x20, 0x05, 0xF8, 0x27, 0x20, + 0x06, 0xF8, 0x27, 0x20, 0x07, 0xF8, 0x27, 0x20, + 0x08, 0xF8, 0x27, 0x20, 0x09, 0xF8, 0x27, 0x20, + 0x0A, 0xF8, 0x27, 0x20, 0x0B, 0xF8, 0x27, 0x20, + 0x0C, 0xF8, 0x27, 0x20, 0x0D, 0xF8, 0x27, 0x20, + 0x0E, 0xF8, 0x27, 0x20, 0x0F, 0xF8, 0x27, 0x20, + 0x10, 0xF8, 0x27, 0x20, 0x11, 0xF8, 0x27, 0x20, + 0x12, 0xF8, 0x27, 0x20, 0x13, 0xF8, 0x27, 0x20, + 0x14, 0xF8, 0x27, 0x20, 0x15, 0xF8, 0x27, 0x20, + 0x15, 0xF8, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, + 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, + 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, + 0x04, 0x17, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0E, + 0x00, 0x0C, 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, + 0x00, 0x0E, 0x00, 0x10, 0x20, 0xFD, 0x00, 0xFF, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, + 0x00, 0x03, 0x00, 0x09, 0x00, 0x04, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x08, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x0C, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x10, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x14, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xC8, 0x20, 0x04, 0x30, 0x04, 0x00, 0x00, + 0x00, 0x04, 0x05, 0x00, 0x0E, 0x00, 0x14, 0x20, + 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x84, 0x00, 0x03, 0x00, 0x09, 0x00, + 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x90, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x98, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x07, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x60, 0x21, 0x04, 0x30, 0x07, 0x00, 0x00, 0x00, + 0x04, 0x15, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x28, 0x00, 0x00, }; static unsigned char vfs5011_prepare_03[] = { /* 117 B */ - 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0xFF, 0x00, 0x00, 0xFF, 0xF4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xF4, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, 0xBF, 0x02, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xFF, 0x00, 0x00, 0xFF, 0xF4, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0xF4, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0xBF, 0x02, 0x00, }; static unsigned char vfs5011_prepare_04[] = { /* 2903 B */ - 0x02, 0xF0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x09, - 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, - 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, - 0x20, 0x04, 0x30, 0xE5, 0x03, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, - 0xEA, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x4C, 0x20, 0x04, 0x30, 0x0A, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, - 0x04, 0x30, 0x01, 0xDE, 0x01, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, - 0x30, 0x02, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, - 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x08, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x40, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x60, 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, - 0x30, 0x30, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x90, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, - 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x30, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, - 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xD8, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, - 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x04, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, - 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, - 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, - 0x30, 0x00, 0x00, 0x74, 0x01, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, - 0x74, 0x01, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, - 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, - 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, - 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, - 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, - 0xFF, 0xF9, 0x87, 0x20, 0xBB, 0xF8, 0x87, 0x00, - 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, - 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, - 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x07, 0x20, - 0xBA, 0xF8, 0x07, 0x20, 0xB9, 0xF8, 0x07, 0x20, - 0xB8, 0xF8, 0x07, 0x20, 0xB7, 0xF8, 0x07, 0x20, - 0xB6, 0xF8, 0x07, 0x20, 0xB5, 0xF8, 0x07, 0x20, - 0xB4, 0xF8, 0x07, 0x20, 0xB3, 0xF8, 0x07, 0x20, - 0xB2, 0xF8, 0x07, 0x20, 0xB1, 0xF8, 0x07, 0x22, - 0xB0, 0xF8, 0x07, 0x22, 0xAF, 0xF8, 0x07, 0x22, - 0xAE, 0xF8, 0x07, 0x22, 0xAD, 0xF8, 0x07, 0x22, - 0xAC, 0xF8, 0x07, 0x22, 0xAB, 0xF8, 0x07, 0x22, - 0xAA, 0xF8, 0x07, 0x22, 0xA9, 0xF8, 0x07, 0x22, - 0xA8, 0xF8, 0x07, 0x22, 0xA7, 0xF8, 0x07, 0x22, - 0xA6, 0xF8, 0x07, 0x22, 0xA5, 0xF8, 0x07, 0x22, - 0xA4, 0xF8, 0x07, 0x22, 0xA3, 0xF8, 0x07, 0x22, - 0xA2, 0xF8, 0x07, 0x22, 0xA1, 0xF8, 0x07, 0x22, - 0xA0, 0xF8, 0x07, 0x22, 0x9F, 0xF8, 0x07, 0x22, - 0x9E, 0xF8, 0x07, 0x22, 0x9D, 0xF8, 0x07, 0x22, - 0x9C, 0xF8, 0x07, 0x22, 0x9B, 0xF8, 0x07, 0x22, - 0x9A, 0xF8, 0x07, 0x22, 0x99, 0xF8, 0x07, 0x22, - 0x98, 0xF8, 0x07, 0x22, 0x97, 0xF8, 0x07, 0x22, - 0x96, 0xF8, 0x07, 0x22, 0x95, 0xF8, 0x07, 0x22, - 0x94, 0xF8, 0x07, 0x22, 0x93, 0xF8, 0x07, 0x22, - 0x92, 0xF8, 0x07, 0x22, 0x91, 0xF8, 0x07, 0x22, - 0x90, 0xF8, 0x07, 0x22, 0x8F, 0xF8, 0x07, 0x22, - 0x8E, 0xF8, 0x07, 0x22, 0x8D, 0xF8, 0x07, 0x22, - 0x8C, 0xF8, 0x07, 0x22, 0x8B, 0xF8, 0x07, 0x22, - 0x8A, 0xF8, 0x07, 0x22, 0x89, 0xF8, 0x07, 0x22, - 0x88, 0xF8, 0x07, 0x22, 0x87, 0xF8, 0x07, 0x22, - 0x86, 0xF8, 0x07, 0x22, 0x85, 0xF8, 0x07, 0x22, - 0x84, 0xF8, 0x07, 0x22, 0x83, 0xF8, 0x07, 0x22, - 0x82, 0xF8, 0x07, 0x22, 0x81, 0xF8, 0x07, 0x22, - 0x80, 0xF8, 0x07, 0x22, 0x7F, 0xF8, 0x07, 0x22, - 0x7E, 0xF8, 0x07, 0x22, 0x7D, 0xF8, 0x07, 0x22, - 0x7C, 0xF8, 0x07, 0x22, 0x7B, 0xF8, 0x07, 0x22, - 0x7A, 0xF8, 0x07, 0x22, 0x79, 0xF8, 0x07, 0x22, - 0x78, 0xF8, 0x07, 0x22, 0x77, 0xF8, 0x07, 0x22, - 0x76, 0xF8, 0x07, 0x22, 0x75, 0xF8, 0x07, 0x22, - 0x74, 0xF8, 0x07, 0x22, 0x73, 0xF8, 0x07, 0x22, - 0x72, 0xF8, 0x07, 0x22, 0x71, 0xF8, 0x07, 0x22, - 0x70, 0xF8, 0x07, 0x22, 0x6F, 0xF8, 0x07, 0x22, - 0x6E, 0xF8, 0x07, 0x22, 0x6D, 0xF8, 0x07, 0x22, - 0x6C, 0xF8, 0x07, 0x22, 0x6B, 0xF8, 0x07, 0x22, - 0x6A, 0xF8, 0x07, 0x22, 0x69, 0xF8, 0x07, 0x22, - 0x68, 0xF8, 0x07, 0x22, 0x67, 0xF8, 0x07, 0x22, - 0x66, 0xF8, 0x07, 0x22, 0x65, 0xF8, 0x07, 0x22, - 0x64, 0xF8, 0x07, 0x22, 0x63, 0xF8, 0x07, 0x22, - 0x62, 0xF8, 0x07, 0x22, 0x61, 0xF8, 0x07, 0x22, - 0x60, 0xF8, 0x07, 0x22, 0x5F, 0xF8, 0x07, 0x22, - 0x5E, 0xF8, 0x07, 0x22, 0x5D, 0xF8, 0x07, 0x22, - 0x5C, 0xF8, 0x07, 0x22, 0x5B, 0xF8, 0x07, 0x22, - 0x5A, 0xF8, 0x07, 0x22, 0x59, 0xF8, 0x07, 0x22, - 0x58, 0xF8, 0x07, 0x22, 0x57, 0xF8, 0x07, 0x22, - 0x56, 0xF8, 0x07, 0x22, 0x55, 0xF8, 0x07, 0x22, - 0x54, 0xF8, 0x07, 0x22, 0x53, 0xF8, 0x07, 0x22, - 0x52, 0xF8, 0x07, 0x22, 0x51, 0xF8, 0x07, 0x22, - 0x50, 0xF8, 0x07, 0x22, 0x4F, 0xF8, 0x07, 0x22, - 0x4E, 0xF8, 0x07, 0x22, 0x4D, 0xF8, 0x07, 0x22, - 0x4C, 0xF8, 0x07, 0x22, 0x4B, 0xF8, 0x07, 0x22, - 0x4A, 0xF8, 0x07, 0x22, 0x49, 0xF8, 0x07, 0x22, - 0x48, 0xF8, 0x07, 0x22, 0x47, 0xF8, 0x07, 0x22, - 0x46, 0xF8, 0x07, 0x22, 0x45, 0xF8, 0x07, 0x22, - 0x44, 0xF8, 0x07, 0x22, 0x43, 0xF8, 0x07, 0x22, - 0x42, 0xF8, 0x07, 0x22, 0x41, 0xF8, 0x07, 0x22, - 0x40, 0xF8, 0x07, 0x22, 0x3F, 0xF8, 0x07, 0x22, - 0x3E, 0xF8, 0x07, 0x22, 0x3D, 0xF8, 0x07, 0x22, - 0x3C, 0xF8, 0x07, 0x22, 0x3B, 0xF8, 0x07, 0x22, - 0x3A, 0xF8, 0x07, 0x22, 0x39, 0xF8, 0x07, 0x22, - 0x38, 0xF8, 0x07, 0x22, 0x37, 0xF8, 0x07, 0x22, - 0x36, 0xF8, 0x07, 0x22, 0x35, 0xF8, 0x07, 0x22, - 0x34, 0xF8, 0x07, 0x22, 0x33, 0xF8, 0x07, 0x22, - 0x32, 0xF8, 0x07, 0x22, 0x31, 0xF8, 0x07, 0x22, - 0x30, 0xF8, 0x07, 0x22, 0x2F, 0xF8, 0x07, 0x22, - 0x2E, 0xF8, 0x07, 0x22, 0x2D, 0xF8, 0x07, 0x22, - 0x2C, 0xF8, 0x07, 0x22, 0x2B, 0xF8, 0x07, 0x22, - 0x2A, 0xF8, 0x07, 0x22, 0x29, 0xF8, 0x07, 0x22, - 0x28, 0xF8, 0x07, 0x22, 0x27, 0xF8, 0x07, 0x22, - 0x26, 0xF8, 0x07, 0x22, 0x25, 0xF8, 0x07, 0x22, - 0x24, 0xF8, 0x07, 0x22, 0x23, 0xF8, 0x07, 0x20, - 0x22, 0xF8, 0x07, 0x20, 0x21, 0xF8, 0x07, 0x20, - 0x20, 0xF8, 0x07, 0x20, 0x1F, 0xF8, 0x07, 0x20, - 0x1E, 0xF8, 0x07, 0x20, 0x1D, 0xF8, 0x07, 0x20, - 0x1C, 0xF8, 0x07, 0x20, 0x1C, 0xF8, 0x07, 0x00, - 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, - 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, - 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, - 0xD8, 0xF8, 0x27, 0x20, 0xD9, 0xF8, 0x27, 0x20, - 0xDA, 0xF8, 0x27, 0x20, 0xDB, 0xF8, 0x27, 0x20, - 0xDC, 0xF8, 0x27, 0x20, 0xDD, 0xF8, 0x27, 0x20, - 0xDE, 0xF8, 0x27, 0x20, 0xDF, 0xF8, 0x27, 0x20, - 0xE0, 0xF8, 0x27, 0x20, 0xE1, 0xF8, 0x27, 0x20, - 0xE2, 0xF8, 0x27, 0x20, 0xE3, 0xF8, 0x27, 0x20, - 0xE4, 0xF8, 0x27, 0x20, 0xE5, 0xF8, 0x27, 0x20, - 0xE6, 0xF8, 0x27, 0x20, 0xE7, 0xF8, 0x27, 0x20, - 0xE8, 0xF8, 0x27, 0x20, 0xE9, 0xF8, 0x27, 0x20, - 0xEA, 0xF8, 0x27, 0x20, 0xEB, 0xF8, 0x27, 0x20, - 0xEC, 0xF8, 0x27, 0x20, 0xED, 0xF8, 0x27, 0x20, - 0xEE, 0xF8, 0x27, 0x20, 0xEF, 0xF8, 0x27, 0x20, - 0xF0, 0xF8, 0x27, 0x20, 0xF1, 0xF8, 0x27, 0x20, - 0xF2, 0xF8, 0x27, 0x20, 0xF3, 0xF8, 0x27, 0x20, - 0xF4, 0xF8, 0x27, 0x20, 0xF5, 0xF8, 0x27, 0x20, - 0xF6, 0xF8, 0x27, 0x20, 0xF7, 0xF8, 0x27, 0x20, - 0xF8, 0xF8, 0x27, 0x20, 0xF9, 0xF8, 0x27, 0x20, - 0xFA, 0xF8, 0x27, 0x20, 0xFB, 0xF8, 0x27, 0x20, - 0xFC, 0xF8, 0x27, 0x20, 0xFD, 0xF8, 0x27, 0x20, - 0xFE, 0xF8, 0x27, 0x20, 0xFF, 0xF8, 0x27, 0x20, - 0x00, 0xF9, 0x27, 0x20, 0xD7, 0xF8, 0x27, 0x20, - 0x00, 0xF8, 0x27, 0x20, 0x01, 0xF8, 0x27, 0x20, - 0x02, 0xF8, 0x27, 0x20, 0x03, 0xF8, 0x27, 0x20, - 0x04, 0xF8, 0x27, 0x20, 0x05, 0xF8, 0x27, 0x20, - 0x06, 0xF8, 0x27, 0x20, 0x07, 0xF8, 0x27, 0x20, - 0x08, 0xF8, 0x27, 0x20, 0x09, 0xF8, 0x27, 0x20, - 0x0A, 0xF8, 0x27, 0x20, 0x0B, 0xF8, 0x27, 0x20, - 0x0C, 0xF8, 0x27, 0x20, 0x0D, 0xF8, 0x27, 0x20, - 0x0E, 0xF8, 0x27, 0x20, 0x0F, 0xF8, 0x27, 0x20, - 0x10, 0xF8, 0x27, 0x20, 0x11, 0xF8, 0x27, 0x20, - 0x12, 0xF8, 0x27, 0x20, 0x13, 0xF8, 0x27, 0x20, - 0x14, 0xF8, 0x27, 0x20, 0x15, 0xF8, 0x27, 0x20, - 0x15, 0xF8, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, - 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, - 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, - 0x04, 0x05, 0x00, 0x0E, 0x00, 0x0C, 0x20, 0xFD, - 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x05, 0x00, 0x0E, 0x00, 0x10, - 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x05, 0x00, 0x00, 0x03, 0x00, 0x09, - 0x00, 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x10, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, - 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, - 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x4C, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x58, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, - 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, - 0x0E, 0x00, 0x14, 0x20, 0xFF, 0xFF, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, - 0x03, 0x00, 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, - 0x00, 0x88, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, - 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, - 0x00, 0x09, 0x00, 0x90, 0x21, 0x04, 0x30, 0x01, - 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, - 0x94, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, - 0x04, 0x03, 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, - 0x09, 0x00, 0xA0, 0x21, 0x04, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x20, - 0x21, 0x04, 0x30, 0x07, 0x00, 0x00, 0x00, 0x04, - 0x03, 0x00, 0x09, 0x00, 0x60, 0x21, 0x04, 0x30, - 0x07, 0x00, 0x00, 0x00, 0x04, 0x15, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x28, 0x00, - 0x00, 0x18, 0x00, 0x52, 0x01, 0x08, 0x00, 0x05, - 0x00, 0x0A, 0x00, 0xFA, 0x00, 0x1E, 0x00, 0xC8, - 0x00, 0x00, 0x00, 0x9F, 0x00, 0x38, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xFF, 0xFB, 0xF9, 0xFC, 0xFD, 0xFF, 0xFD, 0xFE, - 0x00, 0x01, 0x00, 0x00, 0x03, 0x01, 0x01, 0x02, - 0x06, 0x05, 0x05, 0x06, 0x05, 0x08, 0x0A, 0x06, - 0x09, 0x09, 0x06, 0x08, 0x05, 0x04, 0x03, 0x04, - 0x03, 0x05, 0x07, 0x07, 0x09, 0x05, 0x04, 0x03, - 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0xFF, 0x00, - 0xFF, 0x00, 0xFB, 0xFD, 0xFF, 0xFF, 0x01, 0xFF, - 0xFD, 0xFF, 0x01, 0x02, 0x01, 0xFE, 0xFF, 0x01, - 0xFE, 0xFC, 0x00, 0xFF, 0x01, 0x01, 0x00, 0x00, - 0xFF, 0xFF, 0x04, 0x03, 0x00, 0x01, 0xFE, 0x02, - 0x02, 0x03, 0x03, 0x00, 0xFF, 0xFA, 0xFB, 0xFC, - 0xFF, 0xFF, 0x02, 0xFF, 0x01, 0xFF, 0xFE, 0xFD, - 0xFF, 0xFE, 0xFB, 0xF9, 0xF9, 0xFC, 0xFC, 0xFC, - 0xF5, 0xF3, 0xF8, 0xF5, 0xF5, 0xF5, 0xF9, 0xFB, - 0xFE, 0xFC, 0xFA, 0xF8, 0xFC, 0xF9, 0xF7, 0xF6, - 0xF6, 0xF7, 0xFB, 0xF7, 0xF9, 0xF9, 0xF8, 0xF8, - 0xF1, 0xF6, 0xF9, 0xFC, 0xFE, 0xFC, 0xFE, 0x00, - 0xFB, 0xFE, 0xFC, 0xFC, 0xFC, 0xFB, 0xFD, 0xFB, - 0xFC, 0xFA, 0xFC, 0xFA, 0x01, 0x02, 0xFE, 0xFE, - 0xFC, 0xF7, 0xF4, 0xF4, 0xED, 0xE1, 0xD7, 0x01, - 0x04, 0x03, 0x04, 0x08, 0x0B, 0x09, 0x09, 0x09, - 0x05, 0x06, 0x08, 0x05, 0x03, 0x00, 0x00, 0x01, - 0x00, 0xFF, 0xFF, 0xFE, 0xFD, 0xFD, 0xFC, 0xFF, - 0x02, 0xFD, 0xFB, 0xFC, 0xFA, 0xFC, 0xFD, 0xFF, - 0xFF, 0xFC, 0xFC, 0xFB, 0xFC, 0xFE, 0xFF, 0x00, - 0x01, 0x0B, 0x09, 0x07, 0x06, 0x03, 0x06, 0x08, - 0x07, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0B, 0x0D, - 0x0E, 0x10, 0x15, 0x15, 0x19, 0x1B, 0x20, 0x01, - 0x00, 0xFF, 0xFF, 0xFE, 0xFD, 0xFD, 0xFC, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x02, 0xF0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x09, + 0x00, 0x04, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x18, 0x20, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x20, 0x04, 0x30, 0x08, + 0x00, 0x80, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x24, 0x20, 0x04, 0x30, 0x00, 0x00, 0xFF, 0x01, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x2C, 0x20, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x40, 0x20, 0x04, 0x30, 0xFF, 0x03, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, + 0x20, 0x04, 0x30, 0xE5, 0x03, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x48, 0x20, 0x04, 0x30, + 0xEA, 0x03, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x4C, 0x20, 0x04, 0x30, 0x0A, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x54, 0x20, + 0x04, 0x30, 0x01, 0xDE, 0x01, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x00, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, 0x04, + 0x30, 0x02, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x1C, 0x21, + 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x20, 0x21, 0x04, 0x30, 0x08, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x40, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x4C, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x58, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x5C, 0x21, 0x04, 0x30, 0x1F, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x60, 0x21, 0x04, 0x30, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x80, 0x21, 0x04, + 0x30, 0x30, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x88, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x90, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x94, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x9C, 0x21, 0x04, 0x30, 0x1F, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, 0x21, 0x04, + 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xC0, 0x21, 0x04, 0x30, 0x30, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xC8, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xCC, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xD0, 0x21, + 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xD4, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xD8, 0x21, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xDC, 0x21, 0x04, + 0x30, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xE0, 0x21, 0x04, 0x30, 0x04, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xA0, + 0x20, 0x04, 0x30, 0xEF, 0xE1, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0xA4, 0x20, 0x04, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0xB0, 0x20, 0x04, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0xC4, 0x20, + 0x04, 0x30, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0xCC, 0x20, 0x04, 0x30, 0x20, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x20, 0x04, + 0x30, 0x00, 0x00, 0x74, 0x01, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xA8, 0x20, 0x04, 0x30, 0xFE, 0x21, + 0x74, 0x01, 0x04, 0x03, 0x00, 0x09, 0x00, 0x04, + 0x00, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x38, + 0x00, 0x15, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x0C, 0x00, 0x00, 0x38, 0x01, 0x03, 0x02, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x10, 0x00, + 0x00, 0x38, 0x01, 0x07, 0x02, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x14, 0x00, 0x00, 0x38, 0x0C, + 0x0C, 0x05, 0x00, 0x04, 0x02, 0x00, 0x80, 0x05, + 0xFF, 0xF9, 0x87, 0x20, 0xBB, 0xF8, 0x87, 0x00, + 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, + 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x87, 0x00, + 0xBB, 0xF8, 0x87, 0x00, 0xBB, 0xF8, 0x07, 0x20, + 0xBA, 0xF8, 0x07, 0x20, 0xB9, 0xF8, 0x07, 0x20, + 0xB8, 0xF8, 0x07, 0x20, 0xB7, 0xF8, 0x07, 0x20, + 0xB6, 0xF8, 0x07, 0x20, 0xB5, 0xF8, 0x07, 0x20, + 0xB4, 0xF8, 0x07, 0x20, 0xB3, 0xF8, 0x07, 0x20, + 0xB2, 0xF8, 0x07, 0x20, 0xB1, 0xF8, 0x07, 0x22, + 0xB0, 0xF8, 0x07, 0x22, 0xAF, 0xF8, 0x07, 0x22, + 0xAE, 0xF8, 0x07, 0x22, 0xAD, 0xF8, 0x07, 0x22, + 0xAC, 0xF8, 0x07, 0x22, 0xAB, 0xF8, 0x07, 0x22, + 0xAA, 0xF8, 0x07, 0x22, 0xA9, 0xF8, 0x07, 0x22, + 0xA8, 0xF8, 0x07, 0x22, 0xA7, 0xF8, 0x07, 0x22, + 0xA6, 0xF8, 0x07, 0x22, 0xA5, 0xF8, 0x07, 0x22, + 0xA4, 0xF8, 0x07, 0x22, 0xA3, 0xF8, 0x07, 0x22, + 0xA2, 0xF8, 0x07, 0x22, 0xA1, 0xF8, 0x07, 0x22, + 0xA0, 0xF8, 0x07, 0x22, 0x9F, 0xF8, 0x07, 0x22, + 0x9E, 0xF8, 0x07, 0x22, 0x9D, 0xF8, 0x07, 0x22, + 0x9C, 0xF8, 0x07, 0x22, 0x9B, 0xF8, 0x07, 0x22, + 0x9A, 0xF8, 0x07, 0x22, 0x99, 0xF8, 0x07, 0x22, + 0x98, 0xF8, 0x07, 0x22, 0x97, 0xF8, 0x07, 0x22, + 0x96, 0xF8, 0x07, 0x22, 0x95, 0xF8, 0x07, 0x22, + 0x94, 0xF8, 0x07, 0x22, 0x93, 0xF8, 0x07, 0x22, + 0x92, 0xF8, 0x07, 0x22, 0x91, 0xF8, 0x07, 0x22, + 0x90, 0xF8, 0x07, 0x22, 0x8F, 0xF8, 0x07, 0x22, + 0x8E, 0xF8, 0x07, 0x22, 0x8D, 0xF8, 0x07, 0x22, + 0x8C, 0xF8, 0x07, 0x22, 0x8B, 0xF8, 0x07, 0x22, + 0x8A, 0xF8, 0x07, 0x22, 0x89, 0xF8, 0x07, 0x22, + 0x88, 0xF8, 0x07, 0x22, 0x87, 0xF8, 0x07, 0x22, + 0x86, 0xF8, 0x07, 0x22, 0x85, 0xF8, 0x07, 0x22, + 0x84, 0xF8, 0x07, 0x22, 0x83, 0xF8, 0x07, 0x22, + 0x82, 0xF8, 0x07, 0x22, 0x81, 0xF8, 0x07, 0x22, + 0x80, 0xF8, 0x07, 0x22, 0x7F, 0xF8, 0x07, 0x22, + 0x7E, 0xF8, 0x07, 0x22, 0x7D, 0xF8, 0x07, 0x22, + 0x7C, 0xF8, 0x07, 0x22, 0x7B, 0xF8, 0x07, 0x22, + 0x7A, 0xF8, 0x07, 0x22, 0x79, 0xF8, 0x07, 0x22, + 0x78, 0xF8, 0x07, 0x22, 0x77, 0xF8, 0x07, 0x22, + 0x76, 0xF8, 0x07, 0x22, 0x75, 0xF8, 0x07, 0x22, + 0x74, 0xF8, 0x07, 0x22, 0x73, 0xF8, 0x07, 0x22, + 0x72, 0xF8, 0x07, 0x22, 0x71, 0xF8, 0x07, 0x22, + 0x70, 0xF8, 0x07, 0x22, 0x6F, 0xF8, 0x07, 0x22, + 0x6E, 0xF8, 0x07, 0x22, 0x6D, 0xF8, 0x07, 0x22, + 0x6C, 0xF8, 0x07, 0x22, 0x6B, 0xF8, 0x07, 0x22, + 0x6A, 0xF8, 0x07, 0x22, 0x69, 0xF8, 0x07, 0x22, + 0x68, 0xF8, 0x07, 0x22, 0x67, 0xF8, 0x07, 0x22, + 0x66, 0xF8, 0x07, 0x22, 0x65, 0xF8, 0x07, 0x22, + 0x64, 0xF8, 0x07, 0x22, 0x63, 0xF8, 0x07, 0x22, + 0x62, 0xF8, 0x07, 0x22, 0x61, 0xF8, 0x07, 0x22, + 0x60, 0xF8, 0x07, 0x22, 0x5F, 0xF8, 0x07, 0x22, + 0x5E, 0xF8, 0x07, 0x22, 0x5D, 0xF8, 0x07, 0x22, + 0x5C, 0xF8, 0x07, 0x22, 0x5B, 0xF8, 0x07, 0x22, + 0x5A, 0xF8, 0x07, 0x22, 0x59, 0xF8, 0x07, 0x22, + 0x58, 0xF8, 0x07, 0x22, 0x57, 0xF8, 0x07, 0x22, + 0x56, 0xF8, 0x07, 0x22, 0x55, 0xF8, 0x07, 0x22, + 0x54, 0xF8, 0x07, 0x22, 0x53, 0xF8, 0x07, 0x22, + 0x52, 0xF8, 0x07, 0x22, 0x51, 0xF8, 0x07, 0x22, + 0x50, 0xF8, 0x07, 0x22, 0x4F, 0xF8, 0x07, 0x22, + 0x4E, 0xF8, 0x07, 0x22, 0x4D, 0xF8, 0x07, 0x22, + 0x4C, 0xF8, 0x07, 0x22, 0x4B, 0xF8, 0x07, 0x22, + 0x4A, 0xF8, 0x07, 0x22, 0x49, 0xF8, 0x07, 0x22, + 0x48, 0xF8, 0x07, 0x22, 0x47, 0xF8, 0x07, 0x22, + 0x46, 0xF8, 0x07, 0x22, 0x45, 0xF8, 0x07, 0x22, + 0x44, 0xF8, 0x07, 0x22, 0x43, 0xF8, 0x07, 0x22, + 0x42, 0xF8, 0x07, 0x22, 0x41, 0xF8, 0x07, 0x22, + 0x40, 0xF8, 0x07, 0x22, 0x3F, 0xF8, 0x07, 0x22, + 0x3E, 0xF8, 0x07, 0x22, 0x3D, 0xF8, 0x07, 0x22, + 0x3C, 0xF8, 0x07, 0x22, 0x3B, 0xF8, 0x07, 0x22, + 0x3A, 0xF8, 0x07, 0x22, 0x39, 0xF8, 0x07, 0x22, + 0x38, 0xF8, 0x07, 0x22, 0x37, 0xF8, 0x07, 0x22, + 0x36, 0xF8, 0x07, 0x22, 0x35, 0xF8, 0x07, 0x22, + 0x34, 0xF8, 0x07, 0x22, 0x33, 0xF8, 0x07, 0x22, + 0x32, 0xF8, 0x07, 0x22, 0x31, 0xF8, 0x07, 0x22, + 0x30, 0xF8, 0x07, 0x22, 0x2F, 0xF8, 0x07, 0x22, + 0x2E, 0xF8, 0x07, 0x22, 0x2D, 0xF8, 0x07, 0x22, + 0x2C, 0xF8, 0x07, 0x22, 0x2B, 0xF8, 0x07, 0x22, + 0x2A, 0xF8, 0x07, 0x22, 0x29, 0xF8, 0x07, 0x22, + 0x28, 0xF8, 0x07, 0x22, 0x27, 0xF8, 0x07, 0x22, + 0x26, 0xF8, 0x07, 0x22, 0x25, 0xF8, 0x07, 0x22, + 0x24, 0xF8, 0x07, 0x22, 0x23, 0xF8, 0x07, 0x20, + 0x22, 0xF8, 0x07, 0x20, 0x21, 0xF8, 0x07, 0x20, + 0x20, 0xF8, 0x07, 0x20, 0x1F, 0xF8, 0x07, 0x20, + 0x1E, 0xF8, 0x07, 0x20, 0x1D, 0xF8, 0x07, 0x20, + 0x1C, 0xF8, 0x07, 0x20, 0x1C, 0xF8, 0x07, 0x00, + 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, + 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, + 0xD7, 0xF8, 0xA7, 0x00, 0xD7, 0xF8, 0xA7, 0x00, + 0xD8, 0xF8, 0x27, 0x20, 0xD9, 0xF8, 0x27, 0x20, + 0xDA, 0xF8, 0x27, 0x20, 0xDB, 0xF8, 0x27, 0x20, + 0xDC, 0xF8, 0x27, 0x20, 0xDD, 0xF8, 0x27, 0x20, + 0xDE, 0xF8, 0x27, 0x20, 0xDF, 0xF8, 0x27, 0x20, + 0xE0, 0xF8, 0x27, 0x20, 0xE1, 0xF8, 0x27, 0x20, + 0xE2, 0xF8, 0x27, 0x20, 0xE3, 0xF8, 0x27, 0x20, + 0xE4, 0xF8, 0x27, 0x20, 0xE5, 0xF8, 0x27, 0x20, + 0xE6, 0xF8, 0x27, 0x20, 0xE7, 0xF8, 0x27, 0x20, + 0xE8, 0xF8, 0x27, 0x20, 0xE9, 0xF8, 0x27, 0x20, + 0xEA, 0xF8, 0x27, 0x20, 0xEB, 0xF8, 0x27, 0x20, + 0xEC, 0xF8, 0x27, 0x20, 0xED, 0xF8, 0x27, 0x20, + 0xEE, 0xF8, 0x27, 0x20, 0xEF, 0xF8, 0x27, 0x20, + 0xF0, 0xF8, 0x27, 0x20, 0xF1, 0xF8, 0x27, 0x20, + 0xF2, 0xF8, 0x27, 0x20, 0xF3, 0xF8, 0x27, 0x20, + 0xF4, 0xF8, 0x27, 0x20, 0xF5, 0xF8, 0x27, 0x20, + 0xF6, 0xF8, 0x27, 0x20, 0xF7, 0xF8, 0x27, 0x20, + 0xF8, 0xF8, 0x27, 0x20, 0xF9, 0xF8, 0x27, 0x20, + 0xFA, 0xF8, 0x27, 0x20, 0xFB, 0xF8, 0x27, 0x20, + 0xFC, 0xF8, 0x27, 0x20, 0xFD, 0xF8, 0x27, 0x20, + 0xFE, 0xF8, 0x27, 0x20, 0xFF, 0xF8, 0x27, 0x20, + 0x00, 0xF9, 0x27, 0x20, 0xD7, 0xF8, 0x27, 0x20, + 0x00, 0xF8, 0x27, 0x20, 0x01, 0xF8, 0x27, 0x20, + 0x02, 0xF8, 0x27, 0x20, 0x03, 0xF8, 0x27, 0x20, + 0x04, 0xF8, 0x27, 0x20, 0x05, 0xF8, 0x27, 0x20, + 0x06, 0xF8, 0x27, 0x20, 0x07, 0xF8, 0x27, 0x20, + 0x08, 0xF8, 0x27, 0x20, 0x09, 0xF8, 0x27, 0x20, + 0x0A, 0xF8, 0x27, 0x20, 0x0B, 0xF8, 0x27, 0x20, + 0x0C, 0xF8, 0x27, 0x20, 0x0D, 0xF8, 0x27, 0x20, + 0x0E, 0xF8, 0x27, 0x20, 0x0F, 0xF8, 0x27, 0x20, + 0x10, 0xF8, 0x27, 0x20, 0x11, 0xF8, 0x27, 0x20, + 0x12, 0xF8, 0x27, 0x20, 0x13, 0xF8, 0x27, 0x20, + 0x14, 0xF8, 0x27, 0x20, 0x15, 0xF8, 0x27, 0x20, + 0x15, 0xF8, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x08, 0x00, 0x10, 0x03, 0x18, 0x1C, + 0x10, 0x03, 0x18, 0x1C, 0x03, 0x00, 0x09, 0x00, + 0x00, 0x20, 0x04, 0x30, 0x80, 0x00, 0x00, 0x00, + 0x04, 0x05, 0x00, 0x0E, 0x00, 0x0C, 0x20, 0xFD, + 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x05, 0x00, 0x0E, 0x00, 0x10, + 0x20, 0xFD, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x05, 0x00, 0x00, 0x03, 0x00, 0x09, + 0x00, 0x04, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x08, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x0C, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x10, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x14, 0x21, 0x04, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0x18, 0x21, 0x04, 0x30, 0x01, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x44, + 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x48, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x4C, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x50, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x54, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x58, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0xC8, 0x20, 0x04, + 0x30, 0x04, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, + 0x0E, 0x00, 0x14, 0x20, 0xFF, 0xFF, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, + 0x03, 0x00, 0x09, 0x00, 0x84, 0x21, 0x04, 0x30, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, + 0x00, 0x88, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x8C, 0x21, + 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x04, 0x03, + 0x00, 0x09, 0x00, 0x90, 0x21, 0x04, 0x30, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, + 0x94, 0x21, 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x09, 0x00, 0x98, 0x21, 0x04, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, + 0x09, 0x00, 0xA0, 0x21, 0x04, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x09, 0x00, 0x20, + 0x21, 0x04, 0x30, 0x07, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x09, 0x00, 0x60, 0x21, 0x04, 0x30, + 0x07, 0x00, 0x00, 0x00, 0x04, 0x15, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x28, 0x00, + 0x00, 0x18, 0x00, 0x52, 0x01, 0x08, 0x00, 0x05, + 0x00, 0x0A, 0x00, 0xFA, 0x00, 0x1E, 0x00, 0xC8, + 0x00, 0x00, 0x00, 0x9F, 0x00, 0x38, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0xFF, 0xFB, 0xF9, 0xFC, 0xFD, 0xFF, 0xFD, 0xFE, + 0x00, 0x01, 0x00, 0x00, 0x03, 0x01, 0x01, 0x02, + 0x06, 0x05, 0x05, 0x06, 0x05, 0x08, 0x0A, 0x06, + 0x09, 0x09, 0x06, 0x08, 0x05, 0x04, 0x03, 0x04, + 0x03, 0x05, 0x07, 0x07, 0x09, 0x05, 0x04, 0x03, + 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0xFF, 0x00, + 0xFF, 0x00, 0xFB, 0xFD, 0xFF, 0xFF, 0x01, 0xFF, + 0xFD, 0xFF, 0x01, 0x02, 0x01, 0xFE, 0xFF, 0x01, + 0xFE, 0xFC, 0x00, 0xFF, 0x01, 0x01, 0x00, 0x00, + 0xFF, 0xFF, 0x04, 0x03, 0x00, 0x01, 0xFE, 0x02, + 0x02, 0x03, 0x03, 0x00, 0xFF, 0xFA, 0xFB, 0xFC, + 0xFF, 0xFF, 0x02, 0xFF, 0x01, 0xFF, 0xFE, 0xFD, + 0xFF, 0xFE, 0xFB, 0xF9, 0xF9, 0xFC, 0xFC, 0xFC, + 0xF5, 0xF3, 0xF8, 0xF5, 0xF5, 0xF5, 0xF9, 0xFB, + 0xFE, 0xFC, 0xFA, 0xF8, 0xFC, 0xF9, 0xF7, 0xF6, + 0xF6, 0xF7, 0xFB, 0xF7, 0xF9, 0xF9, 0xF8, 0xF8, + 0xF1, 0xF6, 0xF9, 0xFC, 0xFE, 0xFC, 0xFE, 0x00, + 0xFB, 0xFE, 0xFC, 0xFC, 0xFC, 0xFB, 0xFD, 0xFB, + 0xFC, 0xFA, 0xFC, 0xFA, 0x01, 0x02, 0xFE, 0xFE, + 0xFC, 0xF7, 0xF4, 0xF4, 0xED, 0xE1, 0xD7, 0x01, + 0x04, 0x03, 0x04, 0x08, 0x0B, 0x09, 0x09, 0x09, + 0x05, 0x06, 0x08, 0x05, 0x03, 0x00, 0x00, 0x01, + 0x00, 0xFF, 0xFF, 0xFE, 0xFD, 0xFD, 0xFC, 0xFF, + 0x02, 0xFD, 0xFB, 0xFC, 0xFA, 0xFC, 0xFD, 0xFF, + 0xFF, 0xFC, 0xFC, 0xFB, 0xFC, 0xFE, 0xFF, 0x00, + 0x01, 0x0B, 0x09, 0x07, 0x06, 0x03, 0x06, 0x08, + 0x07, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0B, 0x0D, + 0x0E, 0x10, 0x15, 0x15, 0x19, 0x1B, 0x20, 0x01, + 0x00, 0xFF, 0xFF, 0xFE, 0xFD, 0xFD, 0xFC, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, }; #endif diff --git a/libfprint/drivers/virtual-image.c b/libfprint/drivers/virtual-image.c new file mode 100644 index 00000000..6fdd3dbb --- /dev/null +++ b/libfprint/drivers/virtual-image.c @@ -0,0 +1,312 @@ +/* + * Virtual driver for image device debugging + * + * Copyright (C) 2019 Benjamin Berg + * + * 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 image based drivers. A small + * python script is provided to connect to it via a socket, allowing + * prints to be sent to this device programatically. + * Using this it is possible to test libfprint and fprintd. + */ + +#define FP_COMPONENT "virtual_image" + +#include "fpi-log.h" + +#include "../fpi-image.h" +#include "../fpi-image-device.h" + +#include +#include +#include + +struct _FpDeviceVirtualImage +{ + FpImageDevice parent; + + GSocketListener *listener; + GSocketConnection *connection; + GCancellable *cancellable; + + gint socket_fd; + gint client_fd; + + 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 start_listen (FpDeviceVirtualImage *dev); +static void recv_image (FpDeviceVirtualImage *dev, + GInputStream *stream); + +static void +recv_image_img_recv_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(GError) error = NULL; + FpDeviceVirtualImage *self; + FpImageDevice *device; + gssize bytes; + + bytes = g_input_stream_read_finish (G_INPUT_STREAM (source_object), res, &error); + + if (bytes <= 0) + { + if (bytes < 0) + { + g_warning ("Error receiving header for image data: %s", error->message); + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + } + + self = FPI_DEVICE_VIRTUAL_IMAGE (user_data); + g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); + self->connection = NULL; + return; + } + + self = FPI_DEVICE_VIRTUAL_IMAGE (user_data); + device = FP_IMAGE_DEVICE (self); + + fpi_image_device_report_finger_status (device, TRUE); + fpi_image_device_image_captured (device, g_steal_pointer (&self->recv_img)); + fpi_image_device_report_finger_status (device, FALSE); + + /* And, listen for more images from the same client. */ + recv_image (self, G_INPUT_STREAM (source_object)); +} + +static void +recv_image_hdr_recv_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(GError) error = NULL; + FpDeviceVirtualImage *self; + gssize bytes; + + bytes = g_input_stream_read_finish (G_INPUT_STREAM (source_object), res, &error); + + if (bytes <= 0) + { + if (bytes < 0) + { + g_warning ("Error receiving header for image data: %s", error->message); + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + } + + self = FPI_DEVICE_VIRTUAL_IMAGE (user_data); + g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); + self->connection = NULL; + 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."); + g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); + self->connection = NULL; + } + + if (self->recv_img_hdr[0] < 0 || self->recv_img_hdr[1] < 0) + { + switch (self->recv_img_hdr[0]) + { + case -1: + /* -1 is a retry error, just pass it through */ + fpi_image_device_retry_scan (FP_IMAGE_DEVICE (self), self->recv_img_hdr[1]); + break; + + case -2: + /* -2 is a fatal error, just pass it through*/ + fpi_image_device_session_error (FP_IMAGE_DEVICE (self), + fpi_device_error_new (self->recv_img_hdr[1])); + break; + + default: + /* disconnect client, it didn't play fair */ + g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); + self->connection = NULL; + } + + /* And, listen for more images from the same client. */ + 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); + g_input_stream_read_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 *dev, GInputStream *stream) +{ + g_input_stream_read_async (stream, + dev->recv_img_hdr, + sizeof (dev->recv_img_hdr), + G_PRIORITY_DEFAULT, + dev->cancellable, + recv_image_hdr_recv_cb, + dev); +} + +static void +new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) +{ + g_autoptr(GError) error = NULL; + GSocketConnection *connection; + GInputStream *stream; + FpDeviceVirtualImage *dev = user_data; + + 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 (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); + return; + } + + dev->connection = connection; + 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(GSocketListener) listener = NULL; + FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev); + const char *env; + g_autoptr(GSocketAddress) addr = NULL; + G_DEBUG_HERE (); + + self->client_fd = -1; + + 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)) + { + 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_cancellable_new (); + + start_listen (self); + + fpi_image_device_open_complete (dev, NULL); +} + +static void +dev_deinit (FpImageDevice *dev) +{ + FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev); + + G_DEBUG_HERE (); + + g_cancellable_cancel (self->cancellable); + g_clear_object (&self->cancellable); + g_clear_object (&self->listener); + g_clear_object (&self->connection); + + fpi_image_device_close_complete (dev, NULL); +} + +static void +fpi_device_virtual_image_init (FpDeviceVirtualImage *self) +{ +} + +static const FpIdEntry driver_ids[] = { + { .virtual_envvar = "FP_VIRTUAL_IMAGE" }, + { .virtual_envvar = NULL } +}; + +static void +fpi_device_virtual_image_class_init (FpDeviceVirtualImageClass *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 = "Virtual image device for debugging"; + dev_class->type = FP_DEVICE_TYPE_VIRTUAL; + dev_class->id_table = driver_ids; + + img_class->img_open = dev_init; + img_class->img_close = dev_deinit; +} diff --git a/libfprint/drivers_api.h b/libfprint/drivers_api.h index 7867e346..bb401cd3 100644 --- a/libfprint/drivers_api.h +++ b/libfprint/drivers_api.h @@ -23,17 +23,12 @@ #include -#include "fprint.h" +#include "fp_internal.h" + #include "fpi-log.h" -#include "fpi-dev.h" -#include "fpi-dev-img.h" -#include "fpi-core.h" +#include "fpi-usb-transfer.h" #include "fpi-ssm.h" -#include "fpi-poll.h" -#include "fpi-dev.h" -#include "fpi-usb.h" -#include "fpi-img.h" #include "fpi-assembling.h" -#include "drivers/driver_ids.h" +#include "fpi-image-device.h" #endif diff --git a/libfprint/fp-context.c b/libfprint/fp-context.c new file mode 100644 index 00000000..74dda51f --- /dev/null +++ b/libfprint/fp-context.c @@ -0,0 +1,364 @@ +/* + * FpContext - A FPrint context + * Copyright (C) 2019 Benjamin Berg + * + * 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 "context" +#include + +#include "fpi-context.h" +#include "fpi-device.h" +#include + +/** + * SECTION: fp-context + * @title: FpContext + * @short_description: Discover fingerprint devices + * + * The #FpContext allows you to discover fingerprint scanning hardware. This + * is the starting point when integrating libfprint into your software. + * + * The device-added and device-removed signals allow you to handle devices + * that may be hotplugged at runtime. + */ + +typedef struct +{ + GUsbContext *usb_ctx; + GCancellable *cancellable; + + gint pending_devices; + gboolean enumerated; + + GArray *drivers; + GPtrArray *devices; +} FpContextPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (FpContext, fp_context, G_TYPE_OBJECT) + +enum { + DEVICE_ADDED_SIGNAL, + DEVICE_REMOVED_SIGNAL, + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL] = { 0 }; + +static void +async_device_init_done_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) +{ + g_autoptr(GError) error = NULL; + FpDevice *device; + FpContext *context; + FpContextPrivate *priv; + + device = (FpDevice *) g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, &error); + if (!device) + { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + context = FP_CONTEXT (user_data); + priv = fp_context_get_instance_private (context); + priv->pending_devices--; + g_message ("Ignoring device due to initialization error: %s", error->message); + return; + } + + context = FP_CONTEXT (user_data); + priv = fp_context_get_instance_private (context); + priv->pending_devices--; + g_ptr_array_add (priv->devices, device); + g_signal_emit (context, signals[DEVICE_ADDED_SIGNAL], 0, device); +} + +static void +usb_device_added_cb (FpContext *self, GUsbDevice *device, GUsbContext *usb_ctx) +{ + FpContextPrivate *priv = fp_context_get_instance_private (self); + GType found_driver = G_TYPE_NONE; + const FpIdEntry *found_entry = NULL; + gint found_score = 0; + gint i; + guint16 pid, vid; + + pid = g_usb_device_get_pid (device); + vid = g_usb_device_get_vid (device); + + /* Find the best driver to handle this USB device. */ + for (i = 0; i < priv->drivers->len; i++) + { + GType driver = g_array_index (priv->drivers, GType, i); + FpDeviceClass *cls = FP_DEVICE_CLASS (g_type_class_ref (driver)); + const FpIdEntry *entry; + + if (cls->type != FP_DEVICE_TYPE_USB) + { + g_type_class_unref (cls); + continue; + } + + for (entry = cls->id_table; entry->pid; entry++) + { + gint driver_score = 50; + + if (entry->pid != pid || entry->vid != vid) + continue; + + if (cls->usb_discover) + driver_score = cls->usb_discover (device); + + /* Is this driver better than the one we had? */ + if (driver_score <= found_score) + continue; + + found_score = driver_score; + found_driver = driver; + found_entry = entry; + } + + g_type_class_unref (cls); + } + + if (found_driver == G_TYPE_NONE) + { + g_debug ("No driver found for USB device %04X:%04X", pid, vid); + return; + } + + priv->pending_devices++; + g_async_initable_new_async (found_driver, + G_PRIORITY_LOW, + priv->cancellable, + async_device_init_done_cb, + self, + "fp-usb-device", device, + "fp-driver-data", found_entry->driver_data, + NULL); +} + +static void +usb_device_removed_cb (FpContext *self, GUsbDevice *device, GUsbContext *usb_ctx) +{ + FpContextPrivate *priv = fp_context_get_instance_private (self); + gint i; + + /* Do the lazy way and just look at each device. */ + for (i = 0; i < priv->devices->len; i++) + { + FpDevice *dev = g_ptr_array_index (priv->devices, i); + FpDeviceClass *cls = FP_DEVICE_GET_CLASS (dev); + + if (cls->type != FP_DEVICE_TYPE_USB) + continue; + + if (fpi_device_get_usb_device (dev) == device) + { + g_signal_emit (self, signals[DEVICE_REMOVED_SIGNAL], 0, dev); + g_ptr_array_remove_index_fast (priv->devices, i); + + return; + } + } +} + +static void +fp_context_finalize (GObject *object) +{ + FpContext *self = (FpContext *) object; + FpContextPrivate *priv = fp_context_get_instance_private (self); + + g_clear_pointer (&priv->devices, g_ptr_array_unref); + + g_cancellable_cancel (priv->cancellable); + g_clear_object (&priv->cancellable); + g_clear_pointer (&priv->drivers, g_array_unref); + g_clear_object (&priv->usb_ctx); + + G_OBJECT_CLASS (fp_context_parent_class)->finalize (object); +} + +static void +fp_context_class_init (FpContextClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = fp_context_finalize; + + /** + * FpContext::device-added: + * @context: the #FpContext instance that emitted the signal + * @device: A #FpDevice + * + * This signal is emitted when a fingerprint reader is added. + **/ + signals[DEVICE_ADDED_SIGNAL] = g_signal_new ("device-added", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (FpContextClass, device_added), + NULL, + NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + FP_TYPE_DEVICE); + + /** + * FpContext::device-removed: + * @context: the #FpContext instance that emitted the signal + * @device: A #FpDevice + * + * This signal is emitted when a fingerprint reader is removed. + **/ + signals[DEVICE_REMOVED_SIGNAL] = g_signal_new ("device-removed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (FpContextClass, device_removed), + NULL, + NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + FP_TYPE_DEVICE); +} + +static void +fp_context_init (FpContext *self) +{ + g_autoptr(GError) error = NULL; + FpContextPrivate *priv = fp_context_get_instance_private (self); + + priv->drivers = g_array_new (TRUE, FALSE, sizeof (GType)); + fpi_get_driver_types (priv->drivers); + + priv->devices = g_ptr_array_new_with_free_func (g_object_unref); + + priv->cancellable = g_cancellable_new (); + priv->usb_ctx = g_usb_context_new (&error); + if (!priv->usb_ctx) + { + fp_warn ("Could not initialise USB Subsystem: %s", error->message); + } + else + { + g_usb_context_set_debug (priv->usb_ctx, G_LOG_LEVEL_INFO); + g_signal_connect_object (priv->usb_ctx, + "device-added", + G_CALLBACK (usb_device_added_cb), + self, + G_CONNECT_SWAPPED); + g_signal_connect_object (priv->usb_ctx, + "device-removed", + G_CALLBACK (usb_device_removed_cb), + self, + G_CONNECT_SWAPPED); + } +} + +/** + * fp_context_new: + * + * Create a new #FpContext. + * + * Returns: (transfer full): a newly created #FpContext + */ +FpContext * +fp_context_new (void) +{ + return g_object_new (FP_TYPE_CONTEXT, NULL); +} + +/** + * fp_context_enumerate: + * @context: a #FpContext + * + * Enumerate all devices. You should call this function exactly once + * at startup. Please note that it iterates the mainloop until all + * devices are enumerated. + */ +void +fp_context_enumerate (FpContext *context) +{ + FpContextPrivate *priv = fp_context_get_instance_private (context); + gint i; + + g_return_if_fail (FP_IS_CONTEXT (context)); + + if (priv->enumerated) + return; + + priv->enumerated = TRUE; + + /* USB devices are handled from callbacks */ + g_usb_context_enumerate (priv->usb_ctx); + + /* Handle Virtual devices based on environment variables */ + for (i = 0; i < priv->drivers->len; i++) + { + GType driver = g_array_index (priv->drivers, GType, i); + FpDeviceClass *cls = FP_DEVICE_CLASS (g_type_class_ref (driver)); + const FpIdEntry *entry; + + if (cls->type != FP_DEVICE_TYPE_VIRTUAL) + continue; + + for (entry = cls->id_table; entry->pid; entry++) + { + const gchar *val; + + val = g_getenv (entry->virtual_envvar); + if (!val || val[0] == '\0') + continue; + + g_debug ("Found virtual environment device: %s, %s", entry->virtual_envvar, val); + priv->pending_devices++; + g_async_initable_new_async (driver, + G_PRIORITY_LOW, + priv->cancellable, + async_device_init_done_cb, + context, + "fp-environ", val, + "fp-driver-data", entry->driver_data, + NULL); + g_debug ("created"); + } + + g_type_class_unref (cls); + } + + while (priv->pending_devices) + g_main_context_iteration (NULL, TRUE); +} + +/** + * fp_context_get_devices: + * @context: a #FpContext + * + * Get all devices. fp_context_enumerate() will be called as needed. + * + * Returns: (transfer none) (element-type FpDevice): a new #GPtrArray of #GUsbDevice's. + */ +GPtrArray * +fp_context_get_devices (FpContext *context) +{ + FpContextPrivate *priv = fp_context_get_instance_private (context); + + g_return_val_if_fail (FP_IS_CONTEXT (context), NULL); + + fp_context_enumerate (context); + + return priv->devices; +} diff --git a/libfprint/fp-context.h b/libfprint/fp-context.h new file mode 100644 index 00000000..aeaeca07 --- /dev/null +++ b/libfprint/fp-context.h @@ -0,0 +1,52 @@ +/* + * FpContext - A FPrint context + * Copyright (C) 2019 Benjamin Berg + * + * 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 "fp-device.h" + +G_BEGIN_DECLS + +#define FP_TYPE_CONTEXT (fp_context_get_type ()) +G_DECLARE_DERIVABLE_TYPE (FpContext, fp_context, FP, CONTEXT, GObject) + +/** + * FpContextClass: + * @device_added: Called when a new device is added + * @device_removed: Called when a device is removed + * + * Class structure for #FpContext instances. + */ +struct _FpContextClass +{ + GObjectClass parent_class; + + void (*device_added) (FpContext *context, + FpDevice *device); + void (*device_removed) (FpContext *context, + FpDevice *device); +}; + +FpContext *fp_context_new (void); + +void fp_context_enumerate (FpContext *context); + +GPtrArray *fp_context_get_devices (FpContext *context); + +G_END_DECLS diff --git a/libfprint/fp-device.c b/libfprint/fp-device.c new file mode 100644 index 00000000..f9ccb3cc --- /dev/null +++ b/libfprint/fp-device.c @@ -0,0 +1,2585 @@ +/* + * FpDevice - A fingerprint reader device + * Copyright (C) 2019 Benjamin Berg + * + * 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 "device" +#include "fpi-log.h" + +#include "fpi-device.h" + +/** + * SECTION: fp-device + * @title: FpDevice + * @short_description: Fingerprint device handling + * + * The #FpDevice object allows you to interact with fingerprint readers. + * Befor doing any other operation you need to fp_device_open() the device + * and after you are done you need to fp_device_close() it again. + */ + +/** + * SECTION: fpi-device + * @title: Internal FpDevice + * @short_description: Internal device routines + * + * The methods that are availabe for drivers to manipulate a device. See + * #FpDeviceClass for more information. Also note that most of these are + * not relevant for image based devices, see #FpImageDeviceClass in that + * case. + * + * Also see the public #FpDevice routines. + */ + +typedef struct +{ + FpDeviceType type; + + union + { + GUsbDevice *usb_device; + const gchar *virtual_env; + }; + + gboolean is_open; + + gchar *device_id; + gchar *device_name; + FpScanType scan_type; + + guint64 driver_data; + + gint nr_enroll_stages; + GSList *sources; + + /* We always make sure that only one task is run at a time. */ + FpDeviceAction current_action; + GTask *current_task; + GAsyncReadyCallback current_user_cb; + gulong current_cancellable_id; + GSource *current_idle_cancel_source; + GSource *current_task_idle_return_source; + + /* State for tasks */ + gboolean wait_for_finger; +} FpDevicePrivate; + +static void fp_device_async_initable_iface_init (GAsyncInitableIface *iface); + +G_DEFINE_TYPE_EXTENDED (FpDevice, fp_device, G_TYPE_OBJECT, G_TYPE_FLAG_ABSTRACT, + G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, + fp_device_async_initable_iface_init) + G_ADD_PRIVATE (FpDevice)) + +enum { + PROP_0, + PROP_DRIVER, + PROP_DEVICE_ID, + PROP_NAME, + PROP_NR_ENROLL_STAGES, + PROP_SCAN_TYPE, + PROP_FPI_ENVIRON, + PROP_FPI_USB_DEVICE, + PROP_FPI_DRIVER_DATA, + N_PROPS +}; + +static GParamSpec *properties[N_PROPS]; + +typedef struct +{ + FpPrint *print; + + FpEnrollProgress enroll_progress_cb; + gpointer enroll_progress_data; + GDestroyNotify enroll_progress_destroy; +} FpEnrollData; + +static void +enroll_data_free (gpointer free_data) +{ + FpEnrollData *data = free_data; + + if (data->enroll_progress_destroy) + data->enroll_progress_destroy (data->enroll_progress_data); + data->enroll_progress_data = NULL; + g_clear_object (&data->print); + g_free (data); +} + +/** + * fp_device_retry_quark: + * + * Return value: Quark representing a retryable error. + **/ +G_DEFINE_QUARK (fp - device - retry - quark, fp_device_retry) + +/** + * fp_device_error_quark: + * + * Return value: Quark representing a device error. + **/ +G_DEFINE_QUARK (fp - device - error - quark, fp_device_error) + +/** + * fpi_device_retry_new: + * @error: The #FpDeviceRetry error value describing the issue + * + * Create a new retry error code for use with fpi_device_verify_complete() + * and similar calls. + */ +GError * +fpi_device_retry_new (FpDeviceRetry error) +{ + const gchar *msg; + + switch (error) + { + case FP_DEVICE_RETRY_GENERAL: + msg = "Please try again."; + break; + + case FP_DEVICE_RETRY_TOO_SHORT: + msg = "The swipe was too short, please try again."; + break; + + case FP_DEVICE_RETRY_CENTER_FINGER: + msg = "The finger was not centered properly, please try again."; + break; + + case FP_DEVICE_RETRY_REMOVE_FINGER: + msg = "Please try again after removing the finger first."; + break; + + default: + g_warning ("Unsupported error, returning general error instead!"); + error = FP_DEVICE_RETRY_GENERAL; + msg = "Please try again."; + } + + return g_error_new_literal (FP_DEVICE_RETRY, error, msg); +} + +/** + * fpi_device_error_new: + * @error: The #FpDeviceRetry error value describing the issue + * + * Create a new error code for use with fpi_device_verify_complete() and + * similar calls. + */ +GError * +fpi_device_error_new (FpDeviceError error) +{ + const gchar *msg; + + switch (error) + { + case FP_DEVICE_ERROR_GENERAL: + msg = "An unspecified error occured!"; + break; + + case FP_DEVICE_ERROR_NOT_SUPPORTED: + msg = "The operation is not supported on this device!"; + break; + + case FP_DEVICE_ERROR_NOT_OPEN: + msg = "The device needs to be opened first!"; + break; + + case FP_DEVICE_ERROR_ALREADY_OPEN: + msg = "The device has already been opened!"; + break; + + case FP_DEVICE_ERROR_BUSY: + msg = "The device is still busy with another operation, please try again later."; + break; + + case FP_DEVICE_ERROR_PROTO: + msg = "The driver encountered a protocol error with the device."; + break; + + case FP_DEVICE_ERROR_DATA_INVALID: + msg = "Passed (print) data is not valid."; + break; + + case FP_DEVICE_ERROR_DATA_FULL: + msg = "On device storage space is full."; + break; + + case FP_DEVICE_ERROR_DATA_NOT_FOUND: + msg = "Print was not found on the devices storage."; + break; + + default: + g_warning ("Unsupported error, returning general error instead!"); + error = FP_DEVICE_ERROR_GENERAL; + msg = "An unspecified error occured!"; + } + + return g_error_new_literal (FP_DEVICE_ERROR, error, msg); +} + +/** + * fpi_device_retry_new_msg: + * @error: The #FpDeviceRetry error value describing the issue + * @msg: Custom message to use + * + * Create a new retry error code for use with fpi_device_verify_complete() + * and similar calls. + */ +GError * +fpi_device_retry_new_msg (FpDeviceRetry error, const gchar *msg) +{ + return g_error_new_literal (FP_DEVICE_RETRY, error, msg); +} + +/** + * fpi_device_error_new_msg: + * @error: The #FpDeviceRetry error value describing the issue + * @msg: Custom message to use + * + * Create a new error code for use with fpi_device_verify_complete() + * and similar calls. + */ +GError * +fpi_device_error_new_msg (FpDeviceError error, const gchar *msg) +{ + return g_error_new_literal (FP_DEVICE_ERROR, error, msg); +} + +static gboolean +fp_device_cancel_in_idle_cb (gpointer user_data) +{ + FpDevice *self = user_data; + FpDeviceClass *cls = FP_DEVICE_GET_CLASS (self); + FpDevicePrivate *priv = fp_device_get_instance_private (self); + + g_assert (cls->cancel); + g_assert (priv->current_action != FP_DEVICE_ACTION_NONE); + + g_debug ("Idle cancelling on ongoing operation!"); + + priv->current_idle_cancel_source = NULL; + + cls->cancel (self); + + return G_SOURCE_REMOVE; +} + +/* Notify the class that the task was cancelled; this should be connected + * with the GTask as the user_data object for automatic cleanup together + * with the task. */ +static void +fp_device_cancelled_cb (GCancellable *cancellable, FpDevice *self) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (self); + + priv->current_idle_cancel_source = g_idle_source_new (); + g_source_set_callback (priv->current_idle_cancel_source, + fp_device_cancel_in_idle_cb, + self, + NULL); + g_source_attach (priv->current_idle_cancel_source, NULL); + g_source_unref (priv->current_idle_cancel_source); +} + +static void +maybe_cancel_on_cancelled (FpDevice *device, + GCancellable *cancellable) +{ + FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device); + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + if (!cancellable || !cls->cancel) + return; + + priv->current_cancellable_id = g_cancellable_connect (cancellable, + G_CALLBACK (fp_device_cancelled_cb), + device, + NULL); +} + +static void +clear_device_cancel_action (FpDevice *device) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_clear_pointer (&priv->current_idle_cancel_source, g_source_destroy); + + if (priv->current_cancellable_id) + { + g_cancellable_disconnect (g_task_get_cancellable (priv->current_task), + priv->current_cancellable_id); + priv->current_cancellable_id = 0; + } +} + +static void +fp_device_constructed (GObject *object) +{ + FpDevice *self = (FpDevice *) object; + FpDeviceClass *cls = FP_DEVICE_GET_CLASS (self); + FpDevicePrivate *priv = fp_device_get_instance_private (self); + + priv->type = cls->type; + if (cls->nr_enroll_stages) + priv->nr_enroll_stages = cls->nr_enroll_stages; + priv->scan_type = cls->scan_type; + priv->device_name = g_strdup (cls->full_name); + priv->device_id = g_strdup ("0"); + + G_OBJECT_CLASS (fp_device_parent_class)->constructed (object); +} + +static void +fp_device_finalize (GObject *object) +{ + FpDevice *self = (FpDevice *) object; + FpDevicePrivate *priv = fp_device_get_instance_private (self); + + g_assert (priv->current_action == FP_DEVICE_ACTION_NONE); + g_assert (priv->current_task == NULL); + if (priv->is_open) + g_warning ("User destroyed open device! Not cleaning up properly!"); + + g_slist_free_full (priv->sources, (GDestroyNotify) g_source_destroy); + + g_clear_pointer (&priv->current_idle_cancel_source, g_source_destroy); + g_clear_pointer (&priv->current_task_idle_return_source, g_source_destroy); + + g_clear_pointer (&priv->device_id, g_free); + g_clear_pointer (&priv->device_name, g_free); + + G_OBJECT_CLASS (fp_device_parent_class)->finalize (object); +} + +static void +fp_device_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + FpDevice *self = FP_DEVICE (object); + FpDevicePrivate *priv = fp_device_get_instance_private (self); + + switch (prop_id) + { + case PROP_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_DRIVER: + g_value_set_static_string (value, FP_DEVICE_GET_CLASS (priv)->id); + break; + + case PROP_DEVICE_ID: + g_value_set_string (value, priv->device_id); + break; + + case PROP_NAME: + g_value_set_string (value, priv->device_name); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +fp_device_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + FpDevice *self = FP_DEVICE (object); + FpDevicePrivate *priv = fp_device_get_instance_private (self); + FpDeviceClass *cls = FP_DEVICE_GET_CLASS (self); + + /* _construct has not run yet, so we cannot use priv->type. */ + switch (prop_id) + { + case PROP_FPI_ENVIRON: + if (cls->type == FP_DEVICE_TYPE_VIRTUAL) + priv->virtual_env = g_value_dup_string (value); + else + g_assert (g_value_get_string (value) == NULL); + break; + + case PROP_FPI_USB_DEVICE: + if (cls->type == FP_DEVICE_TYPE_USB) + priv->usb_device = g_value_dup_object (value); + else + g_assert (g_value_get_object (value) == NULL); + break; + + case PROP_FPI_DRIVER_DATA: + priv->driver_data = g_value_get_uint64 (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +fp_device_async_initable_init_async (GAsyncInitable *initable, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autoptr(GTask) task = NULL; + FpDevice *self = FP_DEVICE (initable); + FpDevicePrivate *priv = fp_device_get_instance_private (self); + + /* It is next to impossible to call async_init at the wrong time. */ + g_assert (!priv->is_open); + g_assert (!priv->current_task); + + task = g_task_new (self, cancellable, callback, user_data); + if (g_task_return_error_if_cancelled (task)) + return; + + if (!FP_DEVICE_GET_CLASS (self)->probe) + { + g_task_return_boolean (task, TRUE); + return; + } + + priv->current_action = FP_DEVICE_ACTION_PROBE; + priv->current_task = g_steal_pointer (&task); + maybe_cancel_on_cancelled (self, cancellable); + + FP_DEVICE_GET_CLASS (self)->probe (self); +} + +static gboolean +fp_device_async_initable_init_finish (GAsyncInitable *initable, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void +fp_device_async_initable_iface_init (GAsyncInitableIface *iface) +{ + iface->init_async = fp_device_async_initable_init_async; + iface->init_finish = fp_device_async_initable_init_finish; +} + +static void +fp_device_class_init (FpDeviceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->constructed = fp_device_constructed; + object_class->finalize = fp_device_finalize; + object_class->get_property = fp_device_get_property; + object_class->set_property = fp_device_set_property; + + properties[PROP_NR_ENROLL_STAGES] = + g_param_spec_uint ("nr-enroll-stages", + "EnrollStages", + "Number of enroll stages needed on the device", + 0, G_MAXUINT, + 0, + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE); + + properties[PROP_SCAN_TYPE] = + g_param_spec_enum ("scan-type", + "ScanType", + "The scan type of the device", + FP_TYPE_SCAN_TYPE, FP_SCAN_TYPE_SWIPE, + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE); + + properties[PROP_DRIVER] = + g_param_spec_string ("driver", + "Driver", + "String describing the driver", + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE); + + properties[PROP_DEVICE_ID] = + g_param_spec_string ("device-id", + "Device ID", + "String describing the device, often generic but may be a serial number", + "", + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE); + + properties[PROP_NAME] = + g_param_spec_string ("name", + "Device Name", + "Human readable name for the device", + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE); + + properties[PROP_FPI_ENVIRON] = + g_param_spec_string ("fp-environ", + "Virtual Environment", + "Private: The environment variable for the virtual device", + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); + + properties[PROP_FPI_USB_DEVICE] = + g_param_spec_object ("fp-usb-device", + "USB Device", + "Private: The USB device for the device", + G_USB_TYPE_DEVICE, + G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); + + properties[PROP_FPI_DRIVER_DATA] = + g_param_spec_uint64 ("fp-driver-data", + "Driver Data", + "Private: The driver data from the ID table entry", + 0, + G_MAXUINT64, + 0, + G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); + + g_object_class_install_properties (object_class, N_PROPS, properties); +} + +static void +fp_device_init (FpDevice *self) +{ +} + +/** + * fp_device_get_driver: + * @device: A #FpDevice + * + * Returns: (transfer none): The ID of the driver + */ +const gchar * +fp_device_get_driver (FpDevice *device) +{ + g_return_val_if_fail (FP_IS_DEVICE (device), NULL); + + return FP_DEVICE_GET_CLASS (device)->id; +} + +/** + * fp_device_get_device_id: + * @device: A #FpDevice + * + * Returns: (transfer none): The ID of the device + */ +const gchar * +fp_device_get_device_id (FpDevice *device) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_val_if_fail (FP_IS_DEVICE (device), NULL); + + return priv->device_id; +} + +/** + * fp_device_get_name: + * @device: A #FpDevice + * + * Returns: (transfer none): The human readable name of the device + */ +const gchar * +fp_device_get_name (FpDevice *device) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_val_if_fail (FP_IS_DEVICE (device), NULL); + + return priv->device_name; +} + +/** + * fp_device_get_scan_type: + * @device: A #FpDevice + * + * Retrieves the scan type of the device. + * + * Returns: The #FpScanType + */ +FpScanType +fp_device_get_scan_type (FpDevice *device) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_val_if_fail (FP_IS_DEVICE (device), FP_SCAN_TYPE_SWIPE); + + return priv->scan_type; +} + +/** + * fp_device_get_nr_enroll_stages: + * @device: A #FpDevice + * + * Retrieves the number of enroll stages for this device. + * + * Returns: The number of enroll stages + */ +gint +fp_device_get_nr_enroll_stages (FpDevice *device) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_val_if_fail (FP_IS_DEVICE (device), -1); + + return priv->nr_enroll_stages; +} + +/** + * fp_device_supports_identify: + * @device: A #FpDevice + * + * Check whether the device supports identification. + * + * Returns: Whether the device supports identification + */ +gboolean +fp_device_supports_identify (FpDevice *device) +{ + FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device); + + g_return_val_if_fail (FP_IS_DEVICE (device), FALSE); + + return cls->identify != NULL; +} + +/** + * fp_device_supports_capture: + * @device: A #FpDevice + * + * Check whether the device supports capturing images. + * + * Returns: Whether the device supports image capture + */ +gboolean +fp_device_supports_capture (FpDevice *device) +{ + FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device); + + g_return_val_if_fail (FP_IS_DEVICE (device), FALSE); + + return cls->capture != NULL; +} + +/** + * fp_device_has_storage: + * @device: A #FpDevice + * + * Whether the device has on-chip storage. If it has, you can list the + * prints stored on the with fp_device_list_prints() and you should + * always delete prints from the device again using + * fp_device_delete_print(). + */ +gboolean +fp_device_has_storage (FpDevice *device) +{ + FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device); + + g_return_val_if_fail (FP_IS_DEVICE (device), FALSE); + + return cls->list != NULL; +} + +/** + * fp_device_open: + * @device: a #FpDevice + * @cancellable: (nullable): a #GCancellable, or %NULL + * @callback: the function to call on completion + * @user_data: the data to pass to @callback + * + * Start an asynchronous operation to open the device. The callback will + * be called once the operation has finished. Retrieve the result with + * fp_device_open_finish(). + */ +void +fp_device_open (FpDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autoptr(GTask) task = NULL; + FpDevicePrivate *priv = fp_device_get_instance_private (device); + GError *error = NULL; + + task = g_task_new (device, cancellable, callback, user_data); + if (g_task_return_error_if_cancelled (task)) + return; + + if (priv->is_open) + { + g_task_return_error (task, + fpi_device_error_new (FP_DEVICE_ERROR_ALREADY_OPEN)); + return; + } + + if (priv->current_task) + { + g_task_return_error (task, + fpi_device_error_new (FP_DEVICE_ERROR_BUSY)); + return; + } + + switch (priv->type) + { + case FP_DEVICE_TYPE_USB: + if (!g_usb_device_open (priv->usb_device, &error)) + { + g_task_return_error (task, error); + return; + } + break; + + case FP_DEVICE_TYPE_VIRTUAL: + break; + + default: + g_assert_not_reached (); + g_task_return_error (task, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL)); + return; + } + + priv->current_action = FP_DEVICE_ACTION_OPEN; + priv->current_task = g_steal_pointer (&task); + maybe_cancel_on_cancelled (device, cancellable); + + FP_DEVICE_GET_CLASS (device)->open (device); +} + +/** + * fp_device_open_finish: + * @device: A #FpDevice + * @result: A #GAsyncResult + * @error: Return location for errors, or %NULL to ignore + * + * Finish an asynchronous operation to open the device. + * See fp_device_open(). + * + * Returns: (type void): %FALSE on error, %TRUE otherwise + */ +gboolean +fp_device_open_finish (FpDevice *device, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (result), error); +} + +/** + * fp_device_close: + * @device: a #FpDevice + * @cancellable: (nullable): a #GCancellable, or %NULL + * @callback: the function to call on completion + * @user_data: the data to pass to @callback + * + * Start an asynchronous operation to close the device. The callback will + * be called once the operation has finished. Retrieve the result with + * fp_device_close_finish(). + */ +void +fp_device_close (FpDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autoptr(GTask) task = NULL; + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + task = g_task_new (device, cancellable, callback, user_data); + if (g_task_return_error_if_cancelled (task)) + return; + + if (!priv->is_open) + { + g_task_return_error (task, + fpi_device_error_new (FP_DEVICE_ERROR_NOT_OPEN)); + return; + } + + if (priv->current_task) + { + g_task_return_error (task, + fpi_device_error_new (FP_DEVICE_ERROR_BUSY)); + return; + } + + priv->current_action = FP_DEVICE_ACTION_CLOSE; + priv->current_task = g_steal_pointer (&task); + maybe_cancel_on_cancelled (device, cancellable); + + FP_DEVICE_GET_CLASS (device)->close (device); +} + +/** + * fp_device_close_finish: + * @device: A #FpDevice + * @result: A #GAsyncResult + * @error: Return location for errors, or %NULL to ignore + * + * Finish an asynchronous operation to close the device. + * See fp_device_close(). + * + * Returns: (type void): %FALSE on error, %TRUE otherwise + */ +gboolean +fp_device_close_finish (FpDevice *device, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (result), error); +} + + +/** + * fp_device_enroll: + * @device: a #FpDevice + * @template_print: (transfer floating): a #FpPrint + * @cancellable: (nullable): a #GCancellable, or %NULL + * @progress_cb: (nullable) (scope notified): progress reporting callback + * @progress_data: (closure progress_cb): user data for @progress_cb + * @progress_destroy: (destroy progress_data): Destroy notify for @progress_data + * @callback: (scope async): the function to call on completion + * @user_data: the data to pass to @callback + * + * Start an asynchronous operation to enroll a print. The callback will + * be called once the operation has finished. Retrieve the result with + * fp_device_enroll_finish(). + * + * The @template_print parameter is a #FpPrint with available metadata filled + * 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 successed. + */ +void +fp_device_enroll (FpDevice *device, + FpPrint *template_print, + GCancellable *cancellable, + FpEnrollProgress progress_cb, + gpointer progress_data, + GDestroyNotify progress_destroy, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autoptr(GTask) task = NULL; + FpDevicePrivate *priv = fp_device_get_instance_private (device); + FpEnrollData *data; + FpPrintType print_type; + + task = g_task_new (device, cancellable, callback, user_data); + if (g_task_return_error_if_cancelled (task)) + return; + + if (!priv->is_open) + { + g_task_return_error (task, + fpi_device_error_new (FP_DEVICE_ERROR_NOT_OPEN)); + return; + } + + if (priv->current_task) + { + g_task_return_error (task, + fpi_device_error_new (FP_DEVICE_ERROR_BUSY)); + return; + } + + if (!FP_IS_PRINT (template_print)) + { + g_warning ("User did not pass a print template!"); + g_task_return_error (task, + fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID)); + return; + } + + g_object_get (template_print, "fp-type", &print_type, NULL); + if (print_type != FP_PRINT_UNDEFINED) + { + g_warning ("Passed print template must be newly created and blank!"); + g_task_return_error (task, + fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID)); + return; + } + + priv->current_action = FP_DEVICE_ACTION_ENROLL; + priv->current_task = g_steal_pointer (&task); + maybe_cancel_on_cancelled (device, cancellable); + + data = g_new0 (FpEnrollData, 1); + data->print = g_object_ref_sink (template_print); + data->enroll_progress_cb = progress_cb; + data->enroll_progress_data = progress_data; + + // Attach the progress data as task data so that it is destroyed + g_task_set_task_data (priv->current_task, data, enroll_data_free); + + FP_DEVICE_GET_CLASS (device)->enroll (device); +} + +/** + * fp_device_enroll_finish: + * @device: A #FpDevice + * @result: A #GAsyncResult + * @error: Return location for errors, or %NULL to ignore + * + * Finish an asynchronous operation to enroll a print. You should check + * for an error of type %FP_DEVICE_RETRY to prompt the user again if there + * was an interaction issue. + * See fp_device_enroll(). + * + * Returns: (transfer full): The enrolled #FpPrint, or %NULL on error + */ +FpPrint * +fp_device_enroll_finish (FpDevice *device, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_pointer (G_TASK (result), error); +} + +/** + * fp_device_verify: + * @device: a #FpDevice + * @enrolled_print: a #FpPrint to verify + * @cancellable: (nullable): a #GCancellable, or %NULL + * @callback: the function to call on completion + * @user_data: the data to pass to @callback + * + * Start an asynchronous operation to close the device. The callback will + * be called once the operation has finished. Retrieve the result with + * fp_device_verify_finish(). + */ +void +fp_device_verify (FpDevice *device, + FpPrint *enrolled_print, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autoptr(GTask) task = NULL; + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + task = g_task_new (device, cancellable, callback, user_data); + if (g_task_return_error_if_cancelled (task)) + return; + + if (!priv->is_open) + { + g_task_return_error (task, + fpi_device_error_new (FP_DEVICE_ERROR_NOT_OPEN)); + return; + } + + if (priv->current_task) + { + g_task_return_error (task, + fpi_device_error_new (FP_DEVICE_ERROR_BUSY)); + return; + } + + priv->current_action = FP_DEVICE_ACTION_VERIFY; + priv->current_task = g_steal_pointer (&task); + maybe_cancel_on_cancelled (device, cancellable); + + g_task_set_task_data (priv->current_task, + g_object_ref (enrolled_print), + g_object_unref); + + FP_DEVICE_GET_CLASS (device)->verify (device); +} + +/** + * fp_device_verify_finish: + * @device: A #FpDevice + * @result: A #GAsyncResult + * @match: (out): Whether the user presented the correct finger + * @print: (out) (transfer full) (nullable): Location to store the scanned print, or %NULL to ignore + * @error: Return location for errors, or %NULL to ignore + * + * Finish an asynchronous operation to verify an enrolled print. You should check + * for an error of type %FP_DEVICE_RETRY to prompt the user again if there + * was an interaction issue. + * + * With @print you can fetch the newly created print and retrieve the image data if available. + * + * See fp_device_verify(). + * + * Returns: (type void): %FALSE on error, %TRUE otherwise + */ +gboolean +fp_device_verify_finish (FpDevice *device, + GAsyncResult *result, + gboolean *match, + FpPrint **print, + GError **error) +{ + gint res; + + res = g_task_propagate_int (G_TASK (result), error); + + if (print) + { + *print = g_object_get_data (G_OBJECT (result), "print"); + if (*print) + g_object_ref (*print); + } + + if (match) + *match = res == FPI_MATCH_SUCCESS; + + return res != FPI_MATCH_ERROR; +} + +/** + * fp_device_identify: + * @device: a #FpDevice + * @prints: (element-type FpPrint) (transfer none): #GPtrArray of #FpPrint + * @cancellable: (nullable): a #GCancellable, or %NULL + * @callback: the function to call on completion + * @user_data: the data to pass to @callback + * + * Start an asynchronous operation to identify prints. The callback will + * be called once the operation has finished. Retrieve the result with + * fp_device_identify_finish(). + */ +void +fp_device_identify (FpDevice *device, + GPtrArray *prints, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autoptr(GTask) task = NULL; + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + task = g_task_new (device, cancellable, callback, user_data); + if (g_task_return_error_if_cancelled (task)) + return; + + if (!priv->is_open) + { + g_task_return_error (task, + fpi_device_error_new (FP_DEVICE_ERROR_NOT_OPEN)); + return; + } + + if (priv->current_task) + { + g_task_return_error (task, + fpi_device_error_new (FP_DEVICE_ERROR_BUSY)); + return; + } + + priv->current_action = FP_DEVICE_ACTION_IDENTIFY; + priv->current_task = g_steal_pointer (&task); + maybe_cancel_on_cancelled (device, cancellable); + + g_task_set_task_data (priv->current_task, + g_ptr_array_ref (prints), + (GDestroyNotify) g_ptr_array_unref); + + FP_DEVICE_GET_CLASS (device)->verify (device); +} + +/** + * fp_device_identify_finish: + * @device: A #FpDevice + * @result: A #GAsyncResult + * @match: (out) (transfer full) (nullable): Location for the matched #FpPrint, or %NULL + * @print: (out) (transfer full) (nullable): Location for the new #FpPrint, or %NULL + * @error: Return location for errors, or %NULL to ignore + * + * Finish an asynchronous operation to identify a print. You should check + * for an error of type %FP_DEVICE_RETRY to prompt the user again if there + * was an interaction issue. + * + * Use @match to find the print that matched. With @print you can fetch the + * newly created print and retrieve the image data if available. + * + * See fp_device_identify(). + * + * Returns: (type void): %FALSE on error, %TRUE otherwise + */ +gboolean +fp_device_identify_finish (FpDevice *device, + GAsyncResult *result, + FpPrint **match, + FpPrint **print, + GError **error) +{ + if (print) + { + *print = g_object_get_data (G_OBJECT (result), "print"); + if (*print) + g_object_ref (*print); + } + if (match) + { + *match = g_object_get_data (G_OBJECT (result), "match"); + if (*match) + g_object_ref (*match); + } + + return g_task_propagate_boolean (G_TASK (result), error); +} + +/** + * fp_device_capture: + * @device: a #FpDevice + * @wait_for_finger: Whether to wait for a finger or not + * @cancellable: (nullable): a #GCancellable, or %NULL + * @callback: the function to call on completion + * @user_data: the data to pass to @callback + * + * Start an asynchronous operation to capture an image. The callback will + * be called once the operation has finished. Retrieve the result with + * fp_device_capture_finish(). + */ +void +fp_device_capture (FpDevice *device, + gboolean wait_for_finger, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autoptr(GTask) task = NULL; + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + task = g_task_new (device, cancellable, callback, user_data); + if (g_task_return_error_if_cancelled (task)) + return; + + if (!priv->is_open) + { + g_task_return_error (task, + fpi_device_error_new (FP_DEVICE_ERROR_NOT_OPEN)); + return; + } + + if (priv->current_task) + { + g_task_return_error (task, + fpi_device_error_new (FP_DEVICE_ERROR_BUSY)); + return; + } + + priv->current_action = FP_DEVICE_ACTION_CAPTURE; + priv->current_task = g_steal_pointer (&task); + maybe_cancel_on_cancelled (device, cancellable); + + priv->wait_for_finger = wait_for_finger; + + FP_DEVICE_GET_CLASS (device)->capture (device); +} + +/** + * fp_device_capture_finish: + * @device: A #FpDevice + * @result: A #GAsyncResult + * @error: Return location for errors, or %NULL to ignore + * + * Finish an asynchronous operation to capture an image. You should check + * for an error of type %FP_DEVICE_RETRY to prompt the user again if there + * was an interaction issue. + * + * See fp_device_capture(). + * + * Returns: (transfer full): #FpImage or %NULL on error + */ +FpImage * +fp_device_capture_finish (FpDevice *device, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_pointer (G_TASK (result), error); +} + +/** + * fp_device_delete_print: + * @device: a #FpDevice + * @enrolled_print: a #FpPrint to delete + * @cancellable: (nullable): a #GCancellable, or %NULL + * @callback: the function to call on completion + * @user_data: the data to pass to @callback + * + * Start an asynchronous operation to delete a print from the device. + * The callback will be called once the operation has finished. Retrieve + * the result with fp_device_delete_print_finish(). + * + * This only makes sense on devices that store prints on-chip, but is safe + * to always call. + */ +void +fp_device_delete_print (FpDevice *device, + FpPrint *enrolled_print, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autoptr(GTask) task = NULL; + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + task = g_task_new (device, cancellable, callback, user_data); + if (g_task_return_error_if_cancelled (task)) + return; + + if (!priv->is_open) + { + g_task_return_error (task, + fpi_device_error_new (FP_DEVICE_ERROR_NOT_OPEN)); + return; + } + + if (priv->current_task) + { + g_task_return_error (task, + fpi_device_error_new (FP_DEVICE_ERROR_BUSY)); + return; + } + + /* Succeed immediately if delete is not implemented. */ + if (!FP_DEVICE_GET_CLASS (device)->delete) + { + g_task_return_boolean (task, TRUE); + return; + } + + priv->current_action = FP_DEVICE_ACTION_DELETE; + priv->current_task = g_steal_pointer (&task); + maybe_cancel_on_cancelled (device, cancellable); + + g_task_set_task_data (priv->current_task, + g_object_ref (enrolled_print), + g_object_unref); + + FP_DEVICE_GET_CLASS (device)->delete (device); +} + +/** + * fp_device_delete_print_finish: + * @device: A #FpDevice + * @result: A #GAsyncResult + * @error: Return location for errors, or %NULL to ignore + * + * Finish an asynchronous operation to delete an enrolled print. + * + * See fp_device_delete_print(). + * + * Returns: (type void): %FALSE on error, %TRUE otherwise + */ +gboolean +fp_device_delete_print_finish (FpDevice *device, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (result), error); +} + +/** + * fp_device_list_prints: + * @device: a #FpDevice + * @cancellable: (nullable): a #GCancellable, or %NULL + * @callback: the function to call on completion + * @user_data: the data to pass to @callback + * + * Start an asynchronous operation to list all prints stored on the device. + * This only makes sense on devices that store prints on-chip. + * + * Retrieve the result with fp_device_list_prints_finish(). + */ +void +fp_device_list_prints (FpDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autoptr(GTask) task = NULL; + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + task = g_task_new (device, cancellable, callback, user_data); + if (g_task_return_error_if_cancelled (task)) + return; + + if (!priv->is_open) + { + g_task_return_error (task, + fpi_device_error_new (FP_DEVICE_ERROR_NOT_OPEN)); + return; + } + + if (priv->current_task) + { + g_task_return_error (task, + fpi_device_error_new (FP_DEVICE_ERROR_BUSY)); + return; + } + + priv->current_action = FP_DEVICE_ACTION_LIST; + priv->current_task = g_steal_pointer (&task); + maybe_cancel_on_cancelled (device, cancellable); + + FP_DEVICE_GET_CLASS (device)->list (device); +} + +/** + * fp_device_list_prints_finish: + * @device: A #FpDevice + * @result: A #GAsyncResult + * @error: Return location for errors, or %NULL to ignore + * + * Finish an asynchronous operation to list all device stored prints. + * + * See fp_device_list_prints(). + * + * Returns: (element-type FpPrint) (transfer container): Array of prints or %NULL on error + */ +GPtrArray * +fp_device_list_prints_finish (FpDevice *device, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_pointer (G_TASK (result), error); +} + +typedef struct +{ + GSource source; + FpDevice *device; + FpTimeoutFunc callback; + gpointer user_data; +} FpDeviceTimeoutSource; + +gboolean +device_timeout_cb (gpointer user_data) +{ + FpDeviceTimeoutSource *source = user_data; + + source->callback (source->device, source->user_data); + + return G_SOURCE_REMOVE; +} + +void +timeout_finalize (GSource *source) +{ + FpDeviceTimeoutSource *timeout_source = (FpDeviceTimeoutSource *) source; + FpDevicePrivate *priv; + + priv = fp_device_get_instance_private (timeout_source->device); + priv->sources = g_slist_remove (priv->sources, source); +} + +static gboolean +timeout_dispatch (GSource *source, GSourceFunc callback, gpointer user_data) +{ + FpDeviceTimeoutSource *timeout_source = (FpDeviceTimeoutSource *) source; + + ((FpTimeoutFunc) callback)(timeout_source->device, user_data); + + return G_SOURCE_REMOVE; +} + +static GSourceFuncs timeout_funcs = { + NULL, /* prepare */ + NULL, /* check */ + timeout_dispatch, + timeout_finalize, + NULL, NULL +}; + +/* Private API functions */ + +/** + * fpi_device_set_nr_enroll_stages: + * @device: The #FpDevice + * @enroll_stages: The number of enroll stages + * + * Updates the reported number of enroll stages that the device needs. + * If all supported devices have the same number of stages, then the + * value can simply be set in the class. + */ +void +fpi_device_set_nr_enroll_stages (FpDevice *device, + gint enroll_stages) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_if_fail (FP_IS_DEVICE (device)); + + priv->nr_enroll_stages = enroll_stages; + g_object_notify_by_pspec (G_OBJECT (device), properties[PROP_NR_ENROLL_STAGES]); +} + +/** + * fpi_device_set_scan_type: + * @device: The #FpDevice + * @scan_type: The scan type of the device + * + * Updates the the scan type of the device from the default. + * If all supported devices have the same scan type, then the + * value can simply be set in the class. + */ +void +fpi_device_set_scan_type (FpDevice *device, + FpScanType scan_type) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_if_fail (FP_IS_DEVICE (device)); + + priv->scan_type = scan_type; + g_object_notify_by_pspec (G_OBJECT (device), properties[PROP_SCAN_TYPE]); +} + +/** + * fpi_device_add_timeout: + * @device: The #FpDevice + * @interval: The interval in milliseconds + * @func: The #FpTimeoutFunc to call on timeout + * @user_data: User data to pass to the callback + * + * Register a timeout to run. Drivers should always make sure that timers are + * cancelled when appropriate. + * + * Returns: (transfer none): A newly created and attached #GSource + */ +GSource * +fpi_device_add_timeout (FpDevice *device, + gint interval, + FpTimeoutFunc func, + gpointer user_data) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + FpDeviceTimeoutSource *source; + + source = (FpDeviceTimeoutSource *) g_source_new (&timeout_funcs, + sizeof (FpDeviceTimeoutSource)); + source->device = device; + source->user_data = user_data; + + g_source_attach (&source->source, NULL); + g_source_set_callback (&source->source, (GSourceFunc) func, user_data, NULL); + g_source_set_ready_time (&source->source, + g_source_get_time (&source->source) + interval * (guint64) 1000); + priv->sources = g_slist_prepend (priv->sources, source); + g_source_unref (&source->source); + + return &source->source; +} + +/** + * fpi_device_get_usb_device: + * @device: The #FpDevice + * + * Get the #GUsbDevice for this #FpDevice. Only permissible to call if the + * #FpDevice is of type %FP_DEVICE_TYPE_USB. + * + * Returns: The #GUsbDevice + */ +GUsbDevice * +fpi_device_get_usb_device (FpDevice *device) +{ + 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_USB, NULL); + + return priv->usb_device; +} + +/** + * fpi_device_get_virtual_env: + * @device: The #FpDevice + * + * Get the value of the environment variable that caused the virtual #FpDevice to be + * generated. Only permissible to call if the #FpDevice is of type %FP_DEVICE_TYPE_VIRTUAL. + * + * Returns: The value of the environment variable + */ +const gchar * +fpi_device_get_virtual_env (FpDevice *device) +{ + 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_VIRTUAL, NULL); + + return priv->virtual_env; +} + +/** + * fpi_device_get_current_action: + * @device: The #FpDevice + * + * Get the currently ongoing action or %FP_DEVICE_ACTION_NONE if there + * is no operation at this time. + * + * This is useful for drivers that might share code paths between different + * actions (e.g. verify and identify) and want to find out again later which + * action was started in the beginning. + * + * Returns: The ongoing #FpDeviceAction + */ +FpDeviceAction +fpi_device_get_current_action (FpDevice *device) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_val_if_fail (FP_IS_DEVICE (device), FP_DEVICE_ACTION_NONE); + + return priv->current_action; +} + +/** + * fpi_device_action_is_cancelled: + * @device: The #FpDevice + * + * Checks whether the current action has been cancelled by the user. + * This is equivalent to first getting the cancellable using + * fpi_device_get_cancellable() and then checking whether it has been + * cancelled (if it is non-NULL). + * + * Returns: %TRUE if action should be cancelled + */ +gboolean +fpi_device_action_is_cancelled (FpDevice *device) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + GCancellable *cancellable; + + g_return_val_if_fail (FP_IS_DEVICE (device), TRUE); + g_return_val_if_fail (priv->current_action != FP_DEVICE_ACTION_NONE, TRUE); + + cancellable = g_task_get_cancellable (priv->current_task); + + return cancellable ? g_cancellable_is_cancelled (cancellable) : FALSE; +} + +/** + * fpi_device_get_driver_data: + * @device: The #FpDevice + * + * Returns: The driver data from the #FpIdEntry table entry + */ +guint64 +fpi_device_get_driver_data (FpDevice *device) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_val_if_fail (FP_IS_DEVICE (device), 0); + + return priv->driver_data; +} + +/** + * fpi_device_get_enroll_data: + * @device: The #FpDevice + * @print: (out) (transfer none): The user provided template print + * + * Get data for enrollment. + */ +void +fpi_device_get_enroll_data (FpDevice *device, + FpPrint **print) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + FpEnrollData *data; + + g_return_if_fail (FP_IS_DEVICE (device)); + g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_ENROLL); + + data = g_task_get_task_data (priv->current_task); + g_assert (data); + + if (print) + *print = data->print; +} + +/** + * fpi_device_get_capture_data: + * @device: The #FpDevice + * @wait_for_finger: (out): Whether to wait for finger or not + * + * Get data for capture. + */ +void +fpi_device_get_capture_data (FpDevice *device, + gboolean *wait_for_finger) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_if_fail (FP_IS_DEVICE (device)); + g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_CAPTURE); + + if (wait_for_finger) + *wait_for_finger = priv->wait_for_finger; +} + +/** + * fpi_device_get_verify_data: + * @device: The #FpDevice + * @print: (out) (transfer none): The enrolled print + * + * Get data for verify. + */ +void +fpi_device_get_verify_data (FpDevice *device, + FpPrint **print) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_if_fail (FP_IS_DEVICE (device)); + g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_VERIFY); + + if (print) + *print = g_task_get_task_data (priv->current_task); +} + +/** + * fpi_device_get_identify_data: + * @device: The #FpDevice + * @prints: (out) (transfer none) (element-type FpPrint): The gallery of prints + * + * Get data for identify. + */ +void +fpi_device_get_identify_data (FpDevice *device, + GPtrArray **prints) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_if_fail (FP_IS_DEVICE (device)); + g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_IDENTIFY); + + if (prints) + *prints = g_task_get_task_data (priv->current_task); +} + +/** + * fpi_device_get_delete_data: + * @device: The #FpDevice + * @print: (out) (transfer none): The print to delete + * + * Get data for delete. + */ +void +fpi_device_get_delete_data (FpDevice *device, + FpPrint **print) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_if_fail (FP_IS_DEVICE (device)); + g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_DELETE); + + if (print) + *print = g_task_get_task_data (priv->current_task); +} + +/** + * fpi_device_get_cancellable: + * @device: The #FpDevice + * + * Retrieve the #GCancellable that may cancel the currently ongoing operation. This + * is primarily useful to pass directly to e.g. fpi_usb_transfer_submit() for cancellable + * transfers. + * In many cases the cancel vfunc may be more convenient to react to cancellation in some + * way. + * + * Returns: (transfer none): The #GCancellable for the current action. + */ +GCancellable * +fpi_device_get_cancellable (FpDevice *device) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_val_if_fail (FP_IS_DEVICE (device), NULL); + g_return_val_if_fail (priv->current_action != FP_DEVICE_ACTION_NONE, NULL); + + return g_task_get_cancellable (priv->current_task); +} + +/** + * fpi_device_action_error: + * @device: The #FpDevice + * @error: The #GError to return + * + * Finish an ongoing action with an error. This is the same as calling + * the corresponding complete function such as fpi_device_open_complete() + * with an error set. If possible, use the correct complete function as + * that results in improved error detection. + */ +void +fpi_device_action_error (FpDevice *device, + GError *error) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_if_fail (FP_IS_DEVICE (device)); + g_return_if_fail (priv->current_action != FP_DEVICE_ACTION_NONE); + + if (error != NULL) + { + g_debug ("Device reported generic error during action; action was: %i", priv->current_action); + } + else + { + g_warning ("Device failed to pass an error to generic action error function"); + error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, "Device reported error but did not provide an error condition"); + } + + + switch (priv->current_action) + { + case FP_DEVICE_ACTION_PROBE: + fpi_device_probe_complete (device, NULL, NULL, error); + break; + + case FP_DEVICE_ACTION_OPEN: + fpi_device_open_complete (device, error); + break; + + case FP_DEVICE_ACTION_CLOSE: + fpi_device_close_complete (device, error); + break; + + case FP_DEVICE_ACTION_ENROLL: + fpi_device_enroll_complete (device, NULL, error); + break; + + case FP_DEVICE_ACTION_VERIFY: + fpi_device_verify_complete (device, FPI_MATCH_ERROR, NULL, error); + break; + + case FP_DEVICE_ACTION_IDENTIFY: + fpi_device_identify_complete (device, NULL, NULL, error); + break; + + case FP_DEVICE_ACTION_CAPTURE: + fpi_device_capture_complete (device, NULL, error); + break; + + case FP_DEVICE_ACTION_DELETE: + fpi_device_delete_complete (device, error); + break; + + case FP_DEVICE_ACTION_LIST: + fpi_device_list_complete (device, NULL, error); + break; + + default: + case FP_DEVICE_ACTION_NONE: + g_return_if_reached (); + break; + } +} + +typedef enum _FpDeviceTaskReturnType { + FP_DEVICE_TASK_RETURN_INT, + FP_DEVICE_TASK_RETURN_BOOL, + FP_DEVICE_TASK_RETURN_OBJECT, + FP_DEVICE_TASK_RETURN_PTR_ARRAY, + FP_DEVICE_TASK_RETURN_ERROR, +} FpDeviceTaskReturnType; + +typedef struct _FpDeviceTaskReturnData +{ + FpDevice *device; + FpDeviceTaskReturnType type; + gpointer result; +} FpDeviceTaskReturnData; + +static gboolean +fp_device_task_return_in_idle_cb (gpointer user_data) +{ + FpDeviceTaskReturnData *data = user_data; + FpDevicePrivate *priv = fp_device_get_instance_private (data->device); + + g_autoptr(GTask) task = NULL; + + g_debug ("Completing action %d in idle!", priv->current_action); + + task = g_steal_pointer (&priv->current_task); + priv->current_action = FP_DEVICE_ACTION_NONE; + priv->current_task_idle_return_source = NULL; + + switch (data->type) + { + case FP_DEVICE_TASK_RETURN_INT: + g_task_return_int (task, GPOINTER_TO_INT (data->result)); + break; + + case FP_DEVICE_TASK_RETURN_BOOL: + g_task_return_boolean (task, GPOINTER_TO_UINT (data->result)); + break; + + case FP_DEVICE_TASK_RETURN_OBJECT: + g_task_return_pointer (task, data->result, g_object_unref); + break; + + case FP_DEVICE_TASK_RETURN_PTR_ARRAY: + g_task_return_pointer (task, data->result, + (GDestroyNotify) g_ptr_array_unref); + break; + + case FP_DEVICE_TASK_RETURN_ERROR: + g_task_return_error (task, data->result); + break; + + default: + g_assert_not_reached (); + } + + return G_SOURCE_REMOVE; +} + +static void +fp_device_task_return_data_free (FpDeviceTaskReturnData *data) +{ + g_object_unref (data->device); + g_free (data); +} + +static void +fp_device_return_task_in_idle (FpDevice *device, + FpDeviceTaskReturnType return_type, + gpointer return_data) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + FpDeviceTaskReturnData *data; + + data = g_new0 (FpDeviceTaskReturnData, 1); + data->device = g_object_ref (device); + data->type = return_type; + data->result = return_data; + + priv->current_task_idle_return_source = g_idle_source_new (); + g_source_set_priority (priv->current_task_idle_return_source, + g_task_get_priority (priv->current_task)); + g_source_set_callback (priv->current_task_idle_return_source, + fp_device_task_return_in_idle_cb, + data, + (GDestroyNotify) fp_device_task_return_data_free); + + g_source_attach (priv->current_task_idle_return_source, NULL); + g_source_unref (priv->current_task_idle_return_source); +} + +/** + * fpi_device_probe_complete: + * @device: The #FpDevice + * @device_id: Unique ID for the device or %NULL + * @device_name: Human readable name or %NULL for driver name + * @error: The #GError or %NULL on success + * + * Finish an ongoing probe operation. If error is %NULL success is assumed. + */ +void +fpi_device_probe_complete (FpDevice *device, + const gchar *device_id, + const gchar *device_name, + GError *error) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_if_fail (FP_IS_DEVICE (device)); + g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_PROBE); + + g_debug ("Device reported probe completion"); + + clear_device_cancel_action (device); + + if (!error) + { + if (device_id) + { + g_clear_pointer (&priv->device_id, g_free); + priv->device_id = g_strdup (device_id); + g_object_notify_by_pspec (G_OBJECT (device), properties[PROP_DEVICE_ID]); + } + if (device_name) + { + g_clear_pointer (&priv->device_name, g_free); + priv->device_name = g_strdup (device_name); + g_object_notify_by_pspec (G_OBJECT (device), properties[PROP_NAME]); + } + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL, + GUINT_TO_POINTER (TRUE)); + } + else + { + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error); + } +} + +/** + * fpi_device_open_complete: + * @device: The #FpDevice + * @error: The #GError or %NULL on success + * + * Finish an ongoing open operation. If error is %NULL success is assumed. + */ +void +fpi_device_open_complete (FpDevice *device, GError *error) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_if_fail (FP_IS_DEVICE (device)); + g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_OPEN); + + g_debug ("Device reported open completion"); + + clear_device_cancel_action (device); + + if (!error) + priv->is_open = TRUE; + + if (!error) + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL, + GUINT_TO_POINTER (TRUE)); + else + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error); +} + +/** + * fpi_device_close_complete: + * @device: The #FpDevice + * @error: The #GError or %NULL on success + * + * Finish an ongoing close operation. If error is %NULL success is assumed. + */ +void +fpi_device_close_complete (FpDevice *device, GError *error) +{ + GError *nested_error = NULL; + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_if_fail (FP_IS_DEVICE (device)); + g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_CLOSE); + + g_debug ("Device reported close completion"); + + clear_device_cancel_action (device); + priv->is_open = FALSE; + + switch (priv->type) + { + case FP_DEVICE_TYPE_USB: + if (!g_usb_device_close (priv->usb_device, &nested_error)) + { + if (error == NULL) + error = nested_error; + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error); + return; + } + break; + + case FP_DEVICE_TYPE_VIRTUAL: + break; + + default: + g_assert_not_reached (); + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, + fpi_device_error_new (FP_DEVICE_ERROR_GENERAL)); + return; + } + + if (!error) + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL, + GUINT_TO_POINTER (TRUE)); + else + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error); +} + +/** + * fpi_device_enroll_complete: + * @device: The #FpDevice + * @print: (nullable) (transfer full): The #FpPrint or %NULL on failure + * @error: The #GError or %NULL on success + * + * Finish an ongoing enroll operation. The #FpPrint can be stored by the + * caller for later verification. + */ +void +fpi_device_enroll_complete (FpDevice *device, FpPrint *print, GError *error) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_if_fail (FP_IS_DEVICE (device)); + g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_ENROLL); + + g_debug ("Device reported enroll completion"); + + clear_device_cancel_action (device); + + if (!error) + { + if (FP_IS_PRINT (print)) + { + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_OBJECT, print); + } + else + { + g_warning ("Driver did not provide a valid print and failed to provide an error!"); + error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, + "Driver failed to provide print data!"); + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error); + } + } + else + { + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error); + if (FP_IS_PRINT (print)) + { + g_warning ("Driver passed an error but also provided a print, returning error!"); + g_object_unref (print); + } + } +} + +/** + * fpi_device_verify_complete: + * @device: The #FpDevice + * @result: The #FpiMatchResult of the operation + * @print: The scanned #FpPrint + * @error: A #GError if result is %FPI_MATCH_ERROR + * + * Finish an ongoing verify operation. The returned print should be + * representing the new scan and not the one passed for verification. + */ +void +fpi_device_verify_complete (FpDevice *device, + FpiMatchResult result, + FpPrint *print, + GError *error) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_if_fail (FP_IS_DEVICE (device)); + g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_VERIFY); + + g_debug ("Device reported verify completion"); + + clear_device_cancel_action (device); + + g_object_set_data_full (G_OBJECT (priv->current_task), + "print", + print, + g_object_unref); + + if (!error) + { + if (result != FPI_MATCH_ERROR) + { + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_INT, + GINT_TO_POINTER (result)); + } + else + { + g_warning ("Driver did not provide an error for a failed verify operation!"); + error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, + "Driver failed to provide an error!"); + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error); + } + } + else + { + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error); + if (result != FPI_MATCH_ERROR) + { + g_warning ("Driver passed an error but also provided a match result, returning error!"); + g_object_unref (print); + } + } +} + +/** + * fpi_device_identify_complete: + * @device: The #FpDevice + * @match: The matching #FpPrint from the passed gallery, or %NULL if none matched + * @print: The scanned #FpPrint, may be %NULL + * @error: The #GError or %NULL on success + * + * Finish an ongoing identify operation. The match that was identified is + * returned in @match. The @print parameter returns the newly created scan + * that was used for matching. + */ +void +fpi_device_identify_complete (FpDevice *device, + FpPrint *match, + FpPrint *print, + GError *error) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_if_fail (FP_IS_DEVICE (device)); + g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_IDENTIFY); + + g_debug ("Device reported identify completion"); + + clear_device_cancel_action (device); + + g_object_set_data_full (G_OBJECT (priv->current_task), + "print", + print, + g_object_unref); + g_object_set_data_full (G_OBJECT (priv->current_task), + "match", + match, + g_object_unref); + if (!error) + { + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL, + GUINT_TO_POINTER (TRUE)); + } + else + { + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error); + if (match) + { + g_warning ("Driver passed an error but also provided a match result, returning error!"); + g_clear_object (&match); + } + } +} + + +/** + * fpi_device_capture_complete: + * @device: The #FpDevice + * @image: The #FpImage, or %NULL on error + * @error: The #GError or %NULL on success + * + * Finish an ongoing capture operation. + */ +void +fpi_device_capture_complete (FpDevice *device, + FpImage *image, + GError *error) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_if_fail (FP_IS_DEVICE (device)); + g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_CAPTURE); + + g_debug ("Device reported capture completion"); + + clear_device_cancel_action (device); + + if (!error) + { + if (image) + { + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_OBJECT, image); + } + else + { + g_warning ("Driver did not provide an error for a failed capture operation!"); + error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, + "Driver failed to provide an error!"); + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error); + } + } + else + { + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error); + if (image) + { + g_warning ("Driver passed an error but also provided an image, returning error!"); + g_clear_object (&image); + } + } +} + +/** + * fpi_device_delete_complete: + * @device: The #FpDevice + * @error: The #GError or %NULL on success + * + * Finish an ongoing delete operation. + */ +void +fpi_device_delete_complete (FpDevice *device, + GError *error) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_if_fail (FP_IS_DEVICE (device)); + g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_DELETE); + + g_debug ("Device reported deletion completion"); + + clear_device_cancel_action (device); + + if (!error) + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL, + GUINT_TO_POINTER (TRUE)); + else + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error); +} + +/** + * fpi_device_list_complete: + * @device: The #FpDevice + * @prints: (element-type FpPrint) (transfer container): Possibly empty array of prints or %NULL on error + * @error: The #GError or %NULL on success + * + * Finish an ongoing list operation. + * + * Please note that the @prints array will be free'ed using + * g_ptr_array_unref() and the elements are destroyed automatically. + * As such, you must use g_ptr_array_new_with_free_func() with + * g_object_unref() as free func to create the array. + */ +void +fpi_device_list_complete (FpDevice *device, + GPtrArray *prints, + GError *error) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_if_fail (FP_IS_DEVICE (device)); + g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_LIST); + + g_debug ("Device reported listing completion"); + + clear_device_cancel_action (device); + + if (prints && error) + { + g_warning ("Driver reported back prints and error, ignoring prints"); + g_clear_pointer (&prints, g_ptr_array_unref); + } + else if (!prints && !error) + { + g_warning ("Driver did not pass array but failed to provide an error"); + error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, + "Driver failed to provide a list of prints"); + } + + if (!error) + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_PTR_ARRAY, prints); + else + fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error); +} + +/** + * fpi_device_enroll_progress: + * @device: The #FpDevice + * @completed_stages: The number of stages that are completed at this point + * @print: The #FpPrint for the newly completed stage or %NULL on failure + * @error: The #GError or %NULL on success + * + * Notify about the progress of the enroll operation. This is important for UI interaction. + * The passed error may be used if a scan needs to be retried, use fpi_device_retry_new(). + */ +void +fpi_device_enroll_progress (FpDevice *device, + gint completed_stages, + FpPrint *print, + GError *error) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + FpEnrollData *data; + + g_return_if_fail (FP_IS_DEVICE (device)); + g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_ENROLL); + g_return_if_fail (error == NULL || error->domain == FP_DEVICE_RETRY); + + g_debug ("Device reported enroll progress, reported %i of %i have been completed", completed_stages, priv->nr_enroll_stages); + + if (error && print) + { + g_warning ("Driver passed an error and also provided a print, returning error!"); + g_clear_object (&print); + } + + data = g_task_get_task_data (priv->current_task); + + if (data->enroll_progress_cb) + { + data->enroll_progress_cb (device, + completed_stages, + print, + data->enroll_progress_data, + error); + } + if (error) + g_error_free (error); +} + + +static void +async_result_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) +{ + GTask **task = user_data; + + *task = g_object_ref (G_TASK (res)); +} + +/** + * fp_device_open_sync: + * @device: a #FpDevice + * @cancellable: (nullable): a #GCancellable, or %NULL + * @error: Return location for errors, or %NULL to ignore + * + * Open the device synchronously. + * + * Returns: (type void): %FALSE on error, %TRUE otherwise + */ +gboolean +fp_device_open_sync (FpDevice *device, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GAsyncResult) task = NULL; + + g_return_val_if_fail (FP_IS_DEVICE (device), FALSE); + + fp_device_open (device, cancellable, async_result_ready, &task); + while (!task) + g_main_context_iteration (NULL, TRUE); + + return fp_device_open_finish (device, task, error); +} + +/** + * fp_device_close_sync: + * @device: a #FpDevice + * @cancellable: (nullable): a #GCancellable, or %NULL + * @error: Return location for errors, or %NULL to ignore + * + * Close the device synchronously. + * + * Returns: (type void): %FALSE on error, %TRUE otherwise + */ +gboolean +fp_device_close_sync (FpDevice *device, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GAsyncResult) task = NULL; + + g_return_val_if_fail (FP_IS_DEVICE (device), FALSE); + + fp_device_close (device, cancellable, async_result_ready, &task); + while (!task) + g_main_context_iteration (NULL, TRUE); + + return fp_device_close_finish (device, task, error); +} + +/** + * fp_device_enroll_sync: + * @device: a #FpDevice + * @template_print: (transfer floating): A #FpPrint to fill in or use + * as a template. + * @cancellable: (nullable): a #GCancellable, or %NULL + * @progress_cb: (nullable) (scope call): progress reporting callback + * @progress_data: user data for @progress_cb + * @error: Return location for errors, or %NULL to ignore + * + * Enroll a new print. See fp_device_enroll(). It is undefined whether + * @template_print is updated or a newly created #FpPrint is returned. + * + * Returns:(transfer full): A #FpPrint on success, %NULL otherwise + */ +FpPrint * +fp_device_enroll_sync (FpDevice *device, + FpPrint *template_print, + GCancellable *cancellable, + FpEnrollProgress progress_cb, + gpointer progress_data, + GError **error) +{ + g_autoptr(GAsyncResult) task = NULL; + + g_return_val_if_fail (FP_IS_DEVICE (device), FALSE); + + fp_device_enroll (device, template_print, cancellable, + progress_cb, progress_data, NULL, + async_result_ready, &task); + while (!task) + g_main_context_iteration (NULL, TRUE); + + return fp_device_enroll_finish (device, task, error); +} + +/** + * fp_device_verify_sync: + * @device: a #FpDevice + * @enrolled_print: a #FpPrint to verify + * @cancellable: (nullable): a #GCancellable, or %NULL + * @match: (out): Whether the user presented the correct finger + * @print: (out) (transfer full) (nullable): Location to store the scanned print, or %NULL to ignore + * @error: Return location for errors, or %NULL to ignore + * + * Verify a given print synchronously. + * + * Returns: (type void): %FALSE on error, %TRUE otherwise + */ +gboolean +fp_device_verify_sync (FpDevice *device, + FpPrint *enrolled_print, + GCancellable *cancellable, + gboolean *match, + FpPrint **print, + GError **error) +{ + g_autoptr(GAsyncResult) task = NULL; + + g_return_val_if_fail (FP_IS_DEVICE (device), FALSE); + + fp_device_verify (device, + enrolled_print, + cancellable, + async_result_ready, &task); + while (!task) + g_main_context_iteration (NULL, TRUE); + + return fp_device_verify_finish (device, task, match, print, error); +} + +/** + * fp_device_identify_sync: + * @device: a #FpDevice + * @prints: (element-type FpPrint) (transfer none): #GPtrArray of #FpPrint + * @cancellable: (nullable): a #GCancellable, or %NULL + * @match: (out) (transfer full) (nullable): Location for the matched #FpPrint, or %NULL + * @print: (out) (transfer full) (nullable): Location for the new #FpPrint, or %NULL + * @error: Return location for errors, or %NULL to ignore + * + * Identify a print synchronously. + * + * Returns: (type void): %FALSE on error, %TRUE otherwise + */ +gboolean +fp_device_identify_sync (FpDevice *device, + GPtrArray *prints, + GCancellable *cancellable, + FpPrint **match, + FpPrint **print, + GError **error) +{ + g_autoptr(GAsyncResult) task = NULL; + + g_return_val_if_fail (FP_IS_DEVICE (device), FALSE); + + fp_device_identify (device, + prints, + cancellable, + async_result_ready, &task); + while (!task) + g_main_context_iteration (NULL, TRUE); + + return fp_device_identify_finish (device, task, match, print, error); +} + + +/** + * fp_device_capture_sync: + * @device: a #FpDevice + * @wait_for_finger: Whether to wait for a finger or not + * @cancellable: (nullable): a #GCancellable, or %NULL + * @error: Return location for errors, or %NULL to ignore + * + * Start an synchronous operation to capture an image. + * + * Returns: (transfer full): A new #FpImage or %NULL on error + */ +FpImage * +fp_device_capture_sync (FpDevice *device, + gboolean wait_for_finger, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GAsyncResult) task = NULL; + + g_return_val_if_fail (FP_IS_DEVICE (device), FALSE); + + fp_device_capture (device, + wait_for_finger, + cancellable, + async_result_ready, &task); + while (!task) + g_main_context_iteration (NULL, TRUE); + + return fp_device_capture_finish (device, task, error); +} + +/** + * fp_device_delete_print_sync: + * @device: a #FpDevice + * @enrolled_print: a #FpPrint to verify + * @cancellable: (nullable): a #GCancellable, or %NULL + * @error: Return location for errors, or %NULL to ignore + * + * Delete a given print from the device. + * + * Returns: %FALSE on error, %TRUE otherwise + */ +gboolean +fp_device_delete_print_sync (FpDevice *device, + FpPrint *enrolled_print, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GAsyncResult) task = NULL; + + g_return_val_if_fail (FP_IS_DEVICE (device), FALSE); + + fp_device_delete_print (device, + enrolled_print, + cancellable, + async_result_ready, &task); + while (!task) + g_main_context_iteration (NULL, TRUE); + + return fp_device_delete_print_finish (device, task, error); +} + +/** + * fp_device_list_prints_sync: + * @device: a #FpDevice + * @cancellable: (nullable): a #GCancellable, or %NULL + * @error: Return location for errors, or %NULL to ignore + * + * List device stored prints synchronously. + * + * Returns: (element-type FpPrint) (transfer container): Array of prints, or %NULL on error + */ +GPtrArray * +fp_device_list_prints_sync (FpDevice *device, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GAsyncResult) task = NULL; + + g_return_val_if_fail (FP_IS_DEVICE (device), FALSE); + + fp_device_list_prints (device, + NULL, + async_result_ready, &task); + while (!task) + g_main_context_iteration (NULL, TRUE); + + return fp_device_list_prints_finish (device, task, error); +} diff --git a/libfprint/fp-device.h b/libfprint/fp-device.h new file mode 100644 index 00000000..821514d7 --- /dev/null +++ b/libfprint/fp-device.h @@ -0,0 +1,255 @@ +/* + * FpDevice - A fingerprint reader device + * Copyright (C) 2019 Benjamin Berg + * + * 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 "fp-image.h" +#include +#include + +G_BEGIN_DECLS + +#define FP_TYPE_DEVICE (fp_device_get_type ()) +#define FP_DEVICE_RETRY (fp_device_retry_quark ()) +#define FP_DEVICE_ERROR (fp_device_error_quark ()) +G_DECLARE_DERIVABLE_TYPE (FpDevice, fp_device, FP, DEVICE, GObject) + +#include "fp-print.h" + +/* NOTE: We keep the class struct private! */ + +/** + * FpDeviceType: + * @FP_DEVICE_TYPE_VIRTUAL: The device is a virtual device + * @FP_DEVICE_TYPE_USB: The device is a USB device + */ +typedef enum { + FP_DEVICE_TYPE_VIRTUAL, + FP_DEVICE_TYPE_USB, +} FpDeviceType; + +/** + * FpScanType: + * @FP_SCAN_TYPE_SWIPE: Sensor requires swiping the finger. + * @FP_SCAN_TYPE_PRESS: Sensor requires placing/pressing down the finger. + */ +typedef enum { + FP_SCAN_TYPE_SWIPE, + FP_SCAN_TYPE_PRESS, +} FpScanType; + +/** + * FpDeviceRetry: + * @FP_DEVICE_RETRY_GENERAL: The scan did not succeed due to poor scan quality + * or other general user scanning problem. + * @FP_DEVICE_RETRY_TOO_SHORT: The scan did not succeed because the finger + * swipe was too short. + * @FP_DEVICE_RETRY_CENTER_FINGER: The scan did not succeed because the finger + * was not centered on the scanner. + * @FP_DEVICE_RETRY_REMOVE_FINGER: The scan did not succeed due to quality or + * pressure problems; the user should remove their finger from the scanner + * before retrying. + * + * Error codes representing scan failures resulting in the user needing to + * retry. + */ +typedef enum { + FP_DEVICE_RETRY_GENERAL, + FP_DEVICE_RETRY_TOO_SHORT, + FP_DEVICE_RETRY_CENTER_FINGER, + FP_DEVICE_RETRY_REMOVE_FINGER, +} FpDeviceRetry; + +/** + * FpDeviceError: + * @FP_DEVICE_ERROR_GENERAL: A general error occured. + * @FP_DEVICE_ERROR_NOT_SUPPORTED: The device does not support the requested + * operation. + * @FP_DEVICE_ERROR_NOT_OPEN: The device needs to be opened to start this + * operation. + * @FP_DEVICE_ERROR_ALREADY_OPEN: The device has already been opened. + * @FP_DEVICE_ERROR_BUSY: The device is busy with another request. + * @FP_DEVICE_ERROR_PROTO: Protocol error + * @FP_DEVICE_ERROR_DATA_INVALID: The passed data is invalid + * @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 + * + * 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. + */ +typedef enum { + FP_DEVICE_ERROR_GENERAL, + FP_DEVICE_ERROR_NOT_SUPPORTED, + FP_DEVICE_ERROR_NOT_OPEN, + FP_DEVICE_ERROR_ALREADY_OPEN, + FP_DEVICE_ERROR_BUSY, + FP_DEVICE_ERROR_PROTO, + FP_DEVICE_ERROR_DATA_INVALID, + FP_DEVICE_ERROR_DATA_NOT_FOUND, + FP_DEVICE_ERROR_DATA_FULL, +} FpDeviceError; + +GQuark fp_device_retry_quark (void); +GQuark fp_device_error_quark (void); + +/** + * FpEnrollProgress: + * @device: a #FpDevice + * @completed_stages: Number of completed stages + * @print: (nullable): The last scaned print + * @user_data: (nullable): User provided data + * @error: (nullable) (transfer none): #GError or %NULL + * + * The passed error is guaranteed to be of type %FP_DEVICE_RETRY if set. + */ +typedef void (*FpEnrollProgress) (FpDevice *device, + gint completed_stages, + FpPrint *print, + gpointer user_data, + GError *error); + + +const gchar *fp_device_get_driver (FpDevice *device); +const gchar *fp_device_get_device_id (FpDevice *device); +const gchar *fp_device_get_name (FpDevice *device); +FpScanType fp_device_get_scan_type (FpDevice *device); +gint fp_device_get_nr_enroll_stages (FpDevice *device); + +gboolean fp_device_supports_identify (FpDevice *device); +gboolean fp_device_supports_capture (FpDevice *device); +gboolean fp_device_has_storage (FpDevice *device); + +/* Opening the device */ +void fp_device_open (FpDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +void fp_device_close (FpDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +void fp_device_enroll (FpDevice *device, + FpPrint *template_print, + GCancellable *cancellable, + FpEnrollProgress progress_cb, + gpointer progress_data, + GDestroyNotify progress_destroy, + GAsyncReadyCallback callback, + gpointer user_data); + +void fp_device_verify (FpDevice *device, + FpPrint *enrolled_print, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +void fp_device_identify (FpDevice *device, + GPtrArray *prints, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +void fp_device_capture (FpDevice *device, + gboolean wait_for_finger, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +void fp_device_delete_print (FpDevice *device, + FpPrint *enrolled_print, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +void fp_device_list_prints (FpDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean fp_device_open_finish (FpDevice *device, + GAsyncResult *result, + GError **error); +gboolean fp_device_close_finish (FpDevice *device, + GAsyncResult *result, + GError **error); +FpPrint *fp_device_enroll_finish (FpDevice *device, + GAsyncResult *result, + GError **error); +gboolean fp_device_verify_finish (FpDevice *device, + GAsyncResult *result, + gboolean *match, + FpPrint **print, + GError **error); +gboolean fp_device_identify_finish (FpDevice *device, + GAsyncResult *result, + FpPrint **match, + FpPrint **print, + GError **error); +FpImage * fp_device_capture_finish (FpDevice *device, + GAsyncResult *result, + GError **error); +gboolean fp_device_delete_print_finish (FpDevice *device, + GAsyncResult *result, + GError **error); +GPtrArray * fp_device_list_prints_finish (FpDevice *device, + GAsyncResult *result, + GError **error); + + +gboolean fp_device_open_sync (FpDevice *device, + GCancellable *cancellable, + GError **error); +gboolean fp_device_close_sync (FpDevice *device, + GCancellable *cancellable, + GError **error); +FpPrint * fp_device_enroll_sync (FpDevice *device, + FpPrint *template_print, + GCancellable *cancellable, + FpEnrollProgress progress_cb, + gpointer progress_data, + GError **error); +gboolean fp_device_verify_sync (FpDevice *device, + FpPrint *enrolled_print, + GCancellable *cancellable, + gboolean *match, + FpPrint **print, + GError **error); +gboolean fp_device_identify_sync (FpDevice *device, + GPtrArray *prints, + GCancellable *cancellable, + FpPrint **match, + FpPrint **print, + GError **error); +FpImage * fp_device_capture_sync (FpDevice *device, + gboolean wait_for_finger, + GCancellable *cancellable, + GError **error); +gboolean fp_device_delete_print_sync (FpDevice *device, + FpPrint *enrolled_print, + GCancellable *cancellable, + GError **error); +GPtrArray * fp_device_list_prints_sync (FpDevice *device, + GCancellable *cancellable, + GError **error); + + +G_END_DECLS diff --git a/libfprint/fp-image-device.c b/libfprint/fp-image-device.c new file mode 100644 index 00000000..8524e069 --- /dev/null +++ b/libfprint/fp-image-device.c @@ -0,0 +1,795 @@ +/* + * FpImageDevice - An image based fingerprint reader device + * Copyright (C) 2019 Benjamin Berg + * + * 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 "image_device" +#include "fpi-log.h" + +#include "fpi-image-device.h" +#include "fpi-print.h" +#include "fpi-image.h" + +#define MIN_ACCEPTABLE_MINUTIAE 10 +#define BOZORTH3_DEFAULT_THRESHOLD 40 +#define IMG_ENROLL_STAGES 5 + +/** + * SECTION: fp-image-device + * @title: FpImageDevice + * @short_description: Image device subclass + * + * This is a helper class for the commonly found image based devices. + */ + +/** + * SECTION: fpi-image-device + * @title: Internal FpImageDevice + * @short_description: Internal image device routines + * + * See #FpImageDeviceClass for more details. Also see the public + * #FpImageDevice routines. + */ + +typedef struct +{ + FpImageDeviceState state; + gboolean active; + + gint enroll_stage; + + guint pending_activation_timeout_id; + gboolean pending_activation_timeout_waiting_finger_off; + + gint bz3_threshold; +} FpImageDevicePrivate; + +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (FpImageDevice, fp_image_device, FP_TYPE_DEVICE) + + +/*******************************************************/ + +/* TODO: + * - sanitize_image seems a bit odd, in particular the sizing stuff. + **/ + +/* Static helper functions */ + +static void +fp_image_device_change_state (FpImageDevice *self, FpImageDeviceState state) +{ + FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self); + FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (self); + + /* Cannot change to inactive using this function. */ + g_assert (state != FP_IMAGE_DEVICE_STATE_INACTIVE); + + /* We might have been waiting for the finger to go OFF to start the + * next operation. */ + if (priv->pending_activation_timeout_id) + { + g_source_remove (priv->pending_activation_timeout_id); + priv->pending_activation_timeout_id = 0; + } + + fp_dbg ("Image device internal state change from %d to %d\n", priv->state, state); + + priv->state = state; + + /* change_state is the only callback which is optional and does not + * have a default implementation. */ + if (cls->change_state) + cls->change_state (self, state); +} + +static void +fp_image_device_activate (FpImageDevice *self) +{ + FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self); + FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (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 = FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON; + + /* We might have been waiting for deactivation to finish before + * starting the next operation. */ + if (priv->pending_activation_timeout_id) + { + g_source_remove (priv->pending_activation_timeout_id); + priv->pending_activation_timeout_id = 0; + } + + fp_dbg ("Activating image device\n"); + cls->activate (self); +} + +static void +fp_image_device_deactivate (FpDevice *device) +{ + FpImageDevice *self = FP_IMAGE_DEVICE (device); + FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self); + FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (device); + + if (!priv->active) + { + /* XXX: We currently deactivate both from minutiae scan result + * and finger off report. */ + fp_dbg ("Already deactivated, ignoring request."); + return; + } + priv->state = FP_IMAGE_DEVICE_STATE_INACTIVE; + + fp_dbg ("Deactivating image device\n"); + cls->deactivate (self); +} + +static gboolean +pending_activation_timeout (gpointer user_data) +{ + FpImageDevice *self = FP_IMAGE_DEVICE (user_data); + FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self); + + priv->pending_activation_timeout_id = 0; + + if (priv->pending_activation_timeout_waiting_finger_off) + fpi_device_action_error (FP_DEVICE (self), + fpi_device_retry_new_msg (FP_DEVICE_RETRY_REMOVE_FINGER, + "Remove finger before requesting another scan operation")); + else + fpi_device_action_error (FP_DEVICE (self), + fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL)); + + return G_SOURCE_REMOVE; +} + +/* Callbacks/vfuncs */ +static void +fp_image_device_open (FpDevice *device) +{ + FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (device); + + /* Nothing special about opening an image device, just + * forward the request. */ + cls->img_open (FP_IMAGE_DEVICE (device)); +} + +static void +fp_image_device_close (FpDevice *device) +{ + FpImageDevice *self = FP_IMAGE_DEVICE (device); + FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (self); + FpImageDevicePrivate *priv = fp_image_device_get_instance_private (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 + * -> imediately deactivate + * 3. We are deactivating + * -> handled by deactivate_complete */ + + if (!priv->active) + cls->img_close (self); + else if (priv->state != FP_IMAGE_DEVICE_STATE_INACTIVE) + fp_image_device_deactivate (device); +} + +static void +fp_image_device_cancel_action (FpDevice *device) +{ + FpImageDevice *self = FP_IMAGE_DEVICE (device); + FpDeviceAction action; + + action = fpi_device_get_current_action (device); + + /* We can only cancel capture operations, in that case, deactivate and return + * an error immediately. */ + if (action == FP_DEVICE_ACTION_ENROLL || + action == FP_DEVICE_ACTION_VERIFY || + action == FP_DEVICE_ACTION_IDENTIFY || + action == FP_DEVICE_ACTION_CAPTURE) + { + fp_image_device_deactivate (FP_DEVICE (self)); + + /* 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 +fp_image_device_start_capture_action (FpDevice *device) +{ + FpImageDevice *self = FP_IMAGE_DEVICE (device); + FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self); + FpDeviceAction action; + + /* There is just one action that we cannot support out + * of the box, which is a capture without first waiting + * for a finger to be on the device. + */ + action = fpi_device_get_current_action (device); + if (action == FP_DEVICE_ACTION_CAPTURE) + { + gboolean wait_for_finger; + + fpi_device_get_capture_data (device, &wait_for_finger); + + if (!wait_for_finger) + { + fpi_device_action_error (device, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED)); + return; + } + } + else if (action == FP_DEVICE_ACTION_ENROLL) + { + FpPrint *enroll_print = NULL; + + fpi_device_get_enroll_data (device, &enroll_print); + fpi_print_set_type (enroll_print, FP_PRINT_NBIS); + } + + priv->enroll_stage = 0; + + /* 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 != FP_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 == FP_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). */ + fp_image_device_activate (self); +} + + +/*********************************************************/ + +static void +fp_image_device_finalize (GObject *object) +{ + FpImageDevice *self = (FpImageDevice *) object; + FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self); + + g_assert (priv->active == FALSE); + + G_OBJECT_CLASS (fp_image_device_parent_class)->finalize (object); +} + +static void +fp_image_device_default_activate (FpImageDevice *self) +{ + fpi_image_device_activate_complete (self, NULL); +} + +static void +fp_image_device_default_deactivate (FpImageDevice *self) +{ + fpi_image_device_deactivate_complete (self, NULL); +} + +static void +fp_image_device_class_init (FpImageDeviceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + FpDeviceClass *fp_device_class = FP_DEVICE_CLASS (klass); + + object_class->finalize = fp_image_device_finalize; + + 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; + fp_device_class->verify = fp_image_device_start_capture_action; + fp_device_class->identify = fp_image_device_start_capture_action; + fp_device_class->capture = fp_image_device_start_capture_action; + + fp_device_class->cancel = fp_image_device_cancel_action; + + /* Default implementations */ + klass->activate = fp_image_device_default_activate; + klass->deactivate = fp_image_device_default_deactivate; +} + +static void +fp_image_device_init (FpImageDevice *self) +{ + FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self); + FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (self); + + /* 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; + +} + +static void +fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, gpointer user_data) +{ + g_autoptr(FpImage) image = FP_IMAGE (source_object); + GError *error = NULL; + FpPrint *print = NULL; + FpDevice *device = FP_DEVICE (user_data); + FpImageDevicePrivate *priv; + FpDeviceAction action; + + /* Note: We rely on the device to not disappear during an operation. */ + + if (!fp_image_detect_minutiae_finish (image, res, &error)) + { + /* Cancel operation . */ + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + { + fpi_device_action_error (device, g_steal_pointer (&error)); + fp_image_device_deactivate (device); + return; + } + + /* Replace error with a retry condition. */ + g_warning ("Failed to detect minutiae: %s", error->message); + g_clear_pointer (&error, g_error_free); + + 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 == FP_DEVICE_ACTION_CAPTURE) + { + fpi_device_capture_complete (device, g_steal_pointer (&image), error); + fp_image_device_deactivate (device); + return; + } + + if (!error) + { + print = fp_print_new (device); + fpi_print_set_type (print, FP_PRINT_NBIS); + if (!fpi_print_add_from_image (print, image, &error)) + g_clear_object (&print); + } + + if (action == FP_DEVICE_ACTION_ENROLL) + { + FpPrint *enroll_print; + fpi_device_get_enroll_data (device, &enroll_print); + + if (print) + { + fpi_print_add_print (enroll_print, print); + priv->enroll_stage += 1; + } + + fpi_device_enroll_progress (device, priv->enroll_stage, print, error); + + if (priv->enroll_stage == IMG_ENROLL_STAGES) + { + fpi_device_enroll_complete (device, g_object_ref (enroll_print), NULL); + fp_image_device_deactivate (device); + } + } + else if (action == FP_DEVICE_ACTION_VERIFY) + { + FpPrint *template; + FpiMatchResult result; + + fpi_device_get_verify_data (device, &template); + if (print) + result = fpi_print_bz3_match (template, print, priv->bz3_threshold, &error); + else + result = FPI_MATCH_ERROR; + + fpi_device_verify_complete (device, result, print, error); + fp_image_device_deactivate (device); + } + else if (action == FP_DEVICE_ACTION_IDENTIFY) + { + gint i; + GPtrArray *templates; + FpPrint *result = NULL; + + fpi_device_get_identify_data (device, &templates); + for (i = 0; !error && i < templates->len; i++) + { + FpPrint *template = g_ptr_array_index (templates, i); + + if (fpi_print_bz3_match (template, print, priv->bz3_threshold, &error) == FPI_MATCH_SUCCESS) + { + result = g_object_ref (template); + break; + } + } + + fpi_device_identify_complete (device, result, print, error); + fp_image_device_deactivate (device); + } + else + { + /* XXX: This can be hit currently due to a race condition in the enroll code! + * In that case we scan a further image even though the minutiae for the previous + * one have not yet been detected. + * We need to keep track on the pending minutiae detection and the fact that + * it will finish eventually (or we may need to retry on error and activate the + * device again). */ + g_assert_not_reached (); + } +} + +/*********************************************************/ +/* Private API */ + +/** + * fpi_image_device_set_bz3_threshold: + * @self: a #FpImageDevice imaging fingerprint device + * @bz3_threshold: BZ3 threshold to use + * + * Dynamically adjust the bz3 threshold. This is only needed for drivers + * that support devices with different properties. It should generally be + * called from the probe callback, but is acceptable to call from the open + * callback. + */ +void +fpi_image_device_set_bz3_threshold (FpImageDevice *self, + gint bz3_threshold) +{ + FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self); + + g_return_if_fail (FP_IS_IMAGE_DEVICE (self)); + g_return_if_fail (bz3_threshold > 0); + + priv->bz3_threshold = bz3_threshold; +} + +/** + * fpi_image_device_report_finger_status: + * @self: a #FpImageDevice imaging fingerprint device + * @present: whether the finger is present on the sensor + * + * Reports from the driver whether the user's finger is on + * the sensor. + */ +void +fpi_image_device_report_finger_status (FpImageDevice *self, + gboolean present) +{ + FpDevice *device = FP_DEVICE (self); + FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self); + FpDeviceAction action; + + action = fpi_device_get_current_action (device); + + if (priv->state == FP_IMAGE_DEVICE_STATE_INACTIVE) + { + /* Do we really want to always ignore such reports? We could + * also track the state in case the user had the finger on + * the device at initialisation time and the driver reports + * this early. + */ + g_debug ("Ignoring finger presence report as the device is not active!"); + return; + } + + action = fpi_device_get_current_action (device); + + g_assert (action != FP_DEVICE_ACTION_OPEN); + g_assert (action != FP_DEVICE_ACTION_CLOSE); + + g_debug ("Image device reported finger status: %s", present ? "on" : "off"); + + if (present && priv->state == FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON) + { + fp_image_device_change_state (self, FP_IMAGE_DEVICE_STATE_CAPTURE); + } + else if (!present && priv->state == FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF) + { + /* 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. + * XXX: This is not quite correct though, as we assume we need another finger + * scan even though we might be processing the last one (successfully). + */ + if (action != FP_DEVICE_ACTION_ENROLL) + fp_image_device_deactivate (device); + else + fp_image_device_change_state (self, FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON); + } +} + +/** + * fpi_image_device_image_captured: + * @self: a #FpImageDevice imaging fingerprint device + * @image: whether the finger is present on the sensor + * + * Reports an image capture. Only use this function if the image was + * captured successfully. If there was an issue where the user should + * retry, use fpi_image_device_retry_scan() to report the retry condition. + * + * In the event of a fatal error for the operation use + * fpi_image_device_session_error(). This will abort the entire operation + * including e.g. an enroll operation which captures multiple images during + * one session. + */ +void +fpi_image_device_image_captured (FpImageDevice *self, FpImage *image) +{ + FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self); + FpDeviceAction action; + + action = fpi_device_get_current_action (FP_DEVICE (self)); + + g_return_if_fail (image != NULL); + g_return_if_fail (priv->state == FP_IMAGE_DEVICE_STATE_CAPTURE); + g_return_if_fail (action == FP_DEVICE_ACTION_ENROLL || + action == FP_DEVICE_ACTION_VERIFY || + action == FP_DEVICE_ACTION_IDENTIFY || + action == FP_DEVICE_ACTION_CAPTURE); + + fp_image_device_change_state (self, FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF); + + 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. */ + fp_image_detect_minutiae (image, + fpi_device_get_cancellable (FP_DEVICE (self)), + fpi_image_device_minutiae_detected, + self); +} + +/** + * fpi_image_device_retry_scan: + * @self: a #FpImageDevice imaging fingerprint device + * @retry: The #FpDeviceRetry error code to report + * + * Reports a scan failure to the user. This may or may not abort the + * current session. It is the equivalent of fpi_image_device_image_captured() + * in the case of a retryable error condition (e.g. short swipe). + */ +void +fpi_image_device_retry_scan (FpImageDevice *self, FpDeviceRetry retry) +{ + FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self); + FpDeviceAction action; + GError *error; + + action = fpi_device_get_current_action (FP_DEVICE (self)); + + /* We might be waiting for a finger at this point, so just accept + * all but INACTIVE */ + g_return_if_fail (priv->state != FP_IMAGE_DEVICE_STATE_INACTIVE); + g_return_if_fail (action == FP_DEVICE_ACTION_ENROLL || + action == FP_DEVICE_ACTION_VERIFY || + action == FP_DEVICE_ACTION_IDENTIFY || + action == FP_DEVICE_ACTION_CAPTURE); + + error = fpi_device_retry_new (retry); + + if (action == FP_DEVICE_ACTION_ENROLL) + { + g_debug ("Reporting retry during enroll"); + fpi_device_enroll_progress (FP_DEVICE (self), priv->enroll_stage, NULL, error); + } + else + { + /* 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)"); + fp_image_device_deactivate (FP_DEVICE (self)); + fpi_device_action_error (FP_DEVICE (self), error); + } +} + +/** + * fpi_image_device_session_error: + * @self: a #FpImageDevice imaging fingerprint device + * @error: The #GError to report + * + * Report an error while interacting with the device. This effectively + * aborts the current ongoing action. + */ +void +fpi_image_device_session_error (FpImageDevice *self, GError *error) +{ + FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self); + + g_return_if_fail (self); + + if (!error) + { + g_warning ("Driver did not provide an error, generating a generic one"); + error = g_error_new (FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL, "Driver reported session error without an error"); + } + + if (!priv->active) + { + FpDeviceAction action = fpi_device_get_current_action (FP_DEVICE (self)); + g_warning ("Driver reported session error, but device is inactive."); + + if (action != FP_DEVICE_ACTION_NONE) + { + g_warning ("Translating to activation failure!"); + fpi_image_device_activate_complete (self, error); + return; + } + } + else if (priv->state == FP_IMAGE_DEVICE_STATE_INACTIVE) + { + g_warning ("Driver reported session error; translating to deactivation failure."); + fpi_image_device_deactivate_complete (self, error); + return; + } + + if (error->domain == FP_DEVICE_RETRY) + g_warning ("Driver should report retries using fpi_image_device_retry_scan!"); + + fp_image_device_deactivate (FP_DEVICE (self)); + fpi_device_action_error (FP_DEVICE (self), error); +} + +/** + * fpi_image_device_activate_complete: + * @self: a #FpImageDevice imaging fingerprint device + * @error: A #GError or %NULL on success + * + * Reports completion of device activation. + */ +void +fpi_image_device_activate_complete (FpImageDevice *self, GError *error) +{ + FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self); + FpDeviceAction action; + + action = fpi_device_get_current_action (FP_DEVICE (self)); + + g_return_if_fail (priv->active == FALSE); + g_return_if_fail (action == FP_DEVICE_ACTION_ENROLL || + action == FP_DEVICE_ACTION_VERIFY || + action == FP_DEVICE_ACTION_IDENTIFY || + action == FP_DEVICE_ACTION_CAPTURE); + + if (error) + { + g_debug ("Image device activation failed"); + fpi_device_action_error (FP_DEVICE (self), error); + return; + } + + g_debug ("Image device activation completed"); + + priv->active = TRUE; + + /* We always want to capture at this point, move to AWAIT_FINGER + * state. */ + fp_image_device_change_state (self, FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON); +} + +/** + * fpi_image_device_deactivate_complete: + * @self: a #FpImageDevice imaging fingerprint device + * @error: A #GError or %NULL on success + * + * Reports completion of device deactivation. + */ +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); + FpDeviceAction action; + + g_return_if_fail (priv->active == TRUE); + g_return_if_fail (priv->state == FP_IMAGE_DEVICE_STATE_INACTIVE); + + g_debug ("Image device deactivation completed"); + + priv->active = 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)); + + /* Special case, if we should be closing, but didn't due to a running + * deactivation, then do so now. */ + if (action == FP_DEVICE_ACTION_CLOSE) + { + cls->img_close (self); + return; + } + + /* We might be waiting to be able to activate again. */ + if (priv->pending_activation_timeout_id) + fp_image_device_activate (self); +} + +/** + * fpi_image_device_open_complete: + * @self: a #FpImageDevice imaging fingerprint device + * @error: A #GError or %NULL on success + * + * Reports completion of open operation. + */ +void +fpi_image_device_open_complete (FpImageDevice *self, GError *error) +{ + FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self); + FpDeviceAction action; + + action = fpi_device_get_current_action (FP_DEVICE (self)); + + g_return_if_fail (priv->active == FALSE); + g_return_if_fail (action == FP_DEVICE_ACTION_OPEN); + + g_debug ("Image device open completed"); + + priv->state = FP_IMAGE_DEVICE_STATE_INACTIVE; + + fpi_device_open_complete (FP_DEVICE (self), error); +} + +/** + * fpi_image_device_close_complete: + * @self: a #FpImageDevice imaging fingerprint device + * @error: A #GError or %NULL on success + * + * Reports completion of close operation. + */ +void +fpi_image_device_close_complete (FpImageDevice *self, GError *error) +{ + FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self); + FpDeviceAction action; + + action = fpi_device_get_current_action (FP_DEVICE (self)); + + g_debug ("Image device close completed"); + + g_return_if_fail (priv->active == FALSE); + g_return_if_fail (action == FP_DEVICE_ACTION_CLOSE); + + priv->state = FP_IMAGE_DEVICE_STATE_INACTIVE; + + fpi_device_close_complete (FP_DEVICE (self), error); +} diff --git a/libfprint/fpi-data.h b/libfprint/fp-image-device.h similarity index 57% rename from libfprint/fpi-data.h rename to libfprint/fp-image-device.h index 37a7911a..1eda8fbc 100644 --- a/libfprint/fpi-data.h +++ b/libfprint/fp-image-device.h @@ -1,6 +1,6 @@ /* - * Copyright (C) 2007-2008 Daniel Drake - * Copyright (C) 2018 Bastien Nocera + * FpImageDevice - An image based fingerprint reader device + * Copyright (C) 2019 Benjamin Berg * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,18 +17,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef __FPI_DATA_H__ -#define __FPI_DATA_H__ +#pragma once -struct fp_print_data; -struct fp_print_data_item { - size_t length; - unsigned char data[0]; -}; +#include -struct fp_print_data *fpi_print_data_new(struct fp_dev *dev); -struct fp_print_data_item *fpi_print_data_item_new(size_t length); -struct fp_print_data_item *fpi_print_data_get_item(struct fp_print_data *data); -void fpi_print_data_add_item(struct fp_print_data *data, struct fp_print_data_item *item); +G_BEGIN_DECLS -#endif +#define FP_TYPE_IMAGE_DEVICE (fp_image_device_get_type ()) +G_DECLARE_DERIVABLE_TYPE (FpImageDevice, fp_image_device, FP, IMAGE_DEVICE, FpDevice) + +G_END_DECLS diff --git a/libfprint/fp-image.c b/libfprint/fp-image.c new file mode 100644 index 00000000..4b8b3cd1 --- /dev/null +++ b/libfprint/fp-image.c @@ -0,0 +1,610 @@ +/* + * FPrint Image + * Copyright (C) 2007 Daniel Drake + * Copyright (C) 2019 Benjamin Berg + * + * 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-image.h" + +#include "nbis/include/lfs.h" + +#if HAVE_PIXMAN +#include +#endif + +/** + * SECTION: fp-image + * @title: FpImage + * @short_description: Internal Image handling routines + * + * Some devices will provide the image data corresponding to a print + * this object allows accessing this data. + */ + +/** + * SECTION: fpi-image + * @title: Internal FpImage + * @short_description: Internal image handling routines + * + * Internal image handling routines. Also see the public FpImage routines. + */ + +G_DEFINE_TYPE (FpImage, fp_image, G_TYPE_OBJECT) + +enum { + PROP_0, + PROP_WIDTH, + PROP_HEIGHT, + N_PROPS +}; + +static GParamSpec *properties[N_PROPS]; + +FpImage * +fp_image_new (gint width, gint height) +{ + return g_object_new (FP_TYPE_IMAGE, + "width", width, + "height", height, + NULL); +} + +static void +fp_image_finalize (GObject *object) +{ + FpImage *self = (FpImage *) object; + + g_clear_pointer (&self->data, g_free); + g_clear_pointer (&self->binarized, g_free); + g_clear_pointer (&self->minutiae, g_ptr_array_unref); + + G_OBJECT_CLASS (fp_image_parent_class)->finalize (object); +} + +static void +fp_image_constructed (GObject *object) +{ + FpImage *self = (FpImage *) object; + + self->data = g_malloc0 (self->width * self->height); +} + +static void +fp_image_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + FpImage *self = FP_IMAGE (object); + + switch (prop_id) + { + case PROP_WIDTH: + g_value_set_uint (value, self->width); + break; + + case PROP_HEIGHT: + g_value_set_uint (value, self->height); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +fp_image_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + FpImage *self = FP_IMAGE (object); + + switch (prop_id) + { + case PROP_WIDTH: + self->width = g_value_get_uint (value); + break; + + case PROP_HEIGHT: + self->height = g_value_get_uint (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +fp_image_class_init (FpImageClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = fp_image_finalize; + object_class->constructed = fp_image_constructed; + object_class->set_property = fp_image_set_property; + object_class->get_property = fp_image_get_property; + + properties[PROP_WIDTH] = + g_param_spec_uint ("width", + "Width", + "The width of the image", + 0, + G_MAXUINT16, + 0, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + properties[PROP_HEIGHT] = + g_param_spec_uint ("height", + "Height", + "The height of the image", + 0, + G_MAXUINT16, + 0, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + g_object_class_install_properties (object_class, N_PROPS, properties); +} + +static void +fp_image_init (FpImage *self) +{ +} + +typedef struct +{ + GAsyncReadyCallback user_cb; + struct fp_minutiae *minutiae; + gint width, height; + gdouble ppmm; + FpiImageFlags flags; + guchar *image; + guchar *binarized; +} DetectMinutiaeData; + +static void +fp_image_detect_minutiae_free (DetectMinutiaeData *data) +{ + g_clear_pointer (&data->image, g_free); + g_clear_pointer (&data->minutiae, free_minutiae); + g_clear_pointer (&data->binarized, g_free); + g_free (data); +} + +static void +fp_image_detect_minutiae_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GTask *task = G_TASK (res); + FpImage *image; + DetectMinutiaeData *data = g_task_get_task_data (task); + GCancellable *cancellable; + + cancellable = g_task_get_cancellable (task); + if (!cancellable || !g_cancellable_is_cancelled (cancellable)) + { + gint i; + image = FP_IMAGE (source_object); + + image->flags = data->flags; + + g_clear_pointer (&image->data, g_free); + image->data = g_steal_pointer (&data->image); + + g_clear_pointer (&image->binarized, g_free); + image->binarized = g_steal_pointer (&data->binarized); + + g_clear_pointer (&image->minutiae, g_ptr_array_unref); + image->minutiae = g_ptr_array_new_full (data->minutiae->num, + (GDestroyNotify) free_minutia); + + for (i = 0; i < data->minutiae->num; i++) + g_ptr_array_add (image->minutiae, + g_steal_pointer (&data->minutiae->list[i])); + + /* Don't let it delete anything. */ + data->minutiae->num = 0; + } + + if (data->user_cb) + data->user_cb (source_object, res, user_data); +} + +static void +vflip (guint8 *data, gint width, gint height) +{ + int data_len = width * height; + unsigned char rowbuf[width]; + int i; + + for (i = 0; i < height / 2; i++) + { + int offset = i * width; + int swap_offset = data_len - (width * (i + 1)); + + /* copy top row into buffer */ + memcpy (rowbuf, data + offset, width); + + /* copy lower row over upper row */ + memcpy (data + offset, data + swap_offset, width); + + /* copy buffer over lower row */ + memcpy (data + swap_offset, rowbuf, width); + } +} + +static void +hflip (guint8 *data, gint width, gint height) +{ + unsigned char rowbuf[width]; + int i, j; + + for (i = 0; i < height; i++) + { + int offset = i * width; + + memcpy (rowbuf, data + offset, width); + for (j = 0; j < width; j++) + data[offset + j] = rowbuf[width - j - 1]; + } +} + +static void +invert_colors (guint8 *data, gint width, gint height) +{ + int data_len = width * height; + int i; + + for (i = 0; i < data_len; i++) + data[i] = 0xff - data[i]; +} + +static void +fp_image_detect_minutiae_thread_func (GTask *task, + gpointer source_object, + gpointer task_data, + GCancellable *cancellable) +{ + g_autoptr(GTimer) timer = NULL; + DetectMinutiaeData *data = task_data; + struct fp_minutiae *minutiae = NULL; + g_autofree gint *direction_map = NULL; + g_autofree gint *low_contrast_map = NULL; + g_autofree gint *low_flow_map = NULL; + g_autofree gint *high_curve_map = NULL; + g_autofree gint *quality_map = NULL; + g_autofree guchar *bdata = NULL; + gint map_w, map_h; + gint bw, bh, bd; + gint r; + + /* Normalize the image first */ + if (data->flags & FPI_IMAGE_H_FLIPPED) + hflip (data->image, data->width, data->height); + + if (data->flags & FPI_IMAGE_V_FLIPPED) + vflip (data->image, data->width, data->height); + + if (data->flags & FPI_IMAGE_COLORS_INVERTED) + invert_colors (data->image, data->width, data->height); + + data->flags &= ~(FPI_IMAGE_H_FLIPPED | FPI_IMAGE_V_FLIPPED | FPI_IMAGE_COLORS_INVERTED); + + timer = g_timer_new (); + r = get_minutiae (&minutiae, &quality_map, &direction_map, + &low_contrast_map, &low_flow_map, &high_curve_map, + &map_w, &map_h, &bdata, &bw, &bh, &bd, + data->image, data->width, data->height, 8, + data->ppmm, &g_lfsparms_V2); + g_timer_stop (timer); + fp_dbg ("Minutiae scan completed in %f secs", g_timer_elapsed (timer, NULL)); + + data->binarized = g_steal_pointer (&bdata); + data->minutiae = minutiae; + + if (r) + { + fp_err ("get minutiae failed, code %d", r); + g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Minutiae scan failed with code %d", r); + g_object_unref (task); + return; + } + + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +/** + * fp_image_get_height: + * @self: A #FpImage + * + * Gets the pixel height of an image. + * + * Returns: the height of the image + */ +guint +fp_image_get_height (FpImage *self) +{ + return self->height; +} + +/** + * fp_image_get_width: + * @self: A #FpImage + * + * Gets the pixel width of an image. + * + * Returns: the width of the image + */ +guint +fp_image_get_width (FpImage *self) +{ + return self->width; +} + +/** + * fp_image_get_ppmm: + * @self: A #FpImage + * + * Gets the resolution of the image. Note that this is assumed to + * be fixed to 500 points per inch (~19.685 p/mm) for most drivers. + * + * Returns: the resolution of the image in points per millimeter + */ +gdouble +fp_image_get_ppmm (FpImage *self) +{ + return self->ppmm; +} + +/** + * fp_image_get_data: + * @self: A #FpImage + * @len: (out) (optional): Return location for length or %NULL + * + * Gets the greyscale data for an image. This data must not be modified or + * freed. + * + * Returns: (transfer none) (array length=len): The image data + */ +const guchar * +fp_image_get_data (FpImage *self, gsize *len) +{ + if (len) + *len = self->width * self->height; + + return self->data; +} + +/** + * fp_image_get_binarized: + * @self: A #FpImage + * @len: (out) (optional): Return location for length or %NULL + * + * Gets the binarized data for an image. This data must not be modified or + * freed. You need to first detect the minutiae using + * fp_image_detect_minutiae(). + * + * Returns: (transfer none) (array length=len): The binarized image data + */ +const guchar * +fp_image_get_binarized (FpImage *self, gsize *len) +{ + if (len && self->binarized) + *len = self->width * self->height; + + return self->binarized; +} + +/** + * fp_image_get_minutiae: + * @self: A #FpImage + * + * Gets the minutiae for an image. This data must not be modified or + * freed. You need to first detect the minutiae using + * fp_image_detect_minutiae(). + * + * Returns: (transfer none) (element-type FpMinutia): The detected minutiae + */ +GPtrArray * +fp_image_get_minutiae (FpImage *self) +{ + return self->minutiae; +} + +/** + * fp_image_detect_minutiae: + * @self: A #FpImage + * @cancellable: a #GCancellable, or %NULL + * @callback: the function to call on completion + * @user_data: the data to pass to @callback + * + * Detects the minutiae found in an image. + */ +void +fp_image_detect_minutiae (FpImage *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + DetectMinutiaeData *data = g_new0 (DetectMinutiaeData, 1); + + task = g_task_new (self, cancellable, fp_image_detect_minutiae_cb, user_data); + + data->image = g_malloc (self->width * self->height); + memcpy (data->image, self->data, self->width * self->height); + data->flags = self->flags; + data->width = self->width; + data->height = self->height; + data->ppmm = self->ppmm; + data->user_cb = callback; + + g_task_set_task_data (task, data, (GDestroyNotify) fp_image_detect_minutiae_free); + g_task_run_in_thread (task, fp_image_detect_minutiae_thread_func); +} + +/** + * fp_image_detect_minutiae_finish: + * @self: A #FpImage + * @result: A #GAsyncResult + * @error: Return location for errors, or %NULL to ignore + * + * Finish minutiae detection in an image + * + * Returns: %TRUE on success + */ +gboolean +fp_image_detect_minutiae_finish (FpImage *self, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (result), error); +} + + + +/** + * fpi_std_sq_dev: + * @buf: buffer (usually bitmap, one byte per pixel) + * @size: size of @buffer + * + * Calculates the squared standard deviation of the individual + * pixels in the buffer, as per the following formula: + * |[ + * mean = sum (buf[0..size]) / size + * sq_dev = sum ((buf[0.size] - mean) ^ 2) + * ]| + * This function is usually used to determine whether image + * is empty. + * + * Returns: the squared standard deviation for @buffer + */ +gint +fpi_std_sq_dev (const guint8 *buf, + gint size) +{ + guint64 res = 0, mean = 0; + gint i; + + for (i = 0; i < size; i++) + mean += buf[i]; + + mean /= size; + + for (i = 0; i < size; i++) + { + int dev = (int) buf[i] - mean; + res += dev * dev; + } + + return res / size; +} + +/** + * fpi_mean_sq_diff_norm: + * @buf1: buffer (usually bitmap, one byte per pixel) + * @buf2: buffer (usually bitmap, one byte per pixel) + * @size: buffer size of smallest buffer + * + * This function calculates the normalized mean square difference of + * two buffers, usually two lines, as per the following formula: + * |[ + * sq_diff = sum ((buf1[0..size] - buf2[0..size]) ^ 2) / size + * ]| + * + * This functions is usually used to get numerical difference + * between two images. + * + * Returns: the normalized mean squared difference between @buf1 and @buf2 + */ +gint +fpi_mean_sq_diff_norm (const guint8 *buf1, + const guint8 *buf2, + gint size) +{ + int res = 0, i; + + for (i = 0; i < size; i++) + { + int dev = (int) buf1[i] - (int) buf2[i]; + res += dev * dev; + } + + return res / size; +} + +/** + * fp_minutia_get_coords: + * @min: A #FpMinutia + * @x: (out): x position in image + * @y: (out): y position in image + * + * Returns the coordinates of the found minutia. This is only useful for + * debugging purposes and the API is not considered stable for production. + */ +void +fp_minutia_get_coords (FpMinutia *min, gint *x, gint *y) +{ + if (x) + *x = min->x; + if (y) + *y = min->y; +} + +#if HAVE_PIXMAN +FpImage * +fpi_image_resize (FpImage *orig_img, + guint w_factor, + guint h_factor) +{ + int new_width = orig_img->width * w_factor; + int new_height = orig_img->height * h_factor; + pixman_image_t *orig, *resized; + pixman_transform_t transform; + FpImage *newimg; + + orig = pixman_image_create_bits (PIXMAN_a8, orig_img->width, orig_img->height, (uint32_t *) orig_img->data, orig_img->width); + resized = pixman_image_create_bits (PIXMAN_a8, new_width, new_height, NULL, new_width); + + pixman_transform_init_identity (&transform); + pixman_transform_scale (NULL, &transform, pixman_int_to_fixed (w_factor), pixman_int_to_fixed (h_factor)); + pixman_image_set_transform (orig, &transform); + pixman_image_set_filter (orig, PIXMAN_FILTER_BILINEAR, NULL, 0); + pixman_image_composite32 (PIXMAN_OP_SRC, + orig, /* src */ + NULL, /* mask */ + resized, /* dst */ + 0, 0, /* src x y */ + 0, 0, /* mask x y */ + 0, 0, /* dst x y */ + new_width, new_height /* width height */ + ); + + newimg = fp_image_new (new_width, new_height); + newimg->flags = orig_img->flags; + + memcpy (newimg->data, pixman_image_get_data (resized), new_width * new_height); + + pixman_image_unref (orig); + pixman_image_unref (resized); + + return newimg; +} +#endif diff --git a/libfprint/fp-image.h b/libfprint/fp-image.h new file mode 100644 index 00000000..7de9f1a4 --- /dev/null +++ b/libfprint/fp-image.h @@ -0,0 +1,59 @@ +/* + * FPrint Image + * Copyright (C) 2007 Daniel Drake + * Copyright (C) 2019 Benjamin Berg + * + * 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 + +G_BEGIN_DECLS + +#define FP_TYPE_IMAGE (fp_image_get_type ()) + +typedef struct fp_minutia FpMinutia; + +G_DECLARE_FINAL_TYPE (FpImage, fp_image, FP, IMAGE, GObject) + +FpImage *fp_image_new (gint width, + gint height); + +guint fp_image_get_width (FpImage *self); +guint fp_image_get_height (FpImage *self); +gdouble fp_image_get_ppmm (FpImage *self); + +GPtrArray * fp_image_get_minutiae (FpImage *self); + +void fp_image_detect_minutiae (FpImage *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean fp_image_detect_minutiae_finish (FpImage *self, + GAsyncResult *result, + GError **error); + +const guchar * fp_image_get_data (FpImage *self, + gsize *len); +const guchar * fp_image_get_binarized (FpImage *self, + gsize *len); + +void fp_minutia_get_coords (FpMinutia *min, + gint *x, + gint *y); + +G_END_DECLS diff --git a/libfprint/fp-print.c b/libfprint/fp-print.c new file mode 100644 index 00000000..644370d6 --- /dev/null +++ b/libfprint/fp-print.c @@ -0,0 +1,1118 @@ +/* + * FPrint Print handling + * Copyright (C) 2007 Daniel Drake + * Copyright (C) 2019 Benjamin Berg + * + * 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-print.h" +#include "fpi-image.h" +#include "fpi-device.h" + +#include "nbis/include/bozorth.h" +#include "nbis/include/lfs.h" + +/** + * SECTION: fp-print + * @title: FpPrint + * @short_description: Fingerprint handling + * + * Interaction with prints and their storage. + */ + +/** + * SECTION: fpi-print + * @title: Internal FpPrint + * @short_description: Internal fingerprint handling routines + * + * Interaction with prints and their storage. See also the public + * #FpPrint routines. + */ + +struct _FpPrint +{ + GInitiallyUnowned parent_instance; + + FpPrintType type; + + gchar *driver; + gchar *device_id; + gboolean device_stored; + + FpImage *image; + + /* Metadata */ + FpFinger finger; + gchar *username; + gchar *description; + GDate *enroll_date; + + GVariant *data; + GPtrArray *prints; +}; + +G_DEFINE_TYPE (FpPrint, fp_print, G_TYPE_INITIALLY_UNOWNED) + +enum { + PROP_0, + PROP_DRIVER, + PROP_DEVICE_ID, + PROP_DEVICE_STORED, + PROP_IMAGE, + + /* The following is metadata that is stored by default for each print. + * Drivers may make use of these during enrollment (e.g. to additionaly store + * the metadata on the device). */ + PROP_FINGER, + PROP_USERNAME, + PROP_DESCRIPTION, + PROP_ENROLL_DATE, + + /* Private property*/ + PROP_FPI_TYPE, + PROP_FPI_DATA, + N_PROPS +}; + +static GParamSpec *properties[N_PROPS]; + +static void +fp_print_finalize (GObject *object) +{ + FpPrint *self = (FpPrint *) object; + + g_clear_object (&self->image); + g_clear_pointer (&self->device_id, g_free); + g_clear_pointer (&self->driver, g_free); + g_clear_pointer (&self->username, g_free); + g_clear_pointer (&self->description, g_free); + g_clear_pointer (&self->enroll_date, g_date_free); + g_clear_pointer (&self->data, g_variant_unref); + + G_OBJECT_CLASS (fp_print_parent_class)->finalize (object); +} + +static void +fp_print_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + FpPrint *self = FP_PRINT (object); + + switch (prop_id) + { + case PROP_DRIVER: + g_value_set_string (value, self->driver); + break; + + case PROP_DEVICE_ID: + g_value_set_string (value, self->device_id); + break; + + case PROP_DEVICE_STORED: + g_value_set_boolean (value, self->device_stored); + break; + + case PROP_IMAGE: + g_value_set_object (value, self->image); + break; + + case PROP_FINGER: + g_value_set_enum (value, self->finger); + break; + + case PROP_USERNAME: + g_value_set_string (value, self->username); + break; + + case PROP_DESCRIPTION: + g_value_set_string (value, self->description); + break; + + case PROP_ENROLL_DATE: + g_value_set_boxed (value, self->enroll_date); + break; + + case PROP_FPI_TYPE: + g_value_set_enum (value, self->type); + break; + + case PROP_FPI_DATA: + g_value_set_variant (value, self->data); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +fp_print_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + FpPrint *self = FP_PRINT (object); + + switch (prop_id) + { + case PROP_FPI_TYPE: + fpi_print_set_type (self, g_value_get_enum (value)); + break; + + case PROP_DRIVER: + self->driver = g_value_dup_string (value); + break; + + case PROP_DEVICE_ID: + self->device_id = g_value_dup_string (value); + break; + + case PROP_DEVICE_STORED: + self->device_stored = g_value_get_boolean (value); + break; + + case PROP_FINGER: + self->finger = g_value_get_enum (value); + break; + + case PROP_USERNAME: + g_clear_pointer (&self->username, g_free); + self->username = g_value_dup_string (value); + break; + + case PROP_DESCRIPTION: + g_clear_pointer (&self->description, g_free); + self->description = g_value_dup_string (value); + break; + + case PROP_ENROLL_DATE: + g_clear_pointer (&self->enroll_date, g_date_free); + self->enroll_date = g_value_dup_boxed (value); + break; + + case PROP_FPI_DATA: + g_clear_pointer (&self->description, g_variant_unref); + self->data = g_value_dup_variant (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +fp_print_constructed (GObject *obj) +{ + FpPrint *self = FP_PRINT (obj); + + g_assert (self->driver != NULL); + g_assert (self->device_id != NULL); +} + +static void +fp_print_class_init (FpPrintClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->constructed = fp_print_constructed; + object_class->finalize = fp_print_finalize; + object_class->get_property = fp_print_get_property; + object_class->set_property = fp_print_set_property; + + properties[PROP_DRIVER] = + g_param_spec_string ("driver", + "Driver", + "The name of the driver that created the print", + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + properties[PROP_DEVICE_ID] = + g_param_spec_string ("device-id", + "Device ID", + "Unique ID allowing to check if a device is compatible with the print", + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + properties[PROP_DEVICE_STORED] = + g_param_spec_boolean ("device-stored", + "Device Stored", + "Whether the print is a handle for data that is stored on the device", + FALSE, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + properties[PROP_IMAGE] = + g_param_spec_object ("image", + "Image", + "The image that was used for the print, only valid for newly enrolled prints on image based devices", + FP_TYPE_IMAGE, + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE); + + properties[PROP_FINGER] = + g_param_spec_enum ("finger", + "Finger", + "The enrolled finger", + FP_TYPE_FINGER, + FP_FINGER_UNKNOWN, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + + properties[PROP_USERNAME] = + g_param_spec_string ("username", + "Username", + "The username that the enrolled print belongs to", + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + + properties[PROP_DESCRIPTION] = + g_param_spec_string ("description", + "Description", + "A user defined description for the print", + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + + properties[PROP_ENROLL_DATE] = + g_param_spec_boxed ("enroll-date", + "Enroll Date", + "The date of enrollment", + G_TYPE_DATE, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + + properties[PROP_FPI_TYPE] = + g_param_spec_enum ("fp-type", + "Type", + "Private: The type of the print data", + FP_TYPE_PRINT_TYPE, + FP_PRINT_RAW, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); + + properties[PROP_FPI_DATA] = + g_param_spec_variant ("fp-data", + "Raw Data", + "The raw data for internal use only", + G_VARIANT_TYPE_ANY, + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + + g_object_class_install_properties (object_class, N_PROPS, properties); +} + +static void +fp_print_init (FpPrint *self) +{ +} + +/** + * fp_print_new: + * @device: A #FpDevice + * + * Create a new #FpPrint. This is only useful to prepare an enrollment + * of a new print using fp_device_enroll(). For this you should first + * create a new print, fill in the relevant metadata, and then start + * enrollment. + * + * Returns: (transfer floating): A newyl created #FpPrint + */ +FpPrint * +fp_print_new (FpDevice *device) +{ + g_return_val_if_fail (device, NULL); + + return g_object_new (FP_TYPE_PRINT, + "driver", fp_device_get_driver (device), + "device-id", fp_device_get_device_id (device), + NULL); +} + +/** + * fp_print_get_driver: + * @print: A #FpPrint + * + * Returns the driver that the print was created for. + * + * Returns: (transfer none): The driver + */ +const gchar * +fp_print_get_driver (FpPrint *print) +{ + g_return_val_if_fail (FP_IS_PRINT (print), NULL); + + return print->driver; +} + +/** + * fp_print_get_device_id: + * @print: A #FpPrint + * + * Returns the device ID that the print was created for. + * + * Returns: (transfer none): The device ID + */ +const gchar * +fp_print_get_device_id (FpPrint *print) +{ + g_return_val_if_fail (FP_IS_PRINT (print), NULL); + + return print->device_id; +} + +/** + * fp_print_get_device_stored: + * @print: A #FpPrint + * + * Whether the print is actually stored on the device and this is + * just a handle to use that references the device stored data. + * + * Returns: Whether the print is stored on the device + */ +gboolean +fp_print_get_device_stored (FpPrint *print) +{ + g_return_val_if_fail (FP_IS_PRINT (print), FALSE); + + return print->device_stored; +} + +/** + * fp_print_get_image: + * @print: A #FpPrint + * + * Returns the image that the print was created from, or %NULL + * + * Returns: (transfer none) (nullable): The #FpImage + */ +FpImage * +fp_print_get_image (FpPrint *print) +{ + g_return_val_if_fail (FP_IS_PRINT (print), NULL); + + return print->image; +} + +/** + * fp_print_get_finger: + * @print: A #FpPrint + * + * Returns the finger that the print was created for. + * + * Returns: The #FpFinger + */ +FpFinger +fp_print_get_finger (FpPrint *print) +{ + g_return_val_if_fail (FP_IS_PRINT (print), FP_FINGER_UNKNOWN); + + return print->finger; +} + +/** + * fp_print_get_username: + * @print: A #FpPrint + * + * Returns the user defined username for the print. + * + * Returns: (transfer none) (nullable): The username + */ +const gchar * +fp_print_get_username (FpPrint *print) +{ + g_return_val_if_fail (FP_IS_PRINT (print), NULL); + + return print->username; +} + +/** + * fp_print_get_description: + * @print: A #FpPrint + * + * Returns the user defined description for the print. + * + * Returns: (transfer none) (nullable): The description + */ +const gchar * +fp_print_get_description (FpPrint *print) +{ + g_return_val_if_fail (FP_IS_PRINT (print), NULL); + + return print->description; +} + +/** + * fp_print_get_enroll_date: + * @print: A #FpPrint + * + * Returns the user defined enroll date for the print. + * + * Returns: (transfer none) (nullable): The #GDate + */ +const GDate * +fp_print_get_enroll_date (FpPrint *print) +{ + g_return_val_if_fail (FP_IS_PRINT (print), NULL); + + return print->enroll_date; +} + +/** + * fp_print_set_finger: + * @print: A #FpPrint + * @finger: The #FpFinger + * + * Set the finger that the print is for. + */ +void +fp_print_set_finger (FpPrint *print, + FpFinger finger) +{ + g_return_if_fail (FP_IS_PRINT (print)); + + print->finger = finger; + g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_FINGER]); +} + +/** + * fp_print_set_username: + * @print: A #FpPrint + * @username: (transfer none): The new username + * + * Set the username for the print. + */ +void +fp_print_set_username (FpPrint *print, + const gchar *username) +{ + g_return_if_fail (FP_IS_PRINT (print)); + + g_clear_pointer (&print->username, g_free); + print->username = g_strdup (username); + g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_USERNAME]); +} + +/** + * fp_print_set_description: + * @print: A #FpPrint + * @description: (transfer none): The new description + * + * Set the description for the print. + */ +void +fp_print_set_description (FpPrint *print, + const gchar *description) +{ + g_return_if_fail (FP_IS_PRINT (print)); + + g_clear_pointer (&print->description, g_free); + print->description = g_strdup (description); + g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_DESCRIPTION]); +} + +/** + * fp_print_set_enroll_date: + * @print: A #FpPrint + * @enroll_date: (transfer none): The new enroll date + * + * Set the enroll date for the print. + */ +void +fp_print_set_enroll_date (FpPrint *print, + const GDate *enroll_date) +{ + g_return_if_fail (FP_IS_PRINT (print)); + + g_clear_pointer (&print->enroll_date, g_date_free); + if (enroll_date) + { + /* XXX: Should use g_date_copy, but that is new in 2.56. */ + print->enroll_date = g_date_new (); + *print->enroll_date = *enroll_date; + } + g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_ENROLL_DATE]); +} + + + +/** + * fpi_print_add_print: + * @print: A #FpPrint + * @add: Print to append to @print + * + * Appends the single #FP_PRINT_NBIS print from @add to the collection of + * prints in @print. Both print objects need to be of type #FP_PRINT_NBIS + * for this to work. + */ +void +fpi_print_add_print (FpPrint *print, FpPrint *add) +{ + g_return_if_fail (print->type == FP_PRINT_NBIS); + g_return_if_fail (add->type == FP_PRINT_NBIS); + + g_assert (add->prints->len == 1); + g_ptr_array_add (print->prints, g_memdup (add->prints->pdata[0], sizeof (struct xyt_struct))); +} + +/** + * fpi_print_set_type: + * @print: A #FpPrint + * @type: The newly type of the print data + * + * This function can only be called exactly once. Drivers should + * call it after creating a new print, or to initialize the template + * print passed during enrollment. + */ +void +fpi_print_set_type (FpPrint *print, + FpPrintType type) +{ + g_return_if_fail (FP_IS_PRINT (print)); + /* We only allow setting this once! */ + g_return_if_fail (print->type == FP_PRINT_UNDEFINED); + + print->type = type; + if (print->type == FP_PRINT_NBIS) + print->prints = g_ptr_array_new_with_free_func (g_free); + g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_FPI_TYPE]); +} + +/** + * fpi_print_set_device_stored: + * @print: A #FpPrint + * @device_stored: Whether the print is stored on the device or not + * + * Drivers must set this to %TRUE for any print that is really a handle + * for data that is stored on the device itself. + */ +void +fpi_print_set_device_stored (FpPrint *print, + gboolean device_stored) +{ + g_return_if_fail (FP_IS_PRINT (print)); + + print->device_stored = device_stored; + g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_DEVICE_STORED]); +} + +/* XXX: This is the old version, but wouldn't it be smarter to instead + * use the highest quality mintutiae? Possibly just using bz_prune from + * upstream? */ +static void +minutiae_to_xyt (struct fp_minutiae *minutiae, + int bwidth, + int bheight, + struct xyt_struct *xyt) +{ + int i; + struct fp_minutia *minutia; + struct minutiae_struct c[MAX_FILE_MINUTIAE]; + + /* struct xyt_struct uses arrays of MAX_BOZORTH_MINUTIAE (200) */ + int nmin = min (minutiae->num, MAX_BOZORTH_MINUTIAE); + + for (i = 0; i < nmin; i++) + { + minutia = minutiae->list[i]; + + lfs2nist_minutia_XYT (&c[i].col[0], &c[i].col[1], &c[i].col[2], + minutia, bwidth, bheight); + c[i].col[3] = sround (minutia->reliability * 100.0); + + if (c[i].col[2] > 180) + c[i].col[2] -= 360; + } + + qsort ((void *) &c, (size_t) nmin, sizeof (struct minutiae_struct), + sort_x_y); + + for (i = 0; i < nmin; i++) + { + xyt->xcol[i] = c[i].col[0]; + xyt->ycol[i] = c[i].col[1]; + xyt->thetacol[i] = c[i].col[2]; + } + xyt->nrows = nmin; +} + +/** + * fpi_print_add_from_image: + * @print: A #FpPrint + * @image: A #FpImage + * @error: Return location for error + * + * Extracts the minutiae from the given image and adds it to @print of + * type #FP_PRINT_NBIS. + * + * The @image will be kept so that API users can get retrieve it e.g. + * for debugging purposes. + * + * Returns: %TRUE on success + */ +gboolean +fpi_print_add_from_image (FpPrint *print, + FpImage *image, + GError **error) +{ + GPtrArray *minutiae; + struct fp_minutiae _minutiae; + struct xyt_struct *xyt; + + if (print->type != FP_PRINT_NBIS || !image) + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_DATA, + "Cannot add print data from image!"); + return FALSE; + } + + minutiae = fp_image_get_minutiae (image); + if (!minutiae || minutiae->len == 0) + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_DATA, + "No minutiae found in image or not yet detected!"); + return FALSE; + } + + _minutiae.num = minutiae->len; + _minutiae.list = (struct fp_minutia **) minutiae->pdata; + _minutiae.alloc = minutiae->len; + + xyt = g_new0 (struct xyt_struct, 1); + minutiae_to_xyt (&_minutiae, image->width, image->height, xyt); + g_ptr_array_add (print->prints, xyt); + + g_clear_object (&print->image); + print->image = g_object_ref (image); + g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_IMAGE]); + + return TRUE; +} + +/** + * fpi_print_bz3_match: + * @template: A #FpPrint containing one or more prints + * @print: A newly scanned #FpPrint to test + * @bz3_threshold: The BZ3 match threshold + * @error: Return location for error + * + * Match the newly scanned @print (containing exactly one print) against the + * prints contained in @template which will have been stored during enrollment. + * + * Both @template and @print need to be of type #FP_PRINT_NBIS for this to + * work. + * + * Returns: Whether the prints match, @error will be set if #FPI_MATCH_ERROR is returned + */ +FpiMatchResult +fpi_print_bz3_match (FpPrint *template, FpPrint *print, gint bz3_threshold, GError **error) +{ + struct xyt_struct *pstruct; + gint probe_len; + gint i; + + /* XXX: Use a different error type? */ + if (template->type != FP_PRINT_NBIS || print->type != FP_PRINT_NBIS) + { + *error = fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED, + "It is only possible to match NBIS type print data"); + return FPI_MATCH_ERROR; + } + + if (print->prints->len != 1) + { + *error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, + "New print contains more than one print!"); + return FPI_MATCH_ERROR; + } + + pstruct = g_ptr_array_index (print->prints, 0); + probe_len = bozorth_probe_init (pstruct); + + for (i = 0; i < template->prints->len; i++) + { + struct xyt_struct *gstruct; + gint score; + gstruct = g_ptr_array_index (template->prints, i); + score = bozorth_to_gallery (probe_len, pstruct, gstruct); + fp_dbg ("score %d", score); + + if (score >= bz3_threshold) + return FPI_MATCH_SUCCESS; + } + + return FPI_MATCH_FAIL; +} + +/** + * fp_print_compatible: + * @self: A #FpPrint + * @device: A #FpDevice + * + * Tests whether the prints is compatible with the given device. + * + * Returns: %TRUE if the print is compatible with the device + */ +gboolean +fp_print_compatible (FpPrint *self, FpDevice *device) +{ + g_return_val_if_fail (FP_IS_PRINT (self), FALSE); + g_return_val_if_fail (FP_IS_DEVICE (device), FALSE); + + if (g_strcmp0 (self->driver, fp_device_get_driver (device))) + return FALSE; + + if (g_strcmp0 (self->device_id, fp_device_get_device_id (device))) + return FALSE; + + return TRUE; +} + +/** + * fp_print_equal: + * @self: First #FpPrint + * @other: Second #FpPrint + * + * Tests whether the prints can be considered equal. This only compares the + * actual information about the print, not the metadata. + * + * Returns: %TRUE if the prints are equal + */ +gboolean +fp_print_equal (FpPrint *self, FpPrint *other) +{ + g_return_val_if_fail (FP_IS_PRINT (self), FALSE); + g_return_val_if_fail (FP_IS_PRINT (other), FALSE); + g_return_val_if_fail (self->type != FP_PRINT_UNDEFINED, FALSE); + g_return_val_if_fail (other->type != FP_PRINT_UNDEFINED, FALSE); + + if (self->type != other->type) + return FALSE; + + if (g_strcmp0 (self->driver, other->driver)) + return FALSE; + + if (g_strcmp0 (self->device_id, other->device_id)) + return FALSE; + + if (self->type == FP_PRINT_RAW) + { + return g_variant_equal (self->data, other->data); + } + else if (self->type == FP_PRINT_NBIS) + { + gint i; + + if (self->prints->len != other->prints->len) + return FALSE; + + for (i = 0; i < self->prints->len; i++) + { + struct xyt_struct *a = g_ptr_array_index (self->prints, i); + struct xyt_struct *b = g_ptr_array_index (other->prints, i); + + if (memcmp (a, b, sizeof (struct xyt_struct)) != 0) + return FALSE; + } + + return TRUE; + } + else + { + g_assert_not_reached (); + } +} + +#define FP_PRINT_VARIANT_TYPE G_VARIANT_TYPE ("(issbymsmsia{sv}v)") + +G_STATIC_ASSERT (sizeof (((struct xyt_struct *) NULL)->xcol[0]) == 4); + +/** + * fp_print_serialize: + * @print: A #FpPrint + * @data: (array length=length) (transfer full) (out): Return location for data pointer + * @length: (transfer full) (out): Length of @data + * @error: Return location for error + * + * Serialize a print definition for permanent storage. Note that this is + * lossy in the sense that e.g. the image data is discarded. + * + * Returns: (type void): %TRUE on success + */ +gboolean +fp_print_serialize (FpPrint *print, + guchar **data, + gsize *length, + GError **error) +{ + g_autoptr(GVariant) result = NULL; + GVariantBuilder builder = G_VARIANT_BUILDER_INIT (FP_PRINT_VARIANT_TYPE); + gsize len; + + g_assert (data); + g_assert (length); + + g_variant_builder_add (&builder, "i", print->type); + g_variant_builder_add (&builder, "s", print->driver); + g_variant_builder_add (&builder, "s", print->device_id); + g_variant_builder_add (&builder, "b", print->device_stored); + + /* Metadata */ + g_variant_builder_add (&builder, "y", print->finger); + g_variant_builder_add (&builder, "ms", print->username); + g_variant_builder_add (&builder, "ms", print->description); + if (print->enroll_date && g_date_valid (print->enroll_date)) + g_variant_builder_add (&builder, "i", g_date_get_julian (print->enroll_date)); + else + g_variant_builder_add (&builder, "i", G_MININT32); + + /* Unused a{sv} for expansion */ + g_variant_builder_open (&builder, G_VARIANT_TYPE_VARDICT); + g_variant_builder_close (&builder); + + /* Insert NBIS print data for type NBIS, otherwise the GVariant directly */ + if (print->type == FP_PRINT_NBIS) + { + GVariantBuilder nested = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("(a(aiaiai))")); + gint i; + + g_variant_builder_open (&nested, G_VARIANT_TYPE ("a(aiaiai)")); + 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, + col, + xyt->nrows, + 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, + col, + xyt->nrows, + 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, + col, + xyt->nrows, + sizeof (col[0]))); + g_variant_builder_close (&nested); + } + + g_variant_builder_close (&nested); + g_variant_builder_add (&builder, "v", g_variant_builder_end (&nested)); + } + else + { + g_variant_builder_add (&builder, "v", g_variant_new_variant (print->data)); + } + + result = g_variant_builder_end (&builder); + + if (G_BYTE_ORDER == G_BIG_ENDIAN) + { + GVariant *tmp; + tmp = g_variant_byteswap (result); + g_variant_unref (result); + result = tmp; + } + + len = g_variant_get_size (result); + /* Add 3 bytes of header */ + len += 3; + + *data = g_malloc (len); + *length = len; + + (*data)[0] = (guchar) 'F'; + (*data)[1] = (guchar) 'P'; + (*data)[2] = (guchar) '3'; + + g_variant_get_data (result); + g_variant_store (result, (*data) + 3); + + return TRUE; +} + +/** + * fp_print_deserialize: + * @data: (array length=length): The binary data + * @length: Length of the data + * @error: Return location for error + * + * Deserialize a print definition from permanent storage. + * + * Returns: (transfer full): A newly created #FpPrint on success + */ +FpPrint * +fp_print_deserialize (const guchar *data, + gsize length, + GError **error) +{ + g_autoptr(FpPrint) result = NULL; + g_autoptr(GVariant) raw_value = NULL; + g_autoptr(GVariant) value = NULL; + guchar *aligned_data = NULL; + GDate *date = NULL; + guint8 finger_int8; + FpFinger finger; + g_autofree gchar *username = NULL; + g_autofree gchar *description = NULL; + gint julian_date; + FpPrintType type; + const gchar *driver; + const gchar *device_id; + gboolean device_stored; + GVariant *print_data; + + g_assert (data); + g_assert (length > 3); + + if (memcmp (data, "FP3", 3) != 0) + goto invalid_format; + + /* NOTE: + * We make sure that we have no variant left over from the parsing at the end + * of this function (meaning we don't need to keep the data around. + */ + + /* To support GLIB < 2.60 we need to make sure that the memory is aligned correctly. + * We also need to copy the backing store for the raw data that we may keep for + * longer. */ + aligned_data = g_malloc (length - 3); + memcpy (aligned_data, data + 3, length - 3); + raw_value = g_variant_new_from_data (FP_PRINT_VARIANT_TYPE, + aligned_data, length - 3, + FALSE, g_free, NULL); + + if (!raw_value) + goto invalid_format; + + if (G_BYTE_ORDER == G_BIG_ENDIAN) + value = g_variant_byteswap (raw_value); + else + value = g_variant_get_normal_form (raw_value); + + g_variant_get (value, + "(issbymsmsi@a{sv}v)", + &type, + &driver, + &device_id, + &device_stored, + &finger_int8, + &username, + &description, + &julian_date, + NULL, + &print_data); + + finger = finger_int8; + + /* Assume data is valid at this point if the values are somewhat sane. */ + if (type == FP_PRINT_NBIS) + { + g_autoptr(GVariant) prints = g_variant_get_child_value (print_data, 0); + gint i; + + result = g_object_new (FP_TYPE_PRINT, + "driver", driver, + "device-id", device_id, + "device-stored", device_stored, + NULL); + fpi_print_set_type (result, FP_PRINT_NBIS); + for (i = 0; i < g_variant_n_children (prints); i++) + { + struct xyt_struct *xyt = g_new0 (struct xyt_struct, 1); + const gint32 *xcol, *ycol, *thetacol; + gsize xlen, ylen, thetalen; + g_autoptr(GVariant) xyt_data = NULL; + GVariant *child; + + xyt_data = g_variant_get_child_value (prints, i); + + child = g_variant_get_child_value (xyt_data, 0); + xcol = g_variant_get_fixed_array (child, &xlen, sizeof (gint32)); + g_variant_unref (child); + + child = g_variant_get_child_value (xyt_data, 1); + ycol = g_variant_get_fixed_array (child, &ylen, sizeof (gint32)); + g_variant_unref (child); + + child = g_variant_get_child_value (xyt_data, 2); + thetacol = g_variant_get_fixed_array (child, &thetalen, sizeof (gint32)); + g_variant_unref (child); + + if (xlen != ylen || xlen != thetalen) + goto invalid_format; + + if (xlen > G_N_ELEMENTS (xyt->xcol)) + goto invalid_format; + + xyt->nrows = xlen; + memcpy (xyt->xcol, xcol, sizeof (xcol[0]) * xlen); + memcpy (xyt->ycol, ycol, sizeof (xcol[0]) * xlen); + memcpy (xyt->thetacol, thetacol, sizeof (xcol[0]) * xlen); + + g_ptr_array_add (result->prints, xyt); + } + } + else if (type == FP_PRINT_RAW) + { + g_autoptr(GVariant) fp_data = g_variant_get_child_value (print_data, 0); + + result = g_object_new (FP_TYPE_PRINT, + "fp-type", type, + "driver", driver, + "device-id", device_id, + "device-stored", device_stored, + "fp-data", fp_data, + NULL); + } + else + { + g_warning ("Invalid print type: 0x%X", type); + goto invalid_format; + } + + date = g_date_new_julian (julian_date); + g_object_set (result, + "finger", finger, + "username", username, + "description", description, + "enroll_date", date, + NULL); + + g_date_free (date); + + return g_steal_pointer (&result); + +invalid_format: + *error = g_error_new_literal (G_IO_ERROR, + G_IO_ERROR_INVALID_DATA, + "Data could not be parsed"); + return FALSE; +} diff --git a/libfprint/fp-print.h b/libfprint/fp-print.h new file mode 100644 index 00000000..fcb9532e --- /dev/null +++ b/libfprint/fp-print.h @@ -0,0 +1,101 @@ +/* + * FPrint Print handling + * Copyright (C) 2007 Daniel Drake + * Copyright (C) 2019 Benjamin Berg + * + * 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 "fp-image.h" +#include "fp-enums.h" + +G_BEGIN_DECLS + +#define FP_TYPE_PRINT (fp_print_get_type ()) +G_DECLARE_FINAL_TYPE (FpPrint, fp_print, FP, PRINT, GInitiallyUnowned) + +#include "fp-device.h" + +/** + * FpFinger: + * @FP_FINGER_UNKNOWN: The finger is unknown + * @FP_FINGER_LEFT_THUMB: Left thumb + * @FP_FINGER_LEFT_INDEX: Left index finger + * @FP_FINGER_LEFT_MIDDLE: Left middle finger + * @FP_FINGER_LEFT_RING: Left ring finger + * @FP_FINGER_LEFT_LITTLE: Left little finger + * @FP_FINGER_RIGHT_THUMB: Right thumb + * @FP_FINGER_RIGHT_INDEX: Right index finger + * @FP_FINGER_RIGHT_MIDDLE: Right middle finger + * @FP_FINGER_RIGHT_RING: Right ring finger + * @FP_FINGER_RIGHT_LITTLE: Right little finger + */ +typedef enum { + FP_FINGER_UNKNOWN = 0, + FP_FINGER_LEFT_THUMB, + FP_FINGER_LEFT_INDEX, + FP_FINGER_LEFT_MIDDLE, + FP_FINGER_LEFT_RING, + FP_FINGER_LEFT_LITTLE, + FP_FINGER_RIGHT_THUMB, + FP_FINGER_RIGHT_INDEX, + FP_FINGER_RIGHT_MIDDLE, + FP_FINGER_RIGHT_RING, + FP_FINGER_RIGHT_LITTLE, +} FpFinger; + +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); + +FpFinger fp_print_get_finger (FpPrint *print); +const gchar *fp_print_get_username (FpPrint *print); +const gchar *fp_print_get_description (FpPrint *print); +const GDate *fp_print_get_enroll_date (FpPrint *print); +gboolean fp_print_get_device_stored (FpPrint *print); + +void fp_print_set_finger (FpPrint *print, + FpFinger finger); +void fp_print_set_username (FpPrint *print, + const gchar *username); +void fp_print_set_description (FpPrint *print, + const gchar *description); +void fp_print_set_enroll_date (FpPrint *print, + const GDate *enroll_date); + +gboolean fp_print_compatible (FpPrint *self, + FpDevice *device); +gboolean fp_print_equal (FpPrint *self, + FpPrint *other); + +gboolean fp_print_serialize (FpPrint *print, + guchar **data, + gsize *length, + GError **error); + +FpPrint *fp_print_deserialize (const guchar *data, + gsize length, + GError **error); + +G_END_DECLS diff --git a/libfprint/fp_internal.h b/libfprint/fp_internal.h index 5c89e184..81470893 100644 --- a/libfprint/fp_internal.h +++ b/libfprint/fp_internal.h @@ -20,222 +20,35 @@ #ifndef __FPRINT_INTERNAL_H__ #define __FPRINT_INTERNAL_H__ -#include - -#include -#include -#include -#include - -#include "nbis-helpers.h" -#include "fprint.h" -#include "fpi-dev.h" -#include "fpi-core.h" #include "fpi-log.h" -#include "fpi-dev-img.h" -#include "fpi-data.h" -#include "fpi-img.h" -#include "drivers/driver_ids.h" - -/* Global variables */ -extern libusb_context *fpi_usb_ctx; -extern GSList *opened_devices; - -/* fp_print_data structure definition */ -enum fp_print_data_type { - PRINT_DATA_RAW = 0, /* memset-imposed default */ - PRINT_DATA_NBIS_MINUTIAE -}; - -struct fp_print_data { - uint16_t driver_id; - uint32_t devtype; - enum fp_print_data_type type; - GSList *prints; -}; - -/* fp_dev structure definition */ -enum fp_dev_state { - DEV_STATE_INITIAL = 0, - DEV_STATE_ERROR, - DEV_STATE_INITIALIZING, - DEV_STATE_INITIALIZED, - DEV_STATE_DEINITIALIZING, - DEV_STATE_DEINITIALIZED, - DEV_STATE_ENROLL_STARTING, - DEV_STATE_ENROLLING, - DEV_STATE_ENROLL_STOPPING, - DEV_STATE_VERIFY_STARTING, - DEV_STATE_VERIFYING, - DEV_STATE_VERIFY_DONE, - DEV_STATE_VERIFY_STOPPING, - DEV_STATE_IDENTIFY_STARTING, - DEV_STATE_IDENTIFYING, - DEV_STATE_IDENTIFY_DONE, - DEV_STATE_IDENTIFY_STOPPING, - DEV_STATE_CAPTURE_STARTING, - DEV_STATE_CAPTURING, - DEV_STATE_CAPTURE_DONE, - DEV_STATE_CAPTURE_STOPPING, -}; - -struct fp_dev { - struct fp_driver *drv; - uint32_t devtype; - - /* only valid if drv->type == DRIVER_IMAGING */ - struct fp_img_dev *img_dev; - /* Link to the instance specific struct */ - void *instance_data; - - int nr_enroll_stages; - - /* FIXME: This will eventually have a bus type */ - libusb_device_handle *udev; - - /* read-only to drivers */ - struct fp_print_data *verify_data; - - /* drivers should not mess with any of the below */ - enum fp_dev_state state; - int __enroll_stage; - int unconditional_capture; - - /* async I/O callbacks and data */ - /* FIXME: convert this to generic state operational data mechanism? */ - fp_dev_open_cb open_cb; - void *open_cb_data; - fp_operation_stop_cb close_cb; - void *close_cb_data; - fp_enroll_stage_cb enroll_stage_cb; - void *enroll_stage_cb_data; - fp_operation_stop_cb enroll_stop_cb; - void *enroll_stop_cb_data; - fp_img_operation_cb verify_cb; - void *verify_cb_data; - fp_operation_stop_cb verify_stop_cb; - void *verify_stop_cb_data; - fp_identify_cb identify_cb; - void *identify_cb_data; - fp_operation_stop_cb identify_stop_cb; - void *identify_stop_cb_data; - fp_img_operation_cb capture_cb; - void *capture_cb_data; - fp_operation_stop_cb capture_stop_cb; - void *capture_stop_cb_data; - - /* FIXME: better place to put this? */ - struct fp_print_data **identify_gallery; -}; - -/* fp_img_dev structure definition */ -struct fp_img_dev { - struct fp_dev *parent; - - enum fp_imgdev_action action; - int action_state; - - struct fp_print_data *acquire_data; - struct fp_print_data *enroll_data; - struct fp_img *acquire_img; - int enroll_stage; - int action_result; - - /* FIXME: better place to put this? */ - size_t identify_match_offset; -}; - -/* fp_driver structure definition */ - -/* fp_img_driver structure definition */ -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) -#define fpi_driver_to_img_driver(drv) \ - container_of((drv), struct fp_img_driver, driver) - -/* fp_dscv_dev structure definition */ -struct fp_dscv_dev { - struct libusb_device *udev; - struct fp_driver *drv; - unsigned long driver_data; - uint32_t devtype; -}; - -/* fp_dscv_print structure definition */ -struct fp_dscv_print { - uint16_t driver_id; - uint32_t devtype; - enum fp_finger finger; - char *path; -}; +#include "nbis-helpers.h" +#include "fpi-image.h" +#include "fpi-image-device.h" /* fp_minutia structure definition */ -struct fp_minutia { - int x; - int y; - int ex; - int ey; - int direction; - double reliability; - int type; - int appearing; - int feature_id; - int *nbrs; - int *ridge_counts; - int num_nbrs; +struct fp_minutia +{ + int x; + int y; + int ex; + int ey; + int direction; + double reliability; + int type; + int appearing; + int feature_id; + int *nbrs; + int *ridge_counts; + int num_nbrs; }; /* fp_minutiae structure definition */ -struct fp_minutiae { - int alloc; - int num; - struct fp_minutia **list; +struct fp_minutiae +{ + int alloc; + int num; + struct fp_minutia **list; }; -/* Defined in fpi-dev-img.c */ -void fpi_img_driver_setup(struct fp_img_driver *idriver); -int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev); -int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev); - -/* Exported for use in command-line tools - * Defined in fpi-core.c */ -struct fp_driver **fprint_get_drivers (void); - -/* Defined in fpi-core.c */ -enum fp_print_data_type fpi_driver_get_data_type(struct fp_driver *drv); - -/* Defined in fpi-data.c */ -void fpi_data_exit(void); -gboolean fpi_print_data_compatible(uint16_t driver_id1, uint32_t devtype1, - enum fp_print_data_type type1, uint16_t driver_id2, uint32_t devtype2, - enum fp_print_data_type type2); - -/* Defined in fpi-img.c */ -gboolean fpi_img_is_sane(struct fp_img *img); -int fpi_img_to_print_data(struct fp_img_dev *imgdev, struct fp_img *img, - struct fp_print_data **ret); -int fpi_img_compare_print_data(struct fp_print_data *enrolled_print, - struct fp_print_data *new_print); -int fpi_img_compare_print_data_to_gallery(struct fp_print_data *print, - struct fp_print_data **gallery, int match_threshold, size_t *match_offset); - -/* Defined in fpi-poll.c */ -void fpi_timeout_cancel_all_for_dev(struct fp_dev *dev); -void fpi_poll_init(void); -void fpi_poll_exit(void); - -/* Defined in fpi-async.c */ -void fpi_drvcb_capture_started(struct fp_dev *dev, int status); -void fpi_drvcb_report_capture_result(struct fp_dev *dev, int result, - struct fp_img *img); -void fpi_drvcb_capture_stopped(struct fp_dev *dev); - -void fpi_drvcb_identify_started(struct fp_dev *dev, int status); -void fpi_drvcb_report_identify_result(struct fp_dev *dev, int result, - size_t match_offset, struct fp_img *img); -void fpi_drvcb_identify_stopped(struct fp_dev *dev); - -#include "drivers_definitions.h" #endif diff --git a/libfprint/fpi-assembling.c b/libfprint/fpi-assembling.c index 65fad4d7..75291c09 100644 --- a/libfprint/fpi-assembling.c +++ b/libfprint/fpi-assembling.c @@ -23,12 +23,8 @@ #include "fp_internal.h" -#include #include -#include -#include - #include "fpi-assembling.h" /** @@ -42,132 +38,141 @@ * data in small stripes. */ -static unsigned int calc_error(struct fpi_frame_asmbl_ctx *ctx, - struct fpi_frame *first_frame, - struct fpi_frame *second_frame, - int dx, - int dy) +static unsigned int +calc_error (struct fpi_frame_asmbl_ctx *ctx, + struct fpi_frame *first_frame, + struct fpi_frame *second_frame, + int dx, + int dy) { - unsigned int width, height; - unsigned int x1, y1, x2, y2, err, i, j; + unsigned int width, height; + unsigned int x1, y1, x2, y2, err, i, j; - width = ctx->frame_width - (dx > 0 ? dx : -dx); - height = ctx->frame_height - dy; + width = ctx->frame_width - (dx > 0 ? dx : -dx); + height = ctx->frame_height - dy; - y1 = 0; - y2 = dy; - i = 0; - err = 0; - do { - x1 = dx < 0 ? 0 : dx; - x2 = dx < 0 ? -dx : 0; - j = 0; + y1 = 0; + y2 = dy; + i = 0; + err = 0; + do + { + x1 = dx < 0 ? 0 : dx; + x2 = dx < 0 ? -dx : 0; + j = 0; - do { - unsigned char v1, v2; + do + { + unsigned char v1, v2; - v1 = ctx->get_pixel(ctx, first_frame, x1, y1); - v2 = ctx->get_pixel(ctx, second_frame, x2, y2); - err += v1 > v2 ? v1 - v2 : v2 - v1; - j++; - x1++; - x2++; + v1 = ctx->get_pixel (ctx, first_frame, x1, y1); + v2 = ctx->get_pixel (ctx, second_frame, x2, y2); + err += v1 > v2 ? v1 - v2 : v2 - v1; + j++; + x1++; + x2++; - } while (j < width); - i++; - y1++; - y2++; - } while (i < height); + } + while (j < width); + i++; + y1++; + y2++; + } + while (i < height); - /* Normalize error */ - err *= (ctx->frame_height * ctx->frame_width); - err /= (height * width); + /* Normalize error */ + err *= (ctx->frame_height * ctx->frame_width); + err /= (height * width); - if (err == 0) - return INT_MAX; + if (err == 0) + return INT_MAX; - return err; + return err; } /* This function is rather CPU-intensive. It's better to use hardware * to detect movement direction when possible. */ -static void find_overlap(struct fpi_frame_asmbl_ctx *ctx, - struct fpi_frame *first_frame, - struct fpi_frame *second_frame, - unsigned int *min_error) +static void +find_overlap (struct fpi_frame_asmbl_ctx *ctx, + struct fpi_frame *first_frame, + struct fpi_frame *second_frame, + unsigned int *min_error) { - int dx, dy; - unsigned int err; - *min_error = 255 * ctx->frame_height * ctx->frame_width; + int dx, dy; + unsigned int err; - /* Seeking in horizontal and vertical dimensions, - * for horizontal dimension we'll check only 8 pixels - * in both directions. For vertical direction diff is - * rarely less than 2, so start with it. - */ - for (dy = 2; dy < ctx->frame_height; dy++) { - for (dx = -8; dx < 8; dx++) { - err = calc_error(ctx, first_frame, second_frame, - dx, dy); - if (err < *min_error) { - *min_error = err; - second_frame->delta_x = -dx; - second_frame->delta_y = dy; - } - } - } + *min_error = 255 * ctx->frame_height * ctx->frame_width; + + /* Seeking in horizontal and vertical dimensions, + * for horizontal dimension we'll check only 8 pixels + * in both directions. For vertical direction diff is + * rarely less than 2, so start with it. + */ + for (dy = 2; dy < ctx->frame_height; dy++) + { + for (dx = -8; dx < 8; dx++) + { + err = calc_error (ctx, first_frame, second_frame, + dx, dy); + if (err < *min_error) + { + *min_error = err; + second_frame->delta_x = -dx; + second_frame->delta_y = dy; + } + } + } } -static unsigned int do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx, - GSList *stripes, size_t num_stripes, - gboolean reverse) +static unsigned int +do_movement_estimation (struct fpi_frame_asmbl_ctx *ctx, + GSList *stripes, gboolean reverse) { - GSList *list_entry = stripes; - GTimer *timer; - int frame = 1; - struct fpi_frame *prev_stripe = list_entry->data; - unsigned int min_error; - /* Max error is width * height * 255, for AES2501 which has the largest - * sensor its 192*16*255 = 783360. So for 32bit value it's ~5482 frame before - * we might get int overflow. Use 64bit value here to prevent integer overflow - */ - unsigned long long total_error = 0; + GSList *l; + GTimer *timer; + guint num_frames = 0; + struct fpi_frame *prev_stripe; + unsigned int min_error; + /* Max error is width * height * 255, for AES2501 which has the largest + * sensor its 192*16*255 = 783360. So for 32bit value it's ~5482 frame before + * we might get int overflow. Use 64bit value here to prevent integer overflow + */ + unsigned long long total_error = 0; - list_entry = g_slist_next(list_entry); + timer = g_timer_new (); + prev_stripe = stripes->data; + for (l = stripes; l != NULL; l = l->next, num_frames++) + { + struct fpi_frame *cur_stripe = l->data; - timer = g_timer_new(); - do { - struct fpi_frame *cur_stripe = list_entry->data; + if (reverse) + { + find_overlap (ctx, prev_stripe, cur_stripe, &min_error); + cur_stripe->delta_y = -cur_stripe->delta_y; + cur_stripe->delta_x = -cur_stripe->delta_x; + } + else + { + find_overlap (ctx, cur_stripe, prev_stripe, &min_error); + } + total_error += min_error; - if (reverse) { - find_overlap(ctx, prev_stripe, cur_stripe, &min_error); - cur_stripe->delta_y = -cur_stripe->delta_y; - cur_stripe->delta_x = -cur_stripe->delta_x; - } - else - find_overlap(ctx, cur_stripe, prev_stripe, &min_error); - total_error += min_error; + prev_stripe = cur_stripe; + } - frame++; - prev_stripe = cur_stripe; - list_entry = g_slist_next(list_entry); + g_timer_stop (timer); + fp_dbg ("calc delta completed in %f secs", g_timer_elapsed (timer, NULL)); + g_timer_destroy (timer); - } while (frame < num_stripes); - - g_timer_stop(timer); - fp_dbg("calc delta completed in %f secs", g_timer_elapsed(timer, NULL)); - g_timer_destroy(timer); - - return total_error / num_stripes; + return total_error / num_frames; } /** * fpi_do_movement_estimation: * @ctx: #fpi_frame_asmbl_ctx - frame assembling context * @stripes: a singly-linked list of #fpi_frame - * @num_stripes: number of items in @stripes to process * * fpi_do_movement_estimation() estimates the movement between adjacent * frames, populating @delta_x and @delta_y values for each #fpi_frame. @@ -175,221 +180,227 @@ static unsigned int do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx, * This function is used for devices that don't do movement estimation * in hardware. If hardware movement estimation is supported, the driver * should populate @delta_x and @delta_y instead. - * - * Note that @num_stripes might be shorter than the length of the list, - * if some stripes should be skipped. */ -void fpi_do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx, - GSList *stripes, size_t num_stripes) +void +fpi_do_movement_estimation (struct fpi_frame_asmbl_ctx *ctx, + GSList *stripes) { - int err, rev_err; - err = do_movement_estimation(ctx, stripes, num_stripes, FALSE); - rev_err = do_movement_estimation(ctx, stripes, num_stripes, TRUE); - fp_dbg("errors: %d rev: %d", err, rev_err); - if (err < rev_err) { - do_movement_estimation(ctx, stripes, num_stripes, FALSE); - } + int err, rev_err; + + err = do_movement_estimation (ctx, stripes, FALSE); + rev_err = do_movement_estimation (ctx, stripes, TRUE); + fp_dbg ("errors: %d rev: %d", err, rev_err); + if (err < rev_err) + do_movement_estimation (ctx, stripes, FALSE); } -static inline void aes_blit_stripe(struct fpi_frame_asmbl_ctx *ctx, - struct fp_img *img, - struct fpi_frame *stripe, - int x, int y) +static inline void +aes_blit_stripe (struct fpi_frame_asmbl_ctx *ctx, + FpImage *img, + struct fpi_frame *stripe, + int x, int y) { - unsigned int ix, iy; - unsigned int fx, fy; - unsigned int width, height; + unsigned int ix, iy; + unsigned int fx, fy; + unsigned int width, height; - /* Find intersection */ - if (x < 0) { - width = ctx->frame_width + x; - ix = 0; - fx = -x; - } else { - ix = x; - fx = 0; - width = ctx->frame_width; - } - if ((ix + width) > img->width) - width = img->width - ix; + /* Find intersection */ + if (x < 0) + { + width = ctx->frame_width + x; + ix = 0; + fx = -x; + } + else + { + ix = x; + fx = 0; + width = ctx->frame_width; + } + if ((ix + width) > img->width) + width = img->width - ix; - if (y < 0) { - iy = 0; - fy = -y; - height = ctx->frame_height + y; - } else { - iy = y; - fy = 0; - height = ctx->frame_height; - } + if (y < 0) + { + iy = 0; + fy = -y; + height = ctx->frame_height + y; + } + else + { + iy = y; + fy = 0; + height = ctx->frame_height; + } - if (fx > ctx->frame_width) - return; + if (fx > ctx->frame_width) + return; - if (fy > ctx->frame_height) - return; + if (fy > ctx->frame_height) + return; - if (ix > img->width) - return; + if (ix > img->width) + return; - if (iy > img->height) - return; + if (iy > img->height) + return; - if ((iy + height) > img->height) - height = img->height - iy; + if ((iy + height) > img->height) + height = img->height - iy; - for (; fy < height; fy++, iy++) { - if (x < 0) { - ix = 0; - fx = -x; - } else { - ix = x; - fx = 0; - } - for (; fx < width; fx++, ix++) { - img->data[ix + (iy * img->width)] = ctx->get_pixel(ctx, stripe, fx, fy); - } - } + for (; fy < height; fy++, iy++) + { + if (x < 0) + { + ix = 0; + fx = -x; + } + else + { + ix = x; + fx = 0; + } + for (; fx < width; fx++, ix++) + img->data[ix + (iy * img->width)] = ctx->get_pixel (ctx, stripe, fx, fy); + } } /** * fpi_assemble_frames: * @ctx: #fpi_frame_asmbl_ctx - frame assembling context * @stripes: linked list of #fpi_frame - * @num_stripes: number of items in @stripes to process * * fpi_assemble_frames() assembles individual frames into a single image. * It expects @delta_x and @delta_y of #fpi_frame to be populated. * - * Note that @num_stripes might be shorter than the length of the list, - * if some stripes should be skipped. - * * Returns: a newly allocated #fp_img. */ -struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx, - GSList *stripes, size_t num_stripes) +FpImage * +fpi_assemble_frames (struct fpi_frame_asmbl_ctx *ctx, + GSList *stripes) { - GSList *stripe; - struct fp_img *img; - int height = 0; - int i, y, x; - gboolean reverse = FALSE; - struct fpi_frame *fpi_frame; + GSList *l; + FpImage *img; + int height = 0; + int y, x; + gboolean reverse = FALSE; + struct fpi_frame *fpi_frame; - //FIXME g_return_if_fail - BUG_ON(num_stripes == 0); - BUG_ON(ctx->image_width < ctx->frame_width); + //FIXME g_return_if_fail + g_return_val_if_fail (stripes != NULL, NULL); + BUG_ON (ctx->image_width < ctx->frame_width); - /* Calculate height */ - i = 0; - stripe = stripes; + /* No offset for 1st image */ + fpi_frame = stripes->data; + fpi_frame->delta_x = 0; + fpi_frame->delta_y = 0; + for (l = stripes; l != NULL; l = l->next) + { + fpi_frame = l->data; - /* No offset for 1st image */ - fpi_frame = stripe->data; - fpi_frame->delta_x = 0; - fpi_frame->delta_y = 0; - do { - fpi_frame = stripe->data; + height += fpi_frame->delta_y; + } - height += fpi_frame->delta_y; - i++; - stripe = g_slist_next(stripe); - } while (i < num_stripes); + fp_dbg ("height is %d", height); - fp_dbg("height is %d", height); + if (height < 0) + { + reverse = TRUE; + height = -height; + } - if (height < 0) { - reverse = TRUE; - height = -height; - } + /* For last frame */ + height += ctx->frame_height; - /* For last frame */ - height += ctx->frame_height; + /* Create buffer big enough for max image */ + img = fp_image_new (ctx->image_width, height); + img->flags = FPI_IMAGE_COLORS_INVERTED; + img->flags |= reverse ? 0 : FPI_IMAGE_H_FLIPPED | FPI_IMAGE_V_FLIPPED; + img->width = ctx->image_width; + img->height = height; - /* Create buffer big enough for max image */ - img = fpi_img_new(ctx->image_width * height); - img->flags = FP_IMG_COLORS_INVERTED; - img->flags |= reverse ? 0 : FP_IMG_H_FLIPPED | FP_IMG_V_FLIPPED; - img->width = ctx->image_width; - img->height = height; + /* Assemble stripes */ + y = reverse ? (height - ctx->frame_height) : 0; + x = (ctx->image_width - ctx->frame_width) / 2; - /* Assemble stripes */ - i = 0; - stripe = stripes; - y = reverse ? (height - ctx->frame_height) : 0; - x = (ctx->image_width - ctx->frame_width) / 2; + for (l = stripes; l != NULL; l = l->next) + { + fpi_frame = l->data; - do { - fpi_frame = stripe->data; + if(reverse) + { + y += fpi_frame->delta_y; + x += fpi_frame->delta_x; + } - if(reverse) { - y += fpi_frame->delta_y; - x += fpi_frame->delta_x; - } + aes_blit_stripe (ctx, img, fpi_frame, x, y); - aes_blit_stripe(ctx, img, fpi_frame, x, y); + if(!reverse) + { + y += fpi_frame->delta_y; + x += fpi_frame->delta_x; + } + } - if(!reverse) { - y += fpi_frame->delta_y; - x += fpi_frame->delta_x; - } - - stripe = g_slist_next(stripe); - i++; - } while (i < num_stripes); - - return img; + return img; } -static int cmpint(const void *p1, const void *p2, gpointer data) +static int +cmpint (const void *p1, const void *p2, gpointer data) { - int a = *((int *)p1); - int b = *((int *)p2); - if (a < b) - return -1; - else if (a == b) - return 0; - else - return 1; + int a = *((int *) p1); + int b = *((int *) p2); + + if (a < b) + return -1; + else if (a == b) + return 0; + else + return 1; } -static void median_filter(int *data, int size, int filtersize) +static void +median_filter (int *data, int size, int filtersize) { - int i; - int *result = (int *)g_malloc0(size*sizeof(int)); - int *sortbuf = (int *)g_malloc0(filtersize*sizeof(int)); - for (i = 0; i < size; i++) { - int i1 = i - (filtersize-1)/2; - int i2 = i + (filtersize-1)/2; - if (i1 < 0) - i1 = 0; - if (i2 >= size) - i2 = size-1; - memmove(sortbuf, data+i1, (i2-i1+1)*sizeof(int)); - g_qsort_with_data(sortbuf, i2-i1+1, sizeof(int), cmpint, NULL); - result[i] = sortbuf[(i2-i1+1)/2]; - } - memmove(data, result, size*sizeof(int)); - g_free(result); - g_free(sortbuf); + int i; + int *result = (int *) g_malloc0 (size * sizeof (int)); + int *sortbuf = (int *) g_malloc0 (filtersize * sizeof (int)); + + for (i = 0; i < size; i++) + { + int i1 = i - (filtersize - 1) / 2; + int i2 = i + (filtersize - 1) / 2; + if (i1 < 0) + i1 = 0; + if (i2 >= size) + i2 = size - 1; + memmove (sortbuf, data + i1, (i2 - i1 + 1) * sizeof (int)); + g_qsort_with_data (sortbuf, i2 - i1 + 1, sizeof (int), cmpint, NULL); + result[i] = sortbuf[(i2 - i1 + 1) / 2]; + } + memmove (data, result, size * sizeof (int)); + g_free (result); + g_free (sortbuf); } -static void interpolate_lines(struct fpi_line_asmbl_ctx *ctx, - GSList *line1, float y1, GSList *line2, - float y2, unsigned char *output, float yi, int size) +static void +interpolate_lines (struct fpi_line_asmbl_ctx *ctx, + GSList *line1, float y1, GSList *line2, + float y2, unsigned char *output, float yi, int size) { - int i; - unsigned char p1, p2; + int i; + unsigned char p1, p2; - if (!line1 || !line2) - return; + if (!line1 || !line2) + return; - for (i = 0; i < size; i++) { - p1 = ctx->get_pixel(ctx, line1, i); - p2 = ctx->get_pixel(ctx, line2, i); - output[i] = (float)p1 - + (yi - y1)/(y2 - y1)*(p2 - p1); - } + for (i = 0; i < size; i++) + { + p1 = ctx->get_pixel (ctx, line1, i); + p2 = ctx->get_pixel (ctx, line2, i); + output[i] = (float) p1 + + (yi - y1) / (y2 - y1) * (p2 - p1); + } } /** @@ -406,82 +417,89 @@ static void interpolate_lines(struct fpi_line_asmbl_ctx *ctx, * * Returns: a newly allocated #fp_img. */ -struct fp_img *fpi_assemble_lines(struct fpi_line_asmbl_ctx *ctx, - GSList *lines, size_t num_lines) +FpImage * +fpi_assemble_lines (struct fpi_line_asmbl_ctx *ctx, + GSList *lines, size_t num_lines) { - /* Number of output lines per distance between two scanners */ - int i; - GSList *row1, *row2; - float y = 0.0; - int line_ind = 0; - int *offsets = (int *)g_malloc0((num_lines / 2) * sizeof(int)); - unsigned char *output = g_malloc0(ctx->line_width * ctx->max_height); - struct fp_img *img; + /* Number of output lines per distance between two scanners */ + int i; + GSList *row1, *row2; + float y = 0.0; + int line_ind = 0; + int *offsets = g_new0 (int, num_lines / 2); + unsigned char *output = g_malloc0 (ctx->line_width * ctx->max_height); + FpImage *img; - g_return_val_if_fail (lines != NULL, NULL); - g_return_val_if_fail (num_lines >= 2, NULL); + g_return_val_if_fail (lines != NULL, NULL); + g_return_val_if_fail (num_lines >= 2, NULL); - fp_dbg("%"G_GINT64_FORMAT, g_get_real_time()); + fp_dbg ("%"G_GINT64_FORMAT, g_get_real_time ()); - row1 = lines; - for (i = 0; (i < num_lines - 1) && row1; i += 2) { - int bestmatch = i; - int bestdiff = 0; - int j, firstrow, lastrow; + row1 = lines; + for (i = 0; (i < num_lines - 1) && row1; i += 2) + { + int bestmatch = i; + int bestdiff = 0; + int j, firstrow, lastrow; - firstrow = i + 1; - lastrow = MIN(i + ctx->max_search_offset, num_lines - 1); + firstrow = i + 1; + lastrow = MIN (i + ctx->max_search_offset, num_lines - 1); - row2 = g_slist_next(row1); - for (j = firstrow; j <= lastrow; j++) { - int diff = ctx->get_deviation(ctx, - row1, - row2); - if ((j == firstrow) || (diff < bestdiff)) { - bestdiff = diff; - bestmatch = j; - } - row2 = g_slist_next(row2); - } - offsets[i / 2] = bestmatch - i; - fp_dbg("%d", offsets[i / 2]); - row1 = g_slist_next(row1); - if (row1) - row1 = g_slist_next(row1); - } + row2 = g_slist_next (row1); + for (j = firstrow; j <= lastrow; j++) + { + int diff = ctx->get_deviation (ctx, + row1, + row2); + if ((j == firstrow) || (diff < bestdiff)) + { + bestdiff = diff; + bestmatch = j; + } + row2 = g_slist_next (row2); + } + offsets[i / 2] = bestmatch - i; + fp_dbg ("%d", offsets[i / 2]); + row1 = g_slist_next (row1); + if (row1) + row1 = g_slist_next (row1); + } - median_filter(offsets, (num_lines / 2) - 1, ctx->median_filter_size); + median_filter (offsets, (num_lines / 2) - 1, ctx->median_filter_size); - fp_dbg("offsets_filtered: %"G_GINT64_FORMAT, g_get_real_time()); - for (i = 0; i <= (num_lines / 2) - 1; i++) - fp_dbg("%d", offsets[i]); - row1 = lines; - for (i = 0; i < num_lines - 1; i++, row1 = g_slist_next(row1)) { - int offset = offsets[i/2]; - if (offset > 0) { - float ynext = y + (float)ctx->resolution / offset; - while (line_ind < ynext) { - if (line_ind > ctx->max_height - 1) - goto out; - interpolate_lines(ctx, - row1, y, - g_slist_next(row1), - ynext, - output + line_ind * ctx->line_width, - line_ind, - ctx->line_width); - line_ind++; - } - y = ynext; - } - } + fp_dbg ("offsets_filtered: %"G_GINT64_FORMAT, g_get_real_time ()); + for (i = 0; i <= (num_lines / 2) - 1; i++) + fp_dbg ("%d", offsets[i]); + row1 = lines; + for (i = 0; i < num_lines - 1; i++, row1 = g_slist_next (row1)) + { + int offset = offsets[i / 2]; + if (offset > 0) + { + float ynext = y + (float) ctx->resolution / offset; + while (line_ind < ynext) + { + if (line_ind > ctx->max_height - 1) + goto out; + interpolate_lines (ctx, + row1, y, + g_slist_next (row1), + ynext, + output + line_ind * ctx->line_width, + line_ind, + ctx->line_width); + line_ind++; + } + y = ynext; + } + } out: - img = fpi_img_new(ctx->line_width * line_ind); - img->height = line_ind; - img->width = ctx->line_width; - img->flags = FP_IMG_V_FLIPPED; - memmove(img->data, output, ctx->line_width * line_ind); - g_free(offsets); - g_free(output); - return img; + img = fp_image_new (ctx->line_width, line_ind); + img->height = line_ind; + img->width = ctx->line_width; + img->flags = FPI_IMAGE_V_FLIPPED; + memmove (img->data, output, ctx->line_width * line_ind); + g_free (offsets); + g_free (output); + return img; } diff --git a/libfprint/fpi-assembling.h b/libfprint/fpi-assembling.h index d2a66515..77e3c558 100644 --- a/libfprint/fpi-assembling.h +++ b/libfprint/fpi-assembling.h @@ -32,10 +32,11 @@ * populate delta_x and delta_y if the device supports hardware movement * estimation. */ -struct fpi_frame { - int delta_x; - int delta_y; - unsigned char data[0]; +struct fpi_frame +{ + int delta_x; + int delta_y; + unsigned char data[0]; }; /** @@ -52,21 +53,22 @@ struct fpi_frame { * hardware parameters of scanner. @image_width is usually 25% wider than * @frame_width to take horizontal movement into account. */ -struct fpi_frame_asmbl_ctx { - unsigned int frame_width; - unsigned int frame_height; - unsigned int image_width; - unsigned char (*get_pixel)(struct fpi_frame_asmbl_ctx *ctx, - struct fpi_frame *frame, - unsigned int x, - unsigned int y); +struct fpi_frame_asmbl_ctx +{ + unsigned int frame_width; + unsigned int frame_height; + unsigned int image_width; + unsigned char (*get_pixel)(struct fpi_frame_asmbl_ctx *ctx, + struct fpi_frame *frame, + unsigned int x, + unsigned int y); }; -void fpi_do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx, - GSList *stripes, size_t num_stripes); +void fpi_do_movement_estimation (struct fpi_frame_asmbl_ctx *ctx, + GSList *stripes); -struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx, - GSList *stripes, size_t num_stripes); +FpImage *fpi_assemble_frames (struct fpi_frame_asmbl_ctx *ctx, + GSList *stripes); /** * fpi_line_asmbl_ctx: @@ -96,20 +98,23 @@ struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx, * returns two lines at a time, this function should be used to estimate the * difference between pairs of lines. */ -struct fpi_line_asmbl_ctx { - unsigned int line_width; - unsigned int max_height; - unsigned int resolution; - unsigned int median_filter_size; - unsigned int max_search_offset; - int (*get_deviation)(struct fpi_line_asmbl_ctx *ctx, - GSList *line1, GSList *line2); - unsigned char (*get_pixel)(struct fpi_line_asmbl_ctx *ctx, - GSList *line, - unsigned int x); +struct fpi_line_asmbl_ctx +{ + unsigned int line_width; + unsigned int max_height; + unsigned int resolution; + unsigned int median_filter_size; + unsigned int max_search_offset; + int (*get_deviation)(struct fpi_line_asmbl_ctx *ctx, + GSList *line1, + GSList *line2); + unsigned char (*get_pixel)(struct fpi_line_asmbl_ctx *ctx, + GSList *line, + unsigned int x); }; -struct fp_img *fpi_assemble_lines(struct fpi_line_asmbl_ctx *ctx, - GSList *lines, size_t num_lines); +FpImage *fpi_assemble_lines (struct fpi_line_asmbl_ctx *ctx, + GSList *lines, + size_t num_lines); #endif diff --git a/libfprint/fpi-async.c b/libfprint/fpi-async.c deleted file mode 100644 index 6339c9ca..00000000 --- a/libfprint/fpi-async.c +++ /dev/null @@ -1,706 +0,0 @@ -/* - * Asynchronous I/O functionality - * Copyright (C) 2008 Daniel Drake - * - * 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 "async" - -#include "fp_internal.h" -#include "fpi-async.h" - -#include -#include -#include - -/* - * SECTION:fpi-async - * @title: Asynchronous operations reporting - * @short_description: Asynchronous operations reporting functions - * - * Those functions are used by primitive drivers to report back their - * current status. Most drivers, imaging ones, do not need to use them. - */ - -/* Drivers call this when device initialisation has completed */ -void fpi_drvcb_open_complete(struct fp_dev *dev, int status) -{ - fp_dbg("status %d", status); - BUG_ON(dev->state != DEV_STATE_INITIALIZING); - dev->state = (status) ? DEV_STATE_ERROR : DEV_STATE_INITIALIZED; - opened_devices = g_slist_prepend(opened_devices, dev); - if (dev->open_cb) - dev->open_cb(dev, status, dev->open_cb_data); -} - -/** - * fp_async_dev_open: - * @ddev: the struct #fp_dscv_dev discovered device to open - * @callback: the callback to call when the device has been opened - * @user_data: user data to pass to the callback - * - * Opens and initialises a device. This is the function you call in order - * to convert a #fp_dscv_dev discovered device into an actual device handle - * that you can perform operations with. - * - * The error status of the opening will be provided as an argument to the - * #fp_dev_open_cb callback. - * - * Returns: 0 on success, non-zero on error - */ -API_EXPORTED int fp_async_dev_open(struct fp_dscv_dev *ddev, fp_dev_open_cb callback, - void *user_data) -{ - struct fp_driver *drv; - struct fp_dev *dev; - libusb_device_handle *udevh; - int r; - - g_return_val_if_fail(ddev != NULL, -ENODEV); - g_return_val_if_fail (callback != NULL, -EINVAL); - - drv = ddev->drv; - - G_DEBUG_HERE(); - r = libusb_open(ddev->udev, &udevh); - if (r < 0) { - fp_err("usb_open failed, error %d", r); - return r; - } - - dev = g_malloc0(sizeof(*dev)); - dev->drv = drv; - dev->udev = udevh; - dev->__enroll_stage = -1; - dev->state = DEV_STATE_INITIALIZING; - dev->open_cb = callback; - dev->open_cb_data = user_data; - - if (!drv->open) { - fpi_drvcb_open_complete(dev, 0); - return 0; - } - - dev->state = DEV_STATE_INITIALIZING; - r = drv->open(dev, ddev->driver_data); - if (r) { - fp_err("device initialisation failed, driver=%s", drv->name); - libusb_close(udevh); - g_free(dev); - } - - return r; -} - -/* Drivers call this when device deinitialisation has completed */ -void fpi_drvcb_close_complete(struct fp_dev *dev) -{ - G_DEBUG_HERE(); - BUG_ON(dev->state != DEV_STATE_DEINITIALIZING); - dev->state = DEV_STATE_DEINITIALIZED; - fpi_timeout_cancel_all_for_dev(dev); - libusb_close(dev->udev); - if (dev->close_cb) - dev->close_cb(dev, dev->close_cb_data); - g_free(dev); -} - -/** - * fp_async_dev_close: - * @dev: the struct #fp_dev device - * @callback: the callback to call when the device has been closed - * @user_data: user data to pass to the callback - * - * Closes a device. You must call this function when you have finished using - * a fingerprint device. - */ -API_EXPORTED void fp_async_dev_close(struct fp_dev *dev, - fp_operation_stop_cb callback, void *user_data) -{ - struct fp_driver *drv; - - g_return_if_fail (dev != NULL); - - drv = dev->drv; - - g_return_if_fail (drv->close != NULL); - - if (g_slist_index(opened_devices, (gconstpointer) dev) == -1) - fp_err("device %p not in opened list!", dev); - opened_devices = g_slist_remove(opened_devices, (gconstpointer) dev); - - dev->close_cb = callback; - dev->close_cb_data = user_data; - dev->state = DEV_STATE_DEINITIALIZING; - drv->close(dev); -} - -/* Drivers call this when enrollment has started */ -void fpi_drvcb_enroll_started(struct fp_dev *dev, int status) -{ - fp_dbg("status %d", status); - BUG_ON(dev->state != DEV_STATE_ENROLL_STARTING); - if (status) { - if (status > 0) { - status = -status; - fp_dbg("adjusted to %d", status); - } - dev->state = DEV_STATE_ERROR; - if (dev->enroll_stage_cb) - dev->enroll_stage_cb(dev, status, NULL, NULL, - dev->enroll_stage_cb_data); - } else { - dev->state = DEV_STATE_ENROLLING; - } -} - -/** - * fp_async_enroll_start: - * @dev: the struct #fp_dev device - * @callback: the callback to call for each stage of the enrollment - * @user_data: user data to pass to the callback - * - * Starts an enrollment and calls @callback for each enrollment stage. - * See [Enrolling](libfprint-Devices-operations.html#enrolling) - * for an explanation of enroll stages. - * - * Returns: 0 on success, non-zero on error - */ -API_EXPORTED int fp_async_enroll_start(struct fp_dev *dev, - fp_enroll_stage_cb callback, void *user_data) -{ - struct fp_driver *drv; - int r; - - g_return_val_if_fail(dev != NULL, -ENODEV); - g_return_val_if_fail (callback != NULL, -EINVAL); - - drv = dev->drv; - - if (!dev->nr_enroll_stages || !drv->enroll_start) { - fp_err("driver %s has 0 enroll stages or no enroll func", - drv->name); - return -ENOTSUP; - } - - fp_dbg("starting enrollment"); - dev->enroll_stage_cb = callback; - dev->enroll_stage_cb_data = user_data; - - dev->state = DEV_STATE_ENROLL_STARTING; - r = drv->enroll_start(dev); - if (r < 0) { - dev->enroll_stage_cb = NULL; - fp_err("failed to start enrollment"); - dev->state = DEV_STATE_ERROR; - } - - return r; -} - -/* Drivers call this when an enroll stage has completed */ -void fpi_drvcb_enroll_stage_completed(struct fp_dev *dev, int result, - struct fp_print_data *data, struct fp_img *img) -{ - BUG_ON(dev->state != DEV_STATE_ENROLLING); - fp_dbg("result %d", result); - if (!dev->enroll_stage_cb) { - fp_dbg("ignoring enroll result as no callback is subscribed"); - return; - } - if (result == FP_ENROLL_COMPLETE && !data) { - fp_err("BUG: complete but no data?"); - result = FP_ENROLL_FAIL; - } - dev->enroll_stage_cb(dev, result, data, img, dev->enroll_stage_cb_data); -} - -/* Drivers call this when enrollment has stopped */ -void fpi_drvcb_enroll_stopped(struct fp_dev *dev) -{ - G_DEBUG_HERE(); - BUG_ON(dev->state != DEV_STATE_ENROLL_STOPPING); - dev->state = DEV_STATE_INITIALIZED; - if (dev->enroll_stop_cb) - dev->enroll_stop_cb(dev, dev->enroll_stop_cb_data); -} - -/** - * fp_async_enroll_stop: - * @dev: the struct #fp_dev device - * @callback: the callback to call when the enrollment has been cancelled - * @user_data: user data to pass to the callback - * - * Stops an ongoing enrollment started with fp_async_enroll_start(). - * - * Returns: 0 on success, non-zero on error - */ -API_EXPORTED int fp_async_enroll_stop(struct fp_dev *dev, - fp_operation_stop_cb callback, void *user_data) -{ - struct fp_driver *drv; - int r; - - g_return_val_if_fail(dev != NULL, -ENODEV); - - drv = dev->drv; - - G_DEBUG_HERE(); - if (!drv->enroll_start) - return -ENOTSUP; - - dev->enroll_stage_cb = NULL; - dev->enroll_stop_cb = callback; - dev->enroll_stop_cb_data = user_data; - dev->state = DEV_STATE_ENROLL_STOPPING; - - if (!drv->enroll_stop) { - fpi_drvcb_enroll_stopped(dev); - return 0; - } - - r = drv->enroll_stop(dev); - if (r < 0) { - fp_err("failed to stop enrollment"); - dev->enroll_stop_cb = NULL; - } - - return r; -} - -/** - * fp_async_verify_start: - * @dev: the struct #fp_dev device - * @data: the print to verify against. Must have been previously - * enrolled with a device compatible to the device selected to perform the scan - * @callback: the callback to call when the verification has finished - * @user_data: user data to pass to the callback - * - * Starts a verification and calls @callback when the verification has - * finished. See fp_verify_finger_img() for the synchronous API. When the - * @callback has been called, you must call fp_async_verify_stop(). - * - * Returns: 0 on success, non-zero on error - */ -API_EXPORTED int fp_async_verify_start(struct fp_dev *dev, - struct fp_print_data *data, fp_img_operation_cb callback, void *user_data) -{ - struct fp_driver *drv; - int r; - - g_return_val_if_fail(dev != NULL, -ENODEV); - g_return_val_if_fail (callback != NULL, -EINVAL); - - drv = dev->drv; - - G_DEBUG_HERE(); - if (!drv->verify_start) - return -ENOTSUP; - - dev->state = DEV_STATE_VERIFY_STARTING; - dev->verify_cb = callback; - dev->verify_cb_data = user_data; - dev->verify_data = data; - - r = drv->verify_start(dev); - if (r < 0) { - dev->verify_cb = NULL; - dev->state = DEV_STATE_ERROR; - fp_err("failed to start verification, error %d", r); - } - return r; -} - -/* Drivers call this when verification has started */ -void fpi_drvcb_verify_started(struct fp_dev *dev, int status) -{ - G_DEBUG_HERE(); - BUG_ON(dev->state != DEV_STATE_VERIFY_STARTING); - if (status) { - if (status > 0) { - status = -status; - fp_dbg("adjusted to %d", status); - } - dev->state = DEV_STATE_ERROR; - if (dev->verify_cb) - dev->verify_cb(dev, status, NULL, dev->verify_cb_data); - } else { - dev->state = DEV_STATE_VERIFYING; - } -} - -/* Drivers call this to report a verify result (which might mark completion) */ -void fpi_drvcb_report_verify_result(struct fp_dev *dev, int result, - struct fp_img *img) -{ - fp_dbg("result %d", result); - BUG_ON(dev->state != DEV_STATE_VERIFYING); - if (result < 0 || result == FP_VERIFY_NO_MATCH - || result == FP_VERIFY_MATCH) - dev->state = DEV_STATE_VERIFY_DONE; - - if (dev->verify_cb) - dev->verify_cb(dev, result, img, dev->verify_cb_data); - else - fp_dbg("ignoring verify result as no callback is subscribed"); -} - -/* Drivers call this when verification has stopped */ -void fpi_drvcb_verify_stopped(struct fp_dev *dev) -{ - G_DEBUG_HERE(); - BUG_ON(dev->state != DEV_STATE_VERIFY_STOPPING); - dev->state = DEV_STATE_INITIALIZED; - if (dev->verify_stop_cb) - dev->verify_stop_cb(dev, dev->verify_stop_cb_data); -} - -/** - * fp_async_verify_stop: - * @dev: the struct #fp_dev device - * @callback: the callback to call to finish a verification - * @user_data: user data to pass to the callback - * - * Finishes an ongoing verification started with fp_async_verify_start(). - * - * Returns: 0 on success, non-zero on error - */ -API_EXPORTED int fp_async_verify_stop(struct fp_dev *dev, - fp_operation_stop_cb callback, void *user_data) -{ - struct fp_driver *drv; - gboolean iterating = (dev->state == DEV_STATE_VERIFYING); - int r; - - g_return_val_if_fail(dev != NULL, -ENODEV); - - G_DEBUG_HERE(); - - if (dev->state == DEV_STATE_VERIFY_STOPPING) { - fp_dbg ("Already stopping verification, returning -EINPROGRESS"); - return -EINPROGRESS; - } - - if (dev->state == DEV_STATE_INITIALIZED) { - if (callback) - callback(dev, user_data); - return 0; - } - - drv = dev->drv; - - BUG_ON(dev->state != DEV_STATE_ERROR - && dev->state != DEV_STATE_VERIFYING - && dev->state != DEV_STATE_VERIFY_DONE); - - dev->verify_cb = NULL; - dev->verify_stop_cb = callback; - dev->verify_stop_cb_data = user_data; - dev->state = DEV_STATE_VERIFY_STOPPING; - - if (!drv->verify_start) - return -ENOTSUP; - if (!drv->verify_stop) { - dev->state = DEV_STATE_INITIALIZED; - fpi_drvcb_verify_stopped(dev); - return 0; - } - - r = drv->verify_stop(dev, iterating); - if (r < 0) { - fp_err("failed to stop verification"); - dev->verify_stop_cb = NULL; - } - return r; -} - -/** - * fp_async_identify_start: - * @dev: the struct #fp_dev device - * @gallery: NULL-terminated array of pointers to the prints to - * identify against. Each one must have been previously enrolled with a device - * compatible to the device selected to perform the scan - * @callback: the callback to call when the identification has finished - * @user_data: user data to pass to the callback - * - * Performs a new scan and verifies it against a previously enrolled print. - * See also: fp_verify_finger_img() - * - * Returns: 0 on success, non-zero on error - */ -API_EXPORTED int fp_async_identify_start(struct fp_dev *dev, - struct fp_print_data **gallery, fp_identify_cb callback, void *user_data) -{ - struct fp_driver *drv; - int r; - - g_return_val_if_fail(dev != NULL, -ENODEV); - g_return_val_if_fail (callback != NULL, -EINVAL); - - drv = dev->drv; - - G_DEBUG_HERE(); - if (!drv->identify_start) - return -ENOTSUP; - dev->state = DEV_STATE_IDENTIFY_STARTING; - dev->identify_cb = callback; - dev->identify_cb_data = user_data; - dev->identify_gallery = gallery; - - r = drv->identify_start(dev); - if (r < 0) { - fp_err("identify_start failed with error %d", r); - dev->identify_cb = NULL; - dev->state = DEV_STATE_ERROR; - } - return r; -} - -/* Driver-lib: identification has started, expect results soon */ -void fpi_drvcb_identify_started(struct fp_dev *dev, int status) -{ - fp_dbg("status %d", status); - BUG_ON(dev->state != DEV_STATE_IDENTIFY_STARTING); - if (status) { - if (status > 0) { - status = -status; - fp_dbg("adjusted to %d", status); - } - dev->state = DEV_STATE_ERROR; - if (dev->identify_cb) - dev->identify_cb(dev, status, 0, NULL, dev->identify_cb_data); - } else { - dev->state = DEV_STATE_IDENTIFYING; - } -} - -/* Drivers report an identify result (which might mark completion) */ -void fpi_drvcb_report_identify_result(struct fp_dev *dev, int result, - size_t match_offset, struct fp_img *img) -{ - fp_dbg("result %d", result); - BUG_ON(dev->state != DEV_STATE_IDENTIFYING - && dev->state != DEV_STATE_ERROR); - if (result < 0 || result == FP_VERIFY_NO_MATCH - || result == FP_VERIFY_MATCH) - dev->state = DEV_STATE_IDENTIFY_DONE; - - if (dev->identify_cb) - dev->identify_cb(dev, result, match_offset, img, dev->identify_cb_data); - else - fp_dbg("ignoring verify result as no callback is subscribed"); -} - -/** - * fp_async_identify_stop: - * @dev: the struct #fp_dev device - * @callback: the callback to call when the identification has stopped - * @user_data: user data to pass to the callback - * - * Stops an ongoing identification started with fp_async_identify_start(). - * - * Returns: 0 on success, non-zero on error - */ -API_EXPORTED int fp_async_identify_stop(struct fp_dev *dev, - fp_operation_stop_cb callback, void *user_data) -{ - struct fp_driver *drv; - gboolean iterating = (dev->state == DEV_STATE_IDENTIFYING); - int r; - - g_return_val_if_fail(dev != NULL, -ENODEV); - - G_DEBUG_HERE(); - - if (dev->state == DEV_STATE_IDENTIFY_STOPPING) { - fp_dbg ("Already stopping identification, returning -EINPROGRESS"); - return -EINPROGRESS; - } - - if (dev->state == DEV_STATE_INITIALIZED) { - if (callback) - callback(dev, user_data); - return 0; - } - - drv = dev->drv; - - BUG_ON(dev->state != DEV_STATE_IDENTIFYING - && dev->state != DEV_STATE_IDENTIFY_DONE); - - dev->state = DEV_STATE_IDENTIFY_STOPPING; - dev->identify_cb = NULL; - dev->identify_stop_cb = callback; - dev->identify_stop_cb_data = user_data; - - if (!drv->identify_start) - return -ENOTSUP; - if (!drv->identify_stop) { - dev->state = DEV_STATE_INITIALIZED; - fpi_drvcb_identify_stopped(dev); - return 0; - } - - r = drv->identify_stop(dev, iterating); - if (r < 0) { - fp_err("failed to stop identification"); - dev->identify_stop_cb = NULL; - } - - return r; -} - -/* Drivers call this when identification has stopped */ -void fpi_drvcb_identify_stopped(struct fp_dev *dev) -{ - G_DEBUG_HERE(); - BUG_ON(dev->state != DEV_STATE_IDENTIFY_STOPPING); - dev->state = DEV_STATE_INITIALIZED; - if (dev->identify_stop_cb) - dev->identify_stop_cb(dev, dev->identify_stop_cb_data); -} - -/** - * fp_async_capture_start: - * @dev: the struct #fp_dev device - * @unconditional: whether to unconditionally capture an image, or to only capture when a finger is detected - * @callback: the callback to call when the capture has finished - * @user_data: user data to pass to the callback - * - * Start the capture of an #fp_img from a device. When the @callback has been called, - * you must call fp_async_capture_stop(). - * - * Returns: 0 on success, non-zero on error. -ENOTSUP indicates that either the - * @unconditional flag was set but the device does not support this, or that the• - * device does not support imaging - */ -API_EXPORTED int fp_async_capture_start(struct fp_dev *dev, int unconditional, - fp_img_operation_cb callback, void *user_data) -{ - struct fp_driver *drv; - int r; - - g_return_val_if_fail(dev != NULL, -ENODEV); - g_return_val_if_fail (callback != NULL, -EINVAL); - - drv = dev->drv; - - G_DEBUG_HERE(); - if (!drv->capture_start) - return -ENOTSUP; - - dev->state = DEV_STATE_CAPTURE_STARTING; - dev->capture_cb = callback; - dev->capture_cb_data = user_data; - dev->unconditional_capture = unconditional; - - r = drv->capture_start(dev); - if (r < 0) { - dev->capture_cb = NULL; - dev->state = DEV_STATE_ERROR; - fp_err("failed to start capture, error %d", r); - } - return r; -} - -/* Drivers call this when capture has started */ -void fpi_drvcb_capture_started(struct fp_dev *dev, int status) -{ - G_DEBUG_HERE(); - BUG_ON(dev->state != DEV_STATE_CAPTURE_STARTING); - if (status) { - if (status > 0) { - status = -status; - fp_dbg("adjusted to %d", status); - } - dev->state = DEV_STATE_ERROR; - if (dev->capture_cb) - dev->capture_cb(dev, status, NULL, dev->capture_cb_data); - } else { - dev->state = DEV_STATE_CAPTURING; - } -} - -/* Drivers call this to report a capture result (which might mark completion) */ -void fpi_drvcb_report_capture_result(struct fp_dev *dev, int result, - struct fp_img *img) -{ - fp_dbg("result %d", result); - BUG_ON(dev->state != DEV_STATE_CAPTURING); - if (result < 0 || result == FP_CAPTURE_COMPLETE) - dev->state = DEV_STATE_CAPTURE_DONE; - - if (dev->capture_cb) - dev->capture_cb(dev, result, img, dev->capture_cb_data); - else - fp_dbg("ignoring capture result as no callback is subscribed"); -} - -/* Drivers call this when capture has stopped */ -void fpi_drvcb_capture_stopped(struct fp_dev *dev) -{ - G_DEBUG_HERE(); - BUG_ON(dev->state != DEV_STATE_CAPTURE_STOPPING); - dev->state = DEV_STATE_INITIALIZED; - if (dev->capture_stop_cb) - dev->capture_stop_cb(dev, dev->capture_stop_cb_data); -} - -/** - * fp_async_capture_stop: - * @dev: the struct #fp_dev device - * @callback: the callback to call when the capture has been stopped - * @user_data: user data to pass to the callback - * - * Stops an ongoing verification started with fp_async_capture_start(). - * - * Returns: 0 on success, non-zero on error - */ -API_EXPORTED int fp_async_capture_stop(struct fp_dev *dev, - fp_operation_stop_cb callback, void *user_data) -{ - struct fp_driver *drv; - int r; - - g_return_val_if_fail(dev != NULL, -ENODEV); - - drv = dev->drv; - - G_DEBUG_HERE(); - BUG_ON(dev->state != DEV_STATE_ERROR - && dev->state != DEV_STATE_CAPTURING - && dev->state != DEV_STATE_CAPTURE_DONE); - - dev->capture_cb = NULL; - dev->capture_stop_cb = callback; - dev->capture_stop_cb_data = user_data; - dev->state = DEV_STATE_CAPTURE_STOPPING; - - if (!drv->capture_start) - return -ENOTSUP; - if (!drv->capture_stop) { - dev->state = DEV_STATE_INITIALIZED; - fpi_drvcb_capture_stopped(dev); - return 0; - } - - r = drv->capture_stop(dev); - if (r < 0) { - fp_err("failed to stop capture"); - dev->capture_stop_cb = NULL; - } - return r; -} diff --git a/libfprint/fpi-async.h b/libfprint/fpi-async.h deleted file mode 100644 index cf6fa32e..00000000 --- a/libfprint/fpi-async.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2007-2008 Daniel Drake - * Copyright (C) 2018 Bastien Nocera - * - * 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 - */ - -#ifndef __FPI_ASYNC_H__ -#define __FPI_ASYNC_H__ - -#include "fpi-dev.h" -#include "fpi-data.h" - -void fpi_drvcb_open_complete(struct fp_dev *dev, int status); -void fpi_drvcb_close_complete(struct fp_dev *dev); - -void fpi_drvcb_enroll_started(struct fp_dev *dev, int status); -void fpi_drvcb_enroll_stage_completed(struct fp_dev *dev, int result, - struct fp_print_data *data, struct fp_img *img); -void fpi_drvcb_enroll_stopped(struct fp_dev *dev); - -void fpi_drvcb_verify_started(struct fp_dev *dev, int status); -void fpi_drvcb_report_verify_result(struct fp_dev *dev, int result, - struct fp_img *img); -void fpi_drvcb_verify_stopped(struct fp_dev *dev); - -#endif diff --git a/libfprint/fpi-byte-reader.c b/libfprint/fpi-byte-reader.c new file mode 100644 index 00000000..aecbe5bc --- /dev/null +++ b/libfprint/fpi-byte-reader.c @@ -0,0 +1,1259 @@ +/* GStreamer byte reader + * + * Copyright (C) 2008 Sebastian Dröge . + * Copyright (C) 2009,2014 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define FPI_BYTE_READER_DISABLE_INLINES +#include "fpi-byte-reader.h" + +#include + +/** + * SECTION:fpi-byte-reader + * @title: FpiByteReader + * @short_description: Reads different integer, string and floating point + * types from a memory buffer + * + * #FpiByteReader provides a byte reader that can read different integer and + * floating point types from a memory buffer. It provides functions for reading + * signed/unsigned, little/big endian integers of 8, 16, 24, 32 and 64 bits + * and functions for reading little/big endian floating points numbers of + * 32 and 64 bits. It also provides functions to read NUL-terminated strings + * in various character encodings. + */ + +/** + * fpi_byte_reader_new: (skip) + * @data: (in) (transfer none) (array length=size): data from which the + * #FpiByteReader should read + * @size: Size of @data in bytes + * + * Create a new #FpiByteReader instance, which will read from @data. + * + * Free-function: fpi_byte_reader_free + * + * Returns: (transfer full): a new #FpiByteReader instance + */ +FpiByteReader * +fpi_byte_reader_new (const guint8 * data, guint size) +{ + FpiByteReader *ret = g_slice_new0 (FpiByteReader); + + ret->data = data; + ret->size = size; + + return ret; +} + +/** + * fpi_byte_reader_free: + * @reader: (in) (transfer full): a #FpiByteReader instance + * + * Frees a #FpiByteReader instance, which was previously allocated by + * fpi_byte_reader_new(). + */ +void +fpi_byte_reader_free (FpiByteReader * reader) +{ + g_return_if_fail (reader != NULL); + + g_slice_free (FpiByteReader, reader); +} + +/** + * fpi_byte_reader_init: + * @reader: a #FpiByteReader instance + * @data: (in) (transfer none) (array length=size): data from which + * the #FpiByteReader should read + * @size: Size of @data in bytes + * + * Initializes a #FpiByteReader instance to read from @data. This function + * can be called on already initialized instances. + */ +void +fpi_byte_reader_init (FpiByteReader * reader, const guint8 * data, guint size) +{ + g_return_if_fail (reader != NULL); + + reader->data = data; + reader->size = size; + reader->byte = 0; +} + +/** + * fpi_byte_reader_peek_sub_reader: (skip) + * @reader: an existing and initialized #FpiByteReader instance + * @sub_reader: a #FpiByteReader instance to initialize as sub-reader + * @size: size of @sub_reader in bytes + * + * Initializes a #FpiByteReader sub-reader instance to contain @size bytes of + * data from the current position of @reader. This is useful to read chunked + * formats and make sure that one doesn't read beyond the size of the sub-chunk. + * + * Unlike fpi_byte_reader_get_sub_reader(), this function does not modify the + * current position of @reader. + * + * Returns: FALSE on error or if @reader does not contain @size more bytes from + * the current position, and otherwise TRUE + * + * Since: 1.6 + */ +gboolean +fpi_byte_reader_peek_sub_reader (FpiByteReader * reader, + FpiByteReader * sub_reader, guint size) +{ + return fpi_byte_reader_peek_sub_reader_inline (reader, sub_reader, size); +} + +/** + * fpi_byte_reader_get_sub_reader: (skip) + * @reader: an existing and initialized #FpiByteReader instance + * @sub_reader: a #FpiByteReader instance to initialize as sub-reader + * @size: size of @sub_reader in bytes + * + * Initializes a #FpiByteReader sub-reader instance to contain @size bytes of + * data from the current position of @reader. This is useful to read chunked + * formats and make sure that one doesn't read beyond the size of the sub-chunk. + * + * Unlike fpi_byte_reader_peek_sub_reader(), this function also modifies the + * position of @reader and moves it forward by @size bytes. + * + * Returns: FALSE on error or if @reader does not contain @size more bytes from + * the current position, and otherwise TRUE + * + * Since: 1.6 + */ +gboolean +fpi_byte_reader_get_sub_reader (FpiByteReader * reader, + FpiByteReader * sub_reader, guint size) +{ + return fpi_byte_reader_get_sub_reader_inline (reader, sub_reader, size); +} + +/** + * fpi_byte_reader_set_pos: + * @reader: a #FpiByteReader instance + * @pos: The new position in bytes + * + * Sets the new position of a #FpiByteReader instance to @pos in bytes. + * + * Returns: %TRUE if the position could be set successfully, %FALSE + * otherwise. + */ +gboolean +fpi_byte_reader_set_pos (FpiByteReader * reader, guint pos) +{ + g_return_val_if_fail (reader != NULL, FALSE); + + if (pos > reader->size) + return FALSE; + + reader->byte = pos; + + return TRUE; +} + +/** + * fpi_byte_reader_get_pos: + * @reader: a #FpiByteReader instance + * + * Returns the current position of a #FpiByteReader instance in bytes. + * + * Returns: The current position of @reader in bytes. + */ +guint +fpi_byte_reader_get_pos (const FpiByteReader * reader) +{ + return fpi_byte_reader_get_pos_inline (reader); +} + +/** + * fpi_byte_reader_get_remaining: + * @reader: a #FpiByteReader instance + * + * Returns the remaining number of bytes of a #FpiByteReader instance. + * + * Returns: The remaining number of bytes of @reader instance. + */ +guint +fpi_byte_reader_get_remaining (const FpiByteReader * reader) +{ + return fpi_byte_reader_get_remaining_inline (reader); +} + +/** + * fpi_byte_reader_get_size: + * @reader: a #FpiByteReader instance + * + * Returns the total number of bytes of a #FpiByteReader instance. + * + * Returns: The total number of bytes of @reader instance. + */ +guint +fpi_byte_reader_get_size (const FpiByteReader * reader) +{ + return fpi_byte_reader_get_size_inline (reader); +} + +#define fpi_byte_reader_get_remaining fpi_byte_reader_get_remaining_inline +#define fpi_byte_reader_get_size fpi_byte_reader_get_size_inline + +/** + * fpi_byte_reader_skip: + * @reader: a #FpiByteReader instance + * @nbytes: the number of bytes to skip + * + * Skips @nbytes bytes of the #FpiByteReader instance. + * + * Returns: %TRUE if @nbytes bytes could be skipped, %FALSE otherwise. + */ +gboolean +fpi_byte_reader_skip (FpiByteReader * reader, guint nbytes) +{ + return fpi_byte_reader_skip_inline (reader, nbytes); +} + +/** + * fpi_byte_reader_get_uint8: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #guint8 to store the result + * + * Read an unsigned 8 bit integer into @val and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_get_int8: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gint8 to store the result + * + * Read a signed 8 bit integer into @val and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_uint8: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #guint8 to store the result + * + * Read an unsigned 8 bit integer into @val but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_int8: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gint8 to store the result + * + * Read a signed 8 bit integer into @val but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_get_uint16_le: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #guint16 to store the result + * + * Read an unsigned 16 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_get_int16_le: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gint16 to store the result + * + * Read a signed 16 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_uint16_le: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #guint16 to store the result + * + * Read an unsigned 16 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_int16_le: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gint16 to store the result + * + * Read a signed 16 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_get_uint16_be: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #guint16 to store the result + * + * Read an unsigned 16 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_get_int16_be: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gint16 to store the result + * + * Read a signed 16 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_uint16_be: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #guint16 to store the result + * + * Read an unsigned 16 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_int16_be: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gint16 to store the result + * + * Read a signed 16 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_get_uint24_le: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #guint32 to store the result + * + * Read an unsigned 24 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_get_int24_le: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gint32 to store the result + * + * Read a signed 24 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_uint24_le: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #guint32 to store the result + * + * Read an unsigned 24 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_int24_le: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gint32 to store the result + * + * Read a signed 24 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_get_uint24_be: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #guint32 to store the result + * + * Read an unsigned 24 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_get_int24_be: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gint32 to store the result + * + * Read a signed 24 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_uint24_be: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #guint32 to store the result + * + * Read an unsigned 24 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_int24_be: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gint32 to store the result + * + * Read a signed 24 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + + +/** + * fpi_byte_reader_get_uint32_le: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #guint32 to store the result + * + * Read an unsigned 32 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_get_int32_le: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gint32 to store the result + * + * Read a signed 32 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_uint32_le: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #guint32 to store the result + * + * Read an unsigned 32 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_int32_le: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gint32 to store the result + * + * Read a signed 32 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_get_uint32_be: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #guint32 to store the result + * + * Read an unsigned 32 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_get_int32_be: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gint32 to store the result + * + * Read a signed 32 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_uint32_be: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #guint32 to store the result + * + * Read an unsigned 32 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_int32_be: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gint32 to store the result + * + * Read a signed 32 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_get_uint64_le: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #guint64 to store the result + * + * Read an unsigned 64 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_get_int64_le: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gint64 to store the result + * + * Read a signed 64 bit little endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_uint64_le: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #guint64 to store the result + * + * Read an unsigned 64 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_int64_le: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gint64 to store the result + * + * Read a signed 64 bit little endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_get_uint64_be: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #guint64 to store the result + * + * Read an unsigned 64 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_get_int64_be: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gint64 to store the result + * + * Read a signed 64 bit big endian integer into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_uint64_be: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #guint64 to store the result + * + * Read an unsigned 64 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_int64_be: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gint64 to store the result + * + * Read a signed 64 bit big endian integer into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +#define FPI_BYTE_READER_PEEK_GET(bits,type,name) \ +gboolean \ +fpi_byte_reader_get_##name (FpiByteReader * reader, type * val) \ +{ \ + return fpi_byte_reader_get_##name##_inline (reader, val); \ +} \ +\ +gboolean \ +fpi_byte_reader_peek_##name (const FpiByteReader * reader, type * val) \ +{ \ + return fpi_byte_reader_peek_##name##_inline (reader, val); \ +} + +/* *INDENT-OFF* */ + +FPI_BYTE_READER_PEEK_GET(8,guint8,uint8) +FPI_BYTE_READER_PEEK_GET(8,gint8,int8) + +FPI_BYTE_READER_PEEK_GET(16,guint16,uint16_le) +FPI_BYTE_READER_PEEK_GET(16,guint16,uint16_be) +FPI_BYTE_READER_PEEK_GET(16,gint16,int16_le) +FPI_BYTE_READER_PEEK_GET(16,gint16,int16_be) + +FPI_BYTE_READER_PEEK_GET(24,guint32,uint24_le) +FPI_BYTE_READER_PEEK_GET(24,guint32,uint24_be) +FPI_BYTE_READER_PEEK_GET(24,gint32,int24_le) +FPI_BYTE_READER_PEEK_GET(24,gint32,int24_be) + +FPI_BYTE_READER_PEEK_GET(32,guint32,uint32_le) +FPI_BYTE_READER_PEEK_GET(32,guint32,uint32_be) +FPI_BYTE_READER_PEEK_GET(32,gint32,int32_le) +FPI_BYTE_READER_PEEK_GET(32,gint32,int32_be) + +FPI_BYTE_READER_PEEK_GET(64,guint64,uint64_le) +FPI_BYTE_READER_PEEK_GET(64,guint64,uint64_be) +FPI_BYTE_READER_PEEK_GET(64,gint64,int64_le) +FPI_BYTE_READER_PEEK_GET(64,gint64,int64_be) + +/** + * fpi_byte_reader_get_float32_le: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gfloat to store the result + * + * Read a 32 bit little endian floating point value into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_float32_le: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gfloat to store the result + * + * Read a 32 bit little endian floating point value into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_get_float32_be: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gfloat to store the result + * + * Read a 32 bit big endian floating point value into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_float32_be: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gfloat to store the result + * + * Read a 32 bit big endian floating point value into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_get_float64_le: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gdouble to store the result + * + * Read a 64 bit little endian floating point value into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_float64_le: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gdouble to store the result + * + * Read a 64 bit little endian floating point value into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_get_float64_be: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gdouble to store the result + * + * Read a 64 bit big endian floating point value into @val + * and update the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +/** + * fpi_byte_reader_peek_float64_be: + * @reader: a #FpiByteReader instance + * @val: (out): Pointer to a #gdouble to store the result + * + * Read a 64 bit big endian floating point value into @val + * but keep the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ + +FPI_BYTE_READER_PEEK_GET(32,gfloat,float32_le) +FPI_BYTE_READER_PEEK_GET(32,gfloat,float32_be) +FPI_BYTE_READER_PEEK_GET(64,gdouble,float64_le) +FPI_BYTE_READER_PEEK_GET(64,gdouble,float64_be) + +/* *INDENT-ON* */ + +/** + * fpi_byte_reader_get_data: + * @reader: a #FpiByteReader instance + * @size: Size in bytes + * @val: (out) (transfer none) (array length=size): address of a + * #guint8 pointer variable in which to store the result + * + * Returns a constant pointer to the current data + * position if at least @size bytes are left and + * updates the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ +gboolean +fpi_byte_reader_get_data (FpiByteReader * reader, guint size, + const guint8 ** val) +{ + return fpi_byte_reader_get_data_inline (reader, size, val); +} + +/** + * fpi_byte_reader_peek_data: + * @reader: a #FpiByteReader instance + * @size: Size in bytes + * @val: (out) (transfer none) (array length=size): address of a + * #guint8 pointer variable in which to store the result + * + * Returns a constant pointer to the current data + * position if at least @size bytes are left and + * keeps the current position. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ +gboolean +fpi_byte_reader_peek_data (const FpiByteReader * reader, guint size, + const guint8 ** val) +{ + return fpi_byte_reader_peek_data_inline (reader, size, val); +} + +/** + * fpi_byte_reader_dup_data: + * @reader: a #FpiByteReader instance + * @size: Size in bytes + * @val: (out) (transfer full) (array length=size): address of a + * #guint8 pointer variable in which to store the result + * + * Free-function: g_free + * + * Returns a newly-allocated copy of the current data + * position if at least @size bytes are left and + * updates the current position. Free with g_free() when no longer needed. + * + * Returns: %TRUE if successful, %FALSE otherwise. + */ +gboolean +fpi_byte_reader_dup_data (FpiByteReader * reader, guint size, guint8 ** val) +{ + return fpi_byte_reader_dup_data_inline (reader, size, val); +} + +/* Special optimized scan for mask 0xffffff00 and pattern 0x00000100 */ +static inline gint +_scan_for_start_code (const guint8 * data, guint size) +{ + guint8 *pdata = (guint8 *) data; + guint8 *pend = (guint8 *) (data + size - 4); + + while (pdata <= pend) { + if (pdata[2] > 1) { + pdata += 3; + } else if (pdata[1]) { + pdata += 2; + } else if (pdata[0] || pdata[2] != 1) { + pdata++; + } else { + return (pdata - data); + } + } + + /* nothing found */ + return -1; +} + +static inline guint +_masked_scan_uint32_peek (const FpiByteReader * reader, + guint32 mask, guint32 pattern, guint offset, guint size, guint32 * value) +{ + const guint8 *data; + guint32 state; + guint i; + + g_return_val_if_fail (size > 0, -1); + g_return_val_if_fail ((guint64) offset + size <= reader->size - reader->byte, + -1); + + /* we can't find the pattern with less than 4 bytes */ + if (G_UNLIKELY (size < 4)) + return -1; + + data = reader->data + reader->byte + offset; + + /* Handle special case found in MPEG and H264 */ + if ((pattern == 0x00000100) && (mask == 0xffffff00)) { + gint ret = _scan_for_start_code (data, size); + + if (ret == -1) + return ret; + + if (value != NULL) + *value = (1 << 8) | data[ret + 3]; + + return ret + offset; + } + + /* set the state to something that does not match */ + state = ~pattern; + + /* now find data */ + for (i = 0; i < size; i++) { + /* throw away one byte and move in the next byte */ + state = ((state << 8) | data[i]); + if (G_UNLIKELY ((state & mask) == pattern)) { + /* we have a match but we need to have skipped at + * least 4 bytes to fill the state. */ + if (G_LIKELY (i >= 3)) { + if (value) + *value = state; + return offset + i - 3; + } + } + } + + /* nothing found */ + return -1; +} + + +/** + * fpi_byte_reader_masked_scan_uint32: + * @reader: a #FpiByteReader + * @mask: mask to apply to data before matching against @pattern + * @pattern: pattern to match (after mask is applied) + * @offset: offset from which to start scanning, relative to the current + * position + * @size: number of bytes to scan from offset + * + * Scan for pattern @pattern with applied mask @mask in the byte reader data, + * starting from offset @offset relative to the current position. + * + * The bytes in @pattern and @mask are interpreted left-to-right, regardless + * of endianness. All four bytes of the pattern must be present in the + * byte reader data for it to match, even if the first or last bytes are masked + * out. + * + * It is an error to call this function without making sure that there is + * enough data (offset+size bytes) in the byte reader. + * + * Returns: offset of the first match, or -1 if no match was found. + * + * Example: + * |[ + * // Assume the reader contains 0x00 0x01 0x02 ... 0xfe 0xff + * + * fpi_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x00010203, 0, 256); + * // -> returns 0 + * fpi_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x00010203, 1, 255); + * // -> returns -1 + * fpi_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x01020304, 1, 255); + * // -> returns 1 + * fpi_byte_reader_masked_scan_uint32 (reader, 0xffff, 0x0001, 0, 256); + * // -> returns -1 + * fpi_byte_reader_masked_scan_uint32 (reader, 0xffff, 0x0203, 0, 256); + * // -> returns 0 + * fpi_byte_reader_masked_scan_uint32 (reader, 0xffff0000, 0x02030000, 0, 256); + * // -> returns 2 + * fpi_byte_reader_masked_scan_uint32 (reader, 0xffff0000, 0x02030000, 0, 4); + * // -> returns -1 + * ]| + */ +guint +fpi_byte_reader_masked_scan_uint32 (const FpiByteReader * reader, guint32 mask, + guint32 pattern, guint offset, guint size) +{ + return _masked_scan_uint32_peek (reader, mask, pattern, offset, size, NULL); +} + +/** + * fpi_byte_reader_masked_scan_uint32_peek: + * @reader: a #FpiByteReader + * @mask: mask to apply to data before matching against @pattern + * @pattern: pattern to match (after mask is applied) + * @offset: offset from which to start scanning, relative to the current + * position + * @size: number of bytes to scan from offset + * @value: (out): pointer to uint32 to return matching data + * + * Scan for pattern @pattern with applied mask @mask in the byte reader data, + * starting from offset @offset relative to the current position. + * + * The bytes in @pattern and @mask are interpreted left-to-right, regardless + * of endianness. All four bytes of the pattern must be present in the + * byte reader data for it to match, even if the first or last bytes are masked + * out. + * + * It is an error to call this function without making sure that there is + * enough data (offset+size bytes) in the byte reader. + * + * Returns: offset of the first match, or -1 if no match was found. + * + * Since: 1.6 + */ +guint +fpi_byte_reader_masked_scan_uint32_peek (const FpiByteReader * reader, + guint32 mask, guint32 pattern, guint offset, guint size, guint32 * value) +{ + return _masked_scan_uint32_peek (reader, mask, pattern, offset, size, value); +} + +#define FPI_BYTE_READER_SCAN_STRING(bits) \ +static guint \ +fpi_byte_reader_scan_string_utf##bits (const FpiByteReader * reader) \ +{ \ + guint len, off, max_len; \ + \ + max_len = (reader->size - reader->byte) / sizeof (guint##bits); \ + \ + /* need at least a single NUL terminator */ \ + if (max_len < 1) \ + return 0; \ + \ + len = 0; \ + off = reader->byte; \ + /* endianness does not matter if we are looking for a NUL terminator */ \ + while (FP_READ_UINT##bits##_LE (&reader->data[off]) != 0) { \ + ++len; \ + off += sizeof (guint##bits); \ + /* have we reached the end without finding a NUL terminator? */ \ + if (len == max_len) \ + return 0; \ + } \ + /* return size in bytes including the NUL terminator (hence the +1) */ \ + return (len + 1) * sizeof (guint##bits); \ +} + +#define FP_READ_UINT8_LE FP_READ_UINT8 +FPI_BYTE_READER_SCAN_STRING (8); +#undef FP_READ_UINT8_LE +FPI_BYTE_READER_SCAN_STRING (16); +FPI_BYTE_READER_SCAN_STRING (32); + +#define FPI_BYTE_READER_SKIP_STRING(bits) \ +gboolean \ +fpi_byte_reader_skip_string_utf##bits (FpiByteReader * reader) \ +{ \ + guint size; /* size in bytes including the terminator */ \ + \ + g_return_val_if_fail (reader != NULL, FALSE); \ + \ + size = fpi_byte_reader_scan_string_utf##bits (reader); \ + reader->byte += size; \ + return (size > 0); \ +} + +/** + * fpi_byte_reader_skip_string: + * @reader: a #FpiByteReader instance + * + * Skips a NUL-terminated string in the #FpiByteReader instance, advancing + * the current position to the byte after the string. This will work for + * any NUL-terminated string with a character width of 8 bits, so ASCII, + * UTF-8, ISO-8859-N etc. + * + * This function will fail if no NUL-terminator was found in in the data. + * + * Returns: %TRUE if a string could be skipped, %FALSE otherwise. + */ +/** + * fpi_byte_reader_skip_string_utf8: + * @reader: a #FpiByteReader instance + * + * Skips a NUL-terminated string in the #FpiByteReader instance, advancing + * the current position to the byte after the string. This will work for + * any NUL-terminated string with a character width of 8 bits, so ASCII, + * UTF-8, ISO-8859-N etc. No input checking for valid UTF-8 is done. + * + * This function will fail if no NUL-terminator was found in in the data. + * + * Returns: %TRUE if a string could be skipped, %FALSE otherwise. + */ +FPI_BYTE_READER_SKIP_STRING (8); + +/** + * fpi_byte_reader_skip_string_utf16: + * @reader: a #FpiByteReader instance + * + * Skips a NUL-terminated UTF-16 string in the #FpiByteReader instance, + * advancing the current position to the byte after the string. + * + * No input checking for valid UTF-16 is done. + * + * This function will fail if no NUL-terminator was found in in the data. + * + * Returns: %TRUE if a string could be skipped, %FALSE otherwise. + */ +FPI_BYTE_READER_SKIP_STRING (16); + +/** + * fpi_byte_reader_skip_string_utf32: + * @reader: a #FpiByteReader instance + * + * Skips a NUL-terminated UTF-32 string in the #FpiByteReader instance, + * advancing the current position to the byte after the string. + * + * No input checking for valid UTF-32 is done. + * + * This function will fail if no NUL-terminator was found in in the data. + * + * Returns: %TRUE if a string could be skipped, %FALSE otherwise. + */ +FPI_BYTE_READER_SKIP_STRING (32); + +/** + * fpi_byte_reader_peek_string: + * @reader: a #FpiByteReader instance + * @str: (out) (transfer none) (array zero-terminated=1): address of a + * #gchar pointer variable in which to store the result + * + * Returns a constant pointer to the current data position if there is + * a NUL-terminated string in the data (this could be just a NUL terminator). + * The current position will be maintained. This will work for any + * NUL-terminated string with a character width of 8 bits, so ASCII, + * UTF-8, ISO-8859-N etc. + * + * This function will fail if no NUL-terminator was found in in the data. + * + * Returns: %TRUE if a string could be skipped, %FALSE otherwise. + */ +/** + * fpi_byte_reader_peek_string_utf8: + * @reader: a #FpiByteReader instance + * @str: (out) (transfer none) (array zero-terminated=1): address of a + * #gchar pointer variable in which to store the result + * + * Returns a constant pointer to the current data position if there is + * a NUL-terminated string in the data (this could be just a NUL terminator). + * The current position will be maintained. This will work for any + * NUL-terminated string with a character width of 8 bits, so ASCII, + * UTF-8, ISO-8859-N etc. + * + * No input checking for valid UTF-8 is done. + * + * This function will fail if no NUL-terminator was found in in the data. + * + * Returns: %TRUE if a string could be skipped, %FALSE otherwise. + */ +gboolean +fpi_byte_reader_peek_string_utf8 (const FpiByteReader * reader, + const gchar ** str) +{ + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (str != NULL, FALSE); + + if (fpi_byte_reader_scan_string_utf8 (reader) > 0) { + *str = (const gchar *) (reader->data + reader->byte); + } else { + *str = NULL; + } + return (*str != NULL); +} + +/** + * fpi_byte_reader_get_string_utf8: + * @reader: a #FpiByteReader instance + * @str: (out) (transfer none) (array zero-terminated=1): address of a + * #gchar pointer variable in which to store the result + * + * Returns a constant pointer to the current data position if there is + * a NUL-terminated string in the data (this could be just a NUL terminator), + * advancing the current position to the byte after the string. This will work + * for any NUL-terminated string with a character width of 8 bits, so ASCII, + * UTF-8, ISO-8859-N etc. + * + * No input checking for valid UTF-8 is done. + * + * This function will fail if no NUL-terminator was found in in the data. + * + * Returns: %TRUE if a string could be found, %FALSE otherwise. + */ +gboolean +fpi_byte_reader_get_string_utf8 (FpiByteReader * reader, const gchar ** str) +{ + guint size; /* size in bytes including the terminator */ + + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (str != NULL, FALSE); + + size = fpi_byte_reader_scan_string_utf8 (reader); + if (size == 0) { + *str = NULL; + return FALSE; + } + + *str = (const gchar *) (reader->data + reader->byte); + reader->byte += size; + return TRUE; +} + +#define FPI_BYTE_READER_DUP_STRING(bits,type) \ +gboolean \ +fpi_byte_reader_dup_string_utf##bits (FpiByteReader * reader, type ** str) \ +{ \ + guint size; /* size in bytes including the terminator */ \ + \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (str != NULL, FALSE); \ + \ + size = fpi_byte_reader_scan_string_utf##bits (reader); \ + if (size == 0) { \ + *str = NULL; \ + return FALSE; \ + } \ + *str = g_memdup (reader->data + reader->byte, size); \ + reader->byte += size; \ + return TRUE; \ +} + +/** + * fpi_byte_reader_dup_string_utf8: + * @reader: a #FpiByteReader instance + * @str: (out) (transfer full) (array zero-terminated=1): address of a + * #gchar pointer variable in which to store the result + * + * Free-function: g_free + * + * FIXME:Reads (copies) a NUL-terminated string in the #FpiByteReader instance, + * advancing the current position to the byte after the string. This will work + * for any NUL-terminated string with a character width of 8 bits, so ASCII, + * UTF-8, ISO-8859-N etc. No input checking for valid UTF-8 is done. + * + * This function will fail if no NUL-terminator was found in in the data. + * + * Returns: %TRUE if a string could be read into @str, %FALSE otherwise. The + * string put into @str must be freed with g_free() when no longer needed. + */ +FPI_BYTE_READER_DUP_STRING (8, gchar); + +/** + * fpi_byte_reader_dup_string_utf16: + * @reader: a #FpiByteReader instance + * @str: (out) (transfer full) (array zero-terminated=1): address of a + * #guint16 pointer variable in which to store the result + * + * Free-function: g_free + * + * Returns a newly-allocated copy of the current data position if there is + * a NUL-terminated UTF-16 string in the data (this could be an empty string + * as well), and advances the current position. + * + * No input checking for valid UTF-16 is done. This function is endianness + * agnostic - you should not assume the UTF-16 characters are in host + * endianness. + * + * This function will fail if no NUL-terminator was found in in the data. + * + * Note: there is no peek or get variant of this function to ensure correct + * byte alignment of the UTF-16 string. + * + * Returns: %TRUE if a string could be read, %FALSE otherwise. The + * string put into @str must be freed with g_free() when no longer needed. + */ +FPI_BYTE_READER_DUP_STRING (16, guint16); + +/** + * fpi_byte_reader_dup_string_utf32: + * @reader: a #FpiByteReader instance + * @str: (out) (transfer full) (array zero-terminated=1): address of a + * #guint32 pointer variable in which to store the result + * + * Free-function: g_free + * + * Returns a newly-allocated copy of the current data position if there is + * a NUL-terminated UTF-32 string in the data (this could be an empty string + * as well), and advances the current position. + * + * No input checking for valid UTF-32 is done. This function is endianness + * agnostic - you should not assume the UTF-32 characters are in host + * endianness. + * + * This function will fail if no NUL-terminator was found in in the data. + * + * Note: there is no peek or get variant of this function to ensure correct + * byte alignment of the UTF-32 string. + * + * Returns: %TRUE if a string could be read, %FALSE otherwise. The + * string put into @str must be freed with g_free() when no longer needed. + */ +FPI_BYTE_READER_DUP_STRING (32, guint32); diff --git a/libfprint/fpi-byte-reader.h b/libfprint/fpi-byte-reader.h new file mode 100644 index 00000000..0a661c6c --- /dev/null +++ b/libfprint/fpi-byte-reader.h @@ -0,0 +1,680 @@ +/* GStreamer byte reader + * + * Copyright (C) 2008 Sebastian Dröge . + * Copyright (C) 2009 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __FPI_BYTE_READER_H__ +#define __FPI_BYTE_READER_H__ + +#include +#include "fpi-byte-utils.h" + +G_BEGIN_DECLS + +#define FPI_BYTE_READER(reader) ((FpiByteReader *) (reader)) + +/** + * FpiByteReader: + * @data: (array length=size): Data from which the bit reader will + * read + * @size: Size of @data in bytes + * @byte: Current byte position + * + * A byte reader instance. + */ +typedef struct { + const guint8 *data; + guint size; + + guint byte; /* Byte position */ + + /* < private > */ +} FpiByteReader; + + +FpiByteReader * fpi_byte_reader_new (const guint8 *data, guint size) G_GNUC_MALLOC; + + +void fpi_byte_reader_free (FpiByteReader *reader); + + +void fpi_byte_reader_init (FpiByteReader *reader, const guint8 *data, guint size); + + +gboolean fpi_byte_reader_peek_sub_reader (FpiByteReader * reader, + FpiByteReader * sub_reader, + guint size); + +gboolean fpi_byte_reader_get_sub_reader (FpiByteReader * reader, + FpiByteReader * sub_reader, + guint size); + +gboolean fpi_byte_reader_set_pos (FpiByteReader *reader, guint pos); + + +guint fpi_byte_reader_get_pos (const FpiByteReader *reader); + + +guint fpi_byte_reader_get_remaining (const FpiByteReader *reader); + + +guint fpi_byte_reader_get_size (const FpiByteReader *reader); + + +gboolean fpi_byte_reader_skip (FpiByteReader *reader, guint nbytes); + + +gboolean fpi_byte_reader_get_uint8 (FpiByteReader *reader, guint8 *val); + + +gboolean fpi_byte_reader_get_int8 (FpiByteReader *reader, gint8 *val); + + +gboolean fpi_byte_reader_get_uint16_le (FpiByteReader *reader, guint16 *val); + + +gboolean fpi_byte_reader_get_int16_le (FpiByteReader *reader, gint16 *val); + + +gboolean fpi_byte_reader_get_uint16_be (FpiByteReader *reader, guint16 *val); + + +gboolean fpi_byte_reader_get_int16_be (FpiByteReader *reader, gint16 *val); + + +gboolean fpi_byte_reader_get_uint24_le (FpiByteReader *reader, guint32 *val); + + +gboolean fpi_byte_reader_get_int24_le (FpiByteReader *reader, gint32 *val); + + +gboolean fpi_byte_reader_get_uint24_be (FpiByteReader *reader, guint32 *val); + + +gboolean fpi_byte_reader_get_int24_be (FpiByteReader *reader, gint32 *val); + + +gboolean fpi_byte_reader_get_uint32_le (FpiByteReader *reader, guint32 *val); + + +gboolean fpi_byte_reader_get_int32_le (FpiByteReader *reader, gint32 *val); + + +gboolean fpi_byte_reader_get_uint32_be (FpiByteReader *reader, guint32 *val); + + +gboolean fpi_byte_reader_get_int32_be (FpiByteReader *reader, gint32 *val); + + +gboolean fpi_byte_reader_get_uint64_le (FpiByteReader *reader, guint64 *val); + + +gboolean fpi_byte_reader_get_int64_le (FpiByteReader *reader, gint64 *val); + + +gboolean fpi_byte_reader_get_uint64_be (FpiByteReader *reader, guint64 *val); + + +gboolean fpi_byte_reader_get_int64_be (FpiByteReader *reader, gint64 *val); + + +gboolean fpi_byte_reader_peek_uint8 (const FpiByteReader *reader, guint8 *val); + + +gboolean fpi_byte_reader_peek_int8 (const FpiByteReader *reader, gint8 *val); + + +gboolean fpi_byte_reader_peek_uint16_le (const FpiByteReader *reader, guint16 *val); + + +gboolean fpi_byte_reader_peek_int16_le (const FpiByteReader *reader, gint16 *val); + + +gboolean fpi_byte_reader_peek_uint16_be (const FpiByteReader *reader, guint16 *val); + + +gboolean fpi_byte_reader_peek_int16_be (const FpiByteReader *reader, gint16 *val); + + +gboolean fpi_byte_reader_peek_uint24_le (const FpiByteReader *reader, guint32 *val); + + +gboolean fpi_byte_reader_peek_int24_le (const FpiByteReader *reader, gint32 *val); + + +gboolean fpi_byte_reader_peek_uint24_be (const FpiByteReader *reader, guint32 *val); + + +gboolean fpi_byte_reader_peek_int24_be (const FpiByteReader *reader, gint32 *val); + + +gboolean fpi_byte_reader_peek_uint32_le (const FpiByteReader *reader, guint32 *val); + + +gboolean fpi_byte_reader_peek_int32_le (const FpiByteReader *reader, gint32 *val); + + +gboolean fpi_byte_reader_peek_uint32_be (const FpiByteReader *reader, guint32 *val); + + +gboolean fpi_byte_reader_peek_int32_be (const FpiByteReader *reader, gint32 *val); + + +gboolean fpi_byte_reader_peek_uint64_le (const FpiByteReader *reader, guint64 *val); + + +gboolean fpi_byte_reader_peek_int64_le (const FpiByteReader *reader, gint64 *val); + + +gboolean fpi_byte_reader_peek_uint64_be (const FpiByteReader *reader, guint64 *val); + + +gboolean fpi_byte_reader_peek_int64_be (const FpiByteReader *reader, gint64 *val); + + +gboolean fpi_byte_reader_get_float32_le (FpiByteReader *reader, gfloat *val); + + +gboolean fpi_byte_reader_get_float32_be (FpiByteReader *reader, gfloat *val); + + +gboolean fpi_byte_reader_get_float64_le (FpiByteReader *reader, gdouble *val); + + +gboolean fpi_byte_reader_get_float64_be (FpiByteReader *reader, gdouble *val); + + +gboolean fpi_byte_reader_peek_float32_le (const FpiByteReader *reader, gfloat *val); + + +gboolean fpi_byte_reader_peek_float32_be (const FpiByteReader *reader, gfloat *val); + + +gboolean fpi_byte_reader_peek_float64_le (const FpiByteReader *reader, gdouble *val); + + +gboolean fpi_byte_reader_peek_float64_be (const FpiByteReader *reader, gdouble *val); + + +gboolean fpi_byte_reader_dup_data (FpiByteReader * reader, guint size, guint8 ** val); + + +gboolean fpi_byte_reader_get_data (FpiByteReader * reader, guint size, const guint8 ** val); + + +gboolean fpi_byte_reader_peek_data (const FpiByteReader * reader, guint size, const guint8 ** val); + +#define fpi_byte_reader_dup_string(reader,str) \ + fpi_byte_reader_dup_string_utf8(reader,str) + + +gboolean fpi_byte_reader_dup_string_utf8 (FpiByteReader * reader, gchar ** str); + + +gboolean fpi_byte_reader_dup_string_utf16 (FpiByteReader * reader, guint16 ** str); + + +gboolean fpi_byte_reader_dup_string_utf32 (FpiByteReader * reader, guint32 ** str); + +#define fpi_byte_reader_skip_string(reader) \ + fpi_byte_reader_skip_string_utf8(reader) + + +gboolean fpi_byte_reader_skip_string_utf8 (FpiByteReader * reader); + + +gboolean fpi_byte_reader_skip_string_utf16 (FpiByteReader * reader); + + +gboolean fpi_byte_reader_skip_string_utf32 (FpiByteReader * reader); + +#define fpi_byte_reader_get_string(reader,str) \ + fpi_byte_reader_get_string_utf8(reader,str) + +#define fpi_byte_reader_peek_string(reader,str) \ + fpi_byte_reader_peek_string_utf8(reader,str) + + +gboolean fpi_byte_reader_get_string_utf8 (FpiByteReader * reader, const gchar ** str); + + +gboolean fpi_byte_reader_peek_string_utf8 (const FpiByteReader * reader, const gchar ** str); + + +guint fpi_byte_reader_masked_scan_uint32 (const FpiByteReader * reader, + guint32 mask, + guint32 pattern, + guint offset, + guint size); + +guint fpi_byte_reader_masked_scan_uint32_peek (const FpiByteReader * reader, + guint32 mask, + guint32 pattern, + guint offset, + guint size, + guint32 * value); + +/** + * FPI_BYTE_READER_INIT: + * @data: Data from which the #FpiByteReader should read + * @size: Size of @data in bytes + * + * A #FpiByteReader must be initialized with this macro, before it can be + * used. This macro can used be to initialize a variable, but it cannot + * be assigned to a variable. In that case you have to use + * fpi_byte_reader_init(). + */ +#define FPI_BYTE_READER_INIT(data, size) {data, size, 0} + +/* unchecked variants */ +static inline void +fpi_byte_reader_skip_unchecked (FpiByteReader * reader, guint nbytes) +{ + reader->byte += nbytes; +} + +#define __FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(bits,type,lower,upper,adj) \ +\ +static inline type \ +fpi_byte_reader_peek_##lower##_unchecked (const FpiByteReader * reader) \ +{ \ + type val = (type) FP_READ_##upper (reader->data + reader->byte); \ + adj \ + return val; \ +} \ +\ +static inline type \ +fpi_byte_reader_get_##lower##_unchecked (FpiByteReader * reader) \ +{ \ + type val = fpi_byte_reader_peek_##lower##_unchecked (reader); \ + reader->byte += bits / 8; \ + return val; \ +} + +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(8,guint8,uint8,UINT8,/* */) +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(8,gint8,int8,UINT8,/* */) + +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(16,guint16,uint16_le,UINT16_LE,/* */) +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(16,guint16,uint16_be,UINT16_BE,/* */) +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(16,gint16,int16_le,UINT16_LE,/* */) +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(16,gint16,int16_be,UINT16_BE,/* */) + +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(32,guint32,uint32_le,UINT32_LE,/* */) +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(32,guint32,uint32_be,UINT32_BE,/* */) +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(32,gint32,int32_le,UINT32_LE,/* */) +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(32,gint32,int32_be,UINT32_BE,/* */) + +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(24,guint32,uint24_le,UINT24_LE,/* */) +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(24,guint32,uint24_be,UINT24_BE,/* */) + +/* fix up the sign for 24-bit signed ints stored in 32-bit signed ints */ +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(24,gint32,int24_le,UINT24_LE, + if (val & 0x00800000) val |= 0xff000000;) +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(24,gint32,int24_be,UINT24_BE, + if (val & 0x00800000) val |= 0xff000000;) + +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(64,guint64,uint64_le,UINT64_LE,/* */) +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(64,guint64,uint64_be,UINT64_BE,/* */) +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(64,gint64,int64_le,UINT64_LE,/* */) +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(64,gint64,int64_be,UINT64_BE,/* */) + +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(32,gfloat,float32_le,FLOAT_LE,/* */) +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(32,gfloat,float32_be,FLOAT_BE,/* */) +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(64,gdouble,float64_le,DOUBLE_LE,/* */) +__FPI_BYTE_READER_GET_PEEK_BITS_UNCHECKED(64,gdouble,float64_be,DOUBLE_BE,/* */) + +#undef __GET_PEEK_BITS_UNCHECKED + +static inline const guint8 * +fpi_byte_reader_peek_data_unchecked (const FpiByteReader * reader) +{ + return (const guint8 *) (reader->data + reader->byte); +} + +static inline const guint8 * +fpi_byte_reader_get_data_unchecked (FpiByteReader * reader, guint size) +{ + const guint8 *data; + + data = fpi_byte_reader_peek_data_unchecked (reader); + fpi_byte_reader_skip_unchecked (reader, size); + return data; +} + +static inline guint8 * +fpi_byte_reader_dup_data_unchecked (FpiByteReader * reader, guint size) +{ + gconstpointer data = fpi_byte_reader_get_data_unchecked (reader, size); + return (guint8 *) g_memdup (data, size); +} + +/* Unchecked variants that should not be used */ +static inline guint +fpi_byte_reader_get_pos_unchecked (const FpiByteReader * reader) +{ + return reader->byte; +} + +static inline guint +fpi_byte_reader_get_remaining_unchecked (const FpiByteReader * reader) +{ + return reader->size - reader->byte; +} + +static inline guint +fpi_byte_reader_get_size_unchecked (const FpiByteReader * reader) +{ + return reader->size; +} + +/* inlined variants (do not use directly) */ + +static inline guint +fpi_byte_reader_get_remaining_inline (const FpiByteReader * reader) +{ + g_return_val_if_fail (reader != NULL, 0); + + return fpi_byte_reader_get_remaining_unchecked (reader); +} + +static inline guint +fpi_byte_reader_get_size_inline (const FpiByteReader * reader) +{ + g_return_val_if_fail (reader != NULL, 0); + + return fpi_byte_reader_get_size_unchecked (reader); +} + +#define __FPI_BYTE_READER_GET_PEEK_BITS_INLINE(bits,type,name) \ +\ +static inline gboolean \ +fpi_byte_reader_peek_##name##_inline (const FpiByteReader * reader, type * val) \ +{ \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (val != NULL, FALSE); \ + \ + if (fpi_byte_reader_get_remaining_unchecked (reader) < (bits / 8)) \ + return FALSE; \ +\ + *val = fpi_byte_reader_peek_##name##_unchecked (reader); \ + return TRUE; \ +} \ +\ +static inline gboolean \ +fpi_byte_reader_get_##name##_inline (FpiByteReader * reader, type * val) \ +{ \ + g_return_val_if_fail (reader != NULL, FALSE); \ + g_return_val_if_fail (val != NULL, FALSE); \ + \ + if (fpi_byte_reader_get_remaining_unchecked (reader) < (bits / 8)) \ + return FALSE; \ +\ + *val = fpi_byte_reader_get_##name##_unchecked (reader); \ + return TRUE; \ +} + +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(8,guint8,uint8) +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(8,gint8,int8) + +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(16,guint16,uint16_le) +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(16,guint16,uint16_be) +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(16,gint16,int16_le) +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(16,gint16,int16_be) + +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(32,guint32,uint32_le) +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(32,guint32,uint32_be) +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(32,gint32,int32_le) +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(32,gint32,int32_be) + +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(24,guint32,uint24_le) +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(24,guint32,uint24_be) +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(24,gint32,int24_le) +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(24,gint32,int24_be) + +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(64,guint64,uint64_le) +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(64,guint64,uint64_be) +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(64,gint64,int64_le) +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(64,gint64,int64_be) + +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(32,gfloat,float32_le) +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(32,gfloat,float32_be) +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(64,gdouble,float64_le) +__FPI_BYTE_READER_GET_PEEK_BITS_INLINE(64,gdouble,float64_be) + +#undef __FPI_BYTE_READER_GET_PEEK_BITS_INLINE + +#ifndef FPI_BYTE_READER_DISABLE_INLINES + +#define fpi_byte_reader_init(reader,data,size) \ + fpi_byte_reader_init_inline(reader,data,size) + +#define fpi_byte_reader_get_remaining(reader) \ + fpi_byte_reader_get_remaining_inline(reader) + +#define fpi_byte_reader_get_size(reader) \ + fpi_byte_reader_get_size_inline(reader) + +#define fpi_byte_reader_get_pos(reader) \ + fpi_byte_reader_get_pos_inline(reader) + +/* we use defines here so we can add the G_LIKELY() */ +#define fpi_byte_reader_get_uint8(reader,val) \ + G_LIKELY(fpi_byte_reader_get_uint8_inline(reader,val)) +#define fpi_byte_reader_get_int8(reader,val) \ + G_LIKELY(fpi_byte_reader_get_int8_inline(reader,val)) +#define fpi_byte_reader_get_uint16_le(reader,val) \ + G_LIKELY(fpi_byte_reader_get_uint16_le_inline(reader,val)) +#define fpi_byte_reader_get_int16_le(reader,val) \ + G_LIKELY(fpi_byte_reader_get_int16_le_inline(reader,val)) +#define fpi_byte_reader_get_uint16_be(reader,val) \ + G_LIKELY(fpi_byte_reader_get_uint16_be_inline(reader,val)) +#define fpi_byte_reader_get_int16_be(reader,val) \ + G_LIKELY(fpi_byte_reader_get_int16_be_inline(reader,val)) +#define fpi_byte_reader_get_uint24_le(reader,val) \ + G_LIKELY(fpi_byte_reader_get_uint24_le_inline(reader,val)) +#define fpi_byte_reader_get_int24_le(reader,val) \ + G_LIKELY(fpi_byte_reader_get_int24_le_inline(reader,val)) +#define fpi_byte_reader_get_uint24_be(reader,val) \ + G_LIKELY(fpi_byte_reader_get_uint24_be_inline(reader,val)) +#define fpi_byte_reader_get_int24_be(reader,val) \ + G_LIKELY(fpi_byte_reader_get_int24_be_inline(reader,val)) +#define fpi_byte_reader_get_uint32_le(reader,val) \ + G_LIKELY(fpi_byte_reader_get_uint32_le_inline(reader,val)) +#define fpi_byte_reader_get_int32_le(reader,val) \ + G_LIKELY(fpi_byte_reader_get_int32_le_inline(reader,val)) +#define fpi_byte_reader_get_uint32_be(reader,val) \ + G_LIKELY(fpi_byte_reader_get_uint32_be_inline(reader,val)) +#define fpi_byte_reader_get_int32_be(reader,val) \ + G_LIKELY(fpi_byte_reader_get_int32_be_inline(reader,val)) +#define fpi_byte_reader_get_uint64_le(reader,val) \ + G_LIKELY(fpi_byte_reader_get_uint64_le_inline(reader,val)) +#define fpi_byte_reader_get_int64_le(reader,val) \ + G_LIKELY(fpi_byte_reader_get_int64_le_inline(reader,val)) +#define fpi_byte_reader_get_uint64_be(reader,val) \ + G_LIKELY(fpi_byte_reader_get_uint64_be_inline(reader,val)) +#define fpi_byte_reader_get_int64_be(reader,val) \ + G_LIKELY(fpi_byte_reader_get_int64_be_inline(reader,val)) + +#define fpi_byte_reader_peek_uint8(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_uint8_inline(reader,val)) +#define fpi_byte_reader_peek_int8(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_int8_inline(reader,val)) +#define fpi_byte_reader_peek_uint16_le(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_uint16_le_inline(reader,val)) +#define fpi_byte_reader_peek_int16_le(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_int16_le_inline(reader,val)) +#define fpi_byte_reader_peek_uint16_be(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_uint16_be_inline(reader,val)) +#define fpi_byte_reader_peek_int16_be(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_int16_be_inline(reader,val)) +#define fpi_byte_reader_peek_uint24_le(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_uint24_le_inline(reader,val)) +#define fpi_byte_reader_peek_int24_le(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_int24_le_inline(reader,val)) +#define fpi_byte_reader_peek_uint24_be(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_uint24_be_inline(reader,val)) +#define fpi_byte_reader_peek_int24_be(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_int24_be_inline(reader,val)) +#define fpi_byte_reader_peek_uint32_le(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_uint32_le_inline(reader,val)) +#define fpi_byte_reader_peek_int32_le(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_int32_le_inline(reader,val)) +#define fpi_byte_reader_peek_uint32_be(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_uint32_be_inline(reader,val)) +#define fpi_byte_reader_peek_int32_be(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_int32_be_inline(reader,val)) +#define fpi_byte_reader_peek_uint64_le(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_uint64_le_inline(reader,val)) +#define fpi_byte_reader_peek_int64_le(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_int64_le_inline(reader,val)) +#define fpi_byte_reader_peek_uint64_be(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_uint64_be_inline(reader,val)) +#define fpi_byte_reader_peek_int64_be(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_int64_be_inline(reader,val)) + +#define fpi_byte_reader_get_float32_le(reader,val) \ + G_LIKELY(fpi_byte_reader_get_float32_le_inline(reader,val)) +#define fpi_byte_reader_get_float32_be(reader,val) \ + G_LIKELY(fpi_byte_reader_get_float32_be_inline(reader,val)) +#define fpi_byte_reader_get_float64_le(reader,val) \ + G_LIKELY(fpi_byte_reader_get_float64_le_inline(reader,val)) +#define fpi_byte_reader_get_float64_be(reader,val) \ + G_LIKELY(fpi_byte_reader_get_float64_be_inline(reader,val)) +#define fpi_byte_reader_peek_float32_le(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_float32_le_inline(reader,val)) +#define fpi_byte_reader_peek_float32_be(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_float32_be_inline(reader,val)) +#define fpi_byte_reader_peek_float64_le(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_float64_le_inline(reader,val)) +#define fpi_byte_reader_peek_float64_be(reader,val) \ + G_LIKELY(fpi_byte_reader_peek_float64_be_inline(reader,val)) + +#endif /* FPI_BYTE_READER_DISABLE_INLINES */ + +static inline void +fpi_byte_reader_init_inline (FpiByteReader * reader, const guint8 * data, guint size) +{ + g_return_if_fail (reader != NULL); + + reader->data = data; + reader->size = size; + reader->byte = 0; +} + +static inline gboolean +fpi_byte_reader_peek_sub_reader_inline (FpiByteReader * reader, + FpiByteReader * sub_reader, guint size) +{ + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (sub_reader != NULL, FALSE); + + if (fpi_byte_reader_get_remaining_unchecked (reader) < size) + return FALSE; + + sub_reader->data = reader->data + reader->byte; + sub_reader->byte = 0; + sub_reader->size = size; + return TRUE; +} + +static inline gboolean +fpi_byte_reader_get_sub_reader_inline (FpiByteReader * reader, + FpiByteReader * sub_reader, guint size) +{ + if (!fpi_byte_reader_peek_sub_reader_inline (reader, sub_reader, size)) + return FALSE; + fpi_byte_reader_skip_unchecked (reader, size); + return TRUE; +} + +static inline gboolean +fpi_byte_reader_dup_data_inline (FpiByteReader * reader, guint size, guint8 ** val) +{ + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (val != NULL, FALSE); + + if (G_UNLIKELY (size > reader->size || fpi_byte_reader_get_remaining_unchecked (reader) < size)) + return FALSE; + + *val = fpi_byte_reader_dup_data_unchecked (reader, size); + return TRUE; +} + +static inline gboolean +fpi_byte_reader_get_data_inline (FpiByteReader * reader, guint size, const guint8 ** val) +{ + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (val != NULL, FALSE); + + if (G_UNLIKELY (size > reader->size || fpi_byte_reader_get_remaining_unchecked (reader) < size)) + return FALSE; + + *val = fpi_byte_reader_get_data_unchecked (reader, size); + return TRUE; +} + +static inline gboolean +fpi_byte_reader_peek_data_inline (const FpiByteReader * reader, guint size, const guint8 ** val) +{ + g_return_val_if_fail (reader != NULL, FALSE); + g_return_val_if_fail (val != NULL, FALSE); + + if (G_UNLIKELY (size > reader->size || fpi_byte_reader_get_remaining_unchecked (reader) < size)) + return FALSE; + + *val = fpi_byte_reader_peek_data_unchecked (reader); + return TRUE; +} + +static inline guint +fpi_byte_reader_get_pos_inline (const FpiByteReader * reader) +{ + g_return_val_if_fail (reader != NULL, 0); + + return fpi_byte_reader_get_pos_unchecked (reader); +} + +static inline gboolean +fpi_byte_reader_skip_inline (FpiByteReader * reader, guint nbytes) +{ + g_return_val_if_fail (reader != NULL, FALSE); + + if (G_UNLIKELY (fpi_byte_reader_get_remaining_unchecked (reader) < nbytes)) + return FALSE; + + reader->byte += nbytes; + return TRUE; +} + +#ifndef FPI_BYTE_READER_DISABLE_INLINES + +#define fpi_byte_reader_dup_data(reader,size,val) \ + G_LIKELY(fpi_byte_reader_dup_data_inline(reader,size,val)) +#define fpi_byte_reader_get_data(reader,size,val) \ + G_LIKELY(fpi_byte_reader_get_data_inline(reader,size,val)) +#define fpi_byte_reader_peek_data(reader,size,val) \ + G_LIKELY(fpi_byte_reader_peek_data_inline(reader,size,val)) +#define fpi_byte_reader_skip(reader,nbytes) \ + G_LIKELY(fpi_byte_reader_skip_inline(reader,nbytes)) + +#endif /* FPI_BYTE_READER_DISABLE_INLINES */ + +G_END_DECLS + +#endif /* __FPI_BYTE_READER_H__ */ diff --git a/libfprint/fpi-byte-utils.h b/libfprint/fpi-byte-utils.h new file mode 100644 index 00000000..8a991212 --- /dev/null +++ b/libfprint/fpi-byte-utils.h @@ -0,0 +1,488 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2002 Thomas Vander Stichele + * + * gstutils.h: Header for various utility functions + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __FP_UTILS_H__ +#define __FP_UTILS_H__ + +#include + +G_BEGIN_DECLS + +/* Define PUT and GET functions for unaligned memory */ +#define _FP_GET(__data, __idx, __size, __shift) \ + (((guint##__size) (((const guint8 *) (__data))[__idx])) << (__shift)) + +#define _FP_PUT(__data, __idx, __size, __shift, __num) \ + (((guint8 *) (__data))[__idx] = (((guint##__size) (__num)) >> (__shift)) & 0xff) + +#ifndef __GTK_DOC_IGNORE__ + +/** + * FP_READ_UINT64_BE: + * @data: memory location + * + * Read a 64 bit unsigned integer value in big endian format from the memory buffer. + */ + +/** + * FP_READ_UINT64_LE: + * @data: memory location + * + * Read a 64 bit unsigned integer value in little endian format from the memory buffer. + */ +#define _FP_READ_UINT64_BE(data) (_FP_GET (data, 0, 64, 56) | \ + _FP_GET (data, 1, 64, 48) | \ + _FP_GET (data, 2, 64, 40) | \ + _FP_GET (data, 3, 64, 32) | \ + _FP_GET (data, 4, 64, 24) | \ + _FP_GET (data, 5, 64, 16) | \ + _FP_GET (data, 6, 64, 8) | \ + _FP_GET (data, 7, 64, 0)) + +#define _FP_READ_UINT64_LE(data) (_FP_GET (data, 7, 64, 56) | \ + _FP_GET (data, 6, 64, 48) | \ + _FP_GET (data, 5, 64, 40) | \ + _FP_GET (data, 4, 64, 32) | \ + _FP_GET (data, 3, 64, 24) | \ + _FP_GET (data, 2, 64, 16) | \ + _FP_GET (data, 1, 64, 8) | \ + _FP_GET (data, 0, 64, 0)) + +#define FP_READ_UINT64_BE(data) _fpi_slow_read64_be((const guint8 *)(data)) +static inline guint64 _fpi_slow_read64_be (const guint8 * data) { + return _FP_READ_UINT64_BE (data); +} +#define FP_READ_UINT64_LE(data) _fpi_slow_read64_le((const guint8 *)(data)) +static inline guint64 _fpi_slow_read64_le (const guint8 * data) { + return _FP_READ_UINT64_LE (data); +} + +/** + * FP_READ_UINT32_BE: + * @data: memory location + * + * Read a 32 bit unsigned integer value in big endian format from the memory buffer. + */ + +/** + * FP_READ_UINT32_LE: + * @data: memory location + * + * Read a 32 bit unsigned integer value in little endian format from the memory buffer. + */ +#define _FP_READ_UINT32_BE(data) (_FP_GET (data, 0, 32, 24) | \ + _FP_GET (data, 1, 32, 16) | \ + _FP_GET (data, 2, 32, 8) | \ + _FP_GET (data, 3, 32, 0)) + +#define _FP_READ_UINT32_LE(data) (_FP_GET (data, 3, 32, 24) | \ + _FP_GET (data, 2, 32, 16) | \ + _FP_GET (data, 1, 32, 8) | \ + _FP_GET (data, 0, 32, 0)) + +#define FP_READ_UINT32_BE(data) _fpi_slow_read32_be((const guint8 *)(data)) +static inline guint32 _fpi_slow_read32_be (const guint8 * data) { + return _FP_READ_UINT32_BE (data); +} +#define FP_READ_UINT32_LE(data) _fpi_slow_read32_le((const guint8 *)(data)) +static inline guint32 _fpi_slow_read32_le (const guint8 * data) { + return _FP_READ_UINT32_LE (data); +} + +/** + * FP_READ_UINT24_BE: + * @data: memory location + * + * Read a 24 bit unsigned integer value in big endian format from the memory buffer. + */ +#define _FP_READ_UINT24_BE(data) (_FP_GET (data, 0, 32, 16) | \ + _FP_GET (data, 1, 32, 8) | \ + _FP_GET (data, 2, 32, 0)) + +#define FP_READ_UINT24_BE(data) _fpi_slow_read24_be((const guint8 *)(data)) +static inline guint32 _fpi_slow_read24_be (const guint8 * data) { + return _FP_READ_UINT24_BE (data); +} + +/** + * FP_READ_UINT24_LE: + * @data: memory location + * + * Read a 24 bit unsigned integer value in little endian format from the memory buffer. + */ +#define _FP_READ_UINT24_LE(data) (_FP_GET (data, 2, 32, 16) | \ + _FP_GET (data, 1, 32, 8) | \ + _FP_GET (data, 0, 32, 0)) + +#define FP_READ_UINT24_LE(data) _fpi_slow_read24_le((const guint8 *)(data)) +static inline guint32 _fpi_slow_read24_le (const guint8 * data) { + return _FP_READ_UINT24_LE (data); +} + +/** + * FP_READ_UINT16_BE: + * @data: memory location + * + * Read a 16 bit unsigned integer value in big endian format from the memory buffer. + */ +/** + * FP_READ_UINT16_LE: + * @data: memory location + * + * Read a 16 bit unsigned integer value in little endian format from the memory buffer. + */ +#define _FP_READ_UINT16_BE(data) (_FP_GET (data, 0, 16, 8) | \ + _FP_GET (data, 1, 16, 0)) + +#define _FP_READ_UINT16_LE(data) (_FP_GET (data, 1, 16, 8) | \ + _FP_GET (data, 0, 16, 0)) + +#define FP_READ_UINT16_BE(data) _fpi_slow_read16_be((const guint8 *)(data)) +static inline guint16 _fpi_slow_read16_be (const guint8 * data) { + return _FP_READ_UINT16_BE (data); +} +#define FP_READ_UINT16_LE(data) _fpi_slow_read16_le((const guint8 *)(data)) +static inline guint16 _fpi_slow_read16_le (const guint8 * data) { + return _FP_READ_UINT16_LE (data); +} + +/** + * FP_READ_UINT8: + * @data: memory location + * + * Read an 8 bit unsigned integer value from the memory buffer. + */ +#define FP_READ_UINT8(data) (_FP_GET (data, 0, 8, 0)) + +/** + * FP_WRITE_UINT64_BE: + * @data: memory location + * @val: value to store + * + * Store a 64 bit unsigned integer value in big endian format into the memory buffer. + */ +/** + * FP_WRITE_UINT64_LE: + * @data: memory location + * @val: value to store + * + * Store a 64 bit unsigned integer value in little endian format into the memory buffer. + */ +#define FP_WRITE_UINT64_BE(data,val) do { \ + gpointer __put_data = data; \ + guint64 __put_val = val; \ + _FP_PUT (__put_data, 0, 64, 56, __put_val); \ + _FP_PUT (__put_data, 1, 64, 48, __put_val); \ + _FP_PUT (__put_data, 2, 64, 40, __put_val); \ + _FP_PUT (__put_data, 3, 64, 32, __put_val); \ + _FP_PUT (__put_data, 4, 64, 24, __put_val); \ + _FP_PUT (__put_data, 5, 64, 16, __put_val); \ + _FP_PUT (__put_data, 6, 64, 8, __put_val); \ + _FP_PUT (__put_data, 7, 64, 0, __put_val); \ + } while (0) + +#define FP_WRITE_UINT64_LE(data,val) do { \ + gpointer __put_data = data; \ + guint64 __put_val = val; \ + _FP_PUT (__put_data, 0, 64, 0, __put_val); \ + _FP_PUT (__put_data, 1, 64, 8, __put_val); \ + _FP_PUT (__put_data, 2, 64, 16, __put_val); \ + _FP_PUT (__put_data, 3, 64, 24, __put_val); \ + _FP_PUT (__put_data, 4, 64, 32, __put_val); \ + _FP_PUT (__put_data, 5, 64, 40, __put_val); \ + _FP_PUT (__put_data, 6, 64, 48, __put_val); \ + _FP_PUT (__put_data, 7, 64, 56, __put_val); \ + } while (0) + +/** + * FP_WRITE_UINT32_BE: + * @data: memory location + * @val: value to store + * + * Store a 32 bit unsigned integer value in big endian format into the memory buffer. + */ +/** + * FP_WRITE_UINT32_LE: + * @data: memory location + * @val: value to store + * + * Store a 32 bit unsigned integer value in little endian format into the memory buffer. + */ +#define FP_WRITE_UINT32_BE(data,val) do { \ + gpointer __put_data = data; \ + guint32 __put_val = val; \ + _FP_PUT (__put_data, 0, 32, 24, __put_val); \ + _FP_PUT (__put_data, 1, 32, 16, __put_val); \ + _FP_PUT (__put_data, 2, 32, 8, __put_val); \ + _FP_PUT (__put_data, 3, 32, 0, __put_val); \ + } while (0) + +#define FP_WRITE_UINT32_LE(data,val) do { \ + gpointer __put_data = data; \ + guint32 __put_val = val; \ + _FP_PUT (__put_data, 0, 32, 0, __put_val); \ + _FP_PUT (__put_data, 1, 32, 8, __put_val); \ + _FP_PUT (__put_data, 2, 32, 16, __put_val); \ + _FP_PUT (__put_data, 3, 32, 24, __put_val); \ + } while (0) + +/** + * FP_WRITE_UINT24_BE: + * @data: memory location + * @num: value to store + * + * Store a 24 bit unsigned integer value in big endian format into the memory buffer. + */ +#define FP_WRITE_UINT24_BE(data, num) do { \ + gpointer __put_data = data; \ + guint32 __put_val = num; \ + _FP_PUT (__put_data, 0, 32, 16, __put_val); \ + _FP_PUT (__put_data, 1, 32, 8, __put_val); \ + _FP_PUT (__put_data, 2, 32, 0, __put_val); \ + } while (0) + +/** + * FP_WRITE_UINT24_LE: + * @data: memory location + * @num: value to store + * + * Store a 24 bit unsigned integer value in little endian format into the memory buffer. + */ +#define FP_WRITE_UINT24_LE(data, num) do { \ + gpointer __put_data = data; \ + guint32 __put_val = num; \ + _FP_PUT (__put_data, 0, 32, 0, __put_val); \ + _FP_PUT (__put_data, 1, 32, 8, __put_val); \ + _FP_PUT (__put_data, 2, 32, 16, __put_val); \ + } while (0) + +/** + * FP_WRITE_UINT16_BE: + * @data: memory location + * @val: value to store + * + * Store a 16 bit unsigned integer value in big endian format into the memory buffer. + */ +/** + * FP_WRITE_UINT16_LE: + * @data: memory location + * @val: value to store + * + * Store a 16 bit unsigned integer value in little endian format into the memory buffer. + */ +#define FP_WRITE_UINT16_BE(data,val) do { \ + gpointer __put_data = data; \ + guint16 __put_val = val; \ + _FP_PUT (__put_data, 0, 16, 8, __put_val); \ + _FP_PUT (__put_data, 1, 16, 0, __put_val); \ + } while (0) + +#define FP_WRITE_UINT16_LE(data,val) do { \ + gpointer __put_data = data; \ + guint16 __put_val = val; \ + _FP_PUT (__put_data, 0, 16, 0, __put_val); \ + _FP_PUT (__put_data, 1, 16, 8, __put_val); \ + } while (0) + +/** + * FP_WRITE_UINT8: + * @data: memory location + * @num: value to store + * + * Store an 8 bit unsigned integer value into the memory buffer. + */ +#define FP_WRITE_UINT8(data, num) do { \ + _FP_PUT (data, 0, 8, 0, num); \ + } while (0) + +/* Float endianness conversion macros */ + +/** + * FP_READ_FLOAT_LE: + * @data: memory location + * + * Read a 32 bit float value in little endian format from the memory buffer. + * + * Returns: The floating point value read from @data + */ +static inline gfloat +FP_READ_FLOAT_LE(const guint8 *data) +{ + union + { + guint32 i; + gfloat f; + } u; + + u.i = FP_READ_UINT32_LE (data); + return u.f; +} + +/** + * FP_READ_FLOAT_BE: + * @data: memory location + * + * Read a 32 bit float value in big endian format from the memory buffer. + * + * Returns: The floating point value read from @data + */ +static inline gfloat +FP_READ_FLOAT_BE(const guint8 *data) +{ + union + { + guint32 i; + gfloat f; + } u; + + u.i = FP_READ_UINT32_BE (data); + return u.f; +} + +/** + * FP_READ_DOUBLE_LE: + * @data: memory location + * + * Read a 64 bit double value in little endian format from the memory buffer. + * + * Returns: The double-precision floating point value read from @data + */ +static inline gdouble +FP_READ_DOUBLE_LE(const guint8 *data) +{ + union + { + guint64 i; + gdouble d; + } u; + + u.i = FP_READ_UINT64_LE (data); + return u.d; +} + +/** + * FP_READ_DOUBLE_BE: + * @data: memory location + * + * Read a 64 bit double value in big endian format from the memory buffer. + * + * Returns: The double-precision floating point value read from @data + */ +static inline gdouble +FP_READ_DOUBLE_BE(const guint8 *data) +{ + union + { + guint64 i; + gdouble d; + } u; + + u.i = FP_READ_UINT64_BE (data); + return u.d; +} + +/** + * FP_WRITE_FLOAT_LE: + * @data: memory location + * @num: value to store + * + * Store a 32 bit float value in little endian format into the memory buffer. + */ +static inline void +FP_WRITE_FLOAT_LE(guint8 *data, gfloat num) +{ + union + { + guint32 i; + gfloat f; + } u; + + u.f = num; + FP_WRITE_UINT32_LE (data, u.i); +} + +/** + * FP_WRITE_FLOAT_BE: + * @data: memory location + * @num: value to store + * + * Store a 32 bit float value in big endian format into the memory buffer. + */ +static inline void +FP_WRITE_FLOAT_BE(guint8 *data, gfloat num) +{ + union + { + guint32 i; + gfloat f; + } u; + + u.f = num; + FP_WRITE_UINT32_BE (data, u.i); +} + +/** + * FP_WRITE_DOUBLE_LE: + * @data: memory location + * @num: value to store + * + * Store a 64 bit double value in little endian format into the memory buffer. + */ +static inline void +FP_WRITE_DOUBLE_LE(guint8 *data, gdouble num) +{ + union + { + guint64 i; + gdouble d; + } u; + + u.d = num; + FP_WRITE_UINT64_LE (data, u.i); +} + +/** + * FP_WRITE_DOUBLE_BE: + * @data: memory location + * @num: value to store + * + * Store a 64 bit double value in big endian format into the memory buffer. + */ +static inline void +FP_WRITE_DOUBLE_BE(guint8 *data, gdouble num) +{ + union + { + guint64 i; + gdouble d; + } u; + + u.d = num; + FP_WRITE_UINT64_BE (data, u.i); +} + +G_END_DECLS + +#endif /* __GTK_DOC_IGNORE__ */ +#endif /* __FP_UTILS_H__ */ diff --git a/libfprint/fpi-byte-writer.c b/libfprint/fpi-byte-writer.c new file mode 100644 index 00000000..4ee67ff5 --- /dev/null +++ b/libfprint/fpi-byte-writer.c @@ -0,0 +1,614 @@ +/* GStreamer byte writer + * + * Copyright (C) 2009 Sebastian Dröge . + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define FPI_BYTE_WRITER_DISABLE_INLINES +#include "fpi-byte-writer.h" + +/** + * SECTION:fpi-byte-writer + * @title: FpiByteWriter + * @short_description: Writes different integer, string and floating point + * types to a memory buffer and allows reading + * + * #FpiByteWriter provides a byte writer and reader that can write/read different + * integer and floating point types to/from a memory buffer. It provides functions + * for writing/reading signed/unsigned, little/big endian integers of 8, 16, 24, + * 32 and 64 bits and functions for reading little/big endian floating points numbers of + * 32 and 64 bits. It also provides functions to write/read NUL-terminated strings + * in various character encodings. + */ + +/** + * fpi_byte_writer_new: (skip) + * + * Creates a new, empty #FpiByteWriter instance + * + * Free-function: fpi_byte_writer_free + * + * Returns: (transfer full): a new, empty #FpiByteWriter instance + */ +FpiByteWriter * +fpi_byte_writer_new (void) +{ + FpiByteWriter *ret = g_slice_new0 (FpiByteWriter); + + ret->owned = TRUE; + return ret; +} + +/** + * fpi_byte_writer_new_with_size: (skip) + * @size: Initial size of data + * @fixed: If %TRUE the data can't be reallocated + * + * Creates a new #FpiByteWriter instance with the given + * initial data size. + * + * Free-function: fpi_byte_writer_free + * + * Returns: (transfer full): a new #FpiByteWriter instance + */ +FpiByteWriter * +fpi_byte_writer_new_with_size (guint size, gboolean fixed) +{ + FpiByteWriter *ret = fpi_byte_writer_new (); + + ret->alloc_size = size; + ret->parent.data = g_malloc (ret->alloc_size); + ret->fixed = fixed; + ret->owned = TRUE; + + return ret; +} + +/** + * fpi_byte_writer_new_with_data: (skip) + * @data: Memory area for writing + * @size: Size of @data in bytes + * @initialized: If %TRUE the complete data can be read from the beginning + * + * Creates a new #FpiByteWriter instance with the given + * memory area. If @initialized is %TRUE it is possible to + * read @size bytes from the #FpiByteWriter from the beginning. + * + * Free-function: fpi_byte_writer_free + * + * Returns: (transfer full): a new #FpiByteWriter instance + */ +FpiByteWriter * +fpi_byte_writer_new_with_data (guint8 * data, guint size, gboolean initialized) +{ + FpiByteWriter *ret = fpi_byte_writer_new (); + + ret->parent.data = data; + ret->parent.size = (initialized) ? size : 0; + ret->alloc_size = size; + ret->fixed = TRUE; + ret->owned = FALSE; + + return ret; +} + +/** + * fpi_byte_writer_init: + * @writer: #FpiByteWriter instance + * + * Initializes @writer to an empty instance + */ +void +fpi_byte_writer_init (FpiByteWriter * writer) +{ + g_return_if_fail (writer != NULL); + + memset (writer, 0, sizeof (FpiByteWriter)); + + writer->owned = TRUE; +} + +/** + * fpi_byte_writer_init_with_size: + * @writer: #FpiByteWriter instance + * @size: Initial size of data + * @fixed: If %TRUE the data can't be reallocated + * + * Initializes @writer with the given initial data size. + */ +void +fpi_byte_writer_init_with_size (FpiByteWriter * writer, guint size, + gboolean fixed) +{ + g_return_if_fail (writer != NULL); + + fpi_byte_writer_init (writer); + + writer->parent.data = g_malloc (size); + writer->alloc_size = size; + writer->fixed = fixed; + writer->owned = TRUE; +} + +/** + * fpi_byte_writer_init_with_data: + * @writer: #FpiByteWriter instance + * @data: (array length=size) (transfer none): Memory area for writing + * @size: Size of @data in bytes + * @initialized: If %TRUE the complete data can be read from the beginning + * + * Initializes @writer with the given + * memory area. If @initialized is %TRUE it is possible to + * read @size bytes from the #FpiByteWriter from the beginning. + */ +void +fpi_byte_writer_init_with_data (FpiByteWriter * writer, guint8 * data, + guint size, gboolean initialized) +{ + g_return_if_fail (writer != NULL); + + fpi_byte_writer_init (writer); + + writer->parent.data = data; + writer->parent.size = (initialized) ? size : 0; + writer->alloc_size = size; + writer->fixed = TRUE; + writer->owned = FALSE; +} + +/** + * fpi_byte_writer_reset: + * @writer: #FpiByteWriter instance + * + * Resets @writer and frees the data if it's + * owned by @writer. + */ +void +fpi_byte_writer_reset (FpiByteWriter * writer) +{ + g_return_if_fail (writer != NULL); + + if (writer->owned) + g_free ((guint8 *) writer->parent.data); + memset (writer, 0, sizeof (FpiByteWriter)); +} + +/** + * fpi_byte_writer_reset_and_get_data: + * @writer: #FpiByteWriter instance + * + * Resets @writer and returns the current data. + * + * Free-function: g_free + * + * Returns: (array) (transfer full): the current data. g_free() after + * usage. + */ +guint8 * +fpi_byte_writer_reset_and_get_data (FpiByteWriter * writer) +{ + guint8 *data; + + g_return_val_if_fail (writer != NULL, NULL); + + data = (guint8 *) writer->parent.data; + if (!writer->owned) + data = g_memdup (data, writer->parent.size); + writer->parent.data = NULL; + fpi_byte_writer_reset (writer); + + return data; +} + +/** + * fpi_byte_writer_free: + * @writer: (in) (transfer full): #FpiByteWriter instance + * + * Frees @writer and all memory allocated by it. + */ +void +fpi_byte_writer_free (FpiByteWriter * writer) +{ + g_return_if_fail (writer != NULL); + + fpi_byte_writer_reset (writer); + g_slice_free (FpiByteWriter, writer); +} + +/** + * fpi_byte_writer_free_and_get_data: + * @writer: (in) (transfer full): #FpiByteWriter instance + * + * Frees @writer and all memory allocated by it except + * the current data, which is returned. + * + * Free-function: g_free + * + * Returns: (transfer full): the current data. g_free() after usage. + */ +guint8 * +fpi_byte_writer_free_and_get_data (FpiByteWriter * writer) +{ + guint8 *data; + + g_return_val_if_fail (writer != NULL, NULL); + + data = fpi_byte_writer_reset_and_get_data (writer); + g_slice_free (FpiByteWriter, writer); + + return data; +} + +/** + * fpi_byte_writer_get_remaining: + * @writer: #FpiByteWriter instance + * + * Returns the remaining size of data that can still be written. If + * -1 is returned the remaining size is only limited by system resources. + * + * Returns: the remaining size of data that can still be written + */ +guint +fpi_byte_writer_get_remaining (const FpiByteWriter * writer) +{ + g_return_val_if_fail (writer != NULL, -1); + + if (!writer->fixed) + return -1; + else + return writer->alloc_size - writer->parent.byte; +} + +/** + * fpi_byte_writer_ensure_free_space: + * @writer: #FpiByteWriter instance + * @size: Number of bytes that should be available + * + * Checks if enough free space from the current write cursor is + * available and reallocates if necessary. + * + * Returns: %TRUE if at least @size bytes are still available + */ +gboolean +fpi_byte_writer_ensure_free_space (FpiByteWriter * writer, guint size) +{ + return fpi_byte_writer_ensure_free_space_inline (writer, size); +} + + +#define CREATE_WRITE_FUNC(bits,type,name,write_func) \ +gboolean \ +fpi_byte_writer_put_##name (FpiByteWriter *writer, type val) \ +{ \ + return fpi_byte_writer_put_##name##_inline (writer, val); \ +} + +CREATE_WRITE_FUNC (8, guint8, uint8, GST_WRITE_UINT8); +CREATE_WRITE_FUNC (8, gint8, int8, GST_WRITE_UINT8); +CREATE_WRITE_FUNC (16, guint16, uint16_le, GST_WRITE_UINT16_LE); +CREATE_WRITE_FUNC (16, guint16, uint16_be, GST_WRITE_UINT16_BE); +CREATE_WRITE_FUNC (16, gint16, int16_le, GST_WRITE_UINT16_LE); +CREATE_WRITE_FUNC (16, gint16, int16_be, GST_WRITE_UINT16_BE); +CREATE_WRITE_FUNC (24, guint32, uint24_le, GST_WRITE_UINT24_LE); +CREATE_WRITE_FUNC (24, guint32, uint24_be, GST_WRITE_UINT24_BE); +CREATE_WRITE_FUNC (24, gint32, int24_le, GST_WRITE_UINT24_LE); +CREATE_WRITE_FUNC (24, gint32, int24_be, GST_WRITE_UINT24_BE); +CREATE_WRITE_FUNC (32, guint32, uint32_le, GST_WRITE_UINT32_LE); +CREATE_WRITE_FUNC (32, guint32, uint32_be, GST_WRITE_UINT32_BE); +CREATE_WRITE_FUNC (32, gint32, int32_le, GST_WRITE_UINT32_LE); +CREATE_WRITE_FUNC (32, gint32, int32_be, GST_WRITE_UINT32_BE); +CREATE_WRITE_FUNC (64, guint64, uint64_le, GST_WRITE_UINT64_LE); +CREATE_WRITE_FUNC (64, guint64, uint64_be, GST_WRITE_UINT64_BE); +CREATE_WRITE_FUNC (64, gint64, int64_le, GST_WRITE_UINT64_LE); +CREATE_WRITE_FUNC (64, gint64, int64_be, GST_WRITE_UINT64_BE); + +CREATE_WRITE_FUNC (32, gfloat, float32_be, GST_WRITE_FLOAT_BE); +CREATE_WRITE_FUNC (32, gfloat, float32_le, GST_WRITE_FLOAT_LE); +CREATE_WRITE_FUNC (64, gdouble, float64_be, GST_WRITE_DOUBLE_BE); +CREATE_WRITE_FUNC (64, gdouble, float64_le, GST_WRITE_DOUBLE_LE); + +gboolean +fpi_byte_writer_put_data (FpiByteWriter * writer, const guint8 * data, + guint size) +{ + return fpi_byte_writer_put_data_inline (writer, data, size); +} + +gboolean +fpi_byte_writer_fill (FpiByteWriter * writer, guint8 value, guint size) +{ + return fpi_byte_writer_fill_inline (writer, value, size); +} + +#define CREATE_WRITE_STRING_FUNC(bits,type) \ +gboolean \ +fpi_byte_writer_put_string_utf##bits (FpiByteWriter *writer, const type * data) \ +{ \ + guint size = 0; \ + \ + g_return_val_if_fail (writer != NULL, FALSE); \ + \ + /* endianness does not matter if we are looking for a NUL terminator */ \ + while (data[size] != 0) { \ + /* have prevent overflow */ \ + if (G_UNLIKELY (size == G_MAXUINT)) \ + return FALSE; \ + ++size; \ + } \ + ++size; \ + \ + if (G_UNLIKELY (!fpi_byte_writer_ensure_free_space_inline(writer, size * (bits / 8)))) \ + return FALSE; \ + \ + fpi_byte_writer_put_data_inline (writer, (const guint8 *) data, size * (bits / 8)); \ + \ + return TRUE; \ +} + +CREATE_WRITE_STRING_FUNC (8, gchar); +CREATE_WRITE_STRING_FUNC (16, guint16); +CREATE_WRITE_STRING_FUNC (32, guint32); +/** + * fpi_byte_writer_put_uint8: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a unsigned 8 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_uint16_be: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a unsigned big endian 16 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_uint24_be: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a unsigned big endian 24 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_uint32_be: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a unsigned big endian 32 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_uint64_be: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a unsigned big endian 64 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_uint16_le: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a unsigned little endian 16 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_uint24_le: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a unsigned little endian 24 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_uint32_le: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a unsigned little endian 32 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_uint64_le: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a unsigned little endian 64 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_int8: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a signed 8 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_int16_be: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a signed big endian 16 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_int24_be: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a signed big endian 24 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_int32_be: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a signed big endian 32 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_int64_be: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a signed big endian 64 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_int16_le: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a signed little endian 16 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_int24_le: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a signed little endian 24 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_int32_le: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a signed little endian 32 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_int64_le: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a signed little endian 64 bit integer to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_float32_be: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a big endian 32 bit float to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_float64_be: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a big endian 64 bit float to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_float32_le: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a little endian 32 bit float to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_float64_le: + * @writer: #FpiByteWriter instance + * @val: Value to write + * + * Writes a little endian 64 bit float to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_string_utf8: + * @writer: #FpiByteWriter instance + * @data: (transfer none): UTF8 string to write + * + * Writes a NUL-terminated UTF8 string to @writer (including the terminator). + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_string_utf16: + * @writer: #FpiByteWriter instance + * @data: (transfer none) (array zero-terminated=1): UTF16 string to write + * + * Writes a NUL-terminated UTF16 string to @writer (including the terminator). + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_string_utf32: + * @writer: #FpiByteWriter instance + * @data: (transfer none) (array zero-terminated=1): UTF32 string to write + * + * Writes a NUL-terminated UTF32 string to @writer (including the terminator). + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_put_data: + * @writer: #FpiByteWriter instance + * @data: (transfer none) (array length=size): Data to write + * @size: Size of @data in bytes + * + * Writes @size bytes of @data to @writer. + * + * Returns: %TRUE if the value could be written + */ +/** + * fpi_byte_writer_fill: + * @writer: #FpiByteWriter instance + * @value: Value to be written + * @size: Number of bytes to be written + * + * Writes @size bytes containing @value to @writer. + * + * Returns: %TRUE if the value could be written + */ + diff --git a/libfprint/fpi-byte-writer.h b/libfprint/fpi-byte-writer.h new file mode 100644 index 00000000..b15a9a1e --- /dev/null +++ b/libfprint/fpi-byte-writer.h @@ -0,0 +1,413 @@ +/* GStreamer byte writer + * + * Copyright (C) 2009 Sebastian Dröge . + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __FPI_BYTE_WRITER_H__ +#define __FPI_BYTE_WRITER_H__ + +#include "fpi-byte-reader.h" +#include + +G_BEGIN_DECLS + +#define FPI_BYTE_WRITER(writer) ((FpiByteWriter *) (writer)) + +/** + * FpiByteWriter: + * @parent: #FpiByteReader parent + * @alloc_size: Allocation size of the data + * @fixed: If %TRUE no reallocations are allowed + * @owned: If %FALSE no reallocations are allowed and copies of data are returned + * + * A byte writer instance. + */ +typedef struct { + FpiByteReader parent; + + guint alloc_size; + + gboolean fixed; + gboolean owned; + + /* < private > */ +} FpiByteWriter; + + +FpiByteWriter * fpi_byte_writer_new (void) G_GNUC_MALLOC; + + +FpiByteWriter * fpi_byte_writer_new_with_size (guint size, gboolean fixed) G_GNUC_MALLOC; + + +FpiByteWriter * fpi_byte_writer_new_with_data (guint8 *data, guint size, gboolean initialized) G_GNUC_MALLOC; + + +void fpi_byte_writer_init (FpiByteWriter *writer); + + +void fpi_byte_writer_init_with_size (FpiByteWriter *writer, guint size, gboolean fixed); + + +void fpi_byte_writer_init_with_data (FpiByteWriter *writer, guint8 *data, + guint size, gboolean initialized); + +void fpi_byte_writer_free (FpiByteWriter *writer); + + +guint8 * fpi_byte_writer_free_and_get_data (FpiByteWriter *writer); + + +void fpi_byte_writer_reset (FpiByteWriter *writer); + + +guint8 * fpi_byte_writer_reset_and_get_data (FpiByteWriter *writer); + +/** + * fpi_byte_writer_get_pos: + * @writer: #FpiByteWriter instance + * + * Returns: The current position of the read/write cursor + */ +/** + * fpi_byte_writer_set_pos: + * @writer: #FpiByteWriter instance + * @pos: new position + * + * Sets the current read/write cursor of @writer. The new position + * can only be between 0 and the current size. + * + * Returns: %TRUE if the new position could be set + */ +/** + * fpi_byte_writer_get_size: + * @writer: #FpiByteWriter instance + * + * Returns: The current, initialized size of the data + */ +static inline guint +fpi_byte_writer_get_pos (const FpiByteWriter *writer) +{ + return fpi_byte_reader_get_pos ((const FpiByteReader *) writer); +} + +static inline gboolean +fpi_byte_writer_set_pos (FpiByteWriter *writer, guint pos) +{ + return fpi_byte_reader_set_pos (FPI_BYTE_READER (writer), pos); +} + +static inline guint +fpi_byte_writer_get_size (const FpiByteWriter *writer) +{ + return fpi_byte_reader_get_size ((const FpiByteReader *) writer); +} + + +guint fpi_byte_writer_get_remaining (const FpiByteWriter *writer); + + +gboolean fpi_byte_writer_ensure_free_space (FpiByteWriter *writer, guint size); + + +gboolean fpi_byte_writer_put_uint8 (FpiByteWriter *writer, guint8 val); + + +gboolean fpi_byte_writer_put_int8 (FpiByteWriter *writer, gint8 val); + + +gboolean fpi_byte_writer_put_uint16_be (FpiByteWriter *writer, guint16 val); + + +gboolean fpi_byte_writer_put_uint16_le (FpiByteWriter *writer, guint16 val); + + +gboolean fpi_byte_writer_put_int16_be (FpiByteWriter *writer, gint16 val); + + +gboolean fpi_byte_writer_put_int16_le (FpiByteWriter *writer, gint16 val); + + +gboolean fpi_byte_writer_put_uint24_be (FpiByteWriter *writer, guint32 val); + + +gboolean fpi_byte_writer_put_uint24_le (FpiByteWriter *writer, guint32 val); + + +gboolean fpi_byte_writer_put_int24_be (FpiByteWriter *writer, gint32 val); + + +gboolean fpi_byte_writer_put_int24_le (FpiByteWriter *writer, gint32 val); + + +gboolean fpi_byte_writer_put_uint32_be (FpiByteWriter *writer, guint32 val); + + +gboolean fpi_byte_writer_put_uint32_le (FpiByteWriter *writer, guint32 val); + + +gboolean fpi_byte_writer_put_int32_be (FpiByteWriter *writer, gint32 val); + + +gboolean fpi_byte_writer_put_int32_le (FpiByteWriter *writer, gint32 val); + + +gboolean fpi_byte_writer_put_uint64_be (FpiByteWriter *writer, guint64 val); + + +gboolean fpi_byte_writer_put_uint64_le (FpiByteWriter *writer, guint64 val); + + +gboolean fpi_byte_writer_put_int64_be (FpiByteWriter *writer, gint64 val); + + +gboolean fpi_byte_writer_put_int64_le (FpiByteWriter *writer, gint64 val); + + +gboolean fpi_byte_writer_put_float32_be (FpiByteWriter *writer, gfloat val); + + +gboolean fpi_byte_writer_put_float32_le (FpiByteWriter *writer, gfloat val); + + +gboolean fpi_byte_writer_put_float64_be (FpiByteWriter *writer, gdouble val); + + +gboolean fpi_byte_writer_put_float64_le (FpiByteWriter *writer, gdouble val); + + +gboolean fpi_byte_writer_put_data (FpiByteWriter *writer, const guint8 *data, guint size); + + +gboolean fpi_byte_writer_fill (FpiByteWriter *writer, guint8 value, guint size); + + +gboolean fpi_byte_writer_put_string_utf8 (FpiByteWriter *writer, const gchar *data); + + +gboolean fpi_byte_writer_put_string_utf16 (FpiByteWriter *writer, const guint16 *data); + + +gboolean fpi_byte_writer_put_string_utf32 (FpiByteWriter *writer, const guint32 *data); + +/** + * fpi_byte_writer_put_string: + * @writer: #FpiByteWriter instance + * @data: (in) (array zero-terminated=1): Null terminated string + * + * Write a NUL-terminated string to @writer (including the terminator). The + * string is assumed to be in an 8-bit encoding (e.g. ASCII,UTF-8 or + * ISO-8859-1). + * + * Returns: %TRUE if the string could be written + */ +#define fpi_byte_writer_put_string(writer, data) \ + fpi_byte_writer_put_string_utf8(writer, data) + +static inline guint +fpi_byte_writer_next_pow2 (guint n) +{ + guint ret = 16; + + /* We start with 16, smaller allocations make no sense */ + + while (ret < n && ret > 0) + ret <<= 1; + + return ret ? ret : n; +} + +static inline gboolean +fpi_byte_writer_ensure_free_space_inline (FpiByteWriter * writer, guint size) +{ + gpointer data; + + if (G_LIKELY (size <= writer->alloc_size - writer->parent.byte)) + return TRUE; + if (G_UNLIKELY (writer->fixed || !writer->owned)) + return FALSE; + if (G_UNLIKELY (writer->parent.byte > G_MAXUINT - size)) + return FALSE; + + writer->alloc_size = fpi_byte_writer_next_pow2 (writer->parent.byte + size); + data = g_try_realloc ((guint8 *) writer->parent.data, writer->alloc_size); + if (G_UNLIKELY (data == NULL)) + return FALSE; + + writer->parent.data = (guint8 *) data; + + return TRUE; +} + +#define __FPI_BYTE_WRITER_CREATE_WRITE_FUNC(bits,type,name,write_func) \ +static inline void \ +fpi_byte_writer_put_##name##_unchecked (FpiByteWriter *writer, type val) \ +{ \ + guint8 *write_data; \ + \ + write_data = (guint8 *) writer->parent.data + writer->parent.byte; \ + write_func (write_data, val); \ + writer->parent.byte += bits/8; \ + writer->parent.size = MAX (writer->parent.size, writer->parent.byte); \ +} \ +\ +static inline gboolean \ +fpi_byte_writer_put_##name##_inline (FpiByteWriter *writer, type val) \ +{ \ + g_return_val_if_fail (writer != NULL, FALSE); \ + \ + if (G_UNLIKELY (!fpi_byte_writer_ensure_free_space_inline(writer, bits/8))) \ + return FALSE; \ + \ + fpi_byte_writer_put_##name##_unchecked (writer, val); \ + \ + return TRUE; \ +} + +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (8, guint8, uint8, FP_WRITE_UINT8) +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (8, gint8, int8, FP_WRITE_UINT8) +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (16, guint16, uint16_le, FP_WRITE_UINT16_LE) +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (16, guint16, uint16_be, FP_WRITE_UINT16_BE) +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (16, gint16, int16_le, FP_WRITE_UINT16_LE) +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (16, gint16, int16_be, FP_WRITE_UINT16_BE) +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (24, guint32, uint24_le, FP_WRITE_UINT24_LE) +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (24, guint32, uint24_be, FP_WRITE_UINT24_BE) +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (24, gint32, int24_le, FP_WRITE_UINT24_LE) +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (24, gint32, int24_be, FP_WRITE_UINT24_BE) +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (32, guint32, uint32_le, FP_WRITE_UINT32_LE) +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (32, guint32, uint32_be, FP_WRITE_UINT32_BE) +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (32, gint32, int32_le, FP_WRITE_UINT32_LE) +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (32, gint32, int32_be, FP_WRITE_UINT32_BE) +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (64, guint64, uint64_le, FP_WRITE_UINT64_LE) +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (64, guint64, uint64_be, FP_WRITE_UINT64_BE) +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (64, gint64, int64_le, FP_WRITE_UINT64_LE) +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (64, gint64, int64_be, FP_WRITE_UINT64_BE) + +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (32, gfloat, float32_be, FP_WRITE_FLOAT_BE) +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (32, gfloat, float32_le, FP_WRITE_FLOAT_LE) +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (64, gdouble, float64_be, FP_WRITE_DOUBLE_BE) +__FPI_BYTE_WRITER_CREATE_WRITE_FUNC (64, gdouble, float64_le, FP_WRITE_DOUBLE_LE) + +#undef __FPI_BYTE_WRITER_CREATE_WRITE_FUNC + +static inline void +fpi_byte_writer_put_data_unchecked (FpiByteWriter * writer, const guint8 * data, + guint size) +{ + memcpy ((guint8 *) & writer->parent.data[writer->parent.byte], data, size); + writer->parent.byte += size; + writer->parent.size = MAX (writer->parent.size, writer->parent.byte); +} + +static inline gboolean +fpi_byte_writer_put_data_inline (FpiByteWriter * writer, const guint8 * data, + guint size) +{ + g_return_val_if_fail (writer != NULL, FALSE); + + if (G_UNLIKELY (!fpi_byte_writer_ensure_free_space_inline (writer, size))) + return FALSE; + + fpi_byte_writer_put_data_unchecked (writer, data, size); + + return TRUE; +} + +static inline void +fpi_byte_writer_fill_unchecked (FpiByteWriter * writer, guint8 value, guint size) +{ + memset ((guint8 *) & writer->parent.data[writer->parent.byte], value, size); + writer->parent.byte += size; + writer->parent.size = MAX (writer->parent.size, writer->parent.byte); +} + +static inline gboolean +fpi_byte_writer_fill_inline (FpiByteWriter * writer, guint8 value, guint size) +{ + g_return_val_if_fail (writer != NULL, FALSE); + + if (G_UNLIKELY (!fpi_byte_writer_ensure_free_space_inline (writer, size))) + return FALSE; + + fpi_byte_writer_fill_unchecked (writer, value, size); + + return TRUE; +} + +#ifndef FPI_BYTE_WRITER_DISABLE_INLINES + +/* we use defines here so we can add the G_LIKELY() */ + +#define fpi_byte_writer_ensure_free_space(writer, size) \ + G_LIKELY (fpi_byte_writer_ensure_free_space_inline (writer, size)) +#define fpi_byte_writer_put_uint8(writer, val) \ + G_LIKELY (fpi_byte_writer_put_uint8_inline (writer, val)) +#define fpi_byte_writer_put_int8(writer, val) \ + G_LIKELY (fpi_byte_writer_put_int8_inline (writer, val)) +#define fpi_byte_writer_put_uint16_be(writer, val) \ + G_LIKELY (fpi_byte_writer_put_uint16_be_inline (writer, val)) +#define fpi_byte_writer_put_uint16_le(writer, val) \ + G_LIKELY (fpi_byte_writer_put_uint16_le_inline (writer, val)) +#define fpi_byte_writer_put_int16_be(writer, val) \ + G_LIKELY (fpi_byte_writer_put_int16_be_inline (writer, val)) +#define fpi_byte_writer_put_int16_le(writer, val) \ + G_LIKELY (fpi_byte_writer_put_int16_le_inline (writer, val)) +#define fpi_byte_writer_put_uint24_be(writer, val) \ + G_LIKELY (fpi_byte_writer_put_uint24_be_inline (writer, val)) +#define fpi_byte_writer_put_uint24_le(writer, val) \ + G_LIKELY (fpi_byte_writer_put_uint24_le_inline (writer, val)) +#define fpi_byte_writer_put_int24_be(writer, val) \ + G_LIKELY (fpi_byte_writer_put_int24_be_inline (writer, val)) +#define fpi_byte_writer_put_int24_le(writer, val) \ + G_LIKELY (fpi_byte_writer_put_int24_le_inline (writer, val)) +#define fpi_byte_writer_put_uint32_be(writer, val) \ + G_LIKELY (fpi_byte_writer_put_uint32_be_inline (writer, val)) +#define fpi_byte_writer_put_uint32_le(writer, val) \ + G_LIKELY (fpi_byte_writer_put_uint32_le_inline (writer, val)) +#define fpi_byte_writer_put_int32_be(writer, val) \ + G_LIKELY (fpi_byte_writer_put_int32_be_inline (writer, val)) +#define fpi_byte_writer_put_int32_le(writer, val) \ + G_LIKELY (fpi_byte_writer_put_int32_le_inline (writer, val)) +#define fpi_byte_writer_put_uint64_be(writer, val) \ + G_LIKELY (fpi_byte_writer_put_uint64_be_inline (writer, val)) +#define fpi_byte_writer_put_uint64_le(writer, val) \ + G_LIKELY (fpi_byte_writer_put_uint64_le_inline (writer, val)) +#define fpi_byte_writer_put_int64_be(writer, val) \ + G_LIKELY (fpi_byte_writer_put_int64_be_inline (writer, val)) +#define fpi_byte_writer_put_int64_le(writer, val) \ + G_LIKELY (fpi_byte_writer_put_int64_le_inline (writer, val)) + +#define fpi_byte_writer_put_float32_be(writer, val) \ + G_LIKELY (fpi_byte_writer_put_float32_be_inline (writer, val)) +#define fpi_byte_writer_put_float32_le(writer, val) \ + G_LIKELY (fpi_byte_writer_put_float32_le_inline (writer, val)) +#define fpi_byte_writer_put_float64_be(writer, val) \ + G_LIKELY (fpi_byte_writer_put_float64_be_inline (writer, val)) +#define fpi_byte_writer_put_float64_le(writer, val) \ + G_LIKELY (fpi_byte_writer_put_float64_le_inline (writer, val)) + +#define fpi_byte_writer_put_data(writer, data, size) \ + G_LIKELY (fpi_byte_writer_put_data_inline (writer, data, size)) +#define fpi_byte_writer_fill(writer, val, size) \ + G_LIKELY (fpi_byte_writer_fill_inline (writer, val, size)) + +#endif + +G_END_DECLS + +#endif /* __FPI_BYTE_WRITER_H__ */ diff --git a/libfprint/fpi-context.h b/libfprint/fpi-context.h new file mode 100644 index 00000000..c5a10750 --- /dev/null +++ b/libfprint/fpi-context.h @@ -0,0 +1,33 @@ +/* + * FpContext - A FPrint context + * Copyright (C) 2019 Benjamin Berg + * + * 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 +#include "fp-context.h" + +/** + * fpi_get_driver_types: + * @drivers: #GArray to be filled with all driver types + * + * This function is purely for private used. It is solely part of the public + * API as it is useful during build time. + * + * Stability: private + */ +void fpi_get_driver_types (GArray *drivers); diff --git a/libfprint/fpi-core.c b/libfprint/fpi-core.c deleted file mode 100644 index 6009c82d..00000000 --- a/libfprint/fpi-core.c +++ /dev/null @@ -1,835 +0,0 @@ -/* - * Core functions for libfprint - * Copyright (C) 2007-2008 Daniel Drake - * - * 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 -#include -#include -#include - -#include -#include - -#include "fp_internal.h" - -libusb_context *fpi_usb_ctx = NULL; -GSList *opened_devices = NULL; - -/** - * SECTION:discovery - * @title: Device discovery - * @short_description: Device discovery functions - * - * These functions allow you to scan the system for supported fingerprint - * scanning hardware. This is your starting point when integrating libfprint - * into your software. - * - * When you've identified a discovered device that you would like to control, - * you can open it with fp_dev_open(). Note that discovered devices may no - * longer be available at the time when you want to open them, for example - * the user may have unplugged the device. - */ - -/** - * SECTION:drv - * @title: Driver operations - * @short_description: Driver operation functions - * - * Internally, libfprint is abstracted into various drivers to communicate - * with the different types of supported fingerprint readers. libfprint works - * hard so that you don't have to care about these internal abstractions, - * however there are some situations where you may be interested in a little - * behind-the-scenes driver info. - * - * You can obtain the driver for a device using fp_dev_get_driver(), which - * you can pass to the functions documented on this page. - */ - -/** - * SECTION:dev - * @title: Devices operations - * @short_description: Device operation functions - * - * In order to interact with fingerprint scanners, your software will - * interface primarily with libfprint's representation of devices, detailed - * on this page. - * - * # Enrolling # {#enrolling} - * - * Enrolling is represented within libfprint as a multi-stage process. This - * slightly complicates things for application developers, but is required - * for a smooth process. - * - * Some devices require the user to scan their finger multiple times in - * order to complete the enrollment process. libfprint must return control - * to your application in-between each scan in order for your application to - * instruct the user to swipe their finger again. Each scan is referred to - * as a stage, so a device that requires 3 scans for enrollment corresponds - * to you running 3 enrollment stages using libfprint. - * - * The fp_dev_get_nr_enroll_stages() function can be used to find out how - * many enroll stages are needed. - * - * In order to complete an enroll stage, you call an enroll function such - * as fp_enroll_finger(). The return of this function does not necessarily - * indicate that a stage has completed though, as the user may not have - * produced a good enough scan. Each stage may have to be retried several - * times. - * - * The exact semantics of the enroll functions are described in the - * fp_enroll_finger() documentation. You should pay careful attention to the - * details. - * - * # Imaging # {#imaging} - * - * libfprint provides you with some ways to retrieve images of scanned - * fingers, such as the fp_dev_img_capture() function, or some enroll/verify - * function variants which provide images. You may wish to do something with - * such images in your application. - * - * However, you must be aware that not all hardware supported by libfprint - * operates like this. Most hardware does operate simply by sending - * fingerprint images to the host computer for further processing, but some - * devices do all fingerprint processing in hardware and do not present images - * to the host computer. - * - * You can use fp_dev_supports_imaging() to see if image capture is possible - * on a particular device. Your application must be able to cope with the - * fact that libfprint does support regular operations (e.g. enrolling and - * verification) on some devices which do not provide images. - */ - -/** - * SECTION:fpi-core - * @title: Driver structures - * @short_description: Driver structures - * - * Driver structures need to be defined inside each driver in - * order for the core library to know what function to call, and the capabilities - * of the driver and the devices it supports. - */ - -/** - * SECTION:fpi-core-img - * @title: Image driver structures - * @short_description: Image driver structures - * - * Image driver structures need to be defined inside each image driver in - * order for the core library to know what function to call, and the capabilities - * of the driver and the devices it supports. Its structure is based off the - * #fp_driver struct. - */ - -static GSList *registered_drivers = NULL; - -static void register_driver(struct fp_driver *drv) -{ - if (drv->id == 0) { - fp_err("not registering driver %s: driver ID is 0", drv->name); - return; - } - registered_drivers = g_slist_prepend(registered_drivers, (gpointer) drv); - fp_dbg("registered driver %s", drv->name); -} - -#include "drivers_arrays.h" - -static void register_drivers(void) -{ - unsigned int i; - - for (i = 0; i < G_N_ELEMENTS(primitive_drivers); i++) - register_driver(primitive_drivers[i]); - - for (i = 0; i < G_N_ELEMENTS(img_drivers); i++) { - struct fp_img_driver *imgdriver = img_drivers[i]; - fpi_img_driver_setup(imgdriver); - register_driver(&imgdriver->driver); - } -} - -API_EXPORTED struct fp_driver **fprint_get_drivers (void) -{ - GPtrArray *array; - unsigned int i; - - array = g_ptr_array_new (); - for (i = 0; i < G_N_ELEMENTS(primitive_drivers); i++) - g_ptr_array_add (array, primitive_drivers[i]); - - for (i = 0; i < G_N_ELEMENTS(img_drivers); i++) - g_ptr_array_add (array, &(img_drivers[i]->driver)); - - /* Add a null item terminating the array */ - g_ptr_array_add (array, NULL); - - return (struct fp_driver **) g_ptr_array_free (array, FALSE); -} - -static struct fp_driver *find_supporting_driver(libusb_device *udev, - const struct usb_id **usb_id, uint32_t *devtype) -{ - int ret; - GSList *elem = registered_drivers; - struct libusb_device_descriptor dsc; - - const struct usb_id *best_usb_id; - struct fp_driver *best_drv; - uint32_t best_devtype; - int drv_score = 0; - - ret = libusb_get_device_descriptor(udev, &dsc); - if (ret < 0) { - fp_err("Failed to get device descriptor"); - return NULL; - } - - best_drv = NULL; - best_devtype = 0; - - do { - struct fp_driver *drv = elem->data; - uint32_t type = 0; - const struct usb_id *id; - - for (id = drv->id_table; id->vendor; id++) { - if (dsc.idVendor == id->vendor && dsc.idProduct == id->product) { - if (drv->discover) { - int r = drv->discover(&dsc, &type); - if (r < 0) - fp_err("%s discover failed, code %d", drv->name, r); - if (r <= 0) - continue; - /* Has a discover function, and matched our device */ - drv_score = 100; - } else { - /* Already got a driver as good */ - if (drv_score >= 50) - continue; - drv_score = 50; - } - fp_dbg("driver %s supports USB device %04x:%04x", - drv->name, id->vendor, id->product); - best_usb_id = id; - best_drv = drv; - best_devtype = type; - - /* We found the best possible driver */ - if (drv_score == 100) - break; - } - } - } while ((elem = g_slist_next(elem))); - - if (best_drv != NULL) { - fp_dbg("selected driver %s supports USB device %04x:%04x", - best_drv->name, dsc.idVendor, dsc.idProduct); - *devtype = best_devtype; - *usb_id = best_usb_id; - } - - return best_drv; -} - -static struct fp_dscv_dev *discover_dev(libusb_device *udev) -{ - const struct usb_id *usb_id; - struct fp_driver *drv; - struct fp_dscv_dev *ddev; - uint32_t devtype; - - drv = find_supporting_driver(udev, &usb_id, &devtype); - - if (!drv) - return NULL; - - ddev = g_malloc0(sizeof(*ddev)); - ddev->drv = drv; - ddev->udev = udev; - ddev->driver_data = usb_id->driver_data; - ddev->devtype = devtype; - return ddev; -} - -/** - * fp_discover_devs: - * - * Scans the system and returns a list of discovered devices. This is your - * entry point into finding a fingerprint reader to operate. Note that %NULL - * is only returned on error. When there are no supported readers available, - * an empty list is returned instead. - * - * Returns: a nul-terminated list of discovered devices or %NULL on error. - * Must be freed with fp_dscv_devs_free() after use. - */ -API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void) -{ - GPtrArray *tmparray; - libusb_device *udev; - libusb_device **devs; - int r; - int i = 0; - - g_return_val_if_fail (registered_drivers != NULL, NULL); - - r = libusb_get_device_list(fpi_usb_ctx, &devs); - if (r < 0) { - fp_err("couldn't enumerate USB devices, error %d", r); - return NULL; - } - - tmparray = g_ptr_array_new (); - - /* Check each device against each driver, temporarily storing successfully - * discovered devices in a GPtrArray. */ - while ((udev = devs[i++]) != NULL) { - struct fp_dscv_dev *ddev = discover_dev(udev); - if (!ddev) - continue; - /* discover_dev() doesn't hold a reference to the udev, - * so increase the reference for ddev to hold this ref */ - libusb_ref_device(udev); - g_ptr_array_add (tmparray, (gpointer) ddev); - } - libusb_free_device_list(devs, 1); - - /* Convert our temporary array into a standard NULL-terminated pointer - * array. */ - g_ptr_array_add (tmparray, NULL); - return (struct fp_dscv_dev **) g_ptr_array_free (tmparray, FALSE); -} - -/** - * fp_dscv_devs_free: - * @devs: the list of discovered devices. If %NULL, function simply - * returns. - * - * Free a list of discovered devices. This function destroys the list and all - * discovered devices that it included, so make sure you have opened your - * discovered device before freeing the list. - */ -API_EXPORTED void fp_dscv_devs_free(struct fp_dscv_dev **devs) -{ - int i; - if (!devs) - return; - - for (i = 0; devs[i]; i++) { - libusb_unref_device(devs[i]->udev); - g_free(devs[i]); - } - g_free(devs); -} - -/** - * fp_dscv_dev_get_driver: - * @dev: the discovered device - * - * Gets the #fp_driver for a discovered device. - * - * Returns: the driver backing the device - */ -API_EXPORTED struct fp_driver *fp_dscv_dev_get_driver(struct fp_dscv_dev *dev) -{ - g_return_val_if_fail(dev, NULL); - - return dev->drv; -} - -/** - * fp_dscv_dev_get_driver_id: - * @dev: a discovered fingerprint device - * - * Returns a unique driver identifier for the underlying driver - * for that device. - * - * Returns: the ID for #dev - */ -API_EXPORTED uint16_t fp_dscv_dev_get_driver_id(struct fp_dscv_dev *dev) -{ - g_return_val_if_fail(dev, 0); - - return fp_driver_get_driver_id(fp_dscv_dev_get_driver(dev)); -} - -/** - * fp_dscv_dev_get_devtype: - * @dev: the discovered device - * - * Gets the [devtype](advanced-topics.html#device-types) for a discovered device. - * - * Returns: the devtype of the device - */ -API_EXPORTED uint32_t fp_dscv_dev_get_devtype(struct fp_dscv_dev *dev) -{ - g_return_val_if_fail(dev, 0); - - return dev->devtype; -} - -enum fp_print_data_type fpi_driver_get_data_type(struct fp_driver *drv) -{ - switch (drv->type) { - case DRIVER_PRIMITIVE: - return PRINT_DATA_RAW; - case DRIVER_IMAGING: - return PRINT_DATA_NBIS_MINUTIAE; - default: - fp_err("unrecognised drv type %d", drv->type); - return PRINT_DATA_RAW; - } -} - -/** - * fp_dscv_dev_supports_print_data: - * @dev: the discovered device - * @print: the print for compatibility checking - * - * Determines if a specific #fp_print_data stored print appears to be - * compatible with a discovered device. - * - * Returns: 1 if the print is compatible with the device, 0 otherwise - */ -API_EXPORTED int fp_dscv_dev_supports_print_data(struct fp_dscv_dev *dev, - struct fp_print_data *print) -{ - g_return_val_if_fail(dev, 0); - g_return_val_if_fail(print, 0); - - return fpi_print_data_compatible(dev->drv->id, dev->devtype, - fpi_driver_get_data_type(dev->drv), print->driver_id, print->devtype, - print->type); -} - -/** - * fp_dscv_dev_supports_dscv_print: - * @dev: the discovered device - * @print: the discovered print for compatibility checking - * - * Determines if a specific #fp_dscv_print discovered print appears to be - * compatible with a discovered device. - * - * Returns: 1 if the print is compatible with the device, 0 otherwise - * - * Deprecated: Do not use. - */ -API_EXPORTED int fp_dscv_dev_supports_dscv_print(struct fp_dscv_dev *dev, - struct fp_dscv_print *print) -{ - g_return_val_if_fail(dev, 0); - g_return_val_if_fail(print, 0); - - return fpi_print_data_compatible(dev->drv->id, dev->devtype, 0, - print->driver_id, print->devtype, 0); -} - -/** - * fp_dscv_dev_for_print_data: - * @devs: a list of discovered devices - * @print: the print under inspection - * - * Searches a list of discovered devices for a device that appears to be - * compatible with a #fp_print_data stored print. - * - * Returns: the first discovered device that appears to support the print, or - * %NULL if no apparently compatible devices could be found - * - * Deprecated: Do not use. - */ -API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_print_data(struct fp_dscv_dev **devs, - struct fp_print_data *print) -{ - struct fp_dscv_dev *ddev; - int i; - - g_return_val_if_fail(devs, NULL); - g_return_val_if_fail(print, NULL); - - for (i = 0; (ddev = devs[i]); i++) - if (fp_dscv_dev_supports_print_data(ddev, print)) - return ddev; - return NULL; -} - -/** - * fp_dscv_dev_for_dscv_print: - * @devs: a list of discovered devices - * @print: the print under inspection - * - * Searches a list of discovered devices for a device that appears to be - * compatible with a #fp_dscv_print discovered print. - * - * Returns: the first discovered device that appears to support the print, or - * %NULL if no apparently compatible devices could be found - * - * Deprecated: Do not use. - */ -API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_dscv_print(struct fp_dscv_dev **devs, - struct fp_dscv_print *print) -{ - struct fp_dscv_dev *ddev; - int i; - - g_return_val_if_fail(devs, NULL); - g_return_val_if_fail(print, NULL); - - for (i = 0; (ddev = devs[i]); i++) { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - if (fp_dscv_dev_supports_dscv_print(ddev, print)) - return ddev; -#pragma GCC diagnostic pop - } - return NULL; -} - -/** - * fp_dev_get_driver: - * @dev: the struct #fp_dev device - * - * Get the #fp_driver for a fingerprint device. - * - * Returns: the driver controlling the device - */ -API_EXPORTED struct fp_driver *fp_dev_get_driver(struct fp_dev *dev) -{ - g_return_val_if_fail(dev, NULL); - - return dev->drv; -} - -/** - * fp_dev_get_nr_enroll_stages: - * @dev: the struct #fp_dev device - * - * Gets the number of [enroll stages](intro.html#enrollment) required to enroll a - * fingerprint with the device. - * - * Returns: the number of enroll stages - */ -API_EXPORTED int fp_dev_get_nr_enroll_stages(struct fp_dev *dev) -{ - g_return_val_if_fail(dev, 0); - - return dev->nr_enroll_stages; -} - -/** - * fp_dev_get_devtype: - * @dev: the struct #fp_dev device - * - * Gets the [devtype](advanced-topics.html#device-types) for a device. - * - * Returns: the devtype - */ -API_EXPORTED uint32_t fp_dev_get_devtype(struct fp_dev *dev) -{ - g_return_val_if_fail(dev, 0); - - return dev->devtype; -} - -/** - * fp_dev_supports_print_data: - * @dev: the struct #fp_dev device - * @data: the stored print - * - * Determines if a stored print is compatible with a certain device. - * - * Returns: 1 if the print is compatible with the device, 0 if not - */ -API_EXPORTED int fp_dev_supports_print_data(struct fp_dev *dev, - struct fp_print_data *data) -{ - g_return_val_if_fail(dev, 0); - g_return_val_if_fail(data, 0); - - return fpi_print_data_compatible(dev->drv->id, dev->devtype, - fpi_driver_get_data_type(dev->drv), data->driver_id, data->devtype, - data->type); -} - -/** - * fp_dev_supports_dscv_print: - * @dev: the struct #fp_dev device - * @print: the discovered print - * - * Determines if a #fp_dscv_print discovered print appears to be compatible - * with a certain device. - * - * Returns: 1 if the print is compatible with the device, 0 if not - * - * Deprecated: Do not use. - */ -API_EXPORTED int fp_dev_supports_dscv_print(struct fp_dev *dev, - struct fp_dscv_print *print) -{ - g_return_val_if_fail(dev, 0); - g_return_val_if_fail(print, 0); - - return fpi_print_data_compatible(dev->drv->id, dev->devtype, - 0, print->driver_id, print->devtype, 0); -} - -/** - * fp_driver_get_name: - * @drv: the driver - * - * Retrieves the name of the driver. For example: "upekts" - * - * Returns: the driver name. Must not be modified or freed. - */ -API_EXPORTED const char *fp_driver_get_name(struct fp_driver *drv) -{ - g_return_val_if_fail(drv, NULL); - - return drv->name; -} - -/** - * fp_driver_get_full_name: - * @drv: the driver - * - * Retrieves a descriptive name of the driver. For example: "UPEK TouchStrip" - * - * Returns: the descriptive name. Must not be modified or freed. - */ -API_EXPORTED const char *fp_driver_get_full_name(struct fp_driver *drv) -{ - g_return_val_if_fail(drv, NULL); - - return drv->full_name; -} - -/** - * fp_driver_get_driver_id: - * @drv: the driver - * - * Retrieves the driver ID code for a driver. - * - * Returns: the driver ID - */ -API_EXPORTED uint16_t fp_driver_get_driver_id(struct fp_driver *drv) -{ - g_return_val_if_fail(drv, 0); - - return drv->id; -} - -/** - * fp_driver_get_scan_type: - * @drv: the driver - * - * Retrieves the scan type for the devices associated with the driver. - * - * Returns: the scan type - */ -API_EXPORTED enum fp_scan_type fp_driver_get_scan_type(struct fp_driver *drv) -{ - g_return_val_if_fail(drv, FP_SCAN_TYPE_PRESS); - - return drv->scan_type; -} - -/** - * fp_driver_supports_imaging: - * @drv: the driver - * - * Determines if a driver has imaging capabilities. If a driver has imaging - * capabilities you are able to perform imaging operations such as retrieving - * scan images using fp_dev_img_capture(). However, not all drivers support - * imaging devices – some do all processing in hardware. This function will - * indicate which class a device in question falls into. - * - * Returns: 1 if the device is an imaging device, 0 if the device does not - * provide images to the host computer - */ -API_EXPORTED int fp_driver_supports_imaging(struct fp_driver *drv) -{ - g_return_val_if_fail(drv, 0); - - return drv->capture_start != NULL; -} - -/** - * fp_dev_supports_imaging: - * @dev: the struct #fp_dev device - * - * Determines if a device has imaging capabilities. If a device has imaging - * capabilities you are able to perform imaging operations such as retrieving - * scan images using fp_dev_img_capture(). However, not all devices are - * imaging devices – some do all processing in hardware. This function will - * indicate which class a device in question falls into. - * - * Returns: 1 if the device is an imaging device, 0 if the device does not - * provide images to the host computer - */ -API_EXPORTED int fp_dev_supports_imaging(struct fp_dev *dev) -{ - g_return_val_if_fail(dev, 0); - - return dev->drv->capture_start != NULL; -} - -/** - * fp_dev_supports_identification: - * @dev: the struct #fp_dev device - * - * Determines if a device is capable of [identification](intro.html#identification) - * through fp_identify_finger() and similar. Not all devices support this - * functionality. - * - * Returns: 1 if the device is capable of identification, 0 otherwise. - */ -API_EXPORTED int fp_dev_supports_identification(struct fp_dev *dev) -{ - g_return_val_if_fail(dev, 0); - - return dev->drv->identify_start != NULL; -} - -/** - * fp_dev_get_img_width: - * @dev: the struct #fp_dev device - * - * Gets the expected width of images that will be captured from the device. - * This function will return -1 for devices that are not - * [imaging devices](libfprint-Devices-operations.html#imaging). If the width of images from this device - * can vary, 0 will be returned. - * - * Returns: the expected image width, or 0 for variable, or -1 for non-imaging - * devices. - */ -API_EXPORTED int fp_dev_get_img_width(struct fp_dev *dev) -{ - g_return_val_if_fail(dev, -1); - - if (!dev->img_dev) { - fp_dbg("get image width for non-imaging device"); - return -1; - } - - return fpi_imgdev_get_img_width(dev->img_dev); -} - -/** - * fp_dev_get_img_height: - * @dev: the struct #fp_dev device - * - * Gets the expected height of images that will be captured from the device. - * This function will return -1 for devices that are not - * [imaging devices](libfprint-Devices-operations.html#imaging). If the height of images from this device - * can vary, 0 will be returned. - * - * Returns: the expected image height, or 0 for variable, or -1 for non-imaging - * devices. - */ -API_EXPORTED int fp_dev_get_img_height(struct fp_dev *dev) -{ - g_return_val_if_fail(dev, -1); - - if (!dev->img_dev) { - fp_dbg("get image height for non-imaging device"); - return -1; - } - - return fpi_imgdev_get_img_height(dev->img_dev); -} - -/** - * fp_set_debug: - * @level: the verbosity level - * - * This call does nothing, see fp_init() for details. - */ -API_EXPORTED void fp_set_debug(int level) -{ - /* Nothing */ -} - -/** - * fp_init: - * - * Initialise libfprint. This function must be called before you attempt to - * use the library in any way. - * - * To enable debug output of libfprint specifically, use GLib's `G_MESSAGES_DEBUG` - * environment variable as explained in [Running and debugging GLib Applications](https://developer.gnome.org/glib/stable/glib-running.html#G_MESSAGES_DEBUG). - * - * The log domains used in libfprint are either `libfprint` or `libfprint-FP_COMPONENT` - * where `FP_COMPONENT` is defined in the source code for each driver, or component - * of the library. Starting with `all` and trimming down is advised. - * - * To enable debugging of libusb, for USB-based fingerprint reader drivers, use - * libusb's `LIBUSB_DEBUG` environment variable as explained in the - * [libusb-1.0 API Reference](http://libusb.sourceforge.net/api-1.0/#msglog). - * - * Example: - * - * ``` - * LIBUSB_DEBUG=4 G_MESSAGES_DEBUG=all my-libfprint-application - * ``` - * - * Returns: 0 on success, non-zero on error. - */ -API_EXPORTED int fp_init(void) -{ - int r; - G_DEBUG_HERE(); - - r = libusb_init(&fpi_usb_ctx); - if (r < 0) - return r; - - register_drivers(); - fpi_poll_init(); - return 0; -} - -/** - * fp_exit: - * - * Deinitialise libfprint. This function should be called during your program - * exit sequence. You must not use any libfprint functions after calling this - * function, unless you call fp_init() again. - */ -API_EXPORTED void fp_exit(void) -{ - G_DEBUG_HERE(); - - if (opened_devices) { - GSList *copy = g_slist_copy(opened_devices); - GSList *elem = copy; - fp_dbg("naughty app left devices open on exit!"); - - do - fp_dev_close((struct fp_dev *) elem->data); - while ((elem = g_slist_next(elem))); - - g_slist_free(copy); - g_slist_free(opened_devices); - opened_devices = NULL; - } - - fpi_data_exit(); - fpi_poll_exit(); - g_slist_free(registered_drivers); - registered_drivers = NULL; - libusb_exit(fpi_usb_ctx); -} - diff --git a/libfprint/fpi-core.h b/libfprint/fpi-core.h deleted file mode 100644 index d183f885..00000000 --- a/libfprint/fpi-core.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2007-2008 Daniel Drake - * Copyright (C) 2018 Bastien Nocera - * - * 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 - */ - -#ifndef __FPI_CORE_H__ -#define __FPI_CORE_H__ - -#include -#include "fpi-dev-img.h" - -/** - * usb_id: - * @vendor: the USB vendor ID - * @product: the USB product ID - * @driver_data: data to differentiate devices of different - * vendor and product IDs. - * - * The struct #usb_id is used to declare devices supported by a - * particular driver. The @driver_data information is used to - * differentiate different models of devices which only need - * small changes compared to the default driver behaviour to function. - * - * For example, a device might have a different initialisation from - * the stock device, so the driver could do: - * - * |[ - * if (driver_data == MY_DIFFERENT_DEVICE_QUIRK) { - * ... - * } else { - * ... - * } - * ]| - * - * The default value is zero, so the @driver_data needs to be a - * non-zero to be useful. - */ -struct usb_id { - uint16_t vendor; - uint16_t product; - unsigned long driver_data; -}; - -/** - * fp_driver_type: - * @DRIVER_PRIMITIVE: primitive, non-imaging, driver - * @DRIVER_IMAGING: imaging driver - * - * The type of device the driver supports. - */ -enum fp_driver_type { - DRIVER_PRIMITIVE = 0, - DRIVER_IMAGING = 1, -}; - -struct fp_driver { - const uint16_t id; - const char *name; - const char *full_name; - const struct usb_id * const id_table; - enum fp_driver_type type; - enum fp_scan_type scan_type; - - /* Device operations */ - int (*discover)(struct libusb_device_descriptor *dsc, uint32_t *devtype); - int (*open)(struct fp_dev *dev, unsigned long driver_data); - void (*close)(struct fp_dev *dev); - int (*enroll_start)(struct fp_dev *dev); - int (*enroll_stop)(struct fp_dev *dev); - int (*verify_start)(struct fp_dev *dev); - int (*verify_stop)(struct fp_dev *dev, gboolean iterating); - int (*identify_start)(struct fp_dev *dev); - int (*identify_stop)(struct fp_dev *dev, gboolean iterating); - int (*capture_start)(struct fp_dev *dev); - int (*capture_stop)(struct fp_dev *dev); -}; - -/** - * FpiImgDriverFlags: - * @FP_IMGDRV_SUPPORTS_UNCONDITIONAL_CAPTURE: Whether the driver supports - * unconditional image capture. No driver currently does. - * - * Flags used in the #fp_img_driver to advertise the capabilities of drivers. - */ -typedef enum { - FP_IMGDRV_SUPPORTS_UNCONDITIONAL_CAPTURE = 1 << 0 -} FpiImgDriverFlags; - -struct fp_img_driver { - struct fp_driver driver; - FpiImgDriverFlags flags; - int img_width; - int img_height; - int bz3_threshold; - - /* Device operations */ - int (*open)(struct fp_img_dev *dev, unsigned long driver_data); - void (*close)(struct fp_img_dev *dev); - int (*activate)(struct fp_img_dev *dev); - int (*change_state)(struct fp_img_dev *dev, enum fp_imgdev_state state); - void (*deactivate)(struct fp_img_dev *dev); -}; - -#endif diff --git a/libfprint/fpi-data.c b/libfprint/fpi-data.c deleted file mode 100644 index c19142ac..00000000 --- a/libfprint/fpi-data.c +++ /dev/null @@ -1,900 +0,0 @@ -/* - * Fingerprint data handling and storage - * Copyright (C) 2007 Daniel Drake - * - * 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 -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "fp_internal.h" - -#define DIR_PERMS 0700 - -struct fpi_print_data_fp2 { - char prefix[3]; - uint16_t driver_id; - uint32_t devtype; - unsigned char data_type; - unsigned char data[0]; -} __attribute__((__packed__)); - -struct fpi_print_data_item_fp2 { - uint32_t length; - unsigned char data[0]; -} __attribute__((__packed__)); - -/** - * SECTION: print_data - * @title: Stored prints - * @short_description: Stored prints functions - * - * Stored prints are represented by a structure named #fp_print_data. - * Stored prints are originally obtained from an enrollment function such as - * fp_enroll_finger(). - * - * This page documents the various operations you can do with a stored print. - * Note that by default, "stored prints" are not actually stored anywhere - * except in RAM. Storage needs to be handled by the API user by using the - * fp_print_data_get_data() and fp_print_data_from_data(). This API allows - * to convert print data into byte strings, and to reconstruct stored prints - * from such data at a later point. You are welcome to store these byte strings - * in any fashion that suits you. - * - * The provided API to store data on disk is deprecated and should not be - * used anymore. This API stored the prints in the current user's home - * directory. - */ - -/* - * SECTION: fpi-data - * @title: Stored prints creation - * @short_description: Stored prints creation functions - * - * Stored print can be loaded and created by certain drivers which do their own - * print matching in hardware. Most drivers will not be using those functions. - * See #fp_print_data for the public API counterpart. - */ - -static char *base_store = NULL; - -static void storage_setup(void) -{ - const char *homedir; - - homedir = g_getenv("HOME"); - if (!homedir) - homedir = g_get_home_dir(); - if (!homedir) - return; - - base_store = g_build_filename(homedir, ".fprint/prints", NULL); - g_mkdir_with_parents(base_store, DIR_PERMS); - /* FIXME handle failure */ -} - -void fpi_data_exit(void) -{ - g_free(base_store); -} - -#define FP_FINGER_IS_VALID(finger) \ - ((finger) >= LEFT_THUMB && (finger) <= RIGHT_LITTLE) - -/* for debug messages only */ -static const char *finger_num_to_str(enum fp_finger finger) -{ - const char *names[] = { - [LEFT_THUMB] = "left thumb", - [LEFT_INDEX] = "left index", - [LEFT_MIDDLE] = "left middle", - [LEFT_RING] = "left ring", - [LEFT_LITTLE] = "left little", - [RIGHT_THUMB] = "right thumb", - [RIGHT_INDEX] = "right index", - [RIGHT_MIDDLE] = "right middle", - [RIGHT_RING] = "right ring", - [RIGHT_LITTLE] = "right little", - }; - if (!FP_FINGER_IS_VALID(finger)) - return "UNKNOWN"; - return names[finger]; -} - -static struct fp_print_data *print_data_new(uint16_t driver_id, - uint32_t devtype, enum fp_print_data_type type) -{ - struct fp_print_data *data = g_malloc0(sizeof(*data)); - fp_dbg("driver=%02x devtype=%04x", driver_id, devtype); - data->driver_id = driver_id; - data->devtype = devtype; - data->type = type; - return data; -} - -static void fpi_print_data_item_free(struct fp_print_data_item *item) -{ - g_free(item); -} - -struct fp_print_data_item *fpi_print_data_item_new(size_t length) -{ - struct fp_print_data_item *item = g_malloc0(sizeof(*item) + length); - item->length = length; - - return item; -} - -struct fp_print_data *fpi_print_data_new(struct fp_dev *dev) -{ - return print_data_new(dev->drv->id, dev->devtype, - fpi_driver_get_data_type(dev->drv)); -} - -struct fp_print_data_item * -fpi_print_data_get_item(struct fp_print_data *data) -{ - return data->prints->data; -} - -void -fpi_print_data_add_item(struct fp_print_data *data, - struct fp_print_data_item *item) -{ - data->prints = g_slist_prepend(data->prints, item); -} - -/** - * fp_print_data_get_data: - * @data: the stored print - * @ret: output location for the data buffer. Must be freed with free() - * after use. - - * Convert a stored print into a unified representation inside a data buffer. - * You can then store this data buffer in any way that suits you, and load - * it back at some later time using fp_print_data_from_data(). - * - * Returns: the size of the freshly allocated buffer, or 0 on error. - */ -API_EXPORTED size_t fp_print_data_get_data(struct fp_print_data *data, - unsigned char **ret) -{ - struct fpi_print_data_fp2 *out_data; - struct fpi_print_data_item_fp2 *out_item; - struct fp_print_data_item *item; - size_t buflen = 0; - GSList *list_item; - unsigned char *buf; - - G_DEBUG_HERE(); - - list_item = data->prints; - while (list_item) { - item = list_item->data; - buflen += sizeof(*out_item); - buflen += item->length; - list_item = g_slist_next(list_item); - } - - buflen += sizeof(*out_data); - out_data = g_malloc(buflen); - - *ret = (unsigned char *) out_data; - buf = out_data->data; - out_data->prefix[0] = 'F'; - out_data->prefix[1] = 'P'; - out_data->prefix[2] = '2'; - out_data->driver_id = GUINT16_TO_LE(data->driver_id); - out_data->devtype = GUINT32_TO_LE(data->devtype); - out_data->data_type = data->type; - - list_item = data->prints; - while (list_item) { - item = list_item->data; - out_item = (struct fpi_print_data_item_fp2 *)buf; - out_item->length = GUINT32_TO_LE(item->length); - /* FIXME: fp_print_data_item->data content is not endianness agnostic */ - memcpy(out_item->data, item->data, item->length); - buf += sizeof(*out_item); - buf += item->length; - list_item = g_slist_next(list_item); - } - - return buflen; -} - -static struct fp_print_data *fpi_print_data_from_fp1_data(unsigned char *buf, - size_t buflen) -{ - size_t print_data_len; - struct fp_print_data *data; - struct fp_print_data_item *item; - struct fpi_print_data_fp2 *raw = (struct fpi_print_data_fp2 *) buf; - - print_data_len = buflen - sizeof(*raw); - data = print_data_new(GUINT16_FROM_LE(raw->driver_id), - GUINT32_FROM_LE(raw->devtype), raw->data_type); - item = fpi_print_data_item_new(print_data_len); - /* FIXME: fp_print_data->data content is not endianness agnostic */ - memcpy(item->data, raw->data, print_data_len); - data->prints = g_slist_prepend(data->prints, item); - - return data; -} - -static struct fp_print_data *fpi_print_data_from_fp2_data(unsigned char *buf, - size_t buflen) -{ - size_t total_data_len, item_len; - struct fp_print_data *data; - struct fp_print_data_item *item; - struct fpi_print_data_fp2 *raw = (struct fpi_print_data_fp2 *) buf; - unsigned char *raw_buf; - struct fpi_print_data_item_fp2 *raw_item; - - total_data_len = buflen - sizeof(*raw); - data = print_data_new(GUINT16_FROM_LE(raw->driver_id), - GUINT32_FROM_LE(raw->devtype), raw->data_type); - raw_buf = raw->data; - while (total_data_len) { - if (total_data_len < sizeof(*raw_item)) - break; - total_data_len -= sizeof(*raw_item); - - raw_item = (struct fpi_print_data_item_fp2 *)raw_buf; - item_len = GUINT32_FROM_LE(raw_item->length); - fp_dbg("item len %d, total_data_len %d", (int) item_len, (int) total_data_len); - if (total_data_len < item_len) { - fp_err("corrupted fingerprint data"); - break; - } - total_data_len -= item_len; - - item = fpi_print_data_item_new(item_len); - /* FIXME: fp_print_data->data content is not endianness agnostic */ - memcpy(item->data, raw_item->data, item_len); - data->prints = g_slist_prepend(data->prints, item); - - raw_buf += sizeof(*raw_item); - raw_buf += item_len; - } - - if (g_slist_length(data->prints) == 0) { - fp_print_data_free(data); - data = NULL; - } - - return data; - -} - -/** - * fp_print_data_from_data: - * @buf: the data buffer - * @buflen: the length of the buffer - - * Load a stored print from a data buffer. The contents of said buffer must - * be the untouched contents of a buffer previously supplied to you by the - * fp_print_data_get_data() function. - * - * Returns: the stored print represented by the data, or %NULL on error. Must - * be freed with fp_print_data_free() after use. - */ -API_EXPORTED struct fp_print_data *fp_print_data_from_data(unsigned char *buf, - size_t buflen) -{ - struct fpi_print_data_fp2 *raw = (struct fpi_print_data_fp2 *) buf; - - fp_dbg("buffer size %zd", buflen); - if (buflen < sizeof(*raw)) - return NULL; - - if (strncmp(raw->prefix, "FP1", 3) == 0) { - return fpi_print_data_from_fp1_data(buf, buflen); - } else if (strncmp(raw->prefix, "FP2", 3) == 0) { - return fpi_print_data_from_fp2_data(buf, buflen); - } else { - fp_dbg("bad header prefix"); - } - - return NULL; -} - -static char *get_path_to_storedir(uint16_t driver_id, uint32_t devtype) -{ - char idstr[5]; - char devtypestr[9]; - - g_snprintf(idstr, sizeof(idstr), "%04x", driver_id); - g_snprintf(devtypestr, sizeof(devtypestr), "%08x", devtype); - - return g_build_filename(base_store, idstr, devtypestr, NULL); -} - -static char *__get_path_to_print(uint16_t driver_id, uint32_t devtype, - enum fp_finger finger) -{ - char *dirpath; - char *path; - char fingername[2]; - - g_snprintf(fingername, 2, "%x", finger); - - dirpath = get_path_to_storedir(driver_id, devtype); - path = g_build_filename(dirpath, fingername, NULL); - g_free(dirpath); - return path; -} - -static char *get_path_to_print(struct fp_dev *dev, enum fp_finger finger) -{ - return __get_path_to_print(dev->drv->id, dev->devtype, finger); -} - -/** - * fp_print_data_save: - * @data: the stored print to save to disk - * @finger: the finger that this print corresponds to - * - * Saves a stored print to disk, assigned to a specific finger. Even though - * you are limited to storing only the 10 human fingers, this is a - * per-device-type limit. For example, you can store the users right index - * finger from a DigitalPersona scanner, and you can also save the right index - * finger from a UPEK scanner. When you later come to load the print, the right - * one will be automatically selected. - * - * This function will unconditionally overwrite a fingerprint previously - * saved for the same finger and device type. The print is saved in a hidden - * directory beneath the current user's home directory. - * - * Returns: 0 on success, non-zero on error. - * - * Deprecated: Data storage should be handled outside of libfprint. - * See stored prints description - * for more information. - */ -API_EXPORTED int fp_print_data_save(struct fp_print_data *data, - enum fp_finger finger) -{ - GError *err = NULL; - char *path; - char *dirpath; - unsigned char *buf; - size_t len; - int r; - - if (!base_store) - storage_setup(); - - fp_dbg("save %s print from driver %04x", finger_num_to_str(finger), - data->driver_id); - len = fp_print_data_get_data(data, &buf); - if (!len) - return -ENOMEM; - - path = __get_path_to_print(data->driver_id, data->devtype, finger); - dirpath = g_path_get_dirname(path); - r = g_mkdir_with_parents(dirpath, DIR_PERMS); - if (r < 0) { - fp_err("couldn't create storage directory"); - free(buf); - g_free(path); - g_free(dirpath); - return r; - } - - fp_dbg("saving to %s", path); - g_file_set_contents(path, buf, len, &err); - free(buf); - g_free(dirpath); - g_free(path); - if (err) { - r = err->code; - fp_err("save failed: %s", err->message); - g_error_free(err); - /* FIXME interpret error codes */ - return r; - } - - return 0; -} - -gboolean fpi_print_data_compatible(uint16_t driver_id1, uint32_t devtype1, - enum fp_print_data_type type1, uint16_t driver_id2, uint32_t devtype2, - enum fp_print_data_type type2) -{ - if (driver_id1 != driver_id2) { - fp_dbg("driver ID mismatch: %02x vs %02x", driver_id1, driver_id2); - return FALSE; - } - - if (devtype1 != devtype2) { - fp_dbg("devtype mismatch: %04x vs %04x", devtype1, devtype2); - return FALSE; - } - - if (type1 != type2) { - fp_dbg("type mismatch: %d vs %d", type1, type2); - return FALSE; - } - - return TRUE; -} - -static int load_from_file(char *path, struct fp_print_data **data) -{ - gsize length; - gchar *contents; - GError *err = NULL; - struct fp_print_data *fdata; - - fp_dbg("from %s", path); - g_file_get_contents(path, &contents, &length, &err); - if (err) { - int r = err->code; - fp_err("%s load failed: %s", path, err->message); - g_error_free(err); - /* FIXME interpret more error codes */ - if (r == G_FILE_ERROR_NOENT) - return -ENOENT; - else - return r; - } - - fdata = fp_print_data_from_data(contents, length); - g_free(contents); - if (!fdata) - return -EIO; - *data = fdata; - return 0; -} - -/** - * fp_print_data_load: - * @dev: the device you are loading the print for - * @finger: the finger of the file you are loading - * @data: output location to put the corresponding stored print. Must be - * freed with fp_print_data_free() after use. - - * Loads a previously stored print from disk. The print must have been saved - * earlier using the fp_print_data_save() function. - * - * A return code of -ENOENT indicates that the fingerprint requested could not - * be found. Other error codes (both positive and negative) are possible for - * obscure error conditions (e.g. corruption). - * - * Returns: 0 on success, non-zero on error - * - * Deprecated: Data storage should be handled outside of libfprint. - * See stored prints description - * for more information. - */ -API_EXPORTED int fp_print_data_load(struct fp_dev *dev, - enum fp_finger finger, struct fp_print_data **data) -{ - gchar *path; - struct fp_print_data *fdata = NULL; - int r; - - if (!base_store) - storage_setup(); - - path = get_path_to_print(dev, finger); - r = load_from_file(path, &fdata); - g_free(path); - if (r) - return r; - - if (!fp_dev_supports_print_data(dev, fdata)) { - fp_err("print data is not compatible!"); - fp_print_data_free(fdata); - return -EINVAL; - } - - *data = fdata; - return 0; -} - -/** - * fp_print_data_delete: - * @dev: the device that the print belongs to - * @finger: the finger of the file you are deleting - - * Removes a stored print from disk previously saved with fp_print_data_save(). - * - * Returns: 0 on success, negative on error - * - * Deprecated: Data storage should be handled outside of libfprint. - * See stored prints description - * for more information. - */ -API_EXPORTED int fp_print_data_delete(struct fp_dev *dev, - enum fp_finger finger) -{ - int r; - gchar *path = get_path_to_print(dev, finger); - - fp_dbg("remove finger %d at %s", finger, path); - r = g_unlink(path); - g_free(path); - if (r < 0) - fp_dbg("unlink failed with error %d", r); - - /* FIXME: cleanup empty directory */ - return r; -} - -/** - * fp_print_data_from_dscv_print: - * @print: the discovered print - * @data: output location to point to the corresponding stored print. Must - * be freed with fp_print_data_free() after use. - - * Attempts to load a stored print based on a #fp_dscv_print - * discovered print record. - * - * A return code of -ENOENT indicates that the file referred to by the - * discovered print could not be found. Other error codes (both positive and - * negative) are possible for obscure error conditions (e.g. corruption). - * - * Returns: 0 on success, non-zero on error. - * - * Deprecated: Do not use. - */ -API_EXPORTED int fp_print_data_from_dscv_print(struct fp_dscv_print *print, - struct fp_print_data **data) -{ - return load_from_file(print->path, data); -} - -/** - * fp_print_data_free: - * @data: the stored print to destroy. If NULL, function simply returns. - * - * Frees a stored print. Must be called when you are finished using the print. - */ -API_EXPORTED void fp_print_data_free(struct fp_print_data *data) -{ - if (data) - g_slist_free_full(data->prints, (GDestroyNotify)fpi_print_data_item_free); - g_free(data); -} - -/** - * fp_print_data_get_driver_id: - * @data: the stored print - - * Gets the [driver ID](advanced-topics.html#driver_id) for a stored print. The driver ID - * indicates which driver the print originally came from. The print is - * only usable with a device controlled by that driver. - * - * Returns: the driver ID of the driver compatible with the print - */ -API_EXPORTED uint16_t fp_print_data_get_driver_id(struct fp_print_data *data) -{ - return data->driver_id; -} - -/** - * fp_print_data_get_devtype: - * @data: the stored print - - * Gets the [devtype](advanced-topics.html#device-types) for a stored print. The devtype represents - * which type of device under the parent driver is compatible with the print. - * - * Returns: the devtype of the device range compatible with the print - */ -API_EXPORTED uint32_t fp_print_data_get_devtype(struct fp_print_data *data) -{ - return data->devtype; -} - -/** - * SECTION:dscv_print - * @title: Print discovery (deprecated) - * @short_description: Print discovery functions - * - * The [stored print](libfprint-Stored-prints.html) documentation detailed a simple API - * for storing per-device prints for a single user, namely - * fp_print_data_save(). It also detailed a load function, - * fp_print_data_load(), but usage of this function is limited to scenarios - * where you know which device you would like to use, and you know which - * finger you are looking to verify. - * - * In other cases, it would be more useful to be able to enumerate all - * previously saved prints, potentially even before device discovery. These - * functions are designed to offer this functionality to you. - * - * Discovered prints are stored in a #fp_dscv_print structure, and you - * can use functions documented below to access some information about these - * prints. You can determine if a discovered print appears to be compatible - * with a device using functions such as fp_dscv_dev_supports_dscv_print() and - * fp_dev_supports_dscv_print(). - * - * When you are ready to use the print, you can load it into memory in the form - * of a stored print by using the fp_print_data_from_dscv_print() function. - * - * You may have noticed the use of the word "appears" in the above paragraphs. - * libfprint performs print discovery simply by examining the file and - * directory structure of libfprint's private data store. It does not examine - * the actual prints themselves. Just because a print has been discovered - * and appears to be compatible with a certain device does not necessarily mean - * that it is usable; when you come to load or use it, under unusual - * circumstances it may turn out that the print is corrupt or not for the - * device that it appeared to be. Also, it is possible that the print may have - * been deleted by the time you come to load it. - * - * Note that this portion of the library is deprecated. All that it offers is - * already implementable using publicly available functions, and its usage is - * unnecessarily restrictive in terms of how it stores data. - */ - -static GSList *scan_dev_store_dir(char *devpath, uint16_t driver_id, - uint32_t devtype, GSList *list) -{ - GError *err = NULL; - const gchar *ent; - struct fp_dscv_print *print; - - GDir *dir = g_dir_open(devpath, 0, &err); - if (!dir) { - fp_err("opendir %s failed: %s", devpath, err->message); - g_error_free(err); - return list; - } - - while ((ent = g_dir_read_name(dir))) { - /* ent is an 1 hex character fp_finger code */ - guint64 val; - enum fp_finger finger; - gchar *endptr; - - if (*ent == 0 || strlen(ent) != 1) - continue; - - val = g_ascii_strtoull(ent, &endptr, 16); - if (endptr == ent || !FP_FINGER_IS_VALID(val)) { - fp_dbg("skipping print file %s", ent); - continue; - } - - finger = (enum fp_finger) val; - print = g_malloc(sizeof(*print)); - print->driver_id = driver_id; - print->devtype = devtype; - print->path = g_build_filename(devpath, ent, NULL); - print->finger = finger; - list = g_slist_prepend(list, print); - } - - g_dir_close(dir); - return list; -} - -static GSList *scan_driver_store_dir(char *drvpath, uint16_t driver_id, - GSList *list) -{ - GError *err = NULL; - const gchar *ent; - - GDir *dir = g_dir_open(drvpath, 0, &err); - if (!dir) { - fp_err("opendir %s failed: %s", drvpath, err->message); - g_error_free(err); - return list; - } - - while ((ent = g_dir_read_name(dir))) { - /* ent is an 8 hex character devtype */ - guint64 val; - uint32_t devtype; - gchar *endptr; - gchar *path; - - if (*ent == 0 || strlen(ent) != 8) - continue; - - val = g_ascii_strtoull(ent, &endptr, 16); - if (endptr == ent) { - fp_dbg("skipping devtype %s", ent); - continue; - } - - devtype = (uint32_t) val; - path = g_build_filename(drvpath, ent, NULL); - list = scan_dev_store_dir(path, driver_id, devtype, list); - g_free(path); - } - - g_dir_close(dir); - return list; -} - -/** - * fp_discover_prints: - * - * Scans the users home directory and returns a list of prints that were - * previously saved using fp_print_data_save(). - * - * Returns: a %NULL-terminated list of discovered prints, must be freed with - * fp_dscv_prints_free() after use. - * - * Deprecated: Do not use. - */ -API_EXPORTED struct fp_dscv_print **fp_discover_prints(void) -{ - GDir *dir; - const gchar *ent; - GError *err = NULL; - GSList *tmplist = NULL; - GSList *elem; - GPtrArray *array; - - if (!base_store) - storage_setup(); - - dir = g_dir_open(base_store, 0, &err); - if (!dir) { - fp_err("opendir %s failed: %s", base_store, err->message); - g_error_free(err); - return NULL; - } - - while ((ent = g_dir_read_name(dir))) { - /* ent is a 4 hex digit driver_id */ - gchar *endptr; - gchar *path; - guint64 val; - uint16_t driver_id; - - if (*ent == 0 || strlen(ent) != 4) - continue; - - val = g_ascii_strtoull(ent, &endptr, 16); - if (endptr == ent) { - fp_dbg("skipping drv id %s", ent); - continue; - } - - driver_id = (uint16_t) val; - path = g_build_filename(base_store, ent, NULL); - tmplist = scan_driver_store_dir(path, driver_id, tmplist); - g_free(path); - } - - g_dir_close(dir); - - if (tmplist == NULL) - return NULL; - - array = g_ptr_array_new(); - for (elem = tmplist; elem != NULL; elem = elem->next) - g_ptr_array_add(array, elem->data); - g_ptr_array_add(array, NULL); - - g_slist_free(tmplist); - return (struct fp_dscv_print **) g_ptr_array_free(array, FALSE); -} - -/** - * fp_dscv_prints_free: - * @prints: the list of discovered prints. If NULL, function simply - * returns. - * - * Frees a list of discovered prints. This function also frees the discovered - * prints themselves, so make sure you do not use any discovered prints - * after calling this function. - * - * Deprecated: Do not use. - */ -API_EXPORTED void fp_dscv_prints_free(struct fp_dscv_print **prints) -{ - int i; - struct fp_dscv_print *print; - - if (!prints) - return; - - for (i = 0; (print = prints[i]); i++) { - if (print) - g_free(print->path); - g_free(print); - } - g_free(prints); -} - -/** - * fp_dscv_print_get_driver_id: - * @print: the discovered print - * - * Gets the [driver ID](advanced-topics.html#driver_id) for a discovered print. The driver ID - * indicates which driver the print originally came from. The print is only - * usable with a device controlled by that driver. - * - * Returns: the driver ID of the driver compatible with the print - * - * Deprecated: Do not use. - */ -API_EXPORTED uint16_t fp_dscv_print_get_driver_id(struct fp_dscv_print *print) -{ - return print->driver_id; -} - -/** - * fp_dscv_print_get_devtype: - * @print: the discovered print - * - * Gets the [devtype](advanced-topics.html#device-types) for a discovered print. The devtype - * represents which type of device under the parent driver is compatible - * with the print. - * - * Returns: the devtype of the device range compatible with the print - * - * Deprecated: Do not use. - */ -API_EXPORTED uint32_t fp_dscv_print_get_devtype(struct fp_dscv_print *print) -{ - return print->devtype; -} - -/** - * fp_dscv_print_get_finger: - * @print: discovered print - * - * Gets the finger code for a discovered print. - * - * Returns: a finger code from #fp_finger - * - * Deprecated: Do not use. - */ -API_EXPORTED enum fp_finger fp_dscv_print_get_finger(struct fp_dscv_print *print) -{ - return print->finger; -} - -/** - * fp_dscv_print_delete: - * @print: the discovered print to remove from disk - * - * Removes a discovered print from disk. After successful return of this - * function, functions such as fp_dscv_print_get_finger() will continue to - * operate as before, however calling fp_print_data_from_dscv_print() will - * fail for obvious reasons. - * - * Returns: 0 on success, negative on error - * - * Deprecated: Do not use. - */ -API_EXPORTED int fp_dscv_print_delete(struct fp_dscv_print *print) -{ - int r; - fp_dbg("remove at %s", print->path); - r = g_unlink(print->path); - if (r < 0) - fp_dbg("unlink failed with error %d", r); - - /* FIXME: cleanup empty directory */ - return r; -} - diff --git a/libfprint/fpi-dev-img.c b/libfprint/fpi-dev-img.c deleted file mode 100644 index b9d27831..00000000 --- a/libfprint/fpi-dev-img.c +++ /dev/null @@ -1,660 +0,0 @@ -/* - * Core imaging device functions for libfprint - * Copyright (C) 2007-2008 Daniel Drake - * - * 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 - -#include - -#include "fpi-dev-img.h" -#include "fpi-async.h" -#include "fp_internal.h" - -/** - * SECTION:fpi-dev-img - * @title: Image device operations - * @short_description: Image device operation functions - * - * As drivers work through different operations, they need to report back - * to the core as to their internal state, so errors and successes can be - * reported back to front-ends. - */ - -#define MIN_ACCEPTABLE_MINUTIAE 10 -#define BOZORTH3_DEFAULT_THRESHOLD 40 -#define IMG_ENROLL_STAGES 5 - -/** - * fpi_imgdev_get_action_state: - * @imgdev: a #fp_img_dev imaging fingerprint device - * - * Returns the state of an imaging device while enrolling a fingerprint. - * - * Returns: a enum #fp_imgdev_enroll_state - */ -enum fp_imgdev_enroll_state -fpi_imgdev_get_action_state(struct fp_img_dev *imgdev) -{ - return imgdev->action_state; -} - -/** - * fpi_imgdev_get_action: - * @imgdev: a #fp_img_dev imaging fingerprint device - * - * Returns the current action being performed by an imaging device. - * - * Returns: a enum #fp_imgdev_action - */ -enum fp_imgdev_action -fpi_imgdev_get_action(struct fp_img_dev *imgdev) -{ - return imgdev->action; -} - -/** - * fpi_imgdev_get_action_result: - * @imgdev: a #fp_img_dev imaging fingerprint device - * - * Returns an integer representing the result of an action. Which enum - * the result code is taken from depends on the current action being performed. - * See #fp_capture_result, #fp_enroll_result and #fp_verify_result. - */ -int -fpi_imgdev_get_action_result(struct fp_img_dev *imgdev) -{ - return imgdev->action_result; -} - -/** - * fpi_imgdev_set_action_result: - * @imgdev: a #fp_img_dev imaging fingerprint device - * @action_result: an action result - * - * Drivers should use fpi_imgdev_image_captured() instead. This function - * should not be used, and will be removed soon. - */ -void -fpi_imgdev_set_action_result(struct fp_img_dev *imgdev, - int action_result) -{ - imgdev->action_result = action_result; -} - -static int img_dev_open(struct fp_dev *dev, unsigned long driver_data) -{ - struct fp_img_dev *imgdev = g_malloc0(sizeof(*imgdev)); - struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(dev->drv); - int r = 0; - - /* Set up back pointers */ - dev->img_dev = imgdev; - imgdev->parent = dev; - - imgdev->enroll_stage = 0; - dev->nr_enroll_stages = IMG_ENROLL_STAGES; - - if (imgdrv->open) { - r = imgdrv->open(imgdev, driver_data); - if (r) - goto err; - } else { - fpi_drvcb_open_complete(dev, 0); - } - - return 0; -err: - g_free(imgdev); - return r; -} - -/** - * fpi_imgdev_open_complete: - * @imgdev: a #fp_img_dev imaging fingerprint device - * @status: an error code - * - * Function to call when the device has been opened, whether - * successfully of not. - */ -void fpi_imgdev_open_complete(struct fp_img_dev *imgdev, int status) -{ - fpi_drvcb_open_complete(FP_DEV(imgdev), status); -} - -static void img_dev_close(struct fp_dev *dev) -{ - struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(dev->drv); - - if (imgdrv->close) - imgdrv->close(dev->img_dev); - else - fpi_drvcb_close_complete(dev); -} - -/** - * fpi_imgdev_close_complete: - * @imgdev: a #fp_img_dev imaging fingerprint device - * - * Function to call when the device has been closed. - */ -void fpi_imgdev_close_complete(struct fp_img_dev *imgdev) -{ - fpi_drvcb_close_complete(FP_DEV(imgdev)); - g_free(imgdev); -} - -static int dev_change_state(struct fp_img_dev *imgdev, - enum fp_imgdev_state state) -{ - struct fp_driver *drv = FP_DEV(imgdev)->drv; - struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv); - - if (!imgdrv->change_state) - return 0; - return imgdrv->change_state(imgdev, state); -} - -/* check image properties and resize it if necessary. potentially returns a new - * image after freeing the old one. */ -static int sanitize_image(struct fp_img_dev *imgdev, struct fp_img **_img) -{ - struct fp_driver *drv = FP_DEV(imgdev)->drv; - struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv); - struct fp_img *img = *_img; - - if (imgdrv->img_width > 0) { - img->width = imgdrv->img_width; - } else if (img->width <= 0) { - fp_err("no image width assigned"); - return -EINVAL; - } - - if (imgdrv->img_height > 0) { - img->height = imgdrv->img_height; - } else if (img->height <= 0) { - fp_err("no image height assigned"); - return -EINVAL; - } - - if (!fpi_img_is_sane(img)) { - fp_err("image is not sane!"); - return -EINVAL; - } - - return 0; -} - -/** - * fpi_imgdev_report_finger_status: - * @imgdev: a #fp_img_dev imaging fingerprint device - * @present: whether the finger is present on the sensor - * - * Reports from the driver whether the user's finger is on - * the sensor. - */ -void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev, - gboolean present) -{ - int r = imgdev->action_result; - struct fp_print_data *data = imgdev->acquire_data; - struct fp_img *img = imgdev->acquire_img; - - fp_dbg(present ? "finger on sensor" : "finger removed"); - - if (present && imgdev->action_state == IMG_ACQUIRE_STATE_AWAIT_FINGER_ON) { - dev_change_state(imgdev, IMGDEV_STATE_CAPTURE); - imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_IMAGE; - return; - } else if (present - || imgdev->action_state != IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF) { - fp_dbg("ignoring status report"); - return; - } - - /* clear these before reporting results to avoid complications with - * call cascading in and out of the library */ - imgdev->acquire_img = NULL; - imgdev->acquire_data = NULL; - - /* finger removed, report results */ - switch (imgdev->action) { - case IMG_ACTION_ENROLL: - fp_dbg("reporting enroll result"); - data = imgdev->enroll_data; - if (r == FP_ENROLL_COMPLETE) { - imgdev->enroll_data = NULL; - } - fpi_drvcb_enroll_stage_completed(FP_DEV(imgdev), r, - r == FP_ENROLL_COMPLETE ? data : NULL, - img); - /* the callback can cancel enrollment, so recheck current - * action and the status to see if retry is needed */ - if (imgdev->action == IMG_ACTION_ENROLL && - r > 0 && r != FP_ENROLL_COMPLETE && r != FP_ENROLL_FAIL) { - imgdev->action_result = 0; - imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_FINGER_ON; - dev_change_state(imgdev, IMGDEV_STATE_AWAIT_FINGER_ON); - } - break; - case IMG_ACTION_VERIFY: - fpi_drvcb_report_verify_result(FP_DEV(imgdev), r, img); - imgdev->action_result = 0; - fp_print_data_free(data); - break; - case IMG_ACTION_IDENTIFY: - fpi_drvcb_report_identify_result(FP_DEV(imgdev), r, - imgdev->identify_match_offset, img); - imgdev->action_result = 0; - fp_print_data_free(data); - break; - case IMG_ACTION_CAPTURE: - fpi_drvcb_report_capture_result(FP_DEV(imgdev), r, img); - imgdev->action_result = 0; - break; - default: - fp_err("unhandled action %d", imgdev->action); - break; - } -} - -static void verify_process_img(struct fp_img_dev *imgdev) -{ - struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(FP_DEV(imgdev)->drv); - int match_score = imgdrv->bz3_threshold; - int r; - - if (match_score == 0) - match_score = BOZORTH3_DEFAULT_THRESHOLD; - - r = fpi_img_compare_print_data(FP_DEV(imgdev)->verify_data, - imgdev->acquire_data); - - if (r >= match_score) - r = FP_VERIFY_MATCH; - else if (r >= 0) - r = FP_VERIFY_NO_MATCH; - - imgdev->action_result = r; -} - -static void identify_process_img(struct fp_img_dev *imgdev) -{ - struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(FP_DEV(imgdev)->drv); - int match_score = imgdrv->bz3_threshold; - size_t match_offset; - int r; - - if (match_score == 0) - match_score = BOZORTH3_DEFAULT_THRESHOLD; - - r = fpi_img_compare_print_data_to_gallery(imgdev->acquire_data, - FP_DEV(imgdev)->identify_gallery, match_score, &match_offset); - - imgdev->action_result = r; - imgdev->identify_match_offset = match_offset; -} - -/** - * fpi_imgdev_abort_scan: - * @imgdev: a #fp_img_dev imaging fingerprint device - * @result: the scan result - * - * Aborts a scan after an error, and set the action result. See - * fpi_imgdev_get_action_result() for possible values. - */ -void fpi_imgdev_abort_scan(struct fp_img_dev *imgdev, int result) -{ - imgdev->action_result = result; - imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF; - dev_change_state(imgdev, IMGDEV_STATE_AWAIT_FINGER_OFF); -} - -/** - * fpi_imgdev_image_captured: - * @imgdev: a #fp_img_dev imaging fingerprint device - * @img: an #fp_img image - * - * Report to the core that the driver captured this image from the sensor. - */ -void fpi_imgdev_image_captured(struct fp_img_dev *imgdev, struct fp_img *img) -{ - struct fp_print_data *print = NULL; - int r; - G_DEBUG_HERE(); - - if (imgdev->action_state != IMG_ACQUIRE_STATE_AWAIT_IMAGE) { - fp_dbg("ignoring due to current state %d", imgdev->action_state); - return; - } - - if (imgdev->action_result) { - fp_dbg("not overwriting existing action result"); - return; - } - - r = sanitize_image(imgdev, &img); - if (r < 0) { - imgdev->action_result = r; - fp_img_free(img); - goto next_state; - } - - fp_img_standardize(img); - imgdev->acquire_img = img; - if (imgdev->action != IMG_ACTION_CAPTURE) { - r = fpi_img_to_print_data(imgdev, img, &print); - if (r < 0) { - fp_dbg("image to print data conversion error: %d", r); - imgdev->action_result = FP_ENROLL_RETRY; - goto next_state; - } else if (img->minutiae->num < MIN_ACCEPTABLE_MINUTIAE) { - fp_dbg("not enough minutiae, %d/%d", img->minutiae->num, - MIN_ACCEPTABLE_MINUTIAE); - fp_print_data_free(print); - /* depends on FP_ENROLL_RETRY == FP_VERIFY_RETRY */ - imgdev->action_result = FP_ENROLL_RETRY; - goto next_state; - } - } - - imgdev->acquire_data = print; - switch (imgdev->action) { - case IMG_ACTION_ENROLL: - if (!imgdev->enroll_data) { - imgdev->enroll_data = fpi_print_data_new(FP_DEV(imgdev)); - } - BUG_ON(g_slist_length(print->prints) != 1); - /* Move print data from acquire data into enroll_data */ - imgdev->enroll_data->prints = - g_slist_prepend(imgdev->enroll_data->prints, print->prints->data); - print->prints = g_slist_remove(print->prints, print->prints->data); - - fp_print_data_free(imgdev->acquire_data); - imgdev->acquire_data = NULL; - imgdev->enroll_stage++; - if (imgdev->enroll_stage == FP_DEV(imgdev)->nr_enroll_stages) - imgdev->action_result = FP_ENROLL_COMPLETE; - else - imgdev->action_result = FP_ENROLL_PASS; - break; - case IMG_ACTION_VERIFY: - verify_process_img(imgdev); - break; - case IMG_ACTION_IDENTIFY: - identify_process_img(imgdev); - break; - case IMG_ACTION_CAPTURE: - imgdev->action_result = FP_CAPTURE_COMPLETE; - break; - default: - BUG(); - break; - } - -next_state: - imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF; - dev_change_state(imgdev, IMGDEV_STATE_AWAIT_FINGER_OFF); -} - -/** - * fpi_imgdev_session_error: - * @imgdev: a #fp_img_dev imaging fingerprint device - * @error: an error code - * - * Report an error that occurred in the driver. - */ -void fpi_imgdev_session_error(struct fp_img_dev *imgdev, int error) -{ - fp_dbg("error %d", error); - BUG_ON(error == 0); - switch (imgdev->action) { - case IMG_ACTION_ENROLL: - fpi_drvcb_enroll_stage_completed(FP_DEV(imgdev), error, NULL, NULL); - break; - case IMG_ACTION_VERIFY: - fpi_drvcb_report_verify_result(FP_DEV(imgdev), error, NULL); - break; - case IMG_ACTION_IDENTIFY: - fpi_drvcb_report_identify_result(FP_DEV(imgdev), error, 0, NULL); - break; - case IMG_ACTION_CAPTURE: - fpi_drvcb_report_capture_result(FP_DEV(imgdev), error, NULL); - break; - default: - fp_err("unhandled action %d", imgdev->action); - break; - } -} - -/** - * fpi_imgdev_activate_complete: - * @imgdev: a #fp_img_dev imaging fingerprint device - * @status: the activation result - * - * Marks an activation as complete, whether successful or not. - * See fpi_imgdev_get_action_result() for possible values. - */ -void fpi_imgdev_activate_complete(struct fp_img_dev *imgdev, int status) -{ - fp_dbg("status %d", status); - - switch (imgdev->action) { - case IMG_ACTION_ENROLL: - fpi_drvcb_enroll_started(FP_DEV(imgdev), status); - break; - case IMG_ACTION_VERIFY: - fpi_drvcb_verify_started(FP_DEV(imgdev), status); - break; - case IMG_ACTION_IDENTIFY: - fpi_drvcb_identify_started(FP_DEV(imgdev), status); - break; - case IMG_ACTION_CAPTURE: - fpi_drvcb_capture_started(FP_DEV(imgdev), status); - break; - default: - fp_err("unhandled action %d", imgdev->action); - return; - } - - if (status == 0) { - imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_FINGER_ON; - dev_change_state(imgdev, IMGDEV_STATE_AWAIT_FINGER_ON); - } -} - -/** - * fpi_imgdev_deactivate_complete: - * @imgdev: a #fp_img_dev imaging fingerprint device - * - * Marks a deactivation as complete. - */ -void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev) -{ - enum fp_imgdev_action action; - - G_DEBUG_HERE(); - - action = imgdev->action; - imgdev->action = IMG_ACTION_NONE; - imgdev->action_state = 0; - - switch (action) { - case IMG_ACTION_ENROLL: - fpi_drvcb_enroll_stopped(FP_DEV(imgdev)); - break; - case IMG_ACTION_VERIFY: - fpi_drvcb_verify_stopped(FP_DEV(imgdev)); - break; - case IMG_ACTION_IDENTIFY: - fpi_drvcb_identify_stopped(FP_DEV(imgdev)); - break; - case IMG_ACTION_CAPTURE: - fpi_drvcb_capture_stopped(FP_DEV(imgdev)); - break; - default: - fp_err("unhandled action %d", imgdev->action); - break; - } -} - -int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev) -{ - struct fp_driver *drv = FP_DEV(imgdev)->drv; - struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv); - int width = imgdrv->img_width; - - if (width == -1) - width = 0; - - return width; -} - -int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev) -{ - struct fp_driver *drv = FP_DEV(imgdev)->drv; - struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv); - int height = imgdrv->img_height; - - if (height == -1) - height = 0; - - return height; -} - -static int dev_activate(struct fp_img_dev *imgdev) -{ - struct fp_driver *drv = FP_DEV(imgdev)->drv; - struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv); - - if (!imgdrv->activate) - return 0; - return imgdrv->activate(imgdev); -} - -static void dev_deactivate(struct fp_img_dev *imgdev) -{ - struct fp_driver *drv = FP_DEV(imgdev)->drv; - struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv); - - if (!imgdrv->deactivate) - return; - return imgdrv->deactivate(imgdev); -} - -static int generic_acquire_start(struct fp_dev *dev, int action) -{ - struct fp_img_dev *imgdev = dev->img_dev; - int r; - fp_dbg("action %d", action); - imgdev->action = action; - imgdev->action_state = IMG_ACQUIRE_STATE_ACTIVATING; - imgdev->enroll_stage = 0; - - r = dev_activate(imgdev); - if (r < 0) - fp_err("activation failed with error %d", r); - - return r; - -} - -static void generic_acquire_stop(struct fp_img_dev *imgdev) -{ - imgdev->action_state = IMG_ACQUIRE_STATE_DEACTIVATING; - dev_deactivate(imgdev); - - fp_print_data_free(imgdev->acquire_data); - fp_print_data_free(imgdev->enroll_data); - fp_img_free(imgdev->acquire_img); - imgdev->acquire_data = NULL; - imgdev->enroll_data = NULL; - imgdev->acquire_img = NULL; - imgdev->action_result = 0; -} - -static int img_dev_enroll_start(struct fp_dev *dev) -{ - return generic_acquire_start(dev, IMG_ACTION_ENROLL); -} - -static int img_dev_verify_start(struct fp_dev *dev) -{ - return generic_acquire_start(dev, IMG_ACTION_VERIFY); -} - -static int img_dev_identify_start(struct fp_dev *dev) -{ - return generic_acquire_start(dev, IMG_ACTION_IDENTIFY); -} - -static int img_dev_capture_start(struct fp_dev *dev) -{ - /* Unconditional capture is not supported yet */ - if (dev->unconditional_capture) - return -ENOTSUP; - return generic_acquire_start(dev, IMG_ACTION_CAPTURE); -} - -static int img_dev_enroll_stop(struct fp_dev *dev) -{ - struct fp_img_dev *imgdev = dev->img_dev; - BUG_ON(imgdev->action != IMG_ACTION_ENROLL); - generic_acquire_stop(imgdev); - return 0; -} - -static int img_dev_verify_stop(struct fp_dev *dev, gboolean iterating) -{ - struct fp_img_dev *imgdev = dev->img_dev; - BUG_ON(imgdev->action != IMG_ACTION_VERIFY); - generic_acquire_stop(imgdev); - return 0; -} - -static int img_dev_identify_stop(struct fp_dev *dev, gboolean iterating) -{ - struct fp_img_dev *imgdev = dev->img_dev; - BUG_ON(imgdev->action != IMG_ACTION_IDENTIFY); - generic_acquire_stop(imgdev); - imgdev->identify_match_offset = 0; - return 0; -} - -static int img_dev_capture_stop(struct fp_dev *dev) -{ - struct fp_img_dev *imgdev = dev->img_dev; - BUG_ON(imgdev->action != IMG_ACTION_CAPTURE); - generic_acquire_stop(imgdev); - return 0; -} - -void fpi_img_driver_setup(struct fp_img_driver *idriver) -{ - idriver->driver.type = DRIVER_IMAGING; - idriver->driver.open = img_dev_open; - idriver->driver.close = img_dev_close; - idriver->driver.enroll_start = img_dev_enroll_start; - idriver->driver.enroll_stop = img_dev_enroll_stop; - idriver->driver.verify_start = img_dev_verify_start; - idriver->driver.verify_stop = img_dev_verify_stop; - idriver->driver.identify_start = img_dev_identify_start; - idriver->driver.identify_stop = img_dev_identify_stop; - idriver->driver.capture_start = img_dev_capture_start; - idriver->driver.capture_stop = img_dev_capture_stop; -} - diff --git a/libfprint/fpi-dev-img.h b/libfprint/fpi-dev-img.h deleted file mode 100644 index 0b0d48bc..00000000 --- a/libfprint/fpi-dev-img.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2007-2008 Daniel Drake - * Copyright (C) 2018 Bastien Nocera - * - * 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 - */ - -#ifndef __FPI_DEV_IMG_H__ -#define __FPI_DEV_IMG_H__ - -#include "fpi-dev.h" -#include "fpi-img.h" - -/** - * fp_imgdev_action: - * @IMG_ACTION_NONE: no action - * @IMG_ACTION_ENROLL: device action is enrolling - * @IMG_ACTION_VERIFY: device action is verifying - * @IMG_ACTION_IDENTIFY: device action is identifying - * @IMG_ACTION_CAPTURE: device action is capturing - * - * The current action being performed by an imaging device. The current - * action can be gathered inside the driver using fpi_imgdev_get_action(). - */ -enum fp_imgdev_action { - IMG_ACTION_NONE = 0, - IMG_ACTION_ENROLL, - IMG_ACTION_VERIFY, - IMG_ACTION_IDENTIFY, - IMG_ACTION_CAPTURE, -}; - -/** - * fp_imgdev_state: - * @IMGDEV_STATE_INACTIVE: inactive - * @IMGDEV_STATE_AWAIT_FINGER_ON: waiting for the finger to be pressed or swiped - * @IMGDEV_STATE_CAPTURE: capturing an image - * @IMGDEV_STATE_AWAIT_FINGER_OFF: waiting for the finger to be removed - * - * The state of an imaging device while doing a capture. The state is - * passed through to the driver using the ::activate() or ::change_state() vfuncs. - */ -enum fp_imgdev_state { - IMGDEV_STATE_INACTIVE, - IMGDEV_STATE_AWAIT_FINGER_ON, - IMGDEV_STATE_CAPTURE, - IMGDEV_STATE_AWAIT_FINGER_OFF, -}; - -/** - * fp_imgdev_enroll_state: - * @IMG_ACQUIRE_STATE_NONE: doing nothing - * @IMG_ACQUIRE_STATE_ACTIVATING: activating the device - * @IMG_ACQUIRE_STATE_AWAIT_FINGER_ON: waiting for the finger to be pressed or swiped - * @IMG_ACQUIRE_STATE_AWAIT_IMAGE: waiting for the image to be captured - * @IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF: waiting for the finger to be removed - * @IMG_ACQUIRE_STATE_DONE: enrollment has all the images it needs - * @IMG_ACQUIRE_STATE_DEACTIVATING: deactivating the device - * - * The state of an imaging device while enrolling a fingerprint. Given that enrollment - * requires multiple captures, a number of those states will be repeated before - * the state is @IMG_ACQUIRE_STATE_DONE. - */ -enum fp_imgdev_enroll_state { - IMG_ACQUIRE_STATE_NONE = 0, - IMG_ACQUIRE_STATE_ACTIVATING, - IMG_ACQUIRE_STATE_AWAIT_FINGER_ON, - IMG_ACQUIRE_STATE_AWAIT_IMAGE, - IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF, - IMG_ACQUIRE_STATE_DONE, - IMG_ACQUIRE_STATE_DEACTIVATING, -}; - -void fpi_imgdev_open_complete(struct fp_img_dev *imgdev, int status); -void fpi_imgdev_close_complete(struct fp_img_dev *imgdev); -void fpi_imgdev_activate_complete(struct fp_img_dev *imgdev, int status); -void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev); -void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev, - gboolean present); -void fpi_imgdev_image_captured(struct fp_img_dev *imgdev, struct fp_img *img); -void fpi_imgdev_abort_scan(struct fp_img_dev *imgdev, int result); -void fpi_imgdev_session_error(struct fp_img_dev *imgdev, int error); - -enum fp_imgdev_enroll_state fpi_imgdev_get_action_state(struct fp_img_dev *imgdev); -enum fp_imgdev_action fpi_imgdev_get_action(struct fp_img_dev *imgdev); -int fpi_imgdev_get_action_result(struct fp_img_dev *imgdev); -void fpi_imgdev_set_action_result(struct fp_img_dev *imgdev, int action_result); - -#endif diff --git a/libfprint/fpi-dev.c b/libfprint/fpi-dev.c deleted file mode 100644 index 219a2a1a..00000000 --- a/libfprint/fpi-dev.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * fp_dev types manipulation - * Copyright (C) 2018 Bastien Nocera - * - * 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 "fp_internal.h" -#include - -/** - * SECTION:fpi-dev - * @title: Device operations - * @short_description: Device operation functions - * - * Those macros and functions will help get access to and from struct #fp_dev, - * and struct #fp_img_dev types, as well as get and set the instance struct - * data, eg. the structure containing the data specific to each driver. - */ - -/** - * FP_DEV: - * @dev: a struct #fp_img_dev - * - * Returns the struct #fp_dev associated with @dev, or %NULL on failure. - * - * Returns: a struct #fp_dev or %NULL - */ -struct fp_dev * -FP_DEV(struct fp_img_dev *dev) -{ - struct fp_img_dev *imgdev; - - g_return_val_if_fail (dev, NULL); - imgdev = (struct fp_img_dev *) dev; - return imgdev->parent; -} - -/** - * FP_IMG_DEV: - * @dev: a struct #fp_dev representing an imaging device. - * - * Returns a struct #fp_img_dev associated with @dev, or %NULL on failure. - * - * Returns: a struct #fp_img_dev or %NULL - */ -struct fp_img_dev * -FP_IMG_DEV(struct fp_dev *dev) -{ - g_return_val_if_fail (dev, NULL); - g_return_val_if_fail (dev->drv, NULL); - g_return_val_if_fail (dev->drv->type == DRIVER_IMAGING, NULL); - return dev->img_dev; -} - -/** - * fp_dev_set_instance_data: - * @dev: a struct #fp_dev - * @instance_data: a pointer to the instance data - * - * Set the instance data for a struct #fp_dev. This is usually a structure - * private to the driver used to keep state and pass it as user_data to - * asynchronous functions. - * - * The core does not do any memory management for this data, so the driver - * itself will have to create and free its own structure when appropriate. - */ -void -fp_dev_set_instance_data (struct fp_dev *dev, - void *instance_data) -{ - g_return_if_fail (dev); - g_return_if_fail (instance_data != NULL); - g_return_if_fail (dev->instance_data == NULL); - - dev->instance_data = instance_data; -} - -/** - * FP_INSTANCE_DATA: - * @dev: a struct #fp_dev - * - * Returns the instance data set using fp_dev_set_instance_data(). - */ -void * -FP_INSTANCE_DATA (struct fp_dev *dev) -{ - g_return_val_if_fail (dev, NULL); - - return dev->instance_data; -} - -/** - * fpi_dev_get_usb_dev: - * @dev: a struct #fp_dev - * - * Returns the #libusb_device_handle associated with @dev or %NULL - * if none are associated. - * - * Returns: a #libusb_device_handle pointer or %NULL - */ -libusb_device_handle * -fpi_dev_get_usb_dev(struct fp_dev *dev) -{ - return dev->udev; -} - -/** - * fpi_dev_set_nr_enroll_stages: - * @dev: a struct #fp_dev - * @nr_enroll_stages: the number of enroll stages - * - * Sets the number of enroll stages that this device uses. This is - * usually only necessary for primitive devices which have a hard-coded - * number of enroll stages baked into their protocol. - */ -void -fpi_dev_set_nr_enroll_stages(struct fp_dev *dev, - int nr_enroll_stages) -{ - dev->nr_enroll_stages = nr_enroll_stages; -} - -/** - * fpi_dev_get_verify_data: - * @dev: a struct #fp_dev - * - * Returns the verify data associated with @dev. - * This is usually only necessary for primitive devices which need to - * have access to the raw verify data as it might have been stored on disk. - * - * Returns: a struct #fp_print_data pointer or %NULL - */ -struct fp_print_data * -fpi_dev_get_verify_data(struct fp_dev *dev) -{ - return dev->verify_data; -} diff --git a/libfprint/fpi-dev.h b/libfprint/fpi-dev.h deleted file mode 100644 index 98433912..00000000 --- a/libfprint/fpi-dev.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2018 Bastien Nocera - * - * 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 - */ - -#ifndef __FPI_DEV_H__ -#define __FPI_DEV_H__ - -#include -#include - -struct fp_dev; - -/** - * fp_img_dev: - * - * #fp_img_dev is an opaque structure type. You must access it using the - * appropriate functions. - */ -struct fp_img_dev; - -struct fp_dev *FP_DEV (struct fp_img_dev *dev); -struct fp_img_dev *FP_IMG_DEV (struct fp_dev *dev); - -void fp_dev_set_instance_data (struct fp_dev *dev, - void *instance_data); -void *FP_INSTANCE_DATA (struct fp_dev *dev); - -libusb_device_handle *fpi_dev_get_usb_dev(struct fp_dev *dev); -void fpi_dev_set_nr_enroll_stages(struct fp_dev *dev, - int nr_enroll_stages); -struct fp_print_data *fpi_dev_get_verify_data(struct fp_dev *dev); - -#endif diff --git a/libfprint/fpi-device.h b/libfprint/fpi-device.h new file mode 100644 index 00000000..a206798e --- /dev/null +++ b/libfprint/fpi-device.h @@ -0,0 +1,252 @@ +/* + * FpDevice - A fingerprint reader device + * Copyright (C) 2019 Benjamin Berg + * + * 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 +#include "fp-device.h" +#include "fp-image.h" +#include "fpi-print.h" + +/** + * FpIdEntry: + * + * An entry in the table of supported hardware. For USB devices, the product ID + * and vendor ID should be provided. The optional @driver_data field defaults + * to 0 and can be used as a simple flag for device quirks. + */ +typedef struct _FpIdEntry FpIdEntry; + +struct _FpIdEntry +{ + union + { + struct + { + guint pid; + guint vid; + }; + const gchar *virtual_envvar; + }; + guint64 driver_data; +}; + +/** + * FpDeviceClass: + * @id: ID string for the driver. Should be a valid C identifier and should + * match the drivers file name. + * @full_name: Human readable description of the driver + * @type: The type of driver + * @id_table: The table of IDs to bind the driver to + * @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 + * fpi_device_set_scan_type() from @probe if this is dynamic. + * @usb_discover: Class method to check whether a USB device is supported by + * the driver. Should return 0 if the device is unsupported and a positive + * score otherwise. The default score is 50 and the driver with the highest + * score will be loaded. + * @probe: Called immediately for all devices. Most drivers will not need to + * implement this. Drivers should setup the device identifier from the probe + * callback which will be used to verify the compatibility of stored + * #FpPrint's. It is permissable to temporarily open the USB device if this + * is required for the operation. If an error is returned, then the device + * will be destroyed again immediately and never reported to the API user. + * @open: Open the device for futher operations. Any of the normal actions are + * guaranteed to only happen when the device is open (this includes delete). + * @close: Close the device again + * @enroll: Start an enroll operation + * @verify: Start a verify operation + * @identify: Start an identify operation + * @capture: Start a capture operation + * @list: List prints stored on the device + * @delete: Delete a print from the device + * @cancel: Called on cancellation, this is a convenience to not need to handle + * the #GCancellable directly by using fpi_device_get_cancellable(). + * + * NOTE: If your driver is image based, then you should subclass #FpImageDevice + * instead. #FpImageDevice based drivers use a different way of interacting + * with libfprint. + * + * 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). + * + * Drivers must eventually call the corresponding function to finish the + * operation. It is also acceptable to call the generic + * fpi_device_action_error() function but doing so is not recommended in most + * usecases. + * + * Drivers must also handle cancellation properly for any long running + * operation (i.e. any operation that requires capturing). It is entirely fine + * to ignore cancellation requests for short operations (e.g. open/close). + * + * This API is solely intended for drivers. It is purely internal and neither + * API nor ABI stable. + */ +struct _FpDeviceClass +{ + /*< private >*/ + GObjectClass parent_class; + + /*< public >*/ + /* Static information about the driver. */ + const gchar *id; + const gchar *full_name; + FpDeviceType type; + const FpIdEntry *id_table; + + /* Defaults for device properties */ + gint nr_enroll_stages; + FpScanType scan_type; + + /* Callbacks */ + gint (*usb_discover) (GUsbDevice *usb_device); + void (*probe) (FpDevice *device); + void (*open) (FpDevice *device); + void (*close) (FpDevice *device); + void (*enroll) (FpDevice *device); + void (*verify) (FpDevice *device); + void (*identify) (FpDevice *device); + void (*capture) (FpDevice *device); + void (*list) (FpDevice *device); + void (*delete) (FpDevice * device); + + void (*cancel) (FpDevice *device); +}; + +/** + * FpTimeoutFunc: + * @device: The #FpDevice passed to fpi_device_add_timeout() + * @user_data: the data passed to fpi_device_add_timeout() + * + * The prototype of the callback function for fpi_device_add_timeout(). + */ +typedef void (*FpTimeoutFunc) (FpDevice *device, + gpointer user_data); + +/** + * FpDeviceAction: + * @FP_DEVICE_ACTION_NONE: No action is active. + * @FP_DEVICE_ACTION_PROBE: Probe device for support and information. + * @FP_DEVICE_ACTION_OPEN: Device is currently being opened. + * @FP_DEVICE_ACTION_CLOSE: Device is currently being closed. + * @FP_DEVICE_ACTION_ENROLL: Device is currently enrolling. + * @FP_DEVICE_ACTION_VERIFY: Device is currently verifying. + * @FP_DEVICE_ACTION_IDENTIFY: Device is currently identifying. + * @FP_DEVICE_ACTION_CAPTURE: Device is currently capturing an image. + * @FP_DEVICE_ACTION_LIST: Device stored prints are being queried. + * @FP_DEVICE_ACTION_DELETE: Device stored print is being deleted. + * + * Current active action of the device. A driver can retrieve the action. + */ +typedef enum { + FP_DEVICE_ACTION_NONE = 0, + FP_DEVICE_ACTION_PROBE, + FP_DEVICE_ACTION_OPEN, + FP_DEVICE_ACTION_CLOSE, + FP_DEVICE_ACTION_ENROLL, + FP_DEVICE_ACTION_VERIFY, + FP_DEVICE_ACTION_IDENTIFY, + FP_DEVICE_ACTION_CAPTURE, + FP_DEVICE_ACTION_LIST, + FP_DEVICE_ACTION_DELETE, +} FpDeviceAction; + +GUsbDevice *fpi_device_get_usb_device (FpDevice *device); +const gchar *fpi_device_get_virtual_env (FpDevice *device); +//const gchar *fpi_device_get_spi_dev (FpDevice *device); + + +FpDeviceAction fpi_device_get_current_action (FpDevice *device); +gboolean fpi_device_action_is_cancelled (FpDevice *device); + +GError * fpi_device_retry_new (FpDeviceRetry error); +GError * fpi_device_error_new (FpDeviceError error); + +GError * fpi_device_retry_new_msg (FpDeviceRetry error, + const gchar *msg); +GError * fpi_device_error_new_msg (FpDeviceError error, + const gchar *msg); + +guint64 fpi_device_get_driver_data (FpDevice *device); + +void fpi_device_get_enroll_data (FpDevice *device, + FpPrint **print); + +void fpi_device_get_capture_data (FpDevice *device, + gboolean *wait_for_finger); +void fpi_device_get_verify_data (FpDevice *device, + FpPrint **print); +void fpi_device_get_identify_data (FpDevice *device, + GPtrArray **prints); +void fpi_device_get_delete_data (FpDevice *device, + FpPrint **print); +GCancellable *fpi_device_get_cancellable (FpDevice *device); + + + +GSource * fpi_device_add_timeout (FpDevice *device, + gint interval, + FpTimeoutFunc func, + gpointer user_data); + +void fpi_device_set_nr_enroll_stages (FpDevice *device, + gint enroll_stages); + +void fpi_device_set_scan_type (FpDevice *device, + FpScanType scan_type); + +void fpi_device_action_error (FpDevice *device, + GError *error); + +void fpi_device_probe_complete (FpDevice *device, + const gchar *device_id, + const gchar *device_name, + GError *error); +void fpi_device_open_complete (FpDevice *device, + GError *error); +void fpi_device_close_complete (FpDevice *device, + GError *error); +void fpi_device_enroll_complete (FpDevice *device, + FpPrint *print, + GError *error); +void fpi_device_verify_complete (FpDevice *device, + FpiMatchResult result, + FpPrint *print, + GError *error); +void fpi_device_identify_complete (FpDevice *device, + FpPrint *match, + FpPrint *print, + GError *error); +void fpi_device_capture_complete (FpDevice *device, + FpImage *image, + GError *error); +void fpi_device_delete_complete (FpDevice *device, + GError *error); +void fpi_device_list_complete (FpDevice *device, + GPtrArray *prints, + GError *error); + +void fpi_device_enroll_progress (FpDevice *device, + gint completed_stages, + FpPrint *print, + GError *error); + +G_END_DECLS diff --git a/libfprint/fpi-image-device.h b/libfprint/fpi-image-device.h new file mode 100644 index 00000000..06d1a647 --- /dev/null +++ b/libfprint/fpi-image-device.h @@ -0,0 +1,118 @@ +/* + * FpImageDevice - An image based fingerprint reader device + * Copyright (C) 2019 Benjamin Berg + * + * 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-device.h" +#include "fp-image-device.h" + +/** + * FpImageDeviceState: + * @FP_IMAGE_DEVICE_STATE_INACTIVE: inactive + * @FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON: waiting for the finger to be pressed or swiped + * @FP_IMAGE_DEVICE_STATE_CAPTURE: capturing an image + * @FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: waiting for the finger to be removed + * + * The state of an imaging device while doing a capture. The state is + * passed through to the driver using the ::activate() or ::change_state() vfuncs. + * + * 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. + */ +typedef enum { + FP_IMAGE_DEVICE_STATE_INACTIVE, + FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON, + FP_IMAGE_DEVICE_STATE_CAPTURE, + FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF, +} FpImageDeviceState; + +/** + * FpImageDeviceClass: + * @bz3_threshold: Threshold to consider bozorth3 score a match, default: 40 + * @img_width: Width of the image, only provide if constant + * @img_height: Height of the image, only provide if constant + * @img_open: Open the device and do basic initialization + * (use this instead of the #FpDeviceClass open vfunc) + * @img_close: Close the device + * (use this instead of the #FpDeviceClass close vfunc) + * @activate: Start image capture and finger detection + * @deactivate: Stop image capture and finger detection + * @change_state: Notification about the current device state (i.e. waiting for + * 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). + * + * Drivers *must* eventually call the corresponding function to finish the + * operation. It is also acceptable to call the generic + * fpi_device_action_error() function but doing so is not recommended in most + * usecases. + * + * Drivers *must* also handle cancellation properly for any long running + * operation (i.e. any operation that requires capturing). It is entirely fine + * to ignore cancellation requests for short operations (e.g. open/close). + * + * This API is solely intended for drivers. It is purely internal and neither + * API nor ABI stable. + */ +struct _FpImageDeviceClass +{ + FpDeviceClass parent_class; + + gint bz3_threshold; + gint img_width; + gint img_height; + + void (*img_open) (FpImageDevice *dev); + void (*img_close) (FpImageDevice *dev); + void (*activate) (FpImageDevice *dev); + void (*change_state) (FpImageDevice *dev, + FpImageDeviceState state); + void (*deactivate) (FpImageDevice *dev); +}; + +void fpi_image_device_set_bz3_threshold (FpImageDevice *self, + gint bz3_threshold); + +void fpi_image_device_session_error (FpImageDevice *self, + GError *error); + +void fpi_image_device_open_complete (FpImageDevice *self, + GError *error); +void fpi_image_device_close_complete (FpImageDevice *self, + GError *error); +void fpi_image_device_activate_complete (FpImageDevice *self, + GError *error); +void fpi_image_device_deactivate_complete (FpImageDevice *self, + GError *error); + +void fpi_image_device_report_finger_status (FpImageDevice *self, + gboolean present); +void fpi_image_device_image_captured (FpImageDevice *self, + FpImage *image); +void fpi_image_device_retry_scan (FpImageDevice *self, + FpDeviceRetry retry); diff --git a/libfprint/fpi-image.h b/libfprint/fpi-image.h new file mode 100644 index 00000000..dd6dbf88 --- /dev/null +++ b/libfprint/fpi-image.h @@ -0,0 +1,83 @@ +/* + * FPrint Image + * Copyright (C) 2007 Daniel Drake + * Copyright (C) 2019 Benjamin Berg + * + * 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 +#include "fp-image.h" + +/** + * FpiImageFlags: + * @FPI_IMAGE_V_FLIPPED: the image is vertically flipped + * @FPI_IMAGE_H_FLIPPED: the image is horizontally flipped + * @FPI_IMAGE_COLORS_INVERTED: the colours are inverted + * + * Flags used in an #FpImage structure to describe the contained image. + * This is useful for image drivers as they can simply set these flags and + * rely on the image to be normalized by libfprint before further processing. + */ +typedef enum { + FPI_IMAGE_V_FLIPPED = 1 << 0, + FPI_IMAGE_H_FLIPPED = 1 << 1, + FPI_IMAGE_COLORS_INVERTED = 1 << 2, +} FpiImageFlags; + +/** + * FpImage: + * @width: Width of the image + * @height: Height of the image + * @ppmm: Pixels per millimeter + * @flags: #FpiImageFlags for required normalization + * + * Structure holding an image. The public fields are only public for internal + * use by the drivers. + */ +struct _FpImage +{ + /*< private >*/ + GObject parent; + + /*< public >*/ + guint width; + guint height; + + gdouble ppmm; + + FpiImageFlags flags; + + /*< private >*/ + guint8 *data; + guint8 *binarized; + + GPtrArray *minutiae; + guint ref_count; +}; + +gint fpi_std_sq_dev (const guint8 *buf, + gint size); +gint fpi_mean_sq_diff_norm (const guint8 *buf1, + const guint8 *buf2, + gint size); + +#if HAVE_PIXMAN +FpImage *fpi_image_resize (FpImage *orig, + guint w_factor, + guint h_factor); +#endif diff --git a/libfprint/fpi-img-pixman.c b/libfprint/fpi-img-pixman.c deleted file mode 100644 index 1c1bedb9..00000000 --- a/libfprint/fpi-img-pixman.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Imaging utility functions for libfprint - * Copyright (C) 2007-2008 Daniel Drake - * Copyright (C) 2013 Vasily Khoruzhick - * - * 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 -#include - -#include "fp_internal.h" - -/** - * fpi_img_resize: - * @img: an #fp_img image - * @w_factor: horizontal factor to resize the image by - * @h_factor: vertical factor to resize the image by - * - * Resizes the #fp_img image by scaling it by @w_factor times horizontally - * and @h_factor times vertically. - * - * Returns: a newly allocated #fp_img, the original @img will not be modified - * and will also need to be freed - */ -struct fp_img *fpi_img_resize(struct fp_img *img, unsigned int w_factor, unsigned int h_factor) -{ - int new_width = img->width * w_factor; - int new_height = img->height * h_factor; - pixman_image_t *orig, *resized; - pixman_transform_t transform; - struct fp_img *newimg; - - orig = pixman_image_create_bits(PIXMAN_a8, img->width, img->height, (uint32_t *)img->data, img->width); - resized = pixman_image_create_bits(PIXMAN_a8, new_width, new_height, NULL, new_width); - - pixman_transform_init_identity(&transform); - pixman_transform_scale(NULL, &transform, pixman_int_to_fixed(w_factor), pixman_int_to_fixed(h_factor)); - pixman_image_set_transform(orig, &transform); - pixman_image_set_filter(orig, PIXMAN_FILTER_BILINEAR, NULL, 0); - pixman_image_composite32(PIXMAN_OP_SRC, - orig, /* src */ - NULL, /* mask */ - resized, /* dst */ - 0, 0, /* src x y */ - 0, 0, /* mask x y */ - 0, 0, /* dst x y */ - new_width, new_height /* width height */ - ); - - newimg = fpi_img_new(new_width * new_height); - newimg->width = new_width; - newimg->height = new_height; - newimg->flags = img->flags; - - memcpy(newimg->data, pixman_image_get_data(resized), new_width * new_height); - - pixman_image_unref(orig); - pixman_image_unref(resized); - - return newimg; -} - diff --git a/libfprint/fpi-img.c b/libfprint/fpi-img.c deleted file mode 100644 index c7f44c24..00000000 --- a/libfprint/fpi-img.c +++ /dev/null @@ -1,682 +0,0 @@ -/* - * Image management functions for libfprint - * Copyright (C) 2007 Daniel Drake - * - * 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 -#include -#include -#include - -#include - -#include "fp_internal.h" -#include "nbis/include/bozorth.h" -#include "nbis/include/lfs.h" - -/** - * SECTION:img - * @title: Image operations - * @short_description: Image operation functions - * - * libfprint offers several ways of retrieving images from imaging devices, - * one example being the fp_dev_img_capture() function. The functions - * documented below allow you to work with such images. - * - * # Image format # {#img_fmt} - * All images are represented as 8-bit greyscale data. - * - * # Image standardization # {#img_std} - * In some contexts, images you are provided through libfprint are raw images - * from the hardware. The orientation of these varies from device-to-device, - * as does the color scheme (black-on-white or white-on-black?). libfprint - * provides the fp_img_standardize() function to convert images into standard - * form, which is defined to be: finger flesh as black on white surroundings, - * natural upright orientation. - */ - -/** - * SECTION:fpi-img - * @title: Driver Image operations - * @short_description: Driver image operation functions - * - * Those are the driver-specific helpers for #fp_img manipulation. See #fp_img's - * documentation for more information about data formats, and their uses in - * front-end applications. - */ - -/** - * fpi_img_new: - * @length: the length of data to allocate - * - * Creates a new #fp_img structure with @length bytes of data allocated - * to hold the image. - * - * Returns: a new #fp_img to free with fp_img_free() - */ -struct fp_img *fpi_img_new(size_t length) -{ - struct fp_img *img = g_malloc0(sizeof(*img) + length); - fp_dbg("length=%zd", length); - img->length = length; - return img; -} - -/** - * fpi_img_new_for_imgdev: - * @imgdev: a #fp_img_dev imaging fingerprint device - * - * Creates a new #fp_img structure, like fpi_img_new(), but uses the - * driver's advertised height and width to calculate the size of the - * length of data to allocate. - * - * Returns: a new #fp_img to free with fp_img_free() - */ -struct fp_img *fpi_img_new_for_imgdev(struct fp_img_dev *imgdev) -{ - struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(FP_DEV(imgdev)->drv); - int width = imgdrv->img_width; - int height = imgdrv->img_height; - struct fp_img *img = fpi_img_new(width * height); - img->width = width; - img->height = height; - return img; -} - -/** - * fpi_img_is_sane: - * @img: a #fp_img image - * - * Checks whether an #fp_img structure passes some basic checks, such - * as length, width and height being non-zero, and the buffer being - * big enough to hold the image of said size. - * - * Returns: %TRUE if the image is sane, %FALSE otherwise - */ -gboolean fpi_img_is_sane(struct fp_img *img) -{ - guint len; - - /* basic checks */ - if (!img->length || img->width <= 0 || img->height <= 0) - return FALSE; - - /* Are width and height just too big? */ - if (!g_uint_checked_mul(&len, img->width, img->height) || - len > G_MAXINT) - return FALSE; - - /* buffer big enough? */ - if (len > img->length) - return FALSE; - - return TRUE; -} - -/** - * fpi_img_realloc: - * @img: an #fp_img image - * @newsize: the new length of the image - * - * Changes the size of the data part of the #fp_img. - * - * Returns: the modified #fp_img, the same as the first argument to this function - */ -struct fp_img *fpi_img_realloc(struct fp_img *img, size_t newsize) -{ - return g_realloc(img, sizeof(*img) + newsize); -} - -/** - * fp_img_free: - * @img: the image to destroy. If %NULL, function simply returns. - * - * Frees an image. Must be called when you are finished working with an image. - */ -API_EXPORTED void fp_img_free(struct fp_img *img) -{ - if (!img) - return; - - if (img->minutiae) - free_minutiae(img->minutiae); - if (img->binarized) - free(img->binarized); - g_free(img); -} - -/** - * fp_img_get_height: - * @img: an image - * - * Gets the pixel height of an image. - * - * Returns: the height of the image - */ -API_EXPORTED int fp_img_get_height(struct fp_img *img) -{ - return img->height; -} - -/** - * fp_img_get_width: - * @img: an image - * - * Gets the pixel width of an image. - * - * Returns: the width of the image - */ -API_EXPORTED int fp_img_get_width(struct fp_img *img) -{ - return img->width; -} - -/** - * fp_img_get_data: - * @img: an image - * - * Gets the greyscale data for an image. This data must not be modified or - * freed, and must not be used after fp_img_free() has been called. - * - * Returns: a pointer to libfprint's internal data for the image - */ -API_EXPORTED unsigned char *fp_img_get_data(struct fp_img *img) -{ - return img->data; -} - -/** - * fp_img_save_to_file: - * @img: the image to save - * @path: the path to save the image. Existing files will be overwritten. - * - * A quick convenience function to save an image to a file in - * [PGM format](http://netpbm.sourceforge.net/doc/pgm.html). - * - * Returns: 0 on success, non-zero on error. - */ -API_EXPORTED int fp_img_save_to_file(struct fp_img *img, char *path) -{ - FILE *fd = fopen(path, "w"); - size_t write_size = img->width * img->height; - int r; - - if (!fd) { - fp_dbg("could not open '%s' for writing: %d", path, errno); - return -errno; - } - - r = fprintf(fd, "P5 %d %d 255\n", img->width, img->height); - if (r < 0) { - fclose(fd); - fp_err("pgm header write failed, error %d", r); - return r; - } - - r = fwrite(img->data, 1, write_size, fd); - if (r < write_size) { - fclose(fd); - fp_err("short write (%d)", r); - return -EIO; - } - - fclose(fd); - fp_dbg("written to '%s'", path); - return 0; -} - -static void vflip(struct fp_img *img) -{ - int width = img->width; - int data_len = img->width * img->height; - unsigned char rowbuf[width]; - int i; - - for (i = 0; i < img->height / 2; i++) { - int offset = i * width; - int swap_offset = data_len - (width * (i + 1)); - - /* copy top row into buffer */ - memcpy(rowbuf, img->data + offset, width); - - /* copy lower row over upper row */ - memcpy(img->data + offset, img->data + swap_offset, width); - - /* copy buffer over lower row */ - memcpy(img->data + swap_offset, rowbuf, width); - } -} - -static void hflip(struct fp_img *img) -{ - int width = img->width; - unsigned char rowbuf[width]; - int i, j; - - for (i = 0; i < img->height; i++) { - int offset = i * width; - - memcpy(rowbuf, img->data + offset, width); - for (j = 0; j < width; j++) - img->data[offset + j] = rowbuf[width - j - 1]; - } -} - -static void invert_colors(struct fp_img *img) -{ - int data_len = img->width * img->height; - int i; - for (i = 0; i < data_len; i++) - img->data[i] = 0xff - img->data[i]; -} - -/** - * fp_img_standardize: - * @img: the image to standardize - * - * [Standardizes](libfprint-Image-operations.html#img_std) an image by normalizing its orientation, colors, - * etc. It is safe to call this multiple times on an image, libfprint keeps - * track of the work it needs to do to make an image standard and will not - * perform these operations more than once for a given image. - */ -API_EXPORTED void fp_img_standardize(struct fp_img *img) -{ - if (img->flags & FP_IMG_V_FLIPPED) { - vflip(img); - img->flags &= ~FP_IMG_V_FLIPPED; - } - if (img->flags & FP_IMG_H_FLIPPED) { - hflip(img); - img->flags &= ~FP_IMG_H_FLIPPED; - } - if (img->flags & FP_IMG_COLORS_INVERTED) { - invert_colors(img); - img->flags &= ~FP_IMG_COLORS_INVERTED; - } -} - -/* Based on write_minutiae_XYTQ and bz_load */ -static void minutiae_to_xyt(struct fp_minutiae *minutiae, int bwidth, - int bheight, unsigned char *buf) -{ - int i; - struct fp_minutia *minutia; - struct minutiae_struct c[MAX_FILE_MINUTIAE]; - struct xyt_struct *xyt = (struct xyt_struct *) buf; - - /* struct xyt_struct uses arrays of MAX_BOZORTH_MINUTIAE (200) */ - int nmin = min(minutiae->num, MAX_BOZORTH_MINUTIAE); - - for (i = 0; i < nmin; i++){ - minutia = minutiae->list[i]; - - lfs2nist_minutia_XYT(&c[i].col[0], &c[i].col[1], &c[i].col[2], - minutia, bwidth, bheight); - c[i].col[3] = sround(minutia->reliability * 100.0); - - if (c[i].col[2] > 180) - c[i].col[2] -= 360; - } - - qsort((void *) &c, (size_t) nmin, sizeof(struct minutiae_struct), - sort_x_y); - - for (i = 0; i < nmin; i++) { - xyt->xcol[i] = c[i].col[0]; - xyt->ycol[i] = c[i].col[1]; - xyt->thetacol[i] = c[i].col[2]; - } - xyt->nrows = nmin; -} - -#define FP_IMG_STANDARDIZATION_FLAGS (FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED \ - | FP_IMG_COLORS_INVERTED) - -static int fpi_img_detect_minutiae(struct fp_img *img) -{ - struct fp_minutiae *minutiae; - int r; - int *direction_map, *low_contrast_map, *low_flow_map; - int *high_curve_map, *quality_map; - int map_w, map_h; - unsigned char *bdata; - int bw, bh, bd; - GTimer *timer; - - if (img->flags & FP_IMG_STANDARDIZATION_FLAGS) { - fp_err("Cannot detect minutiae for non-standardized images"); - return -EINVAL; - } - - /* 25.4 mm per inch */ - timer = g_timer_new(); - r = get_minutiae(&minutiae, &quality_map, &direction_map, - &low_contrast_map, &low_flow_map, &high_curve_map, - &map_w, &map_h, &bdata, &bw, &bh, &bd, - img->data, img->width, img->height, 8, - DEFAULT_PPI / (double)25.4, &g_lfsparms_V2); - g_timer_stop(timer); - fp_dbg("minutiae scan completed in %f secs", g_timer_elapsed(timer, NULL)); - g_timer_destroy(timer); - if (r) { - fp_err("get minutiae failed, code %d", r); - return r; - } - fp_dbg("detected %d minutiae", minutiae->num); - img->minutiae = minutiae; - img->binarized = bdata; - - free(quality_map); - free(direction_map); - free(low_contrast_map); - free(low_flow_map); - free(high_curve_map); - return minutiae->num; -} - -int fpi_img_to_print_data(struct fp_img_dev *imgdev, struct fp_img *img, - struct fp_print_data **ret) -{ - struct fp_print_data *print; - struct fp_print_data_item *item; - int r; - - if (!img->minutiae) { - r = fpi_img_detect_minutiae(img); - if (r < 0) - return r; - if (!img->minutiae) { - fp_err("no minutiae after successful detection?"); - return -ENOENT; - } - } - - /* FIXME: space is wasted if we don't hit the max minutiae count. would - * be good to make this dynamic. */ - print = fpi_print_data_new(FP_DEV(imgdev)); - item = fpi_print_data_item_new(sizeof(struct xyt_struct)); - print->type = PRINT_DATA_NBIS_MINUTIAE; - minutiae_to_xyt(img->minutiae, img->width, img->height, item->data); - print->prints = g_slist_prepend(print->prints, item); - - /* FIXME: the print buffer at this point is endian-specific, and will - * only work when loaded onto machines with identical endianness. not good! - * data format should be platform-independent. */ - *ret = print; - - return 0; -} - -int fpi_img_compare_print_data(struct fp_print_data *enrolled_print, - struct fp_print_data *new_print) -{ - int score, max_score = 0, probe_len; - struct xyt_struct *pstruct = NULL; - struct xyt_struct *gstruct = NULL; - struct fp_print_data_item *data_item; - GSList *list_item; - - if (enrolled_print->type != PRINT_DATA_NBIS_MINUTIAE || - new_print->type != PRINT_DATA_NBIS_MINUTIAE) { - fp_err("invalid print format"); - return -EINVAL; - } - - if (g_slist_length(new_print->prints) != 1) { - fp_err("new_print contains more than one sample, is it enrolled print?"); - return -EINVAL; - } - - data_item = new_print->prints->data; - pstruct = (struct xyt_struct *)data_item->data; - - probe_len = bozorth_probe_init(pstruct); - list_item = enrolled_print->prints; - do { - data_item = list_item->data; - gstruct = (struct xyt_struct *)data_item->data; - score = bozorth_to_gallery(probe_len, pstruct, gstruct); - fp_dbg("score %d", score); - max_score = max(score, max_score); - list_item = g_slist_next(list_item); - } while (list_item); - - return max_score; -} - -int fpi_img_compare_print_data_to_gallery(struct fp_print_data *print, - struct fp_print_data **gallery, int match_threshold, size_t *match_offset) -{ - struct xyt_struct *pstruct; - struct xyt_struct *gstruct; - struct fp_print_data *gallery_print; - struct fp_print_data_item *data_item; - int probe_len; - size_t i = 0; - int r; - GSList *list_item; - - if (g_slist_length(print->prints) != 1) { - fp_err("new_print contains more than one sample, is it enrolled print?"); - return -EINVAL; - } - - data_item = print->prints->data; - pstruct = (struct xyt_struct *)data_item->data; - - probe_len = bozorth_probe_init(pstruct); - while ((gallery_print = gallery[i++])) { - list_item = gallery_print->prints; - do { - data_item = list_item->data; - gstruct = (struct xyt_struct *)data_item->data; - r = bozorth_to_gallery(probe_len, pstruct, gstruct); - if (r >= match_threshold) { - *match_offset = i - 1; - return FP_VERIFY_MATCH; - } - list_item = g_slist_next(list_item); - } while (list_item); - } - return FP_VERIFY_NO_MATCH; -} - -/** - * fp_img_binarize: - * @img: a standardized image - * - * Get a binarized form of a standardized scanned image. This is where the - * fingerprint image has been "enhanced" and is a set of pure black ridges - * on a pure white background. Internally, image processing happens on top - * of the binarized image. - * - * The image must have been [standardized](libfprint-Image-operations.html#img_std) - * otherwise this function will fail. - * - * It is safe to binarize an image and free the original while continuing - * to use the binarized version. - * - * You cannot binarize an image twice. - * - * Returns: a new image representing the binarized form of the original, or - * %NULL on error. Must be freed with fp_img_free() after use. - */ -API_EXPORTED struct fp_img *fp_img_binarize(struct fp_img *img) -{ - struct fp_img *ret; - int height = img->height; - int width = img->width; - int imgsize = height * width; - - if (img->flags & FP_IMG_BINARIZED_FORM) { - fp_err("image already binarized"); - return NULL; - } - - if (!img->binarized) { - int r = fpi_img_detect_minutiae(img); - if (r < 0) - return NULL; - if (!img->binarized) { - fp_err("no minutiae after successful detection?"); - return NULL; - } - } - - ret = fpi_img_new(imgsize); - ret->flags |= FP_IMG_BINARIZED_FORM; - ret->width = width; - ret->height = height; - memcpy(ret->data, img->binarized, imgsize); - return ret; -} - -/** - * fp_img_get_minutiae: - * @img: a standardized image - * @nr_minutiae: an output location to store minutiae list length - * - * Get a list of minutiae detected in an image. A minutia point is a feature - * detected on a fingerprint, typically where ridges end or split. - * libfprint's image processing code relies upon comparing sets of minutiae, - * so accurate placement of minutia points is critical for good imaging - * performance. - * - * The image must have been [standardized](libfprint-Image-operations.html#img_std) - * otherwise this function will fail. - * - * You cannot pass a binarized image to this function. Instead, pass the - * original image. - * - * Returns a list of pointers to minutiae, where the list is of length - * indicated in the nr_minutiae output parameter. The returned list is only - * valid while the parent image has not been freed, and the minutiae data - * must not be modified or freed. - * - * Returns: a list of minutiae points. Must not be modified or freed. - */ -API_EXPORTED struct fp_minutia **fp_img_get_minutiae(struct fp_img *img, - int *nr_minutiae) -{ - if (img->flags & FP_IMG_BINARIZED_FORM) { - fp_err("image is binarized"); - return NULL; - } - - if (!img->minutiae) { - int r = fpi_img_detect_minutiae(img); - if (r < 0) - return NULL; - if (!img->minutiae) { - fp_err("no minutiae after successful detection?"); - return NULL; - } - } - - *nr_minutiae = img->minutiae->num; - return img->minutiae->list; -} - -/** - * fp_minutia_get_coords: - * @minutia: a struct #fp_minutia - * @coord_x: the return variable for the X coordinate of the minutia - * @coord_y: the return variable for the Y coordinate of the minutia - * - * Sets @coord_x and @coord_y to be the coordinates of the detected minutia, so it - * can be presented in a more verbose user interface. This is usually only - * used for debugging purposes. - * - * Returns: 0 on success, -1 on error. - */ -API_EXPORTED int fp_minutia_get_coords(struct fp_minutia *minutia, int *coord_x, int *coord_y) -{ - g_return_val_if_fail (minutia != NULL, -1); - g_return_val_if_fail (coord_x != NULL, -1); - g_return_val_if_fail (coord_y != NULL, -1); - - *coord_x = minutia->x; - *coord_y = minutia->y; - - return 0; -} - -/** - * fpi_std_sq_dev: - * @buf: buffer (usually bitmap, one byte per pixel) - * @size: size of @buffer - * - * Calculates the squared standard deviation of the individual - * pixels in the buffer, as per the following formula: - * |[ - * mean = sum (buf[0..size]) / size - * sq_dev = sum ((buf[0.size] - mean) ^ 2) - * ]| - * This function is usually used to determine whether image - * is empty. - * - * Returns: the squared standard deviation for @buffer - */ -int fpi_std_sq_dev(const unsigned char *buf, int size) -{ - int res = 0, mean = 0, i; - - if (size > (INT_MAX / 65536)) { - fp_err("%s: we might get an overflow!", __func__); - return -EOVERFLOW; - } - - for (i = 0; i < size; i++) - mean += buf[i]; - - mean /= size; - - for (i = 0; i < size; i++) { - int dev = (int)buf[i] - mean; - res += dev*dev; - } - - return res / size; -} - -/** - * fpi_mean_sq_diff_norm: - * @buf1: buffer (usually bitmap, one byte per pixel) - * @buf2: buffer (usually bitmap, one byte per pixel) - * @size: buffer size of smallest buffer - * - * This function calculates the normalized mean square difference of - * two buffers, usually two lines, as per the following formula: - * |[ - * sq_diff = sum ((buf1[0..size] - buf2[0..size]) ^ 2) / size - * ]| - * - * This functions is usually used to get numerical difference - * between two images. - * - * Returns: the normalized mean squared difference between @buf1 and @buf2 - */ -int fpi_mean_sq_diff_norm(unsigned char *buf1, unsigned char *buf2, int size) -{ - int res = 0, i; - for (i = 0; i < size; i++) { - int dev = (int)buf1[i] - (int)buf2[i]; - res += dev * dev; - } - - return res / size; -} diff --git a/libfprint/fpi-img.h b/libfprint/fpi-img.h deleted file mode 100644 index 4ebc3f39..00000000 --- a/libfprint/fpi-img.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2007-2008 Daniel Drake - * Copyright (C) 2018 Bastien Nocera - * - * 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 - */ - -#ifndef __FPI_IMG_H__ -#define __FPI_IMG_H__ - -#include - -struct fp_minutiae; - -/** - * FpiImgFlags: - * @FP_IMG_V_FLIPPED: the image is vertically flipped - * @FP_IMG_H_FLIPPED: the image is horizontally flipped - * @FP_IMG_COLORS_INVERTED: the colours are inverted - * @FP_IMG_BINARIZED_FORM: binarised image, see fp_img_binarize() - * @FP_IMG_PARTIAL: the image is partial, useful for driver to keep track - * of incomplete captures - * - * Flags used in the #fp_img structure to describe the image contained - * into the structure. Note that a number of functions will refuse to - * handle images which haven't been standardised through fp_img_standardize() - * (meaning the @FP_IMG_V_FLIPPED, @FP_IMG_H_FLIPPED and @FP_IMG_COLORS_INVERTED - * should all be unset when the image needs to be analysed). - */ -typedef enum { - FP_IMG_V_FLIPPED = 1 << 0, - FP_IMG_H_FLIPPED = 1 << 1, - FP_IMG_COLORS_INVERTED = 1 << 2, - FP_IMG_BINARIZED_FORM = 1 << 3, - FP_IMG_PARTIAL = 1 << 4 -} FpiImgFlags; - -/** - * fp_img: - * @width: the width of the image - * @height: the height of the image - * @length: the length of the data associated with the image - * @flags: @FpiImgFlags flags describing the image contained in the structure - * @minutiae: an opaque structure representing the detected minutiae - * @binarized: the binarized image data - * @data: the start of the image data, which will be of @length size. - * - * A structure representing a captured, or processed image. The @flags member - * will show its current state, including whether whether the binarized form - * if present, whether it is complete, and whether it needs particular changes - * before being processed. - */ -struct fp_img { - int width; - int height; - size_t length; - FpiImgFlags flags; - /*< private >*/ - struct fp_minutiae *minutiae; - /*< public >*/ - unsigned char *binarized; - unsigned char data[0]; -}; - -struct fp_img *fpi_img_new(size_t length); -struct fp_img *fpi_img_new_for_imgdev(struct fp_img_dev *imgdev); -struct fp_img *fpi_img_realloc(struct fp_img *img, size_t newsize); -struct fp_img *fpi_img_resize(struct fp_img *img, unsigned int w_factor, unsigned int h_factor); - -int fpi_std_sq_dev(const unsigned char *buf, int size); -int fpi_mean_sq_diff_norm(unsigned char *buf1, unsigned char *buf2, int size); - -#endif diff --git a/libfprint/fpi-log.h b/libfprint/fpi-log.h index 177e0f7e..1c3d5ade 100644 --- a/libfprint/fpi-log.h +++ b/libfprint/fpi-log.h @@ -80,19 +80,19 @@ * * Uses fp_err() to print an error if the @condition is true. */ -#define BUG_ON(condition) G_STMT_START \ - if (condition) { \ - char *s; \ - s = g_strconcat ("BUG: (", #condition, ")", NULL); \ - fp_err ("%s: %s() %s:%d", s, G_STRFUNC, __FILE__, __LINE__); \ - g_free (s); \ - } G_STMT_END +#define BUG_ON(condition) G_STMT_START \ + if (condition) { \ + char *s; \ + s = g_strconcat ("BUG: (", #condition, ")", NULL); \ + fp_err ("%s: %s() %s:%d", s, G_STRFUNC, __FILE__, __LINE__); \ + g_free (s); \ + } G_STMT_END /** * BUG: * * Same as BUG_ON() but is always true. */ -#define BUG() BUG_ON(1) +#define BUG() BUG_ON (1) #endif diff --git a/libfprint/fpi-poll.c b/libfprint/fpi-poll.c deleted file mode 100644 index 3f2c898f..00000000 --- a/libfprint/fpi-poll.c +++ /dev/null @@ -1,485 +0,0 @@ -/* - * Polling/timing management - * Copyright (C) 2008 Daniel Drake - * - * 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 "poll" - -#include "fp_internal.h" -#include "fpi-poll.h" - -#include -#include -#include -#include - -#include -#include - -/** - * SECTION:events - * @title: Initialisation and events handling - * @short_description: Initialisation and events handling functions - * - * These functions are only applicable to users of libfprint's asynchronous - * API. - * - * libfprint does not create internal library threads and hence can only - * execute when your application is calling a libfprint function. However, - * libfprint often has work to be do, such as handling of completed USB - * transfers, and processing of timeouts required in order for the library - * to function. Therefore it is essential that your own application must - * regularly "phone into" libfprint so that libfprint can handle any pending - * events. - * - * The function you must call is fp_handle_events() or a variant of it. This - * function will handle any pending events, and it is from this context that - * all asynchronous event callbacks from the library will occur. You can view - * this function as a kind of iteration function. - * - * If there are no events pending, fp_handle_events() will block for a few - * seconds (and will handle any new events should anything occur in that time). - * If you wish to customise this timeout, you can use - * fp_handle_events_timeout() instead. If you wish to do a non-blocking - * iteration, call fp_handle_events_timeout() with a zero timeout. - * - * How to integrate events handling depends on your main loop implementation. - * The sister fprintd project includes an implementation of main loop handling - * that integrates into GLib's main loop. The - * [libusb documentation](http://libusb.sourceforge.net/api-1.0/group__poll.html#details) - * also includes more details about how to integrate libfprint events into - * your main loop. - */ - -/** - * SECTION:fpi-poll - * @title: Timeouts - * @short_description: Timeout handling helpers - * - * Helper functions to schedule a function call to be made after a timeout. This - * is useful to avoid making blocking calls while waiting for hardware to answer - * for example. - */ - -/* this is a singly-linked list of pending timers, sorted with the timer that - * is expiring soonest at the head. */ -static GSList *active_timers = NULL; - -/* notifiers for added or removed poll fds */ -static fp_pollfd_added_cb fd_added_cb = NULL; -static fp_pollfd_removed_cb fd_removed_cb = NULL; - -struct fpi_timeout { - struct timeval expiry; - fpi_timeout_fn callback; - struct fp_dev *dev; - void *data; - char *name; -}; - -static int timeout_sort_fn(gconstpointer _a, gconstpointer _b) -{ - fpi_timeout *a = (fpi_timeout *) _a; - fpi_timeout *b = (fpi_timeout *) _b; - struct timeval *tv_a = &a->expiry; - struct timeval *tv_b = &b->expiry; - - if (timercmp(tv_a, tv_b, <)) - return -1; - else if (timercmp(tv_a, tv_b, >)) - return 1; - else - return 0; -} - -static void -fpi_timeout_free(fpi_timeout *timeout) -{ - if (timeout == NULL) - return; - - g_free(timeout->name); - g_free(timeout); -} - -/** - * fpi_timeout_set_name: - * @timeout: a #fpi_timeout - * @name: the name to give the timeout - * - * Sets a name for a timeout, allowing that name to be printed - * along with any timeout related debug. - */ -void -fpi_timeout_set_name(fpi_timeout *timeout, - const char *name) -{ - g_return_if_fail (timeout != NULL); - g_return_if_fail (name != NULL); - g_return_if_fail (timeout->name == NULL); - - timeout->name = g_strdup(name); -} - -/** - * fpi_timeout_add: - * @msec: the time before calling the function, in milliseconds (1/1000ths of a second) - * @callback: function to callback - * @dev: a struct #fp_dev - * @data: data to pass to @callback, or %NULL - * - * A timeout is the asynchronous equivalent of sleeping. You create a timeout - * saying that you'd like to have a function invoked at a certain time in - * the future. - * - * Note that you should hold onto the return value of this function to cancel it - * use fpi_timeout_cancel(), otherwise the callback could be called while the driver - * is being torn down. - * - * This function can be considered to never fail. - * - * Returns: an #fpi_timeout structure - */ -fpi_timeout *fpi_timeout_add(unsigned int msec, - fpi_timeout_fn callback, - struct fp_dev *dev, - void *data) -{ - struct timespec ts; - struct timeval add_msec; - fpi_timeout *timeout; - int r; - - g_return_val_if_fail (dev != NULL, NULL); - - fp_dbg("in %dms", msec); - - r = clock_gettime(CLOCK_MONOTONIC, &ts); - if (r < 0) { - fp_err("failed to read monotonic clock, errno=%d", errno); - BUG(); - return NULL; - } - - timeout = g_new0(fpi_timeout, 1); - timeout->callback = callback; - timeout->dev = dev; - timeout->data = data; - TIMESPEC_TO_TIMEVAL(&timeout->expiry, &ts); - - /* calculate timeout expiry by adding delay to current monotonic clock */ - timerclear(&add_msec); - add_msec.tv_sec = msec / 1000; - add_msec.tv_usec = (msec % 1000) * 1000; - timeradd(&timeout->expiry, &add_msec, &timeout->expiry); - - active_timers = g_slist_insert_sorted(active_timers, timeout, - timeout_sort_fn); - - return timeout; -} - -/** - * fpi_timeout_cancel: - * @timeout: an #fpi_timeout structure - * - * Cancels a timeout scheduled with fpi_timeout_add(), and frees the - * @timeout structure. - */ -void fpi_timeout_cancel(fpi_timeout *timeout) -{ - G_DEBUG_HERE(); - active_timers = g_slist_remove(active_timers, timeout); - fpi_timeout_free(timeout); -} - -/* get the expiry time and optionally the timeout structure for the next - * timeout. returns 0 if there are no expired timers, or 1 if the - * timeval/timeout output parameters were populated. if the returned timeval - * is zero then it means the timeout has already expired and should be handled - * ASAP. */ -static int get_next_timeout_expiry(struct timeval *out, - struct fpi_timeout **out_timeout) -{ - struct timespec ts; - struct timeval tv; - struct fpi_timeout *next_timeout; - int r; - - if (active_timers == NULL) - return 0; - - r = clock_gettime(CLOCK_MONOTONIC, &ts); - if (r < 0) { - fp_err("failed to read monotonic clock, errno=%d", errno); - return r; - } - TIMESPEC_TO_TIMEVAL(&tv, &ts); - - next_timeout = active_timers->data; - if (out_timeout) - *out_timeout = next_timeout; - - if (timercmp(&tv, &next_timeout->expiry, >=)) { - if (next_timeout->name) - fp_dbg("first timeout '%s' already expired", next_timeout->name); - else - fp_dbg("first timeout already expired"); - timerclear(out); - } else { - timersub(&next_timeout->expiry, &tv, out); - if (next_timeout->name) - fp_dbg("next timeout '%s' in %ld.%06lds", next_timeout->name, - out->tv_sec, out->tv_usec); - else - fp_dbg("next timeout in %ld.%06lds", out->tv_sec, out->tv_usec); - } - - return 1; -} - -/* handle a timeout that has expired */ -static void handle_timeout(struct fpi_timeout *timeout) -{ - G_DEBUG_HERE(); - timeout->callback(timeout->dev, timeout->data); - active_timers = g_slist_remove(active_timers, timeout); - fpi_timeout_free(timeout); -} - -static int handle_timeouts(void) -{ - struct timeval next_timeout_expiry; - struct fpi_timeout *next_timeout; - int r; - - r = get_next_timeout_expiry(&next_timeout_expiry, &next_timeout); - if (r <= 0) - return r; - - if (!timerisset(&next_timeout_expiry)) - handle_timeout(next_timeout); - - return 0; -} - -/** - * fp_handle_events_timeout: - * @timeout: Maximum timeout for this blocking function - * - * Handle any pending events. If a non-zero timeout is specified, the function - * will potentially block for the specified amount of time, although it may - * return sooner if events have been handled. The function acts as non-blocking - * for a zero timeout. - * - * Returns: 0 on success, non-zero on error. - */ -API_EXPORTED int fp_handle_events_timeout(struct timeval *timeout) -{ - struct timeval next_timeout_expiry; - struct timeval select_timeout; - struct fpi_timeout *next_timeout; - int r; - - r = get_next_timeout_expiry(&next_timeout_expiry, &next_timeout); - if (r < 0) - return r; - - if (r) { - /* timer already expired? */ - if (!timerisset(&next_timeout_expiry)) { - handle_timeout(next_timeout); - return 0; - } - - /* choose the smallest of next URB timeout or user specified timeout */ - if (timercmp(&next_timeout_expiry, timeout, <)) - select_timeout = next_timeout_expiry; - else - select_timeout = *timeout; - } else { - select_timeout = *timeout; - } - - r = libusb_handle_events_timeout(fpi_usb_ctx, &select_timeout); - *timeout = select_timeout; - if (r < 0) - return r; - - return handle_timeouts(); -} - -/** - * fp_handle_events: - * - * Convenience function for calling fp_handle_events_timeout() with a sensible - * default timeout value of two seconds (subject to change if we decide another - * value is more sensible). - * - * Returns: 0 on success, non-zero on error. - */ -API_EXPORTED int fp_handle_events(void) -{ - struct timeval tv; - tv.tv_sec = 2; - tv.tv_usec = 0; - return fp_handle_events_timeout(&tv); -} - -/** - * fp_get_next_timeout: - * @tv: a #timeval structure containing the duration to the next timeout. - * - * A zero filled @tv timeout means events are to be handled immediately - * - * Returns: returns 0 if no timeouts active, or 1 if timeout returned. - */ -API_EXPORTED int fp_get_next_timeout(struct timeval *tv) -{ - struct timeval fprint_timeout = { 0, 0 }; - struct timeval libusb_timeout = { 0, 0 }; - int r_fprint; - int r_libusb; - - r_fprint = get_next_timeout_expiry(&fprint_timeout, NULL); - r_libusb = libusb_get_next_timeout(fpi_usb_ctx, &libusb_timeout); - - /* if we have no pending timeouts and the same is true for libusb, - * indicate that we have no pending timouts */ - if (r_fprint <= 0 && r_libusb <= 0) - return 0; - - /* if fprint have no pending timeouts return libusb timeout */ - else if (r_fprint == 0) - *tv = libusb_timeout; - - /* if libusb have no pending timeouts return fprint timeout */ - else if (r_libusb == 0) - *tv = fprint_timeout; - - /* otherwise return the smaller of the 2 timeouts */ - else if (timercmp(&fprint_timeout, &libusb_timeout, <)) - *tv = fprint_timeout; - else - *tv = libusb_timeout; - return 1; -} - -/** - * fp_get_pollfds: - * @pollfds: output location for a list of pollfds. If non-%NULL, must be - * released with free() when done. - * - * Retrieve a list of file descriptors that should be polled for events - * interesting to libfprint. This function is only for users who wish to - * combine libfprint's file descriptor set with other event sources – more - * simplistic users will be able to call fp_handle_events() or a variant - * directly. - * - * Returns: the number of pollfds in the resultant list, or negative on error. - */ -API_EXPORTED ssize_t fp_get_pollfds(struct fp_pollfd **pollfds) -{ - const struct libusb_pollfd **usbfds; - const struct libusb_pollfd *usbfd; - struct fp_pollfd *ret; - ssize_t cnt = 0; - size_t i = 0; - - g_return_val_if_fail (fpi_usb_ctx != NULL, -EIO); - - usbfds = libusb_get_pollfds(fpi_usb_ctx); - if (!usbfds) { - *pollfds = NULL; - return -EIO; - } - - while ((usbfd = usbfds[i++]) != NULL) - cnt++; - - ret = g_malloc(sizeof(struct fp_pollfd) * cnt); - i = 0; - while ((usbfd = usbfds[i]) != NULL) { - ret[i].fd = usbfd->fd; - ret[i].events = usbfd->events; - i++; - } - - *pollfds = ret; - return cnt; -} - -/** - * fp_set_pollfd_notifiers: - * @added_cb: a #fp_pollfd_added_cb callback or %NULL - * @removed_cb: a #fp_pollfd_removed_cb callback or %NULL - * - * This sets the callback functions to call for every new or removed - * file descriptor used as an event source. - */ -API_EXPORTED void fp_set_pollfd_notifiers(fp_pollfd_added_cb added_cb, - fp_pollfd_removed_cb removed_cb) -{ - fd_added_cb = added_cb; - fd_removed_cb = removed_cb; -} - -static void add_pollfd(int fd, short events, void *user_data) -{ - if (fd_added_cb) - fd_added_cb(fd, events); -} - -static void remove_pollfd(int fd, void *user_data) -{ - if (fd_removed_cb) - fd_removed_cb(fd); -} - -void fpi_poll_init(void) -{ - libusb_set_pollfd_notifiers(fpi_usb_ctx, add_pollfd, remove_pollfd, NULL); -} - -void fpi_poll_exit(void) -{ - g_slist_free_full(active_timers, (GDestroyNotify) fpi_timeout_free); - active_timers = NULL; - fd_added_cb = NULL; - fd_removed_cb = NULL; - libusb_set_pollfd_notifiers(fpi_usb_ctx, NULL, NULL, NULL); -} - -void -fpi_timeout_cancel_all_for_dev(struct fp_dev *dev) -{ - GSList *l; - - g_return_if_fail (dev != NULL); - - l = active_timers; - while (l) { - struct fpi_timeout *timeout = l->data; - GSList *current = l; - - l = l->next; - if (timeout->dev == dev) { - g_free (timeout); - active_timers = g_slist_delete_link (active_timers, current); - } - } -} diff --git a/libfprint/fpi-poll.h b/libfprint/fpi-poll.h deleted file mode 100644 index 2682f277..00000000 --- a/libfprint/fpi-poll.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2008 Daniel Drake - * Copyright (C) 2018 Bastien Nocera - * - * 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 - */ - -#ifndef __FPI_POLL_H__ -#define __FPI_POLL_H__ - -#include "fprint.h" - -/** - * fpi_timeout_fn: - * @dev: the struct #fp_dev passed to fpi_timeout_add() - * @data: the data passed to fpi_timeout_add() - * - * The prototype of the callback function for fpi_timeout_add(). - * Note that after the callback is called, the #fpi_timeout structure will - * be freed. - */ -typedef void (*fpi_timeout_fn)(struct fp_dev *dev, void *data); - -/** - * fpi_timeout: - * - * An opaque structure representing a scheduled function call, created with - * fpi_timeout_add(). - */ -typedef struct fpi_timeout fpi_timeout; -fpi_timeout *fpi_timeout_add(unsigned int msec, - fpi_timeout_fn callback, - struct fp_dev *dev, - void *data); -void fpi_timeout_set_name(fpi_timeout *timeout, - const char *name); -void fpi_timeout_cancel(fpi_timeout *timeout); - -#endif diff --git a/libfprint/fpi-print.h b/libfprint/fpi-print.h new file mode 100644 index 00000000..fe07c260 --- /dev/null +++ b/libfprint/fpi-print.h @@ -0,0 +1,50 @@ +#pragma once + +#include "fpi-enums.h" +#include "fp-device.h" +#include "fp-print.h" + +G_BEGIN_DECLS + +/** + * FpPrintType: + * @FP_PRINT_UNDEFINED: Undefined type, this happens prior to enrollment + * @FP_PRINT_RAW: A raw print where the data is directly compared + * @FP_PRINT_NBIS: NBIS minutiae comparison + */ +typedef enum { + FP_PRINT_UNDEFINED = 0, + FP_PRINT_RAW, + FP_PRINT_NBIS, +} FpPrintType; + +/** + * FpiMatchResult: + * @FPI_MATCH_ERROR: An error occured during matching + * @FPI_MATCH_SUCCESS: The prints matched + * @FPI_MATCH_FAIL: The prints did not match + */ +typedef enum { + FPI_MATCH_ERROR = 0, + FPI_MATCH_SUCCESS, + FPI_MATCH_FAIL, +} FpiMatchResult; + +void fpi_print_add_print (FpPrint *print, + FpPrint *add); + +void fpi_print_set_type (FpPrint *print, + FpPrintType type); +void fpi_print_set_device_stored (FpPrint *print, + gboolean device_stored); + +gboolean fpi_print_add_from_image (FpPrint *print, + FpImage *image, + GError **error); + +FpiMatchResult fpi_print_bz3_match (FpPrint * template, + FpPrint *print, + gint bz3_threshold, + GError **error); + +G_END_DECLS diff --git a/libfprint/fpi-ssm.c b/libfprint/fpi-ssm.c index 64430c16..6b63e1a1 100644 --- a/libfprint/fpi-ssm.c +++ b/libfprint/fpi-ssm.c @@ -1,6 +1,7 @@ /* * Functions to assist with asynchronous driver <---> library communications * Copyright (C) 2007-2008 Daniel Drake + * Copyright (C) 2019 Benjamin Berg * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,13 +18,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#define FP_COMPONENT "drv" +#define FP_COMPONENT "SSM" -#include "fp_internal.h" +#include "drivers_api.h" #include "fpi-ssm.h" -#include -#include /** * SECTION:fpi-ssm @@ -32,7 +31,7 @@ * * Asynchronous driver design encourages some kind of state machine behind it. * In most cases, the state machine is entirely linear - you only go to the - * next state, you never jump or go backwards. The #fpi_ssm functions help you + * next state, you never jump or go backwards. The #FpiSsm functions help you * implement such a machine. * * e.g. `S1` ↦ `S2` ↦ `S3` ↦ `S4` @@ -46,7 +45,7 @@ * implicit edges linking one state to every other state. * * To create an #fpi_ssm, you pass a state handler function and the total number of - * states (4 in the above example) to fpi_ssm_new(). Note that the state numbers + * states (4 in the above example) to fpi_ssm_new (). Note that the state numbers * start at zero, making them match the first value in a C enumeration. * * To start a ssm, you pass in a completion callback function to fpi_ssm_start() @@ -72,20 +71,22 @@ * upon success (or fails). * * Your completion callback should examine the return value of - * fpi_ssm_get_error() in order to determine whether the #fpi_ssm completed or + * fpi_ssm_get_error() in ordater to determine whether the #FpiSsm completed or * failed. An error code of zero indicates successful completion. */ -struct fpi_ssm { - struct fp_dev *dev; - fpi_ssm *parentsm; - void *user_data; - int nr_states; - int cur_state; - gboolean completed; - int error; - ssm_completed_fn callback; - ssm_handler_fn handler; +struct _FpiSsm +{ + FpDevice *dev; + FpiSsm *parentsm; + gpointer ssm_data; + GDestroyNotify ssm_data_destroy; + int nr_states; + int cur_state; + gboolean completed; + GError *error; + FpiSsmCompletedCallback callback; + FpiSsmHandlerCallback handler; }; /** @@ -93,100 +94,128 @@ struct fpi_ssm { * @dev: a #fp_dev fingerprint device * @handler: the callback function * @nr_states: the number of states - * @user_data: the user data to pass to callbacks * * Allocate a new ssm, with @nr_states states. The @handler callback * will be called after each state transition. * - * Returns: a new #fpi_ssm state machine + * Returns: a new #FpiSsm state machine */ -fpi_ssm *fpi_ssm_new(struct fp_dev *dev, - ssm_handler_fn handler, - int nr_states, - void *user_data) +FpiSsm * +fpi_ssm_new (FpDevice *dev, + FpiSsmHandlerCallback handler, + int nr_states) { - fpi_ssm *machine; - BUG_ON(nr_states < 1); + FpiSsm *machine; - machine = g_malloc0(sizeof(*machine)); - machine->handler = handler; - machine->nr_states = nr_states; - machine->dev = dev; - machine->completed = TRUE; - machine->user_data = user_data; - return machine; + BUG_ON (nr_states < 1); + + machine = g_new0 (FpiSsm, 1); + machine->handler = handler; + machine->nr_states = nr_states; + machine->dev = dev; + machine->completed = TRUE; + return machine; } /** - * fpi_ssm_get_user_data: - * @machine: an #fpi_ssm state machine + * fpi_ssm_set_data: + * @machine: an #FpiSsm state machine + * @ssm_data: (nullable): a pointer to machine data + * @ssm_data_destroy: (nullable): #GDestroyNotify for @ssm_data * - * Retrieve the pointer to user data set when fpi_ssm_new() - * is called. + * Sets @machine's data (freeing the existing data, if any). + * + */ +void +fpi_ssm_set_data (FpiSsm *machine, + gpointer ssm_data, + GDestroyNotify ssm_data_destroy) +{ + if (machine->ssm_data_destroy && machine->ssm_data) + machine->ssm_data_destroy (machine->ssm_data); + + machine->ssm_data = ssm_data; + machine->ssm_data_destroy = ssm_data_destroy; +} + +/** + * fpi_ssm_get_data: + * @machine: an #FpiSsm state machine + * + * Retrieve the pointer to SSM data set with fpi_ssm_set_ssm_data() * * Returns: a pointer */ void * -fpi_ssm_get_user_data(fpi_ssm *machine) +fpi_ssm_get_data (FpiSsm *machine) { - return machine->user_data; + return machine->ssm_data; } /** * fpi_ssm_free: - * @machine: an #fpi_ssm state machine + * @machine: an #FpiSsm state machine * * Frees a state machine. This does not call any error or success * callbacks, so you need to do this yourself. */ -void fpi_ssm_free(fpi_ssm *machine) +void +fpi_ssm_free (FpiSsm *machine) { - if (!machine) - return; - g_free(machine); + if (!machine) + return; + + if (machine->ssm_data_destroy) + g_clear_pointer (&machine->ssm_data, machine->ssm_data_destroy); + g_clear_pointer (&machine->error, g_error_free); + g_free (machine); } /* Invoke the state handler */ -static void __ssm_call_handler(fpi_ssm *machine) +static void +__ssm_call_handler (FpiSsm *machine) { - fp_dbg("%p entering state %d", machine, machine->cur_state); - machine->handler(machine, machine->dev, machine->user_data); + fp_dbg ("%p entering state %d", machine, machine->cur_state); + machine->handler (machine, machine->dev); } /** * fpi_ssm_start: - * @ssm: an #fpi_ssm state machine - * @callback: the #ssm_completed_fn callback to call on completion + * @ssm: an #FpiSsm state machine + * @callback: the #FpiSsmCompletedCallback callback to call on completion * * Starts a state machine. You can also use this function to restart * a completed or failed state machine. The @callback will be called * on completion. */ -void fpi_ssm_start(fpi_ssm *ssm, ssm_completed_fn callback) +void +fpi_ssm_start (FpiSsm *ssm, FpiSsmCompletedCallback callback) { - BUG_ON(!ssm->completed); - ssm->callback = callback; - ssm->cur_state = 0; - ssm->completed = FALSE; - ssm->error = 0; - __ssm_call_handler(ssm); + BUG_ON (!ssm->completed); + ssm->callback = callback; + ssm->cur_state = 0; + ssm->completed = FALSE; + ssm->error = NULL; + __ssm_call_handler (ssm); } -static void __subsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void +__subsm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { - fpi_ssm *parent = ssm->parentsm; - BUG_ON(!parent); - if (ssm->error) - fpi_ssm_mark_failed(parent, ssm->error); - else - fpi_ssm_next_state(parent); - fpi_ssm_free(ssm); + FpiSsm *parent = ssm->parentsm; + + BUG_ON (!parent); + if (error) + fpi_ssm_mark_failed (parent, error); + else + fpi_ssm_next_state (parent); + fpi_ssm_free (ssm); } /** * fpi_ssm_start_subsm: - * @parent: an #fpi_ssm state machine - * @child: an #fpi_ssm state machine + * @parent: an #FpiSsm state machine + * @child: an #FpiSsm state machine * * Starts a state machine as a child of another. if the child completes * successfully, the parent will be advanced to the next state. if the @@ -194,124 +223,185 @@ static void __subsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) * * The child will be automatically freed upon completion or failure. */ -void fpi_ssm_start_subsm(fpi_ssm *parent, fpi_ssm *child) +void +fpi_ssm_start_subsm (FpiSsm *parent, FpiSsm *child) { - child->parentsm = parent; - fpi_ssm_start(child, __subsm_complete); + child->parentsm = parent; + fpi_ssm_start (child, __subsm_complete); } /** * fpi_ssm_mark_completed: - * @machine: an #fpi_ssm state machine + * @machine: an #FpiSsm state machine * * Mark a ssm as completed successfully. The callback set when creating - * the state machine with fpi_ssm_new() will be called synchronously. + * the state machine with fpi_ssm_new () will be called synchronously. */ -void fpi_ssm_mark_completed(fpi_ssm *machine) +void +fpi_ssm_mark_completed (FpiSsm *machine) { - BUG_ON(machine->completed); - machine->completed = TRUE; - fp_dbg("%p completed with status %d", machine, machine->error); - if (machine->callback) - machine->callback(machine, machine->dev, machine->user_data); + BUG_ON (machine->completed); + machine->completed = TRUE; + if (machine->error) + fp_dbg ("%p completed with error: %s", machine, machine->error->message); + else + fp_dbg ("%p completed successfully", machine); + if (machine->callback) + { + GError *error = machine->error ? g_error_copy (machine->error) : NULL; + + machine->callback (machine, machine->dev, error); + } } /** * fpi_ssm_mark_failed: - * @machine: an #fpi_ssm state machine - * @error: the error code + * @machine: an #FpiSsm state machine + * @error: a #GError * * Mark a state machine as failed with @error as the error code. */ -void fpi_ssm_mark_failed(fpi_ssm *machine, int error) +void +fpi_ssm_mark_failed (FpiSsm *machine, GError *error) { - fp_dbg("error %d from state %d", error, machine->cur_state); - BUG_ON(error == 0); - machine->error = error; - fpi_ssm_mark_completed(machine); + g_assert (error); + if (machine->error) + { + fp_warn ("SSM already has an error set, ignoring new error %s", error->message); + g_error_free (error); + return; + } + + fp_dbg ("SSM failed in state %d with error: %s", machine->cur_state, error->message); + machine->error = error; + fpi_ssm_mark_completed (machine); } /** * fpi_ssm_next_state: - * @machine: an #fpi_ssm state machine + * @machine: an #FpiSsm state machine * * Iterate to next state of a state machine. If the current state is the * last state, then the state machine will be marked as completed, as * if calling fpi_ssm_mark_completed(). */ -void fpi_ssm_next_state(fpi_ssm *machine) -{ - g_return_if_fail (machine != NULL); - - BUG_ON(machine->completed); - machine->cur_state++; - if (machine->cur_state == machine->nr_states) { - fpi_ssm_mark_completed(machine); - } else { - __ssm_call_handler(machine); - } -} - -/** - * fpi_ssm_next_state_timeout_cb: - * @dev: a struct #fp_dev - * @data: a pointer to an #fpi_ssm state machine - * - * Same as fpi_ssm_next_state(), but to be used as a callback - * for an fpi_timeout_add() callback, when the state change needs - * to happen after a timeout. - * - * Make sure to pass the #fpi_ssm as the `user_data` argument - * for that fpi_timeout_add() call. - */ void -fpi_ssm_next_state_timeout_cb(struct fp_dev *dev, - void *data) +fpi_ssm_next_state (FpiSsm *machine) { - g_return_if_fail (dev != NULL); - g_return_if_fail (data != NULL); + g_return_if_fail (machine != NULL); - fpi_ssm_next_state(data); + BUG_ON (machine->completed); + machine->cur_state++; + if (machine->cur_state == machine->nr_states) + fpi_ssm_mark_completed (machine); + else + __ssm_call_handler (machine); } /** * fpi_ssm_jump_to_state: - * @machine: an #fpi_ssm state machine + * @machine: an #FpiSsm state machine * @state: the state to jump to * * Jump to the @state state, bypassing intermediary states. */ -void fpi_ssm_jump_to_state(fpi_ssm *machine, int state) +void +fpi_ssm_jump_to_state (FpiSsm *machine, int state) { - BUG_ON(machine->completed); - BUG_ON(state >= machine->nr_states); - machine->cur_state = state; - __ssm_call_handler(machine); + BUG_ON (machine->completed); + BUG_ON (state >= machine->nr_states); + machine->cur_state = state; + __ssm_call_handler (machine); } /** * fpi_ssm_get_cur_state: - * @machine: an #fpi_ssm state machine + * @machine: an #FpiSsm state machine * * Returns the value of the current state. Note that states are * 0-indexed, so a value of 0 means “the first state”. * * Returns: the current state. */ -int fpi_ssm_get_cur_state(fpi_ssm *machine) +int +fpi_ssm_get_cur_state (FpiSsm *machine) { - return machine->cur_state; + return machine->cur_state; } /** * fpi_ssm_get_error: - * @machine: an #fpi_ssm state machine + * @machine: an #FpiSsm state machine * * Returns the error code set by fpi_ssm_mark_failed(). * - * Returns: a error code + * Returns: (transfer none): a error code */ -int fpi_ssm_get_error(fpi_ssm *machine) +GError * +fpi_ssm_get_error (FpiSsm *machine) { - return machine->error; + return machine->error; +} + +/** + * fpi_ssm_dup_error: + * @machine: an #FpiSsm state machine + * + * Returns the error code set by fpi_ssm_mark_failed(). + * + * Returns: (transfer full): a error code + */ +GError * +fpi_ssm_dup_error (FpiSsm *machine) +{ + if (machine->error) + return g_error_copy (machine->error); + + return NULL; +} + +/** + * fpi_ssm_next_state_timeout_cb: + * @dev: a struct #fp_dev + * @data: a pointer to an #FpiSsm state machine + * + * Same as fpi_ssm_next_state(), but to be used as a callback + * for an fpi_timeout_add() callback, when the state change needs + * to happen after a timeout. + * + * Make sure to pass the #FpiSsm as the `ssm_data` argument + * for that fpi_timeout_add() call. + */ +void +fpi_ssm_next_state_timeout_cb (FpDevice *dev, + void *data) +{ + g_return_if_fail (dev != NULL); + g_return_if_fail (data != NULL); + + fpi_ssm_next_state (data); +} + +/** + * fpi_ssm_usb_transfer_cb: + * @transfer: a #FpiUsbTransfer + * @device: a #FpDevice + * @ssm_data: User data (unused) + * @error: The #GError or %NULL + * + * Can be used in as a #FpiUsbTransfer callback handler to automatically + * advance or fail a statemachine on transfer completion. + * + * Make sure to set the #FpiSsm on the transfer. + */ +void +fpi_ssm_usb_transfer_cb (FpiUsbTransfer *transfer, FpDevice *device, + gpointer ssm_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); } diff --git a/libfprint/fpi-ssm.h b/libfprint/fpi-ssm.h index a619d42c..31a33e56 100644 --- a/libfprint/fpi-ssm.h +++ b/libfprint/fpi-ssm.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2007-2008 Daniel Drake * Copyright (C) 2018 Bastien Nocera + * Copyright (C) 2019 Benjamin Berg * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,70 +18,77 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef __FPI_SSM_H__ -#define __FPI_SSM_H__ +#pragma once -#include -#include -#include -#include -#include -#include +#include "fp-device.h" +#include "fpi-usb-transfer.h" /* async drv <--> lib comms */ /** - * fpi_ssm: + * FpiSsm: * * Sequential state machine that iterates sequentially over * a predefined series of states. Can be terminated by either completion or * failure error conditions. */ -typedef struct fpi_ssm fpi_ssm; +typedef struct _FpiSsm FpiSsm; /** - * ssm_completed_fn: - * @ssm: a #fpi_ssm state machine + * FpiSsmCompletedCallback: + * @ssm: a #FpiSsm state machine * @dev: the #fp_dev fingerprint device - * @user_data: the user data passed to fpi_ssm_new() + * @error: The #GError or %NULL on successful completion * * The callback called when a state machine completes successfully, * as set when calling fpi_ssm_start(). */ -typedef void (*ssm_completed_fn)(fpi_ssm *ssm, - struct fp_dev *dev, - void *user_data); +typedef void (*FpiSsmCompletedCallback)(FpiSsm *ssm, + FpDevice *dev, + GError *error); /** - * ssm_handler_fn: - * @ssm: a #fpi_ssm state machine + * FpiSsmHandlerCallback: + * @ssm: a #FpiSsm state machine * @dev: the #fp_dev fingerprint device - * @user_data: the user data passed to fpi_ssm_new() * * The callback called when a state machine transitions from one - * state to the next, as set when calling fpi_ssm_new(). + * state to the next, as set when calling fpi_ssm_new (). */ -typedef void (*ssm_handler_fn)(fpi_ssm *ssm, - struct fp_dev *dev, - void *user_data); +typedef void (*FpiSsmHandlerCallback)(FpiSsm *ssm, + FpDevice *dev); /* for library and drivers */ -fpi_ssm *fpi_ssm_new(struct fp_dev *dev, - ssm_handler_fn handler, - int nr_states, - void *user_data); -void fpi_ssm_free(fpi_ssm *machine); -void fpi_ssm_start(fpi_ssm *ssm, ssm_completed_fn callback); -void fpi_ssm_start_subsm(fpi_ssm *parent, fpi_ssm *child); +FpiSsm *fpi_ssm_new (FpDevice *dev, + FpiSsmHandlerCallback handler, + int nr_states); +void fpi_ssm_free (FpiSsm *machine); +void fpi_ssm_start (FpiSsm *ssm, + FpiSsmCompletedCallback callback); +void fpi_ssm_start_subsm (FpiSsm *parent, + FpiSsm *child); /* for drivers */ -void fpi_ssm_next_state(fpi_ssm *machine); -void fpi_ssm_next_state_timeout_cb(struct fp_dev *dev, void *data); -void fpi_ssm_jump_to_state(fpi_ssm *machine, int state); -void fpi_ssm_mark_completed(fpi_ssm *machine); -void fpi_ssm_mark_failed(fpi_ssm *machine, int error); -void *fpi_ssm_get_user_data(fpi_ssm *machine); -int fpi_ssm_get_error(fpi_ssm *machine); -int fpi_ssm_get_cur_state(fpi_ssm *machine); +void fpi_ssm_next_state (FpiSsm *machine); +void fpi_ssm_jump_to_state (FpiSsm *machine, + int state); +void fpi_ssm_mark_completed (FpiSsm *machine); +void fpi_ssm_mark_failed (FpiSsm *machine, + GError *error); +void fpi_ssm_set_data (FpiSsm *machine, + gpointer ssm_data, + GDestroyNotify ssm_data_destroy); +gpointer fpi_ssm_get_data (FpiSsm *machine); +GError * fpi_ssm_get_error (FpiSsm *machine); +GError * fpi_ssm_dup_error (FpiSsm *machine); +int fpi_ssm_get_cur_state (FpiSsm *machine); -#endif +/* Callbacks to be used by the driver instead of implementing their own + * logic. + */ +void fpi_ssm_next_state_timeout_cb (FpDevice *dev, + void *data); +void fpi_ssm_usb_transfer_cb (FpiUsbTransfer *transfer, + FpDevice *device, + gpointer user_data, + GError *error); diff --git a/libfprint/fpi-sync.c b/libfprint/fpi-sync.c deleted file mode 100644 index c2dd7927..00000000 --- a/libfprint/fpi-sync.c +++ /dev/null @@ -1,690 +0,0 @@ -/* - * Synchronous I/O functionality - * Copyright (C) 2007-2008 Daniel Drake - * - * 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 "sync" - -#include "fp_internal.h" -#include "fpi-dev.h" - -#include -#include - -struct sync_open_data { - struct fp_dev *dev; - int status; -}; - -static void sync_open_cb(struct fp_dev *dev, int status, void *user_data) -{ - struct sync_open_data *odata = user_data; - fp_dbg("status %d", status); - odata->dev = dev; - odata->status = status; -} - -/** - * fp_dev_open: - * @ddev: the struct #fp_dscv_dev discovered device to open - * - * Opens and initialises a device. This is the function you call in order - * to convert a #fp_dscv_dev discovered device into an actual device handle - * that you can perform operations with. - * - * Returns: the opened device handle, or %NULL on error - */ -API_EXPORTED struct fp_dev *fp_dev_open(struct fp_dscv_dev *ddev) -{ - struct fp_dev *dev = NULL; - struct sync_open_data *odata = g_malloc0(sizeof(*odata)); - int r; - - G_DEBUG_HERE(); - r = fp_async_dev_open(ddev, sync_open_cb, odata); - if (r) - goto out; - - while (!odata->dev) - if (fp_handle_events() < 0) - goto out; - - if (odata->status == 0) - dev = odata->dev; - else - fp_dev_close(odata->dev); - -out: - g_free(odata); - return dev; -} - -static void sync_close_cb(struct fp_dev *dev, void *user_data) -{ - G_DEBUG_HERE(); - gboolean *closed = user_data; - *closed = TRUE; -} - -/** - * fp_dev_close: - * @dev: the struct #fp_dev device to close. If %NULL, function simply returns - * - * Closes a device. You must call this function when you have finished using - * a fingerprint device. - */ -API_EXPORTED void fp_dev_close(struct fp_dev *dev) -{ - gboolean closed = FALSE; - - if (!dev) - return; - - G_DEBUG_HERE(); - fp_async_dev_close(dev, sync_close_cb, &closed); - while (!closed) - if (fp_handle_events() < 0) - break; -} - -struct sync_enroll_data { - gboolean populated; - int result; - struct fp_print_data *data; - struct fp_img *img; -}; - -static void sync_enroll_cb(struct fp_dev *dev, int result, - struct fp_print_data *data, struct fp_img *img, void *user_data) -{ - struct sync_enroll_data *edata = user_data; - fp_dbg("result %d", result); - edata->result = result; - edata->data = data; - edata->img = img; - edata->populated = TRUE; -} - -static void enroll_stop_cb(struct fp_dev *dev, void *user_data) -{ - gboolean *stopped = user_data; - G_DEBUG_HERE(); - *stopped = TRUE; -} - -/** - * fp_enroll_finger_img: - * @dev: the struct #fp_dev device - * @print_data: a location to return the resultant enrollment data from - * the final stage. Must be freed with fp_print_data_free() after use - * @img: location to store the scan image. accepts %NULL for no image - * storage. If an image is returned, it must be freed with fp_img_free() after - * use - * - * Performs an enroll stage. See [Enrolling](libfprint-Devices-operations.html#enrolling) - * for an explanation of enroll stages. - * - * If no enrollment is in process, this kicks of the process and runs the - * first stage. If an enrollment is already in progress, calling this - * function runs the next stage, which may well be the last. - * - * A negative error code may be returned from any stage. When this occurs, - * further calls to the enroll function will start a new enrollment process, - * i.e. a negative error code indicates that the enrollment process has been - * aborted. These error codes only ever indicate unexpected internal errors - * or I/O problems. - * - * The RETRY codes from #fp_enroll_result may be returned from any enroll - * stage. These codes indicate that the scan was not successful in that the - * user did not position their finger correctly or similar. When a RETRY code - * is returned, the enrollment stage is not advanced, so the next call - * into this function will retry the current stage again. The current stage may - * need to be retried several times. - * - * The %FP_ENROLL_FAIL code may be returned from any enroll - * stage. This code indicates that even though the scans themselves have been - * acceptable, data processing applied to these scans produces incomprehensible - * results. In other words, the user may have been scanning a different finger - * for each stage or something like that. Like negative error codes, this - * return code indicates that the enrollment process has been aborted. - * - * The %FP_ENROLL_PASS code will only ever be returned for - * non-final stages. This return code indicates that the scan was acceptable - * and the next call into this function will advance onto the next enroll - * stage. - * - * The %FP_ENROLL_COMPLETE code will only ever be returned - * from the final enroll stage. It indicates that enrollment completed - * successfully, and that print_data has been assigned to point to the - * resultant enrollment data. The print_data parameter will not be modified - * during any other enrollment stages, hence it is actually legal to pass NULL - * as this argument for all but the final stage. - * - * If the device is an imaging device, it can also return the image from - * the scan, even when the enroll fails with a RETRY or FAIL code. It is legal - * to call this function even on non-imaging devices, just don't expect them to - * provide images. - * - * Returns: negative code on error, otherwise a code from #fp_enroll_result - */ -API_EXPORTED int fp_enroll_finger_img(struct fp_dev *dev, - struct fp_print_data **print_data, struct fp_img **img) -{ - struct fp_driver *drv = dev->drv; - int stage = dev->__enroll_stage; - gboolean final = FALSE; - gboolean stopped = FALSE; - struct sync_enroll_data *edata = NULL; - int r; - G_DEBUG_HERE(); - - /* FIXME __enroll_stage is ugly, can we replace it by some function that - * says whether we're enrolling or not, and then put __enroll_stage into - * edata? */ - - if (stage == -1) { - edata = g_malloc0(sizeof(struct sync_enroll_data)); - r = fp_async_enroll_start(dev, sync_enroll_cb, edata); - if (r < 0) { - g_free(edata); - return r; - } - - dev->__enroll_stage = ++stage; - } else if (stage >= dev->nr_enroll_stages) { - fp_err("exceeding number of enroll stages for device claimed by " - "driver %s (%d stages)", drv->name, dev->nr_enroll_stages); - dev->__enroll_stage = -1; - r = -EINVAL; - final = TRUE; - goto out; - } - fp_dbg("%s will handle enroll stage %d/%d", drv->name, stage, - dev->nr_enroll_stages - 1); - - /* FIXME this isn't very clean */ - edata = dev->enroll_stage_cb_data; - - while (!edata->populated) { - r = fp_handle_events(); - if (r < 0) { - g_free(edata); - goto err; - } - } - - edata->populated = FALSE; - - if (img) - *img = edata->img; - else - fp_img_free(edata->img); - - r = edata->result; - switch (r) { - case FP_ENROLL_PASS: - fp_dbg("enroll stage passed"); - dev->__enroll_stage = stage + 1; - break; - case FP_ENROLL_COMPLETE: - fp_dbg("enroll complete"); - dev->__enroll_stage = -1; - *print_data = edata->data; - final = TRUE; - break; - case FP_ENROLL_RETRY: - fp_dbg("enroll should retry"); - break; - case FP_ENROLL_RETRY_TOO_SHORT: - fp_dbg("swipe was too short, enroll should retry"); - break; - case FP_ENROLL_RETRY_CENTER_FINGER: - fp_dbg("finger was not centered, enroll should retry"); - break; - case FP_ENROLL_RETRY_REMOVE_FINGER: - fp_dbg("scan failed, remove finger and retry"); - break; - case FP_ENROLL_FAIL: - fp_err("enroll failed"); - dev->__enroll_stage = -1; - final = TRUE; - break; - default: - fp_err("unrecognised return code %d", r); - dev->__enroll_stage = -1; - r = -EINVAL; - final = TRUE; - break; - } - - if (!final) - return r; - -out: - if (final) { - fp_dbg("ending enrollment"); - g_free(edata); - } - -err: - if (fp_async_enroll_stop(dev, enroll_stop_cb, &stopped) == 0) - while (!stopped) - if (fp_handle_events() < 0) - break; - return r; -} - -/** - * fp_enroll_finger: - * @dev: the struct #fp_dev device - * @print_data: a location to return the resultant enrollment data from - * the final stage. Must be freed with fp_print_data_free() after use - * - * Performs an enroll stage. See [Enrolling](libfprint-Devices-operations.html#enrolling) - * for an explanation of enroll stages. This function is just a shortcut to - * calling fp_enroll_finger_img() with a %NULL image parameter. Be sure to read - * the description of fp_enroll_finger_img() in order to understand its behaviour. - * - * Returns: negative code on error, otherwise a code from #fp_enroll_result - */ -API_EXPORTED int fp_enroll_finger(struct fp_dev *dev, - struct fp_print_data **print_data) -{ - return fp_enroll_finger_img(dev, print_data, NULL); -} - -struct sync_verify_data { - gboolean populated; - int result; - struct fp_img *img; -}; - -static void sync_verify_cb(struct fp_dev *dev, int result, struct fp_img *img, - void *user_data) -{ - struct sync_verify_data *vdata = user_data; - vdata->result = result; - vdata->img = img; - vdata->populated = TRUE; -} - -static void verify_stop_cb(struct fp_dev *dev, void *user_data) -{ - gboolean *stopped = user_data; - G_DEBUG_HERE(); - *stopped = TRUE; -} - -/** - * fp_verify_finger_img: - * @dev: the struct #fp_dev device to perform the scan on - * @enrolled_print: the print to verify against. Must have been previously - * enrolled with a device compatible to the device selected to perform the scan - * @img: location to store the scan image. accepts %NULL for no image - * storage. If an image is returned, it must be freed with fp_img_free() after - * use - - * Performs a new scan and verifies it against a previously enrolled print. - * If the device is an imaging device, it can also return the image from - * the scan, even when the verify fails with a RETRY code. It is legal to - * call this function even on non-imaging devices, just don't expect them to - * provide images. - * - * Returns: negative code on error, otherwise a code from #fp_verify_result - */ -API_EXPORTED int fp_verify_finger_img(struct fp_dev *dev, - struct fp_print_data *enrolled_print, struct fp_img **img) -{ - struct sync_verify_data *vdata; - gboolean stopped = FALSE; - int r; - - if (!enrolled_print) { - fp_err("no print given"); - return -EINVAL; - } - - if (!fp_dev_supports_print_data(dev, enrolled_print)) { - fp_err("print is not compatible with device"); - return -EINVAL; - } - - fp_dbg("to be handled by %s", dev->drv->name); - vdata = g_malloc0(sizeof(struct sync_verify_data)); - r = fp_async_verify_start(dev, enrolled_print, sync_verify_cb, vdata); - if (r < 0) { - fp_dbg("verify_start error %d", r); - g_free(vdata); - return r; - } - - while (!vdata->populated) { - r = fp_handle_events(); - if (r < 0) { - g_free(vdata); - goto err; - } - } - - if (img) - *img = vdata->img; - else - fp_img_free(vdata->img); - - r = vdata->result; - g_free(vdata); - switch (r) { - case FP_VERIFY_NO_MATCH: - fp_dbg("result: no match"); - break; - case FP_VERIFY_MATCH: - fp_dbg("result: match"); - break; - case FP_VERIFY_RETRY: - fp_dbg("verify should retry"); - break; - case FP_VERIFY_RETRY_TOO_SHORT: - fp_dbg("swipe was too short, verify should retry"); - break; - case FP_VERIFY_RETRY_CENTER_FINGER: - fp_dbg("finger was not centered, verify should retry"); - break; - case FP_VERIFY_RETRY_REMOVE_FINGER: - fp_dbg("scan failed, remove finger and retry"); - break; - default: - fp_err("unrecognised return code %d", r); - r = -EINVAL; - } - -err: - fp_dbg("ending verification"); - if (fp_async_verify_stop(dev, verify_stop_cb, &stopped) == 0) - while (!stopped) - if (fp_handle_events() < 0) - break; - - return r; -} - -/** - * fp_verify_finger: - * @dev: the struct #fp_dev device to perform the scan on - * @enrolled_print: the print to verify against. Must have been previously - * enrolled with a device compatible to the device selected to perform the scan - * - * Performs a new scan and verify it against a previously enrolled print. This - * function is just a shortcut to calling fp_verify_finger_img() with a NULL - * image output parameter. - * - * See also fp_verify_finger_img(). - * - * Returns: negative code on error, otherwise a code from #fp_verify_result - */ -API_EXPORTED int fp_verify_finger(struct fp_dev *dev, - struct fp_print_data *enrolled_print) -{ - return fp_verify_finger_img(dev, enrolled_print, NULL); -} - -struct sync_identify_data { - gboolean populated; - int result; - size_t match_offset; - struct fp_img *img; -}; - -static void sync_identify_cb(struct fp_dev *dev, int result, - size_t match_offset, struct fp_img *img, void *user_data) -{ - struct sync_identify_data *idata = user_data; - idata->result = result; - idata->match_offset = match_offset; - idata->img = img; - idata->populated = TRUE; -} - -static void identify_stop_cb(struct fp_dev *dev, void *user_data) -{ - gboolean *stopped = user_data; - G_DEBUG_HERE(); - *stopped = TRUE; -} - -/** - * fp_identify_finger_img: - * @dev: the struct #fp_dev device to perform the scan on - * @print_gallery: NULL-terminated array of pointers to the prints to - * identify against. Each one must have been previously enrolled with a device - * compatible to the device selected to perform the scan - * @match_offset: output location to store the array index of the matched - * gallery print (if any was found). Only valid if %FP_VERIFY_MATCH was - * returned - * @img: location to store the scan image. accepts %NULL for no image - * storage. If an image is returned, it must be freed with fp_img_free() after - * use - - * Performs a new scan and attempts to identify the scanned finger against - * a collection of previously enrolled fingerprints. - * If the device is an imaging device, it can also return the image from - * the scan, even when identification fails with a RETRY code. It is legal to - * call this function even on non-imaging devices, just don't expect them to - * provide images. - * - * This function returns codes from #fp_verify_result. The return code - * %FP_VERIFY_MATCH indicates that the scanned fingerprint - * does appear in the print gallery, and the match_offset output parameter - * will indicate the index into the print gallery array of the matched print. - * - * This function will not necessarily examine the whole print gallery, it - * will return as soon as it finds a matching print. - * - * Not all devices support identification. -ENOTSUP will be returned when - * this is the case. - * - * Returns: negative code on error, otherwise a code from #fp_verify_result - */ -API_EXPORTED int fp_identify_finger_img(struct fp_dev *dev, - struct fp_print_data **print_gallery, size_t *match_offset, - struct fp_img **img) -{ - gboolean stopped = FALSE; - struct sync_identify_data *idata - = g_malloc0(sizeof(struct sync_identify_data)); - int r; - - fp_dbg("to be handled by %s", dev->drv->name); - - r = fp_async_identify_start(dev, print_gallery, sync_identify_cb, idata); - if (r < 0) { - fp_err("identify_start error %d", r); - goto err; - } - - while (!idata->populated) { - r = fp_handle_events(); - if (r < 0) - goto err_stop; - } - - if (img) - *img = idata->img; - else - fp_img_free(idata->img); - - r = idata->result; - switch (idata->result) { - case FP_VERIFY_NO_MATCH: - fp_dbg("result: no match"); - break; - case FP_VERIFY_MATCH: - fp_dbg("result: match at offset %zd", idata->match_offset); - *match_offset = idata->match_offset; - break; - case FP_VERIFY_RETRY: - fp_dbg("verify should retry"); - break; - case FP_VERIFY_RETRY_TOO_SHORT: - fp_dbg("swipe was too short, verify should retry"); - break; - case FP_VERIFY_RETRY_CENTER_FINGER: - fp_dbg("finger was not centered, verify should retry"); - break; - case FP_VERIFY_RETRY_REMOVE_FINGER: - fp_dbg("scan failed, remove finger and retry"); - break; - default: - fp_err("unrecognised return code %d", r); - r = -EINVAL; - } - -err_stop: - if (fp_async_identify_stop(dev, identify_stop_cb, &stopped) == 0) - while (!stopped) - if (fp_handle_events() < 0) - break; - -err: - g_free(idata); - return r; -} - -/** - * fp_identify_finger: - * @dev: the struct #fp_dev device to perform the scan on - * @print_gallery: %NULL-terminated array of pointers to the prints to - * identify against. Each one must have been previously enrolled with a device - * compatible to the device selected to perform the scan - * @match_offset: output location to store the array index of the matched - * gallery print (if any was found). Only valid if %FP_VERIFY_MATCH was - * returned - - * Performs a new scan and attempts to identify the scanned finger against a - * collection of previously enrolled fingerprints. This function is just a - * shortcut to calling fp_identify_finger_img() with a %NULL image output - * parameter. - * - * See also fp_identify_finger_img(). - * - * Returns: negative code on error, otherwise a code from #fp_verify_result - */ -API_EXPORTED int fp_identify_finger(struct fp_dev *dev, - struct fp_print_data **print_gallery, size_t *match_offset) -{ - return fp_identify_finger_img(dev, print_gallery, match_offset, NULL); -} - -struct sync_capture_data { - gboolean populated; - int result; - struct fp_img *img; -}; - -static void sync_capture_cb(struct fp_dev *dev, int result, struct fp_img *img, - void *user_data) -{ - struct sync_capture_data *vdata = user_data; - vdata->result = result; - vdata->img = img; - vdata->populated = TRUE; -} - -static void capture_stop_cb(struct fp_dev *dev, void *user_data) -{ - gboolean *stopped = user_data; - G_DEBUG_HERE(); - *stopped = TRUE; -} -/** - * fp_dev_img_capture: - * @dev: the struct #fp_dev device - * @unconditional: whether to unconditionally capture an image, or to only capture when a finger is detected - * @img: a location to return the captured image. Must be freed with - * fp_img_free() after use - * - * Captures a #fp_img from a device. The returned image is the raw - * image provided by the device, you may wish to [standardize](libfprint-Image-operations.html#img_std) it. - * - * If set, the @unconditional flag indicates that the device should - * capture an image unconditionally, regardless of whether a finger is there - * or not. If unset, this function will block until a finger is detected on - * the sensor. - * - * See fp_dev_supports_imaging(). - * - * Returns: 0 on success, non-zero on error. -ENOTSUP indicates that either the - * @unconditional flag was set but the device does not support this, or that the - * device does not support imaging - */ -API_EXPORTED int fp_dev_img_capture(struct fp_dev *dev, int unconditional, - struct fp_img **img) -{ - struct sync_capture_data *vdata; - gboolean stopped = FALSE; - int r; - - if (!dev->drv->capture_start) { - fp_dbg("image capture is not supported on %s device", dev->drv->name); - return -ENOTSUP; - } - - fp_dbg("to be handled by %s", dev->drv->name); - vdata = g_malloc0(sizeof(struct sync_capture_data)); - r = fp_async_capture_start(dev, unconditional, sync_capture_cb, vdata); - if (r < 0) { - fp_dbg("capture_start error %d", r); - g_free(vdata); - return r; - } - - while (!vdata->populated) { - r = fp_handle_events(); - if (r < 0) { - g_free(vdata); - goto err; - } - } - - if (img) - *img = vdata->img; - else - fp_img_free(vdata->img); - - r = vdata->result; - g_free(vdata); - switch (r) { - case FP_CAPTURE_COMPLETE: - fp_dbg("result: complete"); - break; - case FP_CAPTURE_FAIL: - fp_dbg("result: fail"); - break; - default: - fp_err("unrecognised return code %d", r); - r = -EINVAL; - } - -err: - fp_dbg("ending capture"); - if (fp_async_capture_stop(dev, capture_stop_cb, &stopped) == 0) - while (!stopped) - if (fp_handle_events() < 0) - break; - - return r; -} - diff --git a/libfprint/fpi-usb-transfer.c b/libfprint/fpi-usb-transfer.c new file mode 100644 index 00000000..6b296212 --- /dev/null +++ b/libfprint/fpi-usb-transfer.c @@ -0,0 +1,522 @@ +/* + * FPrint USB transfer handling + * Copyright (C) 2019 Benjamin Berg + * + * 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-usb-transfer.h" + +/** + * SECTION:fpi-usb-transfer + * @title: USB transfer helpers + * @short_description: Helpers for libgusb to ease transfer handling + * + * #FpiUsbTransfer is a structure to simplify the USB transfer handling. + * The main goal is to ease memory management and provide more parameters + * to callbacks that are useful for libfprint drivers. + * + * Drivers should use this API only rather than accessing the GUsbDevice + * directly in most cases. + */ + + +G_DEFINE_BOXED_TYPE (FpiUsbTransfer, fpi_usb_transfer, fpi_usb_transfer_ref, fpi_usb_transfer_unref) + +static void +log_transfer (FpiUsbTransfer *transfer, gboolean submit, GError *error) +{ + if (g_getenv ("FP_DEBUG_TRANSFER")) + { + if (!submit) + { + 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, requested length %zd, actual length %zd, endpoint 0x%x", + transfer, + error_str, + transfer->length, + transfer->actual_length, + transfer->endpoint); + } + else + { + g_debug ("Transfer %p submitted, requested length %zd, endpoint 0x%x", + transfer, + transfer->length, + transfer->endpoint); + } + + if (!submit == !!(transfer->endpoint & FPI_USB_ENDPOINT_IN)) + { + g_autoptr(GString) line = NULL; + gssize dump_len; + + dump_len = (transfer->endpoint & FPI_USB_ENDPOINT_IN) ? transfer->actual_length : transfer->length; + + line = g_string_new (""); + /* Dump the buffer. */ + for (gint i = 0; i < dump_len; i++) + { + g_string_append_printf (line, "%02x ", transfer->buffer[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); + } + } +} + +/** + * fpi_usb_transfer_new: + * @device: The #FpDevice the transfer is for + * + * Creates a new #FpiUsbTransfer. + * + * Returns: (transfer full): A newly created #FpiUsbTransfer + */ +FpiUsbTransfer * +fpi_usb_transfer_new (FpDevice * device) +{ + FpiUsbTransfer *self; + + g_assert (device != NULL); + + self = g_slice_new0 (FpiUsbTransfer); + self->ref_count = 1; + + self->device = device; + + return self; +} + +static void +fpi_usb_transfer_free (FpiUsbTransfer *self) +{ + g_assert (self); + g_assert_cmpint (self->ref_count, ==, 0); + + if (self->free_buffer && self->buffer) + self->free_buffer (self->buffer); + self->buffer = NULL; + + g_slice_free (FpiUsbTransfer, self); +} + +/** + * fpi_usb_transfer_ref: + * @self: A #FpiUsbTransfer + * + * Increments the reference count of @self by one. + * + * Returns: (transfer full): @self + */ +FpiUsbTransfer * +fpi_usb_transfer_ref (FpiUsbTransfer *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_usb_transfer_unref: + * @self: A #FpiUsbTransfer + * + * Decrements the reference count of @self by one, freeing the structure when + * the reference count reaches zero. + */ +void +fpi_usb_transfer_unref (FpiUsbTransfer *self) +{ + g_return_if_fail (self); + g_return_if_fail (self->ref_count); + + if (g_atomic_int_dec_and_test (&self->ref_count)) + fpi_usb_transfer_free (self); +} + +/** + * fpi_usb_transfer_fill_bulk: + * @transfer: The #FpiUsbTransfer + * @endpoint: The endpoint to send the transfer to + * @length: The buffer size to allocate + * + * Prepare a bulk transfer. A buffer will be created for you, use + * fpi_usb_transfer_fill_bulk_full() if you want to send a static buffer + * or receive a pre-defined buffer. + */ +void +fpi_usb_transfer_fill_bulk (FpiUsbTransfer *transfer, + guint8 endpoint, + gsize length) +{ + fpi_usb_transfer_fill_bulk_full (transfer, + endpoint, + g_malloc0 (length), + length, + g_free); +} + +/** + * fpi_usb_transfer_fill_bulk_full: + * @transfer: The #FpiUsbTransfer + * @endpoint: The endpoint to send the transfer to + * @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 + * + * Prepare a bulk transfer. + */ +void +fpi_usb_transfer_fill_bulk_full (FpiUsbTransfer *transfer, + guint8 endpoint, + guint8 *buffer, + gsize length, + GDestroyNotify free_func) +{ + g_assert (transfer->type == FP_TRANSFER_NONE); + g_assert (buffer != NULL); + + transfer->type = FP_TRANSFER_BULK; + transfer->endpoint = endpoint; + + transfer->buffer = buffer; + transfer->length = length; + transfer->free_buffer = free_func; +} + +/** + * fpi_usb_transfer_fill_control: + * @transfer: The #FpiUsbTransfer + * @direction: The direction of the control transfer + * @request_type: The request type + * @recipient: The recipient + * @request: The control transfer request + * @value: The control transfer value + * @idx: The control transfer index + * @length: The size of the transfer + * + * Prepare a control transfer. The function will create a new buffer, + * you can initialize the buffer after calling this function. + */ +void +fpi_usb_transfer_fill_control (FpiUsbTransfer *transfer, + GUsbDeviceDirection direction, + GUsbDeviceRequestType request_type, + GUsbDeviceRecipient recipient, + guint8 request, + guint16 value, + guint16 idx, + gsize length) +{ + g_assert (transfer->type == FP_TRANSFER_NONE); + + transfer->type = FP_TRANSFER_CONTROL; + transfer->direction = direction; + transfer->request_type = request_type; + transfer->recipient = recipient; + transfer->request = request; + transfer->value = value; + transfer->idx = idx; + + transfer->length = length; + transfer->buffer = g_malloc0 (length); + transfer->free_buffer = g_free; +} + +/** + * fpi_usb_transfer_fill_interrupt: + * @transfer: The #FpiUsbTransfer + * @endpoint: The endpoint to send the transfer to + * @length: The size of the transfer + * + * Prepare an interrupt transfer. The function will create a new buffer, + * you can initialize the buffer after calling this function. + */ +void +fpi_usb_transfer_fill_interrupt (FpiUsbTransfer *transfer, + guint8 endpoint, + gsize length) +{ + fpi_usb_transfer_fill_interrupt_full (transfer, + endpoint, + g_malloc0 (length), + length, + g_free); +} + +/** + * fpi_usb_transfer_fill_interrupt_full: + * @transfer: The #FpiUsbTransfer + * @endpoint: The endpoint to send the transfer to + * @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 + * + * Prepare an interrupt transfer. + */ +void +fpi_usb_transfer_fill_interrupt_full (FpiUsbTransfer *transfer, + guint8 endpoint, + guint8 *buffer, + gsize length, + GDestroyNotify free_func) +{ + g_assert (transfer->type == FP_TRANSFER_NONE); + g_assert (buffer != NULL); + + transfer->type = FP_TRANSFER_INTERRUPT; + transfer->endpoint = endpoint; + + transfer->buffer = buffer; + transfer->length = length; + transfer->free_buffer = free_func; +} + +void +transfer_finish_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) +{ + GError *error = NULL; + FpiUsbTransfer *transfer = user_data; + FpiUsbTransferCallback callback; + + switch (transfer->type) + { + case FP_TRANSFER_BULK: + transfer->actual_length = + g_usb_device_bulk_transfer_finish (G_USB_DEVICE (source_object), + res, + &error); + break; + + case FP_TRANSFER_CONTROL: + transfer->actual_length = + g_usb_device_control_transfer_finish (G_USB_DEVICE (source_object), + res, + &error); + break; + + case FP_TRANSFER_INTERRUPT: + transfer->actual_length = + g_usb_device_interrupt_transfer_finish (G_USB_DEVICE (source_object), + res, + &error); + break; + + case FP_TRANSFER_NONE: + default: + g_assert_not_reached (); + } + + log_transfer (transfer, FALSE, error); + + /* Check for short error, and set an error if requested */ + if (error == NULL && + transfer->short_is_error && + transfer->actual_length > 0 && + transfer->actual_length != transfer->length) + { + error = g_error_new (G_USB_DEVICE_ERROR, + G_USB_DEVICE_ERROR_IO, + "Unexpected short error of %zd size (expected %zd)", transfer->actual_length, transfer->length); + } + + callback = transfer->callback; + transfer->callback = NULL; + callback (transfer, transfer->device, transfer->user_data, error); + + fpi_usb_transfer_unref (transfer); +} + + +/** + * fpi_usb_transfer_submit: + * @transfer: The transfer to submit, must have been filled. + * @timeout_ms: Timeout for the transfer in ms + * @cancellable: Cancellable to use, e.g. fpi_device_get_cancellable() + * @callback: Callback on completion or error + * @user_data: Data to pass to callback + * + * Submit a USB transfer with a specific timeout and callback functions. + * + * Note that #FpiUsbTransfer is owned by the user. In most cases, you + * should call fpi_usb_transfer_unref() just after calling this function. + * Doing so means that all associated data will be free'ed automatically + * after the callback ran. + */ +void +fpi_usb_transfer_submit (FpiUsbTransfer *transfer, + guint timeout_ms, + GCancellable *cancellable, + FpiUsbTransferCallback callback, + gpointer user_data) +{ + 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; + + /* Grab a reference, this means that one can simply unref after submit and + * trust for the data to disappear without explicit management by the callback + * function. */ + fpi_usb_transfer_ref (transfer); + + log_transfer (transfer, TRUE, NULL); + + switch (transfer->type) + { + case FP_TRANSFER_BULK: + g_usb_device_bulk_transfer_async (fpi_device_get_usb_device (transfer->device), + transfer->endpoint, + transfer->buffer, + transfer->length, + timeout_ms, + cancellable, + transfer_finish_cb, + transfer); + break; + + case FP_TRANSFER_CONTROL: + g_usb_device_control_transfer_async (fpi_device_get_usb_device (transfer->device), + transfer->direction, + transfer->request_type, + transfer->recipient, + transfer->request, + transfer->value, + transfer->idx, + transfer->buffer, + transfer->length, + timeout_ms, + cancellable, + transfer_finish_cb, + transfer); + break; + + case FP_TRANSFER_INTERRUPT: + g_usb_device_interrupt_transfer_async (fpi_device_get_usb_device (transfer->device), + transfer->endpoint, + transfer->buffer, + transfer->length, + timeout_ms, + cancellable, + transfer_finish_cb, + transfer); + break; + + case FP_TRANSFER_NONE: + default: + fpi_usb_transfer_unref (transfer); + g_return_if_reached (); + } +} + +/** + * fpi_usb_transfer_submit_sync: + * @transfer: The transfer to submit, must have been filled. + * @timeout_ms: Timeout for the transfer in millisecnods + * @error: Location to store #GError to + * + * Synchronously submit a USB transfer with a specific timeout. + * Only use this function with short timeouts as the application will + * be blocked otherwise. + * + * Note that you still need to fpi_usb_transfer_unref() the + * #FpiUsbTransfer afterwards. + * + * Returns: #TRUE on success, otherwise #FALSE and @error will be set + */ +gboolean +fpi_usb_transfer_submit_sync (FpiUsbTransfer *transfer, + guint timeout_ms, + GError **error) +{ + 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); + + switch (transfer->type) + { + case FP_TRANSFER_BULK: + res = g_usb_device_bulk_transfer (fpi_device_get_usb_device (transfer->device), + transfer->endpoint, + transfer->buffer, + transfer->length, + &transfer->actual_length, + timeout_ms, + NULL, + error); + break; + + case FP_TRANSFER_CONTROL: + res = g_usb_device_control_transfer (fpi_device_get_usb_device (transfer->device), + transfer->direction, + transfer->request_type, + transfer->recipient, + transfer->request, + transfer->value, + transfer->idx, + transfer->buffer, + transfer->length, + &transfer->actual_length, + timeout_ms, + NULL, + error); + break; + + case FP_TRANSFER_INTERRUPT: + res = g_usb_device_interrupt_transfer (fpi_device_get_usb_device (transfer->device), + transfer->endpoint, + transfer->buffer, + transfer->length, + &transfer->actual_length, + timeout_ms, + NULL, + error); + break; + + case FP_TRANSFER_NONE: + default: + g_return_val_if_reached (FALSE); + } + + log_transfer (transfer, FALSE, *error); + + if (!res) + transfer->actual_length = -1; + + return res; +} diff --git a/libfprint/fpi-usb-transfer.h b/libfprint/fpi-usb-transfer.h new file mode 100644 index 00000000..5b8fe9cb --- /dev/null +++ b/libfprint/fpi-usb-transfer.h @@ -0,0 +1,157 @@ +/* + * FPrint USB transfer handling + * Copyright (C) 2019 Benjamin Berg + * + * 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 +#include "fpi-device.h" + +G_BEGIN_DECLS + +#define FPI_TYPE_USB_TRANSFER (fpi_usb_transfer_get_type ()) + +#define FPI_USB_ENDPOINT_IN 0x80 +#define FPI_USB_ENDPOINT_OUT 0x00 + +typedef struct _FpiUsbTransfer FpiUsbTransfer; + +#include "fpi-ssm.h" + +typedef void (*FpiUsbTransferCallback)(FpiUsbTransfer *transfer, + FpDevice *dev, + gpointer user_data, + GError *error); + +/** + * FpiTransferType: + * @FP_TRANSFER_NONE: Type not set + * @FP_TRANSFER_BULK: Bulk transfer + * @FP_TRANSFER_CONTROL: Control transfer + * @FP_TRANSFER_INTERRUPT: Interrupt transfer + * + * Type of the transfer. + */ +typedef enum { + FP_TRANSFER_NONE = 0, + FP_TRANSFER_BULK, + FP_TRANSFER_CONTROL, + FP_TRANSFER_INTERRUPT, +} FpiTransferType; + +/** + * FpiUsbTransfer: + * @device: The #FpDevice that the transfer belongs to. + * @ssm: Storage slot to associate the transfer with a state machine. + * Used by fpi_ssm_usb_transfer_cb() to modify the given state machine. + * @length: The requested length of the transfer in bytes. + * @actual_length: The actual length of the transfer + * (see also fpi_usb_transfer_set_short_error()) + * @buffer: The transfered data. + * + * Helper for handling USB transfers. + */ +struct _FpiUsbTransfer +{ + /*< public >*/ + FpDevice *device; + + FpiSsm *ssm; + + gssize length; + gssize actual_length; + + guchar *buffer; + + /*< private >*/ + guint ref_count; + + /* USB Transfer information */ + FpiTransferType type; + guint8 endpoint; + + /* Control Transfer options */ + GUsbDeviceDirection direction; + GUsbDeviceRequestType request_type; + GUsbDeviceRecipient recipient; + guint8 request; + guint16 value; + guint16 idx; + + /* Flags */ + gboolean short_is_error; + + /* Callbacks */ + gpointer user_data; + FpiUsbTransferCallback callback; + + /* Data free function */ + GDestroyNotify free_buffer; +}; + +GType fpi_usb_transfer_get_type (void) G_GNUC_CONST; +FpiUsbTransfer *fpi_usb_transfer_new (FpDevice *device); +FpiUsbTransfer *fpi_usb_transfer_ref (FpiUsbTransfer *self); +void fpi_usb_transfer_unref (FpiUsbTransfer *self); + +void fpi_usb_transfer_set_short_error (FpiUsbTransfer *transfer, + gboolean short_is_error); + +void fpi_usb_transfer_fill_bulk (FpiUsbTransfer *transfer, + guint8 endpoint, + gsize length); + +void fpi_usb_transfer_fill_bulk_full (FpiUsbTransfer *transfer, + guint8 endpoint, + guint8 *buffer, + gsize length, + GDestroyNotify free_func); + +void fpi_usb_transfer_fill_control (FpiUsbTransfer *transfer, + GUsbDeviceDirection direction, + GUsbDeviceRequestType request_type, + GUsbDeviceRecipient recipient, + guint8 request, + guint16 value, + guint16 idx, + gsize length); + +void fpi_usb_transfer_fill_interrupt (FpiUsbTransfer *transfer, + guint8 endpoint, + gsize length); + +void fpi_usb_transfer_fill_interrupt_full (FpiUsbTransfer *transfer, + guint8 endpoint, + guint8 *buffer, + gsize length, + GDestroyNotify free_func); + +void fpi_usb_transfer_submit (FpiUsbTransfer *transfer, + guint timeout_ms, + GCancellable *cancellable, + FpiUsbTransferCallback callback, + gpointer user_data); + +gboolean fpi_usb_transfer_submit_sync (FpiUsbTransfer *transfer, + guint timeout_ms, + GError **error); + + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpiUsbTransfer, fpi_usb_transfer_unref) + +G_END_DECLS diff --git a/libfprint/fpi-usb.c b/libfprint/fpi-usb.c deleted file mode 100644 index b140d7ef..00000000 --- a/libfprint/fpi-usb.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Driver API definitions - * Copyright (C) 2018 Bastien Nocera - * - * 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-usb.h" -#include "drivers_api.h" - -/** - * SECTION:fpi-usb - * @title: Helpers for libusb - * @short_description: libusb-related helpers - * - * A collection of [libusb helpers](http://libusb.sourceforge.net/api-1.0/group__poll.html#details) - * to make driver development easier. Please refer to the libusb API documentation for more - * information about the original API. - */ - -/* Helpers from glib */ -#include -#include -#include -#include -#include - -/* special helpers to avoid gmessage.c dependency */ -static void mem_error (const char *format, ...) G_GNUC_PRINTF (1,2); -#define mem_assert(cond) do { if (G_LIKELY (cond)) ; else mem_error ("assertion failed: %s", #cond); } while (0) - -static void -mem_error (const char *format, - ...) -{ - const char *pname; - va_list args; - /* at least, put out "MEMORY-ERROR", in case we segfault during the rest of the function */ - fputs ("\n***MEMORY-ERROR***: ", stderr); - pname = g_get_prgname(); - g_fprintf (stderr, "%s[%ld]: ", pname ? pname : "", (long)getpid()); - va_start (args, format); - g_vfprintf (stderr, format, args); - va_end (args); - fputs ("\n", stderr); - abort(); - _exit (1); -} - -struct fpi_usb_transfer { - struct libusb_transfer *transfer; - fpi_ssm *ssm; - struct fp_dev *dev; - fpi_usb_transfer_cb_fn callback; - void *user_data; -}; - -/** - * fpi_usb_alloc: - * - * Returns a struct libusb_transfer, similar to calling - * `libusb_alloc_transfer(0)`[[1](http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga13cc69ea40c702181c430c950121c000)]. As libfprint uses GLib internally, - * and [memory allocation failures will make applications fail](https://developer.gnome.org/glib/stable/glib-Memory-Allocation.html#glib-Memory-Allocation.description), - * this helper will assert when the libusb call fails. - */ -struct libusb_transfer * -fpi_usb_alloc(void) -{ - struct libusb_transfer *transfer; - - transfer = libusb_alloc_transfer(0); - mem_assert(transfer); - - return transfer; -} - -static fpi_usb_transfer * -fpi_usb_transfer_new(struct fp_dev *dev, - fpi_ssm *ssm, - fpi_usb_transfer_cb_fn callback, - void *user_data) -{ - fpi_usb_transfer *transfer; - - transfer = g_new0(fpi_usb_transfer, 1); - transfer->transfer = fpi_usb_alloc(); - transfer->dev = dev; - transfer->ssm = ssm; - transfer->callback = callback; - transfer->user_data = user_data; - - return transfer; -} - -void -fpi_usb_transfer_free(fpi_usb_transfer *transfer) -{ - if (transfer == NULL) - return; - - g_free(transfer->transfer->buffer); - libusb_free_transfer(transfer->transfer); - g_free(transfer); -} - -static void -fpi_usb_transfer_cb (struct libusb_transfer *transfer) -{ - fpi_usb_transfer *t; - - g_assert(transfer); - g_assert(transfer->user_data); - - t = transfer->user_data; - BUG_ON(transfer->callback == NULL); - (t->callback) (transfer, t->dev, t->ssm, t->user_data); - fpi_usb_transfer_free(t); -} - -/** - * fpi_usb_fill_bulk_transfer: - * @dev: a struct #fp_dev fingerprint device - * @ssm: the current #fpi_ssm state machine - * @endpoint: the USB end point - * @buffer: a buffer allocated with g_malloc() or another GLib function. - * Note that the returned #fpi_usb_transfer will own this buffer, so it - * should not be freed manually. - * @length: the size of @buffer - * @callback: the callback function that will be called once the fpi_usb_submit_transfer() - * call finishes. - * @user_data: a user data pointer to pass to the callback - * @timeout: timeout for the transfer in milliseconds, or 0 for no timeout - * - * This function is similar to calling [`libusb_alloc_transfer(0)`](http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga13cc69ea40c702181c430c950121c000)] - * followed by calling [`libusb_fill_bulk_transfer()`](http://libusb.sourceforge.net/api-1.0/group__asyncio.html#gad4ddb1a5c6c7fefc979a44d7300b95d7). - * The #fpi_usb_transfer_cb_fn callback will however provide more arguments - * relevant to libfprint drivers, making it a good replacement for the raw libusb - * calls. - * - * Returns: a #fpi_usb_transfer transfer struct, to be passed to - * fpi_usb_submit_transfer(). - */ -fpi_usb_transfer * -fpi_usb_fill_bulk_transfer (struct fp_dev *dev, - fpi_ssm *ssm, - unsigned char endpoint, - unsigned char *buffer, - int length, - fpi_usb_transfer_cb_fn callback, - void *user_data, - unsigned int timeout) -{ - fpi_usb_transfer *transfer; - - g_return_val_if_fail (dev != NULL, NULL); - g_return_val_if_fail (callback != NULL, NULL); - - transfer = fpi_usb_transfer_new(dev, - ssm, - callback, - user_data); - - libusb_fill_bulk_transfer(transfer->transfer, - fpi_dev_get_usb_dev(dev), - endpoint, - buffer, - length, - fpi_usb_transfer_cb, - transfer, - timeout); - - return transfer; -} - -/** - * fpi_usb_submit_transfer: - * @transfer: a #fpi_usb_transfer struct - * - * Start a transfer to the device with the provided #fpi_usb_transfer. - * On error, the #fpi_usb_transfer struct will be freed, otherwise it will - * be freed once the callback provided to fpi_usb_fill_bulk_transfer() has - * been called. - * - * Returns: 0 on success, or the same errors as [libusb_submit_transfer](http://libusb.sourceforge.net/api-1.0/group__asyncio.html#gabb0932601f2c7dad2fee4b27962848ce) - * on failure. - */ -int -fpi_usb_submit_transfer(fpi_usb_transfer *transfer) -{ - int r; - - g_return_val_if_fail (transfer != NULL, LIBUSB_ERROR_INVALID_PARAM); - - r = libusb_submit_transfer(transfer->transfer); - if (r < 0) - fpi_usb_transfer_free(transfer); - - return r; -} - -/** - * fpi_usb_cancel_transfer: - * @transfer: a #fpi_usb_transfer struct - * - * Cancel a transfer to the device with the provided #fpi_usb_transfer. - * Note that this will not complete the cancellation, as your transfer - * callback will be called with the `LIBUSB_TRANSFER_CANCELLED` status, - * as [libusb_cancel_transfer](http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga685eb7731f9a0593f75beb99727bbe54) - * would. - * - * You should not access anything but the given struct #libusb_transfer - * in the callback before checking whether `LIBUSB_TRANSFER_CANCELLED` has - * been called, as that might cause memory access violations. - * - * Returns: 0 on success, or the same errors as [libusb_cancel_transfer](http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga685eb7731f9a0593f75beb99727bbe54) - * on failure. - */ -int -fpi_usb_cancel_transfer(fpi_usb_transfer *transfer) -{ - g_return_val_if_fail (transfer != NULL, LIBUSB_ERROR_NOT_FOUND); - - return libusb_cancel_transfer(transfer->transfer); -} diff --git a/libfprint/fpi-usb.h b/libfprint/fpi-usb.h deleted file mode 100644 index 822b6124..00000000 --- a/libfprint/fpi-usb.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2018 Bastien Nocera - * - * 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 - */ - -#ifndef __FPI_USB_H__ -#define __FPI_USB_H__ - -#include -#include "fpi-dev.h" -#include "fpi-ssm.h" - -/** - * fpi_usb_transfer: - * - * A structure containing the arguments passed to fpi_usb_fill_bulk_transfer() - * to be used with fpi_usb_submit_transfer(). - */ -typedef struct fpi_usb_transfer fpi_usb_transfer; - -/** - * fpi_usb_transfer_cb_fn: - * @transfer: a struct #libusb_transfer - * @dev: the struct #fp_dev on which the operation was performed - * @ssm: the #fpi_ssm state machine - * @user_data: the user data passed to fpi_usb_fill_bulk_transfer() - * - * This callback will be called in response to a libusb bulk transfer - * triggered via fpi_usb_fill_bulk_transfer() finishing. Note that the - * struct #libusb_transfer does not need to be freed, as it will be - * freed after the callback returns, similarly to - * the [LIBUSB_TRANSFER_FREE_TRANSFER flag](http://libusb.sourceforge.net/api-1.0/group__asyncio.html#gga1fb47dd0f7c209b60a3609ff0c03d56dacf3f064997b283a14097c9f4d6f8ccc1). - * - * Note that the cancelled status of the transfer should be checked - * first thing, as the @dev, @ssm and @user_data pointers might not - * be pointing to valid values anymore. See fpi_usb_cancel_transfer() - * for more information. - */ -typedef void(*fpi_usb_transfer_cb_fn) (struct libusb_transfer *transfer, - struct fp_dev *dev, - fpi_ssm *ssm, - void *user_data); - -struct libusb_transfer *fpi_usb_alloc(void) __attribute__((returns_nonnull)); - -fpi_usb_transfer *fpi_usb_fill_bulk_transfer (struct fp_dev *dev, - fpi_ssm *ssm, - unsigned char endpoint, - unsigned char *buffer, - int length, - fpi_usb_transfer_cb_fn callback, - void *user_data, - unsigned int timeout); -int fpi_usb_submit_transfer (fpi_usb_transfer *transfer); -int fpi_usb_cancel_transfer (fpi_usb_transfer *transfer); - -#endif diff --git a/libfprint/fprint-list-supported-devices.c b/libfprint/fprint-list-supported-devices.c index ed49ee69..124e9d9e 100644 --- a/libfprint/fprint-list-supported-devices.c +++ b/libfprint/fprint-list-supported-devices.c @@ -1,7 +1,8 @@ /* - * Copyright (C) 2009 Red Hat + * Copyright (C) 2009 Red Hat * Copyright (C) 2008 Bastien Nocera * Copyright (C) 2008 Timo Hoenig , + * Coypright (C) 2019 Benjamin Berg * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,69 +23,87 @@ #include #include -#include "fp_internal.h" +#include "fpi-context.h" +#include "fpi-device.h" GHashTable *printed = NULL; -static GList *insert_driver (GList *list, - struct fp_driver *driver) +static GList * +insert_drivers (GList *list) { - int i; + g_autoptr(GArray) drivers = g_array_new (FALSE, FALSE, sizeof (GType)); + gint i; - for (i = 0; driver->id_table[i].vendor != 0; i++) { - char *key; + fpi_get_driver_types (drivers); - key = g_strdup_printf ("%04x:%04x", driver->id_table[i].vendor, driver->id_table[i].product); + /* Find the best driver to handle this USB device. */ + for (i = 0; i < drivers->len; i++) + { + GType driver = g_array_index (drivers, GType, i); + FpDeviceClass *cls = FP_DEVICE_CLASS (g_type_class_ref (driver)); + const FpIdEntry *entry; - if (g_hash_table_lookup (printed, key) != NULL) { - g_free (key); - continue; - } + if (cls->type != FP_DEVICE_TYPE_USB) + { + g_type_class_unref (cls); + continue; + } - g_hash_table_insert (printed, key, GINT_TO_POINTER (1)); + for (entry = cls->id_table; entry->vid; entry++) + { + char *key; - list = g_list_prepend (list, g_strdup_printf ("%s | %s\n", key, driver->full_name)); + 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)); + + list = g_list_prepend (list, g_strdup_printf ("%s | %s\n", key, cls->full_name)); + } + + g_type_class_unref (cls); } - return list; + return list; } -int main (int argc, char **argv) +int +main (int argc, char **argv) { - struct fp_driver **driver_list; - guint i; - GList *list, *l; + GList *list, *l; - setlocale (LC_ALL, ""); + setlocale (LC_ALL, ""); - driver_list = fprint_get_drivers (); + printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + g_print ("%% lifprint — Supported Devices\n"); + g_print ("%% Bastien Nocera, Daniel Drake\n"); + g_print ("%% 2018\n"); + g_print ("\n"); - g_print ("%% lifprint — Supported Devices\n"); - g_print ("%% Bastien Nocera, Daniel Drake\n"); - g_print ("%% 2018\n"); - g_print ("\n"); + g_print ("# Supported Devices\n"); + g_print ("\n"); + g_print ("This is a list of supported devices in libfprint's development version. Those drivers might not all be available in the stable, released version. If in doubt, contact your distribution or systems integrator for details.\n"); + g_print ("\n"); + g_print ("## USB devices\n"); + g_print ("\n"); + g_print ("USB ID | Driver\n"); + g_print ("------------ | ------------\n"); - g_print ("# Supported Devices\n"); - g_print ("\n"); - g_print ("This is a list of supported devices in libfprint's development version. Those drivers might not all be available in the stable, released version. If in doubt, contact your distribution or systems integrator for details.\n"); - g_print ("\n"); - g_print ("## USB devices\n"); - g_print ("\n"); - g_print ("USB ID | Driver\n"); - g_print ("------------ | ------------\n"); + list = NULL; + list = insert_drivers (list); - list = NULL; - for (i = 0; driver_list[i] != NULL; i++) - list = insert_driver (list, driver_list[i]); + list = g_list_sort (list, (GCompareFunc) g_strcmp0); + for (l = list; l != NULL; l = l->next) + g_print ("%s", (char *) l->data); - list = g_list_sort (list, (GCompareFunc) g_strcmp0); - for (l = list; l != NULL; l = l->next) - g_print ("%s", (char *) l->data); + g_list_free_full (list, g_free); + g_hash_table_destroy (printed); - g_list_free_full (list, g_free); - g_hash_table_destroy (printed); - - return 0; + return 0; } diff --git a/libfprint/fprint-list-udev-rules.c b/libfprint/fprint-list-udev-rules.c index de291f11..0c1b0591 100644 --- a/libfprint/fprint-list-udev-rules.c +++ b/libfprint/fprint-list-udev-rules.c @@ -1,7 +1,8 @@ /* - * Copyright (C) 2009 Red Hat + * Copyright (C) 2009 Red Hat * Copyright (C) 2008 Bastien Nocera * Copyright (C) 2008 Timo Hoenig , + * Coypright (C) 2019 Benjamin Berg * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,90 +20,110 @@ */ #include -#include -#include "fp_internal.h" +#include "fpi-context.h" +#include "fpi-device.h" -static const struct usb_id whitelist_id_table[] = { - /* Unsupported (for now) Validity Sensors finger print readers */ - { .vendor = 0x138a, .product = 0x0090 }, /* Found on e.g. Lenovo T460s */ - { .vendor = 0x138a, .product = 0x0091 }, - { .vendor = 0x138a, .product = 0x0094 }, - { .vendor = 0x138a, .product = 0x0097 }, /* Found on e.g. Lenovo T470s */ - { 0, 0, 0, }, +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 struct usb_id blacklist_id_table[] = { - { .vendor = 0x0483, .product = 0x2016 }, - /* https://bugs.freedesktop.org/show_bug.cgi?id=66659 */ - { .vendor = 0x045e, .product = 0x00bb }, - { 0, 0, 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 }, }; -struct fp_driver whitelist = { - .id_table = whitelist_id_table, - .full_name = "Hardcoded whitelist" +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 (struct fp_driver *driver) +static void +print_driver (const FpDeviceClass *cls) { - int i, j, blacklist, num_printed; + const FpIdEntry *entry; + gint num_printed = 0; - num_printed = 0; + if (cls->type != FP_DEVICE_TYPE_USB) + return; - for (i = 0; driver->id_table[i].vendor != 0; i++) { - char *key; + for (entry = cls->id_table; entry->vid != 0; entry++) + { + const FpIdEntry *bl_entry; + char *key; - blacklist = 0; - for (j = 0; blacklist_id_table[j].vendor != 0; j++) { - if (driver->id_table[i].vendor == blacklist_id_table[j].vendor && - driver->id_table[i].product == blacklist_id_table[j].product) { - blacklist = 1; - break; - } - } - if (blacklist) - continue; + for (bl_entry = blacklist_id_table; bl_entry->vid != 0; bl_entry++) + if (entry->vid == bl_entry->vid && entry->pid == bl_entry->pid) + break; - key = g_strdup_printf ("%04x:%04x", driver->id_table[i].vendor, driver->id_table[i].product); + if (bl_entry->vid != 0) + continue; - if (g_hash_table_lookup (printed, key) != NULL) { - g_free (key); - continue; - } + key = g_strdup_printf ("%04x:%04x", entry->vid, entry->pid); - g_hash_table_insert (printed, key, GINT_TO_POINTER (1)); + if (g_hash_table_lookup (printed, key) != NULL) + { + g_free (key); + continue; + } - if (num_printed == 0) - printf ("# %s\n", driver->full_name); + g_hash_table_insert (printed, key, GINT_TO_POINTER (1)); - printf ("SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", ATTRS{dev}==\"*\", TEST==\"power/control\", ATTR{power/control}=\"auto\"\n", driver->id_table[i].vendor, driver->id_table[i].product); - printf ("SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", ENV{LIBFPRINT_DRIVER}=\"%s\"\n", driver->id_table[i].vendor, driver->id_table[i].product, driver->full_name); - num_printed++; + 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) - printf ("\n"); + if (num_printed > 0) + g_print ("\n"); } -int main (int argc, char **argv) +int +main (int argc, char **argv) { - struct fp_driver **list; - guint i; + g_autoptr(GArray) drivers = g_array_new (FALSE, FALSE, sizeof (GType)); + guint i; - list = fprint_get_drivers (); + g_print ("%p\n", drivers); + g_print ("%p\n", fpi_get_driver_types); + fpi_get_driver_types (drivers); - printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - for (i = 0; list[i] != NULL; i++) { - print_driver (list[i]); + for (i = 0; i < drivers->len; i++) + { + GType driver = g_array_index (drivers, GType, i); + FpDeviceClass *cls = FP_DEVICE_CLASS (g_type_class_ref (driver)); + + if (cls->type != FP_DEVICE_TYPE_USB) + { + g_type_class_unref (cls); + continue; + } + + print_driver (cls); + + g_type_class_unref (cls); } - print_driver (&whitelist); + print_driver (&whitelist); - g_hash_table_destroy (printed); + g_hash_table_destroy (printed); - return 0; + return 0; } diff --git a/libfprint/fprint.h b/libfprint/fprint.h index 4b68e4aa..6db6cfda 100644 --- a/libfprint/fprint.h +++ b/libfprint/fprint.h @@ -1,6 +1,6 @@ /* * Main definitions for libfprint - * Copyright (C) 2007 Daniel Drake + * Copyright (C) 2019 Benjamin Berg * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,443 +17,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef __FPRINT_H__ -#define __FPRINT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -/** - * LIBFPRINT_DEPRECATED: - * - * Expands to the GNU C deprecated attribute if the compiler is `gcc`. When - * called with the `-Wdeprecated-declarations` option, `gcc` will generate warnings - * when deprecated interfaces are used. - */ -#define LIBFPRINT_DEPRECATED __attribute__((__deprecated__)) - -/** - * fp_dscv_dev: - * - * #fp_dscv_dev is an opaque structure type. You must access it using the - * functions in this section. - */ -struct fp_dscv_dev; - -/** - * fp_dscv_print: - * - * #fp_dscv_print is an opaque structure type. You must access it using the - * functions in this section. - */ -struct fp_dscv_print; - -/** - * fp_dev: - * - * #fp_dev is an opaque structure type. You must access it using the - * functions in this section. - */ -struct fp_dev; - -/** - * fp_driver: - * - * #fp_driver is an opaque structure type. You must access it using the - * functions in this section. - */ -struct fp_driver; - -/** - * fp_print_data: - * - * #fp_print_data is an opaque structure type. You must access it using the - * functions in this section. - */ -struct fp_print_data; - -/** - * fp_img: - * - * #fp_img is an opaque structure type. You must access it using the - * functions in this section. - */ -struct fp_img; - -/* misc/general stuff */ - -/** - * fp_finger: - * @LEFT_THUMB: Left thumb - * @LEFT_INDEX: Left index finger - * @LEFT_MIDDLE: Left middle finger - * @LEFT_RING: Left ring finger - * @LEFT_LITTLE: Left little finger - * @RIGHT_THUMB: Right thumb - * @RIGHT_INDEX: Right index finger - * @RIGHT_MIDDLE: Right middle finger - * @RIGHT_RING: Right ring finger - * @RIGHT_LITTLE: Right little finger - * - * Numeric codes used to refer to fingers (and thumbs) of a human. These are - * purposely not available as strings, to avoid getting the library tangled up - * in localization efforts. - */ -enum fp_finger { - LEFT_THUMB = 1, - LEFT_INDEX, - LEFT_MIDDLE, - LEFT_RING, - LEFT_LITTLE, - RIGHT_THUMB, - RIGHT_INDEX, - RIGHT_MIDDLE, - RIGHT_RING, - RIGHT_LITTLE, -}; - -/** - * fp_scan_type: - * @FP_SCAN_TYPE_PRESS: the reader has a surface area that covers the whole finger - * @FP_SCAN_TYPE_SWIPE: the reader requires swiping the finger on a smaller area - * - * Numeric codes used to refer to the scan type of the device. Devices require - * either swiping or pressing the finger on the device. This is useful for - * front-ends. - */ -enum fp_scan_type { - FP_SCAN_TYPE_PRESS = 0, - FP_SCAN_TYPE_SWIPE, -}; - -/* Drivers */ -const char *fp_driver_get_name(struct fp_driver *drv); -const char *fp_driver_get_full_name(struct fp_driver *drv); -uint16_t fp_driver_get_driver_id(struct fp_driver *drv); -enum fp_scan_type fp_driver_get_scan_type(struct fp_driver *drv); -int fp_driver_supports_imaging(struct fp_driver *drv); - -/* Device discovery */ -struct fp_dscv_dev **fp_discover_devs(void); -void fp_dscv_devs_free(struct fp_dscv_dev **devs); -struct fp_driver *fp_dscv_dev_get_driver(struct fp_dscv_dev *dev); -uint16_t fp_dscv_dev_get_driver_id(struct fp_dscv_dev *dev); -uint32_t fp_dscv_dev_get_devtype(struct fp_dscv_dev *dev); -int fp_dscv_dev_supports_print_data(struct fp_dscv_dev *dev, - struct fp_print_data *print); -int fp_dscv_dev_supports_dscv_print(struct fp_dscv_dev *dev, - struct fp_dscv_print *print) LIBFPRINT_DEPRECATED; -struct fp_dscv_dev *fp_dscv_dev_for_print_data(struct fp_dscv_dev **devs, - struct fp_print_data *print) LIBFPRINT_DEPRECATED; -struct fp_dscv_dev *fp_dscv_dev_for_dscv_print(struct fp_dscv_dev **devs, - struct fp_dscv_print *print) LIBFPRINT_DEPRECATED; - -/* Print discovery */ -struct fp_dscv_print **fp_discover_prints(void) LIBFPRINT_DEPRECATED; -void fp_dscv_prints_free(struct fp_dscv_print **prints) LIBFPRINT_DEPRECATED; -uint16_t fp_dscv_print_get_driver_id(struct fp_dscv_print *print) LIBFPRINT_DEPRECATED; -uint32_t fp_dscv_print_get_devtype(struct fp_dscv_print *print) LIBFPRINT_DEPRECATED; -enum fp_finger fp_dscv_print_get_finger(struct fp_dscv_print *print) LIBFPRINT_DEPRECATED; -int fp_dscv_print_delete(struct fp_dscv_print *print) LIBFPRINT_DEPRECATED; - -/* Device handling */ -struct fp_dev *fp_dev_open(struct fp_dscv_dev *ddev); -void fp_dev_close(struct fp_dev *dev); -struct fp_driver *fp_dev_get_driver(struct fp_dev *dev); -int fp_dev_get_nr_enroll_stages(struct fp_dev *dev); -uint32_t fp_dev_get_devtype(struct fp_dev *dev); -int fp_dev_supports_print_data(struct fp_dev *dev, struct fp_print_data *data); -int fp_dev_supports_dscv_print(struct fp_dev *dev, struct fp_dscv_print *print) LIBFPRINT_DEPRECATED; - -/** - * fp_capture_result: - * @FP_CAPTURE_COMPLETE: Capture completed successfully, the capture data has been returned to the caller. - * @FP_CAPTURE_FAIL: Capture failed - * - * Whether a capture failed or completed. - */ -enum fp_capture_result { - FP_CAPTURE_COMPLETE = 0, - FP_CAPTURE_FAIL, -}; - -int fp_dev_supports_imaging(struct fp_dev *dev); -int fp_dev_img_capture(struct fp_dev *dev, int unconditional, - struct fp_img **img); -int fp_dev_get_img_width(struct fp_dev *dev); -int fp_dev_get_img_height(struct fp_dev *dev); - -/** - * fp_enroll_result: - * @FP_ENROLL_COMPLETE: Enrollment completed successfully, the enrollment data has been - * returned to the caller. - * @FP_ENROLL_FAIL: Enrollment failed due to incomprehensible data; this may occur when - * the user scans a different finger on each enroll stage. - * @FP_ENROLL_PASS: Enroll stage passed; more stages are need to complete the process. - * @FP_ENROLL_RETRY: The enrollment scan did not succeed due to poor scan quality or - * other general user scanning problem. - * @FP_ENROLL_RETRY_TOO_SHORT: The enrollment scan did not succeed because the finger swipe was - * too short. - * @FP_ENROLL_RETRY_CENTER_FINGER: The enrollment scan did not succeed because the finger was not - * centered on the scanner. - * @FP_ENROLL_RETRY_REMOVE_FINGER: The verification scan did not succeed due to quality or pressure - * problems; the user should remove their finger from the scanner before - * retrying. - * - * - * Enrollment result codes returned from fp_enroll_finger(). - * Result codes with RETRY in the name suggest that the scan failed due to - * user error. Applications will generally want to inform the user of the - * problem and then retry the enrollment stage. For more info on the semantics - * of interpreting these result codes and tracking enrollment process, see - * [Enrolling](libfprint-Devices-operations.html#enrolling) - */ -enum fp_enroll_result { - FP_ENROLL_COMPLETE = 1, - FP_ENROLL_FAIL, - FP_ENROLL_PASS, - FP_ENROLL_RETRY = 100, - FP_ENROLL_RETRY_TOO_SHORT, - FP_ENROLL_RETRY_CENTER_FINGER, - FP_ENROLL_RETRY_REMOVE_FINGER, -}; - -int fp_enroll_finger_img(struct fp_dev *dev, struct fp_print_data **print_data, - struct fp_img **img); -int fp_enroll_finger(struct fp_dev *dev, - struct fp_print_data **print_data); - -/** - * fp_verify_result: - * @FP_VERIFY_NO_MATCH: The scan completed successfully, but the newly scanned fingerprint - * does not match the fingerprint being verified against. - * In the case of identification, this return code indicates that the - * scanned finger could not be found in the print gallery. - * @FP_VERIFY_MATCH: The scan completed successfully and the newly scanned fingerprint does - * match the fingerprint being verified, or in the case of identification, - * the scanned fingerprint was found in the print gallery. - * @FP_VERIFY_RETRY: The scan did not succeed due to poor scan quality or other general - * user scanning problem. - * @FP_VERIFY_RETRY_TOO_SHORT: The scan did not succeed because the finger swipe was too short. - * @FP_VERIFY_RETRY_CENTER_FINGER: The scan did not succeed because the finger was not centered on the - * scanner. - * @FP_VERIFY_RETRY_REMOVE_FINGER: The scan did not succeed due to quality or pressure problems; the user - * should remove their finger from the scanner before retrying. - * - * Verification result codes returned from fp_verify_finger(). Return codes - * are also shared with fp_identify_finger(). - * Result codes with RETRY in the name suggest that the scan failed due to - * user error. Applications will generally want to inform the user of the - * problem and then retry the verify operation. - */ -enum fp_verify_result { - FP_VERIFY_NO_MATCH = 0, - FP_VERIFY_MATCH = 1, - FP_VERIFY_RETRY = FP_ENROLL_RETRY, - FP_VERIFY_RETRY_TOO_SHORT = FP_ENROLL_RETRY_TOO_SHORT, - FP_VERIFY_RETRY_CENTER_FINGER = FP_ENROLL_RETRY_CENTER_FINGER, - FP_VERIFY_RETRY_REMOVE_FINGER = FP_ENROLL_RETRY_REMOVE_FINGER, -}; - -int fp_verify_finger_img(struct fp_dev *dev, - struct fp_print_data *enrolled_print, struct fp_img **img); -int fp_verify_finger(struct fp_dev *dev, - struct fp_print_data *enrolled_print); - -int fp_dev_supports_identification(struct fp_dev *dev); -int fp_identify_finger_img(struct fp_dev *dev, - struct fp_print_data **print_gallery, size_t *match_offset, - struct fp_img **img); -int fp_identify_finger(struct fp_dev *dev, - struct fp_print_data **print_gallery, size_t *match_offset); - -/* Data handling */ -int fp_print_data_load(struct fp_dev *dev, enum fp_finger finger, - struct fp_print_data **data) LIBFPRINT_DEPRECATED; -int fp_print_data_from_dscv_print(struct fp_dscv_print *print, - struct fp_print_data **data) LIBFPRINT_DEPRECATED; -int fp_print_data_save(struct fp_print_data *data, enum fp_finger finger) - LIBFPRINT_DEPRECATED; -int fp_print_data_delete(struct fp_dev *dev, enum fp_finger finger) - LIBFPRINT_DEPRECATED; -void fp_print_data_free(struct fp_print_data *data); -size_t fp_print_data_get_data(struct fp_print_data *data, unsigned char **ret); -struct fp_print_data *fp_print_data_from_data(unsigned char *buf, - size_t buflen); -uint16_t fp_print_data_get_driver_id(struct fp_print_data *data); -uint32_t fp_print_data_get_devtype(struct fp_print_data *data); - -/* Image handling */ - -/** - * fp_minutia: - * - * #fp_minutia is an opaque structure type. You must access it using the - * functions in this section. - */ -struct fp_minutia; - -int fp_img_get_height(struct fp_img *img); -int fp_img_get_width(struct fp_img *img); -unsigned char *fp_img_get_data(struct fp_img *img); -int fp_img_save_to_file(struct fp_img *img, char *path); -void fp_img_standardize(struct fp_img *img); -struct fp_img *fp_img_binarize(struct fp_img *img); -struct fp_minutia **fp_img_get_minutiae(struct fp_img *img, int *nr_minutiae); -int fp_minutia_get_coords(struct fp_minutia *minutia, int *coord_x, int *coord_y); -void fp_img_free(struct fp_img *img); - -/* Polling and timing */ - -/** - * fp_pollfd: - * @fd: a file descriptor - * @events: Event flags to poll for from `` - * - * A structure representing a file descriptor and the @events to poll - * for, as returned by fp_get_pollfds(). - */ -struct fp_pollfd { - int fd; - short int events; -}; - -int fp_handle_events_timeout(struct timeval *timeout); -int fp_handle_events(void); -ssize_t fp_get_pollfds(struct fp_pollfd **pollfds); -int fp_get_next_timeout(struct timeval *tv); - -/** - * fp_pollfd_added_cb: - * @fd: the new file descriptor - * @events: events to monitor for, see `` for the possible values - * - * Type definition for a function that will be called when a new - * event source is added. The @events argument is a flag as defined in - * `` such as `POLLIN`, or `POLLOUT`. See fp_set_pollfd_notifiers(). - */ -typedef void (*fp_pollfd_added_cb)(int fd, short int events); - -/** - * fp_pollfd_removed_cb: - * @fd: the file descriptor to stop monitoring - * - * Type definition for a function that will be called when an - * event source is removed. See fp_set_pollfd_notifiers(). - */ -typedef void (*fp_pollfd_removed_cb)(int fd); -void fp_set_pollfd_notifiers(fp_pollfd_added_cb added_cb, - fp_pollfd_removed_cb removed_cb); - -/* Library */ -int fp_init(void); -void fp_exit(void); -void fp_set_debug(int level) LIBFPRINT_DEPRECATED; - -/* Asynchronous I/O */ - -/** - * fp_operation_stop_cb: - * @dev: the struct #fp_dev device - * @user_data: user data passed to the callback - * - * Type definition for a function that will be called when fp_async_dev_close(), - * fp_async_verify_stop(), fp_async_identify_stop() or fp_async_capture_stop() - * finishes. - */ -typedef void (*fp_operation_stop_cb)(struct fp_dev *dev, void *user_data); - -/** - * fp_img_operation_cb: - * @dev: the struct #fp_dev device - * @result: an #fp_verify_result for fp_async_verify_start(), or an #fp_capture_result - * for fp_async_capture_start(), or a negative value on error - * @img: the captured #fp_img if capture or verification was successful - * @user_data: user data passed to the callback - * - * Type definition for a function that will be called when fp_async_verify_start() - * or fp_async_capture_start() finished. - */ -typedef void (*fp_img_operation_cb)(struct fp_dev *dev, int result, - struct fp_img *img, void *user_data); - -/** - * fp_dev_open_cb: - * @dev: the struct #fp_dev device - * @status: 0 on success, or a negative value on error - * @user_data: user data passed to the callback - * - * Type definition for a function that will be called when fp_async_dev_open - * finishes. - */ -typedef void (*fp_dev_open_cb)(struct fp_dev *dev, int status, void *user_data); - -int fp_async_dev_open(struct fp_dscv_dev *ddev, fp_dev_open_cb callback, - void *user_data); - -void fp_async_dev_close(struct fp_dev *dev, fp_operation_stop_cb callback, - void *user_data); - -/** - * fp_enroll_stage_cb: - * @dev: the struct #fp_dev device - * @result: a #fp_enroll_result on success, or a negative value on failure - * @print: the enrollment data from the final stage - * @img: an #fp_img to free with fp_img_free() - * @user_data: user data passed to the callback - * - * Type definition for a function that will be called when - * fp_async_enroll_start() finishes. See fp_enroll_finger_img() for - * the expected behaviour of your program based on the @result. - */ -typedef void (*fp_enroll_stage_cb)(struct fp_dev *dev, int result, - struct fp_print_data *print, struct fp_img *img, void *user_data); - -int fp_async_enroll_start(struct fp_dev *dev, fp_enroll_stage_cb callback, - void *user_data); - -int fp_async_enroll_stop(struct fp_dev *dev, fp_operation_stop_cb callback, - void *user_data); - -int fp_async_verify_start(struct fp_dev *dev, struct fp_print_data *data, - fp_img_operation_cb callback, void *user_data); - -int fp_async_verify_stop(struct fp_dev *dev, fp_operation_stop_cb callback, - void *user_data); - -/** - * fp_identify_cb: - * @dev: the struct #fp_dev device - * @result: a #fp_verify_result on success, or a negative value on error. - * @match_offset: the array index of the matched gallery print (if any was found). - * Only valid if %FP_VERIFY_MATCH was returned. - * @img: the scan image, it must be freed with fp_img_free() after use. - * @user_data: user data passed to the callback - * - * Type definition for a function that will be called when fp_async_identify_start() - * finishes. - */ -typedef void (*fp_identify_cb)(struct fp_dev *dev, int result, - size_t match_offset, struct fp_img *img, void *user_data); -int fp_async_identify_start(struct fp_dev *dev, struct fp_print_data **gallery, - fp_identify_cb callback, void *user_data); - -int fp_async_identify_stop(struct fp_dev *dev, fp_operation_stop_cb callback, - void *user_data); - -int fp_async_capture_start(struct fp_dev *dev, int unconditional, fp_img_operation_cb callback, void *user_data); - -int fp_async_capture_stop(struct fp_dev *dev, fp_operation_stop_cb callback, void *user_data); - -#ifdef __cplusplus -} -#endif - -#endif +#pragma once +#include "fp-context.h" +#include "fp-device.h" +#include "fp-image.h" diff --git a/libfprint/libfprint.ver b/libfprint/libfprint.ver new file mode 100644 index 00000000..7b484f6a --- /dev/null +++ b/libfprint/libfprint.ver @@ -0,0 +1,9 @@ +LIBFPRINT_2.0.0 { +global: + fp_*; + + /* Needs to be public for the listing commands. */ + fpi_get_driver_types; +local: + *; +}; diff --git a/libfprint/meson.build b/libfprint/meson.build index 976c70c8..af2fe849 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -1,15 +1,32 @@ libfprint_sources = [ - 'fpi-async.c', + 'fp-context.c', + 'fp-device.c', + 'fp-image.c', + 'fp-print.c', + 'fp-image-device.c', 'fpi-assembling.c', - 'fpi-core.c', - 'fpi-data.c', - 'fpi-dev.c', - 'fpi-dev-img.c', - 'fpi-img.c', 'fpi-ssm.c', - 'fpi-sync.c', - 'fpi-poll.c', - 'fpi-usb.c', + 'fpi-usb-transfer.c', + 'fpi-byte-reader.c', + 'fpi-byte-writer.c', +] + +libfprint_public_headers = [ + 'fp-context.h', + 'fp-device.h', + 'fp-image.h', + 'fp-print.h', +] + +libfprint_private_headers = [ + 'fpi-assembling.h', + 'fpi-device.h', + 'fpi-image.h', + 'fpi-image-device.h', + 'fpi-print.h', + 'fpi-byte-reader.h', + 'fpi-byte-writer.h', + 'fpi-byte-utils.h', ] nbis_sources = [ @@ -121,6 +138,15 @@ foreach driver: drivers if driver == 'elan' drivers_sources += [ 'drivers/elan.c' ] endif + if driver == 'virtual_image' + drivers_sources += [ 'drivers/virtual-image.c' ] + endif + if driver == 'synaptics' + drivers_sources += [ + 'drivers/synaptics/synaptics.c', + 'drivers/synaptics/bmkt_message.c', + ] + endif endforeach if aeslib @@ -134,29 +160,32 @@ if aes3k endif other_sources = [] -if imaging_dep.found() - other_sources += [ 'fpi-img-pixman.c' ] -endif -libfprint_sources += configure_file(input: 'empty_file', - output: 'drivers_definitions.h', - capture: true, - command: [ - '/bin/echo', - drivers_struct_list - ]) +fp_enums = gnome.mkenums_simple('fp-enums', + sources: libfprint_public_headers, + install_header : true) +fp_enums_h = fp_enums[1] -libfprint_sources += configure_file(input: 'empty_file', - output: 'drivers_arrays.h', - capture: true, - command: [ - '/bin/echo', - drivers_primitive_array + '\n\n' + drivers_img_array - ]) +fpi_enums = gnome.mkenums_simple('fpi-enums', + sources: libfprint_private_headers, + install_header : true) +fpi_enums_h = fpi_enums[1] -deps = [ mathlib_dep, glib_dep, libusb_dep, nss_dep, imaging_dep ] +drivers_sources += configure_file(input: 'empty_file', + output: 'fp-drivers.c', + capture: true, + command: [ + 'echo', + drivers_type_list + '\n\n' + drivers_type_func + ]) + +mapfile = 'libfprint.ver' +vflag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), mapfile) + +deps = [ mathlib_dep, glib_dep, gusb_dep, nss_dep, imaging_dep, gio_dep ] libfprint = library('fprint', - libfprint_sources + drivers_sources + nbis_sources + other_sources, + libfprint_sources + fp_enums + fpi_enums + + drivers_sources + nbis_sources + other_sources, soversion: soversion, version: libversion, c_args: common_cflags + drivers_cflags, @@ -164,13 +193,17 @@ libfprint = library('fprint', root_inc, include_directories('nbis/include'), ], + link_args : vflag, + link_depends : mapfile, dependencies: deps, install: true) libfprint_dep = declare_dependency(link_with: libfprint, - include_directories: root_inc) + sources: [ fp_enums_h ], + include_directories: root_inc, + dependencies: [glib_dep, gusb_dep, gio_dep]) -install_headers(['fprint.h'], subdir: 'libfprint') +install_headers(['fprint.h'] + libfprint_public_headers, subdir: 'libfprint') udev_rules = executable('fprint-list-udev-rules', 'fprint-list-udev-rules.c', @@ -196,3 +229,35 @@ supported_devices = executable('fprint-list-supported-devices', ], dependencies: [ deps, libfprint_dep ], install: false) + + +if get_option('introspection') + # We do *not* include the private header here + libfprint_girtarget = gnome.generate_gir(libfprint, + sources : fp_enums + [ + libfprint_public_headers, + libfprint_sources, + ], + nsversion : '2.0', + namespace : 'FPrint', + symbol_prefix : 'fp_', + identifier_prefix : 'Fp', + export_packages : 'fprint', + extra_args : [ + '--c-include=fprint.h', + ], + link_with : libfprint, + dependencies : [ + gio_dep, + gusb_dep, + ], + includes : [ + 'Gio-2.0', + 'GObject-2.0', + 'GUsb-1.0', + ], + install : true + ) + libfprint_gir = libfprint_girtarget[0] + libfprint_typelib = libfprint_girtarget[1] +endif diff --git a/libfprint/nbis/glib-mem-warning.patch b/libfprint/nbis/glib-mem-warning.patch new file mode 100644 index 00000000..75b82b45 --- /dev/null +++ b/libfprint/nbis/glib-mem-warning.patch @@ -0,0 +1,13 @@ +diff --git a/libfprint/nbis/mindtct/shape.c b/libfprint/nbis/mindtct/shape.c +index 28bc66c..c399f36 100644 +--- mindtct/shape.c ++++ mindtct/shape.c +@@ -86,7 +86,7 @@ int alloc_shape(SHAPE **oshape, const int xmin, const int ymin, + { + SHAPE *shape; + int alloc_rows, alloc_pts; +- int i, j, y; ++ int i, y; + + /* Compute allocation parameters. */ + /* First, compute the number of scanlines spanned by the shape. */ diff --git a/libfprint/nbis/glib-memory.cocci b/libfprint/nbis/glib-memory.cocci new file mode 100644 index 00000000..c2ac323b --- /dev/null +++ b/libfprint/nbis/glib-memory.cocci @@ -0,0 +1,29 @@ +@ free @ +expression ptr; +@@ +- free(ptr); ++ g_free(ptr); +@ malloc @ +type ptr_type; +expression ptr; +expression size; +@@ +- ptr = (ptr_type) malloc(size); ++ ptr = (ptr_type) g_malloc(size); + ... +( +- if (ptr == (ptr_type) NULL) { ... } +| +) +@ realloc @ +type ptr_type; +expression ptr; +expression size; +@@ +- ptr = (ptr_type) realloc(ptr, size); ++ ptr = (ptr_type) g_realloc(ptr, size); + ... +( +- if (ptr == (ptr_type) NULL) { ... } +| +) diff --git a/libfprint/nbis/mindtct/binar.c b/libfprint/nbis/mindtct/binar.c index fb2be224..57c82a31 100644 --- a/libfprint/nbis/mindtct/binar.c +++ b/libfprint/nbis/mindtct/binar.c @@ -214,11 +214,7 @@ int binarize_image_V2(unsigned char **odata, int *ow, int *oh, bw = pw - (dirbingrids->pad<<1); bh = ph - (dirbingrids->pad<<1); - bdata = (unsigned char *)malloc(bw*bh*sizeof(unsigned char)); - if(bdata == (unsigned char *)NULL){ - fprintf(stderr, "ERROR : binarize_image_V2 : malloc : bdata\n"); - return(-600); - } + bdata = (unsigned char *)g_malloc(bw * bh * sizeof(unsigned char)); bptr = bdata; spptr = pdata + (dirbingrids->pad * pw) + dirbingrids->pad; diff --git a/libfprint/nbis/mindtct/block.c b/libfprint/nbis/mindtct/block.c index f530f94d..ebdf8c3c 100644 --- a/libfprint/nbis/mindtct/block.c +++ b/libfprint/nbis/mindtct/block.c @@ -134,11 +134,7 @@ int block_offsets(int **optr, int *ow, int *oh, lastbh = bh - 1; /* Allocate list of block offsets */ - blkoffs = (int *)malloc(bsize * sizeof(int)); - if(blkoffs == (int *)NULL){ - fprintf(stderr, "ERROR : block_offsets : malloc : blkoffs\n"); - return(-81); - } + blkoffs = (int *)g_malloc(bsize * sizeof(int)); /* Current block index */ bi = 0; diff --git a/libfprint/nbis/mindtct/chaincod.c b/libfprint/nbis/mindtct/chaincod.c index dd5d779c..b5dd9eeb 100644 --- a/libfprint/nbis/mindtct/chaincod.c +++ b/libfprint/nbis/mindtct/chaincod.c @@ -100,12 +100,7 @@ int chain_code_loop(int **ochain, int *onchain, /* number of points in the contour. There will be one chain code */ /* between each point on the contour including a code between the */ /* last to the first point on the contour (completing the loop). */ - chain = (int *)malloc(ncontour * sizeof(int)); - /* If the allocation fails ... */ - if(chain == (int *)NULL){ - fprintf(stderr, "ERROR : chain_code_loop : malloc : chain\n"); - return(-170); - } + chain = (int *)g_malloc(ncontour * sizeof(int)); /* For each neighboring point in the list (with "i" pointing to the */ /* previous neighbor and "j" pointing to the next neighbor... */ diff --git a/libfprint/nbis/mindtct/contour.c b/libfprint/nbis/mindtct/contour.c index 5d802c28..3e9416c3 100644 --- a/libfprint/nbis/mindtct/contour.c +++ b/libfprint/nbis/mindtct/contour.c @@ -110,45 +110,16 @@ int allocate_contour(int **ocontour_x, int **ocontour_y, ASSERT_SIZE_MUL(ncontour, sizeof(int)); /* Allocate contour's x-coord list. */ - contour_x = (int *)malloc(ncontour*sizeof(int)); - /* If allocation error... */ - if(contour_x == (int *)NULL){ - fprintf(stderr, "ERROR : allocate_contour : malloc : contour_x\n"); - return(-180); - } + contour_x = (int *)g_malloc(ncontour * sizeof(int)); /* Allocate contour's y-coord list. */ - contour_y = (int *)malloc(ncontour*sizeof(int)); - /* If allocation error... */ - if(contour_y == (int *)NULL){ - /* Deallocate memory allocated to this point in this routine. */ - free(contour_x); - fprintf(stderr, "ERROR : allocate_contour : malloc : contour_y\n"); - return(-181); - } + contour_y = (int *)g_malloc(ncontour * sizeof(int)); /* Allocate contour's edge x-coord list. */ - contour_ex = (int *)malloc(ncontour*sizeof(int)); - /* If allocation error... */ - if(contour_ex == (int *)NULL){ - /* Deallocate memory allocated to this point in this routine. */ - free(contour_x); - free(contour_y); - fprintf(stderr, "ERROR : allocate_contour : malloc : contour_ex\n"); - return(-182); - } + contour_ex = (int *)g_malloc(ncontour * sizeof(int)); /* Allocate contour's edge y-coord list. */ - contour_ey = (int *)malloc(ncontour*sizeof(int)); - /* If allocation error... */ - if(contour_ey == (int *)NULL){ - /* Deallocate memory allocated to this point in this routine. */ - free(contour_x); - free(contour_y); - free(contour_ex); - fprintf(stderr, "ERROR : allocate_contour : malloc : contour_ey\n"); - return(-183); - } + contour_ey = (int *)g_malloc(ncontour * sizeof(int)); /* Otherwise, allocations successful, so assign output pointers. */ *ocontour_x = contour_x; @@ -181,10 +152,10 @@ int allocate_contour(int **ocontour_x, int **ocontour_y, void free_contour(int *contour_x, int *contour_y, int *contour_ex, int *contour_ey) { - free(contour_x); - free(contour_y); - free(contour_ex); - free(contour_ey); + g_free(contour_x); + g_free(contour_y); + g_free(contour_ex); + g_free(contour_ey); } /************************************************************************* diff --git a/libfprint/nbis/mindtct/detect.c b/libfprint/nbis/mindtct/detect.c index 10ed85c5..703579db 100644 --- a/libfprint/nbis/mindtct/detect.c +++ b/libfprint/nbis/mindtct/detect.c @@ -207,15 +207,7 @@ int lfs_detect_minutiae_V2(MINUTIAE **ominutiae, } else{ /* If padding is unnecessary, then copy the input image. */ - pdata = (unsigned char *)malloc(iw*ih); - if(pdata == (unsigned char *)NULL){ - /* Free memory allocated to this point. */ - free_dir2rad(dir2rad); - free_dftwaves(dftwaves); - free_rotgrids(dftgrids); - fprintf(stderr, "ERROR : lfs_detect_minutiae_V2 : malloc : pdata\n"); - return(-580); - } + pdata = (unsigned char *)g_malloc(iw * ih); memcpy(pdata, idata, iw*ih); pw = iw; ph = ih; @@ -244,7 +236,7 @@ int lfs_detect_minutiae_V2(MINUTIAE **ominutiae, free_dir2rad(dir2rad); free_dftwaves(dftwaves); free_rotgrids(dftgrids); - free(pdata); + g_free(pdata); return(ret); } /* Deallocate working memories. */ @@ -268,11 +260,11 @@ int lfs_detect_minutiae_V2(MINUTIAE **ominutiae, lfsparms->dirbin_grid_w, lfsparms->dirbin_grid_h, RELATIVE2CENTER))){ /* Free memory allocated to this point. */ - free(pdata); - free(direction_map); - free(low_contrast_map); - free(low_flow_map); - free(high_curve_map); + g_free(pdata); + g_free(direction_map); + g_free(low_contrast_map); + g_free(low_flow_map); + g_free(high_curve_map); return(ret); } @@ -281,11 +273,11 @@ int lfs_detect_minutiae_V2(MINUTIAE **ominutiae, pdata, pw, ph, direction_map, mw, mh, dirbingrids, lfsparms))){ /* Free memory allocated to this point. */ - free(pdata); - free(direction_map); - free(low_contrast_map); - free(low_flow_map); - free(high_curve_map); + g_free(pdata); + g_free(direction_map); + g_free(low_contrast_map); + g_free(low_flow_map); + g_free(high_curve_map); free_rotgrids(dirbingrids); return(ret); } @@ -297,12 +289,12 @@ int lfs_detect_minutiae_V2(MINUTIAE **ominutiae, /* the input image, then ERROR. */ if((iw != bw) || (ih != bh)){ /* Free memory allocated to this point. */ - free(pdata); - free(direction_map); - free(low_contrast_map); - free(low_flow_map); - free(high_curve_map); - free(bdata); + g_free(pdata); + g_free(direction_map); + g_free(low_contrast_map); + g_free(low_flow_map); + g_free(high_curve_map); + g_free(bdata); fprintf(stderr, "ERROR : lfs_detect_minutiae_V2 :"); fprintf(stderr,"binary image has bad dimensions : %d, %d\n", bw, bh); @@ -332,12 +324,12 @@ int lfs_detect_minutiae_V2(MINUTIAE **ominutiae, direction_map, low_flow_map, high_curve_map, mw, mh, lfsparms))){ /* Free memory allocated to this point. */ - free(pdata); - free(direction_map); - free(low_contrast_map); - free(low_flow_map); - free(high_curve_map); - free(bdata); + g_free(pdata); + g_free(direction_map); + g_free(low_contrast_map); + g_free(low_flow_map); + g_free(high_curve_map); + g_free(bdata); return(ret); } @@ -349,12 +341,12 @@ int lfs_detect_minutiae_V2(MINUTIAE **ominutiae, direction_map, low_flow_map, high_curve_map, mw, mh, lfsparms))){ /* Free memory allocated to this point. */ - free(pdata); - free(direction_map); - free(low_contrast_map); - free(low_flow_map); - free(high_curve_map); - free(bdata); + g_free(pdata); + g_free(direction_map); + g_free(low_contrast_map); + g_free(low_flow_map); + g_free(high_curve_map); + g_free(bdata); free_minutiae(minutiae); return(ret); } @@ -370,11 +362,11 @@ int lfs_detect_minutiae_V2(MINUTIAE **ominutiae, if((ret = count_minutiae_ridges(minutiae, bdata, iw, ih, lfsparms))){ /* Free memory allocated to this point. */ - free(pdata); - free(direction_map); - free(low_contrast_map); - free(low_flow_map); - free(high_curve_map); + g_free(pdata); + g_free(direction_map); + g_free(low_contrast_map); + g_free(low_flow_map); + g_free(high_curve_map); free_minutiae(minutiae); return(ret); } @@ -393,7 +385,7 @@ int lfs_detect_minutiae_V2(MINUTIAE **ominutiae, gray2bin(1, 255, 0, bdata, iw, ih); /* Deallocate working memory. */ - free(pdata); + g_free(pdata); /* Assign results to output pointers. */ *odmap = direction_map; diff --git a/libfprint/nbis/mindtct/dft.c b/libfprint/nbis/mindtct/dft.c index be485864..3b49ecf7 100644 --- a/libfprint/nbis/mindtct/dft.c +++ b/libfprint/nbis/mindtct/dft.c @@ -113,11 +113,7 @@ int dft_dir_powers(double **powers, unsigned char *pdata, fprintf(stderr, "ERROR : dft_dir_powers : DFT grids must be square\n"); return(-90); } - rowsums = (int *)malloc(dftgrids->grid_w * sizeof(int)); - if(rowsums == (int *)NULL){ - fprintf(stderr, "ERROR : dft_dir_powers : malloc : rowsums\n"); - return(-91); - } + rowsums = (int *)g_malloc(dftgrids->grid_w * sizeof(int)); memset(rowsums, 0, dftgrids->grid_w * sizeof(int)); /* Foreach direction ... */ @@ -135,7 +131,7 @@ int dft_dir_powers(double **powers, unsigned char *pdata, } /* Deallocate working memory. */ - free(rowsums); + g_free(rowsums); return(0); } @@ -355,11 +351,7 @@ int sort_dft_waves(int *wis, const double *powmaxs, const double *pownorms, double *pownorms2; /* Allocate normalized power^2 array */ - pownorms2 = (double *)malloc(nstats * sizeof(double)); - if(pownorms2 == (double *)NULL){ - fprintf(stderr, "ERROR : sort_dft_waves : malloc : pownorms2\n"); - return(-100); - } + pownorms2 = (double *)g_malloc(nstats * sizeof(double)); for(i = 0; i < nstats; i++){ /* Wis will hold the sorted statistic indices when all is done. */ @@ -372,7 +364,7 @@ int sort_dft_waves(int *wis, const double *powmaxs, const double *pownorms, bubble_sort_double_dec_2(pownorms2, wis, nstats); /* Deallocate the working memory. */ - free(pownorms2); + g_free(pownorms2); return(0); } diff --git a/libfprint/nbis/mindtct/free.c b/libfprint/nbis/mindtct/free.c index adaeeb9a..1acd7e2d 100644 --- a/libfprint/nbis/mindtct/free.c +++ b/libfprint/nbis/mindtct/free.c @@ -72,9 +72,9 @@ of the software. *************************************************************************/ void free_dir2rad(DIR2RAD *dir2rad) { - free(dir2rad->cos); - free(dir2rad->sin); - free(dir2rad); + g_free(dir2rad->cos); + g_free(dir2rad->sin); + g_free(dir2rad); } /************************************************************************* @@ -90,12 +90,12 @@ void free_dftwaves(DFTWAVES *dftwaves) int i; for(i = 0; i < dftwaves->nwaves; i++){ - free(dftwaves->waves[i]->cos); - free(dftwaves->waves[i]->sin); - free(dftwaves->waves[i]); + g_free(dftwaves->waves[i]->cos); + g_free(dftwaves->waves[i]->sin); + g_free(dftwaves->waves[i]); } - free(dftwaves->waves); - free(dftwaves); + g_free(dftwaves->waves); + g_free(dftwaves); } /************************************************************************* @@ -111,9 +111,9 @@ void free_rotgrids(ROTGRIDS *rotgrids) int i; for(i = 0; i < rotgrids->ngrids; i++) - free(rotgrids->grids[i]); - free(rotgrids->grids); - free(rotgrids); + g_free(rotgrids->grids[i]); + g_free(rotgrids->grids); + g_free(rotgrids); } /************************************************************************* @@ -129,8 +129,8 @@ void free_dir_powers(double **powers, const int nwaves) int w; for(w = 0; w < nwaves; w++) - free(powers[w]); + g_free(powers[w]); - free(powers); + g_free(powers); } diff --git a/libfprint/nbis/mindtct/getmin.c b/libfprint/nbis/mindtct/getmin.c index 08a087d8..3597a0a8 100644 --- a/libfprint/nbis/mindtct/getmin.c +++ b/libfprint/nbis/mindtct/getmin.c @@ -134,11 +134,11 @@ int get_minutiae(MINUTIAE **ominutiae, int **oquality_map, direction_map, low_contrast_map, low_flow_map, high_curve_map, map_w, map_h))){ free_minutiae(minutiae); - free(direction_map); - free(low_contrast_map); - free(low_flow_map); - free(high_curve_map); - free(bdata); + g_free(direction_map); + g_free(low_contrast_map); + g_free(low_flow_map); + g_free(high_curve_map); + g_free(bdata); return(ret); } @@ -147,12 +147,12 @@ int get_minutiae(MINUTIAE **ominutiae, int **oquality_map, lfsparms->blocksize, idata, iw, ih, id, ppmm))){ free_minutiae(minutiae); - free(direction_map); - free(low_contrast_map); - free(low_flow_map); - free(high_curve_map); - free(quality_map); - free(bdata); + g_free(direction_map); + g_free(low_contrast_map); + g_free(low_flow_map); + g_free(high_curve_map); + g_free(quality_map); + g_free(bdata); return(ret); } diff --git a/libfprint/nbis/mindtct/imgutil.c b/libfprint/nbis/mindtct/imgutil.c index 50cf7666..63f4ec9a 100644 --- a/libfprint/nbis/mindtct/imgutil.c +++ b/libfprint/nbis/mindtct/imgutil.c @@ -191,11 +191,7 @@ int pad_uchar_image(unsigned char **optr, int *ow, int *oh, psize = pw * ph; /* Allocate padded image */ - pdata = (unsigned char *)malloc(psize * sizeof(unsigned char)); - if(pdata == (unsigned char *)NULL){ - fprintf(stderr, "ERROR : pad_uchar_image : malloc : pdata\n"); - return(-160); - } + pdata = (unsigned char *)g_malloc(psize * sizeof(unsigned char)); /* Initialize values to a constant PAD value */ memset(pdata, pad_value, psize); @@ -355,8 +351,8 @@ int free_path(const int x1, const int y1, const int x2, const int y2, /* If number of transitions seen > than threshold (ex. 2) ... */ if(trans > lfsparms->maxtrans){ /* Deallocate the line segment's coordinate lists. */ - free(x_list); - free(y_list); + g_free(x_list); + g_free(y_list); /* Return free path to be FALSE. */ return(FALSE); } @@ -370,8 +366,8 @@ int free_path(const int x1, const int y1, const int x2, const int y2, /* If we get here we did not exceed the maximum allowable number */ /* of transitions. So, deallocate the line segment's coordinate lists. */ - free(x_list); - free(y_list); + g_free(x_list); + g_free(y_list); /* Return free path to be TRUE. */ return(TRUE); diff --git a/libfprint/nbis/mindtct/init.c b/libfprint/nbis/mindtct/init.c index 90152283..28e182c8 100644 --- a/libfprint/nbis/mindtct/init.c +++ b/libfprint/nbis/mindtct/init.c @@ -91,33 +91,16 @@ int init_dir2rad(DIR2RAD **optr, const int ndirs) double cs, sn; /* Allocate structure */ - dir2rad = (DIR2RAD *)malloc(sizeof(DIR2RAD)); - if(dir2rad == (DIR2RAD *)NULL){ - fprintf(stderr, "ERROR : init_dir2rad : malloc : dir2rad\n"); - return(-10); - } + dir2rad = (DIR2RAD *)g_malloc(sizeof(DIR2RAD)); /* Assign number of directions */ dir2rad->ndirs = ndirs; /* Allocate cosine vector */ - dir2rad->cos = (double *)malloc(ndirs * sizeof(double)); - if(dir2rad->cos == (double *)NULL){ - /* Free memory allocated to this point. */ - free(dir2rad); - fprintf(stderr, "ERROR : init_dir2rad : malloc : dir2rad->cos\n"); - return(-11); - } + dir2rad->cos = (double *)g_malloc(ndirs * sizeof(double)); /* Allocate sine vector */ - dir2rad->sin = (double *)malloc(ndirs * sizeof(double)); - if(dir2rad->sin == (double *)NULL){ - /* Free memory allocated to this point. */ - free(dir2rad->cos); - free(dir2rad); - fprintf(stderr, "ERROR : init_dir2rad : malloc : dir2rad->sin\n"); - return(-12); - } + dir2rad->sin = (double *)g_malloc(ndirs * sizeof(double)); /* Pi_factor sets the period of the trig functions to NDIRS units in x. */ /* For example, if NDIRS==16, then pi_factor = 2(PI/16) = .3926... */ @@ -166,11 +149,7 @@ int init_dftwaves(DFTWAVES **optr, const double *dft_coefs, double *cptr, *sptr; /* Allocate structure */ - dftwaves = (DFTWAVES *)malloc(sizeof(DFTWAVES)); - if(dftwaves == (DFTWAVES *)NULL){ - fprintf(stderr, "ERROR : init_dftwaves : malloc : dftwaves\n"); - return(-20); - } + dftwaves = (DFTWAVES *)g_malloc(sizeof(DFTWAVES)); /* Set number of DFT waves */ dftwaves->nwaves = nwaves; @@ -178,10 +157,10 @@ int init_dftwaves(DFTWAVES **optr, const double *dft_coefs, dftwaves->wavelen = blocksize; /* Allocate list of wave pointers */ - dftwaves->waves = (DFTWAVE **)malloc(nwaves * sizeof(DFTWAVE *)); + dftwaves->waves = (DFTWAVE **)g_malloc(nwaves * sizeof(DFTWAVE *)); if(dftwaves == (DFTWAVES *)NULL){ /* Free memory allocated to this point. */ - free(dftwaves); + g_free(dftwaves); fprintf(stderr, "ERROR : init_dftwaves : malloc : dftwaves->waves\n"); return(-21); } @@ -194,53 +173,11 @@ int init_dftwaves(DFTWAVES **optr, const double *dft_coefs, /* Foreach of 4 DFT frequency coef ... */ for (i = 0; i < nwaves; ++i) { /* Allocate wave structure */ - dftwaves->waves[i] = (DFTWAVE *)malloc(sizeof(DFTWAVE)); - if(dftwaves->waves[i] == (DFTWAVE *)NULL){ - /* Free memory allocated to this point. */ - { int _j; for(_j = 0; _j < i; _j++){ - free(dftwaves->waves[_j]->cos); - free(dftwaves->waves[_j]->sin); - free(dftwaves->waves[_j]); - }} - free(dftwaves->waves); - free(dftwaves); - fprintf(stderr, - "ERROR : init_dftwaves : malloc : dftwaves->waves[i]\n"); - return(-22); - } + dftwaves->waves[i] = (DFTWAVE *)g_malloc(sizeof(DFTWAVE)); /* Allocate cosine vector */ - dftwaves->waves[i]->cos = (double *)malloc(blocksize * sizeof(double)); - if(dftwaves->waves[i]->cos == (double *)NULL){ - /* Free memory allocated to this point. */ - { int _j; for(_j = 0; _j < i; _j++){ - free(dftwaves->waves[_j]->cos); - free(dftwaves->waves[_j]->sin); - free(dftwaves->waves[_j]); - }} - free(dftwaves->waves[i]); - free(dftwaves->waves); - free(dftwaves); - fprintf(stderr, - "ERROR : init_dftwaves : malloc : dftwaves->waves[i]->cos\n"); - return(-23); - } + dftwaves->waves[i]->cos = (double *)g_malloc(blocksize * sizeof(double)); /* Allocate sine vector */ - dftwaves->waves[i]->sin = (double *)malloc(blocksize * sizeof(double)); - if(dftwaves->waves[i]->sin == (double *)NULL){ - /* Free memory allocated to this point. */ - { int _j; for(_j = 0; _j < i; _j++){ - free(dftwaves->waves[_j]->cos); - free(dftwaves->waves[_j]->sin); - free(dftwaves->waves[_j]); - }} - free(dftwaves->waves[i]->cos); - free(dftwaves->waves[i]); - free(dftwaves->waves); - free(dftwaves); - fprintf(stderr, - "ERROR : init_dftwaves : malloc : dftwaves->waves[i]->sin\n"); - return(-24); - } + dftwaves->waves[i]->sin = (double *)g_malloc(blocksize * sizeof(double)); /* Assign pointer nicknames */ cptr = dftwaves->waves[i]->cos; @@ -435,11 +372,7 @@ int init_rotgrids(ROTGRIDS **optr, const int iw, const int ih, const int ipad, double pad; /* Allocate structure */ - rotgrids = (ROTGRIDS *)malloc(sizeof(ROTGRIDS)); - if(rotgrids == (ROTGRIDS *)NULL){ - fprintf(stderr, "ERROR : init_rotgrids : malloc : rotgrids\n"); - return(-30); - } + rotgrids = (ROTGRIDS *)g_malloc(sizeof(ROTGRIDS)); /* Set rotgrid attributes */ rotgrids->ngrids = ndirs; @@ -474,7 +407,7 @@ int init_rotgrids(ROTGRIDS **optr, const int iw, const int ih, const int ipad, fprintf(stderr, "ERROR : init_rotgrids : Illegal relative flag : %d\n", relative2); - free(rotgrids); + g_free(rotgrids); return(-31); } @@ -488,7 +421,7 @@ int init_rotgrids(ROTGRIDS **optr, const int iw, const int ih, const int ipad, if(ipad < grid_pad){ /* If input pad is NOT large enough, then ERROR. */ fprintf(stderr, "ERROR : init_rotgrids : Pad passed is too small\n"); - free(rotgrids); + g_free(rotgrids); return(-32); } /* Otherwise, use the specified input pad in computing grid offsets. */ @@ -506,13 +439,7 @@ int init_rotgrids(ROTGRIDS **optr, const int iw, const int ih, const int ipad, cy = (grid_h-1)/(double)2.0; /* Allocate list of rotgrid pointers */ - rotgrids->grids = (int **)malloc(ndirs * sizeof(int *)); - if(rotgrids->grids == (int **)NULL){ - /* Free memory allocated to this point. */ - free(rotgrids); - fprintf(stderr, "ERROR : init_rotgrids : malloc : rotgrids->grids\n"); - return(-33); - } + rotgrids->grids = (int **)g_malloc(ndirs * sizeof(int *)); /* Pi_offset is the offset in radians from which angles are to begin. */ pi_offset = start_dir_angle; @@ -523,17 +450,7 @@ int init_rotgrids(ROTGRIDS **optr, const int iw, const int ih, const int ipad, dir < ndirs; dir++, theta += pi_incr) { /* Allocate a rotgrid */ - rotgrids->grids[dir] = (int *)malloc(grid_size * sizeof(int)); - if(rotgrids->grids[dir] == (int *)NULL){ - /* Free memory allocated to this point. */ - { int _j; for(_j = 0; _j < dir; _j++){ - free(rotgrids->grids[_j]); - }} - free(rotgrids); - fprintf(stderr, - "ERROR : init_rotgrids : malloc : rotgrids->grids[dir]\n"); - return(-34); - } + rotgrids->grids[dir] = (int *)g_malloc(grid_size * sizeof(int)); /* Set pointer to current grid */ grid = rotgrids->grids[dir]; @@ -635,24 +552,11 @@ int alloc_dir_powers(double ***opowers, const int nwaves, const int ndirs) double **powers; /* Allocate list of double pointers to hold power vectors */ - powers = (double **)malloc(nwaves * sizeof(double*)); - if(powers == (double **)NULL){ - fprintf(stderr, "ERROR : alloc_dir_powers : malloc : powers\n"); - return(-40); - } + powers = (double **)g_malloc(nwaves * sizeof(double *)); /* Foreach DFT wave ... */ for(w = 0; w < nwaves; w++){ /* Allocate power vector for all directions */ - powers[w] = (double *)malloc(ndirs * sizeof(double)); - if(powers[w] == (double *)NULL){ - /* Free memory allocated to this point. */ - { int _j; for(_j = 0; _j < w; _j++){ - free(powers[_j]); - }} - free(powers); - fprintf(stderr, "ERROR : alloc_dir_powers : malloc : powers[w]\n"); - return(-41); - } + powers[w] = (double *)g_malloc(ndirs * sizeof(double)); } *opowers = powers; @@ -697,41 +601,16 @@ int alloc_power_stats(int **owis, double **opowmaxs, int **opowmax_dirs, ASSERT_SIZE_MUL(nstats, sizeof(double)); /* Allocate DFT wave index vector */ - wis = (int *)malloc(nstats * sizeof(int)); - if(wis == (int *)NULL){ - fprintf(stderr, "ERROR : alloc_power_stats : malloc : wis\n"); - return(-50); - } + wis = (int *)g_malloc(nstats * sizeof(int)); /* Allocate max power vector */ - powmaxs = (double *)malloc(nstats * sizeof(double)); - if(powmaxs == (double *)NULL){ - /* Free memory allocated to this point. */ - free(wis); - fprintf(stderr, "ERROR : alloc_power_stats : malloc : powmaxs\n"); - return(-51); - } + powmaxs = (double *)g_malloc(nstats * sizeof(double)); /* Allocate max power direction vector */ - powmax_dirs = (int *)malloc(nstats * sizeof(int)); - if(powmax_dirs == (int *)NULL){ - /* Free memory allocated to this point. */ - free(wis); - free(powmaxs); - fprintf(stderr, "ERROR : alloc_power_stats : malloc : powmax_dirs\n"); - return(-52); - } + powmax_dirs = (int *)g_malloc(nstats * sizeof(int)); /* Allocate normalized power vector */ - pownorms = (double *)malloc(nstats * sizeof(double)); - if(pownorms == (double *)NULL){ - /* Free memory allocated to this point. */ - free(wis); - free(powmaxs); - free(powmax_dirs); - fprintf(stderr, "ERROR : alloc_power_stats : malloc : pownorms\n"); - return(-53); - } + pownorms = (double *)g_malloc(nstats * sizeof(double)); *owis = wis; *opowmaxs = powmaxs; diff --git a/libfprint/nbis/mindtct/line.c b/libfprint/nbis/mindtct/line.c index 07edf18d..d556141d 100644 --- a/libfprint/nbis/mindtct/line.c +++ b/libfprint/nbis/mindtct/line.c @@ -95,17 +95,8 @@ int line_points(int **ox_list, int **oy_list, int *onum, asize = max(abs(x2-x1)+2, abs(y2-y1)+2); /* Allocate x and y-pixel coordinate lists to length 'asize'. */ - x_list = (int *)malloc(asize*sizeof(int)); - if(x_list == (int *)NULL){ - fprintf(stderr, "ERROR : line_points : malloc : x_list\n"); - return(-410); - } - y_list = (int *)malloc(asize*sizeof(int)); - if(y_list == (int *)NULL){ - free(x_list); - fprintf(stderr, "ERROR : line_points : malloc : y_list\n"); - return(-411); - } + x_list = (int *)g_malloc(asize * sizeof(int)); + y_list = (int *)g_malloc(asize * sizeof(int)); /* Compute delta x and y. */ dx = x2 - x1; @@ -190,8 +181,8 @@ int line_points(int **ox_list, int **oy_list, int *onum, if(i >= asize){ fprintf(stderr, "ERROR : line_points : coord list overflow\n"); - free(x_list); - free(y_list); + g_free(x_list); + g_free(y_list); return(-412); } diff --git a/libfprint/nbis/mindtct/loop.c b/libfprint/nbis/mindtct/loop.c index 2142d181..6ab8ea2d 100644 --- a/libfprint/nbis/mindtct/loop.c +++ b/libfprint/nbis/mindtct/loop.c @@ -443,7 +443,7 @@ int is_loop_clockwise(const int *contour_x, const int *contour_y, ret = is_chain_clockwise(chain, nchain, default_ret); /* Free the chain code and return result. */ - free(chain); + g_free(chain); return(ret); } diff --git a/libfprint/nbis/mindtct/maps.c b/libfprint/nbis/mindtct/maps.c index ac3b82da..28e5b5f5 100644 --- a/libfprint/nbis/mindtct/maps.c +++ b/libfprint/nbis/mindtct/maps.c @@ -154,14 +154,14 @@ int gen_image_maps(int **odmap, int **olcmap, int **olfmap, int **ohcmap, &low_flow_map, blkoffs, mw, mh, pdata, pw, ph, dftwaves, dftgrids, lfsparms))){ /* Free memory allocated to this point. */ - free(blkoffs); + g_free(blkoffs); return(ret); } if((ret = morph_TF_map(low_flow_map, mw, mh, lfsparms))){ - free(direction_map); - free(low_contrast_map); - free(low_flow_map); + g_free(direction_map); + g_free(low_contrast_map); + g_free(low_flow_map); return(ret); } @@ -176,9 +176,9 @@ int gen_image_maps(int **odmap, int **olcmap, int **olfmap, int **ohcmap, /* 5. Interpolate INVALID direction blocks with their valid neighbors. */ if((ret = interpolate_direction_map(direction_map, low_contrast_map, mw, mh, lfsparms))){ - free(direction_map); - free(low_contrast_map); - free(low_flow_map); + g_free(direction_map); + g_free(low_contrast_map); + g_free(low_flow_map); return(ret); } @@ -198,14 +198,14 @@ int gen_image_maps(int **odmap, int **olcmap, int **olfmap, int **ohcmap, /* 9. Generate High Curvature Map from interpolated Direction Map. */ if((ret = gen_high_curve_map(&high_curve_map, direction_map, mw, mh, lfsparms))){ - free(direction_map); - free(low_contrast_map); - free(low_flow_map); + g_free(direction_map); + g_free(low_contrast_map); + g_free(low_flow_map); return(ret); } /* Deallocate working memory. */ - free(blkoffs); + g_free(blkoffs); *odmap = direction_map; *olcmap = low_contrast_map; @@ -276,44 +276,26 @@ int gen_initial_maps(int **odmap, int **olcmap, int **olfmap, bsize = mw * mh; /* Allocate Direction Map memory */ - direction_map = (int *)malloc(bsize * sizeof(int)); - if(direction_map == (int *)NULL){ - fprintf(stderr, - "ERROR : gen_initial_maps : malloc : direction_map\n"); - return(-550); - } + direction_map = (int *)g_malloc(bsize * sizeof(int)); /* Initialize the Direction Map to INVALID (-1). */ memset(direction_map, INVALID_DIR, bsize * sizeof(int)); /* Allocate Low Contrast Map memory */ - low_contrast_map = (int *)malloc(bsize * sizeof(int)); - if(low_contrast_map == (int *)NULL){ - free(direction_map); - fprintf(stderr, - "ERROR : gen_initial_maps : malloc : low_contrast_map\n"); - return(-551); - } + low_contrast_map = (int *)g_malloc(bsize * sizeof(int)); /* Initialize the Low Contrast Map to FALSE (0). */ memset(low_contrast_map, 0, bsize * sizeof(int)); /* Allocate Low Ridge Flow Map memory */ - low_flow_map = (int *)malloc(bsize * sizeof(int)); - if(low_flow_map == (int *)NULL){ - free(direction_map); - free(low_contrast_map); - fprintf(stderr, - "ERROR : gen_initial_maps : malloc : low_flow_map\n"); - return(-552); - } + low_flow_map = (int *)g_malloc(bsize * sizeof(int)); /* Initialize the Low Flow Map to FALSE (0). */ memset(low_flow_map, 0, bsize * sizeof(int)); /* Allocate DFT directional power vectors */ if((ret = alloc_dir_powers(&powers, dftwaves->nwaves, dftgrids->ngrids))){ /* Free memory allocated to this point. */ - free(direction_map); - free(low_contrast_map); - free(low_flow_map); + g_free(direction_map); + g_free(low_contrast_map); + g_free(low_flow_map); return(ret); } @@ -324,9 +306,9 @@ int gen_initial_maps(int **odmap, int **olcmap, int **olfmap, if((ret = alloc_power_stats(&wis, &powmaxs, &powmax_dirs, &pownorms, nstats))){ /* Free memory allocated to this point. */ - free(direction_map); - free(low_contrast_map); - free(low_flow_map); + g_free(direction_map); + g_free(low_contrast_map); + g_free(low_flow_map); free_dir_powers(powers, dftwaves->nwaves); return(ret); } @@ -364,14 +346,14 @@ int gen_initial_maps(int **odmap, int **olcmap, int **olfmap, pdata, pw, ph, lfsparms))){ /* If system error ... */ if(ret < 0){ - free(direction_map); - free(low_contrast_map); - free(low_flow_map); + g_free(direction_map); + g_free(low_contrast_map); + g_free(low_flow_map); free_dir_powers(powers, dftwaves->nwaves); - free(wis); - free(powmaxs); - free(powmax_dirs); - free(pownorms); + g_free(wis); + g_free(powmaxs); + g_free(powmax_dirs); + g_free(pownorms); return(ret); } @@ -388,14 +370,14 @@ int gen_initial_maps(int **odmap, int **olcmap, int **olfmap, if((ret = dft_dir_powers(powers, pdata, low_contrast_offset, pw, ph, dftwaves, dftgrids))){ /* Free memory allocated to this point. */ - free(direction_map); - free(low_contrast_map); - free(low_flow_map); + g_free(direction_map); + g_free(low_contrast_map); + g_free(low_flow_map); free_dir_powers(powers, dftwaves->nwaves); - free(wis); - free(powmaxs); - free(powmax_dirs); - free(pownorms); + g_free(wis); + g_free(powmaxs); + g_free(powmax_dirs); + g_free(pownorms); return(ret); } @@ -405,14 +387,14 @@ int gen_initial_maps(int **odmap, int **olcmap, int **olfmap, if((ret = dft_power_stats(wis, powmaxs, powmax_dirs, pownorms, powers, 1, dftwaves->nwaves, dftgrids->ngrids))){ /* Free memory allocated to this point. */ - free(direction_map); - free(low_contrast_map); - free(low_flow_map); + g_free(direction_map); + g_free(low_contrast_map); + g_free(low_flow_map); free_dir_powers(powers, dftwaves->nwaves); - free(wis); - free(powmaxs); - free(powmax_dirs); - free(pownorms); + g_free(wis); + g_free(powmaxs); + g_free(powmax_dirs); + g_free(pownorms); return(ret); } @@ -452,10 +434,10 @@ int gen_initial_maps(int **odmap, int **olcmap, int **olfmap, /* Deallocate working memory */ free_dir_powers(powers, dftwaves->nwaves); - free(wis); - free(powmaxs); - free(powmax_dirs); - free(pownorms); + g_free(wis); + g_free(powmaxs); + g_free(powmax_dirs); + g_free(pownorms); *odmap = direction_map; *olcmap = low_contrast_map; @@ -505,12 +487,7 @@ int interpolate_direction_map(int *direction_map, int *low_contrast_map, /* Allocate output (interpolated) Direction Map. */ ASSERT_SIZE_MUL(mw, mh); ASSERT_SIZE_MUL(mw * mh, sizeof(int)); - omap = (int *)malloc(mw*mh*sizeof(int)); - if(omap == (int *)NULL){ - fprintf(stderr, - "ERROR : interpolate_direction_map : malloc : omap\n"); - return(-520); - } + omap = (int *)g_malloc(mw * mh * sizeof(int)); /* Set pointers to the first block in the maps. */ dptr = direction_map; @@ -650,7 +627,7 @@ int interpolate_direction_map(int *direction_map, int *low_contrast_map, /* Copy the interpolated directions into the input map. */ memcpy(direction_map, omap, mw*mh*sizeof(int)); /* Deallocate the working memory. */ - free(omap); + g_free(omap); /* Return normally. */ return(0); @@ -680,18 +657,9 @@ int morph_TF_map(int *tfmap, const int mw, const int mh, ASSERT_INT_MUL(mw, mh); /* Convert TRUE/FALSE map into a binary byte image. */ - cimage = (unsigned char *)malloc(mw*mh); - if(cimage == (unsigned char *)NULL){ - fprintf(stderr, "ERROR : morph_TF_map : malloc : cimage\n"); - return(-660); - } + cimage = (unsigned char *)g_malloc(mw * mh); - mimage = (unsigned char *)malloc(mw*mh); - if(mimage == (unsigned char *)NULL){ - free(cimage); - fprintf(stderr, "ERROR : morph_TF_map : malloc : mimage\n"); - return(-661); - } + mimage = (unsigned char *)g_malloc(mw * mh); cptr = cimage; mptr = tfmap; @@ -710,8 +678,8 @@ int morph_TF_map(int *tfmap, const int mw, const int mh, *mptr++ = *cptr++; } - free(cimage); - free(mimage); + g_free(cimage); + g_free(mimage); return(0); } @@ -746,20 +714,16 @@ int pixelize_map(int **omap, const int iw, const int ih, ASSERT_SIZE_MUL(iw, ih); ASSERT_SIZE_MUL(iw * ih, sizeof(int)); - pmap = (int *)malloc(iw*ih*sizeof(int)); - if(pmap == (int *)NULL){ - fprintf(stderr, "ERROR : pixelize_map : malloc : pmap\n"); - return(-590); - } + pmap = (int *)g_malloc(iw * ih * sizeof(int)); if((ret = block_offsets(&blkoffs, &bw, &bh, iw, ih, 0, blocksize))){ - free(pmap); + g_free(pmap); return(ret); } if((bw != mw) || (bh != mh)){ - free(blkoffs); - free(pmap); + g_free(blkoffs); + g_free(pmap); fprintf(stderr, "ERROR : pixelize_map : block dimensions do not match\n"); return(-591); @@ -777,7 +741,7 @@ int pixelize_map(int **omap, const int iw, const int ih, } /* Deallocate working memory. */ - free(blkoffs); + g_free(blkoffs); /* Assign pixelized map to output pointer. */ *omap = pmap; @@ -910,12 +874,7 @@ int gen_high_curve_map(int **ohcmap, int *direction_map, /* Allocate High Curvature Map. */ ASSERT_SIZE_MUL(mapsize, sizeof(int)); - high_curve_map = (int *)malloc(mapsize * sizeof(int)); - if(high_curve_map == (int *)NULL){ - fprintf(stderr, - "ERROR: gen_high_curve_map : malloc : high_curve_map\n"); - return(-530); - } + high_curve_map = (int *)g_malloc(mapsize * sizeof(int)); /* Initialize High Curvature Map to FALSE (0). */ memset(high_curve_map, 0, mapsize*sizeof(int)); diff --git a/libfprint/nbis/mindtct/minutia.c b/libfprint/nbis/mindtct/minutia.c index ca0d551c..0b29aa00 100644 --- a/libfprint/nbis/mindtct/minutia.c +++ b/libfprint/nbis/mindtct/minutia.c @@ -118,16 +118,8 @@ int alloc_minutiae(MINUTIAE **ominutiae, const int DEFAULT_BOZORTH_MINUTIAE) { MINUTIAE *minutiae; - minutiae = (MINUTIAE *)malloc(sizeof(MINUTIAE)); - if(minutiae == (MINUTIAE *)NULL){ - fprintf(stderr, "ERROR : alloc_minutiae : malloc : minutiae\n"); - exit(-430); - } - minutiae->list = (MINUTIA **)malloc(DEFAULT_BOZORTH_MINUTIAE * sizeof(MINUTIA *)); - if(minutiae->list == (MINUTIA **)NULL){ - fprintf(stderr, "ERROR : alloc_minutiae : malloc : minutiae->list\n"); - exit(-431); - } + minutiae = (MINUTIAE *)g_malloc(sizeof(MINUTIAE)); + minutiae->list = (MINUTIA **)g_malloc(DEFAULT_BOZORTH_MINUTIAE * sizeof(MINUTIA *)); minutiae->alloc = DEFAULT_BOZORTH_MINUTIAE; minutiae->num = 0; @@ -154,12 +146,8 @@ int alloc_minutiae(MINUTIAE **ominutiae, const int DEFAULT_BOZORTH_MINUTIAE) int realloc_minutiae(MINUTIAE *minutiae, const int incr_minutiae) { minutiae->alloc += incr_minutiae; - minutiae->list = (MINUTIA **)realloc(minutiae->list, - minutiae->alloc * sizeof(MINUTIA *)); - if(minutiae->list == (MINUTIA **)NULL){ - fprintf(stderr, "ERROR : realloc_minutiae : realloc : minutiae->list\n"); - exit(-432); - } + minutiae->list = (MINUTIA **)g_realloc(minutiae->list, + minutiae->alloc * sizeof(MINUTIA *)); return(0); } @@ -227,37 +215,37 @@ int detect_minutiae_V2(MINUTIAE *minutiae, if((ret = pixelize_map(&plow_flow_map, iw, ih, low_flow_map, mw, mh, lfsparms->blocksize))){ - free(pdirection_map); + g_free(pdirection_map); return(ret); } if((ret = pixelize_map(&phigh_curve_map, iw, ih, high_curve_map, mw, mh, lfsparms->blocksize))){ - free(pdirection_map); - free(plow_flow_map); + g_free(pdirection_map); + g_free(plow_flow_map); return(ret); } if((ret = scan4minutiae_horizontally_V2(minutiae, bdata, iw, ih, pdirection_map, plow_flow_map, phigh_curve_map, lfsparms))){ - free(pdirection_map); - free(plow_flow_map); - free(phigh_curve_map); + g_free(pdirection_map); + g_free(plow_flow_map); + g_free(phigh_curve_map); return(ret); } if((ret = scan4minutiae_vertically_V2(minutiae, bdata, iw, ih, pdirection_map, plow_flow_map, phigh_curve_map, lfsparms))){ - free(pdirection_map); - free(plow_flow_map); - free(phigh_curve_map); + g_free(pdirection_map); + g_free(plow_flow_map); + g_free(phigh_curve_map); return(ret); } /* Deallocate working memories. */ - free(pdirection_map); - free(plow_flow_map); - free(phigh_curve_map); + g_free(pdirection_map); + g_free(plow_flow_map); + g_free(phigh_curve_map); /* Return normally. */ return(0); @@ -550,11 +538,7 @@ int sort_minutiae_y_x(MINUTIAE *minutiae, const int iw, const int ih) /* Allocate a list of integers to hold 1-D image pixel offsets */ /* for each of the 2-D minutia coordinate points. */ - ranks = (int *)malloc(minutiae->num * sizeof(int)); - if(ranks == (int *)NULL){ - fprintf(stderr, "ERROR : sort_minutiae_y_x : malloc : ranks\n"); - return(-310); - } + ranks = (int *)g_malloc(minutiae->num * sizeof(int)); /* Compute 1-D image pixel offsets form 2-D minutia coordinate points. */ for(i = 0; i < minutiae->num; i++) @@ -562,31 +546,25 @@ int sort_minutiae_y_x(MINUTIAE *minutiae, const int iw, const int ih) /* Get sorted order of minutiae. */ if((ret = sort_indices_int_inc(&order, ranks, minutiae->num))){ - free(ranks); + g_free(ranks); return(ret); } /* Allocate new MINUTIA list to hold sorted minutiae. */ - newlist = (MINUTIA **)malloc(minutiae->num * sizeof(MINUTIA *)); - if(newlist == (MINUTIA **)NULL){ - free(ranks); - free(order); - fprintf(stderr, "ERROR : sort_minutiae_y_x : malloc : newlist\n"); - return(-311); - } + newlist = (MINUTIA **)g_malloc(minutiae->num * sizeof(MINUTIA *)); /* Put minutia into sorted order in new list. */ for(i = 0; i < minutiae->num; i++) newlist[i] = minutiae->list[order[i]]; /* Deallocate non-sorted list of minutia pointers. */ - free(minutiae->list); + g_free(minutiae->list); /* Assign new sorted list of minutia to minutiae list. */ minutiae->list = newlist; /* Free the working memories supporting the sort. */ - free(order); - free(ranks); + g_free(order); + g_free(ranks); /* Return normally. */ return(0); @@ -615,11 +593,7 @@ int sort_minutiae_x_y(MINUTIAE *minutiae, const int iw, const int ih) /* Allocate a list of integers to hold 1-D image pixel offsets */ /* for each of the 2-D minutia coordinate points. */ - ranks = (int *)malloc(minutiae->num * sizeof(int)); - if(ranks == (int *)NULL){ - fprintf(stderr, "ERROR : sort_minutiae_x_y : malloc : ranks\n"); - return(-440); - } + ranks = (int *)g_malloc(minutiae->num * sizeof(int)); /* Compute 1-D image pixel offsets form 2-D minutia coordinate points. */ for(i = 0; i < minutiae->num; i++) @@ -627,31 +601,25 @@ int sort_minutiae_x_y(MINUTIAE *minutiae, const int iw, const int ih) /* Get sorted order of minutiae. */ if((ret = sort_indices_int_inc(&order, ranks, minutiae->num))){ - free(ranks); + g_free(ranks); return(ret); } /* Allocate new MINUTIA list to hold sorted minutiae. */ - newlist = (MINUTIA **)malloc(minutiae->num * sizeof(MINUTIA *)); - if(newlist == (MINUTIA **)NULL){ - free(ranks); - free(order); - fprintf(stderr, "ERROR : sort_minutiae_x_y : malloc : newlist\n"); - return(-441); - } + newlist = (MINUTIA **)g_malloc(minutiae->num * sizeof(MINUTIA *)); /* Put minutia into sorted order in new list. */ for(i = 0; i < minutiae->num; i++) newlist[i] = minutiae->list[order[i]]; /* Deallocate non-sorted list of minutia pointers. */ - free(minutiae->list); + g_free(minutiae->list); /* Assign new sorted list of minutia to minutiae list. */ minutiae->list = newlist; /* Free the working memories supporting the sort. */ - free(order); - free(ranks); + g_free(order); + g_free(ranks); /* Return normally. */ return(0); @@ -764,12 +732,7 @@ int create_minutia(MINUTIA **ominutia, const int x_loc, const int y_loc, MINUTIA *minutia; /* Allocate a minutia structure. */ - minutia = (MINUTIA *)malloc(sizeof(MINUTIA)); - /* If allocation error... */ - if(minutia == (MINUTIA *)NULL){ - fprintf(stderr, "ERROR : create_minutia : malloc : minutia\n"); - return(-230); - } + minutia = (MINUTIA *)g_malloc(sizeof(MINUTIA)); /* Assign minutia structure attributes. */ minutia->x = x_loc; @@ -807,10 +770,10 @@ void free_minutiae(MINUTIAE *minutiae) for(i = 0; i < minutiae->num; i++) free_minutia(minutiae->list[i]); /* Deallocate list of minutia pointers. */ - free(minutiae->list); + g_free(minutiae->list); /* Deallocate the list structure. */ - free(minutiae); + g_free(minutiae); } /************************************************************************* @@ -825,12 +788,12 @@ void free_minutia(MINUTIA *minutia) { /* Deallocate sublists. */ if(minutia->nbrs != (int *)NULL) - free(minutia->nbrs); + g_free(minutia->nbrs); if(minutia->ridge_counts != (int *)NULL) - free(minutia->ridge_counts); + g_free(minutia->ridge_counts); /* Deallocate the minutia structure. */ - free(minutia); + g_free(minutia); } /************************************************************************* diff --git a/libfprint/nbis/mindtct/quality.c b/libfprint/nbis/mindtct/quality.c index 94e9b63a..399c4776 100644 --- a/libfprint/nbis/mindtct/quality.c +++ b/libfprint/nbis/mindtct/quality.c @@ -118,11 +118,7 @@ int gen_quality_map(int **oqmap, int *direction_map, int *low_contrast_map, ASSERT_SIZE_MUL(map_w, map_h); ASSERT_SIZE_MUL(map_w * map_h, sizeof(int)); - QualMap = (int *)malloc(map_w * map_h * sizeof(int)); - if(QualMap == (int *)NULL){ - fprintf(stderr, "ERROR : gen_quality_map : malloc : QualMap\n"); - return(-2); - } + QualMap = (int *)g_malloc(map_w * map_h * sizeof(int)); /* Foreach row of blocks in maps ... */ for(thisY=0; thisYreliability = reliability; } /* NEW 05-08-2002 */ - free(pquality_map); + g_free(pquality_map); /* Return normally. */ return(0); diff --git a/libfprint/nbis/mindtct/remove.c b/libfprint/nbis/mindtct/remove.c index faa6607e..af5ab7d0 100644 --- a/libfprint/nbis/mindtct/remove.c +++ b/libfprint/nbis/mindtct/remove.c @@ -380,7 +380,7 @@ int remove_hooks(MINUTIAE *minutiae, if((deltadir = closest_dir_dist(minutia1->direction, minutia2->direction, full_ndirs)) == INVALID_DIR){ - free(to_remove); + g_free(to_remove); fprintf(stderr, "ERROR : remove_hooks : INVALID direction\n"); return(-641); @@ -424,7 +424,7 @@ int remove_hooks(MINUTIAE *minutiae, } /* If system error occurred during hook test ... */ else if (ret < 0){ - free(to_remove); + g_free(to_remove); return(ret); } /* Otherwise, no hook found, so skip to next */ @@ -474,14 +474,14 @@ int remove_hooks(MINUTIAE *minutiae, if(to_remove[i]){ /* Remove the minutia from the minutiae list. */ if((ret = remove_minutia(i, minutiae))){ - free(to_remove); + g_free(to_remove); return(ret); } } } /* Deallocate flag list. */ - free(to_remove); + g_free(to_remove); /* Return normally. */ return(0); @@ -641,7 +641,7 @@ int remove_islands_and_lakes(MINUTIAE *minutiae, if((deltadir = closest_dir_dist(minutia1->direction, minutia2->direction, full_ndirs)) == INVALID_DIR){ - free(to_remove); + g_free(to_remove); fprintf(stderr, "ERROR : remove_islands_and_lakes : INVALID direction\n"); return(-611); @@ -673,7 +673,7 @@ int remove_islands_and_lakes(MINUTIAE *minutiae, bdata, iw, ih))){ free_contour(loop_x, loop_y, loop_ex, loop_ey); - free(to_remove); + g_free(to_remove); return(ret); } /* Set to remove first minutia. */ @@ -696,7 +696,7 @@ int remove_islands_and_lakes(MINUTIAE *minutiae, } /* If ERROR while looking for island/lake ... */ else if (ret < 0){ - free(to_remove); + g_free(to_remove); return(ret); } else @@ -741,14 +741,14 @@ int remove_islands_and_lakes(MINUTIAE *minutiae, if(to_remove[i]){ /* Remove the minutia from the minutiae list. */ if((ret = remove_minutia(i, minutiae))){ - free(to_remove); + g_free(to_remove); return(ret); } } } /* Deallocate flag list. */ - free(to_remove); + g_free(to_remove); /* Return normally. */ return(0); @@ -950,8 +950,8 @@ int remove_malformations(MINUTIAE *minutiae, print2log("%d,%d RMMAL3 (%f)\n", minutia->x, minutia->y, ratio); if((ret = remove_minutia(i, minutiae))){ - free(x_list); - free(y_list); + g_free(x_list); + g_free(y_list); /* If system error, return error code. */ return(ret); } @@ -961,8 +961,8 @@ int remove_malformations(MINUTIAE *minutiae, } } - free(x_list); - free(y_list); + g_free(x_list); + g_free(y_list); } } @@ -1447,7 +1447,7 @@ int remove_overlaps(MINUTIAE *minutiae, if((deltadir = closest_dir_dist(minutia1->direction, minutia2->direction, full_ndirs)) == INVALID_DIR){ - free(to_remove); + g_free(to_remove); fprintf(stderr, "ERROR : remove_overlaps : INVALID direction\n"); return(-651); @@ -1546,14 +1546,14 @@ int remove_overlaps(MINUTIAE *minutiae, if(to_remove[i]){ /* Remove the minutia from the minutiae list. */ if((ret = remove_minutia(i, minutiae))){ - free(to_remove); + g_free(to_remove); return(ret); } } } /* Deallocate flag list. */ - free(to_remove); + g_free(to_remove); /* Return normally. */ return(0); @@ -2034,12 +2034,7 @@ int remove_or_adjust_side_minutiae_V2(MINUTIAE *minutiae, /* Allocate working memory for holding rotated y-coord of a */ /* minutia's contour. */ - rot_y = (int *)malloc(((lfsparms->side_half_contour<<1)+1) * sizeof(int)); - if(rot_y == (int *)NULL){ - fprintf(stderr, - "ERROR : remove_or_adjust_side_minutiae_V2 : malloc : rot_y\n"); - return(-630); - } + rot_y = (int *)g_malloc(((lfsparms->side_half_contour << 1) + 1) * sizeof(int)); /* Compute factor for converting integer directions to radians. */ pi_factor = M_PI / (double)lfsparms->num_directions; @@ -2061,7 +2056,7 @@ int remove_or_adjust_side_minutiae_V2(MINUTIAE *minutiae, /* If system error occurred ... */ if(ret < 0){ /* Deallocate working memory. */ - free(rot_y); + g_free(rot_y); /* Return error code. */ return(ret); } @@ -2077,7 +2072,7 @@ int remove_or_adjust_side_minutiae_V2(MINUTIAE *minutiae, /* Remove minutia from list. */ if((ret = remove_minutia(i, minutiae))){ /* Deallocate working memory. */ - free(rot_y); + g_free(rot_y); /* Return error code. */ return(ret); } @@ -2130,7 +2125,7 @@ int remove_or_adjust_side_minutiae_V2(MINUTIAE *minutiae, &minmax_alloc, &minmax_num, rot_y, ncontour))){ /* If system error, then deallocate working memories. */ - free(rot_y); + g_free(rot_y); free_contour(contour_x, contour_y, contour_ex, contour_ey); /* Return error code. */ return(ret); @@ -2156,12 +2151,12 @@ int remove_or_adjust_side_minutiae_V2(MINUTIAE *minutiae, /* Remove minutia from list. */ if((ret = remove_minutia(i, minutiae))){ /* Deallocate working memory. */ - free(rot_y); + g_free(rot_y); free_contour(contour_x, contour_y, contour_ex, contour_ey); if(minmax_alloc > 0){ - free(minmax_val); - free(minmax_type); - free(minmax_i); + g_free(minmax_val); + g_free(minmax_type); + g_free(minmax_i); } /* Return error code. */ return(ret); @@ -2202,12 +2197,12 @@ int remove_or_adjust_side_minutiae_V2(MINUTIAE *minutiae, /* Remove minutia from list. */ if((ret = remove_minutia(i, minutiae))){ /* Deallocate working memory. */ - free(rot_y); + g_free(rot_y); free_contour(contour_x, contour_y, contour_ex, contour_ey); if(minmax_alloc > 0){ - free(minmax_val); - free(minmax_type); - free(minmax_i); + g_free(minmax_val); + g_free(minmax_type); + g_free(minmax_i); } /* Return error code. */ return(ret); @@ -2231,12 +2226,12 @@ int remove_or_adjust_side_minutiae_V2(MINUTIAE *minutiae, /* Remove minutia from list. */ if((ret = remove_minutia(i, minutiae))){ /* If system error, then deallocate working memories. */ - free(rot_y); + g_free(rot_y); free_contour(contour_x, contour_y, contour_ex, contour_ey); if(minmax_alloc > 0){ - free(minmax_val); - free(minmax_type); - free(minmax_i); + g_free(minmax_val); + g_free(minmax_type); + g_free(minmax_i); } /* Return error code. */ return(ret); @@ -2248,15 +2243,15 @@ int remove_or_adjust_side_minutiae_V2(MINUTIAE *minutiae, /* Deallocate contour and min/max buffers. */ free_contour(contour_x, contour_y, contour_ex, contour_ey); if(minmax_alloc > 0){ - free(minmax_val); - free(minmax_type); - free(minmax_i); + g_free(minmax_val); + g_free(minmax_type); + g_free(minmax_i); } } /* End else contour extracted. */ } /* End while not end of minutiae list. */ /* Deallocate working memory. */ - free(rot_y); + g_free(rot_y); /* Return normally. */ return(0); diff --git a/libfprint/nbis/mindtct/ridges.c b/libfprint/nbis/mindtct/ridges.c index 8f69fb24..f0d9cd3c 100644 --- a/libfprint/nbis/mindtct/ridges.c +++ b/libfprint/nbis/mindtct/ridges.c @@ -152,7 +152,7 @@ int count_minutia_ridges(const int first, MINUTIAE *minutiae, if((ret = find_neighbors(&nbr_list, &nnbrs, lfsparms->max_nbrs, first, minutiae))){ if (nbr_list != NULL) - free(nbr_list); + g_free(nbr_list); return(ret); } @@ -167,18 +167,13 @@ int count_minutia_ridges(const int first, MINUTIAE *minutiae, /* Sort neighbors on delta dirs. */ if((ret = sort_neighbors(nbr_list, nnbrs, first, minutiae))){ - free(nbr_list); + g_free(nbr_list); return(ret); } /* Count ridges between first and neighbors. */ /* List of ridge counts, one for each neighbor stored. */ - nbr_nridges = (int *)malloc(nnbrs * sizeof(int)); - if(nbr_nridges == (int *)NULL){ - free(nbr_list); - fprintf(stderr, "ERROR : count_minutia_ridges : malloc : nbr_nridges\n"); - return(-450); - } + nbr_nridges = (int *)g_malloc(nnbrs * sizeof(int)); /* Foreach neighbor found and sorted in list ... */ for(i = 0; i < nnbrs; i++){ @@ -187,8 +182,8 @@ int count_minutia_ridges(const int first, MINUTIAE *minutiae, /* If system error ... */ if(ret < 0){ /* Deallocate working memories. */ - free(nbr_list); - free(nbr_nridges); + g_free(nbr_list); + g_free(nbr_nridges); /* Return error code. */ return(ret); } @@ -235,21 +230,11 @@ int find_neighbors(int **onbr_list, int *onnbrs, const int max_nbrs, double *nbr_sqr_dists, xdist, xdist2; /* Allocate list of neighbor minutiae indices. */ - nbr_list = (int *)malloc(max_nbrs * sizeof(int)); - if(nbr_list == (int *)NULL){ - fprintf(stderr, "ERROR : find_neighbors : malloc : nbr_list\n"); - return(-460); - } + nbr_list = (int *)g_malloc(max_nbrs * sizeof(int)); /* Allocate list of squared euclidean distances between neighbors */ /* and current primary minutia point. */ - nbr_sqr_dists = (double *)malloc(max_nbrs * sizeof(double)); - if(nbr_sqr_dists == (double *)NULL){ - free(nbr_list); - fprintf(stderr, - "ERROR : find_neighbors : malloc : nbr_sqr_dists\n"); - return(-461); - } + nbr_sqr_dists = (double *)g_malloc(max_nbrs * sizeof(double)); /* Initialize number of stored neighbors to 0. */ nnbrs = 0; @@ -280,8 +265,8 @@ int find_neighbors(int **onbr_list, int *onnbrs, const int max_nbrs, /* Append or insert the new neighbor into the neighbor lists. */ if((ret = update_nbr_dists(nbr_list, nbr_sqr_dists, &nnbrs, max_nbrs, first, second, minutiae))){ - free(nbr_sqr_dists); - free(nbr_list); + g_free(nbr_sqr_dists); + g_free(nbr_list); return(ret); } } @@ -297,12 +282,12 @@ int find_neighbors(int **onbr_list, int *onnbrs, const int max_nbrs, } /* Deallocate working memory. */ - free(nbr_sqr_dists); + g_free(nbr_sqr_dists); /* If no neighbors found ... */ if(nnbrs == 0){ /* Deallocate the neighbor list. */ - free(nbr_list); + g_free(nbr_list); *onnbrs = 0; } /* Otherwise, assign neighbors to output pointer. */ @@ -497,11 +482,7 @@ int sort_neighbors(int *nbr_list, const int nnbrs, const int first, /* List of angles of lines joining the current primary to each */ /* of the secondary neighbors. */ - join_thetas = (double *)malloc(nnbrs * sizeof(double)); - if(join_thetas == (double *)NULL){ - fprintf(stderr, "ERROR : sort_neighbors : malloc : join_thetas\n"); - return(-490); - } + join_thetas = (double *)g_malloc(nnbrs * sizeof(double)); for(i = 0; i < nnbrs; i++){ /* Compute angle to line connecting the 2 points. */ @@ -523,7 +504,7 @@ int sort_neighbors(int *nbr_list, const int nnbrs, const int first, bubble_sort_double_inc_2(join_thetas, nbr_list, nnbrs); /* Deallocate the list of angles. */ - free(join_thetas); + g_free(join_thetas); /* Return normally. */ return(0); @@ -576,8 +557,8 @@ int ridge_count(const int first, const int second, MINUTIAE *minutiae, /* It there are no points on the line trajectory, then no ridges */ /* to count (this should not happen, but just in case) ... */ if(num == 0){ - free(xlist); - free(ylist); + g_free(xlist); + g_free(ylist); return(0); } @@ -597,8 +578,8 @@ int ridge_count(const int first, const int second, MINUTIAE *minutiae, /* If opposite pixel not found ... then no ridges to count */ if(!found){ - free(xlist); - free(ylist); + g_free(xlist); + g_free(ylist); return(0); } @@ -613,8 +594,8 @@ int ridge_count(const int first, const int second, MINUTIAE *minutiae, /* If 0-to-1 transition not found ... */ if(!find_transition(&i, 0, 1, xlist, ylist, num, bdata, iw, ih)){ /* Then we are done looking for ridges. */ - free(xlist); - free(ylist); + g_free(xlist); + g_free(ylist); print2log("\n"); @@ -630,8 +611,8 @@ int ridge_count(const int first, const int second, MINUTIAE *minutiae, /* If 1-to-0 transition not found ... */ if(!find_transition(&i, 1, 0, xlist, ylist, num, bdata, iw, ih)){ /* Then we are done looking for ridges. */ - free(xlist); - free(ylist); + g_free(xlist); + g_free(ylist); print2log("\n"); @@ -657,8 +638,8 @@ int ridge_count(const int first, const int second, MINUTIAE *minutiae, /* If system error ... */ if(ret < 0){ - free(xlist); - free(ylist); + g_free(xlist); + g_free(ylist); /* Return the error code. */ return(ret); } @@ -677,8 +658,8 @@ int ridge_count(const int first, const int second, MINUTIAE *minutiae, } /* Deallocate working memories. */ - free(xlist); - free(ylist); + g_free(xlist); + g_free(ylist); print2log("\n"); diff --git a/libfprint/nbis/mindtct/shape.c b/libfprint/nbis/mindtct/shape.c index 5f9e7bcb..c399f363 100644 --- a/libfprint/nbis/mindtct/shape.c +++ b/libfprint/nbis/mindtct/shape.c @@ -86,7 +86,7 @@ int alloc_shape(SHAPE **oshape, const int xmin, const int ymin, { SHAPE *shape; int alloc_rows, alloc_pts; - int i, j, y; + int i, y; /* Compute allocation parameters. */ /* First, compute the number of scanlines spanned by the shape. */ @@ -98,23 +98,11 @@ int alloc_shape(SHAPE **oshape, const int xmin, const int ymin, alloc_pts = xmax - xmin + 1; /* Allocate the shape structure. */ - shape = (SHAPE *)malloc(sizeof(SHAPE)); - /* If there is an allocation error... */ - if(shape == (SHAPE *)NULL){ - fprintf(stderr, "ERROR : alloc_shape : malloc : shape\n"); - return(-250); - } + shape = (SHAPE *)g_malloc(sizeof(SHAPE)); /* Allocate the list of row pointers. We now this number will fit */ /* the shape exactly. */ - shape->rows = (ROW **)malloc(alloc_rows * sizeof(ROW *)); - /* If there is an allocation error... */ - if(shape->rows == (ROW **)NULL){ - /* Deallocate memory alloated by this routine to this point. */ - free(shape); - fprintf(stderr, "ERROR : alloc_shape : malloc : shape->rows\n"); - return(-251); - } + shape->rows = (ROW **)g_malloc(alloc_rows * sizeof(ROW *)); /* Initialize the shape structure's attributes. */ shape->ymin = ymin; @@ -128,36 +116,10 @@ int alloc_shape(SHAPE **oshape, const int xmin, const int ymin, for(i = 0, y = ymin; i < alloc_rows; i++, y++){ /* Allocate a row structure and store it in its respective position */ /* in the shape structure's list of row pointers. */ - shape->rows[i] = (ROW *)malloc(sizeof(ROW)); - /* If there is an allocation error... */ - if(shape->rows[i] == (ROW *)NULL){ - /* Deallocate memory alloated by this routine to this point. */ - for(j = 0; j < i; j++){ - free(shape->rows[j]->xs); - free(shape->rows[j]); - } - free(shape->rows); - free(shape); - fprintf(stderr, "ERROR : alloc_shape : malloc : shape->rows[i]\n"); - return(-252); - } + shape->rows[i] = (ROW *)g_malloc(sizeof(ROW)); /* Allocate the current rows list of x-coords. */ - shape->rows[i]->xs = (int *)malloc(alloc_pts * sizeof(int)); - /* If there is an allocation error... */ - if(shape->rows[i]->xs == (int *)NULL){ - /* Deallocate memory alloated by this routine to this point. */ - for(j = 0; j < i; j++){ - free(shape->rows[j]->xs); - free(shape->rows[j]); - } - free(shape->rows[i]); - free(shape->rows); - free(shape); - fprintf(stderr, - "ERROR : alloc_shape : malloc : shape->rows[i]->xs\n"); - return(-253); - } + shape->rows[i]->xs = (int *)g_malloc(alloc_pts * sizeof(int)); /* Initialize the current row structure's attributes. */ shape->rows[i]->y = y; @@ -188,15 +150,15 @@ void free_shape(SHAPE *shape) /* Foreach allocated row in the shape ... */ for(i = 0; i < shape->alloc; i++){ /* Deallocate the current row's list of x-coords. */ - free(shape->rows[i]->xs); + g_free(shape->rows[i]->xs); /* Deallocate the current row structure. */ - free(shape->rows[i]); + g_free(shape->rows[i]); } /* Deallocate the list of row pointers. */ - free(shape->rows); + g_free(shape->rows); /* Deallocate the shape structure. */ - free(shape); + g_free(shape); } /************************************************************************* @@ -260,7 +222,7 @@ int shape_from_contour(SHAPE **oshape, const int *contour_x, if(row->npts >= row->alloc){ /* This should never happen becuase we have allocated */ /* based on shape bounding limits. */ - free(shape); + g_free(shape); fprintf(stderr, "ERROR : shape_from_contour : row overflow\n"); return(-260); diff --git a/libfprint/nbis/mindtct/sort.c b/libfprint/nbis/mindtct/sort.c index 9080ce0d..5343639f 100644 --- a/libfprint/nbis/mindtct/sort.c +++ b/libfprint/nbis/mindtct/sort.c @@ -89,11 +89,7 @@ int sort_indices_int_inc(int **optr, int *ranks, const int num) int i; /* Allocate list of sequential indices. */ - order = (int *)malloc(num * sizeof(int)); - if(order == (int *)NULL){ - fprintf(stderr, "ERROR : sort_indices_int_inc : malloc : order\n"); - return(-390); - } + order = (int *)g_malloc(num * sizeof(int)); /* Initialize list of sequential indices. */ for(i = 0; i < num; i++) order[i] = i; diff --git a/libfprint/nbis/mindtct/util.c b/libfprint/nbis/mindtct/util.c index 1662e629..5ae11990 100644 --- a/libfprint/nbis/mindtct/util.c +++ b/libfprint/nbis/mindtct/util.c @@ -178,24 +178,9 @@ int minmaxs(int **ominmax_val, int **ominmax_type, int **ominmax_i, /* min or max. */ minmax_alloc = num - 2; /* Allocate the buffers. */ - minmax_val = (int *)malloc(minmax_alloc * sizeof(int)); - if(minmax_val == (int *)NULL){ - fprintf(stderr, "ERROR : minmaxs : malloc : minmax_val\n"); - return(-290); - } - minmax_type = (int *)malloc(minmax_alloc * sizeof(int)); - if(minmax_type == (int *)NULL){ - free(minmax_val); - fprintf(stderr, "ERROR : minmaxs : malloc : minmax_type\n"); - return(-291); - } - minmax_i = (int *)malloc(minmax_alloc * sizeof(int)); - if(minmax_i == (int *)NULL){ - free(minmax_val); - free(minmax_type); - fprintf(stderr, "ERROR : minmaxs : malloc : minmax_i\n"); - return(-292); - } + minmax_val = (int *)g_malloc(minmax_alloc * sizeof(int)); + minmax_type = (int *)g_malloc(minmax_alloc * sizeof(int)); + minmax_i = (int *)g_malloc(minmax_alloc * sizeof(int)); /* Initialize number of min/max to 0. */ minmax_num = 0; diff --git a/libfprint/nbis/update-from-nbis.sh b/libfprint/nbis/update-from-nbis.sh index bd3a59b9..c8cde80b 100755 --- a/libfprint/nbis/update-from-nbis.sh +++ b/libfprint/nbis/update-from-nbis.sh @@ -179,3 +179,9 @@ sed -i 's/[ \t]*$//' `find -name "*.[ch]"` # Remove usebsd.h sed -i '/usebsd.h/d' `find -name "*.[ch]"` +# Use GLib memory management +spatch --sp-file glib-memory.cocci --dir . --in-place + +# The above leaves an unused variable around, triggering a warning +# remove it. +patch -p0 < glib-mem-warning.patch \ No newline at end of file diff --git a/meson.build b/meson.build index b7f7f315..8d06d450 100644 --- a/meson.build +++ b/meson.build @@ -1,12 +1,14 @@ project('libfprint', [ 'c', 'cpp' ], - version: '1.0', + version: '1.90.0', license: 'LGPLv2.1+', default_options: [ 'buildtype=debugoptimized', 'warning_level=1', 'c_std=c99', ], - meson_version: '>= 0.45.0') + meson_version: '>= 0.46.0') + +gnome = import('gnome') add_project_arguments([ '-D_GNU_SOURCE' ], language: 'c') add_project_arguments([ '-DG_LOG_DOMAIN="libfprint"' ], language: 'c') @@ -19,9 +21,9 @@ host_system = host_machine.system() common_cflags = cc.get_supported_arguments([ '-fgnu89-inline', - '-fvisibility=hidden', '-std=gnu99', '-Wall', + '-Wtype-limits', '-Wundef', '-Wunused', '-Wstrict-prototypes', @@ -35,31 +37,39 @@ common_cflags = cc.get_supported_arguments([ # maintaining compatibility with the previous libtool versioning # current = binary - interface # revision = interface -soversion = 0 +soversion = 2 current = 0 revision = 0 libversion = '@0@.@1@.@2@'.format(soversion, current, revision) # Dependencies glib_dep = dependency('glib-2.0', version: '>= 2.50') -libusb_dep = dependency('libusb-1.0', version: '>= 0.9.1') +gio_dep = dependency('gio-unix-2.0', version: '>= 2.44.0') +gusb_dep = dependency('gusb', version: '>= 0.3.0') mathlib_dep = cc.find_library('m', required: false) # Drivers drivers = get_option('drivers').split(',') -all_drivers = [ 'upekts', 'upektc', 'upeksonly', 'vcom5s', 'uru4000', 'aes1610', 'aes1660', 'aes2501', 'aes2550', 'aes2660', 'aes3500', 'aes4000', 'vfs101', 'vfs301', 'vfs5011', 'upektc_img', 'etes603', 'vfs0050', 'elan' ] -primitive_drivers = [ 'upekts' ] +virtual_drivers = [ 'virtual_image' ] +default_drivers = [ 'upektc_img', 'vfs5011', 'aes3500', 'aes4000', 'aes1610', 'aes1660', 'aes2660', 'aes2501', 'aes2550', 'vfs101', 'vfs301', 'vfs0050', 'etes603', 'vcom5s', 'synaptics', 'elan', 'uru4000', 'upektc', 'upeksonly', 'upekts' ] + +all_drivers = default_drivers + virtual_drivers if drivers == [ 'all' ] drivers = all_drivers endif +if drivers == [ 'default' ] + drivers = default_drivers +endif + if drivers.length() == 0 or drivers[0] == '' error('Cannot build libfprint without drivers, please specify a valid value for the drivers option') endif nss_dep = dependency('', required: false) imaging_dep = dependency('', required: false) +libfprint_conf.set10('HAVE_PIXMAN', false) foreach driver: drivers if driver == 'uru4000' nss_dep = dependency('nss', required: false) @@ -72,27 +82,23 @@ foreach driver: drivers if not imaging_dep.found() error('pixman is required for imaging support') endif + + libfprint_conf.set10('HAVE_PIXMAN', true) endif if not all_drivers.contains(driver) error('Invalid driver \'' + driver + '\'') endif endforeach -# Export the drivers' structures to the core code -drivers_struct_list = '' -drivers_img_array = 'static struct fp_img_driver * const img_drivers[] = {\n' -drivers_primitive_array = 'static struct fp_driver * const primitive_drivers[] = {\n' +# Export the drivers' types to the core code +drivers_type_list = '#include \n' +drivers_type_func = 'void fpi_get_driver_types(GArray *drivers)\n{\n\tGType t;\n' foreach driver: drivers - if primitive_drivers.contains(driver) - drivers_struct_list += 'extern struct fp_driver ' + driver + '_driver;\n' - drivers_primitive_array += ' &' + driver + '_driver,\n' - else - drivers_struct_list += 'extern struct fp_img_driver ' + driver + '_driver;\n' - drivers_img_array += ' &' + driver + '_driver,\n' - endif + drivers_type_list += 'extern GType (fpi_device_' + driver + '_get_type) (void);\n' + drivers_type_func += ' t = fpi_device_' + driver + '_get_type(); g_array_append_val (drivers, t);\n' endforeach -drivers_img_array += '};' -drivers_primitive_array += '};' +drivers_type_list += '' +drivers_type_func += '};' root_inc = include_directories('.') @@ -105,14 +111,6 @@ if get_option('udev_rules') endif endif -if get_option('x11-examples') - x11_dep = cc.find_library('X11') - xv_dep = dependency('xv', required: false) - if not xv_dep.found() - error('XV is required for X11 examples') - endif -endif - if get_option('gtk-examples') gnome = import('gnome') @@ -122,7 +120,6 @@ if get_option('gtk-examples') endif endif -libfprint_conf.set('API_EXPORTED', '__attribute__((visibility("default")))') configure_file(output: 'config.h', configuration: libfprint_conf) subdir('libfprint') @@ -135,6 +132,11 @@ if get_option('gtk-examples') subdir('demo') endif +# The tests require introspeciton support to run +if get_option('introspection') + subdir('tests') +endif + pkgconfig = import('pkgconfig') pkgconfig.generate( name: 'libfprint', @@ -142,6 +144,6 @@ pkgconfig.generate( version: meson.project_version(), libraries: libfprint, subdirs: 'libfprint', - filebase: 'libfprint', + filebase: 'libfprint2', install_dir: join_paths(get_option('libdir'), 'pkgconfig'), ) diff --git a/meson_options.txt b/meson_options.txt index f40ebc31..746efdc7 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,7 +1,11 @@ option('drivers', - description: 'Drivers to integrate', + description: 'Drivers to integrate, "default" selects the default set, "all" selects all drivers', type: 'string', - value: 'all') + value: 'default') +option('introspection', + description: 'Build GObject Introspection repository', + type: 'boolean', + value: true) option('udev_rules', description: 'Whether to create a udev rules file', type: 'boolean', @@ -10,10 +14,6 @@ option('udev_rules_dir', description: 'Installation path for udev rules', type: 'string', value: 'auto') -option('x11-examples', - description: 'Whether to build X11 example applications', - type: 'boolean', - value: true) option('gtk-examples', description: 'Whether to build GTK+ example applications', type: 'boolean', diff --git a/scripts/uncrustify.cfg b/scripts/uncrustify.cfg new file mode 100644 index 00000000..c1fb82ec --- /dev/null +++ b/scripts/uncrustify.cfg @@ -0,0 +1,139 @@ +newlines lf + +input_tab_size 8 +output_tab_size 8 + +string_escape_char 92 +string_escape_char2 0 + +# indenting +indent_columns 2 +indent_with_tabs 0 +indent_align_string True +indent_brace 2 +indent_braces false +indent_braces_no_func True +indent_func_call_param false +indent_func_def_param false +indent_func_proto_param false +indent_switch_case 0 +indent_case_brace 2 +indent_paren_close 1 + +# spacing +sp_arith Add +sp_assign Add +sp_enum_assign Add +sp_bool Add +sp_compare Add +sp_inside_paren Remove +sp_inside_fparens Remove +sp_func_def_paren Force +sp_func_proto_paren Force +sp_paren_paren Remove +sp_balance_nested_parens False +sp_paren_brace Remove +sp_before_square Remove +sp_before_squares Remove +sp_inside_square Remove +sp_before_ptr_star Add +sp_between_ptr_star Remove +sp_after_comma Add +sp_before_comma Remove +sp_after_cast Add +sp_sizeof_paren Add +sp_not Remove +sp_inv Remove +sp_addr Remove +sp_member Remove +sp_deref Remove +sp_sign Remove +sp_incdec Remove +sp_attribute_paren remove +sp_macro Force +sp_func_call_paren Force +sp_func_call_user_paren Remove +set func_call_user _ N_ C_ g_autoptr g_auto +sp_brace_typedef add +sp_cond_colon add +sp_cond_question add +sp_defined_paren remove + +# alignment +align_keep_tabs False +align_with_tabs False +align_on_tabstop False +align_number_right False +align_func_params True +align_var_def_span 0 +align_var_def_amp_style 1 +align_var_def_colon true +align_enum_equ_span 0 +align_var_struct_span 2 +align_var_def_star_style 2 +align_var_def_amp_style 2 +align_typedef_span 2 +align_typedef_func 0 +align_typedef_star_style 2 +align_typedef_amp_style 2 + +# newlines +nl_assign_leave_one_liners True +nl_enum_leave_one_liners False +nl_func_leave_one_liners False +nl_if_leave_one_liners False +nl_end_of_file Add +nl_assign_brace Remove +nl_func_var_def_blk 1 +nl_fcall_brace Add +nl_enum_brace Remove +nl_struct_brace Force +nl_union_brace Force +nl_if_brace Force +nl_brace_else Force +nl_elseif_brace Force +nl_else_brace Add +nl_for_brace Force +nl_while_brace Force +nl_do_brace Force +nl_brace_while Force +nl_switch_brace Force +nl_before_case True +nl_after_case False +nl_func_type_name Force +nl_func_proto_type_name Remove +nl_func_paren Remove +nl_func_decl_start Remove +nl_func_decl_args Force +nl_func_decl_end Remove +nl_fdef_brace Force +nl_after_return False +nl_define_macro False +nl_create_if_one_liner False +nl_create_for_one_liner False +nl_create_while_one_liner False +nl_after_semicolon True +nl_multi_line_cond true + +# mod +# I'd like these to be remove, but that removes brackets in if { if { foo } }, which i dislike +# Not clear what to do about that... +mod_full_brace_for Remove +mod_full_brace_if Remove +mod_full_brace_if_chain True +mod_full_brace_while Remove +mod_full_brace_do Remove +mod_full_brace_nl 3 +mod_paren_on_return Remove + +# line splitting +#code_width = 78 +ls_for_split_full True +ls_func_split_full True + +# positioning +pos_bool Trail +pos_conditional Trail + +# custom keywords +set FOR udev_list_entry_foreach diff --git a/scripts/uncrustify.sh b/scripts/uncrustify.sh new file mode 100755 index 00000000..cb039069 --- /dev/null +++ b/scripts/uncrustify.sh @@ -0,0 +1,19 @@ +#!/bin/bash +SRCROOT=`git rev-parse --show-toplevel` +CFG="$SRCROOT/scripts/uncrustify.cfg" +echo "srcroot: $SRCROOT" + +case "$1" in + -c|--check) + OPTS="--check" + ;; + *) + OPTS="--replace --no-backup" + ;; +esac + +pushd "$SRCROOT" +uncrustify -c "$CFG" $OPTS `git ls-tree --name-only -r HEAD | grep -E '.*\.[ch]$' | grep -v nbis | grep -v fpi-byte | grep -v build/` +RES=$? +popd +exit $RES \ No newline at end of file diff --git a/tests/README-umockdev b/tests/README-umockdev new file mode 100644 index 00000000..cabbace1 --- /dev/null +++ b/tests/README-umockdev @@ -0,0 +1,24 @@ +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. \ No newline at end of file diff --git a/tests/capture.py b/tests/capture.py new file mode 100755 index 00000000..2ad9385c --- /dev/null +++ b/tests/capture.py @@ -0,0 +1,46 @@ +#!/usr/bin/python3 + +import gi +gi.require_version('FPrint', '2.0') +from gi.repository import FPrint, GLib +import cairo +import sys + +if len(sys.argv) != 2: + print("Please specify exactly one argument, the output location for the capture image") + sys.exit(1) + +ctx = GLib.main_context_default() + +c = FPrint.Context() +c.enumerate() +devices = c.get_devices() + +d = devices[0] + +d.open_sync() + +img = d.capture_sync(True) + +d.close_sync() + +width = img.get_width() +height = img.get_height() + +c_img = cairo.ImageSurface(cairo.FORMAT_RGB24, width, height) + +c_rowstride = c_img.get_stride() + +buf = img.get_data() +c_buf = c_img.get_data() + +for x in range(width): + for y in range(height): + c_buf[y * c_rowstride + x * 4 + 0] = buf[y * width + x] + c_buf[y * c_rowstride + x * 4 + 1] = buf[y * width + x] + c_buf[y * c_rowstride + x * 4 + 2] = buf[y * width + x] + # Byte 4 is don't care + +c_img.mark_dirty() +c_img.write_to_png(sys.argv[1]) + diff --git a/tests/meson.build b/tests/meson.build new file mode 100644 index 00000000..d02b05a6 --- /dev/null +++ b/tests/meson.build @@ -0,0 +1,49 @@ +envs = environment() +# Enable debug messages and abort on warnings +envs.set('G_DEBUG', 'fatal-warnings') +envs.set('G_MESSAGES_DEBUG', 'all') + +# Setup paths +envs.set('MESON_SOURCE_ROOT', meson.build_root()) +envs.prepend('GI_TYPELIB_PATH', join_paths(meson.build_root(), 'libfprint')) +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 +# random numbers rather than proper ones) +envs.set('FP_DEVICE_EMULATION', '1') + +envs.set('NO_AT_BRIDGE', '1') + +if get_option('introspection') + if 'virtual_image' in drivers + test( + 'virtual-image', + find_program('virtual-image.py'), + args: '--verbose', + env: envs, + depends: libfprint_typelib, + ) + endif + + if 'vfs5011' in drivers + test( + 'vfs5011', + find_program('umockdev-test.py'), + args: join_paths(meson.current_source_dir(), 'vfs5011'), + env: envs, + timeout: 10, + depends: libfprint_typelib, + ) + endif + + if 'synaptics' in drivers + test( + 'synaptics', + find_program('umockdev-test.py'), + args: join_paths(meson.current_source_dir(), 'synaptics'), + env: envs, + timeout: 10, + depends: libfprint_typelib, + ) + endif +endif diff --git a/tests/synaptics/custom-recorded.ioctl b/tests/synaptics/custom-recorded.ioctl new file mode 100644 index 00000000..f7edc72e --- /dev/null +++ b/tests/synaptics/custom-recorded.ioctl @@ -0,0 +1,129 @@ +@DEV /dev/bus/usb/001/070 +USBDEVFS_GET_CAPABILITIES 0 7D000000 +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 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 129 0 0 266 6 0 0000FE026000 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100 + 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 129 0 0 266 7 0 0000FE0255010C + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000 + 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 129 0 0 266 6 0 0000FE026000 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100 + 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 129 0 0 266 7 0 0000FE02550119 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000 + 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 129 0 0 266 6 0 0000FE026000 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 + 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 129 0 0 266 7 0 0000FE02550125 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000 + 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 129 0 0 266 6 0 0000FE026000 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 + 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 129 0 0 266 7 0 0000FE02550125 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000 + 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 129 0 0 266 6 0 0000FE026000 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 + 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 129 0 0 266 7 0 0000FE02550132 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000 + 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 129 0 0 266 6 0 0000FE026000 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 + 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 129 0 0 266 7 0 0000FE0255013E + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000 + 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 129 0 0 266 6 0 0000FE026000 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 + 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 129 0 0 266 7 0 0000FE0255013E + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000 + 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 129 0 0 266 6 0 0000FE026000 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 + 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 129 0 0 266 7 0 0000FE0255014B + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000 + 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 129 0 0 266 6 0 0000FE026000 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100 + 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 129 0 0 266 7 0 0000FE02550157 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000 + 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 129 0 0 266 6 0 0000FE026000 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100 + 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 129 0 0 266 7 0 0000FE02550164 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 37 0 0000FE02591F014650312D30303030303030302D302D30303030303030302D6E6F626F6479 + 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 129 0 0 266 6 0 0000FE046000 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 + USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100 + 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 129 0 0 266 39 0 0000FE0468214F2B014650312D30303030303030302D302D30303030303030302D6E6F626F6479 +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 1 0 0 36 36 0 A7FE05811F014650312D30303030303030302D302D30303030303030302D6E6F626F6479 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 37 0 0000FE05831F014650312D30303030303030302D302D30303030303030302D6E6F626F6479 diff --git a/tests/synaptics/custom.ioctl b/tests/synaptics/custom.ioctl new file mode 100644 index 00000000..370a8e07 --- /dev/null +++ b/tests/synaptics/custom.ioctl @@ -0,0 +1,186 @@ +@DEV /dev/bus/usb/001/070 +USBDEVFS_GET_CAPABILITIES 0 7D000000 +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 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 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 05000000000100 + USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 + 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 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 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 05000000000100 + USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 + 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 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 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 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 + 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 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 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 + 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 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 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 + 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 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 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 + 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 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 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 + 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 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 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 + 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 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 05000000000100 + USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 + 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 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 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 05000000000100 + USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 + 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 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 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 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 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 + 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 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 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 + diff --git a/tests/synaptics/custom.py b/tests/synaptics/custom.py new file mode 100755 index 00000000..60167997 --- /dev/null +++ b/tests/synaptics/custom.py @@ -0,0 +1,42 @@ +#!/usr/bin/python3 + +import gi +gi.require_version('FPrint', '2.0') +from gi.repository import FPrint, GLib + +ctx = GLib.main_context_default() + +c = FPrint.Context() +c.enumerate() +devices = c.get_devices() + +d = devices[0] + +assert d.get_driver() == "synaptics" + +d.open_sync() + +template = FPrint.Print.new(d) + +def enroll_progress(*args): + print('enroll progress: ' + str(args)) + +# List, enroll, list, verify, delete, list +print("enrolling") +p = d.enroll_sync(template, None, enroll_progress, None) +print("enroll done") + +print("listing") +stored = d.list_prints_sync() +print("listing done") +assert len(stored) == 1 +assert stored[0].equal(p) +print("verifying") +verify_res, verify_print = d.verify_sync(p) +print("verify done") +assert verify_res == True + +print("deleting") +d.delete_print_sync(p) +print("delete done") +d.close_sync() diff --git a/tests/synaptics/device b/tests/synaptics/device new file mode 100644 index 00000000..6da3eea7 --- /dev/null +++ b/tests/synaptics/device @@ -0,0 +1,75 @@ +P: /devices/pci0000:00/0000:00:14.0/usb1/1-1 +N: bus/usb/001/070=12010002FF10FF08CB06BD0000000000010109022700010100A0320904000003FF000000070501024000000705810240000007058303080004 +E: DEVNAME=/dev/bus/usb/001/070 +E: DEVTYPE=usb_device +E: DRIVER=usb +E: PRODUCT=6cb/bd/0 +E: TYPE=255/16/255 +E: BUSNUM=001 +E: DEVNUM=070 +E: MAJOR=189 +E: MINOR=69 +E: SUBSYSTEM=usb +E: ID_VENDOR=06cb +E: ID_VENDOR_ENC=06cb +E: ID_VENDOR_ID=06cb +E: ID_MODEL=00bd +E: ID_MODEL_ENC=00bd +E: ID_MODEL_ID=00bd +E: ID_REVISION=0000 +E: ID_SERIAL=06cb_00bd_317bb11d90a4 +E: ID_SERIAL_SHORT=317bb11d90a4 +E: ID_BUS=usb +E: ID_USB_INTERFACES=:ff0000: +E: ID_VENDOR_FROM_DATABASE=Synaptics, Inc. +A: authorized=1 +A: avoid_reset_quirk=0 +A: bConfigurationValue=1 +A: bDeviceClass=ff +A: bDeviceProtocol=ff +A: bDeviceSubClass=10 +A: bMaxPacketSize0=8 +A: bMaxPower=100mA +A: bNumConfigurations=1 +A: bNumInterfaces= 1 +A: bcdDevice=0000 +A: bmAttributes=a0 +A: busnum=1 +A: configuration= +H: descriptors=12010002FF10FF08CB06BD0000000000010109022700010100A0320904000003FF000000070501024000000705810240000007058303080004 +A: dev=189:69 +A: devnum=70 +A: devpath=1 +L: driver=../../../../../bus/usb/drivers/usb +A: idProduct=00bd +A: idVendor=06cb +A: ltm_capable=no +A: maxchild=0 +L: port=../1-0:1.0/usb1-port1 +A: power/active_duration=33942 +A: power/autosuspend=2 +A: power/autosuspend_delay_ms=2000 +A: power/connected_duration=33942 +A: power/control=on +A: power/level=on +A: power/persist=1 +A: power/runtime_active_time=33702 +A: power/runtime_status=active +A: power/runtime_suspended_time=0 +A: power/wakeup=disabled +A: power/wakeup_abort_count= +A: power/wakeup_active= +A: power/wakeup_active_count= +A: power/wakeup_count= +A: power/wakeup_expire_count= +A: power/wakeup_last_time_ms= +A: power/wakeup_max_time_ms= +A: power/wakeup_total_time_ms= +A: quirks=0x0 +A: removable=removable +A: rx_lanes=1 +A: serial=317bb11d90a4 +A: speed=12 +A: tx_lanes=1 +A: urbnum=12 +A: version= 2.00 diff --git a/tests/umockdev-test.py b/tests/umockdev-test.py new file mode 100755 index 00000000..f1387d6d --- /dev/null +++ b/tests/umockdev-test.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 + +import sys +import os +import os.path +import shutil +import tempfile +import subprocess + +if len(sys.argv) != 2: + print("You need to specify exactly one argument, the directory with test data") + +# Check that umockdev is available +try: + umockdev_version = subprocess.check_output(['umockdev-run', '--version']) + version = tuple(int(_) for _ in umockdev_version.split(b'.')) + if version < (0, 13, 2): + print('umockdev is too old for test to be reliable, expect random failures!') + print('Please update umockdev to at least 0.13.2.') +except FileNotFoundError: + print('umockdev-run not found, skipping test!') + print('Please install umockdev.') + sys.exit(77) + +edir = os.path.dirname(sys.argv[0]) +ddir = sys.argv[1] + +tmpdir = tempfile.mkdtemp(prefix='libfprint-umockdev-test-') + +assert os.path.isdir(ddir) +assert os.path.isfile(os.path.join(ddir, "device")) + +def cmp_pngs(png_a, png_b): + print("Comparing PNGs %s and %s" % (png_a, png_b)) + import cairo + img_a = cairo.ImageSurface.create_from_png(png_a) + img_b = cairo.ImageSurface.create_from_png(png_b) + + assert img_a.get_format() == cairo.FORMAT_RGB24 + assert img_b.get_format() == cairo.FORMAT_RGB24 + assert img_a.get_width() == img_b.get_width() + assert img_a.get_height() == img_b.get_height() + assert img_a.get_stride () == img_b.get_stride() + + data_a = img_a.get_data() + data_b = img_b.get_data() + stride = img_a.get_stride() + + for x in range(img_a.get_width()): + for y in range(img_a.get_height()): + assert(data_a[y * stride + x * 4] == data_b[y * stride + x * 4]) + +def capture(): + ioctl = os.path.join(ddir, "capture.ioctl") + device = os.path.join(ddir, "device") + dev = open(ioctl).readline().strip() + assert dev.startswith('@DEV ') + dev = dev[5:] + + subprocess.check_call(['umockdev-run', '-d', device, + '-i', "%s=%s" % (dev, ioctl), + '--', + '%s' % os.path.join(edir, "capture.py"), + '%s' % os.path.join(tmpdir, "capture.png")]) + + assert os.path.isfile(os.path.join(tmpdir, "capture.png")) + if os.path.isfile(os.path.join(ddir, "capture.png")): + # Compare the images, they need to be identical + cmp_pngs(os.path.join(tmpdir, "capture.png"), os.path.join(ddir, "capture.png")) + +def custom(): + ioctl = os.path.join(ddir, "custom.ioctl") + device = os.path.join(ddir, "device") + dev = open(ioctl).readline().strip() + assert dev.startswith('@DEV ') + dev = dev[5:] + + subprocess.check_call(['umockdev-run', '-d', device, + '-i', "%s=%s" % (dev, ioctl), + '--', + '%s' % os.path.join(ddir, "custom.py")]) + +try: + if os.path.exists(os.path.join(ddir, "capture.ioctl")): + capture() + + if os.path.exists(os.path.join(ddir, "custom.ioctl")): + custom() + +finally: + shutil.rmtree(tmpdir) + diff --git a/tests/vfs5011/capture.ioctl b/tests/vfs5011/capture.ioctl new file mode 100644 index 00000000..c7ae6094 --- /dev/null +++ b/tests/vfs5011/capture.ioctl @@ -0,0 +1,107 @@ +@DEV /dev/bus/usb/002/017 +USBDEVFS_GET_CAPABILITIES 0 7D000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 01 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 38 0 00008C53DE4A4E000000041E0105000100006C3B5712A6C00000000000000100000000000000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 38 0 00008C53DE4A4E000000041E01050001000A6C3B5712A6C00000113000000100000000000000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 38 0 00008C53DE4A4E000000041E0105000100036C3B5712A6C00000123000000100000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 19 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 64 0 000000030400400CD07104A002000000B84704A0152D6935190000000000000058070060B74187D8000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 4 0 B5C457F9 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 39 39 0 0B000000000000000000000000000000000000000004000000000000000000000000009F000000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 6 0 0000FFEF3013 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 40 40 0 0B00000000000000000000000000000000000000000500000000000000000000000000AB00000000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 7 0 0000FFFFFFFF12 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 578 578 0 069CF19D71C313DF5FE47A1FC717539A1AA1D7B66EBEDF1F9F444222FA2A6AAB2BF05639E37B539A1AA1DBBA62B2E465E5DB68047998DE8F23FBECAD76CAA2EB6138C7AB6E2E78F979138AE59022638D0E9325495AC8A3D87EAE12F62C1CFC484F0E4822FB4BCE7EDB2D91E0C8782EAF2FD4036F1259C62640882E62BA066CC97A8493CF14154487E20997E6CE7E28A92953D7B8D15330156E953EA27ACA9C1D9DEB5F15EF4834CCCB02A6D6A780F23F7E9623AE42F129F5AD5A355736AAAF97E81EA2D3FB4B1D9C1C0684EB9E2CD41894447E4B1291F28B0745DB52BB2E5363E338B8954D9BCF0705DD4CE239AFA951DBAD19C8136E0A2FEA12B92555B664047F146E1208FBBDBD1DC6E284502060A090D2748A18A4D9E969B21E73AB1B7BBB3BE04223F929498909D24C29F12165AC2C97306CB404F43DBD06A0C61ECE7EB333882E439B2B37F070CB91F12BFB8B48CA3997FB21B9CD0E8C7F8DEC36E6EA27A51E402AF222CA07853EC8AE76A6F071F1AB6B046DA9CA062C66A5CAB04B2B62EBD5610DF04626C3449F0C63BBAABD7EF27400662B7A62A10780338D1FF745CB5E24EB84ED274461FF0CA73BE353058404EE234CB5791AF3A066204C942472F37339F897DD6454F26BBAADBC676678BB5E6DFB8AA2743DF5D472C71ABD0E0B2C8C4A0C60B8085EDF5F05335CB57E1DFCFD25BA95C4A7DAEA6AB1311CC4E507C4C59D28CD3CE98949D4FF7F528A9B7FBC8EF5CF0BD949488880717DABEF472BF77B2D793FCFBFFF3F6DF842EC7FE8ED42E61D4D32FA6A0AD7A77CCBA77BCBBF71F348 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 1A + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 2354 2354 0 06FE93FF03BA6AA6269D0366BE6E2AE363D8FE9B4393D70383388CE03888589414AFC9A27ACA965EDE652736EA3A4E8202B90F4B9717F71A9E75C38F53D39F7FFB10E6AA76F6729317FC4A26FE762AEA6A893FF32BA3FF9F1FFC4A06DE5638D858BB0D21F971199919FA4C40981078D858BB0DE139B1D99919FA6C7EA272C67DF942F4865ADAD206863D6F08D000D810902BFDB76BBB67A0209B3536EA3AA20C88337D1AC2122AFE7EC58C17307FE0CFB0944E36EE3E5E9616CD9FE13BEB8B5BDB008AF22AFA0EC848F36D12C81808DC5CE70179A1713DF474CF8417CF7FE0205F7BFBD60E1B65A500DC6AE37ECE4BCE6822B8D7AE33509C1446FA1485354878F823A38E567739FA76A591B434E14DA8351E9EB36B6A3AF9D40D9AD902F494541FE65B8C72C9A3EB6932041C4369F93FBE65F6FE039EF4295982022FF76766A603226B2719BACA2AAA7DC108F663A253D0BA3E51AC3870ADDD0686AB73F2A162C32C99DC47EA7ABA3AE1614C94A6C4098545739F43A5DD1A9648F29802A0CE1295748658447527E3630AB7A5BF0B6A9DA671F020E9640F0833E46F0F11A0C0378B5425F22BA6CDA02345F0F99901CB6DB73F82990AFE2C2829A4851560D508CD68049AFA395B9935150AFD514F3F8597E52317BBA756F6B5745F069AA2F1B0FA94BFC73822CF2DEB68B3C709BDC76567FB5DD1716BD7B7A537E57E19161A7BB715D395F92191C746C6AC2F40209B77DCFE845294E7F228C8E53C2FEF12BF2FEF6FB43419C1D0864574982D8C56437590A143F6BA48589961E2F44089049140BB38C34F8399EA9AFB4199234DBC0F46953CC45B04F91D5829944CCA9CE49635E5C42396DF54C1AD64D435237D66C6BDE44D95683789A0365BD8B1A76E9A662341E9931B741D92F1F3B04F5C609D9CBD7ECE2F39F46CDF8D8E2A3C89C04ADF0E8D0EE569A5DC2E4D40C3FD185138CDAE5EE49F88A07B066540926C6B409B1B4121009D288952C7F510A05147361EAEF879F90794F8A1583B6AD9011632E9F0C98009CF89E53D8DDB5ADA30B3DC089FC704D544F10FD46C6E0FFF2F106AFA4CFD76F522FE9E4173DAE670A31F55D46CA163061C8CCD1FB222884B2287E0AA1E7EA813C31306CEBCC8F42255E927BC04468508F3640CC989E52E2CF44FE11A7700A8276ED5B96DCFB950DE0E11DF4AFADC1C9C4BFF53AB1BD90A829B4884D07AFFD573B5F3F56E0C68A84E8802D62C31527713EEF874D80E7091A037821CCF7F39D651F80569BD07C268CD1A946A91FF5FBF3F76A56933C0A82EAD76621DC2FEE45692495D22FDE86E8804CD66FA90335BF132FF82E9F34727256949E9B96634579A9867502B9D7D8F42C20F305084264D74069026CC04B4565F26AB851C7CEE23E0858313DF97533861B78539598A361A389B9DF9379BF14242E2392D5282D0D5B547C109A73C84F2780ADD058B17A765B63E0069237D08977AFD2A933FC777B566EEB764A8664CDF7A24D972EE3A88AEA6D9BA2EEF3421997F5F14D6DC1D8AE62D7F87EC4238FC565515EE58E65B4B895AD27B9183E70D0724A81E7A588092E1294C4DDD37E6563A850986725D8D57744682595D22F1DDF6845077CD5B8FB755D1516F014B01A5396B22082C1430A2C10CAC56E495BD2047015E7A6E1632942E068AD9EDC51D1BC1119DBC2F956BF98DB1130A4D038FC3A5F887395A10E552744837EC6C4199782DEE36E81CD0F80227D5510A9AD53CAA897A9B0ABFA23182EE862098010B50FE922133CDA509F141B31535DC2EC2A81D7012954E4895494981D2F06CDAAB832EBE72E17CCAA672F1A32727E1A7C74C3E7B6525DE68C67868CEFD8259D9F42CAD8043E277C2874CE171B131EA6A479FBEEB2830E2D81D67FE432303CC5C0AD00522C35E75F5D8001121E243D16439D261901F9CC6214E1F86CF0C25A70C9048F8AE2FAF55B1DE8E1CBB138EF4117E43BEF6A773ABDCE53E3F09CAE21B15726A7000504A8187713A1351B4FA04AF33EB5B0D8C0C7693FC41B6FEDF08D02778A32210D35F88E6A9806605729F666D0E1EAA03CCE1380F3BE0B04DADB44C731BA6137302DB031D528634E48E2E5CC9B8902C4741371393BE66CA622537E87F49923FAFC2403E4E07F2483505855EDEF32BDAE1229314A145D9E002FB3FF9BFD30BBBED6CEC95E19D60ABEBBA61B9876938C1BC8C0CD7577AA2AFCD2CF129B7D90D31DAB81D8C12FF79CA383AAAE80CF9635A58149775512008B8EE6FEF05EE8161D200D34B9C365D6EC435AA29322F6319FA828222F9D7B2E84B2D4F0CC7EB0F5E9D18AB0B62C7B37C274931227558BC6F721030B863F89E5B1B77B5280383AE76F7CA09B1696D13DFA7640CAFBEB3661D0A51C0E0A0D638F35BA2C156E578D6A6E968C84B686DC139893BE8701AE689B1DCAC9E750E6A5595E5A56547B7812DD565C5AF3F469B77E958385A19D2C1C33B4B0BCBDA5EEB05CE7880496B73D523734A597C976C52BDC87AFA32B274325E863660E161F8E6753CED8EFF22FA7D5B8088E3E17AB903424A367674AF6C1A568E9CDFBF96F680CC1426650545BE08F4A404F697175C622E74A76767C71C88C79FEFAF6FAF56F0DEA21232D070895CB0753563E262DF5D3963D0979516EB3B6FBDA0C2BF3C2A985156C4B989A1292DE1C2C26EBEFC64F458A010E228A4BF29452D047426EC3B900CD4641EDF5F84325E8636B67BF942F09D45F59555D50E1476AC7C00C04893583096227EAC2E95BBC51FCF03D153E8C2BD67B7FF2CAE15EB934B9BB763E3589EE63EEEBA7AFA2197FB2393F333B368DEB26ADA925BDB60F2974F9FEF1F9D467008D00030F171AAA0CB13C30BC644FF355E86568E43C17AF0944C9CEC22A01B6507DD0D05D151EAD0B369B9B160E2595733EB3B8352D06BD1AF75A5459715AEF09A42921ECD4FF40264BC6C3ABB3B61C8A1C86500CC165CF49DE71C7C35BC42F79BA6157510954E9DF921F49050B567D1588030F11194FE6900FDF9BE6313C84865BD3C7EBB1AE25114DF72E222A279F9D40C8DC90CAD53E0A5AE039353D30888A57DFCBA7FDE2291D44FE272B232E969449C1D599C3DCE7D3873DE4E8E0ED55578A081C80D815266439B4E2FEFCE3E8D50AE1BBA50D5C77ABF3C9101C1419A1A37EF6E22E746B003468D20B070F02BAB865E6F21E455AC1F52A51059BAB33B900CD46432B33379FF96CF4E2B62CB75C3AF6A2A7CFD7D0783EA80907C149E65B2DE8E14CEB4A86BD1A17548CA2088930569639DF1F338C4573AC656D0039368DEAF8737579717CC7A16CE7E1EDE5E85325E82329E4AC873 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 2221 2221 0 022001010003000900042004300000000004030009001820043000000000040300090020200430080080000403000900242004300000FF0104030009002C20043001000000040300090040200430AD010000040300090044200430AD010000040300090048200430AD01000004030009004C200430FF03000004030009005020043000005003040300090054200430013E020004030009000021043014000000040300090004210430010000000403000900082104300100000004030009000C2104300100000004030009001021043001000000040300090014210430010000000403000900182104300100000004030009001C210430120000000403000900202104300400000004030009004021043000000000040300090044210430010000000403000900482104301000000004030009004C2104300100000004030009005021043001000000040300090054210430000000000403000900582104300100000004030009005C2104301F0000000403000900602104300F00000004030009008021043000000000040300090084210430010000000403000900882104301000000004030009008C2104300100000004030009009021043001000000040300090094210430000000000403000900982104300100000004030009009C2104301F0000000403000900A02104300F0000000403000900C0210430000000000403000900C4210430010000000403000900C8210430100000000403000900CC210430010000000403000900D0210430010000000403000900D4210430000000000403000900D8210430010000000403000900DC2104301F0000000403000900E02104300F0000000403000900A0200430EFE100000403000900A4200430000000000403000900A8200430FE2100000403000900B0200430000000000403000900C4200430470000000403000900C8200430000000000403000900CC20043020000000040300090004000038000800000403000900080000380012000004030009000C00003801030200040300090010000038010702000403000900140000380C0C8A000402008005FFF98720834884208348842083488420834884208348842083488420834884208348842083488420834884208548042087480420894804208B4804208D4804208F48042091480420934804209548042097480420994804209B4804209D4804209F480420A1480420A3480420A3480400855A0420875A0420895A04208B5A04208D5A04208F5A0420915A0420935A0420955A0420975A0420995A04209B5A04209D5A04209F5A0420A15A0420A35A0420A35A0400856C0420876C0420896C04208B6C04208D6C04208F6C0420916C0420936C0420956C0420976C0420996C04209B6C04209D6C04209F6C0420A16C0420A36C0420A36C040086480420884804208A4804208C4804208E4804209048042092480420F7480420F9480420FB480420FD480420FF4804200149042003490420054904200749042007490400865A0420885A04208A5A04208C5A04208E5A0420905A0420925A0420F75A0420F95A0420FB5A0420FD5A0420FF5A0420015B0420035B0420055B0420075B0420075B0400866C0420886C04208A6C04208C6C04208E6C0420906C0420926C0420F76C0420F96C0420FB6C0420FD6C0420FF6C0420016D0420036D0420056D0420076D0420076D040083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842083688420836884208368842000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A000800100351091003510903000900002004308000000004150008000000000020280000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 256 256 0 01010000040F081063666666656866646764666763666668696867636868676B6868676668666A676C6768646768696B6A68666A696A66676867676668666967686655005165686A696260616162696767646A696969696A6D6B69686B646864686865696A6B6A696766686767666B676C6863676665656667646768656763646A646667686567656666676566656562656763616667676464676668686667686767676767666A66656865686767676667666966686667686968686A6566646665696868676969666568686967646865676666666764666564666668666669646667646665656666666669686466666465696765656769656364686A65636366 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 64 32 0 6668676867676364666368656766666463676664676464676766696466666865 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 2770 2770 0 066B066A76CC1CD050EB7510C8185C9515AEA8C810C0B07AFA2196FA2292AE78F843056EB66662D551EAF0E539E9A1199D2680E038E81CCA4AF1BFD800D034D95DB600F22AA2AA7CFC47DDB860B0D0EF6FB4462CF424BB7B042096C51DAD32324D69DFA07AAAB660E05B89F62CFC14C242F92359815131EF6B8036528A3A5A641BF7BDD40CDCBC54D03B0D4C9010709014FF6529F57555B531DA88C51999F939B95AD0BC64EC8CEC6C8F05C91199F919997AC28E56DEBE3EBE5DE3CF179FFF5FDF3C828E56DEBEFE7E9D23CF179FC948C8F6074D0498FB9A37EF553160DA38B131F7B1DD05B5E362E219CEA25F118E6E08C0662AF24E2401AA544301DADB9457B240DEAF873761E06016A24FA71478B13A59780CC55405C68E57EA3D25554146DC0C713F813AAA8F6B950E68ADED90A020FB7B568EAFFC3F9E70C59872C120D45705602E9535CC9F0229A9845CDD8B48DEA7171E49DC945775CC5815FA49B57F7796B2C4083A72B2A029911DCD7D5B9A1AC17B1D205C1C799E454217CCD537FB6734810CEC5FCD05508758A48303F2088BA25CE5BC3E5D45C6F54DE37611D91A78FE1FC173DF7F9F1F4C22DC2D1DEF45E6318E70C250A238EED56B07C2824A89ABBA545D7CEB96A626FD7D5088A9FE3D3FED7F91009550B1314BC6A9F07211DD742DB3CD875D3919914A5E92DEDF894A0BEC598D5E2E6EAEE6311562E7FD363C256CB1F50802429FEF34B49941FD8809BE66E7699D6AE827954ADB9549DF8567C73DAAE478ED90A079E6C2AA576501E76C2E08F4587A5EB9A3F0C62BD2E0C421BC9778204AFEB9DB5FA1B59D4FE42E4E6EC1D5FD0309C3A382786C44B9148444C41F9FB26A1A5A9A16C4F3A279F8A261B050E5FB003A9A7AFA699A946F56B60191CA0B762EF8888828F3773861A1A747B65BEEE27EEEBEDF5BE16B04ECDDB94978E2EC8749D1B9FB50941571D5E4BA79F5645ADE36357555DD067851A82F4C879B56B9DFB5C95781BA6B0FAF8A2CE12DBBDC6A20B40CCEAE2E50501C0693F7F7E7485257A9501471E13A0D5388BAF220409325EB93B76FA8E813A501DFFD861B31413DC8825911341DE698B165DE3E52D3A8BAF60BA8C8A526F14C854FFF57D292D91BEBAA3C15C25F74024E96EE88FA61E7FC92808B52A0C5B82E5F77C7A767552E9927FD478547EF345F227A6011715DA6C006FE6B04C4ECB50F6815ABCB2EE73C86C13C82E23F4F942E48F5E8A8A0653854C71FAF62A104367FE13BAD2FED4A666E1343C11D554DD4DEFB813359951E7C8F41DB4EE663252E67A67D28AE91C31A8A24FE69DEA233008444622A08645B02B6D004BD44C1C35AC96DF0C6615EDE05BFD9E44A2ABC86A11B6DD07E1ED2697FC3A331418AD9F06EDE5C7BCBA74DE82E982CB10D23431D452A031D5FC000805BDBF62E3CFC1849AF1A9770C39265E61C90FF66E88B8B2BF0C48C5A581A5311C957DBB818F8F4656E1468707B3B1B93483E72AA36DC94F0FA0D62089A7072F10F5874AF9F33E28295338FEC4CEC97370CB2DE1B5B0D8C0C961679F07211098D27A6C9831E6262C2192D5680F28F19B06256F2D2F0BD61AABDCB674B390492591B3F3EFACD81379674C148CC59814567D743A3C1F3B97A788B3DB161D1F736B66DD7B18CA6E6AE8BB00E6257ED5FBB3B52FE86FC216371EC6165C2E2854E8FD202096717893999EDFB4BACDE8B8B63C9343A5202E725CE6C25B8C8D2794FEFF6ED3B9B83F1CA5C4EFE54D808B800C4E62A923CF91FDDD7AFD3C92B75C5A544FD25218EA9EFA430A69122AB27B21ADEFC4BDF3F5D6F25E6E417A12DFD4D6BAA2AF14B2D1032723A1F249AF6E6528F4D6FD84C887A0874E2C0D16FE667FF2ED75407E420FC8E4E8ECC4DAD73C16DAF45E7DC620E0490F0C060BBCFBE300CF0923FF8F39D20C78F9D39E2327D9BC9B4231FAA795BA6EE8AE807FEE492C248A06808DB6D89F4A4CC0C14CBF5CCB66F2D0D855E402852F8CF59A385355A82325233F0282F01DAD3E4013DC1AFC7DD70470B874107CA57E455D1525081086AFD80B030EB6B469EEFB87B5ABA0FDFC5F7556BFD6EDED41E855D97F522B00EDD6AA863E5AC1178706ACA9D37A5B19161331FFA588837A97AC250DC7B827832E64439098952E88EB387C70B894F09DD0F6D01E9CB1BAA44972399F3D427D7198D15579C152C96DEF44F2715D9257151AC3E12F478B11A8652E09DAD95445030C0A2C90E0CDC6FD3A1D136DC4039C3877DC6AF8D01FEBADD0D4F6384E671E2AC38AEC2108DA61C72B7F79B59C4EF6F429A0B5D9E9C65D3FE11A240984FA5214E3AF237CA6F2C9856E775B9A3AB4A74102890F0B89BA01E7232806281047DA2ECD46C0C64E69F3308865CC1A065BDBA92494044210AF65DC119A9C9A86BB3C4EA31487C1933CFA1CFC5685FC93411E17B5CECBA3BBB6CD09D73C0DCF0C8112674AFADE6050D3E489F57076FAF875E4AEC6C39FE1984AF2F02DA76CE899B44D3F9228F1F72F00E0E47B2087545C51E9EB36B7614B131EA503EFBBBED6CEC17034FB2E0A756ED351B740C3415579E445075AD36F4D1B14D4A11CAF89A5F2DF445FB219735F77F4CF907DD699B1591C8305923DDBFDFF76D795B8092F0394BDE6FA132A466E8617880E4EE1076663699EF43EF9DB65103930DCBCFAF1EFFAD3DAFDEF64610911107B3D306ADAED355B93B26D53161E5A56597BBE21374D056A6A31DC7770C0E12F1EA8B7873F13DBDB40E6390EC660C5627C631076A006DE086347DC55DF0320FD2680991C0E126C215B8161CAECE15232844E8E08181DDA355EE10C4743F445415639FD606FC1E1CCB7C3B2F1FF5F5F5AF799F6582795BC6ED7617D292FE3CA18A0A07DFAFEF2FEE7CC904942766E162EBFD901AC829298952763860105090B0F2649A2010B050D0891BF6EE7E1E8E867D494118CD8F6AD706A680545C166FEE398408B101B3D35359D8B7AF3F5F5DFFA4D29E46A60AEAB87EC668D2E224F95C2533A3B9284848E83377396B2BC3426246E00BCC8C2CCC4CDCD13FC5F91BB7372E543C33A817864C94C248832363A3A15FED61B10177BD3AED55F81BA8B49C10814B1E0696F6E4401D6B27FFDF22F2D29006F84472D232B29B09E4FC6C0C4C33F8BCB4ED9DDD1D4FF0C06C94248C406890D4B46C6E02C3819622CEAD0C9CE7474EF498823E5F7D9FC5F3539AFA56B6D3E0A94DA63B511991E752DE0EBEC3F373A8127449ADEDABE6C2FCD5ED5535E3193D4DC1E6560081017B86E9807C1F12902E703851AFCC2C86FDEACB106D0FAACD323509D24218783A228449DE6D01C36AB22D52A330798AEFD1439E14A7F70D2D34413D44A5C6E38778C2A74FC505F7B47FE217E6551CCFC42CFC0925385B290977EDCDF0733B5A8951566EB5C76480655CCE139D2E7E84A4DE3D52B8CB8F82013F6A224BA3C0308AF1E6DD067B18BDD8272016CD4D177756D461C01B0E8A6E5FD86D31D3C302991A0CB9704BDF8F654583C5A971C1BB7AFA2197FB23937FB2308BA9D30BDBA666EC37036B3084449715AE1975AD1D01D757EC265C84549C4ACA714F35ED3DD50383382258805030F070AB1D71A91979B939E25438E05030F070AB1D71A91979B939E25438E05030F070AB1D71A91979B939E27C19C111559C1CA7035F87379741C17A7C10C87864A3239882E339E979BE3E85C3A278A8B876F44FF1924898448303B886F923F33FEA68D3537EA6974580B1DA69A7DF6C9DEC6910ED81DB0262C7469D0E60B82D4989A8C073AEC277F2A304C284E83080D657D73D3E57AEA8CD2477B1F79B43F3A524A4CEC0A9404B2ECFF32D1ACC1130E7220361D21716242DFD54ACA35693D38504846E6D04FDF0957C6FA9EF835BEB8B4BCB10A6CA12A2C2028259EE825EEE76A02299 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 2855 2855 0 02B000620003000900042004300000000004030009001820043001806400040300090020200430080080000403000900242004300000FF0104030009002C20043001000000040300090040200430FF030000040300090044200430E6030000040300090048200430E703000004030009004C200430E80300000403000900542004300092010004030009000021043000000000040300090004210430010000000403000900082104300100000004030009000C2104300100000004030009001021043001000000040300090014210430010000000403000900182104300100000004030009001C2104301F0000000403000900202104300100000004030009004021043000000000040300090044210430010000000403000900482104300100000004030009004C2104300100000004030009005021043001000000040300090054210430010000000403000900582104300100000004030009005C2104301F0000000403000900602104300100000004030009008021043000000000040300090084210430010000000403000900882104300100000004030009008C2104300100000004030009009021043001000000040300090094210430010000000403000900982104300100000004030009009C2104301F0000000403000900A0210430010000000403000900C0210430000000000403000900C4210430010000000403000900C8210430010000000403000900CC210430010000000403000900D0210430010000000403000900D4210430010000000403000900D8210430010000000403000900DC2104301F0000000403000900E0210430010000000403000900A0200430EFE100000403000900A4200430000000000403000900B0200430000000000403000900C4200430140000000403000900C8200430000000000403000900CC200430200000000403000900502004300002A8020403000900A8200430FE210000040300090004000038000700000403000900080000380015000004030009000C00003801030200040300090010000038010702000403000900140000380C0C05000402008005FF8307205F820720FF8307205F820720FF8307205F820720FF8307205F820720FF8307205F820720FF8B0720608A0720FF93072061920720FF9B0720629A0720FFA3072063A20720FFAB072064AA0720FFB3072065B20720FFBB072066BA0720FFC3072067C20720FFCB072068CA0720FFD3072069D20720FFDB07206ADA0720FFE307206BE20720FFEB07206CEA0720FFF307206DF20720FFFB07206EFA0720FF8507206F840720FF8D0720708C0720FF95072071940720FF9D0720729C0720FFA5072073A40720FFAD072074AC0720FFB5072075B40720FFBD072076BC0720FFC5072077C40720FFCD072078CC0720FFD5072079D40720FFDD07207ADC0720FFE507207BE40720FFED07207CEC0720FFF507207DF40720FFFD07207EFC0720FF8707207F860720FF8F0720808E0720FF97072081960720FF9F0720829E0720FFA7072083A60720FFAF072084AE0720FFB7072085B60720FFBF072086BE0720FFC7072087C60720FFCF072088CE0720FFD7072089D60720FFDF07208ADE0720FFE707208BE60720FFEF07208CEE0720FFF707208DF60720FFFF07208EFE0720FF83A7005F82A700FF8327005F822700FF8327005F822700FF8327005F822700FF8327005F822700FF8327005F822700FF8327005F822700FF8327005F822700FF8327005F822700FF8327005F822700FF8327005F822700FF8327005F822700FF8327005F822700FF8327005F822700FF8327005F822700FF8327005F822700FF8327005F822700FF8327005F822700FF8327005F822700FF8327005F822700FF8327005F822700FF8327205F822720FF8B2720608A2720FF93272061922720FF9B2720629A2720FFA3272063A22720FFAB272064AA2720FFB3272065B22720FFBB272066BA2720FFC3272067C22720FFCB272068CA2720FFD3272069D22720FFDB27206ADA2720FFE327206BE22720FFEB27206CEA2720FFF327206DF22720FFFB27206EFA2720FF8527206F842720FF8D2720708C2720FF95272071942720FF9D2720729C2720FFA5272073A42720FFAD272074AC2720FFB5272075B42720FFBD272076BC2720FFC5272077C42720FFCD272078CC2720FFD5272079D42720FFDD27207ADC2720FFE527207BE42720FFED27207CEC2720FFF527207DF42720FFFD27207EFC2720FF8727207F862720FF8F2720808E2720FF97272081962720FF9F2720829E2720FFA7272083A62720FFAF272084AE2720FFB7272085B62720FFBF272086BE2720FFC7272087C62720FFCF272088CE2720FFD7272089D62720FFDF27208ADE2720FFE727208BE62720FFEF27208CEE2720FFF727208DF62720FFFF27208EFE272000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A0008001003181C1003181C030009000020043080000000040C000100000D007801500100000E00000002000000006E0065006500720069006E0067005C0070007200690076030000000C00003800070000FD00FFFF0C00003802070000FD00FFFF0C00003800080000FD00FFFF0C00003802080000FD00FFFF0C00003800020000FD00FFFF0C00003802020000FD00FFFF0C00003800030000FD00FFFF0C00003802030000FD00FFFF0C00003800040000FD00FFFF0C00003802040000FD00FFFF0C00003800050000FD00FFFF0C00003802050000FD00FFFF0C00003800060000FD00FFFF0C00003802060000FD00FFFF1000003802030000FD00FFFF1000003800040000FD00FFFF1000003802040000FD00FFFF1000003800050000FD00FFFF1000003802050000FD00FFFF1000003800060000FD00FFFF1000003802060000FD00FFFF1000003800070000FD00FFFF1000003802070000FD00FFFF1000003800080000FD00FFFF1000003802080000FD00FFFF1000003800090000FD00FFFF1000003802090000FD00FFFF10000038000A0000FD00FFFF0E00E000000100010001001F010000000000FE01000101010001001F010000000000FE01000101010101001F010000000000FE01000102010101001F010000000000FE01000101010101011F010000000000FE01000102010101011F010000000000FE01000104010101011F010000000000FE01000104010201011F010000000000FE01000108010201011F010000000000FE01000108010401011F010000000000FE01000110010401011F010000000000FE01000110010801011F010000000000FE01000110010801021F010000000000FE01000110011001021F010000000000FE010F000100021000010001110002000E00120001000E150008000000000020280000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 17216 17216 0 01FE01000101C8107F7A7E7A7E797E7A7E7A7E7A7E7A7E7A7F7A7F7A7F7A7E7A7F7A7F7B7F7A7E7A7E7A7E7A7E7A7F7A7E7A7E7A7E7A7E7A7F7A7F7A7E7A7E7A7E7A7E7A7F7A7E7A7E7A7F7A7E7A7F7A7E7A7E7A7F7A7F797E7A7E7A7E7A7F7A7E7A7E7A7F7A7F7A7E7A7F7A7F7A7E7C807980797F79807A807980797F797F79807980797F79807A80797F7980798079807A8079807980797F797F797F797F797F797F797F797F7A807980797F797F7901FE02000101D8207F79807980797F797F797F797F798079807A807980797F7880797F79807980798079807980798079807A80797F7980797F797F797F797F797F797F7980797F787F797F797F797F797F797F797F787F7980797F79807980797F79807A807A7F798079807980797F7B8277827783778377827782778277827782778277827782778377827782778277827782778277827782778277827781768176817681768178827782778277827701FE03000101D830807880788078807980788078817980798079807880788078807880788078807880788178807880788078807880788078807980788078807880788078807880788078807880788078807880788078807881788078807980788078807880798079807880788078807C8475847485758576857584758374847485748475847584748475847584758474837484758575847585758474847484748474837484748477857584758374847401FE04000101D840807980798079807980798079807980798079807980787F788078807980787F797F787F797F787F7980797F78807980797F79807880797F788079807980787F7980787F7880797F79807980798079807980798079807980797F797F7980787F7980797F798078807C8575857485758575847584748474847484748574847484748473847484748474847484748473847484748474857484748473847484748478847584748474847401FE05000101D8507E7B7E7A7E7B7E7A7E7A7E7A7E7A7E7B7E7B7E7A7D7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7D7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7B7E7A7E7A7E7A7E7A7E7A7F7A7E7A7F7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7C8277837683768376837682768275827582758276837682768275827682758376827682768275827682768276827582758276827682768379837682768275827501FE06000101D8607C7C7C7C7C7C7D7C7C7C7C7C7D7D7D7D7C7C7C7C7D7C7C7C7D7C7C7C7C7C7C7C7C7C7C7C7C7C7D7C7C7C7C7B7C7C7C7C7C7C7C7C7C7C7D7C7C7C7D7C7C7C7C7C7C7C7C7C7D7C7D7C7D7D7D7C7D7C7D7C7D7C7C7C7C7C7C7C7D7C7C7C7C7C7D7C7C7C7C7B7C7C7D7C7F787F79807A807A807980797F787F787F787F797F787F797F787F787F79807980797F787F787F787F787F788079807980797F7880797F7B807980797F787F7801FE07000101D8707B7E7B7E7B7E7B7E7B7D7A7D7B7E7B7D7B7D7B7D7B7E7B7D7B7D7B7D7B7D7B7E7B7E7B7D7B7D7B7E7B7D7B7D7B7D7B7D7B7E7B7E7B7E7B7D7B7E7B7E7B7E7B7E7B7E7B7E7B7D7B7E7B7E7B7E7B7E7B7E7B7E7B7E7B7D7B7E7B7D7B7D7A7D7B7E7B7D7B7E7B7D7B7C7C7C7C7D7C7D7C7D7C7C7C7C7C7C7C7C7C7C7C7C7C7C7B7C7B7C7B7C7C7C7C7C7B7C7B7C7B7B7C7C7C7C7C7C7B7C7C7C7C7C7D7C7D7C7C7D7C7C7C7C7C7C7C7C01FE08000101D8807A7F7A7E7A7E7A7E7A7F7A7E7A7E7A7E797E7A7E7A7E7A7E7A7E7A7E7A7E7A7F7A7E7A7F7A7F7A7E7A7E7A7E7A7E797E7A7E7A7F7A7F7A7E7A7F7A7F7A7F7A7F7A7F7A7F7A7F7A7E7A7F7A7E7A7E7A7E7A7F7A7F7A7F7A7F7A7E7A7E7A7E7A7E7A7E7A7F7A7F7A7D797F79807980797F787F797F797F797F797F797F797E797F787F797F797F797F797F787F797E797E797F797F797F7A807A7F79807A7F797E787F797F797F797F01FE09000101D890797F797F797F797F797F7980797F797F797F7980797F797F7980797F7980797F797F797F797F7980797F797F797F797F797F798079807A807980798079807A807980798079807980797F7980797F79807980797F797F79807980797F797F797F797F79807980797D7681768276817681758176817782778176827781768176817682778177827681768276817781778177827782778377827782768277837881758176817782778101FE0A000101D8A0788078807880788078807880788078807880788078817880788078807880788079817880788078807880788078807880788078807980788078807980798079807881788078807980788078807880788078807880788078807880788078807880788078807880787D7584748474837483748474837584758474847483748474837483748474847484748374837484748374837584748475847584758575857582748474837584758401FE0B000101D8B07980798079807980797F7980787F787F79807980798079807980798079807980798079807980798079807980798078807980798078807980788079807980797F797F787F7880788078807880787F787F797F797F788079807980798079807980798079807980797D7484748474837383748475847484758574847484758475847484748475847485758574847485748474847585748575857485758574847582748475847484758501FE0C000101D8C07A7E7B7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7B7E7B7E7A7E7A7E7A7E7B7E7B7E7A7E7B7E7B7E7B7F7A7E7B7E7B7F7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7B7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7E7A7D7683758276827681768276827683778376837683768377837683778376837683778376837683768376837683768376837683768375827680768276827683778301FE0D000101D8D07C7D7C7C7C7D7C7D7C7C7C7C7C7C7C7C7C7D7C7D7C7D7C7D7C7D7C7C7C7D7C7D7C7D7C7D7C7D7C7C7D7D7C7D7C7D7C7D7C7D7C7C7C7C7C7C7C7C7C7C7C7D7C7C7C7D7C7C7C7C7C7C7B7C7B7C7C7C7C7C7C7D7C7C7C7C7C7C7C7D7C7D7C7C7C7C7C7C7C7C7C7C7C7C7980797F797F787E7A7F79807980798079807980797F798079807A8079807980798179807A80797F7A807980798179807980797F787F797E7A7F79807980798001FE0E000101D8E07E7B7E7B7E7B7D7B7D7B7D7B7E7B7D7B7D7B7E7B7E7A7E7B7E7C7E7B7E7B7E7B7E7B7E7B7E7B7E7B7D7B7E7B7E7B7E7B7E7B7E7B7E7B7D7B7D7A7D7B7D7B7D7B7D7B7D7B7D7B7E7A7D7B7D7B7D7B7D7B7E7B7D7B7E7B7E7B7D7B7E7B7E7B7D7B7D7B7E7B7E7B7E7C7C7C7C7B7C7C7D7C7D7C7D7C7C7C7C7C7D7D7D7C7D7D7D7D7D7D7D7D7C7C7D7C7D7D7C7D7D7D7D7D7C7D7D7C7D7C7C7C7C7B7C7C7C7C7C7B7D7C7D7C7C7C7C7C01FE0100010188107D7D7D7C7C7C7C7C7C7C7C7C7B7C7C7C7D7D7D7C7E7E7E7D7D7D7D7D7E7D7D7D7D7D7D7D7D7D7D7D7C7D7D7D7D7D7D7E7E7D7D7D7B7C7C7D7C7C7C7C7B7C7D7C7C7C7D7D7B7A7B7B7B7A7C7B7C7C7C7C7B7B7C7C7C7C7B7A7C7C7D7E7D7D7D7D7C7D7C7C7B7D7C7C77817680768076807882798277827882788378837882788279837A8378827683788479837A8477837883778378827781768377827781767F788279827782788201FE020001019820827683758475827684758375837583768476837682768476847784778578847684778477847783768476847784768577847682758277837582758276837481758274827581758175837582748374827583758274847682758176837683778376827682768275827B81798178817882788179817981798279817A81798279817A837A817A817A8079827A827A8179817A8179807A8179807880777F7780778078817981798179827901FE03000101983089718870887089718871896F897088728A7189708870897088718871897189718971897189718970897188718971897189728871876F8770876F87708870887087708870876F876F8870886F88708870886F8870887088708870887187728970897189708870887A8672877288738873887287738872877187738873887388728772877387728772887388738873897386728672887286718571857186708774887287738872877101FE0400010198408A6D8C6D8C6D8C6D8B6D8B6C8B6E8E6F8C6E8B6D8B6D8B6C8A6C8B6E8C6D8B6D8C6D8B6D8B6E8C6D8B6D8B6D8B6D8C6E8D6E8B6E8C6D8A6C8A6C8B6C8B6C8A6C8B6D896C8A6D8B6D8B6C8C6D8B6D8A6D8C6D8B6D8B6D8B6D8B6D8B6D8C6E8C6D8B6E8C6D8C6D8A7A8B6F8B6F8B6F8C708B6F8C6E8A6E8A6F8C6F8A6F8B6E8A6F8A6E8A6E8B6E8A6E896E8B6F8B6F8C6F8B6F8A6D896D896E8A6E896E896E8A718B6F8C6E8A6E8A6F01FE0500010198508C6E8C6E8B6D8B6D8B6D8B6E8C6D8C6E8C6F8C6D8B6C8B6C8B6C8A6D8B6D8B6C8A6B8C6D8B6D8A6C8A6D8B6D8B6D8C6D8B6D8A6D8B6C8B6D8B6C8A6C8B6D8B6D8A6C8B6C8B6D8C6D8C6E8D6F8D6E8C6E8C6E8B6D8C6E8C6D8A6C8B6D8C6D8B6D8C6E8B6D8B6D8C7A8D6D8E6C8E6D8E6D8D6D8D6C8C6B8B6B8D6D8D6C8D6C8C6B8B6B8E6C8D6C8D6C8C6B8C6B8D6B8D6D8D6C8C6A8C6B8C6B8C6B8A6B8C6B8E6F8D6D8D6C8C6B8B6B01FE06000101986087708870887088718A70887088718A728871896F8870876E886F876F886F886F8870886F8770876E886F886F886F886F8771886E886E88708870876F8870886F886F876F88718A718A718A7289708A7189718872897088708870876F886F886F896F87718870877A8C6E8B6E8C6F8D6F8D6D8B6C8B6C8A6C8B6D8B6D8C6D8A6C8B6B8C6B8A6D8B6C8B6C8A6C8B6C8C6C8A6D8C6C8C6C8C6C8B6C8B6D8B6D8C708D6D8B6C8B6C8A6C01FE070001019870847683758276837583758375847683768376837582748174827482748274837582738374827583758274837482748274847683748373827483748374837584768475837583758477847584758477857685778576847683758375827383758375837583768275837B897288718872897288728770856E856F866F8771877087708770866F8770866F87708670866F85708770876F87708771887088718872887488728770856E856F01FE0800010198807C7C7C7C7B7B7C7C7C7D7D7C7C7D7C7D7B7C7C7C7B7C7B7A7A7B7B7C7C7C7B7B7C7B7B7B7C7B7C7B7B7A7B7B7B7A7B7A7A7B7C7B7C7C7C7B7D7C7D7D7E7D7E7D7C7B7C7B7D7D7D7D7E7D7D7D7D7E7E7C7D7D7C7C7C7C7D7D7C7D7C7C7D7C7A7B7C7B7C7C7C7C7D7D82778277817983788077817680777F75807680768177807680758078817681757F748075817680757F7480768177827782768278807782798077817680777F7501FE090001019890768376837584768375837683758375837583758375837583748274827482768275827581758275827481748174817482758275837583768375837685768477837684768475837684778577847684768475837683768376847682768375827583748276837584767E7881788177817780777F78807780777F757E777E767F7780777F787F777F77807780777F767E777D777F777F7980788079807A8179817980777F78807780777F01FE0A00010198A071897188718870887087718870886F876F887088718970886F886E866F887087708870876F876F88708971886F8670866F877088718971897188718971897188718972887088718A71897189718870887189708870897187718970887088708870887189718A717E71867186718671867085708571867287718570857186718670856F8571867286718672867085708571857287728773877288738772877286708570857186728701FE0B00010198B06C8B6E8B6D8B6D8B6E8B6C8B6D8B6C8A6D8B6D8A6D8C6F8C6D8B6D8A6C8A6D8B6E8B6D8B6E8B6D8B6D8B6C8A6D8B6C8A6D8A6D8C6E8B6F8C6E8C6E8C6D8D6E8B6D8B6E8C6E8C6D8C6E8C6C8B6D8B6D8B6C8A6D8B6D8C6D8C6E8C6C8B6C8A6C8A6C8A6D8B6E8C6E7F6F8A6E8A6D8A6C886D896E896E8B6F8A6D896E8A6D896E8A6E8A6E8A6F896F8A6E8A6E8A6F8A6D896D8A6D896E8A6E8B6F8B6F8B6F8B6E876D896E896E8B6F8A01FE0C00010198C06D8C6C8C6D8C6D8B6D8B6C8B6C8A6B896C8A6D8B6E8C6E8D6D8C6E8B6E8C6D8B6D8C6D8C6D8C6E8C6E8D6E8D6E8D6E8B6D8C6E8B6C8B6D8C6D8C6E8B6E8B6E8D6E8C6D8B6C8C6C8B6D8B6C8A6D896C8C6D8B6D8B6C8A6D8B6E8B6C8C6D8C6D8B6C8C6C8A6D8C6E7F6A8C6A8C6B8B698B6B8C6B8D6D8E6C8D6B8D6C8E6C8D6C8D6C8D6C8D6C8C6C8E6C8E6D8D6C8D6B8D6D8D6C8D6B8D6C8D6D8D6C8E6B8D6C896B8C6B8D6D8E6C8D01FE0D00010198D06F8970877088718871886F8870886F8870877089718A718A718A71887189718971897088708970897089718A718970897088708971897189718970896F897189708970897089708870886F876F876F876E877087708970886F8871897089718970886F887188707F6B8A6B8A6C896C8A6D8B6C8B6D8D6D8C6F8B6C8C6D8D6F8D6F8C6D8C6D8C6C8D6D8D6D8D6E8D6D8D6E8C6D8C6D8C6E8C6C8B6E8C6C8C6D886D8B6C8B6D8D6D8C01FE0E00010198E0758375837682748375847481758275827583768478857784768475837684778476847684778476847784768678867584768375857584758475847583748475827484758275837483748373827481748475827583758275837583768575847684758274827484767E7087708670866F877187728871887289728A71887189738B738871887188728A748A728A718970887189708973887089708771886F887084718772887188728901FE01000101C810728675877386748572867385738572847487738774877587748572867787748675897388748872877487748975877287748774877187738773867486738673867083748672867485718372867183718371857282728673847186758773877585738672857285747E7486728573837283768673857688758675887487758777877588748674877286768774887688748874887687748673867286728472857280768673857688758601FE02000101D8207A7C7C7F7A7E7B7D7B7D7C7D7D7E7C7F7E7E7C7E7E807B7E7B7E7C7F7C7F7A807E807D807C7D7D807D817F817D827C807C7F7B7D7B7E7B7F7C7F7B7E7A7C7C7C7A7D7A7F7B7D797B777B7A7A7A7B7A7C7C7D797D7B7E797E7A7C7F7E777D7B7F7A7E7B7E7A7D7A7C7583748174827484758376857986788677857685768479847783788575867684788578887987788476867887788474857684778373827282758376857986788601FE03000101D8308377837580758376827682768477847685778377837785788577847783768277847785788276827784788479847A847883778277847781758075807580757F768277807681768076827580758175817683768175837783768175847882768176827783768376827B7A7F777D7A7E7B7E7C7F7C7F7B7F7C7F7C817D817F817B7F7C807C807A7F7C7F7C7F7D817E807B817C817C807C7F7A7D787D777D797D7C807C7F7C7F7B7F7C7F01FE04000101D84087718771867186718670867188728A738971867188738672897288728972877188728772887187728872867388738873877287738672877286718470857085718873877288718770867088718671877187718871887187728671867286728771887287718770867A7D7B7E7C7E7B7E7C7E7A7E7C7E7C7D7C7E7C7E7C7F7D7D7C7E7D7F7E7D7C7D7C7D7D7D7C7D7C807E7E7D7F7C7E7C7C7B7C7B7C7B7C7A7B7D7E7A7E7C7E7C7D7C01FE05000101D8508B6C8A6C8A6D8B6D8A6C8B6D8C6E8F6F906E8D6C896B8B6C8D6D8B6D8C6D8C6D8C6D8B6C8B6C8B6C8B6D8B6C8C6D8C6D8B6D8A6C8B6C896C8B6E8A6D8D6E8C6D8C6D8C6C8B6D8B6C8A6C8B6D8D6E8D6E8C6D8B6C8C6D8A6C8C6D8C6C8C6D8B6D8B6C8B6D8B6C8C7A817683768576857683768276837782768477817683768276827782778376827682778277827785778277817682768176827680758176827A837682768377827601FE06000101D8608C6D8C6D8D6C8B6D8C6C8C6D8C6E8D6D8C6D8D6D896B8A6C8C6D8A6B8B6C8B6B8A6C8B6C8A6C8A6B8C6C8B6C8A6C8D6C896B8B6C8D6C8B6C8A6C8C6C8D6D8C6D8C6C8C6D8D6D8D6E8D6E8B6D8C6E8C6D8C6D8B6D8D6E8C6D8B6E8B6B8C6D8C6D8C6D8C6D8B6C8A798972877188738973897287718670857186718671877186718670867186708570877185708671867187718470867086718671867187728876897287718670857101FE07000101D870886D8A6F8870896F8B6F8A6F8B6F8A71896F896E876D866D8A6D886D886D876E876E876D876E896F896E876E866E896F8970896E896E876D876E876E89708A708B708A7089708B708B718D718A70896F8B718B708B6F896E896E876E896E89708970896F886F897A867187728572877488728871867186708571867086708571847087718570857083708470846F877185708470867288738772877288728675887288718671867001FE08000101D8808673857385718574847285728575847385728470877384728472837184708572826F83738470837083708572856F8471847286718572887385738673857286748673887487728573897587768675877386758674867386738673837185728672837286738473877B8473867687748773857285718772837281728472847182738571867185738271857184718571847384738570826F83718574847387758677857285718772837201FE09000101D8907D7A7C7B7F7C7E7C7C7A7F7C7C7B7E7D7C7A7D7A7D7A7B797C7A7D787B7A7C7A7D7A7D797D797D797B797B777A777C797C7B7E797C797D7A7C797D7C7E7B7D7C7E7B7E7B817C7F7D7F7D807D7F7C7F7C7E7D827C7C7B7E7B7D797D7A7C7A7D797D7B7D797E7B7D7C84768375817682758174817483748176847481717F7384747F717F73817581737F727D738073817381748374837484758277847682758478817481748374817601FE0A000101D8A0768276827781768177837681758275827481778276817581758074817480748175817481768176807581748173807581748176807582778276827683778279837882788478837884798478857883768376827683778378827682778079827581768276817582767D7F7A7F7A7E797D7B7C797E7A7C787C787C797B797B797E797C787A777A787E7A7C787C787E797D787A787E797C787C7A7F7A807B7E7B7F7A7C797E7A7C787C7801FE0B000101D8B0708671877287718771877187718770877287728771877086718670877087738670866F85728670867186708570867186718772867085738773877287728873877387718772877188728873887387718670867388728771877287728772877187718772877287727E7C7E7B7D7A7C7B7D7A7D7C7D7B7E7A7C797C7B7C7A7D7B7D7B7B7B7D7D7D7A7B7A7B7A7B7A7B797C797B7B7C7B7C7C7D7C7D7D7E7D7E7B7A7A7D7C7D7B7E7A7C01FE0C000101D8C06D8B6B8B6D8C6D8C6F8C6D8C6C8B6B8A6C8C6E8B6D8C6E8C6B8B6D8C6B8B6D8C6D8B6C8B6C8B6D8C6D8C6F8D6E8C6B8B6D8B6D8B6D8B6D8C6E8C6E8C6B8C6E8C6C8C6E8C6E8C6F8C6C8B6C8B6C8C6E8C6C8B6C8B6B8C6D8C6E8C6C8B6D8B6C8B6C8B6C8C6E8C6D7F768275827682738175827682758276827582758274817683768176817582768277827782758174817681778377827782778377827882767F758276827582768201FE0D000101D8D06C8C6C8B6D8C6D8C6D8A6D8B6C8B6B8B6C8B6D8C6E8C6D8C6D8D6C8C6F8D6F8D6D8C6C8D6E8C6D8D6F8C6D8C6F8D6D8C6D8D6F8C6D8D6C8D6B8B6D8C6F8E6D8C6E8C6B8A6C8B6C8B6B8A6C8B6B8A6C8B6A8B6D8A6B8B6E8D6D8C6E8C6D8C6D8C6D8B6D8B6D8B6D7F708671876F866F8570876F87718871887187728872887288748972887388728773887388738872887488738871877287728672877286728270876F877188718801FE0E000101D8E06F896E896E89708A6F8970886E876E89708A708B718A708A6F8C718A6F8A718A718A6F8A708B718B718B708B718B728A6F8A718B718A6F896E8A6F8A718B708A6D896E896F896D886C866E886C896D886E876F886F886E897089718B718C71896F896E896E896F7E718671856F867186718771887488768971877387728874887587728872877187748874897388748772887588728772867087728672877081718771887488768901FE010001018810778474857684758374847583738475827383758477847885768676847684768577887884798575837887778477847786778677867884758474827484768274827583758176817480708174807281748274827382778375847684768376857885768473837382747E7784768174817782768374837684788578867A847884768378867784778679877B857785788577847785788575847681758478837583757E768374837684788501FE020001019820758574857283738672847282738474867787778674867785738778867686748677867386758675867B87778878867786778676877385728474847484758373817283748375847081718371826E82728472837684768573867486768674867485738573857686737E7383758275837483778377867887778676867A857884748379847786758575857886788679867A867A86778477857682728174817782757F778377867887778601FE030001019830748375837582748373837281768473827684758678877986768575857683778778877585798878837787788777877785788575877684768476837383728276837683748373817381718172817282748175827583768374847583778574827483778577837483737D718771866F86708675897086748975897388738A758C7689758A75877489748875897489768A748972887088758A7487708471856E856F82758970867489758901FE0400010198407881778176817780778278817780768278827882798179827A837A827881798279827882798277827A8379827883798177827782778377827580778178827781768177817781767F758077807680778077807680788177827781788378817882788176807781787D7583748376827482768277847785778677847685768377847684768579867784768577847785758577847684778475847683758272827480768277847785778601FE0500010198507B7E7B7E7B7E7B7D7A7E7B7D7B7E7B7D7B7E7A7E7A7E7B7F7C7E7B7E7C7F7B7E7B7F7B7F7B7F7B7F7B7F7B7F7B7F7C7F7B7F7A7E7A7E7A7F7A7D797E7A7E7A7E797E7A7E7A7E7A7E7A7E7A7D797D7A7D797D7A7D7B7F7B7E7B7E7B7F7B7F7B7E7B7E7B7E7A7E797D7682778176817881778177827782788378837782788378837883778176827882798479837883788378827782768177817682778275817881778177827782788301FE060001019860817682768176837782768377857784778276827581758075827781758176817681768276827682768076817681778277827781768277827682768277827681768276817681778377837782768176827783778276827782768176817682768477817682768276817B7C7C7C7C7C7C7C7C7C7C7C7C7C7D7C7D7C7C7C7D7C7C7C7D7C7D7C7C7C7D7D7D7B7D7C7D7C7D7C7D7C7D7C7D7C7D7C7D7B7D7B7C7C7C7C7E7C7C7C7C7C7D7C7D01FE070001019870857486748473837384748575867585738274837383738373847483738473847381728373827382738272837382718273827483738373837385748574837484758473837584748675867786768675867584748676847484748374837585738373857484738375857B8375827684778577827583768275857782748275827482748074817682758374827480748173827582758074837582758375837685768479827583768275857701FE08000101988083758575837581758375847585778476847582738274827480738174827483738173837480728175837380727E718474817483748375857584768276857681748676837481748476857787788476837783768476857682768374857482748174827383758477877B81748676837586788374807481737F738175827481738073807482727E758173827380717D7281738276817482768175837381748476857C8374807481737F7301FE090001019890847384738673857583758577877485748072847483718173827383738372817280708172837282728071817082728673847386738372827481748574847585758574867688778574887788778875837486748674857584728173817383728574857381738676877B8575867684758376827384758476827480717F737E7282748274817480737E727D728173807380728174827483758175827585768377857B827384758476827401FE0A00010198A081748373847381738175867683778377837684727F73827381748174817483738272827381738172817182717E728172817281738174837687788677857683768576847484748476877787768678837484768475837585768474847383718175847585758476837B8770867186748672847188708671836F8371836F857287708670857085718673836D836E8272877184708470857186728872887289748778847188708671836F01FE0B00010198B0817881778078827881788076807881777F7781778176807781758177807680757F757F758077817780767F757E757F757F768176817781778276817783798377827782767F77827882798379847980788277827882788076807680767E758278817881788178817C8375847683768577827482747F74807583758274807485758072817481748275827381748173827582748374837483758275857582738277827482747F74807501FE0C00010198C07E7A7E7B7E7B7E7A7E7A7E7A7E7B7E7B7D7B7D7B7E7A7D797D797D7A7C797D7A7E7A7C7A7E7A7E7A7D797D797D797E797D7A7E7A7F7B7F7B7E7A7E7A7E7B7E7B7E7A7F7A7E7A7E7B7E7B7F7B7F7B7E7B7E7A7E7B7F7B7E7B7E7A7E797D7A7D7A7E7A7E7B7F7B7E7C8377837781788277817781778177807681768176817681778076807781768075807480748176817782758176807580768177837882778278817781778177807601FE0D00010198D0778276827682768277837682768276827682768278837782768277827782768277827682778277827782788277827782778278827782788276827782788275827882778177827782778276817682778175817782768276817682778276817782778276817782777D7C7C7C7D7C7C7C7D7D7C7C7C7D7C7D7C7C7C7C7D7D7C7D7C7D7C7C7C7D7C7C7B7C7B7D7B7D7B7C7B7C7B7D7B7D7C7D7C7D7C7D7D7D7C7D7A7D7C7C7C7D7C7D7C01FE0E00010198E0748474847484758474857384748372847585758676857586768675857685768575867786768576857686778575867384758576867483738475857684738473847483728475847282738372827283738473837484758475847383758574857685768574857583747E768475837583758275837582778476857683768478847685768375857784768477857985788576847784768375837683748276837583757F758375827784768501FE01000101C8107583768474837484748373817382748076867685758578867585788878867986788673857586778477867A8877847384778576857986798375857582758273827483758373827481738074827381758273827481768474837683788478857983748374837885737D768573817584748376847885778577867784768674857786788577857484758477857786758777837885788577867885748473827484757F768478857785778601FE02000101D82076837684778475837684778376827382778375837585768476857884778478857B8677867A83778475837A8779837684768476847A857683758376827483778376837881778274817382737F7481748175817581758273817382788275847783758577847683777E7784738177837883778375837C837683768479847A847784788477837482778476867B857D8778867B847983778276817683778375817580778375837C83768301FE03000101D8307285708870857186718872897486708772887188718772897389768A758971877389738972877588768C778B7388728872897188728671886F86728772877387728772896E847084718571866D846E8672867287728872866F8672887388748B758671867087727E7184728572836E847588758776887786748774867587758775857688788972877887768A748877867686748876867586708575867585727E758875877688778601FE04000101D840728373857484728576877686758472817486778775847787758776877584758475877887788776857687778678897786768574877486748473837585718171847583748574847182718272847383748474847283758676847584788775857685748575867587727E71866F84718570867388728A748A74897589748A74887388738874877288778A7688738B768A7487748872897388748770857486718571817388728A748A748901FE05000101D8507783768375827582778376827682768277837783768377837783788478847783778377847783768478847884798476837A847683758274827783768276837682778375827581748275827681757F768277827581758176827883788376817582768276837783777D7581748275807582768278857782758376847883768376837A85768376847883788478857785778377837683778276827483758176827680768278857782758301FE06000101D860797F797F797F79807980797F797F797E7A7F798079807980797F79807980797F798079807980798079817A817A81798079807980797F79807980797F787F7980797F7980797F797F787F787F787F797F797F787F797F79807980798079807980797F787F7880797D7881778177807781788179827782798279817781778178827882788277817883798279827882778178827782798278837781788077817880788179827782798201FE07000101D87082768177837682768276827781768277827680758176807681778376817581767F768276827680768276807580768176807681768076837781778277827782768277837781778077837783778277837782778377827782768276807683778276807680768277827B7E797F7A7E7A7E797E7A7F7A7E797E7A7E7A7E7A7D797D797D7A7F7A7D7A7E7A7C7A7D7A7D7A7D7B7E7B7F7A7E7A7F7A7F7A7E7A7E7A7D7B7E7A7F7A7E797E7A01FE08000101D880847584768776827481748376837484778275847481748373837581748074837481728173847281748173827182718072807382758274837682758377847686748474837483768376837685788777837685778576847785768576837481758374867583748276847B84778576867784758375817382737F72817082758374847483748173807383758373827380718273807381738375817386778475847684788375817382737F7201FE09000101D890847685758474817482778678837583748074827581747E7281738074837580737F7480738275837480757E737E7380737E74837582768076837480768477847682768276857684768478867887788477827783788377857686767F7485738075847582758077827B8477837784778577837781757E7480727F738275817480738174807481717F7580758073807480737D727E7283778376847782768376827A837781757E74807201FE0A000101D8A08270867289718572877288738973877486708471846E83708770857083708770836E8670836F8470846F846F866E81708570856F8572867185708470877386728873897388738A7489728A748A738A7589738872827187718671827087718671867187718671837B867387758674867281728372887488708473826F8070816F8070817384708373827283718070817282718573857485748473847284748A79817283728874887001FE0B000101D8B0837384748373847283748576867485748075847483738571837283728374827380718372847384748373817282718072837383728374867383748374837483738373857386778774847586768675867786768576867586758675827385738375857484738473857B847389738873857385738471856F817188728672877085738672837086718570846F836F836F86708370867085728872857385728672887685738471856F817101FE0C000101D8C0837682768377837682758377847783778275807681768174817681768175817480748175827681758174827580758175817581758275807482758176827783768377847783778477837685788477837682778477837683768276817481768176837683758276827B847683768375847681748274827682748274817681737F758274807482758174817580758175827481748273827582778375827583768077817482748276827401FE0D000101D8D0807A8079807A7F797F7980798079807A7F797E7980797F797F797F797F787F787F787F7980797F797F787F7780787F787F797F787F7980788079807980787F79807980787F798079807A807B80797F79807A80797F79807980787F787F797F7980787F798078807C8178827882798278817781778177817780778075807580778076807780768076807781778076817780768077817781778177817782778179817781778177817701FE0E000101D8E07682768277827582778176827682758279817681798378827682788278837A8378827882788278827882778377837682798378827782778176817781768177827781778377817681748076817681778177817781778276817682798275827882778276827882777D7A7F7A7F7B7F7A7F7B7F7A7F7B7F7B7E7A7E7B7E7A7E7A7E7C7F7B7E7B7E7A7E7B7E7B7E7B7E7B7E7B7E7A7E7A7E7B7E7B7F7C7E7B7E7A7D7B7F7A7F7B7F7B7E01FE010001018810748476847684758375847583758376817484738276857784778378847786768577857784798577847483748479867685768376857584778476827683738274857582738274857581758374817382768374847482778374837383758376857884768475847784747E7681748077817781798278827782798278837783778279837A8279827781768177827A837883778279837882778176827A8278817880777F798278827782798201FE020001019820778377857682758274827782788275817683768379857986788377847784788477857A84788377837A8576847986798579847982788376837382778175827681768377837381788273807680727F748175817781798374807583778477837782768377837883777D7582788079827A807680788179807B817A8479837A847B8379837981788376827A8479847E85788278827A837780778279807781778079817680788179807B8101FE030001019830778572837484738374837483738373837785758476857785768579867A86798679857785788575847783788577857784768477847783758376837683728174817484748377837582738073807281768377837581738373827785788578847684738473827583757E75817380788278817A827882788176817783768178847A857984788379827983798478847A8477837782778379837681778377827780757E7A8278827881768101FE0400010198407186718870887589738774867185738672867286728A728976897588738773887589738872887388748A7489768A72897287708772887287728972866F84718977877587728770856E836D846F877486718571866F86708671877488728874887185718673876E7E7284728373847484758575877585788674857988758676887787778676867686758777867488768575867486798876857685778576867480758575877585788601FE050001019850768374807583778375847583758273827784768477837885788576847785788476847784788576857785778477857785798374837684748375837483758375817683758275817381738073817482748176837482768477837482768375847882758376847682757D77827581758075827884778277837783778375847885788477847784778378847B857A867C8678827885778378837881768277807381747F788477827783778301FE0600010198607782778276817681768177817782768178817782768276827983778277837A83798376817782788278827A8479837984778277827982768276817782788277827781758277827581778276817780768176817882778177817681758277837882768277817781777D78817881788078807981778079817A827881788279827982798278817882778179827882788378827981788178817680798079807881777F7981778079817A8201FE070001019870797E7A7F797F7A7F7A7F7A7E7A7F7A7F7A7E7A7E7A7F7A7F7A7F7A807A7F7A807A7F7A7F7A7F7A7F7A7F7A807A807A807A7E7A7F7A7F7A7F797E797F7A7F7A7E797F797F797F797E797E797E797E797E797E797E797E797F7A7F7A807A7F7A7F797F7A7F7A7F7A7C797F787F787F797F79807A807A7F7A8079807A807A7F797F7A807A8079807A807A817A817A80798079807A80797F798079807A7F797F797E79807A807A7F7A8001FE08000101988084758474827585758475837584768275807481748075827583757F738474807380748475837481748173817480738373837581748376817482768377847685768375847581758676877884778477847882758375827583758475837482748175847684768475827B817783788277837682778276807681768276807681767F757F7681758176827680767E767E757F7680768076827781768277817882788279827782768076817601FE090001019890827683758076827884778377847583768277827683737F74817483757F74827580747F75817485777F738073807380757F7281748175817682778177847884778075827682788377847985788578837683788376827782758277837782778176847681757E74837C85778177827882777F76817882787D768074807781767F767F747F737F737E747E7580747C767F757F7580768276817983777E7680767E787F76817882787D7601FE0A00010198A0857686758375867683758475847585758274837282747F7381728074827381748372827381747F7282738173807280738275837582747F7683748676837583768374837484758477887887768477857784758376827583768375807484768275857582758475847B8078837982768177817780767E7681768176807581737E757E757F75827681757D7480758376807680768075817580778376807781778278817780767E76817601FE0B00010198B0877189728871887386728872847389738670887087728770846E816E846F856F846F84718370856F82708770826C826E847083738872857288738473847185738A7387748574897389768A748B758972857388718472867284708572876F8771887289748872897B8675837584748476807283728274837380728273817484738373837184748170807282727E707F7081718372837486758676857683758577807283728274837301FE0C00010198C0837684758275827784768476857886778175817380758173817483758376807381748274827382758273807483748173827584748274817483758376857681768475837685758478847785788578867782748277847683758175837682738074837482758476837B827582758176827881768275807581778276817483768075807482748075827781737F737E7381748175817582758176837681778277847A817682758075817701FE0D00010198D0817781768176817683778278827882788276817580758176817581778177827781768176827681767F7580767F7681757F7581778277807681778377827682768076837782778277837883788378827884798176817780768277827582778076807682778277837B817781788178817981788077807780777F777F7780767F767F777E7780777F767F7680767E767F777F757D7680788279837880788278827A817880778077807701FE0E00010198E07F7A7F7A7F7A7F7A7F7A7F7A7E7A7F7A7F7A7F797E797E7A7E797E797E7A7F797F797F797F7A7F7A7F797F797E797E797E787F797F797F797F7A7F797F797F797F797F7A7F7A7F7A7F7A7F7A7F7A7F7A7F7A7F7A7F797F797F7A7F7A7F797E7A7F7A7F7A7F7A7F7C807A807A7F7A807A7F797F787E787E7980787E797F787E787F7980787F7980797E7880797E78807980787F7980797E787E78807980797F7B7F797F787E787E7901FE01000101C810798177807580768077807982798076807881798279837882798279817A8279827A827882788078827A827A817A82788179817981788079817880777F767F768079817880777F7680768077807880777F748078817881768076807982788179817B8177817780787D7B7E797D7A7E787E7B7E7B7E7C7F7A7E7A7E7B7E7A7E7B7F7B7F7C7E7A7E7A7E7C7E7B7E7B7E7B7E7B7E7B7E7B7E7B7E7A7E7B7E7B7E7B7D7B7E7B7E7C7F7A7E01FE02000101D8207981767F77827882788376807A8176807A8075817C827B83798378857F8378827982778379837A8377817C857B86798277827A837683778177817582787F7480798275807680777F7781787E747E7680767F7B817982768177817A8279837982798177817880757D787F7B7E7A7E787F7A7F7B7F7C807A817A807D827C807B827E837F817F807D807B807F817D7F7B7F797E797F7B7F7B7E7A7F7B7D757C797C7A7F7B7F7C807A8101FE03000101D830778176817982778177817880798075807A8178827881788177837A827B837B837A8277827B83788279827A847C8477827982788178837A8077817780768076817981768075807681777E767F757E788077807780778178817A827A8178827A81788173807980767D7B807B7E7A7F7A7E7B807C817C807A807C807B7F7A807C817C7F797F79807B7F7E817D837D807A817A807C807B7D7B7D797D797E7A7D7A7B7B807C817C807A8001FE04000101D84074827884758478827381738277827581758476857A8476837886798576857684798579867884778479857986798676837584758375837783728478817481748176827785748173807380727E75817782738278837483758273807A857A867484738374827481737D7881767F797D797F7A80787F7C817B807A827C817A817C817C817B807C7F7B807B817B827B8077807C7F7A8077807C80787E787F7B7E787C7A80787F7C817B8001FE05000101D85076827681748075817682768074817581788278827982788379847A847A82788578827883788379837A837784798477847B8578827883768176817781768275817783768276807582767F747E747E758277827780758277807681798377857582788376807583767D7B80787F7780797F7781777E7B817B827C827A7F7B837B827C837B837C837A817C837B837B837C837C8178807C80787E787F787F76807A7E7781777E7B817B8201FE06000101D8607981788078807880777F7680777F77807980798078807A827B82798178817B827A81788078807A817A8179827C837981788179817880788079807A81767F77807981798178807980777E757E777F787F768078807980788077807A81798178817980777F7882787D7A7F7A7E797E7B7E7C807A7E7D807D807C7F7C807B7F7A7E7B7E7A807C7F7A7F7C807B7F7C807B807C807A807A7F797E787D7A7E7A7E7A7C7C807A7E7D807D8001FE07000101D87079807A7F797F797F7B807A7F7980787F7A80787F7980798079807A807A807A807A807A807A8078807A807A807A80797F7A8079807A7F79807A7F7A7F797F797F797E787F797F787E787E787F787F797F787F787F7A7F797E797F7A80797F7A7F7980797F797F797D7B7F7B7E7A7E7A7E7B7E7A7F7C7F7C7E7B7F7B7E7A7F7A7F7B7F7A7F7C7F7B7F7A7F7C7F7C807B7F7C7F7A7E787E7B7F7A7E7A7E7A7D7C7D7B7E7A7F7C7F7C7E01FE08000101D880817780778077827882778077807884797F777F7681777F777E777F777F76807780787F7780777F777E777D77807780777F7880787F7881797F788078827980797F78827883798278837A817983798178807880788178827984787E767F778178827780778177827C7F7A7D7A7E7B7D7A7D7A7E7A7E7A807A7D7A7E7A7E7A7E7A7E7A7D7A7F7A7E7A7E7A7D7A7D7A7F7A7D7A7E7A7C7A7E7A7E7A7C7A7E7B7F7C7D7A7E7A7E7A807A01FE09000101D890827782778379817683798279807981767D777F7580767D75807682767E737F767F787F76807683767F757D747C757D717E75807883788278847983788178827981778076847A82798079827A837A807983787F777E777E7780777F7680757E777F78827982787F7C807A7F7B7F7B7E7A7C797E797E797C777C777C79797A7C777D797D787B777C777B7778757D787A787F797C79807B807D807B7F7C827B817E7C797E797E797C7701FE0A000101D8A0817880778078817880778178827880787F7681767F7782777F7580767F77807780787E7581757C757F7580757D747D757D7781778277837980787F77827A847980777E77827A827A847A837B847A807881787E78807782768078807882777E77807882787E77807C807B807B7D7A81797B777C777D7A7B787F797E797D777B797E797E7A7F7B7E797C7779777C787B777B787F7A7F7A7F7B7F79807A7E7A807E7B777C777D7A7B7801FE0B000101D8B0817483778274817583768376817685767E748474807580738073827681757F737D74827481747E757F748274827582737E7381758075827686788175867885778275807585778879847787798576857782768175837785748475817383758075827583768277827B81777E7A817B807A80797D7880787E777C777D787D777B787D797E767E79807A7D787E787E777E777D777A777C787F798079817A817A807D80797D7880787E7701FE0C000101D8C08175807682768076837684788279837781768074817581767F767F758375827580748073817580747E748073817480747F7581747F7584788377837581788175827783788378847884788479837A8377827580788277817684767F7483798377827682778177837B7F77837A817980797B78807878757D797F767E777D787C767D767D78807980787E757F777E777D797E7880767F757E787F7A7E7A827A807B7B78807878757D7901FE0D000101D8D08178817880787F7881788079807880788178807880787E778078807781767F777F767F787F777F7880787E777D767F7880777E7680788079817880797F7880787F7881798279827A837A8179827A8079817A81798178807881797F788077807880777F787F78807C7D7A7F7B7F7A7E7A7D7A807A7F7A7D797C787F7A7C797E797C797E797E797D7A7E797F787C797D797C797F7B80797E797F7B7E7A7E7A7E7B7D7A807A7F7A7D79010100000101D8E080797F797F797F797F7A807A8079817A7F797F797F797E797E787E787E787F797F797F787F787E787E787E787D777F797F797F7980787E777E798079807A80797E798079807A817A807A8079807A807A8079817A807A7F797E787E787F79807A807980797F797F7C7D7A7E7B7E7B7F7C7D7A7F7A7F7A7E797E7A7E7A7D7A7E7A7D797D797D797C79 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 32 32 0 7C797D7A7D787C797E7B7D7A7F7A7E7B7F7B7E7B7E7A7E7C7D7A7F7A7F7A7E79 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 2503 2503 0 02B000000103000900042004300000000004030009001820043001804F00040300090020200430080080000403000900242004300000FF0104030009002C20043001000000040300090040200430FF030000040300090044200430E6030000040300090048200430E703000004030009004C200430E8030000040300090054200430003E010004030009000021043000000000040300090004210430000000000403000900082104300000000004030009000C2104300000000004030009001021043000000000040300090014210430000000000403000900182104300000000004030009001C2104301F0000000403000900202104300100000004030009004021043000000000040300090044210430000000000403000900482104300000000004030009004C2104300000000004030009005021043000000000040300090054210430000000000403000900582104300000000004030009005C2104301F0000000403000900602104300100000004030009008021043000000000040300090084210430000000000403000900882104300000000004030009008C2104300000000004030009009021043000000000040300090094210430000000000403000900982104300000000004030009009C2104301F0000000403000900A0210430010000000403000900C0210430000000000403000900C4210430000000000403000900C8210430000000000403000900CC210430000000000403000900D0210430000000000403000900D4210430000000000403000900D8210430000000000403000900DC2104301F0000000403000900E0210430010000000403000900A0200430EFE100000403000900A4200430004000000403000900B0200430000000000403000900C4200430140000000403000900C8200430000000000403000900CC200430200000000403000900502004300002A8020403000900A8200430FE210000040300090004000038000700000403000900080000380015000004030009000C00003801030200040300090010000038010702000403000900140000380C0C05000402008005FF8307205F820720FF8307205F820720FF8307205F820720FF8307205F820720FF8307205F820720FF8B0720608A0720FF93072061920720FF9B0720629A0720FFA3072063A20720FFAB072064AA0720FFB3072065B20720FFBB072066BA0720FFC3072067C20720FFCB072068CA0720FFD3072069D20720FFDB07206ADA0720FFE307206BE20720FFEB07206CEA0720FFF307206DF20720FFFB07206EFA0720FF8507206F840720FF8D0720708C0720FF95072071940720FF9D0720729C0720FFA5072073A40720FFAD072074AC0720FFB5072075B40720FFBD072076BC0720FFC5072077C40720FFCD072078CC0720FFD5072079D40720FFDD07207ADC0720FFE507207BE40720FFED07207CEC0720FFF507207DF40720FFFD07207EFC0720FF8707207F860720FF8F0720808E0720FF97072081960720FF9F0720829E0720FFA7072083A60720FFAF072084AE0720FFB7072085B60720FFBF072086BE0720FFC7072087C60720FFCF072088CE0720FFD7072089D60720FFDF07208ADE0720FFE707208BE60720FFEF07208CEE0720FFF707208DF60720FFFF07208EFE0720FFFF07208EFE0720FFF707208DF60720FFEF07208CEE0720FFE707208BE60720FFDF07208ADE0720FFD7072089D60720FFCF072088CE0720FFC7072087C60720FFBF072086BE0720FFB7072085B60720FFAF072084AE0720FFA7072083A60720FF9F0720829E0720FF97072081960720FF8F0720808E0720FF8707207F860720FFFD07207EFC0720FFF507207DF40720FFED07207CEC0720FFE507207BE40720FFDD07207ADC0720FFD5072079D40720FFCD072078CC0720FFC5072077C40720FFBD072076BC0720FFB5072075B40720FFAD072074AC0720FFA5072073A40720FF9D0720729C0720FF95072071940720FF8D0720708C0720FF8507206F840720FFFB07206EFA0720FFF307206DF20720FFEB07206CEA0720FFE307206BE20720FFDB07206ADA0720FFD3072069D20720FFCB072068CA0720FFC3072067C20720FFBB072066BA0720FFB3072065B20720FFAB072064AA0720FFA3072063A20720FF9B0720629A0720FF93072061920720FF8B0720608A0720FF8307205F82072000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A0008001003181C1003181C030009000020043080000000040C000100030D002800C82004300000000001000000FF00000000FFFFFF01000000C820043000000000011C02B0010000000E001000000101010100011F08000000000000010F000100011000010001110002000001120001000105000E000C20FD00FFFF000000000208000005000E001020FD00FFFF00000000000500000300090004210430010000000403000900082104300100000004030009000C21043001000000040300090010210430010000000403000900142104300100000004030009001821043001000000040300090044210430010000000403000900482104300100000004030009004C2104300100000004030009005021043001000000040300090054210430010000000403000900582104300100000004150008000000000020280000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 45056 45056 0 01FE01000801C810796866716359717A6E6E72747476696D68696E6C76856B71787C7B7B686B6A808C726D73706B666A71756F6C7B8279736F7574727671836B6B747573716A6F71757976746E6A746B72847C6D7A796C6B6B63636E706E6A7F77717A717A736F746B7779767372715D727C65656D7168807477727371797D7D7E686D73666A767C7380797174676D6F75747D686E727287827A6E7078796A68756F6D6C736B696D7477727371797D7D01FE02000801D820716C64667D6F6F646A6E776D6D786370786C6A786C6B766B737474776F636E78787A7A6D6765676F636D71716A757F78636D737A796E68777164697473726C77726F716E6D60716B6B72717A7B706F6F6C736C6D717670756E6D6B75716E6C6D66796D746D73716A6C6675736E6F786674727379716B706F7A66716E746F747073697277776A6A6E76706C6D7C7C706C6F6562646769737172736E777784756C74727379716B706F01FE03000801D8306E62686869766E706E69696C717074716A6E6D727D6B6E806B786E7573716B64696B6B5A63826F7C7A77756F64705E756E75787E6C6E65616470757474737B7567716A6466736971697D7170796A5D6F7076677169797679667071727B6B756E677171647869716E75757C6776707178746D76645E635D67736663746E757A7368676F6D7371756A6D74686B7C7C7972686C70717160656F77767B7868696A6A746D76645E635D6701FE04000801D840576D5B58667170776E7679796D6E70776C79636D7D6469685A6871707576736D5D72767773777768647D747374715F626F63606D71635E686D70766D6876776E6C6E6E6D666A77686E686A687975717578746C63636B676268696B70707D7175776B7772726D6D647067666F746E7270777973695D5F5E6C676552626C7875637F7A756F6772686F74797B686C606D6E6C6F6E5F6D72837368686B5F71716F6E777973695D5F5E6C01FE05000801D8506F6F715E5C6A6F6F68706A62697258596270737378786A7D7165686767726A646465775C606F6F6970826A6874766B666D6C6B656D646B716F6364737276707F5E64626A73746E726F6879756360697270746D777B6B6165716D747371736F6B6E68726C68666B72646F6B6D6B6876766F746775736C7A6E715B6F72696E71716A58657271626E6F65576F6A5C6F6B7174726F5F54656671746C78766F596B6D6F746775736C7A6E01FE06000801D860726C6B716D6A6F816E6A6C69646866716F706E746D696968686766776A695F6B6B726A6B6B66646761676C6C6D6D676975676F6667696D69696E7978706F7B706C646B686A7072766D757068677266656F726A6861606D686568746463678067686F6F686475726871666E786F6E67666E5C6A615B67707C76686C75625F6768626A675E68737065756171776868726B6767706F7171786C5F636E66656A67756E5C6A615B67707C01FE07000801D870726A6C68605B677367616773636C7666696D6A61646F6A74706C676767797565606C69646C72696B5B586864676E626A73706771666B726A6C6C756F6372726E746B686672655E6B66685A5C606671716662676C656266636A646B656B6D6669725E65736A715F706273766F756C686767665C706E656C7268676B7B7B68636A727272626A6D657064696E6C6B6E6A686A5B63625A677859686A65776965677467665C706E656C7201FE08000801D88070806C5D636D706566626560645F6A656B6968716F6B6F6A6460676E786B6C695C6D715E6871716D64615B5B5F666A746C786F767466616C6D69606D766F5F655F626774706D6571726D73606565646D6A675F666261776663656B6C69616A62646C686662675E6D6A636B6B6C6A736B646A5D675F706F5C66757070666A5F5B6C6B6F6C636364606365726E687278766B636B636A6A5F75696B656866616465646A5D675F706F5C01FE09000801D8906A6A6C626A6B6E7469655964616E6C737265745B646E6C73586460616A6F69686D68636C705F5F5C66616968696E6E6D686C68636A6A5F5C6C676879615F5D6B6F5F6261595E676B62685C6F6E6D68656F7077646C625A6067586B6C6861625F575F6C676D605E636C6C6470716C73736D696F616B676966655F625B57625B756D6A6A65696E6670625C626C686867606A60645C64575B64625B675E6B74625E6D696F616B67696601FE0A000801D8A05960646C6562645B6960626461645F5F6D636E726F6C6D66636A69675D656866656A5E5C665C626A6A6B756D6466615A65636362666C6C6A68576B67615B66656B6E5F5C5C66657775726D6A665E6E6D767767635865616A63505B6D666B616D617565666B7065605E6A65827370686861665A5867616C636D6A675D636A6168625D5F5C5C74766556605C655D5B606D5F6665645A585962657263615F616D6861665A5867616C6301FE0B000801D8B071686C6A6E7482635E545E5B567066636160596973705D5C5A7163625F675D6B666A62675C676E6F655F6463665C5A696464665B5667635967655F695B6265596369665D6F605C63635664636563596A6E5D646A63716B726765626F7372615D59575C6E6865676862605A6168606862646D6267666263665457576873757566676471635F6A5866576466625D585D65707562695B646C636762566361606157646D62676662636601FE0C000801D8C0636065576467615D676766637066696E606159605F575F5F56565E6666657160636B686D5658605F5D635C6B63626765666760616F665D5D5F7564615F5563656361666D687D776D6D5A6E67566360605E6E6A696763616965635B5E5C655D63616D5B6F6A5A6D61686D706C676667646463636F5D5F6360616E5255596B6A61595C6267635F68726460515C685F6A605F5C665A5F685C555A5E5A62666B5E606463636F5D5F636001FE0D000801D8D05F5451636C606757605B59726F686565616D5C5E656B6F5E615C6066646361605D60595C54596261645E625E606B7261665B57605D5F615C5A5E655C5B65677164645B5C5A60595D58545D6D5F655C69595A605E6C736268655C646259595B6665666F6B695D545C5E6A69625E607466646F635B6068605B6355666C6375615C605F6C685757546056555959606663665F735F535B616B625F6F6360626D6770646F635B6068605B01FE0E000801D8E05960676A6D5B585B675A6465626559516165615D686C6D596057655754645B63605E5C6A5E74755A53576367565B585A5A5E6353535B6866626C62685D58575567705F635C57666F6C69656E5E535A5E6363607062595C61646D6C696364666364605C5A4F5E5B59655D5B6172645E52595D59686B7468696A6060695C5F58636270705F4E6156615A555B5D636F5E5C5E69665E575C5B635D666861696E5660595D59686B74686901FE0F000801D8F0655F585D50555A6A766A685E5654514F5D67586C66665F5B67635D61615F5B666461635B606B6D62665A5656595F5E5F62655D5E5F5953545F5D5D585C5F626465576058525558626055565C545B61636264525C636C686C67685E615B6762585E55544B62605C655B606364675E5B5858615F5B5D625F69575D6E685F605B61685C5455695B57545E6C625D5C6F5F685657635B645E585660646165715B605E58615F5B5D625F6901FE10000801D8006162666A565E55615C616963695B5459636160676E5E5C5C5C5753494A6365645C605C58595F656659585A5D59675F5A565B695B585A6B665D5E625A58596B62525B58685A6658685F656B5C665D505066566559545A5E564D4F54625E5A58686465535A616058535B6457565A5967666E5558697169565C6159575764585D5D665A5B63625B5B5358585956684C555D6A786D6458595F61595656666164646E6E5558697169565C01FE11000801D8105D545F67626A665E615E5A5C5960645D5D5B515D686C5653625E56575655525F6C75635C50656166595A676E54544F5F6F54516161574F49525D55585F58676558575B58525B5D5E5F5C685E525866646A625F6757515B525B536563665458565A63646162666E66514D4E606955545E5958645958685A5C5B6A665C5853635C5A5E524948585E6061585762594E5F6E726458575E5E565A605C5C5E5B67585F5958645958685A5C01FE12000801D8205957545B5F66605E5C5754575D5A5B6965616048526A6366585957606851575C565D545C5359605F5C54575360625E5A58495D5167625C5B66665E666459585A635F5E5456746155605F545B635E515D4E4D605966705A5C51575656615D5A555954575F5F62565663545F57656559584A526259515D5658685C535D5755525E62575963646458645A595D5C4553636265665B636467584D4C5B4A535C5360614A526259515D565801FE13000801D830586354595B665F575B5B505956575B615F5D586068615F5D57555C584F505C5B5F5B524A5D556764635A5E5F5A5752535B59645B62544A546261555A4654575F5F61635055545B5D6A6466605B5153515D584F5C626958505F4C58605E5D56556458505E655A535A57544E495B6558585F5A57555757515C5A655B58655D57595A5C5B5A52545C5C5C57545B5B505258535D52695F574B4C4C605B5C5D6366535F5A57555757515C01FE14000801D8405552554C4C555851555E504C53585A59505458574C585C674F5E565D5D584E5459595F5A636B61524E4F5560505F655F516254594E5751544B595E646C59554F594855575E645A5B604E58605B645F605D545C564F525A62655B5A554E5B566052505458625C5253575B585B6363645345565956605C5352555C5A5F6654554F4E60505B5463595A5E55575F535C5E645B655C595A5A605B524B5B5154575A5845565956605C535201FE15000801D8506759515E58554B5962605B5B4E575E5C5B5A5C51594F4C5F534C4D54474C5A5A6364635B535E56555A5552565B5E525957594B5153585A5F575359525D5F54566354564F5D5A515249505A655C57574A5D59605D555751574F52424E57615F624F5A614E5A685A5F62635F5F535358524F5B5F5156615B5658555C5A565C576460604E515553514C51635869515F4D5155584E504B4C56585363535C58564E674F5B5F5156615B5601FE16000801D8605E615E5C595C5C534F585E565E5B5751464E4759465067555C645A53585A50504F5552514C59535254505B61695A52525351575F5958575C605F554F54545A5B5746434F55524A605C6E5B5E60584B50575B4F50525461585B58554F4C40474E575C5D61524F504857625B534A5E515C57504D485A6049575F5E535660605557535650504B4B4C5C535156595660504F5C535D505349565853505152695C504F57504D485A60495701FE17000801D87059555D6268645250514C5D5B56585145604F565A5F61544B575059544F4F505C5E65525248473C5E6259544D55535551434F486854565258575059534A57505258554E4F524F4F50515A595B59534E47505957545455515D6C5A52493D525F5A555E624E5B5F5664544E595E53534C6250525157605D4F52525456524D56575362565B625E4A524D485248465152525754525B5B635F5360584A54505B50574650525157605D4F5201FE18000801D8805E5E5150485C494E585B595D4D49525750494448585F5C50545A54504A4F605B585D5753434C5150484B524C4F506163524B4C4F4E4F4F46504C59565C5D5A504B5D5D53505952544E50494A566152585D5E5150505150514D47514B524C4C5B5556585458575E554F4D524B6052605650514B5452584850405059515956525B4B5360575343484D6055594F5958495A5B5B575C52605F4F4F524A56525A5B5450514B545258485001FE19000801D8905B4946463A48534C45435B4A515D49625D5353514C54575D404A4B5C5562464D576052634E514549495A5355584F5B5549584D4E4E59565E4D525348484D484E5D564F59595A50474B4E4F55484E44555D5A52585A5D5E574F51514E53605A4A5B4E51485D56505050585F5A57554F5A4A5D5D4F4F5347584553514952484A4C494C524D51584E565053594F564B515C555350464D564C4F5B5E565C585955474A5D5D4F4F53475801FE1A000801D8A0444E4954574A584C404B504E53525A5451575C5F5D54525843594F585C58594B4D525645554A4C4B58474A59585B4E46515D474F58504A46514A4A5258504E4653564C4C51554B4B504C4B50575D5A535A4C4A4C4C585B5D41495A4C4F504C50404A434F58585554494E5353454F555C4D544A514B5F504C544F5F604C4F4B4E4F494C4A5A53535956464B47424F4C51555A5B4A494E464D494A555D56555C494D544A514B5F504C01FE1B000801D8B03B3E464F575054554F65504F45434D5366555956525647515A575E5653574F4F4B504E4F544A514B4A4D4C50524F3F504D44524F494A4F504B5F5A5756504A60463D344D545B514F484A48504F495458494A3B5452504950484356584D4F474F5545554D524B4953545562554F585D554D525B505950544F52515A5E4E4A4A564B484B6155564C4A58444D544B4B5E4E55525E4242564C4D44434848545646424D525B505950544F01FE1C000801D8C05B514B4C4E4D4E504C4B51554C4C4757535146554D424A574D505452474D5A565F424D5C504C464949504C4B4C4F484A554E4E564D48474F544C45514E5657564C4F4F49454D4E555348554F4C4D4F4B4B3E434C554D4F52464A41585E5950504646493F415855514C44504A575B495157644747475952554A444D4F4C494A434D535E504C4A4E4D4E484F505345555454574749565342514C58514B5B4C444E576447474759525501FE1D000801D8D058584A493D4B4F5D59544654464E515F47484D47434A4846493F4D4B4947405152434442444E444A5C535F64484F5358554C36454B464B434F5E58565854535742414546504A4C493A4D574C5B514C423D4C4E554D5554534B4B4B484E4F3C484E47404B52594C53494C425150465046493E555A594A464C4F524B42574B514D424A3E504B534C5152454C5847524744454F48534846514C4F4E4654585C4856493E555A594A464C01FE1E000801D8E0404B4E5C5A5951544C4446574A44493C4948534C4F43475C5253564D4E484E513A415C4D4D4944484E505650464A4D3B4141544E53553D3E3B45483B46514D4E594B414B535255504F3B444D5C4A48444C494B4953454848484753524842424F4940514C524E584F584D4853525457423348524C4D42444356544D4B4D4F54494745464E4E4E5B494F555D4D503C4F4E57434B4E3D504A4F4E56464F4242504E3348524C4D42444301FE1F000801D8F0573D4C45464955485044404F4E514A49414D4B4E4C53444F4242454C4156504B4F493C3E49505350434A484B564D4750474C494B4D49525056544B4F4C484A3C3E4C414549453F4448514B47504E504C525254544C584F5A4C3943424541474F4F4C4554553E493E435F595F4D48485359514047483B493F43414648504F403A4151514149504F4C4439475648494E4552474E47474B47525542424B584F494A59514047483B493F01FE20000801D80050463E454750373B545E59564B414B443E4F4C4A44414F464D484A565546464A444E59454B4B49434E4E414B4545455343474358494D4741504438535B53474547424D4F4E46504F403D485254584E3E46524553474E4E493843373A424D48504D4A42465643464E494C443E3C3443576055483E4C4754534F44465049463E41403F362E39444B4C504F4C514F3F49525250523C3C46565D504E4A3C4B4B49466055483E4C47545301FE21000801D8104C514B494644414C43573F50504849524A4645454846454349414B494C4045514D5A5343494E453F4A53484E4B3C4B41454B465855584D4D40404C514A554F44483E434C4943453D3C40564244444C49384943484750514E48454844574B5844453739544B524B39504E4F43443F394841434B3D42424349524B564748443F475556524F5B3F464845444F483E453D4D3C4A544B47424D50464438424B454E4541434B3D4242434901FE22000801D8204C50424B3E39413B494E4E54534C414D463B3F494D415149434D363942493B3C4E5647444553534E4B4A3D4F414D3E4D50474841473B42573F444A4A3E42424443594D4F4F4D494546424545434652443F464C46443F433F484844433D544D3C534F4C504B4B3E444A4A4B4C4B493B4D4B4A454939414050453F33423848494139464B4F584C4C4B45423A374C4E3F404E4B4758524947402D434B4E4A38393C4B4A45493941405001FE23000801D8304A4146433D49444B42374B41484444374C47463E364C434447374447373F4E4B44454C4D4A443E4044454D5444444B4F34434A3D404C4E4843443E48484032394941414340414C4B4342414E4A45474C45434A4546453C423E4A4C43394436353E443F41494641504F4440404944473B4B4B4B4749474947484E56444C46414A3646433F534131343F44463F3739434B50484940364E424747453C444840414E4B4B4B474947494701FE24000801D840564F48463F484150503D4C4A4D4E4A473D3647493F3F3E443E3D33404A443A3F38464F4C454E4C4D44474A3E484243434F4A4C4343534A3E4030414646423C454D4D463D2D3B4143504D3C464B52463D4738403942374046423D3D3A3E474D49453A4C4D4E43494D47434D423F4D49422E3C303A453246473D3B46454840504547464743494E414A4341423F5047484D3B3E4037454A43454B5A5046494144402E3C303A4532464701FE25000801D8503C3A3F333C3F46453D3E3E4D40423F3A474D47474A4E4A4A4B3A4341494342443F3640364B4541473A403E434F4450524E49403B3C443F3B3A3D483D4956504544443C3D3F44453E42343E4B50433950584443322E433D3A3E363E44504E46463D393E4A41424546453F3D4E3D42424A4742484334413E4648433D4749413F464A503849363B493D4237414A3F3A453F3D4951484A49402E323F4C3A4539414C4742484334413E4601FE26000801D8603E4044453D39373A4A3651473F40363E40423C434935322E323A3F42443E45414A5239434047443E3C4C3F3F4E4B413F434C4D453F44474B4247493741474D453C424048455149393F413C424C444946403D3D48364A4E423E38453E363644454E423F354047464B2B3B464131423F4A3D474A4739423B473B4646394B4B404343473C443E3D40343E4547514142442D41404136363540384142564A4E4C4B493D474A4739423B4701FE27000801D8703B3238383C4840403B3E48454F4F47483749363E3D4943353734243F3E434B3F373C374352494449423E46323A494247483C34493544403F3B3D3E463A374843453942424142503F413D31454B3E47443D4A514C4A3F4137323A3E384445434032343F3F3C433C4136344251373E3E3C3B3A4045444449434736364336393A4447444143473C3846313E4A3C444639333E473B4B4041373A433F353A4443423B3B3A40454444494301FE28000801D88040433D463B38393D485649423F454A402D3A35324051402D38333F4A3B3C4A4A3D402E3F3C40404A423E49453F4A46313944423F2F3B3C35394642464434363B2B3C3F363B3F383A3B383A454248433D3F47533F34383C3F3C3F45424643453C3E3D34433B3D434031303536393B3C3B4B363B49412F3E41413C414D4D4C3D3F464241444C40352D3B36413C40403D39333B44484941393D383F4749363B31494B363B49412F3E4101FE29000801D8903B383B2B393539383C423C3E3C3E3E443940364939323F413F3F413D4D484F4A413938424A414237413B3534483E3F533E444338343A393644413D442C2E38403138433F3536333E3C42434E3D463E3F3B393A333D3A3F41483E393A3636373B423639404D50433E414A343E3D31383A3B3A35434441424034403E3D3E424E3E36393F364137323E40363E3E3E3F493B47413831333E3C4147393D3D4645433A3B3A35434441424001FE2A000801D8A03F32303843444A3C3C2D3C353A302B43454234493F37384039423E453B393D323B473A413A40343A36363F3D3C383840423536393B3D37373A2E3B43344435383A43415358554C3C36352B392C373537334039374033403F40443F4741423A40413D414A443C263E4D49373E4544402E2F342F3A394547393540343647453232384842444037323A42413C4045393E202C3231443C3E3A2E2D304149473D333A2F342F3A3945473901FE2B000801D8B0374740393E343E313B3E323E373E3A2E3136343F40423A40363A3E3E4543394338392339393F3E3A3E3C3B4234392D393E313D323945394D413344403A3F3A33313640413A3C393B31413F3E333544343D373135313141453A313B353B423D423C3E443C353C3945393B303640343647333E3A3B43353C36374541393B3733333F453D2D4432393F3A453F3A373E3B3E3B47443F33353F44363E3E3C45393C35333E3A3B43353C3601FE2C000801D8C02D3F3F3933313C3E3B373E413238383442453D373A34403E413C3C362E3930343B353B3C41363F36372F38354B3D41342D32373532303B37403B48343333373A433437373343312E34374446363D3D3A423C3443393E3237383B37373241433F3B2A312F3C383F334E42423A412C40433C413F39393C35363136352C2D453E384B3C382F3F483C2A2D3B2F3B33363A403F433C3239363139363D3331333E46403C413F39393C353601FE2D000801D8D03940352F322B2D29333E484543432B3439322732323C2D303A4A3F393B35393B403A2D36413B3E343C393C2E35402F3538323A2627313D4A3C3E404042453D3A473A383842443D3936323636303B3B30383C41342F2F304042462F322D363138363B3B2A343D39303B37404528243430363D4439353B44383A3F353A362F353A40422D333D393A3837373A493E3C393A36283637343D34412B3B35413B302C38363D4439353B443801FE2E000801D8E028353245373642444F4244393838313A392A3137363937293B392F3842322D2331393C3C3D3439373A3E312A2E2C3F3A373B423F4038372F2C352F3737372F383F37443B37302B332C324131353E333E43402E393A33393C332C323A3D373C3232353B3E333131313D312A3F3C2B3B3030292A3D3F42433A3B2940393529292537342E34333339292E37423E4030383A4245423B362F3029353B444A4538323330292A3D3F42433A01FE2F000801D8F04940362C393734311B37424342352B28402628333E35333A3B353D3B3A383B383B3931393E2F2D2E3A2F3733342E2C2C302B293026362C2E31383D3432383D30322E37343B3E36302D333C3B373A35342C2F3A37403D433D3E3D2B38332B3933383C37353634332E2F393A39393A3E3B383A3A32272F2B2428403B354034263B2F4335353238373C353F4125394334323B4937332525313D393E36382F453833383A3A32272F2B2401FE30000801D8003B342D2B3C3F3B33313C293B3D353434363B323732302533334845392B2A302F2F2938343C3D3A3338383D31303831292C3534353B243C40333334332926323E2F313239322F334B3940293D3A33293131383432374138403A3328353633302E37393C3D2C2E3333332F33322F27293439273A3C3424323B2F323E3E332F292D313534343C3A46433431322C392C2C2E37393F3A3626302F35303A363B36333C39273A3C3424323B01FE31000801D810383A3F2F2A312E2F39382E3035382C2B373721332B2E31352D303C363636393C382E32363E3B2E2F2A2531262D2C33393B393A30323A413A322C1D24293D46332128352E2F2B33383A3239302A2939353E3A3843383427323436302F33362A2A393E303B3D2F2B2B292E3C3E352E3636313E372C2B2B3636343633351D2E2D363143423930292F2C3E423A302537302A3C3737212D2A36382F31302F39332E37313E372C2B2B363601FE32000801D82031342E2D2B442E2E2C433E3B3C322D332F2D21373B33393A24263A333738272F272235363D3636352F2E2F3A2E25283637302E2728323B3E37343A394032352E2A2F29343222271F292E31372F33323831393330372F2D3739341F23332C343935352F2C312C333828273233304842222734373634322D323841312C2C3F3F2F2E22312F2D24353F3B3532382F2E3B362B312F39362D353D27282B393C3031472734373634322D3201FE33000801D8302A3034362C3A32303731252F3336333533372E272D2D352E2E36383823382E272C32332B2B362A283C31232123282B362C322E2D2D34362D2C393535292C31342A2E35303E2D2A2C2E302D2D2730302E373338322E3D362F2A2C373B31422B22262E313131372D303A32433828223645362F32302E2930302C28262E333735313C31323731382B282D322F39363C283E3535302C292B352B2329272F1D342B30362F32302E29303001FE34000801D8402B353832333828292E2E2C2A40383732293220252F362431363B3C2A2D2E272525252B362B352B27373B3A27262F2F3636363C2E3438222E23292528283747423435342829272E373028373726313632352F2633332E3A2726282832363A2F30222A242E281E373B2D31282A2E2D29302F2E3328202E3735362E2432323A373B2A3626302E2E29362F363342392428272B373C31372D332B282F30331D262A2D2F2E3328202E373501FE35000801D850262E31312028312826222C2A36402A312D282D2A2E333D2B26282A301F352C1E2333243431372C2D2C2C25262E272E3B38342C302E25352C2A35362B26252F2F24233833252E273234351E1D2629242E333B34293B24263932323730212C35312C1D2437372C2F2E382F27231D2F2E2D2C3536362720302E302E292B31312932482F242F3E3333292D2F1E282D3D322C2C34303528222F28232E3433302831292C3536362720302E01FE36000801D8602E2E2E332E29262626373E2F2B262F382A332F2829262A2F2E312C291D2628303A342B270F292B252F2D252E30212D272A413735353224251D1C1F1A2C313236363331343C362D2D3437422B1B3825321D1F24291F2B323A36302F2727282C25302C28332D301D2B31373E2A292F2C242F2C2E35302824272E32362E2223282534253630272E2B322B272B313B322C30202C292B2E221F3239372F272E2D2B2B2F2C2E353028242701FE37000801D870291D242C2E2C301B252F301D1E2B2B2E3430232C2C333B392A3335372421232B2925212E312726322A272E2D3032212B252C1D3B2E302D312D2C282428273439322833362C30342C2F251F1F2629262B2D3822231F2F3430342D2426292E2A312A212F1F231E302F2A1C2934302F322B2D2C332A3832391F312E2E2C2623273022262837322C3829253C22211B2529292A242D2E2E1E212D3E2B2C2C2F23281C2D2C332A3832391F01FE38000801D88038373131322D2323312C2927262A2628281B1E232B2627293E2A232F302B2A2D282D29372935232D2E2B2B271412212D3826272D29252B31292831352F2F2C312A2C323017232C3B323B20292C2E2F1B2E2C20232C3D2D3122241C2D28252A33312C1E183329312A2C252B2D232E2C291E231D2622252E2E242E2E2324392C1F1D2B37362D2D303329231D291F2D2C29353229272C1C2E2E2A2624252D292C211E231D2622252E2E01FE39000801D8901C2B272A2C321F151F232B2B2629252F1C262F2B352E3C393D3422221A262622322E38383F372220131D222129292720332519272C313022211F212A26242933222E3D2D2E1D261D202E2D2C2D242625261C2D282B302F28232926292C2C32251F2726261E312A362B3C2C28342F2C2224232E2C262725152D292A31252D25172026172526253334302B2B24232B2B281F21293C302832363530292C27212B2C24232E2C2627251501FE3A000801D8A0212B292B352E262B2C30271726242F2F3032302B28282A23252F213028242D21252F2A2B292C22121D332B2A2831242A2B272E282E29252828142220241F21272C32253528222026211E2034321E2C31251D221F26332A221D372427222124232D2F302A1F212A1D2B2A2A2A2F2320292A271A221C2D2E282B2E252628262527222B272C28222223292D26202515201D2422201C253A28212A36322224232B292A271A221C2D2E2801FE3B000801D8B01F2420212D292D201F1F251F3631321E20212D2B292B1D2216211D27261624272420382A2C26282E1C1F2421272C30252D2E2B2A2C291E1E2022291E1B22262F37342E2522262C25242D2A1F1D2E322A2C29241F1D1F1F2F2E252923182024292623231E21221D1E2425171B2F2C271F202B242D2827282B2D2F353725242A2829271E2622252B17232B2C27212430332520202321202F302B2A2C21382B2D1C202B242D2827282B01FE3C000801D8C01C24242E2A2C291F292D2A2F232C2B1F1625302D16292429282C261716222B23292C22272435382E151D271F221B2126252725262934231F1A1F1812222B252122221A1F1E2D28222824142825302F3E23342E1F291B25191C222B25393025202B2A201C191F1B2F1F25241E1D232725232318201F282125221D221E1825362E2A36272A262623181B13231C241D262B2A1C161E1C222328192629252229241D232318201F28212501FE3D000801D8D01C1C1B2825242222211F1F23271E281D2D1B1E1A2C2C1F1C221426231A2229321A23242D292E292313212B1E292A241F292A28282D262C29231F2E150B141B20231529232F30202826221E28222C15212A1D25232B2627291F29172423262419121D282E302B1C20281D2527262321221F2B26262B361F2417182724241F2830213029272625232522241E1F1B16232133262123271F1C1B232123291A1E1D221F2B26262B361F2401FE3E000801D8E0222324271C1D1D1E2A30272C281E2C2B162A291B1D1D292423262831232E2816192827241D2119212C252524181D29182626292618292628292324240F20272322161C11232C131D1C28222821261F302B1E182525202A252421161E2516211F1E2F2B1F251F2A2B2C27291C202A1A1B292020212B1B1E172529231A29252421212224222328262B291F1E222920212025231D221C1C191E2A172D232937202F292020212B1B1E1701FE3F000801D8F02820211F1E2323272A2E2D31211E1B1C1E27231210252C2B292B22170D171819161C24291A221D212225231F0F14171F162C2A1F21201516182424241D1F1C1F2328242325271E1E20221E21192620222220232D2B201D252319211C141F2225242A2225261A141B1127221D2623251F29281E1413202A2C252D24200E1F1E282B292627273623201F1827302B1B140E181817241D231D211E10211E1F1A1F2329281E1413202A2C01FE40000801D80025282427231A25131E1D1E1B0E1E1F181A1B1F1F23271C26230D10211B1223121D1F1A1D1D221C1B2322221C272927191B272B21202B1E1D23231B1B221D1B181D281F27171E21201D1A242A292D211A23241E1F2C1B182425162023282A2621201F1C1F1F1813111E1B282F2722181C1A1D231C2D23161F2014131919232A1B131D1F1A201B1F1D1A1F1B181B1E26291E221619202D312421201C1F231D22281A1D231C2D23161F01FE41000801D8101015271A1929302C211314171A211C1322291B1E27192424171614180E1E1C1A1F1721222122221F1E181A2A371D1D21231B1C1C0F19282A1E1F1D120E1D171116232A2A201F2C2724281E1E201A22221C23231A2225241B1F1B191A171B232A161E171C2B2719151E231F1A181D2219272112141A1E181F29221D18151C1C21191E26241A1E221D170F2327221E1F1D2419221D1A29201C11211D191E261A23272112141A1E181F01FE42000801D820262218261D1B1F1B22161E201D1D1C11181E1E1A231E151E191A1B1B1522201D1B2828151F27211D1610101F1F191A1D211116282C1D2A1F131C1A1E221C1F201318211A1612131E2E1E21161A21202818131F1B12251F1118241828312019251B211E1F1C161D15212214091E1B1B201E291824182419222529261B121C191F16131D1F21181D1F1013121B181015272523291E161C0F1925292622272317181E2918241824192201FE43000801D830191422162324221D2326221816171C19131C1C20181E20191F281C1A262719232A11120E0C1D271C1A161C232C2B2225191C1706190D1F1B1B2120251918211F12121B2B142C18151D1918180A1822291411171B1B241B191F1D2B1C2B1F12181C1F201816211A18171E2625221712202D2216141C211E1A17141B1F191A1A160B1E222418231D20181916151A241012242C17141D23231D10171D1A1A191E222D2216141C211E1A01FE44000801D84017151D0A1F2D201E20252C1B1714221C292C1B231C0A0F101C191D0D0A122017141C0F1A281C1916141913121D28261A071120151F23242B191C101D201C1B0F1D24101019121B1F2112111B17161E1914120D1B15251F1F16251D211D0E1A24261F26181F1B161F211517221C1812212520201C0D201D22222726161A1B0F141B24241014211F162A31241314130B0718191B181C2630281913151A122323152520201C0D201D2201FE45000801D85015170A1E171A281F1B1C24230F1312121D12161A0F15121A1D212019211B1B2518101B1E19232828200C17191C1415180F1C1B16130E1213251E18182D22202224251A191619192213180A0B1212190F1A17251B0913191A1D190E1A23101C1A121521231C181E1A1511261E1C191A20121A1E251A1715131E2221141314141709191F1E13211B13120A2328170615181F1616171C18192C1A1A140D16110E28121A1E251A17151301FE46000801D860281118211C140B1919191416160C141A1B161C1A111818190D0B170E1620200E091516101D15161F2419190B101A070A1B1216201E181C2421221E0E1A23151515181F1C1813181C201C14171E1C160B0C140D060B1F1418111F1C1F191A1A08171D1E1E1D1C1515181C2C171A1E24161D1F1D0E120E1D091B171E161A17181A1A0E101E140E120E0E0D15130C191020171A17211622141C0916181317191B281D1F1D0E120E1D0901FE47000801D870160B0F191E18090F1F181218170612221F271C1515180D1A1E1111180B0B190C1512131617181B191E1916191A101E191C220B211F131D1E1D17160F10110B101D0B1A1B0E0F1114121B1B1A1A0A03191D19040A1B1D2517201210201623161A191E19130E08241C0A1D1613161B21171A1B1B1A221811050A12251B1A131009121F0A1811220819221B24200E0B0E0A131D221D1C1418231C1B141A150B0C031A1B1B1A2218110501FE48000801D880120C171F1C1711151B1B121D1C1A07141818101A1F1E1E0911151416000C1A13121915251917191A1A12130C1818131A09110F25111712190A110F0B11121918221D10101B14121A170D090B0D101E0D0E130F1E1A15201C1D1D171814190D121A181514151B14101817191B1B1D1F131A0E0C111014131110060D1613151E14131C121113201D10130A1213081913241A1121161A251C14150C0D1C231517251A0E0C111014131101FE49000801D89003060F07071B190607190F190613181D0C0F0E1116171E1B201E181A121414130D0818261E17070B14101A191910141A191F130C08201313100D0E14110A121F100E150F050823171E1F0E13180E1C1319210E0D25251311030E0C1A161114030D191B1E120E17101A102008031A090818130F140D070E0C061417221E16151A0B10161612120D0D20161717151A090C181A161B201E15111A11200D181B131B18130F140D070E0C01FE4A000801D8A00E141D1D0F171E0A0C07161F1F16100B140F0E1818011B1807150F0D161F19190C0E171716192F15130B1C0A0F140C1216081813111A0A180B100C0F1E231E1613140E100D09091409191716091412191B1306181208161F1D17190E17161318191710110716120C060A0B0E140E0B15210C0C1A140F17151C1A2210131D1615100D000109100D161C0C1717121B191814140E02160E0F07180E1319111D0C17210C0C1A140F171501FE4B000801D8B010050C1309070E13180B080E131E0C0E0E0E04131117150C08151D09040E0F1312070F10120E09101208161210140C14181B15200C101711140E04151425221C0F1E100F0E0E120E10190D0D120511151812111616160C140B181919151C0A05140918191B121411090E190C0A0C080C0D09090D0F15180E0B1610000914130E0B0C1C14111011131A1C181F1B1E1916150F111111070B0F0B0F070B0F1A0F0B0D09090D0F15180E01FE4C000801D8C01319180F0B06020F0D09121515121E1D1306090B0D12110C1C191202000D191F160F0E16110A100D101A0A1609000503090903090E150F12110A0B0F13130C0E040C1F160F1314181200040C11140A1117151316060E0C192821131A0B110F090C17130D05090A0E0B18121315150B0F0D0D1500080C25150316110A0B1012161819160C0B1010150D130F0C060A0A17140D100F0F060B0E11130A00050B111D0D0D1500080C251501FE4D000801D8D0010008190E0010060B120F05091409101915130B14000708021817090013091C0F1711191908141A10120A0E0E130F161711130A0F1004101B1E131213141A0C0E000C0E0B000003181212021111031213151A110F1310120E170D10110F0901051913100B130A150B060C0A110912110F0E1C1B140C050505121A14101606080012170B120F10100A1D11120817140F040D13120A150C0808041C0808121B0D0F0E1C1B140C050501FE4E000801D8E00609060B0D070B1518170814160D070803060C0F09010414060000090C10120F0F0A0D080800041510121112130E0E1116121E170514141114130E050918141019090D0F0805101A0D0700100A070E0806071915060D0A17151702101C100B0908150C0E1009070E0C0F0D060708150E15081815060213161709121A0C07000B10040D0A13060A06150A1113100F1716160C0F0C0910120D090B001C03090300150818150602131601FE4F000801D8F00D191E14070B0F0E0808040E0B150E0804100C181704110A0B0F1411000C0B181212170B040201090312050803080F100E0F0802040B0B1618100B100B050708070508121C04000A070B1117080B0F160A171B0F0809080713120B141307050D0F0E0F06111118171B1B04100D0A01020711080B0B1405000E0D131C050914130E1009041008121B040000000613130E040202060D0D1108160E010E1216120C0711080B0B14050001FE50000801D8001B120D12060221120A10180D08120907091100080A1812150C0D100A000F1209111C1708040903010A000402040613100B13070A111D0E0B0A110E04110A040A0908090F1A150B04001A00040B060B0403040F1C0D0E0B070A180B0B000A081108131400000B131B061715050F0706060D19080C1014191C080E0000000002131C11080005030D100A1307000001150B13030D110D191B0705140702110C0C030D19080C1014191C01FE51000801D8100000081611060608060B0005080C0B110909100E080A1818090B0E1C0612050A1021190703000F0E1614000801031207000800100C090B0300030709100A030107080D0A00000607111511080A0F0006110C0D17020708000400020A0E0A141210060B06040C120E000F140B100A0A0404090912050915151E0A040106120317120907030E07080F06030800000C00110D040E160A06110C06090B000B0C0F0C040909120509151501FE52000801D8200A0C14130800000000080A0A1017080802000000181507020F0E14000000020C07050F0F0C07090D000B090D0F000005050A061A17030506040A090A070A00070E12060D150D0D00120B06070C08060B14170F0E03000400070C0E0B1003000600160E08000B05060200030E03090A01050607120A070909030C120B100C07090004110A0F0C080A00130A010A070A030007050A020904080B0C0E1A1C050500050607120A07090901FE53000801D83003040003060A0F0900060002081001050104000F100F020002120E000000000000121500040611121601050001090C0C100200000005030708030C160C060C060B08090C0D0C000B040C0A1510110003100C0D0A0E0C000700130F0A110A060000110506170900050F08080008010D06000C0E0C0906020004051604080608060D060B06090902000000140B0E0B000C0909110902090B101209030507030207000C0E0C0906020001FE54000801D840050A0900110003010400050014131103100000140E080F030400050806100D00050715010D0C080D0304010E1304040000000004000400000606130A060B0A171306081708000C10000E02000A0E080500000000030B000515070204000F0C0B08040502000000000A060A030A040D040607090E0A0E1203040D0A07020C040000080414100F0504020B0A0603030A00050A0007010A06080B030000010807020607090E0A0E120301FE55000801D8500B00070000080911080D0600050A09020402000309030000000F040005000D150000050C050B08010A0C110F0903000805110605000002020004050E1106090600000000050700000000050B020404000D0004100E10020001020F0007010B00080A0909060709000C04000806000A000A0E0F0909050002000300100400000606080900000B000D0F1100000002000105130401000C120004060D0D0A0700050A0E0F090905000201FE56000801D860000B1005020C000D04000403000409020308000000050A0000090A08040B040507110C110F06000C0000000000000001000305040007030700070001000509020E0B040A0D060005070300080000000412130B0D060A000000000600030800040009030C08030007140E000000060B0E071202010002000300070506060B1000080A000000000300090005050000170D0506000A000003051003070000000008071202010002000301FE57000801D87001070C00030308000006010300000300061400000100000500011403070001000A0000020900010000030D0B0002080000090A080F0603120000070000000000070300050200080000030507000E0E04020700000005080900010000070D080A0700000500000000000B00050200070000040300090000000002000505090D03070003010802000000050D0C0303020903080100000100090000000000000109000403000900000001FE58000801D8800B000004110A07000000000000000003000602060000090F020A02000000000709080D000201000B00010002080700000B0803030100000001060003070900000400000000000B0300070B070000000000000805000000010708070D07000000090809000001000004080A0B0700000A0700070C03080C00010000000009090000000000020000000000000A070000060B0009050600000002110C03000000010700070C03080C0001FE59000801D89000070000000000000001060000020008080E02000000000000040007080400000004000D0D07000000000000000000000B0000000000000002000F0600000400030000010509000000010000000207050804000A08040100000000000004070000020009040F0E07050000080001000605000000000000040000000007050001000000040A0400000000000800000102070700030002000C0E03000003000000050000000000000401FE5A000801D8A00A08000000000300020006000700000000010A00000000000000000000000001000409020500000000000000000000000707020000010007000005080904030800010001080000000000050A0E0D00070000000000000F040500000A0A0607030000000000000000000605000007040E0301000000020106080705000600000001000500000000020007080B0000030100000000000001020100000003020007030100000002010601FE5B000801D8B0000000060002000A030000000000080900000000000810090E0000000000000A0A0001000007060000000000000000040000000000000902000000000000000A0F0500000000040000000000000000000000000E15030000000D0E00000300000000000003060A02000000000000000900000001000000000400000B000000000702000002060F05000000000000020007030000000000000000000009040000000000010000000001FE5C000801D8C000000000000100010000000000060200000D02050207000B000000000000000000000000000000020000000000000000000000030000000000000000010100050000000005070401000000000000070000000102000000000000050000000000000002000001000500000000080000000000020500000000000012000A0C0104000000000000000000000000000A060000000000010201060700000000000000000002050000000001FE5D000801D8D00001000000000100000200000000050000000208020000050000000000000000000600000000020000000000000C0000000000010000000F000000000800000000050D000000000410000000000000000000000000000000000000040109000000000000000000000104090003000002000200080900000000000000000000000000000000000000000000020000040000000000000000060600000000000007000200080900000001FE5E000801D8E0000000000001000000000000000000000000000000010B0000000002000000000001000000050201000000000100000000000000000000000000000000020200000000040000020003000000000000000000000400000506000000000000000007000B000000000000040500000000000000000201000900000000000006000001040000000000000000000100000000050E0000000000000000040000000000000000020100090001FE5F000801D8F0000003040000000000000000000000000000000000000800000000000000000000000000000000040000000000010000060000000000030000080400000000000000000000000000000805000000000000000400000600000000000D0000000000000601000202000000000000000000000000000100000000000000000000000000000000000000000000000003000000030000000000000000000000000000000000000100000001FE60000801D80001000000000509000000000000000000000000000000000000000000000000000000000000000000000000080000000000000003000000000000000000000003000000000008000000000000000000000000000000000000000000000300000000000000000000000003000000000000000000000000000000000000000A0000000000020000000005000000000000030000000000000000000A080000000000000000000000000001FE61000801D81000000000000001000000000000000000000800010C02000000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000500000001FE62000801D8200000000000000000000000000000000000000003000F000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000404000000000000000001FE63000801D8300000000000000000000000000000000000000001000000000000040905000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000040000000000000A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE64000801D84000000000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE65000801D85000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000001FE66000801D86000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE67000801D87000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE68000801D88000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020001FE69000801D89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE6A000801D8A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE6B000801D8B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE6C000801D8C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE6D000801D8D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE6E000801D8E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE6F000801D8F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE70000801D80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE71000801D81000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE72000801D82000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE73000801D83000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE74000801D84000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE75000801D85000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE76000801D86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE77000801D87000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE78000801D88000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE79000801D89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE7A000801D8A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE7B000801D8B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE7C000801D8C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE7D000801D8D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE7E000801D8E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE7F000801D8F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE80000801D80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE81000801D8106D686E7D7975777D736A707376736B7675706F68707372705F766F6D726F7F7E7D786A6C6E6F65676972786C726F75666F758077717C6D7478635D726E717E6A6666747172746B75777377757D79757664736A6871716968736F756B716B6B717A716B6E687F74736E786A7A767374626A76797560716E717372677C7D817C707B736D6C6F6B696C6B77727172707362686C6F72796D767470757C837C76767C6A76797560716E7101FE82000801D820737074706D686C7378687F6F746F726A72717A786D6D7F717A7385786F748084775F676C75777973676D727175736F77777B75707A798976777572686B7274777E7973777D7880666E686B72696C6E79707F746C7376776B6E6F697B7872716C71716A6C73707C7782756A736E7A827A7173716E726D6D7579806C76706E686565797F706F7A75736C746568768072757B7B706768736D7773777973706F75717173716E726D6D7501FE83000801D8307C72786E857E7B6E6F7980727E6879707075776F767A6D74746F6F6C6B71716B7C7377627B717770707B7E816D7573827F7A736979776B716D74757678727477717175766D82847F776D767271776970716E696F6D73727A7D7A787F727C7B716E6B79726F74806C7067727D74917464757B6E6A7B71756F72797F796E73767176746C6F707377766E69636C62686C7A747580897C6F7A786E77806B75777D79757B6E6A7B71756F01FE84000801D8407C776D787E727F7A717376787275777C79827C7D796C6A69787F7E72746D78757E86827676737675687571747672636477706B7D6A7779767F7A757A8B7D756D776F7A777B8689706E736D6D6E7D7872706B747D7D76756F74757F777877847F727E70746A7A796B747E7E746D777276787B7B716E726A7B7979777775848074766F767E75817D7A676E6D768B7963676C6F6A6E767F727274777370746E7C7F787B7B716E726A7B01FE85000801D85083787874838C7B716F737071716C777679838287837874767D73746B79727F897C6B69746C6E7F8378777D77716E77786F7D75777E776E7C7875776E708176856B7880736F6C6872776D72757C72757E817B857D7A7A7271756E7A7E8775706F7779796E6A7B7B856C74846D6D7676776C7471737B79787D7582776D757A847A71728277746D7780728879767C7F777B75768079827267708578847F647076856C7471737B79787D01FE86000801D86074707C747F7C787B8076747378787E807F807678717B7A767070797477717F736F7379848283737C777D757774767D836F7F777273756E6D7F7C737A697D737980807181807B7C767B706D7171717E7D787278827879827F768A847D71726D73717F6B72786D7478727373757979737E86807576787D83867E7D7D6C7073807E7870707071737E7A7F7C6B707D737F7E7A8279767B7E8870706E7A7F7773807186807576787D838601FE87000801D8707372857F717F7D756975747B75767D837F836275827A7778797E6D7C7B74787F85747C78736F787C7E8682727074817C827D887A74766D7975789090777E6F7472827E7B7A667B84717882838571797C7F7A7B6F70717C80706C787F7C747E80817F6974737B7D7A7B76827E7877767470767B7A6C8188827B7C827F7769787E7A9082706B86877772737A6E737D757878788288726E767B7777758678706F7870767B7A6C81888201FE88000801D880878979797D7E74817F817B7F7B7C8277887A777A72656F85706D7D837E7B7C817E7E79747C7A7E7C8586827C7A777578797472827B6D7C7F897E7B807A7574767F7F7484877A7A7D8C84837C86766D807D8582867B6E747B6E746C7D7170747B7C717B7D75788682757B7973847C74836F7B777B857D777C817E887C78837384827A8375756F7C80827678818984747E82788082707A757B82788580827583836F7B777B857D777C01FE89000801D8907975847F707C6F707A7C8C737C70748071777781848B787E78848E89817885767276706876857E787D7E7C857B828482878B718384807D7E8C897F6D776A7A7E747E778A8B89827C837A7C7B867A6F7A7774877E7E7B85817D868079747472747C896C756F7382818A817B7D80837C6D7C797C806E7478807A7E89777A787F798282827B7F8B776F7B7A7B7C7E7C7B7C7D737D7E857C767A85747E7B857F83757C797C806E74788001FE8A000801D8A07B6E777C7F7C7F8588807F7C7B7B7D81858C88748089867A7672757F817F7D747A6B73757A84847E8B838382867F7C747B73818184847C7D8489848A808885827A80867B7168747B797A7E7A8287856F747F7982787F7D826F8381787A73768379897F727F7D6C77768682877C7D81848782817C85847D7D827C7E897F8373747E77807C8B8A7D838782837A776E847D7987847678807E7F878685807F877F808782817C85847D7D01FE8B000801D8B076788073787F818380857984897F7B728178788D7F7F7F6F7A76817E7D768279818384776E79818288717F8D84837C7B848380878D828283938D8C817B78767B8B778788777E7C7B8185767576797E7B737B7C7F837A7F8482727A867F7C7F7D7D737F89967D7F787A8388707E7F7D857979818883817D7488807B7D7E7C7A707C878587767F848780827D8080878283858790917B7C787E7776757D787A78847979818883817D7401FE8C000801D8C0667582757C838982778A807C757C7F827D7B7B818580828879748180827783897A737E93837D7D7C8A78808B7F78808D81828888837C8690838571757B8482858D7E77718C80797573877C85888A878B7E888B7C857E8087877E72787C8283817D7B747E7E797E8A86838B8088808085828E807C72727B867A7F7D7E827F7E7B768082837F7C82858F888180707F776D78766E7A8385807C827B80857D80807C828E807C72727B8601FE8D000801D8D086807C80828A8394888781767D807B87837A7382867B838A87818187848983938D88817E7B817878767D878B8783788E84808289889189887678827F8A887E8B7D848B81808171707B717E7F8176808380838C908C7D8B8B8A7673747C81807E838384887A7E818A7E818076798278827E6F828F8D83837E8C728A86837D7F7D7B857B8A92808D8888807E7E868D867A7F7A818D8D857F7D78777F81808986717E6F828F8D83837E01FE8E000801D8E0747C808788848580808C97897F7977787D7E86857C787D847E737B828285807B8C8287898D8A8C8E7C7F868B7D79817D898281929B838C808285827F7480857F878B8092888A898E88837971807A848B94838A8B83868279807C80807D8B86707E89887C8F7D85797F74808386847E80867383788184868A818B818D8D877E807C7B797C8A877686787F858D92947574769191848C858285908582737C867779867383788184868A01FE8F000801D8F0908C758787848484887E857F7F81848786868880797F877D7F827C88888D867E82838E8B8480898487827F8286928C818A807D93928985807E81857A76727F8A8B80858879737A89867E83828594868382818386867E907C7C929388817D837F8783828C7C868F88839191899583887C82798F86727F82847E83907A8081808C7D86888B7A81837E858284807E757C8A848C758589888F8C817D8A8E8D90858482798F86727F828401FE90000801D80081716D767E7F8F8F7D778285868D817C8E8788917F827C82818B9389838277818E8C857F837C7A838A83828088858D9284827E737F8C87867D80848A85867F7F908886918F9A878B8F8686868B82888C938B8582827E78807C80858A858988848C7E83898C877687877F87908D98978F867C807A868F85747991877F868A8D878A8C858287878488817C74858393887D80878484848588868287868F79888084867C807A868F857401FE91000801D8107A898E8C7E959087818082797C8B8F8B7E81847C85808A8886788187887E83848D858E8D979081848885827D858F86807F8C8C898F908B8F92937E86918F857D84908382798887928B87847F8271847F7F918986878D887E81887E81888890898D8985878591838083827D8786938C8E8A83818B83867E727789868C86969180928D8688747C8B858882858A837B7D8C92887B8B8A8C8B857D7D80777E8C868B8A83818B83867E7201FE92000801D8208D7F888F8789897E85909184888D878887868D869A918E838B908F899495818D84897E7D87878C8F8283757E808B818A8483838A8499928886988B998E83808784868373888B877A8382897B898A8085838986808C8F83898E8B857C9090958587858C898682848387888C767C8488898D8D94969A8B8388847C888890808C7D88898C8C7B8C7B80847C7F928788897C8E9C8E8884888C898B8A808C88888F7F8D8D94969A8B838801FE93000801D83093949B9B8B998E90888785898D8881807E8C838C8C9B84928286897E7C8C8F8F8A847D878A8B927E767C81877C8C928E8E9C9389888B87888B878F84807E878591878C878B8A84868189858B8A8D8180859393858788898A8C86868B7F7D8A8D9E9D8E8983948D8F8F8E8083768D8C8D958A8697828984838D9C9590888D8A9B8C7E818B83858E8E8484858D8E838280818D8C85888F97868C8B87868D7C9190958A86978289848301FE94000801D840838A7F8E8F888C8889968F8391918A858F8A978E9B808683827C8787788B988F858A8C86828B948C8D8E84848996868D928488898487868C90938E8E968F878282898B84878E92877E868B9F94869590838C898D8E9695898B86A097847C828E938D8B948D7C838085898F838687827F8F8F8C8F9C868182827D8C90858B86938E919790967D7D7B8D94978E8279838182888C818A88878E8C97859A959487878F8F8C8F9C86818201FE95000801D85094868584818B8786958B88888D908A8F929591877A888B8D939489968E918B8B8A8C938D8E8C818A8F92868381928C85868C8D897F90869D8A96A18C9087928B849390828796958E8A8D8F8E98848D838C86878B8C8A968D989582898D8996969F8F888C728697807F868F8E7F89908D8A89898B8D92858D928B8390918D827B88918987958D8A7F8A828A978B90917F8C8F8B88898D869786918F96948F8B828A89898B8D92858D01FE96000801D86087848B8D848E9092938F90969091878C8D8689888898918D84807F8B909091958F8386809890808E8B8B8F95888780918592968B8C8495938F97989684828D90838B89928C998A8A8C8888878782839191948F9995998393939295939382877D968E8E867E8C858296908B8A898A908B958C8B978F858D928F8F86878E85918C8C948F8D837F918E939389958A9482848D868D968B8D938B848F9293958C8B8F958C8B978F858D9201FE97000801D8709B9382919B8A8C88949C9694918C9692888F9C96939089898E8D83868F8B8C8D8588838687898C969294828B879893A398858A7A808E898F968A808B8C898F978F8E8F929B9A92A1909496908A8887988F85848C90877E84878C838A8B979BA1A29B988D7A9683898B8C91909C8E8F968F94858D8F939C94A39382858880848EA3929192888F9089838A8D8D888992928F909692918D94878895928C8D8A8C8C8F94858D8F939C9401FE98000801D880848B999A99918A8F92878E8B8A948B908D8A95868E838996948F9F8A8B92928B8891949D958C909D9A9691909D8F969B979A897D8E81859189848F93898B8C8584948A968D8A938D93928A9589818F8F918F908B85948E96879B9A928E95968E878AA48F829A9492918C9995988F8D9391939A8D847E969E949A9E9C888F7D939A92878B8F8591908B8C878A8B8589938B99918C9095979790A295928C93929891939A8D847E969E01FE99000801D890998A929988808B8C969E9E999A919A928C8C9192969E9493918F908E8C81908988989293948E91968D979C8E87918F96909296A18C908F878880908B8A9693908E8D8C8C908C96958B9896A9999994878A898A8E81948D9995938D988D8F9B8C9B9594958B947F797F8984978F908E8A929295909B95999B8F918A8E8492969C91968F8E9E8C8C959499928F979793908F8E979C98909A8E988A8D9196878990929295909B95999B01FE9A000801D8A090938A8C999994949087928A8F919097979C98919A8C92968C968E84978E91989A95A386959598969F9192867E989691979A979889888392989A90908795978F9388859B9A93928B91939699988F9A949A98A4919294989797978B99A096838F91928F9A939586908E86969F918A9595919C978C8A8B9891A19E9D95A08E8C91918B808E8F938C91919796978B9C91969189A29D949699999390969492838A8F919C978C8A8B989101FE9B000801D8B094949E919488959BA38F93979C8F8D92979F8B8F8B9696948C86928F92948A99A19696A09E98988E9F9496848E888C83999B8994959090988A8D94968F859EA18F928F96918A899AA19796919B939794969C9297A08B969B93969291A0979D94899795818A8D909088999D9788999A9382918C9A8B908E938F93989295989F9A9390899892939798899B94A59D9095949198969A979A979089959C948E9FA08882918C9A8B908E9301FE9C000801D8C09B7B8B888292A09494949395A29F969792999A9894929D9DA6949B9DA2979B8AA3908F9A948C8496999B918B838A9E948A8998A99D8D8B9C98989C9A9A9C8B89948E888692979A91979F8C8E9B97979B9A9B9D919390979B999A92968A99959D8F93A38E949585979290939FA0938B8B979695938D909E95949D98AE8C8D92979CA199938F959998959F9B8E928F8E8E929AA395989C919481908D8F9B9B8D8D979695938D909E9501FE9D000801D8D0979D9FA0988C959B8B969594999287A39698878D989C979F9A9D9C8A989A989E98919B99AC9585998F8D9495989F9B959096959A8BA19299A5A0AB9997A6999485948891998F9293949E9591979994959394928C92A09F9E9E9697919C9A90949A8FA39D8E9091999A98919C99909093A1959591999B8F9D8E939C9D9C949C919C9D9098869096959797A399A49C9B959A9C919096999E9A919B9A9F9891988EA1959591999B8F9D01FE9E000801D8E091A28D9690919697A1A79F9B9F8E888B8AA0A29D8C959394998C969F8B938F97959498988A908E9D949EA499969B97A59D9F9A9692988A9FA4969794949B909B9393A1969B9D9195A4A9A1949799918D939496949D9590919A9695A9A39B94A1918B8F92928F95A69D9E97929A959299899A908F90938E909E9E9A968F96989CA392959BA69A9B9EA0A69592A28C979B987D919C90988F94949897A2979C9792899A908F90938E9001FE9F000801D8F08A9DA292909A9CA39AA09CA1A2A4A7A2AA98A28D929D9C959894949A92949C97989592879B9593938B8F9CA1A59E9C95968A94977E9595A19AA1A79F8E989B9A998F959EA9A3A79F9BA0919BA5A9A59F9194869F8896959A9EA7979F9BA3A7969299A8968F97868F9394909FA591989D9B9F91A1979E99979AA18D9E999A96969C8F9CAE989F94999F9BA79695938F958F908EA19FA69195A5A19D988F9C94969B9F91A1979E999701FEA0000801D80095959A94939A989D94928C9D9FA19A9B9F9C9FA0A6A4958C8B9BA39D95A399A89E9E91A2A09E98939A9F9899979B9AA39E909698939990939FA7A8978D9E989B939393989BA69C9E9D9D9A969C96959D8A9C9A958A9B90989C9B9B9A9A9F97A39F9AA8A2A498999093A0979F9E949BA3A9A4969A9A9DA193969091A297A49B989B9B9596929DA29DAD9F989DA7A4A694A3A69A9C9AA3A0A09597918F999B968AA9A4969A9A9DA19301FEA1000801D8109BA093958F9A9EA49B9FA89792A2A1979EA4A79D999F9FA59292979B9FA293A28D92918BA1A6A4949999909FAAA8A09A9EA49C9A9DA0A28F9E979E8A9C98998C9598A7A0A6A89D98A5A19EA09EA09A9CA19FA39797A38F9E9F919B969890A295928C90989C9FA4A7989B989A9EA5A39E8E94959995A4949B8D9AA0979D9A96909CA4A3AD9D9F9D99A29F8B988D98A09C9E9E9F9E909B9FA6A398A0A1A7979B9D8E94959995A4949B01FEA2000801D820A89F9C918D99A7A996A491A6A49F98A99F979B9496A2AA919896A7A7A39B959B99A3A6A1889096A19C9899939CA0949A9DA0A9A89BA3989CA0B39D9A98949A999BAA9D9A9A8F989F9E9C9DA4919C9A9FA49799A8ACA0969D9DA293A9A0968F97979DA4A69E939C97A2A29A9494A09593969E99A1A698A7A0A0A5B69C9796A1959F959D99999F999AA6A697A3A09E9B97969BA49998A99DA2969997A5A4AAB1A7969E99A1A698A7A001FEA3000801D8309B9DA59AA8999EA9A7A29596A5A0A6979398A2A19CA3A29FA694A2A6A69EA49F9E9E9E9E99A1939B9CA5A3A59B96979AA4AAA69A9AA5A2979AABA4999B91A39C9EA0A29F9C969B9A98ABB4A59D9293919FA0A09BA29F9F99A19B97A6A8A1A59BACA395919391A6A4A19BA09B8EA2AB9B9CA89EA2A19DA1A6A5A3AA9B989C8C97999894949B9F9CA0A0A19D9BABAAA7AFA1A5A2A0979AA2ABA493A4A69B9C90A29CA89EA2A19DA1A601FEA4000801D8409E9B9EA39FA0A29F9AA19C9F9A9E989B979EA2AEA8A89C9C99A4A2A69DA1A5A6A59A98998E9EA3A89C9DAAA9B0989BAE9F9AA39F9DA89D9DA1A0A19A9F9B9E989BA1A0A09C98A1AAA29A9997969A9FA1A2A79AABA2A995A29CA69FA7A19CA0A2ADB1999299A79BA19BA29A999F9B97A298A2989D9FA0A399A3A197A0A5A6969CA2AEA3959F9DA9A9ADB4A09A9F909E999BA4A3A3A99A989B93A19D9BA09D989798A2989D9FA0A39901FEA5000801D8509EA7A4A29BA9A1AE9BA5A69C96A79E928D9C9FAFA5979CA9B699A6ADA1A2A49D9D9FA9A5A89F9BA8979EA6A69EB1A49F9F9C8F9697ACB4A09BA2A69F95A8AA9F99A5A4A598989BA49E94A2A49A96A3AEAAA69EA7A19E9A90A2A0A6AAA99EAA9F9FAB9898A3A5A19FA59DA3A69B9B9F9DA9A49A959AA197A2A0A59B979E90979CA5A0A1A799A1A7A6A2A5AAA29799959B94A09FADABAAA4B4AFB19E94999D9E9BA9A49A959AA197A201FEA6000801D860A59BABA59E9BA4A3968A8DA7A09E9FA69DA3A2A1AEA3A698A19BAD9DA29D9CA2999FA3A7A6A4A5A8A29AAAA5A9A6A4A3B9A4AE9D95A69895A09E9D9E9C9FA39FA3A7A1A2A5A7999A9DA2A1ABA3AD9FA29AA79CA4A1A6AAA19AABACA3A6AA9C9F999B8D95A3AFAB9A9EA4B49EA2ABA1ACAAA8A4A2AFA9AAA4A7A0A7969D9C99A291949C97A6AC9E9AA4A69D999F9A939CA39EA9ADA9B2B5A191A5ACB0A2ABA4B1AAA8A4A2AFA9AAA401FEA7000801D870A39CA1A9AEACA29C9C9EA49E949EA1A0A2A2A7A9ACA9A79CACAEA99F97A79EB2A4A0A2AAA9A1A5A6A1A4B4B3ADA598998FA19B97A5A0AEB59D9EA4AA9F9FA0A7A3A1AFADA9A8AAAAA4A9A1A1A1A9AD9FA1B6B5A9AAA89B969C999B9F99A4AE9E9C9E97999CA5A8A7AEA999B2A5A3AEAF9C9FA5A49C949CA3A5A5A4ADA1ABA8A4ACA7A09EA2A1AAB197A8A7A5A5A59FA6A3A4A196949BA29FAE9B9FA98FA2A49A9C9FA5A49C949CA301FEA8000801D880A1A1A495AEAEA4AFACB2A4A39FA4A9AC9FA3A3AEA5A09D98A0A5AFA2A5A6ADAE9BA1A4A0B290A7B4A6A3A6A49597A0A09E939DA4B0ADAAAAA5A3A6AAB2AFABAEABB1A09D999FA0A2A2B3A2A79CA0B1B2A9A0ABA8ABA9A4A199A1AD9E9BA3AAA39AA28F8F9DA19E9DA7AEA2A69A9FB7A8AF9F9497ACA2B5A6A8AAAAB39EA9AEA9AD9BA5979BA7ADB3A89F9CA3A6A3A1A7A09EA2A0A6A9A7A2A9B1AEB4ADB3A1A5AF9F9497ACA2B5A601FEA9000801D890B1AFA79C98A9A0A0A1A1B0AFAFA797A8B2A6A1A5A8ADB5A49BA2A4A1A4AAA9A7AC9CA7A9A2A79EAFA2A9ABA6ADADABABA8B2A9B1A5A9A4A7A4A6A3A9AAAAAFBAA5A29BA9ADB0AE9FA1A6A0A3A49BA6989BA7B1AFABA7ACA6A79AAAA9A7A4A1A0A59BAEADA49A979BA2A494A1AEB2AC9FB6AFA6AAB5B1AB9A9EB9AAA39FA1AFA6B0AFAD9FA09FA89AA6A59FA2A39EA3A79CA5A4A39A9FA3AEBAB6ACB4A9A09BAAB6AFA6AAB5B1AB9A01FEAA000801D8A09FAAA8A4B2AEA9AA9FA6A2A19CA09BA8B79F9FA6ABABA4A1A3A6AEA89EABA79F9FABAFA6B0A6A2B5A3ADB0A7A196A2A1ADA7A5B1A8AEAFA998AFB5AFA1A6AAABADADAAA9AFB1AEA2A3AAA6ADA3999998A8ADAEA3AFA3A8ABA7A7A69BABB1ABB5A0A6A1A0A9A29CA1AFA8A9AA9EA19FA1A9A7B2A0B1A9ACA9B0B6ADA6B4A79C999AB4B2B3B9A4A1A5A4ACA4AEAA9BA2A79FA2A2A8A8A6A8A7AA9AB1B3A1A5AAB2A9A7B2A0B1A9ACA901FEAB000801D8B0ABAEAAB4A7AAA9A7AEB2A6AC9DA0A3ABA4B1A5AAACA6A6B7B6B8AFA1A4ABADA2ABB4A7A3ADB2AEA9A8A7A9ABA6A1A4A5AC9296B9B1ABA0ACAFB3A7B2A99B98A7A0A3AFAF9DA79D9AB4A8A39E99A8AEADA2A2ABA5B0B2B3B1B6B2A9A5ABB5A6ABB1B1AEA99DA5ABABAC9F9FB3A8B0A29DA191999DA7AAAAACA7AEABA69CAAADACAFAC9CAEB1A1AAA8A6B0AAA7A9B0AB95A8A5A39E9EACB2AB9CA99FA5ABA8A9A7A191999DA7AAAAAC01FEAC000801D8C0A9A2A9B3ACA7A9A7AAB0B5A3A3A5A4A8B3BDC4AAABA8ACA6AEAAABA3B3A7A1ABADA2B1A2A5ABACB0ADAEB0B0ACB2AEA1A0A7A1A2AFB3B1ABB0AFA9A1A19CA3B2A4A4A3AFC2A9AEACB8A9B4B8B9AE9FAEA1A49BADA49B919DACA0A6ABAF9FA4B5ACA9ABB1A8A9B5A8B1A6B7A09A9BAAA39CACAFAEB6A8B8AEA2A9ADADACAFB0AEADA5AEA7A8ACA9B4B7ACB4ADA7A7A2B6B4AD9EA6A3A3A3A7ADACB1A4A6A09E9E9CACAFAEB6A8B8AE01FEAD000801D8D0B6C2A9B4A9AFACA1A4A5A5A8B5A99FAA9FA3ADADAFB2A79BB8B5A5B9ACB5AEA9A6ACA29CA69CA6B1A9A1ADAAB9AFAAA5A5A2ADA8B0A8AAAAAAA7AFB3A4A8A8BBA7AFB3B6B6A6A9A1B3B1A2AA9FA1ACACAFBBADAEB9B3AAABAAA0A2A29EADB8ABA6A4B2AFACA3A7ABB2AEAEB3B69BAAAAACAFA7AFB6ACB3A3A4AFA9A4A2AFB4ABA7A1AAADAEAAA8AFADAAAEADA9A6AFBAB0B1B7A3A6AAAAA79EA7A6ACA59CA0AFACAFA7AFB6ACB3A301FEAE000801D8E0B7AEACB1AAB2ACA8AAB5B3BDB7C0A5ACA7A89DADA9A8ABA2A7B4AB9BAEABB0A0B2B4A9A6A7ADB1A5A89FA9B0A8AAB0AAAAACB2B6AEAFA9B5A6A5A3A0B1ABA4A6AAAFA5A7ABAAACAAA7B2B9C0B4B0B3A5B1ADA8AAAA9FA7AFBFBEB9B8ABA8AFBABDB3AFA89D99A1ACBCB2A6AB9EADA8B2B5B8B9B5ABB5B0AEC2A6A9A2A4AEACB2B5A3AAADB0A7A6AFB4B6B2A9A8A0ADA9ACB3AEB0B2ACAAA8AEA5AAAFB3A6ACB4B5B8B9B5ABB5B0AE01FEAF000801D8F0B4AEAFA1ADAEA6B3B1ABAEB1AD9CB3B0AFAAB6B4B5BEB19DACA7A7AAADB1B8B0AEBAB3A8AEA5B0B0ACB2ACAEA9ACB3B7B3AEB2ACAAB2A9B1A9A0A9B6B6B2A3B0ACB5B8BAB39EA5B3AEAFA1B2A6AAB4AAA1ADA6AFB9B5B3A5ADAAAFAFA7ACA9A6B7ADB7B2ADACB3B1BFB1A7A7B2B6A9B4B0A6B1B9B8B7B4ADA7B5ACA1B2A6B2B1AFB3B4B5AAB4B1AFB6B1AAB0B7A0A9B9B6A4B2B9B0BAAEA8A2A3A3A9A5ADADAAB0A6B1B9B8B7B4AD01FEB0000801D800ADBCACA7C1B9AAAEA4A5B3AFB9A3A1ADAE99A0B8B1ACA6B2A4AEB3B2BBA9B7B3ADB5A9B5B5B3AFB8A7ADB2B0BEBCB1B5AAAAA9B2B9AEAFA7B0ACB8ADACB0B3B1A5AEAAA8A3A4A1AFBBB4AFB4B5B7AEAFB29DB6ABB6BABCAEA7A2AFC0C0BBB1B8B1BC9EA29EA4B5BCABA5B2AEB3B2AFA8AC9FB1B5BABAB1B3A4BBADADADAFABA4A5ADB4AFAEAB9EA4A2ACADA8ADB7A5AB9FAFAEA6B7B6B1BAB2BAAFADA6B7ADC3AC9FB1B5BABAB1B301FEB1000801D810A7B3B1B1B8BAB0ACAFAEABB4A7B7BDB5BAADB0B9B2ADAAABB7B2AFB2ACA3C6B2A8B3BDAFAAB1A7A1A29EA3ABB9C0B0A5A8B1BEB9B4A9AFAAA7B1B4C1BBAFB6AFB1A4ADAAADB5C9BEABB1A6BAB0BDB6BBB2A4B5B4A4A89FB4B8B6A9ADB6B0ACB4B8B9B6AFB5B1AEACAFA8A7ACACAABBB6C2BAB0A7B3C2BEB3B0ADAAAEA9AABAAFAFB0A4ADA8A7A4A6AAB3B0AFB7BBB1B3ABB1ADB4BCB6B4A9B1A7B6B8B0B0B4AFC2BAB0A7B3C2BEB301FEB2000801D820B0B8B1A7A7ACB3AFADABADACA9B5B0BCADB3AFB6B5BBBFB1B3BEB3BCB4B2AEB2B5ACB5BAB7BBAAA6A5ABB7B9A2B1B9B0B4ACB2B2B7BEB9B2B5B4B1BAB6A8ABABA1ABBCB9B1BEACA3ACB3B7ABB1B6BBB1B7B6B9B9AEAAB3B2BBBBB8AFADA5A7A7B19AAAAFB2B7B4B8B9C0B3B2BBBEB3BFB7B0B3B6BCACA19EA3AFABAAB0B2BCB8AFBDC7B4B4B9B2C3ACAEADA9BBBEB7B4ADADBDA9AEB9ADC0C7AFB2B3A7A8ABA7B7B0B3B6BCACA19E01FEB3000801D830A9B3BFB2B1B4B6BCABA8B6B6BDB6B6B7B4A9B2B4BCAEBAB8B9B9B7B7AFB5B2B1ADA9AFBCBFB4B8B5A8B6BFBBAFB3AEABAABCAAB8ABB2A7AEB4B1BAB7BABFB3B2B9B8A9ACA6B8B5ABB2A7AFACB6BAB8BAB8ADB5B3B5BCBABCC5B6B6B8AFA0B6B3ABA7B3AFAAABABAFB9ADB2ADA4C1AEB5A2B1ABB3B3B4BDBBB7C5B7AFB3B1AFABADB6B9C3BEABB7A3AAAFB9B5B4B4B2B2B7B2B2BDBBB9AFA5ABBCBDB2B4BDABB4A2B1ABB3B3B4BDBB01FEB4000801D840B2BFB8B5B1B7B0B4B2B6B7BDA9ACBBBAA9AAB1B5AAAFADB0B6BBB1C0B8B7B0AAA9AAADC6B0B4AAB5B1B8ADB5B3BDC6B2BAA6A9B5B2BDB4B6B6B3C6BABFBABDBCB7C2B9A8A9ADAEBAAFB9B7B5B2B4B8B0AAB6A2AFB5B7ADADABACBAC1AFB3B4C8B7B1B6B5C0B1B1B0A1BEBDBBB4ADB8B8BAAEB1AEB0BBBDB2AABBAFAFB9C1B5BCB1B1AFBAACB5B2BAAEABB8B6BDB6BBB2AFB4B9BCB3B3B2B6ADC5C4C9B9B4B6BABAAEB1AEB0BBBDB201FEB5000801D850B9B3BFC0BCBEC0B7AFBBC1B3B6BEABABB3B1ADB4B0B9BBBFBFBBB9B8BCB1B6B7B5A7B2B3C5C1B3B4B0AAB6BBB3B8B0B2B0B0B5ABB7C1BFBBC3B8ABB9B8AFAEBABCBAB5BBA3AFBAB7BAADB4B5B3BDB1BDAAB3B4A9B6B7B6BEB0BBC4BAACABABADB2B0AEABAEB2C3C1BABFBEC6B8B8ACB6AFAEB5AEBAC0AEB8BAB4A8B0B8B3AABCB8AFB7AFB8B5B3C5C1BBB8B7B6B5BCAAA8AEB0B9C8C6BFC2C1C2ABA4A5AFB7A8AFAEB5AEBAC0AEB801FEB6000801D860B0AAB2B7C1BBBFB7BEB0B7C1B2AFB9B9B3BBBDBCBEC2C6C0B0B7BCB7AFB3B2BCAFB2B5B6B4BBB2ADB5BABBADADAFB3B9C2BFB9B3B0B9B2B6C0BCB5B7ADB3C3BBB8BEBFBAB0AEABB8B0A9B4C4B4B8BBB3B6C5B7C3BAB9ACB5B7B4B7B0ACB5B1B6B0B8BBAEB6B6BCB3ABBCBCB5B2BDC0C6BCC5B6B0ABAAB3B6C0BBB3BDAFB1B1B4B0B1B4B9B8BCB4AEC5BCB9ADAFBAACB8B0BCB0B8B6AEBCBAB8BABFC2B3C8BBBCBCC5B6B0ABAAB3B601FEB7000801D870C3AEB9B4B5C4C5C5C7B1B3A9B0B5B6B0B9BEC1B0B3A4ADC0BEB6B2C1ADB9B6C8BEB9B1B9B1ADBFC6BEC6BFB7B4BCB8B6B7BFBABCBBBAC0C1BCBFB6ABB9B3B3B9B4B9B7ACB4B4BAB9B9BCABA8AABBBBBFBBB8B3BAC1C1B3BAA9BDC2A3B5BBB9BFB2BAB9B1B4ACB3B6CCCEC1ACAEB4ADB7BCBFB6B7B8C1C2B9BBB3BAB6A7C1AFB3B4B7B9C4BFC5C2CDB8B1BAB1B9B7B3BDC4BDACA3B1C6BFC6BEC6BDC9B7B8B8A6BCBFB6B7B8C1C2B901FEB8000801D880B2B6B8CEBDC8C7B6C2C7B8BFC0BBB3BAACB7B1B3B4BEBBBBB8BBB4AFBBBFC7BAB0ACB7B7B9C4BEB9B3C2C3C1C0AEAEBCB3AEB0ADB0AFABBACAC7C6C3BDB4B7C0B2B2B4B7B7B9B1B5BEB8BCB1BBB7B2B7BFB8B1C0BBB0B8C2BAAEBDBCB3ADCEC2BFB5BBB6BEC8BBBABAC0BDBEB9B4B5B6B1BEC1ABB5B6AFB8B2ADB9BBB7B4B4C1B8B6B9B4B7BDB9C5B5BDC4C9B6C4BEBEC3BDC3C3BFB3ADC1B9B7C0B4B0C6C3C8B1BEC1ABB5B6AFB801FEB9000801D890C1C0C0BBBDC9B6C0C0C8C1BBB3ACB3BFB0B3B6CDBBB2BFADAEBBBDB1B2BDBCB9C3C0B8C3CEC4BCC1B4B6B1B9B9B8BBB8B5BDB6B5AFC1BDB3B8BDB8BCC5C8C6C9C1BEC0BEB2B2B9BAC0BDB9C7B3C2B4B0B0C5C7C3C7C3BBC0B8B8BAB3B6B0A7ADB7BDB9C3C4B7B2B4B7BAB6BBBCBCB1BCB8C6CCB8B9BDC6BEC0C6C3BEBAB9BABEBBBDB3B3B9C2B3B7C2C6BBC3C4C3BAC2B5BDBEB5B2B8AFAFC3BBC1B9B9C0B6A4B8C6CCB8B9BDC6BE01FEBA000801D8A0B9BCC0BEBBB3C3BDBEB8A5AFB1AFB3B8BECAC1C3B7BBBDB6B8C1BDB5BFC5BFC7C7BFBAC6C4C7BDC2B2C5BABAB6C5BBADB8BEB3B4B8BBC3BBC3C0C8CAC3BCB9C7C6C8AFAAC0BDBCB7BAB2BEC5BAB5AFB7B9AEBCBBC5BEC0C9B4BABABABBBEC2B8B4BABAC7C0C5C5C0BFC4B6C4AFBDB4B6B9B1B7B7BCB5C3C1C1C5B9B9C2C1B5BCBCC1B4CABDBEBCBAB7C6BBC6C3BEAEC2B9B7BDBAC3C5BDBCBDC5C7B8BCC3C0B9B9B1B7B7BCB5C3C101FEBB000801D8B0BFBDBCC1B4B5B8C5C1BBC0BBBCC0B6B6C0C8BEC4BDB9BBC1BCB5B9BDB6BFB5AEB8C2B6BEB3CBB8BABFBFB4C5C1B9C4CACCB5B4CDBCB7BCC3BAC2C1C2BEB7C8CBB7BDBFBFC9C6CBB8B0B2C5C7C3C6C3B4BCBFB7B6B6B9C4CDBFC8CFC0B8B6C0BAA9BBB7B5B8BABFB8C8BEB9C5C3C6B0C0B3BABEC4C1CDC4BFBCB2BDC2C2BBC2C9B5C8CFC9BAC2B3B4B7C3C2B9BBB8BFBCC8BCBFB8ADAFB7C0BEBEB3BBB9B2C4BEB3BABEC4C1CDC4BF01FEBC000801D8C0B6BBBACDC4BFBCB7BFCABAB3BFBEB7C4BCB5B7BEB9BCB5BCCFBCBDC0C8D4BEBEB2C0C3B4BEB4C1BEBACFC5C2BBBDC3BECACAC3BEB4BCC4C6CAC0BEC0CAC8BFB2ADBBB0C2C0C6C1CDC0BFB4B1B8C9C4BBB4C4C7BAC1C7C0BFC7C4B5C4C1C2C1C6BFBCB7C4BFBDBDBDC4B9BFC1B6BDB9CEB7C5C8BEB6BDB7B8BEBDB8CCCFBFB8C6CFC6B2BFBEBEB9ABB4B1B7C3C5C2C3CBC5BBBEB9C7BEC5BBBEB2BFCDC3C0B6B6B7C5C8BEB6BDB7B801FEBD000801D8D0BEC8C0C1C5C4C0BFC1BDC5D1BFC6BAC0C4C2CDC3B9C3C3BABAB0C0D5BEC0C8CFBBBBC9C1B4C4BFBDC2BABFCBC5C3C5C1C0C2CCC4C3B3C5C1C6BEC5C2B2BBBEC0B5B4BFC9C4C9BABCB7CDB9BDB8BDB3C3C0CABCCBBCC9C4C0BABBCBB0B3BFBBC5C8CCC7C5CCCCCCB6BEC5C5CFC5C0C1B6C0C5BBCCBEBCBCC1CEB9C0BDBBB8BDBCB5B6B3BCB9B2B3BAB5B9C8BDB9C4CDD3C6B8B5BFB4C1C2B8B6C5D3BDBAB8C0B5C0C5BBCCBEBCBCC101FEBE000801D8E0C9C5B9BCB8C0C7CDCECCCDC7C4C8C2C4BBBCC8CBD6C9B5B2BECAC6BEC3C2BEB4B6B0BDBCBDCCC5BBBECDC4C4CCC7CDCDCDB8BCC3BFC6C5C0C6B5BDBDCCC8B7C2BCC5B5BBC7C7C1BAC4C6C2C4C2BECBBFC4CACBBDC2BAB9C7C2CABEB5C6BDBFCAC5C8C1B6CBBEC0BFBBC0B8B9B3BDBEC3CECBC5C6C6C8C4B8B8BFC0D0C1BDC5D0CAC1C4BCBFB1B1C4C2C4BDBBC2C3C4C1C5B8C1C3C3CAC0AFC9C3C7CAC1C2B7BACECBC5C6C6C8C4B801FEBF000801D8F0C6BEC4BAC7CDC1CEBDBCC1BBBDBDBDC8BFC3B3BBC2C3BBC8C9C0CBD2D0CCC4C6C8C7C4C3BEB9BBC3BFC2C6BFBDBDC4C3CEC9C5B4C5CAC7C6C0C6C7C7CDCAC6CABEC0C6C5C1C3C2D2CAC3C0C1BECAC0BDC3ADBEB9CCC2C6C3C4C0C6D3BABEC1C8C0D5BEC4C0C1C9CEC3B5C7C6BBC5C4CEC1C6C2CCBCC1B8B7C2BAC5C1CBC0C5BFC0BBBABFC2CBD4CBC6B7B3C1CCC6C5D3C3C9BAC9BEBEBFC4BDC4C1BBC9C2C5C0C1C6C2CCBCC1B8B701FEC0000801D800BCC4D2C2C7C3CBCAC5CED3D4CCC2C8C3C9C7CCBDB7B6BCC6BDBEBCBDD7D0CFCBC0BFC2D3C4BDC0B2C1CBC2C6C8D4C1CCD5C2CBC6C3C1C4C5C1BECEBDCCCCC1C6BFC3BEBEC2CAC1C0C4CECDCFC5C7C7B7B7C4CCBEBFC7BCC6C4B4B1C4BDC2C5D3D0B3C8C7C0C8CCC9CFC8C4B9BDCCD2CEC6BCBDCAC7C7C3C4BFC6C9C6C3C6BCC3C6C1C1C1BBC0C1B8C0BCBFC1D0CDD1CFCBCBC3BDBEC1D5BBC6C1CAC4C4C2CAD1C6BCBDCAC7C7C3C401FEC1000801D810C2B5C2C5CFC3C6C8C6C9C7C0C7DBCFC8BFB7BFC2C8B8BCD5CAC0C5C4BAC5CEB9C2BFCBCECACBCBC7D2D3BDD3C1C1BABAC4CCC6C4C5CDBFC9DAC8C4CBBDB8C8CACFCAC2D0C8C9C7BFC8BED1BFCCC1C9CBC4C6C8CFC4BDCACCD2BCBAC6CBBCB3BFBEC7BEC4C1C4C3BFB3CFC4C6C7D2C0CECBCBCCC0B2C3C7BFCFCDCBCCCAC9CEC5C0B9C7C0BBC2C5C3C3CACCC6D7C8C5C8C8BFB3C2CCC5D0CBCAD0C1B9BDC5BCC7CBCBCCC0B2C3C7BF01FEC2000801D820C1BABBBEC2BDD2CCC8C6CECEBFC1CCD0D3CAD5D1C3B7BABDBEC9CAC4CCCFC2C3BDC6C6C9D4CCCACCBDC4C1C5C8C6C8C6D2BFC9C9CAC7CECAC4C8C4C4C6C3DBD7D7C9C5CAC0BAC8CEC4B3C8C2C0C5C5C5C5CDCDD0D1CBBAC5BECCB9BAC6C2C8D5DBD7CCC3C2B4B4C6CBCFC3C2C4C9C3BDC4C3C4CDC2C1D5C5BCC2C8C8C6CDD3D0CCD2C8BFCAC4C4D0CFC5CDD0BFC1BACBBFC3C8C5BEC1CABCC5CACEB9C5BDBEC3C4C3C4CDC2C1D5C501FEC3000801D830D7D4CEBEBAC3C3C9C8CDCDD9D5C7C0D3C2CBD2B4C4CCCBBFC8B6D3C4C6D5C8D3C5C6C2CBBEC5CFBABED6D7C6C2C9CAD4CDC2C5C8C8C4C3D4C5CBCED0C5CBCCB7C2C3C0C7BBC1CED2CCC8C3D1D5C6D3D4D3BFCECEC1CCD0C8BEC0C7CAC8BDBDBBC3CBB2C2BFBDCEC1C1C7C4D4CDC9D3D1CBD8D1CAC6CEC9C7C0CAC1BDC8CACEBBB8C8D4CCCBC0C4CED2CCC5C4C8BDCFCFC7CDC8CFC2C9C0D1CCC7C3BECBCAC1C4CBD8D1CAC6CEC9C701FEC4000801D840CDC3CAC5D3DEC6C4CDD0C8C8D5C1C8C8C9C9C8C7CFD6C6CCC7CAC3C9CED6CACEC3C9BBC2CBD7D0C4CCD3D0CBBEC2C4C0C2C6D0C4D3D2CDC3B8CFD4CACBBFBAD2D6D0D7BDC0C5C8C9C9DFCCCDBCC9C6C8C7C2C7CECFD7D0CEBEC2CAD6CBC8CBD3C9CBBABBD6D0CACCC5CDC1BCC8BBC6CBCCD1D4C6BDBEC3D1CAD1C5CBD8D8CDCDB9C2C7D2C5BCC9BDB9C2CCC2C7CCCAC9C2CAC7C9C4CACCCED3D1C0D0D9D2C9C6CCD1D4C6BDBEC3D101FEC5000801D850D4C7C3CBD1CFD3CFC7D7D3CAC3C7C3C0BAC6D9C6D4CCCDCECDCDC2C7D4D1D6D3CAC6C8C6CCC3C4CBCDC4C2D4CDCDCFD1BEBDBBC2D1D0CACBBEC8CCCCDACDD2CDD2C4CECBC0D6CEC3C6C3D9D0C9C5D2C3C0C3C6D2BCBAC9D7CEC5D2D3D3C0BECDD2D2CEDAE7D9E0D2C8CAB8C3C5BACCC9CBC5C9CAD3D0D1D7C6D4CBC5C8C9CFC8C6CACFC8CAD3CEC9BEC7D3C5C8D2CEC6BECEC6D5CCBAC6C7CDC2BACCCAC8DACDCBC5C9CAD3D0D1D701FEC6000801D860D7C9C4CAC1BDCED2D5D6CFCDC7D0CDC2CBC3D8D0C6C9C8CFDAD0D7C0D4CDC2CFC4C4CCD0C0CCC6C4C6CBD7D5C6BBD0D6D4C7BEBEC1D1CBD1CFBFD6D4C5CDC9D0D8CCC8C3CBCECDCEC9D1C4D0DCCBCEC9DDD7D6CFCCCCC7D9CBD7CDDDCCCEC8D5BFC2C6D2CED1D9CFC7BFC8D5BEB7C3D4CACFD5D4CCD1D1CCC6D4D6D8D7CED2D3C8C1C9C3C6CCBEC6C2CEC7C9C6D1D2D4D1D4CCD6B9C1BAC2CECCC7D2CDC8DAD3CACFD5D4CCD1D1CC01FEC7000801D870C9CEC8C9CAC6D0CDC8CDD3D3BCC0D2C6D1CDC5CAD2CBD1D5D6CDC6C1C2CDC1C3D6D1CECEC6CECDCAC0CBCAC7D1C6D0D5D7DED1C7C2D4C6C7CEDAD6D1D0C8D1C6BEC7D4D5DAD3CDCBCAC8CAD5D0D0D1CFCDCACCC3D0C7D3DCC9D7C9CFDDD3CDCACBD0C4C9D4D3CECEC4CBCACDCCCDCCCCC6D0D4D7D5CCCECDD3BFC8C9C9CDCDCBCDD2D2D2D7D5CDCBC9C6CFD3CDCECAC3B7C6BDD0D8D8D4CECBC7C2C3CFD4CECFC6D0D4D7D5CCCECD01FEC8000801D880CEC9C3C5C7D4D6CFC7D1C8CFCDCDC2CCD6CFD6D7D1DDDBCCBFC7C8D4D2D4CAD3C7CEC4BCD4D4C5CAC9C2CADBCAC9D2E0D8C8CAD2CCC7CED4CACED1D2C3CBD8D0D5E1DBD0C9C7C2D3CFC2CDCCCBCFC5D4D3D3C5C4BCD5D6D5C7CAD7CAC9CDDEDECFC8CDD7CCC8D4D7D0CFC4CACEC5BDC0D2D2C8CFD1D9DDCAD3C3D4CED2D8CBD7CBCFD2CACFCCD3C8C8D0D0DAD0D0D6D4CFCCCAC1CDC9CAD0CECFD6D6D1CAD4D2D2D2C8CFD1D9DDCA01FEC9000801D890CFD2CED3D3D4CFD4D9E1D9DCD2C8CABFCCC2BCD0DACACACFC6CCD7D5D3D2D1D9CFDCDBCFD6CFC6BFCEC9D2D2D5C1CED8D3DFD3CACECCCBD4DAC8C6D6D4D8D7D0D4DCD5D8D4BDC8C7D4DCD5D6D6D3BEBFC5C1D7D8D4D6CED1CEE0D5CFDADDD2C7CECAD5D6D4CCCEC9C8D4CCCBCCCDCAD6CCD5DACFBBDADAD2D5D6D2D2CDC1C5CBCBD8CFCDD5CECAC7C7DEDDD6D0CFC6D0D7D0DDD5CADBD6CECCCDC2BECFCFD0D3CCD5DACFBBDADAD201FECA000801D8A0DDCED3D8D9CEDACECADADAD0D8C6CAD2D2C7C7C4CED5D1DDE9E2CFCFD2D0D6C6D7CAD2C8D5CCCFDCDAD2D2CFD3C5D6C7D5C9D3CCD0CBD5D1D0CCCDD5DDD7CFD4DBD8CFCBBECAE2D5CDCACBD3D6D3ECD4BFBDC5CAC8C2C7D5D2E2D8CAD4D9CFCBD7DAD1C8D5D3D6D3DBE6D9CFC7DACDBFC7CCD2D6C0D0D7E0DFD4DACAD2DBC7CFC9D2D9DAC2D3CCDEDAE3CCD8DDDDD7CDC3D8D7DED6C6B7C6CED9C5D5C8C9CCC9C7CCD2D6C0D0D7E001FECB000801D8B0DBC9D3D4DAD6CDC8D4E3E6DAD3D8D9BFC1D2D7D4CDCEE0D7CFC1CFD5D2CED0CED3D1DFC9C9D1D9D2CCD1D5CFCDC7D8D1CBC8D5D3D0D1D5D1CAC5D0D4E6DACED2D1D6CED3D7D2E5DAE0DCD9CECBDECEC2D0D4DDDDC9D1CDD6D2C3D2C6C8D9D2D1DADAC2C1CDD1DFD4D2DECED0D4C3D1D2D5DED8E0DFE1DBDAD7D2D2C2D0D5D4D3D8CCD1D7CED1C7D1DEDBD0D8CED4CBD2D2C8D7CDD0CBD6D7CCD3C9CBC8DBDBDAD5DED8E0DFE1DBDA01FECC000801D8C0D4E2D8E3D8D2DFD5DAD2C6CBD8D7D6D3C7C6C4D6DED2D6CAD7CED5DEDAD9CBC4D1DADDDFD5D8D8D2D8D5CFCDCDCAD5D4CDCFD5D1D8D1CBD6DDD8CDC3CECBD1C5CCD3D9DBD5DDE1E6D6D0D0D2D7D4CFCBD6E0DCD8D5CFCACEC8D3CADBD2D5D7CED6D3CFD8D7D7D7E3C8D4C6CED3CFE1DCCED0CBDEDDDBDFDAC7D8D2C9D5D9D2DFD3CAD0D2D5CFC7CCD9CBD9D3CED2DAD1CDD7DAD3CCDFDCD3E2D7CDD8D5D5D8D3CED0CBDEDDDBDFDA01FECD000801D8D0E1C3CFC6C9D5DBD7D7C9CED7E2DBD3D0CAD4D1C6C8DDDFD1D3D1D0C3CED2DFDDD7E7E2D0CBC8CFD3D7D9C7D1D6D2D7C5DACDCED7CBCFD2DED8D5D7E3D8D0E1DFD3CDDBD5CCDDD6D8D1E1DBDFCDD7D7DDCFDADCE7DAD7D4E0D8D2DFDED2D3D8D0D3D9C7D5DBD7DEC9D4D4CED1CED1CBD0D0DCD7DBD2D8D6D1D2CCD1DED7D0C3CFE2DADFD1D3DCD9E8D4CED2CFDDD7D1DAE2D4D5DBD0D3CBC4C9D8D0D0CDD9CFD2D0DCD7DBD2D8D6D101FECE000801D8E0D3CBD3D0CCDADDDFDAC9CFD5D1D0D1D3D6DAE1E0DDCFD5E6DFDFD3CFDEDED6CEE1DDDDC9C7C8D0D8CFD2D1CED7DDDBDED7D8E4E8E1D3CBDADED2D8CCCCD8D7DAD4D6C7DADDDDD3D3D6D1E2DAC9D4DCD4E5D4D0D3CFE0D1CDCEE0DCDAE2D6C9D0D4D0CFD3D3DAE5D3D8D8D7DAE2D7D6D1D4D6D5D5DDCFCCCDD9D9D8DCDED8D7D4E1D8D9D4CED7D1D5C9D8D1E1D9DEDBD1DDCDD7CBCDD4CAD3D8D0D8E3EEE0DEDCD4D6D5D5DDCFCCCD01FECF000801D8F0EAD5D7CAD1D4D4D0D7CECBD9D2D2E3DBDADBDBDDDBD5D9D4D3DBD7D3E4CBE2CDD3E0DDD7DBD7D1E1E0D7D0E4CFCAD6D7D2CECAE3D9D9D6E3D5E1E8E4D8D2D7CFD9DED7D1D0D6D7DCDADEE4DFD7EDE4D8CFC6D1DBDCDBD0E1D7CDD8D9DDE1CFD1DED3CCCCDDD8D5D9D8D0C4D4D3D1CCE3DCE5D8D3D4DFD6D9E0EBD7CDD3E1D8DFE0D9D9DCE0E1DBDAD5DAD6CED2D3DFE1CACED6D1DCD9E3E6DDE0DFD6CBD1D6CFDCE5D8D3D4DFD6D901FED0000801D800E1D6DAC7DBD4DAD2DCD4E2DACED2D2E7E8D4DAE4DDE1DADCD7D2E4D7D3DED3D3DEE1DDDFD7E2E1D7D5D3CFDAE2DBDABCC4D0D4DCD7DED8D6CFD6D4E5E4DDD9E6D1DCDDD9DED0DDDCC9D1D5D7D4E7D8D2E3E2D5D8D6E8DDDCDCE2D5CEDCD5D0D7DEDBDAD5D9DED9DADAE2DADAE2D4CCD4D8CEC5CCE1CBD5D9DDDADAD1CFE1DAECE2DAD4D8DCD8CED5E0EAD1E4E9D8DBD5D1E4E7D8D8D2D9D8DCD5D6DBD6D5D8DFD8CEC5CCE1CBD5D901FED1000801D810D6DFD6DFDBDBDED5CDDBE1DADFD6D5D8E2DCDBD5CCDADFDDD2E1DFECDADBD4D7D8DAD8DFDDDCD5D1D8DCE5DCE2E3DAE4E6DADFE0DEDFD7D2D8D5DBDBE1DDD6DAD4D4D4E6E1D7D3DBD2CEE1D9DBDFDBECD7CEC7D5D6CBD1D0DBE1DCD6D6D5DED9E6D4DBD5D0D4DBD7E8F0F5E2E1E3DCE2E5D4D9CFD2C7E0E2D6DCDBD2DDD3D4DBDBD6D4E4DFE0E1DEDCD9CDD7E2D6DBDAD9D6C7D2D9DAD5DCE5E7D0D7D8DFEBE8E5D4D9CFD2C7E0E201FED2000801D820DEC7D7DCD9D8D7E6E8E6E5D9D3D9D1CBE1E0DDE4DBDBE6DDCFDEDCD3DAE5E5E1D8E0DBDFDFD5D5D6E4D9E4D7D5DED2D0C8D9E9DBE3EDDDDCE7E3D9DAEBCBD3D8DCEDDEE2E8D8DAD4D9E0E6D6D6D3CDD7DBDCE2E5E0E0D5D8DAD7DAD7DCE7E2D1D9D5CED7D5CFE0D7D7E0EAE7D8E2E0E2D4D0DBDDE7D4CADAD6CFD5D7E4E0DFDBD5E2D8DED5D5D9D5DEDED9D9E2E0DFDED5DAE2DBD6D8D7DEE1E2D6DDDDDADEDBD4D0DBDDE7D4CADA01FED3000801D830DAE4DFDBD9E1E5E8DAD6E8E9E5E8D9E0D9DEDCDCD6D6C9D0CECFE8EAE2DCCFDCD6E9DEDEE0E4EDDEE5E2DDDAD8DDC6D7DEDBD5D9D9DBECDDDFE2E3D9DBE2CCE0E1DFDCE4CFD8D6DBDADAD5DCDCD9EAE3E2E8D5DDE0D9E8D6D8EAE2E1DAD6D5E4DFDED2D4D2D6E2E8DCD6D4E3D5E3F3D5DDE3DEDAE5E7DCDBD1DDE4E3D1D4DBE5E6DBD9DCE1DCD7D6E4DBD4D6DEDADEE7E1E0D7D4D7E3E6EDDDCDD4DFE5E2D3D2DDE3DEDAE5E7DCDB01FED4000801D840D6DEDEDBD1D4D9E4E2DCD4DBE4E7DFD0D8D2E2DEDFECDBD8E3DFE1E7E8E0CFDCDBDCE2EBE2DDDDE4E2DFE3E4D9DFDADDE7E7DBE3D6D9E0E5D4E3EBE3EEDDDED4E2E6E1E3D4D4D4D2DDD5E5E4DADDD9D4DCD8DEE5DFDDDDDFDFECDED9CFDBEBDEE0E1DBE8DEE7DCD7E4EBDFDCCAD6E4DEE5E1DDDADEDDE6E2E2F4DCE3D6E3DDE0E0DFCFD8DDD3CAD7D3DCECDEDDDEEAE3E5E0DFDCDDE4DDE1E5EACFDCE0D7DADFE5E1DDDADEDDE6E201FED5000801D850E5E0DDE5E7F3DAE0E2DDE4D7DFE9E4DCE9D2DCE0D5E0E0DFE4EADCD5D4D9E2DEDBD5D7E0D4D0E7E5E2EDF6DFDCDADFD7DFDDD7E5DEE7DDE6DDD2D8E1E5E2DCCFE7D0E0DEDDDCD3E5D7DEDEE6E7EDE3DCDCE3E3D0E4D9D0E7E3E9DED6E0E6E6E6F0DBDFD7DDD5D5DDDCE3E4DEE7E0DFE6D7D9DFD7D9DBE6ECEDDFDCEBE5E6E2E6E6E0E4E1E2E0D7DBD9D7DDE2D5E1E8D7DAEBE7E7DCD7DDE1D6E3E8E4E2DAD9DDD7D9DFD7D9DBE6EC01FED6000801D860EAEAE3E6D9E4E3E4DDE5DFDFE5E2E9DFE3ECE7DFE3E4D3DBDFE0DDD9E1E0D4DEDBE2EAEBDFDFD7E0DBE9E4DADCE0E2E4DDDDE3E1E1E3DBE2E5DBE8E1E6DCE3D9DDE6DDE5ECE8DFE6DFDEE5EBE0E4E3D8D8D4DBDFDBE5DAE2E1E4EFEBE6EEDCDDDCD8DED3E1E3DFDCEAE3D8DFE5E1DEDCE5E8E4ECE2EADFE2E9EED3D4D3D9DCDED3D8D8D6E0E3E0DBE2E5EAD8EFE4ECE5E6EAE4DBDDDCD1D4CED5D8DADAE5EAE5E5E8E4ECE2EADFE201FED7000801D870E3E5E5DCE4ECE6EDDBDADCDBE4DAE3EAE1E1D6E1DFECE9DBDCE3E4F5EFD4CEDBD7D3DDEBDFE6DEE8E8DDDCDEE6E1DCE9E2E0DADFF2ECDBF1DEE3DEE7EFE4E6D7D9DFE5DAE3E1D9E1E5F0E6D8EAE9DDDADFE4DEECD6EBDDDDDFDFE1D2DBDCD2E8EADDD9E1ECECDEDDDCEFEEE0E3E7EDEDE6DDDDECE8DCDDE6DEE9DAD7E8DEE0DBE6E1DADED2D7E0EBE5D9DBE1E4F0F1E9E9E4E1E3DADCE1E1E3E1DDE9ECE6D6DFE6DDDDECE8DCDDE601FED8000801D880E4E6E5F0E0DDECE8E7E0E4ECE4DFDBDEDCE3E6DFE3EAE8F3ECDCD1DDD9D8DFDFE5EFE2DDEBE9E8D9DDECE0DCE5E1E9F2E6E2CDE4DCD1DAE7E3DFE6EBF4E5E5E1EBE5E2E9DAE4EBF5EFDFD2DEDCDAE5E9EAD9D5DAE1E9E0E6E0ECECE2E2E6DED8E4EAE1DCE6D6ECF9F2E6F5F1DEE1E2ECE7DDDBDCE6E1DAE7DEE1DFE6DADFDED9E7E8E6E4E7DFD5E5DFDDE8E6E6E9E4E3D2E0E9E6F1EEE6E3D7D5E0D6DFE8E6E1E7DDDBDCE6E1DAE701FED9000801D890E6EADDD7DAE2F4E9E8E8D5DFE2D9E7E8E3E3E3D9DAE4F3ECE4E7EBE4EAE7D7E2E3E9E5E8E5E9DFDCDAE0E1D8DBE6EADAE2E2E9E3D8DBEBEFE3DDECF8EED5D3D3E6F6EDE6E1EEEEEDE8F4E1E3EBE9DEE4ECE0E2E2E6E0E5DDE9E6DFD0E0DDDED4DBEBECE1E5EAE0EAE0E8EEE6E0E2E4E8E5F1ECE8DAD9E3E3E4E0E2EBE6EAE9E7E2ECE2E9EAD7DBE1E1DDEBE6E6DDE7F1E9E0E4E5EADAE8F1EFEFD7D4E4E3E9E7E5F1ECE8DAD9E3E301FEDA000801D8A0ECEFF4E8E5E8E0E1E3E8EFF0EDE8E4E9E0E4EBEBE9DAEAE1E9E6DBDAD9DADFECD8DFDFE2E1E7E5E3E8E1F4E4E7E6EBE6E1E5E6F0E0EAEFE3DBD8EBF2E0E7EBDFE4EBEDE2D9E0DFE1EBE5EAEFEBE5DEEAEAEBE1DDE9E7DDE5E9E9F4F1F2ECEEE8E7ECF5F0EEEFE8E6E6F2E8F1F1DFDFE6DAE2E3DCE3E9DFEAECE4E2E9E3EDEFE0EAE2EAE4E6F6DDD8DFF0ECECE3E3E3EBD8E6E0D7DAE2E8EEE8DAD7E7F3E9EAEBDAE2E3DCE3E9DFEA01FEDB000801D8B0EFEAE7DED9EADBDFEEEFE9DDD6D5E0DFEBE3E0E9E2EAE1F2EAD7E4E2EDE6F0F2E4E6E3F1F4F4E9DBF0DBEAEBE7E6E5DEDEDCDCDEEBE3E8EBEAECE2ECEEDDEDF2F7E6F2F1E9DCE4F3EAF1E1EEE9DCE8E5D4DFF9FBECE9E8D9EAE7F5EBE6EFEEEFF2D7E1EFDEE2E2E5EFE1EEE6E8E1DBDBDCE2DCEFE2E6E1F0F2EFE5DCE3E2E3F1EBECE1F1E6E1E6E6ECE7E1E3E5F0E8EBF4E0DFE4EBEDF0E8E2E1DFE6DDEBF1EBDCE2DCEFE2E6E1F001FEDC000801D8C0DFDFEEE9EAE6EADFE8E8DFD8E0E3DFE1E9F0E2E7E6E5F2F1EFEEEDEBE0ECEFEFDCEFF0DFE7E4E4DBE9EEDFEEEDEBE6F1EAE5E6E2E8F3EEF3E4E6E8EBE6EEF1EEE5E7F1E7EAE8E2E3E5E0DCEFEDF1E4E8E3E1DEDCDBDAE5EBE3EDF4F4F4F4F0ECE6E0E3DFDAD6D5E8DFE0E5E6DBEAE3E3DFDEE6E3F1EEF2E5F4ECE3E7EAEFECEBE9DCDEE3EEEDE8F4F1F8EEE8F2EFEEE2DCE5F7E9E4DEDFF3EBDEE5E5EBF2E8E8DFDEE6E3F1EEF2E501FEDD000801D8D0F0E7F2E1E9EBF2F4EAF0ECF0EEE8E8E3E0E7E7E7E5E0F0E7DAEDF9F1ECF2DDEFF0E7E1E2E0E9EBF1E0F2F0EBF3EEDCEAE5E8EEE2F5ECEFF8EFECECE7E3E6D5E7EAE4E9EEDDE8EBEDF1EAE1ECEFEEE8E5EEE8E3E0EBE3E8ECECF9E0E1DCE7E6E3E3DFE4E7E6F0E5DFEDEEF5F2EAE3EAF0E1DFF2F3E5E8E7E3F4F4EAECE6E6DCE5EAF7DEE4F0EBE2DDE7EAE8E8EEE7E0F2F8F7F3DFE8DBE6E5E3E4E7EAE3ECE1F4E1DFF2F3E5E8E7E301FEDE000801D8E0ECDDE2F1E6E4DFEBEFEFF2F1F3F7F1F8EEF0ECE7E3ECFBF5F3F8ECF6EBF1E5EEF5E7EBEAE9F3ECE9E6FEE9EADADBE4E7EDE9EDF1E8ECDCDCF0F3ECE8DFECECEEE1E4EFEBE9F1EAE9EFE3E3FDF4F0F1EFE4E9EFE6F0E5F4F1E9E5E6F5F0FDFDEEE8EDF0E8EDF5EEE8F5DFDEE2DFDDE6E7ECF0DDE5E8F1E9E4F3F4F1F9EFE5E0EBE5EBF5F6E6EFE6EEF9F1E9E3EEECEBF4F7E0F3F1ECE9EDE7E7D5F2E8E3EAEBE9ECF0DDE5E8F1E9E401FEDF000801D8F0F5EEE9EEE8EEE3EBF2FCEEE9EBF3F9DBE3EEE3E1E2EEE8F6EFE9FAEFE4DFE2F6EEFBE8E9E4EDF4FFEEECEDF0E5E7F3F0E9EDF2EFECEDF7F9EBE3E4E9E2E8F2E5E7E9F7F6EFE7E3E7E9F8EEDEF4F2F0EBE3EFF4F1F4F5F5EDE6E8E7E8F7EED3E3E2EBEAFBEEE1F1EBEFF1F7F6F6FCF0E0E6EAE1EAECEEE0E8E8E7F8E9E6EAE0DBECEFFCF5F2E9E1EBF0E5DCEFF0EDF8EAEAFEDCEAF7EEECEBECF5E4E3F0F5ECEEE6EAE1EAECEEE0E801FEE0000801D800E9EEECE6E6DDEEEDDEE7E4EDEFE0EDF2F5E8F3F2FBF2F8EFEDF3EFE9F5F3ECE6F3EFE5EEF4E3EDE4F1EFDFE6EBE5E6E3E7EFF3F1EAF0F6F4EBF3F2E6EBF3E6EDF4F5F6FBE8EADFEEE2F7EAFCF4FFF6F5E2EAE1ECD8E1ECF0EDE8EEF1ECEAF0F0E6EFEEF6F0F5DFE6F2F5ECF2E4EFEFEEF4F3EFF4F4F2EFF1F5F3F1DFE8E3E1E6F8FDF2F1DEEAF2EBEDFDE5EFE8EBF4F9F3E1E5E9EFEFECF3E5E8EDF0F2F0E9F1F4F3EFF4F4F2EFF101FEE1000801D810F6E8E9E5E9FFF5EFE8F3F9E8E8E9EEE7F5F3F4F9ECF5E5EBF7EDEFF3F4FAF5FAEFE2D8EFE7FCF2F5F2EFE4E2EDDFE4F9F8F2EDF2F6F4EDF2F8E9EAEEEAF4FDFAF4E9F4F4EFEFF2F6F1FFF1EAE7E9F0E5E5E2F1EDE7ECEBE9E5F0F8F7FAFCF8EDE6EEE6F1D8E2F0ECF9F3F4F0FAE7E9E4EAF7E7EFF0F5F3EBEFF6EBF3FEF3DCF9F2E9EEF7FBFBF8EEF3F2F6EFF4F4F3ECF0E9EBE3E5E4F3EDE6F3F4EDE4F8EAE2EAF7E7EFF0F5F3EB01FEE2000801D820F9EFF4EBF5F0F0EAEFF9F6F0F3F5EBEFE6E6F4F5EFF8FCF6F3F5ECEDE7EBEEEEF2F7E6EDF7FFF1E8F1F2F2E5EAF1F2F1DEFFF1EDECEEE3EBE1E8F4F1FEF0EFFCFDF4ECEDF2F7F2EFE7EBEDF3EFF7F0ECE8EDEBFEFFF7EDEDFFEBE2F1F1ECF4EAE8EEF7FCECFAEBE9F4EFEDE5FFFCFDF5FFF1EFF4F1EFFDE9F0FBF7E9F2F7F1E8F0EAF0F6EDECEEECF3F6EAF4F4F3E2EBFEF1EBEDF0EDF3EFEEE9F0F4F7E8E6ECFFF1EFF4F1EFFDE901FEE3000801D830E2E8EDECF6F5F8ECF2EDEAF0EEFBF8F6F4FAF4FFF6F6F4E2EEEFEDEAECE8E6F5F6F8F4F6EBEBF6F9F2E9F0F1F6F2EFF2E4EAFAEBF9F0F2FCEFF5F0FCF7F0EDEDEBECE2F4EDF3F3EEEDF0F0E6FCFFFFFCFAE2EBE4EFF0F1F2F8E9F7E5E8E6ECF4F3FBF3E9EFFFFFF4F1FBF5F8F7F7F7F8F1E4E5F7EBE9EFE6EAF1F7F2E8EAECE9F6F7F7F0FFF4F8F5EFF2F7EFE5EAFEFFEFF5F5FAF4EFF0F7E2E2E3FAFDF8F7F9F1E4E5F7EBE9EFE601FEE4000801D840F4FCF4EDF1E9E6FFF5F8FDFBE6F3ECE4F1FFF3F4F4EFFEFAF8FAF9E9F9EEF7F0F0F3EBE2F0F0EBE9EAEBFFF1FDF7FFF9EFF2E9FFEFF6ECF6E7EEEDF4FDFEFAECECF8FBFAFFF3E7F7F6EBEEEAF1F2F1F3EBEDF2F0F3F8F4FCE8ECF9EEF7FEEDF0F4EEE8EAF0ECE9F1F4FBF9F2EFF2F5FFF5F7FCFDF1EFE6F8F1F8F6E8F5EDF0F3E7E4F6F4E4EEFEF8F6F1F3EEF3F5EFEFECF0F9FCF5F6F5F2F7F6E8F1FCFBEFE8F5F7FCFDF1EFE6F801FEE5000801D850F0F0EDEFF4F8F4F7EAF6FFF9FFFFFFF8EEEFECEFEFE8FBEDE6E8F8FBFFFFF7F4EBE8EDF0EFF4F6F9ECE8FCEEFFF2F6F2F4F5ECF7E9F2E7F1F0FCFEF1F2F2F3F5FAF6EDF1F7EFEEF1F8FFF0F1F4EEF8EBF8FCEEF5F1F2FFF5EBFCF0F0FAF9FFF9EBF4F6FFFFFBEEF2F3EFFAF5F2F3FFF9F1F4F5FBFDFAE9F4EFF0F7F6E8EEFCF3EEECEFE7F6F7F1ECECF3FFFAF7F5FCFEFFFAF0EFEFFEFEFAECEEECF7EEF7FBF1F1F4F5FBFDFAE9F401FEE6000801D860F7EFF3F4F7FDFFFBF3F3EEFCEBF9F3FFFFF3F6E7EEFCF6F5EBF2F4F6FBF2F5F5FFF3F1EEF2FAFCF7F6E9F1EEFBFFFFFFFFE9F4F4EEF8EEEBECF5F8F1F4F0F1EAEFFBEBE7F9F4F2FCFFFFFDF5F2F4F5FBFEF3F4F9EEF8F2F1EFFEF2F8FCFFF4FEF8F8FFF0FAF9F6FBF3F6EEEAEFF1F3F7E8E7EAE8FBF5F7E9F2F7ECEDE6F5FBF2F5F5FFFDF7F3FFFDFAF4F4FDECFAF2F3F4ECFAFAFEF8F4F4F4F5F3F8FFEEEFEEE8E7EAE8FBF5F7E901FEE7000801D870F0FCFAF4E8FCF8F4EEFCFFF5F6F1F9FFF6F7FFF8F5F0F5EEF3F4F9F7F5F1F7FCF5F8FCF7ECFAF9EEF1F6EFEDFFEFEEF4EFFFF3F5F4F6FEFFFBFFEEF2EDF4F1F3FFFFFDF8F2E5F7F9F4EBF1FAFAF9FFF4F8F1F4FAECFFF6FCF8EFF9FFE5F0F7FEEAFFFBF4FCFBF6FEF5F0F7EEE0EBF1FFF5F1F1FFFFF4FCFFFFFFF6F6FAFEFBFBE9F7F1FFF2F8FEFDFAF8E5F3ECF8F1F7F7E7EFF2F3FAFEF5F9F7F5F7F1F6FCFFF5F1F1FFFFF4FCFF01FEE8000801D880F9F4ECEBF4F9E9E8FDF1F6FFFEEFF5F6F3F7FBFDF6F3FAFEF8F9F4F3F8FEFFFFFAF3F8F7F8EEFDFFFAFEF1FBFBFDEEF5FFFFF2EAF0F6F2FFF6EBEFF4EAFAFCF3FDFFFCF3ECF1FFF3F9F2EEFFFFFBFFFFFBFFF8F6F2FBF6FFFFF6F3EAF6F6F2F7F8F5EEEBF3F4FDFFEFFFFEF9FDFDFDF0F5F8FDF2ECFBF3F3FCF3F9F9EBFAFDF2F7F8F5F7FFF6FBFAF8F7F2EFF0F9ECFDFAF1FDF4FFFCF8FBF2F6F9FEFFFAFCF5F5F8FDF2ECFBF3F301FEE9000801D890EFFDF0F9FCF3FFFFFFEFFAFFF4FEFDFFF0EDF4F4FFFCF1FFFFFEFFF6F5FFF1E9F2F3F4FDFFF9F9FBFFFFF8FAF5F3F6ECF3FDFDFFFEFDF8FFFFFFF3E7FFF6F4F7FDF4FEF3FAFBF5F8FBFFF9ECFFF6FDFBFFFFFAF5FAF9FDF6EBFCEBFDF8E9FAF8F2F2FFF7F4F4F7F2FBFFFCFCF3F3FBFFFFFFFDF8F9F4F8FAF8F3FDF8F7FFFFFFF2FBFFFFFFFBFFEEF9F7EAF2F4EFEEFFF9F7F4FFF5FAFEFFFBF8FBFDF5FFECF5FFFFFDF8F9F4F8FA01FEEA000801D8A0F4F6FEF9F1FCFEFEFFF6F8FFFBF8F6FAF5F2FFF8FFF4FFEFEEFDFAFDFFFCF1F2FBF4FAFFFFFFFCFCF8FDFAFFFAFAF5F5F5FFFFFFFFF3FFF5FFFFF9FFF6FDFFFFF9EDF9FFFEFCF3FBFEFFEDF0ECEDECFCFEFFFEFFF5FFFFFAFFFFF0F6F4FFF7FEF5ECF6FFFFF9FFF8F9F0F5EBF8F7ECE4FDFFFEF2FBFCF6FDF1FDF9FFEFF2FFFCF2FCF6FAF8FFFFF8FBFCFEFFFFFDFEF8F4F0FFF9ECF9F8F8F9FFFCFFF3FBFFFFFDFFFEF2FBFCF6FD01FEEB000801D8B0FFFFFAF4EAECF0FEF4FFFFFFFFFFF7FFFAFDFBFFFFFCFAF3FFFEFFFFFFFFF8FBEDF9EFFEFAFFFFFFFFF7FEEEF7FEFDFDFFF4FFFAF9FFFEFFFEF5EEF7F3EDFBF9F6FBFBFFFFEFFBFCFFFFFFFFFCFFF6F8FEF9FBF6EFFBFFF3FFFFFFFFFFF9FFFFF5ECEFF2FFF6FDF2FAEEF6F9F7F9FEFFFBFBFFFFFFFFF1FFFFFFF6FBF8FFFFFFFAF2FFF6FEFFFFF1EDF8FFFDFFF4FCFFF8FBF7FFFCFAF8EEF5FBFFFFFFFFFDEFFBFBFFFFFFFFF1FF01FEEC000801D8C0FFFFF2FAF8FFFFFFFFFBF5FAF1FAF8F9FFFFFFF9FFFFFFF2FFFFFFFFF2F8FFFFFFFFFCFDFAFDFFFFFFFAF5F4F1FCFCFFFEF6FAFFF8F3F1F8F3FCFFFEFFFFFFFAFFFEFDFBFFFFF3F9FCFAF6FFFFF8F3F8F7F7FFF0FAFFFFFAFDFFFFFFFCFCF5FEF8FFFCFFF7FAFFFFFFFFFFFEFFFFFFFAFAF8FFFFFFFFF3FEF4F7F6EEFAF9FFFFFFEBF6F7E9F9FAEDFAFEFFFCFEFFFFFFFDFFF8F7FEFFF4FFFCF7FFFFFAFFFDFFFAF8FFFFFFFFF3FE01FEED000801D8D0FAF1FCFFFFFDFCF7FFFFFBF4F7FFFFF6FAFEFAFFFDEEF6F2F3FDF9FFFFFFFDFFFFF7F3FBFFFBFDF6F3FFFFFFFCF6F2FFF4FFFFFFF5FFFAF5F8FFFFFFFFFDF8F8F7F8FFFFFCFFFFFFEFFFFFFFFEFEFEFFFFF7FFFFFFFFFDFDFBFBFFFFF9FBF8F7FFFFFFFFF4FFF8EFECF2FFFEFCF8FFF2FFFFFCFFFFFEFEFFFFF5FAFFF3FAFEFFFFFFFFFFFDF4F9FFFCFFFCF4FFFFFEFAFFFFFFFFFFF2FBFFFFFFFFFEFAFEF2FDFFFFFCFFFFFEFEFF01FEEE000801D8E0F5FFFFFDFCFFFFFFFBF3FFFFFFFFFFFFFFFFFFF3F7FFFBF9FBF6FFFFF2FAFFF8FFF6FDFEF5FFF8FFFFFFFBFFFFFFFCFFFCF5FFFFF7FFFFFFFFFFFFFFFFFFFFFFFDFFFDFFFFFFFFF7E7FDFFF7F5EFF9FFFFFFFFFBFFFFFFFAEFFAFFFBF2FFFFFEFFFFFFFFFFFFFFFDFFFFFAFFF9F3FEFFFAFFFFFAF4FFF8FFFFFDEDFDFFFAFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FDF6FFFFFCFFFFFEF3F2FFFFFFFAFFFFFAF4FFF8FF01FEEF000801D8F0FFFDFFFAF2FDFFFBFEFFFFFFFEF7FCFFFFFAFFFFFFFFFFFFFFFFF5FFFFF2F7F5F4FFFFFFFEFDFFFFFFFAFFFFFCFFF6FFFFFFFEFFFFFFFFFFFFFFF8FDFBFFFFFEF5FDFFFFF8FDFFFFF5FAFFFFFBFBFFFFFFFFFBFAF9FFFDFCFEFDFFFFFBFFFEFFFFFFFFFFFCF8FFFAFEF6FEFFFAF2F1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFBFDFDFFFFFFFFFCF8F6FBFFFEFFFFFFFFFEFFFFFFFFFFFFF9FDFFF5FAFFFFFFFFFAFFFFFFFFFFFFFFFF01FEF0000801D800FFFFFFFFFFFFFFF1FAFFFFFEFFF8FFFFFFFCFFFFFFFDFFFFFFFFFFFFFFFCFEFFFBFEFFFFFFF5FBFFFFFFFFF7F7FFFFFFFFFFFFFEFFF8FFFFFAFFFFFFFFECF8FFFFFFFFFBFFF4FBFFFFF9FEF5FFF3FDFFFFFFFDFFFFFFFBFFFFFFF8FCFFFFFFFFFFF9FCFEF6FFFFFCFFFFFFFFFFFFF9FFFFFFFFFFFFFFFFFFFFFFFEFFFFFCFFFFFFFFF3FFFFFCFFFFFFFDFFFFFAF6FFF8F9FFFFFFFFFEFFFFFFFCFDFFFFFFF8FFFFFFFFFFFFFFFFFF01FEF1000801D810FFFCF5FAFFFFF6FBFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9F7FFFFFFFFFFFCFFFCF8FBFFFFFFFAFFFFFFFCFFFFFFFFFFFFFFFFFFFFFFFFFFF7F4FEFFFFFFFFFFFAFFFFFFFFFFFFFAF8FFFFFFFCFFFFFEFBFFFFF8FFFFFCFCFFF6FFFBFAFAFBF8FFFFFFFFFDFFFFFFFFFFFFFFFAFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3FFFFFFFFFEFFF9FFFBFFFFFCFEFFFFFFFFFFFFFFFFFFFFFFFFFFFAF6FFFFFEFFFAFFFFFFFFFFFFFF01FEF2000801D820FFFFFFFFFFFDFFFFFFFFFFFFF7FFFEFBFFFCFFFFFFFFFFFFFDFFFCFEFFFFFFFFFFFDFFFFFFFFFFFDFFFFFBFFFFFEFDFFFFFFFFFFF5FFFDFFFFFFFFFFFFFAFFFFFFFFFEFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFEFEFFFFFFFFFFFAFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8FFFFFEFFFFFFFCFFFFFFFFFFFFFFFFFDFFFDF6FFFFFFFBFFFFFFFFFFFDF7FFFFFFF7FFFFFEFFFFFFFFFFFFFFF7FFFFFFFDFFFBFFFFFFFCFFFFFFFFFFFFFF01FEF3000801D830FFF7FEFFFFFFFEFFFFFFFFFFF8F3FFFFFFFFFFFFFFFFF7FCFEFFFFFFFFFFF3F2F9FDFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5FFFFFFFFFFFFFFFCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAFFFDFFFFFFFFFAF8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFAFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFFFFFFFFFFFFFEFBFAFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCFFFFFFFFFFEFFFFFFFFFFCF6FFF6FFFFFFFBFFFFFFFFFF01FEF4000801D840FFFFFFFAFFF8FFFFFFFFFFFDFFFBFFFFFFFFFFFAFFFEFFFFFFFFFFFFFFFFFFFFFFFEFFFFFEFBFBFFFFFFF9FFFFFFFFFFFFFFFFFFFFFFFCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6FEFBFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFFFFFFF7FFFFF7FFFCFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFF6FEFBFFFF01FEF5000801D850FAFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFDFFFFFFFFFFFFFFFDFFFFFFFFFFFFFFFCFFFFFFFCFFFFFBFBFFFFFFFFFFFFFFFAFFF8FFFFFDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFDFCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFDFC01FEF6000801D860FFFFFFFFFFFFFFFFFFFFFFFFF5FFFFFFFFFFFFFFFFFFFFFAFFFFFFFFFFFFFFFFFFF5F7FFFCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF4FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFEFFFFFFFFFFFFFFFFFFFCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01FEF7000801D870FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFDFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFEFFFFFFFFFFFFFFFFFFFFFFFFFFFAFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFEFFFF01FEF8000801D880FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAFFFFFFFFFFFFFFFFFFFFFFFFFAFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFEFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01FEF9000801D890FFFCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01FEFA000801D8A0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFFFFFFFFFF01FEFB000801D8B0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01FEFC000801D8C0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01FEFD000801D8D0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01FEFE000801D8E0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01FEFF000801D8F0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF010100010801D800FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 2516 2516 0 02B000600003000900042004300000000004030009001820043001804F00040300090020200430080080000403000900242004300000FF0104030009002C20043001000000040300090040200430FF030000040300090044200430E6030000040300090048200430E703000004030009004C200430E8030000040300090054200430003E010004030009000021043000000000040300090004210430010000000403000900082104300100000004030009000C2104300100000004030009001021043001000000040300090014210430010000000403000900182104300100000004030009001C2104301F0000000403000900202104300500000004030009004021043000000000040300090044210430010000000403000900482104300100000004030009004C2104300100000004030009005021043001000000040300090054210430010000000403000900582104300100000004030009005C2104301F0000000403000900602104300500000004030009008021043000000000040300090084210430010000000403000900882104300100000004030009008C2104300100000004030009009021043001000000040300090094210430010000000403000900982104300100000004030009009C2104301F0000000403000900A0210430050000000403000900C0210430000000000403000900C4210430010000000403000900C8210430010000000403000900CC210430010000000403000900D0210430010000000403000900D4210430010000000403000900D8210430010000000403000900DC2104301F0000000403000900E0210430050000000403000900A0200430EFE100000403000900A4200430000000000403000900B0200430000000000403000900C4200430140000000403000900C8200430000000000403000900CC200430200000000403000900502004300002A8020403000900A8200430FE210000040300090004000038000700000403000900080000380015000004030009000C00003801030200040300090010000038010702000403000900140000380C0C05000402008005FF8307205F820720FF8307205F820720FF8307205F820720FF8307205F820720FF8307205F820720FF8B0720608A0720FF93072061920720FF9B0720629A0720FFA3072063A20720FFAB072064AA0720FFB3072065B20720FFBB072066BA0720FFC3072067C20720FFCB072068CA0720FFD3072069D20720FFDB07206ADA0720FFE307206BE20720FFEB07206CEA0720FFF307206DF20720FFFB07206EFA0720FF8507206F840720FF8D0720708C0720FF95072071940720FF9D0720729C0720FFA5072073A40720FFAD072074AC0720FFB5072075B40720FFBD072076BC0720FFC5072077C40720FFCD072078CC0720FFD5072079D40720FFDD07207ADC0720FFE507207BE40720FFED07207CEC0720FFF507207DF40720FFFD07207EFC0720FF8707207F860720FF8F0720808E0720FF97072081960720FF9F0720829E0720FFA7072083A60720FFAF072084AE0720FFB7072085B60720FFBF072086BE0720FFC7072087C60720FFCF072088CE0720FFD7072089D60720FFDF07208ADE0720FFE707208BE60720FFEF07208CEE0720FFF707208DF60720FFFF07208EFE0720FFFF07208EFE0720FFF707208DF60720FFEF07208CEE0720FFE707208BE60720FFDF07208ADE0720FFD7072089D60720FFCF072088CE0720FFC7072087C60720FFBF072086BE0720FFB7072085B60720FFAF072084AE0720FFA7072083A60720FF9F0720829E0720FF97072081960720FF8F0720808E0720FF8707207F860720FFFD07207EFC0720FFF507207DF40720FFED07207CEC0720FFE507207BE40720FFDD07207ADC0720FFD5072079D40720FFCD072078CC0720FFC5072077C40720FFBD072076BC0720FFB5072075B40720FFAD072074AC0720FFA5072073A40720FF9D0720729C0720FF95072071940720FF8D0720708C0720FF8507206F840720FFFB07206EFA0720FFF307206DF20720FFEB07206CEA0720FFE307206BE20720FFDB07206ADA0720FFD3072069D20720FFCB072068CA0720FFC3072067C20720FFBB072066BA0720FFB3072065B20720FFAB072064AA0720FFA3072063A20720FF9B0720629A0720FF93072061920720FF8B0720608A0720FF8307205F82072000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A0008001003181C1003181C030009000020043080000000040C000100020D0028001400003800006E000000010000008F00FFFF00FF01000000000002000000010000000F00020000000E001000000000000000000005000000000000010F000100011000010002110002006000120001000105000E000C20FD00FFFF000000000208000005000E001020FD00FFFF00000000000500000300090004210430010000000403000900082104300100000004030009000C21043001000000040300090010210430010000000403000900142104300100000004030009001821043001000000040300090044210430010000000403000900482104300100000004030009004C210430010000000403000900502104300100000004030009005421043001000000040300090058210430010000000403000900C82004300400000004150008000000000020280000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 16896 16896 0 01FE01000505C81094599157955A9457975A975B9D5C9F5D975B9359985C9459955A9459985D9259985A995D965A945C955A955D9C5F985D975D9358915B925A945892589259965890579559945A91588F579558905795579559995B985C945992589A5D9A5C9A5C975B93599258985A935991579159965A995C945A925992599559975894599357945897579457925795579258975B925B945B965B9158955C985D965B995D995D995C945A9259925901FE02000505D820975996599259955991599357955799599A5A965C965A985B9D5D985B975C995C9659985C9459985B965D965C9A609C5F96599459935A9058915790568D569258925892588C58965B965A935894559459985798599558925996589A5C975D965A935B935994579558915A9458965B975B985B965B965992579159965990599559965A9557945896589859925A975B945B9459945790599A5C975B9759935D9C60985B965B9659925701FE03000505D830955B9559935A975999599D5898589A5A9C5A985A9759965A985A985C9D5B97589559955B95589456955D9E609A5C9C5D9A59935991589156945893599058975A965A9559965A95579055955691568F55995A9658945994589159995C9A5B9B5B985A9457925895579258985B94569359945A9559985C93569358985A9457945A945796579759935791589659955A975A965C9B5A9158965A935D985D965C975E945A9559985C935601FE04000505D840935A955A965A95599558965A94599959985B995A91599659995D96599B5F995A9A5A995C975B9358955D955C9A5E9C5E96599156955B94579259955691588F57945995598F59945A91569257955794589459975A965A965B945A9A5C985A9659965A965995569359915994599A5B965A995B945A9559935692569259955994579557945991569458995D9557935A955A965C965995599A5C975A965A93599C5D995B945A9559935601FE05000505D85093589257965A965A9758965998599A59995B9A5A975A975A995B98599A5B995B9C5A975A965A975B975C9C5D9A5D9E5B975A9B5B9557945892589458935891569057955897579457935792569655985697579356985A945995599757985A965992599557915896579558965B955A965C98599458975B955894579559965896599958935491558F579859945A9A5C9858955A97599458965B975A9A5D9A5D975C98599458975B955801FE06000505D86098579558995A9559965895579A5A9C5A9B5B96599656985A9A5B9B5B9559985A9C5D995B9558975A985A995A975B995E995A975996579055945B9357925590549458945894589557915390569759955894579155975C9459945A985D975A9C5A985B985996598F58995A97599358965C9959985B995A9556965A98589659975892569957935692599157985A9959995B9558925991579359985E9E5E975C9A5E9959985B995A955601FE07000505D870975795589557975B975893579C589958985A99599959915A9C5B9B5B9A5C9B599A589C5B945994589A5B9C5B9E5A9A5C995C9659935891559456925595599155915A945994569659975891559455925597579758985B93599856965A965A995B9259945892589859985A985997589458995A9359975994589557975793569959975792559656935997599559995C975A975C975A9959985A9358945A935C9A5C995A93599759945801FE08000505D880975795589A599457965897589957995A96599759985A965A9C5D9A59995A975A965A985B9D5D9759975A995E945C9B5C9859945A955996579359915795578F569457975794599357965495559256955697589457985C93589957995A9C5D9A5993599555905594569157985999589D5C985A92589859965695589757975696569A5697579755945796589858965B9B5C995A975891569459955B995C975C9A5D985A92589859965601FE09000505D890925996579A599458995A9A589B5899579B5A9457985796589D5A9659975A94599A5B985A965A97599B5C985B985C9C5C985C94599357975A9455935599589153905696579357935694559657975595569658985A985993579556965A9358975A985A94579659955996599B599759995A9759995A9D599758965996569356965691569254975794559558995A9659995B9658975A955A9557985C9A5B965B9B5D9759995A9D59975801FE0A000505D8A09857975895589A5B945693559A579C599D5A9457975898599C5B96599C5997599759995A9558975A94599A5C995C995B9C5C9457985994579857915494538D57945793589659935692539056955597589B5A9F5B9757945994579C5C9A5C965A935698589959975796579656975896589759945A995A91569357985A965897569357975797569B59955995599758955992589A599458975A945A9D5E995C9B5D9759945A995A915601FE0B000505D8B09959945596579559985999579A5898589A5A9B58975797589A5A9C599B5897579759995A995A975A995B98599C5E9C5B97589156995A9456965A8E559C5A9154935790569257955997569957985795579A579B579A58955698589A599459985896569257955795579556985997589A5A96579559985A9556915697579658935596569456995896579A5A955A9B5B95599959985A91579259975B9F5B965A9A5C96579559985A955601FE0C000505D8C09858965895569659965697579E5A9B5B9E5A985999589A579A5A99599B5A965A99599A5B9B59965797599A5C995B9B5A995998599555965997579455955691559657945592579555965693559756965799599459955694589257995A965A9B59985A9456935899579758965698589B5A9B5893589A5899559054965894579958975693559557975794569558975C9A5B95589758965995599F5A9A5B975B985B9B5893589A58995501FE0D000505D8D0985696569759955699589455985799599C589A59995993569E5A985A9B5A995A97579B59965995599A5B9A5B9D599D5C995896579658915798589657965793569257965592569756925499579857945595579957975994579A59975997579959995993589758945694569456995A99599E5B935798589757945598579756945593559658925594559459975A965796589659975894579B5B9A5A9A5C975A9B5B9E5B93579858975701FE0E000505D8E09857975895589657995994589B589D589B579C599C5A99579657985895589A599A5B9A5D965A99599659995A995B99599B5B985A965A9657935497579357985694599656945595569556965494559756975A99589956965592559A5A9C599C5B9758985597569756945993559458995A9A589459985795559957985A9B5898579A5692519255945795589457975897599C5A98599557985895599D5C985C9D5F9A5894599857955501FE0F000505D8F09A57985798589356955598579D589C579C5A9856955596579C5A97579B5A9959995A9D5A96569A5A9959985C9B5B9A5B9457955A975A9A5997579455995893569757955597579455935594549754965399549658995999569354985898599A5A965895579858975798589557975497599B599B58985895559454995999569B589355965397589455955895599A5A96599A5A975992539859975B9B5B9C5B9C5A9B599B589858955501FE10000505D80099589456945997579959995897579B569456985898599C589E5A9A58995C9A599C5A985997589D5B9C5B9D599C5B9E5A9B59965798589055985696569253935692569A57985695539454965394539455985695579A5896569754975899599C589B58975696559657975694559B589356995A945697579556945697579856975695559957975797569D58985A995894579959975697579A59965B9A5C985B9A5B995A94569757955601FE11000505D8109A5698599858995694569A569C599C589C58975799569457A15B99579A5899589C5A9A57995B99589D5A985B975697589D5A955697569856955696569453955597559554975598549753925497569856955699589B5696559956975799599D59985798569A589A57935592569C5A9958985694559759985796579A579B5597589955935395559A5795579C5796579A589B57985697569B579655975A98599C5B985694559759985701FE12000505D82097599B5795559B579A599A5797549D589D5899569556985A9A5792579A599A589A589C5B9957955796599C5997599A5A9D5998599F5A98579654955395559657965796569655975696539754955697559A549856945796559A569A5A9A589A58975797549657985899569458965597589B589D5A9A589A559454945798579D56955394549A559755945595589B5E96589A589C5A955695579A599A5A9C5D9F5C9B589D5A9A589A5501FE13000505D83098579A599556985799579A569B5498569D599757975695579D5898579C5C93569A5A9F59995897579B5A9A58995A9D5B9958985A985691559557915593569856985599589556965694559552985694549A5895559B58945796549E5A9B589E599C5896539355955896559556995799599E5A9A599D5899579455935596579656955593549B569854965697569558985998589D5A94579456965A9858975A9A5C9E5A9A599D58995701FE14000505D84095559A579A579C5895579C569D559E5798559354975797579E5999589C5899589D589A5996559657975996569A599E5B9C59985798569456925693549556955498579856965797569555975697539553955693579657995998589B5999579F5B985799579B569856935599589B5898589A5798599E599A5493539754985597559554995597549754985A9656955895589958955996589858985A9A5B9C5A9C5C9A5798599E599A5401FE15000505D85098559A5697579856985397559F589D5798569B579D5799569E599B579B5798589C589F5B985799579E599E5A9B599A599A5794589D579A579953935294539855965594559757965392549A54975595559B589A569856975396549F599856985496589F599A579A569A56975698559B569A5794579959995796559958955596569C59995493519153965697569758995798589A5B985697599859995A9858985A9A5794579959995701FE16000505D86095569756975697579B5797549C569E589C599D579A579A559F5B9C579D5897559A579B579B5894549B599B589C599A5B9E589B5A9D569655945695539552945498569A59935498539955975396549655975696569857935498569F599E599A5598569854935697559B56985699569457995997579C599253955696569A589B579A5593539653925394569156965899599558985797569A5A9B589C599C5AA05E995997579C59925301FE17000505D87097569A569856985798569854A1579A579A579A5799539855A05A99569C589D5897569C5699589C5997589B5A9D599F58945697559A579354945496549C5795559556965693549C559654985399549C569A569955985899569B56985699589D599854985697559C57905392559858A0589C589A56995691549A559C56965398569C5592539A5593539B5996559B599A579856975798599D589B599F59995898579C589A569956915401FE18000505D88099579657965698569A5698539A579C569655955497559D589E5B9C599C599D5B97569E5B9A599C5897579B5A9B599E5A9D579756995695559153955296549655985598549254955598549854945599569A5698559D58955595539A5799589D589857995798549A569C56995798559B55985697589B5998559955975795549A569B54955196559553965797589B589A589A579A57945499569D5A9C5897589C5A985697589B59985501FE19000505D8909B569A5697549957975594549C579F57A05997559A549758A05998579D589D5999549A57965798569A599B5898579B5A9A5897579D59925696569655965595569758955499549653945298559A5597559D5696579755965592539C5699579655975799599B5699569B5597589A579B579B5698559C5896559856985496539C5697549551945498569956985799589C589A569F5A97589F5899579F5A97579D599B5698559C58965501FE1A000505D8A09B5898549A55975495549B559A559A539D5796569B5897559B579A59A25A9D579A559557975699579A5A9A599D5B9C599A579957A05999549653915297559455995599559653965499549652945196549C569855955598549A579D589A589D5A9B569A549A57965594559655975597579E5799579A5696549654A05996559B549B5394559B5695539655975599589D579C579E5695559A5696589C589555995A9E5799579A56965401FE1B000505D8B096559C589C55965498559A569F55A1589F559A57995595549C5898579F5A9B559A5795569B569E599F58985799589B559B5998589B589A55995692539A55935397549754935397529854995396549B5498559B56985596539C569C5797579D589C579A54935599549755965497579B59965695569C589855935598569956A0589B5598549A55965395539B549B589B589A579B569A579A589B579F599A5A9B56965695569C58985501FE1C000505D8C098569D569F56985499569A539E5499549B5398569A559A569F5899549F5A9C579B589D5797599A55985598579B599E5A9D59955799549454995694549C55925498569854945598549453975297529A569C579E579C57985397539B5798569D579B5694559456975698579A559A5698579F579B589D5896549A539953975595549555965499569B5798559B569A599A589A559757955597579A58995A9C5A9C5B9F579B589D58965401FE1D000505D8D09C589A559854965698569E549C559F5799549F579B559B589D5598579A5799559B57A05A9A559C579A579F5B9E589E589B559B5795549553985394529653955597569A55995595539653965497529A53995497549553995598559A579A599B5698559B5899559A5798559955985599579B579C549955965296549B569B549C56965596539A5397559B57995498579A569B579A56975799569C589C589957A15B9B579C549955965201FE1E000505D8E09C579D599B569A579C569B549F579E579D569A559E57A0569E5396539D589C5797559C569C579654995A9F5B9E599E589B579B57995699559855945399569253945397559D559C55955195539550995299549B549855975499549C5698569A589B5698549B579755945498569E5A9A58A05797539756955196549A5799559B5698549752975594549A559A579B55985798559F5A955596569A559C589B59A55EA05797539756955101FE1F000505D8F09E5899559B569C569A569D549C55A056A05598569E5599559F5599549E5798559A56A05899559A5499599E599A58A0599C5597559D5796549A569B5499549755965498539853965399549A52985497529A5498559954975498559D579A569D589D579B54975596549A549C55965497549A5798569757955296559C559B539753965496539A56975397539B57985999579D589C57995798559957A0599A579D599A5798569757955201FE20000505D800985499549E569A559A549955A2559F549C5597539C569D559D579E57995398549854A0589E599854A0599C569B579B579D569754975594539B55965499549953905399559A57985396539652995394529C5698559C5595549957975499579A5699589A55965397549A5595549C569956A0599E589D579D54965499549B539952995499559E54985496539B589D5699579955995699569A56975599589B56A55CA0599E589D579D5401FE21000505D8109A549C569E56985499559B549F569F559A5398539B569754A0579C57A15999559D569A589B54995499569F5A9F599D589A599B559B579A5597529655965298549753995296539552965294529A53945396539C569A5498559A5699569A5699569E569A549A5797559A559B5397549B559E569C579B5698539854965297519B5699539453975299539C5699579B579B579D589A5697549A559957A05A9A579A579E569C579B56985301FE22000505D82097539B559B54A05799559954A356A0569E559853955398549B559B58A1589B539B569B55975699559A569D579A59A157A05899579C559A559A55955297539652955399569753975195549751995299549856985396559A5598529B5599569B59975499549B5698559853985598559E589E589A5798559B5699549A55985296529E55965299559A55955497559A5795549C5898559A559D5997579D589B57A1599E589A5798559B5601FE23000505D8309E5496539B55995497549C559E55A2569E569B55995497559B57A0569F579C559A549E57965399529D589C589E579C569E5A97559D55985499549A54925295519953995497549A5399549451975397529C559E559F579C5593509755995499559C5794549C53985396539C5598569E579F569855985599549552975398539A55A0579B539A53965399569B569A569A56995698549A5798579F589A5B9B589C5A9F5698559855995401FE24000505D840A05798539C559E55995595549D549D569D559A569A569C559C559D569C579A559A559F579A5597549F599B589B579D59A05998559A579A55965499539754985599569C5699539A529751955196529A529E559E559A5396539A55A05599569F559B5494529A54965399549B559D569B569A55975298569551975299569C569A5496539D549A529C539B559A5498569C5696559C5897559A589A569B56995798599A5597529856955101FE25000505D8509A539A5497539A5598539B539F53A257A356A05598539752A2569A559E559955A0579B55995495519A569E58A1599D589C5697539A559755995293519C55975397539B5398549A55975298539B5198519A5399549E569B5595539B549A569B549B569E579C56965399519852955497569C5597569D5699549652975298559B539B529951995493539B569A5599589A579E589D579B569E579C5897559C569B599C5597569D56995401FE26000505D8609A539C55985498549B529E549F549C549E549E559B5499539C569B55A0599A559E579C5798549B559A579A569C559D589C5898559B559B559B55955197539A54975498549A559A5394529650985298549D58955398549A5699539F5598549C5699579A539A5698539D5498569D559B549D5698559B569A539550985498529A54985695529B549B5699549A569C559C599B559A5799559B559B58A25999559D5B9D5698559B569A5301FE27000505D8709B559C559C54995497529B539D53A054A459995599559A569E569D549B549B559C569E579B569A5498569E579F579C58955696569F569953975298549953985195549E579854995399549B5297519A549A5395539E5697549F549C5699579C559952995398549C54965396519A5498569D589D5699569A5298539C539D539C539A51995395539B529B5493549D5795539A549B569A589F579B5999579957A45B9D589D5699569A5201FE28000505D8809B5599539B5497529B549E549E55A1549C549C539B539A57A1579854A0579C569C559F5798539955A0569D569C579F579A549D569A5490519853975399549454965297559453935296539D5395509C539D549B52A057945198529B579D579D5599559C569653985192539C5699559B579D5697559C579A54995299569A549C549C5398529C5399549A559753995898559C579B569B559A579C58A0569A559A569D5697559C579A5401FE29000505D890985299549A539C5296529B52A054A254A0579A5397539A56A0589E56A0579D559E579D56995598549D599F579B569E589C589B569C559851965299529A5494519752995595529550934E99529C5398519B559D55995494539C55A0589B579E579C5498519953985498539A549C559B55A1549B549C56975299549853995298519752985197559D559D5497549B57975396559B5699549D569C589F589B58A058A1549B549C56975201FE2A000505D8A09C549E549B539A549B5399549D54A0569B5199549A539A549C559E569F589C559F549954995599559F59A1589B569F579E55945598569B5598529452995395549B5495529852995199529A5297529C51985298529D579A549B539F579C539B5598559C5395519B55995298529C5498549A559C549D56955199549C549A549F5399529653965297529C5499569E5798569B569D5594539B589C589F589B589D5A9A559C549D56955101FE2B000505D8B099559B5597539A54A0579F539B539E52A0549E549F569D56A5589A54A05597529A5495549A539C569E579C569B56A4599C569C55A05597529A529350985497539653995496539A549B519753955197529D5499549A53955399539D559B57A2569D55A05598549851935197549B559D569D579B549F559B54985198549A519A529C539851954F9B539D569A549D589E569554975197539A559E589F5798539C569D579B549F559B5401FE2C000505D8C09B559D559B5598549A5399539D54A054A0549A549E559B559E589B549C559B579A549E579B55995599599E589D5AA2599E559955995196539A5397529753955299549854985496539751965093509B53A0579A55A3579A5297539D559B56A057A0569753985398529C539A519B53965297539E569954995099549C549A549C549A5398539A539B559854975497569A559A569B53955599569B579C599959A55B97539E569954995001FE2D000505D8D095519C559B5297529C539B529E529E539D559852995297519D589F56A0569B549F57A2589754A0559C559A579C57A1589B569D569A539A54975492519A5196519A559B549C54985297539A5297509A519C569C5397539A5398529E549A549E559B559D529A569A5498539C5498529A549D569A5399559C52955296529953985296529A5399529A5598539D579B579E569A569D569A5799559C579D5697559F579D569A5399559C5201FE2E000505D8E0A0569A5499539B5499549C53A0549F539D569B559E569854A05899549E5497549C559F569D569A539A5696569A599F599B559B559753995499559A539552935298529A53975299529A5498539954985299549953A05695529B53995398559B539E559D549E539B539E539B5498539D579C569A569E579B5498559F559A529C5397529C53954E98519E569A529A53985699549954985298549C57A0599C569B599C569A569E579B5401FE2F000505D8F09D579D55A05599529B539A52A2559D52A0569E5495509A559E589C559F5599539B549B569D559A5598549C569E579E579D55995599529B559A5295519E549552975599539A5396529851994F9D53995399539A539C54985398539B589E579E569C539F549451965299549D55995499559C569C569C549B51975398519852975397519B509A4F94539C569A569B589D569B5698539B569C579E57A4599A589E579C569C569C549B5101FE30000505D800985499559B5398539C549D539E53A354A0559A539A539955A0569D559D589B559B55A056A0569E559C569B57A158A2599B5499559A549452975394529852995499549A54995497539850975294509A559C539B549B53965297539E579B57A0589E549853975299549C539D539B5299559E5596549B559850965398549B549B539A52985299539752985399539A5697559C579B559D559A56965598569A569F599E5596549B55985001FE31000505D81098529A539B569A539D589E529952A255A1569A549A529855A1589F55995499559E57A0579C5799559C55935399569E5A9E5699549A549754975396549953995598559E5597529A5297509B5397519A549B5298549F53985298539E5AA156A15699539B549A54955199529A529C569A559B5498549F5698529550995499539D53974F97529952965399559A559B5798569B5499549F579E569C589D579E579E579B5498549F56985201FE32000505D8209C529C5395549A549A539B55A0539D539D5598539E569C549B53A1599F569A549E56A059995497559B569F58A0599F589C559B559B569753985399539E579A519352945395559A539C559B519A549C53995197539751995499519B56995597569F559E55985595529A5498539A559C56A1569D559E55995094529B5599529B539551985196529C559B5497549E5796579F579D55955397549A549C599C579F5AA1569D559E55995001FE33000505D83095539E549D539D5598509D539C529E559D549C54965499549F559D56A056985398549D569C579C549C579E589B569D57A1579B52995194549B5594529751965299549854985597529650985197539B539C549A539D559A529A529C549C57A3579B569B529752945499529A5499539A54A0579A559D56995397529A529D53A0539B5296519852985294539752995598549E56985795559C5699559C589E58A15AA0579A559D56995301FE34000505D8409952955198529C549D559A529D549E55A1579A539A539B5399539C569E569B569753A2579E549B549E569E5698569D569E579D569E569A559E54955299519652965299549452985195529A51995296519C539A529952985496529A5797579C579B559A5598539A5697519C5798549955A15699539B559C5596519A539D539D5395519E529B549B55A054985398549B559952995695539A569B57A0589D56A058A15699539B559C5501FE35000505D8509955985399549E579B5497529B519C549F569B5597549C559E569A579E579B569A549B559C559C559D559E599F589C579C5498569D579853935097539651965198559D54965396539852975296519C549B549C559A5598519953A05798579A569A569755975497539B5598559E549A579C55945498549C5398539F559C559D559B5397519A5297539B5398539D569B569B579B539553985499579E5899589F579C55945498549C5301FE36000505D8609A5499549B559D5195519952A658A2549E5294529854985596539D579E589C569F589B579C569955A1579D589B569B559C569A559A5596549C54955395529554955298539853965198529751975399539C5698539B559B549E559B569A559C549C569A539B559A539855985297539754A0579E579C56995297529B549B529D539851995197539851975496549C589E569853995598549D559B599D5697569C57A0579E579C56995201FE37000505D870975398539E5898539D5598539E549F559C54995497539E589E57A2589C5499549B549E5797549D559E579C579A569F57985597569D559A559954925196539552995399559955995397519550975099509B549B549E5798529752975499569C569A579A54985498539C56955399539B569B569C579C5498529A549A5397519E55995299549A549A54995499569B5496569B559D56965598569A5697579C589C569B569C579C54985201FE38000505D8809C5497559F549B5497549A539F53A4569E559C539A549A529F579F579D559B559A549D579C549D57A0589F579856A05897559954955396529C5399539A54965496539A55985195519752975297519A5198529B539D54985395539D569E589C559C559753985298529252985499559B56A3599C549D569C559652975399539D5598539B549C52955199539A53995494559A56985499589D5898579C589F5A9B57A3599C549D569C5501FE39000505D8909A53985397539752985299539C53A155A2579B5497549D579E569D569C579C5599539B559C5597549B5697569B56A0579A5699579E569554955394529954965499549554975399549752944F955099539B5598539B559B5598529C5698559D569A569B54995598549753975598559E5699539B559B58974F96529E56975299529B52975397529A539C5798559B599F599954985498559B569B5699569B599C5799539B559B58974F01FE3A000505D8A09C5399529754945198539A539B539A539C549A539B549A569E569A56A0579D589C569C5598549A559C579D579D599F569A579A569C5498569853965198559753985599539552975194539A53935197519C549A539C5698539A559D589D579D559A549A53925198549A54935396549B569C559C569A569A549553965399549F559E5398539752965297549C559A5799569A55995596559A569B569E599A56A15B9C559C569A569A5401FE3B000505D8B0995597559B54995399559F559D56A3569D5496549B559B56A05A9B55975295559E599B569A569B569C579B569A599B579C5898579854975397569752945397559D56995695519A5396529852995399539B539E56995395529952995797579C579B589C53955295539A5496559B559955A35896559B56965199539C559B5798539A5296539652975599569E579856995696569B55965396559B59A15A9D5A9F59A35896559B56965101FE3C000505D8C0985395529B559A5299549D539E569C54985298539954975399559E579E5799569B55A05A9E57995697559F589C579E589E589857985393549A54975396509552975393539554965294519B54995198529A539955995496559A539A589C57A0599D569D55955398559A53995599529A55995598549F56965498519A5495529B539751985498519B549A5599569B559A569A55955394549A569A569D589C599F58995598549F56965401FE3D000505D8D096549A5494559D559C539E55A2549C549B56975699549B56A0589C549A57985497549C57975696549B5897549F599B569C559858985696549754935495539A53965496539554975498549752975398549D5499549B55995497539C599F599F589B579B54945399539453985397559957A056965597569A53965399559953985399539752985199559B5699569A579A559554985698569E5796569B579C59A158A056965597569A5301FE3E000505D8E099549653945398569C549957A156A0559E559A55985399549E589C569A55965597579D5796569B569B59A1599E589D58995696549C5593529653935194529E5594539C579754995294529A51985398529A5298539A559752965299589B5699569B569B5497549853945396559B56995597549B579B55995499569E5695539A529850955399539553995596549857995697559B5697569B5799579E5898589C5997549B579B55995401FE3F000505D8F0965596569A559C55955399529B549C569D559A579B5794559E589B579B5697569D579A5596549A559A5698599A599F5BA057985698579854975390539854965097559B569A54975296529652985295529A569A539953985498539C5698559C5597529A549554995495539754985397559E5697559A589653935296559A529C5499549453995598549753965699589C5794559E5799589D579C599A5595569E579E5697559A58965301FE40000505D8009C539854975499559952935099549A539F5598569F5698559E579B57A05798579D579F589A5599559A5797579A5A9E589F579B56965498539754935295549654945798559A56925196539C549A5295529B549A549755975599559C589B57985399559C5599539B549853955397559A579C5599589C56965391529C549651975298549B52965494539C5795549B589D5797579A5796559B5699579C579A599B599C5599589C56965301FE41000505D8109954975396549B559A559B559854A1579D569753945598559D589B569A5899579D569B5697579B579956985799589D5A985596569B589556955390519955935395559A5595549A5595529652965399549A53965497539B58975399569B579C569A57965599569A53995597569A5696539E5696569F579A5795539A5499549A5397529153955393539A58975696579A589B589856995596549B58A15A99589A589E5696569F579A5701FE42000505D8209A549756935396569A5598549C589E55A65A97569A559B579E589E549A5599549B549B549B55995598569B579C5A995A9A58955399579655975396539855925394559A5598549B5695529450945092539E569A549F5698539C579B5598559D5798579854955396539954975595549A579856975499559953925296549A5697549652985395559954965597579A579C5899579C589854955599599D599B5A9E5C985697549955995301FE43000505D83095549B589B569954965499549A5799569A549C569D5699549D56A15A9B5795569A579C57985697579D5998589C59A1599B56985596539254985598559654955296539453935396539453965291539655985693549A5797559353975595579E59995797589B55955597589C57985496559A5795579755975696569E579854985394539355935292519A59995697589756975797579C5798599B5898589759A05C9A5795579755975601FE44000505D8409A5497579A569A569A5597529A56A0569F559755995694559D579D579955975597569C57965497579A579E5A99599C589F599455955596569C549451995493549656985793559352975594539A569851995696539B5897549A569A5797579B579A579655975495559454985595539B599A579A589C579B569653995496549754995599539652935397549A5998599A5694549855905496589B579C5796579B599A579A589C579B5601FE45000505D85092579A589356975797589A599A579A5A9B58935695599A599B5B995B99589558985D9D5B9656975A9B5A9358975D99599B5A9056905699589154915697589558935695569155915692538E549655935693559056965692599558935B9A5B985A955A985893559558965895569356975B9457965A9959945993589859945895589656945694559657955A96599459925A9659955895599558955A9A5C9659985E9457965A9959945901FE46000505D8609658935694569A57975796579D58985597569155965792569C5D99589A58945A975B9659965997599759975D975A99599459965A975B935893568F54935691599359925893589656905592569656955796589456965797599459995B95599858965992569556955690589457995693589658965A9A5A975894569B5793559A5995559053915593579659965B9659965A9359995A955A985B995C985B9459945B9658965A9A5A975801FE47000505D87091599556995B955998579455985996599A5C9959935894599B5A9459975C945A935A995C92589457985B9C5C965B9C5A975A9357975A90588F5691569056905799599558945692559054935593589156935895589958935A98599859945A955A985A9557935692589056935A955998599A5C9B5D99589458945997589255995A92549154915694559458965B9758915991569157965C985B975C965B965B995A9A5C9B5D9958945801FE48000505D8809359935591579658945897589D599A5999589A5994589459995B9759975A9559955C9A5A95589458995A9659985A975A9B5A935793569059935896589056935893589557935691569454905695579B5899579155975991559158965995589657955995579358945A935993589658935A995B995C96589355905792579959965B965893579457915593579458955A975A9359975A9357955C995B925A985D9B5C995B995C9658935501FE49000505D8909758945894589357925A96599859975B995A94589358945A975A985B945C985B975C9B5A9659975B965A985C965B995D975B925A9358905790588E57945794579158905790569357955791579456955794589756955B945A9357955B9A5B95599458955890589557915893599559945C9C5D955997598D5590599A5A935995579257905692579358935993599159925A985B925B965D97599559935A945A955B9C5D955997598D5501FE4A000505D8A0915894589357905893589559975996589A5B9257955B955B9558975C9B5E995996599A5A91579358985B975E995D955B965B9459975D915792589258905892598F57925A8D5592569157955A9357945893569A5B975A93579057975C9259955A925996589659955A95589559995B965B955A9759975891579557975B9658985992568F569357935691588F57945994579759965C9158965B975D975A9259955D955A97599758915701FE4B000505D8B0955A9659945A965A975994589559985A9A598F588D58975C9A5D985B945B935A93599359945A955A9B5F965C945B9B5E965A945B975C925990588E57905892578D55945891578F578E56925890568F589259955995579359955A945C925A93598F58945C975A925993598F5B965A925A945A965B955A93579258965A935A945993578F5693579559975A9359965C935D955B955A925B9559965B985B925B945B945A965B955A935701FE4C000505D8C090589257975B945A94599659965995589659955A95589557965C965C985C955C915A9A5E975D995A985D945D925E9A5E945A915A965C91578F5690568D58965A8E59915B9258935993559055905697599458955A92598E56925A955B925A9A5D975B935A92589659955A90589259975D975B965A965A90548E55915994579459975991549156915995598D58935C965B985C91599159955D945A955E975D955C975B965A965A905401FE4D000505D8D092599459955A915C955C945A9859975A965A955A9157925A955A985B985C955E955C945C9357965C955D985D975D965E945B905A92598F5A93578F58945A955B93598F588C58935A8B5693578D5592589559965B935991599259965C905B945A8F58905A935893599359915A945A985C965C955C945994579057945992578F579359905892579159935C915A955C915D975C90588E5A955C945F945D935F975E965C955C9459945701FE4E000505D8E09559915891588F5A94598F599B5B985C975B965D945A935A9A5D985B915A945A905C935C905B935B985C945E9660985D975C975E955C8F5991578F578F5792598F5A955C925A90578F568B58905893589355915B915A9159955A945B955C965C935B925B925C985B935A9258925B975C955C965A965A935A9057935B8F579058925991588E5891588F588F59925C955D955C9459925A935C965D945C935D985C955C965A965A935A01FE4F000505D8F0955C965B935C9058935C975B975B9A5E9D5A905A935B955A935C975C955C94588F5B955C8F5B915B915E955F985F945E975E8F5C945C9257925A93588F588E578E5A93598A588F5992598D578D56915C955B915C945C90579159955E945E975B955D8F578F599158925C945C945B945E995D915B925B90599059965B945A95598E5991588F588F5A915B915E955D935B8D59945C945B925C935F915D965F955E995D915B925B905901FE50000505D8009459925C91598F598D5A915A9A5C985C985B955A975B925C945D995D965C915C945C9A5E975D925B955D935C965D975F985E915A90578E588E5A8E5691578C5A90598A5A8F598F598D5990588B56945C975D8F5A975D9559915A925C8F5B975C935C915993588C59955B905A905C945D955B965B8F5A9258905A935B9159955C9258925A8D579059965C8F5B945C905C925C945D8E5A945C935D9B5F955E975F955B965B8F5A925801FE51000505D810955E925A8D598D59905B935C965B985D955D945C925C8F5C965E945D955C905B905A945C8F5D8F5C9C5E96619B5F945D915D8B5A915C8E5C905C8E598D598C578D5E925C8F5C905B93598E579058915B925C915B945A8E5A905A935C965F955F8F5C8F5B8E5A8F588E5B8E578F5A925D925D935E975E925C8D5A905C925A935B92598C5A935B905A935C915C915E935C905C905C8F5C985D945F96608F5E985F925D935E975E925C01FE52000505D820955D945C8F588F5C945C9059995B915B935B925C945C955D975E985F975E925D945F975C945A935C945A955F8E5C935E955C8E5B8E5A905A905B925A935A915A935A905A8F59905A90578B57935B935991599259925C915A8E59915D965E945A915C925B915B8B59905D935A915B9560985C945B965C8D598E5B935A965A955A93598D5490598F58915C915B945C8C5A905B925D925F935E9560985F9360995F985C945B965C8D5901FE53000505D830925C925B915A8E5C935F915C935D975C955D97609559915B945C935B925D925F955D905E9460955D975C925C945E965E915C915E925C8D5A8E5A905B8E5B905A925C905B935C8F598D588C588E5A8D58925B935D935A8D5B8E5B945F905D965F965D945A915B8D5A8F5D915D8D59955C925C905C935D93598A588F5A8C59945C90588D588F59905C945D915E945B8C5B925D945E945F9460905C965E9461925E925C905C935D935901FE54000505D8408F5B8F5B925C925C915F905C995E965C965D905D915B925F915D955F945E935E915B925E925D935E945F9360975E945F975D8E5B925C8D5A905A8D5A8F5A915C905A915D8D5A8D5A8F58905B8E57905A935B935C975C8E5B945C925E975F915B905B925C8C5C92598E58925C8F5C925C925C925B8E5B92598C5A905C915C915C925A8B5A8D588A59935D8C5B8E5F8E5F955E9660925E945E9360956196619461925C925B8E5B925901FE55000505D850925D8C5A905C8F59905C935C975D915D945E915D925B8E5C98619660945E945F8D5D925C915D8D5D8D5E915F95629460945F8D5B8E5C915D8C59905C905C8F5C905B945B8E5C8C588D588F5A905B915B945D905B8F5C8D5A8E5A905E915F955E905D925C8D5B8E5C915C8D5C8F5C925D945E935E925E915D8C5B915D925C8E5C8D5B8F5A8F598F5B8E5C915B915B915F8F5E8F5C945F925F925F945E9460955C945E935E925E915D01FE56000505D860905B915C8E5A905C915C925C985C915D985F905A8F5B915E925B935D955E905F935D935F955F8F5D935F945F9361935E8F5C905E905C905D905A88578B5A8D5C905C925D915C8E598F5B8C598C59915C945D945E965C8F5A8F5D955E9460955F8F5C915C8C5A8E5B8E5A8E5D8F5E925D98618F5B915B8D588B5B975F915B915B93598D598D5D955C90598C5B935E905C8F5D935C895C905E925F905F9561925F98618F5B915B8D5801FE57000505D8708E5E945E945D8E5E8E5D915B8E5B94609560925C935C916197609660955F8C5B8E5D935E8F5C8D5C905F936191619962965E915B8C5D8E5C8D5C895A8E5E8C5A8C5C8B5D905C8A5A8E5A8C5B915D905D925B8F5C8F5D8B5D8B5C915F9460925E8E5C8B5B905D8E5B8F5E9160915F8E5E925E925E8F5D8D5C8F5A8B5C905D915E8F5B905B8D5A8F5F8F5F8F5C8F5F905E905D905F8C5E925F9363936090609561925E925E8F5D8D5C01FE58000505D8808C5B915F945D905E925E915D935F965F955C905D935D8E5E925E9260935D8E5C935F935D945D8C5C906096618F609662925C8E5D8E5D8A5A8A5A8A5B925F8D5B8C5E925C8D5B905B8B598F5D915B945F935B8D5B8F5A8E5C8D5D93608F60945E915F9059895A8B5E915D8F5B915D8E5C94608D5E935F8E5C8E5E905D8F5D8F5A8B598E59905B8D5C8D5E8F5C946091619361925C8F5E925F8E6196608C5E976194608D5E935F8E5C01FE59000505D890905E8E5B8E5C9260915D905D93619260945B915F935F905F905F915F94618F5F8F5F91608E5E8D609462926090619061915F8E5E915E8A5C8C5D8B5D8B5E8A5D905E8F5E8F5D8E5B8B598D5B8D5B8D5B915D8C5D905D8A5D8E5D9162946293609060915C8D5D8F5D8F5D8E5C8B5D935D925D8E6093608F5C915F945C905F925C8C5A8E5B8A5B8E5C8F5D8F5E8E5E8C5C90608E5F8D60915F8E62925C91628F61925D8E6093608F5C01FE5A000505D8A08F5F905D8C5D905F915E925F935E925E95608B5C8E5F93629460915D9160905F9160905E905F8C5D9161905F9164956095618F5D8E5D8C5C8D5C8A5C8C5C8E5A8A5D8C5C905F905E905A8C5A8D5B905D935D8F5C935F8A5A8F5B936090629161915F925C8A5B8E5B8E5D925B8E5C8F5F905D8D5C8F5C8D5E8A5F905C935D8D5E925C905D8D5C8A5B8F618E60905E8E61945F8D5F905D8F619262906093649462905D8D5C8F5C8D5E01FE5B000505D8B08C5D8F5F905E8B5C8F60915F8F60916094628E608D5D8F62966193628B5D88619162965F8D5E8D5F90628E62916393648E5F8D5D8C5C915F8E5D885A8A5E8D5F8F5F8F5F8B5B8B5A8A5D8D5E895C895C905E905C8F60925F8E5F905F8C5F955F8E618C5B8C5D8C5F905E8D5F8C5F906291608C5F935F8E598A5C8E5C8C5E8F5E905D8C5D925E8A5C8C5E8C5E916190618E62926094618E5F906091618F62916091608C5F935F8E5901FE5C000505D8C08E5F8F618F5E8D5D8D5C8E5B8E5F925D90608F609060906192618D6091618C609060916197608B5C8D5E91638E63946192608E608E60925F8C59875D8B5E8B5B8C5B91608B5C895D8D5B8C5985578A5D935F8B5E8F5F8B5F8D5E935F8F6197608D608E5E90608D5D8B5C8F5D905F8C5F94608D609260905E8A5C8E5D8C5F925E8C5D8D5C8C5E8B5D8D5D89618E6190619363915E8C5E8E5F8B61946292648F6294608D609260905E01FE5D000505D8D08C5C8D5E905E8A5D8E608B5E9063936392618D5F90619161946190618D5F8D628D6092608B5E906092619063906592618F608D5F90608D5E8B5E885B8B5D8B5B875D8C608C5C8B5F8C5E8C5E885C8C5B8860936090628F5F8F618D618E6193628A5E8F5F8E5E8B5D9060875F895F8D618F60885C8F618E608A5F93638F6191628C5C885C8C5C8C5D8E618D608A5F8D5F8E5F8D5D8B5F91628F638F61916294618F60885C8F618E6001FE5E000505D8E0905D895E8E5E8F5F8F608E5D925F9362925E8F618E5E8C6093628D608D5F9364956496628D5E906089608E618E63906392608C5F8C5F8A5F90608A5E8A5D8C5E8D608F628F618A5B885B8B5C8B5E8A5D92608D5D8A5E8B5C895D9264906291638D608E608A5E8F608E648D60905F9160925F8A5C90608B5A885E91618F5F9060895B915E8C5C8C5E8D5F8A5D8A5D8B5E8B608E5E8D628E628E6093608C649264925F8A5C90608B5A01FE5F000505D8F08E618C62926090628C618C5E8D5E8E608E5E89608D628F60906391648E648F6192628F618E628C608D6194648D6194638E628A5F8D618C618E5D845B8A608A60895E8A5F885E8C5E885D8A5D92638E5E885E8B60916290618A5E8F6492628C608E608D5F8B608F608B5F8B5F8F628B628B608D6290618E5E8A608B5F8B60925D8C628C608B5E8E5F8A6089608C618B5F8E618D628E638B608D638F5D8C6393648B608D6290618E5E010100000505D80087608C5E8D628E6092618E5E936292618D618F608C608D5E8C608E5F8D6191628E638F618C608D639161926493638F6290628E63895E895F8D5F8B5F8F60895D8A608F61875D8B5C8B5D875B8B5F8B619162905F8D618C5C8A5E8D618B6191618D628D608A5E8E5F8E5F8C5E8D609066905F90638F608B5F8B5E8D608C5D8C5E865E8B608C5D8A5E8A608C5F8B618E638E648E618C5F8B619061916491639063905F90638F608B5F +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 2742 2742 0 02B0001C0003000900042004300000000004030009001820043001804F00040300090020200430080080000403000900242004300000FF0104030009002C20043001000000040300090040200430FF030000040300090044200430E7030000040300090048200430FF03000004030009004C200430FF030000040300090054200430003E010004030009000021043030000000040300090004210430010000000403000900082104300100000004030009000C2104300100000004030009001021043001000000040300090014210430010000000403000900182104300100000004030009001C2104301F0000000403000900202104300000000004030009004021043030000000040300090044210430010000000403000900482104300100000004030009004C2104300100000004030009005021043001000000040300090054210430010000000403000900582104300100000004030009005C2104301F0000000403000900602104300000000004030009008021043030000000040300090084210430010000000403000900882104300100000004030009008C2104300100000004030009009021043001000000040300090094210430010000000403000900982104300100000004030009009C2104301F0000000403000900A0210430000000000403000900C0210430300000000403000900C4210430010000000403000900C8210430010000000403000900CC210430010000000403000900D0210430010000000403000900D4210430010000000403000900D8210430010000000403000900DC2104301F0000000403000900E0210430000000000403000900A0200430EFE100000403000900A4200430000000000403000900B0200430000000000403000900C4200430140000000403000900C8200430000000000403000900CC200430200000000403000900502004300002A8020403000900A8200430FE210000040300090004000038000700000403000900080000380015000004030009000C00003801030200040300090010000038010702000403000900140000380C0C05000402008005FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F20720FFF3072080F207200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A0008001003181C1003181C030009000020043080000000040C000100000D002800A02104300100000001000000010000000100000001000000A02104300000000073000010010000000E00E00000010001000100000000000000007E0000010101000100000000000000007E0000010101010100000000000000007E0000010101010101000000000000007E0000010201010101000000000000007E0000010401010101000000000000007E0000010801010101000000000000007E0000011001010101000000000000007E0000011001020101000000000000007E0000011001040101000000000000007E0000011001080101000000000000007E0000011001100102000000000000007E0000011001100104000000000000007E0000011001100108000000000000007E000F000100011000010002110002000200120001000E05000E000C20FD00FFFF000000000208000005000E001020FD00FFFF00000000000500000300090004210430010000000403000900082104300100000004030009000C21043001000000040300090010210430010000000403000900142104300100000004030009001821043001000000040300090044210430010000000403000900482104300100000004030009004C210430010000000403000900502104300100000004030009005421043001000000040300090058210430010000000403000900C8200430040000000405000E001420FFFF00FF0000000000008300150008000000000020280000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 4928 4928 0 01FE01000000C8106E686E686D686D686D686D686E686E686E686D686E686E686E686E686D686E686E686E686E686E686E686E686E686E686E686E686D686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686D686E686E686E686E686E686E686E686E686E686E686E686D686E686E686E686E686E686E686E686E686E686D686D686E686D686E686E686E686E686E6801FE02000000D8206E686E686E686E686E686E686E686E686D686E686E686E686E686E686D686E686E686E686E686E686E686E686D686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686E686D686E686E686E686E686E686E686E686E686D686D686E686E676E686E686E686E686E686E686D686E686E686E686E686D686E686E686E686E686E686D686E686D686E686D686E686E676E6801FE0100000088105A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4E5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D594D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D594D5A4D5A4D5A4D5A4D594D5A4D5A4D5A4D01FE0200000098205A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4C5A4C5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D594D5A4D5A4D5A4D5A4D5A4D5A4E5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4D5A4E01FE01000000C81037213721372137213721372137213621362137223722372237213722372236223722372137223722372237213621372237213621362137223721372137213621362137213621362137223721372136213721372237213621372136213721362136223721362137213721362136213722372137223721372136223721372136223721372137213621362137213721372237213621362136213621372137213722372137223721372101FE02000000D82037213721362237223722362137223621362137213721362137223722372137223722362136213721372237223722372237223722372236213721372136213622372136213621372137223621382237213621372136213621372137213722372237213721372137213621362137223721372236223621362137213721372137223722362237213621362136213722372136213721362137223621372136213621372236223621362101FE0100000088100F030F040F040E030F040F040F040E030E030E030E030F030F040F030F040F030E030F030F040F030E030E030E040E030E030F040E030F040F0410030E030F030F030E0310040F040E030F040E040E030F040F0410040F040F040F040F040F030E040F040E040F030F030E040F040F030F040F040F030F040F030F040F030F040F040F030E040E030F040E040E040E030F030F040F040F040F040E030F030F030F040F040F030F0401FE0200000098200E030F040F040F040F040E030E030F030E030F0410040E030F030E030F030E030D030F040E040F030F040F030E040E030F030F040F040F030F030F030F040F040F0410040F040F040E030E030F030F040F040E040E030F040F030E030E040F040F030E030F030F040F040D030F030F040F030F040E040F040F030E040F030E0310030E030E030E030F040F040F030F040F040F040E0310040F040E030F030F040F030F040E040F0401FE01000000C810080B090C080B080B090C090C090C090C080B090C090C090C080C070C080C080C080C090C080B090C090B080B090C090C090C080C090C090D090C090C080C070B090C090C080B090C080C090C080C080C090C080C080C080C080B080C080C090C090C090C080C090C090C090B080B080C080C080B090C090C080B080B070C090C090C090C090C080C080C090C080B0A0C080C090C080B080B080B090C090C090C080C080B090C090C01FE02000000D820090C090C080B080C090C090D080B090C080C090C090B090C090C090C090C080C080C080C080B080B080C080C090C080C080B080C080B080B080C080B080C080C080C080C080C080C080C080B080B090C090C090C080B080C080C080C080B090B080C0A0C080C090C090C080C080C090B080C080C080C090C080C090C090C090C080C080C090C080C090C090C090B090C080C090C090C090C080C080C080C090C080C080C080C090C01FE0100000088100F190F180F190E180E180F190E180E190F180E180F190F180E180F190F190F180F190E190F190F190F180F190E180F180F190F190E180F190E180E190F190F190F190F1910190F190F190F1A0E190E180F190E180E190F190E180F190E180F180E180F190E180F180F190F190E190F190F190F180F190F190F190F180F1910190F180F180E190F180E190F190F190F190F190F190F190E180F180F180E180E180F190F180F190F1901FE0200000098200E190F190E190E180E180E1810180F190E180E180F190F180F190E180F190F190E190F190E180E180E190E180F190F190E180F190F1910190E180F190F190F190E190E1910190E180F190F190F180F190F180F180E190F1910190F190F1910180F190F180E190F180E190E190F190F190F190F190F190E19101910190E190E180F190F190F190F190E180E190F190F190E190F190F190F190F190F190F190E190F190F190F190E1901FE01000000C8101A251B261A251A251A2619251A261A261A261B261A251A251A261A261B261A251A261B251B261A261B2519251A261A251B261A251B261B261B261B261B251A261A251B251B251C261B271B261B251B261A261B261A241A261B261A251B261A251A251A2619251B261B251A251C261A261B2619251A251B261A251B261A251A251A251A251A251B261A251A251C251B2619251A251A251B251A251A2519251A261B2619251A251B2601FE02000000D8201B251B261B251B251A251B261B251A251B251A251A251B261A261A261B251B261B251B261B261B251A261B261B251A251B261A261A251B2619251B251B251A251A251B261A251B251A251B261B251A251A251B261B261A251B251B251A251A251A251A251B261A251A251A251A251A251A261B251A251B251B261B261B251B2419251A251A251A261B261B261B251A261A251A241B251A251A251B251A251A251A261B251A251B2501FE0100000088102F3B2F3B2E3C303C303C313B303C303B2F3C303B2F3B2F3C2F3B2F3B303B2F3C2F3B2F3B2F3B2F3A2F3B2F3B303B2F3C2F3A2F3B2F3B303B303C313C323C303B2E3A2F3B2F3B303B303C303C2F3B303B303D303C303B2F3B303B2F3A303B2F3C2F3B303C313B303C303B313C2F3B2F3C303C303B303B2F3B2F3C303B2F3B2F3A2F3C2F3B2F3B2F3B2E3B2F3B303B303C303B303B2F3B2F3B2F3C2F3A303B303B303C303B303B2F3B01FE020000009820303B2F3B2F3B303C2F3C303C2F3B2F3B303C313B2F3C2F3B303C303B303B303B2F3C2F3B303C2F3B2F3B313B2E3B313B2E3A2F3B2F3A313B303B303B303B303B2F3B303C303C303C2F3B2F3B303B303C2F3B2F3B2F3B2F3B2F3B313C303C303B303B2F3B2E3C303C303B303C2F3B303B2F3B303C303B2E3B303C2F3C303B2F3B303C303A2E3A2F3C2F3C303B303B313C303B303B313B303B303B2E3A2F3A2F3C2F3B303C303B2E3B01FE01000000C81045544553475547544754485548534754465446534754465347554754475546534754475547554755485447544754475347544755485446544855485547544754465447544754475447544754485546544754475447544754475446534554485447554554465447554754475446544754475446534854485346554853465446534553465347544653485546544754475447544754455446544654465447544753475446534854485301FE02000000D82046524854465347534653465446544754485547544654465447554653465346554753465347544653455347544654465447544754465547544756485447534854475446544654465347554855475446534754475447544754465447534853475446544654475546544754475446534654475446544754475547544754465548554754475448544654485446544754465346544754485447544A55475548544554475446544754475501FE01000000881059655965586658645A665A665B665A655C6659655B665A655A655A6659665B665A655A6659645C665A665B665A6559655A655B6759655B665A665B665A655B665B665C655A665A665B665B665C665B6558655A665B655A665B665A655C665B665B655A665A655A665A665C665B665A665B655A65596559665B665A655B655A655A6557655A65596559655C665B655A665B665A665A655A6659655A645A6459665B655A655965596601FE02000000982059665B655A655B6558655A65586458645B655C6659665A655A6658655B6659665A6558655A665A665B655C665C6659655B6659665A665A665A665A655B655A655A655C665B665B6659655B655A655B6657645B6659665B6659655A6559665B6559665B655B6659655A655A675C675B665B665B6558645B665C665A6559665A665B6559655A6659665A665D675C665C675A655A665B665A645A675A665B655A665B665B6558645B6601FE01000000C810656E686F666E676E666F666E686E676F676E676F686F676F656E666E666F666E666E666E676F666F676E676F676F666F666F666F686F676F676F676F666E666E666F666F676E676F666E656E676F666E646E666E656E656E656E676F676F666E666E666E686F666E666E656F656F676E656E646E656F666E656E666F686E676F666F666F666D676F676F676F666E666E666F676F666E656E676E676E686E686F656E646E656F666E01FE02000000D820676F656E676E666E656E656E656E656F686F6870656D656E676E666F6870676F686F696F686F676F676E666F656E656E666F666E666F666F666F686F696F686F686F686E666F676F676F676F666F6970686F676F686F656F666F6970676F666E686F676F6870676F676F686F676F666E656E666E666E656F666E666E666E666F696F676F636E676F6770676F676F666F676F656E666E666E666E676F676E676E656E666E666E656F01FE010000008810777A7879777A777978797879777A77797779787978797779777977787679777977797779757977797879787A7679777A777A76787879787A78797779767A7879767A787A777976797779787A777A77797679777976797779757977797779787A78797779767976797678767977797679777977797778767975797679787A797A7779797A7679777977797879777977797679787A7779787A7679777975797779777977797778767901FE02000000982078797779777A7679777977797779767976797679787976787679787A787A797A7779777A797A787A77797679777977797779787A7579777A7779787A787976797678777A77797779787A77797879767976797678777976797779787A787A77797879777A7779767876797779787A787A777978797679787A777978797979787A77797879787A78797879787977797679787A77797879767978797879787A7779777978797679787A01FE01000000C810777A787A797A787A787A787977797779787A7779777A797A7779787A7879777A787A787A787A797B797A787A787A7779797A777A787A787A787A7779777A797B797A787A797A7879787A787A7879777A797A787A787A797A777A787A787A7A7B7A7B7A7A787A777A777A787A787A777A787A787A787A787A787A797B787B787A777A787A7A7A797A787A7779797A797B797A797A797A787A797B777A797A787A787A787A787A787A01FE02000000D8207779777A7879787B787B7879787A777A777A787A787B787A797A787A787A777A787B797A7A7B787A777A787A787A797A787A797A777B7979797A787A797B787A777A797B797A797A787A797A797A787A787A787A797A797A787A777A787A787A787A787A787A777A787B787A777A787A7779787A787A787A7779797B787A787A797A7A7A787A787A787A787A797B787A7879787A797A787A787B777A797A787A7779787A787A787A01FE010000008810797B797A797A787A797A797A7A7B797A787A787A787A787A797B797B787A787A787A797A7A7B777B797A797A787A787A797B797A7879787A7879787A7879787A777A787A797B787A787A797A787A777A787A777A787A7879787A787A787A787B787A787A797B787A797A797A787A797A7879787A787A797B787A787B797B777A787B797B787A787A797A797B787A787A787A797A787A797A797B787A7A7A787A7879787A787A797B0101000000009820787A7A7A787A7A7A787A797A777A777A797A787A787A797A787B787A797A787A787A797A787A787A7779787A787B79797A7B797A787A797A797A787A787A797B797B787A787A787A777A787A7779787A787A787A7A7B7A7A787A787A797B787A797A787A7A7A797A797A787A787A767A787A777A787A797A7879797B797A787A787B797A787A797A787A787A7A7B787A797A787A7A7B787A787A777A787A787A787A777A787A797A +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 2612 2612 0 02B000200003000900042004300000000004030009001820043001804F00040300090020200430080080000403000900242004300000FF0104030009002C20043001000000040300090040200430FF030000040300090044200430E7030000040300090048200430FF03000004030009004C200430FF030000040300090054200430003E010004030009000021043030000000040300090004210430010000000403000900082104300100000004030009000C2104300100000004030009001021043000000000040300090014210430010000000403000900182104300000000004030009001C2104301F0000000403000900202104300400000004030009004021043030000000040300090044210430010000000403000900482104300100000004030009004C2104300100000004030009005021043000000000040300090054210430010000000403000900582104300000000004030009005C2104301F0000000403000900602104300400000004030009008021043030000000040300090084210430010000000403000900882104300100000004030009008C2104300100000004030009009021043000000000040300090094210430010000000403000900982104300000000004030009009C2104301F0000000403000900A0210430040000000403000900C0210430300000000403000900C4210430010000000403000900C8210430010000000403000900CC210430010000000403000900D0210430000000000403000900D4210430010000000403000900D8210430000000000403000900DC2104301F0000000403000900E0210430040000000403000900A0200430EFE100000403000900A4200430000000000403000900B0200430000000000403000900C4200430140000000403000900C8200430000000000403000900CC200430200000000403000900502004300002A8020403000900A8200430FE210000040300090004000038000700000403000900080000380015000004030009000C00003801030200040300090010000038010702000403000900140000380C0C05000402008005FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F24720FFF3472080F247200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A0008001003181C1003181C030009000020043080000000040C000100010D002800A021043000000000010000000F00000000FFFFFF01000000A021043000000000011C02B0010000000E001000000000000000000000000000000000000F000100011000010002110002002000120001000105000E000C20FD00FFFF000000000208000005000E001020FD00FFFF00000000000500000300090004210430010000000403000900082104300100000004030009000C21043001000000040300090010210430010000000403000900142104300100000004030009001821043001000000040300090044210430010000000403000900482104300100000004030009004C210430010000000403000900502104300100000004030009005421043001000000040300090058210430010000000403000900C8200430040000000405000E001420FFFF00FF00000000000083000300090084210430010000000403000900882104300100000004030009008C2104300100000004030009009021043001000000040300090094210430010000000403000900982104300000000004150008000000000020280000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 5632 5632 0 01FE01000404C81037213722372237213621372237213721362137213721372136213622372237213721372137213721372137213722372137213721372138223721372137223621362137213722372137213622362136213621372137223621362137223722372237223721372136213722372237213721362136213721372237213621372137223722362136213721362237223721372237213721372137213722372236213721362136213721372201FE02000404D82036213722372137213722372136213721372237213722362137223721372237223722372237223721362136213722372137213722372137223722372137213721372137213722372237223721372137223722372137223622362137223721372137223621372236213621372237213721362136213722372136213722372237213721372237223722362137223721372136213721372137213722372136223722362136213722372101FE03000404D83016001600170016001600160016001600160016001600160016001600160016001600170017001500160016001700160017001700160016001700160016001600160017001700170016001700160017001600170016001700170017001700160016001600150016001600170017001700170017001600160015001600180017001700160016001700160017001600170016001700170016001600150017001700170017001600160001FE04000404D84017001700170017001600170018001600170017001700160017001600160017001600180017001500160017001700160017001700160016001600160016001700160017001700160017001700150016001600160017001700160016001600160016001600160017001700160016001800170017001600170016001700160016001600170016001700160017001600170017001700180017001700160016001700170017001600170001FE05000404D85000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE06000404D86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE07000404D87000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE08000404D88000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE09000404D89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE0A000404D8A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE0B000404D8B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE0C000404D8C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE0D000404D8D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE0E000404D8E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE0F000404D8F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE10000404D80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE11000404D81000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE12000404D82000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE13000404D83000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE14000404D84000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE15000404D85000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE16000404D86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE17000404D87000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE18000404D88000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE19000404D89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE1A000404D8A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE1B000404D8B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE1C000404D8C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE1D000404D8D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE1E000404D8E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE1F000404D8F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010100000404D800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 2625 2625 0 02B000200003000900042004300000000004030009001820043001804F00040300090020200430080080000403000900242004300000FF0104030009002C20043001000000040300090040200430FF030000040300090044200430E6030000040300090048200430E703000004030009004C200430E8030000040300090054200430003E010004030009000021043000000000040300090004210430010000000403000900082104300100000004030009000C2104300100000004030009001021043001000000040300090014210430010000000403000900182104300100000004030009001C2104301F0000000403000900202104300800000004030009004021043000000000040300090044210430010000000403000900482104300100000004030009004C2104300100000004030009005021043001000000040300090054210430010000000403000900582104300100000004030009005C2104301F0000000403000900602104300800000004030009008021043000000000040300090084210430010000000403000900882104300100000004030009008C2104300100000004030009009021043001000000040300090094210430010000000403000900982104300100000004030009009C2104301F0000000403000900A0210430080000000403000900C0210430000000000403000900C4210430010000000403000900C8210430010000000403000900CC210430010000000403000900D0210430010000000403000900D4210430010000000403000900D8210430010000000403000900DC2104301F0000000403000900E0210430080000000403000900A0200430EFE100000403000900A4200430000000000403000900B0200430000000000403000900C4200430140000000403000900C8200430000000000403000900CC200430200000000403000900502004300002A8020403000900A8200430FE210000040300090004000038000700000403000900080000380015000004030009000C00003801030200040300090010000038010702000403000900140000380C0C05000402008005FF8307205F820720FF8307205F820720FF8307205F820720FF8307205F820720FF8307205F820720FF8B0720608A0720FF93072061920720FF9B0720629A0720FFA3072063A20720FFAB072064AA0720FFB3072065B20720FFBB072066BA0720FFC3072067C20720FFCB072068CA0720FFD3072069D20720FFDB07206ADA0720FFE307206BE20720FFEB07206CEA0720FFF307206DF20720FFFB07206EFA0720FF8507206F840720FF8D0720708C0720FF95072071940720FF9D0720729C0720FFA5072073A40720FFAD072074AC0720FFB5072075B40720FFBD072076BC0720FFC5072077C40720FFCD072078CC0720FFD5072079D40720FFDD07207ADC0720FFE507207BE40720FFED07207CEC0720FFF507207DF40720FFFD07207EFC0720FF8707207F860720FF8F0720808E0720FF97072081960720FF9F0720829E0720FFA7072083A60720FFAF072084AE0720FFB7072085B60720FFBF072086BE0720FFC7072087C60720FFCF072088CE0720FFD7072089D60720FFDF07208ADE0720FFE707208BE60720FFEF07208CEE0720FFF707208DF60720FFFF07208EFE0720FFFF07208EFE0720FFF707208DF60720FFEF07208CEE0720FFE707208BE60720FFDF07208ADE0720FFD7072089D60720FFCF072088CE0720FFC7072087C60720FFBF072086BE0720FFB7072085B60720FFAF072084AE0720FFA7072083A60720FF9F0720829E0720FF97072081960720FF8F0720808E0720FF8707207F860720FFFD07207EFC0720FFF507207DF40720FFED07207CEC0720FFE507207BE40720FFDD07207ADC0720FFD5072079D40720FFCD072078CC0720FFC5072077C40720FFBD072076BC0720FFB5072075B40720FFAD072074AC0720FFA5072073A40720FF9D0720729C0720FF95072071940720FF8D0720708C0720FF8507206F840720FFFB07206EFA0720FFF307206DF20720FFEB07206CEA0720FFE307206BE20720FFDB07206ADA0720FFD3072069D20720FFCB072068CA0720FFC3072067C20720FFBB072066BA0720FFB3072065B20720FFAB072064AA0720FFA3072063A20720FF9B0720629A0720FF93072061920720FF8B0720608A0720FF8307205F82072000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A0008001003181C1003181C030009000020043080000000040C000100010D0028002021043000000000010000000F00000000FFFFFF010000002021043000000000011C02B0010000000E001000000000000000000000000000000000010F000100011000010002110002002000120001000105000E000C20FD00FFFF000000000208000005000E001020FD00FFFF00000000000500000300090004210430010000000403000900082104300100000004030009000C21043001000000040300090010210430010000000403000900142104300100000004030009001821043001000000040300090044210430010000000403000900482104300100000004030009004C210430010000000403000900502104300100000004030009005421043001000000040300090058210430010000000403000900C8200430040000000405000E001420FFFF00FF00000000000083000300090084210430010000000403000900882104300100000004030009008C210430010000000403000900902104300100000004030009009421043001000000040300090098210430000000000403000900A02104300000000004150008000000000020280000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 5632 5632 0 01FE01000008C81085738673857385738673877387738673877386738673847386748774867485738673867386738573877587748674887486748573857385738573847285738473857385738573857286738573857284738773867385738573857387748774857386748673857384738573857387748673877486738773857383738673857386738672857385738472867486748774877485738674867486748574867486748673877486738773857301FE02000008D82087738473877386738572857387748673877387738473857386748774887486738774877486738674867486748573867487738573867486738572857385738572847384738573857385728573857485738673857387738573857386748673857387748673857384728572867386738473877486738674867384728673867386738572857385738573857385738574867486738774867486738574867486748774877486738674867301FE03000108D830896F896F8A6E896E8A6E896E8B6E8B6F8B6F8A6E896E8B6F896E896E896F896E896F896E896E886E896F8A708B708A6F8B6F886E876D886E876E896E886D876D886E8A6F876E876E886E886D886D876D886E876D896F896F896F8A6F8B6F8A708B70896E876E8A6F896D886E8A6F886E8A6E896E896E886E896D896F896E8A6D896E8A6E866C876D8A6F886E896F8B6F896E886F886E886F8A6E8A6F896F8C708A6E896E896E886E01FE04000108D8408A6E8A6F8A6E896E8B6E876D8A6E8B6E8A6F886E876D896E8B6F8A6F8B6F896E896F8A6F8A6E8B6F896F8B6F8A6F896F896F896E886E8A6F886E876E896D886C886E896F886E886E886D886D876C886D886D876E896F896E886D896F8A6F8B6F8A6F876E896E886D896E8A6F886E8B6F8B6E896F886F896E876D886E896E896E896D886D8A6E8A6D896E886E896F8A6F886E8A6F876F8A708A6F896F8A70896F8B6E896F886F896E01FE05000208D8508F688C678D678D678E6791688F68906990698E678C678C678D688F688E688F698C6790698F6A8E69916A8E698E69906A8E698D698C688B668B678A658A688A678C688C688C698D678A678C678E668A668F678E688D688B678D678D688C67906A90698E698D678D6790688A678B688D678E698C688E688C6688678C678E678E6689668B678D678D698D688D698C688E698C688E6990698D698F6A906A8B688E698E698C688E688C6601FE06000208D8608E678D678C688D678E688D6791688F6891698E688D688D6890698F688E688C688F69906A90698F6A90698F698F6A8E688F6A8E698E698D678A668C678A678B678C678E678D668E688A668E668C678E668F678B668D678B668D688D698C678C688A678E698B688E688F698F678E688E6890688D688D688D668E678D678B678D678E668C688A668C688C678A688D698B688F698C6A8F688E6A8E6990698D698E6990688D688D688D6601FE07000308D8708F648F6591658F638F649164916493659266906591638E6493648F64916691669266916692658F648F659267906792679266916590648F648E638C638F648C638E638E648F648D638C6290638C618E6290648F6491658F648D6491668F65906590648E6490658E638D65906390648F649265926590658F638F648F648F6490648E6491638E638B648E638D6590668F658F658D65906590678F679466936792679265926590658F6301FE08000308D8808F638E6492648D648E6492649365946491658F648D648D649266926694669065926692648D649066936790679166936791668E6490658F658E638D648E648E638F6390658C628E648D638C628F638E659364916590658E638F649165916591668F6591668F6393648E638E648E64906492658F65936490648E6390638D638F638E628E628F628E638F658D658F64926792659166916591658F658F658F66956892658F659364906401FE09000408D890935F945D955E935F955E945D955E965F985F9A5F965F9860955D98609760955F945D985F945D935E945F986096609A62945E935D915C935D915C945C945C8E5C945D8F5C935E955C8F5B935C935C965E935D985F935D915B925B925E97609A60995E955E935D935B915D945D945E915D965E945F965E925E935D945D975E935B935C945B965B8F5A905D955D945E9560955E935F945F96609460946094609A62965E945F965E925E01FE0A000408D8A0945F975E935D925E965F955D995E955B955E915C935D945F9A61985E985F955F93609960925D935E955E956096619A61985F945C945D935E935D8F5B945D905D925D925F8F5C945C945D935B945C905A965D965E965D945F935C9760945E965F945E925C945D955D955F985F945C955E975D955E955E975D915A925B925C945C8E5A935D935D945C965E935F9660955D925D925F915E956098629860975F9662975D955E955E975D01FE0B000508D8B09B549C549B549C55A0559953A053A0569D5599549B539E569E559C55A2579A559E539F579D5696519C589C579E589F579D549A5297559A5395539953995498549754995497529751965194519B539C53995398529D559B539A539F559F559B5499559B539C549A539A539E549A53A0569B539C55985599519A529D5498539E559B5297519B539C559D529C559C559C559952995394559A5497569D56A158A4599B539C559855995101FE0C000508D8C095529B529751965197539552A056A1559F55975298519654A3579955A0599A559F56A2589D57995499569E59A1589D569A5399549853985294509A539C5499519B539D559A549452934F9952985297529E549B549A53995296529C569D569E569E559854985299559A5398529C549B55A3579A549953965196509C53A0549C52965199519751994F99569A539B5698549D579F569A559E5698569E569D57A059A3579A549953965101FE0D000608D8D09E4A9E4B9F4CA44CA14AA74BA44BA249AA4CA04EA74B9E49A14CA44DA94FA64DA14BA24A9B4AA64FAA4F9F4EA54DA44FA14E9E4A9F4A9B4A9E4A95479F489F4BA149A04A9E4A9F479E489A459B45A34BA14BA1469F4C9E4AA24AA148A64C9F4DA04CA04BA34DA24CA24B9A49A04CA44FA14CA24CA249A04A9F4AA34B9948A24B9A47A2499D479D48A34DA34CA24DA04B9E4DA650A34A9C49A750A750A650AA4FA14CA24CA249A04A01FE0E000608D8E09E499E499F499E499F4AA448A54BA44DA74CA14B9F4B9E49A950A24CA64DA14EA34BAB50A64EA24AA64CA54DA14CA74FA34C9E4CA44DA14B9C489A469B489C4A9D499D499D48A24AA249A0489D499F48A44BA1479D49A04AA24AA8509E4AA74D9C4AA2499B4799499D4B9848A24DA451A44EA44DA14AA1499B48A44B9F48A04BA14AA5489F499E48A04A9E4CA14F9C499949A34EA04BA54E9F4DA2509C4DA74FA44EA44DA14AA14901FE0F000708D8F0B536AC32AD32AD35AF36AD34BA39B735B737AE32AA32B039AE38AE35B43BB238B638B43BAC38AE38B53CB23CB73DBD3CB337AA30AE36AD38AC34AB30A831AE34AB33AB38AB33AA31A42EAF33A72FAC2EAC31B637AC34AF32AD35BA3BB438BB3AAD35AE34AF32AD30A732B734AF33AE3AB135AA35B336AD35AC34B636AC31B333AD33A932A32CAC38B438AE37AE36AD39B038B938A931B338B239B038AF3BB638B135AA35B336AD3501FE10000708D800B232A931B335B239B338AD33B835B635BD37B133AF33B135B133B338B83AB73BB437B337B536B238B43ABA36B53ABC3AB03AA631B232A634AB32A331AC32AB34A733AD35A631AC35B233AB2FAB2EB136B134B638B035B235AD2EB83BB638B435B337AB33A92EA531A635AD34A735B237AE34AF35B038AE32A031AD33AD33AE32B032AB30AC30A730AD33A835BA3DB13DB237B338AE38B139B93EB93CAC3BB83CAE34AF35B038AE3201FE11000808D810BA17C01CC218BA1BC41FC117C81ECA1BCF21BE1CC21DB419C623C623D723BA1BBE1CC71FC61EB71AC01FC022D029C622D027B91FC21AB816C019B61BBE19B618C121C41CB215B513B315B917C61CBE17C417AB11BD1BB819C91FC71FBC1ACE22C21CC31CC41CAE18C11BBF19B518BF23C41BBA1FC920BC18BB16BE1CC918C01CC119BB17C319B515B71BC51BC71EBA23C520C220BA21C41FBE1DC82AC01FC525C41BBA1FC920BC1801FE12000808D820BD19C119C71DBE18B715C319CC1AC219CA1CBC1BC219B518D022BF1BCA22C720C223CD21C31EC01BCB26C319C022C91FC421C319B91CC71EBD17B815BD19BD1CAF17C71CB317BE1EB612BE18BC15BB15B217C11CBD19C01CC41BD420B61DBC19C322C61EC21FBC19C61FBC15B617BF1ABA19C320C61DBD17B717BB19C21FC718BB17B612BF19BC17C422C021C322BB1CB420C71EBF1DB717B61CC827CB28CE28BA19C320C61DBD1701FE13000908D830CA08C403C805D60CCC0BC301CD03D307DC15DC0FCC03D00DD812DA15D00AD30CCB07CB0FCD0DC703D20BD617D40FD20BD315C70DCE0BCB08C307C40AC605BF02CB07C106CD08C000BB01C804C207CA05CD0ECE10C606C406C605CE0BD40DC90BCB0ACE08C202C200C70AC20DCD0AD313D10CCC0ACB0AC205C40BD00BCB0BC60BC606C307D90BD40DCF0AD90ECC0DCD0CC305CC0AC30AC508C20BD10FD117E014D10CCC0ACB0AC20501FE14000908D840CC0ACD0BC604C80DC90AC602DD0AD408E20FCF06CE09CA07CE0ED00EDA10C70FD40CD50FCE0ECD08D113CA13DA18DB11D50CC008C604CF09CC05BD01C103C904C804C207CB08C607C100CB01BB00CA06CE05CF0AD40AC703CD09D80CCE06D510D005C405CE06C701C102CC0BCC0CD912D608C207D20FCB04D309CD09D105E00DCC00C500CC02D10CC504C90BC50BD00DBA03BF09C40AC10DD410D814D50FD614D608C207D20FCB0401FE15000A08D850DC00D700D500E600D900DE00DE00F000EB00E000E600DB00EA00E800E700DE00DF00E800E500E400EB00E400E300EE00D300D800EB00D000D300CC00CE00D500D600D900CC00D400D200D300D300DD00E000D200D800D600CD00E300F100E300E400DE00D200CF00D300DE00D500D000E400D800DE00E400DA00E000E300E100D600CB00DA00D400D100CE00EB00E500D900D400D200E500E100EF00DA00EF00E400D800DE00E40001FE16000A08D860D700DB00D300DB00D800E600E100F900EB00DE00DB00E100F100E000E300DD00DF00EB00E800D800E000E701E200E900E600EC00E800DA00D500D000E100D000D300DF00CC00DB00CD00D700CC00E000D500DA00DC00D500E200DC00E600EC00DD00D900CF00D700D700DC00CF00DE00D700E000E900CE00DA00F500E400D800CD00D900DA00D500EA00D600E600D900DC00CA00C900D700D500E000DC00E300D700E000E900CE0001FE17000B08D870F300E300F400F700F700FF00FA00FF00FF00FC00F200F200FF00FF00FB00F500FF00FF00E000FA00DC00FF00FF00FF00FF00E900FF00E300F100EC00E600E700ED00F600E300F900E900F900E300EE00FB00FD00FF00FD00E300F400FA00F900F100FF00E300E600EA00E700F000FF00FF00FF00FE00EA00EF00E600E900F900F600E100F300F400FB00EC00F300F400EB00F800F100EB00F000FF00E800FF00FF00FF00FE00EA0001FE18000B08D880EB00F900DE00ED00F800F800FF00FF00FE00FA00F900FF00FF00FF00FF00EB00FF00FF00F000F100F700F500FF00FF00FF00EE00FF00F200DF00E100E600EA00DC00E600F500E600DE00F400DF00E700FB00FC00F100F400E500FF00FA00F400FF00F600D700D900E600F000EC00FF00FF00FE00F600F100E400FE00FF00FF00FA00EA00FA00EF00E700DC00F800F000F900FA00FA00F900FF00FF00FA00F200FF00FE00F600F10001FE19000C08D890FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FC00FF00F300F300EC00F300FF00EA00FA00FF00E300FF00FF00FC00FB00F200FF00FF00E800F800FF00FF00FF00F900FF00FF00FF00FD00EE00F600FF00FF00FF00FF00FF00F200F900FF00FF00F800FE00FF00FF00FF00F500FF00FF00FF00FE00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF0001FE1A000C08D8A0FF00F400FF00FF00FF00FF00FF00FF00FF00FF00F800FF00FF00FF00FF00FF00FF00FF00FF00FF00F600FF00FF00FF00FF00FF00FA00FF00ED00ED00F900F900D500FF00FA00FB00EA00FF00F000FF00FF00F000FF00F100F500F000FF00FF00FF00FD00FF00FF00F500ED00FC00FF00FF00FF00FF00FF00FF00F000F400FF00FF00FF00FB00FA00ED00FD00FF00FF00FF00FF00E900FF00FF00FF00FF00FF00FF00FF00FF00FF0001FE1B000D08D8B0FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00F800FF00FF00FF00FF00FD00FF00FF00FF00FF00EA00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00F800FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF0001FE1C000D08D8C0FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00F000FF00FF00FF00FF00EB00FB00EE00FF00FF00FC00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00F500FF00FF00FF00FF00FF00FF00FF00FF00FF00FD00FF00FF00FF00FE00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF0001FE1D000E08D8D0FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FD00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FE00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF0001FE1E000E08D8E0FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00E600FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00F800FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF0001FE1F000F08D8F0FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00DE00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FC00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00010100000F08D800FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FC00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 2666 2666 0 02F0000E0003000900042004300000000004030009001820043000000000040300090020200430080080000403000900242004300000FF0104030009002C20043001000000040300090040200430FF030000040300090044200430E5030000040300090048200430EA03000004030009004C2004300A00000004030009005420043001DE010004030009000021043000000000040300090004210430010000000403000900082104300200000004030009000C2104300100000004030009001021043001000000040300090014210430010000000403000900182104300100000004030009001C2104301F0000000403000900202104300800000004030009004021043001000000040300090044210430010000000403000900482104300100000004030009004C2104300100000004030009005021043001000000040300090054210430010000000403000900582104300100000004030009005C2104301F0000000403000900602104300800000004030009008021043030000000040300090084210430010000000403000900882104300100000004030009008C2104300100000004030009009021043000000000040300090094210430010000000403000900982104300000000004030009009C2104301F0000000403000900A0210430040000000403000900C0210430300000000403000900C4210430010000000403000900C8210430010000000403000900CC210430010000000403000900D0210430000000000403000900D4210430010000000403000900D8210430000000000403000900DC2104301F0000000403000900E0210430040000000403000900A0200430EFE100000403000900A4200430000000000403000900B0200430000000000403000900C4200430140000000403000900C8200430000000000403000900CC20043020000000040300090050200430000074010403000900A8200430FE217401040300090004000038000700000403000900080000380015000004030009000C00003801030200040300090010000038010702000403000900140000380C0C05000402008005FFF98720BBF88700BBF88700BBF88700BBF88700BBF88700BBF88700BBF80720BAF80720B9F80720B8F80720B7F80720B6F80720B5F80720B4F80720B3F80720B2F80720B1F80722B0F80722AFF80722AEF80722ADF80722ACF80722ABF80722AAF80722A9F80722A8F80722A7F80722A6F80722A5F80722A4F80722A3F80722A2F80722A1F80722A0F807229FF807229EF807229DF807229CF807229BF807229AF8072299F8072298F8072297F8072296F8072295F8072294F8072293F8072292F8072291F8072290F807228FF807228EF807228DF807228CF807228BF807228AF8072289F8072288F8072287F8072286F8072285F8072284F8072283F8072282F8072281F8072280F807227FF807227EF807227DF807227CF807227BF807227AF8072279F8072278F8072277F8072276F8072275F8072274F8072273F8072272F8072271F8072270F807226FF807226EF807226DF807226CF807226BF807226AF8072269F8072268F8072267F8072266F8072265F8072264F8072263F8072262F8072261F8072260F807225FF807225EF807225DF807225CF807225BF807225AF8072259F8072258F8072257F8072256F8072255F8072254F8072253F8072252F8072251F8072250F807224FF807224EF807224DF807224CF807224BF807224AF8072249F8072248F8072247F8072246F8072245F8072244F8072243F8072242F8072241F8072240F807223FF807223EF807223DF807223CF807223BF807223AF8072239F8072238F8072237F8072236F8072235F8072234F8072233F8072232F8072231F8072230F807222FF807222EF807222DF807222CF807222BF807222AF8072229F8072228F8072227F8072226F8072225F8072224F8072223F8072022F8072021F8072020F807201FF807201EF807201DF807201CF807201CF80700D7F8A700D7F8A700D7F8A700D7F8A700D7F8A700D7F8A700D8F82720D9F82720DAF82720DBF82720DCF82720DDF82720DEF82720DFF82720E0F82720E1F82720E2F82720E3F82720E4F82720E5F82720E6F82720E7F82720E8F82720E9F82720EAF82720EBF82720ECF82720EDF82720EEF82720EFF82720F0F82720F1F82720F2F82720F3F82720F4F82720F5F82720F6F82720F7F82720F8F82720F9F82720FAF82720FBF82720FCF82720FDF82720FEF82720FFF8272000F92720D7F8272000F8272001F8272002F8272003F8272004F8272005F8272006F8272007F8272008F8272009F827200AF827200BF827200CF827200DF827200EF827200FF8272010F8272011F8272012F8272013F8272014F8272015F8272015F8270000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A0008001003181C1003181C030009000020043080000000040C00010004110002000E001300040018000000140004001E0000001D000A000800A800E682A00A260607003C000000000018000000FFFFFFFF780002000000000018A25503D3A25D0018A25503D3A25D0018A2550320808000FF100F0100000000000000003803000005000E000C20FD00FFFF000000000208000005000E001020FD00FFFF00000000000500000300090004210430010000000403000900082104300100000004030009000C21043001000000040300090010210430010000000403000900142104300100000004030009001821043001000000040300090044210430010000000403000900482104300100000004030009004C210430010000000403000900502104300100000004030009005421043001000000040300090058210430010000000403000900C8200430040000000405000E001420FFFF00FF00000000000083000300090084210430010000000403000900882104300100000004030009008C210430010000000403000900902104300100000004030009009421043001000000040300090098210430000000000403000900A021043000000000040300090020210430080000000403000900602104300800000004150008000000000020280000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 3328 3328 0 01FE01000000C80002A01602CB01400002A01E02D309400002A01A02D309400002A01802CB01400002A01900CB01400000A01900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE02000000C800BA070000AE070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE03000000C8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE04000000C8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE05000000C8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE06000000C8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE07000000C8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE08000000C8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE09000000C8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE0A000000C8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE0B000000C8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE0C000000C8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001FE0D000000C80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010100000000C8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 64 32 0 0000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 57 57 0 1290020000FE030000FF1FFF1F0000000018A25503D3A25D0018A25503D3A25D0018A2550320FF8000FF040F01000000000000000038030000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 2561 2561 0 02F000140003000900042004300000000004030009001820043000000000040300090020200430080080000403000900242004300000FF0104030009002C20043001000000040300090040200430FF030000040300090044200430E5030000040300090048200430EA03000004030009004C2004300A00000004030009005420043001DE010004030009000021043000000000040300090004210430010000000403000900082104300200000004030009000C2104300100000004030009001021043001000000040300090014210430010000000403000900182104300100000004030009001C2104301F0000000403000900202104300800000004030009004021043001000000040300090044210430010000000403000900482104300100000004030009004C2104300100000004030009005021043001000000040300090054210430010000000403000900582104300100000004030009005C2104301F0000000403000900602104300800000004030009008021043030000000040300090084210430010000000403000900882104300100000004030009008C2104300100000004030009009021043000000000040300090094210430010000000403000900982104300000000004030009009C2104301F0000000403000900A0210430040000000403000900C0210430300000000403000900C4210430010000000403000900C8210430010000000403000900CC210430010000000403000900D0210430000000000403000900D4210430010000000403000900D8210430000000000403000900DC2104301F0000000403000900E0210430040000000403000900A0200430EFE100000403000900A4200430000000000403000900B0200430000000000403000900C4200430140000000403000900C8200430000000000403000900CC20043020000000040300090050200430000074010403000900A8200430FE217401040300090004000038000700000403000900080000380015000004030009000C00003801030200040300090010000038010702000403000900140000380C0C05000402008005FFF98720BBF88700BBF88700BBF88700BBF88700BBF88700BBF88700BBF80720BAF80720B9F80720B8F80720B7F80720B6F80720B5F80720B4F80720B3F80720B2F80720B1F80722B0F80722AFF80722AEF80722ADF80722ACF80722ABF80722AAF80722A9F80722A8F80722A7F80722A6F80722A5F80722A4F80722A3F80722A2F80722A1F80722A0F807229FF807229EF807229DF807229CF807229BF807229AF8072299F8072298F8072297F8072296F8072295F8072294F8072293F8072292F8072291F8072290F807228FF807228EF807228DF807228CF807228BF807228AF8072289F8072288F8072287F8072286F8072285F8072284F8072283F8072282F8072281F8072280F807227FF807227EF807227DF807227CF807227BF807227AF8072279F8072278F8072277F8072276F8072275F8072274F8072273F8072272F8072271F8072270F807226FF807226EF807226DF807226CF807226BF807226AF8072269F8072268F8072267F8072266F8072265F8072264F8072263F8072262F8072261F8072260F807225FF807225EF807225DF807225CF807225BF807225AF8072259F8072258F8072257F8072256F8072255F8072254F8072253F8072252F8072251F8072250F807224FF807224EF807224DF807224CF807224BF807224AF8072249F8072248F8072247F8072246F8072245F8072244F8072243F8072242F8072241F8072240F807223FF807223EF807223DF807223CF807223BF807223AF8072239F8072238F8072237F8072236F8072235F8072234F8072233F8072232F8072231F8072230F807222FF807222EF807222DF807222CF807222BF807222AF8072229F8072228F8072227F8072226F8072225F8072224F8072223F8072022F8072021F8072020F807201FF807201EF807201DF807201CF807201CF80700D7F8A700D7F8A700D7F8A700D7F8A700D7F8A700D7F8A700D8F82720D9F82720DAF82720DBF82720DCF82720DDF82720DEF82720DFF82720E0F82720E1F82720E2F82720E3F82720E4F82720E5F82720E6F82720E7F82720E8F82720E9F82720EAF82720EBF82720ECF82720EDF82720EEF82720EFF82720F0F82720F1F82720F2F82720F3F82720F4F82720F5F82720F6F82720F7F82720F8F82720F9F82720FAF82720FBF82720FCF82720FDF82720FEF82720FFF8272000F92720D7F8272000F8272001F8272002F8272003F8272004F8272005F8272006F8272007F8272008F8272009F827200AF827200BF827200CF827200DF827200EF827200FF8272010F8272011F8272012F8272013F8272014F8272015F8272015F8270000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A0008001003181C1003181C0300090000200430800000000405000E000C20FD00FFFF000000000208000005000E001020FD00FFFF00000000000500000300090004210430010000000403000900082104300100000004030009000C21043001000000040300090010210430010000000403000900142104300100000004030009001821043001000000040300090044210430010000000403000900482104300100000004030009004C210430010000000403000900502104300100000004030009005421043001000000040300090058210430010000000403000900C8200430040000000405000E001420FFFF00FF00000000000083000300090084210430010000000403000900882104300100000004030009008C210430010000000403000900902104300100000004030009009421043001000000040300090098210430000000000403000900A021043000000000040300090020210430080000000403000900602104300800000004150008000000000020280000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 4800 4800 0 01FE0100080808106C756B686E646A6A646E6A6C6466636C756C6D80756E6A6F696767706B645F6D74706C6360616C717A717A7178707577747572757373777373636A70686E75656D746C75766E72747B7B7F7A7A746B776B7466726A5A63747672696A656258666269646D6767636367687379686B656B646968646E6866646E6761796E7373707A786B6B747367787F80736F6A696B69706A677368686B695E5F5F645A53463C666C73676766716F736D6C6B5A54565A5F586456666D6B646262656268585463676F6F715E606163707988827B777D796C797675778A757A7E80828685827A805F586456666D6B6401FE020008081820736862635C646A69656466696273696F6D667160686D675F6D73737676786B6E656270636764626A716E6D666A737578806F776B71797C7D746C716F73697579716B6E6E6A706B746B747878716F6F7277737373646D606B7573645A686C595A576C676A696C756A726F6F74606D7373675B62636B736D676F7063686167737B6E73777C726B64787A777875616A6A686761696870726F6B656464655F554B33696C6F6F7171696A75716269646257575559646763726C5C6567625E5A5D5D5F5E5D6261646B686B6F7C8C86847B77767478777F7177768389817B858488918F5559646763726C5C01FE0300080818307569666865646C69746D656A66635D6B7B7164777171635F6E716C78726E6E776A6A646C696B68656A737C7479676D6C7773726F68726D717A7B74716C6A6D706D6B626974797982898B787A706C6B6E72706D796C6A657872806052625F5F5F5B6660716E6169686170706761687B735E5C66786C7571696A5F6C6C68727667696E6C7065708072677C735C57627F6B6C6F6E6A726E7264595A5F6364585F3F5F767E807E6F7872756664695C5F605A5B5D615F57666568645C6C6F686666545A5A646E656B67687583948A8887827C807E798184867F7B797A737F77837F825B5D615F5766656801FE04000808184070706B6F6D6F716F736C6C626B6F707574676866726E766A5D6469737A697169646D636269696B666D70756F6E7A72758B7F826F6E7576736D6E78717469736C715D6074747B6D677B778076696E6F776B74686F69666E6C6F6B66676F6863615C656A6452626968606E6E7C85716F6B63656E6A6D69605F5F75706B6A6C84766B6E737A746D797A757C6C665961667262696966646074706964615E655F5442767D7486746C84767D70696B65665C5A6056556262586C6C6C69716F6A6E6755576257695C516064677987777381716A6F8679728489857E8A7A737D7D7E829C6056556262586C6C01FE050008081850716D62665B63596D7E686365676470637168636069686C6A5A65686F7C7C6679646466656264657D7962676E6D6A6B767C7876766C7E76766E666F696F6D7A707478696864757077726C7B6E736F746D6A846F796C646973736C6052606264706B6D5B766A676966716E6C7472737879715C636D6265595D6D6A6158696D73767D6C79767E7677777B816D6268706B6E61697465696C726E69576468605C54406A665D657468736D796B74706259625463686B6A5E6E61615B6D62626D645A5C665F5B6864646D6A687E8B8088857D7B7F76716B707D837C877E7E7E827D7D8263686B6A5E6E616101FE060008081860786A6A6F746D6C6D7A6D636C5A6665677C6F67626D656A656270747D6A63636D646A6C6D756F6E7680736D747274727381827C716562736E6E6D6D636C68656C6074726F7D77756D78717472786B786F72777172686B737A8071686E6E725D5F576E676764646F6D7E6F6474645D717B6C625F5F6A6C69615C61616B5E6674666F7469655E6A787F847970626C667274786A665C695E646B62574E565756544573757479727280718176676066646D6264655C5C6A6A6C6B646658615D6A646F6B6566726870655C728188898D877C816E73827B727B767A7E77787B8583839064655C5C6A6A6C6B01FE0700080818707B705966636868736E63656A7261636C6B6C6871695D5F63716775797675787B7B7861636E6A6F6B7263655F7075706A81788186736E7B746B75706F6E6A6E6C716F68667274737B7C706F7562647166606E6D6F6A5F6B6D76746C6B706E647561636167676462676E767774616A75787A716A65736658596D686A68696D75786C74787277756E767E7E6F66685E6B716767746C726D5E6670635A5B675A55406D6F697A7576736B6B6E6F716A605B6566606058686D606668636C6D6C66636869636B6D5F6560616D86868D8B7C78786C7D7470707D747F7E817F817E6F798066606058686D606601FE080008081880706F64605E7C72706F6A69755D6F606576767973736469655E6B717D7B706468695C65676F6C7472646E7B7165777B7D7771786F676A68727A7871797473787674687075726D68757D707363656C7A6C7971686B757274776474646A666A5D5F58665C666B5F6E68696E7179747464746A505A6766616B62707265757A6F7379667B716F77807462717B756760636D6B666B686F716E796C5B57606A6864593C6B6970777367797672656972616269635E61646A65636063615C6369696A69636B6A6F6B616A63656D7D8E7F83827E777C757A817A8980788080767B7D8187855E61646A6563606301FE090008081890716C52566461686F6F606B67706D676B6B7169666864606D676971778077696871646C666C64767671646568776C716475777B70667B73766F67736E6660746F736D6266677271718079737370626E6F68727B6868697480776F71666A6D6863606D6E6A65696D7273766A776C6E6F6B6E686564696A6368696C6A6B63676477736D696F797C7571807E70666A6779706D706B656E647F6A645E596165625751716B787B816C747370706D6F6B6D68636C5F6865656B6C656B6162655D6160616C655A66686756636E859283827B7E7D6D6E767676897F88867A7984818882836C5F6865656B6C6501FE0A00080818A083766A6B6A676B6A6F6C726A676A7176716A6C65746F6A5C6B69707469656B736C65686E6C6A6B71726A6D626E7278807E7D7B765D6A72746F656E706D6E6D676A72677077797B7F847E7B6E70656E626975676D70676F6A7B71705970666364616662755D6761696B63716E6E7774736B6067657970736A6B6A7474696A757575746572696F6B78787F695E5F61676A6C6F706F667368746959626360584E33606B7B7B7E707C6D757C756763696467635A5D4D5A6158666563706A6260676C6E7268665D6967676A77847C827A7372756968787A827E7A8B7E86897B838883635A5D4D5A61586601FE0B00080818B0716A6A72606262546B71766D666A71686C6A6D6A6A69646C6F6D716F6E71727B6E625A626A5A6C666973727A83707984827C7374736F76756E7364706D6C686D7A756F6C7276747E7B72747E72676B6E70716D75615165717E7A6A6F5D5E5F6D62666969676864696A81757A796B6F7070545F68706E796F64675C5B61656374737674737A6A6969757B6F6C7171645F645F6A746D726D6A695E6059575D5234626F7A8385817974767172736C6556576D626A68666A6C717268636A616067615D62575C5C676A6F6A7F8786878182765E7071737680778588857C7C7E7B858E6D626A68666A6C7101FE0C00080818C07D8574726E74776E787A706B636B726D7078776B736668717B786D7A746E646D726465626A5E5F7379776F717C7469778B756F70607279756F6D6D6368676D6A6665606E676E6F76847E8079736C726E726C716D6D5B5368697266596860645E5959646C66696B6A6D777371676B73617768686167736D6171676272736F6F6E7B78766F74757376787E766D6059696E66687465736B7A6E6C60585E5A5C5644787E7E807E808773786F77725E595462626062696768646D656C6664675D5B6E6768685F5E6A6E696982898782867B75776D6B717283767D848679848179808E626062696768646D01FE0D00080818D06D7455596B685C74746D64636D6E6774767B6F67726B5E5F7777756E6E6E686F70596D666D67696C7A686971787D70777C716D61677373716E6A6C686A71766C64696767737569737D7D828075716E7A7266686A6A7369707379645E6265656B635C5768626467746B7B6E79716E6D6F6A686763626863626C66686E6E5D7F7375706C6F62706A79788177605E646E6C6C6F6E5F6A747376606463655D584F406B726E78756D7A797D6C766F60606364686360585A636D606C685A5C5E63665E695E615F67726E6A70728C8587877E78777E7C868680726B7D8174817C7B868F686360585A636D6001FE0E00080818E07A6D69737165676E6F6F6C7664677072796F6D65646757646165667574736D6F675D606C6B737A6F7168726F7077756E7B72786C6C68736D6764626A6A706C70747B70706C797477817B706E656E746E6F8377737571606F8178646B747172746F6A6B6F755B6E6B63687375717D6663585F5A6873786D7069626D6B6C6D6A6773666A76806F6B717574675B655D69615F67665C65646C66706162695B5A4941787274856B636E6F7B735F6B60695E5A63666D60616A676D6769646466605F696859596A5A5F676C677B88858984837D79756A7577828C83717879787F89828263666D60616A676D01FE0F00080818F06A6E6C64656D7D676F595D5B6361626F7169616B6C696B616E757E7C76726E7775736769736B766A7578676F6A6B736D77747B75737F736967676C6C78606471646C73746B7C71727D797472786F736F706B6D7E70606D767F73636864646262585A586A6878747574667B78747973786266666A7868656A6F646B67685668675C717D767B7E6B707B75716E65606C666C63686D5E707B6265676970675C533B7784868C827B7D7A7274727A6F736E69605E6455646D686D6C69686F6F67666769675E6569716E5C6879807E8084787C7B7B70756E7E79837D798186867D8083605E6455646D686D01FE1000080818006A73646659666966756C635565685E74726E6F76756569726B70737D7A746D6F686B6F67726E6D6E656A6E6A716A6C7788827C707577767A6B7467606D756A766F7567676A6C6E67827B707E79747173666071705965676C6B6D635F5E5F6C5E5A686D6D6C626D6F6C6F727B637B717667616C6361706B5E706E6671706E7873686C726F787C787A7D7B70646C676C756A70736B68656565676A616B645E4E347879839387747B6A706C76746F64576468625F655E62676B6F5B57616765666969736B6660656362667E8082878180757574807A7A7C777F808A85878880818568625F655E62676B01FE110008081810706D6E61636A726B79727675696D6A726A6C6969655D5C686E6C6E7F837C6D706C5F6C5D69686D6A786F786D676C737B80776B796C7D7076766468676D6D73696E6D69746E7577757D7176736B6A696E766F6372616465717A71675668666269616C67606F69706F6E6E78776E736F72606A6B726F6F666D6567696E6E5F757F74767C6D6A6B6A747C7D6666636B6E6B6B6C6A7066687468655266706A6159396680828B8A847D71747575766164676166676C555B646E706E666370696F6F61646662686C726A687477868B797881757878777A7783818281787B8572778A8C66676C555B646E7001FE120008081820707A76776A766978776F6C7469766D696B77796E6A666872706C677B7276626C686B726A71696E6D6B6C7D706971777F7C757672666D71746F67796C6B727370616A67786D7F727C857D79707469756763696274726063667277686E77636D6F605D5D6E6D67676F746F747B686F716676696E7168606E676D66686771707576696873746F6E6A7171686B6C6068666C61637967677065635F5C5E62605D563A77767381776C6970786D77726B6A5A5D5E63645E5F5C595F6B615770626466676B70716F676F6D6C71828E8C7E7D776C6D78797F7F7C7481857C767A807E7E7F5E63645E5F5C595F01FE130008081830756A71646B63717169676E706B666378686A716D6C6B5F616A6F767262656575626A6D6D6F696E6B77706F736B6775767B7F817A7B756F636D6F636A6163646F71716F777D7B7C797A7A79777570717363696F64655C716D746C685F6B6F6568616D5B7269635F6F7B6C79756A796762696067706D7276676A6B66746D7073726C6E63657272746770826A665F6A69696B6E7165615C6A6D6865665556554E42686B7576706E777271697570645C52576465655E5E62676667686164676563686060696C5B5F616C658085938589837B77707A7B7A78757F837C8089817E7D826465655E5E62676601010000080818406B70747B726D6E6E6669726A6A60676D6B727672736A706B6A71746A6D6D65726A6A6A65716E747C7C6F6E676F717276797C847777746971686A686665667474745F64697A817674797479716A6C706C686A6B736B6B746E6A726B6268655A5F5B67606763607868656A6C776C6A716F67656D7D7D6E686A685F676D6E63706A62746A727F6E6F71817E716F686B6B6D6F6D736E6D667073626859645D54563F707C8479757D797E7C6C73776B64605C6E6D7676716F6F64626462696A6C5D686665646A686D60656C73869084767672717B75797A8171767E89858286827E846E6D7676716F6F64 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 27 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 22 0 00008A131700645E06CB7E569617900D6C3B5712A6C0 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 3794 3794 0 066B066A76C818D454EF7114CC1C589111AA80F42CFC9F5FDF040262BA6A5A9717CC4622FA2ABE03873C9EFE26F6967EFA112766BA3A5ABA3ED54F03DF5F7F9F1BF0A2EF33B3D3139370FA964EC6A6C646A52FE33BB3D333B350E8A47CF494149477C9E53DB5D575F516A8A47CF494D454B709E53DB52DF474CF295C845414AA2E95F7E03CEC8C52D63D7B0ED6068249C9727C18C01010F672C9C3A870A0D877F3480604D808905BDB6036439B4BD4E39CB8F172551A8E57D76CDABE66D6EA3DBF04B2CE16A606DE5EE5B7C31BCB479F1FA43E5B8353538A0AB193F921F131E664DF95E038E8B46DED561D8E56E679B9C6E2624F9702408065B80E07C27237BE3E00F2B8F16D0E6FC21AA0C4952FCD44C4024428F0401697177DE48BFE4C0DE360FD4B2734A6CDB610C07C98427292262160264C9525A003A650EC9DB50553D252A97E122F65FA1A7CB4125E863A50F553ADBAE63D3C6DAECB33ADDCF444129313F97D12EB680BE221E7A1CD15A5F372F2AB1F7EAA01E1A125A8066DB90C60A664AD1565BA3014662278FC944C4E259BD906B1EA8935621E8F69D47F1CA0FD3177AD1B40A410B7CC4DAB16D70C016287BF4C505AD83B50E72CB3B71F46A0576B469893FAC7C18945DED7C3C3BBCFEEEEA8B3DF614BE6040440DAAC43DA9A1525457DEA0C3A7AD487C543771DC676D4B65A4B3F915598C2CE8C5BED5399206DA6F1962141BB168646C61D9DB068693DFEC6162C2B5140402A01BFB3FF8A383D51F4327418C07026A7275DDEB1D85E3D30B20CECA5CC4427C76D16015A81FC9E3BEE1017419A0A5030726ACC01E0533FFD548C136C9D0E47B4D159CA17F34010EACAD3A6DAA3284B6EBC42F89D75FF3FCD8E45E81DEC5F7487612363A2797BBBDE72E5B67B8B9AC70435D065CBD04441D1741EE8876FE52544FB23A708F489EACF1EE0E7C91292C8A88913A607DCC9FA1F2EB10458BAAA6BE86B7DC8018B1ECF49CA21AD6118ED8E83003ED99078E222FF8F54D4F9211037F4FC2F153148B0D336C1329905DD6D3BBA3A6091FEAE16FA7253C075FC51C90C38995F1975AD1D4BCA4A3C880140D233B43764DA3AAABB9350F55AC4B59D2D7BFA7A84177B22D8BBEA588097B269704900894F0965BD0D5BDA5AB0325D891E468554C4718F54ECEE8F7FAF90EA7ACC7DF172A57919C6F45D61F72498D253EB26E40167F7B664C959F33059FC9BD16505D368B8687DB5C7B38F592E925CC77F3DFE73881F77B2F29E55578F349A610C7BD35C15AEC216B4C22BA5756AA43181A767E7308428D060A271F9E033FFAB0104228442040299FB9F5FB97FF521DBC6A500609D8B07AB7D03E2D345F06EBD0D4BA4238A771BCF75309633E46A946F01A141C1885B97CD3E56D053889CE33C001AA86CB7A3DC039614F27EB71C80EA49218B4885F893893D5D5F133393C31C4E2DE0E21D2A51E707F538B8754A2AFE5C370E7CEA5CB67ECE2C255CD1FF660694599A7F7DED2169ADC69F497BC7A774C8E4C6656307C9650FBCBC1CC7D3AC7C2E2B4BB93FF759C27A0C86F423FB75E9599B48C07E13590772ED008750E945BD0DCF1C94CD1ED21C36A580D9248F13C775535B2447D312C95CE80E2E65A7AD6CFB975C0EF69D33498D2724649F29972A3AF82BA30AE0F2967C7655D96F0B29F1E39058BDB020CA1BABC778F47B8FA070AA89BB7FA4A0DF0C200B79AD8A30A6724AA82CAC12703A70D4481A53795D6541D3B07DDD2795E4CC5136702F0B1F6743E55F77FBA89CB46C6AB060ECCDDE639D0F7B47E5FCBBF57935530E714F29639621073B449F1F32EA0B5F9C449A6EA28A7055A72378E8A74ED8FB08E979CCD145F69AF254EC757F248AE65547B9D17D8535C76141A85AB6DC690466E13A3CE13D3DF5A68418AEDFF75ACA069508BED20685D7535395D3B3384A0F1151AA1CB20C1CBA89F62DAD8058D9F7349501B4F13A9707C7479C1C31E9C89C5F4795AF6A1089345474BB2B7DA7F2D031AC87072AF2E3D211B02194C9239061F17228CCA3F26B22E1C84AE17DA51543C242B85D3262F057FF6218FA9528D199C81DC5B288535265A68E77791E061C6C3C26EDEB1D567F3D5811EF44D800B0E667E79D7F102DDF97B66EB6411FC44576B539EE80CFE6016215F8010A6979CD64AB865F685D86D62BCBD22A157DC0385829F32B357AAE1CCCA60674E190B8046F691F3BBB964EE24A0D1FC05760BB1686EB6997E3AA5FE598A828F3735E864760A3FF704E2571894C92128F38542DD5B653EF1C0269BD04F67C640D1B049645E78773CF453A5FED25E2AF778B4D374D096CA95A5E92394F2AEA2DCD6FBE647C1B19399660C0D822E88AC03F6C43B3B171C2FE70A1F62634F035505AC8E23D8D5F3FCB777A1E64701633639CACC31BA7CDD552852F81143CB9B612EC5E3202B537F9E1F60EC353E025DD75B3F59941F1A726A64CBDD23281C05CDF2DE80F5476D50118A08FB0E1628B68CAD399DC47EA7ABA3AE1614C94C1B272EFC44469B10D2742E21B8CA77C412B73F1268A64D5428758FA5D372711ADE59D1FC869A7148C5DD6554ED8B4FE65ADAD0DD610E51D3F345C1CE751CF3C248464E4BFF6BA904B838323F89CDBA9D99959393F9927948E2ECE4E37AA6C74E48484AE657176041528EBCE0094F42F2745890FD82BA73C9DF13888B0F67A4CED3D0E2E974E08DC73DB19097B3D4A0B2BDB6F05126EC8C27E3775F9080C6C91A14998A8C037E97DE85810B0B307D60636E9AAC0C6C054CD8FA34913625630C0C2EE070758AF41D34B4DC4FEAD19D80339CA80B4DD4006546ABAC1B1D0EE00D047A52C4417A3C3102093C3C9E6A2E11329A797E8C38F0D17A9E3C14FBD8B2BE2B21EFEBC3AE0E92090FC35BE303E50931040B044AFFA66047062CE605BAED35D58CDAFE42B1C2EF5D79C796BDB44E810A0488089D9CAF109A434F474AF2F02DA4B6CAF875E4AEC20B58D6D459CA1679AB9FE32F8C1D8343DC6A5A505DEAAEB87F7B7774F96C060A8DAD7A39161F0F929BB63A12DECE8AF5F0A6D8F1239B9944CAD864505FE48669B9F3FDF5FB4463AA25010927718B32FF747119010C7726C14D4E562E13696429F1FBC8CBCC4D26C9E04D4D8F8F39804067A9854F0CB3E43FD55092B81741056BC4794B33EF2E68676C6BD3DBDD0C7DBB818D8B80C677B374F5F4BCD4D962C4A203FDF3A4367690062069479D700AA3601A0303E2D34EFAD6EEDBD4DB904F13D6E75B0F55224907DFB48E80888DB65806A7F56B62B0080AD754463A000B9FF1BCB705313A1EADCE29A581DF7F74A5C40EFAFB55385BA08469C0A287B8BD04429D149189230EB7F02FA6A3BD90AA1551CEE1E3A0AC05DA9C13F2E11D2D24DFAD646C701D55924502FEBA9D5EDEF67A18B51E167B533E45030E1C3F04060190FCB190B0EFC614ADEB04D7BF4CB4B90103DE5593BF772E81976A251F93D7D7452AC69B5C35ADD0D32DE86C220BD51DCE28890D212309F6E6416E84609EF41B66634BB5956BC1C5513BFFEEE2CE54F2699DC849EEF9FB54EF493E90408E2CE87387339C34B26A45A1F8C12A9C9122CD7C35F475D9DEF00F1F7200802C8BA30C195F30232E9385838AE70F529631F3DEC7DB32078B577FB2B78FBDCA4C02A763F8400740D665F2DBBE5419D07BB9914274DEF9A28449F3F66208CC6D624CD677C428EC6EF7F252D74CA81DB26AECBA783FD9546C5BE5CFC07C5FF3470826EC790AFC899ABA74E02C1922205A838F878A3230ED62727E455EF5ABE221BF900C4024428F0401697176E1A661B98D88969B18F6130C9B48404DF5F72AAA7C524C61E80EE3A06ED8FAA73ED00BB08FAF8682ACE3BA1989AD655B793E2CA7A2CAD2DC7137C9C2FFD2EB661CBA09339C856D5CED39FE5067E7EDE052B4E14B7D1B3F03B17F3A26164882841E4905F046A1201567B9F4C5133139B40DBBD783854960B20A08D55D4D615AD75710FC3BB7810B3A2AF7A01164DDCFCBCCA24EF47BEDD4AF964CABAF574D0537075D9219123F06802FF90A8C5B5876C17734C8CFCBC7C5EAE9834CC7CDCB6265F826EF041214300CB5813EB9BDB1B0A8F3AD41FA95198BAA204F2A29B882D89724CA3D664E42CAC6A2C4098287EFF7FE6F86B22F794E507DF587FA4ACC7C55E9D27666E1252508B483E72AAB8FB9BB2D2A4E830024121619A2CD08020D2B33378460A50834343E338ACE3BBCB8B4B8B72D4FA863616F454AD7894511147C646FB791D47F4B3B132CF1F4B9984E69B180EBCF5B5275A6A42CACE0221218D5D1F8717BB43F301CB475CCAA6CEE797C50FD873EF3787FD3CBC67D1BD65D5519C1EA5177AA21272B232E9EF8D5787CD0F8F54E28E56E666B4368D274B9B2B36F20CD3E19F45958152D06B453AE030F023A11A740CD6067EAB2992146EB46430E567DCD2AB71A1C101815A1C8FA8E78747C71C5AC9EEA1C101815A1C8FA8E78747C71C5AC9EEA1C101815A1C8FA8E78747C71C5AC9EEA1C101815A1C8FA8E78747C71C5AC9EEA1C101815A1C8FA8E79740C279EB904A9AEE36B40F1962B86808C8489325499121418101DAA0D40CDC6CB4348FC1B46CBC30F070AB1D71A91978B838E35438E15130F838E35439E05170A024FD6A02FB4F0E4ADA43E49950F1D83A9E6798E677D5FC6ED71EFD800DAC994C99534F097BE12B416B9A7940CD281D885D53B00984E12B012B1E0280F2AC7A1721171796F8A5736E35336BE9DF813F84EB8DE572743FE1CEB593DB496F21BF88B793DB486E21BE81FEDA582DF5257DA4249FD5A078A8FC3CBC67D1BD65D5B575F52E98F42C9CFC3CBC67F99C4494D019992284588232528808B37518C0706CAB2B909AFB21F1AD65E55EFC9E449438F674CFED875F8F4B8406BD4F25FD2DC10E8C377104DC0CB877F54E4835EF3FE72FAF1482FC26F62AED6DD6344A9040E83AB8035D37EF3F3BE361DA2C4A92421495154F7B1178482EF27832056F15EE8EC74EB0046855E181E466BDEE875F0A62A207DF69A071C10043C5AF9DF78A6027FA8A51D1FC24A54086277ACA8F8429B979F922A28F57D631F75605B5F06BC6569616CD4D60B839DC1ABBE9591C57FA6AAA2AF1715C8415F83E8FD86895C77190DB5D0FF0B56EC3539313C84865BD9C72B438EBDFFA22F79656773C8C510EB81956D0C27FBA399404C4449F1F32EA6B9A5CFDB404418A27B777F72CAC8159689C5AEBA3135E13A5EC0F068E25B961D1870686CCEC86DFF89ED77EC0761ADF9FC948C8B29CF69C8C60088279AEC29208D2A8B477CDBD6954D63C948F19757F81EDEF24D84B807BEB6DBE2ED563123A8AEA2AAA71C7AB73C3A363E3388FE33F8F8B51D368 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 2565 2565 0 02F000140003000900042004300000000004030009001820043000000000040300090020200430080080000403000900242004300000FF0104030009002C20043001000000040300090040200430FF030000040300090044200430E5030000040300090048200430EA03000004030009004C2004300A00000004030009005420043001DE010004030009000021043000000000040300090004210430010000000403000900082104300200000004030009000C2104300100000004030009001021043001000000040300090014210430010000000403000900182104300100000004030009001C2104301F0000000403000900202104300800000004030009004021043001000000040300090044210430010000000403000900482104300100000004030009004C2104300100000004030009005021043001000000040300090054210430010000000403000900582104300100000004030009005C2104301F0000000403000900602104300800000004030009008021043030000000040300090084210430010000000403000900882104300100000004030009008C2104300100000004030009009021043000000000040300090094210430010000000403000900982104300000000004030009009C2104301F0000000403000900A0210430040000000403000900C0210430300000000403000900C4210430010000000403000900C8210430010000000403000900CC210430010000000403000900D0210430000000000403000900D4210430010000000403000900D8210430000000000403000900DC2104301F0000000403000900E0210430040000000403000900A0200430EFE100000403000900A4200430000000000403000900B0200430000000000403000900C4200430140000000403000900C8200430000000000403000900CC20043020000000040300090050200430000074010403000900A8200430FE217401040300090004000038000700000403000900080000380015000004030009000C00003801030200040300090010000038010702000403000900140000380C0C05000402008005FFF98720BBF88700BBF88700BBF88700BBF88700BBF88700BBF88700BBF80720BAF80720B9F80720B8F80720B7F80720B6F80720B5F80720B4F80720B3F80720B2F80720B1F80722B0F80722AFF80722AEF80722ADF80722ACF80722ABF80722AAF80722A9F80722A8F80722A7F80722A6F80722A5F80722A4F80722A3F80722A2F80722A1F80722A0F807229FF807229EF807229DF807229CF807229BF807229AF8072299F8072298F8072297F8072296F8072295F8072294F8072293F8072292F8072291F8072290F807228FF807228EF807228DF807228CF807228BF807228AF8072289F8072288F8072287F8072286F8072285F8072284F8072283F8072282F8072281F8072280F807227FF807227EF807227DF807227CF807227BF807227AF8072279F8072278F8072277F8072276F8072275F8072274F8072273F8072272F8072271F8072270F807226FF807226EF807226DF807226CF807226BF807226AF8072269F8072268F8072267F8072266F8072265F8072264F8072263F8072262F8072261F8072260F807225FF807225EF807225DF807225CF807225BF807225AF8072259F8072258F8072257F8072256F8072255F8072254F8072253F8072252F8072251F8072250F807224FF807224EF807224DF807224CF807224BF807224AF8072249F8072248F8072247F8072246F8072245F8072244F8072243F8072242F8072241F8072240F807223FF807223EF807223DF807223CF807223BF807223AF8072239F8072238F8072237F8072236F8072235F8072234F8072233F8072232F8072231F8072230F807222FF807222EF807222DF807222CF807222BF807222AF8072229F8072228F8072227F8072226F8072225F8072224F8072223F8072022F8072021F8072020F807201FF807201EF807201DF807201CF807201CF80700D7F8A700D7F8A700D7F8A700D7F8A700D7F8A700D7F8A700D8F82720D9F82720DAF82720DBF82720DCF82720DDF82720DEF82720DFF82720E0F82720E1F82720E2F82720E3F82720E4F82720E5F82720E6F82720E7F82720E8F82720E9F82720EAF82720EBF82720ECF82720EDF82720EEF82720EFF82720F0F82720F1F82720F2F82720F3F82720F4F82720F5F82720F6F82720F7F82720F8F82720F9F82720FAF82720FBF82720FCF82720FDF82720FEF82720FFF8272000F92720D7F8272000F8272001F8272002F8272003F8272004F8272005F8272006F8272007F8272008F8272009F827200AF827200BF827200CF827200DF827200EF827200FF8272010F8272011F8272012F8272013F8272014F8272015F8272015F8270000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A0008001003181C1003181C030009000020043080000000041700000005000E000C20FD00FFFF000000000208000005000E001020FD00FFFF00000000000500000300090004210430010000000403000900082104300100000004030009000C21043001000000040300090010210430010000000403000900142104300100000004030009001821043001000000040300090044210430010000000403000900482104300100000004030009004C210430010000000403000900502104300100000004030009005421043001000000040300090058210430010000000403000900C8200430040000000405000E001420FFFF00FF00000000000083000300090084210430010000000403000900882104300100000004030009008C210430010000000403000900902104300100000004030009009421043001000000040300090098210430000000000403000900A021043000000000040300090020210430080000000403000900602104300800000004150008000000000020280000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 2368 2368 0 00000000FFF98720BBF88700BBF88700BBF88700BBF88700BBF88700BBF88700BBF80720BAF80720B9F80720B8F80720B7F80720B6F80720B5F80720B4F80720B3F80720B2F80720B1F80722B0F80722AFF80722AEF80722ADF80722ACF80722ABF80722AAF80722A9F80722A8F80722A7F80722A6F80722A5F80722A4F80722A3F80722A2F80722A1F80722A0F807229FF807229EF807229DF807229CF807229BF807229AF8072299F8072298F8072297F8072296F8072295F8072294F8072293F8072292F8072291F8072290F807228FF807228EF807228DF807228CF807228BF807228AF8072289F8072288F8072287F8072286F8072285F8072284F8072283F8072282F8072281F8072280F807227FF807227EF807227DF807227CF807227BF807227AF8072279F8072278F8072277F8072276F8072275F8072274F8072273F8072272F8072271F8072270F807226FF807226EF807226DF807226CF807226BF807226AF8072269F8072268F8072267F8072266F8072265F8072264F8072263F8072262F8072261F8072260F807225FF807225EF807225DF807225CF807225BF807225AF8072259F8072258F8072257F8072256F8072255F8072254F8072253F8072252F8072251F8072250F807224FF807224EF807224DF807224CF807224BF807224AF8072249F8072248F8072247F8072246F8072245F8072244F8072243F8072242F8072241F8072240F807223FF807223EF807223DF807223CF807223BF807223AF8072239F8072238F8072237F8072236F8072235F8072234F8072233F8072232F8072231F8072230F807222FF807222EF807222DF807222CF807222BF807222AF8072229F8072228F8072227F8072226F8072225F8072224F8072223F8072022F8072021F8072020F807201FF807201EF807201DF807201CF807201CF80700D7F8A700D7F8A700D7F8A700D7F8A700D7F8A700D7F8A700D8F82720D9F82720DAF82720DBF82720DCF82720DDF82720DEF82720DFF82720E0F82720E1F82720E2F82720E3F82720E4F82720E5F82720E6F82720E7F82720E8F82720E9F82720EAF82720EBF82720ECF82720EDF82720EEF82720EFF82720F0F82720F1F82720F2F82720F3F82720F4F82720F5F82720F6F82720F7F82720F8F82720F9F82720FAF82720FBF82720FCF82720FDF82720FEF82720FFF8272000F92720D7F8272000F8272001F8272002F8272003F8272004F8272005F8272006F8272007F8272008F8272009F827200AF827200BF827200CF827200DF827200EF827200FF8272010F8272011F8272012F8272013F8272014F8272015F8272015F82700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038A483F58000000000000000150000000300000008000000000000000000000017000000080080000000FF01000000000100000000000000000000000000000000000000FF030000E5030000EA0300000A0000000000740101DE0100000000000000000000000000000000000000000000000800000000000000000000000000000008002028000002000000000000000000000000000000000000000000000000000000EFE1000000000000FE217401000000000000000000000000000000000000000000000000140000000400000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000001000000010000000100000001000000010000001F0000000800000000000000000000000000000000000000000000000000000000000000010000000100000001000000010000000100000001000000010000001F0000000800000000000000000000000000000000000000000000000000000000000000300000000100000001000000010000000100000001000000000000001F0000000000000000000000000000000000000000000000000000000000000000000000300000000100000001000000010000000000000001000000000000001F000000040000000000000002000000000700000015000003080200010502000C0C83001003181C000000000C0000000C000000010300000000000000000000010158026F0000848418620000000000000000000000000000000000000000000000000000000000000000000000000000000000A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A508000000C0014000FF1FFF1FE123FF1F18A25503D3A25D0018A25503D3A25D0018A2550320FF80003F040F0100000000000000003800000000000001000000000000000000000000130000001400000000000000FFFF00000E000000C20000000000000000000000050000000000000000000000000000000000000000000000FF00000000000000EE000000980000008800000011000000000000000000000000000000FF0000000000000000000000000000000000000000000000000000000000000000000000FF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 36 0 000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 4800 4800 0 01FE01000808081073766C6D6F6E757876766E706871766C6F75726C666C676063646B7C7D767A707373666A6E6A7169736C6C756C746F736B767271706A6E7E7466726D686F7A6F6A68676E6B74787B7D797F716E70756A6D7468766866697B8078666C6E5F606660665E68695F615E666B6F7A6C70757674686B6C6B6B625A65616262676D737C6C717775737571767175726D676B73756C62607670665F5F646A61625D574832736B7F7B726F73776E717C7363605C5B655462565B5A606E636C6769695F696863676668697170726D7D8B847D8B857F7A7072787A7975797F787E868A777781655462565B5A606E01FE0200080818207C716B696E6B6D6E7569616E6C6A71716A716E6F75695E615C69717C796874777F6B696965656B74746B7060716E737674717C757485726D6F6F6A676A7969616D6C666E687875757B716D78746A756F626C737A6E6F697078716B6A7268616868685A6A665F706F72756E727273726E6460626365586666696C676F676F7676716A736670797C787D7A706A61656F71726E6E6A67686469656966605D614C3A797E7A7E83817670746D716962656A5E626C6664626A69706569615E6462576E6C6775676B7867637079827E848272757A7D787B7F7E74758076777E7A788B92626C6664626A697001FE030008081830767A605F64606F706C656A73696769787B7170696D59635D657376777C817273636E6B6165656C6B73706F67746E6A76828572686D6C6E716B6C69736F6A7578656C6D74827A7B717A786B65636A786E677872706D6C6C65706E5A676F6A615F5C615D5F5D646E7676716E75716D756E626C69666A64796D68636A706A6F6D787A7274748069726F6A7163675A59686D70656D6E7161746B5D5F5D61575854376C62707E7675707E7C71696766645A57665E6A69726E72696A625F5D65605E6A64636368646D6370717F8B89817878727470787F7C80797D83877A827D7B8184665E6A69726E726901FE0400080818406D696766615F716A686971686367666B75806A6D64665A6466686A716E7C6F756C6D68636A6D70746E626E6F757B6A777274836871777A7A726B71636D6C6A6C666E656F78706F717D7B777070707670656A676F676B717B7F816E67606B6463676A5A6363656F7D786B74716E666C69595359666C706B59686B746E7B717E6C697367656A6E727D788177696A6970706B71716C6A6A72675D6161606456543D676773767B766972656A6A717063625759606E6366656B69676E67676E6F7371726F69645B626C6B6F757F828687766E717073807284887A8274767E78818A8959606E6366656B6901FE0500080818505D676164685C6A6D7464676464706B76747772695E68705F677562696C7865746B64605F7266726D707C77747478747E7C757481737B796769636268736F707573655A706B756D778279677075657173646F717B6B656D77787C6D5C6C716E6864625B5A7675696364687876736F6E6D5F676562746B685B6566636C6B6F727273756F7070706E737A7B6E6665686E6D76776C75676C64666260595B5B5350376C6E7B8167717467746D766B675D58555F5C5C526265646E79735A6159515D5862645666616E75726F758D80897771757C777B808080787C7C6F7381887780845F5C5C526265646E01FE060008081860847C82756F656F7A75746D7767796E76726E666B726D676C656A716B6D77676C666B686678776D746D7B6A707179726F84707E6D6F696B7873797B636C6D74736B706E6A74706D7A7984767A6E686D6C706D646A665F6876867B6862676D6768596A6C6C606C5F687B747D7B756B717D6F6B655F666A655B646C6A73666F636D6C6C6B637174657E7E816E68626267766E5F5E6C5D677D665D555B655C4E55366E797171826C717A6D707677686C6662645E675866616B616B635F646C6B5C70726859646D686A5F69727E807C7C7B797F6A6E797B7B7F7C827783857E7E7F85645E675866616B6101FE0700080818707D6D5D6F6D73687A716D716F74736D7773767174756E66697075777475666965656863676F667071777375737A6570757E79826A6B796C756C72716A756D71716063686E6A6872748074697376787B7B706C6A735E6A5E72757D736570706968726668626164636B767568756D6E6E655B576B5E6C727065676D6265626C71736970667274706E7C7A7A756F605F6171756E6F6E716263675C6B6C606653573D79787D7E79747470726B6F7A73645F6A72686C5455565D6A716B63625C5F59646C6567606764646472778481827F7B7B6D707B7A7F827E7B877A84857E7E868772686C5455565D6A01FE0800080818807A757070726D68666C6E76686366757B7A736E7079776B666F6F746F736B6665615E6C6B64696D6B7A736D6E7975727A7F75796E6971707478686E647162636A686C626F6A7B787482796D666A5E766E72717476736760656C776960696569686465636F656E656071756E796F6D71707366646A6968605B6D626B6767666B7972717273767C6D6F7A8067675B5E716E6A72706D67686A67635A5B605C4F5D416F7075747C6D6F6973716F6F685E59666266655865676A64635F626E6E67646B6E656F69686C5E676B7C7C838D777D786F7A7A777C756F6E83797D8589787C846266655865676A6401FE090008081890766B656A636363727678737367626E736A6A6E6A6F656D666B6B76807776746A6664556370666A77677171797076707F807B756E6A6C706373797E72715E646F6F79626F717E767F817678736C6D6D675F726F7661636668757375666C6A696D6764617160686266687379756A646567686A666F606665555A6F68656561736B71757277707D68747D82696B5F616879806F6A7A72656B636772696B585558457376787978757F6C71765F6C6A645F6072626F665B5D5968685A65696A6669666C706B605F646562707D918D88878380727C7A73787A6F86807E737C7C73878472626F665B5D596801FE0A00080818A0686E6C61655C7064695D5E6D65676F726D6D6D5E70696F6567716C7A76787172645A6C6A656678736F6C706B747376757B85807472656C6F68707A646F6D6E666675696D6E75747586757C7A6E6976696A6B6F6E626C6C7172766B5E6961636C59796A6C776B71686C70797068716E6767646167766B64625F6564636B716A6D6F71717370707079767773666A67676C6B6D6267696C666C675C665A68514834727B717E877980777B7B7B786A5C5F5F72616663676B5A716B5F5E675F5E6766626766635F726972717E8F8080787E8077797C7E7E8079757F7B757D7D7C818C72616663676B5A7101FE0B00080818B06A6A646E5F66656068766D6D64615F757375756C5D5D636B756E71777F6C6F756F6F6268656D646B7A676D706E85757A7C71727870656B6C6D6A696368776C79656E75655D6668707C7F7D6E6F6A706C717F7E786965626A75736968786D7064636F70766B6768646B7273736661706C705D666B6863616F6A676D68636A75767170736B74717A72737E726C626169726B6C6A6570666D756B666A5E67544C395F707283766F787777716E6D62636161655F6262666D696864616467585C5F676D655D6769665F6269798C8E898483837B797A73757E77787C82817C79788882655F6262666D696801FE0C00080818C05F5F5354556063606E6760606565645C626D6F6A6C5F626E68706C68767569705962595E69667265746D69747282806976717C676B757374746D746A647165676E6D6E6673736A707F8478776E707873616E79776F63627874776B696B645A596D6B64696662716C71717A6F78786973765F5E5E6F685B64656467737F7D736C666B7268756B6F6B837A6E6960636F6F666575726E63746F61646F69635C4C416F7F79857A73716E6F6B68696A635E61635D586A5F5F6B7268686A736F67675F686D636A686D6464687B8581838C807F7B786D747B837D7E8E79717E7C7C8288635D586A5F5F6B7201FE0D00080818D077737471676871696B6E726F72696E6E6A72736965616A60646F687A7469696E6B756B7172677771776B707C726D646E7376826F7B737272746C6A6B696B676862756A636B7A7770726F7972787674766A6B6F6B6568656B757D6962747068605B615D6761686270707169716F707A6E6F626C6872726C6660605F6675727273726C6A757B696C73777B6C685D6475646C6C726B64606F776765636B6264573C7271757A7E7C6D69786F64695C61585A6A65665E5E636B736C63666D747865686C6F706A706C65626576877F827E84767276707A7E8182788483867D797F8A846A65665E5E636B7301FE0E00080818E0726B6B6C635E61636866616D5E6D756F726A687175716A66686771736F706B6B6C6A665F6C65635B695B697C717475817D7F777472787D72696C6B6672707369676F69756D7A77787880876D7C5B6769726E68625D625D67767D766562656269676361646F6C7174837867716C5F6971756E5663666B6A64686D7675716F73676B71727976756A687673666A6969676E796B766B6670686F61534D675657554471706D74766C727063636470695F5D62634D575F5F5B6D6C6966646D66606475675D606367706A7075818C8886827C7F7B6D717476847E77767A8188787D878C634D575F5F5B6D6C01FE0F00080818F085766E67616966655F615E676666707379686C6D6C6C646C696B726F7E73726E706A6A6466686F736E726E7379747570846F77746A75686B726960606F60707068696A707177677A77767474757B74756E7372715F6768788275585D6C6B6665696B686E6C6D5E67697A6A74717376696C69626C676467676E6D6768627A7777746772696A6E6C747A7D5E655F74706A6D6E676863686E6D655E4F576356563C6C7C7576776B716A6E79656E5C656A656A605E6E6E625A6160605B6A63596565695E5E6366626368747C8B858C8585837074777B79827574787876828682898F6A605E6E6E625A6101FE100008081800735E64706C69696466626E6D6D686B77767C73767362636F6E6F65727477646E6F68665F656565666C707565747E7878807A77715E6B6271646C7179795E6B6A73717571667F62707F7D6E74767674707B7D6B726A6E6471696D6357645C5A64676A62696863676E6D6E858079767A6F6D63606E766C696E6F65666A656D6E6F6C6E6B7174796C8C7B71726E6364777D6E6B63695F736C68626F666566554D2E66726E72756E6B697376736D625C525B6256646263696366666962665A5C5B66615A5F67676B615D6E7D8B7F827D778184817C757B817978857A707F787A7C90625664626369636601FE110008081810796A6B64625E686D6D616F70586560626F6C676C636E6971757278747E7E726B66626A727765706B696C706A6B6A70767F7F796E67746D6B6B6A736E666667656867666F6A717A7E807D7B7A6B6E796F636D6E7466615F6D767668676E626268666860636D5E62787C7374796F6366676D655F5E5F656B746C6C6F7077707C79696B686E766D6873756F6D6665626873736D7C7C6A6E6F6D6760615A665E513D7C93867D8079726E8279827B675F4D626B6A6D6E5C645F7474676C656B61636768615B636C6B6B606781918D8590807D787D707D6C777584827D7D81767D87836B6A6D6E5C645F7401FE12000808182078786567645E636470666465595F65797176755D6F6D6C6E6E64676375796B5E5D606963696A6F6D6F6E70777B807E8074777567687E75806B616E6268656C65716B71756F6C776D7C79726B7066716E677568786F59676F667B676A7A6D5B555D646E726C706A5F6F75787A7574737565635E6464617167756F6C6267726D807874777669687C817E826A5B5F59696F6E6C656767666B706E5B665B65544D387474747275716E6E69685E695A5A55555E5D6A5E5C5F5F616C6D6B6C6067676C6E7366666C625E586878928C818483716971797D7E7D828682787D7D777F82895E5D6A5E5C5F5F6101FE13000808183068737A7B6C5E74727072827E6C686B6777635D72746F69796E637471767068706E6D6A59696E7A6B7E797B6F7E6E717C73776D65666A5D6F6975736F756365696D776F6B6D6E6579747B736972657E73637173705D5C6C7D767C7A656E68636467696B716A6E6D6C6F64666E7470756A625B6E6F6C706562747562696B6168686E7D736B6E6F686A67817574646567656764606A696E726F66625D6163585A46697570767476777C777B70626061595E685C68595B6660696666646A6165646E6863645B6B66686075848E8774818A79797D767A78817C78816F788A81827F90685C68595B66606901010000080818406F766A6C6D74736F6D6E6462676E74756B676D716D6866677168717071756A6E676A5E69676D766C6F64776A7472787B84717471726F706A6E676D7168676D6B667070766B7167767E7A78706E6675717672646F6D656673897A6C5E5F6365636A6860726B63636E74766F7C706B6A726F63666569676A616A5E646F786C6E706F6F696E6C7A736F7A7373686D6D67696C666B606B69746D5669576657534F41767C73746A747171716E6F6F585F5B6267646755605B59586366635D6A5A62686264676C696C5D646678887F81858F7F6D6C707B797F6C7C818482807D86879067646755605B5958 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 117 117 0 2A0000000000000001FF0000FFF401000000000000000100000000F40100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020BF0200 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 2903 2903 0 02F000000003000900042004300000000004030009001820043000000000040300090020200430080080000403000900242004300000FF0104030009002C20043001000000040300090040200430FF030000040300090044200430E5030000040300090048200430EA03000004030009004C2004300A00000004030009005420043001DE010004030009000021043000000000040300090004210430010000000403000900082104300200000004030009000C2104300100000004030009001021043001000000040300090014210430010000000403000900182104300100000004030009001C2104301F0000000403000900202104300800000004030009004021043001000000040300090044210430010000000403000900482104300100000004030009004C2104300100000004030009005021043001000000040300090054210430010000000403000900582104300100000004030009005C2104301F0000000403000900602104300800000004030009008021043030000000040300090084210430010000000403000900882104300100000004030009008C2104300100000004030009009021043000000000040300090094210430010000000403000900982104300000000004030009009C2104301F0000000403000900A0210430040000000403000900C0210430300000000403000900C4210430010000000403000900C8210430010000000403000900CC210430010000000403000900D0210430000000000403000900D4210430010000000403000900D8210430000000000403000900DC2104301F0000000403000900E0210430040000000403000900A0200430EFE100000403000900A4200430000000000403000900B0200430000000000403000900C4200430140000000403000900C8200430000000000403000900CC20043020000000040300090050200430000074010403000900A8200430FE217401040300090004000038000700000403000900080000380015000004030009000C00003801030200040300090010000038010702000403000900140000380C0C05000402008005FFF98720BBF88700BBF88700BBF88700BBF88700BBF88700BBF88700BBF80720BAF80720B9F80720B8F80720B7F80720B6F80720B5F80720B4F80720B3F80720B2F80720B1F80722B0F80722AFF80722AEF80722ADF80722ACF80722ABF80722AAF80722A9F80722A8F80722A7F80722A6F80722A5F80722A4F80722A3F80722A2F80722A1F80722A0F807229FF807229EF807229DF807229CF807229BF807229AF8072299F8072298F8072297F8072296F8072295F8072294F8072293F8072292F8072291F8072290F807228FF807228EF807228DF807228CF807228BF807228AF8072289F8072288F8072287F8072286F8072285F8072284F8072283F8072282F8072281F8072280F807227FF807227EF807227DF807227CF807227BF807227AF8072279F8072278F8072277F8072276F8072275F8072274F8072273F8072272F8072271F8072270F807226FF807226EF807226DF807226CF807226BF807226AF8072269F8072268F8072267F8072266F8072265F8072264F8072263F8072262F8072261F8072260F807225FF807225EF807225DF807225CF807225BF807225AF8072259F8072258F8072257F8072256F8072255F8072254F8072253F8072252F8072251F8072250F807224FF807224EF807224DF807224CF807224BF807224AF8072249F8072248F8072247F8072246F8072245F8072244F8072243F8072242F8072241F8072240F807223FF807223EF807223DF807223CF807223BF807223AF8072239F8072238F8072237F8072236F8072235F8072234F8072233F8072232F8072231F8072230F807222FF807222EF807222DF807222CF807222BF807222AF8072229F8072228F8072227F8072226F8072225F8072224F8072223F8072022F8072021F8072020F807201FF807201EF807201DF807201CF807201CF80700D7F8A700D7F8A700D7F8A700D7F8A700D7F8A700D7F8A700D8F82720D9F82720DAF82720DBF82720DCF82720DDF82720DEF82720DFF82720E0F82720E1F82720E2F82720E3F82720E4F82720E5F82720E6F82720E7F82720E8F82720E9F82720EAF82720EBF82720ECF82720EDF82720EEF82720EFF82720F0F82720F1F82720F2F82720F3F82720F4F82720F5F82720F6F82720F7F82720F8F82720F9F82720FAF82720FBF82720FCF82720FDF82720FEF82720FFF8272000F92720D7F8272000F8272001F8272002F8272003F8272004F8272005F8272006F8272007F8272008F8272009F827200AF827200BF827200CF827200DF827200EF827200FF8272010F8272011F8272012F8272013F8272014F8272015F8272015F8270000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A0008001003181C1003181C0300090000200430800000000405000E000C20FD00FFFF000000000208000005000E001020FD00FFFF00000000000500000300090004210430010000000403000900082104300100000004030009000C21043001000000040300090010210430010000000403000900142104300100000004030009001821043001000000040300090044210430010000000403000900482104300100000004030009004C210430010000000403000900502104300100000004030009005421043001000000040300090058210430010000000403000900C8200430040000000405000E001420FFFF00FF00000000000083000300090084210430010000000403000900882104300100000004030009008C210430010000000403000900902104300100000004030009009421043001000000040300090098210430000000000403000900A02104300000000004030009002021043008000000040300090060210430080000000415000800000000002028000018005201080005000A00FA001E00C80000009F00380000000000000000000403FFF9FDFEFE00FD0203020101FF03060C08080C060A0B060B0A0C0A0A07020507060A09090C0C110B0D0807090909080609FEFFFF010601FDFB000104010205040002020507050305020A060304000102040101FAF7FAF9F6F7FDFE02FEFCF7F9FBF7FBF5F8F8F9EFEEF2EFF0EDF2F7F9FAF6F6F5F4F3EFF1F5F4F1F5FAF8FAF9FAFE0102FEFE0301FCF9F7F6F4F9F7F7F5F7FAFB00FCFDFDF6F2F4EDDCCEFF0507080E0E0F0A0C060505F6F2F1EFF4F6F4F5F6F7F5F8F8F8F2F7F3F0F3F5FDFBFCF9F9FCFAF8FD0B1C1713140F0D0C0B0B0F0C0E100E1112141C1C202024F4F6F4F5F6F7F5F88080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 04 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 64 64 0 010100007F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 84032 176 0 7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 64 64 0 01FE3063070718008374625F696D6F74826A706A666E686A6D70686F6D6C716B696E6E72766F6C776D6C6E6D6E68716366676E78746870707C7A726C6C726973 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 84032 1616 0 68736E726A6B71696C6E6D6E7371747A797B7A7268696E6C6E78787C7770707475777C7276686867626B656D6D6C6F74787F7E7A72767D746F6B6773776D6E736E6C79746F6E74746A6F73746B77717277766E766C6F767A7B72777A6C747575666C6A68605B614B6A696C7C787A7B77746B696B797B7B7978797E7E747E76707476777473666B6C69717A6E70747476776F717477726D6B716E787C7B7177707D7A787B8688888378797E7E747E767001FE31630707181079777B76767B796C6F716F6E6A716F747B6B696F6F7166706B647171746C6A6F68746E7973686A70686C6F7E71726D6F6E6F6C706B757371716D6C756E7569706E6F6F6F6B676C6D78707B7672656D6D6E72747F756D7675787E70706D6B696C6F6F6C76777374777C7774726C75767C646874716F717075746D656C6F74706F6F7273676974707A76817875656C7A767D73717072716E6E6C656569595E63507277787277777573777B73787D7B807E7E76777D7A75787C75666D77716E6E736C767979787071787D717772726F7177736D6C787C766F767A747A817C827E837E76777D7A75787C01FE3263070718207671737573746F777A6F716F66696C78746E6B676A776F6E6F706B696D706A6D6E68696B6F6B756870626E736E6275716C6D777270707677736E7170716D6C6E696F6C6D6F7074737275786E736C787270757774776C67737679727072726D696A6B6C6C6A6B70757879837A746F757876726D73746E6C756F78706E7074706F707770726B74747F787D706D6669777A7D737A7176707576737269626360604D747A7C797D7A7E6E7B70707284838882837D7B79807571787976746E6B717373717972777873777177767D6D726F73726C6E6B726F7572747A7F7F83827B8185837D7B798075717801FE336307071830726D615E5E5A716F6B676C5F66706E6B726E6D6B6E696B6C6F6E707269716D66685B6B70716A6C6264626D6E6B6B69656774706E696D767372777474766A70656A6D6D70737C777476747C7374747379737A6D776E6975758580756C7273726B676F6C716A6A6D7176777C7C767574746F6E6D71746F6A6C76757C736E737477726E7072706E768083796C717371776C7378746F70746F7170696E6D635F594A7577797E757176796F6E6D707A79787A777B80787D7E7B7A787B6F7A75686D6F726D736F72797073736775727C70756E746E7573727878767A7781847E7E7C7F777B80787D7E7B7A01FE34630707184074707070626B716B73726B71696B6D706E6F6F77696C68656A696E767B756E72676D686969696D6E696D6B6F776E67706E6E6B68676E7079756B77717370686569686E6B6C6E6C74767178737568696F71797B7B6F6C6C778581786B726F656E606A697073726C7279777D80767973727175696E6A7076686E7171757A78746F6D77696D68706E7377786D726A717E807E707C7F7175746C70656062675C5F4871727276787472706F6971747D7C7B70777A7C7A7876716E7978746F6F6E6D6B6E74736F70716C6D6F797E79716B6F76747572747779777677817B807D7F8181777A7C7A7876716E01FE3563070718506D6A6563676C697474656C6568676A67626D696F686E6A68726B717272727175766D6B756F6A66676C6765746F6C67727273706864727874706D737272736B6E686E6C6864696B72736F6D70726873736F7B717B746D7379837D766A77746E6E69706E766C706D697474767573757979786D757C707278737A77747474736B6C6D6A6C6A73697073797E6F706871767B767476737976726C69696A696A63554E6F7973796C7071707676716F807C79767A7F79717578757A77716E76726A7075716F6F787473716E7474777B7C78746B6A70736F7C85747D747778818083837B7A7F79717578757A010100007F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 2 0 0000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 2565 2565 0 02F000140003000900042004300000000004030009001820043000000000040300090020200430080080000403000900242004300000FF0104030009002C20043001000000040300090040200430FF030000040300090044200430E5030000040300090048200430EA03000004030009004C2004300A00000004030009005420043001DE010004030009000021043000000000040300090004210430010000000403000900082104300200000004030009000C2104300100000004030009001021043001000000040300090014210430010000000403000900182104300100000004030009001C2104301F0000000403000900202104300800000004030009004021043001000000040300090044210430010000000403000900482104300100000004030009004C2104300100000004030009005021043001000000040300090054210430010000000403000900582104300100000004030009005C2104301F0000000403000900602104300800000004030009008021043030000000040300090084210430010000000403000900882104300100000004030009008C2104300100000004030009009021043000000000040300090094210430010000000403000900982104300000000004030009009C2104301F0000000403000900A0210430040000000403000900C0210430300000000403000900C4210430010000000403000900C8210430010000000403000900CC210430010000000403000900D0210430000000000403000900D4210430010000000403000900D8210430000000000403000900DC2104301F0000000403000900E0210430040000000403000900A0200430EFE100000403000900A4200430000000000403000900B0200430000000000403000900C4200430140000000403000900C8200430000000000403000900CC20043020000000040300090050200430000074010403000900A8200430FE217401040300090004000038000700000403000900080000380015000004030009000C00003801030200040300090010000038010702000403000900140000380C0C05000402008005FFF98720BBF88700BBF88700BBF88700BBF88700BBF88700BBF88700BBF80720BAF80720B9F80720B8F80720B7F80720B6F80720B5F80720B4F80720B3F80720B2F80720B1F80722B0F80722AFF80722AEF80722ADF80722ACF80722ABF80722AAF80722A9F80722A8F80722A7F80722A6F80722A5F80722A4F80722A3F80722A2F80722A1F80722A0F807229FF807229EF807229DF807229CF807229BF807229AF8072299F8072298F8072297F8072296F8072295F8072294F8072293F8072292F8072291F8072290F807228FF807228EF807228DF807228CF807228BF807228AF8072289F8072288F8072287F8072286F8072285F8072284F8072283F8072282F8072281F8072280F807227FF807227EF807227DF807227CF807227BF807227AF8072279F8072278F8072277F8072276F8072275F8072274F8072273F8072272F8072271F8072270F807226FF807226EF807226DF807226CF807226BF807226AF8072269F8072268F8072267F8072266F8072265F8072264F8072263F8072262F8072261F8072260F807225FF807225EF807225DF807225CF807225BF807225AF8072259F8072258F8072257F8072256F8072255F8072254F8072253F8072252F8072251F8072250F807224FF807224EF807224DF807224CF807224BF807224AF8072249F8072248F8072247F8072246F8072245F8072244F8072243F8072242F8072241F8072240F807223FF807223EF807223DF807223CF807223BF807223AF8072239F8072238F8072237F8072236F8072235F8072234F8072233F8072232F8072231F8072230F807222FF807222EF807222DF807222CF807222BF807222AF8072229F8072228F8072227F8072226F8072225F8072224F8072223F8072022F8072021F8072020F807201FF807201EF807201DF807201CF807201CF80700D7F8A700D7F8A700D7F8A700D7F8A700D7F8A700D7F8A700D8F82720D9F82720DAF82720DBF82720DCF82720DDF82720DEF82720DFF82720E0F82720E1F82720E2F82720E3F82720E4F82720E5F82720E6F82720E7F82720E8F82720E9F82720EAF82720EBF82720ECF82720EDF82720EEF82720EFF82720F0F82720F1F82720F2F82720F3F82720F4F82720F5F82720F6F82720F7F82720F8F82720F9F82720FAF82720FBF82720FCF82720FDF82720FEF82720FFF8272000F92720D7F8272000F8272001F8272002F8272003F8272004F8272005F8272006F8272007F8272008F8272009F827200AF827200BF827200CF827200DF827200EF827200FF8272010F8272011F8272012F8272013F8272014F8272015F8272015F8270000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A0008001003181C1003181C030009000020043080000000041700000005000E000C20FD00FFFF000000000002000005000E001020FD00FFFF00000000020500000300090004210430010000000403000900082104300100000004030009000C21043001000000040300090010210430010000000403000900142104300100000004030009001821043001000000040300090044210430010000000403000900482104300100000004030009004C210430010000000403000900502104300100000004030009005421043001000000040300090058210430010000000403000900C8200430040000000405000E001420FFFF00FF00000000000084000300090084210430010000000403000900882104300100000004030009008C210430010000000403000900902104300100000004030009009421043001000000040300090098210430000000000403000900A021043000000000040300090020210430070000000403000900602104300700000004150008000000000020280000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 2368 2368 0 00000000FFF98720BBF88700BBF88700BBF88700BBF88700BBF88700BBF88700BBF80720BAF80720B9F80720B8F80720B7F80720B6F80720B5F80720B4F80720B3F80720B2F80720B1F80722B0F80722AFF80722AEF80722ADF80722ACF80722ABF80722AAF80722A9F80722A8F80722A7F80722A6F80722A5F80722A4F80722A3F80722A2F80722A1F80722A0F807229FF807229EF807229DF807229CF807229BF807229AF8072299F8072298F8072297F8072296F8072295F8072294F8072293F8072292F8072291F8072290F807228FF807228EF807228DF807228CF807228BF807228AF8072289F8072288F8072287F8072286F8072285F8072284F8072283F8072282F8072281F8072280F807227FF807227EF807227DF807227CF807227BF807227AF8072279F8072278F8072277F8072276F8072275F8072274F8072273F8072272F8072271F8072270F807226FF807226EF807226DF807226CF807226BF807226AF8072269F8072268F8072267F8072266F8072265F8072264F8072263F8072262F8072261F8072260F807225FF807225EF807225DF807225CF807225BF807225AF8072259F8072258F8072257F8072256F8072255F8072254F8072253F8072252F8072251F8072250F807224FF807224EF807224DF807224CF807224BF807224AF8072249F8072248F8072247F8072246F8072245F8072244F8072243F8072242F8072241F8072240F807223FF807223EF807223DF807223CF807223BF807223AF8072239F8072238F8072237F8072236F8072235F8072234F8072233F8072232F8072231F8072230F807222FF807222EF807222DF807222CF807222BF807222AF8072229F8072228F8072227F8072226F8072225F8072224F8072223F8072022F8072021F8072020F807201FF807201EF807201DF807201CF807201CF80700D7F8A700D7F8A700D7F8A700D7F8A700D7F8A700D7F8A700D8F82720D9F82720DAF82720DBF82720DCF82720DDF82720DEF82720DFF82720E0F82720E1F82720E2F82720E3F82720E4F82720E5F82720E6F82720E7F82720E8F82720E9F82720EAF82720EBF82720ECF82720EDF82720EEF82720EFF82720F0F82720F1F82720F2F82720F3F82720F4F82720F5F82720F6F82720F7F82720F8F82720F9F82720FAF82720FBF82720FCF82720FDF82720FEF82720FFF8272000F92720D7F8272000F8272001F8272002F8272003F8272004F8272005F8272006F8272007F8272008F8272009F827200AF827200BF827200CF827200DF827200EF827200FF8272010F8272011F8272012F8272013F8272014F8272015F8272015F82700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038A483F58000000000000000040000000300000008000000000000000000000006000000080080000000FF01808000000100000000000000000000000000000000000000FF030000E5030000EA0300000A0000000000740101DE0100000000000000000000000000000000000000000000000800000000000000000000000000000008002028000002000000000000000000000000000000000000000000000000000000EFE1000000000000FE217401000000000000000000000000000000000000000000000000140000000400000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000001000000010000000100000001000000010000001F0000000700000000000000000000000000000000000000000000000000000000000000010000000100000001000000010000000100000001000000010000001F0000000700000000000000000000000000000000000000000000000000000000000000300000000100000001000000010000000100000001000000000000001F0000000000000000000000000000000000000000000000000000000000000000000000300000000100000001000000010000000000000001000000000000001F000000040000000000000002000000000700000015000001020200030502000C0C84001003181C000000000C0000000C000000010300000000000000000000010158026F0000848418620000000000000000000000000000000000000000000000000000000000000000000000000000000000A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A508000000C0014000FF1FFF1FE123FF1F18A25503D3A25D0018A25503D3A25D0018A2550320FF80003F040F0100000000000000003800000000000001000000000000000000000000130000001400000000000000FFFF0000040000008E0000000000000000000000050000000000000000000000000000000000000000000000F000000000000000EE000000980000008800000011000000000000000000000000000000FF0000000000000000000000000000000000000000000000000000000000000000000000FF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 36 0 000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 4800 4800 0 01FE0100070708106F67666B6A6B716A746E6662646D73716B68696F6C6A71686D6B6A67726C6C6C6462675B746C6F6A6564656B70727078766D706F6D716E716F7370717577796F6E7766706F72726B736D6E706C6F7974717A726F7273737B807A776D72716E6A6C6F64717171736D78797476726F73726B6B73757A6F77766D696F727371706B677069666E767972787A77767271767E78706F716F7771706A646769625F5E526E73787175737278736E65767D7E76736D7371746E6E757F7B74757A7472707A7073736D716F72767D727D74797378726D6D757B737A746A7A7C7880808182826D7371746E6E757F01FE0200070718207670686A686D716C767373686C746F726B65676A6A6D6E7371666B767171726E676662616B696B6E6B6F6A6373737675706D767A73706D6F6D696E696A6C6D696D70737270716B7B8172706E70697870676A717374756C7E817D7370726F706D71686D6C6D737775777882807774777370716E6E6F717171767375757974757665636B686E6D7479827C746A6B71736D7174757870747C756C6968676153544A797977798073766E737771747C7B76757C747773737B767A79777A717971716E7470716F70757573766379757A7672716F6E6F7779827C747375747D827F7D807C747773737B767A01FE030007071830776D62656B6B7673716C686B6B716E6A71706B716E7469706E75706B736F6B6E6E6663676E63686D6C65676D686A6F6979777570747E767E71736E696766656672726D726E746E736F726E7571797D737575787C6D6A707079807B727C7467716C72686F636B717275787277767A6F716A69716A70767A6B79726B746B6D686C6F6C717075717975787D77777072767880776E6F7C6E7C7168626167615C5E497B736B74797A7870776F766F7C7F807E7F777E7A827177787C746C6D727979726B71736E6E656B6B72757F7775737774736C77757C76787675797C7F7E7C76877F777E7A8271777801FE040007071840787D6A70686D6B6B76696D6B6A717677746C707476756D6C716C6B6F736A6969656D696B6E757165645F616970697074746C75706E6F7173746E6C67726B746B75717073686B6C75796F757471737B7672727776697471767B7A797373766A6861696D72726D6D827E7A757C74717672706971746E6E717570727377797377717A6E7270766F6E707775737368747D7D756C726C747B74716C6A5F626060624D807B7A7778757273757A7975827576837F7F7679737C727B7A75717673737073797971786C6C6C7978707E7278626A78777171756C7770777D7D7E807A7D77907F7F7679737C727B01FE05000707185079736C65636A746C706D61605A6B676C6B6D6C666465676E6F6B7178717A6C716C6C6F6D6C646D67636367666969726E736F6F746A797A777B6E72726B6B726E71746D70707571737F7370776D73766D6E797578757270727872797471696F6D667272757768717C727A6F847973756F6B6C6E707C6F6F68656F707372757A6F747F796A6F746E717379776E706C7279717E7F70737178767174656563575A4B767D716D747B747874726D767C7D817675717B7E7776756F78766F706E6977787679786D71777678796F7A7373706F7271736C796B6F707A7D7D797E7D7D7B8275717B7E7776756F01FE06000707186075716C6E6973747D7173796E647075736F74736F706969687470796E6C6F71706E71787B6C6567676366666C6D676B6D7178726C6E6F70797677756E6D6A6B6B75716E79697874797A7C726E6F73746E6D767177716E6F787F7A7171736C68686D6B67676E6B767473767F81737E7A6F6C726B6F76796A6A6A726C7B6F66726E656C696E747B7C76777B7971716B6D707582777B73787870716A6561635C5E4C7879756E7879757B7E72746C787A79818388807675767571757273746C776F6F6F75757375787372796E78757572747C7A7370716F71747E7F7F747E7E818283838880767576757101FE0700070718707370686E6A747575756C6B6D666871716E6F696E696765686B616C6277736C727071646868666D646365686D6F726F73747176727073757B747071696E6D6A6B6C6768716D75747883796A7B6F70716B6B7C73787173756D7C7C7368706D6F6868667073716F6B6E7B838083757D73776B6676717070727173736767717374706A6B6A706C67747E80766F706B72737B7A7371737A78777570716963655A5E3E6972786F6A78747174726F747C7D817B78717A7972777977706E72746F6B747979756B73716D7975726E787573737B766D6B6E74797D73787A807984787F778078717A797277797701FE080007071880706E666D6A6E74736C696F716F696F6E696B68696B6A706B686B727579726C6D6B6F7076716D645D676D6F606F656A6D70716F676A746D6F79696E6F6C6572707575706F7175737782786F74786E6E746F7877806F666B70747D786F71676D626B64726F6E6F7A6F71778280757979796B6A727079716D6E6B6D6A6E70737677706E706D74737C7979767D79756D74797D7168706E767A696F696F776960605178797175787878797B647471797F777775737E817D78766D7475736C727575837A787D776C7075706F6D767178766D6C6C727A7471766D7979767D817B7C7B8575737E817D78766D01FE0900070718907072646F707C7574787C75726C7071716E6B66646D6C72717173757172726872707772787A716B6361626C6B6C6D6E756D6872716D6F7178706E73706C6C6B696B70686D7572656D70766D706E70767B757A7474787072717776736C6C736C6E6F6F747B72707475757672736F756F7870707673746C6D70736C72736F6D7069737378767270747377797A72697476777277807774767376726F6D68606058487573797680797A7A7E776D7670807C7E7D777B7978767774727579756D6A696C7476767276707479817575757373766969746E74747474758179827F807F7F887D777B797876777401FE0A00070718A0766D6A6D666B7A6C706E6F6565626771676C6369696E646E716F6F777266686F696A696F6669666B66656A6B7072736E716E746B69666E7375776F6D6D6C6C717771706A6E717272766D6F7477797D7C78717278766965787E817B697074666D6D706B74707373766F79717973717375706A6A71717275717071736C787876747572696D716E7379797172656271776D766F7D767B7379756F6D6D6464605A4F797976776F6E6C7872746B737D7F76807C6F757479787772757273796E75726E737268716F687275767276777970717178746D77727477727D7D7B807D8182837C6F75747978777201FE0B00070718B0796E5F585E646D6E696E65675C68696D6D6B776C6663636667646B70716C696C636B6E72696765666A6665686C7177757A757274676E7776736D737A766F686770706F6A71706D6E6C7671706C6D756F6C747377787069757C7C726B74776C6D636A707372716F7370797C7F786A767B716E6A6E75777B737A756E7278747A726B6B6F6B776A6E737875757571727F79807B72797271706B6F6673665E5C564A717D72796F77706F6D6C717782767B797B75786B7775767774646E747B707775706E7672706F6A6F6B7077756E6F726E737C767D767A767A7C7D758079767C7F7B75786B7775767701FE0C00070718C0766F706C7272757581787B67746F697271716E6E6D726C70676E6D706D6F757467676A696D6C676B73646968736C7475717C736B656E6A6D7673766E6F746F6C67746D737174686D76736C6E786E796D6F7D6E726E6F676E7C797469716A6C6F6E6A6779756E72767B7B7773737A7B776D6C696871696C6A6F7C75787278726D726F6E7570736D757F82737271777474766D776975757A747A6F6162615C59497076797B767C7776746D787F84817E7B777374687B77767F7A7978767B757476687074726C726B727A737B7A6E6A6F74716B6C726F7C6F787E797E867D7D7F88777374687B77767F01FE0D00070718D07370696E5D61656B746F6F6C666E6A67726F676B6D696B6D697076706C77706F6B6D6A6B70626E6D5C5E6B6C6C767074726F7570647077737075766C726A6A7170706E706B716C6B7970746B727E7B7070697F7D716F726F72777373776D676872766D697070767D7D7D7B7A7D767A6D6B64687064687269756F74737A74766D70746F6A797D7C727779716E716C76747D7A78706B72766A6372716B5F5A57466B6A6E6F75757075796D6E6B747A847D7D7273707C7A747974756E6D787470757171766763687977756E737A79756F7375727378727E757472757D7D787F7F867D7273707C7A747901FE0E00070718E07976707472747D74746D7D7A676C646C686871606A6E6C6B716C706B7A797371666C67706F62686B6966696474696D76756D6D676C6E79757571716F6E6F70766F7268746E717C757D65656E6A79766F6F746F7E78727974787B786C726F6473707162747074777A8276797A68747E776C686B696B6C7278806873717573746F7171636A7274726A727372776B7681847B7474757473747267645E666056544D6B686F6A6D767078706E747B7F7F807B7F7C7972797774797C73717271706A6B6F726F75726F79727070797B7478736E73716F6C78766975757B78847F7D7D827F7C79727977747901FE0F00070718F0746E696B6D6A706D80706F636D615F6C716C6A6C6E6B6D6F706C6B7672716F767167736A6F6C71736D6A6964676576747A6C726C6E6F6B7571726D69676C6566726E7371777771707A6E726E6B6B746E6D7573746B676D777C87737270726B696673737374747A72788A767974787670656A72717370716B67726E6E6A73767772667472706C6F6B787570736F6C747974747581767478706D696B5C5B5A5F4C7480827B7D7A75717D76737D7E7D7873757C7E7A7C7B7772786C686F777472766F79797475767579706E7A797C7974717673746C7676767B767A7B82747B8585757C7E7A7C7B777201FE100007071800756B6C726A6B68706F676F71636D716D6B6F706A696D656B696A6E72757976766D6D726C696B6866706775666A696A70767873776B756B7174726F6A6965646E757170746F74716F7E7674777979776F75717274717174777D857771746B746D706B60706B606A6F727A7F7C777B8079696871737372766E6F70706E716E6E776E6A736A6E6F7C6F6F6C7974746F70767B707578747A736F6A6D666B6A625E477270777A7377716A6B7A70767A837F7576717880747C796E787373726F6B7C75757166717071727172717A7874696E7473737173787471737B6C79887C7F7E8276717880747C796E01FE1100070718107A766B766F6C716F786E776F6E6F6E75666A707067696B696E676E72786F6E6D646D6C6B6D6D6B6C6C6B696C73696D6A6E7573726C6D6C6C6D6C7479786D6E686A7166726E756C6F82767474716A73746B7677776E7274737473746F7A6F636D5D6B6A736C737474756F817D7F76767775647978757F786F6A706B6A706E697070766F7574747C797B79726E7178767070737977756C696A6F686B5C6459624C6E7B7B8181787C737A78737082867F7E80767873777B7B7A746E716E756E737679777279707A76766F6C808081716B6B7273777A7D75727A857F797C7E877E8180767873777B7B7A01FE120007071820747267726D717873786C6A66686B7271716C6C747167666C61666A756E67686D7270706A71696D726966646A746779747D736D7070776E7873716E726F67736A6B716F746F6F7776786A697275746C70776F7171747273747C7C76717069696E62656D766F747B73758179787771796F6D696B776B6D7674756C6F727A7A7C72756D6E7974797370757D787474726A78726C7070707075706D68656A6D5C5E4D7B7C71786F727A6D7175747079827C7C7F82806F78757B73786F75747D74797A78786F6C6E71676C6F69747877726F7571757A7976736C7674717D7B817D7C847F82806F78757B7301FE1300070718307A716E756C6C7376746E6C70646B6C716A6F70736B68726B696A7A79797A786A6B676F6767696D66676B6768676B73727674786A6E6D6F726D6A7A79736672696A7170716E726A6F726F777578727B7C7471797970726C7E797878746D6A6B6E6D6361666E707473757978786C6469736E6F6C72716B6A6C6D697876787F73796E69716E79727A727B7D74746C6978817B7C7C777671716573726B665E5857487A6E7173737477736F7174747D80797A797C7F7279777673767B77787E6A6A6E6E7671717279736D7C6C7971737E797C7170716F74766E6F7B7D7383797A7B82797C7F72797776730101000007071840746D64736B6D6D6B68656D6A666E6F6E787670736E6F6C73746D6A6C6F6E656E6C686C6D666E6B646A5F6E64746B706870757074696F6A766C77737272696D6D69666A7564786F6E7F6F736D7277747175777871726F6F727D7973727363676A71746B6D656F706D77737E808076726F6A68686F727477756A6A747A7E75726C7472757878797779787D7A73706873797C6D6E7B78767870696F65635A625D4E736D6F6F726A6971796C757C7979767C80756F767E797670747675776E6A6E7B7374747075746F777F7277707072716A75716D75807A706D787C827A807A858280756F767E797670 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 2368 2368 0 00000000FFF98720BBF88700BBF88700BBF88700BBF88700BBF88700BBF88700BBF80720BAF80720B9F80720B8F80720B7F80720B6F80720B5F80720B4F80720B3F80720B2F80720B1F80722B0F80722AFF80722AEF80722ADF80722ACF80722ABF80722AAF80722A9F80722A8F80722A7F80722A6F80722A5F80722A4F80722A3F80722A2F80722A1F80722A0F807229FF807229EF807229DF807229CF807229BF807229AF8072299F8072298F8072297F8072296F8072295F8072294F8072293F8072292F8072291F8072290F807228FF807228EF807228DF807228CF807228BF807228AF8072289F8072288F8072287F8072286F8072285F8072284F8072283F8072282F8072281F8072280F807227FF807227EF807227DF807227CF807227BF807227AF8072279F8072278F8072277F8072276F8072275F8072274F8072273F8072272F8072271F8072270F807226FF807226EF807226DF807226CF807226BF807226AF8072269F8072268F8072267F8072266F8072265F8072264F8072263F8072262F8072261F8072260F807225FF807225EF807225DF807225CF807225BF807225AF8072259F8072258F8072257F8072256F8072255F8072254F8072253F8072252F8072251F8072250F807224FF807224EF807224DF807224CF807224BF807224AF8072249F8072248F8072247F8072246F8072245F8072244F8072243F8072242F8072241F8072240F807223FF807223EF807223DF807223CF807223BF807223AF8072239F8072238F8072237F8072236F8072235F8072234F8072233F8072232F8072231F8072230F807222FF807222EF807222DF807222CF807222BF807222AF8072229F8072228F8072227F8072226F8072225F8072224F8072223F8072022F8072021F8072020F807201FF807201EF807201DF807201CF807201CF80700D7F8A700D7F8A700D7F8A700D7F8A700D7F8A700D7F8A700D8F82720D9F82720DAF82720DBF82720DCF82720DDF82720DEF82720DFF82720E0F82720E1F82720E2F82720E3F82720E4F82720E5F82720E6F82720E7F82720E8F82720E9F82720EAF82720EBF82720ECF82720EDF82720EEF82720EFF82720F0F82720F1F82720F2F82720F3F82720F4F82720F5F82720F6F82720F7F82720F8F82720F9F82720FAF82720FBF82720FCF82720FDF82720FEF82720FFF8272000F92720D7F8272000F8272001F8272002F8272003F8272004F8272005F8272006F8272007F8272008F8272009F827200AF827200BF827200CF827200DF827200EF827200FF8272010F8272011F8272012F8272013F8272014F8272015F8272015F82700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038A483F58000000000000000360300000300000008000000000000000000000038630000080080000000FF01808000000100000000000000000000000000000000000000FF030000E5030000EA0300000A0000000000740101DE0100000000000000000000000000000000000000000000000700000000000000000000000000000007002028000002000000000000000000000000000000000000000000000000000000EFE1000000000000FE217401000000000000000000000000000000000000000000000000140000000400000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000001000000010000000100000001000000010000001F0000000700000000000000000000000000000000000000000000000000000000000000010000000100000001000000010000000100000001000000010000001F0000000700000000000000000000000000000000000000000000000000000000000000300000000100000001000000010000000100000001000000000000001F0000000000000000000000000000000000000000000000000000000000000000000000300000000100000001000000010000000000000001000000000000001F000000040000000000000002000000000700000015000001020200030502000C0C84001003181C000000000C0000000C000000010300000000000000000000010158026F0000848418620000000000000000000000000000000000000000000000000000000000000000000000000000000000A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A508000000C0014000FF1FFF1FE123FF1F18A25503D3A25D0018A25503D3A25D0018A2550320FF80003F040F0100000000000000003800000000000001000000000000000000000000130000001400000000000000FFFF000004000000FE0000000000000000000000050000000000000000000000000000000000000000000000F000000000000000EE000000980000008800000011000000000000000000000000000000FF0000000000000000000000000000000000000000000000000000000000000000000000FF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 64 36 0 000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 4800 4800 0 01FE0100070708106E6F6D6A6A6E6D716F736C6D69677474706B6F717369686E6D716C717272686E6973707176676D696765677370707572736C6B6B656F6F797276787C7B71676C6A69676C6F726F71817A71797378736E72746E79726F6F757B786A6D76716B6C69746B716E726D7074727671717272756A6C716E797B7C7A766A677371717670736E747572797873807679776C74747C7873767574767172736D6C6764605F4B76727C837E777876837A756D7D7C7E7D7B70787578806D6F74686E7878706E756F73677072726F6A76767D797A77737070717575747A6E71797780807F7C7F837B70787578806D6F01FE0200070718207C726B73696A6A747A706B68686B7574707166626D6B6A6D6C716E7573746B6C6466736E686A6D66656C716D6D646B6F70726B787771706D74767A7373706E6A6D6D6A6F6E72716A7C6E727972726C686F777573736F6B79817E7875746C6A6F69666770726E71737C7E7374707C77746E6E7379716D71746F6B6E747674736E6F7171686E6C79777A7B77786C6B727870777E79807474766961636862615C4B717C73787B72767B7870717B777A7C787C75766F75787E7B776F737B7770686A757A70716F787A7378757878776B6C6F716E6E7872736F707E80838B817E82897C75766F75787E7B01FE030007071830797775717174726C7369716A6C78696B706D6F6B6E6B6F716D757C796B74717767686F6163637570696A677071707070736D6E6A696F6E6F6C666D74726F6E6F6666646670716C7675726F6F70696E747279807F7371757678787270696369706B6E6B6E70796D6F7C7C787A787D7B7F726C68706D766E686F726F736B737A7A74706C727276787B7477746E6970797679737977737875727167626964535949716F747B6C6B736F6B716A6E8280867D76777B75767A767B7575717170746D7A757170726974767B7973796F717573716F747576707070787D75777B7180888876777B75767A767B01FE040007071840796E6A6F606D716E7474676D6F707A776D726C706D686B6D666C777971706E75665E63606F6A70676E67677A736E6C696C7468626C6F7B6F6C7073776D75606D6E69697072757072756C70767170727B7B74767C6B6E67747E747771716E676B6872696F6B697071777A7A747571747D786D666A74716D7576747171697178717377766E72757178797A6F71726B7B6B72736E6A7B75757875746975635B5A4B787A7B7A7A7C7A71756D707D797A847F706E727879797B817C7A766E777275777475767671707C757970777575726E7371716C767B747077757479807C787F83706E727879797B8101FE050007071850776D656A6A6D746E706D706D646B676B6868666D6668706E6768686C7B7C6A6F736B646D736D64626B69696A6F6F6F71716D727C746C73787070706E6C6F736D6A6D68626E7175797779767A726E737471706F746B6B71707E81707068656E69626868716C766F70777172777772727379716F7B71716D736A6C726B727573706D6F7077716B70807D797876766D76757C797480787371726B676261655E6046667071736E6F7273747073696A76828277757677797179716D6E6E7477776D676F737172696E7377786B7D7D766F757572696F7678766D71777875817A848081777576777971797101FE060007071860786B6C6E656D747175666A69696B69796C646468676672746A616E706D706670696D6D717768676864626E71757471716B73706D6E677171696B7074666E6D6B78746C69686E6D6E766E6E8072776F756E757A80756D6B7178746B71726F6E736A6B71776B6E707D7F78787E747C767B706C73746D6A736E736A74726B707475676571746D6C72757978756C6470797773737D7A707A7273706C6B6B6653584C7B7B756F747073757B6E73717C8182857E747B6D7D776F777B76776C6B6B72776C71727B7578766F756F7B7975796E6D69767B76787B7175797679807A857F857E747B6D7D776F7701FE0700070718707472696965717067706A6F706864726B6D71676B69656D6E6B6E79716E706E6F686769676E6F606465686B6A7364796D717975756A777273736A70717278766C69656B6D69786B7476747477716A7475717273786B7479767B827B716B6A746F6D6C6B6F756F6D6F76847A76717E7C8271676D69736B796F716773707272776E6A726566706F6F78787771747273757075747676757B766C6B6866646355554B727274706D6C736F6D6F6A71757C747E78707877757C7775727676716C7076756B7476707876727574767C6A7673756E6F71777B787B71777B7F7C827C78828178707877757C777501FE08000707188075726E6E646774736E6B6F6A696C6F72756A6769676061656B6C766F6E766C6E686A6E66636F6F646B656B676E736C78776E6D6D6F6A70717173796C71706F6C6F6A646F70726F71747575746A72766F6D75747675696A6F7D8075737B736F6D6470666B6B73727878787C7E7975767C6F6F7A6F70756C6E63756D707074706C74716E726F6E6C74757973767370717279737B757A837B7278695E6661595F5180827C7E76766E747E736E6F7A7C7A7C79747D7C767A7C72757B78766E6F737C6C6E72786D6D71787771767267726B757672787E75796F726F6D80817C7E787779747D7C767A7C7201FE090007071890736C686A676C736E72696C6F71716A706E6F6E73706B70646368716F7371706F66676B6E6B6866706C6A6B7772807769706D7080707973706E716F7473626A62637260716B7170777873727D6F7072716875727672736A7C7C8079677879696664676D74707772797277757D767974746C6A6F6B7E766F746F756C706E776A71766F796A6E706A7678786F71757479737A6C6F767D7C7A73766C6A6A6561584671797C8A7C73707D7A72727E797B7E80807A6F797C797079787675777C7075717177676766707475766C7C7A7F776E6E73787572767873727E7A7B79807D7C7E807A6F797C79707901FE0A00070718A07873606A656C75706D63696C666D7178776B716D716C5F6A666A717577716D6D66636E6B696D6D6A6A6872756F67696C68627273767067726D74797B717672665C60726A6D716D737170746F717976737A776F7B72777672747875707175666767737878726D7577737B777B756F6C8180716B6E717372746D6F6A77767A747073736D74746678777A7D786D6264737D77736E75777970766862666659636253797F80807F767E797F7B7A788180767474717A81777B77807A7B7277716C6E7978786D7B7B6A71737370797D77746A6E6E6E7C7676756E787D7F7B827883828574717A81777B778001FE0B00070718B079716A676B7174727769736F6F756A726B706B6C706E6A6D6D69727778736C72646B6E6066646C60646F75716D6A69706C6D6F73726B72717272716D736A70787074736C65766F6F77726A6D6C797272777A70766B796C7C82837A6D736F6B6C656A6E776A6D6F7A717581797B7E7879796F70786F6D6D6A6D6A70706B74707269707779716D6D6A7A75796F6D6F7A75767E78747377716F6A6B686A6564655374747E81757B7878777970758079776E767F7E7D7D7D717A7A787477716774736D7C78726F77757A70687674716A706E6C6D75756F7A727A727677797C7F8187767F7E7D7D7D717A01FE0C00070718C0716A6B7771727372756E767265666B7469736A6669656B6B706B726F7A6F7270706C7072726D6463625F6C736F6C6A7172796E74656C7375797778746F706F66627074736A716D6B78797C786C6F7D776B757177706E72767B7B71666E6B64686771667B6B6F6E7770777C7B77777A776E6D6A7373736B65717277716F75726C7773716F6B6E6C77747D75807D6D6F7A7B73727977746F706C6D6A6E65665D496D6E7A7472686F6C777C6D74757D7D737A736F797978777778726F77766D6F787C7774726E757679766A6B75766B6D736E6C69787379797B7C7B81847A79787F7A736F797978777701FE0D00070718D0737069726C6D71716C66727663656D747A6D6968706C72716B6D6C7071727176736D6E6B7166666C686A6378727074687870706E71736F74746F7174706D6D6C727166746E756C787F70736F727376737371747B746671727E787271796E6765636F6E7471706C72737D797872747578776E6A6B696F6C6C7077746E707679726B6C727177757876757E7A796C677376756D75757575737272706D6B60675B52727C7780727A766E6F776B6E707E797B817F7D7C7A74737073727574766D6A717A78767468666F6E73707F706C71726F766D6D74767573777F7B79817E7C7B82817F7D7C7A74737001FE0E00070718E07D6A72756B6D757479716D706C706B6978737478736B716B736F79787C746D6C676571717671746A6666677A6D6E6A66716B716C6A6E6B796F736E6F706B6A67696873716F6F6D7A73706E776E6E77767873777873726F797B7E6D636E756E7269716D706C6D6C6E7A7D7C756C79757F71696F706E6A6D74716A717B75777B716C6C7071726673747C8475766B6970797770706F70767A676C6D6D6D6C62524673756E716C6775767A746E727076767C76767777727776787E7770777C6F6D757371716D716E7675706B7680796E76706C6B6F7E7A7B7C847A787A807D7F8684767677777277767801FE0F00070718F07A81777E706C787979766F77726B6D6B736D6E726B7474736D766F6F7D686567706569716C70726D6A6769706E777673766B7874686672756E6E6C726A73716C686F6E7A7378777279706E6F6D7577796A706E7876726E70776F747877746F726B68687072787A73726B7B7A6F6D7477726D6A71707873717A756A727C6E6F72727672777072797271786A6F6D747D74747675737670736E636C68675E5753496C7473776C70707578736E6F7A7E7D808078777579786C6F77746E7A76716F73757471747070747185757172706A696A6C7175746F77737A757C737F7B7C78838078777579786C6F01FE10000707180070766F7F7476797B8377716D676A677D75737570666E6C686E6B7275737576786D6B736C6F696D6B6B636C756C6F6970736E79736A7C6D7477707372736E66696A726A7169666A6D73706F726B6E72787076776E6D6F707A7979727079706A7168767471656B73807978756D6D737C8071666C76716C707572676E7779737474727071726F71726C727C6A6D6C6771797878766F7373767670756A635B605E5374747579787E767972666C70757C7977736E73787D75777C77756F747477737B716B726D7172796D7B6F7872757175726C6E6F7377727679747D7981797C7D83736E73787D75777C01FE110007071810766B6262656067676C6E6B65726A6D756E6E6B646B6366756F6C6764736D6F6F696A6E666E6C6B6E696964686B6F6B7075707A71747673736E777474686A706D6D6964636D756F7370766D75786F767374736B78726B63777C8073726D6E6D656B6A6F73676D6D757B877F7B79787A816F67717477646E6D6C6A6E706F71796D7978717275707574737674776568737D7673797B777B78766E696B7564635548737B777F7C7C7C737E6F767181808183827D7A797B7470817E777977766E6F7373746E7274737275776F73757F7A6C7373716E7B7274747273737C8281837F81827D7A797B74708101FE120007071820766E6B736A6F77716F696C67656C707875776C6D69696C706D686B6F6F76647374716E696966645E6868727569706B7470737171656A7273726D7C6F6A6F62696A746D6C686D726F737476756E696E776C7274737175777A827C73737175676C6A6D72746D747271767A7C83776E73786D6E676B7271746F73716E756D7A696E746C717F777F7270747D6F6E77777A797276746F73767368716C65646757594D6E767C707371756B7A7870747E7C7D83817C8270777A737679766F6E697273746A6E706E6C6F7374796F7D7C7973746C756E7071767D73737980777A857C7C82817C8270777A737601FE1300070718306F6761756D6A727477756C6B67716F7471746B6A5E6A70696B6E6B6866736E73756D686D726E6F6566636A7173726F747078716B6773747F7C7974716A676B676F736E6673806E70746A6D70646D7E736B6F707F7277757B797D726F6F736C6670717079787778747571776B726B6D736D6A6D76716F6B6F71697271707674767D707170727773737379796E6A6F75717072777A7175776A6B685F635F5E5E496C686F71726C716D71687074777B74777579776E78736F777472726F716E7A84776F6C79756F5F6B716D757C78797577757171767A74727C7F78717C788181857579776E78736F7701010000070718407E746F6C6A7076746E6B6A73706E6D6D6C6A6D6F6E6A6B6666777A6D71736B706F656D6E6E676C676E656A746D74727676727272616D6C72697870707071696E676E6C6F6F776F7174796F776C6E7767717479726D69697785827579767266696C6F6A656E776E807881796F6A7377746F6E6871716F6D6E7B7C7977717D717275716966716F6A6D807F7A74686D7B7B747E78757C74777774626D735F5A554276807E7E786D7877817A77727C7F7D7B817C7C75777775777B7C73767574707A72767477726C6F6E787479727570747971706D7370777B747B7479807F758182817C7C7577777577 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 2903 2903 0 02F000000003000900042004300000000004030009001820043000000000040300090020200430080080000403000900242004300000FF0104030009002C20043001000000040300090040200430FF030000040300090044200430E5030000040300090048200430EA03000004030009004C2004300A00000004030009005420043001DE010004030009000021043000000000040300090004210430010000000403000900082104300200000004030009000C2104300100000004030009001021043001000000040300090014210430010000000403000900182104300100000004030009001C2104301F0000000403000900202104300800000004030009004021043001000000040300090044210430010000000403000900482104300100000004030009004C2104300100000004030009005021043001000000040300090054210430010000000403000900582104300100000004030009005C2104301F0000000403000900602104300800000004030009008021043030000000040300090084210430010000000403000900882104300100000004030009008C2104300100000004030009009021043000000000040300090094210430010000000403000900982104300000000004030009009C2104301F0000000403000900A0210430040000000403000900C0210430300000000403000900C4210430010000000403000900C8210430010000000403000900CC210430010000000403000900D0210430000000000403000900D4210430010000000403000900D8210430000000000403000900DC2104301F0000000403000900E0210430040000000403000900A0200430EFE100000403000900A4200430000000000403000900B0200430000000000403000900C4200430140000000403000900C8200430000000000403000900CC20043020000000040300090050200430000074010403000900A8200430FE217401040300090004000038000700000403000900080000380015000004030009000C00003801030200040300090010000038010702000403000900140000380C0C05000402008005FFF98720BBF88700BBF88700BBF88700BBF88700BBF88700BBF88700BBF80720BAF80720B9F80720B8F80720B7F80720B6F80720B5F80720B4F80720B3F80720B2F80720B1F80722B0F80722AFF80722AEF80722ADF80722ACF80722ABF80722AAF80722A9F80722A8F80722A7F80722A6F80722A5F80722A4F80722A3F80722A2F80722A1F80722A0F807229FF807229EF807229DF807229CF807229BF807229AF8072299F8072298F8072297F8072296F8072295F8072294F8072293F8072292F8072291F8072290F807228FF807228EF807228DF807228CF807228BF807228AF8072289F8072288F8072287F8072286F8072285F8072284F8072283F8072282F8072281F8072280F807227FF807227EF807227DF807227CF807227BF807227AF8072279F8072278F8072277F8072276F8072275F8072274F8072273F8072272F8072271F8072270F807226FF807226EF807226DF807226CF807226BF807226AF8072269F8072268F8072267F8072266F8072265F8072264F8072263F8072262F8072261F8072260F807225FF807225EF807225DF807225CF807225BF807225AF8072259F8072258F8072257F8072256F8072255F8072254F8072253F8072252F8072251F8072250F807224FF807224EF807224DF807224CF807224BF807224AF8072249F8072248F8072247F8072246F8072245F8072244F8072243F8072242F8072241F8072240F807223FF807223EF807223DF807223CF807223BF807223AF8072239F8072238F8072237F8072236F8072235F8072234F8072233F8072232F8072231F8072230F807222FF807222EF807222DF807222CF807222BF807222AF8072229F8072228F8072227F8072226F8072225F8072224F8072223F8072022F8072021F8072020F807201FF807201EF807201DF807201CF807201CF80700D7F8A700D7F8A700D7F8A700D7F8A700D7F8A700D7F8A700D8F82720D9F82720DAF82720DBF82720DCF82720DDF82720DEF82720DFF82720E0F82720E1F82720E2F82720E3F82720E4F82720E5F82720E6F82720E7F82720E8F82720E9F82720EAF82720EBF82720ECF82720EDF82720EEF82720EFF82720F0F82720F1F82720F2F82720F3F82720F4F82720F5F82720F6F82720F7F82720F8F82720F9F82720FAF82720FBF82720FCF82720FDF82720FEF82720FFF8272000F92720D7F8272000F8272001F8272002F8272003F8272004F8272005F8272006F8272007F8272008F8272009F827200AF827200BF827200CF827200DF827200EF827200FF8272010F8272011F8272012F8272013F8272014F8272015F8272015F8270000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A0008001003181C1003181C0300090000200430800000000405000E000C20FD00FFFF000000000002000005000E001020FD00FFFF00000000020500000300090004210430010000000403000900082104300100000004030009000C21043001000000040300090010210430010000000403000900142104300100000004030009001821043001000000040300090044210430010000000403000900482104300100000004030009004C210430010000000403000900502104300100000004030009005421043001000000040300090058210430010000000403000900C8200430040000000405000E001420FFFF00FF00000000000084000300090084210430010000000403000900882104300100000004030009008C210430010000000403000900902104300100000004030009009421043001000000040300090098210430000000000403000900A02104300000000004030009002021043007000000040300090060210430070000000415000800000000002028000018005201080005000A00FA001E00C80000009F003800000000000000000003FFFBF9FCFDFFFDFE00010000030101020605050605080A0609090608050403040305070709050403010202020202FF00FF00FBFDFFFF01FFFDFF010201FEFF01FEFC00FF01010000FFFF04030001FE0202030300FFFAFBFCFFFF02FF01FFFEFDFFFEFBF9F9FCFCFCF5F3F8F5F5F5F9FBFEFCFAF8FCF9F7F6F6F7FBF7F9F9F8F8F1F6F9FCFEFCFE00FBFEFCFCFCFBFDFBFCFAFCFA0102FEFEFCF7F4F4EDE1D701040304080B090909050608050300000100FFFFFEFDFDFCFF02FDFBFCFAFCFDFFFFFCFCFBFCFEFF00010B0907060306080706070808090B0D0E101515191B200100FFFFFEFDFDFC8080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 2368 2 0 0000 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 61440 61440 0 01FE305A070718006E6C6C706D6A6677777279706F6D75727170706B70727078746F747F75727274757A7D717C7B7E777672767681868A91918784868DB1D7FFFFFFD8B27D54413B3D486A8EB2E7FFE5985A3C3D557CBFE2D0A789603F282520363E302B313435362E33383B374344555055575B59595B5E5B5A606365635C60666C626A696666696B676C6B696B636870706A686C636E727676747877777970706B677061615F4A707A8D969196937A6C5B464248525D6F8894989A837E76707272747C8D84898C7E81788285868E8D8F6C8F9594898C918C847B85818783818D8B8A848A8A84878894989A837E767001FE315A07071810837770726D6C777B7C73716A6871757B7C747079737374727473787E7E7975747A7B73737F7580737076777A82878E8F9185827B91ABE0FFFFFFE1AF7A543E333C526891B6E5F7D8A55D3B314476BFE7CFAF907452351F25283B382D2C2D3030313A3E3D383D424B4D5D56585C605D5D5E56545960605F5D5D61646A6568666264686F716C5F67716E6B716A6F6D7E73797374777270727168615D695A5A5F4E747E87939694958C89654943444A5C7587919798867C716E6B72758387877C837E787B7C87858A9194708F918F8B888A88828986898E848A8D8F8B8D848A8E8D87919798867C716E01FE325A0707082085796F6D696C7575746E746B686B6D79746D6B7A6F73737571737A7E7F7979707274767F8581827B7772757E8787869497847C7381A1DEFFFFFFDEB3794D3E2F3F536D8BB6DEFEDE9F5A3E3C5681C7E7E1B9966947301D2131352E35332C2C2B2E3537393C3B3F4347585B5D4E56505F59505E5965615F6065565E68676A686C6B6F72706D676C6E6E726E7173717177716B6F727471706D6565656A68625A4B7279848C8E96938D8458503D404E61758A8F918E8A76756D646C817E8D8481867D7B7B827B8290969B71938F9388898A8487878A8D88878A8A8D8D8E8489878F8A8F918E8A76756D01FE335A0707083086777379707D727574777677727A737871746B686D6E6F6B747B818084807B7773787D798588827C766F777F88848D93A08D747580ADDCFFFFFFE1B078523C37384C6F94B8E4FFE5A050382F4688D6F0E3BC98724E2B1B222830302F2E25262A2E373A3B3A43454B4F4F4E545550505557555657615F605F5F64645F5F736C6B6363605C6A686C6D6C6C6C6E6E6B6E7072736F70707172636A646A6F6656594866808F9A939290867E644F434C595D678A959188877E716C6C6873717D848D877E7B787C818685878D65889391968E8F8D87888F8A88828C8D8B898A8B928C928A959188877E716C01FE345A070708407172696A666F6E71746F6D6A656F746F736C6B6F6970757A6D797476807D787F70777F84818286847B6C7A7B868D999D9A897E6F80A4DAFFFFFDD6A8774E31303C547B9BB8F0FBE09D5C3A314479D2FAF0C89B734C3118222D2F2B2F321F29242A2F323C3435434A45465357535B5A565654535E525B615A62666B67646D696A655C68686B636F687A75686D67647B76746C7374707A6E6C74696A646E5F5B4A778B949EA2A3978C8768533A3F555F7192939D9A86787871636F78818B9184927C7E787F84888F9197719391909290959688858A8C8E8D8B8F848C8E898A8D8D92939D9A8678787101FE355A07070850766A67706A687270706F6E6C656D67706E6D79746B66686E767D80808081797B79787B7D7D83817C7A72758B8E879096978A7E767EA9DAFFFFFFE0AC7B4A363131536893B7ECFFE19B543032568BE5FFF1C0A5804F3113252D31262435271D1D26293239363E3C3E46515051534C506356545A54525E575654575E625F616C6968676E696D686F74717C7871696C75685F677473727978676B6867696B645A4E5D7487A09AA09186755F56413C4E5C728D9D9F8E837D706A666A72858E958B828588737A80888C8D8F6A9397908E8D8B8F8B87888A8B8C8E8F878C8E8C8C90878D9D9F8E837D706A01FE365A070708608173676E6C6E75787B757B716C7979736F7A6F77736D767A74707B7A7A7B797976797E88898986837E757680899299999B847C7780A8E1FFFFF8D7A4704B3A313B5378A2B9E5FFE59F5E35344B8BD7FFF2CDAE80512F1B182F36353029252626342D27343D363C424251505751514A5B4D5458545D56575663635D6B59625F6A615E5E656C6A6871777A706B6568756F6F7273756F776F686964626361585C4A6C778D94939B92887666433235465A6B8995ACA3967A706D69656C78878B908D727578827E929B9C9972948E99949493898786908F8F8B8C8883809189838A878995ACA3967A706D01FE375A070708707B746B6C67736F78707A7768727D7A7370726E67756B757D7D7B777E797F737B7777818388918C7F776C757A83929A9E9E85766C809DDAFFFFFFE9AF77472B3435496291B1E0FFF2935B413C5794DDFFEFC9A181532A19223338332B2D221F1F202B303434353D3C3E4F484D4D544D5354514E5F60605253666E69626468625F66645F6D696F697471716B6A736C716B6B68716E7472756E6C72716461605C437A89969EAEA497968273533F454B57748B9AA29F8679726A6B6E6A838F998D8A8178787C7985959A97618A949793928E978D938F888F8B8D8E8F858C889593918B9AA29F8679726A01FE385A07070880706E6D6E6A70776B71676F6663746E6B73756E6C6D6F6F7579757C8A88817C7C6E6E838C98938D837369717F889C9DA69C89827B7DA6DBFFFFFFCFA77649312C38476894B0DCF2E0964D30305892E7FFFACFB4995F250B1D302D2E2D27221F2B2B2630322E32354148545258555A545C574E50515C5655534D61626B66626560676164686B6C726D6D666B675C686D807974726D797B7A6D6A66605F61545B4B697C9B939C9EA49780673F3436445771949BA292887D716975786E7B8E8A8A877673717C828E919FA163899D92978D8690908D988F93858B8C8C9193928F8C8A949BA292887D716901FE395A070708907A66616A726D7277776F6D6C60716A6F746F78747274797678797987847B7C786E7A8784949792867A75747C8C8C9695988B7E7B7CA1DCFFFFFFE2A06F48332B3C3E68A0B9EAFEE99E572A2C4E99ECFFF7CFBDA06430172333302F2426202128312D343A3933383535444A50474C50574E4B50575C51585B5B625E645E6B5D6C65595A6366666B6B69767B6D63686D6D74746A726F70706A6D6C6D72645E5951788893A8A5A0A398806650383F4B5874939BAE9F8F8A777961626E828C8C8E8A75827C78858E8898A063819898978F8D8F8C91969894918C8E8D8690908E8C8F939BAE9F8F8A777901FE3A5A070708A06B69586862666D6467626C6A656A726E6D73737570726E7675797C84877D807F787D7B8B97939789756C79808C979B9E9A887373769BD2FFFFFFD9A971423326314D67A1BBE9FFE79F542A2E508DDCFFFFDBBFA36830151B2A424035211916161E29272F2B323D424144494C52474C494848565357585A605962626968665F61605D5F5F62686D696E6F716B7070736D67677572756D6E6C686866685E695D47607A95A7ACA4AD9D836249363C47597590989F9C977A706760646C858D8D8D85736F7081848F9499956297949D9793949D96918E8C8C8A9695908F8C908A929390989F9C977A706701FE3B5A070708B072766F74756A6E6F75777671636A6E6D7273797680737576797B808B967D7F78757D8189908B96877C716E8A91949A9D9D8C776D7CA4D5FFFFFFCAA46F3A2D28364C6D92B9ECFFE59756302A4B8EE6FFFCE3C7AC663112162E4736342D1B201D2A2B29312D31403A3E3F3C474553545244414F4E58555D5A5D605D5660686060615D63636964686C7A74666D67676D73746E696F657276726E6F6C6F645B594A7B8992ABAEA4A39B865F422E454F597398A7ADA18A837E636269747E8C9388877775777B7E889A9BA267949795919190948F9592858D939094899094998C959398A7ADA18A837E6301FE3C5A070708C071726E72747173717C7970706D756C70757174756F6F74767778908B90908583797977899BA8A186796B757D8A9B9DA3918E79656F9ED2FFFFFEDAA6704425252C496492B9EEFFE59F5D34375490E3FCF8DECFB7813F14202C4438302F24151E22292130353336383A404D503F464247454C4F51524B554C575D5B5963625E6364696664616B72766E6E686C686971726F6C73716F6F686863686F66655D6345738BA9B6B8ADA08D7D7145373D435C7D9CB0B2A49380756B6662657B919B9B8D807771818A918F929668909A9B97919A9588979B8E958F9192959291968993909CB0B2A49380756B01FE3D5A070708D06B6D6C746A70706B72716465686F6C7276707874786F746E767E7A86857E82807F767F98ABA7A1947C746F7E9596A19A97826E747399D5FFFFFDD89F6E452A2A334A6794B8E5FCDFA1503A335394E0FFF8E9D3B2713919162A403E362E1A161D20212A34312D2D3740414B49404C4C48464C4C4D5A59595453545B5D565E5E6362666860716770736E75696A6264696E716B6E6F6D6D6C746E6C646467625D446C8493A9A5A59A948B6F4A3C3D3D577B93A7AE9E8D7C716A60636F78888E8F8875757676808D9CA2A85E919E98969C989A8C96998A998B918D8F97998C898A8F93A7AE9E8D7C716A01FE3E5A070708E06863676668666B7074736B71616E7373686E6B7575696673828587988F888179767A8393AAB5AD927A7374888F999996908979676B9BD9FFFFFFD5A96C3A2D1D294C668BAEEBFAF09F502D294490E7FFFFE6D3BA86421D213551443C332119191721272B2F222E35323B4344414A494B4B3D49484C5556524E515A59545C6C5C5960635E676F72747D7A785F6D69676E6F6B6B6F6A676F646870736E6559524275849AAAB3AFACA28B6C4F373E45597799A4AA9E918371626366757E91978B816D746A737C85919C9A5F96A09B94979C91949A9C9593899196958F938491998F99A4AA9E9183716201FE3F5A070708F06D71646C6C6D6C716A6D746F727C6B7A76787C736F6E716B7A808191998B7E837D838AA3B7B7AB9D846F6B7C969CA3A9957E6C5C6891D2FFFFF6D9A0653B24282E456B96BCF0FFE399582933448EEBFFEDDBD9CD813F141E354B4A463C25162021282E33212C2535313A363E3E444C51474A4A575B4A5354545356575A5F5F6868716A6268666A6B6C6B69686065736C78706F6B6E6F7473696D646E655B534B6382A4BBB7B3B6A5906A46393D4A6281A1B2B1A49A85796664626C7F939E93857468686F7C8592A19C5D94A4A3B39F9C9B9B9CA0939C8E999594918F868F979AA1B2B1A49A85796601FE405A0707080070716563696E6E6A6D6D6B6B6D6F70716E6E7B78767172737C7B8F969695838781798CABB6BCB09A7A626E738A959DA09B866E586E94DCFFFFF9CFA166412C1F2C375D86A9E7FEE49E4B272C5094E9FFF8E2D2D68D491B253E58544C351713221D232D3A2825252D3138363E3E3F424B454041494E4F505B575C5A6255626366616A6768666369736E6E69696A646A716F6B6E6B7071736C686E6B6B645D584A778C9BB4B9AFB1A894644A353541537098ABAFA8938477665D5B7084949390867D746A7A8795A29EA45F8C8A94939996989B979D9B958B97A197979289928C9598ABAFA89384776601FE415A07070810746A656E697578777267766E6D6C716C6D75717B76726D7D7B858D9AA2968D8B787988ABC3C3B59D7468707F90A09DA194856F656893CFFBFFF9CE976235212430436B92BBDEF5D6934D32395199E5FFFCEDE6DE98401D1F435F684A38171B1918261923232423292C2829383B3B42443E34404C5451514D535756666264605E5E6565586265676967706F6D6B6771726A70757074726B676A68605F5E5959477290A5AEA5B2AC9F9171472E313D5081AFADB19A9B857A6C6A6D6B85929492896F666A7985899C9FA1558799979C999B9997959A9C9992959A99929599989598AFADB19A9B857A6C01FE425A07070820706A7878776A7579797275706C736E77787874736975737D7B878C9CA897897C767C8DB4D8E0B69D79656672909A9DA3977F63566190CEFFFFFCCF9E613823162B44678FAFE6FBE99858342C5992E3FFF9DDD6C889411C2D526468543D1B161B232A282719271F2731313941403D3B30323C4347464749525859605B57685E585C595C606A66656772737169676D6A6F75767173786E6D736C635B60595D56456E87A2B0B8B5B5A79366463F3F405D7B9CAAB0A499776667606169899695917C716762717A959FACA65E8A9895939599969D9A9E979A8F979AAE9B97909395939CAAB0A49977666701FE435A07070830766F68666F6A74716A706D71666B747874787479776E707C848B9597A09A90837D8599C3E9EFD8A37A5E5D758E969A9C8879605A618CCAFFFFF5C598613B232227355A8BBBE5F8E99A4C29285295E7FFFCEAE2D38E3F2028577A75593A10060B202B2725212722252C3235352B403B45343A40404D544E4350495C5756675C5B585D64606665646E7675706A6A6C726A666E6D767973716F646B6C6B58585548748CA8A2BAC0BDAA96783E2437455C7D9BAEACAD977E756F6B656A889493907A665E5D757C96A1A0AC609790909694A0907F979B9E9D90929A9B999F9794979D9BAEACAD977E756F01FE445A0707084077716B756C6C6B6C6B6B6B716A707B7D77868B867E706975768B93A3B6AE907C7E7DA2CDF0FFECAD7960546A8E959B9781755A4A5481C3FBFBE7C38E5E33231A27396287BDE6F7DDA34D2A264C99E9FFF6E3E8D893401936668E7F6B3B190E1B2C261F2022251D232C2F2A2C3E443841393A413F40444E514D4F52595C595D5B5F6360656A6C65676B767071656B736F665E6E76796B6B6E6A6963545C5C55477597ACBBC2C2B7A096774A32314451779FB1BBA29482756F646C778A9694957D6560636D7D8DA0A7A65F8B909E90969BA09D979F9B9B908A9E999A8F8E9E9B909FB1BBA29482756F01FE455A070708506F726C64606E6C6F75717372636C7277757C7C787870767976889EA9B4AA9F8D7C829DCEFEFFE4AD775552758D879192906B504C567EC3F6FFEFCE9D64321F1D193C618CBBEBFFEA9B4D201F4691E4FFFAE8DDCC913F1C35678A957549190B1F2B2F2A2D191E1E1B242A3131302F3B342D38303D404C4E44494B5659555D5F5A555D5D676A60646A717471675E606C73716B6F6C66716E616567626D635F5B4E7E96AABBC8BBBBB1A377502F353E4F7D9DB6C2B49E81756C695C718699928C7B725F646C82848CA4A45E8E8F97929CA1A49A989596A1969698969D9C95949D9C9DB6C2B49E81756C01FE465A070708606E68646C6A6B6D708075726A6A69707373777A7E787B7B7B7C8699B0BBB39889757E9FD9FFFFE3A86E54526D7F9495958C6F644F5682BFF7FFEBC7926235171121315981B4EAF6E5964E272B4E8EE3FFFFEAEED18E3B1E3468969F8E5B250B142B34281E131A1615181F2E30323638352A28404C484240454D4C56544F5758584E565D605E64646A7474706B63656E6C6D716B6E75756F68655D6663625F5A4F7C97AECCCEC8BCB79D7341343A3C567BACBBBFB0977F7D645F617A86979A93814E528D79829299A4A3578B9095939EA4A1A098A99595989A99989F9B9794919FACBBBFB0977F7D6401FE475A0707087077716E6C71757A69706870737777737A78757574756F73737D92A0B2B9BBA08B7A8096D7FFFFEDAD78534C6C848F90988A69584C577CC2F4FFE8C69363381B101C366685ABEAFFE1914528354F89DFFFF1E9E4D59B4721376B9AAC945D250D2132432B201910060B151824292B332D3635353F514C3E42423D464C5B575F60605C575B66665E676E6C6C656A6B6C776D6F6A706E676A6A6E615E5E5B645E5E437C97B7BCC0B7B0A69B6C472F353E527EA7BCC1B59683796B5E627987979A8F9B6F60576780949A9CA160969E99999EA59CA3A59E989B96959A9599959A9D969FA7BCC1B59683796B01FE485A070708807A736D6E736C78777F75786F6D68707A7C78787F82797077868AA5BED0B99F88727CA1E0FFFFE8AD7350536A8E90978E806C5548567DC4FFFFF1BF8A552A1915213B5E88B0E4EFDC9E4B202E5193D7FFF6E5DBD79C4C283872B3B99F5F1C0A1C2D38281C080F1E161521222F372F2C34262C363A43433A424751465151555E626064565364656A72676D67606560676D696463677B7277706469615E645E614B6D86A6C5C4C3BDB0A27544262E3E53789FBBB7ACA78A7A725D617D92BAA6968164545B688097A6A3AE51899A9E899298A2A6A7A1A29897999D9B919E9A9B94929FBBB7ACA78A7A7201FE495A070708906D73676A676964656F7476746C706E79787875797F77787A7C8F9CB6CBC7A8847C7CAAE5FFFFF4B57244526791909996857051464D7DBAFBFFF0CAA2602E1E1614265186A6D5ECE1963F25294A98E5FFF0DFE3DA9C4D2D3B7CBFD0A86622071C3B4A32261814100E12161C1C1D2B2A2C232E313C424447464548474D515253545B555A565C5F6465666968655A68696D6B6D6D70727672716F6F6C65615A5651728BB1BEC0C0B1A3925D41293035587EA1BFBEB294777581655D677E959692825A53636F6F8CA4A6A0598E9A97969A9FACA39EA2A6A5A1A1989B979B9F93929DA1BFBEB29477758101FE4A5A070708A07C706F6D72737A7A706E7373777472717984807F7C73707D7A929FBDD0C6A1937581ADEEFFFFF9B0674D4A6A88928A8D82684F4A547DBEF8FFEEBE94652D140F213D5E7CA9ECFBE49444222B4B8DE2FFE9E5D7D6944324366EBBD8BA762506294249301D121A0D0E0E1728312728252C272736403E453B4048484F4C48535157555C5D5D5E6469645F67655D64686D6E6762717373716C6D69636F6C665D5C507B9FB4C4CFCFC3B09F77423031334D878DAEC7AC9D8B7A715D5A6587979B907F5E535C647A8FA1AAA8619099999BA6B0AC9FA7A49E9398979EA599A3A39D9C9F8DAEC7AC9D8B7A7101FE4B5A070708B07A6F6D7067676F71757377736F6C73727E7F8581807372758496AAC7D4D2AE8D757AA0DDFFFFF3B16D474E6176888E8A78634F3F5081C3F0FEE1BF935A35151622405F7AB0E4FBDF9D4F2B2D478CD4FFEFEAE0DD964C233775B3C3C2732A12254E59371C120E040610181B1C1F1A28333135373C40443B3E434F4B514B50525F5C51525C65665F6261736A6D645E626A746C707172686A707367625D615C5D4B829FBFC3D3CACAB59665452C31365084B0CAD1B5A48B7A6A5C657284A3A39A8465555D647C96A9AAAF5689909D9497A1A5A7A29EA59A9E9AA5A59B9E999C9FA3B0CAD1B5A48B7A6A01FE4C5A070708C073776A72696E6E7976787372676D757E7A79827C7B7580798097AECCE4D0AE867A83A4DAFFFFF5AB69414760767F8E8F7E7049394776B2FBFFE5C89C592B160D1A345383B5E1FFE590451E264B8DE9FFF6E1E5D4984723326EBFD3C67A2F131E515A3B291414070C0F1410211D24272E2A2F3236423F443F484F444F4B45584F585B5C5E6156646966665B675F677776686C6C71787D6B6C656A5D655E535A4887AADBE7EAE1D6C6A9805430473E5F8BACC6C2B1A1927672696E6F869598937E5E5857657992A7B3AC5597A29F959BA5A2A2A1A5A3A19AA0A3A2A29F93909B9BACC6C2B1A192767201FE4D5A070708D0736E6B74706A77726E6F6D6F6E78707581857B78766A737A828FA9CDE2DEBC9079789DE2FFFFF5A76A474A6386898B8883694A3C5073B5F1FFE8CB8D5C34170828375D89AFE2F9DD9142281F4F8BF1FFF6E6E1D6954A283B7BC3CBCF812E092E65673E1E1911090005101C1E1F24222426202834353C3C42424A414B505451554D5459625B605A64676D6F63615E6E70696A626D72706E7D6D63635F5E5753488299B3CCD0D3BEB8A1773F292832507EA8BAC0B19C856E6661656E889CA09274635352607B8BA2A8B0639091A0979EA5A1A1A4A49AA69FA29C9C99A09B9F989CA8BAC0B19C856E6601FE4E5A070708E07B6D757972737478746A6E786F6F7476717D7D7A7374777B839DB3D0F1F0BF947D80AAEBFFFFEBA768404A61768E878C7F6257455080BFF6F8DDC0854E29110A12355B90ACDEFBEBA24825234391E0FEFAE6E2DC9A492B457CBBD2C5802B18386E71432D1D0E0400060E16181F221C2426252C30383D3936434B465251524F56555250555F5A5E646D7168675D5B60636B656E727171656D646865625C5453477BA3CCD7D3C8CEB99E753F272336517EAEC7C6B89C8F7969585F6B849D9A937B56525863828DA1ACAE6091969B95A0AAADAAA8A1ABA6A0A3A39997A0989B9CA1AEC7C6B89C8F796901FE4F5A070708F0776F6C70756A74797877777974798A7E7D7B78847F70777D8396B3CFF1ECB48D747AA2DEFFFFF1A45C424561818F95967F614B3B4B79C3EBF7E1C291582C101020355788ADE0F1E3964824264790E1FFF6F1E8DE994D1F3A81C3DFC87A331B3F7E8D481D13130200000D0E14171B1A222A2628323732323E37424050474F55564A4D5A625F5F5E6365716362636371706E726E686F6E6968646967655C5B5D4D7996B9DBD7C7C8B9A16F41222D3F5B7EABB3BBB39A807F66635D668296A68F7E524B5B637492A9B1AD5B8F8F9595A0A8AEA7A2A5A0A39B9DA49E989EA29D9EA2ABB3BBB39A807F6601FE505A070708006F615C6B666A6E6D7775746B6B6D6B7D79808280807A6B798A9DBBD8FBDFB9897079A1E0FFFFF1AD683E42658A9194947F5C412E416EBBF1F9E2B38C5B2A130E1F3F5B90ABDAF0E698431F224E99EFFFFBEAE4D8933B1E3C7FCBE4CE802E133A7B814C2C1D0C030000000D171B2222202029212D31353A3B443F45404C52584E4F55585D5F5664616B766B6260636E6B6B6C606B666E6E62676662615D61554F6D85B0C9CBCFC8C1A6743F2021254B77AABABBAA99856F6861636B86A2AA8E70534951657894A0AFAD5391989C9998A5ACA8A5A0A6A997A1A4A39BA2999DA29EAABABBAA99856F6801FE515A070708107062686B696E7D72776A716F697B786B7B76858179776F6D7A98BAE5FEF1BF8D7278A3DEFFFFEE9D643F4A627A7D8D91796B4B3A4377BAF0F6DEC39566331A1021395E89AEDBF2DB903F22224997EAFFFAF2E4D4963A284074BEDFD278301F43888550301A10020003140E15171F1E262621282A3633363E3E3F3A464350564E5251545A5D6061606867666261606F6B6D706D716A6F6965666A675B5A5956457993B9CBD1CEC9C09F783C1F2C2E4E7DAFC8C3B9A58074715A5D5B8297A69A704E48425E748EA0B3A552929294969DA8AEAFA9A798A4A09CA9A4A2A6A39FA6A1AFC8C3B9A580747101FE525A0707082070645F6263667C707773746B6E75787F8279847F897D77808498B0D9F8F0BD8F6E739ADFFFFFEE995D4542607E908682755E4C3B407BB7E9FDE4CF9F5A2A130E18395988A6DDEFD1974827234590E4FFFEDBDFD49C47274189C5DFD5782F1B3E82854D2F1B0D010006010B141519161E1718262E3434393D424A4B4E484B454C4D52535A595D64646970696A6669686866636E706B6F6D7369636368695E5C46829EC8DDE0D1D2BFA1723E2426384C80B9C6CDBCA48773656155607EA1AA906F534B58636B84B8B3A159929D9D9BA0ABAFAAA49EA3A29EA2A6A1A2A8A8A19EA2B9C6CDBCA487736501FE535A0707083073676D72676A71787A727B79786B6C7C76818B8A8A7A697388A2C0EEFFF8BC8E6E739ADEFFFFEAA0674245657A8B898D7D65473B4170AFDBF6DCC48C53300D15203A5C8CAAD8F5E3A14223294F99E3FFF9ECEADB9E43233E82C1D5C2803213438B905125160E0500000319161E271E1A1B1E272F2F353D313D3F3B404D585A4A4E4C5D575B595C626C695E635F696D6C6B6A6869706A73706A626B656460593C7999C3DED7CBC5B3AD784219292E4481ABBCC8AF9D8879615F5E6B879E9C887A57525154638AA2B1B45C8F92929AA1AFB3ADA6AAA1A6989EA4A7A49C999A9BA3ABBCC8AF9D88796101FE545A07070840766F6C72707375766D6D7C726D79727A7F85867E817A747B819FC2EFFFF4C189727BA5F0FFFFE8A75D46416184918C847E5747363E6EB9E5F5E2C38D59230E0C12385085AFD6EFD68C4821234C95E3FFF9EAEBE19D4B27347DC6E3CD822B16418F9457352815020000020910191829281C201F2D343332353A464F514E5557524F4B4D515D5A615F5F625C606567686B6E6A6D72726D62626C6566625D5A5A4988B1C3C5D2DAD0C7A07F512E2A2A5480ADC4CEC1A381756B5A54598AA0A3967F5C434859708BA0B0AA558E8B8C83979AA6B4BAB3A8AE9A9CA1A4A3AAA3A7A2A4ADC4CEC1A381756B01FE555A07070850726B6E6F7174747A7571707169727E797989908B7D7A7D8388A3CEEDFFF4C5897078A4E8FFFFF39C5B373E5C798C8790715A433F4376B1ECF6DEBE9857220F1A183D6085ADDCEED89C471A254988E9FFF7E0E0D99D4B18337ECAE5CF843A1D468F8C502B1B0B0101000512181A1D2321111D1A24312F3936433E494A4A55555A535451545858595E5E645E685C616A7372696964687574786F6C665D5A5D5A436D8FB5D3D3CCCBC2A774442C1B314267AEBFC5B7A586686162566484999F90734A434D5C718DA7B2AD6094A39C959FA9A8AAADADA7A19AA3A7A0A7A9A1A79E9DAEBFC5B7A586686101FE565A07070860757A77716E747F787275727A6F74717983807F8D8075767686A0C8F4FFFFC3866D7297E4FFFFE7AC6243415D758898937D6144414A70ABE3FBE6C69952281007122D568AABDAF0D497431E264C8DDFFFF9E8EDE5A050213E81C2E5D2842B133D80904F2E191702000306091C1918221D1A1B2322333638403D46474B50504B4C4E4F524F585B616161675E6664676B71747169726B6D70666B5E616354595A4A7298C6D7DAD3CCBEA47749252843587EA2BAC0B5A4877260565166879BA58D734C4246526C97AAB5A15DA89897949EAEB2B2B5AAA3A79EA4A5A2A9ACA1A798A5A2BAC0B5A487726001FE575A07070870786E6F7872767E787D7683797674717E7D828A89898379848EA1CAF6FFFFBD916D6B9AECFFFFE3A75A3C39598191958773564A363B75BCEDF2DCBC8E4B190F050A2B5488AFE6EFD29A4216264E96E4F9F1E6EADC984D214185CFE5C380351F409A985028251F10000007061611151917201F24272C333130393D424B4847484C55565A5E5E6264626A69616166626C6D7068686C6A6C6B6564685F65635C5343708DBFD5D9D9C5BCA77749313231476BA1CBBCB79C887F6A6562607EA3A498674747465C6994AFB7A4569191989E9CABAFAEACAFA5A09DA7AAA29D9BA7A5A9A7A1CBBCB79C887F6A01FE585A070708807C786D7472777B8177736F6F6D738181888A918A7A79788482A4C5F1FFFFC48E6A6C9FE7FFFFEDA96C3B415F838D8E8F785E4A373B75BAEBE7DABB925A30130A17375785B4DFF3E5984D24244790D7F2F4EAE7DA973E2C438FC1DECB7B2F1442879358392723110500000A1B14201B2119161A242F333130353339424349505454494D58575B625E696965646069616D6F6871716874797465646367645C5547799CC2E1E5D5CFC4A4724F211C2C5191B6C1C6B2A1857A7065545F7B9D9B757A574744586F85A6B4B261919CA29B9AA6B3ABABA8A8ABAAA2A2A8A1ADAAA99FA3B6C1C6B2A1857A7001FE595A070708907E79696D706A7070747670746D77787E80888D90877578848B99B7EEFFFFCC8061729DE6FFFFE09F5B4341627B868D88736647303F77B6E4F1D7B59559240B041437608AAEE0FAD7914324254690DBFFF5EBE6E09D42254190C4DCC480352247858C5337302B100000060E17121E1A251D18181F232E2D34344348504B4D594C494F5652524C5E656168685D66606A716E68646B67686D6B6F606365625F5A4E8EA6BFD2E2DCDCC6AB78492328314D69AECDC6B4A4847B6B574E5886A4A49475424143596C95B2B5AD678E8E9F93A3ADB9B6B7A5A5A59BA2A8A6A8A2A3A2A0ADAECDC6B4A4847B6B01FE5A5A070708A075776F686E767C7375697F78716E7775848C8D8C8B7F7A7E8BA6D5FDFFFFC98E6476A2E6FFFFDD9E55353C5E777F8789786846344276B6EFF7DEB49353280B090F315B92B3DCF0DF9B4C2B22458FE7FFF6DDD6D39141293E79CAE6D385301C478D90553A3836130100000A1A1B1A151D201C121C2C312D2E403F394847475251495255595C596565616861625D5B666666646973716E6A636E62645D6060574C79A1C5CFDADAC4C19D663C3F2B305084A9C7CCB7A0806F55565D6387AA9C836E4F413752658BA8B7B05D91979793A4AFB0AFAAA5A8A89C9EA6A1A1AFADAB9AA6A9C7CCB7A0806F5501FE5B5A070708B06F687073706B7876807976727277728587899790897E787E8EA3CBFFFFFFCE8762689CE6FFFFE3A0533A4E5C6F80858076553C39437BBAF8FADEBE9A5A2D180E0E234B83ADD3EFDBA15118254196E9FAF8E7DFE29641273B82C6E1D987360B40818F4D413529120902050D120F1A17231F1829262C2F36322F38405047494B504D4D46525D5D5C5A6464595E5765636E6C7270686E686C6F6567686C6D6153477F9FCBD9E4E0D3C9B5784621242F4D90BAC9D3C69F816D6558546183A4A9946C4D40434F6B91B0B4B7618A898C95A7ABB3B5AFA9AAA8A8A9A8A39BA39EA3A8A2BAC9D3C69F816D6501FE5C5A070708C0757A6F726D6B7B776F7379717274777E85929394887D7B77839FCBFFFFFFBE92647798E2FFFFE2A36039315C7086878A715C4439456FB3F7FFE7BD8E54270A070E2E5389AED9F0E3994922215189DBFEF3E7E6D39E45183983CBDDCE833514438E995A443D3D1F070000040D0C151F1D1617252228292D313B3E3B48494B49454D4A535B585A546062635E5D666B686F6A666B6D717671716B6561685F5A5749729BBDDDE6DED0BAA17B4421112C4488ABC4D1BD9E7579695C61618B9FA7926C483B404D698DABB5B15C8E9C9C989DAAB2AFABACA6A09CA0A6A19DA3A8ABA6A8ABC4D1BD9E75796901FE5D5A070708D0787170736E6E6E72727881727371787F7F8C8F8F887B7A7C8CA7D2FDFFFFCC8C626B9CE5FFFFE6A35D3B3A5B8199938F796039333E78B4E7F2E8C391531D0E0A1734618DA8D6ECDE8F430F1F4C91E0F8F9E2DBE5A646243280C6DAC7823316419199594D3F2E0F0300000E1214191C1E1B1B1A251F202E363A3D46483F505450514F5352555B55605F6462605B5E6868686467666C6E6571636A6F5F5A5B50507AA0D6E3E9E5D4C2A982462524374985BBD0C3B19F89715A565C678EA1AA98763C24384B6E8AA7B5B15E97978E989AA8C0B9B7B1A5A8A3A3ACB5B3ACACA6A5A8BBD0C3B19F89715A01FE5E5A070708E06F76766F72737678858475776D796F798294A8A38B7E7D7F8EA7CAF7FFFFCF8A5A669DDBFFFFE2A15A394058808F928B714B413A3C70B8E5FAD9C7985E26110B13275B87A6DEEFE78D401C204A8BE5FAEEE6E1E5A146244082C5E4CB7F301C4C8C935A4148412304030005131012141E18161D222828343434364C4A4549504E4851544E4E5A5D6965676465615C66666867696D706E6C726460575859595347769CCCE0DFD8CBC3B17D46232A2B4B7FB1C4C5BDA3867466515B617E9CA4967440343D4A5F8FAAB2B1618895989D9FB1A7ADB5B6A8A2A0AAAFA6A8ADACA0A7AAB1C4C5BDA386746601FE5F5A070708F0846D70677173757A737A867B73787B7E8D90989B8C7C817B84A4CEFFFFFFD3885E6297D9FFFFEF9E543A3B60788B938B7B573A2E4072A7E6F4E3B98A542D1007183A608DACD9E6DB8F472B275091DBF9EBE4E0DA94441E3A7BC8E2D290301A50999C57414B411D0000000F1717171D121C13292A2726242B36383D4545534F4D444751555A5D655D5C6169685962646D74736C766B686E62615F5C615E5C5740769BC5D6E2E8DAC4A471442B2E314A7FBAD1D3C0A38267655C5E6189A3A493663E353A455F8DA1A5AD679B98969CA4ACADB6B4ACB2B0ABA5A4A3ABAFA2A2A5A6BAD1D3C0A382676501FE605A070708006A746E746771747A747174705E72737B838D9890897D74798DA2D0FFFFFFCA8669669ADFFFFFE19D5433345A7A8A8E8D735B41313B79B5EEFBDBB48950240E0310365884AFDFF2D38E4120274B8BDEFBF4DDE1D79D47243885C9E4D08335284791935B4A4F4020000000030C171D1D2219131A2A332F2B2F373B3E3C3F47494E4E4D4F4C52555B57626B645E6160666C666E6A6968686E6C65605D605E5D65456CAEE6EBEEE8E9C9A47B331E252F3A82B7CCD8C0A082706263587182A1A79A6C402631456E93AFB8AC5B91A08492A3B5B1AEBAACA7A7A5A8ADB0ABB5A8AAB0A8B7CCD8C0A082706201FE615A070708107A6D6A716F727C807A7B7A7A7A8187898692969A8E8380808CA8D3FFFFFFD17B5D6599E8FFFEEAA25D37305E7785958875533C283B76BBE8EFDEC28E5D1E0A101D37588CACD4EBDB9744211B4194ECFEF5E4E1DD963F223F8CD3E4D5843215458F995C4A5D542A02000001081319171B0E0A151A31373227373F3B43474B544847555357584E565C5A65616C5C59637261605E686C666E74685F655E5F665443739ACDE0E0D7D8BEA16B401C24314777BACCD3B6A2856C67615B5F849FA3896F4236334B6C95B6BDB76094999193A6BCB4AAA88FA4A3A0A5AFAEAABBB0A3A2ACBACCD3B6A2856C6701FE625A07070820767474736E6F757D807E85766C6971828F98A3A4997E7D778FA6D5FFFFFFCF83635D86D6FFFFE9A85A3037547C928C8A785C3A304069BCEDEFDCBE8F522409060E326090B3DBEBD78F3E1B1E4C92E5FFF2E9E7E2A64722367EC9E1D28730214597995C4B654F160A000107130E1C181C1819191B2A1C22303535373A414C4D4F4D4852544F575356635E60585A636A6A60626A68646D6C655E5C576164656147658ECBDBE3DED8C7A87C3E202131497BAAC4D2C6A3836E5956505E87ACA68C66352C324A668DB0B6BB65928D8C8DA5A6B9AEB1A5B0ABA6A5ABABACA2A6A0A3A8AAC4D2C6A3836E5901FE635A070708306D66696869716F73807B7474757E7B7989969D9E8F7C74718BABD3FFFFFFC3886A6B93E3FFFFF09D50322F4E758E8A8D7D5B41293E6EB6EDF1DCC18F5D2611080F2F5D8FAFDCF1E394462224488DD8F2F5DDE0CF9B4A253980C4E4D3842C1C4A8B895F596B59360000010C131212141B1511161124312923303D3A4341425350504D504E4E51605F5D63626459606568656268686C6F746F5C6562625C5D524071A3CCEAE2E7D0CCA975371C292F5184B5D3C8B99E8175665858637F9FA392663530263E6294BAB7AF5F8D888D94A3B9B9BCB3A8B1A99BA2A9A2A3A9ABACAAA5B5D3C8B99E81756601FE645A070708407B787B7C817F7E83807D808072797685869EA4A89582777989A2D0FFFFFFC687656D93D5FFFFE59B503135557B8B8E8B765436354071B2F0F1DDBA885228110E15385B89ABD6E1DB8D451827478EE5FFF0E2DCDBA04D2E4080C6D8D17D2D144E95965852695D2909000005121015191B1712161C23252A2734303E383B404A464D4B4B4A525359666E6B5C5C5B696A696B626D7268656F67646D65604F5750447BA0C8DBE9E5E6C6B37B3B211823528FBDCCDBC29F8273685D5763809BA88F6F453436456C8AB0BFA65788989894A7AEB4B2AFB6B2AFA4A3AFB4AEADA6A4A6B0BDCCDBC29F82736801FE655A070708507E7073786B69708780756E6B5F6C78808793A4A08E7E767A91A4D2FFFFFFC88E666692DBFFFFEAA658352D5170888C8676574236466DB7EFF5D6B98655260A040B2A6484ABDCE3D9963F1F27488FE3FBF2EAE4DB9E472F418EC8E2D09031174F959365546A5C2F020000000B1D14120F0E0D111C232B292F2F3E3D41424F49424946484B4D555D61616C625E5B5E5B67656E6C726769666564636A6256575749769FD3EBE7E3DAC4AF703E132632547EAFCBCDC09C907A6C5B4E5B859AA1926337252B426389B2BBB15C91898898A7B8B3BCB9ADA5A7A8A9B4A7A7AEB2A0AAACAFCBCDC09C907A6C01FE665A07070860737A6A70666C7B8073737C8077787E8B859D9BA28E777E7D88A6D7FEFFFFCE7C536494E3FFFFE29D53333F527581818779513729416FBAE0F1E3BD965D260D080E275B81B2DCF1D38F461E27458DD9F8F8E3DEDE9E4F253A85D2E7D5893521509B966159685A2D060000000A171E1B141110141E242B25252A30393B414944434C474D565E595D635D5E66605A63666B6872706969626E67686A685F5C5D54406D9CCAE6E7EDE7CBA96E351C252D4E87C0CFCCB6AA897364534F5483A4A08E6B3A363A455F8AB7B7B0628C918E93A3B6BDB8B7A8A4A7A2A8ACA6A7AAACACA8AEC0CFCCB6AA89736401FE675A0707087074716773657180817E75827974717B81829D9BA5967D7B7684ADDAFFFFFFD07F616295DFFFFFDDA35A34325B74868E86715B40353875B9EBEED6B696592710040B2E5685B3DDEBD98F461A214385E2FCFDE9E0DD983B1B397DCAEDDB8D361A4C9694595E716E2F0B00000812151B16201312161A241F23262F312D3D393B4A474D4F4D534C4E585D62606060586268766B686E70666C6C616960646A575A5745719ACAE1D9DCE1CFB27E3D1F32334C7FADC9D2B79D82736253595582A7AE96753F262C395D86AFC4BA5C898F9194A3B0C3B9C0A9A2ACA1A5A4A39EAFAFB5A7AEADC9D2B79D82736201FE685A070708806F747072686D6E6F7C7B79776E747D7D869CA7A8957E737689A2CEFFFFFFCE855F688DE0FFFFE396502D33507A8F918972593E2B3068A9EAFCDFC08F602B0C000E2F5F8AAED9ECDA95472524478EE6FFF5DDD9D3994B284688C0D7D3842E114B9596645876673807000003131925141A0E0A0F2024222C2F2E31363D3C44474D49484D4C5B565D62666267695B6B68726E61615E606967655A625F63665E593B7598D1E8F3F0E6D5A67B401829304985BDD7D4C2A2886C654B47517FACAB9D6D3B28263E6391AFBCB25E928B8892A3B3BDBEB4AFAAAEAFB7B2B2ABABABA8A5A3BDD7D4C2A2886C6501FE695A07070890806B68666E71707786837C746C7A8282889AA9A38C7D716E84A9DFFFFFFFC5765B5F95DCFFFFE39953343A5B7D8D8C887B534132396FAFE0F3D5BB93571A000715356485A0D3ECE29A451C1C3E89E4F9EFE1DCDDA042244589D1E4DB912C144994985E5A7975320B00000519211D111204070715211F2127303532353E4D47483E495453555C545A655F5F5C566067636862687A6F6A7566675F6564635A523E63A6E3F7EAEDE5CEB6843D1926394487B4CED4C0A0726E6456545F87A3998667332E2D42629EB1C4B65F92968E98A1B9C4BDB8AEA6A79FA0B5ACAAAFA9ABB3B2B4CED4C0A0726E6401FE6A5A070708A07B777874707483838A7E867F7B82787E93A6B1AF928878718AA6DAFFFFFFC67D526792D5FFFFF0A85630395A7A8F8F8B714B33293E64A4E8F0DBBD8F4F280802132E5C92B0DEE9DE9642181B478FE1FFF0E3D6DC9B4324388ACFE0C7792A154C929D5F5A81773C0D000008161E1F1E120B0F0B16132028263031393E444E44433E48435057515759666461656864697269666A68646761635E635D5F5B5358467BB3D6EBF8ECE6D4BA833F192337518AB6CECBBCA281685D57505088A0A9916F4331373F5D82AEBDB76092968E98A1B2BBADB1AEAAA8A5A8AFA5AFB4AEB0ABADB6CECBBCA281685D01FE6B5A070708B074666A727372736D75748575737A798191AAAE9E8C716A788BABE0FFFFFFD28D564E93DBFFFFE697582D2E5482918A8C7D54342B336BAEE9F1E2BF8D54220A000E315D86AAD1E8D58F461F214995E2F7ECE2DBDE9B44243D89C3DCD68F341E5296925D5E7E73360000000F1A221B1E1609071214211B22272D3433433E444E454C4946514F4D5E626562615B5D5A5F6B6A696E6E696D6F65625D5F635F5052446A96CAE1DED6D5C1A679381C30234381C9CFDCC5A6807161494C567EA6B09D733A2529395886B3C3B6618B8F9398A3B7BFBBB1AAB6AFA7A6A5ACACB1ADABB2AAC9CFDCC5A680716101FE6C5A070708C07B726C766B6E7C75787C807D787B7E8B8CA7B3A695847B7380A8D9FFFFFFCA7D5C5E8ED6FFFEEAA6512E2B548693928E774D2F233E71AAE5F5E3BC9556250C050930638CA4DEF3D88F3621224891E4FBFBE1EAD1943E253E87C1DBD78B371B4C8D8C5C5C867037080000091A13241A18100C1319171F1D272E38353E4646484A4F4946484C504F5A61655F635B5A686C636667665D5F685F69635D5D6054554874A9E6F7F9ECE6D1AA7730211F1F497CB2CBDAD0A4796D604E4D5D89A8A38F62371C1F275A97B8BFBA5B919691919FB6BFC2B5AFA9B2ABABB1AEADB3AEADACACB2CBDAD0A4796D6001FE6D5A070708D073747C7A7977787F8481827C7F7E7B878EA3B6B5A2817C6F88AAE2FFFFFFCC7D535685DAFFFADD9D632C39577C818E866F553C2C3D6DAEE8F6E4B98F561D080B172A5984AEE6EBDB8D4517224992E5F9F3E2DCD99942254487CAE1DB913B1E4890956860837A3D070000041C151B1A130E0E151819242621282E383F414A4D43454C4C505155575759655D625D5E6666666160676B686D636B666363625E4F387CABD6F3EBF3EFD1B9833B1E27313D7FC3DAD6C9C1836F6454475882A1A29364322C26385C8BB7C0C262898D8C93ABAEC3BCBAB4B3ACABA5ABAFAAB3B1ACAFBDC3DAD6C9C1836F6401FE6E5A070708E077716B71727476757E7B7B79776C76919BB1BDBB9E84696F85A9D9FFFFFFC87C5C5D84D2FFFFE39D5B2A2E5A7E869993734936282F66B5E6EFD3B99451230D041237628FADDAE6D78E481A1B3A84D8F6EDE0DEE1993E243E82CBE1CE87351B4493906A6287813C0500011323211D1A1617140D171A1E2728302C31333A39454047484B4E58505A605E6761645B605E6969656B6967666F6B5D685E635B52503D72A8DAF1E4E3D5CFB17C3C0F1E2E4C83BBCED2C2A6816B6250445981A2B0A06E3C251F3E5688B0C2BC588A908C91A5B6C6C8B9B6BAA6A4A4AEAFA8AEB1A7A8ABBBCED2C2A6816B6201FE6F5A070708F0777172736E7578778880817A7171828E96AECBBEA08372737EB0DDFFFFFFC17B575B8AD9FFFED8A14E2532527A8A969276523B203168ADECEBCFBD935B1C09020E366087A9D9E8CF8C3E161D448AD8FAF7E4E7DD944221418AD0E4D6902C19569F9A5A597F7C44070000101C1F1C1B1A07060E13191D1D283434323934443E3E3E4A4F535153575A5F69605F596664645C67685F65706F63626862676259584C70A8D1EDE5E0F0D0B0763D1E2A2E4C83B3CDD8C6A17D655A4E4D567198A4996F4133283E6294B3BBBA5E8B969394A9B6BCBCB0ACA1A8A1A7B3B1B7B2B0AFAFAAB3CDD8C6A17D655A01FE705A070708006E6E6977716E73777D7B817A7D7E7B8D98B8C2C1A57C706F83A6D8FFFFFFC17F54558ED2FAFDE099552C3356848C928876543A2E316EABE4EDDBBD935B1F07010D2E5B8EAAE5F3D48A3B1818458CD0FBF4E4E0DCA64D263F84D5E5CF812E2150919B5B55837E440800000A20282923170C070A15181D2327383131383E42474643454C4E5A585656535F56575D61666A696C6265676A786E605B5F6B6055504282AFD1EFEDE2D4C7AC743D2824384D84B2D5DCC6A18568634F4452769A969A6F3B1F26425B89B7C4AB5E9298888EA2B3B3C1B8B4ACB4A5ADACADACAFA8ABA7B3B2D5DCC6A185686301FE715A070708107070746A6A6C68707C7C807A6C79728991B4CCC29D76676F829FDAFFFFFFC17155548ADFFFF2D0A35F3E355E7D858A826955302F2B67B2EBF0DDB7894A1300000C2E589BB0DBF1DE964216254F9BDAF3F1E8DFD59D45224683C8E4D189331B4C899863677F7D3D0B000515202220181A05070F0E18171C282C33353C3B38424B495157484B53574F5B605C62655E5F61535D6C6A676D626664645E535A5755446A94CADFEBEAE1C9B0763E1E1D324E7FBECBC2BB928A775D514C51809EA89872422A1A2B5686ACBEBA5D8F8E8F91A9BAC6C7BBAEADACA8A7AFB2B3B8B3B3ACAABECBC2BB928A775D01FE725A0707082071756D6A686E7A7F88867C7D737E77869CBAD0CBA37C6D6D82B0E0FFFFFFBD7B504F7FCCFFFFE0934D2E354F7A8995987753352C2D66AFE0E5D5BB925C220B000F31598DB0DDF1D7863B17223B91D7F7F9E3E4D99C3A1A3D92C7DACB872F1D5C9B9D5A5C7C773D1000000A201F1E201E13111309102622272B30373E3D4140404049494A50525B605D6658585D58676A645D5E76776D68615F5D5E5D5958513C6E99D7E8F4EDE6D3B480412124233D86B0D0D0BFB283665E5347477DA9AA906D372A212E5389B6C9BD5E8F888697A9B8C2BFB7A6A9A6A3A6B0ADB3BCB7B4B4B2B0D0D0BFB283665E01FE735A07070830746F696D666F6C7575807D7A7A7575819ABDD0CEA8816A697AA9EAFFFFFFC47952598AD4FCF7D28E4E2E3352888F918C7A583E2E3B6FADD6E3D9B38A58230A00072C5E8BA9D8EFD5883D1A164590DCFFF6EBDED69A47273A91CDE1D186331D4A90995F5778794309000012282A2C1E2516040D11181721252C2F2E343C413F46494E4F4F5B58555A636463565A5A61636468655E6C696B6A6667665E5F4E4D426E9BDAE4F9F2F1DDB67740201E2D478CC0D0DCBD9F7D605E534A4B78A4A09068382328385192B8C0BC648C898893A4B2BABCBFB7B3A5A1ADB5B3B4B8ABB0B7ACC0D0DCBD9F7D605E01FE745A07070840756E6572616D7478807C7E7B6C6F7A8BA1BDCEC3A9806B6F84A4D5FFFFFFB476465A89D8FDFFCC8D512C2B567B8C93927A58422E3F6AADD7DECFB6925E2000000E2A5680ADDEF7D38C4916234689D4F8EFE9EDD193411B3978D2E5D68130224F989A64688A934F1704000B191E261E1412080C1216201C1E212D2E313A4040424145474E54555F5A615F59575158686662696A6B6B6B6B676D6565575C574A3E6F97ABD9E1D4D5C5A56F3E1927324E89B7D0D5C4A26F6F60514C537C9CAD98632E1E2532577DAEC4B86A8F898B90A4B5BBB2BCAEACAFA8B5B4B1BFB7B6B1B0AEB7D0D5C4A26F6F6001FE755A070708507D76727B7B797B7E818789767B847D7FA0B7D3C9AB7E6F6B78A8D8FFFFFFC580506290DCFFFADA9652282D537C8887836E523B2E3163A6E3EADAB693522405040F25528EABD5EEDC8E3E221F3D8AE8FFF1E3E4D296411A4392D3DBC884301B559A9563607E8A3F0D010A132C272D231F110906081312202225313238383744433F44454C4E525B58575D5C625E64636262646B686566665F6563675E65615E446398C5D6D9CCCFC8AB7935101320377DB1CDD2B2967C66584C45527E9BA892692C1A21305C8DB7C6BA5E8C898285A1B8C7BFBBB6A6A1A6AEB9B5B0AFAFB3B1A9B1CDD2B2967C665801FE765A07070860807C7B7972767B83848589837E7D7884A2C2DDD9B3836E767FA3D1FFFFFFC578545582D3FFFFD3964D25305181999890795738243770B6E2E7DCBF955D1903040A2656849FD8EACC853A1A29489EDFFFF3E0E9E0A244244A92C9E7D1852B2045999766658A8A4C0C000013231E2825180B020C09101221211B2A333B3941433F414B44515053565E5D625B6557596963615F686C656C71696658545E604D504577A7DCEEEEECDECAAD71371A1D28508DBFD9D4C2A07D6A563F3C4C7EA9AD94623928242F568ABBC3BB658E8D908CA4BEC4BCABA7A6B2A7B0B8B0BABFB2B0ABB1BFD9D4C2A07D6A5601FE775A07070870716E6F736C6D727F8A867D777B7B7C8899B7E0D4A580696A86AFE6FFFFFFC0794F5684D1F6F8DB974B222A4F868987917C4E322A2F69A9E5F3E4BA965F26010002245490A8D3F0DD97491B1E4D8EDDF4F1E5DFD28F4C294181C4DECC90361C4D8F946D6B868C550D00001030221E22140C120D09141E161B243030332F394C3F40474B4C4B53515E625F565C555D6468665B676870636B5D5F5C5A60615A534D769CCAEDF5E7DACBB27C491D1E2B4080B3DBD9BAA5836C5944384B7B9CB0956A331C1E355482B5C9C1668F867F9BACC3C7C8B9B1A9A9A6ADB3AFAFACB1B3B3AFB3DBD9BAA5836C5901FE785A070708807A716E77707575888C7C8485787B7B8AA6C3DED8A4766C6E7CAAD8FFFFFFBF72545B89D3EEF2DE9A4C30335C8289918E75502F242F6FB4DBEAD3B6975E2A00000834628EA9D1EBD58B3B11113F93DCF5EFD9D7E1A148223F84C5EBDE86312151959060618B8E4C1600000C2A2D2B25200B040B0E10171F18222B3335413D4042403D4652504A50545B6C655B605D63696D655F68616E656A66555B5D57535F4375A0D7EBE0DAE2D3B9823D171A254683B5D1DBBD9E85725E4F484B7CA7A796622E151B2A4D85BCC9C16987899598A9B5C0C4C5B9ABB0A9B3B5B4B9BEAEAFA9ADB5D1DBBD9E85725E01FE795A070708907E816C796F79808A837A81837675718DABD0EED89F7666677EABD8FFFFFFB6744C5585CBFBF2D3924C2C2C507C938F8B754935283366A4DBE5D4C4995B2602060F2C5E8AAADBE7DA913F11193F96E5F0FCDEDBD3A047274182C7E2CE88351950949D685D8895541404000A242B2B2F22140A090A0B12181B252E27373A463F3D4449464D504C545D5B6062644D535A6267656863626363636062626059554E4474ABDAF3F6EEE5D0AF6E32171C2C4581BAD5DEC8A18E6B51524249749BA397673D1D13234683B2C7BF6A928C848CACBCC4CABAB2ABAAABB5A8AEB8B2B5B2ACB2BAD5DEC8A18E6B5101FE7A5A070708A07874796F797B75878E808A80837180889DC0E6E3B6846A6681A9DBFFFFFFC3784B4C81C5F3F4DD9C4D2F304D869B998F784F33282B5AADDBEFCBAF91582A0B000C2F5285B6E2E0D1914424193E8BDEF9F9EAE9D69E43213E7FCAE6D18A381B579DA56761878744100004193433302A1D0D0A050B16101C1A202530363938394540464C494C505150575E5663626464615D635E666A7372635E5D5A61535B5543779FD8F3F0F0ECD9BD78391620275282BED2E0C99B726B5E4D3C4879ACB09B67301B172A4A89B7C9BC60928E86949BB8CAD0C4B0A5ACA9AEB8B0AFB6B6B6AAA9BED2E0C99B726B5E01FE7B5A070708B07470676F6A7575808B7F83857A747B89A1CBEBDDB5846468749ED4FFFFFFB97747497ED5FDFDDE984C1A28527D868B98805130243063A9DADFD4BE955E280E010C306190B5CEDFD08A40121A4C8BE1FFF5EAD8D79746234C90C3D8D1813119539A9C6E6582834B1401081B2B32321E190B0603110E13151A2333303735333942404C4C4C434C50545B5F605D5A625B57625B63636C6765615D63635E585853486BA0D4EDF7E6DED2C18B3A1421234487C3D7DCC49F747056443E497AA9B09A6A3A281C224986B4C9C35F94918C8BA5BED1C4B4B1ABAAA5ACB1B5BBC3AFABA6A5C3D7DCC49F74705601FE7C5A070708C07573676C6D6B7E86868B887F777A788BA5CDE6D8AF7C6B637CA3D6FFFFFFC376484B7FD4F5EAD495501F2E587C8E908E825731233C65B1EBECD6BA97581D00000A28618CAAD8E7D190370F1D4191E0F4EEE3E4D19446254997CFD8CB852E2454959363608F97581F000819303139261A0A00040714221D2325302C2E303A3D3F3E444B4052514D5A595B5C535865695C68675C63666F6E62616666605D5D5A4576A5DCEEF6F0E5D3B2733C1C1D2C4D8ABDD9DCBF9B78695B483D51849CA795703A1B19204F8AB4C5C3638E888B8EADC1CCC7C1ABA7AEAAACAEB2BBC0BBAFACA5BDD9DCBF9B78695B01FE7D5A070708D0797971786E73757D888F887B726F738A9FC7F1EAB47C63687AA7D0FFFFFFBF70465178CCFCF9DB9B50272B548690908B7C573C29366BABE1F0E1BE8F4717000009365D89A8D2DFD287431E1D4286DEF9F4DFE7D0934C284886CCDDD2873718509192695F8B86551B000E203E3B3A282407080E0C13172824292E313030333F40313B44495054575959575A61535B58566063666E60676B6C5E595F6B5D584E4066A4CCE9F9F0DACBAA6F360F1E22438EB7D4D5C39B746556373C4572A0B1A5612F19161E4683B3C7BA6885889196A7BDC9CBBCADABA9AAA9AAAEB1BCBBBCB4B9B7D4D5C39B74655601FE7E5A070708E06F6A6B716C6E8386858B8A8274737E8F9EC3EDDFB1805D607FA3DFFFFFFFBF72434F84BFF0F2CC945727335686959E98744A322E3261AAE0F4DCBC8E571E05001631598DB1D9EECE8637191E498EDEFEF7E2EAD69A48273980C1DEDD8E32164C9597645E969C581200091E2E3B3A29150C08050A0A11181D28343034343137443C43403D484F55625A5959555A5B615E5F61656062686C716166646660595846709DD5EBF0EFE6D4BC7C34181D2A4986BED5D9C99B765A4F3E3C4872A0AA9A6738201F2E518DBCCCC25B8A82828FAEBCC4C5B8B2A5A5B3AFB1B5B3B0ABA8A6B2BED5D9C99B765A4F01FE7F5A070708F07973757D6E697A80868D8B8A7E798390ABCBF0E4B37D63627AA7DBFFFFFFB7703D4885D2FFF1E196482A274B818A8F8C82522F273065A9E1E7D9B88D5B22070208285D94AFDCE4CA833517244386DAF8F6E6DCD58F40233C7FC9DACD83371C539C9A5B5F828E521100071C3C473E33250C00070012121E16232D2F393C343C3D3F4A4A434C554C525A6157515262565C6560676C6B6C6B66646661666754603F81B0DEEEF9F5DED7B5753D1C1D27538CC1DBEAC69181605B46384A80A3A8926C311B16294B80B4CDBD658F858986A0BECFBDBAB0B0ADAEA8B6B1B3C2BAB1B1ADC1DBEAC69181605B01FE805A0707080071746E6E6F6F79858C838E857276788D9CCBEFEAB08A6666719ED3FEFFFFC26F445385D1FFF8D69953212C5384889C90725230233165AAD5EBD9B79D5B24040006275A8FACD7E7CE87431E244793D8F3EDE2E2D69A46233E89CCE1CA89381649889E68628E965B1400052539443B35210A00060613121F1F212829322D3441413C40464E474C515352615A5F575E666D685F6566526164666563656A62565C497EB1E3FCFCF2E4DEB6843D1C272A4F8BC5DEDDC9A37A645A4E3F4381B6B39F68291912264682BDC8BD6790838A96B4BEC5C0B8ABA2A9A6AEB3B2B8BAB6B0BAB8C5DEDDC9A37A645A01FE815A070708106D75706A5E65768A87898B7A6F708390ACCCECEAB57A64637299CEFFFFFFBF71464C7CD1FFF5D98E4A1D2A557E8E9296734E3A243464ACD5E3D6BBA0531A03000C2B5284AADDE8DB8D411216448BD5FFF5E5E1D7994D293F83C5DFCA893618599C9F686D8A91521400112840484033170E0000090C1414191E1E283833393D38413E35414B505555595E635F5E5752615E5A5F646268656E66615B5E5D58544873A3D0E6F3DFEAD19268370F19274881BADBE3C8A5776A564A3A3F83AAAE9C64330C0421448CBCCFC2688E7D858AA0BBCBBCB2A4AF8AA9B1B7BDB7BDB5ACB0B2BADBE3C8A5776A5601FE825A07070820747B747B6B77818791888081737F8483A1BCF0E7BF776566719DDEFFFFFFBD6A404F7ED1FAF7CC944D1821527E959D9A7B4C31262E5FA5E6E9D7BC9E5B2C0D0007325686B4E1E6DA8B3920143D96DDFBF9DEDAD58D50233D83CBD9D1833527519598685C828C5209000D284041523929100A07061111121C281D2735373E38363B3A3F484A4B4B4F5458555658616169655F63696063685D5F5F5B62585A5B4C7FB4E2F8F3F8ECD4B97B3B2015274B92C1D8DAC39D77695E3B34467CA9AE7D621E1F16254E87BED1CC688F898288A1C8CCCABFB8ACB4AFBCBBAFB7C0B6ACA5B4C1D8DAC39D77695E01FE835A070708306F6E62605B62767B87898A82767A7E849ACCFAEFB6795C5A7AA8D7FFFFFFB56B464C83CBF3EEE29A4E243253818E968E76512C222F6BA5D2E7D2C79F612009010C265785A6DEEBCB913C1D224791D9F2EEE1E2D38E48243C87CBD3C8852F1A5BA19B6D628B974C1701082F464B503922110100090D0E111D20232235332D333E4243474E4446524E5A5E575555536063575C686568686462655B5F665E5558476E9EDAF1ECF7F1D5AF6D2E1424254883BAD8D4C59C78665D42344577A9B7996D3A2817214481B1CAC5698F828A8BAABED6C8BEB5A8B29AAEB6B3BEC0B0B3B2BDBAD8D4C59C78665D01FE845A070708407479717271737E7F938E9A887B778191AECBECF2BC825F6676A6DFFFFFFFB96D424476D0F1F1D8944C242455809098927E572D282566A6E9E6CDB48A562506001630558CA7E0E3C993471A1D488BD9F1EAE3EDDAA44C2E498BCAEBD682311852969866618D895213000A23444B473A280E030507100B080B1C282A37343133373B3E404949464F54585C5D5F585960667163666563646B68615255655857534571A4D0F5FBF4EEE2BA803E1E27294994CAD6E1C7A17C655A43314189B0A2935D311E0D1F3A7DB5C4C76F8C8E868B9CBDCECEBCB8AAA5A9B2B9BABDC4B5B5AFAECAD6E1C7A17C655A01FE855A07070850717772736E77817F8C908C817670778EA7D4F7F0B680695D74A1DCFFFFFFAC623E558BCAEEFBD1894B2B2753818D8B83774F2E273973B1D4E3D3C1935C1C08001127578BB2DBE3C682311616478CE0F8F6DCDFD89542273C84C2E8CE833E2A5B989A5E6889985E16000E294B51433B29150A00030008111A252E2F32282F32313C3D3C47485252555F5C5B58535B606266616466666469635B595C5659595B4488AFDFFAFFF1ECCFB9874120313E4E92CDE8EBC4A5836759432E4683A1A89C6B391E0B1A3E8ABAC7C65FAC906985A2BECFCBB7B1A8A7A8B3BAB8B6C9BFB3AAB4CDE8EBC4A583675901FE865A0707086074696E6B63707B869297918774737687A9CEFFE9AD75585C7DA5D8FFFFFFA569484982C7F9F3D8964B2C35557A8F8A827B5136263269ABD7E4CCAF955321060008225D8FADDBECD483402026498FE6FFFBEEDBD09F471B477EC6E5CD82322154939964628788521000092A515D59462B140805030B110B13182A2C3135353E3C403C453D4542475652545352575D5256615B6061696C6F6C5E61665F58555A4375A8DDEDF1EFE6D3B1773720242B4681C7D7DDBBA17D6352473E4E72A4B192623015131E4486BFCDC5688F857785A5C4CBCFC5B2A9AFA6ADB9C0C4C1CDB0ABAEC7D7DDBBA17D635201FE875A0707087071746066677383868991867E736E758CABD5FFF6BC805C57729BD3FFFFFFB867414D84CFF6F5D2954A1F284C84939498844E30212565A6DCEAD7B98B501700000D32588EACD8E8DC973F1B184585DAF5EEEBD3D0A03D233F8ACCE5CD7D311A52929D6A6289885E1100112E4A60634A290A01020E050E13182429252C323C39393E3C3A3F4B4F4B4E4F58595E515A636258575E645C6362656565656359584B3C6F95CDF3F6F0EDDBBB6C2D0F23243F80B4D2CBBEA5856659493B4579A7AA8B7C391C0923457BBACDB75E86808187A6C0D4C5B9B3A7A4A9A5B0B5BABDB9B5B1B0B4D2CBBEA585665901FE885A07070880787D7074676A788492979081747C8088A8D3FFF7BA775D5B7BA1D6FFFFFFB4693E4A7FCDEDECCC964728284E7E919391805335202D609CDDEED7BF8E58210D0302255689AACEE7CA843C191B3E8CDFF4EDDDD6DB9349224692C6DDD88833225798986F5B8F955012010E264D6759483611030003080910172B27242F31373035363B43404C495453515A505652555A5F645D60626B646E6B626759665C53503B5191CFEFEFEEE7DBBB82460A1F30498CC8D6DBC09875655244373F7DA2AE975B331E0C1D4B81BED1C46C8C5D6D84A6C2CCD0C4BAAFA3ADB8B9B2BCC1B9B2B2B3C8D6DBC09875655201FE895A070708907A70726762747A868F9390827A756E91B0D3FFFBC7755460709BD9FFFFFFAE623C467AC3F1EBDA95472C2A51889091907B532F283468ACD6E2D2C6A35C1900000A2C5B93B0D3E0CC8D3E1C1A388FE4FAF0E4DFDA9F432E438DC7DBD1883D1B598F95605A8697561E040C3455756A502A0A000000010B171F172327313234333B423A343E4245434E5151515750546162655D6560686B68655D5D57595B5B564378A4DAEBF8F2E0D6B77E3B25272E4E83BAD2D2BC9C786357462D3B70A8B5A36732160F24457CBECCB76A84877B8BAAC3CDC8B9C7B5ACA8B2ACB1B7BCB0B6B1B2BAD2D2BC9C78635701FE8A5A070708A06B6862686466758287908F8871646A81A7CFF4F9B87A5B5A6DA0D4FCFFFFB36A3D4878C6EBF8DA9F4B252C5A819B9795754A2D272E66A0D7DDD3AD9354190401042C5699B7DBEBD5943F1A1D3B89DAFEEEE7E4D89840203E80C2DFC68229185B989767688D8F581400112D547169472F100100000003171B1A242A2A342F302C3035404648514D4D525057544E566B6A5C5963666969705F585B625F585A554871A1D7EDF2EFECD4B479370C1A23417AB6C9D6CCB0805A4D48354479A8B29366361D0C1C4584B0D3B6638A817F82A2BDC9D2BFAEACA5A7A7BFBEB8C4C3B8B1BAB6C9D6CCB0805A4D01FE8B5A070708B0757075716E79838E978D8E7B6B6C7B92A8D5FFF9C288645A65A2DAFFFFFFB271424A81CFF2F7D4924922294D8490928D6C5834202F58A7DDE7D4C49B4E16000007306394AED6E4D08F38171C4189D8F9F8E1DCD5943B1A3D86C3CDCF863522599994535B908E59160415356679704F2E1800000000040B161E25242D243435393B3C3B3C434751525C5458514D525F62646062685C586265656162585B514F437BAAD6EEF5E8E3C8AE722D11132C3E89BFD3DBC3A574634C452C3B76A5B19A663B1C0E1C3F8CC1C3BB5F8D7F858FABC8D1C1B5B1ABB0ABAEBBB7B4BFBABBB4B3BFD3DBC3A574634C01FE8C5A070718C07B706B7574707B839593988D7D797991A4D2FFFEB9795B606BABDEFFFFFFB56B3F437AD3F5F1D4964A222751838C8F93735139243168A3E3DDCAB7915B2E0800132C608BA4CBDED18D3C1723458FD7F1F6DEDBD29F4F1D4781CBE3C589371D569F9B5C58888B511002163B63787254301302000007090B131918243030292E2E32383D464547484E565651565158585F625E60666567615D5A6060625C56513C7CA8E4FAFDF7F7D6B87E401E1A2B468DC8D7DBC7A47862593F3D447DACB8A0682E16111F3F89B7C6BD6187747990A0C1D2CBBDB7A5B2A8B1AEB0BEC3C4BBAFBAC8D7DBC7A478625901FE8D5A070718D07A7577796D79868B9B9B988B80767989AED4FFFFB879514D79A6DEFFFFFDAC613C3E6EC5F2EBD1974B2129537E9C97937C4F261F2B5FA7D7DBD7BE99581704010E2C5893ABD9E0CF88431C213D8EDAEDEEE4DFE39147223881C0DFD484352154949365618A94652006183F7D927B5331100000000108080F1D1F201F29322C322F393941444B4653555A5750505A5F595D645F656360615E5E695D586555544380B6DFFFFFFAF0D2B57F39222A2C4B89CAE0E0C09B776A554D3B3F7FA7B3A069491900114081BDCDC86A8B847088A3C8CDCABFAEA3B1A5ACB8B8BDC4BFB7BEBBCAE0E0C09B776A5501FE8E5A070718E07D74656F7674738D9999968174787B8DAFDCFFF8BA7B60516895D1FFFFFEB0654D3D71CDF6F8DC8F4A23244F8A92959471471D162960A2DFE7D8BC9C54230F02122B5A7FB2D6E7D08E44181A428AD5F1F3E6D4D1993B193887C3E2CA8C351C56948F645C8E995F1D011237698E845E30180000000205081313162126212B3436383B3D404C4A494D515656524B56505A625E5F6461696667645F5B585359534070ABE3F5FFF2E8D9B2753E1522314B8BC7DCD3C196785C5743373C739BAB9A6C381100164381C3CFC96586857B8BA5C4CCCAC2BBA1B2ABABB0BEBFBCB7B0B8B9C7DCD3C196785C5701FE8F5A070718F078797175696C7E8D9D9F8E84736D7087A9D1FFF5AD77595376A6D7FDFFFFB569424076C4F1F1C9883D1C2052829799927149381A265EA7D5E6D6BC9F55170000132E6090BBE2E8D08E3D1A164992D9F3EEDCD8D3A14B20488AC4E8C8802F1B5198935C5E83995B22011647798F875D391000000002070E111B21242C2F302B29303B4246474549434B565346534D48535A5E596168686860615B585C5C50524674BAE2FBFFF5F1D7C1783F202B33588ACDE3E1C3A57B605545283974AAA2956E340E14254C8FBDAAB76988888187A5C2D2C4B6A0A9A4A6AEB9C2C9BCB9B8BEBCCDE3E1C3A57B605501FE905A0707180076796F6E6C676E80968F9A836A717B8A9DD3FFFFB78159516A9FD7FDFFFFAB65403F79C5E6E4D08D471926578C99918B6F4C2B1D285FA6D2E9D3C59A6521030005316991ADD7E0CA833D141B4586E1F5EEDDD9D99C402B4584C1E1D77A2E24578C8B5A5F8F94591B001D45749A9567390C00000000040B10192022312A2B302D2F3C3D444C3F4C5950534D534E555D5C5755585E64646B6359595E5B60535B447491D5FFFFF3ECCDA770361023223B82BFE4D2BD997A644F3C2B3473B5AE9265291801183477BCD0C36D9596785798BACFC6BDB3ACAFB0BDBFBAC3BFC0B8B4B0BFE4D2BD997A644F01FE915A070718108479727C70798193AAABA090706F7D91B6E1FFF8BD7C5B54779ED4FFFFFFB8663E4078D2FEE9D093481D26528693928C7C523325295DA2DAD8CDB69B5A1B01000E2A5E8BB7D6E3C7813A1B1E4488D8FBF6DCDACE9D4F2E4486C6D0C888331652949863659297521E031C52819E95623C1500000000060011121C1A23242A2D292B393D3B46454C4E584E525449555D575B60635E605F656162554E5856584D3D76AFDFF4FFF2F0E6B77522061A2B488DCDDDE3CF9F775D5349343D78A7AD9B6D381C121D3D89BFCFC76D8F7E7189AFCCC9C4BAC0A9ADB1B0BBC5BFC3C1BBADB1CDDDE3CF9F775D5301FE925A070718207568696F6671758F9F9CA18A73686B8AA2D0FFFFB77E5B586D9BD2FFFFFCAF653E477CC9F1EAD89E462A23538798A49C764A21131A61ADDEE6CFBF985B18000004255C96BCDDE0C68239150F3284DBF1F1E4DDDC973E244697D6DDD2812C1A509799615D8D95571C001A498FA3915F350D000000000005111D191A1E232A363234313034414B474D515B564B4A52575F6164605E5A63626161635D60595851426AA7E1FFFFFFF0E1C37E39172031488DC7DDDCC8BE7B635449393E6BA6AD976A320406134081B7CAB96B837A7A85A0C3C4C7C8BFA9ADA5B0B4B8BABCB9BEB2AFC7DDDCC8BE7B635401FE935A07071830786F6E746B718A96ADA29D897A6E7286A9D0FFF7C1795A51659AD6FFFFF5AB6141437DC9E9E6D18C42222B58879BA0987B492D21265DA6D0E3D6C199561C000000335E94AEDBE6C8843817163F89DCF7F0E1E1D6994C234886C8DBC987311550958D5E5D939F591D11203E7EA39F784E1800000000000B0C131D21212E2824242E2F353B3C3D41534C58525B50555E6466605D5F6161666A575D686353555B417CAFE5FAFFECEBE3B87529192123478ACFDDDDC49973645740303E78ABB39A693415071F4381C1CDC65D8E7E798CA3C3D4CEB6AEA4A3AFB3BCBBC2C7BABBB4ADCFDDDDC49973645701FE945A070718407372747470717390A19A95896B686D8AB4DEFFF7BD795F4F6BA2D0F7FFFFB05E3A4379CEF6F1D691431E2D53858D99927847301A2B57A6E3E2D5BE8A47250D02082A6692ACD1DED0893917183E8CD7FBF1EBE0D395491D438CC5E2CD8430105498945F60878E57180420497FA8A27041270000000000030A101A17222F2027312F3C3C3F41443E46565B574E515E58585D615E5B636467645E586461625C4F3975AEDDF9FFF9F6E5B3712E0E1326467EC8D7E4CAA37B594D3E252C7EACB49F6E310D0F113A84BCD3C668927F7184A1BCD4CFC8ABA8AAA4B1BAB9B5C1BCBCB5B6C8D7E4CAA37B594D01FE955A070718507D84787A71748294A0A09A8B7D70768BB2DBFDFFBA75515E77A3DEFFFFFEAE61413F71C8EAEDD39546232B5183969F95654D2723375B9ADFE6D5C2995A1D0E000728567EA5D0ECC8863C1E194185D6F4F8EBDCDC95431C3F88C3CDCA86352A5499A46E678E9D561802144384AF9E703E150000000000010A0715191E2B2B2C312B3338384140484B515751504D575C555D5E6367655F5D69605E505359584E476FA7D8EEFBFCECD6C179381C1728418EC0DCE0CAA67B5A4E3E323077A6AE9A733218091E387CB7CBC563837E7187A4C2D0D6C8BAADB3B2ABB9BCC8C0BEB2AAB8C0DCE0CAA67B5A4E01FE965A070718607D7F737775767E8DA0A0A386706B7285B5E3FFFFB47E564C6B9AD4FFFFFFA85F3F4578C0E3ECCD90451B234D83969C8F7955301D25569CDEDFD5C191541C00000A315C8BBCD2E5C8853C15164685DAF2F5E5E1D59744234D88C9D9D07B2A1B559E9B625C87914E1C09234B83B7B07D440D0000000001090C12141C22212E27272D2D393443474443495657514B4E58605C59645E656570675D625E575E4B503F81B5DAFFFFFFF8E8C07B3F1E1D26478ECFEFE5C79B7465533E313D6DB0B89F6A2C0D090D3781BACEC06288807B7D99C3CFCBC2BCA5AAABAEC1BECBC3B8B9B0AACFEFE5C79B74655301FE975A07071870786A6E6A6A6F7E8EA2A59E8A79737587AFDDFFFBB77B594C6499CFFFFFFFA56138417CC8EDECCA8F41222D628594A095795228232760ABD7E0C9C691592A02000528538AAADAE2C883341C1D4187DDF3F4DFDDCF95381C4089CED7C781381D5396946065909557140B22558BADA87B4713000000000005080915211E2922352E272C333940434F54505850564B4B595F625B625C62606462655E60655C5952407198D9F1EBE7E7D9BA7D350127344086BED5D8B9A1765B4F4230397CA9B19E63230A071A4080B8D1C5668D80687DA2C3D6D5D2B9AEAEABADAFB2BDC6BFB9B7B8BED5D8B9A1765B4F01FE985A07071880706E5E605F6A728CA09F9A8A7673778CADD7FFFBC17A534A659CDAFEFFFAA55F303E6DC5F0F0C48F4019254C829BA08B7648221A3066AFDEE9DBC0935325010000295987A8D0E5D68B31101B428ADAF4F8E5DCD19D42193B8DCED7C285261A4B9491605E93935B190A1D4F87B3B47F4A16000000000000050D1718242A353431313337373E3F4952474F464A525254585B605E616363646065615F575C58544270A7E5FFFFF0E8DFAE73321A282E478AC8DFDBC7A16E5D604740447AA8AF9B6C341B081F427FC5D2BB5D88726D6EA6BBCEC6BEB0A6A6AAB0BEBFBFCBC2BCBDB4C8DFDBC7A16E5D6001FE995A07071890716B687062607691A1A99C906669718BA9D3FFFAB672594E699BD1F4FFF8B067403574B7E0E5C78E4A2225508B9F9D92744B2919285798CFE5D2BA915726060001295587ABDBE1CD8F3E181A3B91D6F5EEE1DCD9904020458BC6DDC9852F1D509D965B698E985D220F245787AEAD8745140000000000000F120C131D2529302B352B3136413D46504E52515051494B57616063605E656B645F5A6259565056447AB0E5FFFFFFF3D2C292350D16234F8FCADFE5BF9A6C5B5A492C3A70AEBAAF742F0F0F103388C0C6BC628176727EA2C7D4D9BEB8ACA3A699B1C1BFCEBCBBBBB9CADFE5BF9A6C5B5A01FE9A5A070718A0736C696F6A6B7A95A6A7A18F70726A87ACDDFFF8BF7C534F76A3D6F5FFFAA35E474A77C8E7EAD78C3F16214C7C95A28F73512F1A345DA1DBDBCABA915B2303000831557AA6D0E6D0853D19213F8CDFFDFEEBE4CF9341244384C6DEC77D2F205A959B675C8B9A51200C214B8CB5B5814419010000000000081116141A1B21282A343334383F45494F4D53505750455659625B5C5D5E615B5B605F596158554B4370A3D8EEFFF3E7DBBD7634141E294787CADCE1CD9E75614D36333D7EA9AB9B6C2B0D04103281B6CFC064827A6C83ABC3CBD3C7B3B1A39FB4BCC0C6C2C1BAB4B3CADCE1CD9E75614D01FE9B5A070718B08379736E696F7790A7A49F957F6D778AA7D1FFFFC27E555167A0DDFFFFF6A45D3C3B6EBEEEEFCF8745101D4C8DA1A38F76553219225CA4E0F1D6B798612300000E325880A7D1E1C181391716468FDEF4F2E7E4D29C4423438DCBDAD4813620519795625D8791511605285594BCBA8449180200000000090D1117141C22282924242E3035383D41424F5752575154575C55635D6060625D64696C615D5554493D75B2E6F3FBFAF6DDBE802F1D2327469FD0DFE2D0A57A655242353B78ABB8A06B330D0D164580B5C9AF5F8176697E9AC2D3CBC0AEA5AFABB0B4BCC5C9BFBCBDB2D0DFE2D0A57A655201FE9C5A070718C06D6B646C6065728799A09F826B605F88AEDBFDFCBD795349649BD4FCFFF9A75D36427DBEE3E5BC873E1D224D82939D9A754A21172667A5D5E4D3C29B5F190000142E578DB7D8D8CD893E16193D8AE7F0FAEDDFD49C461E4280BADBC9853A24549A9064608B9B5F190C2E5797B4BA874C130000000000040E1212161F2423272625293C41423C444A504F56555A575351555E626265615F5E565B5D5A555154417CCEE7FFFFFFFAEFC48E41191E315695CAE7E3CD97765B5448304078AEB39E6B2A0D0E1D3D87BFCDC46D8876747DB6C1CECBC0B1A3A8B2B9BDC1BEC4B7B7AFAFCAE7E3CD97765B5401FE9D5A070718D075746D68636D72889BA398876D677283A2D7FFFFBF71504B6598D4FFFFFFAA59393F7ECDE9E7C8894315275E8CA09C8F79452617195599E2F3D9BC9B5D1A00020D295C84A5D2DDD08F3317174192D3EEF2E8D9D8924C234788D8DFCE87281C539E9E615D868B57180C295E95BEB78C4B140000000000000909161421272A2D2D2B2D30303942464A4B514C4A4A505A5B57565661656A705C5E5F5E5C55524F4777ACE6FFFFFFFFE5B77E3B272A244A93CADAE1C89F6B5F563D33407AA4AEA75F371A150D3786B1D5BE6283736979A0C7D3CAC2AFA6AAB0B0BEC4C6C4C0BAB4B1CADAE1C89F6B5F5601FE9E5A070718E06C6C645F6161788F9FA39B8870646F7DA7D5FFFFBE7D534E6D9CD2F9FFF2A161383C7ACCF0F2C7913B232D588C92918B72522A1B2558A6D5E8D5BD9B5E170000092E5B8CAED0EAC789390A184491D9EEEDE7DFD79845253B86C6D3C2843A235A9C9C615D8D90541C0C1D5596BFC78F5315000000000000020F0F1225282C32272630323B3D3C40494F4D4A4751596361596062626264675F59554F615852553F72AEE4FBFFF7EFE1B9743C10212E4F84C8DFEAB89F79594E453F4B83B8B4A6742B1701173C8AC0CFC267806C757C9DC7D2CBC1B1AAB3AFB0BDBACBCAC2BBBCABC8DFEAB89F79594E01FE9F5A070718F078776765616A768DA4A19A816C667290AEDEFFFFC072514E61A4DDFFFFF3A963394176B5ECF0CC8F4817214E849A938D7B4B2A202158A4DAE2DCBC9D5621000005285A87A8CCE8D5833C131C4989D7F4EADFDDD29D4C264786CCDED385281E50999957618699531D08215792BEB98A50170000000000010C0F101314162027272B342F3C3D454346585C5258504F566065605C63655F6160615C5752544C4C4C75A4D9FEFFF6F3F2BB782C0919224883BCDED9B89C7860483E32407CB1B8976E3617101D3D87B6CBBF607E6D6A81A3C4DAD6CBC0AD9DAFAEB7C6C6CDBFBFB1B5BCDED9B89C78604801FEA05A070718006D6E717263707A8DA9ABA8896E677285A9D9FFFFB56C4F4E639BDFFFFFF6A665343F78C2E8EED8893E23284E8A9EA293784829121D55A8D4DFD9C599541F0000092E608FAAD1E8DA90380D133E80DBF8F2EFE8D59B3C173786C5DED0882B165C9A9F635C868E581509265FA2C2B98950150000000000000008111B1D28292E23202D303E3E3F474551554D4E4D524F595B5359616360615D5E58575653514E437FABE8FFFFFFF7DEBD8145161F305988C6D9E2CB9F765D53392A2E70ADB39F69421705173782C1D2C668896A647BA1BBD3CCBEB3A7A7B3B6C3C8C1C9C3BFB8BEC6D9E2CB9F765D5301FEA15A070718106C736A696061778BA8A39D8F75636A8CAED4FFFFB96C53586AA3D6FBFFF19C5C343F6CC8EEDED68F431B2A5D8D9C8E8B6D472016275EA8DEE9DAC5A15A1D00000A295485A6D3DAC786331615458EDFF8F8E7E2DC9D45203F8CC8D9D18826144D9B925C6389925C250A266599BFBF8C531C000000000008030912111C252E2A262E313833383C484E4F5451534D505C595C5A62655D61646662615B53575353386194CCEFF8F3E8C7B2782E0F1C294986C1DBE4C19B6E584B3829307BB3B4A36E2C10111B3984C5D0AE5C857D6674A3BBD3D1B9AAA8AEAAB7BFC3C6CDBDBCB7AAC1DBE4C19B6E584B01FEA25A07071820838077766872839FB4B9B19868696689ABDAFFFEC3735B506B9BD0F7FFF99F5A33447FC3E6D9C48843232E638395AA9A7B4D26182B55A3D4E7DBC499531F0000102B5E8CB2D6DBC479301718408ED6F6F2E8DAC89E42294889BEDFCC7C261D589B9C60669594530F092B5E9CBDC196491800000000000611151516181D1D212422273343423D454C5758535148525C555E615A5D6263655E5C645F645154584B73B1E4F7FDF5EBD8B476431C1936438CC9E0E2CBA8815D5541334377B8B49A65320400133A85CDD6C66682787482A3CFD2D3BFAFB6A8A9A9C0C3CAC4C4C5B4B8C9E0E2CBA8815D5501FEA35A0707183074707465636D7B89A8A5A1817A717686AFD7FFFFBC664D4C639CD6F6FFFAA95C2F3477B3E9EFC67F401F2659909D9895784F28152752A0E1E1D3B496571600000031589AB9D7E2CB823F17133889D7FDF8E6D2DF9857274687C6E1D38435275C8C8A5C638C93541B0A1A4F96C7BB995B23000000000005100B10101A1E2825262F322D343A3A3D46474E5253564C525D5B595A5E626A6868616657545B5D4A3E6AA3D9F3FBF6EFCEBC793215172B4883BEDEE0BC9C7B57453E37407CAAB1A667370C0D153D85B6D0BF5A7F6F5F72A1C6D3D7C7B2A8ACADADBDC6C4C5BEB9B6ADBEDEE0BC9C7B574501FEA45A070718407C757375746C7A96A39F9E7F66666B86A9D8FFFFC175504F649DD5F8FFFBAA5E354678C5E8E7CB813E132048889DA09074502815245B9BD5E5D6C2955415000007235A8EB4D9E6C77E340F144287CFF0EDE5D5CEA54B233D87D1E2CA882D17529A9F60618B9C591803215CA5C0C49154100100000000000509141C202A1F2228303439373B3B3F474B50454A4B4C5A5A5F5A5A5D62595D5D57595C605E57584274A9E2FFFFF2F5DFB87B2D181C2A4D94C3DBE0E3A773564B3F303870B2BD9952291A08144388C5D5CB678C7768709DC5CECEC4B2A2A5ACA3AEB8BEC7C0B8BEBCC3DBE0E3A773564B01FEA55A070718506C6B666968677A8BA5AAA3846D676F7CA0D2FFFFBA74514868A0DAFEFFEE9D53343A7EBBE1E6CE8D4E241B578A9A9A95794E2D1924599ECADACEBEA25D23000003236393A7CCDAC7873C11194592E2FAEEE3E4D0953F21408CBFCFD18E392D5897955D5C8892531A0A1F50A5C1C29B621A000000000000080E1A1A201E2224292B2D2D33373A3E494F4B4B4C4F4D525F575D605E5C62666666585C54524C503F6EA6DEFFFFECF0D6BB7B311A18264E96CBF5E6C59D71535143343A76AEB69463331306123B81BDD5BC6A7F636A7EA6C5D4D5C8B0A4A7A6ADB6BEC8C8BDB7B9B4CBF5E6C59D71535101FEA65A070718606F6F6B606363758FADAEAD8D69636680A1D0FFFFB1654B466998D5F8FFF3A760353573C5F3EBCC8D3D0E20598F9EA18C79522B132D5C9CDBEBCBC2935D1C000004315F8AA8D0E4C887390E1D488DE1FBF4EADDD49B411F4288C6DCCD88321E5898A26E64899451170A27559DBEC58E4C1300000000000104111918121C232E2B32312F353A394C4A49564F51495358605B5F555E6069615F60595654514D514681B5F3FFFFFFFDEDBF803C1B233C488ACFE6E1C39E786255382E3C71AAB99F6F3113081A3F8BC0C8C566816A6777A6C5D1CFBEAEA2ACABBBB8C0C7CABEB9B6B5CFE6E1C39E78625501FEA75A0707187070777977706E8292AFB0A5867265768FB0DFFFFFC3734F50609BE0F4FFF29B5F303B7BCDE8E3CA904315255C969E9D9671462E282D68ABD9DED2B1905A260000052A5882B3D4E0C78A391116428FD5F7FAEDDFCEA036203F80CBDCCD862D1E5994925E619097531B082465A2BCBC8F5519000000000000040B14171A29302C2933292F3D3C3D3B4C4B53565350535856605A5B5F5D606161585B575957474E476FAEDEFFFFFFF2DEB66F341F24255193CAD7E6CA996F6459432D316FA8B29873381005194380BCD2C55E87706B729CC6D1D3C4B2A4ADACABB8BDC4C4BCB1B8AFCAD7E6CA996F645901FEA85A07071880696A736F67687787B2AE978868625E8CADDBFFFFB5764C455F9BD4FFFFFC9E4E2C3678CDF2F0D68A44242D508190968D704F211D295AA8D6ECD1B58F5C1B00000830578EB1C8D9C88A3611153E8FDCF2F4E4DDC89945234185CBD8C77F31205AA192645A8C95541D132462A7C9CA9D6122000000000000070C09121D212C26232229383D3B383E484F5754514848525561545F635E5D5D59545B5F555952574075ABDBFDFFFFF7E3C384371323273F86C0D6E1C39B745645362C337CB5BB9E753D0C0D133B79BAD5C1638877687899BFDDD2CDAEA5A9ACB0B5B5C9C9BDBDB6C1C0D6E1C39B74564501FEA95A0707189073706C6C60647E99ABAFB48466637386AADDFFFFBF794D4C5B8ED1FEFFF69E562E4576C5ECE3C78D3F2227538C9D9A8F714F2517255BA1D6E3CEBC985D21000005264D84B1D8E4D789391318418AD9F6F0E6E8D99D401D4088C5D9CE7F29205796A16B658D8F5C1D0F285DA1CDCA96551B0000000000010108140B12212B23202C24353B3F3B46444D4F4C4F504E5653515561626B626D6459545B5E5350514384B1E8FCFFFDFCE4BC7A2E25242B5393C9DADCC8996B5F533A27457AADB89D6D2D120D12387FBED8C56183686E78A6CADECBBDACAEB1A6B7BABBC9C9C1BBB5B3C9DADCC8996B5F5301FEAA5A070718A06D796F7163737D8DA7B1AF8C6E716D82ABDFFFFFBA714D4C669ADBFEFFED9C5E333E80C9F1EACF92411426558DAA9897723B29111C54A3D9E1D2C49A551D000005256288AED8E2C77D35111A4690E1E9EBDEDEC69542263C87C6D7CB8A311A5A9D975D6A9599581C0C2A5D9EC0C697521C00000000000007111819202A27242A2C2C2B373B41474A4A4E473F4155585C5E5A6363646163605A5C5B59574F4A4374A2DFF7FBFBFAEBC2783119222B498ECBE4E7C3A0695A5040334485AFB3A06C310C03103789C0D9C1607B686379A2C0CDCDC2B3A7ACA9ACBBBCC2D0BEB9B5B0CBE4E7C3A0695A5001FEAB5A070718B07C76706C5F6A788AA0B4A997746C6D84A6D2FFFFB4754D4D669ECFF6FFED9E56353D74CAEFE4BD873D24275897AB9C8B70441E0F2264A5E4E8D3C195521A000000265B92AAD7E0C17A3A161C4693E4F1EDE8E5DD9642284488BFD2C382341D53989C5D5F919C561901295EA1C4BF90531D000000000000050A1718181C212223303437383C38414E565751594C485860666056635F6263605E555360575F4C3E6FB5E3FFFFFFF5E3C1773C231F2A4184C1E4E1CCA06C5A4D432A3F77A9B7A3692E0E000D4381C3D3BA5B79686B709ECAD3D8C1AFA1A5ACACB7C9CBCBBFBAAFACC1E4E1CCA06C5A4D01FEAC5A070718C07570716A6A617A889DA29B846B6B6880A0DBFFFFBA6846455F9DD0F3FFF8A75F394075C2ECDFC68E3E1428558A9F9D92784F3022245D9AC8DCD8C29F5915020009295A87ABCDDBC28B3C1516478CD7F3F0E6D6D29945264C92CFDCC6842C155994945E5F9498531309265D94B8C0945718000000000004080618131D23272A28272F2C3744353B4248504D544D504F50545661676262606A5F615D615950514674ADDFFBFFFFF4E6B8864019292D4B9ACEE3DEC89F755C4A3F2E3E72ADC19F70371405143A7FC5D2BC617A716E78A2C4D2CEC1AEA3A9A3B2B2CCCACBC4BDBEBCCEE3DEC89F755C4A01FEAD5A070718D06D6D6B666469728CA8A6A687695C6486A4DDFFFEC171524866A2D6FCFFEE9F5F2F3C71C3EDEFCE8E4B132E5A8797998D7C4B2A1E1756A4D9E5D4C5A6611D03000823548BAFD4E2CA842C03134198DCF9F5E3DAD09342213989CBDDC388302360988F645E8791541D12345C96C0C39C53190000000000001012131A1F232029242332333E4541414647554C535152535957605E635B6065615F595D5A575547357FADDFFAFFF7F7E2BC7C2D161E1D458BC7E3E7C59A7256523B30447CA9C29E6A320402133E8DC1D3B36488706B83A4BFCBCDBDB4ABABAAB6BAB7C0CAC3B5B0B1C7E3E7C59A72565201FEAE5A070718E07C756B6F63667894B3B6AE8E6B627082B1E4FFFFC1744D455E9ADCFFFFE9975534417CCBE6E3CC8C3E232D5893A2978D68441E132A57A4D5DEC4B39A631E0000102B5988B1DEE5CB873B1419398ED8F1F6EFDAD99A43234183C4D3D98B321B59A09B5D6296A3551C042D5DA1CEC893562500000000000008090F151B1D28251E282938343237484450524C504D5252565B5B6865636169615B5356594F4E543E729ADCFCFFF2EFE5B479390F24344C93CFDFE7D19F6C52443E2D3E79AEB8A364270E0308377AB6CCC25E7D6F5B72A5CCD6C9C4ADA6ACACBCBAC2C3CDBFBBB0B6CFDFE7D19F6C524401FEAF5A070718F076827472636D7B99B4B2AF8E6E687C91B0D7FFFFC3704A4E6098DAFCFFE998502A3E77C8EEEACC853F2426568E989D8F714B22142567A3DEE9D4C2A45D1A000004235593AACFE5D18B3C10183D90DBF1F1E5E3D39944253885CDD8C38930245F949B655E8B93521A003364A0C7CC9D5C2006000000000003060A0D171C212526232D262E3E4B3D3C4456484E455451595B5D66615A526166645D5C635B52594379A6E3FFFFFFF5E7C67A3F1F272E4589C4E9E4CB9974594F4333417AB0B6A4712C0D03173483BDD1BF607E676D79A7D1CFCCBFAFABAAA9AFB7ACC3C3C0BAB4B4C4E9E4CB9974594F01FEB05A07071800747675666369728FB4AFA08877696E87ACE2FFFFB86B4244619DDAFEFFF09F50333E7BC6E8EFD08D3B17245984A097927248231C2B669BCEE0D9C89E61240000012D5F8DA1CFE1C6872F1313388BD8E8F0E2E3D29442233E86C1D8D28934215B92915F738E975617072360A9C9CB9852120000000000050C12140F1D2220292622242C35403E3C4C525049504A525C56546162646168655D61625A5C5454594570BEE7FCFFFAF0D5B9762F19282B458DC4EADEC2995F51523A2F4286ADACA068311904193C8BC6CBBA72836A6B73A0C7D3D9C3AF9EA7A1AFBBC4C2CBBCB9B6BAC4EADEC2995F515201FEB15A070718107D79675F5F70718CABB5A8896A606E89B8E3FFFFBB724A4A659FD0F4FFF19C52314281CEDADFC4853A1C3164979C988F724725142A5FA4D4E5D6B8995D1E0000022A5393A9D6DBC88233101F458FDBF2EEE4E8DA91412A3A82BECAC78231235F9B926662859461210B2E5FABC8CA9359260000000000000006131514231D2926223231363C3F404D4D57515647495760615C595F57566065615D5A5C5555554270A4E3F8FFFFF5DAAB7D4211192B4585BFD8E3B7916D4E49352C3B7DA9B0986A380E0C173B84C1CDC159836B63759AC3D7D4C5ADB0ABB2BEBBBCBED5C9B9B3B8BFD8E3B7916D4E4901FEB25A070718207370676B616B758CAAB5A3807067728AA7D7FFFFC8794A47679DE0F6FFE79259314983CDE3E9CA803C19265287A499976D472E1A286098D0E6D3B4945A190600001E5B8DAADDE4CD88340D154994DCFFF5E6E7DCA040203B7FC5DFCC8A2F1C598D9D5C5E7E8D5718163265A5CACB9E541B000000000000090E151D201F2226252A253238393238434948484B4C535B5963565F605E5B63635D5C5D615655533E8BB9F0FFFFFFF6EFCC853D1723304C96D2DCE0C29B6F5A4B3D383E80AFBE9D6E29140611397BC0D1C26890685C7D99C7D5CEBFB0A6ABB2BBC0BCC7C9C1B8B4B4D2DCE0C29B6F5A4B01FEB35A070718307D7F746D5C6B7A8AA8B8A894726E6A84ADE6FFFFBE6B4F46619FDBFFFFF197542F3571C1E7DCCB8B3814295D9EA599886F44200F1B5998D2E1D5C59C5C19000000256391B2CFDCC9823819133B8CDCF3F6EEE0D3914320448EC0D7CB8833215C959258599397581F0E3059A0C3C4A156260000000000050C1311151D12201A242A282F32333C3D43414E4B4F4A565E615D565B616562615956565959565459466FA8E6FFFFFFEFD5AE78341B1C244585C3DCDED09F7E68573B2B3A7AACBCA05F2B0B091D3E87C0D1C1647C72636C9FCDD5D1C2B2A6A8ABAFB8BEC4C9BFB3ACB3C3DCDED09F7E685701FEB45A0707184077737572666C758DACB0AA86705C647CA8E1FFFFB269413C659BDBEFFFEA9153313B85CBE6DECB8A3C1A295B8D9B9B876C40211221679DD0E5D2CC935F280000062C5A88B0D2E6C9853813184287DBF2FDE3D5CA9E41203583C5E1CD8034255C9F9869678F9452170D3264ACCACB965A1500000000010A060B131617252723232828292C343C4042444C565444485C575554665E6068625F625D57555F4E564281B1E8FFFFFFFBE5BE753A2526234E8BC9DDE5C79C6D5E543D2E3D80ACB39E672A150F154086BEC6BC687D7963719EC8CFCFC2B5A7A1A6AAB2BEC7D4C9BBBCB2C9DDE5C79C6D5E5401FEB55A070718506C7570736E6B7D95AAB5AE9273686A89B3DFFFFFB26A4B465DABE2FFFFEA9755303D7DC2E5E4CB813D1D2055949DA1866D4C211424559DD1D7D4BC99591E0000092D6097B3C8E1DD86350F163E91DCF9EDE2D8C99038244495CAE8CA8A32275C9890605A87824714052C649FC1C9A15C2200000000000008131412231D2D2C1F252B2F2F3A3D3F3E4852514F4E4F5655565B5B64595C5F616261605B60544E3B6EADE9FFFFFCE9DFBF77301420354A8BC8E4E6D2A175463C38283C77ADAB956F331A001A4891C5D1BE5E876D6277A0CEDCD7C6ADACACA7ADBDBFA5BCC4BEC0B5C8E4E6D2A175463C01FEB65A0707186072736E6A6267818FB1B1AD9877617087ADE5FFFFB76E414A6494DAF8FFE0995536427ABFF0ECCB853E1B285D95A39A9572431D16195598D6E1D6C19B5C1E0500072A5C92A7D3DCC9922F13194185D8F1EEE5D7CDA041234990BFE1CB8832175F9D9C5B65898A521B0B2965A3C4D49B571800000000000A04131010172123252824292F353948463F4F5243484648555A6059615A5F5F5E5F59615C5D5A4C53438BBEE6FFFFFFFFF4CD7F3A1925355398C7DFE5CCA97E5E4D432D467CA8B6B474361B1412448AC4D4BA527B7460749FCBDBD8C5B3A0A5A4B4C3BCCCCBC1BFB7B2C7DFE5CCA97E5E4D01FEB75A07071870767E7B7467677D9AA8AFA6846F666B87B1E9FFFEC0794E4F629EDBF7FAE69C4E304179CEE7EAC88D4322276099A5A78962381B181F58A2DEE1C7BE8D5325000000215A8BABD1DFCB883708164897DEF9F7EAEAD198401F3484C4D7CB8336275A9595636898A0591F142061A9C4CA9856140000000000030E0709111F20242026292F31363539404C4F5A4A4B4F545654564D5B5D636265625F5B555A5C5055427ABBEDFFFFFAF7D7AF7D38141C214B8FBFE9E7BF9D7056493A2F387CADBEAD6D33140C133C88BDCFC55D7B6A807D9EC6D5CEC4AEA9ADB0B1B7C7D0CEC2B2B3B2BFE9E7BF9D70564901FEB85A070718807272696C5F686B96AFB09F8466616784A8DDFFFFBD6C4C486391DCFFFFE7A058314484CCEFF6C8863514225D93A49C8F6D3D18092560ABDEE2D0BEA0541100000729578BACCFD9C286420F113A93DFF9F1E5D8D0964225408EC7DBD0812C2D60AAA06A65888B4611053069A2C9C59F631B0000000000060B0E0C1C16121B281F262A2D2D3B403948484A4A4A524F55585B625A61635F61625F6563625855544B7CB7F3FFFFFFFFE8CA813D24243D5698CCDBEDCEA66D5D5246304380B4B9A26A300F010E4385C1CEB55A80626375A6CBD5D9CAB8A7B6ACB1BBC5CDCBBDB6BDB0CCDBEDCEA66D5D5201FEB95A070718906E71696C6A687A8DADB5AE8B635E6A88B0E6FFFFB97649485A96D3F0FFEC9E583F497EC5E3E3C58844172856899D9E836D3F1E162661A5E1E6D3B5985813020006295B88B3D1D7C582370A164586CDECF2E7D7CA9743275192D4DBBF7A2E1B50968B5C5D8899521B0D31649FC7BE98641D000000000001060C131D1C1C252422262E2F363C3C36384E4C50494A4C566359555A555A666D635F5556615855523E79B6F7FFFFFFFFEEC17B381D2524448ABBDADFD29E715C4937304480B2BB9D672B1008153F7DC5D8C25B86685673A1C4D0D1C3B6A3ACADB8BBC2C3C7C7B9B6AEBBDADFD29E715C4901FEBA5A070718A0827A736E5F6B7894AAB3AA8C69636586ADE0FFFFC57146385295D6F4FFF59B5A2F4786C5EBE3C4884013256498A4A18D6D3F1F132760A7D6E2DAB3995516000000305A8CACDCDBCA763118143A8DD5F3F5ECDFD2983B254490CBD4CE812C285B9791655A92904C0E153268A7C4C5A55E2001000000000005180A0E151E282529282F352F353B3B3E49504D4B485058595A5B595D64676351565A635F565B54486EADE9FFFFFFFAE6C1813A1821285290C3E8E4CB9E63584B4433427CACBA9C6A2C0D06173E85C6CBB763816F6A70A1C1DAD1C6B4B2B3B0AFBECCC7D8C0AFADB4C3E8E4CB9E63584B01FEBB5A070718B07A79737567637D9DB3B9AC8863636686AEE3FFFBB66A484E6B9CE1FAFFDE9A4F374181C4ECE1C2843B1B1B5A8A9B9A8F6F44231C2665A5D7E1CCB68E521D0000002C6694ADD7DEC5863B17173A88D6F1F6E8E8D09744213B89C7D9CA6F2E2063A08F5A61848F511405296DB5D1D3A5652600000000000F150D10162015202926232A3135423D3D48504E454E4D4E545C5F58545D5D656168585555575C5853407AB6EAFFFFFFFDE6C18538141C264C8FCDDFECD1A27453513C2C4482ACBA9C6A351709033685BCD1BA5D7E6D687AA3C3DDDCC9B0A5AEB1B6C1C0C1BFB7B8B5B3CDDFECD1A274535101FEBC5A070718C0766F67675F63758D9FA9A08D615C6782ACE6FFFFB86D453E5A9ADDFCFFE3894B30477DC4E1D4C3883C132C6AA0AFA98A6D422513315D97D0DED3BF9D4F1B010000255F91ABD8E8CD833911174793DDEAF5E7E7D28B4422408DC3D8C17F363163A295605D8D8F5818102D64A9C4C59D5315000000000006091314151C151E22342C232B3235404646455048454852585D5C5E5A60666B5F5D5B5F5B554E554F3A53A9E8FFFFFCF7E9C27839132A23428DCFE7E8D3A061554E432F437AA9B7A16A35130D103381BFD8B5646F6765709CC7D5CDBFB2B0A3ACB6BDBCC5CEC0C1B9BECFE7E8D3A061554E01FEBD5A070718D07E6C686A66647891A9ADA686685E6C85B3E6FFFFBF784943689EDAFBFFE0934D313C7BC1E4DABF893E192C648C9D988C6D4022152A5CADDEDDD0B797581900000321598EA4CBECCD8A3A1614458DDCF6F9E4DDDA9649204089CBE9CB7E2C1B5BA09266678B904B12123066A3CFCB9F59250000000000000D12131917171B282B27262932383C424A47554D484D48525C5E65615E5A53635E5558525A5B574F4366ACFFFFFFFFFFE7BE7F3E1D2F334D91D4E5E1D3A26D57524131447EADBC9C69300902113885C3DAC06C956A4E729FCDD5CABFACA8ACA9B2BABEC3C9C1BBB6B9D4E5E1D3A26D575201FEBE5A070718E0726B6E6C5A647694B0B2AC906C58638CAEE2FFFFC16A464861A4D4F5FFD98B4E2E478ACFECE9C27E3F152D62909889816A3923162A67A8D4DACEB99A52080000042A6089AAD8D6C1763B1A1F3E98DCF8F6F1EED49240224183CADCC77B26195BA19564648B894D1A0A3671B7C5D3A45F12000000000001051619161C1F2B1E1C2535412E40424847474C4946414D58505255535C605D6363665B5B5158504E3E83B8EEFFFFF5F9DEBA77370B262A4893D0E7E3D3A26A554B37273D78B2B79B703611051E3B88C2CDC15473626288A2BBD7CFCBB2A6A3B5C7C2C4C7C6C5BCB3B5D0E7E3D3A26A554B01FEBF5A070718F0796C6F745D647E97B5AFA7916A63667DAFDDFFFFB46846465F9FE1FCFFEE92543B3E88D0E6ECC18944172A67909C9490653B1A092A64A8DEDFD3C39A571800000129698FABD9E5C5893C0F173E89D5F5F5E5E1D7963F233685CED8CE83261B57978F5862838E541C093067A6CCD2A35119000000000002000D0E191D1D2326282A2A283A3F47473E47524A4F4551515259565F6165635D6059555C645E53544576B8E9FFFFFEFAF6BEA533171D2B4B8DCBDFE6C69776554837313981ACB49D672E1506043F87C1CCB2577D6F697FA1CBDACDBBA3A4ACAFB2C3C7C3C9C3BFBBB9CBDFE6C69776554801FEC05A07071800727175706B697994ACB3AD9270696D90A6E0FFFFB46042425FABDAF6FFE286512F458FCCE7E1C4804315265FA0AA9E866342161B2160ABD6D4CBC29B5415000009315A97A5D8EFC4813A0F1B4388DCF6F6E5DCDA94421F3788C4D2BE7A291D63AA8E555E9397520D073668A0C5CD9F5E18000000000003070E0F121A161F293331322A34333940474B464B4E505461585655575A5B615C5D5D565D56644F4B4276B2E6FFFFFAEFE3B26D31182C334B8FDBEEE4BFA3685540372D3980ADBBA3692F0303193B87B9D0B85A836F646FA3C8D0D4C6A197ABAFB0BACED0CBC5BCB5AFDBEEE4BFA368554001FEC15A0707181071786E646B647798B5B8A58865626C8CAFD7FFFBB266444B679EDBFAFFDD8C48254488D2E6D8C58A4120275F90A79D8A66391C10245CADD5DBD0B798560F0000002B628CB6D8E3C17F3E19124290DFF1E7DFDBD79A45233D94D2D4D4822A1B5D9C926763878E4B0E05256BA3C1C59E61250000000000030E0A0F1C1E1D1E212B292D2F3237373E4A4B54534C454F56605D5957574E63645D5B58596352474A4670A2DFFFFFF7ECDAB277311012243F8ED5E4E9C59D694D45362F347AA2B79A6C370E09113B84BECFB95B75696377A6CEDAD7CCB9A9A0A2A9BBC3D0D1BFB1AFB8D5E4E9C59D694D4501FEC25A070718207E76706D62657589B0ADA483635E6E81ADEAFFFFBE744B3862A3D8F6FFE1904B2F438FDAEBE4C77B3811275B9FA3A3915D311E16276B9AE2ECD0BA984C11000000345F90ABCDDAC688280B1B4A8ED1ECF2E1E2D298381E4494C7D2C67B2C2B66989561698F864914083172A9C6CFA26B2800000000000401070C161B1F26292F2A2D2E33403D3D4046514D4E4E4E585E5B5D5E595F565A5C575C544E4F51513D70AEDEFFFFFFFEE7B876331A252A4A93CCE1E2CC9D6C4B493C2F4A89B5BCA16423080B1D3B86BECFBA5266635D6CA5D1E6D9C3B6A2ACB3B8C0D1CECEC4B0B2B4CCE1E2CC9D6C4B4901FEC35A070718306964605955587083A1ADA18865505C86B1DDFFFAB55C43456EA7D3F2FFD78D442D3E82D0E9E2C6832E12296799AC99836B3518132366ADD7E0C2C38C500E000003306090ABD7E2C1813C171D418BD1F2F7EAE2C19047214291C2E2CA73261E5DA292605D949146120B356FB0C4CE9C59160000000000060E1012112226262028242A2D343136434348594F50455053565A5058625C5D5F5C58526161594D4D4A71ADEBFDFFFFF0E6BD703913182C4B87CAE6E6CD9E624C48432C4383AEBB99632E1811194285C2D1C054766F6970B5CEEFD8C0AB9DA4A4B2B8C0C5CCC3BEB9B2CAE6E6CD9E624C4801FEC45A070718407274706D646B8092ACB29E857166678AB2E8FFFCB262444669A1E0FFFFE4864531427DD5E8E7C7813D132167929B9992643C19182A67B2D6EFCEB48A4C110000002E6B93AAD6E4CA87330B193F8EDDEBF2EFE1D5974420468CC5D3CE71252765A5905D648D8C45100E3273A3CDCC9E561A000000000000141312191A141C1A21222D32323E3A38464C4D4E4A4347565C645B595D6263686A5D5B5D5E58574C3971AEE7FFFFFFFCD8B176401B1E1C4D94D3FFF1D29968513C342D3A80B2AE9A6929150C164884BDCAB85A7567607DADCCD3D2BFA79FA6A9B4C0C7D1CEB6C6B6A1D3FFF1D29968513C01FEC55A07071850807975766B6E7F96AFB9A484675E6A7DAFE7FFFFAF6943426EAEE8F7FED7904D30437DC8ECE6C07A3C1A285E99A5A284623A2318276AB4DCE0C4B9994B0C000007316A8DA8CEDAC3782D121A478BDFF4F8ECDAD28F3B1F3F8BC9DBCD7A2524619B8D5C6A938F471009336EAEC9C799571100000000010905131A1C1A1F221D1E252929343B393E4054524A494254615B5D5A5C6162615F5E5A55555656464F427DBEFFFFFFFFFFE3C784341C23274B93C8EAECC99767514D45284089B4C09C72301008162C8EC9CFC35A836D6686A5CFD8D6BFB3A5A3A7ADB9C3C7CFBEB8B4B7C8EAECC99767514D01FEC65A070718607C6E6B61606B7DA2BBB39E8068666483B5E3FFFCB56A4441649EE5FAFED7864E26417AC3E3EAD1793A1C306FA0A492815935160F2B6CB8DCE4D2B98B4E130500062F6596BFD4D0C27B2A151C4999E4F3F8EAE6CC8B40194189D2E2D0753323629A8F61688F92511917346FACD2CF9A57160000000000010A0E1117201D1E2A1A1E202D3B3B3D423D44474446404F575A5D585E5D6160585C6061615D57504B4381B6F3FFFFFFFFF0CF842B131F365490D0EDE7CFA26450463B314285B7BE9C642B100A1E4594C7CEC15F8069637FA9C9D3CFBDA69BA8BBBEC3C9C7C4BAB9B1AED0EDE7CFA264504601FEC75A07071870726D635F5D687090A9AEAD8D6B676A83A5E1FFFCAF6F494364A9DFFFFFDE894829428CCBE3E1BF7742192A60A3AC9A8D61381B192E6EB8D5DAC7BC8E410C000006296B9EB9D5CDC37F31101E4191DAF1FAEEECD38C391A3D8AD1D6C7722A2265A0925865998C49130B2C75B4C7C5A15E22000000000000001213101723221D2A262D2F2F383C3C4B4A4D4F504E58525A5954555B5A60605F5958595F55564E437EBBEBFFFFFFFBE7BD722E151C2A599BD3E3E7C3986F5043372D3A7BA8B4C7722D0D01103E86C1D0BE577669686FA2CBE3DAC3AFB1ABAEB4B7C8DACFC9B9B3B3D3E3E7C3986F504301FEC85A0707188070736766646C7798B3B4AE8A685C738AB2DFFFFFBB6A444464A8DDFFFFC783452C4085D7EDF0CA783419326C919D97845A3318152C72BEDFE2D2C29547090000052C6A9BB5D3DCC077351414418AD9F4F5E6E7DD913A1E3F92D3E3C9782E215E9992606C8F8541130E3673AECBCA946121000000000000070B100E1F20171B202734373E3D3C464A4547454E46555C5555565B59596063625C5D5E53544E523F7DB3ECFFFFFFE4DDA5703B2424294995C7E3EAC59D6D494333314581B7C3A465260906174188C6DAC7617D6A6575A1D5E4DBD9B9A8AEB0BBC6C4D1C0B7B4ADADC7E3EAC59D6D494301FEC95A070718907C726C65575E7790A8ACA1855F636E91B0EEFFFFB45A3B455DA2E0FEFFDE854026428BD1E6EBC77C3A1A346BA7AA9B825D2917142F70BADFDDD2BD95460C0000042A658EB0CAD2C2713714194A90E1EDE9E1ECCE99441B418BCDDFBC6E29226097995C608E8F531B193E73AED5D4A45620000000000005121819191413111A1E2226303736364446484E47474F5450565865665C5D635A595B5C5D5F525152407DB4F4FFFFFFFCE2B16E3A1B212B4497D6E4E4C8A4654E473A314083B7B39D624F1501124182C5D8B75679665E7EA7C6D5CEC4B3A6ACAABDC2BEBDC3BBB8B4BCD6E4E4C8A4654E4701FECA5A070718A07170625B4F58738CACACB48C6460688AADE8FFFFB26B484970A3DCF4FFD4823E264E8BCAE5E3C8732F122D669AA68A8367391C0D2962B2DBE7D7C18A400A00000C325E8CB2D8DAC37A3111164F98EAF4F2E7DED18B48234688C4D6B775332F6B999366729A934912023878B3D0CC995919000000000002080E0C17221F1C1A262A2A363130383A3B4B504E45404A505862575A5D5A5967615A575C5C5B52503C78B8F3FFFFFFFFE6B672312623033C90CDE8F1D49F6E553B3932498ABABD97682F10090E3B84C7D1BF5988746B81A3CBD6DAC8B2A6A4ABB9D9CAB4C1B8B1B2B7CDE8F1D49F6E553B01FECB5A070718B0797D716F686B7C96B5B5A98A6D5E6990B7E7FFFFB16A3B4569A7DBFFFFD27C43344A8AD5E4E2C57E401733739F9C8A81622E170F236EB9DBE2D8BE824809000005266D97B2D8E4C2782E11214297E5FAF2E5E2D4993F1D4891C3C8B278231F659F925F689D84421513416FB7CBC89E541A000000000007100E0C1C1B19221C1D20292F34393C3F4149524F4F515254595A5E5D615A6C66605D5452574D4D4D3F70B2F6FFFFFFFFE7BE742D1E2F2F4896C9DEE0C396644D3A3923448BBCC79D5C270B000D3E88C5EBC33E74606687A7CDDDD5CFB3ABADAFBCC8CBC9CCBDB4B4B4C9DEE0C396644D3A01FECC5A070718C0746E68645856769AB0B8AC8562606D87B1EFFFFBAE5C36466DAADCFFFFD3855136418BD2F0E9C57C30163469959F947D553817133174C0F0DECCB48840100000103B6F96AFC6D5B175341E1D4499D6E8EFE8D6CB8E43234489CBD4BE762C295FA7935C65848C4D0C0A3872A8CCCB985A1300000000020F0F11151C1E1A1A2026242C272D3B3647514D55514E4D494F5B5D5661655A5852575B595D6058585A406FA9E8FFFFFFFFEBBD7A3419211E4899CCE7EAD09D634449431E498CBCC19C692A0E0021478EC7D9BD52776B63789CCDDFD8C7AEA7AEADB7C1C6CCCDC3BCADB2CCE7EAD09D63444901FECD5A070718D07A7F665C5A5A708BB1B8A9856F616579A9E7FFFDA9633F4969A0E5FBFFD4814B2B448AC6E7E0C67A3013327798A197825B351B152D6CB6E2E5D4BB8B4309000011376899B8CFDDC577280B16489CE4E9E8ECE3CF953A263B86CBE4C6762728659F975E6F97914317143B70B0CAD696561F0000000000020110121D2520201E2823242E2C373440465050474F484A595D56515A595965625D595B5D5D584F533C7BBCF5FFFFFFF8E7B77A3C3C2E334C98D4DFECCB925944463D35477AAFB998622709041E4988BCD2B753756B6E79A9CCDDC5BCADA7ABB6BCC4C5CCCFC2BAB1B3D4DFECCB9259444601FECE5A070718E07277686E60647690A5B7AA7E61666F8ABBE8FFFDA56C3C416BABEFFFFFD0793B2A4B94D6E8EEBC7029162E6C9AA3998561341C123871AEE4DBD2B280491500000F2A659BABD4E5C8722A0518489BDAF6EEE3DBD08C39204990CCD9BB6C2827639D906168828B3E1A0E30789DCBCE9B58170000000000140F0D1A1E2520251F27252429362D344347504E4A4B4E4F565559625B5D5D6262625D5B5650564450398ED0FFFFFFFFFFFCCE8C49262D32529CE6F3E9CE9D724D4737395592BBB097663014121E3F89C7CCBF5F7566637FADD3E2D8BBA9A0A7A5BCC1C6CDD4CABBBFB9E6F3E9CE9D724D4701FECF5A070718F06F7372685E647487A6B2AA8D6A647383B6ECFFFFAF5F424361ACDEFCFFD37E4625428BD7E5E1BE6F34202F69A1A1A3835A32160E2A77BDE5DCD1B090460D0000103F7399ABD4E2C46F2B131D3B95DFF3F2E1E7D28C3D214C92CDD4B860201F6FA38D616D8F85431010397AAEC7BE8B521700000000000A0D151B131623221E221E282B2D31373F42465152504A5C56585C5F5D68655A5E595D58595A514E493D80B7EAFFFFFFF5E4B87247232C325594DAEFE6C4945A45463E334B83B2BDA25A250F041A3C84C1D2B85881746180A9D3E4D6C8B4A3ADAAB3BEC4C5CBBEBAB5AEDAEFE6C4945A454601FED05A070718006A686E625D5C6A92ADB5A77B675F6B85B0D9FCF3A76643476CA4DCFDFDC97A482E4A97D4E2DBC17D361E38749EAC9B7C5B2A0D1D2A67ACD7DAD0B887400E000002326EA0B9DADFC571300F1D4EA0EAF5FCDCDFD692431D428FBBD5C86D281D6AAB9B5F6C907C3C08193C7DB5CFCA93510E00000000000011110717141B22262B262D30343C373E474852524C4D49515759565D5355657162595F5C535252523F73B6ECFFFFFFF2E5BD70361A222E468ED5E8E4CF954F413328293A82B5BD9461290B0819478DBACCC05D7C686279A9D3D6D1C6ABA6A8B0B2C2C4C9CBC1B9B2B2D5E8E4CF954F413301FED15A0707181070706D615E637196B5BAA180655E6F8BBDEDFFFAAC6044446FA4E6FFFFC8773F234796E1EFF2C86D33182969949E8B75522E12132B68B2E8E8CAC3884A04000006387298BCD6DCBC732B05144B94E5F0F1EADECD9243234493CBD4C1701F2869A68A5D6B8E81370B0E3C76B3CDCDA2551D0000000000000110171425202224261F272834383D434E454F4D453D4B57605E5A5D6755625D5D5755505B56524B4176B6F2FFFFFFFAE5C47C361C2A314A9AD1E4E2C69A68483F37344E89B8B5A862220900144090C5D2B65D7C615E7BADD0DDE3C5B1A4A8A6B4C0C8CFCCCABE98A7D1E4E2C69A68483F01FED25A070718207C746F705D5D7392B4B6AB7E5E5C678CAAE2FFFDAE5E414B6DACEBFFFFC1743E2B4384E3FBF8C67336103269A4AC937C602B0F11356EB0DADECCBC84390A00000F38709AAED8DDB16E2A111D469ADAF9EAE6E4CA923E2A4D8ABFD4BD66262364978B5C6B9A964B12123E72ACD3C396501D0000000000080E10120E1B211F2426282D3A3136363E4249494A504851575D565A5F695D5864685F5F5E5B5352523D74ADECFFFFFFF1DFBB5E2A1220284B9FD3EAE3C09662493934334690BBB897691F1008104087C2D2BE6379696B74ABD3DDD9C9B09FA2A0ACB0C8D4D2C5BAB6B4D3EAE3C09662493901FED35A07071830746C6B5C554F7391B0B3A07B5F5F7188B8EFFFF29D5A373F64A8D4F6F8D684452B4492D8EEE8C37A361834729AA59A7B592E161C3377B9D7E5CDB88445020000003476AAB6D5DAB3772D10164897E5F2EBE8E3D3943C1B4994C8DACB6F212573A498616B97813A0B04367FB6CACC935D12000000000004131A1B191712262524262B2F32373E404445434647494D5B575B58565B55595F5E615C5B5A5D5251427EC1FAFFFFFFFFEAC27A3A18262D4C9EDEF5E9C79D6856433F324184BABB924D14000A13468CC4D8C25F77626579A9D8D9DDCDD2A5A3ADBBC2C8D0CBBBB1AEB5DEF5E9C79D68564301FED45A07071840807B78635D657895B5B4AA83645A718FC1EEFFFCAE6442466AACDDF8F4C47D3B2E4C7CCDF0EAC5742812336DB6B89E8658351C102E74C0D7D6CCB98B410900000D3C77A9BBD7D3B275260F204999DAFBEAE4E0D98B3619438CC7DEBB6E2B2378A58E54628277400A0C3A78B5D5D59D5B0F000000000009060C161514192B1D1E2E242D3B36364346474F4B4952485861605F5D576163655F5B67625858534E4079A5E5FFFFFFFFE5B97330251D264894D0DEEAC992624F3E2D375097C1B9995C280A0115439DD2D5BD50785F6278A1D4CCD3C8AEA7A7A8BBCED3CAC1C6BDBDBDD0DEEAC992624F3E01FED55A070718507E7C6867515C7B8CAAB5A280605E7093B1EEFFF3A1543F446EB5E1F7FFCB7C452F509AD3E6EAC06F26102C75A3A5907A562418193171BCE3DFD2BA894210000010357296B4D3DFAB6A2705194D95DBF5EADFDDD288371E4393CDD9C06C3025689E905E68919143180E3471ACD7C9944F2700000000000813131215181F211D281F21302537353B43464B464F4F56615D5B5053535F61605E5958545E5457543B88C2F3FFFFFFFFEEC871372630225EA8D2EBEACA9E5F4A3B3D394F90BDC1985B271601114795C5CCBE5779736967A7D2E1D9C0AEA3A7A4BAC2CDC9D2C4C1B8BDD2EBEACA9E5F4A3B01FED65A0707186079786B6855698098ADB2A8825C5B6F8CC2F7FFF8AC57393F64A3E3FFFDCB7841294799D7DCD3B67828172F72A2A192814E251B0E3074C2E4E5CDB37E480C00000C387AA5B5CCDAB170230B1E4C9CDAF1F2EBE5D5953B214C90CDDDC96D212064A38A5B6D91843E0C144479AEC5CB97601A00000000000B1019191A241E20182024253030384047504C5355484D4F5B5B57545F5E58625F5F5D5C56575A504C4374B9FFFFFFFFFFE4B677371D252E4A94D7F0EEBE8E5A403E38345090B9B99658210F0D1D428DD6DBD0607B6A6377A9CDD4D3BFABA0ADAFBCC7CBD6CABBB9BAB5D7F0EEBE8E5A403E01FED75A07071870716972605A5A6D89ACB4AB8E5F53638EC1EBFFF4A65C374165A6E9FEF4D074442A4995CFE7E1B67034172D72A3A9987E582D140E357BB6D9E1CFB18742010000083977A4C0D5D5BE752C0B1C4888DBF3EDE1DDD3923A214691CFDBBF6C1F2172A78D5C6C947D3904104389B7D2CE8C47110000000000090911130E14262628252338312F33393D3E4E4F4D484A4C4C525C585D6461665F5A56545E574E4B544679BEFAFFFFFFFFEECA79332C33365994D6ECEEC9935D4C32343C4C8DC0BD9E5E301500195090D3D5C3567B6C6881B4D0E3D2C1AD9CA5A8BFBDC7CFC4C3BDB5B7D6ECEEC9935D4C3201FED85A070718806D7469615A557597AAB0A97B5A5F6A88B5EAFFF4A7664A466FB4DFF8EFBC6E3E2C5399DBEDE3B46C2F1B3C78A69F8A744D33140A3573BBE8E0D7BD843A0A00001139789BB2D0D2B781351319479DE2F0E9EDE2CC8A3A214891CAD8C569242872A1895C698C7C4811153A82B2C8CC9B6016000000000510100C171E201F241A1A1F2D292F383745464F4F484942454F54645C5C5E565B615D6359565D5A504B4486BBF7FFFFFFFFF9C07B381D322F4D9EDDEEEACF9D67523E42375191BBB29B5929090B144A8BCED8BF5C7367667DAAD5E3D1C8ADA8A5ACB2C0CFD0C9BBB9B8B3DDEEEACF9D67523E01FED95A070718906F6B6C63555A7893ACBAA97C5C596B83B0F0FFFFA157414A6CACE2F1FAD3753D274193DCE8E5BD792F162C75A8A598794D29110D2673BEE6E5D1BF84370400000C377CA4B0D6E1B46A220D18539DE2F7F5E5D9D08C4124498AC6DCBF5F241C68A39C6169947E3E18164479B4CBD39F54160000000000000E1116111B1B221F26252A2829332E3B3F425951464C4D594F5358555D596B555C5B5F61585B51514684D0FAFFFFFFFCE1B4762F151D26509CCADEDCC5905544312F334797C3BF9559250604204098CCD3BF5F8274757AABCDE0DDBFA5A2A6A1ADBBCCD0D2C9BAB8B7CADEDCC59055443101FEDA5A070718A0736D696054566D92B1B7A38663526692C1EDFFF5A8633F426AB0ECFAFAC9753D305196D2DEE0BA722C183676A7A79D7D552209142F7ABAE4DEC7B7803A050000073C7CA3B2DCE2BB6C3013164A9BE3F7F0F0E8CF863C244993D1DDC378201F6AA49460698B7A2E0F0B3677BACECD97561800000000010B1D0D17111F15191D1E292432313740423A434644424646555862625C536565575C5D655A5A59564B4680C2FFFFFFFFFFF3BE7F3720302850A2CFF1EAC58F61493F3A334F8FBDB8965C240F0C204693CBD8AC557E606172A5D1DCD6C0AEA6ADB1B1C6CDD0CFBEB3ADAECFF1EAC58F61493F01FEDB5A070718B07C6E6C66585C7583B0BFAC81675B698BBAFAFFFCA7553A4163ADE4FFFFC56633244F9CD3E5DDBF6C330C3875A6A99A7C4D260B0A2F70B0DCDEC8B58A3E0900000F4176A2AACBD1BF762E141C50A5DAFCF2EFE6D488361E458EC8D6C1752B2D719C91696E9484410D114089BAD5C5864D11000000000000060D1A14181C28251C272A283942403F464654454742515D5A5C5A5F6264695F62606152575548493C79B3EFFFFFFFFAE3BC73321A20224A98D1E7E3D19258434636355A8AB2B99453200B0B144284C0D5B6587A615F79AED2E7D2BCACA0A6ABBAC3BBC6C2C4B8B5B3D1E7E3D19258434601FEDC5A070718C0707B6F5E56627292A9B3A07C584B648BBCF4FFF7A8553C4266A9E0F8EBBB773F2D4C95DFEBE5B2722E143577A4A0917C4E291605276FB4D3D7C5B98840030000103976A4B7CED3B4642511184DA7E1F8F4E9E3D0873D225493C5CFB46925296FAB95657993853809113A78AECCC79455150000000005091B0E11182A22221E1B24232B38312E3F434E5350544A4956525E5568615A5E5D4F5A5F6056595053437AB7EEFFFFFFFFE7CB7D3F1320294E98D9EBE7CF965645332F375896BBBA9550190D07184295CFDBB75C81697083B5D4DED9CAAD9EA5A6BBBFCEC6C7C3B8ACBAD9EBE7CF9656453301FEDD5A070718D073826D6A57546C96BCB2AA835A55608DB7F2FFEEA5553E3761B2EAF2F9C976352B519EDFE7DEBB6E281B3972A2A4997951230F133176C0E1D4CCBD823C0C00000F3F7FA2B7D6D8AA6A290A10509FDBEEFEF1DCD896361C4190C9DFBD6F252A6B9D8B6870997E3A0D08387EB8D8DB9B5416000000000006101D13131C242222202A293032323D3E424852514D4B505350595D4F5C5F646B615B5E55555658564278B9F0FFFFFFFFE6BB74391B222D4B94CDEEF0D39B5B3F363A345B90C0B69965270B061B428EC5CFAE55735E6581AADDE3DAC7B19899A1B2C6C9D4C9BBBAB9AECDEEF0D39B5B3F3601FEDE5A070718E07B7A6E626166759EB3BAA07F61536A87B9E9FFFBA55F3E446CACE9FFF8C0763C205299CFD9D9BD7027123377A5AF997B4D21090F3176B6DFCFBBBA8A490D000006387BA0AEDADFAF6726121A49A6EAFEEEE3E2D88340254794DCCDB467252A71A38D5E72987F380F163C79B4C7C99A561E0000000000010D101C211D1620211E232C2D2F363C414A45494C454649575156615C645D6661585F565354584D513F89C4FFFFFFFFFFF2C57944242F2F59A1DBF2F2CC9B5F483A33294D9AC4B995601F050517419BCAD4B34E85786E7CA7D1E7D2BCA7A4A9A7B6CAD3CACBBBB4BBB6DBF2F2CC9B5F483A01FEDF5A070718F075746B615C63799CB5ABA185654E6884BBEDFFFEA457333064A8DFF8FBC36A3C264DA6DAEDE3B36B2A18346D98A59280582C16103077C1D5CBD5B7874708000011427598B1D0DCB6712B171A5099E8FBEEE1E5DC8E3B14488FC6D0AC6920276E9C99616A95843514193F7CB2C6C99058180000000000050A0F0F14281F281D1822262C313133464E4C4943455157595E5D5A5965616164615856585B5854483F75BAEEFFFFFFFFE7B06E341B292A4B9FE2E1E3C590603B362B315597C6C0944E1D050612479AC0CCAF5E7F5E5C80B0DADFD5C6AEA1A5B2B5C8C7CEC7BDBEB4B7E2E1E3C590603B3601FEE05A07071800717C6A5F56597295BBBEA27963556985AEF3FFFFA95835436AB2E2FDF1C162362C469FDFEFDEB86A2C173676A5A895754B200B122276BEE2E3D8C28C3C050000053F799EADD1E1B7742A0F1E559EE0ECEDEAE1D6833821438CD3DDC06D2722729E8A5664967D340D134086BACBC69755110000000000020D16161A1E2C24201F2123272634363A43514942455050525B60565F60555B65605F625E5A5050553B72B8F9FFFFFFFFEAB368301E2D365CA1CFE8DBC394613F34343F61A1CABF99571807011A5095CCDBB0487161697BA7D6DEDAC9B7A4A9A3BAD2CDCBC4C2B5AFB5CFE8DBC394613F3401FEE15A070718107074686356627192AEB9A5806252648CBDEFFFF598542C3560A6EAF7FCC76F41385A9FCFE3DBB96F2814387DA1A79A7C55260C0D2F73C1E0D7C3B5853B0900000D3977A5B6D4D5B26D281026579BE1F8F1DED4D2913A1A4389C6DCBA6D1F2D71A28B5A74A3813B0E164386BBCBCF96531B00000000000C0E0F1A18251D1B22222D2A243130363C403E413E4348465150605A525A525F615B64605C555151523E83BBFFFFFFFFFFF0CC7B301F242B4CA3D9EAE3D598563A3432314F97C3BE8D521D080A194794C3D3BA4C72676885BDE3E2D5C1AFA3A0A1B4CED7C9CEC6B7B1B1D9EAE3D598563A3401FEE25A070718208687746153596D9DB2B2AA856450638BBDF1FFEE9C57374666B0F0FBE1AF6A3A304C9AD3E8DCC36E2E132970AAB1967B4A2610113280BBD9DCCAB7843D000000053980A2B4D9DAB36A28161E43A2E2F8EEF4E9D8903B1E529FCCD6C6681A1B70A892627195813D0B0A4287B7D6CD894F1500000000000B13181F221C20201F22212434362F3B3F4A4E534D4641514C52555C60635F58645C5A5F514D5552483E75B4EFFFFFFFFFE5BE763924252A56A1DDEDECC28D5039382E40518DBDB697551F0F0C203F8DC5CDB05D706D6878A9D9E2DEBDA899A5A5C0CBC9D5D0C8B5A7AEDDEDECC28D50393801FEE35A07071830746E67564B587A94AAB0A47A5A4C5F87B3F1FFF9A35038376AB8EEFDF1B565372E48A0E0E9DBBE6E2C10306E9FA2957A4F2619123372BFD8DCC3BD8E4106000007487E9FA8D1CEAB65260A0C45A7E7F9F2E3E2DB8F3D234F94CCD9C2621E2574AD9D6073927D3A0C154684BFD9C6915512000000000006111C140F181419231925252C3137353C484D4F51494350595A5952575B5C60635B5E585655594B57447FB7EFFFFFFFFFE3B075361E1D2A5E9CDFE5E8C58B56413029345097C5BA9651250903183B92CBDBB65D82706880B3CCDFD4C4A59BACAAB6CCC5DCD9AFAFB4B2DFE5E8C58B56413001FEE45A070718406D75706655576C8AAEB9A57E5E4C628DC5F3FFF7A95B373C62B1E1FAF6C3703A2C4D9AD2EDDBB9752F143577A9A7987945200E1D447DC2E4DAC6B57E370B000011407D9EB1D2D49F6B210A225BA5E8F1EBE5E9D58639183F8AC1DAC36D212672AA9265789278390D173E80C3C7CC974F180000000000050E111D1E1D1D182329272A2B2C3638404948474F564B52574F53565A5E59695E5C5D5654534F4D47478EC0F9FFFFFFFBE8C0712E152031509DDCEDE8C69D5C42332D32559EC8B9974F200C08144E92CDD6B65578665C80ACDBE7DAC7B3A0A7A3BDCBCECAC6C4B2AAB2DCEDE8C69D5C423301FEE55A070718507C6A6C5C565A718CACB1A27E5C526084B9E3FFF2A35A38446DA8DFF7F0BF71402856A1DFE8D6B571321230699AA692724B241B1F3C7AC5E0D5C0B47D39030000124A87A9B9D2DAAA591806124DA6E6F0F6E2D7C58333274096C9D9C65F242778A4955D779D843B171D4883BBCACF8F54150000000004071116111624172025242727232F3938404448504C4D50504D595B575759655C5E5D5B5551524E4F524183BEFFFFFFFFFFECBE7A3E292428449ADFF4EBCF8D5B4639313059A4C5B3925A170701174B9ED6D6BB5372595D83B2D6F8D8C4A9AAAFB0B3C0C7C8D0BEB8B5AADFF4EBCF8D5B463901FEE65A070718607774645C53567698B3BA9E755C4E5E80AFF3FFEC9A5134466FB1E1F8F1C271402B4BA3D5DBDEB66628132C76A3B1917350281114387CC0E5DFCCB17E3B06000014417CA4B7D7D5AB5C26121856A5DBF6F2ECE5CE8F35204596C8D5B466242F77A3916074A080350B144782BECEBC89461400000000010F15151B181A1A1B1C26222A282A2D38443D4B48474A46515A56585B5B5E57645E605C5D5C5F5C53494178C2F4FFFFFFFFE2BF81351E2B2C53A1E5F2F1C28958422F322E4D93C4C49757210C08195195D3D9B457766C657ABBD6DAD6BFB4A5A49BB2C2CBCBCBBCC2B3AFE5F2F1C28958422F01FEE75A07071870747664565159728BADABA48261606A8FBEF9FFF29C50353663A2DDF3EFBB6C382F5BA0DCF0DBB36727113478A9AA946C451C11142E7CC0D9DBCEB48239080000063A7BA3A8D7D8AD6B28162359B2E2EFF9F1E6D28E3A1F4495D4D6B0661D1B649E8D5F68957F310F114480B3D6CF9D591700000000000D19141C18181B1B1A20192126312D393B42444F4F465055505F5C58585D5E656867605A59595759554A8DCEFFFFFFFFFFF0B9713E1B342E5DADE2EEE7BD89564233363A5887C3CB99561D06011B4D94CDCDAE5B716C5887B2D6E3DFC5ADA7AFAFBBC1C6D2CDBDB2ACB3E2EEE7BD8956423301FEE85A07071880787D6D5C50607094BDBEAA75574F698CC4F2FFF6A34D30416EA9EFFFEEBC703829519EE1E1ECB863310E3878AAA7947E4A200E10397FC9E0DEC9B181360100001B4688A4ACC7DDB46424111E559DE3EEF2E2DECE8931145094CCD5BF6D21236EA7916567967D3415184183B5CFCF9052190000000003101B161A1B1919251F201E2A2D2D2F3B373B3D403E3E434C595958575A5E626365615A596158564E46447AC2FCFFFFFFFFE6B674381F252C5DABDAEBD7C18F594030323A559EBEB89153220007164F95D2D5B2557C66697EA8D2E7DAB7A69FADAAB9CDD6D2C7B4BBB8B8DAEBD7C18F59403001FEE95A070718907A7A706558667294ADAEA07B63646F88C2F8FFF5AA573B3868B1E4F2F7BD69352846A0D2DDDEBD652C142D7CB0AD9E734B290A123087C7DFD2BFB87F360B00000D3C7EA1B6D1DDAB6624171E4E99D8F2F5F1E3CF7C321F4387C8D3B76421256EA990637898813910154689BAD6CB94501400000000000612181D15171E1D161F1E2C3332383842484648504C44454F54604D5150595F675C5D57575C57514D4277B4FDFFFFFFFFF4BB722C222D3151A0E3ECE6C3985332362D3A5D9DC5BB9D5B130B0018459FD0D0B4516E595C80ADE1E3DEC7A89AA3A8C2C9D0D0CABBB7BFB1E3ECE6C39853323601FEEA5A070718A07F846D6167637E96B5BDAF795B4C5C88BAEFFFFFA35A44466EACE7FFF9B56C39345FA1CEE6E6C16B2B0E3677A4B2906C552D14103275B7E0DBD1B67F390000000C4685A1B7DBCDAC6C1D0B1A509FDFEDE2EAE1D57F38204A92CBD4BA5F1B2A6FAD9261779C7F2B11205490BED1D09A4F1800000000080E0610151616201F1D18222A2E2F2B2A373A404C4B4B414A505E585B4F636165675E54525A5A5C4F503B7AC5F7FFFFFFFFEDBC733A1A233557A6D8E9EBCA9157433837365F97BAC0934F1B0E081B4894CBD0BB547C6B6280B6DDE1CCBD9192A5A5BCCAC8D1D4C2BDB2B5D8E9EBCA9157433801FEEB5A070718B06D6A665A4D48658AAEB09F7F604E5689BAF3FFE99E57354670ACE2F7F0B7613A204BA2DDF1DEB76427112A71A1B59B7A4F2611213388C0E0D0C2B179330300000B4686A4B2D1CEA962230D1C59A4E3FFF5F4E2D88C3B26589BC3D6B5661E2E70AA91636A8F7737070D4C87BECCC195571500000000030D11171710121C191A252930242E393E3E43434D4D4F454E4D5B534E545F54645E5958555855514D524480BAFFFFFFFFFFE9C779421C283C5098CFEFE2C88B5336313638539FC6CD9E561D0F03104193CAD0B05578675E84C0E1DAD5C3A8A6AAABC5C8CACCCCC0B9AEACCFEFE2C88B53363101FEEC5A070718C072726D614D547586A2AF9C76534F6480BCF2FFED9D5A343F66B2E6EEDEB16D3C2958A2DCE6CFA9621D0E3A78B0ADA57B5025101A3987C5E1E3C2B77F3B00000012467DB6B8CECEA15E1C102B5BA6E4F2F6E5DCCB872F1C4996BFD2B8601B256BA2885B769D80350623508FC3CFC49A5319000000000006121F1E1A1C201E1F1A1F24262A333E414550594C4D474D58585653545C5C5A5F5A5554585B6351513E80C1FDFFFFFFFFF3CB7948213049518FDBEDE5C58C4B3C3134375A9EC6BF8C521B090C1C4D98C7DAB3557B666C86A8D2D6D6BBA5A0A8ACC4CDB4C9CCC1B6B8AEDBEDE5C58C4B3C3101FEED5A070718D06971625D5159738DA4A59F7D57545784BFF5FFED9B4E343E64A9E4ECF0B77A412F509BCFDEDCBF64291B3D7BACAE9873421809102F81C7E2DFCFB77D360B0000124483A2AACAD2A9641F08164CA2ECFBECE3DAD3893B1A4B8ECDD2B36B26327AA39660719478350D103B85B4D0C186531C00000000090F180C1C1F1E1023222523222C2E333D4146484846454B505656605E5E525B5963575B575D5C5650503B72ABF4FFFFFFFFD0AD6B2B17212E539BD2DFE5CF934D3F3833325394C2BE8E592208081A4281D2D7BD5476605F81B4E2E6D9C4A79AA1A7B4CACBC3D1BEC0B2ADD2DFE5CF934D3F3801FEEE5A070718E06D6A625A48546F93ABB1A27955506288BBFCFFEB954E413D66A5E1F5ECB7603031589FD1D3DBB2662615307BABA995664C20100D3086C1DED5C7B47C430B0000123C78A9B4D8DAAE6C2811154F9EEBF5EFE8E7CC83322E5298CFDEAD5F1B2876A08E607496763E0E1B3C88B8DDD193460F00000000000C141B13161C1A1D1E1C27272D2C3536323C4C504E4A404D5A5659525765585A5F5D62545B5854514A387CBCF8FFFFFFFFEBC0763D0F25335EA7DCEFE9C181544137373D5A9FC9B88E4E1903021C4D9ECBCBB04F6C596188B0DBE8E1C4B096A1B2C1C1D0D1D1C6B1AFB6DCEFE9C18154413701FEEF5A070718F06C696A5E494E6791A8AFA17354486586C5F7FFF1975339436CADE3E7E8B96536234AA2D6E9E2BA6421113081ACA997784B1E17183580B5D6D9C8C185430600000A458AAFB9CED8A55B22161C4DA5E7EBF7E2E1C5842D1E4B93CBE0B75D233779A38F606B8B752D0A124B90C5DBD18B521000000000000B1D1B1B182419201E181B212A2C3639393F42454947484F525E5D5C5C5658625F615F5B55524E50543F7ABEF7FFFFFFFBF1B16A371E2B3358A9E2F3E5C68C643F29323A5994C5C391470F07061D54A3CFDABA55685D5373B5D8E2DCC5B19CA4A7BAC8D4CECBBAB7B5ADE2F3E5C68C643F2901FEF05A070718007367685249566F81A6A89C76524F6391BEF7FFE8955137416BB1E3FFEFB167372756A5D7E5DEB56424122F79B0B19176472208102F7DC3E3DCC7AD742F0000000E4281A4BBD4DAAC601D0D1C4EB3EFFFF0DBDFD78638264F91C7D4B6611C267AA78C676B927B30111B4486C1D4CE8D501A0000000009091C1516181819141B261C23293036414845464A4040454A52525659625D696B605D66605A545D52574099D9FFFFFFFFFFFED1984C28314662B1DDF9ECCE9D5C3B343B3E609FC1C1975B1406101A4A9BCED0B55273676C78B9DFEBDAC7AC96A5ABB6C2D4CFCEC9BAB7B9DDF9ECCE9D5C3B3401FEF15A070718107A7A735F514F6F89A8C0AC845E566289C4F1FFF09F502B3861A4E4F9EDBD773A33569FCEE6E7B5642206337AB2B3956E4A270B134279C9E4D8CBB079310000001D4A81AAB2C6D3AA5F170F2357A6EAF4FCEBE3D185301E539CCFDDB4612529799C9059689884380A154A8EBFD3C69D501400000000000D131A231C1C131A1C0F131F2531373D363D3E46484A424B51585C524F504F5F5F575A5A6063514D514079BDFFFFFFFFFFF0B47A4227353261A8E4F2DBC283563A2D2A38639EBFBE8C4918060B144797CBD1B45269676A79B8E3E7DDC3A79EA8B0BEC7D4CDD0C2B0B1B4E4F2DBC283563A2D01FEF25A07071820756C6B60574F6F90A7A59C7350476487BDFFFFEBA251343963A6E8F5F2B85F312C589CE1F2E8B45F24082D7AABA89872441B0A163C84B7DCD6D0B8743808000012487DA5B5D7CBA25E2010275DAEE6F0EDE9E7C77D351F4DA0C3D0B15E21377EB0916167967C2D1418488DB5D0D494501200000000070D11121216241C2612282621283037373A493E4147524C535059525C5B5C575D625A57565B5C5C50523C7FB4F8FFFFFFFCDDB26D352034364D9ED5EDE4BC845037292E3865AAC1BF92531B0003184093CED4B1546F5D678DB6DBE2D2BAA9A4A7A6AEC3CAD4CBB8B0A6AED5EDE4BC8450372901FEF35A070718307E7668574C597195A3A8A17D53546387BBEBFFF09851363C67A5E9F5F1B75939254B9ADAEDE7BB6424163277A1AF90714A1908153B8AC3E1CFC8B3783600000114418DADB0D4D2A86725121A53A8EAF5E9EDD5CD7E3211438AD3DBBB5E1F2E7AA4956A64987F3510214C83AECCBD94531700000000081A181A201F241E17221E1823282E30353E4446533B454249535A5557555C57655D5D5B5D5A5C5152544886C1F4FFFFFFFFE1B17133212B2F56A4DBEBE5C27E5137312E3A5BA3C7BD914F15060E21498FC3CEAE4B6F635F7BB9DCEAD9C2B3A8A8ADC1D7D4D0D0BCB7AEB7DBEBE5C27E51373101FEF45A07071840807D70614F506B8BA8B8A3715D4F6287B7F3FFF3944F333E669FE3F3EDB66A40324EA0D2E9D9B961190E337AADAD8F70451904113981C5D8DBCCB67A31020000164E88AAB1CED5B46323071C55ABEDFBEBE5E6D28A3A1D488FC9D6AB52192B81AB9267789A733503124485C6D2C4965319000000000411101518211D161E1D0D232C343434403E463E45484B454E50535F59515A5E5E625F57584F514F544D3F88C9FFFFFFFFFFE6C47F3225252F489FDFF7E7BB894E44383B3967A9C9C79E4B1704071D4D91CBCEAC5776655D80B6DBE6D7BCA99DABA5B7B4D0DDDABFB9B5BADFF7E7BB894E443801FEF55A070718507776695645546E94B5B49E764D4A628AC1F9FFF09A4934395BB5E1F0EBB56431284C9DD6DED6AF592017367AAFB397774221130D388BCBDBD7C4B3783206000014438FB3B3DBD29F63200C1F5CB5E2EEE7E5E6C87E3519489AC7DCAC651B2778AF93677590742D08165089C1C8C695541600000000000915181D15211F2614181928262C363B39434A4A4044474A525D5457585D60655E5759585B57514F4A3D84BDFBFFFFFFFFEDC2783A1A2D2E5DB3E5EFE9BF7D4C4230273A5D97C2B69444120105184E93D0DCB7567464657FAFE7DED6C4A591A6A5B6CBD3CCC5BAB6B3B7E5EFE9BF7D4C423001FEF65A07071860656F685E4E4F6690B1B4AB7C4C4A5E90C2F3FFED915032335BABE4FAEFBE68332743A6D6F0DAB7611F142B79ABAD9972471F11193783C9E7D1C3B27B3504000421497DA8B7C8CBA5591F0C1E4EABECFCE9E5D4C57A35174692D3D1AE5E20307AA99466709E7C3D131A4D92C3CDBC974E1B00000000010B13191413171F1F212421252F33303230414B514C4C4242505356565B5A63636261625E59575659503C7FBDF7FFFFFFFFECBA73322A2A2D58A9DEEFE7B88850392D30325DA2CAB98C4C1F0706164397CBD3AC4D74687083ACDDE2D3B6AEAA9DA5CECBCFCCCDBCB3AFBFDEEFE7B88850392D01FEF75A0707187071716B513F556E8CAEAE9B7647465E90BFF5FFE8903D283B64ADE9F7E4B15F352857A1D3DFDDAC5D23153F81B2AC9D7A45180E1A3D85CBDECEB9B4802F000000164E8AB2B0D8D0A4551B162453AFE0F5F3ECE3D18230213E96D4D1BC601B307EA18E667391722D08145894B9C8C19C5314000000000410091915191F1C1B1C21231F29283741444B4C4B433F404553525B4B5B5F6160605F6160665458544D3B7CC8FFFFFFFFFFE4B6793E252E3451A5E4F0E8C189583F30342F5AA5C8BF8F5D090519244D99C9CDB94C6D636176B4D9E7D1B7A89FA8A5B8C7D2D3D3BCB1B2B2E4F0E8C189583F3001FEF85A07071880737D614C42506C93B3B2A2705149557EBBF9FFE98D50303F61ABE2F5EFB65E3C2C4EA5DAF3E9B75F1E0D3682ACA6916C3A190E0F2F82C1E2D7CFAC763306000015508A9FB4D9D9A9581C0E2A5CACECF6F4EDDBCB84331C4890CAE2B95E1A266FAE8D6361957A2F0F1B5393C9D2C89050140000000009101311211B1E1812141B24282A262E3B3D3C3C544B50474F52555858596767666B5D5E585E635750503D85C4F7FFFFFFFFE6BF753525232F80B2EBF4E6B88B563026373A65A0C2C1955616040413469AD5D0B5517166627EB6D7E1CEB8A49EACA7B0C7DEDAD5BBB8AAB1EBF4E6B88B56302601FEF95A070718907573634E37496486A1AD98784C4A5282B9EFFFEC8B5031385AABD9EDE0B4632C24559BD9EBE8B55F20133B81A3A5946F48240F103A88C9DDD6C7AD7A2C0000000E4886A4B1D4DDB05F2B111A4FACE5F1EFEADECB7A32184B95C9D7BC551A3877AC8F6472997C2E08164C86C5D6C59655170000000010121919191D261F21181E1722302E2E35384042453C45484B49584E56605C5A5B63675E5A52545B54564680C2F7FFFFFFFFE4C17339292C3760A7DDEEE7C38F503527323665A9CBC38F5118080C16479FC8C0BB3266646383BBD8EAD8C9B4A0A9B0BECBD2D8D6C8B4ABAFDDEEE7C38F50352701FEFA5A070718A071745A533A3F608AB4B39E73504A5A85B8F3FFF0934F283A55AADBF9EFB35F382347A1D3E0E8BD6C230B3781B3AF937240190D113D83D1EAE1D7BB7F300100000F4088A4AED7D7B36718111C55ACF0F5F1E1DFCD812E184990CAE1B555172973B099656F9572230417478BCAD6C48D4E1F000000000512201E2922211E16161C1D2A2C2C2F333B3E45403C4E484A5151545052515864635A58595C52524E4B387DBDFFFFFFFFFFF6B872351F2E3459A4DFEFE2C89756333D375A6EA1BCB4934A12000F1D4994D1D4A951635C5D77B3DAEAD3BBA79FA5A6B1C4C7C4CCC4B2B7B5DFEFE2C89756333D01FEFB5A070718B07E7860594A576C8BAFB79C75504D5289BFFFFFE0904E393969ACE9F7E5AE6B362E5FA1D0E3D5B8642312357AB2B0957B44120F163587C0E0D1CAB17C330000001D5086A5BCDADCA9601E0A1E4EA4E5F1EAE7DDC976341E4987CFE7BB58202E7AA68C626C9A7A2C0C194F93C8DBD58D5019000000000F121518171919162019141D2A342E363B3941434C42444451514F555B615C4E535A60515052585759534399D6FFFFFFFFFFEDAB762920342C56B3E3F3EBCA93502E34334065ADC9BE9A4F1C090B1E488FD0D3B6597068637CB0E2EBE0C8AD9CA1ACA3BDC8D7CEBFB2B2A6E3F3EBCA93502E3401FEFC5A070718C0746F64563B54688EAAB7A37A52475587BEF7FFE493472D4069B2E7FFEBA95B2E2254A3D1E6D4B55F2713387BAFA994673E1B0C133783C4D8CDD4BE7831000000164982A1B1D6D2A95D1E101958B2E6F6EDEEE1D6812D1A5395CCD2AE5820387DA89A5D77927D2C031D5398BFD2CB974C1E000000000313181B20182622251D221B1F2330272F3C404347454940474E4E5A525E62595961605750565B585B503C79B1FCFFFFFFFFF1B8712F1C2E2B5AACE4F1EFC58D503C352E305F9EC3B58D4A1B0904284F93C8D6B64F585B5D7DB1DFE8E1BEA5939EAFC0C7D0DDCCC2BBB4B5E4F1EFC58D503C3501FEFD5A070718D08387665947506E91B0AD977752416195C3F8FFEA9344273363ABDCF2EDB25A362A57A2CFE2DEAD6A1F17347DAAAA9A6F410E13103983CBE2DDD2BA6C2A000000144588B7B0CACA9F5F1C0D2154AFEEF9F0E7E3D38133244B92CAD4A95B212978A8916C778D6D280E1E5A8FBCD3C48C581A000000000D1416201C1018131F1B211E202A31332F3443435242413C474A50585855616060615E5C585B555155514578BBF8FFFFFFFFEEB970321E2C384E96DEE8E8BE8F4F38262D3C6AACCCAD8667221206164093D2D3B252735F5F7BB4E0E1D3C09E969EA8B0C7CFD1CBBBB5AEAFDEE8E8BE8F4F382601FEFE5A070718E0707969573B3F61829DAB9A7450465F87C1EBFFEE8E4E323363B7EBF3E6A865302B53A5D4E5D2AA65210B417DAFB3896F401D111A3F89BDD7CEBFA37932010000144C8FABBBD8CCA95C21122254A6E5EFF0DDE3D78236204794C9D2B56C182A7FAD9462768D722E14194B92BCD3C89758190000000006181C201C141A181E1C1C1F282C2A3236423A434E43433E4E50545B545B595E625B5557545657554C51437CBCFBFFFFFFFFEBBE76231D2C3658A0D8EBE6D08F3A3230313A5CA7CEC28F471F0A0E244798D7CBAA4E79616178B4E1E7D6C0A29FA9ACC0CFD6CDCCB9BDAEB2D8EBE6D08F3A323001FEFF5A070718F06A7060504146607FAAA8A4794A4C587EBEEBFFE49340303A5FACE5F2E9B2633221549DD3E1CFB0682221407BAAAF90654B1D05113B8FC6D3D9BBA97D2D0000000F418EAAACCCD2AC5B1C0A2757B3E5E9F5EEF2D0892A1F4799CDCFB25A1B2C7CA19C666E97752A03114994C5CCC494551A000000000616261D24201E22221A1D172528283730373F4A4A434A48565B57555455585E626161575A4F555451504172B1F8FFFFFFFFD6AE6F310B27325BA9E8F5E1BF824C4235333A619EC8BC91461C10141F479CCBCFAE5274676A7FB1DCE5D8BC9F95A1B2B8CCD1D6CFBEB8ACB9E8F5E1BF824C423501FE005B07071800797E6D55474D6282A9B1997656445B8BC5FDFFE88A4E33305DAFE6FBEDB15737254EA6DFEBD1AA611F133981B2AF956F42180B1C3C89C6E1D3C6B47B34000000194E86AEACCECAA55E23141D57B1DFEFDEE6DAD27F36245593C0CCB96520387AA0915D749077310B1E5691CADCC793541E000000000518132222191F1A1920232727282A3A393E424B494D45414A53585554595A595D5A595C454E525652503F80C5FFFFFFFFFFF6D1793B2D302848A8DAECE4C58E4F33222E3B63AECBB9894A1C080E22509AD8CEAF516E595A7EA7DEEADCC8AA9DA5B0C1D0DAD0C5B4ACAFB2DAECE4C58E4F332201FE015B070718107B74685A464D698BB0B29F734C465C85C2F6FFE79044383665ABEAF9E5B25934284F97D9DBDABA5A20153C7FA7A0907243210C163486C7E1CBCDB87B30020000185385A3ADCED1A85D1E182756B2EFFEECECDCD187341F4791CDD1B65B1E3676A99763748F722B0819598BBAC6C9895123000000000319251C121E21191B1F161C2A2E2D3B3B393D3E4540404349494F5A5D605C5C5F59605C5652505A4D503F72AAEFFFFFFFFAE1B772341A202957ACDDE9E8C07C4B302F383168ABD1BB89400D02041C4595D0D7B04465655A7AB6D9E9D5C0A798A4B0C0C7CFCFD4BFB3B4B6DDE9E8C07C4B302F01FE025B07071820696E5F4D3C3D5A839EA69A6F4B465F8BB4F1FFE3904B29285FAAE8F6E6B051302955A0DAE4DEA85D23122E7CA7AB916B411707143687CBDECED1B973310000001D4D8EA3B7CDCE9C521F0F2F5DAFEEFBF1F0DBC483301F5299CCD4AB5B25357DA6895E6F91742405184B88C1CEC893561A000000000B1923212B241E151C1920201B2E30313C313C42474A4A473A45504F52565E5B636661605A5455534C4A4179B7F3FFFFFFFCDDB4672E1D232C59AAE0EAE0BD8649302E343870A2CABF9150160403194697CBD7B1486B5C5C7FB0DEE9DCBCA9A2ACACB8CDD7D4CDBDB3B8B4E0EAE0BD8649302E01FE035B070718307E7770564C4B5F7FABAB9D734B436286BEEEFFE594422B3761ACE6F5DBAC583C28519FDAE7D9AA6823153C84A8AE8D604220060E438BCBDDD1BBB576330000000F4C93A4AACAD5AE5E130D205AB5E8EEE8EAD9D784341E438FC5D9B1571A2F7BA78F6E759B732F11245490C0DCD28E4E17000000000B15282E2517220E1D19141C262728283533404A504C3E404A5550564D50575E605956555A594F504B4D4180BFF9FFFFFFFFEAB87A3F22242565A4DBE8E3C491513D262E2D5FA7D6C3904B1D0E14204A96C9C9B54967605D79B2E1DBDFC4A6A5A3A7B5CACFD0CEB9B6AFB4DBE8E3C491513D2601FE045B070718406E6B5F4935395A89A0AD94664A455787BAF7FFE48B38263E6AACE1F5E4A65F2C234B9ED4DCDEB0671E0D2D75ACAF8E6C471D060D3C8CCADFD2C6A66F2B000000165096B6B6D0D0A8571F0E2757A7E4EAF0EBDBCA882B234B94C2D1B8601C2F7FA6905E6E97803405215995BAD4C3864A1E0000000014222025211B1C191B1D1B2021202B35343D40424C4243464E5457575E5E605E5D6061635453504E4E4F397DC2FFFFFFFFFFF6BD6E3726312A5BA4E7F0EEC5885029272D4169ABCCC6914A1C0D06234B9FD4C7AC546D5D6380B4DFE1DBBDA1939FA6B8CBD5CAC9B5B1B3B8E7F0EEC58850292701FE055B07071850757E684A374A617E9AA99D6F513E5781B7E4FFE6914B2B375FA5E2EDE7A2572C2350A1D7E7DFAE6521123980A5AB9C7D4723090A357BC3E5D5CCB47932030000154682A8B0CCCBA864220B2157ACE9F8ECE9E6DC842C23549FDDDDB0581A317CA995616E8D722F04274E93C2DACA97541000000000041718142320271D1A1B12211E34373835373737423F3E433C474C5050595F5E5E585956565957544D4A4279B6F6FFFFFFFFE3BC7534232B2C54A4DBEBE3C88A4F3328384467A2C8B48846170C0A194D9ED5D7A74E665C607AB1E1EED7BEAB9EAAB1B1CAD5D2BEBCB0A1B3DBEBE3C88A4F332801FE065B070718606F6D5A3F3D43597C9DAB9265444A537EBDF4FFE3934924315FA3DDF2E9AA5F2E2348A6CEDCD4AA6527143E81AFB2926D401F0A153680C3DEE1CAAC7531020000114A93AEB2CDD7A259200D2656A9EAF2EBECDBC8852B1A4A90C6D3B05E203686B08F5E628F792B121C5792C9D7CE935716000000000B1A221B20251117191A191D282E3330393E3C404E41433A49505559655C5C5856595557615E625D4D4C3C7DBAFBFFFFFFFFE8B4752F1E202E539DDEEAE7C18B4C3234363D69A9C9BB924A06020B1E449ACCDFB8536F57587FB3D6E4D2C49E94AAACBACDDACFC9B7B0B3B6DEEAE7C18B4C323401FE075B0707187071715A483C456184A6A9916243415582B8F1FFE2904D303465ADDDEDE2A858311D599FDFE4DAA8591C0C3472A6AC9470412019183985C7E2D8C8AA6A2D040000144891B4B4D3DBA95310161E5DAEEBFAF7EDDCC57C2D1B4B9AD1D69C57213683A58B6474966E350A1A5691CAD5CB83571E0000000016181C231D181A1E1D201C261E20282D2732373A444E504E4753595F58555A5A5F645B5B5C54505B4D524584BEFFFFFFFFFFF3BF70342D303461AEE0EDF2BF844A39252D385B9EC7C49B56200A06184B94CDD4AB4968646176B2DEEAD2C2A09AA8ACB5D2D5D8C9B3B4ACA5E0EDF2BF844A392501FE085B070718807B7A68513A465C80A1AA9E6F4D4F567DB3F5FFE38E4A393C6AA9D8EFDEA55E27264FA8DBD8D2AC55191A4689B0AB9367411A10103E8EC8E4D5CCAE7F2D0A000018498EABB0D0D0A760160F1D56A7E9F4EFE7E9CF86301D499AC6DDBA5F1E2C6FA793597A95722D001B4D91C2D5CA94561E00000000071B2F2B232021131D111B221F262E31333C3A43443F4041414F4F5A55535A565E5E5B5E555F574E50564386BFFFFFFFFFFFEBB4763B1C282D59A5DBF5EDC28A51381F303763A5C8CA954A260B07133D90CDDBB852665F6188B4D9E8D8B69D9CAFB0B7C9CDD1C7BFC1ABA6DBF5EDC28A51381F01FE095B07071890777364533F4661829AA9A26A4A3C527CBFF5FFE6943E283F6AB1E3F1E0A6592E255CA3DBE4DCB15A26133A82A8A494743D20120D3982C4E5DDCCB6752A030000114690A6ABCFCCA353270E2556AAECFEE7ECE6CF7F33214497D1DBAA57233880AF97646C977C361024558CBDD6C18E4B1B000000000E191D2118191A191513171A1F26312D343E4335473C463D4B574C544F58605A585558585C515656484A4381C3FFFFFFFFFFEAB7803B2140384EA7E1F5E8C3824935272F3D6DADD4BD8948180A0A194C9DDED5B14B6A625E81B5DDE3DCC4A2A4A4A5B3C9CCCAD4C0AEAEABE1F5E8C38249352701FE0A5B070718A07084675540435A80A0AC9D7752485879B1F2FFE79442263C68A9DEEBE3B55C271E55A5CEDFD3B46220113D7DA6A48E6042200F093D89C6D7E0D0B1752F000000124B85A9AED4D8A95A2B0C1D5BA9EBF7F0E3D7CE7D2E194296C8DDB4591F2A7BAF91606F947227142B4F8FBAD6CA8D5A230000000009181626232424241E161E2220222E2E32393541414A4640495550584F49545A585E5C5C55595C4E534A3F86C7FFFFFFFFFFEABB8241272B365AAAE4FAE9C98A52322E2F3D649ECCC0904C1204092053A7D2D1AD5172636175AED2E0DBC1A79AA3A7BBD3D4CBD1BEABABAFE4FAE9C98A52322E01FE0B5B070718B0796F6A553D40597AA2AB996C3A40557CBEF4FFD98A3B1C2B63A9EAEFE49F5F32284B9ED5E3D8B35A1C153E86ABA79A794313070E3485C0DBCFC4B6792E050000124890B3B9D2BFA76121141F52A5E6F4F1DDE3CF803423418CC9E2B460203582A189566F9A6B230F1F5B94CAE2CA956324000000030821281E1F282723131A1B1B1B21312F3B333D46424548434B50515A58575859525D5F585D565A53514E387ABBFFFFFFFFFFECBB7D432E2C2859A0DAE6E0C4814A3325384170B2CBBC8E4919000021499AD5DCB053716C5A7AB3EAF5E3BEA69998A2B7BEC8CFC7B4B6B3B5DAE6E0C4814A332501FE0C5B070718C0847E63483B3D5E7EA1AD9C7051375683C0F2FFE7874A2D295CB2E1F2EBB15C2C2858A1D6DDC7A05323143C7CB5A6926A431C030E398FCDDFD4CAB9792C0000001E4C90AAB2CACEA6673215225AAFE2EEEBECD9C46E2D21509ACCD9B55B26337FA98F62738D712904185B93C4D5C79B581E00000000141A2628252221131013191C2C2E312D3335373D4A403F4447555354515F5F5762675C575756545A5559418DC7FAFFFFFFFFF8BD733D26303A5EAFE4F2EECE944E362D343A68A7C5C089401D09061C4EA1CBD1AF5D6C50567AB3E0EEDAC7A49AA5ADB9C3C4CECDC2ADAFB4E4F2EECE944E362D01FE0D5B070718D06A816954393F4B7DA2AC966A49435287BCF3FFE884442D2D64ABECF8EEAC592B284EA2DDE6D5AF6620153A82ACA894713F16020D3A7FC3D5D4CEB3752A000000104695BCC3D7D3AA5F20052757ADE0EFE5E7E1D2852D174891CDD2AA561D2E81B19C6C7591712B0F165295CACFC6945B2100000000101D2226212115150F12131B20232E332F3B384046424245504C525A6260554E5A5D56594B5E595A56583E82B8FFFFFFFFFDE6C06C2B24262C56A8D6ECECBE854C353E3B476DA6CEBF8F401500050D3B8FC9D2AE56685E627FBEE2F8E0BDA68F9BA5B9C7CDD1C8BAA1A5AFD6ECECBE854C353E01FE0E5B070718E07A7A6A563B37477C99A98F6A48425A7CB6ECFEE08740243D69A8DEEFE3A9583228599FD2E6DBB26028133A80A7A891704218060D2E88C4DED6CBB47931000000124B8BAFB6D4C89C5318071E52ADF7FCECEBE5CF76311B4F98C9CBAC5F1C3D88A5895D6999722F081B5897C2CDC4965D1F000000001827242C2B1F141316211D1B1C2B2B2A2F333B494F404944474D5850525C615F5B5C605A515354514E4C4179B2F9FFFFFFFFDFB263331E2F345AA3DAF4E4C9854B322A363975A4CABF9949170009144D9ACCD5A04C65646B83B7E0E5D5B8A597ABA9B5C8CDC7CBBEB3B0B8DAF4E4C9854B322A01FE0F5B070718F082826850333D4C7CA3A695653B3A557EBAF1FEDD8B4931315FACE5FAD9A24F27245BA6D6E3D8AC5D22083B81AFB0946E3F180A0A3480BCE5DAC1A67229060000144B8EAFABD0D29E50190B1752B5F0F8FBF0EDC87D381F4A99D5D9B7571B307CAA8C676E9371260E1E4A97C6CBCA99562500000000101C201F201C1E2519141E211F203033333936384A493E41494D484D4F565A5F5D5F5C5C564A575E594A4079ABE9FFFFFFFFDCAB6A2A18262B4BADE2F0E6B4834C2D30353C5DA9D2C18F441810001A5397D1D1A9475E5B6283B1E0F0D4BEA598A1ACBBCCD1CCD1C1AEAFA9E2F0E6B4834C2D3001FE105B07071800746F614932344D799BA8957344395280BEF5FFE0843D2D2C5FAFE5F1ECA957292A509DCBDED4B45D280F3B86B0B594703D190A093990C2E1CEC1B4753204000012588BACB2D6CBA45D1A0C2062AAECF0E8DCE4CD8428184490CBD6B75E223981AC9563728F69200A245792C9D2C98A531C000000001B2C292A21211D1E19211C1B201A232E322B3A41464041415152525353565D605364635C5F5C594F55534483B6F2FFFFFFFFDDB8703C2A2A3059A4E6F1E8C3894E382A31466AA0CBBB8B4917030F204A98CFD1AA516E5C597CBCDFE8DDCBBF9C9EA1BBC7D4CFC9B8ACACACE6F1E8C3894E382A01FE115B070718106C6A5E4B27325D7AA0A791603D3D5576B3EDFFE4853B303160ABE6E9E09B5F291E539CCFDFD5AC651D0C3C7BB7AA94643D1F0B19388CC9E3D0C5B5722E000000184F95B7BDC4CDA05619081D60A9EAEBE9E1DFC8802F224498CCCCB05B253083A38F68739B76290E1B549BBFCCC2975F1E000000001A252929281C29231A17141E242B312C38343C3B45423E3D444E564E584F575C6364605A545456574C4D3C7AC3FFFFFFFFFFEBB8722E182B314CB0DAF5F6B983522D3037447596BFBC9945100B1619479BD3D5B45566575A80B7E3F2E4B5989A9CA4ACC9D2DBD1B7ADB5B1DAF5F6B983522D3001FE125B070718207A77684F3A394B7CA0A995603C37507DB1E5F8DD8C4126265FA5D9EDE0AA5C292352A2D2E2D2AF5F27152977ABA1946D411E0C103D83BBDBD6D1B67733020000134790ADA7D1CC934E140C1F5BB9F3FEF0DDD6D186361B4D9ACDD8B359243386AD8B566F8C722B12255AA0CCD7BF9155200000000112202C252025311E1B1212152327272D2B2B3E434041443F404E4A585F575757525A5D55515659514D47327CB4F3FFFFFFFFE5B26C322129345EAEE0EAF0C1904A3629293D56A8D3C494440D01091C50A8D6CFAC526259606EB2DAE4D3C0A69BABAEB9D1CED5C8BDAEB5B9E0EAF0C1904A362901FE135B07071830807A60483541537C9AA48F67443D4774B5F2FFD87C3D2130609EE6F6E4A64F2C2352A1CFDFDEAA542813397CB2A695773B150A1E427FCCF4E0C7A7702E000000164F92AEAAC9C6A6591A10215CB0E9F3ECE7DFCB833121478FC4C99E58223581B19462799770260C1E599BBEC9C9995B1D00000000192129282B241B1F1815171F1D1C27352C32343C454041433F4D525359575A52575E57595D5D5858504C4284BDFBFFFFFFFFEABB763C25303A5EA9DDF7EABE924F32232B4174B2D1CA904B15020B194B96D4D2A24C64615F75AEDAE5D6C49F8B97A8C3D6DAD8D6B994A5ACDDF7EABE924F322301FE145B07071840707D6B53352E4E7A99A3945B3D3E4B79BEE6F8DE7F36292E58A4DBF5E7AB5C2D215AA1C9DCD0B567230D3382B1A992673D18040E3882CBDED4CBB676320100000B4A92AFB4C7C99C581B0D1B59B5EBF0E5E5DACA832A154798D0DDB258213076A793657A95712410275F9BC7CAC08F5D1D0000000114272C29272127181A101B142A24252B2C3B363647403E41454A53504C53615B5D575153605C5A564E4F3E7EC8FFFFFFFFFFFDC7763D31333B5CB6E8F7E8C080493D3233456BA8CBC486542608091C4599C6D2A93F6C555581AFD7E4D9C3AE9693A3B9CFDADACDB2B4AEB2E8F7E8C080493D3201FE155B07071850787E5644323B4B7994A394673F374575B8F1FED98239273064AADDE3E1AA59251B4EA4D6DED2AA5A170F3183B1B3926F3D1905063684C8E4DDC7B07328060000154891AAAFCEC0A0572512224DADE2F2EDF5F0E08438193C99CFD4AF5223317D9E99657B9C6D2B081C579BBAD5C6915E25000000041B302F26241B1E101F1E1B1C1C232D352F333D444346424249534F55525159555D5F5157645E545246453978E3FFFFFFFFFFEBBB762F1C2C325BA3D9E7E1BC784935233A4563A3D5C890481301001547A6D0D2AC4C735D617AB7E1E7D9C3A59697A2B7CADDD2C9BCB6B4B6D9E7E1BC7849352301FE165B070718607471624626315077909F8C5E3F345784B4EBF8D78342222D5B9ED4E4D8A15E2D284AA1D0E1DBB15B250A4081AEAA9568461C0B0A3082B8DED4CBAB6B2D00000013498EACACCED0A15D220F265BA7E7F3EEE6D9CD7E31254F94C6D6AF5719398AB49A6079947C240B1E579BC0D2C1935F2100000000102628282527241E14121318171F2226272D3742433C473F44455850525759555D5C5A59575759554A4D3882C3FFFFFFFFFFE7B87239212A2B58A4E6F3E5C587512F26313468A5D0CA9144090605194898D8D3B15D6B5E687AB1E1E9D7B69E9BA8AABDD7D6D5CABFB1AFABE6F3E5C587512F2601FE175B0707187071765B3C2A3248779499975430334D73B4E3F8D9883E243862A5DBDFD09D5032234EA2CEDFDAB257161535719EA496773E1E110E3B7EC0DCD5CEB17A2D040000134C96B2BBD4C5A05B19082156B3EAFAF0EBDDD0822922509CD2D2B057192C83A88F646E8B61260D1D5598C6D7CB915F2A0000000F1C2D2D2E1E1D2018211B1C191F25262B2F333A383B3D4344445253515750504F575E5F545C545550464C3A89C0FFFFFFFFFFE8C07D362C2B375FB5E4EEE9BD854A32273A3C61AED2BE964F16060E19469DCED0A548695C5E81B8E1EBD9B89A9DA8A8BCD0D4CFCCB7A4ACB7E4EEE9BD854A322701FE185B0707188072775D3A212A46738F998B5431364E7CBFEDFFDE7E3929385FADE1E8DA9D56322952A7CFDED9AA5D21123B7DACB7926D3D14050B327EC6E2CFC7B8792E0000000F4D90BAB6D4C39D570E112154AEE9EFEAE8DBC06F3224559CD4D7AC58122F78A9956B7E996E280E265593C4DBCB92541B00000000212F2B282822231513181521211C212C302F343C45404042464D5B54504F5D585D585A59595454544D504378C6FFFFFFFFFFE5B8732A2A263664A7E9F5ECC4833C2B2E2B355FA7C6CA984E1701031A4F9ACDDAB35B64596279B2E1E6E0B99A94A1A5C0D4D5D4C9B9B7B2B4E9F5ECC4833C2B2E01FE195B07071890706A583D22284C6A919C86572E2B476EA9E8F8DB883C253C65AEDFEDE4A2542A2259A1DCDDD29E58170B3878A7A58D62471807193C89D5E5DABEB47B320600000F4884ADB9D0D6A15713071D55ADEEF7EAE7E5C37A28144E9BD1D7B05316327CA997686F937023041A649BC7CFC295591D00000002183130232529222320140E17251E2725313A3E3A423F3D394752575D5F5B525F5D635E5A504E585551503E82C3FFFFFFFFFFE7BF7C3C26323955A1E1F3E3C08148322E324167AACFC28C4614090A1C549CD0CEAB5A6C575076AFE4EDE0C0A197A3AAB9D1D6CFD3BAAFA9B8E1F3E3C08148322E01FE1A5B070718A07376543B2429437596A08953372C4579B7E6F6CF84371B315FA6E1E1D7A352332751A3D9DCD4A15A170B3A84AEB28F6F3F1F0E143687B7D3D2C1B07429000000114E8FB4B5D2CAA75C16001651B0E2F3F2F0E3D18033214BA0D0D0A353202E7BA585687E967128131B50A6CCDEC995571E000000001C2E322F2C2B2A1E1B141B14191E25312B373C4543444844404B494C4F51555A585B5A5D59585654494A4074B7F6FFFFFFFFDDA9733017212C58ADEDF3E9C688452B1F293D6BABC0C18C430E0D0A184799CBD2B14C645F5876BAE2EAD8BEAB999CAFBFC9CDD5D1BCACAAACEDF3E9C688452B1F01FE1B5B070718B0788263422C2F4D7E97A98B5B2E334877B4F2FED1814223345EA9DEEEDDA047221F539DD3DBDAAF6417003C81AFA0967743210518378AC7DECDBFB46F31000000165394B1B1D3DEA5551B111C57AAEFF1E8EBE0D17B311B4C9BC8D1AC51193189A98F62738C7426071B5998C5D2CA8D5522000000001A2C3B38342623230E0D0F171C2325262A32414848494A43444E545155585754555A545658595E594F4A3B81C3F9FFFFFFFFE9B6732C1E2C3050A9E9F7E7BC824D2E2D363E6DABCFC5914415020C2356A5D6CBA8526B535979B2E6EDD8BD9E96A2A9BCCDD8D0C9B9B0A8A8E9F7E7BC824D2E2D01FE1C5B070718C075715841292B45728E9C865D343A4B79B7E6F2CF8142212D59A9DCEAE2A5541F234DA2D3D6CAAA62250F2F7AB0AB936B410E04194089C6E1D7C5B1702B0000000A4C8FB4BACFCB9A582408215CB5E7F6F2E6D2CF7A34285298CDD9A957213582A89969819C7525051F4E90C8D5CA90571F0000000819312F2F2A1919241D13131C161D2226302B2F41443F41444A534B5354535455555E594F595756514C534088C7FFFFFFFFFFFBC77F432E2F415CB1E7F6E7C59347332633396EA7D4C28B4615050A214199C8D2B24F6F605772B2E1EEDDBEA39AA4A4B3CDD9CCCBB5A9B0A8E7F6E7C59347332601FE1D5B070718D06F6451331C1E43708D99885322254378AFD4F1D180351F1E5DA8DDE7E1984D1D2054A2D2DAD3B260230E3276ABBC96763D1D040C337AC4E4DBD1B26B32040000134E89A7AFC9C89E5E1F071A53AFDDF4E6DBE3D57F311F4B94C8DBB164223985B09B67748C682F081E5895C4C8C09763270000000020353A332A2924131F0C1013241F2A282E313240413943413C4B5659555A5159535B54525A58535252564880BFFFFFFFFFFFEDB36D37222C365FB0DFFCF2BC8450311C2D3D61AAC7BC8E3610020A1B589AD1D6AA54655A5A78B3DEF1DBC7A296A19CAACCD4DDCDBDB09FAADFFCF2BC8450311C01FE1E5B070718E07477633E212C446E91958D562D274075B0E9FFD689311F235AA7E0F9E49C561E2551A2CBD3D3B15B210E3983B3AD9666381E09153B8CC8DFD0C6B37930000000104A98ABB4DCCD9F5D1F031A60B6EFEDE0E2D6C17A30264B9BD6D6B15A212F7EA1965A768A6E290D245A96BFD0BC8F5E2500000000172C2E25362C1C1F1D1B1A1D28282F27302E2E36413D463D3F494B51524F535F585D5A554D53574E5054427AB9FBFFFFFFFFE4BC6C321F233166ADEDF3F0C086472D2D324067AACCBA8846130C0B205399CACEB4535B555D78BAE6EBD9B2A298A8A1BDD0DED0D5BFABABADEDF3F0C086472D2D01FE1F5B070718F075744F32162643658CA2865D3432446DB2F3F7D17A3A28245D9DD4E8D59E4D1F26519DCED7DDB55F180B317BACA78D6B3A190B173E88CDE2D5C6AB70280000001F568EB0BCD6CD9C551103245EB3EAF3E8E4DECB8232214C93D5DAAD51203887A68061678D72310A245997C2D5BC93611E000000071D383E302520221B1514131018222F2E2E2E3740414145454A4B50584F556555555952515056575649493982C6FEFFFFFFFFE7B76F34243B305DACEBFAEAC3864B2E2A38486FAACDC28B491209030F4997D0D6AF4B6958596EB9E7E4DAB8958DA7B2B8CFCED2CBB7A6A3A9EBFAEAC3864B2E2A01FE205B070718006D70623D211C43688FA28B5F3932386DB0EDF4D17B341F2858A7E3E8D59C4A201F529ACDD9E2A65E1C0D317BABAC8E6C38190A0F3E8ACAE8D4C5AE742B000000105396B5B5DBD29E5619082755ABEBF0E1D4E6D4843B21509CCED6AC581C2D73A8875E7592732E0A274F93CED3BE8B581A000000032438333C302C1D1B191212181C21232F31333B4140393D3E414C4950595A5559595B5958514C5652454C4186CFFFFFFFFFFFEFB3783E2028345DA7E0F0E4BC7F47241D2F396EABCBBD8E4C200F10294BA7D1BEA651685A5D7CAAE1E6DBC2A79DA4ADB5C7D6D7CABAAEA6AFE0F0E4BC7F47241D01FE215B07071810766C5B311C1A3F668D958E57302F3C77B0E1EDCE7B371F265BAED6E7E5A34927244B9CD7E1CBA54F1A0F2E75A7A594753A18060C3C8DCAE0DAC9BC8241000000175398B6B3CFC59E571A082057B0E9F2EBE3DDC7762F204C8CCCDBB5591F377EA2975F74946A240925559ECAD9CB9F542200000006273C373635341F1E130D191519232522261F2E36443A443E3F4A4A4D5457595B586559515854544A4D4F4283CFFFFFFFFFFFF2CA764D33313765ACEFF9F2CC844125353B406AA5C4C38D4919020C194899D4D8B25C6B5C547DB1D8EBDACAA79D9FA3B5C3D9D3CDB5A8ADA1EFF9F2CC8441253501FE225B070718206F774B2D1F2342658E998D542E23486DABE6FBD27B331D2A56ABE2ECD49B59292551A1C7D8D1AC621C063071A4A0836C40170513318FD3DDD7BEB46A25000000185294B4B9D4C99D5412081A54ACEDFCF6E2E1CE81362A4EA3CADFAF56253382AD9064759678270A1F4A95C6D0BB8D592600000008273D413A3426211E11160E1118292C23332B393E3B413E3C4748494D535A534A5A6154545A545450534B3C86C9FFFFFFFFFFEEBE6D3F2F323961A8E6FAE7C68A48392332466E96C6C592481303122454A3D1CFAC4A63535472B9E1E8DEBFAB9BA4AAB4CED7D6CCB6ADABAEE6FAE7C68A48392301FE235B07071830737F562E151A395F8D928B562A24406DACDCF3CE7B2F172861A3D7EFDBA252211E4D99CDDCCBA55D19032E87B2A897763D140014368CC7DFD5CAC27B31000000174891A6B0D1D09B581C0B2256ADE7F9E4E0DBC881321B549ACACFA852213786AC9A6776926D280728669FC1CAC59458250000000A2A372F292C2E241B1B1411111B201A2C24253D3D3F3E404044424E54525C5A5958595853574C4B534F493385E1FFFFFFFFFFF1C77C45222C3761B1E2F9EFCC84512E3A324166B1D4BD904114100E1F50A1D4D3A93A5F59529CC1E7EBD7BDA6939C9FA7C3C8CDC8B39C9CA6E2F9EFCC84512E3A01FE245B070718406D6F56311615386387948151291C3E72A3DEF2BE6D311C2756A3DDE5CF964D231E4E95C2D9D8AC591D103679B0A8916C371C10153688C3D9CCC3AF6F3300000014569AADAFD1D0AB5B120C2053AEE4F9EEE7E5D2883A1F4991C7CFA84F1E3880A7856A7796712D08245C98CAD4C599571A000000001D37393D2B22221B140F100F121E28242C383D4046403F38414A4C58615557596159505D5A4E5453504C3587C3FFFFFFFFFFEDBA7C35202E3060B2EBECE0BE7B472532323F64AFD0BD954C0E040317489ED2D6AF556E5F637AB5E7F5D6C299959EA9B5CBD1D1C4B7A5AAADEBECE0BE7B47253201FE255B070718507571502F111A345D8988835028233D6BB1ECEECA7E3E20225A9DDBEBDD934F1C234A94CCD9D9A5581B0C397EAFAD92683D180509368AC0DCC9C3AC7B2A0800000E5293A9A9D0CA9C5B1A0F2157B0F0F4EDE7E0D18A2F1D4691C7D0AD53193183A98A5E70966E2B05215799BFD0CA905A270000000825393B2F323B261C1410191F1825253425303D3A423F34324144494D565B5A55585F5F58514F504A44523F8DC5FFFFFFFFFFE7C06F2E1F293158AFE4ECE0C38A4834313B4668B2C9C18D390B040E1B4EA1CFCCA84D67625D7ABDE9EBD9BFA08994AABDD1D6D4CBB2A9A7B2E4ECE0C38A48343101FE265B070718607068492D171C3A5E84917B4F2D304167ADD8EFD078301B224F9BD2EDDAA4552C245497CCD2C5A2571F143983B1A39A6A43150817337EBAD6D0C2AF78250000000F468FACBFDAD4A05C1906265DB5E8F6EBE1DEC9803623569ACDD4BA652A3680A19165778E6C290A225691C7D0BD8E59260000000E2C3E43372B2C2B2B17101313171B262733333738393D403E3F4346594D5B58525E5A5A525556534F4D483678C4FAFFFFFFFFF4B9693B2522235EA7DCEBEEC78F4A2A262A3667A8D0BD934A180B0F1E4694D1D5AF525E545774B4DFF1DBBD9995A0A5B1C7D8D3CEB4AAACACDCEBEEC78F4A2A2601FE275B07071870827358351A1D3A658C9B8C5022223B6EA9DDEEC9733920215EA9D6E4D19D531F2053A7CFD9D7AC54220A3179B3AE91643F14030E3E8BBFE1D7BEB77A2A00000011539DB2BCCCC698581E05245FB4E9F4F0DCD8CA7E38214F9CCFD4A9521C3182A78A5E789369310D1A62A3C1DCC695601B000000122B3C3F352E2A2722180D060B1D27221F2E2F38393E394241414951544C56535F5F5D564F52484D4B4B443C83C7FFFFFFFFFFECBC732F202A324EACE8F9EABA8A4B2C312E4A64ABD0C89753120A0C1F5296CBCFB3455C53587BB4DAE3D1BAA09697A5BECFD6D6CDB2ADACADE8F9EABA8A4B2C3101FE285B070718807F7865401C253C688B98764D2A2B3576B1DCF0C8853B212F66ABDEE9DC994E241F4B93C3DCD2AB5A1F0B377DA8AB93653913090E348AC4DDCDC1AB732A000000185691ADB2D0CFA1571F191E54ABDEEDEAE5DDD58532194C98C5D4AA521D3284B1936A7B9B6E2603175E9FCDCDBB99682C0000000F2B40452F2D2B2A1B0F0F160C19241F1C212C2E343C3C3A3C4B56575C585151515D645E5753545B4D49483778B6F9FFFFFFFFE7B06B2A16283061A8F2F8E7BB81392935343963AACFBD87421804041A4BA3D5D1AA5364514F73B2DDDBD6C2A293989AB5D3DBD4CBB8AAB3AEF2F8E7BB8139293501FE295B070718907C7A58321E213D6498997D51302B416AA9DAF7D27C3718285EA3DDDED79A52242158A1CCDCD6B86224143576A8A38C663D16000F3184C7E2D6CFBC772D000000125598A8B9C6BC905A140B1E56AEE5EFE8ECE4CF843930539CD1D5A54C173980AC9968759471280E2155A1C5CFBE8F591F0000000B29453A36302B2C251610080F101A202D2C32383849403C43474E4C505157595151595656534F584F57514084C1FBFFFFFFFFF4C0793C2C242F5CB0E7F8E7C088492E27373D61B0DBD48E431207091142A2D1D8AF4B6C5A597FB2DBD3D2BC9DA09FA8B0D5D1CEC4B9A1ACB5E7F8E7C088492E2701FE2A5B070718A06B614D2A0C0A305882847A4A26193963A6D6ECD4712E1B2C5FA3CCE2D69C502B1A4296CBDAD5AD5D24123280A9AA8A63441B03112D86C1DAD9BCB06C280000001C4F8BB1AED4D59E5419101E5BB5E6F1E4E6DECC823328519BCCD6B15A1E3386AC9C647799661E00195C99CDD0C496611D00000010223C41372E2D2516120D0B131923252B2A233335463D3436424E54554B52595C5A59575C4E4D504F5351427FC4FFFFFFFFFFEDB66E372D323558AFE7F2EBC8894D34222D3B69A5CCC0884C110B0D224F97CFD0AB4C615C567CB2F3F5DCC59C93A0A4B6CAD0D7CBB3A7A9A8E7F2EBC8894D342201FE2B5B070718B078735335151F34617D857B4C2F222864A7D9F3CA793E1A2756A1CEDFC1974E241C53A9DCDFD3AE601A0B3E77A5A98F66321B08103288BFE6DDC8B1742D0000000F4BA3BCBBD3CE8F4D190A225EB3EEEFEEE7E8D77E3322529ECACFB25A132E83A79764728B66260A21649BD1CAC0935D2500000011283E42362B2827140E070C0E1919222229332E313B3F3D393D4B4A4A5158575C5E635C4F52585857564F388DCEFFFFFFFFFFF7C081412A232E5FB2ECF5ECBC7B43321F3D416EA3D1C58B602509102854A2D7CE9E4162535373ACD7E7D7B296959EA4B3CDDBD2CEB2B3ADA9ECF5ECBC7B43321F01FE2C5B070718C06E734D2B0B13275287A17F451E25406CACE5F0C57827171F58A6DDDFD399542824469FD7D4D1B15A1B082B75A9B28F6C3B1E1518347DBFC8CBCBB3712D000000145195BABDD7D09E5719111B56A8DBE7DFDFDCCB843327539AD1DBAE5A1D377BAA8F6A7188722F1223629BCCCCC596551C00000007324440313328201B131610060F171E2835353D3940373E3D434C484F5152565B635C5F5E605758514F513595CDFFFFFFFFFFFCB96F402E2D3C6AB1F0FFF4CB864F3028283C6D9ED1B68E412503021B569ED4D7AD535F5A5979B3E8F1DCB0A2949BADC1D4E0CFCAB5A6A7A4F0FFF4CB864F302801FE2D5B070718D075774B2A0F1535598A8E7A4F1F253965AFEAEBC2742C1A1F57A5D8DDD999491F224894CFD5D7A8591A183285ADA6906E3C16080B3A8BC2DDD2C6BC7228000000165387ADA7C9C9A4571E0E2557ABEBF4EDEDDEC8792D1D4E95C4D3A760223D8DAB916A7B9A6920052067A3C5D5C88E602A0000000C2D483E3A37322A17110E0D1518192936212B29363439373E434D4A53484A534F555257534A4F50574E513B8DCFFFFFFFFFFFE9BC79442937375F9FDCF3EEBB81412727393D6AA7D0C5904C16040C1E50A1D2CDA5505C554F71C0EBECE1B69C8D93A4BDC7D4D1C7C0B6BBB1DCF3EEBB8141272701FE2E5B070718E07D7B482E171A3562838874552E283E74ABE2F4D17130112353A3D9E6D09545201C489FC8DACBA7531D103C88B0B4916E4017000E3980C7D9C8C4B76E27000000155098BBB3D1D499572111265EB3F2F9F0F1E0CF802E264C97BFCAAA4A1D2C77AE9D6C80946D2404225B98C6DCC68A5619000000072C4A423F3827281D160E0E141A262A2C223038353C3E423A3D49564C504F5A4E54555A4F4F4B5354474E3883C2FFFFFFFFFFF4BF6D23272D2E61B0D7EDEDC58A4C2B22283A6FB2CDC4944A1603081E46A5DBCDB05E67564B80B2E1EAD7B49E87A0A9C0CED3D5CFB5A4A8AAD7EDEDC58A4C2B2201FE2F5B070718F07473552B100F2D5C809A7E4325213E6BA8DBF0CF752B13215DA9D8E3D99F4B1B1E4F9DCDD8D6AE53150830779EA7936838150C193F87C5CFC9C3B48037030000155698B5ACD5D1A4561E102051A3DFE9F3DFE0CC843023569FD1CFB15715368C9D8A646E946F24001E619CC7D6CB975E1E0000000B2D3E4C463B2E2620160B0B10101E23222F2C2C353E343C3E424650575B5251575E565F56575C544A4743387FC9FFFFFFFFFFE5AF6838202E3D63B8DFF6EAC2864A2F25313B68A3C5B8884A12040A204CA2D1D3B0506859577FBFF3F2DAB797939FA9AFCBD5D1CEBAAEAAA2DFF6EAC2864A2F25 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 61440 61440 0 01FE305B0707180072795A2B08062E6281927C431C203C6CA7D4E4BE7633192558ACE0E6D1994424255198CDDACCAF531E14397DA5AC95713B140A1A2A81C1D6CAC1B4712A0400001B4D99B1BCCFC99D51170C1A56A8E2F0F2EBD7D58D36204490C9DAAB531C34809F8C5A778C752C12245B9FBCC8C59B60220000000E304C4A3F332F271F0F02020F161F2931232A37423C3B453A404A4C4C4D46525252524F5D4D57554C4A483B85CAFFFFFFFFFFFFC578312C353E6CB5E9F6E5B487472C2C2D376DB3D2C7904708000D2757A2D4CFAB5762504F7ABDE2EBD6B9A0929CA6B3D3D1D9C8B5B0A7A6E9F6E5B487472C2C01FE315B0707181071684423030F26578892774A1F1A2E66A2DAE6C97137092459A1D9E2D69550201A4E98CBD8D5AA57140F3877ACAE946C3F1B0E152D7BC9E0CFC6AB6D28000000174F9AB6B9C8CD9B511B0E255AB4E8F2ECECDFC6822A1E4098D6E4B7571C327CA88D6F7E926E1B05296292CCD5CB98611F0000001134544B38322A25251106090B13162024262B34393C38403E3D47465256585350515554545A575A574A49377FBCF7FFFFFFFFE7B3673D1E2D3660ACE7F1E6C6884E282327406AA8C9BE8A401109061E4D98D6D5AC485D565E76B6E7EAD1BEA59091A2BED0D0CDC6AEA1A6A8E7F1E6C6884E282301FE325B070718206C70502E0412375B7E8E7F4C1F1C386FA6E1F2C86F2D142758A6DFE8CD9A52201A4C9DCBD7CEAC5D160C397DA8A5916B3C1101113B87C8DDD2BEB77E2E000000175294B7AEC8CC9A63280F1B5CABE1E5E8E1D9C9822E294796CBDCAE551B3778A79267759E6E2A011F589ECDD8C38B581B0000000F325149442D352A1B130C0910171B25242D2F2C3B3C34393B39474A4F53555B4F575B605951545A55454E3985BFFFFFFFFFFFF6C5793C28303961AEE5F7EBC0894B2C26282F65A9CDC390481A1207154398C9DD992F6A545780BAEBEFDDC49D8FA3A5BBD4DBCBCEB3AAADABE5F7EBC0894B2C2601FE335B0707183080744F2D0B122F5D8498834F221E3D6BA5E3F6D77732172154A4DDDCD39345241F4F9FCCD4D3A5621D0B3787AFA892723D1602103A80BBDFD1C4AF7523000000115496AFB1D8D59D551E0B264DA8E2F0E8DBDDD08033284F8EC2D6AC5A2B3C83AC9263698B70260A285F98BFD4C58B5C1A000000133D534942342A28110D0C0C17141A1B2729313035373B3B384A4C4949444F555857554F574F535D5D5C513D75C7FEFFFFFFFFF0BA70352930335FAEDFF9EFC182412A1F2A366BADD0C28E461A09152581A6CFCFA44D57504D7AB7DFEEDABF9F8F989DB7CEDCD8CCB7A7A9ADDFF9EFC182412A1F01FE345B07071840827A50270713335E8B987D37191D2D5EA4D6ECCD7B30111F5499CEE0D8954D2523549EC7D5D3B2581C0C3381B0AC9B713F18050B307DB9D2D5C3C4792E000000155095B7ACD0CCA0571C061E5CABE0F5F3DCD2BE812A2B589FCED1B2511A3680A185617795782C0B13619DBFD3BF935D2400000015415659492E2B281D1811140F191A1E2C222F2B2D364439353B52515251595350495A61574F55504F51504282CEFDFFFFFFFFE7B666372A2E2F64B6E6F5E7BD7D40312728396AADD0D28037170D0728539ED0C8B04A61555880BDE2E9E0B59B8E9AA7B8DADAD5C6B1A7A49FE6F5E7BD7D40312701FE355B07071850746C53290D0F23559791743C26223F68A6D6E4C6803023234DA3D2DED9975021235195D0DBD0A85D15152479A9B2936F450900083686C7D8CDCAAF8033000000104B9AB9B6C9D19D51180B1B52B2E3F3EDDFE1D180281F4A9DC7DBAD56163079AA92687D92682C10256498C0CDC79965230000001636534D443C302213100B091A211F1B1F2636333A3431363C3F4550474D535656585956584D4D5B514B48388DC7FFFFFFFFFFF6BF78362C2E3962A6E9F7F0C3855A3556414F6BA8C7BB903D060A111D4D9ECECDAB4A6F565786BBE1E3D0AD938E99A1B5CADAD7C9ABABAEABE9F7F0C3855A355601FE365B070718606E6B561F060E2C5678847A46170B3067A1D6E0CA763A1A2658A4DDE3D1984D20194A9BD2D1CEAF541F0E3982A4A6976B3F100818388EC1DDD3CEAA711E00000013508AA5B0CDCBA15013081D60ADE7F3E5E8D6CD823420559FC9D2B254292A7AAA90647F986C250B285297CED5BA8F5A23000000163B5D59442B2B2D150E0C0D10161C1C2A2D26313845403C3D3E4B53444D544D4956565B5158575451524F407EBCF6FFFFFFFFE9BB6C3114233255A3DBE9EAC3914B2F2935376099C6BD8B3A12030427529DC9CCA35065584E6FC8EDE5D9B39A9596A2BDCFD7B2C4D1B2A9AADBE9EAC3914B2F2901FE375B0707187075754C2A0B12275C7F93824A1F1F3467AAD7E5C7752C142657A5DCF2D2954C261C5095CECEC3A55719113B75B6AA90663C10000C3B92C2DFD6C1A4712E000000104694B5B2CDC59D521D0C1C5BAFEBEDEEE4F1CC7D2E1D5491C9DBA95B223382AF9769829F641F08285E9EC2CAC48E57230000001E4960543C31271D18160D0A0D0C181A23252C2E363538393D4945504F505254585B6253564A4F525A54523177BAE5FFFFFFFFEABB744B2C403E63B8E2EADFBC813F2C28323F60ABCCC58A48170A03124A97CDD1A74F625B5D7CBCE6EFD4B59C919FA5B7CFD2D4CCB4A4A4A7E2EADFBC813F2C2801FE385B07071880747953250D032B587A88754921172D60A2DEF6C36A2A1721529BCDDED0934C25174E9DD3E0D3A95E200E2F7EB1AA87663713080B3485C2DACFC3B67B350600001B5394AEB9D1D094521D0A2059AEE5EEE9E4D5D27E3320468ECFD8B2501D3887AC8C637B96721F08255699C8C8C3945F270000001048595545402D1C16171207060F1A161F20262A37433C3B3C3E4952524B554C59534F4B595A585F5957453677B4FFFFFFFFFFE5BA743C32302E5FA8E2FCE5C4843A27252E3E6AA8BCBA8B4E180B041B5C9BCCD5AE5264495778C4ECEADFBB92919BAEBFCFD3DACBB9A9ACA9E2FCE5C4843A272501FE395B07071890756C5126070B20527C887D3D221E3864A9D7E4BE63250C234EA2D2E3D1954F2A1E55A4CCE5DCB05B1D0B3A76A9AE876C3C15030C3884C8D3CCC4B27A35030000115097BEB9CAC198521706205AACE3EDEADBDEC77D3422579DCEC8A55519358AAC926977946F220A225DA1C4D1C79E5E280000001849655F4C372D2D21110B090907181B1E282E28303E3C3F474B4C4D474652515A5657554A4C56544F554E3C85B6F7FFFFFFFFDEBA6C321C293260ADE2FAECC6863F161A0F3775BAD7CA92441A030B2256A4D8D6AE4C5E575577BAE7EEE1BD998E9CA1B4C6DDD8CDB1A4A8B0E2FAECC6863F161A01FE3A5B070718A07B764411000B264C7C886D38181B2D529BD6E4B86D2B142A60A0D8DDCA9B51281C429AC8DDD0A85A18083580ABA9986A3E1B0903327FC3E1D4C4B1743000000015548AABAAC3CCA05B260B205EADEAF3ECE2E3C4833D2B5A9ECED0B1481D2B809B93677A936D2604225FA3BFD1C28C611A00000017465C5B4E462C2C1E180909080D0E162126282E3535343E3F3B3B44504D52504C585C51545A4C4C5247493688C8FFFFFFFFFFE1B3653328383668B6EBF3E8C2893F2B2B343E71AFCFC9903D1204081B4799CBCDA6425F5A5780B9E9EBDCB6988094CBC8C9D3D8C9BDB1A4A7EBF3E8C2893F2B2B01FE3B5B070718B07B78541C0A072354828879411B1A2D69A3D0ECC07036192B5DA6D4E3C997421C1F54A3D5DBD2A552170C3979A2B39566391A04083F8AC3D7CFBDB06D300000000E519FBABAD3CC9B50150A2B59B9EBEEE5DADFC57A37204B90C2D4AE5E203A7EAD966B828B642A1123609BCBD7C596561D00000022465B564E3933211A0807050D161D1916232B2E333B3839333745454B4C4A4F4C625C6155544E4C5351483F7DC2FDFFFFFFFFEEB674392B24325FB3E1F1F1C78545211B294272ABD3C08848090206194179C6CFAB5C6B4E5172BDE7F4DEB59B97A3ABC0D4DFD8C5B5B1B5B3E1F1F1C78545211B01FE3C5B070718C067663C0F0002204F808371401316265CA6D3E0C3692D091A4FA0C5D1C49B49261F4C9EC6E3D8A95D280F3377A3B2917444180E13428BCDE3CFC1B07922000000125699ACA8CEC8925618061E57A8E6F2E7E3DCC98731224F9CCDD8AC581F4087A491636F98641F082159A1C6D3C49C61290000001A4B61525233311C190500060C171E262831363937403736354245494B4A4F515850595156585352474A494382BFFFFFFFFFFFECC2753716292E5BACDEFFEFE9924121112B3B64A6CCB9874A0D000B19489AD2D19C475F4E5881C4E7F1DDB89B899AA5BCCAD7D4BFB4A3B7B2DEFFEFE99241211101FE3D5B070718D068663E1600002052697B713D09122B639CCEE0C17B2F15274A98CCDED1944A1E164596D1DFD6A84B16073287A8A89E6A3E1601053782C8E7DDC1A37232000000185399B9B6C7D2A6510E08235DAEE8ECECD8E4C983291E519AD4E2A8461E3585AF9166778D62210A2A66A4C2D5C08D5C19000000143F635F4E3A3027140A090E0D131A1A231F2A3235373235333B43494E4B4D50515B5B5D56514E59514E4B3485AEEEFFFFFFFFD6AA7338282A2C59A7D8EDDCC589412717283866B1CAC58D4212030D175297C9CDA85375627679B1DDE9D6AF948896A0BACED3C9C2B3B69EA8D8EDDCC58941271701FE3E5B070718E07B764E220104204F7A89754B1B16305DB6DBE9C16B22102B5AA7D6EAD593491A1C549CD2DDCBA95516113582A9AD8C633A1902153285C2D8CAC6AC732A0300000E4794B3B4C8CFA4561E0E2153ACE6EFF0DEDED47C34215D95CBD3A847163A8DB495617E8B5D1E1227649EC3D2C7975922000000244C6C64503A2D2D181302000C101B1E2A222523343C30323A3C3F4E4E4851504E54575F525056544946503790CFFFFFFFFFFFF5C67232212E3866B6EDF6ECC8805334272F446CAACBB8873C0F0E0823459FCBD0A84A615A5973BAEEEFDBBEA1829EABBBD6D6D9C8B6A8ABA5EDF6ECC88053342701FE3F5B070718F074704F1E000025506E817A3D170F316FACD2DFBF6926132152A5DEEAD8974B1F204EA1C9D5C6A75D17013777B0B29A794415030E337EBED5D0CEB0792900000012539BC7BDCFCA965411071A4EAFE5F1E3DFE3CD7E301C4B9ED3D5AA55203589AD986E719469200B2A6499BFD6CB9C64160000001C4F675D4B343129190F080004151C1C2221222D333A323D323F42515250504A5150555A60584A4A4B444E3E64A2EFFFFFFFF9DBA2581908132959A7D8F0DBB87A382626213165ADC9C187430C0A0F1E52A1D0D0A5466173627BBFE4DBD7B58E8B99A2B7D1D6D7C5B5A3A2AAD8F0DBB87A38262601FE405B07071800787E60290708284F70897F43181C356AA6D0E5C56E2B1B2E5799D2E0D8A64D221A4A99C7CAC5A15316133B85B2A1916840120518367FD3D7C4B6B0732F000000195793ADB8CFC59458100A1F60AFE8F5E3E6E4C57E31284E9EC9DEB6601D35889983737D9A6522041C639ED1D1C28E5929000000204B5F574D3B332D180B06060A151C1E2022292E2F3B3030313E4B52534A4D535450585E54555358554A45398CC2FFFFFFFFFFEFBF783E272C306AB1E4E2DBB187492D23323D6BAFD6C6883F180A182053A2C9C7A34865565775BCE7E8D8AC8F8A99A4C0D3DFCFCAB6A9A3A1E4E2DBB187492D2301FE415B0707181077684C1B00001F4E6B807039151C2A67ADE3E6C2702D132353A2D1DFD690502014439FC7D2C99E5316033175A6B5976E401A09124083C5E0C6BBAF7532000000104A9BACADC9C79D52120C1D4EA9EEF2EFE8E0CA873726599EC7D6AC521F4091A69E63768B6921022965AAC7CFC59E541B000000144E6C60524F30211811000205061119251E24363931363A353F423D40514D585461625759555A5955454A2A87C9FFFFFFFFFFEBBC77401B33335FAEE9F0E8C485452C2A2C3B6AA8D5C68F410A0008234AA2D5D0AE4C624E577EB7E4E1D6BA948C9CA8B5CFD2D4CCB3A6ADA4E9F0E8C485452C2A01FE425B070718208077501F00052752777E6E3B201F2D64A2CAD4C46D35132154A8D2DDCF8A43261F4B9BC6D9D3A5561C142B7CAFB88D6E3E1204154191C8DBCCC4A876290000001D5396B6B4CECB964E180B265DB7E7F6E7E9E4C86D2C174CA1C4D1A6532A3585AF926579976F2113285FA1CAD5C3985A1B0000001E506C6050342E241C0E010304161E2128332B2D393F3A37362C414C5041474C4D4B585152555755504E47378ED2FFFFFFFFFFF3C378312A313265BDEAFAEDC0864631282D3E72B0D6B78C4314010C1E4EA2CBCCB0525F57587DB2EAEDDAB6908DA5ACB9C9D4D5C9AAABA7A6EAFAEDC08646312801FE435B07071830776E43190002214C758872481E152868A5D4EEC572300D1C4895CDD6CB8B471E1553A4D1DCCC9C50160E3777A9AC99773F180A133E8CC6E2D7C9A87233000000184F9EADB2CAC69D5117061B50ACE3E8E6EBDED37E301F4E9BC7D3AB52233884AF8D647C95682B112859A0C8D7B98359170000001F516966544437251F1701010C1C161C281F2B2C29343430383A3C4647545355575A5B5F5B565858534C4D437CBAF7FFFFFFFFF1C66D42242A3E60B4E7F4E2BC85402B1226426CA9D0C496470B000D284FA5D3C6A0495C4C4A70BEE9EBDBB0928D8B97B5D1D9DCC4B7A9AAABE7F4E2BC85402B1201FE445B0707184076764C1B00001A4B74806B3B09142A66A0E1E5BE5B250A1E4DA7E3E2C589412123519DC6D5D4AA581807387CAEA78E6E3B120418378BC2D9CEC9B8782A000000155496B0B5C6C99A431506225DB1ECF3E8E3DFCA7A35265896CDD1AC4B1E3E83AD8567829762220029649FC6CFC08E591C0000031855735F53493C2D1C1205000C0D14151E172428303635323E434B474A4D4F535A5E5758585A534D4A44493B7FC3FFFFFFFFFFE3AC6E35212D386BB5DAF2DEBD844A241C2B3670B2D5BF863A000120244FA0D2D1A84762544C7EC0E6EDDCB3938B9CA3B9D5D8D5C2AEA5A2A3DAF2DEBD844A241C01FE455B07071850796F4B1E0003244D748067340F112C68AED9E2C36729091F5CB2E4E8CD9843141E5598CAD5CFB053100E377BAEA690633A180D103990C4D5CFC8BB733000000010509BADACC6C69A551F151757A9E0F5F5E2DBCA782B1B509ECBD9AD511A3C91AE91687D927024052A5D9BCCD5C990581D0000052C5373644D3D3327130704070B0F121D231E262A2E383A3239434652474D4650545150514C4B4C4E504D563F8BDBFFFFFFFFFFF5BF733C282E3664B5ECF5E9BB8346212031387AAECEC28841120A131F4D9CCAD0A6444C484B83C5EAEDDFC1999098AEC6CFD5D5C8B1AB9FACECF5E9BB8346212001FE465B07071860767B541C000A2B50728366421313285EA2D9EFCB6C21101A59A3D0E3C690411F1B4EA3CED5C79D5011093880AFAC88713B1106113F8EC9D7CFC29E6F290000001D5697BFB4CEC295541C0F2461B5EDF3E7E7DFC17E251B4B97CDD7AC4A1F4496AF92697A9360210C285CAAD7D9C391541D00000027577A684A40322D1A01030003161915282B33333A3D3630393B3948474E4B4E4C535F56524E4A504E434A3983C7FFFFFFFFFFF0B97A3222263767B5E5FADDBB79382C23303E72B0D0CC86440F030C215498CDCBA14656545D7AC0E9F1D7B4A6949BA6B4CBDAD2C8B39DA7ADE5FADDBB79382C2301FE475B07071870867C461200002049727F6F3C1A132A60A8DDDCB7691C091C52A6D9E7D2893B171F519CC9D0CA9B531C0B3877A6A78E6934110012438ECBDAC3BBB176330000001B5C9DB9B7CCC29C50190C2059B3E6FFF0E4DDC16F302A5D93C7D3A94F1E4586A9945E778A641C072A65A0D0CEC390651E00000124576C5F524642230F0E0304040C202524292C23333D313231383D46544E5057555558595B534F5B4A444D3C79C2FFFFFFFFFFEAB66F3426302658BCE7F6E3C685412D2A2E436BAAD8B98B440907082C52A6D5CFAA4C66564D76B5EEEDD6BF9A8B9FA6BDCFE8CFC0A8A9ABABE7F6E3C685412D2A01FE485B0707188074704414000020466D82683E16102F68A3D9E3BA6D230A1F5998CCD1CA90471E164AA1D1DFDBAD520A062F72A2B07F66381105173D83C5E3D2C7B076310000001A54A1B5B2D5C593491910215FB2F0F3E2E7DDC9702C1D4C98C8D2A055223D84AB9268828F641D102A649FC3D4CA9653110000002957807258463032110000030F0F0A101A14242E353C3A3A353949464D4B4649525D625F5C5A5453554A4C308FD1FFFFFFFFFFEFB57A3A273B3E6DB1EEF9E9A1703D3026404C81BDD8CD8A3A0A0C0F1752A5D9D1A554675D5D79BCECEFD5AA8F9AA0AEC4CFDDD5D0AEC0A6A8EEF9E9A1703D302601FE495B0707189079704C1E0006204F7686723F1E14346BABDAE7B96B281A29569FD6D6D08648232256A6CED5CDAC52160A3581ACAA91693508000D3985BEE0D0C2B376270000001F5399BFB4C8C6975418112155B6E7F3E9ECE3CE7E2A1C5497CECAA55121408FA38C60758A6122032562A7CCC9BA945C23000000255E786A544134201D10040B0918161E191C25242C313938323B4C4A4A534E53524B504C5B5158564E4C403576BAF8FFFFFFFFE7BE773D1F2E345CBCE9EADFBE893F221D334E7EAAD3C8933C110C0A1F53AACCD4A24B65565E79B7E4F1D7B490869498B8D4DFD4BCAEA6A2A4E9EADFBE893F221D01FE4A5B070718A07C754C12000332567988723311112B6EAED8DBB86628192A5CACD4E1D281401D25589BCFCDCC9E5214053681B0A68C64351406063A92C8E8DAD1B472260000001858A5BDB4D3C79E53190D225BB8E9EDE5E5D6C2762C1F59A4CDCDA24F264387B59F687D95581D0F2E72A4CBD0BD88491D000000286376704F49302C0E000500000E18121717222F38363E3D34353F4E4E484C5053555E574D5654565247473A7FC0FFFFFFFFFFF6BE7E3E2A273462BBECF0E7BA7F3C261E2D6387B4D5BF833D0E04031A439AC5CA9C405D595882C5E3ECD4C198919DA6B9C2D9D4CEB2A89FA4ECF0E7BA7F3C261E01FE4B5B070718B079734C0E0000144D777C703B19183066A6D0DBBB68280E2254A4D5D4C1813E1A1F539DC6D7C9AC4E140A3184A8AB9269380E0610419ECBD7C7C4A76E210000001D5BA3B0A9C5C89C54140C225EB4F5FBEDEAE8CC7627205399C4CE9F50213882AD915E798C6715032667A9C9CBBA975217000001295E8070524E372714070008101216212E2A2D3131342C2E3B3B434A4D484E5660585A5556544E5A4D4B493B83BFFFFFFFFFFFF6BB73352E353A63B7E5FAEFBB773C221B2F4A78C6D9C280390B080C1C53A5D3D0AC4D6450557DB7F1E8DBB494889DA7BFD4D4D4C2AFA4ABA8E5FAEFBB773C221B01FE4C5B070718C0786D3B10000420487C816B3511112A67A8DCE0BD6C27112456ACD9DFD78D3D151C59A1D1C8C9A849140C397BB6B399672F04000C438FCADFC1C5AD6F250000001754A6BEB9D2C59645120D2068B9E9EEE4E9EAC67532225698D0D3A74E1D3E8BAE956977925F1B0D2868ABD7D3BD8E52170000002663796A5844331D1608030005121515201A212B37362B30383C4052524C504F59585C574E4A494F494E4D3D72B9FAFFFFFFFFF3B86F3A252C3359B9EFF2E3B77A421D253B3C71BADAC18B35050006164CA8D1CA9E45564D5587C7E7EFDBB48A919DA8C7D1DFCDC7AEAFA6A5EFF2E3B77A421D2501FE4D5B070718D07573431100000E3D6479673D141A3368ADD1E5B1591F162457A0D4D6CB88401F2754ABD7DAD2A24F1608337EAAA7966E371506124796C9D6C7C2B0661E0000001D54A2BCB5CBCA8D5219092F71ADDCE1E2E9E0C27A2521439CC7D2A44E284888B59D6E7D8B611B113272AED3CFC29256140000002669746D513F241A08080304060D171F2026292A32372E393C32454849544D4E5B5B524E5251504B4144474183B5FFFFFFFFFFEBAE6C3326273D5FAAEAFBE6B976391F28384B7BBDC4B8823A0404131657A9D1C39B4268545D7FBFDCEFE0B98E9096A1B2DAD9D3C8B59EA1A7EAFBE6B976391F2801FE4E5B070718E07B704815000020527B7A5D311B192D68B8E1DBB35924101E54A7D4DAC5853A132251A2C9D4D29B5317093781A8B3A16D380A000C4593C0E0C9B7B064240000001854A5B7B9CEC696501509216DBFE8E4DCDCD6C97F2D285BA2CBCB9B5229428FAC8A6C8793601E092C61A1C5CBB98D5C1B0000002E7484775E4B362812090A060008171C1A1E2123363A313A3639464943474E4C50545156504D545A5546453B8BC3FFFFFFFFFFEDB2653F27353964AEE4F3EDB0743C261A2E4F83B6D2C181370E0A052160A2DAD09D4658575E80B5E1E3DBB697889BA9C3DCD7D4C0A9A2A2A4E4F3EDB0743C261A01FE4F5B070718F0726B4A150000164770766430131A3769AAEAD9BC631E091D59AAD8EAC47D3B0C18539CCFD7D5A7530E0C3172A5A693693813000E408FC4D5CABAAB7233010000175DA7B7B5CEC9944B1205215FB0F2F0E4E1E1C66F23215499C8D0A44E26468CAE896A8392611D022567AAD6D9C3884D1B00000028657F6B553A2E22130902060915101C1A1C252D33362D31363F424B4E494B4D4F555F5C59534D53534C4B368CBCFFFFFFFFFFF1BC763E27343F78C5F3FFEEB976442820344582BDD6AF8231130811294F92D3D6A750574B4D80C6F0F2D7A9848E979FC5D5E7D9BEAFA3AB9DF3FFEEB97644282001FE505B070718007665410C000013486D7768310E0B2E64A3E0DBBD621808215AA4D0DDC8883C1D1953A0CADAD09E57140E3785AC9F8A632E1710113490CADDD4CBA5672A0000001F5FB0C1B8CDC6964F1604275AB2DDF4DDD8DECA72251E569FC3C6AA5728499DAA8D6880925E1A123272A1C9CCB98B51150000072F6B87745B472C291C0D000008100C171815202A34413A333138394642504C4E515856585C464F4E4C4F543C89CCFFFFFFFFFFE8C6783D2A2E3670BFEEFCE6BD7B42221B374B70BCD6C78C3F0B060E1C529ED2C19E475D545F7EC8E1E8D3B89F949DB0C3D5D8D5C1AAA6A6ABEEFCE6BD7B42221B01FE515B0707181077744E1A000A1F4B728C683C0E103573AFE3EFB75F1E12315CB0D7DEC8883E22254FB0D5D2C9964F180F3B7DAD9D86632E0600124596BED3CBBCAD682D020000205DA7C5C1CBC28E4B1F0B175FB4EDE4E3EBD6C7772D2B619DCBD298471C3A8FAC925F7F94631E0E3077ABD3DCB487571600000033677B675A4D34240D00000108121818151C28242D312B3B343A45424B4D4B504F575C575A484C4A4F433F3E7DCCFFFFFFFFFFF3B873403135356EB7F4F3DDB57F372A1D333D7EBCD8BF86480F080C1D4FA4D3CD9F3C58565A82C2F1F0E0BE908D94A4BBCFE0DFC0AAA2A4AAF4F3DDB57F372A1D01FE525B0707182078744A1D00001E4C7F7C683C10112B66AEE2E2B961240E1B5AA5CEDCC4863A1E22589FC2CED09D4F17033889B0B08C632F0D0014459CC6DAD2C7A86B270000001A62A5B5BBCDBD89470F081767BAF5ECE0D8D9B874332558A2D4D79C4A264891AB8A6A7E8E58180E3572ABCBCFBC85500F0000002C6E896F5E493B321505000107150C10191823342D3033302B3841474B525750504B4F5559564F5C4C47453772B3FDFFFFFFFFF1BB6B33232D3868B4F1F8F5BF72382A1B2E4881B9D0C580390D04051950AAD8C4A945584B5481BCE6F0D6B09B9493A0C3D9DFD0C7ADA3A6A8F1F8F5BF72382A1B01FE535B07071830828251170000224B747F6B310F132F6CADD0E2AF5C23113267ACDFEAD18A39181A5498CAD2CFA656180E3B85ADAE8E67370D050E358FC3D9CFC0A85C1C0000002164A0C1B9CAC5944A1C0D2069B5E9E7E1D3DECA733325579BCCC99F4B1B4295A69773838C531D082F77B5D3D0C2995A14000007316F81725F4B34200B09030001090D131C1C25232E30333731393842454A4F5D53505C5F5B4A4F4F4D484E347CB6FFFFFFFFFFEEAC642D29273974CDEBF8E4B9763D1E1527508CBBD9C57C3C0F030B1D50A6D7C5974061575E82C0EEF0D5B19B949CA5C2CBD2CBCBADB4A4ABEBF8E4B9763D1E1501FE545B070718407B7153230000245276806D3C1A1C3561ADDCEDC35E220F2361ABD3E4CC833E232356A7CCD4CA9C480B154387AFAE8C5F30140A123D9BD0DBC6BBA86A250000022661A7AEB7C3BF904414012668BAECFBE6E6D5C37628295495CECAA54419488BAC936C81904F16043172ABC5CCBD865314000011426B897153483E2E14000009121216131F1D1A2C2B2E2D32353845484F514D4D4453524B4F51514E53514D437FB5F3FFFFFFFFF6AB622917283964B2E7EBDFB279330D13325384C3D9BA7E3D0900122259ABD3CDA4456154577EC7EDECD4B2868C96AABDD5D6D0C1AEA5B0A8E7EBDFB279330D1301FE555B07071850817B480E000024536A7C5D310F103470B7E3E3B36221182E5BAFD4DECA833B111B50A3CCCAC69C491A0F3F86ADAB8E61310E00114599C3CAC9C6AA671F000000225EADB6B7D2C1834315062963B9F3F6E9DAD6C26F2A24519ED2CE9F471E4391B092749192591D0F3572AED8D8BE854A14000003386F81705B4536270D030508150F12192221171D242A3D36353E43484A4850524D4E594F4D524D564E4448388DC4FFFFFFFFFFFDB9713D262F4373BDF2FBEDBD7228231B3A4D83BCD5BC82310802101B58AAD3C89D425F5E6191CDEEF3D7A8848593A9C6D7D8CDBEAAA6B0ABF2FBEDBD7228231B01FE565B0707186079754916000827557876612B13153A69AFDDE1B76126091E59A1D8E0C37D3D10215AA4C9D5C697470C0D3D7DA5B1956B3B0D00154993CFDACAC0B36F1B000000245DA3B3B0D3C08B4213102D63C0E3EBE4E0E5C674211753A1D7D294411E4E98B9936A84985C180C3677B3D1CDC080420E0000062E6D8A796445372812010001080A1313191D2D22243233322E3843434D4B4A4E4B515953564B4A54524E4E3879C6FFFFFFFFFFFBB4773C272E3F73C0EFF9E0BB83331F1C314980BED9C3803A16130F2053AAD4D39E404E4A5E8CC3F1F0D6AE8F949CA4B7DBE2CDC1ADA4A1A3EFF9E0BB83331F1C01FE575B07071870736F541200001C4B73785F2912113872B6E3DFB0631F0B265CA5CADBC27A390A1C58A6D0C9C1994E0F0D468FBDB09665270B04104E9EDCDFCBC8A8611C0000001466ACBCBEC8B8823D1208286BC8ECDDDFD6D5C0692125609FCDC7973F1C3C98B79C68868E551F163474AACFC6A77A3F0600000C2E7399805E5239250E030000000A0D1B1C23222937322C3B3D3E3B474D4D444351565755565A4B554F49453C8EC8FFFFFFFFFFECB470332E3C3C7ABDF5FFF0C0743D2F28435D92C6D6CC7A1D0904122956A6D8C2904157545F89CFF0F0D8AF908FA3ADC9D9DCD2C0A99CA4A4F5FFF0C0743D2F2801FE585B0707188079743E1000001E4F6B7F64351115306DB2E2E2AE5A251A245FB0D4DDC1783B171A59A8C3CEC99D3F0A02398AB2AD8F642C15090F4B9DD5D9CDB9AB641F0000002675BCBFB5C4C0823D09032168BAECECDEDBE1BF7125265AA4CDCF974321498FAA93738B8E4B13113076B8CCCEBA7E5212000000366E8A70644F3A1D0E0800060E09151C19161E242C272C31393B3E4F525455524C494F574C514D4D4949473C8BCCFFFFFFFFFFEBC3723123303D7CCCEDF5E7B46F36241D346690C8DDCA77340B000C1B56A8C9CF9E43594F5597C8F1ECDAB68D8498A8C3D0E2CABDA4A4A5A4EDF5E7B46F36241D01FE595B07071890666837080000194A6F76552E050A2E70B7E6E7B556120D2767B4E0D9BA8030172853B4C6CAC68F4515184493ADA8866732010B1E46A2C4D0C9CCA65B18000000246CB2B9B9C8B57F4109043174C0EAE6DDDFDFC16D2E285F9DCEC5933E1B4692A78A6E868D531A103E7AAAC9C8BE85500C0000083B79916D614D2E1E0F02000004080A15161F2425303B3F3C3C393C3E4A494A4C4C53524B56514B5454504F3898DDFFFFFFFFFFF3BA723E2F354171CAF9FCEFBA7C3522203E5C8FC9D9C582391006101950A4C8C49C4A515B628BCEF1FFD2B19394A6A6BFD1D2C5BFAC9CA3AEF9FCEFBA7C35222001FE5A5B070718A077724C1600001538607B582A0C0F2979B2E8DDAD5718082064B2DBDFC37D31122462B3C8D4CB913D0D164B90B2AF8D5926060217459FCCD6CABDA664170000002263A8B5BACFC07E3C170A2674C3EFEDDBE2DCC469211F569FD5C88D431F5298AB967482864E120D4076B7D2CBB37E470A000003437E8D785D483329150500000012191A1616182332372A2F3236454B524A4B4D4B545658544F47534A484D3E8ACBFFFFFFFFFFEFB16D372A353C6BC0F5FCEDB672361716395F8DC5D3BE7F3A12000C13519FCEC897405A4F558BC7F1F2DEB7948B969EBED9DFDBBFA7A1A7A8F5FCEDB67236171601FE5B5B070718B078764C1800001E4D7277582E120F3668BDE4E4AF4B21192963BAD4D5BF8139132064ACC7D0D19D4717104187BAB2885A2C0604184A9DCBD6C4BFA1570F0000063271ADBFBFCCBC86410D0E2B70BEECF7E2DDE6C86A2E1F5CA0CCCB933F20498DB199718184521C0E3B73ABD6D0B07B40170000093C7690715C433621060000000F101913201B1C1C30323238363C46444A444D55545555485356564E514F493D94CDFFFFFFFFFFE7AD603928314471B8EFFFE3B6763B1B15405887CBD7BB752D0005142659A7D1C3953E504F588DCDF2FAC7B58B8E9CAACAD5DCC4BCA7A29DA9EFFFE3B6763B1B1501FE5C5B070718C07272490F000023466A6F531F050A2673BAE2E3A9511813265EA5DCDBBF7E3714265FB2C6CFBF8C3F07063F8EAFA792633708001558A5D4D3C1C0A85F1C0000002467B5C3BBD7B97E37110D216DB4E8EEDDE5E0BD752A285798CDC78E42114997AC94708C8D5115083278AAD1D3BA7E451000000C477E938367483A240C050000000412111D2127272C2F2B342E3A3C45503E485356535B57504C5253544A4F3A84BCFFFFFFFFFFECBA7143323E4679CAF7FFE0C06C34121339628CC5D9BA73290D08162459ADDBC9903F5152648BD1F2F0D3AB838696ABCAD8DED9BDA59CA0B4F7FFE0C06C34121301FE5D5B070718D0726F460B00001C4374765931130A3176C5E5D69F491A0A1767ADDEE1C47635152663B1CDD6C290450C144A83AFA48F591D0504184CA0CBD0C2BBA063210000052A73B1BEBDD2B9823E130D286BB7E0E4E7E7DFCB6C222460A0C3CD9A47264D92AB976F8E8C56150F3C74B1D2CEB7804513000006478390775A472F220B0500000F10121E211A232D2931333638323A3F54525652454A5A50534D4F57574F523E94CFFFFFFFFFFFECB972312D584773C7F3F6E1B4662D0F1A445D95CBDCBF7C330A02121F52AED6CA9A4A48495F9ED6EAEEDDAD90889DAFC0D0CFD5BCACA6A5A7F3F6E1B4662D0F1A01FE5E5B070718E06968401100001E4A6A755F2607163971C0DCD8A94D170D2764B2D3D6BC772A0F1E60ADCCD6D29A440B0C3E8AB5B393532B08051F4BA1CBD6CCC1A14F180000062D70ABC4C4CEBB7C45100B2871C1E7E9D9E5DAD173231E5EA6CDC3953F1B4D97B09971798046150C357CABCCCAAC7A410300000E4281987A634A312808030000040C161E241A242C3132333729313C45474B4C4E5356585353574F584F4F453688BEFFFFFFFFFFCEAC5E282D3E486CBFE7F9E6B1713C1F1845689FD2D9BA6A2E0300142466B7DBBE96425C575E86D5F3ECDCB78F8CA1A9C0D7E1D2B79DA19F98E7F9E6B1713C1F1801FE5F5B070718F076753F1300001C4D6D725A2D0719377BC3E1DCA65D1E0A245FB4D7E2C07F321F1867B4CAD1C7973D0C144799BCA98D612106001252A5BFCCBBB9A35519000000286DB8B7B2CEBA7E3F130C2B76C2F0E3E1D6D3C975352F619CCFCCA5461A448FAD926E8D8E450A114280B4D3D4BB7A4F0C00000140768E765E4234301B000000030A12131A18242C302F282E363836434E454E4C5054554F48554A4C4C443F3E93D2FFFFFFFFFFF3B56C37303D3F78C3F1F8EAB1713723164B6B9ACCE5C170311505102D58ADD7C0923D525A6995D4F6F8D4B18B91A3A8BFDDD9D2C1A39D9EA8F1F8EAB17137231601FE605B070718007C73431000032B496F77542F1A21337ABBDFD9A7591A152C76B9D2D8BD6D2F171F62ABC9D1C2924110195293B9AB92572506001553ACD4D5CDC5A85D14000006236AB4BFB9CDB1753919142C66BCF0EBD4D7D4C37926235DA1CED29345214F92B0936D92873B16113277AEE3D5AF7449080000024482937E6C4B2F1D07000006040F151E181F292B2A2D33302D3F46444844454F4A4C5B585E594D52504D4D3A8EDCFFFFFFFFFFF4AF6735263E4382CEF9F9EDBD74311A1F406F97C7CEAB6C2E130C0A2453ABDAC79440595B618ECEECEFDAB2878F9DA7BFD7DCD2B99DA1A5AFF9F9EDBD74311A1F01FE615B070718106A76440E00001C4C6B6E5A2307163B80C3E2D3A65B18112768BDE0E7C172331F226FA8C6CBC48A3B0D104386AFAF8B532404041855A8D1CCC6C6A559120000012E70BDC7C6D2B37B360B03236DC4F0F3E2E5DCCA6D2720559CD0D09535175595AB9F7D92854B090A3E77B3C9CCB47C4C0B0000043D808E81614A3A24090500000508101B1A221A213037333332383C43484B475051515B62605C5650534B40347EB5FFFFFFFFFFE6A368392B3E4680CBF8F8D7B2723510173A6096C5DCBD792B04080E3055AFCFBE873D574F6999C7F9F3D8AA8D8392B2BDD6DDD3B99F99A2A4F8F8D7B27235101701FE625B070718207D6F441700042B4F6F7A602B13163A79C9DED3954D110A246EBFE2E2C2793A17276DC2D2D1CA8E370F144A88B3AC89542A0F0A245CA4CFD9CCC5AF5E1F0000042C76B3C6BFC6B6753A080A2972BEE8E8D3E2D7BA6A27245CA5CAC78E372357A2B99F768A84450E0A4A89B7CDC8A6783C060000094885957960473C1C10000000000A11111B17262931333534313839413D42474E54515457584F56554B454A3682C8FFFFFFFFFFEFA3623B2C2F3B75C8F6FDE2A36F351B1E38639ACED8C371230705111E5FB0D6BC8D3A4B596CA1D3F2EAD9B29592A3B2C0D4DACBB7A49CA1A4F6FDE2A36F351B1E01FE635B0707183076703E07000026546F744E220F0D3381BFD8DCA04E1D11296DAED5E0C56E3416256DB3C5D9BC8838070B4391B5AE895322090C1D59A4D0CDC8C3AC570A0000082771B8CCC0D7C67B35090F2C6DBEEAE2D2DAD4B85E222B63A6D2C7913C2254A0B89C768183400409478AC2CFD8B6743D0400000847879878543F311B0500000005130A0E2024262A28333733343D3D404A464D4B4F54545B5B54514F4F47473480BAFCFFFFFFFEE9AB6F3E3D37427ABFFCEFDCAC703013164472AFD2DFBA6F2E05030B2258B4CCC1883A4B596AA0D3F2F1DBB08F879DABC0CED7C7AFA1A6ADA7FCEFDCAC7030131601FE645B07071840837D511C0009284D6F7B5A2E15223E84C9E4DB994C180C2D72B8E1EACA7830172977B6D2D3C79A3C060E4C91B5AE864F2506061E50A2C4CAC6CBBC59110000043171B7BBBDCDB26E2D0D0D3B79CCEEF0E1D7DBC1651F2460A6D1C987371B489CAB967686753F0E0A3F7AB6CEC2B37A4809000016488B9C7E5E433723060000000A12151C1C1E25282C342C37303B4649443E46484D52564B50535D4D5146533B79AEF3FFFFFFFFD5985D30282E4379D5F0FAE2AA6432191A3A6C9EC6D3B4732900000D245FBCD7C08B3E4B556D9ED2F1E6D2AA889092B0CADFD9C7BB98A1A7B0F0FAE2AA6432191A01FE655B0707185072673C14000025466C6F492B101B3B89C8E1D0984C150E2A6FC3DFE1B6722D152974B5CCD3BE8D3F11104E88BCB0854F240803175EA9C5D0B8BAA05C160000022D80C4CABBD3B8712F090C2C70D0F3EDD5D2D5C05F211F629ACDC78A3F295BA1B29A6D878647080E4080A7C6CBB17D4A030000184892A27B5B4A2C1B0300000308121B1919181F2A2A312C2C2F32393F473E454A49555B544F485156534B463E8CC2FEFFFFFFFFE1A9653F343E4486CEF9FCE3B272351F22466A9DCFE6BA792A0F00061F62BCD4B7893E4F546DA3DCF2F0D0B1888A8EA2C2D0DEC9B39B8FAA9DF9FCE3B272351F2201FE665B070718606D6F3E0E000724567679532E0D1C3A72C0DFD3AC581D1D3D75BBE3D2B36A3219287EBCD3D5C28C36060E4886B2AD7E5B2909062066AECDD9C0C4B25E140000002B76B6BCC2CEAF682A06083076BDF2E6E1E6DFC4661F2763A4C2C291462F5E9FB08F7784813906094193B4D9CBA7763D0300000D508C9E7F634B3823030600000013131B222421202C232731363F494644474A494C544E535353494C4D4B493C89B1F3FFFFFFFFE59D60382F374B82D1F3F7DFBB672413164171A3D5DCAF6C2A090E0C2366B6D1BB84384B536093D6F1EACFAE6F7193ADCCDAE0C7B6A1A8A4AAF3F7DFBB6724131601FE675B0707187076714B0F00021D50706C4C2105133B82CAE2D59B4A1D0B3775B9EAE0B867231A3178BED1DBC57931090B409AB3B1884D2304091E63B0D9C2BAC1AA5A100000003175AFC1B6CFB6723006033579C7F2E0DCE7DFBF66242760AECFCA994124639FB591748A8B36021B3C81BDC5BFAD733C0000000C478A9B78614736240A000000051311162226282F2F313038283C4040494246514C525952525152534B47483988B6EBFFFFFFFFDDA2633A263E4B7CDDFFFDD3A05D2A1B16486CA1D2DDBA69230000062A59ADD1BF88354D506BA1DAF5EFCFAB8C8297AACAE2D9CFBE9EA09DA6FFFDD3A05D2A1B1601FE685B07071880797C440E00062957767B59300C1C3F8FD3EADF9B4916163A73B0D7E4AF67270B2D74C1CED5C38B3F0813558FB0A080521500092463B0DBD2C7C3AA51120000033573B6C0B8CBB57330050D377BC3E4EBDCE3DBC265282D63A8C1CA884028589EB693718B7E3007124A8BC3D2C7AE6E2F000000104F8D9A7A6344312009000005010F121A1F1D232525313B3931373C4E494F46504D52565454445158504948348ABDFFFFFFFFFFDAA9662E2D444F85D9FFFCE6A7642E16244476A4CACDB3672F0D09092162B1D9B78238525E6B9DD6ECF1D2A6808390AFCDE4D9C8B5A19CAEAEFFFCE6A7642E162401FE695B07071890747F4C1C000A2B4D6F74532F0E1B4196D7F1D6985116143171B5DBE9C074261D306CC0DCCEC883330F164992B0A78B5A2B0303275CA7CDD2C0B99F55190000023682BEBDBCD6BA743310083674C8E7F1E3DFDFB96216125AADD0C2853A225B99A7967987803908174A84B8D4C3A8693F1000001253909E8165492D1C06000000070D0B081423232428312C35293A3D474A4F49525051525451524C554D524B438DCAFFFFFFFFFFEAA0643D38465390D9F7F2E1AD582B0C19437BB5DDE1AE5D1D0512142060B5D4BC8436505A6EA2CEEDECCDA57F829FADCADDDAD5B89F9895A1F7F2E1AD582B0C1901FE6A5B070718A0777A3F13000020526F69531A0813377ECBF0D79745130C3574B5DBE3B371271F297FB7C9D2BA82320F125195B6AB87521C0D022269A5B5D4C1B79C5A170000023A7EB7B9BBD6B26F2D100B2E73CBF1E2CED7D2BD61242972B3D3D08E391A60A3B99C7987713400054B91BBCFC3A9643E000000185F9AA484605237190000000001090B161C1C2623252F292D323749494948484D4B505851545356585346493D8BC4FFFFFFFFFFEDA6664136435094DDFDFDECB1692B1F2B497DAFD6D4AC6328080F0F2964B8D8BF7D4051596F9CD4EFECD2A488989BACC5D6D5CBB9A2969E9DFDFDECB1692B1F2B01FE6B5B070718B07F784510030022516F774D2C0F1F448FCCE3E1A045101A356EB7DEDEB06223182F80BCCCD1C279340B155091B5BC884B1E05103268AFCFC9AAAE994F150000093C86BEC0C6CEAF67300E072E76C7EAE8DDD4DACC621E1C6AADCEC98B38285D92B09172897B310616468DBDCAC9A3774000000013629C9D77604A2C1C01000005080D151A1D1F1A3031312A2E322F3B4C514A4C515A595A46474853514D4B49388AB9EFFFFFFFFFE1A6603229385C8CD2FFF9D7A4702517224179AADCDDBC72250912181C63BBD5B87D3B525C6D9ED6F1EFD7AC818293A9CADBD2C7B4A58997A5FFF9D7A47025172201FE6C5B070718C0747C4F1600103054676D522E14213D8BD4EEDB9A441A123577B6DED6B470281D2D80C1D7DCC2772D060C5CA4B9AA7E50200000256DB5C9C6B2C4A14B0B000007367EBFCABECBA4702D0F093B80CCE9D7C9D7DBC46924245FA6D4C988341D5E9FBA9A7D91743510154F92C1D2C5AD7037000000155DA8A5815F4023220D0000000010131011191E242D37363131303F4340464B4F4D5250494D59575A51504E358BBFFFFFFFFFFFE79E6839353E5495D9FFFBE7B362361B1C487FB8DEDFB36627040314336BB4D1B67C32505F75A6DBF6EACFB08E869DAEC4DED1C1B8A39699A8FFFBE7B362361B1C01FE6D5B070718D070733F1300062C4B6D6A4B1E0E1C3D8BD2F2D8953F1D11326DB6DEDFB0672D223981CAC7D2C17D2F0B14599CB5A4864A1C000A2E6DBBCFC2BEBCA148130000014593C3C1B9CBAB65240B12397BC1E8E5D7DED9B9601F2A68A8CBC48B36275CA4AB8D7B83772D06145091BFD1CAA36F320000001461A4A685674F2D2009000000031208131620232929303735303E474A4A3D4B534C50585051574B434750493584C5F4FFFFFFFFE5AF5E373F3E4D92ECFFFFE998542F161E4488BBDBE0B4642310060D2066BBD1B67B2D51556EA7E0F6ECC99E848598B0C4DEDDCBB197939DAAFFFFE998542F161E01FE6E5B070718E080764D1A000D30587366542F111F4895CCECD48945151E3275BDDCD5AC6A270E347AC8CBD5BA82300B14559CBBBC8D4F1502022276B5C9C5BABA9A4E0F0000023986C2C4C8CEB06924030A3182D0F1E8D0D3D4BD53192460A7CFC08039276AA7B99F7F8B7434111E4D98B8CBC19B6A3B0300001F62A5A7816A5130160000000000050A131A1B21242834333832323A3B40464C4548565352534F5C524D49483988C9FEFFFFFFFFE5A96442394459A4E1FDFFDFA36137191B4A86B5E1E5BC6C260502122A6BB7CEB6A139534D6DAEDEF5E2C6AD868199B0D6E0D4C3B29DA3AAA4FDFFDFA36137191B01FE6F5B070718F06F784F1500092A536A68511E061E4585CDE5D08B4225183177C2E6E1AC5C211A3D8DC6D8CFC47E260D105698BAAD81491A0C0A2876AECEC0B3B49A530E000015448BC4C6C0C4A5611D050F3788D6F0D7C8D4C9B66721266CB1D7CD863A3068A7B9A7788C692B0514508DBDD4C3AD642F00000011649FAB865A46331F0300000000070F1B2121242A2836333735363D4140454C5558595C5E5646454A493F433A80C7FDFFFFFFFFE59F6346433D629BD6FFFEDDAE6A2B151A4188BADEDEAE5E230212193165ACD1B27C2B4F5670AADFF1EFCEAC89849DB2D3DFD6C19B959A9DA9FFFEDDAE6A2B151A01FE705B070718006E7143130000214F676B431A07174091D7EBD2954B151F3373B1DAD6AC632517408BC1D7CABB81300C23588FAEA67F4F1D08093577BECDD4BEAF9A4C0400000D3B8FC9CECBCDA65F30070D357CCAEDE4CDD7DBB756212F6FADCEB77D35295CA1AE9177896B3105165297B8CDC5A1672F0000001F68A4AE7C5B462F150900000008151114191B233128312E383B3E444147494A44444D5D4E544B47545156462D85AEECFFFFFFFFCD975A3236385297EAFFF6D6A04E281E21528AC3E0E3BC5D1B0000122660B7C8AF7A3B46546CABE9FEFBD4A68A899AB3D2D9D8CCB295979F9BFFF6D6A04E281E2101FE715B070718107A793F0F000932557469481F0915458CCAEFCA8F3C13153677B9E1EAB65D180F2D8ECBCED4C0882A0707469FB5AB7A431C0416367BB9C1C3B2B89C4F1500000A4289CFC4BCC4A85827080D478DD1E9DED3D9CCB7692B387DB6D4C47E353063A0AD9A7A8465260317509BC5D3CDA1784100000018629CA689614C33190000000B02091617131520232D2C2D31393940443F3A484F4D505A5752524E544A4046377BB3E4FFFFFFFFD595513E33424B8BE0F9FDE79E57280D1D488CBAD9DCAC5E17070A142B6FC0CFA56D2C52607EB6CFDDE8C5A18A89AAB6CAE2E0C8B1A79EA19FF9FDE79E57280D1D01FE725B070718206D71410E0000264365613C1A0E244B99D9E6D294420E133A85CAE9E4A254211B3B8BCAD7CFB46625071E5B96B2AE824A23010B357AC3D2C7B6BB9B4A0400000E4096C6C2B7C0A9651D00113F88CEE8DDD0D7D5C15C1A2276B0D4C2803025719FB4A17D856F2F04205E98BDC5C8A467310200001E69A2AF825A45241501000000080813141A182022242D363732343D4644495255534E514F505050534E46433587BEFCFFFFFFFFDBA5643933435DA5ECE2DFD9A15F27181E4F96C4DFE2BF65240D060C2971B7D0AE752A4B5874AEE3F1F0C89F8A849BB8CAE1E5D1968F95A1A9E2DFD9A15F27181E01FE735B070718307D7B460E00082F496F64461F0F1C52A5DDEBC383370B163F86CBDEDAA1591412318CCCCFD6C0731E001E589CB7A788471E00063274B4C9BEB5B6A0460900001F4F92C3CEB9C7A45E2B0C103C80CFE6DCC5CDD0BE69213473BADAC57C373162A9ABA076826B240B215C92B7C3B293692D0000002669AEA4826B4A2D100200000712181618201A1B262C3328292F323D433E485157514B55525052504F4D454C398EB9F6FFFFFFFFD69E5C423B4053A3ECFFF5D8A95A2812235A94D5DFD8AF5D261412172872B7BFA770344E6477AFE0F1E9CD9A83848BB9D6DDE0CAB29B9CA1A6FFF5D8A95A28122301FE745B07071840727B431600083554625E4E200C1B54A2DDF1CB8139141E4192CDDCD9AC591F193B91D3D0CCB57020031F64A3B29F7B4F1D04053675BBC2B9B5BE96430D000012438BD1C7BAD19F5123091D4B99D3E5D8BED3D3B851192C7FB1C2B97D3F386FA7AD95818A642608205998C4D3D1A76D2E000000136FA6A6805E47261600000000000F11181F201F282C38312B32453F3C3F424A585355534E5155594F494B4D2F7DA7E7FFFFFFFFD99E5C3139485AA5E8FFF7DB9C58210D225490C9E0EAB6611C060D172B74BFD5AB74384A5C77AFE5F7E9CF95737997ADD0E3D5BBA79E9A9DB0FFF7DB9C58210D2201FE755B0707185072733E1100032F50685D341E0C1E52A2DCEFD2833A0F1A4284C4DCDDA15624183F97D3D4D9B96C260F1A62A4BAAF7B4A150107367BAFB9BEAFC19C490900001C4C98C8C8C3BE954B1F0315418DD2E7D4C6D2DAB153183F7BBCD5BF7C2C2764A7AAA084895D1E061C4E92C1D8C2A26F32000000296BABAF866F4629120000080200061014131C1D222A302B2C29334341474B4E4A544E4C4C5B5854515F4C55387FB2E5FFFFFFFFD38F523A3C5562A5E7FBF2C2935F2A161F4B99C7E0E4AF5B180B13153474B9CEA2702C4D5B7EB3DEF6EBD09C79849FB9C9DAD7BEB59D9396A0FBF2C2935F2A161F01FE765B070718607F8248120008325F746C451A111F57A1D6EECD7B3E0C194D8CD8F1D8A249201F4D97D6D8DCB9762108135E9DABA07E4510010C327EB8C4BDB1B18E4A080000135995C7CEC7C5A150280E154C8CCDEBCFB2D0D8BA521E3A74B2D2D382362D65AAB29C818D6516001D548EBDCEC3A25D2D0000013273B9B5815C422615070000000D0C101113161B24232B33362A2E37414147555550515B5953554C4E5249423C83ABE9FFFFFFFFCC92573745485FADEBFFFFD592532315275695C8E4D2AD6226030315317EBED9A4683252607CB5E9F8F0C984787F9CB1C9DAD7C2AD959AA0A7FFFFD5925323152701FE775B07071870817A491000072B4C655B3C1C1422559FDFE9D3823816264C90D1E6E0984F2017409DD3D1D2B9661A000E5EA6BBAA7A481A030C3687BFC0B0B6BA96450700001E52A2CCD4CBCF944B150B184F95CFEAD3BECFCEAC591C3876B2D1CA77262369A3AC9E858E671E00145797C7D0C1A56D30050000267CB0A485603B26110000000007060D161823292A31303C383140443F45424D464E555F52514C51534C4B502F7EA9EDFFFFFFFFD99D67455E606EBAEAFFFBD494512814185699C5E5DEAD55250400132D70B7C7A5662E4E627FBBEAF8E5C2988E7D8BB6D0DDD7C7A9928FA4A6FFFBD4945128141801FE785B0707188081824A09000D3552665E3F24162553A1E1EEC66E31162B4A8FCBE4D5A44E1B194399D3E0D6B36B1D032369A1B1A97C3F12000C3E8BBECBBCB4B5954505000012569CCFC7B9C495481B06144298DDF9CFB9D2DABB57163481BBCCB7732D236EA8ADA0858D5B20041F5C9BBBD6C29F6A2D0000023077B4A584654124110000000100140D181E1A22202B2B1F34322E46414448535358584F484A4E5A58544A4D3A80A6F2FFFFFFFFD19564402A467DB8F2FFECDB98592C151F5AA0CBD7D8AC551A0705153480C3C99E7236495E85BEEBFAF4CC9D7A7693B5EDDEDBBFA28E9C9EA5FFECDB98592C151F01FE795B070718906265360400002852684E3E1E152455A4D8E7C56D33141B4F89BAE3D79E521C1C4995CBD8D4B27124021B619AA9AC79431300104382BBC4BBB7BE8F3F0000001D59ACCACCC5BF92521D05174C96D5E7CBB7CCD1B44C283982C6D1BB68303171ABAE95897B5B15002567A0BCCBC9A16F37000008316DB3B37F5E40180500000000040C120D0F1A291F28372C263429364045494A4D55565B5551474D504C454D3888C0F4FFFFFFFFCC8C5F4A41587BBBECFFF6D4935929092267A9D2DDD7AC521A0E031A3789BBCA9F703A4A5D8CBAECF4EFC398747696B3CADFD0ACA293989DA9FFF6D4935929092201FE7A5B070718A07672380700022657696443251328519FD5E6C375320E174F97C8E9D4A0451C1E489ACBD8D7BE691707256DA9B6A074340C00104087C5C1B9B1B1894E0600001F5DAFCACCC4C997491104134D9DDBF1CEBDCED5AD561D3580C4D2BF76302F6BB0B19F868F4F13012A579CC9D0BCA1651A000000287EBCA48D6B4322050000000000100F0D12111E24282D2D332D3A49424B3E474F4B4E4D52545656524C49524186ADEBFFFFFFFFCB91683F42577BC7F6FFF7E4996522111E5AA6D3E3D6A5521F0E01193577C8D29B562F4D6585B7EAF4E3C08D70759AB9D2DDD5BBA2928C7495FFF7E4996522111E01FE7B5B070718B07D72430E00163A537361461C0F2562B7E5EBBD66311529548AC2E5D3A6451E2A5BA3D3D7C4A464170C2275A4BEA57B3F150A07478FB7B4A5AEB787360200012760B1D7D0C3BE904C190D17419EDDE6BCB7D0D8AD4B1B418FBFCFB8692E3479B0AAA188854D08032468A2C3D3C59C68240000003282AAB68B65441F0D00000000040D14141223231F2A342D3432343949403F4241495C574C4B5354584D4B432F749AD4FFFFFFFFB9864D37444D72C0F6FFF6CF8D4A270E1F5CA4D1FFDCA14C0E0503143576BEC29B5D304A5C7FC4EAFFE6C897747181AACEE0CFBF9C8F96A5AAFFF6CF8D4A270E1F01FE7C5B070718C08B86451602203C596D654A1D162B60BAE6E9BE722B12295594C4EBD18F3F0D2459A1CDD7CAAE5F20082A6FA8B19D783C191019438FC0B5BABEB689410600002867A7CECED1C38A441A0E174C9CD9EABCA9BFCAA647224181C2CEB377342F77B3BAB09286480B011A68B1C4D0CDA4692E0000043D7CC1AE896E4A2D1100000001000B191018111C1A2725222A30333F3A48414349585C4F594F5152524E4C4C387EA8ECFFFFFFFFC9815834355483CCFFFFEECF974F1F121758A7D4E2DEAA531607090A347EC0CA996835505D86BFECF8EEBE96707998ADDAEACDB69F93979DB0FFEECF974F1F121701FE7D5B070718D0725F2F0A00002D4A55573B14092D66B1DFE4BF6A2B19245298C1E3D7964813245DA9D0D1CCAE5B0F001E6EB3B1A0793E1205134C93AEB9B7B6B6822F0200012566ACD8D2D3D1963E18051B5A9EDCE8C8B4BECC9A40254984B6CFB667282876B2A99E8683410B06276BA2C0CBC5A2702C0000113F8FC0B98D7553280A00000000080A0D1311151E2226282B352C363A3B4D45464D5157554A4B4E5056534C4C3D7B9DECFFFFFFFFD193543F445A7CCDF4FFF0CD7C4C27161F6DADD7EBE9AA4E1A0C061A4486BDC79D6C2948598EC1E7EDE4BE8D6C7493AED4DFD5BDA291989AA9FFF0CD7C4C27161F01FE7E5B070718E07E7C400F0011395F6C5838190A306DBDEDEAB666270C27589AC8E3D98C3E0F1F4CA7DCD8DAA7551C112875AEBBA7743F10071C5198A9AEACADAB85421000022F71B4C7C7D2CB943F140C1F539BDAD5B4A2BFD2B44C1F3D8BC5C9AD64333877B1B49990814511022C63A1BDCEC1A7702B0000033D8EB5AB927D50270900000000080A070A1616161E1F2A32322E2E3B41484D4B484E58564D554F4B514F4449337A9EDCFFFFFFFFCB80554748608DD4FFFFF2C1894422122670A2D3EADBA74814050B164993C9B890552D576983B6EFF7E1C39870869CB4D0DBD7B4978C999FA8FFF2C1894422122601FE7F5B070718F0837547110013365163643A22173172C2EBECC26E2618225CA7CEE2DB9345272B59ADD1DCCCA94F0F082474B7B59D79430C041557A2B9A4B0B4B38539000006346EBAD1CDC9BF7D2D0A001D61A9D2DCB9A3C8CFA449194789BCCFAA5726377FABB1AB937F410E023B73A8C2C8C6A26C25000003418EBFBA9D76471E0A00000000020B090F1E201C2732352B333234394342455157565657554E4B454B433F3E2D7494DEFFFFFFFCBB7852494E5991D9FBFFE8C38344181C1F69A8DAEDD29F4F08090F193E89C6BB935A2A4A5E8AC9EDF2DFB88568789FB9D1DAD1B39E93999AA4FFE8C38344181C1F01FE805B070718007A662C0D00063F56615C3519132A6ED0E5EFAE5925142E68A1D7DFCF80380E285CB8DCEFCBA05213062F81B8B1967338160C2566ABBAA9ACB5AE7D31000007327ABCD0CCC9C88A2F06002763ACE9DEAEA7C4CE9643284A8FC0D5A857203175A6B7A49A7E3B04012B71ACB6D4BFA4712A0000023F88BFB8977F4D1D040000000009080A0D1816191A27332D3231353D414D494A51474C4E4A4A4E4D4F444F4B3A7B9AEAFFFFFFF7B27963534B6393E2FFFFE6BA7B3B20182E73B1D9EBDA9E5111090B244B93C8B88A5B30465C89C1EAF0DAB2886B819BB5CFE0CCB09590999DA5FFE6BA7B3B20182E01FE815B070718106F6336100619415A615E4C2B193874C6EEE6A958200B2C75ABDBEDCE81380D2862B7DDE3D3993E0605357EB2B398793B11072D6BADB1A3A4A7A17123000008438DBBDEDFD8C1823308033173B8DED2AB9CC1CD923C194B90B8C5A44D214881AEBAB89F7B1F00023870AAB1C2BFA16D200000084498CDB1A28347240500000000080A0D0E140F181A272F282B2C30373F49504B4D525557574A42444D484348337B9ADAFFFFFFF7B07D61545A6AA0EAFFFFECC4792F26082E7CBCE2EACB854C1A1517265091CFB8844A2542658CC4EAF9EABD866E759CAEC6D2C8A78B8F9196A2FFECC4792F26082E01FE825B070718207B6B2B1D132547585A644B281F3581D3F0F3AD5020173C75ADD3DFC7773A152171BDD7E0D1913A06032D82B9BBA56E2F0A0E2968AEAD9FADB4A66D1F0000134A9AC1CAD0CDC0782305072A72C5E0D9B1A1C2C189341F5A93B8C39140294B7EAFB5AD9E7828000A4387BDB7BABAA2702C000012599CBCBCA88849190000000000000712100C0E12101E2D28312A2B3B41413E4A494A54534B5449564E4A4D4B38748ACBFFFFFFE8A779615F6581B8F0FFFFDFAF6C362928436FB8DEE3D08B3B190D0C27589FBEAE733822425C9EDBF2F7E0B17E686C8DB2D7E0CA9A878F899DA4FFDFAF6C3629284301FE835B0707183076692B1114264B55675F49352F508EDEFCF49B4316214485BCD8E9BE6F1D132E7CBDD1E3C68030020A3F8CB4AD9C652A100E3B7EAFB09EBABB9F551C0000175098C9DEE6DBBB742C06103A8ABEDDD6A89BC3BC78241F59A5BFBF9642223E86B9B7B2AB6F1900094680B5CABCB2A66D2400001E65A3B4BAA68B5313000000000006040B091212161D1E2E2D292A3946413E3D3E484B535854534E4C5548484336748FD4FFFFFFE0AA7E666A6787BBEDFEFDDBAF68323523307EBFE2EBC883350902152E6BB0C1A46E41253C5495CEF5F0DFA9796C7793B0D9DABA9485838C8E9AFDDBAF683235233001FE845B070718408362331E233F5C7684816237305EA6EDFCEAA1401A184B8FC0D6E5B6622C0D3D7ABDD6DAB8772600134D95B9B19566240C194B83AAAAA0B4B78F450A0000155EB1D2D3D5D8B76B250812468ED1DFD9BBAECAB27424256CA3C9B7813C24498BAAB1BEA36519000C4690C6AEAEAEA36D2500001E6CA7BDB4AC85521400000000000C0A0D121B0A1A161E212B2E28363F3748434244484F4D46534C4F4F464A4735869BD5FFFFFFD7A484706B7198CFF6FFF6CFA163332E2A488AC6DEE1BE752A0005092C69ADBE925B341B2D5CA4E4F9F0DAB17D6E6882B2D0DCC48B75808697ACF6CFA163332E2A4801FE855B070718507D5A2E14294E6A708782673F345FB4ECFCE991370C1E5292BFD6E1AE5E29193A8AC7DADCB36720081C59A0C6B4A467280613489FBEB1B0BCBA87430200002466B2D7D6CECDB35F1F0E1E4598CCDCDDC5B4C6A1531E2771A2BFB676282B5692ABB1A998600A0013599DB2B4A7AE9F6E1E00002E77A1BAC8B07F3E140000000000020C0F0906171D1922302E2C30343C3D3C423F4845484C4B484A3C474F49443F7C95D5FFFFFACEA787776F82B4E8FDFFECC99D533C34274491CDE2DAB9772B0A00143474ADBD90543128345CA4D9EDEAD0AA7F736F90BCD2D1B98D77817E889BECC99D533C34274401FE865B070718606D531E1A274B687C9C9661292C52AEEDF2DC842C0E245BA0BED5D5A14A1C154083B9D0CEAC571E002762A2BDB9A66119061D579FC1B0B5C6B47E3C120608346FB6C5CDCECCA4460B03124EA0CCDFD6C3B5BE93490D2B6CAEC0B580312B5695AFA8B99F5401001A5F97B3ACADBBB7701A00033B82A9B4C2B58842070000000003051010030D1216131D241F252622364442454944474E4C4A524E49454A4B4E397793D3FFFFF8BF9568737083B1E5FFFFE7C38D6448404558A0CADFCFA9762100000B4481AFB385492C1C376CAFE3F0E4C3936A5F6672A9CBD9BC95787C888DA0E7C38D644840455801FE875B070718706948241E2B516889A2A0653D3765BCF4F8D6842D1A285E9BCACBC3843D130F4189CDD9D6A1561B122C6CA4BDB99F6D2B0D1F5BA4BDBBB8B7AA69250000002B68B6D0D7D1B995430F091F64ACD0E0D9D0C2B97A34103A86B0C2AB72372F60A3B9B3AA8D4100002966A0BAAFB8ABA5651F00013F84ADC3C3B37D380900000000080D0D11081315191F1E21262B242E3B403D42424145504C454B4C4B4E464A4C3375A0DBFFFFEBBDA28E7F7383B1E3F7FFDDC2975D4A47526F97CED7CF9E5C1B0000134788AAA66A3A25234972B3E5EFE1B699756F6E87B8D7D4B2806E707E87A4DDC2975D4A47526F01FE885B0707188078593229375B768CB3AE6E3D306EBCF0F5D5772C142768B2CDD6B77A351110459CC8DACC97420B0D306DA2B6B88D6124112764B0C4BBBFCCA067280000003676BCD7DAD0B88F3A08042163AFD8E1D0C9C6B3742C0B3485B7C0A96E2C3165A2ACA6A6843A01023067A4BCB0AEB3A76B2000044890B2C3C1B580320000000000080E09151516170E0D1D283127282E363A44393C3E434C484A49494F4E554F403987A2E0FFFFE5B7A19A83758EC5EEFFF3E5B995655D5C4C6B83C5D8CE95572400000B438AB5AD6F3B22184771B4DCE9E0C3916D636E94BACCCCAD7B7278838394E5B995655D5C4C6B01FE895B070718906C502425355F8399CAB663333369BCF5FECF7B28163069AED0C5AB712609144C98C7CFC78D3808154181AEBCC1965A1F173473B9CFBCBFC6A866180000002B79BEC7CECFBD8E360907266AAFCDDCE0D7C8AA631D0A4792BBBFAB692A346A9AA9ACA9863B0300327EB1BBACACB3A15F0B000C4E99AECAC4C4813300000000000D0E0E0B100B0B1913152E2C29282A394045363B3F43494F4A4A4F5B5449413A2F76ADF4FFFFDCB68F87807084BDEFFFFFE4B1956656655B77ABD6D8C0905F1600001F518DB6A1643120214178B6E3E6D7AB836E6F7693BACDC7A981746E76819AE4B1956656655B7701FE8A5B070718A075472521345C87A6C4AF6534346DCAEEF8D0691E112067B1C1B79E58251018579BCCC9C28B3B0A0A3A87B1C5C3A359201B3884C3CDC6C0C297591A0000003B82B6CED7C3AC86320A132871A7CDD5D4D0C89A5422144395B9B59B5D2E3067ABB3B2A485320000387FB4BEB7B9B2A05C18000D5394AFBAC2B9843500000000000A1415190F070B0F181A24252D282A30323A393D48465051504E444C524249433C82AFE8FFFFDAAA968073728BC6EEFFFFDEAE8C645661627FB8CCCABD8A4A090000014689B19D5B31211F3B78B9DCE3D9B48C6E727393B5CFC9A770636A7C7E90DEAE8C645661627F01FE8B5B070718B073471B21336487ADC3A85D30366FBAEDEFCC6A24153977B5C2BB9C59210B185F94C8D8BD7A2A17164389ABAFBD934A19133D89C4CBBFD3D2A559110000003785C0D1C9CFA9782B01072D77B3D7E0D2CCC79A4B0F114997B3B19C5E313673A9BBB3AD762D00003A81B6BDAEB3B4A85A1D00195B96BCC2CAB37A2A000000000614121616130E0D111815221B252725323D3F3B3D41444B4D4D4A524C4B4746463875A9E9FFFFC7AB97836E7C92C7F0FFF2D2A7896E64636078AAD1D2BA89410C00000F4B8FB29D622A191A457AC4EAF3D1A8845C6A7B9AB8D5CA9D716D70747D98D2A7896E6463607801FE8C5B070718C075522927437095C5D6AD6734347ABBF1FACA6D22183478C8C4B5924E1D112064A4CFD4B47329061553809CA9B194542424428FC5D0CBCAC89D5010000005378CBDC3D5C5B27326000B2F70AAC2CDD8DECA944A140A55A3BCB29853323674AAB6B3A8812E00004089B8CFAEB1BCAC5A13001E5A94AFBCC3A3712C000000000911181B11151415091318282F2D212B383B473D453F4E4D4945434C4744453F3D387AB8F3FFFDCCA39F947B749DCCF4FFF5DCAE8B6960686E8AB1D0D1BA8D4D1A00000D5792AA995A2B21204A82BDD9D7C0AB826E6C789BBFDDCAA278686880808DDCAE8B6960686E8A01FE8D5B070718D0744A1B2332619EC3DDA962393270BEECEDBC551810347BBBC2AB8148220920629FCACBAD742C1419518DA2B6C0904B231E4693CBCFC4CCBDA5550A0000093E90BED5C7C4A879230002357DB8D5DBDBC9C28E3A0E105CA6BAAB9C5E303B74A2C1B3AB7C26000A4F8DB4CAAFB4B39A4A0A00225EA2B6BFC6B07F2F000000000B191B201E100E0814160D20222C2429313C373A3C4144464C4B4A52524A4A473E2679ACE7FFFFC1A2A698757F9DD6FFFFF7D1B28F6A69786B78A7C8CEB88D3F0400000D5A96B98F4E322E253D8DCAE5D3C2A97F71727896B6D6BD98756C72777E8FD1B28F6A69786B7801FE8E5B070718E072462422366D94BCD6A253263079C9E9E6B857201B3888C1C5A186441F0F23629EC5DCB56F27131B5394A5B2B98A4F1A175096BBC8CBCCC7924A0900000B4888BECDCDC8B2782A0506327EB4D1DADCD2C2883D0D115AA7C2BA92431A397AA5B9AAA56D1900114B8CBFC2B3B9B4AD530B002361A7BCC9C9B47323000000000518201B110F0E0F11111E22202A2C33352F3636424242444D4F414B4D4A4642403088BFFBFFFFD2A2A39B6D7496D4FAFFECD4A78772686D6B8AC3D7CCB383390E0000205697A6924E2418265092CEDAD1C3A37D667D808FB7D2C59A7E6A62717A94D4A78772686D6B8A01FE8F5B070718F075481A17346496C5D69F562C3C76BFEAE7BA641F153F7EBEC39A864B170A2158A4C4D3AA672B0E1C569CB3C6B58C492926579FC6D1CAC0C29F5A0C0000054B8CBAC8C4B8A977240009317ABBCDD9DFCEBF863516195BA4B0AC84472B447CB0BAB6A66C26000E579BC0CBB0ADA59D480F031F69A7B8BBC6AC6D1C00000000061620201718110B0E0816201C272425313C403A3C39454B4D4A47494B4C49524C2C88BBF2FFF7C79C98917D739EDCFEFFF3D4A678666673758EB4BED3C17D3D04000012589CB796522B1D24478BC9E1D8BC9E82646C7BA0B9D2C99F6D6970707C9CD4A678666673758E01FE905B070718007D4B120F325C95BCD6A24F28437DBAE0DCBA6021174289B5B8A9753E0D062863A3C2CBB2722400225E9DB7B1B38840181E539BC6D8D6CFCA975606000000488EC5CEC1C0AA7B280009357ABEDDD6D0CEB4822D060C59A1BBB58D4E2F4274A0B4B39F682B09155891C1C6B7BABEAB541400276CA5BAC5C8B2671800000000080E141512110B141211222C2729242E2C393342443B3D4950454D4440454C48432E74A6E4FFFAC1A29B94747CA0DCFFFFEDCCA1806F6C77748BB9D7C3B47F300000000B5595B68B462B221F4A8AC0D6D5BA956D6D737B91C6D8C79A7A776C747A96CCA1806F6C77748B01FE915B07071810743B0F1D39599DBED79F472B3B7BBDE5E3AF551617498BBBB6A6763507002568A7D0D1A95F190827609CAAAFB78E3A14215C9EC5CFD1D1BF984A0600000A4A8AAAC2C9B3AE6E29000E3A81BED4D1CACDB5792A071662ABC4B191543A4B799CB6ABA2661E001553A0C7CFB5B7B3A14908072369A4B5CAC5B16D2000000000081D1D1D1D12120907151E28241E1622373C4335343F424B4F4B4543434946433E357DB9F7FFF1B89D9C8775769EE1FCFFEECCA5816B5F767190BECEC6AE803A01000012499AAB8741202826528BD1DDC4BB93747178809AC1D1BF9F7B6C71767C8FCCA5816B5F76719001FE925B07071820823D15182D6291BDCF944C2B397DBDE0DEB6571F1A498DBFBD9E6C3711032E6BA5C7CBAA5B1D0D34669EAFAEB7854614225DA4C5D3D9D9CB96480A0000005497B6C0BFB8AB6F1B000C3D89BECBD0D5CAB37A2403186AB0C6B68B5636417AA9B2A798681E04165DA0C6CAB7B7B1944108042C76A9BBC4CBB27320000000000E15151618180F0E0A03152323232825363436384145443F49464E4946534345422E83C9FFFFFEC2A1A4958273A0DDFDFFEAC5A6826E6C797C95BCCBBDA67D2E08000019679EAE83382722235294D5E6CFB8907771797795BBCCC3A07B7E77767C91C5A6826E6C797C9501FE935B07071830783B14213A6999BDD5984A193675C5E6DEB25521204492C3C19A6B2D08102D6EAFCFCEA151140E2A6B9DBBB7B5864515245DA0C3D2D6D5BF9C46030000024595BDC2B7B6A96E24000D3787B8CCC6CDC9B86E200C2471B5C2A88A5D373F7AA8B1A89B5E180224679CBFC7BFB9C0A3450E0D2E6AA7B7CDC2AE640F00000000031E212025130C080E132026202C29232E3734343E3B4047444040444B4A4C3C413491C8FDFFF6C5A4988A7680A7E4FFFFF4CE9C816C717D7B9CBACED1AF7A3500000010609EAC8A472318255595C7D6C0AF9777607183B2C3D6B99C7F746469778DCE9C816C717D7B9C01FE945B070718407645181D32639EC2D28C44283E7CC6E9DEB554191A579ABAB999663D100B3377ABC5C9A3511A0F2B69A2BEB1B48535092463ABC9CBC7CDC09B460900000B4A8BB3C8B7BCA66A2205104186BDD5CECCC9B06920081D6EADBDA78458384779AEB7A69A6D1A001E639FC9C0BDBCB79A450E0A337CABB5BBBCAE662100000013161C1E1C150716100F17191921202A29313B3A33303D404F504144494A464B483A288DCCFFFFEFBA9997907A7CA6D5FFFFF2C89A807070798199B5CACCB26F3100000018649FAD7F4422231A479FD8D3C8B19B827B7D7F96CDD6CA9479646B707397C89A80707079819901FE955B0707185074310506306493C1CD893D253A70B5D9E3AA4E1819509EC2B5915C2E04052772AECDCAA35816102A719FB1ACB084390E2664ABBFC6CDC8BC9F42000000105196C4C6C3B3A4671C00163C89BED0CFC8C4B86B1F0F2271A5BCA686523952819FB1ABA15A1E042B6F9FCDD0C0B7B1934A0F02336BA7BDBCBEB562100000001119161C1B1B1B170E070B1D1E1D25222F31394336363F3A4547444B504148414038368ACFFEFFECBE9B95947A7CACE8FFFFEEC6AC7A6F7F788BA2BFCEC4A779380600001E5B98A67F3E171E216B9ED6D8C0AC8E776F7889A5CBD5C09575635D657192C6AC7A6F7F788BA201FE965B070718606C3E0F182D669ABBC37D3D20317AB8DAD4AD541F205194C5B38D61330A0F2869A6C8CB9A4D0B0D306E9AAAB7AF7831172965B0C6C8C5C5BF984000000013529AC0BFB9B6AC701D00134288C4D2D3CFC1A76923091F79B5C4A4804E3A4977A5AEB1A25712002367AAC2CFC3C0BC9F3D0A083D79A9C1C4BFAD6A16000000061815231D19180A0905071D2520241D20313640343D3E444B404A495149464A3F45349CC9FFFFFBC5A19A937973ACEEFFFFF1D1A083696B84829EC3C9C6B080380400001D6CA5A479451C1F24599FD5CEC5AF8F6D647F7C9CC4D6CAA67E6257626B8ED1A083696B84829E01FE975B0707187079380C09336490B8CB8541203576BDDDE2AD471D1E5292B7AF8D6126171A2A74B3CFC599470C072A72A8B1B9B17F2D172B62A4C7D0C9CBC197430000000C558DC2C5BAB1A2671E0512408AC7D3D5CCCB9B551B0A2477B3BAA68A4F354A73A8AAA6985219002B71B1C6CCC0C9BAA04B0B0B4585B7BBC3BEB26B1200000008191919211F0D0A00101218211A211E2032323E3A3C3E3F484B473E484C4D48433E3484BBFAFFE5AF8F998A7272A9DFFFFFE6C9A27E666D8284A0BBCBBEA4682A000000185DA1A1713F1F1A235BA4CBD4BFA38D7E7B8180A9BFD2C69B6F685E6A6E99C9A27E666D8284A001FE985B070718807C3605123B6B96B8BF894529377CB3D1DBB045181D4B94BCAA855220030A3476ABC7D0964817133074ABBDBAB382361C2F74BDC5C7CFC6B08641040000174F92B6B7B3B0A26D1D071D4789BED4D1CCD1A65F1F081F73B1C2AF85513F4C70AAAFAAA35615072C6B9CC0CDBCC8BC9D460E0E4C80ACB6BFC1A765150000000B272A2B20240A0708090B1219111C202E2C33363A4041444648474B4D444A403C393694D3FFFFF9C29C9A9A767EB0E3FFFFF2CDA787746E8292B2D1CEC7A2732F0000041E75A5A3723011201F60A5D4D4BB90927570728A96C3D6BDA0776B6A657897CDA787746E8292B201FE995B07071890733D0D072C608FB4C07C37183C81BAD7DA9A500F1556A6D1B67B4D22050F3777BACECF964F1A1B3F7BAAAAA8A76E30112769B1BFCBCECACB984201000014549EBEBEB5B0A5631400163F8ABAD2D4D3C5A25B14082A80B4B9A9725C434D74A4BAA8984D1406256CA6CFD1CCC2BC943405104E80ACB3C2CAAE5C0F0000000D2123201D191215090A06191E211F1B262F322E3C373C40404A4B48504D444343443584CAFFFFE3B79389787583B6F2FFFFE9CFA17D646F8483A7C3D3C8A1742A0000002568A7A47F381321215FA0D5D3BCA08E706A7C83B1CAD7C697786B5E6F7B8ECFA17D646F8483A701FE9A5B070718A0673B040D205386AEB979391D3877B0DACEA7451A225AA2BFAF7F4E1A0611387CABCBC7974816083179B2B0B7A46D32113575B4CAD9D2C5BB8A36000000164D9EC2BDB1ACA1641C00184996C1D3CCBBB6A352170E2B74B3B9A07D4C465B7C9EA9A3944A12002D6FBACCCEB7C2B88D36080D5791B4C0BFBE9F55090000001827251C231B0E0B0002051122211D131C2832393E4240463F494A4551504E4E47453A87D0FFFFE6AE858C7D737AB2E9F8FFE9C9A0836C71858CA7C2C2C4A16A1E000000246CABA374371B1F1D5CA2CCDEBBA47E687A8785A7C5D0C19A79746166788FC9A0836C71858CA701FE9B5B070718B06F3300032A5E84A6AA6E2E18327AB7D9D89D46111D57ACC3AF784E1E0A15427FB0CCC5893D07093575AFB9B0A6692A1E3176ADC8CBC8C0BD8A310000001D61A1BDB6B4B3AA6211001A509FCBD7C8C8C49C5512102D81C3B7A47458494F779FAEB490460D0E3479B2D2CCC1BDB58B350B174F90ABB7BDB8A7620D0000000C2A231C22120F0B0C0707151C1D281E293733323F47423B444044484B4849403F373191D4FFFFEFB49992886D86AFEDFFFFDEC19473656E8188AACECFABA16D200000012E77A3A26636161D1C6EB7D0D0B69E867B7C8B8FAFCAD3BA89766964617793C19473656E8188AA01FE9C5B070718C06727000023588FB4AD6C2C1E367FC2DCD599430C1861A5C0AB7D471603094086B6CFBF893B0A10367FAAB3BCA969341C306FB3CCCED1C8B9833100000019589BBABFB2B5AB611700115294C5D8D0C0BC8F470E032B83C3C9A373504B4A76A3AEA99E410D033A7DADBCCBC2BBC081380E0C5796BABEC0C4AC5B0B0000001C292D36261612070000081620191F1C2332333D3B373B3D454744504945494442443384CAF9FFDFB37B837E7C90C7E8FDFFECC398806A76888CAECCCDBEA167190000042E769EA56E2D19241966B0D7CFB69E776C7D8088A8C9DCBC906E685D5F7299C398806A76888CAE01FE9D5B070718D06F340200265E89B2AC6F2813387EBCD3CEA840142A5FA3C0AB784515040C3C85B8C5C5853C110C3D84B0BBC0AB6C2D213675ADCDCACBC5BC85340000001963A2BBB0ABBDA5621C00194D99CFD1CDC4B78B4712043C83B7BAA17A574955729AA9AF883D0C083980B0CCD0D1C8B6882C001C609CB8C0C5C2A2580E0000001A282F2F29120D090003071A2021181D222A35333230423946454841474C4C4A43432E8ECBFFFFE5AD837A846D84C1EAFDFCE2B793847880828EABC6D1AD9F7625000005246BA79E6A2A0C1B255CB3CFC5AD917E706B8797B2CFD5BD9985706C607C9BB793847880828EAB01FE9E5B070718E0742A000218598AB0AE5C281F3780BBE0D0A139112169B1BFB278380E000E3A85B8C9C7823A0F163E83C4C6C4A86823153471B6C7CDCABFBA792B000001225E97BCB3B2B59E5B170120508BC2DACFCABA894B0F0F3286C2B89C7559515375A5ADA284430B093A76BACFCDBFCCB77B2E0F2A679BAEBEBDC3A7530B000001252F2E2F2015150500000A101C1D19242B2A29262D343D3E3F43404346463E44423E3795D3FFFFEDA7838A877788C1F9FFFFE3B6927F737C8998A9C6D3B8995F1F0000003382AAA1642D11242162ACD2BEAA7C74706D808CB2C9D5BC927D6C67687D9DB6927F737C8998A901FE9F5B070718F06E270000115083AEAC5F23102A71B7CFC38F3816256BABBDA0662E070016438FBFCAB67F2C0209387EBDBCBAAA5F251E3F7BB2CDD3C9C4B67F2A0000001D63A6BDAAAEB9A3540D002A599DC8D4D3BCB3914911153C86BCBC90675053617A9BACAD904710093E86BED1DAC4BEBA7F2F07306E9CBAC3BBC0A04B00000000233533322619090700050C131D1E161527332E34373538444A4842444E473D3F3E3F2B97DAFFFFE3A485807D7B96C3F2FFFDE3BF927469718BACB5C9CCBEA05F1B0000002A6BA696672B1424196AAFD3C2AC8D746E737D89B4CBCEBE98836B5A6482A8BF927469718BACB501FEA05B07071800722D00001F5486A79F5422153A78B5CECB9438122A70B4CD9E6A4015050D3C8FB8BEB57B380C0B4187BFC3C0AA6426133D81B8CEC4C0BBB07E260000001D5E9AB6AEAEB39B5C11032B639EC0D7D6CABB853613133691B4C0976C564C57739AAAAC8B3C0C10428DB3CDD1C8C5A7812C0B2A70A8B9B4C4C1A1540D00000B2A3B3425262012070000131720201B1A2D2C332D32333F413D403C3C394442473E41309AE0FFFFDD9F73707C7189C1F4FFFDE2BD9B8A7D88939FAED5C8B597641E0000023582B29D621000192C77C0DEBEA7927A6C6F7A88B9D3DEC296806D5D667BA6BD9B8A7D88939FAE01FEA15B07071810722400001E648CA8A55F2318377EB3C8C8943A172879B8C4A273350D001B548CC0C7B176350D113B90BCC1BA9F55221A3677B0CBBFBCB7AE78220000002D64A0B5A8B0A98F521C0024699EC9D0CDCFAF7B3D0B083D90B8B4A37B68545A6F9EB5AE873709104887BBC3C8C6C0B979230E2B739CB6BFB5B8A65D080000082D3D3436251C110601020508171D201D1F292F2A2C2F3A3E3A454B48393E454C3F483C9FF1FFFFE0A0888E8C4E88C7FEFFFFE4C49C887A7E91A5C2CEC5B79A601F0000093E83ACA45C261327206AA6CDB89E8F7A6D728186AED2D7BB99816F5D60749AC49C887A7E91A5C201FEA25B0707182077340502245C8AAEA56129203B86BFD5CE8E3F152F73BCCBA969330A09225696B9C5BB6C2D111E468CB2BAC1A35923194089BFCAC1C2B1AB6D240000003069ABC0ABA9B196541D0A2B5E9AC3D3D4CBA97333090F478DC5B99570656059709BAEB17D2E10154A89B0CCCFD0BFB3781C032E77A7C3C6C2BB9B510100001139433B33251D0F040001000117191B18192A282B2B3B3839404341424D4741434247309BE0FFFFE299727C80808BC3F3FFF9DEB7977E75808E9EB6CBC3B48C5C180000093F84AB904F19091A2079BDD2BC9F85767475828EAFC3C6B2957D6D5763789DB7977E75808E9EB601FEA35B07071830792400001A518AA1944C18103E76B2C5C18A3C1A2F7BB5C8A4643518071D4C94BDC5AF6E2703103E85B7C4C0A45626244D89B2BBBDC1B2A266200000002F6EA2C1B6A5AB9D4F1508295A9BC0D4D0C8AD79390E1E478EBCB7996A6364576E9DBDAB792C0B104F86BECFDBD2C6BA70210E317CABBEB9C1AE9247000000083F5845351E1203000000080616191C202332362F2E33353647413D3D4239484C3E3D2D9EEAFFFFDD9879737C7090BDFBFFFDDDB5937E858C919AB2D0C8B3875A1800000E3E84AE964F231219226EB4D1C29A81786572798BB7CCD8C695727464617CA7B5937E858C919AB201FEA45B070718406D1C0000215D8DA399461A1C307BB2C2BF7E2A0F3379BBC8A66A2A0800154D99C0D0AC652D000F3B8EC3C5BF9D52131C487FB8BDC9BDB5A868200000013071A8BEB0AFBC9B4C0C002E6FA1CBD7D6CBB976321020498EC0C7926C5D5F5B789BB1A2732606164F86BDCAC8BDC3AF6620033B7FB6BFBCBFBB9A4100000013505E483C2A1A130100000A0C15191C181521272C383A363A433E4340403E44423F45319EDEFFFFCE99796573778BC8F9FFFADBBC948383929CA3BCCBCAAB8C57150001104A89A39B47121F271D6CB4CDB18B76736A798891C2CFDBC2A183735B55789FBC948383929CA3BC01FEA55B07071850872C00011E518CAA99491F1A387DB4C8C38536132E81C8D1B2692801001E59A3C6D7B86A2B091A4591BECCC99B45181C4988B0BBC4BEADAE66240000033A79AFC0B3A8A583460B002B72A3CBD3CABDA47531111C529BC2B0986F66695A6D9FAEAE762603165593C8D5D6CDC8B06C22103D7FA6BBBBBBB6A24A000000184E644E402A220C04000000111015141C1D28262C2B3136333C3B3B43453B3C3C393F2FA8E6FFFFEBA16B6C828196CBF5FFFEE0B3877A7C8B9CAEBFC8C19D8B551000001D4D87B1954D1D1C21227AB6CEB59B84766E69788DB2D0DCB896786247598AB0B3877A7C8B9CAEBF01FEA65B0707186071280000155B8DA8994C1E153374B4C8BB8029123588CACCB164280700276498BCC8AA5F1D03043D91C6C4C19C511A225795AFBDC2B6A9A6691E00000B337DABBCA7ABB8953A09102C6899C7D4CEC5A06C310F1F4C9AB9B5967677715C7295A6A56E250615539BBED1D6C7BCA5612710418CAAC7CDB8BA8F440100002A5E64503A2D1C13000000001317140F1216261E293132363C38414040403A3F403F402FA8E9FFFFD9977B74776A9DE3F8FFFBD7A68074748E90A1BCCCCBA888481A000018478CA294531E05212A72B9CDAC887C796E6C8F9AA5CDD1B4927F6D60677EA2A68074748E90A1BC01FEA75B070718707B220000245684AEA7521B183D75B2C5C0812F17378AC9CEA15F250400205E9FC3C99A5820010F5590C3CDCA903F13235690BCC2B9B4B2A35706000004397EA9BAB5B9B68B400C0D3976ABD1D4E0CAA5692207255890B3B38F6D6B66586D90B1A6682309205E9AC9CECCC2CAA55A1C10428FB4BBBCBAB69E470000002C69745340311E0B000000020F1112141A242223202D31393A3D4541473C3C46473D36309DE3FFFECF97696D777496D6F7FFFFDBB7868179889CA4BAC6B5A57F4613000218528BAA92531D1A232F7DBBCAB48879736974849BB8BFD2BF967B71605F7DA9B7868179889CA4BA01FEA85B070718807A290000225A8DB39544101E4080B2CAC57B2719338ECFC7A7631F0102255EB2C5CEA5561B00094B8CB8C6CE984419265F8DB8C6BDB8A6915A120000103A8DB7BAABABB08A39090B34739DCBD4D7C19E642202205892C1B68D716C685B699CBBB06D22061A57A3CED4CBD4C9A355100D4089B6BAB7B8B19B4A000000246E74553B322C160000000004121715141D2028282B2A343A3D433F3A3C3D3E3C3C3E2C9FEFFDF9CF9669736573A0D6FCFFECCCB38579788797ABBCCCC1A1744A130000195694B292511E0E2A347FB3CFAD847C7166718594B3CBCDB8827264555E7FA9B38579788797ABBC01FEA95B070718907620000027508EA88A370A1C3A78B5C7B77D310E3A94C2CEA7541400002268AEC8C2995A200514498EC4CCC99B47242E5C95B8C6C3B8AF894A0F00000E4786B0B5B3A3A6893D0C073A72A4C7D6D1BF97591F062A60A6C6B28F747476646D93B09C6115021F619ECCD7CEC6C3A95914134A8CB5BEB7B1AE98400000003570806545382103000000000409130D12151E2B31272A2F303A394043423A423F3C3E2DACE3F8EBC3815962617091D3F6F8E5CDAC876D647C94ACBDCAC0977E4E1000051B5792AE8B44160728327BBECCA880777768728298B9CCD1BB8A7572606981BAAC876D647C94ACBD01FEAA5B070718A0742400001A608DA5944B1522418AC5CFBC722E133C91C8C0A75E150100255FAFC7C398531001104FA3D0D0C3913B12265B99BFC5C0B5AA92520500000E4C84AABEB5ADB4823103123975A6D4DBD9C69D5D21072E61A2BAC09C6D6B70526695BDA05418061C5FA7C4CDD4D0C99751111A4D94B7C0BCB6AE8B3C0000003E7E865647382A0B0000000003110C1314191E2228262D3233383F39343339403E393A2EA4D7F0E4B27C594A597391CBEEFFF8C5937366718094B1C2C9B899793C0800011B5A92AC814310001F3782BBCA9C776C70716F8492B8CDD4B98B776D5A6D92B2937366718094B1C201FEAB5B070718B071200000285987B5953E13123C82B7C9B77222113E94C3D4A45B1A00002770B2BEBC9F4D1300154690C2C5C39340152A5D9EC1CCBBB4AD894B020000104690A7B0B1B3BF8B36100F4176A0C5CDD6C9A55C1C092C5E9FC2B18B817C7C556C91A18C5816072964A8C7C6D2D0C3984E1E195093B1BBC4C1B98F420000033A858B5A3F40240900000000040C08131313212827282C373F413B403F424341362E34259BCDEED2A165484D50638DC0E6E9DDC5A47468758A95A6BAC0AF99673C02000F285084A5863F19001F477FB4C5A17B686C6B7B889FC0CCCBAE89735F5D678BB9A47468758A95A6BA01FEAC5B070718C079210000245993B28E4013193B85B6C2A96B27184091CDD7AA64290400327DBBC6BB86421000144D9BCCD0BC863D1A306D9DBBB8B6ACA48B420800000F4583B0B4A9B2AC773C040B4A81ABC7C6C4BF9656220F366C9CB9B19467767A606794AD9855190E2B65A5C2DCDCC8C49E4C0E175199B2BEBAC2B68F3B020000417D825B503D280300000000000B12150C111D1A282F2F30353C3E3B4139464139313A31A0CFDCBFA56C433C535F96CAE9EBEAC5927770717D8CA2B5BDB58D603203000D2F5996A37B45150B2A578CBCB78F6F65716C707795C1CDC8AD8F7C6E546481B0927770717D8CA2B501FEAD5B070718D072280003265F909E8934101B4388C2C4B0622012358EC5CBA85B1C00032679B5CAC38D4218001F4F97BCCFC5883C1E2863A2BEBDB8AA968443070000205992B1ADABB1B5833403134B8AADCAD2D1C7965D1F0E3A70ABC5B38A78797C576994A6834D140B1F6AA7CBDAD8D7BB954E0A165AA3B5BBBEC3B894360000044C7B88644D3F301500000000000E1111080E1E28251B26373534384241423B3B35353A30A0C6D5CF9760333446769DD5F6F2D9B38B716373818CAABEBBAD8F5E3300000524548DA88149160224507CBAB9977371786D6F8495C5F7D5B080665E566383B68B716373818CAABE01FEAE5B070718E06E1E0000206487A28D3A11143682AABFA65E14043D97BECCB1631B00073679B2CAC48F450D061156A5CAC7C39032112E65A3C0B5B5AFA47F390D0000194F95B4AFB4ABBF83350515447BA9C9CBD4CB9A57200D326F9CB1A58B787C7F626796AC8E4907022974ABC7D2D8CEC6994D191553A0BABBB9B9AD892C0000044592957150442F0A000000000B0E0E0D1310191B2127282228353E35343F3D414133332598CFDBCF9A615047585F8BC2E4EFE3C59C6D656D7B92A8B1C1C2826130000009276299A2874A19002A4C7FB9C39D6B61717270849CCCD2CFA7847363566482B09C6D656D7B92A8B101FEAF5B070718F071260000295D85A28F3E10163C83B7B9A25E1E0A4594D0C6A858130007397CB7C5B693471300134C99C8CCC1883A1A3374A2C0BDBCB2957942000000205196B6B1B5B6B979310D0A3C7DAECACAD0C79F5A281845769EAEAA87767C7A616998AF8E4C060C2E70A7CDD1CCD1C595400A145599B3BBC5C7B685360000064992967257462B0700000000000D1210120914241E212F363636413D3D41403A3332382896CFD6C59965423949668ECDE8EBE1B99A6C5E6F759BB6BABCAD8F6C340000072C5E95A57D3C0E053C5189B4B9926B74716C6E8097C4D3C4AD806E61546885AE9A6C5E6F759BB6BA01FEB05B070718007E3500022B69A5B48C3E0E164688B5C2A55C1C124390C3CBAB66180005337DB9CDB9863E0D001D51A6CBCFBC813818366FA7CBC2BEB39B873B0200001E5991AAADADAFB470320210437EAAC9D3D3C5995217073F729FB8B9908385794E578DA180410A0E3268B7C9D2DBD5C58D410D1D5CA2C4B9B7B6B58F330000074A95A174594E2D1300000000000810100C1112222B241E2C312E36393B433E443E3A36259CCED4B98D533135606F93D4DDEEEBB8896665678499A7BFC4AD8E5B2902000C2A5A91A27E401706275184BBB98C685F716E758BA0BFD1CDB17C746260658ABC896665678499A7BF01FEB15B070718107B2A00022E7199A484431019458BBDB5A2591E0F4E9DCFD3AE57170000327BBFCFCB8B350B000D4F96C7CBC4862F12367BA9C7C3B1ADB3803A01000022589AAEB4AFB4B6773312125082B8C5CBCECF9753211142789DB0B18D788575546798A7823C140E2C7AAECBD5D6D4B98F40111356A6BDB6B4B8B1822F0000055296956F654E3207000000000006080E01060C1E202B2B302C283B3A3841403A3D34373099C3C4A879442929446085BEDCE3D5B8876C5B5F788F9CBEB8A37A4F2400000029589AA7743D1207316297C2BA896B6E746970809BBECCC7A47E7464606B88B2876C5B5F788F9CBE01FEB25B070718206E1B0000265888A378340F053E83AFC0A151160C4096CECEA75E1C00012678B8C7C07E370200104D9CC9CEBF84360F3478B4C1C4B7ABA77F2F07000028639EB1B0BFB6B2621D0C13588AAFC2C6CBCAA54C150D3F7293B0AD8A75857F666F9FA87B3A0708367EB8CFD3D5CEB183350F235BA0BCC1C1C0B1812B00001259A1A37B685641180000000000020811080F18202720262633313239343337353B37372799B2B6AD7F4927254C5D9AC7E1E4D4B08E6C5A5F798EA9BFBAA3804C24000011376E9D9C793B15132C5E8AB6C08C69687A7971868DBED1CAA57B6363526588B68E6C5A5F798EA9BF01FEB35B070718307026000023618BA37C380C173D7EAAB39C5317104499D7CFA95B180006347EAEC8B283340800114A9EC9D6C6842A193172A2C0BEC1B79C7832000000296E9EB5B3B8BEC174330B1C5086A8C3BCC7CB97551B184578A3B4A487758581636490957C3503053373AED1C5D2C9C586360F1E5FA6C6C0C0AEB380290000105D9D99796957371700000000000B0A0E0B0A181D1F25212933323835333B3A3E39353B2E9CC1C6AE804E28303A6490C6DEDDDAAD866759667497B3BDBDA58156230000072C559AA57D361C0F285F8ABBBC8B656E7275757FA1C5D8C8A27F6D655E688CB5866759667497B3BD01FEB45B070718406E21000024568AA27C2B06123F7CADAB90421719409FD3D2AD5B1200103989B8C7BC82300200174D9ED1D0BB772A1A3B70B2CFBEB3B3A174320000002364A1B2BAC2B3B2712B0B124E85B3D4CFCCCEA254110C39789BB5A79279897D5764869C7E3400093783BDCED0D0C7B78B3C0B1A639FBDC3C4B2B0832C000012569EA4735B592F090000000003070D0B080B1E1F191B2A3038323834393A39494739312199B6B1A47A48211C376593CDE5FBDAAA815B51637791A5B5B2A07C451200000836659BA67637180D2B6B9BB3AB7D57666E656A7FA2D0CBBCA97B5E6466778BB7815B51637791A5B501FEB55B070718506E2400002B688BA57E360013458EB5B68D55120E479BCED0AC581B0001387FB5C3BA7B2A0800104D9BD4D7C67B291F3981AEC2B1A4ACA77727000002275F9CAAB0C0BAC1722108184D93BBCBC4CAD19F571B13497B9CA5A38C8592825D688C9D69260C124186BCC3D1DDCBC27F330B226FA9BFB2B1C4B783270000105DA3A3795C553C1700000000000A0904020C0D1217162328302E343B3941403D3A413A2B9DB0B7996A3C28314A5C91BBE6DFD1AF8C6256637897B5B7B49B7D44210000062E61959A783D0E101A6594BAB4856F7285847385A4C2CBBAA07B635F5A7090B58C6256637897B5B701FEB65B0707186078250000256890A1802D070E4A87B3B88E4B0F0F489CCCCAB05D0D000B3E87BCCABA7A3700001E56A4CED1C881331D437FADC6B5B1A79370310000012361A6B0B5B8B9B87127011B538AAFC2C8C6C78F481C19457C9AAFA78A7C988267687F8F7931030F3C7EB5D9D5C7C7BD893C142163B1C3CDC0B7AE7B2900000D60A6A8786D5D34120000000000091007070511221B141C27303C3A352F3032403B2D332B94B4B796723A161C436196CAE6E5D0A17C63585F7C97ADC1C5996D4919000011326DA8AA793A2210326391BFAF79576A76766F84A7C9CDC19F7666625B6C8FBA7C63585F7C97ADC101FEB75B07071870801F00002A6699A8822F05183D87AEB791470E0C4697CAD0AA5D1200093D8AC4D0BB6E2900001A57A2C8C9C075371F4086B0C4BBB0AC9B6E290000002566A3B3BBBBBAB26C2906206092B4CDC7C9BD9A53180A4280A0B7B085828B7E65617C93752E000B388BBADBD8DBCCBF742605235F9ABDCAC6B5B47C2500000963B0B080755D380D0000000000000B0A06101A1C281E1C203137363A353637373C4246279BB8B59E78472031495A9BC2E8E6CFAD876A5D607798ABC1C1A471491B000009367BA0AA6C301A1538758FBEA87A63666C707482BBC6CCBEA17465625B6D92BF876A5D607798ABC101FEB85B0707188077280008356B9EB1792800133C88AFAC8144111248A4D7D2AE5006000D3481BBC0BA6F2F0900205AB0CECEC3842910397DAFC8BDB3AC93671D0000001F62A2B5BABCBAB0742A09185D8DADC9C9CAC3A2521D1946809AADB1917E897C546391966A25000B3E7EBED7D8D0CEBF832B0D2065A4C4C7C4BBA5791C00001860ACA67C6F65421D000000000210090A0009140D1E1D2024293534313C3A383C3834382B8BA8AD8C5F3618173A547FB5CDD5C4A77E5B4B58708EACBDB09B6B3A180000173672A4A27033180D2F749CB9B8835A627E706F85A5CCCBC29477655C62738FBB7E5B4B58708EACBD01FEB95B070718908028000031669DA37D35131F4489B4AD893F0E0B4197C8D4AF5B1E010B3F8CB8C8AC762D05001753A9CCC8C07A311C3A7BB3D4C1AFAD9D68240000002460A7B3B5B4AFA7672307205E88B7C8C1C8C49355191D4A7CA0B4A596798A88645C8BA0763000124483B5D1D7DDCCB87F300F276DA7B9B6BBC3AD792B00001667A4A78B745D3C180000000000080F0D070E1112151A2D21222A353D3C2E34383E3B2E27859CA087522B1013385E8EB3D1DCC296775A54536D93ACBDB69F6F5C1821000A336C9198653118122A688EB2AD76555E716B6F8CB1D3CDBE9D6F665B607794BE775A54536D93ACBD01FEBA5B070718A0732000002D75A0A4812A0D12427CA0A5853E060D489DCDD3B85B14000D418CC1C9B3722100001A58A5CBCBBF8A35214588B3C1BFA7A79965240000002663A9B6C2C1BBB26718061A5796B4BEC5CDBF9E571C1548849AB7AA8A8293825C638B966723000B4281B9CCD2CBCBB47A2C0A2170A7C5C7C0B5B3822700001A64A6AF85776240140000000000080B0D0009121B1C1C1D1B2736382D35353B3A3D32352C97A9A290623B1F1F3E5A8AC0D9E4D199794F58587494ACB1B490713B100000114276A49D7040241B306C9AB8AE825D6870617089A6CCCEBD916A616159739BC9794F58587494ACB101FEBB5B070718B06F1E00001C65869D6E2001143D8AA4A57A3A080E4099D1D5B0551200063E8FBFCBB3702501001664A7C8D1B67A321D408CB4C5B6AFB39858160000042D6CA1ADACB8BCB36C21001B6198B5C9C7C7B994450D10528E9FACA38883968463658D94732B060F458AC4CECDC6BEBC78280D2970A3B9C7C6C1B4781C00001C6BABB58D7864451200000000000302050200131518202A2E2F323A353232343A3335382A85A49B7C591E161B365D99C1DED9CCA1755B49597490AFBAB3966B3A120000103C6FA09C6C3B23142C7494B3AC75577175736B81A8C1D1CB9C7A5A5D5B739AC4755B49597490AFBA01FEBC5B070718C07B22000025699A9C73230A1A5492B0AA7F38110F4B9DCFD6AF5D1F00093E90C6CBB46F2600011F60A2C4C9B87C2C213F8AAEC6BFAEA89358150000013277A3AEB9B7BCB5631E071A6090B8C4D2C5C4954A1A164C899BAF9C85859B84665D839A5E2105174B83B6C8D9D0C5B17B200B316AA0BDC2B9B1B0761D00001D73AFB9937565420C000000000001000604060B1E2422262A2838383938343C3D35322C238EA19E7E5D29131E385D90BAD5DCBC987451475F7597A6B7AA916B3F190000153B7E96986B2C1F122D7897BEA47E586476746683A5C9CCB7947462625C7597C97451475F7597A6B701FEBD5B070718D0751F00002F7192977132050F3E7BA4A6803D09134AA3D6D7A25116000B448FBEC3B6722304021458A7CDD4BF6A2F1F4E8DBBC6BEAEAB94601700000B2C6594A2AFBCBDB26A1A041E639BB5C6CACDC8A956160F4E8899B1AF90849283616C93925A2104163B85BAD0DCDFCFBB7E2B0C30689EBCC6C2BCAE751800002870B0C2937B63450E0000000000070E080406130A181911282A31312C332F393939363328909A9487591D071B3D558AB8E1E0C5A07D584E566F92A7BDB894623B0400001D4378AA9B59292313387A97A9A667526D8070778AB3CFD3C397765F69667197BD7D584E566F92A7BD01FEBE5B070718E06D1000001B5C859E712100093E7EA09E73330A0D449BCDD2B05B1300093991C0BFAF651F00001555A4CACDC1782C264B8EBFC2AEA5B29B64200000062B6DA0A0B3B9BFB36218031C6791B2C9CCCBCAA24F1C164F7F97A4A58C808C7C636C90925E2400145291C9CFDEDACDBC7620042D79B3CDC6B0ADA06A1500001A71AFBCA180743B10000000000003060200090D10131721242F2F383C3B363A35423C3C268BA093774A200E0D346595B7D0D3BEA07A5546556F90AABBBA896235130000154E7C9F9A613623233A5C96C3A872535B7466697CA8C6CFBD9770656469839DC07A5546556F90AABB01FEBF5B070718F07B21000024628E9F7322030D4686A8A47B340C144BA3C8CBA64B0D000B3E90C6C6A76D2200022261A5D4CFBF7A2C1C5490B8CCBCABA79457190000063769A6ACB7B9B7AF5F1C062A639ABBCDC8C3BA934D0E1652809FB0AD87858E8A6363908A591F001C4E8ABFD4D4D1C8AF6D260D2B6BA6BCC9BDB6AC751E00002179B9BE918070410A000000000003070000031712141418242A312F35393939413A35332B8C9F96714D260F15385F96C8DCDBC3956E5444596A91ADB9AB875E310900001B42809E996A311F02308697B9A46F586A7B6E6F96B5CCD0B89C72585960799BC86E5444596A91ADB901FEC05B070718006B15000025679C946818090F4B85A3A17531090F4799D7D7B65B1500094490BEC6A8631400001D65ADCDD2C27C2E214D8AB8CFB7A6B189530F0000043C6F96ACB6BCBAA760230620649DB7CFC3C7CD964A12104E8E9FA8A79886917E696F8C85580F001C5293C4DBD4CFCFB0651D0E3280B4C6C4BCBEB46A1700002F8BB7AD8D836D3D1100000000000806020C0B001115161E2D2D2D312D353E42453A34322695978C704615020E3F6694C2D9D4C59C6E57525A7096A4B3B0946630000000144F7AAF9B7D281919388097B9A26F5663786B768EA9CABEB79A69535960759DC96E57525A7096A4B301FEC15B070718107D2B000027679D9E7819000D4686AEA5712C00014792C3D0AE5417000D398EC5C7AA5F1802061D66A5C9CCC47A291C4890BCBEB2A9AA9B631E0000002A6C9FA9BACBC2A9611D062065A0C4CBC5C0BF9D4C1A124F7C9CA8AE918896876A6C8A875A1C020C499DC1D1D1D2C7B4661D113B76B5BEC5B4BAAB701800002B7BB6BA927E683D0F000000000000000A0209151A1A192124212C2E2E32363C3E37353126899C83764E1A041241699CBED1D8BCA2785B4358799DA7B0AC8F60340500001B387BAFA2652C181E367EA1B9A2664A64716B7A90B2D1D0BB946C6452657C99C2785B4358799DA7B001FEC25B0707182072200000205C88A06A24001C498BA3A16328050A4594CCCDA95111000E439AC7C9A56C1C00001B60B2CECAB676301E5196C1CBB9A69F8E520F0000073278A4A2B5B9C299581F132E669DBDB6BDCDC6A547161E668998A6A28B83957A646582895615011B4E9CC9DDD7CBC3AF5E1F0D327BB0C3C2C3B2AA6F0C00001E83AEBF9B856A3F0E0000000000010506030C141613151D23272D3332383B3C3D393030298690876E4212070A38688BBFD3CEBE906E4F4B527491A6B3B38377270100001F48809E975E2D22163784A7B9A36F536F74706C94B7D0C9B4856B5E576881A2C96E4F4B527491A6B301FEC35B0707183074220000226493926A15000D4687A5AB6B2100093FA1CACDAB5915000B4092CAC8B0631200002862A6C3CDBD7B3122508EB7CABBACAD91550E0000013175A0A2B4C3C0B05C1D07286E9EC0C1C1C4C79C430A1B5D8F95A29E8B8C8B7E6B768D884E1700104796C7DAD4D8CBA95B2316387FA7C7C2BAB9B9701100002881BEB9958C764C0C0000000000000002030512161A1D2529253435343B2F34323F3633208B8F8A5D38101013376696C5CED2B192725747576E97ADAFA68353260400002551819F975B2E19123A86A4BFAA75596D75707194B8CDCFB693645F60677CA5C5725747576E97ADAF01FEC45B07071840762300002B709B9E6813001145889F9B642A0A13499DCCCDB45816000D4591C9C7AA61160005206DADC5CAB26B211E5596BEC8BEABAB98571000000B38729FA8AFBFC1A7571B0018609FBFBCC2CDC49E4C19175996A1AEA98F84968A5F7391894613001F559BC4DFD1DBC79F551E10397EB1C4C8C2B9AE6C1700002C80B9BF9887663B0200000000000C0504000410181C172024292C2C363731353C3A2F35287D8377613211000E376499B5C0C6B28F7050384D6D8CABB8A87C53250000001E4982A7A162291F163588AEBAA05F4C6A78687797BBCCCAB78A6056626A85AFCF7050384D6D8CABB801FEC55B07071850681E000023669096541F02183B87AA98520F000D50A3CFD4A95D18011D4D93B6C5AC671F00001963ADC7CFBD742B285692BABEAEA8AA96591300000E3F6D96A8B6C3C699571B05296AA0B8C0CACBC19B4D19185F8F98A6A8938F947E62698383490D0019599FC3DBD2D6C89F5A14103D7EB2C3C7BFC4AB610D00003087C0C2978A69450C000000000000000000040F181F1D1F242A2F3B3234353138343B30208C998F5F331000153F6196BED6D9B2A1685642496796B1B2B1834B20000000214F8EAB9D6B291616448BA7BDA05649667D757A92B3C6C5B28860535B718FAED2685642496796B1B201FEC65B070718606C1C0000266A99935F1F000F508CA193511C061953A1D0DBB3610D0012418FC0C7AA541B0004256EB6CFCEA96E2722539DBFC3B8A6AF8D4B08000009376B939DB5C6BA9A4F1B0E2B6EA4B6BEC5CAC0A34B1B23648D98A7AA8E8E888369758A703802001D5F9FC1D3D8D4C1AA581C093B83BBC6C4BFBEAD641200002688BDC39D89653F09000000000000010B070807121A171F1C2D35332D312F3B3F37333329857F6C4F2904000E356194B4D1CBBC9A6E4D444A7394A8B4A8814A1C000000204781A5A163321C1942939DB09A654D6E7B727690B9D3CBB4965C4B5B677BACD16E4D444A7394A8B401FEC75B070718706D1000001D689398541B000C418BA4945D1B000A47A1CFD0A9621D01154997C1CDA1561400002173B1C8CEC0742E255BA0BCC8AFA8AD8F50070000033C769BA8BAC4BE9D4D1B042C6CA0BFC6BFCDBD9D4413225F8998A1A78C8A9B886E70937B3303001C5197C2D5D6D1CD985B120D4084BAC3C2C4AEA35E0900003690C9BE938D6B3A0E000000000310060200030C1719152027242E3A303232373738363E2A7C7E725930070016406699B9C2CCB4856944454E7190A9BAA9854B22050000264883A893581A18143A91AEB89B6C5374846C7E94ADCFCFBC956B595A6B84AAD36944454E7190A9BA01FEC85B07071880802700002E6E928F5D1D08194F8DAC9459240013469BD2D5B2581C01114299C3C3AB5B0D00002A6FB8D4CFB3612C25599BBCC0ABA4B08F4F0D00000B477E98A1AEC5BE9D4919082978ACBEB8BEC4C59C4A1023668994A2A98F8C97896A768C74360700215B9DC4D4DAD4CB984A1412468DB4C9C4C0BBA05A0800003E86B5C598826D431100000000000100030408060D0D15262C272E3334332E333539303A2883926D421900010D396C96B7CFC9B4966A4E41526F8BA9BCAD7A421C00000022598DAC93581C17174499ACBB9E5B49707668799CBCCFC8B68F654A536D86A7D56A4E41526F8BA9BC01FEC95B07071890712A0000287290975E1400114E83A19D5317001151A0CDD7B75E1700143D92C6C5AB5C1900032063B0D0D0BD732E2B5FA8C9D6ABA3A694590800000F447499A9BFC2B8904815152E78A1B1ABB7C0BB9749111B608D8CA6A0878BA389707A907A380D001F55A3C9D1CFCCBF994D0B164C8DB2C1C9B7BEAE5C1600003192B9C39F826942090000000000050704080F1226160F202B1F1E2D302E3B2F3D363332277E7E69440F000011446A97BACFCDBF9161433D51649DB0B1A77943170000002A4F8BA991592612153D8EA6B1965A5B8187747893C1CFC9B5865B4B5E7294B3C861433D51649DB0B101FECA5B070718A074240000236FA097550C00185289A38446180612469EBEDAB0511500205A9BD1D19F51140000216EAAC0C6B369232E60A5C2D2B09DAB8D430000000D42719599AFB1B8945119133876B4C3B5BEC4B59C54131E658895A8AF9F8FA28A7975856F3800002167A1CDD5D3CFC1923E0E0D4193B8CAC9C7B5AA58020000408FB9C3988271450D000000000008010A020911101A1822292B272F2E3331352F343636287A725D3A1000000E3A6E9BC1D3C9B58D5E4031406C9AAFB69F70410A0000002C528A9A91561F15164297AEBEA05F4A757E7C7DA0BECACBB08B6555615F89A1D45E4031406C9AAFB601FECB5B070718B0761C00002F7A958A570A001B548C99884F1102114AA0CBDBB65E1401124C9AC1BB9D570200002471B2CDCBB97025276CA7C8CCB0A8AE914F010000154477969AC1BAB38E3A14082F75ACC1B8BBC0B4934B1424648D959EA48B8E9A8873759075310700295AA2D7D6D9D3C4914312134D9ABED3D1C6B9A5510000004792C5C09A7D69430000000000000A030600050C0A181318212832332F2E3338382F333229817862460F00001C4F71A3B6C5C3A58A65453B56779FA9B7AE7A3A0A000001214F84A0925E2413104BA1B3BA975D487782737697BECDCAAD82614E577691A6C865453B56779FA9B701FECC5B070718C0721B0000316F8F8E5B10071151809F8B460A001149A0CCD2A95C13041C5690B6BC9F53090004286DB3C6CAB864202364ADC7CCB3A5B698490000001A4A7890A3B2AFBA924A170D3A82B5C5BCBDC3BC8B410E1E5F94989EA18B84948E7A84906A2A04001F65A8CCD9D2D9C58634111C5194BED0C5B6BCA3450000004DA8C7C19B8A6F410600000000000D0A0A000408131214161B20373536313E363C382C3020766F4E2A000000114071A2BFC6C5A98A643545497793A1A29674430C00000023508BA4985217161B4B9AB6BE995749787C7A7C99C8CCBEA8815757626F93B8C9643545497793A1A201FECD5B070718D0722900083378A09B551409255095A2824F0C00104999CEE0BE6814091A539DC9CAA6511100042B7DB6CED1A85A222B6AB9D1CDB8A6A4924E0600000C4F799699AFC3C58C3C0D033886B3BAB1BABBC0904D142B679A98A6AB938D99917B8A85652500002860A8C4D1D3CEB8863506155197C3CAC3C5C5A2530400004894B9C49E83753F05000000000004050B0300090D191919232C322E323437323736263627897855390C0000204E77ADC4C3CBB08F65443241709EB4B8A275280100000031538EAC9D5F1B0B134BA3B1B188524771806D7C99C1DCC7A97B5A49607494B6CE65443241709EB4B801FECE5B070718E07E2600023C809D904A150021548EA88F441108154C95C4D6A35916081E54A5CCCBA64A1303002871B4C8D3BD5C202565B2C8C5A9A8AA904808000020517E8C9DBFCEBF863A0F0F3987AABBACB4BEC99C3A1526699596A49B958F9887818C92621E00002B68AFD4D6D8D1B5802B0A1A5890BEC2C2C5B4A1540A00004B8FC8C8A38866350000000000060C020406000B1215101B25262A2F3932323437332D261D7C6F4D1F000000184C7996BED0CAAC8263342F4B6D93B2AA9E753204000002336096A69A5C1F12174A9BB3B18B4A5C77796B84A9CDD5C4A8875F56607590B5CA63342F4B6D93B2AA01FECF5B070718F0711F000028749988480C00194F91AC883D0900134994C6D1B35B170B215DAACAC4964A0A00003782C1CAC7B15C2A2B6FACCBC7A99CA5904C0200001657788795B6BFB97D3704093A8DBBBCBBC0BFB8964017206D939BA8B2998B9C91858A8F5C1600002C71A7CCCCD1CFBF7F2B07185CA7BCB9C0B7BE9D4D0100064E96BEBA9782724C13000000000208000700080E0E141B1C2928313134323330383B3832148275512D000000155790AEBCCAC2A7876147404D749AB8B9A27030000000003863999592531F0B09469FBBB993545278847F86A5BECDC2A2845F5560728ABAD16147404D749AB8B901FED05B070718007127000034748E804C0E051E4B89A8783400000C4A9DCCD6AC63150D275FA0C7BC94420D00052E78BECEC7A75F24306CB6C6BDA6AFBA90440400001A4E748A92ADC7BE873B050B398BB7C2B2B4B6BD92421B226E968C969D8D90A29991919A591500002F6DB1D1D1D6CDB27122052463A0C6CDC6C4C19D4801000D4C95B8C1A285703E0600000000000C00000003121019192D212C2E2C342F2F2E32343937217560351600000020336E9EB9C5BFAA8557413D3A6E9AA6AD9D6F2E000000002B6B9FAA914F190A1755A2BCB3884A517D827482A3B5C6B9A2845E525F7492B6D557413D3A6E9AA6AD01FED15B070718107A3000013881AD994D110A2D599BAA8542060010509AD2D9B261150A2866ACC4CF9E4B0D00093A82BACFC7A655212D7BB8C2C6ACA2B29241010000225079869EB0C5B17C3005154B86B8B6A4B8B5B48C3315277B9C969E9E8A999DA18F93894C1500012F73B9CCD3CFD5AE6C1E0C306D9BBFC0C8BBB796400000074EA1C1D0A483733A0400000000060A000007040E191919171F26232930393B323B3137362472633913000002225278A1BBBFB799705F3532426E98BFBDA8672900000000305E92A38E561C14294AABB0AD834C487A896B7BA5C9CFB7A082534A61839CBBCD5F3532426E98BFBD01FED25B07071820812B0009468FAA8F410F0E2D5D9EA88A3C15081E56AAD5DEB35F170C255CA2C6BE8C4306000B377AB7C9D0A75829347DCAD5C8ACA6AE933D0000002B607F8A99B6C4AA7A2903022F7DB8C5ABAFC8BB92361D31709896989C9494A098899C945B1400003678BCDCDEC8D1A8641B0D346A9EBFC1C6C1B482360000075AA0C5BCA4846635050000000005100D00050010100C0E141D242F3738332F2E3033302920786F3917000009266082A9BDC5BDA57D59443D476E99A8AE9A601E000000073265998D9161240B1C52A9BBB68B4F4C837E788BA6B9CDC1A7855C4363829AB6D359443D476E99A8AE01FED35B070718307E2F00133980A4904A16042C6796B4873807001A61A4D3D7AF5D27122662A5C1C29A4208000E408EC5CFCAA94C243078C6D8CAABA5B0943F000000245D6C7F97B1C5B2751F18114A93C0C0ABADC1BB8C3D223482979997A5898CA197959C8C4B0400003D74B5D1D9DAC8A1590F0F3B72A1C0C6C5BBB28E3000001361AAC0C2A3886A390100000000080F060B020108090E18161B1F272E2B2D3230363B2E2F2C816B400B00000825648AABBCBFAC9B72533E354D749CBAB5955C1E0000000028689AAA8F5921081960B8C3BC864A507A7C7183A8CBD0B8A1875B5A608096B5D7533E354D749CBAB501FED45B07071840752D00063E87A49143110723619BAA7F340000225EABCFCEA25C110B2D65A9C6C18D350A000D478EC3CBC9B05621377FBFD4CCA49FB2933E0000001D5D767B96B1C5B1762608194A95C3C2A9BAC1C0963814317A918C96958796A49F94A1854100000D407EBAD6CFCCCDA35D1408316DAFC9C6C6C1C0862C0000145CA4C0C8A98B6C3A00000000020708000006080B10111D1C182229322E322F37353A372F236A562700000002216188AEB7B5AD8E7064442D496EA1ABA9956714000000002A699FAC91551E09206AB7BBB984475586776B7EA1BAC8BFA4733E4A6A82A0C7DF64442D496EA1ABA901FED55B07071850661F00064C8AA28D3A06012B67A1A6752A00001758A3CBCEB05618172F6BA9DAC8973A07000A438BC4CDCBA04B123687BECFC9ACAEBA953B0000002B657E8690ACB6A76E270B114396BBBEACB0C8AD893311287AA393939F91909F9B96A890410000003D81BCD1DFD3CFA15114093C76B5C6C6C0BAB78C2B000013619DC3D4A78D673201000000060B080902020B020D0E141C1F242A372F2A2E29323531322767542600000000235E90ABB2B8A995755744354F7DA6A8A3925E1B000000002A6499A3975D241D1C67AAB9B4803E497779767AA3BECDBAA783434D677EA0C2DA5744354F7DA6A8A301FED65B070718606A2800154D96AD9743110C3974A4B3753407001C64A2D3D8A2541D12376CA4C9C2913D06000A4194C4D0C59C4F203B84C5CABFACAEB8894100000031697E8E96B5BBA8641F02124A8FBCBAA3ABB8BB96351934849494A5A18997ADA8B0AC8E3B000000388BBFD7CCCCD2A24D0711487BAFBAD2C4C4B078290000206FAAC0C6BA8E5E300000000000060E030000000D081113121A202734312A303534322D331F6D5321000000062A5F91ACC2C0B09A7156363C4E74A7ADB3915E1500000000326C9CB398611D0E1A6EB3C4B381515487827680A9C4CBB1957057506984A9C1D756363C4E74A7ADB301FED75B070718707D30051C5298B6975016195084ACB67D360C0B1E619ED5E9AD561A163569A6CBC78B360000125294C1D1CC92471F3188CBD6CBAAA7A5893A000001456D748292B6BCA2591300164894BEB5A0B8BBBD903A13378BAA989B919498AA9CA3A1874100000B5088B6C5CED0C9914105023F8CB8C2C6C6CCB6812800001167B3C8CEA482632500000000020D11120000020B08181C171C29252D31312A2E37333335276C4C2300000013337097BBC0C2B78B725A38365485A3BDB681580E000000012B70A6AC9E5E1A182375B4B7AA7D4E5479787C8BA9C5C3B794684E567188A1C6D35A38365485A3BDB601FED85B07071880792F0019589FB390471017447FADB07D2B00002465AAC5D0A05C23133F76A5CBC7993E09000952A3C9CFCC96421B3D8EC2CCB7B1A7AF7F340000003D7B807E92ADB79C521204144C9BC5B89FAFBFC58D33193B76A0938A8F8F91A9A9ABA591400000003F8FCAD5DCD2C789400401408DAEC0BFCED4BE842200001567A6C0C5AB82662E0000000006140E09080103070F1110161A21302D2B292F31323633311F664D1C000000053B6494B6B7B8A48C74504241517CA3B0A58C5D13000000002B649DAC9B5B230F2670B5C1BD7D474D8081778CADC6C7B4966C4F4D6791B1C5D6504241517CA3B0A501FED95B07071890702C0C226AA2B9914211194084B2B87E3401092668ADD8D7A64C201B3D70AAC9B980340406214595BDD4CD8E431E3A8ECCCFCBB6B6AF87320000003F72797EA0B1B397511300154E9AC1B3A5B0C3C98F32193E8C978D9497899CAEADABA687370000074D96C6D9D3CEC3822E05175392B9CBCBC5BEB177210000266AABC1C6B3825E29000000000514150C0604070E0912131A201B27302D333B3639332B322D684D1D00000019416C9CB7BEBFAA7D645740425A7EA7ADAB804908000000062C69ABB59E672B152170B9C9AD753C5A757B7C8BB8D3CEAF9577464C6E87B4D1DA5740425A7EA7ADAB01FEDA5B070718A07A3B172E72ABC9A25A2420548BA9B57A300E0B3066A4D1CFA14B2223497FAECFC08A3008081763A3C6CACA983F1D4590C8C1C6B4B2AA802C00000A4F7B857C99B3B98B48140A1A509EBCACA7B9C3C192361F43839C8D8E8B8198AFAFB2A9762400000E5492C3D5D3D4C77B3100124D94BBC7BAC8BDB8742000002C7BAFC6CAB0825E2800000000051B160C0A00000B0810081B1B262E302C3031363A3B37302A6A3C0C0000000C487096AFC1BAA97D67513E3A5787A6B7B08F5B0E000000052763A5A7915221131D6CB1C2B67538447D7C7B8AB0C5C8AB8F625A4F6D8DABD4E0513E3A5787A6B7B001FEDB5B070718B06D2E15326BA7C7A2551C274E88B1AE6B2103083067B2C4C39C561F1F497DBECFC0893204001E67A7CECDC78B431E4192D2D6C7A2A8AF7E2B000004508C868598AAAF90460D09204A8DBDAFA8B5BDBC8E35214D8B99918A8A899EAEB1ABA67E290000125695C2D3C8CBC17D26051F569BC0C2C0CAC2AC6A1400002674B3C6C4B77D4F1D000000001218180E0F02000A050D112022212B30303132373834312C19653F1A00000019457E9FC3BEB19A8A64514B415988A8B3A98D4B0B00000000316E9EAC9A5F23021B6AB7BC9F753C4479787C94BBC6C6B18B634E4D739DBED8DD514B415988A8B3A901FEDC5B070718C07A3E1D447BBAD0B1612C336B98B8BB7C3011033A78ADD0D1915126305588B9CECF873705001861A9CCCFC7863B15439FD4D0C4B7AAA46A1A00000B4E8A8A819EABB1853F04061F578BB1ADA1BEC2B98C2F1F428A9994958991A3B2B1BAA8802F0000125D96C6E1D7C8B86426041D5CA1B8C0C7C3C0B0721A00002C7CAEC4C6B283511A00000000161C1A07050101030C140B0E19222B2E32342F2B34383431206730000000020F4C7899B7B4BA9F84646A4A476587A9A8B9915B12000000023365A3AE9759210E2374ADBBA9783C5584887C9ABDC8C1B6896848457599ADCCD86A4A476587A9A8B901FEDD5B070718D0743B194183C5D7A65F2C34709FBFB07C2F0D153372AACCCB9547252B5991B8C8C37E2505092B689FBFCCBF7F30264D9ACAD6D1B6B09F6D2000001159978889A0B3BA85330002185691AB9FA2B8CBC37E2319478C958F808B8DA2AFB0AEB0821F000017619AC6D8D8C6B77022001964A4BFC9C7C7C6AA680F0000317EAEC1C3B07B491400000007202321171400000308111217191E28292D35332D3932312A2A592D06000000143B81A6BDC0B49C7D5A50363A707FA1B1A9824108000000002A6FA5AA865E1A05297DB1C0A5713D4A797A82A0AFC9C5A38E6540547F9CBBCAE150363A707FA1B1A901FEDE5B070718E0763A264590D3D8B0622C3B69A2BDB4702A030E3B7BAFD5CE984D242E6496B9C5C5832D030D2869A7D0C5BB6E34204998D9E3D0B4AAA9711800000D589A8B849DB1AA782E0003225699B09EA1BAC3C182301B488D9B958883849FAEB3C1A76E1B00002968A9CCD5D1CBAF701C00216BADC2CDC7CABFA05E0100003481B1C7CCAA7A4B14000000061629240C0901000403080E1A202731312E2C2D2B2D33302A215D2F00000009234692AAB7B9B8A078524D323B6695B3BDA78A4100000000063471B0AF995D1B022582AAB4A16E2A4273817A9DC1D2C9A78E67385B739DB8CED64D323B6695B3BDA701FEDF5B070718F07348385798CDE4BE5E434774A3C0AB762D15123E7EB7D3CF8D3F25355F9BBDC8C18A36070E2C7CB8D0BAB07632224DA0D0DCCAB7AA9D651C000015669A988B9AA3A86C2708031D61919F9A9FB4C6C18131245690A692897E859FAFA4ADAF7E2200002B69A4C9D1D3D5B95C18011D6EABB7C1BFC3B69F560C00003B8EB1C6C6AE7A4410000000082A28170A060500060A161120242A2D2A2B2B2B28302F303221583600000000274D7DA3ACB5B5A6835D553B436890B7BDA9844503000000082F739FB2955C20042977AFB9A26927417B7A739FC4D7CFA887564C4F7DA9C2D8E1553B436890B7BDA901FEE05B07071800724B4360A4D3E8AF5D344A76B6CEB871290F1E477CB2DBC988462B3D6F9FBABEC780310E123377BED5C8AC6E2E1F4FA9DBD5D1B3BAA6520E000014589E9196A3AAA35F2A0805205E8E9E99A5AFC6BF8134214B929C938D8B8C9AB1B5B8B0711700002C67A8C3DFE0CAB55619092D6AB3BEC1C8BEB8A7570700013C8BB1C2C7AB793D070000000A1D28200C05070C04090E131321202526272C2D2C2C303334235A310000000E325591AFB8C2B196665650334F6B96B4C0AE904400000000003884A5AB9C692E00337CBCB993652B42677E818FC3D3CCA48A5F41537A9AB6DDEB50334F6B96B4C0AE01FEE15B070718106F433266A5D8E3A96D3A4A7FB8CDB4672B121C4C89B6CDC6803A253B7CACCACBC07D31131C407DAEC6C1AE6D38255094CED5C6AFAFA2621A000015649E99969BA396622400052B5A9599929AB6C4CC7F2E265592A29B958695A8BABCB8AC741D00003377A0C9D4D7C6B55716012572B5C6CABFB8BC9E4D0400055098BBC4C2A8714204000000112E1F1E130C00000909010B111B1D2B3038393633282C2D251A54280000000B1356A2BABEBCB99261534833446C9BB7C0B9884000000006042969A9B4965C20002E7EBBC5A765333E6677809FC1A8C3AA7F554558809DC1DAE74833446C9BB7C0B901FEE25B070718207E4A3868B1EEE5B169434B8AB8D1A664260A204C91B4CBC07B3C2D4C78B4BCC9C07D220719398DC2C8C6A6602F22519AD8D8C1AEAE9B571200001C64A3A1A5B3A38B4D18000D2B5D888B919FBACBC77B2F21529BA9A89689889EBBB9B29E641500003C89ACCBD6D9D5AE5511003887B9C1C6CAC0B9A14500000C4B89B4CDC4A5732D050000001B2D3527140C000000000507131E29263427282F312B2C2F2320622C05001613375F8EBAB8BBB29376524B404A78A4BEBCA3894107000000003E76A8B1945A2901267BABC3A8602C40648489A9C6CDC3A38560404B83AAC5DCE14B404A78A4BEBCA301FEE35B07071830774F3A5FA8DAE8B76D3E537DBCD3AE7423071B437BBBD7B8743A2D4E8CB4C4D1C57E2D09164480BAC6C49D5D291E57A8CFD8C5B4AD99551300002568A8A6A1A69F844717001031708E8A959DB4CAC97B2A275DA0AA967B7A89ACBABABBAA5E1200004178A6CBCAD5CCAC5A1A0A3579B0CDCFC9C9BF9D44000008579FBBC1C2AF773B000000001C3330260A070000000C0E1112151A2C2D2C282D2E3932312B1C591E010005223A4388C1C0B6AA855B5045414D7AAEC2C9B1853C02000004123872A4B7905510002B7CA6B3955F3341697786B4CDE9C5A57C59415887A9BAD1DA45414D7AAEC2C9B101FEE45B0707184077535075BAF5F2BC6C465C91C6D5B16D2E1A2B4E88B2CBB76C3A32549AB8C5CABC772C10214880B6C9B98C532020569EC6D6CAB3AE93460700002E75A9ACA9B3A0824313000A2A5A888D8397BBD4CD7D32336199AAA3847A91A9BFBBB9B45D0C00073D85B9CCD4D7CD9C4D0D103B85BCC0C7C1BCC3913A000012509EC3C0C4A96F34030000001D34302B130400010805110C0B131A2F2625292B322E2D35302347110000071F36528BABBBB1AC8860443D394D629FB7B3A6874900000A1818317693ACAA631A083280B0BA955A2438637B8AA5BBD2C3A78063455C88B0C5D3DF3D394D629FB7B3A601FEE55B0707185079504477B9ECF4B973436199CBD3A6662A1F274A89BDD0B26E3B2D5196B9C8D9C1802C07174C8DC4C3B9985A252163A9D1D4CAACA4974D1000001D74A2A3A5AE9A75431100093267818890A0BFCEC2742D2A659EB4A8928296ADC1B2B39C541400023D86B1CFD6D3D9A54E06044590C0BFBEC5C5C7992E0000125E99BBC0C6B46F2B000000002536372B170400000405070B131F222927252A2A292A2E262D1C4D2200061D2A436B98B6C6B4A2936B4C42083677A9C2BCB5873F02002115153B6FA3A78E5B1A073688B1AB9B6C3230696C7C9EC5CCB8A17E5F4C6287AED3B5CE42083677A9C2BCB501FEE65B070718606E49446AB2D9EEB66C4E598EBBD4AA61291524518DB4D0B776353158A3C4C0C7BC7D280B174494C2C6B77B48191859B3D8DBCDA8AA964C0200002978B4B1A6A8987433090014366D877F8898C3D2C1742F2D6BA5B2AA918094A9B9BEBD99520700024792BACDD3D5C69645130E4B8BBBCABEC9CACA9D3200000C5B8FB3C1CEAD662F0000000025423D2D1B07000000000704141E1C1C26252A232C2D332F2F235E3909031012345C8EA8A9A4A189594239434C70A1C1BAAA832E00001717172F6E9EB192550E022A759DB5996037383B6E80B3CACFC0937E654B5D86A8C2D5E139434C70A1C1BAAA01FEE75B07071870724F427BC0E5EBA7664A6499CFD5B26D2B15244C90BCCFAA5D3A3B67A4D1C4CFC675260D195094C5C3A8773E18225FADDDDDCEB3A693430100002777B3ADA9AC966B370D00104169816E85A3BFD6CD6F283367A9B2B28C83A0B1B3BDBC9847000008458EC2CFD8D0CD9D3F0B1A418BC5C6C7D3C5BB983800001454A2BBC0C1AD6D25000000052F40372A120C0003000103051515161D2C262D2C25312E2D29234C1904141C2E446D96B5B7B7A288643D2F35436DACC1BAA7753402041B1A1A535385A084561B0B3486AEB79A572835637286B1CCD0C6A17B61405787ADC8D5DC2F35436DACC1BAA701FEE85B0707188076584D7ABBE9E9B3714E6096C8DEAE6E311D20599ABCCEB764323664B2D1CCCFBF70270A224B8BB9B7997C3F242768B9E0E1BFA3A58E3C1200003585B9B6B4B38F67240B051A4371766F7C95BCCBBA6E2C3D6CA0B2B4908799B2BDCDBB9A4B06000A4F80B6C7CBD3CC8A400E0E4C95C6C3C8C0C8C0902300001B6C9EBFC5C2AA6D2F0000000128443B2413100000010105110A181D2A262D2E2D292A2A30321F47190A111B24416D9DC2C0BFAA84533D373676906DB7BBA773430A0E201D213874A4A88654200B3383A7B08D5C262E546F7FA8CAD7BEA2836655628BABC9D2CF373676906DB7BBA701FEE95B0707189071504D73BFE3E7B3714E66A1C7D5A9592419234D89B6D9AE6D343C72B3D2C9D4BB6D270C135699C3BAA26F35181D68C3DDCFC1A3A48D4009000A2E82BCB0ADAB8E582700001044737B74879EC1D2C76E2C2E6BA6BAB78E7798BAC3C5BC95460200105498B9CDDADCCF9B40100C4B97C1BEBFC1BFC4953E00001E6EA5BBC7BCAA63200000000E3355433217090000000009081118161C282E2928252D2D25271745120512282B5095AA82AEAAA188664537395083A2C4B79F783400002522173973A5AC9059150C3483B0B49459172B48648DBACED5BDA18B6C4F658BA3C2D8D537395083A2C4B79F01FEEA5B070718A0715B5B80BBE2EEAA735B6B9BCBD5AC69281E35569EBFCFAA63363E71B2CAC7D0B8691B02285E96C2C5946D34101D65BDE1D2C69DA57D37050000358AB8B0AEAF91601C0C002046726B6C799EBECEC56F353179B9BBB4857FA0BBC3C5B48C3B03001F5796B4D0D9D7C3843409134F99C1CACEC5CAC38D2C00002667A6BEC0C2A4661C00000010345148320F0300000000010A12141D1F242027242821262B2F1D6145373F454F6E9CC3D1CCBEB59462493D446992B8D0BFAE7C330314312A28427EA2A582542305358BA3BE91532E32586C8BB4D8CAB79F806552638BA7C9D8E13D446992B8D0BFAE01FEEB5B070718B07752537DBFE2E9AD6A5C74A2CCDFB5682D112867A5CBD4A0622F3880C8DBCDD8BC661A0329599AB7B9A26D310F1E60B5D5E1C4A49D753200000B468CB3B4BDB78D50140001205069756A809FC1D3BF6E293678B3BCB4947B9BC2CBC8B9883403000F5596B5C9DBDBC684360C1A609BCFD7C7B9B8AF82240000256EB0C7D2BDA460190000000F3C59482D0F08000000000305101C20212A2D2C292C2D222D291C572619292E3C4673A2B7B9B0A781503830355387B1CABF9D7931000D342B273E7A9EA48A5A26003987A7AA85512024516E90BED5D5C2A08160506B8DA7C4D1D330355387B1CABF9D01FEEC5B070718C07A5E5A80BDE0DCAA644D6EACDAD2A564311E395EA3CCD2A96331427CC6D6C2D2BE6A1C0B1E519CC4C09664241D2A74BDDBD3B79E9B74290A000A448CBCBBBEAF784F1E0000225476686B7F9FC7D7C56C2D346EB8BEB09685ACC3C0B5B682330000185C96BACFDACAC18B2F0E125CA9CCD4CBC1B8B379150000267AA4C9C6C0A86D1C0000000D35554832100800000002080A0C0D191E2A2C2523282C2E2E261C502A1B222E354D7699B4BCB09D8244262B395183A9BDB9A2832E000F2F35233975A89485501A1232859FB08B562125466295BED5D2BF9D80655A6895B9D0D7D32B395183A9BDB9A201FEED5B070718D0755D5091C6DBD5A66A5575AEDBDFB36B2D1F2B57A5CADCA65E343A84CBE0D1D7B673240C2A639BBEB2945821122272BCD8D8BE998F6E2A05030E4D88B7C0BBA281401C03001A4B766B5E7AA9C6D5BD632A3E78B2C7C09882A6BFCBC4B086360000246595C2D0D7D5BA84320A1D62A3C9CECDC9CABA812200003176B2B8BEBFA05B13000000144457522D170A000000000000141A181D271E2026212823302C17502321373336557CAABFC1A99C774C36313C5D8BA7BBB19D6C2B00083F34293E79A6A983491108468099A77C5222294E6D92BDD1D3BA987C6C5D6D97B0C7DFDB313C5D8BA7BBB19D01FEEE5B070718E06D605C8BC5D7D8A6645575B5D5DAAC63321D34689CC6D59E5A424B86C6CDC9CAC06D24112F6492BFB796552316216DBEDBD7B39B946E2504000B4695BAC2BCAF80470E00042D5B79726776AAC3D3BA62273D79B9C3B19493ADB8CCB9A67822000026649FC3CBCEDAD2842C0F2065A4C8CFB9C5C4BF8A2100003676A9B8B8B8A3500C0000001C495E4B3019030000000000000A18121A20212F2E33332F2D241D461F222D2E3D5880A1C1B8B69C78492E212D4987ABB9BDAD7524001E3F371C417E9CA2794214063F8CA3A186511A28486293C5DADBBD957F6D5E759AB0CEDBD9212D4987ABB9BDAD01FEEF5B070718F06E636190C1DBD99D685C79B1DEE0B46A2B2039689BD6D2A3573A4E90D5DBD7DABE62190A276AA0BCB5824414142670B7DCE1BE9B92721E04000F4996B6C2BDA4784312000630597E6B6379AFC5BFB15C2A417DB9C9BD9A94AEC6C5BFA56C2700002B66AAC2C9D1D4C7872A042970A5C5D2BECCC5B7791900003184AAB7C7C0A6560A0000001D55685C4416040000000000001110161E1D20201C27362E232F26481F292C36335C85AAC4BAB39B7C432D24375488B4C0BAA3712E03193A31254781A89E70401B0A4491A0A4805E1C1F385C8FC6D9D9C396796B637994B2CFD9CE24375488B4C0BAA301FEF05B07071800755B6388B9D4C890615380B6D1D3A7592F1A336CB0D7CF9E54405596DDE1D4DCB1611F06286BA0BBAB7D4E17082973C1DCDBC1918C622206001C5FA8BEB7BDA475470C0406316A806B637EAEC4D5B45628307BB7C8C29996A7BFC5B6A06C1C00002670ACC1C7CED2C4793A1B336EAFC7CFBFC1BAAE741E00003884BCBFC5BA9D520B0000001E5B7B5C370E0000000000020D08110F231F2724301D1F2525281C48272131383C5980A6C3BEB3A0784A232F33588BBBBDBA9F662A001535282F4C80A9A36B3C1E044390A4AB814E1E213E6A97C1D7CEB2978171676E9EA4CADED32F33588BBBBDBA9F01FEF15B0707181076555E8CBDD0D493635680BDDED5A45828273967A9D6DBA0533C5292CBDBD9DEB5611C12346B99B3AB8340170B2D79C0E3DCBC908C651B00001A56A0B9BAC0B67C2B08000831607B67617CAFD1D3AE5B2D3F82BECEBB9691A9BEBEB397642400003870AAC8CCD7E4C27829182E76ABC7C6C9CBC2B56E1C0007468FAFBAC3B799520800000030676D5F360900000000000000090F0F1A1F22202724212627281A463535343545608DAFBFBCA89676472820245B94BBC8B89A5F1B001D3E412C4B8FB3A07746261346919EAC834718203E6791BEDBD1B199827068728FC1D0DDDA20245B94BBC8B89A01FEF25B07071820755F6199C0CDCA97675B86C4DAE0AE682B1B3771B8DEDA9D5C34549FD5E0D6DBB75818152C619CB6A0773A19162E7DCBDDDAB99588641D00001B59A2BDBBCBAF732F100006316273656D88B0C8D9AF5A26418CC7CFC2A492ABC3BDB49D5D0B00002C71A6C8D0D3DFC0711A103471ADC6D4C8CAC2B6781000063D8DBAC4CBB79A5B0F0000002F5D765936140100000000000809110C171D222022252B2C3231254F2D38393F45648DB4C4BFB199764B3123326698B7CAB6985F2801164243345798AB9C8142170F4D919AA76F451817366B9ECEDFD1B3987F70616E96ADD0D5D623326698B7CAB69801FEF35B0707183077676B87B3C5C0915E4F85C6E5D8AD66342634679DDEDC9C483C5CA7E0ECDCE0A756170D356AA0B4AB7343130C3679C5E6E6BDA384501903001D5B99C9C5BDB1692C070008336A7961688AB1C8CCA85128448ED1D7BDA694A0C4C0AE9A550E00003277ABBACDCFD4BD7720133E87AFD7D1C9BCB8B96D150003478BB7BEC5B89848080000002D647A67410F05000000000000010C11192523242A30322A2632175033343E414F7091B9C8C3AD937449261B296397BBCEBC9A662000143D40395B8FB29F764217145293A0A38A4316193C6496CDDFD4BF9C7F72657898A9CCD4D21B296397BBCEBC9A01FEF45B070718406D667096B8BCBC88656087C3D6CFA45B2E2F4877B8D2DAA2533A539CD1D3D5E4A75A10123F73A5BCA76F2E16123480C7E3DBBB907D5C1C0B031C60A9C0ACBBA3772B00000441767C66637EA9C7D0A750274285CCCEB99A9AB2C3C2AD87470C0002367AB2C6D5DBD3BF7A2314408DB7CEC6BDCBC2AB6D1000065394BBC2BEB689460000000032718B6638150300000000000208090C17201C232822252F282817523D4A4D524C6B91B6C2BFB393724522232B508DB9C7B79B631500123946386097AB977D3F1B1A53969D9C743D1223436C9CCDDFD8BB957E7269788AA4D3D4D7232B508DB9C7B79B01FEF55B070718506F657090B1C4B48B5E699ACCDDD2A764392C4072ADD9E6A850385DB6E5E1DDD7B0561D10316AA0B9A66B35110D3981C4E6DEBB8B7C4D160B001C5EAFC4B9C3B769340000073E748D675981A6C8D19D4A2B4C8DCDD4BEA8A1B1CFC0A38545040011467FB4C4CCCDCFBD68240E4290B9D1CFD2CCBAB4710F00024C9BBFB9BAB49245000000013A75906A3C18060000000000000004120E1A1B1F2325292126261E4D4748433C487598B3CFBDA9926D441D2036609AB8BFB699571B0024423B456B96B19D6C370D1959929E9D6B401D1B3A689AD3E0D2B6867E7C556D92B3CEDFD62036609AB8BFB69901FEF65B07071860786F79A0B6C3B77F716B9ACFF4E1B06B3B24416CA6D2DF98544561B8E9ECE7DCA34C0F113B709ABCA7712D06093788D5F0E3B7926E470F00132859A1C1B8C3AA5C2805010B3C808967658FBACACE9D3F1E3D94D1CEC9A999B6C3BBA785470600124F85B9C5CAD0D5B56C26174590C1C5BFBBBFBEB26B19000B599FB5BAB8AC883A000000013670896C361000000000000000000A141A1C141D1A25303129281D534646444E5778A1C3C7BFAB97734B27243462A3C8CFBD9B5E180026413A376B97B5A1683B211B549198927F4620273966A6CED9C1B28A807E6D6C8FA8C9DBD7243462A3C8CFBD9B01FEF75B070718706D5E6B96A6B9A37353699ED0E4D49A572F293868ACD3DC9D5A4665B9E5E7E9E69D420B0D3E6E91A691602607012F88D7E0E5C08C694317050E2671ACC8C3C2A763260102183E7F8A6B608EB8CAD29344254791CACCC4ACA1B3BEC4A87E360500134888BAC8CDD0C8C36B201F5096BDCBC3B6B8BDB56809000D6398BDBDBBAD863700000000397A90693E1A0B00000000000106080F21191C2021292A282A2C2046353D40465B7EA5C1C8C3A68A68421B18355C9DC0CBB291561A001E36434A6FA5BB9B622B1D265892939C7A3E171E3B65A6D1DCD0AF8C81806E7090B1CFDBD018355C9DC0CBB29101FEF85B0707188074666E98A6B6A586626387C6E5CE9D5B2A294581B8DCE09050416FC1ECF7E8D4943E151A46678DAD9E591B040E3288CCEBE6B58E663A0C00082C6CA7C5C2C0AB6B270001124D8185696093BFCECD8A43244094D2C9C8B19EB5C2B4AB75320000185290BDBCCBD7D4B9662121569DBEC8CBBBB9ADA8610C001D6C9FB9B8B9A88345000000003B798662411B00000000000000000C1022222029232C2420202415503A424348607C95B8C4C8B48F693E22224473AACAD0B8955C0F00183F475077A6B7945B361C316D9D8F9D6F331D12306BA5D6DAD1AC9381806D7C91B2CCD5D6224473AACAD0B89501FEF95B0707189077717E9CB8B0A376586894DBF3DEA95D38344E74BEDBDF965A4C76BFF2F3E1DC9E3B141D3E7295B39B4A21061A3D92CEEEE7B88761310D00083870ABC3C2BCAA6C290511164B818262588EBECBC488391F4399D5CFCCB6A0AEBEAD9A6B2B000020619BBEC1CCD3D5B568231E5C9ABECFCBD0C3BDA45403001F64A3BBB7BAA58334000000064085937343140000000000000204050E0E1D23251B2428212524194E43484C5B677E9DC0C8C0A7886D4A1E153C6EA7C4CEB88C5313001A39443F74ACAD93633B0E1E609B978D5F3616203B66A7CFE1CAB2897C766A7F91B6CDD2CD153C6EA7C4CEB88C01FEFA5B070718A0756F769CAFBA99746B6DA1E6F6E5A36637294174B1E7DF91545280CBEFF3E3D68B46131342748A9E8E4D1C0A0A398ED5ECDDBF8B63310D0410346EB5BDC0C1AB651C08071A518888706B94BDD1CA8A39223F90CDC4C0AFA8A7B8B7995F2300002960A3CCCED4D6CEAD5B1B2156A6C0D3CFC7BCBBAB5200001E71AABFB1B3A67B31000000124A7F8F76431B0200000000000000080718161B181C20242B25291B5B404850506489B5C7D7C7AA906E452B2B3D6895BFD2BA9357190016383B4C82A7C29A6B36151F648D83916C2F1125336EA7D6E2CCAF8A7B807C7E99B5D5DBDB2B3D6895BFD2BA9301FEFB5B070718B073728AABB0B09B75666CA0D7EEDEA7633C2F4676BBEDE490504072C4EBF0EEDC943D14224F7096A8904916021B448FCFF2E0B9956029030010337AB4C6BDC2B5671F000D215B938E6F638BBDD0BE8A301E529AC4BCBDB5A2AFAEA78D602600062B74A0BAC6D6DAD6B4581B2363ADC0CECCC6BAB1AA4B000029729EBAC0B5A9843900000012498694794612000000000000000108121923201D251F2324282A1B503B4C46476696BACAD8D3B48E733D23254172A9C9D2C89C611D00102A4B568AACB799603A2F2A75988195642F1A263D64ADD6E2CBAA8F7D74686C92B5D6D9D3254172A9C9D2C89C01FEFC5B070718C0736B79A1A9B2986F5F6FA2DDEDE0A55F352C4275B2ECE5A2554C84CAF9F8EDD68E310E1B497194A68A40130218468DC7D8E2C48B5A270604164781BBD8C6D1B66B20000017518A8A666797C0C9C3813E14489AC5C0C6B9A4AEB6A1794F1A00033370A2CAC8CCD1D8B85B172372ACC8D0C5C1C7BB9C4801002578AAC4BBB7AA8432000000034995997740130100000000000002060A111B1C281E262722242616473E4C4B456196BED4D6C69F8F69450D1A4377A3C5D5BE8F5919081C353A5486ABB88E57311B2A69A3868C69361533447CBED6E1BB9B857D836E6B8EAEC8D8D91A4377A3C5D5BE8F01FEFD5B070718D0706B7F9DA2A9926E5C6FA2D5F0E8A15338325279BEE9E9944A4580D4F8F6E7D57F2D0C1D4C76879473391409174198CFE5DCBD9057280D0725408AB7CACCC2A45721000B205C9896716188B0CBBB7122204EA3D4D3CAB3A7ABAAA3753F0400053388B7CCD0D9CBCEAC511B2973B5CDD2CEBEB9BBA44C06002B7AAAC2B7AF9E7430000000145499A47E4A1E00000000000000000C0C151B1A1D1C1F2226181B165A4C524F586F95C2E9E6D1B8937044293A4F81B2D1CEB4885B1B08153A3D4D859FB28E612D18225D9A8B8D6B2C17274F78B8D9DCCFB08A726E6B628CB9D5E1D03A4F81B2D1CEB48801FEFE5B070718E0737482A39C9C896A5B6EA5DAEEE99A4D383D4F76C2ECE59D554B85DCF7F4E0D07E26031C597C9BA580300F0210449AD3DCE2C4926228030B1E498DA9C0BCC2A3622305001F5F9B92746B95B8BDAE6F23194792C5C1C2B7A1A7B29F7348110011518AAAC7CAD2D2CAA451162C7AB6CDD0C7BAB6BB924301033A7CA4C2B1AF9D7D2D0000001E589FB683431800000000000000000C0A0F151D181920161C2122175452544E597CA0C9E4DDD6B29479502C355285B5D0D2BA90591E061E333B6093C0BB8E552B1F3473A68591592E26333970A7DCE1C4A77B7774676D94BFD2CCD1355285B5D0D2BA9001FEFF5B070718F06D737CA2AA9D8361566795CAE4E0A0613A335183C1EBE68A504E89D2EBF6E3C5792D16215C7A8C9E6B3110051C479AD0EDE3C99C5D28030E1D4D86B4CECCC39E5218000422619C95776B96BDC4B56327174796CBC3CCBCA39E988C6B341000094986AFDAD3D3DCD2AE501D2E7EB2C3D2C6BABBB29C4500002B83B1B6B4B2A27C30000000175F9BAA7E510F00000000000000000D0C181F1D1F1B1D262222201256536052677BABD8EFE4CBAF96694838354789B7D6D5C4974F1404182D42648FB9B68C572F1D206CA0808A56251C2E447CBCDDDFC3A57C6E72727589B2CCE5D5354789B7D6D5C49701FE005C070718006F768CA2A29789635A6AAED8EEE8A45537334E7BB9E2E18D48528FD9F4F7F0CC782D10275E7A8FA472280C06174894CDDFDECE9D58250A09274C83BCC9C8D0AD571E00001F629D9A776C95BAC8AC601E11419FC4C3C8B498969B8C6D2F0400155C98BCD9C9D0D8CCA64921307DB8D0D7D3C1B3B28E3A00003D8EBAB8C0B29B712100000015659AB08D58230500000000000000060D10131A1F1C1B222B252416604C444A5272B6D9EBDED5B98C64522F3B4F7FB4C9CBAD81561F0D0E28315EA1D6C29658302D3773956F875927202B4C74B9DBD9BE96796D70625D94B9D9E1D73B4F7FB4C9CBAD8101FE015C0707181065788AADA5A17E585D6BA0C6DFE79C5D34314E80BEE7E198575A9DE4F1FDE8C96B2A132C6181929A703107031A4E92CFE7E7C4A44F13000924538BB7CBCBC9A361190409336E988E757693BEBB9F5818104495CAC8CFBCA39290835F330A001C6AA4C7D9C4CBD2CB9F4F1B3980A7C4CDC3BABDB48A3500034F95BBBBB7AE9075280000001D62A1BA8F58210000000000000000060F151D1E16151E261A17140933322944657CB7ECE8E5C5B18E6C45223B588CB5D4D9A7875B1F121F2E3A6BA0CBC08A522B2128759F717F5D25212C498CC4E2DFC4926F6566676596B8E0E1D73B588CB5D4D9A78701FE025C07071820776D91ABA39B83635A6D9FCDE4DE9D5D3B395F80BAECD8874E5C92E3F0F7F5D67528102B6A8698A4662303001B448BC7E5E3CBA05C2711092B548ABECBC9CCAD5D180010276BA29D7873ACC2B590471E123E98CBC7CBC09F858977592002001A65A5BEDED3D6D7CD9A51193383BACBD6C4C0BAAF892C000D4E98BCBDBBA9967629000000206DA9B48B4F130000000000000000080C151615191B202622212313483A4456628CBCDCEFF0D9C2986548363C5790C0DDDCB78758190D1B2B3B67A0CABA86543E2B397CA27687503325335D8FBDDAD6B88C6A6D7162668AB2D1E6D43C5790C0DDDCB78701FE035C07071830798095C0B79B7B605F78A6D5DCDD9C5A3D3F5D8BBBE6E28D565B9EECFFFEF3C4661E0A286A8A90965C1E04031D589ECDEDE7D0A5521B00101F528AC1CCC7CB9E5819000C3476A19A80809FC2C9A4561D114290C9C0C7BB9B867B67441800002566B6CEE0D0D7D6CA9545234187B6C8CDC2BCC6B78B340B11599DB5BEB7AC9C7224000000266DA8B08B521500000000000000000507131616181716241F1F21124A403D465E84C3E6FCE8E1B98A6A4B33365593C0E0D9C0875927131B213D74A6CCB9874F2F273376A36F7C5028213B5496C1E0DAB590686370645D8CB7E1E0DC365593C0E0D9C08701FE045C070718406E7BA2BCA2998361616EA1CCE6EB9A5136365178B5E7D68E5D61B3DAF1F5EAB55C1E0B33698F94926B1E00092753A0D5E3DACE9F541A00172A6196C3D6CFC5A350160008316892967D7DA0BDBF90410F124593CCCFC9C0988279673E1400002B75BFCDD9DBD7CCC7943E123A81BDD1D3BCB7C3BE862E0D1A5B95BBC6ADAC99862D0000002776B4BA98511E0000000000000000000C0C13181E151D23221921104E3341466C98C2E7FCFFDAAE86764938375D99C7E5E7C191551B15202D447DB7C9BD83523A2B3B78A56D8154271F2D4A92CDDFD2AE7F606A645E5783BADBDDC1375D99C7E5E7C19101FE055C0707185065819EBCABAC7D605F7198C6D8E09855383D5381BCEDE0875161AEE7F7F7E0B2541415366C999497581D00081B509ACFE4DDD5A6481205122C5E96C7C8CCCCA44F0E000E3A7C9E9C8A86A3BDB68B3811154293CBCAC9C29A796F563512040B2A81C8DADFD8D3D6CA9148184791C3CED2C2B9B3AE7D24051263A0BCBCB7AE91772D0000002B76ACB68E491F0000000000000000020410141318171A242C261D0D514C4C53678BD4EAFDFCD9C78F6447314469A0CBE7E5BC88572514242E4E81BAD1C18554302C3E82A4627E53291C30569BC5E3DCB18665625A5A5B81B7D3DCD04469A0CBE7E5BC8801FE065C070718607B80A6C8B3A37C51506C9BC5D8E09B53303F558CB7DCCB875466AFE9FBFEECB0511D18407E879B9A581C000A1F5A99D6DFD9CEB3561700112F62A1BCC9CAC38D4611000D37709FA08586A1B3AE7D3D1012428DCDD4D1BE956C6250290D0001327FC5D0E3DCD3CFC6843B26549AC2D3D9BEBCBFB27F24021C65A4ADBBB7A9997734000000307CB0B3895625030000000000000000040E0F0806191F20211C22174B3138446796C5E8FDF5D7B690744E3C4B769DCEE4D1AF845F2218213A4690D0CEBA815236303E799B68834F2C24235D83BED8CFB187646E6C5E5B87BDDADBCC4B769DCEE4D1AF8401FE075C070718706F83A3BFBB9F7A53616C99B9DADA995843425783BFE1D4814D60A9E6F9F4E2A64F18173A809E9F9E631D0000285695D2E3E2D8A64815021F3B659EC8CEC3C697460E000C3F76A4A3947D9DBBB27A2E13184F93C5CAC8B38866614C2E0D03023B8CC0DBEACED2C6BE8535214C99C5D0CEBDB7B9AC682C032A6EB1B4C4BCAF9A7C2B0000003481B1B6915222040000000000000001030714121B15181F211D1F1948393C4D679DD5FBFCF8D9BB90795C2C53689ACCE1DFB58A4A241C2F315A8AB4C4A77E3D372C43859F5F7A4C32333562A4CDE0CBA17A61616C615D90C1DDD7C753689ACCE1DFB58A01FE085C070718807C8EB5D5C8A77C59536E97BCDBE49A56413E5282AADAC8874C71BCF0F9F2F0A548171C4D8EA29D97520A000A2157A3CBE5E2D6A43E0400123C6EA8C9D2D1B58C3E0D00133D719AA7928FA0BDB474280C124891C6D7CDB98B6153391C0400094093D1E3E8D5DAD6C583302661A0C4D4CEB8B0B7AC6D1B002067A7B6B9B0A79D8E360000003D8AB3BA8F55160000000000000000040F141A110E1B17201D141B17442C40455F96BFF8FFF7E2AE8C63543B4B6B99C7E2DDB1916123192B354F88C8CBA5754023414C818E4A7856312A385B9DC9DBCDA8794F5D585E6691C0E4DBBD4B6B99C7E2DDB19101FE095C070718906B85AFDEC7A680555361839FCCDA894B30365C7DACE0CB73496CBAF8FEF2E5A14B13153B8AA5AF9B551500011C579FD7F2E4D0A4430D0015396BADCED5CFC095330000084181A69F8C8DA4C3B16721070F4394C7CEC5AE7D634D442510000C4CA1D1E6DEDFE0D5BB762C20599CC9CFD2B0B5BFAB691703357FB1B9C2AEA99A7D340000073E7DAAB398552A000000000000000000040A1110131318232322210C4B34405277A8F0FCFFFADFC29874574D5177B0DCEAE6BE844E282029455E9ABECBB7734A3B3A4A85984D71523B2C4A6E78C9DACB9C7053555D5F5987BDD6D9C85177B0DCEAE6BE8401FE0A5C070718A0718AB3D6C09D7756576C8CA8CFDE91543D405D86B4DBC4835C6EBCFAFFF9CE97401618428EA9A7974B0F000C2467A3D8E1DBDAA9480C001C456FAAC7C8CCC88A430D0117407C9EA689889CB6A66D26071C529BC3CECBBD7E58432D1400000E5AA2DBE6EAD7D4D1BE7F342058A1B6C9C4B5B3B6A3631A03387BADBABBBBB29C82360000003F88A7AE94552206000000000000000002060C0F1213231F221C1B0F5B48414D79B5E9FFFFFFE5BA9774642A4D7AACD9EEDDB6815D2F2A333E6996C2CCAF7A41313646809854845D33263362A4C2DACB9B6F51565855598DBCD8D3BF4D7AACD9EEDDB68101FE0B5C070718B0788FAFCDB7996F51496183A8CDD78B4341496186ABCEBA7B5177BFF6FEF4DD9A43111F4898AFA69E501900072C61A2D7ECDFCD99451100194B7DACCDD8C9B6823C00001E4E809BA89C9498B49568250A16468FC5D1C9AC84533C301300001659ACD5E3EFDDDFDDBB602F2255A2CBDBCCB3B3B5A96114002778ACB0B9B4A79B853E0000084D90B3BB9B6023000000000000000008040814121314151B1B1A2219453D3C5976A4DCFCFFFFE3BF9B6C54515074A7D7ECE1B7814F1E25343B6398BBC8B577483F3D4A849E517454312C375E9ED4DDC799654656615A5C82BAE4CFC65074A7D7ECE1B78101FE0C5C070718C0798EBBD4BC9D7758526384A8C6C7884937496690BCCFBA724F77BBF8FFFFDB97381C1C4D8FB5AC934C11000C2F69AAD6DBDAD09D430E001D4A7BB3C7D4CDBE7C350200154C81A1A89998A3B2965C1D0D0F459ACBD2CCB27D4435260605001A5DABE0E7E5DADED0B76A2A275EA8D2D0D0B2BEB29D53120A3788B7B3C0B1ABA7852500000E4A94B4C09E5B1E000000000000000000050C180F10121B251E191D126152596985BFF9FFFFFFF5C3A1886261657AAFD8DED7B28E602B2B32456A98C9D0AF6D3C3839498596567A55322E4369AED4CFBC996751495850548FC4DFDBBF657AAFD8DED7B28E01FE0D5C070718D06F89BFE6D3AE724F4B63829BB7CA8C4A3A446993AFC6A76A517DC5F9FFF3E1993B1110559EADB09E540E000D275DA5D3DFD8D4A3470C0B21527DB2C3C8BDB17D2C0A001D4E83A8A7A6A1B1AA904D1400174786C4D8D8AB75413C22090008225EADDCE8E4D4D5D3B963202A6FABCECECBB3B9B79F590D03388FB6B6BDAEA19E86310000175299B3BB9D5D1B0200000000000000000009100B151C171B181D19124F39374B6DABE0FFFFFFE0AF867053535872AED1E9E0B67F4D221B303E6FA3CBC8AB6C353B414E7D94517D5E372D4476AACFD3BB8E5731475A5A569AC2DFD3C25872AED1E9E0B67F01FE0E5C070718E07793C6E6CEA966454C5D7794BDC1864C36385D86AFCAA8675C82C0F1FCF9D78138181F509CB4AC9B4D0D00092E71B6D0E1E2CEA7481301254F86A9C7CAC6BA863200001D5D8F98A8999AAAAA904C1D061A4C8DC3D7C9AD6B422E1A00000C2B71BBE1E6E3E3E2CBAB5C272766AAC8D6C5B4BEBE9B4F150C3784AAB7BCB5B2A68A3600001C5B90A8B38B5C200000000000000000000304101810191A1C15171F0F584B4C6286B8ECFFFFFFDFC0A07975616478ADD6E2DEAF7F492730333772A8D2CDB0775343334374945379563C3C4674ABD3CDBC895B35475D515C93C8D7CCB36478ADD6E2DEAF7F01FE0F5C070718F07891BBDBCFA4715347577A93C2C481413D49698CADC6A8655880C5F7FFF6CF882F0C1B59A0AEB99E50160011397AB2D6E0D9D0A53B0902235982BACBCAC6B67F2C0000236089A5A9AB9AA2A384440902124C8BD2DDC6A16A2F261A040007347AC8DFE4EFDBDACFAD5A262A6CB2CED0BFA9B4B29A4D0A0B4C9BB3B0B7AFB0A286370000135D9CB9BA8E5C26000000000000000000000107160C181A201B1B180D4E49535B79C8E3FFFFFDDBBE99826D54617AB7E0E5DAB77B4E2B1D374C77A8C9C9A1733D3E42547E824975663F3E466C9CCEC8B1905D434C5653528FC9DDC9B1617AB7E0E5DAB77B01FE105C07071800698EBFE6C8A36A4847587492ACAA71403A536D8BA8B5915D5689D6FFFCFEDB7C2808195290BCBC954C0F000F3A70AEDCE0D6D0A4380906285A93B1C1C5CFB96F230200306692A3A2A69E9EA081411005164E93D0DDC59E5D2D1C0C0000102E7BC5DFE0E9DCD0D2B35C273779B1CCCACBADB5C09C410D114792ADB2BCB8B0AC8A2E0000225E8FAEAE8F5B21000000000000000000050D08121510151E221B22135B404D6D89C2F3FFFFFFDBAD8A7A676B6576B1E4EED5A9854816172F4C75ACCDC5AC6D3C3D40507F9B50805F3D2B416CAECAD0B17F583B404B4F5A8FD2DAD7B86576B1E4EED5A98501FE115C07071810708CC9E3C39D694A5060688FB2B57045395773919BA48F595584D4FFFFF5DD821F121F54A2B6B9974108021A447EBAD0D3DCCC9E3C03002D5E97BFD4D4C7AA701B00002A6A959B9FA39FA6A28031110B20488ED4E1CEA15F2A100300020D3282C6EBECE7DAEAD5A1511F307FBDD5D8C1A9A4AE8E3A0519458FB7B8BEBBABAB7D2E000026679FADB5935C2900000000000000000000070D13120C1C22212A1A0A635E636F86BFF8FFFFFFE9AAA37B6F61768FC0DDE8DEAF764E222432517BB4D1CAA36142434A527A90437A653C384779AECBCEB67B483234484A5889D4E2D0AA768FC0DDE8DEAF7601FE125C070718207098C5DCC7976D4D4A617087A8B06E393955758F9FA6855B5483CDFFFBF7D1782C111F5AA2C8C297490F00153C7DC1D5DBD3CB973D0805285994B1CAC8CEB8761B00002B6E8E9D9FAAAAA5A1773310051B5D9FDBDAC190572A190400000F3492D6ECECEADFDBCA94511A3184BCCBCDBAA6AAAD85380B215099B6B2BAB2BAAE812B00002D71A4BDC496512000000000000000000004040E16101D1B1A1216191263585B7899C2FCFFFFFFF4BE96796C686C88C0E2EED5AA76471D242C5D8BA6D2C89762433F44517C8F4274663C344B7DB5D1D6B7804E2E344345629CC6DDCEB16C88C0E2EED5AA7601FE135C07071830689FC4E1C59C5B43505C6D89B0AA61383F598294A5A68453487FCBFFFFFACA6A1B081E6095BDB8924504021A448DBAE1D8DACA832A070E346397BDC4CCC9A462200005377697A7ADB4B0A89D6E2604041E549AD1D0B891562D0C000000133F92D6EFECE2DAD6CB9741213E80C0D2CDC4A4B0B18F360E1E5DA2ABAABBB2B8A5802800012E6D9AADB5985E250000000000000000000307101415191D181F201F0D67566287A4D0FEFFFFFED9B0A19173727498BADAEBDAA675471A1A445587B0CFBF995E3B4345567E9042705D3E2D4876B5D4CBAE693925293B3054A3D1E2C1A87498BADAEBDAA67501FE145C0707184074A2D8F2D2A9634B4A67778DB1B2614A485B7A989B96734B588BD5F9FFFAC96B260A235FA5C1C7984911091B4889C2DAD4D5BC902E010A3A73A4B8C4C2BFB3711B00063579999DADA2A5A395622F0F0824558BC3D0C18D4F210E000009164E9ED9E5E6E3D8D4CC924A1F3D86C0D3D5CEAFB7B07929091B61A9B8ADB1B5B6AE843000003B78A6B0B68A5A1A00000000000000000000040E0A111C171C1D121716534E5B7EA9D5FFFFFFF9D7B79B886C676D88BFE9EDD7AD763F1E1B365993C5D0C598613E3F3C4D80904A705B4B2C4380B7CFCEAB754523303538559ED0E2CAA96D88BFE9EDD7AD7601FE155C0707185089ADD8ECD0A575544D5A708BA8956241425D7D97A5956F4E5992D8FCFFFAC86725112B5EA6C4C09142100A1A5291C5D9D7CEB98532040C447B95C0C3BFBCB35E1800113B7D969BA8BEB4AD8E5F1902091F5C9CD6D3B482491E090000061A539EDCF6E9EFD3D2CA913C163E83B5CCD7C8ABA9AA712B0B2E6CA8AEA6B6BCB9B07E2700124B7CA6AFB8915317000000000000000000000407120B12141B211C240E57505B7591CDF6FFFFFDCBAD8D7B74526585B9DFE7C9A06F391A2B3B598EC2C7B18F593846364A748A3D7764402F4583C5D1CAAD6C3E1F1E38435EA5D0DEC5A96585B9DFE7C9A06F01FE165C070718606EA1CFE0C08E5F404B62738AA0945E3D4464829B8F876B50598ADDFFF5F5BB5D210F2D5CA4B4C095411A0F24599EC6D4CCC0AF7B310908437EA9C4C7CABBA2641500174C8AA09A9CACB0A5854D230004265AA7D2E0C07A491D0A0000040F52B6E9FBE9E7D8DCC18E381E3C8FC1D1CEC3B3ADA66F2E162D64A2AEA3BBBDB7A9782600034C8AAFA9B38A4414000000000000000000070B060D1415141714151A135E546780AEDEFFFFFFFCDBA5909679657590B9E0E4CDA873432122305A8DB1C9BC9A6346394F517391427E64472B4988BACDCAA2663E262A33315B98D7DDCCAA7590B9E0E4CDA87301FE175C0707187077A2D2E9CD9F693C46596E81988953404C688990988861415A9CDDFFFFEABF5F1F062769A8BAC192440F082D5B99CDE3D1CDB47420000C477CAFBBC1C9C7A9600E00084A87A89EAAB3ADAA7E480E09072A659FD1DDB6763919070000081C5DA9E9F4EEEFD8D5AE6E352741A0BDD7C7B498ABAD7838163072A7A79FB2B8BFA8732A00105C84A4B3AB803A1300000000000000000203040A09101315181B1B21145765767D9ADBFFFFFFFBCFA5937A6F646C95C2D8DEC39E723E1915356596B8C6B790614441444671903E79603F375273BFDCCFA6693C1922334366B1D7DCC2A76C95C2D8DEC39E7201FE185C0707188077A4D0E9C78F593D4A5E6E8C9E885C3E436B919A947E5C435596E3FCFFF1B15B1A0B2965A7C0BD9042090B2C61ABD0D4CDC3B26D2105174D8CA7BEC6BCB0A45312000F498DA4A7ABBBB0997A471305062E659CCFE7BA79310D0400000B256ABBEEFCEFEDDAD4B9712F174DA3C2D0C5B59FA6A86A26162F6CABACACB5BABFAF7115001F6597A4ADAC763E17000000000000000000000413120F1618191B1A15105A556A83AEDFFFFFFFFFD2B59F85746C6A8BC1D7D4CDA06639151738699DB3CAB484573C3C5D56748A40786047335688C3CEBAA06B381A1D314363AFC9DEC39B6A8BC1D7D4CDA06601FE195C0707189078A9D8E8CC94513C47476C7788794D41547395A98D665347569EE8FFFFFAB45417102D6A9BC2C08A4016093470AEC6D2C6B5A97125010B4388AFBFC7CAC2AB540700155E98A49CABBBBFA477380A010B2E5D98D0D4B76F360F0100000D2864BEF1F8EFE9DCD1AF682B215295BED0CBC3A8A5A46624113D80ADAB95B5BDB5AE7223002D70A3A2A8AE7A441700000000000000000004050A0B0E1A181B1F171E13676A7387B1E6FFFFFFF8D3B18F8072696A96CFE1E0BA8E6E3B1A1B526E78B6C7B6885A44414B56788A427D653F2B5A92BFCFBF965929141F2D476EB3DEE0C2996A96CFE1E0BA8E6E01FE1A5C070718A077B4DFECCD95523A455370808A7243384D7A94A58A624C3C5AA4F0FFFFFBB64D1512246A9AB8B18C3E07133070AFCEDCDAC7A5631C09164C86ADB9C8C6BAAD5A1801155190A0ACA8B7C3AA733407000C316FA3CCD2B57A3610000000042472CBEBF7F1E4CDCEAB651F184EA5C9D9D8C8A8A3A169220C3B85ACAC98B5BDBEA36B1C052D7AA3A4B09C794A12000000000000000000000A07090E0D141D1C1A1D186B667997B8E1FFFFFFF8CDAA868B7267758CB9DCBFB2705D321E1F4073A4B9C3B6885638464A546D8C417C684A3B5499CECCCA975A2C0A17344A6AAEDFDEB69A758CB9DCBFB2705D01FE1B5C070718B075A8DFECD1985D35455B6378856A48344D7B9FA28B5F484159ADE5FFFFF7A94711123468A2C0BA89360309337DB9DFD4C6B99E5724081A558CB8C0C7C8C5A44B08001E5C8EA09FAFB4B8AB7B3606000C4071AADBD0B36F3206000000052A78CAF2F2EBDDCBC3AE62231E4EA2C2CBC8BEAFA69A561A164783B0A696BCC1BCAB6916002C81B0A8ADAC804F1D0000000000000000000000090B1215141B1A170E086E687D8EB4EFFFFFFFF8CFA083807672767DC1DCDDC394662C1D284A80ABC3C5AE8A50384942586C7E357B6C49456696C8D2BD934D2A1C1C304775B4D9E2C89B767DC1DCDDC3946601FE1C5C070718C06F9FCCDAC7824A314F5B697C7F643B3F4979ABA07D5734325DAEE7FFFFE6A3420C0B3079ACCEBF8131111A397CBBD7CEBDB2934712091C62A8BBBEC8C4B79F4C10001A65A5AFADACB4B8A8792F0000124573A5D8C9B0702D0200000004347BC2EAFBF2ECD7C191581D245298C7D1C1BDA5A9A0591C174F81AFAC9BB6BBAAA6621A0A3F8EABA7A7A789471800000000000000000000010C13070B131E1C191D16707B888FB8EDFFFFFFE7C993826774727198C4DDD9BF905C301B1D4B7CACCBC5AC8355464A53556E8435847054385F9CC5CCBB93551F01122B4683C0FFEABF8C7198C4DDD9BF905C01FE1D5C070718D068A7DEEDCD8759444E5C6F7E80583C3C5D85A8A385613F355FAEEEFFFFF19D440D11356BAAC2C08137080D397BC6DDCDC7B38E4B0C031B679EB2BCC4C8B9924300022E70A0BAB0AFBEB89C5C210000184185B0D6CCA260270B010000123D89D2F3FCEDE2C8BC95520D1558A2C8CDC9BFADB18B55231B5897B8AAA3B5BEC09C520902398EA4AFADA972482100000000000000000005010B0A17100C1F1A151F0D6776809DBCE5FFFFFFE8CEC089886B5F709DC4DCDAB988592910174173A6C1CDB1865543424E516C823079764B4465AACAC9B485441203161D4765C3E1DBB98B709DC4DCDAB9885901FE1E5C070718E07BB4E0E7C88D563A4E5A73838163313E5F86B4A7784C353463B2EEFFFFEC9C3F0F143F78A9B8B67E30071A3F8CCCE6E0CEA5723A09002270AAB0ACB5BCB898390C002979AAB7B0B8C2C5A2611D0000134C86B5CBCAA3612A09000000073588D4F7F0E8EBC9BB8743182A60ADBFD4CFBDA09F8C430E1D649EB7B09AA5B2B599530A085396B4ADB3AE794B18000000000000000000010A090A101B171213171F0E777388B1CFDDFFFFFFF1CFA58C876B717BA6C8DEDEBF905F2F1E244C7BB0C0CEB084543E504D526887387F725245689DC8C9B7865D1E000525587CC8E1D9B38A7BA6C8DEDEBF905F01FE1F5C070718F072B2D5E8C47C4537486271766B55363F6492B2A4723D2E3969AFECF6FFE7963A0210427AB0C0B678361014478DCEDBD8B398763B0F021D63A4B7B9BDC0B495450B093179A8ABA8B0C2BA9C652100011C5080B3CEC89A6024000000000F3D8FD5EEF3E9DFCCB68340181E61AFC9DBCCBDB1A18A50172B5CA6BFA4A6B4BDB89A490B05558FA8A2ABA882492200000000000000000000040D140A1309181116240E968B5EA1D4F8FFFFFFF6CFA29886706F84ABCEE1DBB77F58371B1D477EAFD0C8A47F5A47404E525A8E3778775E526EB9D2AAA9784618080B2C5481BAE4D6B18684ABCEE1DBB77F5801FE205C0707180077B0DBE5BF7E4F394F68717876463B37619BC2B17E3D282F67C1EDFDFFE38A340C1D4783ACC6BA83320C13468ECFD2D6BA936C2D0805266FA7BAB8BBBBAA7E3C06033381AEB6B3BDB9B699601C00001E5889BFCDCDA46626000000001E4795DDF3F1EEE1CDB07D3D111D60B4C7D2CDC2B0A579420C1F6AA9C9ABA1AEBABD9D4C0D0A4E9EB0A6ABB4864C1D000000000000000000000B130E0A0A1812162022127E8195ADDFFFFFFFFFEEB3ADA3817467759ED6E0DAB87C47211B214B7EABC7BEA7885C49547B876680006A74534E78B0CECAAF7F3A0C060A2A6296C7DDD7A474759ED6E0DAB87C4701FE215C070718107BB4E0F3CE864B3D5966727C6D462F3A5F96BBB074442E2E67BCF6FAFAE3893303144986B0B5AD76280D144F9FDCE9D4B6995B210000286FAEBFB3BBCDAC782A03043A89B0B9B8AFB3B08E4E140000265E99BCD3D0A85D1E00000000154C9CDEF4EDE9DCC3A874320E206CAFC6D6CCBFA9A977300E2267AEBFA9A7BBB8BE8F420C1057A5ACAC9DA08254160000000000000000000005070E0F19181F1D1814086E7E9FB4DEFFFFFFFFDBC3A3986F60626BA3D0DAD7B288512521274A7DA8C3B9AA725A4D4F6E807F8331787B615A81A6C6C0AD783A0E000821578DCFDCD39B776BA3D0DAD7B2885101FE225C0707182071A8E5F5D27E4B475A6A7B7A654624325EA2BCA36C3A1C356BC1F5FFFADA7C280618438AADBCB96F27021C5394DADFD1B586592302062E73B4C2B9B6BAA7782F00093D8CB5B8ADB7BDB99B521400032C6795BCD2C0A25D1E000000001451B5ECF4F0E6ECBF9A621F061F71B2C3D9CFC8A5A2722E1C2E78B1B7ABA1B6BBB98B3A091563A3B4A4A3A87D4814000000000000000003000801070E121118181D180C7F839AB2EDFFFFFFFFF5BBA29381736B84A4D9DDD1A56E4E3B25275181AFC9BB9E76564558757C77883075745A5884B7C3C5A37A3900000B285A99D0D6CBA06A84A4D9DDD1A56E4E01FE235C0707183076AEDCE7CD73434561788C83603E263768A2C3AA6B371D3267C7F4FFF8D27023001B5194BECDB5722A0D1D56ABD9E2D3AB82541500002C75AFC3BFC4CBB2762E000A4895BDB9B9BBB9A894480800023272A5AFD0C4A86822000000001C4FA7E2EFEEF1EBCC925D28082D70B0C9CBCEBBA895662D0D2A79B3CDB6A9BEB3B28938091A66ACBBB2AEA9784518000000000000000000030902040C090F1915111C147A788EC0E8FFFFFFFFE4CAA66D7E6F647CAADBE1CEAB7C4D382525437CABD0C8A3805A4D53717B777B276C72645E7FADC3C1A7742F110008365FA0DAE4CE986B7CAADBE1CEAB7C4D01FE245C0707184073BEE8EFCB81513F5C767E755732213472B2C8AC5D2E202F6BBBE7FFFFD76F2502135499BFCEAA6821081960AFDEDACFB478470B00003174B8C8C3C9C7A9711F00144894BBC5BBBAB9B38D48110001346996BECEC4A15D27000000001F4BA0EBEFF1EADCB0874819082F79B1D2DCD9C6B39C61270C3A83B7BAA9A4BEBCB289400A1874B3B8A7A4A47D4E1B00000000000000000006080B090D0D12141A131B0BA5C0D3EDFFFFFFFFFFFFEEC9B5A4878393BEE6E7DBBC8B5E3D332F5B81B9D3C8A781634F637B777A8626737262688BB8C8B9986727050316376CA5D4DBC4935693BEE6E7DBBC8B5E01FE255C070718507EABDDECD37F4B4270827F6F5438274174C1CFA960251A3068C3F9FEFFCC711E051D5C9DC3C1AB65290F2665AED5E6CFB086470C00002C77B8CAC4CDC6A15B1A001753A0B6CAB6BEB7A98A460B00023B769FB9CEBFA45D19000000001B59AFEAF4FFEADBAE7B450D08307DC0D3D1C8C5A48D4E1B103A8EBFC9B4B0BBBCBD7F3A041D78B2ADABB1B086542000000000000000000002050C02110D0B1820191F14808999ADE5FFFFFFFFE6CDB2A4846C657DB2DBDDCDB1824B312F314F86B0CAC29F7D5B53647E81707C216F76656F90B8BDB89267200A000D4266A2D3DEC2875A7DB2DBDDCDB1824B01FE265C0707186080AFCFE4CC7B4138657E8776502C223E83B8CAAE6926162A70C5EDFFFAC6622503165B9DC4C2AA6B1C0A2970B7E1EED2B371380700012F82BBC6C1C4C19D621E0412569FC2C4B4B4C5B3974C0800083C76A4B9C6B69B5D1C000000001A64BDEDEFF7E1D4A66D330E003482C3D7DBC9CDA98D5924203F84BAC0A7ADC0CBAD7723082686B7BCA8B0A88053190000000000000000000003050B0C0D101B18171810798E94B6E7FFFFFFFFE9C2A8947B656C88AFD5E2D1A975593F352B4D7DA7C6B89473605B637E7D7A881E6C74636C91C4CABDA25B280200083463A1D7D5BA815188AFD5E2D1A9755901FE275C070718707BA3D3ECCA70464970938E76552D1D4A7AC1CBA4622D21325FBCE1FFF7C1551A092E65A2CFB9A85E21103071B4D0E0D5B1702A0000032878BDC7C3C8BDA05F10011655A3C5C8BDBBC4AC8D3E0000004083ACB3BAB9935D1A010000001E5BBDE7F2F1E5DD9E662509033B85BDD0D4D9CCAE814912154C97CBCAB6B9C0B6A76F21062F89B9B8A7A3AC8B581B0000000000000000000000050D131618131416150D92928BB5FAFFFFFFFFE5BBADA58B71708FC2E2DCC7A773543C30264C89B7C1BB9D7D66615C747B71791E63695F71A0BCCEBA9355160000113976B8DBD7B97E4C8FC2E2DCC7A7735401FE285C0707188077A5DCEECA7B414D809387743F29254C89C5C5A1621C163767BAF3FFEEB34D12021D5CA9C9C6AA5F22102868BEDDE6D5B36C2E000000368CCCE0CFC7BE9A4A12001B63A3C2D4B6B8B1A57A37000007468BADB2C3B9926218000000002E60BFEDECEFE9D9A05E250003318CC9DAE0DFCCB18A3914144F9CC6C7B5BCC2BAA85C15042889BBB3A69FA98E5D1B0000000000000000000205090F0E09191F1D1E1E1382818EB7F1FFFFFFFFE2BFAD8D7F6A577FBAE3DEC29A7252383B345780AFC6C0937B6561697A7F75791B626C60749DC9E1BD92551B020005357CB9DBDCAF743F7FBAE3DEC29A725201FE295C070718907DAEE0EFC8784C558B9EA17B4F272A4083CBCEA4572B182F77C2FAFEFDC35310012576B3C7CDB15C1909307BC3E4EAD0AC6E1F00000A3D8BBFD0CCC5C59D4C0E001760A3BDC3B3A9B5A5792800000C4B96B0B2C4C0A06721040000002367B9E1EFF1E7D8994D1700053890C3DEE9DFD1AF7536061856A0C8D4BEBDC6C0A4641603358FB9AFAAA5AB9F602300000000000000000000000E13040D0A150F18161180829DC7FDFFFFFFFFF0CDAFA188726690BEDEE1C9A3754B4B333C588AB3D0BD8479615E637E7D7C7E19696A728B9DBBCFB78F53190300093B7FB6DDD5AB6C4B90BEDEE1C9A3754B01FE2A5C070718A07EA0D3E5CC7E454D8EACA57D492A1F4C95C9DA9F541E182A75CAEEFAEEA44413062474AABFC3A4591613427BBCDBECD6B86B220000063F88C5CBD5C7C6933F0400156DB4C6CBBFB1B2A1711E0000024E96ACA6B1ABA86522000000002B7DCDEEEEECE7D89A4A160301408EC3D6D6D7CEAF7D320C1554A3CAC9BFBDCDB8A25B190C448EB4AFA7A9A58B681B0000000000000000000004080A1110161216171405868B99BFF0FFFFFFFFE8C5A29A7E747A8FBCDFDCC69982536941365285B9C8AC97836D6A5F70766B741653555879A6CCC8AF8B551A00000F438FC6E5D6B3693E8FBCDFDCC699825301FE2B5C070718B07BA7CDE3C777474A84A7A77E4221274F99C6C490531E153577CDEAFDF1B2450805336FB3CBC6A74713114684C6EDE5D0BA6C160000093A90CFD6D8C9BD8E450000165AA7C0CCB9B1B9A7772500000A5894B2B3B8AFA55E1F000000002B7AD2F4EDE6E9CC85380700084496C7D9DBD9CCB17428011860B0C8D4BEBCBCBE974D1A104C96B5A9A299AC905A1C0000000000000000000005070A0A1715161916190AA09E9ECAF7FFFFFFFFF0C7BAA081697CA0CFE3E5C59B6C5650453C5790B7C3B1917B7D68678277637120705D5281ACC1BDAA823C090000124B8BC5E2D09F6F48A0CFE3E5C59B6C5601FE2C5C070718C070A6CDEEBC734B5C8FADA7803B2B254C89BDCF9E5220192C7FC8F7EDE3A04010062F71BCD0C79B4615164D96C9E5E1D2BA67190000034799CCDED3D3BC8F3500001F5EACB8C6B7AEAF9F6C20000009509BABA8B5B1A061290000000C357EC5EAF5ECDDCC89310A000D4693CADBE3D1CEAE651602215FAFCBD1CECEC5B596450D09459CBBB79EABB0AA783000000000000000000002050A090809100D16131F12828A95BEFFFFFFFFFFDED1B8A3877E7B83D2FFE3CE9F785D5A48385185B4CBBE9875655D6C837D6C680D4A5B647EABCBCAA884431C0800154D8DCCE1D6A1764183D2FFE3CE9F785D01FE2D5C070718D0789DCAEBC3744A5A9FB6AB7C3B1D285493C8C7954B1516317DCCF2EEE6943A08052977B8D9C79646170F4290D2E7E3DAAF611900000A42A3CCD5D3C1B7843300001F6EA5B9C7BEBBADA56A1F00001456A1B4A9A4AB9D6626000000093C8CD0F1EBF1E8CF7D2C0000144E9AE4E0DACBC8A9641D07296BAFCFD3CECBC8BD933F03013F93BAA6929CB1996D1F000000000000000000000A0A0806030A0F1D1F1B0C899281BBF9FFFFFFFFF0D0AD9D7D6C63A2CBE2DCBF986E59573F345A90B4C7BC8A7C7469697D70675E1256555F7BABCEC8B17F461508021C5099D0DED3A65F49A2CBE2DCBF986E5901FE2E5C070718E075A9D8F8BF774E65B2C4B68443292C5F9FCBC79A4C1F174081C1E8ECE099321515307CC1D2C3964F221F4A98D3E7E6D3B2591000000A46A5CAD6DACCBE873000001F65A7BFCDB7B8AE93611800000D5EA2B4A8ABB9A16127000000073A8AD2E7E9E4DCCF762900001B57A5D3DBE0DFD4AB5C15002475AFC7C9C9C4CABC8A4107094B96C7A68992B2A976210000000000000000000003110B0C0B10150C0C19068A8688D3FFFFFFFFFFE5C0A79D7C6B759FD0EFE1BB966A555850415D82B8BEC391726C6A657D756364114E59618AADCDB4A182440F0208175698CFE4C99B5F4A9FD0EFE1BB966A5501FE2F5C070718F071A0DDE1B56B4D6DA6C8B5773D2224549CC1CC8F4822214183C7E3EFE59B370C043175BFCECE9D44101B4D9CCDD6E1E1BC5D080000064598CADED6CDB88A2D00002B74B2BEC6B4B9B599591700001353A0B49BAAADB06928000000023E8DD9EEF2E2DCD26D210000165EA8D0E3E7DECDA35611062272B0CAD0C7D2C4B386400A0F56A5BBA78C90B09F711F00000000000000000000000B050913131C1B151905898891B8FFFFFFFFFFEFD5B5937E6F72A8CBF5DEC29A626460493D5C8CBCC2B6897B74687079786C651246465F90BDD6C3A4783B0D07141D62ACD4D8CA9E5B47A8CBF5DEC29A6264 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 61440 61440 0 01FE305C070718007CA5DFEAC2744C73B2CCC47D42292D63A8BDCA924A181D458ACCEDEBEA99340F10347BB7CBC4943E0C215DACCFE4E8DAC3651B00000B469BD2D8D7C6B57F260000276FAAC7D7B9A9AA90551400000D6195A99EAAAFA97722000000155099D4EFF1F4E1C7792300002161A5D4DBE6CFC1994909002D72B9CDCDCECECEB382340A0F549BA7A282A0B2A16C1D00000000000000000004080A0E0F0E0D181914190B958C91C5FFFFFFFFFFE6C7B99F8C6B7AB0E2F0E7C3986E5E5A483C53A0BCC6A985756F727378715A59093D405D8FBDCEC1A974340D040B236FADD4E7C2986451B0E2F0E7C3986E5E01FE315C0707181082ABDAE1B16E5574BDCAC28943323C68B4CCB88943171D4885D4E9F3E4973A0E0B3D82BED9CE8F4119235DAED1DDDDCFB35D0500001156A4D4D9D2C4B26F2000002676AECCCEB9BCAB82450200000F5C9FAC9EAFB7B26E21000000175597C9ECEEF1ECCA721A00001B68B0DDE2D8D8CB994600002A80B1C8D0D1C4C6B46E2A07145DA1C0A1849FA8A76E1700000000000000000000090304050C0B15181D1B09747D7DBBFFFFFFFFF6D6BEA88B766C83AEDAF4DFC097726762523C5093B6BAA885716E6C717B70625E0D3B3D588EBBCECEA375370D0B0B2A6DADD6E6C09E6356AEDAF4DFC097726701FE325C070718207CA0CEE5AE644E6DBAE1C57A432B3473A9BFC489451E22468FCEEFEAE78E2E040A377EBCCECA8538131E63BAD3E0E0DCBB640D00000F53A2C7CED2C5B5761C00001B71AFC0CDC1B7B58E540B0000166398A7A0A8BCAD7026000000164C9AD2EAF3EADEC56F1C00002564AFD9DDCFD0C99C460700357ABACECEC9CFCEB87328001766A6BA98819DAFA77919000000000000000000000304070E0A11171917190E889184B9FDFFFFFFF8D9C4A68E82718BB6D4E5D8C18F6A5C62533E567FB4BCAA8A736F7C747D71615C113E5A6499BED0C1A16D2D050F092B70B7D6E8C98F564CB6D4E5D8C18F6A5C01FE335C070718306EA6D4D6A363527CB3DBC37F38263476B9C8C3813A17224999C9E6E2D791300D06387DBDD3C99036102063A6D0DDD7D9B65D1200000D56A6CDCCCDBCAF6E1900002D72AFC6C1BEBCB08B440100001465A0AAA6ADB2B4722B04000013449EDCEDE7E6E1C869180000266EBBE2D9DCD4BD993D06003082C2D1CEC8C9B9A7671E000E62A6BF9F8194A1A67022000000000000010000000509060F1317101615160C7A818BC2FFFFFFFFFAD9C6A795727188B2DAE6CFB3976F655E493F5D8FBCC1AA8D8470656977715A4D07363E6298B7D1DBA46A31040B1B2B7BB4D4E6C4906057B2DAE6CFB3976F6501FE345C07071840809FDCE1A9656182CAE2CA7D3F1F427DBBD3BE83431C265394C2E3E6E1831E00023580BCD8D8823210246DB0D6E1E1D8B4560900001864A9CBCBCFC2BB6B1700002F73B5CBBEA9AFB08A430600001C6699A99CACBBB46E220000002256A3DBEBE9F1E5B7600A00042672C5E6E6DECFCC994104002E83BCC3C5CECABFAB642700135DA9B697838CAAB1731F00000000000000000000090908090B14171B1615078B8B8CC8FFFFFFFFF8DCCBBC8D7D7590C7DFE9D9BA9F75676C5A49588DB0BEA880796C686B71715B4A102935609CB8CDAC8964280915133F7CC1E5EDC3906759C7DFE9D9BA9F756701FE355C070718507298C3CB965C5576C7D8CA732F1E3677BFD3BC7831162A5E9EC9E1EBDC802100013582BDCFC679300D2D71B9D1D9E5D0BE560B00001B61AFC4D4D3BFB5712100002283AAC0C5B0ACAF803A0000001460A7ACA8ABB9B77A2E0000002059A9CFEBE6E6DDC0651300002F83BCE1DFDAD2D1972B00003B93BBC3BDC6C2BF9F611F00106DAAB5A08694A9B2711200000000000000000000040201010B0D1514201A11948FA5DDFFFFFFFFF8D8BEB4A07E8797CEEEFCD9BC97747B6D4E40588CB4BDAD87767877737A7451460328305F9AC4D9C092642B01131C4685BCD9E2C289574FCEEEFCD9BC97747B01FE365C07071860699ED6CC915F517FBEE6C8873A293B84CACBC07732172B5CABDCECE9C87E210A0F3482BCD3B67626123171B6DBE2DCD9B45F040000145DA9C3CCD2C0A8681100003C82BBC8C1BBB1A873360000002768A4AEA4B2B2B877220200001E67AAD4E3EDE6E2BB600C00042B79C3E1DBD4CEC0882A00002E85B7CAD1CBC4BB9D5B1F001A6EB2B4938891ACB47E18000000000000000000000E0805091214141B161C0C7C8695DAFFFFFFFFFAD5B4A7937E9DA0CAE0F2D8B599756E61473D4B91B4C0A18472757579806F4D4E022A346998C2CDBB92582F1405193F84C2DCDBC38D6856CAE0F2D8B599756E01FE375C0707187072A4CDC48D5B5F8ECEE0D087372C5094CFDCBB853C1A3660A2CEDCE5D8751D01093883BCD8CA7F32153478B5D7DEDCDAB6560300002269B1D7C9C7BC9D570D00003385B5BCCBB5B0977B36030000226096A5A7B8BEB273260700001F65ADDAF0EEE9DCBA530F0005357EBADFD6D1D2C47E2200093B96CAD1C4C4B5BD955114001D75B0C1B192A1A4A36C13000000000000000000000006050010110E1D1A25068A90A5E2FFFFFFFFF3D0BCAA928989A0D6E9E8D5B59675756A4B345494B9B99E7D74707F74726A51440A29366CAAD2CDC1925825020A123C8CC4DFDBBA8C5A5DD6E9E8D5B596757501FE385C07071880699BCCC8815D5D91E1F1D573362D4990CDD6C87C301E2C5AAAD5E0D9C9751E0A053F90C2C9BB6D2918387DC5DFE4DDCEB4560C0000236AA4BCCDC3C8AD610D0001478FC0BCC6B5B1A2742A000000235AA4B7B2C4B1B06B24000002195CADDCF1E5DBD6BC5B0B000B428FC7DCDCD7D0BD7E2E00024B93B6C1B9BCBDBB954D2006257EB3BFABA2A1A8A76E1100000000000000000000000304060B15111515170F7B8CA3D4FFFFFFFFE7CDB3AA908B87A3D3E0E5DABD9A777166503A578DBBB69E7E75717A716A5D4C44092D3866A5C8D3B9985E2605040F3A95CCE1DCBC925A45D3E0E5DABD9A777101FE395C070718907799BBBA81515592D7ECCF7A30204DA2D4E9CB7C36152867A6D9DCE5CF741E020E3C86C5DDBA7727133186C0DCD7D7CDAA4E0000002475A8CBC6CFC3A8681600003C8FB3B7BAAFAE9C71240000002159A3B2ABB5CAA86B1C0000032A76C1D9E4E0E3CEAB520500093D93CFE2DFD9D6C17E2400094F96C0CACBC6C3B8884611011E78B1B4ACA499A5A96C0E0000000000000000000000080201080A12110D110A8189A6DCFFFFFFFFF7C6B4AB968798ADDCEDE9DCB7A48277664D2E4486BAB9A282717278766F6E4B20001B286AA7C8D2BE8F5731040F1D479AD1D8D9B8875448DCEDE9DCB7A4827701FE3A5C070718A0779DCCCA8D5D73ABE2F6D9893F314A99DDEBC06F23163072B4D9EAE3C96812000D3E97C0D3BC6629143A7CC3D7E1E0C8A84E0A00002274B9C7C4C1C1A45712040A4188BEC3BCB9AF9D6B1E0000002064A7B8AEBEB9AC5B1702000B3876B0DFEBE5E0D2AC4B0800125098C3D9D3CFCDC07D1D00004099C5D3C7CDCCC3904B2105206FABBAADAD99A5A2600900000000000000000000000001060D0A10141B1608868AA3E9FFFFFFFFEEB3B19D908897B9E2E6F0D9C0A1847E64452D4784B3BA9F797570766D74563B340E1C2E6DABD7D0A884522200121C55A3CAE3D1BC8C564FE2E6F0D9C0A1847E01FE3B5C070718B0729CC5C382616099DEF3DB8043314CA8DBCFBC742A122C71B6DCE4E1C9771C000E3C8BC0D6B56028194788BBD3E1D1BDA045040000308BB7BFCBCCC39E4F0A00004B94B8B8BEC1AE9A601D0000002364A7BBB2CECBB6672601000B2D79BDE4EBDCD7D2A34D06001659B1D3D9D6CDC5B566120004539EBAC8BFB8B8B288501F022675A0BAB8AA97A2975E040000000000000000000000000207060514181517098691AFE9FFFFFFFFE5C4B79E9396A0BCD7EBE8CEB69D8A76563E395395AAB7967C68736C787060402C0018316AB2DDCBAA855627100C1357ABD4DDE1BA784D4BD7EBE8CEB69D8A7601FE3C5C070718C07C9DC3B37E5E6C9CE5EBD87B342D5EA5E4E9C86F31223D71B0D9E5E7C36A1D00114A90BCC6B46A271C4285CCDAD7D9BF8B3C0000002C79B7C5CDC6CD9D510200105099C0B9B9BAB19857180000002A6CA2B9C0D0CDA96321000007277CC2DFDFE5DDD4A9480000206AB1CFD8CED8D2BB71140004549BB6BFBCC1C2C18A5020062981ABB9BAAE9EA89F5C0D0000000000000000000000020202060D1B12160F008089AFF4FFFFFFFFE9B6B19E938F94C5E6F4DEC4AA9B8E7962473A5A84ABB4937E6F62636F7060453600202F75B6CFCBAF854F1C000D1456AFE4E5CCA8774D45E6F4DEC4AA9B8E7901FE3D5C070718D06E93BDAD766170AFE3FFD07D443A5AA9E0E8C5722C1D3783BBD0E0DFBA6118061C5D9BC5C8AF571F11408CBBD5D5CBB989330100004086BAC1C6CABFA24F0800145498BCC2AFB6AA975A13000000226EA6C0BCC2C3A559120000083780C6E2E2E0E2D4A64602002167B7D2DBD0CFCEBB631200104D9DBBBCB5C0BCBB8D582905307CB3C0B8B1A9A89354000000000000000000000100000106090C13131417038788AAFFFFFFFFFFE4C6B49B8C9E96C3E7EEE4C4AC9D927D633E395292B3B490666B706E7C6F5841230E1D3B78B1CEC29C7A461404000B59B0DDECD0A7785046E7EEE4C4AC9D927D01FE3E5C070718E0709CBCAD73556CACEDEECD7C363369B6EAF8C26C341E3D8AD0DADADEC15F11001651A2CED5B65B1F1E4B9BCEDBD1CCB2863B0300083E88C3BDBABEB79643080019569CB7A9B2B7A99B4E100000002B6DB3D0CCCAC7AB56130000153C81C0D8EEDBD6CCA03F00001D76C3D9DDDDCEC5B85A0200035DA8C5C1ADBABEB17D4E1A062D79ADC5B8B4A8AC964906000000000000000000000000000008080C15151E0A8D8DAFFCFFFFFFFFE4B5A6A19598A6CDE6EBE6BBA99F9B7D5D3A2C488EA7B991775E517872695838230E21377DBDD5C49269431D02080F57A6D7EBE1A96E4639E6EBE6BBA99F9B7D01FE3F5C070718F07797BFB77F6177B1F2FBD17A403C5BB6E7ECBE653416418AB5D9E3DBBE601004115391BACDA55C1D244F9BC4D7D6C5AD833203000A509FBEC1C8CCC18A43060015589DC1A9B1BDB6954D0B0000022E70AAC0CDD0C3A35513000114378AC1D2ECE6D8CB983500002C77BCD5D4D6DDCEB25306000A63A7C9BCAAB8ACB1835C25113480A9B2B7ACA59F964C000000000000000000000000000002050E0A17151506798BB7EFFFFFFFF6CDB6A1857E97A9C1DDD8D5C6B6A593766141204E8BB7AA92715A5E6E706453322000214886BEC8BA8F64381E0806135FAEDCE9D3A3694140DDD8D5C6B6A5937601FE405C070718007493A89A715872B6E4F6CA683B3E66BEE7E7B95A271C3F8DCEE2DED9C0731C131C599DC8D0AF591D18559ACBD8DBCCAB6F3101001047A0BCB6BEC0BF8B3900001666ACBCAFAEB0A3904C080000073776ABC3C9D3BF944D11000116408CC7DEE9E0DDC48C2C05002D86C2D6CED1D8CAB15C0800095CA5BDB5AABABBB8865E2C133081AEB0BABEACA99740000000000000000000000000010A000D06120E120F0A7F8CBFF2FFFFFFF6C4AB97848A93AEC5E2E6D6C5B7A88F82714E2E4F8AB4AE9063555D68786650301E0A1B3685BAD9C6956B3C1C00001B5EB8D9E2CDA26A4431E2E6D6C5B7A88F8201FE415C07071810628C9D8967567CB1EDFAC76D3F3C68B2EFF8BC5C221B4B8BD5DCDCDBBA5E100C20579EBDCAAA58202F5D9AC3D2C7BFA3722B00001056A7C2BEC6CBBB812D0000225FA0C8AAAAB2A58D450F000005327BB2CDCFD2C4A44A090000164786D1DFE2E3D9C9933A00043982C1D9DDD8CDC2AA500A00125BA7C0C0B7C6C5B5815A26082C88B0B7B0ADA99B80380000000000000800000000000004050D0C151111110A808FB3F7FFFFFFF6CCB08B7B819AB1C9D4DBD5B9B19D8B7C6940314C90A7A0825C55536F6A584E321E141D3D92CCD4CB7C5F371400001766AFE4E4D3A4694135D4DBD5B9B19D8B7C01FE425C070718207688A88D696580C4FBFBC871374071C0F3F3B86832225792DBE1E9DEBF61120C1F5EABC5D2AB5314245B9CD0D6CFBEA6651D00001956ADCBB8C6C9B98530000016639FCAAAA9AC9F8F41000000093377A5CCDCCFBD9753140000203C8CC5E7ECE3DCC6872E020D3F94C9D7E1D8C7C2A34B00001868A3C3B8B4C3B5B380632F183D7EA6B7B2ADA7A08A3F0000000000110A0000000000000001000A0F160C0D008493B6EEFFFFFFE3B39F8D87899BBED5DEDDD4B2A89D88705B391F4486AAA0835E54546A695D492B1A191C4895C0CFC1895B331A0000156EBDD7E9CD9C5F3C38DEDDD4B2A89D887001FE435C070718307C8EB2916D678BCEF0FACB6D43446EBBF8FCC4673B2D4786C6D7DFE1C462180D205DA9C4C6A54B213363A0CCD3D6BF9E691D00001C63B5D3BDC4BDAD6A2200002670A9B6A6A3B4A78341060000124170ABD4DEDAB38C460500091D4889BFD7EBEAD7C489240004499DD0DCD9D2CACAA13D00001968ACC2B6A8B3C6B587693012418AA9B9B8B7AAA07A34000000000B0E000000000000000208060A0D120B17017284ABE6FFFFF5DBB19884807A9CB9CDE2D0CBB5ABA28D77663E1E4E82A2A571504052666C593D24161C1D5291BCC9B38C552E160509257BC8EBE3D09B612F2CE2D0CBB5ABA28D7701FE445C070718406A819085687194D8F5FFC97646426FC3F4F7C1622E274B90D1E4DEE0C25E160B2166A3C0CBAB54212A67A2CCD2D7C09E56100000186CB4CDCCC4CBBA762000001E70ACB99DA4A6A9803B020000154784B8DCDDC9B4853A0C000A194B8BC5D5DFECDCC57A210008499AD3DEDAD2CCBB983600001F74B1C3B8ABB7BEB38866391B3A85ADB9B9B1A9A28026000000000608000000000000000000080F0A0B1418068F89B4E6FFFFF0D6B696817F7F95B8D0D5D1C8AFA5A38D745C3120417DAD9D7C4D434A636A4E23130E24244AA7CBCDBF8B5336270D052973CAE3E3CA97541F2AD5D1C8AFA5A38D7401FE455C070718506F8299866A6E92C9FAFFBB6F464772BFF5FDD06F2F2243A0C9DCDFE0B85813143567AFC9D1A2501B356EAFC0CAD0B397530900002373B6D0D0C8C8B3681D00002B79B6C9A09FAEAE8A34000000184E8AADD5D8C1A97F360F001220538CCAD0DEE1CFBB741600094CA3C9E2DED2CCD0A23600001E71A5C2BFB1B2C0AE816D441D4A8EB2BCB4B1A6976B19000000000E0A02000002000000000004020710100F038693BBE5F9FFFFD2B58A7B6E658FB8CBD6D6D2ABA5A3917E592D1D4989A196754E344563593D231518283662A6CECEB485583F210F0A1B75C4EAE3C1955B2C28D6D6D2ABA5A3917E01FE465C070718607693968560719DDBF7ECBC70435088D3F7F7CF6B2F2D529EE0E1ECE9C2601611316FA8C7D4A94820287CB0C0D1C1B5954E1300002574BFDAD3D0C89F5D1300002E76B3C1A1A7ACA275320000001C478CC1DBE2D2AA732E00000B28508FC5DDE7E5D8B06D15000F55A2D4E2DED0CBC68E3B01002175A8C0BFA9B7BBAE8168351C4798B1B3BEBBA89D6C1F000000050E01070000000000000004020C120F0C1002818AAFEEFFFFEBD3B4907A6D7093B6D3DCD3C4AAA49F8B74552E16488FA59968463D4D62633D000C11313E6AB5D2CEA77F5A371102062E8BC7E9E0C387522A25DCD3C4AAA49F8B7401FE475C0707187077818E856B77A6E2FFFEB668495485CFF7FFBC6C3D35569AD3E1E1E3B95415183367A6C6D09F40203375B0C8D1BEB796510C00002B79C2DBD0D1C39D5F0B00012779ADC1ACA9ADA27E350100051D588BBBD6CFC5AD6D2C0402112A5698C7D5E4D4C9B0701B001357A6CED9D6DFCBBF902F00002579B2CFC3ADC4B9AA866F391F4390A9B6BCB7A89E681700000009190B01000000000000020300030C111416008B85B5E6FFF5E8C79E8373697191AFCED7D1C1AEA8A28C78562D205092A189663B322E57613D1C0B15384A70B2CDCFB57D532F25080B267ECDE8D2BA82522623D7D1C1AEA8A28C7801FE485C070718806E7881746671A4E4FFF5B06B464B80D3FFF4BC5D322B5AA0DFEBE9E5B6531516366FACC8D0AC52203E75B2D2CFB8B494470A00043784CAD9D1CFB890440B00003473BEC5A3A5A19A73290400041E508EC5DADDC89E672602040C245288C2DEE8DED0AD6313001661B1DED8D7D2D0BC832200001C83B5C8B4B1B9BDA78579441E4F8AABB5BEB5AA965E140000000C110E090000000000000003060C0B1A1012029193B4E6F4F8E5C3A48077696893BDC5CEC6BBA1869C756B5036275196A69762393238535D2E1513152D4585BED4C6A77843261F0C062A86CEE5E1BB8C491F21CEC6BBA1869C756B01FE495C07071890767D7F787081B5E9FFFFB267485E8DDFFFFFCC61343057A1D2E8EBE7BA5E211C3D6AAECAC8A04E244582ACC7CBB7B696430500043F94C3DECED7B086410100073681B4C79CA4AB97742400000D3162A3C8E2DCC299521D00010F346194C0DAE3E0C7A06914000B66B4D5E1D8D2CBB6822300002B89ADCFC6B9B7C0A6867F3A15509BB1B9B9AF9F93570C000007171612000000000000000000000414121009008CA1C2EFFFFDEAC098746C646D9FACD6C9D5C2A7A09F9074563A28538AA8956C3F2C3C53553526121A3D5889C7DDCCA775412B11070B3391D4E5D2B178381D0AC9D5C2A7A09F907401FE4A5C070718A0727B77787082B1EBFFF2AA654C5B94DDFFFFC55F2B2F5C9FD5F1E7ECB8510F204682B5C7D2A44A204085AEBFC1B6B4A0480400074793C9D6D7D3AC8239080004317CC6D1B4A8A29A641B0000092D669ECFE3D7BE83552800000D345C9BD0D6DCE1C69B590C00186FB6DEE2DCCACBB87E2B00002A7EAFC3C4B3B3AF9C817E452F5D98AAB1AEB2AC8E520800000720261A090000000000000000050901080716088DA0C3EEFAFEE5B593726366679AC1D4D9CEC59EA59B8D6C51361F52979F84663929364F5E2B120D193C5492C2D4C49E76462A230A113B92D4E0C9AD79442119D9CEC59EA59B8D6C01FE4B5C070718B071717A6A758BC0F3FFECA764465E9DE1FFFFBE5E2B2F5CACDAECECE5A4511B22468BBAC6CCA949213F80B8C3C0B1AB864300000B4792CADDD5C2AB8236020000347DBED1B3A2A1895B2302001B3D78A4C3D8D5B5935C1C00001738568AC6D5DDDFC2944F1203146CB7E2EDE9D6CDB57A2200003895C6C4B5BABCB097837639225396ADABBBB2A58D450200000D242A1F090000000000000000030D14100A0C097DA0C6EBEEE8CFB08779665F7899B7CFCFC8B9A09199856A4B312A5895AD8F5E2F32344B57320A061F315E95C6D6C5A66C41241302064092D3DFD1B178471F21CFC8B9A09199856A01FE4C5C070718C072777A69778CC1F1FFF2AB5D4E6599E0FFFFC262363561A1DEE3F1EEAE4D0B204979B0CAC8A043294A86ABBFCABAB0914200000953A5CEE4D0C0A1742C0000104A90B6CFB59F9B85562400001A4076B2CAD2CCB8935320020125416198C3DCDED4C596510A00166ABAE0E0E2D5D4B7722100003984ACD0B9BBBEA79D8F7F41286095A4AFBEACA28E4C0000000C2B2B1D03000000000000000000050E0C0505008CA5CDECFFE6D5B88E795F5C739CB8D2DBD2C0A2A29C9874553A285F96A386583430314C5637111B2A426C9FCBCBB796603A2112070B258DD2DCCAAE763D1822DBD2C0A2A29C987401FE4D5C070718D070726A696B93C3F5FFEF9C64516595E6FFFFC071383863A8E0F3F4E1A14814244688BFC7CF9345325088ABB5B8B7BA84350000115BA7D1E4CEC4A376270000114A82B9D1C0A6978453180001235484B9C4D4C6AC803C090005294A6899BEDBDAD2B7854808001E76B6DCE9ECDCCFB56D1700093E82B7C9B6B6B4AD9B947F3D276295A3B7B8B3A88D430200002236332A0900000000000000000000000C0D110080A2C9F3F4F6D1AA8663544D6C97BDD1D4C8B89B9A9B966C4832316798A8875B3C303348553C1722314774A3C2C6BD91694C2D09000C328CCCCCC29D693E1D1DD4C8B89B9A9B966C01FE4E5C070718E06F767D758197CBFFFFE29F6A486D9CE8FFFFC56137345EA3EDF7FADFA3461C244B88BDD5DE9D4E244D8DB3BAC0AEB48A3400000F57A8DBDED9BB94661F00000F498BB5C8BDA79C814E11000225548DB8D1D5C1AF82440F001021426FA2C3CED3D2BE853D01001F78C7ECEEE0DACFAB691A0000388CC1C6BFB4B0AC9B8E753D25639CB2B3B0B2A985360000001A3E3924020000000000000000000B0909020C0291B1D6F0FFF3D6B08C69605D76A9CDE0E6CAB89DA09B8C674C302B619CA08C65403637464C2E202A3F417EA7C1C6B38F68361D0C0000338AD4DEC29969401E17E6CAB89DA09B8C6701FE4F5C070718F069706667749CD0F7FFDA9B5D5372ABF1FFFFCC6E3B3560A8E7EEF2DE974419325289BCD1CD923E1D4D88A9AFACABAF943A0000195FB1DAE5DAC09054150000174E9BC4D6C9AB92764609000C296496BED8D9C3BB793E07000D2B55739AC4D4D2CCAE71300000267DC2E8E3E4CCC7AB71170009469AC5CAC2B3B59F918F863D316EA2AEAAB1A5AA87370000002E4737180B0000000000000000000010100A100290A8DCF7F8E9DEAC8E73595B7DA8C4DDD1CAAF9CA2AA9C73552C286A9DB7895C34381F424F42282A433E80B9D3CBB58C5C39180E03083491CED9C1925C341C1AD1CAAF9CA2AA9C7301FE505C070718006E6B71828AA8D1FFFFE0965C5173AFEEFFFFBC613C3863AEE7FFFEDA8D421C2C6093B9CBC8933D224895B0BBAFA5B5863000001E6BBCD4DACFB988512100001C4D93C1D3C4AC9C794B0F00042B6A8BBFDEE1BE9A762F06000F275380AAC9D5D2C5B27E320000217CC9E0EADCCABDB0621C00084395C1C9C2B9BBAB999872382D6B9CAAB6B1A59F7D26000000314E45291000000000000000000000050E1104008AACD9F4FFE4C8AD896C525478A7CFDEE3C8B190949C9068514334649AAD8F5D3433324B543E27354F467BB8D2CEAB86502410070005378FC8D3B7A069352315E3C8B190949C906801FE515C07071810767A7B758BADE1FFFFE0945D5877AFF5FFFFBB61353368B4EBF9FDE6993D18316A99BCCCC68E37245793C1C5B4A9AD8D2B00002775BED5E4DBB98A4B0A000022529FD4D5C2A385663903000E376BA7CDDADFC1A3753206000B375A74A5C9CECFCAB4743207002D79C6E1E7E1D9CDA76117000D4698B9C1C4BEBDB09D8F773D356A9BA49EAFAFA780260000003A533D1E0200000000000000000002050400100389ACCAE7F6E8CDA182604E4573ABC1CAD0BEA88E93A68967503A3972A8B09B623A3C354D524A273A504279ACCBBFA38353251E08000A3996D2D0B4885A321B11D0BEA88E93A6896701FE525C070718207274728391BBD9FFFFD08A635A79B1FFFFFFBA582F3360A6E8EDF4D48C3C20386C9FC7CBC4893E275696B2AEA7A8AC8C3100002780CBE0E4D7BA7E380700002A5C9CCEDDC7A57F613B0A00193C75ABC4D1D3B1A072330D01113A5D82ABC8D4DACEA6712600002572C1E5E0E4D5D6BA5E2400124B94BBCBC8B9BBA48A8A6D37317497AFA7B6B1A3712600000D4760432006000000000000000000060607040A0091B1DCFFFAE2CBA380665B5C75ABD6DDDEC6AE988A97906E49434075A2A58D5F3334304F5644374560508AB0C9C69A754A2A130300063299D1D2AF8C50241A0CDEC6AE988A97906E01FE535C0707183071706B7A8BAED6FDFFD0825F4871B4F9FFFFB15A343868B5E8FDF9D77E32214273A2C3C6BE8535254D97AFB4A6A7B384330001318EC7D8E7DFBE7A3A0A00012266A7CCD7CCA98762360100165385ABD2DAE0B5A0672C0B001035627CABCACEC8C1A16A2A0000297BC3DFE8DFD9C8B06117000F4F94C0C6C9B5B59D7F8F7A34386C9EA3A7A3A3A26E17000018537051250100000000000000000003050B0F0D009ECBF4FFFFF3D2AC91715D5F7BABD7DCDCC6A29191988B714338488BABAE9A6C403932425B503A4F73418ABBC2B89D72451F0F0F010F3593C7D5A67E4E33201EDCC6A29191988B7101FE545C070718407073707791AFDAFFFFD1854E4D76C2FEFFFFBC572F396CAEE4EBEDCB722A1D4576A7C9CCC0803A2F5297B4A8A2A4A983290002398DC2E0E4E1BE7631000000296CAACEE4D6AC86592F0100195C91B6CED9CFC1A46B2700000C376A89B0C8C8C6BDA360280000227EC4E0E5E1DBBE9A5A1000084CA5C0C3C2BBB8928C8B683A3471A2A6B2ADA8A37119000023547545250400000000000000000000000906050092BBEDFFFFF3D2A9856C5F5E8AB4D3E5D7BDA9989DA294714E343E82A8B1986A3A393B5362504651704292B3C9B08F6A411B070300103C99CBD4A986452D100AD7BDA9989DA2947101FE555C070718507775798EA3C5E6FFFFC47F555172C3FEFFFFBC60394472C2F3FDEFD37A37204A79A3C3C1AF77352C649EB6AEA8A5BA8A3700023A94CFE3E7D6B56B250000043169A9CBDAD6AD78592D00021C5A8CC7D2D5CEB49E642C0000123B6F92ADBDD6D6C299541300002D7BC5DFE9ECD9C9A66016000A4A9ABECED0C5B494858669303878A4A6ACB5AFA365180000206176511E0800000000000000000000040D0E09009AD9FFFFFFF8E5AB8474636B7AB6D5E8DDD1B19B9EA091755241518EB5B19364453C3A4959574C607A3B88C1C7B293623A18190500033DA0D2C7A58044201812DDD1B19B9EA0917501FE565C070718607D7E72889EC9E3FFFFC57D5B5B82CEFFFFFFAA5030457BC2EBF5EBC37537275189ACBEBAAF7133295991B4B4A4A4AF8130050E4C9DD9E1E6E0B36D20000006306D9FC0D9D5AD714D2202072A679CC3D4D8D6AC94591F030B234A7693ABC3D6CAAF8F571A00002C84CBECE6DECFC29C5D11000E4B9EC4BECDC0B3907786733C45759DA8ACADAD996C1700001F627C5B290900000000000000000000030100040091C3EFFCFFF1DBAB846B5F637DBED9E7D9C0A48E8E9B85725B445691AEAE945E40373D49625C5256713891BAC3AF8D692B10090100093698D0CD9D76482D141AD9C0A48E8E9B857201FE575C0707187074767583ADD5E7F5FEB97F586183CAFFFFFBAC52344C7DBDE8EDE3BD6F2F254A8EB5BFBDAC70312C619EB0AC9F9BAB7B340202449DCCDEECDEB6621800000C397AAFC8D9CFAB73491E07022C6DA5C8D2D0C5BCA06A2000001D4A7D96B8C9CBC1AF954B0E00002E79C5DFE5E5DDCB9B581C01185AA6BAC8BCBBB2826D836D39447799ADAFB1B6AD6B190000206A8B5A2B110000000000000000000007010601039BCFF5FFFFF5CFAA8E665A6D9DB6D9E8E0CAB3959FA591775540588CB4B4956A4A3E30486360576D7C3F9BC2CCB08D612C0C040000063D97C0C6B2763E241B1EE0CAB3959FA5917701FE585C070718807A6F717DACCEEDF9FABC735D5B7FCEFFFFFFAC5938476FB3E1EBEABF672F285C8AB9C3B9AB64332F6796ADA5999C9E6828030D449CDAE4E1DBB9681E0000154376AEC9D0CEAA793E1501103470ADCEE3E1C9B29E581F01001D548091BACBD0C4B18B4D090000287FC9E1EAE1D8CE9D661A0413519FC5C4BEBEB77F727C5D2B41849CA1ABA7AEA65B11000031788A5A2A02000000000000000000020300070A009BD6FFFFFFF0DEB78E6A62648FBBE2E5E3C9B6A298988A715A496699BDB18F6850372D4178705D6A8D3497B7BCA1815F25090A00000B4EA9CBBC9E6C381B1E1AE3C9B6A298988A7101FE595C070718907A7F7D98B5DBFBFFFFB37958608AD8FFFFFFA9572C3576BAECF5ECBA602E315D98B8BBB59C5D2B3765A5BAA29C9DAA762400134FABDBE4EBDDAC59180000144176B4CCD8CDAA6E451E01083D77AACFDBD0CFB39A68190005235592A1ACC3C5CFAF8A4C010000348CBFD9E2E3DDC7975B1E091C4E9DBACECBBEA66D637461384E80A2B3AFBBA49C4F0C0000327291622E080000000000000000000000040709009CDFFFFFFFF5D9B08D754B508FEEE6E5DEC2AF9B929A8B785C4862A1C0BF9D7A5731314E5F635D728B2996BBC3A278532B090400000D48A3C69E765E42262A24DEC2AF9B929A8B7801FE5A5C070718A06F6F738AAFDAF3F5F0AD765F5F8CD0FFFFFFAE4F36467CC3ECECE4AC61272E5F99BDC0B29B5C242A5F9CA4A3A4A6A272250D1751AFE4F0E7DCB05B0E00001D4482A8CCD1CDAE753F15000F3989BFD8DCDBD2B8996218000127628EA5B6BBBDB5B17E450A00002E7EBEE6E2DBDAC9A763220A1A5AA6B7C6BFB9A56E646F522D4A8DB0B8AFAEA1954300000033808F5A2602000000000000000000000003030400AAE1FFFFFFFCE4B0866D627097C8ECE6D5C5AB8F949B827A5C5869A6BFB39C6B431D3453686B6A7B862EA3C5C2A8864D25000500001250A2CCC59B6A3D2A2826D5C5AB8F949B827A01FE5B5C070718B07B757D94B9EAF5FEFFB87A59548ADAFFFFFAA454364E82C6E7EAE2AE5B2D28609FCCC8AB96572B27679DAD9E979E9F65240F0F5CA6DCEEEAD5AA5A1B000022498ABAC6D9CEB27F361100154488C9D9DAD3C8B19C561E00012A5D94A3B4B8B9B79B76330000003687C2D5E5DAD2C6A4662510225CA1BEC4B8B7A86F617349305C8DAAA7ADA5A98F5202000146848B55220700000000000000000000080E010C0091E4FFFFFFE6E4C7835E4E6A9ED0E0F4EFBEB19B9A9D8D785D506EB0C3BC9D64443A3751666B6E80A12898BDC4AC75451D000000000D5AACC9B795612F212521EFBEB19B9A9D8D7801FE5C5C070718C07A7A789BC1EFFFFDF4A570595A8CE0FFFFFCA254404E84CAE5F0E1A95D242E70B1CEC29D7D48212B62A1A3948A979C6C22081962B4D3E2DFD4B062170002254E8DBFD3DED2A978351402124887B1D1CFCCC1B293501D0009295F96A7B4C0BAB5A07A310000003A82C9E3DBD9D4C1A161190E276CA3C4C8C2C29860556754345C91B2B0ACAAB09F4C00000341878D6632000000000000000000000000060001009CDAFFFFFFF1D7B2826F556C9FCEE6ECE4C9A794958784735E616F9DC0B6945E4734354F706B788BA4299FBFC79F724922000000000A54ADCAB9915C35262423E4C9A7949587847301FE5D5C070718D0685D6E95C5FBFBFFE7A0654A5598DDFFFFF69A50344B7DBEE4E8E8A151272F76AAC9C4A78142252F5D9EA5978C9697641D092162B5E4E1E7D7A95A1100002B5A88BACAD7D6B077361A00125190C6D4DBD6CAAC92571B00002166959DB2B6BDB79D6C250000063A90BCD9E1E4CEBC9B6A27132765A6BDBDC4B5995D5964513A5B97AAACB4AEA1893F000006528E915E300C000000000000000006000601010300A9F5FFFFFFEDCDA7876B5F67A2CAE8ECDBC5AF938F86896F656B79A9C3B89C6B412E466168696888A0228DBEBEA4724116070000001158B3D3BE8A593A233224DBC5AF938F86896F01FE5E5C070718E0666E789ADBFFFFFFF099674E5B84D6FFFFF191443A5294C7F1EED8914F2F3B77B1D9CEA6713A17285E949A938D9C905C21052964B4DFE0DAD3B45611000D36558BBAD1DDC8AF76290D0619579DC4D6DBCFC9BB91501A0008306A9EAAA9C1BEB19964260000053A85C4DDE6E2CFB5976926173465A1BFC2BEB39A635C63402D6697B2B5B2B2A28C3B00000657949E703207000000000000000000000400010100A7EEFFFFFFF9D4AE987D6675A0D3EEF2E9C9A396878A887C6B6783AAC0B7996540313B58757D79979D2096C5C4965C3100000004001B62BAD8B7995A33292F2EE9C9A396878A887C01FE5F5C070718F07B6B769CD2FFFFFEE7A6614C5D9EE0FFFFF19A4B315590CFE6DFD9955832397DB1CAC7A673371D2C699B998981918D58250F2275BCE2E8E2C8A04C1000163C6F8FB8CCD2CEAF813404002161A9C9CFCCD2CBB497511200003175A0A7ADBBBFAE8E5918000000388ABDD9DCDECAC59E6D3318366C9EC2C3C7B9905A585D3D366698ABAAA5B4B38D420000025990A66E290A000000000000000000000301060A02AEF8FFFFFFFBD9B69071697EA6D4E3F3D4BFAC9D928E816960638DAFCCB194723E373A64827C7D92A01F9DC8C39C653E12000600001263ABBAB6A2602E1C3531D4BFAC9D928E816901FE605C07071800787679A3E1FFFFFFE8A462505F8ED9FFFFF39A483D558DD4DDE0D99152273F87C3DACC9B6D34152E5C838E7F8E9F9050140A2674BBEAE9DDD4A64B030012477495B9CFE3D4BB7E300F072161ABCAD2CEC6BDAE8F4A1900093574A2A7B5B6B5AC9862220000003F8CC6E3E6DBC8BAA279391C356AA6C2C0AEA98D5657614138689BB4BEAEACA7863900000D5AA0A16E2D03000000000000000000000004020100A1F1FFFFFFEFD0B190756D79AED9FBF3DFC5AC8786888E775D728BB7C2B092693D2D3753767E869AA6299CB9BC905A390B000000001F6CB8CAB37A60342E3B2EDFC5AC8786888E7701FE615C07071810787C7EAAE6FFFFFFE19F624E6197DDFFFFEB8B46445694D5E5EED28C49233F84C2DBD1A96321142E6D93947D8091814D130C2C73BCE9E4E1D0A14A130516527B93AFC9CDC3B37E3706092A6EABC9E2CECAC2A48E4D16070B3E7496A3B2B6B3BA9862160000004189BCD9DEDFC7B9A4793625427BA5B5B7B8AF805850623B3C6C95B4B5B4A6A97F31000013618F9D703008000000000000000000000100000500B4F5FFFFFFFCD0AD937A5F81ACDCFBF1DFB79C968A796A645D7090B6C5C3856139243D62839393A6BC2E9EC5B78A64310A000000002C7BC4D1B6804F302E3428DFB79C968A796A6401FE625C07071820717082ADFBFFFFFFDB945648599EE4FFFFEB8B403857A6E4F3E5D88443224390D5E0D9B16B230C1E598479728D947B44190A2F70BFDADEDDCEAD460A00185682A2AFC7D0C8B987300712386AB3CED8CCBDBBA58F521E0417497490A1AAB3BAAE8552130000064A98C4DCDED6CCB49D7640314C7FAFBEC2B4B48F4E4A4F31376CA4ABB3B3A49C81290000186898A1723809000000000000000000000000000700AFF1FFFFFFF4D2AB94736274AFE6F4E9D2AFA3948B7C6F696C7699BBC6C1A3741E1F185D878E8C9BB42E98C5B8874C1700000000022F84BFCAAD7151372D3F34D2AFA3948B7C6F6901FE635C07071830747182B6F4FFFFFFE78C51455E9BDEFFFFE6893F3653A5CDD0D8D18E47284796CBD7CDB166180B275D847D72878F7A40191B3477C0E1E1E1CA9E480A032A697F9EB8CAC8C3B67F37070A3C76AECDD0C8BBB5AF913C1502185185A4A1A4ADBAAB8E4B0B0000014A9BBDCCDCD8BDABA2783B335081B1BFC0AEA17F4A4A4B363974A4B8B1B4B5AE7C2C00000F5F96A27B400D000000000000000000000004080600ADF2FFFFFFDBBB977F685D74ACD3F7E8CCB79887817B6F6E6F7488B5C8B4986F352B3961B8A39AA3BB36A3B9AB844A1B00000000023187C1CEA46A3E2B2F3C2FCCB79887817B6F6E01FE645C07071840797D88B8FBFFFFFFE98F5B495D9EE8FFFFE28C4D3868A6DCDFE2CF77422750A4CFDCD4B05917021F5D747A79888C7A3E180E2C73C6E9EAE4D191440F0B386E809EBBC6C9C5AF84300D104381B3C9D5C6B2B7A58B4013001B4D839F9F9A9FB5AA8C490A00000D4F9EC9D0E4E0BDA29B773F355A8BB0BAC0B9A873454C4E3141809EB1BAB2A6A17121000023719FA4833D1200000000000000000000010105080096DDFFFFEACEB38F72585E699AD6EAE5C8A39282766D6962667898BDC4AF955F2C21365E8B8E90A9B63598B8AA753E1100000000052D8CC7CFAA75482B263F3BC8A39282766D696201FE655C070718507B858FC1FFFFFFFFED8F5A5364A4F6FFFFE9874C426AA7CFD3D7C679342B51A5D1D9DBAF601E0A234B71757589836B3C11113C85C2E9EEEBCC9439080930708EA3A7C2C7C0BA82340E1A4384BDCDD9CFBDB9AE893F120812448DA4939AA2A1B2924F1400000550A4C6CDDDD0B3A6A07A3C3D5E88B1BBB6BA9E72404F462F4173A3B2C3BBAC9D6E1D0000146FAFAE914C14000000000000000000000000000700A8E5F9FFE4C2AE987B64536EB0DCECDEBFA189877169595A617499BAC5B299643A28325A8BA9B6B6B53BA2BA9F763A0C00000000063596C8D1A4623C2129423BBFA189877169595A01FE665C07071860737686AEF2FFFFFFDC855A47639FE3FFFFED81413E67A5D6E5DDBE75321E59ACD4DFDFB35C0A031949697069828E642F1014357FC5DEE3DFCF8D3B0905307D9FA3B5B9C4CCB87F380C175396B8CBD0D1BAB9AB893D14031C5584A6A39FA4A6AD8B460000000C4197BECFD5C9A69C9B773E457097B2B3BBAEA175454F482A4B759DAAB0AEB2A36D1E00001F71A0B3944B1C000000000000000000000000000400A7DBFAFBE1BCA28A6D575669A5D0E4E7C19C8A6C72715A687186A5BBC2B4985F2F212E6090A2B9BCC24AA2B4935F2A0400000000003999C8CB9D614735304E38C19C8A6C72715A6801FE675C07071870757C88B8FFFFFFFFE689534A60A5E9FFFFE087483767ACD4CBDAD278352352AEE2ECE1AF5408001A4E6478787D845C3014113D8BBEDCDBDACA8F461B174180A8ABAFB6B1B6B0832F121D639DBBCCD2C2AEB1A1843E1606205E93A29795A2A5A58145020000105798BED6DCD1B38E9D7B3F436BA2B2BDC1B1A96B45483E2D4282A6B5B5B0A9A26E1C00001B78A0AB8F4D1A000000000000000000000104000100A4D5F3EAD6BDA4867253436795CCE0D9C4A18E72694F50586C869FAEBCAF936126183E5E9AB3C0BBC053AAB89E652500000000000E4998CFC29F673824314A3AC4A18E72694F505801FE685C070718806C7189B8FCFFFFFFCC7F544160AEEBFFFFDD75433064B2DBD6E3C466372C58A9DFE5D6A9510B0518586E6E6E757C612811144A88C3E0E2D4B2833F16174690A2B0C2BCB7BCB27C3419215894C4D1E1C8B4B4A9803B13091B5E95A793959C99A2833E000000146298C5CCD1C2A58F9B7649537899C2BFB8B0AE5D3E44443154899FAAB1ADAF995A1500001F6F96B1A25B140000000000000000000000000000009FD7FAEBD3B19B7F694F4964A0D8EADBB4887D716756575E7081A8C6C6AE8E6127052E609DBACDBACA539FB38E5B230400000000244FA8C9CB9F61422D2B4636B4887D716756575E01FE695C070718907E7993C5FFFFFFFFD181505270B9F0FFFCCE7D43496FB8CAD3DBC0712E2860BADEE9D8AB5407001E5A696D73807B5324080F3986C3E8E0CEC88A3716174698ACB7C2B9B6B4B27C370D2C6DA6C0D0CFCABCB5A77631180D2E6F99A9998B9AA5A07A38000000146098B7C9CDC89F858F754C59769EB3BBB5BCAC7344454130488BB3B1ACA6A48D530E0003307BB4C1965011000000000000000000000000000000A5DCE8C1C09A8A7F7056416E9FCCDBC7AB867C575F54585F7A86A0C3C4AB87571914387095BCC5C7C95CAAAC804900000000020E185395C8C091643D33394B38AB867C575F54585F01FE6A5C070718A0727693C2FFFFFFFFD37F464C67B6FAFFF9DA7B3A4272B5C5CAD0BB6B313165C4E1E5DEAB4A04001B4C6974748070531D0A133B84C5E5E3E2C184310B1550A1AEB6B1B9B6B0AA7A33132C75A3C7CDD7CEB9B2A56C2F0A0729709DAA898A97AAA176340000001E62AFC0D1D2B88B7685644B6183AEBBB8BEB9A46A3B5043364C8BABB5B4B6A599551100002C7BA1BFA554150000000000000000000000000000009FC5DBD0B8907A7360523F5B8BC8D2C19D78615955584E637091B3BEBAAC80541D06336193C2C6C3CA63B2AE8A4D1600000000021857AACCC29B603E3530343E9D78615955584E6301FE6B5C070718B06F7484BEFCFFFFFFC369444B67B0E1FAFFD77D404171BED7C7D7B95E262F6DC0E4DDDEAF4F0A011C5C67646673753D1C0C1C4789C3E8E7DAC68B3013174E9FBDB8BCC5B2B0B4813018326FB1CACFD7C5B8B8A4671F0B0B2A72A0B1928A93AAA779340000001C6CA2BEC6CCC1827A8A7947608DA3BAC2BAAEA46C434A382F5B83A1A3B0ABAA9C570500003183ACB6A55820000000000000000000000002030A009FCCD4C7A58F7E6B5241465D9AC9D4C0A07A634C53524B58728EB1C6C09F81450D092A6FB0CACCCDC76AB1B085490500000000021D6DB4D5B58A5F4229334B43A07A634C53524B5801FE6C5C070718C0776F8BC2FFFFFFFFB97553466CB8EDFFFFCF7B3F417DBFCBCADDBB6A332D65AED7E9E4AB4F0C001E52726A7875613D12030C4189C2E3DDCEB87A3C141F5AA5B9C0C4B3ACABAC7332203A80BAD7CEC6B9BEB7A85E27170E2D78ACB2898598949B783A0000001968A3B4BCC2B586728460436B92BAB8BCB8B4A067424A41295695A3ACB6ACA9944D0100023089A8AE945E1D00000000000000000000000000030097C3D2C3AE90736951383873A0C1D3BE9B72615855454A627E95B0C6BE9C753C15142F71A5C0CDD0C870ADB1813E000000000014195DB5DFC38D613C253850439B72615855454A6201FE6D5C070718D0767B8CC1FFFFFFFFB96F4C4573B0EBFEFFD37149517EBCCCCBC6AE65333368BAE0E2E3A84205001F5E716D79796031140714438ECCE4E2D7B47A30191F5CAAC2C9C2B1ABB0B37C321A3E87B9CBCCC8BAB2C4A46526120D3E7CA7A88E8697A293752600000025679ABABDC2B0747385755C6991B2BCB8BCB0975F32462F3A63909EA6AAB0B197520400083E83AAB7A065220000000000000000000000000000009CBFC5B4A17D735E514231619BBDCCB39067564E47433A557EA5BDC0C09E854B1A092662A2C0D9D6C46EA6A7873B04000000000B307BBCD5BB7E5D3C20344C489067564E47433A5501FE6E5C070718E06F708EC4FFFFFFFFB46B42456ABFF0FFFFD06C424182C5D8C7DABC58282978C1DAE2E0AD460900275F7B74776E572C140413458AC3DCDFD3B67737172262A9C4C9B8B0A8B2AF6F2E1C3A85C0CAC8C0C5B2B28B5F2A1917317CADB29A88919F9B74270000002676A3ACB8BFA26F6D8267566E9EBEC6BAB7B49C5B2E3F34366F9ABCBAB3B0A491500800013484A8AF9D581F00000000000000000000020400000091B9CBBD976F5D5843293C599EC2C6AF926B624B3A3D3B5880A8BDC7C09F704311022A70A5C4CCC8CF87B09D783800000000001B427FBDD4C4905A433933544C926B624B3A3D3B5801FE6F5C070718F07B7F9DC8FFFFFFFFB967444E7BC1F2FEFEC7733A4979C9E0CCD3B05A2B2F72BEE5E5D4AA41020124617C79737650280A010B4088C4E8E0DAAB75230A1C6BAFD1C6BA9F9EA9AC732C1E4D90B8C8C7C9BAB7BA9A612A1F18448DB2AE8F8794979A742A000000286DA5B8B7BC9D666A755B557EA3B5C0B7B4B29356364D3E356693AFB2B1A5B18B4007000D3F91B1BAA7641E0000000000000000000000000404008DA9A99A79574C4140323A6496B7C5A4744941343C393F5C83A3BCBCB0966C350F1C316DA1C5D1D4CE7FB1A77A1F0000000008244A8EBED0B28D60442E3B5053744941343C393F5C01FE705C07071800747B94CFFFFFFFFFBA66464D75BFF3FBFCCC72414980C2D6CED5B6562D386CBDE2E8D6A93D0802316D82807564481E0509194684BAEEDACAAB6C28133069B9D2CFBFA597A9AD742E1C4497C6D5CAC2BCB3B69A5F2B1B0E3E8AA1AB99888EA38D61120000002C7DA7BAA7AF9366757B5D5073A8C3D1C8B8B4905136483C3D749EADA5ADAB9789450000014990B1BAA06A1B00000000000000000000000000030088B4BAA47A59423F312F416493BDC0B77A62382E37313C5B8CB5C3C4B885683406082F6DA4C6D8D4CB7FAF9F6E280000000014325FA2C8CDB0835D462E31434C7A62382E37313C5B01FE715C07071810757C94CBFFFFFFFFB06B4A557CCFFCFFFAC06F405488C3DBDDDDB45B242A71C0DEE3D7A4420307306F8E7D7C6C46180206134680BADCDECEAE6E28142B79BED4D1C6A092A8A76E271E5896C4D5D1C0B7BBB0894C2F21193A8BB2AF927F92A29A611F0000003580ACA898B99D656B74614781B4C3C2BFC1A4904A2D48364875A6AEABAF9F998D3F0300144699B3B8A8671700000000000000000000000000050098B2B2A480513A353231386A9BC4CAA16E55362F30443D5C8EB4C3C3BA8B64350C002473A8CAE0D9D084A8A37123000000001C406CB3C2CEAD75493920315A536E55362F30443D5C01FE725C07071820797B99CFFFFFFFFCA36044496FB9F1FFF4C16B44508DC9DAD8DEAD5B21366EC0E3E7DBAA440302327392848060300A0001174080B6DBDFD2AC5D28192B72B8CFC4C59D9BA5AE6C292B5C9FCFCFCCCABDBEB3864A20180F4093B3A997888D969F741D0000002F79A6ABA5B1976B7C80605B8BAEB6B9BBC2B38E3B2F3F3C4678A7B6B3B6A99E833B00000D4B86AFB0A15F1C0000000000000000000000000000008AA9AD946E423026211F34638DBABC9E6E40342D263A3C568DABC9BEB48762390D023775A7D0E3D3DA8EB29966180000000020436EA1CFCDAE76614038344A4D6E40342D263A3C5601FE735C070718307E7E97D1FFFFFFFEA863445A75C4EAFFF0AB61405086C8DBCED1A64A28377AC8E7E3E2A447030031749596816739050000144A82C0DFDFD2AC60200D2D72C0D8D6CAA79EA9A2602C2D5CA6C6C8C7BBC0C6BA8E472416194B91A6AD96849996875B0E0000003A899EA1A3AB95667871556087A8BFC0C3B8AC8F482F36364D81A6B2B7AEAEA5852D0000194888B1B1A86624000000000000000000000D00000800879EA48F6C4D30252422305FA0BCBC9369462F2836333E5E89ADC4C5AB895A2B0F012E77ACCFDEDDCE94B29A66200000000025567DB0C7D29C704F3C2C2B545469462F2836333E5E01FE745C070718406D7C9BD3FFFFFFFA9D55424872C2EEFAF1B76441528BD1D8DCDCA94C253372CCE3ECDB9E420002356E96958866360C0002234F80B9DFE4D3A35A1D113273BDC8D0BC9D8FA6AF642E326CACCCCAC4C2C8BBAE8A492F1B13428EB2B097979897905E19000000417EA3A09FA98F5E737353538AB3BEC0C1BCB285453138334889ABB5B1A5A7A17E320000255695A9B1AA6C2900000000000000000000000000050082A5A9865B33281513203A68A6B8AD8C663830262B343F5684B0C5CCAD885F36150E2665B3CEDCDECD96B0A46A1B00000000264F80B7D4CCA5674136242F4B55663830262B343F5601FE755C07071850777FA0D5FFFFFFFFA964495279C2F5FFF4B85A3E5A97CCDCD0D7A651203A76BFDEEADB9A37020036809CA0845D310A00081B477CB6D9DECDA0552313306FC1D4D0C39888A3AC67342C64AECACEC8BFBCBCAD7B47231E1D478BB6A89492938D7D500D000000428FB6A49BB49770726C4C5793B6BDC3BBC3BB8C462B362D4E86A4B0B4AFA59A7D24000024658CA2AE985F1F00000000000000000000000000000087969784632D150F0B102B6DA9CDBD9262362A1F2E31316593BCD2D9B17A5E39160C316FA1D6E4D7D1A7BD9F600D0000000029668CC3D4C39E66442E1F33565962362A1F2E31316501FE765C07071860747C9FD2FFFFFFF595574B517DCDF2FFEFB45D455D99D4DEE2D2A152263979CFE7EFDA8F2D0000357F959C856B310C0000204F87ADD1D9CDA851160E2E6EB6D1D2BF9493B2B061222975B0CBC2CAC2BAB5AF7D4A2D231E4A8EB1A89E8A8F8C7C530B000000518EA49EA2B28C6E796E4B5F93B2BBBCCFB9B3853B2834264D96B5C0BAB9B09C7A2700022A5A9CAAB999591A0000000000000000000000000000008FA59687572E18161119306DA5C1BA9D632F1B152A313A6495BBD3CBAB7D6037131C3D6CA1CADEDDCFA0B7955E140000000031699DB0CCC29A6D443928325158632F1B152A313A6401FE775C070718707783A2DEFFFFFFF6A2633E5184C1F6FFF7AE6344659FDAE5E1D39B4B273980C8DFEDD2912A020C4082A6A8875D250000001E5590B6D1DED5A14D180B3780C5D1D1C1918DADA862253A77B0CBC7BFC3B3B4A97C3C2C291B4B97B7A798959691783D0A0000004F91AA9794AC95697B71485B9FC4C7BFC2B9AA82422630324F8BA7B5BCB3A8A57A2701102E5A99BAB297531D0000000000000000000000000201008EA19989502311040C163475B4BCAF865826242926324968A3C4CED5A4805E3C25213D6EABD2D8DBD99CB7935C0C00000000347196C4D0B28F593B2C2C2C5360582624292632496801FE785C070718807D8BB0E2FFFFFFEF995D4C588BCBFCFFF0A963475D9ED8E4E1D2A34525397DC1D1D9CB812801063688A8AF9B692A020002255685ADD6EACBA047200D2B6EB6D7D7C89A8D9F9C522A317AB4D4DED9C1BABBAA7043221E1B498BA7A9A09E917474410100000F5B92A2A3A0B38F7C886E566A9DC1C7C6BEB1AA854015261C4F91B3B8B6AEA7996C200413406C98A6A9925F14000000000000000000000000000000919C9D865320060B08132E68A5C2B48C562D17213635467DA5CCD0C7A36E584427213D659ACAEFE4CB97AD90580E00000000376F97BBCABD92603725212F4A63562D17213635467D01FE795C070718907885AAE9FFFFFFF18B51454E81C6F1FEE1AD584C63A2D7E4E3DDA148294082D1DFE3CC80270001377EABA89068270000001D5B94B5DADECE97451D0F3470BBCBD5B989849FA05B28377EB9D4CECAC9C8B8A970392C1C194D93B1B0A7A8837568380A0000126395A59899AA8A718162516AA3CAC8CEC7BCAD8839161C205D8FADB3B2ABA9A46E2A131A3E6590A6AE894714000000000000000000000300040100949B987D471A0D000C0E3A76AFC6B692512C0D2A3542536EAACED5BFA67C57432E1F2A6797C7E2E0D39CB1A05E11000000003270A9C9D3B38D492F261C325E7B512C0D2A3542536E01FE7A5C070718A0788AB0E9FFFFFFF89C544B5686D2FDFDF5AF58445FA4D8E5D8CB8A45202C76DCE4EBCE7C1C000E3F86AAB4A36723000000235383B1D1E4DEA05111193B80C2D6D2BC9485A69C51203B7CB5CCD7D2CCC6BDA0652F21171B4C90AFADA29C8C79632C060000186D959F929BAD9779776A47699EC8CFC3BDB7B2803A111A285E9CB3BCB4BBB1A36C28121C427491A89D834B0F000000000000000000000001000000788B8673321400000007327DAEBBB3864C1D10242F3D4780A9CAD1C4A6775541291B3468AED4E7D8CE99A8875D06000000044478A6CCCFC18C4627241B2B576A4C1D10242F3D478001FE7B5C070718B0778CB6E7FFFFFFEC9956475481C3F4FFE79C5C4E6AA5E4EDE7D58E411F3780C0DEE7D07E1F05063982ACB4AA6C300B0004265C8AA9DCDBD19246170D2C76BAD4D0C1968C99905023478BBED8D1CAC2BDB79B5B35291D124689A9ABABA88770602C0C000015679EAA97A4BB89818D684E69A9BACAC8C9BAB57E3618172A5BA0B7B9ABB0B39E6719002C506E97AE9B7C4C130000000000000000000000000000008F8F997A49080000000B3283B3B5AB7E511D161D233F547CA9CFD2BE9D74654E4226366FA2CCDBDACAA2A9884F0D000000004581ABD0D6BE824021140E2B576A511D161D233F547C01FE7C5C070718C06A7DB3ECFFFFFFE5874F41517FC9FFFFE2A05F405B9DD2E4E4D08C34274487CAECE4D1722100043C83B5BDAA6D2B00000B335F90ABC9DCCF9F4415153A79BDD2D2BE8A819E9142264690B9D7D3C7C4B8B092572D22151F4D94AEAFAEA588614B2A0C0000276D9DA997A4B193788164506CA4C4C7C3C1BAAB822B02122867A3B4B5BBB0AE976A1C1231546A93AAAB88480F000000000000000000000000010800899A937642050000100E3284B8C5B2844415001A353E5181B8CFD9CBA8746254422C3A68A3D1E4D8CB9EA7835802000000003E8ABCD0C8AB8047161B1F3154744415001A353E518101FE7D5C070718D06E83ADE9FFFFFFDF8A4B404E7CCDFEFFDF95594A6BADD3DEE0D2833921438AD1E8E4C6721E000D3C83A5B8AF6621000004316C91B3CFD9C9903C1216387DB8CBD8C59E90A48C3D214B8BBDCFD1CEC8C9B490502420141F418DB1B3AAA48F6746240B0000246C9FADA4A5BA9E8184614874A5BFC6CBC4B1A97D290B031E6CA3B3C0B5BDB0A05A1F1A38607490A9A2794B1400000000000000000000000000000082968F652D03000000002A6CB2BD9F7B47180F18363C5A87ACC4D9D4AC75604D3C32396597CDDFDAD498A17D4000000000004182B2CAD5B87B3723131F3D628247180F18363C5A8701FE7E5C070718E07389AFF8FFFFFFDE804F44507FC8F0F7DD8E544B69A7D6DAE8CE7637294C94D3E5E8C7741A000A3E88AAB5B074230000053D7399ACC9D8CF933C11173776B7CFDCC78F859E8638255391C0CDD7D5CDCAB68A45252718134989A1B2AAAC815B3D1600000024739CADABB7B8908393665072A8BACAC7BEC3B7802808002070A7B8C4C3B7B2AC6B211941637B98ABA376390900000000000000000000000101000086928A692E00000000003783B2C7B38944170B1921375285B3CCD3C8AD78685B3E2F3062A8D6F8EAD19BAB884000000000054898B7CDC9B2803A10111831577944170B192137528501FE7F5C070718F0708AB8FCFFFFFFD979423D5885D5F8FFD98D4C4468B2DBEDE9C87C2F2D478FCEE8DAC5651300033380A8BEB57D2901000D4074929DC8D1D8983A0E154186B7D9D1C496929C7935204E92BBD3D3C5C7BEAE89432B201512498CABABB0AD8B52381C0A00002975A1B7A5B4C2918283584E7CAFCBCAC9BFBBAD7D320F0B3375AAB0B6B7B4B09556181A48717C9CA79B7B3C0D000000000000000000000000000000839B93703D00000000003889C4C9BC7C42120A203649578BC3D6D6C7A27B67583C2C2A60A2D2D8DCCD9CA283410000000009438BBBCCCFB87C3E0F11142B5F8342120A203649578B01FE805C07071800798BB5EEFFFFFFCF7444374E7DD3FDFFD589443A6AB2E3E8EAC36A2729458CD2E8E6BC621500003B83ABC2B2832B00000E508796A3C5D3C787380C1E4384B8D0D6CB948397742D194A99C8D2D7D2D3C5B37C422A1A0C194888AFBBB6B0884D2E15000000317FABB9B5C4BC908486514669ACBCC1BDC1B8AF702D0C0C3077B1C2B6C0B2B196502731548183A19B9D7939010000000000000000000000000000007D88876028000000000A3A7BB6C8BA7A350E0A1633475484BDD4D9C7A782635E463138579EC7D9D2C19BA1804200000000014595BDCDD0B37D370B0A1A386488350E0A163347548401FE815C07071810738EC3FFFFFFFFCB794B3D5987CAEBEDD38A4C456FB0E3E8E4C26E271A4698CAE3E0B5510E0003417EA9C1BF823208000E548AA0ADC9C6CA98430B154385C4D3DCC893898D6F2B2755A1C9D6CEC1C7BEAF7A3F1E20101B4B86AAB7BDBC884626100C000B4582A7C0AABCB987837B575476A8C9CBC7C6C8B2712308123578A3AAB7AEB7AD975A2B385F788C9FA09C7E33000000000000000000000000000000008990805E2F000000000B3F8ABCC4B0763B1009183347688FCADADCCDA36E615D49352C5C98CFE4D5C4A2AF814A0000000000488ABAC8C7AD7A331C1214335F8A3B1009183347688F01FE825C070718207E93C2FFFFFFFFCD7F51465588D1FFFCDF84434472BAE7E1EAB56123204F98E0F3E6BE5C0F00013D7CA8BBBA80350500155F9CA09EB5D0C389360A174184BED9DACB9384936C2C21569FC8DCD6C7D0BFB3752C1A0E0C193F90AFBFB9BE833D1A0C07020D3D8DACC4BABDBD8B8A7748527CAAC5C4C0C4BDB3762402063784AEC0BFBBB7B99B54264062828A9FA39A6F44000000000000000000000000000000007E8379581F00000000003485B7C89E713304001D354D6C99C4DCDACAA26B615E45272E5E9CCAE4ECD79F9F784100000000004899C0D3C1A97437141015385E883304001D354D6C9901FE835C070718307794B9FFFFFFFFBE6B3E3D5691CCEDECCF783D3F72B6E6EEECAB5F26285299DBE5E5BA53100003387AA5BFC38B3D060016539AA9A3C1D0C3812F1219448EBDD2D5C5928A9460231D61A3C6D4DCD6D8C4AE7027141406114688AAB9B9A97B3B1A0E09040C4B87B0B7B8CDC78B8B83475A74ABC0D3CDC8BDB97A2A0012428DA9BCB7AAA8AF93512944728C9696918E66380000000000000000000000000000000084958D6229000000000E4189B1C7B0733A0E051B3F4F5493D0E3DFC2A87A645A3F2E2B5CA3D5E9D8C7A2A5763300000000065494B8CECEB57C2B091114336E8E3A0E051B3F4F549301FE845C070718407A90CDFFFFFFFCB56E4A4F6193D0F2FDCF7E454374B5DFE3E3B0612B345FA9D7E6DFB44604000B3D7BA5B8AF853309052667A6A6A6BDD0C782300C114390C6DED2C7987E8558232B68AFCCD6D6CFCAC3AC652B190E0D0D4189A6BDC3B67B3C190F140B194189B0C2B8D0B78A786E4B547BAEBDC6CABFB7B07620060F3F8BB3C0B4B8AAB290482554758B8C9DA294763F040000000000000000000000000000008287754D0800000000043082B7C7A96B2F1003183448649ECADFDFC6A17B6A5848382C61A1D2E5DCC89A95793400000000005595C7D3C9AB69300D0D13355D8B2F1003183448649E01FE855C07071850768BC5FFFFFFF9AC6F39445F95D1E7F4C984454367C0E3F1E4AC6027285FADDFDFDAB74C040007396B98BEC791390A01206DA4AAA2B1BCBF7E300F194B95CCE0E0BB9F878F531F2360A6D6D5D1CCCDCEA6581D0F14060F4780AABAC4B17739110317081A478CA7C2CFD2C3898173465175B2B9C7C7C0BBBC7E21000F4D98B2BBB4AAAFAB91442259829F96AEAC99733E010000000000000000000000000000008A8D815F1500000000093C8DB0BC9D6A300105112743639BCBE1E0CFA974625C46152F5C9DD1E2E0D3AAA17536000000000658AAD2DECF9B601D040F0F306296300105112743639B01FE865C07071860698DCCFFFFFFF3B06A40486891C7EEF3C97C45467FB9E1E2DCA351262658A0D5E8E5AF480000012F6DA0CAC195420F072978B5B69DADC0B5732A121E4F95C3D5D5C4958D834D172A71AECDD9D2CCCFC2A4561A13101019458BB1B6BDAF732214121D13174A8CB9C6BECDBC838273485177B1CBCCC7C3C8B2732700155C95B1C2C1B8B39F833F2C648A9693988F8E6D3B04000000000000000000000000000000858C77551B0000000009397DB1C7A568320A0016325076ACD5DFDDC3A571665F442D37659DC9E8D9C1929E6D2F000000000757A9D3DCC6945E1C02041738638F320A0016325076AC01FE875C070718706E8CC8FFFFFFE99F5B4245699FD2EEF2B76B434B76C3EAF0DC9D48272E59A4D9E5E6AD410B000C306494BEC3943F0D063175BAC1A1AEB8B5692B0B224B97C8E4DECBA18F7E411C2B7BB8D6D7CCC6C7C09B521A0C010218488BAFC4C6B16B210F162718154086AEC9C2E1C27D77613B4C82AEC8CDCACCC0AD731F01154F92B2B5B9B4B3AE9240376D88A397A39588683F0800000000000000000000000000000081867A4E120000000000438DB9BE9F6427000013234873A8CFE2DEC9A9745C563C2D3476B6D2E5DBBE9A996A23000000000553A4C6D7BE8E5225000913305E9127000013234873A801FE885C070718806D8FC4FFFFFFE29F603B4E6993CCE5E9B66A3C3D71B4D8DCDD9B4F2B3069A9E3E7E49F3705000032638EB9BD89410E0A3984CCC6A4A8B3AB631A0D1F56A2CDDFD0CD9C837E46142A71B5CCD0D4CCCFCFA14F19110D0E184183B5BBBFB174281219261B1E4688AFC7CED0B7847559455C93BCCBC5C5C7B7AC6A1400165A94BAC5BAB3A6AB8A3F2A6E95AEA3A5998D6640070000000000000000000000000000007C877C45070000000000368AB7C2A6631500091B2D5879AAD8EBE0D09E68554D38322F5B9BD4EED6CAAB966E31000000000B57B4E0D7C7964E19030A143772C21500091B2D5879AA01FE895C070718906B8FC4FFFFFFD78B583D446DA5D1E8DEB15A313C6BB5E4E2E29B461C2B65B6E3EAE39F2D0100002D5F89BEC497410E183A8FCACD98A5A1A75B1D0D1D5598CCE3DEC9B197733B15368EBECEDCDCD1CBC396491107000E1C488AA8BEBCAB6B2A0C132818244D92B0CECFD4B28360533E5C7FB2C7CACACCCCAB6819001D69A7AFBBBAB1ADAF783A2D6D9A9F9A9B988B6C4300000000000000000000000000000000788678400000000000064089B6B48F5A1B010B232E4F77AFD3E1E3C1915E5059432E2A62A2CFDEDDC1AE95702A00000000004CACD7D7B98547180D0D183368C01B010B232E4F77AF01FE8A5C070718A07288D0FFFFFFD7905639547EB6D9E8E1AC6333426FB3DDE8E49E44242E65B2DBEBDC9932000008346288B7C595461B173E93D7C9A5A4B19D5815051E57A3D3ECE4D8A5966E340E2E89C3CBD6D1CECEC88A3F0E000412204F92B8C5C0A65B1F0B0E2B1A19408BB6D6D2D8B67C5F58415F88B0CCC9C2BDC0B06B1800216FB0B6B8B3B7B5A98D4139739FABA49D96886E43000000000000000000000000000000008786663E0100000000004393C5B798501C010F11284D77AED9E3D9C59A6F533D341F3061A5DBE8DEC4AE91612300000000065EBED9DCBB86400D030C182F69B81C010F11284D77AE01FE8B5C070718B07490CDFFFFFFCC85523D497DB5DAE9DEAD613C4077B4DEE7DA9D532A2D65A8D6E2DEA03B0000092D5F8BB5BF8C4414133A85CFCBA8A7AF934D170919539DD0E4DBE0A4906A300D338FBDDAD9D3D1D9C59A43120F060B1C4E95BDCAC1AA60120915251B214C8FB8D5DCD2B17C664A3A5293BEC9C9C8C2AFAE6B21031E73ACBDB7BBB2AEA18131417A99A8A0939A916944000000000000000000000000000000007D8883430600000000024A97B9B79D60240003212D4A84B4DDE6DBC4976345402F2B3F6AA2D3E1CFCAB4A26221000000000466C0D6D8B2843E160C080E3B6EBA240003212D4A84B401FE8C5C070718C07096C5FFFFFFD08B5A3D587FAFD0E6DBB35939406CACE0F0D98B47283573B6E1E9D3952E0B00052A5F87BECE95450F204895D1CCA9A8A6843E0F06224F9DCBE8E7D7B6A66E2C0E4098C9D1D0C8C2C2C6904611071018244F89ACC5BBA4591509253022235098B4CAD5D1A16D5B3A366490BFC9D2CCC6C8AE6616002474A7C2C5B2B4AEA87A394284A5ABA19C9088784B00000000000000000000000000000000767765340000000000075794BBBE8E4B16000B152B4E7CAFD1DACBBE9E6C4B462D2F2B64A3CEE0D5C9B390651A00000000116AC1DECDAB78380A0015103371C316000B152B4E7CAF01FE8D5C070718D07B99D0FFFFFFC88055435B89C3E5EBE09C4F354670B2DBDED5904E29376EBCE1E1D58E28000003375C7EB3C8934B161D4BA3D8CFA9A3AB8F511D0B2354A0D2EDDEDBBC966B2B0C4091C3D3D9D6CDC7B583390F040D1A255093BCC2B9965A1911253D2628478EB3D4D3D6A76551383F6597BCCED6C0C4BFB06419002F80AFB8BDBCB6B2A87D37407AA7ABA9A19289724900000000000000000000000000000000897C6D3E00000000001759A5CAC1945C25071E1F2F558AC2E0E6D9C69B6C46322E25386DB0DDEAD6BBA9955D0D000000000D80C9DACFA878370B000A112C7ACA25071E1F2F558AC201FE8E5C070718E07991DDFFFFFFC57D483F5B83BEE9DFCC9A57273C70AEDEEFD489482A3972BAE1DFD1882900000F375C84B5C59D42171E56A3DADAA6ADAD803A13091B5597CBE4DFDBB49D5F231146A1C1CCD4C8C2C5B98A3507100B152D5B98BBBFBD9A57151C2846271D4A8ABBD5E3D8AB714A374276A5BCCCC6C8C7BDAA651E0A3175A7B7B9B4B3B09F6F35478AA8B1A6968F8278440000000000000000000000000000000088856E41000000000000358EBDBF9B5A20132325365C80B9DED4DCB795663F302830376DB1D6ECD6BFAD95661D000000001C67C3D8CF9F742F0606151A316DCB20132325365C80B901FE8F5C070718F079A8DDFFFFFFC07C53486298C1DDDCC78A4A304179B8E5EFD3833E203E73BADDE2CA85270000122F5A7BBCCB984F222856A7D9DBB5AFAA7A350606215397D3E0DFD1BFA76728124BA1C5D2CCBDC2C8C4813C0C0D1D292F589ABAC2BA9B4F0F0B3043232F5593B7D4E2D7A05D44334474A4BABEC6C9BEB1AC6311053988BBC8BBB4AFAFA3672D448FA3A7A59E8F937C460000000000000000000000000000000075725A280000000000005090B9B48D4610091D12274D87BED6E2D9BD935D3626211E3679B4E1E9D9BEB497621C00000000267AC4D6D19A602808000D102A7CD310091D12274D87BE01FE905C07071800608FC7FFFFF6B96E453E5891C5D7DBB978482B376DAFDFEACD8038264175C4E8E5CC7D22000009315187B7C49347212E64B0DECFA9ADA578340A001B5A9BD4E7ECE2BC985518054AACC3CACFC3C0CDBD8E3E05051B272D5F9EC3C6B699491619313A1B284C8FB9D3D5D39C583C2D4181A3C1C5C0C7C4B1A762140B4083B6C1BCB6ADADA577345588A7ADA6A28D80734E00000000000000000000000000000000806B532A00000000001059A1C2AE864D1C14231F2E599CBEE1D5D1B3905B29151C252E6FB5DCE5D6C3AA99601000000000257EC4D6CE935F2C08000A142F76CE1C14231F2E599CBE01FE915C070718106F91D4FFFFF7BB6F55476C9DD4E0E5BD7D41293666AFD4EAD8843F2D4173BBE6E9C9801E00090D345E8CB9CA9446192B5AB0DFDCB3B2AD6F2902081E5495CBE6E1DCC09B4E180C49A1CEC8D2C1C3C4AE7531110C19353759A5C6CDB7944E11143A42292A5094BDC9E4D29C5933324E82B5BFBEC5C6C2C1A2530F053F9AB3BEB2ADA9ABA269355D93A6B79D9993917543000000000000000000000000000000007D6F541F00000000000B619FB4B78349221C1D1A245885BCD1D7C3928C5F3A1B1921437FB7DBDCD8BFBB916014000000002C88CAD9C28F462008010B162C74D5221C1D1A245885BC01FE925C070718207C92CBFFFFF6B37548436DAACEDDE2B6703F283A6CABDADFD37B472D3C7AC0EAECC7741F000616335B8CBDCC9B47203664B7DDD7B9B5A76B2403001E549ECBDFE6E2C493460E0F51AAC8CBC8C0C4C0C07F2C0A0E223B395FA0C8C7B4943F09193A46292B4E95C4DED0C8874C2A2A488AB1C0CACCCEC5BD9D520D154E99BBB8BFBBAD9F9263314F84A7B1AC9F918C784400000000000000000000000000000000746A4F220000000000176BA2BDB0834F1F181A1C295189B9D1D1C5BC834A1A0D1426417DB3E4E9D2B7A7925813000000003489BDD1BD8D551F0A0211113483D41F181A1C295189B901FE935C070718307598CCFFFFE8B0734C4471A5D7DEDDB86932294567A5DBEAC7813425417CCCE3E8D170170200133B538DBBC79C4B232E6BBDE7DFCAB4A5602000001F5993D1E4F0E6C799471A124EB3C7CFBCB4C6CEBE722D0F14333A3960AAC4BEB8944410072D42252A5494C3D2D9C89045242D4E91BACCC6BFC0BEB39F48110D5099B3BEADADA9AE9F5D486498A7B6ACA79D937D4600000000000000000000000000000000785C4A1E0000000000226CAABCB68D4C2024211A275D8EC2D1D2C8B58B482208051E4E86C1DFE0CEB4AF8A531C000000003690C8D8BB904F1200001011357FD42024211A275D8EC201FE945C07071840759DDAFFFEE09A5E434E79AFD6DEDBAA6A36292E6BA3DDE7C36F33274484C5E5E6BF681B020C13315A8CC3D29642223370BBE3E6C3CAAC5F1B0104165096C2E0E1E2C68D40111056B1C6C3BAB8C3CFC071240D1C2F3D3B63B0CFC5BA8A420E0F39442D304C91C4D4D5C6823E21235595BBC8CCC8CBCBC39C510A0E569DBDBEBEBBB5A9955F345C93ACAA9D9892826D3F00000000000000000000000000000000675B3D0B00000000002C73A5B2A785511B12261D2C5584B5CBD2CCAE79431E04001C458BB9DEE7D2C6BA9D550D00000000438FC1D0C6844B1A050008102E8BD61B12261D2C5584B501FE955C0707185082A6D7FFFFE7A065504A79BDDAEAE3AF6836283862AADFF1CF6E312B4986C5E3E0C17320000C213A5E91C3C48D4329397BC3E6E9CBCAA0580B0002155E96CADDE2DCC595410C0E55ABCCC0BFB1C3CFAE6523040A344C4867ABCAC3B3954D121239362F385EA4BAC8C7B97741252F65A0BCCACFC5C2C8B1953E0B105196B9B4BFB5B4A99565356293ABADB0A29D8D723A00000000000000000000000000000000736C3B0F00000000002671A9B9AA884C211F221E315391BFCECFBAA072320A001024488AB7E0E1CEB0B1934A15000000003394B8D4C3864113050B1018398CE7211F221E315391BF01FE965C070718607B98D7FAFFDFAB65464C76B8E5E2DBA0532521416DA9DDE9C57133284C8BC8EBE1B45C19000D31445789C8C68A4227346FC8EAE0CFCBA654130000285F9FC6E3E4DBBF903B120D52A9C1BEB09EB5D0BA632C1A1D38574D69A7C6BFAF8842181B3F472736669ECBCECEB879391E365EA0BDC7C3C6C8BCB39641091559A0BEBDBBB4B2AF935D3B6195A8AFA79F929075350000000000000000000000000000000075663B0D00000000003B7DAEB8A97E4E0A0F292743669AC6D4CABDA6782F000000194788C1DAE0D4BCB0915F19000000004295CBD2C086410E090F2013749EE60A0F292743669AC601FE975C070718707497D9FAF5DB9A573C4B7EC2ECEFD69C52301E3463ABD8DDBE70322A518FCFEADCB2611A080E1E385D94CFC897412B3981D4E7D9C8C9A8541000001F5EA2C1D9E6DEBD8B3E121459AAC0BEADA0B1C5BD692A09244156416BAEC4C5BC8A421C1E3A3A28345B9ECCCBC9A96638253366ACC3C5C2CBC3C3B58F4009195BA6BEC4B6ACA5A0965939649EB1ABA69B978D6F33000000000000000000000000000000006A5B36000000000000367CA7B4A88148191A2A2D497194BECBCDB5A76B150000002B5698C8E8DECBB9B38F5721000000034399D3D7AD7A3D110310101F3D99E9191A2A2D497194BE01FE985C07071880749AD1FAF7D389503A4C81C7EBF1DC9D4620233A6DB2D4E8C1703424468ACCECDDA96218000C27496791CAD28C3A234286D9FCE8C9CCA7600D00001B589BCDE4EAE7C68937020E51A4BCA58E89B1CAB75F2E182F4E61546DA1BCC8C094391314373930366BA2D0D5CBB2612C1B2168ACD5CDC0CAC8B4A98A3E0F195E99AFB9BDB4AEA78B533F7398AAB2ADA4958B743B000000000000000000000000000000006F5B4F00000000000E5285AAAF99773D10122726476C9BBFD1D0B39864230000002B5792CADFE0CFB1AC89642100000009569FD1D3BC7F45160006111248A4E110122726476C9BBF01FE995C070718907AA1D7F6FBD1915940417FB7E6EDDB97522A27416FADD0E3BD652B245497D6ECDBB55809020D2C476699C3CB86462B3C89D2E9D7BFC0A74C0F00002056A0C9D1E6E4C5843608145BAEBDAE8D8DADC4B2662A2C325A65516AAAC1BFB98C3D091A2F392F4473B3CDCDC4AC642D1E3169B1C5C9BDC4BFBCB08F37081963A2B1B8B9C1ABA6965F4A6F94A5A69F9D8F90772C000000000000000000000000000000006E564105000000001E5892B9BBA67F3B10180029497BA6C9D0CCAF8A5C18000002275AA0CBE4E4CEB5B2894E160000000E61A3DCDFB3743008000613375291E610180029497BA6C901FE9A5C070718A07099D1F2EBD187463C4B86CCE2ECD2905226223961A9DFDDB8662A2D52A0CCE7DB9A450A061623526498C8CA823B254587D0E4DACAC5A0461400001D659AC8DEDDE2C58C32090F5AADBAA18B90AEC6B9632A193F69705871A3BCC9BF97380D20313C314575A9C3C8C2AD6130173078B5C2D2C3C5BAB1A17B2B12276EA0B1B6B8B1BCB285504873A4B2ADAAA89F9D792F0000000000000000000000000000000062402000000000001E528AAEAD95793F0F0C1A31467FA5BFC9C3AF8A5718000000315E96F3F2E4C9AFB788440C0000001767A5D4CBAE6B330D0017111D55A2E60F0C1A31467FA5BF01FE9B5C070718B06E9FBEE0EBCB7744424E88D2EEE9D9964A28213E6FA9D3E3B96822265498DAEFD29741060316364E6C98C7B97F3B294590CCE6D9D3C698510E0000256BA7C6DADCD1BF7D2E091058A3AD8F7E80B5D7BF6935243C6D79586CA4BDBFB996380D0C2E35315678B4D2CCC495561F103682C1CFD0CECAC5C4B06C230E236DA3B6BAB3B3B0A582494A7495A8B2AAA399917327000000000000000000000000000000006D572C00000000003B629BADCFB578420C03193A5582A3BCC5BBA37F53160000062C66A0D1E8E2C7AAB17E4B1B000000225FAAD6D5AD672F0904070C225AB6ED0C03193A5582A3BC01FE9C5C070718C070A4C4D7E9B77544384990D8EBE6CE93451F1E3D6DB7DBE2C164262C5B9FD8E0C8823D0405173A5370A2BCBE722E2C3D8ACAEEE3D0C8924D0700052570ADCBD8E6DBC08123000E579BAA8C6F78AACEBB5B29254175765B60B0C7CABD9B3B1013293A345481B8CDD4C090441E0E3381C8DFCACCC4BFC1A26E2E062873A6B9C2C5AFAC987D4B487CA7ADA3A7A09B997923000000000000000000000000000000006C531E00000000003473A4C0B78869370C07263D548AA9C9CFC09C7E46050000133C7095C9DFDECBA7AD844C1E000000296AB1E1CBAF6F2A070002101B61B2EA0C07263D548AA9C901FE9D5C070718D0729FC8D8E7BA73443C579CD7ECE7BE8945211C3B6AB4DDEBB0582F2D60AFDADBC27D3504071B486280ACC9B77028214199C7E3DAD2C78D420B0009246CA9CDE1DEE4BA7722020D4A9AAE8D6B7BADCBC06D312A42717C606EABBFC0B396450B0D283A395990C7CBCABD964B200F3A8ABEC7CDC7C1C9C1A86F24022B7DA6B4B7B1A8ACA97F484C7BA1AEB1A2A6A0947A25000000000000000000000000000000006646200000000000386996AFB69B6A2000041D396883AFC3D0BEA47B43020006103A74A8D2DEE3C3A7AE8452170000002F71BADBD6B26D2C0300000E1B53B0EB00041D396883AFC301FE9E5C070718E06FA8CBE0DFBB7A433A569BD8EDE9C8894721203C72B2D8E5B450223367ACD9DABF823807072748637FA0C6B068271F4CA0D4E0E0D0C98C4A0500002F76A8C9E3DCD6BF7223000A53A3A58B6174B2CDC0632F2851818C5D62AAC3C9C399370C0E2A2C427391C0CFC8BA8E441C0F3887CACED2CDC1B9ADA0681B092F7AAAB8B9B7B5B2A26D4B558DABAFB3A4A69BA275240000000000000000000000000000000069481800000000004480A1BEBA956D2E0402143B6585B8CDCBBE9B723D010000144B7AA7DFE9DABF9DA9844B170000002F6EB5D6CDB26D190000040C215FB4EA0402143B6585B8CD01FE9F5C070718F07A9DC5DACDB274443E539EDFEBE4C982441D1B4680BCE6E1AE541F2E6DB1E0D8AE6B29030F2C56717EA2BBA7652F28559ED2E9DFC7C68C4B0B00002F72A7CEDBDCD1BB7922000C5296917C5A6AA9CABD662D275C919165659CBAC0C1943E090926375479A3C3D3C4B5843B19113B99CFCECCCDC1BFBB9C580E04338EADBFBDB1B6AEA375545084A5B2AD9D99928E621700000000000000000000000000000000644A1E00000000014B8BA4B8BA9268320000153C6FA1B8C7D0C19C7F3A0000001A487EB5C9E4DAC0AAAC864B12000007387CAED2D0AB68270400020F2160BDEC0000153C6FA1B8C701FEA05C070718006EACC8D4D5A76535324C98DBEEE5C682401C21477BBAE2E5A84B1D2D69AAD5D8B6662900021C587B86AFC6A1622D2B4EA6D9EDD4D1BB813A0600072E89B0D9DED4D3BF7B1E000A44938D6B5F6EACD4B669313B61948D5C5299C0C6B890470A0F1F2F537C9FB8CBCEAE753D231B4091CBC7CCC8CEC7B6904D0F023380A7C1BDA9AEAEAC7D595688A5B0B5ABA8A6957011000000000000000000000000000000005C390200000000075186ABB7C0A66A2900000D347495B7CEC6AD8A6731000006294873B2D3E1D5B399A67E4B080000084082C2E0CF98732E030001091B64BBED00000D347495B7CE01FEA15C0707181070A7CFD5D9AE623C3B5B9EE6F4EFD07E3C1A1C447EBFDEE6A749223B74C6DCDBA5581E000E2C627F91ACCAA35C262155A4D1DBD0BDB8844C1000053872ADDAD9DCD9BB7B23001148968B6B5C71ABCEBD663D30629A965E6C9BCBCAB9953B06051F35527DAAC8C7BAA86E35141E5091C5D6D3CEC5BFB69D4308033789B1C2C2BCBCBBA07653588BA4B0AD9F979B8E69140000000000000000000000000000000061310000000000084E87A5B2AA945B25000016467B99B3CDC9B88E622C000000294883BADBD2D7C497A78143110000104988B9DDC4A6661C03000908226FBCEB000016467B99B3CD01FEA25C0707182070A5D2D2D5A85B312C56A0D7F3EEC77F3F1E264990C5E6DB94451B3C7DC9ECDFA25E17000A325F8598B0CA9341262B529CD3DCD4C2B48B441200073684B4D3DAD9D2B76B1D03073D8B815B526DA7D6B0613C3D71A4975B5F97BFC8C09543120C1C325A8BB6D0C1B4A465280B15569FC9D6D2CCC7C6B58D480C0D4799AEB9BBB8B0AA9C7B5A6B95A9A8A49BA19C855B050000000000000000000000000000000063410E00000000146392B8BAB29B602500001D487DA8C3D1B3A375572A000009285D96C2CADBCAB08EB27F4B2001000F518DC5D3C4A75F250000040A2571B7EB00001D487DA8C3D101FEA35C0707183073A0BAD8D59A612A2D4898DFEEDFB9752F17224B98C2DFD49442273676BFD8D9A45618000E36668998B6BD854F1B2954A3D7E7D0C1B27D380100053C87B7CBCEC6C8B4731E00003F7F7F61506BB1DCBB6D3D376AA297635E9FBFC5BD92430E0620376FA5C0CBBBBD9F5C2013185395CCD7CFCFC2BEC2974407034493B3BEC5BFBFAAA373646E93A1ABA89E9D918F5E130000000000000000000000000000000055260100000000095786A3B4AD8159180500144582A0BFC6BB9F856224000007295B8BB1D8DCDFB78CA468351900021E5296C8DBCDAB5E1B01000200206CB9F30500144582A0BFC601FEA45C0707184076ACCAD5D2A1532E3155A1E1E9EEBF7534232E5189C6DDC58A43193884C4E1E2944C1C001540769497A7AB793D24315F9FD5DFE2C9B173410800074085BEDCDACBD5BC731C00003B76705C4F72B3D5B55D303979A29B5E608EB3C6BA93340202113C6AA8C8D1C1C0A3562513164E9FCAD4CAD5CCC5BE813100114E98B7C7BEB7BAB3A973646A8CA5AEA3A6A591915D000000000000000000000000000000000063380A00000000016599B2BBAD8E5F250100164082ABB9D7C9A56B421900001337638DBED9DFD6B482AD6C3C160006266196B8CEAB96611C0000000A2F70BCF00100164082ABB9D701FEA55C070718507CB2D0E8DA9F5E3537529BE7F0E8B46E2F192E5D97C6DFC97B361D3B87CDDCD5994B12000E377894A9BBBA794016265AAAD0D6CDCBB585381100103B88C5CDD1CCCCB07414000033747061527AB0D5BE68394075A99C5A5684B4CBB589380A0D124371A9CBD6C5BD9B50180E1852A1C9CFC4CFD0CDBC832E010F5AA8C6C6C5C3B2ADA06A646990A5B6AEA49F9B87530000000000000000000000000000000000643300000000000E639CB5B4AE865B2300000F4876B2BFCBC5A97344150000002B7090B8CCDCD2B188AD78451A020D2664A8CEDCC59F581B000000102E6EB1DF00000F4876B2BFCB01FEA65C0707186074ADCEDED19E5A1F2655A5E8EDE0B85F291B335B97C4DBC485381A4A97C7D5C2863E1100083A82AAB0BBA46E32193162A9DCE3DBC4AF803E08000C3E8DC0D3CAC6C5B06D1A00002B6869655D7DB9E1B1603A457BAA9F534B8DBDC1B6893913101D4282B1CACEBEB9915020152053A5D4D7D5C6C9D3B87F24000461AFB9BEBCB9B5A9A069647183A6B1B5A9A1998C4D00000000000000000000000000000000005A2E0000000000196EA2B8B09F93612100000C427CA8C2CEC9A1723B0800000A377198C2E0D5C79B7EA86F2F130C042F68A6D4E3D0AA6318000000153778B4E200000C427CA8C2CE01FEA75C070718707BABDFEDCF9A522A30599ED4EAE7B66624203A5A9BCCD1C27C3722449CCEE4CA893D0F001A4080B0B4BEA669301A2D68AAD0D7D9D0AF7C3F09000D4591C8CDC4C0C2BA691600002A5962545B85BBDBA55C39477EAB9A5F4F82BBC5C68F3E040517508DBEDADAB5B1893A100F1A5CAAD7D9D4C1C7C8AE732200146BA7BFC7BBBBB9B3976F73768DAEB0AAA4A59C904500000000000000000000000000000000006E3700000000002F7CA0B8BAB58E58220000164780B5D7D6C19C623010000011427094BDD8E3CB9F80A6652E1D0A1D4373B2D3D9CBA6581A00000510316BBCE90000164780B5D7D601FEA85C0707188077B2D9F3D3925429295098D7E6E5B364271B3464A3CBDABB6B352A5097CFD6C9873F1000185187A6B1AE9A6121102677B2D1E3D9D0B67C3703000D458DBACEC5B7C4B55F1500002757585D5F79BDE0B260364E81BAA067598EB2C3BC812E040518468BB6CED8BDBC8C42140E205FB9D7D3D2C6C8C6B2691E001365AAC5C9BABAC2B89F74737085A8B0A7A7A0958744000000000000000000000000000000000054250000000000096AA7BAA59C7B611F0000094B8ABAC3CCBB91632F0B00000C3F759AC8DBDECCA376B572431807113F76B2D6E2CC9D5D1600000014316DA8DF0000094B8ABAC3CC01FEA95C070718907CAFE1E8D89754292945A1DAE7E2AA5D1B152B5EA7C7D0B05E282249A9EDE6D08A360209174C89ADC0BA9A61260B2671B5D9E7D5CAAD7A39050014478ECACDC1B5BDA65D1200001F4A5D5E6591C5D7AB573A4386AB9A544F82B4BEB78F380010235792BDC9C4BABC8C4112102466B2D5CFCAC0C0C3AD631500186CB3C0D0CBBCBEB7996866728AA6ABA99CA89C8D450000000000000000000000000000000000633200000000001A76A3C1B1A1865A2800000F3F81B3CCCFB193581C0F00001B4580A6C8DCD2D0A379B06B3A0B0B1D477BBAE0E1CAA05617000005143E73A9DD00000F3F81B3CCCF01FEAA5C070718A072B1D8E2D19549292B4F9CDBEDEAAE552711326BABC7C6B16E2A295EAED4D4C6873705001E5192B6BFB089421A153372B6D4E0D7C8B27C370100114F9ECAC1BBBAB9A660190002214E58596893C1E2B258303D8BB2A05F507EA7BBB4742A0B0B1C5698C8D4CAB7AD823C1709226EBADFDAD3C4C2C4B9660E002173B0C4CDCBC2C3B19A78756D899AAAADA2A28886430000000000000000000000000000000000633100000000001A6D9FABAC9D89572600000E4189C3CBCFB583542100000013487EAFD4DEDDCD9C6EAF663815021B4C88BCE1D9BFA267230300031A3F70ACDE00000E4189C3CBCF01FEAB5C070718B07CB9E4E9C889422432499BDFF8DAA255241A346EABC8CCA0611F2364BBE0ECD2812F00000A4E96B6C2B1803A160B2B6AB4CADBD7C3B4883D080017549AC3C7B5B5B8A8570C00002D4C5A616C9BBEDEB452354C86B69D5D5085B0BDB46F210001195FA3C2CBD5C7BD803211131E66AED0DBCBB8C3C19D570B002A7EB6C3C9C5B9B4B6A97A79758CB0ABAFAAA6A08D460000000001030000000000000000000000652A0000000000217CAAB7A697844E2100000C4181B9CDCAB28A4B1D0000001A4976A6D3DDD3C19363AE6F411F151D4885B4D9D8C59D63210000091C3E6CADD600000C4181B9CDCA01FEAC5C070718C078ADD9EBCF894B2531519BD5E5D4924D19112D73AED1BE944D19245DB6E2DEC379320100205A9DB7D2B2824017153A73ACD9E1D6CDB9783705001B5C9FC4C2B1A2A69D4B0C0000224C615D6A98CCDD9F4A2E4790B3A8635A87B1B1A66F2100001668B0D0DAD6B9B97A2D10132871BADCE3D1BFBFC4AC530E00217DC4C6C8BCBEB8B093766D6D8AA5AAAEAEAAA28E3E00000000030600000000000000000000005F2500000000002B779FAB90846B461D0000024187C3D2CAB6824A1700000420457CB0D6DECEBF8C6CAD734B190A1F5496CBE4DFC6985B25050000264369A7D20000024187C3D2CA01FEAD5C070718D073AEDAE7D18D4D223159A0D8EADDA247191D3B73B9D5BB8C4D202971BFE0E0C78131010021599BBAC9B276320E08326EB0D8E6DAC7B47D3500011A5FA5C8C5B5A49E974D0A0000144C6C737A9BC7DDA14A344897BCA7695185ABB5A05F1800022A72B8D8D0D1BDBE81360A052976BCE1CDC6B0BEBDA44604002E89B8C9C4BCBEC0BB977A6C6E8BA5A7B0AC9E937E4600000000060000000000000000000000005B2400000000003586B1A99480645220030012427FB3CBC4A7823F0E0000001F5182B3D8D9D2BD8D66B0724520111A4B8BC8E8E7CAA15B320A0114385A749CCA030012427FB3CBC401FEAE5C070718E073AED1E6CF8740252C55A2DFE7DF9943171B3C88BACBBE89441F336EC2E4E2C6792E05001E63A6C3C4B36A3110133077C3D5DFD3C6B386400A0010599FC4C6AEA9AA9243000000214E6C7D869AD5E3A046294592C0A45E5486A9B099661D000D276BB8D9D6CFBFB875310B132974BBDAD2BFB4B8BC9D4806002E83BDCDCDBFB9ABAEA17C656886B1B1B1A6A99D8D4600000000040000000000000000000000005B2000000000003482A4A78D7669481A02000C3280B7D0BFA37E3E0D0000041A4281AFCED8CEB18462A86A4B2313205D99CBDDDDC99D5E2C020617455C7EB6D602000C3280B7D0BF01FEAF5C070718F080B5E5F3CE8841282B55A4DFEFE290461C1F4084BED4BB793F293471C6EAE3C1702404002261A0BDC8AD6C2A0B153174B5D7E2D3C3BB8C4204001D5999C1C2A69EA99849000000174F6D7E81A4C6D1984B224A95BFA46A5E95AEB498541000062E80C7DDCAC5B5C280300E132F80C9D6CCBBAEC2BE984400003195C1CFD2C7C2B4B1916965688EB0B1AFA0A1988A4600000003140800000000000000000000004F2000000000002E81A4AB8B715C441E00000A367DB3CEC69E733C00000000295088BAD7D3D3B68066AF79532F23255299C7E7E2C3935C2C08011F4B6477A0CB00000A367DB3CEC601FEB05C0707180077B1D1D9CA88411624539CD9E5D786461F1C4990BDC8B27230182B75C1EEE9C373200200225EA8C5C6A964200C0E3078BDC7D5CCBCB18C4412052761A0C9CDAA9DA3893F000000205573848DAACED8943C2D4990B6A4695D8AAEAF84490C00032C88BBD6DCD5CDBA72361010337FC0D5D7C3AEAFB7984200003E95C4CFC5C3BBB4AE906F6A688AA5B7B5B0AE948E3A0000000E191002000000000000000000005610000000000031809BA5836F583A120601032E7CB5D1C9A774390C000000234787BBD0D4D0A88C5DB37D5A2E1626589DCBE7E3BF98613812001B566D80A8CE0601032E7CB5D1C901FEB15C0707181079B4E2E3C27A392126569FD2DFCE7E3810204795BBCCA87537223378C8EDE8BA702400052969B6C5CAA35F1E000E336DB6C4D5CBC5B386460B0B275C9DC9C6A7A5A2853B00000020557C8999A3D5D18333294C95BDAB685E8AA9A684420500053186CCE2DAD4BBB072300D123785D0E1DCCEAEB6BF99430300459EBAC3CBC4BFBBAD8F746B6A8BA1AFB19DA698894000000008100F0000000000000000000000582100000000003C81A89D846C553E1E0E08173D86BCD0C1996B300B000001204684BDD5DACAB67E56A27F5A3F182467A8CDE1E7CC975333160F265F6A709FCA0E08173D86BCD0C101FEB25C0707182073B0D2E7BA702A122454A3D0DAC17D381F28589DC3CCAA6726182F7DC8E8E5BD681601002876B0BDB89F631A0413387ABBDBDCD8CFBE893D060028609DBDCAAA999A7631000000245D869DA2BED4C181382F549EBEA3645E94B1A5742E0000022B8CC4D7D2CEC5BC7C38181E327FD2E3D7C5B0B7B28B2D00004597C2C4C0C4BDB7B88E76686089A0A9B0A8A59C87440000000B12140E00000000000000000000501E00000000004086A79C7A5949311601031A377FC2CFC09362240100070D3E5F91B7D0D4CDA36F53AE785D31112660A0D3E6DCC3985C33120722607983A8C901031A377FC2CFC001FEB35C070718306CAACFDCBC6C321C2F64AADBE2C07D3615245AA7CEC79E6021153381CEE9E5C26B2600032C79B6C6C49F5F200709356DBED2DAD5C1B88E3E17143468A3BEC1A6938F6728000000226D92A1A3B4CCBB792221549CBEA8796990B1A570260000003284BCCFD4D1C8BA793310153894CDE2DAC2B2BFB78730000154A1C2C2C7BCB3A3AAA5816D62809FAEAFAAA4938B3D000000172621010000000000000000000054250000000000428DB0997559422B07030F1C3B86C5CAB58D642C070000042A5591C3D2D0C3A3775FB186633B262F62A7DEF6DFC48F5A3717021B677D849EBC030F1C3B86C5CAB501FEB45C0707184078ADD1DAAE672B1A2952A2D3D6BC82300D245FAAC9BE9C5E23173876D1E6DEC96D1C00003584C2D6BDA7591700093781B3D3D6BBBCB3933E100731649BB1C19DA29968240000002D6298AEB1C4D7C36C1E1A4A9ABCB47E6A8FAEA1692C030005358AC4D7DDD4C2B270271010348CC3DED8BFB0C0B6832D000350A3C0CDBFBAB2BDAAA58C676483A0ACB1A6A1A0943E000000232F180400000000000000000000562100000000004484A99773443A30141218254A8DC8CBB78457210400000B234F8CBDD3DCBE977859B286643B162964AFD3F2EAC292633E26053A6F7F85A1C21218254A8DC8CBB701FEB55C0707185076AAD2D3A96E39152C4A9BC9D6B1733D162368B3CEC89F501D0C358DD2E4EABE5D1901063983BCBEBD9D5D200313376FAFCBD6D5BAA68B46131A3D7CA7BABFA7898C5D18000000347694B3B0B9D0C5672019529FC5B7816F9DB6A9651E000008428FBEDEDFD1C3AF6A2A15153D92CDD3CDB9ACBDB78020001067AFC4C3BAB0B4B1A78D79655F83ACB4B2B0A9A18A3E0000001E33200D000000000000000000005A2F00000000094E8CA796693C392C1A0C0B194494C4CEB3845027040100091F5192C4D7D8BF946B57BB885A421E3269AEDBF2E7CB9C64411C0F33727F8FADC10C0B194494C4CEB301FEB65C070718607CAECCD7AC52281B285C9DD2DABB6F2B212A67A9CCC1975420254082CAE3EDBC541700033C7CBCC5BCA45A1201133175B1D9D1C5C2AB893708144274A5B3BCA9A8835F110000024088A6BEC0C5C8B1601E1954A9C5B28270A2CBA3541A0000003E96C7D0D6D1C3B1692806114091C4DFD8C2ACBFB37322001563A6BFBEB9BBB7B2B29F745963879AAFABA4AA9B834000000022422907000000000000000000004D250000000000478DA4986B322510080C0B1D3C88CACCB3804C1C000000112A529BC6D0CBC098715BB28162381A2E70B1DDF5E5C38C583C291A437E8087ADBC0C0B1D3C88CACCB301FEB75C070718707FA3C2CE9D59241320619AD2CEB46B2E15316CB1C9C38B441A163E79CFE5DCB35A13000A3E88C5C8C39E5C0D000C3974ACD6D0C7BFAC86340D224F7CA1B8BFAF97804D18000005408DAEBCBAC9C8A85D171E58A7C8AE827896BE9B4C0C000001379AD1E3DBDAC7AC611C04123E9CD0DBD4C2BFC3B66E18001162A2C6C4CBC0BCAEB092765B5E7EA1A2B0ADA39E7B2E0000042E433312000000000000000000005B2000000000084E8EA18E5C3016110E0B151A3A82C1C9AD7043150108040B244C9BBFD4D7C2996D5AB3896845213568B1DDE8D6BE88634C2D183788888AADB10B151A3A82C1C9AD01FEB85C0707188074A6B5C08D4A17152F61ACD2CEAD6325133571A9C6BC8E3E10193787D0E7E6B85B1200134F86B7BEAF9F5F1900083373ACCFD2CDC1B681360E134B82B1B7B9AE967C461200000D4A83A9BBD0C0C39F49161757A2BFB293809EBD9852090000003A9FD0D9D9D1C4B2682E1413439AD0D9CEC9BBB7B96615000E6EA7C1BCBEB8BAB7A19A765065849CA7ABB29F988F3500000A353F240F0000000000000000000054230000000013639FA38F5830100F102426274090BFB9A56C340D070C08102C5395BAD2D3B9936C50B0896E47212F6AB8E7F0E5B58C5F432C265388868DA6B02426274090BFB9A501FEB95C0707189074A2B7B1974D1D0D2C63A2D1CCAC5E291F3A7EB3C6BB853B0C153D8BCEE5E2AB561903124893BABFB39B4E100004376EAFCADEC5C2AC823B142967899DB3B5A69E78390600000F4DA0B5C7CBC2C69B3B071752ACBEB98D82A5C09A470600000E4097C7D6C5CBC2B268280D1341A0CDE8D6C5C1BBB36919001679B3C4CABBB1B4B6A591794E668AA0A9B0ADA29A863A000018374A3113000000000000000000004D26000000001357928F80552509050B19252A4289C4BFA06833080106040C245FA8BBD4CFBC946655AC795E442B3472BBE7F5E8B48F61422C1A4888888FA0AA19252A4289C4BFA001FEBA5C070718A07392B8B57E2E0B062F66B1D2CBA450180E3D80BED6B9823413113F93CFE3DFB94E13000D5893B1B3AB97501200063877B3CAC7C3BBB07E3B101F5B8BA8AFAAA59675340C00000656AAC3C4CEC1C394421A2257A5C3BC8D7EA8B5A245080000074595C9D6CFDABFA963261215509CC9E1D4C9BCBBAA5E0E00247CB6C1B7B9BAC0B1A6966656638CA1B0B0989A9D7F3000001641523B0E0000000000000000000062370000000026649B9D8D4A1E010011252C234690C7C398662F0A060801122760AABDD6D1BC996D57AC8E6646273676BFE5F3E0B98463473D1D548C8B97A39F252C234690C7C39801FEBB5C070718B08095B4B082321916356FB4CCC4A458231A3A86C8D9C2823215114085D7E5D8AF510D00195891C0BDB7975A190012407FABC6CFC5B8AB73340E276B9AA8ADB2A5926C2F0100001254A3C0D3D0C1BA873C061C62AFBDB6898AAEB993470000000B4899BFCCCBD0BDA85928141A4AA3CDDCCDCCCABFA9611600217BB4CAC7B7B8AFACB388644E668FA4B1B4A69F9B7C2000002153624311000000000000000000005A2F00000000306D9A9A7E48150504182A2123448BC1C18E5E280A060C00142764B2C8E3CEA7806059B98B6B4C2C377BBEEAF0D7BA8A63553323517A8093AFA52A2123448BC1C18E01FEBC5C070718C07097ACAD783F12102E7EB7CAC39D5323224085BED3B78731061A4398D1E2E3B4520C03175C96B0ACA4954F0D000C427CB7C8C1BFB7AD7A36122D6E92ACAFAC9E976A2C000000115BACC9D1D3CABA7F380B1D61A5C3BD8E88A4BC983D000000054F9ABECBC7D5B79D5229181D4D9FD0DBCCBFC9C4AE5C09002F84B5C4D2C4B9BBB6A58360536287A9A9ADAB9A96762E000026526C4F1B0000000000000000000057250000000033789BA3844B1904001C352F2A428BB9B490531C0400111510306CB4C6D4D2B1875E54B18372493B4986C6E2EED8B67A5450351F54848DA2B2A2352F2A428BB9B49001FEBD5C070718D07596A9A06D30150A3A77AEC5B7944C1724488EBECEBD833708083D93D9EAE4AE400A002174A5A7A1A697491300134484A8C5C1B2BCB06C33133A74A0A9B7AD9D816429000000195FADD0D6C9C7AF7C2D031765A6BFB79D93B1B88C39020000074A99BBCECCC5B9A45E2919174DA2CFDBD4C9C3BAA24F0D002E87C1C9BEC4C0B4ACAC97694B698DA7A7AFA59693751D00012A63775311000000000000000000005839070000093E75969A6F3D1D0C0B1F3736203F88B2B68C441700070A020B2C66A8C1CFD3B0865253BF8070583D4391C1E7E7CFA986616548325383929DA7983736203F88B2B68C01FEBE5C070718E0809BB7B07D32120F3C85C4CFC38F521A1C4C98C5C7B37734060C3789CBE2E5AF491200206DA0B1A6968D480D001A5486B6C9BCA4AEB06733233580A7A8A6A9A080571A0000002473C0DCE0D6D0B1721F021D61A8C3B09693B5BC9639000000094C9DB9CBDDCCB2964C23122156A6CBE3D7CDCAC5A4470D083A93B7C2BCB7BAB4A3A483654E6696A5ACA9A0A092621E000531667E551300000000000000000000603B00000007427C9CA08B460E0000123331304D95BFB6833E0F000C121514386AA7C1DED8A98D695BB07E725B39498FCAE6E4D3A981594F32285D8D8691AE983331304D95BFB68301FEBF5C070718F07A98ABB2752E050A3C80C4CCAE8A3E15164B9AD2DCC2732A000E4197CFE1E2A54805082E74A3A39D977F3A05081A5082B2C0B6AEB9B3752F102F86B1B1B6A7927D521A0200001E6CBDD9D0D0C0AD6F28000B52AABEBE9E9BB6BE91340000000F559BB6CBD5D2B9954D211A1E4D9AD0DADBCFC7CCA8470C054495AFBEC1C0B3A8ADA171574574929BA2AFA9A08B6A1B000840697C5A22000000000000000000004D26000000003D809F9B874A20080A203C39264D92C3AF7C370000000800103682BBCCDBD1B087655CB97D6558464C8DD0E9E3CBA07A4C574331617A8998A89C3C39264D92C3AF7C01FEC05C070718007DA1ADB0702A0D1E428DC8CDBB8A3D1A265EA2C7DAC5712302094399D4E8E4B743050029709E9DA1987A360704265897B9BEAFA4B3A46D281A4088A6A8B0A78E8554170000052E74BEDBD9D5C2946117001B5BB0C5C69C95AFBE8D33010000004896B9C0CCCAC19757291A2750A2CCDCD7CEC3BD9D410C114A9CBBD0CBBDB1B2AE9B744B476D9DB2ACADA3968B5D23020C3E6F7B491600000000000000000000592E000000053D7E9DA2794311000015323D2C4B9FBDB1733713030F08041B407DB1CED9D2AD846564B983705C4C6091C0E0E2C48B6B5C62422757748BA2AA84323D2C4B9FBDB17301FEC15C070718107596A0AC641E000B3D8EC5CDAC7B3C16195AA5D0D8B96F28000B419ED7DEE7AA4301002D82A4A4989478370D001C5594B7B3A4A4B0AA712A1A4989B4AFB3AC977D51240000032F75BED2D5D4BB9D561200216EAABFC2A8A2B5C191300000000D5195BBCECAC5BB9A56291E2C4F97C7D7CCCCC5CD933A0C235CA0B9C9C9C3B9ABAA9A6F49416F91A9A5AAA1A8855614000A457A774D18000000000000000000005E2F0000000C4177A0A2793A0800001A394136529BB6AB6F370A001C1608174082BAC1DBD1B18C736BAA81706A4A6091C9D4D4BA8A6D5B5A432461848397A98B394136529BB6AB6F01FEC25C070718206E8B9E9C571000093290CBC19C70301C2E5BA7C4CFB6671A02054D97D5E8D9B44002033C7B9D919C997B3F0D001A649DB3B0A498ACA9642E1C4F8EB8B9B19E866B4A2307000A2687BFD2DBD6C68F4914001E63ABCEC5A0ADC3C2842C0000000D5297B1CACECCB8884022151C44A5C6D8DDD6D0CA984108115B9CC2C2C4C5B5ACA89D6446477495A4AAADAEA584521900174D7D78511B00000000000000000000563F0600000D4A83A1A679420F0001184A3D2E509CBCAA6D320C000E1312194294BFCDD7D3AC907270B2786B61556C9EC9DDDCBE8B6952584031607B80949E7E4A3D2E509CBCAA6D01FEC35C0707183071899D9D55190000388CD0D2A9712E162868A8CAD3BC671F010A469CD7E4DBA64308093D8497978B8E653206061F5DA9B9AE9C9AB5AB652C234798B7B8AC9D8D71440900000A3182BECAD9DBBF843F06042769AFC4C8A8A8BEBF882F000000245997ABBAC0C2B49B4F27202B4A93D1DADBCCD0C68F3401195998CCD2CCBFB8A7AC94623D48769EA6ABAEB5977D4814002051736F4C1C00000000000000000000533700000013447BA19D783F0D00001B4C423656A6C2AD6C280300081C0E204D98B9CAD5C8A4A27266B2806F60546A9ECFDFDAB9835E464E2F19577D869D9D8E4C423656A6C2AD6C01FEC45C070718407591AAA9651F00054099CCC89E682F184170B3CFD0B36820000D499DCDD8D1A639050F44919B90878E6A2803012970A4B6A5999AB2AB6133294D9BBEB7B5AA8A67480E00000C388AC0C9D8CEBE84450600236AADC3BEA1A1B7C37F2F0000001D5F91AEC0C0C6B58F4930282B5095C6E1DCD6CFC5983B0A1D6AA4C2C5C4C0B5B3A98D53314D85A1ACA5A79D9A7E3B0D071E507F804A17000000000000000000005E34000000135E95B0A082481600002B56453E60ABC4A85C3010000E1A162351A0C4CED0D5B98D6B60A87D6E6C5E90AECEDBCBB2815C4A4C3A2A607E8694A17B56453E60ABC4A85C01FEC55C070718507394A39C4F15020C3C92C9C5835C271D3C7FB8D1CDB96C190012499FD7E1DBA340050C4294AC9183865B2100002F71A1AAA09497ACA25F2C2F589AB9BFB09E8266400D0A000E429AC1BDCDD6BE7D3B07002570B2C3CFB5B1C5C1832400000011568BA8BDC9C7B98B482C2B2D4B98C7DCD8CDD2BE8F360A1D71BAC5D1CDBEACB2A67C442752839DA1A9ACA19A88420E00215B87744719000000000000000000005E3D1B000A215494BBAF83461200001D4D533E6AA9C39B622900000B1417276AB3CFD2DCD1B38E725FA673606C607DADCCD5D8AB8054454928265D7284A9AC804D533E6AA9C39B6201FEC65C070718607C9BA196480E000C4E9FCFC18C5E1F0B3486B6C9C3AD601B05154EA6DBDBDE9B38081145969E7E898B582201002E7DADB0A1938FAAA356241D549FB9B3AFA182623D120100194D94BDC5D0D3BA772A02053174B2C3CEB6C0C2B976270000001B569AAFC9CED1B88A4A36292D5892C0DED5D6CCC0923C031C6DABC6C1C0B4AEAEA78B4D334F859BA5B1B09E9778370100255D86744E1A000000000000000000004F380F000019578EA59A7A32010000104A423570B0C39E66260B030C1B183277A9C3C9DCD2B3876B5E9869646C6587A6C5DACCAC7E513C442522526C7AA6A1824A423570B0C39E6601FEC75C0707187078979B914E110015519DD1C1874A201E4788C9DAD0BD630D001151A3D3E4D697320B0E4897987F848D531100053282BBBAA39493B3A75E2D2B5096B8B89E98745834160B0B20539DC2C2C7D7BA712F0000266AADC0C9B7C0CFC87A17000000326098ACC4C4C9BB893F22242D549BCFE3DBD2CFC18F2F0B2B7CB3BEC5C0B7BCADA883452B50829DB3ADB5A29C752700042E5E7C69461300000000000000000000664B290005246493A7A573330900001D4A524D7AB0BCA4631809021628193E79B2CECDDDCDB08C71549370687C6F8EB7C5CFC4A77845322D16214F698CA7A17E4A524D7AB0BCA46301FEC85C070718806C839B91440A000B4093BAAF793D12194B90C7D6D6B4590C001355ABD0D9CF9A3A00134A949D8288804D110003388FBEB7998E96BBA1541F2554ACC8C3B2967B5A3A1C0F0A114FA4BDC9CFCBBE652300002E65A5C0BCAEB3BBB56D19000000296E99A8C1C6CEC785422523314A90C7E7D7D3CDBE8D320D3283B8C9D1C3C1B4A09970382852899BADA7B0A39D6A21000B407A94774311000000000000000000005A56391B182B5F96B5A3733C0200072C56575580B9BA9A5B2300000F19164287BED5DAD9CAB98B705A8E6C63717086B3C2CEC2A97950433222194E6B81ABA57556575580B9BA9A5B01FEC95C0707189074888C803F0A00003E9AC0B37B3C1B1D569CC4CDD2B359150015549BCDDDC7882D041556999F7F8C7B461000063683B8C2958B94A79247232254A5C4C5A9906C5733170E0C2660AEBBB1C9D1B46B1D00012E6DAFC6CBBBB8BBB27520000006316A88ADC5CFD7C1883C2B262D4F94C3DAD2CEC3BC83300C358AB7C7C4C6BCC0B49C7832235A8EA7B1ABAFA9955C150011457388733C0D000000000000000000005147351A272F729CB1A171350000002A4D5E5D8AC2B9964D0C00000A1A1F518DB5CBD1DCCFAC91675B895E5775758CAEC2C6BE9F7646352619295C7286A79E764D5E5D8AC2B9964D01FECA5C070718A0778593833A02000545A3C9B9773D151C569AC5D0D2AB5410001651A7D6D0C3883100114A9BA4888582471100003584C1BC9390A4B59C4921254DA3C8BDA4916C58331D130D3166B7C0ADC4D1AA5C2D0000287BB5BDCBB1B6B8B66F160000033D6C91A9BDBFC4B27B443C26344B93CCDBD9D4CFC1822A0C3F8FC5C9C0BBB5B9B0A47930154E899FACADA4A7975D09001146768E73340A00000000000000000000555744221D386F9DB7A97F3C0A00001E4D596288B4BE8E4E1201000B151D5295C8D3D6D8CDA7896B5388565A6F7B98B7C3C5C5A870582E2B102056718AABA0784D596288B4BE8E4E01FECB5C070718B07083907E36000002449EC3AB6D310D1850A4CACBC3A95C1D001256A4CEC9BE833502134F9FA7888976390A0003408EC0C19F9998B1A1501E295EA4BEB09189744D331E1216316FA9BBA7C8D9AB551100002978B4C3C2B3BAC5B265150000083F7A96A6BBCDCBC1753F2D2A374F89BFE3D4D4C7BF8434233A84B6C7CBB5BEB6B7AF76281A5495B2BCB4B9A58D510000094D7C8B6F3D0D000000000000000000005D675B44395086AEB4A581370D00002253586894BBB4944D1C06030F201C58A2C5DFE0DBCFAC8A604A7F555A7C818EA3B5C3C99F70502D2E181E5B6F85A7A66C53586894BBB4944D01FECC5C070718C06F848B763600000041A3CAAC682D1122569EC2CBD1A95307000954A7D8CFBC822501114F9DA28C86703708000F429CC7C79F9499B0974414245BAABAB28B7962582D191D1D2C77C1B9ABC0D3A74E1B00003885B2C8D0BDC0C9B66615000007407D98A5C4C3B7B8763F27232E508BBDDCD3CACCB97722164597C6D1C8B4ACB9B3A169221F5CA1B0B2B3A5A48F5401000C41849A7340150000000000000000000052566C4E415B90AEBE9E7A430A00001E4D6374A0C9BC78430701000C24265DA1C0D3D9E7CFAB81685183534C7A8E989FBBC4C59B693B1F1813245C7993ABA5694D6374A0C9BC784301FECD5C070718D075848B7E2C00000243A0CEB1722C071E60ADDAD9C8A95718001460A8BFCCBE7223000B48979C8E87742E0300153F9FC8C3A39A9DB58F401A1D61ADC0A88376695436272D263877BAB29FC0D2AC4D150000327FA7C5CBB2BBBDB45C0D0000084688A6A9C4C0BEAE68352F2224599BCBD4DDCFCAB56F24144897BCCFC7B7B8B5BAA5681F195A91A7B1A5B29E8E3B00002664888F74320E00000000000000000000576C6C574D619FBFC7A78A3E0F000422505984B4C6B28340160E00001B1E5CAAD3DEE0E0CAB788685477545977869AA3B1C1BD996E3B1D2212225E7C9DB0A26F505984B4C6B2834001FECE5C070718E07984867328000000409EBFA569310A1D68A7CBCCCDB4570B001064ABC8D2AD6F250517548F9B929172320700104A96D1CFB19DA5B38C320D1E599EC1A77E7A6B4E271E2927407FC1AEA2BBC6A5561200004185B6C3CBBAB2C0A4570900000B4E94ADB8BDBEBFB2654131172C5590C7E1DBD9CDBB6828194994BFC7C5ADB4B0A79B5E14186D9EACABB2AB9F803800001E5F909C72310D000000000000000000004F555C504B5893B8BBC5893B04000013506479A5BFB1703D0E0000121C235DADDED6DFD8CAAB89605073574F7893A5B7B5C1BE997C4E461F0D21587896B0A071506479A5BFB1703D01FECF5C070718F07984816A200000003D97C8A55921022363A7CDD3C7AC5404001761AED0C4AC651A00093C8E9C928C763000000F56A5C8C0B1A4A9A97C311B2962A1BA9F7A6B6354362B2E324E8DB4B5AFC8C99D501200003587B5C4B9B4B9C4AF52110000125897ACB1BFC0B5A06336221E26569FC1DBD0CCCABC6E1C15479FD0C5C7B9B3B8B0A7650E165695A6A7AFB0A8812F00002867949467300700000000000000000000555E6F6D697EB0BEC4B074460A00071B4B6181BBCFB2723D110000131D276DB2D6DADFDCD7B59C6B44694B547A8C9FA5AFB8B0A5703C170B0B225D8AA0B5AB6C4B6181BBCFB2723D01FED05C07071800718C86631F00000044A3D9BB672300256AADD0DBD5AA550D00165EADCDD2B16614000844889A96987B3404000F4A9BC3C9ACA3ADB07C2E112B62A2BE99736A6947382E3235458CC9B4AEC1CFA5501300003F96C0C7B3AEB2B6A5560F00000E609DA6B5D1BAC7A75B2F22222F5B98CCDFD7D1C7A966201145A0C6C5CDB1B2B9B29A4F101B6D9DB1ACA9A89A7B2100002F69929B6B330500000000000000000000505C67657484B6D2D6BA803D0F04002E5B6089B5CEA460521606000E202A71C6DEDCDADDD2B08260436541557F9DA4B2ACBCBA95684419160E2F6D91ABAAA0695B6089B5CEA4605201FED15C070718108387815D170000005197C6B0581A011D69C4D6DEC9A6480B001460A2CBC6A05E140001418BA7B1A0772B00000E45A3CCD6BDB79FA7692E152169ACBE95716A654D3B4946334692C0B2A7C3CBA3490E000043A0C0C1C1A0A9C19F530000001D6093A4ACBFCAB8A163382B2A31599ABFDCD4C7C8B761241A57A1C7C9C1B0AAADAA93450A2167A0ADADACB49A751A00002F7394835C3711000000000000000000004F596967638BB3D2D2BB83430B000A1D4F7897BAC5A76026060005191A2875BDDCE3E1D9D1B581492B5D3D598A9FA9AEAEC1B79A5E290903132D6B9CAEB092614F7897BAC5A7602601FED25C070718206F89805D160000004A9ECAAD5B19001F6AB3C9C9C5A84A09001A63ACBEB5A05309000238809CA1A3782B030017549DC1D5B6ADB0A469260E286EB2BEA5746C68413547503F488EBFB7A7C3CBA2480D00004696BEC0A69AA6BCA5560800001B6CA8B5B2BBB5BD924A28261F3257A2C5CCD3CBC3A2561B195BA3C3CAD0B9AEB5ACA04B0D1C69A4B4B4BAAC9D711200002E779A9676370800000000000000000000606E81857DA4C7CED7C78C5216020D2A5677A5C5C99F5A2B090600191C3D84C6E1EED9DECCAC8862345532407E9FADA9B5C8C39E603114100D2B7798B4BA945D5677A5C5C99F5A2B01FED35C070718306A7A754D0A0000004097BCB06221001F6CB1C9D3C4AC4C0C002260A3C4C79E4A040002307DA6B0AA7E2D040011519EC6CDBAAAA29D6623122966A9BF95737271472F45513C4D8BC9BCB8CBC69A470800003E8EBDB5AAA3A1B8A3460A00002173A6C0CBCCBFBA924E29352A2C649DC5D6D9C9C1A24B1D2B529BBFC7C4AEA3B0A99543061B71A3AFA1A4B1A26E13000039849895673910000000000000000000004E638B918999C8D8D7C2834510000B204F6CAAD0D29E5A3008040B20253A87C3D8FFF3E0C79B7C4F295745568FA3A8AAB4BDBC9D683811070F2A759EB2AD95544F6CAAD0D29E5A3001FED45C070718407E8A875C0A00000052ABCDB25E1C0A246EB8CFCABEAA5104002165AEC9C48D4806000037749EA8B6862C00001C5BA5CBD1C3B8A5935A200A2969AEB3A07E756D523A495A444F84BDBFBBC9C59E4D0D0000428BB9B09D9697C69B4B0C0000276EAAB6B6BDC0B78848282B1A346C9DC9D7D3D4C7A04F1A1B5F9EC3C5BAAEACAAA98F4108277398B4B3AFA0976C1100003B869D9B6336090000000000000000000054617F938EA0BFD4DAB58B4F11080A2250749FC4C49058191426101424397FC5E2E4E4D3C19F6E4F2D583E6190AFA8A2AAC1C3A774420E1416326C9DA8AC904D50749FC4C490581901FED55C070718507B8F8258030000004E9DCEB3661B012470B1CCC9C6AA5014092266A9BDBE97480400012F6F97A8B68F3300001451A3C9CECCC2A37F5315113476B4BD9A7C756A463C5B6A4F5F93C5C4BDC5CB9A3B080000429CC1B09B8B97B69E4A0C00002676AEBFB3C7BDA980452C2B2F3875A8C5D1CBC4BE954212225EA0C2C1C6ADB3B2B08B35021B75AAB6B7B3B2A2680200034787A098632A03000000000000000000005C6C8D929AA9CED5D8BB95571D0210195D778DC4BD9151280C060B151D3787CDEEF5E6D9C1A1724625564F679FACB0AFB6B7B59A583412070F3178A5B3B7904C5D778DC4BD91512801FED65C0707186078827C3C00000000419AC5B36B1D071E64A8C6D5C6A94007002674A3B2B7852E00000534729EADC69337000016559CBCD1CBCCA9804D17143071ACBEA4778073483E596A4E5891BCC1C9CCC8993B0000024593C3B394889EB48D420F00032979A3B0B7C4BAA97839272C2B4680AAD0D1DECDCB933D0D20699CBACABFB6BDB9B78F310026738FA7A8ADB1995B000000478E9F94673002000000000000000000005C628190A6BDDFECDDC4994323180D2E5481ACC9CD8E4321100E0C171B4689D7E7EFD8D7C0AB793F2054405D9DABAEA6B1BFBB995C2C1409104685A8B4AE884B5481ACC9CD8E432101FED75C07071870697E7638000000004497BAA9631D00226EA5BAC2BD9F5109072E72AABFAF802F0000012D67A2AFBC874002001A5197C0CCD4BE9E7640130C3177AFB79D7C7A75554F6B784F5D99C1C8CBBFC49F470000003F96C9B68D8198C19941040002327AA8C5B2BBB8A36437322B273E80B8C7D0C6C0BC8838112564A1C3D1C2B4B3ADA3812D00236DA8B7AFADB49A57000002458CA194693205000000000000000000004F5A7B809FBFDDF6F3CF91511F08031E4E75B5D1C18F451F100F0E1821418FD5E5E1D9CDC1996B3B31524A72AFC2C2B3B4B9B58750240E02153785ADB7A87A4F4E75B5D1C18F451F01FED85C0707188075796C39000000004797C2B96110002163A9C1C2C2994309002C74A3B7BA7E2F0000001D5C91ACBD923F00001858A4C7D5C8BE987340110E3A6BA6B99E878673544F6867565F92BECDCACDC88F36060000419FBFAE887F9CB99A40080000337DB3C1BDC6B5976C2E2E31304581ACC1C8C1C2BD86360B1F70AEC9C6C6B5B4BAAA7D28032276A5B1A8ADAEA1530000034F88A49F6633060000000000000000000045627E8EA6C0F4F4DFB3805A1A091526587DB1D0C477370E0D12171A264599CDEDDDD3C6C0996A422548426FA8C8C3AAB6C0B3985E32040C174881A5B8A47F4A587DB1D0C477370E01FED95C070718906975773F000000004693B4B06D1B001E68AEC1C5BD983D0D10396EA7C2AF7D200000001C588DB2B386390B00225EA2C8D0C8BE94673110113A76A4B29F848A7F535674775B5F96C1CDCCCBC89A400000004397CDAC7F738CB28A3D00000C3B82B1C1BDBFBFA3642F2628344A8EB5C9D2C0BCB6812A0B3173B5BFCCC6B7B3B2A5761D002C7794ABA9ACA7985300000D5A90A79264301100000000000000000000515C7498BECAECF4F4D5AF622B0C12254984B8CEC2883C1F1B181F18234E9EDBE4E8D9D6C4926A3B2E3F4D74B0C5C4B0B2BCBB91532B0E0815418BB1B4AB7C414984B8CEC2883C1F01FEDA5C070718A0757A6734000000004C9BBCA5621B001C60A8C3C1C296451110397A99B4A978250000001B5B83AEB9943D0703265E9ACAD2D4C69A5B2303093664AAAEA08E8E775657877B5A729ECADDD0CABB943B0400003F99BBA27B6E85B08F3503000A4383B4C1B6C3B69B54342A332D529FBED3D4CAC2B2832E0A296EADC2C7C6BDADABA0731A022978A2B3A5A3A8965200000D60929983652D03000000000000000000005B648EA1B6D8F5FEF4D2A36E310D171C538AC3D9CF80401A1E2222262D4F98D9E5E0CEC8B692673528474C78B8CDC3B5B6C0BB864B27120B1A5495ADAEA07241538AC3D9CF80401A01FEDB5C070718B082856A32000000004E96BBAB681A001C6AA8CFC2B59A410A184785A7B6A7701D000000215B8DABB48E3605072E61A1C0D4D5BC9456270B1037729AAC9F8D918059648A876277A1C9D5CDCCC1903E0B00003C8CB697757188A97C2F0000183F86B6CBBCCBB79250353133215097BBC6D1C9BAB67F2510317CB0C9C4C7BBBAACA26818002F7AAFB2ABA8B09448000002689C9695602D0800000000000000000000575A7C97B3D1F5F3ECCAA15C29130E1C538CBFDDD081422219262E1E21459DD5E2DCD1C6BA8D6139243B4770B7D1BCB2B7C9BA945720100B225C94B3B19B6B35538CBFDDD081422201FEDC5C070718C07A71642B00000000458FB1A9600C00196DA0C0BBBE8C350C184C80A3B1A6631A0000001C4580A7B5944E19082A69B0C0CBD9BF8950250310357190A5A2939F7F666A8680586DA4C1CECAC3B685380000004198B5A97E7895A87B2C030014498AB4C5C3BCAF8A4B2A3034305991C7DCD2C9BDBC7224092A7BB0C2C5CCB9B2AE9E5915073D869FAAA3A7AF823D00001A709E9C8F5F2B0800000000000000000000536A849CB8DEFEFCFAD29D6835111D265D8FC7D9C283401E162432252258A6D8DDEBCEC5AC93623D2D3E4878B0CBC3B0B0BBB9834D1905071F619DC0B7965A365D8FC7D9C283401E01FEDD5C070718D07D796532000000004C92AAAD6518001A63A2B8BDB990370A154D7E9FB3B466110000001B5381A8B18E410B08306BA1C6D8D2C68D511A030D336B8D9EA39EA27F657B9782617399C3DCD7C8C38836040000458FBBAD806D75946F2B000010558CB8BDBEBDB48B4C342F2F2A69A5CAC9C7CAC1B87B280C337CA7C1D1C5BFB9BD984E05013883A0B6AEA4AE8A3F0000116D9E978A5B270400000000000000000000525F7E9FBDE0FFFFFEDC9F67331A0F254F87C6DBC47C2D1B21343228265BACDEDFDACDC3B29764432D3E4270B6C4C3BDB8B4AD834219110F1F61A2BBC0985D304F87C6DBC47C2D1B01FEDE5C070718E0666C611B000000003D82AA985514011964AAB7B9B7963F0F285C84A3AAA9620500000017517CAAAD9A400C083A72AFCBD1CBBC7B390C0513386790A79F9FAA865D789A85667BACCCD7C8C9AE782B0100002E84BFAA807483906D2A00021F529CC4CBBDC1B3854A31362D3762A9CFCFBEC5BCB16A1C103675AFBCC5CAC7BDBB965814003A85A4ACACA09D892F00001673A2A0906326040000000000000000000046577793B9E4FFF8F5C9A161411D000F5085CADACB823320283F391D2C58A9D9E1DDBEB9BB8E5E3020394A79AFD4C2B8B3BFA0763C1A0B092971A597A58D602C5085CADACB82332001FEDF5C070718F075755B1900000000468CAFA4610E0008639FB9B9B3833619306284A4AAA56211000000184D7EA3BB9E46140F3E80A6B5C3CBBB76340300193864879BA8ACA9846780A08F6F7CA4C1D2C9C5B47D360400003888BEB07D74849A6522000020599BBAC6BDBDAE7E412A2B30315E9FCED2C5BEBCAB6B2016388AB2BCC3C6BFC5AB90540C0A3F8BA9B1A0A1A183320000227BA2918A6A300600000000000000000000646EA9A6C4EBFFFFFFE2A16B3C190E1E508FC7DCBC7C39272C4B483A2955A3D4E0D4C0AEA38B4F34293E517FB6C9BAB7B8B3AE7C3A12031C3876AAC8B4905520508FC7DCBC7C392701FEE05C070718007B765719000000004A87ACA45E0E00136CA7B2B9B3853C16347499A2A9A8600E000000205782A0B39940060F438AB2C8CECDB977330600123B628399A9A5A7816D88A795718DABC7C8C1BAB574230600003380AFA883797990681D0000245A9AC5C3BBC1B2863C252F273367B7D2D8D2CDC0A25D1A094083B3C6C3C1C2C2AC8F490B004391ACA8A4A7AD842C000029779F9C8F683004000000000000000000004A5C8599BBE9FFFFF4D399673510091F538CCCD3C0753033345A492C2557A4D9E0CAA0A5B5945A3324364C76B6C7C8BBB9B5A5742B0F01183A7BB6C5B888542D538CCCD3C075303301FEE15C0707181077785F1D000000044785AD975C0A001768A5C2C2B0863B233B699CA1A994520A0000001D4986A5B496551317448FC1C2CDC4AA6B2300011742647E9FBAB3AD827091A48D6788A6BDD1C9BCA87734080000327CAFAC87717777571C00052B6298B7CBC1BCA36E403B3739386FB3D7D4C9B6BCA15815093B93C2C8C4CDBECBB4884103004690ABAAACA49369260000337C9AA5925F2A0100000000000000000000566685A7BDF4FFFFFFDDAB7030211A234F9AC9E1BE78352F456058352D53A8D3CBC8AFB1A96F462B2337487DB6CDCDC1C4BC9B6C27070617387FB5D4B8914E2B4F9AC9E1BE78352F01FEE25C070718206E72571D000000024489AAA4580D001960A7B8C4B986391D45819C9BA6924E090000001A587A9DB2914513144693BDCECCCAB7762102000F395D8EA3ACACAF857190A686769CB2C6C1B8B3AB752E0400003E85B5AC89787A76551702102F66A2BCBCB7BDA876433C35303D7FB1C6C9C4BDB69F5612134E94CACBC2C8B7B0A4823A0100408FAAA6A6A7A1722500002E79A3A28D612E000000000000000000000069768FA3CCF7FFFFFDDD9F613A1D1C2A5995D4E3CF893A2F457061343053A3D4D7C9AEAA9C77412D252E3B76BAD5CCBDB3B896602C1008203789B1C7A98048315995D4E3CF893A2F01FEE35C07071830746B4E1600000006488EA799621200236FA2BDBBAF7D391A49849BA5A0904600000000215E7EA9B89A3D160E4C97C6CACBCBAF7226050013345882A8B4C0AA8E77879D8F7999B1B9C5C8BAA36F2C0500003789B0A685777C744B0E00002467A0C1BEC1C1A86E493E36314775ABCCCBBBBCB8A1631B0B468DC3D3C5C5BBBCAC8136000A5391B1A9A8A8A9741A00002D89AAAC9D5F250300000000000000000000536585ABDAFFFFFFFCD8A8643720212B4F8CD4EFCF814145587362332751A4D2D6C9ACABA87F3F2222354373BBD4CBBEB8AB9B5D201418224087B0CBB17847234F8CD4EFCF81414501FEE45C070718407872540E0000000E5C89A2995A1C02216AACC5C0AE80362151859E9FA5954D00000009345D88A5AD9949060857AACECBCCC0AE5E140000132F6292A3B8BDB68A728E9B8F77A1BBC1C9C3BFA6612B0B0000327AAFA990817673461100002374A9C5C8C1C8A171413833313175AED2D8D2BBB3954B150A4595B2BCBBBBBBBCAA763000135A9AAAA5A8ADAB72190000397E9BA792623A04000000000000000000005A738AAFD8FAFFFFF8CB975F341A21284E9BD6EBD17D434A6C806A3E3560A2CED8BCA09DA57B442E25304973B6D5CFC7B9AF9459180D0D1C4590BDCFB07C38154E9BD6EBD17D434A01FEE55C070718507A7455110000000C5489A09B551100266CADBABFB07B36325A91A6A7AB9F49000000062D597DA3AA924D131853A0C4C9CCCBB464200000143464839EBBC0AD796CA3B299798FB3C2C8B5B9A5642B0B00003A82ADB3988472663D1300072E73AFBFC5BEB9A261433639334D87C1CECCC0BCB59A520D0E4D96C2C4C5BEB3B1A37724000C609AA9AFAFADA46C1700003A81A1A19E682B06000000000000000000005A6B87ABD5F4FFFFFFD2975C3616182E5193D3E9CE754252618164372959ADD5D6B5949DA77C452D19214272B9D4D0C8B1A38F51200C0E274F94BBD9BB7A44275193D3E9CE75425201FEE65C0707186076745410000000116097A3995A0C042D75B6CBC4AD74302C609B9CA3A7934B08000000245C7DAAB39446131C5EA8D1CFC0CBA9581D00001741688DAEBABAA27D769DA28785A1B2C5C3B9B6A5612F1100002D78B4BB98826F5E3606000B3977A6C2C2B9B69C6A3B473D31458DBAD3CFC8CAB48B3E0C11549DBBCEC6C2BDB4A6722A00075A94A4A1A6A8A06F1000003A89AAB09C6B2D00000000000000000000005F6C8BB1DFFAFFFFFFD79D663B201D254E97D9EEC8804A596B816C33285A9CCBD0B999919D8754211F2A4076C1D0CFBFBAAB8F4C111019324793BBCAB680451E4E97D9EEC8804A5901FEE75C0707187075784F160000002371A2A092491000226CA6CCC2AC6C30336A9FAD949D90440000000A376687A6BA94450E1764ACC9D4D2CAAA5F0B00001C3F6799B5C1BFB27F739A9C857EA4BDBEC6C5B69B531F130000327DACB297916E5C2C00000F3686AEBDC7BDAF8E5E473E332A4A98BAC6CBC8B7B58A400B115795B8C4C0BDBDB19A661B001F6D9BB8B3B5AEA9671400004187A1B29B6631080000000000000000000069779DC3E1FEFFFFFAD89E67342123245699E0F5D2884C5874857136315CA6D1BFAE929FA68C412717283A75BED1CBC3BEA17645221712255FA2C4D9AE7544235699E0F5D2884C5801FEE85C070718807B724F090000002F78A5AC93470D032775B5C4C0AD6028377197A093A39A480600000C416E8AACBE9A3F0D2360AAC5D8CAC3A45C13000012336B9BB6C3B8AD766E969C7D80AEBEC4C8B3B08C4C250D00003380B0B9B19473541D000215497FAAB8B3AFAA925A464B40365490BFDDCDCEC0A8853C051B65A3B8BBB9BEB4B9A15E16001A699AB1B3B5B7AA661100003B8DB6AE96662C00000000000000000000005B6B7CA5D6F4FDFFF2C892543A1C232D4A9DD8ECD2925B5F7986753D355BA1C9C9AB8894A8833E221E2D4177B8D1D4C4BA9F793C13121B3366A0C3CBAB7443254A9DD8ECD2925B5F01FEE95C07071890736F4D0B0000003179A2A88D430B052C74B1C2C9A054223378A5A896979150030000163C678EB0B98E42171370B3D3CEC6C1995314000019386C9DB9B9C3AB74709C987A7CA6BAC4C2BBB49352251101093A80B3AFA490674A2400001C4F8CB0C1BCB4B08E584E51352D4D9CC3D4D9CBBFA58432021361A0B2C7C4BFBBB4AE5D11002070A1B5B1AFBAA85D080000508AAEAD9A62210000000000000000000000607BA2C2EFFFFFFFFED69C683A1B23274F9FE6F6DBA4646C818477432C569DC6C0A78993A7804824141D3A75C0CACBBCB09E80442323264370AEC5CEA77132174F9FE6F6DBA4646C01FEEA5C070718A0747240030000002D86AFAF8E3E10012273ABC7BA9852243D79A59D909F924A0200000F386A89ABB99041142167B9DCD4D1C39E510E0000183A6597B5C1C0A0736F98956F80AEBEC5CBCABB92442E1F0400377CAFB6AB9A6E4717000519558FACB2BFB8A279534E54383E66A0BFDACCBEAC9A723200105EABBEC9C2C9BDBB924A0D00277CB3B5ACB5A99E550C0000538AA8AC9E75370200000000000000000000667790B9E7FFFFFFFFC88D5A3629282F579AE6FEDDA273798C8E6A342F5FA2C9BDA88CA1AA85401E11213E6FBFD7CFC3AA92743A1219263C6CB3D4D1A2693116579AE6FEDDA2737901FEEB5C070718B06C663B040000013579A2A1833500023183A8BBBF9B4D29397EA9A68B978E3F00000016437585ACBA9140122267B4D7D1CEC09C470600001D3B64A1BCC0C3A37675A0A0808AB3BDBEC2BFB0863E2A1D0502377EABB7AE996A3B1900001E5B92B1A7AFAFA770464C583E3E5DA0C7D8CEBFBBA17622051363A6C1C5BAB8B4B59F551001327CB4B1ACB3A5A1560800005B97A5AB9D69330000000000000000000000647193B8E2FFFFFFFFD18C563426202C59A7EEF2DDA77A798C9572392A58A1C0BA9E7A85A1824D3025203A78BFCDD1C4B1896C2F241E253875AFBECDA861371659A7EEF2DDA77A7901FEEC5C070718C0706836040000003790A9A67A3A0403327DAEC0C0973C254A94B19F8895823B000000113C7890B1BA914C121F6FB7DADBCABD9E4B05000017396BA0B3C1BF996872968F7888B0C2BCC6C7B78C4E2E1F06123979ABB6B0A1703C100000256693B0ACA7A9A2704851574C4471ACC5CBCDC6B09B6C2300125E9DB4BDC9C3B8B3964D09003082ACBEB8BBB7A45600000E6099B1B5A8712A0000000000000000000000596F8DB0D0FFFFFFFBC8965936312E2F57A6F5FBE2A97F869492683431579ECAC59F7F89A2894D2E1D22407DB8D3D0C4AA936D3F232F304288B4C9C99657280D57A6F5FBE2A97F8601FEED5C070718D0755A24000000003D90A5A3722900002F769FC0BF8634284C95AD958088762F00000020437791A9B68F3B1A1F6FB6D3D5D5C09B4C0800001949769EBDC6CEA16C6F988C667CA6AFC2C7B9AC834F3A210A0D3580B5C0BAA56A34130406306C94ACB0A8A698694D5C644B3E6EB7D5D5C8BFB49B5819000E59A4B8C2BFBBB8B5984D0500337C9DB4BDB1B59D500A000B6094A3B3A67C2F00000000000000000000005E6680B9D9FFFFFFFFC9865231303635539FE1F0EAAB8275868E63362E5C9DC7BD90757FA48B562F24294180BDE3D7CAA78C5A2D1C2A35477DB2C6C794632D17539FE1F0EAAB827501FEEE5C070718E074712A000000004391ACA6792B00002877A7C1C17F2D23509AB48D7A877C2E000000144E7B98B8BF8038112566AECFD8CEB789460A0008204C80B0B7BABD9A62789E886F85B2BAC5C8C1BC7A53402C06073E7AB0BAB3955F310C00022A64A1B0A19EA59F67445B64484481B5C5D4CEC5AC9A5C14001466A4BEC7BDBDB9B19B4B0000358AABB0BABEB6A250000012619CA5ACA26C2900000000000000000000005F6585AEDFFFFFFFF5CD7A503F322F3B58A1EDF9EABD92928E8367332C51A8C5AF97717D9D854C262032457FC5D0D0BBA282532B1D2B324D84B5C3CF9D50291758A1EDF9EABD929201FEEF5C070718F0735620000000004991AF9D73270008387EB2C5B97B2E175097A99A7A8B823100000020537892AAAE7F32192467B0D2D4D8C5943D0B0604275185B2BAC3C19862799E796471B2C0BDCBBBB57E4C3F3915143D7BB1BBAEA65D2A080000367DA0ABA291968B64546369524E87B6D7D0CACCB1853D05000F62A1C0C2C2CBB9B39B4800003E8FB0B1B7B4AC9B4C070023619DADB1A374260000000000000000000000656B7CABDAFBFFFFF4C68D513928323952A8E5F6E6B28F898688622C2561A9BDAF8B84839C7C4C312B26528FCCDBD2BA907158291A35395486AFC0BA8C4B291652A8E5F6E6B28F8901FEF05C070718006C4D0F00000000458DA18E6D250000327AAEC4AB661E1C559DB197818E73340000002C5A839EACB08735091B59B2D3DFD3BC8F3B00000B28508EB2B5C4BD8A626993805778B1B9B9BFBCB785524433181A4582B4B9AF995E2D0F00104381B6C29989A09762495D694E5589C1D0D6D2C0A6803702001162A3C2C2C2C3BDAD933B02024990BCBCB2B9B19B4600001F6FA0ADAA9A6F210000000000000000000000565F75A8C9F5FFFFF2BC7A4F463B303054A9EBF8E1B792878E8B61381F54A5C3B691627B876B4E3329305789C0D4D7BD9C745125243C375882B9D2C29050160F54A9EBF8E1B7928701FEF15C07071810755010000000045C92A69770200009438EAEAFA55F182152A0B6947A82742C000000315B89A3B3B68035151E61ADD5DBD2C18E4608000829568BB2BFBCB5825865937B5D7CACBCC0C7C5B582514F461B144B88ABC3B9A45D26000009437DB0BE948A8E8863497174535595C7CEC9CEC2AA7E3600001163ABC2C6BEBFC3B8953E00045390A8B4B9BCB6924200002E7197B0A7965F1B00000000000000000000005C647DABDBF1FFFFF4C078462F323D355EAEEAFAEFB492938A835430295CA4C6B58C657B9E81534B40395597CCE1D0BB886738261A2E30528ABECDC692471B115EAEEAFAEFB4929301FEF25C07071820704E06000000085894B2A3692000003A85ADB89E561A2152A1BB987E7D6C1C0000002C5A8B9DABAD7631161E66B3CED7CEB9883F0300082E6193BAC1C2BE8C5A7294795C7CB3C7D1C4BFB57C4C503C1C1C4589B7AFA99F621F00000B4592B2AC938080815554757B615F9BCED5C9CAC1AF6E3000001B6EADB9C1B4BFC0BA933700055A9DB5B9AFA6AE933900003068A0A6A694611C000000000000000000000053607EAACEFFFFFFF7BB7A453231343762ACEBFDE1C09C928C805B2F2E5CA6C3B4896D789283503E382C5998D2D3CEBB96693C191627305688B6C8C2914E1A0D62ACEBFDE1C09C9201FEF35C07071830755301000000095C99ABA2651200083B88A6BE9E54132261ADB09A777A5D1B0000002A618C9DB5AA7929142461ADD7DAD6BB82390400082B5594BFCDC2B38257748C685175ADBDC8C1C2B279505E401E204986B2AFB29F6424000011518FB6B28671777E5E587D72496DA7CDCDCBC5BEA36B2300000B65AECBC3BFC9BDB88C390009669FB3B0B3BDB38F340000407F9AA5B39C5F1F0000000000000000000000605E71AAD8FAFFFFEFB76F463941463D62AAE2EFEAC39C7F8275522D225EA6C0B98F6577A27E514142325DA2CFD8CDAD8663411521372C488DBDD3BA854E241862AAE2EFEAC39C7F01FEF45C070718406E4C000000000067A1AFA05E0B0003408AA9B18B3E012168A1AE8F6A735A180000052C7195A0ADAA703216226DB0C7D9D9B17B24000010315294BFCBC1B0795C739A664A7FB0C1BEB6B6BA7C526D4A2227498AC2C0B89C51220000175E8DA7B18465737C525F91895164B1D4D9D5C7BC9F571000001467AFC8CCB9BFBEB19035001469B1C0BEBAB6AD862D00003E859BA9AF9C662300000000000000000000005E698AAFD7F7FFFFF1B478483C40464051A7EAF8F2C492807A76592E2F67B7C2B482627C9285523E3D326BA8D7D5CFBA8359341E2B34345590C5D4C88444230E51A7EAF8F2C4928001FEF55C07071850753D00000000156297B2A8661400024298B0A4873903206EB2B6957A6C5710000012356D9398A79B642B0C295EB2D6DDD3B6792F03000B31569EB7CCBCAF7D5E6F86665376A4BCC9C9C7B2795B6B5828285386AFBAB596560B07001663A3B5AE845E666349548F804F6EB7D6D1CFC8C89A500B00002269A3C8C7C2BFB7B78C31001576A9BBB2B3B3AA8C2700064081ACB2A6976615000000000000000000000056617699D1F6FDFFECB16C37314550485BADE8F9EBC2968B8276431F2571ACC6A77A676A958053414E4273AFD3D9D0AB7A532E1A243620528FC7CEC0873F21145BADE8F9EBC2968B01FEF65C070718607545000000001C699DA1976305000E4F92B0A37331022261A8B498726A421200000E3A799CA7A896601F082668BCD7DAD7BF7D3400020C3864A3C1C9C2AD7655758C625275A8BCBDC2C5AB6C5B734B30325694BABBB998501901011D5F9DBFAF7360666A4F5A89835F77ADD2C9C7C3BF8D500D0000206EA5C0C0C1C5C7BF9735001374ACBAB9B7AFAB821D00024E84A7A79E99651700000000000000000000005B5D7CADD3F8FFFDEDB3703F394D564469BAEEF1E9BD937C756B4B2C3168AEC7AB7F5970906F5646503672B3CFDAD1AF72483725293A40688EBCC6C089421A0969BAEEF1E9BD937C01FEF75C070718706C410000000019719FAA905208000E4D99ADA9802E072273ABAC8E725F3C0400000541829EA4AC9F62260D1F5BAAE0D9D6B98B3102000931729FC8CDC8AB7B4C667F5F536EA9C3BBC3C8B27565756542495E89B7C5B4914E1000001F6397B6AA755A5F605063837A5A78B7CCC8CBCBB48F44030000166EAECFC8C1C5C0B98B2F00217CB6BCBEB4B2A37E28000D508AAAADA3986420000000000000000000000074708AABDCFFFFFFEFBB5C4934535A557FC0F4FAE5BE948277714E232E6CB2C8AD7A5F70937F4D4049367ABDDFDCD1B87B40251B2435456B93C3D4BA873B1E107FC0F4FAE5BE948201FEF85C070718807C3600000000136B909E95580A00135C9AA9A8781C002176B3BFA176633900000015497F9AA5A1935B240F216FB9E3E1D1A97C2E00000D4274A8C4C6C1AA794E6D8654416EA7C6CAC7C1A96B5B786D554471A0B2BCA3853D0A0000196B9FB09C7A5C5E675262947C5371B4D1D6D5CAC989360800001D70A0BDC4C7BEBAB6953800207AACBCBCBDB7A46E1E000E578FAEAD9D915E1A00000000000000000000006C7788A1D4FFFFFFF4BC75454353515479CAF4F7E6C0857A6F60362C3473B7C5A07B5A758A804B44543D86B3D4DACDB07749251B2D384A6C9AC4CAB67740180A79CAF4F7E6C0857A01FEF95C07071890753600000000146DA1B396580B001D5AAAA8A46B1B00347BAEBD9A7C61290400001F5988A0AFA58A58240F1F64BDDDDFCEBB823100000F4377ABBECAC7A1685371865B4669A8C3C9C3BCA66456745844517197B9C2B282390F00021C6994B4A6754B5861466797815E84B8CBC9C5C7BB8B2F0000002A77BAC1C4B5B0BEBB9331002D8CAFBDBABAB3A46E17000C5A8CA9A69298651B00000000000000000000005C6587AADAFFFFFFEDB675503440485384C8F9FFEEC18778786746223177B4CCA57564758C7C504253327DC4DEE3CBAD7746271D25394C6C9FC9D7C280311C1384C8F9FFEEC1877801FEFA5C070718A07B41000000001B70ACA79A521202216AA5BAA95D12002A78B0C19E7169320000001F5B8CA79C9A84501F072272B6E2E6D8B4822C000006417DACBCCFCBAD6D52687554466FAFBAB8C6C5AC65607F68495678A6C6B1AC90420400002575A7B8A979504E4F3E6893805E8BC2D5CBC8CAB5792D0000001F79ABBCC8C3CBC9B48532001F89ADBFC2B0B2A66B18001564979B9895915A1800000000000000000000005E637BA3DAFFFFFFE7B16E3A31464C4A80D1F8FCE8B580746F5F41263373B6C6A67D5C6A8A77453B593A87C1E4E1CBA9723C271E2441507CA7C6CCB37437140780D1F8FCE8B5807401FEFB5C070718B0763300000000247D9CA1994A06002C699FA6A16017002F87B0BFA48163230000001C6691A8A7A07D451008316EC6E9EFDDBE812C0000144271A9C4C6BBA66A42688154456DAAC4BDB9B49E655A846E5A5A79A5BBB5AA8A3203030029669FBAB277544D4E3A6CA18D5C8CBCD4D1CEC3B6732A000000237CB1C4D3C9C3BAB78527002D8EAEBAB5B6B79C6113001D6D8DA9988E8B601600000000000000000000005A6481AFD4FFFFFFE7AB7740364B5A5180CFF8FBE6B6806666614026347FBCC8AB78586F8A714B40502D84C7E7E1CFAD6D3A1A0B223A5488A4C3D3BB7333191F80CFF8FBE6B6806601FEFC5C070718C06A29000000002382A5AE9D4903002C669AB4A85818003287A7AD98705A240000002C609CACA69C7E48240F3477B9E1EADAB87E320000103E7EAFCCC4C0A3674D6C83474865A5C3BABFC6955E5B7C6A56658BA8B3B4AB823C1000002D7EADB3A6795547453468A5776089BDD3D7CFC1B67E240000003186B3C5C2C5BDAFB77C2400307CB2C5C4BDB89F68090020708A9A9D899266200000000000000000000000626A8CADD6FBFFFFE6AF6D4139434E5E95DAFFFFE6B479575B5C3B234681BFCEA9735B6D807644344E3991CEE0E2D2AD6F361E11203F5A7EA5C2C9B77C351D0A95DAFFFFE6B4795701FEFD5C070718D07931000000003283B1AB904914032D7CA7AC9A5A11012F7EB6C3987658210000002E6EA5B2A497754715102F75BEDFE4D9BE84330000184A7DAFCED9CD9564416877554265A3BEC9C5BA8751577A6B5B6E82A3B8AEAB8A340E03033176A9B6A57A404B40407395725E97BED4D5D4CDB672230000003182B0C8C7C0C7C2B67D2400358CB2C1BEB9B3975106002573979F9696945E1600000000000000000000006E7C84A7DBFEFFFFE3B170464650576992E3FFFFE6AB82636055402E428DCACFA8735B6487724739643A9BD0E9E2CCB1763B13141C3F5385B4CED2B3682B141192E3FFFFE6AB826301FEFE5C070718E07629000000003B86B8B7904A0900347EB4A5934D17043E8EB6B69C79541E0000003777A6B6B39E7843160F3685C8E6E1DDC589340000144F86ADD0CEC3A361416172433B5DA1B3C0C5B3844C59816C6A7791ACC1AFAD8838000002337BB1B8A3754E4C4A416D9670538BC0DDD6D0D0B36E200000002C76A7C0C7CAD1BAAB7D1F003689B2B7B7B6A6A65B0E002B829D9B8C8B8E5B1D00000000000000000000006F7595B2EAFFFFFFE3B3784843586072A5DCFFFFE4A8755D5650382D4C98C7D5A57D5B6B7A6A433D5E338ED0E6E4D6AD6E3C1A1123406085B2CBC9AB6B2C140CA5DCFFFFE4A8755D01FEFF5C070718F07B35000000002E86AFA9843400013583B2B2934208053F86A9AC957E5A200000033B77A9B4A89B7D410C0C2680D2E8F3DCC3933500001A538CB3C7D0BCA15C4968643D3C63ABBAC0C4BC8445527E71757E9BA9AEA8A2792E0000002B75ABB2B27F4C3E3C3F6C9E806199CDD7D5CEC3B868160000003281AFC9D2CCBEBAB47B11003592B7B8B9B6AC954D050030749BA18F82865B1C00000000000000000000005F6E8BBAE5FFFFFFD8AE775448535569AFE5FFFFE3B26B51514D31254995CFD5A3784E68806F47455B3399CFF1ECD2A06D35120E254A618FBACECFBB76281D1CAFE5FFFFE3B26B5101FE005D070718006E3A000000003F98BBAC8741000A3E84AEAD945207063784B1B7967A5323000009497EA7C3B4986E400D123581D8E3E4D9C595410000185999B8CACAB99455406C6D3B3567A9CDCBD3B67D3E5483747A8AA3AEB0B6AD80240000032A7CA6AFAF7E533E322E6C9C6B5D95C7CEC9D2C0B6652A0000003883AEBAC6D6C4C0AC6E0C002F96B8B9BBBAAD8D4000043C91A99A87878D560900000000000000000000005C6981A5D1F9FFEFBB93604046556176B0EBFFFFDA945A40404531294799C7CC9E75596175694C436539A1E1F6EFD5A56D371716294D6C90B5C8C2B16E2E140FB0EBFFFFDA945A4001FE015D07071810702A00000000388FBCB6873D0510408BB0AA8E400302448CB1B39681561A00000A438DB7C4B7A57B46110F2C89D4E6DEE5CA902F0000245C8EABC9CABA924C3F62643C40689EC6C4C1A56F3C4B7F7C7E94A4B0B8A59E732C0100023380AEACA578504A343D7C956F5E9CCDDBCDC5C1B4691F0000003287B5C1C6CBD2B8AA6D1A00418DB3C4B8B1AA8F430401328A968E7C7B8254120000000000000000000000557084A8D3FFFFF6CF96623D4C556387B2F0FFFAD696604A4A45302E51AACACCA27D5D647B653A306535A2E3FAEAC9A55D3C19131F4E78A4C8CCCAB0671A0612B2F0FFFAD696604A01FE025D070718206F2B000000084A9BC1B77F35000E3D93ABAA99460A00488AB7B8937A52180000134980ABB7B5A275310913388DD4F5ECE4D19C3900001E6192B2C7C5C197483E5C6141416DA8C6D2C2AD66334C71778BA1A3B1BBB5A671230000092F7FA5B5A47B593B2B467F835F619ED1D6D0CDBCBC631D0000034192BCC9C4C1CEBEAD7012003F90B7BDBEB3B18E360113468D9183767983581E00000000000000000000006A7594B0E7FFFFFFC8946B475158658BC4F0FFFFD18E635A524835375FB2D0CD9D635358725E3F39643DA4DBFBEDD3A36B3F1C1524537AAAC6D4D3A95F150607C4F0FFFFD18E635A01FE035D070718307C3B000000004894B8B17D3209165293AAA8873F00104685ACB6A0825110000110498DC0C8BD9E6A3310103B8BD0ECDFDACA90410702266EA5B9BFC3C0924F4464522D446BA1BECFC89C572B44797E819BBABBBCADA6731B0000063782B3B5AC84603E30387A8D615E9FD5D9D4CBC4A55F190000054088B7C4C4C3C7C5B2611400489EB5BEB2B5B081380006428A9C896B7C884D100000000000000000000000747D8FAFE5FFFFF5BA94614F4E496C93D0FEFFFED99A503C3E4032336DB4D5CD9C69564D6F6C40376E3DAAE5F5F5D69F683A1C14235084AEC8C5C899662A1014D0FEFFFED99A503C01FE045D0707184073240000000E4E9EC5BE8B3203165790A193824204134C8DB4B39B7551130000185490B6BEC0A5723616113B8ED6E8E9E0CA963700012170A0BCC8B9B88A41365C5A3A4473ABBDCACE9A54274A737A98AAB0BCC5B298711E0000014282BAB5A68B66422639747F5D5C9FCAD8D4C6C7A75D120000074A99B9C5BECDC0B1A76517004993ABB4BAB4B28B350011459092806A73845B170000000000000000000000738395BDEFFFFFFFC19363585A5D7299D2FFFFFBDA8E5A413238363567B7DED294674E586D633A386C3BACEBF2EED29E5E4128121A4B84B7C9D2CB9F5C270812D2FFFFFBDA8E5A4101FE055D07071850783E00000017529EC5B37F360A1C5E989F99883C030C508CB3AE8F79440E00001D5CA0C1CCC2A775340D143E91E1F0EEE5CA963A06072E62A0B7C5C7BD8F47385658344372ACC1C3B88C461E4C7B8091B7C6B5B9ABAA6618000008428EAEB8A08F6D482F386C795958A3CADDCAC5C3B2662100000A4A96B8C0CCC6C0B4995704004198ACA9B5B9B4772500084E969974647795581A000000000000000000000074818EB0E5FFFFFCC0865E45505E7298CDFEFFF8CE95614A3B3C33396DB2CFCF9B6D4F526751363A6A41A8EBFFF4DCA15F341315285984AEC5CECAAA662D0F09CDFEFFF8CE95614A01FE065D070718606F340000001957A4C3BD8D320B1D539BA09E7E350B135794B3AC9377461400001C63A4C2CCBDA05D2906154BA3D9F0E9E3D39C380A063371ABCCC5C3B082402F4E4F3A5173B0C9CCC8873E16356681A3B6B8BAB3B29D7820000009428CA7B2A48B69401F356E755960A2CDDAD3CDCAB4601900000D509EC5C8C5BDBFB2A24A00004198B9C5C1B9B37F300005528A88746777845418000000000000000000000079888DAFEAFFFFE9B5865F5360687FA8DEFAFFEEC681483A34383E4D82C0DBCA9372464A5A4C393D6E32AAECF6EBCFA46141241F2C5C96AFC5CEC4AB5F240A08DEFAFFEEC681483A01FE075D070718707B410000001B5FA1C2BF7E2C0E275B9A9B9F7F340F124F96B5B090703D110004296BADCAD0BD9D60200A1F489EE5F5F4DFC98A31000B3080A9C2C5C4B97F34294849354878B0C4CFBD80301C45637BA1BFC3BDC3B2A76A1900000B499DBBB4A8966D392C386570465DA9D3E6E0CBC3AA551B050008529CCBC7C9CBB5AC90480300409BB5C3BDBFB37E24000A5A927E5E637984521500000000000000000000006E7F8BB1E9FFFFE9B086564A596783B0DBF4FEF0C98A4F40353A334088C9DBCEA56E4C42573C2F3A6D47BAF0F5EFD2A6673D231F2A6082B2C7D2C4A65C1E0D0EDBF4FEF0C98A4F4001FE085D070718807E3C000000236AACCABB7D2B0F27629BA19B77320F215998B6B49F7B3D0D00032B64A9CED2BF9F6225121755A0D5ECEDDFCC843809062D79B0BCD0C8B680392B3F43304D82ADC5C2BB772D1C46708594B4B8C1C1B7A95D120000135F93A8AFA999684229386955495EACDCE0E2D8D0A7582D0A00165D9BBCC1B9B3B8B18A3E0100459DB8BBBAB4C16C1A000864A08A6960727D4B0F0000000000000000000000767E86ABE9FFFFE1AC8356525C6884ADD9F9FFF2C68858422A283B4494D0DFCD94654D3C5143312E6543BDF3FFF2D49D5D40231C285B8CBCC7C6C8A2551F0702D9F9FFF2C688584201FE095D07071890732F0000002B6FAAC7BB8030142A6EA7958B6D2B0314599CB0AFA167370D00072065B3CED8C9A15D1E04184EA3E2EFE3D7C78532040C3C86B9C3C8C3B27740293C2F2F5488B3CBCEBB7D270E376583A8BCC3C3C3BCAF641600001F5E9BB7B0B6A07436122557544364AED3DAD0D7CEAD632707001B629ABAC2C5BABAB08F3200024A9BBDCABEBCAD630E0019609B815A526D7A491600000000000000000000007D888FA1D6FFFFDA9E735C53607286B0E1F0FEEFBE8854372534334B98D3EACA9E6541434C4425346A44B9E7FCEBCAA1653D281D305D8AADBDC7C2A666211407E1F0FEEFBE88543701FE0A5D070718A0752F0000001E65A6CDB77D33122C7AAB988F6F320C115C98B5B2A670390D00062A6DB2D3D5C6A655200A174DA6DEF0E7E2C7822D06103C92B3C1BDBEB2772F2235262B518AACC9C5C0712B15335C82ACD1CEC5BFB7A164170000184F98B6B0A990773E1E255B523A5EB1DDDED6D4C19B53270300145CA0BBC9CBC0BFB58A3700004F9EB4C5C1BEAE611F001E6B937B5E66767C4E0F00000000000000000000007A7D7EA2DFF9F6CD8D624C3D597D88B5DAF0FFEEBC7957361D273751A3CFE1CD98603B3746412D398258B8F3ECE5C79E6239271B2B4F88B2C9C6C1A45922080CDAF0FFEEBC79573601FE0B5D070718B07D33000000247EB0CDB77B301532749E9090802F111F5BA0ACB09A6E350500072674B9DBD5C8A05E1D00175AA8DDE9E2E7C6822B0517518FBAC5BCC3B2703121312C26538CBED0CCBD69250E325175A4CAD0CABBB4A163100000246096B8B3AE9B72351921534C4564ADD6E1E0D8BDA2522004002264A4C6C2C5C5B7A98322000256A6BAC8C3BFA95F130018658E76505A6C7D4812000000000000000000000072737797C9EEF1C3865243344E677AAAD4ECFCE5BA8B593E2C272B419CD1DFC298653E3F453F273B7C5ABBECEEE1C09C6640291E2A5293BECECABB9D66170007D4ECFCE5BA8B593E01FE0C5D070718C07D3A0000003A8EBECEC480331E3A76A5938C6E2B082167A5AEB59E63360F000B2E74ABCCDBBD9D4D1B0C1756B3E3EEEED8C27E2D0E215696BDC6BFC5AD6927182B31306696BEC4BFAF591B1631557EAAC3CDCAC7B5A0560E00001B63A0AFC4AE9C7A33142045423D5CB5D8E3DBCCC99B592A0C0C317AB1CACCC3B8B3AA791F000050A4BDC8C1BAAE600F00206C8B735259767C4C1600000000000001000000007A8679A1DCFAE4BA7B5346455B7B94B7E0F4FDECC3875B451C243D59AAD3DEC88B5E3A394737273A7850BAF3FFE6C89C66441D17415F90B6C9CDC5A25D1A0700E0F4FDECC3875B4501FE0D5D070718D0733C0400063680C0D0BC7A341C3C81A6908F6D28092166A7B1AA9D622E0700103C82B8D0DCCA9E521F071658B7EBECE6D8C47B310C2A599FBDC5CAC3AD6B291A232D346798BDC1B9A562190C2B5976AEC9C5C5C5B6A3520C00001E619CB0B2AF9E77371B24393D3A65B2D5E1DED6C5905A30170A2F65B1D1CEB6BBB7A979230000599CBEC7BCB4A0510C002374926D565D78724C190000000000000000000000726B6A9FD7F3E2B5794537385B7595C0E0EDF3DDB4825B3C1014184AA6DBE2C1945F3E39392F1B398369C6F0FDE3C29261432C202D518ABEC6C3C69D551B060CE0EDF3DDB4825B3C01FE0E5D070718E07F410C000E478DC8D8C17B38274E88A69793732E132169A5B7B094622A080010397FB8CADCCCA45921031B67B6DADBE7DFC374280A21649FC3C6C3BF9A68210C1A1A2F7195C0CFCBBC58110527537DB7CFD4CBC2B79C4E0B0003256BA2B4A9B2AC863811183639366CAEDBEFDACDC3956034130A3380B9C7C5C3B6BEA56E1C0000559ABEC6C6C8A2500A00236C8C67505C736E3C0F0000000000000000000000706B6090CBE8DDA56D402D3A5C7791BCDAEDF1D6A97C5D441D132558B1FFE7C4845C32283932263E8B62C1F0F3DDC0906D47291625528FB3C4C6C4A85D27030FDAEDF1D6A97C5D4401FE0F5D070718F07B36000006448FD2DBBC722919418DB098976E2F0A2663AAB2AF9D501F0200173C88C5D9DCC89D4E15041B60BBDFE4E4DCC57B29032C68AAC7C5C0C2A45F1B0913193275A2BCC9CAAF5612031D4777B1D5D3CFD3B99D53150000276CA5AFAFB2A3723A170E2A2E3E6DC0E7EAD3D6C39657311B19377AB5C4CBC2BBACA2690F000F5FA8B9BFBBBE9547090029759970595777733D0C00000000000000000000008475729FCFF6E9B6754B2B416B848797D1F2EAD9B582644925203D6BB5DCD7BE895F341D39302B4B8E6AC8F4F5D3BB8D6B49291D335E91BCD0C4CAA55D15000BD1F2EAD9B582644901FE105D070718007137000002428AC6D2BA712B2653A0A79F9E742708255EABAB9F874C270500173F87BCD3DDCE9B4113001E68AAD5E6ECE1C36D26102F69A9C2C5C7B9A257190B0D113D7FAABDC3C4AA4E06001F5382C6DCD8CDD3B5A350080004336AA6B8BBB09B793B0F0820313B76B7DCF3E2D1C99C5B2F15154381BDC9C9BEBFB0A05B0C000C659FBABEBBB799450000276E8D7058627C77380C000000000000000000000079666A99CEE5E2A767382640537294B4D7DFEAD1A87B613F121A2D61B8D7CCBE895D3527302E2B438B65CFF3F1DBBE90655629191F4A8FBDC6C9CAAD58230008D7DFEAD1A87B613F01FE115D07071810783E07000947A3E1DEBA703A205DA3AC9E8F6823092B6E9EA9A6854F210702194794C5DBCCC599531910206DB8E0EBE5E2BD651E07367EB1C5BCC9BBA25A19010712387AA2B2BBC3AA4B0C09184778BFD2DDCECDC49C4D0A0001276CA5B8B1B2A07B380A1124293D74C2D5EAE2D4C08D5A39111C468BBCCCC5C2BEB3955909000E67A3B9C0C2BC9A430000307690715F5C716E320A07000000000000000000007C766E9ED1E6E3AE663C3F516D80A1C8E0F1E8D4A4836E3915063270B9D6DFC08A5628223C332D488D6ACCEFF0D4AE8A60432C1A144E90C2C9D5C0A6601C0000E0F1E8D4A4836E3901FE125D0707182077350F14205BA5DAECBF712E2F65B6AFA09E6B1F0A2774AAA9AB8B45160103194C9ECBE6DDD5974311072569BCE5E2DDD2B86917083885B0CCCCC7B3995818090C0E2E80ADC2C3C0AC460002133579BFDDDBD9C5B4944D0C0000407FB0B3B4AC9D893812071A1D447FC2E8EBDFDDC6895D3A191D4988B4CCB7B7AAAA965808001366B2C3BFC2AF8A3A00002E789D6E5766736E3B080100000000000000000000725F639AD7EBDCA75D393D50667B9DC6D7E5E8C5A17D6543141A386AC0DCCFB9875629242D2B26428C65D0F4F7D7A884683D232123479AC2CBD2D2AA61230605D7E5E8C5A17D654301FE135D07071830672E02001854A2CDDBAB66353069A6AFB0A2711A0D27709DA78D823D0C000316539ED7DFD7CA9B3F0701277CC3D9E0E6D6BB66200A428EB8CCC3BDBA98410D00000F3B7EB2BEB6C1A84F0A03164788B5DADBD4D2BE984C080004397EAABAB7AB9F7931080A17174081D0E1E4D6CBB38665391D27598CBEBFBFC0B4B1965102002579ADC0C0B9BB8C3F00003081926B5C637D65350904000000000100000000007C626CA4DBE4D8A4613C48577497ABC4D5DDD4C19F75614411113677C2DFD4AB81522B1F2E342B47996ECAE9F3D0AC7D6A483323364C99C1C7C7C5A35D1D0504D5DDD4C19F75614401FE145D07071840752905011165BFE6E1B566323675BABDA59868270D1E60A1AE9D6F3B0C00021856AEDCE1DEBB823D12092D71BDD7E3D9DFB9691C154990BCC9C8C2AB903D0100000E368DB5C7BCBFA04507000F3D87CBDBE3E4D7BC95530C000A467CB0B6B0A4A27F2E0B0004103985D0F3EDDFD6BD82593A1C275B90B7B8B0B7B2AF8D4C00002775A9C7C8BCB480300000376E927E6C6B7D66260000020000020000000000007565649CD5EAD69B613B435F798EA8C7D1D5DEC69778613B09083B7BC7DADBA9774C21222B2F2A509F65D1F2F2DCAE835C412C262B5596CFCAB7B7A16F250400D1D5DEC69778613B01FE155D070718506F3D0B031D61BEE8D8B16D343D83BCCAADAA621C132B669D9E9575370F03012966B0D6E1E1C88136100A327AC2D5DDDDDCBE5C140E5398C3C3C0BCB38938090000053E8BBABCB1B6A74C1000134387C4DDE5DCD0BF8B3906000B4588ACC3B8AAA87C2E0500081C3F82C9EBEEDFE0C28A61431D2E5F97BBC7C4B9B3A6893800002C7DABBFBFBBA97C260000286C8F7C77707B632A010000000501030000000000786770B0E5E9D3A1604055708297ADCAD3D3D9BB9C745E3D0C0A3B8DC5DFCFAD864D0C1832332558A371D6F0ECCBA176573B17283A63A4BBCBC9BF9662190000D3D3D9BB9C745E3D01FE165D070718607C3E11102E72C2EEE1AE6A323B87BAC5B6A8672309366F9EA08D632F1100032F71B7D7E3E1C28137080C2D6CC1D3DFE2E6AA5D191661A2CAC7C6B9B47D3300000009418BB9B9B5BC973E09000A3F8DC9DDE4E1D8BB8F4305001A5290BCBAB8B0AC862B0000001B509BD4EFF6EEE0AE745B4723306998BAC2B6B7B8AA83300000357EB6BAB4B5AD7A2700002F7A9C866D797E5F2D000000000000000000000000705A6CA6DAE0CA925438475A7F96B7C1C2D2CBB989665B35110D3D87C7DED0B7804F2D22393126549A5AC5F0E6C9A67C573020062C58A0BBCACFBD9B5924090BC2D2CBB989665B3501FE175D070718707C430B0A2A80C8E3E6A7643A4D89C5D1CBAB71240A2E699BA08964290A00002A6EBCD3DCDEBD823E0E093170BFD1E5E5DFB0581E2C6DAFC3CAC3C5AD8032000000074597B1B7AFB9903E0500093986D0E1E1DACBBA954904001D53A2BAB9B4AEA78E370200000F4392CBDFE2DDD2B0796545203876ABCAC1BEB1AAAE732300003C83B0C0C6B5A467190000357EA18483727F571A00000005090002000000000067667AA6D9E1C595613D597D8F93ACC1C6CACEB88A62592F000B3C83C6DECCA76E4A2E313E2F345BA668D3DDDBC39E7A4E372B2E3D67A3BDCDBFB9A2561E0503C6CACEB88A62592F01FE185D070718807D4920203D80C8EAEFB063385598CCD6C5AE68190230719A958358321609174182C4E3EEE4C5742F10002E70BAD1CED5D3B3611B2478B7CDCBC2C1A56D23000000104A98B7ADACB898410000134590D4EDF0EBD7B88B3F0601175392B5BCB4A8A47A2B010000154B97D6EFE7E2CFAD7063482B4B87B1B7BCBDB8C0A66C1F00004483A8B0BFAE9E5F09000026759C86848582561B000005000103040000000000726F83B6E1DDD3874A3D61808BA2B7BEBCCCCDA488655E401710468CCCD9CBA87345302F372F314E9E41BAEAE2C4A27A4B2F1B243D6CB0C4C6C6B49654150607BCCCCDA488655E4001FE195D07071890743A1C193881D3F8E7B263385193D0D2C9B15D1B1639749CA282582F0D0C0D3685C7E1D8D7AC7A2B05083573C1CDCED6D7B1511D2B80B5D3CAD0BC9E712800000015579DB8B8B4B88E2E00000E4A91D6DEEDE5DCB6843708001B5DA7C5BEBFB9A67D2C000000115599CCEBEDDEC99C6658392D4280AECAC1C0BBB5AC721F00095394AFBBB7B3A3680900002F709092878373561C000000020003000000000000738087C0EDDDC2894E4B60658A9FB7BEC4BCC6AB7F554D320D124396DBE6D6A26E432F364033305FA25FC5EBE2BF94664C381724447AA9CEC7C6B2915914090AC4BCC6AB7F554D3201FE1A5D070718A07333060C2F80CAEADF8F513358A3D0D8CEB063160E32698D9B7954240F0710468FCEF1ECDBB07B2A0901307CB9C8C8D0DAAA4D15317FB7BECDCBC6A96C170000001749A5ABA8A4B0853102000E4B9EDBF1F5EAD7B0773100002369A7BCBAB7BBAD79270000001A4A91CCE8EBDAC99A695A43304487BCBFB7BABCB79C6816000A5B98B7C3B7AF9F59110000307D9B968F878C5E1A00000000060000000000000080859BD2F5F1C98A544C688290A0B9C5BEC2C7B48044434211164C8BCDDECEA46941364343343764A760D1E4DCBE9062431F1A2C4478B1C7C7C3AE8A49131112BEC2C7B48044434201FE1B5D070718B07A4516224E94E1FBEBA359445FBDD5CFC5A45F180C3A6FA28D7851250F0A1D5293CBDFDBD9B66B2503042878BEC5C9D6DDAB5122357EB7CED7D4C59E63180000001863A6AEA5A2A7792100000946A8D8E9E7E0D1AB7A300902296DA9CDBFBCB1A58226000000174FA7D5E3E9DAC796645D402E5690AFC0C2C0BAB39B60140014619CB7C0C2B19D5500000030779A94969386501800000001000D0000000000007286AFDFF3F5D7905B51738B93A4B8B2B8BDBBB579424A3912134999DDE9CCA0693C2F474D363359A161C7EFE3BA8F5E422C232B4677ADC1C8C8B68B55220B09B8BDBBB579424A3901FE1C5D070718C0783E202D4A97D7FFE29A573561B8E3EAE0B86A22153871949263391C15181F55A4D5E0D5D0AD511503072673B9C9D2DCD1A54A1C2681BFDBCCCBC1A15F1B000000175AA6BDA3B1AB752D00000E4EA9DDE4E9E2D3A86D2000082A74B3CBC8C0B8B280250000001C60ACD8F0EBDAC089604E3D395896B4C4CBBCABA0925E0E00136A9DAEB6B0A59558060000367D9EA18E92874F15000000050E090300030000008699B7E8F7EDCF8E6861768D94A4ACC5C1B5BCA56842443616225A9ED9E7C7A0603D3B4E533D3068AF61C8E2D8B07B56472F20294E8ABDC2C4C8AF7B410E080BC1B5BCA56842443601FE1D5D070718D0704121374B96DFF0DF98543F63B7D8E2DBAB6A1E193A78938665441C130F1E5DACDEDEDCD1A664200002337DC4C5C6D6DAA03D213A7FBCD7DCCFC5A14E110000002068AAAB9CA2AA752500000847A6E8F2EAE1D2A2611B00032C7DBAC9BBB2B3AB81290000002467A7D3E3E3DFBC7F584F3C3563A6C2D0BCB9B8B29F5D0800177097ACB4BDAC8C3F000000327FA6AD9C9886400A0000020C0E090400000000008597B0DBEEE8C789625E778C9BA8BDBFBDBCC6A2653B3A27071751A2DADECF9E66393A50504C3B66B460C2DECDB48B50372D1B284C8DC4C8C5CBAB7645110516BDBCC6A2653B3A2701FE1E5D070718E07A422B34538EE3FFE3904C3C6ABDE0E4E1AB591F19478292806745271818316CB8DFE1DED19B58160506377ABCC4C2CCCF9D4D1C3C9CBED0C8C9B9914D0C000000206FA8B3A3A8A0681C00000852A9E5F0F4F3E2A4681B00003D78AFC5C9C7B5AF80250000002766B3DDEBE4D5B56E47493E3B6AA2C6C2C5C2B2AB904904001C71A6B7BFB3AB8C460000003278A1B0A592733B0C000400070C0800000000000089B2D2F7FFF5D69B6C5B7A8F9FA9B7B6B5C0C4A06E303333101E6EBEDFE0CB9850353C5A5A4C456AAF54BED6DDB07650400D1D2C539ABCCCC8B9A26C3718120CB5C0C4A06E30333301FE1F5D070718F0773F1D284E9CE9FFE6904F436DBDE2EED4B255201F487C918A69401B0C182D6DB3E1DECACA97481E05082F7EC0D1BECED09C4E273996B8D8DAD3B386430E000000386EA8B09AA4A666200000114DACF1F5ECEAD88847120215428CBFCCBFBFB9AE7B2C0200002F73B7DFE4E4D8A960414C3A3B66ABC1CBC5B9BFAA844301001B6BADBBC2B8AA84360000003283AFB7A5976F341000000210110C000500000000809AC5EBFAE8CC986A5F768A96A7B1B1A1B4BA9E5C272F23061A6BBAEBE4CE94552F3B6456494C76B952BADAD5A777503A2D18345DA0C3CACDC19F68381E0C13A1B4BA9E5C272F2301FE205D07071800774227365FA6EDFFD98D4F4A77BEE3EEE0AC561D18427E8988754D261A1D3478C3E6E4D6CB964B10000A397CBCC5B5C7C69D4925478FC2E1D2CFA67E44030000043672A8B09FA49C59110003165DBDF0F9F1EDD895471600094192BFBFC6BAB6B47C1C0000013376B7D9EAE0D7A957454C40437AB5CDCDCBC5C1AA7A2B00002680B1BDC4B39579230000003F8BACB7AB9E67330700000110190B080000000000809EC4F4FFE9C59875627C818DABB9B1ABB2B995502325230F1F79C9E5DFCB984D334669664B4574AE55C5E4D5A57C50382D253163A5C5C6CAC0A66E3E1C1215ABB2B9955023252301FE215D070718106D3B243654A1E3FEDD814D3C6FB9DDE6DA9F522016447C907B6A472C171D387BBCDFE3DDCB8E3907000F3E7CBAD0C1D7DF9640203E89C1D1D6C1AA6A35080000113A7FBAAAA5B9A7591300000F57B3ECFFF6E3D885390A00144C8DC0C3BBB5AEA879220000003B81B9D9E6ECD3A3513C4041497DB9CED4D0C2C0A67C2100002B7DACBBBBA597802D0000003683ABB0AF9B70320000000E151B1208000000000089B9D7F3F8F4D69A7464779194A4B8B4ACA5B496572912110C1F7DBDE9F5CE924B334669624F3F77B758C5E0D7A4774D3828233A5CA0C4CDC5C29D692F05080FACA5B4965729121101FE225D070718206435272E5BADF2FCD982393D6BC6E3E5D89F451612438290857D542A22223A77C6E1DBDCC985431400093C83C6CCC3C3CA8E3A1B3D8AC5E1CEC0A06B2E0A00000D4489AFB9AABD9B4D0700001C62B3DFECF4E5CA80370A00184792BCCBBBB7B1AD761D00000A4082B9E2EFE3D59345323B36518BC1CFD1C7B8BCA6692100003B94C0BABDB8A07726000000388BAFB3AAA05F2B0900030E1114131A070000000092BBE5FAFEECC89E7670748492ABB1ACA5A8AD885719110D152786D1E9E9C78C3D2C4C696E564177B356C6DEC8A5764E3224223B6DAAC0CDC0B59A5D300E1B0FA5A8AD885719110D01FE235D07071830774D383F67B3E6FED679524070C6DBE0CF9B4817194F7A85827654301F243F87D3E8CFD1CB8C3810000E3D80C8D0C2CAC4933520418FC5D3D5C09E622E0A00000B4589B5B5ACAB8C470F00001E74C0E6F1EEDECF7C2600000D4C9FC4CABCAFAEA3742C000006518EBEDDE3E8D09841344045598AC1D1CAC7BAB391581400034898C0C0C1AE9676240000024C8DB7BAAC996C210100000E181707050C020000008FBAEDFFFFFBCEAB8C76798E9AABB7A89DA7A9863E120A100D2E80CAEDE4CC9049314268815E568EBF5BC5D9C99872442E26283171A9CEC6C7BA955C26120C109DA7A9863E120A1001FE245D07071840713D2D396AB3F4FDCC7340476DBEEBECD8A04B141A3F75817B795F2C1C23489BD4E4DDD3C57C3106000E3A87C2CDC6D0B67D40203F8FC9E4DAC49A6127000000195088B8B1B8B88B360000001F6DCAF0FBF6E1C3722A000022599AB8BDB9B7B3A86E1B00000B5390CCE4F0F1D38934303542699DC4CEC6C4C0BA925007000048A6BDC8C3B3976C1E00000B468CAEBBA9975D1C0000000E18180903030000000093BDF5FFFFF8D7B3897C778D98B0B8A59F9FA387481B100C123A93CDF2ECC49D4E2F4C696E57568EC44CBBDECFB1734E30211A3473AAC6CBC3B5945B2E18150F9F9FA387481B100C01FE255D07071850704A36527CC4FFFFCF7D494A72C9E3F3D890401F1A49767C7A825F38252B4F96CFEEE1D4C382280001134190BDCBCED3BD77301A3B91C7E0DEC6975D1F0500001E5094BCBFBAAF88390000002276C1E8F1F6EAD5711B00001C519FBFC5C0B4BAAC691200000E5CA6C9DDE0E1C67F2B2B334375AECACDC8C9BDBC8A3E04000D61A2B8B9B4A68F5D100000054F93BCC3B7965D1F0700001221271E16010000000093C3FCFFFFF4C9A58E756C8191A7AEA295A6AD83461A0C1111399ED2EEECCF934C2E4D7973655B8ABE52C1D4BF9C6A483B2A1F3E74AAC2C3C2B8875327050E0F95A6AD83461A0C1101FE265D070718606C443C527AC3FFFFCD753F4978C9E1F0DA9A3C131F43697B9196704632374794D0E9DACFB86B2900000F4691D1E0D2CDB86F2A12419BCCDCDDC38F532A080000115598BDC2BAB372300000002877C8E7FCFEEEC36B200000175AAABECDC6BAAFA6520F0000226AAAC6DDDCE3C669272A334571A7CFCCCCC9C2B8853600000C60A4BCB8B7B59B5E0B0000064D94BCCAB0914E160000000F241D1619030000000097C7F7FFFFF2CFAB91797E8A8BACAA9A94A29B78410B08071748A4D9F7EED1A1543E4869726A6E99BF55C1CDB38F56373325173A7AB4C1C7BFB79156211B140B94A29B78410B080701FE275D07071870734D3F4F7AC8F8F7CE76495575D2E9F2DF973F1217446078859C74442A324C99E1F0E4DFBE761B0001164C93C3CED1BFB5662D1D3DA0CCD6DBBE7F401A0000001E5C98B8C9BEB2722E0000063980D6F4F7F9ECBD62140000195A9DC3CEBBB4B1AC681700001C6EA9D2DBE9E1C36C1F172E4F84AED1D4CBBEC2AF7A2B00001474ABB6BDB9AF8D500B0000004B97BAC0A891562A0701082028221B0E0A0000000095D3FAFFFFF0DBB48C787F7E92A9AD9A96AD9C753310080C16429FDAF3ECC79E5C3B4F6F747375A0C54CB8CBBA8E5C3B281D133F7BAEBDCAC2B8894A1C10141296AD9C753310080C01FE285D070718807D52405C83CDFFFFC37341517FCCECF0DF934310153767748CA4755238354F98D7E2D1CAB9702807081D5294CBDCCCB9A85519134393CFDFD9C98446220802022369A2C2C3CCC37F25000004388BD8F3F4EDE8BD5B1300001252A1C1C5BCABB796540A0000267AB6CFE1E8DCB45C1C1739628AB3C9C2D1C1B8A96B2B00001977ABBDB3AFAF975000000017629CBFC5AE8644130000101F2B261B1408000000009ACCFFFFFFF4D8B68976758791AFA6929A929369340D0A0B15449DE1F8E6D09161414961827B79A0C049B7C9BD8B57351D1913417CB4C5CDC9B6944C1F0D1A169A929369340D0A0B01FE295D07071890755446588CC3F8FDC8734D6087CCF1F6DE913813183D537396A276483B3A53A0DEEDDDD7B369280600245C94C4D7C9B89054181853A8D6DDD2B8833A1B11010427699DB1BECEB36C1F0000053F92D6F4FAF8E6C5580800001C5FA0BFCEB8AFAAA651090001397FB6CEDEE1DEB54F1D1B436699B4C9C8D8C9C2A4631A00001A76AABDBFBBAC8C460000001964A6C2C7B780461303030F232B271A0F0C00000000A8DBFFFFFFF7D3B28F7F778599B6B199A09895672D0F0A141F54AEDBEFE6C9965E3A516375787C9EC44CB7CCAE8168421B151B3E83B9C1CBC9B3854924101B0FA09895672D0F0A1401FE2A5D070718A0784D466996D7FFF0CE704C5D92D8F1F6D481290F1E445673A0B587533B3262A8D7E6D6D4C4641B00041E5A9ED0E5C9AD823F0E1647A0D2DDD1BE7E3F1A06041025719DCCCFD1B3681A00000C459BE6F3F3F6E6AD55080000206099B8C0B4B5B49D52090000338DC9CFDBDADFAE540F1D456D98C2D5D2D3C7B6A45A130000226DAABFBABAA8823D0000002077A7C5C8BB8743050000031E281E190B000000000095D8FBFFFFEECBA787766E778DAAAA978E9C926C340800021C63BCECF8E6C59A583F4C67828683ABC852B6C6AC825B4B2B1916427EACC5CCC0AF7D481D1018108E9C926C3408000201FE2B5D070718B079584466A6DCF8FDBF65505F93D7EFFBE68634091A3B5975B1C4875A423955A4D2E1D3C9B2651300022B72A3C9DFD1BC7733171B53ADCED4D2A9703A1A0805032F6BA3C9C9D0A65D1600001155A3E6FFF7F6E4B1530B00001B61A0C2D4BFB1B0994B0A00003D90C5DEDCDCD7AC3F02183B72A1BBCCDBD3C5BEA24D0A00002986AFC5BEBAB07E320000002270A0BBC4B08C430E0000132735311D0D0300000000A4DFFFFFFFEFCBAE8F7A698193A7AE9A908C86592A0A030B1C69B5E5F5E4D09E63474960737688ADCC44AEC0AE7F5F391F1920478BB7CCC6BEA47A3D1713110C908C86592A0A030B01FE2C5D070718C071585674B0DAF5F8C8714E5F8ED0F6FFD7883E1219385375A8C39263493754A0D8D6CDD1B35D1B0004206A9ECAD9D1A97332121752AED9DBCEB4652A120F050B2B6DA5D0C9C6A6511200022157A3E3F6F8E6DAAA48090000266190B9CEC6B9B590450700053A9ACBDCE3D6CFA03B0510508CACC5D3CDC4CBBA9F4D0100002F7DADC7BBBFAE8636000000286EA6BCCCAF8740000000102B2E2D1F0F08000000009ED6FFFFFFEBCFA3806D706F8CAEA49A90927E582314000B1A5DB7E9F3F0C49C5D40475C7F8799BED154B0C3AE7D563D2E23265291B4BCC0BEA3723C1116141190927E582314000B01FE2D5D070718D0644F4E7BA7DBF1F6BB6E516591D1F4F7C97B361319375A72B7C9975D5237569DD5E7C7CAB65C150007366FA6D1D9D4B06F250F2457AAD4D6CFA56C34101810172973A7C9CFC19447100006296EAFE9FBFAEDDC9C4101000023568CBCD1C2B2B58D38010006409FD6DFDBDDD5963F061C5599B3C6C5D2CACBBE9C480C00003387B4B5B0ACAD7B1E0000002575AAC0C3AC7D40150000152B311D120E0900000000A2DFFFFFFFE6BFA28273717595A29E7D8A8C82541803030F1E61BFE4F0E4D19F5C3D4C64738FA9C3CF4DAFBBA4825C452E202A4F8AAEBFC0C0AD722B0E1211148A8C82541803030F01FE2E5D070718E07758507AB0E1EFFFCD7A597098DCF0F4D2782D101F3B5277BAD19B6A424257A7DDE2CDCAAB5414010C3D77B1D6DEC9A2561F051C61ACC8CECAA16528201E160D2E72A6D1CAC28C3B0D00083775B9EFFBF2E5DCA3440000012A6392BECABBB5B08A3F05000D4EA2D5E2E6E0D1972D00135D9EC3D6D3CFC6C5B491410000003B8AB8C0B7BCA576210000002C76ABC4C4A3813B18000011282E281C140400000000ACF4FFFFFFF1C8A2806A727C9AA59894959677411C0806082467B9DDF0EBCAA061423A607993A0BBD753B5C5A870644D39312C5F89AAB3BBB69F682F040D0C13959677411C08060801FE2F5D070718F07458658FCBEEFCF3C56D5871A5DEFFFDD071301620305979C3DB98634B465DA9D5E7CAC2AC561600184277B0C9D6C5925F19051E66B0C9CFBF905F36251F17162B6AA7C1D1C88A450900032F7CC2E6F3EAE9D39F3904000C286297B9CBD1B4B3843A03001047A0D2E6E3DED7982E00206AA4B8CAD5DACAC4B385360000004097BFC1BEC6AD74120000003180A1B5B8AD89430800000D2835291A0F0200000000A0EBFFFFFFDDCB9C836D617A93AFA5968E9068461B07070A186DAECDE8E7CB9D69453556738FA7C6CE53B2B3A076695D4836396193A9B5BBB595622A0B00101F8E9068461B07070A + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 61440 61440 0 01FE305D070718007063699DD4EBFBF4C97D617CA9DEF4FFCC6A2D15243E558BD3DC975C464560AAD4D7C9BF99451000154E8AA5CDDBC28F470A002363B5D1D0BE9C6032141216193275A9D3CBC882350700082E86CCF2F0E9EBCB91310000042C6099BBC7C8C1A97F3000000E58B3D7E1E2E2D3841E00116CABC5D2DCC6D3CFB487410700004391B3B7BFB1AF7522000003407BA5BEB9B2894603000019292E291B040000000000A8DCFDFFEFE4C19E8072637797A18C86898B72331A0700052170BCE9EEE3C895563435537590AECED25AB9BA99795D574D3D477799ACB8B7AB834D1905071019898B72331A07000501FE315D0707181080697094DBF5FFFEC67B5778A9E8F1F0C66D321826446291D6E596624F3A68AAD8E1D2C7913805001B569CB7CCD6C391471108256DB2CACAB995572D252324172F6E9FC4CFBE652D0600164A8AC1EDEDEEE5D499300000002D598EB1D2D7C9B97B2600001761B1D4E1DFE2CB852200277CAAC3D4D9C7BFBBB080330000054CA0C0C2BEB8A36B150000034383AFC5CEA4862F0000001D32392D1B0A01000000009DCEF1FBF6D9B29069594D6C8EA49A898F866F3A130900021573B9DFF4EFCE9959332B4B6F8EABCFD061ACAF9472706754495D8096ADB3AFB781411100000C168F866F3A1309000201FE325D07071820705A669AE0FDF5F7B8635371B5E8F6EEBD5B1D141E3E6892E0E39760464362A8D3D1C8C095440E0729629CBDC2D3C88D3405002467B0D0CAB688572F2B311F1A3372A1C8CCB2692603000F4596CBEFF4FBE9CC7C2500000A2A6496B8D6CBC5AD742500001467C2E8E2E2DED1821B00237BB0CECFD9D0C7C3B5833106000F5599B2BCBDB9A55E0F00000B477BA8C1BA9F863A03000019353A311B090000000000A0D6F1F4E2CEAD8E7058647198A696879483623B040A00002675ADCDDEDFCA93583E31516F97B8D7DE5EACAB866D6E675A49577C96A6ADB297733E130708051A9483623B040A000001FE335D070718307D7786BCFEFFFFF6BC6F5983B3EAFCF0BD682723324667A0E2EA9B694F4967ACD1D8CFBE88380C092D69A7B5C2D3C4842F02002B76BAD0C6AF855E373034261D3372A3C6C9B3652100000D4B9ED4EFF2F0E3BD771E00000D315F91B2C7CEC4AB6E1F00001B6BB2E0E8E9D8CB811B002A80B9C6CCD3D2C2C4A2803400000560A1B7C1B4B1A6610F00000F4E8DA8B3BBAD8B3D07000020373C29160F0000000000ABDDFCFAE8C5A77C695B4B6D8B97918C938E673212060500216FB2D5DAD6BD8F4C2D41507B96B5CFD76CB2AB856B5B6A6661628492A9A3A48F64341405011B17938E67321206050001FE345D070718407F717EBBFFFFFFEEB375677BBAE3F9EAB259271B3B5074ABE0E09A5F524967A7D0DAC8BD7F380D11386FB1BDBDBECD843F040D2679C2C5C5B181563B323A2818306CA5C2C9AF5C180000134FA1D1E3ECDBD1BC701D0000173F638DA9DBDEC7A661170000206BBDDBE3E9F0CC721701287EC0D4CBD1C5C8C0A6763815001464A1BCBAB9B4A15900000013477AA5C1B8A2853B0100001B34382F19080400000000B3EAF5F9EBC7A2756153587395A6998E948F62260F0502082578B4CAD3F5CA934E252D45709BB9CED673ABA18062666E61687288939CABAA8E5D2E10000A0A20948F62260F05020801FE355D07071850736276BBFFFFFFECB7765C81BAF1F4E3A4502A2534516EA9E5D9996251496DB0D8DFCCB3772D0C0B3B83B8B8C9C5BF853608082C72C1C7C9B28C4C382D312C1D386CA3CDCAA4540E00001A4EA7D9DDE6E9D5B2611F0000103B5A8BBBD6CEC8AB5C1500002876C1D8E9E2D5CB741D003493BAC9CED3D7CBBAA2733508001A69A1B0BCC6ACA355010000144C81A1B4BBB58F45040000224137220F000000000000ABD6ECEBDCBD9E705A525677A2A5938992875D200F00000F32799BC9DAE0C2935124204870A0B5C7D581B8A876625F6F7F6C6D7F94969DA883541D0A0005102B92875D200F00000F01FE365D070718607B6A8DD2FFFFFFFEB3736A90CAEEF8E3984E2825395D7AA6E9D6986B514F75AED0DFC6AA702304134689BBBFBDC6C07C2A01042C73C2CECCB38A54413B3F36233874AEC5CCA55C0C0000105CAAD1F0E3DFD3A65E0E000019447095B2C6D4C8A6620C0000277FCAE3ECECE9CA6B0D003793C1CED3C8CDC5B19763330B000E5FAEB9C0C1B9A552000000135184A2BBB5B88C3B000000243D3A281705000000000098CFE2DFD7BB996C5241415D8597847A8E87591C0806000C2E74A1BFD1CEB993502A204C73A9C6CFD772A79F775F5E7A7171748A9A97A1A180471801000010218E87591C0806000C01FE375D07071870787B8BDBFFFFFFF7AD6C608ECFEAEFDC9447222E406C7DB1E6DD8F644D4D74B6C7DAC4A56C2800104C86B1B9B4BDC079260000337DC2DAD6B2835237363F36243579B1CAC7A053120000125BA8D5E0DCE2D0AB54050000193D6793B0D2D8CFA1511000093682C5D6E9EBE8CE691304368CBBC7CACBCFBCB5946A300F002072AABBB5B2B4A24F0000001B5C8FB0B8BDBA8D3600000221373A1E0F040000000000A0D7E1E2D8B28A644B3F416B8D9D8589947F5121200D000E2F79A7C2CFCBB17D4B27224681B0C6D1CB6AA19A735F6D787E72748A908C999C754216000406162C947F5121200D000E01FE385D07071880787A97E1FFFFFFFFB15E6893D2F2ECC88946223151738AB7F7E391613F476DB2D2CCCA975217021A4B96C0BEB3C8BF762400053686C7D0C5AC82604A474E4123337EA2C0BAA64D0300000C5DB3D5DBD4E4DEA852030000244C759AAFD5DECFA5530900033584C4D7D9DCD9C85D0900348FC6D8D0D2CDC5AC885D3A1500207AADC2BEB9AC9D44000000236494A0B5BDB78E340000032240402914080000000000AADCEDE9D0BAA070513F4E6B9AA992779A8057270B0A0007317EA8B9D3D3B2884D26244B7DB0C7D9D37FAC976E6173877F7D808F8C8B9994712E0D00000017309A8057270B0A000701FE395D07071890767792E7FFFFFFFAB56B5D8AC8F6F2CB7D3D274063828EBBDCD18C5F484577AFCFD3C996541711205395B8B0A3BCBA6D23000D3787C1CED7A99166434D573E304978ACB6BB9B410200001968B5D3E1DCD6CD9F4D0900002C577FA0C1CDD8C79B3E020000318FCBE5E1D9DDBD5C0A004393B6D1D0C3CCBEAB86604417062B7CAEC7BFB9A89144000000256990A5B2BCB48A28000000293C3C2D14000000000000A1CEDDD5C3B195604D3A4B678A9C868D8E81541E060C000D3978A0B0CBC3B07F4124223A80BACBD6CF77A19364536C8784818290948A918D6C290F01000914448E81541E060C000D01FE3A5D070718A0727C96E9FFFFFFF7A1636587C4E9F3C76C342B3E648E99C7ECD3844E424675BDD3D1C2905419042968A3C2BAB0BBB46C1A00083E87BDC6D4B3745A495E5F4E34427CB2BEBE9A340000001361B4D9E4D9CCC494430000001F5279A3BDD9D8C198420400003394DDE4E6DDCFBC550A004094BBBFCACBCBB6AB7A60491C0C3C7BACBABABABB9C38000000265E84A4B6BDB38536000000253E30270E000000000000ABD2EEE5D8AF8A61493C527DA3A78F879C7F481B140B0D0E3887A5B8C7C5AA89482520497AB0D7DCD17FA28D6C5661838F878D96877F8B9270280400000E18459C7F481B140B0D0E01FE3B5D070718B06E7793F2FFFFFFF89A645F87C2DDDFAC6A37283D7A949ECADFCB855E4A5583C2D1D2C086480E00296EB0C2BCA6B2AA661B0010488DC1CFCCAD7A614C576E5B324083A8BAB793380000002466B2CCE4DAD7C47D2E0000002E6592BAC7DBD0C798360000053B8DD3DEE2DFD8BF570C053F8EB7C0D0C7CAC4A37E544419133777A6B2B2AFB79638000000226693A6B0B4AF842700001D33473E1C0F000000000000ABD4E6DFD2AE8C63524E5D819B9983879F885A2210120B0C4A87AFBABFB89E73402826417FB7D5DDD87FA38662536786908485908682958B611A0600000D1E4D9F885A2210120B0C01FE3C5D070718C07E7D9DFCFFFFFFF39A655E8BC1E2D5A762342C5187A3ACD1E6CF8058424B83C0DBCFAE7D450E092D6FA1C5B3A2AEA1621E000C478FC5BDCAB78C644E637A593A4685AEBEB1952E0000001C6AB2D0DEDBCDBD743600000C32719CBAC0D5CEBA8D3A0000004198CAD9DAE3E0BA4902004293B7CAC2CEC6CAA6624D411A0D418FA6AEC0BCAB862C000000336B8CA5B3BCB27C2600000A3A43341E09000000000000A4D6EEE5CDB589483E42527CA2A4949CA08155280D0F03063E89A7B9BEBDA6723E1D2A508CBAD4D1D1759286685976959486889583888A896221060000122260A08155280D0F030601FE3D5D070718D076719BF2FFFFFFFF9F56548AC0E4D9994E29315792ABB6D5EAC7785B494E86B8CDC5AF7D3B06072C77BFD0B09FAFB6671A000F4C8FBEC9C8AD896D4F61745933467BA7B8B2882F0000001A6BB6CBE0D7C4A86E2D00001245819FB5CFD7D2C5912E0000044FA3CCDADED9DCB7520F005298BCC1C6C1BAB99B5E5547231B4585AEBBB2AFA9882A0000082C718E9BB5BDB17F2600001330412F180E0100000000009ECEE6E2C2A67D553D364D79A097898BA793601E090D101142879DAAB9B3917535181B4685C0D4DFD680A183655569919792999887869490501915000004245AA793601E090D101101FE3E5D070718E06C7FADFFFFFFFFFF9C576080BED5C39358303A68ABC4C4DDE9BF77453E5187C6D4CDB3773008002F79BDC5A9A1AAA9571300155192B9D3CEAC805E537182614250829FB2AD88300000002767B2D0DECEC1AE682000000F508AB1BED3CFBDBD8F320000053FA7D2DEDCD4D0AA48050554A2B2BFC2BBBFB6945C4E432A1A4A89AFB8B0ACAA81260000013C7B8B9CB1BEAD692100000D2F47322310020000000000A6DBE8E4D1A6815A333C4E799A9F919BAA9068260D170915568A99ABADA1955C2A1D214C89C8DADDD785977D5859739594939595817D92905818000401132A65AA9068260D17091501FE3F5D070718F0737FB1FFFFFFFFF7975A5A8CCACCBC82422E3C67ADCCD8DAE6BF754E3D5788BACEC7B1652900033579B3CCB8AEAB99521400115AA1C8D0C8AD876553787F5A374680A5B5B99129000000206FB3D7D5CEC79C61210000124E8CB3C2CACECAB97E2B0000064DA1CCDDDEE4D9AF45000B52A0BBC7C6C9C5BB8D554E3915165291B0BCBAA99A741A0000034A7B8C9CB6B3B36E1F00001A4346361F09000000000000A5DEEBECD7A67F4936335679AAA2918FA8926D2C1D0F0623719D9A9DB19D865B2F1E20428BC2DBDCCD7199815D597083999EA698787D8D8148160401000A3176A8926D2C1D0F062301FE405D07071800707BABFEFFFFFFF8975B5989B9C6AE7434253A6FBADFDDDFDAB26E4C365594C7CDC3A869210312448DBADFBAAAA9A05A0F001A5D9DC0C3C9A484655F79845D384A7F9DADAD7B25000000236BB5D1CFC8C2995C2200001C5D9DC2D1D5D5C4B87F1D00000A4B9CCCD8D7D0CE9C3F040861B4BCC8C2C8C1B587544B3E1F265699B2B6AFACA8771C00000C407A8898ADACAF6E1C0000153A3D2D1908000000000000AAD4F1EDD19E785235445685A7A08D96A292682F1B140A3474A3A39C9A968359311C2A4F87C9DCE0D4728E7A605C7498A29FA09E8289A08449100000010D3A78A292682F1B140A3401FE415D070718107A81B5FFFFFFFFF493505985C5C79E7145254185CCDFDAE2E3AD66493D548DBCC7BFA46217020D4A96BEC4ADB2B3A05007041C6096C3C9C8A37E6963797F5D445389A4AFA17A210000002775AACDDBC8C09C5B1900012D74A4C8D3D1D0C4B374190000154C96CED7D2DDCAA43D10115FACAFBABABEB1A57E4B413A1C29689FAFB5AEAD9F6B0D0000135175929FACAFAA611400001439462F21030000000000009ECBDEE2B8896238232946789E9A9FA09D8661291912063482A49E9BA1866F4227191A5192CADBD7C1798972515178939EA7AC927D86928243070002000E367F9D8661291912063401FE425D070718207A8FBBFFFFFFFFEB875B6A97BDB6985C372C4C8ED4D8DCE2DFA15B3B365895BCD6CAA35C2500144996C3D2BEB1B08A480D002067A3BCD0CCA584705A707B56435A84A1AAA071170000002E70AFCBD3CDBA934E180009336DAAC7CECDD3C0A5661900000C53A2CFE1DFDEC89A3600095AA6BEB7BEC3BFB98C4B433E243974A4B4ACA8AA9E650700001C5E849A94A1B29E5C1900001C3B3D2C1C12000000000000A9CBE1D4C39366413032478BAC9291A1A88F662E1B15164589A391969982704B1B15265690CADEDECA75816658597A919FAAA79381879683490E000000103780A88F662E1B15164501FE435D070718307A83BBFFFFFFFFF28D566697BDB288563138529DDDF6E5DAD792573F455EA1C3CEC5A55A10000C5092BDC9BAB1AA833A090A2A73A4C1CAB7A78F5F4E75765C4E6195ABB8A164100000063080B3CBC8CEBD95481D000F3984B8C6DADACCCBA9600500001D56AAC6D0D4D4CC932A021164A6BCB5BEBFB7B57B3A3E2E25427E9EB8B1ADAEA35D000000296B8D8A8FA3AA944803000020403E311304000000000000A7D4F1E4C09D673E302A4983AD9494B3B2A06D321D0C134D93A09C8E99745A3F191329619FC6E2DFC07982685B597B9AA8A7AD9A8687927A3F08000000134681B2A06D321D0C134D01FE445D070718406C88C5FFFFFFFFE0844D6598AEA27C4E3432599CD6EFE9E4D79558364A67A0BED1C09F5116021E4C9BC6CFAEA7AC863B0E06296CA3B6C3B9A3966C4E6D82664C608AA0A492620E0000093A7AB4CBC2CDB89444150111458BBFD9CFC5C0C0A75E0300001B59ABD8DAD4CAC18123041E6FA7B0C2BDBBBDAC703D3B29274C7FA9BBB7B3AB905000000020688E969BABAE8D450A0008203D3D2C0D00000000000000AEE0E3D9B2885B301E234C85A99D9FA9A88A5D372023245298989493A179583C211F274CA0D7EADEC47185644F4D658AA7B4AAA08A899E784A1100000015498FA88A5D372023245201FE455D07071850737BC4FFFFFFFFE281525A9BB1A7774A1F3C5B9FE0F2E6E5D8824A3F49649ABEC8BF974919041B5DA3C5CAB2B0A770310611337FB8C3C7BBA38A67556D6E5E566993A6A18D4E0E0000094079B3C1C1C2B88B3E1500155292BACDD2CBCEC3A1530300001D66B4D3DEE3DBC28528002581AEB8C4B8B2BBB17040322726458DABB5B7B2B2944D0000002B6F8B8D94A2A4852E04000021443A240D00000000000000A8D1E3CDB4895731222B528AA79C9CADA791642B1611286B99A0989B87614C3C1C141D58AADBE6D7C6748962574D7394A6A9B3978190A07C40020000000E468EA791642B1611286B01FE465D070718607387C4FFFFFFFFD97B5266A4B4A37146373D66AEE4F6ECE6CB7942343B699FC0CABC9E4509002166A7CFCBBEB9A05D2200023987B3BAC5C9A28F654C6B7463597291A59D8747080000063984B3C3B9C6BF934D1C04185398C3D7CECAC6BDA34F000000205EB0CCD7D9D9C0731C001E72B4BBC8C3BBBCB66D2B26231A4F8BB2BABDB7B293410000023972909095A8AA7D3302000121362F1A09000000000000009DCFCED1B784533127275181A7A9A0A9AF875A2A1E142373A9A99A928365432B140E235BA3E0E5DDB9738165555A76699DAFBD9E919BA0803805000C0711438DAF875A2A1E14237301FE475D07071870788FDAFFFFFFFFD27E5C6B9EBE9D6F44334172ABE7F6F5E9C57D3B31486CA3BBCCB88A400E022863A7C5D1B4BCA6682A0513438FAFC4C1B9A3835B546F79726A839CABA57F3E0000000C4382B9BCBFBEB08D421707225D9DBFD9D8CAC1BC8C40000000176AB2D4E1D5CDB87321052B80AAC0BFC1C3CBA362351B11235294B4B9B3B5B28A35000001447A8F8D9BA2AF762C020000223F37240E05000000000000A2D9E1D4AF6E472D21254F8DAEA3A9AEA58489401D0E2678B0AEA28B7D4A2C2714222B5EABE6E8D5BC7980614C546F90A1B4B8AA989F9E79390800000411508DA58489401D0E267801FE485D070718806F95CDFFFFFFFFD2805D6DA0B2966A442C3C6DB6E8F3F2EBB666322C3F73A0BDC8BA893F12072E68ABCCD8BFBDA96E1D000A3D90B7C2BEBFA4875C5A6E66605D7D93A99A803D0000000A4586B8BEA9B7BC96531C051D5FB2DADFD3BDCCB5812E0000003374B2CAD8D5DAC2760F003780B5BFBCB6C1B9AC71280E071B549CB5C2BCB8AC86380000154E7E999290A29B701F000000283E39220A00000000000000A9DDDFCFAB734629242B4F92AEACA9BAB98E572C11082D88BDA39494845A2F16161F255AACD2E4E0C080866C55556D8AADB1BBA4929DA476300300000314508FB98E572C11082D8801FE495D07071890788AC9FFFFFFFFC6695674A2B494623D2B3C7BC1E3E4E8DBAD5C252D5074A6C1CDC28E3F0E012B79BCC7CCBCBBA45C1200044A99C0BBBFBEA6845C4B68706770849D9FA17B31000000184C8CB7BAACB5C799501C0A267AB3CFCFC9C5BDAC792D0000002F7DC1D7DCD7D8B76413042D8FB2B9B7B9BEBAA6602209001B6AAABEBDBAB4AA80250000095C869D87899BA76D250005132B3833190600000000000000A8CCDFCCA86E3C1F14225587B1B4A5ACA289512B1C183985B7B29A94704E252419112766B3E0E8D7BA7D7D635C60728CAEB7B99A97A89D751C000000001F5397A289512B1C18398501FE4A5D070718A07187CFFFFFFFFFCD725B76A3AF9160372B4991C9E7F1EAE8B8532A29417FAEC8C1AF7D330A08327CBDD7D2CCBFA15B110007498EBEC1BAB8A28A4E436766687087A5A2A3792D000000165697C1B6AEC2B29B4D1F0A2478B1C8D8CFBDB8AD7B20000000397DBCD8D7CDCDAE580B003C95BBB6C4C4C9B5A865210D04226DA2B7BBB9AAB174200000186796A38D8CA5A4511D00000C334435130500000000000000A7D0D5C5975326182125448EB2B3ADBBA986562913083586BCB59A8E77422D20121C3469B4E3EBDAB9877A5D56577185A4C2C0BBA0A3A4752400000000125E95A98656291308358601FE4B5D070718B07393DCFFFFFFFFBB765D719EAE8E63322E549AD1EEF4EAE1A44B231E4979B5BAC2BD83360F08317EB4CFCFC8BDA74C0B000C4C9AC5B9B4ADA08A55445D696E7592A8A6A673330000001C6392AEB1A5B7B59946160D3889C3D9CACFC5BDA06A1B0000003A8ABECAD1D2C7B254080D519EB5C1BEBABCB09C560D00002A7BB2C9C1B6B0B369180000256E969A8486A59A601E0000122E42251302000000000000009FC2CFBB8F551D121127509DBEABA89C957A442511104894B9B4AB9D713A21111620316CBCE4F3DFBC8171685A546B94A6B9C1ABACAAA277240000000020679E957A44251110489401FE4C5D070718C06F98D2FFFFFFFFBB745971A6B39658323C6697CCDFE5E7D7A05620265196AAB6C1B987340B0B397FB2BCD6CDC39D4D09000D50A5C0B7BAB49A7541445A6476849D9D959E6A230000002664A0BDB39CAAB6944B18104092C7D7DCCDBFBA9F5D0F0000035098CCCED4D4D9A5440009509BBABBC2B1BCB29E540E00062B75B3BBBAC1BAA46516000025779C9C88859B95512105001030442D100000000000000000A6D3D0B78947210E0C225195B8B5B2B2A1753E121318569BC2BBA79F612B11121215316FBBE7F1D9B47E775C50597290B0C2C7B5A9A79F6A19000000001B6591A1753E121318569B01FE4D5D070718D0769ED8FAFFFFFFBA6F57709BAD915A34295EA9D1DEEDE7D78E3F18265B90B5BCB1B3792E11173A85B9C8D2CED1964717000B599CB9B3A5AEA37E3B3F5C687F86A1A99A9E661E000000286CA2C1C0A4ADAB97591C134B94C7DDD5C4BABC9E5E020000005097C4D1CFD1C7A241020A5EA7B8C5BBB2B6B5A15A0900002D84B1BBC5BBB2A864100000377BA2A38B8DA896501D0000223B3B18050000000000000000A9C8C7B2894615171B2B4C98B9C4CDB5A37D5223120B42B0C9B7A88D682E000E18163072BFE8F2DBAE8A77625E53698BACC1C7B2B9BF9E6514000003061D6399A37D5223120B42B001FE4E5D070718E0789AE1FFFFFFF9AB624F76A5B38D52323167A9D3E3EFE4CC822C15285F97BEBCC0B580390E0A4C86BEC9C8C3C79C4700000448A1C4B5AAB3AF7E4643536C848BADAEA5946A18000004326BA6C1B9AAACA98A421B154B98C4D1D0BBBDBC934C0000000850A3C8DBD5CFBC8F2E000E63B5C1C6B9B7B8B5994F0700002B7EB7C5B6B8B79C510A00003683ABA79086998B5218080C223B3518000000000000000000ABCFD0B7793611071921539DC6C3BCAE9D834D2316194C9EBEB0B2975D291016231F3A79BEE8F0D5A97F705D52596589A6C5BFB3A7B1A064170000040425659B9D834D2316194C9E01FE4F5D070718F06B9AE1F7FFFFF1A16A6485A4B284502D3567B6D9E3D7D9C97F34151C5692AFB8B3C28B3210155190B9D0D2CDBE994A04001154A9C4A5A1B29D6D3E3E53647C99A4A89F985D220000073472ACC2B69DA8A28749201D55A6C3CCD0C4C5B38E3D0000000263ABCFD3DDCDC2882D04125EAFC4BBBEB0AEB49D4D0A0000348AB1C5BAB8BC9D4B000000388DAFB594869D8E4E1C0000213A3515010000000000000000A3BFBFA06E2B0C040C2156A2C7C4C0AA9C67331D1C254BABC0BBA8946310011F18193880C1EBECDCA37F725752587192A7BCC3C4B5B59E5C0F0000000825759E9C67331D1C254BAB01FE505D0707180074A1DAF1F2FFEA9F665A7EA1AD905433447BB8DCDFE3DEBC6D25092C5EA0BABEC1C2833211194E90AFC1CEC7C1923701000851A6B69AA5BEA9633A344F63879DB2B999934F1300000B4373B2CCB4ADB1AB813F0F1F5A9FCAD9D2C4C7B781340000000F70AEC8D5D6D6C27C24001971B8B4BCBDBDB8AE9B4C000000358CBFC8C3B7AF933E000000498EB3AF878D9D87471A02041F373416020000000000000000A0B7AE89591800030C255994B2BDC6B896562F181C2158A9C1C1B2945619040B0C213980C5EFE3D3A88A745553596982A3C0CEC0BDB893571000000B072A699896562F181C2158A901FE515D070718107BA3EBFBF7FEF09B69658CACAC854D2E387BCAE3E7E9E0B758150B226BABC8BABFB5802C0B1C5A91B3CED4C5BD8E3704000D60AAB79BA1B9A5683B374A6591A4B9BAA6975E130000063F82BECDC6A9ABA06F3A1F215CAFCCD1C8C1B8AE732C0000001A73ACC6D5CDD5BD741300197ABCBFBFBDB9B9B19749070000439DC4C2B6BFB39138000000498DB3AD98949E75381E0B0C243D340C000000000000000000A3C5CA814D170005132867B1C2D4C6B1865E4127132764ADC9C2B896541800070C1E397DCAF1E7CAA98D714D60587E85ABC2CEC7BCBA9763190000000C3078A1865E4127132764AD01FE525D070718207A9FDDE9E8F2D48D606688A9A77C4D364081C4E5E4E1D7B35511001B5F9CBDC1C2B9812F070F4B9EBEBFD1C9BB933E00001B64ACBC9B9ABCA5602833436296B0B8B196915C0A0000154290BDCFC4ACB39E6E29141F66AFCED4D7CEC3AA6D1E0000001278B9C8CDD1D1BD660B00217ABCC8C2B6BBBCB4984402000047A1C6C6C3BABC86270000096098B0B08E95996A321600082B443911000000000000000000A1B4A2773B0F0000082169B0C6CFDDB9854D34241C2A69A9CAC3B1954C0B04130D1D4192C6EEE0C39A8E63483E4D6888A9CBC9C2B5BC986412000000002D7C9C854D34241C2A69A901FE535D070718307EB1EBF1E4F6DA8B63688AA7A6813B24428CC8E0E8DFD2AD490C00206FAACAC3B6B66E3108255E9DBDBCC7CAB5933900001A649FAE8F9AB8A35A32334C7799B6C2BEA08C550E0000174684BAC0C0A9AF9B662E171F6EB4D4CFCCCBB8B36917000000217ABAD9D9D8C9B56106002778C1C5B1B7B4B1AA873D0000004EA1BDBEB1B7AE832E0000165FA2C2B09994A36E3213061635503718000000000000000000A3ACA673450B00000D2465A0D7D5CAB18C4D322A21296EB0BFBBC3913F0C00060D234A8BD8EAE8C4967F644E4348637EB2D1D0C6BDB697550C0000000E3C779B8C4D322A21296EB001FE545D070718407CB3ECEADFD8CB846A698AA6A37F472E4B8CC7DBDFD0D0923B04012A72B0C6B9B7B37929021F60A4BDCEC2BFB4863100001F63B3C5939FB5A35224274776A0BBB9B1949045060000265E98C7C9C3B3A18E602D15236FAFC8D0DACBC1A3680D0000002887C4CDE2DBCBAF4D04002E8EC5BFB0B3B5B0AC85370000005CA2C7C8BAB4AF7E2500001361A7C2BB8D8A8E6134140B173554320D000000000000000000A0A99D7137030000123A77B4D8D4D0AF7C534330262F6EB1D3C5B28D38070008091D4D94D0E8E9C0917F554D4D48547F9CC2D7CFCBB49B5B130000000A44849F7C534330262F6EB101FE555D070718507AA9E9DCCCDBCC795E6D91A4A2753A2E488FCFDDE3DECF833100002A6FB1C4C2C1AF7027062565A2C0BFC4BCB47F2D0000226EB4BF9BAFB59F532728476DA4BCBAAA8D884C050000204E95CCD1C6B7B2965625192C7AB1D4DED6CDBEAE62040000002C96C7CBCCC9D4A951050D4291BABFB9B9BBAFA4873B0000004FA1BEC8C2BFA9701E00002272A3BDBA9C968E643B1303113D4B2E09000000000000000000A0B29255240000001A2F73B8D6CDCDB8855434382E3376BDCFC7B0883508000004214890DBEFEABE83856848403F557AABC8D4D5D5C29A590E0000061851809E855434382E3376BD01FE565D070718607AB0E1DBCDDFBC734F6B8C918F703324519FCCD8E0D4C0792200002B7AAFCCC7B7AF75290A277BABC0C2C6C0AF7B2900001C75B2AB96B1BE945226203D78A7C1BEAB948544020000285B9CC4D0C3C6AE784A1B0E2A71B4CCD6D6C4C0AA51000000003B8FBAD1D1D7C9A0400000398BC4C6C2BEB0B3A5793B07000C60A4C1BFC2BFA56A140000226DABC7B2959396632C160E254B502B000000000000000000009DAC9063220000020C3275B3D0DAC9AD7342313D2C337DC5D3BEB1823200000003125796CEECE3B98E86604940495077AFCAD8DAD0C2954D0D000002135D8DA07342313D2C337DC501FE575D0707187074AED5CDC5D2AA6F596689968A6D332C4A9BCAD5E0D6BA6C1C0000287DB6C7BBB6AC631C072E87B2C7CAC2BDA6712400001D70C1CAA5BACD9D481C1C40759DBABCB69E773400000525609DBBC3C4C0AD7D461F12297EB1CBDAD5CCBFA147000000003491CED1D8DFC79B3500003B93BDC6C0C3B5B7B480320000085EA6C8D0BEB0AB660900002A76B0C9B09B937E5C2F1C0A1A3D4F290B00000000030000000094A688591F010000103878B9E2E3C8A87A43403B203E8CC4D7C5AB7D300000000726589DD6E6D9BA828558453638497AA7D7D1D5D4C2904A05000006266999AC7A43403B203E8CC401FE585D070718807BB3D7C0BBC1A86058708B9C8E6D3927549BD2DCDCCFB15E0E00002E7EB3C3BDBABC6C23113B7FB3BFB7C2C2A86A1D00002378B8BFA8B2C3A04916164380ACBABFBA8D74380000002D6BAAC5C9C9CCAC774118102A7DB5D5D9D7CCC09745000000003E9FD2D5D3D2C38F36000148A1C7C0BBBAC3BAAF7C3405000C63A9C6C7BCB5A6630000002C80C1C3AC98978557331A0A2848592F09000000000000000000A3AB895118000000104A8DC8E1E2CDB57D523E423E418EB9BDB8B07E3800000002235F9CD2EFE4B67A8459413B384D6E9FC7E4E7DBC78D4B09000004246D98B17D523E423E418EB901FE595D0707189077B7DABFB1CCA0615B7688948D5C222559ADD6DDD3C8A95F0900002F80BCC2C4BCA8631E0D3383B2C9C3C5B297550E00002E86BFC2ABBEC59B4A191B3E7DB1C1B7AD8A6C2E0000063B71A2CACAC3C1A66B3913172D76BAD4DFDFCEC1953E0000000746A0C9D3D8DCCA882C00003F98C5C9B4C5BEB4A9713702001366A7C1BBB8BBA351000000348CB9C3B99C8D8C59301E13335153320300000000000000000095AC854E0C000000044285BBD8DDC4A267453C422F438AC5D4BEAB7722000000062B65AACFE0C6A8747E51342E2E4171B1D7DDE0C4BC7B460C0002112F7C97B667453C422F438AC501FE5A5D070718A080B3D2BAB4B8A461546C848A804F262F579BCADBDECB984A0A00003783B6CDCDC6AB6217143D8FBDBCBBB5A6874D10000A387FBFC5A9C3CCA24313153A7EABC2B8AA9273310000004277ABC6C4BDB9A3642F0E0F368BC0E1E6D7CAC6932D0000000856A7CED7CDD6C38236000657AEC9C4B7C1B8AB94622F01000D62B3C9BCC3B6A3510200003789BAC5ADA69E7D4B31261E375E532B050000000000000000009898763C0000000004388EC7DFD8B8976447463E304188C3D1BCA27122000000123E71A8D0E4D5B16F844A29242B3D68A9CEE2E3D8C4914B090000063C80B2BD6447463E304188C301FE5B5D070718B075B7C9BCB4B394534A698C91754824265EAACBD5D0CA8F41000000408AB8C4D2C0A9551E133B95BCC9BFC0A3804A0A0008338CBEC8B8C0BC943C05103388AFC9BAB29164250000033C81B2C6C7C7BA9A57230B092F7CC1E1E4DBD1C08829000000125DB5D6DEDBCEB67B2100005CA5CCC1C3C2B1AE9C5E280200116CA9BED0C7B59E4B0500004295C9D1B6A795744034291F3D55522802000000000000000000939E6D3D07000000133F8CCFD8D6C6975B394D39283E92C1D2CAA6761C0000020D3775B7E0E6D2AD6F825A392D2A3B6EACCCDCD8CDB58E510C0000093E8298BB5B394D39283E92C101FE5C5D070718C07FB7BBA9B0A68854526986867B502A3561A5C4D8D4CC9A450000003789C8D0C6C9A45718133E99C2C5B9BAA3743B060009398BC8CFBBBCC4993F0B033B8FBBC6B8AB9363200000065079B4C4C3CCC18C4C1B04133677BDDFE4DFD0BA82240000001D67B7D3D7D6D5BD6F1200156AAED2CDC0C1B5A88A55290B00176FB5C1BFBDB0943C0000014A99C9C5BB9F9E734536291F4965582A06000000000000000000A1956C3902000000114F93BFDDD0C5965E405449254587BFCDC9AC6F1E0000000B4184B7E0E8D098647C522D2A253E60B4D6EAE4D6BA844A0E000012448BA2B35E405449254587BF01FE5D5D070718D080B6C6C5B1A870454A6681866B491B1F59A2C9D7D9D28F320300013D91B0B9CABEAA56180A3C8CBBBDC8BE986E3204000D499ECCD5C8C7BE8A3708073E8ABEC1BAB6975D180000064381B2C6C2C6BA8E3F170F153886C5DDE2DCDBC57C210000001F6CB4D0DBDAC9B76A1100116AAFC9CBB6C6B0A08455310E001877B3C6BCB7B28D4100000A4A99C3C4A89A9D74423D252B4965592C00000000000000000000948A69290000000016549DD3DAD3B995583D493E2C4B94C7CCC1AE73200000000C4384B7D7DECA915D7A5343312E386EB4D6E2DFC6B57B3B080000134F8AA7B6583D493E2C4B94C701FE5E5D070718E06FA1B3A89C916D4A4A5E8087684117235DAAC4CFD6B783330000003C9BC1C0C5C09F4E11144C95B9C2C1B4915D1E0000144AAAD3D4C2C5C58D3702113B8CB5C0B4AB8C651C00000D4D83B3C9BFBCC18F39130016358DC9E7E8E3D5BB7311000000247EB6D1DCD9DCAC5E1600206EB4D4D0CAC2B8A16F4C3308001174AFC3BCB9B8893702000D68A7C8CFAEAAA1663F3D282E4B69582D0000000000000000000096986D310000000014549AC6DBD6BC8C674C4930264692C5D7C6A36C1C000000174E94C6DFDFBF8B5B7E4B3129273967B0CFE2DBCAB173400600000F5A94B0B6674C4930264692C501FE5F5D070718F081A3ADA29C816337446C868862351C2B63A6CCCFD2B37C21000000489BB9B3CDCFA44811124193C2C6B6AD82522100001557ACDDE1D4CFC290360203378AC4D3BAB38E5712000010598CB7C5B6C0B6823811071A3D8DC5DFE5DED6BD6B0A0000002888CAE2D7DCDDAA5506000772BCCACABCB9BA9A7540260E00277ABEC8CAC7BC812E0100195DA9C5C2AEA49266443A2D39577C5D23000000000000000000008D835C2A0000000025659ECFD9DABD8A5F3441362B4FA2CBD1C9A467240000001A5189B8E3E0C08F57854F3229283362A5CEDED9C2B3783E1204001A5EA2AAB95F3441362B4FA2CB01FE605D0707180078A9A9A7A482572F486E83875F2B0F1D61A7C1D3D2B374200000144EA8C1C8D6C5934A18113E93C3C1C3AE874B1500001862A6D2D7D4CFC7903206054295C3CFBFA58E460B000018599FBFCBCAC5BA85311509114088BFDCEAE5D3BB63080000003A8BBDD2DAE2C59C4A0100247DB3D1CFD2C3AD90552E1A09002380B8CAC5CABB7D3307001767AEC4C1B1AD935A3C332B34678C6B330100000000000000000097986A23010000002B78AFC3D6D9BA8A573D4C382A5BA0CECCC2A270260000000A5091CDDCDBC08D5C7E47302B293362ABDCE9DACAA66B2C0202001859A0AEB9573D4C382A5BA0CE01FE615D0707181077A4B0B4A37A4A293D6682855F2A142568B6C4C7D0B6661F00001255AAC3C5CFCF8F40140D4095CBC8BAA56A370B00002461B4D3E2DECEC3882F060D3D95C5D5C9B99B4B050000226096B5C3C8C7C1832A1203143B8EC2DCE3DFD5B962070000003992C9DCDECDD1A03E00002688C6D7CAC1BEAF9C60281A02002E7EAFC8BEC3B781360001206DB8C3BFACA48A5B433A38425F815C29020000000000000000008A845A15000000052A71A0D3DBD3AB7B4B41433D2D549FC8D3BBA863180000000E4F94CAD6DDC0824E7E4C37352C366AADDDE0DBBDA0792A0300031E61A2B8BD4B41433D2D549FC801FE625D070718207CA6A9AF9D78472E315F7B90632807276CAEC2CAD0BC621600001B61A9C2C7D2C7833D0F124E9ABFBFADA0672E0C0000286ABCE0E0DFD2BE7A22000C478CC2C8BEBB9A4B0A000022699CBBCDCBCAB5792E01000E3B8FC5D9EFE8D7BB5E0C0000003D90C9DCD9D9D0994106002F8AC5D6D1BCBBAB9449241B00002A85BDCDC2C0B07E3300002576B2BCBDA1B090523B433039718C6A3000000000000000000000827B550F0000000034759DBCD2D4A37D54393D30265EACD6D4BE93510D0000000B5B9FD8E5DCBC7E53814D342B2B2E67B3D6D8D6C199672D020000297DAAB9BF54393D30265EACD601FE635D0707183070A1B2B2966F361B345C868B5421112E70B2CDCEC9A765160000176FA8BEC2C8BB8F4312133F9AC1C1BA9C682F0900062F72C0E0DFD6CBB97C2600003C91C2D0BCBE9246050000216CA7BDC8CDD0B978210303163F8CC4E3F0E3CCB5570300000959A2D0E0CED5D68D3300002F8FBECEC8BEB7B48A43251F02002C83B4C0BABBB4793300023485B9CDC8B6A8864B3F4337447D91652D0900000000000000000085794903000000004781A4C5C8BEA06F492F3E262161A8CACABA8F4D13000000114E9ED1E0E2C28851834F3C2B273465A7DBE1DBB88E66300000032E81ABB7BB492F3E262161A8CA01FE645D0707184075A8A6A98958251F396084905525072E73B9CFCED8AC5B1400001665B0C9C0CABE7C2C0A1C54A1C0C9BC9D68200000023A82BADFE1D2CCBC6E25070E499FD1D4BEB78F4A0700002272A0C4C8CCCEB8761C0000023B85C6DCDFD7D5B65C0000000856A3CBDEDBD6C18E3300013B90C8D6CCBCBBAE7D4320130000328EBDCFC6BDB2732A08033686C6CBC9B09D7148393F3B457991632D0400000000000000000085785111000000003977A7B9D5C39565432728252B6EBAD4D5B09C5015000000085FA5D0DBDCBB765183472F3326346CAEDEE8DDBF8A5D300000002B85B7BCB9432728252B6EBAD401FE655D070718506B8E8F91855021153165867E5C160C2C78BAC4CCBEA9581500002272BAC7CAD2B26F2808185292BBC6AE9E5C200000013383BFDBE2D9CDBA65160410489ECAD1C2B890480000002F76A8B9C4D2BBB6701E000115448DCAEBE6E8DBAA53000000145CAAC8CFD6DACB8B2C0006419DC6D3CAC5C0AF7B3109110000418FBBD1C3BAA36A300003448CC0D2C9B1A17B4B44492F53798A653007000000000000000000866A3D00000000084480ACC4C6B9925E3A17261E3472BAD5D6AF8944090000000F59A2D9E4D8B2804C86402A312E3974BAE3E4D7B28652230000053B8EBDBFB63A17261E3472BAD501FE665D07071860739E9EA480491819386C9E965720132A6DA9CEC6CFA546080000287DBDCDCAC9BA792B021A609BC3CBAF945A110000063990CBE0DACEC0A56C1A000D59A4C9D2C2C189400100012C87A9CBD0BCB6AE6718000019488EC7E5EEE6D1A7550100001A67B8D4D6D1CDC77F2E02024D99C1CCC2BEBFA96C320A0A00033892C1CFC2CCA3652508033C91C1CBC2AEA57A4449403C598C9B6E3400000000000000000000916E3200000000054E82A9BDCABC97633824291B207CB8CDC5A885440A0000000F5BA2D8E8D9AA7C548B483532323172BED7E4D6B78A531A05000042A2C4B4AC3824291B207CB8CD01FE675D0707187078A0B0AC82491D1E4B72A5A56C291C3F72B3CDC8B8964B0C00042B7FC3D7CECCAA64190A1959A6C6CABD8F4C1A000000388BC9DED6D1C1AB590F00135AA6CDD0C5C7964C0000002D80B1CDD0CFC1A85C1602001B579CD2E6EFE3D19C420000001D78B2DACCCED3C07422001454A8CFD3C8BFBBA8651C00000009449BBFCFC2BDA05F290C14519DBBC4CAB6A96C3C403E3F5B93A4713700000000000000000000786F3B080000000D639BA7BDC5B896684028241E3678B2CECDA77B3F030000000B63AADAE6D3B47F548C4B3D3535467FBEDEDED0B3814C1C090000489EBFBDB54028241E3678B2CE01FE685D070718807594A09A70350B0F3F729EA05612072F77BDC8CEC491370200063798CFDCC9C39B5415082165ACC5C0B39551110000043D8EC0DFE0CEBCA35F1B050E57A3D5CDC5BB87370000003482B4CAD0D1C1AC631200001C5299C2DDECDDD19B400000001C79B1C9CED5D0C77326000957A5C6C7C2B7B79E6D270700000A4390C6D0C4BD9E6126071654A7C3CECEACA367404A47406696A67533060000000000000000007A6A390B00000013527DA1BDC3B193603C2D2D172D7CBAD1C3AA7C32000000001067B2DADCD8B476498F40323332417CBEDDDFC2A37D462300000A57A5BFBDA73C2D2D172D7CBAD101FE695D0707189078A4ABAC72410F1D5081A7AA5C210E307DBAC3C0C2884204000450A2D6E2DDCF975C11021A5E9EC2BCBB904113000003488FC7DBD6D4C0A55114000762B6CFD4C3C38B3C000000347FC0D2DBCDC39F5512000426599BD2DDE7E2CAA23B000000287DB9C5BECCC6BA671E001562B7C3CDCABCB9A9641E0400000A4195C7CED0B08C5B2D051B59A6CCCEC4B29865374C4E455F979F6B2E04000000000000000000765D21000000001557839AA9C1B68A673726201A3385B7D7C4A46B2A00000000146EBDE3E2D2A7773B9152353B37457FBDDFE0BF986B331500000A59A9C7C1A83726201A3385B7D701FE6A5D070718A0679498925725040D497BACA75A17133778B6BEC3B3853700000E4EA0D3E0CBC7874408023371AFC8C7B08E4A070000074996C5E2DAD2BB8C3E0C001B66ADD7D5CDBB8A37000002328CC3D7D4C7BF9D4F0800082F6CA5C3DCE1E3D39B350000003487B4D7CCC9C8C2661B001065BBD5D5CDBCB2A15A0C000000084B9BBDD4D1B1804622051F67ACC4D0CFC298623A4F4D4D6796A4692D020000000000000000006F5A29000000001E618D9CAAB6A985592B1814103085BECCBEA46C2900000000187AC7DFE8D4AE7E3F93493235384A81BEDCC9C29E6E2F0D00000666BBC9B8A12B1814103085BECC01FE6B5D070718B06F95A38C56240A1D5A8DAAA961271C3F89BEC2BFAB7B2A02000958ABE0DDD1B886360B00347DB1C8C8B78B4507000008488CC0D6D6CBB7873802002364AACCCBC6C18C33000000358FC3DBD0CDC4A35906000A34759DC6E0DADBCC9D420000024290BBCFC9D0C4B0550A001568B9D1CCC6C0BDA557090000000851A2CDD1CBBA804827112260B1C9C9D4BF9B563948474066A6A169240E000000000000000000785D29000000002564859EA4B3A98558282026174E8FC0CBC09D662B000000002F86C3DFDECBA8724290362B353B4F84C1DCDBCA92572D0400001B6EB7CDB59B282026174E8FC0CB01FE6C5D070718C0759F9E88581A021F5B84B0AA591C0A348ABCC2C6B6772F00001058B3D7DCD5BB7C2B090D4082BDC7C0AA7D3A0700000D4D96BDD0CFCEB0873702002B6DB9D4D7CEB8742900000C3E92CDD5D6D2BB944000000B4485B4CCDDE3E0CA9433000001459BB8C8CBCAC6AC5712002278B9CECBB9B7B39A4C000000000E52A2CFCDC2AA7249300D2478B6CBD7D3B89962415A514863909C6723000000000000000000007C5C1B000000003E6680919BB9A68556291310254EA0CAD0C18D5D24000000002980C6E8DDC9A17844983E223A3A4E8FC8D7E6C5A656240000001374BECBBD89291310254EA0CAD001FE6D5D070718D087A5A392532812326499BFA4562916498BB6C6C1AC702B02000760AFD5DDD5C2752D06084384ACCAC4A7753A000000104C8FB8D0D1C1A5772B01002B75B7D5DCD1BD802A0000073C9DD0DADAD2BA994404000B488DB6CBDBE1DDC4882E00000C409CC3CFC7CBCAAB540F00277CB6CDC9BCB9B3965002000000095E9ACDCAC7B1723F2A1C327AB1CBCFC4BA8A473B4D4742749B9E632B0000000000000000000075511600000000306E80899DB7A4804E1E0F1B23498EC2D3B6824D18000000003091C4CFDAC1A6824F9C3B3036355D9ACFE6D5C484471A0000001F7ABDCBB1901E0F1B23498EC2D301FE6E5D070718E0769BA08C51220E376A99C0A2571D114791C8C7BFAD6F2B0000206AB7D9DBD1B66C26050C5098BABDBBAD853C0900000B4D8AC0CFC4C0A4762E0604307FB5D3D0D5B97722000000439EC9DEE2D6BB8F320000114E8BB7CAD8DAE3D5962900001058A4C3CEC9BFCAB0420A03277CB7CFCDC6BFB9964500000000145AA7CDD6BF9667473A1C2D78B4CCD8D2BB834D3B51514C7AA9A26628000000000000000000006D420B000000002B6B8590A2AFA483522912101546A0CADBB689440C000000043A8FCBD2DCCBAA824A96402435365AA3D1E4E3BB823E120100002088C2C6AB8A2912101546A0CADB01FE6F5D070718F074989285522C1B437A9FC2A24C201E509DC1BFBDA16C1F00002C76BDD9E0D1AF5F20071D689EC9B3B3A17B420000000C4A91B8CDCCBFA5701C00082D7CB6D6D2CCBA7A1F00000249A4CED5D7CBB5863100000C519BC3C6CEDAE4CC9130000019569BC4C7C3C7BEA24206092F80C4D6D2C2BBB29B3E000000001E68AECCD6CA94594130163485C7DBD7D0B4853E3A524A4D6FA29F6933070000000000000000006A4C0000000000366F7A8E9FAA9B794E22111C2758AACAC5AF8B4F1400000002389DCEDFDCCBAD7C4C923F2E3236699AC6D6D6A67B3F0A000000208CC1C7A88022111C2758AACAC501FE705D070718007FA99980551E15396A9DBF9D541C235091B9C4BD994D0F0000317CC6E2E6D7B6621E051C5CACBBB7A89D6A2E0000000A5391B0CDCFC3B96C2300044286BEDFD6C6AE6E230000084FA6CBDCE3DFBB772800000C5C9BC9CDD2DEE1CD8F2A00001E5D9EC1CAC0CAC3953E0D113989B6CDD4BFBBB28D49000000001665A9CDD7B8844E42341D478EB7C8D0D2B67341404A4C5884AB9C702E0100000000000000000065310000000000326B858B94A29A743C0A01172560A8CFCCB17B3D08000000114196D0E0DAC6A87E5D9A4D353439649FC5DCD2A96A37050000002699CACAA7780A01172560A8CFCC01FE715D070718107A9B967D452120426EA3C59A45121E54A0C7C5B98D490B000B2D73BDDBDCD0A8510F082770A5BBAEA79171300000000F5587C0D2CAC5A8651F010D3984BDD0D2BFB3791E0000155DB3D8E4D7CCB46D1900001E6DAAC0CDC8D0D3CB832000001E69B3CACDC4CBBA8E35070E418FB9C3BCB8B4BD9C3F00000000186FB0C8CAB0835B493D284F8DC2CBCCD3B06F4038544B5B8CABA2702401000000000000000000632D00000000002B6F818A9A9F9E693A0C03132C66AED7D1B76C32050000000B50A1CAE4DDCDA2814C974B34333E6B9FCDE2CFB66E22000000012490CFD19D6D0C03132C66AED7D101FE725D07071820819FA4824C2A254B81AFC392400F2158A6C7C7A77E39140013387DC3E5EDCFA04808002E84BDBB9C94967441060000125897B4C3C6C1AD781D000C4285C3DAD6C9A96A1700001754B0DAE3D8D8A6601E00001664A8CECCC9D3D8C47E2600001E7AB3C5C6BEC7B88C3B0C2359A0BFC9C2AEB4AE8839000000002883BED9D4B377454B37274B96BDDADECEA26B36394E4D5D8CB39E662A050000000000000000006233000000000E4774848C98A69E75390E08162F68A9C6CAAD7A330E000000065CA6D0DFDBC9A77D4E984F26293E6FADD0D2C7A25624000000003595CBBC9C650E08162F68A9C6CA01FE735D070718307F909A863A1A214984B7BE8A33161553A6C6CEB26C330E011B4585C3D7D6CF9B3E0A003086BFBB9B9E966E3B000000175A90B4CAC7C2A7691B00094394C5CDCBBEAC5A1B00002166B8DFDAD5CAA4612000001F6BABCBC7C6D7DFC1701C0000347CB4C7C4BEC0B4913C0A1967A6C8CDC9B5B0A9984000000000317DB6CFCEAE684C484029559DBBCDD7D2AE663036544B6195AFA76522060000000000000000005C2E000000001A497185879E9D9F72370300184271B9D3C4A56D2D000000001863B6DFEDD7C3A678559D421F314576B7D3D2C49B5B0E000000002197CFCD9C6C0300184271B9D3C401FE745D07071840749C9A84532B254C86B7C28D3D162758A1C2C1A77322080420529AC6D9DAC7943809002F92C0B38A9B8D78310000001C548CB4C8C8BAAA682101144490BFD4C3BFAA640E00002265BFDEE0D9CF985E1700002872ADCCC8CBD5D6C06D1100003E84ABC9CCBCC3B985300F306DA1C4C3CBB0A8A9914400000000338DBACAC7A4624654402D5B9CC8CFD5CDA55629334950738EAC985823000000000000000000005D32000000002347798D898A9EA2722F16061F4889BFD7D1A36B2E050000001B70B7DAE5DBBF9D7949944226334771B5CED2CAA5541C0000000031A3D5C68E5216061F4889BFD7D101FE755D070718508297A08F5D2F345983B6C6833008165DA7C2C8A35A1D0D0B275296D0E1E1D28739060C4394C2B3918B8766370700052E608CBBC9C0C3AA6B17000F4797CAC9BFBAA7511100001C61BFE2E3D7CAAA5F1100001E70ACC5C4CAD7D1BE711D00134A90BFC4CEBBC4B27325112A6AA5C0BCBBB1B1B69B38000000004A94C7C7CC9B5543513E39679FC5D2D5CA9E4C26314D597597AF9A5F2B030000000000000000006B2E00000000295780868091A2996730131027458EBAD7CDA2681F00000000226EBAD5DBD0BB9B7047984B242B3B80B5D5D3BC924B1800000000289AD4C38A58131027458EBAD7CD01FE765D070718606F878F784822224A7DADB4732B151C649FBFBB9F5E22000330599CC9DEE2CB832D00023A9EC6BA838D8A6A440F0003215E8EAFBCC2C3AB641A00084D9ECEDBB6B09E4F1100002B73C9E5EBD3C896500700001D74B0CBC5C0CFCEBC5A15000F508FBBBBBEC1C1BA7023194689B4C5C2BDB3AEA98C37000000004D99C5CAB996483E54453E6E9DB9CACDCA954F1627445974A5B6A168260000000000000000000061300000000020557C8D888F948768250515344F8BC5D9CAA05A26000000001F77CBDEE4D5B6906D50963E22213D72B9DCE0C891471200000000329CDDCC86550515344F8BC5D9CA01FE775D0707187079A49F8D5A37304F87ADAA75230F3361A8BDC19D4F1C0006285A9DCBE1E7CD7C260004489ACABC938383773D030000256589A9C8C3C3B46F1B001058A5CBD3C3BE994C0D00002474C6DDDCD2CA954F0400022D78B4D3CBC0D2CAAC590A001B5896BDC0BDB5BBAF631E104B8AB9C7CFC7AAA1A6842F000000015DA8C4C9B7844B4557433D6BA2C3D1CEBD8843293347527FA1AC986E2B060000000000000000006224000000003D657A8384929E9361290A0C326396C7D4C1995919020000012D7BB8DAE3D3AF8D50419744251F4486C1DADBC3893D0F0000000C45ADD7D07B580A0C326396C7D4C101FE785D0707188073858C7E4123275282AB9B461C132B5E94B7B48E4715000C346AA6C4D5D4BB741C000F4FAAC5B085867B703C000000326294AAC2BEBCA75D170014509ECFD1B8AA904306000E347CCCE4E3DCC38F4C070002327AACD7D2CDD3D6B04F10001F5898BBB9BEBEB8A55F1B1A50A3B7C1C6ACB1A9A79231000000055AA0BCC5B67F3E3956494878A5BFC9CCB9904D21294A5B81A7B59E6923000000000000000000006021000000002C5873827D879B8E6527050B275D9ECCD7B792621600000000367FBCDEE7CFA5855D408F4223254182C3E6D9BF8439090000001544B2DAC18D51050B275D9ECCD7B701FE795D0707189075939994502C264D87A4964F13172A65A6B6B88B460E000D3675A7CCDFD5AF662201115AB2D2B7898B7969390100042D6891AAB9BEC7B1671B001A559BC0C9BDB68C3D0B00042C8DD1E9E3D4BF933D0100002981B8D6D0CBC8C7AE500C002168A3C4C3C7B7BAA05916194F9BBBC8C4B3AFA8A1861D000000076CB3CABEB67A3D3D4B3F4078AAB9C7C8B8863F25234455819DB79E672F0000000000000000000058240000000027597B897984A0916334190D315F9ED5D1C5934A10000000003994CAE1D6B6A38353379A451C23467EC5D9DDC08A380D0000000F48B7E0BF814A190D315F9ED5D1C501FE7A5D070718A0768E8F884732355480A887430B0A34629EC4C6872809000B437BB9CDD2CFB16B1A00105EABC8C0997F7974390700012F65809DBAC3BCB06419001A5CA5C5C8BAB68A380200063A89D2E9E2D5CA9340000003337EAFCDC4CAD6D3A04009092B7098B9BDB8C4BEA955152162A8C2C0BCB4AEACA481220000001471A6C1BBAF7A473A593E4577ADC3CFCDBC792D1722375996A9B99A5B22000000000000000000004C17000000003E637E7C7B8B9E8D6323120F2D649FCDD8C495481100000000448FCAD7DDC09E734B338D311C1B478ECAE3DDB880360E000300174FBFE7CC7B42120F2D649FCDD8C401FE7B5D070718B077899B8755363B54859D793A1225457398BEBB80320A02165391B5CBCCCEAD5D11000C4AA2CCB89D9488743E0C000A3671909FC1C2C0A55116051A5CA7C8CFBCAC81370000053F8ED6EBDDD4C292400000023785B9CDCCCED1C89A3404002E749FC5C9BAB9BCA44F0F2266ACBEC0BCBDA19F9B7B220000001974ADC8C9B26B363A524A4B79A9BECBC2B9783015203C7293AAB8995D27000000000000000000005C230000000041738D89868A9F8B682917173E71AAD7DBC5954B0900000003479AD1E7DBBC8C623C288B3B16214491CEE6DAB47126000000091158C2DDBC813E17173E71AAD7DBC501FE7C5D070718C0878C938D563D4F5D8FA27B340B17416DA0B6B8803200002A68A3C3C3CCC4A75D1000135EB3C1C69D8984793900000B44728BAAB3BBC4A85716021B70AECDCDC2AD7D2900000D4096CDE0E1D6B4873600000C458FB8D6E0D5C4BD812E00003D8BB2BDBFC4BEB69B4E132C6CADC4BFB8B6A1A69A7C21000000207EB3C7C2A35E283341394680A2C3BBC8B26E2D12263F689EC0C2A2682C010000000000000000005A28000000004265827C8292978B5B2D1B1A4274AEDEDBCA984C1100000019549DD4DBD6B285513427903D1727509CD1E6DFB67A2D0B00050C1663CDE1B9733D1B1A4274AEDEDBCA01FE7D5D070718D078909789563A4B648CA27123041D52708AA6AC742300052264A1C5CFC6C3A76919000C5BA4CEC29A90887C3D06000C3D7E94A4BBB7BD9E521A041D64AAC6C8B4A67B20000015509CD7DCE0D2C2933C000000468FAFC3D6D6D5C4882C00003B8BA3C1BFBDB8B38D43153284B7C6C1BEB4ABA8A16E1E0000002080B6C4B9A35F353B45404F82ACB7BAB7AC6B2C161C4063A7BEBDA470260600000000000000000045190000000841718E80769094826035121B3975B6E1DCBC85440D0000000F58A2D3D7CFA37E432F208C3D1F2557A9E5E8DEB96D26060000011C5ECAE8BE743F121B3975B6E1DCBC01FE7E5D070718E07C8E877241303F4D73815118001A4468879F9C5B1500002972B1CBCEBEBB92570F000D57A2E1D3B0A690813F0200184A849EA3B8BCBDA24A0000176AAEBCC4B6AF6B160000175CA2DCE7D9D5B6812D0000024B9CB1CECED2D2BB7B25000B4488ACBABFC6BEBF8A380F408DB3C1BBB5AFA3A8A276180000003390B5B7AF9C50222F413C5583B6C7BDB9B06728191C366B9FC0C59C6A2E0B000000000000000000551F0000000750819090878D9A875B311C233A80B8DADABD8F440B0000001D4EA6D9DDD1A3713B2C1A8C35162764A6DAE3D7B26B230300060E2B6CCFDDB673471C233A80B8DADABD01FE7F5D070718F075888B773A3D49577876510B000F5269839D9B551400002070B3CCC1B7B29B4D1100105DA2C6BDB0A9957B380C011A558F9B9AABBCC59C4B0A001C6EADC3CDC7AC71150000105EA4D7ECE6D2C58A2C0000094092ABC7C8C7C5B7691500105597ACB6B9B5C0B48F34184695BAC0B4ABB0A09E976B140000003E94B9C7C1A758242C433E4D90B9B6BABEAD6A1F120E336CABB7B6A6662E0000000000000000000053140000001350789682818992874E2D23285386B6E8D3B68A4B00030000135EABD5D7BF9D5F362715863E253265B9E6F0DBB16A1E090007062681DFE9BE6F3F23285386B6E8D3B601FE805D070718006677856B3127445F7A7237030019516B7D9A8D530F00032C7DBED2C6B2AF904A09000B589DC8C3BCB5986C370300115099A8B0A2B0BA8C420E002369A7C2CDC4A8611300001B64A8D9DED6DBC1802500000D519CB9CAD4C4C09C560E000A539EB5B1B8BCBDB5722D1A4798B9CFBFBCBCAF9C9B6316000000429BBDBFBE9148182A3B3C5A95ADB3AFBAAD601B0B1B407EB4BDBB9F6D340700000000000000000050190000001D628EA19A8C9B9A8F552922355F96CCE6DFC17F3F010000001565A5C1DCC18B55301C1080412D3A75C2EEF7E1B06B220400040A297CDDE7B9734922355F96CCE6DFC101FE815D070718107A878C6C3D3448637D662B00001E50657B917B4A0D00003394BED8C1B4B193440900104A9BBEBFBCB09C70320000165D99A7B0B4B5C1893C06022575B6B4CCC1B2611000002062B5E2DDDDD3C884300000034791B4C4CECFC4A6490A03185D9AA6AAB0BAAEA76A2B144C9DC7BFB4B6ADADAA9468100000005AA0BBBFBF97451B2D42405A9BB0BFB9B1AB5C110B14356EB0C1C3B37633070000000000000000004D0C0000002B5E8F9A9390919F7D4F332D336A94CCE3D9B47E4F090600071961AFD0D7B78749271913873B283376C7E6EEDCAD651300000A1B3094DDE3B1643D2D336A94CCE3D9B401FE825D070718207381836C2D365568795F2300002662747587743B0500002D84C3CEBDBAA88A3E00000D539FC5D4D1BE9E6E2D000018559DB3BABAB3B48A3408032B73AFC4C2B8A25C0800002872AFD7DBD9D8BD74210000155294B0CDD9CEC48D3E0504286C9B9F9CA3BBBEAD6E22135FA7C4BAB7B6B1A8A49C5A070000085BA9BCB6AE883E212D3C4B6899B6B8AEB19E56150713467FB0C3BEA9723A0F0000000000000000004009000000195D8CAB988A95967E4D32244083B1CEDCD3BD793F000000001561A7CAC7AE753A1F1115843A303D84C2E7EAD7AF711D060108113893E1E6B2633B244083B1CEDCD3BD01FE835D0707183075787C5A304258737A5712000027686767725F260000033F97C7C9C0AFB0844403000B4895BAD0D1BDA171280000156AAAB4BAACB2B0762507053281B1C4BEBCA2580500003174C9D3D1D6D3C17D1E000015519FAACDD1D6CA8F3B07001E6A909992A2B8BDAC701D2065A8C3C8AEADB0ADA894580E00000F68A5B7BEBC8B3B1628384E6798B3B3B2B6AB501D0A184683B4C4B7A97732070000000000000000004702000000236788A4958D968B7247342A498EC2E1E4D1B07A2F0D0B04082973ADC6BCA66B30121A118437224088D7F3ECD6A65F1D00010C123F9DE4E3A164362A498EC2E1E4D1B001FE845D070718406B796A52262D556D714D0500002E656867745528020006409BCBD4BDADA979390000044494C2CFD0BC99662800001F6EA8B7B8B2B0A76D2C0B0E3279AFC3C3BBAB600800002D91C7E1D5D5C6B4792200000E63A4B6C8C2C0B9852C0006256B9B848BA0B6BBA05D2E2471ACC8C0B7AFB3ADA5914B000000197CB0B0B7B5883611183F5B7DA2ADB1A8AD954A2009104282A0BBBEB77E3C0B0000000000000000003D06000000206E9AAA9F9A97906B422A354D94C8E4E0C5A76B3109120B0B2872B0C5C5A25F2E0E060E7E402A4088CBF0E1CD954D13090211224FABEFE1AC5F36354D94C8E4E0C5A701FE855D070718507866655C2D416D83794E0900003570636A6E521C00000848A0C5C4BBBFB4762E0600074793B7C7CAC6A3763200002474ACC6C1B3AEA7612707103878B4C3C3B8AB540200003081C1DDCDCAC3BF761A00001E639CB5CECEC7B8732500033472A1888187AFBB9B541A267EBFD0C6B4B0B0B1A1894C0000002E83ADBCBAB8883B1C21345B83AAB6AFA3B396480E071C487EB1C0C4B16D3D110000000000000000004318000000387895B39D96938754483535509ACCD7E1CFAD7C2E1E140A083178ABC3BE995F210D020B7C382255A0EAFDF8CDA24D0E00000B1B61BAEFDE95503D35509ACCD7E1CFAD01FE865D070718607E745F5230476E807938010000477D756E643E1700000F4E9ECBD0C1B8AD773501000C4492BBC5CAB79B753100012976B8B9BAB3A99C5B16071B4A87B6C2BFB8A1540000002F89CEE5DCC6CEB96F1B0000226BB0B6BBBEBDAA570C0000367E9D7E789ABDB9A05117237CC1DACCAFB2C3A8A792430000003186B4C1C6C68F36132037698BB1B2B4A8B68D461C0A1F458ABBC5BFAA653106000000000000000000380E000000306899A7A39293825D2D23314C96CADFDDD3A26F280B140F0A2D6EACD6C0864B230B07097D41365FA2E9FFF4CA9852160100092157CDEFDD9A5726314C96CADFDDD3A201FE875D070718706B6456462741788C73360000004972645A50350700000E51A8C9CDCCBCAB6F3100000D4997C8CCC5B8A67B3303002B7AB7C4C2BBBA8C551910174E90B7BCC3BB9E440000003F94CED4D0CCB9AF701300002F75B3BDBECDC3B3601100003382936D6A87ADC2A3520F257CC8DABAA5ACB6ABA0803C0000003B9DBABEBFBA8539121D396A98B4B8B6AFB586381A0B194E8DB9D0C79D582A09000000000000000000400B00080E31709BB39C939B7F4E3128335D93C3E7E3CAA55B1E1A221514397CADC2B388471E0C08157D3B396AB8EAF4E3CD95410E0000091D6AC4F1CF904B37335D93C3E7E3CAA501FE885D0707188071716044223F7889762C0000034F826E624E2F0000000E4CA8D0CEC3BDAF752700000C479CCCD7C3BBA97A3500002E7DB5C9C1B3AD94531D0816528DC6C5C8B4964700000D4FA6C5D4C1B9C1B3670700002D7EB2B0BFC8C7AE4E07000A468C925F5C85B1B39151213A88C4DEBC9BA3BEB4A07A360000004297B4CDBFBF963812113A79A2B6B8B4B5A7863C100E224F8AB4D1CE9E63310D00000000000000000042120F091D4776A2B2AF937E6E492D264763A0CEE5E3C6A25E22021A111C387BB8C8BF8B4911010008783B3F79C0F2F9EAD28B54110100022371C7EED182432E4763A0CEE5E3C6A201FE895D070718906E6B60452B4980986E27000012618E7B634A210000001A61A9D6D9CAC1AE742E00001B498BB6CCC9C2A6752900103474B7C3C4BEA38A47130F2A5597B5B8C0BC9B3F03000049A6D0DED0C9BFA95E0300003378AABDBECBC5A44300000041838D605485BABF8B3F123D8FC5D8BEA0BAB9B2A6823500000055A1C2C0C2B58C380C164782A7B0AFADA5A5802D0E0D285A8DB4C2BD996835010000000000000000003C1513161A4173A8BAA79D876C472F2C4562A8D9EADCBD9A501E002521243D72AEB8A3783B0D09090A7F504D86C1ECFDEECB88360E0C000A257AD7E8C17C3C2B4562A8D9EADCBD9A01FE8A5D070718A073705841365A8797742700002A6E977F65401C0000001861B6DFD2CBC1AF6D250000023D87B9CEC1B3A7823A09083981BDC4D0CBAE843C1E162E669AB8BDB4B2903D00000B59ADD1DAC7CCCDA5510400003073B1AEBCBEBE994B00000D529990504676B5B77F33133CA0DADFBB9FB1BEB397672700000D62A2CBC2B8BB862E091B4D8EADADB9AFAAA0692711172C4992B7D1C7995730120000000000000000003D112C2B334F8EAABDA8997F5E33262E4A63B3DAE9D2C3934E15091E2123438BBED3B27630160909128043548ACCF2FDE8BD8234050004102E7ACFE9BD643B2A4A63B3DAE9D2C39301FE8B5D070718B07973583F2F5984927823090A287B978A6B3A0F0000001667B5DDD3C4C8A76A1C000015559DC2BFB9B5AD862C000B3586BAC6C7C2B68636101F386BA4C1BCC6BC8B3A0000116AB2D6D1C9C9CDA2450000003E7DBBBFC6BBBB8F3B0000184D97914C5080B1A66B27184099D9E2C39AB9C2B48D5E1800001566AAC9C9CBC288320D1C5B9AB0B8AFB5AFA66F2915162F5A9BBBCCCA9A552A0A0000000000000000003A17303A28518DB5BEB697825D392F334173B1D1ECE9C288541A0921212C4E8DB1BFAD70340B08020B7E435295E0F7F6E6B27A2D0B00000F3590D0E1BE6E34244173B1D1ECE9C28801FE8C5D070718C06C67542D27588E935D200A123C82A5946338060000002166B3D4CAC7C5A26C210000165495C8C5B7B4AF7A3206113D91BFCEC3C1A3752F0E194C76ABCACCB8AF8D2D00001B64ACD1DBCED2CC93470000004093B5B7BEB8B28F2E00001A5C90824C3F69B7AB6A291A4AADD5E2C8A6B5CCB584510800001B71B7D0CDD2C18F350B0D549CB4BBB3B5AF9A64240E19396393B7C7C293451D020000000000000000003B143A3D45649AB1BDA892764B32222D416DC1DAE9D7BB8E43130B2A2832639EABBFAF6F340C0606006B4057A1D7F8FDE3B76C330C07001C4BA9DCE3B0693727416DC1DAE9D7BB8E01FE8D5D070718D0797B5D4037709DA26C2315164B8BAE976F32070000002770BFE3D1C7BE9D5F1900001E5292B5B8B0C2B9802B0B16397DB9C9C1C3AF76280E1F5683AFC2BFBBB68C3600001B75ADCEDED3D3CA9735000000468EB9B9C4BFB58E2F0000185C9B9144417CB7A25C19104BADDFE5CCB1BAC5B47A3D0B00001F7CBDD1D5C9C784350A14529EB4BCB1B3B59F5A1B0A193B6B9FBDC0B98F4A1E000000000000000000003417363C354F86A8BBA4855F442628365384B4DCEBD39A73380800251D2B5D99BCC69D5E1F09000A0F7E446AAADEF7FAE1AF6525010A0F114BB3E4E5AB60392A5384B4DCEBD39A7301FE8E5D070718E0737B5B3A356D9E9C6A2C102B5AA0B7A87334010000052E7BCBDCD4C3BF8E540E0000194F96BFBCB1BDC3792C010F3C94CFD3C4C4B56F241129618DB6BEBCB4AC7B2400001F77B7DAE4D2CCBB83370000025395B6BDC7B9B68A340000205C96813F4578B29C53141D52B1D9EADFB3B7C2A476340100002F8BBDDDD1D0BB701F051763A4B4C2BFB8ABA14F1C1520346398B5C7B38B502304000000000000000000372046534B6D96B5B6A5906C58322135537FC9E3E2CFA8793507021D1936669DC0BC9758200306010F6D456DB8EAFFF8E0A75F1F080B05154AB5CDE3AB5B312F537FC9E3E2CFA87901FE8F5D070718F0778A633F3A6595995E252038649FB7BA7A3A06000000347BCBDEDEC6B58B501500001D579DB1BEB5C3B87722050E4599D2D4CECDAE681D09276296B5B8B2BDB06E2700002376C0DBDDD3D0BA85290000045295C4C5B9B1AF822B00002D77B092494478A98E45121350B7DCE6CDBABFC7AC752A0000002B80C6D7D3CFC57B1B01135EA5BCB6B7ADB998521F1722467C9FBBBFB8804621030000000000000000002D2F455A506993B4B8A387653E2A203E5E92C2DFE3CEAB72290A001A233E77B0BBC2A14E1A060E0316834468B7E0FBF7EDA966180000041960BAE8D79A4D322D5E92C2DFE3CEAB7201FE905D070718007B81674139619A966030274477ACC7AF7C27000000043D81CDDED4C3AA82491800001D5488B2AEB4C5BC76240E1C509ACCD5CBC6AE6424112E70A8C9C8BDB69A5D160000297DBCD5E1DBD1B56E1B0000055E9DC0C5C5BBB0732100003472A889474181A18231101152AADDEAD6B7C0CAA7681F0000003A8DC4DECFCDC0742004146AAAB9BAC3B7B893481B0E246693A2B2BDBA7C431A0000000000000000000041274452456399BABFA58663361121466788CBE5E2D7A065270C1213295283B0C2B5954E170602000A614D80CAFFFFF7D5A84A130F07001463BEE4DA994E27266788CBE5E2D7A06501FE915D07071810737E60372F61928C572C2B4E82B2C9B78127000000063C8DCEDFDBC2A982410D0000165D8EA4B5B4C8B76925101A609DD8CDC8D0B664140C3376ABC0BFB6B2955D1700002E8BC1E7E4DDCCAF5C0F0000095FA0BEC6C4B1A17A2000004185AD8C494D80A47A2D0E155CC0E9EED9BBB1CAA8581A0000013F98C4D2D9D5C07421001966AABCBDB5B2AA883E100F286091AAC3C6B1773F1D05000000000000000000383057636277A6C4BFA787644521214768A6DEF7F6DBA96B320803222F4F85B6C6BD964C0F00000F0E75537FD0F1FEEED0954B1501060A2074CCE1D697452D2B68A6DEF7F6DBA96B01FE925D070718206E79562C2858807250203C6595B9D3C88C350000000E3F87CADBD0BA9C7C3B0F00072E5788A8A9A9C3AB6C2E0E2362A0D5DCD3CCB8641612307FB5C8C0B9B792480900003783C6E0E1D8D4B15E0900000862AAC4BBBDBCAF6D2200033D83A78B5350879D6B270F1C69C3E9F4DFC5C7C49C4D0B0000004695B9D2C4C9B16221032377AEB6B8B7BAB48C37141A34719DABBCC0B579361000000000000000000000352640524C5FA2C0C0B38B583B201D477DA9D6E6D8CDA76C2808071A2C578CB7C6CD914910070008166C558FC9F8FFFCDC944017000000207BC6E5D892452E247DA9D6E6D8CDA76C01FE935D0707183071835536336182784A2E43709ECBCDC0832B00000007419CD1DFD9C1996A360500052D6091AAB0B4BCA959200F2A65AECCD4CFCDB86217153E8FB8C5CEBBB791490000003590BCCCDAD6CD9F50090000196AABCACEC1AF965610000A4396B3964F52919A5C1E000C63C1E4F1E5CDCDD0A34E00000008498EC2D6D8D2B2581708237DB1B7CEBCC1B07539211D41779CAEC6C1AB6A2E0F00000000000000000000362D484B4D6FA9CECEC18F5730101E3F7EAEE8F5F0D0A1662815111929699AB8CAC68A3A060005081373609ED1F9FFF7C4884313090B0C3382D4E7CC793128227EAEE8F5F0D0A16601FE945D07071840716F582B235172603B21417BAACCD0C39033000000154D90D2E0D8BB9C68340800072B66829EB4BBB3A0612715306BADD4D9CECC9E5A14144693B8C2C7C1B78730000007469ACCD8DFDECF9E4E000000186EAEC8C8C6AF97560900065288AE925360949B4E13000E63C7E2EEEDD0BEC8924A0000000B50A8D3D5D8D0AE5A13002D71AEC8C3BCB7AB76381419357DACB5C6BEB66B2A1600000000000000000000492D4C58567CB0DAD6BA905E33272A517BB3E6EFECCF9D6E2E180015316DA2C6CFBA8F410B0E080D196A589EDCF8FFEDC68D4009040906378DDBEED67F3228227BB3E6EFECCF9D6E01FE955D0707185077875D322E4C69633C2E4D8DB5D2CBC48334000000124E9CCBD1D0C39B5D20020002325991A9B6B2B7A75A1B133776B3D5D0CDD2A95D13164E9CC0C1BCBDBA7F2500000043A3CED5D6D1DBA3410000001D78B1C4C7BEBD9E490A00145698AE8A566D998D420A001066C3E7EBDCDACCCC994000000009569FD6E0D8D0A1530D002480B4C7C3BAB7AC773F201B377DA6B3C7C49C62320B00000000000000000000503954596780B9DBE6C4925A2E1D2E5A89C0F0F4EBD6A47A3513171B3B79A6C7C5BF8836070003001464609AD8FCFFF1BE85350805080E3895E4E8CA813E202E89C0F0F4EBD6A47A01FE965D0707186072845B2D2849593E2828578FAED4D7C88E25000000154D98CED8CEB389561F0000103C6690A9B7B6B39C53140E2C76C2E2DCC8CBA8560C1A5A97C1D0D2BCB77A1D0000054FA9D4DADDCECD9C3D0000002277B3CABCC3B497400400136295B7936A708D753904001E70CFEAF5E0CBCDC994390000001458A3D1E0DFC58D4F0900247EB7C9C3BBBEAB78331B284489AFBBC2C0A157250B000000000000000000004A2D45545B85C0D5DEC38A48232A2B4D8FB4E9EDE4C99D6B341F151C3D78AACBC6BC8A360B17110D1060609FE1FCF8E5BB7A340700070038A6EFF3D07B311D1E8FB4E9EDE4C99D6B01FE975D0707187072734B17143549312B275299C3D9D0C57D2D01000014539CCDD9CDAE8A501E0200092B658BA8B4B8BB9349130B3C7CC1D8DCCEC7A057121050A2C8D2C6C0B6711800000D50AACCD5D7C9C48E2A0000002F86BED7BDBEAD873400001B699BBF9B63768E652C02001A6BCDECEAE3D0CDC18C3A0000001B69B3D2DCDCBE96440C012983B6CDC6B9B3AD6A341E365793B3BAC0BF92532406000000000000000000003C2B3F4C6188C6EEE4D796522426396798CAE7F9EBC99F6E301709143D84B3C3C4B57A30030000040F656DB3E8FFF6E9B9732A0800010F3CB0E7E9CC7E311F2198CAE7F9EBC99F6E01FE985D07071880777644251E3D4434192452A4C3CDD1C58E310000001660B9D3DCCCB68645100000083B6B94BBC2B0B48D3E0404377BC3D8D4D4C8A756161A53ACC2D8CDB7A3611200000855B3DCD9E4D3C9872B0000002780C5CEC7BDA5742602002670A4C3A070838C5C1D0000105CC4F6F2F4DBC6C9903C0000002365AFD8C5D9C3903202002886BCCACBBCBC9C66331E295199BEC6CBC09D571800000000000000000000001F293146578FC3E9EDC9965430232F659BD6ECF6E0C4986336211A1E4089B6D5CFBA7B3C0D020802135E63ACEEFAF1DFB273340D07031656AAE6EBC5703D261A9BD6ECF6E0C4986301FE995D07071890727E511C1427282616285D9CC2D0D1C18A2E0000001F69B0C2C6C0AC81451600000B447897B9CCC1AD7E3D1012388EC9DCE3CFC3A54D101C61A0D3D4CCBEAE5D0300001160B2CACDD7D5CB8C2B0000003291C3DDC7BFA2691500002876B5BD987C8B95671A0000186AC7EFF4EBD3DACB8626000000216BAAC7CEDCBC6D1900002F88C2BDBDB7C39D60292F384E9AC3CDCFBF9B481D0000000000000000000000301F3842548AC9F0EACF9052342D3F689CCDEEF9D9C0965D2E191A1B4192BBD0D0BD84370105060B105063A8E3FFFBE2B0671C05040D1457BDEBEBBB752B16209CCDEEF9D9C0965D01FE9A5D070718A072784310081A201204215BA2CACDD0C788290000001E67ADC4C8CEB38636050000024679A1C5C5BFA3703407143D95D0DBDBD0CB9C4E0D195FA5CBCFCBB9AF4F0000001562B6C5D0DCD5C17F270000083494BFC7BBBC9C531100033E8AACC4A77C9196570A00000B6AC1E7F2E9DECFC586220000002574A4CBD2D1B66C22000C3785C0CACDC4C29F5A34263B5F9EBEC7C8B8894619000000000000000000000032272F456291CFEEEDC9874A2F344673A5D5E7F4E0BB91542C190D244D94C0D6D2BE8B3809040C07185E74B7EEFFF0D8A35B1E06020A1359C4F9E3BA672B181EA5D5E7F4E0BB915401FE9B5D070718B06D6B2E030015170208255B9DC4CEC3AF7E31000000255DB1CCC7BAA779390600000E4B77A6CAC7BE98631A02114198D4DDDCD3CFA14A0F1962A6D1CFC2BCA653000000186CB8CDCCD0D1C17C220000003187C2D8CFB191470200033B95C1C1AC8D99984A0700000F67CEE9F2E4DED3C5861E0000002A74B8CBD2CCAA5F1D00113689C9D5D2BDBC994D312D3C6CA1C3CAC5B48D42130200000000000000000000422A36527CA0DBEDF7D38F412C354973ABD3EDEEE0C08C53210F12255A99C1D7D3BD8D3F030202091B4F76C4FAFFF2D3A1541C000007165DC1F4E6B65D2C1F25ABD3EDEEE0C08C5301FE9C5D070718C07366330C05110E00062266A6B7C7C2B77A2B0000001F76B8CAC6BFA2702C000000285287ACC8CEB88E5A150617488FDAE7E6D3C79C3D051B60A9C8CFD0C0A24E000000206DB9C7C7D7CBC4771F00000841A3CFCDC6BA81360000004597BCC4A9949E863B0000001261BAEBF7E7DEDBCC7F240000042E78BBCAD0D0AA561100053D90C4D2CBC5BC9A553D35406799C6BFC3B97E3D1305000000000000000000003425445E7AAFE7FFF9D39352302B5071AFD9EDEADCBA85502B191025559CD1DADBBC82380800000A1D517AC0EDF2EFD29F5A1E0700021968C5EFE7B36122191FAFD9EDEADCBA855001FE9D5D070718D0736D390C00070100011F659CB9C3C6AD7426000000297BC1CBBEB797622A050000205496B5CACDC19B5419000C4395CEE6DDDED29B3F0B1C60A8C2CECEC6A4490000001E74B8CDCECDC8B37A200000114CA6CAD5CAA8722500000A4F98C9CFB497A38A390000001A66BDEAF5ECDAD0BB83260000023077B1C5C6CC973F0600104798C9DCD6C6BA9F472E304464A1C5C2C2AC7A3F0F00000000000000000000003F31456786B3E2F8F9D093522E3A457CADDAFDF2DFB276461B101B2A6BA7D5DED8C1853E09000006164473C6F4FAF1CB984F170000081665C5F8E6AD642A1622ADDAFDF2DFB2764601FE9E5D070718E07B75350000000000041F5B90B6C1B1A76F190000002879BFC8C1B9936927000002236598B8C9CAB883430F021053A3DCEAEDDFCC953F051C62ABC8CAC4C1A44B000000287EC6C8C9CDD0BF731B00000F4FA8D0D3C0AC6A1A000008489AC0C8B7B1AD802F0000002361BAE3F4E3D4CBC17F170000043780B6CCD4C7903D0A00165391CCDBCBC5BD974A353847659CC2C5C6B177370B00000000000000000000004637455890B9EDFDF8D0904B2734436AAFDEFFFBE4B97A401B14151F5CADD3E9D2BE883508010002234A82C9F0FBF0CF93420C05090D1369D1F1DFAE611D1D20AFDEFFFBE4B97A4001FE9F5D070718F0715E1F0000000000051C6496B0BCB7986119000000256CB5C5BAC39360210000002D64A4BFD1D0B88F490C001C509ACDE6E2E0D2933D0B1C6AABBEC9C9CAA3420000002F79B3C8C0CCCCC2791C00001056ACCDC7BFA4561700000E529FC5D5B8A5A07C2B0000001E6BC4E8F7F0D4D1BD701700000C4687B6BFC9CD913800001B54A1CCD9D9C6C08C48383D48619EC2C4C0A766330C0000000000000000000000463C4A7484BAF1FFEBD18B3E1B2C4574ADDFFFEBDBAF703D1C171E3076B2D8EAD8C58030040002091D4B80CFF3EDE8C289451F1106101C71D0EDDBAA5422171CADDFFFEBDBAF703D01FEA05D0707180073621A0000000000002B6792ABB6A099630D0000002D7AB6BDBBAD8B561C0000002E71A9D4D3DBC089330C0213479BCDE8DBD8C08D360B1E66AACBBFBEBD9D3D0000002B7BAEC4CDD3CBBA761B00002262B4DECAC09D480400001B65A4C4CBBAAFAA802E0000001864C9E8EFE7DFD1C1680E0000114C92B4CBD0C592350200265DA8D1D7CDC8B26F3C32424964A6B9BFBBA66D2A100000000000000000000000392F436D92C6F6FDF4CB89421A314274ABDBFBF2E4B06E3C1C0F113F71A9D5E1D1B7873F0A00000017458BD1FAF8E3B1843C0C000208237CCDF3DA9E5422121EABDBFBF2E4B06E3C01FEA15D070718106C4F12000000000000275A92AEB4A88A5106000000287EC2D1BEB28C4C0E0000033073B4CCDADDB773280600154E97D5E5DDD8C99531052467B3CDBFC7B58A380000003483BEC1C6D0C2B9681500002B67ABD3D4C6A14B0000001E74ADC1C3B3B9B67A200000001C62C4EBEDECDAD1B765070000185A9FBFC8D3C07D2700002060A3C6D9DCCFB67F3F38444F67A4BAC6BBA871350C00000000000000000000003A3746759FCFF7FFFCCF7C2F1B333D6CADE7F5F1D8AE6D3914000A286EB8DCE7DDB47F370A0000032B518CD6F7F7E4B87432120D040A2381D7F6D788441C172BADE7F5F1D8AE6D3901FEA25D070718206E5721000000000000306784ABB6A280570B0000002778BDCFC2B4885413000005357EC0CAD3D7B972220B00194C96D5ECEDD2C4873A0C2564A3C2CAC4BD92380000003684BBC8CBCBD4B5610F00002F74BCD2CCB393440000001D73ACCBCCBBB3B580240000001468BEE0ECE1D8D3B45F0300001D6397B8C9CAC27C230000205DB1CBD5CDCABD734038464667A6C1C7B9A576320600000000000000000000004541547E9DD0F1FFFCCC7F3D1D2D4162AAE8FBF5DBA26A321D0C1C3670B1D4EBCCAC7934060000001F4891D7FFFCDDB3743A150201192B81D7F3DA954B281D27AAE8FBF5DBA26A3201FEA35D070718306D500A0000000000002B6A8DA5A89E753900000000257CBCCAD3C39347100000083681C4D8D5CAAE66230503145494D3E3E0D6C08133132D6FAAC3BCBDB78E2C0000053C82B5C3C5D0C8B4641100023276C4D3CABB802F0000002B81C6CEC5BEB9AD731F0000001472C0E0E8DED3C3AD54000000265E9BBACED4BA751900032D71B2CFD7CFC6B8724142474E5D9BB3C5C5A6733A0A00000000000000000000004E39517BA4D5FEFFEFC785462B314875BBE2FCF7D3A7642A150A133F80C0D6DDD7B16F3306000000275496D7FEFAE1AB6D321705050E278AD4F0D38D4C202B29BBE2FCF7D3A7642A01FEA45D070718407E6A300100000000153E6F96AEB59A7940000000002575C5DADACB9F520C000011448DC9D9DACCAF64220005225097D1E0EAD7BC7E2C08256AADC3C9BAB58F2F00000F4B89B9BBD0C4C0AA5912000B4184B8C5CCB67C2A0000003187BBD0C2C8BCBA6B1E0000001D6DBFE4EDE8D9C5A94C000000216DA7B3BBC7C2761600003A7FB3D5D5C8BEA6602E414C4666A0B9C5C4A87A400C00000000000000000000004E2C4679A3CDF8F9EFBE7537112F4566ABE8FFF5DAA264250A13144285C1E8DECAA36B3011000007315697D5F5F2D8945C250E09000E2E90E4F1CF854E1E212BABE8FFF5DAA2642501FEA55D0707185079611D00000000000A3E6A94A9B18D6D33000000002A7DC4D8D0C8984F0F0000054291CBDED2C6995B2000022A5A94CEE3E0D4BA812D042C73AABBC4B8B18827000009518FB4C0C9C6C5AB5512021B4D92C0CBC6B27F1C0000003B8EB9C1C4BDB2AA6619000000266DC4DEECE2CCC397450000002F79B2C0C7C7BC762400133B80B6CFCEC5C7AC6A34453F3E6DA5CEC0BFA2753202000000000000000000000044384D79A4D6F5FEF1BA7B36192C3C5EB1E8F9FBDA9B56240D00114EA1C3DFE3CCAE783107060507254C92DEFCF5D59D6122030204162C97EBF9CB7743242829B1E8F9FBDA9B562401FEA65D070718607857180000000000074A7699AEAA8D5B1E000000002176BAD9E0CE9E4C1300061D539FC6D1D0C394491206093563A6C8D1D3D3B5732B0F2B75AFC5C1BEAE832600001F5282B8C4C9CBD0AC4C0A001D4792BBC4C7A96E1C000002468EBFC7BBB9B6AC5D130000002870B7E1EDE2DABE90350000033B7AA7BFBFC7B8650F00094D8DBECBD9D9CDA35E2D323C3D70A2BDC2BAA57E37070000000000000000000000483D4376A9D9F3F6E7BE773B18132C83C0E9F6F2D2954E1F0B101F5A95BFE4E0CDA165270E04000127569EDFF7ECC9915221110A0E18338DDEECC97938282528C0E9F6F2D2954E1F01FEA75D0707187075501804000000001351849DAAA1885519000000002A74B8DBE6CA9C4C150009276297C4DECEC7874E130513325596C1D5D9D0B578220D3677B3C2C8BEAE83210000185B8BBABCBDC7B791410B062F599EC4CFBEA76107000001449FCED7C3BBBDAA58130000042E77BBDBE4D1BCAC762F0000003377A9B7C0CBB7661C061B5B92C3D6D7CCC3995032423F4471A7BFC5B5A17932000000000000000000000000503D4B719ED2F5FEEFBB72371829407AC0ECF9EAC992431C100C205198CCDDE2C28F5E35190903073763A0DFFCDFC29649220D0115184AA3E3F1BA7437202E32C0ECF9EAC992431C01FEA85D07071880755B1A02060000001E5E7F98A9A7804F1C000000002069B1D7DBD39E541C0008265DA0C4E2D3C58E4E1B00113A7093C3CBDACFB5641200286BAFCBC6C4B4731D000027669CBFC8CACCCA8E39070029609DC2CABEA45E0700000A51A3D8CFC5B7B5A360130000003277C5D5E7DBC9AC742B0000084682ADC7D5CAAB63100019619EC3C7D2CBBD8B452D3D38386EACC1C3C19F80420C00000000000000000000004D343D659BCFF5EDD6AD6B3417113B75B7EBF3ECBE86431005011C5BA2E1EDE0C3905631170105113763A3E3F4E6C7884B1C0D02050E32A1ECF5BB75311B242BB7EBF3ECBE86431001FEA95D0707189066420C00020000001D5B74929C99743F0800000000216CAFDEE4CF9D571400092F6DB2D6D6D5C492490C0013326695C6DBD5BFAD601A07287DA6B6BFAF9C6B1E00032F6591B8BCC7C6B5923E030C356FADC2C6C4A0500000001459AECACAB9B7AAA15506000006368ACAE1E7E4BFA1731800000C4891B8BBBBC3B3711706256AA2C4D5D3CBB487462231374270AAAFC1BAA6833E0200000000000000000000004743496D9BD0EBE9D5A3642B19292B6AB4E0F4E6B677250904122B62A8D9DADEB87C4C231C130E04385BABDBF0DFAF773F1706090D093CB3ECF2BC6B31202B2DB4E0F4E6B677250901FEAA5D070718A06946020004010000275C889BA29A754305000000022774A6D2E7D1AA5D0F0014357CB0CDD1D5C78A3F170916456A8EB8CDCBC6AA5F1A052B7BB1BFBEB89C6C130004366C92C3CCC9CBBA903600083779ABC6CAC499490000001159A5C2C0B1B2AF9C4C050000014094CDE6E7D0C08E581100000B4B8CA9C4CAC9B05F13042675ACC9CCD7C7B49447222D353E6AA3B5BFBCAB93370300000000000107000000004B44496A95CDEBEECF995E250F193871BEE1F8DDBB752B0D08072C69B2D3E5DEC1824F2810090C093466A6E7F3DCAE71340A070B0A2543B0E5E1AB633721252BBEE1F8DDBB752B0D01FEAB5D070718B0784918111F06000030709B9BA99E753306000000013066AAD7DDE0AD5C0F0015447CB3D6D6D2C58C43120A204F749ABAD3D0BA9C541506327AA5BABDB1A3600E0010476A97B8C1C0C7B88D31071C487FB1CCD0BA923E000000206BA9CDC2AAB4AB954C0C00000D3F90C6D8DDD7C69452000000124B97B3C1CAC7A5530C093276A3B9CDDAD5C28F3E1E2A303B729FB6CAC6BB9540000000000000000300000000514B4C6993C4E6E2D09A541D0A1C3B70B6DCEFE7B8691F0A0E062969A7C6DCD9B383472B2415120B3E74B4F1FFE4A763311B0A0610264DAEDEE4A1512C20292DB6DCEFE7B8691F0A01FEAC5D070718C0724E1319280A0000367294979793672A00000000002A67A5D8D7D2B55919001F4C84BCD9D6CFBD87431A0E314A7596C0CCBDBD9B4613003A79B2BDB9AB99630B001555819DB4C0BCC0B87E2300154A8AB5CACFC18E440000002369B8CDCAAAA9A5904A0C0000104697CED9DEDBBE7C43000000145792B7B9C8C9AB530A03387FA2BDD1DBC9B5853B222B263977A7B9C0C2B490400200000000000000000000004E49455D7EBDDADDC98C4B180A192679C5E5F2E4AE68260907041D6DAED1DFDBB67D3621131205144168A5E2EBDAC6672B150C150C1F4AACEADAA25A3023302EC5E5F2E4AE68260901FEAD5D070718D06F3E0A0E210B000037768C8E9A9F6430040000000024629DD3DDD7B35B170D1D5499BCD5DED4C283361B132C537292B7CAC3BA8D3700003088B5BDBAB3985E080014587CA0B5CBC3C2B07722052E6691BCCCCDBC822E0000002D75B3C1CDB3A5A79A42090000114C8BC6D5DBCEBB8038000000275D97A9B7BFC2A54F1411408EB9CBD2C9CBC0862D1822223876A5C3C0BEB3853C0200000000030004010000005346445F8EBFDED7BC9E4B130C21346BB6E5F4E8B4641C0000042271B6D8E7DDAC7E461D1B0C02023E71BBE2EECC9C5E330F07030D1F51B6E7D29F5332263333B6E5F4E8B4641C0001FEAE5D070718E07046192638190006417D9099A09972270000000003255CA6D8DCE0B7621A0E2B6199BACCD2C7B4823D161034647A96B9C2C3B9883B0500347FB0BAB8B39652070021608DA0BBCAC8C6AA64150B266189BCC1C7B37A3A0000003E87B2C9CDB1A7A68833090000125D9BCFCCCDD7B77E370000001E599EB7C2CAC6A1450B004490BBDAD4D1CCBA7C2A13151E3F77AAB8CDC6A99741050000000000000C020000005D595D678CCAE7E4CB8C4A20202D4163BDE3F0D9AA60160000093178B5DDE4D8B4723A1C20150C0E4369BEE7E4CE9F5A210F100D15254FABD8CE9C532C27303EBDE3F0D9AA60160001FEAF5D070718F07648182F3D2009124E899D9D93916223000000000B296A9CD9E2DDB761200C3374A1C0D5DEC8B2754417183968859EB8C2BFB27F2B0000358DB4B8B5B68C4604002C6D96AAB8B4B8C2AC6117002B6A9EC1D3C9B0752A000000408BBACFC1AAAFA9842B070000165DA5CEDAD8C7B4762700000027689DB2BDC1C9984107093E88B6CDDAC7B6B37A24111C274677B6C3CDBCB3943E0900000000030600000000004D3B42557BB4D5D8B57D2C0D202F357DBAE9EED5A757170000002677BFDFE4D6A4794623210F030D4372B7DEE5C79F52280B0513141855B2CCC58F572F20353FBAE9EED5A757170001FEB05D070718006C44244050220218558EA296A0936626000000000832659ED6EEEEBD59180F30779FBDC9D5D5BC7F4C1D214D70839EB5BCC0A86B1B00053A87B4BAB6AD953E00002D73A1ABB7B9B6C7A04E0B083580AFBDBCC5B27C260000004E92B5C3B3A6AAA07E320D000B205FA0C6D4CDC5B17123000000346F9DAABACACF943A080B478FB8C2CFC5BBB274280C131A3881AEBFCBC7B390430C0000000300080C0A0000005E494E6091C5E3DDBB84381618324683C9E8EED7A657150000103E85C1DCE5DEAE7F38231E0A040D527ACAE9E3B78447220B101E10235DB1CBBD7F4830322F31C9E8EED7A657150001FEB15D07071810724425515B2F0E246296AFA8A18E541200000000143365A5DBE8E3B6621F103C82B0BFD2D9C0B676472727597B828CABBEB5A767150000388EBDB6C3C2934E0801347FA4ABBEB8B9B4964A04033A7EB0C2BCC5B27A280000004F99BBCAB8A8ABA57D3B0A00001E5FA3C7D4D3C2A866180000002B679BAEC4C2BD8C3B01084999BDCFCDC9C7AD6A21040C18418CB2BBBFC7B38C43110000000003080900000000524531487CC0DFDFC0853B131F384E91D0E2E0CA9E4608000007377BBFD8EBD2A7713B1D261202174D7BBEEAE9BB842D21101217232B5FBCD0AF83512B282D38D0E2E0CA9E46080001FEB25D070718206E40345C672E122C73A4AB8E9787572000000000133B669EDCEBE8BB6520113C94B0B9C8D1CFB582502E2D56868994AEB4B4A0611B0000398DB7B4B8B18E3A00023B8CADACB9B9C0B791350002458FB2BEC8C7B378260000126A9FC6C1B9ACA2956E2B060505286AA3BCCBC6C3AA58180000003A7AA9B2C3C3B98225000F4E9DC2CEC9C3B7AB6E21060E1E4386B2C2C3BAB18236050000000908110B020000005938474B87B8E2DFB56F2C071034468DC7DEE1CE9E470A0000093A8ECBE8EAD0A66E2F18140609155B88C4EEE1B5763411050E1221346FC3CC996A45223F4646C7DEE1CE9E470A0001FEB35D070718307F553C636B43223D75ABB29E97855019000000071F3E73A7E4F6EDC25F201859A2B3B4C3D0CBAD765335496D8E8D9DAABAB29E55000005468DB6B5ACB5883B0003439DB0A1BFBEBCBA8930000A448EACC6CEC4B16D1F000016729BB5C2B7B1B199691D020202216AACC4CDCDBEA55908000009417AA3ADBBC8B36E2C080E559DBCD1CFC8C0B866180609194A86BBC7D1C6B4813805000001000808040000000054443E5C8ACCEEE0BC743010263B5796C9E0E6CD913C0100000B3F8EC5E1E7D09F662F1D150F07155B84C6E5DDB4783C151510151F3072BDCCA2613E342A3A3BC9E0E6CD913C010001FEB45D070718407546446C6F3C2F4C70A7BBA8917D491900000006193E6DABDDEFEBC364212761A2BCABC0D2C9B0744D32396F999A98A0B3B3994906000043A2B3B1ADB0852A0000458EAFAFB8C1B6AB8934090D3F9ABCBCC8C7AD6F2600001270AAC5C3BDA9AC95662413050C2B75A6BDCECDB49F4D0700000B4A87AAB4B9C0B07022000C54A2C2CECDC8D0B26111040913488EB2BDCABFA683350A04000306111110000000004F4243527AB9D3C9B786321820385D94D3E3E5CD8535060000043D8ECBDAE5CD9B68340D0B12141E6477C6E7D6AB743718161D1C273D7CC3C58355362A2E3F40D3E3E5CD8535060001FEB55D07071850724940777547314F7EAAB3A0877D440F00000006204F7DC1EBF6E3BC61262567B1C7B2BFD1C5A6714E39447B988C92A6B0B99E3F00000C539CB6B4B1B18A2900025797B0B4C5BAB7AC7624000C54A1C6CBC8C8AA6A1B00001B75B0C3BEBEA7AD9760200B110D2876A3B0B9BBB39946060000144C85A9B1BBBDB4681D000F52A2B9CCC8CBC5B15C0C00091E578DC1C2CEBBA47B380300020109060008020000006444405590CDE5DEB6722D10264064A1C9E4E0BE8330000000094389C5E6E4D3A7692D14120D0E217A83C9E7CE9C5C2B100D1625264382C3BF8C5331302C393EC9E4E0BE8330000001FEB65D070718607A4B4E7A7A4F48588EAFB5A0927143130000061C334B8CBEEBFFEDB061273269B5C6BBC2CEC1A46F553A4A889E9299A8B5A88731000009589EB7B7B9B6832A00004998B6BBC5BBC3AE741B00125BA3B4C0C5BDB0772100001E81B5C1BBB3AFA4955D2114121233779CC3B6B8B69040020000185B91ACACB7BBA96519001854A8C4C7CFC4C7AA5309000328579BC7BEC3AF9C7A2D0500000313110B0302000000593D466091C2DDCBAD692E0A1B3A619BD9E5DEC28126010000114D95CAE9E2D4A16A25130F070820718DD2E0D08E632D10131D21283B7FC2B27C4D3E2F33434AD9E5DEC28126010001FEB75D07071870784F4E7B7E5748628DADB9A6846B3C1903000D2A3D5B8ABFEFF6E9C06B302B6DBEBDA9BAD5C2936B5038508AA5908C9FACAA872B00001158A3B9BDB4B8842600005698B4C0C2BEB1A76B1600176CA7B9C6C8BDA8721F00002F87C4C6C4B3A9AF985B21180E093179A6B3C4BFB08031000000226696B2B1B8B9A9510E001861A4C9C6C3C6C7AC4C110006245EA2C5C1C8B69F752E09000710100E1109060004005C555C6191CBEBD7A6612E142641649DD3EEEBBF7E29000000094091D7E5EACF97643612100E122D827ACEDBD2985626120918182C4D90C2AD7D47362C323E4BD3EEEBBF7E29000001FEB85D07071880734F50817D5A496B99B2C1A47C612E1904060B1937619CD1EBF5F8B968262A73BFBDB5C8CEC4926D56435D929F9A99ACB5B07F2D00000D5CA0B9B6B1B380250000559DBDBABDB7B99F5D0D000F6AB1B5C2C6C1A86E1A0000318BB8C4C1B7A19E914E1E1817173384A4B4BFB6A986330000002571A8B1B1AEC5A45F16021858A5C4C4CAC8BD9F4E0B000D2A6AA5C4C4BFAD9F74210700000C1A130D0E0100000062575570A3D5E0D6B36E341618365FA6D5E3E2B97E260000000C4898D4ECE9C6956023110C1615348F7DCDE1BD8D4D201B151B20335692C3A56C42322D303E44D5E3E2B97E26000001FEB95D07071890714658847E61597A98ACB6997A5D30100B081D2E5178A7D4EFEEE1B45E272C73BBCBC1CCCFB2866156375B96B2A69DA8B7A8811F00000A5CAAC6C1C1B47D28000B5FA9BBB5BBBCB4A6510B001466B4C4C7CBC0B1691100002992BBC2B8ACAFAA915424221A15377BA7B5BAB6A97B2A000000296C9DB2B7B5B29B4D0D001D59A5C3CABFCBC3A94802000E3571AED3D3C6A69274240000000A10130C0902000000655F667EAAD3E6E0B37330121B3672A6D3E8E3B97230060003103D96D3EBE8C7956026140A0915328889D4DFB9844B2610191E2932589EBC9F6944313B414940D3E8E3B97230060001FEBA5D070718A0685D5F7D7A5F667DA1B0BF926A46260C03111D31517BB3E1FFF1E5AB5A28337CC4CDC5CED2B388634D3B5F97A9A89A9AADAE801D0000136AA7BCBAB9AD6C1B000761ABC1C3B9BBB7A14E0A001A6AABC2C0C8BEA45E1200003BA0C1CABEBDABA6924F2934211A347AA5B3BCB1AF822E0000002976ABAEACB1B190410700105A9AC0D1C9BEB39A530F00042F7AB6CDD1C5B193692601000B0D1418140603000000706B747BADD0EBD9B06D2D13233B70ACE1E9E0BC761E000000144B95CBE1E2C89A672B150B0E1F479982CADFC1795228131717212A5FA1B1935D3D3337374147E1E9E0BC761E000001FEBB5D070718B074565679725E6393AFA9AD93654726160D1A293A5982B2ECFEEDD9A55121367FC0D9CDD4D1A97244423B6FA0BCA3A4AFB7A5771C00001E71B2C5BDC0B87A25000466A7B9B5BEBDB297400000166BB7C6CEC2BB9D5C0C0000379DC0C4BCB2ACA99151313327193993B1B4BFB9AD7911000000347BADB4A8B0B38F480500185EACC6CAC0BABA964C07000E487EB1CACFC8B69B631F00000B2520180700000000006B70899ABEE2F5D9B76D271A263F6AB2DCF0E3BE7120050000134499D7ECEDCE9D602C15050C1848A17ECFE0B773452320161E23355FB8C9A55B392E2C2F3E4DDCF0E3BE7120050001FEBC5D070718C07D60617F7D6E78A3A7A3A88B6A502A1C0B152B445F95C4EBF2F6EAA5512E408CCDD9D5E1C7A56B504D4976A4BBA8A1A5A69C650F00002774ACC1C3B8AC6D1B000F71A6C6C3C5BDBF9A4100001F72A7BCBFC4C0A76B110000389DC6C2BDB2ACB2964F243B31163A7CA4BEBDBFA76D170000003680AEB2ABB0A88F3600001063ACC9CCC3C4BB9B4000001B4A8DBBC3C9C0B29E641B0000061A1E231311060000006C6C7D96C2DFF5D9AD622C11213A76B6E6FAEBBB6B240000000F50A6DFFAEFBF8D66290F090E1C4EA473CEDAB4683A241F1726293B67ADAD7D4A352C2B394F51E6FAEBBB6B24000001FEBD5D070718D0795C597E7A787CA3A9A3A08263412B150C1829416198DDF2F5F0E0A35623378ECFE4E1E6D79A64433A3A689DBFB2A3A8ADA15C0D00003181B0C1C1BEA8691B001470A8BFBACCC0BE963000001B6BA7B5B4C0B293600E0000479CC0C1B8B0B1B29C58394734234485B2BCB9BAA967180000003D8CB2A7A8ABAD8A2E06001661ABC5C3C9C5C09F410200175191B9C7CDC7A896621701000D1B2C221703000000006D7285A6D0E5F0D7A46D2C182C4D77BBEBEDE0B7712D0002060F47A2D9F4E5C2915E291D131D1C59AE70D2E1B36342322C211E232F5CA9B67B4332312D3A4152EBEDE0B7712D000201FEBE5D070718E06A515769646484A4AA9A9D774F352B1510273F4B679FD7F8F7E3D59D4F2F478DC9E4E4DBD28F5F413D386FB3BEB7B4A6AB935709000C3A80B8B7BBC0AD6810001070B1C5C4BFC2BC893000001C68A4B5C2C0B09F590D00004298C7CBB9B7BBAA9B59394C3924418CB8BDBBB3A165170000003A87A8B49FACB185330000105F9ABFC1C1C0C08F3D0100295B9CBEC7C7BCA9965B190000081C2B231B0E000000006D778CA7CDF1F5DBAC5E382A2A446EB6E9F1DEB871270000000751B2E7F3E0BF8F582E0D0B162F69B670CDD6A76741412919182D417BAEAC734D39403743454EE9F1DEB87127000001FEBF5D070718F079555A6F6F8195B4B0A0907A51371C17152D3F4D75AAD5F3F8E3C9974E31448ECBDAE2DED38E544542396EA3BCB8ABACB09F580400043F8EB7BCC3C2A65710000F6BB6BFC0C6BFBA9137000024689EB0B8C6BBA36614000241A2C5BCB4ADAAAA95524363421E3F89A8B3B4B8A1640E000002458EB2B0A0AAAA76260000185AA5C4C3BEC4B49332000016539CB7C7CFC0B8914D1F0303102B37281C0A02000000748291BBE5FDF9EAB75C2622344975BFF2FEEAB26C2F16150C1E56B3E1EBE8C08955340D0B072F79BD6DC4CBA8624344431D1C343D7CB0A86E3E33413E324556F2FEEAB26C2F161501FEC05D070718007E625B6D7487A7C4AE9D906F4F36211E1E2B446B89C1EFFFFFE7C9864C2D4A9AD3E8F0E4C878493A3D487EBCCABDA9A6B69D560900044491B8C6C2BAA4570B001974A4BCB9C4BDB88F2B0000136D9999B5C3BB9D5E10000349A2C8C8B6B2B2A8995F48694A2D5591B9BCB8B19C680F0000004D8FB3ACA5A9A26F1E00021D6493B9C4BABDBA842C0002266AA7C4CBCDC6AE8D500F00000F353C31150F010000007B8D9FC7F2FFFDE5BF723D2A364A84C6EFF0DFAF6F280B16121851A9E3F0DEBC875C2B140E1A448CC66EC8D3A26946463D211E264078AFA3681A263F463D4049EFF0DFAF6F280B1601FEC15D070718106F5A586A6E80B3D3C1958D6C442915141E40546D86BAEBFFF3D7BD7B42304692CFEDF0EFD07F463A2E4881B5BFBEAFABAC974700000648A0C6CACDC59D4804000A67A5C3BEC0C5B6852B00001D6698A3BBC2B5A3601800004DA5C0D1B0AEB6AF92554772462F4E95B4BBB3C0B57409000004528EACA2A1AFAB6F1700001967A2BBC3B2BEBA7A29080A306CB1C5D5C5BAB28E4C080000182D3C38180F000000008997B0D4E5F6FDEBBA65382A335296D9F2FCE2AD681F0B0F0E1C57ADD9EFD8C18A4C31180E18428BD071CBCB9A634D573C222739459BC3A85A322A34413C4346F2FCE2AD681F0B0F01FEC25D07071820705C54646783B9CCC08D725E34271D1E253D4E6989C2F5FFF4D2B677382A5596CFEAEFEFC5763D3B323E8ABECBCAB0B5B78B4300000E56AFC7C8C1BF984600001661B1C4C6C4C7C17E1C0000225F8BA4B3C1B5A65912000056A5CCCBB4B3C0AF9F5C466D41254C8FB5BFBCB7A86D0C000009599EAEB5A2AC9B6617000016548DAAC2B7B7B3771B0006357AB4CBD6D2CABA90430C00050D333A351E0A040000007B80A8ECFFFFFEE0A9592C2B355289D3F7F1DFAC6823181109185DB4EBFCE0C5865D2E1003204999C765C5C79C5A4D5A4028172C4A95BDA963372A4053414548F7F1DFAC6823181101FEC35D07071830776A6C686F9AD3E9D0886450392D1F242C4063789ADAFFFFF3CBA56B3C31589FDBEBF5EFC77440382C3F8CB7CCCCBBAEAE84400000185DAACAC0C2C1A8370000116EBCD0C9CAC6BF821A00001B688DA1B0B9BBA1581000004CA9C2C7B8AFB1B18E55547D4F345196B9B6B3BEA56C0C00000A5A99B9B39DA49B5B18000016558BADBDC1C9B5772100023C7CB9D1D5CECBB489460300011A374238240900000000849DBDE7FFFFFEE4AB5F2D293E5CA1D8F5FBE7B66023212815215DB6E3F5D9BC81562A190E1248A0DC63C2C89F5B61676F3C22204494BA9A5A2E29484A403B43F5FBE7B66023212801FEC45D0707184077636367729ACBE8C58E60422B201E202E457290A0DBFEFCEEC19960302C57A6E2F9F8F2C6653831344487BFC8B4AAA6B68C3600000F65B0C3CBC8BB963B00000966AFC1BEC5C6BD832500001D608A9FABC3BBA3580A000253ACCACEBCAEAFAD925B628349274D92B4BCBFBCA7640E00000F6AA6B2ACA09E9558130000184B8FA7BFC1BDB076240012468ECCCFD5DCCBAD853B07000515375548230B000000007B9BBDEBFFFFFFDFAD5C312F2D5296E1FDF4E0A56B23102A161860BFEBF3DBB57E562A13091852A3D557CAD4906C61705D31203258A3BE9851282D4549413D42FDF4E0A56B23102A01FEC55D07071850776262656F94CEE6D28861432F1C1C242A4571849FD8FDFFE8BE915D2E2B63A5DDF1F0E7C2603F443A3B80BBD0CDAFA9A8822E0000256DB5CBCBC5C1902B00001168AFC8B8C7CDBA76120000185F83A2C5C9B7A75904000A5DACD2D3BDB2B4AF926156724B2F5DA2BEB8B9B2A65C060000136CA7B9B7A69B985B0C0000194B8BA1AEBEBEB46C1C00094788C1D9D2D0B8B082360700001F4A60462A0A00000000809CC6F6FFFFFFE4AA5F3B2E395BA3EDFFF9E0A85D2E1D221A1A60BBF4F2D9AC77492B180E1B53ABE164C1C79A65677B592B21255EB6CCA24F271E3C4C403A3FFFF9E0A85D2E1D2201FEC65D070718607A62535B699ED1EBC78A6E3F291518233B5D7A9DB6E9FFFFD9B17A3F232D60ADDDF0E6EAC06B3B3E3C4887C5D4C0A9A8A4701F00002578C1C8C9C5BA863400000A67B1C7BACBC4BC681400001F4E89A3BBCBC39E5910000258B9DAD7CBB1B6B18C5B647B4B315F9BB7B3ABA5A55F040000267DADB1B59FA2944E0900051F437CA1B8BEBCA5631C00124D93C8D6D1D4C2A97F350303002250674D200E020000007E99CCF9FFFFFFE3A4593D354973B6EAFFFFE3A6522823240F2775C4F4F6D8AC773E201E122B63B4E85FC3C79A5E69876733223172B4CB94482525474D3C3B4AFFFFE3A65228232401FEC75D070718707867686575ACE6F3CB8E5F3E1F201B2D365C83A8C4F3FFFFDDA379472A3368B4D8EAF1ECC46E413A2E3D91C7C2B9AA9C96661E00002F8AC3CEBBC8BC83270000196CBDCBBEC2C5B57415000018558EA2C5D1B6A25108000D5BBED8D1C5C0BCAB894D6076463B6492B2AFB6B6A35C0600002978A9BAA8AAA28D4A00000C1C416E8EB1C0C1AF560C0017589BC9CBD3CFCAA67A3904000D2A5C6F502409000000007993BBF6FFFFFEDB9D5630354065A3F2FFFFDB995B281F28233A88CFF4F2D9A773471F0B072461B7E15BBFB97C566E8A743C1A336BC1D19248201C4C4F3A3948FFFFDB995B281F2801FEC85D070718807D6A5C5C75AEEDEFD48A553824221F26396389AAC4E8FDEDD1905E302B3C7BC1DAEBECE8BB5838342E408CC3CBBCB0A3AC631900002880CCC8C3C1BA832800002478B8CFC3CAC4B86D1400002660899EC7CAB89F4E00000359B9D0C7CAC5C1B28A5C6A7C493D729EB8AAA4A7905B0A00002E7BA5BDB2B4A68A420B00041B2F598CA6C0C7A357140A2353A2D4D9CDCBBDA269290200073061785C361007000000849ECFFFFFFFFFDF9C5933344F81BEF1FFFFD79A511D11201B4083E0FFF5D3A06F46201A162166C6EA5FC0C18959718D763B1B357FC6D69C4E1B184444334248FFFFD79A511D112001FEC95D07071890756C5F576CB1EFFED48C542D22191426426794B8D1F8FFFAC1845122263770C1E6F3EDE3BB643F352D4B96C2CFBDB6B6A5681000003496CACDB8C9AE70180000197FACC7BCCDC8B861120000225888A7C5C6BFA3500400084DB1D2D9CDC5C4B0865264754C40759DB2A6A4AB9D58050000357CA7C4B8AA9D883E0300020A2A4F73A4BAC6AC5A15092F699FCCDCD8D8C59F642800000F2B5D7A573216000000007C96D4F8FFFFFFDFA7573A39548ED0FBFFFFD694491C0C1717398DDEFCEDCDA66936150D172676C2EE61BBB5905878987D40253B7ECBCE8F3C101F394E373148FFFFD694491C0C1701FECA5D070718A07069656F79B0E3FFD389563418181D243F77AACCDFFFFFF9C88A46201D3470CAE3F2F7E2BC633333324A99D1BDBFBCAEA2530F00003990BFC2B9BEAE691D00002279B0C6BEC8CCAF59090002275F83ACC3CEBA914703000B5FC0E6E2DDCCCBB48C57656E384171A5A9AEA5AF9251000004427FA8BFB7B39D823603001018283F709AC4C09C510C01226FACCED8CFCAC5A55D1F000011406E7D582D19040000007E94C6FCFFFFF8CF8A5A42395380C6F4FFFFD18E451D0C18193B90DEFEEBCFA25F30120A1F286ECBF166B7B783517292834D295397CCCA8E35121D3A3D393A4FFFFFD18E451D0C1801FECB5D070718B07D6C605C77C0FEFFD08C5A2B1C111D294C81A9D1E9F6FFF7C57B381B162C79CFDCEEECEABC65322D244C9CC5C2B4A6AF934A0D000D50A7DACFC0C99E530C00002E83C4D3CDC3BBA75B0C0000275E97ADBACFB5934A0600005CB5D0D7CAC3C2B4945968784A537D9FACA3A4AB974A0100074689B3BDB0A9AB7F310000050C21396394B2BB9F430D10377BB3D3DAD5D3C19D5918000210356879582E1710000000827FC7FFFFFFF9BF884F39485D8ECFF9FFF1D183432C1C0E1B409FE7FFF6C78A5C2C1714173085C7F153C0B2805A798C8646294890D3C98436150E3C4628354EFFF1D183432C1C0E01FECC5D070718C06B66625F6FB9EFF6D4894C270B181B304D85B8D0E2F6FBECC4793316133374C6DBECF3E8B7603938274F93C4B3B2B2A6854B0B000250A3C6C7C3C69C500B00002E8BC1D4BFD2BF99580B0011396C9CB0C0CFC49A3800000556B8E1E6DAC7C1AE87525F653C5080A4B3ADA59F8E4803000D5293B7BFB4B19B74260000090A13275399B8CA98461920488EBFDCD3DDD4C694480B00011C4077795F391D05000000768FCBFFFFFFFFC6864D35435C94DBFFFFF9D1824018160F1F49A8E9FFF5DB9955302121223583D0ED5FBAAC7F5A7C8F743E33599FD7C985310F0F2F4035334EFFF9D1824018160F01FECD5D070718D0716A616077B7EFF1D58953291A14192E5189C8E2EEFDFFEEB86F2F0F0E2975C4E2EFEAE4B462382C2E529FCFBEB9B8A2793C05000B5CB1D7C5BAB4913C0500003681C0D4CCD3C49C4B0400144675A7C2C8D4C2953B0000095AB7DBDAD7C4C4AF814F6168445984A7B1B09CA39041000018599CB2B4B7A79E742000000E1012285296C2C88F3C0B0D4593C1E0E1D8CCBB8E490C00001B4A7183643919080000007990CFFFFFFFF1BE8A453A31629DD7FFFFF9CE763913181C214FA9E9FFE8C78655341E11132F93DAEE61B3A873517BA0873E2A5C9DDCCA7C2411163840323653FFF9CE763913181C01FECE5D070718E06F69656078B8F0F8D88551301D1A1D2A5393CFE7EFF7FAE2AB692A0F1A2A70BBDBECF1E0B75928272556A3CBB5ADBCA27E3D0700145FB3DEC5BEBC9547080000448FC2D0CFD5CF9A400200084278A0B3C7C7BB8C3600000C5EABCEDADCCDC1AE80515E61495E8CA7B2A09CA6823C000029639BB6BFB7A8986A15000311030718457FBCBE8F461B1E479BD4DBD5D7D3C5933E080000224C7E815A3222000000006778B1ECFFFFE8AF7339393A6198D1FFFFF1C36C3211130C1D52ABEBFFEBC388532A1E121F388FD9EC5FAB9D734F749575453964AEE8CA723114132929283660FFF1C36C3211130C01FECF5D070718F0716B635E7DBEF4EEC4885B2C1B121934539BDFEDFCF8FBEEAA562203112971BCDBEEF1DDAB5C31292F61A8D3B8AFBC99622604001664ABD6CBC0BD8F480400053991BED6D3DEC9863500000D4672AAC3CBC5BE933300000856B3D7DAD7CFCBB57641525A406998A5A69EA0A4843900002172ACBCBFB2AF9B6117000013090C174286B3B67B340F2161A1CCE6DFD3D7CB8E450C000036607D805E3B250E0000008095CDFFFFFFF1B98249353C66AAEDFFFFF3C27A39180F1B265EB4F2FFE9C48E44221A181C47A8E1E855A9A36C486D8E7542367ABDECC77D2E0810313D34345DFFF3C27A39180F1B01FED05D070718006E75615C7CC0F1E3C58C542C1813203B57A5DAF0FFEEF2E09F5A1F0B112C6FBDDBF3EFE0B45E2B1B2A4BA5CAB9B1B797692400002273B9D8C7CBC287370100124099CFE3D0D6C07E3301001F5381AFC3C6D2C0782500001E6EBBDEDDD3C8BDB06E43505148709FA1ACADA2A5813800002D76B0BEBAB2AC9D540D0000180C01103E72B3C3802B102D60AED3DDE3DDDACF913E0200002D667E7E552E1A010000008894C9FFFFFFF1B97B4D484879B4E9FFFFE7B671311A141C2169C0FDFFE9C08745221E201E469CDDF463AF986C416F917842407FBEE8C476310F0929354A3B67FFE7B671311A141C01FED15D07071810706D646180BBF4E8BE824E2D1A1A24346CB2EAFBF0EFF4E3994613030E2E6BBAD4EEF2DCB4592420275BAECFA8A5B788562000002072C8E4B5B6B7823706000D519ECADBDEE1CA86270304275A8BB2C0CFCAC3822B00001B65B3D8E0CEC5B6A2613B4A50466394B3BAA7A39F833900054186AAB8AFB4AB995A0C0008180900113673B4B57835192D67B9D6ECE9DDD3C6903F03000031557574533B21080000007480B4F6FFFFDDA769352E3C6CAFF3FFFFEBB25A29170C1D3768BDF1FDEFBA782A1F151A2658A9E2F165AF9A633F688770434C8ACAE9C06F2C020C272D2C326AFFEBB25A29170C1D01FED25D070718207D705F6B7FBBF4E0B48853281C20243F6DB9F2FFFFEAEED8924C1308132E66BEF3FCECE3AB4B2A18245FB3C9A5B0B47C441400002781D8EAC8BAC08927000421519DD3E1D7D0C1792A00012A6A90BCC6C5B9B6862700001C62B4D5DFCEBEB4A6592E44544F75A1ACB2A49D997934000B4A8AB2C1C3BAAC9257040002210E02082C6FB4AB692613346FB1D0E9DBDBDBC7913B01000A38707D704A3022090000007A82BDF8FFFFE3AE6B3A363E81BCF8FFFFE7AB53200F0E132374C7F8FCF1B679432E1D19214EA9EBF46B9F8F5733668D743B508FC8F0D06F250B0A26342C3364FFE7AB53200F0E1301FED35D070718307378686E7EBEF6E6BE84572C22202A3E6DBAF8FFFFF7F2D68D45150114306BBEE1F8F0E9A44C1D142061AFC7A5ADB47C411400093688D5E0B6B2AE7E2A0B011E54A5CBD9DEDDC16E29000C306092BDC9CDC5BA7C2C00001F6BB6DBDFD9CEBC9651293C435180A5BAB2A19FA26F1A000C5099B6BABAC0B0844600000D1D0D0009366BA4A05A23153584C0E2E9D7D2C9D19F3704000644767F6E503520090000008090CAFFFFFFE0A36F3E41547BC1F1FFFFE9B75E2D1914172B75C7F4FDE7B2753A27201C1A58B2EAEB5BA2825432568C66475999DFF3D17A24090A2031233275FFE9B75E2D19141701FED45D0707184072716E707EBEE0D8A781502E1715193C72CAFFFFF6E3F2DA8842180611336CB7F1F8EDE3A94318172761BFD39FB2AD6E2F0A00023E90DBEFC7BFB86F2000072056B0D1DFE5DAB9721F0004336494B6C3D0D0B6772600002662B3D6DCD1D7C39B481C2F41487CAEB1B6ABA199712900074E97B6C1BEBAAA8E4400000D1F1403022D6BA49B5A1F183884D0E4E8DED9D9CC973E0000143E7B80673D231E0F0000007C7CC3FFFFFFDFAC65474C6380C8F5FFFFE0A7582219161B2E77CFFBFFE7A8663323181D2661AFE0EA54A08B5333638A724864A1D8ECC677251509252727406DFFE0A7582219161B01FED55D07071850706E65667CB6D5CE9A724B2D1C1F32447CD2FFFFFFEEE9CE85420C010F2C66A9DAEFEBE7B5571F132860AECBADA49E6C2E0E001242A3D7E8C4BDB5732502061C62B3DBE2E0DDB26C1E03063D66A3CCC6C6C6BB80290000286EB0CFD3CFD2C19641192D384886A9BFAFA69F9C672200175DA0B8BCC4BFA67D370000212F0B000022609A95572421488ACBDDE0DAD6CACD9B3600001250838A70493321090000007675BBFBFFFFDE93433632518DD4FEFFFFE4A9512818261D2877CBF8FFD9AB6E3215191B2867B6E6E65997814B3F6C896C4069A6E3FFCA73270B081E282B3A74FFE4A9512818261D01FED65D07071860767665707EB6C8B59A6340211E1C365086DAFFFFFFE6ECD4803C130010356AB9ECFAF4E7AB54190D2164BDCEACAC9D6924000004469DD8E6C2C1BA702600012763ACCEE2E0D9B565180011447EADC7D3D1C7C57F1B0000256AADD4D7CBCFB78E300B2B3B508BACC5BCA8999860180015709FB8C6CDC0AD7A420000102C1600001C679F894B20204A8FDBF2EBE1D3CFC99B3C030019578B7A50403529110000007183C0FFFFFFDD98643F455593D8FFFFFFD7A24F331304133981D5FAFCDDAF66261F0E0F2C79C2F1ED589E71482D567A6F4F74B5E0FFCC7229090D1E25274075FFD7A24F3313041301FED75D07071870756D59667BB7C7AD916D3D1F1B21294B85DAFFFFFBDEDCC8793A130F15346DC0EBF5EAE5AF4C1A122166CAD0AEA997551D01001149A5DFE7C0C0C56F17050A2C75C2DDE1DFCE9A5217001D4D7DA6C7CFCACDB66B1F00013C6EB1CECED3C4BE8D2B132742608EB2BDADA4B39A51110012609CBABDC2B4A0733200001B2F14000129589087552C274493D3E7EBE2DBD7CA943C040022538E88533C35240F0000006F82C0FCFFFED296614B486188D9FFFFFFD69943271D1419367ECEF7FAE2A668241B1D27327DC6F4E64C9571442D5C7863537FC4EEF7C975230D101F2A193772FFD69943271D141901FED85D070718807C745F6883BDCBA9805C3E302722325C89D6FFFFFFE6F2C57A2D140A163E6DBCE9F2F3E19A4617112968C3D5B3AFA4541100002253A7DFEDC6CDBF6E21000C2F73B9DEDCDED4AE541700184F88A7CECCCBC7B36E2400053073BCCDD1CBCABB8819061F3F5E90BEC8AFA59F8A430A0023729EBCC1BAB49A712300001E321403012657937A4D2B2D559CE4EFEEE4D7D7CE862D00001C6298875B3A30230E0000007581C3FFFFFBD8936244485F90D4FFFFFFDB9A56251C1D173283CDFFFFE3A364281216193288CAE9E2568868342C5976605581C0F4FFC671200F051E1E21397AFFDB9A56251C1D1701FED95D0707189070635D6A86B3B897774F372C1B273B5685E3FFFFFCEFF3D178310B0E234473B9E6F1EBDDA742130A2C6EBBDDB5B99A4E0C00001355BAEAE1BDC0B45F1A000E3671C2D5E2DBD49E4E0D05265F8AABC7CBC4C7AB711B00074088BED2CBD3C6B17914001835609BC3BBAB9EAB923F04002576B0B4C2BAB59060250000233215000225588D7F47262B56B0E3EAF2D7CDD6CE93360D03296092854F3838281C000000717EC3FFFFFFD99254484F678DD5FFFFFFDA924E2A15171A2B83D5FFFFE69A541D100F1B4196DFF5EC48896F3E2759685F5086CFFBF5C5681A0C031A22283C7CFFDA924E2A15171A01FEDA5D070718A078776D7B80AAB8A47D4E4437232E38568BDFFFFFFFE5F1CE71300D0C163F79BEF0F0ECE79C3717132F6EC3DBB4AB8A500C00001C5AB4E5E5CBD4B15A1401104383C2DDD4D4D29B4B10001E6690ABCCCDC6CFB26C1900054A95B9CBCFD1C5AD740A00114E6CA3BCC0BCB0A3762300002071B2BDCDC7AF8C51100000213D1E061026628B753A1B285DA5DDEFEEDDDBDCCC913107002465988C4B2E312D1D0300008392CBFFFFFFDF9358524D6E9DE8FFFFFFE5A1502E170D163089DDFDF2D79D52292018284DA0DEF4DB4E876C31294D64475798DAFFFECB691A09111B1D273372FFE5A1502E170D1601FEDB5D070718B0707068738ABEBC9C7B4E3929282D344C86D4FFFFFFF2EDC56F2C1109214074C4EBE7DCD39F4813133474CDD9CCBE974D0D0000185BC2EDE4C4CBB55C1500133E80C5D2CEDDD0984104012A7498B4C7CECDBEA16815000D4B86C0D6CFC0B8AF6B0800124A71A0C3C3B0A6A17B2E00002973B5B6BBB9B08C4C0500002D40230C0F275C7D68391E2763C2E7EFEBE5DED7CD92320A073477A87D4C35322B170000007585C0FFFFFDC58C5C43445186E6FFFFFFD592442A221614368DD5FFFFD5955627201C2857A7E8F4DF448865361E3A554B579CD5FCFFCB6C200B081C212A3B7DFFD592442A22161401FEDC5D070718C07E71657E90AFB38D735043302F28305E93D6FFFFFFF9F9CD76240C0B20427FC3E9EFE6DCA24417072A7BC1D8C7BD95470E00021B6CC0ECE2CDD9AE5D1200094088B7D7CBCFCA8D3409032A6E99B5CED5BCBCAF6C1A01165D91AFC9C1C5C8A75F0000164E7CA2BDC3C0AE95731300002E84C0BFC5C3B17E370000001E3B24161830597C61342A3275BAEFF6E6E0DAD5C0892C07003675A793513A362F130200007996CFFFFFFFD7916848425A9EEAFFFFFFE69D5D3C221E243488E0FFF7CC924F2515152B62B6E3F4DE437E5E3423495D445C95D3F0FCCF7226080A23222F4789FFE69D5D3C221E2401FEDD5D070718D07176768694B6B38A694C3F2C2B3434558DDCFFFFFFF0FBCB69350F162F4A90D3F1EEDBD5943A0D12357ECBE5CFBE8E430300002670C4EADFC8D3B7510B0010508EB3CBD0D1CB8E3D0902317FA9BFD5CCC0B6A257110016649EBDD1C4C7C4AF6100000F517FA8BEC1AFA89667070000288BB3BAC1CAB87A350000002837301D142A586F5636284378C4E6EFEDE0DBDEC390390C0D3476B08D4A30272D12000000768BD4FFFFFFD584564E455FA0EAFFFFFFDE94473329272E378FD9FDFBD597441C161A2A6FC3F4FCD84480621E1C344D4664A3E5FFF9D2702111182022223880FFDE94473329272E01FEDE5D070718E06D68657089A5A57B64413B342C37394C82CCFFFFFFF0F6CB6B2C0A142A528CD0F5E9DAD2903D110B347DCCEBD2D3973F01000A2873C9E6EBD6CCB2480C00104E8CB8C0CAD5C6883A0D022B81ABC1CACDBFBD9B4E0D00156EA0BFDBD7D5B7954D0000165E8DB6C3BBB2A196600900002F88B1C1C9CEBD732B0000001D39251F203454705B352A4384CDF2E9E7E7D8D2BF83290B14487DAA904B30312B0F0000008195D5FFFFFFD69467504F63A6F3FFFFFFD89851382F1B2D4895D8FBEFCF8E431D151F4588C9F9FBD53B6F53291D2D453F67A7DAFEFFCB702E1101101B2C3D87FFD89851382F1B2D01FEDF5D070718F0707367748BA3A8866A523D2C2D433E558BCAFFFFFFFCF3C16D2C1918375599CEE8DED3C8893212104387CBE0DCC69337040000206FBFE1EAD0CBA84E0A001E5B98B8C7CDCDC8812E02063886B2BFCDC1BBB9974D0D00277BA9C0D7C2D2BDA04C00000D6F95AAC1C1AFAC905D030000307EB6C6D0CEB064140000002B423C2627305B594D302F4582D0F6ECE6DFCECCBF782A0A164880A98B583D3B35180000007588D7FFFFFFCE834F4747619AF5FFFFFFDB93593C28202A3E97E0F5F0C48F481F23163083CAF0EFCF31624C2A1D3E45456CB1E5FFFFCF722B0805171F264487FFDB93593C28202A01FEE05D07071800786D698295B1A67D5C43392E3C383E6385CAFFFFFFFFF6C56B2D171B3A5597DFEDE4DED28C2C04183F89C4DEDDD490390300002F7CCDEDEFDFD5A24503000C5090B5CCCBCCBF762D00003084AEC6D5CDC5BF944F0C09317DB4C1C5C8C8B7993E00001171A1B4BCCAADAA793F0000003C89BEC6CFCDA955090000002738322D303A58563C3135518AD3F7F6F2E0DBD6C076290B1E4685B288533A3D3D1D0000007889D9FFFFFFCF8861525065ABF7FFFFFFDE975940332B23419ED9F8F3C37F400F14193A86D4F5F4D33A744A281E4542466EB0E6FFFFCB6D28101519202A4091FFDE975940332B2301FEE15D07071810776C7083969A8966523933312C38465982C3FFFFFFFFF2C56A2A0F193260ACE2ECE1D9CF823819185097CBDFE6D0933D000000317AC5E9EAE0D8A7440A001857A1C4B8BCCABA772000053993B4B6CBCCBAAF89471309378BB6C6D2CCCAB399450000207BA9BCC3B4AF8E703F0000004894C5C5CACFB34F000000001B393222203E4F5B4431435F94D7F6F1EFE3E1D4BB6C1F0D194B8EB190533E3A362202000086A3E9FFFFFDCF91675F5B719FF3FFFFFFDE9863432F2B293F9AE3FBECC28536140F21499AD9F3F4CB3C664329192B3D456FBCE5FFFDCC7E2808061118213C97FFDE9863432F2B2901FEE25D07071820676F6B879197896F5D42403C343E49587BC5FFFFFFFFFFC66926171F385DA4E4FAD6D9CC812F11204485CFE1E0DD91300000042D84CCDFEEE1D4A34003001A61A4C3C0BED1B86D1A00023990ABADC0BBB1A7803B0609428EBAD1D8D1C5B995360000237EB1BEC2BEB29E6F3900000246ACBBC5CFCBAB4A0000000026453F2A2B3E4645302C3C5F94DEFDF6EDDED7D4A8681805225494BA9A5F3F3F481F0200007A95D6FFFFFFD084614C5B6BA2F3FFFFFFD39A60372E21233D97DDF9F1C36A34131B235198D5FFEBCD295F41261F33303C75B8EAFFFFD1702C1105132225419FFFD39A60372E212301FEE35D070718307D6D60778F94856C604142433B434A5783C7FFFFFFFFFFBF56221C213966AEDEF4E3DECC7B2C0D165587CDE9E4CF983402000E3E84C8E8EAD4CA983500001961ABC6BCBDC1B06F210308388CB8B7C4C2ABAC724A10123B93C3C8CDCFCCC59C3B00003082A9B8B8B1B697642500000D51A9C1CFCECB9D3F000000002240423C30374A462D39456693DAF4E7DDE5DCCEB6641E05205191BD96624444441F0700007D9FE8FFFFFFCA8B5C4D4D63B6F2FFFFFFD4965F3F28262D44A4E1F9EBC1702F16202756A7EAFAECC0355D3E1D16233D3F81BCF0FFFFCD74320D072E2B3159A4FFD4965F3F28262D01FEE45D070718406F5E5B7683947E6B4A443E403D434E6484C0F9FFFFFFF0A54422131E3870B4EBF0DDD5C9832611265DA0CFEEEBDA8F2B0000063A84C5E3E7E1D6973C0200116BA4C1B3BCBCA8631900004397B8B7B8BBB2AB76491D0B42A5C4D1CDC7C6BD8A2400003290B0C1CCBFB0844F1A0000125894B3C6D5CE9E39000000002C5148433D3B4F362E30446399CFF4EAEDE7DCCDA059160B26649FB8965E364138210200006F9ADCFFFFFFC47F5C48596EB2FCFFFFFFC8955B4A362A2446A1DDFCE8A65F24120F2F5DA7E4FAE0B2385842201424354282CCF1FFFECC7A24090B1B2A425AADFFC8955B4A362A2401FEE55D0707185084706B7F9B9B88655D535046454B45598AD0FFFFFFFFFBAA5424132A4B81B8E7EDE3D4B9772F0E275A9CDEEBE8D890320000143688C2DAE1E0D48A3102001E6CA0C0C1C5C0AC5A1500053892BAB6B6B7A89F69320B1853ACC7D8CCC9C0BB8F3000003B91BDC0B8B7B98E3E0000001663A1BFC9C5C19939000000002E5050454742413C26385379A0DCF2EAE5E5D8C4A1581B1738629CB99F694B4C452C00000079A4E8FFFFFFC58364575F77B4FBFFFFF5CC945A3E31212C4DA4E5FCE5A86B2915172E61B1E5FCE5B2344B37181D1D2D4893D6F2FFFCC87130110A152E3B56B5F5CC945A3E31212C01FEE65D07071860745A56707F8C7C625C4C47484D464A6089C5FFFFFFFFF2A3481E1426508AC8E5EEF3DAAE601C12295FA5D4E5EFD78D300000063B84C4EDEAECCE882F0000216DAAB8B6BDBEAB560E00014A93C2B8BCC0AEA1692A0814529CCCD9D1C6CAB8822500002A8CC1C8C3BBA9862D0000002067A6CDD7CFCE903400000000345357494A44432E28355073ABEEFDF0E8D2D0C192460E0B3163A0BE95674F4941280000007390EAFFFFFFCA8C62595F81B5FFFFFFF3C2904B3235172351A8E6F7D4A15C261519275EBFF4FDEAAF234933222426284185CDF5FCFBC9712D171223253167BCF3C2904B3235172301FEE75D070718707D6E6974828778655A4D4C484D5352668AC6FFFFFFFFE9A045211A325284C4F4FCEEE0AD541C102F6AB9E5DCDDD78E3C00000E4A89C2E0E3D5CD802700002977ACBEB6B9BC99510503053C8FB4BFBBB8B79C652E10185BACD0D7DAD3C5BD85290000409BBCCAC5BBB77E1D000000276EABC8CFD4C9953100000006315E604A4943372C2936557AA2CCEEF2E5DDD6C28F39050F306EA6C1986E4D4B44230000007E9BE2FFFFFFC98663536380BDFFFFFFF0C3894A3A28252154AFE4EDDAA256241A152D5FB6EDFFDFBA34412B1D20212B3E90D8F7FFFFCF7B2F1B101F2E3B63B4F0C3894A3A28252101FEE85D07071880736A66787984736A655D4C4847495D769BDBFFFFFFFFEB9E471F10365B91D1F8F5EDD2A5531D162D6DB4DEDEE5D9922B00000E4289C7DCEAE8C9802700012982BCD4B9B8B59A470D00004397BBB2B5B3AA94662A0B1E5CB0CED7CFC3C4B2781F000048A1C3C5C2B8AA75190000002C74B5CDD3D0CD973A0000000138636D5F503D32252A415D7CABD6EDF0E2D3C8B37E32000F3471AAB99C725D5A4B1D0200007A9EE4FFFFE8B17458546983C6FFFFFFE1B97E4730281B2A58B5E8F0D4994317131C3170CAE9F5E5AA30462A1D1F2934428BC7F4FDF8C47225150F1C2D3D65C2E1B97E4730281B2A01FEE95D07071890796C637B7877766657535355525859709BD6FFFFFFFFDF8E53261E2D5988CCFEFAEBD39D521B0C3371B6D9ECE0DD942D00000A4792CED9E6E2CF872000002B84B5C1B7B7BB97450000004496B5ABAAB4AB95562811186BBED9DED8CFC8AE7C1F00004EA9C4CCC2C0BB7F0F0000003575ACD8DBD7CC913300000000345364645A4D342425385F8AA6CDEBE1D9CFCAB378310C113171B0C2A071474F471A0400007D9DEDFFFFFDBC775D556389D6FFFFFFE1B17D5134221A2B4FB6E5E9D2905E220F1C2E72CAF6F6D4AB2E3824192029313B8BD6F3FFFFBD732C10161E223F7ED3E1B17D5134221A2B01FEEA5D070718A07E6B6972727B6E616250535A57566177A7E2FFFFFFFFCC7F341D223E5597E0FEF0F1D198481C1A417FBEDDE6DDD18D36000009478EBBE2E2E0C1782700033E7DBDC4B8C1C0A1420100034996B7B5A6A4A19551230A1763B5DBDBD3CDC6AD741B00005BB2CBC6B4BCB16F02000000368BC2D3CDD8CE8E3500000010446D6E605D4B2B231B376A8FB0D8EEE3D5CDCBA666280A153976AFC19D7C5343341300000075A2F5FFFFF4BF735D4F6490C5FFFFFFD5A979412F2C242D68C1EFEBCE8F3E1B0C193479C6EDF9D89D2B371A203E2725428BC5F6FCFCC4713410161F314179C9D5A979412F2C242D01FEEB5D070718B0786A6170746C655C5B52565658606176A4E1FFFFFFFFC9783D2023386B9EDFF5F5E4CF9D47141C4488BFDAE6DFDC933204000F469ECADFD5D4C2731E0000338BC1CEBFBEB697420000043F98BCAB99A6A587502A0D256BBDE4E3DECEC2B06918000762B0C0C5B8B5AD6101000000488FBBCAD6CBC5852400000007466F7B6A62422C191B3D7296AEDAE1D8D8CCBF99612208134180B2C7AA80614C431F0000007D9CEFFFFFF0AE6F5E516B8DCEFFFFFCD2A471422A2D29336AC3E0E9C382461D06213B81C9F4FFD19C35382B24261D264C94CAEDFDF2B66C2826181F354A8AD6D2A471422A2D293301FEEC5D070718C071695D686D6F6D5C5A5B5C59555A6076A5DFFFFFFFFFCA703B1A193A6A9DDEF4EBE1CD8E4C1B1E3F89C3D8E4DDCC9D2B0000135788C0DCE8DCBF711800003A8EBAC3C3C2BD9C460400044190B6BBA49EA990401810287BC3E4DCD6C6B4A2660D000861B4C3C2BABCB071040000005C9FC2D1CCCABE8B320000000B547A80756C4A261C1E427F97B0CCD5DAD1C8BF97582507164482B7C3A2785B4E431E00000089C1FFFFFFF7AF80655D628BCBFFFFFBDBA4623A242337336ACDF6E6C0823C201427347ED8F6F3D48C333A272A25242F4794CFE9F1F0C0672E1A1D26344394DEDBA4623A2423373301FEED5D070718D07B6E637670726C65685D6064676D6B82A9EAFFFFFFFECD7B3A1E284472ACE0F0EFEAD08E4621224891BDD5E4D1CC992A0000125B9DC6D4E6D7B96A0D00003F89BCD1C7C7BC9C380000053A8BB9A891A5A3824D240E1977B9E1E1D4D2C2AC5D0A00166DB6C7CDC1C1B76303000004639DB9CED3CBC89933000000195076838272533113123B799CB1C0CDD9CFCABC80491700113E83B6C6A58E6652371F0000007DAFF3FFFFD9A073515D6089D5FFFFFDCBA27A473129252C69B4DCD1B870331B18263B83CCEEEFD3982B34211C312D2F509BD5E9FAE6B569191417243758A0E8CBA27A473129252C01FEEE5D070718E0775F63716E6872616760647363656084ABF5FFFFFFF5B968382829467AAAE5F3F3E9D28F3F0C174A9ACAE3E9DDD1962D000018589EC0D9DBD0B25F1000003E90C4C3C1C1B88F350000024199C8B29E9E997D39170E2E82C8E0DDD5D0C2A15908001174B4CABFBAC3AF58000000066FB1D6CBD6D4C7923600000014547E8C847749210F1D4580A1B4C7CFC7C7BFAF753D1000174A89B6BDA17F63593B0B00000081CCFFFFFFEFA97262646C87CCFFFFF6C49768382D3233407CC9E7D9A76434180C244396D5F5F1C77D2B2F21272C29214098D3F2FEF0B15F271E1C2E3D67A0E7C49768382D32334001FEEF5D070718F07969656A6667635B655D616E76625C72B1F2FFFFFFFAB35F2A22264678B2E0F7E7E2BE8340111F4FA0BFD4DAD8CD973900001D5EA5C7DDD6D2B3570A00064796C2C7B9BFBD90330000074195C1AE929B91653C150B2F7ECCE8E2D6C9C59B4A0000217BC5CACABAB9AC54000000166AAFC8D3D6D3BA8D2D000000165D85958C854C220A174589A6ADC3C9C9BFC3AF7038090012428BC3C0A883615033110000008DB0FFFFFFE6A17962626A8FCCFFFFEEBB8B67391931334982C4E7D5AE67341C18294691D5F5E5B87E3C351B202F3336559CCEEBEDEBAD5B1E1718253668A1EEBB8B67391931334901FEF05D070718007665666D6A6266756068626F7B696D7FADF6FFFFFFE9AE602B1D294C7CBDEBF3E6DDC5773618225EADD3E4E1D3D8922500001666A7C1D0D1C9B95B140009499EC7D0CCC8B48C2F0000003E97B9AB949F8F682D1C102886C8D9DFD0C2BC984800002780BFD2D3C1BDAF5B0000000D74B8D2CCCFCFBD912C0000002360909B918257210C164388AFB1BDBDBDBCB4A468340F0A1B5296C6CEAF8B614B26080000007EC1FFFFFFE397726A666091D9FFFFE1A58B683C28333A3F7FCDE0CDA45E351B2C2F5C83D0FEE4BA7829281721302E2B47A3DBE6F3EAAC5C2B1A252F3F67B5F7A58B683C28333A3F01FEF15D070718107D6D67726B6A6A736D656A72726A6E7DB6F7FFFFFFF3AF602E1C2D4F81C6E6F0E9DCBE7734182871B6CADAD4CFD5972F00001E67A6C7C7D4D5A6540600044FA4C5CCBEBDB790290000093C8EB4A2969D9F643413103685C6E7D2D0C8BE832D00003994C3D6D9CCC3A057000000087DB6D8D7D4C9BE9534000000206D95A2938A5932151E4C90A3AAB0B9C0B4B2A162240E0D184E97C8C7A48767432A120000007FBBFDFFFFD99661646B6A8BE0FFFFE4AB8C623C2121314998D9E8CCA3552C241D2D569ADAF9E2AF6E282F1926322D2F55AFD8E3F1E59C552C13191F2E6AB3F5AB8C623C2121314901FEF25D0707182078676D726A5D616E6662727A7A68668BC8FFFFFFFFE0A9572720335286BBEBF1E8DAC57E3C1B2462AECDD1CFD7CE993100001C6DAED9DCDBC3A25A0D000055A9BFD3CBBBB181270000003695BFB196998B5C23120C2C8DDCE5D6D3D1BD813500003393C9CAD1D0CBB65C0000000C78B9CDCECDC9BC933E0000002970919D97875B1E10133F82A3ABB5A8A6B6BEA364290603216298B9C9AB835E442D1100000086C9FFFFFFDA8E65656A6894E2FFFFD7A27061382F38314B98D9E8BB8A4E2B1B283755A2ECFAE3AC6C2C291F292F273664A5D7ECE8D79953281D202C3C81C0F2A27061382F38314B01FEF35D07071830776A65695E5E636C69656C7174747387BCF3FFFFFFE89F532425354D84C2E5F3E4D3B06E2C102C6BBDCFCFD7D6D4923E00002B73AFC8D7D8CFB05600000957AAC8CAC5BDBC84290000004097C6AC989D8150250D12328BCFDFD6CECBBF7A310000398FC1CAC5C7BCAF5B0000001D83BCD2CCCDC3B694370000003180A3ACA6926724000E4890A8AFA9AEADB2AD9753230D08215E9BC7C2A2886743210A00000091D4FFFFFFDE95745E606496D9FFFFDBA97C61462F2E3758A0E0ECC9854F2F1926315CAEE9F8DDB171242C262B2B2A365AB1DCE2F0DC99542D1C1F223C77C0FAA97C61462F2E375801FEF45D070718407660656C68686E786A71747C887D6C83BAFEFFFFFFE096422B2430538AC6E6E2DADCBF722D183880C0CDC4C8D5C8893000002B7BABD5D9DBD3AC5E06000E5CA4C7CBC5B2B481290000003896C3B090968A4D1E0E083A8DD0EDDACBCEBB792A0000439AC6CED5CDCAA8520000001C7FB7C4C2C2C9BD963B000000357BA6AAA6A061220C144994A6B2A49DA4A9AE9B602508041E5B98C1CAA8836037260C00000086CBFFFFFDC884635B586291D5FEF2CF98725B332B1E3F72B3DDD9B27C4A25161F33569DDDEFD8A764363425272D2A3769AFD9F0EBDB9F5325171F1C3F7DCBFF98725B332B1E3F7201FEF55D070718507068686C6B696D7478797F9695816F7FBFF9FFFFFCDC935023222C5494CAE6E0D3CFBA73331B3579C3CBD5CDC0C08F2B00002C76B7D6DBD6C9A2550F001371A4C9C8C2BBA374240000003692C0C09A9D893F120D0F3197DCDFCFCBC9B3721E000053A7D1DBCBCAC4AA5B0000001C87C5CBD2D5C3B3923C0000003682A6A7AA8F582309124E8FADB5A7999EABB5985F270F07215B98C7C6A9875F35190602000087CFFFFFFFD38663645B5D96EBFFFFDC924F4C38363D4869B6E3E8C37D482A2221345AA8E3EFDA95582C23232733303B73B7DFEFEFD7964F29272A34457EC2FE924F4C38363D486901FEF65D07071860695E5D69656C747D8171778F907C767DB8F4FFFFFDD88C503230455C95CEDBE3DDDAB66E2B1D3775BBD0CDCFC0C28A2C00002B7AB5D1DADACEA5450000156EB8C8C6B7B6AB782200000243A3C9B1A39B773B100C103D8DD1E2CBCACDB96B18000054AACDD0D2D0BAB664000000218FBDC8C9CDCBBC963A0000003A84A3A7A58F5824001C51A2B9BEA58E98A4A789542A09032860A7BFC5B3865B35120A0200008AD6FFFFFCC07D58645A7596DEFFF6CA845A54312F435174B8DDDBB47A48261B29385CAFE4F8CA92542A251926252A3A6CB5DFE8F1DD9154382E35353F80C5FF845A54312F43517401FEF75D07071870736D6F7C706B797A837A80A0987C6D86BCFEFFFFF9DC8F4B29283B61A1CDE2DCD6D8AC5D281A4288C4CFCDCED0C4893100002C7CB1D2D2D7CE9D450000156DA9CDC9BDC1AD771C00000A469FC1B79F9C68370B07003290D1E3CFCCCEB8621B000058A4C9D2D0D5CCB5540000002794C8D0D1C9C0C5A23C0000004197AFAAA69E5F1D05115494B1AF9D8E97A7AA8D522601002E6E93BCBEA7845C230E070C000096E6FFFFF8BB76565E5E548BDBFEF9C3865E48352F3D4672BBE4D9A86E412320324165A7E3ECD295522D281D2928293065B0DAEDECDDA25832262F314E8ADAFF865E48352F3D467201FEF85D07071880716C6069656D6E757D728698A38B7987C7F7FFFAEECA784423263F6699D4E3D1D6DAB567311F4289BBD6D2C5C2CA872800002588B0D1CFD2CE943C00001374B3BDC7CABCAB741600000E4A8FBFC2AE9E7932090A003490CEDDC7CACAA96417000970BBCECBCFC2C9AD5C0000002C90CED3CFB9BEB99D3E0000003F8BAEB5AEA1652300144A98AAB09F8997ACAA86452912092B5F99BEC3AB7E59240605040A0097E2FFFFFFC77B5753516599DDFFF5C08361422C2F3C4F78CDF0E3B16C3E2120263F72B7EBF1CC865124271B202B2E366FB9D8E3F0D99958322722304F95DFFF8361422C2F3C4F7801FEF95D070718907A6E6C726E7883908A82939F9B8E7D97C8FBFFFDEDC37F4B2C28415FA4D7E0C7C8CDA453251B3A88C5D4CCC2C3BF8B2F00013085BFC6D5D0CD9F4308001E7CB4CCC2C3B7A36D16000018489ABDB1AA9D72270100083492D9E7C7CED2A25315000769B6D2D1C9C5C2A253000000369BCAC8CBBBBBB197440000104693AEB2B0A76A1A0114539DB1B09A878D9EA9914B27150C366D9EB4C4A57D512306000200008AE7FFFFF5B97447564E4E84D4FDF3B7784C433431425987CAE6D7A6623C16272B4472C0E9ECC48042272B23262D2D426DB7D4D9EAD7905B2B2934385397D5FF784C43343142598701FEFA5D070718A07A716D716E767F8C9E8EA1B4B28E7793C9FCFFFFDEAF7745292F426DB2E3E4C7D1D5A5582A214595CBD1BDC4BCC48C3402003991BBC8C8D5D09C3F03001C7AB1C9C8BCB6A66B1000001C54A3C0B7AD9267240000002A8BDAE5D1C9D19B510800076ABBD2CDCDC8CCB05900000035A5CAD3C1B6CDC3983E0000024491A7B7ACA0671E06205C9DACB6977F97B0B08F512E18092F6A95ADC0AD7C461A02000A0A0097D9FFFFFAB5714F4B525486DBFFF7BC7652462E2B3A5C88D6F7DCA4633B252227457AC2EBEFBE7C4D2A28272822273477AFCFD7E1CF91552F29363A5998E1FF7652462E2B3A5C8801FEFB5D070718B07C71686F76788793968D9DB6B3927792CCFFF9EDD3A5633924324470B2E4E4D5D8C99C5020204B9BC2C9C3BAC1BE8D330200378FC4D2D1CECCA03900032B7CBFC0BCBAB59E5A1400001C51A2C3C2B99D5C1D0000022F92DCE1C9D0C89C4D08000B6DBAD5C4C6C9C7AF4C0000003F9ED5C3C3C1BACA97410000075391B0B5AB9E5B1B071B66A9BCBB9375819CA87D4C2C1C0D3D719DB1AFA37F4816000013080096E2FFFFF9B473524E525597E7FFF1B77849342C29436192DBFBDFA75F3C1E222F517CBEECE6C889402A23222A28313D81C3D9DCDBCB8E5D382F2B3554A1E5FF7849342C2943619201FEFC5D070718C073726D77737983969A9495BBB8907C98D3F3FFE5CC9F684B2629497CB6E1DFC6CDC89253211C4B9CC6D2CBC0D2C07C28000B4290C7CAC6D2C4914608002780B5C1C2BAB3AA650C00001C61A0C3BFBAA4521000000A3085D9EED6D1CF9B4007000C7BD0DFD8CDC4C9B456000000449DBAC7B7BBBBAF93300000095A9EB5B0B6A2681B0420689EB9BC978990ACAF864A23110F32729EB1B4A67D441100030C0C0093DCFFFFE7A6694945464C87D3FCF6B270402C252A435D8AD6F9D897582F1B21305483C5ECEFCE7E3D25231A27272C4A82BBD0D0E5D08D584133374255A1E3FF70402C252A435D8A01FEFD5D070718D07E72787B7E7D87A1AB9BA5CAC7A57D91CBFDFFF0CD9568432F35527AC0EFEFC9C2C5914C1B234B96BDCFBCB7C2B4792C01084499C3CBCED3C9903805083784B3BCC1BBB7A2600400001D69AABEB4C0AB5D17000008328CD4E7CDD4CAA23C03000A71C7D1C5C7CFC9AD520000004198CFCEC8BDBBBB963B0000125DA3B2BAB79B67240B1D719EB3B0957E84A9A27A4D2E21133D7E9CAAB9A17C4219050105050092E1FFFFE1A8624348455590E5FFF1B26E4B3B3230445490E2FCDE9A612E2425315086C3F1E9B8743F2F1D1D30252D3D7EB6C9D4EBCB8357423138475FABE7FF6E4B3B323044549001FEFE5D070718E06D6F6476717889A9AC99A3C7C79D7C8ECDF6F3E2C38D6549393A5185CCF5E3C5C3C18C421C1D4C97CBD7C0B2C2C17B2E0B074296C9CCCAC2BD893500043792C9D0C1C0B99D5C0500002871A7C4BDB89551050000073686D7E5D3C8D0923800000D7DBCD2BFC6C7C6A84600000046A8D3CCC7C4C3BE934200001B639BB1BBA693621E081C61A4C2C09C7F8EA6B08B4C3819143E7CA3AEB19F753F0900000B1100A2E8FFFFE79D61434E485895E6FFF1B364363025354C679ED9F2D79F5A2D1D16255191BBECECBC6D3B2D291F27252A3B78B0C8D4E1C77E514035374467A8E7FF64363025354C679E01FEFF5D070718F0787076807B809AAEB2A1A5CCDAA48591D4FEFCE4B5895B493B395889C8ECE2CBCDB97C32161D4791C5D2C5BDC6BD782D06054897C6C9CACEC8902D06113F8DB7CBBAC5BC9D620400072F6DA7C9BBC2974C04000000318BD2EBD9D0C09B330100107FC9CBC4C6C5C6A53F00000056AACDC9C8BFBDB38E3A000019609EB3AFB3A17228031C73A7BAB48C7D88AEAB8153331C184D7AA1A5B1A67C41060000031300A4F5FFFFE5A15F4D42475A9DF1FFF9A65D3E392828476DADE4F9D8A04B271E22345982D0ECF1BC6B2C2427202625254086BBC3D3DDC881564034384E7CBCF1FF5D3E392828476DAD01FE005E070718007E747A827F87A2B4B89CAAD5D6B07E93D0EEEED9B0765C443A4A5896CEEEEEC8C5BA6D3419124B92C3C4C2BABCB9782700083D99C9C9CAD0C4933201124A92C5CBBEB0AC94570300063979A7C5BEC697510B0000002D8CD4F3E3DBC5892A00001379C0C9B7C4D4D2A44500000059ABD3D1BCC4BDB48B3200001E6798B0B3B1A36B27042F6C9EB9B6988898A29E7757392516477FA0ABAE9C7B3D0C0000050F00AAF8FFFFE8946849444B5E96F2FFFAAD6B332A1A3141619EE2F0DDA05F372A2938538ED1F3E8B16D382D23262621283B85BCC2D4D7CA794E3837354974BEEDFF6B332A1A3141619E01FE015E070718107B75767C798AAAC9C3ACB7D5CFAE8591D0F6F6E5B4845B403B48609ED4E4DBC2BFB3631C12184C9ABFC6BDB6BAAE6D27101847A3CFD2D3CDC88931080D4893C0CCCFB8B49D5600000A3F7AB3C2C9CD9445080000033983CCDADBD8C28D230000128CBBCABFD0CEC8A6380000005CA7CBC4C6BDBFB58B3500001F74A7B6BFB7A86617001D6DA4B9B8A2868D9B9E7B583D21255482A5AAA097753B0000000B1400A8F6FFFFD68C59343536539EEFFFF4AB623E312B2B3F67A6E8F4D79859341F18355E8EC9E7EDB96F3A291F212A2621387BB2BDD0D9CA74463838344871C0F6FF623E312B2B3F67A601FE025E07071820746B73817E8CA0C0CDA6BDDDD3A37D8EC9F5F1CDA07054443A405E99E1EAEBC4C4AB5920071A54A2C1C8B1B7C4AE681C020B4CA0CED1CBCFBC842B001B5C9DC3C4BCB3B79A4701000A4780A7BFC5C19B45000000003A90D4E8DDDACA822800001981CBC4A7C8CECCA53A00000061B6D4CDC1BEB2B8933800001E6AA4BCB1ACA05D15052B6DA8BAC39E8B8DA9A47E604F29235382A6A2A098672B0000000F1300B3FBFFFFDD8E4F47464D66A7F2FFEDA65B332927284261A6EAFFDD9E673C27272F608ECEEDDAA2552C2218252B2B2B4C87AEB9C4D8C5794F4033314A72BEFAFF5B332927284261A601FE035E07071830787D7784878EABC6C2B2BDE1E6BC87A3D3F3F1D09C69584E3B4466A1D7F1EBD6C4A34D16071858A3CBD2BCB5BBAA5E20000C4895BFCBD8C7C28B3A08215F9EBAC4C0B6AB904E0000154887B3C2BDBE8D39000000054098CDEFDFD5BF7D1B00001685BCC5BACAD2C9A94100000067B3CBCABDC4B9B68932000022699FA9B1B5965C1211306EA9BAB49B8691AB9F7D62512128698EA3A6AE997330000000121900ABF5FFECBE6F4B38333B5BA4F2FFEE9F5E33251C243668B8E3F4D09A6037241F385C8AC5E7EDBC602C301A2F3023254582B3B9C4D4C178453331364E77C9F4FF5E33251C243668B801FE045E07071840696E73798195A8CCCCB5BEE8E0A28295D0F2E2C58B61494D484F6CA0DAEAEDD7CB9C4E0B0017519AC3C8B9B1C2B56024091A4C99BEC6C8C7BA7E2C082465A8C2C2C3BEB9964900000D4484BAC1C2B38C4605000003338BD5E6E6E1BF701B00001F8ACCC7AFC2CDCC9A3700000067B6C7C5C3B8B4B0852A0000276FB0B5BFB2A466290530749FBDBE9F8A8DA5A274614B2C28669AA4A7A09A7426000000161A00C0F3FFF7C47F4B3A3D3B5AA7F1FFE6A55F2C261B28406BAEE7F8DA9C5F3E2D24375C86C5EDDDAA612E3C2926312E20357CAEABBBCAB77643312F404B78C4FEFF5F2C261B28406BAE01FE055E07071850777B7D8E8D9FBEDFD6BBC8E9DDAB799AD4F4F5DB9E5D5453464470A9D2E3DFD8C29E410B00145FA7C9D3BCB3C6AF521800144C9DC9D4D0C8B0722C092873B3C5C6C7B7AB8F3E0000165291C0C9C1AE8D4701000008388BCEE4EAE8BF6C1200002186CBC4B4C2CEC8963400000060B3C4C6C5C3BDB48B2E00002A74A8BCB3AFA4631E003078AAB9AEA79599A8A1746756352E7095A3A2998972270000000F0F00B3F6FFFDBF74453538355AADF9FFF3B25B302B2B2E3063B5F0FBD9A77347291B30628BCCEDD7A5562C322C323223193B7A9AA4B5CEC6764532363B4873CFFFFF5B302B2B2E3063B501FE065E070718607A88828A8FA1C3ECE5C4D1EFE1B68A9EDFFFFFD78D635B63555877B6DEE4E8D3C28A340C061C5BA4CAC0B6B5C4994F1201174B90C5D3CEC6B8802F05237AB4B7B9BDB8B195410000165791BABCB6BF9649000000004195D5E0E8E1BF6A1700002191C9BCB5C6CCC98C3000000674BBCAC1C2BBBAAF7C2B00002983B1B1BCB29D6117011E73ADC0B99D979FAA9F7960602C2E749FA5A19C94671F0000000F2000B4F9FFF5B36C4D3238365BB1F4FFEAA65B302D30273461B8F0FFE3A968452822344F86C2E6E0AC5B233628353020253679A0A2B5C9C0713F2D3534497BC8F4FF5B302D30273461B801FE075E0707187080807C899499C1E6DDC2CEF5DDB38A93C6EFEECE8C5A5057535074AFDBEAE8DFBD892900001958A1C5C9C0BABDA6521E0D154998C8CCD6D4BD7A29073175A5B4C8C4BBAB8839000022639BB4C0BCC0973B00000000388FCBE2F3D9B85F1800002186BCCABCC7CDC2822E00000268C0C3C0BFBBB5AB7D2A00002D7DB0BBBCB0A7611900337EAAAFB09A9C9AA49D6F676034336F98A7A29A826B30000000121C00BBF7FDEBAA623B3127315EB4F1FFE697532925292D396DB9ECFADDA465423521355784BEE0D1A357272F2035392725418C9EA1ABC6B36E45382A2F4C7BC8FBFF532925292D396DB901FE085E07071880757E888F95A1CAFBEBCBD8EFDFB68394CBF6EFCC8B6061614F557CB2D6E6E5D8BE7C200000135AA8D1D0B9B4BD9B4A150A1B4C93BBCDCDD0AD741E08287BB7C5C3C1BEA88E3F00001A60A1C1B7B1AA8D3A0000000441A1D4EDE4E5AF51080000158CCFC0BBC7CCC3801C00000276B0CEC8BCB5B8AC72240000337DA8B4A7A6985D1C0D2B7CACBAB5A097A0AEA27E7264343776919499A49163200000000F1A00B4E3F4D1944B24202A3256B4FDFFE5A2512E2F1F242669C1F1F2DAA76A4E311929497FC8E4D7A54F24341A39341C203D859695B6C2AE6D39353830497AC8F9FF512E2F1F242669C101FE095E070718907A817C8992A8CBF2F2D0E2FAEBAD8098CEE8DFC981545E715E5E83BCDEDFE4D5B175190000125A9BC0C3BDB9C4A34713061F448BC0D2DDD2BE7420082D83AFBBBDBFB2AC86380000186B9ABFB4BEBD8F430000000A499BCFE3E8D7B44C090000349CC5CCC0BFCECC87260000027ABBCBC8CAC6AEA76D1E00003477A4AAA7AC9B521B042B78ADBCB2A498A3AD9F7172632D39809DA2A0A58D671B000000121B00ADE7FFDF9543151529275DB1F0FFEA9851232A26223772B8E4F7D9A5794F3120364B81C9E5DDA54A243A20262E221D3A7CA299B0CCB66E43353239537AC7FEFF51232A26223772B801FE0A5E070718A06A6A7B808FA2D0F7F1CCEDFFE5AB839CC9E5EAC97D5D5D6F606484B7D8DFDED9B671160000145C9DC6D2B6B8B792441806184A93C7D9CFD2B76A1F053590B8BABEC8B9AC742B00001D6EA3B6BDB7BA91450000000B4DA1D2EFE2D5A9560000003A96C3C9C2C9CDC780200000006BB0D0CEB8B3BBAA702800002D76A5AEA59D925F1F0D377DA9B2B19C9AA7A5A06C786C3A3672939D9E918A6A1E000000152104B8EEF1D78E391814222155AFF0FCE093472B291D263568BCFEFFE2A077502A202B4A81C0E1D59A4D214823292D201F3F84979AAEC3B666382C2C344177CFF8FF472B291D263568BC01FE0B5E070718B07272788B8EA1CBF5EAD1DEF7E8AA8698C0EBE1C0784D5C86756479ADDADAD5C7B5731E00001C56A3C3C4BBB6C2923F0F0D274C9CC3D1CFCCAA5F15083987B0B1C2C5B3A7732400002475A2BEBCAEB19B430200000D58A3DAE8E1D2A0450700003E9DD3D1CBC9CAB4721500000C80B8D1C6B5ACB1A76E1600002E7D9AA6A7A0975E19033484AAACACA9A3A7B19D6F7164423A819F999F9F8A5F1C000000161300B3E7F1D19241261F232E62BAF0FFDBA04C2B251A1E2B6BB6EFF5D2A46F532922395780C3DFD598490F4022302E22234D8E907CA2C3B2642D3435394E75CCFDFF4C2B251A1E2B6BB601FE0C5E070718C07C797C8790B6DDFFF7D7F0FFE4A98DA0BFE5DAB7754E677D6B6287BEE0E9DACFB8731100002060AECAC9BAB7B68D3A0C091F5C9DC5DACBC7AD5B18064393BBBBBDC1BAA46D2100002779A8B6AEB0B2953E000000115CA8D1DBD8D4A54B0800004096C5C8C5CFCEBE791E00000E7BBED4C8C0ADAFAB681800002F7CA6A5AA9C946019072B7AAEB6B7A2A8A8AF9D7D7A7343437FA1A29B998E600F000000141C00B2E7E7BF732F12181E1F53B9F7FFDB97481E201A1D326CC0F1F8D7AA815132222A507FC0E2D38F461D432630392526377E8C86A1BCA4663A2F2A2E4181CFFFFF481E201A1D326CC001FE0D5E070718D0796F7A8F9EA9CCFFFFE8F4FBDEA7869DCEE7E6B571527D9280708AB8CDDDD5C0AC640000001C5A97BBC1C0B2AD84350C0B2F5B9DCDCFD1CAA85A0F083F8AB4B7BDCAB49E5F1C0000267FB1C3BFC1B6903D0000001060B0D6ECDFD7A4390300014EA1C7CDBBC3C7BF6D1100001681B7C2C0B5B1A69C691000002E80A2AAADA49D5F1D0C2E78A2ADB1B0ABA9B19E757165373E7E909EA599945B1E000000192400A7D9D5BA67280E1419235DADF0FFD98E451E261F232D6DBDF7F6DBA273512D1D274587C9D9CC98431B4B23232D181B49898F7FA5BFA369422E39364671CEFAFF451E261F232D6DBD01FE0E5E070718E07F8786A0A6BDECFFFFEDFFFFECAF8EA5C7DFD5B3725B6F8C7C819DC0D4E5D0C7B26A0E000012579DB8C1C4BAB5883F191A305797C6D1C5CEB35709034095BEBCC3C9B694571600002C7BAFC1C2B7AB94380000001961B2D8E1DACF974101000B5BA7C9CFBFC9C4BA63040000188DC1CBC4C4B9B19D59200000347A9DBEA69D8C461A08367AA6B8AFAEA7ACA195716C653948789B9A9AA0905F15000001181700B7D8DCB0671B0E101B2467C2F7FED993431F271F222E75BEF2F1CAAA7A4D28191F4B7FC9E2CC974C174E2D232717174080847CA4BEA662373B37364677D0FFFF431F271F222E75BE01FE0F5E070718F0798185979FBAD3FEFFE9F2FFE7AB97ACCFE3CB9E6C57708B847993C0D9CFD3CFB45F0500001B669FC0C6C2B5B8873B141E3B5C92BACECABB974A0F0E4C91B3A8AFBDBA945C1800002D85B3C0BFB7B79B410000002069B4DFE3DCCA923E07001267AFCCC7BEC8C3B361070000137FBBC5C2BEB7A98F4D0F000035819DA6AE9F87531A0333769FB7B7A3AFB8AA95787B6D3B478991949CA98F5713000002201A00A9C5CDA85D200300081968B3F6F6DA8F3F262617112F77BBF0EFD1A87A502A1A2A477CC4E7D08F40134F2A292C1A1E41857A75A1B49E623E2E2F3B466ED3FBFF3F262617112F77BB01FE105E0707180080808696A4B2D4F7F4E7FFFFE5AA96ADC4CFCCAA684F74908E8092C4D2D5CDBBA75C0400001859A2C0CAC3BDBC863E181D3C5F9BC4CBCDC593400B074C9AB5A6ADC4B9984A120000347CB4C2CCBFB89E4B0000001D6BB0D8E2EAC8894213000B5FB0C5CAC6CAC4AD530000001484C7CEC9BBB2AC964F1700033A809BA7A09B804218043575A3BCB5B2BBABA08D6D735D3C3F85999CA2A19861120000051B1D00A9CACEA24E1100000F1E68B7E4F2D17F371A1718183478BFECE8C5947B4F1F172F4482C5D9C58A321157262925162246808476A0AD9E583D3336424A89D5FFFB371A1718183478BF01FE115E070718107176838D9DB5D6FEF4E6FFFFE4AB95A8C7D3C79A5E4F708F897E9EC2E4D7D2CAA6620200001A5CA1B8BBB3ACB1872C0F1B40649EC4C9C6C2A3490A0D4A96ADA1B0BEBFA03D000000308AC5D0CAC1BD973F0000002370B5D3DCDBD490310000186EAFD1DACACBC8A6500000001A7EB8D3C7B4A9A9944C0C0000387F9DA8A48F8C4A12092E74A2B6B7AEB5B5AE96757766474E818F9EA7A8925E15000001141D00A0C1BD9948060000001E62B6E5EDCA7638181B10183376C8E9E0C5A47745301A234581CBE3C790400C68281D1E1016428881739AB1915C3F34313F4D7FCCF9F638181B10183376C801FE125E07071820818A8E9EA3C7E4FFFFF9FFFFDCB39CABC4D5C799644C75968C7FA1C4D3D9D1C6AF5E000000125CA0BCC4C5B9AC782D112053709BBAC1C7C09C4406135692B3A0B1C1B588310200003888C5C7C8C0C39B3A0000032177B9D3DFDAC1823B00001E68B2D4D7CBCDC8AC530000001B88C1CDC0B1B4AB8D541100043C7E9D9F949C824509002A75A3B6B7ADB0B1A48D7C806D3859889291A3AEA05D140000000F1800A3BBAF883E000000081D6DB5E8E8C27B2E0C15090F2B81CAE9DEBD9F78462714224787CAE4CE8D3E0D6021201A12174D888379989C855A3A3631333C7BD3FEF82E0C15090F2B81CA01FE135E07071830808394A2AAC3DFFFF8F3FFFBDEA9A3BAD1DECD9C5848769F9495A9CFD8CAC5C2AD570000001C6CA0B8BAC0B8B3762B0C23536E9EBDCDCFBC954200034B97AB9EB1B6BC7E370000003B8DC7D2CAC1B7964A0000002A79BFD4DCE2CC872F02001F75B9C9CAC7C2C29F510000001881BEC5C4B8ADA2873F070000397D9DAF9A9C864B1B022F72A9C0BAADBAADAE947075744D5B818E979F9E8D6316000007190C008FADA57929000000001D68B3D9DBB8682D0F140C0E2D80C5EAE0C39D6C411E0F254488C2DED1984512631F202012164A83827393A48450333E3B324680D6FFF32D0F140C0E2D80C501FE145E0707184070767E8FAAC5E1F5E5EBFDF9CDAEA2BBD6DBBD94534874A59C93A2C4D9DCC5C0A256000000195F9EB6B6B6BEAF8033122E5D83ACBEC5B8B88A360405519EA8939EB8BB802B0000003C91BECECAC4B795400500063485C4D9E1D5C6892F05002381C1D0C8C9C3CA98400000002289B6BDC1C2AEAC83440F0003447A9BA3A193813D05072B609CB7C0B3B5BBA37E647769455E8A8A86A0B39E601F000008211D009AACA8752E000000001D5EB3DBD2B66625141300002F78C5EFE5C4926541241D264B89C8DECD8E43167732171E131C57756D698D9F8652383A3B394D8FD9FFF525141300002F78C501FE155E070718506C75879AACC2E1EBE8E7FBF9D9ADA5C5CDD4B989594D75A09B9CB2D3D2D4C5C2A65A0000001E6AA2B7BFC3C8A86D280A2E637EA0B6BFC0B07C2E00044591A597A0BAB376250000003795C3CCCAC9B8954102000A3D89C3E0E1E2C9873205002079B6CCC9CCCFC59E38000000198BBECCBDBFB7AF89490E00003D789AA4A392813E0C022B6595BBBBBAB5B3A094767B6242609090909DAD9762110000071412008BA09C6420000000001568B4D2CEAE6521000C080D3A88CFDEE1C1926743180E21508CC7DFD1913A10842D1E0F011D4E85776C90A2724D363F39374583CEF1F021000C080D3A88CF01FE165E070718607888939FABCFE4FBE3EDFCF7CAB1ACC0D5DCBB874F4C7DAC9A8FA5CFD9D4C8BAA95C0000001C6CA0B8AEB9B9B56F2918326B7EA9BAB9BAB57B26050A4B9BAB9498B0AF741C000000459EC7D2D7C7BF9238000005368AC2E1E2DFC884340A002E86B5CBD4C7C2B88C38000000208FC0BAC3BBB2A583440B0004407D9BA69A90723A0E052D6EA7BAB6A8B9B7A79766746647598C8F87A1AB9D671700000D190F008E9D985F0D000000001B6EB3D3D0A05B23070100113D84C7E8DABA966A3619121F4C82BDDFCE96420F7625140B0D1D5289726995A2774C3C3C42424C87DBFEEA23070100113D84C701FE175E0707187080908FA6BAC7E0ECDEE3F2F3CAB6B8CEE1D2BE80504F80A5ACA9A7C7D0D7CEBCA14F0000002775B2B8B0B4B8AD642C15286A90A5BBC3B7B67C25000E508EA58498BAAF6F170000003B9DC0D9D6CDBC953D00000C3F85C3E6E3DBC0803100002688C6C8CBCDC2BC97340000002F85BEC5BCBCB5A5803B07000B4D80A49B9199733006002A7AA0B7BFBEBBB4A78467766047688888859EAA9C572100000A1C1000949A905F11000000001A75BCDED2A75F1F0000010B3B89C6E1D6B7895B37180723518ECAD8D1924416822711130B225E8673648E91643D333D3C3F508ED3F5E81F0000010B3B89C601FE185E07071880708A8B9FC3DDE9E4DEDAF6E9BEA6C0DCDFDDC27F4E5280AAABA5B3CDD3CECDB89F520000001D77A4B3B5B7BAB16B1D15376D9BAAADC4BAB77B1F00054E98AB989EADAC6F0C000000479ECCD7D1CAB59E4001000B408CBDD7D6D6C77E2E00002D94C9D3CDBBBEB695380000003090BFC0B1B2B6A982360C00014B7C9CA4A398742B050328639BB9C8BBC1B5A58E626A5E486B8C868096AD995B190300101E1A008A92874C04000000001C68A9CBC399521900000009448DC6DAD3B0825D270E0C23488FC9D5C38E37087E29110A1B2460917D74978F5D422B3F323E548EE4FFEE1900000009448DC601FE195E07071890737F97ACBFE1DEDDD6D5F5E0C2B9C2D6E8D9C67E473C78A2B1A7BCC5D1CFC3C9A8530000002674A7B4B6B8B9AA611E11377E9AA7AFB5B8B06E1500054C9FAD8BA4B6AB620A0000003EA2C9E1DDCDBF973A0000114490C8EAEADAC07A3400002D8DCBC6D3CDC3B8842F0000003398C0C5B6B9A9A7763A0F000D3A7CA5ADA8A1792C0000195999C2C0BABBB0A590656C624F7A947E869DB6985C1C03000C1513008982784A00000000002371B2C3BD945509000000064494C9DAD2AF865322130F18419DCDDBC6903E138D29170F041C6889776F8B90663C313C3D395297E0EAE209000000064494C901FE1A5E070718A07A8D9EB0C5DEE9DBD4D8EEDCBFB5BEDFE1E2C07E4140739CA8AEC3D7D9C9BEC5A3560000002F68ADB6BDBCBAA45D1C0B3D7A9EB5B7B9A8AD7721000A4B93AC899BB7A46C02000000449DCED6CDCAC0953300000F4E95D1E1E8DABF742F03003593BDC9CAC3C2B881310000003B8AC0C5B3C1AAA16D300400014D84A9B5AFA1712C00001C60A1C1C3BBB5B6AC8766604C3D75958A8AA9B2A05A18060F10181100868F80460100000002337BADC4BA914A1300000007438DCFE6CAA677552811101F4B95CBD8C98E440F8F320D100225658E817598825C402E3738324B97E6F3D81300000007438DCF01FE1B5E070718B0768396ADC2E3E3D1BFCDE5D6BEBDD5F0EDDCC0713C3D7AAAA7B7BEC9CEC9C8C2A74D00000038739ABDAEB9C0A34E141142879FAFB0B2BBB66A2000084A9CAE97A2BBA469070000014893C3D6D3C7BA8F3400001B5190C2D2DFE2C7782803004496C8C2CFBFABB582270000003A92CBB9AAB6AD9C681F000002497FACB3A99F772F020626569EC3BFB7BEAF9C7B61625256819B7E7FA7B19E5F260E151E2312007382683200000000002768A3C0B990510D00000007408FC4D8CB9F72492615151C4C92CBD6C18B35108A350B0D1934738F77718E885C38324F373859A0E2F6D20D00000007408FC401FE1C5E070718C073829FB1CDEAEED9C4C8DDCEBEC0D6E1EAE0B3713F4279ABAFB4BFD0CDCDCEC2985400000024729EB9BBBAB6994C07083D89B1B0AFBCB5B57721000D5B9EB38E9DBAB060060000003D98C3D4C8C6BE872D000017579FC9D8D7D4BA672902004198BAC9D3D4C7BA79160000003F92BBC1BBB9AEA5642E0200045078A4BABEA979250000114C8FBDCDBDC5B8A87E5857545078908288AEC3A66C2A080A142114007877612900000001002A73ACC8B7814901000000074994C4CFBD9B6E4F21130D1F448CCAD6C08D490F923C170D0528688F797A95784D3628373D455C9EE4F0D901000000074994C401FE1D5E070718D07E8798B5C7E4E6C7BAB6D2C2B4C4D9EBE9D1B060373C6792B5B8C9CCD6CAC0BEA14B0000002872AEBCC2B8B19B4D111A468EB1BAA6A7AEA75A12000B579BAF99A1B9A7580000000049A8CFD1DAD2BF7C2F00001E5A9EC7CDD3DDC4762B07064E9CBBCFD3C7BCAB7115000000429BBFBBB2BCBAA46B2D0100024384A3B2B7AE712300001B4E92BCB7B2B8B0A27C585044517E918D8A9DBBA45726151A182013007E82623000000000002F78AEB5B37F3E00000000074794C5DBBE916B411C180C1A4295CEE0D19946138F2F0A0B0625769D888794744E3731403736549BE2EBC800000000074794C501FE1E5E070718E07689A4BFD7F2E4C6B2BFD3BEB7CBE6F6F5E6B46230336393BCC2C8DBD5D6CBC19C490000002567A9ABA3A9B89C4F14114492B9B9AFB8BAB26412001161A7B3979CB1AA5D00000000479FC1D6D0CDC38D2D00001C64A5CADBD3CAAB6F2506094B9DBCCBCDC4C3B9751900000049A4C3B7AEBAAD975C160000124988AEB7B09E69240000135596C4C2BCC3BCAD8357534B578397838E9DAD995F201A1E261500007F7E622900000000002A86A7BCAD82480B0000000E5397CCDBC19C6E341917091A489DDCD9C28943139033241A0A37809E84878E7B4F392A3C323B5EA8E2EAC00B0000000E5397CC01FE1F5E070718F06C8193BCD5EEDFB5A2B4C3BDACD0E4E8E9E5B15430305F91B5B7C0D8D3C6C4C5A3490000002F74A6B4B4BCB3913A0E0F3C8DA8A8A6B4B2B55A15001769A7B69FACC1AC590000000045A0CFDCD4C8B27B1D00001C68A0BAD5DFD2B26C24000754A9BBC6C8C0C3B16C0E00000047A1BFB6ACBCB89C5C280200175E95ADB2B7B074130000234E97BFC4C5BFC09A7D4E474053859F8182A0B6AD6B322220171403007B80612100000005003481B3BDA47E4101000000125396C3CFBE89633A130301144D99D4E2C1904D149A340706002B75A0888A8E744C322941363663AEF0EAC401000000125396C301FE205E07071800738DA4C1DEF3D8BCA5ABBDB3B0CCDAEBE8E3B25D313A6395AFB3C5CFD3CCCDC19C4E0000003A7FAFB3B8BCB99441090E4C95B3BFA7ACB8AB5A0D00146BADAFA3AEC2A453000000024FA4D3DAD6CAB7751D00002768A7CEDDD9D1AE6222050B4A8FC2D0D6C2C4AD6E180000044AA4BDB5ACB9AB904E1D0000155786ACBEBAA9751D000009579FB6BFBDC3B6A48055493B5586A1948BA5BBA0612F1D2522200B0081785D230000000000307FA6B7A77B3C00000000094F9DCBCAB598612F14000F1B52A0CEDFC685380B9A2B0908143880A498958D724D282B3E3A3A5EB5EFEBBA00000000094F9DCB01FE215E070718107387ACD2E1FCECB7A7A5A4A2B0DAF0F1EFE1AF59292B5795B5BCCED3D9CDC2BB98430000003286B4BCB5B4A8863A050C4699BFB7A2ACB89A5D1C001C6FA8B4A6B1B79C460000000252A5CFD2CECCC67B1E0000216EB2C8D6D6CCAE641B030E56A2C4D2CBBFC1B560090000095698BFC1AEA7A690521700000E589AB2C4C6A975210000155592BDC2B3B9BCA7784E40415F929E96879EB9A7603B2D2E23150200897B681B0000040B014A7FA6B9A8843E02000000135299CED0AD8A602D140606184F9AD9CEBC9045149D3E0A0C0A358AAC95949579432F2E43383E64B5E5E3B302000000135299CE01FE225E070718206A7EA2C9D8FADDA8908EA59AB3DDEEEDE7DFAA4D262A558BBEC3CFDED7D4C3C193420000003980B3BAB2BAA3782B01084494BCC1A2A0AF9D5C1A001C6EB0B8ABBBBA9D4C0000001064AED6DDD4C9B86C1D0000266DABC7DFD8D1A7603217114FA3C3CAC9C1C7B4631200000C5BA1B3B4AFB6B89244160000126B9DBDB7B9AF72180000105594BEBCAEB8B8A676473C3A5C8F9C9A93A4B9A45E3A2937311702007C71490800000000033B7FAEB4A57D3800000000145DA0CBC2A9835A30150C141F4F9DCDD8BA8A3E1DA238100B0E3586B09A918C7351262438373E70BEECE6B200000000145DA0CB01FE235E070718307592B5CAF1FFEAAE97A2A5A3BBDDF3ECE3DFA95321285B8FBCC5C5D7C9C5C7C7A2450000083F89ACB2BAB4A97A2806134A9FC3C5A0ADB6B05B14001870AEC2B3BCB9943C0000001564ADCFCDD3C7B2691100002878AFC7D5D9CEA45614040958A0BFC6C8BFBFA9590C00001266A7C0AEA4B1B39554130000185C9AAABDC4B4731600000F559EBEBFBBBDC4B4724731395C90A38F93B1B6AC60413F3D311B0200746A511000000000003E7EA7B79C7833000000001867A7CEC69F755C39160811164F9AC9D7B6804214A13A17060C4089AF9E9290734A212743353674C1E3E7AD000000001867A7CE01FE245E07071840718EAFD7EBFAE2A690899E98AFEAF2EDE6D8A1551B1A4582B6C9D0D3D7CECCC899400000043C91AFC1B8B5A9752900135298BFB3A09CB9B65E0C002881B2BDBCC1C0A247000000155FAAD4C9C6C3AC6B1200002774B0C5DCDACC9D5B1F071668B3C4C8C4BCC0A6570000001B62A8C2BBA7B3B190460D00001B6B9EB9B8B4AB691400000F599FC7C1B3BEBBA7724839315C95A99E92ADC3A56A484045332001007F714A0400000000024189AEB89E773E0000000015679ACECCAB735632160C1322529FC6CCAD7D330C9D38130F18448FB5A292816E41292136374A7DC5F3E7A80000000015679ACE01FE255E07071850708AAED3F5FFCFA58C8F9097B1E9F4EADCD49D4D212B4E89B5CED4E2D6C3BCB6963E0000084E96BCB8B2B09E69260710579EC0B4A4A1B5AD6116002C7EB5C4C1BEBB973C0000001364A6C6CDC7CCA55C0500002D7BB5D8DAD9C69E4B2009105AAFBDC2BFB3B6A5550000003672B2C1C0ADB7B58F440800001E6B9DB5B4B6AA731E0000205D9EBBC0BDC1BDB0774325396289A79C98A3B9A466564C47331900006C67430000000000003D91ABAFA9792F000000001B6CACD2C69E6D4319090D07225AA6D2CEB078471CA4320E0010429DB7AB98845B2C1C293434428FC8F3E7A2000000001B6CACD201FE265E070718607FA4CDEEFBFFE0AC9593898CB3DFEBECDFD89A502B274A88BAD1D1D2D0C4C3CA8F3C00000A4A9DC0C4BAB59E661C011852A1BCBCA4ABBEA04E10052482B1BFBCB9BA93420000000F6ABAD5DAC6D0B05F0A00002D73ADCBD8D5CC924C25001066A8C5C3C7BBC4AD560000002572B4C5C1A7AEAB8D320D00001369A6B2BFBEAC6B170000155895B9B5ADC2B9A875352B366CA0AAA19DAFB49C634E5159461B0000776D470000000000084386ABB0966E39000000001E68ADC3BF92684F2613130E1B509DCECAAA7B441DA13F240D1750A3C2A5947B503124273B484E8FD5EFE8A2000000001E68ADC301FE275E070718707293B2CDEEF6D69B7C808289B4E8F1DFD9D7974C1E264683BECEDED6C7BBC4C0862B00001458A6B7B6C0B1935E1100124B97B8BBA7A5B8A95E1507358BB7C1BABDBD9433000000136AADCDD2C2BFA1550400003086B6CECED2C8915020101668A8C8C6D0CBC79D430000002A7EADCEAFA8B5B78D370300001669A2B7C5BAA8661D0001185E9FBEB1B0BAB4AD683A2E3469A1B79F9DB2C0A46B585E53431B0000745E36000000000000448DA6AE9D6837000000002070AFCFC1966041210C1111195CA4CEC7A5713C18A83E181C18529EBCB2947D582F262E373D4B8FD3F4E0A6000000002070AFCF01FE285E07071880778FB9DCF5FDC89887808078B8EEF7DFDFDB9F4A1C153E7CB4CFE0DFC9B9B9B5892F00001D5B9FB3AFB3AD976428000F5CA6C7BBA6AAAB9E5714003C82B3C2C2B4B691350000002A6FC0CCC3C0BD9E500400003375B6D1D0CAC38A3F13081E72A8C4C8C9BDBA9D450000003183ABC4BEB8ADAB82350C000014699BB5ADB6A3621000002469A5C2B1ABBEB8AC6F2C253568A0B4A39AB3BDA17061646C4B1E0000706738000000000000468EA7B4986626000000002565AAC8B78E6645270A0A1E2160A7DAD0A1773D09AA3818161A4996C4B59C7B5D331F2A3A464B92D8FEE7A6000000002565AAC801FE295E070718907794C4E2FBFFDE968C847B83B6E8F2D9D6CF9144191C3C7DC4DBEBECCDBBC1C2842C0000145EA5AFB3C3B99B5315001552A0C7BBA6AFBDAF590B0B2E83B9C6BEBFB4912D000000267AB4CFD3C8C79A520400003887C0D2D1CCC07A381A0C1D74B3C7CEC5BBBC9E430000003980BDC1B8A5B1A6813D0700001F719EB7C2BCAA610C00000E5E9CB6AEB8C1BAAA6E352E3B77A5B8ABA7B2AF976C646E60421E0000745E360000000000004292ADB1906421000000002471B4CDB78A5A47280E13191C509ECDBC976E3D1AB84E1D0D114F9AB6AA8F704B35222B3C4858A1DBF7E29D000000002471B4CD01FE2A5E070718A072A0C6E5FDFFCA93827D7D82AAE5F2DDD7C18A491714437DC5DDF0E7C7AAC0AF79250000256DA4B4B7B9B4934F15001658A2B5B39AB4BBA158160F3C86C0C5C5C6C197340000002B82BCD6CECBC19B450000003781B4C9CFD5C27F39180F2376B3D0CEC9BEAA8D3A0000024B8EC4CAB2A1A9AD7E23000000186FABBEC2BB9E5B1E0000256EA9BBAFAFBABBA7652C1B397AA9B0A9A1B1BBA66D74716F541000006D5F38000000000000508CB5B8925522000000002B76B0CBB47F5A3B1A01011A2564ADC3BE9C673917A14515191854A6C2BB94724937232F3F4962ABE1FCE5A0000000002B76B0CB01FE2B5E070718B07199C3D9EFF8CA8D817D787BAEEFFBE2C7C0873712173783C4D7E5DBC2AFBBAF772100002A70ADAFB1BAAE8F4C0900104F9EC7BBB6BBC1A24F100D3C9AB7C2C2BFB78C300000003B94B8CFCBCBC68A3E0200003685B8C5D4D1BE772E1A0F247CB5CCD2C8C6C39D3D000009508AB5C2BBA0A7AB7727000000116FA9C0C1BDAE5B0C00001B63AABBB2B5C9C6AF6C26153172A8B8ABABB3B49971778076551400006C5A370000000000004584ACAC875B2C02010000297BB5C5AC7852351C0513121D5CAAD1C692572F21B13E231A1B5AB1D1B58F72492A1E282B3A6AB1DEF9DBA002010000297BB5C501FE2C5E070718C06C9BC3E7FDFEC58F7F746D6CB1EBFADCD2C17C3513143083C1DEE7E9C3B0B9AF6A1D00002A6FB4B6B3C0BD95470A01205499B9B5AFBCBDA7560D0C3D93ACBFBFBBB38F260000003889C1D0C9C1BC8D3A0000003889BAD8D3D4BD752A120B256FB7C6C5CBC2B89E3600000D4F92BBC4C1A4A3A674280000001F6CA7C5C5BCA6561100001F669EB8B1A4AEBEAF5A2D1A4686ACB4A5A7ACB79476707D80591F00006654240000000000004A89A8AA905529060000002E7BAACFB8884A36201111152F6DA7CCC58C562110BD460F111B64AABFB5865B472831333D486CB0E9F8D5A0060000002E7BAACF01FE2D5E070718D0789CC9E1FBFCC289827E7075ADEDFEE1CECD85411917427EC8E2E6E6C9A6BCB3671400003285AFB2AAA8A384470B001359A3C1BCABB2C0A35015124795BCCFCCCAB8832C0000003E8CC0D8D1CEB8812E000000468BB9CFCCCCB574240D062B7BB6C7C2CAB9BB973600000E5293B9C6C4B2B4AD781E0000001C66ACC0BBBDA55D0E00002564AAAEA3B2BEBFB1692E1B417CACBAB3A7BBB49D7B7F7B7C5617000074522E000000000005548FB2AB8E5015000000003787B2BFAA804F361F0F0E0D2A6DAECFB8865C3A15B2451C122064A8C7B2845B3D28252D3C547CB4E7FFD886000000003787B2BF01FE2E5E070718E0719EC6E2ECEFBD7A6E6B6269A4E0F4D6CFBC7B310E0A3484C5E0E5E0C4B5BCB2632100003986BEB7B0B6AB7C411002155C9DC2C5A9B7BBA04D16144895BAC4C3BABD82280000034A92C4CCC3C2B283310000004393C2D4DAD1BF722A07082876B2D0CCD1BAC3992B000012619ABDC3C0A69AB06E210000001B6DA2BCBEB5A7550900002267A7ADA39DBAC2AD63211C458DAFBEB3AFADB4A0808293846212000070552C0000000000005697C3AD8C531F000000003C83C1C7B383483116010B142E70B7CBB584522F1AB43215161D5CB8CBBF835B412E252D375981BDE5F4D88E000000003C83C1C701FE2F5E070718F0768FC0DFF8F7C089716E6477ABD8EDDFCBC1783312153282CED8E5E0C6A5B7AA5F1600004C90BBB4ADB4AE7E3702041D589EC9C5B1B1BD9A50191A5390BDC4C5BEB07B2E00000A58A1BCD5C8C5A97E2E0000003E8DBED1CFD1A360200E08297FB2CFD5CABAB9953A00001E70A5C0C3BFB1A69E651D0000001979ACBDBBBC97520B00002467A1B1A397B5C4AD642616408CB9B7B5B3B6B4957D828D885C2000007258370000000000005795B6B78E5818020C02003582C1D8C1804D34151111232C74AFD0B47548301FB54213151B60B5CAAB784F352B2E35395D7FC8EDFCD993020C02003582C1D8 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 61440 61440 0 01FE305E0707180075A0D7F0F2F8BC8776725F6FA2DCF0D4C8BB742F12183A87C0E6E4E5BCB0C0A9621300004A92BCA8A5B5A673350800165592CAC7BBBDCAA13D0C1051A6C6BDC4BBB1792500000F58A8CCC5C1C6AA761F000000438EBFD2D5CDB65E2601002684BED0CFC5C2B59D3000001A67A4C4C7B8AFA5A166170000001475A8BCB8A899591500022D6EAFA9A39BB3C0A85B1D154388BABEB4AFC0BD997A8A8D916817000079623B0000000000075099BCAB89562907070003398FC0D1B279483720090E192E7FB0CCC27E4D2C0DAC401F1E2B67B0CCB37D4931271F2D3F6391CBEFF5DE9407070003398FC0D101FE315E07071810769FD5EBE8DEB489856D5865A4E0F9DBC8BA7426020F2970C1DDE4E2C2AEB5A25A1500004E91BEB7A4B7A4752E0000115CA4C5C4BBBEC799430F0D509EBFCFBFC0B5802100000C68A9C3D8C9CDAF751A0000004D92BCCBCDCCB45C200B062D83B5C5CED0C1B988240000296CA9B6C1C0ABAB9C5D120000002176A5BDC3B596480F00063576A0A19C91B5C1B75D2016448EBABEABABB6BDA1908B8C8063130000715F2D000000000000579CB3AE854018080700003F8EC6CDB3754932180A1325357FB5D1BF7644271EBC451B172674BFCCB6734C3A2A1A24436B95CFF2F2CC86080700003F8EC6CD01FE325E0707182080B2D9E7F5F4BA8B7D6F636CADE0F6DBCEC0692C0A0B2E7BCEEAF1E9C2A6B39F5A0C00015D97BDAFA3AFA169270000195BA4CED0B8C2BD934716245A9CC2C5BDB8B0771C00000B61ABD1D4D1C5B36D19000000488EC4C9D1CEB35B1D0B0E2B84AFC7CBC9BFB7903200002A71A8B6BFBDAF9F9C690D0000002174AEC7C0BC995016000A3077A89E919CB3BEA35E19184496BBBEB5AAB7BD9C878A958B681A00006B55300000000000005198AFA6804C130004000A408EB9C6B17F47421709181C3578B3D0B16F3C1F15B8441D17276AB6CEA8784A2F2B22263D6D98D7F2F3DA8E0004000A408EB9C601FE335E0707183078A2D1E3EEE7BB7F7D725E6CACE5EEE2C9B16826050D347EC0DBE3E4C7B3BB9B4C02000158A0C6B7ABB89F642300001355A4C0C9C6C8BE99400A1B58A5B9C7C1C8B676170000186CACCACDC1BBAB65120000004EA1C4CBCFD2AC601C140E3385BDC3C8C6B4B37A2D00002C7AA7BCCDBFA6AA995B110000001B79ACC4C1B2994A04000F3879A8A28888ABBEA65D2D244F93B3B9B0B1BABB9B8E939B966F2400006E55290000000000055DA1B9A5753E150002070C4887BCCAA7704432180F1C204286BFC4A4682D1E00AD472D242E70C2CFAC694626292C294071A2CBEBF6D48E0002070C4887BCCA01FE345E070718406AA0D6E0ECE1A37F846F5A68A2E0F2DDC7B26F2C14113280CBE7E8E6C1A5B6A15100000667A3C5BDAFAD90611F00000E4EA2C5C5C1CBC8943A0F185A9DC5C0C7CBAA640F00001775B3CCD2D0BDA966110000004096BDD2D6D0B752190F0A3586C0D6CAC6BCAB832700003286ABC1C3C5ACA1965D0D0000002377A8BBB7B9A1450E000B337CADA3848CB1C2AA53171C579CC4C4B1AFB9B79F8C9F9A98641F0000624820000000000000509BA8A4754112040000094A8BBDC8A4714A301C0E121E3C83B5C9B27B3D1B15AE421C2A316DB7CDAA7335332E27353B74A7DCF3F5CD7A040000094A8BBDC801FE355E070718507A9ECBDBF0E2AE7584736069A2DCF3E3D0BC702702072C73C4D9E6E8BEADB797480300125DA0C5B1ABB298602300001B5AAFD1C0BCC9BF9139041A66A2BED2C7BEB46F0C0000246BB0CCD4CCC4AF6411000000489DC4CED6CCAF57180F0B358BBDC4CACCC2B4842C00073983A8BDC1C0ABAA9255150000002471B1C0BAAD96480C000F37779F97888AA9BAA852222259A4BDBCB1AABCC2B092A496936A2000006E44230000000000005399ADA8763410121600094C90C2D6AF684534170A11234385B7CEA9663A2015AE40181C3176BECDA366352F322B314778B1DAF1E6C28C121600094C90C2D601FE365E070718606E9CC3D4E7D89D797C6652679EDBE4D9C6B163220912347FCFEAF0DDC2ACB28C4400000A65A1C7BFABA892661E00001351A5D1CCC3C3C896370E2066A7B9BFBDB6AA67160000237BAECAD0D2BFA7630C00000152A0BBD6D4CDA348070B0C277FB7CEC7CEB9AB852600004090B5C0B9C4AAAA98530A000000237EB1C5BFB98F440800093676A89B787FADB49E4F19205BA5C4CAB6AEB8B7A4989A9E97701B000068461B000000000000619FAEA372340E060C08094393C4CBA76E302318141628528FBDC7A26D331A0CB346211D2376C0CA9F63392B241F334782B5D9F0F2C980060C08094393C4CB01FE375E0707187076A9D4DAE7DEAA7876694B5E9ADBECD9D1BB6A1F0F0D3070C6E7E3ECC7B5BD8E3503000E77AFD0BAABA48952120000144F99D1D6CCCAB987300B27669DC1CBC4BDAB580900002378B8CCD7D5C9A554100000004B9AC8C9D1CD9E42100E123683B8CACCCCBBB9772600003E8DAFC3C9C4A9A18B49040000003182B5C2BBA88E3D04001A3E81A29C7D7FA6C3A1511C2259A3C3BDB3B3B9B9A29CA19C9B6D1600006950300000000000146A9BB5A26424040914130C488EC8D3AF702F2F1A0C191F388BBABDA166341714C04B1E25307EC5CBAA5E34262F2F2F4B8BB0D7F0EBC27F0914130C488EC8D301FE385E0707188079A5D6DCECCAA08182695A5C9BD3EED4C5B3621E08052978C5E5EBDBC8B0B18D3300000D76ABC4BEB7AA8B5B1A00000C4B9CCFCCC6C9B97C350E2472AAC4CABDC5AB5B0C00002F80BDCFCECAB9A15B050000004997C4D2D4C7A247190B162A85B4BBC6CAC1B7801D00003D90B4BECAC9AC99894C02000000347CB2C2C2BD903906011B467996906C7EA4B4A3581F2A5D9ABDC9BFB0C4BBA997A5A99E731B000075542600000000000160A1AE9F612A0A03040315549AB8CFB081433429161A294D8CB7C29D6C2E1B0DB4452027397ABCD0A45F2F262F2A324886B6E2FFF3CC7D03040315549AB8CF01FE395E070718906CA5CCD8DFD89F76796B535D90CDE3DDCEB1591B05032D85CFE2E6EACAB8B8833400001670B5CBB7ABAA88451700001052A9C7CECAC6BC8B340D2468AFCAC5BDB9A9500800003089BEC9D0CCC4A4580A00000454A5C0D0D4C19441100A062F87C3CCC5D0BEAE782100034A93BDC4C4C3BAAA8A3F00000000377EAFBEB5AB7F410B061E4083A2876A7BA2B3A54D18266CA8C2C6B8ADBEBBA8979BACA4812E000063431300000000000066A2ADA46A340402050011609DD1D6AE663C2F20141B27448AABB5985C33160FB94325233489CFD6A7593015242738528FC2DFE5E6C07902050011609DD1D601FE3A5E070718A080A8D3E3E8D4A2858767575696CEEFDDC7BA642204002275BDE3E4E5CCB6BB7B2E03001872B6CFBEB2AC81461100000C5298D1D2CFCCC688330F2973A9B6C1C4BA9B520800002788C5CCCDCFBB9D4E0B00000C58A1C7C9CAC597440F060A3098BBD3C9C5B5AA7013000E5DA4BEBAC3CCB9A58D41000000073184BDC7C0B37D3300002050859A866074A5C8A14214286BA5C8C9B1B3BCBFA79B99A0997C220000704A2300000000000C63A5B79D662F0A0708050C609FC1D4B16D392E1B1F202A5798C2C19A61341414B25D221B2B77BEC6984E341A23273F5693CEE8F1DFC3710708050C609FC1D401FE3B5E070718B06990CAD4DFD69672785F4B5187CEDDD1C8B3601A02002575BDE2EAE1C9B1B1822D00001684BFC1B9ADAA8141060000144E9EC9D0C2C9BB7B2818347FAFC2C4BCB99746080000388EB7CBC5C7C79E4E0000000456A1C3CBCEC39C40110205368BBBCACDCAC1AD681B00044FAAC3C1CBC2B5AB8B3E010000043A88AEB9BBB77C2C02022250889C76616A9EBBA551263371B4C7C9B6B4B3ADABA1A2A09B752800006E5B260000000000025FA0BBA2662D100809161B5CA2CCD4B0663428231720305D96B6BC995827100AAF3F1D20398CCACEA75D3214222C355D95C8E1F0E7B7720809161B5CA2CCD401FE3C5E070718C0779ECBDFE5D098847A60415291D0E1DFD2B3591D09002A70C4E1E9DEC5BBB3803000001885B8C3BFB5B48338040000084A97CCC9CDD1C5822C122D7AAFC4C1CBC59E500300002F8DC2C6C4C0C5AA56050000085EA1BDC9D4CA8F3C0D050B338DBACBD1D3C8B66F1000075DA1B8C3BBC5B19E7631000000003B8ABBC3BDAF802B08062551838F785E6B9EBA9B4E192D71B9C2C1B7B8B9BFADA5A99F9E7229000063471C00000000001162A5B39E652A080504081F6198C0CDAB6B2F2C21292830639CBBAF8E4E1C120EBE4526263A8CC7C59F592C212B24455587C4EAF1DBBA720504081F6198C0CD01FE3D5E070718D070A7D9E0E7D99C8B836A545A92D2DFDFCAB0581E08082E76C1E0E3E1CAB9B17E2900001C85B3C3C4B8A97F380C0000105293D0CEC9CAC484350E3179ADC3CDBDB79D450000003891C0D5CACBC29D400000000C5E9FC2D1CBC592350A040D3782BEC6D1CFBDA66A15001660ACC3D0C7C7B2A78430000000083D84B6C4BFB1732700031D5892A0775A6F9DAF9B55273176B5CDBFBDB9BCBAA7A5A0A39878280000654B1F0000000000116DAAB39B5F190A07020B1552A5BEDAB56F372C251A2E3E639EBDC0955728100FB844281D3B85C7CCA4542012202C305093D1FEFFEFBA7007020B1552A5BEDA01FE3E5E070718E078A5CEDDE2CA957D8462495B8FD0E8E4D0B05D1C10021F79C0DAE4D9CFC4AE6C1D00001C8ABECEC2B4B083340400000D549DC4CDC7C6B770220F3885B9C1C2C2B192430100004293CED0D3C6C7A450000000074A93BECBD1C8963A090C0B3989C5CCC5CBBFAC6917000C57B1C1C2C3BEAFA48934000000064786B1C3C2B1803C0300315890906F5A6697B9953C173076B6CBCCB1B2C2BFA5A6A8A69C712000006E4D28000000000011679EAE955920000100051E67AAD4DAAD6D36332F25232C598FBBBA8C4D201010B0451D233D94CFCD994A2121362C304899D7F1F4DFB06B0100051E67AAD4DA01FE3F5E070718F0739EBDD4CEC789747D5C435994C9E2D2C8AF602607001F70BDDEE0E5CEC1B76D1A00002280BDC1C7B8A472310000001251A7C7D2CBCEC27C2C153B8BB4C1C8BDB88E37000000459FC1CCD0CBBE9A4C0200000B52A5BAC4C8CA8D3B0B02063B89BFD1C5C6BAAB651500165FAFC1C1C3C5B3A47C3100000006478CAEC8C2B9772700012C5C8C8B6E4560A2B9974D1F337CB5C3C5BCBCBCB4A8A0AAA19A72240000664E2000000000000E63B1BBA96026000000001B68ABC6DABD712F252E27213769A0B5B99A54190706AE48202E45A2C5C69343241D2D21284FA4D7F0F4DAB7680000001B68ABC6DA01FE405E070718007890BDDADDCA8D7F8060405189CAD8D6D5AD54160300186ABAE2E4DED4C4B3671A0000208BBBC7C7BDB26D2F0200000C4A9FD3C5BFD2B57A30143782B8BFC9C6B694340000004A9DC6CACEC9CC9849050000155CA3C9CFD7BE8E3C07080C338FB8C1C8CBC1AE6908000D58A4BEC8C2C3B0AB7D280000000A4E8DBCC0BAA35D190008377392936F4E6297AC874711357EB3D1BCB7AFBBB6AFACA89F967928000066360500000000000B6A9FB992591D0A0C0900247BA8C3D5B372322B33202A396FA1B4B68D4D250B08B13A16194A97CAC19449191A2628325CA4DEF7E7D5A7680C0900247BA8C3D501FE415E070718107BAFCDE1E6CA9781886548538BC0DCDAD4B6562702002469C2DFE1E0D9CCB1631300002688BBCABDBAA979270000001152A5C9C9C6CBBC7728103E8EBCBFC3C0B68D3C000008479EC7D2D6C3BB8D49020000185E9AC0C8CEBC8631120B11308CBDC4BABFBFAA5C0900176DB4C3C4CAC3B6AC7C2D000000185299BABBCBB2651500123A6F8F9566475E9DB3924118397FC3C3CFB9ADB5B4AB9AA1A6A0771F0000663E0E0000000000156EA3BA995515010400031464ACCED6AD602E2C371B253777AFBDB57F441E1006B3432124519EC6C08C45262027253157A8DEF4EAE0AF680400031464ACCED601FE425E070718206DA2C7DAD7C094828A6B4A5384C0E7DFD1B05E2002071C6EBBD3DCD5D6C7AD620B00002188BECDD0BFA772260400000F549DC5D0C8C7B477291A3E87B1CAC2C0AE80310000135CA6CDD0C6BDB7A748000000135EACC6CECDBF882E08000D3B8DCACBCACDC59C450200206EB2C0C4C6BFBAA87D280000001A518DB2CBBBAF651C000B3A709B9562445693AA873C122F8BBED0C5BDB5C5B3A5A9A7A39A6D2600035E441100000000001876ABB48F4E1C070000061E6DAED0D0B4692F152E2E304476A7B9B58745190209B15124234DA4C8C38F4A20132D2D284695D3F7F2D0A2630000061E6DAED0D001FE435E0707183079A2CAD6DCC78D7B8D69444D8ACDE1E2D2AE571D0B012B75C3DDE6E1CCC4AA5D0A0000228FB5CECBC6B780290000001863A3C5C8C5BEB4702E224688B0B9B9BDAF843200000F5BA6C1C1C6BDBDA74F0000001768A7C2D1BFBF8635070B1A3691C1CCC9CEC29B5205001B6DB3C8C2BBBAB3A4701D000000215896BFC9B6A76118000E4476A18D65445797A882371A3688BDCCD1BFBABFBAB3A79F9FAF75210000603D1000000000001373A5AD874510000000092B72AFD4D0B76D332C39322B3C72ABBAB1824108060AC0461B214E9BC4C38348261F271E2A5EADE2FFF1D39F5F0000092B72AFD4D001FE445E070718407AAECCD6E0BC7C818E60435087C8DAD8D7B254200C09297AC2DDE1D0D0C6A45E0B00002487B2CECECAB27C20000000114DA4C7CBBAC2B6702E164296B4C4BEBCB0802700000D52A1CBD4D3C6BB9C4900000017649AC4CBCCC4863A0F00023891BDCECBBEBA984C0A002079B8CABCC0C5B6A071180000032867A0B7BEBAA2611D0319507F988357415E9DB18B3317348EBDBFC2B9BCBDC8AFACA394936F1E060A6C3D1500000000001477ABB386521000020508226DA3D0E1B46E281F2D292B4577A5B9B37D3610040DB4431E2A62ACC3B2813D27262A2D2558AEE0FFF2C89355020508226DA3D0E101FE455E07071850749EBACED5B98274835F41518EBED1D0CEA953180B041C65B2C9CED6D2C4AF5A0100002190BECABFC6AF71210000001054A1C1BEC3CEB87028214D97BDC4C5C2B0772A00001A51A4C4CFBDC7B8964100000022679DBAD1CAC38C2E0400083F8CC3CFCDCCC0924503002474B7C8C9CCC9B4A1701C0000002C619ABBBBB8AE641900164C7EA3915331598AA87E3824498CC1C9D0C1BFBBB2B0A09F9F9C731B000D643A0C00000000002280A7AD8A4C0C000009102571B1CCD1B6752B2838362D4976AAA0AC75340F0C0FBB41242C5DA0BAAD7E422015272B3866B0E8FFF7CA94570009102571B1CCD101FE465E07071860799DB8D7DABA817B7960464C8AD2D9DBD3A65C2A110B1F71BDCED8DED4CCA0480400002287BBC8D1BEAD70210000001254A6CCCACBCAB56D1F164A99C3C7CABFBB7A1E00001761ADC8C9CACAB6983F020000216DACBEC6C0B672240703134486BCD0D3D2CC9C4D07001A79C1C8CCBEB4B2A171100000022967A3BBC0B09F541500194F92A79A5D3A4E8CA2762D133C9BC1CDD2B8C4B7B8B1A5A6A09B7422060C6A43090000000000277EAAAE904D09000006092C7AB7D1D9B26C2321372E2C517FA7B8BC813A0F090EB34D1E2A5C9DC5B4763B221723203162B2E5F6E7D495510006092C7AB7D1D901FE475E070718706DA3C2DED6A97E748A613E588DB7C7D3D6A252180C0C1D62B3D3DBDED5CDAA480500002A96C2C7C0BBAD8025000000145EA1C1C3C5CBAD671F184F8FB5BEB9BEA8762400001B67AFC8C7CAC2BF9B44000000236DA4CACACBC1812D100A163D8AC4D2D1D4BC913D0200227ABDCEC7BCC1B19E69160000002B6AA4BCD2BA975A0F00205190A488573F558CA06A2C173A90C0CAC9BFBBC2B2A4A29CA79E6C230C17572A000000000000126FA6AE7F3700000308082670AECBDBAB692A1F3D3B335284ABBAA974360E060EB34C242D5AA6BEB4792C1F222929305FACD7EEECC086560308082670AECBDB01FE485E070718807391BCC7C5AD81777D50454B8AB8D3DACCAA57241000196BB2D5DDD4D0C29242000000298FB8C9CABBB27522000000165EA9CFC7C0C3B672281A5395B5C3C2B3AB781600001A6CAAC5C2CBC7B8923F000000256AA5BECECFBB732203021A4281BBCAC7C1B7954100002886B8C9D4C2BCABA06F170000033672AEC7C7B79F4D0D0012538EA28B5B32508A9A6B271A4899C7CFD5C5C2C7BA9FA3A79C9A6A18021057350200000000001A74AEAE7F420E00070609317ECBDCE4C07023192E0F29548EACBDAE752A00080FB34A232A60A2B8B37C3A1F14181E3C68AAE4FFF2C58F51070609317ECBDCE401FE495E070718907CA6B8CED2AB7B7D895F3B4682BCD1D9CDA94A2112071B5AAECDDFDFDCBE8D45000000228BB6D3CDC5AE721E000000195EA6CBC6C3C8B0631E225C94C1CCC3B8A96E1500001D6ABAC6CEC5C1BF9F3D0000002B75AAC1C2C6BC772C040A11448CB6C1C7C9BD923F02002672B0CBCDC2CCBDA66B180000073A71A6C0C4BC9C5115001D6797A9894F3354888E6A25194B9DCCCBC7BEC0C6BCADA2ACAB9E6E1C05135E3800000000000018779FB27F3900000003112887C8E8E5BA6321243239365C93B4BEB77226080105AF411E2468A0BAB4743115171C222A63B0EAFFECBE7D4F0003112887C8E8E501FE4A5E070718A081ADBFD4DFBB7F7985593A4F8FCCD6D2CDA8503323010D5FB3D7D1D1CCCB983E0000002C92C8CFC7B9AF6F2A000000126BA4CCC3B4BAA4631B14579AB7C3C2C0AE671A00001D6AB0CAD7CDC8BD993A0000002D76AEC5CEC5BC772B0112174F8FC1C8BFBDB48C3200003087BABEC4C3BFB19C63170000114179A2ABC5B6A9510500236794AB8D50365285985D2218479BB6CCD2C5BEBFC0ACA79B96986B170D13592B0000000000001C7AADA87E3A08000000032886CBECE0BA682723453B395B89A9B9A9662D070009AB502A2C68B3BDA468321E1319273168B7E9F7E3B1774D0000032886CBECE001FE4B5E070718B07396ADBFC2AD6B6B7D4B395080BAD1D7C7A1481F1807155CA4C6D5D6D7CF993B0000001C85B8C6CED0B474230000001561ACBBC6CCC7A3621B235DA0CEBBC6C2A762160000186DB5D2CCC4CDC3933E00000D2F6FABBFC6CEBB7326120E1B498DBDC5BEBDB58B3500003384C5CEC9B3B4AAA06D16000001457EA5C2C6B3A3500B00215F95A4864F3C55839156211453A3C7D3CFC6C0BFB0B1AE97A29A701B121B65360000000000002783ABA8843A08000100012883C6E2DAAF64291F3935335B95BEBEB1742B09010AB44B282D66AFBDB070281916231D2D62B3EAFFEBB37A470100012883C6E2DA01FE4C5E070718C07BA1BAC6C5A57C7177583F5390C0D4CCB59A412C14061A62B5CFE0D2D0BA9132000000269DCAD9D0C2A76F200000000B68B0CAC2BEC0B26022205C96B7C2BEBCB6601A00001C6CB0D0D2CEC6B99A400000063C7EACC0CCD0B46D190109134993BBCFC5C8C1872B0000388DC2CAC5C2BEB89965080000155886A3BEBEB89E45090022639FB09051344E818C55120F4DA5C5C4C7B5B3BDBAB3A698A0966918011755240000000000002383A5A3823B10000000122C87D2DCD1AD5A242139392F5E8FB1BCAE782500000BB04F242F6EAFC2AA6C26171A221E3B6CB8E6F6E4B173400000122C87D2DCD101FE4D5E070718D07B98B5C3C4AE766D745237528EBAC9D0D0A65E2E1D06165DA4BFC9CFD0C19B31000000248ABCD4CCBAB474180000001768AAC7C9C7C9A15D1C295A99B0BDBCBCA46B1200001D6CB3C9D7D2C9BC89390000043383AAB6CFBCBC6E1E08071E579DC2C9C8BFC1952E00002F87BFC8C2BDBDB5965908000013558DABBCB5BA994706002671A0A88A4E394A808455141255A2D1D1CBBBBEBBB6A8A79C99996B240F20623E000000000000318AB5AC872F05000207143C93D0E9E4CB721F13383B43668DB3C0AC6B2F040807AC44263171B1B6A0632D231A25232F60BAEDF2E4AF76450207143C93D0E9E401FE4E5E070718E076A4C6CCBF9B756E7C523A5387B5C0C2BC944C291E0A195FA5C0D2CBD4C99737000000289DBBCAC8CEB1761F0000001969A9C3BBC1B8A15718215FA5BFC5C9C8A95C0B0000266AB8CEC6C5BEB89B380000073A84ABC0C8C5B85F1A00091C4E99BACAC5C8B2812300003891BED1CBBAB8B5A2680C000018528EB8B9B9B09B491000206D9CAA9156364E7E7048181B499FC3CACDC3C0C2BAA4A08E9D9B6E26142653260000000000003381AAAF742D00000000002B8AD2E8D9B569281B3B393F74A4BCBEA76620090610BA3D1D3072A6B7A35F31191F24252E6BBCE7FFECAD6B420000002B8AD2E8D901FE4F5E070718F075A3B9BDC5A07066774D335293B4C1C8C892522D22051257A0CAD0CCCDC28E3D0000002B92B9D4C3C7B678250000001969A9C7BBC5C7A558161F58A3BABFBCB59B580300002E74C1D3C7C4BEB4914200000D4581B7C3BFBCBA6F21130D1C5497BCD0C5BBB0812000003296C5C7C7C0BCA8905A030000266196AEBCB8B098410500266FA8B78E503645717A451D1953A6C8CFD4C8C4BDB2B3A1999C916E201A3168390000000000003283AFAB7D28000000010B3293D9E9DBB06726193D32416B9CBCBFB26A2206020CB2481E3574B4B292582A242426293E6FBCEBFFEEB25A4500010B3293D9E9DB01FE505E070718007998AAB7C59A706E784D2E518DBCC7D0BF8F4E34220B0A4D97BCC6CAD7CD88290000002E8FBDCCCABFAB67220000001364A9CCC6C2BFA45216206DAEC3C2B7D1AA5B0C00002D74B9CCBDCDC5B289350000124A8FB4C2C4C4BC6B25010827589BBBBDB5C7B2841A00003E94C4C9D1BEB3A6995705000026629AB0BDC1AC9D3E01002A739EB18C48334D6F6E390E1654AAC8D2CDCDBBC5C1B4A29D9F9F5F1717285F2D0000000000003689B099721D00000409133396D4E2D7B45E221A3D383D64A3BEC1AD671A000603A9421C3486B4B7965627151926223476C4F0FBD8A2653E0409133396D4E2D701FE515E0707181080A4AEBEAE8E70646C402B478AB5BFCDBB8F41291B040F6094BDCCC7CBC28D2E0000002898BECFCBBEB1781F0000001A74B6D0C5B9BCA0541D266195B9C1C1BCA1530500002F80BACBCBC6BCBC8F390000234B8CAABAB9BCA763200B1534619AB6BFC5C4AA701A00013F91BCC0B8BAADB09B5B0D0000306C89BAC6BDB0913F020029789CAD85523C4E686C42131759AFC4CAD6CAC4C6BFBCA68D8D986410142C672E0000000000002A80B0B17D2600000005093C96CADDD7AC641B1C3D444A78ADC5C0AA6C26000E16B3482C3A7DB1AD96561E1A14181F3E73B7F1FDDCA75D430005093C96CADDD701FE525E070718207696A2B7B691626E6A3C344D83B0BAB9B88F4A2F2908054C9AB5C6D1C9CC8223000000288DB8C8C2BDB3792B0000001770B3CFCCC4B89C5818207AA9C2C1C1B7964F0200002C83BED1D0CEC8C18F350000144287ADBCB9BAA6611F0902205C93BDCCBBB8B7761D00003E95CBC9C8C9C5B19E510200002F659BB1B7C9BD8E3600001669A6B595593B46615E2E101859AEC9D5C2C7C7BDB2B4A896A79B5F191335673B060000000000368DACAC7E2A0000090F123791D1E3DBA961181737384076ACC4C7B7701F030910B34B22388CAEB390561C182320253575BBF3FEE7A15A34090F123791D1E3DB01FE535E0707183076A0B7BABC9A6C67724C31478EB4C1BBBB9455321D011055A4CAD2CBD3C0842E0000002E8EB9BFC5C8AE701B000000217CBBD1CAC3BD9E4D1C2473A9BCBCB7B69F530600003076BED1CCCBCABB89360000245692AFB1BAB6A76923100F286998B5BAB7BAAE6C0F0000409ABECDC7C2C0AE9954030000256B9DB5BBC3B4A03800002A72A9B1864B3547645E381A1A5DAED3D0C4C6B9B2B2A99B969B9D5D1F1239612B0000000000002F86B2A86E2F080002000C399CDCECD7AB5E2225404A4F81B2BEBAB06B270F0E0DAD492C4775AAB0894C211519111F2F74C1EFFFE69F644002000C399CDCECD701FE545E070718407890A8BEB593605E60362E518BB3BEB8B48D49342F100D4D9CBABFC2C9BA88320000002995B3C5C9BFAF7521000000237ABEC8C7C8B19C460F2175B2CAC6B9B69F560B00003685BDC8CDBFBBB28A390000285A9FBEB7B6C0AB5614000B265DA4B7BEC1B9A2610F00004795BDD0CEC3B7B69E4C0000002F72A0B5C3C0B68D340000287CA9A88A5A3F4B605230121165ABCFD2D3CABFBBB7B2A08D98956120113C56210000000000003083AD9D70260000000A193993D7E5DCB164231537354B88B2C4C2B3712000010FAC4128488AB7AD864F1E161720304378C3EBFFDE9E5D3A000A193993D7E5DC01FE555E07071850748C99B0A38555585B36285087ABBBB9AB864B3C371512498FB6C5CAC8BE7E220000002D8FC0C5C4BFB1751A000000207DB8CAC0B5BB9748122477B0C7C8C0C0A6560300003388B6D2CFC7C2BC872C0000275C97A9BFC2BDA65F20020625679DB9BDBBC3A7611200004994D0C1C3B8B3A78E4400000028739FB7BABEAE80390000367CA4B7915646495944220A1555A9D0D2CDC4CBC3B4B29F959B956719204A612A000000000000338BAFAD6C1A00000008173E95CDE0D7AE69151C22384997B3C4CEAF6D25020A10A83E26568FB2AF86481E1918242D3365C3F5F7DE9D5B410008173E95CDE0D701FE565E0707186074A0A9B2B58D57595C39245293B0BABCB6864B34350C0A4788B8C0BBCFCA7B200000002C91C1BFC0C5B0812A000000247CB1D2C1AFB997461A276DA3BEC6BDBE994A0300003D7BB5C9CEC6BFBA9530000030599BB2BCC0AEA458150307316FA4BBB5BDBAA65E1000004193C3D1C8C1B2AD963C0000003F85A9BAB6C8B3862E00002D84A6B18B5B3A495B482908195CB9D1D1D2C4C0B5B6AA9A8E9F995F25194464290000000000003B8EABA567180000030715479DDAE7D5A6561A19384A5B8EBDCBC6B1601D000010AE442C5495B2B0843A1F1F1C1E203A78CAF9F8D28D5941030715479DDAE7D501FE575E070718707C97A8B5B38A5B60663F2E528EADB9BAAC88524032080C4696B1BFC0BBB184230000002795BBC3CDC7B57C280000003786B4CABAB8B891471C2A75A7BABBAEAFA14D0800024282BCD3CEC1B5AF80290003326E9DB5BABFB8AC551B03112B729CBAC3C1C1A86305000046A6CCD2BDB6B3B093480000003B82A8B4BFBBAC7F2300002785B0B08A5947505A3D1D0E156DBAD3CDD3CCCBBBA5AFA194948E5E232A4E63230000000000004C90AE9E65240500000324489DDDE0D2A6551413383A4D91BACAC5B27521000710B241254C8EACA5813E1F111A2A24397CD6F5FFD58A553C000324489DDDE0D201FE585E07071880778A99AAAA865B5254281E4D88A9B7B3A578443E31100F3F95B6C3C2BDB877250000003594BEC2CDBAAF731A0000002777AECBC7BEB88B46142C7DA2BCBABCAF974B000000408AB9D1CDBFB7B1782E0005406FA6B5BFB3B1A45E190D062D7AA7C2C8BFBAA355050000459EC1C3C6C2B6AB974F0000004986A9B9BAB4AE812A00003882ADB78E4E314646382000135FB5C8CFD2CAD4C7B0B3A28F9B92511A3057591B000000000000438CB5A465130000000016419EE0E5DBAB521A152C39538EC1D0D0B06B21081311AB40205997B8AD793D1B120E19222B78D0FBF9D596593D000016419EE0E5DB01FE595E07071890747C93B0A1764C445A34295583A4ADADAA81473B36140F4686B4C1C3C5B27E240000003098C0C6BABDBA80290000002787BCCCBBB2AF893F142A7BAFBDB7BBB1934B00000B498DBCC0BCB9B5B57C2900003983B4BBC0B7B09D521D040C367FA4B8BEB5B39D570B000043A7CECDCFB2B5A98A410000054A8EACB2BAB3A7751F00002E8AADAE90635450482C0C00175CB4C3CDCEC8CDB7B4AEA28D9B9E61192749551E0000000000004197ADA86113000000000D45A6E1E6D3B15D201A2F3D5A98C1D4CCB36E240A1012B3442264A5B9A676321616221D192C72C6F2FBD582512500000D45A6E1E6D301FE5A5E070718A07A939CA8AC8A5444492720528CA7B0AFB0864F473B11094285B1B5BBC3C8811A0000003294B7BEBAC0B785240000002883BDD1CCBBB0893E132885B6C3C3C8B18F3A0000054991BCCAC8C2B9A87F3000094277ACBFBFB7B09B511F03063279A8B6B0B6C09D430000004FAACBC9BEBEB5A9914A0000004688ACBFBDBAB07F280000257DACB7955F433F4E2D09001466B1C5D7D6CEC3BCB0AD9A8CA094581D2E4E561F000000000000458DB2A3641C0000060B1C4BA2DCE1D3A4561F1F2A3E578FC1D4D2B8702709141EB64B285CA1ADAB763815121818223A7CC5FBFACD8B4835060B1C4BA2DCE1D301FE5B5E070718B06B848E989D76433D42242A577FA0A9A3A0794A503D180B4089B7B6BFC1BE7E1C0000002383BEBEC5C2B17D2C0000002D84BFC4BEB3B6883F102E82ADBAB0A4B39F4B000005468CC2CDC4C5B9B4771E00084A81A5B2C6BDB5964619000C3A81B4B6BDAEB4924000000047A2BFC7C4C1C1AC923B0100024990AAB0B6B8A871200000378FB1B08E6353483A1C0B08196BB3D8DCCEC3C6B3ACAE9D939E985921335353160000000000003C8EAC9A5F2200000C02154FA3DAE2C7A057291A2B355A9EC4D4C9B5732800150DA83F225EABBFB07D38130D1424243A83CEFFFDCD7E4B330C02154FA3DAE2C701FE5C5E070718C0757E909C8E7448483F1B1E5790A6B0AFA78054554415053787B0BDB3C5B276170000002C84BBBABBB5B883270000002B89C0CDCBB5B083390A297EB7BCB9B7B295460000114E92B4CCC0C4BCAF6E2500014F7FAEB3BDBAAE965317030D367DA8B4BFBABA9B490000004E98C1C5C9C8B7AB8E420000055196ABB8B3B49F741F00002C86B3B38A665152461C040B226ABBD6D6D6CDBABCADA79690999353192E55571C0000000000004495B297541100000000124BA6D9DECBA3612A182A3A62A3CFD1D2B26D20000E1CAF4A225CA7B5A96C35171E1F1A1B3780CCFDFBCA854F3B0000124BA6D9DECB01FE5D5E070718D0728E8D9C92693C3C46212857809CA7A7987246474616113C88AEC2B9BDA9701B000000268EC3C0C1C5B881340000002C84BFC8C0BCAE80320A3281B2C4B6B2B0873B00000C549EBBCBC8BBB9A87A23000F5487B1B4B6BAAF8F5316000B3682AFBAB7B2AC90420000004AA2D0CABEB4BBA38B4100000C5993B0C1B7B9AF741600002A7BB8B39F614E4C42220C031C6DB3D1D0D6CABABEA7AD978C93954E1B2E5B59100000000000004092AD9766190000070B1E55AFDEE7CD9646171D1F3062A6D3E2D2BA7922060A11A0472461A9BBA4712E13172025223283D0F5F8D2844B31070B1E55AFDEE7CD01FE5E5E070718E0778C959D976F494E482021528DA9ABB6A57B58584B150C3B7EA5B4B3B5B67B240000002B85AEAFBBB6AE7D1F0000003493C0D7C5B2AA79320B3174AABDBBB7B38E3600000E5894B5C6CAC7BDAB6E200014578CBAAFBBB3AB934C190400317CABB1BBB3B0923800000043A0C9D0C5CBBCA98B2A000015599BB2BAB5BAAB6E1D0000348EB3AF9069524C3D120001226DB8DAD5D0CCC5B8A7A9A49798914A19325755130000000000004288A78D580C000000041551ADE0E1C8934F140A223C61AAD1CCCAB46C11000712AF3F2A62AAC5B37E3D181E1A2118377CCDFCFEC57E4D3500041551ADE0E1C801FE5F5E070718F06F8991978D72444A35121E6A88A1A5AAA374545556250D3979ADB8C3C1B77C1F000000257EB0C1B8B7B9852C000000288DB4BFBEB8B689360D328BB7BEB7AAB0943F00000F5992BFCDC8B8B1A76A1700186095B2BAB0B5AC985118070E3F89BAC2B6B4B78B2F0000004FA8D3C9C0BEB8AA843100000D669BBBB6B5AEA2731400003B87ACAD97634C4E351105001A6BB8D5DBDBCCBFB0A7ACA89CA48D4E1E395C5B19000000000000539DA5905613000005091C59B6E4DAB897451C1B233667A6D1DDD5B3731F03121BAB472D6DB7C0AB692D121D1A221C3685D6F1FECA79412F05091C59B6E4DAB801FE605E0707180079848697876C4B473514164E859DA5A7A37351554D22063888ADA6AEB9B46A130000002584B9C1BDBEAD802C000000327CBDD6C3B4A7753917327DA6BCC0B9B388350000145C8DB9D0C6C3BFA9641300176096B0B4ADB1AA914A1400083986ADC8BBBEB48F3C00000149A2C8C4C0BAB7A37F330000176EA5B7BDA7AB9C70190000308FB7B0906D594F331907002775B3D7D9D5C3B3B2A4B1B09FA39444223B5D5E220000000000004A92AF8D53120000050B2658BDE9E1C18B511A0D1B2F6BB0D6DCD2B66E21000C10AE503B7FB0C3A86B24211D1A23243182C9FCF6BF7E3E38050B2658BDE9E1C101FE615E070718107B8385908E71434130111B548B99ABA4906B5262561F093786ABB1C0B9B173110000002A89C4BDB9BAA9752C0100002D8DC0D1C1B0AC71290D3987B8C4BAAEA586380003215E9CB9CBC1C0BEB8671500186AA0B2B0AEB0AF924F0E020B3787A8B9B8B1AB872B0000004CA7CFD5CCB8BEB2872A0000145B9BB1B5B4B29C69130000307CB6B99D77635A2C0C00001F75BBD8D1CCD0B8AD9CAFA79A9889481D415F5E14000000000000458FA08F550800000204225CB4E4E6C78942141B2C3B6AAFD0CFCEB8711E081217A9472D6DBDC4AB6A331912151C1E396DCAF9FFC374432E0204225CB4E4E6C701FE625E07071820787C849A916546372E0D195A85A0A3A7A07052615622092F7CA9B1B4B7A86E100000002683B4B7BBBAAE852A0000002D8BBBC8CAB5AF732E0D2E80B4C3C0BFB98C3E000019669DB1CEC3BEB0A36414000F73A1BDBEB4AD9F834715090D3C83ADAEB9B7B1882900000050A9C4CDC6C2B5A07A250000217AADB6B3B6B2A76A1900002C7FAAB39B6C5D50290606031F68B9CCCBCFC7B6A392B2AD99A5974B183A5A612800000000000060A1B38E530C000000051D57B6DFE4C176471E1024326CAFD0DFD9BA752A0B0A15AD483474BDBEA4622C151E1B1F26367ED2FFFDC37C493000051D57B6DFE4C101FE635E070718307B85898E8B6F473D2E0D1F648A959EA1967C566E681F0E367F9FACBEB6AA6410000000257FA9BFC1BCAC7E32050000318ABAD1C3AAA7682F10378DB2C2B8B1AF823300082868A1BCD2CABBB2A25D1000237BA4B4B5AEAFAB83401000093B89ACB8BCB4B07E2C00000050ADC7C0C3C5C4AB7A2700001878AEBBBEB2A59A5C130000327BB4B1927464512E0B00002576C5DBD4CFCBB9AB9FA7A695A18F4D1B40694A000000000000004F89A1964408000000001656B2DECFB989491819233969B6D6E9DBB87223061219AC3C357AB9CBA56622132621211F388BD2F3F0B56D3B3000001656B2DECFB901FE645E070718406F81818C7A58383C2608225F7D8E99AD9B6B5864561703337FA9A2ACB5AC670E0000002E81B7C0BDB4A77131000000348DBAC2C8BFA3722810408BB9BBC1BAAF8F3600001D6B94BDC0BEB8AB9E601B002070A6BCB9B0A69E7D3E16020C4D93B8BFB8AFA9772200000052ACD0CCC6C0BCAD7F2300002479ACB1BCB6B9A2681500002E83ABB89B776C502B060200287BBFD5D9CFC2BAA397A3AA9FA083462748684E0D0000000000005096A0864F060000060C2066BCE5D5AD793A0E13233873B5D5E1C8B36D23000A13AD45397DBDCDA35E1C1328241C1F4587CCF5F9B65F3B2B060C2066BCE5D5AD01FE655E07071850757C7E8982603D4432071D5D839A9C99917A566D5C2409317DA3A5B0B2A768130000003383B6B6BBBBB17A2C0800002D8DC1CBD0B9A16C1F083787B3C4BBB7AD8731000023649EB7CAC8BEB5A75A0B001A72A4BEB9AFA8A5823C12030D438EA8ADB6B6AB7B230000004CACC7C2C8C3BBAD862D00002A7FA5B4BEABB8A8620E00002F85B1B5A5756D5826040000277ABBD1C5CAC6B89C9AABA995A1833B20486A510C000000000005589AAD8E390700000A0E1853BBEAD6C2864910161C2E74BFDCDED1B47426050B17AE462D7CBDCFAB6A2110231E25223C86D9F5EEAE6037260A0E1853BBEAD6C201FE665E07071860777677887B59404122091453818193A090725871642708307AA1ACABADA364050000002E86B2ADAEB7AA7B340800003287B8C1B5AD9B6C290B3E8BB9B6BCBDB48D3000063471A6BCC7BEB4A398540800217EACB7BDB3AF9F753014020D4593C5B9B6A8A0741C00000455A7D3CBC7C6C0A5761E0000377EA9B3B6B0AC9A590800003085A8B29D7D6B5A2E0606002A7AB5D2D9D7D0BF9F93AEA8999E81422B47725606000000000007569CA9874A07000000172460C3E1D5B081440B12173D77ADD8E8D5C07224000F1AB14D3A86BDCDAA66211329291E13368ED8FBEEBB6B323000172460C3E1D5B001FE675E070718707282818A7D6740402D10205C7D979B98916B536A621802347F9EA7BAB89D560B0000003B83B2B6B7BCAE73390A00003893C1CBC1B29A612102398FB3C0B3BCAD8237000A3A7EABC0C3B7B5B29B530C001B78ACBAB5B7A59D7F390C000B4887A9BEB6A89C712300000056A6CCC6BEBCC6AE762000003179B4BAB8B0B79E5C0E0000347B9DB1A186825E240000002877C1D8CEC7BEB6A09AA8B2A7A18640284A745B0A0000000000085797AB894A0F000000000D61C7E0D3B58142160C213471BDDAEBD6BB7321080F15A7443E83BBCAB0692A102C251C18308BD6E5EAAD67402B00000D61C7E0D3B501FE685E07071880738387877D5544351E091E5F858AA19F8A69566D6423112B78ABA5ABACA054040000002A7AA5B7ACB2AA76391500003F8EC6CFC2B0A8602813478FB0B9AFB2AD8A2D00003583A3B4BBC0BBAD9C4F0B00277CA8BAB4B1ABA07B3516000A3F8BB6C6C1A9A3751C00000054A7C7C4C1C0C3AB75240000328AB5B6ABA5A8955C050000287AB3B6A88F805C240000002082C2D4D6C9C6B8A59BADB9B7A98A352050755A060000000000005D97A87D38020000040D226CBBE1D8B379301817293A7BB7DEE9D7B36E2200000DAB443B8AC4CFB65F1513231D12203B94E0F8ECAE613630040D226CBBE1D8B301FE695E070718907582818381513C3E2D0826557B92969588615D6E5824163375A0A4AEB39C5A020000002F83A2B4A4A9B0803A100000308FBCCABDAC9B671E094189BEBFBAB6A8823800083E80A9BDC5B6B5B5A45309002587ACBDB9A897997B330A00074395B8BDBBADA77A1300000053B0CBCCC3BAB5A3671D00003189B5BCBCAEB5964E0A0000387BA0B3A4938060230200072E83BFCFD8C6C5AE999AAFAFAAA7893D245171570D00000000000963B2A77D3804000201082068C5E9D3A7743C2207244179C4DFEAE3B76320080518B142378FC0C3A660261933251B263E89D8ECEAA560312001082068C5E9D3A701FE6A5E070718A0737573806E523D3D240919587A7F8D998E74626F5C1E1332789FA1A8B49A4E130000002E76A5AEA7A6B77F440C00013692B5D2C4B49D55160D3F8CAFBCB7BBB3822F07123F83A7B7C5BAAEA892460A002486ACC0B7B1AFA6703311000F4689AABDB0B2A7711A0000095DA6CFCAC6BFB9A7731100003587B1B9B8B9B99C550200002B77A9BFAD978969260500002179BBD1C8CCCAB48E99A6ABB3A47D33275A6E4D150000000000005BA3A37C2E06000004141B63BEE5D8A76534151423467FBDDDE7D9B26A2402120EAC493E89BFCDB96B1B112E1C1A1C3993D7F0EAA65A3C3A04141B63BEE5D8A701FE6B5E070718B0706D7782785141361F0017547889949089645471601D10347EA7A3B3BCA358040000003174A7ADBBC2AC7B3E1600003795BFBCB9B39C571F0C408FB4C7BCB9AD793107134485B0C0CBB4B3B198460000247EAAB3A6A2AB996A330B00043985B6BBBCB4A465120000075BB5D2CAC0C4C7AB6F1400003E86A4B3BEB2A5A1560000003A7EA9BCB29290682A0200052480BCD1CACEC4B1908CAEADB1B48B352A6078652800000000001476A8AC843B06000100182F6EC3E6D5A971381D231D4080C3E6EDE3BB6A24050F14AA424B9BCCCEB4701E0F32271F183B91D7F4E9A4613F3400182F6EC3E6D5A901FE6C5E070718C06D727677664442341B00185079758C957E6159725F240C38789DACA9B2965804000000397BADAAB0B2AF7E400A00013C97BDBFB4A5844E1A0E469AC1C5B9C3B68A3200104B8DADBABEB0A8AA983F0A002D83AEBABAB0B19C62200000003F91B9BACABDAF681200000057B2D9CCBAC1C5AB681500003B8FB3B5BAAEB69A530C00083279A2BAB49F8B64250000002B83C0C8CAC1C3A88F92ACB5B3AD873D2B5E75500A0000000000136BAC9C712C000000010C2176C1DECBA76C36130D0D337CBFDBE9DBB0741F0A0B139A424F9FD9D2AC631F16331D13233A94E3F7E49C5E3237010C2176C1DECBA701FE6D5E070718D0807A727A764939411A000B4F6B7B928F735D616B642111367693A5ABB59A51000000003A7B9FA5A6B4B380411300003A8ABAC1C6BD91541309429AAFBEB9C1B7842F04145190A8B5C1BCB5B58E3F00003387AFBBB6A2A7A26B280000003A90C3C9C7B4AA69140000065BAFD2C7C7C7C2A45E140000418FA9B1ADAFAF954B0800002975A4B3AD959065260300003982B9CDCBD6BFAF9193A4B0B2AF7B41375F75500D00000000001672AEA270300A000003153578C8E6CB93632F1D1D253C7BBFDDEED1BC712408070DAD524497CFCEAF691D102A151B1B3D95DDF2EC9C55383D03153578C8E6CB9301FE6E5E070718E0787478767852463F210712567A808F8F7E5D647A6319193F7AA4A0B9B2A14D0C0000002B76A3ABADB2AD863D190001388EBEC4C1AF8C4B140B419BBEC1B7C3AC7B250017529BACB4BABFB0B08D3E00002889B9BAB7B0AE9F662A00000A4389B2B9B6B4AB670E00000B5CB2CABEBBC1BBAC6B1200003F90B0BABBBCB2914403000133749FB4B39F936C290000003089C2C2C7C7CEB99D88A7A7B1AB7A312E647D561900000000001F7DABA8742D00000008092B75CEF1CD9C66301F11273C80C5E0EFE6B4772001060FAB4753A4CED6A65A19142F18141E4098E3F7ECA954252908092B75CEF1CD9C01FE6F5E070718F074877E80775849501E0624577175918F7352537261211E3580ACA7A4AA8E49000000044581A1A4A6B3AB7C421900064C8EB6B9B4AD9059200C4794B9BDC2BFB081320E225B8AA4A6C2B3B2AA8C3F0000327FACB3B3B6A9976123010005468DAEBDC2BBA8610E00000D62ACD4C5C1C3BB9D611200004195B4B0C0B5B18E460000002874A2BCB9AC976C280300003B87C5D3CAD0CAAF8A88AAB3B3A772343254745B2100000000001F75A5A47D2F0800090C1D3078C9E0D49B682F1F161E3577CAE8F1DEBC712402070CA54357AEC9CAB0621F21301D13194195E4F5DEA25D33360C1D3078C9E0D49B01FE705E070718007D736F7B6A4A3E3506001158767888897C52566B57281D4282A59DA3AF99420000000B4375999FAABEB87F441E00003C8ABBBFBAA188430E0D4597B8ADAEB4B2803103205D96B2BAB9B1ADA286360000368EB2BDB0AFAF965D1F0000003D95BBBAC4BAB5630C00000D63ABCCBFBDBBBBA75D110004479BB4B7C6B5BE97400000012E7AA7BAB59D9B641D0200003386C7D1CACCC9AB7F7EA3B1B6A87335326984571F00000000001B7AA6A26C2C0400000C1B2F88D3F2CF966527162A213E79BEE9F0E7B8652804050EA94956ABD1D4AD6217152D191A1D3BA4E0F5E69E522F320C1B2F88D3F2CF9601FE715E0707181073747673674E3C3A1D06184D7175847D744E66755B1C123C859BA5AFB4934A0100000E4D80A2ADA9B4AB78452204003386B2BFBCAF8C460F0A3C9BC2B5C2B8AC782E072A659DAFB9C0ADAEB3934000003C8CB3B9B4B0B0995813000000378EB2B7B9BDB2611200000A5BA5CABEC1C7C6A7660D00004EA5B7B9B7AFB88E490B00022870A5B6BBA2A46F2D0200003788B8D3CAC4BCA17C84A9B2A99D6B3B3D6B885B1700000000001E7AB0A8682A000000060F337DCFF2CF945D25181A29397CCBE1E9D8B667240C0C19A7485EA9DACC915616131A1C212248A8E0FBE6954C3132060F337DCFF2CF9401FE725E0707182088827D767251473F1D051A547680978D73595E815A26114680A6A4B3B08A42010000074F89A7B2B1B0AB77502705083695B9BBACA98A4213053E95A7BDB4BAB57C2E0B29609CAEB9B5B3B2B0913300003191B7C0B2AEAC92551902000B408FBCBBBEBEB6610700000665BBD1BFB5BDBF9D4E0B000C4E97B6B7B7B1B595490000083771A1B7B6AAA16C29070002308BC3D4C7C1C4A57B87A5B7B6AB7A303B6B7D5D1D00000000003083AAA16F3008000205183F85DCEAD29C512E1B202C3E7ABDE5ECE2B16D240F0C12A8485EABD5D4B76C1C1528191D184BA7DDF4E9944D333305183F85DCEAD29C01FE735E070718306B757278744F493F1D00125A7979848062496279561C1B3E80A0A1B2B68A3D0000000C4C7FAAADACB1AB8055250E0A4198B8B2ABB8883609084996BEB6B4B6A66A1C083473A6C3C1BEB7AFAA8D3A00003289B0B4B1A6B1914F1B0000054090BCB7BEB5A35E0200000E5BADD2C5C3BFC5A55707000B57A5BAB8BEAEB69A3E00000829599AABBDB6A36A28000007318EC0C9CDCDC7B27E96AFB7B0A6742F366D815F0E00000000002B81AEA16D270000010A143892D2EBCE944E281B24314780CBE0EDDFA75A1D000816A24B62B0CECAA6702314271D221F4498E5F6E5994B37340A143892D2EBCE9401FE745E07071840767A6F7661423C3A1C011B52726D8A7B604B5C7265271C4A85ADACAEAE8839000000195687A8ADACAFAE7B4D2303063B8AB6BBBEAD8737110C4697BEB5ADAFAC6D1B013B75A0B5B7B4ADADAA8F370200398BB2B9B2A9A48A4C0C000002469BBBC0C1C3AC650500000D5FB7CCCBADB7BFA95E0700004C9BB2B2B5BDC3903E0100052D679FB3C0AAA36D2A000005358FBCDED8CEC4B0798AB0ABAE966B2C3F6F7A531B00000000003186B5A65E28050000051D4791D4E2C78A572817202E5B7FC8E2EFE0B15B1C00050FA65366B5E3D7AF52110A2215171F47A0F2F8E498563536051D4791D4E2C78A01FE755E07071850827F767F6C4D46351000225A717A8279584A637255231D528DADA3B7A58738000000165A87A4AFB3B7A77B562504093E8BADADB8A585400C0E4997B6B8B9B9B26F220A3C789EA3B1BFB4B3A8852A00003F94AFC4BAADA48A54250000003690BDC2C0BAB1610600001366ABCAB6A9BAC89C510900135895B4ABB2B0AB923C030007306A9AB4BCC0A96E210000044097C1D1C0CAC29B788EB5B2ADA7713B417C8152120000000000318DAD9A611E0600040D224693DCE2C18F4B241A1F1F347BBEE2EFD6AA63290B040DB0536CB7D2D4AD5A1E182A251C1E45A4EDFDE191583D250D224693DCE2C18F01FE765E07071860747272715E4140341D031A546E7981775643557552241B518CACB4B4B37C2D0000001F5E8DA7A89AAAA57C5A2B040E479AB3B3B9A57A3D0D095499BAB9B2BAA868220D3F82B3ACB0AEAEACA8852800004397B1B6B2ABA79145100000003F94BEB6B9BCAA600300001560B5DCD2BEC2CAA74E000006599FB9B3AFBDB1883700000C346997A7BAB79E6A2008000B3C99C5D6C7CFC5A07480A8B1B59C6633436F795A1200000000002C89A89B591B000000131A4191D8EDBD854F2013222C3B7AC3DDECD2A8671F0E030BA05071B2D6DDB65C1E0C251C1A2442A1E0FBE98D452E26131A4191D8EDBD8501FE775E07071870746A6D6866444E411B06194F73778378543A587457201F5F99ABB5B5AB7B31000000216592A4A3A4A59D7F55390B0B4A9EB0B3ADA9782D0E0B519FB5B0AFBDAF66210B3D7F9FB2B1BAB5AFA5803100004899ADB3B2B6AA8747140000013E86BDCAC6BBAE530000002166B0CCC1B6C1C59F49020003509DBFB8C5C1B98E3500000D326294B2C4B4AC732C0000074A95BECBC6C7C7A0757CA9B1B0A972313B6F7F5F1D00000000002E8CB2996626060000131C4B99D4EDC78A4C1E1117243E85BEE1F0D6AD61220111109B5B6EB8D7D7A74E160F251D1E1B4CA7EAFEE39B4F322F131C4B99D4EDC78A01FE785E070718807272727361424F3E17021555747A89724C355871471E2B579BAFAFBCB0842E000000236699AEABA0AAA583653404084794B6ADB3A7772F01004F9DB7B8B1BFA966200D418AA8B4B9B6B4ADA379270100489CB8BBB6A89D803D07000000389BC2C6BFBAA1530000001E70B8D3BBAFBCCBA94500000E59A3B1A5ACBDC7943F00000F326595B0BFBBA76B2200000C4790BDD7C8BFCDA16A82A2B1B09F6E35497C8E5E1800000000004593B59E5C1B02030512205294E0DFCA88481E152223417BC9F1F8D6A957280A0C11A14A6CC2E0CAA54A16111E151A1F54B4E8FFE8965A343212205294E0DFCA8801FE795E0707189070745F5F5D494936150D20596C77856A44386177481C24598DA6BCAFAE842D000000296D9AB0A8A5B09F7B5D3302013F99B7B3B1AD7D2F020550A5C1A8ACB9A5651B083C7FA6ADB7BABFB0B27C2400003E95ADC1BDB7B0893E04000000478CB1B9C2C0AE57000000266CB7C9CCB5B9C1A8460000125A9EADAEB3B3B48C3500000D2B5B92AEBBBCA96A1C00000E4FA0CCD5CCC6C19C667A9FAFADA362334675854B0D00000000004596AA975C1C000001091954A2E2F0C67942170E182A4888CFEAEED6994F210F0411A15979BFD3CCA25D1F112017242956ACF1FFD68F47302B091954A2E2F0C67901FE7A5E070718A073796F6D5A3E493A18052450727C876E4A3C59764E1D2A5A96AEB5B6AA781B00000036749CAFA3A3A797795F3A080B489FB7ACADA47A2E030A4894ACB1ADBEB06C1E114E95B2B3B9B8B2AFA2741900004295A7AFADB0A78641060000043A9BC0C7C2C3AC560000002970B9D8C0B6BEBA9F4800001161A7B6AFB5C1B881300001143A618EABBEBDAC67210900124B9FC3C9C2C6B3976F88A3A9A6A06838477B855A1100000000034AA0C0A45E210A01010F2558A9DCEFC77B46190A1A27467DC6EDF2D3A54F1D000E1DA7577EC1DFD7A55318101421222553AEEEFCE490492F260F2558A9DCEFC77B01FE7B5E070718B0746E61655737403211011C556C7B80623D30556F4616296D9EB0B3B8B67B2F000000347DA1ACAD9DA99976613A11104D99AFADB19766240113609CBCAFAAAFA35B1B124D90B2B8B5BCABA5A075250000489AB6B8B4ABA17B31020000063487B3CDD5C5A8570D0000247CB7D9C7A6B3BB9A4000000D62A4B4A6B8C1BF843100000C345C87B2BCB8A8662C00071854A1C6C9C8D5BD936B81ABB5AFA45A32547A855D25000000000850A1BAA45F1E12070006256DB0E3E7BE732E17171D334280D2E9E7D0A25718070D1AA45182BDD8D1A343160E1023251C5AB0F1FFDB934A2B2C06256DB0E3E7BE7301FE7C5E070718C0796F6666543C3C300B001D566E768360322E526D4A1E2D6794ACBCB6A7782B0000003482AFB9A8A7ADA17B663807145B9AABACB7AD7A22030C5FA8B2ADAFB49D551E125589AEB5B6BBB0ADA6732100003D93B4BAAEB1A37331050000014B8EB5C8D0C2A853030000267BAFCCBDB7BECD95310000195F9FA6AAC1C2B882310000173F668CB1CAB5A65F2702000C51A5BFCBBFC7C49C657EACA6B3A4602F51828662150000000008559FBDA666210C0D0D0F216BBFF7EAC37D41230C0A253E7DC9E8F2DD9C501605020C9A527CC7E5DAAC4B0E0A1B17232758BCF5FFDC884C34350F216BBFF7EAC37D01FE7D5E070718D0615D5C655432392C1309234C7376876E352C56653D1A2B65A2B2B5B3A776210000003680A7AAB2A59D9A786F370A134BA2AFA2AAAB782B000D5B9FB4A3AEB0A550140C5193B5C8B8BCB5AA9D75250000489EB3C6BAB0A97027000000054494C4BFC9C0A3510400022D79C0D8C3B5BACA923900001C70ACB8A0ADB9BB8B2F00011C3D598DB1B9B5AD762705001156A5CAD0C5C8C18C5E76A5AAA7945A3E618592521C00000000004BA8C09E572709020410286FBCE5E7B7783A150A161B387FD1EDEFCC9A4A1D09050B975186C9DFD4A24F1A122421162A5EC4F2FFDE86492E2D10286FBCE5E7B77801FE7E5E070718E07263615F52343D2C16172E5A7A848861222A55684921346AA2B4C0AFB06A230000004182A8B9C2A6A49F757049161F4F9BAB9E9D9A641C0011599CC2ACA7B4A050191D5597BEBEC2BAB1AC9D6C2100004794B3AAADAD9E7231000000085194BDBFC7BEAC570700003581B9D7C4ACB1B4883500001A65A69D9CB6B0BD862D00001C456490B4C5CBB2732600000C529FC2CBC9CBC1977078A5B5AD9C5D2C5B8D93532100000000085FA1C1AC6129140B0214366FD1F2F7C1763B1F0D0F203B83C5EAE9CD9B4715131111975B85C4E1CA9E501D092422172452B8F0F6E08442342A14366FD1F2F7C17601FE7F5E070718F078766B5D4A3C483210143666767D7F5F2F2C57643B152C70A5B9C2B9A76B24000000488CAEAEB4A89E8F77714814225CA0AFABA89B622400095299B7BEACB2A4551216528DB1B1B9BDC1B3A674240000579CA9A8A4A7A1712102000002449CC6C6C1C7B3530300052981B9D1C2B0BCC588380000176DADACA1A6B8AB7A2D0000283F6388A6C3C4AC67290000105A9FCBD8CFC2C58E6080ADBDB093613859848C601E000000001360B6C3A55B250D0B0C133175BEECF1BD7B3E120A131C3786C4E8EACB915023080415955490C3DED3944D1D1113211F2364C5F0FCDA8B4A2D2F133175BEECF1BD7B01FE805E0707180072706059452B3F2C0E163065788480592223505F39253078B1C3C4C4A56B1C000000468FB2B8BDB29C917A714F1E1E59A0AEA1A6946119000F59A6BCB3B2B2A44C0D145397B8BBBFC6B6A29765120000569EB1ABA7ADA87223000000034E91B9C6CABEAA57000000338ACBDAC4AEB8B68E2700001573B0A39BA5BDBA82290311333A5783A4B7C0AC6A1E00091858A7CACDC8C1C48F5C7DADB9B29056355E8C915725000000001A6FA6C1A3591E0D0F0A103579C3EEECCA7C381508161D3E82DCEFECCA9B47220E0E17965580BFDACA8D4116161A18212669C3FEFFE089442F30103579C3EEECCA7C01FE815E07071810716C5C53482F3A240F18376580888B592D22545D381F2B74ADB7C5C2B371200000004E9AB0B9B8A597856F714C1C1D5A95AA98A7A26516001467AFC6AAA3AA99450C18579CB9B3BEBBBAB2A76E0F00005AA5B5AAAAAEA06218000000044DA1BCC4C0C8AC52060000388BCAD2BEADB5B8802B0000246CAEAE9DAAB0B876220B102B49608CB5BBC1A65A24020A1B5DA8CCD1C9C9C0986484A2B4B09E6037638387662D000000001C75BFCDA16025190C0D143F7FC9F7EAC274320B0C101E3C82CDECEDC8894B12090E20986686C6E4D39039150F20251F2662D0FBFDDD824A2E2C143F7FC9F7EAC27401FE825E0707182074635654442F2F2C1E203C6D817E85501F225C623B223A7CAFBBB9BAA46A210000004799B3BCB0AFA07E7A784D1914559BB499A79A671B001960ACBDABB2B59E47090E5A9EBAB3B4BBB3B2A9720B00004B98BEA9A1AF9D692400000008469ACFD1CACDA7450000003A91C4DABAA9BAC1821D00002177ABA397A9BDAD7619000B3847647FAAC3C9AC66250500205EA3C3C8D0CCC48D577196ADAF9E573F658B815F31000000001F75BCC6AC5D34220A0A104585D2F0EEC5742C150B1025327FD1ECEFD49141190B08108A5F94C3D9DEA0450E06171F262A67CAF7FFD57D45322F104585D2F0EEC57401FE835E07071830836C5E582D20342A2221456B858D814B1E244657341A3381B2C1C0C2AA6B240000085FA0B9BABBA49B7D77724B1F1C58A3B1ABB0A15D16000B65A9BDAAA1A9994C12216D95BBB9B9BCB1A59A600E000056A6AEB5A5A9975C220000000B4A9FBCCDCEC6A9490500054594CBD5C5B3B8BE871D00002275B1A095AAADAC6B1F00173B52668AAFB6B3A96B1C00051C62ADCAC9C5C9C18B5974A0ADAB9654406B9186612D000000002476B9D0AF632C211A121B3E87C6F1ECB8722D121416233B88D2EBEAC78A45120E0F178D5789D2D3C9924C1A131A141D2972CFFFFFD77C422C291B3E87C6F1ECB87201FE845E070718406E5A423B281D2F301A23386B858E79461E1E4D5D33244280ACBCB8C09F672300000A519DB8BEB8978E82727B521C1765A4AAA0ABA36513000F5DA2BCB0ACAB9A43181B6DA1B5B1B5B9AFAC9E600700045A9DADACA2B0A0611E0000000F5997CDC5C6C0A9560000035099C7DBC9B7B9B77E1C00003079A9A893ABB9B47420001B3D4A6080A7B8BEAF6B1900002870B0CDD2C4C7C0866070A0A8B8924D426982954D2B000000003379BECEA9642E2D1F110F3A94D5F7F3BC7228050C242F4980D2ECE6C58E461A121217885293D1DBC98B451E161E201F2C6FCDFBFFDF824830320F3A94D5F7F3BC7201FE855E070718507D6D53522F1E2E281E374E7E919487511718445C31184682B2BFC5BBA5631C00000E5D9EC1BDBFB693767277491B235C9AB2A5A99F4F0F00176FACBCAEB1B398401326699AB7B5BDB8AEB09E5708000057A3AEA3A9B2955616000000094F9DC9CDD6C3AD500200064D94CFD7CCB0BBC47C1E00002F77A9978BACBFA76211001640596B829BAEBEB25D1C00082769B2CCD5CBC7BE8C527EA9ACAC8C423E608F8650260700000B2683C5CBBA5B2E40271B0D448ACEF9F3C07528121115243B87D0EDE3CA90431B0D0C1A905F97CDE0CC93400C0A161F263270CEF7FFD67F392B310D448ACEF9F3C07501FE865E07071860806C574B282132272133557C82817C4C14124D6037294693B3B7BEBA9F5E12000012609FC1C7B8A08C727781511F2B5FA3ACA0AA99500C0012669EC5BBAAAD90440B206FA3B9B2BEB1B9AFA06212000057A8A19C9FAE955E230000000C579DC4CACCBEA244040016589BC1D0C2B8B2B0782300003586B49690A9C0AC6515002147636987A6ADBDAA601D0001266CB1D5CFC1C6BE8255759EAC9F8E503C6C928C6329070000002B7EC8CFAD582D28190B143F9AD8EEECC06F27080810283C7ED8EDE7C48444160F1B19825A99CEE0C77E45170C15242D2D77DCFFFED87B3E3338143F9AD8EEECC06F01FE875E07071870776C4B47281B28242A36537F8D9B8845131C444E2A1D4883B5BABABC9E571500001267A7CEC4BDAE826B687D4F2D28609CADA9B199611200126C9EBBB8AEB2933C10226DA2BFBCB6B7AEAA94560D00075FA5ABA1A6B39E5317030000125099BDCFCDBFAE3D00000B56A8C9CBBFB0BCB8761A0000267CAFA18FB2B6B0641501264C666880A3BCBCA45C1400012D73B3C2D0C9C8B8835672A2AEA88B553D7688805929010005003980C9D1AF603C2F221217419DDAFCEEBE722208021C263E86D0F5EEC58D4215181A13746A9ED2E0CA84350F0C1F18212D80D6FFFFC9743E2D2D17419DDAFCEEBE7201FE885E07071880735C3A3116141A1C23415B828E92813D1016414022153D85ACC2BDB99A5A1100000D5FB1CCBFC9A78C73757F4D212D65A3B2A9AC9D550900196DA6B4B3B0B0903C11257CA9BFB5B4B9B4AB9C550B00065CA7AD9DA5AB95592000000015579CC5CDD1CBA44A0000095EACC9D4B6B0BDAE6F1600003289B1A18AA2C0B16B180021586664869EB9BDA7582100093980ABC5C4BDBFAF794F759EADB084433F748D8254230200030A2E8CCDD8AA5935361F1217459DD2EBFBBB73381A0912203785D2E9E6C8863C1A100F1C815D9DD2E6C5853B130E19201E2F7ED8FFF5E17A36242F17459DD2EBFBBB7301FE895E070718908262472C1A0C2014244D6781928E923C0A143F53311A3992BCBEBAB499571300001C6AB0C9C1B9AB856B72824D252F73A5ACACAD914C04001A6DB0C7BBAFB68C35061774ABB7BFC1BBB2AB9B5A0A000562A5A5928EA29151100000001053A5BBC5D3D3AF4A0400145AADC7CDCAB5BCA9691000003687AD9C90A6BCAF5F14001C5A73718095B6B1A3551A000B3583B8C2C8C2C4B5855F719CAAA8884139718D8655360C01030A3E94DAD5AA622E3323121752A7DCFEF1BC68250C041627458FD6EEE5C4803820140F157263AEE0E0C780381312171D283889D9FFFCCC853428351752A7DCFEF1BC6801FE8A5E070718A07A5743290F0D231D283F648294977D3C061242482F1F4B91B7C0C1B690471800000C63A6C9C4BDB58C66798A5225366FADB3ADB691520600156BB0C5B8B0BC913E0D2278A2BBBAB0C2ABAD9C5D0900065EA7A38E9FAA994918050000164899C3C6CEBDA5440000226AAFCFDBC9B9B3A9590C0000348DA99889A6B2A9532506205E777B89A1AFC3A45B12000F3D7EB6C9C9C5B9AA7B517797B1AB7642416E928A4F2E0F0A0C144596D1DAAB5E2F362C222456AFE6F8F4B7722C0D110F234787D7ECE7C38841140C0B21705C9DCFDBC1783D1F0E1E232C418AE0FFFCCF7B452A2D2456AFE6F8F4B77201FE8B5E070718B0715A42290811191E26506B858C968041121438442A224695B9C5BFB688481B00001863AECFCFC5A87B6276805424376FAAB5A5AF8F4707001970A9C6B2B1BC91350F2F78ABB3BBB6B8B6AA9C4F0100095FB0B08DA1B6924B1B0000000A54A0C8CFD2C9AC460000156AB6D3DAC9B7AF9C5E0600003D84B89E8EAEC2AC591400205D7C7B8997AAB39C511500062A85B7C1BCC2C6B47F53779AAE97783A3D7496924F341A0D08244FABDED5B3603D3E2F272457B0DEF1F6C17229150C1922428ED8F1EEC47E3A1A1112187960A6D5E8C3702D110D1728313C8CE5FFF3CC793E2F2F2457B0DEF1F6C17201FE8C5E070718C0665A3727130B15242F4B7789949578350910394B220E3A92B8C2C3B9864D0E0000186FABC5C2BCAA806172805C2A3570ACBA9FA9934400002274B3C3B5AEB28C35102685B6BDB8BBB5ACA89B5300000465A89D96A2AE85481202000014519ACCD9C9C0A44400002770B4DADCC7B8BCAB54020000358BB4A28FA9B9A84E08032B677D8081A5B2B3A6540E00053D83B0C3C7C2C0BC7F597693AAA872444970958B5126110B0E1C4AA1DCD8A24E2E372B213062B3EBFFECBB6C230908122B4B93D6EEDDB5843D1B0E081C755B9BDBDBC480390C13171F28398EE7FBF8C8743B37303062B3EBFFECBB6C01FE8D5E070718D0756142290008141D3463748D97A28031091339462B194E97B9B9C5BD883F080000236CB4C4C4BFAF795A6F8956303977AEB2A6A6904400001B7DB0C7B5B2AD8B380D257AB3B7B5C1B7AFB09B5200000B65AAA08D97A1863C0F0000002263A6C2CBD0CB9F3A0000287AB7D2D6C9BDB79D4E0600004292AF9689A7B59E4A0D0C3669887882A4B2AD9D50180008418BAFBDC5C4BFB1785172A1A49D72363D6E898857352013141D58AFEBECB05C394735202061BBEAFCEEC5662B0C0D192F499AD6EBE2BE7A39200D1018736C9FD7E5BD6E2F1916192329429FF1FFFBD677382B2D2061BBEAFCEEC56601FE8E5E070718E073522A1A0000131C405E74879791732800133A46201D4C94BCB2BBAD7B360C00001F70B0C5C6C0A271567789592F497AADB3ACA78E3600002283B7CBB4B1B28C310F3173A5B8BEBEBCB2B2A35205000667B5A68A8EA3893E130000001C609FC3D2CBC2963500002880B3D1D3CAB5BDAF50000000369BBDAE91A8B4A24E0B022D77937E88AAAAAD95500D000E4585A8B5BDC5BFB97B4A6B9CB0A2743C4774978B6A463329283164B0ECE7B464364638273272BBEAFFF2C36625171616274A95E2F1E4B46F351A1B171F736894D1DBBA722E1215161D2B459EEFFFFDC76C3B2E363272BBEAFFF2C36601FE8F5E070718F06C522F1300000C0E3261718393917836000D3228181D448FB6BBC6B57B3B0800001D75B5CFCFD0AA6E59657C552F4989A7B1AEB28A3D0400247FB9CCBFB4C18B340F3880AAB3B6BFC1B0A6935700000A6DA5A4828CAB814A180000002662A8D5C7C6BF97290000207EBCCED5CAC1BD984A000000399AB59F92A9BAA2470A07367492818CA1B7B19F560B000A498EB9B7BBBAB8AF784C6299A59E6B2A468099944E2A28221E2459A4E5EBB369314A2F282E68B7E7FFF5BE65230507081E4B9BE9F6E8B37D33171D111A6B619BCDDDBB782E121A2328294798EDFFF4CD763335372E68B7E7FFF5BE6501FE905E0707180072553210000009133D6C8895A79B6E2501123231181F58A0C7B8C4B676330B02021F66AEC8C5C7A56F57678058344B87B4C0B8AF92440000207AB9C3BAB6B67D2D083383B3B8BDBBB1BCB19C4F04001369ADA1909AA48242120200001F67ABC4D1C7BD972F0000217FB6D2DBC6C1BBA24D0000004291B4A690AFB99B4906003175918A8AA6B9B09A4500000C5097B0B3C2BCB7A171467399B19F6A304382999055262826202658AAE6E7B15E3C463E28326EC6F0FFF4C16D3111141B2E4E9ADFEFDCAC7031141114166355A8D3E0BA71311F13171F2F45AAEFFFF2C372373239326EC6F0FFF4C16D01FE915E0707181072572804000000054268809A999B6C29010B392E141D5199BABCC7AB73300E0201216BABCBD0C4A66C5374835F405A8EB3B4A8A3893900002482B0C7B6AEB08D2D093279A3BEC0C1B4AEB3A25406000D63A7A08392A68B48190300002D71ACC0CDCCC294310000227CBCD3D5CABEB6A04B0000004795AF9D8AA4BE9746130E487D8B9292A2A9AD8E4B0800215896B6B8BEBABAA66E47679EA7905D2F498292825130362C262766B9E2E9AA523A463433417BCDFFFFEFBD6722070D132D469BDEF6E4B36B2B1B160F166862A2D7DEB67729100F1E242743A1F2FFECC56B3C3C3B417BCDFFFFEFBD6701FE925E070718207356340200000016476D969BA2966B1D000F36331C1F54A0BFBBBCB376310201002265A3C2C9C0AB654B698A653D5C98B4BAB6B4853300002F8AB9C4B2B3BA86290A2D85A5B5C1AFB0B0AF96500000117AB09E89919D86400F000000216CACC6BDD1C29A3200002F86C5D7D5CFC8BC964000000A4D8FB39F96A5B89F3C00004586968C8D97B5B09B46000018599DB9B3AEB9BEB36E436B95988A573152809A885843383D2D2A62B3E7E7AB563448372E366CC9EBFEFAC374220D06152747A5DDEEE3B47C321C0A1421685CA4D7D7B6612813191F263051B2EAFFF5CE6F423033366CC9EBFEFAC37401FE935E070718307B6D341200000222526F85909F92602F000C3026111B53A5C4BFC4B36E2E0F090A236FB3CACEC4B16F466B7956355595BEB5B5B780370000318CBABDB6AEB07B2905358DADBEB9C1B7B0B2A04E00000E64AFA68286A080411A0300003166AAC5D0CDC08E3200002480CCD7D8D2B9AE92360000004DA0BDA8A2A9B18539000C4B859B9397A9AFB0984A0D00145D97A8ADB3BEB99F5E476A9AA28D4F294B7D998E4D383A3B343E74C0F5F0B7604441392D3A7CCEF4FFF3BF6C2D11080F2858ADEDFAE0A06642221515206866A5C6D5AE66241810141E2A4EABF6FFFCCC763C30403A7CCEF4FFF3BF6C01FE945E070718407F663104000000174D7D989A99996B24000C2C26172358ADBCBACCA35E200205042B6EB3D9D0D4AB6543698559396099B1C3B4AE832900003596BBC1BFBAAA761F033685ADBCB3ADBEAFB4955000001167ADA28893AA78430E0300022D7FACC4CCCBC48A2C0000298DBDCFD3C8BDBD8F2D0000054D9AC0B09CAFAC8131010D4C8E9C9399A0ADA592450C001B559BABAFB3BAB4AC65406996AC8B52304B7E9E90584444392B4576C6F3E8B06343423F2E3C77CCF7FFFABC682315111A3260ADEBEEDFA760331812171B554C9DDBD3B4662B18141C283355B3EDFFF5C16F3A343F3C77CCF7FFFABC6801FE955E0707185080652B000000001A4D738B929E8F602003132D2D0F1F5BA7CAC8BFAF6B260206082A6DB2D5C6C4A3654F637B593F6BA1B0B7BAA97C260000368AB5C1C5B7B47A280D3489A4BAB9B4BBB0AB93480000096DAAA7888FA7804A190000003B7DADC0CFC7BC8D2100003692BFD3D2D1C5A9872B000002489AB6B6ADBABD903100044E92A196949CABAC9B440D001C68A8B09BA2B5B5A567416C969C8B48324F7F9A8B5546525247357BD4F7EDA7603841382D2E75CEFDFFFFC069261314182F59B1E6EAE0AC6728111811175E70A7DAE0AD65231A191B293150ABEEFFF1BC6A363B432E75CEFDFFFFC06901FE965E070718607A5F2C02000000144C859299928A6213000D202119255EA4BFC2C69F5C290800062D6CAAD6CDC3A565415F76544A71A1C0C2B5AC7B2900003488BBCBBAB8BC85250B3988B0B8BCC1BCB1A7944A00000D69A3A98695A77C3F1E0400023972ACC4CBC6BA8E250000318DBDCDD7D3C8AF7720000007499CBDB5AAB1B18725000E538E9C9D9CA6AFAD8D4306002568A8B1AEB6ADBAA568405E989B7C422C518A9A8F4F4647453D4E8CE3FDE8A75F3F4430293680CBF8FFF5BD672B130F193364B3EBF2E1AE6A29100B0B20566CA2CBD8B05B301323202E3657B6F4FFEDBF76403A3F3680CBF8FFF5BD6701FE975E070718707F652300000000105077948D999B5A11000C2A24192C6DAAC6C8CBA156190900042770BDD0CEBE9D523B657551446F9AC4D3C2B6792200003F8ABDC8CAB4AA6D1C05438EB4BDBDBBC0B7B1903E00000D71A6A4828EA3823D130600084092B4C1C2B9BA832800003B90BDC1CBC6C4B27D2100000B5497BBB7A1B3B58424001966A2A8A299A0A9AA923C07001D62A0AF9FA3B1B2A56B42609291743F306187A69F5044524E3D4687D7F8E0A754334C42363A83D4FBFFFFC3631F1409112655A9ECF7DEA45F2A171D231C5A72B3D7D8A455321D25262A2E5DBDFFFFEEBE6E3931403A83D4FBFFFFC36301FE985E07071880785A320000000017577F919AA790671A000B221F152868AED0CBC19F5318000513336CBDD5D0CAA15A3B576B4F4477A5C4CCBEB6762100003495BBC6BDBAAD6F22063D8CAFC0AFB5BBB4AC974400001473AAA78E9AA47D46150600094485B1BDC3C5BE781500003A99C9CFCBC1C4B5761700000852A1BFBBB5B9AC7E28001260A0ADA598A7A6A28D330300276FA4AD9AA1AAB6A6644A5D93996632285D90A29C52454A533C528EDEFFEEAE5D38433A2B3A8BD8FFFFF2C064262015152E67AEEAF6DA9D623A1C1F1E2C5A78ABD5D5A8652615141B292D5EC2FFFFF0AF5E3A394B3A8BD8FFFFF2C06401FE995E0707189071551B00000000155984918E9589570D000421170A276DB8D0C7C79B4D1D01060D2E72B2D5D1CF9B4F30546B505079ADBEB9B8A9701900003683C2D2C2B5B2771D0F3F90BDBFC4BFBBBCA5974300001377AEA690A0AD81451F0000034A8BAEC9C1BBAE801800002A85BFD2D4C7C2AB6C12000011599FC1C0A8B2B67B200014629EAEA59996A9B18E3F0A003775AAA9949DB1B3A45C4C6090886539245190A38C4E4250533E4589D7FFEC9D582D303126407BE5FFFFF6B560121412162965BEF1EDD0A15D311C1C262B5372A0C9D1A55D261A20282A3D69C9FFFFEAAC65353941407BE5FFFFF6B56001FE9A5E070718A0745616000000000E6187919397894E0900091D1F102970B5C6CDBE974B1C0D000A3875BCD3CDC9A44D27485E495287B5CCC1BCAF6C1800003994C8CFC8BDB07314023B89AAB8BAB8BEB3AB963900001D73AFA48A9FA37C481C08000B4A94B7C6BAB9B06F190000408CBFCBD9CABC9F710C00001C58AACCC1B4B4AE78240014639B9BA8A5AA9FA5903F02002776A39B9095AEB1A46046598A91643331628EA29652455956404389DBFEE59E50424E4036458AD4FFFFF5B86028181C25346DC6EDEDD9AB5F2B16181B2B5877A7D1D1A55B22162027223569C9F8FFE2AF64373A46458AD4FFFFF5B86001FE9B5E070718B068642B000000001667909B9DA0894A0B001120150C3073A8CBD4C39947160609163C83B3CBC5C9974A2D486244487FB0CCD2C7AB6A1A00004B9AC3C7C2BCAF6A12184798B4C0B8BDBFB9B89D3C00001877ADA78A989C7F45280B000F5892AEB8BFB4A5731200002E88B5C2D2C4BDAA690200000F61B0C6C6B9BDB7701C001E65A0B2A5AAA3A4A17E3808003179A0A38794A5AD9A5C39648884602D306297A4A04B4D5C674E559AE5FFEAA556323D3A314C95EEFFFFF9C26924181B1E306EC2F7FED59E5728201C192D4C73A3D9DCA35C2B12292E2C3268D2FFFCE4A95B382B3A4C95EEFFFFF9C26901FE9C5E070718C06E521D00000000186383969A9D834E0A000A16100F3875B5C3D3C6994D19101214327CC4CFC2C1923F29455241578CB0C7C9B6975012000B4C9BCAD2CFC0B46F120E4283A4C3C9B6B2B4AD884000001975B6A69BAEAC89533008000A5095B7C3C3C2B4630800003588BECEBBAEBBB1610500001166B0C7C5B8B7B773100021799FAAA89BACAAA78B2F01043781AFAE8394A4AE9F583D5A897D52253C7198A2945A4F655C505196DDFFE7A44D3A4035204699E6FFFFF4BB5C1F21252E4876B5F1F2CE914827162A1F30557DB0D3CD9B492019201A243E6CCDFFFFD6A8593936434699E6FFFFF4BB5C01FE9D5E070718D07D6623000000001E708D9CA4A88C46120014231A102A7EB8CAC9CEA44F210C09193E81BAD2C8C293422735513C4682B0BEC6BAA86011000A4CA4BFC4BBC5AE6413094892B9BDBBBEBDB6AB8D3B0000187CB4A69BA9B6864D2A15000E5F99B7C0B8B7A7660800003591C4CACBC5BDAA630000001669AEC7C6BDBCBC6B0D001F68A3B3A2A59EA09D833403043B89A7A98895ADAF9A5D365A7882532C2F6A8FA4954D495A59565C98DBFFE19F533C4035345191EBFFFFF6BE63221B24202F6EB1EDF7D290572C1719233D5686B5CEC9984515181D242D3C73D6FFFFE29F553740515191EBFFFFF6BE6301FE9E5E070718E079662A000000001A6D8399A2937C3C0900091709173D7FB9D2C8C396411A0E0E1B487FC3D5CBC793361E374636598DB9C5C2BD9F500F0009559BC3BFC1BFA75D1C0C4199AFBFC3C3B4B3A8994000001778AFAFA1A1B88E52260B00105196B6C6C0BFAA5D0000003694B9C2D0C7C1A34C0000001E6AACC1C0CAC0B8731300226698ADA5AAA7A59D892D00004486A99A838CB0B29855335A806B472B3B7398AB9E57586C7C53599CEAFFE29E53384135374599EEFFFFEBAB51271E242C387BCCF7EFCE8B442316121F40577FBCCFD4964F2D25282C353A75D2FFFED19C533137474599EEFFFFEBAB5101FE9F5E070718F07E702A000000002A77878D989D874710001B1E15114288BDD1D7C39C441E101B2E5D90C6D2C3BF893B1D354439588DB0C9CBC39C4E0B000A57AAD0CEC0BBA7570E0A4693A7BFC2B9C3B2AD893600002B83B2B7A5A3A087532C0D00125F9AB7B5BBB096550000003889B6CAC1C8C4A4500100001D66A7C3C6B9B5A75D10002773A8B4BAAEA8A69D793508003F8AA5A6878FA5A98D4A2C51747143263C779FAFA6545467645752A4EDFFEA9E51303036374B93F5FFFFF3A85C251A1D233F86CEF2F2CC8444210B1110405487B4CBCB924D21231E37353C7AD6FFFFCE8F50303D494B93F5FFFFF3A85C01FEA05E07071800785C290000000029759094A2A1813C0900160C0E0E357EB0CCDACF8F4B1A1214245C9FC8C9BCB68532152C2C36549CB4C3CDBF9D4707001357A2C4C1CDC9B85D12094D98BFC3B7BAC1B6B28C2F00002680B9B5A4AAAF9274390F000B57A1B0B1B5B2A0550000002B86BFC5C4BDB49D530000002773ABC4CBCAC4A6630C002C78A4B3B6AAA5AAA37E300008498CAF9B7C95A8AF8C5C334E63653B213C789BA99D51485E5E585DAAE9F7E1914F363A2E3B4F9EF2FFFFE39950271F21274582D3F8F4CB894C251C1821415388B5CEC890481F252F292B3C75D8FFFFD5934F2C37494F9EF2FFFFE3995001FEA15E0707181073602B00000000267B8A90959E7E40080710110E134A8EC1E3D9C88F412016162F6999C7D0BCBD82341022362F5698B6C4C9BA913E00001658A8C5C4D0BFA1500A0E4E92AABCBFCDC5B9B39D2D00002981B7BEB2A6AA8B6C340D00186398B5BAB8B09848000000308FBAC5CDBBC29D48000000327DB3C3CAC4BCA55806001F74A6A7B0A9AAB0B4832C060B4B8DA6967F869FB0944D2B4A695D2C254581A5B7A5525660624F67AEF0FFE78F4C3633353D52A6F9FFFFE3984D222026254B91D2F8FCD284381F1A2821475096C2D0C083401E1A243235428EE2FFF9C88C4635474352A6F9FFFFE3984D01FEA25E070718207A5B1E000000002E7B90919D997F451000101413135197C5D3D0C5854127221B306AA5BEC6B9B9772803191F245A9CBDCBC2BB953F00001F5DA7C4C7C6B9A856001051A2B7C0C6BBBBB5B08B2C00002C84B7C0B6AFAB976F351000115C99B5B1ADAD91440000004594BCC6C7BFB7983A000000337DB1C9CBC5C19C5602001F77A4B8B1B7ACA9A97F33010A4786A5997F8E99AE884D2D435D56301A4A89AAB6A3515E5F624E6BB0F1FEDD9244353F38344FA4F7FFFFE48D431C1A1A2C4B9BE3FFF7C8774116131A1F424D92C5D9B78250231E2225324090EBFFF2C28949373B4B4FA4F7FFFFE48D4301FEA35E0707183071632300000000347F87899E9B8244090009180B1D519EC3DADBC89348241A223C6CA1C6D0BAB57E23000C19316DA1C6D5CDBD90320000165F9EBFCDD2C2A84F060751A6BECABFBDC3B8B3862C00002C8EBBBFB6ACA7907C521C001C5D999DADAAA9903E0000003090B3C0C8C0B392340000064276B0D0BEC1BCA1510000277CAAB0B7B0B1ACAC80290208478FA5A37E91A5AF9450253A564A241F508BA9B5A15D5367624F6EB0F6FFD98443343C373D5DB4FAFFFFDD9441201E1E2F4E85DDF6EEC48142221F1C305355A1BED1BF71321C18162930458FECFFEACE874D2F3E495DB4FAFFFFDD944101FEA45E0707184075672D0000000031828A98ACA7823E0E00130A05154498C3C0CDC27E472B1E244280AFC8C4C2B47C2E000F1C3168A8C1C7C5B48B330500145EA5CACDC6BBA6500410529BBAB9BEC5C2B1B08B2E0000307EB3BFB6AFAE91794C100013639EA4AFA1A48B38000000419ABDC8C6C3B8842B0000023E82B5CBC7C6B79B4200003A8CAFB7AFBAAFA7A3852600115194A8937B979BA18247303E4B3C23275493AEB7A45F5264614F69B5F7FFD5984B323C313E5EB4F2FFFFDA8940211F25345BABE5FCEBC67945171414204D669DC6D1BB702B16192C2C23468ADFF6E6BA844A364C545EB4F2FFFFDA894001FEA55E07071850706B2E0000000038879093B0A9873F0E091314101758A5CCDAD2C18A492E2F363E7BB2C6DBBDB370210000062A6AA4C8C0BFB4732100001F68ADC6CCD5CCA3500B0B4FA7C1C8BDC1C6B5AD831D0000338EB6BAB1A1A798835517001A6696A0ACB2A67D300000004298BEC8C8C4B07926000008488EB8C6BFBABBA04800003286AFB0AEAEB0B0AF812603135F9BA5A58A96A6A8833F1D35463C261F5890A6B2A35A505E5D5871C1F7FBD384413735343866B6FEFFFFCE7842362422335FABE8FFF4BC6E2C1E141D275B6699C1CFB36E32151A182C354C9CEEFEE4B0794132395166B6FEFFFFCE784201FEA65E07071860757232000000003C9698B0B9B083491F141B1105255AA4C8D7D6C48942383732518EB3C6CFBAB27B160000002163A5C1C9C6B0702000002468A7BED1D2C6994605075DAEBFC8C4BDC7BCAD781800004285BFC1BCB3B09D7C4F1700126495A7AAA49983340000004A90B8CCC5C3B77E1F0000105485B4CECCBFB5984500002980ACB9ADB5ACA7A6782307126098ACA68F93B2A686402430362815265998AABAAE57505D635271BEF1F8D38346382A343E63B8F7FFFFBC73371B1D1B2F60B7F5FFEEC3763A1A1919276462A8CBD2BD662E171D202A30429AEEFFDFA06B49353A4663B8F7FFFFBC733701FEA75E070718707E7A3700000000418CA2AAA5AF85330D03120E0A2661AACECFD8BB84473A302F5495C4CAC9B5B170160000072563A5CAD9CDB86E1F0000236A9FBFC1CABE9A3900065AADC0BEC6C8CAC0B5761800003F8EBFB7C0AFABA08B5821011D6798A9A8A2997D2A0000074896BBC0CDBAB278220000125399B9C9CBC8B6913F0000298CB7B5B0ACAFA7A27627001B5B95A8A290999BA1793E2627322E232166A0AEBAA35154695C5171BCF4F9C07240302E313752B8FFFFF6C17E32201D223F6DBAEBFFFAB96D2C1818242F6369AACADABE6C340F1919283351A2E7FFE0A26F462E3A4B52B8FFFFF6C17E3201FEA85E07071880767533000000004294A2A6B19F883B14050E0D0A2963A7CECBCEC27C453A3A365392AFCAC2C0BC791A0000001F6CB2C3D0C5A6671E00052C70A9BFCCCFC4973B0D0A50A4B5C7C3C9C5B4A67F190000448EB5BEC3B0A293855A16002A709BAAA9A5A17D34000001499BBFBEC7B3AD791C00000B6092B5CBC7C2BF81290000408FB2B4B4B0AB9FA67A290B15619FAAA18D929CA27535162014190F3376ABB4C1AE504A534B5475CCF9EFC77546333D383778C9FFFFF1B35C2F1F17213478BFFBFFE9B164291114132B6168B0BCD0B96C2D19131F2B294BB7F1FFD9A0673826384678C9FFFFF1B35C2F01FEA95E0707189071712B00000000408D9CA5AC9D863907060C0D062867ABCBCBC9A675454D43385E99B6C6CCB7B3780C0000001D60A7C3D1CCA05F1700003277AACBD2D5BA9430000A54A4C1C8C7C5CCC5B06E1700004D96B5BDB9B4B4A79A611C0024719DA7AC9C9B7E2700000E4E9BC2C4C1BBB0701A00001E5F96C6C9C3B9B4802600003A91B0B1B2B5B0AAAE742E051B6E9EACA3958F9CA2713813120F171430749EAFB6A4554A575A527ADDFAF2BF763E3737444976CBFFFFE7B5682F1F17214486C7FBFFEEB2692E211920346A6BB6BECFCF752C1D1E1C292E48A9EEF6CD9E5E3725304276CBFFFFE7B5682F01FEAA5E070718A0727838000000004B90B0BBB1A683490C0A02090C246EB2CFCFCCB875494B443D6AA2C7C5BBB9AA6D0F0000001D6FB5C8C6C3945C0B00083C84B8D6D3CABA8736010E57A3C9CFC3C8C4BEA9630B0009599CBBBBC7B9A7A2925E1D021E6E95A8A7A498651D00001061A9C2C1C9BAAE660A00002075A2BDC9CABCB3782E00004098B7BFBBB9AAA1A36F22031F67A2B8B3989B9F886D3416141413113C7C9EACB0A64E4646494477C9F7E4B36A2E2A282E3E79D2FFFFE9A55A2621161F3B8CC7F4FFF6C469271A1500287971BDCDD1A8572A19191930335EB3F0EFD08D51262A2F3979D2FFFFE9A55A2601FEAB5E070718B0716A2F0000000153A1B4B2B1A6813A0D000406072D71B3BECCCAB2744A4E4C4F65A2BDC2C8C0AB6405000000116AB7CCCAC09F560D00003882A6CBDCC9BB893100105DA9C5C7C5C0C8C1AB610B000B5CA3BAC3B8B6A590966820032A6D95A9A1A19E751400000F61AAC6C2CBC2AF5D0C00001C65A7BEC1C0C2B86B1900004099BBBAB9BFA9A4A4682000247297B8B6A096A49C6D2F0E0603000A3586AEBEB8AD49434A3F457CCEFBE9AB61312D2B313C82D5FFFFE7A750291220213F8DD4FFFFE9B9672B121E26358072B2D6D1AB602A161B192F3752A9EEF8C59150372E304B82D5FFFFE7A7502901FEAC5E070718C072682000000001579BABADACAC7830050C0301113575B3C0C3C6AB69465A4A4D74A4BFC0BEBFB5680F0000001678B2BDCDBC8F4806000A4488B6C9D0CAC38E36001054ACC0CBCCC4C5BDAD650A000B5EA4C7C1BBA9989C955818052B6E9094A6A299701A0000185FA5BEC2C6B2995B070000337FB7C7C0C0B5AA610F00004295B4BDC3ADB6B2A27128082673A5B5B2A297A29A672B0D040000203A8BB5BCB4AC584852525383D8FBE6A365352D37364386D5FFFFDF8F56311C20275193C2F4FFEFB266280F0B17318270B5D3D7B3642B150E1A353666BAF8FCBD794F2D28324486D5FFFFDF8F563101FEAD5E070718D07A6112000000004A96AAB4AAA27C3209000000152F76B3C0CED3AB63505E404E79A0B6BCBDBFAC5C00000000217AB4BEC5B6883800000B538CB3CCD8CABE812800115DB2C6CFCEC5C6B9A95F07001569A2BBBEBCAF9E9C895B1A03307D929AAA978C681400002169AFC2C2BDB5A14E0600003B86B2C9CCCABDA4620D00003D95B0BBADBAB9B4A46C1E0D3174A4C4BAACA39D92683002000000164185B3BFAF9C4D494D4D4C84D3F6ECA45F312D322E3E89E6FFFFDD8E4724322517378BD2FFFFEDAE6022090A153A8B75B9D6D6B556200F0F1D293363BBF8F5B573513B28304089E6FFFFDD8E472401FEAE5E070718E0725C0700000000559BBAB8B399732A080C0100083981B1C7C4C49F5E4A634A4D7B98B3B0BCAC9C5500000000226EB9D2CBAE843E030014639AB0C9CAD5C1852000125BAEB8CECBC6C2BFA45B0500176DA8C4C4C9A5888C90661D002D7D949EA79B86651200001D6AA5C5C3C1B59B460100003C8CB7CDD4C9B9AE5D0C0000449DB8B9B9B6B3ACA65E120D247C9EB5B7B1A29E8A6131070000001D4A8DB2AEB4A35345564D518BE1F1D79F5736342E3F4F96EAFFFBD49048222823234485D0FDFFE5AE58271610193F8270BDD2D7A8542219111D313870CBFCEEB86E49341F293F96EAFFFBD490482201FEAF5E070718F0735900000000065896B0B7AC9B6B2B03070000143980BAC7C9C791585767595E83B1BABEBCB19C52030000002677B8C5C8AD85270000185994B4C4C8CDC27D21000B66B3BED2C6C4CABCA65000001773A9C3C3BAAD9B8E8E5D14043777909AA2A094601100002875A7B8C3CCB88B3D0000003594BBC5C2CAC1B15E0300003F90BAC4C6C0B8B899601C143376AAC0C0B3A89A8966320E000000215E96C0BAB9A2543D413B4E8BD3F2D2A15636282D374D9BE5FFECCB8B5029231B244D9BDEFFFFF0AC541D10131C378F76BECDD6AE54181B100F252E71CAFFF1AE6D3D2D2F394A9BE5FFECCB8B502901FEB05E070718007449000000001A6CA4B8BAADA07435161107021A4289B2C7C3B9955B53685A5181A8C0BFBFB5A04B000000002C8FBCC8CAA3651D00001E609EB9BFCED1C2711B001966B4CBCFC4C5C4B8A84D00002177B3BCC3BDBA8E83945C1906367A98A9A69D8C5F0F00002E7CA5C3C2C3B089390000004693ADC4CCC9BFA44B0000004A99BAC6BEB8B2ADA8621E123C7C9FB7BBB49E917F532B01000000235996B1B1B3AA5B4B4D424E9CDAF2E396492F343D3E55A6E0FFF7CD7F462E1C1C2A4DAEEBFFFFE0A34C1F051722469572C2D8CFA656251A111931336AC3F9E7A96C4515313747A6E0FFF7CD7F462E01FEB15E070718107654010000001C6CA3BCBDAF96682C0D0E08091E5185B2BFC7B793514973536080AAB4B8BABCA44B000000002C8DC8C2C1A4662200001F7AA0BCBFD1C5AA751F001A62B1C0CCC3C5C2BC964400002783A9C4C6C1A289868E5A2213428B9693ADA191540400003A81B9CCC4B8B3822C0000004498BDC5BEB7BDA6450000004D9DBEC5BDBAB0B3A354180D3E82A3ADBEBAA6887B52350C000000275E9BB6B7B2A35C4F4F4A4F92D5FBDC9A5E4335333C55B0FAFFFAC78942211D1D2851A1E1FFFFE1AA5A27161421499E78BDD0CDB54E210F1E2B292373C8F3DE944D353131333CB0FAFFFAC789422101FEB25E070718207045000000001168A2BABBB09E6427111106041A4B89B5C3BEAD7D494F715D5F81B3C0C0C3B9964100000000358FB8C9C097591600002672B2BBD1D3D4B16711001275B6CCCCC3CAC5B9923200003084BECCBEC8B28E858C5718054280969C9E948B510800004790B7CDC6C1B680260000003D95BFC8BFC4BC953C000000559DBFC4C6BFB5BAA051180B3F88A5B2B1AF9F8271533E1600000028639AB4B2B29A514F4256559AE5F5D583483229373C65B4EEFFFBC3733F1C1C2022459FECFFFFDB985020191F2551A477C4D5D0A75A1C15121B343883D5FEEB9B583A2A38343FB4EEFFFBC3733F1C01FEB35E070718306E4500000000136DABB8AFA38C511A060C0803214986B6C4B6B882494D67687188A8B6BDB2AA8F3600000000439CB9B9C79C561200002370B1C1D6D7CBAE680F00136EAFC1D2C8C5C9C18D3D00002F7FA9BFC3BFB187768052140F3F8C97A3A4A4924F0800003E8CAEC0CCC5AE7A1D00000050A5C3CACEBEB793340000085BA7BAC2B3BBBCBCA24F0D114688A4AAB2B2A081615047180000012F74A9BCB1AEA162515C5D64A3F2FFD98D53383630396BC4FEFFF5C281481C20242D48A1E8FFFFCA9B511F1113204B9977BEDACFA5571B15121F293E8DDFF5E29C553926302F40C4FEFFF5C281481C01FEB45E07071840783F000000001768A0C0C0AD90582517151109285592AEC6C0B7723A50745C6D9CB2BBB8B3AE8F34000000005097BED0C2964B0300002C78B5C0BFCCC9AB5F08001778AFC1D3D0CEC4BD8C2D00003894B8BBBDBCAB82798B581D1750768DA3A59B884B000000509BB4C8C2C3B3771700000254A4C1C8C2BBB58C3000000553AAC2C5C2BBBBB89A4D15154687ABB7BEB99F806454450C000005376A9EC0BFB2A2555E554E65A4F1F0D186452B25313D6BC3FAFFE7976C3D2D2C1B1F55ABECFFFFE89E4F1E141B295DA870B5CDCAA258250E1D192F3689DBF6DC8A4A38322C2F39C3FAFFE7976C3D2D01FEB55E070718507640000000002072AEB4B3A38B521E1D2019162A4D88B5C0C2A770364E74626C9BB1C2BDB0AA8931000000004C9AC2C3B887450900002E83B0C0C1D0BEAE5A03001879B2C0CFD2CED0C0842D00003788B1BEC7C1A4737879432625588E91959194873B0000075596B7D2C8C3AB7A1B0000005AA9C0C5CAC5B985330000035EA6C1C9C9C4B7AF984817184D8FABBABEB49A6E544A44170000053D6FA0B5AAB29D5F5D635865A8E9F6C6814A322D3A437AC9FFFFE6AA6D31222127234DABE7FFFFCE904D1912152262B36FBFDDCA9B4D2015130C1E308FDAF8DB874D392B333640C9FFFFE6AA6D312201FEB65E070718606F2300000000266DA2B3A4A3874B1523261B1731609CBEC1BFA66E46516B5D739AADB5ADB2B790310000000049A2C4C6AD8035000000418FB3BECEC6CEAD5711002482C5C6C6CAC3CCB5772E00003F93B7C5BFBCA976727853171D5A8092AAA89C8E430000025A98BCC8C9BBA8710F00000964ACC1BCBEC6C3912B00000B62A9C5CECBBDBCB299450A105196A8B6B9B99D6C4C48450C000008437EA7B8A8B39C5A615E5379BEF4F1CA7C46282A2E4082D4FFFFECB173422C231B194EA8E4FEF6CD84400B13183670B876C5CDD8AD571F161F1C2B4A9EE6F9DA804234272C383ED4FFFFECB173422C01FEB75E070718707C3900000000397DB4B9ADA88547262E3220193B6A93B6BCBAAA65364E71697893B1B7B6B5AD87290000000460AFCACFB8722D000000359AC5CDD7C5C5A64D0000227AB7C1D2C4CFC4B3751E00003E93ACBFBDC4A274687A4E1926618E96A3A094853A00000F69A6C7CDBEC0AD660A00000463AEC9C3C2BAB4902000000A5CAEC4D0D8C9C3BB8B380E184B90A8BFC6B6976A4D4E491300000C4B7A9DABAFB4A268645B5775C2FAF2C88347383C3B4C88DEFCFFE4BA6D40232119235BAEF8FFF7CE8C4512111A2F69AD73BEC5D09D4B211509142A4BACEDF6D68A4626312F3644DEFCFFE4BA6D402301FEB85E07071880722E000000002977ADB4AEA3844E1E31372421456197B2BFB2965D3D526B5C7D9DB0B3A9B7AA721A0000000C65A9C7CBC1822E000004378EBACCC3CFBE943F00001C75AFC5CEC6CCC6AE692400004B95C4CCC9BCAE746A6E441520658C9BA4A99C7C350000136AAEBECAC7CEA0600600000364A8BEC7C2B6B2811A00001D67B5CAC8C7C7BCB98B35061B5C90B5BFC1A794644A565A26000013527C9CAAA7ADA3654D496088CCF6F3C37D4A31323D4E8EDEFFFFE89C65382425282B59B2F5FFF5C07F41201E153170B56FC4D4CA9A451D1C1F242952A1F2FFD28146342A2D373DDEFFFFE89C65382401FEB95E070718906D2600000000357FA9B0B2A28B53273043252E436A91B0BBACA5592D4D625D7BA5B6BDBFB9A77F200000001067ACCEC5B969220000073B91C9D3D2C8C0994100001D7EB8CBD2CDC7C2AC691600004F96C2C6C5BA906364683D182A68989AA3AAA98B3700001473B6C7C1CABFA75C0000000464B0C7CDC8B5AF7E1B00002165B2CACECDC8BBB17F2C0114588FB1B2B6C18E5E48545A2901001D5381A2B3AEA39C6561655D89C5FFF8C585503A3B3C5897E8FFFFD6A668392322253762B0EAFFF4BC73330D141D2F75BB68C0D2CF92451F0D1A222C51ACEDF2D57839241C33354DE8FFFFD6A668392301FEBA5E070718A07824000000003A8CB4B6ADAA864A1E3349332B4A6D8EAFB9AC9850274A625F84A9B3BBBEB3A47F110000001879B3D1C8B36D1D000005498CBFC9CEC5C69B4000001B7DB9B7D2BEC0C5AD570900115A9DBECBBEBB97605B603128327B9BA4A4AD92823400001B74AAC3C5C0C7A7500400000F69A8CACDCDC3AF761400002266ABD0C6CCCCC0B57A2C081B609CB1BAB5B59A6348565F2B00001C5684A4ADA89E8D696C676D8FDBFFFDC3794F3A474C62A1F8FFFFDC93572A1E25253469C8F3FBEDB26F391620283B7AB668BBC5C18B46281F1B1E2E56BDF3FFD77A3C292D36353DF8FFFFDC93572A1E01FEBB5E070718B0762C00000000428CBCBAB7AB824D2D494D39305C7B96AAAEA98D512A3C59638CA8B5BAB5BBAA7E1A0000001F82B8BFCCAD6716000005479DC9CBD0C7B78B300000227EB6CCCCC6C4C49C500800115FADCCD4CEC8985D584F2C1A3A72949AA4A691712400002C83BAC6CFC9B69B590000000569A8C4CCC7C3B9801A00002C74B5C5C3CDBAB5A87726051F66A9B4BFB8BA8C4D3B5F621A00002B5C7EA1B3A2A6976E7369709CDFFFFCC674443D414A5FAEFFFFFFD49A5C301E261B2E65D2FCFFE6B1682C2D222A3E7EBD6AC6D8C892431E1016253261BFF2F8C8633D292427354BFFFFFFD49A5C301E01FEBC5E070718C07F3400000004478FB3B9BAAD894D2D525741445D769EB5AFB08C3D1C3C536386A9B5AEACB3A56C090000002D8DC9D0CABC6610000005428EC1CECFC9BA8D3000002B79B5BECEC3CCC78F4100001869AFC6CEC8CB9A584C52281E41789DA6ABA594712600001987B8CBC5C5B8A0500000001372B5C9C5C2BEB1701200033883C0C4C0C4C8C0A96820001A659FAABFBBBFA557385F5B1B0007335C849BA4B0A7955E6467689BE7FFF5C4744A3F44445CB6F8FFFFD993542C182325386CC8F8FFDEA3672520222F4582BC5AB9D0BE84401A1A1C243665C3FBFFC3703C362325333FF8FFFFD993542C1801FEBD5E070718D0762C00000004589FC5B9B2AC7E502D514D354C6487A7ABB3AA8434143F5E5A96ACAFBDB2B0A56D12000000348FC1CACBB062160000004892BFD1CFC6BF83280000247BBCC8CDC4CBC18F3A06001B64B2C2CAC6BE9057514A2A1E4980A6A3ABAF8C6A2800002D88C3D0CDC5B4A14D0200000F67B1C8CECCC5B4751300033683C2C4CBC9C1BEAE6C13001E68A0AFBEC2BB8C4D375D5820000B356D7F9DA2A2A0856F6C7D79A8F4FFFBC16D4B3B494C62B5FEFFFFE4995D31242A27356BC8F9EBD89B64412A1A243E85BD5DBBCBB47D38241614203973D0F5F2C4663E302E3C3843FEFFFFE4995D312401FEBE5E070718E0792F000000055A99B9BFBBA67F503758594749687697A7A8A383331A33425B96AFB9BCBAB8A56C100000003C98C0D3CBB56614000003569AC1C2C7C8BC762300001D75BFC6D3C5C8C58D3B05002570B5C3D0BDBF844F454528254289B0A89FA2815C1500002588C3CBD0CAC9A54C0000002178BECEC8C1B9B4720C00044690BDCBD1BDC6BCA15308002A70A1B1C1BFB8954D40616026010D366B9096A2A0957E737A818BABEEFFF3BA764E5053566DB0FEFFFFC9974D302A2B27357AD6F6F2D58D57331B26344D91BD5DB3C7B5733B2525282D3980E0FFF7B4603A33293C4345FEFFFFC9974D302A01FEBF5E070718F06C2A0000001A599FBDCABDB4865035526240497082A4A69A9D8126051D3C568CB9BBBDB7B8A363090000004CA5CECEBBAF640500000A57A4C7D7D6C3AF6A1B00002C77B8C1CDD1C4BD7B2700002B7FB5C1CBC4C38A51433B2726417FAAAFBA9B73591800003385BFD7CECBC29A3F0000001670B6CDD1C9BFA76B1000074692C0D7D9C5B9AF9D5F0A022D6CA6B8B3BABB924C40655F260D1A48798B8A959C9B7F74717F83B8FAFFF5B3674A4B4F4D6DC8FFFFFFCD994731292C2A3D85D5EDF6C78B532B1D22304F98CC5BB0C1B16F391F2223304285E1FFFBB5603C3034393042FFFFFFCD9947312901FEC05E070718006C340200001366ABC5C1B7AA7E51456A654E5F768199AAA49F772E0D2A3D5A9AACB9BBBEBBA85C01000000469CBDCDD0B36C1100001564A9C4CCCBCAAD6F1A0000267CAAC4D7D2C2BE6C2000013F87C7C8D3CBBD7C43363525284E90B5B8B2A176501800013A8DBECFD8D1B8A0400000001870B5CDD8C3BDAC630E000D4D94BDCDC9C3C0BC9F500C002B70A9BDC8C6B992514170592805184B748F94A5B3907274868988C1FFFFF2B3734D48484A81CFFFFFFFCF904E2F2D2A2B3A88D7F9EBBC834B2A1F262C589DC15AB1C7B1773C271F1D2B458EE2FAEEAB683A1F2D343C4BFFFFFFCF904E2F2D01FEC15E0707181074240000000F5E9CC0BCC5AE88563A6A5B46577D899FA3A6A27C210A1E2E5492AEC2BFB6B9A55B000000004AA8CAD1C4AF660D00000E5AA6C1D2CCCEB6650800001E7BBCC6D0CBC7B262150000408BB8CACFD0AF80463F361B2E5091B8B8B59A64420C00063E90C0D8D7CAC794450000001E70BBC6D8CFCBAA5F0D00155699C5CEC6BAB7B7933E09062C71A7B7B6BCB1834A4C716A2B0B254D8390979D9E936F6A6C7389C1FFFFE7AF644D474E5C84DBFFFFFFC282461B1D1E2A3F87DDF0E3AD71412D29222953A1C95AB5C8AD6C3424262931438FEEFFFBAC5833293441384EFFFFFFC282461B1D01FEC25E070718207B340900002B7DBCCBCAC8BB875643705B4C668B97979AA09E6E2A03123459A3BEBFB6B7C1A051050000004DA3C9C0D2B35C0B00001B68B2D1CCC3C5A75B0900002989BFCAD6CABFB0630E00004C98BEC8C1C4B66C382C271C356F9FBBB4B79659390300053D91CDD0CDCBC4A745000000257EB3D7D1C8B9A66108021C61A1C4C3CFC3BEBC8C3D02003172ADBAC4C2B19A4D56745E15032A5D858885989C92717C768CABD9FFFFFEC4804F4C50538BDFFFFFEBB77D4530242F355591E4FEE8A67D5430202C365498BC5BADBEA964361F1D2A314B91E5FFF4B259312E2F35433BFFFFEBB77D45302401FEC35E07071830743B0C06013283B7C7C6BEBA905B4B746A6072888F96919B90671A0213265291ABBDB9B6B8A24E040000095DADC7CECEB9660B00001162B1CED3CFBEA64F0000002C88B7C7D5CAC7AC5A13000A4598B9CBC9C1B06A352E2623386AA0BEBDB08F5B2A0C02094799CED1D1C4C59237000000247AB8C9CFC7C4A8621703246CA7C0C3C5CBC0B3833700004487B1BAB7B1AE84505276632D182D62938C83929995646E778394CFFFFFE1A860413B4F5B8ED6FFFFEDBE80442C322A31438FEAF3D7A367402E2B2930569EC259AFBD9A6528171D27294B9BEFFFF7A15432363836484DFFFFEDBE80442C3201FEC45E070718407D42090F102E82C1CEC6BDBB8D574F72656071919A99979CA16A18020F255296B8C9C2B4B098530400000E6DACBECFCEBB5C050000156CB9D6CAC9BF9E520200003184B9D1CBCDCDB4590C00034EA0C4CECDBEB2662D231D1C3F71A7B8C0B490491700000B50A4D5DCD0C5C1843A0000002B85B8CCDFC4C2AF5C0B002671B2C7CDC2BEC5AE772C00033785ADB9BCB3B0894C5876521F1E44708F968892968359747F98B0E6FFFFF5A45E534754619AE4FFFFEDBE7F3E2639332D4C94E9ECDB9E65481D25303C6EA5C855B6C99A532E242828305AB0F7FFF1A7512F2432333B46FFFFEDBE7F3E263901FEC55E07071850703A11151A3A90C3D7CECBB98A5752776E69859B908F949D9D570F0009285498B6B9C4BDBEA14D0000000869B3CAC6CAAF67030000216CB7D5CCC0C0A44F030000307DBAD5D3D0CAAD4B0A002264A6CCD0BFC7A65A2529201E3D72A2BDC2B385441300000F52ABDADCD4CABE95380000033790BED3C7C7CAA24E0A07377EADC6CEC3C7C3B36C1D00003984AABAB4BEB1834B5870521912487E958484969D7F4D6D788FB0E4FFFFE0975A4546566196E5FFFFE1B17140362326304A9CEDF5CE925F39262635436DA7C35BB2C4964E3020212C395BB1F6FFF39C4F3B3433324242FFFFE1B17140362301FEC65E070718606D2E040A152B78AEC7BCC5C589605F70645D859A988D88A18F510B0004204F8FBEBFC4BFBCA14D0000001364B2CAC6CFB0590400002179C2D4D3C6BE9B420000002D85C7D8E4CBC9A44505001A60A5C3C8CAC1A8541E2020234274A4BFBCB27A340F00001560ABCFE0DCD5CA9E32000000378CBFD3CCC4B99F530C083B83B8C6C2C1BDBDA66518000B5086B5B6B9B2B4874B5773501B224A809A887D8C8F734D7B8692BDF7FFFFE094624C4A506399EAFFFFE6AA6F3B2529313151A9E9EFC77E503C3528314A71B1CC5CBDC99F532618292D3C66BCF7FFF3A0442429352F3951FFFFE6AA6F3B252901FEC75E07071870702B1D0D123B8BBAC5C0C7AF875A5776656C8FA49E93939F964305000413519CBBC4C9C5BA96410000002173C1D2CBCAB1580A00002982C9D8D2C5BF993B0000003383BACAD7CFC0924100002369B3CDCBC8BCAA561B191F1D4C84AFB8BDAF7229000000205DABD9E8E0D0CB8E27000003328AC0D9CCCABD994200034187BBCBD2D3C2C1AE62150006458BB1B5BAB5AE7D545C6449171E52869B897C8A9B7D4779748DAFF0FFFFE2965647484C58A3EDFFFFE19F713C2C342D3358A9FAFBC37B4B352628344670AEC960B5C1925034241D2F426DCAFFFFF0A5442F2825333947FFFFE19F713C2C3401FEC85E070718807542201D295393BCCDCAC4BB8D5B5A78687795A39A939094854004000025569FC3CCC7BDB885400000001D76B9DBCBC7A9520500002C89D0D8D1C5B49441000000338BCCDAD4D0CC973000002C7BB8CBCECDBA9E4A1115121F5891B0BDC3AE75250000002066B9DDE2DDD1C8832C00000B4A95BFD0C8C3BA9B4107103C86B8D7DBC2CEBB9E5608000C4A94B6B5B1B7A97C535F72421B235D8B9D8174848F6F416F789CC3FAFFFFE49A584E4A5158A2EBFFFAD6A7703F333A37315AB6F0EBBF7C4F392221354578B4C656B2C6904A2E272128376AC7FFFFEF94462E273539454BFFFAD6A7703F333A01FEC95E07071890783F26292D599BC2C9C6CBBA89595F6D6F85A0AD998B9090883F0700042058A2C9BFC1C5C393410000002783BAC7C9CBB350090000268AC2D5D7CCBA8B2D000000378EBFD6CBCAC6993000003A86C1CDBFCDC39E3E120B13255184B7C5CBAE6C130000072465AFD7E0E1DBC88B2E0000134C8EBDD0C5C7C6903D09104D9BBCCCC7BCC9C69E5006000C548EABBFB7BAB38653586D3F19235B8D9D85798589683579899FC8FCFFFFDB8D5E514A5162AEEFFFFDDD9D623F29363B3A5ABBF0F2C57B46271D2E34437BBBD262C3CC8C3A202223314B6EC9FFFFDE943D293033353645FFFDDD9D623F293601FECA5E070718A0754B2B2427548CB4CECDCCBC815C60726A82A4A89E7F858D7E380B00051E5FABBBC3CBC4BB96400000002B87C4D0CCCEA74F0000003090C6DADAD3C085270000003893CCD9D8CDC3843100003788C2DFC4C7C49B360D02112A62A0B9C5BAB1680A00000B206EB2D4E0E4D5C4802C00000B4990C6CAD3CDBF983A081354A2C7CAC6BCC1BE9C3F0000176397B9B9B9B4B6825060733920326E979F7664768F65256878A0C9FFFFFFDA8258483F4255A4F0FFF4CA9B5731323C333963BFF2EEAF69381F273A344684BFD460C2C9934823262937407CC8FAFFE5943E2E2D34373454FFF4CA9B5731323C01FECB5E070718B07441282E376096BACAC7CDB1875F626B7084A1AB9D81828E742B0000022965A2C9D6CCC6B785380000002D89C6D9E0D2A04C0000003196CFDBD9C5B47D1E000000388FBFD1D5CBC18A2900003D87B4C1C6C3C496410C0C19306C9EB8C1C2AC69090000082976B5D2E0E1E0CA89270000195D9FC4D8CCBABB7D32051755A3C9C9CCB7C2B38C390000125AA0AEB3B2C1B17D5D6A6D2C1D396F9D9C7A6982776C23757C96C7FFFFFFD38D654E434C60ADECFDF3C48B5E3B1E2E37366BC1FBF8BF753F27282D354B8DC7D15FC1CF904A242828384788D3FFFFDA8F41303834354058FDF3C48B5E3B1E2E01FECC5E070718C0703F242C436AA0CDD8CFD3BA7F5C5B66708FB4B29181838F762F0000032B5FA9BFD6CCCAAA7E310000003F96CEDBDEC6A4480000003999C8DBCACABB7D22000000449FCCDCE2D4C1771F00004891BECABDC3B3903A0D01113878A7BDC1BF9D580800000C2D73BAE8D8E0D5C67A240000285C9EBCC2C5C6C98C3603196AA5CCD0C7C4C2B0752B01001C6BA2BDB9BEB5AB7A5166723B184380989C7C66718456147A7B99CFFFFFFFBE7A4E46474B61B9F2FFEAD383523934232E3771C9F0E8AE64362E282E364F90CBDB5FB8C49246232021394389DCFFFFE59045292826283E50FFEAD3835239342301FECD5E070718D0794E3B404874A5CDD1CFD8BE845C5B6A6B94AFC29D7E829B752D000009346EB3D4CECDC3AC7325000000348FD4DED6D09F47080000358FCFD7D8CCBC6D220000004498CED7D8CDB36F18000D4B94D2C3C4C3B784280F06113A7DA5B6C4C0A55001000012347CBFE1ECDADDC1811A0006316CAAC6C7CCC6BE7B27001D5FB0CECECCC1BCAB7D2500001864A7B5BEB5B4A56E4C67673018447C9FA57960757F48097986A9D8FFFFFFD07E595341426AC2F8FFE6B5805A3E2F2E3C4679C2F4E9A3593527202A335999C9D85FC5D38E49251B29334C8ED9FFFFE3823D3034362C324CFFE6B5805A3E2F2E01FECE5E070718E0775252545C7DB3D6DED9E2C78665606C769FB1B497807D896D320504083474BAD7D4D7C7AD6A230000003FA8D6E0E7CBA24106000043A8D4E0D4D0B77C1E00000048ACC8CBDDC5B06412000A4C9BCAD5C9BFBB892C0400133A80BEC3C4C4A14D000000123B81C5DCDADFDBCA841500072D6BA8C0CAC3C0AB7123011F66A6C4C9C2BCB8B16E240000236EADBEB3B9B8AE7261746833204E84999E775D6E715300787F9FD7FFFFFFB67C5C4D48436FBAF5FCDC9F774B362131313E7BD3F8EBA75C2E252E30445F9ED2E468C4CE873D1C1720264096E8FFFFD57F392F302C3A3756FCDC9F774B36213101FECF5E070718F07458484B5686A9C9D8CCD7BC7151585D72A5C3CAA58D898262210200103670AFD2D7CEC0AA67260000003F9DD6E0E1CEA34B07000040ACD7DED7CCB275140000014AA1CADFDDCDAD6613000C5BA4C9C9C3C8C28C2408000D3A8AC2B5C8C196470000001B418CC4E3E1DBDEC371180009396CA2B8C5C0C3AC6A1F00216FAFBDC4C3BBB9B36B120000347EB1BAB1B8B2A37958705E34214F8CA2A274546B6F4D006B729EE5FFFFFFB96F585A484F74C0FBFBDDA8744C2D243A393F84D8FFEFA85A30222C323B65B1D8EC62C3C7832F20261E264498E1FFFFD77F442D3A32364358FBDDA8744C2D243A01FED05E070718006F5D415A6D88AFCDD3D4DBB2664D4E58719BBFC6A5867D855D1F00000E417EBAD4DEE1CEB06A2300000A46A8D4E8E7CA9C450000004BA8DCDACEC2AB6F1300000A55A5DAD3D4CAB15908001253AFCEC9B9C8BA772202000A408CB4C0CFC89848000000174388CBE1DDD8D6C1721900073A7BADBECEC4B8AD7016001F6EB3C7CEC8C0BAA85F0C00003587B3C1ACA9B8A7784C675A372B5C919F9C7150677540008F849FD7FFFFFFBE7355534F506FC3F8FFD19D60432B1E30384081D7FBE69F503833292B386BAFD6EF6EC5CE8336191820334B8DE6FFFEDA7C31222F2F323A54FFD19D60432B1E3001FED15E070718107C6951577295AACDD8DADDBB6E5152566898CAC99882796A4E18000B164998D1DDD0CBC7A1571B0000194FA6DFDEECD0892C0000094FA9D6E4D9C0AD69080000135BB0D3D4D1CB9F4D05001863A2C2CAC4BDAB722300001D4C95B8CAC4BE8F3E0000001D4891CBE0DCDFDAC57A2200084281ADBBC7C0B8A5631803257BB5CACAC5C7B8A75C0400003987B0B7AFA6B9A4735771632E265D94A9A06D485B6830007B7EA5DDFFFFFFB76D4F484A4A85BEF3FAC8895C3D3232323B478BD8F7E3984E2E22262E3A6DB9E1EF70D0CF8C36201F1E3052A0E8FFFFD177332A3938363E5BFAC8895C3D32323201FED25E070718206E5849586794A5C2D9D1D8BB7148464F78B5C6CEA97E766C451100031E4C94CDDEDCD1CBA04D0E0000094DACE2E7E8D08E3300000C5DB0D5E2D8CBA5560A00000565B1DADED1CA9A550B001867B0CDCFCCC2AF6D1E0006104897B7C3CBC18940000000215894C8D9E0E2DAC66C1000174287B7CFCBC1BDA2521100328DBFCEC6BDBBB3A25B0A00003B8DADB5A5B3B1986F596C57262B6593AE9C694A5C663100726E92DAFFFFF89F615A55484D7DC9F9EEB57C4C393726323F448ED8FFE4954F362E262C3777C1DDE96AC9C7853D1A2226274DA1E9FFEDCA6E382944352D2D5EEEB57C4C3937263201FED35E070718307461516A88AFBFCCD7E0DCB66A41435470B1D3CCA586846E44180006215EA7D9DFDCD0C49F421000001656A4DDEAE1C27F2700000F60BFDCD9E1CBA35A0800001267ADD5D9D8C49C4E0A00176AB1CCC5BAC5A96917000014589ABDC4C5B8853500000627529FDBEAEAE5D8BC6411001A4E91BABDC0B8C7A75D15002F7CB3C7D0C7C7BC9E4C0000014395B6BDB7B0AB905E5B6C542B2F6C95ADA067464E5A310077799CDCFFFFEBA76348554C487BD2F8EFBD7F513F382F333E488CE3FEDA894E362F29243D71C3E0F973CAC8823F242521254AAAF2FFF4C26B31273E3735375CEFBD7F513F382F3301FED45E07071840696251657FAEBAC0D7D7DDA65E3A374475ADD9CDA0897F6D451308082154A5D5E2EFE4C994470C0000165DACE2E5E3C77A2A00000F5DBAE4E3E8C29A470000001861B5CFDFD1C2944305001A6DB3C2C6CFC1B965130004114A9EC2BEC2B4853A000004335D9FD2E5DBDFDAC261160025619DBBC3BDBABEA84D07003585AAC1C2C5BDB79E4C00000A4E92ACBBBEB4AB9064557F5D352F669FA8A26C4C5457180077709BE1FFFFF4995B4955444685D7F1E5B7735237232723315397E1FFDE904D31282A334280C5EBF274C9C687351D191D2456B2F6FFFAC2732F2C4946303E60E5B773523723272301FED55E070718507467637192B0B3D0E7E7D9A25F39334D6DAAD6DDBA9581683A130310275EADD9E1DAE0D19D450E0000205FB3E7F1E7C16A1D00001069BFE1E8E4C89F460000001C6FB3D9D8DEC98C3B02032973B3BEB8C1C8A35D140000144F9FC0C1C6B681320000133969A5D9E5EBE2D2B26512002A699EBAB8BFB7BB97430E023183B9C8C6C2BEB89A430200085897B5B6B1A9A9956259774F333E71A0AB9A5E43535323005E5B88D2FFFFE08E48443B304080D1FAE7A6684B2F25212336549BECFDD88E5034221E264185CCE5FA74D3C37D35211F1D2250B1F4FFE0AD5F2B284338374374E7A6684B2F25212301FED65E070718607E6D5D7994BFC5D5DBE0D69C573841527CBBD9D7B59086683E0D03032665BADFE7E6DFC591441200001D62AFDEEADCB66A1C00001C67BFDEE0CDB2944C000000277EBDD8DFD8C0873700002C7CB2B9B9B9C3A3601C00002B5EA0BDC0BDAF722C0000184179B5D5DFE7DDD5C15D0B002F73A5B5BEC6C1BA89420800468CBCCAC7C3C8BD973500001460A7BBB0A3A8A5855B5A6F5133457596A593633D4E491900646690E0FFFFD8874E474C444A84DEEFDAA06647312D291F2F4CA0EBFFDF85492C25182D4B91D4EEFA7CCEC3752F1F2316244DACF0FFF5B6632A29494236396ADAA06647312D291F01FED75E0707187061515A6FA2C6C4CACDDCC8914731334C79B9D6DAB792805A3005030C2F7CC0DFE4D3CAC491390800011B6CB5E2E2E1B2641800002678C7E2E0DDB3863B0400012A80BDD4E0D6C07A2401012B81BCBDB7C3BF96520900001F5EACC4C2C5B0711D00001B5386BFDAE3DCD7D1B3520C00307EB4C8BEBBAEA77B340003559BC1C4CDBEB5B7954200001A64AAC3BBB0A4A4855D516853363F859F9F976236433C02006C6A9EF1FFFFE48C53494D4C4E90E4FDE19A683E3025262E385EA1EEFFD7804F3F2A22264484CCF3FF76CDC375311A1C192256B2F1FFE4AF662927504B313A6CE19A683E3025262E01FED85E07071880736F7389B0CDCCCBE1E7D89A522D2F467BAECFD2B49E7D4F2C0E0A143C7FCAE7EDEBDACF8A3D0300032974B4D7E6DEAE681200062B7FC6E1DAD5AE78300000002F88C3E2DADAB4753004032F94B3B5B4BFBA93520D00052059A9C2C6CBAC6D2400072A5F8EC4DDE1E8DBCCAD510B003980A5C2C1BAB1AA782B0007549AC9C9BEB7B5BF8F3300001C67A6BBBEACA7A1805C5E784C314D83AAB4A155353924010067659BE7FFFFDE804A4B47414E9CE3F4D1915B43433428313C62B1F4FFCE6F3545352D334998D8F2F770CBC57633221918234CABEDFFE8AF5A2D26463B39447ED1915B434334283101FED95E070718907370648AB5D4D6D9E2E8C9873E2E284880BDD8E3C4A6834A2612071D398CD4E8E0DDD4CD8B310700002A6AB8E4E5E1A05D0D00002681C4E5EAD4B07C280000003C92C3D4D4DCBA641F00024285AFB1B2C9C5934B0100002260B3CDC2C2AA6326050E366B99C4E4E0E9DDD8AE5206003D81B3C2C3C2B1B3802D00074E9CC9C9BCC2B2B08D2900002170A8C2B5A9A998745462674C37527D99A3905C3C3C3B000062649FE6FFFFDA8C474A524D4498E6F7D28E5630362D232A3A5FA8EEFBCA753F35392E2E55A4E1F1FF74C1C37C2F16161D2354BBF1FDE3A45821254B312B4379D28E5630362D232A01FEDA5E070718A0787B7B8EC1EDD8D4EAFCD18E402829437BBBDCDCC5AB8450250B0E1B43A0DCE4DAD9D3D091390300002C6FBCE3F6E3AD480E00062982D3E5DFCC996B160000063893C5D1D8D5B4621900063C8DBFB6ADB9BE893D0200022A68B0BECCCAA5641D05143E799FCBD8F0E1DBCDA74B0D145293B4BEC0C4A89D6D2200084D95BEC0BFBEC4BD931A00002174ABBCB1ACA8997651566344415F8DA2A591633E412100006E78B2F9FFFFD691513F574A559FE4F0C68E5A3C30282B2C496AB0F2FDC77A4A4C422E355A9FCEEDF970C1BE74381617141D52B6F0F9D6924D23284F40364287C68E5A3C30282B2C01FEDB5E070718B0756D6683C6E6CDC9E4E2C17B3A26284471B6D6E6D0AA884B270F151D458CD7E6DFE1C9CB92421000002B7BBEDEE6D5A14A0300033086CAF0E8D1A0601600000C499AC3D1DBD6B9541400054591B5A9ADC5B5853F05000B2270B0C8D3CBA14D14000C3377A7D1DCE2DADCCAA643000F5196B8CAC4C2AEAE6821000C66A4C4D2C2C1B8AC812600002D83ACBAB0AB989C74545E5F4743688A999D97573C3F2000005F72C0F7FFFFD38B4C465142509FE6F1CA7F56372D2A27323A6CB5F5FFC36B434736293464A7DBEEE86DCCC67E3A1624211653BAFBFFD18F4E212542433D458ECA7F56372D2A273201FEDC5E070718C08072719AC8EAE1DFEAEEBF7A3A222A467ABBE8E3D7B58844200C0F23549BDBE3DBDCD6C98A35060006337BC2DDE5D6A24C0700062B86D1EADBD69D510B00000F53AAD3DBD9CDA04908000A4B98C7B1ACCCB87233000100236CAECED2CB9D4E0D081D4B8FB5D2EEE2DEDCC39D41000B5094BEC0C0BBB8A16516000867AABDC6C7BDB7B6822500003483B4C0B7A7AB92634C5364424768929CAA9D552B301400006076BAFEFFFFCA7B5151524A4EA4EBF2C67A442B2C3228343668AFF8FACB6C4D58472C3163A4CEECEF6AC5BE77372C1A182B5FB4F2F8CC89462627464030449BC67A442B2C32283401FEDD5E070718D07473668BCAEDE6EAE2DFAF66301D284978B9DFEDCFB7964A25101222559DDFE4D9D5D4C591390B000A3080BFE4EDDC9240070001308BCEE8E3CA99520B0000104FA5D5C7D8DEAA480B000F4F9FC3A8A9BFB46E280000033570BCD9D7CB9A501D00205895BDD8EDDFE1DECFA03100065898BEB9BFBFB5A25A1200115AA7C6C6C0BFB8A87E1C00003F8CB9B7B0A8A28E64415861444D7299B39F9051302A1D00007080C9FFFFFFC98053405A4A54A3E4F7BE7B4C39332B32394367BEEBFCC97041524131396CB6DFF0F76CC2B27737141016225EB8F4FCCA8448292C4332314697BE7B4C39332B323901FEDE5E070718E06A767998D8F3F3E5F1E9B060332425487EC0EFE0D0BC89462517151C53A1DADEDADFD5BF88440E00063C7AB4D2E4D491400F00003996D0EAECCF88440500001258ABCED0D3CC924210001450A3C1A8A6C6AB642300000A306CC1DAE0C3984E1C00185498CCE2E7D2DCCFCF933A05135B9EB3C9C1B9AE9E510D001666A6C1C7C3BDB7A77F1E0000488FB5B3AE9F9B945F4A5C5C4A51759C9DA58E5B2A2F0C00007684C7FFFFFFC37942465D5362B8ECF4CF784A2B222B30323A72C7F7FFCB6B44564C334070B5D5F6FF6BBDB46E20080D1D205CC7FCF6CD823A1B2743413D4CA0CF784A2B222B303201FEDF5E070718F0787C75A0E0FFF4E9F4D8A15D321F274776C3E3F2DBC58B4A280C132758AFDED5D9DED9CB934213000F387AB4D5DEC794430600003F96D3EDE5C4872C0000002168B5D3CED6CD8B2E0000115EB0C4A9B3C5A95A2700000C2F79BAD2D9BC863E0A001B60A6D7E9E4E2DBC7C79730021366B2BCCCC2BBB69D460B03146EB0C1B9B8B8B5AA761800004790B1B7B19E9B85514B5E61465680A2AAA38C5530200500006982C7FFFFFFCF7B3B49584E65A8EEEFC1814E2F262528364777D1FFFEC865425E52262967BADFF6F568BBB0692A140D1E3369C0F3F9C87338262342373D53AEC1814E2F2625283601FEE05E07071800747F7FA4DCFFFFE1E4CBA254221C2C4986BDE1EFDBCF94462711102865B6DFDFCFD9D2C78A360C03143F77B8DCD6CF9341090005429ACDDBDDC385320000000E65BBD8CED5CA8F2B11001860B0BFA4A6C2AB572209000A2F7DC4DED9B77C370300286FAED9D9EEE3DBD5CA9536070F5E9DBCC2CCB9B9904500002276ACCAC9C5BDAFA37412000A588FB5BBB6AA997F543F545E4C5C848D97A2925D3626020000738ADBFFFFFFCF7B59515B4F71BAF5F1BE77533830332C364E7DC8FCF5C762425E4C273474BDDAF0F568C0B36B32191413216ACBFBEFBA6F3B2124353B405DB4BE77533830332C3601FEE15E070718106E7075AFE3FEFFE5F2D39A4F2422214580C5E3EFDBCB96481A1D1E2753B3D2D3D8D2D4C88D3F12000D3882B8D6E4D38F3A0000103F99CFE5DECF842B0000002074C0D2C5C4C58A240000155BA9C8A7B0BE994F1A0000124383D0DDDAB36F3209052C75B6D8E3EBE9DFDBCC922F001975AFB6C4C3BCB1944200003082ABBBBCB1B0ADA77D180005589CBBB2AF9998784B4952575D6893A39B9D8F5F41280000007290DCFFFFFFD67E53544D4959ABF0EBB475423B3A363B3D3E72D6FFFEBF5D515C5634427CC8E5F7F45EB0B26F210D1015286AC3E9EAAF75402121323D466DC0B475423B3A363B3D01FEE25E07071820756976A0E2FFFFF6EBD68F441E1B1F4F82C4EFFAE3DA903E22191E2E67B3D9D3D1D8D6C996431E081A4178B6DDEBCC7E26000000479DD2DBE0CD82220000002176CCDCD4D3CC7D2100002A67B7BCAAB1B991481901041D3886C7DDDAB36F2E08002277B5D9E6EADFE1D3C28C29001D6FA8C2BEBCB9B6903607002E87BBCAC4C0B5BCA36D16000A5A9CB9BAAF9F956F44435C61597190A2918A84534529000000768FDBFFFFFFC774473D564686BEF5F3C67643313333252E427FD0FCFEBA6746635B304478BAE4EFF15CB2A760221312232A7CD6F6ECA86E311F0B31353E6BC6C67643313333252E01FEE35E07071830767275AADCFFFFF7F3CE8C4618162F4A80C9F0F8E8DA9F442C1F1C2659B7DED6D0D6CDC4984A1C03113676B2CFD9D1882900001A519AD5E6E2CF851F0000001A75BED0CDC3B4752000002A6FBDC0AEB4BD86411506081A4A90CED9D6A8682302022B7CD4E9EADED8D2CEC28E2802227FB6BAC1BDC0B78F3400003078ACC3BFB3B7B6B07208000960A1BCBAB49E966E3C41616551709E9F988C855D49220000006E7CD6FFFFFFC4755444495478CFFFF1B76E4634333B37374D82D1FFFFB55E4B6855384186BFD7E9E455B49B5A261800193B81D0F3EDB169402924413C3E75C8B76E4634333B373701FEE45E07071840787B7FB1EAFFFFF0EDC8823B14172A518CC4E2F0ECD99E4F3123272A70AFD3D2C8DED6BD874B2006193C79BAC9D7C8862B00000D47A1D2E3D9CD7A140000002983DFDECECCB9681200021F7CB4BCBAB0B6933C1300021C4C8ED5D8DBA6540F0705348DCFE2EAE3E6E2D5BB8A19012075BAC5C3C8B4A6873100003290B7CCC3BCA2ADA77110001068A1B5BDAAA3986F3C3D55575A7697988E8C7E5D4A1C0000007A9CDCFFFFFFC17D554E57506FC6EFE3AB6340383839363F4483D7FFF9BF5F486249304188C5D7E6F157AA9D64221314173185D9FFE79C5E31222A3A354171C7AB6340383839363F01FEE55E070718507B7980ABF0FFFFFEF9CD7A3A1F1E315D96C9E9FDEED79550372B242F6AB0CACDD3D9CCC78B4B230E1B407CAEC7D6C57A2600001545A2C8E4D7C47417000000308CD1DDCACAAF5A1300003578BBC1A7AFBB863A0A0006194B9FDBDDD1AE4D1401083383CAE2ECECE8E3D3BE741E002778B1C2C8C3BAAB822D0006408FB6BFC9BBB0B3A76D14001F6CA1BCBDAA8E8C5E403C5B5D5F819FA18491876B422700000074A7FAFFFFFFC184514D494675D0FCF3B9634235382D2E39498BDFFFFFBF64496F5E38468CBFDBEBE852A08A5A260F18183687E1FEE49D5A312A3135354778D6B9634235382D2E3901FEE65E07071860777386AFECFFFFFCF9C0713B181B335994D2F2F7F0D990433A36222860ADD4C6C5C9CCC4874B2F10203E6AB5CDD6C5802A00001851A1D1DBDEC36F0F0000002A90D2D8C6D3BD5F1000023188BEC7AABCC483230000001865A8E0DFCF9D4A19000A348BD1E9E4E0DFE2D3BA6F1A0C3484BEB8C3C2CCB5851C00003C81B7C1B9B2AFB3AF6F11001E74A6BEB9AA9189653B455A545D7EA59D8C9C8F644A230000007CA5F0FFFFFFB369463D384875CAFAEDA9614330313B32374484DDFFFFBF604E695533438EC2DFEBED4DA48D531F111A233590E5F5DD8E512E1F213C314983E1A9614330313B323701FEE75E07071870747B85B0E1FFFFFCF5BB6535161D3C6AA1D3ECEEE9DD914E413A272965AAD4CFC8D4D2C1924D2516274275B3D2D1C0702100001456A2D4DED8BC68100000002E8EC4D3CACEAC4F0F00023C88C4C0B6B4C279270000051E5CA9DEE4D49546060007448FCEEBE8EAE4D5CFC07415002C8EB3C3C4C7C2A9721B00004392BEBEB8BAB3AFA76313002477ABBCB4AB9C82532A4263516E81A3987E938F6D4E2F00000077A9F3FFFFFCB96E4D4B43476EC5F2E29B62472C36323D404C92DEFFFBB85C466554374E8DC1DFE8EC56A18950181616204790DFEFD7914C31202C313F4C8BDE9B62472C36323D4001FEE85E07071880727582B7F8FFFFFBF3AC672C1C223365A5D7EFFCF4D99A624B41362D66B5D2C8CBD8D1C48749200C234577A8CCC6C372190000245EA7CED8D6BB650E0000002F8BC8D1BDC1A8470900083C8EC8CAB5B5B7792F0B00002863B0DBE5D18B2F01000A3D96CFE2EDE4DBD5D1BD6F1C072F83B3C2C1BFB9AB74180009549ABBCFC7BCB9B09B5D06002872ACC6BDAD977C3F2A3C625A7790A490738A8A71613500000076ABF6FFFFEAA6664B403C487CD6FFE89A58412E27322F334A87E6FFF8AF5D4C6051414A8AC6E5EBE5589F784A261C15214094E5F7DC8E4821191E2B364B8BE59A58412E27322F3301FEE95E07071890737E8FC1F4FFFFFCEEB667341F24436CABE5F0F9F8DB9354524E363A6AB3CCC6D1D2C4B57F4B2D172C5084A5BEC7AD6A2500001A60A7D2D9CEC0690C0000002B92CDDFC6C19E3A00000D3B86D3CEC2B8C070260400032969B4DDE9C983310600043C98D6EBE2E9DED7CDB16515064092C3C6C1C1BFAD6B1A0003519DBFCEC5B8ACB0A26108002B7BA1B8B4AB906E432C465F57648DAB9269819881693400000083B9FFFFFFF3AA6E484548487DDAF8DE905B3E3A332B32444E98F3FFFFB263475554334B90C6DCEEEA4F987144231D1B24449DE7F6D78F40322A22353851A1F6905B3E3A332B324401FEEA5E070718A072778CBCF2FFFFFFEBAA582917223A75B6ECFFFFE7C58C57494C38306AB5D8D3D0D1CAB481481F1F2C4F83A6CACAB3641E00002A5FABC7CAD0B1660000000242A4D6DCCBC09A3A0000104E94CBC4BBBAB776190000082D6CB5D9E6C07E320000003F9EDBECE9E4DBD6D0B35A09094BA0B9BAB5BBB4AC63060015599EB7C3BFB9B1B29B560C003188B0B4B5A89A73462A4460596E90A68F6D848A82672F0000007DC1FFFFFFF5AB5E473D3D498FDFFFE79B5A3E2F38333C395491E6FFF3B7594B6651365191C7D7E6DF568F733A1E1F181F49A1ECFFDC83462F2727373F53A2F69B5A3E2F38333C3901FEEB5E070718B0768197C7F7FFFFFFE69B562B191D3B73B8E8F7F8E7D08F5F5F5C3E4376BFE1D0D2C8C1BB794C3022335479A9C2C2B1661700002F6AABC6CFC0AD6604000000388ED4DBD0CA983400000952A2CFC3B4BEB0661C0000063372B7DBD5CB7A290000003BA4E1EDE3E3D9CAC6A4561410449CC3CEBFC1BBA7660D00095FA3C0C9BAB4B1AF9C4B00002B81B1BDBBB599753D27395B567399A38B748C8A846F2A00000084C7FFFFFFEFA2623B353A4682DCFCD38C574032393C3D3E5299F0FFF6AB55505B56364D8BB7D3E7E5559074452513252B52AAF0F6D7803C2C2E28342C4BB1FD8C574032393C3D3E01FEEC5E070718C07F7F96C0F7FFFFFFEEA15D35272A5189C0ECFFECE4CA8F62696644366ABBD6D3D1DBC5B17B462622325D7F9AC3BEA6611A0000346CA1BECECAAF56000000043B9DD2DEDBC48D2B00001C5AA6C7C7C0C0B2641B0200093E7DC0E5D9BD71210000053C9EDCE6EADFDACDBC97470605509DB1BDCBBCC3AC610D00166EA2B3C0C2B8B7B8954300003687AEC0B4AA94663C253F646987A6A78A738797836E320000008FD5FFFFFFF0AE6E453D425A94E3FFE59950482E2D413D3B5B9BE4FFF6A55A4B5B4735478CBDCFE7DE4D8B723F291D28285AB8F7F6D27F4435272A343D68BAFC9950482E2D413D3B01FEED5E070718D06E7A91C2F7FFFFF4DB89511C19285685BEE2FDF7E3C98C566561393468B4CED3D0D1C1AA6D4B2923455E91B4C5BE99580E00002E70AAD0CBC1A14C04000001479FE7E8D6C282200000115CAACBCDB6BCA6580700000D3E86C7E7DAB6732700000A43A2DCEDE7E7E1C3B797520C1048A2BBBEC2C4C2AA540000196BAFC1C6BCB6BBB1924908003889B2BBB3A799673E224B615673A0A27F69809B86702C0000008EDAFFFFFFEEA76B4D453F4D9DE4FEE8975139342B352B3554A6EEFFEF96554B62493A4C87BBD8EBE652876D49271C29275DBDF5F5C67D432B2E27394263BAF5975139342B352B3501FEEE5E070718E0727E9AD0FFFFFFFFDC8A43231C335494C2E9F0F2EBD28F6A706E474570BBCED6CAC6C7A46E4B2F2E456385A6C2BDAB5B0D000033679EC1C5C19C4902000004428DCBD7D6C3791D0000216CAEC9C4C4C1AB5D1900000C438CBFE1DDBA651500000243A5D1E3E0EBE1C8BA913C0A1757A8B7BDBBC0C4A14300002E7EAAB8B5B9BBB5AA913E00084B8DADC0BBB39862382C4C63607C9DAE906C8B948E762E00000098E5FFFFFFEA985F453738458EDAFDE0965B47392E2C34364FA7F8FFEC9C543E5941314B88B8DAE9DF4E7F5F342F20203061B8FDFDD3773B292526324070BAFC965B47392E2C343601FEEF5E070718F0797E9EDAFFFFFFFFD3814C1D1B325DA5CEE7F5EFEACC8560838346336EB5C7D5C8C9B69A6C3F38364A6992ACC1B3934A0C00003877A9C4C4C0924600000004499ECFD7DBC2770F00001B5FA8D0C8C3C3AD6B180000115299C8DED0B0661A00000447A5E1DBE0E7DDC1B28A440C205FB3B3ACBCC9BF973D0000297BA6B7C2BCB7B6AF914300034A99B5BEBFA6875526274B5C5D80A5A5866688938F782C0000009FE3FFFFFFD8A462503D3C498BEAFFDA955D3C29232C36425DADEFFFE9A4553A483D314F81B7CCE8DA4F7E5E35251B222864C7FDF6D1813E2B2B2C3D4879CCFF955D3C29232C364201FEF05E070718007083A4D9FFFFFFFFCF853C201B3065A4D5E7F1E6D8C38971878A584B74ACC7CCCEBEB39A653F293F58738FA9B9B79E4E0C00084883ADBDB9B091430000000B4D97D5E3DCBB680800001F64B1C9CCC6BFA7650F0000195398C5DCDAAE591000000047A2D7EDEADCDAC3B18338091A64B2BCB6C1BCC79B4000002B7EAFB8C4BFB5B5AC8C300003519AB6BFB5AD915E25274B5C63839CAE8D77869E93732300000093E9FFFFFFDC8C574B393D4C9DEAFDD98A4F362A303037465AA8F9FFE89C4E475347304F8AB4D7E8DD5C7D583E21191B2A70D6FDFDCB7541382F35394671CDFF8A4F362A3030374601FEF15E070718106F829DD9FEFFFFFFDA79341A13336FA9D8EFF2DED1B87E68968C514074BBD4D6CCCAB48A65433A39587E9FA8B5AE94440D000E5486A7BAC1BE9237000000144D9CD6E0D6BE69080000286EBCD1C7C8C6A6550E000019559BC9E0CBA75C0C00000651A4CEE1D8D7DAC1A4742E0B2C70B4B0B6C1C2BC8A3500002C88B8B9BBBEB9B5A2842A000A549ABCC4B6A78D51232243585F86A2A08E768E9F9A7B280000009AE9FFFFFFD78C5C4035364D9EF8FFCF844F37333032393957B2EFFFED9F4A3B493B404B7FA9D3DCD6597650341F212A366CC9F3FCCC7D3F2F282E2A4485D5FF844F37333032393901FEF25E070718207C8BB0E6FFFFFFF3C36E3423203D79B6D8F3FCF0DEBB7A6F979A5A4B73ADC3CAB9BDB58A5D382F43667C9AA9B8AD964B1D00044686B3BFC0AE822B0000001852A6D5DACFB5580000002175B8DAD6D5CBA45404000012579ACCD9CAA762140000074CA3DBDDE1EAE2C29F692C0E3476BDB1B1BEC5B78A2D00003D98C0C0B9B3AEB9A78835001754A0B9BFB4AA895627204D575B88A8AF88718F9F9B771E000000A4EDFFFFFFD4945F4A43455CA7F1FFDC834834282B32364660B9FFFFE493514142382D47729DC1EBD452785B342A302D3C79D3FEF4BD733A302B333E457FDAFF834834282B32364601FEF35E070718307B85ADE8FFFFFFFDBF6634221B4483C0E1F1F7ECD1B78475968C51497CB4CAD4CFBDB5855440395171858E9FAAA28F43090017578AA7B3B3BD832E0000001B549BC8DBD5B256070000347DB2CCC8C2C39C580A00001969B3CDCED1AA570E00000B46A6DCE0DBD8CDBE945E250C367DBDB1ADB2C5BB8E340000418FB5BBBEB9A9B7AB7F2707155CA7BFCDC2B790532629475A5F7BA0A08E7C8D989B7A25000000A6F8FFFFECCD8F5E392C374CA3E4FFCF7848342B3030364362BAFAFFD785493A3A3D364471A3CDE0D7657D58382B2F22307AD4FCEFB670402B292F3F4687DAFF7848342B3030364301FEF45E070718408290B6F2FFFFFFFBB258311A214E96CEEBFCFCE1CFA576809D955B4874A9CBCDB9B79E764E3B33587C8599A9ACB280421100116496B3B1BBAF73250000001E63A7CDD9E0B9510000093D8CBDD3C4C5B599470000001B69B0CFD8CAA5520500000A49A8E3F3E7DED7AB8C521A0F3B85BAB2A8B9C2BB812500004395B6BBBFBFAEBAB1802A00245F9AB4C5B7AC8A50231F4660627EA3A89681939494741A000000AFFAFFFFF5CB8D5339262A4EA4EBFABE783E3422302F324764BEFBFFD793462A353230486AA1CCE2CE626844363025222F86DAFDF6BE6D3C372F383E4381DBFF783E3422302F324701FEF55E070718507680AEE8FFFFFFE6B161301C1F3E97D2F5ECE3D5C5A16E709E9B57466FAEC3CFBCB3A3744D3B3B5A7C93A2A8AEA47E3D14001A5F9EB9B3BBA96A1E0000002358A3D7D8D0AF4500000C3387BFC3C4CEC1A8580200002770B1C2C9CD9848090000104B9CD0DEDEE1DBB08847190F3E92C4ADA3B7C7BB7F1E00024CA3BFC2C5C1B1AEA6771F052671ABB2B6BBAF8F511C183B525A8BA5A2847F9AA49D661E000000AFF6FFFFF4B1764C3522234AA6EAEDBB76382A1F24302A3D76BDFFFFCE85452425362C48609CCAE6D86A774D352421304085E0FDE8BF76392B2F313E5A9CE7FF76382A1F24302A3D01FEF65E07071860748FBFECFFFFFFF7B2542713204F9FD7EAECE4CFB5936C7EA7995F4D72AAB9BFACB59B66432D3A608B89A4ADB5B68D46160A1C5F93ADADB49F6D190000002663A4CDCBCCA5430000044C93C4D3C3BDB89D540A00002173B6C9D2C48E4104000003439AD2E0E7DBCF9F7C3A111D509EC3A4A9C2C8B87C2B00054DA4CDD1CBC2B7A9A1731600266EAAB9B5ABAE8B4E1F25414D5883A9B196899B978C6019000000B2F3FFFFE1AE7A402F24224EA6E5EFC76B44371E313625366FBDF4FDC4713A2B2A33303E6195D1EEDB746F513437322E3E91E5FFEBB1624335333140639DEBFF6B44371E3136253601FEF75E07071870728DB7F6FFFFFFF7A45023152252ACDBF5F0E4C2B4907380A9995E5477A9B6C2AB9F91613B353564909FA8B0AC9D7C421A0825729BB6B0C0A15A1D000000316BA6CFD4D8A74000000E439DCCD0C1CAC49E45080000247AABC9C5C18F3B000000054A9DD7E0E0D7D1A674261521549CCBA6AEC4CFBB7623000A5CA9C8C6C4B3B1B49E6619022E78AEBBBCB8AF844621153E434C82A4B0A09EABA2966717000000AEE9FFF3CBA36F41261B2541AAECEAB66836281D2B2E333A6BC6F8F6C77833222B23293A6294CBE6D177784C43232D314D93E6FFE2AB57382927273F55A5F1FF6836281D2B2E333A01FEF85E070718807284C0F6FFFFFFEB9A482617225EB1E3EDE3CEC1B2916C8AAE98614D7DA6B9B6A4A087573B31386B87A6ACAFB4A27947170C28759BA7A8B69C50100000003273ABC9DACF9F390000124FA0BAC8C0C1C39C51120000337EC4D3C3BB84370000000950A4D2E6E4DBC79F5C1C142659A5CFAEACBDC3B0701A000B57A3C7C9BEACA3A8A15F18083E8AA9BCC5BFBB964C1A0F3E3D5283AAAFA293A0A1946819000000AFEBFFF2C3875F2E211D1946A3E1EAB763302A26202B344173CFFDF1B873362320282F455688CCE7CE756E513D2A2A2A469BE8FFEAB169302D2C2E465DADF4FF63302A26202B344101FEF95E07071890779AD1FFFFFFFFEB995223162969C0E4F4E9DECEC0936B8EA99A625584AFB8B39C91704B301F3E749CA7B2BCAE9D7441210C33769EA5ABAE994E05000000377DB5D6D6D1A33E00001162A5C6C9C0BEBAA4500300003385AFC8C7B07E33000000034AACDFE2D4DDCC975B180C256AB0C5A8A2C6C5B97720000E62A7D0D6C5B0AFAFA16017083B8FAFB5BEB2A983411423343F537EA5ADA8A29B9A896111000000A4CFEEE6C68750251212193FA5E7EAA85B2F201A232729316BD3FCFAB469362A2828293E5380C7EBC47F78463729312B3E9EF1FFE6A856312C322C335CB3F8FF5B2F201A2327293101FEFA5E070718A07091C8FCFFFFFFED94431B15246BC5F1F0E7E0C2A57E6A929C956A5D80ADBEBBA2846F3A1C243D7B979EAFBAB4976A3F290C2E749FAFADAD924C0C0000044B7BB4D2C8C99B3600001562A7CAC9B9BDBA9C3F0500003784BAC8CBB47D2B0000000B4EA2DBEADFD3C18D4E1C173982B6C3A0AABCCFB76816000D68AACCD3CCAFAEA88D4F090A4495AEB1C2C3B1883F141D3B395794B0B6B0A1A3A38A590B000000B1E8FCE3BC7856271111184CAFEBE2A7553023232527203B7FCCF8F1AD5D2F21252B31475882C8DDC07D72453827292742AFF3FFDDA256322A313C3C67BBF0FF553023232527203B01FEFB5E070718B0708DC0EEFFFFFFEC9D4C150C216EB9DFE6E9D4BDAE856B87A39A745C7BA0AEBB9F90713D1A113675939FAEC4B7955F4524132C799CABA8BE9144000000074B7EB8E3D6CF992500001969A3C6C7C3C1C59C40000000418DB3B9CEAE7D330000000D49A9D6E8DEDBBB854615072F80BCC8A7ACCACDB25C1300156CABBEC8C7B5A8B4964911125A94B1B7C4BEB1853C152138404B83AEBCAA9F9A9D8B530B000000AEDBE8D69E6B451009090845AAE9DAAC511F1A1A21232B3F7DD7F5EFA8572D231D323B405786C4DABB8D6F453224282E4FA8ECF7D7934F28282A35496DC0FFFF511F1A1A21232B3F01FEFC5E070718C06695CCFFFFFFFFE6933B110F256AC7EFF3E5D5C0A883718EAB936F67859FB0B4A088603115133E7EA9A8AFB3B196684C311F3883A2A19BAC8C380200000B5391B5D2CEC6862600002871B5D1CDBABDC99D3F0000013E91BFBBC5B6772C0000001358A5D0DDDFD6BC773E0D053A8EC8D3AFBFCCC79F4801000E6BB2C5C7C2A8A6A3963F030C5898BCBEBFB7B07C2F0914383B4F84B0C3B9B5AEAD8E4D0D000000A0C8D5AF8A522B0A0100053DA0D6C48A3813111020201A3580D8F9E3A5552617222A32495380C0DECB997850322228384EA6EBF5C78C512E2A313C4379CDF8FF3813111020201A3501FEFD5E070718D06D90CDFFFFFFFEDE8F3C13143B80D7E4F5E8D9C6AA836E9AAF94725C82A2B8B397815B1E09153F7B96A8BCB4A08B6755391A398099A1A1AD8E35000000126596BAD4D4CC892400002C71B5D0C1C0C5B7963A0000004097B7BEC1B06C24000000175AA9D9E0DADFBC813B01144294CACBB9B9C8BA97420000116DB4CBCDC7ACA7B0923C011A60A0B3C2BAB0A67A280F1F3840568EB5B9B8B1A9A38E4706000000A0CDD4B68851281303030C51B1E2D488330F0D161828213A74D4F5E19F4D29231D33414C4A77BCD3B5A87851342823304EAAF0F8C68549292B353A5376CBFFFB330F0D161828213A01FEFE5E070718E0709CD7FFFFFFFFEC8E3713143588CAE3EDEFE0C4AF7D6D929B94856E86A3B3C49E7C4F1C0912368F9FABAAB2A38957533525407BA0ABA5AD7A370000000B5197B5D4D2D08E2900003084B3CBC4BDC0B8903A0000024C96B3B3B7A963190000062560A0D7D6E9D9BC682F02195D9FC6DCB7B8CBC0953B0000166EB2CED0C7B2B4AB8B32102060A2B9BEC0B7A26C270E1E2E344D87ABC0C2BBB1A2834200000000A6C8D0AF824522080B000C59B3E5D5913C101615131F2B3E87D5EDD5954B1F1E1D2A43515585C5D6B4A96E4A3A26223153AEF3F3C27F462B2E312E4B7FD7FFFF3C101615131F2B3E01FEFF5E070718F07C9EDFFFFFFFFEDF95451B193486C8DFF3EFDAD0B984768A95887C6C81A8B4B49279411406165390A9A9AEB1A57A615B4E313985A8A19BAE782E0000001963A1C1D0D0C7932500003E8DBAD0C3C1BEB6883D0000014490AAB0BAA6641B0000001E64B2DBDFDFCDAB6721001A5A9CC1D1AEB4C8C791300000166DBDCAC7BAB1A1A97B30112F68AEC4C3C0BCA3691C0A1A38315794AEBFC5C0AD9F8842030000009BC0B9A25F33120000000154AAD6C47B37150F191723243888D7EBD58C3A20241C2136474D81C3DDBEB47F553427222B56B8ECEBBE80442C2F353C538CD3FEFF37150F191723243801FE005F070718007CA6DDFFFFFFFFDA87380F133E8CD0E2E3E7DBC3AC777598988684798EA7ADB0A06938120613488DA7B0AEAC9C7C5D5F4C2D408099A39BA7742C000000206BA1B9CCD0C3842900024190C4CBC1B7B5B2893800000E4D95ABABC1A75B1B000004296CA6D6E5E0DBA55C2200215AA2C8CDB9BDC5BC892E00001077C6D6D5C5B0A8A0832402317FB0B8BBC4C1A86A220E132D3D5885B7C1BAB5AAA48032000000009AC0BF945E30130000000F5CADDEBE69220E061012171C4C92DCF1D388421F1B1A253E4D4C80C5D2AFB57F5238302B325AB9EFEAB06C3A302A28314B93ECFFFF220E061012171C4C01FE015F070718106E9BDDFFFFFFFED07639161C3C8FCBDDE1E9D7CAAD826A888F808C7C7EA5AEB599663601020D4F94B8B4BAA59E6E586859293F7B98A4A3A468230000001977AABFCFC8C48A2C00074A98BFCAC3BEBDB6842B0000015395989FAF9B5E21000000307AB1E7E3D4CAA0551E001F67B8DBDAC1BEB9B47A2800001D77B8CEC6BFB3A69B6D23093885B3B9BDC2B89D641E0413263B5B84AAD0C8BDB7A97637000000009FA9A4885718000000000051ABCEB368220C060A1015224A9ADFEBCD7F361A1A15254E545B83C0C8ADBD7C473224252C63BEE7E1A46D3D2C2D403F5797E0FFFE220C060A1015224A01FE025F070718207CA1E7FFFFFFF1D478381F1F3C8FCACEEBEAE0D0A8726A878B808D8490A8B7AA9A642700000B579AB4AFB3B0966C59684C2E48859E9BA79E69180000002B71AFD3D7CFC27A23000A5C9BC6CBC2BABAA97F2700000453929BA7B398570D000006337EBFE7E9D9CDA7551400247AB8D8C5B3C2BDAF6E160000247AC2D0C9C5AAB0A46E260D4387AFBDC5C0B6A45A1C0C1324345B8AB3CBC6B3B09E6F2F0200000091A4A0733F11000000000051A0C6B76D28000005150F183E94DFEFCA7C33191B1F2A4C42467BBDCDA1B56E493A27292F68C4F8E4A35F33292D293256A0F3FFFC28000005150F183E01FE035F0707183085B8F1FFFFFFFFD17326161949A8D5D7EAEADCC6A2756D847A82928B98A8B8AF9F5D1B0000125A9CB7BDB6AE99715E6D52394780A194A1975E13000000337EABCACDD4B3781C00125EB6D1CFB8B6BAA56F23000005559C9A9DB39444180000083E87C4E5ECDDD5A4500D03297BB8D4CDCCC2C6A8731300001D7DBBCAC4C0BABCAB5D1C06398AB8BABDC2C0A057211116333C5593AEBDC0B8A79F7128000000008FA9A5764410000000000657B2D3BA6724040A0002171C479FE2E5BA772B10151E30485E5783C3CDA0B97A4B382B353069C6F2E29D512B2B29303B66B2EAFFF224040A0002171C4701FE045F070718407FB8EFFFFFFFFFC87737151F529BCDCADDEAD9CAA671686F7882A29A97A3B1AE9B5A1C0000185EA6BFB6BAC2A36B5D6A52385284A89EA493540A0000002472A3BFCFD2BF7718001B72A9BDBEBCBCBFAC771D0000095A8C9797AE94480600000C408AC4E2E9D9CEA24C07003479B8DED4C8CEC7AF600A0000308AC2D2CEB4B8B19B5916084A94BEBCBCBFAE954B151111253F6D98B6C1C6B7A68E6A2800000300849E93642E06000000000660AFC5A85A1900050608121A51A4E4E4B46E32100D142A4F4E4A8CCACC9BBF66422D2E293874C1EBD5925C2E1F2D3A3769B6F7FFE31900050608121A5101FE055F0707185072A7EBFFFFFFF2B36228131A4C9FCED1E7EAD9C2A071606C6C7B9AA198B0B7B696541300001F64ABBDC3BFB491635E75453050869C9EA0A44F01000000307AA8C3CFCFB96F17002474B5CED1C8C1B1A776170000185F7F8592A68B3E070001185391C5EBE5E2CF8F3F08043795C6D9D9CEC0CCA04E000000207BBEDBC9C1A9A3944F0F095598BBC0B7C7C0A4521B00111E366C9EB0BBBFBFA99A6121000001008F9D91682500000000000057B3CBA5651E050204020B1556B1E5ECB65A261320242847595A90C6C69FBE6D4A2E2F2D3C72C8EED496542D2127303C67B2F8FFE91E050204020B155601FE065F070718607CAEEEFFFFFFF0C5732D16234FA6D0D4DEDED0BFA37865656576A2A3A4B9BBB7924F0000001863AABBC0C1B391626A7C55365C99ACA5A29748040000013378A8C8D1CBB8681800277EB8CFCBBBB6B2A86B15000008568891A0A97F410600001A5098C7E3E5DECA9B4308084597CFDCDAC7C4C39E4B0400002783C3D7C4B4A2A4924A0F11549FC8C6BFC3B18E420A0B161E3E709BA9B6C1BCA89D5C1B0000060888928763240000000000116DBBD1AC5A1E0600070E102265B1D8D8AA5B250B181B2A5C5C548DC8C192C17348382E2C3983CDEFD87F472A292A283770C3FBFEE61E0600070E10226501FE075F0707187079A2DDDCE1E3DEA450180A18449EC6D6E4DADABC956150505882A3A7A6B0BCB08F430000001D72AEBFB5B6B88C655F745146698FA3A0A48C3D000000003981A4C3CFD0B55A0F002A85BBCAD5C2BFB8AA650C00000C55808A9AA6803E06000423599DCFECE4E5C6984713014696CBD7CDC9C1BD973C000000328DBFD4CFC3B1A18D42101866AFBDBACBC6B590390E020422456B95B0B8B9B9AC8D55100000060495948C59220000000000096CC0CEB45A1E010900061A256BB5E8D8A95D2913131628575F609BCCC394BD754F3E30314384C6EACC8147231D2B30417DD4FEFFE81E010900061A256B01FE085F070718807EB2EAF2F4F0E2A0552D1A2048A4D1D7DCE5D2BB8A665756517EA9AEA6AEB8AE9041080000237AACAEB6B7C68B646C794D3D6C96A9A4A0883D000000053677A5BBC8CDAB551800348EBFD4C6BEB8B197510000000A52767F97B18A300300022F6AB4CFE6E3D4C682321D1655A6D0D5D2C5BCB88B3E0000003E94BAD8CAC6BEB28B3607185FA2BFBCC5C3B98C380C000A213E7B9FADB9B3B5A5884C0F000012188D9687551900000000001479BBC19B522209000705142A6CC1DFD2A35425110D132F555C5F9ACDBE85C26C4D343635408CCDDAC67A3B1C191B323F79CDFFFFE02209000705142A6C01FE095F070718906EACE0E1D5DFC5965215131B468CC0CAD3DCCCAC886352494B7CA9A7AAB3B6B18C3A0200002C86B4BABCAEB486616A7B574B72A0B2AEA276250000000C3778A4B6CECAB14E13033D9BC0C5D1C0B6B3974B00000010547A8796A9873A0C00102E74AFD2DEE5D5BE833612165CA5D1CFD6CBC8B2811E0000003B99C8DACAC8BAB1832C031465AABBBDC2C6C0863E0C000325477F9FB2B5B6B3AC88400600000E1A918D73521400000000000575BBB99F50240602090F132C82CADECA923F1D0D17173A6566649DCFB185C56840362B32448CCFE4BB683C21222E2E3A8AD8FFFFDE240602090F132C8201FE0A5F070718A075A8D6D7D9DFBD864714191D55A2D6D6E2DFC8A17C55453B427DB4BAAEAEB9AD7C330000003681B4BEB1BBB29166757254486F91A59CA57A280000000B4680ADBBC4D09E4B03004490CED6CECBBEAB8E380000000E557B889BA376300A00083980BADCE7DAD2BA76310D1E69B0D0D5D2C8C1BA78190000003E98CBD5D2C1ADAD7F2B052473B2C8C2BAC3B07A3405020D1F538FA1AEB3C0B7AC8239000000201F899982501200000000001B82C6C998440F0C03080E0F2E84CBE3D1934B1C0C101739676C72A5CAAD77BA6846382D304C91D7ECC1703114172227448BCFFFFFE10F0C03080E0F2E8401FE0B5F070718B076AED6C4D1CFB473441307215DA3D8D9DAD5CBA1725D493B5183B8BBA3B5B7A57229000000388DB5ABB1BBB58C707C654A4C70A4B09E9D7517000000094688AFB9CEC39447110B53AAD2D9CFCAC1B887300000001B5C87879AA576270A00113F81BBD8DFDDD9BB6A25092975B8D9D6CCBFC2B56C190000054D95CAD9CDCEB5AA731F001C77ABBABEC1C6B174320A0007205787A3B0B0B8B7A6792D0000082528888A723F0200000000002B89C4CA9F501C0403030808438ECFE5C6853A0D0811203C717577B1C8B375BD613928292B509DD4E9B5633318171F2E4893DFFFFFD81C0403030808438E01FE0C5F070718C073ACD6D0C7D5B878401B131A4CA3DAE3E3D7CB956C4636344686B2BDBBBDBFAB76210000003E8AB7B3B0B8B78069756B49487BABB2B2A4651300000017468BB1C2C3C88F3A090A60B4DCD4CEC6B8AF812C0000000F4C708E9EB2762D0A0019388ACFDEDFD8D3A6693212307AC4D5CACAC1C5B66814000003519CC7C9C5BCADB16B2C03257AA9C1CABABCAA70290C010C2C5D94A1A6AFBDB8A3682505000E1B2D899382430000000000003090BEC49B4F11000000041148A5DAE6C380381C191613407A7782AEC8B075B86739352C2E51A6D7DFAE60291B161D31499ADBFFFFD011000000041148A501FE0D5F070718D0749AADB0BDC9A8664618112560A3D3DDDFD5BF83594931314882B6C6BEB6B9AD671D000000489AB3ABAABAB27C697A63474D7AA2ACB8A3590D000000205687ADB9C8C18B33040B60B5D5D2D1C6C1B5791D000000185F8B90A2AA6F31030221428DCFE0E4DED4AC631C122C80BFD3D1C7BFBBAA610B0000004BA3C8C9C5CCB8A8651B022A82A9C0BBC7C7AC6928010000215E9FB4B0AABABAA476200100112D3385806E320000000000003388C0C48F4B1100000305124FA8D7DDB4733421120C1A45797184B8C5A368B55E342E2E4362AED8E0A85421161B1D28459FE8FFFFD31100000305124FA801FE0E5F070718E06C95AFAAB0C39E6C35110A24559FE0DBD8CDAF73543C2E374E86BFC7B6B5B19D5B1400000048A0C1A9ADBCB582706C5C3D577EA9B8A994540A00000222698FBDC1CAC58736020B6CBDC7CCCFC1B9AF6C110000001C638A91A5AE69180A0D2D569BD4E2ECE3C8A258130F2C84BFC8D1BFBFC0A85B0700000E63A9C4D5D5CEBFA1590F032E8CBDBEB5BCBEA16A270200082D70A4B0AEAFABAC9E6A1F00000D343A8D846A2C0000000000003F96C5C9913A070000050A2051A9D4DCAF6C2F12111A194F7D7F8BBBC3A65AB1552C232F4670ADDED5A75224192025334CA4E3FFFFCE070000050A2051A901FE0F5F070718F073A6B2A0A7B38D583113101D4C9ECAE2D5BCAC78543028224483BFC7C0B7B2A556090000004AA2B6ADB0B1A16C676D4E3C5089ABADB3935C04000007306C9EB9BCC5BE872B030B6CBFCBCACBC1B39E67150000001C63939AA8A56D230309275E9AC3E2E6DCD9A34E1D103B99D2D4D1CEC3B99E4C0B0000105FA9C4CED0C7B68E4B0600338EBCC9C7C7D0A2682309000631689FA09B9CA3B19A5F1700001D3E3A8A836725000000000000468FC0BF864213000000061F64AED7CDA85B2A12171B215288869ABEC29959B35F3121334E81BAD3CF9F50250F17212B489DEAFFFBC613000000061F64AE01FE105F0707180072A5A593A0A68A593C0D07205A9ECADDCCBF9B6543361A25468DBFCFBAA7B19D55060000065B9CBA9FAFB1A077645F50445D8CA7B7BA9E580000000E377399ADB0C7B87F2D041572C4CEC8CFC1B49F57050000002B6E96A6A6A9691E07172E5FA9D5E4E0E1C88D4E18114291C4D4CFC3C1B9A0460800001B67AFD1D3CDC6B9944301003387B9C7C1C8C1A3582702000C376FA0ABA5A09FA68C5312000013413E797C6925000000000000399BBEC28D3707000000041D71BBDCC79C6124110E0A244C8B9098C0BD9D65BA592A21335685BDD7CC9C5C291A101D2C49A5EAFFF9CC07000000041D71BB01FE115F070718106DA1918598AB7E5C3E180A3165A8CFCBCAC99D62422D171E4286B8C4BDC1B88C420000000C62B0B5A6A3AA99736E66463A5992ABBAAB8D40030000124A809BB3BFC4BE7521031B80C3D5CBCFCDB1A15706000002307696A9B9A85B170006326CABD7DADEE2C496451A1C509DC5D1C7C8BCB0964F0000001D74B7CBCBC6C3B2843D00024097BDBEC1C5C59B622700000634739BA9A08D96AD914A1000001D4E558A856B3400000000000151A8D1BD913A020000000A166CBED7C698551D050A102765918B9DC8C08F4FB05A352C386A93BCD2CE8C39160D1426284FA9EBFFF5CD020000000A166CBE01FE125F0707182077A38F7D8A997E583F160B2A6EA9BFCDCDBD8D4C2C2621274991BCCABCBCAE8C350000000F5EA6B9AAB1A98B67645C4141649BB4B4B69141060000205492B1AFC1C3B4682701227CC1C7CCC9C1A89649000000093A78A4A8B5A55F1700153A72A2D7E2E6D8BD7B3A0D1458ACCDD5C9C4B7BCA0440000002375BCCECAD0C9B68D3500033D94BCCBD0C3BA9055250C00112E769DA8968D979583430900041B545A8785641700000000000055B0D1B98C3D020000001A2D73B8D9BF864B1E0E131331709192A1B7B8884CB5562E253D6D9FC4D6C38D371209161C2F58B6F4FFFABC020000001A2D73B801FE135F07071830739F957F8F9378583D1A112E689DB9C9C0BC86392719251D489AC8D0B6B5A87D300000000F62ABBCB3ACA28B685F534443709DB9C0B08D420000001F5E8CAEB0B8C0B76D22002B83C6C5C3C1B6AC953E0000000B3E81AFBAC0A05512071F4576B3DADDE6D6BF7834071254B1D6DDCBC3C0B08F3C0000003181BDD1D0C3C0BB7B290001449FBECEC7C5D09655240300063777A8A596818B9F8B43100000305D5984815C1200000000000A64ACCBC38B32060000000B287AC9D0C5884516090B263578A2A0AFC0B28050AF4D28274974A0C0CEC7893A1C0E0F17325AB5EFFFF6B5060000000B287AC901FE145F07071840749A88808D8B695841160F2F71A3C2C9C3B17B3813130F19488FB8CDC3B9A77D2C0000001166A9B7AEABAA8B645E553A416FABBDB9BB8D380000002F6096B2B2AEC1A5611A002D8ECBCBC8C7C7B18430000000124196B6BEC3AC580C09164575B1D6E1DAD1AB72340A1F65B0C9C6C5C1BEC09032000000337FB9CBCFBFC3AF7D25000F54A0C6C9C1C4B98D542E12000B3D76A29A96848996863A0500012B62627E7D5B100000000000075CB2C9B9832D090000000D317DC6D2C27535130B10203E7BA4A4B1BCA87940B24D2623467BB0D1D5C68535130D111A2659B8F5FFF7AD090000000D317DC601FE155F070718506A81786F7F7D644E4214102F77A6B6BDC4B3812E0D0F101C4D98C0C5C2B6A56F1E0000000D64A9B6B1ACA573554544364073ACC1BDC48C300000003C759DB9B3BDC09D5213022998CABACBD1C0AB7A290000000F4E9EB8BACBAB4C130B1D5388BAD3E1DCCCB068280E1A77C2D3D7C9BEB3AD802A0000003687BDCDD0CBB8A56720000E5AA7C9C7BCC1B4895E3609000C43719AA690788996732E0400083462617B775A0A00000000000E66A7D0BA812B00000000003687CFD9AD77401110101F418DA6B0ADB99D6F39A84721275689B7CADABD7E2E170F061D2964BEFCFFF4BD00000000003687CF01FE165F07071860798C8070696C5D57400A073474A9BABEBFA365250A0403095498C0C2B5AB9C6D1A0000001763B0C1B5B097744B5344354989B5C7C2B87F340000103D76A9C0B4B9C4A35310062F8DCFB8CBCCC8AD75240000001A589EBEBBB8A44F0A00206090BBD3DBE4CAA26322001F6CAEC3C8C2C8BDAC86280000003D94BEC6C9C5BEA86A1D000D58A5C3C4C7C6B88958290200124A80A0A58C79808B722E0000123B6F75787A4E000000000000146AAEC6B8812F00000000093886C7D1A267331D13131B3E86AFACB9AD986638AC4520275697BBC8DBBD7D2B0C040F192761C4F9FFE9AE00000000093886C701FE175F07071870727D726963594E4A3E070537719FB2ACB3975A150300021246A2BDCACBB2995805000000216FAFB7ADA2936A444A3F2F4893B6D1C8BD7E2D0000124171A9BEBAB4C6A64603053392D2C1C0D0C0B17312000000266DAFC9CDCCA4460A09236398BBCED3D1C1A25D2000206AB2CACCCCBFBFAC752400000A599FBEBFC6C1C09E5A0B001466AABDC2C1BCB88B653107050B468BA098846B797A6E29000319436B757B6C440000000000001879B3CDB77C2600000000024196C1C89D6120100F13223D8BAAB4B9AE966239B749272C5A9CC5CCBDB8772A0D030C1E2765C1F7FFE5A400000000024196C101FE185F070718807489897B71584E594214063B82A7AFACAFA0520E000006105398BEC4C2B0944F090000001868ACBDC2AB88593B3F3B2D4E90C2D5D0BF822700001E5385ABBFC8BFC69D3A0B003AA2D2BEC5C9BA9E600F0000002D6EAEC9D0D39D3B060C307497C1CFD9DAC59E4E12001B77BACDCCC7CFC3AE731900000457A5BBC5C6C3C89D480400145EA5BDC4C1C4BA825F3607021D5A92A69E845F627C6A2E0803194483747F734C0600000000003584BCD3B0782600000000074B9FD1D4A26025060B10144392B4BABFAC8D6531AE46203B6CAABECACFBA7E3107060A162968C1F4FFE6A200000000074B9FD101FE195F07071890718479706647424F3B130A44809EAEB1B29E540E0000002351A5C5C2BBB48847020000001B71BFC9BBA378472E3D352E5592C7D8C8B477240000285E95B9BFB7BBB9963D060A4298CBB7C1CABE955805000000307CB2C4CED290380008397DA6C9D8D1CEBD92470D002C7BBED0C8C7BFC0AC68250000085BA2C0C1CFBFB48D480600216DACC3CAC8C9A37C653914001B508DA29278605B6B5929070419507D81746E41000000000000328AB8BFA76D16000000001353A2CBC69F592108000B1C469EC1B7B6A982502DBB4822306FA9C6D0D6BC7A2F140916222963C7F2FFDFA0000000001353A2CB01FE1A5F070718A06C797072593C3255480B084586A4A1ACAA8C52030000001251A3C2BCBDA28A49080000001E71AEC4B99A723F302E2B2A59A2CBE0DCCC812500001F608CC0C6C1C0BB7E38070C50B1D3BEC1C9CC9243000000003976B7C9CED0A43D00043D7BA8C7DAD7D6B68F380A013686BBCAD3C2B9AFA26C1200001265A8BFBABCBCAE813800002275A9C5C2B7C2AD796B3D0900205B8BA5917E606A70581B000627588882736935000000000000468CB8BAA16C14000000000E61ABC8BB85461C130E10285494B7BCB0AB804D37B5462C306CACC1D1CDBA6D2400000C153673CFF4FBD687000000000E61ABC801FE1B5F070718B06C848078503C3B533606083C74A3ACA5A99C42010000001560AAC1BBBFAA8043000000001A6EB9C6CCA665322C2D303D6BA7C7D9CEB5762800053177A3C2CAC0C6B87D26000C50AECFBBC6C6BD8B3D00000003428AC0C7C6C88E3408104888B5D0D0C5CABB96430E00308FC3C1C3BCC2B69B610D0000186DADC4BEC2C1B481350100226CABC0D0CCC4A26E623F0D03286193988B755C595C4811000D2665917A796C3A000000000011578FBCBF9D5E12000000001364A8CDBA8F5218121413265498AFB7B89B6B442EB54D2B2A6BA2CCCDCCB0722006000B1C2570C8F1E7C090000000001364A8CD01FE1C5F070718C06F7E806D4927284D38090546829AADAAAB8837000000000552A5C1B5B5AE7E3F00000000206BBBD2C09B662A2022232B6ABAE1DFD9C47A1F00002A78B1C3CCCDC2B4752D001551AFD2BCC4CEB38038040000064793C2D4D6C78F2E0315579FB2C8D3C3D2BA8B3B00003990C9C9C9C3BDA696550E00001877A5B8B7C0BCA86A1E00003372AEBDCEC4C79D7C703A09082763949F8A73514E593F1A05082D6D968D71642E0000000000104B8DA6C1A7580B000000001267B2CBC3843A15040707245DA7B6B6B79A723B21B2502F307EB5C7CCC9B37D22090305142E6FCDF9EAC18E000000001267B2CB01FE1D5F070718D06E75776C4423234A31000C447E9EA4A59D8934000000000F5CAFB7B2C0AF7A3300000000217AC9D6CA9550231C1D24336CBEDDE6DABD68180003387FB9D4DECFB5AD6421021160B5D0C0C2CCBA7533000000094E94BBC9CFC98E30000D539AC0D0CACECFB28B370000368DBACACFCACFB19A4A0900002579A7C0B1BDC0B26A2601023C88B4C2C2C1B9987678430D082D6698A497735349482E16050D2D69928B6C623800000000001F689EB1B7A1590F000000001F75B6C7B77F33160604091D5CABC2C2B49D683728B45328397CB2B3C2BBA9681F0B0B0C192771CCFAE9B475000000001F75B6C701FE1E5F070718E07B848D7D31141E422A100D448EB1A3A7A1833000000000145AAFB5AAB3B16D31000000002676BAD2C18C4A1B101C233173C0E5E9D3BF7320000D4C8EB6CCCEBCB9A16611031769BACFC9CECCB36C250000000C539CC7C9CACA7D2B04175698C5C7D3CACFBB8D3903003590C3C6CBC9CBBA95450100002F86AEB9B0BEB8A4661D00063B87ABBEC4CEC39D6A7546120D346B95938D624B493E310E0810376FA38E765D29000000000025629ABDB89A5100000000002783BAD3B5723410000A0E2A63B4C7C2B38C5B3A2CB8512A3C7FB7C3D0BE9D592501040F172F7EE1FFF1B96C000000002783BAD301FE1F5F070718F07D7E857A451A2A4D32000546839EAAB0977832000000001D68ABB8B1BBA87529000000003982C2D6C9833B120B131E3C82CAE7EBD8BB6C19000D4B92BEC8CFC2BDA4621B061E6CBDD2B9CFCBAD651E0000001D62A5CDCCD2D18B27021D63ACC1D8C9BEC2AB7E2E00003F91C4C1BAC5C5B79142070000358DB6B0A8ACB2A3570E00104991B5BAC4C5B291727A45160C3274A19F9866413B3F210507164A799F8C715A2900000000002A76A3B4B28B470000000000368FBFC4A76F30161519114272B3CDCABD91512926B34C2A4688B4C2BAB4994A16000006163385D9F5E4A86600000000368FBFC401FE205F07071800747D81723611293C2B00064A84A6A5A3957025000000001063AEB5A7AFA8723400000000357CCCD5C6803C1110171E317ACCE5E5E1BA5F180311489DCED5D2BFB6965614002266BDD2BDCDCCB2601B0000001562A6C0D4CFCA802406266DB2CACAC8CEC6AF7A260000419FC6C3C9C0BCB08B320000003F8EB7A8A3AFBC9B470900145996BBBEBEC1AE8B7A77441615357C9F9B846B503C2B1E040016407DA38A85733D00000000165089B0C0BC984904000000003E9AC6CFB46923140B10132D71B5C1C3B79051302CB75727498FB3B7BBB197601A000000102B7AD4F6DC985C000000003E9AC6CF01FE215F070718106F858672310E1A402B0114447DA19FA591762300000000176FBABEA7B6AA6B29000000033D85C0CDBE7E3210030A18408AD2EFE7DBB6601C00154DAACAD8D1BFAE91480E052778C6CEC6C4C4A35D100000001D6EAFC8D2D1CA7D1F03176CB2CED4CFCAC5AC853500004CA2C3CDC3B9B5AF792D00000853A1B8BDA2A9B0924005001B6193BCC1CBBBB08677784C17154181989E875F302C28120503205098AE956E541E00000000001F6E9FBCB3873B00000000004C9AC8D1A25B2A0F0408092D7DB2CECEB5874E2A25B648254A94AFB6CBB2894C140200091E3682E0F2D59F5E000000004C9AC8D101FE225F07071820717B7C742B05183625000C4C83A0A29D9B6E2500000000186EB9BDA5B5AC7135000000033E7DC0E0C1842F030002193F8ED3E7E0D5B86324001856A0CDCACFC0B1914B1907347ABFCEC4C7D2A04A0E0000002475B3CFCCCFC6761A09246EB6CED4CEC9C7B3802C00094E9CC7CCC5C5C2A4792600000656A4BDB2A0ABB68F35000017619DBFCCCCBDA7866A80491D1C44829B9D89663C2A190D02031B5591B3956E5B2B0000000003418AA6BA9E6F3E00000000054FA0BEC0A4501D130D080F3382CBCCC4B58D3B282FB04C34509CB9B9ABAA8D4A160400040A2C83D1E5CF8C5A000000054FA0BEC001FE235F07071830747A7C7127041A3728000744809AA5A1946D24000000000E6AB6BDA7AFAC6C2A000000063484C2D1C9752300040A1F4591DDE0E0D6AF600E03245A9ECDD3CFC2A78337060D2E84C5D8C8C9C2984A110000002678B2D8D4D6BC741F032676B6D1CFCFC3C7B4862D000341A7C4C4B9C3C3A0782E0000085CA6BBB7A8B5B88A2A00002867A3C2C4C7C6AA74707C45112056839FA394573E2C16060009285C8DB49376562600000000084687ABB6A7823C000000000964ABC8CD9D4E20170D10193781BECFC6B08A44241FAA4F345B97A3A5B2A28C49120000000D328DDCEEC288510000000964ABC8CD01FE245F0707184086888F7A3409193A20001C4F7D9EA7A39C661A00000000166CB0B3B1BBBA8026000000123F87C9D7C5731A000003254C9ADEE7E5D8AD5D17002166A8CBD1D1C0AD802B08093B87C0D1C6CDC48D3C070000002979B9D1D6D9B56A200B3275B6CBCDCACEC3B8883200044AABC7C7C2BCB4A87A2300000B5AB4C5B5AABBB67725000026639FBAC3C8C3AE7678804515234A88A89E9266441B12080009235B94AB9968481700000000034E87ADB0A47C3C050000000F68ABC5C69A43100F080A133F8DCBD1C9B283362922B14B2B5A9DB4B0A9997037170101081D3A92DBEDC9835D0000000F68ABC5C601FE255F070718507484806C25000D291404164475999C9697681D000000002573B4C2B0B9B38229000000024785C2D6BB7320040004174AABD9E1DDD9AD451B061A5DB3DBE6DAC8A16E2C0B0E398BC4CEC4C9C08534010000002780C7D1CDD1B66C200F3F85B0D2D6D8CCCAAC8028000655ACC3C9D0C5BFAB6A1D000012639AC1AEA0B1A7721B00003572A5BEC8C5BDA8706D77501E255A8BAEAE9965361F050000082A679AA18E6F5D2800000000105D90B4B9B47A30000000001A6CB2C6B492641C1E1204134B9CC7CCCAB97C3F1E1CA6462D639DB9ACA994663208070005183386DEE1B877490000001A6CB2C6B401FE265F07071860798E87671C00162815052552809698A290650F000000001D84CBBFA1ADB9792E000000164B8FC4D5BF68200000062051A2D8E3DED5A8541A0A206DACCFD3D1BA9B6C230D0F408FC2D6CDD4C0862D000000003480B9D0CCCDB05E1C0C3A7EBBD8DDCFC8C7B48125000150A0C7C8CEC5C1AA6B1800001373ABB8AEA1B5AD791700003874ABBEC4C3B89873627D50282F6195A9A59A6D3416010000072F6697AD8F65461400000000064D91A8AB996729000000001566B2CEBC913D1612120E1A4FA1CCCEC6AF8C342920A7463076A8B6B0AA9260360D000005153D90D8E4AD75470000001566B2CEBC01FE275F070718707B7E7B612004182914031E4D7A8BA1A28D6512000000002A80C3C5AFBFB87D2E000000095097CBDDC16D1A0000001A58A6DBE5E4D49F430F01256FBDDFD5CCBB8E5A15070C5091C2D3C7C6BE862E030000014482C1CECBC6A05D1805378ABEC9CDD5D9CABA8820000657ADC6C4BEC3BEA6641E00001473BACBB5A3C1AA6C0E00003274AEC6BCC3C19E776D77431F296C9DA59A985E2912010000062F73A2B197664B190000000012618DB2BAAB792A000000001E7BB4CDB78035132C23121852A1CBCBC4AC7732231AAA433972A3BAAB947A63290700010D1A439CE4DEAB5D490000001E7BB4CDB701FE285F070718807C847C712E09212C1211315D7A909C9D915C1300000000287EBEC2B6BBBE872E0000000F519DC8D1C268140000001A57B2E0E1E0D5993810072D70B8CADAC8B88E541A02134E91CAD1C8CBBE8623000000073C7ABAD1C6CBAB4D0E083D92CFD6D4CDD0D0B3812800185DADC9C8C5C1BAA5640E0000116FB6C5A7A8B0A3621100003F87B4BCBCCFC69E726B7F4522336E98B1A796663211000000023674ADAE8867651A000000000B5491B5B19F6B2B00000000277EB7CABC7B4326230D11236599CDD7C8AC73381A11A5453B76B3BB9D8C754C12000600051B418DE1E1AB5F42000000277EB7CABC01FE295F070718907476696812000E170605305280979E998C4900000000003287C4C2B0B4B38B2A000000125B9DCBD1B4620C000005285DADE1DCE2C28B3B0B073380C0D8DACFB67D4A0D00174A98CECFC5C1BB761D0000000A4387C4CFCCCB98460C0E3A92C2D5D6D5CEC4BC7C22000F66ADD1C9BEB6B79F5D1A00001A73B7C6BAADBBAB690E00064B8FB0B7BEBDBB9A6A716F411E307696ABA78F622D0B000000083C7BB0B08964471600000000116490B4C19C6928000000002F89BACCC3882F0C2118042770B2D1D0CAA86D33221BA7453C7CADAFA083754C230000000F19419DDAD9964F3C0000002F89BACCC301FE2A5F070718A0707A856C2B081E2914223F617D999F98965F0D000000002D87BAC4C0CFC69631000000135698CAC7B061120000002966B4D8D9D6D1923C180A3A8BBFD5D1D0C17D3505000E5795C9D6CBC8BC701A000000173B87C4D4D3C29348090E4C88BED1D1D6CEDAB87721000161B7D6C6B8C1BC9F591600001F7DB4C7C0ADBAA15C01000E5289AAC8BDB1B58D5A6A6943313D76A1A3A38E5F2C080000000E3A84A4A98F62541900000000196B9DBDB49D682800000000288DBFD2C87E2304271E12296EADD2D4C9BD6E330F0DA04F4F83BAAEA4805D3B1502000310215099DED39A563A000000288DBFD2C801FE2B5F070718B07D867E691C00171A061846678499AAA485490200000000337FBEC5C3B9B0933A0000001860A3CCCCAB5C0E000000246BB7DEDDDDC5853210123281C3D7D8C9AD733108001763B0C8D0CBD5C1711B000000144C8BC4D2D1C48A430C0B3B95BFD1DBD8D0CEBB7421001666ACCECCC7C1BD9F5A1100002083B5C5B5B0B89E500000085A92B9C1C6C2B992636C6640223D7B9CA29F8B622A0900000013437EA5AB90704C10000000002573AABBBCA56D1A00000000408FC3CBB1732E0B28200E2D79B4D6D4CAA466281114A844578EB3B59D775832190307080D2754A4E9D1914F22000000408FC3CBB101FE2C5F070718C079716E651F080E0E00164C687F8A9F9E7F4300000000003481C3CCC4CCC6983A000000206BAAC5C7AC59090000002469B5DBD5D7B87A2F11113D8BBECDD5C3AF722D00002363ABCED8D0CDBF65150000001A4CA1CDD7CFBD8038030C3986C0D1D3D7D6CEAF641500136FBBD0C0C8C1B5AA520800002983BBCAC4BAB89D420000195898B6BEBAB7B7855C687242314C80A1AFA3A1612308000000174087ABAF92603D0000000000236EA2B1A9936018000000004A99C8CAAB6F2A122E1700387EB4D0CBC3AD6B29140CA4585D8FB1AE8C6E4F2409000D07152750B4E9D48748310000004A99C8CAAB01FE2D5F070718D0767673530D000B080014576F7C959D94743C00000000003182BDCFC8C7C9903B000000266DA4CBC9AF580B0000002F81C0EBDADAC7751B01133A91CDD0D1C3B26D1A00001B5FA3CFD1D3DABC65130000001A4D98C5D6D4B6793409144B84BAD0C9D7DACDB1680E00106CC1D2CEC8CAC2A04B0400003291BDBEBAB0AE9F44000014669AB2BABBB7A77E526C6C462F578CA3AA968D6124040000000A4392BAAE8F643D0500000000277CACBDAEA0631600000003539DC7CBA97125112416083A89BAD3CEC49D6C270F0FAB616D93BDB08A6847240B060803071555A2DDCA834B35000003539DC7CBA901FE2E5F070718E0666C6A4D17040A0B031E5F737A888F8D7E3300000000003187C0C7CEC5C094340000002A6CABC5C5A457100000012E84B4D8E2D7BC6C250F164C9BC1C8C9C4A7651D00002473B5D1D4CDCDBF5B0C000000295E9CC2D0CBB6782602114A90B7CADCD9CDCCB3630E001874B8D2CBC2BDBC9C47000000308DB8BEC4B6B0963F0000216997AEBCB9BCAD76506064432E488CA9AFA79B60250E000000184E889FAA8B66450F000000002481B1C7B8A25C1B000000015EA8C8C7B4752516231B14498DB2D2D6C7AA61230D15A05777A4AFA57F62310F0B000506182157AFECCC8648340000015EA8C8C7B401FE2F5F070718F078716C51190D1E08053370867988978D6B2E000000000B478AC6D0C8C6B990360000003778AFBBBBA45A030000003287CBD6D4DDB95F1F07144797CAD7D2C3AC601800002F7FB3D4DCD1C4AA58070000002565A4C6D7C4A86C22010E539EB9CAD4DFD6D1AB5A0B00197DB9C9C8C4B9B597450000003B8CB9C6BFB4B895360000156198B8BEBEB8AB785654674A22518FA7B0AA9D6320000000001A5A94ADAC93624100000000001D7FA6B5AC8D4F100000001263ADCBC9A462160A301A184891C2DAD0C58F682B0F0A956E80A8BAAB795030100500070A0D255CBAE9C5863C2D00001263ADCBC9A4 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 61440 61440 0 01FE305F070718006C6E64450E020A020627677A848B9B84621C00000000094194BFD0C8C7BF90370000003C7EA7C3C1A34B000000023A8DCDDAD3C2AC58130C194C9BC7D0C7C4AB580600002D7CB7CDDACCC4AD5E1E010000316BA7C3D7BFA15B19070F4E8CB6CBD6DED9D1A35405001A7BC0C5C6CBC8B79E410000003D94BFC9C3BDB88B2D000021739AB8BBC0B7A36F54636941426298AFAAA39D5B230000000319498FB6A988604200000000001E86BCC2B89A5C130000000E65ACCCB3985411122C1C1B4699C2D3D3C29D59220816A77484B3BAB27A562B0D00000E1821245CB4E2BE6C403100000E65ACCCB39801FE315F070718107E807B63170B11090C3A778C8C8F968A61240000000014508ECBD9CBD0C58B3A00000E408CB1C2B9A154040000003A90C9E3D7D0A34F0F05184A97D2CECAC1A3510900003F87BAD7CFCDC5AB64160300002E639ECBD4BF995A1D0012509FC4D0D4CEC9C4A2500C00227FB8CFC2C4C2BD9938000008439CC2C4C5BDB38A2C000030759AB5B7B2B0A164485A60463F6A94A5AEA3985D1C0000050E1A508BA0AF94623E00000000002B88AEBBB38D4D070000001875BAD1CA994B120C19161C53A0C6D4CEC0975C1C040E9B6683ACC4B5743F1A060000030F212E6EC9F4C16E332800001875BAD1CA9901FE325F070718208086754911040D0610437595868D907C530B0000000011549EC3CCCECCC296320000075192BDC4BCA657030000044396D6DED9D2A54D0908205DA9C4CFC7B997460300003A8DBECCDED8CEAB5A15000004396CABC1C9C294481001135195B1CCD4DBD5C78D3F01001D7BBDC9CCC6C1B68E3B03000C5098BCCAC6C5B8802400003379A0B6B9B8B5A36448575F474B6790AFADAB99571B020002081E5C97ADAA955E3C00000000003D93B2BDC7995D120000002683BDCCB48F4C140E221E235DABCCD2D0B68F4C1900139A7793B7C0B0723A1A0000000A0B222670BFE5BC76413200002683BDCCB48F01FE335F070718307473704C120401010F46859E8D868C7A4A1700000000195A97BDD8D4C9B98834000004498BB5BDB3A05600000000459CCFEAE2D2A04B0B072B69AAC8D1C2C399460000033C8CC1D3D5D7C9A9510E00000F3D74A8C7CDC0893E0B00135792C3C5CBD3CBC3973C00002884BFCDC2C0C4B3923400000C5297BBC1C7C3B97A2900003E7F9EB4B7ACA895664460594A5079A6B7AAAE8C59260701041025669DAC9D8960380000000000398FBEC2B79C54140000002983C1D6BE89460E0F26201E61AFC6DDD0B6904E1F0D1A9C7D9EBABAA76D361B0A00031212112F74C1E9B868342800002983C1D6BE8901FE345F070718407B77754D0600050010447A9787868A6B4012000000001B5990C1DBD7CAC38B340000165F9BBEB8ADA14C050000004498D5E1D7D58E3B0607256BA6CCD9CAC6903A0000084991BDCAD3CCBD9C46100000144D80B0CAD0BC823A1100175DA1BBCBD2DECDBF8B360000217FBAC3CAC3C4B78A3100000A58A1BEC7C3BDAE74200000447D9DB1BAB3B496574B546752446A9FA8A6A89A601F0B0902052956A3A7AB90663000000000004596B8C1B6904F15000000318EC4CFBA854A0F14201F1863AECED7CFB8934F1A051A967AA2C1BB9E692E070400000913252A76CDEAB66537270000318EC4CFBA8501FE355F070718507071705019090805185485A58F828A713C0D000000003169A3C2CED2C8BB913300001E5FA6BBC1B69F4D0100000C56AAD3DEDFC3933E05092672B6BFC6C8B88B310000055B9ABEC7CCD1C39D490D020011558EBEC5CFBC7F320400105B99C2CCC8CDD1C3832D0000238EC4C9CDCCC1B1803400001867A5CCC9BFB7B06E1A00004484A3B3B6B3A1955C455C5940507DA8AFABA495551F040600142B67939B9F8A583100000000004498BAB8BFA148070000004194C5CCB28A3F03132421226BAACDDCCCB28D421A09199A89AEC8C6AA68360E040900100F1E3579D4E9BF5E2E2E00004194C5CCB28A01FE365F0707186072776F4F140500062B5B92A189978C683A06000000042D67A8C7D3D6C8B2813400002567ADC0BFB29A4C040000085BA4C8DDD8C68933000F3676ABC7C8C7BC802A0000094EA8C3DFDBCAC29A4A1203000F5790B5C1CDB76D2B0000205DA0BBC7CDD7CEB9762300002B8EC8CCCCC8C0A8843500001C61A7C1BDBABAAD681200014389AEB9BBB7BB90524A5C524A5480A0B6A39F9047190C000F14316490A39B835D36000000000050A3BBC6B89154090000003F91C2C8AE8A4211152118316BAED0DBCAA1773A0700189584A8CCCAB56F24110004010A151C438EDBE6B35B2B2500003F91C2C8AE8A01FE375F0707187071757E561D0C0C091C639BA8948285612B09000000053A72A1BBD4D7CFBD833800003673A7C7C4BE9F55000000075BB1D4D2D9B98234000F3E80A9C9CFC5BA822700000C559BBCD5D4CDBD9349110A0A276391AFBBBDA76A1A0003146CA7C3D5D3D0C4B3791A00003899C9C6B8C7BCA77F2200001A6DB6C5C1C2B5A2660F00064C8BACBEBAACA88C56495A52465C84A1B2B1A0954B1106030B152E6898A6A38A602E000000000055A8C3CCB89357100000014FA9D8DABF7C35040B1A172C7AB6CFD9D0A977380B0A19949AB4C8C3AF692610000000081419398ED6E6A45C332B00014FA9D8DABF7C01FE385F070718807E7C794A23100904215A9EB0978D7F54300C0A0000123B79ACC3C4D4CFC180290000347EB9C0B9B7A2490000000562B0CBD3CEB2802C0212498CBACFC2C0BA751800000F5AA0C0D2D6CDAF9248170E0F1F6B9AC0C8C7A75E1700002266AABDC8D1CAC4AE6B1F0000349BCED3CBBCBEB26C1800002373A3CAC9C6C6B2610A00116093B1BAAFAFA08D54495D5E486191AAACAC9D8C3F0C01071318285A8AA4A38C5429000000000E5BAEC0CAB087480000000D53A8D3CBB47D3A0A0F18102B73B7D7E6CDA5753D0D002B9C90BED0D6AF76340D0000010B13224297D4EAAA562225000D53A8D3CBB47D01FE395F07071890626266470B060000236799A493907E4E1D00080000174E84A3BBCBDAD0B87A2700033586B9C8B7AE9C4B0000000B55ABCED7D0B7752303114789BBC4C3C9BC6D260000135FABC2C7D0CDB3923C15110E296B9DB7C8C39F4E1301053666AAC7C7CBC9BCA96C1F00003491C0CBC6C7B89C6D1C00002F83B6BDC8C2BFAF5E0A000C589AB2B4B9B4AF834E445754536181A3B5AA9D8A4514090C12232C6995A3A685582D00000000176DBACCC9B495540E0000126DB1D2D8AE732F060811133371B5D3DFD0A36A330E0B1E9A94C1D1CEB16F2B0700000613122B489CDBEAA951312900126DB1D2D8AE7301FE3A5F070718A07A91824E1B040B20487CA6BBAD9488531C00010305245B8BA4C6D8D2D0B96E2500003B8BBAC3C0B59F4A0000001558A3CED0C2A06A250316529CC8D4D4C2AC6E180000156AA9C2D0C7CBAF95481E0D173178A0B9CAC7A04E0D00052671A9BDC6C6C6B5A5610A00003E9ECCD1CECCC6A76A1600003181B7BBBEC5C3A64F0300125D96A8B6B6B1A6854D4C5254505F90A8B8ABA585390D060A13172E6693A19E8E522A000000001D6FB8C5C6B7944E0A00001569BCE0D0B07129020B10132778BFD7D9B99B6E360C0D208F96BED0CEA266290E00000515223256A7E6E3A8502F26001569BCE0D0B07101FE3B5F070718B07A887E571F0E0A164986BAC8B19E7F451E050F03062D6593B3CCCBC9CDB8712807094A90BAC9BCB296450000001368ADD0D8CDA86A23031D5AA1C8C7C0CCA85B1A00001E73B2C9CAC7CABE9241191C153977A7B8C2C49A480500082E6DB3C9CECEC3B49A500E00033B99BACFCCC5C0A0691400003980ADC8C1BCB79F460B001D649AAAB1BBB29E7C49484D535A668CA7AB9F9C763A0B02121E2A4676989E9F88461E000000001C7EBCD7C7B58D4D080000136FB1D3D4B8803006070D173487C3D0D4C2905F32100C2F959ABAD9D5B6742B0408050E10192450A6DFDE9F4F293000136FB1D3D4B88001FE3C5F070718C06C88895C2E0B0C265E93C1C2B39A775019111D0B05356B97BCC1D1D1CDB0672100154E97B8BFBEB99A4B000000106CA8D7D5C2A25D1100276DAABBC7C5B9A7630D00001E79BBD7D0C7C4B9853829241C3A8AAFC0BDC29F3A010008367BABC2CCBEBBAD914700000046AAD0DDCCC0B593500100024194C3C5C9C9B9A64B01001E6098ABB3AEB0A582464A4C5E616A93ABB1A79A77380C08061F26406F93979B91491400000000307CC1C8C9B78B390000001F75B8D6D3A66625040814132E7CBCDCDDC39865340E0C279299BFD8D1B4702005000804111D2B58ABE4E6A54D2F2D001F75B8D6D3A66601FE3D5F070718D0757D7B5218010C236686BFCCBC9E7F3E180F0F16184078A1BCBFC9C3C3B26B2100105BA6BCC3C2BBA1460000000A6BB2CFD4C39D5B1804276CA7C1D9CBBAA255030000287DB8C4C6D1CAB7873D1C21264685B2BCC1BC87300300063E87AEC4CAC7C2AF8D4200000846A8C9C9CEBDB997450000024795B5CACEC7BC9A4E0200266B96ABB3ADB0AB7E49464F5F65728EA5A8A7A581300F07102730386F9DA8A0814218000000002C7BBACDC1AC85420100001C7DC0DDCBAC672000000C13378FC4D8DBCB9A602E1810389A9DBED9CEB46E2300000015071C3365B0E3DA9750332B001C7DC0DDCBAC6701FE3E5F070718E074908B522B1C19336699BECEC9A87641170C1F1B1D4883A5CAC3D3D2CAA0651C001A69A0BDC8C9B48F3E0000001B68ACCDD1BFA04711072D71B3CFD2C4B399450B0000338EC0C5C8C4B8AF813A2D2B2A498DACBDB9B88D340000144885B5C5CAC7C1A8823E01000B55ABC2CACABCB6843C0000034097C1C3C6CCBC9E4C01002A73A0B7B3A7ABA77C4E4C5263606991A4AB9C9C752D05070F2F2F4172909C9E864C2A000000003F86BCD6CFB7894A0600000F79BDDDCDA56A2C030D161E3E8ECCDEDBBC8D5931190C268CA2C5D6D2AE6C22050004071C1B3363B6E2D88D432D24000F79BDDDCDA56A01FE3F5F070718F07A938552271C27446FABCED2C3B07935150E21242C568DB3CCD3D5CECEA55F1E021960A4C0BDBCC4A6490500001067AAD1D2BC854112052E7DC5D3CCBABF9F420000003B97CACAC5C6C0B2873F2E3333539EB4C0B2AF732B0000134480B2C2C7BEB7AA7F3200001559A8CDCFC4C0B7863C0000044C97C2CBCDC4B79C4A0A00266EA4B0B2B4BB9E714A574C626A7296AAABA8A1652809000F2B364F72969899823E1600000001388CCCD8C5AE84410D00001788D7E6D09A6723010005183984C2DBD9BD9050311E193899A6C4D4CBAF6A250B000318192F396DC0E3D88E4C2E30001788D7E6D09A6701FE405F07071800738B87592B22315586ABCDDFD1B67B370F1225223056A0C3C6CCD1CDCEA351220A2B7EB0CBCBC1B19A46000000166CB0C7D9BD7C360B0B4082BDCFCBC1B09147000000399AC2CECBC0C1B2833C2C3E425792B3C7B9AF78210000124C8EB6C9C5C8C39E772C00000F60BBD4D9CCBEA26B300000085BAABECCC7C0BF97400C002F82AAB8BCAEA096674451535D627F91A2ABAD966B2708091835384C7596A69A814C20000000135498D1DAD6B689440400002684CAD6CC9E56240C0E19223187C2E2DABB7A4A2B111C3087AACBE5D7BA732400000B1018253970BEE1CC8B493936002684CAD6CC9E5601FE415F0707181078918256342732609CC9E7E3D0BF6F32111029283465A7C4D4D0D9DCC78E44120A3181AFCACFC5B89B420000001B74A3CDC8AE642C0C0E4382BDC6CFC2A88E3D0000004898D0D2C9C4C1AF773C354447669CB5B0A59B72210000265C8FBDC8C1BBB59A6F2400001467B7D3D7C9C5A36E1F00001464A2BBC6BFC3B2943A03084085A3B3BFAFAC9669474E5565777D96A5A5A596672304062232424A768C9F9A814D240404000657A2D2D3CAB081470900002188D1DCCA915923030E0E123D94CFE6D6B58649311E164297AFD3EADCBB75270300000A1C26387ECCEBCE7D3F2D33002188D1DCCA915901FE425F0707182073887F6036323C74B3CFEDECD7BF6D34201B2B2B2F6AACC9DBD9D4D7C5904A1C07368CBCC9CCC7B5963F0000002463AEC6CDAF6B250009438DBFD2D0BCA48D3E0000003FA0C3C3C4C7C4A87E443A493C6AA3B2C1B89F6D210000215792B4CBC3BDAF8D61180000196CB8D4DBCFC1A3690C00001862B1CDD0CFBDB7913000024884A4ACB7A6A89F624652556C7682A3A9AA9A925B1700082036465079979E9D7F44110402001061AAD6D6C9A378390000002388C9DACB8D5315040E14213C8ACAE0DFAE744A27161B4095ADD4E5DCB57026000100101B24418BCAE1CD81433B33002388C9DACB8D5301FE435F07071830768980533735548AB6D9EDE6DFBD723716233433366DAAD0DAE1DCD5BF813D1A12378BBFC9BDBEB79E3B0000002273B3D5D4B2611B06124795C6D2C9C0A883350000004AAAD3C7C6C4B0A46F443E5651779CB9BEAAA46C1D0000235B93B6BEC2B4AA7D531900002071BAD5D4CBB9A8610D0000186DACC4C6C6C3C0962D05185389A6BBB3ACAA965D4A4C536F7D8D9FA3A4AB9862190002253F4A58849A9699823E170105001665ABDDD5C8A37F41030000238AD3E3C5874A1C04101B214194CEDDE0BD743F2B1E255098AED1E4DCB76B2106000509172A529BCBDFBE712E383700238AD3E3C5874A01FE445F070718407A94875E3F40579AD3EBF8FFE5C1723E1C28372F3F72BED6E1D3DAD8B6743A171D3C91BFCCCDCABC96480000001E75B2C9CEA65918001048A1C7D2D2C4A47E2F0000005AABC8CAC9C9B4A67143475A5D729DB5C5B89C621200002C6FA3C1BEC9B2A681510D0000267AC9D9D0D3CDA4560000001D6FA8D0CACAC0B98A2D000C528DA9B4A9A4A7965536535D72808DA3A5A8998E5A1C000D2B4A51527A969493803E130300002071ACDAE0CDA775380700002288D0DBC886451B071314293F8FC9E5DAAE763E2D1F1E5086AFD6E8D8B46E1E0200000B18334E93D2E6C0773F4036002288D0DBC8864501FE455F070718506F7974543B3C5BA2D6F2FCFFEDBE7034191E31324D80BCD4DFD3D7D0B16F2E1C154F9FBED5D1C7C198430000001E71ABCDC5984C16001B65A4D0D7DCD7A9781900000556ACC5CEC6C7B3A3723E4E615A76ABBDBAB29C540A00012C6A9EB4B8B0B29D79480300003085C3D2D2CDC499520000002C7EB6C9CCC2C1B6852C00115699B2B3B4ADB09C5E4B545A74738594A29F9E924B0E00012F49545D828BA29D853B10050A022E78B2E3DFC9A6772F0800002E8DC5E0BF803912090612214695D5E6DFAC6E3C2D1E255697B8DBE8E4B1681B0005120C212B509DD8E3BE663A3E2C002E8DC5E0BF803901FE465F070718607B827F5C42436CB6EAFFFFFFE8C6742D232A36314989C8DCD7DACACCA56836181C4EA4C5D2CDC5BEA2490000003075B7C3BB904B0C001D56ABC8D7CFC7AB722100000B64ADD2CDBECBBCA169474B536287AABBB0A59B550000023171AABDC3C2B6996F380000003990C2D0D6D9C28F470000002A82C1C7CAC1BFB3832300115EA3B8C0B5B0B1965B415765768995A09F9F9783450D000634504F5E728E968F7C3F1D110A0F378AC2E1D6BCA07C3D0600002B89C1DCC77B3810091A1820358ED7E7D6A7694537352C5B93BEE0EADDB9722B0D08060C1C3764A5D9D8AE5C354C3F002B89C1DCC77B3801FE475F070718706C7C6C53373D72C4EAFEFFFFF8D16F3227232B374D98C1DDDEE0DDD2A35D1D161655A2C6D3C4BDBCA1460000003274ADC6C59A3E09001963ABD2DDDBCBAA641600001263B4D1CCCCC9B19F634655766791AABDBDAD95480000063F81ADC3B3B9AC995622000006479DC6D7D2D3C08539000000248BB8C9C6CAC3B57C2A01186793AFB8B1ADA59056446074838D8D9A9F9C9A85340C030F3A4E535F7B91948A714F211F1D1C3B89D3E5E2C49B7D401000052E8CD4DDC4853817100C15244893D3E5D7A269382F202F578CBEDEEADAB67A2E0A0103061C3E72B1DFD9B05C36443E052E8CD4DDC4853801FE485F07071880777E775F444C79CAFAFFFFFFFAD67B36212D393A5199C7DFDBD9D7D1A355251E245EAAC8C1C5C6C4A0410000043A79BCCDB3863000002674B1CCDDD8BCA960110000126AB2C7C7CBC8B397673D57676D8CACB5C3B08F3E0000124F8AABBDB8B8B28D52240000064FA3CEE5DFC0B4762E0000003391B1C6CCC6C1AB6E12002470ABBBAFB4AEA58A473954667A8593A4A1B09D7E4211000838685C617E8F91867246221812244E9BD0E5DCBA9F7D3D0A0000369BCFDBC1792A0D0A151E214A97D2E2DA975F383232336093B7DEEFDFB1732A050009141F3F7ABAE5D3A35229443B00369BCFDBC1792A01FE495F070718907170614A38477CD0FDFFFFFFF7C57132202932334D91CDE4E4DADBCE95481A1B2F65B2C9CCD0C7C1A1410000033A7DA7CFB788250003277ABAD1D5D6C8AB6B0B00001772B8D4D2D2C5AE9863435871738EADB6BDA891460000094989B0B8B5B2BA894510000013519BCDD8DAC9B3792A0000004394C3D0D6C9B7A57016032C7CA3B6AAB1AAA0914B3353677F999EA8A8A7967840050008426466687F908E88633A1B2122184199DAF6E2C89F6B3B070004379AD0D7AE6D30090B0F1A254598DDF0D69F5B33343030698CC0E6EFD8B26A2508000811173985C2DFCB9F4D31474204379AD0D7AE6D3001FE4A5F070718A0736E5B50404C92DCFFFFFFFFF1C168331D2A312C58ACD1E3E4E1D5C58B441A163874A9CBCCD1CFC59B400000003C79B2D0C881290000337EB8D6D0DAC7AD600A00001A78BAD0CAC8C5B2986043557A809FAFB7B9A78D390000105C96B1B9ADB4AD87491800000B4D97D1D2DACAA370200000004290C1D8C7BFBBAD641A022E6D9AB2BBB3AEA77F433358698F919DAAAA9C9E8038020013496F686D8290978E6443292C262454A5DCF4E3C39B73330000003396D6DFC1733410101B141848A0DAEADF94563B3124296A8AC2EBEBDFB9702305030A151F478BC6DBCA944B354A3C003396D6DFC1733401FE4B5F070718B078756B584E5892E2FFFFFFFFF4CB652F232B332E5CAAD9E3E7E0DCC88737121F3678B0C5CFD2D3C5A24100000C4082B4C8BB6A1F0000337CC0D6DAD1C9A5570B00001A74B3CDC5C6C5B193603F56777F9FB4B8C4A98A3C000016549DB6C7B8BBA0763B060000175AA1D3DEDAD0B36D15000000459AC5D7CCBEC2A66717002F79A5B3B7BEB3A77B4436586C909BA3A5A4A99B6E320000145470646C8697998F7046242C292A60A2DBEBE6C997703E0D07073D99CAD5B36A250C0913211D47A4DBEDDA9A593D3631326F8AC0DFECD8AC6A220B020F0B205490C7D8C38B4A3A4539073D99CAD5B36A2501FE4C5F070718C0807B6759475A9CFAFFFFFFFFF9CE74382B232B3C67B3DEEBE1DADABB8339151D3975BBCCCED4C8C9A73D0000144684BDC9B66C2200003594C9D4D1CFB99E4C0000002577B6D4D1C8C5AA895342627B80A9BCB2B6A77D3500001C5E8EADACB5B4A676280100001C73B4D3DEDBCDA867170000034CA5CDD2CAC5BB98590D003183AEB4BBB0ACA07D44324F6E8EA0A6A6A7A189703400001550667A7B8A979288623F2825262C63AEE4F7DEC58E68340000053289CAD8AC5D28080E1E22384BA5DBE9D2955741352A2E7188B4E5EBDBAE681F06051517205397CFD4BB9341364936053289CAD8AC5D2801FE4D5F070718D0777A6551515E92EEFFFFFFFFFDBE70402C252B355EB2DCEAF2E2D5B6773D1E2E4982C3CCC0CCCDC1A03F00001A4388C3CFB0661100003D8DCAD5DACCC9AA4B0400001C7DBDCBC9CEC8AC8D563A6073809EB5BAB7B17B2E00001F659FB9BDB6BA9F68230000001E73B6DAD5D4CDA85B1300000158AACECBD3CBC7A5610700388BA7B5AFABA59D7C3D304D6E8BA1AAA9AAA5966F2F00001A597E7277859890805A4A2B312C3B72B7E8FCE4C29974340E01093B9ACBD59E5B180C1423202A4EABE1E8D1884E383D31407B91BFEEF9D7B1651F070C0D192A539EDBDEBB8038273736093B9ACBD59E5B1801FE4E5F070718E07A6F5445405A9BECFFFFFFFFF3BB622D1C2130385DA9DFF0EEDDDEBE6F3512274C88C1C7C3C6CDCFA845000014488BB8C2B067180004419BC3C3D1D3C898430000002A89C5DBCEC3BEAC864B37657D93A6C1BBB89F711D00002A689AB5B9BABAA56D210000002D77B8DBDBD6CBA24F0900000056A7C4D6CBCFB99C4C09063E87ACB6BFB7ABA07632294A73999EAAA9A9A3956B2C00002163817571879289895F4B2D29353D7DC2EAF8E2C99C703E0A000436A0D1D0A65E17020A1C1F2A50A3E6EDD2894E4244353F788FC4EDF3D4AC67290E07090C215DA8CED1B379412E35420436A0D1D0A65E1701FE4F5F070718F07468564E52649EEBFFFFFFF9E8B6643225202D3860B0E0ECECDDE0B36A3313254E8CC1BEB9D3D2C7A73E0000205497C0CEA85C08000150A3CCD3D6D5CA98430000003288BBD3C3C2C1A48347384F718DA6B2BDC7AA721D00002F78AAC0BDBBB1A961130000002C80B7D8DAD0C29F490A00000464A8C7CFCEC4BDAE500801408EB3C3B8B5AEA07031284C8098A6A0ABAC9E935B1B0003256B8C8B7E8A968F835448202827447CCFE9EEDFBF8E68361702093B9ECACFA0511708151827275BB4EBF4D894584C4E3C457386C5E1EEDCB05C1E01020410295BB0DDDCAB7A3A273834093B9ECACFA0511701FE505F070718007B75614F485F9EEAFFFFFFFFF2AF643F2D302A3A6EB5E7EAE6E0DEAE5F25102B5C97C9C6B2BEC9C3983A01032B6192B3C7A55B1000114CA8D3E1D5D5C68B3A0000043A90C1CEC6C5BCA1833C345F788AA6BABFBDA5731D0000357AA4B9BBB0B89F5F0D0000003D7BBADDE5DAC79549030000146AACCFD0C6C9BD933D000E4791ABBEBFBAB19F64302552779B9FA3AAB1A894611A0000205F837F878D93938D52462D3039478ACFEFFAE7C18C68330E00073C95CAC79C4C220F0C18162C61B8E5EAD2845246503E427C80C6F5F4D1A65F2000001112315FAFD1CEA56E35234133073C95CAC79C4C2201FE515F070718106F6A554A48649EF0FFFFFFFFEFAE5C2C292622336EBAE5E7E4D8D0AB5E2A0D3066A2CAC2B5B8CDC2943E060C386EACC1C89E4E03000548A6CCD1DBD2BF92340000054095C8D8CDCAC2A27440395B7792A9AAB6AC9D681E00004383B7BFB8AEA89B4E0D0000004492C2D1DCD9C79B3C0000000B6DB5C4D3C9C1C19D3F07085294AEB9C0B5AA9A6025214878A3AEAEBAB29F8C5D1E00002A6D8E857D898A8B8346412D2C2F4C8FD6F9F5E0C2936D391702063DA1D1C894461811131625305DB7E4EDCB8A4B4D50364A8C82C2EBE6D3A3641A030613122868B1DFD2955B352F3D31063DA1D1C894461801FE525F070718207C6D5D525174A1FEFFFFFFFFF0B05E3631302C376CB7EBF1E7D8C89B502620316F9AC3C2ACC3CCBD913900063973A8BEC3994208001052AACED4D8CDCA893A000004469CCACDD4CCBAA174342E4E7C98ADBCBAAF9D6D1A00044882A4B8B1B4B29755030000094D9DCCE3E2D9C289350000001273B3D2D3CCC7B6983C0005509EB2BCBABFAD995C271F3F74A3B2A8A9AAA69D611C0000226E938A868B94948850492E3A435F99CDF0FBE9C492683208031849ACD3C48C3B12040915263969C2EDF2C78964645C434C8776C1E9E7CE9B521F0103070C346AB9DBD29B5C2F21313C1849ACD3C48C3B1201FE535F0707183077654B4A4D6CA2FBFFFFFFFBE9AD5F3E292D2C416CBCE2E9E7D8CC9A5118124172AACDC0A6B6CCBA904106104172AFCAC28E3B02000D56AFD4DBDFE0CA8B2A00000B4A97CBD5CDC9BC96703A345D7C9BADC2C4BBA25E0A000B4D8AB2B7B6B4AA9A4C00000003589CC5DAD8DCC3872D000000157DC2CDD2C8C2B4813300094F97B9BAB7B8B09A581D1B4D73A6ADB3B0B6A286501A00072E6D8C838C938C8D7C4F472D363865A3D5F8F7DCC394683C0F05164DA5DAC18632170A10141B3770C4F0F2D08C605B5C43588C81CCEDEED39D521900000B10236DBEDEC68A4D2F263B2D164DA5DAC186321701FE545F0707184075684F49495FA0F2FFFFFFFBECA35C342A24334177C8EBF2E6DDC593451E183E81B5D1B9A6BACDCB8F2F03134C7FAEC7BB7F3909000958B9D8DFDAD7CB822700000A4DA6C0D2C4BEB1996D3A39617D97ADC1B6BDA4581000075B97B2BEB4BAB092430000000D5AA8C9D2D7D9BF81260000001F80C0CFD1C8BBB17F2703135BA0B0C2BFB1AD965021213C6D9CA3ABB1B8A386491300002C7095908E99978D85484035353F6DA9DFFAFBE0C2936235130A194FB0D3BF7E33140F13141E3479C6F3ECC88F63615E54609679CAF0F0CB964F11000006112774C0E2C5854A26213635194FB0D3BF7E331401FE555F0707185079604A4B4260A0EFFFFFFFFFEDA25B3F2F1C263671B8E5E9E7D8BB8A471D204587BED5ADABB9CFC47B2E0019557EBBC4BD8B3800001256B7D8D1D0D9C3862700000E5BA5CAD1CDC7AD9F67322C567A98B6BCC0C09D510800126396B9C6B7B4AF9145000000135FA5D3DDD3CFBE76230000002B87BCCCCCCAC7BD7A2B0013589EB8C6BEB0A9894B16163678A2B5AFB2ABAB84491501013377969899998992813F47313A486DB0DEF4FCE0BD8B653112041351A4CDB87A2A0C12181C253A84CDF3F8CF9063675D485C8F74C8E4EAC388480E00000D0B2773B5E5D28E42252D35331351A4CDB87A2A0C01FE565F07071860715B4B505067A6F7FFFFFFFFE2AA5E3832282D407AC2DCDEE6D8C1853E16104A8EC3D1B7A5BECCB9731D001D5787B2CCBA7C2A00000D63B2CCD8D7D8B5762300001863ADCCCDC8C3B1986B21294C76A1B8C5C4C39F570100095DA0BBCCBFB2A9983D0000000F74BAD0D6DBD7C167140000002C8AC3CFCBBCB6B7792300185BAABEB7ADBAA98C4B1B183D75AAACA7B7C0B1924C0D060A317C96948E948B81793252313A4C7BB8E5FAFDE1B786623E1D071557B1D0C0722D0C09161722368CDEFFFDD49766606451569373C8E0E5C284440D000008113B7DC3E4BE694824282A2D1557B1D0C0722D0C01FE575F07071870715E49484B64ADF5FFFFFFFAE69A543939342C3D7FBCDDE3ECDABE783210134F9BC8CFB59AB7C4B76E1B08246A92BECCB173240000146CB9D8D3E2E1BF7C2800001C6BACC7D6D3C8AF92581E25446EA6B6C8C9C59B460B00186199BCBFB4ADAF8633000000166DBFD1D2DBD7BD6D150000002A85BED3D0C0C7B96D21001667A5B5BDC3B3AB894416173771A2AFABB1AEA6804412000A49849C9F9B9C87888239422B3E5183BCE9FFF7D4B38E5B361E0C2568B0D1B4732B120010132D4583CFF5F7D2896863635668A378D6ECDAB3783D0A0000070C3582D5E4B97639202B2D252568B0D1B4732B1201FE585F070718807755493B475A9DF7FFFFFFF8DB915432332D314281B9D2D8D7D4BC75321D2863A7D4D1B394AAC6A565230D2C699EBEC7B66F2700001665C0CCD5D8CBB7731D00002276C1CDCBD4C4B58C531F2142659AB2CFBDBCA34C00001374ADB6C2B5A7AB91310000002A7CB8CBD2D2CEB76C140000003A93C3D5CEC7BEA46119001663ADBDBDC3B6AE7D3E13123C80B0AEB2B2B3B1863A0300034083A5A89394928E7C2E5032345189C7EFFEFFEAB5845439150C2165B2CDAF66231011121026489FEAFFFBCF846B6761576C9F7ACDDEDEB8763C0500020F15347CCAD6BB71381D1F2A352165B2CDAF66231001FE595F07071890765F4D4E4F67A9F4FFFFFFEFDD965C44362B2A507EC0D3D9EBD6A86B2F102664ADCAD6B99EACC2A25D1804297AB1D8D0B96D1E00001368B6D0D6D5CAB2631800003283B8CDCFCEBCAB8A531E1F40709BBDD5CAB9984100001F7AABC4CCC1B7A589320000002A93C6DED6D1D3B4690D0000003A98CED1C8C6BBA8681C001E72A5B4B8B4BAB1752F070C4376A1AFB4B9BCAC823907000F4285A49D9C938C8B7830453731528BC9FFFDF7D2AA79563E2809195FB6C9A45C1C0C0F1723355CA3D8FFF8CD856966645561A56DBAE7DFB472200000000B193B86D6DEAF643523213330195FB6C9A45C1C0C01FE5A5F070718A06F5C43444369A3F4FFFFFFFAD2935245332532538BC1D0D7E2D6B2622B102966A9CFC9A79CB0BA965817074080A8BCCEBA711D00001E63BACED9CECFB865190004398CB4CDD5D3C1AA845412133875ACC6CECBD09D4100001E76B2C1C5B8ACB47C28000000278CC7D1DED7D5B55D0A0000003E95C6D4CDB7BFAB6815002972A5BCC0C4B9AC71360F133E83B7B9B8BCB4AB7F310000144A8DA69F94969D8770215642425F96D0F9FFF4D9BB82573A1F212472BCCCAF5D260A1016252E55A1EAFFF3CD91675D605466A76FCBEDD9B4642A03000007183487D0D4AF652E22222C2A2472BCCCAF5D260A01FE5B5F070718B08468574E4C64A5EEFFFFFFFCD38A514E432A325088B7CDDCE3CFA36021142D66ACC7D9AF9CBAB887410A0A4089B6CFC5AE5E170000266DC1D8CBD3D0AF601100064391C0D0CDD3BDA9823F0B113367A8BEC9CDC2973E0100277EB1B9C3BFC0A980260000003194C7D6E7E0D1AB5A09000000419ACDD8CDC6BEA0510F012C7AB0C0B5BBB1A76E250515427EADB8B6B5BCAB82300D000E478B9FA2999B9C8D6C1F593441679AD8FFFFFCD6B07D5E3C1F12276FBCC9A156210C0E1F24345AB0EFFFF4C78C6C66635667A96FC6E1D8AC6B220000010D123883CACC9E5C3120283334276FBCC9A156210C01FE5C5F070718C0766641474261A7F2FFFFFFF4D28753473E34345492C3C0D0D9CBA35921111F6ABBE0DAAD9EB0B27C380D0E468FB7CEC9BE6A170000146DBFD2C7CAC6AC5217000C4593C8CED5D2BD957740010F2C6BA6D2D3D6D0923E00002886B7C3BFBFC0B27A270000003A9EC8D8D5D1BFA74F0000000353A2C6D3C6C7BA97550B02317FADB2BAB9AAA3601D0A13498CA7B1B1B9B6B07B300B0010538D989DA89F98906A204846516AA5E6FFFFF4E1AF8364411B15367CC5CFA04F1F0F161C222F6AB1F2FFF6D494636D685971AC64C4DFD7AB682D0000000210398DCED39A533220222A33367CC5CFA04F1F0F01FE5D5F070718D0775A423C4864A7EDFFFFFFFDC685574D352A3D5794BDBEC6D4C99C4F150C296BBAD9DDB9A8B9A276410D125498B3C2CFB0590D00001A70C5C8C8CFD6AC5D0F030950A0C2CED3C8AB9070350E093370A8C6D1D0C69B400001328CB8CBC0C1B7A373180000003897C7D0D5CFD2A2470000000E57A7CCCEC8BCC1A25D17003B88A8BAC1BDBC9D5B1A01104D8BA8B3AFB4B0AB6D2B0402165D94A7A3A79C98876817483A4665A8E9FFFFF7CFAB835D432521368BCFD69B482B10121E233173B5F6FFFAC18F7160625476B365C8DBC6A955170000000922459CDAD0975D2B1B22312A368BCFD69B482B1001FE5E5F070718E0746146444D65A4F2FFFFFCF6D7895A5546353B609CC5C7C8D4C28E4D16112971C6EBDBBBA4BB9C6D250A195AA9BCCCC9A8500D00001865BECBBFCCCCA65C12000F55A1CFD3D4CFAE8F673900063067A4C9D0D8CC933300003896C2D1C6C2BEB7701000000044A2CDD1D8D6CDA3480000000A539FC9D2CCC5B79D4509063D92B3BEB6B5BB9B5C220113488BB5B9BEB8B2AD7632110015528FAFB09D94898469114C444E79BCF6FFFFF8DAB66F58442E26418FCFCE954C1D181124273C74C4F1FFF4CE856561645676B566C6DBCF9C4E160000050A1F4AA0D0CA925532281C2D3C418FCFCE954C1D1801FE5F5F070718F076513F3F466DB2F7FFFFFFFECD825B5F3D373A6296B9ACC5D6C28B421A112977BEDFDFBBA9B8995B2802125D9FB8C8CAB2580800001467BDD6D0D8CCAC5910001B56A6D2D0D1C5A97C5A2200022B67AFC7D4E1D7963504043794BFC6BEB8BAAF690F00000050A4C5D1D6E2D39A380000000D65A0CDD1CEC7B39F3F0609428EB6BAC1BBB59E5515060F4C8BB8B6C4BEB4A0712C02061B629AA199A2988C815F1249405375AFF1FFFFFFD29D746A4D2F244B95CFD094461D160E1B273E7CC6F4F7EDCD95726C595E81C05EC9DBCFA848120000000619459AD5C4854B2C25312A384B95CFD094461D1601FE605F07071800826352585B79BBFFFFFFFFFCCE895E5C543B4A7EACC1AFC5D4C2823509062A7BBBD9E0BCB0B7924F200D1360A6C6C8C4A94E010000176DC3D0C5D0CC9E5B1A001868B5D0D1D7CAAC8059200004256CBBD7EDE2D88D2700003E97C8CCC0BFC0AC630B00000043AAD1D6CDD6DB98350000001961B2C6C3C2C1B88D3300035795BEC7C1C0BDA35B1305175191BAB7BBB3B0A465210B082663939FA5A396987F5A185D49597FC8FAFFFFFFD6AA76634A242858A1D9CB8F45231912202D4782D9FDFFF3CC8C5C55555378BB5EC7E2DD98410F000000081F54ACD7CE81351F2126303858A1D9CB8F45231901FE615F070718107B674A4C527DB4F8FFFFFFFFCC7F65614D3F4771AEC5A6BDD2B87036170E3B80BCDEE2C4BABF894E18001365ABBFD1CAA94A050000236BBEC6BFC0C99B5507001F6BBAD8D4D3C19D6F4C0F00002667B7CFD7DAD6883503053793C9C8CAC6BEB1661100000055A8D4D8D1D1CB913B0000001C68B1D3D9D5C8BA882D040C58A9C6D3C5B3AC984B14001C609BB9B7B5B5BCA15D250704236BA0A39A928A8F7C590F584D5380C5FEFFFFF6C3937C6851391F569FD7CC86432C2317212A488CCEF3F6E3B87B56595F5279B95CCADFBE94530D000003151F5CB4D4C177402224303235569FD7CC86432C2301FE625F070718207760454F5476B9FDFFFFFFFFC47D6C69493F4376B7B9ACB6C7B169280A10317BC2E3E6CEBFB2833711002075B3CDE0CCAB490600001764BBCDC7CACA8F4110072A7AC0D1CCD3BF956B480B00002470BCD0E7DBD07A2900074097C3D9C8C1B6B365110000025EB1CCD3D6D9BB9233000000287DC1E1D7C9C2A7852B030D56A5B9BDC1BBB39E491000186099BABAB6BEB49E5A1D040B20658FA5A3A39A857F4F0F5452578FDFFFFFFFFFD4A1746853363064A4DBD68B3D2C21181D27509CE0FAFFE5BF7F5956555586C558BED8C192400D00000015266EB4CDBE763424232A343B64A4DBD68B3D2C2101FE635F070718307B5953454F7CBAFDFFFFFFFCBC7C5E69573F4C75AEBFAFB6BC945D200C123C8ECDE6DDD2CFBB792C01001D6FB5C8C3CBA24D040000246CB6CCBCC6CB9C4A11072E7ABBCAC8DAC6945F3D000000276CC1DAF0E7D07B1F001147A3C3CCBAB4B6AE630700000C5FB9D0DCDCD8CB8E230000002879BED2D3C0C1B47B2F0D216CA7C7CBC1BBB29B41020018649FBDBBB8ADBEAA691D08132E6C96ADA59D978C824F02584A669DE6FFFFFFF8D1977C6654362E6BABDDCE8E452F251F202A5CA9E0FFFFE5B76F584C515686C453C0D4C0954705000008112D60B4DDB86E3926203C3C426BABDDCE8E452F2501FE645F07071840785D474C5785C8FFFFFFFFF8BA8175745642557AB6C0AEC6C5A0581804123885C5E5E6CDCCB778260000237ABCD8D6C59E41010000226CBEC6BEC9CC943B110F2D7EBBD6D6D7C48D4E270000002A75C3D7E8E5CA6E24020F4CA2D6E5CEBBC5A4550600000661B4D3D2E2D7D08E2D0000013487BACECACAC6AE771C001663A3BFC3C4B6B597450C00176DACD2C0C0B9B294541D0B0B2570989D9B969C9085510664546290F0FFFFFFF9CC9B777356424172B8E4D0914630231C253153A5E2FFFCDDB4755345494884CB59C1DBBA964303000000112668AED2AF703D30312E2B3372B8E4D09146302301FE655F070718507A564E58537CCBFDFFFFFFFFB782777959465A8CC3BDA2B4C1975019101D4085C6F0F0D2CAB8691F00002A78B3C5CAC596390000002C7EC4C0B5CCD59B4B1B0A338FC3D6D1D7B1814F200000003677C9E2E8E5C2661D0010479AD1D5CFC4BEAD4C000000115DB4D3E0E7DEC88C25000006398DB7CFCFCBBCA76C1C002270B2CDCBC1BCA88E450D001A6AA0BAC0B5B3B0A7612713162F64969F9F948E897C41006A6386B8F7FFFFFFF3C48F6969583B4680C7EED286432D251C182853B1F4FFFFE2B16A4C4852458CDB57CBD1BF8F440E000003142B73BACDA95932292831383F80C7EED286432D2501FE665F0707186075614754648BD4F7FFFFFFF8B077767A5F4A5B92C4C8AFBDBB8F501B0A113581CFE3E4DBD5B9681000002681B6CBC9C492370000002B82C2C9C0C8CB863A12143F94CBCDD2D0B3763F090000002B7ABEE2E9EDC56A210919519EC9D9CDC2C7AE4D010000116DC1E5E4E4D3C886220000104087BBC6C7C3BC9E6313082873A5C4C5C9B9B78B2F0000267AABC0C0BFB9B3985B1C0F0D2A7199AAA49C9F88783800626385AEFEFFFFFFFCCC98756A5F455093D2ECC9823429291511326DBCE7F7F4D8A36542434D5389C64EBDD6C1853C0D000009173D7CC5DEA66B352A31343B3C93D2ECC98234292901FE675F070718707A5B3C4C5385D5F7FFFFFFE9AE7B78775D486C94C4C1A3B0B6864108000C3A94D1E7EBDDDDB25B1000003082C3CDCBB888380000012A71BCC3BFC8C8953D0F134795C5DADBD1B17138050000002B79BDE4EAE2BF642105154EA7D6DECAC6C8AD4E0000000D67BADEDEE0DACB821F00000F4E8DC5CECCC5C3A45C0E002B84BEC3B6BFC7B58B340200277DB0C1BBB3AEAA934C241615347B989FA3939389762F005C6180B4FAFFFFFFF5BB886E5D55444A9DD3ECCF75393132272A3160C5EAFFF4CA9E5B38393A5392CC56C2CCAD7C3E0900000A294B8EC9DC9E5B372730353B3B9DD3ECCF7539313201FE685F070718807F694B53669AE2FFFFFFFFEFAB8480846557699FD1CBB3BFBB863607000F4687C4E9E8E0DCB15A1300003B90B9D4CCBE852E000000357FC2CDBDC6D0A3430D0B46ABC9D0CDCCA85721000000003186C9DCF5E4C9661A081B569FDCDBCBCCBDA9470000001B71C0D2DEDCDCC87D2200001E4F9ACAD2CDC7BC9D500E083184B1BCBFB9BBAF822200003681B4C9C1C4BEB48C481A15143770999CA39599887135006F7082BAFFFFFFFFF1BD8C6E615A4A589EEAF1D07831352921253071C3E8F2F4D293563C3A3B5698D147C0CFB97E30030000071D4592CCDEA255352A2B34353B9EEAF1D07831352901FE695F07071890776147556E9DE0FFFFFFFFEAB58985815E4966A5D1C3BAC2BA7C3C0907163B8DC1E1ECDED7AF5A1100083B8CBEC8C6B97F2B0000003883C9D2CBCFCF9F39081350A0CAD7D5D49D5820000000083C8AC4E4F5EDC15A1800224FA5D6D8CBBCC1A247000000207EB3D3D3DDD3BF731C0104265C98C1D4D7BFB59145040F418EACBFBCC0C3B3782A00063384B6C6C2BCBAB58E42111019357793A1A198978B6F3600686E87BEFFFFFFFFF7BD85677062565AA2DDF5C777363C2E1E234882C2E9FFF1C18E4B3E3640569FD451C4C5AB7732000A05192A4A92D6D3954F2A303B392B3CA2DDF5C777363C2E01FE6A5F070718A07153504C639EE9FFFFFFFFE3A8828C8B5D4C66A0C7CCBCB8A76D410D0718438EC2DDE0E8DBAE52080008368FC6D5D3BA7A29000004328AC7CEC3CFC8883C161458A2CFD4CEC08E5219000000003B94CDE5F9EAC06014032E5DA3D9D7CFC9BA9C39000000247EC3D6D4D8DDC8741E000628689ECACCC6BAB9923703074C96BDBFC8BFB8A67B320002398EBBC4B8BCB7AE90492314163D76959E9B918B8E652500696994CFFFFFFFFFE7AA8A6F5553495EADE6F2C475383B2E23243E79C9F5FFF8CD904C342B3B5E97D249BBCCAF7C2907000010295298CDCE894B272625273742ADE6F2C475383B2E01FE6B5F070718B0785C4D54649AE6FAFFFFFDD79B7C8F8F665174B9CECBC0BEAA612D040C164687C9E5EAEBD8A24C02000E4D95C6D1CAB86D220000044780CED5C4CBC291460D1653A8CECED1C68E451300000000317CC1E6F2E7BC591A00215DA9DFE6D7CEC29D330000002E81BDD7DCD8DECB721200143D72A3BFD2CBC3AF8B36000350A2C0D0C3B6B1A57C1E00003C8ABCC5AEADB0A47F401C1319447C99A3978F92885C2A006F6E84C2FFFFFFFFE0B5836062594C60B2E9F6BE6738333921274287D6FAFFF4C08A4D37393A53A1D94BC6C8A9702505000C103356A3E0DE924A272C292F4448B2E9F6BE6738333901FE6C5F070718C08263495E74ADFAFFFFFFFAD79E92998B604F7FB7D2D5C6BFA5642C0A09224B88BCDCE3DECA954708000E5199BCDBD3BA711C000006459ACED5CED2BF873C0D1A61AAC7DAD2BE893E0E000000003E95D0E8EFE2BD5916001F64B5CFE1D4DCC78A2A0000032D82C5E0DAD6D3BE6C1904184879A5C6C2C6BBAC703100144995C2BFB7B2B1A77623000B438ABDC9C4BDB5B17B3717161547798D939693918462250071728ED2FFFFFFFFE8B375666060516ABFEEEFC4703D3739282B4B9BE9F9F9ECC08439332C335FAAE155C1C19462200C0905172C65AAD8CF834025272E3F3C45BFEEEFC4703D373901FE6D5F070718D07A61566375B1F5FCFFFFF1CC9982958D604F7CB6CACFCAC7A5582E0B0A264885C1E5E0DDD1A73E0000154F9DC4D5D3B1651F0000044291D1D8D9D5C78134162572B1CEDAD5BD7C280000000002449AD8EEF3ECAE4D120E306BA7C9E2E3D9B9882A00000F3883CBD2D2D9CAB7671600224C7EA9BDC7D5C6AD752100095F9AB4C2C4BBAFB0701A00054699C1C3BEB0B1AD73351C21264A8092A39C928F865E1D00697589E5FFFFFFFFE6A983695C5C5283D1E8EEC6733648302430559CD9FFFFECC27F3F2B292E57A1D947B4BF8B662D110A161A4076BCD7C288422930292A3F40D1E8EEC67336483001FE6E5F070718E0705D4A5263A9FDFFFFFFE8C898889079555083BADCCEBFC5A258250501214D93C3E1E1E8D6913F00001756A2C8D4CDA76516000019478ACBDDCFD6C18237152B70B2CBD1D1BC713201000000014791CFF1E9DFB54E1A103670AED4E7D5CEBB8524000008337CBFD2D1DCD4B4601003165787B2C4C9D1C4A16213000C67A8C1C5C7BBB0A6651A00125193BCBDC2BEB7A975281228285281979992878781581B00677794D7FFFFFFFFD3A371615F5A5577CDF2F4BF663433372D3255A1F0FFFCEEB1724223122B66A9D947BBB58860221300061B3E73BEDFCC8044242628313242CDF2F4BF6634333701FE6F5F070718F0745548516FA8F9F4FCF4E7BD91909F895A5687B9D6CABDBE9459170308225297B7D6E5E1C4883001001F65ACC8CDCBA9611B00001950A6D5D0CFD4C1742C09276CBAD6D8D8B66F26000000000A57A2D5EBEDE2AB43100C336FB9DFDAD6CDBF8019000011328EC9D7D1CECAAE5E1910296098B4C4C8C4C19C5409001773ACC3C2BEB6B59F671400045799C1BCAFB6B6A76E251E1E1E538FA59C91848F8250170073758ED4FFFFFFFFCB93685451555D8DD7F7F1BF5E333834142C58AAF0FFFFE1A861322525255FAEDC43B8B680512B170A0B1C3773BFE0CB77312D333E3C3E42D7F7F1BF5E33383401FE705F070718006F5A4E5A76B6F5FFFFF9D2B68887997A534D8DC8D4D8CBC38F551E000B254B8ABED8E4DCC3812D00002264A4CED9CCA5591500031E5CB0D5DED6CDB76F2F182C75C7D0DECFAF681F0000000009509CD6E5F5DDAA3A12163A78B3D0DEDFCCB1741A000010408DC0CEDAD5CDA74A14072F72A3B6C0CCC9C29A460800176AACBFBBB2B1B6A9661B000758A3B6C3B5B7B39A6D2F1B2333608C9CA39D8D837B5818006B7096DBFFFFFFFFCF8C5C5462615D8BDFFCE9BD67343F3C2F3467BFF8FDF9DEAB70351F252D58A4D849B9B67F451D040A121D3B85C4E0B5743C25353540334ADFFCE9BD67343F3C01FE715F07071810765E575D80C2FFFFFFFFC7A48B849B7D4D4C92CBD5DAD0C4944F230908255096CCE3E2E2D280290300225AA4CFD8CEAA571400002858A2DBE4D9C9B277361C2F81BACEDBCCB76813000000001661A3D2E2E5D49F3D0C18497DB6DCE3DACEAC6D110000144790BACCD4D2C4A24C130E36759CBDC6C1C1BE913E00001A80B3C8C4B7B9B7A8651A000C5B98B4B8AFB2B79B55252026305B8C9798948B8A83470A007C7899EAFFFFFFFFD890615453605F8BDFF5EAB76A353732263575C7F7FFFFEBA7612F1E242E5DB5D93DAEB47A4A291206001D3F88D0DFC0643B30362A2F3C3BDFF5EAB76A35373201FE725F070718206E605D607FC2FFFFFFF9C5A5828F9B7D54568DCAE5E7D7C68E4B231415315796CBE1E0DEBA6F240000337EB0C9D2C6A8490E00062467ABDADBD4D7B0783111277EC0D1CAC1B0610A000000001764ABDCECEDE19D3914204E7CBCD9E4DDBDAF641100002E4F90C7CED5D0C39743090D387DA6BFBBC3BEA9933D00002C7CC1C5B6B7B5AFA76812000E5FA1B8CAB7AEAD8C5C1D1F2D3E628E989D8F8B84844B0F006C658ED8FFFFFFFFC181605253596295EEFFECB267394034292E7AC8FDFFFBDE9E5D2D1F1F2864B0DA47B3AF6C3C160B0813193E83D8E3BC663A31332C343D4CEEFFECB26739403401FE735F0707183076695A6482C6FFFFFFF3C597788695735660ABD6E0D9DBC98945180B132F619ED0DCEAD2B4631D0007317BBCD4D9D5A84D08000C2766B6D7DCDAC6B06B2A113285BFC2D2C1AE5C15000000001D66ABDAECF0D9992F0E195F88C4E7D8D3BFA7600500002C52A0C2D5D3C5BC8E441513487DA9B9B5BFB5B38B3C0000287EB8BEBFB6B5ADA76E19000E5EAEBDC4AFABA58753261923346585A09F9A878672420A00757193DCFFFFFFF1B47951474B526BA8E7F8E5AF672E332F364883CAFEFFFCE1945728201D3763B7DD45AEA76C3C170B13191E488ED0DFBA623A2A293839404EE7F8E5AF672E332F01FE745F07071840796355667FC4FFFFFFECB68A748B936B5060A5D1E4E3DEC88E511F0F1A356496C7DBDDDFB6591300053881B6CBD5CCA6520D001240759CD0D2D9D1AF6825143687B8CFD5C7A75F0A000000001A6DB0D3E7EDD695310B205796C6D5D8DEC894530800002E5994C3D5D5D6CA9A3A091A4D83B1BDB9C2BDAC762D00003081B4C4BCACB0B3A3610F00186AAFC0B7B1B0AA873C1017313569979AA1958B8A75400B006B6B94E9FFFFFFEDB46F4E49535C64AEEDF8ECA24C2C3F371D387DCEFCFFF9E19E622E1A202967B7DF54B89A5A2D120C131A264493D7DDB26430322F30333F44EDF8ECA24C2C3F3701FE755F070718506D58546782D1FFFFFFE1A77D748C8D66465AA3D1DED8D3C98A461806203769AAD6E4E0CC9D601500073F81BACED3D0A34A08000C3569B1D8D9CBD0B36A2C1A4883BFD0D6CCAF5901000000002465BADDE7E2D28D3110236698C1E0D2D3C58E4E0000063F61A1C9D0D8CAB7852D121D5794AEBAC1C1BDAD77210000308EBCC1C4B8B4AFA05F0F001368AEC2BEC4B7A7783B1A272B386590A4A7958E85763403007D86A8F4FFFFFFFFB7805045506078B5F4FFEBAB5B323C33304B8ED7FDFFFDD99A572F191B2366B3DE50AB9B5E3517141C17253C98D7E6B46523222F312F374AF4FFEBAB5B323C3301FE765F07071860766A5A6383C5FFFFFFD99A70637E7E705365A6D3E3D7DECA84421F0D204173AFCFDEE3D6A25114000F4B8EBED7CBC99B3E0000194280B4D1DED4C2A16223183A8CC3CCC9CCB65608000000002077BFDEE6E5D08B2B0B29699CCED2DAD7C893470000114167A1C3D2C9BFB881290B1B549CB5BABDB4B8AA6F220000328CBAC9B8B5B9B79B5A12000F66A3C4C7B0B09F6D2F142A29406D8FA297938B8A79390900757BA8FAFFFFFFFDA7694D4851647FC7FFFFEAA6533232262B3F89DAFFFFF6DA8F56291F192B6FC1E65DB69D54281218131D244691D7E3A95A302B2C353E3A54FFFFEAA65332322601FE775F070718707E65606B97D9FFFFFFD397685F8B7F684C6AAFDCDEE8DFCF944B2414214876B8CFE2E7D49B460A00013D94C3DBDFD09F470804113D7FB2D1CBD9CA9B6523183A94B8C8C9C9A94D0B000000002075B9D2E6E7D382250F3774ACCDD6D1DCC2823300001B4D7CA6C9D2D3D0B86D220B275E99B6C0B0C4C1A7621D00002782BAC4B4BABDBDA36517000C6BA6B6BEB7B7A66E2C1A2338467A9DA29B9884896D2A00006D749FE8FFFFFFEA9F664541485E85C7F8F3D7A5513A372E224592DDF5FFEFD5975126221D2E66B5D94DAA8C582E1819181628418ED6E2A558322C2D2A3A455EF8F3D7A5513A372E01FE785F0707188078736774A2E5FFFFFFDA99676A87815F4D6CADE8EDE6E7CF95411E0B2A4A7FB6D7E2E5C0933C03000949ABC2E0D9D5993C0400144B8AC7D8CCC8BF944F231A4296BBCDC8C1B35009000000002F80BDDEE5E9C87328103176AAD3CFDADBB77420000021647EB3C8D0D5C1AB6C1D05225C9EAFB9B1BDBDA7661600003E99C1C3C2B8ADABA05F18001679B9BEC3AFA897682309232E477A9CA1A29C978D702B00006F70A1E9FFFFFFF5A8634E38516580D1F7FDE09149223837244F9EDDFFFFFDD494552E23192275BEDE50A2804F2610151616234E98D6E0AD5D3024373F43395AF7FDE0914922383701FE795F070718907063615F8FD1FFFFFFBD774A5071765F4A63B2E5DFE2E0CA8C3C22102D5787AFCAD7D6C98F3910000C55A6C6DDDBCC943F090B20558CBBD3D3C4BB9350211D4891B5C6C4CBA75700000000003A85C7CBDAE4BB6A1F093184B9D3D6DAD2B267180000296683B2C7C7C2BFAB6B1D002972A1BDBEB6C0B9A35F0C0000429CBFCBB6B8B2ACA2651C001168A7BCC1BCAF95571E0D29374A789BAC96918687732A00007370A2EFFFFFFFE29E5B43343E6DA6D5FFFBE18E4F293B3A324C99E6FFFFF0CF863F271A172A7DC1DF57A98E4F1B040D1613294491D5D9A4552C2B39363B3C52FFFBE18E4F293B3A01FE7A5F070718A0715B51678AD5FFFFFFBC733E547B7658496EADE3E8EBDCC885411C0B2F5588C1D8E7DEC7863100001356ACD1DCCFC598420E091F5899C1CECFC8B9864A15163C8CBDCAC6C2B45C06000000003080C3CCD9DDC17721133E86C5DFD7D9D6B860160000226587AECDC2C4CB9D5313104079A9B2BEB0B4BFA7561000003A94BFCBBFB6B3B79C6018001678B3B6B5B4B792531B0C1D2E497E989F9A918887631800007176A2F5FFFFFFD08252343C4167A1D8FFFBD9964B283830234BA0E8FFFBEFCF884824171E3B83CAE454957E4B1A0C151816213DA1E0D9AA57322E423B353C5AFFFBD9964B28383001FE7B5F070718B06A5A4D6791C8FFFFFFB36D3E466A6F5A5974BDE6EAE3DFCA8B42170C2E608ECAD8DDDCC97C2600000E5FB1D0DDDCCC942E000128639BC6D4D5C8B77E3F1818468BBBCECBC4AF4E00000000004597C5D1D7DBB069200E3E90CBE6D9DAC8AD4E0E0000287194B5C6D5CDCE9E530C0D3772A4BAC4ADB3B6A3500500004A97B8C1C4BCB9B3A6670E001A77A2B7BAB8B2944E130C2B324C84A2A2A0A09B855C1100007271A9FCFFFFFFDD8D5440394D6D9DE2FFF7D7914D2B3530284E9CE5FFFFE9C68245241A1A3580CEE253A07B381B060F18251C3E91DFDC91513A35393E314160FFF7D7914D2B353001FE7C5F070718C073655C7795D7FFFFFAA9653A4B736F464C7BBDEBEFE5E1C77E371814366397C0D8DEDDBE752700001167B5D5E0D2CF9B4000083575ABC7CDD5C1A97336141E4E8ABAD0CBC3A6540B000000003D94BEC5D3DEB65E0D094B97CDDEDFD5C89F4D0300003C89A0BED2CBC6B9913F03094786ADBBB4ACAEB8964900000356A0C3C2C0B1BAB1A1610A002377B1B2B2A7A58A400B0821374F85979793918F936C2600007376B1FEFFFFFFD37B4433384573A6E1FFFBD78C461F2B31284FA2F4FFFFF4C88A4C1C1A1D3E8DD0E55698703C18110A19132651A1DCDBA2582E2C322C304060FFFBD78C461F2B3101FE7D5F070718D07A645F6E9ADCFFFFF4B2693D4A6960535C7EBCEDF3E5E2C5813A1C143B6E94C3DADED7B3731F00001167B9CADCD8CF934413143D84ADC7D5CBC6A86B2909124D8FC4C0C3BAA6450400000000439BC7C9CFD3B7641C154A98D2E6DCCEC493370000063D88A1C4C8C0BFB29241051F548BB3C0B4A4B5BA91410300085896BFC8B0BDB9AC9D6213001A80AFB7B9B4AD7F2E02001836608CA6959189888A5E150100797DBBFFFFFFFFDD8A5139405576BBE7FFFDCA89462C292F2455ACF4FFFFE7CA7D331B14224496D9EE47A37B44250E0E1218204F9FDCD5954829212E3B393E5CFFFDCA89462C292F01FE7E5F070718E07560556D8DDCFFFFF5945537456759535776BAE4F3E1E3C8792C1E283E749BBFD5DAD0B46D1F00001368B9D2DDDFCF953808103F84ADC7D1CEBD9A5C2B0A1F549AB6CBC6C0AD54000000000053A6C1C6D2D9A9530F0E4FA0CCD6D5D2CC94310000094B94B1BEB8C6C5C0883C060E5594B3BCB4A4A8B8903300000E5795B7B9BBC1C2B6A1611A002071ADBCB2ABA0813609041C3A5D899F9590919793590E00006C76B6FFFFFFFFCC874936364372BBF5FFF6CC80461E25252056ADF5FFFBE5C07B3C1919244790D4DF49A1793F1B081517081D51A4E7D59348262B4140374163FFF6CC80461E252501FE7F5F070718F077625B7094E3FFFFF0955D304158594C5B7EBAE4F0E8DFC2813715194B71A2C7D1DAD4A7561000001B6CBED1DADAD98C370C114683B2CDD0C9C4994F1F0D25569EB4C6C6B8A94E0000000000509EC3CBCDC7A656181556ADD3D8D1C6CE912F0000044DA0BABFC2C1CABD8B3702175E99B3B5B6A8AEB285360000156CA5BEB9B4B1B2B09A5314001C77B1BEBFB1A379380B0628335B879E97969C9B84571300006F7BBAFFFFFFFFCE7F473933487BBCF4FFEFC47D443425272864B8EEFFFDF1C47E3C1F182A4B9FD2E847947F441B101315110F469CE4DA8E4A2A243432434368FFEFC47D4434252701FE805F070718006D5B517197DDFFFFE7894527345C4E425681C2E2E6DAE5C27A3317184387ADC6DADAD6A1520B00001C71C3DDD9D6C4862B0E15508BB6CCD0C8BD91521E0C2A629FB5C3C7BBA44500000000004FA0BBB6CDD3A752141959A8CBD7D9CEC18C2700001365A4B1CACFCBBBAF7B31061F699CB5B7B5A1ADB37E250000196CA8C1BFBEB6B6B1A05E0800217CBEBFB7B4A375360A001B405F91A19089909A91500B0000737ABCFFFFFFFFC66A3D36334884C4FBFFF0C08A472B222C386ABEF3FFFFE4B682421F1B2B52A1DDE84B95793E170C0D15152450A7E9D78F3F262C2E35474765FFF0C08A472B222C01FE815F07071810795C52709DD1FFFFF08D46273A5A4F4B5A86BFE4F2DDDEBE7336111C4888B3CDD5CFC9A0560F00001C72C6DADBDDCA822A03085099C1CCCECDBE914E18111D5398C2CDC9C4AA51010000000059A2BFC3C7C59D50121962AFD7E3D6D1C7892100001A6AA8C3CBC5C6BEAB7023002474B2C4C1AFA1A3AA7D2800001C6DAAB4BFB1A5AAAA99550E002874B3B7C3B9A369270800173C648FA29385939C8A4A0A00036F82C3FFFFFFFFC36C372A315680C9FFFFF9C685482D191E2B60B5E7FDFDDCB071371F1E3968ACE2E649937B42180B06131F265AADE8DB8A3E2A303D44414B6DFFF9C685482D191E01FE825F07071820755F54649CE6FFFFE277342033544C516A95D1F2F1D8D2B25D2D18215194B8C8D4D2C5954B1000002380C3D7DAD7C57F2B0418599FC5D1D4D4C08B3C0B022B639ABBBCC7C0AB470400000008589EBCBED2CB953E12195CB3D7D3D4CBBA84180000216CADBBC2C6C4B5A76C1D00296CAAC2B9ACAAA8B188320000307DAEBDBCBCB2B4AD925906002475A7B6B9ACA5692109070F336692A796969696854F0C00007486D5FFFFFFFFC37D4C3235478AD5FFFFF6B67C463525243573C5FEFFFFDBAA63341B282662AEEDE84C9779471E120F0C113657B6ECD591442D293638304775FFF6B67C4635252401FE835F070718307C6455699FDCFFFFE4844324365A4B52618ECFF6EBDED7AF632A17245691B7D7D8D9C38F400000001D75BEDEE3DED07B29062165A9C5CCC8CEBF802F090734639EB7C5CAC89C480B000000025AA3B8B4CBC6914D13165AA8CDD8CEC6B482240000227BB5CACFD1C1ADA66410002D78ABC3C1B4A9B09E74210000327CB4B2B6B6BAB6A5904E0300217DAAB6AEAEA0642002061B40659A97948798997F4007030A6885CEFFFFFFFEB3714936365390D5FFFFE7BB783E25231A2761C1EFFFFEDBAC6C3819223178B9E8E34D9D753522120F0B11285AB0EAE28C472F2D3D363B4B7EFFE7BB783E25231A01FE845F0707184071584B5C88DEFFFFD37C351A2F46453D5C93CAF0ECCBC79F58200D205BA7C3C7D4D7C1813B010000277AC5D7D6D8C371250A2368ACC6C3D3D0B77C3108032D75A4BDBEC1BFA43E00000000076AAEC1C2C5C78D39091B64B8DDE4D7CAB9781400003180BDC7C0BDC5BEA65E10002E82A9B2A8B2B0B1AB6D1E000A3C789FB6B6B5B1ABA3914A08002A7DBAB5B2AA9D652000011C41759EA79582929680430B0003738FE6FFFFFFFFB56B414142578CD9FFFFE5AB704A2B222A3C75C7F3FFF7D2A96B2C10214276C4E6EC4E9A743C1C130B10182264C3F5DC8F412A2B3C363A4979FFE5AB704A2B222A01FE855F070718507A6D636DA0E3FFFFDC7139263A453C53709DD3F3E8CECBA355220E1850A7C6D0CFD2C47C35000004307ACAE2DBD1C36D16021C6AABC7CBD8CDBD752C00043E82AEBBC4BCC0A23E060000000D6CAAB9B6B8C087350F1C58B4DBDED7CEBF7B2000003988BBBBC3BEBAB0965618002F8CBCBBBAB1A9A899651900134787B3C0B9B7B7AAAA853D00002576A9B7B6A79B591C0204193B6C9DAC8F7D8F8C823900000A6F93D8FFFFFFF9AF613B353F5398E1FFFFE6A76F402724273372C5F6FFF7D19F63341C0E3A83C8EDEE438A754F241712090E2465C1ECD47D3A25253D383D528CFFE6A76F4027242701FE865F070718606C58506494DEFDFFDD77351C2B45424D6BA2D9E5E9CFC195441B0F1B5EA0B6C2C9C8AE76280000073183C2D9E0D5C372270F317BB1C9D0CDC9AA742D0B0A3A74B2C9C6C3BC8B37000000001B67A4B7BDC6C88830072053B0D4DFD5D0BD731300004080B1BAC6CFC5B6964B08003F89C8C5B1B2B2B69D680D0009448CB0C7C4BCB2B3A3903B0000276E9CB3B8AF8F561A00001F4466949D84848E9478360301087F9EE5FFFFFFFCAD64433B4C62A1E6FFFFE0A36C4329272E3E7BCBF6FFF0C4945B231D2B5188CEEEE53E8D663022100E10193264BCEDDB82302425383F424888FFE0A36C4329272E01FE875F070718707A66506AA7DFFFFFD7753816233F3A5172A1CFF0E4D2C38E421D0D2869B0C6CDD1CFAD73280200053282CBE3D7D9C1681F0F3681B3C5CCCBCCBA5B1B00023A81A3BDC6C2C09D3F120000001A6CABBDBDC7B87729062066B4D1E2D5CCBD711500003C8CB9BCBCC8BEB2933B02003592BCC2B6B4AAB2AC6408000F497FAEC0BCB8B6A49F963B0000297FA2B1BAA89057160A001B3F7998A183829BA1853600030A7897E0FFFFFFE3995940343B64A3E3FFFFE49E6F412C203C3273C3F2FCECC691552110244C97D1EEE93E8D70382711151520306ECCF4D27D3424302D393F4B86FFE49E6F412C203C01FE885F070718806B5950638FDCF6FDCF712F0B21383D4F75AED9E5E2D4BF8C4314101D68A8BFCDD8D2AE631F000005418BC3DCDACDB7691E073B89B8D3CCC7C0AB580A00064B88B3C6BFBCAF903F050000001972AFB3B8C2BE71290E236CABD3DED0CCBA621100094E9CC0C0C3C5B7AC802E0400368FBDC2C1B9B0B59E5F1000165890AEB7C6BAA59293803200003581A5AEB3B19753190B031A406893A97E78938E722E080E2481A4F0FFFFFFEC9B62433A345DA4E1FFFFD5975C3D2D28272B7BC3F2F3EABE875927162858BFE6F9F1428F683F1F11111B1A2774C7F3D07B36232F302C395489FFD5975C3D2D282701FE895F07071890765E516DA3D7F3FBD06D2B151B3D3B577CB2DCF0E2CFB8822E0B0B296EB3C9CBC7CB9F5F22000006398CD0DDE1D8B95F19124993C3D9CDC8BEA7511500094E8EB1C5B4C0B081310F0000002479B1C1C2C5B5661F021B64B0D2E2D7C7BF630100084E9AC7C2C7CCC9B1883C02004485AEBCB5B2A1B99F5D1202236099B2C0C1BAB49E977C2C00002F789EB3B4A78546160502124578959C837B988C702800061788AFFBFFFFFFE7905F3F2C3C66B7EEFFFFD5925D372B262C3B76CCEFFAE7B98B522F242E61A9E3F3EC408869401A0C090E1C2D82C9FFD76C302B2F3A2E3F4897FFD5925D372B262C01FE8A5F070718A0725C5166A2E3F6F7D2702A12273A3A5A81ADD9E3D7B7A8732F100D2A72B3CBD4CCC49F5919000008509DCBE4DECAAF5D1D16458EB3C6C7D1C6A54B0D0013579AC4BEB8BAB57E2E030000002D81BABABBBFAF651B032764B3D4DCD4C3B25A050009539CC4B3B2BDC7A97B280000469BC1B4BBB7ADBDA54E07022A619CB1B9B3BBB4AB92782E00003589B0B8B5A2803E1500070C417A97A78876928F682000041A7FB8FFFFFFFFDD9C60433B4174BCFEFFFEC99057362A272E4580CEE1E8E2B87C5630192665AFE7F1E3438969321D15131B293B80CCF2C975402C2530363E5891FEC99057362A272E01FE8B5F070718B0786855749DD4F8F8CF6B2E162032415E8FBAE1E3D5BAA471340D081D70B0C7CDD2BE9B52130006194E94D9DDDED7B2601E11449BC1CEC9D0BA9B4D0B0017639CB5BEB9BCBA8D36040000002374AAB7AECAB65F1D022676BFCFD8CAC1A8590300165F9CC0C3BCC3C1A36C150000509FC5C0BFC0B8BCA3560C001F60A0B2BABCB3AFA08F712100003881A8B6ACA4823C0D0805194D7AA49C797C9A9A6F2D0B001E8AD1FFFFFFFFD1884E3F353C60B8EDFFF0C77C4F37222C2F4383D4EBF2E3AF794F2C232C5FA8DCF2DD478766391C0812161A368ADBF9C97B352328333544519BF0C77C4F37222C2F01FE8C5F070718C06D545173A4D5EAEED4722C0D0C252A5C92BAD9E7D7C2A05E2103092C72B8D1CDD4C993420D0000134FA0D6E9E8CDAD521111599EC4CCCDD2D3A549010008549BC1C4C3BDB07D2B0D0000013282B6C1C0B8A45B1B082868B1D2D9DDC4AC590A001167A0C6BCB2BDB7AC772000004C9FB8C6B8B0B6B4A14F08052A659EA8B3ACB8A99B865D1400053B84B3B1B2A6833E1D04051E5480A8A976788B92621900002A86C3FFFFFFFFCD8B573B464771C5FFFFFBBE805731242830458CD1E3F0D5A96A462D223172B8F0F5E24187603A1A161520243C91CFF5C971302E2C3A3A3C569CFBBE80573124283001FE8D5F070718D07B615575A9D9E7DFC46D1B040B27355D91C1D8D8CFB2915E1C050F2278B4C6CAD0B98B440000001556A7D2E6EDD79F4913155AA4C8D6D6C8C39E3F00001767A6C0C4B9BCAD733010020000327EB2C4C0BF9C520F00226EB3DBDBD4C9B54F0400196DADC0AAACB4C0AA6F1A0000509ABDBFBFB6B1B1A1540C0B35689CACBDAAA49F9083692000004583B0B1AFA2753A16020019547A9EAB777D968D6415000B3091DBFFFFFFFFC579473A343E71C6F9FFF9B27C48332224313E82CFE3E6D4AA5E3F2A2A337AC2ECFAE4447E56341614121D1F5697DBFAC6702A212C3D3C405CA5F9B27C483322243101FE8E5F070718E0775E627EB6DFF0E4D0782B03082430548BCBEFE5CEAD84561B0008296CBDD3C9CABE8D371200001F5AA0D1DBDBCE9C4A161D5CAAD1D0C6D3C7953B06001E67A8C7C2B2B4A6661C000302022D8BC2C0BDB9965612052D78ADD9DCD3CEB45600002077A2C3BAB8B9B2A1601600004B9EBAB9BBB7B7B799470A083D7BAABBC3BEB8A8847051190000347DACB9B1A0713A12060020558C9DA880809991551A00042491D0FFFFFFFFC3754B2E263777C5FFFFF0AB7645291E2B31387EBFDFE7D7A267412E1D3377CBF0EFD34A82622B1C0C1323224B9EE4F2C46F3325242F34445CA6F0AB7645291E2B3101FE8F5F070718F07569607CA7E1EFE3C96B2D0F08273B65A9D4E3E9C49F834618040D3385C5CAD2C6C686360700001C5DAFD9E4E8D29245161960AECCC8BED0C28B3702021E69AABFC5BFBB9E702C040300124587B2B6C2C2964003022B74BED6D9C9C3B04F01002C81B9C8B4A8AEB79C590B00004B97BAC2C2BCBBB9954D1112488EA3B5B1BFB1A88D6D4B0F0005418BA8A9B0AB69301806001D588CAAA5868B96935511000C2B9FDEFFFFFFF5BA6B442D3B4181D1FFFFEBA262322F2E28303D91C6DEE5CC9A653E2F2A3883C8F3F8E34D7F5D2D17151B1D1F4DACEAFDC5682A1D2937384666A6EBA262322F2E283001FE905F070718007A706897B9DDF1E8CA682A0E0B26386BA7CAE4E3D1A3753D0E00093788C5C7CEDABB742E0500062A69B4E6E4E3CE9341191B65B8CAD5C7C9C3933400001372A4C4CCC3BDA5642508080F1E4C83A5BCB6BB993E0F04347FBECFD5D4C0A34400002780B3C5B7ACBCAE964E05000155A2BFBAC1BCB9B59241040D5288A9B5B0B3B59A715D490900064689A9B5B79D74341A0C04225388A2A7817F9B83471609163AA3E2FFFFFFF7AA674031314A8DDAFFFFE19B6E442D2C2F2F398DC5D9DECB8D5D371D1D378CD2F9EDD05173552D1A1F1F2A315AABE7F9BD6F272123243A4A61ACE19B6E442D2C2F2F01FE915F0707181078636882B8DFEAE1CD692601091D3C78A8D6E7E6CDA16C3D18030C2B82BFCACAC4C5812A0000072C76B6D8E7E2BE8D420A1764ADC9CFCBD9C1863906002077B7C6C2BBBCA46528110911264F8CAFC1C3BA8C3D08072D78AACCD7D6CBA43F00002B7EAACABAB5C2B4A048060004529BC8CDC2BEBFBD963F0C12488FA5A7B9A9B4A3775A3D0800044191B1BBB6A4652D0D02021E5E8EB1AD85909F874408001A37B0F1FFFFFFE8AC634035344887CFFFFFF19A643429262F30447EB6BDCAC4915D2F1F29418AD4F8F6DD55784E29161F20223055A4E9F9C2672B2024363C4E6AB5F19A643429262F3001FE925F070718207D767C9DCEE9F2F7C8772D070520406EB5DEE7E6C38561320800113F8BB7C8D0CFC0762E0000083875BBECE7DEBB82320D2469B5D5CAB8C7BA882C0002287DB6BECEC3B7A662291108121D5198BACAC8B0842A0000377EBBC9DADFBCA04506003887BAC6B3A6B5BD934300000454A8C2BFB7ABB1BA8A36091D6189A3BDB7BAB7A57A512F0A000B4D92B3B8BA9B67330C0105226096B0A987879685440B001643AAE5FFFFFFD8905B3F2C32478DD3FFFFDE9153352D28252E4D94C6D3D2BD884D2A211C4595DFFBEACE4E71482916181D26325FB1F0F8BC5A26232E313B4B6DB7DE9153352D28252E01FE935F070718306A7683A4CDE2EFE5C767250000153C75B9DFE4E2C78B59280908164587B6C2C9C5B97528000008327EBBE6E9DCCB7F35182564B1CBCBCCC9C3842400103583B5C9C1B5BC95581C100A13245894B8C3C0B07C2C02052A7AB3D8DCD6C09B480002448EC1CDB9AAB8B490460100085C9EBEC2B7B5B9B1862A001E5C96ACB9B0B3B1A4694A220000125F97BFB6AE9A60210D0C0B2A6195AAAD9292A080490F00144EABFCFFFFFFD88E4E2A2A334991DCFFFFD3834F2E20212F324989C0C7D8B07B492E21224698E5FDF0CD536D4E33201827325166B6F0F3B16632201D30324374C3D3834F2E20212F3201FE945F07071840797F8AAAD4E6ECE6CB6D2707051F407FC7E8EEEDC9824819000118488EC0D3D0CABC7623000012488CCEE0E3ECC876300C2776B5CDCACFC5BA782502013586B2BEC3B9B69D5724110B1A256398B4BABEB57B250005367FB6D2D8CBB699450000438FBCC4B2B7B8B28B2F000009559AB7BFB6BFC8BC862200186A96AFB4AFABB298643F1F0000165092B8C0BB965E2A15050F2B68A7B8AF94879981400D081F47ADEBFFFFFFCD7D5036222C4293DBFCFBD3843C2D272A2A2F478ABABCC8B8874C2E273049A7F5FFE8B44965482C1D222D273E6ABEF4F9B7652F1F2630354D82C8D3843C2D272A2A2F01FE955F07071850757783A2C3DDE6E6C6671D0406234083C2E6E5E1B97045170200194D97C6C9CFC5BA6E2C0000134082C1E0EEEAB95923123077C2CFC5BCC3B280360B0D3E7DB7C7C1BEB08E592514081A4061AABABABDAF772100003592B4CCD1CBC29A35000654A0B6CBB1B2B7AA813000000859A0CAC2BBB2C6B97821021C63A2ACB7ACB1B59E6233150000285C99C1AFA995572914010F2F64A6BFBA968FA1853309001348B2EAFFFFFFCB853F2423344FA4DFFFFDCC8646261E272A2C4993C1BEBBB36F45202B2C4D98DBFFF2C45B6A4720212B29293B6AC2F5F8B45A2C2627393E5989CDCC8646261E272A2C01FE965F07071860747E89B6D0E7DBDAC6752D060018488FD5EBE5D8AD733F1C0001195799C4D0C8BDAB642000000B4694CCE5E7D3AF60281B3A80CAD3C0BCCEB57D2C060C4393B4C9C1B8BB8B4F2B1B11234B709CABB3B4A86C1C00003B84C4D3D3CFBF902B00005298BBC9BEAAADA991330000035999C2C1CDBBBCB77716002471A1B9B9B7BAAF935C320A00002660A0B3B9B59A4D270F0C0F3366A3BFB49D8E9C7E3408031644B8F2FFFFF5B37A422B26335099E4FFFCCA7C46202527262D4B92AAB3B8A76D45282B2046A0E3F9EDC55C6B3C2419232C334075C6FFEAB05D2A2228353C4C85D3CA7C46202527262D01FE975F07071870738293B6D2EDE0EBC56E2100001B5197D3EEE0D6B5703A1000002561AFCDC7C8C4B16C2B0E00154694C8DFE5DBAA51180A2B82C0CDC5B9C5BB7B28000A488DB7C2C8BDAF8A4E271B142853749FAEC3C1A863120000388DBAD1CCCDB69831000D53ABBACCB6ADB8AB762800000D5FACCAC1C0C6C3B16A14001A709DB0BFB0AFA69C57250900002A68A0BFBFB6935C2B13080D3B83ABC1B08D8C9379340A041C4EA9E7FFFFE5AA6A371C223349ADEAFFFDC76D38242521252E4A90ACACB8A96A3A271E2E4FAFE9FFE9B25464412021142B3C4B7AD2F7EBAA643519253435568DD7C76D38242521252E01FE985F07071880656C8CA7C3DED9D7BA5F2600001E458CD0D8D4CAA7692B0300002661A4BCC4CCC3B5691A00001C4C96D3E6E8D2995420103A81C1CCB6B8C5AC6D2A111C4895B0B8BEC5C2A0512D1E1E365F7A9FAEB2B0A1580D00013B8DC6D8D6C2B18132000A5BA9C3CBB6A3ACA5762A0000005EA1C7C5C2BBBAA86412002870A1C1B5BBB7A29C4D220300003173A4B5BFC091562A1400083272ABB8B49592AB752E0F0C2C53B0E4FFFFE7A26A381E253348A7E6FEF8CA7B4523252629294C90AFA5A7986A4333293058A8E9FAE7B65A663D220D1D2F344B95D6EFECAA5632212830315199E2CA7B45232526292901FE995F070718907184A5B7D3E9D9DBBB67270800164F97CDE3DAD0B36D340000032368AEBAC9CBCAB05A1700000D509AD0E9E4D49F4A121A3A87CBCDC7B9C7B7671E091F5897B6C5C7BEAD824C32211C3B6178A0B4C2B39552100000378DC5D3D7C6B07B23000E58A3B9C9B2B0BBAC7B1B00000B539CBAC8CCC1C2AF6E0F002772A1AEB2ADB1A58B4E130000023676B5C7C7B6924729150A143B82AABBB99A9F9E652500051E57BAF9FFFFEAAE603628213354ABEEFFF1BE663D2328243033498EA6A2A08D6541262C3458B0F0FFE6BB68633C231F202739508AD3F6EAAC5B2A2624202F5F9FD8BE663D232824303301FE9A5F070718A0697DA0C8DEEAEDE0C9651F02001D5A9AD3E0CDCAAC5B1E000001275FABBCBCC1CAB3642204021E55A5D9E3E4D5994A1C144691CEC8C6B9CDAC5A15091F5D97B8BFC0BFB88D472B1014375784A9ABADB19C570F00003391CCD5D1C9AC7529001D64AECAC7B7B5B3A4751B00000B6BAABAB7C6BAC0AE630E002B80AABDC0BCAAAC8F44050000023874AAC9C2B88F4823110A15498AACC3C099989C6B2500002754B2F1FFFFCE9C5E32212B3A52A4E9FBF9C467332929232D2C5196AEA6A28B5D3322222E64B1F2FFE3AE635E331A1E232D455999ECFEEF9951251F252B3C57A5E1C467332929232D2C01FE9B5F070718B07A92B1CCDEE6EADAC6783200012A599ED9EEDDD2A259210000062F72B6C2C5C4C1B456190000295D9ECBDEDED79C4510104BA1D1D2C0B6C8A5520F102D599DB9C3B8B2AC824C2E211D3B668AA0B2ACAF91420200023E97C7DFE2CAAA7620001971ABC1CBBCB7B5A06215000015619CC0D0BDC5BCAB5309003679A5BBB7B1B4A98833050000003979B0BFBDBB92492A1C16254789BFC2B39F9A9E63200D042152B6EFFFF9CD8B481D15142253AFEBFFF7BC682C2026222E355596A297A28B5B3A30263560B8F8F8D3AC695E392A1C1D2A4566AAE7FFDF9140211C22373C64A0E6BC682C2026222E3501FE9C5F070718C06983ADD2DDE9D9CEB7651E02072A5CACDFE7CFD0A2571A0000053374BFC5C0CBCCBE601E00031A50A4D1D7D5D48E420E1D4892CCC8C6B3C1A0561B0E375F9ABBC5C8B5B08D553F171F376C8EADACA9AA7F360000003D95C9D3D4CAAE731F012163B3BDCDC0BBBAA36C1C00001861A1C5C3C7B7B49D4606003980ABB6B6B7B3AD8136010000053D89B2BBB7B687492616101C4F88AACFB9AA9B97612309112C63BEF8FFFFD09C552B111C265FB5E9FFE9B75B2D1C2827282F559AA59E957C54322B2F3767C0FAFFDBA6665D341E1C282D4072AEE8F4E08D462F1A28314370AEEFB75B2D1C2827282F01FE9D5F070718D0768DB7D7F1FAE3DFB8662A06052F66B3DCE4D3CDA65D1A0000073574ABA9B6CFCDB15F1E00072569BCDBE0DCD48C31101350A4CCDCBEABBAA25419173B69A3B6BDBFC0B575422D121D387493A9B1ADA78C410000084FA3C7D7CEBFA5630F001E78B1C3CBBCBAB1A55D170000095E9FC2BFC2C5C0A54A06013585AFC0B2B4B6A5772C000000084F8FBBD9C9B47F4A22140C205090B9BBAD9D96965B200308224EB2ECFFF0C5823F24170C2A54AFE7FFE7B054220B1E2B3234588E8F89997E5131222A3863B7FEFBDCA46E5A311C19152D4569AAEBFBDE9B461B1C2732396CBBEDB054220B1E2B323401FE9E5F070718E0708EB6DDEEE7DDD0B06A2900032466B5DFE6CCBF9A511800000B3784B2B1A9C2CDAF5F14000A2870ADDAD7DBCB852F041754A0CCDAC4B9C895461C1F4073A2B9BABCB9B77D412C1A1A3A7093AFB0AEAB833500000A4599C4D7DDCF9F5D16001D71B0C0CBBCBFB3965F1400001E6CA8CDC9BFBDB8934405003080A7C2B1B5BAAA7E29000000175193B0C6C3B48446261A08145088B3C3BAAD9E9258220004285AADD8EBE2B883462119222A51B3E4F8E2A952231615192832609B9296A17B472F1E2B2E65C4F4FAD990725734241C1F315379B6F1F8E29145282627304676B4E7A95223161519283201FE9F5F070718F07497CEEEF5F0DDD9C068260A10326BB9E5E9CDC594470F00000B3C83B7AAA8C1D1B4551801072874B0DFE6E0C87D250417509ACBC7C5BCC796431118467FABC7C7B7BDB178452F1F1A478292B7B3AC9B7B2D000000439EC9D6D2B5954D0F042D83BACBCBC2B6AFA35F0E00001D649FC1BCB5C0B28C3E0700428CB6BCB3B7B8AF822F000000185092BBC3BCB6873D2517091C5F8FBCC6BEA4998C5B1403063360B2E6F2E6B46737100E132362BFE8F7E1944618141E272C2B549193858E80502A2236366EBFFBF3C488765739251C28305C80C2EFF0D28B47241E252C3D74C4F3944618141E272C2B01FEA05F070718007CA3C9E5F3F3E3DAC2673007083C80BFE2E7D2D294490F0000073E7AACA8ADC9D4B3520E00083677B7D4D7DABA7B2C0B265CADC8D7BFB7BC93421A205479A8B6C3B8B2A7784824141847869BAEA2ADA37A2900000350A4CED7DBC095530A002C7CAABDC5BFB9B9A55C0B00001F6AAFBBB9BBBBB3943700004291B8C3BAC0C2B2812C000000125F97BACBC0AC76452C190A215D96B5BDB4A3928F591600063466B2D4E7E3AA62270C0F131D59B6E7F5D898411C162218223466989A837F76422F2C2C386ECCFFFDC98B75512724131C366486C3F3F7D07E3E1E131D2F4079C5F498411C162218223401FEA15F070718106E8DC2D6E6EBD5CCB85B1F00053679C7E4E6D9BE864A0D00000F4087AEA6A3C7D3AE5811000E3C71B6D3D7DCC5742A0B1F59B0CDD7C0B1B48B401823598AB8B9BBB8ACA9693A23171B4B849CB0B8ADA0742700000951ABD7E7DEBA9B570F00307FB9CCC4C1C2B19A540A00002772ABC3BEBCBCB6914300003C89AEC3B5B7AFA9762300000018629DBBC3B8B57F4B2F150D235B97C0BCB6A997884614020A3966AAE2E6D4A764280D03102063B7E8F1D69542251921312A2D65A09B828271472E34305277C0EBEDC78672502B23181F356887C7F1F2C57B3B281D1F2B4682C7F49542251921312A2D01FEA25F070718207B9ECFE4F1F0E1DAB55C29090A4087D6F1F4DECB8C3E0C000011418EACA1A4CBCFB14E1301123A76BBDDE2DEBE701C0A2263B0D7C9C3B3C3833718215486A9B6B4B8BDB06A3C271219478FA1ADACA894601C00000B50AECAD6D8C18A3D09002A7DB9C6CBD4C1AC9C4E0600003180A3C0C3C0BBB9973900004392B5B7B0B6AEA66F200000001E649FC4CFCABE7743361A0E2A5A97A7BFB1A39893511403073B6CACE1E0CE9A52140000082160C4E2F3D498471D1624140C306CA9978A7C75422828363B74D4FCE7B886774D2C1D1A24336CA2D9FCEBC56D251C1B23384C97CCEC98471D1624140C3001FEA35F0707183077A0DEEFF1EDD4CDB2682600054287C6EFECD5BB87410C0000194A91A59CADC7D1AF570D000C4281B7D5DACEB96820052E68AFDDD9C9BBC680381127658BA8B8BEB8B6A362342E141B5790ABBAADA992651A00000758A2C8D7D6C48F4002013A85BBC5CCBAB5AE95460100002770A0BFCAC9C0BA8B2B00004789BCBCB0BBB1A9741A0000001A65A9C2C5BAB97B3B2B1A1C2D679DB7BCB2A7948E4B1A0C0930609EC6CEBC8B47100500030B57B4E9EAD383300F0D0C14293070A0977F826B3C2F1F293177CEF7EBBC857E4B231B3027426D9DD0EFE4BA6B371E18242B548EDAFF83300F0D0C14293001FEA45F07071840739BCDF6F3F6D7D7A45222010B408DD0E5EDD3BA81430A0000124C90B3A0ADC7CEB85D0F03174A97C2DAD6D5C3691E05276BB7D6D3D2BCB56D2C09235E96B6BABDBDB1A1572D1F0F1A58A1B2B4A79E91560F00000354AECCE1DDC28633000B3E8FB2CFCDBDBFB98940000000337BA4C0C3C4C8BE8C2700034E93B9BDB6B0A69F6D16000000205FA2C6C3C1B278472A1C1533639EB6BBB0A09B8B4614020D386FAFCDDDCC8B41190100001968C7EAF6CB873920151A261F316AA39A817B5F412F27343C7AD6FBEEAF777C4823211F2A4972A7DCF8EABD642E1920233A508BDAFE873920151A261F3101FEA55F070718507CA9D1E6EDEBE3C6AD60261018499CDCEFF3D9B57D36080000134D97B19AA5C9D3B9550B0012468DCED4D4C7AA58150B3279BBDBDCCBC7B7712A17356C9DB6BCBCAAAC965F36280E164B8BA2B4ABA893591A00001363B0D2D8D6C97B310000418FB6CED4C6B3A48A3C0000003A7FB5C9C2B9B9B5892A0001529EBEC3BBB7B0A27018000000266BA8C2BDB4AE783A2B171C3B769CABBEB69F988A481002153C6BA5D2D7C192521C000000196BC7F0F0C28433121319212C32749F9D847A5E3C292032427ED8F3E6A8687E49251B1E243F70A4D4FAE7B0652616161B355797D4FF8433121319212C3201FEA65F07071860759AD3F2E8ECD9C4A46022000A459CCCEAEECEB77628000000185A94AD93ACD0CCA94E190B13468FC4D2D3D7B5611C0A2E6FB6D1D3CFBEBD721C1336799EBDBCB7B5ADA66335240717488EA1A8AAA68D460700001059A1CADFDDBA712C06064297C6D1CCC0B19E7D3E0500073983ADCBBDB2B7B38E2700075BA0BDC5B1B5AFA970190000002978A9C3C3BCB7783D2C1A12336E9BBAB3ACAC9E8F3C120315396BACCBD3B88242190B00011263BBE6EDC47B2D1709181E22387DAB8D797E5A321C1A313A87D2FEE4B56E814B2C271A294B7EABD8EDDCB360352223182B5599DAFF7B2D1709181E223801FEA75F070718707EA8DEEEF0F6D8C09C5523040E4DA1D7EFE9DEB778270000001C5A9DA695A9C9D6B25619051B4C91C8D9D5C7AB5A15083074B9D6DAC9BCAC6A210A4083A0B1B2BAB5A193532A1711214F9DB8ADAAA786430500000F63B7DEDBDBB6712000004693C6C4CFC3B4A5813D00000E4185BACFBFB4B4AB782300055598B3C2BDBCB8AE741A0000002B7FADC0CFC1AD6E34301F16367999B5B9AEAAA0894513020F4579AED2D1B183360C0005011C68B8DDDAC56C250D0D1120292D79A994817C613525222E3A8AD1F7E19E688245231F192C4978ADE0F9E5AE612E2818203659A5E1FF6C250D0D1120292D01FEA85F07071880699DD1E6F4F2CEBF925111000A509CDDE4E8D8B56E2A000000156099B09FA8C4C7AB531710225A9ACBD8D4C1A05815012F90C7D5D9C6C6B25E16144785AEBAB9ADAEA5965D2D1B03135799AEB7A4AB88440700001161B2DDE6D4B06D240008448DC4CFD6CAC1A779330000164B8DB2C8BFB8BAB17D1E00004B93BAC1B1ADAFA6600D0000003183ABCDCBBFAA753E2A1A1C4088A6BCB7B49B977F3C0F00154A749EC4CEBB7135010000001963B3DCDAB774260A0A0F17233D7AAD9A7977553728262B4185D5F1D7985B85523A1A18254A7BB8EEFADDA05A2B2419263751A7E1FF74260A0A0F17233D01FEA95F070718907FA5D1EBEBE5D6BC8D4A2B070D4DA1D7E8EAE5B464240000001C5AACB394AFCDD6AA510D011C5298C7D3D7DFB15F210C3786BFD4CDBEBFB05B150E4688A7BBB5AAADAA944D221507175DA1B9B3B6A574320000000B5CA7D5ECDDBC6C26000A4E9EC2D1D0C6C1A375330800184886ACC6C1C2C3B076200008599BB7B9B3B7AEA65F160000003783A7C1C8BFA86C3E3222234B7AA2B1B4B8A99F803D09000F4469A5C9C3AD793B07000000096BC1D7D9B2652610000E182C4283AA98807158322D24314189DEF0D2935A86412C211D2D4E95C2E8EFCF9E582D1D1C2C3D609EECFB652610000E182C4201FEAA5F070718A080ABDDF7ECEEDEC49A58260A1C56B0DBF9F6DEA96221070000225BA9A896A9CED9A85213061E6093C9DCD3D7AB4D07073B8EC5D4D0CBC5AF5914154687B3BBB0B6B0A989532A150B185591ACB0ABA97D350000001662B4DDE4E1B25E1A000954A3C1CED4CEB595672D010015508FB4CCB6C3C2AD7418000D57A5B6BDA9B6B29E65150000003C89B3CAC5B4AE6A453018203D77A1B2B4B0A58E8037050210476F9BB8C0A7661D000000001865B5E1D3B266120004151C2A4183A99D8478532D231F263D8FCCF0D69862884C2417182D598DC3E2F7D39E521F141E243C60ABE6FF66120004151C2A4101FEAB5F070718B0749DDAEFEDDFD2B08A5122051B5AACE0ECEDDFB86C1C0000001967A8ACA0ADD1CAA64C0F0D2C66A4CCD5D3C7A3440E083B90C0CCC9C2BFAA4A1217518CB3C0BFA9A4A3834C302005175D9EB4AFB5A473360000001971BCD4D4DCAC6019040C57A2C2D1CCCDBA8A65320700125190BDCFCBB8B1A96E1A00105A9DB6C7BBB6B1A2610B0000003C8CB2C8CAB9A36A412E2123487DA0ACB3A59C8E853C0900145074A8BECEB07932010000001570C4E4E2AF611A03090919284388AC9686754E302A25264D93E1F9D69961994A271B22265396C9EEF2C887431E1C272E3F62AAE4FB611A03090919284301FEAC5F070718C07BA1D6E6EAE8D4B58C4C2909185AA4E4ECE8D4AA691B0000022961A9AF93B3C9D6B55415133166A4C8D2CFC898420F00388CBFDBD8CEBAAB56101D518EB4BDB2B7A9A2854E2010001B61A1AEB3AE9F75290000001769B3D3D3E1AB5913000F61AAC0CFD7D8AF8A583209001D569EB9C7CEC8CBB46D17000C5C9CB0B8AEAEA8926118000008428AB3CCC2B29E673E311724457EABBDB4B4A5A3843D0200114B7095BABE98661E00000000136CBDDED2A15F1C0A091D252B45809F948871462D1D1A2C3E8DDDFACE8F578E412322191C5493C7E7F7CA93491D1A1B2B3866B8F1FF5F1C0A091D252B4501FEAD5F070718D077ABDBE0E5E4C9A88A4C2A081258ABDDF2EFE1A65C1E0000002B5AA8B3A0B5CBD3A8461C102B609DC8E0CFB7973C09063D8FC8D7CACBCDA54C0F1952A2B1B1B4A9AAA27437110A001662AABBB7BCA96F23000000256ABEDCE7DEA95309000B5DA9CCCAD9C8B591572E0100145DA9C7CAC3C2B9AC681F001965A8BABEB8B2AE9D5F11000004448EB7C5C8B6A9663E3524214378A5B5AFA5A795752A0000185277A2BAB3A45F1200000000116CC1E4CEA55D1903080F1D234886AF90786D3B2B2722274390DEF5CA81537C371F2824354E93D2F5EDC48343211E272D3973B9EEFF5D1903080F1D234801FEAE5F070718E0779FCBD9E0E1CFA77F5222030F52A1DFECF3D8A255170000002E69B2B0A0B4D8D9AF4716193067AACBD2CDCA993F0D023E97C1D1D4CEC2A24B0D17579BB9B8B9B5B09F84371300001C5AA2BBBDB7A368200000001C70CDD9E1DCA64A11000B58A8C0C7D3D0AF7A4829040020649EC1D2C3C0C7AA6A0D00196AA3C1C5AFB1B0A6610F00000A438FB6C5C3B5A269412D1C1B4E8BAAB3ACAA9F9A7E3102111E4C77A1B9BA9D5911000000002279C5DAD3A85A1810091A21304992B3987B674532281B264495D9F4C982478F3C242922356091CFF2F1CC7F3D171317214681C3FAFF5A1810091A21304901FEAF5F070718F077A1D6EAE8E2C7A7875521060D5BB3DFEDF1DBA54E11000004216BB6B9A1B2D1CAA94712153271A2CCD2CFC28F3D00023995BED1D7CEC39E44001F599CAFBAB9B1A8A4874A1A03051F659BBABAB69D631F0000002882C5D6D6D19A4B0A001467AFBFC5C2B899764728100D3569A7CAD0CEBFB7A8650F00196FAABFBAB0B2AE9F52120000105898BEC0C3AFA5593F302026578BA7B4B4A19D9E7C370A06165479A1C6BFA25B1100000000186ABAD9D2A85F180A0409212D5099B499876A3D2928262D4C9DE0ECC5793B884C28221D2E5598CDEEF6CB8234141E23314C7DBFF7FF5F180A0409212D5001FEB05F0707180073ADE5E1EAE3D6AC7A4E240B1A5DB3DBE8ECD19E56140000053774AFBBA0B0C2C59D45100F4073B7D0DADCC4863100003B92C3D3DAD2CD9F41051A69A3BCC7BEAEA8A07A290C00001F62A4C0B8B4A45F0E0000002775B4E0E6D99B4B0B00166CACC2C8D4D5AE7A471F09012E6DA9C3D0D0C8BA9F570F001167ADBBC2B4AAA1A6630D000011568FB3BEB6B0A156383B25294E88ACB4B5A8999A7D28000024597CA7B3B79C5C0C000000001362BAD8CA9349170B080B1E275399B69B875F4325131F2B439AE1F3CC7C448E451D22192A5AA0D0F3F2BA7A2C15111F284382C6FCFC49170B080B1E275301FEB15F070718107FACDBE4E8E9C9A88B4D250C1764B4E1EBE5DC9E4F120000003478BDBBB3B5C8C7A44710213977ADCCCCCABA862F000B4798C7D5D8D0C5AB3E101F6CA8B4BAB3B1AE9876300A00002067B1C6B9B09B5C080000002C86C6DFE7CF9A4E01001165B0C6C8CEC19F71482A0E063672B2CACCC4B1A69D5A08001C6BA7B5B8ADABB4AD500900000D5D9EBECBCDB298623F362531538FA9B1ABA69C93713200051F5779A2C3AE90580D00000000157CC4DFCF984A0609000B1E31539DB79C7A5A2D1A1218264A96CFE6C570558F401C1E283A61ABDFF6E7B97A3A221F2829468FCFFFFF4A0609000B1E315301FEB25F0707182076A2D4DCDBE1BD99734A200C1966AAE1F0E7D895490E0000023076BCBEB3BFDCD0993F14183A77B3CBCFCBB8852C00083C97C6D1D5D9C89E40051B659DBCACB3B4A8A16C341800011D6BB1C9BFBC9C53070000002B76CAE9EAD58D4009001668AACECFCEC7A06E422D0A083071B2C9C7B6B7C3A15A0E001A65A4BCC0ABB2AF954F0D000012529AB9C3CABCA35F372A1126548AADAEA59E9A9E7831060620627DA1BBB59A4D09000000002172BFD6D399460D0A0B0D1B375C98AEA683674924221E1F4B9BE6E9AC673D883E2021242B62B0E1F1EAB76C2E1A1E1F274282D2FDFF460D0A0B0D1B375C01FEB35F0707183077A8DDE1D7DCCA9573461A0A1C60ADDFF1EACB9742100000003177BECAB2C2D5CF903B0D0E488AA9C4D1D2C2832B00084897C8D1CCD6BF9C3D0A2C6EA8BCBFBAB5AB976521070000255CA8C7C3BD9859090000002F85C8E5E5D8994207002677B0C3C4C9BD976440220C043A72AECAD0C9BEBBA35C0B00156BA1B9BCB4BDB4A250100000115D9BBAC0C4BCA664482E1B225992ACB5BAA3A3937124030323587E98ACB1884302000000001874B3CDCA924904000009253E6CA8B89B7957331A1B1E2749ABE0E1AD6F3B903E1F1B14276CA8E3FFEAB16F2D22181E2B4987D3FFFF4904000009253E6C01FEB45F0707184084AAD8DBDEE6C69D6B4326072369B4DCF3F0DE984A0C0000103D84B6CCBBCBD4C994360612427CB5C7C8D2B87B29000D4798CAC8CDD0BD923E0E3374ABBEC4B2B8A8966021050000296DB2C3B8B58A4C080000043787C7DCE5DB953A00002473ACC5C9D1C39F61331F0808337AB3C4CFC8C4C0A3560E001D70A1BEC3A4ACAFA5570E00001B68A5BFC7BFB09B5B39331E325E95B6B2AEA699A778290001205E7B97B5B4884300000000001982B7D8CE933C1004060D1C366CAEC2A488622B1A16121E4CA1E9EFB1643991402A201F2C66AADDF4E4AA622F141516335285DAFEFF3C1004060D1C366C01FEB55F070718507298CCDEDFDFCB9971422710296BB7D7FAEFD69244120000153986C1DAB6BEC4BE8C30041E4E83B5C8C9C8B1712D030D459BCBD4D0D0C493320F2677ACC1BAB8B2AB9C671C0000002463B2C2C0B38E44060000003B98C7EAE9DA943501001F73ABCDCAD3C4995B42301310397BB6CDD0CCBAB98D3F0300206BA5B4B8B0B2ABA6581300002365A1B7BEBAB79F6B46371C295A96B0AFA89E9791772A000025657C9AAEB895490F000000001D78B9CCBB843A0006000D30416EA9BA9B7D5E3D241E152355B0DCDEA36538934221190C2967BBE3EEE0AA5E341B2427294B90DEFFFF3A0006000D30416E01FEB65F07071860769ECEE1DCD8C7996B4727031C67ABDAE4EBDC8743120000104180C5CCB2BEC6C98D380D224C8AB0CAC9C8B16A27030449A0CDDED5D4C28C2E082C74B1BABAB1AFAD965D17040005216CAFCDBCBB924B000000024196D2DBE1D48F3905002878B6C2BFCECD985E33280D05388DBDD2D5CBB5AB8F3D00001E6CA3B4C2B6ACB5905A190000266CADC1CABDAC925132281D286299B6C1BAA5A4926728000234698099AEB290500C000000002080C6D1C6833A0E07030826487AAFBDA88A61341F16101A4AA0E3E2AB623287371D2321306BC0E5FDE3A05C28141D2C394B99DCFFFF3A0E07030826487A01FEB75F0707187071A0D3DED8E4C79366422C112463A8E7F1E7C98A300200000F4385C0C4B3C1CBC38D3108265D92BED6CCCAAF701300054B96C7CDD3CAC28F36013281ADBCBDBAA9AF9758170000022B6DAEC3BAAF8E40000000084091CEDBDBD799350100397FB6C5C3C8C294573428090E3F8CC3CDD1BDBDB089380000256DA8B3B7A9B1B4A3590F00043171ACBEBEBCA89A59362E1536609BA9AFAFA39A98753301062659749CB1A58E4704000000001D7BBFC2B583310800010E264A7BB3BF9F8453290F0F13314897DBDEA05C2C8F37261D273970B1E8F6EA994F26232128335798E1FFFE310800010E264A7B01FEB85F0707188072A2D3DEDADCB98B6439210D1B66C1DFE5EACE86430A0000073F88C7D5BCCAD9C784360C1E568DBBC1C7CCAE67200000419DC8D6C3CCBF933A123778A7B6C7B5AAA89E6315000000226FB0C8BDB484460000000A439FCCE1ECD1903600002683AAC9C2D1C7904E3A260E0A4697BBCCDBC0C0BD903D00001977A6B4BBB1A8A09C531600022C7CADC7C0C1BD9B644A341F346798B0B2AAA29C936D1F00002A618496AEB3894000000000002F88B9D1BB8439020308112A4A85BEC79A885F2B180F091F4AAEE2E09E502B8C34211D222C69B6EEF7E2985123182023315897E2FFFF39020308112A4A8501FEB95F0707189074A6D2D3D3DAB97F633D28082761ADD4E3E1C88B35000000043786CAD2B7CED6C6813814255D97BEC9C8C1A85B16000546A4CAD2D4BEBB8E22052B7DB0BBC0BAB7B59C52110000002A71ACC4B9B380370000001544A4DAE5E7D57F2D0000348AB9C9CDD6C0854934280D04408BC6D2D2C7BFA787400000216EA7C0BCB3AFB19A591200003579A6BCBEB9B098623523112D5E97ACAFA8A19A97751E000926617F9DA8A88A4C03000000001F79BCCDBD88340107020B235286B7B4A6835A2410060E2152B4E0DFAA522B93441F191E2B6ABEE7F8DD8D4E21181C233252A4EEFFFF340107020B23528601FEBA5F070718A078AACECED7DAB17E573B2B12286AB8E2EAEACA873D0000000F508CC7D9C8C9DBC07A200827639EC7C8C9C8A55714000142A0C6D6D5D5CD89270A348BB3C2BBBCB2AC9357120000002772AEC3C3AE7A320000001254A2CEDBE4D188300004338ABCCDC8D0BB8B4D322A0D124B90BBCDD1C3B7AE853E02001F76AEBAADA5B0A792520F0008337BAFC4C3B6A9975B3F2E253D6990ABAFAA9B989C721D0004316B7C9CAFAF8D480A000000002580BED3BF803205020007254D8DBDC3AA84532B0A0B14244DB0E4DF9F5335944019141C2C75BAE8FEDB934D212226202853A1F1FFFF3205020007254D8D01FEBB5F070718B07FABDACFCCCCB0855B39200D256FB3E5E6E4C67F370600001A488BBBC9C7CDD9C28125092766A2C0CDC8C0A45B1100054DA5CCD4CEC6BB8227023B89ADC1B4B0AEAB945006000000347CB7C5BBAE8E350000001153B0DDE3E8D4872A00073A92BEC4C5CAB6813C2F2C201C4A89C1CFCEC2BCA97B370500246AA4BDAEA1ADAF964C1B000D3A7AB0BDC5B6AB8D5B402C1D366795AEB2B7AD9F91621A040B2A6D889CB8AD8C4300000000002B7FBCC8B1782B0500000D246396BFC0A288512A1613112355B3E2E1A54B2F94492714193675B7EAEED68A4F1F15191E2B5BA8F4FFFF2B0500000D24639601FEBC5F070718C07DABCBC9CCD6B8795239261C3371AFDEDFE4CC7C2B000000164691CCD0CACED0B881300E2E6EA7B5C9BEC6AA5A15000351A8D3D8D8CCBD832404377CB7B9B7B7AEAE834605000000257FB6CDBDB9842C0000001852AADAECE5CA8127000A418EB8C5C3C9B079422A241A184298BBCED8C2BEB37A3000002372A7B5B3A6ABB0964A100113407BB5CBC8BFB1925336221D35668EACAAB0A598916418000F2D728B99A6A57B4204000000002881C2CBBA7F2300030004355B98C4BBA083572F0D0F122C5DB0E3D5934A218D3D1D181B306DC7F0F0D58345221918202C5EB1F4FFF92300030004355B9801FEBD5F070718D07CAED6CDC9D2B37D503523143172B4E1E7DFC371260100000D4B9FD3D7CAD2D1B675280D216B9FC0BEC9CA955914001250A0CFDBD1CBB17C230C4085AABDBCBBA9B9904E050000003480BFCEBFAD73200000001456AFD4EEEBDC802C09093A92BBC3C2C6BD7E402E2C171D5997BAC7CFBDB8A27F3C00002B70A3B9B7AEAEA7985211020A4389BDC0B9B9B0935138291B47739BA6B1A7A499835E12000835678B98A2A5883C00000000001C71B7C6AD6E2606000001306BA3C8C6A5884E291E160E145BB3DFD5983F208E3C291F1F3B75C0EEF6D2853E1A1D2227345FB4EAFFFE2606000001306BA301FEBE5F070718E07AAABBBBC2D2B16E4F29170C266EB4D8E2DEC37128000000174D9ED4E1D8D2CBB06E220A246CA3C1C6C3BE9C510C000856A1CCD9D5D5BD872F0E3B8CB1BEB6B2ADA6904E020000003684BBC0BAB27729000000135EB6DCE1DFD7852404104B8EBAC4BCCAB97B3D332A1913589CC0CECBBFC2A86D2100002A79A7BEC1A3AEAD9E531503124189B6BEC1B2A78F5B35231D3A729BADB8AB9E93866816000C3168799AA9A687490B000000001D76B6CAAA6A22070009082F6CADCCC8A38F5D250F0D09265EB5D6D1964423923E152315287BC2EEF2D7883C201B121D3158AEF0FEFE22070009082F6CAD01FEBF5F070718F077ADBBBBB9C5B370583423122C74B4DBE0DDB76A22000000145096DBD8CBD3D1B96C2B132F79AAC7D1C8BD994B0C0002559FC5D4CFC9BE86230C3A8BB6B2B1B0ABA5813C00000004397ABCD0C0A973270000002466B7D5EBEDCD761C00004998BBBDC6CBB47C3F33291A1357A3C4CACBC3B9A3661D000329739EBEC1A9AAB29A541800144686B2C3C3C3AD8757361E1B3C7793ACA9AEA8A795660F04072E708197A4A1793100000000003389BCC3A165200001000C406BB1D0CBAC9254240D1C14285EB2E8E0943B218C3B1D0A173B79C5EAF0D1833A0F11212C2D5DB5F6FFFF200001000C406BB101FEC05F0707180075A7C5C0C0C7AC6F4D371A0C226FB8E3E9DDB964150000001B4D99CAE0D4E3D4B36C1E052E74ADC5C9C6BA974700000555A6CCD8D4CFB87A2B0D4E9BBDB7BBB3B2A87D3500000001367FC4C4BCA16D290000001959B1E6F3EACF7A1B00033A8DBCBDBBCDC071373C2F1D27609FCAD3D0C2B29E732900002D6F9FB6BFABB2A38D471000204E8FB3BFC4B4AD986344251F367995A0A5AEA6978E6411000940738694A5997C2B00000000002B85BBC1A25E230405000E3971A3C8CFB18D481C0E090F2063BAE1D6943D10913D201F203486C9EDEED97A34180915293067B9EEFFF8230405000E3971A301FEC15F070718106FA4C8BBB8CBA469502A170F2C75B0DFDED3B76917000000115A9ACDDCD3CBCBAE681E103980AFB7C4C5BD9C4B0500004E99C9CFCECDC27821124C8FB5C0B9AFAEA7753100000002347FC4D3AEAE6C23000000246ABFE7EAE9C47D20000E48A1BABDC1C4AC6E3538301D1B55A3CAC6CDC7B99A6E1400002D74A4BBBDA5AFB28D49210F1F5999B8C3C8BBB1884B2A241F41718FADA7A39E93895D140007367581848F8C6C2A0000000000287CB0B7965610000500103874A6CDC9A589561D070407215DB6DDD98F491E903D2A1A20357ACFEEF2C86B341D191C263061B3F6FFF710000500103874A601FEC25F0707182075B2C7B7BBC9A266462F190E3379B7DEE7DBB86A18000000154D9ED9DEDAD4C8AB671D143483B1C0BBC0B998470000004DA6C7CCCDD1C38027174B90B3B8AFB0AE9D7A2D0000000A3C8BC0BDB5AC741F000000256AB7D9EBEDD57B17000844A0BDC1BFCDB86B38363B281E59A2C6CDDBCAB79E5D16000F34719EBDB2A9B1B68B4C150A29578FB1B6BCB2A38754391B20407995A4B1ADA2918B5E10000138748F95A5A7793800000000002F82BAB59F5413000000103C76AFCEC7AE8F581F0608001A5DB4E4DE9A3614903F201F1A3E81C9F6FACF75321A1724293468B7F3FFF713000000103C76AF01FEC35F0707183079A5BFB2B4C0A26034241D0F2F7AB4D7DCDBBC6515000000185094CDDEDCD3CDA6612303397FAABFC0C1BD96400000094EA1D3DCD0D7C381320C4E98B5B6B4B5B5A6702C000000053F8DCDC9B2A36A160000002A79C1E4E9EDCE7C1E000C4695C2B7C0CDB4763C322E1B1A5A9FC7D2D0C1AE955C0D000134779CBEC3A3ADAA8B4D1E0B275E99B5C1C3B8AF835435251D447499B2B0B5AFA8885E13000A3D738A8BA29E742B00000000002A85AEB8A05C12000000104278ADC9C6B18958170005031A63B2D7D58D3D128C391E16122D71C7F7F4C77038131F1B273864C6FBFFF112000000104278AD01FEC45F0707184079ABBBA5AAB9945B361C16152D79B7DCDAD2B46412000000155799C1DDD9DACA9F551C0E3E87AEC2C0C2B68A3B0000065BA3DBD8D2D0B97B240F5298B2B6B0B3AC9D69280000000B4994B9C8B4A86A120000002C7AC6E1EEECDA7215001057ABBFBEBEC4AF6D3F3B341C225BA9C0CFD2C7B0935D1A000038799FB4AEA9ACAD94581E0E27639AB0B0BBB4AA8F572E16184A779BB1ACA8A196864A04000C4C6F8289988F732E00000000002C76B1C69C4C0E000004124D84B2C7C3B08D511B000B092A6DB4E2D29339128D381C1E1B3684CDE8F3C9743511171B1A2B63BEF8FFF70E000004124D84B201FEC55F0707185081AFC9B9AFC1A0663D281A163B84B2CDD5D1A957100000001D5CA1DAE9E2D0CEA4551A0E408BBEC7C2B6B3913E00001159AACAD7D5C9B5721D0A5099B7BFBBB7A8977620000000003983C5CEAD9B621A0000002E7CC8ECEEE3D06C1A011B5F9FBEBCCAD4BC743A3B331D205FA3C5CCCABFBB91570F0006327D9FB9BBA4A7AD8A4A1F14326DA0BBBAB9AFAC8C5632201E4C7893A39FA59B95833F00000E3A7A9191A699793900000000003188B3B893460B0000001B4C87BAD1D3B088491B0504041D67BCDFCC8A351A984415141D3B8BCFF5EFC8702E1A16151E3071C2FAFFEA0B0000001B4C87BA01FEC65F0707186081B1C3AFA7C69D5F341E13103581BBDCDBE0AA5B12000000235BA3D6E3DED0CF9656190E3F82B6C4B9BAB98D32000002599FC3D9DBCDC47A19115BA6C0BCADAFA69B651E00000000499CC6C7B09A62180000042C77BFDFF1EDCE7423081458A1BCC3BBC4B065313931212A62ABBFD2C9BFB68E561A000B407EA2BBC0AFABA6854D1908316C94A6BDBEABB0925B34190F447E98AAABA99C988B4C090012487881849E90702600000000002878B6B5914D0B0000001A4F8FC0D5C5B38A491D0001012167BCDCCC8C3613963C1B1F1E3D88CFEFF3C26F25110D1A232C68C7FBFFF30B0000001A4F8FC001FEC75F0707187077A9B5A8B4B88F4C322011163487B9DBD5D5AA5111000000225DABCFDEDAD0C4A250120D4092B7BEC0B9B78B3905000951A6CBCED0D7BE70190356A3BBB9BEAFB39C5F1E0000000E569BC8CBAE96580B0000003176C1D8EEE9D46919011C6AABBDB5BDC4AF63343B32272463A8C5CACBBAAE904D0E0005377795B4BBADABA78A4D20204174A7BEB5B3A7AD905533151A4F7B9AABABB0A58B783C04000A55848F97A4A3702F00000000002780B7BF8D460C0000011F5F99C4DBD7B1914D0D00090F1E75BAE3CC85340A91331D0B1A358BD5F3EBB26426160C18272D6BCBFFFFE80C0000011F5F99C401FEC85F070718807BA7B4A0A5BE944A26181A143B86BFD4DDCBA350090000001A589FD5D9D8DBC89E4C10143C8ABBC8C5B9AB803100000D5BA8CDD2CEC7B86E1E054F9BB2BBBCB7B59F5B15000000175FA6C6CBA684561100000D3A77CAE8F1E0CF6F1200095FA5CBCAC0CCB2653F3B3724255C9CBFCED6C3AF8E4B09000F3F7BA6BAB4B2BAAE81461A093A7BA6BFBCADA6AD92583417244E7C969DAD9DA2937A4100000F4077929AA3916E270000000000197BB5BA8E4B0F0000001C5996CBDACFAD8F50170109031C6FC2DCCB8C39158F38171A12348DCAF2EBA957281213151C3674CAFDFFE80F0000001C5996CB01FEC95F070718906DA0A68C9AB390481F1309152F80BBCBD0CCA24B140000001E58A0CBDADECFB2814417094090BFCBBCB2B383380000155BA1CDD5CAD3B56C140854A2C1C5BEB8AE9E530B000000145DA2CBCBAD8C52080000013578CAE0E4E0D16C0F052063ABCBC0BCC0AC6330433E272261A8C1D8D5C5AE8E420E00184388A7ADB1A8ADAA844B1C1B467EA2B3BAB19A98824D2D1D21468998AAA7A3A6967C3F00001B46848C88968E5F1A0000000000237AACB0864B0800000021619DC7D7CEB48541090000081A74C0E2D088321099391F1C13318AD6EFEEBF60240D1821222B6EC4F8FFE60800000021619DC701FECA5F070718A07CB0B7989DB294451B0A0F143D91C1D2D2CFA24F080000002567A0C5E5DDD2B6873D05074D94BBC2C0B4B597370000115AA6D0C8CCBCB56F23185E9FB8BDB9A8A29257070000001660A2C5C2A67F410400000E3C7EC9E4F0F1D06B15052467ADBBBAC4C0AE68434A37252963A3C7CECCBDB9823502001344839FACB0A3AFAC87501B0F3F80A3B1B1A8B3A489532215285B829CA5A4A3A5928C3D00000E5385858E9488622400000000002C88B0AA7F3E0A000000175396C2D9C4B585460D0007002B7DC5DAC87935148F34291C173593DAF2EBB75223191919273674C9FAFCE70A000000175396C201FECB5F070718B080AEBA9E9FBA924D231418183E8CBAD7D5C8954903000000216BB5D8D8D7DAC3873F03033F92C2C7BBB4AF863600001859ABC3C9CFD0AF6618155BA7BCB6B9B5A89757070000001E61A8CDC9B27D4A140000073E81CCE6E8E9BF5E0D00216BB4CECBBFC2A55D364046262868A8CBCEC3BEAD753813071551849CB6B8B0B1B0874F1F174780A9AEB7ABA39D8A50291A23508691A6A5A394937338080015578E9A8D9D88641D0000000000287BADAF8841090000052968A5C9DED0AB894D0D000B042376BEE4CE7B3114963720181B3B8BD4FCF2B359280C0A17253579CBFCF7E1090000052968A5C901FECC5F070718C0709FA59392B085411E0C0C1A4089B5C9CBBF8F44030000002063B1DADED9C8B374390B0A4F97BED1BEBCB082360000145FACCDCFD9D6B567211454A4B8C2C4B8AB9248020000001D65B2D1C1A67838000000084A91CDEFF2EDC97010062373B6BEC4C2C4A15A3E4943222463A7C5CFC4BFA8802F00001949829CB1BBA7A5A17C4B2226528DAAAFBAB09FA28E5133141B607B9DA9A1A9A59A783300000D588D8E9F98886B2700000000002B80B3A97B3C0C0000092768A5C9DACCB784460B06010A2C7FCDD7CA81260C9939230B0D499FD3E8ECB4582107191B253479CFFFFEE10C0000092768A5C901FECD5F070718D0699C9B8693A079351007090F398AB7C8C7B7943F000000002066A5CEE8D8CCA970310C0B4DA1C8C8BDAFB6852E0000135BB0CECECDD0B66A160F68AFCAB8C6B5B49740000000002163A5CEC3A977440600000C4A88D3E2EAE1C66713002F7CB0D0CDC2BEA35E3A434C231F66A8C4C2C1BDA16D2503001D5A93A8AAB8A5A8A6834D2222598BA8B5B9A79D9A894E291921557B96A8ABA9998F732C00000C51878D909A976D2500000000003392B7B48C3D100000092861A6D1DCD9C5924C120205152B7AB8CDCB86370E943A22150D3795DBF0E7AE5528100D161F2D7FCEFFFFDD100000092861A6D101FECE5F070718E077A6A28094A87E2D150907155094BDCBCBB58D33000000001C5FAFD3DCD7C8AE6F27010649A3C5C2C7BCB6872700001660B5D1D0D8CCAB5909055BADBCB7BDB9B4924804000000306EB3D5B69E6B3B02000010508BD3E6F0F0C2661C062F6FB2C9C8C7B8A757303D38213564A9C9C9C7C5A96F2B060927568FA7B5BBA9A69B7B4F21244F89AAB4B2A49B9B894A21152C608B9DA8AAA49F9A662A00001A668893838181631300000000001F79A39F792C0100000033729FCCDACBB1874A0F0000042B80CBDAC37A30109E3D290A164AA0DEF0DFA94D1F1011191D3683D3FBFFDD0100000033729FCC01FECF5F070718F078A3A68D9CAB79371A12131C4C93BDD4D5C0923A000000002D71ABD3DCDCD2B26126020C5599C5C8BBAFAA802700001166B1D3D1DAC5B4560E1867A6BEC7BBB1A88E4600000000327EB5D0C0A675320000000B5496D3E0E9E3BA5D0B032F76B6C7C5C0BF9D56393E3B2C3467A3BFC3C1BCA669210008246197A4B0BAA4B2A671481A2A5D91A5BBB9A6A0A89454210A22698292A1A3A7A49A682E0000275F86888789825B0100000000002C73A4A36A28050002113266A9D6DFD7B17C3A11000008377DC7E0C385360C9E3B2818224DA8E2EBEDAD4D1E0E0D00163583D9F6F7DA050002113266A9D601FED05F070718006C96947682966720000000104682B7C8BBB9872C000000001E6AA6C5CED3CAA563270A1153A1C0C7BBB1B0822900001563C5D6D3CDD0A25910106AA8C4BFBCB9B3822F000000063A72B8D5CFA37030000000105597DAF4EDDCC564180D2F7EB9C7C7CBBE9F54344B4025345FA2C4D1B9B8A5611E00001D5C8CA8B1BDA2AC9E75462C275995B1B8B0A2969785542313266789A3A1A9AE9E996E2000001F668D90909390581600000000002977ADA775360A000006367CABDEDDD3BB823F0800000D378CC2D6B8803D189D4126141B4B9BE4F4E19E40190C131E203585D6FFFFD50A000006367CABDE01FED15F070718106C9D947D7F9A701E000000174B8CBFCDC2AE7F2A000000003375ABCFD7DECCA96123000B52AAC5CDAFAFAC722700001A6DB7CDCED4C8B057171260ACC0C8BDB9A18A3C000000003778B5CFBFA46C2C000000225CA2E4F7EDEDB7610F063180B4CCCBC1BC9C5540413C2A3066A8BCC9C0B4975B1F00052E65939DA6A7A3B0A97A4F26276691A1B3B6B0939B874E21132D6A8FA3B4A6A18E86621D000024608D8C8E9387570D00000000002B88B0A66D2D000000083A7BA7CADDCABB84490F0400002F89C0D8C281321296372B1C154BA2DDECE4AC492511121A1F348BD4FDF9C8000000083A7BA7CA01FED25F070718206998947975865F1B0100011B4FA0BABFB3A7761E000000002F6DA5C3D6D1BB9C5A12001263A0CDD2BAB5AF711600001670B8D0DBD2D4B156110F69B6B8C0BAC6B6902C000000003D8EC0D4B399622C0000001758A3D3E8DFE5CC630F013783BFCBCACAC6975449513F2C3261A1C7BEBEAF96571800042162939FB4B0AEAD996B46212466A0B8C3BDA7938E7E521F0A32638D9EA6ABA7A796621900002B698D8E858E8A5A1200000000002F84A7A4702A000000053985C1D7E5CCB6823A0C000100368BC6DFBD812F119240220F1C45A0D6F6E8A7451513101A213080D9F1F1CA000000053985C1D701FED35F070718307CA48472818956180100001E49A7B8CDB8A87827000000002A78AEC9D4D3C0914C0F001056A6CDCBB7B0B080210000206FB4CFCDC5CFA84F0B1E66ABBFBFBCBFAE802C000000084188B8D0BF9D601F0000001E63A5D1EBEAE5C5560D143A85BBCACDC2C199523F5145273169A2B5C0BFB3975A140001356AA2A7B6B9ADA4936B51353E6D93ACB5AD998C918048221D306A949E9D9EA69A89571301012D6A939184857C5C0A00000000002B84A6A67135030000114287BFD3DCD0B4814605000010398CCCDBC5792C129A4224100D54A1DFF1E29E431D0A1117264584D1F9E9C6030000114287BFD301FED45F070718407892917175895111000000204599B0BAB1AF8128000000002C7AACD2D3D0BE8D4C10000D58A6C5C0B5B3A9701800001F73BFD1D3CDD0A25A0F206BB1D0C8C3BEAC7C26000000003A94C1D2BEA6581C0000001D5DA7D2ECEFEBBF540C0A398BBEC4C8C7C79D52384C492836649DC3BDB2B6924D160513407499A1ACB2A2A29871442436749DB1B6B39B87948B4D241032778A9DA49EA6A08D501600002865878A878C733D0100000000002B7DACA66325000000124490C3DAEAD2AD8342050000054098C8D2B97F310E9B3D24170D489FE5FAE3A24315070F182A398CDAFFEDB8000000124490C3DA01FED55F070718507F9B9A7E82865919000000245B98B7C6B7A27D2D00000003397CADCFD9DBB67F480E00125BACC8C7B1A8AD761E0000176FC2D9DAD6C5AA4D061374ADBFBABAB5AF8D280000000F4B91BCC8B89453230000002165BEE0EBDDE3AF48070C3F95BBBFC2C7BF9F543D573C23316BAFBFB6B0B4944E0C030F40779BA3A8BAAFAD906D492632799DABB7B2A2939C8B501F11396C92A2A0A2A69D84450000002B6B95948E8A76450200000000003178A59B672900000017518EC2E2DFD8BA893F030000033B96CED4C47D2A0F9B391D0E194FADE5E8D39A4126181212243688E0FCE6BB00000017518EC2E201FED65F070718606486846A6E7A4800000000195994ABAAAA986E10000000013D79B4CBD0CCB57D3D04000D5BA7C6BBA9B2AD661A00002581C2D4CAD2D39F52121372B3C5BEBDC1B17B200000000B4F9CC9D2C59A5315000000276CABDAE3EBE4BC5A0D043C81B5C0CBC5C4954A4B573D2939669ABEBEBBB38A3A04051D437CA7A2A9ABA0A198744B2E437BA0A7B1B1A69893814A2114316E979FA1A8A99D8548060000296D8D907D8472440000000000003480A4946924000000144A89CEDDE4D7B77F400B0000003F96C7CBB97B2A089A41211D1C53ADDCF5E399491C0812171E3487D7F3DBA3000000144A89CEDD01FED75F070718707E94967A8988510E000001255B9BB9BCAE996714000000073F7EADCBD4D5AE6F3104001B66B5CEC7ABB0B1601100002279BED9D9D5CDA3510D2474ADC1C0C5BEB075180000000F59A1CDD3BB964D0F0000002D6EB4E3E7E8EBBB46050B4192B4C0C5BCBF93574D5147304171A5C3B1B8B583320100184482A29EA0AFA3A09276552938759AA6B2B8A58F92884819193E7891A2A9A2A69B81420B00002E719B957D8C794C000000000000347DA9955C20000000135A9ED0E5DFD4A87E34100000084693CADBBD772E109E361F172057B1DCE9D7993A13090517203E95DFF9E2B4000000135A9ED0E501FED85F070718806C827C68757E4F07000000204E94B4BEAC93661C0000000040729CC9CCCEB96F2F00002068A4D3C8B3ACB06F1A00002076B7D5CDD4DBA64C0E1D6FBABEBBBBB4B07413000000155F9CC7CFBD984E130000022877B1E0EFF3E7B5490C07438DC2C4CCCBC38E4F405A43253A73A7BCB7BBAD813500001A4E86A99D99A9A79B88614B2C3E86A4AFB4B393918B874D1C2048829B99ADA4A6A4833B060000377A9190838A74450600000000003383A8965A220500001E5495CBDEDFCDB97C3E0200030F43A2CACEB07830089B4622111A53ADE2EFD69D3F1D0E111B1C38A2E4F1DDB30500001E5495CBDE01FED95F070718906C95906F786C3300000000245B94AEAFA19B6010000000043D78A9C3D5C9AA682D04001366B1C3C4B2A6A7661C00002880BFDDDCD1C6903B0B1D73ADC7C2C3BDAC6A180000001B6CADC6D5C495470E0000063279B7E2F0EAE4A84B0C124998BCBEC2B3B9964E45463A374B79A6C1B3C7B97E2F040029537CA4A1AAB5A99E8E6F52224379A1A9A8ADA48D918149180A357E95979AA1A9A07C320100002F799392808374480300000000004485B6955113000000185C9CCBE9E7CEA572380C000005409BC8C9BC742703A03B180B1C64BAEAEFD1913B080B00192A48A1E3F1DEA1000000185C9CCBE901FEDA5F070718A07183837072763600000000255E93ADB29C925D0A000000013E85ADC4D9CFA5682F00000D68B1CEBABBBBA7531300002E81C4D2D9D1CD9E3F102179B1BFB9C2B9AE640E000000196CADD4D3BC974E0B00000C397BBFE2E9EAD79C3D0C174C95C0C7C7C5B2894746543B3B4972AAC5B4B3A5722B02011B568AABA6A2A9A89A887B562E4281A1ACBEAC9D85997D3A19193E78909BA6AAA09A813D0000003775949B7D77643F0000000000002978A39655160000001861A0C5E2DBCFA8753A050000084BA4D3D4AE7931049B391D10185FB8E1EDDA8D39160D131A2A439EDAF1D9970000001861A0C5E201FEDB5F070718B0758A85757474390000000029639AA8B0A28A56080000000A467EB0C7CEC9A15C2100001D6FBBD8C1B1B49F5B0A00002984C0D7DFCFCC95420F1D71A9D0CEBFC2AC66060000001F70AED0D2BB9B3B090000002E78B2DFE4F0E1A340061D53A5C4C8C6B6BE874B4C573F354978A2C3B0B5A3772905082A668D9FAA9BAFA5A982715130457CAAA4B0AC928B857B3D131645879BA5ADA89F94722A0000083B82A59C7B796E430000000000004086AB925214000000195BABD0D9D2C4AC7135040000064496C8C8B1762D0BA24A221F2569BBEBE8D69A3A140C050D1D4DABE4F0CF98000000195BABD0D901FEDC5F070718C077998276756E3100000000366E9CB0B59C845302000000094487A1C6DCC995551600002679BDBEBAADB2A05A0D00003384C4D7DED0C48B39071F74B6C2BEC1C8AE680B000000297BBDDAD8C49941040000022774B5DEEFEDE09B35061959A3C9CAC5B9BE94484B4D4134417BA1AFABB3AE792A0102326B94B49899B0A39C8373522E4986A8B0B0AC9C8B817A471A1E448597A1A1A8A294712900000B457B9D9E79785F360000000000003A82A08A45140000052463AAD0E0DDD7AD77310000000B4798CDCAA9681D04A34F1F0C236EBEE4E5CF8C3A1915141D2246A4EAEECC930000052463AAD0E001FEDD5F070718D07C9188797F782F000000013E6D9FADB19F764F1800000012548FA9C7D5C39E4E170000176EBACFC0A6AAA35B120000338CCAD4DADEC894370E1C77B7CABCBABDAF5E070000002874B6D8D6BD923D0300000A3B7BB2E0EFEAD898380C215EA1BDCFD1C1BA874B485B3C304880A2B3A8B1B06E2600032A5893ABA899AA9E94817A54344E8EAFAAA4A3958A857A39162C4F8FA89FA2A3A19E692800000D467195907D785E2C0000000000004A89A69554180000001365A8CEE2E7D9AC6C320000001558A0C8CCAB682D09993326182A68BAD2DDC88E371D090D21224CAEE9EEC5900000001365A8CEE201FEDE5F070718E0718085737C712E000000002B739FB2AB99774A000000000E5492AABDC8C28A490D00002579BDD0BFABA396581500003793CBD5D7DFCA852F05227EBDC9C2BCBCA1620B000000287ABCCFDAD09A3A0100000C3A84C1DFF0EED29425002165ADC4C0C1BDBD90514D5E4B355487ABC0A8A7A3661A000A3B7291A69F95A49E958076523A4580A3ACADAD9B8288773916214D869FA5ADA89796641D00000F48869A91848060300000000000003C88A58C4406000000216DB9E1E8E5D1AC752F0300000B5AA6C5C19C682503A43A1E172B6BC0E8DFD48A2B0F1214192647A7E2E5BA8B000000216DB9E1E801FEDF5F070718F07C8C91847D6D2C000000033F6CA5ADB89F7A4205000000185798B2C4D7C4904B1400001E75C2C8BAAAAF9946080000398ACDD9D5D2CF8E33062381BFCBBFBAC3B25E070000003089BCD6D8C7923F04000004468DC4DAEBE7D1872E001A60A2BEC7C7BEB38A47495C40415D819EBBADB2A75F19000A406B9BB5A496ACA48B727A5F325290ADAAA6B3957C8B71331725528CA6A9AAA69D94611800000E4C7D9F9A7878622C0000000000003380A48A4518000002246EACD8E9E0CCA8752B07040112549DCCBF99642B089A3C180F3071C3E5E5CC913218020820304EADE9F1BD83000002246EACD8E901FEE05F070718006B8082776B6120000000003D6E97A9B696733E000000001D609AB6C7CFBD8A380400002880C1DFB6A3B69B4C0200003893CADDD9DBC77F330C2C81BACAC0BAAEAC5E000000003780C1CCD8CE9C46010000033B85BDDDE6E6D48630081A5EA8BEBDBEBEB8854850503F3C5F85B3C0A8A2A05F13000C4B7C9EB59EA0B0A1907B6F552B5194ACA5A39F93797B773E1B2D5A8E9EA0AAA1A6975C1300000C47889D956F685126000000000000467D9B823E050000032578BBDBE2DFCE9B68280000000857A5C3C4A3631E099C3F201B3178C8E3E0C48A34170909142845AEE2EAB87F0000032578BBDBE201FEE15F070718107889796E6E57180000000042749CA9AA8F6B33000000001B6193BCBED2BA84470400001E7ABCC9BAAFBCA7530E00023A96C8DCD6D2B57522001F7CC1CFC3CCC0A95D00000000378DC8D7D9CD9A35000000094A86C7D9E0E0D68926032770AEC6CBC1C4C1813A4A543E395691ACB4A2A6965915000E4F77A7AAA097A49E8B7783542B538DA9ACB3B0937D7F6B2610205390A3A6AAA0A18C590800001D56869598717554200000000000004086A28E4007000000347AC1D3E4EAD1A6732C0300030F66ADD6C79762280BA1421C19307BC4E1D9C270280E0C1A1C2A4DB0EEEEB07B000000347AC1D3E401FEE25F070718207282796E695C2000000000476E9CADB18E6A3500000000195A97ADB4C8B878300300003384BDCEB8A9AE90480D00094198CBDED6C7BB83360E2A8AC0C6BFC2BCA45900000000389CD1E3E4CA9436000000003E90CBDDE6E8C77F27072564A7C9BEC0C3BC79464B5C3C3D5F96A6AC99A19D5A190020467A96A49D97AEA7876A765D365088A79DABB5A08682772B172D5B8C9BA9A49E998D5C1200000E518399927971521C0000000000034589A1893A050000092C80BDDEDFDAC29B6526000000145DA9C6B99D5923089A4319173585D0EED9BD7C3C1B0C13212452B0F2EBA86F0000092C80BDDEDF01FEE35F07071830747C867F694F18000000004974A1ADA08D612F000000001863A1B3BBC8BD7C2D050000338ABAD3BAA5B8A6490A00004099CED7D0D6C5772902278CBBCBBBB7BEA654000000004093C8DBD1CC9B34000000134290C5E4E6EBCB801F00206EAACCBEBBBEAF854A515943406A8FA9ADA0A6994D08001B4A7BACB09898A69D816D7B53315392A49BA9AF9D848A702E1630669AA4A3A9A7A5934F0400001D59808E8E75744B1C00000000000051869C843D03000008207DB8DEE3E1CF9D68290000001068A5BDBA945D2508A1360D0D3686D5E5DAB97A2F1D16261E2658B0DFDFB06F000008207DB8DEE301FEE45F070718407B7F807E73651F00000000487A9CACAA966131000000001866A6B9C3C9B77A2A0000013686C2DCBAABB594480400054097D2D9D3C9BD7629062B8DBFDAC5B9B6AA5B010000003B97D1DAD6C5963B0100000D4C8FC6E1E0DECE741A002969B8CCC3BAB7B3814C54542C3C6095B4BB9DA5974F0000195A89A8ADA795AC967B6F80542F588EAAA7ABB3937D8176301A3964979EA8A7A89B874D030000205284A597786846140000000000004489A7893A0700000B327EC4EBF3DACC9D60210C00000E5BA3C4B98E5A1B08A23B1A1C4090D5E5DAB67B2E170A1827285CBFE2E0A76900000B327EC4EBF301FEE55F070718506880847967570D000000075377A2A9A6825219000000001C70AEB3B6BBAE6E31000000398CC8C9B2A7B89B4A100005439FD3E4D0CEB97120002A86CFD0CAC9C1A459000000004CA0C5D3CFBE9729000000104B97C6DDE1DBCB6F2504327AAFCDC1B9B9B6824453574C487399A5AF99A390460A001B4D809FB5A09BA6A081697B5538619AACABA6A79380786C2E1938669C9EA6A79F97864F0A000017658E9A928772501700000000000C5C8EA4852C03000000327FC2E0F2E7C8A35B26020000185DB0C9AF835D21089B361B2D4893DADECDB9742517081922255AC6F1E7AA69000000327FC2E0F201FEE65F070718608083847B765D15000000004773A0AAAD8A5318000000002582AEBABDCAAA671D0000053699CECEACA6B1974303000E469FD1D5D3D0BF6D1F022985C6DECDC1BDA854000000004EA9C7D1D1C9952F0000000F509FCBD8EBE8C363110D317AB3C4C3C3C2AD77424F5D46456B9AB1B08C9F84370200206084A4B3AA94A18C7B6E775531609FB1A0A6B3977B806A351D346B92A4AAA9A59B8B4B0000002C5C889D99755E48140000000000054C8C9B8337010000012D83C9E4E7DDC59B65200000092467AEC6AC87532612AA3A191D4698D5E0CCAA621D0C0B141F3462B9F0E0A7550000012D83C9E4E701FEE75F0707187069808074684B0C00000000436F9EACA483501F000000001D77ABB6BAC9A55E200000014195CDD5ABA2AD90400100074793DADAD7D9B76C22013A8EC2D1C2C7C2A455020000004EA7D6D9D6C692360000000B5598CFD9E7E1C16D1E0A2C77B2CCBCBFB8A96F3E5B5F454B7398A6AE939992480B00195182A2AEA79DAC926A627D5A335A97ABA7A3AD9E7E7E67240F3A6C9AB3B1A9A39D8F4C0000002F5E88A19B7C744A1500000000001B5D87A38B3C0B0000033287C4DDE7E1C78E521F0102001C70AFC9AD804C2300A444151B53A7DEE3D0A86F2B160F101D2B6AC4E5D9A3680000033287C4DDE701FEE85F07071880748682756B4F0800000004467EA3AAAD7C4415000000003180B0B9B3B5A161130000033C8DCDD6AD9FB68D3600000B4AA5D4E1CFC6CB6D24052387BFD8DAC6CFA8590100000045A9D5D6C7C08A2F0000001A4E92C7DBEFE3B5641105358CB5C5C3C5B7AE7E4E544D3E4B75A5AFB49FA38337000022618DADAC9E8E9D947A616E55335C9AA09EA7AD9B7B786632233F7A9FA3A6A3AC99874B02000032668697907B71460F000000000018588DA77F3C0D0000012B87CCEAF0E3CB8F4F18000005256AB1C5A8824C1D13A6361E2B549BD5E1C29D6A2E1814172B3670BFEBD99B550000012B87CCEAF001FEE95F070718907176777168460A0000000249769FA39F7F4308000000003483B3C0B4C1A7631F0000043E94C6D2ADADB994310000064D9EC8D6D4D9B86620052A8DC4D5CEC7C0AF5B0300000054A7CDCED1CC8E28000000246099CCDEDFE2C6641502338BBACAC1C0B9B971415D5A46546E9CA8AD949B8239000025669CAAACA099A889746F774F325FA0A89AA2A0927675613A2748819CA6A7A99C9A80370000003B68909C95685F3605000000000010598CA6813C0B0000002980BEE2EEE3BD864E1F00000E1572B7BFA36F42140CA1401D1C55A6D6E1C69E6B2513131C1D346BC9EACD91630000002980BEE2EE01FEEA5F070718A0737F7F75644300000000005386A9AFAF81400F000000002F84B9BDC0B498570D00000749A3CFCFA3A6B28D3800001451AED7DCD6D4B25610033088BECFD8D2BFAE5B0400000354ABD0D2CDC3912D0000001158A0CEE1E0DFBC6314013389B5CDBFC2BAAE71505C564855849C9FB9A4A581370400337191B2B0A08D957F665E6B462F5A95AD9BA0B39B827C692A27437BA0A2A7A699917A2E000000386E88988C72673F020000000000226CA3AC852E000000002A8BD3EAF1DFC28E4B27050010286BAEC49973471F14A643283061B3E1E0C7A05E240F100D1A2E6EC8E3CD8F4D0000002A8BD3EAF101FEEB5F070718B080867E7D714B050000000A5A8EA8ABAA804409000000003189B9C8B5C790500F0000094998D0CDA5A7B8893809001153AAD1D8DED0B45B15063094CAD9CAC3C9A75B0000000151B0D5D8D4CA94290000002668A1CBDEE2DABF4F0E0B4084ABC5BEBEBCA7694665604D608E9FAAA79AA07E280000336595AEA5979AA085605A6D4D37649AB19F9DAAA68076622B224F8CA6A2A1A5999485340000003E738BA099746A3C0000000000001C6395A57A36000000003887CDE8F7E4BD864E1D000000227DB9C6AA753E1605A4361E3363B4E4DEB8915E241819182C3B78CCE0C58C530000003887CDE8F701FEEC5F070718C06C726E67653E0000000000507A9EA2A17B330900000000338FB6B5B8BD98490D0000074998CECCB0A9AE7F2F00001254B1E4DDDBD6BC6018042E98C7DAD2C6C2AA530000000961A2D0D9CBC08627000000175CA3C9D8E9DBA9530702458CB6BFB9BAB4A47250646151618BAAA9B396967B2A0005347295A6AB9F949C856964764A285C9DACA2A8AD9D7579572D2F4F7E9CA3AEA19D99772F0000063C73878E8B78663A090000000000256399A47A31020000092D8DC6E5F3E4BF905018030105207DB6C2986C361911A245232D68BEDFD9BF9A66281213182C3E7BCAE0CB814F0000092D8DC6E5F301FEED5F070718D0797D8475653F00000000034F879BADA2723103000000004395B4BCB3B39B4A1000000443A1D6CFA7A5B07C3700001551A6D8DFDACCB95A0F013998CED3CECECAAA58000000085FB1D9E2D3C19226000000245D9EBBD2E1DDA5460B084996BFCBC3B8BAB474466064576D929DA0AE989A7B2F00003A7699BBB4A2959A7A54626D442C689EB79295B3A47A7451282954889DA9959B98977A2D00000441758E99906A53270000000000001E62989A77370A0000022D84CAE3E4D5BE83481E01000D257EB2BE995C2E1A13AD45263470BEE4DBB588542319141A2A3B7ECEE3C7864B0000022D84CAE3E401FEEE5F070718E06D7D78685D340000000007517DA19CA16F3200000000002D86BABDBFBD873E0D00001056A7D4CEA9A5A7792D0000105AB1D5DFD5CFB05B16043597CCDCCCC8C5A75B0000000E63ACD9D1D2BA842D000000226CABC5E0ECD7A840090B4794BACFBEB5B7B272446F5B515F84ADB0AF9D997322000030759CB1AFA1999F7B5A5D693F2F5F92AE9B9FA89C7C714F31386685A3A6A8A39B93711F00000E59858B938870531E000000000000357995A081310400000C3388C9E6E6DABC80421105060C2682B4B69466361214AA47204282BCDCD7B07F4C231617191C337CD0DCC3874700000C3388C9E6E601FEEF5F070718F072757C755F3200000000095D809DAC9E702B01000000083D9CC1B8B4B691470C0000145AACD0C9A3A7B5832700001B63BCE0E2D9D1A44813002F8DC5E2D0C7C4A74E0000000C5CAACCD0CACA841C0000002276B3CAD2DCDA9E3907094B96B8C6C6BFB1A360446C5F446893A8A0A59697711B00003B719CADB3ADA2A78556656B402F678FA49A97A7988072582E30628A9DA0A2A0A296641F00000E4C7389928C644E240000000000003C7B9A9F7E2F000000023194CAE1EAE3BE864C1C0F020A2F8BBEB98E5E2D140AA23D1D3280CBDBD4AF7F4F1F15151E294187D2D7B8794A0000023194CAE1EA01FEF05F07071800757E8583633300000000116194B2A7A47B3800000000063E94C1B6B8BB89340400001954AECBCBA6B0B27A3200000A5BB7DCE3D2CCAE4611063897CAD6CED5C2AA4C000000105EB0D2D4CFC27D200000002873ACCADEE2D9A33D0B084A94B6C6C1BCB3A869436964527095A6A6A892A07B260000397E99B3AFA99F9D7457637C4A325F90A195A1AA9D7A714E283A6489ACA7A69D95856D1F00001849748B989365481E000000000000437E989B7436080000082F8FD5F1EAD7AF78371600040A2682B6B9955732201BB2462C4D85CDE0CE9D6D4A2417141A284385D4DBBA7C440000082F8FD5F1EA01FEF15F070718107B8884806B3200000000025B89ACB3A270310000000000449DC3C2B4B1873A060000135CB3DCCEA4ABAA7A2700002363BCD9DADDD3AB4E06053A9CD1D9D8CFBFA84A0000000B65A9D3DAD9C88B24000000266CA1C0D8DED295350611549FBEC3B5C1B5AD6A4E696154758DA6A3A89EA26D1700024884A4B4B199969C7D535F5D35285D99B09AADA6977A6D4421466A8DA3ADA2A8958D6C1400001C5C7E8C948965471700000000000039719A9F792F000000083090D5F0F0DCBC8246210000113B8CBDB7895A2B1119A748273F85C5D7C99C703E241B141B234091D5DCB26D390000083090D5F0F001FEF25F07071820767677705A2E00000000055889A6A39A6D2700000000003B90C3C1B6B6813D0000001560B3DBD0A9ABAE732C01002368B5DADAD7D0B04A09023498C7DAD6CBC3AA4E0000000F67B4CECDD1CD851F0000002B6FB0CFD7E5DB9D2E071353A1C7C9BEB3B2A85F46696052799FAAA09E95A16F1B00003B86A7B1AA9F99997956616535275DA2A68F93AC967C694C314B729DA4A6A19B98905D1E0000205A868E9D8D674B1B000000000006467B99967A300000000B2D8BC8E6E3DAB57C3D1B06000B3397C2B8895B2B0D05A43F22478CCBE5D49E69422215111D2A4695D9CFAF6C4800000B2D8BC8E6E301FEF35F070718307E7B776A53240000000011638E9BB3A0682303000000034AA6D0C3B4B5812E0000001559B5D6CCAAAAAB742C07031869B7D9E2D9CE9A3F0A02399ECCD7D0C8CDAE4D0100000F5DACC7CDCBBF8C220000003A77AFCCD7CFC99C38010E529CBCC9C0B8AFA36A4B6760507BA2A8ABAC989C661000064B839CAEAF9DA7A47F4F626D39255B92A2A1A2A88F74644B31436C99A7A29EA390805B09000020628295998D5C460D00000000000B467D959F7C33000001022B92D7E5E1D9BE8340140000062C8BB8B98753281112AB3E2B548FD4E6C8976C3E1C17181F2B4D99D7CEAF67340001022B92D7E5E101FEF45F0707184072737869502000000000085387A3A8A37428000000000146A3C6BFB1B670260000001F6EBED8D5A8AEA6752800001B66BFE0E7DCCDA3410200379CD0DAD6C5C9A64F000000186AAED6DFCDC58A210000003181B9D6E3D7CF8F2D04105295C0BFC1BDB4A1664C6E66577C96A99DAA9D98630A000C4C7B9AAEA99E969C7852626A342969A1AB9D9FAA9E725F37264A799DA3A5A99992804A0D00002065888DA19970501E000000000019568FA9A0722E0A00000B3A8ACDE6E6D9B6703E1E04080C3E98C3B97D4A280713A94A324E92CEE5CD98613F1A1419222C509ADED9A86C3200000B3A8ACDE6E601FEF55F070718507B786A644A1A00000000156390A3B1A4682500000000004497C1C5B6BC80310100002064BCDABD9CA4A8701D0700175FC0E2E5DEC895400A003D9DD1DDE4D7C8A2460000001465B1D2D9D4CE8C200000004186B7C6D3D2C987300110559BC2CCBCC4B5965E4967715E799FAD9EA7A18858080000528BA4A9ACA79F9D664B676033346999A78F9BB3A17364403359738FA2A8A5A7937449000000216E8193999368440A00000000001B5987979D7831030000033493CEEEE9D7AC6E3F1109020C3D96C5C17F46231911A53D295793CDE6CA885B331B1C1923254B9CDDCE9E6A380000033493CEEEE901FEF65F07071860767D7C6A4D1900000000135F8EA5A39E6B2C00000000074FA4C3BCB8C177200000002274BAD9CBA09DAC74240201216DC1E1E9E0C78A4202003F9BD1E1D1D6CCA947000000156ABFD3CAC5BF83210000004390BDCFD4D8D18629010E59A0BAC1B9BCBA97624C71645D81A29CA4A5A29F620B00094C83A2ABA9A599957A45657241356B98A08E9BA299705C3E315A86A0A6A59F9C887740000000306C8690928C694413000000000013588DA2A76F28000000002D87CEE9F4DBAC6725130706104998C2BF7E441D1116AA49395BA5DBDEBE8A5A341A1A1827255AACD6CCA262490000002D87CEE9F401FEF75F070718707B767D76491C00000000156C92A9AD9C6C2300000000024A99C2C5B4B26A290000012D73C4E3CCA2ADA86A220306236DC0E7E9E0C8923600033D9ED4E3DAD0C1A2460000001863B0D9CED2C577180000004A96BCCFD4DCC88327021960A4C3CDBDBDB39B625671666484A3AA9DA29F955805000E52889DAA9C969E946C4262632F2D6D9DAF969EAFA0685C353B5E7F9FABA5A4A38B744E00000025739091978D6B470F00000000002E678BA29A792D0000001A3B94D1F2E6D8AF6C31060F0E134493C2BE763E19161DAC4A3060A2D8E4C5895531111019223459A8DACA985C4100001A3B94D1F2E601FEF85F070718806E7361593E0A00000000116A95A6A6A1792700000000094D98B4C7B9AF772A0000002B71BEDEC8A3ADA55E1E03092271C6DEE3DBC194390505379DCAD7D2D2C4A3490000002077B5D8D2D0C47F1B0000004895C5C7DDDECC761F051A64A9C3BFBBBAB59D57536C676188A9A99898979147020010588DAEA5ACAB9D8E674B63622F2A619BA59A9EAB9C6C4A323E638DA7A7A3A0A493813C0000002E6C8697A09365420F00000000001D6784A2976E21000001083090DAE6F0CDA06C2707060E0D459DC5B6764526171CAB462E60A4CBDCBB7F512E2010162F415BB4E1C5975A3D0001083090DAE6F001FEF95F07071890717F7562350D00000000196E99ABA79C681900000000044BA0C6CAC7B572250000002672BDE8C6A19CA15F1E0002246DBBE3DFD9BE8F3B110A3D99C5D1D5CECBA5420000001F74B9D5D4D0C287200000054D92C7C8D5CDC57F23001364A6BCC9BBC4B49A4C477C686C8AAEAEA2AB9E974F06000D5A88A1AAAEA7968F62476F5B282668A8AA93A6AB92654D35345E89A4A4A2A6A0927230000000437A96929C9961400000000000002C6E98A39D75210000000D3B90CCEBEDD8A86C2B11040311519CC6AF6E401F1218B04C3466B1D3E3BD7D4629141A1A293F67AED9C296593C00000D3B90CCEBED01FEFA5F070718A0776F6D63310000000000156E98ADA5976319000000000D4EA9D5C0BDB372240000002B76CAE3C49C9D9D571D00002873C2DCDFD6C3883009053F8ECCE1DCCFC99B4A0000001A73BBDAD9C9B6771C0000064B94C9D5DDEACE7A0F042368A7C5C1BDBCB59954456866658EADB3A6A49B8B4F0100106791AEA9A89F968C5944695D27266C9BACA4A7AD8B6346333B708BA0A7A8A598896A2C000000477E92929488653C0900000000002C7293A08D672D020000033E95E2F3EADFB25B32170C041E4D9EB8AA6F321F1214B2492A66AEDFDDAD794C27140E14243B64B1E5C38C55360000033E95E2F3EA01FEFB5F070718B07B756F603A090000000019659AAAB29A6D1E000000000C4DADD2CCCAB96C170000062972C1DDC8AEAE9854160000287CC7D9DBDAC885330100388DD1E4DCCFC29D410000001C73ADC5DDD5C57E1D0000004099D2CAD0DFCA7A2108256DA7B0C1C2C2BA974E5375637398AEABA49C9B8A3A000012649CAAB3ADA294956148675F282C649FAA98A1AC9163462A42648EA0A4A6A0A28E68290000004B7C949A9D9358350900000000003573939E996F230000001544A2D9EDEDDCAD5D2C16080C1C49A3B9B6752E0E151BAD513072BCDEE4B2723C2C1C200F263A66B3D9BC804C3100001544A2D9EDED01FEFC5F070718C077756E572D00000000000B658FACA89B6321000000000D4E9FC1C1C4AD65180000002C77C2D6D4ABAA9A481700002B6EBBDFDCD2BA7A24071545A5D7DFD9DAC7A83F0000001772B2D4C6C8C180160000075792CDCFD7E2C67C1F002174B0C3C9BEC4BB9A504163596195AEB49F97988D3F000019628DA6A79C9A9EA05C496B5B2927709CACA9B2B3865D4B32456E8EA2A8AA9E99835B2D0000044B87978E958C5A280000000000002D77919F9361230000000C3F9AD6F0F1D2A861231A0E0C2551A4C7A8652E1B1419B14C2E6BB6E7DEB35F3216101E1E243B6DAFD1BA88553A00000C3F9AD6F0F101FEFD5F070718D077807A5B2F0000000000126D96A1A5985F1A000000000A5EA6D5DCCAB5601900000D3877C6E2C5ABAFA2571503082C6FC2DEE4DAB37A280106449ECCD1CFD0BA98340000001F7DBBD9CCC1C88218000009509ACBCBDBDBC4691E072273B9C0C6C2B8BA9B564F6A54719EA8A89DA5A08A4403001C648DA9ACA4A19F92553E5F552527709CB19EA9A386554E30416E99AFB0A39CA2805B2800000C437E959391875A2C0000000000003B7497A0865F1D0000001044A1DAEEF2D7A45E291A03051E50A6B6A26233140D18AB533376C2E7D9B0653B22171F222A4773BDDCAA7D4A3300001044A1DAEEF201FEFE5F070718E0746D6A4B1A0000000000236E9EABAC956521000000000E51A8D7CEC6B765150000003085CEE0C8ADB3934C0F000C2A83CDDDDCCEB56E1F04013E9FD2D8DDCFBE93390000002676B9D4D8DABA7A1A00000555A5C8CFD0D1B9681C042877B2C8C8C2C2BE8B43516E5C7896A6AE9DA999853C00001D78A2A9ACA1A4A08E62496655232D729CB0A2A8A07552412F4D7C9BAEA9A99F967E52140000064D859EA19689532B0000000000003C7A999B8B551F050000013297E0E7E7DA9B571A1C06020D55ACC6AE693620151CB24F346FB9E8D5A56138180B2031304178BDD8B27B4C3D0000013297E0E7E701FEFF5F070718F079746E451B00000000001E6C95AEAC935B1200000000135CA2D1D4D1B866190000032D79CBDECEABB4924A0D01002F79C1EBE5DCB86F24020D409ACAD4CED2BF9A3C000000267BB1D5DDD0BD771E00000F5AAFCFD8D7D0BE7015002679B5C1C0BBBCAE914A496B5E75A3B6ACA59EA4883D0000247189A0A0A4A39D8854436256212B70A6B9AEAEAA8541352C547B989DAE9D979A794A130000125A8D9A9997995A200000000000004D84A3A18A6122000008053C9FDCE7F0E1A2582A131416235FA5C1AB6935130A16AC4B3774B8DCDDA65C3018171D202D3E75B7E1AA6A3C3D0008053C9FDCE7F001FE006007071800766D6C501800000000002C7498AFAAA56820000000000C5BB0CEDBD5AF641C00000A3A83C7E8D4AEA486461000022E79BEE3E4D7B7751B00074197CAD6DFDCBB9132000000277EB5D6D0D0BF791B00001060A2D1D6D1D3C0661B002976AFC6BBC1AEA5824C516D677B9CAFB0A09EA38040000028789FAEB0AB9F96874E4463522A3573A2AAA9AFAC794C382B597E99A7A8A4A99D7943060000124B8A9E9690895A2F000000000007568195A58E531B0003090F4AA3E1EFEFD3A15828150B051859AFC4A861271B0111AB523F73BCE2D7A4582618171D1B324C86CBD3AC6F4C3503090F4AA3E1EFEF01FE016007071810707576480C0000000000296C9AB1AF9A641B000000000D60A9CED3C6B6661100000E3D88CDD8D3B1B9943F0600042E84BFD9D7D3B86E1900083F9DCCDADFCFC598360000002C7EB8D2D4CFC3721B00000C61A7CECCD8DEC26B170B287CAABABBB7C2B1904945646280A8B7AB9AA9A77A2B0000317BA8B0BAB39D968E534E6B45222A6C9FA7ACA9A7764E2F20548698A6A7A6A0987343120000185F8C95999B80522D000000000000598CA1A5824B29090D0619479FD4ECEFD8A75720160F132E62ACD0B15D1B0D091AAF4E3C78C0E8D3AB6129180E1B27263D7BC3DBB37144320D0619479FD4ECEF01FE0260070718206F6958340800000000002E759BA9B1925A1D00000000105AACC7D0D0B85C0D000013458CD9DACFAFAF8D38080009387DC3D6EBDAAC601700093996CEDBD9D3BB92350000003A7CBCD8CEC9B974170000136CB3D2CDDBD4B668120D3A8AC4C4B6B8B5AE8037425C5768A2B5AFB2A7A5803900002D7D9DA8ABA4A593854F47574D25297AA0B0B2B39F764435335693A4A9AAA1A59A762F0100001A648C9591958E5A240000000000005591A8AD89561400000B1646A6DAEFF1D69E532A150A121F5FB5C9AC60261F111EAC4F4180C3E6CF985229221017122F488ED2D9AC6A3F34000B1646A6DAEFF101FE0360070718307D6B60390100000000002C7DA9A8A88F5312000000001F56A7CCD9D1B05F100000113C8DC9DAC9B5AD852E03000A3182CFE0E5D1A0622001113C92CDE0D8D3C188340000002C7DB3D6CFD0C6741A00001564ADD0CDD3D5C667160E318ABEC2C7BAB3A770454A675F7E9CAEAFA1A29E7D270000387A9AA1B5A89694834F4B6A4E28366E9BB1AEB59A6D3A282E5D95A4AEB0A6AB9B74300000001D628B9DA09E805B230000000000115A92A9AB8C52220709001650ADE2EEECD498502320160C2269B0C7A45B1F13131BA64B3878C7E6D79E50291B142222315098D5D99A66423309001650ADE2EEEC01FE046007071840716E633500000000000027749BACAB975714000000001157ABCBD3C5B25B100000194695C9D8C9B0B986420D010C2977C1E4E2DAA8540C010E45A0D6DFD0D3AE77280000003384B8D0D5CFC07B1F00001A71B6C2D6D4D1BC62160D3B80B8C3C9BFBFAD84494559607DA6B6ABA29EA4792B00003E7A98A7A49AAEA68851475D4E252A6AA1B3A9A4956437293B6992A8A8ADAAA09C652B000000246F94A3949A88491900000000000C5D9EAAA27E491B0D080D1D489EE2F6EFD199461F1F18061C6AB8C0A05C241B140EA9504184C8DFD495451D0F122029355595D4E59F65422E080D1D489EE2F6EF01FE0560070718506862573200000000000037839DAFB1985B130000000014549FCDD8CFAB5E040000134C8BCAE0CEB5AE74320000093276C2E6E6D49F511100124A99D1DBDBD4B37B2B0000003A79B5DBD6D4C1711D00001673B6D8CDCECAB8611E123A7BB1C6C7B7B5A77242495C4F75A1ADA99EAAAA84200006438A9AB0A7A2A8A18D4B41624D1A2D71A0AFB7B3A26C2F1F2A6897AFA9A8ABA295632E0600002168969D979C894D10000000000014699BB09F7E43140000010E49ABCAECEAD29D5129171A0F2266B0C7B1622B170C17AB4D4284CAE3D0824A281814272D36659BCFD2995D372F00010E49ABCAECEA01FE0660070718607E79693E010000000000338AA9BFB49B5615000000001A5BABD1DDD2B95E0A00001C508DD2E1CDB1A87027040003387EC3DCDCD7AA4D0A000E4797D0DEDED2BE7B20000000417FBCCFD9CFB9681A00001C7BB6D4D0D1C3BA5A1016438CB2C4C8B6B9AD6F433F5D5278A4B2ACABA6A27B2400003E8CADA8AAA19CA4864340675023306F9DACB3AF9C612A19296C9BACB9A6A5AA95601A0000002A6B91979598855218000000000016659CAC9E77461D080E08184EAED7E9E5CE9A47251E141A357DBAC2975921131B1F9F4C388FCAE4CB8E3E20120F1D1C27519EDCD9955941390E08184EAED7E9E501FE0760070718707570622D000000000000377EB4BEB58D501302000000215DACC8D3D2B3550F00001F4696D1DCCEC5AD68210200043281BDD5D6D4A34A0900194A99D1DFCFCAB6731D0000003C7BB8DAD9D7BE6F1900002A81B7CFCCCFD3B95213184488B2CDC8BFB69B63354B58577AA0B3A6A89F96741F00094C8AA2A39E9DA0917B4337644B25347DAFBDB5AF9C65251628719FB4B0B7AE9A9361200000002C748F98A09D8C511000000000000C679EA6A27F401D0C0B152156ACDCEBE1D1964D33221C082570B9C4A35A190B0C1BA54E3E8CD0E1C7895523131F24263453A6CAC99259333A0B152156ACDCEBE101FE0860070718807A776722000000000001408AA8B4BA984919000000002469B7D1DFD3A859090000235295CAD8D4C6B46C2300000C2E82BBDBE0CA8F3C08011E3F9AC7DCD8CDAE6F1E000000398CBCD5D2CFBC6F120000237DBBCFD7CBCEB8611F1E4A88B9C2C9C6B29F693A48585075A2BBBEACA8A46C1400064B85A9B0A9A9A3997E3E396C4E193379A6B8AFB89C53251D447D9DABA7AFB3B19A63170000002A6B8B9B9B9A8156170000000000186E9EB29B79410B00070A235CB1E1E9E9D1914E20120E0A2F83BBC89D571C141822A3504086CEE2BC803F1B1A2120283360B7EBD68F5D4034070A235CB1E1E9E901FE09600707189076775A270000000000004294A9AEB4984F19070000012566B1DDDED8B7540E00001B5D9CD1DBD1BFAE631A0000083480C4D6DBCD8C3600082750A1D3D8DDCFAD681A0000003E84B3CBD4CCB56F1C00002B80BCD8D2D7CFAD5518143F85B5BEBDB1B7A66D373F4E5579A7BDB5B3B79D6D1600085196A6B0B0B1A89C7E3E395D42213975ADB4B3B1974C151138799FAFAEAEAAA0874C10000000337A9EA3989180450700000000001A77A2B8A47D46290C0A0E195BADD2E5EAD29550282219163D81C0CA9D5920110818A53D4494CFE3BB7A3E251719312F3F62ACD6C88A5F3B3A0A0E195BADD2E5EA01FE0A60070718A073746220000000000000508CA7B3B2944F1300000000206BB7D9D7D2AD520D000021579CD9DFD1BFAE681F00000D3183C3D6D2C68A4100022252A2D2D9D3CD986B1C0000004391C0CBCDC8B3611000002E8DCCDDD5D0CBA95417244A98BCC3CABEBCA75E2B414E5673A1B9B9AEA797661200155492A8ACA6A3AE9C7C503E604C1F3377ACB2BEB4984D16113577A0AAABB2ADB09357180000003478979E978B804D120000000000237AA5B4A2703E1D030D0E2164B6E5EDE7D49A47272013173C85C8C199581814181FAA4E498DC8DABE7F3621101B131F3A68B9E1D1895336360D0E2164B6E5EDE701FE0B60070718B07471591D0000000000004A8EA7ADAF915111000000052A66B4CDDBD4A85C120000265DA5D1D5CBB9A75C1900000E3A85CAD6D9CA883208031B4DA1CEDCD5C7A56219000000458DB5D7DBD6BE6E1B00002B84C7E5D9CED5A84D141B5297BEC2BAB5B79E5E343E505383AFB9AEA5A7A16B1C00135E94A4AEB0A9A4A17C40406045203A789FB0B4AB8B4E100E337C96A9BBB7B3AD9E520E000008377EA4AA9E917F4A0D0000000000297DB1BC9D693F120E10183466CDE3E5DFD1944C261E0E143884C6BF984C160C171DA351408BD1DDAF683B171A0E172B4170BAE2D78A51583410183466CDE3E5DF01FE0C60070718C07D755E200000000000005D9CB3B6AD884611000000002C6AB3CDD3D7B34F0D00002566ADD3E3D5C6AC580D0000093682BFE0ECCF80340F061F5D9CCDD7D0C09A5512000007418ABBE1D4D3AE5B1A00032E8AC5D6D1D3C79950171C5196B9CCC3C5C29E5D2D3D434370A5B6BAA4B8A65E0900005A97B4A5B3AAAD9F7A433E5E44213385A8B7B5B28C4810073C8BAEADAFACB2AD8F500D0000004688A8AA999B793F0500000000003483ACB89B673B150711192E66B7E0EEE5C885402E271F15388CC3B98A522017181998545496D4DDB0653C2024171E23416EC6E5CA7D45373211192E66B7E0EEE501FE0D60070718D08372531A00000000000856A1B2B6B48E3A1500000000226EB4CADCCAA64F0800003273AAD1CFCEBEA855110000124381C8D2DDC5832D07002C529DD1D1D7C69C47070000004E8EB9C9D3DEB7601A00052F8FCAD4D0D3D3A659212A58A1C0CEC1C0B89B522234454182ABB0B3A6A390530A0017669FB7B5B5A19BA3753E3E5740254089AEAEA9A588400513427FA6AFBAB7B2AE914B140000033B829B98939383420000000000003188B4BB9A6D380C050D0D2564B7D8EAE2BE843E221C170D4293CEC38F4B22150E1DA6534297D1DDB16F2A11171C2A303C78C4DCCB7E4C363B0D0D2564B7D8EAE201FE0E60070718E07A77591600000000000D5A97B6C3B8973F1C0600000A3675B8D3D1C69E480A000B3D74AAD8D2C8C2A64F0A00000C397DBFDDD8C87326000F23569FCBD8D4BB9448070000124C9AC0CFD7D3BD5A0C00043B8DC6D7D2D2D79D461C295E99BCBFBFBDB69656263D3F497BA7ACB5AFB1A65C0E0018669BB8B3BFB1A39774383C503C22488BB2C0B2AF873607073886A5BBB2A7ABAC934E0C00000F4F8E99A19F9680440500000000013787ACB9996937150D0E182B73ACD5E9E8CA90452B2413114F93C6C1914D2419151C92495399C9D3A3642D1E0F14282F4B82C9EAD1804B37340E182B73ACD5E9E801FE0F60070718F07274531400000000000568A3B7C4AE89431B06000007377BB1D3DAD6A8470000063477B1CDDDC5B994400700000D3A91CFDCD5C6832500052E5EA5CCDCD0BB8748000000085298BDD5CEC8B3541108103D8CC8E2D4D4BF9E451D2E61A7C1CFC8C8B18F44132B374282B5C0B9B2AE975D0900236A9DB2BABDA39D9A71302F4B3E27528FA8B3B2A77834100E498DAEADBCB0B6B293410800000954879D98A28E7149000000000000358FB7B3A26434170610163073B7DCE3E3C48A4725221A25569ED2B48B3E23231A1399454594D5DBB160291613122B35538ECEE9D67C543D2F10163073B7DCE3E301FE10600707180071694411000000000008669EA8B4B89042110000000B3478B8D4DDC79C4200000F4A77B8D8D7CDBD9D3F010000114486B7D0DAC670160005205FA4D0E5DDBA8335000000055BA0C1D6D8D3AE5506000F4B9CD3DFD5D1CB9E471B30679FB4C2C2BCAA884C252F35427BADB9BAB2B69D5A050020649FAFB8B19B989D7B363C59391C4689B6BDB6AE742C00095092B0B6B2BCB5B29A4804000010548E99A5998B7A38000000000000418CC1B897652E16080C11346CB8E3E1DEC68D3F201D1B1B55A2C9C493432113071D994C4DA1D5CDA45B2B241C1B22324D87CCEDCA724A34340C11346CB8E3E1DE01FE1160070718107A71480A00000000000D72A8A9BEB2874D1400000015417FB2D8D5CAA8490B000F3C7EACD2CFD3CBA14B000000093F8DC6E2D1BD711E00082A63A8C8E0DABC7F310000000D56A2BFD8D5D4B35A0A0012399AC4D4D1D0C89647233366A6BCC1C4B6B28E472438344578B3C5C5B6AE8E5101002A71A7AEB5AFA9A3A37931384E32284987B0C4BBAF6C2600104E89B1C6C4C2B9B28C430700000D5489A6A8A189783A0800000000014395C0B8996328141012183579C2D7DFE0C181382321181C59A9CFB6914B26110F1AA05553A8D2D38E5625181A252B344B95D8E6C6714B332F12183579C2D7DFE001FE12600707182086694A080000000000186FA1B0AEAD7E38120E000017477EC1D4D9D5A9420000104685B0C9D2CDC097370100000F408CCADEDDC2651F0010386AA6D4E1CFA9782B0000000B5896B6D8D1CDA45E14021044A8DAE3D2D8C1913A1F356CAEC3C3C5BDB386431A29364B83B5C0C2AEA58E4F0000266FAAB3B0AFAA9FA06A2D2E4B3A364C8EAFBFC0A4692200094B9AB6B8BABBB0A87F30060000135E92A09E958E74350300000000003B93BCBB9276361804100E2B71B6D0E4DFC97F361C1A101E5DA7D7C38948240C161C9E5152A6DBD59E521F14122226274E93DCECC779443834100E2B71B6D0E4DF01FE1360070718307166460800000000001581A8ADB8AA88391A110000114280B3D2D2C6983F0500155285B5C9D2CCB28A3700000011498FC9D5D8B46214000A3B6AABD2EAD2AD793300000012629FC0CEDDD6AC5810041E4E9BD1E2D1CFC98B452D4076B1C4C1B9B8A88230142225407DA8BAB6B7B1A15A0600367DA4B4ADADA096926D31344134295395B4B2B5AB6E1D0010559AA9BAB9B6AFA6893E0000001C6791A4A49D967D3400000000000B49A2CAC18F572C08061E244075B9C5DEE1C0833530241F2466AFD8C084471D160F19A3524FA0D5D1984B2018211B283055A7D7F0C17141433A1E244075B9C5DEE101FE1460070718407A6E38040000000000127FB0ABBBBA843B180E000115487FABC2CCCC93390000125090BFD5D1CDC79E3A0000000F4196C6D5CCAF5A18001E466DADCED8DAA6742B0000001861ACCCCEC8CEA5470800144B9BCADDD2D2CD893F1F3D77ACBCC2C0B8B78438193C34467DA1B8B8B7B18C4603003691B3BDB1AEA39C90622B303D30234F8CABB6BFAC6810000F62A4B5B3B7BEAEAE7C3D0500001A6B97989098947D3F0000000000044EA1C6B6895229151718203A7EB4D6E3D4B9753A1E1B1D316AC4D7C3824D2918231C9D4D51A9D8CD9A53251D181B2C3757A3E1E4C56E3A363618203A7EB4D6E3D401FE1560070718507A76450400000000001E74AFB3C3B18040170E0200154C81ACC9D4C8903C0300135688BAC9CCCCC18A2F0000000F4991C3DACEB3591E02214172AED4DAD6AC66250000001C65A1C4CCC8C7A94F0E0017539BD2DCD2C6BD8140234272ABC2C2C4BFAC793A1D26304185B1BEB9B0B3964905003784ADBDB4B6A0A297692B2C37312E598EB6B7B1A0611200156999AFBAB3B2B3A979330700001E7194A3AE9F927D3D0000000000025E9EBEBA944F2B1101151F3E89C3D9E4D7B2752C1F1A1D2D69C1E1B47D4B21181820974350ABC9C5944C1A0B1924283660ADE6F0C170443139151F3E89C3D9E4D701FE16600707186076714C000000000000238DAEB8B9A46E3018130609225489BCCBD7C694340A01185F96BBD1C8B9BA87320000000A478FCCD1D5B35F1809164178B7D6D7CFA85D170000001B68A3BEC6C6D3AC4D11011652A8CDE1DBCFC782301E4D7CB7BFC1B2B7B378381B2329458EBACBC5B5B0883D02063E92B5B6B2AEA5AB9A641F213F282F6394AEBCB8A36009001A629CB4C0BAB7BCAC7F410C00001D6B969DA09D87723300000000000550A2BEB0905B291213172A4381BACFDAD7B1723B221C192E77C0D5B980431A13141D944754AEDCCA8C4D200F232932395FABE3EBBF6B3B3634172A4381BACFDAD701FE1760070718708471480500000000002F8BB0B7BBB478321C130C0F265F91AFC3C6C78A3104001E67A5C2D5DAC8B98D350000000C5996C7DED1A7500B0423527AAEC9D4CAAD56170000001863ACD0E2D1D0A14100031C4FA7DBE1D0D4BB7C301D4985BBC9C5BAB7A5702E0D262A3F7EAFC2BBB5AE944000023D89B7B8B1B0A2A6A0682B1D3837365F95B9C2BD9E5B1D002870A9BAB9BCB6B5AB7933020000186B8A9C9F9494753300000000000355A3C5B98D4D1D130E16244781B9CFD4DAB37533271C162871B0D7BF82411F1E21188F4F5CACDFCC8B471F1E1E242B2A60B7F2F5C06436343916244781B9CFD4DA01FE18600707188074693C0000000000002477A8AFBBAA6B2B191308092B628FADC5C5B37F25000021619ECBD4C9C9B780240000001153A1C7D2CAA85417002D5C87AFD3D3CB9C4D19000000195EA1C4DCD0CCA24D0A012658A6CEDFD7CCB46D27285589AFBEC8C1BAA76F2312222D427FA7BFBBB1AE9C4505054996B4B3B9B6A7A0926221193428326598B2BEB9A3550E001B74A9A9B8BEBFBBA97C2E0100002E6E919C99A290773100000000000357ABC4BC9154251C1416254687ACBAD1CAAF713226261C2877C4DCBE7D432520111794485DADDFC9884A24152D2E2D3B67B9EBE8B16938332E16254687ACBAD1CA01FE1960070718906C68470000000000002E8CA8BBB39B612C141201072D688EB2CCCFC0843000003173AAC8DFD2C2B6802A000000175199C4D2D8A44D15001C5B83B9CEDBCC89411B0000002171A5D1D3D7D5A94E110C2C68AED7DBD1C8B06B312B5782ABB2BDB9B3A466240E1A2A528AADBBB9A9AF8B3903034591B6B8B6BCA8A7935B211D322C3A649CB7BEB19A5001002871A4B4BEBDB5B3AB782C000000226E94A2A092897B3B00000000001E6FB0C2BF8C4B2B1812131A488DB9CED2D0B06C2F2C1E203081C7DCB8813C13061624965462B1E0C88B451D201F29232A5DB7EEE6BB6B44303A131A488DB9CED2D001FE1A60070718A07A72470000000000003D92B3B8B8A1673115190E151E5C95B2CAD0BE85330000256FA2C1D4D2C7BE84250000001557A4D1D3D3A34A07001D528DB2CDCDC79A410B0000042E76ACC7CFD4CB9938010B2357AAD4E0D6CBB369322E6491BEC8BBB4BDA669260D25283D82A9C1C0B8AF8F4000064E8BABB0BAB1A4A59C56211E323644699FAEAEAA9A4910001E78A9BEC1C2BDABA17B2B0000002474999F9F9192763D00000000001F70BFCCBD8E532B1A101A254D8CB7CED9DBA2703623231D2A86C9E0BE803D1A1D17208E4E62BAD5C487421F1A1A252C376DC2F1EFB9603C34341A254D8CB7CED9DB01FE1B60070718B077713A0000000000003293A7AFB3AB682C1A1C0E0E27649DBDC1CABA782700053185ADC6C9BEBFB97F210000002367A8CDCCCAA24D1101236191BBCDD5CA8D480C0000022E78B2CED5CFC2913705022866AAD5D2D1CBB061302F668FBABFC3C5B29C591E0C1C274386B4C7C8B9A7873100044B92AFB1A7B6A5A5995D171B2C2E3F6CA3B1C2BC944301002478A6C1C3C2BCB6AB742A0000003475899D998B7D6A320000000000186EB8C9B28854250E12142C4E87B0C9D8CDA76A2C2526213485CDDCB28139170D1029955566B7D7BF82411B14222033306BC5F5EABD6142323A142C4E87B0C9D8CD01FE1C60070718C07A744F0000000000003C9CA3ABAF986034231A0A1B316A9CB8C4DBC0781B00023580ADD0D4C7C1A9821B000002205BA6C1D0C79A430A0625638FB6CED1BD8433000000042E75B6CACFCFC595420E0F2E6BB2CFDCD3C7AB692E33628DA4BFC0BEB29E5717061128458AC3C2CBB5AF873100094F8FBAB8B4AFA09896561E1627344477A7B7B8AF894100001A74A6BAC9C9BDB9AD6A250800003484989E9A9C8E6A3800000000002778BCCBB388542117111B1E508CB5C7DDCBA16126292A1F3583CEE5BE85461C1A151A904E70BDDEBB7D3917141D1D2A3371C4F3E4B36A4330331B1E508CB5C7DDCB01FE1D60070718D077764A0200000000004296A4A4AE9563241A18130F3470A1B3CACBB5762000003690B2CFCDC4BCB679220000001C66A6CED4C59C440F0126688AB5CCD2C3883901000004317CB3C4CAD1D5A13900082E6FB2D8DAD8CBAF5F2B306999B9CAC8C5B69E510B0010244988B7C3C2BFAE8E39000B5F91B5BBB0B8A29E905A1C0C253C507498B0B5AC853F07001871B1C0BFBFBFBDAA6B1F0000003282919BAB9B866C4307000000072F7FC3D2BE8B54271A1817285B95AAC4DCD2A5672E2328273893CDE7BF7C43241E202A8F5675BED3BD7E3A191C2326283778D1F9EFB666422D3617285B95AAC4DCD201FE1E60070718E074734E0600000000005294ABADBE9B592C1F1A1210437DA7AFBEC8B2742400002E7EB3C7CDCCC2B06D190000002667A8CED6CF9A40040130638FB2C8CCC085350300000C3279B5CED3D0CA953109133D73AEDAE0C8C3A361212E6D9EC0C3B9BAAC935018000F28478CB8C1C7B5B2893500135E9DB8B6AFB3A0A79B52150825334D7FA2AFBAB28E3900002E81ACBDBFBEB4B59E681B0E000030899E9D988D95724606000906153889BECDC2894E261618212B578DABCEDBC8A56B303031274791D4E5B8773619161C1F894D6BBCD7BA76341D24262F3E4177CDFAF0B05B3F3E36212B578DABCEDBC801FE1F60070718F070734E030000000000529AAAB2B5A45329231D11173B77A5B8C3CDB8691F00003387B3C6D0C8BAAD75170000002876AEC7CDC192390309387296BDD0D0BF8130040000062D80B0CCC7CFC58B38040C4179BBCCDACEB89B4B1B2F749FBBBFC0B8AE8E471304172C508FB7C7C6B9AB8C31000B5F97BABBB4AEABA38F52140B1D385381ACB4B0B2873600003083A4BCC7C6BEBBA96B220100083E8089959D97866F2D00000000002E86C3C9B3743B29171E1D2E6097AECAD0BF98543127261E4398D1DDC0773D16151A208D597FC0DCB4723A17282B25323E79D6FAECB5663D32381D2E6097AECAD0BF01FE20600707180076714800000000000352A5A9A4A29153231D230F204E85A3AFC2D3B160220006439CB9CACFC1C5AF6917000000256BACC4C9C28C2E000239759AC4CDCCBD7F2E000000103174B6CDC8CCCF8535000B417AB8D8E3CEC99F561F30759DB9C4C2BEA889410C001327508BB0BCC9B1AE832E001B6FA4B2BEAFA59DAA9D5B150920365485B0ACB1AC8E2800002E8BB5BCCABEB5B09C6E29090001387E8F96968E886D3100000000002E85BBC5B07B452414141E306590AFC3CEC08E4F2C27231E4B95D6E3C07C3D21151D27905B78BAE0B67337231F272830417BD0ECE7AC573033301E306590AFC3CEC001FE2160070718106D6F40000000000008599FA9AAB5975B252D1C171C3778A4B0BDCAAA691A00074798C5CEC8C1BFA15E140000043174B0D0D1BE883C0A05366FA0C9D2CCBB803404000006387FB4C9CFC9C4883101144E74B2CDCDC6C7A05524397BACBBC6C1BCB08A3F0C0003255F92C4C4BEBBB883220016609EB2B7B5A6A8A392580E071D3E5186A6B2AFAB822B00003A7DA7BCBCCBBCB9A15E251100073D829196988B80613903000000003D8DC1CCAC8A46221B10202F649CB7CDC8B09A5831262A204797D7E5BE7E461A1C141E875878CAD0A968311B1E21292C3984D7F3E3A35E2E3430202F649CB7CDC8B001FE2260070718207C794500000000000C54A9AAA6B28C412828290D163C85ACB4C4CFAD631B00054BA2C3CBCACEC1AA64130000042B78B7C9C7C28D390507357DACC0C9CEB67B280000000E3D88BDD0D4CFB47E2303134288BBCDD5C4BF9048234377A5C1C3BFC5B68C340100142B528FB9C4C4B4A78732002169A7BDBCAFB2A0AA925F04001B45618DA7ADB1A674310000378EB5BBBEBFBDBCA1641E0800023F788F8A988E8568390C0001060F44A1CDC7B07A4F251416222E6CA0B4D1D2B7895434302739469EE8EBBB6E330F11212E885985C8DBAC6434182B2F30384887DCFDE3AB5C343532222E6CA0B4D1D2B701FE23600707183067724500000000000D67A4A5A2AB8A502323181724488BB0ABBECFA4570C00084CA2C2CECABFC3B5761A0000002C72B3CED2C3823100003E7EA1BBCECEB87120000000154388BEBBCECBC178280A1B5285B3CAD6C4C29B411C447DACBCBCB8B8AD833B0204172B5899BEC3C1BCA6792300206CA1BEC3ACA49E9C8D45040923446395A6B4B49E7F2400003D88B2C3C7BAB1B8A6682508040A3F85958C9F9789713D0A000304084199CCC5A2764A2A121C23326D98C5CACFB1885333372C2A51A9DEECB86B36231619248D6187D0D8AD6530181E262638478FDBFFE8A962342F3023326D98C5CACFB101FE2460070718407685510600000000185EA1A9A1A984462C2A2619234E9CB4B3C3C8A15C0F00064BAAC5D2CEC8C0AA59100000052E7BB7CBD3C7853400013D80AEBFC5CBBB751D0000001E4690C3CECDCABA7A25091B608FBFD4D2C6BE9448233C83A7C2C2B5B09D7C32000008275693BCBBBEBDB27A26001F6C94B3B6B6B6A6A68D4C0A0022456D98B4BAAEAB681B00063782B4B5BEC9BEB3A45C210A010539859793938C8F6A31080000010B449AD2C8A4783B13151A2240759DA8C7C4B186512B302A3961AEEBF6B8783C241B192A8C5C93CAD9AE6B281E1E212C314A8EE1FAE5A6554935382240759DA8C7C4B101FE2560070718507D794900000000000E68A9A3ADAD843B262821141F5093B8AEC4C4A1510C000650A9C6DECEC9BF9A5E080000053C7CC2D0D7C57823000B478DB2C8C8C2BD752600000027488CAFC3D0C6BE7D1E00225A92BDD3D7CEBD843B183D8DACB7BAB4BDA16F2D04000B3559A4C8BECBBEB38620002473A9BEB9AEA69C9E894612001C446594A5A8A2A6761C00094689A9C0C9C1B7B39B4F200800104C88969F978E835C32080002101E539CD4C8AE713C191C1B284076A6B4D2CEA77449272C322B5CADE6EDC26F3A10121D277F6296D8D9AD642F201F2631384D91DCF7E1A556362B32284076A6B4D2CEA701FE2660070718606F6D3F0000000000176BA79B94A0803C2134291D255593AFB5C2B6964E06001962ADCACBDBD1C1A95B060000143779B1C4D8C77F1F02104D90B7C9D0C2AC711A000000235094BECEC8C3C07D2500165C8EBCC9D7C6B284331A3A85B0BDB9BABAA26A2100000B35619CBBC3C9B6AC7125002C7CA9B5BFACAAA4978E45000024516D8BA9ACA89D7528000D5593BFC4BFB6B4B0975D240F080B437E928D939C8F69380C09070D1D50A9E0CFA56B38222020253D7199B0C9CEAE7B4B282D2C346EBDEFEEB6682D1F101931896795D2D4A65B230C1A2C372E468EE7FBDE9E5739323B253D7199B0C9CEAE01FE2760070718707576440000000000116AA2A69FA97F3F22302D19215BA4C1B7BFBD914106001565B4D3D9C9B9B59D59170000143881BBCDCCB9732F03105A96B8BFC7CAAA781F000000214992B9C7CAC1B8771F002A6D98C7D2D9C6B67B3318409BB7C5C0B4BA9E661800000D336197B6B3BCACA47829112E83A4BEB8B3ACAB9F883B060010567D9BADADA79B632000084D94B6CCC8B7B6B29B561E08000546899F90919689663C0C040806145AA8C6CBA474432E222427397297B3D0CEA6763F2B2D35366BBDE7EEB96A351818213085639AD2DAA7622A1F1D28262D4A9DEBFFE29A583A3C3627397297B3D0CEA601FE2860070718806F7B4B00000000002373ACA19AA878453A3C331D1D5799B8BACBC190470600106BBAD2D2CCC6B89C5A00000010448EB2C9D8C5752500064A94B2C6C2C6B3681D00000622539ABEC8C7C3AF601B0323659ABCCCD1BDB17A2E1C5295B4C4B8B2B39C5E1300001236629EC0BEB7A9A271320A2F82ACC0BDA7AE9DA18C3F0600245984A7B7AEA497611400135595B1C3CBC0B1AE9B552511051550819099999684532B0C0A0E1D2066AECCCAA164432C2D2327447EA2B5D0D7A87645352F37366EC5F6F2B86E3317181E2A7C6691D6D5A15531241B26292E52A3E9FFE2995138343627447EA2B5D0D7A801FE29600707189079764F04000000002572ABA5A8A4693825302A1F2D59A1BCBACFC78F440C001663ADCFCECBBBCBAE5A0F0000103D8AC2D7D7BD7F2300116090B2BDC0BBAC68160000082B5B9CC3CBCAC8B266180029659DC5C8D7C4AF712819468CBCC2B9C1B7A160180000133C6B97BDBFB7B39E6924082C79ACC0BAB2A79895863600001A5E7A9DB9AB9F935E150418589FB9C9CCBABCAC924F1F14000D448794979492864E410D161F182975B9CEC59C603C3222242E3C80A2B6D0D2A6833F222B353A6EC2ECEFB467341A11251D7E6FA0DADA9F5722151D29313754A8E5FFE89A4F31333E2E3C80A2B6D0D2A601FE2A60070718A07D7E570D00000000318DBCAAA7A6783A2638311A2969AABFB6C3C0963A0000196FB9D2D8C8C7C19F4E0A00000F4387BDD1D7BA6E2C0B1A5DA1C6CCC4BDB76D1C0000072A4E8EBCC8CEC7A661120029669FC8D3DAC2AC7525154D96B6C4BEB4AC8F530B0000154875A7B9C2C2BAAD7126092D74A7B7B4A7ACA39A7E2F0D001C5F8A9DA8A09A9E5D0E001A5AA0C2C3C0C1C2B7934A2A090013508285949A8E844E3913151D1B2F67BCDAC191643D2C2D2F2C5289A8C2D2CAA5733F2234383E80C9F5F5BC682D1D16262D7672AAD6C99554231C232C29385CA8EFFFDE994E3933322C5289A8C2D2CAA501FE2B60070718B06F825606000000002B8FBFAAA5AC7E3E2D3A342A325FA2C8BEC7C2833B08001369C2D1D0C6C8BEA7530500001B4192CAD3D5B56D2806135FA0B5BDC0B4A8691500000E35599CC3CAC4BCA8590C002A6FA9C4C5CAB5A46725194C9AB8BDC1B8AD925600000017476EA5BBBCBBBBAC661D0B338EACB9B2A8A79C97823500012A5A87A5ADB09D9C621A00195F9BB4BAC2C2B9AC864B241209145C8A97969594835E3F0F1118132976C5DCC58B5E38232124384382A7AFC7BC946C352836343F82D3F3F2B5612F18121C387E76ADDED898492216202D2E394FA1E6FFDCA057383336384382A7AFC7BC9401FE2C60070718C07C8C550F000000002981B8AAA49A653432433326305EACC6BDC3B9803F01001676BFD2D8D4BEBDA54F0000001E508FCBCFC9B26223030E5B9EBBCAC0C0B46A2000000F3262A7CCBDC8C1A65D0B01337CAEC9D2CEB8AA60210E5192B0BDC3BBB3874F0700001E4C7398BFC0BAB5A25A1B023689B5B9BFB4A89391702E0300346C99B9B6A5A6824F0900155FA2BAC8C4BBBDAD964222090011528C9992979480533F1A111D1E227BB5D6C78B5D34212627334A8A9BB3D5CF91623A303A3E4789D8EEEDBB5C28171720397D79B0D8D4944F1C1D262D2F395EBDF7FFDA8E47352C31334A8A9BB3D5CF9101FE2D60070718D0737B4C00000000002D87B3A4A1A2703E323C24223774AEB7BCBEBB823000001B77BFD5D2D2C1BD9B4A0100001A4A9CC5D1CCB87026001464A8BDC4C7C0AB650F00001337619CBABDC1BFA4530F002676BCC3CBCEC0AB5E221F4D91ABB7C2BCB08A4500000026517CA2BAC2C9B4A35E18063F83B3C8BDA7AA95937D33000731728FA5A9A2978B550B00185D9EB3B4BDB7B9AC87472809111E5D8F92889293864C41201F25243C89BFD3C08E5E3A3E2A2D314B8CB2BAD4C2966335232C3B3B88DAF8ECB55F2F191B1F2D747EB1E5D894572B1F251F2E3C59ABF0F2D2945C3B393A314B8CB2BAD4C29601FE2E60070718E085885B15000000003B9BC4B1A3A66C3630453A2E3F73B2C9B7C1B87C2C00001A75BFCED7DBCDB995400200001A5698CAD3CFB46C28001458A1BAC6C5C0B168190006174D71A2BCC2C0B9994A00002C73AACEC6CBC3AE5919135BA0BCBEB5B9B98E410000001B597BA4B7C8C4A7A45F1C03398CB0BAB1B0B09C9C6C2D0000296888AAAFA69C925911001A62A0B5C9BFC0B8B38240201B021B588F96919A9074423E1B1A1C193389C5CEC081502F2C28272F4D95B8C1DECE9361361E343E4985D8F7F4B46327101E23347475B7E3D294481E27252E33335BABEEFBD99A4C3F2C352F4D95B8C1DECE9301FE2F60070718F073804C01000000003695BDABAD9C5B30263B36263A7AAAC2BCBEBC77260000237DB6CDCFCECBC09F4E0000001E529EC4C6C5AE672407185CABBFC4BAB5AB6818000118476EA7C2BBC1B890450C032F7DA9C7C9C4BE9D56121C5C96AEC6C7C3B3833B00000026608CA3B6BFB6A8995A1C054791B8BEAEB8A6919A72260000347E9DA9A8A19C8E420600256CA2BBC3BDC2BAA8844326160009568997969F8E7E3E401C1C1D1F3689CFDCB78B4F352A2A334355A2AFBBD4C6905A352E3A3F489BE3F7F4BF67281012263C7077B7DDD68C4728161D242E436DC7FAF4CF7849362B404355A2AFBBD4C690 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 61440 61440 0 01FE3060070718007A7A4406000000003395C0B9B09F61212B422C1F4077B9BFBACFB36F230000217FBCD1CECDBEBF9D4A010000275FA8C5D1CBA860290E155CA0B2B8B8BCB2681B0002194871ACC4C5BFB7943E01073E83B5C9BBC4BA955017164C99BDC8C8BFAD7A32000000286283AABDBDBDB59B57170A3F8BB6C0BAA8AB9B926C2600003C759EB6AE9B9B874A02001C6EB6C8C4B8C2C3B07F3D1C0D00175E8E90978E8B793A421E28232F418AC8D2B17B4E2D2B2D2532518CB6C2D2C990593A262F38539BD9F8EFB062240D141A3B747EC7E4D190431716202B303E6ABBEFF8CE8455312F3832518CB6C2D2C99001FE3160070718107079460B0000000038AACEB4B5A95F342E3E30243870B4C9CEC4B36D2000002A85C7D2D6CDBDC39D3F0000003464ACC8CECDAB6124091261A0BAC4C3C0A85D11000323527CA1C1C9C3BA903F08023882B7BEBEC1B89A480E185496BEC1C4BBB77F25000000296185AABAB8B5B7A04A13134D93B3B3B6B49A959574260004478497A8AFA08E843C07002671ADBEC9C0B8BEA97E402613001B558A959594977E353B1A20201C3F92D5D3B16F4B30262930335890B3C5D1C38A572A273A485B9EDBF9F6B45D2E11171B407983C2E5C188401D2428312C386FBAF5F4CE834A352630335890B3C5D1C38A01FE32600707182070744105000000004095B9ADA29753342A3833343B7AB5C7BFC2AA6D2000002885C4D8DFDECFC194400000013068B1CED7C7AC602204136CABB5BAC4BFA663110004205278A6BAC2BFBD8F3B00004287BABEC4C3B095410C155A96BAC4B4B8A67A2D000000306C91ADC3BAB8B2A350140A428FAFBFBEBFAA938E6220000045809EA6A8A192823E00002D78B5BEBAC0B6BAAB79482B21051D63978A8C90907836402826251E4A99D4DBB6784A3F312E303668A1B0C5D3C68B4D2F273A3A569EEBFFECB0672B1818213B8082BBE5CE884221181A212B486BC0F7F8DA8340292F3A3668A1B0C5D3C68B01FE3360070718307B85500F000000044B9FC0B8B99E522F37423528477AB4DBCBC7B1641800002F92D0DAD4D4BDB79647000004366DA4C4C9CEA96A2C081264A9BCC2BCB4A55A1F0005235581A5C0C2C8C3943C00034180AFC9BDBEB08A410D145093B3BEB5B8AB7B26000000327491AAC1B7BDB19C5212004B90B0BBB6B5AA9C935F1700004180A3B1B3AC987D350000337CABBCC3B9B5BCA77E422A1D0B1658949F919792772C3C233035304F9CCCD9AF6F3C32313235456AA5BACDE1CB834C2928394B65A5EFFEF3B2662108121D3D6793CADFBF803E2119192B324574C0F4F7C57B4D383135456AA5BACDE1CB8301FE346007071840797F4F130000000B4AA0CDC3B99C5B352E42342D4373B3CBCAD4AF601A00033597C8D7D5CDCCC3953E0000113C6F9BC7D4C5A1691F081B62B1BFBFBDBCAA5F1400072F5E8EA9BFBCC9B7822F00004891B0BFBDBEAF893E0F225FA5B9CEBEBDAA7224000000357094B2B2B7BBB29B480B0A488FB6C2C2B5AC90855B1800003F83A5A6AC998F773802083476AFBBC7C0C2BBB0764629100C205989988D8B8F702E44303D3A3E5AA8E1E6AF744F3B323B3B496BB0C3CED8D18C56393A454466BAF3F7EBA5561F0F1921476790CFE3C77D4424191B2A344B6FC2F2DCBA7D46382D3C496BB0C3CED8D18C01FE3560070718506F7249140000000B50A2C1C1B09B5C292C433A2D427AB5C2C0D1AE5F1E00003997CAD1DACCC2BA9233000000366EB0D2D5CDB16E250E1B66ABB9B9C2BB9F5D10000B2C6386ACB6BBC5BE872600024691BAC4B7B8B08F37051160A3B6BEB1BCAE721A000000407395AEBEBDB2B5994A0D0E4A90A6BBAFAFA6988B5F1200065395B1B5B0A09A782E0004347AAFC3BEB4B8B8A375402B1201155D968C99908A6E1D4A272C292E5EB5E0DAA770432E292C343C6CB3CCD4DCBF874E2727344469B8E3FDFBAD5B1B121B24486A94C5E5CD7B3B201116252C4984C6F1EFBF79383634323C6CB3CCD4DCBF8701FE3660070718607B7241040000000552A2C9C5BF92502A34483D3A4E8AC4D5CDCDA754120000368FC9D6D6D7CFC5913300000B4373B0CACCC3A16529031A6AA6BBC4B2B79F501807112C6691A5BBADB9AB7A260000418FBAC4BDB6A98D36032063AABDC1BCBBB67D16000000417D9CAEB3A7B8AB934B0E044E99BBB8B7B8AC8E81510D00054E8D9FAFADA497782E0A08367DABBAC2B9B8BEAE7A41270C0A1B5F979A9498936D2733191A25284C9DCDC99C623D262232363F6CA9C3D3E3CB7F452C2E34466EACEDFFF5B2551A0D1E214B6C98D3F1C573351C111932365070BAF4E5BC7B3D2F31333F6CA9C3D3E3CB7F01FE376007071870707342070000000D54ABD6CDBC9C562D2B49382C4885BACCD3CE9B591400023B96D7DECECFC6AE87330000103F7EB5D0CBBDA56226051C65AAC0B6B2B7A1500904132A7090ABB5C1C5BC7E2700004B9EB9C5C7C7A97B330D24609CBDC9B5BCA86B12000000477D8DA3BDC1BBAF904C080E4F98A7BCBCC1A28988541800094B939DB3AA9E976F380807418CB0B5BBBAB6BEA263412D170B1E6484929A9288671A51424A3A436ABAECDBA973443A3D333D4E74AFBED1E4C77E502A303A3969BEF7FFEFB3591A08162A4E7392D5E8CA72301418252A284B83C8F3EFBE7B473A3B374E74AFBED1E4C77E01FE38600707188069694209000000125BAAD0C6B795582C383E36334082C4D6D9D09F521300004C9ACDDDDBD0C4B185380000104786B3C5D2CDA269330B1F70A2B7B7B8B09C4C0F020D386886A1B1B9BAB57E2600004D96BBC5C1C0AA782C001664A2B3C2B2B4AF67100000084D8895B0C4BFB3A9853B070C4E95B6B7B7B5A88E7E4C0C0014619DA6A3A9A093722F0E094180B3CFC2BAC5C19C6B3929180A27668D9896958963124639443D3967BDE2D8A3684A353831404678C9D1D9DFCB7E493029304875C8F9FEE6A465180F0C24536EA2DAEBB66A3217161C333A497AC1F0EFB972422F343A4678C9D1D9DFCB7E01FE396007071890806F3B0B0000001257AEE0DEC79E582D3040392E5385BDD0DBCE9951100004409FC8D8D4D4CEBD8B2600001B5189AECAD1C8A66C2A1216679DB6BBB0B197460C081640718FADC4BBBBAE721B00014896B8C4C2B6976D200021659FB6C1BCC4AA6E0C000000418598B2BFBBBBAF883A000C5593B8C8B9BBA98B7247090009599F9FB1B6A3915F2D0216528CB5BAC3C1C6B4A1693B2E1F0E215C9397959E8F61144428372D3370C5E3DBA9653C313F3D3B4480BDC9D5DEC07C442E2A3F487AC7F4FCE5A753150B102C5C6FA2DCF4C4702B1A211E20365982C4E9DBB0682E282E344480BDC9D5DEC07C01FE3A60070718A06C643702000000145EACD3CBBF975538443B33395086BEC7C8CE96501300003C9CC7D8D8CAC5BF87250000154981BDD2D5CBA2652D131D6BADBEB6B5B3965405001C41769AAFB8BEBCA56E1E00024595B9B8B9C1A36C1B03236DA2B9B5B9B7AD6810000000528BA0B4B8BFC2AF843906045897B4C2BDB6AB84773C0700086093A8ABA89D927328040D4E8CB6BCBAB2B0B5A273462E1D11215E959F9A90885B113D35363A386BB7E5DB97553A333637384C8AC2CED7E1BD7A442B232A4C7DC9F9FBE5A74F211417195867A5D7E4BD70361C170F2939518BD1EAEAB17F3E2630324C8AC2CED7E1BD7A01FE3B60070718B072603D02000000125CB0DDCCC094482C353D373B5189C0DED7CC9A4A1100003B9DD2E5DFD6CDBD7C2500001B497FB3CDCFC9A0702D131871AEC4B5A9B18F4F160E22447B99ABB0B3B1A46C180000579AAEC3BEC09B681F0C2A76B2B6B2A7B1A4610600000F569BA3B0BBB5BAA7813900005197B9C8BCC1AF7E643404001E71A3B0ADAE9E90701F000D5199C1BFC3B9B6B58E63442C200E2B69929890968F6B0E462E35343F77BFE1D6A0533937363A3E4D77BECBE0E7C272482520425189D1FFFFE7A9501E111925576CB0E1EAAA58291F13202339588CCEF0E8AD673730353E4D77BECBE0E7C27201FE3C60070718C0766D3D100000001C6EB8D7D4BE9258433B4540486194C8CDD4C99A450C000052ADDFE1DCCEB9B67A230000165C93BCD0C7BE9E653B1D20689DB8B5B5BC954B1210234377A2B0BEC1B5A2691400004B94B4C6C6C4A1571800286DA3BFC4BFACA258050000065994A7BAB8C1BEA87C2700055398B1C0BDBCA987733604001A62A0B0B5B3A3A16C2105175999B6BDC1A8B1B8896B3E322814285D8E93969B8B620A48393A3C3B75CEEBD99C563D3E3E3941498EC5CDE2EACC784128263D4886D5FFFFE79C5616150E2A6065A6E3EBBA692C1C151F233D5E91C9E4E2A0603733373B498EC5CDE2EACC7801FE3D60070718D06B5A360D0000000E68B8D7D3C1944534363D3D455B8ABBDEDBC2954409000251A3D1D9D5D1C2B37C1D0000174C85BECFCEC5A76C390A1C74ACB2B9ACB3933F1710225287A1AEB4B8BFA8621200004F98B7C6BEBE9B6017001F6FACC6C9C2BA9F5B000000005997A1A5BAB7BEB67B2F0008589EB6C1BDBCA389642B00001F7097ADB4B19C936621031E5D96BDBFC1B5B7AD9471473C1D132366979B9B958557004E424947507EC7F9E39862413C38444C5290CDDDEBF6D073452D373B6393D3FBFFE69E451B16131D5564A5D5E2B2632F1B1F1A223D5F8CC4E9DAAA68423932315290CDDDEBF6D07301FE3E60070718E06F5B32000000001863BBE0DFD194603A413E3644628CBDD4D8CA883E0E00034FACD8DBDBD3C9B6801C000026659CB0C9CBC3A474360D19699EAFBBB0AA874712192A44819EADB1B1BBAF600F00005FA2BFCFC4C28F561300256CA7BEBEBDB9A15D0800000B598F9CB0BAB6C1AA7B290000579DB6B8BEC2AA80592F000019619EB2BABAAE9D692405205C9EB8C2BBB9B99E80654937201122618D9C958D835802393033363D73D0EDD1894E3C302A39435793CCD8EBF1C77435272C3F588CD2FFFFE09849150D0C2B726AAFDCE7AC5E2E1A0F162F47648AC9EEE7A95B3732352E5793CCD8EBF1C77401FE3F60070718F06E663413000000186CBADCD4C0964C373C3C364B688FC9DAE0CB8D3707000852B2DADDE3D6CAB2711E00001D5D9ABBCAD1C89F64340B1D78ADB3B3AAAC9C4718172E4D7E96B1B3B0B89F640B0003589CB8BBBBB6955B14002C6FACB7C7B8ACA1540000000C649695A3B1BAB6AC802A000B5BA4B3BFC0B5AC846B3003002275A0B0B4ACA19D6A1C04216C99B8C1C7BFB6A9855F523223182C609B9C9597915C0347304B394582D5F1DD9556323D3E373E6191CEDCF0EEBF723B2A2133549EE0FFFEE49845140815205D68BCE3E1A45A281D0E1B274D6D93D0E1E5A861343839396191CEDCF0EEBF7201FE40600707180077633C090000002B71B7E7E0C892593C3A40404964A0D2DADFCD933A03000853A8D7DFDAD0C5B97218000025649BC0CCD4D09B73400D1C639EB9AEB2A59140171C2B5188B0BAB1ACB19A580F00076098BBC0BFB488510D032D75AACABAAEB2A0510200001067A3A697A9C2C3AE722700095298ADBEC5BEA36F552100002073AAB3BCB8AB8D6821012764A1BBB8B5B5BCAD7D67513B1C0F2C5F8FA0A099895400494C48444586E4F8DB9356393D39404C5C9BD8E2F0F3C56B352C33435CA6D9FFFFEA9543131219276761B2DBE3AF5B25130F202C457397C6E1DBA660382C29355C9BD8E2F0F3C56B01FE4160070718107A62360700000A2D73B3E6E1CF97563B3F4835466098C6DBE8D3913800000855ADDCDBD2CFC9B16B2000002B70A7C2C9CDBD987336151F73AAB1BCA9AA873E1B1D2A5687A1AEB7B2BD9D5201000B58A0BFC3C8AC7D4903003985BDC8C1ADB39D4E040000136A9EA8A4B1BBB2A36D2102075098BACAC0B7A77A5B1F00002373A8BCB7B5A998671B09276BABC7BAB7B3BAAE8763443F2C1F23628A9E96967F480041313240438CDBEDD7875241363C3B415A98D3D7ECE6BE704A292239539ADCFFFDDE9442160A1A296666BFEAE9AD592515151D28467096C3E6D99E563A2F343B5A98D3D7ECE6BE7001FE4260070718206F5D3606000009276CC1F1E7D49E523F45493B476B9CC7D9D6D0833500000D63BDD2DED8E0D3B9711900002368A4C3CACABC9A763D081C68A3B8B4B6B389431D1D385C8A9DA9A4A7B8955207000A5FA3C4CDC5B3823F09072D7BB4C1C0B7B59647000000105D94929EABADC3A9762902125398B5BBBDB79F6F50280000357FACB8B9B1A8925412002268B2C4BFC1BBBCB28257503D1F17296395929090825008473C4A4B4D94D7F0CB93563F3F3B3E4358A3DDE9F1F1BB733B2633375FA1E0FFFFE792480E0609276D6DC8ECE0A759280D111C34496C94C1E3D39F5E38282C2E58A3DDE9F1F1BB7301FE4360070718307853281000000E2E74C5ECECCF8C4F3D3434375366A1CCD3DED8832F00000D52B1E2E2E0D8C4B26D1D00002874A4B7BFD3C2A683431D22659EBAB7ABAE8B4419192B4D8BA0B1A7ADAD944F0000146BB0B7BAC0B7803D00003486B6BEBCBEB59F4F0000001C77A1A2A0AEB9B1A3712100055A99B8C3C0B7A3704C1900002B79A8B7B9BDB1A3571805256EA1BEC0C2B9B9A4825E4A3F3016336895A19D9A7E45003A3639424E93DCE8CF864C433F3B42435BA7DEE6F2F3BF6D3219243668ABE2FFFFE39439110E10267068BBEBE3A34F1F191E293D4B6F93BCD5C79155333333395BA7DEE6F2F3BF6D01FE4460070718407C61361D0300163D80BFECECCE9A4A4442443D5C7D9DD6E0E1D98C2D00001064C0E9DED5D5C7B2671700002D77A3CBC5CEBB9C80441317699EB3BBAAA286441A1F275A92A4AEB1A5AE9B4C060007699DBDCAC1AE793B00003583B9C3BABCBA9E490000001477A59995B1BEBD9F6223000C579DC2C8C3C7A26F400C0000317CA4B9B0ADACA9581B0C2B7CA9B8BABAB7B9A883605249291F2E718E8F9890804200513E3F434783D2EECD7F513A3643425167A0DBF1EAF0B564392C283A6EA7E4FFFFD1873E0D0910216C64B0E9E9A251231A191E3250768BBADDD0916239322E3D67A0DBF1EAF0B56401FE4560070718507547200E0000093272BDEAF9CA8845383E353E5C74A5CEDADDCB7E2B00000468B8E0E5DBD7CAB5671E00002D78AAC4D0CDBF9B7740101C6CA2BCBAB3AC843D1118385F8EA5B3B5A5B08B4800000F65AAC2C5BFAB783001033687B7BDBBB1B3A14C0000001B73A6A199AEBBBAA66418000D64A3C3BCC6B9A2764E1100003583B1B3B1B0A395561C03317EA9BBC4C8C9BAA07D5C4E3D2D203671979794907944005A404C5953ACF1F9D5924A3B3F3E424C71ADE4F0FBF5CA6E3629324572B6EDFFFAD08342140911236566B6E3DC9746221718192F537291BEDAD78F543C2E3A3A71ADE4F0FBF5CA6E01FE4660070718607859341C020617347CC5F3F2D2924D3C463A425477A7D1E2DDCF7C2D0000025CBBD6DFD6D3C9AD631900003384A6C2C8C7BE9B7740101C62A7B3B8A7A08137202E3D609AA7AEA9A7AD8D3F00000664A6B7C1C2B8723000083F8CB0C1BAB1B68E400000002A73A79B95AFB2B2A9712900075EA5BCC3C3C4AB6F44160000398DB7AEAFB9A6985B1B082975A9BBCCC5B5AE9D82644D49302332688F919393723D0051444B4B4D99E1EBCB884D35343A3A4A6CABDEE8EBEBBF6B35352F466AB5D7FFF8CD823E0D0D112B7166BCF3E49C4528201A1B335E859CC6DCCF9655352B373D6CABDEE8EBEBBF6B01FE47600707187071592A09010117337AC9EEEACB994F4643423A5982A7CCE0D9C7842E00001369C0D9D6D9D2BFA7651800003282AAC5C8CEBDA2824B1521679EB2B2B4AA8A451B1D366187A0AFAAAEAD8C4300000B69ABC1C2C0AF713800043892BBBEBEB1B689420000001E77B29A94ABBAB7A6651B00095896B4C1C8BBA671461100003388ADB2BFB9B0925107003082B0C0B9BCBDB4A1805857432B213A6992A2999B8446005641383D4097E2EDCB8A54474448454D6BB4E8EFF2EAB5692B2D2F4477B9F1FFFDD38534080019346E5FB4DED5A04A2C1A1219264F7C91B1DBCE8E4F3127343B6BB4E8EFF2EAB56901FE486007071880724D1D0700000C377ECAEEE4D0875246484240627BACCBE1D9C77E2300001667C0D7D6D9CFC7B5660F00003E7EB3CACDC4BE9681441B1A6F9BB1B3B7A88B3A1824396796AFB39DA2A48E3E00000A68A2BAC1B4A7662300034497B9C4C3B6A89C3F0000001E76A38991AAB1B5A45F1804105EA5B8C7CABFAA6C3A0600013C86ADB8B8B9A7935517103986B4C5BCBABAB9A1715858452B2038728E9894967943005145434849A3E5F1CE78443F3C40425072B6E7F5F5E9BA5C2A252D4478B9E1FFFDD8893110030C338265B6E8D9984C281512182E508591BCD4C688533731383E72B6E7F5F5E9BA5C01FE496007071890795A37150C0E12428DD6FDF6D186534A4A3C3F5B85A8CEDED4C1832A00000E64B7DBD8D6CFC9B2681100003E8FB7C0CBCABB99874C172073A0B3B9ACAF82301930416A949EADAEB0AA853900000761A3BCC0BFA26521000D5096B2B3C3B9B3933B0000002A7DA19590A4BBB8A25B18001164AAC3C9C0B9A064390B00044183ADB9BABCA8884B12084988AFB7BCC2B4B3A678585E492D2132698B92A19C844200484040435799DEF4CC7F513A343D464670BAEBF3FBEEBE61332A35457AB9EDFFFBD488310F000C327263C4EBEFA3581E11121F355A7E94C0D5C58847322D373670BAEBF3FBEEBE6101FE4A60070718A07C552B0E0A051F3C81C2FAEECA805A424549406485B2D7D3DFCC823101001771C3D8DAD5DBC7A8661400003E89ACB9C5CEBB9C884E1C23779BAAB1A4A4853D1731416490A1A3ADAAAE833B00000C5EA4C3C9C0A4682300074296BCBFB5B2AC8D3C0000002980A9988E9FB7B6A2671A010F5F9CBDCEBEBB9962340700053B88AEBCC6C6AE944D12043684B2CBBDC3B9B2966E60534B262434649FA0A298783400503E414C5FA8E9FFCA8445383B3C474B72C0E8FAFFF2BF6D373C2A4A81C2EEFCF0D27F300B0B193A8361BFE4CE944623140F122B5C8195C2D5C7855032242A3572C0E8FAFFF2BF6D01FE4B60070718B073532A160115253F91D2F8F7D8975849463E446687ADD6E0DED0832C0000186CC1DDECDCD3C4AF5D1200004099BCC4C8CABC8F823F0F236F9FA8B9B0A678291C2D4165929FA197A5AC81310000066CAAC4C9C1A6671D00024F9CB7C6C1B2B0912F0000002980A28C8EA4B3AE965812001169A5BCC4C7BFAA642F03000A3E8BB4B5C7BCAD9850180F438EB5BEC4BABABAA87B64503F2A29376B999DA1907938004C4446495BB4EFFBC88A4E394645445173BBE9FCFFEBB3632E222B3E75BDF3FFFDD17632040B0E327F5DBAE1D4944724161C1E31608599B8E0C786512F22314173BBE9FCFFEBB36301FE4C60070718C06F4C251007090F4793DBFAF0C78A5948463E4E6B92B7D7E1D8B870200200157CCFE5D6DFDCD0AD60100000428BB1C7C5C8B99E8F4A191D6091ACB2ACA68037242A42688EA0B5B1A9B48C2F00001974ACBACAC2A14E10000A4E93B6BCBBB4A58A3A000000398CA49994ABB5BC9F651500125AA3BABDCABDA36D330700064383AEBBB9B09E904C09105699BCC2C2B9B8B79468585A452F2D3C7292A39F987A3000524E4D4C62A8F3F7CF8543403E4447527EC0F1F4FAFABD64332D333F7FB5F2FFF2CE8025070A14338462C1E7D793472B1D13222D5E8D9DB6D8BA834928252F437EC0F1F4FAFABD6401FE4D60070718D0744B2214020E1D458FD4F9F2CA815144413C3F5A81B5CCE3DBC9813002001874BED9DBD4DBC8AE630F0000448DBACDCBBEC09C8A4A19196B93A8AEADAB7F311B31476E94A9AFAAB0A8823700000F6FA6BEC6C4A55A1200005098BFC1C5BDAF94380000002877A39487AEB3BBA25309000C58A4BFC7D4BAA7672B000010428FB7BAB4B2AB9851110C4A96BFCCC6BBB9B6906858624F2D263869879E9790743900524953576DB0F3FFCC79413B4748465180C3F4FBFFF0B85B2C222D518AC2F3FFF1C9702410121A31865FBFDBD18C3D2516171F32668291B3D6C0875131282E3680C3F4FBFFF0B85B01FE4E60070718E075421A0705041C3B93D9F3EFBF864F414336426D95B6D6DCDDCF7B2901001F79C6D9D8D7D5C7A7580A00074492BBD2CED1BC9D864C161D6892AEBAB0A47533232C436D9BABA7ACA5A478300000146C9EB5C7C396521000085AA0B7C7B5ABB38B340000003385A49082AABBBC9A5C1200165EA9C4C0CDC6A25A290000094893B6B6C9BCB6914910144891B5CDC5BDAFB48E5D565C553728496F969F9E9273280053414C5168B7FFFAC57A4E3F3D423E4E7EC5F3FEFFF7BC67322328498ECCF1FFF1CE72280C030A3B8F5EBFE7DC9A431D18141B3366919ABBD1B7774E3A2B323A7EC5F3FEFFF7BC6701FE4F60070718F0804D29110C0A295296D5FEFDC8835E4F463B4E7292B5CDD3DBCD7E2500001979CCECDDD4D4CFA660040000529DBEC8C9C8B79C894F141F6797B2B3A9A2722B22384C6499A0B3ABB3AC7C2C00000E6EA5BDB8B59B510D001063A5C1C9BAAFB3922A0000003084A88C7E98B2C0A15715001466A5C2D4C1C4A85F3200000C559CB8B8B8B1A28D48100C4293BDC9C5C3BBB3896A515C533330386D91959A97712A00574C51516AB6F9FFCA7D4C443E4544587AC5F4FCFFF9BB6830202A488ACBF1FFFACE7A310E061633895FC1E4D298442B24201E36698E8DADCCB27C53342B3A447AC5F4FCFFF9BB6801FE5060070718007E4D220B090B235396D8F3F6D0805945443D4A7B9FBFE2DEDEBE7B1B00001A77BFE4E3D6CDC8A353080000499DB8C6C4C5B49A8F55161B689CA9B0B5A871322735516E959DB2ABA2A1762C00001E73AAB8C2B498460600155FA5BFC3C1B3AE8A210000002D8BB0917DA4B7BEA35314000E61A9BCC0BFC2AD5D2100001554A0B9BBB7B3AA95420A0B5199B3C2BCC7BBB98D5151635F3832446B8E9D9D906E1F0066564F5A6DB1FFF8CE7741433E48496085C4F4FFFEFDB66F402C324A87C8F2FFF2CC762D08040B2F8C60C3E0CB813B1E20172039639092B6D2B077442A2C363D85C4F4FFFEFDB66F01FE5160070718106F4929170E15264B91D1FAEEBF8558533F3D497A9BBBD7E0E0BC741D00001C7CC8D9D8DFE1D9A753080000519BBAD0CDCBBC998A5218246AA3B2B3ACA2753626344A6E8CA7B0A3A9B27D2600001369A6BBC7BB974509001066AEBBC8B5B3B57E2400000031849F877FA6C0C49A4A00001063AAC7C9CABBAA5B250000095593BCBDB4B3AF8D480E1655A4B6BEBBB5B9B5905D5C635B332F3C6D989799896A1E005A4C555E6CB8F4F0C1754F4437474E588AD3F3FFFFF9B762282B315893CAF1FFFDCC6F240C10133B9055C4EBCF854026251923376D8A8EAFC4A377442D2A36398AD3F3FFFFF9B76201FE5260070718207A592E160C0E25579CE1F1F3C7855F4F4C374C75A5BAD6E4DEC3792501001E81CFDAD3D1D7CCA45102000458A3BAC9CBC7B4938C4F211D6F93B3AEAA996F2824314A6E9AAAAAAFA8A97A2E00001471A8C0D0C9994900001463ABC8C6C4AAAD8E30000000388EA78276A1B2C5A04E1100105FAEC0C2C6BFA8551C01000D57A1B3BDB9B7AE8E430B12569CB8C2C2CCC6B582574F614B2B2D3D70909A998C6B27005351574C6ABAFCF7CD834D3E3C444D5B89CDF5FFFFEDB4572C27294A92CAF1FEFBCA6A240C0D0E3C8B55C7EBCF913A2719121241748B91B1D3C571412C2F363C89CDF5FFFFEDB45701FE5360070718306E42230D0C10295290DFFFF8C081584742445877A1C7D3DED9C2722100002186CFDDD4D1D7CBAF530100085BA1BAC1C1CDB39F87471A2C789AA5ACA79663352B304B6F979FB3AAABA8712800001169AAC4C6C3A24300001765A6BCBEBDBAB68427000000358EAA80769EBCC19E520E00195E9EC4CDCDC2A25F22000018559EB8BEBCB4AD95440F175693B8C4BEBABBB78555575B533941466E9198A0986D2300594B524E62C5FFF9C5804D313B464A5B8FDAFDFDFFF7BD5928222E5690CFF5FFF4C26B250D0609408C5AC3DEC8834328251C2242769590ACC8B17743372C2E3B8FDAFDFDFFF7BD5901FE5460070718407F51291B0E172F57A5E6FCF7CE8A5B504C4C5481A0BBD7E7DABD6C1B0000208BC7DDD7CCD4BDA65205000A61A0C2C9C5C1BA958A4E1C1B6AA8B5B2ABA1722F293B4F7394A4B2A7A4AF81220000106EA9C0CFC38F3900000E64A8C2BDC4B8B88126000000468DAD8B759DB8B8924505001464A7BCC3CBBD9E541D00001756A6C1C3BEBBA98F40062165A8B7C2BBBFC0B88A61586159382D4B7E989194816E27006058555774D0FCFEC6854B3A4350535892E0FFFFFFF4BA5C28232B5398D7FBFFF1C5631B1210122C8555CAE8D5843D2B231A1F33688B8DB0D2B16F442B2C323C92E0FFFFFFF4BA5C01FE5560070718506C44190B101B325B99DEF4F6CA89564B403B4B7BA2C3DCDDDDBC6D1F00001B84C3E3D8D9D2C6A85500000B5DA4BDD1C8CBBD95904C1F22679AA8B5A69864271B2D4F7290A4AFAAA2A3752000001576B0B8C7BD993900001767B2BFBBBFB4AA7E210000004497AA8A859FBBBC9F510B000D65B2C4CFCBC1A75B1D00001063A0B5B0B9B0B3933A161B5499B8BEC2C0BEB57B54576C573831467092948C906E1A005651555975C5FEEFBF7946464448475A9AD7F9FFFFF3AD59292A275697DEFFFFF5BD66260900003E965AC5EFD086421D1A242D3B7A8483AAC9B2724F2F373A3B9AD7F9FFFFF3AD5901FE5660070718607A43250F1C1F3161ADE8FFFACB83604D4C425288A9C1D6DBD6BD6F2200002484CEDBDDDCD5D7A7500000015EA0BCCBCFC4AC938D5115216F99AAA9B09A6C31293E476D94A8AAA8AEA0711E00001C75B3C4CCC38E3700001972AFC2BFB5ABB384280000004597A9827CA2B6B18F4905000F63A3BEC7CCBEA5591100001E6DA9BDB2BCBFAF9840081662A9C0C8C0BABDAF80554E655A37334472959FA2946F1C0051484F5168BDFFF5C4774F383E484B5893DBFFFFFEEDAD5328292F4C95D1FFFFEBC2662411070C3D9455CADFCE893D2023191838689584AACAC2774930272F3993DBFFFFFEEDAD5301FE576007071870723A1B1710192D62AEEAFEEDBD7B4E5440394786A6C7D6E4DEBF712100002B8CC9D7D3D0CAC2A4530100105FA5C6CFC3C5B99A994F1C266B93A2B1A793682B293D57709EA5A6ABA7A4761800001670B1C1C3C2882D00001B71B6BCC4C5BBB37E250000004395B085779EBAB6914A08001664A1BCD1D2CBA5551600001A5CA0B8B5C1B9A98342101461B0BDC6BCBCB6AE8A5C656A57303B52819F99979367180050505C5B73C6FFFBC9734E4B4D49515A98E8FFFFFFF0AB592A2C2F52A0D8FEFFEEC86721000611379B58CBE5D2833A211E1E2C3F70958EA9C7B26E432B30384298E8FFFFFFF0AB5901FE5860070718807240231F15173659ABEBFFFCB87F585749354D87AEC3D1D8E3BF64180000228DCFD9D0D9D1C2A74406000869A7C3CBC8C4B79E8E4F111F699EABA4AA9665302C4857749AADAAA8A49F6E1500001B72ABB8C7C8892A01001372B5CFC6C6B8AE7C170000004696AA7E6C94B4B7904605001264A7C7CCC3C3AA53140000256CA3BBBFBBBBAE87380D1663A3BEC3BBBABFB9885653715D3D354D74938C969C6D21005D4F4C5A70C1FFEFBD744A373B505C6099D9FAFFFFFDBD5C2F353762A3DBFFFEEDBF60180D080A2E9850C0E3CD7B391A1E16213F78948DB3CCAF73452E32323899D9FAFFFFFDBD5C01FE59600707189072451E140D142C5C9BE9FFF2BD7F65534D39568BB1C6C9D8DAB8631600002282C7DAD4CFD7CBA84B00000D61AFCCC2C7C0B4A08D59191E6A99AAAFAE99622928445B7792A9B7A9A69B711200001A76ADC5C9BD882600001576B3C0C5C3B6A07323000000499BAE837093B5CA94440800196FADBDD4D0C3A1571300002868AEBEBDC3B4A87C350B1866B2C4C5BAB3C0B683535D7449403A4D78979E978A6218004A4C505471C7FFFFBC704A43413B525D9FE3FFFFFFF4BB5C302B3A599ED9FBFFF8C4631B0202093C8C49B9E5C87E3B201F1F1C3E748F82A8CFBC6D3B2B1938409FE3FFFFFFF4BB5C01FE5A60070718A0734026221A264167AFECFFEEC57A5F5947344E8AB3D0E3DCD4C26D1E00002785C3D7D2D1D3CCAC4904001361A4C1CDD1C9B198944F22207298B1B2A5965C26273D5F6D92A7AEA09F9C751500001C7AB9CDC8BC831F00001A76B0C7C2B8B8A87A17000000459DAC8473A2B1BE8E3C08001068AAC7CCC3C5AF5A1400001464AFC3BABFC0B18035041D5EA4CBC2BEC2BBAE734D5D6D5F3F4854869A9898935A140063565E5F76C8FFF7B777583F464B5066A8E9FFFFFFF7B2582F2C3456A0DFF6FFF5C5632000000D469552CAE5C474371B14202140718E83ABCABE764C362F303DA8E9FFFFFFF7B25801FE5B60070718B077442C2E26233262B2EFFFFFC1835C553B355A9BB5D2DCDBDDBE6B1400002485C4D7D3DDD5C8A05100001A71A5B7C9CCCDB49B9151141F70A3B0AA9D91642B2545556C98A7B1A2A89A71170000187DBDC1C7C4852100001E75B9CBC5BEADAC6F110000004A97A27B76A0BDBF903F05001C60A9C4C5CAC69F480500002C73ABBCC0BEC5AE7D32052A70B1C0C4BFC3C3AB7553657D5A3B3B5679969B977D560E005B5B606A81CEFFF8B977534E54554F5EA4F4FFFFFEF3B25B313B415BA2E4FAFFECB85C2500040D3AA363CBE6C375361D1B1C24417A9B85A1C5AF6842292D364AA4F4FFFFFEF3B25B01FE5C60070718C0814C322826243763B3EDFFF7B4775E504D405690B5D3D8DACDB8612100003090D6E3C9D4CFBF9D460500166CB4C0C7C0C8B4A08A4E1D266AA2B1B0A98F58282547587E9CAA9E9FABA4671C00001973ADC2CCC0842100002585B6C5C7BEB19F721600000250A3AE80709EB4BB96420C001667B2C0C3C2BDA2500C00002373B4BEC9B7B6AC7A3408266DBCC5C3B9C4C1B2755360735A3B3D567B8A9198885909005A59565579CBFEFFC0754540484F5569A2E4FFFFFFF1A5563431405EACD7F7FCE5B0581B0501113C9C55C0E6C57A3A1D0D1823367A8F80A6D1B0674124343544A2E4FFFFFFF1A55601FE5D60070718D06736151E1B253160B0E7FEF7B8785C4E40384C84BBD6D6E7DFB7661400002F85CAE0CED0D8C9A24305001A6BAAC2D2CBC1A99597561C245D93A1ACA69C58252648557F98A2B3B3A39F651200002178AEC2C6B77E1F00002186B7C8CCBAA8AC751000000450949F7A6C8CB4BD8D3E00001265ADC5D0C4B9A0510900082F78B3CACCB9B6A6792D052879B2C9C6C4B1BAB0824F6171563F49557F949F938D5F0D005A5B606583CAFFF8BD775449454C4A69A1E7FFFFFFECAF54262E3C63A6DBF8FFE7BE5C1A060B0E40A756C7DEC47B3C221C141B45799380ACC8AF623B282F343CA1E7FFFFFFECAF5401FE5E60070718E07A4E261B1C253669B7F3FCF3B7785F5E533C5A9EBAD5D9DDD7B659120000288AD1DBC7C4D6C79B5309001671A5C2CFC4BFB8988A572D266BA3AFAAA18F4F262550597FA39DA1A8A9A25E1300001E7CA8B8C8B77F1E0000318AC9C4C9BAAEA76A0C0000024FA6A47973A5BAB48D3803002161ABC4CECFC4A1530C00003173ABBFC1B9C2A9762C102774A8BAC9BDBFBFAF774962795B3E4F6586909F8D864C02006B51585F79D3FFFCBF6F4D414C50546DAAEDFFFFFFF5A5512C343A65A4D9FFFFE9B14F16030C10449850CBE3C3803B221E1C1E457E917D9FBEAC5E3D2D32393EAAEDFFFFFFF5A55101FE5F60070718F07446221D1D273A76B6E5FEF3B275625F58415991BDD4DDDCC9AF5A1200002D8DD0DED2CCCDC79C4900002071A3CACDBFB9AC97895A272A6C98B1B1A78F5D2E37545A7F9CA7A6A4A190620E00001B82B7C8CCBB821B00001F8CB7CCCFBEADA0650E0000054C9BA875648EB1BD8A3605001E64ADC8D0CECCA6490400003480B4C4B8BDAFA678320E297DAFC0C0BFBBC1AC764E6C7A5D484B56779594978F520C005D5A4E547BD5FFFDC46D4548434A536BB5F4FFFFFFEEA65731323A68AAE1FCFFE5BF5A13010013409753C6E1C27F34231B1F23457C8E78A7C9A9623D2830393CB5F4FFFFFFEEA65701FE606007071800783D191B2126456CC7F4FFECB3725D5C4B385A9EBEC4D5DED7AD5F1800023A95D2DBCECECBCAA1470000156FAFC7D1C4C0AB98844A232B68A0ADB7A89452232B5B5A8095A6A9ABAF95560500002584ACB9C8B8751D00003993BCD3C2B9B7AC77100000015CA6A66F6C9DBEBC852D05021A69AED2CACFC597440000003585B8C1C4C0BDA86C240B237CB4C4BFBBBFC3B06F4C61765F424965868E8D8F805809006057595A7CD2FFFCAF6C44363E494C68ABEFFFFFFFE7AB47222E3966B4EAFFFFDFB3561900050A469F52C7E3BB65291C1F202D4E80928CA5C5A9663B292C2D41ABEFFFFFFFE7AB4701FE6160070718106637202422283B73C1FBFFF4B5765F67503E6499C3DDE1DED5AA5A1300003B9DCECCC2C7D7CDA34B00002B77B0C5CBC2BDA28F8D5B25387EA1AFACAF90542A2B4D618099A7A49D9E9B540200002379AFBCCBBD7D2300002F83BEC9C5BBB7A7680E00000753A5A66D5F8DBEBA883503022374AFC3D4C9C79B470200073F89B5C1CCC5C2AC681C0A2C7DAEBABFBFBEC6B564486676573F4B5F7A9099908D450000736C606A84DFFFFCAB6B4F414E545973BEFBFFFFFFF1A64E2D344569BCE6F5FFEDAF4E1B0002103BA24EC4DEBB632F1C251A204A8A8F7BA9C5B4664335353541BEFBFFFFFFF1A64E01FE62600707182072452A262430447ACAFFFFF1AE746560474163A0C4D9E4D5D0AD56020007379DD5D6C6C9D1CC9C3400001D83BCC7CDCCC5B094885B1F2A739AA4A9A884431F34535A8898AAB6B2A696560600002076ABC1C7B27A1100002E91BFC4C4B8B29F580000000A65ACAB7B6F8AB1BF873300001866B0C1D2CDBFA2490000043C8FBAC6C4BFB8A46A210D3087B8C3C4B9B9BFA5634B6C7F5C4D5B617C88938F874D0000585655587ACEFFFAB96A4F4C49474876C0FCFFFFFFEDA85B2B364067ABE0FDFBE7B14D1B02111049A14EC2DBB86C2D192021234E878F80A0C2AB6A402F323B44C0FCFFFFFFEDA85B01FE63600707183079402223242F457AC1FCFFF3B27B62674C445B9DCED5DBD7CCA4480900063A99D3D7CDD2D1BE953B0000227FC2D2C9C5C0AD90824619277C94A6B1A3904F2437505C819BAAAFB1AF9E55000000247BACBDC9BE760E00003893BECBC3B9A39B600E0000035FA0AE796F9DB2C58C2C00062167B0BFC9C9B999460000084690B9CAD1C7B79D62230B3B88B6C2BBB8BCBCA2664F6576604157668591938D843C0000675A57628DCFFFEDAE624C42454F4A72BFFAFFFFFFDFA853342F406EBBE5FAFFE2A8501902000C53A146C3DEB46B2C222523204A87907DA5C6A55F39222B323BBFFAFFFFFFDFA85301FE646007071840703B25242B2B4E76C9F1FBF3A6706367464161A8C7D4DFDAD7AF561100013A94D4D2BFD0D7C5933C00002C82B5CCC4CAC2A5968A5C24356A99ACB4AA904C2531475880A3A1A8A1AE974C0300002281B5BDC1AF6B1000003F99C9D6C2BDB09A5D0A0000095EA4A66F6297B3BA81310000216AADC8DBD6C5983B00000F499AC2CBC0BBB79B5319013589C1CBBCBEBDBEA26E4A6588604F626D879491917A45000065615F6589D9FFEBAC625F4842495576C1F0FFFFFFE7A1402C374574C0F3FFFFE1A4471600030D4BA64EC7DFB05F2B1F27252B4C8F8A78A9CEAA503C2D34333CC1F0FFFFFFE7A14001FE6560070718507952372A2C32417ED5FFFFF6A56B595D564769AED4DFD8D8CEA8540900003F9AD2D6C3CDD4C9963F00003178B2C6CDC2BFAC8F7F4D1E2D76A3ABAFA888432B3C5A688A94A9AEA49F8F480000002A86B0C3C9B770110000389BD0CEC6B8B19B5D040000075FAAA66C6497B7BE852800012A69A5BFC5CEC5954400000A51A1BDD4C0C2B09D5C1E154189B5C1BBB7B3BC9C60426E7F654A62728D9897907A440000645D5A5B8CDBFFF6AD60403D4E4F4C74BFF9FFFFFFE59C4F2F363E73C3EAF7FFE2984B14010A1148AC5FC9DFB0592B171E1823578F9582A0C29B5F3830353B47BFF9FFFFFFE59C4F01FE6660070718607A4F2E312E3A558CD8FFFFEDAE6F6A6A534670AACFD9D7DBD2A1450800003FA0DADBBDCAD5C7933900003988BBC9BDC6C7A28B804A1F2F7EA4B3AAA37F4F24395562859FAFACABA48D490000002E81ADC4CEBA6D0500003993CAD6CAC0AC9C5E0300000E60A9A7726991B7B0772D05002270AFCAD5D2C38D3700000F53AEBCC6CBC0B18C4C0E093D98BBCDC3BDB3BAA0614A6A8061456770828C9491813700006F68616D96DFFFFEB66F4D504B4D5985D0FFFFFFFFE19E50353A5280BEE4FBF5D9A0480901001255B452C7D7AB561B1A29213155968A75A0C5AE58312D332C3CD0FFFFFFFFE19E5001FE6760070718707541302F3236548EDBFFFFFBA86E68634B4975B7D8E6E1DCC99B4301001648A8DBDAC1C4C7C2903300002D8DB7CABBC8B7AA8D84481E367DA9B9AAA07B3C223455638EA9AFB0A2AB883F0000002B88BDC4D0B1670700004B9ECCCAC7BCB09651000000106EAAA9706095BFBF761F00002B6FACC1CAD1C295360000165B9DC0CCBBBCB8985711104CA1C5BBC7C0C0BE97554B797F6144576E818F8A95823800005B565F648ED7FFEDA361504A3E53587ECAFFFFFFFFDC8F3E30414B82CAEAFEF8D9A1441000001658AF4BC4D4995318151E16314F878C78ABD3994E3A2F272D40CAFFFFFFFFDC8F3E01FE68600707188076412B2B29335693E1FCFFEAAD736768474371BAE3DFDDD8CB99440400054099D0D6C5CEDFCF8E3100003C8BB9C9D4CCC19F897E44293B7EA7B0B1AB87402642576981999FA49AA08135000000288EB9C1CFB9700100004DA7C6CBC2B9B49B5E0000000A64AAA5756694B9B7792200012775B9C3D1C8B38A3A0000185BA9CBC5C1B7B6A04B0C074892C0CEC5C0BBBFA0543B69905D546E7788939294773800006C5B646C9DEAFFF1A365584947555D89D6FFFFFFFFD99844343E4E84C2EFFEFFE099440800001B54B544C2D9A44A2A1E201F29578B84639DC5A25A392C282B3CD6FFFFFFFFD9984401FE69600707189074573E3A3942579FEAFFFFF5AA716663544B71B0D6DFE4DECD9D4C0A001046A3DCDAC2C9D5B58D3400003583BEC6CEC4C9A88184552439859FABACA279351739636E8D9AA2A9A9AD8A2F0000002E81A7C3CBB2660000005AA8D2CECAB5AF99510000001E72B2AA75749DBEBF742100072D71B4D2CFCBB38B3B000025599CC0CBC2B6AA884003164F99BFBCB9BFC1BC9F5A4B74865C52697C8699948A722F00006F6673779CF1FFF8A869525153525A8DE0FFFFFFFFE09B493C435187C7F1FAEFD79D430B00091C5FB957C6CF9C4A171924292C628A85759AC19E54372B273A3FE0FFFFFFFFE09B4901FE6A60070718A074412A2C2E415C8CEAFFFFEE9C717066584A7BBFDBE8E2D7CE833C0900194DAACBD3BCBDC9C18C2A000048A1CACAC6C8B9A3897742284187ACB8AF95743B233B56638BA9AFAFB0A9842E0000002F87B9BFC1AB620000005AAFD7D0C5C1BD9B450000000D68B3AB81739DB5A9601300022973A8CCD3CAB7892A0000286BB5D1C6BBB3A181400B0E52A8C4CDC0BAC2C19E5B52767E53566F8085918B876E2900006A67686D9DE5FFE59A665B4C50556195DDFFFFFFFBCF84463C495590C7ECF7F2D398440500010A5FB850C2C493452D11151C30628D836DA5C2A15A40322A364EDDFFFFFFFBCF844601FE6B60070718B0764D313533416BA6E6FFFFEA936A676754517CB6D5E1E0D4C58B3A07011656A4D8CEB6BECCBC8328000A58A5C1CBD5CFBB9D827F4B243F789EAAB1A4662C1F3C596C9CAEAAB6B1AF802C0000003E89B6BCC9AA610100015BA8CBC7C8B8AB9141000000106BABAC7F659BB8B6691F000C357AB0CBCACCC28C2D00002671AAC2CCC0B8AC883A0A135A9DBFC6C5C5B9B1925A4F718C625E7E81909091926C1D000057545A6797E2FFEC956656424C4E6588E4FFFFFFFBCC793938455E9AD5F6FAE5C79739060000155DB24DBFC492511615271F24568F8374A8CCA3633D2B35393EE4FFFFFFFBCC793901FE6C60070718C07E583B3F484E64A8F5FFFFE6906A6C67545578C0E2E6F0E4C683290A00135FB4D8CBB0C5D9BD792700024AA6C9D6CDD1C49F7F6D3E294589A4AAA2915F2E22455B7397AAB0B7B79F73290000003592BDC1C0AF570000055AB2D2CFB2B4B6993B0000001876B2AA7E789EADAE621300012F74ABCED2C7B6833500002B7FAFC8BEBBBEB4843D091862A6C8C4B3B2BBB39855456C80575B7A818C8E948A702100006466646C95F0FFF6A265534751526693E4FFFFFFF0C97F3A383F5BA0D1F2ECEED0923F0600071158BC46BEBF8E44181724213473988C73A1C3A157322A2E3745E4FFFFFFF0C97F3A01FE6D60070718D06D453334344271AEEFFFFFE58E666765535C84BCE5E3DCD9B7802B01001D60B6DAD7BFC7D2BD7724000B529DC2D2D4C7C2917F6F40254198AEA9B3A2672D1B40546D92A4ACB1A0A77A290000004595B5C2C6B35900000562AFD3CFBFBEB49238000000217DAEA98178A0BAB46F1E00063077AEC7C9BEAA7B21000B3F7FB2C4CBB6AAAB742E08166AB1C7BABDADB4BB91594981855B55737E82898384691B000065676C7AABF7FFF1935F5558525461A7EDFFFFFFEAC27F3D344B65A9E0F8FEF1BF8934040000136BBB4EC0BE863D1218212B316793726DA6C29B5A37303E3C47EDFFFFFFEAC27F3D01FE6E60070718E068473233354675B3F4FFFFDA83696466585786CAF0EBDCD3C07B2F00001C5CB5E7DAB5BDCEBE7C26000E57A9C7CECFC9BE8D745F312057A0A7ABB08E5A2E234859738FADABB5A79C6E21000005509CBDBABDA1510200036EADC6D5BEC1B38F300000002373AEA38E7CA8BEA76114000D3C7AAAC6D5CDB27C230005368AB6C6C2BAAB9E6C2500105FAACAC4BEBCB8BD9858507D8458547A87978E90895E0E000071696564A7FEFFF1A66C5E52564961AEF6FFFFFFEEC37B35444E6CA9DBF0F3EABF7F320000001970C84FC2BF863419202321306B99867C9FBDA0563A31303540F6FFFFFFEEC37B3501FE6F60070718F075503947485075BCFEFFFFDE85676C67514D80C6E0DEDDDEBA73280000226AC4D9CCBBC7CFC57328051865A9D1D3C7C3B189686632295696B7ABAE8E521E1D47576987A9B1B4B2AB6C140000044F91B9BCCBAB4B00000975C4DCD0BFBBB3872A000000176EBBB6847FA4CBAE560F00114283B6C1C6BFAA701F0007479EC2C9BCB3B0A0621E002366ACCCBFC4B3AFB1855F527C7A526587898F8F89875C040000626F6567A2F2FFE8A2635B56475672AEF7FFFFFFE8B76D383B5271C0EDF7F6ECC276280600032471BE4AB7B8722A0F1A1E1C356F917B7EACBC945D3E3D333C41F7FFFFFFE8B76D3801FE70600707180073593D44465485C9FFFFFFDA82635E6E5C5B8BCCEEECE0D2BA6E2C07032369CAE5D6BAC5D0B46723002169B1C9CFCBD1C38A64522D295F9DBABEB29152242442517391B1B4B7B0A8671E0000064C91B8C9C7A74400001678BDD6D0BEB8A78235000000296DAFAD9A8BA2C2A34800000E4591B5BDCCC7AB721D0013488BBBD0C8BFB090530D072770B2C0C2BDB1B3B79151567F78505E8287869789825008000072645E75B1FDFFE98A67635B565B6DB9FFFFFFFFE3AA5A383A4C78B5E9FBF6EEC37F280000052175C74AB2AB762D191817202E75928680A5BC8D4D3F3C3F3B48FFFFFFFFE3AA5A3801FE7160070718106B453B37415580C3FFFFFFD97D5961675E6E97CCE5EAE1D4B56D280106266DC1DCD5B4C5D3B2601B001B6EB0C7CFD1CDBB85534D282966A2B3BDB7884A1E2649537294AAADB1ACA46412000008559BBBBCC7A3450000197CB6D3D2BCBDB58928000000237DB7B19A90B4BDA845000009428DABC3CABFA9661300185697BEC5C3BEA989541C002277B4CBCBC3B2B4B59F594A7A7D566283909F8D92814E00000076666A7EB9FFFFE68D695D54555378C9FFFFFFFFD6A05B35405280C7F5FBEFDABC752A000000287EC649B7B26529191320233277998178ACB58E5A3B3A3A3F50FFFFFFFFD6A05B3501FE726007071820765A433B445681CAFFFFFFD17C5B5F6462759FD3E7E0EDCFB45C1D0000317BD0E5E4CBD2D3B46A12001F79BACED4CDCCBB835A3D212A69A7B7B0AE843F1A29424F7592ACC2BAB89E5B0D00001055A7C4C7C4A04600001D7DBCD1CCC4C4B383200000002973B2B5A495ABAF914302000C4590B7CBCEBAA0671D001569A3BDC3B8B8AF884D0E00277FBED2C8BDB8B0AB8E585582755F6F888E96988E703B000000767E6F7AC1FFFFF2956D6E514F5974CEFFFFFFFFD48F502B3D638CC7E9FAF2DEBB6A1E0300023B93D350B5A2652E19181E284A79917674A4AE95583843453A58FFFFFFFFD48F502B01FE7360070718307464504648638FDEFFFFFFD3765261676E779ED9F3EBDCD0A051160011307EC9E7D5C5D0D3AD6016062E87BDD6CFCBBCB4805438142C72A0B9C1AB6D371928435372A5BFC0B9B6A254010000286CAABEC6C0913000002986BDD0D9C9C3B280140000002B79ACBBAA91B1BA963900000F548FADBFCDC5A35B13031E74ADC4C2C2AF9B764008003389ABC2C0BCB8BBB791585B8281556B8D8A8D8C86743900000070696475BFFFFFE3815B57504D5C89D8FFFFFFF6C588533E394D96D4EEF8F2E1AF6C210700054095CF4AAB9B5F21130E15203C83947B82AEBC8347384441485AFFFFFFF6C588533E01FE7460070718407E504A4D4E6390D4FFFFFFCE75535B637084ABE1E9ECE1D7A4531500003585D0E6DACBD5D4A65A0401308EC5DAD7CEC5AF643E321C2A79B4B9BFBA792F17204B5A84A1BBB3BBC293480000001F70ABC0C5CB912F00002894C0D5C6C3C1AD75220000003282B0AFA1A1AEBE933700001B4C8AAAB8C1C3A15B18002178ADCDC3BFBD9F833003003B8CB3C5BCBCA7A5A48A5E55867257698D8F968F8C783800000076787482C7FFFFE58D5A5950556286D7FFFFFFF3BD774B34435C93CFF5FEEAD4A6641C0001094AA1D84FB19A512314171A26447E8E818EB3B07C4C3B45424063FFFFFFF3BD774B3401FE75600707185070525450476597E2FFFFFFCD734F56686885ADE0E3E9E4D199440900163A8EDAE3E8D8E1C89E4A08093D8DC3D8D2CCC8A55E3C24152E82B4B9BFAE78351A21404F7BADBABDBDBF963E0000003183B8B3B9BD813000003194D3D6D4C5B7B079190000002F85B7B8ADA8B9C2973B0000155093B3BFC9BD924B08012B82B0C3BDC0AAA16C3300003C8FC0C3C3B5ABB1B595535E837D5B6A8A8D938C8370300000007A808091D0FFFFE4945C635057578CDDFFFFFFF0B9734A3342619ED3F6FFFDDAA657170000084AACD140AB9149180C1423233E849A8784A9A682493A3A4E496FFFFFFFF0B9734A3301FE7660070718606E5D4D4D4F679DE2FFFFFFB9695057717C97BFDCE7EEE9CA92360D071B4A94DAE9DED6D0CF94400706379DC5DBCFCAC3A468311D113887B8BBB3A77137272E3A547CAAC1CAC9B286360000002B87B4BCC1C3882900003998CFE1D4C0B7B173130000002E81B7C3ACAEB4AE8B3000021A4B8DACC3C5BC9E510E002B7FB3C7CAB6B4995F2300003D88B5C4B6C6B7B8B388545A85795366888B8F88816E2400000874727A8BDBFFFFDE895F504C536191DAFFFFFFE9A76C392B365AA5E2FFFFF7E49E571103001357B0D94EA6904C16130512294B94987D90A29F6D514053554F67FFFFFFE9A76C392B01FE776007071870785F52505E71A0E6FFFFFFBC69535A5E7E9FC1E4E6DEDFD3933C0A000E4495E2EDEADCE4D490300005439DC3D1C9C9C6A25529190A398DB7BAC2AE7938222E414A769DB8C7C4B78B3A0000002E7DB4C4C0C182240000419FD2D9D3C3B8AE70150000003781B6C2B8ACB9B6882600001B5890B5C9C3B891480609438FC0C4C9C3B68E521F00094FA2BFCDBFBBABB4AC7B4B5C867D557591989792876C25000012767A8797F4FFFFD5885852584E6190E7FFFFFFE4A96C40313A519DDBFFF9F1D0A05B200000145FBBD34AA7844316080E1C264F87927883A89B704B45514D4975FFFFFFE4A96C403101FE7860070718807569575F5E77A7F6FFFFFFB76A5653678FAEC7EAE4DAE7C78334060B154FA3E3EFE6D8D4C08931051453A4D0CDD0CABF9D4F2108103894C8CAC5B973321F2A3A46799CBEBFC3B386230000003687BBC9C1BD701E000047A3D4D8DBC1C1B06E130000014880B2BFB9B4C0AF7A260000295897AEC1C4BB8E40110D4491C1C9C3B8A88C4C0700004E9FBCCEC3C2B4AEA4724A557B79617F98A2A09684682000001072697592E1FFFFD08A61544F545797EAFFFFFFE3A15A36334058A4E7FFFFEDD59E4C160005206EC4E0479D873D192018182A4B85847989A7946F4D49505E4D7EFFFFFFE3A15A363301FE79600707189071666A61647BB4FEFFFFFFB2624B507298BDE2EADCD9E0C4772F01001857ACEBFCE7DEE2CE7928001753ABCCCDCBCCC597491B000A499BBCC1BBB47C3D2E373D497EA8C0BBD0C684240000004187B9C1C5BC691B000048A6CFD3C8C0C6B5690900000B478BB5BEBFB4B1A6661C00022B668EB5C7C2BC95400D164097BAC8C0AFA98640000008569FC3CCC1B0B1B0A27D525783755F7F9497989091691C00001B7A777799EDFFFFD0805E535458609CEAFFFFFFDD9161372B3D5FA6E8FFFFF0CD9B53190000227BC2DB4B9975431D18201E2B4F898B7E8E9A8B61514458565280FFFFFFDD9161372B01FE7A60070718A0766750545878AFF6FFFFFFA7624E4A6EA2C6E1EBE1E4D8C5722B00091556ACEAECECE6E4CE6E1D031D57AECDCECECFC2903F10000D4EA2C0C2BDB36E3B31332E4274B0C1BEC9BF85260000004F91BCC7B6A96019000858A7CCD9D1C2BAA95E0B0000085395BFC4C4BAB797661600002B5F98B7C0BCB5883808145197BCC5CDBFB17F3A0000195BABC1C1B4C0B5ADAA78515A807956809E9A948A7C4D0D00002371666588DCFFFFBB724B4B4752648FE3FFFFFFD28D54382A3154A7E6FFFFE7C88D4C15070B1D7EC7DA4E936B340E101620295B958A7990A48564515058624E8AFFFFFFD28D54382A01FE7B60070718B06C615665657CB5FAFFFFFFB159484D77A2D0EAEBE2E4D8B56B20000C2C59AEE9F2E9E5CEBE6B1B071A5DAFCDD0D2CAC388400400214CA5C3B7BEB07846343528407DB3C4BAC1BA7517000008519AB1C0BCAC5E18001265B6DAE1CFC9B9A95D010000134E8EACBCB5B1B4A0641B04032C679CAEBABFB48134101557A1BCBABDBDA0712700001468ADC2C3B8B4B4AE9C6B4A6480725D8C9FA599937B4F0C00002C73747CB2FBFFFFD47D4D43515A5C9DEEFFFFFFD1844F2E2B3F5EABEEFFFFE8BD8B4A1602001D8BCDDE51906B31170E1A263055908C7A8B8979624C43565C649BFFFFFFD1844F2E2B01FE7C60070718C06B57545F547BB2FCFFFFFFAA584A537BB2DCF3F1D7E5E0BE712200081F5DB5EDF0EFDED8B96414082369B7CACDCFCDC3813B0000094B9DC6C2BAAF72524B3C334682A8C8B8C1B87419000010549DBFBAB0A04B0800176BB7D4DCCBBEC3A35600000016589CBCBDB9B3C09B4F05000E3C719EB2B7B8B57D2F102667ABBAC2C0B89D6D3200001D6AA8BEC4BAB1AEA69D6C546F857B65829295978E7D4C04000036706A71A6FAFFFFC3665245515065A2F4FFFFFFC5774E39303956B1F6FFFFEABC74410A0D093684CDD151896C31141326232F5C8A84828C9478524F545E5E5B92FFFFFFC5774E393001FE7D60070718D072686264658BB9FEFFFFFEA45845537EB6E6F7F5DADBDAB7642502052C6CB4EEF6F1E4D0AB5414092B75B9D2D6E0D6BF802B00000155A2C0BFC1BB7C474933313C86B4CBC1C8B26B0D0000145A9DC4C5BC994A07001A6EBBD8D6C7C6B6A854000000155A9EB3BAC3C0B8905205000F387DA3B8BCC2B4762E092861A9B2B7BDB8A2632200001472B6C4C7B7ACAEB6A76C426485725A839A9D9D997B3F000000347A8187BBFFFFFFCE705549484F5EA7F3FFFFFFC678442B2C2C61AFFCFFFFE3B2783C1601042B97D2E0498D69360F1122203366958472939271514C5460605C9EFFFFFFC678442B2C01FE7E60070718E073716F73758DC2FEFFFFFF9B5E4D5989D3E9FFF9DCE0D9B1611800062169BEE8F3F3E7D0AD551B072985C1D6DBD0C8B36F1D0000115998C2CAC8B67F524D3D28408CB7C5BBC5AA65020000135B9DC0C0C197490D001F79B6DAD8C9CDBB9742000001225794B2C0BFB2B690440F00074B87ADBDBBC3B071250D2F70B0B6B5B7B699681300001E77B4BEB8B2B9B8ACA460486B897364839DA6A3957244000008427B8289C2FFFFFFCC784A4E49505D97EEFFFFFFBC754631313664BCF7FFF6D9AF763B13070A3C9CDCD844895A2C12151C1E3660967A7C90866B56485162646EACFFFFFFBC7546313101FE7F60070718F0796B6570798CCBFFFFFFF3935F48578BCDFFFFF7E4DDDCAC590A00052D6DCAEAF2F9EDD8933F0E0B3587C2D3CED3C7C1782100000A5FA1C6C3B9B6825C5A402E4189AEBABEC2AC5E0B0000155599C5C2C19B380200267BBEDCE0C9CBC29F4A000000295A9CAFB3B8ACA6813906001B538AB1C7BCB7AB6920152D72A9B0B1BABC99591100003885B0CCC0B1B0AEAC94583B6B8E776187A6A59398753800000B42626B7FC2FFFFFFC2703C3F4643559CEEFFFFFEC4764E37353D61B4F8FFFADB9F612C0C061147A7DCD34B88542B13172220306C967B788F8064524851555D66B7FFFFFEC4764E373501FE806007071800756D6467708EC4FFFFFFF69E5B40589ADDF3FFECD7D5D6A95A1D00092A6CBDF1F8F2EEC88836050F418AC0D5E0D9CFC36D160000105EADCFC4B7B579625431223E88ADC9BCC4B15C0200002070A3BAC2B68C2D07002877C1E0D8CBB3B892410000003A6A9CB1BBBDB0A77C310002215B8FADB8BDB8AB631D013580AAAAB1C3B798531200003887ADBCB9B3AAB3AC8F5E436C8968669DB7A49D937B3B00001C4D7D7392D6FFFFFFC2733C3A474864A3FAFFFFFFC17D422C313B64BCF1FFF7D1975F2D0D0D1048B1E5DD4B815C2C17131A1F2D6E97837F8875574D51575A5F6ABBFFFFFFC17D422C3101FE8160070718106F736D6C7E94C7FFFFFFEC904B3E599FE4FFFFFEDEE3D9A34F1700072A78BDEBF0EDE0B8862C050C5294C1D6D9E0CDBC631000001F64A8CEC6C5B087665235274088B4C6BAC6A45B0000001F68A4B5C7B6813400003480C6E2DACBBBB9A03F0000063D7096ADC4CBB199712E000427608AADB5BABAA1621D164180B6AEA8B7B99A400000003D86B2B7A9A1AEB1B48F5E4568856A6D8FA7A7A593733200001A4F7D7F9BECFFFFFFC6755945465766A9FBFFFFFFB87149302F3769BDFAFFF9DC985927140E1151AFE6DD487852231518212D397696737479725E5048545D6074BEFFFFFFB87149302F01FE826007071820766C6A74859FD4FFFFFFE38A4E415C9CE0FFFFF5D7DCE4AB571500112D77C2EAF8F9ECBE7422010E5AA1CADBE3DCD3BC6F1B00001D60A8C1BBBDB97E665A39294691B0C5BBC8A0500400002077ACBFBCAD78320000388CCFD8D3CBC4BD923400000B39729CADBAC7B39A6E2C000B31618BAFBFC4BA9A590E0B4483ABA8B4BDB990410000003593B7C8A596AFBDB68D4E4A667C726FA1AAA6A893682300001953696B8FE3FFFFFFB66F433E3F425BAFFAFFFFFFBA733D26243764BCEDFFF0C88D492F1211255CB0E4D9447C5121121213233B769778728871564D4F4A535D78BEFFFFFFBA733D262401FE8360070718306E6768747B9DD7FFFFFFE08B494262A5E6FFFFFADDE0D9A24C0E0507327DC2EAF5F4E4B96B1E00195FA7C9D7D9DBD8B8640E0000145FAFD4B9B5AB8672683D293886ADC5C3BCA3510000002C779FB0B4AF6F290A094391CFE6DCCDC1BF8827000014508D98ACBABAAE9C5E2101102B6E8EA5BCACA6924C1219458CC2B1ABC0BB8B3C010002468DB7B0A1919EB0A783523D768C8482A1ADA59F906E1D000030607985ABFDFFFFFFCA6F4B403D496EB1FAFFFFFFBA7242302B2E62C4FFFFFBCA7B371E12101454AFE6DA4973482D19141520377A997B7B7E766248595B616974CCFFFFFFBA7242302B01FE8460070718406F6B687C7DA1DCFFFFFFD9844E4162AFF0FFFFFADDE0D9A0460C010A3973B6F2FEF0D3A96212061C6DA8D7DFD7D6C6AE4C0700002C69A6D3CBC5B68167613B254E8CB5BEBEBA9A48030000327BA5B5BBA96C26060F4A9BDAE2E3C4C1B5891E0000124D819DAFB9AE9A88581C00083C76A6B4B6A8B09141191C538FADA3A5AFB1833800000C4E9EB8B09D91A7AEAA7E40436F907473A8B7B1AE91681E00002B64807FA4FFFFFFFFC1734A404B5666ADFFFFFFF7BC6B3D272A3565C4FEFFF3C37C422417161A61B0E3D54C75461B120E20333E7D9472747A67544752526B587BCFFFFFF7BC6B3D272A01FE8560070718507F6C677382A3DAFFFFFFCD8649455CA7EDFFFFFFE3E6DC914310001A3A81C2F0EEEFDBA05214002871B1D1E1DFD3D0B4570200002D73B1D7CBC9B17D704F34244D8FAFC0B9B4AB450000003579A0B7B5A55D12000D4DA1C7E1D7CDD0B7772300001855809FAEB3ACA287541B06184880A5B1BBB2AF8F4C121D5298B4ACAFBAB4752E0000065999AFA9958EACB2A881454A6F866B7EA6B8A9A6915F1B00003367727DB5FFFFFFFFC174453A40545CB8FFFFFFFDB96F3E2C263569C3FFFFEFBB79432A0F121D66BADCD341653A1B1B232A2B45838E6A78775D4B4E5F575A6A8ED5FFFFFDB96F3E2C2601FE8660070718607E76706D769CCDFFFFFFC9744E4660BCFFFFFFF9EADFD792410100103D8CC7EEF4F2D390430D092971B9D7D9D3D9D7B14E0100002A6DB2D0CEC2B881825E2A1E4A8AB2C5C2C39D3A0000002D78A8BFBBA25B180D1653A2CCD9D4C8B9B47F22000025648596A2B0B09D774513021F548EB2ACB5B1AA8A41163059A1BCA0AABCAB73280000135B9FB19E7884A4A9A2683D467B907479A3B5AFAC9B671A000032718385B8FFFFFFFFC8734A43444D6DBAFFFFFFF5B76D3B28263C71C6F8FFEBBF7939250A0F1F65BFDBCF41693B1F130C1F31448CA06E7B7D5E4C4B5853576897D9FFFFF5B76D3B282601FE876007071870706E6A767AA4D8FFFFFFCE78414962B0F7FFFFFBECEAD19346120317488CC8EDEEEDD78E370000268ECAD3CFD7D6C9A94A0000002E73B1CECCC1B07C6F4C2E234590B3C4C1BF96460000013C8BAFB9B798570F000957A8D4D8D1D3C6AF711700002C7195A2A7ADB58E67340001235D8BADBABEB1AD833B0D276CA7BEA8A7BFAB64210000145CA8B28E7782A8B7A4673B4A73847684AEAEA9A5904B0B00003E707B88C5FFFFFFFFBE7448333B466ABEFAFFFFF3AE6C46332E356CCDFFFFE9B07036150B0B216FC8E9CF4262371C0F192228418E957273705A4544535353669FE6FFFFF3AE6C46332E01FE8860070718807574797A8AA8DBFFFFFFC771404266B5F7FFFFFFEAE9D88B33010019478BD7F7FAEED4833400003396C6DBDCDBD6CB9D3C000008347FB6D2D1BCA7746A4C2E205991AEB5C0C593400000054188ABB3B495510C051F66AAD0DAD9C5BCA86C1E0000357196A2B9AEA3885A2609072E6392B0B5C2B3A77D330D2D70AFB99EA6B09E6A2200001D61A5B38E7389ACB3A965393E7D8D7B80A8BDACA99F500A00024275788CC6FFFFFFFFC2683D363A4F6FC5FFFFFFF0B4713327282A6AC5F6FFE5B4652B1300052176CCE6D3446A3C25151D252C518F9671786759544A494E506090DDFFFFF0B47133272801FE8960070718906D6C6A7A8CAFDCFFFFFFC56B3F4A6FC5FFFFFFFFF0E9D58C3E0A001B4B86CAF0ECEAC2702700063998C6E4E3D2D7D09D3500000E4688C5D9CDBCA9715B4025245E9DB4C5BCBC7F2E0000074A84A5B9BC964A0D0A1D73AEDDE3E6C6B2B1650700003E7C8E9CAEAFA27C4A1D060A336CA1B4B5B6A79E842F093D7BA3BF9CBABCAD602000002168A8AE87767194AEA761334372888393AEB8ADA8944904000C4C716286CCFFFFFFFFC15C322F3B3F71CAFFFFFFE9AB6638272A346DCBFDFFE5AB662D120F0C257ACEEBCA385A362414092024508B927374775942404A545067ADF4FFFFE9AB6638272A01FE8A60070718A07774758889B5DFFFFFFFB9664E4A64BCFFFFFFFFF2EBD7923A05001A5390C8EAF4EAC66822000B3B9CC8D2DFE2D7CA923A0000124A8DC1D2D5C5A370634D2223589CACBDB9B484300000065099ADBDB58C4407012C7BB9DEDED3C5C5AB5F010000467D979FAFAB96683A12031047759FB6B5ADAFA46B29093E82ABC0A3AEB0A253150000307EB4AA7E7078ACBB9755304A7B8D798EB2B7ABAA92410000084B777296DBFFFFFFFFBB714336404C7CD0FFFFFFEBA7693C251D2A77C8F6FFE3A25D2A0C0A1C206FCFE2BE3554341C17161F3C578F906B777557434D4F515368B0F0FFFFEBA7693C251D01FE8B60070718B07170737B90B9E9FFFFFFB067474B6AC7FFFFFFFFEDE6D6933904031D4D96D5E6EAE3B55A1D00053FA3D1E1DDE1D9D89D330000195486BACDD2B59269573E1A1F65A4BCC8BAB46D1F0000144F9FA4AFB2943F05052A7BBDDAE5D5CCC5B667060000487FA0A9AEA590653304001B4D89A9B6AAB3A0A06725194890B4C4B1BABE9F541600002574A8A87B5F70A1B49F5B355072878CA0BCB9A9A58A3F00000C5B7E6D97DBFFFFFFFFC06B3C32334689DCFFFFFFEBA5703325273A7FC7F8FFE3A564250703001A74CFE2C5365431190D1D2432619A8A7886805541404A525874B9F2FFFFEBA57033252701FE8C60070718C0717678828EB3DBFFFFFFAA573B416DC6FFFFFFFCECE8D583360505215D9DD0EAEFE5AB4D1200004EA8D5DEE3D8DACD8E2C00001B6092CED4C7B08E6354321C1D6DA3BCC6C2B972240000175E9DB6C4BE8A3600002C89C3D7DCD8CCBDA24C0000004C83A7A89E9D905F270010154D86A6B3BBBCAFA5671F175486BEC2A6ABB2A45C1100003081B7A46D516DA3B0894B35486985809FBDC7B4B38E3D0C0017578072A0E2FFFFFFFFB26138393A5387DBFFFFFFE6A36E3C292A3575C2FCFFCF995928140C15227CCDDEB939522C0E09131B345C9998808B6948394548566677BAFCFFFFE6A36E3C292A01FE8D60070718D073747A9299B4E4FFFFFFA95E3E406FCFFEFFFFFFFEF1DA7A360E0A1E64A0D4E0E7DBA34C0E000849A6D1DDD6DBD3CB7D2300002969AEC8D5CCAD875742291C2768A3B8C6BFB2621A0000276FADBAC0BA8B390005348FC1D5E2D2CFB7A44B00000B5B94A0A79DA3835116000023578AB1C4C5BEA697611D1754A6C2C5B3B5B7A1500B00002D7B9B905744689CB38D4F344B77938A97B3BDB5A6873D0600225E7A83AAF6FFFFFFFEB6683D37465694DAFFFFFFE7986A3E21253977C8FCFDD58D5B1B10080F1E87B6DEBD3A552E1B18111E2A67989583917750433D4B564B77BAF8FFFFE7986A3E212501FE8E60070718E0777C798499BAE0FFFFFFA760424779D3FFFFFFF9F2ECD37C2B120E2E619ED1F4F1DB8E420C000C4EA9D2DFD7DBD9C27E2300003473B6D2D2D5AD745238240F2678A3C5C3C2B76F2000002A75A5B5B7B5762800033B8EC6D8DED8C8C3A049000000569AAAAAA9A480321000001C649CBDBEB9A69F8958221A64A3C6CBBBB8B5933B0800003989B491563E5FA0A9854F334D788F99A5BBC7C1B4893C000010638881A8F3FFFFFFFFAC6238343A4F98F5FFFFFFE89F5F47221E2D7FC2F1EFCE8C511D10070E2A93D5E1B12D502A1E1A1821396BA29582926F48443F4249456DC0FCFFFFE89F5F47221E01FE8F60070718F076818092A1BDE5FFFFFB9857333F7AD1FFFFFFFDF8ECCA76370B0A2C68ADD9EEE8DB983500000E52B3CCE2DFE1DDC1791C00003A7EA2C4D1CC9F6445280E003780B6BCCDCAB1581100002F76A5B1B1B87B2B01164E96CAD7DDD4D0C3A2460000105892A4A4A79E7D3203000023719FC3C0C1B6AA88551E1A5FB0C9C9BEBABB95531400003E849F76443B5EA8B58D45344F738D959DB9BBB9B186350000296D7D83BDF5FFFFFFFFAE623D3937609BF2FFFFFFE4936C46312E3C8AD4F9F7DA88380A140A0C2A87D0D6AA364C29170412293B6FAB9A8295754F44434A4E5A79C4FEFFFFE4936C46312E01FE9060070718006C7887969FBBE9FFFFF09850333D78D5FFFFFFFFF5EDCD83380C182A64ACD7EAE4D6923400001856B5D8E5E0D8C8C3741400003382B5BBCDC7926E3C2A0D042E82B4C3CDC3A6610D0000367BB4BEB9B77E26001658A5CCE4DEE1CBB8943700000C5A9CACA8A09B732D0000002972A5C2CEBBBBA97C5117216AA7CBBFB6BCB58C3E140005468BA180483C5D9EAE874B2E4870959BA4B9B7BAAC81310000246A8678B1FFFFFFFFFDAF5F3931395BABF1FFFFFFD9966747231F2B78B8F1F5CF8E4926180C09338DD7D9A3324024161422262E6CB097899474473C3A444E527EC9FFFFFFD9966747231F01FE916007071810757589A2A5CAF1FFFFED8A533E3B79D4FFFFFFFCE2E9C3732D0D183776BCDDEEEACE872A00000651AFCFDDD4DCDABB6113000A4990B6D5D8BE8A4A2E210A0F358BBEC2C2CBA84B0A00043D7CAAADC1BB7F2E020D56AACFE2E4E2C1C1983B00000967A0A4A39493691B0000003283B3C2BEC1B39E7C3E19276EB2C6DAC3C3B58D431800054491A27D434371A9AF8649304E6F8794A4BDB6AEA67E32000034737F7EBCFFFFFFFFF39E5D4033446FB8FFFFFFFFD4946843291F3479D2F6F3D2833816130D0F3D91C8D0A43447250F131F2E397BA99285966E4A3A353845518BD8FFFFFFD4946843291F01FE926007071820767A849CACCBDEFFFFED863F35477ECFFFFFFFFDF9E9B16D2A0C1C3888BDDFEFDDBE812C00001366B9D6DEE4CDC6BA721000004795C3CBCBC39652250C060C2D7EBCD5CFC3914E0B0011488BB4B4B4AB6D2706225FB1CEE2DEDDC7BB88320000185E9EAE9B9F966C1C0000053789B9CBCEBCB59C7E360A2C75B2C1CDC0B9B78A4123000C5297A3643134559EB2814326466D8CA4AFBABEB7AE7123000033728272A9F3FFFFFFDE9F5432283E6FC0F7FFFFFFCD94603B2624378BD8FCF2C972330A03090D349ACDC29A3540241A101C273D78AAA18D9A754D393E52545B89D5F1FFFFCD94603B262401FE9360070718306B778AA0B1BBE4FFFFDA844630487BDAFFFFFFFDEFD9B35A210F174680BADCF1DCCA7F1B00001E6AB6D1D8D8D0D2B6630F00035197BAC6D6C084401E0F030D398ABECED1C09E4E0B00174C91BDB5C0B7661B001761B9CDD7D7DAC6B8852C00001561A1B8A596925C160000003A91BACCC0B8B79F722C0F2E83B0C5CDC5C3B9803A12000D5795A56D2F2A61A7B07A3D2A3D6F8F9AB7CEC6BAA47824000C3D7E898AC3FFFFFFFFE8A9592A234A79C9FFFFFFFFCE8A673E28233C8CDBFBF2CC723415131210479DC9C89B312C1F211C1B2B4181B29E959D7C3F333141414B87D5FAFFFFCE8A673E282301FE9460070718407784989FACC3E8FFFFDF7F4D3D4677DFFFFFFFFEEFE5C168290F163F90C7E5E7DAC3782800001D62B4D7D7D6D5C5AD5F09000A5C97BAC5C8B979350A00030C4599C0CAC7C9A03C06051A5697B9B6C2AB6B22041C67BED7DCD8DBCCA8741B0000236E9BA49D9B935A190000094290BFC6BEC2BF9D7838103C86BEC9D1C4BEA87D30110518569A9B6633245FA9AB703D304964819BADC6C6BEAF7521000D39748481C3FFFFFFFFDB9E6439374B87CBFFFFFFFFCE7B583A2225398CD3F9E7C57432110B0A0E409BC2BE97323F27141C21274C9EB79F9EAA7F4B333B45495A9ADDFCFFFFCE7B583A222501FE9560070718506F7988A2B0BEDCFFFFD7805431407FD9FFFFFFEEEEE6B65D201920458CC2DEECDCBB721D00002170BCD1D8D2C7D0B04E00000D58A6C8D1CABB6B1E0100000F4493C6D2D2CE963D00001D5E9CBDBABCA45C16012974BAD4D7DCD4D0B1671600001B79A4ABA49A86510B00000C5197BED5D7BDAF99642F133585BECCCDC5BDB2703612001265A5A76322345299B674382F466292ABB8BDC7BAB0731D000F47839185CCFFFFFFFFC9945B33374E9BE0FFFFFFFAC37A523E2B1E4B90DFF7F0BD692A130D0B1D50AAD1BE902C422E251A1724468FBAACA29D6F3F353536454F86DFFCFFFAC37A523E2B1E01FE9660070718607E8BA9BBC4D0DBFFFFD8824A364D7ED9FFFFFFEFF3E2B2511C122A509ED2E9E2DAC26A1B00002675BBD8D9D4D6CEAC4B0200135FA5C2BFC0AF6916000200184D9AC7CED3BD833100001E69ABC6BDBEA8621B032A76BBCED5D6CAC2A36A0A0000247AAAB7A6A7924F020000124E9EC2DDCEC1B0945D1F0B3D86B6CED4CBC5A4623215091D69A79E60232063ABB27C3B2D406398B1BCBDBDC0A7601600205A848F98D3FFFFFFFBC67D493839519AD9FFFFFFF4B77A4E392E1F3A99DCF7E0B0702B120B131D5EABCBB8892B352C2213212D5CA1C9A8ACAA6F3E353241435393D7F7FFF4B77A4E392E1F01FE9760070718706C7A9AAFC3B7D0F8FFCF7E372D447ED4FFFFFDF2F0DBA552201727549DC8DFDCD5B25C1200023985C3D5D9DBD5C7A14900001D5FAECBD0C8B05D19000000114C9CC4CDC2BE88290002287AB0C4B9BAA2501008327EB6D3DFD9D5CAA8640E00002277A6B2A39A8D430700001757ADD2D2BBB5C29D561C114294C0CAD7D4CBAD6930120B2D6E9D98501E275CA2A56C342B416796B4B2BBBDB7A36E1A001C5589938FD8FFFFFFEEB97C4C3336549DDDFFFFFFF7B771614430234C92D5F3E4B664260B09080F57B1D2B77E37351E1E1E212E56A2C1B4ACA26F413D353F4A5396DCECFFF7B7716144302301FE9860070718806E899EC6C5C3D7F5FFBD6F41324775DDFFFFFBEFEEE7A7541E153568A9D7E5EEEAB0580E00002A85C7D9D6CBC5C7973C00002071A8BECCD2BD640F000000154F9ECBD0D1BD7C270000277CAABFC0BE98531B113679B4D7E4DBD1C0A0570E0000348AAEB89D9D96450000000F60B3D3DCCABFAA8D4E130B3E8EBFD2CCC3C5AB64301A1325759B8C501D275B9DAF6A3421346DA0B3B7BCBCADA26318001C5D878F93DCFFFFFFEDB48343362A56A1E9FFFFFFE1B771482F2121459CD7EDDEAF65270E0B10246FB9D1A87E373727161C1B325DAAC5B2AEAC6E3528313F4B529ADEECFFE1B771482F212101FE996007071890708BAEBFCBC3D2F3F6B2733B274381D4FFFFFAEADDCD924822213C6EB7D6E0E3CEA44E0900043387C5DAD3D0C1BD983400001F6CB5CBC8CCAF600A0000000F4D9BC1D6D1BA852601012D83B9C7B6B6974F1501357BC0D5DEE3DFBF92470400043E84AFB79F968A31040000175DB5CCCFBEB3B2984E120F4A8FBFCEC6CAC3AA69381D0F3278A58F47232963B5B26A2D2A34679DB6B5BFC6B79D52110014578D92A4E9FFFFFFEAB9764E2F3956A9EEFFFFFFE3B1794C3831294F9BDDEDD8A9591B100C1B2E6FC5CBA36B2F30211A1D29336AB6C7B6B5A9703C3036394F5699DDEAFFE3B1794C38312901FE9A60070718A0768EA9CFD3C0C2E9F0A96E4A2F4087DDFFFFFBEEDFD1A04D20274771ABD7DBDCCE98480400003987C2D1D4CDD2CC902A0000267DC0CFCECAB258080000000C55ABCED0D2C0701E00053686C0C6C4C28E4A0F093990CAD3DFEBD4C08C38000000388BB0B5AFA784340000001364B9D6D3C3B9B59353120F4B93BBD1D4D2BB9B52331418387EA9944D232E699F9E652A243D5B9CC4C4CBC1AF955B0A002C6794989EE2FFFFFFCEA66E43352B58A5EAFFFFFFE2B0644D4A332B4EA5DEF3DEA1591D030509257EBBC19B613136242B20232F6CB3D0C3B79D6238334344445297DEE0FFE2B0644D4A332B01FE9B60070718B0758AAEC3D8BFC4D5DCB66F4034457CD6FFFFFFEBDDCB8D41191F3E79B7D4DEDFC58C4603000B3289CCDCD7D3D3C4812A00002A7EABC2D1CFAF550C000000165FA6D0D5D1B56B1A0007388DB7CDBDBD8F3F120C3A8BC2D5E2E7DEBE8333000009458DADB9B1A98A34000000116DB4CED1BCB8B186401419519CC4CAC8BEC19A522E1713417BAC9E4C1B376CA3A5592D243F6CA2B8BFC7C1B7A94E0300246998919BDCFFFFFFDC9F6C4530335DB0F1FFFFFFEEAB634B41262450ABE1EFD9994A20080E14347FC5BCA16432361E20211D3A7AC1D2C9BCA861392826353B509CE1EBFFEEAB634B41262401FE9C60070718C0778EA7D1D0B9B8D2CDA15A2E263E75DAFFFFFEF7EBD99845251A4279B3DBE8DFC37F3804000E4A8DCBD0D2C6BEC18E1E00002B7DB9CAD0D1B04D00000000185CACCFD2D4BF6A1A000E3C9CB8C4B7A27F381103418ECDE4DDD7DCB879390000004997B7BEB0A583330000001F64B9D0DAD5C2C08835061B57A5C5C9D5C3C8934B3423203785AB92471A356F9E9C5D281F3866A1BBBABDB7B99D4F0508266A988E95DAFFFFFECD8B623E2C3862A8F5FFFFFADAA06447392F2959AAE0E6D2944B120B06144584C5C3895E2E2E2120211F427FC8D6CCB89B6139323241515697E1DAFADAA06447392F2901FE9D60070718D07591B3D6DDC2BDCAC49460362F4480D1FFFFFFE9E8C9874326335087BBD9E1D4BF85390200114997C8CDD6D0C3BD841B00003A84BBD1D6CEAD52000000001462ACCCD2C8A86E1600063A8EBACFD0AB812E0A12539DC5DADFE2D1B5772C00000B5395AABAC2B77F270000001E6CB7DCD8C6C5B1853E0F1458AACDCBCBC5BB92502017163991B29649223676B3A95726213E76A9BDB6BEBEB385430308246C949A9FF2FFFFFFC28A613C323866B8F1FFFFF3D9925C4D48302F5FB4DFEECC8E4A1A0111124490CCBF83592A2A1C24242E4889C9E4CCBCA66232283134495D9DE2E4F3D9925C4D48302F01FE9E60070718E07799BDDAD9BFB1B1BA88542E293A79D4F8FEF8F0E2C07B3F24315695C0D9D9D2BB6D2C00001F5A9DC6C6C9C9CCBB7D1600023F86BDC4C9C8A84A000000002264B3DAD2C9A96312000A4291C6C6BDAC7E2C030F4D95C7DFE1E4D9B3691C00000C5B9DBDBBADA7822E0000001F78BFD6D7D1C2BD893806135A9BC0CCD3CEC08A42261A1F4484B48F4F223570AEA45625143A71A0B7BBBCBDB48F400008377F9897A7E5FFFFFFBE7F563F28325EBDF3FFFFF5C9925740402A2E68BBE5EDC88F511C0B0E183C97D0C38A512C3327221D2E5093D1D7C2AD9C61373733373F55ABDAE6F5C9925740402A2E01FE9F60070718F07798C0D9CDAE9CABA5774B3825427DD7F4F8F4E7DDBD7F3F29386993C4DCCECEB3782000001858A9BFCACFD6CDBF7C1800003D94C5CACBC7A84E000000001D69B4CCD1D19D500C00073E8CBECCC9A9712801114BA4D1E7E9E2D8A75B110000135A9CBAC4C3AA77220000002377C3D7D7CCC1B88E400C1C5EA3C3CCC5CCB6793D23101E4490B08E49263D6AA69E5F24233F73A4B7BDBFBAAB8A3D000638798E91A6DFFFFFFFBB865836343360B2FFFFF7E1C49A57403B33366EC8EEEBC685482419171C4EA1D3C284552B3222261A345E9DD6E1CBAB9053302E2D374665AFE3D7E1C49A57403B333601FEA0600707180078A0C7E4DBBAA59897714C332D417CD7FAFDF9F3E2BD7040234374A6C7D2D3D0AA5E1F00001D61AEC6CACDCEC0B5741200003796B9C4BBC9AE57000000001E75B2D9CFCFA5560D000A4789B9BAB89B6426061758A4D3E1E9E7DBA954190000125EA8C0C1BEAB7D210000002368BED5D6D1C3B570280C2B6EB0D0CECEC2B46A351B1C264E8DAC955231497FA9914616123C73B4C2C4C3BBAE883700003D81A393ADF5FFFFFAB78366503D3161C0FBFFFFEFC2804A3C41363A7AC5EBECBC7340120E0F1154ACD4B5824B2C2C1F30222E5BA4DFEACAA78B493C332C31506CB4E7D2EFC2804A3C41363A01FEA160070718106595C2E0E1B39497845D3A2924397EDAFFFAF7EFE0A574372D4373A5D0D8DEC698550D00002562AEC4C4C2C5BBB3721400034C92CCD3CDC8AD41000000001E6EBAD0D7CD9C470600003888BDCBBD9B6520071361B2D7DDE0F2DAA2480F0000256DA6BCC4BCB274160000002A76C2D6DEC5B5AE7B29101B67ADC8C6CBC4AA683731211E4D92AF9346294883B2954920213C71A4C1BCBEB8B6842C02093980A297A8E9FFFFEFAA7A524A3B3B6DC2FFFFFFECB48042343B2E3C7DCFE8E7BD7A342718081A5EB1DAC57C3F28202423243772B4E0EBCDA7895B302E2F414C64AFDDD9ECB48042343B2E3C01FEA26007071820789BD1EFEAB39385764F3922223E7ED4FFFFFFEDD7B06A2F234C7CC2D0D9D4CA975A10000935669FB9BCBEB8BCB16B0900015095BED6CAC7A34B000000002878B0CEDAC79D42090003448CBAC1BA9B591C001564B2D3E6E2E1DFAE43090000296DA7C1C5B3A66B240000003484C2DAD6C1BFB57127001E65B0D0DDD2B8AB6F39281E226097B2925C334686B19237221C4780ADC1B8BBC8B27C2D000038799690A9F2FFFFF8B4815E4F423462C1F5FFF8DFB082533B3E2D478DD3F1E2BD7B3E23110F226FB5D6B16D3E26272629253877C1ECE9C59D78463A3236384767B3EADADFB082533B3E2D4701FEA3600707183080A6D4F2E5B6997E6A483322244283D7F5F8F1E8D19D643431537DB1CDD8D6C38F411100163C78B4BFB8C6C7CEAD610B0008529CBEC4CFC19B46000000002278BCD2DBC58B420000053E97B3C7BB88481100196DB6DEE7DCF0D797480800023474ADC0C1B6A66B230000002A85C7D0CBC8BAAD6F21112975B2BACBD1C7AF62292E27325F91B1955A385090AA8F42111F4983ABBABFB3B3A3742E021B4D709B94A3E6FFFFE8A67C5741333A6DC8F8FDEFD9B280463A41334788D4FBDFBC75391F0D172F6CBBDAB56E362A211A1E27406CB6DBDFC090764834302D454A6BB4EBD0D9B280463A41334701FEA460070718407CA2D0F1E4B1866D6340241E214386D6F9F6FFEFD0995A2C295490B7D5D3D6C18E460600174977B2BFB9B4C0BCA85A08000B5BABC3CDC5C69E48000000003186BACCCFBE893C000001498AB6B2B586471B0F256DB5DEE3EDEDED9C380000002D7DB9C6C0B5AE6F170000003183BBC5CACAB3A467240C327AABCFD3D0C697592A28222F6293B19B5E3B518AAA872B10225587B7BDB5BCB3A3782500103D809893A2E4FFFFECAF7E5541393B6DCEFEFFF8DCB0784733353448A5E2F7E9BD74341D1D1D3376C1D9B5724A322C201D213D79C8DFE0BC9671472E332E373E69B4DFCCDCB078473335344801FEA5600707185075A4D8EADFB0875B49231A111F3C79D9FFFFFCE7C8945D3F2E5D99C1D7CCC4B57D360000144985B8C4B1C5BAB5A85B06000B5BA7C0C0BFB69E4200000000348FBACED6B87E360000124E83A9B2B3924612062D79BBE1E7E2E1D9993500000B3B83B7C5BDB7AC69190000043C86CCD1C8C2BAA466210D397FC0CDD0CDC2A5502D2E282B5A96B9955C436499AF7D3311104889B7BFBAADAFA07A2500104A7F9290A3DDFFFFF1AC6C54433A3E73C8F5FFF1CCA76E3E2D2B224F96DCF7DFAE6B3A211A2B3684CED4AE703A362A232B223485C6E6E5C694634233292C3A5270BEE4CECCA76E3E2D2B224F01FEA6600707186077A6D5EADCAB795036271B181A4084DAFCF6F2E2C18755333A6799BBD2D7D2B2772D00001E4A87B7BFB1C3C2C3A74B00000D65A0BBC0BEC89F36000000003686BDCDCABB6D2D000009478FACB9B4803D1111297FC9F0E8DBDBCF8B310000094386BCC9C1C3AA6C130000073882C0D8CDC2B89E5F1E053C7DBBD7CCC7BCA559262B312F5EA2AEA4634F74A4B9833511184D84AAB8BBB2B3A26C130018547F9683B6D7FDFFDB9A6C4C402B306DC5EFFFE0C0A06D3F342B2A51A0E1F7E7A45E321F22213C8FCEDCC370381B2524261D3F8DC5EDDFB58E65492B282E394877CAECC7C0A06D3F342B2A5101FEA76007071870719CCBE4DAA573482E1B0B19204383CEE6E5ECDEB97D4A283473B4CEDADBCDAB631D00001E598EB3B6A3B5B6BB974300000A65ADBDCFCFC6983C000000004598C2CFCDBC6D2B0000164E88A1B19F7B3A0F0C3489CEE4E6E2E4D79B2C0000154E8DBFD1BEAEA5610C0000003A91CBD2CDC7BD9D4E200F398BC1D0CBC9C2A04823202430719DAC9759426CA2B6832E08184D89ADBFBDB2BDAD651100214F849583A3E0FFFFE7926549412C3976CEF4F6EBC1946233343C3454A5E0F2DAAA69322A26304792CFDEAF6C3733282328233786CEECDEBD835D3B2E333B3B4F7ACBE7CCC1946233343C345401FEA8600707188084A4D4EADEB27C4D29181A2027498CC9D8E7EAE2BC7F40243576A8BFD3D1D0A15C2100023168A3BFB8A4B4B8C19C3A00000D6CA7C8D0CDC0983300000000409BC0CDCAAA5B1D0000184E889EA8A471350C093B8BCBD5E0E0E7DF95260000155993BEC9B6BAA55C0B0000093991CCCDC8C8C29E551F104996BCD6D5CCBC804822282E3A6CA1B7A26C52749CAE792609214D86B2B9ADAFACA66417001F65919684A5CFFBFFE2966B42383A396DC5EDF6DCB7815A3833292B58ACE6F2D2A05D271D293A559CCED6AA66383A251F232F4492D0EDD0A6795F452B36323A4A7BCFEBB9B7815A3833292B5801FEA960070718907CA9D2E0D9A5662F15000713204387D3ECEBEBD9A76839323D7AB0CACECEBC984F1600032E74A0BFB7A3B3B3B18B3400001F70ABC1C7C3BC8D30000000064C9BC4CBC8B3621E000026567D8E9F9F62260B073899D8EFF0EDE2D9942F00001B569CC0C4B6B89F53020000133890CAD2D1C0B68E4E11145097BDCFCED7C1823C211D2F3E72A6BCA15E506C97AE7A280D0E4684B6B9B6BFBAA661130022568A928298C0F0FFE19B665142393F76C7ECF3E2B77C5C4339354163ADEDF7E3A5603526223E62ABD8D8A85B332B241E1E1F3F94DCF9E0A66C54443A342E3A5289D7F6C2B77C5C433935416301FEAA60070718A07EAAC2D8CCA66C2C0F04051220447CCCE1E2D7CA9A603E314883B5D0D0C7C5AA5D110002346D9FB7AF96AEBBBB8E370000126AACBEC7C7C6902F00000001489CCCD7C99B58150000225576909CA16F2B0B0E41A1DBDFEAE7E0CF802300002465A9BDC1B8BC9F590A00001A5291BFC6CFC4AF8C481420529BBED7D2CAC18A39261E22417AA5B09B654A80ACB472220D19588DA7B2B6BEAD9A611500235A888C7B9ECCF8FFDA99684546384177D5F4EBD8B576522A3734496CB4ECF1D29C58332A203B67B0E0D7A45D2E261C1D2A264FA1E4F1D8A56E53442E2D3142528DC7E6C4B576522A3734496C01FEAB60070718B07AAAC8D6CCA6783306000006214B91CDE0D3DACC9E62422C3C8FC5D3D1CDBF91430A0006407BB1C0A9A0B0BAB1873200001B7CADC0C9BAAF9031000000094F9CBECCC5A1531000002860758A97925A1F041050A9DDEAE6E8DFD2801D00002965A6CCCDC2B89F4D020000115397C3C3C0BBB4873E121C5E9DC6C9CBCFC890372420273D78ADAE9D7C5B789DAD7821041B5587AFC3B9B1B297501200255B8694818CB8E9F2CF8F6C4C37364280C5F1E6CFA87D502D2C2E407BC4F1F1CF8F522D23254873B0D8D1945F2E282029221C47A2E5F0E1A4674F4B3839333D548AD8E7B9A87D502D2C2E407B01FEAC60070718C079A1C7D7C8AE6A26000000051A4D93C8DBD8CBCB9E53302C4680BDD1D4CAC28F3F03000A4581B4BD9985A9B5AF7C2B00001973ACC0CAC6BF862E0000000A58A2CAD4C2994B0C00001F648886988D5A1D001A4CA1D7F3F7E7E6D57E2800042072B0C8C1B8AD993F0000001E4C9CC9C7C0B7AF7E4314195BA7CBD2D4D2B986382620294777AEC0AA6F54779FAB6B1900175B8EAAB9B5B0B2965313002D739D916E99BCE5F8D89E6C4C40394783D5F3EECCA272492D30333C7BC4F6F4D79857272E374E7DC1DFCF94491F292E2F282448A1E0E9CE9F664D4743323038548ED6E8C7A272492D30333C7B01FEAD60070718D078A8B9C7C1A46520000000001C4790CDD9D7CDB38852302F4993BFCBCDC7B983310000154A8BB4BCA087A2B2B1751C00002685B9C2C3C5C57C270000000C62A5C8D5C394440800002C65857F867F521A061852ADE7FFF3F3F3E2741100002876B5D7C5B2B39D480500001B50A0CECBB3C1AD813613205DABC8CCC5CDB88235161C274589B0B79369537DACB06F1D011F628FA3B1B5BBA98A4E1606396F898F6899B5E6FCD2956950463B478CD2EBE7D2A169483033373E7FD7FFF7D1944A2A27365D87CDD8CB8B47242B2D2E25264DA8E4F7D28B4E494B37342D3E529EE0ECC0A169483033373E7F01FEAE60070718E07698B7C2BA985B11000000021B4793D2CFD4D5B2794229264594CAD4D8CAB378280000104D93BAC99D84A2BBAD711A0000267EBBC8C1BFC47D200000001F65A8C6C8BC8C3F0500002D6F977C897646170A205DB8EBEDECEAECD27D1900053780B5B9C1B7AB8F480200011E4696CEC3C2B8A9773D1F3067AAC6D3D1C7BD7B311B17253D85BDC6A8706883A1B86510001E6A97A9B2ADA79D874203003875948E6893B4E6FBD59167453E373E84C9E8DFC291633A28322D5094D9FFF6CB7F4D2E283D6997D2E8C9823F222D2F2A1E2450A8E5F4DE924F4B503D2A2C4258A4E7F5C091633A28322D509401FEAF60070718F0729FBBB8B6A55F12000000021B5997C2D5CFD6AE6D32231E3D8FB8C2BFBFB580270000185B92BCC19A87ABB3A8681300002980B3BBBECDBB76240000001971AFC6D0C990320000003C7890817D714318041C50B2F0F9EEF6ECCC7A140106458EBDC4BFB1B08F3F00000021539CC8C3BDB59A652A15286DB2D3D4CAC8C4782E1B22214A87AEB99E705C7CA0A66B1E061F6197AFACABA9B2944701094077958C608CAFE1EAD7A05E453A384A89C9D8D1C298613B2929324A91DBFEFBCD7F3C2A25336FAAD4DEB8784125342D332D215DB6EAF4D98457525B4338333D56A0E5ECBC98613B2929324A9101FEB0600707180078A7AFB3B3AE6118000000001951A2D2D6D7C9A466371A244B8FC4CDC8C0AE7723000321629FC4C6997D9DAF9A5D0900003683AEC1D2CABA6F22000000176CAEC9D0AF6F27000008307D8488786E3F12102260B9E6F5F8EDF2C9761B000F3C8FBAC1C3B6B09438000000335FA0CECCBDB4985D280E2C6CB5CCCCD4C8B86D301C1A1F508BB0B2996B6482AAA75B14111E6597B1BAB3B7A8813D00084483A28E5C8BAED6F4D8925E434043529ED6DDD5BE915B3B3936375398E4FDF8C27E3D222A4386B8D9E3C87A331934272A1F275BB5EBE1CC84484756463834405CB0E8F4BF915B3B393637539801FEB160070718106F89A4AAA4964F08000000001D589EC1C6C6C5AA5B221829519CC5CED3BFA6681B00002769A1BFBC977D97AC984D0000003185B7C5BCC4B1731B0000002478B1CAD3AA712900000B478A957671604411082A61BAEAF7F3F7EDBE6315050C458DBEC6BDB7AE903705000A34619ACEC4B8B8A4561D0B3170B2D0CBCCCDAF70271819295195B4B8926F648CAAAA630B051E6F8CABB8AFB2A37F30030C50809A82538AA5DCF1D5885F40373A549CE1E2D7B9855943262B2D54A7F2FFFACA7F38221F458EBBDDE1B6732D122926291C2E6AC1F3E8C8794A46594F373C3B62AAE7F0BF855943262B2D54A701FEB260070718206D8F9CAFA88A5308000000002E5E9EC5C7C3BD9254241519499EB8C2CABAA35C1B00002E75A4BDB8978397A7894A0000003688B8C3C7BDB07217000000307CBFC8D2B36E220000104C8E92736F5F3611112968CEE3FBF7FCE8BE681A031D5699C3CEBEB9AF7F2F0000082F62A3CFBFBAB38E531C103481BDD6CBC7C7B1681E101014568FB9AE91675F89B5BA6A1603236999ACA6ADB4AF7938091151869B85527F9AD7ECD3905C3737364C98D2D6CDB98F673B272C3158A5EDFFF7C978412C1E3986BBE0E5B4652D1C312C1E22286EBDEDF1BF7C444765514140396CB2F2F4BD8F673B272C3158A501FEB360070718307B98A0A89F985B07000000002868A3C8CDBBB78D491810245A9ABFBFCAC19A580E00003479A4C4CB9F7B9BA082340000003488B4CDD5CEB365130000003890C4D0CBA65C1700000B56A19C83835D350E001E62C8E6F6F5F4EAAF5A1100044899C6D0BCAFB38A320000103A6FB3C9CDB5A481471B114184C1D9D5C3C7B366240A07194E93BEC19363608CABA15C17072F709FAEB2ADB6B0772F091A5B85967F508297DDE5C2845339343C5A9DC2CFC9AE8157332224365FA2E5FFF5C47E4421253F7FBCE3E3B56C291E3B2938253971C3EAF4C97C363F645836333A61B1EDEDC08157332224365FA201FEB4600707184071938F989784450000000000245E9AC5BEBBA98D471C131E519BC4C0C3C0A4560F00003784B1C7C298739EA5762B000000448DBCCACFCCB3651B000005398BC4CEC3A151110000094D92978179542805082479C5E5F0EBEFDFB55008051657A4C7CDBAB6AF7B2900000D4172ADD1D0C7B692440F103B7CB1CDC7C1BF9E5D1F0C121D5293B8BA98736088A9A6591C132E79A4A9BAB0ADA3701D001A5D8F9B794C8CAADBF3D98C60423C3662AFDDDFC5AC84553C36323E6FB6F8FFEFBD6F3421213D8BC2EFE1AB60260F35291F202A73CDF4EEB971455875653A293470B5EBF1C484553C36323E6FB601FEB5600707185077868B908F874C0000000000266AA4BAB7B5B1842C05061F6198C4C5BDB19447010000398CB1C5B9928096A775240000024990B9C8D2CDB55E120000083F93C0D4CB9F420400001A62A4A47F734D271008256AC4E3EAECF0E8B059100922649EC9C5B8A8A4792D00001C437CB6D3CEC6B483410C1A488BBFDBCFCAB9B5601402091B58A0C0B692696294A6A0510E092D779CAEB6B6AEA2661C0A27638C9A72478398D1E1BC8250373A3E6AB5D8D2C3A275523020253B68B8F5FFEDB76C3117233A93CDE6D9A759261939332E2C3477C9F2E9B9723D587A613E3B427AC5E7E0BA75523020253B68B801FEB660070718606F878F8F89823A00000000013A6F9EBEAFB1AA7A3003031A5BA3BAC1C3B383320000004794C0CEBD916D88926D1B0000093F93C4CED3D2AC530900000E4694D3D9CE95420000001859A8AD8A704B210C063380D0F1EEE3EBDCAC4B0C0D2468AEBFD0B7B99F732A00001E4A7CB2C8D5CCAA79400E16528EC3C7CCC9C0A75E11000514519CBDAE97736B8BB09C5612133F87AEB6AEAAB0A1611502226A939C75487E97C1E2C47A493932406DB8D8C9C29B6A49362A2E4570BDF5FEE8B4672A1E264491CBE6D5A2522717402127192F7CD7F1E1B26733527E633B3A3F79C6F0EBB96A49362A2E4570BD01FEB7600707187077848B86897F3F0000000006397EA0B7A8A0AA7C2C02001061AABDBFBAB6853700000945A1C4C6C5937D8998690B00000E559AC2CED4C6AA601C0000104C9BC9CBC98B420500001F6BB5AD8C66401C000A307BCEE6EDF1E8E29D460B03296BAFD5CAB6AB9E691F00001B4E8AB0D2D8CAAB753F0913559DC5CDC5C6BB9C4B0C0005195C9BC0B2976E6690B8A14708053385B0B2A6AFA4924E0F032A6D9AA2814A7E89C4D6AB6D41342D3E6BB8CECAB8916A3D26242A3D7BC3F9FFEBAF6131202F4797D6ECCF8A42201040282C2C3986D3EDE7B36130537665442F4286CAEDEABA6A3D26242A3D7BC301FEB860070718807E9183958B7F3D00000000014882B1C2ACA7A3662605051F60A3BEBDC5B074280000005AA4C2C6C397748886500200001565A3C2D2CFCBA7550D0000195AB4D4D8C58C320000001B6CA9A28A74410F0B0D367BD3F2F2EBECD090350F06206AA7D3C4B3AD9D6A1C0000285C88ADC7D2C1B4772D0A175491CDCBD4CAC39C4409010B19599DB6B2986B6D96AE8F4002093E88AAB3B5B4B5914808012C74939E7548749CC1CAAB623C272A487EB4D2C8BC926132202B2C3E80CAF9FFE4AD612F191D4BA2D3F0D394411B1A432C23233F8DE6F8DEB560315A7D673A334781CDF3E9BB6132202B2C3E80CA01FEB960070718906E817F7D796D2B00000000054B87A5B4A096975B0B00002869ADC5C3C7AE6B190000075F9FBAC1B9966E8482410200001557B7CBD4D6C49D481800032558A8C6C5C1863B0000002A6EB1B297783A0B020A3A85CAEBE9DDD8D48837050D2C73B5D0CAB8B59C671600002F6997B9DED8BFAB6D3013215998C0CACDC1C2A3520A00091C4D98B5B78E6C7094A29147090D438CAEB6B6B7AB833F09002E7198A58146849CCAD5A9663B32384B80BDD8C4B78B5C34252B2B4187D3F4FFE7AE612C1C213C93CEE4C882411E13452D23263E94E1F6E6AA5D3752766A31324586DAFDEBBF5C34252B2B4187D301FEBA60070718A0818C8A8B7D7238000000000B5394B3B4A098955E2200001E68ADC6C2BAA8672400001862A6C3C6BC98848C7D420000001D64B6D5C4CECA9F480F00092A68B0CDCBC181370000002275BFB490642908000E367ECEE9E8EADDD2862E0310398ABCCDCEC2B69856110001386FA3C1D0CCB9A26B2B0C18559EC1CFD2C6C696440D00001052A4B8B89A777191A992420B0A4196AFAFABA7A5833805002C7093A583507B94C0C294532B1F243C81BACEB5A68959321B1B204187C8F6F6DCA95C2B161A4599D4ECCA833610114D322B314498E1F8DFA6543851776644314389D7F2E5B959321B1B204187C801FEBB60070718B0707C7D7B766A2E000000000C5691AFB29F9C93570B00001B6BABBCBDBAA9681D0000186EB1BCB3B28A787B71270000002D6AB8D3DFD6CCAA491800002D6DA6CBC9C17C220000042D79B5B7A37336080004378AD1E4EDF0E9CA7E251113368CB7CBC5B7A9905C18000238739BB1C8C9C9A65C1D021A679EC4C4C5C1B99B4318000019589DBCB5976C64A2A48B3800115094B0BEBCB2A97B400B08367599A28A54809CBCCA96532B1F24578AC2CBBFAD7E4F312B22243D86C5FCFFE9AC5E270C1145A4D6E5C276331314572E2C26499EE9FCEAA7562C57806D3D2D3E8BD2FAEDB74F312B22243D86C501FEBC60070718C0707C7A796C6632000000000B538FADA99697954D0100001E7CB1BFC6B79D570A0000186FB2BFC4BB9878706324000000337BBDD1D4D7CCA04F12090D337BB1C7C9BD77250000002787B9BDA175340A000A3B93D0E5D5DDDFCA742608163986BBC6CBBFA389400F000D357DA3B8C6CAC69E6117002263B4C6CBD0CFC59A4C030000195595BDB58D7376A2AD8837040D5499B0B2B3B5AB792900002C7FA2A38C5C8B9EC0C5865030242A5C95B8CCB7A77D4B1E2119214B90DCFFFFE1A9622E181948A1D7E3BA6E2F150B51342A2950A5E3F8E4A358365773623D2D3E99DCEDE5B94B1E2119214B90DC01FEBD60070718D0757776747B6924000000001C5F98ADB3A2A7984F000000357DB2C7C2B78D490B00001877B9CBB9BA976C64571A0000003983C2D5D2D3C1A14A2017173972A8BCC4B8782D0000003A83AFBDA27A310B000A4392D1E1E2DAE1C1741E10193785BFC7CFB6A183420D000A3D83ACC6D0CDCEA55F11001F6FACC4D2C7C8B79542090000155AA5C5C0A1797399A9822F00155FA3B8B7A8B09E671C00002E79A5A3855A7FA2BBBC833C22202F5B8CBFCCB59F7B3B24151C1D4492DAF8FFDC9F522E1F184EA7D5E9BC692A0E1D5734293153A5E7F9E0A1543859745E37324695D6F4E4B13B24151C1D4492DA01FEBE60070718E0788079807D682E00000000196CA2B7B7A29B8F430000002777ADC4CABE9E440000001C73BAC4C3C09D685C4A0C0000003787C0D3DDDDC99A411613204784B4C6C3BB721E000003428AC7C7A87A2D0400124D98DADDD9DCDCB55E1A051F4284B7D5CEC3A1733F0B000A4890B2C1D1C5C3A65012062F72B0C8C7C2C1B785350100000E54A8C1BB9C8170979A792B041B62A0C9BFBCAE9C631100033D89A9A6935C82A5B6AA74412319265A98C3CEBCA26A3B2419222948A0E1FFFFD39644230B1C4DA1DFE2B668291215542E2E2A5AADF8FADD9D4F2A4F7167422F49A3E7EBDDAA3B2419222948A0E101FEBF60070718F0746B70797A671D000000002B6BA2ADB0A09295430000002C78B3CCC7B783330000001E77BCC6C3C49C685232050000004096D2E0D0D2C996461F1F24528AACC3C2B7711F00000B3893C2BFA5762D00001852A3DBEAE3E5DBB55B1708273B89B7C8D0C0A8682D0400114C92B2C2C0C3C29C550E012974B5C4C1C5C4BC98350100001C58A0BDBA9C787D9E9E6E2B071B5DA5BECABFA792511100003E8DA8AC99648BA7B4A3732E1600265997BFC3AA966C3C12151D2356A7E5FFF4C98C492013224EA9DCE4BD661E0B075732282552AEE8FEE1A4472C4F695D38354B98E3FEDFA33C12151D2356A7E501FEC06007071800707D726C715E1D00000000276CA1B3AF9DA08438000000317FB8C7C9C080320000002284B6C6C4B98D69492B000000004C9FCBD4D9D2C8944C201B2D5A9AC0CEC4B5701B00000A539BC7C7A56C28000012549ED5ECE7DFDAA4500B1027477EBCCBC8BC9E5C240000104B94BBC4C9C8C9A75417022978BCD3C9C5C8B98A340000000E5198C2C0A78D909E9B6523001567A3BDCDC2A8A0561000064992A8AC905D8799AEA263291C0C205998C1BEB3956F3A211C19255DA3E9FFF8BF8C3D1A1B1F5CB7E0DFB15D2305075E3B2F294FACEEECD89453364F6D65373751A5E4EAE0AB3A211C19255DA3E901FEC160070718107676777B7F6B1F00000000377AA7ACAFA4998632000000327DB6C7C4B87521000000218EC8D2C6AD8A58442400000006519FD4E4DAD2BC8441271F336B9CBDC2C9BA6F1900000F4F96BFC4AB71220000175D99DFDED1D7D4A4571207325293BFCEC4B890571B00000F5B90BBBFC3C4C19C520F0C3884B8D4D1C5C2B2812E0100031C60A0CFC4A88487948F601C0821689FBAB8AEB094530200044D8EA6B19D6976909B86511C120015539BBAB5A29765301A10121C54ABEBFFF6C2813D0D0C154EB2E4E6B0571C0B116939223256ACEAF6D29441244169633E2E4CACEEF5D7A6301A10121C54ABEB01FEC2600707182068736F78795A170000000027729CAFB0A79F7E2F000000267CAEC0B6B680240000002183BCCFC5B8965936190000000253ABDDE3E8DDC28B381D2C3A66A5C5C8CBBF6C1000001654A4BFC8BB681C04001D67ABD9E6DDDBC99F420D0C24518EBFB8C7B996431200001E69A9C3BFC4BEC89C500D0C3783B9D5BBBCBFB07E260000042164AEC1C89986839A925D0D002C70A4BFB6ACAD874302000A4F9CA4A29B6796A7AD995E1C090F265C9CBCBEB19A66321517152A65AAE9FFEABE7B42190C1B53B6E1E0AD5B200811673E2D2B5AB1E8EFD5953E1F3D5E58423561B2E1F0E09E321517152A65AAE901FEC360070718307C76727D80602D00000000417CA6B7AFAA957B370000003289B0BFC7B26E1B0000002B93CDD3C2B5915D27040000001969AED9E4E7E8C58A3C262F45799CBAB3B8B46B0A00001861A8B9BDB06C2700001D5CAADDDDD2DCCC9D430A12315090B8BDBAAA85420F00002168A6B9BBBEC5BF925412053C83B0C1CDC7C3AF7F330000001E5FA6BBBCAB929CA27E501200317AA9C1BFAFAB8640090007549CA7A8966E8A9CA48D50150200145696B8B4AA89602318121C2A57B8EBFCE7C17D330F0D205CBFE9E6A5511409106533293565B9EDF5E1954C2F3B4F4B383958B2E9F1D2932318121C2A57B8EB01FEC4600707184074746C6E6D551A000000064B86A1A6ACA2987D230000003088BAC3CAAF5C0B0000002D8DC8D5C2BC8F4D24010000001663AFDEF0EAD9C17A3C29355081A8C1CBC3AD611600002367A8B6BFA96C1D00002971B3CFD8D9D7C58F3D1715385A91BCC4BEB48E460F00002C75A7C2BEC1C1BF943E1302388DBEBDC3C5BDAE7A26000000186AA6CABEAB8F8E9F834808002982B0BEBAB0A4843B00000C4C94ADAA9C777A8C907236000000085694AEB9A7925925060514205BB6E7F6DEB1712C0B0B205FB4D9DDA1480B0611733928285FAFE6F4D59A492838524E36335CB6F6FFD99625060514205BB6E701FEC560070718506E767176735210000000004B93ABAFB5A8A2851E0000003C86B3C1C0AE6403000000238EBAC9C4B18E5422000000001B75BEE2E8E3E3C37C392D425B80B2C4BEB7A95C0A00002A76A9C0C2AF6A180000215FB0D4D5D8D2BF8D3A1023465D98B5B1BCB47C2F0200013279BABFB7BFBCB79243110C4090B9CAC0BFC2B16B1D0000032A68ADBEB6A7939097743C1307367FA6C1BAB0B0843E0000185894A6AAA07593A1A07E3B0B00000D519DBBB6B6985225170B1C2A6DC7F8FCEBAC682C1A12225FB6DFDE904012081274342B3161B6F1F9D78F4029384F4E3E426DBFF2F6D9A325170B1C2A6DC7F801FEC660070718608084787E8361260000000B5885A4BBBAA7A0761F0000003F91ACBFB8B85B08000000309EC5D4C4BD8B461C000000001D77C9E7E7DCDBB8743835536B8FA9C2BCC3A3550000002D70A7C3C0AB64100002296CA7D9E5D2D9C17D3E0C214D6E9EBFBBC1AE812D0000003874A5C2C5B9B9BF95400A184495BFC7B6B9ABAF6B340000072363A1BFBBB39B9896723300003886B8B8BFB3AD812500001D6198B4A59F778A9CA16F2B0000001E5D9DB8B4A984531A0C0C13276BBBF1FEE2AA632A15112463C1DED89239100C107C3A262E62B9EFEFC98F431F2B4D493C385EBCF6F8D5941A0C0C13276BBBF101FEC7600707187070807E8580570E000000185E93A9BAB0A6997B150000003D8FADBDC0A94F03000000349DCFD1C5B9863A18000000002480C7E8EBDEDBB5733D41527196B1C3C4B3AA57000000337AB1BFBC9D5B0E0000307CB6DDDCD6C8C173260B26587499BAC7BBAE7A2A0000003383ACC9BCB3BAB28A3D0D0B408CB5BDB5BCBEA4732800000A2362A0BFC7B4A09E90672A01003C83BAB9B6B8AA7D2600002169A8A9A9A17384918B5C1B000000095397B0B3A188501006160D205EBBF4F0DFAD6A2D120E1E6AC5E7CF87320A06047B3A2A3164C1F5EFCF9248292C3E4B3C3D6CCAFDFED49B1006160D205EBBF401FEC860070718807F758E897F4F150000001E6B94A4ACB3AD9F771E0000003B94B7B3B5AD58020000003399CED8C9B684350100000000328AD0DBE5D9DCB66F2E34627CABB8C1CABB9E4F060004377DBCC5C0AA581200012E83BEDAD1D6D0B7702309265F779AC0B3BFA0751A0000053881B4BCB9ACB9B98838001552A3C1C8BFBBB6B174230000002564A9BDBCAD9FA38E531700003D95B8BEC3AEAC792D00001A679EB0A89A7B7B88835A1100000017447D9FA6A48247230C04102A71B9E8F5D19F612E1514256CBBE6D689390600037D39262B66BEEEF3D2994122253B45393D76CDFDF8CE97230C04102A71B9E801FEC960070718907783818E80530C0000001F6498AEB3ABABA67C1C0000004294BFBCBDAA49000000003E9CC6CFC3B3823D05000000002F97D9F0EADFD0A95F38376889AEB3C7BBB49F46000000357EB2C6B7A3530C0002337EC0DBCFD4D6B8641F0E376685AABEC0B0A3641700000A3D85AFBAB3B9C3B6832E081B5699BAB9B4BDB5A36C240000102D6498B7C1B2A39D7E4D1500044B97B6BDB9B4A56C2300002874A2A8A5A77384968C6513000000074B829AAC9C8354190A090A1C6CB9F6FBD996572B1D142E70C2DFD483331006097E36253072C4EFF0CC8C49231D33472E3878D5F7EEC98A190A090A1C6CB9F601FECA60070718A07A747D867A4F12000000206E95AEB9B5A89670160000004E8BB4B2BDA74E000000002DA6CDCDC2AE762E0000000000429AD7EAE7E2D39E5D2E416C91AFB8C1C3BC9A400000003488B8C4C396491000004094D1DFD7D1D2A65819073D6D80AABFBDB7A367140000004996BFBDADABB0AC7B300A1C4D93BBB9C2BFB7A85F1E0000083063A0BEB1B8ABA1804A0D0006419CC3C9C1B8A0651E00002C75ABAA9DA478859089520800000008508BA1A69A813C1A0605111E65C1F0F0D69E602611102C74CCDAC586331009058C3C1F2C6BB9F3F2CA8845232C2F39303A7BD2F2F0C8861A0605111E65C1F001FECB60070718B077867E7B6F4E0600000027778DA4ADB0A69C69130000005193B5B5B6A3470000000039A1D1DAC5AB802C00000000003A99DCF4E9E6D4994F2D46769BA5BFC0C4B891380000064890AFB7BE94480900094D98C3D5D7D3CA9B51251B4A7C8EA5B9B9AF9E5D0A00000A4696C1BBACA3A8A4813913185E9BBDC3BFBEBCA6551900001032669FAFAEB5A79B71330000064A91BCBEBFB4A8602200003280AFBDAE9E728E94955F0D0000000D4A8098948E7745120700051D6DC4ECF2D89258371D122E76C9DDC9853108040B803324346EC6EEE1CC8E4A28292D3C33448AD3F3EAC082120700051D6DC4EC01FECC60070718C0838F9595845A0F0000002E7E9EAEA8AAA49D6B170000015A99AEBBB99F44000000003499C5D5D4AC782A00000000004BA2D7EAEAE4D799542C3E7E98B3C3C8B6B78E320000104792C5BDB8914A0500114B9CC1DAD4D4CC9E49171149778FB5BEB5AF965308000007549BC3BAB2A8B0A7722B0C2369A5C3C4BAB6B49760220000183B6799AAB0A8AAA16E2F0000044FA1C2C1C8B3A4621900002B86ACB4AEA06E8D948B4F190000000F41799BA09E81471303040C2272C7F1EFC98D4B2D10102A7DC6E0C1702A0C0008844126347FCDF3E3B5773C27223234334E86DCF5EAB3811303040C2272C7F101FECD60070718D0728080858251110000003682A0A3A2AFAF95630A0000005EA0BDB3C3A14A000000003895CAD0CEB06F28000000000046ACD6E4E1DCD290472C418AAFC7C7C1B5B3873400000A4A9CC6CAB78E410100085195CCE1D9D4BC8D43171B4B85A0B4B7B0B38D490300000858A9BDBBA2A9A29D772D11396D9FBDB8BCBAAD975B1D01001E305F97AEA6ADA998672600000854A6BCCDCBC2A76A1200083D87A1AFA5A56C82897D5A0E000000003D6E88969F8A44090006001F75C8EBE7CB8E432414143186CBE2D0862A090908903826276FC9F0DFBC7F3C222A2C2D314B96E4F6E8B47C090006001F75C8EB01FECE60070718E074878F917A54090000003B81ABB0B5B1AA995F0800000362A3BDB8B1A044000000003E9FCBCDC7B46A1B00000000024BB3DFE8EAD4BD8346274A8DB4B4B9C4BCB8802500001657A4C5C1C2903D0000074EB5CED3D1CEC38A421C30598FA1AEBBADAB8F4300000008519CBCBBA7A59DA8793515306DAABFBDB8AEAC9C4F14000021406D9DABA3A9B28E561300001164A7C3CAC1B99E550E00004599B9BBA9A3728385814F0000000000406D889598833C0D000503227CC7EBE4C48647261C1E398AD2DBC3761D00050C903420277DCFEBD5C07F42212329383D4C97DCF3E0AF760D000503227CC7EB01FECF60070718F081878E8C7B4B120000003A819FA9AFAAA78F550400000067A5B5A8B0A043000000003D97CED2CDB1691A000000000A57BAECEDE7D3B67132204A90B3C4C1C8BFB3772300001D5BA7C3C7B58E3500001854ACC8D5D4C6C38036102C6AA4A3B2AFB0AA8C45000000156AA8C1B7A4A1ABA26222103475A4BAC3B5AFAC9150200004263F739CB1A1ADB3844F0900001E66ABBFB8C5B7985B0D00044E8FB4B2ABAB6C7E8776420800000000416880979E7C3C0A00030A227ACFECE6BB744827171A408DCFD7B96B240604109840303178C6DFD7BB75492A252638325597E5F8E8B0800A00030A227ACFEC01FED06007071800818D968B88420400000B528DA4A6A7AFAA96580000000462A0B2B9B796430000000047A8CBCCC4AD6815000000000F58BCF0E4DDD8C1722E234892C3D1C2C7B8B7761C00002159A4BBBCB1833D0000155CAAD3DFCDCCB57C2E0F316B9AAAB7B0BEB3863B0000001670AEC3BBACA9AEA05E21103A7FB2BCC4C4B9AC914715000A1C3B649B9A9EA5AC874C110000156BA9C1BFBABDA04F120009468BA4ABA5A06E858778430400000003406A7A919F803A14000303237ACCEEECBD824D250D154096D1D8B9741C00000790381A287DD3E9D0A8783D27212C3743529CD8EAD8AF7114000303237ACCEE01FED1600707181073818B967A3F0600000F448DA2ACABAEA08E4F00000004649FAEB9BF9C3B00000000439ECDCCBB9A5811000000000450CCE3F0E9DCB36F311A4693B8C3CAC4C1B8791D0000226FA8C1BDC28A350000176CB5D8DFD5CBB7752B1239789EAEB2ACB3AD7A300000001F5FA0BBBDA0A1A09C601D184A80A2C0BDB0B6AB925721070622466F9A999CA2AB8D450C00001D6AAAB6BEBCC197531300144C98BCB4ACA0637479612E000000000036546E818F77350E0000001D70C6EBE4B4734C2110184698CFDDB86D220000079948222E85D1E1CEA16C3426272530355BA8EFF4DAA7720E0000001D70C6EB01FED26007071820727980866B2C0000000944899AA4ADA39C82380000000169A8BBB6C09842000000033E9DC9D2C7AC5C0E000000000C65CAE3F4DFDAAC6323124393BCCFC1C4BDAF6F1600003875ABBEBDB98B340000166CAAD5D9D7C8AC672515487BAAB1AFAFACB3722B000000286BA9BCB39F9FA0945018144C8DAEB9BEC1BEB092471600032D4F71999A93A9A8813F0300002570AFC1BCC1B48A5014000D559EB9AFA993567977643B00000000002A5D768F9A7233050000092780C5E8E2AF6D3D1211124CA8D5D6B660150005059845233583D3E7C99C793F28212B333D69B3EAEED19F6A050000092780C5E801FED36007071830718F9D9579400400000741849DB4AEAAA48F49000000106C9BB4B0B08E3F00000008579EDBD1C6A75E1200000000126DC3EAF2E2DFAA531D1B4C9FCED1BCC9B6AD6F170000397EB9B4BAB4802700001D6BB6DADCD2C7A86020184781A5B6BAAEB1AA70220000001D72ACB6ABA1929990541B155695B6C4C1C2BEB590441C090D2554748A878CA3A279330000002278B0C3C0B7B692440E0012599CB9B6ABA25E7C7A5F3C000000000034576D878F77340A0002062B87CBE3DCA66A41231D1B5CADD4D0AC62200000069B3D233D87CDDBC195663B291E1F314567B5EEEFD7A0630A0002062B87CBE301FED460070718407B87888C73410400001554909EA3A9A8AA8D4500000004659EB5B4B295410000000C4FB7D2D0BF9B510A000000001667CFE9EAE1D3984B19154B9DD1CBC2C1C1B25F1400004083B6C8BCB67D2F02061F6CB0DBDADBC0A55C20143F8AA8B4B3B3B2A0571C0000002476B5B8B19D9BA58A4D122361A2C2C5C0C2B5AF894C1A0010335A7A9C8F929BA076290000002770A6AAB5C0C38F450B00176AA9BABDAC9A577D6F642A00000000063C6077979A7137050002002486D4ECE5AA724427171A5CA7D6D1A95B1C0005079C3E1C3C90D0E0BE8C613E261C213A3C71B4EBF3D0955B050002002486D4EC01FED5600707185079938F957B3A0C000017598CABB0B7B0B08835000000157AAAB9B5B797400000001359A9C6CFCD9C4800000000001E74CBE6EDE6CF9A43150C52A2C5C9C5C0BEB561070009518EB4C5C2AF83270000246AB5CBDED9CCA84718144C90ACB3B6B1B7AA65110000003581B6C0B19A9C9D8440102E6DA7C2C7C5BDB1AD894F2101093D617B8D80879A9A65220000002B77B0BFC2C1B98A3C09001E73ABBFB6A0964B7776643800000000063E5E7E96907B350F00040D328ED3EFDBA76F3B25152563A3D3CDA7591E00000D9A39184495CEDEB58B633B26251F345074BCECE1C58C5C0F00040D328ED3EF01FED660070718606E787C8269280000000A4D88A0ACB4B0A5762E000000186BA8ADBAC1983D0000000D579DD2CDBE924700000000001F83D1F1E6E7D28E41120D59A7CDD2C7B5C8B3610A000E529AB5B6C4AF6E2302002371BFCBD7D3C1954618134C94B0B5A9B6BAAF6113000000378BBACDB59E959A8C3E122A6BA9C3C6B7B8AFB18D542805134063708E7B7896A6681F0000033486AFB9BCC1B8862F00002B6AA7B6BBA7914A75725A2B000000000D41607790907028010000003490C8E4D2A35A3B20182D6AAFD7CEA9570A00000FA33321499AD0D0A6804F2E2B2D283B5D79BCDEE4BB8453010000003490C8E401FED7600707187074888E93722F00000016639AADA9A8ACA48437000000196BA4BCB9B49539000000195CA8C5CFC192470000000000227DD4F9F9E6CF85381112479DC4C5B5BCC3A75A0700195F9CC7C8BEB371200000277BBECCDAD4CA934014236399B6B5B7B7B6A3550D0000003085B7B6AB9E9F9E7132102F6CA6C3C4C0B5B8B28B5B2809153F69899973758C88621F0000074B8FB7B2AEC1B88D2F00002475A9B7BBAC97487A72582F00000000184B5F6F8B937136050000032D7EC1D9CF98532B221B337CB9D7D29A52150001139F3A285099D1D2A67350311E30243D5990C6E7D1BA7F47050000032D7EC1D901FED860070718806C7E868D6D30000000195790A3B2ACA7AA81250000001D7BA5C4C2BE90320000002261B2C7CFC49A3700000000002183D3F2F0E7CB84370A0B50A9D0D2B7BEC0A14C02001A679EC1D2C3AF6F1400002B73B9DDDAD2BA9540151B63A7BAC2A6AFA49754090000004091C0C0B59C958C6F30123075B0BDC8C8AEB6AF93571C000B4F76868A75708D924D1C0000124788B0B1AFB7B47D2C09001E73A5BDB8AA92507260502300000000284D5F76978F6925000000002A8DC4DFD18D5431190D2467B5D5CB96430F060510A84325469AD3D19B724E34262430497090D9F7DAA67547000000002A8DC4DF01FED960070718907B888D8C67290000071D578BA0AFB2AEA5752C0000001A84AFC2BEB991330000012672BBD7D6C58F3F00000000002B84DAF7E9E4CB7D2D151A53A4D2CAB3B3BB9C4200001863AFC9D8C7A66E1800002C79C1E0DACDBB84300F2867A1B4B9C0BAB18F45000000034493C2BCB59E92976A2915407EB3BFBDC5B7B3A68F5E2B0C1C516E8C8E72708B9454120000184582AFA9ACBAC47E2C00002A70ADBDB4A18B517562411B0000001F395C668392946418000000093A8DD1E4CB914B2723143781B4D4C08C4A1302000AAA45254EA4CAC8986252332D312F45709DCDE5CB9A6344000000093A8DD1E401FEDA60070718A0757B7C86581E000005205E909AAAB6A9965D20000000297CADB9BDB381280000083481BFCCCABF893700000000002690D6FFFBF1CC8231071253A6D5D6B1AFBC994905001B6EACC2D0C0A9610C00023176B7D1D9CBC9862B152567A2BFC3BDC2BD983C000000004394BCC0B8A695926122114890C3C6BCC1BEB6B1946C36191E587B8585796C8C8B46160000194996B2A9ADBDAF762D00003174A5BAAD9F8C40715B3D13000000023A55657D8E804C0F000000023B99CED5CB8D462E1D1C3B7AB9CDC088420500050AA841254FAAD7CE99654F30292C34587EA3D3DFC1906340000000023B99CED501FEDB60070718B06E7276885C1500000010538BA4B0B0AFAB6A11000000176CAFBFB6B9802C00000C3A72B6CBCEC98C3900000000013382D7F6F3E3BE6E1B001153A7C5D2BABCC0974603002B77AFC7D8C7A8630F0007427DBED8E1CEB370210E327BAEBEAEB1BBAC833501000001459CC0C4B99B948467231F4C87C3C9C5C4B6B6A58B6237171F5687938A6F6C84864510000019529AB0ABAABAB36E2200002F79AABAABA28B4A795E42110000000B486B7C89978F4B1900000001489EDADEC67E3E1E120E378CC1D6B485380B060C0EA33C1F59AED0C58B5F3C342B3447658BB0D4E3C38D5B3F00000001489EDADE01FEDC60070718C0727179855A1B0000001E5A94AAADB4AFA86B11000000237AADC1C3B27B2C0000114985C3C4BCB67D3000000000052D8EDAF3F4E3BA6D1E041C59ADD2DEBABCC5A34600002674AEC2C3BFAE5C1200053681BEDDDFCEB35A1E10307AAEBEBAC3BEB58F33000000054A97C5BFB9A49A7C4D180F549CC1CDC8C2AFB3B29767441C285F7D938671658A8136090000225F93ADA1AAB6AD672706033579A6A7B39F883C7965400D000000224B6A718EA38E591100000006419AD5DDBE783A1F16154094CBD9AF823D0800030DB2492C5BAFD6C48C5439372C2A3B6898B8D3DDBA88583800000006419AD5DD01FEDD60070718D0706F6B7F4D17000000175691A0B0B5ABA55F120000002274A5B6C3B77927000019508CC1C5BFB2823200000000003892DAF1F3E2B5641B081C62B2D8D4C2C2C4973900002C85C0BCB7C19D570400023E90B7DCE2D8B4612510367EB1BCBDB0B8B08D3900000007519FC8CDC49C927E4F13115FA6CDCCCDBFB6B4A991733D242E627891876B65807B38010000266199B09AA3BCAF651800003179A6B3ADA98D3B6B4D2B0000000018516A848B947F41130000000B54ACD3D9B978351C1B1F3D8FCDDDB3782404020512A13B2B5EB8D7BD7B4E3A3827283D6F9CC4D7DAB17554390000000B54ACD3D901FEDE60070718E07C61627B4910000000205C8CABADB6B09D5B0B0000002572A3C1C3AA6E2300001C569DC6C5C7BA752F000000000F459BE3FAF5E9B85E13000F5DBEDAD4B3B4C0942F0002338BB2CCD7CA9B4E03000C498DC4D6DED2AE511F143A7EABBDC3C2BBA78324000000144FA2C4BBBAA18F763F111E63AECFC9BFBEBBB5AC97704A1D2E648C908E5E5F84803F0000002D70A0AA9EA0B0A05D110006377EAFB6B3B18D39725A2701000000295D79899A9A844209000000065AACD6D7B66A2F221C23418BC6CAA46B3409020B14B6452E6EB0D4B77E4839342A324A7CA8C8D6D6A96C402D000000065AACD6D701FEDF60070718F06F584E6C4608000000145491ADAFA7A99754000000003276ABBAC8A97A2700001A5D99C5C6C6B57C26000000000E3D9BDCF6F5E8B25C1100195DAEDBCFBAB5C590340100328ABFD0CFBE965813001B5397C8DEE4CAA24905033180B1C9C7C8C4A67B2D0000000E56A1C1C3BC9E94713E0E1B6BB0C8C6C5BDB9AAA597714B2A34668C917E6360806927000000377EAAB89D9FB1A5581400003583AEC0B79D893068441A000000001F5B767A838D7D3B02000000095EA9CDC8B774331609134899CED7A15C2300050109A43E2D79C0D1AE77473B322D355087B4CACFC9975D4232000000095EA9CDC801FEE060070718007751566C430100000013578DA9A9B6AB9348010000003580A9B7C0A56C1700053165A2CCC5BFAA72200000000014489CDBF7F4ECAF521501135FC4DBD4C0C5BD8D2800104095C3C2C7BB91420200144F98BDD1DAC79B40080E3C8CC3C8BDC2BFB17B27000000115CA9C7C3B9A4946E360C196CB7CDCBCAC2B7A3A39986502A426D9291836657766C270000114678A9AA9B9FAEA2530F00053B7DACBBABA38328694A1500000000206786919091733F030000000E58AECFD5AF6935251A15529CC7C69B5C1705090610AD504280B8CFB4733E36312E33538CB8D1D2C2966A462F0000000E58AECFD501FEE1600707181074524B65380000000023598EB1B2A8A6924B000000063875A6BCB5A9661700032C77AFCECABEAE7527000000001C49ABDEF1EDDAA34F14021962B8DCD9BCBDBE8C2D00104495BDCBC2BD8F4101001F549EC8D7DECA962E00114182B6C5B6B9B3A374250000001B61AAC8CFBDA793692C042473AEC1D9C4B1ABA99D9B7F572C467C898E7D64577968260600114E84B8B99FACAC99430300024284ADA8A7A183265F421800000000296286888E9D7936040000000E69B7D3D2A2692E1D101D4F9CCBC9995B19060C0F0DA8473385C9D5AE693C393F33394F91C4DAD3BF845339350000000E69B7D3D201FEE2600707182085535A6025000000001C5186A9A8B5AF8D49000000073B7BA7B0BFB15F1300083777B6E1CAC8B279260000000020569BD2F5E8E2A2490802166DC1DDD9C3C2BF8A2A0016489AC1CCCBB9842D0000165699C5CBD4C98A3408124386C7C5C8B8AFA8791A000000276AA5BFBAB8A49B67320B257CB3C6CECFC1B3AFA38D7F50334D798D92764C5C6F5A240200164A89A0A8A0ACB7A44E0A00064381A9B4ADA08125653C0D00000000326F8C8B979A752A00000000156FAFD1C99A59281D14245DA8C6C29D510F05000205A94A4681C7D2B164463A3333385CA0C4D6D1B77C503A2D000000156FAFD1C901FEE3600707183083625F6835000000001D608DAAB1BEAE9340000000074781A9B9C69C5C1800074481B6D5D1BAAA742600000005255DAAE1F2E7DB933C0300206EBBDCDDC8C0BA7729000C439AC3BECDC48A2F00002761A2C7D1CFBE933100164789B7C4BDBEB1A06F13000000246AA3CAC4C4A6986726062F7CB9CACBC0B8B0B2948A7C5C364B8793907D554E61481500001C5989B0AFA9A8B0944505000D4586A9B4A8997B215C440C00000000306C8F959C97732B040000001976B3C9BF925220211E2063AEC6C99448120000070EA94E428DC6D5AB6C373340353E5EA0D2DFD6B16E432F220000001976B3C9BF01FEE460070718407C54545E2500000000254C84A1ADB5B88B390000000849818FAEC39A501A00093C86C9DCD5C3AF661A0000000B335EA5D7E1E2DC934905001E72BAD8DACED4C48327000B519FC0C5C3AF7721000027659CB6D9DBC187300C1F478AB6BFB9B7B09C650F0000002A6FA7C3C4BBA996591F023387C3D8CBC0B9B6A69D9180513358818C99704E53664A150000236B9EB2ACABAAB48E3906000A457EA6B0AA937023553400000000003571889094956D2E000000001D73BFC4C88F56282C1E1C60ABCDCD914A1200000616A8484B96CCD4A6662F2D2E34406AA7D8DDC8AD6E37272F0000001D73BFC4C801FEE56007071850764D4B5513000000001B527D9AB3ACB0772B00000016527693A7B78F4D1200094995C2D7DEC4AC6E18000000113767B3E1F2E7D2893409042165AED8DFD2CBB476280012509CBFCDCFB4702900023173A3C1D6DEBD761701134087B4C6CEC4AD9F6B0D000000317BB3C2BFC2B29B5E14002B8BB7BFC3CAC3AF9987768658416D8A928A715244503718000223659CB2B7AFABA9893500000E4484ACB4AE9E7E245F29000000000037708F93A1976830000000001C7EC6D7BB8C4F1F26172C66A8CBC68B420A00000E17B15154A4CCD8A55B2B26322C3E6FAED4DFD0A5603329310000001C7EC6D7BB01FEE66007071860744F4F501500000001275185A4AEB2A57B330000000F567B91B5B9954104001046A2CAD9D7BEA85915000000073D68AFDAEDE6D3973904062273BBD2E0D6CAB66B19011A5497B5B9C2AC691D0004397CB5C9D2CFBC721800245B8AB0BDBBB6BA9F6410000006357D9DB4C3C7BA985B170A3A8EBEC9C3C6C2B9AC8F878358426684968C6C4D3839300B00063874A7ADB8A7A5A87C350000144E87A2AEACA471135E2C00000000003F839790989E703200000000227CC5D1B8874C1414162A70BBD1C184380C0000000FAD4A5AB4E2D0AA5C2E242B2F406FA8D4DFD3AA63332D2C000000227CC5D1B801FEE7600707187072574E4A0500000000214B86A5A7AEA970210000001F486F89B4B1834108001257A4D1D8CBBC9D5A1E0000001B4174AFE1EBE6CE89350A092770BFD3DBD8CEB16A2000175D9FB6BFC4A46B1C00073E7BB0BBD2D3B87B16001C518FB8C3C8BBA79D5C150000003878ACBDB8BFB69A571C0E3A98BECED3C1B8AE9B837478523C6D939588684B3745330E0B0C387AA5B1BBB4ABB2762D00001D4B88A4B5ABA46C155530000000000052859AA8AEA3742A000000002F90C7D0B3824B1F1D18327DBBD4C788460D00000615B05168B0DAD89F53262A37303D73B8DAE0CE9E562E242E0000002F90C7D0B301FEE860070718807350453A0000000000264D6A9CADA7A7701A0000001C5D7D8DA7A7782B00001058ADDADFDEC19D5D18000000194F82AFD6E5DED08C3200022974BFD9DCD0C7B06115001C60ADC0CABE9C5D13000A3E82AAC4D8D6AC6D2508205A90C5C2B9CABA9C5D0600000D3372ADAFB9BEA4894C1715449CBFC6C2C8C2AF947279795F437C90978B744E3731180B060E437EB1C5BABAABA3701900001C578EA8ADB1A66F1157310000000000508C9DA3A89A712E000000093E8ED0D6C180431C211A2B77BACDBF8535000005020FA65870B9E2CF98552A283533467DBCE3E5D29B4F27242C0000093E8ED0D6C101FEE96007071890726657470000000000365C7EA4AAB7A6730F0000002D66747DA2A97A3F00001950A6D6DED8C2AA611A0000002A5489B5D9E2E0C7843403003475BDDFD4D1CCAF5B13001960AAB0BBB5965311000B4A8BB8BACCC6B0611009265C8CBDCBC5B9AF9A5C0F000015456F9DAEB9BFB28F4A12094796BBD1CFCEC3AF8F736C6D514379969E8E72462D36270A0D154983B7C3C4B0B29F602200041D558A9CA3A09E680E582200000000004A899BA2A299742C000000054297CDCFB47638141C1A407CB5C8B77D3A1100000010AB5679BCE5CD954E252728364E7DCCECE1CF8C4225192C0000054297CDCFB401FEEA60070718A07C6B5A43000000000235547EA1B5B59C621200000029677A849C9B652200001952B2D5E7DFC3A2661400000A295389BDDEE4DDCB883609112D77B8D1D7C3C7AC4803001E67AAB0B8B18C420B000F5093B4C5D2D2AB5C130A326995BDC7BFB7A68F5A100000224B7897ADB7C9C58F4A0D0944A7CBC1C7C0BCB18F63716D5145739FA08A72462D29131000154D8AACBAC1BAAD95591B0106255F8C9A9DA9A66C0C5A2600000000004A93B5B5B39A6C29000000034392C9D5B3783E1714233A84C0CDBB7030090002111BAC6185C7DFC58F4720262E334985CFE8E7C88E482823290000034392C9D5B301FEEB60070718B06F66543B000000001446547E9DB6A9885402000000266C7C7DA098611500001E63B1D2DDE3C7A9691B00000E2F6891B9DEE3DBCE782902023772BADED9D3CEA34611022D6EABB6AFB4933E02001C5A92B1BBC4BD9C5C120C4276A1B8C9C5B9AB91460100002C497190A8BABDB1893D100E569DC5C1C4C9BEAA855E636857508098A19D87482418100501125191BDCEC9B5AB996918000025607E9294A49E6609582800000000004894ABB1B0A6762F0000000853A1D2CFAE6D341723243E85C3C7B8712B0000010C10A26290C9DAC58C512824272F4287C6E5E6C8863A1C222C00000853A1D2CFAE01FEEC60070718C07759532A000000000040597798A39E9550090000013D7B7A80918E4F1700001D5AAFD1DEDBC39F5F18000009366598B6DBDACDC37F29060E2D7FC3D8E1D3DBA0510C072E6CA4B9B7B682350300165CA1B6C7CEC899460314407293C1C2BEB8AF974904000425507394A5ACBDAE8F40120F58A2C9C5C5C2C1AE81505362484D89A2A89B7B4E1F110A000D275897BCC8BFC2AE955614000F2C638A9598A19E680F561F00000000004D9EC4BBB3A371280000000E4CA7D1D6AD6A3011162B588EBBCCB4722B0900000617A9688FC6E6D59D52231925303E82C9EDE6C38A3B1E1C2E00000E4CA7D1D6AD01FEED60070718D07561532F0000000018505D6F92A7A37E360000000043777F7797954A0D00002B6CBADCE4E5C7995B0C0000093E709CC3DFEADCC37E2E0D132D7CBDD1CAC6C49A3C0B0C406F9EADAFB27D2E06001969A1B5CECCC690450F0D427BA9BCC0C7BDA9904700000330536C869DB1B3B68A3D1D1B61AAC4CCC8CEC6AB7346535D49568394A49B7848200C03080E246097B7B9BABBB5935A120404346F728C949C977013511C00000000004C9DB9B2BAA56E25000000145EAADCD1AE5E321121376399CBCEA860280000000313A377A6D0DDC3843A1A1A2A2D4990CFF2EBC78E47181F260000145EAADCD1AE01FEEE60070718E073675320000000000D4F616D91A3A28236000000023B7D7E7894843F0700001C67B1DEEAE4C49352180000103F74A1C3D4D7D9C3832F0111327CC0D9CEC4C39C3C0A04377CA7B3B1AC78260000266E96B2C1C1B8873C0F124080ABCFCCC4BEAC83370000103059708EA7AFBDB286370F1C63ABC0CDC3B9C1A2713F385C535391A3A7A9894F1400000A1A2465A6B8C5C1B9AC8D4D1603113A6C777685989865094D1900000000004E96B5BAB7A666220000001663ABD5CDAE683016253B5C9ECCCBA0641E000003011BA670A7CFDBC2883D21172A284498D5F1EBC47C2E1C162100001663ABD5CDAE01FEEF60070718F0756D5624000000001E4B636A92A9A57A2D0000000A4F868D819479340000002566BCDCE3E8D0954F0E0000195D91B7BECFCDCCC17E340A183D85B7C8C9C7C3892E060E427DA2A9ACAC692800002060A0B8C0D2B2783514205584A7C1CCC5BAAD833B0000103C555C778FAFC3AC812C0C1662ABC1C5C5C0BEA4713C364F495C97AEAEA7934E0C000007132564A2C1C5C5BBB2894216040C45718275829B975E104D1700000000045AA7C0BEB6A16B270000001C68BADACFA36A2F131E3C6EA5C9C9A4601F0400000014A17EB1E0DDBC7B3611191D234E9AD5EDE2BE7D3322142100001C68BADACFA301FEF060070718006B635012000000001D546260849E9A6B200000000B4C8A837E9E79290000002571B1D6E5E4C192490F00011E5498BDCCD5D5D3BA7B2A0A124887BBCCC7CAB5822A02124E86AAAAA69E5D1E0000356FA1BFC3C2AB67290228659BA6BFD1C7B1AF832D0000225160677C93AFBEAC7524162A6EB0CDC9C7BEB2975F2F3240546595AEA3A693520C00000E1D2F74A0BFC3CFB9A57C390F0514487D826B758A8A5D0A521A00000000004F9EC1C7B59F6C2C0000002871AFD6CF9F6930151D3D72A5CBC9A65E1E0000000A25AD86AECECFB4703117181C2456A4E7F6E8C77C3E1B1A1E00002871AFD6CF9F01FEF160070718106F6C5915000000002A656C6A7F989E651F00000015608F8886937027000000326BBBD8E0D0C38A46070000255D9EBDC5D8DFD7B8813009225498C1C7CBC7BA852100175487A7A6A8984E0400003576ABB8C5BDAB6722002D6A92B0C9C9C7B9A3762F02001A48676E7393B8C1A26A250F3274BDCCC7C2BDB7A15A242B504A6696A8A7AA95590B00000D16357BAEC0C3BDBDA2743C0D0210517E79617386945B13520E000000000357A6CDCEC09F6823000001327DC0DDD0AD672B102C4B6FA7D1CDA35C1A0000000021A594C0D7CEB172300F0D2033539ED7F2E9C9853A241E250001327DC0DDD0AD01FEF260070718207067570F000000002D5F6059708E90671E000000205B91958A9568230000002D79C2D8E2E2B978380A000B296CA6CBD1D1DDC3C87A230F254B8EBCC7CDC0B7801A001F608AA9A7A7863C020000427F9DB8C2B6A251140A3380AFB8BAC9CBC0A5711E0000255560666688B0BDB2712D0D327BB1C3C6C4BABBA25A242344506DA4B2B1A8995105000005133681B3C4C6BAC19F6D2A0A09165182775E6182925F133F05000000000056A1BBC0BEA36B270300003B85C9E1CD9D612D121D4E87B6CBB99656110000000025AA98C5E1D4B26B27131A182857A2DCF4E9BB763113132200003B85C9E1CD9D01FEF360070718307C705607000000003C69615E73979058120000001F5F91978F966815000000357DC5DDDBDDB8843C0600083E76ACD2CFDECECFBE7E240D306099B6CCC9C1AE761200135A8BA19F9E7D330000004084A9BCC5B998440F0A3984A4B9CECEBFC3AD6C200004295E70565A83AFCBA2642A192D88A7C0BECAD1B8954B0C0E2E4663A0B0BCAD9C5D0C0000021A3991B6C7BFC1B8AD692D0C0520638C7958577A915B0C4C0D000000000854AAC8BDB99A5826050008428CCAE6D19E632B1F285789BAD1C189420A0000000031A6A4C0E0CAAE5F2812151E2C58A4EAF0DEC0742C1814250008428CCAE6D19E01FEF4600707184086805C0C00000000547A77656990925F1A0000063367A4A2969E6918000000327FC8DBE4DDB3632706000C3E82B4C6D6D8D6D3B4752F1C365C9AC5C9C7B7AA700F00256F949D998C74320000074487A1B9C8C188410E01428FB4BEC5C7BFB9A65F1C00002C5F7B595B7FB5BF9C622915378BC9C6BDC0C5BF99501A1B34457BAAB8A5A392560A00000B164B88B4C6BEB4BB9B5B250C09256D9671434B71905A144005000000000662AED3D0C6A0571E0400134E97C7DCD49E6A3128316491B9C8BA853E050000000C26A4A9CBDACC9156200E080D1954A8E8FBE8BB732D14121B00134E97C7DCD49E01FEF560070718506D713E00000000004B70704D5F8A854C040000002D74A4A6A4A058140000003C7FB7DAE2D9B068280200154988C2D6DCDED3C4B364231C386E99B9BABCB6B5641300256F8FAA92957530000009519BA3B3C3AF7F300100469EBFC1C0C4C4BD965B1300083C6980615380AAB6935A1B164891C3CFC9C8C2BB94410B1B335176ACB5BAA597590D000013204B8AB1B1BBC0BA884E20070A31799677414C738F5711450E00000000116BB3CACCC0965B1E0102175A9CCBE1CF9F643931326C9BB8C9B38737080000000025A2A6D3E3CE9A5B1F091C162260ADE4FBE8B6762C111A2202175A9CCBE1CF9F01FEF6600707186081774A000000000858857D52649280480000000C3C7DA7ACABAB5B110000024088C3D9E5DFB261220400185CA0C8D9D9D5C7C4A7673021456394B9C9CEBE9F580D002B729D998988671F00000A49909FBBC5AE7A280604549BC8CBC2D0BEBF9F58140005397C775B577DA9B79951221852A3BFC3CBCEBCBA973D151F3852759BADB2AF94510A00000E224595B9BFBEB8B18C5413000A32799870393E7C8D5410500A000000000969B3D7D0C4954D210503185FA1D3DBD6A1694939406992C0CAAE793500000000002C98AFD8DCC68C3E0F020D171F63AFE8F2E0CA7B3113162503185FA1D3DBD6A101FEF760070718707A7639000000000B608A71495D917E390000000B4F80A7A8A3A35508000008417EC6CED9DAB95C2901001A5CA5CDCDCED2CCBEA2662A174371A5BEC0B2AEA0570800347F9E8F8E825A0E00000C5397A5B5C7B5722201094FA0CCD4D0CACCB795490100164682845F517BB0B8975A201F4A96C8D2CECAC4BE903501133852779FAEAFAF99551500000F225A9BB8C5C2B7B185491F0810357495683A426C8A4D0E440E000000000861BFCFCFBE9A551C05012066AED3E9CCA57654384571A1C1CDB57727000000000030A7B7CBD1BC8D44181415232463B0E6FAE8C07B2F111C29012066AED3E9CCA501FEF860070718807F713A000000000B6784724D497D6F2E00000014557FA3A4A596570E0000114E8BCADCDBCAB55E1804002065AED3E6D0CCCAB89F652118507BADBBC1BCB2994B05073C859B868D7F4D08000011579DB5C3C6B4731E00075EADD1C8C8D4CDBF923E0000124D8583544471B7B78C47222761A3D3CDC4C5C6BB8F3E0D0F305C81ACAFAFAF995810000012255A9EB7BCC3B5B182351400163D8199672E2C608F53104A0E000000001177BFD5CDBA914F2304082B6AAEDDE0C89E73594B4873A9C2C8B27B2500000000003B98AFC6CEBA894013011113256AB8E2F8E3B66C310B1F27082B6AAEDDE0C89E01FEF960070718907B6E350000000017758D724547777030000000236088AFB1AEA352040000114B94C2D5D7D7AD581703022A6DB1CED4D5D3CBB996512D286090A7B2BBB6AF8D4201004B8B998C6E6A3C0700001763A0A7BEC4A55D1400025FB2CFD9D7D5D1C79B42030015548B865D4A78ABA88244182C5E9CC9D5CED2D7C68F33000A3E6790A1AEAFAC91460400000F234D9BBACFC5B6A57A300C010D488D995A313165864C174309000000001B73BFDED0B58B4D1D040B2D7DBBD8E2D0967558525382AABCC6A0642300000000003C9EB1CEDBB97C390B0913162268BBEBFDF1C870311D271C0B2D7DBBD8E2D09601FEFA60070718A0686323000000001B6A8C70333F755D23000000206496AAB2B29D410000000A5396CAD0D5D3AB531400083072B6D2DCDBD5CAB68F51282B598BABB7B9A9AA8E3F00004587A18D7868340000001763A1B9C0CBA3540400126AC1E2DBD2D0C5B3823600001A5F96905B5174ABA176341C336CACD7D2C4CAC3B683320309406B91A9BABCA88F4F0C00000A24509AB6C6B9A69E70280802134A9297612C347A914D17430F000000001E83CEDFDABB874B1D03063682BCDCDDC59D745A4F6896A5BFB49F652400000000003B8CB5D2D6AE742D090A15202C77C3E8F0E4BC7831222424063682BCDCDDC59D01FEFB60070718B0786925000000001A6B89694246715C160000002D6B96AEB3B99C3C000000175899C6CED7D3B25212060C357CB2D4D7D3CBC6B07846222F6A99B8B9B7B3A78A3600044C919F886C52250000002B70A2B1B6CDA0520C000C68C3E0D8D4C9CEC48D2D0000186590945D547AA59D6A321F396CB1D2D9E0CACCAE7D29000941769EAFBAB6AD88400700010F305493B8C3C8AF9E68210F0C25599AA454252E7481411A3910000000002A87C5D5D0B4843C19000C4387BEE6EBC29C716A62608BAECBC1A1611A00000000043E9DBCD3CEA76B260B0B1D1D2D72C4F8F3DEB972241627280C4387BEE6EBC29C01FEFC60070718C076641C000000003286906841496F53150000003A81A0AFABB2943700000021629BD0E1D2D4A45813000D397FB8CFD0D5D1CEA36F432540779BB0B7A9B3B385390000518E9A896A531C0000002E73ABB7BBD2955903000F7FC8DBD4D7D4CAB4862B00001E62A29D714C6FA998662A1E3B81B5D5CDD1C4C4A97426000B4F7299B8B2A5AA853500000913234696C3CABAA399672B0E0329699FAE67262B6887461C3C05000000001C80C8CFCCAF793D1300105092C9E8DEC69B6F675C6D8CB3C7BD9D590500000000004097BBD3CBA45C240D091720367EC7F1F9DFAE6223232F28105092C9E8DEC69B01FEFD60070718D06D5F1700000000357C936F3B3A624C14000004438CA8C3BDB5933100000024679FC7D8DBD2AF4F1602144186B7CCCECEC6BCA16B30224485A7ACB7ABB1A7842800085C99A0906A49140000003881B1C0BBC39B460000196FC1E2DCDBD8CBB17A25000022639995654E78A7975C27213B83BED4D3D2CCC7A87D1F00135092A2BAB1A9AF893D00000317284E8CBCBFBAA5895A2303001B5AA0AA59283974873A133F10000000003797D2DACFB37E33180818579CC4ECE6C68C7A7C6875A0B4C6C492500600000000004B95BCD3D59858200B10241C307CD0EDF3D7A5682923272A18579CC4ECE6C68C01FEFE60070718E0715E0E00000000337C88723D3D6144070000004D91B6BEB5C08A2B0000022566A1C4D1E1D5AD56170112418CB8D5C2BCC1BF9D602C22548EABB5BEBAAEA47B1E00105F9F9E8963340B0000003D8ABBC0C9C18D3E0000197ECDE3D8D8DCCEB9751D00002968AA98635474A8903F181D4B82BCD2D7C6D2BD9D6220001A5E95B2B4C1BBA77F2F00000813275599B3BFBCA68A571E0D072568ACA7561D32788341173B0B000000003A98CED9D0B57C32100116579DD1E0DABB8D757C6B7B91ABBFBA8F450300000000004B97C0D0CB9B4E18030F161C2E8BCEEFF5E3A5713526242816579DD1E0DABB8D01FEFF60070718F079560C000000004A8D9C7E43426B4B0C00000C589FB9C1B7B27F27000000316EA6CBD7D5D9A0521E08245195C2CCBFBABABD9054232D5898ACB6B7B3A6A06D1D00166D9EA18A54270400000C4595B8C9C5BC85370000197DCAE7E2D3D3C3A7611500002968A2A67D6487A37E3F23214D8AC5CFD0D4CFBD9B61190011609CB8BBB1A5A57F2F00000913244696B9C8BCA38D4E19110F2E76B0A65D2F426F7A381740130000000049A1D0D7C4AC773013082564ADD4E7DDB5866D7073849EBEB7B388410800000000005892C0D8CB9C5217041520183489D0EDE4CD9F5D20282A292564ADD4E7DDB58601FE006107071800755413000000004C92987A465278440100001863A1B6C3B2A9732700000A3D78ABD0D4D2D5905E2715215496C4C6BCC1C6B1773E1D2F6DA2B5BABCADACA46E0D000E68A0A794582D010000084A9CC2C8D3C87D2E00001C8BD0EBD4C7CBC6AB620C00002E7AA8A98061839D762A0B265A9DC3CED3D9CCC590591600226AA7B6B7BAA6967120000010142C579DC0BEB0A28C531C0E083480B8A357304881783D144726000000024FA3D1E1CFA9713914092774B9D8ECE0B48274747E8BACB8C1B39040000000000008699FB8CCC1874510011723244491D7F3E8C89D6527202B302774B9D8ECE0B48201FE0161070718106C41000000000051A0A27B464E69390000002464A9CCBFBCA6681E0000073D8BAFC9CBD4C8965B25192E65A4C6C5B2B1C6AF813B1B2C6BA1BBBFBBBCAE9F610600136992AC9859280000001353A1C7CBD3C37B2700002781CAE5D7CFD5CCA3590700002D71A5A5796A809573301D36699FC4DBDDD6C9C89E4610001675A7B2C1B7A39F732500000E132F589BC1CDB09C823C0E05002D79B5AB57303178753C213F130000000551A0CADFD1A85E2300002D72C3DFE3D1B073637D7D8CA3C1CCBD843A00000000000B6398C1D9C9873D1000131C2A4494D5EEE2C498592B2E31282D72C3DFE3D1B07301FE0261070718207D59020000000F65A5AA935C5E6F3A0500002C7CB4C5BDB7A45A1100000C478DB8CFCFCFBB8E5E3219306B98BBC1BBC5BEB273321A337CACC5BDB7B8A99C5C05002176A7A38C54120000001F64ACC6C6C9BC732000002A86D1DCD1D4CEC19D4A0600003375A7A98F7A90946A2C16326DACCAD2D7D4CBC08D4A1300266BAEBBB8ACA8975C1C00000C13325A95B9B9B0A78742130F0C3785B3A25E2C40806F2B1740110000000857AADADCC49D62280E113D82C3E3E4D3AB796E79798EB5BEC7B680310000000000186C94C5D7B780371003102A1E39A4D1E5E8C6995A36212B2A3D82C3E3E4D3AB7901FE036107071830824A0B0000001876B2B69568696F3D0E0000307CB8CBC5C2A4661700000F448CC3DBD5D0C6A162381A2C6AA0C4C0ABB4C6AF6224113787AEB9B8B5AEA89D5D03001880AEA69955110000001B6EAECEC7C8BA6A1C00002995D5E4D3CECFC29B470000073E77ADB09D787C94531C123571B1CFD3DEDAD4C68A3F08023286ADB8B5AAAD914E150005141B28549BB4B1AA9A73370E0F0E337FB4A46535537E75391B44130000001767B1DADCCFA263251515478FC5E2E5D4A7735C768194B8C6C8B37E330000000000297B98C6CDB1762F0C0418282E50A7D7E4D7B88948191D2D33478FC5E2E5D4A77301FE046107071840733E00000000226BAEB6986D716A360300003180CCCFCBBB985D0A0000185499C6D6D7CDC49A6E462B4586ABCDC8A8B1BC9F5412023D87B9C5BDBAB8B4A05600001F80A5AB97570F0000002376ACC8CFC7B2651500001C7FCBE5E2D4D7C792420000003776A4B39C858A87511B103B7DAECFD6D6C8C0B4893600023B8CADB2B1B1AA8D52100001171D3861A4BABBA8966F2F1611113A84B3B65F36528971312043120000001062B2DEDDBF9763210F154091CCE3F0C99B6B5D747C9FB8C8C7B9632000000000002C8E9CC8C9AA7038060013202757ACE2EBDAA0864D283030374091CCE3F0C99B6B01FE056107071850734101000000257DC2D1B27E78743104000A3893CAD9C9BC953E0200001B5CA3CAE5DEC5AE8E754A314B7BA6CCBDADB2C29B4A1103469DBCBCB6B0B0AFA05C000023719FB19657140000003387AFC5C6C5A3581200002082C8DFD5CDD2C38E29000008426AA6AE97898A8F4C1D204E8ABBCECFD7C8C4B87C420C024096AABAB6B1A3865204000C1B223B629EB9B2A19C6D270A09163897BCAC6140598C77321A3C170400001F6AB1D2D7C38F53210F1A499DDEEDEACE9A67626D7C9CBAC6C5A872280000000000399092D2CFB5721E04021A2A2D63B8E2E7BEAC7E4628212E32499DDEEDEACE9A6701FE0661070718607A410F0000053C9DD3DBBD8B7E7A3F0C00114D9ACCDAD8BF8F430300001D5EA3D8DDD9CBB48B7A5735508AB7C5B5A9B7B8964207034B97B8B6B6B2BDB4994C00003084B2B499530E0000004281B6CBC9C6A1500A00002590C8DCD0D5C6B783370000073F76ACBAA5939181431017458FBFCDD4D2CAD3BB812C00054A8DA8B4B0A9A7954D08000621213A70A1BDB0A89B5E1D1209163E94B6B4623966855E2D184317040109277CB7D8D7C19152230C195CA5D7EADEC99967627A80A7B5BFC6B6712200000000033F9792D2D8B36A1D000015253868C0E7EBCBA47C44231F36435CA5D7EADEC9996701FE076107071870723A0C0000104BA9DEE6C39791873C0E00174CA4D4E4D2C8923B0100002663A1D0DCD8C7AD898A63425695BDBDC5B4B4BE934206034599BFC2B3A8AFA592450000337AABB19F51060000043D8DB4C6C1B592460300002A81CAE4DACED1B8772100000E487AB0B2AF99846B360E1B5C9FBED4E0CFD0CDB781390A024290B4BAA6A39E823D09000720274573A6B4A7A8A1672A0B0D164B91BCA362416E895825203B1201090A3088BCE0DDC1843A251C22549FD7F8ECCC8A5D556E7FA1C7CEC7B473180000000006449B88CCC8B16C23050C0D22296BC6E5E9CFA26B4529212232549FD7F8ECCC8A5D01FE08610707188071471606072766B1EBEAD0ABA3813B16111F5EA8D7E4D7CE943E0000002B71B2D9DFD5B8A3879B6D42548DB6B9C7BAB3B38935000052A2BDBBB0B6B1B69E4400002C84A4B4954C0C0000054694C1CAC5B997340000002D8AD5DAD3C4C3AE7120000015445FA6B2B79B8F723614265EA8BDD0D3D8D2D3AF89450C0A55949F9FA9B1A5823F00000C2030567EA6AEA29D97611A080E19539DC0B16C4C6C8155291B44171109153391C9E3DAC08B4D241E2A6AB1E9FFEAC98E6A5D6D87A5CED2CAAB6E1C00000000004EA297D0D1AC621A060014223D77C5E5E9BD91703E151E28386AB1E9FFEAC98E6A01FE0961070718906E41161219336AB3EBF2DEC3B58639100C2E5EB2D4D5D5CE8A3300000B346DB6DED8D3B29882946E576BA7C3C4CBB3C6B97729000053A3BFBDADAAA6A78A3D00003C86ACA38F4B080000115B90AFC2BAB082310000002C88D2E6DACBCFB1671C00001D4A7CABB9B4A98564250B316FAACDD4DCCECCC1BC953D00115D9DAA989CA19F793502001026315C82B0BCA59E8B521C03001751A1C6BB78546B8C54202946210E151D4CA3D3E8D9BC8A4223193377BDEDF8F1C3865B5B6C80AACED6C9A66617000000001563AE82C8CAB15F0D00001423377FC9EAE5BC8B5D3B2227373777BDEDF8F1C3865B01FE0A61070718A07C4F2F1E244181D1FFF9EED0C48F3B190F2E66B6EBE9DFC687280000093482BEE1EED4A38D8B9F7E566EA6BDC3CFB9BCB8801F0005509ACCC5B7A9B1A27F270000418CA4A493440300000E5A99BEC2BFA67D300000002E88C8DED4CFC7B65F1600002A5179ADBBB9AE8F5227113179B1C8D3D4D7D0C4B9814609025B909FA4989E9F6D23000014323E6788B5B0A2AB894E160908245997C1B26B527C854F22214729160F2558B0D8E1D6B17842242A3F74BEF1F0E8BE8A5B4C5C7FB5CFD5C7A85A0E000000002172B78ECACCA85B16000C16264690C9E5D8B07C593220212D4174BEF1F0E8BE8A5B01FE0B61070718B0704A3625315088D3FFFFFADCCC934421113662BBE7F2E9C581280000133E81D0E3E7D8AD89869C836479A3C2C6BEB5C1B2772D000053A3BFBDAEAAAFB0842F00003C87ADAC8036010000176CA5B9D0BCAA72250000004096CFE2D9CFC5A44B09000128607BA3B9BFA990591B0E3E81C1CCD2D2CECDCAB89C4D0E0C5A968C80889A936C28000118383E5B81AAA8A29C8C430D04071655A4CAB67A5F7F8A471926492514263068BEE0E5E3B472472B294684BCFAFFE7BD8057526F8EBCDFDFD9B16D10000000002173B97DB5C69C53140006112E5292D1E3D8AD7A533D2526364684BCFAFFE7BD805701FE0C61070718C0725235363A5EA3F2FFFFFCE7C98B411D123274BBE4EEE6C5772800000B4887D7E8E9CE9C787BA18E687AA8BDC7CBC3C7B37517000B589DBABEB1AEACA984260000418BAEA77935010001226DA9C7CBCAAB701E000001358FC5D6D0C6BDA35305000D366781A9B8BFB3834A1C093C90C0CCD1D0D1CEBBB39E4B0C186F998A80899EA171250000163648739EABADA7987B3709000E2561A5B9B57F66797739122B4F2C2A343872C4DDE7D8AE7B502F2B4E84D6F8FCF6C4805D526890BBDDDACC9E5811000000033477C179C2CEA250150007213B6BA0D7E0C9A06C46392527334884D6F8FCF6C4805D01FE0D61070718D072502C272E61ABF6FFFFFFE8C6893E24263E78CAE6EBE2CD801E00000F4D89D1E0EAC88D6B7BA0826C91B4C3C7C6BBBFAD6810000365A9ABB1B7AAACA9761C00034891B09A6F2400000A4683B1AFC8BBA65D0B0000034396D1DED3CCBE9C4B080010416F88AABABFA67839120E4397C2D2D0C8C9C0BEBC9A5010186393837E829AA2681D000630444F6F9BAFBCA5A07A3307010A2167AAC1BA7962808333162C543A2B2C4288CDF3F5D9A76F4F352F519CD6FBFFE7BB86575C6D9AC5DEDED1A5510B00000002387CC277BECB964B140109193E7AA9E1EBCC96643C2B2622253C9CD6FBFFE7BB865701FE0E61070718E0675541394B75BAFDFFFFFFEBCA7E411F2F4982CEF3EFE2B86D270000124194D3EAE3D0866575A8917992BFC9C4C4BBBEAC6813000C61A0C0C0ABAAABAF781500074D91A193631D0002143E86A6B4C0C49F5506000000389DD1DBD2CFC5933B0400204B75829FB3BDAE7330030C489FCEDED3C8CDCDC2B7A2450B1D74A0876C739494591A00002B4453789FB3B4A3A46E320A06052163B4BEB97E72826D3914354E3B3D475090DBE9E2C8AE734C36304B9BE2FFFADEB07C4F4A6A9CCAE2DBC59C5110000001084491CD71BFBA973A080312193F78B9E0E0CE925C3C37273037479BE2FFFADEB07C4F01FE0F61070718F07C5E4E50608BD7FFFFFFFFFCCF834524305F8FC6F2EFE7C17126000019529FD4ECE3C7866178AC938197BCC9D8D4CBC8A85507000B6AA4BCC0B7B1BBA36E1500084F86A598641A0001234386B1B8C5C693490300000F4CA3D7EAE4CFC78D3607032A4C73819EADB3A9692E0C175B9EC6C8C9D7CBD2C3B7975418216D93796870909055160006344A537DA2BDB6A99C742E0400102068AFB9AA817387662B163D55453E495FA0DEECDDBEA57753393356AAEFFFFFE2B27F5B5A6D9ACFE6E0C1924B090000001555A1D26AAFAE86390F0A192C4C83BDD9DABB86563A302F2F314EAAEFFFFFE2B27F5B01FE10610707180076533C496090D1FFFFFFFFECBC743321355A92CAE9EDE6B264250000135AA3DFEDEBCC865170A28986A1C0C2C7CCCBC19D5106001065ACB8BDAFB7B6A2581000135B8FAD975112080F23548FB0B9C7BC8E3D0200000C53A5CBD7CFC6B79032090137618B8A96A6B1985E1D061F5EA1CBC5D4D5C9C7CBB89D4D0D2672906A52628487571100003C526187A6B5B6A9A1792304050F327BB4C7B688758A5E1E11305C4E485069A9DDE8D9C6996D433C394EABEEFFFBDFA17561596CA6CDEBE2C4944109000000165BA1CD62AEA67C390F000E234C8BC0E5D1B97C4C3735312F3648ABEEFFFBDFA1756101FE116107071810735446496597DDFFFFFFFFEABB7F3C2E3D6EA3D3EFEEE8B5611D00001C5BB5DEEBE6C170476EAA908AAFBFD0C5C2BFB28D4900000868B9C2B6ACADA9A65813001A6A98A67D440F001334629EBABDC9B48432000000115EAFD9D0CCC5AE7B2A0209336A888A9DB2B2914F0F0A1A68B0D1CDC4CCCDBFBEB49849121E748E6C516A93945810000936536E9AB3C7BFAD97661D010215387BB0C0AA857B7A581617485B50464972B5E2E7D6BC8B6351473C6BBCECFFFFD39B5D52546FA2D3EBE4BF8D46030001052068B0CE62B09F83381414132764A0CBE9DAAD74402C3838413751BCECFFFFD39B5D5201FE1261070718207A554F5B6FA8F1FFFFFFFFE9B17037304982A5C7E0F3E9B6631500022762B3E1EDE0AB61496FA49997AEC6C7C4CBC4BB8F4200001869B4B5B8ACBAB9A0510A0629689B997F42030823406C9BB0BACCB674230000001973B4D6D5D4C2BC802A05043C7A9793A6B2B38C49110A2771B6D3D6C4BFBFBBB5AA9B5813256D8F5E3E52848B460E000D3F6A7BA1BCC4B8A99F5D1D00000E3576B3C7B0867F7B4B13184A534D465E82CDF5EBD0AD815B4B434A7DCDF5FFF6D4A174515277B1E2F3E0AF783803000000347DB7CC6099906C3713071E286BACD5E9D3A67542353430444456CDF5FFF6D4A1745101FE136107071830776E666983B9FFFFFFFFFFEDAB6540425F95AEC1E1EDE5A9541A00002D70B6E6EEE8AF664066A19495BBC8D1D7C9CFC0923800000B6FAAB6B6B7B7B6A24A070039799EA4753205052E4B73A9B4BEC6A55D170000002273AFCADECFC0AE671E07115380A3A7BCB9AB834207092D7EBEC6C5CABAC3C6ADAA985917277B8A58365C8A7F3D0C000C4465769CBBCAB2AB9F58210000153E85B8C9B0928C804E1F1C465950545F8DC7F2E7CFA279604A4C4D87CBF9FFFCCF96604A4E75AFDCECDFB77B2D0F00050A3581C1CE5D92875B320E121A3A7AB0D3EAD0A366332B4043374757CBF9FFFCCF96604A01FE1461070718407863526589CAFFFFFFFFFFE49956393E609FB6C6E6EFE3A44D12000C3E72C0ECEEE9B55C3B67A1999EBCCACED0D0C9AE802800001771AFAAB7BEC3B59748070C3D819AA9712A0A163A5B7AA2B5C3CDAA570D0000002E75B1CAD3C5C2A2631C131B578DA5A5B0B7B279350901368DC0CEBEC0C5B9BFAEA38D56152A7288524051807A430A00154E697FB2B7CEC3B09557160006144383BEBB9B84837F4313205D65585963A2D9F8EBC594715B404B5491DEFFFFF7C4845A495082BEE6F5DBB06D2A040000094090C3C95D85765D2C0F232F4177C1D2E7CBA0593D373D39343966DEFFFFF7C4845A4901FE156107071850736D6B7B9DD8FFFFFFFFFFD58C53364473AFBDC7E8E6DB98491905114385C2E4F3D999583C6CA19CABC6D7C9CDC6C3A1722A0000166CB1B5B0C1C1B68E3E000D4F88A7A3672501134D668CA9BACBB68E430A000000307BABBDC8C2B8A85B1207277095ABA0A5AAA4702D00053D8FC5D6C5C3BEC1B4AF9E8F511A2B78814F2E5480752F010021527A89B2CAC4C3B8934F14090D1D4F88BACDAA8C8C733B0C1D556A63586BA7E7F1E6B689644F494F6098E7FFFFF6B88F62515677B2E3F2D3A67126060006164D9DCCC559736C4D2312121C4488CBDCEACF8F563B35363D414867E7FFFFF6B88F625101FE1661070718607369647EA6DFFFFFFFFFFFD58442263A73BCC4D1E1E4DC934714091A4380C4EAF6D7A04734669C8FA7CBDED2D6D3C0A4682100001875A9AAB4BCC4B4862F081B6290ACA467260A17507495B0BBC0C3883D010000073F77ABBCC3BDB78B47080D3876A5ACA8ADB295551C000F4A93C1D3D7CEBDBCBAA8998052112D7B7D50384D716D380D001C577A93B4C7C5BCAF9A501D020B285E88ADBCA68D896F300326706A665B81BAEBFDEAB27B624D4D465CA3E6FFFFEDBB78624A5584BFEAF1C49E5A1A0000001657A7C5BD5D7B5E4924191E25438DC6DCEDCD8F4B253F4F4A3F446CE6FFFFEDBB78624A01FE1761070718706E707087B1EFFFFFFFFFFFC3763C3B4F8FCFC9C7D8E0CE82381211235A81C0E6F1D9A15435559E9DB2CDD9D0CFCBC195612100002275B9B6B1C9CABA9031051B5F9AAC9E5F1B0B275D82A9B7BCB7B77E2D00000015407B98AFC1BDB0823E140D3877A7BAAEAFA68C5417001259A1C7CED1C6C1BDB9A4918F470E257782523A4E7061240F011B5B899EBCC5C6BDAA984B0A02113162AFC5C09F82826020052F7570676185C6FAFFE2A9745A5A544466AAF1FFFEE9B5725044587EC2DFEBC68D49211005102376B7CFB24A7059432B1A1A285D96CCE3DDBD7F46333C4B4445476CF1FFFEE9B572504401FE1861070718806F64607BA3EEFFFFFFFFFDB65633365C9DDAD8C3CDD9C3782F0D1A2D588CB9E0ECD08B442C5491A7C1D2D9D0CFD8BB91511400002B83ABAEB8CDC6BD852B05206BA5B5B162200B2F7292A7AFB6B8B36E220000001852839DABBBBDAF7C3A0A10428AA3AEA9A89782491200146DABD1CFC5C1BBBAB39087804016287D884F36527A572407001E6497AAB8BFBAB5AA944B2713103263A2C6BFA79176581A073B797D797792E5FFFFD29C78645F524D75B8F8FFFFE0A86B57405188CCEFEDD298531B0A03052C7ABAD0AF485A443726241E285BABD4E6DBB17C413043504E4A4E81F8FFFFE0A86B574001FE19610707189074697187BEF6FFFFFFFFFEAA5C302F5FA9E6E2D6C7CEC16C301D1A2F5B8BB5E5ECC7853E2E5D92B1C9CFDBDCCDCFB9834B1800002A7FB8AAA9C6D3C07D26052A709DAE9E5623163B7A96ADA6B6B9A95B1100000625588893AABDBCA06F2A0D1D5B9BADB7A5ADA5823B0A00186DBCD8CFC0BCB5BCAE8E746F4621328089533C53674A210D07206391ABC4CDBDB2B2883D1308153676B1B9C19D7E80521B0E42836F62639BE4FFF7D2925D5655595480C7FAFFF7CE966750475889CBF5E8BE874A1D04030B307ABECCAE424F42322124273A66B1D0E0DBB06D47303C4D4A445193FAFFF7CE9667504701FE1A61070718A0776D708FC3FFFFFFFFFFF79D4B2F3966B9EDE2C3CFD4B5612C1A1E3C5A86B0DAE0C27644345297B2D4E0E6E0DCD4AD6C350C00003187BAADB5C8D9C4771D083483ACBBA35E1816467EA5ACAAADAF934707000016386D94959DBFB995521A102E709FB8C3B0ADA4743206001E70C3CFD6C4C2BBBCA1786E68381B327483574147554A25130C23609EAECECCBEBBB088370B051F436FAAC2BFA0918150170E49827C6D7BBDF2FFFFDD99665C6D656294D7FFFFFACE955F4540508DD5EEE5B57F3C1401071542A2D0C59D344C3D26142122377DC4DEE9D8A05A38313F564846599EFFFFFACE955F454001FE1B61070718B0786D7393D2FFFFFFFFFFE79536263F6DBBF6F8D5CFC2A95A2E202A456285AFCED3BC753C2D5499B9D4E2E0E0E3E0A86D431704002E86B6B0AFCDCEBB69240B3C83AFBA9F541A22518FABAAAFADB48E430200002745798C839BAEAC875418082A77A5BAB6B1B3996D2A0300277CC3CFCFBFBCB6AEA37B696239223B6B7857474D5A2C1714122B74A3C1D1CCBDBDB37E42220F1F4B8DB1C5B4A27E6640120D4A8D787996D7FFFFFFDE93615670756F9ADAFFFFEBC38E604C4B5495D2EDE1BC79350A040510519ECCBF983647332C18222F3C7DC4DAE8D4975A2F373F594E405D9BFFFFEBC38E604C4B01FE1C61070718C0716E7498D4FFFFFFFFFFE18E38243B77CEFFFFD9C4B0914B2E2736466C80A3C3D4B566322E5394CAE5E9E0DCCFCCA7673C110404409FC8B8B4C7C9B764171A498BAFAE93591F26699EB3B5BCACA682330000022B437B8B8398B69F7740130F3E7CB0BBBBB7B19A592000002683CAD4CCC9C3B8B59268605E2E1F417D96694F4D4B332016082768A5C5DAD5BAB2AA75371A0F225090BBCAB8958C6036111C5D8D7A7386D6FFFFFFDA985F557B7873A6E1FFFCDEA77A5136455697D6F1EBB4823D1300010D55A3CBBE80283430221515314D95C6E8EADA944C2B233A59474A72AFFFFCDEA77A51364501FE1D61070718D0807E7F9BD4FFFFFFFFFFDA793B2D4787D8FFF8D9C1A77C3B20293D657B82A3C6C9935A2324589AC6EAFCF1E2E0D6995F3B120B144E96C0BBBBC7CAA8651B1C528BABAB95461227699BAFBCAFA6986F1C0000002C5B8A928793B8A370380F1F4988BCC1BFB4AD884F1A01033A8BCAD9D6CBC6BBA58762575C392047898B724A52402B2019162B72ADC4D4CDB0B0A47C38190D255996C1C5B79C87602F0B1F5A8F7C8CB4E0FFFFFFDC886167858283B4E8FFF4DDA26C453B3D5FABDAF5E9BF72280D02061865B4CFC0782D36281B201E214C92DDF0E9D5904C312F4956485177B8FFF4DDA26C453B3D01FE1E61070718E078737B99CDFFFFFFFFFFCF7F39364A84DBFFFFF1C697673423385375837A8CB2B3864E2924539FD1E6E7E0E2E1D494583C290E1651A4D3BFB6C3CFB14F1C215188AAAA903B214076A1B7B5A7A99A65190000083362939D8791AD9A622E0A14598DAFC0B2B2AB8F531F0004459BC7DBD9C4BFB2A27E61625432294A827E614E4235262325202C76B3C8D1B5ADADA269392420306BAAC3C6B8A58458270C1B6D937A8CB5F1FFFFFFCF8958608C8086B3EEFFFAD6A1704F383856A1DEE9E0B0712A0802072272BFD7B0662E382B1C1A1D2A5AB1DBEBE4C989452E35475E535576BBFFFAD6A1704F383801FE1F61070718F071767F9CD5FFFFFFFFFFBF6E3C344F90E7FFFFEDC68D5E292C3F5C7C8A828FA3A2763D232951A1E5F4EBEDE5E6C486563D2E0D235AA8CECBB9C0C9A959212A628FA7AE8C41233A74B3B2B4B1A3925E0D0000094782A9A9878D99824914011E5491BAC5C0BBB89555130000409ED3CCD2CCC2C2A0735362552D20508F906F553A2525251B172F72ABD0DDC1A0A99E6A38211F3878A3C0BCAD9E864A1803226C9A7B89C6F6FFFFFFDC824E618A8489C4EDF5E7CB8A5D402E325CADE2EAD4A95F2502020D3387C4C9AA6724282B2220223068B4E5F4E5C9834A2C3C445646547CC3F5E7CB8A5D402E3201FE2061070718007C7789A8E2FFFFFFFFFFAD6B3E36529CECFFFFFFCA814D2A2938678E997E7C96966F3D222D52A5E2F9F7EBE7EACF8F514437242561ABCFCEBABAB291401C306792A7A27D39224581B3C4B8ACA4914E000000105E87A1A08383A67D48140A1F5D99BBC2BCB7A6813B0800043EA0CADAD6C5BFB7966643574F343B569595745443322A231A1B397BAEC2CAB49BA49A65352A1E397DB4C5C1BEA272531F10326D9A8298CDFFFFFFFFCC8656678B929FCAF0FFF7C884533B30356CB4E5F2E3AD6D2C09080B2B86D5D09F6125201F1F20263670BBE5F3E7C1773E292E4B6156578FD0FFF7C884533B303501FE216107071810717C83ADE5FFFFFFFFF0A3653437589BF1FFFFFFC67E431924517DA4A68E7A908A612B1A1F469EE6FFF8E5DEDEC37E4E4943242273BCD4CBC0C7BC9140233A7091AFA075342E518FB7B1AAAFA18C4000000020628DA49D7E85A3772F090C36679FB2C8B7B0B0883A00000048A5C8E3D3C2BFB6906C4752553D3E648D9177583D292530301F3983BCCBD2B39C9C925E3E342B488CBBBDC5A49C713A150229789C839CDEFFFFFFFFC570495D8E8D9AD5EDFFEDC58856452D356EB5E6EAD29B591D030B0D4599CDD59D551E1B201F171F356CBCE5F3DFB985332C343F534D5AA1D6FFEDC58856452D3501FE226107071820757B84ADDFFFFFFFFFDA905B374267B0F3FFFFFFAE63231430588BB7B389737D69362212205CB2F0FDF9EFE7E2C67D4E4C482B2A6DBFD7D0C6C7BF893821416290A99C722623589AAEB4ABA8A7863A00000022759BB3A87C84966B2E06003270A4B9BFB9B3AF892E00000049A9D1D6D9C3C0B585654E595138487195A5844724202532271F387FB6D3DBB1A18E8D4A313228468BBAD3BFA9A06C2B040739809A7C95DCFFFFFFFFBC6D48598A899ED2F8FFEBB0754732313873C1EDF0D0985524080E134BA0D6D49651151D2020272D3E7DC2EBF0DEAB653A2D3642555564A5D7FFEBB0754732313801FE23610707183079747BB1EAFFFFFFFFC98053354A71B6F5FFFFFFC2641B10326498C0BB94777A5D331B031A50AEEEFFFBE3E2E4B9765C625D3A3C84C3D4D8D1BDB26C2A1B477B92A4A2732B215D9AA8ABA7AFA3852A0000023378A4AF9C8788925614000B387EA8B6B1B1A6A2772A00000752A8D6D8D6C9C6B9894B4C5F4E414B769BA181512B1322322D264889B7C6D9B6A0A27A41303B385591ADB8BCB29665320B0C3E88A27398E8FFFFFFFFBF75575D8695A7DAFFFBE2A0634136314783C4EDE9CF904E240E17205FABE0D69545191514201C21397DC2EEFBEAAE63311F344D595174B0D5FBE2A0634136314701FE246107071840707580B0F6FFFFFFFFC5814B3C4C77B9FFFFFFF7A64D0E023479AAD8C4987B704229100B1E55B9EFFAF9ECE8D6B06257705E35448ABACED5C3C3B36B2725518099A799622731699EABA4ABA9A17E3400000B4385A6B5A18C8F854D0800024182A6ABABB3B5A5732401000E5BAFD2DBCFC1B6AE7C524760564B6984A9A58545150C1F3B322B4687BDD7CBAF9292713D323B325B9BB8C4BDA795652708124C8D9C74A1EEFFFFFFFDB7794764868AA6E1FEFBE2AC5E4033324997C5F0E1C1865525091B236FBADFCD9047110F151F1A2B418FD4F2EAE2AE5E3626354D4C5479BBDDFBE2AC5E4033324901FE2561070718506F7984A9E6FFFFFFFFB86F4530406FC5FFFFFFF9A545090C3B81BCDDCD9C846A3817040A225CB3F3FEEAE1DCCFA06C65786745478BC3D4D5CAC1AB682124658E969682582E31779CA29FADB0A16C1B0000134E93AAB8A88387883E0000114F899DA5A5B3B5AE6D2800001260ADD2D1D6BFC3A87A5240514B4B6799AFAE79411B0E314035244182BCC7CEA98B90633D41403F609FBDBBB7B29A531505043B8EA17FA7F6FFFFFFFFBC6D4B588D91B5F1FFFFDAA161423B355B98D7E7DAC27E3C170D0B2674C0E8CB8B401211111E212D498FDAF8FDE1A557353332364F5883C4DAFFDAA161423B355B01FE26610707186077828BB1E5FFFFFFFFAC72403C517FD0FEFFFFEF92410009418BC8DAD1A485633814080E2D53B6F7FEEFDFEDD697606C816F414895CBD0C3C1BB9C521B1F679B9E8B8157263C77A09C97A7AD9F6D1E00001A548FA9ACA29494813A00011D5E94B3A9A2ACB6A1641F00000C62B1D9D7CEC4C1A77B4A434E48587293AAAB77390D0F3347371F4D86B7D0C9A19A90633F3A424D6C9CB9BFB7B091541B00104D929D7C9BEAFFFFFFFFB5683B518B96BBF2FFFFDA95573C36365FA1CFF1DAAF703C200F052A81C8E3C78336141524242828418DD8F1F5D59D532E252D42584E88D0D8FFDA95573C36365F01FE2761070718707C8392BBE7FFFFFFFAA05F473E619DD1FFFFFFE2882900044299C7E8CDA7805F200900002557B5EEFFF1E4EBD4926F7587794A5999B7CBD3CEB87D3C1528709A948F724421407E9F9D92A1AC975B0F00002A6CA3ACB4A6988C71250000186FA7A19597ACAFA65F120000176DBED6D7D4B5B6A6684C4D4B43577DA5B7A9773E0E0D385440365088BEC8C2AF9F8E513A4C485370A3BABDBEAA84360B000F5493A180ADFCFFFFFFF9B36B485D8692B8E9FFFDD99961413E3660ABDFF3E4B074321E0B173089CCE4CC7D3C101B0F1A1C3255A3DFF6EBCB93472D2C2E3B49629EC9D3FDD99961413E366001FE2861070718807D8393B6E4FFFFFFEB8F4D3D44558FD9FFFDFCDF812F00044DB0DFE8D3AC8D501D0000031F5EB6F5FCEEE4E5BD775E7FA27E475C96C3C3D2BFB27B291C31799C918373451F3C869F8E859DA68E530C00013475A9B3B2AF9C8A5F2200002B6DA9A1838AB2AC95520A0000196EB9CECDD8CABBA569463F3B4E5786A7B9B87A2A040B44624B3E5597B8D5D0A49A804C2E4C5C506AA8B1B5B3AE8A3B010016558F9C80A6FAFFFFFFFFB06D48577688BCEEFFFFDB9057413E3B76B8E7F2D5A35E391B0C11398ECDDDC67B2D06141D25202F5BA9E2F1E3C7884836412E3A4858A9D7D4FFDB9057413E3B7601FE29610707189079879DB8E1FFFFFFDB87463542608FD6FCF5F4CD731D001657AFE9EAD5B7884810000004326FC3E9F0E1D5DEB67E6183A88051619AC2BFCDBFA46F2E1F39799A82796C3F274A80937A7A9CAB96530B05103F7DABBBACAA9C7D4F12000B3F7DA08C728296AD93480C00001E7CBED2D7D2BDB99964424043587C9EBCBAA96D24071243654D3A5C92BED1C4A48F72424250624C71A6BBB8B0A583370000165B9A9A6C99F1FFFFFFEEA9564452748DBBF3FFFDCA89504E3F457FC5E4DCC095592E190E143599D5DFB674240C0D11181C2F5CACDEEFE4C1884F393031324269B2DCD4FDCA89504E3F457F01FE2A61070718A0748FA1BBD7F7FFFCCB743D3C3E68A6E0FFFDE7BB631A00125BB6ECF4DCCB984608000000346AB6EFF0DBDADEB682738EAB824A67A3BCC8C1B39B5024133D85928F78603228588D978884A1A37F3D1200195988AFB0AEACA782460D00054088A88E6A78A7B396490B020A2784CECECFD1C1B28F554632405774A0BAB7A96520000E4B644D3D5DA0C1C8C9A9916C3D3A5D5E5A76A8B8B4B8A3792D00001E6D9E9A76ABFFFFFFFFEA9D5D4D5D8397D3FAFFF9C88B5A49455290C9E5DCBD925A31160B124495C8D6C0702D0D0B131324365FB8E5F1DCB17F504035333A5377B8DECEF9C88B5A4945529001FE2B61070718B0748A9EB7D4E6FAEFBA5C2C2C466CA4DFF4F4EFBD5C18001164BCE7E9D6C094410C0000062F6BC1E7E9DCDCD9AA75779FAA834A60A3B0B8C6BD87461C172F859686805F2B2E6A95996E819A9F72370906295D8DAEACAFACA3783F00000B5696A47E6275AAB0863E0E000C3787C2CBD2D3C1BB8E533930396093B0BCB8A55C1A021B4D76634F6F9BBFCCC2A1955E394565716089ABB7B4AE956C1D000020649FA778ABFFFFFFFFEA9D6448597FA1CCF4FFF0C27A594D4C639CD0EFE1B68C643F1C0F1954AED3CEA55D2008131B24323469B8E7EFD2A67D48343135364D7AC5E9CAF0C27A594D4C639C01FE2C61070718C0717E94A8B8D3E5D38A452A2F4D73ABE5F4F4EEAE5214001166C7EEF0D2C88D3F000000032D6DBCE4EAE2E1D2A77379A0AB795570A3C0C0BFB7833B1913387D988B745B2F29639791787BA2936220010C3876A0BDACA9A09C672D00000E4D9BA58463799CA67F3100000C3893C5CCCFD7C4B18A513733385D93ADC2C3A35B1104175171615A82A7C0C6C3A98D56323C64746E8AADB0AFB7A16F200000226EA4A182B5FFFFFFFFE99B654D5183A0DAFFFFE3B37A5B57597AA9E1E7DFB1805330160D215CB2D1D2A0652D0307131B283878C5ECE3CEB27F4C3A2D2E30468AC5E3C1E3B37A5B57597AA901FE2D61070718D06F809DAFBED2CDB4733E202C487EC2F2F3F6D79A4209001063BCE2E6D9BC812F0000000D4173C6E1EDE3D8DDA96B7AA2AE7D4F6C96B2BBBFAC7D300F173685A7947C4D2E386C9394707D97864E1003234A85B5BDB3A8A499601C00001160A4AD7D5D80AB9C7831040218438EC6C9CDCCB6AB83433423296999BEC6BFA4560600215A7A6A6084AFC3C5B9A985472D446D7E6D92B4B3B5BBA3691400001F67A79A70AEFFFFFFFFDC8458444D7E9EDBFEFFDEAC724D4A5782C2EDECD6AB8454372B173B75BED0C18D541C061317191B3E88D5EADDC28F7D51423E3D354E8BC4DAA9DEAC724D4A5782C201FE2E61070718E07C909AA6A8B4B4A3612D142B5490C9ECE9E5D28C3303001C74C2E8E9DBC17B25000000084988CDE8E8DCD8D19F6D7FA2A6756282B5AFAEBAA6732B111748809A8A764835417796856D7896833C05001B548CACB3B2ACA28B490D00002266A9AD7A617BA2A46528080A224DA4D8D5CCCCBBAD7C48301A326AA7B8BDC09B4B11041F5D836E6A8BB8C6BAAF96733F2D4D78777592ACB3B0AC99590800002F7FA2A372B1FFFFFFFFCB835A4E6186C0F2FFFBD69C725C5E6891C2E7E3D4A3744E3F272D4082C2D1AA7E451501110E141D4390D4E9D0BA987F6046373C3B518FCDDBA7D69C725C5E6891C201FE2F61070718F06F929E9E97A0A37B4716162E5492C4DCD5DFD0893200001475C4DBDFDBBE751C0000000D5394CAE4E7D8D5D18B5D83AAA5735F7FA6B4BFBA9D5B1C0D15488596947D5036487E9D83747F8868310503306C9CB0BBB2A3A1863F0000002572AAA06C5575AEAA5C22040D2257A2CFCEC7CCBAA4723D2A153984B6BAC6B98B4005001A598778729BBAC6BCAD9B6A3E284D767984A4B8BEB0B88E470F0000227A9EA394CAFFFFFFFFD384584D618FC9FFFFFED29B746B6678A1D2F3EBBF9A74553A1B264A8CCACAA373451E000C1617314F93D2DAC7A88B7D604F39303A5A98D8D39ED29B746B6678A1D2 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 61440 61440 0 01FE306107071800718E909694927C5C2809111E4A91CAD7E9D9BD681A00001871BDD3D4CBB2751D0000001F5F95CCDEE6D7CBC78E6D8EAB94645F86ADB3BDBF9F5312000D448FAA9F7F4C38477B8F7B788180572100032E71A4BBC0B9A8A37C380000002A80A99F786B8AB09B511800102E59AADBCFC6D3B39A6D3022193B7FABC3C1BE893A000020657D706E9CBBCDC6AE9C66342D58787B88ACC3BDB5AA8A3D0000003889AEAB84B9FFFFFFEBB67552466693C9FBF9F2C39B7F727685B2DAEDE3C68F6F4F2D1F3C5E94C0B8925F3718061811172F59A1D7D9C2A1847F69523D3332509FD8D195C39B7F727685B2DA01FE316107071810748F9C8F837D6E490C0000225FA0C8D7CCD0BA5D130000267CC5D8CDC6A55C100000001F65ACD7E4E4E1D3BF8D6D89A593625F8FB0B0B7B4A252170D165295A59F7E413654879676737B784A0E000C3A8CAEB4C2AF9F9864270000002A78A397766F87A98544120A163E77B8DEDFD2CEB49C5A2A12103A89C0C4CAB78C3F080015557D7D81A8C4C6B1AC96622925577B8490ADC3BEB1B188330000003A83B7A281C7FFFFFFE7B4744F4D6D97CBFFFFEDB68A7F7F7C95C7F0F3DDB6936C392E364272A7C4B5845A3110000E1D23395FACDEDEC4987C887A5F3F283B5BA4D4C781B68A7F7F7C95C7F001FE32610707182072819283826345190000001B62A5C3D2CDC39A480200002A8ABBCFBDB89752140000002B6FB0D8E3DED3CECA8B698DA48C636D98A1AAB1B59A51230A1B5791A99A7441465B86927A737C5E3A0600044389AEBABEB1A892561B0000003488AF9D777091B4834914001C4978BEE2E2CFC6A2825326070F3A8FBCC7C7B2763401001A55847B89B2C9C5BFAF94571D1F517F8696B0BCC1BCAA7E300000004090B3B08DCAFFFFFFDAA5785B476495D5FFFFE0B1897C808FA0CBEDF1DCAD86654B27285885B0CEB47F50230C000B10203C82B6C3D4B287798785663A303871B6D8C276B1897C808FA0CBED01FE3361070718307989947F7C63390C0000002070A6C2CFBFB98F380000002F8EC8D1C4B78645040000002F83BED5E7DFD0CDBD856A8CA981596F92A9AFB5B5904E1710295F979D98794349639492787B76541F00000A5097BFCABBA9A48C47050000003C8CA7977E8199AB71300E05244D7CBDD1E8D3C4A2824E1D090D4192C6C8C5B37C2F00001C51818791B4C3C8B8AD8B4E212650768C93B0BCC7C2B1741C000000438BB4AA90DEFFFFFDCB996249516CA5DCFFFFE5AB8589969BABD1EBF0EAA67960412D3F5B8EB9C6A16339220D101115214483C6DAD09C716E917F5931283D79C4E1B86DAB8589969BABD1EB01FE346107071840718F817E6C552E000000001571AFC0C4C2BE902F0000003A8EC9D8BCB0793000000000388AC2D2DAD5D4CCC4826C90997967809AABADBFAA81491D0C246B919E9D79475E688F8F83856F401200000D529CBBBFBAABA07B390200000F4996A99A838F9EA2672A0910215A93D3E5E4D6BB8F65300B0C0D439DC3C0BEB778230000195983929AACC4BFB5B5904B1F21577084B0BBBAB7BFAD6E200000004E92BAA79CD6FFF3EAAC7D58524A60A6E7FFFFDC94788792ACBED9F4EBCB93665B442B41579CC3C4975E2D0E000F0F0B1F508CC9E2CC9C716A8C8F68402B4F91CDDBB05C94788792ACBED9F401FE356107071850818A8480764006000000002070A9AFB1B6A56916000008409BC9CFBDA87129000000043798CEE5DED2CDCAAB82748C9071577DA8AFAAA8A07B43130A225A8BA5966D525D73959988856B320500001B69A7B7C3BEA8937436020000185B9AAA97859AA78D5F200210397398D2E5E6D6B77F4E2312051A48A8C6CDC4B37526000016508B9098B6C1BFA6A08A4B15214F7890AFCBC6BDB598560C0000034E8EB4B19FD8FFFCD3AA7C493B4664A3E7FFF4CD886B788DA7CFEAF4E3BF8B654F3926486BAEC2C38F4A1E0507180E1A1C4991CCE1C78E676C908E613C30499EDCD8AB5E886B788DA7CFEAF401FE36610707186077807876703700000000002E80A5ABB3B4995E1A00000A5492B3C6B9A261140000000D4AA0CFDCD6D3CBC9B3886F9C9D6D6990AFA6ADB19F6F3A1F102064939E8B5E4E647C98928C855D19000000166EAFBEB7B8B2A1772B05000013649F9D9091A3A989501B0E17417AA1D6DECAD0AA724C1F050C205DB0CEC7C6B265130000185096A29FACBDB7B6AD8B3A1519456784ADC6CCCABC9E59030000035197BBB59ED3EEDAAE7E5A382F4265AAEFFFF5B6825F768CA5CFDEF0E9C37E5A4727264C7EAED0C478351C1000221E15285BA5D5D7BE865E5C888B5B452F609FCACD9D4C825F768CA5CFDEF001FE3761070718707E736F6B663D00000000002D7C9CA8AAAF954C0100001B5C9EBDC2B192430D0000001C5FABD3D7D5D5C5C8AC706991846F6A8EA1A5B0A7A37943251620629CA595634C6F8994868D814E110000002172ACC7C3B0A9A07525000000266CA4A5A09DA1A67B3608041D4D8AB4D6E2E2D5AF67380B00041862ACCBD0CCB0671A00000D5598ADAFB6C8BFABA27D37131F49688FACCBCAC4C5973E080000005198B9B097C0CABB895A39251F24599EDBFFF2AD6E587385ADD6F3F7DCA676503C2C316687BBC5B2762D1D000036231A2B62B0DBDAB176485A898A56304075BCD2CD8D486E587385ADD6F3F701FE38610707188079766F7B68320000000000488C9FA5B3B08C380000002E74ADCACFAB7E37030000002369B7DDE6D8CDC0B3916A709381668199ADB8B1B69E6C3A240E18678EA98B5D5E7B819A91917E4807000000266CA7BBB7B4B7A672200000003174A8AAA6A7B89A641D0706225992BCDBE5DDC6994D261000041768B8D7D0C9B35B17000010528DB0AFC2BFB6ABB3852F0A15446195C0D4DADBC48A37000000095795BBB09BC2CAA8714A2C1A2027599EDFF1D99A6A536A8BBBE6F0EAD2A15A3F3A1F306197CACFB5682B160003442A1C2C6CB0D7D2AC67455781835F3B4C84C6DCC38A3F6A536A8BBBE6F0EA01FE3961070718906F74737E653100000000085183A0A0A7AA83300000003581BAD0CAAA772A00000000307EBFD5DCD7CDC7B691617095856B8297A4ABA1B39661312516306D94A17E52597E9B9A9A988134000000002B7CABB3AAB2A89F5D230000083F83AFA69CA8B296602E040E316F93B9DCE0D2C69F51110000012C72C0D2CFC5AB5F1C000715468EA6A2B0BCAAA9B989360F143C6194BDD0DDCCBD7F310000001A5BA5B7B6A1BFB68E65391A1422304E90D6FAD7974E456595B8D9F2E7CA98563A2D223569A5D1D2B66F2A0C0C04542E1F3272BCDFD7A2573737788E5E40548FC7D2BA76334E456595B8D9F2E701FE3A61070718A0737E737F6730000000000968A4A1A3B8A973230000115A96B2C5C1AC6A210000000E4C8ECEDCD8D6C9BFA17C556B8880738C9EA7ABA6AA8B5D472D15266591946E4F6A8790A89B8F7425000000003380B6BFB5AFACA3601D00000A4691B3AA98AEB1904F130A17317BBDC5D5D1D1C09339020000072375BBC7CBC1B2622400001E5192B5B5C1B6A2A6B47632151A3D61A3C8D1DBD6BA781E0000001C65A5B6A996B5A772402F20150D27469BE0EEC4814E3B5188C0E0F0E9C9894B31301F327BABD9D0A95B16080000583B234384CDE4CD9550313A747D5F3F66A4CCC7A960304E3B5188C0E0F0E901FE3B61070718B06C7F787856200000000025769FAA91B0A766190000235C98BDC3B99F52110000001E4A91CBE1DFDACEC5A4654C678D857A94999CA6B0A589523C36213478AB9C684D658F9FA4909B6A1900000000377BACB8ADB2B6A1581A0000164E9EBAB1A4B1AC7B441106134985BCD6E5D4D1C2892700000009397CC5D2D4CDAD5D11000A1A4F9CB5B5B2B8A4B6B47B2807103367A8BED7D0CDBF6D1E0000002168AEC3B88A9D82553016090B0E103C8DD9E0AF7B3F38608CC0E8ECE9BD7C402718163C83C4D9D3A8511D000001613C264991CFE1D49C5139416C71544E75ACD1D2A161253F38608CC0E8ECE901FE3C61070718C076798C8D6029000000003A86AEABAEAE9D5E1400002D72ADC3CBC19544110000002E67ADD6D3D4CEC5B691573B658A7970A1A09DAEB7B38A4D443F1A2E769A8E67456B95A0ABA3926610000000183D86B8AEA8A0A395580C00001D5DA9BDA9AEB0A367330D0F194C92C1DDD2D6D0BE842A000000003888BED4D6CBA84B090010205791BBAEB5A6A3AFB4732F08153573B1D5D6D2C7AF64110000012E74A8BCB78987723A1106030015184799DBE4B8703E304680BFE2ECDDAF74341E0D124289BFDBD6A34A1100000B7136264CA2E3F0D39E512E316366564585C0D6B98F53293E304680BFE2ECDD01FE3D61070718D074868C8862240000000647A1BFAAA4AB924D0600003C82B7D3CEB6854A0D0000003A72A8D7DFD0D8D5B27C382055837676A6A3A0A8B8AA824E534B374980968C5A5180A0A6A4919057100000001C558EAFB1A29DA095510D000C2A69B2C4AEB8AC9B5B2A090E21559ACCD8D7C7C8B3771C0000000D4494C7CDD5D29D4112000C204B96B3AFACB0B1B4B45F25010B377DB0C8E5E1D0A95E160000003E7FAFB9A287896335080007080A133C97D4DBAD5E36285294C7EBEDD8A55829181A184895CBE1D6A74411020007773C2E5BA4DDE3BF92502F2E57674B568DBFD8BB874C2336285294C7EBEDD801FE3E61070718E06E7489895A250000000E6CACB8AAA5AE80380400044F98BCCAD1BD8A3A080000144D84AEC7D1D5CBBCA86D31234F827A9BB8A99DB1C0A9683A42442740799C7A585783A2B4AC979855090000002D5294AFB0A6A5A386451304143777B3BFB4B5B19E4D2406072874ACD3D1E3D0CEC177140000000A4C97C4D5CEC59345160006124185B9C1B5A4A4B1A2601C0B164281BBD4DBCFD3AF540C00000B4E8BB4C2AE8E83561C0000001314022D8EC6CFA5562922538CD4ECE2C48F4E1918191857A2D3E9D198470C000002813A295FB0E0E3C08E44302B465E4E6397BFD2AA6936152922538CD4ECE2C401FE3F61070718F0798CA1965A27000000297EC0BEB2AFAF7A3200000B60AFCFDAD0BC7222000000235E99C5C9C2CCCBC9AD6718114B7F7B98BCAA8EA3B798623844543647828F6F525F8CB2B6B1A1864E00000008376AA1BDA9A6AF9D864701000C3C82B5B8BAB9AA8F4616061A3472ABC6CED7C5C2B86F10000000155195C3DBD3BE95360E0009284F93B7B4A89F97ABA2662C0E1F438CC7D2DBD9D5A34E0B0000175397C1BBB37E692F000000051104073997CCC6964A252C5C97CBDDD4B5894C2013041F65B2D5DECA903A0C0600008B3F326EB4DADCB67344222D4952446EB0D4D499662810252C5C97CBDDD4B501FE40610707180075868680460E0000103C86BEC0B6AC995B1E0000176BBDCACFE1BC7428000001267CA6C7C6C1C6CFC79B440308407084A4B9A28FA2BE9C553150493468979B6F5B5A8FB7B8BBA6812C0000001141699BADADA9A3A5852D0601264B7EBBC2AFACAB883D1A141D417EBEDBCDD6C3C6AE620E0000001758A6D5D7D0B98F3207010A254D8EBAB8AB9CA5B69A5933141F4CA0CEDAD5D2D7AB410000001D629DB1B2AF79693A0000000003050C3997CBC58D432D3767A0D1D8DDB38140170B042970AFD9DAC78D360800040A913F3C7FB7DBCFAF7B5128253F3B4F73AFCFC3905728192D3767A0D1D8DDB301FE41610707181075798E76431200031D489DCDD8CBB38A4A1500002785C3D7D5D7BA662000000D4780B9D4BDAEBABEC58B3A06063C6C98B1C4B09DAAB9914124414B39638E84605A70A2B8B6B8A4802E00000029618CA5B0B5B2B2AE74280000204A80B5ADB0ACA87B300E102B5490BAD2CAC3C0BFAA5B0E0000001B5DADC3D1CEB2823203091826528DB6BDAF9FACBA9F511B0C1E59A2C8C4CCD2CDA0440000002260A1AFADA7886E2C000000000004083E8BBDBA843F22426EAACFDAD3AA6E391B0B133884C6E0E2C9822D010008088B373683B9D2CDA876432822343E4C7FB6D0BB7C462A1622426EAACFDAD3AA01FE4261070718207C86907543170E162D64B1DEEBD1BE854A10001242A2CDD2D8DBB25A18000016539BCFC8A7A9B5CBC4842A00033C75A4C4CAAD90ADBA843F293D4C415F957D575979A2B6B4B9A26E290000013B7298B4BFB2ABA99A6E2503092C588AB0B1AFBAA26C2E1412355E99BED9D0BDC2C59B4E050000002E6DADC7CCD2B87D2501081D364C88B9C1ACA2A8AE9244210C2C70B2CCD2CFD0C8A13E000000297AADBAADA27B621A00000000000000459ABDB8703C23407BAACBD0C19A5732100A184A8BC8DCDBB679250200030C9336428EC5D2C4986D3F2D262942558ABECAB36E35241C23407BAACBD0C19A01FE436107071830788379663B140A1B4268B9DBE5D7BA713708020E50AACBDDEED4974B0A00033067B5D3D1ADA3C2CBC37425000034769FC3CBB8A7B8B374311E3A41366889764B5991B4BCB9C0A458100000004B84ABBDBBB9B5B392510E0011336C90ABA8A29F8A58251820497FAECAD2C5B6B9C09345070000002676B8D1D7CAB4681D08112C3C5D8FB6BEB3A0A7B5894A1D153271A9C9C8D3CBC08B400000003080A6AEB19D725F1700000000000000479DBCAC77302F5D92B7D4CEB3985F381A0013488DCBDDDDAF752B0000000B9345579DC7CBB58E6D47261D2E3A5998CDC59F56331A172F5D92B7D4CEB39801FE4461070718407C856C471E0D12264E7EB9DFEDE3B9743408061D61B6D5CDE3D79C43060009327BBFDAD2B1A7B3C9BE752300072A73B4D5D4BAB1AFAF6A2E1C3334366D8778546D9CB7C4BEBC954E0B000012528CA4BDBDBFB7B7913E0D001648739BB7A598988851271D2D517CB0CEC5C1C1B8A98645000000002F82BBCDC9B9975D0F0011324C6394C8D0BCA2B2A9753313103384BCD0C7C9CAC5912D0000053E85ABAEB49472520A00000000000000549FBEA560302D5988B4CCBEA9824F28110C1A539CCDDFD3B66B200300080B974E5EA0C6C6A2746136291B1B3367B7D5C08E4328131F2D5988B4CCBEA98201FE456107071850656D58461E121B376294C6E5E9E2AF611B0105225CB5D2DEDCCC89370D000A479CD4DEBE9BA1B0C7B56B1900083C80BFD8D4BCAEBEA0561D1A1C23305E6B63587FADC4D1CBB7913800000020619EB9C6B9BEB2B47C3000001D5091A4AA95848A6D3C142A476B92B3CBC6BBBAB9BF8842050000074188BBD1C8C19E5811021631506394BDBCB6A7A8A172401E163F91C3CDC3C4C6B47024000003499FBCB2B68F724A0E0000000000000456AEB89D58383C629ABCB9B39177492615152E71A8D0D9CFA156120000090AA44C64ABD1CB9E6A4D3D1E1F264180B0CDC18D421E0C153C629ABCB9B3917701FE4661070718607C7D6145221D2B5576A4E8FEF3E2A85814000E277BC7DED6DFCE7A260702235EA3DAE8C5A7A4B7CDAE570700104C89C1D8CFAFABB99B4F1A0516152E606E615B88B1CBCFCDB08A310400002D7EADCCD1C5BBBDB97B2B00062A6297B0A6857978582C102B446F9EBDD0CCBDB4B4AA86310000000A458DBEC7CCBA974C0308294F5B689CB5BDB8A6A89C643B1C17438FBDC8C4C8BFAC75290000105898B1B7AF8A6B430000090000000003609DA8835534386B9CB7B8A48265411C120A3075B5DDDEC9914B1200070B0D9B5473B6C4B28B6249372B282F4887BBCAAF73401A1118386B9CB7B8A4826501FE476107071870785F44391F2D3D698BBCE5F5F3E7954F1A091D478FD9E9DADCB9671A010A2B71B8DFE8D2AEAABEBC96480000044393CDD8CEB2BFB994431012100A254F585E6693C2D2DFC8B469230000002E87B0C0C2BFC4C4A2671D00093D79A5AD9F726462482216304D78A2D4DBCCBAADB4AC723B0700001852A1C6CFC3B7863607072751646E8EBBC3B4B4B191583C2427609EB8C7BEB8B3AC732900001D7199A4AAA6766C4208000900000000136D999A83462645729BAFAC8D7A542D0D00154F89C7E4DFC189450C040502149F5F8ABEC4AD855B45433428335292C2C9A5662B1B141C45729BAFAC8D7A5401FE486107071880745A402E272756729FCBF3FDFCE9973C180B21488FD3DCD9DBAD5E22151F3C86C5E6EBCBAEA6BCC093400000154EA6CCD9C8BCBCAA712A0607060A26545C5566A2CCD4DCC8AE6B1C00000A4C91BBD1C1BDC4B8965015041D4A83A5AF97786250341719385F8CAECAD0CCC3B9B3AD67350A00001E569EC3CCBCB48439060838677A73A2C5C4C0B2AB815C412A2B5A98ACB6C0B6B7A86D1C0000226DA1A6A29A616344030013000000001776908F63372E4272A3B2A2866C4E34261021609CCEE4CFB276310900030510A97094BCBB9C6A4B413029274263A1D6CBA15E1C17191B4272A3B2A2866C4E01FE4961070718906C583E3125385C80AFD7F4FFF5D38A38141128559FD6E0DEDAA14B1600204597DAF2EED1B7B5B9AF802600003071B1D2D2CFBDB9AE6E230000000E234C5C5979B1D0D2CCBFA24D130000124E99C7D8C2BEB9BA93480A00225F9AB6A89C71523D1F0B17376293B1CED2D5CBBDB4A6602F0C00041F66A5BEBFC2B57B250816426E7A7D9EBCC0BBAEA68954351E2966A0B0C2B5B6B4A0591800002D7FA9ACABA15A643B0207160000000024759C85663C364B79A9A293795040291908256DA9D1E7D8B378370A01070B1EB4769EBCBE8F613C3D302C2D4073ADD0BE88421B1420244B79A9A29379504001FE4A61070718A06758422E2F4A6A9FC6DDF4FFF4C7763515162D65A3DEE2E8D8883D160C2154A8E0F6F0D4BAABC2A9661E00003C8AB5D3DBCCC4BDB16D20000000002159565D8AB3D3D8CDAB8E390000001E60A2BFC6BABDBABF893E00002773ABBE9C8A6B4939130A1E40648AB9E3EAD8CBC5B0A15D2B0F0109387AA7C3AAADAE6F1F08255888968CAAAFC1BCAFAB744932203273A6BAB7B5B9AF98590A0000377C98A5A5994F5D3F000B1B00000000357F88775B392D4E7BA2A38C62453C341D1C4384B6D4DDCCA86D3E1100060924A97FA1BFAD874C2E33373633457CB6CFB67B3A110619264E7BA2A38C62453C01FE4B61070718B0705A4D4C3F5988BCDEF3FFFFE9B365311A1D4374BAE5DEE7CF86390D123467B0E7EFEBD1C7C9C29D550800045194CADED9D2CAC6AC57160000000024535B6B92CED1DCC89769200000002A67A8BCC6C5B9B5A07925000D4489BDCDA99473411B000019466A97BDD6D6DCD1C9B2895634210C18418AA4A7B2B8AF6015043072A0AA919EB0BEB9B1A06B47322A377CA3A9B4A3ABA88C44070002378AB1B0A3923D5C3706081E10000000468992765436295187A39777584A352E2229518CC0D0C4B89B714622070E1329A095BAB699723831252D2E384B85BECDAF652C1217222D5187A39777584A3501FE4C61070718C070524847495E90CAEDEEFFFFEDAF62291E24477ECEF3F4E1C1752D0B143778C6F2F3EBD2C4C4B8854203000863AACADEDCD8CABB9646030000000025555C80A1C5D5CDBB8F5B1100000B387FB0CED7BEB9A384581200145999CBC8A9947B451800000C3A5F8DC0D4D6E0DACFBC834F33242332569AB79DA6AD9F581C13397EA89D98A1B1B9B7B7976647352D5684ABB4ABA0A3A37F390000004C8EABAF98853B623A080320060000005997956C4F372D5C88AB8C70513C313B323266A6C5D5D2B9905F4631180D183DA498B1BE96582D212B2F313C65A2C5CA9259210E091F1F5C88AB8C70513C3101FE4D61070718D07A635C5C5573A4DAFFFEFFFFDCA85A322D305C91D8F6FCE5B36125131B4A7DCBEEF9ECCFCDC9AF742D00002082C1D2D4D1CACECA9042080000000030646B7BA2CBDACEAC6C3C0B0000104781BFCDD4BBAA9F77400E00176BB3DDC9A39E844F10000009386393C4DAD2CBD3CEAE775847322F3E75A5B49894A9893C140D4588B0AFA3A9AEB1B1A78B584638335C8DADB1A59DACA372360000095492AC9F988221603E0A081C0700000263848A6C412B375B8CA78E6B443B393E2B4B76B6D2DCC5A891644B511E15254CA9B2B9AB7D46241226292F426AA6CDCA8F411C131212205B8CA78E6B443B3901FE4E61070718E0785A57646884C2E8FFFFFFFFCA8A4826224461AAE0F7F9D99D4F1F0E1E5297E2F4F4F3D4C7C59B5D0E0000278BC7DCD7D1C7D0C2974413000000022E63718CB7CFDEC998652A0000001A548ECBD7D4C3A784552301073285BAD9C7A79E8A3F0D000008335981C2DCCFD1E0CE9B7459523F335483AFA89087A280360B10539DC1B5AF9298B0B7AB835A4C303D5E8FA2A8AFA8AB9A791C000013529EA4A59F6A19622F00001100000014688F815F42433C5E98A5825137252F2D314884BED9D4CBA2764F4F4132263A73A7B0B3A66B3B1E0F1E2D2F4781B4D5BE7A3318080D1C2C5E98A5825137252F01FE4F61070718F07563525E739CC2FFFFFBFFFFCA7D4231314E7DB9EAFDF0D8893C0E112965ABE7FEF7E9D2C6C28C39080000339AD9E7E1D1D2C3BC902F010000000C3A6C7291BFD7D8BE935217000007356298BCD6DAC19F6C3B22030C458FC6CFBEB6AD91470900000B2F4D87CBDDCBC8D7BE92655D5E504E679BBEA686829C73260313689DB5B5A39399B3B5A97C5C4C37496C8EAAA9A3A09E9B661800001D688EB0A899680B562300000F0900003A74917B5C3C3039688D92784E36273B42425A99D4D9CAC1966D52594E38384F81AEBAB097602D10101E1D2D508DB5CBC1762A0803071F2B688D92784E36273B01FE50610707180076716A6F7A9CD2FFFFFEFFFBB3723A26315D87C6E6F3EDC57B3B1B1E3472B3E9FDF9E4D3C7C1822500000049A8D8EBE2DAD3D1BE7A2300000000194D8A7E8CC2D9CAAB7831030000123A72ABC9D9D6C98B561E0E051857A7DEDCC8BAB2934501000009244B8DD4D8CBCDCAA98B6D6D715D5C7BA5BD9E6C74946D26091766A7BFB7A78991A9B8956B4B4331527E9EACB0A5AEB19E590B00001D72A3AB998759094F24000007000000418295835E444143769694704A39313242345FABD2DAC6B18457505E5C3D41678EB0BEAC8D521E0E0319232B5599C4DCC1661F0F0D151F26769694704A39313201FE5161070718107C706B7893B0DDFFFFFDFFEDA3623434375790CFF0F9F4B6652B0F153D7CCBF5FFF8E5D5D7C06A1700000352B5DFE2D6D1DAD1BD6D2000000000195B8D8090B4CAC3AD6F200000000E3F82BACAD8DDC486391208052665BFDDEFD4B2B3994C0A0000001E4F8DDDE0C3C7C6A679657887727493B5BEA07371875216052574A5C6C5B1868CA8B08A5A3E33385D92A5ADA99F97998C420800001F7DAAB5AF8D5400532A0000080000085898908058443D5D8E9C906E4B40353E4B4A6CB1DAD7BB9D7D59485A5D43557AA9B0B9AA904517080A1522315EA0C8E6BA5F141015161B258E9C906E4B40353E01FE5261070718207D767492A8C8F3FFFFFFFFEB9759362B456DA1D7F6FFE8A1561D0D22438ECFF4F5F4E4D5D4B0580900000865B9E2E1D5D3DDCEBB7321000000022D6B979293ABC5B6894D0E000000216195C9D6DBD3BA6C2E0A02043A7AC5EFECD2BDB7943F0B00000125589DDAE8C3BBAF91606292958485A0BEC49C79798B4B0600287CB2C2B5AB857F9CAC8E5543313962919CA6AAA8A29F792C000000297C9EA8A08D41005621000000000010608B8569504D485B8FA4935A44423C393B4B7EB7D0CFB495665259605D515F84B0AFBFA76A311C0E14141B386FA7CCE0B151190E071A27308FA4935A44423C3901FE53610707183078716C8AA1C9EDFFFFFFF1CB83432A2D4972ACD5F2F6E49B41051124549AD8FEF9E4E2E2D6A14C0500000668CCE6E5CDCACACCB66114000000052D7DA9959CB0B7A0753D080000083466A5CEE0DBD4B2601E0900042C7CC3EAF2D8B4AF893904000000265BAFE3ECC3BCB2864D648F9D9698B2B9BD907C81783804002C85B8BCB99677879C9875422E35437D9BA5B1AEA89E9B6A26000001398DACB3A2833F00551A000000000029889C835D5554527298AA8C5C45493D41475D87CAE2D8B0886648435E5F566F98BAA7C09B67391A1013161C3678BCDBDEA54214080914263698AA8C5C45493D4101FE5461070718407A7D8098BCD7F5FFFFFFF8CC7146373E4F7AB4E4F7F4D1762B07092055A6ECFFF4E8E3D4CD9637000000147FCCE1DAC8D2DDD3AE591300000014488BAF9A99A3A3926C2A0000000B3469B1D0D8DBDBAC47100000154495D3EDE9DFC6B482350000000A3066B6E5E0BEA98F664A65A1AC9AAEB6BCB19B8B857C3000003088ACBEB4A0848B9F9A6E3825264887989CA7A6A7A3925E130000083997BEB19C7927004B12000000061E4785A3815E566167769B977F46413E4046466392CADDC8A17552423A4F585776ADC8A4B6855D2D1C17151C1B488FC7E0DEA544180E08202B2C9B977F46413E404601FE5561070718506C6E84AEC6D9FCFFFFFFDDA45F3828415991C5ECF8F0C26B300A072C63B9ECFFF7E6E3D5C38627000000248BD5ECDDCECEDED19D460A00000019509EB6A18D9F9A785A1E00000018496AB8D0E2E3E5A442040005174E99D5EDDED8C1B78239020000053B6DB4E7E9CEA383553B63A2AFA6B6C4C9BAA19992692100004198BDBFBBA07D88A37F4A1B141A4890A7B0B2ACAAA2864A090000074A90AFAA9667250050170000000A3365899681595F6474859B9C724A4A55443E5473AFCADEC79F6C403B40535A6184AFC0A5AF7C4D251B1913111D4891D3DDD89C48150B0F1827389B9C724A4A55443E01FE566107071860717C93B6D4D9F9FFFFF8CE954A29293E669CCFEDFCEEB35E2212223F70C8F6FFEED9E2D7B668180000002D89D1E5D4D3CCD9D0933B0500000C2460AFC0A6938D7D66402900000120537ABFDAE6D5D0993500000C1A5EB0E1EEEBCCC7C17C310000000A468CC0EBE8BC915E3B4178AEACADBAC2CBC3B3AB90671B00064C9DB1BBAD94748D8E6F38100F204F97B1B9B6B1AEA97F3D0000001A559CA6A9955417004C12000002093C739CA87F535C5E68829495774E5C5F403F5475ABD4D5BB875B2C353C526976A7BCCD9FA97C4F2D252923171757A6D3E5D6973E1A060A1822329495774E5C5F403F01FE576107071870707996CFE7E8F4FFFFFBB4712F202C486E9BC8EEFBD98E47130A1D4390D9F9FCE8E3DFC2AB5A0800000038A6E2E9DDD6DCD2BC7E27000000062A65A3BFB4907F5E593914080A0D295380B7D0E3E6D8993E04000F296BBBEFEFF0E1C8BD741C0000001C5195D4ECE2C17C4D2A3381AEB4B1C3C8C0C6B8A38D4806000F59AABAB1A18E7D7E7D4F1A0102184FAABBBCB7C0B6A17C34000004216CA2ACB292460800430A0000000D4D80A7A2804F5D6C7F90A28B6352606B48365986B7CDCBB17A492F3941596C89AECACF999F683B2E33312113225EA6D7E6CB8331070D141C252CA28B6352606B483601FE5861070718807488ACEBF1E4EFFFFFE2A05D3229344D77B3CDE7F3DA8C421812305098E0F7F7DFE3DFBF8C350000000A4DBBEDEFE6E0E0DCBF6818000000093378AFCAC3946852412E17000412385B79B1D3E4EBCE86300200123375C9E5F0EAD9CCAA66120000001F68ACD8F2E1BE7F42253181AAACA7B3B7C2C8B8AC813A0000125F9EBCB6A18E7A7B723C1600082363ACBEBEC2B8B892682A0000002D7CA6BEA27F470F0844170000043172A9BAAE7A54576B81A0AE8A61617C7D5B556F96C1D2B8A17340283146516E91BAD1D198915334344A472D1D2966B0D9DFCA8434131212181F33AE8A61617C7D5B5501FE596107071890758FB8ECF4E1EFFFFFC87E3E2820375F8FC0D4ECE4B7742D1C17265AAAE4FFFFF3D8D1B07C230000000A49AFE5E9E5E8DCD7B66B1A000000093C7EAAC8B58B4C3E3F2116131920406281B6D9EAE9CE7E3106001E4682CAE6EAF5E0C2A6580A0000072E76B9D3F4E5B6723E1B3486AAA0A2AAB9C9D5C5B2782500001171BABAAD9F957F67552800000E2370BACCBFBEB2B29D551900000F3D7EB2B19B7536110F431A0A10093386ADC1A76B46536089A5AE8158588079555B8CB2C5C4B58358331F36364F6EA0CDCFD1968C513A3C5C4C2D152770BAE3DBCC7E2D121912172B36AE8158588079555B01FE5A61070718A07895CCF2F1DBF2FFF5BA6D321119305C96C1DDE3E2AE60230E13346EB6F0FFFFEAE0D59F5B0E0000001768C3F1F7ECDEDDD7AA53120000001A4080BACCBB7D411E1D221F181D31477087B6D4E0DCCC792400092C4C8DD8F3F2EEDAC7A14B0F00000C3F83C0DCDEE0B3732C10327B9396A7B4C3BDC8B5AB661900002484B7C1A8A28B6F5A391800000E2E79C9CCC5C6BCAD894A0E0005255496C1B49A6725090E4D280C19234D9EC6C5A76A595A6B899EA2795F68807969759BB6D9C9A8754224243B455580AFD4D7C280864E344E705E301B3274B0D3DDC0732B1C1E141E2B4DA2795F688079697501FE5B61070718B07697CDF8E8D9E2ECDDA455210E1B3A6AA0CCE1E5DE9D49130A173478C5EAF7F8E5DAD08E39000000001C72C5E3F0EDE6E7D8A64A0D0000001C4889CBCEAE65301E27231D1D283B637885AED8E3E2B7601C0513335991D3F4FEF0E5C99343040000145090C4E4D6D4B56924174280968F9DB8C3BEBFC09C500900004291C0C8A89E8F6C472F0A000010307CC4CCC7BEBBBB8D4007000036629CB8B785581C0A1E462A160C23539BBABFA46C49586D81979074507078766E7BA2C2CDBC99693D2A29394C6494BED7D8B97D7C4735506E5E29193E8BC1DCD4A860181A2C1A2B2C4B9074507078766E7B01FE5C61070718C0708ECFE9E3C7D9DFBB7E460F031C3E80B7DDD9E7DE97411309224280D4ECECEBDCD2C4792500000000287CD4E7E1E9EBE2CF8940050000051E4A7DBED0A260311319262F383F5172848DB4DAE9E0AB571500174870A7D6F7FFEFE1BF7E3000000021549AC4D4D8DABA6D271130868E89A7B5C7C4C6BD953F000000379CC3BB9EA09369371B060000154B9DDBD1B8C1C6AD8A44080608386FA8BCA27839110B24502E1B1E337FC1D9C6AD6F47566B8A99976D5268807E8592B4D3CFA97C5A3D1E2D3F4D72A0C8E9E2C576653E34536E592A214E9AC9D8C6AA5D211B1D1A273351976D5268807E859201FE5D61070718D07CA2E1FEE9DFD9CEA67339110A21458EC5DAE8F7DF91350B0C204E91E0E9E7DDDDD5B8671C000000003492D9E2D0E0FBE7CC8E3D100000001C448BB5C0994A1D0F2934343F5175929789B2D0DFC78F41100624527FB9E3F6FFF6D5AC640F000005205D99C3D9D7D7AB651E0F3D848D8BA9B9B9C6BBB68B330000074E9DC7C1A5A6915625090000001960ABD1C7BEBFC0B475341100124388B6C1A8743C0F0B3972403B35519BD3DDD9AE6C52566E959D9171586E818A8DACD3E3CCAB7143281F30455778B4DBE9E3BF665C373B5F7A5B2B2353A2CCDDCA9E561F1D2B182537589171586E818A8DAC01FE5E61070718E0759AD6EFEFD0C4A38352210002284B91C9DDDEEDCD7C2F08082961AEF3EEE8DFD9D3B158020000000035A7D1D5C6DFE6D9BB7F48140000051C4785CDC5813F11092A3442476D809B9D91A4D1D9B37B33040E376A92C3DAEAF7E6D192520E00000C3A6EAEC8CED6D7AF611F113D899998B3C7CABABEBC74110000105CA1C5B9A8AA955324030000002267AED7C9B7BEC5A8652E0300174D8CBAC6A4642E071344523D353755A0DAE3DCA4684E5D78959D8B5D4E6D8D99A2CBE2E3DAA56C391D222A4B628CC3DAE1D7BB5D522D476076512A3370AFCACFBD96491B1F28202D3A5E8B5D4E6D8D99A2CB01FE5F61070718F07DB5E0F5E9D9BA896032040011305EA5D6E2E5E4C3671E01122D67B4EBE0E6E0DCD8933D00000000144DA6E1D5BFD7DFD6B97C3F1200000A1B3F86B7C0792F121B34434F638298B0AD9CA9D0CBA26D280C15467CABC8D3E7E7D7B773360100001E5481B9D0D0C4CCA65D1B1140929DA3B5C3B9CBC3AB6D1500001663ABBDB7A9A18E4314000000022373B9E3CEC0BEBEA2611F00022D669FB6BE9E622904225A514C514878BFF0F3DEA86F4E6281959777695E78919EB7D7EBECD29A592D171E304E649FCEE7F4E0A83C4838526A68522F4183B8CBC3A388410E1D2B1E3B426777695E78919EB7D701FE6061070718006DA4CCD5D2BC9B6D43200800092767A8D3E6EDE4BE60210C0D5284C8EAE7EDE2D4C68B2E000000001259B2E0D2BDD8E8D7A877400C00000322437AB99D591B031639415A6A93A2C6AFA2B0C9C18D5E24011D588DBAD0DDDEDBD09A551D000002255A92C0D9C9D0CDA9531912448DA6ADC2C2BABAB99B5E0F0000237CB6C3BAA7AC88470D000000023583C9D5BFC7BEB59C5426000C266A95C1B8A060140019575B4D505788BEE5F1E6AB644B6490A28C745C5F7B90A6BDE9F4EBD58F4B2920312D4D7BA8CCE9E8C99C4550454D61604836569CC4CABF9A6939170F2630435A88745C5F7B90A6BDE901FE6161070718107393BACBC09F724E331107000C3F6BB7E0E6DFD899440E001C4981CDE8E5E0DCD5C1752200000003296AB7E1C1ACD5D5BF98713D140000131A4579A292481A061A2C36628FBDC6CFC49FA6BEB47C3B0601296BABC2CEC3D3E4B77A370B00091A3974A9C8CAD1D2C9A65112104080A6BBBFCEC2BEBF8F4A0100003384BAC5BDABAB8A3201000000034398CADBCEC2C9AC884A1808033382AAAFAE964E10001F6C62584F658EC5E5F9EAA768466A8C9E8B795B6B8093B7D0E9F8F9D18648232430405174B5E2F7E8C89D444647575752454262ABC6C6B48065340F161824596B9E795B6B8093B7D0E901FE6261070718206F9AA6B7AF8B5832170900021C407CBEDDE6E1C684310C0B23558FCAEAEEE2D8C8B371140000000E3477C9D1C0B0CCDEB98E6A421509070D264578917032100A1732466FA4C7C6D3D5B4B1BA945A26090B3076C0D4D6D4CDCEA964351200002B5584ABC9D2CBC1D39B400B0C3982A4C5CFC3C1C1BB893300000F3584B8B9BEB2AE863006000000104E98C8CECBBDC0AC804F1100144187ADB9B694540D001F645D485470B1DFECF7E2AC6C5066969C736A55677599C4E0FEF7F6DE86412729373A587EB5E4FBE5BD85393E49585545375579B5CFC79B76492806111F37667FB46A55677599C4E0FE01FE636107071830798AA5AB9D82471B0800000A27417EC2E1ECDBAE68240E0D3169A3DCF8E6D6D7C29E5000000000144490CBDBC4BFC6C6AA7F62402021182839576D825A2E0F03162F387DC4CED8DCD4C1B3AC7A371100064EA0D2DED0CBCCC6874523060001396DA3BED5D0C8CDC9872C02003077B1C7CCC7C3B9AC722C000009438FC2D3C1B6AD792A000000001861A8CDDAD1C1B796714316010E4C88AEB7B7984F0E0836735E565B7AA1D0E7ECDFA16253749A8767545A6E82ACD8F0FCFFEDBC7C38222A3D374880C3F0EDDAB37D31353E4C43383A6199C2D5C0905D3620111022497A9BC4545A6E82ACD8F0FC01FE6461070718407B838D8F8365330A00000012295088C1D5DACCAA52180D0E4577ADDAEAE0DFD0C1923C00000000195B9BD9E5D0C5D6C38C6358381A1D2C3B3E536566431D04051939448CC9E9EDF1E0BBB399642206000B5AABD8CFC7BBC4AF713918000115418AABC5C9C2C5CABD753107062D77B5CBD3C8BEB5965B1600072A4C96BAC8BEBAAB7826000300042461B6D6D6C5BAB99366300C0C1A5A9CADB9B69443110C4577564D517EC0DDE7E6D2945554819F86644F435F75AADBFAFFFBEAC1682E242B423F5089C9E9EBDAB1713B364B533E364778A8C8CEAB784831160812224D84B6CB4F435F75AADBFAFF01FE6561070718507B757889764A1A0000000528435F88C2D0D3C3834314001F5895BBD9E1DDD7CCBC7E20000000003873A3D8D7D2CAC1A566524C351F314355596A67562A0803000F21418FD9EBE6E7DEB8AB8A4B1200002864BEDAD7C9C3C2A8682F1513051A5FA2C4C9C6C7BAB09A5A200305297CBBD7E4CCC9BA82400A000D2E5EAAC3CAC3BFA960280C08070F2A7EBBCDCCBDBBAF915B2D0E0A26629EB4C4B58D360B0C53794C404878B6BFCAC7BE7F4A4F888E6B4E45546787A9E3FEFFF9DBB86B2F2B39494F5D8DC7E3E6C39858372B38382D30578CB0D1CEBD6C2F1E100C0F255C9ABFD845546787A9E3FEFF01FE6661070718607173747C67320B000000153152779CC8D8D3AD6C3405081C61AAC5E1EDD4CCCAAD6815000000103B78B6E2DAD2CBBD8B4C3A393632486165626A5535180401000C204DAEE9FEEBE0DCB89A6B310700033281CCDED5C6B8C3AA66311609102A79B4BEC8C4BCAAB994430E000C276FBDDCD6D8C9B07A2603001B3B73AECFD2BFB6A5621E090A0F173E7DB8D3CDBFB8BA8C582B0E13407DA8B2AFAA863401124B7C462E4984B4C6C4C2A1674A5183876A493A4D6580BCF0FAFFF0CBA1663538494F405A9CDEE9DDBA874E3635362E2125699CB6CCB598592619090F132261AFDBE63A4D6580BCF0FAFF01FE676107071870706B6A674916000000001C375871A7C3D9C49C56150009317CB7DDEAEDEBCEB08D4C040000001B588EC8DADDE1CFA2682E293628356C80837B765C290C00000009184CACEAFAE5E6D9B68A572006000D3B94D3E8CCBABDC29B58371E14163585B1BAC2BCAAAEA986410000082F85CDDFE5D5C2A55C1B00003B5D7EA9C1C7C2C2944D2019161623418AC2D0D7BBBCAD884D1F010F4891AFB5B9A97D2E01115785533B4F93C8BFB9B599614A67847F533E2E384F83C6F8FFFADEBE9457324847584C589ACDE6E4C1864A372C2E2A1E3171ACCBC9AF784C201A091A1F2A6CBEE4EC2E384F83C6F8FFFA01FE68610707188064635F562A0B000000002350757BA9D1E2BD75340800163581CBDCEBEAD9C0A97B3C080000012E65A0CDEAE2D9D0904927231C1F44819FA48F7F5329000000020C1E4BAFECF7E5E2D8AB7B49120000184DA7D0E0C1B5C1BD94603F220D1D469EBDC1C3B5A59F976B26000008339CD1E9E2CCBE844A13000E43718BB3BFC4C8BD8F4714121C26345C98CDD4D0B8B9A37B3D0F011B4F99BDBAB29B612500186C904D3255A3D9CFBDB9956866798A744D2733355D8FD2F2FBF3D4A77E58374B584B466CAED3DBD5AD6C443C2B2F28253A7DB1BFB99D6A3619120D1B223B77BCDDF033355D8FD2F2FBF301FE696107071890747266512D000000001144778B95B9D4D5AC68240000234A94D0DAE8EDD4BD9C6228000000134785AED0DEE2DFC3722C0E091C31539AB0B3AB914E0F030005000D225CB7F5F7E3D3C8A661290000062E5EBFDCDCB8B6BCBB95644A2C252A599ABAC4BBA98B747B4D1D020010439BD7F3E3D6B678330B0020648AA2B2B9B7B7A67E38111320304870A1D0D8C2BDBE9874340000145BA0B5B6BE98561B002B7590504365A3C7BDBDBBA16E738989643523273759A1D5FCF2E1B08D64413B535448477BAFD5D6C29F6A3D3A2E292422488CB5C4B48E602A101D1917243F89D8E9F3273759A1D5FCF2E101FE6A61070718A07C75694D1F0000000B2F5C98AB9ECADED69B4E0D000023579ECEE3EDEDD0A97F3C0F00001029609DBCE2E3E1DBC6610C00020A2B60B7C3BDC2A1551100000000051C60BBE7EFD4CEC49C6C20000000296BBBD9D8BDB9C5BF977052291E366EA4B9C3B5A575635F310A00001A54ACE9FEF6E7B364210001327CA0ADB2B2B9BAA56A290E123044597CA9CCD8CCBCB093683504001A63A2B9BFB08A441609357C8A433C7BBED2CCC8BE9C7176908357311C213465A3DAF0EFDEAD7E543D3D4249454881B9D6CFAE8D553747443C202A598CAAACA174451D11241E26244891D7F8FA213465A3DAF0EFDE01FE6B61070718B07C72643F1A000003113877AAAAA8BAD6BD80370300142D6EADD5EAEBE3BD895F240200000D327AB5DDE2EBE4D7BA4B0000000C2F66AEC8CBC8A655110000060B0D316BC8E4EACECBC9A14A1B00000E387BCAE7D5C0CECAA1725E4B32293E6F9CB4C6B49C7354421700020B2865B8F0FFF1E49D421200034690B5B9ABB4BEBE9F58251524405F7094B4BDC0AFA9A696682000001B6AADC5B4AE8132111947899B4F5C93DBEDDFDAC6A6868F947B451D0F142D68ADE4F5F2D191604133414851516899CCDECDAA7749283344322B3A72A1A69C846A361F152A2F3025489FDEF4FB142D68ADE4F5F2D101FE6C61070718C0727C623A160605162C578AC1B8B6C7D1B4722807061D4B7CB1D9DFE8DDA66B3F1C0100072D5392CAE2E9DBD8DDAC37000000163A83BEC5D5D7A64C13060610161A3372CAEFE5C3C2C18D4C140000184F92D3D6CABDCBC59E7B714B2A25437BA3AFA7AC985B3A210800000D336FC3EAFFF0DE99410E001756A4C5C7B1B4C2B88A4D20171348728BA0BFCEC5BCA4947B501C0000246FAAB5C1A96E27060D4780985883C1F5F2EAECDDBAA59FA2783F0C12283E78C2F1FCE8C08A553834474F44445BA4D9DABE9A67393932404D4A4E88A1A19174522917152227272E5AB2E6F6FE283E78C2F1FCE8C001FE6D61070718D0847F6340160A0F224078B5E1C8C0D1C0A14E200806275C95C7DDE5E6D48F4D1E0800001F3965A3D4E6E1E6DECA86210000001A5090C1D5D6CDA84D060003111A294C99D6EBEACDC4BF8A470D000013519ED1E7CDC8CFBC907176553434667FA2A99FA59A521C0500000820418ACBF2F9E9DD913906002075B6C2BDB2B7BFA070320A13275E8296A5B9C9BDAB9A8672411200002B6EA8C3B79E5A1818366C9DA46DA2DFFDFFF8F8E5BFB0AC8B69321D1F254492D3EDF6E2B88045263B5C4B485D7FBCDDD1B180533C4230565E556B99A599795A421A0D092537313363B9E7F7FB254492D3EDF6E2B801FE6E61070718E0766D512D0E07192D5B95CADED2C2C5A97C3712080F3F6CAAD0DBD9E8C37834120000112E4D80B2E0EFF5E1D2BD6617000000245A96CCE2D4C79237120B0F111D365C9FD8EAE6CBCEBE923E0400001F74B2D9DAD2C5C7B17F677060363E698CA89B8DA38F4011000000051D58A2DAE8EEEED17C210002267BBBCCB6B4B2B999471C0D09296F96ADC0D8C9BEA48972673C0C000A37729BB2BC974F1C17397AA7A285C1FCFFFFFFFFEDC7B2A48F59311C264365ACE7FAFBE7B0643D2D3C525B587098C8D4C6A37240314826545D7A87A8A288624A3619100D2A41293471BBE8F8FB4365ACE7FAFBE7B001FE6F61070718F0746A4D20010D153C6FA4DDE5D5C4B49E6426060A244D84BBD0C9C9DBB35B190001001A406A97C6E1EFD9E2DCBF57030000123D77AFCECDC5BB8A3C100E101D2C3F70B4DCD9E0CBCFB98D3B0400002B7AB6D4DBD0C4BDAA7A5F6D50293F719BA79087897D3E00000000163973B9EAFFF5D8BD741C00012F87C1C9B3AEB7B38240150E1433759FAABBC5BBA99A745B57310B001C3E7EA2B9AD8843161A528EB2A484CAFFFFFFFFFFF3CDBC9B8559372E29527CC5F2FBEDD1A563342D354D60667FB2D1D7B58B4C30334218567A8B97AAA28A5E4D2A110A0E242E293A82C5DFEFEA527CC5F2FBEDD1A501FE7061070718006D613A200E152B588DC6E4F2E4CCAB853F150D103669A1D2E1CBCEC5974A1300000B214D7CA8D7E7E2D9DAD3A73D000000125A87A2BDC5C7BB6D30131B1B25395A87C0E6E2E3D9CDBA72290000003883C1D3D0C1BABFA46763764D274A80ACAC89898E75290000000B224680CFE6EBEBE0B55C0F000F4E95C6C1A7A3B2A968280B06093E82ACC3C2BEBBA1875D4844200902294F7EA2BEAA7E381525649FB2A895E1FFFFFFFFFFECC6B5A57653351A2D6C9CD4F4FFECBB925D31273E6169739DB6D3C5A068361A3548235D7D93AEB4A78D6B4C2C0C00041A2A2F3E89C5DEE8E36C9CD4F4FFECBB9201FE716107070810766447322E314C7AB2DBFFFFEEC38B6438251B395A7FBBD7DFC2BEAB7C36050002114477A3CBDAE5E3D5DED3982C0000002A6496ACC3BCB8A25B2A1A1A1D2D507498D1E0E3E2D8C7BE72290000003493C2C6C6C4C5B98F5B6077442D5798B3B4938B9066100000000A32599ACEEAF4E6C7A24C06000F60A3BDC3B3A1AB9B5C23110B183B79B5C8C6BCC0AB7A5644341B0A142A5A83A5B49562291E3F7BA2AB9EACE7FFFFFFFFFFDAB2A499733E241E3378B6E6F6FEDEAF774B232640616C80A3BDCEBC8A522A1E3445306181AAC0C7AA926A49230B0E091C30305499BBCED9DA78B6E6F6FEDEAF7701FE72610707182084634A3A3D4A6F93D6F8FFFFE7B16D4C2918264479A6D6EFE1AC9A9761220200081F599AC8D6EAE8F0DDDFD18E170000053A83ACB2B3AFA9884F1F141B27366B88ABCCDCD6DAD7C0A25E180000004293C9C9BDB1BCA37B5E676941355F97A4B08B8B85540C000001254070BDD3E6E6E7C0893800002168A9C4C5A1A2B39849120B121F3B80B6C4CEC3BB9B6C3D2D2C180F25507690ABAE995019184C91AFBDA7A2D9FFFFFFFFF7D6A99E87582E22274C8DC7E9F7F1D59C66402B3B4E6D8095B7CDD1A5663E1D183237215990B8C4C8BFA0765721050A101D3038639FB8BCCBC38DC7E9F7F1D59C6601FE7361070718307056403336547DB1E4FFFCFFE09F5C3319162D5A9FBEDCEECD9B807C561401030C2E7CB9DBD8ECE5E1D6CEC584180000124D9AB8AFB2A7A36F2B11121F2A46739DC1DBE3D8E1CBBD9C4A0E0200034B9FBBC0BABDC0A470505C5C3C39699BAAAC999586490300000123538CC9E8E7DAD8B6722900062F7AC1CAB9A7A9A68A2F0F05010C3D96C1D1CCC9B2945D313436161B315E84989B987C3F141B599BB7B5A09EDCFDFFFFFDE7C7A08E794E3315284F9CDCF8F8E4C28D582C1622517097AED0CFC89D642D0B13313D2C4D7FBECFCFBAA98B5F1A07150E0C264A7DA0A3BAC5A99CDCF8F8E4C28D5801FE7461070718407D5A3837446088C4EBFFFFFFC9814F2C191F3B6EA8CED8EDC19B6C5B391E0314264694CEE8F1ECE3E3DECFBE630500000E5D9DAFB0AFB0984C220C1825325C99B9CFE4DBD0D1C5B99246120000005AA2C6C1B5B5A88652415E52373D6EACB9AC999A793E0300000A2E6A9BD4E5DEE1D79B4D1100084A97C2CAB99E9AA776290A041B1E4597C2C4C9C2B58A544239210C2150849CA5947E5F341325629BB4B59CA3EBFFFFFFFFEBB69F8A7A5B302C4371B4DAF2EBDDB17A5031222E467AA3C6CCCFC28E47140016353E344F8ABED2D1CBB18A561A0A221724405080908D979586B4DAF2EBDDB17A5001FE75610707185079644E4C5C7AAFDCFFFFFFFFBF7532190F225293C8D6F0E2BB784A382B11101E2653ABE3F7EFF3E8DACFC59E420000002475ACACB1B7B88F4B1607131D3A66ABCBD0D8DED1CAC1B485361102001164A9BDC1BEA8936E4A3F4A45364583ACB4AD9691763A0400001C488CC5DEE4E2CDBE883011001E56A0C5C9BA9FA29961250509102A58A0C8CDCDCBB38158433924192E5F8C9D987A774C230E3472AFB7A98FBEF0FFFFFFFEE0B59388805C3F436092C5E7EFE7D5A36E39201C2E518DB6CFDBCBB687370A0009243A31558CC2D2D9C6AB8A5714062F211D456487837C7C826FC5E7EFE7D5A36E3901FE766107071860705B5062658BC1EDFFFFFFFDB260371D223B64AAE4DDD9D9BD6C38251200061E4067B7ECE3DBEBDFDAD8C5A1320000113882ABA4A7B7BA8A35100C162C3E7ABDDAE0DAD3BFC2BAA56D2E100205267CBECDC7B8977B543233393A315795ADB0A6918B66230000012A59A3CEEBEAECEFBE621600002975B3BBC7B4ACA78B451A0D101A3A6CA2CCD5CCC8B57F574B37181B4378A1AE9B71502F0C093679A8B6BA97BDF1FFFFFFEEC99A83797A605A5C76A6CADFEDCFB49468402815284D87B7C1CBC1A86D2800000D1B2D385994D5DDD6C2AF7E4A0D002B3934608E806F5C6B675CCADFEDCFB494684001FE776107071870856358627BA0DAFFFFFFFFF7A2542717243873BBE8DCE3D8AB592B14100F1B385280CFF3DFD8E6E3CED5BE8429000017469AB3A5AFC3BB80250907162B5AA3D1DDE2D4CCB7B0AB8E60301D12103389C5CEC5AF8B5937191F2B203065A2B5B4A494774F220401032D71AEDBF3E3E1DBB14C090009368DBAC8C6C1B1A47039180618203175B0CAD9DAC7BE915E5638191D4E89A9AD925D331200083F85BBB4AA98ACE6F7FFF0DABE9169656A726D737DA8CADCDBCEA282563A1D0E1B478BB6C1D3C5985F1900000520213D5D9CCAD6CDC5AB7E3A000028485882927E6243494D3CCADCDBCEA282563A01FE7861070718807661616988BAEEFFFFFFFFE78740241C25478FD2F9DCE0D692481D0808112342567CD2F4E1D2DFDFC2C0B46617000C305B9DB19BADD1BC792A0A051C3E6DAADAD7DACEC9B3A79B7B442D21192758A9D1D7D5B3672A15000E1D2B406EA9B6B4A5957241200D121C4791C8DDEEF0E8D7983D00001651A1C3CECBC1AB925E230D0D1D253C79C4D7DED4C3B9866A603B1B206491A6A887441E00000D5298B2B5AA91AEDEF0F9ECC2A4746659667D807E7FA1BFDBD9C7AC7D5631161015478CBBC6D0AD813C000000001F2C4E68A4D3E5DECCA66E3500032953729799734E35433A27BFDBD9C7AC7D563101FE79610707189072666B839ACFFEFFFFFFFFE7813C2326385BA4DFF1E6E0CE8635120008132D485F8FD4E5D9DADCC8B7B19B540F00163E75ADAF9CB8D1C477240F17284F80B3CCD0D3CDBFA2858160373531234579BCD3D3D5A9621B000000171F3D74B3BEB6AC976C3D261E19284D99D1E5F0E9DDCB83210000216AB4D3CDC7C6A17A4915121918274382C4CBD5DED6B58F7A5C2B13286999B1A8712F040000275CA8B8B0A391AFD5DCD9D4C1A46E4F5468738D8D8899C3CCC6B2947052240C0C194D8EBDC6C2AB85430000000214295A73B3DEE3DEC28E591F0000366090A79D643F4541322BC3CCC6B29470522401FE7A61070718A072707796B4E4FFFFFFFFFFC86D3719223C6CB4F5FBEEE2C879330A04031A3D65739AC5E1DFDDCCAF9AA5843703163C6688B8C0A3BBCFB26C1B060E35629CD2DDCDCFC8B38864554B3F3C39345680C6D2D6D4A34800000000151D4187B3B7B4B7AC7B302226282D5BA2D3EDEFE9E1B96D14000E2C76B8D1D3C5B98B562A152127242D4B85BFD0D6CACAB489886D27102E6E9FB3A167210000002973ACB8968B829BBFC6C4B7A27F5C45405D7A848B8E94BCBBBCA48A653E2816081D598EB0C3C3A87327000000050E25667CB7DED9D0AD783E0A0002306EA8BBA45E3D31342413BCBBBCA48A653E2801FE7B61070718B078758A9EC7FFFFFFFFFFFAB668301D26457BBCF3FAFAE6B45D1F000307224A6E7A9DBFDBE0D7BD94888E722501114F80A1CABEB5C8D8B3591D0B142E6BA6C7D4D3C9BEB4734A3D33404A434E739FD0DBCBC5953E02000000041B3F82C2CFD3CDB56E322936343B5CA6E1EBEFDECEA4530F0016478AC2D4C9C2AD7C45100E252D2E35498FC3D4DCDDCBB697935E130A3175AEB19A62190000002D78AEAA887F858EA6B7B09A85664937395A7D8D827F90A8B5AB9E7F664B291005255C93B4B5AE945E140000000015387086C7D5D8C6AC6B2D0200083E71A9C1975F49463A2626A8B5AB9E7F664B2901FE7C61070718C07F828AAADAFFFFFFFFFFE4964F2E1E345F95CFF6FFF9E7A8501400000D2B658189A2C8DEF9CFA7735672652009266AA4C7CFCAC1CBD2AA5E1E08194281B4D7CCC4C5AB954F3115253B4A41568CBCD9DCCFC280320000000009244594C4DBD2D0B76C282734353E73B9CEE0F3DDBE8B3B0C0B2A589BCFD1BBB6965B1E021B3A3D3A3F5A98C6E4E0DCD2B19A8A4D16124279A3AA904E190000013A85B4AB7A77859AA5B5A69E8B684F32395D80968C8483929A97807963492D1B1A36739BB4B8AD83580E000000001942859CBFD8D3C29F5A15000000306DA9C6A75F5459412817929A97807963492D01FE7D61070718D074839BC6EDFFFFFFFFE2B98748322A4A739CD2F5FFF7E28D461E04000E3C64908EAFCEE4EECD8F4E3960431C173D80BBDCE3CDCACECE9B4610061E5195C3C9C2BBB7A7904516001F3F4E456DA0BFD3D6D0C37929000000001436518AC7D0D9D6B574303444484071A4C2E0E4D7C26E20071E4D6B9FCBBCBBAD823D0C012C4451494C70A8CAD6D4CFB3999A83440B174588A6AA864C0B0000005199B9A17483798A9BACAA9685643933486884908B817F8E8D8C70615848311C1F4C80A9B0A8956C3F070000000A2D6D87B2E0DCC3AE8951110000002C74ACBB97625B5E3F211A8E8D8C706158483101FE7E61070718E07892A9D7F1FFFFFEEAB9935A382D364977B5E2F4FEFAD47B290404011C487E8EA3B9C3D7E5C16C2F1C3F3719245C9ED6F1E9DEC4C6C1874A16082257A3C8D0B6C2ABB18E3801001C4D5F4A71A3C7CFC7C4B5681700000000283F63A1D5DECCCEAA653B474F394B70A9BDD4E2D4B155100C2C668EA8CACCC4A86D240208325660595671AAC1C6D9CAAF8987672905205C91AAA3853E08000010629BB59F717B8095A6BEACA38F785645557D909184747C84857566625441232032598DACB1A5846435020000001B407693B4CDDECBA97E3610000000276FB2BFA6645953351920848575666254412301FE7F61070718F07492C3E0F7FEFDFACD8E653E21273B5E93D0E8F6FDF4C4672D01000411567F95A6B7BECFE9BB5E1E1830281C3775C2E1EEE6D2C6B8A46E351E12286BABBFBFB0A9A89F712900002253575383BCD2D3D5CDA154090000000634577BADD7D2CBC9A6623849534E5575ACCCD4D7CD9F3D0A1E5481ADCAD1C5B598490B000D4667685A5F84ACC2C8C8C7A48980581E081F6493A593783D0800001170A6BB9B7D8A798CA7B3B7A890774F587488989C8D757070555D4E5356412E35527AA9B9B0997447280F00000034659698B9C9C3B2936B2F01000006276AB6C8A55B4E4D2D201F70555D4E5356412E01FE8061070718007CA9CDEDF9FFF3DA9F6B41271B254A75B1E4FCEBECE1A44F1B0B0E1931638091A9BBBCCDE2B34E1609100E1D398DD1EEF0F2CFB49F85563025132170B1C7C0BBB3A68A681E000028685F70A1D1D0D6D0B5853B0D000000295B6D8CAFCECDCDBD9451405D54425C77A4BFC9D4CB802A0C277199A0BABBB5B0802C02001F597971666D94B0C1BFBFB69A85844D0A00297799A99C7F4D1100001473ACB8A38886738A99B0AE9E8A7163655E8A9D95847E6D583E3D35353B3627456889ADB7A8886140280D04000B4F8FB4A8C7D3BD9C734E1200020C11297BBCCC9C5B453A2E1A25583E3D35353B362701FE8161070718106A9ECAE7F4F1DAB56C30160F0E245B92C7E1F2E6E7D696461009070829657C88A5BFBCBED3A04D0D030306254FA5DBEEE8E6D19F84643D32241B357CBBC8D4C9B9A681440700043864767CA8C7D3D8CEBC86320A000000356690A7B2CACAC6BB834B3B5746436182A0BFCECFB66F2710368AB4C0C1BCB1945C16000026677F6A647FA1B9B0B6B5A4938B7D4200002E75A1A89E8F5D1C00003177B1B7A585835B99BBB7AEA4967F6B7A8C8C9A99877169523634292D3E433E5F7C9BB2B3987148241C181905296E9EABA1C1C0B17F5F3715010101113787CBD19D61402E1D1A25523634292D3E433E01FE82610707082077ABD0E6E9DACB94500F0701052A6AA8D5E3E5E9EDC770310E00000A3767809FA2BDBDC2CB8C370B0000002363BAE3F1EBE2C68763403132271D3780C1D2D7C3BD98692B00000F2E6184A5C0D2D0CDBFAE68240200000C588FA9B5B8C9C2B3A16A414363584B6087A5BACBCFA959110E5594BAC3D5C0B2904A08000D41778A70708CA0B0ABADB396848F6A240000457A98A7AC97601E04002E76A2AAA19282497F9192958C82777483939E99948C75602E1311181C324149708FB3C3AD8B5637261F1A191A4076A0B8A8C3B9A56C431F05000304144A95C7CDA45A4423151C212E1311181C32414901FE83610707183074A9CADDD3C8AF6A250000000E4484C3D5D6DCDDD7AB59280900020C36698EA1B2B4B5C3C3771F010000032B76C0ECF7E7DEAE653E222230312A4489C9DDDAD2C694551B000003305F94C1D5E6D3CCBC99611D0300001870B7C6C6B9B8B2A28C574350675346738BAEC7C4C299470C0A65A1B8C5C1BCAA762E000037629287716C90A2A79CA4A1837B84641D000743839CA3A99D621D000A367C98A99E8F713574807C7E837872788293919D9892785520000D0F2232425B8AA2B6C3A084492720262D2A285587A7C3A9BBB493463521120810101A50A0D8E0AB6D380D04110F20000D0F2232425B01FE8461070718407BA0B4C0BBB7853F07000000185A93C7D9D6D5DCC59543190E0109173C6691A0B8BFBBC4AF671A0000000C3586CEE5E8E3CDAC5F1E08112434283E90C7D3E1CEC8934A070000062B6CBFD5E0D8DACFBE905D231500002477BECAC5C1B8AE9C764B415C6E534B7D9AA4C0CDB982270A1C64A4BBC9C0B4945B19000E4A7B9587686E8DA59E9D988C6F707A500C04185A889FA39DAE702E040E4984A8AB9C8455156967706D6B676F7F95A4A3979A96714A19000006172844668BA2B8C4A974342015292628335C8CA4BDAAC1A9783A1A1811142B153066B7DEDAAB6A290A050417190000061728446601FE8561070718506DA4BAAEA993671E000000062D6CA8D4DEC7C5C2AB7E330F0100031A416E98ABB2B7C0CBA74C0C000000134389D0E4D4E0CC98430E051A36261E4790D0DED9D7BC7730000000092E74BEE9DFE4D6CFBA98662E1B11183982C2C0B9BEC0A07850354F637557547A98A7C4C2B16523002172AEB7C9C8BF8F3E00002C66949C93626D8EA89E979784676D6A3703002359869EA2AAA46C2800145898A7B29E834201735C4C4F525869859C9A988E9D9472400000010D1A2F4C7497B5BBBDA3612918223731343C70939CACA9BC9C692A0E040C283E344886B9D4DBB76A2300000B1F0000010D1A2F4C7401FE86610707186077979DA4A08E4B03000000124B8CB6D4D2C5C7C2A15A1C0C0705032C507698AFB8B3B7B18C3F03000000264E9BD3E9DECCB57A250408192B25244B8ED3E0E7D0B9681C00000010347ED1E9DCDBD7D3BEA774402C1E2C4C8ECACEC6B6A88B5F3A36536B7F61628C9EB0BCBC9D4A11002C83B1AFBCBDB575270005387C95A5905F728F96A1909A886363561C000B3D7499A1A8B2A86D22051F639DB5AB9B652200654D3535475166869EA2A69DA69B7435000000100D26478AA8C3C4B9945A201027342F323C6B8F9EBDB4B59B5D2100071C414F4868A2D0DDDBB0611500000D17000000100D26478A01FE87610707187077868EA08873390000000026619DC5D5C9BBBBAF7C3E1000000E1F3C5E7991B9C4C1B4B07D27010000083C5EA3DBE1DACDAB662503051D27242B459DC9DCDDC999580D0000000F478CD3E2DBDBD8D3CAA67C503B37465E92C2C1BBB5B084452839657686707B97ACA7AEAC8C3C0D053493B6C3C9C2A5580B00194E87A7A88A5E70919A91928772584D3C1600145982A2A9ADABA16920063075A6A7A5A25F180060423D313D51658A9CA5A09FA49D6F3A000000142039649FB7C5BDAC85420D0C292F293647788A96B2ABB2835B23070C234F667289C2D5E3D8A55B0D00000219000000142039649F01FE886107071880768A808979571D000000043584B5C9CFC0B8B89A6726050202112F63717A84A2C0B7A3996B220200001D5177A1D4DCD7C18F460D00172431242C599BC1DEDBCA9A540D0000001143A0E1E9D1D8D7D1CAB17C5857484D7099B8BAB1AB9C732E1B326B849181839CA4B4AA97682500014199C0C3BFC2984508022E6DA5ABAB77556A90989692816459492A0C0A3E789FA6AAA6A79D62271D44859EA0A29344010060462D2C39506B83A19D99A29F9676300000000F29437093BBCBB7A86C3A0A101D21132E567A8C9DAAB09F84481F0D0B1E507593B2C9D1DCDFA45A0A000000210000000F2943709301FE8961070708906E857B8068370000000005418EBCC2CDCEB49B7D450900000D1E3C6D7D7983ACC1B19F85471A000003386D8BAFD5DBCEAC70320C071F242A2A34659ECCD7CFB79143060000001C58AFE5DEC7DDD8DBCAAA785650566B84A8CBC5BBAF89511712356778878191A4ADA898803A0800074CA1BFD5CEBC7E2C050C5D93B6A69F604554869D969B7A4F3F34190E1B528EB1BEB5B0ACA04F18224E92A8A9A984360300614F3E36424D6F91A1ADA7A6A09B742E0000000F20436FA0B8CAC0956330000E1F131B3D58798A9AABB59D6F4D1E2928455F9CB3C6DDEADFCF9B4000000000250000000F20436FA001FE8A61070708A076898B89511F000000001F6FB6D3C6C7C5B197631F00000016325D84836C839EA98F7B683B180002185AA1A4B7E3E4C5A04A160510273437314277ACCBD7CAB18031000000112F77D0F4E5C4CFD6DBC49564535358808FB3C9CBBE966D250400205C6A8591B0B5BFB0854A1600002464A1C7DAD3AF601A031E69A1B6B697594A608BA4AC885D443D2C11113979A8C0BDBEB1B39A4E1D1D5C8CA6A8A57E3100005346383641547B96A0A3979CA28D66230000000A1A3C7AB4C8CDB58C552006101B1C214764767F9E9BA2986D403039454E7B9FB8CDDDDFD6BC8337010000003A0000000A1A3C7AB401FE8B61070708B07C9287702F00000000063986BED3CCD1C9B8994E0B0000041C4B7F9A85697A98997C5B4F1F0F10113885C2ABB1CFDBBF743D1105192E36383E5187B6D9D0BAA46921000000053086DBF8EECFCDD7D5C683524C4C52829BBFCFC9BA844D1200002543517CA1B7C3CDAA743B0C000B306EB1D4DACB96441402308CB1BDB6874F385F85A8AB95613A3521191B5894BDC8BFBEB2B08E45293A759DA7B29B702200005D5A505153657D92ACA3A99F98825728040000001C4682C0DDCDB7884515112A222227597E757E9CA6A78854383F554A5C7BB0C5D3D7CFC3AA6C24000000103E040000001C4682C001FE8C61070718C06D7D805C2100000000114E92C8D0DAD6CDAE7D2E000000102F649AAF96827B92886644321001060E3F92BFAFACD5E3BC61200613243334485B78ADCEDFD8C291541E000000113995EAF8E9DEDEDCDAAD5C2D2B3D4F80ADC7D9D4AF76350B00000C354666A6D0D3D3A3541C0203193C85C3D9CCB273390F19589FBBB0A87945455C8DB2B185512D271A123475BCDADFCBC2BCBB8434224C879EABA897661800006E5D6673727AA0ADADB0A18E8D744D1F010900081E4E81C1DCCDB08D3E0C1C302121285C867A8B999DA2774433425057699DBDD1DFD2D9C099600C000000074B010900081E4E81C101FE8D61070718D08092884300000000002D6AB3CEDFD8D2CFA9681F0000001F5289B4BC9B9C837B63392C1F0A060715479AD6B8BFDADDA8591405152C4046596E92C3D3CCC9B89C58110000000B40A7EAFCF7E9DED6C08C471A12234676B1C5D5CFB16C26000000112247789FCEDED6A24F17050F305092CFCDBD90532E122C69B2AE9A997A424071A5BCC991531F161121438AC5D9E1D5D8B19D763F33678FA2AFA79D5F0F00026065585C6986A3B3B6AB968F7A67401200000000155094C7DFD4A96A2D1B2A3E3C323C798E7E7D9F8C917946323C4F5678A1CADCD8CCC0A889410F000000135D00000000155094C701FE8E61070718E07C7C5822000000000E447ABAE1DDD6D5C2934101000000356CA2C7C1B9A7805B3C1C151904080A19499BD3D9D0E0DBAF4A0E00081C30497594B0C9D9D6C8B9954A0D0000001B54A6E2F5ECE9CEC8BC762E0D08264E86B0C9CBC7AF6A2A00000000214983C0D7DCCF8F410600104172ACD4D9A96E2E12144491BAB39D805A373D709DC1BF843C1D0F0A275FA9D2E5E4DCD0B29155323B6E9CBAB5B0985C1505197B68636B8298B3B8B5A6957E6D482902000000032964A2CADAD6B377332C3F49444558778481969D8E896234253F5B6482A4D0E1CFC5B094622400000000216A000000032964A2CA01FE8F61070708F07263370500000000185193CAD4D8DACEB9861F000000084186B5CBC2B5AD713B2616171609060A2660B5D2D8D5E6E0AF4613030A21336683A3B9D0CEBEC0BB9646030000002150A6E8EEE8DDC5B088480D00043469A0C0C2C1C0AA6425000000002B55A0C8E6EDD387340A00175A91BAD5D1944A14061D51A2C3AB896039263E7EB3C6C58337100410336FBFE3EAE3ECC49B70462B528AA9B4B4BA9A4914042C6D6D6C6E86A2B7B7AAAC9E764C3B1800000101072C77A7CFDAD2A86736354E55606477878785928C7E7E56384151535E71B0D1D7D7B4967243100000000D38A3000101072C77A7CF01FE9061070718006F542000000000002C6596BAC4E2DBCDBA6C13000000176C9ACAC9C5C1A4622F0C051F1A0A030D2760BAE8E0E1E3D3993A0600051C3F72A1B7C3D0C9AFB4B78D37020000002960AEE4E9E7D5A48D712D0400093984C0D1CDBDAA8E65290000000D3D78B2D9E2E7D0763202031D66A5D1D6B474320B07276CA9C09E794E281C467BAECFBD782B04010F3A84D0E3E7E5E1BE7C513430649BBBB7BBAF87450C17496F5F5E6985A7BCB7AF9F886443230800001013164179A9C4D7C8AA5C2D344762778395968E8D8B987F82564B3F514D6588B6C3CFC1AF844A23060000031055AC001013164179A9C401FE9161070718106B3800000000000A4276A7BFC9D6D8C69D4403000000227AB5C7D2CDC6A75D200003222915162D4479BDE4E6E3E5D0852E000004133E81C0C6BBC0B8AFB5B78B3300000011386DB4DEE4E4C59F7C51180000105393C7C3BFAF9F713D0C000000256596C4E0E2E4C96B2504123680BED0D6A1561A0811418DC5CBA1744420254E88BCC5AC5C24000027529DD3DDE3E2D5A76334233B7AB1C1BCB89F7531142D5E705A586888ABBBB2AE9B794B2812040C1F2D2D294C83ABB6BEB794451D2348708892A2ABA3A3A4966E71544653565E6F95B6C7CABA955D381400000004237DC01F2D2D294C83ABB601FE9261070708207A3C08000000053D7FABBFCBD9DCD7BF842C000000003A92D0E2D5CFCA9E5D210009291E181A3D5784C3DFE9DBDBC5742A0000001B4EA2D6D1B5BBB3ACBBB6884200000B2A5B88C1D2D9CFAF7543290F00001C6B9EC0B7B7A57A4B2B0800000B327CAAD2E7E9DFB0592306133F93C7E2CB8C3B0A00105AA8D1CFA177421F2C5391B3C1A7571600022F6AB6DBE3EFECCB95441F224188B4C8C7B79C6B200C356F6659445985A9B8B1AA926630130510103643464B74959BAAB1AC774C1D1B4D7490B0BCBFB8B7A68B6864493D4B4F5A7890B2BDBFB58E5825000000000C4A9AD43643464B74959BAA01FE9361070718307E36040000002466A2CEE1D9DFDBD2BC7C21000000184DADCBDFDEDDCA9C4310000122291720516E9BC1E2E9DCD5A05C1A0000052058A8D7D7C1AFBCAFB6B47C4205061740668BC2D0CDC592552F180B010C377BB1C5C0B8A3754313000000174591BAD5DDDCCE9A4713001850A7DFDFC4752D0A012478ADCDC3AC7F371F2E64A0C4BA8B361000023185D1ECE1E9DDB1723B0E174E9BC3C5C2B79B48100A467D645038568CB2BEB9AF8755320000072A405F6158889595A4A19465280A164475A1BEC0C1B8B9AC95676E4D36484E587F9CAFB6B8A7854215000000092D6FADDB405F6158889595A401FE94610707184079481608091F5191D4EBF0EBECDDCDA25712000003276DBBD3D3D9D4CD93471100001B1B18417789AEDDEBE9E1BD894C18000013317BBAD6D4B6A7B1B8B7A47C3B1409326186A4B8C5C2AD773A171510000D3A86B0B0B2AD956A35090000001764AFD1E9E6E6BF7C2B0E112265B6D8D8B9712600003487C4D5D1B9883A243873A9BAB0742300000C4390CCE0D9DAD1A25B14021F69AACCC8BFAF772C0A0E4E8072565074A5CEC6BAA7875C27050A1C2C567C8C879D939A9E9D7F5727031B477BA8C5D4C1CBC7AE9266634B44454B5A84A4B5AEB5A8784013000000133387C1DE567C8C879D939A9E01FE9561070718507143211A173672BDF1FFF5EAECCCAD7C3C0D00011F4E88CCDED9D7D8D298460A00081E2423588EA9C5DFEAE3C7AA652D0A00061E5391C1E3D3B4ADB8CDBD9B6F411D23567B8D98B0B2B59C502508090D001C4D89B5BFBEB19D622202000000236DB6DBE6E3DAB0651B04112D68B4DBE4B5611801084090CACFC9B4893C2C457BACC29F621500001E5FA9DBE2D5D1C1773A15052E7DBFCED4C3A463180018598C6355546797BBC4BA896E3D110A132D4765929EA6A39A999882633E150A173D83BBDCE0DDCBC2B09068644B382F2B4D819BA0A0B19775370E000003184CA7D0DA65929EA6A39A999801FE96610707086071462B272F5590E2FFFFFFFFEEC48F5B28040319447BBCE5D5CCD3D9CB923B0E00021A172D6EB0CAD5E3E3D9C18A41140504083170ADD0E7DFBCB1B7BCB39878552A3C698E9492A0ADA984370D021B0F06245B97B1B7BEBFB56C1F000000002F83BACDCCE0CF8E492319173A79B6DFD8AF4E0A000A439AC3CCC8BC8A3D415D96B2B38E3D0B0008347EC1D9DCD6CEB1732600063485C2D1CEBE8D4304001E71947563719BAFD0D6C1A1663D3136323A5180A3AEAFA28A8F8F754B200007265487B6DDDDD4CAC5AF8A545537321E264C7FA1A8A4A89F85431602040E2367B0DCDE80A3AEAFA28A8F8F01FE9761070708706F4D4346547FBDFEFFFFFFFFF7B47E3F11060D305D9FD4F1DAC4D2DFD1903B0D000012285591D0D1E2E1D3D5C37E320C0409194188BDD3E0D8C2B5BFB9AE85726130428799918895ACA06D2C02061B14132E5587A3B8B7BDBB7721000000002D83C0D5D3CEBD7D46251C204083BDD3D3A74504000C549DCCC8CBBA7A414D72A1B6B47F360500093E87CDD4E0D2BD82411100154C93C5D7C5B9732B00002C7C9C746F6889BED0BEA98D663C2937424E5E84A8B8B99C81827E6D3A1805001F569BC5DCE2E3C6C5AF874B6336191918387A999895A4936F37160E0E0F357BBBCFD384A8B8B99C81827E01FE986107070880786750606C9DDAFFFFFFFFFFF4A55C340E0A22448CCAF0F0C4B8C9E7D5853508000E254274B4DCE7E0D6DEDABE76280000001658A4CCDDD7D2C4BCC1B6936B6D5C345088979B8089A69B6D1F040D1E1917435D7390ACB1BAB6782300000008438EC7CDC8CCAF6B4332393A569ECED4D191350000084FA3C2CEBEAB773F6085A3AC985F1600001D5CA4CBD9DBD0A36D230000165CB2D6D6D0B15F0E000D4085A575797E9BBBC9C0AB91673A2F4450617389AEBAAB94828178512207010A476BB5D6E0D5CAC6B194743F3F38260F124682A28A99A18E6A371C030E115889BEC4B789AEBAAB9482817801FE9961070708907B6D6A6C84B8F3FFFFFFFFFFE48A3D2016173369A4E2FDE8B5ACC5D8C9762F0E050E306DA4D0E5E7DDDDDBC4AA581C0005000D64BBDADBDDCEC9CCBD956B556764415C9EAFA1909EAC915613061E34241C44616886A1B4B9B271230000000E489CBFC4BFAE8A4F4753595D85B2C9D1C68C2900000050A2C1D0BEAA6855739AABAF9451100000306BADCBD8E1CD8539080000256BBEDEDDCFA4460500185491A285939AB1B6BDCBB2825F4637445D71759AB1BDAF8F757E77431B00061D3F7BB3CFDFD7CFB8A1905B404C2F1C0C174B8A9D97939D926835231D0A1A599BC5BB9A9AB1BDAF8F757E7701FE9A61070718A07D7C7591ACD0FFFFFFFFFFFFD2843E231E273D81CEFFFFE9AEA6C0D3B96B240601143782CCE8E6E1E2CCCFC79E5C310C0000225AA5CDC9CFD3CDC6A67D554A574A4367A0B3AA9BAAB58838101C374C38365659596F94B6B9A4641D0000000B4FA5C1ADA78C6445486E7E81A7BECED1CB761800000C529DC5CCBD905450879C97A37E3C0200134F8EC5DED3D0B2732C0000032E83C1DFDECF902A0001306FA098899FADC1BCB7B39E85552826465A7193AAB3BDB2927B6455290800031C4281C1D8E4DFCFA38A62422D4E3A271D2551949F8E98958B6B461F1E0D237EB8C39E71AAB3BDB2927B645501FE9B61070708B07E737A98BFF0FFFFFFFFFFF5A96229202B395B98E3FFFFCFA9ADC7C19A4B150400164B9EDEECF5E3DECFCBC48E442911060E1E5FACD2D1D5CDC5C19857232F3B404579AFBAB8B2AAAA823C1D2A5268524E6E63525073A9BEA859160000001558A5C6AF9372433B6A97ADAEBACCCECAB55A020000105197B0C7BD8A5659959F9E976B250705296F9BC5DEC9DCB1550700000A42A2D4DDE7C7781A000D4182A3A98B9AA9A9BCBAAD976C4B252029527596B1B6BFAB8F735034110000192A5D90BCDADFD6B8936843333154373428346695A3A5A0907855383224184291C3C79055B1B6BFAB8F73503401FE9C61070708C075788CAADEFFFFFFFFFFFFCB8243312C324268B5F3FFFDE2B7BDCEAB6A340B00071755ACECF2F2E1DFD1BEA76B352523130C2771B9D3CED5D1CAB28639101421274788B2B5B1BBBAAD73331D436F70575B7C5F434568A9B58E480B0000113466AEC4A27E4C2B3D7FAEC4C9D3D2CCBBA049020000185AA5B8BB9E64485F97A4A5905B1F040B4887AFC5DFD4CFA746000000235AA4D1DDD8A95717000D5CA0A799899CA5A9A198A28C5C301D133C5D7189B1C7C0A2896D3A0E0400000F33609DC3D1DBCFB3804E2F2F37684E4F456D7E95988A96916B4E302312174999C7B38249B1C7C0A2896D3A0E01FE9D61070718D079859CCFECFFFFFFFFFFF2AF602D22263C5990CAF9FFFEE5D2CBD1914F1D0000012965B6EBE8E2DAD9C9C29250322D321E1D437DB6C2C9CEC2BC9A722200000B1D4991C8D0C6C2B79E621F295A768876808D683E486FA5A96C2E0800041A407CB4C29366321F4289CAE3D7DBD8C4C68F360000093362A7C3C3924A3E69A7B7A9813003001669AAC4DBE2DCBD8C350000003170AFD5DACA873705082870A3A59992A7AAA3A6A2A5905E3323203B5C7D9CA8BCBFA9886218000000001E375B9ABDD2D7CBA970382E2C36885E56566C8A96847F848461483424231D5CB0CEAE6A2CA8BCBFA98862180001FE9E61070718E07C93AEE7FFFFFFFFFFFFDE8C44221F3453719DE5F0FEFFEFE0D9CD8234090000043175C5E0CFCADACAC8BA71291B3A47383B5189B0C0BBC2BFAD894C0A0000001B62A6D6D7D2C8AF9155283C778E896F848B63463A6CA49D52230000102A608ABEC69F562015318EDBDDE8E8DFD2B66B1A0000133A739FC5AC74383E74A8C5B881300000196FADCFD5DCC8B37E280000105194C3D3D5A8641900003977A9BC9F849C96A294928C7E52331A1C415A7A9CAEBCBA9784570B000000041E3F587EB5BBC0C0A15632183D3B7B5F5D768A8E85796F8B80563B32291E367FC0D2AF5A24AEBCBA9784570B0001FE9F61070718F07387AFE9FFFFFFFFFFFBBD66342025375C86B2EBEFEDEFE6E7D4B36C1C0100000E417AC5CCB5B4D4D8CFAB5A291B3C53514D679FB3A3A2B3C4A66125000000001A6EBDE5E5DFC59764342D4E88A8927782927D5D4D80AD8B4011000012487A94BCC0995014043291CEE3EFE7E0D0AE5C0B0000235388B2C3A561374881BCD0BB601800001E6FBBD4D0CAC4A259130004285FA1CBDAC694470C00164292A5BBA6849299929798A2725E2A1E1D3157748DA9AEAF987E4900000000021A314C719FA9B6A591513236374A947379919F94715C616156413F3730294892CBCBA05026A9AEAF987E49000001FEA06107070800778CB8F7FFFFFFFFFFF2A7522614234A7AA7C4E4F6F2E6E1D2C8AB510F00000011479ACDCCA9B2CFE0CE8F3F11122F5071768AA8A098A0ADB8833C0B000000073884CCEEEEEDB3753E1E2C649FAE98909BA97C655D7C93672E0D000E2D618BB6C5CB8F4408032D8BCEEAEBE6E2C7934804000E3E7590B6B779442E5A9CBDCDA8560800003486BCD7DAD5C7974506000B3F83B8D0D19B612003001B61A9BEBC9A7F7F887F7D7D886F4C251A223D577B9AA39CAD956F3A0000000000172A466A8C959C958152383B46569D81849299826C5D5A624D343941464965AAD7C1974E20A39CAD956F3A000001FEA16107071810728CBDF2FFFFFFFFE7CF863B0E1325539FBCBDE6E7E8E6CAC4B2863A080000082E63A7CDC6A39CC2D3C67B2E050D346C8F9EA2B7A596A1AEA06F23000000000A4085D4F3E9D292603011216FA4A09791A5BA9B8D74836E481B0300184D85A4B5D5BE813200072B78C1E7E4E7DFC876290000245C90B3C7B56A282C62A4C7C39F4A0300002F89BFD5DBC9BA771D000014549BC3D4C0853C0E00003380B7BCB9A57D7F7B8485847E5F3A21112B456A7C9DA9AB9D926A1E00003A140C0E1D49728888908A724834304158A28D9A9EA78A645E584E3F263144516A89BAD6C68B3F0EA9AB9D926A1E000001FEA261070708207194C7F0F6FFFDEBD9B96A2B0B0F3369B5D5CBD4E0E3D3AAA4985B2203000022478EC1DCC79596BDCCB57222081E3466A1B7C9BEA39FA6A6753B0800000000195EA0D5EDDFB6713419082772949A9B98B3C2B19E7D705B331A0E173B6A90B4C2D4BB63230000267FC8EDF2EDDFB0561300003779ABBDCBA453253478AAC5B78628000001388DBFD3DED9A95F12000E326D9FCCC9AD742202000B4898C0C6C2A3707174767A7A744D28151630526A87A1B3C1A4895E1900000D0D07042851818A8B877A5C3E2626366AAF9AA8B1A59578655245291828436F8DA9C4D5B67F3411B3C1A4895E19000001FEA36107070830748DC9E2E0F5FAE6C68F4A12030D3393D5EBCBC8DBD9BA8E867040080006183875BFE4E4C69690B7C4A14F1D100A306CABCDC6BFADA5AC84511500000000003976A6D7EDD9A95E270B0C2E708D8397ABB6C6C1A87245351D1414365F94A7B9C7CA9F521603082874C0E7EDE7CE88410D071155A6B9CFCF954E28438DBCC0B374140000113F92CFDADFD4964A12001E5194BCD1C091511C000213539FD3D4C3A07472707271786C3C290C132E3F7091A2B7B49C7F5316000008000E15345886A0978B7365401E153E6CB0B8B0B8AE95867C552C13112B447EA8C8D1CCA86E2E10B7B49C7F5316000001FEA461070708407186BDD4D2DDD9C7A169240901134995D6DDC5D0D4C7A475503920020001205096D1E3E3D5B897A5AE803F241A152A63B2D8DAD0C1B2A6772F0000000000184C93C3E1EFDCAA501A0000254A5976A7BDD4DADBB87B321E0F1D30578AB1ACB6C0BC8F4B100000317CBBD7EFF1D280280D042570A6CBD1C394362B5196BCBDA04C0600000A3C8BBADDDCC9812D09093575AFC3CBBE883F00000C357AB4D0D0C2976D61655A64613E1D08031224416795ADBDAFA87E4809000003101B2F557D96A49E967D5E423B344278B0AABBB9B292877552270E001B47849CC8D1D1AA69220BBDAFA87E4809000001FEA561070718507593A7B1AAB3CBA5651C0000001359B0E9E8C7CBD7CC89522C1F0800010F336AB9DEEFE1E2B79689987139341C182667C0D8D9D8C2BD9B4C1400000000052B63B3D3D7E1D2B25616050010253E6CAACFD9DFD9AD571A091C28507BA6B097A5C1A96F300F01113B7AB6D3E2F2C561180B16408ABDD1D2B876322766ACC1BD913E07000020498CCAE0E1BB7131131E5397B3C5C6A8622200000A4793C7D4C6BAA76A7169675E48391F1003192943749DACBDBBA58B460100000125323D709BB3AFA3906C50454141637AACB3B9B7AD9E88745E1700001A5791B0BFBEBDA368351BBDBBA58B4601000001FEA66107070860707D86908BA0A76D2E000000001369BFDCD6C5D0D3B86C3411020000021C3E86D0EEEFEAE1C29C838565474125161868AFD1D3DCCEBC802F0000000000044A91CCDAE1DBD2B856150000000C2B5CBEE1DADAD5B1571F060F356A9ABCBF94A5BA92561C020A224B81B1CFDDDE994C1C2D446496C1CECD9D58213584BBBDB77B2E0100052262A0C8E5E1A24F2115286EACC8CDBAA35A1E00032061A9D2CAB9B0A1726B635A4B3E290D000D131D48799EB2C5C5B17E410100000120415E8CA7BDB49F7D5B514F47485F7DAAAFBCB9AC9F96763E140000225187B8C3BEA98E5C3B39C5C5B17E4101000001FEA7610707187074665E728295824500000000002F82CFDCD9C2DAC8A14911000000000D26639DC8EBEBE1DFCFA0695C56575D351F3174BCCFDBD7C9BF74340000000000175AACD4DFDCDBD3B8571C00000005296CB4D3DADDD8AB4D1400184B7BAAC1C1A6ADB27A3600000E376CA0C0CCD2DA933A1A386387ABBEB9B780401B489AB8BFAC6A240400153C6DAED6D7C37F341B1D4A8FBFC7CDB77F3A0E00082C78A7BEBDB3AD985E6265453112010000151423407DA5B8BFAF956E3B00000008355D7299A7BBBDA17549504C56656D92C2B5BAB5AFA383673B0B00002661A2CDCBB4926C4B3B40BFAF956E3B00000001FEA861070708807760496C828264230000000000388FCADBD0C4C7C38A3D0900000000122965C2DBE4E2E4E5CE8A583E2F56663F314475B9CFE0D4CBB581360000000000276EBCD7D6CBCEC8B65A17000000001C54ADD6E3E7D59A40030B3877A8C9C9B5A4A19354150000164E88B4CAD4D8BC691F204F809BB2B19983502124589BC6C1AA611D0712295B8CC4DEE1AD641C14295699C1C4BFA75E20000011579DCCCBC1B4BD937174673F1800000519180E1E427CA7C2C3AC9E6F380000000C406285ACBFC9B48E634A535367757A92B6B1B8BBAB96885B2700071133639EC5BFA78558413D53C3AC9E6F3800000001FEA9610707089069574A70807145040000000001448DD2E1C6C2B8AE6F2C0700000002133980BAE1E6E6E3DFC0864231315B5F48446389B2CBE0D6CFBC832700000000002471BAC5CCC5CECAB4591B000000001A58A8D2E0D7C8852D020F3289C6D8D1B9A59E6E2A0300092173B9D2D5DED6A34E15296F97A7B9A481583311205BA6C4C4AF64200E123B75A6C4D6CA9B4E1F142C72A9B7CBC49C4C1600002A6DB0C3C5A9B1AB866D6E5D380B00001B1F1A140F4A81AAB3A1A0885F360700001A597B99B4C0BCB08F6A504E4C62758D9CB1B2B9B6AB8B754D1B0007133B81BAC9A99D7746343D72A1A0885F3607000001FEAA61070708A0715D4F72835A290000000000205BA7CFD6CABCB890551F05060200031B4778BEDBEBE9E4DFBF7827001148534D5B8997A8C3D7E0D1C7953A00000000063385C5D6D7D2D0D2A9531D000000011B599CC5D5D3B86A24041955A3CAD7C6B097814E0D00000A3A90CDE3E3E6C27C2F183987BABFB9855D2E1409216EAECDD4B963220D155095C5D2D2CA95390F183B7BBCCEC6B2813F06000C4580BDCEC5A8ADA46A63594D250000001518110A17467EA3AF9E847359311F1018436F94A4AEBBADA68256584A33546F93A1B1BEB5B7A17F5B260E00131D4C7EB6C4BF9C663E2D49749E847359311F101801FEAB61070718B0736A637374481500000000114665B3E2E1D1BA9E7942271A0905050F295B8FB1CCD9DCE7E3B75E1700062E45527FB7A4A2B7CFD8D4CF953E0A00000010499AD5D4D0CDC4B4934216000000042A529CBCD1CFA44C0E022060AEDAD5BDB2A7752E000000164CA1D3DEE1E3B6601C164AA0C1CBB67F431900052B74BFD5CDB3642010215EAECFD2CFBB833218204C8CB8C4C5A173280000195C9DC1CEC2BBB19B576355431C000007212D2018385E7899B79C7E7667433D333D648B9DA3AAA6A596745944474E597B88A4ACB7BAB8A8734E2811000D2A6DA0C0C7A78536222242869C7E7667433D333D01FEAC61070708C06F706C74501D000000000022578DB9D8E0C9A98A65382D2C220D0C20356C94ACCADEE5E2D9A551120002283A609FCBAC95B1D2DBCEC5923E100500001D5AA6D1D8CDC1C3AB74350F00000D2E486CA6C1CAB4713004051F68B8D6D0C2BCA967210000001D60A8D8E3DED69C4E1A1F60AFCED8BA732E0600124E9CBDDFD8B25923081F5CABC2D2CFC176270A204790C5CDBBB6732000002671ADC2C6CCB6B88D39695137100000001F2D2A2D446C81969181695F574C5053668597A4B2ACB0A59374573A4F3A54769CB0ADBEC3BA906F4B1D0001103879AAC4D1AD814718173E7D81695F574C50536601FEAD61070708D07981765A2A00000000000854808EACD1D5C49369442D474C41231F2D4A7A9690ABCFEDDFD087370A000621366AB1C7B09AB2D4DFD5B67D37170B09082B77ABC2BFBBB5AC8D4E1706000013486A80A6CFCFA4501900002575C5D8C9C8C6AF621B0000012E6AB4E6DADED084411E2472C3D5D9C880210000165BB0C7D9D5AA5710061F5EB0C5B9C6AE5E200C145796C9D1C5AD641A00023780B8D1C3BCAEA9600866532E0200000011223E43346E7380816E5957526366617290B0B2B2AEADA1937967524D49527599B2A4BDB8B48C60381E0D0E2D4E7CADCEC8996C401512417F6E5957526366617201FEAE61070708E0686C58360800000000001D68858BA5CDD2BC8E48352F5D7A542B0E26517B939297C2E1DCC47E2F12080D244180CBE1C7AAB8CBCCC1A36129201911183778ACC0C3B0978E5E2B0800000B3E73929DC3C0B4863A1000012982C5C7C3C5C5A0500D0000145086BCD0CFCBB7722A0C3D8ECFE1D9B46E2300003073B5CBD4C29B471309206AACB4B0BA9A48140312479CD5D4D8B470270A154891BAD1D1BFBD964D0061412710000000173E4F687783858D8164444B5D665A5F87A2B8A4A9A3A4978F7862574E454F749EADA8BDC0B48760492F271F34638EA1ACAD9354310E0A419064444B5D665A5F8701FEAF61070708F0736E5C2500000000000058A5B79CB0C1C6C7844025437A8E592E2E4571949F8B9BCBD9CDB15F20090D15295F90C6DFD5B3C1C3C4BA844B2F3A4228213C749FB7BFAC75642900000005215590BBBCC6CAB97F2C0000053885BCCFBDBDC0832D000000276EAAD9D0C1C39A5628194696D1D4D5BB6A1A000D488DBAC4C1C28A310F113480C2B3A0A485340506184CA5D8DCD1AE5B15002266A2CBCBC8B1AA793500703508000000001A4A53737A767B85774D33466066676A8AAFB0B09D9E929087756B5B47424D6D8DA89EB686A189553E39434659718A8A8F8E744931191D4A9B4D33466066676A8A01FEB061070708006D65461C00000000111A7CC3C2A2AFCAC2A96F2A2B578F8F59424D66909FA99CA5C3D6C38F3E1B131C20436CB1D6E6CCC1C4BAC2A868352B444B422B457697ACB1925B16000000001B4782C2C3CBCAC6B679260C0006367EB5B6A6ACA66F270000144F9FC9E7C9B6B880340A1755AEDFD9D9B3550E0019589AB7C5BBB5762C081C5997C0BEAAA3692900002055A5C5D4CDB65F15052372ABBCB7B4A693541E005D33150000000D2B535A768782828A6F483750655D65708AA7A59A9395928F847D7669554D466F99C09FBEB7A880583A404656687C896D5D9D62372F2B3665A7483750655D65708A01FEB161070708107564361F060216182B3998DED9C2BED7CA945C3746789C8A5A517091ACC6CBBAA7BFC1A065241A242C2E538CBBCDDFD1D2CCBCB57C391F2F415F53334F7990AFB98F3302000000002F6DA4CCDAD1D3C8B6751F000016417B9A9D99998C491300001B6BB9DFE2C9BEB7772C102161B0DFE2D49F47090827609CA6AECDAF752913316AB3CCCAB8A15F1705052766ACC6CBCAA34307002A82BABEB3AE9F8137090064320D0900001C3C50687A87828785643A2F4D5B616B7D8790968B7C8883847A85837561515D7A92AAA1B7AFA2764E3E47585B737D68454746402D36364E7FB83A2F4D5B616B7D8701FEB261070708206E5F4428101D28445569B5F3F2E4D6CEA97C4F3A57849578667C9DB6C9D8DBCBB1BFAC793D16242C283465A5C2D8D0B9B3BDB69F6329152A44766B5457849F9CA88D350000000012549DCDDBDBD0CFB79F5F1C0806213A638B908D7D632F04000B3885CCE0E1E1D8C86B2518366EAAD0D8CF832E060843879F95A8B6A3571E143E90B5CECFBD9C3E0406214A84B1C3BFBA933A060D3E98B7B8B2997B50160000583928271C21334C5A728D9194897E4F202541596B6E7E959D89777A7C7371797E89786755698B9CAF9CAFA793694F414A5D728278633D231A13112E3F6793CD202541596B6E7E9501FEB36107070830806852493B405673808EDAFFFFFFFBDCA576564F75938E6F6394C6E3E2D8E5D5B7AC93642B11293D293880B9D2D6C7BDADB2B58A3511111D3F8187737393A3ACAF7B1E000000002780BBCDD6D0DBCAAF8C4B1A0F153C4556707B84694918000A204F99D6E6DDE2DCBB6A211E448ABDD3CEAF582006125C97A29699AB8C49152158A7CDD8C7AB75240D0F406DA6CBC0BFAB631A000B569EC4C0AD8A5A2F0400006A50504440444B577C8D979F9C947C4C301C3550667087948D7C7570747571868F8B745F546F8AA8B98EA19B7A57434D4B657F877E612D0D030009274678A4CD301C35506670879401FEB461070708406F645251434F6695AD9CEFFFFFFFEABA87594E577888776972AADBE0E7E6E1D2AC9B7A4522264C523E4788C5DFD7D2B79FA9AA7421080E1F3889A49E96A0ABACA77610000000003B9ED8DFD4CDC7B5A56F381319395D655E6C878B5D2E0800092D5B98D7DBDBE3E0A653222D5B96C4D8CDA34A110A2F75ADA18D9A906322002167A9CACFCA994E1D0A22649CC3C9C7B88D500D012267AFC2C0A3613B0B0000016858525654535D6A7C8E9BA09F9371452623354969839598897C6F71716C636B808772615E7A97A0AA899F927758303257738B978960220000000018518BC8E3262335496983959801FEB561070708507C70635F65798BB0BEC0FFFFFFFFDDAA7C605C616D8167597CBBE7EDE6F3EDC69369503E2F415F584262A0D5E4E0DCB7888F945E23100D163C8EC3BFA19AA7A8985C0F0000000241A6DFD4D5DAC6B8834E30103D6192896E6D9595531D0000154077ABD5D2DCDFC6893014356EB7C7D2C38E3206104494BCB58D776A3D1B002C81B9C7BEB66F2B010A3978BACED6CDA67224030B347AB7C4B9A76B250000000C6865736463617B80A3ACC6B1A48E6A43312C3D4F7189979B856763656D6B6B67727B62636D8AA3A6B3738880684134384C6DA5A28F5719000000001263A0CADA312C3D4F7189979B01FEB66107071860726D626B7487A2CCEED8FFFFFFFFC387545058656461546487C4DCDBE7FFECB96D462D202B406566507BB5E4F8F8E1B77F7C8C562A1E15133792D2D5BAA4AFAE8F48000000001D64C8DFE4DFDBC19F67311B143780B1AF8886A195490D0000255886B3D7D8D2DAC1712813387EB0CECAB4702B0E1A54A8C3B8935D3A1A00012A7EB4C3C3A96018020F4998C5DCE0D0A05520061A4797BFC8C2A5551700000021707C7F81807D889AB1B59AA888927C50344058738A979498826B70737164585E6E7A706B7F92AA9F9E617D6E58493E38527AA4A693660000000000297BBFE1E6344058738A97949801FEB76107070870776A686F7A94BBDEFFFFFFFFFFF0A96D554F58544C565B6F94BBD4D5DFEADE9C502D1D1E394C5F4E6194E7FFFFFEE4B17263704D251F162354A3D3DECDA4A3AC7B3404000006306EC2EEEDE7E4BC844616131E458EB6C7A499B290400900003873A8C0D8D6D8CBA84F0E0E3C7EBACCD0AB591A052660A8CAC18C53200000003B85B9C8C79E4911082264A3CAD9D1C284430F1442759FBDBFB690440D000008396A70848995A1A7ADB8C2C1BBAF925E4742426271909BA39A8C6E646D685A5B556C7677838C9FABA590537466514943436085B4A9986D21000000002786C9DBE742426271909BA39A01FEB861070708807575787B87ABD4FFFFFFFFFFFFD180574A404C534D557583A2C0CEDBE7F1C57B360E09143543514C61ACEAFDFFFFE098533A51462C21242D5EB0E6E5D6B7AFAF823000000014347CC2EFFEEDD1A061200B0E20418CC3CCB8BAC0913C00000E509DC2D8D5CECFBE83370B093485B7BFC4893A0E0C2D6EACD1C6995B1F01010A448EC4C6B8802E0E133C83B7D4D3CDB36F2A12244182B3CDCBBA904100000018467A7C8E9796A9C8CBCDD3C8BBB08A6A4B35425D81AAB7A2A5937C726A5F564F556475819297ABA1A48A475C5C4E3E464C7186AAA89B753D140000004486B7CCCE35425D81AAB7A2A501FEB961070708906E69718697B5F5FFFFFFFFFFF0BB7B4124334A46495F7899B3CAD4EDEDE2B8702B0503062034415780C5F3EDFBEECC7842304830302B263477C0F6F0DAC3B5B376240000001C4A7AC6EDEDF1C47743190914253E8CC8D2CCD1BD713003001E66B7CFD1D8D0C7C06F19000C4092CAC4C0742604134A89B1CEC198531E00001A4D91C0CBB0732B020D4487CBD5C5BEA6541D163974ABCECCC9B48C32000000265B6D7488A6C6BCD6DBE3DFD2C698745A383C4B6C79A4BCB4B2A396836E544C51556A7C8897A3A8A39274344F5B46524D61889CABB098794D331C0F1F599DC2C4B93C4B6C79A4BCB4B201FEBA61070708A076797B90B6ECFFFFFFFFFFFFD99B5F3A312F35414674ACC5D6ECE9ECDFD7A9551A040006152A2F5497D8EEEBEDEAAC642C202E2F36382D4185D6F6E6DACCBDB6761E000004325794C8F2F0E7A2581600040C27528FC6E3DDD4C574280700297CC4D4CFC4C9C89A4C0B000F5A9CC9D1AC60170C305E91B7CFCDA9600E00001C5A9ABBCAAE591A0C1E5BABC4D2C9C78D3B0E114F94BFCBC2BCAE74220000003E7C6B6F8CA9C3D8E7E7F6E5D9CDA974583F48476588B1CEC8BBB5AC8E76604C535E667E8B8D9C9D96885F364D5F635156698FA4AFA295754E3C3E25316995BBB7AA48476588B1CEC8BB01FEBB61070708B07E808697ABFFFFFFFFFFFFFFC88553302F3132435884C2ECF3F1EAF1D5B0803F0A0000001423406CBCE8E9E0E7E5A2552320111A222839598FD4EDE5E1D4D3C6761B0000053770A5E1EBE0B9823F140607202B5692D5F2E7E3C1621D000A4492C4D7C2BFC2BD822700002167A4C1D4AF5215144585B1C6D4C4AD610C000B306F9EAEB584390D042679BAD8C7BAB87A2C0E2166AAC5C3C5BEA66019000011517F6A7494B3CEEFFBF7FFE5DCBA9968565546395981B2CBD4CCC5A791736156505F66839FAA9C9C84635929475D60585A7E94AAA39F95544B4240484B8394AEA89946395981B2CBD4CC01FEBC61070708C07A76789CC2FFFFFFFFFFFFEB9E6738222F262C3C6592D5EFFFF8F2E6C29D67310000000112224A8ED3ECE7CEDADB96452016151731373E588ED6EBE2DFD4CEBA732400001D5C90B7DFDAC69456310E1210283864AEE7E6E6E5B14B0A00145299C5D5D1BBBBAD5F1A00012C67A8C9D09C3F0D285EA0C1C9CACAA655140008377AA0B7AD5E2100002F7EC2CDC9BCA46B26112575B0BEBCC8C0A55A150000236093575E749BD1F2FFFDF7F9CEB294735B5B504C5C82B0CAC2CDCCB89A87604B5C5F698B9BA49A896A5648255268676B718A9DABA69775553736443C538BADB4A086504C5C82B0CAC2CD01FEBD61070708D07A7E8DA8D7FFFFFFFFFFFFD58D533126192635457BBEE0F9F9EEF3DCAA784D2411010B1115234D9EDCEDE3C3D2D2854C241E21283D556A7CAAD8DED3D7C9B2995C1C00002C76ADCEDDCB9E6B401E0C0C0A234B89CAE8F7E6DFA23E050015569CC8DBD8D1BF92450F00083480B6CBB67E2B104090BFCFC4D0CCAC541800144B90ACAA90450600002D76B7C5BAB9A9642B103083ACB1AFC2C39E5B110010447B9668687296C7F7F8FFFFF4E3AF986F6E645E5F7B97A3C4CFD2C9BDA17E6556585E6A879EA39C8368243D1F4F6D6A6C819CB1B2A393663F223746577BA6AEA47D6A5E5F7B97A3C4CFD201FEBE61070708E07A7D90A5C7F4FFFFFFFBE8B06F422F2A2432315B8EDFF9FFF0F0E8DEA9692B0906060F14172F5BB1F1F6DEBFC9C680351E22323D4B71818AAFD8DEDCD0B18661280E001055A9CED7CABA8147180100021A2F579BDCF6EFEDE0883901001852A0CDDDDCD8BE7E2E0004194C8CB6C1A8591C1942A2CFCEC6C7C3AA4D1C0D3874A0A39D7B3500000C4082B5BFB7B59750181B4891ADA3ACC1B6953A0506205998A255495A89BCEEFFFFFFFADEAD846F6C6F666587A5BFCCCCCECCBBA18A725554667B9BA9AB9063513E3D214E705D7B8FA6AEAE9B774325191C40277DB1B39C8168666587A5BFCCCCCE01FEBF61070708F07E8A8390A9CCF7FFFDDEC5A5623D2A292B364A6EB2EDFCF7E7F5F5DFA34513070C07111D1C3876C9F4EBDBC6CCAB6633252E40576B8BACB3BAD3DACFBA875D391200001D65B3CFC8C6A4692D0B000508213F6CB7D9E6F0EACF743201061456A9CBE3DBD39F601D131F3E6CABBEBE8C3A121751ACCFC4C4CEC69A481B1E49809C9E9567200000164E8BBAC6BCB186411B2961ACA99DA9C3C0843609012C709EA448404874ADDBF0F5FAE5CFAA8366706C6E75839BBAC9C3CBC5AF967B6156547D8378A6A48A6D543F4229546269849DAFB3B0996E3A201C31447196AFA9945B546E75839BBAC9C3CB01FEC0610707080078827C98A9B9E2FBEFCCA77E5A36302F353D5B82B4EBFFFAF3F7F4E199430E03071A1B1A234381CDF6F0E4D5CFA1572012243A568CB4C9C3C0D4D4D3AB673E160500002886B9CCCEC9A964230200040F285383CAE4E5F4E4B5571E0A071B549BD0EAD6BB7F41191F467096C4CCB6632204094BAEC6ADBBCAC49444203A729CA8998E4F12000019579CBBC3AB957337132D81B7C0AAC3D3B7692100093A86AA9E42364977BADCFEF2F6E9E5A77D6266637388A1B0C3CCC0CBB297887C69545E6E8FA5A993845B3F44432345586D889BB1B3A5906438271E495B819EB39E8556467388A1B0C3CCC0CB01FEC161070708107078838A8FAFD0E3D0A3896A453632353D4A779ECBEBFFFFF5EDF1E291320E000C1A1F27305491D9F7EBD0DBCA95481B0D173A67A4CFDBC8BEBCCCCDA45A18000000053084BBCACECFA15519000006103D6FA4D1E7EEEED99E58180E142857A1C9D7BB8C4F1B173A7D9FC5D0CAAC531600135EAEBFA8A7C7BF8B43305886A9A89B86530700013173ADBBB4997E5A2D1B488FC9C7B0BBBD9B4B0C05115090ACA0513B4F7DBBE0F9F3EDD8C39E8676738C9293A1ADBAC9C3BBAA93796C6456537898A4AFA286634C494B2435526D8FA1BBBE9F876B3D3137485F82A1BCA06F564D9293A1ADBAC9C3BB01FEC26107070820787C79818D9BB4C6A37D6548303431344A6191C0DDE7FAFFFFFCF1CF7D23030112262F252E5597DBF6F8F8DEC8823A14070E275EB4E2E5CAA7BDCCBD7A3700000000073D86C6C7D3D5A95E1B08000E2D5A95CBE5F1ECD2AB72371911233868A2D6DAB77725121D5F9CCBDAD8D09C4D0A000F77B6C1A5ACBAB37936326AA3AEA69B883700000F498DB9C7AA7C552E0C184FA7D2CFBEC3BB842400001E729AB5A0544F76A9D0EAEAE6E3D5BCA28C81868E99A2BBBDD4C4BCB29B8270615D5A608498A7A1978167514D49234D628096A3AEAB957B5C44454F647591A6A687634C4799A2BBBDD4C4BCB201FEC361070708307C7A7F807D90AAA38F684C362A2F33405272AEE2EAE2F4F7FFFAEAC26F280C1116252A2C385891CBF4FFECE5C38F481D0D0B1E65B0E3E8C7B0BCD1B76B160000000007338EBDC2CCD4AB4719090626457AB9DBF5F0DCB88749291E232E4A7ABACDD694521D0D2A81C6D4E4DBC398460D033181C0D0B8B8BC9A54264282ABA39D90753004002161A3BFB7A0603305002268A6D1D6CCC2A05F1200004089B3C0A154648CC2D4E3E4DADBDABCA4928C8896AFB6C1C7C4BDB2947D6B6662615A6A82A9B0A69A7A6657544F1D51708498AFB5A9876A53434D59627E9FAAB08C5D3C43AFB6C1C7C4BDB29401FEC461070708406F706D787C8790926A41302D25282A394B73C1FFF3E3DEF5EFF4E0AF6120090618222936456586BAD8F4F2E1BF9368350F0C2561C2E0E5D0BBCED4A4510E00000000104892CEC5C7D59C4E18030D2A579DD6E0EDEDE3A9532416212E4A6799BDCCC1863B0D0946A6D9EADDDCBE8C310109368BC1D1C9B4A58746184C8DA9A9A494722200032F7BA6B7BE94591800012970B1D3DACFB27C2E0000004696BEC2A6636F9EC3D6D1CCC9C6B4A38F8E777B8DA1B4BEBBC2BCAF92755B464A57605F809FAABBA684635B5A662C5A708B95AAADA3815A3C414F5E6B82A0A5A287664839A1B4BEBBC2BCAF9201FEC561070708507A756E7C82917C6F54392F212029364F5185CEFFFBE2EEEFFFF0D1924E16060D11212B49668595A8CEDEE8D8B693773F14112863ADDCDDE4D5DBC3883F05000000001A5197CACBD8CB9B491C13072361B1DEE8EAE6C67538120F283E6C8DB5CAD0BB742907104DAED5DFDBD2C68B2B03114FA5D2E0C5B1A3782F21588CB5B2968A611E00064088AAB7AD90520000083B7EBCCDC3B286530E00001B69A2C7CFA67B87A5C3D1C6AFB1AAA395867277848CA6B4BCBBC5AF8F766953475052546C83A4AAAF98886E68616E395E81979EA3A68F6856343B384F6B8B9EABA67B60473DA6B4BCBBC5AF8F7601FEC661070718606D7479858D8B7A6B4C342E2D2D3B465A6691D9FFFDE4F6F0FBE5C279432119141429395C889E9AA6BADADECBAD9B8A4A22203A6BABDFE7E6DDDEBF6C2501000000031A5DAAD5C8C7C084461D1811336EC2EBE3E0DAB16329121D244179AEC7CEBBAA5E24011A6DB1D4E2E1D0AC7628021B65A7C3C9C7BA996622205E93AAA19F81491100155591B1A6A48536080006468DBFCDBD9C6A2700000C377DB7CEBC976C95B2C4BEB4ABA296948079767C878AA4B8BAB7AE9E7D6C53494C4B4C59708D9FA69F917F676D5F715371899EA4A39C8453382F254955708C9EA79778594144A4B8BAB7AE9E7D6C01FEC76107070870707277888B856A56453A3635313C545F749FE7FFFFF4F9F7FDE3AF6B3C270D1D19274A70A6BFABA4ADA9AFA699B19F4D24274E82B0D9EDF8E4D0A75B240000000003154F9FD5D5DAB26831161C1B347DC2E6EBE9D7AD571B020B265198BAD3D7C79C501400166DC4DED2CFCCAB5813063172ABCDDBC6BA9F591C215E9EACAA9F7B380A001D6CA9B6A8A5753600001C5797BFC4A97836070000184D9ABBB9A6718593A6C2B7B09F8B7E807C7178737C919FB1C3BCB3926B504F474E545B5E6A8698A28B7F78767D6B70567D92A0A394917E4A382D3949546C8CA7A596785B3D399FB1C3BCB3926B5001FEC86107070880777B747E83716A5B4A413E3E464D5A7D8CA9E3FFFFF3FFF5E5C38D59372F1B191D2D4F92C2D3BFA3867076869DAB9A5A3342679AC2E9F1EBE4BE884C180E00000A16295BA1D1D9CDA94F2322252A3F7BC2EDD9DCCC9F4F2011092B6DACD7D9CCB68C4010032784C6D8E7D7C292400C0B3384B7C9CED5BF8A42182A75A1ABA9A26F2400002F7EACAE9993692B00003778ADBDB79F520F0000002F79B0BFA683497495A5AAA49D92806D6768676A6E7C8FA1ACBEB4A888634E4F4D4A59636B7690958E796D666B8173765B819CA1A5A084664926242F4A56839AA3A29168594842A1ACBEB4A888634E01FEC96107070890716F696E68625A4E4F46494843516C99B0B3DBFFFFFFF6F5C78C6C4A3C332D22242C5FB4D5DDCB9A6D51475E80988A6559739FBAD4E2DEDBD6BA662215110A0C142C395B97CAD2C99C53252A2A1C3974BADDE7E7CC924B070A083480C3D7D8D2AF82370F002B81C7DBDDC69C6526071B60A6C5D4CBCAB46A291F3C779BADAF99611A0003468CA9A78B895F15000C448EB2BFB57F2C0300001C509ABFC89C6423757F8E9791918169524D5A6066627580A2A0B0A8947D5A4845454D5C6A738990917F63565A636F6A74728F9DA8A4997C6246342C3A4852929F9B807D60585857A2A0B0A8947D5A4801FECA61070708A0707067685E5E564B5A545848445885C3D1C4DFFFFDF6F8DAAA69443C43413F3B2B4C7AC7E3E7DEA45D2D183A5F7B79697391C0CFD8DFDAE7DFB45C1F17111118394049567BBADAC48B4E373125284275BDD7E5E4D9973E0705072D80C8CFD2CCAC632205063295D3E3D0A87226080B307BBBCBD2DDDBB45D26224F7A9EB6AE95571200084FA0C0A78F78451D000B5A9DBDBAA3682A070001366EA5CCBC8043066C767C878477735A463A44566461768CA19BA0A78D7A544D4E494A5E677D939884735E4F5457595C73838F969B987F7255382F2F3B477B7B9DA6977E61595065A19BA0A78D7A544D01FECB61070708B07F78716C665F666C695E605D5879AEEEFAE3DDF9FFFFF3CC834E38434C43332A495CA2D2E9EDDAA5420600284E5F66768FA8CFD7BDC8DDE0D9AE4E200B0611306A856B55678EB9B182443F4B4038517DBAD8E5EACC813307000D3386CCDBCBC7A9571D060D449EC8E0C57F430D041B5290CDEBE8E0C59A470B255D839AA4A9823400002772ABBEB1996C3207002367A6BCBF96480C0202204788B8C8B98444066D6F807C847462543B274151606A7C92969AA09C8E80473C405B5962757E8C8580745548434D5A58708A90ABA49D7B6F563C3438405A688AA69D907463585F77969AA09C8E80473C01FECC61070708C06D66625A52595568756C635F617CB0FFFFE0D8E2F7FFE3B9622B223048494246658DB3DFE2E4D08C3705031F333B4886B6C9DCBDAABFE3F3E0933C1707001445909A815E4F66918664515C5C5353799ECEEBDFDCC4742E0A0C102A7BBFCBD1CAA84E09001365B8D4DAB1631F000C346EB3CBDBE4DDC180350F2D6682A0B39A632400175695BFC6B295541F00003787ABB59F89400B000D2D68A1C8D1BD8431006C727F6E6E6D5C3F322B34485065698396999E9785765E4A4F4C5A6A7D87878B846C463D364647566987979EB494584D34373E5453667B9FA8A18E725E58627B96999E9785765E4A01FECD61070708D07C665A5351556B6F897B6A666D88BEFFFFEBE3EEFBF9CA8D4D2720283D41415F8DC1EAF5EAE2CA934500000625384E95D2D9C8B5A2C1D4D8BB7C38170C02265BA0B99F6245536A6B57576E69697291B0C8D3D6DFBC8742190109236CA9B3C2C5954304042766B0CFCF9F440F0421619AC5D8D5DFD8C07020154480918FA5732F03002170A6C1BCBB87450900024587B4BEA7793509071C3A83BACFCABF913400776D747C79795E383C3D3A4156627E8E9E9AA88E85735949444E61788C878A8B7673503E31374059729998AA9A7E644D4148555557708E9CA9998A6D5E5E68879E9AA88E8573594901FECE61070708E0716C636464646B85977F75757C9DE3FFFFFFF9F1EDE3BA6B341B142136394779ABDCF7FDFADABC782902000E284066B1D9CCB3959CC0CDC3975F281411183B76B0C6AF764D40413E3C6182959FABBFC9C9D0D6CFAF7B4F25030A2E6EA0A7B5B97D290000075BA9C4BD8B40180E488CC2DAD9DCD3CE944410174F95ACA091591D00004089BEBEBCA66D31050006529BB9BCA3702F0713264B80B6C6BFB27B2E007676747D6C5F4F31312A35455D71808D939D9A8F806D5C524C566276888D8B968A65462B282E315A808FA7AD9A73563A374953636F8D9BA5A5A187705E5F7899939D9A8F806D5C5201FECF61070708F07C746260647077858E77787B87ACECFFFFFFFFFFE0C197522B18131C30385089DAF6FFF6E8C69C5E24050618364F81C0DDC89382A4C3C29D6739160F1C2C5582BDD4BE97633D281E34518EBBBEC1E4E1C9C6CEC3B592712C1D174478989BA89B530A0000094791B2AA7B370E215CB4DCE8E8E2DCBA6D27071C60A3B397733300000A47A0C4B89885561D00081C62A9BFC1AD6E34171F3C678BADBFC3AB6225007F7F807E77735845383349565E75839193959785786B5A5B5B63748397968584726448342332465F8F9BA39E8E7D5547425566666F8393A5AC9E847761566F8E93959785786B5A5B01FED061070708006F65585C64727A869289898699C0EDFFFFFFFFEEBA8E693E1F171D262F4363A1EFFFFFFFEBC383371300112C4C7DAAD6E2C08883B5C1AB713211010B21477FA4C6E8D8B67C411A11244A90B2D1E0DDD0B1B7BBC2B1A08550202F5C9BAAA4A58F37000000053A6D8D7F552C1A2F76C4E4DED9D9D1A5521A12326CA0A47C4B1A02082165B5C4A77B5E321302092770B2C8BE9A59282440617F94A7B7BC9D5513007979797C715E424232354B5766738B9C9096978578685E5E6670788A99938A8B78674421344051698B97A7A09374503D504E505E73909DA9A18C716C616D7F939096978578685E5E01FED161070708106E675D5A5C6B7F8186848C99ACDAFBFFFFFFFFE5985C4B312B34242B3B4870B3F2FFFFFFF4A65E2713061A3A72A2B8E6F3C48C8AB0C28E48090000092662A4BED2DDD3C8AA5C1C070E2F75B1D4D8E1C8B9C7B0A591948F6050618BA9B3A2905B1A0000000F3B5F8680501C163377CEEFF7EAE7CD84310D1E4F849EAA7B4114000D3576ACC1A56A43230F01103076B6C2A891543231507E9EA08F998F7034090079766F5D59514D3E3A38475F778193A5A4909174776966646C7F86908F8E8D8572613B312F4552738E92999B8F745D494C515B6A7E8C9C99998A736B5F668498A49091747769666401FED2610707082072685E6A63707D847B7F89A2BCE6F2FFFFFFFFCE804C353232332B2E3B557BCEFFFFFFFFE29A4B200A0C1D4C8CC5D9DFE9C9A0A8BB9F661B0000000D3074BCCEDBE8D1C7A865190002185BA6D4E2EECCB3C2A6845977836B7299AEC6C4B88E41000000001B4B7E94764019193983BFE4E8EDD8BB652719457BA6A39F7B360003224886BAB78846170902041A387FB3B6936831283C6BA8B8A88B7768512000006A63605F524740304C3F4A5F808C989896887D6A6864646E78818F94957D84876C634E464848586E8182999C8C6E5B4E464D5E738C95A09384735E59677A94A396887D6A6864646E01FED36107070830737571766D7180858E9099B5CCF1F9FFFFFFF9B6774335364A463638435E88CAF9FFFFFFF0984C1D08062353A3D9D7EBE7D8B9B2A67F30020000000D2C70BFD1D8DFD8DEBD641F00050E418CCCE9E2D7CBC997542F3948649DC4D3D2CBBD7C2A0000000A2E6B9BB6813B1D1E4290CCE7E7E2D39E4217246B9AACA5AC7F35060D376A8FAB97672F0B0000041C4583B3AF8B572B2B4885B8C8B3765D442209000076655C52474754443F465F6B8A90999992837365655D616D7287908C97918878655C4E464F4A577981868F8B877458574E5268747B8D8D7B75685562687C8EAD92837365655D616D01FED461070718406D6C6363616F7E85918F9FBAD3F4F9FFFFE7C499603F374E615C444C527195C5F6FFFFFFE698441B0F11245AA6E0E9ECE8DAD4BEA3652100000000114184B7C9D1DED1CDBB6C210000062D79C2DFF0E2DBC38A350F183259A1D6DED6D5B86C1C000000225384BABD802F0F1654B1D8EDE8D0BC783317408DB2B1ABAF80360717488099A284542700000B1A2D48789C9C704432315A9BC7C4A4774A27100000006864584E484D594B4A52656C8A93A1A09C8B7A6A60645E6B7B8D968D8D816670715545525164718293878E968669554D475A6D7E80927E6D69615B5F6C829CA69C8B7A6A60645E6B01FED561070708506E756D6E767E8B99A7AAACBFD8FAFEFFEBBA9569523E4A5F726759556B92B4C5DBE5E3F0ECA15225120C285FB9E9F1EBE4E5DAB492662A000000001D3475B7C6CAD3DFD0B3702F06000A1C6CB0E4EDDBD3C5752900001656A7D2EDDFD5A75A1200000C4578A3C6BB7730223D76BCDAEADBD0B5681E184C9EBDBEA7A4792C0D2A6388A09C804A20000012253A557E8A815D2F20376DA1CEC08A653816040000007B6B584C424C5647545A5D79959D9B9A7A7E5C756E61636482868D908E8971655552515C56677D848B848C838069564E475B748C8D9079675E5A5060618BA3C97A7E5C756E61636401FED6610707086078716D7280898F9FA8A1B3BFDAF9FFFBC69B7D5C4C4E5D74837E686278ABC3CBC5CDCCDAD29355331A223777C2E6E3E7EEDFCAB18974350900000A245085BBC6C6CDCDBFA25A210900002058A0C5E2DDDFBE621E00001C4E94C8E3EDD19A4606000032739DC7D8AB61312D51A0D0E3E4D3B5924F1214539EC2C1B89E6725083370A3B19F84642B050718395D77807A6341201A316DAACAB184552909000000007D6E4E4439303B3F425054859EA1A58F8D7A736C6C62626F7C7E88988E776F6250484B505D6F7C80828E8A7F6E44415C66697B928A8064585B55556777929E9F8D7A736C6C62626F01FED76107070870717580888A93A2B0BAA6B2B9CBEFFFE3B6956A554D525F708E81807F8BB5D6DAE6D7BFC6B28456342C2A4C82C2EAF0E8DCD7BDA296895414000015336488BABBB2D3BCAF773E1D0F0608295B92C3E1D8DEAF4F120000174A87B6D4E9D67D2A00001056A1CDDACC92471C3268B6DDEBE4D5AA8037132364B5C3B8AE9B5D180C3E8FAFAEA0936E320C0834617B8F8A6F4B1E090C2968B2C09F644017060000000066664F4741353539405162849696979F987E7B6A72666E7A878B8C91997057534C484650627380878489807A6D5854536168778F8F7E67555967656E7A8CA5A3987E7B6A72666E7A01FED86107070880706A74828F8E97A4A497A7B0CDEFF0DDB47F6D52566060747B84909393ADB4D4E8E6C19F8A6C4F4C4C5173A0CCE5E1E8E1D7AA7D8891622A0C07285B80A5BBC0BDBFAF814B311F1215061E5694BACDCDCF8F300000001F5A92C0DCE3B267220200286DB8D4DAB3703C1F3882C0E2DED8C69B642D22306BBCCBC6B3833A11145194B2BCAAA1803A122056869A9E8D653C0F00022361A1A3845C331000000000006A634C442C3329364C3C68AAA6A3A1948F7D7467676F636F7C8B8B8983735D4F494D556170818987828284785F4F4E575D6F8094887F6351505A6273809AA69F8F7D7467676F636F01FED96107070890787171858D9DA7A3ADA5ACB8D9EDEAD3A28064646D6868667695B9ACA2A6C0DDF1E0B1866D5D4D4F57699CB4CFD3EAE1D8C48E7B8A9D612717265983A4AAAAB2B6B8905B372E2B1A1515356BACC5BFB4A2591E0000063070ADCADDDBA1420800074780BFDACA914F1C173D92D5F6ECDCC5894B31233565ABD3CBB0762605296AA7B5B2B1A47A381D3978A3A89F815C280500002D5A84846A4E2E0D0000000000666050443C2B3942536D7889989AA79B8E8372615A5B5D718289898C836E54464E3949656785908E858279644B515B6764788B9090836B6063616A7A9494A19A8E8372615A5B5D7101FEDA61070708A0766F687A87959DA6AD9AA6B9CBD6D5C393786F696F6F696486C2E9DAB09496BAD6CEA46B4A4841446392C7D3D0D0D7E6DCBD795774845C3D2D4189B3C4BBB19FAAA87C3F2E4A4D391D2D4B7CA7C4B1865C320300000D4988BECDDEBB7D361109144688C1CEC47D310D154497CBE7DDDABE7D493A3E4B729EC1CC98481C0C2E7CAAB9C3BDA66C321F3F8EB5C0A98C4817000005225775745F3F1F0500000008006F6E574C4C4948536474828C98B0A193978170665C5A687A8A8787877F6F544E40444B61758E98957B7F75644B4D5B61677B898B8D7E6350618A788682909789978170665C5A687A01FEDB61070708B07C7B79838E9199A4A7979FADBAC5CDB6877470747B7A6F6D9BE4FFF4C689839FB8A6735639434F5172B3D5E9E1D3CCD5BB8B554C6E795E474F77AAE3D1BAB1AEA79E652D45696150504E67798EB6AA6E2D090000072D62B2D4E6D69B560B000C307695B6BCA25C290A093790CCE5F0E8B863433E565B689AC7C885350E164584A5ADB7AF975A292C5F9EB7BDB182440C0000072A4E606B4F331E100D040E0C016C656458594F5262777A7F8B999D999595836F645B5A6E7A867C888C7C6F554A3D67565E75838C88837F75685C59586171778A91848565616C67768A8C989A8B95836F645B5A6E7A01FEDC61070708C0777E80818B98AEA4A19CA19CA1ABB290837C848E96807C7AB1FDFFFFC18E78878E7C623B403A465480C2E4EEE7E6E0D3AD653D3E5F76626A8BAED1E7DABBBFBE96663525436F67657E8793938DA9A05914000000053C7BBDE4E1BB762E01011F5F9DABA89E773F1A001B417DBCD9DDE2B56139637C655383B8B3722F0D204C6482949E9779462A346FBAD0D5B782490B0000184457605C46301A0D0F0F0B110C697170666D60716D747C83869796918F847F807777736E797B85847B7B685C454653577072909194806D70605B5455686E8594938A77666268687C97999D897C847F807777736E7901FEDD61070708D0787A7883839EA0A3A5A0A794908C8987848294A392837F84BEFFFFFFCD9B857D6A594232373A4C64A2E4FDFBF2F7EEC87A40202735516F8DBACEE1E1E5C7C5BC7F3A060E3665667AA6B2B8AD97A8A5450000000010559EDAEED5A25313000A448CBBAF99845A24080013316C9ED5E9E2A65B588BA8694A649C975829213C5D695A6776735933264C93D2EEEDC6893F0B00071C425A524B3D2A10191A150D0D0B686B71736F615D7077828E99989289827F7F897D7972717C85867B787162504E4B54536B7D8995918F746D6A5B5C60647B8AA1A08573636570778093A29987767F7F897D7972717C01FEDE61070708E0756E6077799090959695977E75726A70708891A099868193C9FFFFFFD0A37B6F51483A30343D4A66C0F5FFFFFFFFF2A24C1B0A16284265A7DEE4E6EAE5D6CCA8601F00002650608EC0D6DAB7A4B8A246000000002181BED9DCB98136100C1C62B1D5BC9F7243190000163D719CCFD7C3845D76B6BC7B535466673A202C537C6F494851483E303C5FA4E1EEE9BD803A120714335F5E443C2B1A120D161620270B667676756D696A6A788488919392807868738580827D7F7C80787C756E5C49474B5E586F8389918B8D68716A6B5C5B6D78888C897D656067767B909B9991786268738580827D7F7C01FEDF61070708F0726C6D708183909A9FA58C7364625A6C6E7E8A8B8180859FDBFFFFFBCEAF8063442F2B2E3A3C5178D2FFFFFFFFFCE895490B000110286CB5E6F2EDEFDDD5C58D4A0B000016374D91D0E5E9DFCAC08F3B0000000B3889C4D6C297631208123984C1E2C9A7682F100A122F5488BFE2D3A0694B88DDD193523C483C1D274481AA8A482E2C2B1620457FC8E3E7D4AA662C0F1015384A4E42362C261D1C2323211D07837F73746B747F7F888C8A94928B7F877E75878C7C7C868085767273555D5456505A5A6978879399966D7577695D65737E809B965E68615D6F888B998E87745B7E75878C7C7C868001FEE06107070800747271737B8187889685867160615D6B637E8A857F8794ADD5FFFFFAD1B88E6A39292A383E4F5D80DAFFFFFFFFF4C57C38080400001971B8ECFAFFEDE4DACC833B0D000003304D93CCDCEFE4E4B87730000005234D8FC1C7AA6F2F0D111C50A7D0F1D1B56C2C0F08234479B3CFDCAD6E435EABDFD5AE6938261B1C375E9EBF9F5E321A0E11214185D2E4CDB5844526110716374943372C281F1E22302C2121147071737071787581889794948F8A776A6E7C727E6A7F79797D6664586255545C505A576F7A7D8D92896D7A7A6E6C676F8A8D94918574696C77869593956E5D406E7C727E6A7F797901FEE161070708107E78798582818E9792927C74686C6B7B757E8283828399C0DFFFFFFFE6B984542C2B2A2A3A495B8DD8FFFFF2FFEE9F542D0F090A1B3267B1E9FFFFE0EDEABF6A280100010833599EE5EAECEBDEAA6425000011396282929A87552A1019396FB6D5F1EBDE7C2E0E17376E9FCDE6E49F573B69B3E5EAC0713B0F05153A74AFBFAB623211030D1C5DACD7D7BBA26B341405001130393B38291D1C20232729222615728883827B7E8A8F9C9E92998F857D7471727A808880898B737362414A4156696167676C72788987887477716A6B687D8C9198918376736E7A81959B83665D4E71727A808880898B01FEE26107070820776D6F7B737C8185908481726B6B6E7272707D747D87A7C3EBFFFFFFFFC787563429273344455994CDFBFDF1F3C57C301C1013172A3F81B3D8FFFFE1E6DFB0531C01011626496399CBD8D5E8DD994A180A1535678B857F866D371B0C22427EC1E2F5EFD7743217223D83C0DADEC28240356EC9DDDCB47E290600115787C3CEA660230000082E7CBCE6E3C1975F2A090104152F382C2A1E19241A20242226241B797D7C8385838F889A9990818A756C646579777980898790806C5C685B525A63595E5261777C7D8182716F616B616C7E9099A89A8F8071727A818D9888865E51657977798089879001FEE3610707083066686A7574787E7B7068716B696E656976746C707A97B1D8EAFFFFFFFFCD844925182124334F769CD4EEE9DCE6BB652A121212232E508DC3E2FCF9F2E6CC8D4917020410336281A6D1C7CFE1D6954C18061E428BBCA37E6E46230B0B275590CDECF3E7CA6D2A17294B7AADCBCAB46E373473C0D7DBD2AC570D030E5BB6CCBD94511E0000033D8CD6E2E2CF9D562109020B1C293124201D11141C2323301E1B04A9B6C6C8C7C4CDD1C8BFB3AE95928A7D877D7E939BA2A4A09A7E7068605E606965727778767C775D702450626B717B87A1A39F978A7B748890959D98886C5E59877D7E939BA2A4A001FEE4610707084079786F7B82827C7C73706F6C6B76747A6B71777A7E9DB2DBF0FFFFFFFFCE845131202A30435887BBDFEBF6F2E39D4F1E0E0F18385282BDD4D1E8F5EADFAE6821060002234B82A4BDDDDCD6DFD5843D0B0B2C5FB6D2C3A27540170001174473BDD9E1DBB05D281429597C8BABA88B5325467FC8D9DBDABF6015102B7AAEC2C78D3C0700000C4FA6D6DCDECFA25A1300020A182E301F20140F131A272C3024210A83898C939DA4B7ABABA7918A8C867B746C6D6F798B9590A0887F6B665F505C616779787B62696F696852776E786E818B96A1A29489787D7E8A8F94997C6D66596C6D6F798B9590A001FEE56107070850676E69687A79787B7470676D6B7C827A7075736F87A1B6CEDFF0FFFFF8C781543A35393F50738ECAEFF1FFE9D58445221215234A6FA7E4E3CFCEE8D3CA7E380B00000C3A6F93BACBD1E5F5F4C26F2D070C3880C4DCD8BF86411E0000093073AACEE0CA8E3C131D4A7F8C879181533633599FCBDBE5E0C45F110F2675B0C5B886370E00001A539BD5D3D6C08D400F0007112D37352D231D18161D1B2D2419110A777C869DB3E1C4AFA6999383807D726161716D778A9C9E968A80666257595E625D6F7C84827C716664525D60706A7B8D989D908B7B7072768195938B736A575461716D778A9C9E9601FEE6610707086074756D6E6E7668697668797D7A82827875777A808C9AB6C7D4E1DCEBE3BA7B57424445485776A5D3F3FCFFF2B874331B1D172D5E9DD7E0EBBBBBCEBB935C260F0A0C183A80C4CFC5D2E3E6DFB05B1D09184697CDD9EAD59C4B140000023069A6C7D7B67F31122A71A59F897A5F34244476ADCCD9E1D8B8581C092872ADBEB28238030005144892BCC8C6B67A3E1409122132443A322922151C231E262A2828107A8694A09DACAFB1B4A09E8A827E7F74786C787F8994919D927A695D5D52565F687B86907978766159525C667278868E95979B856A6E676E8492948972615F5E786C787F8994919D01FEE76107070870766B6D706969736F75716C747F82827F7E7F80888C99A4C1CDD4CEC3BA99725F5B4B525B7499BFD5F8FDF8DFAE54280F13214273B9E5ECEDCBCBC8A6763D14060714285196CFC6B9C7DDDDCF9D471D081F65B4D7D8DEC7863D130001193D64A4C6CBAC6324233F90C4C099583A2E2E67A0D1E2DBD6CCA1400D06296FAED0B77F2C0501001343719AB3BAA178330C0918334A49433A25161D28262F2C201B20157787979C9A9BAAB7B2A390867D7B7A7374737B81829597979686706C5858655B667D86938B7D75645B4D606B6C7985939888847A706F6E7B828170814059637474737B818295979701FEE861070708807B83747673787A7976797A8F8D8F8A7F79788D9A98A3A4B5C3D0C0AA967867686D6A697F94C1DEE2F3F7EFC3783E1C181C2D528CCFF5E8F5D5BDB385533213110B172E67A9E1CACCD9E2D4B07230100F2A6EB1E1DCDDBE662B0605193F678FB5CAC58843161F5699CBCCA2673223387ABCDAE0DACCC17E330D0F3069A9C3BA7B2F0400081B3B527A959D8D5C200C1A2C4050554E412E2B2A25302B2A21251C1277788BA2A3A8B5ADB5A48E777D80766E7774888191918B97936F727E665E5E6D737C91918A83787167546162727C8599968E7971666D697486998A7D656365677774888191918B9701FEE961070708907D7C6F74766A726F757977958280858384858F9EA2A19EADBABBB08F7E7B707F7D8693A5C1E1FAE3E9E8C88E5E27121520345B91C5F8F7F7E3AF93613A1D10121F27457AB7E4D8D6E3DDB272471F0C0E3D75B8DDECD59D51200B142E588AA7C4D6C7773D0F20499BC9D3B978332A4F8FD2DDD7CEB9985617051A4075A5C7BA772C12111D2E223C637D7E6048241421304B4B534C3931272C2B292725271E21157091958C89A2ABABA8928983887A7B777B77878F96979F9B8A8B7864646C686E77858E968B897068674D5D626F8291928B7E7C6A656E70818C8783776E6366647B77878F96979F9B01FEEA61070708A0787172736D727875767474757A808087879297A5B1A39992A3A198807C7A7C9598AAB8C6F5FFFFF8E2C9985E321605041F3D628DC6EAFCFAD8AE6D43261A131821486FA1C7E3EAF9E7B5724123040720468BCDEBECC887431A0D17498CB2B6CCD1B96530122667A2D5DDC57D3B305C9DCDCFC5C2AB76431312326696A2B69754250A1B3B382A30426468503218172C40474B51463A312C2A262D2E272E27221C78828C8E8D9FA99B968E83767A80796F757883868995929D9E8A7C69656A6A7283928F9A907F726C644D6D6A73849291888078776970747F8F897F76625B6369757883868995929D01FEEB61070708B0717370716C70797877737C838083827F949CA6ACBAB3A28E8A81786C6F757F92A5C3E1FFFFFFFFFFE2AE692F190C09121F376991C3E5F0FCD79B5C35190814222F5B93D1E9E3E2E7DF96552B0C000D3059A5D3EBECBC632B1517316EB6CEB0B4BD994C1B113067A8D0D4BD74393B63B9DEDBCAC1925415071B4B7FA4B498663B151442645D412E4355514426151C3747465050473733302A272A2E37302C21106F87898485999B938A7871696C7D797780858B8D899286908C8A6E6C7073797E81919294827F6768605170757B7D8A8D85796E6B5D6F76848D867C796966626980858B8D8992869001FEEC61070708C07C826A756E75767A82828576798589949697AEACBEB99A8E7E7A6C65696F8396A2CFFBFFFFFFFFFFE198512603000B1F263D6893B7D5EEF4D39158331D101F23437CBCECF2DCEBE6BA6D28060006244C80BCDDF1DC9B4D2415213782C0DAC5B1A1763A1D1A4B99C0CED6AB64312E71BDD2D4C7BD773908082A638AA7987B461C172C698C7A584453523B190B1825404C5140423D2F332F322D2D342C2C2428197E7D84818A8B8A78716D6169727B7B83818587927F808084837979756B767D89948C998D80756F63635465708584858A7F756670647680868C8B8C826E6B636A818587927F80808401FEED61070708D066676068677070737A757074716E7B939596A5B0BCB6A18D7B6965686A6E6B8AA6DBFFFFFFFFFFFFCA7B3812110F161C2F3D6F8CB0CFE6F3CC86542B181C19345697D5FFF7E5E3CF96500F0001173D6E9FCAE0EBD7913B160D2E4E91CCD9D3BC8D4B281320589DD3D7C48B4A232D74BED5BDB1A46D361A1A4D949F8D6E49240C173B7AA5956A5359492F1D181A2D42544A373933332C2D2D38373032332A332381958F7A7F8077806C665E5E6D78777D948A8F888C817C7C766D71697078848688928D8580776F70685B6C7B7F898A83776E6C70697B838D9497747074686C67948A8F888C817C7C01FEEE61070708E06B746F7377777B7A7F797575787B878999A3AAB2C7B6A2876D62585C667C7E8EA4DCFFFFFFFFFFFBB06A3B2B1C141A2837486B91ABCEDFE3C07D452F26282B4272BAF2FFFFF2EABB74240100011B5E98B8CBDFF0C3823F1210275598D2E1D4B56C3610102667B1D1CAA6602316327BCAD5B99E885B2B18306AA7A1895D3D18101A438DB19E856C5844250E13223443464C3939302E2D373336303736323329177B807F7E776F6B645F5C5B5465707D8387888A848A7E746A6B68667A71777D8C91A19B6E6D716966636A7E7F898880787464676F777A7C8A918C877E76646C7587888A848A7E746A01FEEF61070718F06F64646F6868727675747E7D798088808D95A1ABB0AF9B85706364626C798293B5D1EFFFFFFFFFED9752463E2B2C30343D536C89ADCED5CBA16844362E1F2A4873BDF0FFFFFFE3A85D150001123172AAD0CACEDEAE642B12244372A1D1DBD5A962280611285EA8C3AB8A4D160F3D92E5DBAA8668412C284785BBB59E622C160A1F4E819F9D7C5D4E3D211A2128384752453337343030383A343B383D37292D1D87807E7B80646A5C6056556A676875868F8C98907E767164606467686D6F7B9298968B84776D6C636C6F7981888581786C6773777180807B858185806670747A8F8C98907E76716401FEF061070718007A74736C6E7880797F716B727E85808F8FA4A1A19C9994826C687068747C8FA5BFE0F6F9FFFFFFE08757555D5B4D434855555C6992BFD0AF82502E2B302B41558AD5FBFFFFFFDB84390500081D4B7BCBE6D5D4D89C4E2A1D375684B3CED3C28D3C140005235590AE956335112158B2F3EEB882553C26406090B8B88D57391E252B4F7B9090775B422F2926232931474B4F3A3634363A4245372F3B3B39392E1C768092817D725D534F4B51526A737D8A988F95928E89766B5D565565727688919598887B6A54596571737A85878C746F6869656E6F888D8F898483776B6A7781988F95928E89766B01FEF16107070810777673717777716E786F7A7D79818D90979095969B9288817A7271797E8196C2E6FFFFFFFFFFFCC07B567590796355687952505E86A5A67E4F3232322F2D4A649FDEFFFFEEE19F5B28020014295595C8EAE7D2C177422625426A9CC5DEDEB3712405000D21507B8E7B4F2C152B66B8FAFFD3814A44385C8EA7AD955E371A1327496B7C8A8D6F51371E26304241564A4341323A38333740403C3F333F3E3544267D89857E7467645A4E465754596780828D9F926D7E7C7668635B62637A807D8D9495827B6E6A6862707380867E76806C6365706D788F8A948F80786D676873858D9F926D7E7C766801FEF261070708206D6B6B736C6C79787C726B7280888690968981878B8880807F7A78888298AADEFFFFFFFFFFF3BF85554B79A68977889EA58C6A5769858A6138282A28303E517CB0E3F6FAE3B9753116060819346CA1C1DEEED1A35F28243D5A8594ADCAC499501301030F2B46707D6B482A212B68BCFAF9C8835B4D5B91BCC2C2845528100F2A577382767A5B3E282D32304345484C453B3736363D3F3F3E424243453A2F2D21828386776C5C574340494D5363788187918D907D83766E64615B5A687076838C9792807A736370767E7A8887827966735E5A5E63737F8686857468656A676981918D907D83766E6401FEF3610707083074736766696F757E78776F7D7782858E888C8880757C7A77818185888F9CB6E2FFFFFFFFFFD0906044507FA39388A4D3DECC976A57605840251B1C22365D78A1D5EDF8F5D290441F04000D203D729CB3D8F2BB7D442129518DA39491BDB9803B0E0000223D5C77795B3D21182F6FABDCE3B28672758DBCE3E7C9883B0E0E1B345D78866B5A43231A212A354943454752453B393C3A43424543433F48393744337E828180736157505153515264757F8B958D948B837366716F605A6667727C8A978E7C766A73756D7D81908980746962555C5D6F7C858582847C766B656C7D88958D948B8373667101FEF46107070840686B6C7067737569776E76797B8C888B7E7F8677796D707680807E8293A2BBE5FFFFFFFFF1A6634533407189828EC8F3FFF8C982614936231B1E2935477AADC4E1EBEDF3CB7E2B000000152F597E939FC6DCB16E35213B79B8BC877CB4A565270100062A4C7D8C8354302622315898C2BE9D86869EBBDBF4EECA7E351515203C65716E594533201C2831354844454D4B433B443A3F48464D4C403F42463A38296C7D7B6A5A52554C4F5454546567787F9092867F7E7570675A595F5D6B7B8389827C6F6A73747A7C7B818D8D7E78706356545C6D748182847972727C727A838F9092867F7E75706701FEF561070708506B71636B6769716C797279747D7B7A898D837F787573797B8586918D94A5B7DAEEFFFFFFDB834A30283F61788896D8FFFFFFF6BC6C3D23191A1A2C425995D4F4F3EFEDE9BB71250000000D26406284A0B1B495612B1F3F8CCDCE9F839B8E5720050C1A3C6C949586593C2D1F426292CEAC8F83A3C6C9E0ECEEC06D27101529424E605C47312920202A3436443F4449474341454347474B49483B3D3E3E403C3281827069544D324D53495161767B868C8981898375746D5F5B605663787687897A7372645D6976768C8A9287837C746A5F5B72707F8080837D6D70817B808A908981898375746D5F01FEF66107071860737569686D7072747E747079738781797B737979726B71797C80848E959EBCD2EAFAFFFFD079463D3638536C799EDDFFFFFFFFDA7E371A130C1F2D4968A7E3EFE1CEE4E2A65A1D080711213950748C9FAE9179592C244A93E1E8A692A4803F150005264E799BA5865E3D2722376491B9AB918CB6D1C5CEDED19F56210D12294150464030282B2C30343E394545464B4647363B45474D4A4B4D414143413C403376706C604D4D4F5459565B65798589888E8880756B6E626A60505B687179828C817264655A676E86957489879284766A59555C677C817C7D7A7B7582838E8A888E8880756B6E626A01FEF761070708707374727874777E7A7B766D75787F817D7F867B776B6F7177808A8F9C999EB2CEDDE5F3E1AF795237383E516D7EAAEFFFFFFFFFE087461F0F0E20335581C2F3FAD2D8D9D2984F16050C17264467819DB6AF814C36212F4F8EDAF6D3BCB6793217040D285281A7967D5039261E376891B29693A1CECCAAB9D9C888401D11262D3C413A353529272930354343484046474D4C51484E5054544B4245454A45403D2C656D5E5F464C4C554352596876898F858B857C6462665F59585A5F687881889A88785F5A60605D758B878A97877C6B645B6065737F7C7D6E666E6E7E7D8083868B857C6462665F5901FEF8610707088075605A64686B6C6F736F6C6C73767C7E79747673706B72727A889799A0A5B5C0BCBEB49F8870574B4C565D7492C2E7FFFFFFFFD38345232619253C5687CCFFFFE3DCDFB679431E101D263A6184ABC9C69962301D1D28468BDCFDE7DDB3692700001438748E9B9E8F5A3421152B578294939DB9E4DCACA8BEA76A2C0D0E1F314043312A282C1F2A2D373F414B484245454042505A4F53524D4B4A44454F443C2F787569563E444A4D57505D77839395888D8A8274615A6159587C5F7285818981756C59575C66717D888D919089756465595362787E847B5C5B60667C808C7E7F8D8A8274615A615901FEF96107071890706E65746E6F726F6E716D72776F7B787175727B727171787B81919EAFB0B5ADAAA9A08C7F655B5958606983B0CCEFFFFFFFFCCF7E4F34262730354C82CAFEFFFBEFE0B6632D16162735476D9ED0EACB82491E15122B4B88D5EEEBDDB358250A051C408394A6ADA16835150F26587A9390A2D2EEE0BDA9A383471A120B243134312E3B2B1D1C27363B4344494745494B4644484F585C5C534C47414A4A434533736D645C5856494A56636E6E7894968C88947C6568575F665C5E67747E7F8B8471635D60656B8482938D7F81816868604F5B6D8082847E7B6D6B6D767D8E817588947C6568575F6601FEFA61070718A079706B7A746F77777A7976797D7F7B7D717270727574787F817F8C9EA39D9EA295938F82796560555D6581A8D5EDF1FFFFFFE0A8735945372330446180B1EAFFFFECCC92513D2B2745636D83AED7DCB6723616181D3F5D80BDE4E9DEA24D220B17306292A5B5C5AF692E180C2A4C7A828C9FD1F3F2C6A8865F2F120709263A383B302D2C1D262F35403B3B423F44463A464144484F4C544E4E51504D4F46453666655C4E4E4249534E5A667781938B867F6F6C65635C505A6263747D827C817F77655A59576A7A8B9190897C746D5F6669646F828480756B665E5F748185896E7F6F6C65635C505A01FEFB61070708B0737368726A756C6E78727972746B717B7C7A797675717F767B7C8C939FA1A2A196978C726A5D6B6366757799CFECF3FFFFFFC490635A463831353D4F79A7D9F8F1CE9E7147372E4C7894979CB1CCD7AA5A2817252859799CB5DEE0D39F4F200D1F4887B6C2CAD8D67F3012051744789DA0B6CFDFDBB685613713020A132E333A3A373225262E27303E3642414243414A47414A48494C53484E514A56514B4D3E656656505E524B5A5A5D687E7286948D826A69635E5853616B727C858F8B857D6E584F5A5D617D7780848D8075635C6264687781848C755D6461686177797F72826A69635E58536101FEFC61070708C06A6A666B656A6769676B716B6D74777B7E7B7E6C6E6F7D717A82888E9D9C8B8D8886766A645E65656C7486A1CAFFFFFFFFE0A675614F494F4B48526E80A7D6DEC4A06F523A3E5275A4BEC6AA9DB4B684522D1A27356288AAB4CEDAB87B4025222A5C98C3CBC1CAC7814018111C4D8BB7C6D4DCD6C4995F3015090E0F24313F413A312A2D282C3433364A41423B40484A4A42494D4F56504D484C4A4F4C494A376B625C5E524C45486262697B7C868983746261535C615F646C757A81899779765F5A5256696F7D7E95928F85665C5E61605C78807C866E556966676B80948476746261535C615F6401FEFD61070708D07375777D747977818275716C6C7777747B78716F717480707C8883839294908B7D7A716564696A716D7C91B2DAF9FFFFF6C5956754535A64595B6E838AA4C7DCB87E4F3B2B395884C3DDE9D3ACA5A86535211E334267A1BAC3C8C797693F2424376DA2D2CBC4C5B8873E150E2461A0D1D7D9CFB8997645180B0B122736384B424936252F293038383B4442444B4447484F4B4C5054565A594E4F4D4F494F40326E5B575B4C464B50636C7978828585796862504B4B4A4A5972777A8B8A7E76786454595D6D797D88918C8A7365575965636C7B7E8E8F746565606E80898883726862504B4B4A4A5901FEFE61070718E0726F62706E748175726668717178727B7273766F7C75787F7F887D81878B888D7B7577756D67626B7C8894B1CBE5FDF4D5A9835B5268606F6E717C848DA4C1CCAE734B3531476097D3F1F8D5B5A68A52272D26364E74A6C2C7D3B2874E261E3350779FB0C3C3C6A068321D1B3A689EBAC5C0C3A57A58371A17253740383E404B3A3A3A2A373339424950483D3A404C474B4E4F56585957555B564C524D474342917C6A5A57525A57646C7683878782766D604C48455058697A7B848C817C7566595D605E5E72848E90908F7D756758676B71818A8D82696360647282878F89836D604C484550586901FEFF61070718F06B66676867656466635F766D6D70767B6D7B756F737472807A7D83838B8B848172726B666D6863767B839EAEB8D6E1D2B78C725B57677781848F949DA6BAB3AD8F693F333F485D88BDE0F2E6D0A37D4A2F2D2C41526E9BC1D4E3C27E4729263F648EA39FA8B0A580593B282A3C6D98C1BEB697805D41271B27313E4F484B4D46403D343A3C3749544D554F514F475D5F5D554F53585F5C55574849534C4F483C746463625953545C646D7278898B7B776A4D4845505564647581868F8C816A5D5959575B6C7F7F808A85877A61655C5B6677878E8A81726E6B6F789290857D6C6A4D48455055646401FE00620707180073776E766F6D7075785D65746B70697A736F726B7B71747D7C7F8087918B7B7A787775686F68727E798191A3BAC2C2B39D836764576C829B989BA8AAAAABAF9C816443474659718ABEDAECF2E0A66E432E2934585D7294B4D7E4B27A442F2B3A6E96968B8694856844322B26477994A598897C734D312C2C3D485C615D5D58534544403D47514E525B59524E4C4E53594F5C5C5C5E5B5551625654575149483C787A7E7972646A6A7F76738083847C7473584F4C4A5A627A85939590887C6D765F5D5C676E79818E887D756864565E62727D858F8E816E707279818D8C8E827A73584F4C4A5A627A01FE0162070718107B716266656F736E746F6C676774716D7476756B696D767775887E7B7E847779747874746E7176787B919AA2AFA8B29D91726763617B90A0B9B7BDAF9FA293806C55454E59697A9CB1D0E8F1D09A5E3F27333C5C707D85A0C4D6A671472E28407B9C9385797C694B413B413B526D8E9C887C6951493A333A455A635F575A62514B49414A5143525D5D6362584F4B4F566160686163646564665D5F5B474D4539827F796D6E656B6B71818583928A7E6F5E514D4C52547084879992878574646553535768718285847F7E7B776F605C65757F8A918F8B837374838A8D908C7E7D5E514D4C5254708401FE026207071820756F76736D6F7074736266726F71777A77707375787A6E7473707E82797D7878756F6C6C7576797E878D99A4A3A19F8C7867655F617C8FA4B1B8C8BCB392826B58524C556A8B96B3C1C8E0E1B3855640333E557F80858EA1C2B288563D32385983A8998370644934323E4149617B92927C655349423B414C5366616564645C59574F414951525B636262616565525F5C5856595E686E72675E5B64604B45493D7572756E6D72777A7F7577888A7D746654424851576F81858F8F8D8E82706E5F5B585D6D6B85838380797A736D65667276878A918D8278727B808690968F807C54424851576F818501FE0362070718307872656665697270766D616E7171716E75726065717374787478797181716A707573767073737C8083819398A3958A7C7B726267738098ABB9CCBDBAAE86715B545C525D7C9AB6C8DBD5DBD7A8764E3728425080949F9FB4ADAA764A3A2834557B929D97705C4A39333B3D525F7E928C775D4944353B4E4E535F63616162594F4D5850545C5C595C625D5A585A5F66635D66606161685D5E5F6268645A52513C71747F8888757B80898583838A84756D5841474853717892999E9088796D6566615B5B6F8285857F706D7675746A637183878E8F918F7F74767781988F989380584147485371789201FE0462070718406E64656B645E6B6A776A6E766577686E7A7370717071726E7273777B797F77796E7274727B7678797B79838D89867F7C7470676E76849AB0B9BBBDAE97866B5E4E57626C92C0CBE5E5E1D2C89861412E3152648192A1A5BCB5925D3B2E3246597E958D9175553E383A3F4B4B5B7275856549443B43424F4B5B63616C615E5E5A50544D58645F66686670666A575E61686C6565636471605C605E5D5F5E5253486D70787F8283828C8D937F877E775F585147494D58747F8A9598999082746D6865676477778A87766D6E767B7A726570807A888E86807A77777E859494908B7E5147494D58747F8A01FE056207071850725F6769645D6F716E696D656870766F7476746F696C74796C727B767D7571766D6F6D6B727F7875837A8A8E8C807F776C696E7D7B85909BA7ADB9AA90796E5F5A606D829AC8DCE7E3DDCBA4714D4637394D658092A4ADB7A5815A3C34384762758987806E5046383C4F585569707D7D614B433A51515E68656061645D685D5756545A5B58606062646763655A5C6167605C6B6B6E706B6269606060595D5049748173818985888F8A7E7F837F735C5B60524E595F76859E91938C837A6A666354636D7B8C8E85796A756C6D6A6B6A7E868E978F8E8A7B7E72808A9397988B8760524E595F76859E01FE0662070718607B70667967706E707465706D68687174716F7470727671716F707D78797A746F696F6E697670717770728084847D716F7073757A8086869A9BA9A9A28A7A6A5D5C696783A4C6E0E1EEDEBF9569504C464E5C6A7889A1B4B1AB906442343C55606D767B7161534B4348505A5D6A646F6B5F5D514A4E464C58635D6266635F515C53585F60646869696762615E52646F706B6E6C6E62616B6765605D5C62575B4E7067717979868C8F91817F7E7A66615C5F574C57637C8F98938F8A7D716A5E6055676F7B848283796A6E706E6F6A6E747B878F928C83787A7C858F9A9B918E8D5F574C57637C8F9801FE0762070718706A666C76676E6F6C6B66676F6D68666D74797064676E6D717374776B746B746E6B656E6E766E797A81727A84807D7E7F73747C7E8184839091949391877362555B6976879CC9E7E3DEC1A68A61584E5150646C828B95ADAFA7885942363D506B7A7A71695A534B4548585D5E6169736A634B49555B5A59625D5F6364616565615E585F6064636E6C6B6B635F5E656E6C6F66656F7270656667655E6962565148737774757E85888780817B76797568625654575C6A78898D8F8F847B6554575B586373837F848175666F636A6B6D6C7C888C9991938C787E847C8B918F918F905654575C6A78898D01FE0862070718807676716D736F7D7576706A7068756F6E6F7876696E696A696C7273767B6F74796D6C706871767A7572717F8081797376726B70728183848F8F948F81736C6A696871768696B1C4D4CBBE97715E575C63656D7B7E8493999B9B79604E50585962646A6F7675684F5355546E685F72686D5957514E555C5B5C6363696C676567625A605D63685C65766E6C656D606A67686E7A716B7070736A64665E65615E5243706F6B767C87879487887D7A776B635A57545E6267727F7F8C7B74756C554F586673797C878C8977777366686B6D6E757F83838E8383777B7B7A828C92928F9057545E6267727F7F01FE0962070718907B6C5F76737A737A7D726D716A6B777A71796B6B6A6F6D736A6B757674777A7471786C696B737379736D727E747775786F72747A7B7F81837C838A7C716E726A676D73848D9C9F9FBBA48C766D68706D7E807C8A87828B90897163575D615C676C6A6D76635E5657555E6A6D6C70746B66626169625F646262636C69656B675D5E5E696B5A616C7A6D6D6E66606A6E6E6A6E7370767D71746E645B66585F554B7A7A797D807A8589858775767B6F6D62686065656E7078828178756F6662615C6C727D7C80847F75726D776D746E7276737E87827C7F79718182858C8B899392686065656E70788201FE0A62070718A0747163695B656463655E646865696C7074676D6B6B646F686C74717275716C73746D6F6C75646C6C6A74727879727174717A77777F797B7F88817F796F6D706D727573758284868690967E776C69747B797E808375727B82787B6569646A5F65687076746D6A5E696B6C746C7170767A6C625E585F6365676F6A6C645F6267636967656B6D6A6A7A7C7F6B69686D6671767466706D6C7B6C6B6969605A5D5941746F6F6D7373797D8278726B72756E6D696664666A7E7B807A706B6F6A6A6B6D6A747981797674717678776B6C6B6E72767675777E7871737D81819490868885696664666A7E7B8001FE0B62070718B07A736A6B68696B6A756972696E6E676E6A676A73677071787A72757C7A7A666A6A656D716F71696C7070707C7270716F746D797F76757B7F7F7580786F69736C7078757F7C857E859381796E7271747772757F7C787A70797B7969676D6A666E6A64677266636A6A75756F6D706E76786F626565636269646C6C686F6C6F76736465646C716B6F75717770686E6E736B6D6B6B766F746C6B5F66655E6255564671756F73737877767B736A7C8082806A776C6D747D7474786F74666F717165756D6B7A797B787C7A766A787D77737375767575747B817A7E7F7C828683818A84776C6D747D74747801FE0C62070718C0777477726F6C716E7E6E776D6C7266726A6A6A6B726C616A6C7B6E73757574717270766C756F706E6B6A6D76757C736B7073756E6C7875747577818071696D7A76787375767A6F84897776747B78727C7D7D76786F6C716F79737166666F73706B72727269666567716F70727180757A71696972696A6965696D6D69746F696B71686F6F6E6264767771706C7068716F727176797B7E756D6866616A645855427270677B746C7476737A7C76797D7477727374737171737C73696770696667706F747170757074707B737D79767273717372767E7C6C6A727F8083807F847F8C727374737171737C01FE0D62070718D0777771777376726B7564676F63706E7973706D7276666B7077716D737379737971686A6B766E73676867707E76707067736B79756F77726D73817F7E7378706F6472737B77746874857D757179766A75727B767A686E70727F7A796A7B6C66626E6B71726E766C7779757E68666B7680716966686A70686C6F72726D72736B6C686A6C6F6E727070797C75736B676F746E636A726C6E756E6C5C6868605F604E73777A7873717277767A7A78817A7B7B7F797B7C78797A7A786E6A686D6A6A726C717B7D7C7C6D716D6C756C72757372786F77787779727675857B7B828581827F797B7C78797A7A01FE0E62070718E07679687069707976766A72706D726F777373726B6C6F6D706A6B787472706C67706D6B6C7970716C67636E78706E74777071726F777972777B787B756874716F73716E776F71737883777C707772787976757B7E746C6A78787C73656B6B6861646E74747172726E7679796D68777E77726769676F676E65666F716C6D6C736A646671696E6871747C70786D6E737E7B6F7A6C787B6F7276646A68645A5B5B4F6F686D75796E747073747176797976786F7C6F716B716E6E81766D7674747170747D7072797D7A6E7271746F75676F6F6A717B7E7A6E7276727B8087827F7F7F6F7C6F716B716E6E01FE0F62070718F0746465696467666F736966646375706B6870696D6F6E69677070626A76726B7D6E6B6E6A746768676C67727E7F796A76757073737275777B6A6E78756D6B736C686B6E71767768727974706F6E6F737C6E79757D746F6C71797977716D70716C67676A6F7566717B767C7371757F7D887D6A6971706D6C69766E67666B6C7870696C746E726E7272787974776B6C6D6F79717C66766C706E636468645E585349777578756C747A717C716A72797F7A7B7A7A767A777B7D7A7972707375726D6C6F736E74786E787073737D726E6D727673716E7A797A777A7A7A7C837E8289817A7A767A777B7D7A01FE1062070718007C7C6E69646E6E696F6B6B6A686F6C7571716B6470736D656869757775676C766E6D736C746F706D6266727A777174767977776C6A666D73737B73766F6C66676C766E707074716C716F6C6B6A707577777A79806A6A70717C7D71747973706F6B6E6E72686B6F76767879716D727D80726E6C736D716F6F6E7579706D7676756E6870686A6B6D7475717374756E6F6E746D79757774736F6E67696A6B615E4974797370747168667273707080827D7A787578736F6F6E7577746C6E726E777778767876767A7A797A7D7B706B6E716C746B757A757270767E7F8180827D7C87787578736F6F6E7501FE11620707181077706F6E71707578746F69676768686F706F6F706D72716D7474726C75726D716F6F686A6E6F726F6764697C6D71716A706D6F6E7376727C70747573716E67646D6B6B6D6B74677680787070717B7C707471776F6A72727682757873746F706B6E69726B6C766F6B6F707070726E7A80766D6A6E75726A6E6F6B767376706C686767676A6D6D71787E7C72766E737274786E6D79787477716B6E646D605E5B4770706F7773716E6B7371756E707675817A74756E6F74726A6D777573756E687C7A7E74736D737E70786C7673776E767471746A756D7B737B7C787C878281857F7A74756E6F74726A01FE1262070718207576726F6B73746B736E6E6667726B7B6E706E657077726B666E72736C6F6B69726F6E72706F6E686C70737F746E6E6E726B736F6A6E7271747B7A7B6C726C6C6D6F6B6E73756B67797671786A706E6A6C75787C727271727C7E686F727A7578696E7076706F77737577736F64747F85736B6E786E6968676F777371737F786F6E72676E716F696D6E74757373737773756F747572716F74717266685D58544D797D7D7E8279797A77727A767B7B7678747374757B7B77777579787673677178727D75766E72757777757C7976746E72706C6F6E6F726E777F757A7F7F7C7D83747374757B7B777701FE1362070718306D6C6267646966737466686762666D746F6C64626C716E686E6D6F7074766C736F6E6B6B747276656A5D6F79786C6D7B727069706D756F76726E73786E746C6E7774696B676F646F7778706E6E706F756C707476757073717F8271756F70686A5E6670767277757E7B6B72687173797E7175736B696C6E706A6E70727473747068686C75747B7275757A736E706B6A77707571776F7574727166656F655A5D4E747976787A7971746F73746F7D7983787E707775777B6D7679756C6A71756E777874736E74777F7473697278746E7971686A7075797573767974767D818086807E707775777B6D7601FE1462070718407768656F67656C6E6B62666B706B6D67736A726C6C6D6F6E746D7178757977756B676D61686C6E6E6564757C73726E6C766C6A6E6B6473736C73847F7E73666A68746A6D696D7373747770746F707380717474716C6F7B7C7E80737571676E72737365676D726874777E756F7A7B7B837175686B6C706C636A6A6A72727B6F71726F7371677276746F796F797C7F7B71766E73646D72746D5E6A686B606A624D7670767571746D6E6F6D6F6F6E7B77706E677A6E777472707A76696A6E7268726F6E706F6F7278727271777673727072676D727D786E7475796F828A817E82896E677A6E7774727001FE15620707185074796D7475766D7F736E69646670746F6F636C646669717D757669706D7076706B6A786D6C6F716961716A767578716D6970766B76746F726C787C7A7270716D6C635F6B6C6F6E7D7270726E716D77706F796D7A807977737377736879716A5D5E6F7075676773786E7B7A6C6F737B807A766E74757376776F6F706E727B756F6F716F706E6A6F7C6F7876737069787F797373766D6C72716E696166625A5B48786B72757879797B787C6D747C7975838178777A80776F7574717270736E6A666C72776E6D6E7C74796C7872777072736D697575736F7A7C7B7A7E857F827F858178777A80776F7501FE1662070718607A70776C6C6A6D71746E74706D6C6E776E6E6C756A726F676D6A72747D6E71756B6B66686A69716D6E6A71726F6F637270746A66727573797573726E746C7B676B6C696869756A75706B7177726D7F867B7573726B6C6D72747D76766A6F7972716864726A6B72767A7A70706C777E81776E726D7073726F696F706E696F6D73746D74757472777B817B6B6A65657375757972797974706B65676664615C59556C69677078756C67666C6D6D76707D767977766B74786D7A7E7D77706E636567746D6D6C6D7873777E7276727B7271736F6D727771757172797E7C7F7E807F807977766B74786D7A01FE1762070718707B786A646A767D7570676E6A72767D676B74736C686C66646A6E7872796E706C6B716D6D786C6C6C68686E7A74736F77696A6D60656D6A71787369717775746E6E7565706E776F6E716B707C757375736C7A767B6D6A6B716F75717277716C6D656E737B716C7A797A7E7A6D6E71797A7A72766F71686B69686D7174747E746F6C726F6877726F6F777973706C6E73777175777E7A78786C706563645E565A4B717174707B717977827D747B797A7C757776756C6C786B7273777374716E707964767274786A6F70796D7A716D7370756E73788378747779807E7B7D797C86877776756C6C786B7201FE186207071880736D686F67706D757D6F6E68696B6E707168756F6B647368716F6472726D6F6B72716C677768666B666E757E756A6E6C70726F6B667474797673767770726E71687267657374716F767E71716F6D70746A756D72707971787C76716C6C6D6B6961696A76716E72717B7B7E74667276826D727672766B71727879746C6C707C716E757C766E767576747473726C6A6E736E6E717674716C746D736C69635C54476B6966676C6A6F6C6B6D70707E7E7C78706D7071757478747471736E726A6C696F7774716D6E6C746D6D777578717570717671737174797E7C7474837A80897E706D70717574787401FE19620707189077786B7068746E756E686967626F6C71726973746E6A6373756A6B6D7A79736C6A6F6E6568656F6A676F7373707B7573716B6C676D6D646F6F6E777B76666F666B67666D6D707075767373726C757B76757476767271767E807F746A71706668666D7B726B6A6D6C6B72727070737D897370757478726F5F74746D746F707270716C6E6C6F73706F7775726C697175766F746E7370787972666E6C61695D5C4D787C7C7B7D7577777E7B808080757E807B7E807A79777874716E6C757572706B787871737B7676817672767874686D70766F7A7B777B7A78817B76787E7984847B7E807A7977787401FE1A62070718A07574626A63716A706C66717A6F716E73736F6F695F6C6D706D6F6466716F746E6A67706C756A6B6267677078727273736C72756E756768757A7675736F676C706B676476727772707A7868696A747C787382706E6D7076787D827A726975696D6C706D73776D7777756C69676E737F7E78746E787B757569766F6C737C70706663676C6C7373776E716F717D77757B70746D74787D6D6C6E6A676C655D52584E727374757270766F70776D7476737B75767E7F79827D78747978727D72776D716D726B6865696E7475707A7D7B7475746D676E7477747A747A767C8884818285767E7F79827D787401FE1B62070718B0746263676570666D716B6665696667716B6A6E726E6E6E696C6B716D75706E6A70746A6E7076726A6A666870796D6D6F70716A696A756F787873716B6967686C6D746F7164796E75736E726A72717B7370736B76726C6A7C8473736C796B707063726D7370686D6E707E7769727B7C81796D726C71737176776B6C747B7A6E7375706F6C6D716F77737B7072736F767B706F76787476737071656961645B594B6974717C6D6C7575736A717B8276796F7D787A767A7D777A787177736D647077777A70717578727874737774706B727676727175686D76797B7A7E7A837E79837D787A767A7D777A01FE1C62070718C0726D6966677170707166747072686F6E6A706A696562696C6D6E6F75746E7070656C655E7069746E6A706E7F73736F74716E6F69676E7372756D71736B6A6B736D69706F716F6674786870756F717571757F7871676F6C797A7D757974746C75696E6670706E69727A7C716D68787878716F766E757677776D6D74716F6C70797375686A69736F767D79786D65696E717D777C7C77757874776D6868606267487779787C76726B7475746D767C7F877B86756E787277707A767C7A7680736F7264746F6E6871767770697C837C6B706F7674736B6C75767B8279767F7B797F7C86756E787277707A01FE1D62070718D080766D7A74737878736674786871797A75767774726F6A6E7175717A7B6E72787364766D6C646A67676D6879726E676B706A6F6A656A6F746E757E7673746D616876677272726070737D7572796F76747475737A6F74767B84826D6D6F71746A677064716A6A727470747470686D78797778747077787A7172736A77717768746D746E6E6D6D73727574716B6C6D7A807972727471787672676C6B6F675F5D477A7F7E7D7D7E797A737471767D7F7E797D717A7A72766D797D81726C716F75776F747176697C75767976736F72636D7277757775777B71767B7B817A817A7B827D717A7A72766D7901FE1E62070718E0827665706C7274767E746465636F686A6D716D7178676B6370767B6D6F7568786D676F6D6C6D6E6767666C6D716D6B6E6D706B6F7371707A7A777E7572726A675F6A61696A7364717C7670747471797A7371787E73766C718679766F6E746C64666F68746D69727B797A786F69777378736A7072777970696E706A6E6F75736D7075687270727377727979786A6C717B7074787D7973716A6B676866615C5C4D73787C7B78737176786E736E797F7C77807679777C7475837D7377766D656F71707777746F74736F817B7A6F6E716B736D6B6C72756C696F7A7B7B847E808085807679777C74758301FE1F62070718F07876617073756C6E716A6B6866696F737669706B6D656870786B74767A6E736D6B6A6A6D6C62646D68696F7871766A6E73716C6A6C737276756F767D766F6F6F6C6A666C686B6A6D77767E6A736F6D6B73777172656E717681797A766C6F696B63706D7564776F727F7F7677707072746366666B727071737270797A72717775626D6C7376766D727A7E787070697480777C7576797776786D67615E6359594E7E82857B7C7A7D757C807A7F7E7A7E7C7C737B7D787C6F6F756F77747572777F73747678707270717B767770736A707073737B7770736E777E7A7A7F84818B8C7C737B7D787C6F6F01FE20620707180078736F6B6F6C707B77766C7272767A75757576706866696F6E6A7270746B74746767666A6D6A6D6869687970756A6E6A6B696B6970736C6D72717C7275717163706B6E71676F6C7C717C776D78757268706C6E726E71767378767075686B666B646A727571707077777878736C6C747E77706E707A6C727871776E7469796C6D736B6D73746D7B7E7B7B7372747073777675757B7E78796B686C66605B575A4C7D7B82797B75817E76796E747E7D837D7B7A848278786F76727677777378707C757874797B75746E6F697A6D6E6E696F726E7A7C717171737A748283797C81807B7A848278786F7601FE216207071810766B6469686D6C6C7263696161626869726E696668666C746F62687577796A6F706A7272796E726166616B76756E6A6D63676D6A6B757575787077706E6C71736E6B6B696E6D707180777175757A85717179717A6A6A6D717C79786C766A65696C676E706C6C7571727A77766E74707E817373697776716E73736E74717D6C6970717073746C73746A707971706D73747A7D767F797373716C6468645A58604B70707C6F756B69696E716C727A807B747972737371737076747577776C667074756F716A6B7376777B707D776F6C7168686870747875767B7B838183787A7D84797273737173707601FE226207071820776F64786766736E7A74786D716E7777756E686F6C6B696D6A716D70797577756E67666B6D6D6D5E68686B6F7B69676A72726E71696E6C776F6B7F7A70706F656F7165767778706A7172726A666C7B747576767B6B656D767B767573716E6E6D6A69636C6D707776757A7B766C7C758177736C697277746B70756C7370737372707372706E707D787A8270726D6E7A7A7B6D6D687371746F6C736268625B574E72787C7C73746F6F706F666E7779807C79706F7A75787771756D7077777C74707472767975736F70706D797B7D7176766B686B79717A787382837F8280857E7E79706F7A7578777101FE236207071830726F67706B6F75746A6D716B68736D6F726C766D695C666B676D74716B6F71736B6D6974766E6E726F6B7076796D6A7174696B6763676C7E7A707A7475706D6F646D636863706E7077747A766C6F71726E7572766E647271827B78707275686967676B736B7678777579766C7378747971746F75696F74726D656C73707A7D72756F6E7D70707472767F7972697072716D737476767778736E6A6E66645A524A69707077777C786F7A77706D767B797D77797B7279706D7078706E75797370747A736C6F70757180796B76797976747A787076786F6E6975797885817C7E797F77797B7279706D7001FE246207071840686761676A6D6C6C6D6A62686270686E756B6E71646C757C7170626B71766A6B65606668706B706A66687274726772747A6F716F6B6F6E706A6E6C717A6E626D69726A6473766F737B736D706772776F757670796F7173797D80777479766A6E646E6D77726A6E696C757B6E677A758171706C73706D6E6C7978777271737774676A6E6A736F6B737B8074796F756D74726D697479766F76756B646B6E615D507873767C72736E75737470787A79757D787978777577737B736C6872796C7070777A70777C767672786C7172777379746B6C6E7F737B6C70827F7E837C7D8088787978777577737B01FE2562070718506B75696F666370706E6D6C696E6B707172746B697876786E6D6668747E746B6C67716F706E6D6B636463766D6D6E616E6F6F706D6E70697372697176776B716A7473666D677377767E7A76786C63766E6E72747D787573767778737A7568706C696D6B696B6E7275777A6E6E7578797E7C7274787C746E71717267747272726D7172716D726C767A767B7D796B6E787A76777770727871696366626B61665F4F6F73787B6C707078776D66768079777775717575766E6C7E73717278716E696F70736C6E726D75767D6E747C766C75716D6C7A757C7B70727781797B7B7D7E8475717575766E6C7E01FE2662070718607C78767774747B767771706A70736D757370716E6A676B6E74726F73686D68706972706970616767646973727571656B746E67676E7A6A7278796F71706F726E6F737370777370717D7372717173786E6E767A736D6C756C6F7572717C726E706174706E696B6971787570737576758484717372796A6D67677277727573696B74687871756B7C7F7B7B75736A727A707175757A75746E70656660655E5E5E4D7574707478777E787170706F6F7B807B79767777797971727975747971747472716B6F707072787279707F76726E746F707970766A70707E787A7A837E807781797677777979717201FE2762070718707176636A61747075726762626671767179786973656D726E6D6C69646F6C6B777175706E706C5D6A6A6A707C74736A6A6E6A6370666E68726E6F796A6668736C74706A6B706D707173786F72726C74636B7476766F7174787D7E73766D7566706F6F6A6D6D6A777476766E766D76808174666F6C706D706C6B6D776F717870726D71726D7B7173737E74727476737671787174797A7F76696D69646863635A4D6E737D837A7D767276766A75817F7E7F857F7D7683787179726A73757B7573796F6D6769746E787177716E7576696D726D757A7C767976747B787E867E837C83857F7D768378717901FE286207071880766B6A726E6B68707A6E67696B70706F6A686B65646D726D6D69747A7973656A6D66646B6B67616C6C6C7177786D65736E6F716C6B717074727C766E6C6E6F6F766D696168716874756D737574756F636D7676756C7274727E7A6E697772696B6B6C666F6F6A7377747D77706B71757C7176756E72766E707671757374716E7376747270706B6C798585807A6A6E786E767A746F71776F706E706C665E5B5E506B6B676967676E6D7369686874747578787A766F72747B7F7D787774756E757072717270706B646672757678767275737674736F737A79797478827C787E8185787A766F72747B7F01FE2962070718907674606C706D727470676C71736D666E6E707378706B6E716D6D70757678746D6D7267656B6968676465706F76707A706B6C6A6F697A737875786B6F736D64686D7A706E6C6F65627175717C7675787373676C786F76757874766F6E6C6D68716F6B69766B6D6A73777B7F79757D7C6F756C716A71716D6A726D6C6A70787F75716D706E726A716F7679737870717774766E737779787C757B6E6B636559594975747878726973767C75707880777E74737A7D7E7D767E727177766A746A6371726D6C70736E71717C6F786D6E6A6D6F6E72737A76747C77797D808684827981737A7D7E7D767E7201FE2A62070718A07874676E6C7073726E66676962716E75706D707266686C7771727273736F70746A6971716F6C66676F6272716F6E746F756D73666A7772766A7879796D6C6B5D686F6A6E656F70737C77746D717275796D717675767177767A79777976706B7268776B72786E72767B7D7B736B6E737C7674776F716B7269676E6A6E717578746A6D6B6D797077797582786E696B686F7770737B78796D6B6F76756C5C57574C7475797D7B79746C746F7478797F7E7D79727A727B7C757370707472716E74767A7877706D6E707376727D76746E73706B6C6E76777C7A7776797C7C817D838979727A727B7C757301FE2B62070718B06B666A62686E6D686D686773666B6673706D717475626367656A6D73786C75776E666D666A6F6F696565797A766B707178746F685F68676E6C6E777B71716869756C6F6E6C6A6073786E6F74767577777976747274766D777376766E726C6C7468666974697276757176757C707C7F79776F746B6D7071736C6B6C71747578696B6D746C7271716C72797D776D706E6F786D77777F7A7B77716B66685F5F5E466E6D7775776B777572656E757F7A797476797175756E6A7C7D77747B756E707673786E6870746F7B756C797C7A7571707373767B7676716D787B7B7C7C7F7E7D76797175756E6A7C01FE2C62070718C0776F6D6B63727366676365696B6E76788278736E706B696A76756A717677736A676668686A68696E6F72796E7077706C75796C6D647776736C767D76726F6F6B6669696E677A6E6C75726B6C766E757772726979686D6F7984747071767167636761666E6F75737B7B7F7E686D72767E706465767A716B6B6C6E6D717B7974726E6C717478787777827F766C776B727B807C76797A7B776B65636661655F564A827C867C818183827671737E767C81787F7C7D7380797876787270757572727D7272727B717177707A7476787B6E707071696F7B767B7678777678807C7D7B837F7C7D738079787601FE2D62070718D0696769685F6A657468656F7361706A6674646C676567666D6E73737B726F6F716B6D67676C6F6C6364686A7170717970716A6C6B656672766E7575787F7C73676C6C6A736D74737E71747675716C7B7B7572726D6D6F6E767D7170776F6A6E6F686B6B6F71736E7372727A706971767C78737770706D726B73757472766D6C6C6D756F707175776D707C7579637474757273717A7472756F71696F62605C5A446F74827D8078797B7B7674777C757C7F7D776D75797675787377716F72716E6F6D7375777978746F736F74727178736D706D7077767976807E7E7C797C7F84827D776D757976757801FE2E62070718E0746B6B605F67676F78666B6E6B6E6C7470776F726C6B6D6F71686A696D6E6C746E716B6F6A696E6D6D626D6F727267776F726F6E707171777676766C6B6C68626C706469606D71747A766F757871717A6B7271726D6E74727B82737873766C696E6B6B706E716A6D797674766F7775807C727672757A747077736F74767A72716871776F686C6F76767074766F78767575737975757470726D72696260585C4A786E73756E7272726B7571747E7A7D7579777F7D7972797A7C777B7479726A756E6F72717571767577686C71786F726F7075747776726F746B78797E8481817D79777F7D7972797A01FE2F62070718F0736C68726F707074716568696B71646E6F6C666D7166727173686C706F756C757568666C6E6C6A6867636D706A767070726F6A6D6F6774726D7678726F72616F68706A6E777B6B6E6A6E71706F727A717379787B6B717479757A7770726D646A726D7077737273736D777A756F717A7F71736C716E6C72746D7172746C74716F6D756C7074736C74797B74726B6F78726F6D7176747978746B6C6A6B685C6651757786867C7976827D7976798080868884817B7A787E79797C787A7978746E6C756C74726F7168696D6E79857A74746E6F6F6E7076786F767F7A77847D82808384817B7A787E7979 + USBDEVFS_REAPURBNDELAY 0 3 130 0 0 61440 61440 0 01FE3062070718006F7374777068746A6E6C6871716E6A767472736F6E686A64656C6E787B6E69695D6D676C6F6A6D6C68686A7B6E6E6F717A776E726B69707074747E7B75706B6C676868686D6B706C717B7575696C76776C7477807C7176797E7A6C6E6F716F70676866717C70756D7179826A7072787D74706573716E6C686D6E6F6F737A716C6A75716D797D7E726E767065646D767A7E707676736E746A67716D6C62615F4E707A8084828685717A79777A868881837D7F797C7E7F738378737176777579746E75717879737B72747378766F6E737B73717979717C6F7274757D7B7D7A7D857D7F797C7E7F738301FE3162070718107771717062666C707A6F70676B716C7873716E6F6E706C6B6B6E6E7379736D6A736B6C6A6B6D6F6D646E6B806D7268736F69706D6F6D6E74737A757173756D686B64686B656D6B6D766C72706A6C726D786F73716974727B7C7C7677716E6C6B6D707270706D7471707779747A7A78806D67707A76717869676A7673767A71737472747675727073726F6D68656274717177767A767C766E6A6D6864646552457677797E7573726F726A6C707D80777C7B7C7D7A7B776C737D736E6D69716B6B7372626D70726B7072757C767C786E6B6E707178747270777D797E7F7F8087817B7C7D7A7B776C7301FE326207071820736E6D6A69696F6F75686B6D656568716D746F6F6C646C6C66636E6E75787173696B6C70706D6E6C69646A726D726E6D6F6B6E67697171766D73737971706D646B666A6F6B716F72787B706F6E7580776C7870766D667075797E7670726C6A6F6B6E676E6F7574717978737273777A7A6F6C706C6D6E756A6C6D7172747677737873706B6C716C7279847F76757474746C7575717470706C69696A656461574C6D7A7574736D6E6A7675786B77797B7877778077747A76787271776E756E70727379726D6C717473736A787D747176756F6B7472757E7B78767B78828081818477778077747A767801FE336207071830777068606364666F736B6969666B65756C6576736B6A6E6673706C71746F71756C6675696A686A6667676D7175696A70777C736E68736E6C73737A6F6F6F6D61666F6A6F6B6F6E71776D66676A727B7973797B7E746A69727F7B71736D6C696A67616B6F757871757377706A7677757D757675737C74717075726C7071756F70736E6F7574707979787676796D6B73777971797F7B7975726365646A5F5C534C6C77757373757670726D6E6B6D78828280777B7579786C7673727170756B70706F776E74716B7470726C7A79766C6C6F706B707B7A797973787B7A867D84838180777B7579786C7601FE34620707184072736C756D697A78796C6A6E6C726B6C6B736A6D6D7073756571726F726D777B746F6D6A6E6B726860676F6C75716C6E7370756D6A706D6E726E72767C70726C686C696D6E6C6A687F747A707068787A757779726E70666D757C78717B73716D66646473706F7378777A76716C747D7C6A6D6E736E756E777C706D6F6E737E73796B757A73717276757A716D6E6775766F70737971767472706F5D5E615D5D487D77747776756C6C79746C6E7E807C7779787A736E736D7079726A7575726D6F7375756E787A6D7272747378736F73736B6B747773796F727E7A828C89827D7E79787A736E736D7001FE3562070718507A726D6A686F636E6F6B6B63647477706871716D6E666B6C62716A6C6F70726C67676C6868696D7062656B726C6D6C736E71706D717C70746B75747A716D756D6F6F696366736C727D757772696A70747573737B6F6D6A747B7F7573726C6A70666C6D706C71797575796E7A786E82827869726D757A7073686C6E6E6C727A716C706D707A6D6E74757876766A6A6E7877777C7B8178786C6B696C685E634E487576727F7C7873687477706E847A7E807F76847D77767079797871736E6B6C756B756E726F756F70786B7770716C736E7C747B756A78727B7881818B7F7E827E7F76847D7776707901FE366207071860786E6D726A676C6C6B68666869706A70686A7374756769706A686E717B7D6D6C6D666A656B6E716D6A5C6F7478746E70727E7179706B6E6F75747D75786F6867676C64647070716779756D6D7077776E716D79786C6E777387787D7E706967716B706C71666D6A71707A7074787A7579766F736D7075746F70717171736F716D726A6B71786E7175757D7B747E7B7E6D696C757D72776F746A6F686D685D5547787C807C7B6E777A75707670797C837B7B787475717B75736F70736F7A6978747B7E7576716F74797D717170756F6F6F6F776C777578717176727E86888A86837B787475717B757301FE3762070718707575716F726B707279626D7374706F6669707274706C666B6971746C786C68676C7168706E696A6F70686E7276686467746966726C73736A676F78796E696E6C6E776A65696D6E6F76736D68726D7E7168746F7A736B72787C7F76717574686C626D6C6E69696A7C7D7178716D7277807C6F76706F747173746E717878746B6E697B7375746E7376778173786E6F747B727178787978777464606268645D534873797C706F726D6E6C6967766E7B71747776736E7C75777073706B7277706B6E716F6A75706E6E7275727B6E70767378777A758271797475757D7F847B7A7E827776736E7C75777001FE386207071880766E71706F70776B726869726A636C78727B6F716A6E726C6B6F726B726C6C7170716C6B686B646E6A6B6B7771716C74717371736E7966747174727877737168666E696367716D7471726C6F6E6E72746F817A776E6B746B777A7971756E666D716B687273667875786F6F6C716E7970747575707371756E7F7671716A7370736C736F6A706F75767D71797A727273796F707772737979736363666B6B5D5B4F6D71727B766C7B7474786E757E827873717070777C7870737778767A7772787577736F796F726A6C716F747A7872766B6E6D686E747C75797D7E8187807B7E7D717070777C78707301FE39620707189073676C69676E6D6A706B6A6A6C736F62716F65746E6E6769676E717C746F6D6F6E6F6F6B6D6D6A67635E6874746A6B6E766A6869716B70787C687D74726A7572696D6E6E69696B736A7173787C777579737F797F726B69727E74736A76726D6F6C6A72756A6F6F7376736F6770766F7A70766F6F7274736D726C716B717378796E716C747273786A797A706F7676767E756F77797A7A746D636467635858574E7C77777576747D786E756B73787E78777B7378727877746F7F7270726F6D6E746E746E6A736E716C7A73747A726F70736B72767B7678717B827B7A777F7C827F7B7378727877746F01FE3A62070718A0706E6E6B676B6F747268656A63686A747969636A72656D7373736B76736D66676F6C756D6D6B6E626E69706F6D776665666F776D706D716C767378767171686C70717270707066676D746F736D70756E70737B757C74797D77717570736E6D726F7070757370707377797565707A837F74676C6C6E676D6B6F7273807B7A80756F6B6F6E6F71727071726D716E6F707A7F7572726D78726D6C6D6B665E5B61466A6A7C7A756F7D6D756F6E6B707D727C7B7D776B777B777A75728275747275806F6A72726D6F74717770757E6B6F72726D6B7579737572757E7F777C7D827D807B7D776B777B777A01FE3B62070718B07B786C78666E73717173756D70667276756D70706D6B6A6D6F72727271716A776B6E656A6E6B686969676D727961697570706B746975787174707A6C6B7169696D6D636D6C74686A6E6C6B6C6D76747B767272787167697E7C7F6E6F6E756F6D6B6F6C6F666F747A7B7B6C6E6C767A7E6E6877726C686D6F74726D776F7A756E76747471757A7F797E8579686B707175766D7976776E6D6B6E696D6F5E585B4274727C7A7E72796D7A71696E7D7E7E7E797A7C73777975767475797C78706C726E7171676F7977767272787E736C6D75786F6E7A737276767E7B7A8481817C8A797A7C737779757601FE3C62070718C07269646365686A717068676E5E6C6D756D72736872796F6B706971787164666A746F77716F66716A6E6B7471656D6D6E6E76796D6A77706F6D7574716E696564615D62676E73757975716F72777570706A737180777A7C77858476746F706A6D756F76756C73736E7876726F767B79796D726A75786F756E6E7477666F7476726B6876767766687D7B75676F6D6D727B7F797074777B737366676F676A5D634C74706E756B736F72757379707B7B777A8073747575786C727A777473717179787171696A7470736D76718274757474746E6B727873727274837E8088807F7D7E8073747575786C7201FE3D62070718D0786D69746D70756F786C6D66687175766B706F6A676E736F6C6A7473706C7B6A5D7970746E695F6C656B7077776D6C706C716D6C666D63787B74727571696D65666B6B686B7C6D777A726D696D73746E7775716F6B68727C848073797C6F6B6C69676A7367717971707772766B76788071766E7A716B747876757373726D727767776A6B7170737776827A727574747573767676767672696C695D6463545949766E78736B6B707775787079797D79787A7F79797277706C71797578787667717C747772736D6C7C6E79797C7C72767873666D726F75697679777D857F7B7F827A7F79797277706C01FE3E62070718E0746D65706D6D6A6F746B696961726C6B6E6D6C6966676E7B6F7077776F736E6D716D7471716B6D7562636C71676F6E75706B6B6F6869727C6E757173706E6C6B736E666E6D766C6A6B747179796F76716F7774796D706F78807A766C71746F70696D66686D71757C6E7A7977767F7B756F6573737169747374736B746F756D716D6E6D727A757075797874707069787B7B707474787779686F665E66695A604D77707A7A7476797773716B65737A787A7C71727772727279807977747468717474746C777579726B717277707472776E6D6D7E7674767172787E7E8280857F877C7172777272727901FE3F62070718F0837F747E7974787070716668606E757376736D74746E6769686B7579726C6D66677B76726C676B6D695E6B6F717271716F6D6E6A6E6D73706C72736F71716C6F6C6E6D716A6B717888756C746D7A7C7374766F78646C6F6C777B726D72676A67646E6A6D6A6B6D737E7A75726E8076857B6969677576776A71717579768075757075766A72667570787E77746B7075747A7A7077727079706A6A6367625F61526E78797D75726A6D7A6E6C78777A787A787381787F7E6D7475716D6F71757370746F746D75727B75746D7A7977777269766B6E74727978717F797A8482838684787381787F7E6D7401FE4062070718007573747562656F6B736C6E726F75786B70746C6C6B6B686D6970706E6E706B7170656D6970696866625D6A757D767F767169726E6A7374796F716F726264636172736F6F6E6F6A737A787876756C7273746F70766C6B6D728180777873746F6F626B7178716F767A7575726A6D74757C796E717974746F6B656C6F726E767972756C6A6E70736E78747B7375776B7975767273727479746F6B6A636060575A496E727373676D7372766E716F72787A79747273757D787C8077697073766870787A7A717374727478796A7671746B756D716D7276777A71797B757C7F7C807A81747273757D787C8001FE4162070718107E796E79776D74777D6A6F6F706D6F6D7672706F74736F6F716F77707975716D676B6D616A73746C6C6C76737B6B6767687161616A746D717872717576636F6C6D6B6A6F6F736F7D8778736C7C707073707074736B6C6B747E777971726A706D6F6B676C666A72776D7B71716F75787B7A747875726B6C6D71786D797178757266666E6C6D786F73718077766B697B7270777B7F7D806E646B686B6C6A5D5A496F79877E7C76777476766F787E81817C7B7E7F777674797878706D7070706F7271716E6D6F706873767C837974696C70767875767C7A75707A797C82777D827D7B7E7F777674797801FE426207071820726A706E69697370736C6A6D6F796B6E73686A6770716C65686C7A6A6A717070696B65707073776D6B6171766D6B6E676C6D726B767D6D736D68706B71736A6B7068687970746E71746F66707A7076737080827B747175787C7A746C6D6B666369696A7161707B7E767B7C6C7576797B6A7170766A70716F6D767275766D6E75766863717578727579797A70717275797670756E73787673686C6E6D6262574A727B7F807F797B71767770787D868A7F76777E787B7D807574777271706E727675767075696D73766F6D767377737577757A7573747273747F727D81717C777F76777E787B7D807501FE436207071830766671747375746E75656375756B726C6C6B7875736B6E6A6C6764707078716F6D716B7162666A6C6D6D6E71706869726F78706C6B706D7072707774756B706B6E706271666F6C707C6E7471787475726B746E6F6B70777E7A787A72746C66655E666E6F6D716F7A75847D73777A7781706F70797978736871717372757471736E727474727078787C7E78706C6C6E6D73717877746F7A71706B696B5F565855747274758377787C8283777D7F85897E81827D747A797270756D7477777778766D6D767872726B6F72707B796F6678706F6A6878757870707D787C807B7F7F7D81827D747A79727001FE4462070718406C70606E675F6C66746B6769676868616F706F686A74766E6A6C676D69726D617269696468666D6B68646C726F6C6E6F7277716A706D6E7372726B776D716E6D706B6A686F6F6C70706E706F6C6D6F7B7A8077746F797878787C736E7069686A686468737170706B707D7C777975767D70726E737C6C69646E6A717276767B7374706D706D757A72737C75706E6D73736E71787C75808171766A7267605A5C4C716F7A71757A7771726C6A73757E7E787B7C80787576706F726872796F74757472767073777372727A727E80716D6B757574717D7272646E7873858A827F85847B7C80787576706F01FE4562070718507272747C75767C75706C6F75687A7376777371716E65676F6F6E70736C756E6F686662666E6E6E68676D687A7671696E6F6C716E6C7B7477796C6E736A6B6978726C6C6A776F6D6E796C716E737779706F72767668737070727C78696B7976736B71736B7172726F7B7A7D76776E76736E6E6C6F7076696E747878757C706C6B6871716B706F7076747771736D6D807E7C737C7679786E676D686D68655D5C50726D7674787673797A80777674757376817A7C7A767D74797B74726470736B6E736F6E73757773707975806E6F726F726A6C7F7E73707B7C807C787A7A7E7C87817A7C7A767D747901FE46620707186074756B77666C72767568697065756971716E766B7367706F716C6B69686D6C706769656D696373666C7475796E72706D6D6F7270696F7379757777787672796A6567666F6C6B696A7271736F7670737670777B756F7170787A7C786D7171676A62667177756F777572726E70707D7E7D7370686D746A73706D6A7170777B6B6E667A7578726C717A70787A7271776E7B7079736F7E716F677067696266635C4F7777897E7778777471706E6E76777D7B7F7E757A7F7B7A787C77807E7B6F6A6D6A7076726F777A75746A757275716C6B6775737470786E797A7F828F7E7E7A857F7E757A7F7B7A7801FE4762070718706C716966676670726D6571696D6B7E776B71716E6D69716B6B6D766F77726A736B71766B7872686A6A6B6D78737169716A74716A6D75777373706C7B7575686E6765686B6B6A7073787A6B71736A74776C6F777D7069737C817F756B676F64626D667471706C6C6F6C7B77736E7D7B7A6F707474706A6C6667767077727573766F70706A7A7274817F7A7B6D6969787678747D7C8275746E6764646568625E47766D756C6E6D7173747070737B817578796C78747D7C747876707573706B6C6C6D6D70706E76756F746D6E776D6D69707271747B7B797B787B787A7D7E7F7981796C78747D7C747801FE4862070718806F66636266656E756B60666F68697272737476696B606A74746E6673706F6E6F6C6C6F6E7668686E66626E73726A70686F6F7468696F69797970747578727772706E67666F786874807274717772776C71757870737270757C817575746F6B6C625F6B7077746E7678777970787775817A6E6E736F666C6B7669716F7179737B6C686968696E7973767975726E6F747F77767D7A708170726E6D6F6263625C4D7172746F68737A7276736F6577716976797A77787E7D70726A726B7876717077726E776F6F76736E79707A777A71706F7372726F6E717478767A7D8086808584797A77787E7D707201FE49620707189075716165676E6E73766E746871676A6C6F6D7076666D6A6A646D7676726E6C6C6665656B6F686D6A686475797D70656E666C6D6C6C77757B76787B78766E6F65656C69676C726B747E7A73716D70686D6E7A797C6E767F7980807B686F68656C64737171727175716A767A72797177756B6876736F6D6C6F7775716D75746F6B6E716F756D787B747674746E707170787A7177727679786B66696A6B655A504B767A797B7B727875787471757F837C77757974756F71757177787B6D6D6E6873767378787478726E796D7975736E6F766F737A7A7C6C6F7B857C7E877F7C7F80757974756F71757101FE4A62070718A077766D6964647275716A6968636F737174716E6D60706D6F676A6B656D706B6F6C65656D6F6C6C706668746F7469707078737370687573736E7274706871766D696B676B5D6C6F72776E6A6F6E6876757576747570736F6F7B70756F786F6F706F6768737373717C81826E737A787F79786A6B716F6F6E716C6D6A7373737A7B6E6F766C6E6B72736F7D7B6E6B72727B756F71716E72736B6F6D676B645B5D5078748178717473767B7A717376747B7C797479757B7471797175726F706D78777179736C7C726F6F707176777C716B6B72756F757A6E6F76807D81857E858085797479757B74717901FE4B62070718B07C746E7A70737074786A726B6064626C70706E6F68646C7271717478797B69706D6B6A73676A6A6764656B7377696A6E756F7376746E6F74747D786D7A6968666A72646E6D7874698074706F6D6F73786F717B7E7166707D797E706E6F6D666872696F79726E707A7278797A6D7A797772756A6D7A7173706C71687266717574706F716E7371716E76776E75706E76807E7E7774706C72706C6A6A6A695C644C6E6E747776797B7476676B6D787A7A74726D7476808079797A767275786F777570736D666E7171766E6C737C826D6D6566717674707070747B80818382888482726D74768080797901FE4C62070718C0787667666F6A7276766D726A676A636E706E6A6C69656A6C6B6F7373736E737266686E6A6E6A6C6B686772706B66706F6E6974716D74727F74747575716F70696F6C6A656B78706C75786F6A7171737572786B7D777474778082737272666566696774706E737372737872756F767B76706B6C6F7176766F7273727675737570676D736F6C7271707C807175707B7B7A716A78757265766E6C6A6966665C5C4976746F73757B7675827C72777C757A7D7D717D727D7A787976746F74717276796B766E72716F74727C6F716E726B726F6D717C7A73717C7C787D8084757B76807D717D727D7A787901FE4D62070718D0827762616B6C666C746C756C6A67696A72656C656B706E707072707576717674737670726A64626D696E73736E6A6C706E637075666D727671736E746C6F6667686C726A6B6C6A6F7575737B736F756B68787377697376757D7E716A7475746B6A6B6E7773727879777C7C6F6A7275816F706C77746F706C6E75716F7274776E746E6B6E7470727D7983767A7372717672696E6E7171746B655F5E635F665D4F7A807B797879757978706F757681807F7B75757676707276746D72697470707C7279767974757A7A7B70797778717272706C767B6E77767671717883828083847B7575767670727601FE4E62070718E07E767369715F706E716C737063736B737073716A746A736F72786E72757367727071716C6E6D6F6D7067676D726F69746F6E63696B70777A776C77786C7067716D7774736D666E707D7173716F6C6E776C776E716D7375787682746F74796F70626D6C736E6D776B72797D727775827C7674716F80727569736F7972716E727372706D6D73736E7274797069676E71737970736D7378776A6F6F6D65645E5D5272767D78747676727879706F7B787A777B7778767D706971796C6E74776E6F7577726B6970716E71716C7F7F78716E6F73707775707976767B7780837E7E7F837B7778767D70697101FE4F62070718F07C756C69656C7573746E726C666F7777716C6E6B6B6D7374706D6F727D6F6E6E696E776E7269676B64626A74776E6F6F7074796F706D6D6B6F72746E716F736E696C676A6D756A6D716D7679736C76766C757478716F6B6E7D85787072706D716C706F786B6B72707E7D7C7A7077787B75716F6C6F69707371757C717A6F70716A6A68767B787C797D7C6A6E686E6E7071736D6C6B6D77726B68757168564E4F6D727F70766C717771656D777A85787E7A7D787A7572737A78716F70746C706E676C7077747A77707273707C8076727672717A79747876747D7F7E857E7D84817A7D787A7572737A01FE5062070718006B6E686C6766706B675E696569736A6E7372736A5D6162696B62746F7571687269736C6B6E6B6369646B72726A6F6B7372656D6E6970787777706F7C72676F6B6E666A69686D6874706D6766726D75716D7A788374716B79827D736F7A686964646F7A736A6D6F77757F797672747273767073757A77727169717779737E6C636A776B6A696A737A728174727573777B8174736E73786F7277645B655F605B4B6E777B7374777479807D7375737D817A7A7A7F7C7A75777D7A6F70727B706E7974716B6D7276756D6F6F787476746F6B6E707576757875837D7A79827C7F7E827A7A7F7C7A75777D01FE51620707181077696B6C6C75726D6C6B6F696F6C666E726B726A746F6B726B626D6D6E74766E6D68726A6E6C6D6C66697178767370716A6F7A6C656A7572737478756E696D68676A6469696F74726F786D706F6F7174717671776A6B7079778077687577666B6B72776F706B7E7775756E716F7A7C7C69696B6F7A7577706D7274796F6B6E726A686B716F757C6D6F6E73796D697B786F71787777807D706F6B6C6A635B61547275717675767D757A6F77767A757C727D747D7C7E7C77787578726F6772717B7575776E6E7977697570776C747573786E6D697575767E7C777B717C827E82817D747D7C7E7C777801FE526207071820706F656B6D6B73766E6C6E6F676E706E6C6F676E6B6C71747478746C6B736D6E676262626B6E6E656E656F74757173707373746A6D747F7B727472726D716D70686E64666D71666E7572767175736F77686B7A7E786A7D757777706E7C6F726966706D6F76636B7A7981756C72696F796E716F6E71736C67716F6D747A71706A6F78776E70777C796C76706D686F7B6E777675777474736F666B6465615B634D6E6D6C6A6C6F6B71796F6A6D7C7E79857F72797379786E717A776B7072696C7269777070717279747A757F7A6E686F6B6F776D767377747473757C80827C87827F72797379786E7101FE5362070718306D736464676C756F7B6F686C69606D6D6B6767686D6A6E6B646D6A6C726C67696D6E6967716D6D6C6F6B6B71626F696F72747B717371756F7472777474746E6C7269656E6B676F6E7E7173796C6879746C717B757373787672787B7274726668706E70756B74737278717072666F7B7A6D6A7476706E6F6F6C717A7B78706B7076716269717374767E747B74726A75777B747274717A72696D716F7066585E4B74796E75776A757376787A74797A717A7A79867B7E77737B7572707370696D6B707676756F726E6E73757D7B7873776B6F666D7A73756F7877767D85797A7C807A79867B7E77737B01FE54620707184069716F6D6F7773727070706E6C6F6A6B646C7168716C69666D66706F73716D71716F6A76746D6767646F6E7A746A75676E70766C6B677271707A71736E6A6B6D6B646A6E716B707876706E7976726F736F6E767A71717278797D78726B766B73696C65706B706C776F767A746D7079756F6A6B727272756C6F74787A716C73726B6F716D707579717B8170756D70706F727576777B77716C6C675D6C6A6B59487777837C7E7471757671767D7B888581847D7971797C7C7976747579776C7272706D746F6F6D706D79717A807D7372736C73747A74746F78767A74807D79847C847D7971797C7C7901FE5562070718507E7772736E746F7A746C7373716B6671757A706A677272696E6C777B796B6E6F75726B727A716A6B64666D726E686871726A736E69706C78706E6D6F79756D68686E68686D6D6A747B72747171716E716E767C7C6E676F787B82736C73716B6C706C6C717872706F6A71716D6972787B77716F6C786E70667272707269796B7076706F797D717775817C72756A6E6E6B70737177757372766E6F65655F5A5D4C6F6774777371697071756D6D7A737B7D7477726E73787E7377706F7E706F707274786F76777271777074766E70716E756E706C737878746C72727C807D777D817477726E73787E7301FE5662070718607271686C636C77706F6461706F6B6869686C6C6E726F676B67766A6772666C6F696B6E6D6F6E70626E6271726C6A6B6E73767C6D65687479777176796E6E6A6E666D66656E73716C776E6E7470717572707C75726E6C6E76877F757073706E6B6A6B6C726D72796C7D767473737A757F73757178766B6F6B6E6A6C726E6C706D6B747B726E74747A7A7A7A756E676A74736E677674807869716F6C6763665D4E7C737D828476737A777D7C7D81868076797A76707373717479746E787C73717D71746D696F7B74727B6B7C7C7572717573727D74757675748082807F7E7B8187797A76707373717401FE5762070718707E736D6A6B6E6771786D6967656A6F7A726C6F686A7768646E696D76727270776A6C6A686B696D6F6966637D75787573696D686F6E6D7573797172746E646A686C6F6A7162716D707C736E7277757B766A7A777E746C7275717A716C71755D67656C6673746D747179796E70727D848A78717373706B6B6E716E757B726C6C75716D6F6E726A747872736A7A767C7979777777767E777467686B69635F60574E787574797C777B717274686E737F797477717678787D787A7678757A726D6B7078756971747072706E727D747772707573716B73797A7B77797579767A82828577717678787D787A01FE5862070718807E7373786D6B6F72716F7A766B73727B6F716F6A636B656B716C76717F746876686C6B6A6E63666C686C7078736E6A70707270696C6A71736F6C767274656C70656F697069746C676E7280787371787C717F7684796F73777C85767174706C73686D6B76686F6A707675797271797476796E796A746E716C6B70677576737A74767072726E756A7272706F726D6C787A7C7171736D747374736B696862586049717572766F687B707270707479707779807A7B75787378767B7272717E7370746F6E6D72786F6E77716E757271707B7A73797B6E737771768075757E7B7C7B84807A7B757873787601FE5962070718906D7171707278757774646F6F6A6D6B746C6D7069696D6F6B6F726E827778686D6A676C68666C726F6D716B73766D6A70706E686C71786C727A6A6B716D70706C727473686B77716A7C787271687B7A777974716D6B686B737A7A7871756E756D73736973676472737876756F6E6E7780777579767977746570777B7C7B726E6B6A737367737075707479776467757B757377787C7778786C6F6A665C5F5B644F77736E7675717B6D796F747D7C7C74837374706C767A787C837B74807971757579807576706A6F6E726C6F706E756F717278747977787073767372807E777C7F7374706C767A787C01FE5A62070718A0767A71797273736B79756D74647468716E7574706C6E79747676716C767573766F6B6470706964666E6575756F67666D6B7078716D746E7570767476716C70706D6D686D6F6E716F79746B706E717774706F796D6F7478787C807573726E6C67666C6A726F696C72757B7B766F757C81737270677A6B677278716F767479726E6D7071697872736E727D7177676E7579767A6A6C716C746F6D736D6961555B4B747076777171737279736F71797B7574716F747B77756F7376747574766C70666A6E7672787C76737B727A7672746E71666C73716E6F7B7F7875767F84827C87716F747B77756F7301FE5B62070718B072736B666A6C6A6E6D636366676D70736C726E62686E6D69676E726D72717170696C716B676B666664686D766B666870706F7367727075726E707277756F6B65716468686D6D6F72757A7773727172716C6C6E776D6F74707B787775726F686C67687077707473777377827C747778776D696F6C7B74736A6E706C7C7B7E7A686B6571726F6D6F7073777972736F75777670717779837A756C6C5A5D645F534E726F70767678777771677279897F7F83867A70787576717970776A6C716F716F70787271757B7D777C6E787A766F6A726E6C696D7D7E76757E7E7A807F807D82867A70787576717901FE5C62070718C070736466636C6D69726A777468696E70736E6A6F7175686B69796F7373736871726A69676C716A666C6A696E686A6E7A7F726D67656B7275676C726F7167676D6F706B71737574727D766D756C6F716F716B75736D6B6F76827D756E70736D6F74677278776F7175767578707674797A7E666A747773706F72746D717071716971717471707273747C7671796F6E7278747D7F7D7479757572695E6A645F53417B78707E7375786B77737B6E7C7C777B7481817A777A76746E7173746F6F6C7477787270737377726C757A7773696C6F6E777679747571747D7D7E8F7B8485817481817A777A767401FE5D62070718D07A696C676B6B70696A68626D66696E757067686A666E726D69716F6F7776696F676A6C6B6E6C6D6C6B656D777370747374726D6A6B6A706C6B7D7072676C6D73676F726D6C686C6A7A73696C756D7B7C6D72727673737577727778726D6F6C6F68756F7674777479817B777170766E78716F6D7474757B6F6F74727A6F7273716D686C6F727779777778716D697173787B737876727A786E716A696760605F4E7477736D757276737572707680857B717B7D7E6F796D6E797C776C6C6F6B6F746C756E716E75756B6F727C77756F71696D71727C7575717A757978837F7A7B867B7D7E6F796D6E7901FE5E62070718E07774706768696B6C73646B6671687968777570716761616E68696B6D6B72696C6B666C69696B5A696C6B7A7A797377736C6D706F666976807575747270767266706D666D6E736F6E727874736B66737069787C7D6B686A7977756F7A777370756C757268737070757B7C7C707175757975747970696F746E707B76757273766C6D6D6E6E716A727A757D7979726E717375726C71727474696966656A635B5C5275737677777A8178776E6E7C7E87837C7E77747B78727474736F737A787274727072706773706F73776F7A786E6F6D71716F697078787073777C77827D7982847E77747B7872747401FE5F62070718F073696267746E72746A5F5F635D6A646E6D756E676960656A71767070776F666C677166676668676E6C6E7276736F6E6670686968616A6F777179807B71716C676B73666A73756A757B727471746975706B727379706F6D70787B75706F6E6A6C666D6C6E6C76737378757B6F726D7680706A636E6F726B747372766F7773726D6F777A68736F7974727B716C72747E817676777675747D776E6A64646C5B5E4A726C6D7B746D6C7172696A767C85766F7A7B797A7E726A6E7478787878706B706C6A647272786F737A65727D7F72736D74717671757976737174787B858083807A7B797A7E726A6E01FE60620707180074646A6A6665666E6A64646F6A6D71696A6E6C686164626F68736C726D6F7273746B6768737165616968727A717371616D6E6561666F6B746D777178686467666A7072696F6C6370766F7175766B7772706A6F7A756E767883877C76746B716961686C7373737478767874787073777570666E73736F7072707A6B76796F7775736F6B6B747976726F79767B7573706D7478777273707369636C5D686C64594A7170797477727777726C6C737A7C767674727D76777471737D6D6C6E6D6C6979757C737979797164766E787C6F6972787476757672757E7A8077777F7A7F828674727D767774717301FE616207071810707A72746F6974746D69736767766B716D686A706F6E657077696C7378787374696C70696C656C6A656F6E6F727370716668666A696A6E786B6B716C736B6E6D6B767175716E71737E78736F726E6D6F6973727A726B6E7A80787571766C6C6D6C746C736C6F7075857A79716D6F76756B6F72696F71716B7874787A71747B706F6A716E73706D7A75746F786A7270667876757E717D7D75696E686C645D60507677767A75777A756A6C69787C797E7976777D7A7B7572817A7368707B737375706F79727572777973737778747D77707175697B7477707975738082807F7A8576777D7A7B75728101FE62620707182079706E6C69696F74767571726B7570676E68776F6B696B6F6C6B75786D736C75716869676A696E686967707D726F6D6F6D6974766C7071716D7881756969676D66667173726A71747682706D746D6E716E787B7773686B7B7574786B797172696C6669676E7975757A78756D6B817D79736D757677756F7076726E6E6E7277717A766A6F78676A76757D70746A6F6C777B7777697275796E6A66676A675C6248787B81747375777673737B7E81867E7F7D7B78766F6E74797B767E786D75747470726D73716C69757B797873726F736C707571747D7E76787981798884827F827D7B78766F6E747901FE636207071830786D5F6E6568737276716B716A706E75706E6D6D6C6A656A6C6B72747B73756E68706771696E706C6A6B74726F6A6B777276706F616C6F707273766E71646C6C6C72706D5E6E6C6E7E75787776707C757174666E6C70747B7E7E726B72727164646A6974746F6D746F767370747E78736B656E7770756D70727272777B797D7E706F6F797275787F767E7777716E707370726F73757077776D6868675B615E4E77727F736F697B7B6D6C6A70717A7C77847F7B777D7575787D747970756C77786C6B6D6E6A6B6D777D76747B7A72736C6D70777A77766C72797F7B7B7B7A7983847F7B777D75757801FE64620707184075696677726C746B7667736C6F6F6D6A706A6E697572766F616C69797475666E76606A656A6B616A6C646C75786E6F706E6A6B6C637374817A6B727A706D626471626C6E6F7573757D75787075717A707773797B736C717F7B796E676C70686B65696E6E636570797778787C6A777F796E6173726D7376706A72707A776E6B6D6F6A6E756D7070757B7D7470706D6B7374727170787879706571696861605F4A75747E7879797474737072727D78787E7A7375758281757B8478747B79716D6974716A717C79747479747C78717674747573777378767276787A7E7C75757C807A7375758281757B01FE6562070718507E7A786F746E7A75786F6C6B6B6E6B706F7170716F6D706A6F727273726A687673706C6F6E61675C68696B6E726D6D706F6E70706C747173746D76766E6B66656F67606B74706C717773777471737E7166757C7A7A7878797C81706C7571696F656B6D726F69716C76756E6B73767F7B6B6A706A756F766C737A71737377746D6D6D6A69736A76707378756A7373787374766E767975766C6764636969616050726E7B75736B7275727176757576817578787C797D75727577706D70736E6E726F736D787470737979737C76726E76746D727A7C75756B707B807B79767D788478787C797D75727501FE6662070718606A6E636764686A666568676F6B6B6D7472716866676065716B6E6E6B76717070666A6B666D6A6570726A706E6C74717172706C6D6A6A6D7C7174706F7172727169656A707678716D7C7569726F717E767375737A676C7C7B847E776C7472696D6C726E6D69656F7B6C7571666D767573736E7576706F6E6E6E7674747777727775766F6F736A756F777470726772737575716E7379736D6D6C6A64725A5F5B566D6F767677747A73766E756F787C7B7D7F747376787270757073707576777579737570746E707A7679767B7872777571736F6D7375726971767D7A8085887E7B7F7473767872707501FE6762070718707572716D6D65786E6E6968706B6F6779707271736D6A6E6E6872706D73786B6C7068686572786F6965666A716B706E6B7479766C6A7271706F706C6767696F6B656C67756F7C6A7C7D72726F72716C6D747B7476736B6F7678817B726E70696C6F75706B6E697779727B796E6971767E6E747273736D7C707A716E6B737D75746C7065656E70787D787576776D6A717074797479787E7B7577696965655A5A4A7A78887E7C797E7B6A7072837D827F7A817A7E76777C6F777A7A777671716B726E6E6E75786D7476756E7B7A757277666772707974736F737C75777E787E7D87817A7E76777C6F7701FE68620707188076756B696A737377736A656C696F6F77736D7073736C696A64686F756E72687F707172686A6468636B6C6669706F696D6E6A6C74757677756D7176776D6E666E6A6A686B6D6A717B7B7A7477736E6E6D6D736F71726B7574797472737B756D6E646C6976717B72727775787278787C80716C697372736F787272716E7A726E696E696571737371777684797971767A6F776F6F7974707678685E676969585C4D7A807D7F7D747A79756D6F7179797E7D79797B7D7A7A6E787677746C6F716F737D7D706E73707279786B7679746F6A6B6E6F6E7C71786F7D7B797D837B82857D79797B7D7A7A6E7801FE696207071890796D7A7A777275717B716E656E686E7878766D6B6D6D6C6F6E706C71777366736969706C6F62696B666C6A717674697B717B72736C676865796B757676766F6F6B6F706F666765676C6D74807E7476796E77777D6F776476767B75737C737065696C757B6B6A69747A77786F71736E696F6A747F7B7C7A716967747071776D6B706E6D6D7970757A75727A707069737B77716F72707371736D72716E6A5C5F486C7671807C6E766F7374797A787D7D7D81797A787A79737B7C7773726E717379747A747175766F727A6B797A716869706C6C6E7E7D78737973737A7F78787F8481797A787A79737B01FE6A62070718A068696268696F706D73696D73657369737371716C6963666D6D686564737371696D6D6C6A6E6A66696C6E767874696670766D73766978746E636F7571786C6F6F747568716E7163707B75756A6F6E79776878737C696B717C77727971766D6D726B676D6D6E6B6B7B6B767D787A7479757A6C68737476747269656C68686B6F737476756E7274706D6F6B7173767475717270747A777974726E6C6C645F585E467A71777B7D7D7E7473707574817E7A7476767B75747774787C7977766F75776F7272706B6F706A757B747C77787472767174707071736D79747E8288827A837F76767B757477747801FE6B62070718B08070626A696A6D726B6B6C6F6C6E6F6D6C6D7777786C656A73756F77727470756B6C6F6A776C6B64626867716D776A6A6F6F6C6B69717976757276756D6A6B6E6E6B6B6D707574737B706D76746A6E6B737A7372756E6A757A717D7D776E637F676869685D676E717581806E7178737D7270737D74736C706B77716F7374706C756A6C6D757175797579796B726875717C76767A787A716F6A6A6B6366615451666B747174707A6A716C6C727D7C7F78797B71737C787577786D72737B6F71706C7673757375747A776A7374796D6D747871787B7B7A75747D78757E807F757C797B71737C78757701FE6C62070718C0686A766F6B7175756F697466726C7172736269716B646C66686B6D717671727071716E666D6973726A676F6C6F6F71686C6C756C5F636F77736D6F75786E706C6D716B726A6A6C787075776E6D7A7A6E6D7672827B716C79797D7376776B6762606A6D6F706A786E78796E6F7C797B7A6F746D706D6E7277777D70757A796E6C6C736B717371746C7A8079776E6D716F726F7470717C7B76686A5E625F5D5C487579757779747269757268727D807C797E7C787A72736D6D70726C707574747A7579696B68727475796F7979726A7472786A71787376777B727F797D7D7E81897E7C787A72736D6D01FE6D62070718D072706C645E6768686D6E72686B687874766D706D746C68656C6C737C7773666668666E6F7474705F61696B6D7170697175686A706B6B737974756E7765696B6568626C706A756D717A7A80796A6C746F727A76796E717577747C71757973686C616B6C6A6B6E737D7175717A6F747083786971737F6E6F737C726B73776D7071696A6F666E677276707474786E7774838275706F7575746B68696A67666760507C7D7B7E847B7475747472767980837C807B7979807A77706E71716F7673676D6E716C7173717C7076707373777A7C6F6D757276797875747F7C7F85837D8382807B7979807A777001FE6E62070718E0766B6B696A6B6D6D71756B6E6D6A6F6E6F727170736E6B6B73736A6E74716E71686C6A6D706E6B6464696F6D6B656A6E736F6A6C6A7472717373756F7A71626F6C71656A7976757480776E796E6F6B656E74777D6A6A6A6A787A727572686D646B716974776D747A7F7B757473797980707472717A76686F687971737676726D747774706967767073746F6A726E6F727B7E746E727477756B685A68645B5B45807E7C827C716D6D71777972767F7E7675797B75707A7A7B80796D7B74727270737A707676756C6F756E7A6C6C71747B7475797477756A7A7D787A817A81857F75797B75707A7A7B01FE6F62070718F06A726C696E626E6B7266706F6E7D6D766F726B6A6B6A6C6E7369706D70646D6C686A6C6969656D6467666875726F71736C6C676B6F766D6F70696B6F786C72756B6E6D72716F6B797D736A6B696F7671717275786A6F7177857C7A6A666A656E6F72727A7170756E7678747B6B747071727373756F736D6C6C6978758875717C726B6D6D73707278757467706B707979746F6D67727A7E756D656566675B5B4A76767C80776F797B7B7B757D8478827C7A7678797A767A7471767278707579726B736E69687B796F77717673746E72706F65756F6C757B7D7E777E887E7E7E787A7678797A767A7401FE706207071800746A62656A6C6C676C626C69676C70717070676B6A675C6C666C7372746F6A68696A676C7074706B666B727378776C6E6B7073736F696E6F6C76757675706D6769716F697073696F7C7170756D6F76716D7578776D7476757D7B6F6C6D6B676967626E706F76747F7A7579736D71747B776F6E6F776E70706D6A72706A7274756B74726D686E7074797E7B77706C6D73707671716E7D73786D6769635C5B5749737D7D78776C6D69756D69737E8388787F77777D7B7A7574716E71756B6D7671787275706E696A7876747D79737676787473767976726D7378747A7C797885867F77777D7B7A757401FE7162070718106878696D6B6D6F6E67656E6661706D7473726B6E696A6D6C696F6D7274776F746F64686965646E6869676C78716F6F6E74706E666B7278736A767B786971706E756E7170676B6B727A7A726E6E756F6C6F6E7877776D6D6C777373737076746B626E686E62657670787971706F73807D74746962727774727A75717A757D6B707176706A716F7A6E7E7E756F726D6A6B71757E777472736C6D656E67635968526F7B7F7A7B7677747978727676877C7D7E74756E75777377737973787A6D6D707878707076746F707F787C76706A6E6D6B687073716B73757881818982777B807E74756E7577737701FE7262070718206D70716B65716E697170726B696F6F7472766969626C696B6D667A6E6E7772736871656869706D6F66686F776C676A766F69626872707575767A75716B6A70696B6E69676B6F77767B76746C6F7279717C7679787275787B7475686C6D67646A667375747877757B7173797873737079776A696F7873626A6A6F6D72716F6F716D6E7171727873717778747973706F6E7A7275757476787570746A6465645D4C71757B7376777478737A736A747E797C7C7E7E797A7D777E7B706C6E6D6571736D6E6C7268717179786D7C8371717474767275797174707582777A85817C78827C7E7E797A7D777E01FE7362070718307C72707070667078746A656F63726E6F6E6B736F6869686A6D696E777C6B6B7A786B6D706A656D6C6D666875746B7968737178766D6B6975707877717B706867716A6A686D6F6F756E79766E6F657473767675726F776A7D85797369717172686C666D71756B6B717A7F7B6F756E717570697275777A6C726C746D6F7375796E6C71746D7371707A7A7A706565677071756F777B6E787E756C6A706A70655D4B6974748179767576796D6F7581767E7D75717A756E7A787A7F7B7475706F737873716F6E6D69757676707A767873706B70676E7278756F77747B81888283838275717A756E7A787A01FE746207071840726C6864666469686B6660715F6C68706F6F706167656D666C6B6E6A756E6B706A6364706F696363676D7C776C6E63736A6F6D686676746D6E6A7975756B64696071636B6C7675757A777871756F736C6F73747C6E6F6977877D7D706E696F7271706E72706B797776737A6F697676736B7773737573726E727174716A76686B71746E6D7473747A7771786D6577807D777A77716C70747464696E706E645D4F75757E7C7677737B7F767275727C7F7B7770736B767B7976777870777378706F71756D79797375747E6976797271746F767778747974717B807573787B837C7D7770736B767B797601FE7562070718507471606D726E757177676E68657369706D6B69696A71756C696E706673746E6A65697171716C656567696F7A786B6F7570726D6F70706E766E7272717970676B6D72657873706B707B74726D676971726E7E7774686A6F717C787D7671726F68676B7074696F716E7578726E71767C807575716C736F716B686C7374757676746D69716E7978737C787973736E69767071756F71797A7B6E6C6D6D6E605D5D4F7E7B7D8080767779797B7872777986808779816D70796D766D697274736E747D767A7074727A776D72717D79776E7772736E71787478716F77747E7D817A7B858779816D70796D7601FE7662070718607971686860706D6D6B6A5F715A6C68717072746B70726F716C706D726F737171646669727468696D6A6F6C7777686A70726F6D706C756F786F707672686F7068716A686B6B76707676776E6C736E716F6D7770766E6D746D767D786F78706A69686E716A656E76787580757E77757C7E6D64716A726D6B6A757173727A777C76666E6A6A6C7878756B787D746E6A737778727A73717572726B6A6A68655E5B47797379777070717C777278717A807D7D867E817777757472756E707674726A6C66717272767A72716F6E727276736C717370777A787F7B7B7D717881817D7E86867E81777775747201FE77620707187071706770666B6C757666636161676E6A676C706B6D6F6D706D716E7179686B6C666E706B6B686F6C6B6A6C70736A7173746A736E6A707D70717379776D6A65766C6D626E6A75686C7571676F7270777176827B7371706C6F8075706C76777572666A71736E78797374757A7074746F7A6C6B6C756B74756D6E7069686F7479706E6E777A77776D6F71717173696A7B7670727773737975736765696D62645E4D737D7B7C7E7B7772757176787F7A777C7C7875757572727C807A7C74716E6B7B737373777178726A6F727C7B7671716E7774737A727B74747179757E7B82807D7C7875757572727C01FE78620707188072716667646E75827A6468666D6E6A706C736C756974746B6B7472767465626C726D6A6E6B6E6F6866656A777370746E7071787676746F746573767670717764676E6D6E6A7068727072696D7073786D6E7277726C6673757E827A6D6D686D71696D6E6D7074756F7B797D7B72727578717A6F736B6D7068696C72777A7372736D6D7076716F717B757A6D777070777E807576766C6B7072726A646B625E5D577B77817478726F717F73737F83847F7A7D7376797175737678756C6D76776E686F7B736F79786B7576717A7B786C6874686266687875757876807B817E80818A7D7376797175737601FE796207071890787A70726F7174747470726A6D6C6F75747669686D6A606B68676E6F7473707068706C65696C6B6F6A6877746D71777176736D6F6E6A6E79726C807274666D736D676973646F6B757B7577697972787574706E726D6F717A7B766F6E6D656D69676F7076727576707370747076747D806E6E6974707069706E6B74717A6F757070756A68696A71777B7D75716C72817A73727776787574707276686A6A615B477A7C78767371767B7A726D7C788080837B8280827980787975777C7C746A7176746C6D70726E7875756F747474716D74736A717B76767A7575787D817F7F83897B8280827980787901FE7A62070718A0746F636760626969736F6C6F6D686C777068736B7472696E696D6C707468716E6B6C70646F67716E666D6973766E6C696A7475726B6F727E74766D6D6B64766B69766E706E6E71706B77707571717B776E74787B757274717E7D746B706A646463726C706D6E737072737678707A7879736E706E72706F7670726D736C72747A6A766D6D746E6F767B72756E74707575707371747977776E67666C6C605F5F4B756E757B786C6D75776E6A777E7F7F7A737A7D7C74756C7874766E75717473776F7470786F6E6E7673727C786D6972796D7374737574717E78757C8484817F79737A7D7C74756C7801FE7B62070718B0756C69605D6476776F6A756969706D6F69666D6B6C6A6C6B6F6474717F73746C64696A686A716768696A73737779666369646E6F656868737470747A7E6A6E6F79716A646E7B707479776E746566756B6C7679706972737C797A7770796965676A6B69726E6F6F71797C72746D747B736D67706D787377736F6E706A767B7B70766E6E716B706F7A74786A6D7273787679727675788077786C6F6D635D605F4F797C737875657272756C767B84807A6E7173776F797C7A717768686B7274796E73726B7775727372726D76767C6F707677736C7674737778757D7C837776767A7173776F797C7A7101FE7C62070718C0767576746B71766B67696B71696E75787470706D76726B6A655F6E707171717064616560706B6C73726D6C727A706D6C6C6D6C706B7070796E76726D786E706A6C6F696E646B73787174777171737774766F6E7B6E6B7474787D787271736F6D60706A7067696E717A7D76716D6F7A7C756A6B70736C6D7777756A696C6E7174726571727A7171726C796E7D73707777767472787A75857B6D6D62616B635F507B7A85807D7172727674796D7E7F787675796D7A7E7871737A787370777770736F7679787672757079787F7A6E6D73756B6F7179727A7E7479777B83817D828275796D7A7E78717301FE7D62070718D07B7E7C76726F736E7C727875726B6E6D73746D6A6E616F726F70777581736C7369706E6C6A6D6F72726566706E6D6867737373716D747179757A716D666970696F6D706A6B726E767C6D716D71747B6E757473766A79787E7E827866726E636A6B70637E696D696D717674797A74807F756F6E7A75766D6B6A6F7273737778706D696F6B6E6B6F70757577746E6D767B77767B797B7C807865676564635E594D747C80817C737E6F7A747576737A82727474797D7E7B7C797C7D7073787372706B7472767071737774718281796B71656E6B6E717A7E797577797E81878080837474797D7E7B7C7901FE7E62070718E0746C646F6767746C79706F6C636D64727376726B6D6E716A706E766870746A6D6573686A6D6B777069626A6A6474766E6B736D706D766D6B717679726F726E686A746871666B667476787571756E77736C75787D6D7069767A7A7678736E625F6A6F6A6E686C76747B7C787F75777E796C6F6B6B7375736F737170797277666D6B71716F767A6D7C737C72716A717677787871737A817B7567656564646262466C79797B7978796A7B747774717D736F73777A7B746C7377747770766E6D73777076777A6F787176796C7475766D70716D70687A768480827D7B7D827A7F858C73777A7B746C737701FE7F62070718F07265605E62615E6C7267606360636D6F756E676863646D63726B746F6C696A7273736A6A6F6F706F6D6A67756F6A6B75746B736A6E68716B737070776B736C6F69696B656F7071687478706E727477757E7A8185766F7075737A7573746C6E6F6C65636969716F6F778077747276787F6C67666E766E757076727071737A76766C656F70766F726E777B766E6D6A697574767B77777579757067716A665C604A6A72717970646D716C756F6E76767C73807373717A777779756F686D74776C767C7776796F6D796E73727A76706F6C676B68757A7B7972777C7B7B847D83817F807373717A77777901FE8062070718007A6D6970676C726D7467696067716E6E6F707274696A6B6C696C71727C6F6F6A6A6E6E716C706C6963666A76736D736E727773716D736A756B65767071746B706B6E63636273677775727579716F7A75727B6D79727875757A777470706E68686B67667A7377716874777B7E7A7779786F656C666E6D6F72716B74786C6C706865707972747C7D77747B747D6C727374776E707674767862656F666E665C634C7B82818A7A7A807A837A7A7F857F8A7776757D7974856F79797970706F747778706F6A736F7A716F7C6D787D79716B6D6F6974797B776B7B797E81837F80818076757D7974856F7901FE816207071810696C676B646664666465606764666F696B706A6565616C77696E706D6E756D6B68736F69716C676C6B686D747066696C6B6C74686B7077716A77736F7774796E706C66706E6A6D6D717775727573797572767177706B6A7C7C84777676696B65626F726D6F64686B72727973777179796B6F6B7C7475776D6B74716D7876786B726A6E727277757576736E70676F79797A7D7C75746F756A6D716B705F5D57497C7D7E877E7C797D807D7871898D83818379706D7577757D7673797F7870737B6F78766F7774727171757B7D7A7271766C6B6F786E726C75747979787D7E7F838379706D7577757D01FE826207071820786B6465676D736D716E656A6C6D6A6E69636C6B7169736971716F7C6F706F6F6D6F6C6667666E66616A777C7570736F6A6C76716E6B6B6B696E707773696E6468736B6E6A726F708070726F737A7770757B737A726C6D78777C7A726D71676E647267736C6F75767E756F6E6A7B7B826F7167747B6E756C7471687176727D71726E6E6F7075797B787575767972666971737372707375756F656968625E5949797F7C7E7E7C7975776F7772777D7D7C7F80796E78796D7476747876736F706C6F756F6E70726F7379737A7F766E70716D666C797A7B72797B797D8383807C7E7F80796E78796D7401FE8362070718307D7A74736D717673726E666E6C686D6D6E6873707B6F6C666A767072757371766B65696E7669746868667268707373757671786F706A6E6F6D6F757B6C6E6D726A686E7070727A7B8672746F6F6F75706C7470797277757A7A786F6A717166646269757666677174748379736E6A7379726B6D74746D71757675666D6B756C6D7575717470747577727A767C696B7478766E71777779766F697467676463574C7177797A787182737A716A6B797F7C7673727E757E79737375787B6F6D7177706C746B6E6A7975736D6E7875756F71716D7272766F76757A7F7E7F817A7C858A73727E757E79737301FE8462070718406B646363616671786F6861645C6268676469666C7172686D6D6A6366757575776A64645E696F6B71756E72756E6A646C7172726663717477756F72777B7768716C6868696D78686D776E72706A6274797270727870757573768381747C6E6869626F646C66757179817C7C75797879797C786A716D6A6A7077666870756F6970737171767A6F727C797B76706D7172767471797A71706C6C6F6B605F63585D4C7775807D7B737A73736D74777F77737778777A7A887674727175737176716D696C7076756E757B80806B7971726C7171676B707075796E77757C7A838084828178777A7A8876747201FE856207071850796E6973796F797571686F73696B6D74756F646A7169676B6F727074767B76706463666471696D67655D6B6F7171727479767579706876768074716D6C6C6A69646E69706C6C71706F69747A6F7675726D7E7777756C716E7A757B737B73686A66656C73686F75717D807E77687171786F6C716E7671786E6E6B7176716B6A776F76776D706F74716D78786A717374786D70766F6C7C726C756D6B676A6363496D686D6F7171717774676464797778767C7E72747E6E6D7E7E747175766F7075666F6B75747C716B776F817870676E6C717071767F7777787B7C778284807A807C7E72747E6E6D7E01FE8662070718607173626D696C707878666D6965656D6C6B6A6B6E71696767716A71716E6C736D716A6B6A6A72736D6962727070686D6D6A6E6C6D656D69777275786F71686B6C67776F726F7B66707D73716D6A6C786D74737078767269778075706B71706A736D72687B6A7670777773796B7076797D776E707772706A6966666C6C71757A686E6E74767672766E757873726F737975757074757A7B7A76736E68676764574D6A75797E76787C7C7472737E7E82877E7D787A73737776787072726C77736C7070716D7370707570716E7B77746A686D636A787C7673777A797F82837F79827E7D787A737377767801FE8762070718707A737974747677787D7168686A70716D6C7272706F686E6E6B6D6D6E7B7469706C656F6875756B6D626A6F78787066666E6A6F68697370806F74767675726361637269686C706E6D767271797372757D797D7674696E767A777D787683726F686E6D696E666A686E72787A73717878776C6D727082746C757874767C766B7070726C6C65706B7976747A72776A70747975716A6C7176726D7A6B6B6064585B51707B847875727871736E757873857F76736B7671747972767679676D7173757471746F6F6F737078767B79746F6E777579767375717773757A7E7D867C7C787C736B76717479727601FE8862070718806C726A6C6B6A6D6F6C6A6B6D6466686C6864616F706D696D6977767273716F72666C6D6A6F6C7071736E687D6F6A7070716F7A6A736F6B72666D747B6F6D6C63706D6A70726C72757775746C706C79716F736A7A6E6C6B78807F77717174706C6A716A6766677274747D7174707A7C816F6B70737572726B646F717674756F767073746F7476726C7B7C7A786B6D7773766D7375807276756F6B5F6662625B4273796F7D807F7E747A7174787C7F7B77777D7B7C7774757577716E777B706B6F72776F6F72716E726E66757376706E766F777977757C80767A757B80847E7D81777D7B7C7774757501FE8962070718907977696B6E696C6C76726C6C666B6B756E74747A6D6E6E757A766F766D7270726B6B646B6A6C6967666B6D74766C6B6A706F7D706C706D72736E7675786E6F6F696B6E6C6E77716B79747B766B6A6F79787873766F756C6F7A76786A6E6C69726C6F7A78706976767476756D6B757C8271716B737A7573696F736E6E73756F7374756E6970737579787E756F6F73767D776F77727876736E6A6A66655F58524B7072767073737873767176827E84857E726F7A76757775757A747676786B6F736B6B7172717473727B76787774737B726D746C727775767B79797B817E7D7F7F726F7A767577757501FE8A62070718A07870737574757B79777271716C6A69777A71746E6C6C696C7274707173756E736A6A666A736D706A6B706C7669656A67696D6B676C6F6E77777B76757561686E6E746D696D77747179756A6C6D6D6B6978756C7773717B767D837B7272646A736864696F6E6875777A7B7A7671697A7D76707270776F6E6C72756B7374736C7078706D686D6A6D76797778747472787A7274727978796F6C6E7271756B65554E7C7A74766D73767C78767675807E767073787C757776767F7978747077716E7372726D7C7570747073727B83767570716C6A6F726E797B7B78877E847E7D797A73787C757776767F01FE8B62070718B07473666A6564717172686B685F656F7D70736A6F6C6168746E71736D6E68676B6866676B6E686B6D686A6C797B726E726E6A73706C6C73717A736F726F6E7068686B70736C736E6E7A706D716D727B7674757F796B7075747B79736F72756D666E63696A6C6C71727783747464737B7C6766706A727475757279737E7C76766A68716D7270716C787E806F6B6769737C737D78787678797278696C655E5155507980847B738083787675727D7C7C7B7D787E817D7E777275777F7B76737272746E6C717473746E747A6F7A7275766C6C6A676E786E6C6B7B7A7D838C857A7D84787E817D7E77727501FE8C62070718C078717370727374727173766D616D6F6F6D71706A706F736A7173777173706F706E6F65696F61676B676F6D7271706C6E70746E6877747275666E7370726F6A6B706D6E6D706E6A6C7C786973656C71747475747A6B69707D838276716E776A6869757173726F777572707B746D757E81706B6F6F746B716B6D716B72747572776C73746F6E77777D7F7E7170696E7B756F737F7C786E796C73696B6A5E5E63477C7C7C7E7B74847A757F767D808079766E6B7A7980807975797573757E756D7470716B6A7276727377727D736B6C6D74776A6E7B797C787D787C7C857D7C80826E6B7A798080797501FE8D62070718D073626D6F70726B7479736F72717679737175707262646A686F6F717471686D706A66686F74686766656464787C6E6D6C717678776D687C697276756D6768646D71746B7780766D67766E6D787972796D6C70736D696C6C7986787A7582757074657268726D746C7B777975656A7D7E7D6C706D7272726B6E6D6E68747379736D6A6D6769757B7C74717D767275697A7C7A7176747A76796F6A636866685B59496C73706F6D73747474746C6E797B7C79747B7F797A7275737E7E787377757A78687473716B746F75716A7E73776F73726F6D73808578767A807578857C797D82747B7F797A72757301FE8E62070718E06F676B6D6A6C736F6C6B716B626468726A696B7269686174726A696F6C6E6869707170686A6E6E6C6D6F717671786B6B6C6A656373726F767270778576706E67676D736E6B6B676E757578767069727570787F7E6E737772747C6C6C67706C716B696571707674747779756F6C7E7B877B746F776D717274736E707376786D6B6C7273706C6E697371766F7B736F6E6E6C707372787A726C6D706566695C5347797C777774737C79746F6F717A7F7D797E777374767B78827C7473736E6B6D756D737276767B7371746E7A767E716F7B73746C70717773727C7A7F88807582867E777374767B788201FE8F62070718F0756B646766656C6B776A726D626E717172746F7468625F6E6D69716F726F6F726A6D60666B686A756F666D79716A6F746A6568706C7B6A746B73766F775E6F5E73716E6C66716B6C7972736E78717D736B766E726E6B70797E7D76797068656E6E6C6E7071706E6E79747A7575737E7C76726D716E75726D6C736C766E7575757770706F707872757A7B75716974757877757773767A7776736C666864605C4676787D838583797079706F7B7F847D75747A837D74757B737B727679756F7376716971746B7278777D7673757776676D7277787979737077787C7E7B7C80848A747A837D74757B7301FE9062070718007F77756D6A707876746B6E6F6C6D6B766E6C6C7171746E70777278777771687169686B676C676D6C6E6E68746C72677474726E70746D6D716B6C786A6770686B6B746C7169716D71756C6C777272747072776C7275736F6F7A7C796B716E63726E6E6D756967776A75777C7973797B79736A716C6A74716E74776E73827C746E746A6C6F6F6B6B7783857473706F7C7F796F6F6C73757B7565675F6567645E4B777E73747A71727277787B7B7E80837C7E808279716E7676737A747D7B7271717772717B7472746E74727B766C70776E7276787A7A746D7A79727C85797D80867E808279716E767601FE9162070718106E675F6B65626B676D6272645E676871607377606569716E7770737174757571766A65696E6B696A6C646D70726B6A69666A64686E6D6D6C6E726F7571716872686B686F71777173776E706E7675736D747F797C6D6F737F857C7F6F7C737563666B6A6C737172737077767372716F7375727A79726E756D73707577716D7272706C716E737178737D776F676E6D71787377766F747B71796868696D6C655A4678817D7B89757F7F8086736E7C7E847F6F777A797D7B7C7C75717076786D706E7C7E7179787B6C70786D727574746C656D6D7279757E797F7779797C7D7B797D6F777A797D7B7C7C01FE926207071820707569666D686E6D6E696D6968666D6A716D6F696E6F676F6F70767B746E65716764606E786F6667676C6D796C766E6C747572716B6D6E74776E72726B6B686A6E6E6771676B7571796D73736C6F7E6F7270716F637474757F7E7B707E6E626561666E7C71777A746F7A807C6A6E72787875716B7976716C7E7469757570686D67666A6A707270737B7F7876706D7D6F7D7D77747578736E726A6C695E5560487170737276717671716D7075797C827C7F6D6F707574757B757276707868747A74776F716F73707279747D717471746E6F6C6C776E71717F7D7A7C827C7F7D887F6D6F707574757B01FE9362070718307774766E69726D717C706F66686E6B71706E6E70746C6F706E6C6D676E716C75707067696B6F6A6B6263677A6F6B686D7372707469736F706A7A7775766B716A6F666A6D686B6D73757172716F6E737374757B7F727670747B7C75786D646B70646864706D7675707275767E767972756D6B726F6573757B6A6F706B76716F6D717B6D736F6C74727A7F716F67717C7B797468726F79736B6E6E6163645D584F706C73767A6A696C6B706E69808582727A77787A6B6C6C70716E767B756B696E747C717071777269796F7F717375777C727677797479716B75807783807D88847A77787A6B6C6C7001FE94620707184075786C6D6B6B6B64717672706C6E6C786E6F7365696862646B696A737D737077696C7073766D6E6F68626A6D756A7372716E6F74637171746E7875736F7269696B6F63736E706E6F79787570776B70776C79756F6871726E75827E6E72776C646C64676C6675776E777777796E7E76746C796B737072746C6F71717B78796D6B71676D717075707B6F7E7B787076757773737A767179786E666A6D68615E624F7D7A7E7D80797E7573787476878188767F7970798676757B766F73727A767174697B737378767174787579717478746D7674767172767777777779837A7887877F7970798676757B01FE956207071850807B6D747378757875706D706B736D777C6E73686E74706D6670676D6D6E6E696B6A6E6E727775706A666772776F72717265696868746B706F69737471676F5F666A73717073766C777173746D6E7675747A7B7D7667707A80757C6F79756A7069746676726C73707B7682726C6E7A756A686D72797367777976666E74767C797A6F646B6C737373727C796F6E6B70767072727D757C777166686066695C5E4C6E72767F7872766E7B7673747D7E78756F727274797D797275757176776F6C79737872756C6E6E6A757474747675707178717577707F707071797A7C7E7B81886F727274797D797201FE966207071860776C6C6768727270757070746F6E70727068716B6667696D686C6F74796D666A6B6B666A73716B6B696179726D6B71696E736B6E6978717875757C73746A6E676C696B6F6F726D6B70776F706B757A777070727A71716F7A79836F6D7575666E6C67696C746F706D78727673766D7579786D6A6D7D7B787476747B6D727B77706C6B6E6E72687072747C747870717475736D7776707772776767666A6457564F726F79737A6E6F737773747479817E7E7A73706F6A766E768274737076746F707371746F6F726F7277717C7D71707373747474746F7B6F757F797A81847B81877A73706F6A766E7601FE97620707187077766C7770717674716C70706A6F6A6C6B6E666D716C6E6B7671727D7D756B6D6E706B6B716B69615F6675756E6E626770726D6D6D706D6F70717276716A6C6A7368696E68716F7E7B73667C7574757B726F777F746D6B7B858073747973686B686E6A6F69676E6B6E776D7176787C7F716970707D7C77736B69697174766D656870737571737A786F7C77736E6B7D72696C706E75797C71726C6D6F676161477A7D6E6D757D7B807F757077777D7E7C7C717875747A6E7776746F7C74766F716C726A6A78797773756C797C7A6C6F74727476797B77757476777E84778079857C717875747A6E7701FE98620707188078746870656E756D756D6E725F676E777872696D7371666B68766E7476696F726D6B6B6B6F6D6A68656F716E757474757D6D6F79636F64706C77787F786C6A66676F6C7071766C727C7470636A6E7F6C737273786F6F74727E76706F6B7070706F72746A656C6774707E7F746B77737D766E7776716E6F6C6F756F746E736D6B6A7068697276727B7A7A7471677176707C6C827A79777276706A67636357594D807C7E7E747C717A76787475768080767B77887D7E70807577716A7A7672726B6F6E73736F777072726C7779786F7573746D7978737876727C7B7B837E7E777C7B77887D7E70807501FE9962070718907670696E686A6D6E756E706E666A6F70676B6B6E7176796A6D696F78766F6B676B6871717C706F696264676F71716B6A6970786C6B6A6F6C7475737668707A7F6D6E676164736F6C7E6E6B7474747D7368776F787068676C86857978716C66686A766D766B707875797A6E6E6A727E72757072766F6F6C696A6C6E786E6B6F7C6E6B727173736F7C7D7C7573717275716D736C6F717B7F796D6B6667616355467A737E787E716E76747A72717F85837B7A7B7D6E7D807A71746E6D7570707A75726F6D726B7473796B6D797170717376736D787673747571827F7681867A7B867A7B7D6E7D807A7101FE9A62070718A0707374787575807D6E6C736A676B706E6F6F70797470706C6A70766E8079756F6D676C666868756C6E6F667079707162706D68676A6B71767E767074736E6C6D66706871656F777C74756D717072756A6D7675706E6D75757B8071736F7A6A6C71717872716A6E74777C757C727A75716D6F7673726E666E68687076817976706D6F6F706B7569747C786E786A667378706770747072757571645F69675D635179757C76767575767B7874797F817C7D7577827D76827579747A757A706E6D72737674736B6C7A767E717977787077757774747A7073747375827C7D7F7C7B797577827D7682757901FE9B62070718B07B7672726C6F6C6A786D7C736D6D7372706B6B666E6B6E6F6F70706E747771726F656867736A6D6665696F727B69736F70707471706D6F6E6D757577776E7067666A6E6E737378747B7C7C767170746E6E756F6F6D706A768081776E727067716873676D67757C777774787472757B77706B76726C6F6F797371696F707675796C73686E6C6B75737F7E7974737273697874776E71797C796D656D675D5E5650797B7E80716E727973687272797E847F8076777C7877787377707873716F78757073697176786D7278687879796368726A6D777874707178737A79837F8389848076777C7877787301FE9C62070718C06A67656261686C72706B6B6D606E6C7F71776F666D686B666369686E74706A6F6D6E737470666D656A687071656D6F7477706F6A6A746674716E767470696D6F69686573727870767370756E64677473727B757C736E7175726C74737071736F647077786D6E716F777D726F706C737A6A6B706E79767072706B6B707A746E716B6B716B7B757F7775737B756F6D797E77747670737A74726D69625C655F5E4873716F6C696369666A6F68727A76747C7D75777578767271736B6E6D6F6F7171717473767471787D71707074736D74756F6A777372776D747A7C7C817E85827F7D7577757876727101FE9D62070718D07074696D626A697076726F65676E6F666C6E6D6D6D706B6C6F756A71757B7371737370706D6A5D62645F6F787174716C7778706B727474796B706F6C7279716D6A6C696C6F7A7376776E6C6D6B6A777270706B74666E747C7B7D707B7B6E67696870757469726B71747C747A757976777E6E6D6F747C7C6A6E76707477836E68656C6C6F6C747B7E7D767873686C726C6D6F7A796C727765686C656260675C4E757F7F7D7C7D787671727578857E82857B757D7675796F7472767279736F6C706D78756D6B6F757785747B74776B6D726E74797B727B797673766F7984837C7E7B757D7675796F7401FE9E62070718E07B776B6F6D5F6D737971706C67756D6F767965726F6B727474737A696F6B6D6C66676C666C706B626A7071726A71737978796D716E6D76726E727C76696C6F7067686B66676A6F6E807374736F717070677375786E707180807E7572766F707B6E6D6A716B74737C75777278767771736F656E767B736D6B667063727472736E7272777372797670767A72716B6E747479736E717576707370756F6B655C5445737175737270737873716F6E7A777A7A79737875857B777D7E736C6A6B6E71726E75706D7072766D7B6F7375776C6F6F6C6C72717278787D7A80727C7D817D8879737875857B777D01FE9F62070718F07C7B78786E6F716C756C686E6B776B706D6E6E706D706F7172766B6B74716C7D716E6C6B6D6D676570656C747668766E727E74676F6F6D6F6F6C6F746C676B6873706A69686E6B757C76737672716D72766F6F73727274787879747370746D6B646F696F6970736F73757F7470777E7E6C6E69777778726776717C6D7A6F7375706C706E756F71707B797B73666C7B797B787672767976706A6361615F5E5950706E79777B77756F71747A707E7E8D7D7D7C758078797079736F727B72716673776B6A7371716F6F726D777C786E7A75726C737B7A6C6B747E7B757C828280817D7C75807879707901FEA06207071800786E60666667666B71616A6A66756E70666871716A6B6162655F6F69716D7372736D71716F726B64636D706D786B7A777570686764717777797A7E74736D6E6C6766616F67736C6D6F7678746F686F70767A767A726873787C7E7A7071696E716A7169706E696E7273726B726C767D7B726A666E7B76726F72756C6F7A76716A6B6F6F697A6F7C78777E6D796C666F7073727377707275736F716A6F5F615A537474767E7F7C7970706C71707D7B7B6F786B767F747977726D7774707D73707671747677716A6C6E7E6A74797B736E6B716A6C7677857474797D7E7E79827E86786B767F7479777201FEA1620707181077706A6D6767656C6B69696A70706A726C706E6065636E6670737373707571736064606C6B6B6D6D696A737A6F756A696A706D64697174757576736D7465676F736D656D6E766F7473726E717874776F686E6F796C706F76807A6D7270746D676B72726D6B747672786E7C736C767475726C6A7270787A7A7D7D737273797B73686C726A6F6B6D6D73747B776B70737574766B747877827068666866625F5C456F7C7B7A7470706773746F6F7C7F737E7A767B786E807676736F7173776D73747B757975736F736A72747F767E7775797978747C7776746C7C78787D82847D847A767B786E80767601FEA26207071820807E74716D737C75727667717375706B696472686E6E63737274707A7E72726C726A756C766E68695D6473747D6F6F6F6F77736D6E677073777F72737B666C656A686D6F756C747F7E776C726C656B776D71727F7A677A73787B716D766A656C70726E6E6C747676757A787370797A7B7467657677736A686F7772686F7378736C7175707A77787C7F7E6E756D728275727276786F726E6B5E63656561585A4F7878767D74737D7E796D77767A7B7E79746F7A79736F767273717F7F7A6D747A77776F6F7374727074737D78776C6D716C71717B73796E6B75838283817B817E746F7A79736F767201FEA362070718306D6B5F6E65677670756B6B6562636A686E70706F6D6E6D686D73726C746F6A72676671696D6E666E6C6176767566716E6C756C6B6D756E776F6B7772706E726D6A6B6B6C69737374776D6D716D6770767275757C726F7A79867778626E6E6E6A60636C79676D71767E7574757470807F777B6D7177716977716F77746E66776D6D6E74706D77737B747C756C706B737577786E787D7B7373707370615F5E59437370737C747678798575756D747A7A74797D7B7B787A787A7A757870726A6B756E75767874756F74726F7A7476796A6F6F747B78797B74767D7B7E8682798081797D7B7B787A787A01FEA462070718406B675564605D656A6970676D61606C69767272665F616B6D786D786D6F6B676B6A6370666F6567696E6774736F706B6D6C7173726F6C7365736E736B676B6B777565726A6F6D6A6C7D79726C787478736C7C71736A6E767B7E80736C756C686C66666B6F71756F6E6F787A7A73736A6E77716F756C716F726568656F727378716A6C707E767C857A7F7F7A787868736F716F6F71766C716E676B6E6B655F5C438077868382747D757C776D717D84827F82797671757C7C717A76746E72756C7673746D767176767673677773786B6E6C6A707375727071706F766F7E7E7B7A7A82797671757C7C7101FEA562070718507F796A76676F717876786F7064686870746C736E71706E67776F6F767C7574737962666B6F6E69646F6C6C787D696D6D6F70746D66736D7366766C737069776E766C6E6B6B6F6E77777270676D6F77716574747674767575817B7472746D6D6D676F6C7271696972798179767278727674696E6E72697173727375727178697471706B74757B81757376797F717577766C7267687475786C69686B72665F5C4B7278787F7B77736F78716F747A7F787A7373777075706F6F737473726E7272767A777270706E697571697B78777273706E6D73757172736F77787F7F7C8586857373777075706F6F01FEA6620707186070646567635D646F7C7070666D726E66646E6F6C686E716D6F6C6E777876646D6A665F626D626F726461686F6F73726B6D686A77677C7477737070716A6D696C637269706E7A737379787772757077757275766F6C7072767B797573716E6A70706A69746E71797372757A7176787475736A727376797471766A6974777573717272726C7174717A747B757374767C7975767B6F736F6F6A676F70635F605E4A70726A7675727A74757477767D817F837A7479777D7D747D7568716F736F6E726B746B716D79756C75727078736C71706E6B6E7A737171707D837F837B8080807A7479777D7D747D01FEA762070718707976796E72727976786F6C726E6F74707368707473696D6D766B627370716A716E6E716C6F5D6B70616C6E727768716A767372706C78697974706E74766B6A6C6D686B6A6273686F7E74777B77787F776E75707B6E6D6B6F767B7577766867626A6E68707774747A707B777373717B75756A696E71776E6D676C6F7C73757478706D716B73736B7375746E656D707B7B7E7A7D807E787C6F6F6A61615E5E5E4C7D7F837F7D72707B7A72756E7B817F7E7B747F77827E7A796D746F6C767476807270727674707A7A7A72787B747578767070777679787071787A81857C7C7B807B747F77827E7A7901FEA8620707188074776D736A716D76706A67706C6F6F726F73706D66676B6D6B6F6B6E706F6B6E70706D6E7571656B6A6C7674717074666F6865716D7270727071757D706A6769686E6969686F6870787B6E70697177746D6C737D6E687371807E7473787D706B626B736E6A6D717674807973707B7D7C6F6974777C6D716E7569686C7077756C6C72726D6C6D70727B7F7372696D747C7671706B7672706B6D6A6A7266645E4B7C7B7D7A74737A77797A737782748478787C7D7C7B78747677756E707271737573746D76787873706A6B7D6D6F717675756D737F7C78797A7F797B83847A7B81787C7D7C7B78747601FEA9620707189075696A6C656A656A75676E6C64676C73706B70646465716A65716E6C766E68756D716C6F656A6F6F67656D787B757170787C72736C6F6D6B6D6A6D6A726C636A6C73706F6E726F72746B6D6D67717878747A777675706D7B7E7C737271736D736C6871706B72736E72736D7F777A7476786B6870756F6D6C6E7D687C797177726F71716E746B777B777677716B6A71796D6E75787A767D76676A6A6A6560584C7674747C706F766F767C7B7B80787A7E70767E797B75737875796879737471767670697678747169767578707470786D6F70807F747A717E767E7D8982807B7F70767E797B75737801FEAA62070718A0756C656B666B756C6E6C6E6A626F6B71706C6B696B63686B72747A716C6E68726E646969726B686A70676C716C7070727A6F6B6E65656E746B6A7A78766B6D7166615D6771756A777F6E756D75757B70797971807C7A736F79777371736E6870696A67706B696F73817A777468697480746E6C716E777372726F706D73727272707A7475707273757A7A7A6C6A6C72766F6E767C7D7574706F646B6E65615B4D7D80817D757471737C787272798A877D817C7D747B77787B7F727676776F747172706F76747376717A707A7977646C737068717C787A77787B75777A7D7D8685817C7D747B77787B01FEAB62070718B06F6D6C645F6A6C696864626A6D6E6A6F6A6C6C74686170716C69676D6C6D6F6C7267656A6A646B726F746F69686C66686973716A6F6877787080797572746E726C6E6C6568716F7173716866777776716C6D7970797470707183787A6F69666F656A6E7A73707071787A787A717576787473707678676C6E70797766717A776F6A71716C6D77737077787674726A7172706F83827574776F6D736F61665B5D42747F8073757B7B777D78747683857E79767779776F7F766C7173707476747277767374726C776E6E7B757C7172747471717076787877777882777F837C82857E767779776F7F766C01FEAC62070718C07270616C626568707069726463676C69686664656A726D716A696A6A6A6A776D6C6F6F6F716D6C6C66676B737677736E716F6E686D7171796B6C706F75636F7570776C6B696C67696F6F6F73766A707C7F79797E747371757E797274717171716A6E706D696A6A736B72727470737A7B766C7173776F7B7B736D69727074756C6D6565676F757476777A766F71707A7A797A7D7379757372706D6A6961605A4B76777C7E707278807B757571778080827E72747A7E7377787D7B78767C7A738079776F6D7572757572697770766A6E74717A79797478757D7C7A797D81827E817E72747A7E73777801FEAD62070718D0767371615F696C6C706A71726C666D6D726E70696F6A64726B6F6E786E686C736F72636E746F736D6868686A75706B736D71736D687176766F717673726F6F6F67656A6D6A706D767B79716F7470737175767D7D706B7271727573747778706D6B6A6671766F6A7076756C716E737177716D7379736F726F766F696F6B726C6D6B6E6F746C77747A818573766E73716B70707975797878726B6C7267655C584975696D7877706E76736D6D777C7B817D776C7B75758178707B706B6F6E736E7B6F7972687371746E746B7D77706E6E726E6F7177767778797874797777777980776C7B757581787001FEAE62070718E0796E6C715E67706E726D6A686A6A6C746C6968726E777472676B6D6F6C6B686F6E66716B696A70726D686F77776A6D6D736F6E696C7070757A7475727567686F6C73736A6F6B676F756A787B736E746F6F6D7670717B7974807F767378716B6C67706B6E6C6E6C6C7076797D767977776B75697570776E756A706C6B707C71736A6E716C6D6E71777B7A7A706D677470777A706F75796E716A6F6A67655D57497D7D847C7B8078747E756F747D877F7976787F767978747D7C73727671757B736E74697277756D7175737A766F7476796F66706C6D776E78747B7B828084867E76787F767978747D01FEAF62070718F07D79747168727372766B75746B787C6F7B6C6A6F75716D7367706C6E786A71726A626A6F756E6769656A6D72736B686F7372736A72756E666872737370776C72716D706C74756B72776E67706C7072767771747D7467717A7D7670706F69646468687076727179797B77787678787973666574757D73736E6F6B7174727874726F6470696A6B6E6A787C7674737472767D7A7B777977796F6F6F6568645F53437267727D7D807A77827574797C7E7E7C7E717876747B7981786E73757A736C706B776E78727274747C6E7A7A776C72786F6D73767A766E797D7F7C837C7E827F7E717876747B798101FEB062070718006E6D5D696E6465656E6F6A6664786C72746F686B6D6B6B706A63696F6E6F6B646A6E706970646B68706C6F77706E6E6C756D7B686A7272796C69757273696D696D6D656665666F6F76766973717C76747A7E79836F7A7076787D786D70706F716B6D676A696D727076767F76737475827572726C777370716C6A6B69757575716C6566666C6D70737679796F6D6D73767071747A787E76766869666B62695A486C767B7974747B747B8174777B8479807A7C84727F7C69687B7177747A6E75726E76717273756F6F766C75757B6F6E71736F7374767A777B7E778381777775787A7C84727F7C696801FEB16207071810686559605B57616565625D666C63666C6B6F6C6A6960656A6C68707970776D6F6E6C6A646966666965656D72606A7173776F6E6C776E6D6E6F716974716C6B66656B6763706E737B7D7A6E7677777A73716F78706E6D777379807A6F6F716872706C78766E717872706D7C76767377726A69706D6871747169756E7669767272736D756C73707B757B75797873757A70796C71706C7579776A6A6362625E594B6E71726E6E757571737178727E827D7C7D747171827C72737471746F696E716C6F7278747772767776707676766E71787672717376766F797E797D8684837A7D7D747171827C727301FEB262070718206A6D6B696368746A6D696A746770686E61676A6974696D63696D71737674706F686D6D6F727067646B7568766D63676C6E6C71756B736D7171696B76736D6465676F717B73746F74796B73686B72766E68727B766B7676807E857F7777726E756D6C64657071727874717175686F7272726B6E7B7F7B7A6F7072706D6C767371726D6C756B726E6E7878726C697367737C7973727177706E696B6267656253446C6F727C70696F6E6F686B6B7B7D807B7B7672716E79726F7772757B71786C7376777575706F71747674707470746D796C71767F79726E7778727683808386857B7672716E79726F01FEB362070718306F6E666E6B72717572676F68666A696D7470766D756D6E716D6F6D6C796A6F6C716F6E6A6C70676766666F7A6D6A696E7275787260756F6E6D6970717771616B6468677270737071727174706E7075716E767279716D76727673767C7574716E6D6B6C6D67686D707074757A7172797D736C6D6F6E72717078727074727B736C6C737775706C716E797D70717170787A757077737476747871696E6A615B614A8179807B83757C87847C6D797A7C807A8275747979777B7A7472756F776D716C7A7E73727A776D74736E7D77766F6B70717079817075797D727A7E877C827A7C8275747979777B7A01FEB462070718407B776E706C6A747975686E72706D697170736F6B6268736D6A70737878736C6B6A6C6D65706F66666465706C777472726E787173676A6D726B737C796E6C6D6A71686D6968746973707570797173796F78776E707675717976817D7574706C6C6A706C726B73716B767A7974707579766C6D6F6A6E736F667073737376717378787073766D7273717373716C6D728074796C767979797676736F716D6657594A747B777777737A7170776E7C827A7685787A7C7A7E7B77787674726E74756B7371726371727982777B75767D76757170676C7171757A707A7D807D8483817F7C787A7C7A7E7B777801FEB56207071850736F666C676D717D7C686269676B676F6C6C756D626A6C6F6F6C69726D7262676D6B797676716E61696872776C74716F6D7572646F6C6C71726F76756E69666E6B6D707174706670797D6E7370746E69697275707B7575737C7A7C716C69656A6F6A70747C717A6E79817A6D68727885716E73707E776F6A6E726875797C7A716D6C6F68716E77756D73736E6B6D7C7971737B79777477656C6A5E655C5A5C4C78737A7A7873797473736C78747A7779807A837E7E75787474747077716D6D6B6A71787C6F6F73707A747C7C777576706C74707779746E7373747A7E79807C83807A837E7E75787401FEB662070718607B6F6E6C716C6C726C6D666B6877706474686A71706C6874746F737072716F716F676D6B716A6B6F66636C7A7271706A71676C6B6E756C75746F797A716C69636A6C6C707271717974816D736D7178736F7673776C6B6F767B7B7A77756F6A60646D7178757677787C7A70726D76727872676F75756E697175746B766A706B6F706E6D6E706B747578797170666D7A797E6E7C7A776F6F6D6972696C655F614D797B7B7B7270737976747D767A777778776F73767B787E7577756F787172727278746F78736E737A7A747670706E736A7479777773727377777780807F7C7B81776F73767B787E7501FEB76207071870716C666861676F6E716C6B6F756E6B6F6B667273706B706A6E7170757A716D6B656A70676F766F6F6B6B7571696E706A79706F696F7574716A6E767B716F756C6D7370706868656C717770666D71757474767B7A71696B74707973716D6E6970726A6B77716F6E79727B7C7C79777B7B79696660716E697371686D746C7E7577706D6F727276787C72726B696869767C7A7775746F716D6C6F70686D615C5E4A787676747C7B7978756F726E757981797C75797B807674767B7171727C7B74706873787775747B74726C73746C7674766C6C7372727875747976757C7F79827D7C75797B8076747601FEB862070718806F736F61646D676C6C6D6D68676D656E6972676B6E6C696B6B6D79796E78756C6E6E6D656D66686062687274716C6D6D747A786F6E736B726C6F7774736C6E656F75726F6C6D6E7A7E786A747372727368786B7973746D7F7B7C68707468666F6C6E6C6C6D726B7379817570767C787871686D69767171756C7070767178717270716B6E69766D7D7A707076686D6E7576716F706E7D7B6F6A65656D6C5D5B4C6B78767876736E6D6D69666F766E747578707B72707B7082786F6F74767070766C6F77756F74747175677479747371737270717471716A6E777E8383807D828278707B72707B708201FEB962070718906E726A66666B7671766C656E667068726E6C776069646B6A6B736D73717B7370686D6B676A6666686B6A6C7E6F6B676A74756F6F7168696D70756F6F71736C67696A6F666F7265767A6F68737B7779777774787A736F6C737576716C78726C6D6D736D7171726F7B73777C7A7475787B6D707170776F6F72767072726E757377696D6E6D7874756D6D8477766C736E7D7570747D7D76756E736965596655584980787E7C827C7C79766C686C81788487807A7879798174727B7A7272767067706D72747372706D7A767B757D807372726C6E706E76786A737E747781827A7D8E807A78797981747201FEBA62070718A0726E676B656E6D65736F6A6362626B747674726C6B686C67786F7176777167746C6C64666E6F6D666A6B65757A6C6B6A716D726D676E71786E766D7E776A6C61666E696871706F75787571726C796F69717873726E6C74808478706C75766C6569676F6A6C7279726F7B73786C767776766D766F7173736A6C73767470766D786F6F75726E6E6D797979746E6F656E77786C7274767B7D77776C6C6B5E595A4B707A77737D77756D73766D6E6F7D77748482818275756C72737771797071717173777273696E6B717C7474747572746D6F6F7271777F7579777E80847A7E797A8482818275756C7201FEBB62070718B07470696F66606E6E7B6F6C676769636E716E6D6D63616F676F726E72737174766E6F636E676D68666F71717A707265706C6971766A696C72716B7677706B6B6A6E7469726675726D7472746F716A727073757A7A6E7576787876786D7462636B706C736E7375717679747A72797879806E696A7472766B69727779736E6C706C6C676A6D6F6F777A7A7D7377696D74737D7C72787C757F6E686766685F5959506D6D6A756772766D7A6D6F737A897C8173737D80787C727373767172747370787976727173767E77726D6E6E7372796D6C6E7074797A716F787E7C847C7D7B7D73737D80787C727301FEBC62070718C0776E6A707274776F74706D65636D767B70726D6D6A6969746C6D6E707273756E6D6D6770696E796F67706F727C7A796A6B706F6E676C7170717772736F6C6F6A72776B69697971777F72756D6D7076727071737D726C707581766E6A71736C6C69686A76747075787A7A73706D6C7D767470747072777D74706F6C696B786F716E7063686D6E7073798682756D777A7676727972776D798077746D6558575A4F777A757B726E736E7C776F77727C80807B787576757A7670737A717671776E6F706D706C716D717A79787D79726B676B70727C70747377747C7E767D78787D887B787576757A767001FEBD62070718D06F6E6D6B6A6D6A6C6D7470666671707D7272676868676C6F727472746D6E6A6F676B6871636A606961636A75706F6E6F6D666B6C706A73747877786F6F6C6E72696764677373706E75777B6A6B75726E6773777D7A7066747C7F7D7375696B6D67766E716B6D757376797D777573797A72786F73736D6E63736B7473727479786468697077767A7B787B706C70697A7C756E72707777736F736B5E675A5A6154747473747A71716F716C73677D7E7D758071727270747A7D7774757178737278706E6E6D6C706E74746E757476747D7272727478767A78757C737E7B7C807D848071727270747A7D01FEBE62070718E0746E71706D63757176726E6F6969646F716E77776D6B6363666F6E71706C6B716F69716F75716B6677726F726F73766B696C7971706E736F6E687370726C69656565656E717274737F6E6D6F797A77726F6E7176756F7B757573716E70776D696D6F687071706F76757674776E7177746C6A727A7C6D6C6B776E6D7671716C786F7A70706F717A72797D71736F6F76776E68777A76786D6467696B6C68625B44717273787175697176747777807A797578727C74767275787576717274736869727570757372757378707E717C6C6A6B6D6E797573767676838081817D837C8078727C747672757801FEBF62070718F0736D6B6C6266796C70686A6E6D616C726A75776D736B6A6D6C76737373747275676D686369656A65665F6E71746F6D727372726D6F6F6A7177707076706D6D6C696A69686C716E76717177776E6F78736C6C787C736E6F787F807572786E6D716D76726F706C73797B80786F6F7B747172676F74736C766F706B676A6F6C6D6C696A6C6D726F7573777B7A766A7C75777279747673777C766F6D626E6961584A747F837672766A747B746F7581777B73766A756A76766A787B787277757270776E787178766C757070707170716C7874727473747A7E766F7C78788082807377766A756A76766A7801FEC062070718007C7E786C626973696F6F70706F73707775756A6D6372626A6A6772717A71707171706C666F6B67646165707B796F77746D736C6B677668746D72786F786F6F6C6A6E636E656A6C726F706871716F787A6F7979807170797A8181786B696C6D6D6C7374736D7270717681756D6A717C75706D6C6B68717A7D7473696770707876766D746F68767576797E7875696F74717072727B787C746D72706863655D58456E7A7F7F787C807B7B7171737A7B7C7B7E7D797277797C7D7D746D726C7072777278727771707E767670777A7574726E6C6B747B707875737B82767C7C7E7F807E7D797277797C7D01FEC162070718106F6E6B696567706B756670646B626B76716E7671676A71716961706F727366716A71686E746F6F6F6C686D69747868706B6E706C6E766E76756F786F71716A76676E6E7667736A68716E6B767B6B6D726A6F717974706B737F817D74796C6967676D716E697068737577756E72767D756E6D6F74726E6B74716D7477767F78736F7A687C7474747E757372726B687479786E71727280726771696664625D644A6E75756B73737779786E62767C827D79767177737B7A67777C7479787A726F6A73716C756C7276706F6B807676687276706A7278767774787E7E777E7D7B8289767177737B7A677701FEC262070718207B77706C6B7070767071697164697178776A6E73716D716F6E756F71736C7066756964656F6B6965696A6D7676667275716F6A6A69736E70706E7A7575736C6D74706C676B6869767D706F7A736B717070726C737072757D77767E71736D666A686D68756E74737B777E71716D75727C7873747272766F6871767375756F796E6B635C6971716F757C84796D6475767B7D6B7A737871716E6B716F6D6761564D757C77757C7E7A6F756D736B787D82847E76737875776C77767074717274777C7379757172706C6F7B737A7675716E6E776A707377756D777A7777837B76757E7E76737875776C7701FEC362070718307B76757A6D6E6F737A6D6A63646B6E7B75746F6F726E67696B6A7072726B6472726968716D6B6C6C68676C6D6E6F696F6F746F6D706F7179666A727668675F6F73797175726D6B6F7A73776F6F737174737A747C71636675777B7A68736D717A6A736F716A6A7074807B72786A6E7273716C767573706D6C6F7471787C7075796E6F6D68726F716B7280797574727A7D79747E717375726B6B71645F5A64574971767573777475757675736E787A867F75797A7B7F84737C73787572706F6E6E6E72726E7074767471717975726C686C6B717772697770768078778480837E7E75797A7B7F84737C01FEC46207071840756E6568666D757474706C67656E726E6B6D6A696C6B6B68726B70676F766F736D6D696C776A6B6662646B706E646B756E6C7174697278747173766A696A696F7172686E6F7475757B72706C70737A836A72707670717876857D7075776C6765696D71716E6F747870767A746E77767F6B636A796F72707975787576707179726967687074767876748071766D747278766F797B79737E6C6563665D625B57496C7376666E697B74786E6871737A787A7A797478817971727977716C6F74707372757A7472727877776F767B6D6D716F766A7372727E7675757A807F857180827A7974788179717201FEC562070718507C7778707373757977717A7072707176656E7170716D73756C747677706E686A6475706C6F6D6C6861616F6C716B706D767470706969707274767778776A67676F6C67676670746B7D727A767C73777B74736F7B70747079717674697772756A676C6E736375767B7879737577767A7771666B736F767070726A6F6E6C726F6F706D707B73797670777377706F7679777470737174807668646C6C6B695A55466268666D6F6B6C69706B6D7574727772756B767B8378786E767A7775757067736E726A756F6F7074726F767E797968737372756E737A777E8377787F7D81787A756B767B8378786E01FEC662070718606F726E6B64676D706E6B6772636F636D6D736F6E766A6E7070727872777667716765676C7166675E696D6F7B716E6C6A646A6E7271706E746C74737268696F726C7168727075686A6E74696A65717671767C7E75716B6777788172747570726C676C69726974747677787B766E7D778077686769756B6A70746F6E7172766E6B756D6D7071796A6F817776757372767276787076747C77756E6D61645E615C45756F777873748072707976797B81807C797478777771757978706A75776F706E7B79777673666C726F70787A6E7270746F6F797271787B77817F7B7C79847C7F797478777771757901FEC76207071870726E707874727073786F736E6F6C6F6B656C6C6F767369696D746E70726C6B6F666C7372736D6B6A68686A6F756F6A676C6A6F6D646A726B737173717A71707571746B6E656B656C747077746E73727970776D7469707979808478757A6D646564636369686A736F7A737073716F737D7474777574706E69757970766E73707969706C6F6C6E7172757B7C736C737970757577788079767270726D6D5A5756487071737167737371776B696F73777E6F7E69756A7F71727974797170735F6E6F73767877787D7B74787277766F6E6A726C656C75757A727579767A8483847E867E69756A7F71727901FEC862070718807C7769616B6C6F686F6D686D707369656670696A6670716F7471737278786C6E6B606B6A666B726865666D7A7373766E736F6F6D6B6F747475747270706E6B676B6D6D736F7769747D76706A6C707F716B7072746E6F6A7D7A74706C716E6C656764676F707975777F8079746D7C77767262697477757776746E74707B74726C706B716A7076787979816D686671726E766E737B7771786D666C6B725E64694E7069726E70707276746F696A797E857775737774787A7A746F6D6E737674787370746E6D747670666D687472667377777075747A6D6E68757B74777A7D7F808575737774787A7A7401FEC962070718906968606069746C7374636C6D6D6D706F68656366666A716A6A6C7670736F6D726D6C686C6F6E6A6A6A656B6C716F7771716F666A69686F6C717570717369726A6C756D6A65726B727372716D777272756F7881746D6B79807580847373706C6E666D69706A6C6F717C847F74757A797B687072716B72726973776D7777777774646E6A7075736C737976726E6D677F7D796E75706E77777673685D6467575D4C69787375756B7B767D787A78797B7D7878747B7D7E766C727D7C6F6C7573676C6977757F76756F6B786D7273716D756B726F7577777A74747A7B7D817B747F8078747B7D7E766C7201FECA62070718A077736C6E6A717074716C6D71706D6D7671706F6E6A686D6B696F6F7079746C6B6360726A70736F6F6C67727871766F6A7370696A72756F6A73746F6C6B6D6B686F6A6E707A76707073716B766D717175707577767774777C7D7C7A7072726870636769716B6B6D7676787B746F7577806B73736874787369756F6D71707B73756B73746F7C7278717A7377706E76717A7175686F776E6F6F6965686366605C45767E797D756C717074706E7279767B7F7A777F7D797E7B707C727573766C68726D75766E73717573787280756E6D69756D6F77767275767E79777C82778387897A777F7D797E7B7001FECB62070718B06D6C66706B6B6C716D6A6F6B6A7276716F6F6E6F6A68676C77687271716D6A6D736E6C7269696E69666B686D72716A70716572716F716C747A7C7B78796F6D63676F686E69686A727D7779736E6C777379767276696A727C7A7E747877726C6F7372706B6C6A7673737B6D757375777E74746D7277727367696D6A767475716B6C68736E6E6D6E79787C78736C787577757A7C73777D7B7776645D66615B54487874766F7171767673746F6D837B75797E71736F7D77757B757479787367716F6F74797571736C6B72747672747477736C70707E79796E6C77757B85807B7F817E71736F7D77757B01FECC62070718C0776C646B656E6976706A62696A6C74736F686969687773756C68726E706D706F6C6F6C7474756D62646471737178786E6F6F6C6C71796E6B6F6D736E79717071686E62726E706F6E73706F6E6C727A756F76757E73717074797A7470776A6C66666D71776D757176787778797770727B6C6A6F737976737C71787876737A73696E6B6D76797375727776777565617076717479757A7A766D667069635D605947787A7E746F6E6F767A77716E797C887E767775767C776C757B76737B6F71717370706D6C736F726B72657173706D77746C7578717276726D76877E7F7E7C8183767775767C776C7501FECD62070718D077786B7065737B6F6A6C6468696D656D706F6E6065646D6D717268706D72686F66686E70726F7169696B6C70716B726F6E75746E6C6C737172706E7575776D68676969636E727173777A77736C767676777577746D6C6E767482716B6869666C6B796A716C7B707C7C7E787678706C7775667170716C7071757079707375727070726D696B717370707277776C7074767D797B77737C7979706C6966675C5C4A71726C6C6D757A6F7671716C7179807A76757476777A6D787174736E7B6A7A7671797771737579707B68786D6B6B7677746F6E746F767475767A83857B75798676757476777A6D7801FECE62070718E0756F686164697070736D6F6B6B726B746B6B706D6E666968697172726E726D706F6B6E69706B65626B6F70727371676774746D67686E6E6B7070777B78686E6A7267747572766D6F646E6D787A807872746F76746C6D69767C807E6F7173696A6974736E746771746F767876707C777C6C626A757268716D7B787471707772776C6F6F736F6E7774807A6E6C6E78746F7E787877767C7572676C666868615D4A76727474736971707C6E73767B767E807C7872716E7872737A78727672736F73737A736E656D6D6C7174837D7A6F6E71736E78727778727274777F83818278807C7872716E78727301FECF62070718F084797B716F6A7675746B7570706D6A676B767371706D696569706E6E74726D71746B6D647174706364716F776D706E6A6D706E7076746E7D767276726C6A7172786D6E696A69677579766D70716D73757173797A77767075747A6E6C716D6866696C6C7A75757578736E727B747878786E6D696C74746C6B6C6F717673746A6A6D6A72717771838173807474776B787C7F756C7570746C79716C706B5F5B545072747D7B6F7577757B787477777D7B737674777280776E7A79777874716B6C6B6D747D7B70737473766A76797275716F7472707A747E7B827D7E7A7C778279847674777280776E7A01FED0620707180070715D6C6A7372736E6D6A6C69686B746D73706B65676674726F6B6B736B6569626A6D6C6D6F6C6B6E666E76767365716D69656E727A776A6F6B776A706C6F786C6C65747472686E7C696A667971736A727A7480706F6E737E807A7A6D7566726C6F6A6B716B6F7B7573787A6D767D7971636A73746C6E6F6675787472777A737068716E706D727877746F6F69737D7C746E76707B737A716E7065675E5A584C78777A767D776E737A786B726E76787F7F79746E797A6B7978796E707377707172776E6F706A7275716E8480736F6B716F71737776776D707474818C828183887F79746E797A6B7901FED162070718106D706A6F6B6A6B696C6F686D656E6C6572786E646D636A6F696F6E787F71776E656A686368616E6A68646E716C6D686D7C7474696F6672776D7377726B6E696B697575766C69707A7A6C7176786F6D7574777079726A71777A7D726B746D6B6B60666E706B727072797B8079796F6E736A6C717E746D6F74746C7372727C747076696F706D73707277786F6B6672787774737A736E6E726C696A726669675E4B7472796E70676E6D786A7274777E777976737E787978787A796F6D726E6F74717675706A6E7277707271756E737176726F6D6F79797D747478837B7F7D7D7B7E76737E787978787A01FED2620707182077796F716F6E756F71706E6D6C6F6F747076766A706D717068667273706B6C716E6B6E71727172696961706E78716C6D716E73736C736D7A707576716A6C70636C717472686C7475767371786F65706B707379716B6B746E7579776C7E7271706E706D716B6E6D77747B787A6E7977797A666B73787470746D7278746D76767268636C7264686D70748074786F7478757774797B7B76787670746A68695D564E73777170746C706C746F707083817C747E707D7674726C707D726C7370766E707877717077766C6B7365777F7E726E72746C7275727E6F6D787C7D83817A828B7E707D7674726C7001FED36207071830736E5D5F696D6D6E676E726B6A696C667069696B666F716F676D6E6A72746D6869606B6F6C7167746963636E6E6E6F777374756D6B68656F6E6D7A7B71616A657274676A69716C7276727277756F79706D747A75696D787C7A7771756D6C606A72716F736E7476776B7776776E74737B6E70736F70727D6B6C757D77716E6F6B7069767C78797D747579786B6E73747B7578787C7377707272686A6666605B4F757B807C7C727A72756E716D7677787B7D717878737375746D7C77727072717B7779796F6B66746F7779747B79757A74656A6D75737A77757B7E787A7E807C7E7D7178787373757401FED462070718407F6F67666C656C747A666F646861716B6E6C6A75696C666E7068686F6A7373707171646E70716C6C6C65737670676F6B7770686965726A726978767A726571696F746B6C686E716A797B6F716F7075797477767775706D72797E706A71696C6C7273706D697772726E7778727F7E816C746E6F6E7F706E6D7572777A746B6B726B6E6C6E6C7A7976797F786D70717E79777870747C7A7474666B686D5C5C5544747F8A887F6F7874716E74707E827775767F7F797E7770797B76717A746D72746D74777A787C78696F70767576756E726C697076757678727A7B80847F868087767F7F797E77707901FED56207071850726F6D6B687573767B6A656C656F6E6B6E67696770636C6D747E7C726C72656E686F6B676C6A6C6D6A656775756B6C6C6F77726B7878717A737278766D6B6B66626B6C6674727475737671756C7675797172737D716C6A6E79827477746F6E6C6F6E70726F75767A7C7C75776F72756E646A666A6D70726A6A7470736D75777277707C72716F767979746B76706E777278746B7476747C6C696C6C6F5D5F574C6C7676797875746F73716E747A788079797C7D7774727974807575706F6C6F6D746F6F7574737471766E7777757C7A716F727A7774746A747D81737C80847D81797C7D777472797401FED6620707186071626060686A6B6B686464666461716B6C706D6B6C676A746F76726A76726F6F6C6C67666E6A696B77776F746B75736C6D6B686E6D757173687771706A5F6D6B7077696B6A6B6C7C7A816D62646F796F6E786D70736F7379717B766E7171706668716F787173786F69757B797A7480726C6B6B74726D6D746F71707874777579736772726D70797C737676797372747B78796D6E6B77746B6366646E69605E517475767B7A7479717D7D7A71827F797B7B7975747E7472737873767679716A736E6E7074726F7179776D7A7A78706D746C7278746C7F726E79797D877D7F838B7B7975747E74727301FED76207071870786F6E7278686E7368786E6D676D687870727471696A676B6A6C6F76767063706C646D69706B71686666716F736E6D736D74706A6E6E7B7172707374716F736C6C6D626B647173778075686B7074717072797B806D727277857E757573706C6A687170716A6B707274757A747B79777D7270746A6F6F757671676F72757F746F6A6E686C736C737B717C7670656D7B79717978797773707469636C68635C58517674767B736A6B706F6C6C78778285797E7B77747C75757476746E7178756C726D7573766B7072716F737A787767746F72747A7B717777807F7B798179767F887E7B77747C75757401FED8620707188073746572736D7473796C71746E6D6E6B706E74726867706F706E6F75797276766E6C6E706B676A705E64606D726E716F756D72676D7C6F736A6F7679706A6C686F73656F696E69727474717474737B706F777476706C6B7782837C77777471666163696F7373717477797C82727071776B6D726A7579756F6A6E6E7371807A757071746F6F65777481887B796F6E72746C6776727C74706B69646B5D615D614E74757B7A7B7C757777706D6D7A7A7D77767E7F757678737A787A776F6E6A75787C716D7B77736C73726F7E707B7E747C7275727777776B737F7B7C7A7C7B7F84767E7F757678737A01FED962070718907C71706B707275706B6D6E736A676A717269706E6E6E78706E73767471736E6968706E6D6B636A6D6A676D757272726F727E796F686C6F73797375756D6E6F646976756D6A6B737B7E74747171736E6A6F7B71706B6B737A7C6D7471706D6E6C6D73736E6D666F6F71787B7C76828181796D70727374666669717A7A757772726B7071716B7173757D7C7972666A7377737071767377746D6E6C6467645A5E48666E71726C6A68647172716B7A767E766A787C6F737579726C6F6F7A786D78796E6F747072747275726C72756D6A6C6B6C747A797C82727470707B7C7E7D7B7F6A787C6F7375797201FEDA62070718A074686765645F666671706B666D71666F6969756E69696C6F68726D727A766A70676C7066756C6C666F6A6574706D6B6B716D6565667079717678767072706A75797467696A6F6F787C7A70746E6D716F70797F756D7072727B7E726B6868656E686A6374767276796D7B79726D767C7F7A73736B6E646A6D6D6E6C79686D676C7977746D6F74747483777978716C717373757B75707A737062606760675F594A777B74787F74766F71686971777F7B7C7F7D807A7F7772756C67687780796F797473707077727471746C717674717A786E6566666C777271737D7F837F8483857F7D807A7F77727501FEDB62070718B0626C606A677269706C6E6D7367726F7E736F6C6F62636E6C6E6D6E7372736F6A666E7175736B6A646361787C73706A6D6D7770756C6C70727172727376686D71687375786D6F6D74786D7B7877676F676E7A6F7A676C77787475756A776C68666A6A72736C74797C7B7F737072767778757773746D6A70716D706A72777F776C75716F6E6D706F7570746C736F757D7A75707A747677726E6C6B646A6054564C777D888079737D7D7F7374737F7D867C73727C777E7C777A71707976746D747C7671706B6B777A78766F7276706B6C6A6D747576777476758278777F8178808073727C777E7C777A01FEDC62070718C06F776E7068686C697575666C666A75706E6B746E716B6F706C6E7272777274766E6E716D74605E66626F6973726E7170676C777064767078727070686A69696D696D6B6D70756A6D736F7173756F78706E7A727C7777707588767B7672685F66686F67796B70797E7D8075767572727A786F6B686C6E726C716F70787878716C6E6C69706D7B7371797F7B706F6A717C7B787375707876726D6769615B58554A7672746B74707478766A68707E797E7E8274777178756D73706C6D72796E6E706A71716E6970796F73757B74746E70706A6C73737580787F7771778477787F838274777178756D7301FEDD62070718D0777269665E657371756E6E696E6D7976707671676F6A6E6F6F6C76767A746F6C7064686C6F666765706C766B6E6B707075766F71706C6C716E716F6E7476696C696C68737270677887736E6B6C6A727878747379736A747C7F7E7B6F7168716D646D70786C686B79717A7F756D757C74736473706F6D6C67777C7C716E7277706D6F6F747573757C72776F746B6E76777873707C787A6E6B736D6B6A585458476E767E7E7E747F766D757B757F7B7C7878777A7280777B757C7971747A6F71766C75776D6F64746F79717579756F7171716E7271717276787D7B7D807C827B8878777A7280777B7501FEDE62070718E07C8175746D6C6E6D7263726F646F707976736B656D686F6F67686E766F705E6B646A6D69706C6B6A6B706E7D736E716A6C736E706F6F70686D7579716A6B6977736A676C6D6D6D6E707A7C7A716F7A76777A7279686D687783757671756C6B706E6C6A737879787D7C7777716C736F74766F6C6E787072706C726A6D6D7077757270736D72746E74747C7D6F64737B76736D6E79727A7B6C6D6F666460595E4A6A6F72736D70727478737275767574798075747A7C7C7072706D7178746A6972737974787472736F7E6D7C78746F6F6C7472797B706E6B7876747B7E7C7E84868075747A7C7C707201FEDF62070718F07B75727A7B74767B776E6C6E6C706D7971686264676D6D62666F6B807B766A6D676D6B6F736660656C696B727D74736B7072726A6A7465706F7A72706E6B746B6A6F6A646C6B6B78757A6E7374746E6B736C707E7C727C787C7F7B676D716E7265646B6F7074787176797B7A767476796F707170757770786C7576736C6C6C76706C7368676D7474747778776A6B71797776797971747D7C6A6D6868655A5B4A79786D7A6F66726C727371767A8280758577817E817F727C776D69746A6C6C6C6C6F787673746F7983717372706D7A72606E6F7F767A72737479777E827E787E8577817E817F727C01FEE0620707180078756E78716D6D7478726E726E6D6F787A726D6369706E7263757B7776776D736A67706E6C6A696965666B716D6B7073707077726A6D656D766F707975766B716D77716665686B707C6D74707077716F6F6D6F766C676A7478857B79766F6B6E6B6F72697475737971737076727A798178716F727A716E6B6D6D7179736E656869677370717875787D7B6F6F7370787576756F7A767577716E71626661625D487C7B7575767B7A7473787079787D7F7B7B8085797C7C767275786C7477747979747B6D6C756B6E6969686A72797677727675707D747571797B7E7E8376797C827B8085797C7C767201FEE162070718107274666F6773747B776C68606E6E73706A60677166696D686E697168736E706A686F74736E6C6F696C6B6E7B766C6A6A74706D6B6A6D70726E727B726C6C706C6A70696A696A7072736C7784777772706E726D76747174758483786D6A686C736B73706F685D72757A827D82727580796F6D65656E7371707375717A6C70716F676A70686F7A7C7A787D7772646A767A74836F7774726E6D70767068695D5A4A717575747375756F6F707478837B7880797778727B7A7976747078777079747772726B6E70676E6D776E7673736D73716C70727570736F727D817A8D847F7F86797778727B7A797601FEE26207071820776A67696D706A6967636B69646B6577707069756769666F7B73756A6B736576736B696A706164666A656F706C6768726F72726B7677757675717B6F666B6F786C6E6D7177717D71757778736F76787A75696974696C7577767C70706A676B70696970736E71787A7B7A767866746F736966726D6B7E7669706A686F767C7876716D6A72797772757A7473706A6D7373736E7378747E746C6768686B665D594D7C7A79747774776C6F6C6D707A767E7B777B7D7D7078757D7271727775706D7472727575727A6F74737073707A746E756E707A7C76796E787974758C807E7F83777B7D7D7078757D01FEE3620707183068686766666A6964756D766E6762686C65607266696D70656B6D6D7576757176646C686770736F686A61656C6C726E6D6C706D72697268726D6C766B737070635D6767706775666D787A7B746C6E75726B716B726C6D777C7F8380737871696E68736C7476767B7673797C766F6F767866716775787B6D686F6D737470787A7672696C6B666F747A737D74706B6C756E7B77747A737A7D73726E636A5E5D5E4E676E737373666D72766F6C6D767C7B757C787C7874746F7D78716C726F6D6A716F716F767B736E6E6C68716B766D73797371747A736F6E797E7A757E737777837C787C7874746F7D01FEE462070718406C6960635F6C66687669666861636D6D726A68616F6B6F6A676F73736B73736F6E6F696A696B67696C656C796A6A7574786E70656B6F7379716B6C6B7570706E6F73706C6C70656A737273736F6E7A6E6D717373726E78787A82766F6F6C6E6D6569687071777B7B7F727384717D7A75676F6F75786D72736F6E726F6E716B726E6D6D766C776D727B786F6F6B707D74716E74787973707469656769645E5F4B6D6E6B706F686C627277756F817F787D7A6F707577767F7E767574727B676D716A76737276796D7178727C807B7478766B6E73746E7570747B7373787C7C7E7B7A6F707577767F7E01FEE56207071850817C7B7277746C7C75726E6E707D766F6A686D7272706977737674747473767B6B706A6F6C67676E726F6A756D6879686B6D726E67696A766E706B736E696D6A6A6B6D71757D7367807969706F6E6F766A7678767077756B797E726F7074706A706F6D6C6B66707C78857F776F717377796B6A6B6D6E716B7073657773737B70696D7071707B7C78787C7470646A6E747875807A736F76706768666B6B645A4876696D6D717770686F7077797877757B7677787B7D7A787C7E7B6F6D6E6B6A79767072737E757072786A75757975736C6F7176787677767A807D807F7D7C827E7677787B7D7A787C01FEE66207071860746C6D706C70697370706C72656771706B6B6B6B6C6870726B707672727367706A7370727372696B6868666E6F6A6C697371737670756C777372706E65646965746F6A6C6F70757473746D706F73706C6F7378746D676F7E7F837571707269666475707675786D7473797C7576807B816F6A6A7979727370716D6B6B6B71766766706F7176757B80767878756F73766F707575757E79757265646262655C5A4F7174766D6C746F6B74727174757A837D75757273707D7A74766F6E76777674736F676F6A69797574786C767D787472686F737172747E767A7D7D7A7F777B817C75757273707D7A7401FEE762070718707275686D616E766D706C6D6C706E6F776A66636B6A68736C65646F6E7571726F636D6B65737B7667656670716F71666B6B706B6D6B74776E726C6E72726D6D6F6B6E686B666F76717E7E766F6A6971676B7C7877736A74798379746E6C67686A69666A77717E77767D7B7B7572707D7D71736B786F766E6F72676C7276717168756E6F6B6E73787B7F8075716A777A8079737B6B7077746B657068625F64644A6C7171726D6577717C7173747B7E7A77706D7879798073756F747170737077796C6F6E707A7A7675786F7C6E7174746F76787973767883767877797A7F837E80706D78797980737501FEE862070718807275696D6F7470737876646B6C6C70766F6D6D6A6E6C6A6C686E6F787572746A706B6A6A7172756C6C656C6E726C6D6A706E6D6B656A6C756D7B78706D6B776F69665E646F7369757779777275727C7972767C7F6D7275727E7876727274697065696E776B747B717B8075747074717F6F6C6D7670666E7071766C7771706D786C706D7069716976808076736C737371716E717476737170686A6A676159524D727D7878767080787B746E78818386817D737A7B73767A7B7D787777777371767477686F6F737E76726F776F73636F736C70777C77717178827878867E847F837D737A7B73767A7B01FEE962070718907E6B65646870706C73727372696B7677676B6D6565656A656A687A767673716F6B6D6E6E6F6C6A6765686D6B7379737270656B6C716E6E726F707777736D6D6A7574636D6A6A64677B767473766E7773717F6F78686E7177807776756B6D6D6A64686D6E716F7376747D7C7272787C7473686B737975746F706E677172706C736E6E67747B796F73707D7173716E79776D6B6E73727076756A65676665675B5074787A7772727977796D65787C837D727474737780787B7B7B786B736C6D6D6D73736C776D70706F766F79777675727176766E717872787575737A88817C7C7C7474737780787B7B01FEEA62070718A07375716D676F6D77786A6C6E70717B6F776F72756A716E6E6D696A65756F6A6D7472736562686D686A6F726E696B6E7072717E7162716D756E6C6F767168666C6C716670676C706D767370726B73737572786C7474717278857F737077736C65646D6D73776D7A727574777276797D816E6B6E7671696E7177736D6D717A6B6D696E706870676C77787C716B71757B736F6D72757675766C7167666B695B5A537679777A7D807874717672737D887F7F7F787877797B758079716A707373737970787A766A6F6E7673747D727772747472716F76737A7278827E7881837E81817F787877797B758001FEEB62070718B0707374676864726B6B6C6B696768717470746D6A68626E7370707177776F716E6A686C6D6E6D7669696C727776736B69646B6E6F71696D6A72757A75716F7675636A646C716E6A70817070776E71727A74786E7B7A6A71717D767170716C676E676E6B6C707478777A7A7570696F717C737473736F6F6A6571767269707478726A7372766775727A787B716E7170717E787579757878706B676D6865635A5E4A6A6D717A7371796E756F66707880807C7278766B747974726B6C7A717372717574766D76756E7B7872697A6B797B7570756E72707478757A747C777E7B7D7C8B7278766B7479747201FEEC62070718C0786F68766F6F6E706B6B73696C706C6666686B6C67656365706D6C6C716C6C686B6C686577706B7274676C73726F6D716D7070706971717578777271625F6A656863666B6B73707670776E73727178757671787C747571767783746E6E6A716D6D6D706C697075787E72787170777082706F6B6B73757365736D716F6974767073726F6D74757474797D686B6A77757C78756E767A797C776E6C6866666159517179787E787975717D6D6F6F7C797C7373767B727178717876797A777272706B72707C76716A726C79727A74786F71786F7470797A7D767570737E7C7C84807C73767B727178717801FEED62070718D0716F6B70756A6A6A756E666E66746C716B696B6C71736C7274676C6A6A6F6971717066666E736A666B696F757069726B706E72726C7770707571716C6B5F656E696D6D706974797780746C77726C72716B73787A7070706C77786D71777674686A696A75737571757177717A737B8484776E6668706B6D6F706973757879726F6E7068696C707D72787D787A6B626A73746F767D7B8479746D6D70625E5D5F4B777E7D777D76817B7E7E777770767C7B797B797574737172787670767D75737F707676716D73736D776E77736F767B6A6B71747B75756C757F7F807E79797B84797B79757473717201FEEE62070718E0766D6D685E6D7275776E71706A73686F726D6E6A6F646B69706B6E746F6B69716B6E736D6C676868686F6E756F7B71666F6F6F696D747274706F76796C6F62666B6C6E6C6B6E7276816F6D736B777874747F77766E70647177757E737B6B6D6B6869677569656E6F707C7E7A80767476716E6B68707478767B73716E7674726D727073746E75727173756F706D717F787472776F7C7D756F6A67616657555A4B7A7E867E7D81747976787584838581877A7778777C7774767977787A7F6E7376696A6E747374727D7A73817A76756D686C6C757B727672758077747B7879757E7A7778777C77747601FEEF62070718F06E6B616C656D6C6B6E6F6F6761626C6C687278726C6765666D6C74706E6C6E746C6A6D72796E756767626C717070726D696D746E6774776E776D696F6A6E716C6A6F6F6C75716B70716B6E746A6F6D796C71737F716F737A7F7C6E67766C6C6963677074787279737274797B757A767D6E6C76717A71706F6E736578797D6C676B73716E6E6E747F7878707C76756971777D797778726F6D6963666F635A5942767D787C6D676D6E766E716E7E7E838274767C737A70717B746C7474787573746F73707667726F6C777176726E73746F74736F73767A706C7F7879817E82838B74767C737A70717B01FEF062070718007C746E746F6F7A707A76786B6D7372747371706A6C6D6A6F766A71676D726C76676A6D6C716F6F7069656B787267716B6A666B6466716E746E73756F6E72746E69716A6F6E716C6D7673737277747179657776776C6D6A717879737674777369676E6974676E707C737670797577787A6D6D71736C6E716F78766C756F706F6F6572746D74707B7F7F80746F656972757B757876737478776A6C68686356564D717478736F796F7577716B7374858279796D767275747B7A7B867C75756E70726B706B6D717175707D7683746E6C6F7474737E7C777B7B7E7D7A7C807A84887F796D767275747B7A01FEF162070718106B6A6766656C6C686C5C5F6565716B706D69666E66746A6873716D6B7E76656A6869686A6C626B7072696973746B7178707C6A696A716E7777696E776C6E706D676E666F6E7B727678656E726A6C706F7E7975796D67727A777B7B7173706F6A696E71726A6B726E7676767471747E746E767973767374726E736F736B706E746C6E746E707379737C76786C71706C7678766F72797B78766B6B5D64645D5C4B7A7B786E6D7577756D6F766A7A8483858378807D7475807A7A7674756B66716F6A73696D6D706F75807579817E716F6E6D6B72717076707770787681827F84808378807D7475807A01FEF2620707182071786D6B6C6D6D71676B6B6566686E79706473686C6B69686C6C70766E696A6F7270716D736B6B68635C676C68716F75776B7469656D6C736C7375797B716D5C6B6D69746A746D7476776D6D6D6F787B7879737670707371797D73746E71716F6C6E69706A716E787A757B6F6F797F7B73736F786D706B7570696F747070696F6B7375706F6B6E74737A706D72707D7F77747479747273736F675F6E5A5959517A76777A737D80787A757772757A7A757D787D817374727D7C7B7770746E7170666A6F7171787473776C7D74777574747D6E71777075727C74717782867E7F857D787D817374727D01FEF362070718307561656B6D66716E69626A655E64756D686A686D6963656E686B7470757A6A66696B6F686F77736C6A686C706C6C6E736D6F716B687073756D6F7C73726E6C66646F6267706D6867776F7B736E78767B74757178756F73777F7B7175746A616D6F736E6E6A747676757F7D766F6B7476706C6F7574706C6C69726F737071797376706871716C7273797F7175716B7779807871777375746D66716F6C625D624B736F75797B827C807A7770787D7B837E787B7D777A7E727473777C7C76686B7475706D726D6E72767C6F787C71726D737475787A78776F7879727881837F7D85787B7D777A7E727401FEF4620707184079736D71636471756B646F6B65666E766C6B6A68726B69656C7475707170716C6569636B706C656467677478766C706F72706C73727168727370736E736E6C676D706A6B696F737675706970706C6C6E7278727C706F6B6F737B776A727371706B6F727D717372757B7779767377777F7A6B706C6A6C76737171717174767270766C6871756F73707B7D70736B697478766B6B7B70767679746D666468625B426F7471777C7772676C7574757E8077777977756D707779786A76706F77777279746C717172656F766E707A707C7473766B6F7077747F7D726F787C85787B7B807977756D7077797801FEF562070718507C767576717378747A726F716A64686D747C716E705F6B69776D7279776C6F7468686C716F6C6A67706D777B7A746671766C686D706A676A6E6B6C6D686B6E6F6766686F717273737B726F7275727872767476787A7673787D79786F706C6C746272717274766C737980747D6A6B75786E686F71777C757C787374717675726E6A6D66686D767D737574796E69736E75666A70757A76746D7069676961635B4D6D707879787A7F777C797576817C7A7A7575787B7D78797C736B6B6D726F7478717B72756F736A6A73727D7B7878706F7672777A797A6E737874777E7A817E857575787B7D78797C01FEF662070718606B636464656A706A64606364606C6D746F676F6E706E6F706E6674766F696B72646B6D7573696E66676A72726D727172696E6B77667473838171786F75676A6B626C637067706B7679706F737767726F717A69776C70717B7B78756F696A6670666A70726F7E6C76757B7479716F767F76676B6F7678736F6E817A787577736D7176746F6B6F7172748375706B6E7B7C766E6B73716F726D706E6A696960694E7A76727A787672747A75727078777A7B797C827A7D737679736D73716E71676F7878707176776F7176757C7E797068726E727D707678747780807D817D7E7C80797C827A7D73767901FEF762070718706E6C6B656B74736D726C6F69626B6A6D6C6F696C6C696D6A6C6D7B78767E6F6B686B686674666E706E6866686D6E6A71777573706D707074697375757269796D5F6D6E70676B6E7E7D777472746F7B706D717A726D6B73717C8172696F716E6C696E7272676B73727A7F7C81706F73727072757170676A707976746D787A6B70707671767375767175717879676C78787B7B7B7A6F7775686C6A6967675F574E76737370716E736B766D6274717B7D7D7E73746E786E717A797C6C686C6E6A6B7075757673747769736F7B7678716C746C747B74787A76767F757A80807D79817E73746E786E717A01FEF862070718807876716C666A71747F72696A616772736E666A6871666A6C7A72736F7376727769656D69726E6968636C757B6F6865696F6670626F776D6D6D71717679746C736D686D6D736D606C78796F736971736F75767D796F6F71787F7A78756B71666663696D72706B7377727974727470757370767175797E6F6F706B6B736F6F6E717769726F727472797674746F6F6F7C73777675837573707172686B6C6658584A797E81797A6B768A8B7276707B7E7674837479737F7C7B867F767076756B6D7A72706C6F6A6E6F74766E757B7774706F706E767D797D6F787370838A827E777A837479737F7C7B8601FEF9620707189074746F6D6572736C676D71736A6F6F6D6C6F76716E706C6C717473677D73726E6B6C6C6E72756D6B666D686E716B6F6E78706A6D6C6E727D6C6F68686C64676165736C7171736C6D777666746F79827D6C797673727370777F766F6E73706E6B6A706E74736C7875737C7A7C797471786C6A6D6A72706A72727073817A7771766A756C6B78707572767E776E6A6A697276757A6C7775776B6D7364656E6A594D7980777A7C7A80767F79757D7D7D777876777A797479767979737975796C6E706D6D7175736F736D736D757C76767670606A767A77776F70747984877E7B808276777A797479767901FEFA62070718A07974736E687479726F75686F626C6D7B706D736D695F67696A7474797A7573766F6C6F6F7467676B6A646968716D716D756E7573676F70766B6E71726A70726B6A696B74726A6F787B72746E6F747D6E6F6E7976706F6F797B80746A6D6D696E6D6C6D6A7273727A7A7E7777707E77857C6C6D7372656B6A716F7870797079747173696D7272717C7475746F71727A747778727672787D6C6D6D64706158584B6C716D7572687269756B6B736E747A767A746E6F727775777C776D7A746C606A6C757775767273717F6C7C7A747068716A6A70777E7C796D77797489817F7E857A746E6F7277757701FEFB62070718B0686F6C6B606964636D68736876686966646E656C6E6A6D73706C6D6B7374746F6F6D69686E6D72666A6D6B736E696D696C7772746F777272766F73716F726E6B68756B686B736C7179737774726A726D6B717780726B6E6F7378756C6F6968686769687B776E787A7776726D707478756F67696F7477727375706F6F78777B7168726C6B6E726F78717A7C73706E7674727474777676797B6F6C6F66665F5C4C7472677276706F7871756E737479788083747373796F7079797171727976716E6C6B69767A746E747579807870706C757573717A76746E6F7C7879857C7C7D7F83747373796F707901FEFC62070718C075706D756F7375757C62646C696465676E726D766F727376686D726C6B6D6E72726E73707266696A616574706C7578747674696F6B706A75736A756A73706A6B6D6A5D676E7B71767974786F746B766C736E7272636F6B717B7C7677706F6F6963696D78656970727E77817E728179797167716F6D7277706F7171726F6B6C6F6B6E777473706E75777B74736F7579767D726D6A6F717C706C68696F61625B487B7A7C867B797B6F6F736F6E7D837A837C7F7D787B75767578786F707A716A72737674787175736E74707878766F6F6E7C7071726F73757A7B837C7E7D747D8B7C7F7D787B75767501FEFD62070718D07870677067666C6D706876716265726D656B716C6B696C6869656C76766E6A72746B6E6B716569706A6670766E6C74777171766C6775727A7A6F75726D6B67716D6B64686874756E6F6F7071726D7676767A7F85716A7173727C766D75676F726367687475767E787D7A737271747C8173686A6A6C70706F71676A7075716D736D73686D7773737A767D7B746E6D687275736C7275797E776F606770635E5C516D747A7573727A7475776D68777D778080797A707F817A7B7B79706B7277757977786F76768178727A7271787272727272716C717273777D7B74747F7C85828780797A707F817A7B01FEFE62070718E0796E66696A6E6E706A706D71676F776F72727468655D60736C6E73727A7171706D6D6E6A6E68636D706C6E7770757171757169696A6D6D72706E746D7368696C6C68696F70776E7A756E727171636F686D75737C746D727E82807A7575706F6B6A706E6F6F727071707570716F75717A77716F6D706E716C7075697578727477706E757D80726F6C727E726C746F7A7775747177737771686D726A6C5B595D4A6F737574706E70757B746A6D7A847E7F7C747D707B7F7571746D6F73746F6F6F6F676B717373737A7977837775706C74716576787679706F74777C7F788182827C747D707B7F757101FEFF62070718F0797672736D706B76776F626A6B7170776C6D72726B606B6C756A6D6F6D726E72736E776A6A67706D6A656E72686B767A7774746E696D738279717173726D6B6C6C7A676466766B686E6E72757471796D737D78816E676A76777B6B726F6E686465727076766A7A74727478716D6C7479716E707973716E7870707C75787370756F68706F6B6D7B79717A76736A7073797671757078767B72666B6C676358584D697070737477707378706F6C7C7C7A7E816E7C727378777C7E797475756A6E7176716D716A6B6D66707376777C7575777B7775727B747E75807B777A83827B86816E7C727378777C01FE0063070718007878767774736E7679707277737577717669667369636B6B6F767C717B6E6768646573796E6C6866646763767177716E6D6F6F66636B75786C727B767270676866696368656E6B717D77797878717674747577766D6B737A7B80767875686C6D68697174736C737A7B796F75747677786E6B6F757A77717172737074767374706874686E6E717C7B7D7D75766A6A77756A78756F70717A7F74665F63605C5A486F747B7976777475737073847D7F8180767A7F757179756C7576667473716F7B6873626B766F787A7D7078776F6A7176797E7F7D6F777477797B78837B857C79767A7F757179756C01FE01630707181075766D786A68717676746C6B6B756D796B746A756C6E72676F6E7B756C726D756E736D6E76776A665D66716F6B6A717375737062706A74706D6D7975746B7275686B6B6A68666B707A71726E7C756E767879707A76777478827A7575747571695F64687874767770797470746F777A7C716D676B6E70746A696E6F6D717971716B78757479697270747376736B77767B7269787B7E7B7772686B6265625F5B4D6A706F776A706D66717271686E7585797776797175746D7177757579777068706E73737474736D6C6B6A7E7775727672706F6E75777B7B757A808081767C81827776797175746D7101FE0263070718207468657065676F6E6E71646D656C6F70757877696862686F6E6D7472746F6B6D6B6C6E667B76736E6F686D756A71706E71686869726D6D6F747370786C69666E726A6F6B7772766E787C6C6C6E6976726873767B757075777B7B77757B6E726D66746C666863787A737672766C7675726C666A6D6F73797173786B70747A77716E6A656A676D74767A7A6E76746F707A7876706C767471776D716B676060594E6A717E6F79757C7B717574737F7B72747E757A77777978787174747C776F6B74776E707571727273726C7573756D717175727679777D7A797379777C7A7A818A7E757A777779787801FE0363070718307C7773706F6E746F7B726F736C6E736F746A716A6C69686B6D746C6F766C6C727669686C6B686464686D687271756C6A6B77736C6E6D73717077776B6C6B6D676C6D706A6E726E787C77756F686473756F777475726F797F7877766C6E6C6E6C706B727270676E6D6B7576737574757779736E6E716E716E6F78747A75766B7277736A6C6D6D757E79776A74707077737E78736D6A77766F686766696157644675777878737773766E7871727D7E7E7874707174737B6F75727B7774767076766E706D7972746C7373787E706B71746F68736876787473787B7C7E8B7B7E7D7C74707174737B6F7501FE0463070718407D6A647068696F6B7264656A606A757B7571686870676A656E686B6E7774787A6F746C6D6E6C68656A6166757667686E70736D756D7B78736E6D6C7478696E6C6F73676864686B77826E6E71787078737179777A6E6E6E7A7D756B687E7374706C75686D68686D74716E7C797E747A76756A75777976706C6D6F726D767E786C6D63696C6D726F7A7D7170717070727F78747B776B757274646D726F645E5E586E7078797873726874746B777C757F7479788675746D736D727570736E6F747B746E7C7271717570746E74747071767A7174717378786F767E7E7C7B7B7D7E7F79788675746D736D01FE05630707185078786B6D656C746F64646969676E6A6B6A736D6A616764687170756B7771676C6976706A6D66686F64686C7070766D7A6D72636871686D6E706C756F736E766F6C6A6568726E6A6F7C75716E6E6C7A787678757A6A707178757B6C76726F6D6C676F66696A71798179707479797880816E61716F696F6F716E74727C727C75716F676A6F72657675747A7874736D727777717A7972767460696F615F605F6049747C797C757578777267676C75767C7B7077807A807477757C7578757571706D717D746B72747A7D796D7B73746F7170696D787877777078757E7D7E7D7A79807077807A8074777501FE0663070718607878726B7470706A747373746A6F6F736A72706A69746C68716B716E767572776E6E6D71706C72666366696D6F6D646B7071756F6F6F6D6F726971727670756F6B756D6E71746F71736A737072707175707271797976716F7A7D7273776B6D69666A6E766A71706F8181726D6E6E76776F686E6C6E76716F7575716B7073746E727573747D71727273766F6C6F777874796F73767679816E78696165626058516778767C71716F6D736F707879797F78807A80757472747D73757175726F767F7779646C6C6C6D6E726E78787A7070726D70727678737772737B7F817779798A807A80757472747D01FE076307071870786F6E6D70716B6E7364716B707371796B6F6F69686A766F716E6C6E76756B74686A68706E6C6466766B717272676F706F6E716B716E7D7E6F6C747167686969667373737074677073706B6D706D726D7173747F72756F7984776F72747071726F7167736E6E6C717078787877756F7A6A6B6E766C727B6F6E72766F70746A6A716D7A7776716E6E727E7876696F6B7671726E737D787D7777676A68575C5749737377747C74756D6B6866747B767B7E73767D7B737A777179716E717372757B6D6C726E6E727373756C77807D7A6D737A6E6F7570736D7271787E808580878A73767D7B737A777101FE0863070718807D716D6D67686E696F71737372716B6A696D6B6E6D6D6371726C777C716E7675696B66676C6D6F67696A6B6E6F676F70706B73706B6B68757570776E766D6F707071646C68666D717F776B7175757A6F6E756D70676D6F7E7F767F706D656C6D66746D726E6F6C6E79817F7676737F7A786D7079797A6B70736D7C797674707171716F75716E6E71707A78706C716B7074717670756F73736C696B6F686055477173787174736E6F7F796F71777B81717B7B7D70747573726C6E7072817874737171717475727371736D77767075717571746E76727474737B80867E7C8180887B7B7D707475737201FE096307071890766D697071717474746D6F6F6B666C6A6A6D746E6E706E7273766D756F6D707467686067696C6A666D6E747672706A6A717271686C6D6F736D72707179686E6D686A74786C7976766F6E6D716F7380766C7576766C7868757B7A76756765736C706A6F696F6B79807A7777776E72736F776A736B727272716C6D6C7D787B6D6E6D6773637A6A6C6A7271727570767D83837073757A7B7A70776B69676563564C716F756D726F727278706D6F7A82787E796C717D817877757179717979796A746F6C70736C70706D796E7873716F6D6C707C7377757B6F737B767E8483758283796C717D8178777501FE0A63070718A06F6E6A69656A6C68776863646F71766B6A7074646564666F716C6C727B7E77716A6B626C7164666769676C71686A626E6C6E67726A75776F7B737A7775676A6C676969696A7476757A767973706D7771727778736C7977767C7A7470746867716D716E706D70756F78797874737E797C7264756E6C6B727770756F7072787478677075716F7472747A7A75776D6B7B777B75707271707A756C67666561535A476F7976787376766F776A6E687B7A7B787E7878757A776D76736A666E777472777371756F6B6A6E7577737772766F72687378767B7177737070737B7D7F817F7E7E7878757A776D7601FE0B63070718B07F7A6D74747A837E7B7378786F76726E68717068676366726D686D717379706E696B616E6E7068616764716F6C6F6F7673727075737D6F73766E71687476716D6B6D6A666B7171777E766F6C6F687D716F7971776D6F7A7478746D7174776B6C6C6F6D7672746C6878807B746D77787E74677175706E736E7373766E7371736D6F716A706D6E7C747474777E71746F7D747672787E76726F7962656B6B5A5A44757A80817E7477767974747778797A7976767A797B81797B7770726E7376716B6C7372757A72797376746F73787371666A6F737D77797380777A8184837F827C76767A797B81797B01FE0C63070718C0777373706C6C736F6E696B6C6B6E7A786F6A6D6D6A666772767372766D656969656D6C6A746C7279736D70727676666C6D7971766D6669726F75766F6567706A666F636D6C7367756D7577716C6B76776A7F747B6E796C747C787A6E75746A68636E67706B6D6C77787A6F7179827A8375666B726C76736D7472716A747E756B706F706D6C7168787A807376726F76787773717B797D777874656A696A605A486D736A6D72727269717D7A6F847D827B817E767D8178747B7A6E6E707674706D6C73747C73716D6C6D6F767271726C6E70767876747175768279767B7E807A80817E767D8178747B01FE0D63070718D06C6B6E64646D6B6E7466676C676A69736D68736D6C7175746E727077706E6F6F716F6E6F7066696C67726A726E6B686A6E6E76736C736B7465737374706A6F6A77796B716D6D686B786D64726D70777875757677756E68707D7D7D7672797169666F6C73666B70746F737B817A80797D776F6E72716F626377677174716D6A6F7170676D6F706F71727676716F74767A7171777A716D73706C696068635A574E7571717C787C72737F7275777F747E8079787B797C7A76757775706B79757474746B6772767973767B6F7C746D707178777073737274767878797A817A79808279787B797C7A767501FE0E63070718E0756873756B746C7A6F6F6C6C6674787578676667685D686C6F6D6A747771696A6B6973746E6B6E6B6E5D6F6C6F6C6D6E6C7A7073757176746D7679786B6A6B6C736C68706B766A6F887F73716F6672736F7470786C717775877C786B686D7469696F6A706E7173757A796D78747780756F686D7175706D6A6E746D747575786F6A726D6F686E7B74787D78766F6D7676756F71717975746C6D6A6365635B584877777C757C7A7E7B82746F757C8084858077797577787070767A756C726F6D71666B6C7077707B727A717678766B706D757273727076787B817C828379788184807779757778707001FE0F63070718F080736B77687673796C6F6E6B646C716A6E706E70746E726F716E727D7C706F6D6D69686A6A686A686466797B6C676D6B706A67746D756B7E75757469726B7064687164706D706C7775747A6D716D7D796B7573786E6D6E758582736D757171706E6D6F7668716E77717C77736776797C726E68706E777A6E6B6F706E717571786E6F6F6E76796C717181766E6671737B6C6C6676737E79726B6C6C6E625A5E4B73767A746B6C70727B6F73706F7874736D7584767678756E736F7574737169746F7375726C6D757674757270736E6E706E737B81727B717A7C7A7F81858786826D7584767678756E01FE106307071800736F6764666C6E6D69616B6E636C746E71706A6D676B736D76676C6D6D766C706A686D6D6963696A696D7A7B79746E6D6C6667746F6E6C6B73717070756D6569656A73736E7574757D7078716C6B7677748071716F6D6E7C82796F70716E6B72716F70736B6C6B6E7A79747476737C7B756E7773716F6E6771716A6F6D6C7572696A747276777678747D706F71757C787A7271757F827A79727260656866594F727471776E6E6D76776C7771767E767777707C7B777971776F6B7271727671766B6E707677737B7A726C7870727375736C7F797A777874767A777C847C79828177707C7B7779717701FE1163070718107E6D707678747B7B74656B676368777369726B6D6B6F71726B7471706F73706C6F66696B72706C6867706C7A70696D6E726E667170777F7F6F6B6B6C6C6E6A73716A696A67696D747673737A7571746C707A7370726A7381837B7871726E716D6769687072797573717C7C82748078777C756F6B6D6E69676A6D62706572786D686C717274776C6A7977767375737A7D76727179737578746F6D67656457514B746D79737778787773776D707E7D797273707673777771727A7572706E6C6F776F786E71737577767973737977736D746D7171777977737B887C747D7D7D7F88737076737777717201FE1263070718207470686967757772766A7263696E70736F6C6A6B6E716F6771716E717B6E697070676E716C6A6F756568706B6B626D70766E6F716F6E7675716F776667656D756B6E697567716B7576727E79776B7177696E75766A696A75717D716A6F736E716A686D75766F7774797C7C786F7576736664717A78757377746C74736F777A726E70756F77717178747F7473686F6A7479706D6D717A766B6F67676C655C5C407B7F8282807B7B74797468767A807B7B8278787779767374716F7372766E6B706B6F71737272737A796D797A7776767471717676707075787E7D7B7A7F838082827878777976737401FE1363070718307A76686F6C736E797B726F68696E73706F736E6C616770656C6F6D706F717175756865706B696A6C656D6576706D706D666D68736F776D7C736D756F726C6E6B6D7371706F7C70797A726E756B73706D72767877716870717A7E776F766A64696C6E6C747372747A7B7C7776716F79837C70726F777369686C6C6D756F726B72706B6D686E6F7A867874746C696E787C78707476706E74756B676D655E645C486B727C79737171736F81737476807E7E7F747A737482757C786D6F6773746C77737070747979776E7E6E7F7676756B6D666C7576777A7574787B80827C7879837F747A737482757C01FE1463070718407B73757669746E7371736D706669707A6E6A736A716F777374777079757671706B6861646D6B6B68686A6471706B68686F766F636C7371776B7078736C66716B686A696C7174757178716B746A67706D7A75767D746874737E7D827978736667666B6B786F7078727B737B6E6D7572786C68786E736F6A686E6C716C737D787B76756A6C706E707973727170746B757A7A7370747A7873777277696E5C635A5174747C7E656C6F7777726D7481807D757D766E7C7E7A787D7D7369696B7172767472736A6C72707875757C717C7172706B716F73797F6D767D8082867979777B7D766E7C7E7A787D01FE1563070718507A73696C5D636F696F696970647066716C6768706E6868746C6C6871786F7077696C706B686D6C6B66686E6667706E76776B6D6D696B676D74777672716D6D707A726966646E6F6D7A7E7B7477787B6E6E7476796E6D6E7A8475767977686C726D70637074617071786E787A7B7A7A726E6E6E72716E686269697775766F6F6C6A6F716870736D767A7A79716B6E777771787D8078737B726E60676D635B57496D6C71797671747D716D6A747E82847778737973787D79777670736D6A6872716D736E7471757973796D7470766D6B6F766D747A777B76757B7D82847D817B7E78737973787D797701FE1663070718606A71656467606B6D736F6C6062666C746E6C6B6673716E786D787471736E6C716B676C6B70686E626569717671736E6A6C696D686C716F7770746D7B7173686B6B726C6E6A686F687576676C777D77736B72707978656D70847779726E786E75636A69766F76756E7776787B73758480706B726B7270706D6A74726D6C717374707B7178797A747A7875716C716570747A797C7E7D7273726E716663645B514772757473766E7C7D7C6E66747F80807F7C7F73767678787573757470726B746D6D6B676D72747870746F7E7D736E6F6B746E757C75797B7E7A6F7385807C828C7C7F73767678787501FE1763070718706B7070726B6D6C7975666C656E70727D76726A6C666F72797470666D6F6E69686B6D746E6964626872676B74786A72797573686D636E6B727175726E77747971657060676470786C7A726F6F707A7672696D6D827A78727375787173786E686B686F6E76756E70727C77787A6F767976736670707A7373716B6A75717874786C67696A6B707870707979727667767879807A7C777676776E6E6466695E585D52726C716F70706B707B6C6D747B7F7C797776716B7A7C79797D73736F746C727571757077757077767F777774726F726B766D7175777B7470727B7A877F817F847776716B7A7C797901FE186307071880746E6F62667276727F6E676F6873737675726767716C696E736B7073776F736B6C6F6C6F6E6A65676E676B727473756F6B6E616C6E716C776D6F806B7B666C6E696A63696A7D767C7370776F6F637B6C70766F7577787271817F797070706A68656E6A756B767477787E76766E76737C73717478757074707172706E71796F6E61726D707165726D727A827A6F737779797B7A6F737B79726C6C6C696668644F67766C7473787A6D716C7372817D7B7171747675756E6B71787B7679787672776F75747A786C736B7376757671716F6C7274787D7675707A817B80807880828471747675756E6B7101FE196307071890666C616C6A626F716C606F675E6665706F6E6B69686F786A6268727074726D6C6B6D68676F686C636A607479766E6B6D6F6A6B6E6B716D72726F7974766D66605F6C69656D727C747877766D746F797F747B707C7871736F757A7A726E6F666F656B6C686D71777B7D777A74697171756A6D6E7B747072717169737273767077697671767974797369757073707176786D726F7571716D6F72706E67635D564D70797A7E7970726A7574726F7D7D72787A7879707C766C7876717072736A6B76727A7071716D6F6B76707C716F71746F677978757C7875797B757D817B807B817A7879707C766C7801FE1A63070718A071726D726C71716970736E78666B63706C6E716C6E6A6D66666F717770786E6C6B6F7064716F68676C6E71776C66636A6D756F70686C676D75737D7D726C666A72726B6A7277746E7670757B6D737C7471786F75746F717D817C76686E6D6B6A6E666A737170747F7F7F81737270747C6C62626D6A6E7C727474716C706F68766E776D6F767673727F777575727276767676766D7778766D695A63696464624A767D847E757674767D75756F75787D7E817E787C7E807C757978757A76726B74686A676C6E6A6D6C78717E757473807B757174756E727370777B7B818381817D817E787C7E807C7501FE1B63070718B076716A7279717174776A686E6B6B6F74676F6E727363646D696F6B72726B70746B6F6C6A74716B6D6D606A7878756C706A7271727072746F6E71707072766F70656B6B686B6E6C75706B6C6D706C77756A736979726F626D7B807B75756F6E6B6D6C6B746B767075777B7B796E76797D7370686C78757769747268716B6C6F706F716B737874747C79767C756C6C7A8575767A7A72786C6A67696B5F65605B4B717F76787073737376697278777A7C7B737275777876727676787575766D717C71756C6B6774746E74747976797374686A6B6E79747D76717A7E787F83897F7F737275777876727601FE1C63070718C07B786D706864696B706B706D676C726F6F646A736B72746B727D727471706B77736966656D716C766B6B6C74756E6971726F6F696A6B6E6A6E7970776A726E6C5A68686F6B7379717574736E73727672757875787672717C7C8177757063696E5F66716B6B707D7F75767C746F70717B71757370716B6F776E7E6E726C6374786B6F6F747D6C6D73728178796F6D74747771727C7B736C706F70716D60615F4D717076777B7D76797D706B6F727B80777F768276777E6E737E72696B656F6F75787B787375706F6B736A737577696D6D6E70727A7B706C6F73797E83817C82857F768276777E6E7301FE1D63070718D06E6F6B6C6870716A695D6464656D6E777B6A6C6C6F6B6C6C6C6D6D716D6F6E6E6C6D706B6C646D70646B6C73726F6D7A78766F66686B6B7872777075686C6F6A6E6E6A676978717377726F7674767479797A767B717570717D7579786A6C74685F6D676F69707175777A7A797B707D766C6E72707A7A70696B68666B6E75796E6B6F646A706F7076817F76706F6F78756A716E7B797F756C6C686968675E5D4C77887C71757A7375757C777D797A817E80807B717376757776736F767A746D7673746F76737576767678776E6F6F6D747B69737575776F6E7E787A7D8485858380807B717376757701FE1E63070718E07071616E69687A71716B6F69666568706C716B6E6E6A6B6B746E6A75707373716B6966696A6D6D607070706F746D6D6E7374776F6A6D70716D6E72716D656B6B72737074777C6A736D6D73747077737A6E6F73756C6A6A7374806C7273726C75696F70726F7476706E7D75796D77787B776E6B6E7676767377766C7171707076687171706A706D7A70706767686C7F757977808172726A6D676C5D656A635948717477757973807A76796F7876817B787A757E80797873787A726F73767675706D6E7374706D7076726977797C71716E696E7B7A76777178817A7886797174817A757E807978737801FE1F63070718F082716A6B71786A6F726D6C686B716D6E6A73726A776F6D6E6E7B6C6D75726B6864646B676F716E6066696671767772757275726C716C697171726D6E69696D6A6D726A6F6F6C6B72716E7876706F75766D7976796E6A6E7678817770717970756D736C71706A6E756F7173757371787B72677273736E796B6C746D7075756D737071646A6B7D7C7E797C706A6F6D7679817B777F737A736C6869696C6C5F6049737E728472727572736C7279767978857C7979787E786B7375796A74736E6D7479796A696E767973776F7B7476726E6D696F757A777C6F717E7F777D787C7E887C7979787E786B7301FE2063070718006D6A6A736E6C6A71736A6866646B656E72716D6F6C696B696C6C73727271726E69656C6E7F736F70676A70746E6D746B75726F6C6E6F6E6E687176797A656D6B776F706F6D746D6F7473736B6A706F6979717176717871797D7F726C6D726C686F70747275717770807C6E786F6D787F7D6F6E756F6F6B6573726E7072727D7071676B6F74797C77737672766F7275746C7471716D7D82736B6A6D6A61555D4B7B7E817A7F82837776776C7683837477797A81787B7C7878787A747C7772707A7171747174787A7172707D7C6D7073756B6C7373777D76727A7E7880817B747F797A81787B7C787801FE216307071810796E75777673737672706D6F6871766D6F6B6A616B6C6E6F6D6E6F7F73726A6A7269746D716D6A6E686B6B71756D687172666E6760666C7172717A7D736E736B706F6C6E6D6E6A797C7376727176756C7B73767C6E676B797A7B746F79716C6A6D5E6F63676D717E7573727875747B84736F716D766665707373717C75716E766E6A70777372767270797971696C706F747377797171766E6C6F6667645F594B6B6C676D666A6F6C79706D6D75787977746B777E7B7978747E74746D6D6D7172736B6D6F6D6D6F76777473786E74757B7473717B747A746D7D7A798482817E7E746B777E7B79787401FE2263070718207A726E6F6568646F7674716269706E7272676266696F6E6E6A716D6E6B726775716A696C69726F6967626C736F796C73736F6C6A6B7177706D757777726663706B6E6E716F776D6F776E736E686777707773787F716F7173838478646D6978726270646F6E6C75766A707173767477807376706F7271706E71706971757674777375726F6E6B6F717A79746E656C716F7A76776D7C83786E69676C6E675D5D4A7782827F74696E6F706F7C7E7880807F7D7B7D7271786D76777177727673757A6D75706F74746C6B7D6F79777A6A69716D666D776D757073747F777F757C827D7D7B7D7271786D7601FE23630707183077716F75676F6B716E75707168636C696760716B726E6E6D6771696D6B7169706A6B676971636C616B6967636E676B6F6E6D6E6E656C75717775767A6D726E6F6D716D6D6975687175726D6A73767F767272797F76706C707E78706D716C6D696872768070666F6D7D7B78757A6F777D7169676A6D716F7276756E6F69676B69717472707277757A7E85797376707876767C7A7A707976766F696B645D4F594472727A70736B706D77716F6F72757C7E7C7577787A736D7A767075787C73717574757575677470727768757572786E6C6B6B6A76797A74797E74757A7E8282847C7577787A736D7A01FE24630707184071656A686F676B6C7777747167736C716B6D6C64636B6C6C746A6B757B6E75716668706E766D706E646B676F71686E6F746D7A6D67706E71707477766A676B7169676D6C7077706E81717476716F7570736E6D797463697C7F7F787681756B6A656E6E756C6B77797C77797A6E7777726E6D737B73706B6D6A73717370766F716B727174737279727672776F757079717470736D697276736F6A696B62665C5077797D857E7C7D747A787A7B80817D7977777D807D7A757D7A7A747279716D76716C6B6C72756F74756C7B7C7B6D71726F727580877570797D7A7C7F73827B7E77777D807D7A757D01FE256307071850736F7068636968656C73716F676966726D736B6A6C68706B736E72736F7366696567676C727173736D6B6C6F6D68676C717B77736D716F6966766B7273696B6B6D6C67676E7B7373786B6D6D717176786C736C7675756F78807C6D686D6B6B6D6C696F6C78726B72727576817478727C7670736F7073766F6F7574716B6E71776E716A7274687677827B736B686E76777671757275746F6A6C6D66626260634A737479777C70797170726A6E7C83827B7B7879787A817C7A78727170767576727178707A797774777C737E7374677469696968696E7B75707A7D7A7A7D7980857B7879787A817C7A01FE2663070718606B78797269707A7A7169676B6F716D67766C686B6B6C706C6B79776B6E7276726A637465756E6D677269616A6B666C706B6F69747176716F75737970716A686A646B6C6D69746C777D7272706D7270737879797071726C7581837472767170706A6C6A6C6B6B747975807E7C7076787E746D767173706C6A726967756A73716E6C7071716E706B72737172736A70756C6E767776767C766C6D68636464615F466E777F82817D7673756E7474757B8085817C77756F7C767A71716E706E70706E6B74737770777875796D76726C68707771767674737372707A7386827C81777E817C77756F7C767A01FE2763070718707A696F70737779727471726E676866726C6A68656469696F6C7274747773736D676B6E69707271727A6E73766B676F6B716E716B676D657770747771776A686570746C72646F6466796D736F737374726B707370686974757B7F827476776E7167696F7C7A766C7570747C7C7F777B7D686C6F69696C727074747D767A787170726D67706A6D7476777E75717175787A73747B7A78726D697163626B655F5C50716A7B70796E76696E7471767876777A7E7E807A7C78767478777478766C6D757675696F78727374747177767E706E6E777370786F6F71797C7D7D817C807D857E7E807A7C78767401FE286307071880787C746769747B7071766E6A6E7166716D6766636A746D6D6C757C75716F6D6B677173686C6C73676371717C6F7571707070736C69686B716C6F7C6F6F6B6D6D6F6B6A6F706669747C70706F707375716E737B76706F7B717A7E7574707A67666A6B6875757C6972727279757A7579777576717578806A686E70727477706F757474776F76716B707A7074767271736F736F71776E746C776F6B6470685F644E787C7A7D7E77787C7A74727A7D7580827E747E7B7979757C7C6F6E73726D757C6F6A726B72767274776D746E726E74757C776D7673797679808481837D80878A7E747E7B7979757C01FE2963070718907F7F797A6E70787A7F7D7677747573716463736C70726F746E7475717C6F71666A636E6C6F6D6D6B6D686D6B6F6A6C6A746D697071777A706979716C65666F6671786772716B646E74777D7C6A6B7D7370726B716D697A71767A786E6C6B6A65666D6971686D6F776D7F887971727A7F6F6C6F686C7475777378727776787D7670717577746F737A7778706D6D73726C767E747376757B766E67636A6660574875757E7976777C7B74746C737D7876707C74817976736D6D7B737271746E716F7679776F757076796E717B706F6C6D736F696F736D7B74837C7585807A8081877C74817976736D6D01FE2A63070718A0746F73786C6E736F706D65706C706B7467686E6C6A6A6E6E6E71726E706A6D6E6C6B6C6B716E7065656663677574686E717A716A6B7471716D74767870756F666C696F6B6D74787679727A706C6A7571737277766D7275797E797D7976695F6666636A7676716D707D73787B777F7F786A6E6E6E7576726D71716D7072716D69647670706C6B7B837B7F7473696874747970767A737477746F665F605F51584D727B7D81837F7871726F76767C827A7F777779747874736E7476747276786A70747370697770706A726E6F767A7B78736F7376777672777B7F7C7D837C81817B777779747874736E01FE2B63070718B0737470706972747D7B6B6868686F6E6D736A707A706C706A68746A6D776C736E6A616D6B69666E6969656A7870686C717574756E686F6D77787372706A686D6C746D6B6D6F7670746F7171787170726F6D726C7978726E717A7F726E6D6F6B6D6F6A716D7274776872787B7471776C736E676D73727A77857A706D6D76747973766E72757474706F757774746E6C70697C73737772726C706C786D656E645A436F767672797474726B6E71757B7880827D707777747B7A77746C6C75786D696D73696A6E74827672766E797B7772746F6869717B7176737E807A7D80857D76837D707777747B7A7701FE2C63070718C07A70706E6A646F7279716C6764636673716F68696B706964686F6B7776726C7B73757771696A6E6B67666C716966666E676E777063646F73777274717370716F6F7E6A706E706C6E6E707472726F71757673747A736868727683796A72666866696C6C6F7970737674847B766E76756D736B67656E716F6D7971708070757073736D6F6C7677727474797C7C756D767A756F6D6D7A747B736A6A676463605C537B797C816F7D797D7E786D7A89758583847A78747D7A77817973727071696E707172757379736E7D727F78787C6F707075736E717D73746C72797C827F797F80847A78747D7A778101FE2D63070718D07C7E6D72696F72706F72716F67606C746D786F75736F74706970766F77796C706F6B61686668696867686F6E777173727974616F77717579767876726F656967606B6A6E6C7573787A7373737576756B6B6D74786C756E7883857A6A737164656671676E70726D73746F7375737573786E6F7575707A707A726F6D76777670727673777271697072747D6E6E6B6A77797D726F73716772756B6A666162615D4869787D736F75756F6B67677676786E71767879707C6E737177737878797576736D726E767674767075737B766C67716A6D7370757D746A7B7F74757F7F778081767879707C6E737101FE2E63070718E06D656562606C6E706B676A66696E726B6F636D696B6964676E706D786F7376746B676B6B6B6E666B6767796A6E676A7070726C6E6D6C717A7E737073706C6B6D696F6C6E676865727B6C6A6D6F75796F707972766F727569737C757173716D68636A676D6F707D727880787E7272767E7368706E7270756C75706E71807B72777D786F6C7065737B737972767272747379717C7571786F6C6E6668656A605A52767076757874706E6D6F6E778A7F7A77736F6D767B7B6E777477726E71777E6B707272696B776B777D6E7778776F6D757574716F747A75767B7E7C807B7C7D7B736F6D767B7B6E7701FE2F63070718F07673646E666675726F676963606C676E7670716E6C7173707A73716F766E687267646363636466666B646D726F726D716F6C77706B767A79747077726F756B6C6D6A637177786F687E7377747772787A71756D72656B6D737B807472796C666A696A6C706D6E6E72717A767376737775716D726F6A6F6D6B6C6F6A7074706C6E6C6873737473737676787B726C6D6977757478837E7C7C73706F62605D595B506A706371706A6A6966666B6F6F76757473757579786F7073747C716B6B6F666C73756D797A6E6F6771737B707F6E6D6B72726E747779747380787F7C787B808573757579786F7073 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 2368 2 0 0000 diff --git a/tests/vfs5011/capture.png b/tests/vfs5011/capture.png new file mode 100644 index 00000000..c33f01a7 Binary files /dev/null and b/tests/vfs5011/capture.png differ diff --git a/tests/vfs5011/device b/tests/vfs5011/device new file mode 100644 index 00000000..4c75e596 --- /dev/null +++ b/tests/vfs5011/device @@ -0,0 +1,80 @@ +P: /devices/pci0000:00/0000:00:14.0/usb2/2-6 +N: bus/usb/002/017=12011001FF11FF088A13170078000000010109022E00010100A0320904000004FF00000007050102400000070581024000000705820240000007058303080004 +E: DEVNAME=/dev/bus/usb/002/017 +E: DEVTYPE=usb_device +E: DRIVER=usb +E: PRODUCT=138a/17/78 +E: TYPE=255/17/255 +E: BUSNUM=002 +E: DEVNUM=017 +E: MAJOR=189 +E: MINOR=144 +E: SUBSYSTEM=usb +E: ID_VENDOR=138a +E: ID_VENDOR_ENC=138a +E: ID_VENDOR_ID=138a +E: ID_MODEL=0017 +E: ID_MODEL_ENC=0017 +E: ID_MODEL_ID=0017 +E: ID_REVISION=0078 +E: ID_SERIAL=138a_0017_6c3b5712a6c0 +E: ID_SERIAL_SHORT=6c3b5712a6c0 +E: ID_BUS=usb +E: ID_USB_INTERFACES=:ff0000: +E: ID_VENDOR_FROM_DATABASE=Validity Sensors, Inc. +E: ID_MODEL_FROM_DATABASE=VFS 5011 fingerprint sensor +A: authorized=1 +A: avoid_reset_quirk=0 +A: bConfigurationValue=1 +A: bDeviceClass=ff +A: bDeviceProtocol=ff +A: bDeviceSubClass=11 +A: bMaxPacketSize0=8 +A: bMaxPower=100mA +A: bNumConfigurations=1 +A: bNumInterfaces= 1 +A: bcdDevice=0078 +A: bmAttributes=a0 +A: busnum=2 +A: configuration= +H: descriptors=12011001FF11FF088A13170078000000010109022E00010100A0320904000004FF00000007050102400000070581024000000705820240000007058303080004 +A: dev=189:144 +A: devnum=17 +A: devpath=6 +L: driver=../../../../../bus/usb/drivers/usb +A: idProduct=0017 +A: idVendor=138a +A: ltm_capable=no +A: maxchild=0 +L: port=../2-0:1.0/usb2-port6 +A: power/active_duration=624952 +A: power/async=enabled +A: power/autosuspend=2 +A: power/autosuspend_delay_ms=2000 +A: power/connected_duration=624952 +A: power/control=on +A: power/level=on +A: power/persist=1 +A: power/runtime_active_kids=0 +A: power/runtime_active_time=624676 +A: power/runtime_enabled=forbidden +A: power/runtime_status=active +A: power/runtime_suspended_time=0 +A: power/runtime_usage=1 +A: power/wakeup=disabled +A: power/wakeup_abort_count= +A: power/wakeup_active= +A: power/wakeup_active_count= +A: power/wakeup_count= +A: power/wakeup_expire_count= +A: power/wakeup_last_time_ms= +A: power/wakeup_max_time_ms= +A: power/wakeup_total_time_ms= +A: quirks=0x0 +A: removable=fixed +A: rx_lanes=1 +A: serial=6c3b5712a6c0 +A: speed=12 +A: tx_lanes=1 +A: urbnum=7 +A: version= 1.10 diff --git a/tests/virtual-image.py b/tests/virtual-image.py new file mode 100755 index 00000000..a9fe8f5e --- /dev/null +++ b/tests/virtual-image.py @@ -0,0 +1,280 @@ +#!/usr/bin/env python3 + + +import gi +gi.require_version('FPrint', '2.0') +from gi.repository import FPrint, GLib, Gio + +import os +import sys +import unittest +import socket +import struct +import shutil +import glob +import cairo +import tempfile + +class Connection: + + def __init__(self, addr): + self.addr = addr + + def __enter__(self): + self.con = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + self.con.connect(self.addr) + return self.con + + def __exit__(self, exc_type, exc_val, exc_tb): + self.con.close() + del self.con + +def load_image(img): + png = cairo.ImageSurface.create_from_png(img) + + # Cairo wants 4 byte aligned rows, so just add a few pixel if necessary + w = png.get_width() + h = png.get_height() + w = (w + 3) // 4 * 4 + h = (h + 3) // 4 * 4 + img = cairo.ImageSurface(cairo.Format.A8, w, h) + cr = cairo.Context(img) + + cr.set_source_rgba(1, 1, 1, 1) + cr.paint() + + cr.set_source_rgba(0, 0, 0, 0) + cr.set_operator(cairo.OPERATOR_SOURCE) + + cr.set_source_surface(png) + cr.paint() + + return img + +if hasattr(os.environ, 'MESON_SOURCE_ROOT'): + root = os.environ['MESON_SOURCE_ROOT'] +else: + root = os.path.join(os.path.dirname(__file__), '..') + +imgdir = os.path.join(root, 'examples', 'prints') + +ctx = GLib.main_context_default() + +class VirtualImage(unittest.TestCase): + + @classmethod + def setUpClass(cls): + cls.tmpdir = tempfile.mkdtemp(prefix='libfprint-') + + cls.sockaddr = os.path.join(cls.tmpdir, 'virtual-image.socket') + os.environ['FP_VIRTUAL_IMAGE'] = cls.sockaddr + + cls.ctx = FPrint.Context() + + cls.dev = None + for dev in cls.ctx.get_devices(): + # We might have a USB device in the test system that needs skipping + if dev.get_driver() == 'virtual_image': + cls.dev = dev + break + + assert cls.dev is not None, "You need to compile with virtual_image for testing" + + cls.prints = {} + for f in glob.glob(os.path.join(imgdir, '*.png')): + n = os.path.basename(f)[:-4] + cls.prints[n] = load_image(f) + + @classmethod + def tearDownClass(cls): + shutil.rmtree(cls.tmpdir) + + def setUp(self): + self.dev.open_sync() + + def tearDown(self): + self.dev.close_sync() + + def report_finger(self, state): + with Connection(self.sockaddr) as con: + con.write(struct.pack('ii', -1, 1 if state else 0)) + + def send_image(self, image): + img = self.prints[image] + with Connection(self.sockaddr) as con: + mem = img.get_data() + mem = mem.tobytes() + assert len(mem) == img.get_width() * img.get_height() + + encoded_img = struct.pack('ii', img.get_width(), img.get_height()) + encoded_img += mem + + con.sendall(encoded_img) + + def test_capture_prevents_close(self): + cancel = Gio.Cancellable() + def cancelled_cb(dev, res, obj): + print("Capture operation finished") + with self.assertRaises(GLib.GError) as cm: + dev.capture_finish(res) + assert cm.exception.matches(Gio.io_error_quark(), Gio.IOErrorEnum.CANCELLED) + print("Capture cancelled as expected") + obj._cancelled = True + + self._cancelled = False + self.dev.capture(True, cancel, cancelled_cb, self) + + with self.assertRaises(GLib.GError) as cm: + self.dev.close_sync() + assert cm.exception.matches(FPrint.device_error_quark(), FPrint.DeviceError.BUSY) + + cancel.cancel() + while not self._cancelled: + ctx.iteration(True) + + def enroll_print(self, image): + self._step = 0 + self._enrolled = None + + def progress_cb(dev, step, fp, user_data): + print('Print was processed, continuing') + self._step = step + + def done_cb(dev, res): + print("Enroll done") + fp = dev.enroll_finish(res) + self._enrolled = fp + + template = FPrint.Print.new(self.dev) + template.props.finger = FPrint.Finger.LEFT_THUMB + template.props.username = "testuser" + template.props.description = "test print" + datetime = GLib.DateTime.new_now_local() + date = GLib.Date() + date.set_dmy(*datetime.get_ymd()[::-1]) + template.props.enroll_date = date + self.dev.enroll(template, None, progress_cb, tuple(), done_cb) + + # Note: Assumes 5 enroll steps for this device! + self.send_image(image) + while self._step < 1: + ctx.iteration(True) + + self.send_image(image) + while self._step < 2: + ctx.iteration(True) + + self.send_image(image) + while self._step < 3: + ctx.iteration(True) + + self.send_image(image) + while self._step < 4: + ctx.iteration(True) + + self.send_image(image) + while self._enrolled is None: + ctx.iteration(True) + + return self._enrolled + + def test_enroll_verify(self): + done = False + + def verify_cb(dev, res): + match, fp = dev.verify_finish(res) + self._verify_match = match + self._verify_fp = fp + + fp_whorl = self.enroll_print('whorl') + + self._verify_match = None + self._verify_fp = None + self.dev.verify(fp_whorl, None, verify_cb) + self.send_image('whorl') + while self._verify_match is None: + ctx.iteration(True) + assert(self._verify_match) + + self._verify_match = None + self._verify_fp = None + self.dev.verify(fp_whorl, None, verify_cb) + self.send_image('tented_arch') + while self._verify_match is None: + ctx.iteration(True) + assert(not self._verify_match) + + def test_identify(self): + done = False + + def verify_cb(dev, res): + r, fp = dev.verify_finish(res) + self._verify_match = r + self._verify_fp = fp + + fp_whorl = self.enroll_print('whorl') + fp_tented_arch = self.enroll_print('tented_arch') + + def identify_cb(dev, res): + print('Identify finished') + self._identify_match, self._identify_fp = self.dev.identify_finish(res) + + self._identify_fp = None + self.dev.identify([fp_whorl, fp_tented_arch], None, identify_cb) + self.send_image('tented_arch') + while self._identify_fp is None: + ctx.iteration(True) + assert(self._identify_match is fp_tented_arch) + + self._identify_fp = None + self.dev.identify([fp_whorl, fp_tented_arch], None, identify_cb) + self.send_image('whorl') + while self._identify_fp is None: + ctx.iteration(True) + assert(self._identify_match is fp_whorl) + + def test_verify_serialized(self): + done = False + + def verify_cb(dev, res): + r, fp = dev.verify_finish(res) + self._verify_match = r + self._verify_fp = fp + + fp_whorl = self.enroll_print('whorl') + + fp_data = fp_whorl.serialize() + fp_whorl_new = FPrint.Print.deserialize(fp_data) + + # The serialized/deserialized prints need to be equal + assert fp_whorl.equal(fp_whorl_new) + + datetime = GLib.DateTime.new_now_local() + date = GLib.Date() + date.set_dmy(*datetime.get_ymd()[::-1]) + + assert fp_whorl_new.props.username == "testuser" + assert fp_whorl_new.props.description == "test print" + assert fp_whorl_new.props.finger == FPrint.Finger.LEFT_THUMB + assert date.compare(fp_whorl_new.props.enroll_date) == 0 + + self._verify_match = None + self._verify_fp = None + self.dev.verify(fp_whorl_new, None, verify_cb) + self.send_image('whorl') + while self._verify_match is None: + ctx.iteration(True) + assert(self._verify_match) + + self._verify_match = None + self._verify_fp = None + self.dev.verify(fp_whorl_new, None, verify_cb) + self.send_image('tented_arch') + while self._verify_match is None: + ctx.iteration(True) + assert(not self._verify_match) + + +# avoid writing to stderr +unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2)) +