summaryrefslogtreecommitdiff
path: root/chromium/ui/events
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2022-09-07 13:12:05 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2022-11-09 10:02:59 +0000
commit33fc33aa94d4add0878ec30dc818e34e1dd3cc2a (patch)
treef6af110909c79b2759136554f1143d8b0572af0a /chromium/ui/events
parent7d2c5d177e9813077a621df8d18c0deda73099b3 (diff)
downloadqtwebengine-chromium-33fc33aa94d4add0878ec30dc818e34e1dd3cc2a.tar.gz
BASELINE: Update Chromium to 104.0.5112.120
Change-Id: I5d2726c2ab018d75d055739b6ba64317904f05bb Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/438935 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/ui/events')
-rw-r--r--chromium/ui/events/BUILD.gn4
-rw-r--r--chromium/ui/events/blink/blink_event_util.h4
-rw-r--r--chromium/ui/events/blink/web_input_event.cc4
-rw-r--r--chromium/ui/events/blink/web_input_event_builders_win.cc3
-rw-r--r--chromium/ui/events/cocoa/cocoa_event_utils.h4
-rw-r--r--chromium/ui/events/cocoa/cocoa_event_utils.mm52
-rw-r--r--chromium/ui/events/cocoa/events_mac.mm68
-rw-r--r--chromium/ui/events/cocoa/events_mac_unittest.mm93
-rw-r--r--chromium/ui/events/devices/device_data_manager.cc3
-rw-r--r--chromium/ui/events/devices/input_device.h4
-rw-r--r--chromium/ui/events/event_constants.h143
-rw-r--r--chromium/ui/events/event_switches.cc7
-rw-r--r--chromium/ui/events/event_switches.h1
-rw-r--r--chromium/ui/events/fuchsia/DIR_METADATA1
-rw-r--r--chromium/ui/events/fuchsia/fakes/DIR_METADATA10
-rw-r--r--chromium/ui/events/gesture_detection/gesture_configuration_aura.cc12
-rw-r--r--chromium/ui/events/gesture_detection/gesture_detector.cc1
-rw-r--r--chromium/ui/events/gestures/blink/BUILD.gn3
-rw-r--r--chromium/ui/events/gestures/gesture_recognizer_impl.cc8
-rw-r--r--chromium/ui/events/gestures/gesture_recognizer_impl.h4
-rw-r--r--chromium/ui/events/gestures/physics_based_fling_curve.cc2
-rw-r--r--chromium/ui/events/keycodes/DEPS13
-rw-r--r--chromium/ui/events/keycodes/dom/keycode_converter.cc2
-rw-r--r--chromium/ui/events/keycodes/keyboard_code_conversion_mac.h4
-rw-r--r--chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm30
-rw-r--r--chromium/ui/events/mobile_scroller.cc8
-rw-r--r--chromium/ui/events/ozone/device/device_event.cc8
-rw-r--r--chromium/ui/events/ozone/device/device_event.h14
-rw-r--r--chromium/ui/events/ozone/device/udev/device_manager_udev.cc19
-rw-r--r--chromium/ui/events/ozone/evdev/BUILD.gn16
-rw-r--r--chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.h6
-rw-r--r--chromium/ui/events/ozone/evdev/event_converter_evdev.cc24
-rw-r--r--chromium/ui/events/ozone/evdev/event_converter_evdev.h24
-rw-r--r--chromium/ui/events/ozone/evdev/event_converter_evdev_impl.cc39
-rw-r--r--chromium/ui/events/ozone/evdev/event_converter_evdev_impl.h17
-rw-r--r--chromium/ui/events/ozone/evdev/event_converter_evdev_impl_unittest.cc54
-rw-r--r--chromium/ui/events/ozone/evdev/event_converter_test_util.cc12
-rw-r--r--chromium/ui/events/ozone/evdev/event_device_info.cc281
-rw-r--r--chromium/ui/events/ozone/evdev/event_device_info.h38
-rw-r--r--chromium/ui/events/ozone/evdev/event_device_info_unittest.cc18
-rw-r--r--chromium/ui/events/ozone/evdev/event_device_test_util.cc27
-rw-r--r--chromium/ui/events/ozone/evdev/event_device_test_util.h1
-rw-r--r--chromium/ui/events/ozone/evdev/event_device_util.h11
-rw-r--r--chromium/ui/events/ozone/evdev/event_factory_evdev.cc20
-rw-r--r--chromium/ui/events/ozone/evdev/event_factory_evdev.h9
-rw-r--r--chromium/ui/events/ozone/evdev/event_factory_evdev_unittest.cc5
-rw-r--r--chromium/ui/events/ozone/evdev/event_thread_evdev.cc4
-rw-r--r--chromium/ui/events/ozone/evdev/fake_keyboard_heuristic_metrics.cc28
-rw-r--r--chromium/ui/events/ozone/evdev/fake_keyboard_heuristic_metrics.h26
-rw-r--r--chromium/ui/events/ozone/evdev/gamepad_event_converter_evdev.cc12
-rw-r--r--chromium/ui/events/ozone/evdev/gamepad_event_converter_evdev.h3
-rw-r--r--chromium/ui/events/ozone/evdev/gamepad_event_converter_evdev_unittest.cc12
-rw-r--r--chromium/ui/events/ozone/evdev/input_controller_evdev.cc24
-rw-r--r--chromium/ui/events/ozone/evdev/input_controller_evdev.h12
-rw-r--r--chromium/ui/events/ozone/evdev/input_device_factory_evdev.cc177
-rw-r--r--chromium/ui/events/ozone/evdev/input_device_factory_evdev.h17
-rw-r--r--chromium/ui/events/ozone/evdev/input_device_factory_evdev_unittest.cc440
-rw-r--r--chromium/ui/events/ozone/evdev/input_device_opener.h47
-rw-r--r--chromium/ui/events/ozone/evdev/input_device_opener_evdev.cc134
-rw-r--r--chromium/ui/events/ozone/evdev/input_device_opener_evdev.h30
-rw-r--r--chromium/ui/events/ozone/evdev/keyboard_imposter_checker_evdev.cc74
-rw-r--r--chromium/ui/events/ozone/evdev/keyboard_imposter_checker_evdev.h47
-rw-r--r--chromium/ui/events/ozone/evdev/libgestures_glue/gesture_properties_service.cc20
-rw-r--r--chromium/ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.cc4
-rw-r--r--chromium/ui/events/ozone/evdev/touch_event_converter_evdev.cc2
-rw-r--r--chromium/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc18
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.cc8
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.h1
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_model.h3
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/palm_detection_filter_factory.cc26
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/palm_detection_filter_factory.h6
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/palm_detection_filter_factory_unittest.cc1
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.cc7
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.h6
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.cc3936
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.h40
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.cc7
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.h4
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.cc85
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.h3
-rw-r--r--chromium/ui/events/ozone/features.cc7
-rw-r--r--chromium/ui/events/ozone/features.h10
82 files changed, 5882 insertions, 530 deletions
diff --git a/chromium/ui/events/BUILD.gn b/chromium/ui/events/BUILD.gn
index bdc40a6b505..62b4dd632d6 100644
--- a/chromium/ui/events/BUILD.gn
+++ b/chromium/ui/events/BUILD.gn
@@ -495,7 +495,7 @@ component("gesture_detection") {
if (is_android) {
sources += [ "gesture_detection/gesture_configuration_android.cc" ]
- } else if (is_chromecast) {
+ } else if (is_castos) {
sources += [ "gesture_detection/gesture_configuration_cast.cc" ]
} else if (use_aura) {
sources += [ "gesture_detection/gesture_configuration_aura.cc" ]
@@ -712,7 +712,7 @@ if (!is_ios) {
deps += [ "//ui/events:keyboard_hook" ]
}
- if (is_chromecast && !is_android) {
+ if (is_castos) {
sources += [ "chromecast/scroller_unittest.cc" ]
}
diff --git a/chromium/ui/events/blink/blink_event_util.h b/chromium/ui/events/blink/blink_event_util.h
index e0f3d387d19..ed105fc09f7 100644
--- a/chromium/ui/events/blink/blink_event_util.h
+++ b/chromium/ui/events/blink/blink_event_util.h
@@ -29,6 +29,10 @@ struct GestureEventData;
struct GestureEventDetails;
class MotionEvent;
+// The scroll percentage per mousewheel tick. Used to determine scroll delta
+// if percent based scrolling is enabled.
+const float kScrollPercentPerLineOrChar = 0.05f;
+
blink::WebTouchEvent CreateWebTouchEventFromMotionEvent(
const MotionEvent& event,
bool may_cause_scrolling,
diff --git a/chromium/ui/events/blink/web_input_event.cc b/chromium/ui/events/blink/web_input_event.cc
index 7143fb67ae4..1b7d11a6362 100644
--- a/chromium/ui/events/blink/web_input_event.cc
+++ b/chromium/ui/events/blink/web_input_event.cc
@@ -22,10 +22,6 @@ namespace ui {
namespace {
-// The scroll percentage per mousewheel tick. Used to determine scroll delta
-// if percent based scrolling is enabled.
-const float kScrollPercentPerLineOrChar = 0.05;
-
gfx::PointF GetScreenLocationFromEvent(const LocatedEvent& event) {
return event.target() ? event.target()->GetScreenLocationF(event)
: event.root_location_f();
diff --git a/chromium/ui/events/blink/web_input_event_builders_win.cc b/chromium/ui/events/blink/web_input_event_builders_win.cc
index fdaef0451cd..6d8d63a7377 100644
--- a/chromium/ui/events/blink/web_input_event_builders_win.cc
+++ b/chromium/ui/events/blink/web_input_event_builders_win.cc
@@ -21,7 +21,6 @@ namespace ui {
static const unsigned long kDefaultScrollLinesPerWheelDelta = 3;
static const unsigned long kDefaultScrollCharsPerWheelDelta = 1;
-static const unsigned long kScrollPercentPerLineOrChar = 5;
// WebMouseEvent --------------------------------------------------------------
@@ -313,7 +312,7 @@ WebMouseWheelEvent WebMouseWheelEventBuilder::Build(
// the percentage amount (out of 1, i.e. 1 == 100%) the targeted scroller
// should scroll. This percentage will be resolved against the size of
// the scroller in the renderer process.
- scroll_delta *= kScrollPercentPerLineOrChar / 100.f;
+ scroll_delta *= kScrollPercentPerLineOrChar;
result.delta_units = ui::ScrollGranularity::kScrollByPercentage;
} else {
// Convert wheel delta amount to a number of pixels to scroll.
diff --git a/chromium/ui/events/cocoa/cocoa_event_utils.h b/chromium/ui/events/cocoa/cocoa_event_utils.h
index f447342fa6f..12986a1c0f8 100644
--- a/chromium/ui/events/cocoa/cocoa_event_utils.h
+++ b/chromium/ui/events/cocoa/cocoa_event_utils.h
@@ -27,8 +27,8 @@ EVENTS_EXPORT int EventFlagsFromModifiers(NSUInteger modifiers);
EVENTS_EXPORT int EventFlagsFromNSEventWithModifiers(NSEvent* event,
NSUInteger modifiers);
-// Returns true for |NSKeyUp| and for |NSFlagsChanged| when modifier key was
-// released.
+// Returns true for |NSEventTypeKeyUp| and for |NSEventTypeFlagsChanged| when
+// modifier key was released.
EVENTS_EXPORT bool IsKeyUpEvent(NSEvent* event);
// Convert an NSEvent to an opaque serialization using CGEventCreateData.
diff --git a/chromium/ui/events/cocoa/cocoa_event_utils.mm b/chromium/ui/events/cocoa/cocoa_event_utils.mm
index 908e4c6ff30..dca4916c2ae 100644
--- a/chromium/ui/events/cocoa/cocoa_event_utils.mm
+++ b/chromium/ui/events/cocoa/cocoa_event_utils.mm
@@ -15,14 +15,15 @@ namespace {
bool IsLeftButtonEvent(NSEvent* event) {
NSEventType type = [event type];
- return type == NSLeftMouseDown || type == NSLeftMouseDragged ||
- type == NSLeftMouseUp;
+ return type == NSEventTypeLeftMouseDown ||
+ type == NSEventTypeLeftMouseDragged || type == NSEventTypeLeftMouseUp;
}
bool IsRightButtonEvent(NSEvent* event) {
NSEventType type = [event type];
- return type == NSRightMouseDown || type == NSRightMouseDragged ||
- type == NSRightMouseUp;
+ return type == NSEventTypeRightMouseDown ||
+ type == NSEventTypeRightMouseDragged ||
+ type == NSEventTypeRightMouseUp;
}
bool IsMiddleButtonEvent(NSEvent* event) {
@@ -30,8 +31,9 @@ bool IsMiddleButtonEvent(NSEvent* event) {
return false;
NSEventType type = [event type];
- return type == NSOtherMouseDown || type == NSOtherMouseDragged ||
- type == NSOtherMouseUp;
+ return type == NSEventTypeOtherMouseDown ||
+ type == NSEventTypeOtherMouseDragged ||
+ type == NSEventTypeOtherMouseUp;
}
// Return true if the target modifier key is up. OS X has an "official" flag
@@ -60,11 +62,11 @@ namespace ui {
int EventFlagsFromModifiers(NSUInteger modifiers) {
int flags = 0;
- flags |= (modifiers & NSAlphaShiftKeyMask) ? ui::EF_CAPS_LOCK_ON : 0;
- flags |= (modifiers & NSShiftKeyMask) ? ui::EF_SHIFT_DOWN : 0;
- flags |= (modifiers & NSControlKeyMask) ? ui::EF_CONTROL_DOWN : 0;
- flags |= (modifiers & NSAlternateKeyMask) ? ui::EF_ALT_DOWN : 0;
- flags |= (modifiers & NSCommandKeyMask) ? ui::EF_COMMAND_DOWN : 0;
+ flags |= (modifiers & NSEventModifierFlagCapsLock) ? ui::EF_CAPS_LOCK_ON : 0;
+ flags |= (modifiers & NSEventModifierFlagShift) ? ui::EF_SHIFT_DOWN : 0;
+ flags |= (modifiers & NSEventModifierFlagControl) ? ui::EF_CONTROL_DOWN : 0;
+ flags |= (modifiers & NSEventModifierFlagOption) ? ui::EF_ALT_DOWN : 0;
+ flags |= (modifiers & NSEventModifierFlagCommand) ? ui::EF_COMMAND_DOWN : 0;
return flags;
}
@@ -73,7 +75,7 @@ int EventFlagsFromNSEventWithModifiers(NSEvent* event, NSUInteger modifiers) {
if (IsLeftButtonEvent(event)) {
// For Mac, convert Ctrl+LeftClick to a RightClick, and remove the Control
// key modifier.
- if (modifiers & NSControlKeyMask)
+ if (modifiers & NSEventModifierFlagControl)
flags = (flags & ~ui::EF_CONTROL_DOWN) | ui::EF_RIGHT_MOUSE_BUTTON;
else
flags |= ui::EF_LEFT_MOUSE_BUTTON;
@@ -82,50 +84,50 @@ int EventFlagsFromNSEventWithModifiers(NSEvent* event, NSUInteger modifiers) {
flags |= IsRightButtonEvent(event) ? ui::EF_RIGHT_MOUSE_BUTTON : 0;
flags |= IsMiddleButtonEvent(event) ? ui::EF_MIDDLE_MOUSE_BUTTON : 0;
- if ([event type] == NSKeyDown && [event isARepeat])
+ if ([event type] == NSEventTypeKeyDown && [event isARepeat])
flags |= ui::EF_IS_REPEAT;
return flags;
}
bool IsKeyUpEvent(NSEvent* event) {
- if ([event type] != NSFlagsChanged)
- return [event type] == NSKeyUp;
+ if ([event type] != NSEventTypeFlagsChanged)
+ return [event type] == NSEventTypeKeyUp;
switch ([event keyCode]) {
case kVK_Command:
return IsModifierKeyUp([event modifierFlags], NX_DEVICELCMDKEYMASK,
- NX_DEVICERCMDKEYMASK, NSCommandKeyMask);
+ NX_DEVICERCMDKEYMASK, NSEventModifierFlagCommand);
case kVK_RightCommand:
return IsModifierKeyUp([event modifierFlags], NX_DEVICERCMDKEYMASK,
- NX_DEVICELCMDKEYMASK, NSCommandKeyMask);
+ NX_DEVICELCMDKEYMASK, NSEventModifierFlagCommand);
case kVK_CapsLock:
- return ([event modifierFlags] & NSAlphaShiftKeyMask) == 0;
+ return ([event modifierFlags] & NSEventModifierFlagCapsLock) == 0;
case kVK_Shift:
return IsModifierKeyUp([event modifierFlags], NX_DEVICELSHIFTKEYMASK,
- NX_DEVICERSHIFTKEYMASK, NSShiftKeyMask);
+ NX_DEVICERSHIFTKEYMASK, NSEventModifierFlagShift);
case kVK_RightShift:
return IsModifierKeyUp([event modifierFlags], NX_DEVICERSHIFTKEYMASK,
- NX_DEVICELSHIFTKEYMASK, NSShiftKeyMask);
+ NX_DEVICELSHIFTKEYMASK, NSEventModifierFlagShift);
case kVK_Option:
return IsModifierKeyUp([event modifierFlags], NX_DEVICELALTKEYMASK,
- NX_DEVICERALTKEYMASK, NSAlternateKeyMask);
+ NX_DEVICERALTKEYMASK, NSEventModifierFlagOption);
case kVK_RightOption:
return IsModifierKeyUp([event modifierFlags], NX_DEVICERALTKEYMASK,
- NX_DEVICELALTKEYMASK, NSAlternateKeyMask);
+ NX_DEVICELALTKEYMASK, NSEventModifierFlagOption);
case kVK_Control:
return IsModifierKeyUp([event modifierFlags], NX_DEVICELCTLKEYMASK,
- NX_DEVICERCTLKEYMASK, NSControlKeyMask);
+ NX_DEVICERCTLKEYMASK, NSEventModifierFlagControl);
case kVK_RightControl:
return IsModifierKeyUp([event modifierFlags], NX_DEVICERCTLKEYMASK,
- NX_DEVICELCTLKEYMASK, NSControlKeyMask);
+ NX_DEVICELCTLKEYMASK, NSEventModifierFlagControl);
case kVK_Function:
- return ([event modifierFlags] & NSFunctionKeyMask) == 0;
+ return ([event modifierFlags] & NSEventModifierFlagFunction) == 0;
}
return false;
}
diff --git a/chromium/ui/events/cocoa/events_mac.mm b/chromium/ui/events/cocoa/events_mac.mm
index b716ef85eec..a20fff8a55f 100644
--- a/chromium/ui/events/cocoa/events_mac.mm
+++ b/chromium/ui/events/cocoa/events_mac.mm
@@ -24,40 +24,40 @@ namespace ui {
EventType EventTypeFromNative(const PlatformEvent& native_event) {
NSEventType type = [native_event type];
switch (type) {
- case NSKeyDown:
- case NSKeyUp:
- case NSFlagsChanged:
+ case NSEventTypeKeyDown:
+ case NSEventTypeKeyUp:
+ case NSEventTypeFlagsChanged:
return IsKeyUpEvent(native_event) ? ET_KEY_RELEASED : ET_KEY_PRESSED;
- case NSLeftMouseDown:
- case NSRightMouseDown:
- case NSOtherMouseDown:
+ case NSEventTypeLeftMouseDown:
+ case NSEventTypeRightMouseDown:
+ case NSEventTypeOtherMouseDown:
return ET_MOUSE_PRESSED;
- case NSLeftMouseUp:
- case NSRightMouseUp:
- case NSOtherMouseUp:
+ case NSEventTypeLeftMouseUp:
+ case NSEventTypeRightMouseUp:
+ case NSEventTypeOtherMouseUp:
return ET_MOUSE_RELEASED;
- case NSLeftMouseDragged:
- case NSRightMouseDragged:
- case NSOtherMouseDragged:
+ case NSEventTypeLeftMouseDragged:
+ case NSEventTypeRightMouseDragged:
+ case NSEventTypeOtherMouseDragged:
return ET_MOUSE_DRAGGED;
- case NSMouseMoved:
+ case NSEventTypeMouseMoved:
return ET_MOUSE_MOVED;
- case NSScrollWheel:
+ case NSEventTypeScrollWheel:
return ET_SCROLL;
- case NSMouseEntered:
+ case NSEventTypeMouseEntered:
return ET_MOUSE_ENTERED;
- case NSMouseExited:
+ case NSEventTypeMouseExited:
return ET_MOUSE_EXITED;
case NSEventTypeSwipe:
return ET_SCROLL_FLING_START;
- case NSAppKitDefined:
- case NSSystemDefined:
+ case NSEventTypeAppKitDefined:
+ case NSEventTypeSystemDefined:
return ET_UNKNOWN;
- case NSApplicationDefined:
- case NSPeriodic:
- case NSCursorUpdate:
- case NSTabletPoint:
- case NSTabletProximity:
+ case NSEventTypeApplicationDefined:
+ case NSEventTypePeriodic:
+ case NSEventTypeCursorUpdate:
+ case NSEventTypeTabletPoint:
+ case NSEventTypeTabletProximity:
case NSEventTypeGesture:
case NSEventTypeMagnify:
case NSEventTypeRotate:
@@ -112,17 +112,17 @@ int EventButtonFromNative(const PlatformEvent& native_event) {
int GetChangedMouseButtonFlagsFromNative(const PlatformEvent& native_event) {
NSEventType type = [native_event type];
switch (type) {
- case NSLeftMouseDown:
- case NSLeftMouseUp:
- case NSLeftMouseDragged:
+ case NSEventTypeLeftMouseDown:
+ case NSEventTypeLeftMouseUp:
+ case NSEventTypeLeftMouseDragged:
return EF_LEFT_MOUSE_BUTTON;
- case NSRightMouseDown:
- case NSRightMouseUp:
- case NSRightMouseDragged:
+ case NSEventTypeRightMouseDown:
+ case NSEventTypeRightMouseUp:
+ case NSEventTypeRightMouseDragged:
return EF_RIGHT_MOUSE_BUTTON;
- case NSOtherMouseDown:
- case NSOtherMouseUp:
- case NSOtherMouseDragged:
+ case NSEventTypeOtherMouseDown:
+ case NSEventTypeOtherMouseUp:
+ case NSEventTypeOtherMouseDragged:
return EF_MIDDLE_MOUSE_BUTTON;
default:
break;
@@ -269,7 +269,7 @@ uint32_t WindowsKeycodeFromNative(const PlatformEvent& native_event) {
uint16_t TextFromNative(const PlatformEvent& native_event) {
NSString* text = @"";
- if ([native_event type] != NSFlagsChanged)
+ if ([native_event type] != NSEventTypeFlagsChanged)
text = [native_event characters];
// These exceptions are based on web_input_event_builders_mac.mm:
@@ -288,7 +288,7 @@ uint16_t TextFromNative(const PlatformEvent& native_event) {
uint16_t UnmodifiedTextFromNative(const PlatformEvent& native_event) {
NSString* text = @"";
- if ([native_event type] != NSFlagsChanged)
+ if ([native_event type] != NSEventTypeFlagsChanged)
text = [native_event charactersIgnoringModifiers];
// These exceptions are based on web_input_event_builders_mac.mm:
diff --git a/chromium/ui/events/cocoa/events_mac_unittest.mm b/chromium/ui/events/cocoa/events_mac_unittest.mm
index f317cb3165b..7e26a3b927b 100644
--- a/chromium/ui/events/cocoa/events_mac_unittest.mm
+++ b/chromium/ui/events/cocoa/events_mac_unittest.mm
@@ -148,59 +148,62 @@ NSArray* EventsMacTest::TrackpadScrollSequence(bool initial_rest,
TEST_F(EventsMacTest, EventFlagsFromNative) {
// Left click.
- NSEvent* left = cocoa_test_event_utils::MouseEventWithType(NSLeftMouseUp, 0);
+ NSEvent* left =
+ cocoa_test_event_utils::MouseEventWithType(NSEventTypeLeftMouseUp, 0);
EXPECT_EQ(EF_LEFT_MOUSE_BUTTON, EventFlagsFromNative(left));
// Right click.
- NSEvent* right = cocoa_test_event_utils::MouseEventWithType(NSRightMouseUp,
- 0);
+ NSEvent* right =
+ cocoa_test_event_utils::MouseEventWithType(NSEventTypeRightMouseUp, 0);
EXPECT_EQ(EF_RIGHT_MOUSE_BUTTON, EventFlagsFromNative(right));
// Middle click.
- NSEvent* middle = cocoa_test_event_utils::MouseEventWithType(NSOtherMouseUp,
- 0);
+ NSEvent* middle =
+ cocoa_test_event_utils::MouseEventWithType(NSEventTypeOtherMouseUp, 0);
EXPECT_EQ(EF_MIDDLE_MOUSE_BUTTON, EventFlagsFromNative(middle));
// Caps + Left
NSEvent* caps = cocoa_test_event_utils::MouseEventWithType(
- NSLeftMouseUp, NSAlphaShiftKeyMask);
+ NSEventTypeLeftMouseUp, NSEventModifierFlagCapsLock);
EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_CAPS_LOCK_ON, EventFlagsFromNative(caps));
// Shift + Left
- NSEvent* shift = cocoa_test_event_utils::MouseEventWithType(NSLeftMouseUp,
- NSShiftKeyMask);
+ NSEvent* shift = cocoa_test_event_utils::MouseEventWithType(
+ NSEventTypeLeftMouseUp, NSEventModifierFlagShift);
EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_SHIFT_DOWN, EventFlagsFromNative(shift));
// Ctrl + Left. Note we map this to a right click on Mac and remove Control.
- NSEvent* ctrl = cocoa_test_event_utils::MouseEventWithType(NSLeftMouseUp,
- NSControlKeyMask);
+ NSEvent* ctrl = cocoa_test_event_utils::MouseEventWithType(
+ NSEventTypeLeftMouseUp, NSEventModifierFlagControl);
EXPECT_EQ(EF_RIGHT_MOUSE_BUTTON, EventFlagsFromNative(ctrl));
// Ctrl + Right. Remains a right click.
NSEvent* ctrl_right = cocoa_test_event_utils::MouseEventWithType(
- NSRightMouseUp, NSControlKeyMask);
+ NSEventTypeRightMouseUp, NSEventModifierFlagControl);
EXPECT_EQ(EF_RIGHT_MOUSE_BUTTON | EF_CONTROL_DOWN,
EventFlagsFromNative(ctrl_right));
// Alt + Left
- NSEvent* alt = cocoa_test_event_utils::MouseEventWithType(NSLeftMouseUp,
- NSAlternateKeyMask);
+ NSEvent* alt = cocoa_test_event_utils::MouseEventWithType(
+ NSEventTypeLeftMouseUp, NSEventModifierFlagOption);
EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_ALT_DOWN, EventFlagsFromNative(alt));
// Cmd + Left
- NSEvent* cmd = cocoa_test_event_utils::MouseEventWithType(NSLeftMouseUp,
- NSCommandKeyMask);
+ NSEvent* cmd = cocoa_test_event_utils::MouseEventWithType(
+ NSEventTypeLeftMouseUp, NSEventModifierFlagCommand);
EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_COMMAND_DOWN, EventFlagsFromNative(cmd));
// Shift + Ctrl + Left. Also mapped to a right-click. Control removed.
NSEvent* shiftctrl = cocoa_test_event_utils::MouseEventWithType(
- NSLeftMouseUp, NSShiftKeyMask | NSControlKeyMask);
+ NSEventTypeLeftMouseUp,
+ NSEventModifierFlagShift | NSEventModifierFlagControl);
EXPECT_EQ(EF_RIGHT_MOUSE_BUTTON | EF_SHIFT_DOWN,
EventFlagsFromNative(shiftctrl));
// Cmd + Alt + Right
NSEvent* cmdalt = cocoa_test_event_utils::MouseEventWithType(
- NSLeftMouseUp, NSCommandKeyMask | NSAlternateKeyMask);
+ NSEventTypeLeftMouseUp,
+ NSEventModifierFlagCommand | NSEventModifierFlagOption);
EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_COMMAND_DOWN | EF_ALT_DOWN,
EventFlagsFromNative(cmdalt));
@@ -272,11 +275,12 @@ TEST_F(EventsMacTest, ButtonEvents) {
// Test correct location when the window has a native titlebar.
TEST_F(EventsMacTest, NativeTitlebarEventLocation) {
gfx::Point location(5, 10);
- NSUInteger style_mask = NSTitledWindowMask | NSClosableWindowMask |
- NSMiniaturizableWindowMask | NSResizableWindowMask;
+ NSUInteger style_mask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
+ NSWindowStyleMaskMiniaturizable |
+ NSWindowStyleMaskResizable;
// First check that the window provided by ui::CocoaTest is how we think.
- DCHECK_EQ(NSBorderlessWindowMask, [test_window() styleMask]);
+ DCHECK_EQ(NSWindowStyleMaskBorderless, [test_window() styleMask]);
[test_window() setStyleMask:style_mask];
DCHECK_EQ(style_mask, [test_window() styleMask]);
@@ -294,7 +298,7 @@ TEST_F(EventsMacTest, NativeTitlebarEventLocation) {
NSRect content_rect = NSMakeRect(0, 0, 600, kTestHeight);
NSRect frame_rect = [test_window() frameRectForContentRect:content_rect];
[test_window() setFrame:frame_rect display:YES];
- event = [NSEvent mouseEventWithType:NSLeftMouseDown
+ event = [NSEvent mouseEventWithType:NSEventTypeLeftMouseDown
location:NSMakePoint(0, 0) // Bottom-left corner.
modifierFlags:0
timestamp:0
@@ -311,7 +315,7 @@ TEST_F(EventsMacTest, NativeTitlebarEventLocation) {
// toolkit-views coordinate system.
int height_change = NSHeight(frame_rect) - kTestHeight;
EXPECT_GT(height_change, 0);
- [test_window() setStyleMask:NSBorderlessWindowMask];
+ [test_window() setStyleMask:NSWindowStyleMaskBorderless];
[test_window() setFrame:frame_rect display:YES];
EXPECT_EQ(gfx::Point(0, kTestHeight + height_change),
gfx::ToFlooredPoint(ui::EventLocationFromNative(event)));
@@ -332,20 +336,24 @@ TEST_F(EventsMacTest, NoWindowLocation) {
// Testing for ui::EventTypeFromNative() not covered by ButtonEvents.
TEST_F(EventsMacTest, EventTypeFromNative) {
- NSEvent* event = cocoa_test_event_utils::KeyEventWithType(NSKeyDown, 0);
+ NSEvent* event =
+ cocoa_test_event_utils::KeyEventWithType(NSEventTypeKeyDown, 0);
EXPECT_EQ(ui::ET_KEY_PRESSED, ui::EventTypeFromNative(event));
- event = cocoa_test_event_utils::KeyEventWithType(NSKeyUp, 0);
+ event = cocoa_test_event_utils::KeyEventWithType(NSEventTypeKeyUp, 0);
EXPECT_EQ(ui::ET_KEY_RELEASED, ui::EventTypeFromNative(event));
- event = cocoa_test_event_utils::MouseEventWithType(NSLeftMouseDragged, 0);
+ event = cocoa_test_event_utils::MouseEventWithType(
+ NSEventTypeLeftMouseDragged, 0);
EXPECT_EQ(ui::ET_MOUSE_DRAGGED, ui::EventTypeFromNative(event));
- event = cocoa_test_event_utils::MouseEventWithType(NSRightMouseDragged, 0);
+ event = cocoa_test_event_utils::MouseEventWithType(
+ NSEventTypeRightMouseDragged, 0);
EXPECT_EQ(ui::ET_MOUSE_DRAGGED, ui::EventTypeFromNative(event));
- event = cocoa_test_event_utils::MouseEventWithType(NSOtherMouseDragged, 0);
+ event = cocoa_test_event_utils::MouseEventWithType(
+ NSEventTypeOtherMouseDragged, 0);
EXPECT_EQ(ui::ET_MOUSE_DRAGGED, ui::EventTypeFromNative(event));
- event = cocoa_test_event_utils::MouseEventWithType(NSMouseMoved, 0);
+ event = cocoa_test_event_utils::MouseEventWithType(NSEventTypeMouseMoved, 0);
EXPECT_EQ(ui::ET_MOUSE_MOVED, ui::EventTypeFromNative(event));
event = cocoa_test_event_utils::EnterEvent();
@@ -516,7 +524,8 @@ TEST_F(EventsMacTest, TrackpadScrollThenFlick) {
}
}
-// Check that NSFlagsChanged event is translated to key press or release event.
+// Check that NSEventTypeFlagsChanged event is translated to key press or
+// release event.
TEST_F(EventsMacTest, HandleModifierOnlyKeyEvents) {
struct {
const char* description;
@@ -525,24 +534,26 @@ TEST_F(EventsMacTest, HandleModifierOnlyKeyEvents) {
EventType expected_type;
KeyboardCode expected_key_code;
} test_cases[] = {
- {"CapsLock pressed", NSAlphaShiftKeyMask, kVK_CapsLock, ET_KEY_PRESSED,
- VKEY_CAPITAL},
+ {"CapsLock pressed", NSEventModifierFlagCapsLock, kVK_CapsLock,
+ ET_KEY_PRESSED, VKEY_CAPITAL},
{"CapsLock released", 0, kVK_CapsLock, ET_KEY_RELEASED, VKEY_CAPITAL},
- {"Shift pressed", NSShiftKeyMask, kVK_Shift, ET_KEY_PRESSED, VKEY_SHIFT},
+ {"Shift pressed", NSEventModifierFlagShift, kVK_Shift, ET_KEY_PRESSED,
+ VKEY_SHIFT},
{"Shift released", 0, kVK_Shift, ET_KEY_RELEASED, VKEY_SHIFT},
- {"Control pressed", NSControlKeyMask, kVK_Control, ET_KEY_PRESSED,
- VKEY_CONTROL},
+ {"Control pressed", NSEventModifierFlagControl, kVK_Control,
+ ET_KEY_PRESSED, VKEY_CONTROL},
{"Control released", 0, kVK_Control, ET_KEY_RELEASED, VKEY_CONTROL},
- {"Option pressed", NSAlternateKeyMask, kVK_Option, ET_KEY_PRESSED,
+ {"Option pressed", NSEventModifierFlagOption, kVK_Option, ET_KEY_PRESSED,
VKEY_MENU},
{"Option released", 0, kVK_Option, ET_KEY_RELEASED, VKEY_MENU},
- {"Command pressed", NSCommandKeyMask, kVK_Command, ET_KEY_PRESSED,
- VKEY_LWIN},
+ {"Command pressed", NSEventModifierFlagCommand, kVK_Command,
+ ET_KEY_PRESSED, VKEY_LWIN},
{"Command released", 0, kVK_Command, ET_KEY_RELEASED, VKEY_LWIN},
- {"Shift pressed with CapsLock on", NSShiftKeyMask | NSAlphaShiftKeyMask,
- kVK_Shift, ET_KEY_PRESSED, VKEY_SHIFT},
- {"Shift released with CapsLock off", NSAlphaShiftKeyMask, kVK_Shift,
- ET_KEY_RELEASED, VKEY_SHIFT},
+ {"Shift pressed with CapsLock on",
+ NSEventModifierFlagShift | NSEventModifierFlagCapsLock, kVK_Shift,
+ ET_KEY_PRESSED, VKEY_SHIFT},
+ {"Shift released with CapsLock off", NSEventModifierFlagCapsLock,
+ kVK_Shift, ET_KEY_RELEASED, VKEY_SHIFT},
};
for (const auto& test_case : test_cases) {
SCOPED_TRACE(::testing::Message() << "While checking case: "
diff --git a/chromium/ui/events/devices/device_data_manager.cc b/chromium/ui/events/devices/device_data_manager.cc
index 03a5ccd6ece..16835a48ea0 100644
--- a/chromium/ui/events/devices/device_data_manager.cc
+++ b/chromium/ui/events/devices/device_data_manager.cc
@@ -28,7 +28,8 @@ namespace ui {
namespace {
bool InputDeviceEquals(const ui::InputDevice& a, const ui::InputDevice& b) {
- return a.id == b.id && a.enabled == b.enabled;
+ return a.id == b.id && a.enabled == b.enabled &&
+ a.suspected_imposter == b.suspected_imposter;
}
} // namespace
diff --git a/chromium/ui/events/devices/input_device.h b/chromium/ui/events/devices/input_device.h
index e3cc0019366..d61a4f2d525 100644
--- a/chromium/ui/events/devices/input_device.h
+++ b/chromium/ui/events/devices/input_device.h
@@ -57,6 +57,10 @@ struct EVENTS_DEVICES_EXPORT InputDevice {
// If the device is enabled, and whether events should be dispatched to UI.
bool enabled = true;
+ // If the device is suspected to be identifying as another device type
+ // (Currently only applies to Mice pretending to be keyboards).
+ bool suspected_imposter = false;
+
// The path to the input device in the sysfs filesystem.
base::FilePath sys_path;
diff --git a/chromium/ui/events/event_constants.h b/chromium/ui/events/event_constants.h
index c16556cd8c1..8728f1200f2 100644
--- a/chromium/ui/events/event_constants.h
+++ b/chromium/ui/events/event_constants.h
@@ -13,91 +13,90 @@ namespace ui {
// this list and/or reorder it, but make sure you also touch the various other
// enums/constants that want to stay in sync with this. For example,
// KeyEventFlags and MouseEventFlags should not overlap EventFlags.
-enum EventFlags {
- EF_NONE = 0, // Used to denote no flags explicitly
-
- // Universally applicable status bits.
- EF_IS_SYNTHESIZED = 1 << 0,
-
- // Modifier key state.
- EF_SHIFT_DOWN = 1 << 1,
- EF_CONTROL_DOWN = 1 << 2,
- EF_ALT_DOWN = 1 << 3,
- EF_COMMAND_DOWN = 1 << 4, // GUI Key (e.g. Command on OS X
- // keyboards, Search on Chromebook
- // keyboards, Windows on MS-oriented
- // keyboards)
- EF_FUNCTION_DOWN = 1 << 5, // Function key.
- EF_ALTGR_DOWN = 1 << 6,
- EF_MOD3_DOWN = 1 << 7,
-
- // Other keyboard states.
- EF_NUM_LOCK_ON = 1 << 8,
- EF_CAPS_LOCK_ON = 1 << 9,
- EF_SCROLL_LOCK_ON = 1 << 10,
-
- // Mouse buttons.
- EF_LEFT_MOUSE_BUTTON = 1 << 11,
- EF_MIDDLE_MOUSE_BUTTON = 1 << 12,
- EF_RIGHT_MOUSE_BUTTON = 1 << 13,
- EF_BACK_MOUSE_BUTTON = 1 << 14,
- EF_FORWARD_MOUSE_BUTTON = 1 << 15,
- EF_MOUSE_BUTTON = EF_LEFT_MOUSE_BUTTON | EF_MIDDLE_MOUSE_BUTTON |
- EF_RIGHT_MOUSE_BUTTON | EF_BACK_MOUSE_BUTTON |
- EF_FORWARD_MOUSE_BUTTON,
+using EventFlags = int;
+// Used to denote no flags explicitly
+constexpr EventFlags EF_NONE = 0;
+
+// Universally applicable status bits.
+constexpr EventFlags EF_IS_SYNTHESIZED = 1 << 0;
+
+// Modifier key state.
+constexpr EventFlags EF_SHIFT_DOWN = 1 << 1;
+constexpr EventFlags EF_CONTROL_DOWN = 1 << 2;
+constexpr EventFlags EF_ALT_DOWN = 1 << 3;
+// GUI Key (e.g. Command on OS X keyboards, Search on Chromebook keyboards,
+// Windows on MS-oriented keyboards)
+constexpr EventFlags EF_COMMAND_DOWN = 1 << 4;
+// Function key.
+constexpr EventFlags EF_FUNCTION_DOWN = 1 << 5;
+constexpr EventFlags EF_ALTGR_DOWN = 1 << 6;
+constexpr EventFlags EF_MOD3_DOWN = 1 << 7;
+
+// Other keyboard states.
+constexpr EventFlags EF_NUM_LOCK_ON = 1 << 8;
+constexpr EventFlags EF_CAPS_LOCK_ON = 1 << 9;
+constexpr EventFlags EF_SCROLL_LOCK_ON = 1 << 10;
+
+// Mouse buttons.
+constexpr EventFlags EF_LEFT_MOUSE_BUTTON = 1 << 11;
+constexpr EventFlags EF_MIDDLE_MOUSE_BUTTON = 1 << 12;
+constexpr EventFlags EF_RIGHT_MOUSE_BUTTON = 1 << 13;
+constexpr EventFlags EF_BACK_MOUSE_BUTTON = 1 << 14;
+constexpr EventFlags EF_FORWARD_MOUSE_BUTTON = 1 << 15;
+constexpr EventFlags EF_MOUSE_BUTTON =
+ EF_LEFT_MOUSE_BUTTON | EF_MIDDLE_MOUSE_BUTTON | EF_RIGHT_MOUSE_BUTTON |
+ EF_BACK_MOUSE_BUTTON | EF_FORWARD_MOUSE_BUTTON;
// An artificial value used to bridge platform differences.
// Many commands on Mac as Cmd+Key are the counterparts of
// Ctrl+Key on other platforms.
#if BUILDFLAG(IS_APPLE)
- EF_PLATFORM_ACCELERATOR = EF_COMMAND_DOWN,
+constexpr EventFlags EF_PLATFORM_ACCELERATOR = EF_COMMAND_DOWN;
#else
- EF_PLATFORM_ACCELERATOR = EF_CONTROL_DOWN,
+constexpr EventFlags EF_PLATFORM_ACCELERATOR = EF_CONTROL_DOWN;
#endif
-};
// Flags specific to key events.
// WARNING: If you add or remove values make sure traits for serializing these
// values are updated.
-enum KeyEventFlags {
- EF_IME_FABRICATED_KEY = 1 << 16, // Key event fabricated by the underlying
- // IME without a user action.
- // (Linux X11 only)
- EF_IS_REPEAT = 1 << 17,
- EF_FINAL = 1 << 18, // Do not remap; the event was created with
- // the desired final values.
- EF_IS_EXTENDED_KEY = 1 << 19, // Windows extended key (see WM_KEYDOWN doc)
- EF_IS_STYLUS_BUTTON = 1 << 20, // Event was generated by a stylus button
- EF_MAX_KEY_EVENT_FLAGS_VALUE = (1 << 21) - 1,
-};
+using KeyEventFlags = EventFlags;
+// Key event fabricated by the underlying IME without a user action. (Linux X11
+// only)
+constexpr KeyEventFlags EF_IME_FABRICATED_KEY = 1 << 16;
+constexpr KeyEventFlags EF_IS_REPEAT = 1 << 17;
+// Do not remap; the event was created with the desired final values.
+constexpr KeyEventFlags EF_FINAL = 1 << 18;
+// Windows extended key (see WM_KEYDOWN doc)
+constexpr KeyEventFlags EF_IS_EXTENDED_KEY = 1 << 19;
+// Event was generated by a stylus button
+constexpr KeyEventFlags EF_IS_STYLUS_BUTTON = 1 << 20;
+constexpr KeyEventFlags EF_MAX_KEY_EVENT_FLAGS_VALUE = (1 << 21) - 1;
// Flags specific to mouse events.
-enum MouseEventFlags {
- EF_IS_DOUBLE_CLICK = 1 << 16,
- EF_IS_TRIPLE_CLICK = 1 << 17,
- EF_IS_NON_CLIENT = 1 << 18,
- EF_FROM_TOUCH = 1 << 19, // Indicates this mouse event is generated
- // from an unconsumed touch/gesture event.
- EF_TOUCH_ACCESSIBILITY = 1 << 20, // Indicates this event was generated from
- // touch accessibility mode.
- EF_CURSOR_HIDE = 1 << 21, // Indicates this mouse event is generated
- // because the cursor was just hidden. This
- // can be used to update hover state.
- EF_PRECISION_SCROLLING_DELTA = // Indicates this mouse event is from high
- 1 << 22, // precision touchpad and will come with a
- // high precision delta.
- EF_SCROLL_BY_PAGE = 1 << 23, // Indicates this mouse event is generated
- // when users is requesting to scroll by
- // pages.
- EF_UNADJUSTED_MOUSE = 1 << 24, // Indicates this mouse event is unadjusted
- // mouse events that has unadjusted
- // movement delta, i.e. is from WM_INPUT
- // on Windows.
- EF_NOT_SUITABLE_FOR_MOUSE_WARPING = // Indicates this mouse event should not
- 1 << 25, // trigger mouse warping (which moves the
- // mouse to another display when the
- // mouse hits the window boundaries).
-};
+using MouseEventFlags = EventFlags;
+constexpr MouseEventFlags EF_IS_DOUBLE_CLICK = 1 << 16;
+constexpr MouseEventFlags EF_IS_TRIPLE_CLICK = 1 << 17;
+constexpr MouseEventFlags EF_IS_NON_CLIENT = 1 << 18;
+// Indicates this mouse event is generated from an unconsumed touch/gesture
+// event.
+constexpr MouseEventFlags EF_FROM_TOUCH = 1 << 19;
+// Indicates this event was generated from touch accessibility mode.
+constexpr MouseEventFlags EF_TOUCH_ACCESSIBILITY = 1 << 20;
+// Indicates this mouse event is generated because the cursor was just hidden.
+// This can be used to update hover state.
+constexpr MouseEventFlags EF_CURSOR_HIDE = 1 << 21;
+// Indicates this mouse event is from high precision touchpad and will come with
+// a high precision delta.
+constexpr MouseEventFlags EF_PRECISION_SCROLLING_DELTA = 1 << 22;
+// Indicates this mouse event is generated when users is requesting to scroll by
+// pages.
+constexpr MouseEventFlags EF_SCROLL_BY_PAGE = 1 << 23;
+// Indicates this mouse event is unadjusted mouse events that has unadjusted
+// movement delta, i.e. is from WM_INPUT on Windows.
+constexpr MouseEventFlags EF_UNADJUSTED_MOUSE = 1 << 24;
+// Indicates this mouse event should not trigger mouse warping (which moves the
+// mouse to another display when the mouse hits the window boundaries).
+constexpr MouseEventFlags EF_NOT_SUITABLE_FOR_MOUSE_WARPING = 1 << 25;
// Result of dispatching an event.
enum EventResult {
diff --git a/chromium/ui/events/event_switches.cc b/chromium/ui/events/event_switches.cc
index 477aff13462..a28b059cbba 100644
--- a/chromium/ui/events/event_switches.cc
+++ b/chromium/ui/events/event_switches.cc
@@ -14,6 +14,13 @@ namespace switches {
const char kCompensateForUnstablePinchZoom[] =
"compensate-for-unstable-pinch-zoom";
+// Overrides touch slop distance for gesture detection. The touch slop distance
+// is the maximum distance from the starting point of a touch sequence that a
+// gesture can travel before it can no longer be considered a tap. Scroll
+// gestures can only begin after this distance has been travelled. The switch
+// value is a floating point number that is interpreted as a distance in pixels.
+const char kTouchSlopDistance[] = "touch-slop-distance";
+
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
// Tells chrome to interpret events from these devices as touch events. Only
// available with XInput 2 (i.e. X server 1.8 or above). The id's of the
diff --git a/chromium/ui/events/event_switches.h b/chromium/ui/events/event_switches.h
index 158766a600e..08a45c39642 100644
--- a/chromium/ui/events/event_switches.h
+++ b/chromium/ui/events/event_switches.h
@@ -11,6 +11,7 @@
namespace switches {
EVENTS_BASE_EXPORT extern const char kCompensateForUnstablePinchZoom[];
+EVENTS_BASE_EXPORT extern const char kTouchSlopDistance[];
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
EVENTS_BASE_EXPORT extern const char kTouchDevices[];
diff --git a/chromium/ui/events/fuchsia/DIR_METADATA b/chromium/ui/events/fuchsia/DIR_METADATA
index 5b3985ecc8b..7bba048979f 100644
--- a/chromium/ui/events/fuchsia/DIR_METADATA
+++ b/chromium/ui/events/fuchsia/DIR_METADATA
@@ -7,4 +7,3 @@
# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
mixins: "//build/fuchsia/COMMON_METADATA"
-os: FUCHSIA \ No newline at end of file
diff --git a/chromium/ui/events/fuchsia/fakes/DIR_METADATA b/chromium/ui/events/fuchsia/fakes/DIR_METADATA
deleted file mode 100644
index 5b3985ecc8b..00000000000
--- a/chromium/ui/events/fuchsia/fakes/DIR_METADATA
+++ /dev/null
@@ -1,10 +0,0 @@
-# Metadata information for this directory.
-#
-# For more information on DIR_METADATA files, see:
-# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md
-#
-# For the schema of this file, see Metadata message:
-# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
-
-mixins: "//build/fuchsia/COMMON_METADATA"
-os: FUCHSIA \ No newline at end of file
diff --git a/chromium/ui/events/gesture_detection/gesture_configuration_aura.cc b/chromium/ui/events/gesture_detection/gesture_configuration_aura.cc
index 8fb64e014bd..5dabd73bc54 100644
--- a/chromium/ui/events/gesture_detection/gesture_configuration_aura.cc
+++ b/chromium/ui/events/gesture_detection/gesture_configuration_aura.cc
@@ -6,6 +6,7 @@
#include "base/command_line.h"
#include "base/memory/singleton.h"
+#include "base/strings/string_number_conversions.h"
#include "build/chromeos_buildflags.h"
#include "ui/events/event_switches.h"
@@ -32,12 +33,21 @@ class GestureConfigurationAura : public GestureConfiguration {
private:
GestureConfigurationAura() : GestureConfiguration() {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS)
// On ChromeOS, use 6 which is derived from the android's default(8),
// multiplied by base dpi ratio(0.75). See crbug.com/1083120 for more
// details.
set_max_touch_move_in_pixels_for_click(6);
#endif
+ double touch_slop_distance;
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kTouchSlopDistance) &&
+ base::StringToDouble(
+ command_line->GetSwitchValueASCII(switches::kTouchSlopDistance),
+ &touch_slop_distance)) {
+ set_max_touch_move_in_pixels_for_click(touch_slop_distance);
+ }
+
set_double_tap_enabled(kDoubleTapAuraSupport);
set_double_tap_timeout_in_ms(double_tap_timeout_in_ms());
set_gesture_begin_end_types_enabled(true);
diff --git a/chromium/ui/events/gesture_detection/gesture_detector.cc b/chromium/ui/events/gesture_detection/gesture_detector.cc
index cb9c65d1d8e..6c1d39bc1ff 100644
--- a/chromium/ui/events/gesture_detection/gesture_detector.cc
+++ b/chromium/ui/events/gesture_detection/gesture_detector.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <algorithm>
+#include <cmath>
#include "base/cxx17_backports.h"
#include "base/memory/raw_ptr.h"
diff --git a/chromium/ui/events/gestures/blink/BUILD.gn b/chromium/ui/events/gestures/blink/BUILD.gn
index 76de402ac88..d4373485671 100644
--- a/chromium/ui/events/gestures/blink/BUILD.gn
+++ b/chromium/ui/events/gestures/blink/BUILD.gn
@@ -10,7 +10,8 @@ source_set("blink") {
"web_gesture_curve_impl.h",
]
- if (is_chromecast && !is_android) {
+ # TODO(crbug.com/1314528): Should not need the is_android check.
+ if (is_castos && !is_android) {
defines = [ "USE_MOBILE_FLING_CURVE" ]
}
diff --git a/chromium/ui/events/gestures/gesture_recognizer_impl.cc b/chromium/ui/events/gestures/gesture_recognizer_impl.cc
index e48876dd7bd..8d67ff2ee57 100644
--- a/chromium/ui/events/gestures/gesture_recognizer_impl.cc
+++ b/chromium/ui/events/gestures/gesture_recognizer_impl.cc
@@ -62,7 +62,13 @@ bool RemoveValueFromMap(std::map<Key, T>* map, const Value& value) {
GestureRecognizerImpl::GestureRecognizerImpl() = default;
-GestureRecognizerImpl::~GestureRecognizerImpl() = default;
+GestureRecognizerImpl::~GestureRecognizerImpl() {
+ // The gesture recognizer impl observes the gesture providers that are owned
+ // by `consumer_gesture_provider_`. Clear `consumer_gesture_provider_`
+ // explicitly so that the notifications sent by gesture providers during
+ // destruction are handled properly.
+ consumer_gesture_provider_.clear();
+}
// Checks if this finger is already down, if so, returns the current target.
// Otherwise, returns nullptr.
diff --git a/chromium/ui/events/gestures/gesture_recognizer_impl.h b/chromium/ui/events/gestures/gesture_recognizer_impl.h
index d03d63889f4..fa757fbac6d 100644
--- a/chromium/ui/events/gestures/gesture_recognizer_impl.h
+++ b/chromium/ui/events/gestures/gesture_recognizer_impl.h
@@ -21,6 +21,8 @@
namespace aura::test {
FORWARD_DECLARE_TEST(GestureRecognizerTest,
DestroyGestureProviderAuraBeforeAck);
+FORWARD_DECLARE_TEST(GestureRecognizerTest,
+ ResetGestureRecognizerWithGestureProvider);
} // namespace aura::test
namespace ui {
@@ -83,6 +85,8 @@ class EVENTS_EXPORT GestureRecognizerImpl : public GestureRecognizer,
private:
FRIEND_TEST_ALL_PREFIXES(aura::test::GestureRecognizerTest,
DestroyGestureProviderAuraBeforeAck);
+ FRIEND_TEST_ALL_PREFIXES(aura::test::GestureRecognizerTest,
+ ResetGestureRecognizerWithGestureProvider);
// Sets up the target consumer for gestures based on the touch-event.
void SetupTargets(const TouchEvent& event, GestureConsumer* consumer);
diff --git a/chromium/ui/events/gestures/physics_based_fling_curve.cc b/chromium/ui/events/gestures/physics_based_fling_curve.cc
index 448edd0b88c..eb437935398 100644
--- a/chromium/ui/events/gestures/physics_based_fling_curve.cc
+++ b/chromium/ui/events/gestures/physics_based_fling_curve.cc
@@ -7,6 +7,8 @@
#include <algorithm>
#include <cmath>
+#include "base/check.h"
+
namespace {
// These constants are defined based on UX experiment.
diff --git a/chromium/ui/events/keycodes/DEPS b/chromium/ui/events/keycodes/DEPS
index d974f6c24be..4feb273fdab 100644
--- a/chromium/ui/events/keycodes/DEPS
+++ b/chromium/ui/events/keycodes/DEPS
@@ -7,8 +7,19 @@ include_rules = [
"-third_party",
"-ui",
- "+third_party/abseil-cpp/absl",
"+ui/base/buildflags.h", # Doesn't bring in all of UI.
"+ui/gfx/x",
"+ui/events",
+
+ # Abseil features must be allowlisted explicitly for now. See
+ # //styleguide/c++/c++11.html. Allowed features' headers will be listed
+ # explicitly here.
+ # Please keep this section in sync with //DEPS.
+ '-absl',
+ '-third_party/abseil-cpp',
+ '+third_party/abseil-cpp/absl/base/attributes.h',
+ "+third_party/abseil-cpp/absl/numeric/int128.h",
+ '+third_party/abseil-cpp/absl/types/optional.h',
+ '+third_party/abseil-cpp/absl/types/variant.h',
+ '+third_party/abseil-cpp/absl/utility/utility.h',
]
diff --git a/chromium/ui/events/keycodes/dom/keycode_converter.cc b/chromium/ui/events/keycodes/dom/keycode_converter.cc
index 88486fca8ba..d0f8c2abc91 100644
--- a/chromium/ui/events/keycodes/dom/keycode_converter.cc
+++ b/chromium/ui/events/keycodes/dom/keycode_converter.cc
@@ -338,7 +338,7 @@ DomKey KeycodeConverter::KeyStringToDomKey(base::StringPiece key) {
// the key value is that character.
const auto key_length = static_cast<int32_t>(key.length());
int32_t char_index = 0;
- uint32_t character;
+ base_icu::UChar32 character;
if (base::ReadUnicodeCharacter(key.data(), key_length, &char_index,
&character) &&
++char_index == key_length) {
diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_mac.h b/chromium/ui/events/keycodes/keyboard_code_conversion_mac.h
index a2246bc5460..0ee3b9a0093 100644
--- a/chromium/ui/events/keycodes/keyboard_code_conversion_mac.h
+++ b/chromium/ui/events/keycodes/keyboard_code_conversion_mac.h
@@ -20,10 +20,10 @@ enum class DomCode;
// including unit tests. But Mac uses a different set of virtual keycodes.
// This function converts a windows virtual keycode into Mac's virtual key code
// and corresponding unicode character. |flags| is the Cocoa modifiers mask
-// such as NSControlKeyMask, NSShiftKeyMask, etc.
+// such as NSEventModifierFlagControl, NSEventModifierFlagShift, etc.
// When success, the corresponding Mac's virtual key code will be returned.
// |keyboard_character| is the corresponding keyboard character, suitable for
-// use in -[NSEvent characters]. If NSShiftKeyMask appears in |flags|,
+// use in -[NSEvent characters]. If NSEventModifierFlagShift appears in |flags|,
// |us_keyboard_shifted_character| is |keyboard_character| with a shift modifier
// applied using a US keyboard layout (otherwise unmodified).
// |us_keyboard_shifted_character| is suitable for -[NSEvent
diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm b/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm
index 0b53a810806..daf208147ae 100644
--- a/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm
+++ b/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm
@@ -221,9 +221,9 @@ const KeyCodeMap kKeyCodesMap[] = {
bool IsKeypadOrNumericKeyEvent(NSEvent* event) {
// Check that this is the type of event that has a keyCode.
switch ([event type]) {
- case NSKeyDown:
- case NSKeyUp:
- case NSFlagsChanged:
+ case NSEventTypeKeyDown:
+ case NSEventTypeKeyUp:
+ case NSEventTypeFlagsChanged:
break;
default:
return false;
@@ -533,15 +533,15 @@ UniChar MacKeycodeAndModifiersToCharacter(unsigned short mac_keycode,
// Convert NSEvent modifiers to format UCKeyTranslate accepts. See docs
// on UCKeyTranslate for more info.
int unicode_modifiers = 0;
- if (modifiers & NSShiftKeyMask)
+ if (modifiers & NSEventModifierFlagShift)
unicode_modifiers |= shiftKey;
- if (modifiers & NSAlphaShiftKeyMask)
+ if (modifiers & NSEventModifierFlagCapsLock)
unicode_modifiers |= alphaLock;
- // if (modifiers & NSControlKeyMask)
+ // if (modifiers & NSEventModifierFlagControl)
// unicode_modifiers |= controlKey;
- if (modifiers & NSAlternateKeyMask)
+ if (modifiers & NSEventModifierFlagOption)
unicode_modifiers |= optionKey;
- // if (modifiers & NSCommandKeyMask)
+ // if (modifiers & NSEventModifierFlagCommand)
// unicode_modifiers |= cmdKey;
UInt32 modifier_key_state = (unicode_modifiers >> 8) & 0xFF;
@@ -570,7 +570,7 @@ int MacKeyCodeForWindowsKeyCode(KeyboardCode keycode,
unichar* keyboard_character) {
// In release code, |flags| is used to lookup accelerators, so logic to handle
// caps lock properly isn't implemented.
- DCHECK_EQ(0u, flags & NSAlphaShiftKeyMask);
+ DCHECK_EQ(0u, flags & NSEventModifierFlagCapsLock);
KeyCodeMap from;
from.keycode = keycode;
@@ -592,7 +592,7 @@ int MacKeyCodeForWindowsKeyCode(KeyboardCode keycode,
*us_keyboard_shifted_character = ptr->characterIgnoringAllModifiers;
// Fill in |us_keyboard_shifted_character| according to flags.
- if (flags & NSShiftKeyMask) {
+ if (flags & NSEventModifierFlagShift) {
if (keycode >= VKEY_0 && keycode <= VKEY_9) {
*us_keyboard_shifted_character =
kShiftCharsForNumberKeys[keycode - VKEY_0];
@@ -787,7 +787,8 @@ KeyboardCode KeyboardCodeFromNSEvent(NSEvent* event) {
// Numeric keys 0-9 should always return |keyCode| 0-9.
// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode#Printable_keys_in_standard_position
if (!IsKeypadOrNumericKeyEvent(event) &&
- ([event type] == NSKeyDown || [event type] == NSKeyUp)) {
+ ([event type] == NSEventTypeKeyDown ||
+ [event type] == NSEventTypeKeyUp)) {
// Handles Dvorak-QWERTY Cmd case.
// https://github.com/WebKit/webkit/blob/4d41c98b1de467f5d2a8fcba84d7c5268f11b0cc/Source/WebCore/platform/mac/PlatformEventFactoryMac.mm#L329
NSString* characters = [event characters];
@@ -831,7 +832,7 @@ DomKey DomKeyFromNSEvent(NSEvent* event) {
// Apply the lookup based on the character first since that has the
// Keyboard layout and modifiers already applied; whereas the keyCode
// doesn't.
- if ([event type] == NSKeyDown || [event type] == NSKeyUp) {
+ if ([event type] == NSEventTypeKeyDown || [event type] == NSEventTypeKeyUp) {
// Cannot use [event characters] to check whether it's a dead key, because
// KeyUp event has the character form of the dead key in [event characters].
bool is_dead_key = false;
@@ -860,8 +861,9 @@ DomKey DomKeyFromNSEvent(NSEvent* event) {
// Unicode 'Other, Control' General Category.
// https://w3c.github.io/uievents-key/#selecting-key-attribute-values
bool unused_is_dead_key;
- const int kAllowedModifiersMask =
- NSShiftKeyMask | NSAlphaShiftKeyMask | NSAlternateKeyMask;
+ const int kAllowedModifiersMask = NSEventModifierFlagShift |
+ NSEventModifierFlagCapsLock |
+ NSEventModifierFlagOption;
// MacKeycodeAndModifiersToCharacter() is efficient (around 6E-4 ms).
dom_key_char = MacKeycodeAndModifiersToCharacter(
[event keyCode], [event modifierFlags] & kAllowedModifiersMask,
diff --git a/chromium/ui/events/mobile_scroller.cc b/chromium/ui/events/mobile_scroller.cc
index 039eabd3104..701963bffd7 100644
--- a/chromium/ui/events/mobile_scroller.cc
+++ b/chromium/ui/events/mobile_scroller.cc
@@ -75,7 +75,7 @@ struct SplineConstants {
float x_min = 0.0f;
float y_min = 0.0f;
for (int i = 0; i < NUM_SAMPLES; i++) {
- const float alpha = static_cast<float>(i) / NUM_SAMPLES;
+ const float alpha = i / float{NUM_SAMPLES};
float x_max = 1.0f;
float x, tx, coef;
@@ -118,10 +118,10 @@ struct SplineConstants {
float* velocity_coef) {
*distance_coef = 1.f;
*velocity_coef = 0.f;
- const int index = static_cast<int>(NUM_SAMPLES * t);
+ const int index = base::ClampFloor(float{NUM_SAMPLES} * t);
if (index < NUM_SAMPLES) {
- const float t_inf = static_cast<float>(index) / NUM_SAMPLES;
- const float t_sup = static_cast<float>(index + 1) / NUM_SAMPLES;
+ const float t_inf = index / float{NUM_SAMPLES};
+ const float t_sup = (index + 1) / float{NUM_SAMPLES};
const float d_inf = spline_position_[index];
const float d_sup = spline_position_[index + 1];
*velocity_coef = (d_sup - d_inf) / (t_sup - t_inf);
diff --git a/chromium/ui/events/ozone/device/device_event.cc b/chromium/ui/events/ozone/device/device_event.cc
index e20079a79cf..7303803a08b 100644
--- a/chromium/ui/events/ozone/device/device_event.cc
+++ b/chromium/ui/events/ozone/device/device_event.cc
@@ -8,9 +8,13 @@ namespace ui {
DeviceEvent::DeviceEvent(DeviceType type,
ActionType action,
- const base::FilePath& path)
+ const base::FilePath& path,
+ const PropertyMap& property_map)
: device_type_(type),
action_type_(action),
- path_(path) {}
+ path_(path),
+ properties_(property_map) {}
+
+DeviceEvent::~DeviceEvent() = default;
} // namespace ui
diff --git a/chromium/ui/events/ozone/device/device_event.h b/chromium/ui/events/ozone/device/device_event.h
index c2d6618943e..14f45f8e3de 100644
--- a/chromium/ui/events/ozone/device/device_event.h
+++ b/chromium/ui/events/ozone/device/device_event.h
@@ -6,9 +6,15 @@
#define UI_EVENTS_OZONE_DEVICE_DEVICE_EVENT_H_
#include "base/component_export.h"
+#include "base/containers/flat_map.h"
#include "base/files/file_path.h"
namespace ui {
+namespace {
+
+using PropertyMap = base::flat_map<std::string, std::string>;
+
+} // namespace
class COMPONENT_EXPORT(EVENTS_OZONE) DeviceEvent {
public:
@@ -23,19 +29,25 @@ class COMPONENT_EXPORT(EVENTS_OZONE) DeviceEvent {
CHANGE,
};
- DeviceEvent(DeviceType type, ActionType action, const base::FilePath& path);
+ DeviceEvent(DeviceType type,
+ ActionType action,
+ const base::FilePath& path,
+ const PropertyMap& property_map = PropertyMap());
DeviceEvent(const DeviceEvent&) = delete;
DeviceEvent& operator=(const DeviceEvent&) = delete;
+ ~DeviceEvent();
DeviceType device_type() const { return device_type_; }
ActionType action_type() const { return action_type_; }
base::FilePath path() const { return path_; }
+ const PropertyMap properties() const { return properties_; }
private:
DeviceType device_type_;
ActionType action_type_;
base::FilePath path_;
+ const PropertyMap properties_;
};
} // namespace ui
diff --git a/chromium/ui/events/ozone/device/udev/device_manager_udev.cc b/chromium/ui/events/ozone/device/udev/device_manager_udev.cc
index e3e2132d7c9..8deeea25a02 100644
--- a/chromium/ui/events/ozone/device/udev/device_manager_udev.cc
+++ b/chromium/ui/events/ozone/device/udev/device_manager_udev.cc
@@ -5,12 +5,15 @@
#include "ui/events/ozone/device/udev/device_manager_udev.h"
#include <stddef.h>
+#include <string>
#include "base/logging.h"
#include "base/observer_list.h"
#include "base/strings/stringprintf.h"
#include "base/task/current_thread.h"
#include "base/trace_event/trace_event.h"
+#include "device/udev_linux/udev.h"
+#include "device/udev_linux/udev_loader.h"
#include "ui/events/ozone/device/device_event.h"
#include "ui/events/ozone/device/device_event_observer.h"
@@ -159,10 +162,8 @@ void DeviceManagerUdev::OnFileCanWriteWithoutBlocking(int fd) {
std::unique_ptr<DeviceEvent> DeviceManagerUdev::ProcessMessage(
udev_device* device) {
const char* path = device::udev_device_get_devnode(device);
- const char* action = device::udev_device_get_action(device);
const char* subsystem =
device::udev_device_get_property_value(device, "SUBSYSTEM");
-
if (!path || !subsystem)
return nullptr;
@@ -177,6 +178,7 @@ std::unique_ptr<DeviceEvent> DeviceManagerUdev::ProcessMessage(
else
return nullptr;
+ const char* action = device::udev_device_get_action(device);
DeviceEvent::ActionType action_type;
if (!action || !strcmp(action, "add"))
action_type = DeviceEvent::ADD;
@@ -187,8 +189,19 @@ std::unique_ptr<DeviceEvent> DeviceManagerUdev::ProcessMessage(
else
return nullptr;
+ PropertyMap property_map;
+ udev_list_entry* property_list =
+ device::udev_device_get_properties_list_entry(device);
+ udev_list_entry* entry;
+ udev_list_entry_foreach(entry, property_list) {
+ const std::string key(device::udev_list_entry_get_name(entry));
+ const std::string value(
+ device::udev_device_get_property_value(device, key.c_str()));
+ property_map.insert({key, value});
+ }
+
return std::make_unique<DeviceEvent>(device_type, action_type,
- base::FilePath(path));
+ base::FilePath(path), property_map);
}
} // namespace ui
diff --git a/chromium/ui/events/ozone/evdev/BUILD.gn b/chromium/ui/events/ozone/evdev/BUILD.gn
index b54cd8da6d9..ffb0749e886 100644
--- a/chromium/ui/events/ozone/evdev/BUILD.gn
+++ b/chromium/ui/events/ozone/evdev/BUILD.gn
@@ -65,12 +65,17 @@ component("evdev") {
"input_device_factory_evdev.h",
"input_device_factory_evdev_proxy.cc",
"input_device_factory_evdev_proxy.h",
+ "input_device_opener.h",
+ "input_device_opener_evdev.cc",
+ "input_device_opener_evdev.h",
"input_device_settings_evdev.cc",
"input_device_settings_evdev.h",
"input_injector_evdev.cc",
"input_injector_evdev.h",
"keyboard_evdev.cc",
"keyboard_evdev.h",
+ "keyboard_imposter_checker_evdev.cc",
+ "keyboard_imposter_checker_evdev.h",
"microphone_mute_switch_event_converter_evdev.cc",
"microphone_mute_switch_event_converter_evdev.h",
"mouse_button_map_evdev.cc",
@@ -109,6 +114,8 @@ component("evdev") {
"touch_filter/palm_detection_filter_factory.h",
"touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.cc",
"touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.h",
+ "touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.cc",
+ "touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.h",
"touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.cc",
"touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.h",
"touch_filter/palm_model/onedevice_train_palm_detection_filter_model.cc",
@@ -137,6 +144,8 @@ component("evdev") {
if (is_chromeos_ash) {
sources += [
+ "fake_keyboard_heuristic_metrics.cc",
+ "fake_keyboard_heuristic_metrics.h",
"numberpad_metrics.cc",
"numberpad_metrics.h",
]
@@ -193,8 +202,10 @@ component("evdev") {
}
source_set("event_device_info") {
- public = [ "event_device_info.h" ]
- sources = [ "event_device_info.cc" ]
+ sources = [
+ "event_device_info.cc",
+ "event_device_info.h",
+ ]
deps = [
"//base",
@@ -237,6 +248,7 @@ source_set("unittests") {
"event_factory_evdev_unittest.cc",
"gamepad_event_converter_evdev_unittest.cc",
"input_controller_evdev_unittest.cc",
+ "input_device_factory_evdev_unittest.cc",
"input_injector_evdev_unittest.cc",
"libgestures_glue/haptic_touchpad_handler.cc",
"libgestures_glue/haptic_touchpad_handler.h",
diff --git a/chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.h b/chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.h
index b4d8e1d6b34..0b4f26aaa61 100644
--- a/chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.h
+++ b/chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.h
@@ -196,7 +196,8 @@ class COMPONENT_EXPORT(EVDEV) DeviceEventDispatcherEvdev {
// Device lifecycle events.
virtual void DispatchKeyboardDevicesUpdated(
- const std::vector<InputDevice>& devices) = 0;
+ const std::vector<InputDevice>& devices,
+ base::flat_map<int, std::vector<uint64_t>> key_bits_mapping) = 0;
virtual void DispatchTouchscreenDevicesUpdated(
const std::vector<TouchscreenDevice>& devices) = 0;
virtual void DispatchMouseDevicesUpdated(
@@ -209,7 +210,8 @@ class COMPONENT_EXPORT(EVDEV) DeviceEventDispatcherEvdev {
virtual void DispatchDeviceListsComplete() = 0;
virtual void DispatchStylusStateChanged(StylusState stylus_state) = 0;
virtual void DispatchGamepadDevicesUpdated(
- const std::vector<GamepadDevice>& devices) = 0;
+ const std::vector<GamepadDevice>& devices,
+ base::flat_map<int, std::vector<uint64_t>> key_bits_mapping) = 0;
virtual void DispatchUncategorizedDevicesUpdated(
const std::vector<InputDevice>& devices) = 0;
};
diff --git a/chromium/ui/events/ozone/evdev/event_converter_evdev.cc b/chromium/ui/events/ozone/evdev/event_converter_evdev.cc
index 84dd3e7864c..a5bf68079af 100644
--- a/chromium/ui/events/ozone/evdev/event_converter_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/event_converter_evdev.cc
@@ -83,6 +83,14 @@ bool EventConverterEvdev::IsEnabled() const {
return input_device_.enabled;
}
+void EventConverterEvdev::SetSuspectedImposter(bool is_suspected) {
+ input_device_.suspected_imposter = is_suspected;
+}
+
+bool EventConverterEvdev::IsSuspectedImposter() const {
+ return input_device_.suspected_imposter;
+}
+
void EventConverterEvdev::OnStopped() {}
void EventConverterEvdev::OnEnabled() {}
@@ -95,6 +103,10 @@ void EventConverterEvdev::OnFileCanWriteWithoutBlocking(int fd) {
NOTREACHED();
}
+KeyboardType EventConverterEvdev::GetKeyboardType() const {
+ return KeyboardType::NOT_KEYBOARD;
+}
+
bool EventConverterEvdev::HasKeyboard() const {
return false;
}
@@ -156,6 +168,11 @@ bool EventConverterEvdev::GetGamepadRumbleCapability() const {
return false;
}
+std::vector<uint64_t> EventConverterEvdev::GetGamepadKeyBits() const {
+ NOTREACHED();
+ return std::vector<uint64_t>();
+}
+
void EventConverterEvdev::PlayVibrationEffect(uint8_t amplitude,
uint16_t duration_millis) {
NOTREACHED();
@@ -225,6 +242,13 @@ void EventConverterEvdev::SetReportStylusStateCallback(
void EventConverterEvdev::SetGetLatestStylusStateCallback(
const GetLatestStylusStateCallback& callback) {}
+void EventConverterEvdev::SetReceivedValidInputCallback(
+ ReceivedValidInputCallback callback) {}
+
+std::vector<uint64_t> EventConverterEvdev::GetKeyboardKeyBits() const {
+ return std::vector<uint64_t>();
+}
+
base::TimeTicks EventConverterEvdev::TimeTicksFromInputEvent(
const input_event& event) {
base::TimeTicks timestamp =
diff --git a/chromium/ui/events/ozone/evdev/event_converter_evdev.h b/chromium/ui/events/ozone/evdev/event_converter_evdev.h
index 7d31dc8feac..8c9ee759ba7 100644
--- a/chromium/ui/events/ozone/evdev/event_converter_evdev.h
+++ b/chromium/ui/events/ozone/evdev/event_converter_evdev.h
@@ -19,6 +19,7 @@
#include "ui/events/devices/haptic_touchpad_effects.h"
#include "ui/events/devices/input_device.h"
#include "ui/events/devices/stylus_state.h"
+#include "ui/events/ozone/evdev/event_device_info.h"
#include "ui/events/ozone/evdev/event_dispatch_callback.h"
#include "ui/events/ozone/evdev/touch_evdev_types.h"
#include "ui/gfx/geometry/size.h"
@@ -41,6 +42,9 @@ class COMPONENT_EXPORT(EVDEV) EventConverterEvdev
using GetLatestStylusStateCallback =
base::RepeatingCallback<void(const InProgressStylusState**)>;
+ using ReceivedValidInputCallback =
+ base::RepeatingCallback<void(const EventConverterEvdev* converter)>;
+
EventConverterEvdev(int fd,
const base::FilePath& path,
int id,
@@ -80,6 +84,12 @@ class COMPONENT_EXPORT(EVDEV) EventConverterEvdev
bool IsEnabled() const;
+ // Flag this device as being suspected for identifying as a device that it is
+ // not.
+ void SetSuspectedImposter(bool is_suspected);
+
+ bool IsSuspectedImposter() const;
+
// Cleanup after we stop reading events (release buttons, etc).
virtual void OnStopped();
@@ -92,6 +102,10 @@ class COMPONENT_EXPORT(EVDEV) EventConverterEvdev
// Dump recent events into a file.
virtual void DumpTouchEventLog(const char* filename);
+ // Returns value corresponding to keyboard status (No Keyboard, Keyboard in
+ // Blocklist, ect.).
+ virtual KeyboardType GetKeyboardType() const;
+
// Returns true if the converter is used for a keyboard device.
virtual bool HasKeyboard() const;
@@ -146,6 +160,9 @@ class COMPONENT_EXPORT(EVDEV) EventConverterEvdev
// Returns whether the gamepad device supports rumble type force feedback.
virtual bool GetGamepadRumbleCapability() const;
+ // Returns supported key bits of the gamepad.
+ virtual std::vector<uint64_t> GetGamepadKeyBits() const;
+
// Sets which keyboard keys should be processed. If |enable_filter| is
// false, all keys are allowed and |allowed_keys| is ignored.
virtual void SetKeyFilter(bool enable_filter,
@@ -169,6 +186,13 @@ class COMPONENT_EXPORT(EVDEV) EventConverterEvdev
virtual void SetGetLatestStylusStateCallback(
const GetLatestStylusStateCallback& callback);
+ // Set callback to trigger keyboard device update.
+ virtual void SetReceivedValidInputCallback(
+ ReceivedValidInputCallback callback);
+
+ // Returns supported key bits of the keyboard.
+ virtual std::vector<uint64_t> GetKeyboardKeyBits() const;
+
// Helper to generate a base::TimeTicks from an input_event's time
static base::TimeTicks TimeTicksFromInputEvent(const input_event& event);
diff --git a/chromium/ui/events/ozone/evdev/event_converter_evdev_impl.cc b/chromium/ui/events/ozone/evdev/event_converter_evdev_impl.cc
index c2df3597633..60835c6af80 100644
--- a/chromium/ui/events/ozone/evdev/event_converter_evdev_impl.cc
+++ b/chromium/ui/events/ozone/evdev/event_converter_evdev_impl.cc
@@ -53,7 +53,7 @@ EventConverterEvdevImpl::EventConverterEvdevImpl(
devinfo.product_id(),
devinfo.version()),
input_device_fd_(std::move(fd)),
- has_keyboard_(devinfo.HasKeyboard()),
+ keyboard_type_(devinfo.GetKeyboardType()),
has_touchpad_(devinfo.HasTouchpad()),
has_numberpad_(devinfo.HasNumberpad()),
has_stylus_switch_(devinfo.HasStylusSwitch()),
@@ -65,6 +65,14 @@ EventConverterEvdevImpl::EventConverterEvdevImpl(
if (has_numberpad_)
NumberpadMetricsRecorder::GetInstance()->AddDevice(input_device_);
#endif
+ // Converts unsigned long to uint64_t.
+ const auto key_bits = devinfo.GetKeyBits();
+ key_bits_.resize(key_bits.size());
+ for (int i = 0; i < KEY_CNT; i++) {
+ if (EvdevBitIsSet(key_bits.data(), i)) {
+ EvdevSetUint64Bit(key_bits_.data(), i);
+ }
+ }
}
EventConverterEvdevImpl::~EventConverterEvdevImpl() {
@@ -96,8 +104,12 @@ void EventConverterEvdevImpl::OnFileCanReadWithoutBlocking(int fd) {
ProcessEvents(inputs, read_size / sizeof(*inputs));
}
+KeyboardType EventConverterEvdevImpl::GetKeyboardType() const {
+ return keyboard_type_;
+}
+
bool EventConverterEvdevImpl::HasKeyboard() const {
- return has_keyboard_;
+ return keyboard_type_ == KeyboardType::VALID_KEYBOARD;
}
bool EventConverterEvdevImpl::HasTouchpad() const {
@@ -137,6 +149,10 @@ void EventConverterEvdevImpl::OnDisabled() {
ReleaseMouseButtons();
}
+std::vector<uint64_t> EventConverterEvdevImpl::GetKeyboardKeyBits() const {
+ return key_bits_;
+}
+
ui::StylusState EventConverterEvdevImpl::GetStylusSwitchState() {
if (!HasStylusSwitch()) {
return ui::StylusState::REMOVED;
@@ -234,6 +250,20 @@ void EventConverterEvdevImpl::OnKeyChange(unsigned int key,
GenerateKeyMetrics(key, down);
+ // Checks for a key press that could only have occurred from a non-imposter
+ // keyboard. Disables Imposter flag and triggers a callback which will update
+ // the dispatched list of keyboards with this new information.
+ if (key_state_.count() == 1 && ((key >= KEY_1 && key <= KEY_EQUAL) ||
+ (key >= KEY_Q && key <= KEY_RIGHTBRACE) ||
+ (key <= KEY_A && key >= KEY_APOSTROPHE) ||
+ (key >= KEY_BACKSLASH && key <= KEY_SLASH))) {
+ bool was_suspected = IsSuspectedImposter();
+ SetSuspectedImposter(false);
+ if (was_suspected && received_valid_input_callback_) {
+ received_valid_input_callback_.Run(this);
+ }
+ }
+
dispatcher_->DispatchKeyEvent(
KeyEventParams(input_device_.id, ui::EF_NONE, key, last_scan_code_, down,
false /* suppress_auto_repeat */, timestamp));
@@ -295,6 +325,11 @@ void EventConverterEvdevImpl::OnButtonChange(int code,
timestamp));
}
+void EventConverterEvdevImpl::SetReceivedValidInputCallback(
+ ReceivedValidInputCallback callback) {
+ received_valid_input_callback_ = callback;
+}
+
void EventConverterEvdevImpl::FlushEvents(const input_event& input) {
if (!cursor_ || (x_offset_ == 0 && y_offset_ == 0))
return;
diff --git a/chromium/ui/events/ozone/evdev/event_converter_evdev_impl.h b/chromium/ui/events/ozone/evdev/event_converter_evdev_impl.h
index e1604a132fc..12c4e37f64e 100644
--- a/chromium/ui/events/ozone/evdev/event_converter_evdev_impl.h
+++ b/chromium/ui/events/ozone/evdev/event_converter_evdev_impl.h
@@ -45,6 +45,7 @@ class COMPONENT_EXPORT(EVDEV) EventConverterEvdevImpl
// EventConverterEvdev:
void OnFileCanReadWithoutBlocking(int fd) override;
+ KeyboardType GetKeyboardType() const override;
bool HasKeyboard() const override;
bool HasTouchpad() const override;
bool HasCapsLockLed() const override;
@@ -53,6 +54,7 @@ class COMPONENT_EXPORT(EVDEV) EventConverterEvdevImpl
void SetKeyFilter(bool enable_filter,
std::vector<DomCode> allowed_keys) override;
void OnDisabled() override;
+ std::vector<uint64_t> GetKeyboardKeyBits() const override;
void ProcessEvents(const struct input_event* inputs, int count);
@@ -75,11 +77,18 @@ class COMPONENT_EXPORT(EVDEV) EventConverterEvdevImpl
// non-axis-aligned movement properly.
void FlushEvents(const input_event& input);
+ // Sets Callback to enable refreshing keyboard list after
+ // a valid input is initially received
+ void SetReceivedValidInputCallback(
+ ReceivedValidInputCallback callback) override;
+
// Input device file descriptor.
const base::ScopedFD input_device_fd_;
+ // KeyboardType
+ KeyboardType keyboard_type_;
+
// Input modalities for this device.
- bool has_keyboard_;
bool has_touchpad_;
bool has_numberpad_;
bool has_stylus_switch_;
@@ -116,6 +125,12 @@ class COMPONENT_EXPORT(EVDEV) EventConverterEvdevImpl
// Callbacks for dispatching events.
DeviceEventDispatcherEvdev* const dispatcher_;
+
+ // Callback to update keyboard devices when valid input is received.
+ ReceivedValidInputCallback received_valid_input_callback_;
+
+ // Supported keyboard key bits.
+ std::vector<uint64_t> key_bits_;
};
} // namespace ui
diff --git a/chromium/ui/events/ozone/evdev/event_converter_evdev_impl_unittest.cc b/chromium/ui/events/ozone/evdev/event_converter_evdev_impl_unittest.cc
index ec9a2142ea9..0ceac82f6cd 100644
--- a/chromium/ui/events/ozone/evdev/event_converter_evdev_impl_unittest.cc
+++ b/chromium/ui/events/ozone/evdev/event_converter_evdev_impl_unittest.cc
@@ -18,6 +18,7 @@
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/events/ozone/device/device_manager.h"
#include "ui/events/ozone/evdev/event_converter_test_util.h"
+#include "ui/events/ozone/evdev/event_device_test_util.h"
#include "ui/events/ozone/evdev/event_factory_evdev.h"
#include "ui/events/ozone/evdev/keyboard_evdev.h"
#include "ui/events/ozone/evdev/testing/fake_cursor_delegate_evdev.h"
@@ -31,12 +32,13 @@ const char kTestDevicePath[] = "/dev/input/test-device";
class MockEventConverterEvdevImpl : public EventConverterEvdevImpl {
public:
MockEventConverterEvdevImpl(base::ScopedFD fd,
+ const ui::EventDeviceInfo& info,
CursorDelegateEvdev* cursor,
DeviceEventDispatcherEvdev* dispatcher)
: EventConverterEvdevImpl(std::move(fd),
base::FilePath(kTestDevicePath),
1,
- EventDeviceInfo(),
+ info,
cursor,
dispatcher) {
SetEnabled(true);
@@ -65,7 +67,16 @@ class EventConverterEvdevImplTest : public testing::Test {
delete;
// Overridden from testing::Test:
- void SetUp() override {
+ void SetUp() override { SetUpDevice(ui::EventDeviceInfo()); }
+
+ void TearDown() override {
+ device_.reset();
+ cursor_.reset();
+ events_out_.reset();
+ test_clock_.reset();
+ }
+
+ void SetUpDevice(const ui::EventDeviceInfo& info) {
// Set up pipe to satisfy message pump (unused).
int evdev_io[2];
if (pipe(evdev_io))
@@ -84,18 +95,10 @@ class EventConverterEvdevImplTest : public testing::Test {
dispatcher_ =
ui::CreateDeviceEventDispatcherEvdevForTest(event_factory_.get());
device_ = std::make_unique<ui::MockEventConverterEvdevImpl>(
- std::move(events_in), cursor_.get(), dispatcher_.get());
-
+ std::move(events_in), info, cursor_.get(), dispatcher_.get());
test_clock_ = std::make_unique<ui::test::ScopedEventTestTickClock>();
}
- void TearDown() override {
- device_.reset();
- cursor_.reset();
- events_out_.reset();
- test_clock_.reset();
- }
-
ui::FakeCursorDelegateEvdev* cursor() { return cursor_.get(); }
ui::MockEventConverterEvdevImpl* device() { return device_.get(); }
@@ -148,6 +151,21 @@ class EventConverterEvdevImplTest : public testing::Test {
base::ScopedFD events_out_;
};
+// Test fixture which defers device set up, tests need to call SetUpDevice().
+class DeferDeviceSetUpEventConverterEvdevImplTest
+ : public EventConverterEvdevImplTest {
+ public:
+ DeferDeviceSetUpEventConverterEvdevImplTest() = default;
+
+ DeferDeviceSetUpEventConverterEvdevImplTest(
+ const DeferDeviceSetUpEventConverterEvdevImplTest&) = delete;
+ DeferDeviceSetUpEventConverterEvdevImplTest& operator=(
+ const DeferDeviceSetUpEventConverterEvdevImplTest&) = delete;
+
+ // Overridden from EventConverterEvdevImplTest:
+ void SetUp() override {}
+};
+
TEST_F(EventConverterEvdevImplTest, KeyPress) {
ui::MockEventConverterEvdevImpl* dev = device();
@@ -750,3 +768,17 @@ TEST_F(EventConverterEvdevImplTest, ShouldSwapMouseButtonsFromUserPreference) {
EXPECT_EQ(ui::ET_MOUSE_RELEASED, event->type());
EXPECT_EQ(true, event->IsLeftMouseButton());
}
+
+TEST_F(DeferDeviceSetUpEventConverterEvdevImplTest, KeyboardHasKeys) {
+ ui::EventDeviceInfo devinfo;
+ CapabilitiesToDeviceInfo(ui::kLogitechKeyboardK120, &devinfo);
+ SetUpDevice(devinfo);
+ ui::MockEventConverterEvdevImpl* dev = device();
+
+ const std::vector<uint64_t> key_bits = dev->GetKeyboardKeyBits();
+
+ // KEY_A should be supported.
+ EXPECT_TRUE(ui::EvdevBitUint64IsSet(key_bits.data(), 30));
+ // BTN_A shouldn't be supported.
+ EXPECT_FALSE(ui::EvdevBitUint64IsSet(key_bits.data(), 305));
+}
diff --git a/chromium/ui/events/ozone/evdev/event_converter_test_util.cc b/chromium/ui/events/ozone/evdev/event_converter_test_util.cc
index 2ccc123cdb7..604e07d386e 100644
--- a/chromium/ui/events/ozone/evdev/event_converter_test_util.cc
+++ b/chromium/ui/events/ozone/evdev/event_converter_test_util.cc
@@ -67,8 +67,10 @@ class TestDeviceEventDispatcherEvdev : public DeviceEventDispatcherEvdev {
}
void DispatchKeyboardDevicesUpdated(
- const std::vector<InputDevice>& devices) override {
- event_factory_evdev_->DispatchKeyboardDevicesUpdated(devices);
+ const std::vector<InputDevice>& devices,
+ base::flat_map<int, std::vector<uint64_t>> key_bits_mapping) override {
+ event_factory_evdev_->DispatchKeyboardDevicesUpdated(devices,
+ key_bits_mapping);
}
void DispatchTouchscreenDevicesUpdated(
const std::vector<TouchscreenDevice>& devices) override {
@@ -101,8 +103,10 @@ class TestDeviceEventDispatcherEvdev : public DeviceEventDispatcherEvdev {
}
void DispatchGamepadDevicesUpdated(
- const std::vector<GamepadDevice>& devices) override {
- event_factory_evdev_->DispatchGamepadDevicesUpdated(devices);
+ const std::vector<GamepadDevice>& devices,
+ base::flat_map<int, std::vector<uint64_t>> key_bits_mapping) override {
+ event_factory_evdev_->DispatchGamepadDevicesUpdated(devices,
+ key_bits_mapping);
}
private:
diff --git a/chromium/ui/events/ozone/evdev/event_device_info.cc b/chromium/ui/events/ozone/evdev/event_device_info.cc
index 96dca421c65..d728dba3a3e 100644
--- a/chromium/ui/events/ozone/evdev/event_device_info.cc
+++ b/chromium/ui/events/ozone/evdev/event_device_info.cc
@@ -8,6 +8,7 @@
#include <cstring>
+#include "base/containers/fixed_flat_set.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/logging.h"
@@ -33,10 +34,20 @@ namespace {
// unusual.
const size_t kMaximumDeviceNameLength = 256;
-constexpr struct {
+struct DeviceId {
uint16_t vendor;
uint16_t product_id;
-} kKeyboardBlocklist[] = {
+ constexpr bool operator<(const DeviceId& other) const {
+ return vendor == other.vendor ? product_id < other.product_id
+ : vendor < other.vendor;
+ }
+};
+
+constexpr auto kKeyboardBlocklist = base::MakeFixedFlatSet<DeviceId>({
+ {0x0111, 0x1830}, // SteelSeries Rival 3 Wireless (Bluetooth)
+ {0x0111, 0x183a}, // SteelSeries Aerox 3 Wireless (Bluetooth)
+ {0x0111, 0x1854}, // SteelSeries Aerox 5 Wireless (Bluetooth)
+ {0x0111, 0x185a}, // SteelSeries Aerox 9 Wireless (Bluetooth)
{0x03f0, 0xa407}, // HP X4000 Wireless Mouse
{0x045e, 0x0745}, // Microsoft Wireless Mobile Mouse 6000
{0x045e, 0x0821}, // Microsoft Surface Precision Mouse
@@ -70,47 +81,184 @@ constexpr struct {
{0x046d, 0xc093}, // Logitech M500s
{0x046d, 0xc534}, // Logitech M170
{0x046d, 0xc53e}, // Logitech Spotlight Presentation Remote (USB dongle)
+ {0x04b4, 0x121f}, // SteelSeries Ikari
{0x056e, 0x0134}, // Elecom Enelo IR LED Mouse 350
{0x056e, 0x0141}, // Elecom EPRIM Blue LED 5 button mouse 228
{0x056e, 0x0159}, // Elecom Blue LED Mouse 203
- {0x05e0, 0x1200}, // Zebra LS2208 barcode scanner
+ {0x05e0, 0x1200}, // Symbol Technologies / Zebra LS2208 barcode scanner
{0x0951, 0x1727}, // HyperX Pulsefire Haste Gaming Mouse
{0x0c45, 0x7403}, // RDing FootSwitch1F1
- {0x1038, 0x1369}, // SteelSeries Sensei RAW Frost Blue
- {0x1038, 0x1824}, // SteelSeries Rival 3 Wired
- {0x1038, 0x1830}, // SteelSeries Rival 3 Wireless (USB dongle)
+ {0x1038, 0x0470}, // SteelSeries Reaper Edge
+ {0x1038, 0x0471}, // SteelSeries Rival Rescuer
+ {0x1038, 0x0472}, // SteelSeries Rival 150 net café
+ {0x1038, 0x0473}, // SteelSeries Sensei SP
+ {0x1038, 0x0475}, // SteelSeries Rival 160 retail
+ {0x1038, 0x0777}, // SteelSeries MO3
+ {0x1038, 0x1300}, // SteelSeries Kinzu
+ {0x1038, 0x1310}, // SteelSeries MO4
+ {0x1038, 0x1311}, // SteelSeries MO4v2
+ {0x1038, 0x1320}, // SteelSeries MO3v2
+ {0x1038, 0x1330}, // SteelSeries MO5
+ {0x1038, 0x1332}, // SteelSeries MO5 (Dongle)
+ {0x1038, 0x1356}, // SteelSeries Sensei Dark EDG
+ {0x1038, 0x1358}, // SteelSeries Sensei Dark Snake
+ {0x1038, 0x135a}, // SteelSeries Sensei Dell Alienware
+ {0x1038, 0x1360}, // SteelSeries Xai
+ {0x1038, 0x1361}, // SteelSeries Sensei
+ {0x1038, 0x1362}, // SteelSeries Sensei Raw Diablo III Mouse
+ {0x1038, 0x1364}, // SteelSeries Kana
+ {0x1038, 0x1366}, // SteelSeries Kinzu 2
+ {0x1038, 0x1369}, // SteelSeries Sensei Raw
+ {0x1038, 0x136b}, // SteelSeries MLG Sensei
+ {0x1038, 0x136d}, // SteelSeries Sensei Raw: GW2
+ {0x1038, 0x136f}, // SteelSeries Sensei Raw: CoD
+ {0x1038, 0x1370}, // SteelSeries Sensei Master
+ {0x1038, 0x1372}, // SteelSeries Sensei Master (Hub Controller)
+ {0x1038, 0x1373}, // SteelSeries Sensei Master (Flash Drive Controller)
+ {0x1038, 0x1374}, // SteelSeries Kana: CS:GO
+ {0x1038, 0x1376}, // SteelSeries Kana: DOTA
+ {0x1038, 0x1378}, // SteelSeries Kinzu v2.1
+ {0x1038, 0x137a}, // SteelSeries Kana Pro
+ {0x1038, 0x137c}, // SteelSeries Wireless Sensei
+ {0x1038, 0x137e}, // SteelSeries Wireless Sensei (Charge Stand)
+ {0x1038, 0x1380}, // SteelSeries World of Tank mouse
+ {0x1038, 0x1382}, // SteelSeries Sims Mouse
+ {0x1038, 0x1384}, // SteelSeries Rival
+ {0x1038, 0x1386}, // SteelSeries SIMS 4 mouse
+ {0x1038, 0x1388}, // SteelSeries Kinzu v3 Mouse
+ {0x1038, 0x1390}, // SteelSeries Sensei Raw Heroes of the Storm Mouse
+ {0x1038, 0x1392}, // SteelSeries Rival DOTA 2
+ {0x1038, 0x1394}, // SteelSeries Rival 300 CS:GO Fade Edition
+ {0x1038, 0x1396}, // SteelSeries Rival 300 Gaming Mouse
+ {0x1038, 0x1700}, // SteelSeries Rival 700
+ {0x1038, 0x1701}, // SteelSeries Rival 700 (Basic)
+ {0x1038, 0x1702}, // SteelSeries Rival 100 Gaming Mouse (ELM4 - A)
+ {0x1038, 0x1704}, // SteelSeries Rival 95 PC BANG
+ {0x1038, 0x1705}, // SteelSeries Rival 100 For Alienware
+ {0x1038, 0x1706}, // SteelSeries Rival 95
+ {0x1038, 0x1707}, // SteelSeries Rival 95 MSI edition
+ {0x1038, 0x1708}, // SteelSeries Rival 100 Gaming Mouse (PC Bang)
+ {0x1038, 0x1709}, // SteelSeries Rival 50 MSI edition
+ {0x1038, 0x170a}, // SteelSeries Rival 100 Dell China
+ {0x1038, 0x170b}, // SteelSeries Rival 100 DOTA 2 Mouse
+ {0x1038, 0x170c}, // SteelSeries Rival 100 DOTA 2 Mouse (Lenovo)
+ {0x1038, 0x170d}, // SteelSeries Rival 100 World of Tanks Mouse
+ {0x1038, 0x170e}, // SteelSeries Rival 500 (MBM)
+ {0x1038, 0x170f}, // SteelSeries Rival 500 (Basic)
+ {0x1038, 0x1710}, // SteelSeries Rival 300 Gaming Mouse
+ {0x1038, 0x1712}, // SteelSeries Rival 300 Fallout 4 Gaming Mouse
+ {0x1038, 0x1714}, // SteelSeries Rival 300 Predator Gaming Mouse
+ {0x1038, 0x1716}, // SteelSeries Rival 300 CS:GO Fade Edition
+ {0x1038, 0x1718}, // SteelSeries Rival 300 HP Omen
+ {0x1038, 0x171a}, // SteelSeries Rival 300 CS:GO Hyperbeast Edition
+ {0x1038, 0x171c}, // SteelSeries Rival 300 Evil Geniuses Edition
+ {0x1038, 0x171e}, // SteelSeries Rival 310 CSGO Howl
+ {0x1038, 0x171f}, // SteelSeries Rival 310 CSGO Howl (Basic)
+ {0x1038, 0x1720}, // SteelSeries Rival 310
+ {0x1038, 0x1721}, // SteelSeries Rival 310 (Basic)
+ {0x1038, 0x1722}, // SteelSeries Sensei 310
+ {0x1038, 0x1723}, // SteelSeries Sensei 310 (Basic)
+ {0x1038, 0x1724}, // SteelSeries Rival 600
+ {0x1038, 0x1725}, // SteelSeries Rival 600 (Basic)
+ {0x1038, 0x1726}, // SteelSeries Rival 650 Wireless
+ {0x1038, 0x1727}, // SteelSeries Rival 650 Wireless (Basic)
+ {0x1038, 0x1729}, // SteelSeries Rival 110 Gaming Mouse
+ {0x1038, 0x172b}, // SteelSeries Rival 650 Wireless (Wired)
+ {0x1038, 0x172c}, // SteelSeries Rival 650 Wireless (Basic for wired)
+ {0x1038, 0x172d}, // SteelSeries Rival 110 (Dell)
+ {0x1038, 0x172e}, // SteelSeries Rival 600 Dota 2
+ {0x1038, 0x172f}, // SteelSeries Rival 600 Dota 2 (Basic)
+ {0x1038, 0x1730}, // SteelSeries Rival 710
+ {0x1038, 0x1731}, // SteelSeries Rival 710 (Basic)
+ {0x1038, 0x1736}, // SteelSeries Rival 310 PUBG Edition
+ {0x1038, 0x1737}, // SteelSeries Rival 310 PUBG Edition (Basic)
+ {0x1038, 0x1800}, // SteelSeries Sensei Raw Optical
+ {0x1038, 0x1801}, // SteelSeries Sensei Raw Optical (Basic)
+ {0x1038, 0x1802}, // SteelSeries Sensei Raw Optical RGB
+ {0x1038, 0x1803}, // SteelSeries Sensei Raw Optical RGB (Basic)
+ {0x1038, 0x1810}, // SteelSeries Rival 300S
+ {0x1038, 0x1812}, // SteelSeries Rival 300S Dell Silver
+ {0x1038, 0x1814}, // SteelSeries Rival 105 (Kana v3) Gaming Mouse
+ {0x1038, 0x1816}, // SteelSeries Rival 106 Gaming Mouse
+ {0x1038, 0x1818}, // SteelSeries Rival 610 Wireless
+ {0x1038, 0x1819}, // SteelSeries Rival 610 Wireless (Basic)
+ {0x1038, 0x181a}, // SteelSeries Rival 610 Wireless (Wired)
+ {0x1038, 0x181b}, // SteelSeries Rival 610 Wireless (Basic for wired)
+ {0x1038, 0x181c}, // SteelSeries Rival 310 Wireless
+ {0x1038, 0x181d}, // SteelSeries Rival 310 Wireless (Basic)
+ {0x1038, 0x181e}, // SteelSeries Rival 310 Wireless (Wired)
+ {0x1038, 0x181f}, // SteelSeries Rival 310 Wireless (Basic for wired)
+ {0x1038, 0x1820}, // SteelSeries Rival 610
+ {0x1038, 0x1821}, // SteelSeries Rival 610 (Basic)
+ {0x1038, 0x1822}, // SteelSeries Sensei 610
+ {0x1038, 0x1823}, // SteelSeries Sensei 610 (Basic)
+ {0x1038, 0x1824}, // SteelSeries Rival 3
+ {0x1038, 0x1826}, // SteelSeries Sensei Raw Optical RGB v2
+ {0x1038, 0x1827}, // SteelSeries Sensei Raw Optical RGB v2 (Basic)
+ {0x1038, 0x1828}, // SteelSeries Radical Wireless
+ {0x1038, 0x1829}, // SteelSeries Radical Wireless (Basic)
+ {0x1038, 0x182a}, // SteelSeries Prime Rainbow Six Edition
+ {0x1038, 0x182b}, // SteelSeries Prime Rainbow Six Edition (Basic)
+ {0x1038, 0x182c}, // SteelSeries Prime+
+ {0x1038, 0x182d}, // SteelSeries Prime+ (Basic)
+ {0x1038, 0x182e}, // SteelSeries Prime
+ {0x1038, 0x182f}, // SteelSeries Prime (Basic)
+ {0x1038, 0x1830}, // SteelSeries Rival 3 Wireless
+ {0x1038, 0x1831}, // SteelSeries Rival 3 Wireless (Basic)
+ {0x1038, 0x1832}, // SteelSeries Sensei Ten
+ {0x1038, 0x1833}, // SteelSeries Sensei Ten (Basic)
+ {0x1038, 0x1834}, // SteelSeries Sensei Ten Neon Rider Edition
+ {0x1038, 0x1835}, // SteelSeries Sensei Ten Neon Rider Edition (Basic)
+ {0x1038, 0x1836}, // SteelSeries Aerox 3
+ {0x1038, 0x1838}, // SteelSeries Aerox 3 Wireless (Dongle)
+ {0x1038, 0x1839}, // SteelSeries Aerox 3 Wireless (Basic for dongle)
+ {0x1038, 0x183a}, // SteelSeries Aerox 3 Wireless (Wired)
+ {0x1038, 0x183b}, // SteelSeries Aerox 3 Wireless (Basic for wired)
+ {0x1038, 0x183c}, // SteelSeries Rival 5
+ {0x1038, 0x183d}, // SteelSeries Rival 5 (Basic)
+ {0x1038, 0x183e}, // SteelSeries Rival 5 Destiny 2
+ {0x1038, 0x183f}, // SteelSeries Rival 5 Destiny 2 (Basic)
+ {0x1038, 0x1840}, // SteelSeries Prime Wireless (Dongle)
+ {0x1038, 0x1841}, // SteelSeries Prime Wireless (Basic for dongle)
+ {0x1038, 0x1842}, // SteelSeries Prime Wireless (Wired)
+ {0x1038, 0x1843}, // SteelSeries Prime Wireless (Basic for wired)
+ {0x1038, 0x1848}, // SteelSeries Prime Mini Wireless (Dongle)
+ {0x1038, 0x184a}, // SteelSeries Prime Mini Wireless (Wired)
+ {0x1038, 0x184c}, // SteelSeries Rival 3 (NVIDIA Support - Standard)
+ {0x1038, 0x184d}, // SteelSeries Prime Mini
+ {0x1038, 0x1850}, // SteelSeries Aerox 5
+ {0x1038, 0x1852}, // SteelSeries Aerox 5 Wireless (Dongle)
+ {0x1038, 0x1854}, // SteelSeries Aerox 5 Wireless (Wired)
+ {0x1038, 0x1856}, // SteelSeries Prime CS:GO Neo Noir
+ {0x1038, 0x1858}, // SteelSeries Aerox 9 WL (Dongle)
+ {0x1038, 0x185a}, // SteelSeries Aerox 9 WL (Wired)
{0x1050, 0x0010}, // Yubico.com Yubikey
{0x1050, 0x0407}, // Yubico.com Yubikey 4 OTP+U2F+CCID
{0x1532, 0x007a}, // Razer Viper Ultimate (Wired)
{0x1532, 0x007b}, // Razer Viper Ultimate (Wireless)
+ {0x17ef, 0x60be}, // Lenovo Legion M200 RGB Gaming Mouse
{0x17ef, 0x60e4}, // Lenovo Legion M300 RGB Gaming Mouse
- // (which can send keystrokes as part of macros.)
{0x17ef, 0x6123}, // Lenovo USB-C Wired Compact Mouse
{0x1b1c, 0x1b7a}, // Corsair Sabre Pro Champion Gaming Mouse
{0x1b1c, 0x1b94}, // Corsair Katar Pro Wireless (USB dongle)
{0x1bae, 0x1b1c}, // Corsair Katar Pro Wireless (Bluetooth)
{0x1bcf, 0x08a0}, // Kensington Pro Fit Full-size
+ {0x2201, 0x0100}, // AirTurn PEDpro
{0x256c, 0x006d}, // Huion HS64
{0x258a, 0x1007}, // Acer Cestus 330
{0x2717, 0x003b}, // Xiaomi Mi Portable Mouse
{0x28bd, 0x0914}, // XP-Pen Star G640
{0x28bd, 0x091f}, // XP-Pen Artist 12 Pro
{0x28bd, 0x0928}, // XP-Pen Deco mini7W
-};
+});
-constexpr struct {
- uint16_t vendor;
- uint16_t product_id;
-} kStylusButtonDevices[] = {
+constexpr DeviceId kStylusButtonDevices[] = {
{0x413c, 0x81d5}, // Dell Active Pen PN579X
};
// Certain devices need to be forced to use libinput in place of
// evdev/libgestures
-constexpr struct {
- uint16_t vendor;
- uint16_t product_id;
-} kForceLibinputlist[] = {
+constexpr DeviceId kForceLibinputlist[] = {
{0x0002, 0x000e}, // HP Stream 14 touchpad
{0x044e, 0x120a}, // Dell Latitude 3480 touchpad
};
@@ -244,47 +392,46 @@ bool IsDenylistedAbsoluteMouseDevice(const input_id& id) {
} // namespace
-EventDeviceInfo::EventDeviceInfo() {
- memset(ev_bits_, 0, sizeof(ev_bits_));
- memset(key_bits_, 0, sizeof(key_bits_));
- memset(rel_bits_, 0, sizeof(rel_bits_));
- memset(abs_bits_, 0, sizeof(abs_bits_));
- memset(msc_bits_, 0, sizeof(msc_bits_));
- memset(sw_bits_, 0, sizeof(sw_bits_));
- memset(led_bits_, 0, sizeof(led_bits_));
- memset(ff_bits_, 0, sizeof(ff_bits_));
- memset(prop_bits_, 0, sizeof(prop_bits_));
- memset(abs_info_, 0, sizeof(abs_info_));
-}
+EventDeviceInfo::EventDeviceInfo()
+ : ev_bits_{},
+ key_bits_{},
+ rel_bits_{},
+ abs_bits_{},
+ msc_bits_{},
+ sw_bits_{},
+ led_bits_{},
+ prop_bits_{},
+ ff_bits_{},
+ abs_info_{} {}
EventDeviceInfo::~EventDeviceInfo() {}
bool EventDeviceInfo::Initialize(int fd, const base::FilePath& path) {
- if (!GetEventBits(fd, path, 0, ev_bits_, sizeof(ev_bits_)))
+ if (!GetEventBits(fd, path, 0, ev_bits_.data(), sizeof(ev_bits_)))
return false;
- if (!GetEventBits(fd, path, EV_KEY, key_bits_, sizeof(key_bits_)))
+ if (!GetEventBits(fd, path, EV_KEY, key_bits_.data(), sizeof(key_bits_)))
return false;
- if (!GetEventBits(fd, path, EV_REL, rel_bits_, sizeof(rel_bits_)))
+ if (!GetEventBits(fd, path, EV_REL, rel_bits_.data(), sizeof(rel_bits_)))
return false;
- if (!GetEventBits(fd, path, EV_ABS, abs_bits_, sizeof(abs_bits_)))
+ if (!GetEventBits(fd, path, EV_ABS, abs_bits_.data(), sizeof(abs_bits_)))
return false;
- if (!GetEventBits(fd, path, EV_MSC, msc_bits_, sizeof(msc_bits_)))
+ if (!GetEventBits(fd, path, EV_MSC, msc_bits_.data(), sizeof(msc_bits_)))
return false;
- if (!GetEventBits(fd, path, EV_SW, sw_bits_, sizeof(sw_bits_)))
+ if (!GetEventBits(fd, path, EV_SW, sw_bits_.data(), sizeof(sw_bits_)))
return false;
- if (!GetEventBits(fd, path, EV_LED, led_bits_, sizeof(led_bits_)))
+ if (!GetEventBits(fd, path, EV_LED, led_bits_.data(), sizeof(led_bits_)))
return false;
- if (!GetEventBits(fd, path, EV_FF, ff_bits_, sizeof(ff_bits_)))
+ if (!GetEventBits(fd, path, EV_FF, ff_bits_.data(), sizeof(ff_bits_)))
return false;
- if (!GetPropBits(fd, path, prop_bits_, sizeof(prop_bits_)))
+ if (!GetPropBits(fd, path, prop_bits_.data(), sizeof(prop_bits_)))
return false;
for (unsigned int i = 0; i < ABS_CNT; ++i)
@@ -326,39 +473,39 @@ bool EventDeviceInfo::Initialize(int fd, const base::FilePath& path) {
}
void EventDeviceInfo::SetEventTypes(const unsigned long* ev_bits, size_t len) {
- AssignBitset(ev_bits, len, ev_bits_, std::size(ev_bits_));
+ AssignBitset(ev_bits, len, ev_bits_.data(), ev_bits_.size());
}
void EventDeviceInfo::SetKeyEvents(const unsigned long* key_bits, size_t len) {
- AssignBitset(key_bits, len, key_bits_, std::size(key_bits_));
+ AssignBitset(key_bits, len, key_bits_.data(), key_bits_.size());
}
void EventDeviceInfo::SetRelEvents(const unsigned long* rel_bits, size_t len) {
- AssignBitset(rel_bits, len, rel_bits_, std::size(rel_bits_));
+ AssignBitset(rel_bits, len, rel_bits_.data(), rel_bits_.size());
}
void EventDeviceInfo::SetAbsEvents(const unsigned long* abs_bits, size_t len) {
- AssignBitset(abs_bits, len, abs_bits_, std::size(abs_bits_));
+ AssignBitset(abs_bits, len, abs_bits_.data(), abs_bits_.size());
}
void EventDeviceInfo::SetMscEvents(const unsigned long* msc_bits, size_t len) {
- AssignBitset(msc_bits, len, msc_bits_, std::size(msc_bits_));
+ AssignBitset(msc_bits, len, msc_bits_.data(), msc_bits_.size());
}
void EventDeviceInfo::SetSwEvents(const unsigned long* sw_bits, size_t len) {
- AssignBitset(sw_bits, len, sw_bits_, std::size(sw_bits_));
+ AssignBitset(sw_bits, len, sw_bits_.data(), sw_bits_.size());
}
void EventDeviceInfo::SetLedEvents(const unsigned long* led_bits, size_t len) {
- AssignBitset(led_bits, len, led_bits_, std::size(led_bits_));
+ AssignBitset(led_bits, len, led_bits_.data(), led_bits_.size());
}
void EventDeviceInfo::SetFfEvents(const unsigned long* ff_bits, size_t len) {
- AssignBitset(ff_bits, len, ff_bits_, std::size(ff_bits_));
+ AssignBitset(ff_bits, len, ff_bits_.data(), ff_bits_.size());
}
void EventDeviceInfo::SetProps(const unsigned long* prop_bits, size_t len) {
- AssignBitset(prop_bits, len, prop_bits_, std::size(prop_bits_));
+ AssignBitset(prop_bits, len, prop_bits_.data(), prop_bits_.size());
}
void EventDeviceInfo::SetAbsInfo(unsigned int code,
@@ -401,55 +548,55 @@ void EventDeviceInfo::SetName(const std::string& name) {
bool EventDeviceInfo::HasEventType(unsigned int type) const {
if (type > EV_MAX)
return false;
- return EvdevBitIsSet(ev_bits_, type);
+ return EvdevBitIsSet(ev_bits_.data(), type);
}
bool EventDeviceInfo::HasKeyEvent(unsigned int code) const {
if (code > KEY_MAX)
return false;
- return EvdevBitIsSet(key_bits_, code);
+ return EvdevBitIsSet(key_bits_.data(), code);
}
bool EventDeviceInfo::HasRelEvent(unsigned int code) const {
if (code > REL_MAX)
return false;
- return EvdevBitIsSet(rel_bits_, code);
+ return EvdevBitIsSet(rel_bits_.data(), code);
}
bool EventDeviceInfo::HasAbsEvent(unsigned int code) const {
if (code > ABS_MAX)
return false;
- return EvdevBitIsSet(abs_bits_, code);
+ return EvdevBitIsSet(abs_bits_.data(), code);
}
bool EventDeviceInfo::HasMscEvent(unsigned int code) const {
if (code > MSC_MAX)
return false;
- return EvdevBitIsSet(msc_bits_, code);
+ return EvdevBitIsSet(msc_bits_.data(), code);
}
bool EventDeviceInfo::HasSwEvent(unsigned int code) const {
if (code > SW_MAX)
return false;
- return EvdevBitIsSet(sw_bits_, code);
+ return EvdevBitIsSet(sw_bits_.data(), code);
}
bool EventDeviceInfo::HasLedEvent(unsigned int code) const {
if (code > LED_MAX)
return false;
- return EvdevBitIsSet(led_bits_, code);
+ return EvdevBitIsSet(led_bits_.data(), code);
}
bool EventDeviceInfo::HasFfEvent(unsigned int code) const {
if (code > FF_MAX)
return false;
- return EvdevBitIsSet(ff_bits_, code);
+ return EvdevBitIsSet(ff_bits_.data(), code);
}
bool EventDeviceInfo::HasProp(unsigned int code) const {
if (code > INPUT_PROP_MAX)
return false;
- return EvdevBitIsSet(prop_bits_, code);
+ return EvdevBitIsSet(prop_bits_.data(), code);
}
int32_t EventDeviceInfo::GetAbsMinimum(unsigned int code) const {
@@ -590,30 +737,29 @@ bool EventDeviceInfo::UseLibinput() const {
}
bool IsInKeyboardBlockList(input_id input_id_) {
- for (const auto& blocklist_id : kKeyboardBlocklist) {
- if (input_id_.vendor == blocklist_id.vendor &&
- input_id_.product == blocklist_id.product_id)
- return true;
- }
-
- return false;
+ DeviceId id = {input_id_.vendor, input_id_.product};
+ return kKeyboardBlocklist.contains(id);
}
bool EventDeviceInfo::HasKeyboard() const {
+ return GetKeyboardType() == KeyboardType::VALID_KEYBOARD;
+}
+
+KeyboardType EventDeviceInfo::GetKeyboardType() const {
if (!HasEventType(EV_KEY))
- return false;
+ return KeyboardType::NOT_KEYBOARD;
if (IsInKeyboardBlockList(input_id_))
- return false;
+ return KeyboardType::IN_BLOCKLIST;
if (IsStylusButtonDevice())
- return false;
+ return KeyboardType::STYLUS_BUTTON_DEVICE;
// Check first 31 keys: If we have all of them, consider it a full
// keyboard. This is exactly what udev does for ID_INPUT_KEYBOARD.
for (int key = KEY_ESC; key <= KEY_D; ++key)
if (!HasKeyEvent(key))
- return false;
+ return KeyboardType::NOT_KEYBOARD;
- return true;
+ return KeyboardType::VALID_KEYBOARD;
}
bool EventDeviceInfo::HasMouse() const {
@@ -624,6 +770,7 @@ bool EventDeviceInfo::HasMouse() const {
input_id_.product == kSteelSeriesStratusDuoBluetoothProductId) {
return false;
}
+
return HasRelXY() && !HasProp(INPUT_PROP_POINTING_STICK);
}
diff --git a/chromium/ui/events/ozone/evdev/event_device_info.h b/chromium/ui/events/ozone/evdev/event_device_info.h
index 88cc90dc311..090d247ac9a 100644
--- a/chromium/ui/events/ozone/evdev/event_device_info.h
+++ b/chromium/ui/events/ozone/evdev/event_device_info.h
@@ -10,6 +10,7 @@
#include <stddef.h>
#include <stdint.h>
+#include <array>
#include <string>
#include <vector>
@@ -44,6 +45,14 @@ enum COMPONENT_EXPORT(EVDEV) EventDeviceType {
DT_ALL,
};
+// Status of Keyboard Device
+enum COMPONENT_EXPORT(EVDEV) KeyboardType {
+ NOT_KEYBOARD,
+ IN_BLOCKLIST,
+ STYLUS_BUTTON_DEVICE,
+ VALID_KEYBOARD,
+};
+
// Device information for Linux input devices
//
// This stores and queries information about input devices; in
@@ -136,6 +145,9 @@ class COMPONENT_EXPORT(EVDEV) EventDeviceInfo {
// Has stylus EV_KEY events.
bool HasStylus() const;
+ // Determine status of keyboard device (No keyboard, In blocklist, ect.).
+ KeyboardType GetKeyboardType() const;
+
// Determine whether there's a keyboard on this device.
bool HasKeyboard() const;
@@ -191,6 +203,10 @@ class COMPONENT_EXPORT(EVDEV) EventDeviceInfo {
// The device type (internal or external.)
InputDeviceType device_type() const { return device_type_; }
+ std::array<unsigned long, EVDEV_BITS_TO_LONGS(KEY_CNT)> GetKeyBits() const {
+ return key_bits_;
+ }
+
// Determines InputDeviceType from device identification.
static InputDeviceType GetInputDeviceTypeFromId(input_id id);
@@ -209,17 +225,17 @@ class COMPONENT_EXPORT(EVDEV) EventDeviceInfo {
// do not tell us what the axes mean.
LegacyAbsoluteDeviceType ProbeLegacyAbsoluteDevice() const;
- unsigned long ev_bits_[EVDEV_BITS_TO_LONGS(EV_CNT)];
- unsigned long key_bits_[EVDEV_BITS_TO_LONGS(KEY_CNT)];
- unsigned long rel_bits_[EVDEV_BITS_TO_LONGS(REL_CNT)];
- unsigned long abs_bits_[EVDEV_BITS_TO_LONGS(ABS_CNT)];
- unsigned long msc_bits_[EVDEV_BITS_TO_LONGS(MSC_CNT)];
- unsigned long sw_bits_[EVDEV_BITS_TO_LONGS(SW_CNT)];
- unsigned long led_bits_[EVDEV_BITS_TO_LONGS(LED_CNT)];
- unsigned long prop_bits_[EVDEV_BITS_TO_LONGS(INPUT_PROP_CNT)];
- unsigned long ff_bits_[EVDEV_BITS_TO_LONGS(FF_CNT)];
-
- struct input_absinfo abs_info_[ABS_CNT];
+ std::array<unsigned long, EVDEV_BITS_TO_LONGS(EV_CNT)> ev_bits_;
+ std::array<unsigned long, EVDEV_BITS_TO_LONGS(KEY_CNT)> key_bits_;
+ std::array<unsigned long, EVDEV_BITS_TO_LONGS(REL_CNT)> rel_bits_;
+ std::array<unsigned long, EVDEV_BITS_TO_LONGS(ABS_CNT)> abs_bits_;
+ std::array<unsigned long, EVDEV_BITS_TO_LONGS(MSC_CNT)> msc_bits_;
+ std::array<unsigned long, EVDEV_BITS_TO_LONGS(SW_CNT)> sw_bits_;
+ std::array<unsigned long, EVDEV_BITS_TO_LONGS(LED_CNT)> led_bits_;
+ std::array<unsigned long, EVDEV_BITS_TO_LONGS(INPUT_PROP_CNT)> prop_bits_;
+ std::array<unsigned long, EVDEV_BITS_TO_LONGS(FF_CNT)> ff_bits_;
+
+ std::array<input_absinfo, ABS_CNT> abs_info_;
// Store the values for the multi-touch properties for each slot.
std::vector<int32_t> slot_values_[EVDEV_ABS_MT_COUNT];
diff --git a/chromium/ui/events/ozone/evdev/event_device_info_unittest.cc b/chromium/ui/events/ozone/evdev/event_device_info_unittest.cc
index 41b2e7a8a11..d10eaa0b003 100644
--- a/chromium/ui/events/ozone/evdev/event_device_info_unittest.cc
+++ b/chromium/ui/events/ozone/evdev/event_device_info_unittest.cc
@@ -500,4 +500,22 @@ TEST(EventDeviceInfoTest, HPProBook6560bTouchpad) {
EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_INTERNAL, devinfo.device_type());
}
+TEST(EventDeviceInfoTest, DeviceOnKeyboardBlocklist) {
+ EventDeviceInfo devinfo;
+ EXPECT_TRUE(CapabilitiesToDeviceInfo(kSymbolTechBarcodeScanner, &devinfo));
+
+ EXPECT_FALSE(devinfo.HasKeyboard());
+ EXPECT_FALSE(devinfo.HasMouse());
+ EXPECT_FALSE(devinfo.HasPointingStick());
+ EXPECT_FALSE(devinfo.HasTouchpad());
+ EXPECT_FALSE(devinfo.HasHapticTouchpad());
+ EXPECT_FALSE(devinfo.HasTouchscreen());
+ EXPECT_FALSE(devinfo.HasTablet());
+ EXPECT_FALSE(devinfo.HasGamepad());
+ EXPECT_FALSE(devinfo.IsStylusButtonDevice());
+ EXPECT_FALSE(devinfo.HasStylusSwitch());
+ EXPECT_FALSE(devinfo.HasValidMTAbsXY());
+ EXPECT_FALSE(devinfo.IsSemiMultitouch());
+}
+
} // namespace ui
diff --git a/chromium/ui/events/ozone/evdev/event_device_test_util.cc b/chromium/ui/events/ozone/evdev/event_device_test_util.cc
index e67b23c4683..e470b7e8977 100644
--- a/chromium/ui/events/ozone/evdev/event_device_test_util.cc
+++ b/chromium/ui/events/ozone/evdev/event_device_test_util.cc
@@ -1465,6 +1465,33 @@ const DeviceCapabilities kRedrixTouchpad = {
std::size(kRedrixTouchpadAxes),
};
+const DeviceCapabilities kSymbolTechBarcodeScanner = {
+ /* path */
+ "/sys/devices/pci0000:00/0000:00:14.0/usb1/1-6/1-6:1.0/0003:05E0:1200.0009/"
+ "input/input27/event19",
+ /* name */ "Symbol Technologies, Inc, 2008 Symbol Bar Code Scanner",
+ /* phys */ "usb-0000:00:14.0-6/input0",
+ /* uniq */ "S/N:D698905D483448AD806AAC8CD63B8B4A Rev:PAACES00-002-R033",
+ /* bustype */ "0003",
+ /* vendor */ "05e0",
+ /* product */ "1200",
+ /* version */ "0110",
+ /* prop */ "0",
+ /* ev */ "120013",
+ /* key */
+ "1000000000007 ff9f207ac14057ff febeffdfffefffff fffffffffffffffe",
+ /* rel */ "0",
+ /* abs */ "0",
+ /* msc */ "10",
+ /* sw */ "0",
+ /* led */ "1f",
+ /* ff */ "0",
+ /* abs_axis */ nullptr,
+ /* abs_axis_count */ 0,
+ /* kbd_function_row_physmap */ "",
+ /* kbd_top_row_layout */ "",
+};
+
// NB: Please use the capture_device_capabilities.py script to add more
// test data here. This will help ensure the data matches what the kernel
// reports for a real device and is entered correctly.
diff --git a/chromium/ui/events/ozone/evdev/event_device_test_util.h b/chromium/ui/events/ozone/evdev/event_device_test_util.h
index e22a8b27311..2a99db93d4f 100644
--- a/chromium/ui/events/ozone/evdev/event_device_test_util.h
+++ b/chromium/ui/events/ozone/evdev/event_device_test_util.h
@@ -115,6 +115,7 @@ extern const DeviceCapabilities kMicrosoftBluetoothNumberPad;
extern const DeviceCapabilities kDellLatitudeE6510Touchpad;
extern const DeviceCapabilities kHPProBook6560bTouchpad;
extern const DeviceCapabilities kJinlonKeyboard;
+extern const DeviceCapabilities kSymbolTechBarcodeScanner;
} // namespace ui
#endif // UI_EVENTS_OZONE_EVDEV_EVENT_DEVICE_TEST_UTIL_H_
diff --git a/chromium/ui/events/ozone/evdev/event_device_util.h b/chromium/ui/events/ozone/evdev/event_device_util.h
index 15000e350c9..4205b7dcdb6 100644
--- a/chromium/ui/events/ozone/evdev/event_device_util.h
+++ b/chromium/ui/events/ozone/evdev/event_device_util.h
@@ -10,16 +10,27 @@
namespace ui {
#define EVDEV_LONG_BITS (CHAR_BIT * sizeof(long))
+#define EVDEV_INT64_BITS (CHAR_BIT * sizeof(int64_t))
#define EVDEV_BITS_TO_LONGS(x) (((x) + EVDEV_LONG_BITS - 1) / EVDEV_LONG_BITS)
+#define EVDEV_BITS_TO_INT64(x) (((x) + EVDEV_INT64_BITS - 1) / EVDEV_INT64_BITS)
static inline bool EvdevBitIsSet(const unsigned long* data, int bit) {
return data[bit / EVDEV_LONG_BITS] & (1UL << (bit % EVDEV_LONG_BITS));
}
+static inline bool EvdevBitUint64IsSet(const uint64_t* data, int bit) {
+ return data[bit / EVDEV_INT64_BITS] &
+ ((uint64_t)1 << (bit % EVDEV_INT64_BITS));
+}
+
static inline void EvdevSetBit(unsigned long* data, int bit) {
data[bit / EVDEV_LONG_BITS] |= (1UL << (bit % EVDEV_LONG_BITS));
}
+static inline void EvdevSetUint64Bit(uint64_t* data, int bit) {
+ data[bit / EVDEV_INT64_BITS] |= ((uint64_t)1 << (bit % EVDEV_INT64_BITS));
+}
+
} // namespace ui
#endif // UI_EVENTS_OZONE_EVDEV_EVENT_DEVICE_UTIL_H_
diff --git a/chromium/ui/events/ozone/evdev/event_factory_evdev.cc b/chromium/ui/events/ozone/evdev/event_factory_evdev.cc
index bf457a11c34..671439ee09d 100644
--- a/chromium/ui/events/ozone/evdev/event_factory_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/event_factory_evdev.cc
@@ -94,11 +94,13 @@ class ProxyDeviceEventDispatcher : public DeviceEventDispatcherEvdev {
}
void DispatchKeyboardDevicesUpdated(
- const std::vector<InputDevice>& devices) override {
+ const std::vector<InputDevice>& devices,
+ base::flat_map<int, std::vector<uint64_t>> key_bits_mapping) override {
ui_thread_runner_->PostTask(
FROM_HERE,
base::BindOnce(&EventFactoryEvdev::DispatchKeyboardDevicesUpdated,
- event_factory_evdev_, devices));
+ event_factory_evdev_, devices,
+ std::move(key_bits_mapping)));
}
void DispatchTouchscreenDevicesUpdated(
const std::vector<TouchscreenDevice>& devices) override {
@@ -146,11 +148,13 @@ class ProxyDeviceEventDispatcher : public DeviceEventDispatcherEvdev {
}
void DispatchGamepadDevicesUpdated(
- const std::vector<GamepadDevice>& devices) override {
+ const std::vector<GamepadDevice>& devices,
+ base::flat_map<int, std::vector<uint64_t>> key_bits_mapping) override {
ui_thread_runner_->PostTask(
FROM_HERE,
base::BindOnce(&EventFactoryEvdev::DispatchGamepadDevicesUpdated,
- event_factory_evdev_, devices));
+ event_factory_evdev_, devices,
+ std::move(key_bits_mapping)));
}
void DispatchUncategorizedDevicesUpdated(
@@ -394,8 +398,10 @@ void EventFactoryEvdev::DispatchUiEvent(Event* event) {
}
void EventFactoryEvdev::DispatchKeyboardDevicesUpdated(
- const std::vector<InputDevice>& devices) {
+ const std::vector<InputDevice>& devices,
+ base::flat_map<int, std::vector<uint64_t>> key_bits_mapping) {
TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchKeyboardDevicesUpdated");
+ input_controller_.SetKeyboardKeyBitsMapping(std::move(key_bits_mapping));
DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance();
observer->OnKeyboardDevicesUpdated(devices);
}
@@ -459,8 +465,10 @@ void EventFactoryEvdev::DispatchUncategorizedDevicesUpdated(
}
void EventFactoryEvdev::DispatchGamepadDevicesUpdated(
- const std::vector<GamepadDevice>& devices) {
+ const std::vector<GamepadDevice>& devices,
+ base::flat_map<int, std::vector<uint64_t>> key_bits_mapping) {
TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchGamepadDevicesUpdated");
+ input_controller_.SetGamepadKeyBitsMapping(std::move(key_bits_mapping));
gamepad_provider_->DispatchGamepadDevicesUpdated(devices);
}
diff --git a/chromium/ui/events/ozone/evdev/event_factory_evdev.h b/chromium/ui/events/ozone/evdev/event_factory_evdev.h
index a7fa692fb3d..f3980da6f92 100644
--- a/chromium/ui/events/ozone/evdev/event_factory_evdev.h
+++ b/chromium/ui/events/ozone/evdev/event_factory_evdev.h
@@ -7,6 +7,7 @@
#include "base/callback.h"
#include "base/component_export.h"
+#include "base/containers/flat_map.h"
#include "base/memory/ref_counted.h"
#include "base/task/task_runner.h"
#include "ui/events/event_modifiers.h"
@@ -77,7 +78,9 @@ class COMPONENT_EXPORT(EVDEV) EventFactoryEvdev : public DeviceEventObserver,
void DispatchTouchEvent(const TouchEventParams& params);
// Device lifecycle events.
- void DispatchKeyboardDevicesUpdated(const std::vector<InputDevice>& devices);
+ void DispatchKeyboardDevicesUpdated(
+ const std::vector<InputDevice>& devices,
+ base::flat_map<int, std::vector<uint64_t>> key_bits_mapping);
void DispatchTouchscreenDevicesUpdated(
const std::vector<TouchscreenDevice>& devices);
void DispatchMouseDevicesUpdated(const std::vector<InputDevice>& devices,
@@ -94,7 +97,9 @@ class COMPONENT_EXPORT(EVDEV) EventFactoryEvdev : public DeviceEventObserver,
// Gamepad event and gamepad device event. These events are dispatched to
// GamepadObserver through GamepadProviderOzone.
void DispatchGamepadEvent(const GamepadEvent& event);
- void DispatchGamepadDevicesUpdated(const std::vector<GamepadDevice>& devices);
+ void DispatchGamepadDevicesUpdated(
+ const std::vector<GamepadDevice>& devices,
+ base::flat_map<int, std::vector<uint64_t>> key_bits_mapping);
protected:
// DeviceEventObserver overrides:
diff --git a/chromium/ui/events/ozone/evdev/event_factory_evdev_unittest.cc b/chromium/ui/events/ozone/evdev/event_factory_evdev_unittest.cc
index f9c13253bb0..eac55378d50 100644
--- a/chromium/ui/events/ozone/evdev/event_factory_evdev_unittest.cc
+++ b/chromium/ui/events/ozone/evdev/event_factory_evdev_unittest.cc
@@ -53,7 +53,7 @@ TEST_F(EventFactoryEvdevTest, OrdinalImpliesFlag) {
EXPECT_CALL(event_observer_, WillProcessEvent)
.WillOnce([](const PlatformEvent& platform_event) {
MouseEvent mouse_event(platform_event);
- EXPECT_TRUE(mouse_event.flags() & MouseEventFlags::EF_UNADJUSTED_MOUSE);
+ EXPECT_TRUE(mouse_event.flags() & EF_UNADJUSTED_MOUSE);
EXPECT_EQ(mouse_event.movement(), gfx::Vector2dF(2.67, 3.14));
});
@@ -71,8 +71,7 @@ TEST_F(EventFactoryEvdevTest, NoOrdinalImpliesNoFlag) {
EXPECT_CALL(event_observer_, WillProcessEvent)
.WillOnce([](const PlatformEvent& platform_event) {
MouseEvent mouse_event(platform_event);
- EXPECT_FALSE(mouse_event.flags() &
- MouseEventFlags::EF_UNADJUSTED_MOUSE);
+ EXPECT_FALSE(mouse_event.flags() & EF_UNADJUSTED_MOUSE);
});
event_factory_.DispatchMouseMoveEvent(
diff --git a/chromium/ui/events/ozone/evdev/event_thread_evdev.cc b/chromium/ui/events/ozone/evdev/event_thread_evdev.cc
index 14f6ed14f36..591b071c4cb 100644
--- a/chromium/ui/events/ozone/evdev/event_thread_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/event_thread_evdev.cc
@@ -18,6 +18,7 @@
#include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h"
#include "ui/events/ozone/evdev/input_device_factory_evdev.h"
#include "ui/events/ozone/evdev/input_device_factory_evdev_proxy.h"
+#include "ui/events/ozone/evdev/input_device_opener_evdev.h"
namespace ui {
@@ -39,7 +40,8 @@ class EvdevThread : public base::Thread {
void Init() override {
TRACE_EVENT0("evdev", "EvdevThread::Init");
input_device_factory_ =
- new InputDeviceFactoryEvdev(std::move(dispatcher_), cursor_);
+ new InputDeviceFactoryEvdev(std::move(dispatcher_), cursor_,
+ std::make_unique<InputDeviceOpenerEvdev>());
std::unique_ptr<InputDeviceFactoryEvdevProxy> proxy(
new InputDeviceFactoryEvdevProxy(base::ThreadTaskRunnerHandle::Get(),
diff --git a/chromium/ui/events/ozone/evdev/fake_keyboard_heuristic_metrics.cc b/chromium/ui/events/ozone/evdev/fake_keyboard_heuristic_metrics.cc
new file mode 100644
index 00000000000..5bef3c9b59a
--- /dev/null
+++ b/chromium/ui/events/ozone/evdev/fake_keyboard_heuristic_metrics.cc
@@ -0,0 +1,28 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/ozone/evdev/fake_keyboard_heuristic_metrics.h"
+
+#include "ui/events/ozone/features.h"
+
+namespace ui {
+
+FakeKeyboardHeuristicMetrics::FakeKeyboardHeuristicMetrics()
+ : feature_usage_metrics_("FakeKeyboardHeuristic", this) {}
+
+FakeKeyboardHeuristicMetrics::~FakeKeyboardHeuristicMetrics() = default;
+
+bool FakeKeyboardHeuristicMetrics::IsEligible() const {
+ return true;
+}
+
+bool FakeKeyboardHeuristicMetrics::IsEnabled() const {
+ return base::FeatureList::IsEnabled(kEnableFakeKeyboardHeuristic);
+}
+
+void FakeKeyboardHeuristicMetrics::RecordUsage(bool success) {
+ feature_usage_metrics_.RecordUsage(success);
+}
+
+} // namespace ui \ No newline at end of file
diff --git a/chromium/ui/events/ozone/evdev/fake_keyboard_heuristic_metrics.h b/chromium/ui/events/ozone/evdev/fake_keyboard_heuristic_metrics.h
new file mode 100644
index 00000000000..b07112a9a71
--- /dev/null
+++ b/chromium/ui/events/ozone/evdev/fake_keyboard_heuristic_metrics.h
@@ -0,0 +1,26 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_OZONE_EVDEV_FAKE_KEYBOARD_HEURISTIC_METRICS_H_
+#define UI_EVENTS_OZONE_EVDEV_FAKE_KEYBOARD_HEURISTIC_METRICS_H_
+
+#include "chromeos/components/feature_usage/feature_usage_metrics.h"
+
+namespace ui {
+class FakeKeyboardHeuristicMetrics
+ : public feature_usage::FeatureUsageMetrics::Delegate {
+ public:
+ explicit FakeKeyboardHeuristicMetrics();
+ ~FakeKeyboardHeuristicMetrics() override;
+
+ bool IsEligible() const override;
+ bool IsEnabled() const override;
+ void RecordUsage(bool success);
+
+ private:
+ feature_usage::FeatureUsageMetrics feature_usage_metrics_;
+};
+} // namespace ui
+
+#endif // UI_EVENTS_OZONE_EVDEV_FAKE_KEYBOARD_HEURISTIC_METRICS_H_
diff --git a/chromium/ui/events/ozone/evdev/gamepad_event_converter_evdev.cc b/chromium/ui/events/ozone/evdev/gamepad_event_converter_evdev.cc
index 46129d638b0..fec1d4fa814 100644
--- a/chromium/ui/events/ozone/evdev/gamepad_event_converter_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/gamepad_event_converter_evdev.cc
@@ -58,6 +58,14 @@ GamepadEventConverterEvdev::GamepadEventConverterEvdev(
}
}
supports_rumble_ = devinfo.SupportsRumble();
+ // Converts unsigned long to uint64_t.
+ const auto key_bits = devinfo.GetKeyBits();
+ key_bits_.resize(key_bits.size());
+ for (int i = 0; i < KEY_CNT; i++) {
+ if (EvdevBitIsSet(key_bits.data(), i)) {
+ EvdevSetUint64Bit(key_bits_.data(), i);
+ }
+ }
}
GamepadEventConverterEvdev::~GamepadEventConverterEvdev() {
@@ -199,6 +207,10 @@ bool GamepadEventConverterEvdev::GetGamepadRumbleCapability() const {
return supports_rumble_;
}
+std::vector<uint64_t> GamepadEventConverterEvdev::GetGamepadKeyBits() const {
+ return key_bits_;
+}
+
void GamepadEventConverterEvdev::ProcessEvent(const input_event& evdev_ev) {
base::TimeTicks timestamp = TimeTicksFromInputEvent(evdev_ev);
// We may have missed Gamepad releases. Reset everything.
diff --git a/chromium/ui/events/ozone/evdev/gamepad_event_converter_evdev.h b/chromium/ui/events/ozone/evdev/gamepad_event_converter_evdev.h
index 09f905350d0..9270c332e74 100644
--- a/chromium/ui/events/ozone/evdev/gamepad_event_converter_evdev.h
+++ b/chromium/ui/events/ozone/evdev/gamepad_event_converter_evdev.h
@@ -43,6 +43,7 @@ class COMPONENT_EXPORT(EVDEV) GamepadEventConverterEvdev
void OnDisabled() override;
std::vector<ui::GamepadDevice::Axis> GetGamepadAxes() const override;
bool GetGamepadRumbleCapability() const override;
+ std::vector<uint64_t> GetGamepadKeyBits() const override;
// This function processes one input_event from evdev.
void ProcessEvent(const struct input_event& input);
@@ -124,6 +125,8 @@ class COMPONENT_EXPORT(EVDEV) GamepadEventConverterEvdev
// The effect id is needed to keep track of effects that are uploaded and
// stored in the gamepad device.
int effect_id_;
+
+ std::vector<uint64_t> key_bits_;
};
} // namespace ui
diff --git a/chromium/ui/events/ozone/evdev/gamepad_event_converter_evdev_unittest.cc b/chromium/ui/events/ozone/evdev/gamepad_event_converter_evdev_unittest.cc
index c0c77021b42..d0c7117804a 100644
--- a/chromium/ui/events/ozone/evdev/gamepad_event_converter_evdev_unittest.cc
+++ b/chromium/ui/events/ozone/evdev/gamepad_event_converter_evdev_unittest.cc
@@ -23,6 +23,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/base_event_utils.h"
+#include "ui/events/devices/device_util_linux.h"
#include "ui/events/event.h"
#include "ui/events/ozone/device/device_manager.h"
#include "ui/events/ozone/evdev/event_converter_test_util.h"
@@ -251,4 +252,15 @@ TEST_F(GamepadEventConverterEvdevTest, XboxGamepadVibrationEvents) {
EXPECT_EQ(expected_events[1].value, received_cancel_event.value);
}
+TEST_F(GamepadEventConverterEvdevTest, XboxGamepadHasKeys) {
+ TestGamepadObserver observer;
+ std::unique_ptr<ui::TestGamepadEventConverterEvdev> dev =
+ CreateDevice(kXboxGamepad);
+
+ const std::vector<uint64_t> key_bits = dev->GetGamepadKeyBits();
+
+ // BTN_A should be supported.
+ EXPECT_TRUE(EvdevBitUint64IsSet(key_bits.data(), 305));
+}
+
} // namespace ui
diff --git a/chromium/ui/events/ozone/evdev/input_controller_evdev.cc b/chromium/ui/events/ozone/evdev/input_controller_evdev.cc
index 61107110a3a..5e42002b8ed 100644
--- a/chromium/ui/events/ozone/evdev/input_controller_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/input_controller_evdev.cc
@@ -108,6 +108,18 @@ void InputControllerEvdev::GetAutoRepeatRate(base::TimeDelta* delay,
keyboard_->GetAutoRepeatRate(delay, interval);
}
+void InputControllerEvdev::SetKeyboardKeyBitsMapping(
+ base::flat_map<int, std::vector<uint64_t>> key_bits_mapping) {
+ keyboard_key_bits_mapping_ = std::move(key_bits_mapping);
+}
+
+std::vector<uint64_t> InputControllerEvdev::GetKeyboardKeyBits(int id) {
+ auto key_bits_mapping_iter = keyboard_key_bits_mapping_.find(id);
+ return key_bits_mapping_iter == keyboard_key_bits_mapping_.end()
+ ? std::vector<uint64_t>()
+ : key_bits_mapping_iter->second;
+}
+
void InputControllerEvdev::SetCurrentLayoutByName(
const std::string& layout_name) {
keyboard_->SetCurrentLayoutByName(layout_name);
@@ -205,6 +217,18 @@ void InputControllerEvdev::SetPointingStickAcceleration(bool enabled) {
ScheduleUpdateDeviceSettings();
}
+void InputControllerEvdev::SetGamepadKeyBitsMapping(
+ base::flat_map<int, std::vector<uint64_t>> key_bits_mapping) {
+ gamepad_key_bits_mapping_ = std::move(key_bits_mapping);
+}
+
+std::vector<uint64_t> InputControllerEvdev::GetGamepadKeyBits(int id) {
+ auto gamepad_key_bits_iter = gamepad_key_bits_mapping_.find(id);
+ return gamepad_key_bits_iter == gamepad_key_bits_mapping_.end()
+ ? std::vector<uint64_t>()
+ : gamepad_key_bits_iter->second;
+}
+
void InputControllerEvdev::SetPrimaryButtonRight(bool right) {
mouse_button_map_->SetPrimaryButtonRight(right);
}
diff --git a/chromium/ui/events/ozone/evdev/input_controller_evdev.h b/chromium/ui/events/ozone/evdev/input_controller_evdev.h
index 52765901c51..6aa1b8bdf41 100644
--- a/chromium/ui/events/ozone/evdev/input_controller_evdev.h
+++ b/chromium/ui/events/ozone/evdev/input_controller_evdev.h
@@ -61,6 +61,9 @@ class COMPONENT_EXPORT(EVDEV) InputControllerEvdev : public InputController {
void GetAutoRepeatRate(base::TimeDelta* delay,
base::TimeDelta* interval) override;
void SetCurrentLayoutByName(const std::string& layout_name) override;
+ void SetKeyboardKeyBitsMapping(
+ base::flat_map<int, std::vector<uint64_t>> key_bits_mapping) override;
+ std::vector<uint64_t> GetKeyboardKeyBits(int id) override;
void SetTouchEventLoggingEnabled(bool enabled) override;
void SetTouchpadSensitivity(int value) override;
void SetTouchpadScrollSensitivity(int value) override;
@@ -81,6 +84,9 @@ class COMPONENT_EXPORT(EVDEV) InputControllerEvdev : public InputController {
void SetPointingStickSensitivity(int value) override;
void SetPointingStickPrimaryButtonRight(bool right) override;
void SetPointingStickAcceleration(bool enabled) override;
+ void SetGamepadKeyBitsMapping(
+ base::flat_map<int, std::vector<uint64_t>> key_bits_mapping) override;
+ std::vector<uint64_t> GetGamepadKeyBits(int id) override;
void SetTouchpadAcceleration(bool enabled) override;
void SetTouchpadScrollAcceleration(bool enabled) override;
void SetTapToClickPaused(bool state) override;
@@ -146,12 +152,18 @@ class COMPONENT_EXPORT(EVDEV) InputControllerEvdev : public InputController {
// Keyboard state.
KeyboardEvdev* const keyboard_;
+ // Keyboard keybits.
+ base::flat_map<int, std::vector<uint64_t>> keyboard_key_bits_mapping_;
+
// Mouse button map.
MouseButtonMapEvdev* const mouse_button_map_;
// Pointing stick button map.
MouseButtonMapEvdev* const pointing_stick_button_map_;
+ // Gamepad keybits.
+ base::flat_map<int, std::vector<uint64_t>> gamepad_key_bits_mapping_;
+
// Device presence.
bool has_mouse_ = false;
bool has_pointing_stick_ = false;
diff --git a/chromium/ui/events/ozone/evdev/input_device_factory_evdev.cc b/chromium/ui/events/ozone/evdev/input_device_factory_evdev.cc
index 025bade447f..59ceb06ca91 100644
--- a/chromium/ui/events/ozone/evdev/input_device_factory_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/input_device_factory_evdev.cc
@@ -12,6 +12,7 @@
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/containers/contains.h"
#include "base/files/scoped_file.h"
#include "base/memory/ptr_util.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -24,6 +25,7 @@
#include "ui/events/ozone/evdev/event_converter_evdev_impl.h"
#include "ui/events/ozone/evdev/event_device_info.h"
#include "ui/events/ozone/evdev/gamepad_event_converter_evdev.h"
+#include "ui/events/ozone/evdev/keyboard_imposter_checker_evdev.h"
#include "ui/events/ozone/evdev/microphone_mute_switch_event_converter_evdev.h"
#include "ui/events/ozone/evdev/stylus_button_event_converter_evdev.h"
#include "ui/events/ozone/evdev/switches.h"
@@ -52,24 +54,6 @@ namespace ui {
namespace {
-struct OpenInputDeviceParams {
- // Unique identifier for the new device.
- int id;
-
- // Device path to open.
- base::FilePath path;
-
- // Dispatcher for events.
- DeviceEventDispatcherEvdev* dispatcher;
-
- // State shared between devices.
- CursorDelegateEvdev* cursor;
-#if defined(USE_EVDEV_GESTURES)
- GesturePropertyProvider* gesture_property_provider;
-#endif
- SharedPalmDetectionFilterState* shared_palm_state;
-};
-
#if defined(USE_EVDEV_GESTURES)
void SetGestureIntProperty(GesturePropertyProvider* provider,
int id,
@@ -95,100 +79,6 @@ void SetGestureBoolProperty(GesturePropertyProvider* provider,
#endif
-std::unique_ptr<EventConverterEvdev> CreateConverter(
- const OpenInputDeviceParams& params,
- base::ScopedFD fd,
- const EventDeviceInfo& devinfo) {
-#if defined(USE_LIBINPUT)
- // Use LibInputEventConverter for odd touchpads
- if (devinfo.UseLibinput()) {
- return LibInputEventConverter::Create(params.path, params.id, devinfo,
- params.cursor, params.dispatcher);
- }
-#endif
-
-#if defined(USE_EVDEV_GESTURES)
- // Touchpad or mouse: use gestures library.
- // EventReaderLibevdevCros -> GestureInterpreterLibevdevCros -> DispatchEvent
- if (devinfo.HasTouchpad() || devinfo.HasMouse() ||
- devinfo.HasPointingStick()) {
- std::unique_ptr<GestureInterpreterLibevdevCros> gesture_interp =
- std::make_unique<GestureInterpreterLibevdevCros>(
- params.id, params.cursor, params.gesture_property_provider,
- params.dispatcher);
- return std::make_unique<EventReaderLibevdevCros>(std::move(fd), params.path,
- params.id, devinfo,
- std::move(gesture_interp));
- }
-#endif
-
- // Touchscreen: use TouchEventConverterEvdev.
- if (devinfo.HasTouchscreen()) {
- return TouchEventConverterEvdev::Create(
- std::move(fd), params.path, params.id, devinfo,
- params.shared_palm_state, params.dispatcher);
- }
-
- // Graphics tablet
- if (devinfo.HasTablet()) {
- return base::WrapUnique<EventConverterEvdev>(new TabletEventConverterEvdev(
- std::move(fd), params.path, params.id, params.cursor, devinfo,
- params.dispatcher));
- }
-
- if (devinfo.HasGamepad()) {
- return base::WrapUnique<EventConverterEvdev>(new GamepadEventConverterEvdev(
- std::move(fd), params.path, params.id, devinfo, params.dispatcher));
- }
-
- if (devinfo.IsStylusButtonDevice()) {
- return base::WrapUnique<EventConverterEvdev>(
- new StylusButtonEventConverterEvdev(
- std::move(fd), params.path, params.id, devinfo, params.dispatcher));
- }
-
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- kEnableMicrophoneMuteSwitchDeviceSwitch) &&
- devinfo.IsMicrophoneMuteSwitchDevice()) {
- return base::WrapUnique<EventConverterEvdev>(
- new MicrophoneMuteSwitchEventConverterEvdev(
- std::move(fd), params.path, params.id, devinfo, params.dispatcher));
- }
-
- // Everything else: use EventConverterEvdevImpl.
- return base::WrapUnique<EventConverterEvdevImpl>(
- new EventConverterEvdevImpl(std::move(fd), params.path, params.id,
- devinfo, params.cursor, params.dispatcher));
-}
-
-// Open an input device and construct an EventConverterEvdev.
-std::unique_ptr<EventConverterEvdev> OpenInputDevice(
- const OpenInputDeviceParams& params) {
- const base::FilePath& path = params.path;
- TRACE_EVENT1("evdev", "OpenInputDevice", "path", path.value());
-
- base::ScopedFD fd(open(path.value().c_str(), O_RDWR | O_NONBLOCK));
- if (fd.get() < 0) {
- PLOG(ERROR) << "Cannot open " << path.value();
- return nullptr;
- }
-
- // Use monotonic timestamps for events. The touch code in particular
- // expects event timestamps to correlate to the monotonic clock
- // (base::TimeTicks).
- unsigned int clk = CLOCK_MONOTONIC;
- if (ioctl(fd.get(), EVIOCSCLOCKID, &clk))
- PLOG(ERROR) << "failed to set CLOCK_MONOTONIC";
-
- EventDeviceInfo devinfo;
- if (!devinfo.Initialize(fd.get(), path)) {
- LOG(ERROR) << "Failed to get device information for " << path.value();
- return nullptr;
- }
-
- return CreateConverter(params, std::move(fd), devinfo);
-}
-
bool IsUncategorizedDevice(const EventConverterEvdev& converter) {
return !converter.HasTouchscreen() && !converter.HasKeyboard() &&
!converter.HasMouse() && !converter.HasPointingStick() &&
@@ -199,14 +89,17 @@ bool IsUncategorizedDevice(const EventConverterEvdev& converter) {
InputDeviceFactoryEvdev::InputDeviceFactoryEvdev(
std::unique_ptr<DeviceEventDispatcherEvdev> dispatcher,
- CursorDelegateEvdev* cursor)
+ CursorDelegateEvdev* cursor,
+ std::unique_ptr<InputDeviceOpener> input_device_opener)
: task_runner_(base::ThreadTaskRunnerHandle::Get()),
cursor_(cursor),
shared_palm_state_(new SharedPalmDetectionFilterState),
#if defined(USE_EVDEV_GESTURES)
gesture_property_provider_(new GesturePropertyProvider),
#endif
- dispatcher_(std::move(dispatcher)) {
+ dispatcher_(std::move(dispatcher)),
+ keyboard_imposter_checker_(new KeyboardImposterCheckerEvdev),
+ input_device_opener_(std::move(input_device_opener)) {
}
InputDeviceFactoryEvdev::~InputDeviceFactoryEvdev() = default;
@@ -224,7 +117,8 @@ void InputDeviceFactoryEvdev::AddInputDevice(int id,
params.gesture_property_provider = gesture_property_provider_.get();
#endif
- std::unique_ptr<EventConverterEvdev> converter = OpenInputDevice(params);
+ std::unique_ptr<EventConverterEvdev> converter =
+ input_device_opener_->OpenInputDevice(params);
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
@@ -278,11 +172,31 @@ void InputDeviceFactoryEvdev::AttachInputDevice(
base::Unretained(this)));
}
+ if ((converter->type() == InputDeviceType::INPUT_DEVICE_USB ||
+ converter->type() == InputDeviceType::INPUT_DEVICE_BLUETOOTH) &&
+ converter->HasKeyboard()) {
+ converter->SetReceivedValidInputCallback(base::BindRepeating(
+ &InputDeviceFactoryEvdev::UpdateKeyboardDevicesOnKeyPress,
+ base::Unretained(this)));
+ }
+
// Add initialized device to map.
converters_[path] = std::move(converter);
converters_[path]->Start();
+
UpdateDirtyFlags(converters_[path].get());
+ // Register device on physical port & get ids of devices on the same
+ // physical port.
+ std::vector<int> ids_to_check =
+ keyboard_imposter_checker_->OnDeviceAdded(converters_[path].get());
+ // Check for imposters on all devices that share the same physical port.
+ for (const auto& it : converters_) {
+ if (base::Contains(ids_to_check, it.second->id()) &&
+ keyboard_imposter_checker_->FlagIfImposter(it.second.get()))
+ UpdateDirtyFlags(it.second.get());
+ }
+
// Sync settings to new device.
ApplyInputDeviceSettings();
ApplyCapsLockLed();
@@ -307,6 +221,19 @@ void InputDeviceFactoryEvdev::DetachInputDevice(const base::FilePath& path) {
// Cancel libevent notifications from this converter.
converter->Stop();
+ // Decrement device count on physical port. Get ids of devices on the same
+ // physical port.
+ std::vector<int> ids_to_check =
+ keyboard_imposter_checker_->OnDeviceRemoved(converter.get());
+ // Check for imposters on all devices that share the same physical port.
+ // Declassify any devices as no longer imposters, if the removal of this
+ // device changes their status.
+ for (const auto& it : converters_) {
+ if (base::Contains(ids_to_check, it.second->id()) &&
+ !keyboard_imposter_checker_->FlagIfImposter(it.second.get()))
+ UpdateDirtyFlags(it.second.get());
+ }
+
UpdateDirtyFlags(converter.get());
NotifyDevicesUpdated();
}
@@ -600,14 +527,16 @@ void InputDeviceFactoryEvdev::NotifyTouchscreensUpdated() {
}
void InputDeviceFactoryEvdev::NotifyKeyboardsUpdated() {
+ base::flat_map<int, std::vector<uint64_t>> key_bits_mapping;
std::vector<InputDevice> keyboards;
for (auto it = converters_.begin(); it != converters_.end(); ++it) {
if (it->second->HasKeyboard()) {
keyboards.push_back(InputDevice(it->second->input_device()));
+ key_bits_mapping[it->second->id()] = it->second->GetKeyboardKeyBits();
}
}
-
- dispatcher_->DispatchKeyboardDevicesUpdated(keyboards);
+ dispatcher_->DispatchKeyboardDevicesUpdated(keyboards,
+ std::move(key_bits_mapping));
}
void InputDeviceFactoryEvdev::NotifyMouseDevicesUpdated() {
@@ -616,7 +545,9 @@ void InputDeviceFactoryEvdev::NotifyMouseDevicesUpdated() {
for (auto it = converters_.begin(); it != converters_.end(); ++it) {
if (it->second->HasMouse()) {
mice.push_back(it->second->input_device());
- has_mouse = true;
+ // Some I2C touchpads falsely claim to be mice, see b/205272718
+ if (it->second->type() != ui::InputDeviceType::INPUT_DEVICE_INTERNAL)
+ has_mouse = true;
} else if (it->second->HasPointingStick()) {
mice.push_back(it->second->input_device());
has_pointing_stick = true;
@@ -641,16 +572,18 @@ void InputDeviceFactoryEvdev::NotifyTouchpadDevicesUpdated() {
}
void InputDeviceFactoryEvdev::NotifyGamepadDevicesUpdated() {
+ base::flat_map<int, std::vector<uint64_t>> key_bits_mapping;
std::vector<GamepadDevice> gamepads;
for (auto it = converters_.begin(); it != converters_.end(); ++it) {
if (it->second->HasGamepad()) {
gamepads.emplace_back(it->second->input_device(),
it->second->GetGamepadAxes(),
it->second->GetGamepadRumbleCapability());
+ key_bits_mapping[it->second->id()] = it->second->GetGamepadKeyBits();
}
}
- dispatcher_->DispatchGamepadDevicesUpdated(gamepads);
+ dispatcher_->DispatchGamepadDevicesUpdated(gamepads, std::move(key_bits_mapping));
}
void InputDeviceFactoryEvdev::NotifyUncategorizedDevicesUpdated() {
@@ -663,6 +596,12 @@ void InputDeviceFactoryEvdev::NotifyUncategorizedDevicesUpdated() {
dispatcher_->DispatchUncategorizedDevicesUpdated(uncategorized_devices);
}
+void InputDeviceFactoryEvdev::UpdateKeyboardDevicesOnKeyPress(
+ const EventConverterEvdev* converter) {
+ UpdateDirtyFlags(converter);
+ NotifyDevicesUpdated();
+}
+
void InputDeviceFactoryEvdev::SetIntPropertyForOneType(
const EventDeviceType type,
const std::string& name,
diff --git a/chromium/ui/events/ozone/evdev/input_device_factory_evdev.h b/chromium/ui/events/ozone/evdev/input_device_factory_evdev.h
index 63e759b7e59..c4256533453 100644
--- a/chromium/ui/events/ozone/evdev/input_device_factory_evdev.h
+++ b/chromium/ui/events/ozone/evdev/input_device_factory_evdev.h
@@ -21,7 +21,9 @@
#include "ui/events/devices/haptic_touchpad_effects.h"
#include "ui/events/ozone/evdev/event_converter_evdev.h"
#include "ui/events/ozone/evdev/event_device_info.h"
+#include "ui/events/ozone/evdev/input_device_opener.h"
#include "ui/events/ozone/evdev/input_device_settings_evdev.h"
+#include "ui/events/ozone/evdev/keyboard_imposter_checker_evdev.h"
#include "ui/events/ozone/evdev/touch_evdev_types.h"
#include "ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.h"
#include "ui/ozone/public/input_controller.h"
@@ -50,7 +52,8 @@ class COMPONENT_EXPORT(EVDEV) InputDeviceFactoryEvdev {
public:
InputDeviceFactoryEvdev(
std::unique_ptr<DeviceEventDispatcherEvdev> dispatcher,
- CursorDelegateEvdev* cursor);
+ CursorDelegateEvdev* cursor,
+ std::unique_ptr<InputDeviceOpener> input_device_opener);
InputDeviceFactoryEvdev(const InputDeviceFactoryEvdev&) = delete;
InputDeviceFactoryEvdev& operator=(const InputDeviceFactoryEvdev&) = delete;
@@ -118,6 +121,10 @@ class COMPONENT_EXPORT(EVDEV) InputDeviceFactoryEvdev {
void NotifyGamepadDevicesUpdated();
void NotifyUncategorizedDevicesUpdated();
+ // Method used as callback to update keyboard list when a valid key press is
+ // received.
+ void UpdateKeyboardDevicesOnKeyPress(const EventConverterEvdev* converter);
+
void SetIntPropertyForOneType(const EventDeviceType type,
const std::string& name,
int value);
@@ -175,6 +182,11 @@ class COMPONENT_EXPORT(EVDEV) InputDeviceFactoryEvdev {
// Device settings. These primarily affect libgestures behavior.
InputDeviceSettingsEvdev input_device_settings_;
+ // Checks if a device identifying as a keyboard is another device
+ // mis-identifying as one.
+ const std::unique_ptr<KeyboardImposterCheckerEvdev>
+ keyboard_imposter_checker_;
+
// Owned per-device event converters (by path).
// NB: This should be destroyed early, before any shared state.
std::map<base::FilePath, std::unique_ptr<EventConverterEvdev>> converters_;
@@ -182,6 +194,9 @@ class COMPONENT_EXPORT(EVDEV) InputDeviceFactoryEvdev {
// The latest stylus state, updated every time a stylus report comes.
InProgressStylusState latest_stylus_state_;
+ // Handles ioctl calls and creation of event converters.
+ const std::unique_ptr<InputDeviceOpener> input_device_opener_;
+
// Support weak pointers for attach & detach callbacks.
base::WeakPtrFactory<InputDeviceFactoryEvdev> weak_ptr_factory_{this};
};
diff --git a/chromium/ui/events/ozone/evdev/input_device_factory_evdev_unittest.cc b/chromium/ui/events/ozone/evdev/input_device_factory_evdev_unittest.cc
new file mode 100644
index 00000000000..a6e97a1bc64
--- /dev/null
+++ b/chromium/ui/events/ozone/evdev/input_device_factory_evdev_unittest.cc
@@ -0,0 +1,440 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/ozone/evdev/input_device_factory_evdev.h"
+
+#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/task_environment.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/devices/input_device.h"
+#include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h"
+#include "ui/events/ozone/evdev/event_converter_test_util.h"
+#include "ui/events/ozone/evdev/event_device_info.h"
+#include "ui/events/ozone/evdev/event_device_test_util.h"
+#include "ui/events/ozone/evdev/input_device_opener.h"
+#include "ui/events/ozone/features.h"
+
+namespace ui {
+
+class FakeEventConverterEvdev : public EventConverterEvdev {
+ public:
+ explicit FakeEventConverterEvdev(int fd,
+ base::FilePath path,
+ int id,
+ InputDeviceType type,
+ const std::string& name,
+ const std::string& phys,
+ uint16_t vendor_id,
+ uint16_t product_id,
+ uint16_t version,
+ bool has_mouse,
+ bool has_keyboard)
+ : EventConverterEvdev(fd,
+ path,
+ id,
+ type,
+ name,
+ phys,
+ vendor_id,
+ product_id,
+ version),
+
+ has_mouse_(has_mouse),
+ has_keyboard_(has_keyboard) {}
+
+ bool HasMouse() const override { return has_mouse_; }
+
+ bool HasKeyboard() const override { return has_keyboard_; }
+
+ void OnFileCanReadWithoutBlocking(int fd) override {}
+ void SetKeyFilter(bool enable_filter,
+ std::vector<DomCode> allowed_keys) override {}
+
+ private:
+ bool has_mouse_;
+ bool has_keyboard_;
+};
+
+class StubDeviceEventDispatcherEvdev : public DeviceEventDispatcherEvdev {
+ public:
+ explicit StubDeviceEventDispatcherEvdev(
+ base::RepeatingCallback<void(const std::vector<InputDevice>& devices)>
+ callback)
+ : callback_(callback) {}
+ ~StubDeviceEventDispatcherEvdev() override = default;
+
+ void DispatchKeyEvent(const KeyEventParams& params) override {}
+ void DispatchMouseMoveEvent(const MouseMoveEventParams& params) override {}
+ void DispatchMouseButtonEvent(const MouseButtonEventParams& params) override {
+ }
+ void DispatchMouseWheelEvent(const MouseWheelEventParams& params) override {}
+ void DispatchPinchEvent(const PinchEventParams& params) override {}
+ void DispatchScrollEvent(const ScrollEventParams& params) override {}
+ void DispatchTouchEvent(const TouchEventParams& params) override {}
+ void DispatchMicrophoneMuteSwitchValueChanged(bool muted) override {}
+
+ void DispatchKeyboardDevicesUpdated(
+ const std::vector<InputDevice>& devices,
+ base::flat_map<int, std::vector<uint64_t>> key_bits_mapping) override {
+ callback_.Run(devices);
+ }
+ void DispatchTouchscreenDevicesUpdated(
+ const std::vector<TouchscreenDevice>& devices) override {}
+ void DispatchMouseDevicesUpdated(const std::vector<InputDevice>& devices,
+ bool has_mouse,
+ bool has_pointing_stick) override {}
+ void DispatchTouchpadDevicesUpdated(const std::vector<InputDevice>& devices,
+ bool has_haptic_touchpad) override {}
+ void DispatchUncategorizedDevicesUpdated(
+ const std::vector<InputDevice>& devices) override {}
+ void DispatchDeviceListsComplete() override {}
+ void DispatchStylusStateChanged(StylusState stylus_state) override {}
+
+ void DispatchGamepadEvent(const GamepadEvent& event) override {}
+
+ void DispatchGamepadDevicesUpdated(
+ const std::vector<GamepadDevice>& devices,
+ base::flat_map<int, std::vector<uint64_t>> key_bits_mapping) override {}
+
+ private:
+ base::RepeatingCallback<void(const std::vector<InputDevice>& devices)>
+ callback_;
+};
+
+class FakeInputDeviceOpenerEvdev : public InputDeviceOpener {
+ public:
+ explicit FakeInputDeviceOpenerEvdev(
+ std::vector<std::unique_ptr<FakeEventConverterEvdev>> converters)
+ : converters_(std::move(converters)) {}
+
+ std::vector<std::unique_ptr<FakeEventConverterEvdev>> converters_;
+
+ std::unique_ptr<EventConverterEvdev> OpenInputDevice(
+ const OpenInputDeviceParams& params) override {
+ std::unique_ptr<FakeEventConverterEvdev> converter =
+ std::move(converters_[0]);
+ converters_.erase(converters_.begin());
+ return std::move(converter);
+ }
+};
+
+class InputDeviceFactoryEvdevTest : public testing::Test {
+ public:
+ InputDeviceFactoryEvdevTest() = default;
+
+ std::vector<InputDevice> keyboards_;
+ base::test::SingleThreadTaskEnvironment task_environment{
+ base::test::TaskEnvironment::MainThreadType::UI};
+ base::test::ScopedFeatureList scoped_feature_list_;
+ std::unique_ptr<ui::DeviceEventDispatcherEvdev> dispatcher_;
+
+ void SetUp() override {
+ dispatcher_ = std::make_unique<StubDeviceEventDispatcherEvdev>(
+ base::BindRepeating(&InputDeviceFactoryEvdevTest::DispatchCallback,
+ base::Unretained(this)));
+ }
+
+ private:
+ void DispatchCallback(const std::vector<InputDevice>& devices) {
+ keyboards_ = devices;
+ }
+};
+
+TEST_F(InputDeviceFactoryEvdevTest,
+ AttachSingularKeyboardFakeKeyboardHeuristicEnabled) {
+ scoped_feature_list_.InitAndEnableFeature(kEnableFakeKeyboardHeuristic);
+ std::vector<std::unique_ptr<FakeEventConverterEvdev>> converters;
+ base::RunLoop run_loop;
+ std::unique_ptr<FakeEventConverterEvdev> keyboard_converter =
+ std::make_unique<FakeEventConverterEvdev>(
+ 1, base::FilePath("path"), 1, InputDeviceType::INPUT_DEVICE_INTERNAL,
+ "name", "phys_path", 1, 1, 1, false, true);
+
+ converters.push_back(std::move(keyboard_converter));
+
+ std::unique_ptr<InputDeviceFactoryEvdev> input_device_factory_ =
+ std::make_unique<InputDeviceFactoryEvdev>(
+ std::move(dispatcher_), nullptr,
+ std::make_unique<FakeInputDeviceOpenerEvdev>(std::move(converters)));
+ input_device_factory_->OnStartupScanComplete();
+ input_device_factory_->AddInputDevice(1, base::FilePath("unused_value"));
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ run_loop.QuitClosure());
+ run_loop.Run();
+ EXPECT_EQ(keyboards_.size(), std::size_t(1));
+ EXPECT_FALSE(keyboards_.front().suspected_imposter);
+}
+
+TEST_F(InputDeviceFactoryEvdevTest, AttachSingularMouse) {
+ std::vector<std::unique_ptr<FakeEventConverterEvdev>> converters;
+ base::RunLoop run_loop;
+ std::unique_ptr<FakeEventConverterEvdev> mouse_converter =
+ std::make_unique<FakeEventConverterEvdev>(
+ 1, base::FilePath("path"), 1, InputDeviceType::INPUT_DEVICE_INTERNAL,
+ "name", "phys_path", 1, 1, 1, true, false);
+
+ converters.push_back(std::move(mouse_converter));
+
+ std::unique_ptr<InputDeviceFactoryEvdev> input_device_factory_ =
+ std::make_unique<InputDeviceFactoryEvdev>(
+ std::move(dispatcher_), nullptr,
+ std::make_unique<FakeInputDeviceOpenerEvdev>(std::move(converters)));
+ input_device_factory_->OnStartupScanComplete();
+ input_device_factory_->AddInputDevice(1, base::FilePath("unused_value"));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ run_loop.QuitClosure());
+ run_loop.Run();
+ EXPECT_EQ(keyboards_.size(), std::size_t(0));
+}
+
+TEST_F(InputDeviceFactoryEvdevTest,
+ AttachMouseAndKeyboardDifferentPhysFakeKeyboardHeuristicEnabled) {
+ scoped_feature_list_.InitAndEnableFeature(kEnableFakeKeyboardHeuristic);
+ std::vector<std::unique_ptr<FakeEventConverterEvdev>> converters;
+ base::RunLoop run_loop;
+ std::unique_ptr<FakeEventConverterEvdev> mouse_converter =
+ std::make_unique<FakeEventConverterEvdev>(
+ 1, base::FilePath("mouse_path"), 1,
+ InputDeviceType::INPUT_DEVICE_INTERNAL, "mouse_name",
+ "phys_path/mouse", 1, 1, 1, true, false);
+ std::unique_ptr<FakeEventConverterEvdev> keyboard_converter =
+ std::make_unique<FakeEventConverterEvdev>(
+ 2, base::FilePath("keyboard_path"), 2,
+ InputDeviceType::INPUT_DEVICE_INTERNAL, "keyboard_name",
+ "phys_path/keyboard", 2, 2, 2, false, true);
+
+ converters.push_back(std::move(mouse_converter));
+ converters.push_back(std::move(keyboard_converter));
+
+ std::unique_ptr<InputDeviceFactoryEvdev> input_device_factory_ =
+ std::make_unique<InputDeviceFactoryEvdev>(
+ std::move(dispatcher_), nullptr,
+ std::make_unique<FakeInputDeviceOpenerEvdev>(std::move(converters)));
+ input_device_factory_->OnStartupScanComplete();
+ input_device_factory_->AddInputDevice(1, base::FilePath("unused_value"));
+ input_device_factory_->AddInputDevice(2, base::FilePath("unused_value"));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ run_loop.QuitClosure());
+ run_loop.Run();
+ EXPECT_EQ(keyboards_.size(), std::size_t(1));
+ EXPECT_FALSE(keyboards_.front().suspected_imposter);
+}
+
+TEST_F(InputDeviceFactoryEvdevTest,
+ AttachMouseAndKeyboardSamePhysFakeKeyboardHeuristicEnabled) {
+ scoped_feature_list_.InitAndEnableFeature(kEnableFakeKeyboardHeuristic);
+ std::vector<std::unique_ptr<FakeEventConverterEvdev>> converters;
+ base::RunLoop run_loop;
+ std::unique_ptr<FakeEventConverterEvdev> mouse_converter =
+ std::make_unique<FakeEventConverterEvdev>(
+ 1, base::FilePath("mouse_path"), 1,
+ InputDeviceType::INPUT_DEVICE_INTERNAL, "mouse_name", "phys_path", 1,
+ 1, 1, true, false);
+ std::unique_ptr<FakeEventConverterEvdev> keyboard_converter =
+ std::make_unique<FakeEventConverterEvdev>(
+ 2, base::FilePath("keyboard_path"), 2,
+ InputDeviceType::INPUT_DEVICE_INTERNAL, "keyboard_name", "phys_path",
+ 2, 2, 2, false, true);
+
+ converters.push_back(std::move(mouse_converter));
+ converters.push_back(std::move(keyboard_converter));
+
+ std::unique_ptr<InputDeviceFactoryEvdev> input_device_factory_ =
+ std::make_unique<InputDeviceFactoryEvdev>(
+ std::move(dispatcher_), nullptr,
+ std::make_unique<FakeInputDeviceOpenerEvdev>(std::move(converters)));
+ input_device_factory_->OnStartupScanComplete();
+ input_device_factory_->AddInputDevice(1, base::FilePath("unused_value"));
+ input_device_factory_->AddInputDevice(2, base::FilePath("unused_value"));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ run_loop.QuitClosure());
+ run_loop.Run();
+ EXPECT_EQ(keyboards_.size(), std::size_t(1));
+ EXPECT_TRUE(keyboards_.front().suspected_imposter);
+}
+
+TEST_F(InputDeviceFactoryEvdevTest,
+ AttachSingularKeyboardAndMouseFakeKeyboardHeuristicEnabled) {
+ scoped_feature_list_.InitAndEnableFeature(kEnableFakeKeyboardHeuristic);
+ std::vector<std::unique_ptr<FakeEventConverterEvdev>> converters;
+ base::RunLoop run_loop;
+ std::unique_ptr<FakeEventConverterEvdev> keyboard_and_mouse_converter =
+ std::make_unique<FakeEventConverterEvdev>(
+ 1, base::FilePath("path"), 1, InputDeviceType::INPUT_DEVICE_INTERNAL,
+ "name", "phys_path", 1, 1, 1, true, true);
+
+ converters.push_back(std::move(keyboard_and_mouse_converter));
+
+ std::unique_ptr<InputDeviceFactoryEvdev> input_device_factory_ =
+ std::make_unique<InputDeviceFactoryEvdev>(
+ std::move(dispatcher_), nullptr,
+ std::make_unique<FakeInputDeviceOpenerEvdev>(std::move(converters)));
+ input_device_factory_->OnStartupScanComplete();
+ input_device_factory_->AddInputDevice(1, base::FilePath("unused_value"));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ run_loop.QuitClosure());
+ run_loop.Run();
+ EXPECT_EQ(keyboards_.size(), std::size_t(1));
+ EXPECT_TRUE(keyboards_.front().suspected_imposter);
+}
+
+TEST_F(InputDeviceFactoryEvdevTest,
+ AttachSingularKeyboardFakeKeyboardHeuristicDisabled) {
+ scoped_feature_list_.InitAndDisableFeature(kEnableFakeKeyboardHeuristic);
+ std::vector<std::unique_ptr<FakeEventConverterEvdev>> converters;
+ base::RunLoop run_loop;
+ std::unique_ptr<FakeEventConverterEvdev> keyboard_converter =
+ std::make_unique<FakeEventConverterEvdev>(
+ 1, base::FilePath("path"), 1, InputDeviceType::INPUT_DEVICE_INTERNAL,
+ "name", "phys_path", 1, 1, 1, false, true);
+
+ converters.push_back(std::move(keyboard_converter));
+
+ std::unique_ptr<InputDeviceFactoryEvdev> input_device_factory_ =
+ std::make_unique<InputDeviceFactoryEvdev>(
+ std::move(dispatcher_), nullptr,
+ std::make_unique<FakeInputDeviceOpenerEvdev>(std::move(converters)));
+ input_device_factory_->OnStartupScanComplete();
+ input_device_factory_->AddInputDevice(1, base::FilePath("unused_value"));
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ run_loop.QuitClosure());
+ run_loop.Run();
+ EXPECT_EQ(keyboards_.size(), std::size_t(1));
+ EXPECT_FALSE(keyboards_.front().suspected_imposter);
+}
+
+TEST_F(InputDeviceFactoryEvdevTest,
+ AttachMouseAndKeyboardDifferentPhysFakeKeyboardHeuristicDisabled) {
+ scoped_feature_list_.InitAndDisableFeature(kEnableFakeKeyboardHeuristic);
+ std::vector<std::unique_ptr<FakeEventConverterEvdev>> converters;
+ base::RunLoop run_loop;
+ std::unique_ptr<FakeEventConverterEvdev> mouse_converter =
+ std::make_unique<FakeEventConverterEvdev>(
+ 1, base::FilePath("mouse_path"), 1,
+ InputDeviceType::INPUT_DEVICE_INTERNAL, "mouse_name",
+ "phys_path/mouse", 1, 1, 1, true, false);
+ std::unique_ptr<FakeEventConverterEvdev> keyboard_converter =
+ std::make_unique<FakeEventConverterEvdev>(
+ 2, base::FilePath("keyboard_path"), 2,
+ InputDeviceType::INPUT_DEVICE_INTERNAL, "keyboard_name",
+ "phys_path/keyboard", 2, 2, 2, false, true);
+
+ converters.push_back(std::move(mouse_converter));
+ converters.push_back(std::move(keyboard_converter));
+
+ std::unique_ptr<InputDeviceFactoryEvdev> input_device_factory_ =
+ std::make_unique<InputDeviceFactoryEvdev>(
+ std::move(dispatcher_), nullptr,
+ std::make_unique<FakeInputDeviceOpenerEvdev>(std::move(converters)));
+ input_device_factory_->OnStartupScanComplete();
+ input_device_factory_->AddInputDevice(1, base::FilePath("unused_value"));
+ input_device_factory_->AddInputDevice(2, base::FilePath("unused_value"));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ run_loop.QuitClosure());
+ run_loop.Run();
+ EXPECT_EQ(keyboards_.size(), std::size_t(1));
+ EXPECT_FALSE(keyboards_.front().suspected_imposter);
+}
+
+TEST_F(InputDeviceFactoryEvdevTest,
+ AttachMouseAndKeyboardSamePhysFakeKeyboardHeuristicDisabled) {
+ scoped_feature_list_.InitAndDisableFeature(kEnableFakeKeyboardHeuristic);
+ std::vector<std::unique_ptr<FakeEventConverterEvdev>> converters;
+ base::RunLoop run_loop;
+ std::unique_ptr<FakeEventConverterEvdev> mouse_converter =
+ std::make_unique<FakeEventConverterEvdev>(
+ 1, base::FilePath("mouse_path"), 1,
+ InputDeviceType::INPUT_DEVICE_INTERNAL, "mouse_name", "phys_path", 1,
+ 1, 1, true, false);
+ std::unique_ptr<FakeEventConverterEvdev> keyboard_converter =
+ std::make_unique<FakeEventConverterEvdev>(
+ 2, base::FilePath("keyboard_path"), 2,
+ InputDeviceType::INPUT_DEVICE_INTERNAL, "keyboard_name", "phys_path",
+ 2, 2, 2, false, true);
+
+ converters.push_back(std::move(mouse_converter));
+ converters.push_back(std::move(keyboard_converter));
+
+ std::unique_ptr<InputDeviceFactoryEvdev> input_device_factory_ =
+ std::make_unique<InputDeviceFactoryEvdev>(
+ std::move(dispatcher_), nullptr,
+ std::make_unique<FakeInputDeviceOpenerEvdev>(std::move(converters)));
+ input_device_factory_->OnStartupScanComplete();
+ input_device_factory_->AddInputDevice(1, base::FilePath("unused_value"));
+ input_device_factory_->AddInputDevice(2, base::FilePath("unused_value"));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ run_loop.QuitClosure());
+ run_loop.Run();
+ EXPECT_EQ(keyboards_.size(), std::size_t(1));
+ EXPECT_FALSE(keyboards_.front().suspected_imposter);
+}
+
+TEST_F(InputDeviceFactoryEvdevTest,
+ AttachSingularKeyboardAndMouseFakeKeyboardHeuristicDisabled) {
+ scoped_feature_list_.InitAndDisableFeature(kEnableFakeKeyboardHeuristic);
+ std::vector<std::unique_ptr<FakeEventConverterEvdev>> converters;
+ base::RunLoop run_loop;
+ std::unique_ptr<FakeEventConverterEvdev> keyboard_and_mouse_converter =
+ std::make_unique<FakeEventConverterEvdev>(
+ 1, base::FilePath("path"), 1, InputDeviceType::INPUT_DEVICE_INTERNAL,
+ "name", "phys_path", 1, 1, 1, true, true);
+
+ converters.push_back(std::move(keyboard_and_mouse_converter));
+
+ std::unique_ptr<InputDeviceFactoryEvdev> input_device_factory_ =
+ std::make_unique<InputDeviceFactoryEvdev>(
+ std::move(dispatcher_), nullptr,
+ std::make_unique<FakeInputDeviceOpenerEvdev>(std::move(converters)));
+ input_device_factory_->OnStartupScanComplete();
+ input_device_factory_->AddInputDevice(1, base::FilePath("unused_value"));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ run_loop.QuitClosure());
+ run_loop.Run();
+ EXPECT_EQ(keyboards_.size(), std::size_t(1));
+ EXPECT_FALSE(keyboards_.front().suspected_imposter);
+}
+
+TEST_F(InputDeviceFactoryEvdevTest,
+ AttachAndRemoveDeviceFakeKeyboardHeuristicEnabled) {
+ scoped_feature_list_.InitAndEnableFeature(kEnableFakeKeyboardHeuristic);
+ std::vector<std::unique_ptr<FakeEventConverterEvdev>> converters;
+ base::RunLoop run_loop;
+ base::FilePath mouse_path("mouse_path");
+ std::unique_ptr<FakeEventConverterEvdev> mouse_converter =
+ std::make_unique<FakeEventConverterEvdev>(
+ 1, mouse_path, 1, InputDeviceType::INPUT_DEVICE_INTERNAL,
+ "mouse_name", "phys_path", 1, 1, 1, true, false);
+ std::unique_ptr<FakeEventConverterEvdev> keyboard_converter =
+ std::make_unique<FakeEventConverterEvdev>(
+ 2, base::FilePath("keyboard_path"), 2,
+ InputDeviceType::INPUT_DEVICE_INTERNAL, "keyboard_name", "phys_path",
+ 2, 2, 2, false, true);
+
+ converters.push_back(std::move(mouse_converter));
+ converters.push_back(std::move(keyboard_converter));
+
+ std::unique_ptr<InputDeviceFactoryEvdev> input_device_factory_ =
+ std::make_unique<InputDeviceFactoryEvdev>(
+ std::move(dispatcher_), nullptr,
+ std::make_unique<FakeInputDeviceOpenerEvdev>(std::move(converters)));
+ input_device_factory_->OnStartupScanComplete();
+ input_device_factory_->AddInputDevice(1, base::FilePath("unused_value"));
+ input_device_factory_->AddInputDevice(2, base::FilePath("unused_value"));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ run_loop.QuitClosure());
+ run_loop.Run();
+ EXPECT_EQ(keyboards_.size(), std::size_t(1));
+ EXPECT_TRUE(keyboards_.front().suspected_imposter);
+
+ input_device_factory_->RemoveInputDevice(mouse_path);
+ EXPECT_EQ(keyboards_.size(), std::size_t(1));
+ EXPECT_FALSE(keyboards_.front().suspected_imposter);
+}
+
+} // namespace ui
diff --git a/chromium/ui/events/ozone/evdev/input_device_opener.h b/chromium/ui/events/ozone/evdev/input_device_opener.h
new file mode 100644
index 00000000000..0bf94b45765
--- /dev/null
+++ b/chromium/ui/events/ozone/evdev/input_device_opener.h
@@ -0,0 +1,47 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_OZONE_EVDEV_INPUT_DEVICE_OPENER_H_
+#define UI_EVENTS_OZONE_EVDEV_INPUT_DEVICE_OPENER_H_
+
+#include "ui/events/ozone/evdev/event_converter_evdev.h"
+#include "ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.h"
+
+#if defined(USE_EVDEV_GESTURES)
+#include "ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.h"
+#endif
+
+namespace ui {
+
+class CursorDelegateEvdev;
+class DeviceEventDispatcherEvdev;
+
+struct OpenInputDeviceParams {
+ // Unique identifier for the new device.
+ int id;
+
+ // Device path to open.
+ base::FilePath path;
+
+ // Dispatcher for events.
+ DeviceEventDispatcherEvdev* dispatcher;
+
+ // State shared between devices.
+ CursorDelegateEvdev* cursor;
+#if defined(USE_EVDEV_GESTURES)
+ GesturePropertyProvider* gesture_property_provider;
+#endif
+ SharedPalmDetectionFilterState* shared_palm_state;
+};
+
+class COMPONENT_EXPORT(EVDEV) InputDeviceOpener {
+ public:
+ virtual ~InputDeviceOpener() = default;
+
+ virtual std::unique_ptr<EventConverterEvdev> OpenInputDevice(
+ const OpenInputDeviceParams& params) = 0;
+};
+} // namespace ui
+
+#endif // UI_EVENTS_OZONE_EVDEV_INPUT_DEVICE_OPENER_H_
diff --git a/chromium/ui/events/ozone/evdev/input_device_opener_evdev.cc b/chromium/ui/events/ozone/evdev/input_device_opener_evdev.cc
new file mode 100644
index 00000000000..e91a33054c3
--- /dev/null
+++ b/chromium/ui/events/ozone/evdev/input_device_opener_evdev.cc
@@ -0,0 +1,134 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/ozone/evdev/input_device_opener_evdev.h"
+
+#include <fcntl.h>
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_file.h"
+#include "base/memory/ptr_util.h"
+#include "base/trace_event/trace_event.h"
+#include "ui/events/ozone/evdev/event_converter_evdev_impl.h"
+#include "ui/events/ozone/evdev/gamepad_event_converter_evdev.h"
+#include "ui/events/ozone/evdev/microphone_mute_switch_event_converter_evdev.h"
+#include "ui/events/ozone/evdev/stylus_button_event_converter_evdev.h"
+#include "ui/events/ozone/evdev/switches.h"
+#include "ui/events/ozone/evdev/tablet_event_converter_evdev.h"
+#include "ui/events/ozone/evdev/touch_event_converter_evdev.h"
+
+#if defined(USE_EVDEV_GESTURES)
+#include "ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h"
+#include "ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.h"
+#endif
+
+#if defined(USE_LIBINPUT)
+#include "ui/events/ozone/evdev/libinput_event_converter.h"
+#endif
+
+#ifndef EVIOCSCLOCKID
+#define EVIOCSCLOCKID _IOW('E', 0xa0, int)
+#endif
+
+namespace ui {
+
+namespace {
+
+std::unique_ptr<EventConverterEvdev> CreateConverter(
+ const OpenInputDeviceParams& params,
+ base::ScopedFD fd,
+ const EventDeviceInfo& devinfo) {
+#if defined(USE_LIBINPUT)
+ // Use LibInputEventConverter for odd touchpads
+ if (devinfo.UseLibinput()) {
+ return LibInputEventConverter::Create(params.path, params.id, devinfo,
+ params.cursor, params.dispatcher);
+ }
+#endif
+
+#if defined(USE_EVDEV_GESTURES)
+ // Touchpad or mouse: use gestures library.
+ // EventReaderLibevdevCros -> GestureInterpreterLibevdevCros -> DispatchEvent
+ if (devinfo.HasTouchpad() || devinfo.HasMouse() ||
+ devinfo.HasPointingStick()) {
+ std::unique_ptr<GestureInterpreterLibevdevCros> gesture_interp =
+ std::make_unique<GestureInterpreterLibevdevCros>(
+ params.id, params.cursor, params.gesture_property_provider,
+ params.dispatcher);
+ return std::make_unique<EventReaderLibevdevCros>(std::move(fd), params.path,
+ params.id, devinfo,
+ std::move(gesture_interp));
+ }
+#endif
+
+ // Touchscreen: use TouchEventConverterEvdev.
+ if (devinfo.HasTouchscreen()) {
+ return TouchEventConverterEvdev::Create(
+ std::move(fd), params.path, params.id, devinfo,
+ params.shared_palm_state, params.dispatcher);
+ }
+
+ // Graphics tablet
+ if (devinfo.HasTablet()) {
+ return base::WrapUnique<EventConverterEvdev>(new TabletEventConverterEvdev(
+ std::move(fd), params.path, params.id, params.cursor, devinfo,
+ params.dispatcher));
+ }
+
+ if (devinfo.HasGamepad()) {
+ return base::WrapUnique<EventConverterEvdev>(new GamepadEventConverterEvdev(
+ std::move(fd), params.path, params.id, devinfo, params.dispatcher));
+ }
+
+ if (devinfo.IsStylusButtonDevice()) {
+ return base::WrapUnique<EventConverterEvdev>(
+ new StylusButtonEventConverterEvdev(
+ std::move(fd), params.path, params.id, devinfo, params.dispatcher));
+ }
+
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ kEnableMicrophoneMuteSwitchDeviceSwitch) &&
+ devinfo.IsMicrophoneMuteSwitchDevice()) {
+ return base::WrapUnique<EventConverterEvdev>(
+ new MicrophoneMuteSwitchEventConverterEvdev(
+ std::move(fd), params.path, params.id, devinfo, params.dispatcher));
+ }
+
+ // Everything else: use EventConverterEvdevImpl.
+ return base::WrapUnique<EventConverterEvdevImpl>(
+ new EventConverterEvdevImpl(std::move(fd), params.path, params.id,
+ devinfo, params.cursor, params.dispatcher));
+}
+
+} // namespace
+
+std::unique_ptr<EventConverterEvdev> InputDeviceOpenerEvdev::OpenInputDevice(
+ const OpenInputDeviceParams& params) {
+ const base::FilePath& path = params.path;
+ TRACE_EVENT1("evdev", "OpenInputDevice", "path", path.value());
+
+ base::ScopedFD fd(open(path.value().c_str(), O_RDWR | O_NONBLOCK));
+ if (fd.get() < 0) {
+ PLOG(ERROR) << "Cannot open " << path.value();
+ return nullptr;
+ }
+
+ // Use monotonic timestamps for events. The touch code in particular
+ // expects event timestamps to correlate to the monotonic clock
+ // (base::TimeTicks).
+ unsigned int clk = CLOCK_MONOTONIC;
+ if (ioctl(fd.get(), EVIOCSCLOCKID, &clk))
+ PLOG(ERROR) << "failed to set CLOCK_MONOTONIC";
+
+ EventDeviceInfo devinfo;
+ if (!devinfo.Initialize(fd.get(), path)) {
+ LOG(ERROR) << "Failed to get device information for " << path.value();
+ return nullptr;
+ }
+
+ return CreateConverter(params, std::move(fd), devinfo);
+}
+
+} // namespace ui
diff --git a/chromium/ui/events/ozone/evdev/input_device_opener_evdev.h b/chromium/ui/events/ozone/evdev/input_device_opener_evdev.h
new file mode 100644
index 00000000000..b09d269b05e
--- /dev/null
+++ b/chromium/ui/events/ozone/evdev/input_device_opener_evdev.h
@@ -0,0 +1,30 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_OZONE_EVDEV_INPUT_DEVICE_OPENER_EVDEV_H_
+#define UI_EVENTS_OZONE_EVDEV_INPUT_DEVICE_OPENER_EVDEV_H_
+
+#include "ui/events/ozone/evdev/input_device_opener.h"
+
+#include "base/files/scoped_file.h"
+#include "ui/events/ozone/evdev/event_device_info.h"
+
+namespace ui {
+
+class COMPONENT_EXPORT(EVDEV) InputDeviceOpenerEvdev
+ : public InputDeviceOpener {
+ public:
+ InputDeviceOpenerEvdev() = default;
+
+ InputDeviceOpenerEvdev(const InputDeviceOpenerEvdev&) = delete;
+ InputDeviceOpenerEvdev& operator=(const InputDeviceOpenerEvdev&) = delete;
+
+ ~InputDeviceOpenerEvdev() override = default;
+
+ std::unique_ptr<EventConverterEvdev> OpenInputDevice(
+ const OpenInputDeviceParams& params) override;
+};
+} // namespace ui
+
+#endif // UI_EVENTS_OZONE_EVDEV_INPUT_DEVICE_OPENER_EVDEV_H_
diff --git a/chromium/ui/events/ozone/evdev/keyboard_imposter_checker_evdev.cc b/chromium/ui/events/ozone/evdev/keyboard_imposter_checker_evdev.cc
new file mode 100644
index 00000000000..33c8bb01ff1
--- /dev/null
+++ b/chromium/ui/events/ozone/evdev/keyboard_imposter_checker_evdev.cc
@@ -0,0 +1,74 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/ozone/evdev/keyboard_imposter_checker_evdev.h"
+
+#include "base/containers/cxx20_erase_map.h"
+#include "ui/events/ozone/features.h"
+
+namespace ui {
+
+std::vector<int> KeyboardImposterCheckerEvdev::GetIdsOnSamePhys(
+ const std::string& phys_path) {
+ std::vector<int> ids_on_same_phys;
+ std::pair<std::multimap<std::string, int>::iterator,
+ std::multimap<std::string, int>::iterator>
+ iterators = devices_on_phys_path_.equal_range(phys_path);
+ for (auto& it = iterators.first; it != iterators.second; ++it) {
+ ids_on_same_phys.push_back(it->second);
+ }
+ return ids_on_same_phys;
+}
+
+std::vector<int> KeyboardImposterCheckerEvdev::OnDeviceAdded(
+ EventConverterEvdev* converter) {
+ if (!base::FeatureList::IsEnabled(kEnableFakeKeyboardHeuristic))
+ return std::vector<int>();
+
+ devices_on_phys_path_.emplace(converter->input_device().phys,
+ converter->id());
+ return GetIdsOnSamePhys(converter->input_device().phys);
+}
+
+bool KeyboardImposterCheckerEvdev::FlagIfImposter(
+ EventConverterEvdev* converter) {
+ if (!base::FeatureList::IsEnabled(kEnableFakeKeyboardHeuristic))
+ return false;
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+ if (converter->GetKeyboardType() == KeyboardType::IN_BLOCKLIST) {
+ fake_keyboard_heuristic_metrics_.RecordUsage(false);
+ }
+#endif
+
+ if (!converter->HasKeyboard() ||
+ (!converter->HasMouse() &&
+ devices_on_phys_path_.count(converter->input_device().phys) < 2)) {
+ converter->SetSuspectedImposter(false);
+ return false;
+ }
+
+ converter->SetSuspectedImposter(true);
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+ fake_keyboard_heuristic_metrics_.RecordUsage(true);
+#endif
+ return true;
+}
+
+std::vector<int> KeyboardImposterCheckerEvdev::OnDeviceRemoved(
+ EventConverterEvdev* converter) {
+ if (!base::FeatureList::IsEnabled(kEnableFakeKeyboardHeuristic))
+ return std::vector<int>();
+
+ base::EraseIf(devices_on_phys_path_,
+ [&](const auto& devices_on_phys_path_entry) {
+ return devices_on_phys_path_entry.second == converter->id();
+ });
+ return GetIdsOnSamePhys(converter->input_device().phys);
+}
+
+KeyboardImposterCheckerEvdev::KeyboardImposterCheckerEvdev() = default;
+
+KeyboardImposterCheckerEvdev::~KeyboardImposterCheckerEvdev() = default;
+
+} // namespace ui
diff --git a/chromium/ui/events/ozone/evdev/keyboard_imposter_checker_evdev.h b/chromium/ui/events/ozone/evdev/keyboard_imposter_checker_evdev.h
new file mode 100644
index 00000000000..871416c5f03
--- /dev/null
+++ b/chromium/ui/events/ozone/evdev/keyboard_imposter_checker_evdev.h
@@ -0,0 +1,47 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_OZONE_EVDEV_KEYBOARD_IMPOSTER_CHECKER_EVDEV_H_
+#define UI_EVENTS_OZONE_EVDEV_KEYBOARD_IMPOSTER_CHECKER_EVDEV_H_
+
+#include <map>
+
+#include "base/component_export.h"
+#include "ui/events/devices/input_device.h"
+#include "ui/events/ozone/evdev/event_converter_evdev.h"
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "ui/events/ozone/evdev/fake_keyboard_heuristic_metrics.h"
+#endif
+
+namespace ui {
+class COMPONENT_EXPORT(EVDEV) KeyboardImposterCheckerEvdev {
+ public:
+ // Registers the id of a device on its phys path and returns the ids of all
+ // devices on that phys path.
+ std::vector<int> OnDeviceAdded(EventConverterEvdev* converter);
+ std::vector<int> OnDeviceRemoved(EventConverterEvdev* converter);
+ bool FlagIfImposter(EventConverterEvdev* converter);
+
+ KeyboardImposterCheckerEvdev();
+
+ KeyboardImposterCheckerEvdev(const KeyboardImposterCheckerEvdev&) = delete;
+ KeyboardImposterCheckerEvdev& operator=(const KeyboardImposterCheckerEvdev&) =
+ delete;
+
+ ~KeyboardImposterCheckerEvdev();
+
+ private:
+ std::vector<int> GetIdsOnSamePhys(const std::string& phys_path);
+
+ // Number of devices per phys path.
+ std::multimap<std::string, int> devices_on_phys_path_;
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+ FakeKeyboardHeuristicMetrics fake_keyboard_heuristic_metrics_;
+#endif
+};
+} // namespace ui
+
+#endif // UI_EVENTS_OZONE_EVDEV_KEYBOARD_IMPOSTER_CHECKER_EVDEV_H_
diff --git a/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_properties_service.cc b/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_properties_service.cc
index 40fc6c252a2..64537810dd2 100644
--- a/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_properties_service.cc
+++ b/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_properties_service.cc
@@ -34,15 +34,15 @@ bool PropertyTypeMatchesValues(ui::GesturePropertyProvider::PropertyType type,
GesturePropValue::Tag values_tag) {
switch (type) {
case ui::GesturePropertyProvider::PT_INT:
- return values_tag == GesturePropValue::Tag::INTS;
+ return values_tag == GesturePropValue::Tag::kInts;
case ui::GesturePropertyProvider::PT_SHORT:
- return values_tag == GesturePropValue::Tag::SHORTS;
+ return values_tag == GesturePropValue::Tag::kShorts;
case ui::GesturePropertyProvider::PT_BOOL:
- return values_tag == GesturePropValue::Tag::BOOLS;
+ return values_tag == GesturePropValue::Tag::kBools;
case ui::GesturePropertyProvider::PT_STRING:
- return values_tag == GesturePropValue::Tag::STR;
+ return values_tag == GesturePropValue::Tag::kStr;
case ui::GesturePropertyProvider::PT_REAL:
- return values_tag == GesturePropValue::Tag::REALS;
+ return values_tag == GesturePropValue::Tag::kReals;
}
// This should never happen.
return false;
@@ -121,19 +121,19 @@ void GesturePropertiesService::SetProperty(
}
size_t num_values;
switch (values->which()) {
- case ozone::mojom::GesturePropValue::Tag::INTS:
+ case ozone::mojom::GesturePropValue::Tag::kInts:
num_values = values->get_ints().size();
break;
- case ozone::mojom::GesturePropValue::Tag::SHORTS:
+ case ozone::mojom::GesturePropValue::Tag::kShorts:
num_values = values->get_shorts().size();
break;
- case ozone::mojom::GesturePropValue::Tag::BOOLS:
+ case ozone::mojom::GesturePropValue::Tag::kBools:
num_values = values->get_bools().size();
break;
- case ozone::mojom::GesturePropValue::Tag::STR:
+ case ozone::mojom::GesturePropValue::Tag::kStr:
num_values = 1;
break;
- case ozone::mojom::GesturePropValue::Tag::REALS:
+ case ozone::mojom::GesturePropValue::Tag::kReals:
num_values = values->get_reals().size();
break;
}
diff --git a/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.cc b/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.cc
index 79712903656..4068429e0c1 100644
--- a/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.cc
+++ b/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.cc
@@ -503,11 +503,11 @@ bool IsMatchDeviceType(const std::string& match_type) {
// Parse a boolean value keyword (e.g., on/off, true/false).
int ParseBooleanKeyword(const std::string& value) {
for (size_t i = 0; i < std::size(kTrue); ++i) {
- if (base::LowerCaseEqualsASCII(value, kTrue[i]))
+ if (base::EqualsCaseInsensitiveASCII(value, kTrue[i]))
return 1;
}
for (size_t i = 0; i < std::size(kFalse); ++i) {
- if (base::LowerCaseEqualsASCII(value, kFalse[i]))
+ if (base::EqualsCaseInsensitiveASCII(value, kFalse[i]))
return -1;
}
return 0;
diff --git a/chromium/ui/events/ozone/evdev/touch_event_converter_evdev.cc b/chromium/ui/events/ozone/evdev/touch_event_converter_evdev.cc
index cf9d405f791..3d5d2ab7319 100644
--- a/chromium/ui/events/ozone/evdev/touch_event_converter_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/touch_event_converter_evdev.cc
@@ -532,7 +532,7 @@ void TouchEventConverterEvdev::ReportTouchEvent(
ui::PointerDetails details(event.reported_tool_type, /* pointer_id*/ 0,
event.radius_x, event.radius_y, event.pressure,
/* twist */ 0, event.tilt_x, event.tilt_y);
- int flags = event.stylus_button ? ui::EventFlags::EF_LEFT_MOUSE_BUTTON : 0;
+ int flags = event.stylus_button ? ui::EF_LEFT_MOUSE_BUTTON : 0;
dispatcher_->DispatchTouchEvent(TouchEventParams(
input_device_.id, event.slot, event_type, gfx::PointF(event.x, event.y),
details, timestamp, flags));
diff --git a/chromium/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc b/chromium/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
index 2f00dbffe89..e79ac42dd92 100644
--- a/chromium/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
+++ b/chromium/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
@@ -166,7 +166,8 @@ class MockDeviceEventDispatcherEvdev : public DeviceEventDispatcherEvdev {
void DispatchMicrophoneMuteSwitchValueChanged(bool muted) override {}
void DispatchKeyboardDevicesUpdated(
- const std::vector<InputDevice>& devices) override {}
+ const std::vector<InputDevice>& devices,
+ base::flat_map<int, std::vector<uint64_t>> key_bits_mapping) override {}
void DispatchTouchscreenDevicesUpdated(
const std::vector<TouchscreenDevice>& devices) override {}
void DispatchMouseDevicesUpdated(const std::vector<InputDevice>& devices,
@@ -183,7 +184,8 @@ class MockDeviceEventDispatcherEvdev : public DeviceEventDispatcherEvdev {
void DispatchGamepadEvent(const GamepadEvent& event) override {}
void DispatchGamepadDevicesUpdated(
- const std::vector<GamepadDevice>& devices) override {}
+ const std::vector<GamepadDevice>& devices,
+ base::flat_map<int, std::vector<uint64_t>> key_bits_mapping) override {}
private:
base::RepeatingCallback<void(const GenericEventParams& params)> callback_;
@@ -1919,12 +1921,12 @@ TEST_F(TouchEventConverterEvdevTest, ActiveStylusBarrelButtonWhileHovering) {
auto down_event = dispatched_touch_event(0);
EXPECT_EQ(ET_TOUCH_PRESSED, down_event.type);
- EXPECT_TRUE(down_event.flags & ui::EventFlags::EF_LEFT_MOUSE_BUTTON);
+ EXPECT_TRUE(down_event.flags & ui::EF_LEFT_MOUSE_BUTTON);
EXPECT_EQ(EventPointerType::kPen, down_event.pointer_details.pointer_type);
auto up_event = dispatched_touch_event(1);
EXPECT_EQ(ET_TOUCH_RELEASED, up_event.type);
- EXPECT_TRUE(down_event.flags & ui::EventFlags::EF_LEFT_MOUSE_BUTTON);
+ EXPECT_TRUE(down_event.flags & ui::EF_LEFT_MOUSE_BUTTON);
EXPECT_EQ(EventPointerType::kPen, up_event.pointer_details.pointer_type);
}
@@ -1966,24 +1968,24 @@ TEST_F(TouchEventConverterEvdevTest, ActiveStylusBarrelButton) {
auto down_event = dispatched_touch_event(0);
EXPECT_EQ(ET_TOUCH_PRESSED, down_event.type);
- EXPECT_FALSE(down_event.flags & ui::EventFlags::EF_LEFT_MOUSE_BUTTON);
+ EXPECT_FALSE(down_event.flags & ui::EF_LEFT_MOUSE_BUTTON);
EXPECT_EQ(EventPointerType::kPen, down_event.pointer_details.pointer_type);
auto button_down_event = dispatched_touch_event(1);
EXPECT_EQ(ET_TOUCH_MOVED, button_down_event.type);
- EXPECT_TRUE(button_down_event.flags & ui::EventFlags::EF_LEFT_MOUSE_BUTTON);
+ EXPECT_TRUE(button_down_event.flags & ui::EF_LEFT_MOUSE_BUTTON);
EXPECT_EQ(EventPointerType::kPen,
button_down_event.pointer_details.pointer_type);
auto button_up_event = dispatched_touch_event(2);
EXPECT_EQ(ET_TOUCH_MOVED, button_up_event.type);
- EXPECT_FALSE(button_up_event.flags & ui::EventFlags::EF_LEFT_MOUSE_BUTTON);
+ EXPECT_FALSE(button_up_event.flags & ui::EF_LEFT_MOUSE_BUTTON);
EXPECT_EQ(EventPointerType::kPen,
button_up_event.pointer_details.pointer_type);
auto up_event = dispatched_touch_event(3);
EXPECT_EQ(ET_TOUCH_RELEASED, up_event.type);
- EXPECT_FALSE(down_event.flags & ui::EventFlags::EF_LEFT_MOUSE_BUTTON);
+ EXPECT_FALSE(down_event.flags & ui::EF_LEFT_MOUSE_BUTTON);
EXPECT_EQ(EventPointerType::kPen, up_event.pointer_details.pointer_type);
}
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.cc b/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.cc
index 90f92656811..85c7124b7b2 100644
--- a/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.cc
+++ b/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.cc
@@ -215,7 +215,7 @@ void NeuralStylusPalmDetectionFilter::Filter(
config.early_stage_sample_counts.find(stroke.samples_seen()) !=
config.early_stage_sample_counts.end()) {
VLOG(1) << "About to run a early_stage prediction.";
- if (DetectSpuriousStroke(ExtractFeatures(tracking_id), tracking_id,
+ if (DetectSpuriousStroke(ExtractFeatures(tracking_id),
model_->config().output_threshold)) {
VLOG(1) << "hold detected.";
is_delay_.set(slot, true);
@@ -238,9 +238,8 @@ void NeuralStylusPalmDetectionFilter::Filter(
is_palm_.set(slot, IsHeuristicPalmStroke(stroke));
continue;
}
- is_palm_.set(slot,
- DetectSpuriousStroke(ExtractFeatures(tracking_id), tracking_id,
- model_->config().output_threshold));
+ is_palm_.set(slot, DetectSpuriousStroke(ExtractFeatures(tracking_id),
+ model_->config().output_threshold));
if (is_palm_.test(slot)) {
shared_palm_state_->latest_palm_touch_time = time;
}
@@ -307,7 +306,6 @@ bool NeuralStylusPalmDetectionFilter::IsHeuristicPalmStroke(
bool NeuralStylusPalmDetectionFilter::DetectSpuriousStroke(
const std::vector<float>& features,
- int tracking_id,
float threshold) const {
auto inference_value = model_->Inference(features);
if (VLOG_IS_ON(1)) {
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.h b/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.h
index 6b023e3a2a9..7c2bcd20b1b 100644
--- a/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.h
+++ b/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.h
@@ -76,7 +76,6 @@ class COMPONENT_EXPORT(EVDEV) NeuralStylusPalmDetectionFilter
std::vector<std::pair<float, int>>* biggest_strokes) const;
bool DetectSpuriousStroke(const std::vector<float>& features,
- int tracking_id,
float threshold) const;
// Extracts the feature vector for the specified stroke.
std::vector<float> ExtractFeatures(int tracking_id) const;
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_model.h b/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_model.h
index fdf858b96c6..c6c25888f11 100644
--- a/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_model.h
+++ b/chromium/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_model.h
@@ -74,6 +74,9 @@ struct COMPONENT_EXPORT(EVDEV) NeuralStylusPalmDetectionFilterModelConfig {
// If true, uses current active tracking_id count as a feature.
bool use_active_tracking_id_count = false;
+ // The model version (e.g. "alpha" for kohaku, "beta" for redrix) to use.
+ std::string model_version;
+
// If empty, the radius by the device is left as is.
// If non empty, the radius reported by device is re-sized in features by the
// polynomial defined in this vector. E.g. if this vector is {0.5, 1.3,
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/palm_detection_filter_factory.cc b/chromium/ui/events/ozone/evdev/touch_filter/palm_detection_filter_factory.cc
index dca26527bbc..a01d016e5d4 100644
--- a/chromium/ui/events/ozone/evdev/touch_filter/palm_detection_filter_factory.cc
+++ b/chromium/ui/events/ozone/evdev/touch_filter/palm_detection_filter_factory.cc
@@ -84,6 +84,28 @@ std::string FetchNeuralPalmRadiusPolynomial(const EventDeviceInfo& devinfo,
// By default, return the original.
return param_string;
}
+
+std::string FetchNeuralPalmModelVersion(const EventDeviceInfo& devinfo,
+ const std::string param_string) {
+ if (!param_string.empty()) {
+ return param_string;
+ }
+
+ // look at the command line.
+ absl::optional<base::Value> ozone_switch_value = base::JSONReader::Read(
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ kOzoneNNPalmSwitchName));
+ if (ozone_switch_value != absl::nullopt && ozone_switch_value->is_dict()) {
+ std::string* switch_string_value =
+ ozone_switch_value->FindStringKey(kOzoneNNPalmModelVersionProperty);
+ if (switch_string_value != nullptr) {
+ return *switch_string_value;
+ }
+ }
+
+ // By default, return the original.
+ return param_string;
+}
} // namespace internal
std::unique_ptr<PalmDetectionFilter> CreatePalmDetectionFilter(
@@ -97,10 +119,12 @@ std::unique_ptr<PalmDetectionFilter> CreatePalmDetectionFilter(
VLOG(1) << "Will attempt to use radius polynomial: " << polynomial_string;
std::vector<float> radius_polynomial =
internal::ParseRadiusPolynomial(polynomial_string);
+ std::string model_version = internal::FetchNeuralPalmModelVersion(
+ devinfo, kNeuralPalmModelVersion.Get());
// There's only one model right now.
std::unique_ptr<NeuralStylusPalmDetectionFilterModel> model =
std::make_unique<OneDeviceTrainNeuralStylusPalmDetectionFilterModel>(
- radius_polynomial);
+ model_version, radius_polynomial);
return std::make_unique<NeuralStylusPalmDetectionFilter>(
devinfo, std::move(model), shared_palm_state);
}
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/palm_detection_filter_factory.h b/chromium/ui/events/ozone/evdev/touch_filter/palm_detection_filter_factory.h
index 8a9f6058b0c..6c64cc38faf 100644
--- a/chromium/ui/events/ozone/evdev/touch_filter/palm_detection_filter_factory.h
+++ b/chromium/ui/events/ozone/evdev/touch_filter/palm_detection_filter_factory.h
@@ -36,6 +36,12 @@ std::vector<float> ParseRadiusPolynomial(const std::string& radius_string);
COMPONENT_EXPORT(EVDEV)
std::string FetchNeuralPalmRadiusPolynomial(const EventDeviceInfo& devinfo,
const std::string param_string);
+
+// Returns the model version to use on the current device. If empty will use
+// alpha model.
+COMPONENT_EXPORT(EVDEV)
+std::string FetchNeuralPalmModelVersion(const EventDeviceInfo& devinfo,
+ const std::string param_string);
} // namespace internal
} // namespace ui
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/palm_detection_filter_factory_unittest.cc b/chromium/ui/events/ozone/evdev/touch_filter/palm_detection_filter_factory_unittest.cc
index 053107fc3ed..451a149b921 100644
--- a/chromium/ui/events/ozone/evdev/touch_filter/palm_detection_filter_factory_unittest.cc
+++ b/chromium/ui/events/ozone/evdev/touch_filter/palm_detection_filter_factory_unittest.cc
@@ -6,6 +6,7 @@
#include <linux/input.h>
+#include "base/command_line.h"
#include "base/test/gtest_util.h"
#include "base/test/scoped_chromeos_version_info.h"
#include "base/test/scoped_feature_list.h"
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.cc b/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.cc
index 97cc367e3ed..5bb81b253e8 100644
--- a/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.cc
+++ b/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.cc
@@ -14,7 +14,8 @@
#define USE_EIGEN 0
#endif
-namespace ui {
+namespace ui::internal_onedevice::alpha_model {
+
namespace {
// -----------------------------------------------------------------------------
@@ -3878,7 +3879,6 @@ int32_t input_from_feature_columns_input_layer_concat_concat0Shape[2] = {1,
323};
int32_t logits_MatMul_merged_with_dnn_logits_BiasAdd0Shape[2] = {1, 1};
-namespace internal_onedevice {
void Inference(
const float* __restrict input_from_feature_columns_input_layer_concat_concat0 /* shape: 1,323 */
,
@@ -3921,5 +3921,4 @@ void Inference(
#endif
}
-} // namespace internal_onedevice
-} // namespace ui
+} // namespace ui::internal_onedevice::alpha_model
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.h b/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.h
index 02bb87d20cb..601d4af9e7e 100644
--- a/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.h
+++ b/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.h
@@ -6,8 +6,7 @@
#define UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_PALM_MODEL_ONEDEVICE_TRAIN_PALM_DETECTION_FILTER_INFERENCE_H_
#include <cstdint>
-namespace ui {
-namespace internal_onedevice {
+namespace ui::internal_onedevice::alpha_model {
struct alignas(16) FixedAllocations {
float alloc0[20];
int32_t shape0[2];
@@ -36,6 +35,5 @@ void Inference(
,
FixedAllocations* __restrict fixed);
-} // namespace internal_onedevice
-} // namespace ui
+} // namespace ui::internal_onedevice::alpha_model
#endif // UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_PALM_MODEL_ONEDEVICE_TRAIN_PALM_DETECTION_FILTER_INFERENCE_H_
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.cc b/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.cc
new file mode 100644
index 00000000000..8edd15bb7d9
--- /dev/null
+++ b/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.cc
@@ -0,0 +1,3936 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include "ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.h"
+#include <algorithm>
+#include <cassert>
+#include <cmath>
+#include <cstdint>
+#include <cstring>
+#include <limits>
+#include <tuple>
+
+#ifndef USE_EIGEN
+#define USE_EIGEN 0
+#endif
+
+namespace ui::internal_onedevice::beta_model {
+namespace {
+
+// -----------------------------------------------------------------------------
+// OP LIBRARY
+// Copied here to make sure that the inference code always stays in sync with
+// the lib that it was generated for.
+// -----------------------------------------------------------------------------
+
+// Default to using std::copy and std::fill over memcpy and memset as they
+// are usually faster, thanks to the compiler getting stricter alignment
+// guarantees.
+#ifndef USE_TYPED_MEMSETMEMCPY
+#define USE_TYPED_MEMSETMEMCPY 1
+#endif
+#ifndef USE_EIGEN
+#error Please define USE_EIGEN to either 0 or 1
+#endif
+
+// Helper to reinterpret memory as Eigen matrices.
+#if USE_EIGEN
+template <typename Scalar>
+using ConstMatrixMap = typename Eigen::Map<
+ const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>>;
+template <typename Scalar>
+using ConstRowVectorMap =
+ typename Eigen::Map<const Eigen::Matrix<Scalar, Eigen::Dynamic, 1>>;
+template <typename Scalar>
+using RowVectorMap =
+ typename Eigen::Map<Eigen::Matrix<Scalar, Eigen::Dynamic, 1>>;
+template <typename Scalar>
+using MatrixMap =
+ typename Eigen::Map<Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>>;
+template <typename Scalar, typename StorageIndex>
+using SparseMatrix = Eigen::SparseMatrix<Scalar, Eigen::RowMajor, StorageIndex>;
+#endif
+
+#if OP_LIB_BENCHMARK
+class PerOpTimings {
+ public:
+ void Add(const std::string& op, absl::Duration time) {
+ time_per_op_[op] += time;
+ }
+
+ void Reset() { time_per_op_.clear(); }
+
+ void WriteTimingsToInfoLog() {
+ std::string message = "Per op totals:\n";
+ absl::Duration total;
+ for (auto& entry : time_per_op_) {
+ total += entry.second;
+ absl::StrAppend(
+ &message, entry.first, ": ",
+ absl::LegacyPrecision(absl::ToDoubleMilliseconds(entry.second)),
+ " ms\n");
+ }
+ absl::StrAppend(&message, "Total: ",
+ absl::LegacyPrecision(absl::ToDoubleMilliseconds(total)),
+ " ms\n");
+ VLOG(1) << message;
+ }
+
+ private:
+ std::map<std::string, absl::Duration> time_per_op_;
+};
+
+// Timer for individual operations. For each operation, add a statement like
+// BENCHMARK_TIMER(name_part1, name_part2, ...);
+// to the beginning of the code. All name parts will be concatenated together
+// and a line will be logged after executing the operation showing the name and
+// the elapsed time.
+class BenchmarkTimer {
+ public:
+ explicit BenchmarkTimer(std::string name)
+ : name_(std::move(name)), start_(absl::Now()) {}
+
+ ~BenchmarkTimer() {
+ const absl::Duration elapsed = absl::Now() - start_;
+ Singleton<PerOpTimings>::get()->Add(name_, elapsed);
+ VLOG(1) << "Time for " << name_ << ": "
+ << absl::ToDoubleMilliseconds(elapsed) << " ms";
+ }
+
+ private:
+ const std::string name_;
+ const absl::Time start_;
+};
+
+#define BENCHMARK_TIMER(...) BenchmarkTimer timer(absl::StrCat(__VA_ARGS__));
+
+#else // OP_LIB_BENCHMARK
+#define BENCHMARK_TIMER(...)
+#endif // OP_LIB_BENCHMARK
+
+// The size of a shape in terms of number of coefficients.
+inline int32_t ShapeSize(const int32_t rank, const int32_t* shape) {
+ int32_t size = 1;
+ for (int32_t i = 0; i < rank; ++i)
+ size *= shape[i];
+ return size;
+}
+
+// For convolutional operations, calculates the output size with VALID padding.
+// Returns (height, width).
+inline std::tuple<int, int> GetConvOutputSizeVALID(const int32_t* input_shape,
+ const int32_t* kernel_shape,
+ int32_t stride_y,
+ int32_t stride_x) {
+ return std::make_tuple(
+ (input_shape[1] + stride_y - kernel_shape[0]) / stride_y,
+ (input_shape[2] + stride_x - kernel_shape[1]) / stride_x);
+}
+
+// For convolutional operations, calculates the output size with SAME padding.
+// Returns (height, width).
+inline std::tuple<int, int> GetConvOutputSizeSAME(const int32_t* input_shape,
+ int32_t stride_y,
+ int32_t stride_x) {
+ return std::make_tuple((input_shape[1] + stride_y - 1) / stride_y,
+ (input_shape[2] + stride_x - 1) / stride_x);
+}
+
+// Helper to compute the size of the inner loop for an op that uses indices to
+// specify which axes are reduced.
+template <typename Tidx>
+int32_t GetReduceInnerSize(int32_t input_tensor_rank,
+ const int32_t* __restrict input_shape,
+ int32_t index_tensor_rank,
+ const int32_t* __restrict index_shape,
+ const Tidx* __restrict index_values) {
+ assert(index_tensor_rank <= 1);
+ const int32_t num_indices = index_tensor_rank > 0 ? index_shape[0] : 1;
+ int32_t inner_size = 1;
+ for (int32_t i = 0; i < num_indices; ++i) {
+ Tidx index_value = index_values[i];
+ if (index_value < 0) {
+ index_value = input_tensor_rank + index_value;
+ }
+ inner_size *= input_shape[index_value];
+ }
+ return inner_size;
+}
+
+template <typename T>
+void ConcatV2Args2(int32_t arg0_rank,
+ const int32_t* __restrict arg0_shape,
+ const T* __restrict arg0_values,
+ int32_t arg1_rank,
+ const int32_t* __restrict arg1_shape,
+ const T* __restrict arg1_values,
+ const int32_t* __restrict axis_value,
+ T* __restrict output_values) {
+ BENCHMARK_TIMER("ConcatV2Args2");
+ const int32_t axis = axis_value[0];
+ const int32_t num_lines = ShapeSize(axis, arg0_shape);
+ const int32_t arg0_line_size = ShapeSize(arg0_rank - axis, arg0_shape + axis);
+ const int32_t arg1_line_size = ShapeSize(arg1_rank - axis, arg1_shape + axis);
+ for (int32_t line = 0; line < num_lines; ++line) {
+ std::copy(arg0_values, arg0_values + arg0_line_size, output_values);
+ arg0_values += arg0_line_size;
+ output_values += arg0_line_size;
+ std::copy(arg1_values, arg1_values + arg1_line_size, output_values);
+ arg1_values += arg1_line_size;
+ output_values += arg1_line_size;
+ }
+}
+
+template <typename T>
+void MatMul(const int32_t* __restrict input_shape,
+ const T* __restrict input_values,
+ const int32_t* __restrict weight_shape,
+ const T* __restrict weight_values,
+ T* __restrict output_values) {
+ BENCHMARK_TIMER("MatMul");
+#if USE_EIGEN
+ const auto in =
+ ConstMatrixMap<T>(input_values, input_shape[1], input_shape[0]);
+ const auto weight =
+ ConstMatrixMap<T>(weight_values, weight_shape[1], weight_shape[0]);
+ auto result = MatrixMap<T>(output_values, weight_shape[1], input_shape[0]);
+ result.noalias() = weight * in;
+#else
+ const int32_t batch_size = input_shape[0];
+ const int32_t num_inputs = weight_shape[0];
+ const int32_t num_outputs = weight_shape[1];
+ assert(input_shape[1] == num_inputs);
+ for (int32_t batch = 0; batch < batch_size; ++batch) {
+ for (int32_t out_i = 0; out_i < num_outputs; ++out_i) {
+ T value = 0;
+ for (int32_t in_i = 0; in_i < num_inputs; ++in_i) {
+ value += input_values[batch * num_inputs + in_i] *
+ weight_values[in_i * num_outputs + out_i];
+ }
+ *output_values++ = value;
+ }
+ }
+#endif
+}
+
+template <typename T>
+void DepthwiseConv2dNative(const int32_t* __restrict input_shape,
+ const T* __restrict input_values,
+ const int32_t* __restrict kernel_shape,
+ const T* __restrict kernel_values,
+ int32_t stride_y,
+ int32_t stride_x,
+ int32_t out_height,
+ int32_t out_width,
+ T* __restrict output_values) {
+ BENCHMARK_TIMER("DepthwiseConv2dNative");
+ // Give the shape values nicer names.
+ assert(input_shape[3] == kernel_shape[2]);
+ const int32_t batch_size = input_shape[0];
+ const int32_t kernel_height = kernel_shape[0];
+ const int32_t kernel_width = kernel_shape[1];
+ const int32_t in_depth = kernel_shape[2];
+ const int32_t depth_mul = kernel_shape[3];
+ const int32_t in_height = input_shape[1];
+ const int32_t in_width = input_shape[2];
+
+ // Compute the amount of padding needed to get the desired output size.
+ const int32_t pad_height =
+ ((out_height - 1) * stride_y + kernel_height - in_height) / 2;
+ const int32_t pad_width =
+ ((out_width - 1) * stride_x + kernel_width - in_width) / 2;
+
+ // Cache the strides for address computations.
+ const int32_t in_strides[4] = {
+ input_shape[1] * input_shape[2] * input_shape[3], // batch
+ input_shape[2] * input_shape[3], // y
+ input_shape[3], // x
+ 1, // channel
+ };
+ const int32_t kernel_strides[4] = {
+ kernel_shape[1] * kernel_shape[2] * kernel_shape[3], // y
+ kernel_shape[2] * kernel_shape[3], // x
+ kernel_shape[3], // in channels
+ 1, // channel mult
+ };
+
+ T* out_write_ptr = output_values;
+ for (int32_t batch = 0; batch < batch_size; ++batch) {
+ for (int32_t out_y = 0; out_y < out_height; ++out_y) {
+ for (int32_t out_x = 0; out_x < out_width; ++out_x) {
+ // Compute the input read offsets.
+ const int32_t in_y_origin = (out_y * stride_y) - pad_height;
+ const int32_t in_x_origin = (out_x * stride_x) - pad_width;
+
+ // Compute the range of the kernel to be applied (we may need to clip
+ // when we'd read outside of the valid input region - for SAME).
+ const int32_t kernel_y_start =
+ std::max(static_cast<int32_t>(0), -in_y_origin);
+ const int32_t kernel_y_end =
+ std::min(kernel_height, in_height - in_y_origin);
+ const int32_t kernel_x_start =
+ std::max(static_cast<int32_t>(0), -in_x_origin);
+ const int32_t kernel_x_end =
+ std::min(kernel_width, in_width - in_x_origin);
+
+ for (int32_t in_c = 0; in_c < in_depth; ++in_c) {
+ for (int32_t mul_c = 0; mul_c < depth_mul; ++mul_c, ++out_write_ptr) {
+ // Convolve.
+ T sum = 0;
+ for (int32_t k_y = kernel_y_start; k_y < kernel_y_end; ++k_y) {
+ const int32_t in_y = in_y_origin + k_y;
+ assert(in_y >= 0 && in_y < in_height);
+ for (int32_t k_x = kernel_x_start; k_x < kernel_x_end; ++k_x) {
+ const int32_t in_x = in_x_origin + k_x;
+ assert(in_x >= 0 && in_x < in_width);
+ const T input_value =
+ input_values[batch * in_strides[0] + // batch
+ in_y * in_strides[1] + // y
+ in_x * in_strides[2] + // x
+ in_c]; // in chan
+ const T kernel_value =
+ kernel_values[k_y * kernel_strides[0] + // y
+ k_x * kernel_strides[1] + // x
+ in_c * kernel_strides[2] + // in chan
+ mul_c]; // chan mult
+ sum += input_value * kernel_value;
+ }
+ }
+ *out_write_ptr = sum;
+ } // mul_c
+ } // in_c
+ } // out_x
+ } // out_y
+ } // batch
+}
+
+template <typename T>
+void DepthwiseConv2dNativeVALID(const int32_t* __restrict input_shape,
+ const T* __restrict input_values,
+ const int32_t* __restrict kernel_shape,
+ const T* __restrict kernel_values,
+ int32_t stride_y,
+ int32_t stride_x,
+ T* __restrict output_values) {
+ const auto out_size =
+ GetConvOutputSizeVALID(input_shape, kernel_shape, stride_y, stride_x);
+ DepthwiseConv2dNative<T>(
+ input_shape, input_values, kernel_shape, kernel_values, stride_y,
+ stride_x, std::get<0>(out_size), std::get<1>(out_size), output_values);
+}
+
+template <typename T>
+void DepthwiseConv2dNativeSAME(const int32_t* __restrict input_shape,
+ const T* __restrict input_values,
+ const int32_t* __restrict kernel_shape,
+ const T* __restrict kernel_values,
+ int32_t stride_y,
+ int32_t stride_x,
+ T* __restrict output_values) {
+ const auto out_size = GetConvOutputSizeSAME(input_shape, stride_y, stride_x);
+ DepthwiseConv2dNative<T>(
+ input_shape, input_values, kernel_shape, kernel_values, stride_y,
+ stride_x, std::get<0>(out_size), std::get<1>(out_size), output_values);
+}
+
+template <typename T>
+void FullyConnected(const int32_t* __restrict input_shape,
+ const T* __restrict input_values,
+ const int32_t* __restrict weight_shape,
+ const T* __restrict weight_values,
+ const int32_t* __restrict bias_shape,
+ const T* __restrict bias_values,
+ T* __restrict output_values) {
+ BENCHMARK_TIMER("FullyConnected");
+#if USE_EIGEN
+ const auto in =
+ ConstMatrixMap<T>(input_values, input_shape[1], input_shape[0]);
+ const auto weight =
+ ConstMatrixMap<T>(weight_values, weight_shape[1], weight_shape[0]);
+ const auto bias = ConstRowVectorMap<T>(bias_values, bias_shape[0]);
+ auto result = MatrixMap<T>(output_values, weight_shape[1], input_shape[0]);
+ result.noalias() = (weight * in).colwise() + bias;
+#else
+ const int32_t batch_size = input_shape[0];
+ const int32_t num_inputs = weight_shape[0];
+ const int32_t num_outputs = weight_shape[1];
+ assert(input_shape[1] == num_inputs);
+ assert(bias_shape[0] == num_outputs);
+ for (int32_t batch = 0; batch < batch_size; ++batch) {
+ for (int32_t out_i = 0; out_i < num_outputs; ++out_i) {
+ T value = bias_values[out_i];
+ for (int32_t in_i = 0; in_i < num_inputs; ++in_i) {
+ value += input_values[batch * num_inputs + in_i] *
+ weight_values[in_i * num_outputs + out_i];
+ }
+ output_values[batch * num_outputs + out_i] = value;
+ }
+ }
+#endif
+}
+
+template <typename T, typename TBlocks, typename TPaddings>
+void SpaceToBatchNDRank4(const int32_t* __restrict input_shape,
+ const T* __restrict input_values,
+ const TBlocks* __restrict block_shape_values,
+ const TPaddings* __restrict padding_values,
+ T* __restrict output_values) {
+ BENCHMARK_TIMER("SpaceToBatchNDRank4");
+ const int32_t input_batch_size = input_shape[0];
+ const int32_t input_height = input_shape[1];
+ const int32_t input_width = input_shape[2];
+ const int32_t input_depth = input_shape[3];
+
+ const TBlocks block_shape_height = block_shape_values[0];
+ const TBlocks block_shape_width = block_shape_values[1];
+ const TPaddings padding_top = padding_values[0];
+ const TPaddings padding_bottom = padding_values[1];
+ const TPaddings padding_left = padding_values[2];
+ const TPaddings padding_right = padding_values[3];
+
+ const int32_t block_size = block_shape_height * block_shape_width;
+ const int32_t output_depth = input_depth;
+ const int32_t output_batch_size = input_batch_size * block_size;
+ const int32_t output_height =
+ (padding_top + padding_bottom + input_height) / block_shape_height;
+ const int32_t output_width =
+ (padding_left + padding_right + input_width) / block_shape_width;
+
+ const T pad_value = 0;
+
+ for (int32_t out_b = 0; out_b < output_batch_size; ++out_b) {
+ const int32_t input_batch = out_b % input_batch_size;
+ const int32_t shift_w = (out_b / input_batch_size) % block_shape_width;
+ const int32_t shift_h = (out_b / input_batch_size) / block_shape_width;
+ for (int32_t out_h = 0; out_h < output_height; ++out_h) {
+ for (int32_t out_w = 0; out_w < output_width; ++out_w) {
+ T* out = output_values +
+ (((out_b * output_height + out_h) * output_width + out_w) *
+ output_depth +
+ 0);
+ // Check if padding cell are being handled.
+ if (out_h * block_shape_height + shift_h < padding_top ||
+ out_h * block_shape_height + shift_h >=
+ padding_top + input_height ||
+ out_w * block_shape_width + shift_w < padding_left ||
+ out_w * block_shape_width + shift_w >= padding_left + input_width) {
+// This may not execute correctly when pad_value != 0 and T != uint8.
+#if USE_TYPED_MEMSETMEMCPY
+ std::fill(out, out + input_depth, pad_value);
+#else
+ std::memset(out, pad_value, input_depth * sizeof(T));
+#endif
+ } else {
+ const int32_t i0 = input_batch;
+ const int32_t i1 =
+ (out_h * block_shape_height + shift_h) - padding_top;
+ const int32_t i2 =
+ (out_w * block_shape_width + shift_w) - padding_left;
+ const T* in =
+ input_values +
+ (((i0 * input_height + i1) * input_width + i2) * input_depth + 0);
+#if USE_TYPED_MEMSETMEMCPY
+ std::copy(in, in + input_depth, out);
+#else
+ std::memcpy(out, in, input_depth * sizeof(T));
+#endif
+ }
+ }
+ }
+ }
+}
+
+template <typename T, typename TBlocks, typename TCrops>
+void BatchToSpaceNDRank4(const int32_t* __restrict input_shape,
+ const T* __restrict input_values,
+ const TBlocks* __restrict block_shape_values,
+ const TCrops* __restrict crops_values,
+ T* __restrict output_values) {
+ BENCHMARK_TIMER("BatchToSpaceNDRank4");
+ const int32_t input_batch_size = input_shape[0];
+ const int32_t input_height = input_shape[1];
+ const int32_t input_width = input_shape[2];
+ const int32_t input_depth = input_shape[3];
+ const TBlocks block_shape_height = block_shape_values[0];
+ const TBlocks block_shape_width = block_shape_values[1];
+ const TCrops crops_top = crops_values[0];
+ const TCrops crops_bottom = crops_values[1];
+ const TCrops crops_left = crops_values[2];
+ const TCrops crops_right = crops_values[3];
+
+ const int32_t output_depth = input_depth;
+ const int32_t output_batch_size =
+ input_batch_size / (block_shape_width * block_shape_height);
+ const int32_t output_height =
+ input_height * block_shape_height - crops_top - crops_bottom;
+ const int32_t output_width =
+ input_width * block_shape_width - crops_left - crops_right;
+
+ for (int32_t in_batch = 0; in_batch < input_batch_size; ++in_batch) {
+ const int32_t out_batch = in_batch % output_batch_size;
+ const int32_t spatial_offset = in_batch / output_batch_size;
+ for (int32_t in_h = 0; in_h < input_height; ++in_h) {
+ const int32_t out_h = in_h * block_shape_height +
+ spatial_offset / block_shape_width - crops_top;
+ if (out_h < 0 || out_h >= output_height) {
+ continue;
+ }
+ for (int32_t in_w = 0; in_w < input_width; ++in_w) {
+ const int32_t out_w = in_w * block_shape_width +
+ spatial_offset % block_shape_width - crops_left;
+
+ if (out_w < 0 || out_w >= output_width) {
+ continue;
+ }
+ T* out = output_values +
+ (((out_batch * output_height + out_h) * output_width + out_w) *
+ output_depth +
+ 0);
+ const T* in = input_values +
+ (((in_batch * input_height + in_h) * input_width + in_w) *
+ input_depth +
+ 0);
+#if USE_TYPED_MEMSETMEMCPY
+ std::copy(in, in + input_depth, out);
+#else
+ std::memcpy(out, in, input_depth * sizeof(T));
+#endif
+ }
+ }
+ }
+}
+
+#if USE_EIGEN
+template <typename T, typename Tidx>
+void SparseDenseMatMulCSR(const int32_t* __restrict input_shape,
+ const T* __restrict input_values,
+ const int32_t num_rows,
+ const int32_t* __restrict nnz_shape,
+ const T* __restrict nnz_values,
+ const Tidx* __restrict outer_index,
+ const Tidx* __restrict cols,
+ T* __restrict output_values) {
+ BENCHMARK_TIMER("SparseDenseMatMulCSR");
+ const int32_t num_cols = input_shape[1];
+ const auto in =
+ ConstMatrixMap<T>(input_values, input_shape[1], input_shape[0]);
+ const Eigen::Map<const SparseMatrix<T, Tidx>> weight(
+ num_rows, num_cols, nnz_shape[0], outer_index, cols, nnz_values);
+ auto result = MatrixMap<T>(output_values, num_rows, input_shape[0]);
+ result.noalias() = weight * in;
+}
+
+template <typename T, typename Tidx>
+void SparseFullyConnectedCSR(const int32_t* __restrict input_shape,
+ const T* __restrict input_values,
+ const int32_t num_rows,
+ const int32_t* __restrict nnz_shape,
+ const T* __restrict nnz_values,
+ const Tidx* __restrict outer_index,
+ const Tidx* __restrict cols,
+ const int32_t* __restrict bias_shape,
+ const T* __restrict bias_values,
+ T* __restrict output_values) {
+ BENCHMARK_TIMER("SparseFullyConnectedCSR");
+ const int32_t num_cols = input_shape[1];
+ const auto in =
+ ConstMatrixMap<T>(input_values, input_shape[1], input_shape[0]);
+ const auto bias = ConstRowVectorMap<T>(bias_values, bias_shape[0]);
+ const Eigen::Map<const SparseMatrix<T, Tidx>> weight(
+ num_rows, num_cols, nnz_shape[0], outer_index, cols, nnz_values);
+ auto result = MatrixMap<T>(output_values, num_rows, input_shape[0]);
+ result.noalias() = (weight * in).colwise() + bias;
+}
+#endif
+
+template <typename T, typename TIndex>
+void Gather(int32_t params_rank,
+ const int32_t* __restrict params_shape,
+ const T* __restrict params_values,
+ int32_t indices_rank,
+ const int32_t* __restrict indices_shape,
+ const TIndex* __restrict indices_values,
+ T* __restrict output_values) {
+ BENCHMARK_TIMER("Gather");
+ const int32_t num_indices = ShapeSize(indices_rank, indices_shape);
+ const int32_t num_params = params_shape[0];
+ const int32_t slice_size = ShapeSize(params_rank - 1, params_shape + 1);
+ for (int32_t i = 0; i < num_indices; ++i) {
+ const int32_t index = indices_values[i];
+ if (index < 0 || index >= num_params) {
+ std::fill(output_values, output_values + slice_size, 0);
+ } else {
+ std::copy(params_values + index * slice_size,
+ params_values + index * slice_size + slice_size, output_values);
+ }
+ output_values += slice_size;
+ }
+}
+
+template <typename T>
+void Im2Row(const int32_t* __restrict input_shape,
+ const T* __restrict input_values,
+ const int32_t* __restrict kernel_shape,
+ int32_t stride_y,
+ int32_t stride_x,
+ int32_t out_height,
+ int32_t out_width,
+ T* __restrict output_values) {
+ BENCHMARK_TIMER("Im2Row");
+ // Give the shape values nicer names.
+ assert(input_shape[3] == kernel_shape[2]);
+ const int32_t batch_size = input_shape[0];
+ const int32_t kernel_height = kernel_shape[0];
+ const int32_t kernel_width = kernel_shape[1];
+ const int32_t in_depth = kernel_shape[2];
+ const int32_t in_height = input_shape[1];
+ const int32_t in_width = input_shape[2];
+
+ // Compute the amount of padding needed to get the desired output size.
+ const int32_t pad_height =
+ ((out_height - 1) * stride_y + kernel_height - in_height) / 2;
+ const int32_t pad_width =
+ ((out_width - 1) * stride_x + kernel_width - in_width) / 2;
+
+ // Cache the strides for address computations.
+ const int32_t x_stride = input_shape[3];
+ const int32_t y_stride = input_shape[2] * x_stride;
+ const int32_t batch_stride = input_shape[1] * y_stride;
+
+ for (int32_t batch = 0; batch < batch_size; ++batch) {
+ for (int32_t out_y = 0; out_y < out_height; ++out_y) {
+ for (int32_t out_x = 0; out_x < out_width; ++out_x) {
+ // Compute the input read offsets.
+ const int32_t in_y_origin = (out_y * stride_y) - pad_height;
+ const int32_t in_x_origin = (out_x * stride_x) - pad_width;
+
+ // Compute the range of the kernel to be applied (we may need to clip
+ // when we'd read outside of the valid input region - for SAME).
+ const int32_t kernel_y_start =
+ std::max(static_cast<int32_t>(0), -in_y_origin);
+ const int32_t kernel_y_end =
+ std::min(kernel_height, in_height - in_y_origin);
+ const int32_t kernel_x_start =
+ std::max(static_cast<int32_t>(0), -in_x_origin);
+ const int32_t kernel_x_end =
+ std::min(kernel_width, in_width - in_x_origin);
+
+ // Padding top.
+ if (kernel_y_start != 0) {
+ const int32_t num_lines = kernel_y_start;
+ const int32_t num_coeffs = num_lines * kernel_width * in_depth;
+#if USE_TYPED_MEMSETMEMCPY
+ std::fill(output_values, output_values + num_coeffs, 0);
+#else
+ std::memset(output_values, 0, num_coeffs * sizeof(T));
+#endif
+ output_values += num_coeffs;
+ }
+ for (int32_t k_y = kernel_y_start; k_y < kernel_y_end; ++k_y) {
+ // Padding left.
+ if (kernel_x_start != 0) {
+ const int32_t num_coeffs = kernel_x_start * in_depth;
+#if USE_TYPED_MEMSETMEMCPY
+ std::fill(output_values, output_values + num_coeffs, 0);
+#else
+ std::memset(output_values, 0, num_coeffs * sizeof(T));
+#endif
+ output_values += num_coeffs;
+ }
+ // Valid values.
+ {
+ const int32_t in_y = in_y_origin + k_y;
+ const int32_t in_x = in_x_origin + kernel_x_start;
+ const int32_t num_coeffs =
+ (kernel_x_end - kernel_x_start) * in_depth;
+#if USE_TYPED_MEMSETMEMCPY
+ const int32_t offset =
+ batch * batch_stride + in_y * y_stride + in_x * x_stride;
+ std::copy(input_values + offset, input_values + offset + num_coeffs,
+ output_values);
+#else
+ std::memcpy(output_values,
+ input_values // Reusing the restricted pointer.
+ + batch * batch_stride // batch
+ + in_y * y_stride // y
+ + in_x * x_stride, // x
+ num_coeffs * sizeof(T));
+#endif
+ output_values += num_coeffs;
+ }
+ // Padding right.
+ if (kernel_x_end != kernel_width) {
+ const int32_t num_coeffs = (kernel_width - kernel_x_end) * in_depth;
+#if USE_TYPED_MEMSETMEMCPY
+ std::fill(output_values, output_values + num_coeffs, 0);
+#else
+ std::memset(output_values, 0, num_coeffs * sizeof(T));
+#endif
+ output_values += num_coeffs;
+ }
+ }
+ // Padding bottom.
+ if (kernel_y_end != kernel_height) {
+ const int32_t num_lines = kernel_height - kernel_y_end;
+ const int32_t num_coeffs = num_lines * kernel_width * in_depth;
+#if USE_TYPED_MEMSETMEMCPY
+ std::fill(output_values, output_values + num_coeffs, 0);
+#else
+ std::memset(output_values, 0, num_coeffs * sizeof(T));
+#endif
+ output_values += num_coeffs;
+ }
+ }
+ }
+ }
+}
+
+template <typename T>
+void Im2RowVALID(const int32_t* __restrict input_shape,
+ const T* __restrict input_values,
+ const int32_t* __restrict kernel_shape,
+ int32_t stride_y,
+ int32_t stride_x,
+ T* __restrict output_values) {
+ const auto out_size =
+ GetConvOutputSizeVALID(input_shape, kernel_shape, stride_y, stride_x);
+ Im2Row<T>(input_shape, input_values, kernel_shape, stride_y, stride_x,
+ std::get<0>(out_size), std::get<1>(out_size), output_values);
+}
+
+template <typename T>
+void Im2RowSAME(const int32_t* __restrict input_shape,
+ const T* __restrict input_values,
+ const int32_t* __restrict kernel_shape,
+ int32_t stride_y,
+ int32_t stride_x,
+ T* __restrict output_values) {
+ const auto out_size = GetConvOutputSizeSAME(input_shape, stride_y, stride_x);
+ Im2Row<T>(input_shape, input_values, kernel_shape, stride_y, stride_x,
+ std::get<0>(out_size), std::get<1>(out_size), output_values);
+}
+
+// We use macros instead of template functions with templated functors here
+// because it's a lot less verbose and easier for the compiler to optimize.
+#define POOL_OP(OP_NAME, DEFAULT_VALUE, UPDATE_EXPR, RESULT_EXPR) \
+ template <typename T> \
+ void OP_NAME##Pool(const int32_t* __restrict input_shape, \
+ const T* __restrict input_values, int32_t stride_y, \
+ int32_t stride_x, int32_t kernel_height, \
+ int32_t kernel_width, int32_t out_height, \
+ int32_t out_width, T* __restrict output_values) { \
+ BENCHMARK_TIMER(#OP_NAME, "Pool"); \
+ const int32_t batch_size = input_shape[0]; \
+ const int32_t in_height = input_shape[1]; \
+ const int32_t in_width = input_shape[2]; \
+ const int32_t depth = input_shape[3]; \
+ \
+ const int32_t pad_height = \
+ ((out_height - 1) * stride_y + kernel_height - in_height) / 2; \
+ const int32_t pad_width = \
+ ((out_width - 1) * stride_x + kernel_width - in_width) / 2; \
+ \
+ const int32_t in_strides[4] = { \
+ input_shape[1] * input_shape[2] * input_shape[3], \
+ input_shape[2] * input_shape[3], \
+ input_shape[3], \
+ 1, \
+ }; \
+ \
+ T* out_write_ptr = output_values; \
+ for (int32_t batch = 0; batch < batch_size; ++batch) { \
+ for (int32_t out_y = 0; out_y < out_height; ++out_y) { \
+ for (int32_t out_x = 0; out_x < out_width; ++out_x) { \
+ const int32_t in_y_origin = (out_y * stride_y) - pad_height; \
+ const int32_t in_x_origin = (out_x * stride_x) - pad_width; \
+ const int32_t kernel_y_start = \
+ std::max(static_cast<int32_t>(0), -in_y_origin); \
+ const int32_t kernel_y_end = \
+ std::min(kernel_height, in_height - in_y_origin); \
+ const int32_t kernel_x_start = \
+ std::max(static_cast<int32_t>(0), -in_x_origin); \
+ const int32_t kernel_x_end = \
+ std::min(kernel_width, in_width - in_x_origin); \
+ const int32_t count = (kernel_y_end - kernel_y_start) * \
+ (kernel_x_end - kernel_x_start); \
+ (void)sizeof(count); \
+ \
+ for (int32_t chan = 0; chan < depth; ++chan, ++out_write_ptr) { \
+ T value = DEFAULT_VALUE; \
+ for (int32_t k_y = kernel_y_start; k_y < kernel_y_end; ++k_y) { \
+ const int32_t in_y = in_y_origin + k_y; \
+ assert(in_y >= 0 && in_y < in_height); \
+ for (int32_t k_x = kernel_x_start; k_x < kernel_x_end; ++k_x) { \
+ const int32_t in_x = in_x_origin + k_x; \
+ assert(in_x >= 0 && in_x < in_width); \
+ const T next = input_values[batch * in_strides[0] + \
+ in_y * in_strides[1] + \
+ in_x * in_strides[2] + chan]; \
+ value = UPDATE_EXPR; \
+ } \
+ } \
+ *out_write_ptr = RESULT_EXPR; \
+ } \
+ } \
+ } \
+ } \
+ } \
+ \
+ template <typename T> \
+ void OP_NAME##PoolVALID(const int32_t* __restrict input_shape, \
+ const T* __restrict input_values, int32_t stride_y, \
+ int32_t stride_x, int32_t kernel_height, \
+ int32_t kernel_width, T* __restrict output_values) { \
+ const int32_t kernel_shape[4] = {kernel_height, kernel_width, 1, 1}; \
+ const auto out_size = \
+ GetConvOutputSizeVALID(input_shape, kernel_shape, stride_y, stride_x); \
+ OP_NAME##Pool<T>(input_shape, input_values, stride_y, stride_x, \
+ kernel_height, kernel_width, std::get<0>(out_size), \
+ std::get<1>(out_size), output_values); \
+ } \
+ \
+ template <typename T> \
+ void OP_NAME##PoolSAME(const int32_t* __restrict input_shape, \
+ const T* __restrict input_values, int32_t stride_y, \
+ int32_t stride_x, int32_t kernel_height, \
+ int32_t kernel_width, T* __restrict output_values) { \
+ const auto out_size = \
+ GetConvOutputSizeSAME(input_shape, stride_y, stride_x); \
+ OP_NAME##Pool<T>(input_shape, input_values, stride_y, stride_x, \
+ kernel_height, kernel_width, std::get<0>(out_size), \
+ std::get<1>(out_size), output_values); \
+ }
+
+POOL_OP(Max, std::numeric_limits<T>::lowest(), std::max(value, next), value)
+POOL_OP(Avg, 0, value + next, value / count)
+
+template <typename T>
+void Memcpy(const int32_t rank,
+ const int32_t* __restrict input_shape,
+ const T* __restrict input_values,
+ T* __restrict output_values) {
+ BENCHMARK_TIMER("Memcpy");
+ const int32_t size = ShapeSize(rank, input_shape);
+ for (int32_t i = 0; i < size; ++i) {
+ output_values[i] = input_values[i];
+ }
+}
+
+template <typename T>
+void Softmax(const int32_t rank,
+ const int32_t* __restrict input_shape,
+ const T* __restrict input_values,
+ const int32_t reduce_dim,
+ T* __restrict output_values,
+ T* __restrict scratch_values) {
+ BENCHMARK_TIMER("Softmax");
+ const int32_t size = ShapeSize(rank, input_shape);
+ if (rank == 2 && reduce_dim == 1) {
+ T logits_max = std::numeric_limits<T>::lowest();
+
+ // Max.
+ for (int32_t i = 0; i < size; ++i) {
+ logits_max = std::max(logits_max, input_values[i]);
+ }
+
+ // Pre-compute exp.
+ for (int32_t i = 0; i < size; ++i) {
+ scratch_values[i] = std::exp(input_values[i] - logits_max);
+ }
+
+ // Sum over the last dimension, then divide the exps and write out.
+ for (int32_t offset = 0; offset < size; offset += input_shape[1]) {
+ const int32_t end_offset = offset + input_shape[1];
+ T sum = 0;
+ for (int32_t i = offset; i < end_offset; ++i) {
+ sum += scratch_values[i];
+ }
+ const T rcp_denom = static_cast<T>(1) / sum;
+ for (int32_t i = 0; i < input_shape[1]; ++i) {
+ output_values[offset + i] = scratch_values[offset + i] * rcp_denom;
+ }
+ }
+ } else {
+ assert(false && "Generic Softmax not yet supported.");
+ }
+}
+
+// Returns the start position for a slice in a single dimension.
+template <typename T>
+int32_t StridedSliceBegin(int32_t range_mask,
+ const T* __restrict range_values,
+ const T* __restrict strides,
+ const int32_t* __restrict input_shape,
+ int32_t dim) {
+ const bool is_explicit = 0 == (range_mask & (1 << dim));
+ if (is_explicit) {
+ const T range_value = range_values[dim];
+ return (range_value < 0 ? range_value + input_shape[dim] : range_value);
+ } else {
+ const bool is_reverse = strides[dim] < 0;
+ return is_reverse ? input_shape[dim] - 1 : 0;
+ }
+}
+
+// Returns the end position for a slice in a single dimension.
+template <typename T>
+int32_t StridedSliceEnd(int32_t range_mask,
+ const T* __restrict range_values,
+ const T* __restrict strides,
+ const int32_t* __restrict input_shape,
+ int32_t dim) {
+ const bool is_explicit = 0 == (range_mask & (1 << dim));
+ if (is_explicit) {
+ const T range_value = range_values[dim];
+ return (range_value < 0 ? range_value + input_shape[dim] : range_value);
+ } else {
+ const bool is_reverse = strides[dim] < 0;
+ return is_reverse ? -1 : input_shape[dim];
+ }
+}
+
+template <typename T, typename TIdx>
+void StridedSlice(const int32_t input_rank,
+ const int32_t* __restrict input_shape,
+ const T* __restrict input_values,
+ const TIdx* __restrict begin,
+ const TIdx* __restrict end,
+ const TIdx* __restrict strides,
+ int32_t begin_mask,
+ int32_t end_mask,
+ T* __restrict output_values) {
+ BENCHMARK_TIMER("StridedSlice");
+ const int32_t MAX_RANK = 8;
+ assert(input_rank < MAX_RANK);
+
+ // Compute the address strides for each dimension.
+ int32_t dim_addr_strides[MAX_RANK] = {0};
+ dim_addr_strides[input_rank - 1] = 1;
+ for (int32_t dim = input_rank - 2; dim >= 0; --dim) {
+ dim_addr_strides[dim] = dim_addr_strides[dim + 1] * input_shape[dim + 1];
+ }
+
+ // Resolve the masks and get explicit ranges for each dimension.
+ int32_t dim_begin[MAX_RANK];
+ int32_t dim_end[MAX_RANK];
+ bool dim_is_full_range[MAX_RANK];
+ for (int32_t dim = 0; dim < input_rank; ++dim) {
+ const int32_t stride = strides[dim];
+ dim_begin[dim] =
+ StridedSliceBegin(begin_mask, begin, strides, input_shape, dim);
+ dim_end[dim] = StridedSliceEnd(end_mask, end, strides, input_shape, dim);
+ dim_is_full_range[dim] =
+ dim_begin[dim] == 0 && dim_end[dim] == input_shape[dim] && stride == 1;
+ // Make sure that the dim_end is always bigger than dim_begin, this
+ // simplifies the boundary checks below.
+ if (stride > 0 && dim_begin[dim] > dim_end[dim]) {
+ dim_end[dim] += input_shape[dim];
+ }
+
+ // Our termination criteria for loops is that we hit the end exactly, so
+ // we need to ensure that we don't step over the end with stride != 1.
+ const int32_t length_mod = (dim_end[dim] - dim_begin[dim]) % stride;
+ if (length_mod != 0) {
+ dim_end[dim] += stride - length_mod;
+ }
+ }
+
+ // Find out how large the blocks are that we can copy contiguously. (All
+ // dimensions on the right for which we fetch the full range)
+ int32_t last_sliced_dim = input_rank - 1;
+ int32_t block_size = 1;
+ for (int32_t dim = input_rank - 1; dim >= 0 && dim_is_full_range[dim];
+ --dim) {
+ block_size *= input_shape[dim];
+ last_sliced_dim--;
+ }
+
+ // Initialize the read pos for each dimension according to the begin offsets.
+ int32_t read_pos[MAX_RANK] = {0};
+ for (int32_t dim = 0; dim < input_rank; ++dim) {
+ read_pos[dim] = dim_begin[dim];
+ }
+
+ while (read_pos[0] != dim_end[0]) {
+ // Compute the read offset for the current position.
+ int32_t read_offset = 0;
+ for (int32_t dim = 0; dim <= last_sliced_dim; ++dim) {
+ read_offset += (read_pos[dim] % input_shape[dim]) * dim_addr_strides[dim];
+ }
+
+#if USE_TYPED_MEMSETMEMCPY
+ std::copy(input_values + read_offset,
+ input_values + read_offset + block_size, output_values);
+#else
+ std::memcpy(output_values, input_values + read_offset,
+ block_size * sizeof(T));
+#endif
+ output_values += block_size;
+
+ // Advance the read position.
+ for (int32_t dim = last_sliced_dim; dim >= 0; --dim) {
+ read_pos[dim] += strides[dim];
+ if (dim == 0 || read_pos[dim] != dim_end[dim])
+ break;
+ read_pos[dim] = dim_begin[dim];
+ }
+ }
+}
+
+template <typename T>
+void TransposeRank3(const int32_t* __restrict input_shape,
+ const T* __restrict input_values,
+ const int32_t* __restrict perm,
+ T* __restrict output_values) {
+ BENCHMARK_TIMER("TransposeRank3");
+ const int32_t in_strides[3] = {
+ input_shape[1] * input_shape[2],
+ input_shape[2],
+ 1,
+ };
+ const int32_t out_strides[3] = {in_strides[perm[0]], in_strides[perm[1]],
+ in_strides[perm[2]]};
+ const int32_t out_shape[3] = {input_shape[perm[0]], input_shape[perm[1]],
+ input_shape[perm[2]]};
+
+ int32_t write_offset = 0;
+ for (int32_t it0 = 0; it0 < out_shape[0]; ++it0) {
+ const int32_t read_offset0 = it0 * out_strides[0];
+ for (int32_t it1 = 0; it1 < out_shape[1]; ++it1) {
+ const int32_t read_offset01 = read_offset0 + it1 * out_strides[1];
+ for (int32_t it2 = 0; it2 < out_shape[2]; ++it2, ++write_offset) {
+ const int32_t read_offset = read_offset01 + it2 * out_strides[2];
+ output_values[write_offset] = input_values[read_offset];
+ }
+ }
+ }
+}
+
+template <typename T>
+void TransposeRank4(const int32_t* __restrict input_shape,
+ const T* __restrict input_values,
+ const int32_t* __restrict perm,
+ T* __restrict output_values) {
+ BENCHMARK_TIMER("TransposeRank4");
+ const int32_t in_strides[4] = {
+ input_shape[1] * input_shape[2] * input_shape[3],
+ input_shape[2] * input_shape[3],
+ input_shape[3],
+ 1,
+ };
+ const int32_t out_strides[4] = {in_strides[perm[0]], in_strides[perm[1]],
+ in_strides[perm[2]], in_strides[perm[3]]};
+ const int32_t out_shape[4] = {input_shape[perm[0]], input_shape[perm[1]],
+ input_shape[perm[2]], input_shape[perm[3]]};
+
+ int32_t write_offset = 0;
+ for (int32_t it0 = 0; it0 < out_shape[0]; ++it0) {
+ const int32_t read_offset0 = it0 * out_strides[0];
+ for (int32_t it1 = 0; it1 < out_shape[1]; ++it1) {
+ const int32_t read_offset01 = read_offset0 + it1 * out_strides[1];
+ for (int32_t it2 = 0; it2 < out_shape[2]; ++it2) {
+ const int32_t read_offset012 = read_offset01 + it2 * out_strides[2];
+ for (int32_t it3 = 0; it3 < out_shape[3]; ++it3, ++write_offset) {
+ const int32_t read_offset = read_offset012 + it3 * out_strides[3];
+ output_values[write_offset] = input_values[read_offset];
+ }
+ }
+ }
+ }
+}
+
+template <typename T, typename TIdx, typename TDepth>
+void OneHot(const int32_t input_rank,
+ const int32_t* __restrict input_shape,
+ const TIdx* __restrict input_values,
+ const TDepth* __restrict depth,
+ const T* __restrict on_value,
+ const T* __restrict off_value,
+ const int32_t axis,
+ T* __restrict output_values) {
+ BENCHMARK_TIMER("OneHot");
+ const int32_t num_elements = ShapeSize(input_rank, input_shape);
+ // We can assume axis >= 0 in this implementation.
+ const int32_t prefix_dim_size = ShapeSize(axis, input_shape);
+ const int32_t suffix_dim_size = num_elements / prefix_dim_size;
+ int32_t write_offset = 0;
+ for (int32_t i = 0; i < prefix_dim_size; ++i) {
+ const int32_t read_offset_pre = i * suffix_dim_size;
+ for (TDepth d = 0; d < *depth; ++d) {
+ for (int32_t j = 0; j < suffix_dim_size; ++j, ++write_offset) {
+ const int32_t read_offset = read_offset_pre + j;
+ output_values[write_offset] =
+ (input_values[read_offset] == d) ? *on_value : *off_value;
+ }
+ }
+ }
+}
+
+template <typename T, typename TIdx, typename TDepth>
+void OneHotLastDim(const int32_t input_rank,
+ const int32_t* __restrict input_shape,
+ const TIdx* __restrict input_values,
+ const TDepth* __restrict depth,
+ const T* __restrict on_value,
+ const T* __restrict off_value,
+ T* __restrict output_values) {
+ BENCHMARK_TIMER("OneHotLastDim");
+ const int32_t num_elements = ShapeSize(input_rank, input_shape);
+ int32_t write_offset = 0;
+ for (int32_t i = 0; i < num_elements; ++i) {
+ for (TDepth d = 0; d < *depth; ++d, ++write_offset) {
+ output_values[write_offset] =
+ (input_values[i] == d) ? *on_value : *off_value;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+// Simple unary ops
+// -----------------------------------------------------------------------------
+
+// We use macros instead of template functions with templated functors here
+// because it's a lot less verbose and easier for the compiler to optimize.
+
+#if USE_EIGEN
+
+#define SIMPLE_UNARY_OP(OP_NAME, _, EXPR_EIGEN) \
+ template <typename T> \
+ void OP_NAME(const int32_t rank, const int32_t* __restrict input_shape, \
+ const T* __restrict input_values, \
+ T* __restrict output_values) { \
+ BENCHMARK_TIMER(#OP_NAME); \
+ const int32_t size = ShapeSize(rank, input_shape); \
+ auto values = ConstRowVectorMap<T>(input_values, size).array(); \
+ auto output = RowVectorMap<T>(output_values, size).array(); \
+ output = EXPR_EIGEN; \
+ }
+
+#else
+
+#define SIMPLE_UNARY_OP(OP_NAME, EXPR, _) \
+ template <typename T> \
+ void OP_NAME(const int32_t rank, const int32_t* __restrict input_shape, \
+ const T* __restrict input_values, \
+ T* __restrict output_values) { \
+ BENCHMARK_TIMER(#OP_NAME); \
+ const int32_t size = ShapeSize(rank, input_shape); \
+ for (int32_t i = 0; i < size; ++i) { \
+ const T value = input_values[i]; \
+ output_values[i] = EXPR; \
+ } \
+ }
+
+#endif
+
+// Second macro param is value expression, third entry is Eigen vector
+// expression.
+SIMPLE_UNARY_OP(Abs, std::abs(value), values.abs())
+SIMPLE_UNARY_OP(Acos, std::acos(value), values.acos())
+SIMPLE_UNARY_OP(Asin, std::asin(value), values.asin())
+SIMPLE_UNARY_OP(Atan, std::atan(value), values.atan())
+SIMPLE_UNARY_OP(Cos, std::cos(value), values.cos())
+SIMPLE_UNARY_OP(Cosh, std::cosh(value), values.cosh())
+SIMPLE_UNARY_OP(Exp, std::exp(value), values.exp())
+SIMPLE_UNARY_OP(Elu,
+ value < 0 ? std::expm1(value) : value,
+ // Use branchless version of Elu: min(ReLU, e^x - 1)
+ values.max(0).min(values.exp() - 1))
+SIMPLE_UNARY_OP(HardSigmoid,
+ std::min(std::max((static_cast<T>(0.2) * value +
+ static_cast<T>(0.5)),
+ static_cast<T>(0)),
+ static_cast<T>(1)),
+ (0.2 * values + 0.5).max(0).min(1))
+SIMPLE_UNARY_OP(Log, std::log(value), values.log())
+SIMPLE_UNARY_OP(Log1p, std::log1p(value), values.log1p())
+SIMPLE_UNARY_OP(Neg, -value, -values)
+SIMPLE_UNARY_OP(Reciprocal, static_cast<T>(1) / value, values.cwiseInverse())
+SIMPLE_UNARY_OP(Relu, std::max(value, static_cast<T>(0)), values.max(0))
+SIMPLE_UNARY_OP(Relu6,
+ std::min(std::max(value, static_cast<T>(0)), static_cast<T>(6)),
+ values.max(0).min(6))
+SIMPLE_UNARY_OP(Rsqrt, static_cast<T>(1) / std::sqrt(value), values.rsqrt())
+SIMPLE_UNARY_OP(Sigmoid,
+ static_cast<T>(1) / (1 + std::exp(-value)),
+ ((-values).exp() + 1).cwiseInverse())
+SIMPLE_UNARY_OP(Sin, std::sin(value), values.sin())
+SIMPLE_UNARY_OP(Sinh, std::sinh(value), values.sinh())
+SIMPLE_UNARY_OP(Sqrt, std::sqrt(value), values.sqrt())
+SIMPLE_UNARY_OP(Square, value* value, values.square())
+SIMPLE_UNARY_OP(Tan, std::tan(value), values.tan())
+SIMPLE_UNARY_OP(Tanh, std::tanh(value), values.tanh())
+
+// -----------------------------------------------------------------------------
+// Broadcasting binary ops
+// -----------------------------------------------------------------------------
+
+template <typename T, typename OP>
+void OpNoBroadcast(const int32_t left_rank,
+ const int32_t* __restrict left_shape,
+ const T* __restrict left_values,
+ const int32_t right_rank,
+ const int32_t* __restrict right_shape,
+ const T* __restrict right_values,
+ T* __restrict output_values,
+ OP op) {
+ BENCHMARK_TIMER(op.name, "NoBroadcast");
+ const int32_t size = ShapeSize(left_rank, left_shape);
+#if USE_EIGEN
+ auto lhs = ConstRowVectorMap<T>(left_values, size).array();
+ auto rhs = ConstRowVectorMap<T>(right_values, size).array();
+ auto output = RowVectorMap<T>(output_values, size).array();
+ op.apply(lhs, rhs, output);
+#else
+ for (int32_t i = 0; i < size; ++i) {
+ output_values[i] = op(left_values[i], right_values[i]);
+ }
+#endif
+}
+
+template <typename T, typename OP>
+void OpInnerBroadcast(int32_t left_rank,
+ const int32_t* __restrict left_shape,
+ const T* __restrict left_values,
+ int32_t right_rank,
+ const int32_t* __restrict right_shape,
+ const T* __restrict right_values,
+ T* __restrict output_values,
+ OP op) {
+ BENCHMARK_TIMER(op.name, "InnerBroadcast");
+ const int32_t output_size = ShapeSize(left_rank, left_shape);
+ const int32_t inner_size = ShapeSize(right_rank, right_shape);
+ const int32_t outer_size = output_size / inner_size;
+#if USE_EIGEN
+ if (inner_size == 1) {
+ // Apply the same value to all elements.
+ auto left = ConstMatrixMap<T>(left_values, inner_size, outer_size);
+ auto output = MatrixMap<T>(output_values, inner_size, outer_size);
+ op.apply(left.array(), right_values[0], output.array());
+ } else {
+ auto left = ConstMatrixMap<T>(left_values, inner_size, outer_size);
+ auto right = ConstRowVectorMap<T>(right_values, inner_size);
+ auto output = MatrixMap<T>(output_values, inner_size, outer_size);
+ for (int32_t col = 0; col < outer_size; col++) {
+ op.apply(left.col(col).array(), right.array(), output.col(col).array());
+ }
+ }
+#else
+ for (int32_t idx_out = 0; idx_out < outer_size; ++idx_out) {
+ for (int32_t idx_in = 0; idx_in < inner_size; ++idx_in) {
+ const int32_t offset = idx_out * inner_size + idx_in;
+ output_values[offset] = op(left_values[offset], right_values[idx_in]);
+ }
+ }
+#endif
+}
+
+// Increments indices according to a shape.
+// Returns false if indices can't be incremented because they point to the last
+// element.
+//
+// E.g. if shape is (2, 3) and indices is [1, 2], indices is incremented to [2,
+// 0].
+inline bool IncrementIndices(int32_t rank,
+ const int32_t* shape,
+ int32_t* indices) {
+ int32_t i = rank - 1;
+ while (i >= 0 && indices[i] == shape[i] - 1) {
+ --i;
+ }
+ if (i < 0) {
+ return false;
+ }
+ indices[i] += 1;
+ for (++i; i < rank; ++i) {
+ indices[i] = 0;
+ }
+ return true;
+}
+
+// Returns the offset in a values array given its shape and indices.
+// E.g. if the shape is (2, 3) and indices are [1, 2] the offset is 1*3 + 2.
+inline int32_t Offset(int32_t rank,
+ const int32_t* shape,
+ const int32_t* indices) {
+ int32_t offset = 0;
+ int32_t mul = 1;
+ for (int32_t i = rank - 1; i >= 0; --i) {
+ offset += mul * indices[i];
+ mul *= shape[i];
+ }
+ return offset;
+}
+
+// Like Offset() but with broadcasting.
+// E.g. if the input_shape is (2, 1, 3) and indices are [1, 2, 2] the offset is
+// 1*1*3 + 2*0 + 2.
+// The indices_rank can be greater than the input_rank and then the first
+// indices_rank - input_rank indices are ignored.
+// E.g. if the input_shape is (4) and indices are [2, 3, 1] the offset is 1.
+inline int32_t BroadcastOffset(int32_t input_rank,
+ const int32_t* input_shape,
+ int32_t indices_rank,
+ const int32_t* indices) {
+ int32_t offset = 0;
+ int32_t mul = 1;
+ for (int32_t i = input_rank - 1; i >= 0; --i) {
+ int32_t index =
+ input_shape[i] == 1 ? 0 : indices[i + indices_rank - input_rank];
+ offset += mul * index;
+ mul *= input_shape[i];
+ }
+ return offset;
+}
+
+template <typename T, typename OP>
+void OpGenericBroadcast(int32_t left_rank,
+ const int32_t* __restrict left_shape,
+ const T* __restrict left_values,
+ int32_t right_rank,
+ const int32_t* __restrict right_shape,
+ const T* __restrict right_values,
+ T* __restrict output_values,
+ OP op) {
+ BENCHMARK_TIMER(op.name, "GenericBroadcast");
+ const int32_t output_rank = std::max(left_rank, right_rank);
+ const int32_t kMaxRank = 8;
+ assert(output_rank <= kMaxRank);
+
+ int32_t output_shape[kMaxRank];
+ for (int32_t i = 0; i < output_rank; ++i) {
+ int32_t left_i = i - output_rank + left_rank;
+ int32_t right_i = i - output_rank + right_rank;
+ output_shape[i] = std::max(left_i >= 0 ? left_shape[left_i] : 0,
+ right_i >= 0 ? right_shape[right_i] : 0);
+ }
+
+ int32_t output_indices[kMaxRank]{};
+ do {
+ output_values[Offset(output_rank, output_shape, output_indices)] =
+ op(left_values[BroadcastOffset(left_rank, left_shape, output_rank,
+ output_indices)],
+ right_values[BroadcastOffset(right_rank, right_shape, output_rank,
+ output_indices)]);
+ } while (IncrementIndices(output_rank, output_shape, output_indices));
+}
+
+#define BROADCAST_BINARY_OP(OP_NAME, EXPR, EXPR_EIGEN) \
+ template <typename T> \
+ struct Op##OP_NAME { \
+ const char* name = #OP_NAME; \
+ T operator()(const T lhs, const T rhs) { return EXPR; } \
+ template <typename X, typename Y, typename Z> \
+ void apply(const X& lhs, const Y& rhs, Z out) { \
+ out = EXPR_EIGEN; \
+ } \
+ }; \
+ template <typename T> \
+ void OP_NAME##NoBroadcast( \
+ const int32_t left_rank, const int32_t* __restrict left_shape, \
+ const T* __restrict left_values, const int32_t right_rank, \
+ const int32_t* __restrict right_shape, const T* __restrict right_values, \
+ T* __restrict output_values) { \
+ OpNoBroadcast(left_rank, left_shape, left_values, right_rank, right_shape, \
+ right_values, output_values, Op##OP_NAME<T>()); \
+ } \
+ template <typename T> \
+ void OP_NAME##InnerBroadcast( \
+ const int32_t left_rank, const int32_t* __restrict left_shape, \
+ const T* __restrict left_values, const int32_t right_rank, \
+ const int32_t* __restrict right_shape, const T* __restrict right_values, \
+ T* __restrict output_values) { \
+ OpInnerBroadcast(left_rank, left_shape, left_values, right_rank, \
+ right_shape, right_values, output_values, \
+ Op##OP_NAME<T>()); \
+ } \
+ template <typename T> \
+ void OP_NAME(const int32_t left_rank, const int32_t* __restrict left_shape, \
+ const T* __restrict left_values, const int32_t right_rank, \
+ const int32_t* __restrict right_shape, \
+ const T* __restrict right_values, \
+ T* __restrict output_values) { \
+ OpGenericBroadcast(left_rank, left_shape, left_values, right_rank, \
+ right_shape, right_values, output_values, \
+ Op##OP_NAME<T>()); \
+ }
+
+// Second macro param is value expression, third entry is Eigen vector
+// expression.
+BROADCAST_BINARY_OP(Add, lhs + rhs, lhs + rhs)
+BROADCAST_BINARY_OP(Maximum, std::max(lhs, rhs), lhs.max(rhs))
+BROADCAST_BINARY_OP(Minimum, std::min(lhs, rhs), lhs.min(rhs))
+BROADCAST_BINARY_OP(Mul, lhs* rhs, lhs* rhs)
+BROADCAST_BINARY_OP(Sub, lhs - rhs, lhs - rhs)
+BROADCAST_BINARY_OP(SquaredDifference,
+ (lhs - rhs) * (lhs - rhs),
+ (lhs - rhs).square())
+
+// -----------------------------------------------------------------------------
+// Reduce ops
+// -----------------------------------------------------------------------------
+
+// We use macros instead of template functions with templated functors here
+// because it's a lot less verbose and easier for the compiler to optimize.
+#define REDUCE_OP(OP_NAME, DEFAULT_VALUE, UPDATE_EXPR, RESULT_EXPR) \
+ template <typename T, typename Tidx> \
+ void OP_NAME##InnerReduce( \
+ int32_t input_rank, const int32_t* __restrict input_shape, \
+ const T* __restrict input_values, int32_t index_tensor_rank, \
+ const int32_t* __restrict index_shape, \
+ const Tidx* __restrict index_values, T* __restrict output_values) { \
+ BENCHMARK_TIMER(#OP_NAME, "InnerReduce"); \
+ const int32_t inner_size = \
+ GetReduceInnerSize(input_rank, input_shape, index_tensor_rank, \
+ index_shape, index_values); \
+ const int32_t input_size = ShapeSize(input_rank, input_shape); \
+ const int32_t outer_size = input_size / inner_size; \
+ for (int32_t idx_out = 0; idx_out < outer_size; ++idx_out) { \
+ T value = DEFAULT_VALUE; \
+ for (int32_t idx_in = 0; idx_in < inner_size; ++idx_in) { \
+ const T prev = value; \
+ const T next = input_values[idx_out * inner_size + idx_in]; \
+ value = UPDATE_EXPR; \
+ } \
+ const T count = inner_size; \
+ /* Used by mean reduce. */ \
+ (void)sizeof(count); \
+ output_values[idx_out] = RESULT_EXPR; \
+ } \
+ } \
+ template <typename T, typename Tidx> \
+ void OP_NAME##GenericReduceRank2( \
+ int32_t input_rank, const int32_t* __restrict input_shape, \
+ const T* __restrict input_values, int32_t index_tensor_rank, \
+ const int32_t* __restrict index_shape, \
+ const Tidx* __restrict index_values, T* __restrict output_values) { \
+ assert(input_rank == 2); \
+ assert(index_tensor_rank <= 1); \
+ BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank2"); \
+ const int32_t output_size = input_shape[1]; \
+ std::fill_n(output_values, output_size, DEFAULT_VALUE); \
+ for (int32_t dim0 = 0; dim0 < input_shape[0]; ++dim0) { \
+ for (int32_t dim1 = 0; dim1 < input_shape[1]; ++dim1, ++input_values) { \
+ T* out_ptr = output_values + dim1; \
+ const T prev = *out_ptr; \
+ const T next = *input_values; \
+ *out_ptr = UPDATE_EXPR; \
+ } \
+ } \
+ const T count = input_shape[0]; \
+ /* Used by mean reduce. */ \
+ (void)sizeof(count); \
+ for (int32_t i = 0; i < output_size; ++i) { \
+ const T value = output_values[i]; \
+ output_values[i] = RESULT_EXPR; \
+ } \
+ } \
+ template <typename T, typename Tidx> \
+ void OP_NAME##GenericReduceRank3( \
+ int32_t input_rank, const int32_t* __restrict input_shape, \
+ const T* __restrict input_values, int32_t index_tensor_rank, \
+ const int32_t* __restrict index_shape, \
+ const Tidx* __restrict index_values, T* __restrict output_values) { \
+ assert(input_rank == 3); \
+ assert(index_tensor_rank <= 1); \
+ BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank3"); \
+ int32_t out_shape[3] = {input_shape[0], input_shape[1], input_shape[2]}; \
+ bool reduce_mask[3] = {false, false, false}; \
+ const int32_t num_indices = index_tensor_rank > 0 ? index_shape[0] : 1; \
+ for (int32_t i = 0; i < num_indices; ++i) { \
+ reduce_mask[index_values[i]] = true; \
+ out_shape[index_values[i]] = 1; \
+ } \
+ const int32_t out_strides[3] = { \
+ reduce_mask[0] ? 0 : out_shape[1] * out_shape[2], \
+ reduce_mask[1] ? 0 : out_shape[2], \
+ reduce_mask[2] ? 0 : 1, \
+ }; \
+ const int32_t output_size = ShapeSize(input_rank, out_shape); \
+ std::fill_n(output_values, output_size, DEFAULT_VALUE); \
+ for (int32_t dim0 = 0; dim0 < input_shape[0]; ++dim0) { \
+ for (int32_t dim1 = 0; dim1 < input_shape[1]; ++dim1) { \
+ for (int32_t dim2 = 0; dim2 < input_shape[2]; \
+ ++dim2, ++input_values) { \
+ T* out_ptr = output_values + out_strides[0] * dim0 + \
+ out_strides[1] * dim1 + out_strides[2] * dim2; \
+ const T prev = *out_ptr; \
+ const T next = *input_values; \
+ *out_ptr = UPDATE_EXPR; \
+ } \
+ } \
+ } \
+ const T count = (reduce_mask[0] ? input_shape[0] : 1) * \
+ (reduce_mask[1] ? input_shape[1] : 1) * \
+ (reduce_mask[2] ? input_shape[2] : 1); \
+ /* Used by mean reduce. */ \
+ (void)sizeof(count); \
+ for (int32_t i = 0; i < output_size; ++i) { \
+ const T value = output_values[i]; \
+ output_values[i] = RESULT_EXPR; \
+ } \
+ } \
+ template <typename T, typename Tidx> \
+ void OP_NAME##GenericReduceRank4( \
+ int32_t input_rank, const int32_t* __restrict input_shape, \
+ const T* __restrict input_values, int32_t index_tensor_rank, \
+ const int32_t* __restrict index_shape, \
+ const Tidx* __restrict index_values, T* __restrict output_values) { \
+ assert(input_rank == 4); \
+ assert(index_tensor_rank <= 1); \
+ BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank4"); \
+ int32_t out_shape[4] = {input_shape[0], input_shape[1], input_shape[2], \
+ input_shape[3]}; \
+ bool reduce_mask[4] = {false, false, false, false}; \
+ const int32_t num_indices = index_tensor_rank > 0 ? index_shape[0] : 1; \
+ for (int32_t i = 0; i < num_indices; ++i) { \
+ reduce_mask[index_values[i]] = true; \
+ out_shape[index_values[i]] = 1; \
+ } \
+ const int32_t out_strides[4] = { \
+ reduce_mask[0] ? 0 : out_shape[1] * out_shape[2] * out_shape[3], \
+ reduce_mask[1] ? 0 : out_shape[2] * out_shape[3], \
+ reduce_mask[2] ? 0 : out_shape[3], \
+ reduce_mask[3] ? 0 : 1, \
+ }; \
+ const int32_t output_size = ShapeSize(input_rank, out_shape); \
+ std::fill_n(output_values, output_size, DEFAULT_VALUE); \
+ for (int32_t dim0 = 0; dim0 < input_shape[0]; ++dim0) { \
+ for (int32_t dim1 = 0; dim1 < input_shape[1]; ++dim1) { \
+ for (int32_t dim2 = 0; dim2 < input_shape[2]; ++dim2) { \
+ for (int32_t dim3 = 0; dim3 < input_shape[3]; \
+ ++dim3, ++input_values) { \
+ T* out_ptr = output_values + out_strides[0] * dim0 + \
+ out_strides[1] * dim1 + out_strides[2] * dim2 + \
+ out_strides[3] * dim3; \
+ const T prev = *out_ptr; \
+ const T next = *input_values; \
+ *out_ptr = UPDATE_EXPR; \
+ } \
+ } \
+ } \
+ } \
+ const T count = (reduce_mask[0] ? input_shape[0] : 1) * \
+ (reduce_mask[1] ? input_shape[1] : 1) * \
+ (reduce_mask[2] ? input_shape[2] : 1) * \
+ (reduce_mask[3] ? input_shape[3] : 1); \
+ /* Used by mean reduce. */ \
+ (void)sizeof(count); \
+ for (int32_t i = 0; i < output_size; ++i) { \
+ const T value = output_values[i]; \
+ output_values[i] = RESULT_EXPR; \
+ } \
+ } \
+ template <typename T, typename Tidx> \
+ void OP_NAME##GenericReduceRank5( \
+ int32_t input_rank, const int32_t* __restrict input_shape, \
+ const T* __restrict input_values, int32_t index_tensor_rank, \
+ const int32_t* __restrict index_shape, \
+ const Tidx* __restrict index_values, T* __restrict output_values) { \
+ assert(input_rank == 5); \
+ assert(index_tensor_rank <= 1); \
+ BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank5"); \
+ int32_t out_shape[5] = {input_shape[0], input_shape[1], input_shape[2], \
+ input_shape[3], input_shape[4]}; \
+ /* If true, reduce the input across that dimension. */ \
+ bool reduce_mask[5] = {false, false, false, false, false}; \
+ const int32_t num_indices = index_tensor_rank > 0 ? index_shape[0] : 1; \
+ for (int32_t i = 0; i < num_indices; ++i) { \
+ reduce_mask[index_values[i]] = true; \
+ out_shape[index_values[i]] = 1; \
+ } \
+ const int32_t out_strides[5] = { \
+ reduce_mask[0] \
+ ? 0 \
+ : out_shape[1] * out_shape[2] * out_shape[3] * out_shape[4], \
+ reduce_mask[1] ? 0 : out_shape[2] * out_shape[3] * out_shape[4], \
+ reduce_mask[2] ? 0 : out_shape[3] * out_shape[4], \
+ reduce_mask[3] ? 0 : out_shape[4], \
+ reduce_mask[4] ? 0 : 1, \
+ }; \
+ const int32_t output_size = ShapeSize(input_rank, out_shape); \
+ std::fill_n(output_values, output_size, DEFAULT_VALUE); \
+ for (int32_t dim0 = 0; dim0 < input_shape[0]; ++dim0) { \
+ for (int32_t dim1 = 0; dim1 < input_shape[1]; ++dim1) { \
+ for (int32_t dim2 = 0; dim2 < input_shape[2]; ++dim2) { \
+ for (int32_t dim3 = 0; dim3 < input_shape[3]; ++dim3) { \
+ for (int32_t dim4 = 0; dim4 < input_shape[4]; \
+ ++dim4, ++input_values) { \
+ T* out_ptr = output_values + out_strides[0] * dim0 + \
+ out_strides[1] * dim1 + out_strides[2] * dim2 + \
+ out_strides[3] * dim3 + out_strides[4] * dim4; \
+ const T prev = *out_ptr; \
+ const T next = *input_values; \
+ *out_ptr = UPDATE_EXPR; \
+ } \
+ } \
+ } \
+ } \
+ } \
+ const T count = (reduce_mask[0] ? input_shape[0] : 1) * \
+ (reduce_mask[1] ? input_shape[1] : 1) * \
+ (reduce_mask[2] ? input_shape[2] : 1) * \
+ (reduce_mask[3] ? input_shape[3] : 1) * \
+ (reduce_mask[4] ? input_shape[4] : 1); \
+ /* Used by mean reduce. */ \
+ (void)sizeof(count); \
+ for (int32_t i = 0; i < output_size; ++i) { \
+ const T value = output_values[i]; \
+ output_values[i] = RESULT_EXPR; \
+ } \
+ }
+
+REDUCE_OP(Max, std::numeric_limits<T>::lowest(), std::max(prev, next), value)
+REDUCE_OP(Min, std::numeric_limits<T>::infinity(), std::min(prev, next), value)
+REDUCE_OP(Sum, 0, prev + next, value)
+REDUCE_OP(Mean, 0, prev + next, value / count)
+
+// -----------------------------------------------------------------------------
+// Dequantize ops
+// -----------------------------------------------------------------------------
+
+template <typename T>
+void DequantizeMinCombined(const int32_t rank,
+ const int32_t* __restrict input_shape,
+ const T* __restrict input_values,
+ const float* __restrict min_range,
+ const float* __restrict max_range,
+ float* __restrict output_values) {
+ BENCHMARK_TIMER("DequantizeMinCombined");
+ const int32_t size = ShapeSize(rank, input_shape);
+ const float offset =
+ std::is_signed<T>::value
+ ? (static_cast<float>(std::numeric_limits<T>::max()) -
+ std::numeric_limits<T>::min() + 1) /
+ 2.0f
+ : 0.0f;
+ const float range_scale = (max_range[0] - min_range[0]) /
+ (static_cast<float>(std::numeric_limits<T>::max()) -
+ std::numeric_limits<T>::min());
+ for (int32_t i = 0; i < size; ++i) {
+ output_values[i] =
+ ((static_cast<int32_t>(input_values[i]) + offset) * range_scale) +
+ min_range[0];
+ }
+}
+
+template <typename T>
+void DequantizeMinFirst(const int32_t rank,
+ const int32_t* __restrict input_shape,
+ const T* __restrict input_values,
+ const float* __restrict min_range,
+ const float* __restrict max_range,
+ float* __restrict output_values) {
+ BENCHMARK_TIMER("DequantizeMinFirst");
+ const int32_t size = ShapeSize(rank, input_shape);
+ const float range_scale = (max_range[0] - min_range[0]) /
+ (static_cast<float>(std::numeric_limits<T>::max()) -
+ std::numeric_limits<T>::min());
+ const float range_min_rounded =
+ (max_range[0] == min_range[0]
+ ? min_range[0]
+ : std::round(min_range[0] / range_scale) * range_scale);
+ for (int32_t i = 0; i < size; ++i) {
+ output_values[i] = ((static_cast<int32_t>(input_values[i]) -
+ std::numeric_limits<T>::min()) *
+ range_scale) +
+ range_min_rounded;
+ }
+}
+
+// -----------------------------------------------------------------------------
+// AddN op
+// -----------------------------------------------------------------------------
+
+template <typename T>
+void AddN(const int32_t rank,
+ const int32_t* __restrict shape,
+ std::initializer_list<const T* __restrict> input_values,
+ T* __restrict output_values) {
+ BENCHMARK_TIMER("AddN");
+ const int32_t size = ShapeSize(rank, shape);
+#if USE_EIGEN
+ auto output = RowVectorMap<T>(output_values, size).array();
+ std::fill_n(output_values, size, 0);
+ for (const auto input_value : input_values) {
+ output += ConstRowVectorMap<T>(input_value, size).array();
+ }
+#else
+ for (int32_t i = 0; i < size; ++i) {
+ T output_value = 0;
+ for (auto input_value : input_values) {
+ output_value += input_value[i];
+ }
+ output_values[i] = output_value;
+ }
+#endif
+}
+
+// -----------------------------------------------------------------------------
+// CONSTANTS
+// Note that for now, endianness of the target machine needs to match that of
+// the one training was performed on.
+// -----------------------------------------------------------------------------
+const int32_t dnn_hiddenlayer_0_bias__0__cf__0_shape[1] = {20};
+const union {
+ uint8_t bytes[80];
+ float values[20];
+} dnn_hiddenlayer_0_bias__0__cf__0 = {{
+ 0x93, 0xa2, 0x71, 0x3e, 0x73, 0xa8, 0x38, 0xbf, 0x57, 0xda, 0x8d, 0xbf,
+ 0x99, 0x04, 0x97, 0x3f, 0xed, 0xf1, 0xef, 0xbf, 0x0f, 0x0f, 0xa0, 0xbf,
+ 0x44, 0xad, 0x97, 0x3f, 0x4f, 0x01, 0xd0, 0x3f, 0x1a, 0xab, 0x30, 0xbf,
+ 0x26, 0xec, 0x01, 0x3e, 0x2b, 0x49, 0xfb, 0xbf, 0x01, 0xc6, 0x57, 0x3e,
+ 0x84, 0xf7, 0x8d, 0x3f, 0xaf, 0x32, 0xd1, 0xbe, 0x95, 0x54, 0xc9, 0x3f,
+ 0x3c, 0x57, 0x30, 0xc0, 0x90, 0x1a, 0xc9, 0x3f, 0x38, 0x7f, 0xb7, 0x3f,
+ 0x5d, 0xf7, 0x2a, 0x3c, 0x53, 0x6b, 0x0b, 0xc0,
+}};
+const int32_t dnn_hiddenlayer_0_kernel__1__cf__1_shape[2] = {325, 20};
+const union {
+ uint8_t bytes[26000];
+ float values[6500];
+} dnn_hiddenlayer_0_kernel__1__cf__1 = {{
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0x50, 0x3e, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0x08, 0x50, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x5c, 0xad, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0xb4, 0x72, 0xbf, 0x60, 0xb0, 0x8a, 0x3f, 0x70, 0xb1, 0xa4, 0xbf,
+ 0x80, 0xb2, 0x3e, 0x3f, 0xa0, 0xb4, 0xf2, 0x3e, 0x78, 0x07, 0xb6, 0xbf,
+ 0x70, 0x5c, 0xad, 0xbf, 0x60, 0x06, 0x1c, 0xbf, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb0, 0x8a, 0x3d, 0x58, 0xb0, 0x8a, 0xbf,
+ 0x90, 0x5e, 0x61, 0x3f, 0x70, 0x5c, 0xad, 0xbf, 0x70, 0x06, 0x1c, 0x3f,
+ 0x80, 0x5c, 0xad, 0x3e, 0x68, 0x06, 0x9c, 0xbf, 0x78, 0x07, 0xb6, 0xbf,
+ 0x60, 0x06, 0x1c, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0x08, 0x50, 0xbf, 0x58, 0x05, 0x82, 0xbf, 0x70, 0xb1, 0xa4, 0x3f,
+ 0xa0, 0xb4, 0xf2, 0xbf, 0x70, 0x5c, 0xad, 0xbf, 0x60, 0xb0, 0x8a, 0x3f,
+ 0x90, 0xb3, 0xd8, 0x3f, 0x60, 0x06, 0x1c, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0xa0, 0xb4, 0xf2, 0xbf, 0x60, 0xb0, 0x8a, 0x3e, 0x58, 0x05, 0x82, 0x3f,
+ 0x60, 0x5c, 0xad, 0xbe, 0x90, 0xb3, 0xd8, 0x3f, 0x72, 0x5c, 0x2d, 0xc0,
+ 0x80, 0xb2, 0xbe, 0x3f, 0x88, 0x5d, 0xc7, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0x05, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x60, 0x5c, 0xad, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x5c, 0xad, 0x3e, 0x58, 0xb0, 0x8a, 0xbf, 0x70, 0x06, 0x1c, 0x3f,
+ 0x80, 0xb2, 0xbe, 0xbf, 0x80, 0x08, 0xd0, 0x3e, 0x60, 0xb0, 0x8a, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x68, 0x06, 0x9c, 0xbf, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0x5c, 0xad, 0xbe, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x60, 0x5c, 0xad, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0x58, 0x05, 0x82, 0xbf, 0x90, 0x08, 0x50, 0x3f, 0x80, 0xb2, 0xbe, 0xbf,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x68, 0x06, 0x9c, 0xbf, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0x5d, 0xc7, 0xbf, 0xa0, 0xb4, 0xf2, 0xbf, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3f, 0x84, 0x5d, 0xc7, 0x40, 0x18, 0xb4, 0x65, 0xc0,
+ 0x80, 0x08, 0xd0, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e, 0x68, 0x06, 0x1c, 0xc0,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x70, 0x5c, 0x2d, 0x3f, 0x80, 0xb0, 0x8a, 0x3d,
+ 0xe0, 0x05, 0x0f, 0x40, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0xa8, 0x5f, 0xfb, 0x3f, 0xe0, 0x05, 0x0f, 0x40,
+ 0x80, 0xb2, 0x3e, 0x3f, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x70, 0x5c, 0x2d, 0xbf, 0x60, 0x5b, 0x93, 0xbf,
+ 0x70, 0xb1, 0xa4, 0x3f, 0x98, 0x09, 0xea, 0xbf, 0x68, 0x06, 0x9c, 0xbf,
+ 0x60, 0x5b, 0x93, 0x3f, 0x80, 0xb2, 0xbe, 0x3f, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x80, 0xb0, 0x8a, 0x3d, 0xa8, 0x5f, 0xfb, 0xbf, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x68, 0x06, 0x9c, 0x3f, 0x60, 0x5c, 0xad, 0xbe, 0x88, 0x08, 0xd0, 0x3f,
+ 0xf0, 0x06, 0x29, 0xc0, 0x88, 0x5d, 0xc7, 0x3f, 0x70, 0xb1, 0xa4, 0x3f,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x5c, 0xb0, 0x0a, 0xc0, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0x08, 0x50, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x60, 0x06, 0x1c, 0xbf, 0xa0, 0xb4, 0xf2, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x58, 0xb0, 0x8a, 0xbf,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0x5d, 0xc7, 0xbf, 0x80, 0x08, 0xd0, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0xf2, 0xbe, 0x78, 0x07, 0xb6, 0xbf,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x58, 0xb0, 0x8a, 0xbf, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x90, 0xb3, 0xd8, 0xbf, 0x60, 0xb0, 0x8a, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0x5c, 0xad, 0xbe, 0x68, 0x06, 0x9c, 0xbf, 0x00, 0x00, 0x00, 0x00,
+ 0x68, 0x06, 0x9c, 0xbf, 0xa0, 0xb4, 0xf2, 0x3e, 0x90, 0x08, 0x50, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x5c, 0xb0, 0x0a, 0x40, 0x70, 0x5c, 0xad, 0x3f,
+ 0x54, 0x05, 0x02, 0xc0, 0x58, 0x05, 0x82, 0x3f, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x90, 0x5e, 0x61, 0xbf, 0x60, 0xb0, 0x8a, 0x3f, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb2, 0x3e, 0xbf, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x60, 0x5c, 0xad, 0xbe, 0x70, 0x5c, 0xad, 0x3f, 0x5c, 0xb0, 0x0a, 0x40,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x58, 0x05, 0x82, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0x5c, 0xad, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0x06, 0x1c, 0xbf,
+ 0x58, 0xb0, 0x8a, 0xbf, 0x68, 0x06, 0x9c, 0x3f, 0x98, 0x5e, 0xe1, 0xbf,
+ 0x68, 0x06, 0x9c, 0xbf, 0x68, 0x06, 0x9c, 0x3f, 0x90, 0xb3, 0xd8, 0x3f,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x80, 0x08, 0x50, 0x3e, 0xd8, 0x5a, 0x06, 0xc0,
+ 0x80, 0x5c, 0xad, 0x3e, 0x60, 0xb0, 0x8a, 0x3f, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0xb2, 0xbe, 0x3f, 0xf6, 0xb1, 0x31, 0xc0, 0x88, 0x08, 0xd0, 0x3f,
+ 0x78, 0x07, 0xb6, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x05, 0x0f, 0xc0,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0x08, 0x50, 0xbe, 0x60, 0xb0, 0x0a, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbf,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x70, 0x06, 0x1c, 0x3f, 0x40, 0xb0, 0x0a, 0xbe,
+ 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0xb0, 0x8a, 0x3d, 0x98, 0x5e, 0xe1, 0xbf,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x60, 0xb0, 0x0a, 0x3f, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x90, 0x5e, 0x61, 0xbf, 0x80, 0x08, 0x50, 0x3e,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x80, 0xb0, 0x8a, 0xbd, 0x90, 0x5e, 0x61, 0xbf,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x90, 0xb3, 0xd8, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0xbe, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x80, 0x08, 0xd0, 0x3e, 0x60, 0x06, 0x1c, 0xbf, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x68, 0x06, 0x9c, 0x3f, 0x68, 0x06, 0x9c, 0x3f, 0xa0, 0x09, 0xea, 0x3f,
+ 0x24, 0x0a, 0x77, 0xc0, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb2, 0x3e, 0x3f, 0x60, 0x5b, 0x93, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0xa0, 0xb4, 0x72, 0x3f, 0x80, 0xb0, 0x8a, 0x3d, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x70, 0x5c, 0x2d, 0xbf, 0x90, 0x5e, 0x61, 0x3f,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0x06, 0x1c, 0xbf, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x58, 0xb0, 0x8a, 0xbf, 0x60, 0xb0, 0x8a, 0x3f,
+ 0xa8, 0x5f, 0xfb, 0xbf, 0x60, 0x5b, 0x93, 0xbf, 0x60, 0x5b, 0x93, 0x3f,
+ 0x88, 0x5d, 0xc7, 0x3f, 0x80, 0x08, 0x50, 0xbf, 0x80, 0x08, 0x50, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0xbf, 0x80, 0x5c, 0xad, 0x3e, 0x60, 0x5b, 0x93, 0x3f,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb2, 0xbe, 0x3f, 0xf6, 0xb1, 0x31, 0xc0,
+ 0x80, 0xb2, 0xbe, 0x3f, 0x78, 0x07, 0xb6, 0x3f, 0x80, 0xb0, 0x8a, 0xbd,
+ 0xe0, 0x05, 0x0f, 0xc0, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x8a, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe, 0x70, 0x06, 0x1c, 0x3f,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x70, 0xb1, 0xa4, 0x3f,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x60, 0x5b, 0x93, 0xbf, 0x80, 0x08, 0x50, 0xbe,
+ 0xe4, 0xb0, 0x17, 0xc0, 0x60, 0x5c, 0xad, 0xbe, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0x08, 0x50, 0xbf, 0x80, 0xb2, 0xbe, 0x3f,
+ 0x80, 0x08, 0xd0, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x68, 0x06, 0x9c, 0x3f, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x60, 0x5b, 0x93, 0xbf, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0x5b, 0x13, 0xc0,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x90, 0x5e, 0x61, 0xbf, 0x80, 0xb2, 0xbe, 0x3f, 0x70, 0xb1, 0xa4, 0xbf,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0x06, 0x1c, 0xbf, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x58, 0x05, 0x82, 0x3f, 0xa6, 0xdb, 0x99, 0xc0, 0x80, 0xb2, 0xbe, 0xbf,
+ 0x98, 0x5e, 0xe1, 0x3f, 0x80, 0xb2, 0x3e, 0x3f, 0x90, 0x5e, 0x61, 0x3f,
+ 0xf0, 0x06, 0x29, 0x40, 0x78, 0x07, 0xb6, 0xbf, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0x05, 0x0f, 0x40, 0x80, 0xb2, 0x3e, 0xbf, 0x70, 0x5c, 0xad, 0x3f,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x88, 0x5d, 0xc7, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0xd0, 0x3e, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x58, 0x05, 0x82, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb2, 0x3e, 0xbf, 0x60, 0x5b, 0x93, 0xbf,
+ 0x60, 0xb0, 0x8a, 0x3f, 0x98, 0x5e, 0xe1, 0xbf, 0x60, 0x5b, 0x93, 0xbf,
+ 0x68, 0x06, 0x9c, 0x3f, 0x88, 0x08, 0xd0, 0x3f, 0x80, 0x08, 0x50, 0xbf,
+ 0x80, 0x08, 0x50, 0x3e, 0x98, 0x09, 0xea, 0xbf, 0x80, 0x08, 0x50, 0x3e,
+ 0x58, 0x05, 0x82, 0x3f, 0x60, 0x5c, 0xad, 0xbe, 0x88, 0x08, 0xd0, 0x3f,
+ 0x72, 0x5c, 0x2d, 0xc0, 0x88, 0x5d, 0xc7, 0x3f, 0x78, 0x07, 0xb6, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x54, 0x05, 0x02, 0xc0, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0xa0, 0xb4, 0xf2, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x06, 0x1c, 0xbf,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0x08, 0x50, 0xbf, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb2, 0x3e, 0x3f, 0x80, 0x5c, 0xad, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0x08, 0xd0, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x60, 0xb0, 0x8a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x90, 0x08, 0x50, 0x3f, 0x60, 0xb0, 0x8a, 0x3e, 0x70, 0x06, 0x1c, 0x3f,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x5c, 0xb0, 0x0a, 0x40, 0x80, 0xb0, 0x8a, 0xbd,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0xb2, 0x3e, 0x3f, 0x51, 0xde, 0xda, 0xc0,
+ 0x80, 0xb2, 0xbe, 0xbf, 0xa0, 0xb4, 0xf2, 0x3f, 0x78, 0x07, 0xb6, 0x3f,
+ 0xf0, 0x06, 0x29, 0x40, 0x60, 0x5b, 0x93, 0x3f, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x80, 0x08, 0xd0, 0xbe, 0x80, 0x5c, 0xad, 0x3e, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x70, 0x5c, 0x2d, 0xbf, 0xa8, 0x5f, 0xfb, 0xbf,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e, 0x60, 0x5b, 0x93, 0xbf,
+ 0xa0, 0xb4, 0xf2, 0xbf, 0x70, 0x5c, 0xad, 0x3f, 0x58, 0xb0, 0x8a, 0xbf,
+ 0x58, 0x05, 0x82, 0xbf, 0x70, 0xb1, 0xa4, 0x3f, 0x70, 0x5c, 0x2d, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x5c, 0xad, 0x3e, 0x5c, 0xb0, 0x0a, 0xc0,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0x08, 0xd0, 0xbe,
+ 0x74, 0x5c, 0x2d, 0x40, 0x60, 0x5b, 0x13, 0xc0, 0x60, 0xb0, 0x8a, 0x3f,
+ 0x80, 0x5c, 0xad, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e, 0x7e, 0xb2, 0x3e, 0xc0,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0x08, 0x50, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0x06, 0x1c, 0xbf,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0x3e, 0xa0, 0xb4, 0x72, 0xbf,
+ 0x80, 0x08, 0x50, 0xbe, 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0x06, 0x1c, 0xbf, 0x90, 0x5e, 0x61, 0xbf,
+ 0x07, 0xb3, 0xcb, 0xc0, 0xa0, 0xb4, 0x72, 0xbf, 0x60, 0x06, 0x1c, 0xbf,
+ 0x68, 0x06, 0x9c, 0x3f, 0xa0, 0xb4, 0xf2, 0x3e, 0x14, 0x09, 0x5d, 0x40,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x88, 0x08, 0xd0, 0xbf,
+ 0xa8, 0x5f, 0xfb, 0xbf, 0xa8, 0x5f, 0xfb, 0x3f, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x54, 0x05, 0x02, 0xc0, 0x98, 0x5e, 0xe1, 0x3f, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x5d, 0xc7, 0xbf, 0x68, 0x06, 0x9c, 0xbf, 0x80, 0x08, 0xd0, 0x3e,
+ 0x90, 0x5e, 0x61, 0xbf, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x8a, 0x3f,
+ 0x90, 0x08, 0x50, 0x3f, 0x60, 0x06, 0x1c, 0xbf, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb2, 0xbe, 0xbf, 0x80, 0x08, 0xd0, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x78, 0x07, 0x36, 0x40, 0x88, 0x08, 0xd0, 0xbf,
+ 0x58, 0x05, 0x82, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x84, 0x5d, 0x47, 0xc0, 0x80, 0x08, 0xd0, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x70, 0x5c, 0x2d, 0xbf, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e, 0x70, 0x5c, 0xad, 0xbf,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0x58, 0x05, 0x82, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0xce, 0x88, 0xd6, 0xc0, 0x80, 0x08, 0xd0, 0x3e,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x60, 0xb0, 0x0a, 0x3f, 0x60, 0x5c, 0xad, 0xbe,
+ 0x64, 0x5b, 0x13, 0x40, 0x60, 0xb0, 0x8a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x58, 0x05, 0x82, 0xbf, 0x60, 0x5c, 0xad, 0xbe, 0x90, 0x5e, 0x61, 0xbf,
+ 0x90, 0xb3, 0xd8, 0xbf, 0x60, 0xb0, 0x8a, 0x3e, 0x18, 0x30, 0x84, 0x40,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x98, 0x09, 0xea, 0xbf, 0x70, 0xb1, 0xa4, 0xbf,
+ 0x80, 0x08, 0xd0, 0x3e, 0x60, 0x5c, 0xad, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb2, 0x3e, 0x3f, 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0x06, 0x1c, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0x70, 0x5c, 0xad, 0xbf, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0x5c, 0xad, 0x3e, 0x74, 0x5c, 0x2d, 0x40,
+ 0x80, 0x08, 0x50, 0xbf, 0xa0, 0xb4, 0x72, 0x3f, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x00, 0x08, 0x43, 0xc0, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0xbe, 0x60, 0x5c, 0xad, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0x5c, 0xad, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0x06, 0x1c, 0xbf, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0x08, 0xd0, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0xe0, 0x05, 0x0f, 0xc0, 0x01, 0x08, 0xc3, 0xc0,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x68, 0x06, 0x9c, 0x3f,
+ 0x80, 0xb0, 0x8a, 0xbd, 0xa0, 0xb4, 0x72, 0x3f, 0x60, 0x06, 0x1c, 0xbf,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x70, 0x06, 0x1c, 0x3f, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb2, 0x3e, 0x3f,
+ 0xf8, 0xb1, 0x31, 0x40, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb2, 0x3e, 0xbf, 0x98, 0x09, 0xea, 0xbf,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x0a, 0x3f, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x60, 0x5b, 0x93, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbf,
+ 0x80, 0xb2, 0x3e, 0xbf, 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x74, 0x5c, 0x2d, 0x40, 0x80, 0xb2, 0x3e, 0xbf, 0x70, 0xb1, 0xa4, 0x3f,
+ 0x90, 0x5e, 0x61, 0xbf, 0x80, 0xb2, 0x3e, 0x3f, 0xf6, 0xb1, 0x31, 0xc0,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0x06, 0x1c, 0xbf,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb2, 0x3e, 0x3f, 0x70, 0x5c, 0x2d, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0xd0, 0xbe, 0x9a, 0x09, 0x6a, 0xc0,
+ 0x80, 0x08, 0x50, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x5c, 0xad, 0xbe, 0xa8, 0x5f, 0xfb, 0x3f,
+ 0x80, 0xb2, 0xbe, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x70, 0x5c, 0x2d, 0x3f,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x90, 0x5e, 0x61, 0x3f, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x90, 0xb3, 0xd8, 0xbf, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0xd0, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x58, 0xb0, 0x8a, 0xbf, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x0a, 0x3f,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x58, 0x05, 0x82, 0xbf, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x60, 0x06, 0x1c, 0xbf, 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0x08, 0x50, 0x3e,
+ 0x60, 0xb0, 0x0a, 0x3f, 0xe0, 0x05, 0x0f, 0x40, 0x58, 0x05, 0x82, 0xbf,
+ 0x90, 0xb3, 0xd8, 0x3f, 0x58, 0xb0, 0x8a, 0xbf, 0xa0, 0xb4, 0x72, 0x3f,
+ 0x7e, 0xb2, 0x3e, 0xc0, 0x60, 0xb0, 0x8a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e, 0x70, 0x06, 0x1c, 0x3f,
+ 0x80, 0x08, 0x50, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x58, 0x05, 0x82, 0xbf,
+ 0xa0, 0xb4, 0x72, 0xc0, 0x20, 0x5f, 0x6e, 0x40, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x8a, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x70, 0x5c, 0xad, 0x3f, 0xe4, 0xb0, 0x17, 0xc0, 0x80, 0x08, 0x50, 0x3e,
+ 0x58, 0x05, 0x82, 0x3f, 0x90, 0x08, 0x50, 0x3f, 0x80, 0x08, 0xd0, 0x3e,
+ 0x80, 0x08, 0xd0, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0xac, 0x86, 0xa2, 0xc0,
+ 0x70, 0x5c, 0xad, 0x3f, 0x60, 0xb0, 0x8a, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0xd0, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0x06, 0x1c, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb2, 0x3e, 0xbf,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0xa0, 0xb4, 0x72, 0xbf,
+ 0x80, 0x08, 0xd0, 0xbe, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x0a, 0x3f, 0xa8, 0x5f, 0xfb, 0x3f,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb2, 0xbe, 0x3f, 0x68, 0x06, 0x9c, 0xbf,
+ 0xa0, 0xb4, 0x72, 0x3f, 0xf6, 0xb1, 0x31, 0xc0, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0x08, 0xd0, 0xbe, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0xbe, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0x08, 0x50, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x78, 0x07, 0xb6, 0x3f, 0x80, 0x08, 0xd0, 0xbe, 0x58, 0xb0, 0x8a, 0xbf,
+ 0x80, 0x08, 0x50, 0xbe, 0x90, 0x5e, 0x61, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x90, 0x5e, 0x61, 0x3f,
+ 0x58, 0x05, 0x82, 0xbf, 0x60, 0xb0, 0x8a, 0x3e, 0x90, 0x5e, 0x61, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x90, 0x5e, 0x61, 0x3f, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3e, 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0xa0, 0xb4, 0x72, 0x3f, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0xd0, 0xbe, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0x50, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x60, 0x06, 0x1c, 0xbf, 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0x08, 0xd0, 0xbe, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x90, 0x5e, 0x61, 0xbf, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x70, 0xb1, 0xa4, 0x3f, 0x80, 0x08, 0x50, 0x3e, 0x70, 0xb1, 0xa4, 0x3f,
+ 0x80, 0xb2, 0xbe, 0xbf, 0x80, 0xb2, 0x3e, 0x3f, 0xe4, 0xb0, 0x17, 0xc0,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x58, 0xb0, 0x8a, 0xbf, 0x60, 0x5b, 0x93, 0xbf,
+ 0xa0, 0xb4, 0x72, 0x3f, 0x70, 0x5c, 0xad, 0xbf, 0x58, 0x05, 0x82, 0xbf,
+ 0x58, 0x05, 0x82, 0x3f, 0x68, 0x06, 0x9c, 0x3f, 0x80, 0x08, 0x50, 0xbf,
+ 0x80, 0xb0, 0x8a, 0x3d, 0xa0, 0xb4, 0xf2, 0xbf, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0xb4, 0x72, 0x3f, 0x80, 0x08, 0x50, 0xbe, 0x5c, 0xb0, 0x0a, 0x40,
+ 0xf0, 0x06, 0x29, 0xc0, 0x78, 0x07, 0xb6, 0x3f, 0x60, 0xb0, 0x0a, 0x3f,
+ 0x80, 0x5c, 0xad, 0x3e, 0x6c, 0xb1, 0x24, 0xc0, 0x40, 0xb0, 0x0a, 0xbe,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x68, 0x06, 0x9c, 0x3f,
+ 0x80, 0x08, 0x50, 0xbf, 0xf0, 0x06, 0xa9, 0xc0, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe,
+ 0x90, 0x08, 0x50, 0x3f, 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0x08, 0x50, 0xbf, 0x80, 0x5c, 0xad, 0x3e,
+ 0x60, 0x06, 0x1c, 0xbf, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb2, 0x3e, 0x3f, 0x98, 0x09, 0xea, 0xbf, 0x00, 0x00, 0x00, 0x00,
+ 0x70, 0xb1, 0xa4, 0xbf, 0x68, 0x06, 0x9c, 0xbf, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb2, 0x3e, 0x3f, 0x98, 0x5e, 0x61, 0x40, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0x5c, 0xad, 0xbe, 0x60, 0xb0, 0x8a, 0x3f,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x58, 0x05, 0x82, 0x3f, 0xfc, 0x5c, 0x3a, 0x40,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x70, 0x5c, 0x2d, 0x3f, 0x70, 0x5c, 0x2d, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0xbe, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0x5c, 0xad, 0x3e, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x70, 0x06, 0x1c, 0x3f,
+ 0x80, 0x08, 0xd0, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0xd0, 0x3e, 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x70, 0x06, 0x1c, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb2, 0x3e, 0x3f, 0x60, 0x06, 0x1c, 0xbf,
+ 0x80, 0x08, 0xd0, 0x3e, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb2, 0x3e, 0x3f, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0xd0, 0x3e,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x8a, 0x3e, 0x70, 0x06, 0x1c, 0x3f,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb2, 0x3e, 0x3f, 0x80, 0xb2, 0x3e, 0xbf, 0xe8, 0x5b, 0x20, 0xc0,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x84, 0x5d, 0x47, 0xc0, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x60, 0x5b, 0x93, 0xbf, 0x88, 0x5d, 0xc7, 0x3f, 0x90, 0x5e, 0x61, 0x3f,
+ 0x70, 0x06, 0x1c, 0x3f, 0x68, 0x06, 0x9c, 0x3f, 0x80, 0xb2, 0x3e, 0x40,
+ 0x98, 0x5e, 0x61, 0x40, 0x80, 0xb2, 0x3e, 0x3f, 0x80, 0x08, 0x50, 0xbe,
+ 0x90, 0xb3, 0xd8, 0xbf, 0x80, 0xb2, 0xbe, 0x3f, 0xe8, 0x5b, 0x20, 0xc0,
+ 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0x08, 0x50, 0xbf, 0x80, 0x08, 0xd0, 0xbe,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x70, 0x5c, 0x2d, 0x3f, 0xa8, 0x5f, 0xfb, 0xbf, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x68, 0x06, 0x9c, 0xbf, 0x70, 0x5c, 0xad, 0xbf, 0x80, 0x08, 0x50, 0x3e,
+ 0x90, 0x5e, 0x61, 0x3f, 0x9c, 0x09, 0x6a, 0x40, 0x80, 0x08, 0x50, 0xbf,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0xa0, 0xb4, 0xf2, 0xbe, 0x60, 0xb0, 0x8a, 0x3f,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x90, 0x5e, 0x61, 0x3f, 0xf8, 0xb1, 0x31, 0x40,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb2, 0x3e, 0x3f, 0x80, 0x08, 0xd0, 0x3e,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0x08, 0x50, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0xd0, 0x3e, 0x90, 0x5e, 0x61, 0x3f,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0xa0, 0xb4, 0xf2, 0x3e, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x70, 0x5c, 0x2d, 0xbf, 0x60, 0xb0, 0x0a, 0x3f,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x60, 0x06, 0x1c, 0xbf, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x70, 0x06, 0x1c, 0x3f, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0x3e,
+ 0x70, 0x06, 0x1c, 0x3f, 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0x5c, 0xad, 0x3e, 0xa0, 0xb4, 0x72, 0x3f, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0xb2, 0xbe, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0xd0, 0xbe,
+ 0xe4, 0xb0, 0x17, 0x40, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e,
+ 0x98, 0x5e, 0xe1, 0xbf, 0x80, 0x5d, 0xc7, 0xbf, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x90, 0x08, 0x50, 0x3f, 0x60, 0xb0, 0x8a, 0x3f, 0x90, 0x5e, 0x61, 0x3f,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x84, 0x5d, 0x47, 0x40, 0x40, 0xb0, 0x0a, 0xbe, 0x0c, 0x5e, 0x54, 0x40,
+ 0x74, 0x5c, 0x2d, 0x40, 0x60, 0x06, 0x1c, 0xbf, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0x5c, 0xad, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x70, 0x5c, 0x2d, 0x3f, 0xa8, 0x5f, 0xfb, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0x5b, 0x93, 0xbf, 0x68, 0x06, 0x9c, 0xbf,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x70, 0x5c, 0x2d, 0x3f, 0x9c, 0x09, 0x6a, 0x40,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0x08, 0x50, 0x3e, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x68, 0x06, 0x9c, 0x3f, 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0xb0, 0x8a, 0x3f,
+ 0xf8, 0xb1, 0x31, 0x40, 0x40, 0xb0, 0x0a, 0xbe, 0x90, 0x08, 0x50, 0x3f,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0x08, 0x50, 0xbf, 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x40, 0xb0, 0x0a, 0xbe, 0xa0, 0xb4, 0xf2, 0xbe, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0xd0, 0x3e, 0x90, 0x08, 0x50, 0x3f,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e,
+ 0x90, 0x5e, 0x61, 0x3f, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x5c, 0xad, 0x3e, 0x90, 0x5e, 0x61, 0xbf,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0x06, 0x1c, 0xbf, 0x60, 0x06, 0x1c, 0xbf, 0x80, 0x08, 0xd0, 0x3e,
+ 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb2, 0x3e, 0x3f, 0x80, 0x5c, 0xad, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x8a, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0x5b, 0x93, 0xbf, 0x60, 0x5b, 0x93, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x70, 0x5c, 0x2d, 0x3f, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0xb0, 0x0a, 0x3f, 0xe8, 0x5b, 0x20, 0xc0, 0xa0, 0xb4, 0xf2, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0x72, 0x3f, 0x64, 0x5b, 0x13, 0x40,
+ 0x60, 0x06, 0x1c, 0xbf, 0x60, 0xb0, 0x8a, 0xbe, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x90, 0x5e, 0x61, 0xbf, 0xa0, 0xb4, 0xf2, 0x3e, 0x70, 0x06, 0x1c, 0x3f,
+ 0x80, 0xb2, 0xbe, 0x3f, 0x80, 0xb2, 0xbe, 0x3f, 0x60, 0x5b, 0x93, 0x3f,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x70, 0x06, 0x1c, 0x3f,
+ 0xa8, 0x5f, 0xfb, 0xbf, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0x5b, 0x93, 0xbf,
+ 0x70, 0xb1, 0xa4, 0xbf, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x98, 0x5e, 0x61, 0x40, 0x80, 0xb2, 0x3e, 0xbf, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x68, 0x06, 0x9c, 0x3f, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x90, 0x08, 0x50, 0x3f, 0xfc, 0x5c, 0x3a, 0x40, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb2, 0x3e, 0x3f, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x5c, 0xad, 0x3e, 0xa0, 0xb4, 0xf2, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0x08, 0x50, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb2, 0x3e, 0x3f, 0x80, 0x08, 0x50, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x90, 0x08, 0x50, 0x3f, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0x08, 0xd0, 0xbe, 0x80, 0x08, 0xd0, 0x3e, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x0a, 0xbf, 0x90, 0x5e, 0x61, 0xbf,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d, 0x70, 0x5c, 0x2d, 0x3f,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb2, 0x3e, 0x3f, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0x08, 0x50, 0xbe, 0x60, 0xb0, 0x8a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x90, 0xb3, 0xd8, 0x3f, 0x68, 0x06, 0x9c, 0x3f, 0x58, 0xb0, 0x8a, 0xbf,
+ 0x62, 0x5b, 0x93, 0xc0, 0x60, 0x5c, 0xad, 0xbe, 0x70, 0x5c, 0xad, 0x3f,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x70, 0xb1, 0xa4, 0x3f, 0x60, 0x5c, 0xad, 0xbe, 0x29, 0x31, 0x9e, 0xc0,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x5b, 0x13, 0xc0, 0x90, 0x08, 0x50, 0x3f,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x70, 0x5c, 0x2d, 0x3f, 0xa8, 0x5f, 0xfb, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x68, 0x06, 0x9c, 0xbf, 0x68, 0x06, 0x9c, 0xbf, 0x80, 0x08, 0x50, 0x3e,
+ 0x90, 0x5e, 0x61, 0x3f, 0x98, 0x5e, 0x61, 0x40, 0x80, 0x08, 0x50, 0xbf,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0xa0, 0xb4, 0xf2, 0xbe, 0x60, 0x5b, 0x93, 0x3f,
+ 0x80, 0x08, 0xd0, 0xbe, 0xa0, 0xb4, 0x72, 0x3f, 0xfc, 0x5c, 0x3a, 0x40,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x90, 0x08, 0x50, 0x3f, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0x08, 0xd0, 0xbe, 0x60, 0xb0, 0x0a, 0x3f, 0x90, 0x5e, 0x61, 0xbf,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0xb2, 0x3e, 0xbf, 0x80, 0x08, 0x50, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0xa0, 0xb4, 0xf2, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb2, 0x3e, 0x3f, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0xbe, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0x08, 0xd0, 0x3e, 0x90, 0x5e, 0x61, 0xbf, 0x80, 0x08, 0x50, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0x72, 0xbf,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0x5c, 0xad, 0x3e, 0x60, 0xb0, 0x8a, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x80, 0x08, 0x50, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb2, 0x3e, 0x3f, 0x80, 0x08, 0x50, 0xbe,
+ 0x58, 0xb0, 0x8a, 0xbf, 0xa0, 0xb4, 0x72, 0xbf, 0x60, 0xb0, 0x8a, 0xbe,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x74, 0x5c, 0x2d, 0x40, 0x90, 0xb3, 0xd8, 0x3f,
+ 0x60, 0x5b, 0x13, 0xc0, 0x6c, 0xb1, 0x24, 0xc0, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x88, 0x5d, 0xc7, 0x3f, 0x58, 0xb0, 0x8a, 0xbf,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x98, 0x5e, 0xe1, 0x3f, 0x80, 0xb0, 0x8a, 0x3d,
+ 0xdf, 0x05, 0x0f, 0xc1, 0x60, 0xb0, 0x8a, 0x3e, 0xa6, 0x5f, 0x7b, 0xc0,
+ 0x90, 0x08, 0x50, 0x3f, 0x90, 0xb3, 0xd8, 0x3f, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0x3e, 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x70, 0x5c, 0x2d, 0x3f, 0xa8, 0x5f, 0xfb, 0xbf,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x70, 0xb1, 0xa4, 0xbf, 0x70, 0x5c, 0xad, 0xbf,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x90, 0x5e, 0x61, 0x3f, 0x98, 0x5e, 0x61, 0x40,
+ 0x90, 0x5e, 0x61, 0xbf, 0xa0, 0xb4, 0xf2, 0xbe, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0xd0, 0xbe,
+ 0x70, 0xb1, 0xa4, 0x3f, 0x80, 0x08, 0xd0, 0xbe, 0x58, 0x05, 0x82, 0x3f,
+ 0x74, 0x5c, 0x2d, 0x40, 0x40, 0xb0, 0x0a, 0xbe, 0x90, 0x5e, 0x61, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb2, 0xbe, 0xbf, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x90, 0x5e, 0x61, 0xbf, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0xa0, 0xb4, 0x72, 0x3f, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e, 0x70, 0xb1, 0xa4, 0xbf,
+ 0x80, 0xb0, 0x8a, 0x3d, 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0x08, 0xd0, 0x3e,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0x06, 0x1c, 0xbf, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x90, 0x08, 0x50, 0x3f, 0x80, 0xb0, 0x0a, 0x3e, 0xa0, 0xb4, 0x72, 0x3f,
+ 0x80, 0x08, 0xd0, 0xbe, 0xec, 0x5b, 0x20, 0x40, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x58, 0x05, 0x02, 0x40, 0x60, 0x06, 0x1c, 0xbf, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x5c, 0xb0, 0x0a, 0x40, 0xa0, 0xb4, 0xf2, 0x3f,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x40, 0xb0, 0x0a, 0xbe, 0x74, 0x5c, 0x2d, 0x40,
+ 0x80, 0xb2, 0xbe, 0xbf, 0x40, 0xdd, 0xc0, 0xc0, 0x80, 0x08, 0x50, 0x3e,
+ 0xfc, 0x5c, 0x3a, 0xc0, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x0a, 0x3f,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x5c, 0x2d, 0x3f,
+ 0x90, 0xb3, 0xd8, 0xbf, 0x80, 0x08, 0x50, 0x3e, 0x70, 0x5c, 0xad, 0xbf,
+ 0x60, 0x5b, 0x93, 0xbf, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x84, 0x5d, 0x47, 0x40, 0x80, 0x5c, 0xad, 0x3e, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0x5b, 0x93, 0x3f, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x68, 0x06, 0x9c, 0x3f, 0xe4, 0xb0, 0x17, 0x40, 0x80, 0x08, 0x50, 0x3e,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x05, 0x82, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0xa0, 0xb4, 0x72, 0xbf,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0x06, 0x1c, 0xbf,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0xd0, 0x3e, 0x90, 0x5e, 0x61, 0x3f,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x0a, 0xbf, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0x08, 0xd0, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0x5c, 0xad, 0x3e, 0xa0, 0xb4, 0x72, 0x3f, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0x08, 0x50, 0xbe, 0x70, 0x5c, 0xad, 0x3f, 0xd8, 0x5a, 0x06, 0x40,
+ 0x60, 0x5b, 0x93, 0x3f, 0x90, 0xb3, 0x58, 0x40, 0x80, 0xb2, 0x3e, 0xbf,
+ 0xa0, 0xb4, 0x72, 0xbf, 0x60, 0x5c, 0xad, 0xbe, 0x90, 0xb3, 0xd8, 0x3f,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x70, 0x06, 0x1c, 0x3f, 0x60, 0x5c, 0xad, 0xbe,
+ 0xd8, 0x5a, 0x06, 0x40, 0x60, 0xb0, 0x0a, 0x3f, 0xa1, 0xb4, 0xf2, 0xc0,
+ 0x70, 0x06, 0x1c, 0x3f, 0x68, 0x06, 0x1c, 0xc0, 0x68, 0x06, 0x1c, 0xc0,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x70, 0x5c, 0xad, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x58, 0x05, 0x82, 0xbf, 0x90, 0x5e, 0x61, 0xbf, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x70, 0x5c, 0x2d, 0x3f, 0xf0, 0x06, 0x29, 0x40, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x60, 0x06, 0x1c, 0xbf, 0x80, 0xb0, 0x0a, 0x3e, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x8a, 0x3f, 0x68, 0x06, 0x1c, 0x40,
+ 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0xd0, 0xbe, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x8a, 0x3e, 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x0a, 0x3f,
+ 0x60, 0x5c, 0xad, 0xbe, 0x60, 0xb0, 0x8a, 0x3e, 0x70, 0xb1, 0xa4, 0xbf,
+ 0xa0, 0xb4, 0xf2, 0x3f, 0x68, 0x06, 0x1c, 0x40, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0xd0, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x78, 0x07, 0xb6, 0x3f, 0x60, 0x5b, 0x93, 0xbf, 0x70, 0x5c, 0x2d, 0x3f,
+ 0x80, 0x08, 0xd0, 0xbe, 0x60, 0x5b, 0x93, 0x3f, 0x60, 0xb0, 0x0a, 0x3f,
+ 0x5c, 0x34, 0xec, 0xc0, 0x80, 0x08, 0xd0, 0xbe, 0xe0, 0x05, 0x0f, 0xc0,
+ 0x56, 0x05, 0x82, 0xc0, 0x58, 0x05, 0x82, 0x3f, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0x5c, 0xad, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbf, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe, 0x68, 0x06, 0x9c, 0xbf,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x70, 0xb1, 0xa4, 0xbf, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0x08, 0xd0, 0x3e, 0x80, 0x08, 0xd0, 0x3e, 0xe0, 0x05, 0x0f, 0x40,
+ 0x40, 0xb0, 0x0a, 0xbe, 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0x08, 0x50, 0x3e,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x70, 0x06, 0x1c, 0x3f,
+ 0x70, 0x06, 0x1c, 0x3f, 0x80, 0x08, 0xd0, 0xbe, 0x58, 0x05, 0x82, 0x3f,
+ 0x64, 0x5b, 0x13, 0x40, 0xa0, 0xb4, 0xf2, 0x3e, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x80, 0x08, 0x50, 0xbe, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x8a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0xd0, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0xd0, 0x3e, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0xd0, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0x3e, 0x54, 0x05, 0x02, 0xc0, 0x60, 0x5b, 0x93, 0xbf,
+ 0x80, 0x08, 0x50, 0xbe, 0x90, 0xb3, 0xd8, 0x3f, 0x20, 0x5f, 0x6e, 0x40,
+ 0x88, 0x5d, 0xc7, 0x3f, 0x78, 0x07, 0xb6, 0xbf, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x70, 0x5c, 0x2d, 0x3f, 0x90, 0xb3, 0xd8, 0xbf,
+ 0x60, 0x5c, 0xad, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0xa0, 0xb4, 0x72, 0x3f,
+ 0xa0, 0xb4, 0x72, 0x3f, 0xc3, 0x32, 0xc5, 0xc0, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0xb2, 0xbe, 0xbf, 0x6c, 0xb1, 0x24, 0xc0, 0x60, 0x5b, 0x93, 0x3f,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x90, 0x5e, 0x61, 0xbf,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x70, 0xb1, 0xa4, 0xbf, 0x40, 0xb0, 0x0a, 0xbe, 0x70, 0xb1, 0xa4, 0xbf,
+ 0x60, 0x5c, 0xad, 0xbe, 0x60, 0xb0, 0x8a, 0x3e, 0x70, 0x5c, 0x2d, 0x3f,
+ 0x88, 0x5d, 0xc7, 0x3f, 0x60, 0x5c, 0xad, 0xbe, 0xa0, 0xb4, 0x72, 0xbf,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0x3e, 0x70, 0x5c, 0x2d, 0x3f, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0x08, 0x50, 0x3e, 0xd8, 0x5a, 0x06, 0x40, 0x60, 0xb0, 0x0a, 0x3f,
+ 0x80, 0x08, 0x50, 0xbf, 0x60, 0xb0, 0x8a, 0xbe, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0xd0, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x0a, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0x5b, 0x93, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x58, 0x05, 0x82, 0xbf,
+ 0x90, 0x08, 0x50, 0x3f, 0x60, 0x5b, 0x93, 0x3f, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x58, 0x05, 0x82, 0x3f, 0x58, 0xb0, 0x8a, 0xbf, 0x60, 0x06, 0x1c, 0xbf,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x58, 0xb0, 0x8a, 0xbf, 0x60, 0x5c, 0xad, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x70, 0xb1, 0xa4, 0xbf, 0x80, 0x5c, 0xad, 0x3e, 0xac, 0x86, 0xa2, 0xc0,
+ 0x90, 0x5e, 0x61, 0xbf, 0xa0, 0xb4, 0xf2, 0xbe, 0x23, 0x86, 0x95, 0xc0,
+ 0x60, 0xb0, 0x8a, 0x3f, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0x5b, 0x93, 0xbf, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x70, 0xb1, 0xa4, 0xbf, 0x80, 0x08, 0xd0, 0x3e,
+ 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0xd0, 0x3e,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x70, 0x5c, 0xad, 0x3f, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0x50, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0x08, 0xd0, 0x3e, 0x98, 0x5e, 0xe1, 0x3f,
+ 0x70, 0x06, 0x1c, 0x3f, 0x80, 0xb2, 0x3e, 0xbf, 0x60, 0x5c, 0xad, 0xbe,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0x08, 0x50, 0xbe, 0x70, 0xb1, 0xa4, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x0a, 0x3f,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x8a, 0xbe, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x70, 0xb1, 0xa4, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x70, 0x5c, 0x2d, 0x3f, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb2, 0x3e, 0xbf, 0xa0, 0xb4, 0xf2, 0x3f, 0x80, 0xb2, 0xbe, 0x3f,
+ 0x90, 0x08, 0x50, 0x3f, 0x80, 0x08, 0xd0, 0x3e, 0x88, 0x08, 0xd0, 0xbf,
+ 0xa0, 0xb4, 0x72, 0xbf, 0x5c, 0xb0, 0x0a, 0x40, 0x68, 0x06, 0x9c, 0x3f,
+ 0x80, 0xb2, 0x3e, 0x3f, 0x80, 0xb2, 0xbe, 0xbf, 0xa0, 0xb4, 0x72, 0x3f,
+ 0x80, 0x08, 0x50, 0xbe, 0xf0, 0x06, 0x29, 0xc0, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x5c, 0xb0, 0x0a, 0xc0, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x8a, 0x08, 0x50, 0xc0, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x8a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0x5c, 0xad, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x58, 0xb0, 0x8a, 0xbf, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb2, 0xbe, 0xbf,
+ 0x80, 0x08, 0x50, 0x3e, 0x58, 0x05, 0x82, 0xbf, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x70, 0x5c, 0x2d, 0x3f, 0x70, 0xb1, 0xa4, 0x3f,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x90, 0x5e, 0x61, 0xbf, 0x80, 0x08, 0xd0, 0x3e,
+ 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0xb4, 0x72, 0x3f, 0x80, 0xb0, 0x0a, 0x3e, 0x70, 0x06, 0x1c, 0x3f,
+ 0x88, 0x08, 0xd0, 0x3f, 0x80, 0xb2, 0x3e, 0x3f, 0x58, 0x05, 0x82, 0xbf,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0x08, 0xd0, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x88, 0x08, 0xd0, 0xbf, 0xa0, 0xb4, 0xf2, 0xbe, 0x90, 0x5e, 0x61, 0xbf,
+ 0x80, 0xb0, 0x0a, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0xa0, 0xb4, 0xf2, 0x3e, 0x70, 0xb1, 0xa4, 0xbf,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0x5c, 0xad, 0x3e, 0x60, 0x5c, 0xad, 0xbe,
+ 0x60, 0x06, 0x1c, 0xbf, 0x80, 0xb0, 0x0a, 0x3e, 0x88, 0x08, 0xd0, 0xbf,
+ 0x80, 0x08, 0xd0, 0xbe, 0x58, 0x05, 0x82, 0xbf, 0x00, 0x00, 0x00, 0x00,
+ 0x70, 0x06, 0x1c, 0x3f, 0x60, 0x06, 0x1c, 0xbf, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0x5c, 0xad, 0x3e, 0x78, 0x07, 0xb6, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0xa0, 0xb4, 0xf2, 0x3e, 0x70, 0x06, 0x1c, 0x3f,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x90, 0x5e, 0x61, 0x3f, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0x5c, 0xad, 0x3e, 0x78, 0x07, 0xb6, 0xbf, 0xe0, 0x05, 0x0f, 0xc0,
+ 0x80, 0xb2, 0x3e, 0x3f, 0x90, 0x08, 0x50, 0x3f, 0x80, 0x08, 0xd0, 0xbe,
+ 0x60, 0xb0, 0x0a, 0x3f, 0xa0, 0xb4, 0xf2, 0xbe, 0x78, 0x07, 0x36, 0x40,
+ 0x80, 0x5c, 0xad, 0x3e, 0xec, 0x5b, 0x20, 0x40, 0x60, 0x5c, 0xad, 0xbe,
+ 0x78, 0x07, 0xb6, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x8a, 0x08, 0x50, 0xc0,
+ 0x60, 0xb0, 0x8a, 0x3e, 0xa0, 0xb4, 0x72, 0xbf, 0x60, 0xb0, 0x0a, 0xbf,
+ 0xe0, 0x05, 0x0f, 0xc0, 0x70, 0xb1, 0xa4, 0xbf, 0x78, 0x07, 0xb6, 0x3f,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0xb0, 0x8a, 0x3e, 0x78, 0x07, 0xb6, 0xbf,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x90, 0x5e, 0x61, 0xbf,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0xbe,
+ 0x90, 0x5e, 0x61, 0xbf, 0xa0, 0xb4, 0xf2, 0xbe, 0x70, 0xb1, 0xa4, 0xbf,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0xbf, 0x90, 0x08, 0x50, 0x3f, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb2, 0x3e, 0xbf, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x90, 0x5e, 0x61, 0x3f, 0x70, 0x5c, 0x2d, 0xbf, 0xa0, 0xb4, 0x72, 0xbf,
+ 0x90, 0x5e, 0x61, 0x3f, 0x90, 0x5e, 0x61, 0xbf, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0x08, 0xd0, 0xbe, 0x90, 0x08, 0x50, 0x3f, 0x80, 0xb0, 0x0a, 0x3e,
+ 0xa0, 0xb4, 0x72, 0x3f, 0x58, 0x05, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0x50, 0xbf, 0xa0, 0xb4, 0xf2, 0x3e, 0x98, 0x5e, 0xe1, 0xbf,
+ 0x80, 0x08, 0x50, 0x3e, 0x70, 0x5c, 0xad, 0xbf, 0x80, 0x08, 0x50, 0xbf,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x70, 0x5c, 0x2d, 0x3f, 0x78, 0x07, 0x36, 0x40,
+ 0x60, 0x06, 0x1c, 0xbf, 0x80, 0xb2, 0x3e, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x58, 0x05, 0x82, 0x3f, 0x60, 0xb0, 0x8a, 0xbe, 0xa0, 0xb4, 0x72, 0x3f,
+ 0xfc, 0x5c, 0x3a, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0xa0, 0xb4, 0x72, 0x3f, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0x5c, 0xad, 0x3e,
+ 0x70, 0x06, 0x1c, 0x3f, 0x60, 0xb0, 0x0a, 0xbf, 0x78, 0x07, 0xb6, 0x3f,
+ 0x90, 0x08, 0x50, 0x3f, 0x80, 0x08, 0xd0, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x70, 0xb1, 0xa4, 0x3f, 0x90, 0x5e, 0x61, 0xbf, 0xa0, 0xb4, 0x72, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x90, 0x5e, 0x61, 0x3f, 0x90, 0x5e, 0x61, 0x3f,
+ 0xa1, 0xb4, 0xf2, 0xc0, 0x40, 0xb0, 0x0a, 0xbe, 0x5c, 0xb0, 0x0a, 0xc0,
+ 0x5c, 0xb0, 0x0a, 0xc0, 0x90, 0x5e, 0x61, 0xbf, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb2, 0xbe, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x74, 0x5c, 0x2d, 0x40, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x68, 0x06, 0x9c, 0x3f, 0x70, 0x06, 0x1c, 0x3f,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x90, 0x5e, 0x61, 0xbf, 0x78, 0x07, 0xb6, 0x3f,
+ 0x80, 0x08, 0x50, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0x5c, 0xad, 0x3e,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0x08, 0xd0, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0x5b, 0x93, 0x3f,
+ 0x90, 0x5e, 0x61, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0xbe, 0x70, 0x5c, 0xad, 0xbf, 0x60, 0x5c, 0xad, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0x06, 0x1c, 0xbf,
+ 0x80, 0x08, 0x50, 0xbe, 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0x50, 0x3e, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0x5c, 0xad, 0xbe,
+ 0x70, 0x5c, 0xad, 0xbf, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0x5c, 0xad, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0x08, 0x50, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x60, 0x5c, 0xad, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe,
+ 0xa8, 0x5f, 0xfb, 0xbf, 0x58, 0x05, 0x82, 0xbf, 0x98, 0x09, 0xea, 0xbf,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x60, 0xb0, 0x8a, 0x3f, 0xa0, 0xb4, 0xf2, 0xbf,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x8a, 0x08, 0x50, 0xc0, 0xfc, 0x5c, 0x3a, 0x40,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb2, 0x3e, 0x40, 0x58, 0x05, 0x82, 0x3f,
+ 0x80, 0x08, 0x50, 0xbf, 0x80, 0x08, 0x50, 0xbf, 0xa0, 0xb4, 0x72, 0xbf,
+ 0x68, 0x06, 0x1c, 0x40, 0xe4, 0xb0, 0x97, 0xc0, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0x50, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x06, 0x1c, 0xbf,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0xf8, 0xb1, 0x31, 0x40, 0x80, 0x08, 0xd0, 0x3e, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0xb0, 0x8a, 0x3f, 0x60, 0xb0, 0x0a, 0x3f,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x80, 0x08, 0x50, 0xbf, 0x78, 0x07, 0xb6, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0x5c, 0xad, 0x3e,
+ 0x90, 0x08, 0x50, 0x3f, 0xa0, 0xb4, 0xf2, 0xbe, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x80, 0x08, 0x50, 0xbe, 0x60, 0x5c, 0xad, 0xbe, 0x58, 0x05, 0x82, 0xbf,
+ 0x60, 0x06, 0x1c, 0xbf, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x60, 0x5c, 0xad, 0xbe,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0xd0, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x58, 0xb0, 0x8a, 0xbf, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x5b, 0x13, 0xc0, 0x70, 0x5c, 0xad, 0xbf,
+ 0x88, 0x08, 0xd0, 0x3f, 0x60, 0xb0, 0x8a, 0x3f, 0xa0, 0x09, 0xea, 0x3f,
+ 0xd0, 0x88, 0xd6, 0x40, 0x70, 0x06, 0x1c, 0x3f, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x58, 0x05, 0x82, 0xbf, 0x40, 0xb0, 0x0a, 0xbe, 0x98, 0x5e, 0xe1, 0xbf,
+ 0x80, 0x5c, 0xad, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x58, 0x05, 0x82, 0x3f,
+ 0x90, 0x5e, 0x61, 0x3f, 0x6c, 0xb1, 0x24, 0x40, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x88, 0x08, 0xd0, 0xbf, 0x88, 0x5d, 0xc7, 0x3f, 0x78, 0x07, 0x36, 0xc0,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0x50, 0xbe, 0xf8, 0xb1, 0x31, 0x40, 0x80, 0x08, 0xd0, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0x5b, 0x93, 0x3f,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0x08, 0x50, 0xbf, 0xa0, 0xb4, 0x72, 0xbf,
+ 0x78, 0x07, 0xb6, 0x3f, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0x5c, 0xad, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x70, 0x5c, 0x2d, 0x3f, 0x80, 0x08, 0xd0, 0xbe,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb2, 0x3e, 0xbf, 0xa0, 0xb4, 0xf2, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x60, 0x06, 0x1c, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0xbe, 0x70, 0x06, 0x1c, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x06, 0x1c, 0xbf,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0x5c, 0xad, 0xbe, 0xa0, 0xb4, 0xf2, 0x3e, 0x68, 0x06, 0x1c, 0xc0,
+ 0x90, 0x5e, 0x61, 0xbf, 0x70, 0x5c, 0x2d, 0xbf, 0x70, 0x5c, 0x2d, 0x3f,
+ 0xa8, 0x5f, 0xfb, 0x3f, 0x9a, 0x85, 0x88, 0x40, 0xd8, 0x5a, 0x06, 0xc0,
+ 0x90, 0xb3, 0xd8, 0x3f, 0x70, 0x5c, 0xad, 0x3f, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x60, 0x5b, 0x93, 0x3f, 0x80, 0x5c, 0xad, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0x08, 0x50, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e, 0x90, 0x5e, 0x61, 0x3f,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x88, 0x08, 0xd0, 0xbf, 0x80, 0x08, 0x50, 0xbe,
+ 0x88, 0x08, 0xd0, 0x3f, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0x5c, 0xad, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x78, 0x07, 0x36, 0x40,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0x06, 0x1c, 0xbf,
+ 0x60, 0xb0, 0x8a, 0x3f, 0x70, 0x06, 0x1c, 0x3f, 0x60, 0x06, 0x1c, 0xbf,
+ 0x80, 0x08, 0x50, 0xbf, 0x70, 0xb1, 0xa4, 0x3f, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0x5c, 0xad, 0x3e, 0x70, 0x5c, 0x2d, 0x3f,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x60, 0x06, 0x1c, 0xbf, 0x80, 0x08, 0x50, 0xbe,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x58, 0x05, 0x82, 0xbf, 0x60, 0x06, 0x1c, 0xbf,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0x06, 0x1c, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0x08, 0x50, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0xd0, 0xbe,
+ 0x60, 0x5b, 0x93, 0xbf, 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0x08, 0x50, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x5c, 0xad, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x70, 0x5c, 0x2d, 0x3f,
+ 0x90, 0x5e, 0x61, 0xbf, 0x70, 0x5c, 0xad, 0x3f, 0x60, 0x06, 0x1c, 0xbf,
+ 0x58, 0x05, 0x82, 0x3f, 0xa8, 0x5f, 0xfb, 0x3f, 0xa0, 0x09, 0xea, 0x3f,
+ 0x60, 0x5c, 0xad, 0xbe, 0x90, 0x08, 0x50, 0x3f, 0x58, 0x05, 0x82, 0x3f,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0x08, 0xd0, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x88, 0x08, 0xd0, 0x3f, 0x80, 0x08, 0x50, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb2, 0x3e, 0xbf, 0x88, 0x08, 0xd0, 0xbf,
+ 0x60, 0x06, 0x1c, 0xbf, 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x06, 0x1c, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe,
+ 0x78, 0x07, 0x36, 0x40, 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x60, 0x06, 0x1c, 0xbf, 0x68, 0x06, 0x9c, 0x3f, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x80, 0x08, 0x50, 0xbf, 0x90, 0x5e, 0x61, 0xbf, 0x78, 0x07, 0xb6, 0x3f,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb2, 0x3e, 0x3f, 0x60, 0x06, 0x1c, 0xbf, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0xd0, 0xbe, 0x60, 0x5b, 0x93, 0xbf,
+ 0x60, 0x06, 0x1c, 0xbf, 0x80, 0xb0, 0x0a, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0x5c, 0xad, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0xd0, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb2, 0x3e, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x70, 0xb1, 0xa4, 0xbf, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0xd0, 0xbe, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x70, 0x5c, 0xad, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0xb2, 0xbe, 0x3f, 0xa0, 0x09, 0xea, 0x3f,
+ 0x78, 0x07, 0xb6, 0xbf, 0x70, 0x5c, 0xad, 0xbf, 0x58, 0x05, 0x82, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0xf2, 0xbe, 0x78, 0x07, 0xb6, 0x3f,
+ 0x90, 0x5e, 0x61, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x78, 0x07, 0x36, 0x40,
+ 0x58, 0x05, 0x82, 0x3f, 0x80, 0xb2, 0x3e, 0x3f, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x80, 0x5d, 0xc7, 0xbf, 0x90, 0x08, 0x50, 0x3f, 0x70, 0x5c, 0xad, 0x3f,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x74, 0x5c, 0x2d, 0x40, 0x80, 0x08, 0xd0, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0x5c, 0xad, 0xbe, 0x68, 0x06, 0x9c, 0x3f,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x70, 0x5c, 0x2d, 0xbf, 0x90, 0x5e, 0x61, 0xbf,
+ 0x80, 0xb2, 0xbe, 0x3f, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0x5c, 0xad, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x90, 0x5e, 0x61, 0x3f, 0x60, 0x06, 0x1c, 0xbf,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3e, 0xa0, 0xb4, 0xf2, 0xbe, 0x60, 0xb0, 0x8a, 0xbe,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x60, 0x5c, 0xad, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x80, 0x08, 0xd0, 0xbe, 0x60, 0x5c, 0xad, 0xbe, 0x70, 0x06, 0x1c, 0x3f,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x5c, 0xad, 0x3e, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x8a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x78, 0x07, 0xb6, 0xbf, 0xa0, 0xb4, 0x72, 0x3f,
+ 0x80, 0xb0, 0x0a, 0x3e, 0xc8, 0xdd, 0xcd, 0xc0, 0x00, 0x00, 0x00, 0x00,
+ 0x58, 0x05, 0x82, 0x3f, 0x90, 0x5e, 0x61, 0x3f, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x70, 0xb1, 0xa4, 0xbf, 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x78, 0x07, 0xb6, 0x3f, 0x90, 0x08, 0x50, 0x3f, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0xb0, 0x8a, 0x3d, 0x88, 0x08, 0xd0, 0x3f,
+ 0x70, 0x5c, 0xad, 0x3f, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0xd0, 0x3e, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x5c, 0xad, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x5b, 0x20, 0x40,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3f, 0x70, 0x06, 0x1c, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x60, 0xb0, 0x8a, 0x3f, 0x90, 0x5e, 0x61, 0x3f,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x60, 0xb0, 0x0a, 0x3f, 0x70, 0x06, 0x1c, 0x3f,
+ 0x60, 0x06, 0x1c, 0xbf, 0x70, 0x5c, 0x2d, 0xbf, 0x60, 0x5c, 0xad, 0xbe,
+ 0x60, 0x5c, 0xad, 0xbe, 0x60, 0x5b, 0x93, 0xbf, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb2, 0x3e, 0x3f, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x70, 0x5c, 0x2d, 0x3f, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0x08, 0xd0, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0x08, 0xd0, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0x5c, 0xad, 0xbe, 0x60, 0x5c, 0xad, 0xbe,
+ 0x68, 0x06, 0x9c, 0xbf, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x80, 0xb0, 0x8a, 0x3d, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x60, 0x5b, 0x93, 0xbf, 0xa0, 0xb4, 0xf2, 0xbe, 0xe4, 0xb0, 0x17, 0xc0,
+ 0x80, 0xb2, 0xbe, 0x3f, 0xa0, 0xb4, 0xf2, 0x3f, 0x54, 0x05, 0x02, 0xc0,
+ 0x60, 0x06, 0x1c, 0xbf, 0x9a, 0x09, 0x6a, 0xc0, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x60, 0x5c, 0xad, 0xbe, 0x90, 0x5e, 0x61, 0xbf, 0x68, 0x06, 0x9c, 0xbf,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x8a, 0x3f, 0x90, 0x5e, 0x61, 0xbf,
+ 0xd8, 0x5a, 0x06, 0x40, 0x80, 0xb0, 0x0a, 0x3e, 0x88, 0x08, 0xd0, 0x3f,
+ 0x70, 0xb1, 0xa4, 0x3f, 0xa0, 0xb4, 0xf2, 0x3f, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0x5c, 0xb0, 0x0a, 0x40, 0x80, 0xb2, 0x3e, 0xbf, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x90, 0x08, 0x50, 0x3f, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0x5c, 0xad, 0xbe, 0x70, 0xb1, 0xa4, 0x3f,
+ 0x70, 0xb1, 0xa4, 0x3f, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x60, 0x06, 0x1c, 0xbf, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0xd0, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3f, 0x80, 0x08, 0xd0, 0xbe, 0x60, 0x06, 0x1c, 0xbf,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0xa0, 0xb4, 0x72, 0xbf,
+ 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x58, 0xb0, 0x8a, 0xbf, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0x08, 0x50, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb2, 0x3e, 0x3f, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0xd0, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x5c, 0xad, 0x3e, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x70, 0xb1, 0xa4, 0xbf, 0x80, 0x08, 0x50, 0x3e, 0x70, 0x06, 0x1c, 0x3f,
+ 0xa0, 0x30, 0x11, 0xc1, 0x60, 0xb0, 0x8a, 0x3e, 0x1e, 0x5f, 0x6e, 0xc0,
+ 0x80, 0x08, 0x50, 0xbf, 0x60, 0x5c, 0xad, 0xbe, 0xa8, 0x5f, 0xfb, 0xbf,
+ 0x80, 0x08, 0xd0, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0xe8, 0x5b, 0x20, 0xc0,
+ 0x80, 0xb0, 0x0a, 0x3e, 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0x08, 0xd0, 0xbe,
+ 0xec, 0x5b, 0x20, 0x40, 0x80, 0xb0, 0x0a, 0x3e, 0x70, 0x5c, 0x2d, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0xe4, 0xb0, 0x17, 0x40, 0x70, 0x5c, 0xad, 0xbf,
+ 0x70, 0x06, 0x1c, 0x3f, 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x0a, 0x3f,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0x70, 0xb1, 0xa4, 0x3f, 0x90, 0x08, 0x50, 0x3f, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x88, 0x5d, 0xc7, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0x50, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x58, 0xb0, 0x8a, 0xbf, 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x60, 0x5b, 0x93, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0xa0, 0xb4, 0xf2, 0x3e, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x70, 0x5c, 0x2d, 0xbf, 0x58, 0xb0, 0x8a, 0xbf,
+ 0x80, 0x08, 0xd0, 0xbe, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x8a, 0x3f,
+ 0x80, 0xb0, 0x8a, 0x3d, 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0x08, 0xd0, 0x3e, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x60, 0x5b, 0x13, 0xc0, 0x70, 0x06, 0x1c, 0x3f,
+ 0x90, 0x08, 0x50, 0x3f, 0xf6, 0xef, 0x00, 0xc1, 0x70, 0xb1, 0xa4, 0xbf,
+ 0x94, 0x5e, 0x61, 0xc0, 0x80, 0x08, 0xd0, 0x3e, 0x80, 0x08, 0x50, 0xbe,
+ 0x72, 0x5c, 0x2d, 0xc0, 0x60, 0x06, 0x1c, 0xbf, 0x80, 0x08, 0x50, 0xbe,
+ 0x72, 0x5c, 0x2d, 0xc0, 0x60, 0x5c, 0xad, 0xbe, 0x68, 0x06, 0x9c, 0x3f,
+ 0x80, 0x08, 0xd0, 0xbe, 0x88, 0x5d, 0xc7, 0x3f, 0x68, 0x06, 0x1c, 0x40,
+ 0x78, 0x07, 0xb6, 0x3f, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x5c, 0xad, 0xbe, 0x68, 0x06, 0x1c, 0x40,
+ 0x90, 0xb3, 0xd8, 0xbf, 0x70, 0x06, 0x1c, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb2, 0xbe, 0x3f, 0xa0, 0xb4, 0x72, 0x3f,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x8a, 0xbe,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0x5c, 0xad, 0x3e, 0x70, 0x5c, 0xad, 0x3f,
+ 0x60, 0x5c, 0xad, 0xbe, 0x90, 0x5e, 0x61, 0xbf, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x70, 0x5c, 0x2d, 0xbf, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x5c, 0xad, 0x3e, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x58, 0x05, 0x82, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0x60, 0x5c, 0xad, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0xd0, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x0a, 0x3f,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x58, 0x05, 0x82, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0x5c, 0xad, 0x3e,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0x5c, 0xad, 0xbe, 0x78, 0x07, 0xb6, 0xbf,
+ 0x80, 0x5c, 0xad, 0x3e, 0xe0, 0x05, 0x0f, 0xc0, 0xb1, 0x31, 0xab, 0xc0,
+ 0x00, 0x00, 0x00, 0x00, 0xf6, 0xb1, 0x31, 0xc0, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0xf2, 0xbf, 0x60, 0x5c, 0xad, 0xbe,
+ 0x60, 0xb0, 0x8a, 0xbe, 0xfb, 0x5c, 0xba, 0xc0, 0x70, 0x5c, 0xad, 0xbf,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x5d, 0xc7, 0xbf,
+ 0xe0, 0x05, 0x0f, 0x40, 0x80, 0xb2, 0xbe, 0x3f, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0xa0, 0x09, 0xea, 0x3f, 0x68, 0x06, 0x9c, 0xbf, 0x80, 0x5c, 0xad, 0x3e,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x70, 0xb1, 0xa4, 0x3f, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0x5b, 0x93, 0x3f,
+ 0x90, 0x5e, 0x61, 0x3f, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0x3e, 0x80, 0x5c, 0xad, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3f, 0x90, 0x5e, 0x61, 0xbf, 0x58, 0xb0, 0x8a, 0xbf,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0x5c, 0xad, 0xbe,
+ 0x58, 0xb0, 0x8a, 0xbf, 0x80, 0x08, 0xd0, 0x3e, 0x60, 0x06, 0x1c, 0xbf,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb2, 0x3e, 0x3f, 0x80, 0x08, 0x50, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x70, 0x06, 0x1c, 0x3f, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x60, 0x5c, 0xad, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0x58, 0x05, 0x82, 0xbf,
+ 0x70, 0x06, 0x1c, 0x3f, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x80, 0x08, 0x50, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x70, 0x5c, 0x2d, 0x3f, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0x08, 0xd0, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0x5c, 0xad, 0x3e, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0xd0, 0x3e, 0x58, 0x05, 0x82, 0x3f,
+ 0x58, 0xb0, 0x8a, 0xbf, 0x80, 0xb0, 0x8a, 0x3d, 0xe0, 0x05, 0x0f, 0xc0,
+ 0xa0, 0xb4, 0x72, 0xbf, 0x60, 0x06, 0x1c, 0xbf, 0x5c, 0xb0, 0x0a, 0xc0,
+ 0x80, 0x08, 0x50, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0x5b, 0x93, 0xbf,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x94, 0x5e, 0x61, 0xc0,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x60, 0x5b, 0x13, 0xc0, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x78, 0x07, 0xb6, 0xbf, 0x88, 0x5d, 0xc7, 0x3f, 0x80, 0x08, 0x50, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0x72, 0xbf,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x90, 0xb3, 0xd8, 0x3f, 0x78, 0x07, 0xb6, 0xbf,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0x08, 0xd0, 0xbe, 0x60, 0xb0, 0x8a, 0x3f,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0x5b, 0x93, 0x3f, 0x70, 0x06, 0x1c, 0x3f, 0x80, 0xb0, 0x8a, 0xbd,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb2, 0x3e, 0x3f, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0xd8, 0x5a, 0x06, 0xc0, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x90, 0x5e, 0x61, 0xbf, 0x80, 0x08, 0x50, 0x3e, 0x70, 0x5c, 0xad, 0x3f,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3f, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x68, 0x06, 0x9c, 0x3f, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0x08, 0x50, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x54, 0x05, 0x02, 0xc0,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x90, 0x5e, 0x61, 0xbf,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x78, 0x07, 0xb6, 0x3f, 0x80, 0x08, 0x50, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e, 0x70, 0xb1, 0xa4, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x70, 0x5c, 0xad, 0x3f, 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0xa0, 0xb4, 0x72, 0xbf,
+ 0x58, 0x05, 0x82, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x0a, 0x3f,
+ 0x90, 0xb3, 0xd8, 0xbf, 0x58, 0x05, 0x02, 0x40, 0x60, 0x06, 0x1c, 0xbf,
+ 0xe4, 0xb0, 0x17, 0xc0, 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x90, 0xb3, 0x58, 0xc0, 0x80, 0xb2, 0x3e, 0x3f, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x29, 0x31, 0x9e, 0xc0, 0x80, 0xb0, 0x8a, 0xbd, 0x8a, 0x08, 0x50, 0xc0,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb2, 0xbe, 0xbf, 0xa0, 0x09, 0xea, 0x3f,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbf,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x90, 0x5e, 0x61, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0x58, 0x05, 0x02, 0x40,
+ 0x80, 0x5d, 0xc7, 0xbf, 0x80, 0x5c, 0xad, 0x3e, 0x90, 0x5e, 0x61, 0x3f,
+ 0x90, 0x08, 0x50, 0x3f, 0xa0, 0xb4, 0xf2, 0x3e, 0x90, 0x5e, 0x61, 0xbf,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x68, 0x06, 0x9c, 0x3f, 0x70, 0x5c, 0x2d, 0x3f,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e,
+ 0xa0, 0xb4, 0x72, 0x3f, 0x80, 0x5c, 0xad, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x80, 0x08, 0xd0, 0xbe, 0x90, 0x5e, 0x61, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb2, 0x3e, 0x40, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0x08, 0xd0, 0x3e, 0x80, 0x08, 0xd0, 0xbe, 0x58, 0x05, 0x82, 0x3f,
+ 0x80, 0x08, 0xd0, 0x3e, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x88, 0x5d, 0xc7, 0x3f, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3e, 0xa0, 0xb4, 0x72, 0x3f, 0x80, 0x08, 0xd0, 0xbe,
+ 0x70, 0x5c, 0x2d, 0xbf, 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0x08, 0xd0, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x5c, 0xad, 0x3e, 0x98, 0x09, 0xea, 0xbf,
+ 0xe4, 0xb0, 0x17, 0xc0, 0x90, 0x08, 0x50, 0x3f, 0x78, 0x07, 0xb6, 0xbf,
+ 0x80, 0x5c, 0xad, 0x3e, 0x60, 0x06, 0x1c, 0xbf, 0x60, 0x5b, 0x13, 0xc0,
+ 0x60, 0x5b, 0x93, 0x3f, 0x80, 0xb0, 0x8a, 0xbd, 0x70, 0x5c, 0xad, 0xbf,
+ 0x60, 0xb0, 0x8a, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x90, 0x5e, 0x61, 0x3f, 0x90, 0x08, 0x50, 0x3f,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0x5c, 0xad, 0x3e,
+ 0x70, 0x06, 0x1c, 0x3f, 0x80, 0xb0, 0x0a, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0xd0, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0xb0, 0x0a, 0x3f,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x64, 0x5b, 0x13, 0x40, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0xa0, 0xb4, 0x72, 0x3f, 0x60, 0x5c, 0xad, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x70, 0x5c, 0x2d, 0x3f, 0xa0, 0xb4, 0xf2, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0xbf, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0xb0, 0x8a, 0x3f, 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0x5c, 0xad, 0x3e, 0xa0, 0xb4, 0x72, 0x3f, 0x80, 0x08, 0x50, 0x3e,
+ 0x70, 0x06, 0x1c, 0x3f, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0xd0, 0xbe, 0x90, 0xb3, 0xd8, 0xbf,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0xd0, 0x3e, 0x90, 0x5e, 0x61, 0xbf, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0xbe, 0x90, 0x5e, 0x61, 0xbf,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbf, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0xd0, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x90, 0x5e, 0x61, 0xbf, 0x80, 0xb0, 0x0a, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x90, 0xb3, 0xd8, 0xbf, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0x5c, 0xad, 0x3e,
+ 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x70, 0x5c, 0x2d, 0xbf, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x90, 0x5e, 0x61, 0xbf, 0x80, 0x08, 0x50, 0xbe, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0x5c, 0xad, 0xbe,
+ 0xa0, 0xb4, 0x72, 0xbf, 0x60, 0xb0, 0x8a, 0x3f, 0x60, 0xb0, 0x0a, 0x3f,
+ 0x84, 0x5d, 0x47, 0xc0, 0x6c, 0xb1, 0x24, 0xc0, 0xa8, 0x5f, 0xfb, 0xbf,
+ 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0xb2, 0x3e, 0x3f, 0x80, 0x5d, 0xc7, 0xbf,
+ 0x60, 0x06, 0x1c, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x17, 0x30, 0x84, 0xc0,
+ 0x60, 0x5b, 0x93, 0x3f, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb2, 0x3e, 0xbf,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x88, 0x08, 0xd0, 0xbf, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0x08, 0xd0, 0x3e, 0x70, 0xb1, 0xa4, 0x3f, 0x80, 0x5c, 0xad, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0x06, 0x1c, 0xbf,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x64, 0x5b, 0x13, 0x40, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x58, 0x05, 0x82, 0x3f, 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x70, 0x5c, 0x2d, 0xbf, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3f, 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0xb0, 0x8a, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x60, 0x5b, 0x93, 0x3f, 0x80, 0x08, 0x50, 0x3e,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x1c, 0xbf,
+ 0x70, 0xb1, 0xa4, 0xbf, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0x08, 0x50, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0x06, 0x1c, 0xbf,
+ 0x80, 0x08, 0x50, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x80, 0x08, 0x50, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x80, 0x08, 0x50, 0xbe, 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0x5b, 0x93, 0xbf,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0x08, 0x50, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0x08, 0x50, 0xbf,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbf, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0x06, 0x1c, 0xbf, 0x80, 0x5d, 0xc7, 0xbf,
+ 0x80, 0xb0, 0x8a, 0x3d, 0xfc, 0x5c, 0x3a, 0xc0, 0x90, 0x5e, 0x61, 0xbf,
+ 0x68, 0x06, 0x9c, 0x3f, 0xea, 0x5b, 0xa0, 0x40, 0x80, 0x5d, 0xc7, 0xbf,
+ 0x58, 0x05, 0x82, 0xbf, 0x60, 0x06, 0x1c, 0xbf, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x5c, 0xb0, 0x0a, 0x40, 0x60, 0x5b, 0x93, 0x3f, 0x78, 0x07, 0xb6, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x74, 0x5c, 0x2d, 0x40, 0x64, 0x5b, 0x13, 0x40,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb0, 0x0a, 0x3e, 0xe4, 0xb0, 0x17, 0x40,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x90, 0x5e, 0x61, 0x3f, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x70, 0x06, 0x1c, 0x3f, 0x80, 0x08, 0xd0, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0x50, 0xbf,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x8a, 0x3f, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0xd0, 0x3e, 0x58, 0x05, 0x82, 0x3f,
+ 0x80, 0x5c, 0xad, 0x3e, 0x70, 0x06, 0x1c, 0x3f, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0x08, 0xd0, 0xbe, 0x68, 0x06, 0x9c, 0xbf, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0x06, 0x1c, 0xbf, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe,
+ 0x60, 0x5c, 0xad, 0xbe, 0x60, 0x5c, 0xad, 0xbe, 0x60, 0x5c, 0xad, 0xbe,
+ 0x70, 0xb1, 0xa4, 0xbf, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0xd0, 0x3e,
+ 0x80, 0x08, 0x50, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0xbe, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0xa0, 0xb4, 0xf2, 0xbf, 0xa0, 0xb4, 0x72, 0xbf, 0x98, 0x09, 0xea, 0xbf,
+ 0x58, 0x05, 0x82, 0x3f, 0x78, 0x07, 0xb6, 0x3f, 0x9c, 0x09, 0x6a, 0x40,
+ 0x70, 0x5c, 0xad, 0xbf, 0x60, 0x5b, 0x93, 0xbf, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x0a, 0x3f, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x90, 0x5e, 0x61, 0x3f, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x90, 0x5e, 0x61, 0x3f, 0x58, 0x05, 0x82, 0x3f,
+ 0x98, 0x5e, 0xe1, 0x3f, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0x5c, 0xad, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x64, 0x5b, 0x13, 0x40, 0x60, 0xb0, 0x8a, 0x3e, 0xa0, 0xb4, 0x72, 0x3f,
+ 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x70, 0x06, 0x1c, 0x3f,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0xbf, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0x3f,
+ 0x80, 0x08, 0xd0, 0xbe, 0x60, 0xb0, 0x8a, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x58, 0x05, 0x82, 0x3f, 0x60, 0xb0, 0x8a, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x80, 0x08, 0x50, 0xbe, 0xa0, 0xb4, 0xf2, 0xbe, 0x70, 0xb1, 0xa4, 0xbf,
+ 0x80, 0x08, 0xd0, 0x3e, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb2, 0x3e, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb2, 0x3e, 0x3f, 0x90, 0x5e, 0x61, 0xbf,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0x08, 0xd0, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0x5c, 0xad, 0xbe,
+ 0x60, 0x06, 0x1c, 0xbf, 0x60, 0x5b, 0x93, 0xbf, 0x80, 0x08, 0xd0, 0x3e,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x60, 0x5c, 0xad, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x90, 0x5e, 0x61, 0x3f, 0x90, 0x5e, 0x61, 0xbf, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x5c, 0xad, 0x3e, 0x60, 0x5c, 0xad, 0xbe, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x90, 0xb3, 0x58, 0xc0, 0x68, 0x06, 0x9c, 0xbf,
+ 0x68, 0x06, 0x9c, 0xbf, 0x70, 0x5c, 0xad, 0x3f, 0xe4, 0xb0, 0x17, 0x40,
+ 0x18, 0xb4, 0x65, 0x40, 0x60, 0x5b, 0x93, 0xbf, 0xe0, 0x05, 0x0f, 0xc0,
+ 0x60, 0x06, 0x1c, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0x3f,
+ 0x90, 0x5e, 0x61, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0x3f,
+ 0x90, 0x08, 0x50, 0x3f, 0x60, 0xb0, 0x8a, 0xbe, 0x70, 0x5c, 0x2d, 0x3f,
+ 0x80, 0xb2, 0x3e, 0x3f, 0x5c, 0xb0, 0x0a, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0xd0, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0xe4, 0xb0, 0x17, 0x40, 0x80, 0x08, 0xd0, 0x3e,
+ 0x58, 0x05, 0x82, 0x3f, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x90, 0x5e, 0x61, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x68, 0x06, 0x9c, 0x3f, 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x60, 0x5b, 0x93, 0x3f, 0x60, 0xb0, 0x8a, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0x06, 0x1c, 0xbf,
+ 0x80, 0xb2, 0xbe, 0xbf, 0x70, 0x06, 0x1c, 0x3f, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x90, 0x5e, 0x61, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0xd0, 0xbe, 0x90, 0xb3, 0xd8, 0xbf,
+ 0x80, 0x08, 0xd0, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x90, 0x08, 0x50, 0x3f, 0x90, 0x5e, 0x61, 0xbf,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0xd0, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0x5b, 0x13, 0xc0,
+ 0x70, 0xb1, 0xa4, 0xbf, 0x00, 0x08, 0x43, 0xc0, 0x58, 0x05, 0x82, 0x3f,
+ 0xfc, 0x5c, 0x3a, 0x40, 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x54, 0x05, 0x02, 0xc0, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0xd8, 0x5a, 0x06, 0x40, 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0x5b, 0x93, 0x3f, 0x80, 0x5c, 0xad, 0x3e, 0x60, 0xb0, 0x0a, 0x3f,
+ 0xa0, 0xb4, 0x72, 0x3f, 0x60, 0xb0, 0x8a, 0x3f, 0x78, 0x07, 0xb6, 0x3f,
+ 0x70, 0x06, 0x1c, 0x3f, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0xe0, 0x05, 0x0f, 0x40,
+ 0x80, 0x5c, 0xad, 0x3e, 0xa0, 0xb4, 0x72, 0x3f, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x0a, 0x3f, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0x5b, 0x93, 0x3f, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e, 0x60, 0x5b, 0x93, 0x3f,
+ 0x80, 0x5c, 0xad, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0x08, 0x50, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x68, 0x06, 0x9c, 0xbf, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0xd0, 0x3e, 0x90, 0x5e, 0x61, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0xd0, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x0a, 0xbf, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0x5b, 0x93, 0xbf, 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0xd0, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0xd0, 0x3e,
+ 0x90, 0x5e, 0x61, 0xbf, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0x06, 0x1c, 0xbf, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0xf2, 0x3e, 0xe4, 0xb0, 0x17, 0xc0,
+ 0x58, 0x05, 0x82, 0x3f, 0x78, 0x07, 0xb6, 0x3f, 0xa6, 0x5f, 0xfb, 0xc0,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x5c, 0xb0, 0x0a, 0xc0, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x78, 0x07, 0xb6, 0x3f, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x58, 0xb0, 0x8a, 0xbf,
+ 0x68, 0x06, 0x9c, 0x3f, 0x90, 0x08, 0x50, 0x3f, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0x08, 0x50, 0xbf, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0xe4, 0xb0, 0x17, 0x40, 0x60, 0x06, 0x1c, 0xbf, 0x90, 0x08, 0x50, 0x3f,
+ 0x60, 0xb0, 0x8a, 0xbe, 0xa0, 0xb4, 0xf2, 0x3e, 0x70, 0x06, 0x1c, 0x3f,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x90, 0x5e, 0x61, 0xbf, 0x80, 0xb0, 0x8a, 0x3d, 0x90, 0x5e, 0x61, 0x3f,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x5c, 0xad, 0x3e,
+ 0x70, 0xb1, 0xa4, 0x3f, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe, 0x58, 0x05, 0x82, 0xbf,
+ 0x90, 0x5e, 0x61, 0xbf, 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x05, 0x82, 0xbf, 0x90, 0x5e, 0x61, 0xbf,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0xbe, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x70, 0x5c, 0x2d, 0xbf, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0xf2, 0x3e, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0xd0, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0x08, 0x50, 0xbe, 0x90, 0x08, 0x50, 0x3f, 0xa0, 0x09, 0xea, 0x3f,
+ 0x70, 0x5c, 0x2d, 0xbf, 0xa0, 0xb4, 0x72, 0x3f, 0x80, 0xb0, 0x8a, 0x3d,
+ 0xf0, 0x06, 0x29, 0xc1, 0x70, 0x5c, 0x2d, 0x3f, 0xa8, 0x5f, 0xfb, 0xbf,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0xa0, 0xb4, 0x72, 0x3f,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e, 0x70, 0x5c, 0x2d, 0xbf,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3e, 0xfc, 0x5c, 0x3a, 0xc0, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x0a, 0x3f, 0xe4, 0xb0, 0x17, 0x40, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3f, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x70, 0x06, 0x1c, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x90, 0x5e, 0x61, 0xbf, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0xd0, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x90, 0xb3, 0xd8, 0x3f, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0x08, 0x50, 0x3e,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0x06, 0x1c, 0xbf, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x70, 0x06, 0x1c, 0x3f, 0x80, 0x08, 0x50, 0xbe, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0x06, 0x1c, 0xbf,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0x50, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x58, 0x05, 0x82, 0x3f, 0x80, 0xb2, 0xbe, 0x3f, 0xa0, 0xb4, 0x72, 0x3f,
+ 0x80, 0x08, 0xd0, 0x3e, 0x62, 0x5b, 0x13, 0xc1, 0x70, 0x5c, 0x2d, 0xbf,
+ 0xe4, 0xb0, 0x17, 0xc0, 0x60, 0xb0, 0x8a, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x70, 0x5c, 0xad, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x68, 0x06, 0x9c, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb2, 0x3e, 0x3f, 0x58, 0x05, 0x82, 0xbf,
+ 0xa8, 0x5f, 0xfb, 0x3f, 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0x3e, 0x60, 0x5c, 0xad, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe,
+ 0x60, 0x06, 0x1c, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x1c, 0xbf,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0x5c, 0xad, 0x3e, 0xec, 0x5b, 0x20, 0x40,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x78, 0x07, 0xb6, 0x3f, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0x08, 0xd0, 0xbe, 0x80, 0x08, 0xd0, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x80, 0xb0, 0x8a, 0xbd, 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0x08, 0x50, 0x3e,
+ 0x68, 0x06, 0x9c, 0x3f, 0x80, 0xb0, 0x8a, 0x3d, 0x88, 0x08, 0xd0, 0x3f,
+ 0x80, 0x08, 0xd0, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0x5c, 0xad, 0xbe, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x5c, 0xad, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x70, 0x5c, 0x2d, 0xbf, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x8a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb2, 0x3e, 0xbf, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0x5c, 0xad, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb2, 0x3e, 0x3f, 0x80, 0xb0, 0x8a, 0x3d, 0x70, 0x5c, 0xad, 0x3f,
+ 0x80, 0xb0, 0x8a, 0x3d, 0xfc, 0x5c, 0x3a, 0xc0, 0x56, 0x89, 0xe3, 0xc0,
+ 0x70, 0x5c, 0x2d, 0x3f, 0xd8, 0x5a, 0x06, 0xc0, 0x88, 0x5d, 0xc7, 0x3f,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb2, 0x3e, 0xbf, 0x70, 0xb1, 0xa4, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb2, 0xbe, 0x3f, 0x80, 0x08, 0x50, 0xbe, 0x80, 0x5d, 0xc7, 0xbf,
+ 0x18, 0xb4, 0x65, 0xc0, 0x88, 0x08, 0xd0, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb2, 0x3e, 0xbf, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0x50, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x5b, 0x93, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x58, 0x05, 0x02, 0x40, 0x40, 0xb0, 0x0a, 0xbe, 0x58, 0x05, 0x02, 0x40,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x58, 0x05, 0x82, 0xbf, 0x80, 0x08, 0xd0, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x90, 0x5e, 0x61, 0x3f,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x8a, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0x78, 0x07, 0xb6, 0x3f, 0xa0, 0xb4, 0x72, 0x3f, 0x70, 0x06, 0x1c, 0x3f,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0x50, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0x08, 0x50, 0xbf, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x60, 0x06, 0x1c, 0xbf,
+ 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x8a, 0x3e, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e, 0x58, 0x05, 0x82, 0xbf,
+ 0x80, 0xb2, 0xbe, 0x3f, 0x60, 0xb0, 0x0a, 0x3f, 0xe0, 0x05, 0x0f, 0xc0,
+ 0xdf, 0x05, 0x0f, 0xc1, 0x70, 0x5c, 0x2d, 0x3f, 0x98, 0x5e, 0xe1, 0xbf,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x5b, 0x20, 0xc0,
+ 0x70, 0xb1, 0xa4, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0x88, 0x5d, 0xc7, 0x3f, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x88, 0x08, 0xd0, 0xbf, 0x1d, 0xdb, 0x8c, 0xc0, 0x78, 0x07, 0x36, 0x40,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb2, 0x3e, 0xbf, 0x60, 0x06, 0x1c, 0xbf,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e, 0xa0, 0xb4, 0x72, 0xbf,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x64, 0x5b, 0x13, 0x40, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x58, 0x05, 0x02, 0x40, 0x60, 0x5c, 0xad, 0xbe, 0x60, 0x06, 0x1c, 0xbf,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x5c, 0xad, 0x3e,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x90, 0x5e, 0x61, 0x3f, 0x90, 0x08, 0x50, 0x3f,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x5c, 0xad, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0xd0, 0x3e,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x90, 0x5e, 0x61, 0xbf, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0x08, 0x50, 0xbe, 0xa0, 0xb4, 0xf2, 0x3e, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x70, 0x06, 0x1c, 0x3f, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x60, 0x5b, 0x93, 0x3f,
+ 0x60, 0xb0, 0x8a, 0x3f, 0x68, 0x06, 0x1c, 0x40, 0x80, 0xb0, 0x0a, 0x3e,
+ 0xfc, 0x5c, 0x3a, 0xc0, 0xd4, 0x33, 0xdf, 0xc0, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x90, 0xb3, 0xd8, 0xbf, 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x5d, 0xc7, 0xbf, 0xe4, 0xb0, 0x17, 0x40, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x78, 0x07, 0xb6, 0xbf, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0x08, 0xd0, 0xbe, 0xa0, 0xb4, 0xf2, 0xbf, 0x6c, 0xb1, 0x24, 0xc0,
+ 0xe4, 0xb0, 0x17, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x1c, 0xbf,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x68, 0x06, 0x9c, 0xbf, 0x40, 0xb0, 0x0a, 0xbe, 0xa0, 0x09, 0xea, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0xa0, 0x09, 0xea, 0x3f, 0x58, 0xb0, 0x8a, 0xbf,
+ 0x80, 0x08, 0xd0, 0xbe, 0xa0, 0xb4, 0xf2, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x90, 0x5e, 0x61, 0x3f, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe,
+ 0x90, 0x08, 0x50, 0x3f, 0x80, 0xb2, 0x3e, 0x3f, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x5c, 0xad, 0x3e, 0x60, 0x06, 0x1c, 0xbf,
+ 0x60, 0xb0, 0x8a, 0xbe, 0xa0, 0xb4, 0x72, 0xbf, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0xd0, 0x3e, 0x80, 0x08, 0xd0, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x60, 0x06, 0x1c, 0xbf, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0x08, 0x50, 0xbf, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0xd0, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x0a, 0xbf, 0x40, 0xb0, 0x0a, 0xbe,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x90, 0x5e, 0x61, 0x3f, 0x98, 0x5e, 0xe1, 0x3f,
+ 0x80, 0x08, 0xd0, 0xbe, 0xa0, 0xb4, 0xf2, 0xbf, 0xf6, 0xb1, 0x31, 0xc0,
+ 0x60, 0x5c, 0xad, 0xbe, 0x98, 0x5e, 0xe1, 0xbf, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0xe0, 0x05, 0x0f, 0xc0, 0x98, 0x5e, 0xe1, 0x3f,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x0c, 0x5e, 0x54, 0xc0, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x94, 0x5e, 0x61, 0xc0,
+ 0x5c, 0xb0, 0x8a, 0xc0, 0xf8, 0xb1, 0x31, 0x40, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0x5b, 0x93, 0xbf, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0x06, 0x1c, 0xbf, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x68, 0x06, 0x9c, 0x3f, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0xb0, 0x0a, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0xd0, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0xb0, 0x8a, 0x3e, 0xe4, 0xb0, 0x17, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x68, 0x06, 0x9c, 0x3f, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0xd0, 0x3e, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e, 0xa0, 0xb4, 0x72, 0xbf,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x90, 0x5e, 0x61, 0x3f, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0x5c, 0xad, 0x3e, 0x68, 0x06, 0x9c, 0x3f,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0x08, 0xd0, 0x3e, 0x70, 0x06, 0x1c, 0x3f, 0x58, 0x05, 0x82, 0x3f,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x60, 0x5b, 0x13, 0xc0, 0x90, 0x08, 0x50, 0x3f,
+ 0x60, 0x5b, 0x13, 0xc0, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0xb0, 0x0a, 0xbf, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x0a, 0x3f,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb2, 0x3e, 0x3f, 0x80, 0xb2, 0xbe, 0xbf,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x80, 0x08, 0x50, 0xbf, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x80, 0x08, 0xd0, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x5c, 0xad, 0x3e,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x60, 0x5c, 0xad, 0xbe, 0x60, 0x06, 0x1c, 0xbf, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0x08, 0xd0, 0xbe, 0x90, 0x5e, 0x61, 0x3f, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0xa0, 0xb4, 0xf2, 0x3e, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x90, 0xb3, 0xd8, 0x3f, 0x80, 0xb0, 0x8a, 0xbd, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x0a, 0x3f, 0x60, 0xb0, 0x0a, 0xbf,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0x08, 0xd0, 0xbe, 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x60, 0x5c, 0xad, 0xbe,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0x60, 0xb0, 0x0a, 0x3f,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x80, 0x08, 0xd0, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbf,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0x58, 0x05, 0x82, 0x3f,
+ 0x60, 0xb0, 0x0a, 0x3f, 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0xa0, 0xb4, 0x72, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0x09, 0xea, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0xf6, 0xb1, 0x31, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0xbf, 0x80, 0xb0, 0x8a, 0xbd, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x60, 0x06, 0x1c, 0xbf, 0x80, 0xb2, 0xbe, 0xbf, 0xf0, 0x06, 0x29, 0xc0,
+ 0x5c, 0xb0, 0x0a, 0xc0, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x60, 0x5c, 0xad, 0xbe, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb2, 0x3e, 0x3f, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x0a, 0x3f, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x90, 0xb3, 0xd8, 0x3f, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x0a, 0x3f, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x40, 0xb0, 0x0a, 0xbe, 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x70, 0x06, 0x1c, 0x3f, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x60, 0xb0, 0x8a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0xa0, 0xb4, 0x72, 0x3f,
+ 0x80, 0x5c, 0xad, 0x3e, 0x70, 0xb1, 0xa4, 0x3f, 0x18, 0x30, 0x84, 0x40,
+ 0x80, 0x08, 0x50, 0xbf, 0x60, 0xb0, 0x8a, 0x3e, 0x78, 0x07, 0xb6, 0xbf,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0xb4, 0x65, 0x40, 0x68, 0x06, 0x9c, 0x3f,
+ 0x68, 0x06, 0x1c, 0x40, 0x60, 0x5c, 0xad, 0xbe, 0x6c, 0xb1, 0x24, 0x40,
+ 0x68, 0x06, 0x9c, 0x3f, 0x78, 0x07, 0xb6, 0xbf, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0xbe, 0x60, 0x06, 0x1c, 0xbf,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x80, 0x08, 0xd0, 0xbe, 0x80, 0x08, 0x50, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x0a, 0x3f,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x90, 0x5e, 0x61, 0xbf, 0xa0, 0xb4, 0xf2, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x70, 0x06, 0x1c, 0x3f,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x0a, 0x3f,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x70, 0x5c, 0x2d, 0x3f,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x70, 0x06, 0x1c, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0xd0, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0x50, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x0a, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0x3e, 0xa0, 0xb4, 0xf2, 0xbe, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0x5c, 0xad, 0x3e, 0x58, 0x05, 0x82, 0xbf, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0xb2, 0x3e, 0x3f, 0xe0, 0x05, 0x0f, 0x40,
+ 0x08, 0xb3, 0x4b, 0x40, 0x90, 0xb3, 0xd8, 0xbf, 0x68, 0x06, 0x9c, 0x3f,
+ 0x60, 0x5b, 0x93, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb2, 0xbe, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0xf0, 0x06, 0x29, 0x40,
+ 0x70, 0x06, 0x1c, 0x3f, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb2, 0xbe, 0x3f, 0x70, 0x06, 0x1c, 0x3f, 0x60, 0xb0, 0x8a, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0xd0, 0xbe,
+ 0x90, 0x08, 0x50, 0x3f, 0x60, 0x5c, 0xad, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb2, 0x3e, 0x3f, 0x80, 0x08, 0xd0, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x90, 0x5e, 0x61, 0xbf, 0x90, 0xb3, 0xd8, 0x3f,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0xb0, 0x0a, 0x3f, 0x90, 0x08, 0x50, 0x3f,
+ 0x60, 0x06, 0x1c, 0xbf, 0x40, 0xb0, 0x0a, 0xbe, 0x70, 0x06, 0x1c, 0x3f,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e, 0x70, 0x06, 0x1c, 0x3f,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0x08, 0xd0, 0x3e, 0x90, 0x5e, 0x61, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0x90, 0x5e, 0x61, 0x3f, 0x90, 0x5e, 0x61, 0x3f, 0x68, 0x06, 0x9c, 0x3f,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x64, 0x5b, 0x13, 0x40, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x70, 0x5c, 0x2d, 0x3f, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0x5c, 0xad, 0x3e, 0x60, 0x5b, 0x93, 0x3f, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0x5c, 0xad, 0xbe,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x78, 0x07, 0xb6, 0x3f, 0x80, 0x08, 0xd0, 0x3e,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0x5c, 0xad, 0xbe, 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x90, 0x5e, 0x61, 0x3f, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x60, 0xb0, 0x8a, 0x3e, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x70, 0x06, 0x1c, 0x3f, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x90, 0x5e, 0x61, 0xbf,
+ 0x90, 0xb3, 0xd8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x70, 0x06, 0x1c, 0x3f, 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0x5c, 0xad, 0x3e, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0x5b, 0x93, 0xbf, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb2, 0x3e, 0x3f, 0x80, 0xb0, 0x8a, 0x3d, 0x70, 0x06, 0x1c, 0x3f,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x70, 0xb1, 0xa4, 0xbf, 0x80, 0x08, 0xd0, 0x3e, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x70, 0xb1, 0xa4, 0xbf, 0x80, 0x5c, 0xad, 0x3e, 0x90, 0x08, 0x50, 0x3f,
+ 0x60, 0xb0, 0x8a, 0x3e, 0xa8, 0x5f, 0xfb, 0x3f, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x80, 0x08, 0xd0, 0x3e, 0x70, 0x5c, 0xad, 0xbf,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb2, 0x3e, 0x3f, 0xa0, 0x09, 0xea, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0x98, 0x09, 0xea, 0xbf, 0x60, 0xb0, 0x8a, 0xbe, 0x58, 0xb0, 0x8a, 0xbf,
+ 0x08, 0xb3, 0x4b, 0x40, 0xa0, 0x09, 0xea, 0x3f, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0xd0, 0xbe, 0x60, 0x06, 0x1c, 0xbf,
+ 0x80, 0x08, 0x50, 0x3e, 0xa0, 0xb4, 0xf2, 0xbe, 0x70, 0x5c, 0x2d, 0x3f,
+ 0x80, 0x08, 0xd0, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0x5c, 0xad, 0x3e,
+ 0x60, 0x5c, 0xad, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x70, 0x5c, 0x2d, 0x3f,
+ 0x80, 0x08, 0xd0, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0xbf, 0xa0, 0xb4, 0xf2, 0x3f, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x70, 0x5c, 0x2d, 0x3f,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0xd0, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x90, 0x5e, 0x61, 0xbf, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0xa8, 0x5f, 0xfb, 0xbf, 0x80, 0x08, 0xd0, 0xbe,
+ 0x90, 0x5e, 0x61, 0xbf, 0x60, 0x5b, 0x93, 0x3f, 0x6c, 0xb1, 0x24, 0x40,
+ 0xa0, 0xb4, 0xf2, 0xbf, 0x88, 0x08, 0xd0, 0xbf, 0x60, 0x06, 0x1c, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x06, 0xa9, 0xc0,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x94, 0x5e, 0x61, 0xc0, 0x58, 0x05, 0x02, 0x40, 0x74, 0x5c, 0x2d, 0x40,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x58, 0x05, 0x82, 0x3f, 0x58, 0xb0, 0x8a, 0xbf,
+ 0x90, 0x5e, 0x61, 0x3f, 0xa0, 0xb4, 0xf2, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0x08, 0xd0, 0x3e, 0x60, 0x06, 0x1c, 0xbf, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0xd0, 0xbe, 0x98, 0x5e, 0xe1, 0x3f,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0x5c, 0xad, 0x3e,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x70, 0x06, 0x1c, 0x3f, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0xbe,
+ 0x90, 0x08, 0x50, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x60, 0xb0, 0x8a, 0xbe, 0xa0, 0xb4, 0xf2, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0x5c, 0xad, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e, 0x70, 0x5c, 0x2d, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0x08, 0xd0, 0xbe,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0x08, 0x50, 0xbe, 0x80, 0x08, 0x50, 0xbf,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x70, 0xb1, 0xa4, 0xbf, 0x60, 0xb0, 0x8a, 0x3f,
+ 0x80, 0xb0, 0x8a, 0x3d, 0xac, 0x86, 0xa2, 0xc0, 0x00, 0x00, 0x00, 0x00,
+ 0x68, 0x06, 0x9c, 0xbf, 0x80, 0x08, 0xd0, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x56, 0x05, 0x02, 0xc1, 0x80, 0x5d, 0xc7, 0xbf, 0x68, 0x06, 0x9c, 0x3f,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x84, 0x5d, 0xc7, 0xc0, 0xbd, 0x87, 0xbc, 0xc0,
+ 0x70, 0x5c, 0xad, 0x3f, 0x80, 0x08, 0x50, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x60, 0xb0, 0x8a, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd, 0x90, 0x08, 0x50, 0x3f,
+ 0x58, 0xb0, 0x8a, 0xbf, 0x90, 0x5e, 0x61, 0x3f, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0xd0, 0x3e, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0xbe,
+ 0x98, 0x5e, 0xe1, 0x3f, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb2, 0x3e, 0x3f, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x70, 0x5c, 0x2d, 0x3f, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x70, 0x5c, 0x2d, 0x3f, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x60, 0xb0, 0x0a, 0xbf, 0x80, 0x08, 0x50, 0x3e,
+ 0x60, 0x06, 0x1c, 0xbf, 0x80, 0x08, 0x50, 0x3e, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb2, 0x3e, 0x3f, 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0x3e, 0x70, 0xb1, 0xa4, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0x3f, 0x12, 0x09, 0xdd, 0xc0,
+ 0xa0, 0xb4, 0x72, 0xbf, 0x78, 0x07, 0xb6, 0xbf, 0x60, 0xb0, 0x8a, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0x3f, 0xd8, 0x5a, 0x06, 0xc0,
+ 0x00, 0x00, 0x00, 0x00, 0x9a, 0x09, 0x6a, 0xc0, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x60, 0xb0, 0x8a, 0x3e, 0x98, 0x09, 0xea, 0xbf,
+ 0xa6, 0xdb, 0x99, 0xc0, 0x88, 0x5d, 0xc7, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0xd0, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0x5c, 0xad, 0x3e,
+ 0x68, 0x06, 0x9c, 0x3f, 0x80, 0xb2, 0x3e, 0xbf, 0x58, 0x05, 0x82, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0x08, 0xd0, 0x3e,
+ 0x60, 0x5c, 0xad, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x5c, 0xad, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb2, 0xbe, 0x3f, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0xb0, 0x8a, 0x3e, 0xa0, 0xb4, 0x72, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0x90, 0x08, 0x50, 0x3f, 0xa0, 0xb4, 0x72, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x5c, 0xad, 0x3e, 0x60, 0xb0, 0x0a, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x90, 0x5e, 0x61, 0xbf,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0xb0, 0x8a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x90, 0x5e, 0x61, 0x3f, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0x5c, 0xad, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0xb0, 0x8a, 0xbe, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x90, 0x5e, 0x61, 0xbf, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0xd0, 0xbe, 0xa0, 0xb4, 0x72, 0x3f, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb2, 0x3e, 0xbf, 0x80, 0xb2, 0x3e, 0xbf, 0x70, 0x5c, 0x2d, 0xbf,
+ 0xa6, 0xdb, 0x19, 0xc1, 0x68, 0x06, 0x9c, 0xbf, 0x78, 0x07, 0xb6, 0xbf,
+ 0xa0, 0xb4, 0x72, 0x3f, 0x80, 0xb0, 0x8a, 0xbd, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x88, 0x08, 0xd0, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x90, 0xb3, 0x58, 0xc0,
+ 0x80, 0x5c, 0xad, 0x3e, 0x60, 0xb0, 0x8a, 0x3f, 0x80, 0x08, 0xd0, 0xbe,
+ 0x70, 0x5c, 0xad, 0xbf, 0x9a, 0x85, 0x08, 0xc1, 0x78, 0x07, 0xb6, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x06, 0x1c, 0xbf,
+ 0x80, 0x5c, 0xad, 0x3e, 0x70, 0xb1, 0xa4, 0x3f, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x68, 0x06, 0x9c, 0x3f, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x06, 0x1c, 0xbf,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0xa0, 0xb4, 0xf2, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x8a, 0x3f,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x0a, 0x3f, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x68, 0x06, 0x9c, 0xbf, 0x60, 0xb0, 0x8a, 0xbe, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x90, 0x5e, 0x61, 0x3f, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0x3e,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0xd0, 0x3e,
+ 0x90, 0x08, 0x50, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0xd0, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0x06, 0x1c, 0xbf, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x58, 0x05, 0x82, 0xbf, 0x80, 0xb0, 0x8a, 0x3d, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0xd0, 0x3e, 0x60, 0xb0, 0x8a, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0x3e, 0x90, 0x08, 0x50, 0x3f,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0xd0, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0xa0, 0xb4, 0x72, 0xbf,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0x06, 0x1c, 0xbf, 0x80, 0xb2, 0x3e, 0x3f,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0xe8, 0x5b, 0x20, 0xc0, 0xf6, 0xef, 0x00, 0xc1, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x78, 0x07, 0xb6, 0xbf, 0x58, 0x05, 0x82, 0x3f, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x58, 0x05, 0x82, 0xbf, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x17, 0x30, 0x84, 0xc0, 0x80, 0xb0, 0x8a, 0xbd, 0x98, 0x5e, 0xe1, 0x3f,
+ 0x80, 0x08, 0x50, 0xbe, 0xa0, 0xb4, 0xf2, 0xbf, 0xea, 0x5b, 0xa0, 0xc0,
+ 0x88, 0x08, 0xd0, 0x3f, 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x50, 0x3e,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x60, 0xb0, 0x0a, 0x3f, 0x78, 0x07, 0xb6, 0x3f,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x68, 0x06, 0x9c, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0x08, 0xd0, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0x3e, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0xd0, 0x3e, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3f, 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x0a, 0x3e, 0xa0, 0xb4, 0x72, 0xbf, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x90, 0x5e, 0x61, 0x3f, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x90, 0x5e, 0x61, 0xbf, 0x80, 0x08, 0x50, 0xbe,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb2, 0xbe, 0x3f, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x5d, 0xc7, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0x50, 0xbf, 0x80, 0x08, 0x50, 0x3e,
+ 0x60, 0x5c, 0xad, 0xbe, 0x60, 0x5c, 0xad, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0xb4, 0x72, 0x3f, 0x80, 0xb0, 0x8a, 0x3d, 0x70, 0x06, 0x1c, 0x3f,
+ 0x80, 0x08, 0x50, 0xbf, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x5c, 0xad, 0x3e,
+ 0x80, 0xb2, 0xbe, 0x3f, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x5d, 0xc7, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0x06, 0x1c, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0xb0, 0x0a, 0x3e, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x88, 0x5d, 0xc7, 0x3f, 0xa0, 0x09, 0xea, 0x3f, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0xfc, 0x5c, 0x3a, 0xc0, 0xa0, 0xb4, 0x72, 0xc0,
+ 0x80, 0x08, 0x50, 0x3e, 0x70, 0xb1, 0xa4, 0xbf, 0x70, 0x5c, 0x2d, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x5c, 0xb0, 0x8a, 0xc0, 0x70, 0x06, 0x1c, 0x3f,
+ 0x80, 0x08, 0xd0, 0x3e, 0xa0, 0xb4, 0xf2, 0xbe, 0x90, 0x5e, 0x61, 0xbf,
+ 0x12, 0x09, 0x5d, 0xc0, 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x80, 0x08, 0x50, 0xbe, 0x90, 0xb3, 0xd8, 0xbf, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x80, 0x08, 0x50, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb2, 0x3e, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x78, 0x07, 0xb6, 0x3f, 0x60, 0xb0, 0x8a, 0xbe, 0xa0, 0x09, 0xea, 0x3f,
+ 0x60, 0x06, 0x1c, 0xbf, 0x58, 0xb0, 0x8a, 0xbf, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x80, 0x5c, 0xad, 0x3e,
+ 0x98, 0x09, 0xea, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb2, 0x3e, 0x3f, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x60, 0xb0, 0x0a, 0xbf, 0x90, 0x5e, 0x61, 0xbf, 0x80, 0x08, 0x50, 0x3e,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0xbd, 0x70, 0x5c, 0xad, 0xbf,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0x08, 0x50, 0xbe, 0x70, 0x5c, 0x2d, 0x3f,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x5c, 0xad, 0x3e, 0xa0, 0xb4, 0x72, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0x70, 0x5c, 0x2d, 0x3f, 0x80, 0x08, 0xd0, 0xbe,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x80, 0x08, 0x50, 0xbe, 0x60, 0x5c, 0xad, 0xbe, 0xa0, 0xb4, 0xf2, 0xbe,
+ 0x58, 0x05, 0x82, 0xbf, 0x60, 0xb0, 0x8a, 0x3e, 0x60, 0xb0, 0x0a, 0xbf,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x60, 0x5b, 0x93, 0xbf, 0x80, 0x5c, 0xad, 0x3e,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x70, 0x06, 0x1c, 0x3f, 0x80, 0xb0, 0x0a, 0x3e,
+ 0x60, 0xb0, 0x8a, 0x3e, 0xa0, 0xb4, 0x72, 0xbf, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x90, 0x08, 0x50, 0x3f, 0x60, 0xb0, 0x8a, 0xbe, 0x80, 0x08, 0xd0, 0xbe,
+ 0x60, 0x5c, 0xad, 0xbe, 0x60, 0xb0, 0x0a, 0xbf, 0x60, 0x5c, 0xad, 0xbe,
+ 0x60, 0x5c, 0xad, 0xbe, 0xa0, 0xb4, 0x72, 0x3f, 0xfc, 0x5c, 0x3a, 0x40,
+ 0xa0, 0xb4, 0x72, 0xbf, 0x60, 0x5b, 0x93, 0xbf, 0x80, 0xb2, 0xbe, 0xbf,
+ 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0x08, 0xd0, 0x3e, 0x78, 0x07, 0xb6, 0xbf,
+ 0x58, 0x05, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0xd0, 0xbe,
+ 0x80, 0x08, 0x50, 0x3e, 0x40, 0xb0, 0x0a, 0xbe, 0x67, 0x06, 0x9c, 0xc0,
+ 0x58, 0x05, 0x82, 0x3f, 0x6c, 0xb1, 0x24, 0x40, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x70, 0x5c, 0xad, 0xbf, 0x80, 0xb2, 0xbe, 0xbf, 0x88, 0x5d, 0xc7, 0x3f,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0x06, 0x1c, 0xbf,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0xb0, 0x8a, 0xbd, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0x5c, 0xad, 0xbe, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0x08, 0x50, 0x3e, 0x70, 0xb1, 0xa4, 0xbf,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0x5c, 0xad, 0xbe, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0xb0, 0x8a, 0x3d, 0x80, 0x08, 0x50, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x8a, 0x3d, 0x60, 0xb0, 0x8a, 0xbe,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0x5b, 0x93, 0x3f, 0x60, 0x06, 0x1c, 0xbf, 0x80, 0xb2, 0x3e, 0xbf,
+ 0x70, 0x5c, 0x2d, 0xbf, 0x80, 0xb0, 0x8a, 0x3d, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x5c, 0xad, 0x3e, 0x68, 0x06, 0x9c, 0xbf, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x5c, 0xad, 0x3e, 0x60, 0xb0, 0x8a, 0xbe, 0x60, 0xb0, 0x8a, 0x3e,
+ 0x60, 0x5c, 0xad, 0xbe, 0x70, 0x06, 0x1c, 0x3f, 0x80, 0x08, 0x50, 0xbe,
+ 0x80, 0x08, 0xd0, 0xbe, 0x60, 0x5c, 0xad, 0xbe, 0x60, 0x5c, 0xad, 0xbe,
+ 0x80, 0x5c, 0xad, 0x3e, 0x60, 0x06, 0x1c, 0xbf, 0x90, 0x5e, 0x61, 0x3f,
+ 0x60, 0x5c, 0xad, 0xbe, 0x80, 0x08, 0xd0, 0xbe, 0x80, 0x08, 0x50, 0x3e,
+ 0x80, 0x08, 0xd0, 0xbe, 0x80, 0xb0, 0x8a, 0x3d, 0xa0, 0xb4, 0xf2, 0x3e,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x60, 0xb0, 0x0a, 0xbf, 0xa8, 0x5f, 0xfb, 0x3f, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x60, 0xb0, 0x8a, 0xbe, 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x88, 0x08, 0xd0, 0x3f, 0xa0, 0xb4, 0x72, 0x3f, 0x70, 0x06, 0x1c, 0x3f,
+ 0x80, 0x5c, 0xad, 0x3e, 0x80, 0x5d, 0xc7, 0xbf, 0x70, 0xb1, 0xa4, 0xbf,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x58, 0xb0, 0x8a, 0xbf, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x8a, 0xbd, 0x60, 0xb0, 0x8a, 0x3e, 0x80, 0xb2, 0x3e, 0x3f,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x12, 0x09, 0x5d, 0xc0, 0x00, 0x00, 0x00, 0x00,
+ 0x70, 0x5c, 0x2d, 0x3f, 0x80, 0xb0, 0x8a, 0xbd, 0x80, 0xb0, 0x8a, 0xbd,
+ 0x98, 0x5e, 0xe1, 0xbf, 0x90, 0x5e, 0x61, 0x3f, 0x80, 0x08, 0xd0, 0x3e,
+ 0x60, 0x5c, 0xad, 0xbe, 0x60, 0xb0, 0x8a, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x60, 0x06, 0x1c, 0xbf, 0x80, 0x08, 0x50, 0xbf, 0x70, 0x06, 0x1c, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0xb4, 0xf2, 0xbe, 0x80, 0xb0, 0x8a, 0x3d,
+ 0x70, 0x06, 0x1c, 0x3f, 0x58, 0x05, 0x82, 0xbf, 0x40, 0xb0, 0x0a, 0xbe,
+ 0x80, 0xb0, 0x0a, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0xd0, 0xbe,
+ 0xa0, 0xb4, 0xf2, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x08, 0x50, 0x3e, 0x60, 0x5c, 0xad, 0xbe, 0x20, 0x5f, 0x6e, 0x40,
+ 0x68, 0x06, 0x1c, 0xc0, 0x68, 0x06, 0x1c, 0xc0, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x60, 0xb0, 0x0a, 0x3f, 0x2e, 0xdc, 0xa6, 0xc0, 0x70, 0x06, 0x1c, 0x3f,
+ 0x60, 0x06, 0x1c, 0xbf, 0x58, 0xb0, 0x8a, 0xbf, 0x70, 0x5c, 0x2d, 0x3f,
+ 0x60, 0x5b, 0x93, 0xbf, 0x80, 0x5c, 0xad, 0x3e, 0x60, 0xb0, 0x8a, 0xbe,
+ 0x40, 0xb0, 0x0a, 0xbe, 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0xd0, 0xbe,
+ 0x90, 0x5e, 0x61, 0x3f, 0x80, 0x08, 0xd0, 0x3e, 0x70, 0xb1, 0xa4, 0x3f,
+ 0x90, 0x5e, 0x61, 0x3f, 0x60, 0xb0, 0x0a, 0x3f, 0x60, 0x5b, 0x93, 0xbf,
+ 0x90, 0x5e, 0x61, 0x3f, 0x58, 0x05, 0x82, 0xbf, 0x70, 0x5c, 0xad, 0x3f,
+ 0xe0, 0x05, 0x0f, 0x40, 0x60, 0xb0, 0x0a, 0xbf, 0xa0, 0xb4, 0x72, 0xbf,
+ 0x90, 0x08, 0x50, 0x3f, 0xe8, 0x5b, 0x20, 0xc0, 0xfc, 0x5c, 0x3a, 0x40,
+ 0x80, 0x08, 0x50, 0x3e, 0x80, 0x08, 0x50, 0xbf, 0x90, 0xb3, 0xd8, 0xbf,
+ 0x90, 0x5e, 0x61, 0x3f, 0x40, 0xb0, 0x0a, 0xbe, 0x70, 0x5c, 0x2d, 0xbf,
+ 0x90, 0x5e, 0x61, 0x3f, 0x8a, 0x08, 0x50, 0xc0,
+}};
+const int32_t dnn_logits_bias__2__cf__2_shape[1] = {1};
+const union {
+ uint8_t bytes[4];
+ float values[1];
+} dnn_logits_bias__2__cf__2 = {{
+ 0x6c,
+ 0xee,
+ 0x8d,
+ 0xbf,
+}};
+const int32_t dnn_logits_kernel__3__cf__3_shape[2] = {20, 1};
+const union {
+ uint8_t bytes[80];
+ float values[20];
+} dnn_logits_kernel__3__cf__3 = {{
+ 0x96, 0x59, 0x45, 0xbd, 0x84, 0x25, 0xf6, 0xbd, 0xe9, 0x7c, 0x89, 0x3e,
+ 0xa0, 0x66, 0x3c, 0xbe, 0x37, 0x01, 0x89, 0x3d, 0xe4, 0x97, 0x22, 0x3e,
+ 0x21, 0xf8, 0x84, 0xbe, 0x92, 0x74, 0x8d, 0x3e, 0x30, 0xde, 0x0f, 0xbe,
+ 0x88, 0x44, 0x3b, 0xbe, 0x42, 0x78, 0xb8, 0x3d, 0x0a, 0xf2, 0xf6, 0xbd,
+ 0x48, 0x60, 0xd6, 0x3f, 0x2c, 0x86, 0x83, 0x3d, 0x92, 0xcc, 0xb6, 0x3e,
+ 0xab, 0xc5, 0x4b, 0x3e, 0x6f, 0x6e, 0x1f, 0x3f, 0x07, 0xcd, 0x32, 0x3e,
+ 0x5d, 0xb3, 0xb2, 0x3d, 0x31, 0x53, 0xf6, 0x3d,
+}};
+
+} // anonymous namespace
+
+// -----------------------------------------------------------------------------
+// INFERENCE
+// -----------------------------------------------------------------------------
+
+int32_t input_from_feature_columns_input_layer_concat_concat0Shape[2] = {1,
+ 325};
+int32_t logits_MatMul_merged_with_dnn_logits_BiasAdd0Shape[2] = {1, 1};
+
+void Inference(
+ const float* __restrict input_from_feature_columns_input_layer_concat_concat0 /* shape: 1,325 */
+ ,
+ float* __restrict logits_MatMul_merged_with_dnn_logits_BiasAdd0 /* shape:
+ 1,1 */
+ ,
+ FixedAllocations* __restrict fixed) {
+ const int32_t input_from_feature_columns_input_layer_concat_concat0_shape[] =
+ {1, 325};
+
+#if OP_LIB_BENCHMARK
+ Singleton<PerOpTimings>::get()->Reset();
+#endif
+
+ // dnn/hiddenlayer_0/MatMul_merged_with_dnn/hiddenlayer_0/BiasAdd
+ FullyConnected<float>(
+ input_from_feature_columns_input_layer_concat_concat0_shape,
+ input_from_feature_columns_input_layer_concat_concat0,
+ dnn_hiddenlayer_0_kernel__1__cf__1_shape,
+ dnn_hiddenlayer_0_kernel__1__cf__1.values,
+ dnn_hiddenlayer_0_bias__0__cf__0_shape,
+ dnn_hiddenlayer_0_bias__0__cf__0.values, fixed->alloc0);
+
+ fixed->shape0[0] = 1;
+ fixed->shape0[1] = 20;
+
+ // dnn/hiddenlayer_0/Relu
+ Relu<float>(2, // rank
+ fixed->shape0, fixed->alloc0, fixed->alloc0);
+
+ // dnn/logits/MatMul_merged_with_dnn/logits/BiasAdd
+ FullyConnected<float>(
+ fixed->shape0, fixed->alloc0, dnn_logits_kernel__3__cf__3_shape,
+ dnn_logits_kernel__3__cf__3.values, dnn_logits_bias__2__cf__2_shape,
+ dnn_logits_bias__2__cf__2.values,
+ logits_MatMul_merged_with_dnn_logits_BiasAdd0);
+
+#if OP_LIB_BENCHMARK
+ Singleton<PerOpTimings>::get()->WriteTimingsToInfoLog();
+#endif
+}
+
+} // namespace ui::internal_onedevice::beta_model
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.h b/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.h
new file mode 100644
index 00000000000..efac7f4755b
--- /dev/null
+++ b/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.h
@@ -0,0 +1,40 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+// Code generated by tf.native.
+#ifndef UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_PALM_MODEL_ONEDEVICE_TRAIN_PALM_DETECTION_FILTER_INFERENCE_BETA_H_
+#define UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_PALM_MODEL_ONEDEVICE_TRAIN_PALM_DETECTION_FILTER_INFERENCE_BETA_H_
+#include <cstdint>
+
+namespace ui::internal_onedevice::beta_model {
+struct alignas(16) FixedAllocations {
+ float alloc0[20];
+ int32_t shape0[2];
+};
+
+extern int32_t input_from_feature_columns_input_layer_concat_concat0Shape[2];
+extern int32_t logits_MatMul_merged_with_dnn_logits_BiasAdd0Shape[2];
+
+#define CHROME_KNOWLEDGE_INPUT_FROM_FEATURE_COLUMNS_INPUT_LAYER_CONCAT_CONCAT0_RANK_BETA \
+ 2
+#define CHROME_KNOWLEDGE_INPUT_FROM_FEATURE_COLUMNS_INPUT_LAYER_CONCAT_CONCAT0_DIM0_SIZE_BETA \
+ 1
+#define CHROME_KNOWLEDGE_INPUT_FROM_FEATURE_COLUMNS_INPUT_LAYER_CONCAT_CONCAT0_DIM1_SIZE_BETA \
+ 325
+#define CHROME_KNOWLEDGE_LOGITS_MATMUL_MERGED_WITH_DNN_LOGITS_BIASADD0_RANK_BETA \
+ 2
+#define CHROME_KNOWLEDGE_LOGITS_MATMUL_MERGED_WITH_DNN_LOGITS_BIASADD0_DIM0_SIZE_BETA \
+ 1
+#define CHROME_KNOWLEDGE_LOGITS_MATMUL_MERGED_WITH_DNN_LOGITS_BIASADD0_DIM1_SIZE_BETA \
+ 1
+
+void Inference(
+ const float* __restrict input_from_feature_columns_input_layer_concat_concat0 /* shape: 1,325 */
+ ,
+ float* __restrict logits_MatMul_merged_with_dnn_logits_BiasAdd0 /* shape:
+ 1,1 */
+ ,
+ FixedAllocations* __restrict fixed);
+
+} // namespace ui::internal_onedevice::beta_model
+#endif // UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_PALM_MODEL_ONEDEVICE_TRAIN_PALM_DETECTION_FILTER_INFERENCE_BETA_H_
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.cc b/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.cc
index fd3add9ccd8..c4318783699 100644
--- a/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.cc
+++ b/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.cc
@@ -14,7 +14,7 @@
#define USE_EIGEN 0
#endif
-namespace ui::v2 {
+namespace ui::internal_onedevice::alpha_model_v2 {
namespace {
// -----------------------------------------------------------------------------
@@ -15349,7 +15349,7 @@ const union {
int32_t input_from_feature_columns_input_layer_concat_concat0Shape[2] = {1,
173};
int32_t logits_MatMul_merged_with_dnn_logits_BiasAdd0Shape[2] = {1, 1};
-namespace internal_onedevice {
+
void Inference(
const float* __restrict input_from_feature_columns_input_layer_concat_concat0 /* shape: 1,173 */
,
@@ -15419,5 +15419,4 @@ void Inference(
Singleton<PerOpTimings>::get()->WriteTimingsToInfoLog();
#endif
}
-} // namespace internal_onedevice
-} // namespace ui::v2
+} // namespace ui::internal_onedevice::alpha_model_v2
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.h b/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.h
index 733d0bd4e74..97b53666cc2 100644
--- a/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.h
+++ b/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.h
@@ -6,7 +6,7 @@
#define UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_PALM_MODEL_ONEDEVICE_TRAIN_PALM_DETECTION_FILTER_INFERENCE_V2_H_
#include <cstdint>
-namespace ui::v2::internal_onedevice {
+namespace ui::internal_onedevice::alpha_model_v2 {
struct alignas(16) FixedAllocations {
float alloc0[117];
float alloc1[115];
@@ -36,5 +36,5 @@ void Inference(
,
FixedAllocations* __restrict fixed);
-} // namespace ui::v2::internal_onedevice
+} // namespace ui::internal_onedevice::alpha_model_v2
#endif // UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_PALM_MODEL_ONEDEVICE_TRAIN_PALM_DETECTION_FILTER_INFERENCE_V2_H_
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.cc b/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.cc
index 2eeaf29c573..acf43d8b6fd 100644
--- a/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.cc
+++ b/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.cc
@@ -19,15 +19,24 @@
#include "base/feature_list.h"
#include "base/logging.h"
#include "ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.h"
+#include "ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.h"
#include "ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_v2.h"
#include "ui/events/ozone/features.h"
#define USE_EIGEN 0
namespace ui {
+namespace {
+const std::string kBetaVersion = "beta";
+}
+
+namespace alpha = internal_onedevice::alpha_model;
+namespace alpha_v2 = internal_onedevice::alpha_model_v2;
+namespace beta = internal_onedevice::beta_model;
float OneDeviceTrainNeuralStylusPalmDetectionFilterModel::Inference(
const std::vector<float>& features) const {
DVLOG(1) << "In Inference.";
+
if (features.size() != expected_feature_size_) {
LOG(DFATAL) << "Bad count. Is " << features.size() << " expected "
<< expected_feature_size_;
@@ -40,16 +49,20 @@ float OneDeviceTrainNeuralStylusPalmDetectionFilterModel::Inference(
}
}
float output = 0;
- if (base::FeatureList::IsEnabled(kEnableNeuralPalmRejectionModelV2)) {
- std::unique_ptr<v2::internal_onedevice::FixedAllocations> fixed_allocations(
- new v2::internal_onedevice::FixedAllocations());
- v2::internal_onedevice::Inference(&features[0], &output,
- fixed_allocations.get());
+ if (config_.model_version == kBetaVersion) {
+ std::unique_ptr<beta::FixedAllocations> fixed_allocations(
+ new beta::FixedAllocations());
+ beta::Inference(&features[0], &output, fixed_allocations.get());
} else {
- std::unique_ptr<internal_onedevice::FixedAllocations> fixed_allocations(
- new internal_onedevice::FixedAllocations());
- internal_onedevice::Inference(&features[0], &output,
- fixed_allocations.get());
+ if (base::FeatureList::IsEnabled(kEnableNeuralPalmRejectionModelV2)) {
+ std::unique_ptr<alpha_v2::FixedAllocations> fixed_allocations(
+ new alpha_v2::FixedAllocations());
+ alpha_v2::Inference(&features[0], &output, fixed_allocations.get());
+ } else {
+ std::unique_ptr<alpha::FixedAllocations> fixed_allocations(
+ new alpha::FixedAllocations());
+ alpha::Inference(&features[0], &output, fixed_allocations.get());
+ }
}
return output;
}
@@ -59,43 +72,57 @@ OneDeviceTrainNeuralStylusPalmDetectionFilterModel::config() const {
return config_;
}
-OneDeviceTrainNeuralStylusPalmDetectionFilterModel::
- OneDeviceTrainNeuralStylusPalmDetectionFilterModel() {
+void OneDeviceTrainNeuralStylusPalmDetectionFilterModel::Initialize() {
// Common configurations:
config_.include_sequence_count_in_strokes = true;
- config_.max_neighbor_distance_in_mm = 100.0f;
config_.max_dead_neighbor_time = base::Milliseconds(100.0f);
config_.heuristic_palm_touch_limit = 20.0f;
config_.heuristic_palm_area_limit = 400.0f;
config_.max_blank_time = base::Milliseconds(100.0f);
config_.nearest_neighbor_count = 0;
- config_.biggest_near_neighbor_count = 4;
-
- if (base::FeatureList::IsEnabled(kEnableNeuralPalmRejectionModelV2)) {
- config_.min_sample_count = 3;
- config_.max_sample_count = 6;
- config_.neighbor_min_sample_count = 1;
- config_.output_threshold = 0.90271f;
- expected_feature_size_ = 173;
- if (base::FeatureList::IsEnabled(kEnableNeuralPalmAdaptiveHold)) {
- config_.nn_delay_start_if_palm = true;
- config_.early_stage_sample_counts = std::unordered_set<uint32_t>({2});
- }
- } else {
+ if (config_.model_version == kBetaVersion) {
+ config_.max_neighbor_distance_in_mm = 200.0f;
+ config_.biggest_near_neighbor_count = 4;
config_.min_sample_count = 5;
config_.max_sample_count = 12;
config_.neighbor_min_sample_count = 5;
- config_.output_threshold = 2.519f;
- expected_feature_size_ = 323;
+ config_.output_threshold = 4.465f;
+ config_.use_tracking_id_count = true;
+ config_.use_active_tracking_id_count = true;
+ expected_feature_size_ = 325;
+ } else {
+ config_.max_neighbor_distance_in_mm = 100.0f;
+ config_.biggest_near_neighbor_count = 4;
+
+ if (base::FeatureList::IsEnabled(kEnableNeuralPalmRejectionModelV2)) {
+ config_.min_sample_count = 3;
+ config_.max_sample_count = 6;
+ config_.neighbor_min_sample_count = 1;
+ config_.output_threshold = 0.90271f;
+ expected_feature_size_ = 173;
+
+ if (base::FeatureList::IsEnabled(kEnableNeuralPalmAdaptiveHold)) {
+ config_.nn_delay_start_if_palm = true;
+ config_.early_stage_sample_counts = std::unordered_set<uint32_t>({2});
+ }
+ } else {
+ config_.min_sample_count = 5;
+ config_.max_sample_count = 12;
+ config_.neighbor_min_sample_count = 5;
+ config_.output_threshold = 2.519f;
+ expected_feature_size_ = 323;
+ }
}
}
OneDeviceTrainNeuralStylusPalmDetectionFilterModel::
OneDeviceTrainNeuralStylusPalmDetectionFilterModel(
- const std::vector<float>& radius_poly)
- : OneDeviceTrainNeuralStylusPalmDetectionFilterModel() {
+ const std::string& model_version,
+ const std::vector<float>& radius_poly) {
+ config_.model_version = model_version;
config_.radius_polynomial_resize = radius_poly;
+ Initialize();
}
} // namespace ui
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.h b/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.h
index a058d71a2d9..1690c5d2e43 100644
--- a/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.h
+++ b/chromium/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.h
@@ -18,8 +18,8 @@ namespace ui {
class COMPONENT_EXPORT(EVDEV) OneDeviceTrainNeuralStylusPalmDetectionFilterModel
: public NeuralStylusPalmDetectionFilterModel {
public:
- OneDeviceTrainNeuralStylusPalmDetectionFilterModel();
explicit OneDeviceTrainNeuralStylusPalmDetectionFilterModel(
+ const std::string& model_version,
const std::vector<float>& radius_poly);
OneDeviceTrainNeuralStylusPalmDetectionFilterModel(
@@ -32,6 +32,7 @@ class COMPONENT_EXPORT(EVDEV) OneDeviceTrainNeuralStylusPalmDetectionFilterModel
const NeuralStylusPalmDetectionFilterModelConfig& config() const override;
private:
+ void Initialize();
NeuralStylusPalmDetectionFilterModelConfig config_;
size_t expected_feature_size_;
};
diff --git a/chromium/ui/events/ozone/features.cc b/chromium/ui/events/ozone/features.cc
index 0297d76a018..8e557b7c939 100644
--- a/chromium/ui/events/ozone/features.cc
+++ b/chromium/ui/events/ozone/features.cc
@@ -38,9 +38,15 @@ const base::Feature kEnablePalmSuppression{"EnablePalmSuppression",
const base::Feature kLibinputHandleTouchpad{"LibinputHandleTouchpad",
base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kEnableFakeKeyboardHeuristic{
+ "EnableFakeKeyboardHeuristic", base::FEATURE_DISABLED_BY_DEFAULT};
+
extern const base::FeatureParam<std::string> kNeuralPalmRadiusPolynomial{
&kEnableNeuralPalmDetectionFilter, "neural_palm_radius_polynomial", ""};
+extern const base::FeatureParam<std::string> kNeuralPalmModelVersion{
+ &kEnableNeuralPalmDetectionFilter, "neural_palm_model_version", ""};
+
const base::FeatureParam<double> kHeuristicCancelThresholdSeconds{
&kEnableHeuristicPalmDetectionFilter,
"heuristic_palm_cancel_threshold_seconds", 0.4};
@@ -58,6 +64,7 @@ const base::Feature kEnableInputEventLogging{"EnableInputEventLogging",
constexpr char kOzoneNNPalmSwitchName[] = "ozone-nnpalm-properties";
constexpr char kOzoneNNPalmTouchCompatibleProperty[] = "touch-compatible";
+constexpr char kOzoneNNPalmModelVersionProperty[] = "model";
constexpr char kOzoneNNPalmRadiusPolynomialProperty[] = "radius-polynomial";
} // namespace ui
diff --git a/chromium/ui/events/ozone/features.h b/chromium/ui/events/ozone/features.h
index 6abe3e4f082..2cdfab53f23 100644
--- a/chromium/ui/events/ozone/features.h
+++ b/chromium/ui/events/ozone/features.h
@@ -35,6 +35,9 @@ COMPONENT_EXPORT(EVENTS_OZONE)
extern const base::Feature kEnablePalmOnToolTypePalm;
COMPONENT_EXPORT(EVENTS_OZONE)
+extern const base::FeatureParam<std::string> kNeuralPalmModelVersion;
+
+COMPONENT_EXPORT(EVENTS_OZONE)
extern const base::FeatureParam<std::string> kNeuralPalmRadiusPolynomial;
COMPONENT_EXPORT(EVENTS_OZONE)
@@ -56,14 +59,19 @@ COMPONENT_EXPORT(EVENTS_OZONE)
extern const base::Feature kLibinputHandleTouchpad;
COMPONENT_EXPORT(EVENTS_OZONE)
+extern const base::Feature kEnableFakeKeyboardHeuristic;
+
+COMPONENT_EXPORT(EVENTS_OZONE)
extern const char kOzoneNNPalmSwitchName[];
COMPONENT_EXPORT(EVENTS_OZONE)
extern const char kOzoneNNPalmTouchCompatibleProperty[];
COMPONENT_EXPORT(EVENTS_OZONE)
-extern const char kOzoneNNPalmRadiusPolynomialProperty[];
+extern const char kOzoneNNPalmModelVersionProperty[];
+COMPONENT_EXPORT(EVENTS_OZONE)
+extern const char kOzoneNNPalmRadiusPolynomialProperty[];
} // namespace ui
#endif // UI_EVENTS_OZONE_FEATURES_H_