diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/Kbuild b/drivers/input/touchscreen/chipone_tddi_mmi/Kbuild index 1c45646c3b19..c95271914f3c 100644 --- a/drivers/input/touchscreen/chipone_tddi_mmi/Kbuild +++ b/drivers/input/touchscreen/chipone_tddi_mmi/Kbuild @@ -14,3 +14,4 @@ chipone_tddi_mmi-objs += cts_firmware.o chipone_tddi_mmi-objs += cts_tool.o chipone_tddi_mmi-objs += cts_sysfs.o chipone_tddi_mmi-objs += cts_test.o +chipone_tddi_mmi-objs += cts_charger_detect.o diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_builtin_firmware.h b/drivers/input/touchscreen/chipone_tddi_mmi/cts_builtin_firmware.h old mode 100755 new mode 100644 index 94716d57b24c..92594c970d9d --- a/drivers/input/touchscreen/chipone_tddi_mmi/cts_builtin_firmware.h +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_builtin_firmware.h @@ -1,3846 +1,12 @@ -static u8 icnl9911_driver_builtin_firmware[] = { -0x40, 0x3d, 0x01, 0x20, 0xe1, 0x01, 0x00, 0x00, 0xe9, 0x01, 0x00, 0x00, 0xeb, 0x01, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x02, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x02, 0x00, 0x00, 0xdd, 0xcc, 0x00, 0x00, -0xe5, 0x6f, 0x00, 0x00, 0xc1, 0x6f, 0x00, 0x00, 0x9d, 0x6f, 0x00, 0x00, 0x6d, 0x6f, 0x00, 0x00, -0xdd, 0x6e, 0x00, 0x00, 0xbd, 0x6e, 0x00, 0x00, 0x3b, 0x6e, 0x00, 0x00, 0x31, 0x6e, 0x00, 0x00, -0xa9, 0x0d, 0x00, 0x00, 0xfd, 0x56, 0x00, 0x00, 0xf1, 0xb5, 0x00, 0x00, 0x61, 0xac, 0x00, 0x00, -0xc5, 0xd7, 0x00, 0x00, 0x2d, 0xd8, 0x00, 0x00, 0xe1, 0x3c, 0x00, 0x00, 0xbd, 0x3c, 0x00, 0x00, -0xa5, 0x3c, 0x00, 0x00, 0xad, 0x3c, 0x00, 0x00, 0xb5, 0x3c, 0x00, 0x00, 0xdf, 0x3c, 0x00, 0x00, -0x25, 0x41, 0x00, 0x00, 0x35, 0x41, 0x00, 0x00, 0x61, 0x41, 0x00, 0x00, 0x39, 0xa9, 0x00, 0x00, -0xfd, 0x3d, 0x00, 0x00, 0x41, 0xca, 0x00, 0x00, 0xc5, 0xc9, 0x00, 0x00, 0x1d, 0xc9, 0x00, 0x00, -0x85, 0xc8, 0x00, 0x00, 0xb1, 0xc5, 0x00, 0x00, 0x59, 0xc3, 0x00, 0x00, 0xb1, 0xc9, 0x00, 0x00, -0xde, 0xc0, 0xad, 0xde, 0x00, 0x03, 0x60, 0x00, 0x64, 0x99, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, -0x4d, 0x61, 0x72, 0x20, 0x32, 0x32, 0x20, 0x32, 0x30, 0x32, 0x30, 0x00, 0x31, 0x36, 0x3a, 0x33, -0x36, 0x3a, 0x32, 0x35, 0x1c, 0xec, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x01, 0x01, 0x00, 0x00, 0x41, 0xd1, 0x28, 0x02, 0x38, 0x35, 0x58, 0x58, 0x40, 0x06, 0xd0, 0x02, -0xe5, 0x05, 0xa7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0xfa, 0xad, 0x0b, -0x00, 0xf0, 0x02, 0xf8, 0x00, 0xf0, 0x30, 0xf8, 0x0c, 0xa0, 0x30, 0xc8, 0x08, 0x38, 0x24, 0x18, -0x2d, 0x18, 0xa2, 0x46, 0x67, 0x1e, 0xab, 0x46, 0x54, 0x46, 0x5d, 0x46, 0xac, 0x42, 0x01, 0xd1, -0x00, 0xf0, 0x22, 0xf8, 0x7e, 0x46, 0x0f, 0x3e, 0x0f, 0xcc, 0xb6, 0x46, 0x01, 0x26, 0x33, 0x42, -0x00, 0xd0, 0xfb, 0x1a, 0xa2, 0x46, 0xab, 0x46, 0x33, 0x43, 0x18, 0x47, 0x58, 0xed, 0x00, 0x00, -0x78, 0xed, 0x00, 0x00, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x10, 0x3a, 0x01, 0xd3, -0x78, 0xc1, 0xfb, 0xd8, 0x52, 0x07, 0x00, 0xd3, 0x30, 0xc1, 0x00, 0xd5, 0x0b, 0x60, 0x70, 0x47, -0x1f, 0xb5, 0x1f, 0xbd, 0x10, 0xb5, 0x10, 0xbd, 0x00, 0xf0, 0xb1, 0xfd, 0x11, 0x46, 0xff, 0xf7, -0xf7, 0xff, 0x0e, 0xf0, 0x2d, 0xfc, 0x00, 0xf0, 0xc9, 0xfd, 0x03, 0xb4, 0xff, 0xf7, 0xf2, 0xff, -0x03, 0xbc, 0x00, 0xf0, 0xcf, 0xfd, 0x00, 0x00, 0x70, 0xb5, 0x05, 0x46, 0x0c, 0x46, 0x16, 0x46, -0x02, 0xe0, 0x0f, 0xcc, 0x0f, 0xc5, 0x10, 0x3e, 0x10, 0x2e, 0xfa, 0xd2, 0x08, 0x2e, 0x02, 0xd3, -0x03, 0xcc, 0x03, 0xc5, 0x08, 0x3e, 0x04, 0x2e, 0x07, 0xd3, 0x01, 0xcc, 0x01, 0xc5, 0x36, 0x1f, -0x03, 0xe0, 0x21, 0x78, 0x29, 0x70, 0x64, 0x1c, 0x6d, 0x1c, 0x76, 0x1e, 0xf9, 0xd2, 0x70, 0xbd, -0x11, 0x48, 0x80, 0x47, 0x11, 0x48, 0x00, 0x47, 0xfe, 0xe7, 0x11, 0x49, 0x11, 0x48, 0x08, 0x60, -0x11, 0x49, 0x12, 0x48, 0x08, 0x60, 0x04, 0x20, 0x71, 0x46, 0x08, 0x42, 0x01, 0xd0, 0x04, 0xd1, -0xfe, 0xe7, 0xef, 0xf3, 0x08, 0x80, 0x06, 0xf0, 0x91, 0xfd, 0xef, 0xf3, 0x09, 0x80, 0x06, 0xf0, -0x8d, 0xfd, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0x00, 0x00, 0x08, 0x48, 0x05, 0x49, -0x07, 0x4a, 0x08, 0x4b, 0x70, 0x47, 0x00, 0x00, 0xa9, 0xcd, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, -0x24, 0x00, 0x01, 0x20, 0x40, 0x3d, 0x01, 0x20, 0x28, 0x00, 0x01, 0x20, 0x00, 0x04, 0x00, 0x00, -0x40, 0x39, 0x01, 0x20, 0x40, 0x39, 0x01, 0x20, 0x43, 0x43, 0x51, 0x43, 0x30, 0xb5, 0x5c, 0x18, -0x01, 0x0c, 0x13, 0x0c, 0x0d, 0x46, 0x92, 0xb2, 0x5d, 0x43, 0x80, 0xb2, 0x51, 0x43, 0x2c, 0x19, -0x05, 0x46, 0x55, 0x43, 0x0a, 0x0c, 0x09, 0x04, 0x4d, 0x19, 0x62, 0x41, 0x58, 0x43, 0x01, 0x0c, -0x00, 0x04, 0x40, 0x19, 0x51, 0x41, 0x30, 0xbd, 0x70, 0xb5, 0x00, 0x25, 0x2c, 0x46, 0xad, 0x1a, -0x9c, 0x41, 0x12, 0xda, 0x00, 0x25, 0x2c, 0x46, 0x2d, 0x1a, 0x8c, 0x41, 0x02, 0xda, 0x00, 0xf0, -0xad, 0xfc, 0x70, 0xbd, 0x00, 0x24, 0x40, 0x42, 0x8c, 0x41, 0x21, 0x46, 0x00, 0xf0, 0xa6, 0xfc, -0x00, 0x24, 0x40, 0x42, 0x8c, 0x41, 0x21, 0x46, 0x19, 0xe0, 0x00, 0x25, 0x2c, 0x46, 0x2d, 0x1a, -0x8c, 0x41, 0x0a, 0xda, 0x00, 0x24, 0x52, 0x42, 0x9c, 0x41, 0x23, 0x46, 0x00, 0xf0, 0x96, 0xfc, -0x00, 0x24, 0x40, 0x42, 0x8c, 0x41, 0x21, 0x46, 0x70, 0xbd, 0x00, 0x24, 0x52, 0x42, 0x9c, 0x41, -0x40, 0x42, 0x23, 0x46, 0x00, 0x24, 0x8c, 0x41, 0x21, 0x46, 0x00, 0xf0, 0x87, 0xfc, 0x00, 0x24, -0x52, 0x42, 0x9c, 0x41, 0x23, 0x46, 0x70, 0xbd, 0xf8, 0xb5, 0x04, 0x2a, 0x2c, 0xd3, 0x83, 0x07, -0x12, 0xd0, 0x0b, 0x78, 0x49, 0x1c, 0x03, 0x70, 0x40, 0x1c, 0x52, 0x1e, 0x83, 0x07, 0x0b, 0xd0, -0x0b, 0x78, 0x49, 0x1c, 0x03, 0x70, 0x40, 0x1c, 0x52, 0x1e, 0x83, 0x07, 0x04, 0xd0, 0x0b, 0x78, -0x49, 0x1c, 0x03, 0x70, 0x40, 0x1c, 0x52, 0x1e, 0x8b, 0x07, 0x9b, 0x0f, 0x05, 0xd0, 0xc9, 0x1a, -0xdf, 0x00, 0x20, 0x23, 0xde, 0x1b, 0x08, 0xc9, 0x0a, 0xe0, 0xff, 0xf7, 0x3d, 0xff, 0xf8, 0xbd, -0x1d, 0x46, 0x08, 0xc9, 0xfd, 0x40, 0x1c, 0x46, 0xb4, 0x40, 0x2c, 0x43, 0x10, 0xc0, 0x12, 0x1f, -0x04, 0x2a, 0xf5, 0xd2, 0xf3, 0x08, 0xc9, 0x1a, 0x52, 0x1e, 0xf0, 0xd4, 0x0b, 0x78, 0x49, 0x1c, -0x03, 0x70, 0x40, 0x1c, 0x52, 0x1e, 0xea, 0xd4, 0x0b, 0x78, 0x49, 0x1c, 0x03, 0x70, 0x40, 0x1c, -0x01, 0x2a, 0xe4, 0xd4, 0x09, 0x78, 0x01, 0x70, 0xf8, 0xbd, 0xd2, 0xb2, 0x10, 0xb5, 0x13, 0x02, -0x9a, 0x18, 0x13, 0x04, 0x9a, 0x18, 0x00, 0xf0, 0x0e, 0xf8, 0x10, 0xbd, 0x01, 0xe0, 0x04, 0xc0, -0x09, 0x1f, 0x04, 0x29, 0xfb, 0xd2, 0x8b, 0x07, 0x01, 0xd5, 0x02, 0x80, 0x80, 0x1c, 0xc9, 0x07, -0x00, 0xd0, 0x02, 0x70, 0x70, 0x47, 0x00, 0x29, 0x0b, 0xd0, 0xc3, 0x07, 0x02, 0xd0, 0x02, 0x70, -0x40, 0x1c, 0x49, 0x1e, 0x02, 0x29, 0x04, 0xd3, 0x83, 0x07, 0x02, 0xd5, 0x02, 0x80, 0x80, 0x1c, -0x89, 0x1e, 0xe3, 0xe7, 0x00, 0x22, 0xee, 0xe7, 0x00, 0x22, 0xdf, 0xe7, 0x00, 0x22, 0x03, 0x09, -0x8b, 0x42, 0x73, 0xd3, 0x03, 0x0a, 0x8b, 0x42, 0x58, 0xd3, 0x03, 0x0b, 0x8b, 0x42, 0x3c, 0xd3, -0x03, 0x0c, 0x8b, 0x42, 0x21, 0xd3, 0x12, 0xe0, 0x03, 0x46, 0x0b, 0x43, 0x7f, 0xd4, 0x00, 0x22, -0x43, 0x08, 0x8b, 0x42, 0x74, 0xd3, 0x03, 0x09, 0x8b, 0x42, 0x5f, 0xd3, 0x03, 0x0a, 0x8b, 0x42, -0x44, 0xd3, 0x03, 0x0b, 0x8b, 0x42, 0x28, 0xd3, 0x03, 0x0c, 0x8b, 0x42, 0x0d, 0xd3, 0xff, 0x22, -0x09, 0x02, 0x12, 0xba, 0x03, 0x0c, 0x8b, 0x42, 0x02, 0xd3, 0x12, 0x12, 0x09, 0x02, 0x65, 0xd0, -0x03, 0x0b, 0x8b, 0x42, 0x19, 0xd3, 0x00, 0xe0, 0x09, 0x0a, 0xc3, 0x0b, 0x8b, 0x42, 0x01, 0xd3, -0xcb, 0x03, 0xc0, 0x1a, 0x52, 0x41, 0x83, 0x0b, 0x8b, 0x42, 0x01, 0xd3, 0x8b, 0x03, 0xc0, 0x1a, -0x52, 0x41, 0x43, 0x0b, 0x8b, 0x42, 0x01, 0xd3, 0x4b, 0x03, 0xc0, 0x1a, 0x52, 0x41, 0x03, 0x0b, -0x8b, 0x42, 0x01, 0xd3, 0x0b, 0x03, 0xc0, 0x1a, 0x52, 0x41, 0xc3, 0x0a, 0x8b, 0x42, 0x01, 0xd3, -0xcb, 0x02, 0xc0, 0x1a, 0x52, 0x41, 0x83, 0x0a, 0x8b, 0x42, 0x01, 0xd3, 0x8b, 0x02, 0xc0, 0x1a, -0x52, 0x41, 0x43, 0x0a, 0x8b, 0x42, 0x01, 0xd3, 0x4b, 0x02, 0xc0, 0x1a, 0x52, 0x41, 0x03, 0x0a, -0x8b, 0x42, 0x01, 0xd3, 0x0b, 0x02, 0xc0, 0x1a, 0x52, 0x41, 0xcd, 0xd2, 0xc3, 0x09, 0x8b, 0x42, -0x01, 0xd3, 0xcb, 0x01, 0xc0, 0x1a, 0x52, 0x41, 0x83, 0x09, 0x8b, 0x42, 0x01, 0xd3, 0x8b, 0x01, -0xc0, 0x1a, 0x52, 0x41, 0x43, 0x09, 0x8b, 0x42, 0x01, 0xd3, 0x4b, 0x01, 0xc0, 0x1a, 0x52, 0x41, -0x03, 0x09, 0x8b, 0x42, 0x01, 0xd3, 0x0b, 0x01, 0xc0, 0x1a, 0x52, 0x41, 0xc3, 0x08, 0x8b, 0x42, -0x01, 0xd3, 0xcb, 0x00, 0xc0, 0x1a, 0x52, 0x41, 0x83, 0x08, 0x8b, 0x42, 0x01, 0xd3, 0x8b, 0x00, -0xc0, 0x1a, 0x52, 0x41, 0x43, 0x08, 0x8b, 0x42, 0x01, 0xd3, 0x4b, 0x00, 0xc0, 0x1a, 0x52, 0x41, -0x41, 0x1a, 0x00, 0xd2, 0x01, 0x46, 0x52, 0x41, 0x10, 0x46, 0x70, 0x47, 0x5d, 0xe0, 0xca, 0x0f, -0x00, 0xd0, 0x49, 0x42, 0x03, 0x10, 0x00, 0xd3, 0x40, 0x42, 0x53, 0x40, 0x00, 0x22, 0x9c, 0x46, -0x03, 0x09, 0x8b, 0x42, 0x2d, 0xd3, 0x03, 0x0a, 0x8b, 0x42, 0x12, 0xd3, 0xfc, 0x22, 0x89, 0x01, -0x12, 0xba, 0x03, 0x0a, 0x8b, 0x42, 0x0c, 0xd3, 0x89, 0x01, 0x92, 0x11, 0x8b, 0x42, 0x08, 0xd3, -0x89, 0x01, 0x92, 0x11, 0x8b, 0x42, 0x04, 0xd3, 0x89, 0x01, 0x3a, 0xd0, 0x92, 0x11, 0x00, 0xe0, -0x89, 0x09, 0xc3, 0x09, 0x8b, 0x42, 0x01, 0xd3, 0xcb, 0x01, 0xc0, 0x1a, 0x52, 0x41, 0x83, 0x09, -0x8b, 0x42, 0x01, 0xd3, 0x8b, 0x01, 0xc0, 0x1a, 0x52, 0x41, 0x43, 0x09, 0x8b, 0x42, 0x01, 0xd3, -0x4b, 0x01, 0xc0, 0x1a, 0x52, 0x41, 0x03, 0x09, 0x8b, 0x42, 0x01, 0xd3, 0x0b, 0x01, 0xc0, 0x1a, -0x52, 0x41, 0xc3, 0x08, 0x8b, 0x42, 0x01, 0xd3, 0xcb, 0x00, 0xc0, 0x1a, 0x52, 0x41, 0x83, 0x08, -0x8b, 0x42, 0x01, 0xd3, 0x8b, 0x00, 0xc0, 0x1a, 0x52, 0x41, 0xd9, 0xd2, 0x43, 0x08, 0x8b, 0x42, -0x01, 0xd3, 0x4b, 0x00, 0xc0, 0x1a, 0x52, 0x41, 0x41, 0x1a, 0x00, 0xd2, 0x01, 0x46, 0x63, 0x46, -0x52, 0x41, 0x5b, 0x10, 0x10, 0x46, 0x01, 0xd3, 0x40, 0x42, 0x00, 0x2b, 0x00, 0xd5, 0x49, 0x42, -0x70, 0x47, 0x63, 0x46, 0x5b, 0x10, 0x00, 0xd3, 0x40, 0x42, 0x01, 0xb5, 0x00, 0x20, 0xc0, 0x46, -0xc0, 0x46, 0x02, 0xbd, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47, 0x00, 0x00, 0xf0, 0xb5, 0x0c, 0x46, -0x87, 0x1a, 0x9c, 0x41, 0x0d, 0x46, 0x86, 0x1a, 0x9d, 0x41, 0x03, 0xd2, 0xc0, 0x1b, 0xa1, 0x41, -0xd2, 0x19, 0x63, 0x41, 0x0d, 0x0d, 0x1f, 0x0d, 0xc9, 0x4e, 0xec, 0x1b, 0xae, 0x43, 0x5c, 0xd0, -0x7f, 0x05, 0x7f, 0x0d, 0x00, 0x26, 0x00, 0x2f, 0x51, 0xd0, 0x2d, 0x05, 0xac, 0x46, 0xa9, 0x43, -0xdd, 0x02, 0x01, 0x23, 0xed, 0x0a, 0x1b, 0x05, 0x1d, 0x43, 0x20, 0x23, 0x1b, 0x1b, 0x24, 0xd4, -0x17, 0x46, 0xe7, 0x40, 0x38, 0x18, 0x71, 0x41, 0x2f, 0x46, 0xe7, 0x40, 0xcc, 0x19, 0x9d, 0x40, -0x28, 0x18, 0x31, 0x46, 0x61, 0x41, 0x0c, 0x0d, 0x27, 0xd1, 0x61, 0x44, 0x9a, 0x40, 0x13, 0xd5, -0x00, 0x23, 0x40, 0x1c, 0x59, 0x41, 0x52, 0x00, 0x0e, 0xd1, 0x40, 0x08, 0x40, 0x00, 0x01, 0x22, -0x4b, 0x00, 0x52, 0x05, 0xd3, 0x42, 0x07, 0xd3, 0x05, 0x20, 0x40, 0x07, 0xc1, 0x42, 0x01, 0xd5, -0xb0, 0x49, 0x00, 0xe0, 0xb0, 0x49, 0x30, 0x46, 0xf0, 0xbd, 0x6b, 0x00, 0x00, 0x2a, 0x00, 0xd0, -0x01, 0x22, 0x9a, 0x18, 0x1f, 0x23, 0x20, 0x3c, 0x1b, 0x1b, 0x01, 0xd5, 0x00, 0x23, 0x02, 0xe0, -0xe5, 0x40, 0x28, 0x18, 0x71, 0x41, 0x0c, 0x0d, 0xd7, 0xd0, 0x01, 0x24, 0x24, 0x05, 0x09, 0x19, -0xc4, 0x07, 0xcd, 0x07, 0x40, 0x08, 0x49, 0x08, 0xe4, 0x0f, 0x28, 0x43, 0x61, 0x44, 0x00, 0x2c, -0xd5, 0xd0, 0x00, 0x24, 0x40, 0x1c, 0x61, 0x41, 0x9a, 0x40, 0xd0, 0xd1, 0xcd, 0xe7, 0x6a, 0x05, -0x52, 0x0d, 0xd9, 0xd1, 0xc9, 0x0f, 0xc9, 0x07, 0xd5, 0xe7, 0x9c, 0x4d, 0x4e, 0x00, 0x00, 0x28, -0x01, 0xd0, 0x01, 0x24, 0x00, 0xe0, 0x00, 0x24, 0x34, 0x19, 0x5f, 0x00, 0x00, 0x2a, 0x01, 0xd0, -0x01, 0x26, 0x00, 0xe0, 0x00, 0x26, 0xbe, 0x19, 0x95, 0x4f, 0xac, 0x42, 0x0c, 0xd8, 0xae, 0x42, -0x0a, 0xd8, 0xb4, 0x42, 0x06, 0xd0, 0x01, 0x25, 0x6d, 0x05, 0xec, 0x42, 0xbc, 0xd0, 0x10, 0x46, -0x19, 0x46, 0xf0, 0xbd, 0x99, 0x42, 0xfc, 0xd0, 0x00, 0x20, 0x39, 0x46, 0xf0, 0xbd, 0xf0, 0xb5, -0x1f, 0xb4, 0x0c, 0x46, 0x0f, 0x46, 0x81, 0x1a, 0x9f, 0x41, 0x25, 0x46, 0x86, 0x1a, 0x9d, 0x41, -0x06, 0xd2, 0x01, 0x25, 0xed, 0x07, 0x6f, 0x40, 0x40, 0x1a, 0xbc, 0x41, 0x52, 0x18, 0x7b, 0x41, -0x21, 0x0d, 0x1e, 0x0d, 0x8d, 0x1b, 0xac, 0x46, 0x7d, 0x4d, 0x8d, 0x43, 0x7e, 0xd0, 0x75, 0x05, -0x6d, 0x0d, 0x7c, 0xd0, 0x0d, 0x05, 0xae, 0x46, 0xac, 0x43, 0x1b, 0x03, 0x1b, 0x0b, 0x79, 0x4d, -0x52, 0x42, 0x9d, 0x41, 0x20, 0x23, 0x66, 0x46, 0x9b, 0x1b, 0x14, 0xd3, 0x17, 0x46, 0xf7, 0x40, -0x38, 0x18, 0x00, 0x26, 0x00, 0x90, 0x74, 0x41, 0x60, 0x46, 0x2f, 0x46, 0x07, 0x41, 0xe4, 0x19, -0x00, 0x98, 0x9d, 0x40, 0x28, 0x18, 0x66, 0x41, 0x16, 0xd4, 0x71, 0x46, 0x71, 0x18, 0x9a, 0x40, -0x25, 0xd5, 0x01, 0x23, 0x20, 0xe0, 0x93, 0x18, 0x2a, 0x46, 0x6a, 0x41, 0x52, 0x00, 0x00, 0x2b, -0x00, 0xd0, 0x52, 0x1c, 0x1e, 0x23, 0x20, 0x3e, 0x9b, 0x1b, 0x00, 0x2b, 0x61, 0xdd, 0x35, 0x41, -0xee, 0x17, 0x28, 0x18, 0x66, 0x41, 0xe8, 0xd5, 0x00, 0x18, 0x76, 0x41, 0x5b, 0x1c, 0x9a, 0x40, -0x00, 0xd3, 0x40, 0x1c, 0x4b, 0x05, 0xf3, 0x18, 0x15, 0x24, 0xe3, 0x40, 0x10, 0xd3, 0x00, 0x2b, -0x52, 0xd0, 0x71, 0x46, 0x71, 0x18, 0xd3, 0x0f, 0xc0, 0x18, 0x02, 0xd3, 0x49, 0x1c, 0x05, 0xb0, -0xf0, 0xbd, 0x01, 0x23, 0xdb, 0x07, 0x9a, 0x42, 0xf9, 0xd1, 0x40, 0x08, 0x40, 0x00, 0xf6, 0xe7, -0x01, 0x22, 0x52, 0x05, 0xb2, 0x18, 0x01, 0xd1, 0x00, 0x28, 0x53, 0xd0, 0x01, 0x23, 0xcc, 0x0a, -0xdb, 0x02, 0x99, 0x43, 0x89, 0x1e, 0x00, 0x2a, 0x08, 0xd1, 0x02, 0x0c, 0x03, 0xd0, 0x02, 0x0c, -0x00, 0x04, 0x10, 0x39, 0x02, 0xe0, 0x02, 0x46, 0x00, 0x20, 0x20, 0x39, 0x00, 0x23, 0x55, 0x0b, -0x05, 0xd1, 0x12, 0x02, 0x08, 0x23, 0x55, 0x0b, 0x01, 0xd1, 0x52, 0x01, 0x0d, 0x23, 0x55, 0x0c, -0x01, 0xd1, 0x12, 0x01, 0x1b, 0x1d, 0xd5, 0x0c, 0x01, 0xd1, 0x92, 0x00, 0x9b, 0x1c, 0x15, 0x0d, -0x01, 0xd1, 0x52, 0x00, 0x5b, 0x1c, 0x20, 0x25, 0xee, 0x1a, 0x01, 0xe0, 0x2c, 0xe0, 0x22, 0xe0, -0x05, 0x46, 0xf5, 0x40, 0x15, 0x43, 0x98, 0x40, 0xca, 0x1a, 0xe1, 0x07, 0x69, 0x18, 0x13, 0x05, -0xc9, 0x18, 0x00, 0x2a, 0xbb, 0xda, 0x03, 0x20, 0x40, 0x07, 0x08, 0x18, 0xc1, 0x0f, 0xc9, 0x07, -0x0f, 0xe0, 0x71, 0x46, 0x61, 0x18, 0xb2, 0xe7, 0xf1, 0x07, 0x40, 0x08, 0x08, 0x43, 0x71, 0x10, -0x71, 0x44, 0x4a, 0x00, 0x0c, 0xd0, 0x01, 0x23, 0x5b, 0x05, 0x9a, 0x42, 0xa7, 0xd2, 0xc9, 0x0f, -0xc9, 0x07, 0x00, 0x20, 0xa3, 0xe7, 0x49, 0x05, 0x49, 0x0d, 0x26, 0xd1, 0x00, 0x20, 0x01, 0xe0, -0x00, 0x28, 0xf4, 0xd1, 0x00, 0x21, 0x9a, 0xe7, 0x28, 0x4d, 0x66, 0x00, 0x00, 0x28, 0x01, 0xd0, -0x01, 0x21, 0x00, 0xe0, 0x00, 0x21, 0x71, 0x18, 0x5f, 0x00, 0x00, 0x2a, 0x01, 0xd0, 0x01, 0x26, -0x00, 0xe0, 0x00, 0x26, 0xbe, 0x19, 0x22, 0x4f, 0xa9, 0x42, 0x10, 0xd8, 0xae, 0x42, 0x0e, 0xd8, -0xb1, 0x42, 0x08, 0xd0, 0x01, 0x25, 0x6d, 0x05, 0xe9, 0x42, 0x06, 0xd0, 0x19, 0x46, 0xa8, 0x02, -0x41, 0x40, 0x10, 0x46, 0x7b, 0xe7, 0x9c, 0x42, 0x01, 0xd0, 0x21, 0x46, 0x77, 0xe7, 0x00, 0x20, -0x39, 0x46, 0x74, 0xe7, 0x10, 0xb5, 0x0c, 0x46, 0x5c, 0x40, 0x05, 0xd5, 0x01, 0x24, 0xe4, 0x07, -0x63, 0x40, 0xff, 0xf7, 0x0c, 0xff, 0x10, 0xbd, 0xff, 0xf7, 0x78, 0xfe, 0x10, 0xbd, 0x30, 0xb4, -0x0c, 0x46, 0x5c, 0x40, 0x04, 0xd5, 0x01, 0x24, 0xe4, 0x07, 0x63, 0x40, 0x30, 0xbc, 0x6d, 0xe6, -0x30, 0xbc, 0xfc, 0xe6, 0x70, 0xb5, 0x01, 0x24, 0xe4, 0x07, 0x61, 0x40, 0x0d, 0x46, 0x5d, 0x40, -0x02, 0xd4, 0xff, 0xf7, 0x63, 0xfe, 0x70, 0xbd, 0x63, 0x40, 0xff, 0xf7, 0xf0, 0xfe, 0x70, 0xbd, -0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0xe0, 0xff, -0x00, 0x00, 0xf8, 0x7f, 0x03, 0x46, 0xca, 0x02, 0x40, 0x0d, 0x10, 0xb5, 0x10, 0x43, 0x0a, 0x15, -0x04, 0xd0, 0x01, 0x24, 0xe4, 0x07, 0x20, 0x43, 0x00, 0x2a, 0x05, 0xdb, 0x0a, 0x4c, 0xa2, 0x1a, -0x04, 0xd4, 0xd0, 0x40, 0xff, 0x2a, 0x00, 0xdd, 0x00, 0x20, 0x10, 0xbd, 0x4a, 0x00, 0x00, 0x2b, -0x01, 0xd0, 0x01, 0x20, 0x00, 0xe0, 0x00, 0x20, 0x10, 0x18, 0x01, 0x22, 0x52, 0x05, 0xd0, 0x42, -0xf2, 0xd8, 0xc8, 0x17, 0xc0, 0x43, 0x10, 0xbd, 0x1e, 0x04, 0x00, 0x00, 0x1f, 0x22, 0x03, 0x0c, -0x02, 0xd1, 0x0f, 0x22, 0x00, 0x04, 0x02, 0xd0, 0x03, 0x0e, 0x03, 0xd0, 0x04, 0xe0, 0x00, 0x20, -0x01, 0x46, 0x70, 0x47, 0x00, 0x02, 0x08, 0x3a, 0x03, 0x0f, 0x01, 0xd1, 0x00, 0x01, 0x12, 0x1f, -0x83, 0x0f, 0x01, 0xd1, 0x80, 0x00, 0x92, 0x1e, 0x00, 0x28, 0x01, 0xdb, 0x40, 0x00, 0x52, 0x1e, -0x12, 0x05, 0x51, 0x18, 0x42, 0x05, 0xc0, 0x12, 0x41, 0x18, 0x10, 0x46, 0x70, 0x47, 0xc1, 0x0f, -0xc9, 0x07, 0x00, 0xd0, 0x40, 0x42, 0x01, 0x22, 0x92, 0x07, 0x11, 0x43, 0xd6, 0xe7, 0x01, 0x21, -0x89, 0x07, 0xd3, 0xe7, 0xf0, 0xb5, 0x8b, 0x4c, 0x0f, 0x09, 0x25, 0x46, 0x89, 0xb0, 0xbd, 0x43, -0x7b, 0xd0, 0x1d, 0x09, 0x26, 0x46, 0xae, 0x43, 0xfa, 0xd0, 0x0e, 0x46, 0x5e, 0x40, 0x27, 0x40, -0xf6, 0x0f, 0x3e, 0x43, 0x25, 0x40, 0x71, 0xd0, 0x24, 0x01, 0x21, 0x42, 0xfb, 0xd0, 0xff, 0x24, -0xad, 0x19, 0xa4, 0x04, 0x2d, 0x1b, 0x03, 0x95, 0x01, 0x25, 0x2d, 0x05, 0xdb, 0x02, 0xdb, 0x0a, -0xc9, 0x02, 0x2b, 0x43, 0xc9, 0x0a, 0x29, 0x43, 0x1e, 0x01, 0x09, 0x01, 0x04, 0x0f, 0x13, 0x0f, -0x05, 0x01, 0x21, 0x43, 0x17, 0x01, 0x88, 0x0b, 0x82, 0x03, 0x91, 0x43, 0x2d, 0x09, 0x8c, 0x46, -0xa9, 0x0b, 0x1e, 0x43, 0x8a, 0x03, 0x95, 0x43, 0xb3, 0x0b, 0x9a, 0x03, 0x96, 0x43, 0x3f, 0x09, -0xba, 0x0b, 0x94, 0x03, 0xa7, 0x43, 0x02, 0x96, 0x2e, 0x46, 0x7e, 0x43, 0x04, 0x97, 0xb6, 0x46, -0x4e, 0x19, 0xd7, 0x19, 0x0c, 0x46, 0x01, 0x96, 0x54, 0x43, 0x05, 0x97, 0x7e, 0x43, 0x37, 0x1b, -0x76, 0x46, 0xbf, 0x1b, 0x36, 0x01, 0xb6, 0x46, 0xbe, 0x0b, 0x36, 0x19, 0x00, 0x96, 0x76, 0x46, -0xbc, 0x04, 0x37, 0x19, 0x00, 0x9c, 0x01, 0xd3, 0x64, 0x1c, 0x00, 0x94, 0x64, 0x00, 0x00, 0x2f, -0x01, 0xd0, 0x01, 0x26, 0x34, 0x43, 0x02, 0x9e, 0x04, 0x9f, 0x75, 0x43, 0x66, 0x46, 0x7e, 0x43, -0x04, 0x96, 0x76, 0x00, 0x34, 0x19, 0x6e, 0x00, 0x34, 0x19, 0x00, 0x94, 0x02, 0x9c, 0x01, 0x9e, -0x1c, 0x19, 0x66, 0x43, 0x75, 0x1b, 0xae, 0x46, 0x06, 0x94, 0x65, 0x46, 0x45, 0x19, 0x05, 0x9c, -0x05, 0x95, 0x6c, 0x43, 0x59, 0x43, 0x75, 0x46, 0x08, 0x91, 0x69, 0x1a, 0x01, 0x91, 0x04, 0x9e, -0x01, 0x46, 0x51, 0x43, 0xa4, 0x1b, 0x04, 0x91, 0x61, 0x1a, 0x00, 0x9c, 0x07, 0x91, 0xe1, 0x06, -0x05, 0xd0, 0x61, 0x09, 0x01, 0x22, 0x11, 0x43, 0x02, 0xe0, 0x72, 0xe0, 0x6e, 0xe0, 0x61, 0x09, -0x08, 0x9d, 0x00, 0x27, 0x2c, 0x0a, 0x2d, 0x06, 0x69, 0x18, 0x04, 0x9d, 0x7c, 0x41, 0x2a, 0x0a, -0x2d, 0x06, 0x69, 0x18, 0x01, 0x9d, 0x62, 0x41, 0xac, 0x0d, 0xad, 0x02, 0x6d, 0x18, 0x54, 0x41, -0x07, 0x9a, 0x91, 0x0d, 0x92, 0x02, 0x55, 0x19, 0x61, 0x41, 0x02, 0x9a, 0x64, 0x46, 0x58, 0x43, -0x54, 0x43, 0x06, 0x9b, 0x05, 0x9a, 0x5a, 0x43, 0x12, 0x1a, 0x13, 0x1b, 0x9a, 0x0e, 0x9b, 0x01, -0x5b, 0x18, 0x7a, 0x41, 0x01, 0x0b, 0x00, 0x05, 0xc3, 0x18, 0x51, 0x41, 0x22, 0x0a, 0x20, 0x06, -0x44, 0x19, 0x5a, 0x41, 0x9a, 0x42, 0x00, 0xd2, 0x49, 0x1c, 0x01, 0x20, 0x40, 0x02, 0x81, 0x42, -0x03, 0xd3, 0x15, 0x23, 0x02, 0x26, 0xf6, 0x43, 0x02, 0xe0, 0x14, 0x23, 0x03, 0x26, 0xf6, 0x43, -0x20, 0x20, 0xc5, 0x1a, 0xa9, 0x40, 0x17, 0x46, 0xaf, 0x40, 0xda, 0x40, 0x0a, 0x43, 0x20, 0x46, -0x03, 0x99, 0xd8, 0x40, 0x09, 0x14, 0x73, 0x18, 0x19, 0x05, 0x51, 0x18, 0x03, 0x9a, 0x38, 0x43, -0xd2, 0x07, 0x51, 0x40, 0xac, 0x40, 0x09, 0xd0, 0x01, 0x22, 0x94, 0x40, 0x06, 0xd3, 0x00, 0x22, -0x40, 0x1c, 0x51, 0x41, 0x00, 0x2c, 0x01, 0xd1, 0x40, 0x08, 0x40, 0x00, 0x1e, 0x4a, 0x93, 0x42, -0x12, 0xd3, 0x01, 0x22, 0x03, 0x98, 0x92, 0x06, 0x90, 0x42, 0x07, 0xdb, 0x05, 0x20, 0x40, 0x07, -0x09, 0x18, 0x1a, 0x48, 0x01, 0x43, 0xc0, 0x12, 0x41, 0x40, 0x04, 0xe0, 0x03, 0x20, 0x40, 0x07, -0x08, 0x18, 0xc1, 0x0f, 0xc9, 0x07, 0x00, 0x20, 0x09, 0xb0, 0xf0, 0xbd, 0x00, 0x20, 0xf1, 0x07, -0xfa, 0xe7, 0x05, 0x18, 0x0c, 0x46, 0x4c, 0x41, 0x11, 0x48, 0x6d, 0x42, 0xa0, 0x41, 0x15, 0xd3, -0x94, 0x18, 0x1a, 0x46, 0x5a, 0x41, 0x0e, 0x48, 0x64, 0x42, 0x90, 0x41, 0x0e, 0xd3, 0x01, 0x20, -0x4a, 0x00, 0x40, 0x05, 0x82, 0x42, 0x09, 0xd3, 0x5a, 0x00, 0x82, 0x42, 0x06, 0xd3, 0x59, 0x40, -0xc9, 0x0f, 0x08, 0x4a, 0xc9, 0x07, 0x00, 0x20, 0x11, 0x43, 0xdd, 0xe7, 0x00, 0x20, 0x06, 0x49, -0xda, 0xe7, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0xfe, 0x07, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, -0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0xf8, 0x7f, 0xfe, 0xb5, 0x05, 0x46, -0x10, 0x46, 0x0c, 0x46, 0x18, 0x43, 0x73, 0xd0, 0xae, 0x46, 0x8c, 0x46, 0x00, 0x20, 0xad, 0x1a, -0x01, 0x46, 0x9c, 0x41, 0x67, 0xd3, 0x66, 0x46, 0x00, 0x27, 0x01, 0x24, 0x3d, 0x46, 0xb6, 0x1a, -0x9d, 0x41, 0x02, 0xd3, 0x13, 0x46, 0x3a, 0x46, 0x21, 0x24, 0x65, 0x46, 0x76, 0x46, 0x2f, 0x04, -0x36, 0x0c, 0x3e, 0x43, 0x2d, 0x0c, 0xb6, 0x1a, 0x9d, 0x41, 0x04, 0xd3, 0x15, 0x0c, 0x1b, 0x04, -0x2b, 0x43, 0x12, 0x04, 0x10, 0x34, 0x65, 0x46, 0x76, 0x46, 0x2f, 0x06, 0x36, 0x0a, 0x3e, 0x43, -0x2d, 0x0a, 0xb6, 0x1a, 0x9d, 0x41, 0x04, 0xd3, 0x15, 0x0e, 0x1b, 0x02, 0x2b, 0x43, 0x12, 0x02, -0x08, 0x34, 0x65, 0x46, 0x76, 0x46, 0x2f, 0x07, 0x36, 0x09, 0x3e, 0x43, 0x2d, 0x09, 0xb6, 0x1a, -0x9d, 0x41, 0x04, 0xd3, 0x15, 0x0f, 0x1b, 0x01, 0x2b, 0x43, 0x12, 0x01, 0x24, 0x1d, 0x65, 0x46, -0x76, 0x46, 0xaf, 0x07, 0xb6, 0x08, 0x3e, 0x43, 0xad, 0x08, 0xb6, 0x1a, 0x9d, 0x41, 0x04, 0xd3, -0x95, 0x0f, 0x9b, 0x00, 0x2b, 0x43, 0x92, 0x00, 0xa4, 0x1c, 0x65, 0x46, 0x76, 0x46, 0xef, 0x07, -0x76, 0x08, 0x3e, 0x43, 0x6d, 0x08, 0xb6, 0x1a, 0x9d, 0x41, 0x1a, 0xd3, 0x92, 0x18, 0x5b, 0x41, -0x64, 0x1c, 0x16, 0xe0, 0x00, 0x18, 0x76, 0x46, 0x65, 0x46, 0x49, 0x41, 0xb7, 0x1a, 0x9d, 0x41, -0x01, 0x91, 0x00, 0x90, 0x09, 0xd3, 0x60, 0x46, 0xb1, 0x1a, 0x98, 0x41, 0x8e, 0x46, 0x84, 0x46, -0x00, 0x98, 0x01, 0x99, 0x00, 0x25, 0x40, 0x1c, 0x69, 0x41, 0xdd, 0x07, 0x52, 0x08, 0x2a, 0x43, -0x5b, 0x08, 0x64, 0x1e, 0xe6, 0xd5, 0x72, 0x46, 0x63, 0x46, 0x03, 0xb0, 0xf0, 0xbd, 0xff, 0xe7, -0x00, 0x20, 0x01, 0x46, 0xc0, 0x46, 0xc0, 0x46, 0x2a, 0x46, 0x23, 0x46, 0xf5, 0xe7, 0x75, 0x46, -0x00, 0xf0, 0x24, 0xf8, 0xae, 0x46, 0x05, 0x00, 0x69, 0x46, 0x53, 0x46, 0xc0, 0x08, 0xc0, 0x00, -0x85, 0x46, 0x18, 0xb0, 0x20, 0xb5, 0xff, 0xf7, 0x89, 0xfa, 0x60, 0xbc, 0x00, 0x27, 0x49, 0x08, -0xb6, 0x46, 0x00, 0x26, 0xc0, 0xc5, 0xc0, 0xc5, 0xc0, 0xc5, 0xc0, 0xc5, 0xc0, 0xc5, 0xc0, 0xc5, -0xc0, 0xc5, 0xc0, 0xc5, 0x40, 0x3d, 0x49, 0x00, 0x8d, 0x46, 0x70, 0x47, 0x10, 0xb5, 0x04, 0x46, -0xc0, 0x46, 0xc0, 0x46, 0x20, 0x46, 0xff, 0xf7, 0x30, 0xfa, 0x10, 0xbd, 0x00, 0x48, 0x70, 0x47, -0xe0, 0x38, 0x01, 0x20, 0x01, 0x49, 0x18, 0x20, 0xab, 0xbe, 0xfe, 0xe7, 0x26, 0x00, 0x02, 0x00, -0x70, 0x47, 0x70, 0xb5, 0x8c, 0x18, 0x05, 0x78, 0x40, 0x1c, 0x6b, 0x07, 0x5b, 0x0f, 0x01, 0xd1, -0x03, 0x78, 0x40, 0x1c, 0x2a, 0x11, 0x06, 0xd1, 0x02, 0x78, 0x40, 0x1c, 0x03, 0xe0, 0x06, 0x78, -0x40, 0x1c, 0x0e, 0x70, 0x49, 0x1c, 0x5b, 0x1e, 0xf9, 0xd1, 0x2b, 0x07, 0x05, 0xd4, 0x00, 0x23, -0x52, 0x1e, 0x0d, 0xd4, 0x0b, 0x70, 0x49, 0x1c, 0xfa, 0xe7, 0x03, 0x78, 0x40, 0x1c, 0xcb, 0x1a, -0x92, 0x1c, 0x03, 0xe0, 0x1d, 0x78, 0x0d, 0x70, 0x49, 0x1c, 0x5b, 0x1c, 0x52, 0x1e, 0xf9, 0xd5, -0xa1, 0x42, 0xd8, 0xd3, 0x00, 0x20, 0x70, 0xbd, 0x70, 0x47, 0x00, 0x00, 0xf0, 0xb5, 0x96, 0x46, -0x8c, 0x46, 0x02, 0x03, 0x01, 0x23, 0x00, 0x21, 0x12, 0x0e, 0x3c, 0x2a, 0x0b, 0xd0, 0x20, 0x4a, -0x90, 0x42, 0x08, 0xd0, 0x52, 0x1c, 0x90, 0x42, 0x05, 0xd0, 0xd2, 0x1c, 0x90, 0x42, 0x02, 0xd0, -0x52, 0x1c, 0x90, 0x42, 0x00, 0xd1, 0x00, 0x23, 0x1a, 0x4a, 0x14, 0x7b, 0x1a, 0x4d, 0x2c, 0x70, -0x1a, 0x4c, 0x26, 0x7d, 0x6e, 0x70, 0x16, 0x7b, 0x01, 0x27, 0x3e, 0x43, 0x16, 0x73, 0x18, 0x4e, -0x00, 0x2b, 0x0a, 0xd0, 0x32, 0x8a, 0x6a, 0x80, 0xb2, 0x8a, 0xaa, 0x80, 0x27, 0x75, 0x15, 0x4a, -0x32, 0x82, 0x15, 0x4a, 0xb2, 0x82, 0x00, 0x22, 0x22, 0x75, 0x62, 0x46, 0x00, 0x2a, 0x01, 0xd0, -0x01, 0x78, 0x04, 0xe0, 0x27, 0x75, 0x72, 0x46, 0x02, 0x70, 0x00, 0x20, 0x20, 0x75, 0x00, 0x2b, -0x06, 0xd0, 0x27, 0x75, 0x68, 0x88, 0x30, 0x82, 0xa8, 0x88, 0xb0, 0x82, 0x00, 0x20, 0x20, 0x75, -0x68, 0x78, 0x20, 0x75, 0x03, 0x48, 0x2a, 0x78, 0x02, 0x73, 0x08, 0x46, 0xf0, 0xbd, 0x00, 0x00, -0xf0, 0xdf, 0x03, 0x00, 0x20, 0x00, 0x03, 0x40, 0x0c, 0x01, 0x01, 0x20, 0x60, 0x00, 0x03, 0x40, -0xe0, 0xdf, 0x03, 0x40, 0x5a, 0x59, 0x00, 0x00, 0xa5, 0xa6, 0x00, 0x00, 0x70, 0xb5, 0x04, 0x46, -0x15, 0x46, 0x0e, 0x46, 0x08, 0x20, 0x04, 0xf0, 0x4b, 0xfc, 0x76, 0x1e, 0xf1, 0xb2, 0x6d, 0x1e, -0x12, 0x23, 0xea, 0xb2, 0x59, 0x43, 0x89, 0x18, 0x89, 0x00, 0x42, 0x5a, 0x6f, 0x23, 0x12, 0x19, -0x12, 0xb2, 0x6f, 0x2a, 0x01, 0xdc, 0x10, 0x2a, 0x01, 0xda, 0x43, 0x50, 0x70, 0xbd, 0x42, 0x50, -0x70, 0xbd, 0x00, 0x00, 0xf8, 0xb5, 0x94, 0x46, 0x02, 0x46, 0x09, 0x98, 0x13, 0x4c, 0x00, 0x07, -0x00, 0x0f, 0x06, 0x9f, 0x07, 0x9e, 0x08, 0x9d, 0x60, 0x70, 0x90, 0x06, 0x80, 0x0e, 0xa0, 0x70, -0xe1, 0x70, 0x63, 0x60, 0xa7, 0x60, 0x26, 0x61, 0xe5, 0x60, 0x60, 0x46, 0x00, 0x07, 0x00, 0x0f, -0x20, 0x70, 0x60, 0x69, 0x03, 0x21, 0x08, 0x43, 0x60, 0x61, 0x01, 0x20, 0x0d, 0xf0, 0xfc, 0xfc, -0x60, 0x7d, 0xc0, 0x07, 0x04, 0xd0, 0x0d, 0xf0, 0x33, 0xfb, 0x60, 0x7d, 0xc0, 0x07, 0xfa, 0xd1, -0x60, 0x69, 0x02, 0x21, 0x88, 0x43, 0x60, 0x61, 0xf8, 0xbd, 0x00, 0x00, 0x00, 0x60, 0x03, 0x40, -0xf8, 0xb5, 0x9c, 0x46, 0x07, 0x9c, 0x83, 0x06, 0xe5, 0x0f, 0x14, 0x48, 0x9b, 0x0e, 0x06, 0x9f, -0x08, 0x9e, 0x03, 0x75, 0x89, 0x06, 0x89, 0x0e, 0x41, 0x75, 0x91, 0x06, 0x89, 0x0e, 0x81, 0x75, -0xc5, 0x75, 0x61, 0x46, 0x01, 0x82, 0x47, 0x82, 0x00, 0x2c, 0x00, 0xda, 0x64, 0x42, 0x04, 0x83, -0x46, 0x83, 0x0b, 0x4c, 0xe0, 0x6b, 0x03, 0x21, 0x08, 0x43, 0xe0, 0x63, 0x01, 0x20, 0x0d, 0xf0, -0xcb, 0xfc, 0x60, 0x7d, 0x00, 0x07, 0x04, 0xd5, 0x0d, 0xf0, 0x02, 0xfb, 0x60, 0x7d, 0x00, 0x07, -0xfa, 0xd4, 0xe0, 0x6b, 0x02, 0x21, 0x88, 0x43, 0xe0, 0x63, 0xf8, 0xbd, 0x20, 0x60, 0x03, 0x40, -0x00, 0x60, 0x03, 0x40, 0x70, 0x47, 0x70, 0x47, 0xf0, 0xb4, 0x5a, 0x48, 0x5a, 0x49, 0x02, 0x7e, -0x5c, 0x48, 0x10, 0x25, 0x00, 0x78, 0x59, 0x4c, 0xc0, 0x06, 0x59, 0x4b, 0xc0, 0x0e, 0x01, 0x2a, -0x49, 0xd0, 0x92, 0x1e, 0xfd, 0x2a, 0x44, 0xd2, 0x22, 0x7e, 0xf7, 0x27, 0x3a, 0x40, 0x40, 0x26, -0x32, 0x43, 0x22, 0x76, 0x54, 0x4e, 0x32, 0x7e, 0x3a, 0x40, 0x40, 0x27, 0x3a, 0x43, 0x32, 0x76, -0x1a, 0x78, 0x2a, 0x43, 0x1a, 0x70, 0x51, 0x4a, 0x13, 0x78, 0x2b, 0x43, 0x13, 0x70, 0x50, 0x4a, -0x13, 0x78, 0xf3, 0x27, 0x3b, 0x40, 0x1b, 0x1d, 0x13, 0x70, 0x4e, 0x4b, 0x1d, 0x78, 0x3d, 0x40, -0x2d, 0x1d, 0x1d, 0x70, 0x15, 0x79, 0xe1, 0x27, 0x3d, 0x40, 0x05, 0x27, 0x3d, 0x43, 0x15, 0x71, -0x1d, 0x79, 0xe1, 0x27, 0x3d, 0x40, 0x05, 0x27, 0x3d, 0x43, 0x1d, 0x71, 0x17, 0x7b, 0x0c, 0x25, -0x2f, 0x43, 0x17, 0x73, 0x1a, 0x7b, 0x2a, 0x43, 0x1a, 0x73, 0x0a, 0x7e, 0xdf, 0x23, 0x1a, 0x40, -0x14, 0x23, 0x1a, 0x43, 0x0a, 0x76, 0x40, 0x49, 0x0a, 0x78, 0x52, 0x09, 0x52, 0x01, 0x02, 0x43, -0x0a, 0x70, 0x0a, 0x79, 0x52, 0x09, 0x52, 0x01, 0x02, 0x43, 0x0a, 0x71, 0xa0, 0x20, 0x20, 0x70, -0x30, 0x70, 0xf0, 0xbc, 0x70, 0x47, 0x0a, 0x7e, 0xdf, 0x26, 0x32, 0x40, 0x54, 0x26, 0x32, 0x43, -0x0a, 0x76, 0x35, 0x4a, 0x10, 0x70, 0x12, 0x79, 0x52, 0x09, 0x52, 0x01, 0x02, 0x43, 0x32, 0x48, -0x02, 0x71, 0x00, 0x7a, 0x30, 0x4a, 0x28, 0x43, 0x10, 0x72, 0x08, 0x7c, 0x02, 0x26, 0x0e, 0x74, -0x08, 0x7d, 0x01, 0x20, 0x08, 0x75, 0x2d, 0x48, 0x02, 0x7c, 0x01, 0x27, 0x3a, 0x43, 0x02, 0x74, -0x2b, 0x48, 0x02, 0x7c, 0x3a, 0x43, 0x02, 0x74, 0x20, 0x7e, 0xf7, 0x22, 0x10, 0x40, 0x40, 0x27, -0x38, 0x43, 0x20, 0x76, 0x20, 0x4c, 0x20, 0x7e, 0x10, 0x40, 0x38, 0x43, 0x20, 0x76, 0x18, 0x79, -0xd7, 0x24, 0x20, 0x40, 0x18, 0x71, 0x1d, 0x4a, 0x10, 0x79, 0x20, 0x40, 0x10, 0x71, 0x1c, 0x48, -0x00, 0x7b, 0x0d, 0x27, 0x1a, 0x4c, 0x38, 0x43, 0x20, 0x73, 0x1a, 0x48, 0x04, 0x7b, 0x3c, 0x43, -0x04, 0x73, 0x17, 0x4c, 0x24, 0x79, 0xe5, 0x27, 0x3c, 0x40, 0x05, 0x27, 0x3c, 0x43, 0x14, 0x4f, -0x3c, 0x71, 0x04, 0x79, 0xc5, 0x24, 0x04, 0x71, 0x1c, 0x78, 0x2c, 0x43, 0x1c, 0x70, 0x13, 0x78, -0x2b, 0x43, 0x13, 0x70, 0x3b, 0x78, 0x94, 0x24, 0x23, 0x40, 0x14, 0x22, 0x13, 0x43, 0x3b, 0x70, -0x03, 0x78, 0x23, 0x40, 0x13, 0x43, 0x03, 0x70, 0x0e, 0x74, 0x01, 0x20, 0x08, 0x75, 0xf0, 0xbc, -0x70, 0x47, 0x00, 0x00, 0x28, 0x0d, 0x01, 0x20, 0x20, 0x14, 0x03, 0x40, 0x00, 0x11, 0x03, 0x40, -0x40, 0x11, 0x03, 0x40, 0xa8, 0x0d, 0x01, 0x20, 0x00, 0x13, 0x03, 0x40, 0x40, 0x13, 0x03, 0x40, -0x60, 0x11, 0x03, 0x40, 0x60, 0x13, 0x03, 0x40, 0x40, 0x14, 0x03, 0x40, 0xa0, 0x11, 0x03, 0x40, -0xa0, 0x13, 0x03, 0x40, 0xf0, 0xb5, 0x80, 0x48, 0x89, 0xb0, 0xc5, 0x7f, 0x7f, 0x48, 0x6e, 0x23, -0x42, 0x7e, 0x00, 0x92, 0x2a, 0x46, 0x5a, 0x43, 0x7d, 0x4b, 0x00, 0x7e, 0x00, 0x21, 0xd3, 0x18, -0x49, 0x24, 0x84, 0x46, 0x64, 0x01, 0x7a, 0x48, 0x42, 0x18, 0x09, 0x20, 0x00, 0x02, 0x10, 0x18, -0x86, 0x7d, 0x04, 0x2e, 0x11, 0xd0, 0x00, 0x2e, 0x15, 0xd0, 0x02, 0x26, 0x86, 0x75, 0x0a, 0x26, -0x4e, 0x43, 0x9f, 0x19, 0x31, 0x26, 0x76, 0x01, 0xbe, 0x19, 0xb6, 0x7f, 0x00, 0x2e, 0x29, 0xd0, -0x00, 0x26, 0x10, 0x19, 0x06, 0x73, 0x46, 0x70, 0x34, 0xe0, 0x00, 0x26, 0x86, 0x75, 0x10, 0x19, -0x06, 0x73, 0x46, 0x70, 0x2e, 0xe0, 0x0a, 0x26, 0x4e, 0x43, 0x9f, 0x19, 0x31, 0x26, 0x76, 0x01, -0xbe, 0x19, 0xb6, 0x7f, 0x00, 0x2e, 0xeb, 0xd0, 0x16, 0x19, 0x32, 0x7b, 0x00, 0x2a, 0x00, 0xd1, -0xc5, 0x72, 0x52, 0x1c, 0xd2, 0xb2, 0x32, 0x73, 0x62, 0x4e, 0x76, 0x79, 0x03, 0x2e, 0x05, 0xd0, -0x00, 0x9e, 0xb2, 0x42, 0x16, 0xd9, 0x01, 0x22, 0x82, 0x75, 0x13, 0xe0, 0x00, 0x2a, 0x11, 0xd0, -0x01, 0x22, 0x0e, 0xe0, 0x16, 0x19, 0x72, 0x78, 0x52, 0x1c, 0xd2, 0xb2, 0x72, 0x70, 0x59, 0x4e, -0x76, 0x79, 0x03, 0x2e, 0x02, 0xd0, 0x62, 0x45, 0x02, 0xd8, 0x03, 0xe0, 0x00, 0x2a, 0x01, 0xd0, -0x04, 0x22, 0x82, 0x75, 0x49, 0x1c, 0xc9, 0xb2, 0x0b, 0x29, 0xac, 0xd3, 0x52, 0x48, 0x00, 0x25, -0xc6, 0x7c, 0x28, 0xe0, 0xa8, 0x42, 0x0b, 0xd9, 0x4d, 0x49, 0x09, 0x22, 0x12, 0x02, 0x4b, 0x19, -0x9b, 0x18, 0x9b, 0x7d, 0x00, 0x2b, 0x03, 0xd0, 0x6d, 0x1c, 0xed, 0xb2, 0xa8, 0x42, 0xf6, 0xd8, -0xa8, 0x42, 0x18, 0xd9, 0x0b, 0x2e, 0x16, 0xd2, 0x45, 0x4a, 0x09, 0x21, 0x09, 0x02, 0x49, 0x20, -0x97, 0x19, 0x40, 0x01, 0x38, 0x18, 0x40, 0x78, 0x00, 0x28, 0x08, 0xd1, 0x78, 0x18, 0x02, 0x90, -0x80, 0x7d, 0x01, 0x28, 0x0f, 0xd0, 0x02, 0x28, 0x0d, 0xd0, 0x03, 0x28, 0x0b, 0xd0, 0x76, 0x1c, -0xf6, 0xb2, 0x0b, 0x2e, 0xeb, 0xd3, 0x3c, 0x48, 0xc0, 0x7c, 0xa8, 0x42, 0x01, 0xd9, 0x0b, 0x2e, -0xd0, 0xd3, 0x09, 0xb0, 0xf0, 0xbd, 0x36, 0x4c, 0x01, 0x23, 0x60, 0x19, 0x01, 0x90, 0x40, 0x18, -0x00, 0x90, 0x83, 0x75, 0xa0, 0x19, 0x40, 0x18, 0x04, 0x22, 0x82, 0x75, 0x30, 0x46, 0x0a, 0x21, -0x48, 0x43, 0x07, 0x90, 0x31, 0x4b, 0x00, 0x19, 0xc1, 0x18, 0x28, 0x46, 0x0a, 0x22, 0x50, 0x43, -0x06, 0x90, 0x00, 0x19, 0xc0, 0x18, 0xff, 0xf7, 0x47, 0xf8, 0x28, 0x46, 0x06, 0x21, 0x48, 0x43, -0x05, 0x90, 0x00, 0x24, 0x30, 0x46, 0x48, 0x43, 0x04, 0x90, 0x6e, 0x20, 0x24, 0x49, 0x60, 0x43, -0x40, 0x18, 0x07, 0x99, 0x26, 0x4a, 0x41, 0x18, 0x06, 0x9b, 0x03, 0x91, 0xc0, 0x18, 0x89, 0x18, -0x80, 0x18, 0x0a, 0x22, 0xff, 0xf7, 0x30, 0xf8, 0x42, 0x20, 0x60, 0x43, 0x1c, 0x49, 0x21, 0x4a, -0x40, 0x18, 0x05, 0x99, 0x04, 0x9b, 0x41, 0x18, 0xc0, 0x18, 0x89, 0x18, 0x80, 0x18, 0x82, 0x8a, -0x8a, 0x82, 0xc2, 0x8a, 0xca, 0x82, 0x00, 0x8b, 0x08, 0x83, 0x31, 0x22, 0x03, 0x99, 0x52, 0x01, -0x00, 0x20, 0x89, 0x18, 0x64, 0x1c, 0xe4, 0xb2, 0x88, 0x77, 0x04, 0x2c, 0xd5, 0xd3, 0x02, 0x98, -0x01, 0x78, 0x00, 0x98, 0x01, 0x70, 0x02, 0x98, 0xc1, 0x7a, 0x00, 0x98, 0xc1, 0x72, 0x49, 0x21, -0x49, 0x01, 0x78, 0x18, 0x01, 0x9b, 0x42, 0x78, 0x59, 0x18, 0x4a, 0x70, 0x02, 0x7b, 0x0a, 0x73, -0xc0, 0x7d, 0xc8, 0x75, 0x25, 0x21, 0x89, 0x01, 0x78, 0x18, 0x01, 0x9b, 0x82, 0x78, 0x59, 0x18, -0x8a, 0x70, 0xc0, 0x7b, 0xc8, 0x73, 0x8e, 0xe7, 0x24, 0x2d, 0x01, 0x20, 0x48, 0x0d, 0x01, 0x20, -0x44, 0x24, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0x62, 0x05, 0x00, 0x00, -0x3e, 0x06, 0x00, 0x00, 0xe2, 0x07, 0x00, 0x00, 0xf0, 0xb5, 0xa6, 0x48, 0x8f, 0xb0, 0xc1, 0x7f, -0x00, 0x29, 0x02, 0xd0, 0x48, 0x1e, 0xc6, 0xb2, 0x00, 0xe0, 0x03, 0x26, 0xa2, 0x4c, 0xa0, 0x7e, -0x0b, 0x28, 0x01, 0xd9, 0x0b, 0x20, 0xa0, 0x76, 0x00, 0x20, 0xa0, 0x4a, 0x07, 0x46, 0x45, 0x00, -0x6b, 0x46, 0x5a, 0x53, 0x06, 0xab, 0x1f, 0x54, 0x40, 0x1c, 0xc0, 0xb2, 0x0b, 0x28, 0xf6, 0xd3, -0x6e, 0x20, 0x9b, 0x4f, 0x41, 0x43, 0xc8, 0x19, 0x9a, 0x49, 0x0d, 0x90, 0x41, 0x18, 0x6e, 0x22, -0x99, 0x48, 0xfe, 0xf7, 0xc1, 0xff, 0x99, 0x4a, 0x00, 0x20, 0x15, 0x89, 0x80, 0x3d, 0x29, 0xb2, -0x0c, 0x91, 0x97, 0x49, 0x52, 0x89, 0x4b, 0x7e, 0x09, 0x7e, 0x1b, 0x02, 0x0b, 0x43, 0x59, 0x08, -0x52, 0x1a, 0x09, 0x92, 0x12, 0xb2, 0x0b, 0x92, 0x6e, 0x22, 0x56, 0x43, 0x3a, 0x46, 0xb2, 0x18, -0x0a, 0x92, 0x8b, 0x4a, 0x13, 0x18, 0x49, 0x22, 0x52, 0x01, 0x9a, 0x18, 0xd2, 0x7d, 0x02, 0x2a, -0x2e, 0xd1, 0x0a, 0x23, 0x06, 0x46, 0x5e, 0x43, 0x0d, 0x9a, 0x0a, 0x9f, 0x93, 0x19, 0xb4, 0x46, -0xbe, 0x19, 0x19, 0x22, 0x19, 0x27, 0x92, 0x01, 0xbf, 0x01, 0x9b, 0x18, 0xf6, 0x19, 0x1a, 0x88, -0x37, 0x88, 0x5b, 0x88, 0x76, 0x88, 0xd7, 0x1b, 0x9e, 0x1b, 0xba, 0x18, 0xf3, 0x18, 0x12, 0xb2, -0x1b, 0xb2, 0x80, 0x2a, 0x01, 0xda, 0x80, 0x22, 0x02, 0xe0, 0x95, 0x42, 0x00, 0xda, 0x0c, 0x9a, -0x99, 0x42, 0x01, 0xdd, 0x0b, 0x46, 0x03, 0xe0, 0x09, 0x9e, 0x9e, 0x42, 0x00, 0xda, 0x0b, 0x9b, -0x73, 0x4e, 0x67, 0x46, 0xbf, 0x19, 0x17, 0x26, 0xb6, 0x01, 0xbe, 0x19, 0x72, 0x82, 0xb3, 0x82, -0x40, 0x1c, 0xc0, 0xb2, 0x0b, 0x28, 0xc4, 0xd3, 0xa0, 0x7e, 0x00, 0x26, 0x00, 0x28, 0x35, 0xd9, -0x0c, 0x20, 0x6b, 0x49, 0x70, 0x43, 0xff, 0x22, 0x40, 0x18, 0x3f, 0x32, 0x12, 0x5a, 0x0b, 0x92, -0xff, 0x22, 0x41, 0x32, 0x12, 0x5a, 0x00, 0x25, 0x77, 0x00, 0xff, 0x30, 0x21, 0x30, 0x0a, 0x92, -0x09, 0x90, 0x0a, 0x20, 0x29, 0x46, 0x41, 0x43, 0x61, 0x48, 0x09, 0x18, 0x17, 0x20, 0x80, 0x01, -0x09, 0x18, 0x08, 0x7c, 0x00, 0x28, 0x10, 0xd0, 0x48, 0x8a, 0x89, 0x8a, 0x0a, 0x9a, 0x51, 0x1a, -0x0b, 0x9a, 0x09, 0xb2, 0x10, 0x1a, 0x00, 0xb2, 0x00, 0xf0, 0xbe, 0xfb, 0x6a, 0x46, 0xd1, 0x5b, -0x81, 0x42, 0x02, 0xd9, 0xd0, 0x53, 0x09, 0x99, 0x0d, 0x77, 0x6d, 0x1c, 0xed, 0xb2, 0x0b, 0x2d, -0xdf, 0xd3, 0x76, 0x1c, 0xa0, 0x7e, 0xf6, 0xb2, 0xb0, 0x42, 0xc9, 0xd8, 0x00, 0x21, 0x00, 0x06, -0x00, 0x0e, 0x38, 0xd0, 0x48, 0x1c, 0x09, 0x90, 0xa2, 0x7e, 0xc0, 0xb2, 0x82, 0x42, 0x21, 0xd9, -0x4a, 0x00, 0x94, 0x46, 0x0c, 0x22, 0x4a, 0x4b, 0x4a, 0x43, 0xd2, 0x18, 0xff, 0x32, 0x21, 0x32, -0x15, 0x7f, 0x47, 0x4b, 0xff, 0x2d, 0x21, 0xd0, 0x0c, 0x26, 0x46, 0x43, 0xf3, 0x18, 0xff, 0x33, -0x21, 0x33, 0x1e, 0x7f, 0xb5, 0x42, 0x08, 0xd1, 0x66, 0x46, 0x6d, 0x46, 0xae, 0x5b, 0x47, 0x00, -0xed, 0x5b, 0xae, 0x42, 0x2c, 0xd8, 0xff, 0x25, 0x1d, 0x77, 0x40, 0x1c, 0xa3, 0x7e, 0xc0, 0xb2, -0x83, 0x42, 0xe5, 0xd8, 0x0c, 0x20, 0x41, 0x43, 0x39, 0x48, 0x08, 0x18, 0xff, 0x30, 0x21, 0x30, -0x00, 0x7f, 0xff, 0x28, 0x02, 0xd0, 0x01, 0x21, 0x06, 0xaa, 0x11, 0x54, 0x09, 0x98, 0xc1, 0xb2, -0xa0, 0x7e, 0x88, 0x42, 0xc6, 0xd8, 0x00, 0x21, 0x00, 0x06, 0x0a, 0x46, 0x00, 0x0e, 0x29, 0xd0, -0x34, 0x48, 0x06, 0xab, 0x00, 0x88, 0x84, 0x46, 0x0c, 0x20, 0x15, 0x46, 0x45, 0x43, 0x2c, 0x48, -0x28, 0x18, 0x06, 0x46, 0xff, 0x36, 0x21, 0x36, 0x35, 0x7f, 0xff, 0x2d, 0x03, 0xd0, 0x14, 0xe0, -0xff, 0x20, 0x10, 0x77, 0xe2, 0xe7, 0xff, 0x25, 0x43, 0x35, 0x45, 0x5f, 0x65, 0x45, 0x0c, 0xdb, -0xa5, 0x7e, 0x08, 0x46, 0x85, 0x42, 0x08, 0xd9, 0x49, 0x1c, 0x1f, 0x5c, 0xc9, 0xb2, 0x00, 0x2f, -0x34, 0xd0, 0x40, 0x1c, 0xc0, 0xb2, 0x85, 0x42, 0xf6, 0xd8, 0x52, 0x1c, 0xa0, 0x7e, 0xd2, 0xb2, -0x90, 0x42, 0xd9, 0xd8, 0x00, 0x22, 0x00, 0x06, 0x13, 0x46, 0x00, 0x0e, 0x22, 0xd0, 0x18, 0x4e, -0x1d, 0x4f, 0x0c, 0x20, 0x50, 0x43, 0xff, 0x21, 0x80, 0x19, 0x3d, 0x31, 0x09, 0x5c, 0xff, 0x29, -0x13, 0xd0, 0x0c, 0x21, 0x59, 0x43, 0x89, 0x19, 0x5b, 0x1c, 0xc9, 0x19, 0xff, 0x30, 0x3d, 0x30, -0x05, 0x88, 0x0d, 0x80, 0x45, 0x88, 0x4d, 0x80, 0x85, 0x88, 0x8d, 0x80, 0xc5, 0x88, 0xcd, 0x80, -0x05, 0x89, 0x0d, 0x81, 0x45, 0x89, 0xdb, 0xb2, 0x4d, 0x81, 0x52, 0x1c, 0xa0, 0x7e, 0xd2, 0xb2, -0x90, 0x42, 0xde, 0xd8, 0x0d, 0x48, 0x03, 0x71, 0x0f, 0xb0, 0xf0, 0xbd, 0x30, 0x77, 0x01, 0x25, -0x1d, 0x54, 0xca, 0xe7, 0x24, 0x2d, 0x01, 0x20, 0x64, 0x25, 0x01, 0x20, 0xff, 0xff, 0x00, 0x00, -0x44, 0x24, 0x01, 0x20, 0x3e, 0x06, 0x00, 0x00, 0x14, 0x2a, 0x01, 0x20, 0x84, 0x2e, 0x01, 0x20, -0xa9, 0x0d, 0x01, 0x20, 0x1a, 0x01, 0x01, 0x20, 0x46, 0x02, 0x00, 0x00, 0x84, 0x26, 0x01, 0x20, -0xf0, 0xb5, 0x83, 0xb0, 0x00, 0x27, 0x68, 0x46, 0x87, 0x80, 0x33, 0x48, 0x02, 0x24, 0xc0, 0x7e, -0x80, 0x06, 0x53, 0xd5, 0x08, 0x20, 0x04, 0xf0, 0x83, 0xf8, 0x02, 0x90, 0x05, 0xf0, 0x9e, 0xf8, -0x2f, 0x4e, 0x01, 0x21, 0x35, 0x46, 0x2d, 0x48, 0x80, 0x35, 0xff, 0x36, 0x01, 0x70, 0x61, 0x36, -0x7d, 0x20, 0xc0, 0x00, 0x05, 0xf0, 0xde, 0xfa, 0x28, 0x7f, 0x12, 0x28, 0x40, 0xd0, 0x00, 0x21, -0xaa, 0x20, 0x0a, 0xf0, 0x07, 0xfb, 0xbc, 0x21, 0x26, 0x48, 0x02, 0xf0, 0x50, 0xfb, 0x03, 0xf0, -0x3f, 0xf8, 0x09, 0xf0, 0xdf, 0xfe, 0x0c, 0xf0, 0x17, 0xff, 0x28, 0x7f, 0x12, 0x28, 0x32, 0xd0, -0x00, 0x21, 0xaa, 0x20, 0x0a, 0xf0, 0xf6, 0xfa, 0xbc, 0x21, 0x1e, 0x48, 0x02, 0xf0, 0x3f, 0xfb, -0x03, 0xf0, 0x14, 0xf8, 0x09, 0xf0, 0xa6, 0xff, 0x28, 0x7e, 0x01, 0x28, 0x17, 0x48, 0x25, 0xd0, -0x07, 0x70, 0x68, 0x46, 0x87, 0x80, 0x00, 0x94, 0x70, 0x7e, 0x33, 0x7e, 0x00, 0x06, 0x01, 0x14, -0x19, 0x43, 0xb2, 0x7e, 0x01, 0xab, 0x00, 0x20, 0x00, 0xf0, 0x5a, 0xfe, 0x64, 0x1e, 0xe4, 0xb2, -0x03, 0xf0, 0x56, 0xfe, 0x68, 0x46, 0x80, 0x88, 0x00, 0x28, 0x01, 0xd0, 0x00, 0x2c, 0xbf, 0xd1, -0x0d, 0x49, 0x01, 0x20, 0xc8, 0x73, 0x02, 0x98, 0x00, 0xf0, 0x60, 0xfa, 0x03, 0xb0, 0xf0, 0xbd, -0x00, 0xf0, 0x60, 0xfd, 0xc5, 0xe7, 0x00, 0xf0, 0xed, 0xfc, 0xd3, 0xe7, 0x01, 0x78, 0x00, 0x29, -0xd7, 0xd0, 0x07, 0x70, 0xe6, 0xe7, 0x00, 0x00, 0xa8, 0x0d, 0x01, 0x20, 0xdd, 0x00, 0x01, 0x20, -0xa8, 0x0c, 0x01, 0x20, 0x85, 0xd2, 0x03, 0x40, 0x8c, 0x03, 0x01, 0x20, 0xf0, 0xb5, 0x89, 0xb0, -0x02, 0x20, 0x05, 0x90, 0x08, 0x20, 0x04, 0xf0, 0x13, 0xf8, 0x00, 0x90, 0x59, 0x48, 0xc0, 0x7e, -0x00, 0x07, 0x6e, 0xd5, 0x05, 0xf0, 0xce, 0xf9, 0x57, 0x48, 0x01, 0x21, 0x01, 0x70, 0x58, 0x48, -0x03, 0x90, 0x58, 0x48, 0x07, 0x90, 0x55, 0x49, 0x57, 0x48, 0x04, 0x91, 0x01, 0x90, 0x7d, 0x20, -0xc0, 0x00, 0x05, 0xf0, 0x67, 0xfa, 0x04, 0x98, 0x00, 0x7f, 0x12, 0x28, 0x5a, 0xd0, 0xaa, 0x21, -0x00, 0x20, 0x0a, 0xf0, 0x8f, 0xfa, 0x3c, 0x21, 0x50, 0x48, 0x02, 0xf0, 0xd8, 0xfa, 0x05, 0xf0, -0x8d, 0xfd, 0x09, 0xf0, 0x67, 0xfe, 0x0c, 0xf0, 0x9f, 0xfe, 0x04, 0x98, 0x00, 0x7f, 0x12, 0x28, -0x4b, 0xd0, 0xaa, 0x21, 0x00, 0x20, 0x0a, 0xf0, 0x7d, 0xfa, 0x3c, 0x21, 0x47, 0x48, 0x02, 0xf0, -0xc6, 0xfa, 0x05, 0xf0, 0x61, 0xfd, 0x04, 0x98, 0x00, 0x7e, 0x01, 0x28, 0x40, 0xd0, 0x3e, 0x49, -0x00, 0x20, 0x08, 0x70, 0x20, 0x20, 0x03, 0xf0, 0xd3, 0xff, 0x01, 0x46, 0x90, 0x22, 0x40, 0x48, -0xfe, 0xf7, 0xc2, 0xfd, 0x03, 0x98, 0x00, 0x9d, 0xc0, 0x7c, 0x02, 0x90, 0x07, 0x98, 0x00, 0x26, -0x42, 0x7c, 0x01, 0x7c, 0x10, 0x06, 0x00, 0x14, 0x08, 0x43, 0x06, 0x90, 0x39, 0x48, 0x00, 0x7a, -0x00, 0x28, 0x3a, 0xd9, 0x00, 0x24, 0x77, 0x00, 0x02, 0x98, 0x00, 0x28, 0x0b, 0xd0, 0x24, 0x20, -0x21, 0x46, 0x41, 0x43, 0x32, 0x48, 0x08, 0x18, 0xc1, 0x5f, 0x06, 0x98, 0x40, 0x1a, 0x02, 0x99, -0xfe, 0xf7, 0x1a, 0xfe, 0x02, 0xb2, 0x12, 0x20, 0x60, 0x43, 0x80, 0x19, 0x80, 0x00, 0x29, 0x5c, -0x49, 0x06, 0x49, 0x0e, 0x29, 0x50, 0x89, 0x1a, 0x09, 0xb2, 0x7f, 0x29, 0x0f, 0xdd, 0x7f, 0x21, -0x10, 0xe0, 0x3d, 0xe0, 0x00, 0xf0, 0xce, 0xfc, 0xab, 0xe7, 0x00, 0xf0, 0x5b, 0xfc, 0xba, 0xe7, -0x1d, 0x48, 0x01, 0x78, 0x00, 0x29, 0xbd, 0xd0, 0x00, 0x21, 0x01, 0x70, 0x2c, 0xe0, 0x00, 0x29, -0x00, 0xda, 0x00, 0x21, 0x64, 0x1c, 0xe4, 0xb2, 0x29, 0x50, 0x04, 0x2c, 0xcc, 0xd3, 0x1d, 0x48, -0x76, 0x1c, 0x00, 0x7a, 0xf6, 0xb2, 0xb0, 0x42, 0xc4, 0xd8, 0x1a, 0x4e, 0x01, 0x9f, 0x00, 0x9d, -0x00, 0x21, 0x32, 0x7a, 0x00, 0x20, 0x00, 0x2a, 0x0c, 0xd9, 0x12, 0x22, 0x0c, 0x46, 0x54, 0x43, -0xe2, 0x19, 0x23, 0x18, 0x9b, 0x00, 0xeb, 0x5c, 0x13, 0x54, 0x40, 0x1c, 0x33, 0x7a, 0xc0, 0xb2, -0x83, 0x42, 0xf6, 0xd8, 0x49, 0x1c, 0xc9, 0xb2, 0x04, 0x29, 0xea, 0xd3, 0x05, 0x98, 0x40, 0x1e, -0xc0, 0xb2, 0x05, 0x90, 0x03, 0xf0, 0x7c, 0xfd, 0x05, 0x98, 0x00, 0x28, 0x00, 0xd0, 0x5e, 0xe7, -0x09, 0xb0, 0xf0, 0xbd, 0xa8, 0x0d, 0x01, 0x20, 0xdd, 0x00, 0x01, 0x20, 0x28, 0x0d, 0x01, 0x20, -0xe8, 0x0c, 0x01, 0x20, 0xe9, 0x0c, 0x01, 0x20, 0x30, 0x0e, 0x01, 0x20, 0x85, 0xd2, 0x03, 0x40, -0xe4, 0x11, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0xf0, 0xb5, 0x87, 0xb0, 0x03, 0x20, 0x02, 0x90, -0x08, 0x20, 0x03, 0xf0, 0x45, 0xff, 0x00, 0x90, 0x3b, 0x48, 0xc0, 0x7e, 0x40, 0x07, 0x70, 0xd5, -0x09, 0xf0, 0x90, 0xfe, 0x39, 0x48, 0x06, 0x90, 0x39, 0x48, 0x01, 0x90, 0x39, 0x48, 0x05, 0x90, -0x09, 0xf0, 0xb0, 0xfd, 0x0c, 0xf0, 0x82, 0xfd, 0x09, 0xf0, 0x84, 0xfe, 0x36, 0x48, 0x82, 0x7c, -0x06, 0x99, 0x0b, 0x7a, 0x10, 0x21, 0x99, 0x40, 0x8a, 0x43, 0x82, 0x74, 0x20, 0x20, 0x03, 0xf0, -0x27, 0xff, 0x01, 0x46, 0x90, 0x22, 0x31, 0x48, 0xfe, 0xf7, 0x16, 0xfd, 0x30, 0x4c, 0x60, 0x7a, -0x00, 0x28, 0x08, 0xd0, 0x01, 0x20, 0x03, 0xf0, 0x1b, 0xff, 0x09, 0x21, 0xc9, 0x01, 0x40, 0x18, -0x01, 0x88, 0x2c, 0x48, 0x01, 0x81, 0x01, 0x98, 0x00, 0x9d, 0x00, 0x7c, 0x03, 0x90, 0x05, 0x98, -0x00, 0x26, 0x42, 0x7b, 0x01, 0x7b, 0x10, 0x06, 0x00, 0x14, 0x08, 0x43, 0x04, 0x90, 0x20, 0x7a, -0x00, 0x28, 0x2b, 0xd9, 0x00, 0x24, 0x77, 0x00, 0x03, 0x98, 0x00, 0x28, 0x0a, 0xd0, 0x24, 0x20, -0x1e, 0x49, 0x60, 0x43, 0x40, 0x18, 0xc1, 0x5f, 0x04, 0x98, 0x40, 0x1a, 0x03, 0x99, 0xfe, 0xf7, -0x63, 0xfd, 0x02, 0xb2, 0x12, 0x20, 0x60, 0x43, 0x80, 0x19, 0x80, 0x00, 0x29, 0x5c, 0x49, 0x06, -0x49, 0x0e, 0x29, 0x50, 0x89, 0x1a, 0x09, 0xb2, 0x7f, 0x29, 0x01, 0xdd, 0x7f, 0x21, 0x02, 0xe0, -0x00, 0x29, 0x00, 0xda, 0x00, 0x21, 0x64, 0x1c, 0xe4, 0xb2, 0x29, 0x50, 0x04, 0x2c, 0xdb, 0xd3, -0x0f, 0x48, 0x76, 0x1c, 0x00, 0x7a, 0xf6, 0xb2, 0xb0, 0x42, 0xd3, 0xd8, 0x02, 0x98, 0x40, 0x1e, -0xc0, 0xb2, 0x02, 0x90, 0x03, 0xf0, 0xec, 0xfc, 0x02, 0x98, 0x00, 0x28, 0x98, 0xd1, 0x09, 0xf0, -0x49, 0xfd, 0x07, 0xb0, 0xf0, 0xbd, 0x00, 0x00, 0xa8, 0x0d, 0x01, 0x20, 0x6c, 0x03, 0x01, 0x20, -0xe8, 0x0c, 0x01, 0x20, 0xea, 0x0c, 0x01, 0x20, 0x00, 0x50, 0x03, 0x40, 0xe4, 0x11, 0x01, 0x20, -0xa8, 0x0c, 0x01, 0x20, 0xb0, 0x00, 0x01, 0x20, 0x1a, 0x48, 0x40, 0x78, 0x80, 0x07, 0x80, 0x0f, -0x01, 0x28, 0x2e, 0xd0, 0x70, 0xb5, 0x18, 0x4d, 0x00, 0x26, 0x2e, 0x81, 0x01, 0x20, 0x0c, 0xf0, -0x93, 0xff, 0x70, 0x1e, 0x28, 0x81, 0x14, 0x20, 0x0c, 0xf0, 0x8e, 0xff, 0x13, 0x48, 0x00, 0x79, -0x80, 0x07, 0x0b, 0xd4, 0x12, 0x48, 0x40, 0x7d, 0xc0, 0x07, 0x07, 0xd1, 0x11, 0x48, 0x00, 0x79, -0xc0, 0x07, 0x03, 0xd1, 0x10, 0x48, 0x40, 0x79, 0x00, 0x28, 0x01, 0xd0, 0x2e, 0x81, 0x70, 0xbd, -0x0e, 0x4c, 0x20, 0x79, 0xfd, 0x21, 0x08, 0x40, 0x20, 0x71, 0x0a, 0x20, 0x0c, 0xf0, 0x74, 0xff, -0x20, 0x79, 0x03, 0x21, 0x08, 0x43, 0x20, 0x71, 0x05, 0x20, 0x0c, 0xf0, 0x6d, 0xff, 0x2e, 0x81, -0x70, 0xbd, 0x70, 0x47, 0x60, 0x00, 0x03, 0x40, 0x20, 0x00, 0x03, 0x40, 0x00, 0x70, 0x03, 0x40, -0x00, 0x60, 0x03, 0x40, 0x00, 0x80, 0x03, 0x40, 0x18, 0x00, 0x01, 0x20, 0x00, 0x00, 0x03, 0x40, -0xf0, 0xb5, 0x49, 0x48, 0x01, 0x25, 0xc0, 0x79, 0x89, 0xb0, 0x01, 0x28, 0x7c, 0xdb, 0x47, 0x4f, -0x47, 0x48, 0x07, 0x90, 0x44, 0x48, 0x01, 0x24, 0x00, 0x7a, 0x01, 0x28, 0x6f, 0xdb, 0x45, 0x49, -0x28, 0x46, 0x28, 0x22, 0x50, 0x43, 0x41, 0x18, 0x05, 0x91, 0x43, 0x49, 0x40, 0x18, 0x04, 0x90, -0x05, 0x98, 0x66, 0x00, 0x81, 0x5f, 0x78, 0x7d, 0x3a, 0x7d, 0x00, 0x06, 0x00, 0x14, 0x10, 0x43, -0x81, 0x42, 0x57, 0xdb, 0xb8, 0x7d, 0x40, 0x1e, 0xc1, 0x0f, 0x08, 0x18, 0x41, 0x10, 0x68, 0x1a, -0x01, 0x28, 0x00, 0xdc, 0x01, 0x20, 0x34, 0x4b, 0x49, 0x19, 0xda, 0x79, 0xc0, 0xb2, 0x91, 0x42, -0x00, 0xdb, 0x11, 0x46, 0xc9, 0xb2, 0x8e, 0x46, 0xf9, 0x7d, 0x49, 0x1e, 0xca, 0x0f, 0x51, 0x18, -0x4a, 0x10, 0xa1, 0x1a, 0x01, 0x29, 0x00, 0xdc, 0x01, 0x21, 0x1b, 0x7a, 0x12, 0x19, 0xc9, 0xb2, -0x9a, 0x42, 0x00, 0xdb, 0x1a, 0x46, 0x94, 0x46, 0x14, 0x22, 0x42, 0x43, 0x52, 0x18, 0x53, 0x00, -0x01, 0x22, 0x12, 0x03, 0x9b, 0x18, 0x72, 0x46, 0x10, 0x1a, 0x62, 0x46, 0x40, 0x1c, 0x51, 0x1a, -0x86, 0x46, 0x49, 0x1c, 0x48, 0x43, 0xc2, 0xb2, 0x06, 0x92, 0x9a, 0x04, 0x23, 0x48, 0x92, 0x0c, -0x13, 0x18, 0x00, 0x20, 0x00, 0x90, 0x01, 0x90, 0x02, 0x90, 0x03, 0x90, 0x70, 0x46, 0xc9, 0xb2, -0xc0, 0xb2, 0x08, 0x22, 0xff, 0xf7, 0xde, 0xf9, 0x1d, 0x48, 0xc0, 0x6a, 0x06, 0x9a, 0x00, 0x2a, -0x0e, 0xd0, 0x11, 0x46, 0xfe, 0xf7, 0x78, 0xfc, 0x07, 0x99, 0x49, 0x7c, 0x40, 0x1a, 0x04, 0x99, -0x00, 0xb2, 0x88, 0x53, 0x05, 0x99, 0x89, 0x5f, 0x88, 0x42, 0x01, 0xdd, 0x04, 0x98, 0x81, 0x53, -0x0c, 0xf0, 0x1e, 0xfd, 0x0c, 0x48, 0x64, 0x1c, 0x00, 0x7a, 0xa0, 0x42, 0x98, 0xda, 0x0a, 0x48, -0x6d, 0x1c, 0xc0, 0x79, 0xa8, 0x42, 0x85, 0xda, 0x00, 0x20, 0x01, 0x90, 0x03, 0x90, 0x0d, 0x4b, -0x0d, 0x49, 0x05, 0x48, 0x02, 0x93, 0x00, 0x91, 0x01, 0x7a, 0xc0, 0x79, 0x01, 0x22, 0xff, 0xf7, -0xb1, 0xf9, 0x09, 0xb0, 0xf0, 0xbd, 0x00, 0x00, 0xa8, 0x0c, 0x01, 0x20, 0x08, 0x0e, 0x01, 0x20, -0xc8, 0x0c, 0x01, 0x20, 0x00, 0x50, 0x01, 0x20, 0x00, 0x5a, 0x01, 0x20, 0x00, 0x00, 0x14, 0x10, -0x00, 0x60, 0x03, 0x40, 0x2a, 0x10, 0x14, 0x10, 0x2a, 0x1a, 0x14, 0x10, 0xf0, 0xb4, 0x0d, 0x49, -0x00, 0x22, 0xcf, 0x79, 0x00, 0x2f, 0x12, 0xdd, 0x0d, 0x7a, 0x00, 0x21, 0x00, 0x2d, 0x0b, 0xdd, -0x09, 0x4b, 0x12, 0x24, 0x16, 0x46, 0x66, 0x43, 0xf3, 0x18, 0x74, 0x18, 0xa4, 0x00, 0x04, 0x5d, -0x5c, 0x54, 0x49, 0x1c, 0x8d, 0x42, 0xf8, 0xdc, 0x52, 0x1c, 0x97, 0x42, 0xed, 0xdc, 0xf0, 0xbc, -0x70, 0x47, 0x00, 0x00, 0xa8, 0x0c, 0x01, 0x20, 0xa4, 0x0f, 0x01, 0x20, 0x0b, 0x49, 0x48, 0x7e, -0xc2, 0x06, 0x11, 0xd5, 0x0a, 0x4a, 0x52, 0x79, 0x03, 0x2a, 0x0d, 0xd0, 0x10, 0xb5, 0xef, 0x22, -0x10, 0x40, 0x48, 0x76, 0x08, 0x20, 0x03, 0xf0, 0xa3, 0xfd, 0xff, 0xf7, 0xcf, 0xff, 0x08, 0x21, -0x04, 0x48, 0x08, 0xf0, 0x54, 0xfb, 0x10, 0xbd, 0x70, 0x47, 0x00, 0x00, 0xa8, 0x0c, 0x01, 0x20, -0x4c, 0x03, 0x01, 0x20, 0xa4, 0x0f, 0x01, 0x20, 0x10, 0xb4, 0x04, 0x46, 0x01, 0x22, 0x64, 0x43, -0x49, 0x43, 0x0f, 0x23, 0x00, 0x20, 0xd2, 0x03, 0x09, 0x19, 0x01, 0x29, 0x02, 0xd8, 0x10, 0xbc, -0x88, 0xb2, 0x70, 0x47, 0x44, 0x00, 0xa4, 0x18, 0x9c, 0x40, 0x5b, 0x1e, 0x9b, 0xb2, 0xa1, 0x42, -0x02, 0xd3, 0x80, 0x18, 0x80, 0xb2, 0x09, 0x1b, 0x52, 0x08, 0xf3, 0xd1, 0x10, 0xbc, 0x70, 0x47, -0xf0, 0xb4, 0x01, 0x22, 0x00, 0x23, 0xd2, 0x03, 0x01, 0x25, 0x0f, 0x27, 0x1c, 0x46, 0x2d, 0x1a, -0x8c, 0x41, 0x10, 0xda, 0x00, 0x26, 0x5c, 0x00, 0xa5, 0x18, 0xbd, 0x40, 0xac, 0x46, 0x7f, 0x1e, -0x0c, 0x46, 0x45, 0x1b, 0xb4, 0x41, 0x03, 0xdb, 0x9b, 0x18, 0x64, 0x46, 0x00, 0x1b, 0xb1, 0x41, -0x52, 0x08, 0xf0, 0xd1, 0x18, 0x46, 0xf0, 0xbc, 0x70, 0x47, 0x00, 0x00, 0xf0, 0xb5, 0x8f, 0xb0, -0x93, 0x48, 0x07, 0x90, 0x00, 0x78, 0x00, 0x28, 0x79, 0xd0, 0x92, 0x48, 0xc0, 0x7c, 0x00, 0x28, -0x75, 0xd1, 0x00, 0x90, 0x01, 0x90, 0x02, 0x90, 0x03, 0x90, 0x04, 0x90, 0x07, 0x46, 0x05, 0x90, -0x8d, 0x48, 0x0d, 0x90, 0xc0, 0x8b, 0x00, 0x28, 0x6a, 0xd9, 0x8c, 0x48, 0x09, 0x90, 0x8c, 0x48, -0x0c, 0x90, 0x8c, 0x48, 0x08, 0x90, 0x8c, 0x48, 0x06, 0x90, 0x00, 0x20, 0x0a, 0x90, 0x8b, 0x48, -0x79, 0x00, 0x08, 0x18, 0xe0, 0x30, 0x8a, 0x4c, 0x01, 0x78, 0xe1, 0x71, 0x40, 0x78, 0x20, 0x72, -0x03, 0x28, 0x04, 0xd9, 0x87, 0x49, 0x09, 0x7a, 0x89, 0x1e, 0x88, 0x42, 0x7e, 0xdb, 0x07, 0x98, -0x41, 0x7c, 0x02, 0x7c, 0x08, 0x02, 0x06, 0x99, 0x10, 0x43, 0x88, 0x83, 0x09, 0xf0, 0x8c, 0xfd, -0x81, 0x48, 0x82, 0x4b, 0xc1, 0x7a, 0x40, 0x7a, 0x08, 0x1a, 0xc0, 0xb2, 0x0b, 0x90, 0x21, 0x7a, -0xe6, 0x79, 0x8c, 0x46, 0x06, 0x99, 0x30, 0x46, 0x89, 0x8b, 0x05, 0x46, 0x8e, 0x46, 0x61, 0x46, -0x4c, 0x00, 0x01, 0xe0, 0x40, 0x1e, 0xc0, 0xb2, 0x28, 0x22, 0x01, 0x46, 0x51, 0x43, 0xc9, 0x18, -0x09, 0x5f, 0x71, 0x45, 0x01, 0xdd, 0x01, 0x28, 0xf4, 0xd8, 0x72, 0x49, 0xc9, 0x79, 0x0e, 0x91, -0xa9, 0x42, 0x0b, 0xd9, 0x29, 0x46, 0x28, 0x22, 0x70, 0x4b, 0x51, 0x43, 0xc9, 0x18, 0x09, 0x5f, -0x71, 0x45, 0x03, 0xdd, 0x6d, 0x1c, 0xed, 0xb2, 0x0e, 0x99, 0xf1, 0xe7, 0x40, 0x1c, 0xc0, 0xb2, -0xb0, 0x42, 0x1a, 0xd2, 0x09, 0x99, 0x4b, 0x7f, 0x09, 0x7f, 0x1b, 0x02, 0x0b, 0x43, 0x0e, 0x93, -0x28, 0x22, 0x01, 0x46, 0x65, 0x4b, 0x51, 0x43, 0xcb, 0x18, 0x19, 0x5f, 0x1b, 0x19, 0x9a, 0x5e, -0x8b, 0x1a, 0x0e, 0x99, 0x8b, 0x42, 0x04, 0xdd, 0x01, 0x20, 0x0a, 0x90, 0x05, 0xe0, 0xa4, 0xe0, -0x9e, 0xe0, 0x40, 0x1c, 0xc0, 0xb2, 0xb0, 0x42, 0xea, 0xd3, 0x6d, 0x1e, 0x30, 0x46, 0x0e, 0x95, -0xae, 0x42, 0x16, 0xdc, 0x09, 0x99, 0x4a, 0x7f, 0x09, 0x7f, 0x12, 0x02, 0x0a, 0x43, 0x15, 0x46, -0x28, 0x21, 0x02, 0x46, 0x4a, 0x43, 0x55, 0x49, 0x53, 0x18, 0x19, 0x19, 0x28, 0x22, 0x8a, 0x5e, -0x19, 0x5f, 0x52, 0x1a, 0xaa, 0x42, 0x7c, 0xdc, 0x40, 0x1c, 0x0e, 0x99, 0xc0, 0xb2, 0x88, 0x42, -0xee, 0xdd, 0x0a, 0x98, 0x00, 0x28, 0x74, 0xd1, 0x0b, 0x98, 0x00, 0x28, 0x07, 0xd0, 0x01, 0x28, -0x60, 0x46, 0x1b, 0xd0, 0x03, 0x28, 0x3a, 0xd8, 0x01, 0x21, 0x3a, 0xe0, 0x69, 0xe0, 0x72, 0x46, -0x61, 0x46, 0x30, 0x46, 0x00, 0xf0, 0x8e, 0xf8, 0x01, 0x46, 0x28, 0x20, 0x46, 0x43, 0x43, 0x48, -0x30, 0x18, 0x02, 0x5f, 0x0c, 0x98, 0x43, 0x79, 0x04, 0x79, 0x18, 0x02, 0x20, 0x43, 0x82, 0x42, -0x54, 0xdb, 0x08, 0x98, 0x80, 0x7b, 0x88, 0x42, 0x50, 0xd3, 0x52, 0xe0, 0x03, 0x28, 0x01, 0xd8, -0x01, 0x21, 0x01, 0xe0, 0x37, 0x48, 0x01, 0x7a, 0x60, 0x46, 0x03, 0x28, 0x01, 0xd8, 0x02, 0x20, -0x02, 0xe0, 0x34, 0x48, 0x00, 0x7a, 0x40, 0x1e, 0xc4, 0xb2, 0x72, 0x46, 0x30, 0x46, 0x00, 0xf0, -0x69, 0xf8, 0x05, 0x46, 0x06, 0x98, 0x21, 0x46, 0x82, 0x8b, 0x30, 0x46, 0x00, 0xf0, 0x62, 0xf8, -0x85, 0x42, 0x36, 0xd3, 0x08, 0x98, 0xc0, 0x7b, 0xa8, 0x42, 0x2f, 0xd3, 0x31, 0xe0, 0x29, 0x48, -0x01, 0x7a, 0x60, 0x46, 0x03, 0x28, 0x01, 0xd8, 0x02, 0x20, 0x02, 0xe0, 0x25, 0x48, 0x00, 0x7a, -0x40, 0x1e, 0xc4, 0xb2, 0x60, 0x46, 0x03, 0x28, 0x01, 0xd8, 0x03, 0x20, 0x02, 0xe0, 0x21, 0x48, -0x00, 0x7a, 0x80, 0x1e, 0xc0, 0xb2, 0x0a, 0x90, 0x72, 0x46, 0x30, 0x46, 0x00, 0xf0, 0x42, 0xf8, -0x05, 0x46, 0x06, 0x98, 0x21, 0x46, 0x82, 0x8b, 0x30, 0x46, 0x00, 0xf0, 0x3b, 0xf8, 0x04, 0x46, -0x06, 0x98, 0x0a, 0x99, 0x82, 0x8b, 0x30, 0x46, 0x00, 0xf0, 0x34, 0xf8, 0xa5, 0x42, 0x08, 0xd3, -0x84, 0x42, 0x06, 0xd3, 0x07, 0x98, 0xc0, 0x7b, 0xa8, 0x42, 0x02, 0xd2, 0x01, 0x20, 0x69, 0x46, -0xc8, 0x55, 0x0d, 0x98, 0x7f, 0x1c, 0xc0, 0x8b, 0xff, 0xb2, 0xb8, 0x42, 0x00, 0xd9, 0xfc, 0xe6, -0x0f, 0x4a, 0x68, 0x46, 0x11, 0x46, 0x07, 0xf0, 0xef, 0xf8, 0x0f, 0xb0, 0xf0, 0xbd, 0x00, 0x00, -0x08, 0x0e, 0x01, 0x20, 0xa4, 0x2d, 0x01, 0x20, 0x04, 0x25, 0x01, 0x20, 0x89, 0x0d, 0x01, 0x20, -0xe9, 0x0c, 0x01, 0x20, 0xe8, 0x0d, 0x01, 0x20, 0x84, 0x2d, 0x01, 0x20, 0x44, 0x24, 0x01, 0x20, -0xac, 0x1b, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0xb8, 0x1b, 0x01, 0x20, 0x00, 0x50, 0x01, 0x20, -0x22, 0x25, 0x01, 0x20, 0xf0, 0xb4, 0x05, 0x46, 0x12, 0x4c, 0x6b, 0x1c, 0xe4, 0x79, 0x00, 0x20, -0xdb, 0xb2, 0x11, 0x4e, 0x49, 0x00, 0x9c, 0x42, 0x0b, 0xd3, 0x28, 0x27, 0x5f, 0x43, 0xbf, 0x19, -0x7f, 0x5e, 0x97, 0x42, 0x05, 0xdb, 0x40, 0x1c, 0x5b, 0x1c, 0xdb, 0xb2, 0xc0, 0xb2, 0x9c, 0x42, -0xf3, 0xd2, 0x00, 0x2d, 0x0b, 0xd0, 0x28, 0x23, 0x6b, 0x43, 0x9b, 0x19, 0x5b, 0x5e, 0x93, 0x42, -0x05, 0xdb, 0x40, 0x1c, 0x6d, 0x1e, 0x2d, 0x06, 0xc0, 0xb2, 0x2d, 0x0e, 0xf3, 0xd1, 0xf0, 0xbc, -0x70, 0x47, 0x00, 0x00, 0xa8, 0x0c, 0x01, 0x20, 0x00, 0x50, 0x01, 0x20, 0xf0, 0xb5, 0x44, 0x4e, -0x83, 0xb0, 0x30, 0x78, 0x00, 0x28, 0x6e, 0xd0, 0x42, 0x48, 0x01, 0x90, 0x00, 0x25, 0x42, 0x48, -0x2f, 0x46, 0x00, 0x90, 0x14, 0x20, 0x29, 0x46, 0x41, 0x43, 0x40, 0x48, 0x0c, 0x18, 0xa0, 0x7c, -0x01, 0x28, 0x08, 0xd0, 0x04, 0x28, 0x38, 0xd0, 0x00, 0x28, 0x36, 0xd0, 0x02, 0x28, 0x36, 0xd0, -0x03, 0x28, 0x34, 0xd0, 0x65, 0xe0, 0xe0, 0x88, 0xb1, 0x78, 0x88, 0x42, 0x07, 0xd3, 0x01, 0x9a, -0x53, 0x7c, 0x12, 0x7c, 0x1b, 0x02, 0x13, 0x43, 0x59, 0x1a, 0x81, 0x42, 0x59, 0xda, 0x60, 0x81, -0x20, 0x89, 0xa0, 0x81, 0x62, 0x7e, 0x23, 0x7e, 0x00, 0x20, 0x01, 0x2a, 0x19, 0xd0, 0x30, 0x49, -0x09, 0x7a, 0x91, 0x42, 0x05, 0xd1, 0x48, 0x1e, 0x01, 0x22, 0xc0, 0xb2, 0x22, 0x74, 0x02, 0x28, -0x02, 0xd0, 0x49, 0x1e, 0x81, 0x42, 0x0a, 0xd1, 0x28, 0x21, 0x4b, 0x43, 0x29, 0x49, 0x40, 0x00, -0x59, 0x18, 0x09, 0x5e, 0x00, 0x98, 0x40, 0x7d, 0x81, 0x42, 0x00, 0xdd, 0x27, 0x74, 0xe7, 0x75, -0x37, 0xe0, 0x02, 0x20, 0x01, 0x21, 0x21, 0x74, 0xee, 0xe7, 0x27, 0x74, 0x31, 0xe0, 0x20, 0x7c, -0x00, 0x28, 0x02, 0xd1, 0xe0, 0x7c, 0x00, 0x28, 0x2b, 0xd0, 0xe0, 0x7d, 0x40, 0x1c, 0xe0, 0x75, -0xe0, 0x88, 0x61, 0x89, 0x40, 0x1a, 0x00, 0xd5, 0x40, 0x42, 0x82, 0xb2, 0x20, 0x89, 0xa1, 0x89, -0x40, 0x1a, 0x00, 0xd5, 0x40, 0x42, 0x01, 0xb2, 0x10, 0xb2, 0xff, 0xf7, 0xed, 0xfd, 0xe0, 0x81, -0xe1, 0x7c, 0x00, 0x29, 0xf1, 0x78, 0x07, 0xd0, 0xc9, 0x00, 0x88, 0x42, 0x01, 0xd9, 0x04, 0x20, -0xa0, 0x74, 0xe7, 0x74, 0x0d, 0xe0, 0x10, 0xe0, 0x88, 0x42, 0x0a, 0xd9, 0x27, 0x74, 0xe0, 0x7d, -0x08, 0x28, 0x04, 0xd2, 0x60, 0x89, 0xe0, 0x80, 0xa0, 0x89, 0x20, 0x81, 0x01, 0xe0, 0x01, 0x20, -0xe0, 0x74, 0x6d, 0x1c, 0xed, 0xb2, 0x0b, 0x2d, 0x84, 0xd3, 0x03, 0xb0, 0xf0, 0xbd, 0x00, 0x00, -0x08, 0x0e, 0x01, 0x20, 0x28, 0x0d, 0x01, 0x20, 0xe8, 0x0c, 0x01, 0x20, 0x68, 0x02, 0x01, 0x20, -0xa8, 0x0c, 0x01, 0x20, 0x00, 0x50, 0x01, 0x20, 0x70, 0xb5, 0x08, 0x4d, 0xa8, 0x60, 0xe9, 0x60, -0x07, 0x4c, 0x01, 0x20, 0x20, 0x70, 0x20, 0x79, 0xc0, 0x07, 0x04, 0xd0, 0x0c, 0xf0, 0x68, 0xfa, -0x20, 0x79, 0xc0, 0x07, 0xfa, 0xd1, 0xe8, 0x69, 0x80, 0xb2, 0x70, 0xbd, 0x00, 0x40, 0x03, 0x40, -0x20, 0x40, 0x03, 0x40, 0xf8, 0xb5, 0x33, 0x4c, 0xe1, 0x79, 0xf0, 0x25, 0x29, 0x43, 0xe0, 0x1d, -0x01, 0xf0, 0x1d, 0xfe, 0x61, 0x78, 0x60, 0x1c, 0x29, 0x43, 0x01, 0xf0, 0x18, 0xfe, 0x20, 0x7a, -0x2d, 0x4f, 0x81, 0x08, 0x89, 0x00, 0x38, 0x46, 0x01, 0xf0, 0x11, 0xfe, 0xa0, 0x78, 0x81, 0x08, -0x89, 0x00, 0xa0, 0x1c, 0x01, 0xf0, 0x0b, 0xfe, 0xa1, 0x79, 0xf3, 0x25, 0xa6, 0x1d, 0x29, 0x40, -0x30, 0x46, 0x01, 0xf0, 0x04, 0xfe, 0x21, 0x78, 0x20, 0x46, 0x29, 0x40, 0x01, 0xf0, 0xff, 0xfd, -0xff, 0x20, 0xf5, 0x30, 0x04, 0xf0, 0x7e, 0xfd, 0x03, 0x21, 0x38, 0x46, 0x01, 0xf0, 0xf7, 0xfd, -0x30, 0x46, 0x01, 0xf0, 0xec, 0xfd, 0x81, 0x06, 0x89, 0x0e, 0x0c, 0x25, 0x29, 0x43, 0x30, 0x46, -0x01, 0xf0, 0xed, 0xfd, 0xe1, 0x79, 0xe0, 0x1d, 0x29, 0x40, 0x01, 0xf0, 0xe8, 0xfd, 0x03, 0x21, -0xa0, 0x1c, 0x01, 0xf0, 0xe4, 0xfd, 0x20, 0x46, 0x01, 0xf0, 0xd9, 0xfd, 0x81, 0x06, 0x89, 0x0e, -0x29, 0x43, 0x20, 0x46, 0x01, 0xf0, 0xdb, 0xfd, 0x61, 0x78, 0x60, 0x1c, 0x29, 0x40, 0x01, 0xf0, -0xd6, 0xfd, 0x60, 0x7a, 0x81, 0x07, 0x89, 0x0f, 0xf0, 0x1c, 0x01, 0xf0, 0xd0, 0xfd, 0xe1, 0x78, -0x33, 0x20, 0x01, 0x40, 0xe0, 0x1c, 0x01, 0xf0, 0xca, 0xfd, 0x41, 0x21, 0x07, 0x48, 0x01, 0xf0, -0xc6, 0xfd, 0xf0, 0x21, 0x06, 0x48, 0x01, 0xf0, 0xc2, 0xfd, 0xf0, 0x21, 0x70, 0x1d, 0x01, 0xf0, -0xbe, 0xfd, 0xf8, 0xbd, 0x00, 0xd1, 0x03, 0x00, 0x08, 0xd1, 0x03, 0x00, 0x16, 0xd1, 0x03, 0x00, -0x17, 0xd1, 0x03, 0x00, 0xf8, 0xb5, 0x00, 0x21, 0x2b, 0x48, 0x01, 0xf0, 0xb0, 0xfd, 0x2b, 0x4c, -0x20, 0x46, 0x01, 0xf0, 0xa4, 0xfd, 0xf3, 0x25, 0x28, 0x40, 0xc0, 0x26, 0x30, 0x43, 0x01, 0x46, -0x20, 0x46, 0x01, 0xf0, 0xa4, 0xfd, 0x26, 0x4c, 0xe1, 0x7c, 0x0c, 0x27, 0x39, 0x40, 0x25, 0x48, -0x01, 0xf0, 0x9d, 0xfd, 0x00, 0x21, 0x24, 0x48, 0x01, 0xf0, 0x99, 0xfd, 0x23, 0x48, 0x01, 0xf0, -0x8e, 0xfd, 0x28, 0x40, 0x30, 0x43, 0x01, 0x46, 0x20, 0x48, 0x01, 0xf0, 0x90, 0xfd, 0x61, 0x7b, -0x1f, 0x48, 0x39, 0x40, 0x01, 0xf0, 0x8b, 0xfd, 0x60, 0x7d, 0x81, 0x07, 0x89, 0x0f, 0x1d, 0x48, -0x01, 0xf0, 0x85, 0xfd, 0xe1, 0x7b, 0x33, 0x20, 0x01, 0x40, 0x1b, 0x48, 0x01, 0xf0, 0x7f, 0xfd, -0x20, 0x7a, 0x81, 0x08, 0x89, 0x00, 0x19, 0x48, 0x01, 0xf0, 0x79, 0xfd, 0xa0, 0x78, 0x81, 0x08, -0x89, 0x00, 0xa0, 0x1c, 0x01, 0xf0, 0x73, 0xfd, 0xa1, 0x79, 0xa0, 0x1d, 0x29, 0x40, 0x01, 0xf0, -0x6e, 0xfd, 0x21, 0x78, 0x20, 0x46, 0x29, 0x40, 0x01, 0xf0, 0x69, 0xfd, 0x41, 0x21, 0x20, 0x1d, -0x01, 0xf0, 0x65, 0xfd, 0xf0, 0x21, 0x60, 0x1d, 0x01, 0xf0, 0x61, 0xfd, 0xf0, 0x21, 0x0c, 0x48, -0x01, 0xf0, 0x5d, 0xfd, 0xf8, 0xbd, 0x00, 0x00, 0x14, 0xd1, 0x03, 0x00, 0x12, 0xd1, 0x03, 0x00, -0x00, 0xd1, 0x03, 0x00, 0x13, 0xd1, 0x03, 0x00, 0x0e, 0xd1, 0x03, 0x00, 0x0c, 0xd1, 0x03, 0x00, -0x0d, 0xd1, 0x03, 0x00, 0x15, 0xd1, 0x03, 0x00, 0x0f, 0xd1, 0x03, 0x00, 0x08, 0xd1, 0x03, 0x00, -0x11, 0xd1, 0x03, 0x00, 0x70, 0xb5, 0x1c, 0x4d, 0x00, 0x24, 0x28, 0x6a, 0x00, 0x78, 0x00, 0x28, -0x31, 0xd9, 0x1a, 0x4e, 0x28, 0x6a, 0x01, 0x78, 0x49, 0x1e, 0xa1, 0x42, 0x10, 0xd1, 0x14, 0x21, -0x61, 0x43, 0x0b, 0x18, 0xd9, 0x88, 0xc2, 0x88, 0x80, 0x1d, 0x9b, 0x1d, 0x89, 0x1a, 0x00, 0xd5, -0x49, 0x42, 0x8a, 0xb2, 0x59, 0x88, 0x40, 0x88, 0x08, 0x1a, 0x10, 0xd5, 0x40, 0x42, 0x0e, 0xe0, -0x14, 0x21, 0x61, 0x43, 0x09, 0x18, 0x8b, 0x1d, 0xc8, 0x88, 0x4a, 0x8b, 0x1a, 0x31, 0x80, 0x1a, -0x00, 0xd5, 0x40, 0x42, 0x82, 0xb2, 0x58, 0x88, 0x49, 0x88, 0x40, 0x1a, 0xee, 0xd4, 0x01, 0xb2, -0x10, 0xb2, 0xff, 0xf7, 0x99, 0xfc, 0x61, 0x00, 0x70, 0x52, 0x28, 0x6a, 0x64, 0x1c, 0x00, 0x78, -0xe4, 0xb2, 0xa0, 0x42, 0xce, 0xd8, 0x70, 0xbd, 0x38, 0x02, 0x01, 0x20, 0xc0, 0x34, 0x01, 0x20, -0x00, 0xb5, 0x14, 0x48, 0x85, 0xb0, 0x00, 0x7a, 0x00, 0x28, 0x16, 0xd0, 0x04, 0x20, 0x09, 0x21, -0x00, 0x07, 0x49, 0x04, 0x43, 0x18, 0x00, 0x20, 0x0f, 0x4a, 0x01, 0x90, 0x03, 0x90, 0x0f, 0x49, -0x00, 0x92, 0x0f, 0x48, 0x02, 0x91, 0x01, 0x7a, 0xc0, 0x79, 0x01, 0x22, 0xfe, 0xf7, 0xd2, 0xfd, -0x0c, 0x48, 0x40, 0x79, 0x00, 0x28, 0x02, 0xd0, 0x07, 0xe0, 0x03, 0x20, 0xe7, 0xe7, 0x55, 0x22, -0x12, 0x01, 0x09, 0x49, 0x09, 0x48, 0xfd, 0xf7, 0xef, 0xff, 0x09, 0xf0, 0xa1, 0xfd, 0x05, 0xb0, -0x00, 0xbd, 0x00, 0x00, 0x6c, 0x03, 0x01, 0x20, 0x2a, 0x00, 0x14, 0x10, 0x2a, 0x10, 0x14, 0x10, -0xa8, 0x0c, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, 0x00, 0x50, 0x01, 0x20, 0x28, 0x2f, 0x01, 0x20, -0xff, 0xb5, 0x05, 0x46, 0x8b, 0xb0, 0x08, 0x20, 0x03, 0xf0, 0xe2, 0xf9, 0x04, 0x46, 0x61, 0x48, -0x08, 0x90, 0x28, 0x0a, 0x04, 0x90, 0xe8, 0xb2, 0x05, 0x90, 0x00, 0x20, 0x07, 0x90, 0x5e, 0x48, -0x00, 0x7a, 0x00, 0x28, 0x32, 0xd0, 0x04, 0x20, 0x09, 0x21, 0x00, 0x07, 0x49, 0x04, 0x0c, 0x9d, -0x43, 0x18, 0x2d, 0x04, 0x5a, 0x4a, 0x01, 0x95, 0x58, 0x48, 0x00, 0x21, 0x02, 0x92, 0x59, 0x4d, -0x03, 0x91, 0x00, 0x90, 0x29, 0x7a, 0xe8, 0x79, 0x01, 0x22, 0xfe, 0xf7, 0x8b, 0xfd, 0x00, 0x20, -0x02, 0x90, 0xe8, 0x79, 0x00, 0x28, 0x7b, 0xd9, 0x53, 0x48, 0x0a, 0x90, 0x53, 0x48, 0x03, 0x90, -0x50, 0x48, 0x00, 0x25, 0x00, 0x7a, 0x00, 0x28, 0x73, 0xd9, 0x02, 0x98, 0x24, 0x21, 0x48, 0x43, -0x08, 0x99, 0x40, 0x18, 0x00, 0x90, 0x02, 0x98, 0x12, 0x21, 0x48, 0x43, 0x09, 0x90, 0x29, 0x46, -0x02, 0x98, 0x03, 0xf0, 0x45, 0xfa, 0x00, 0x28, 0x6c, 0xd1, 0x01, 0xe0, 0x03, 0x20, 0xcb, 0xe7, -0x68, 0x00, 0x00, 0x99, 0x01, 0x90, 0x08, 0x5e, 0x00, 0x28, 0x01, 0xdb, 0x01, 0x46, 0x00, 0xe0, -0x41, 0x42, 0x0d, 0x9a, 0x91, 0x42, 0x5d, 0xdd, 0x07, 0x99, 0x49, 0x1c, 0x89, 0xb2, 0x07, 0x91, -0x11, 0x1e, 0x03, 0xd0, 0xfd, 0xf7, 0xf8, 0xff, 0x00, 0xb2, 0x06, 0x90, 0x09, 0x98, 0x40, 0x19, -0x86, 0x00, 0xa0, 0x5d, 0x47, 0x06, 0x7f, 0x0e, 0xa7, 0x51, 0x0a, 0x98, 0x80, 0x7d, 0x03, 0x28, -0x40, 0xd3, 0x14, 0x99, 0x88, 0x42, 0x19, 0xd1, 0x01, 0x99, 0x00, 0x98, 0x03, 0x9a, 0x41, 0x5e, -0x0c, 0x98, 0x09, 0x18, 0x50, 0x7a, 0x12, 0x7a, 0x00, 0x02, 0x10, 0x43, 0x0d, 0x9a, 0x82, 0x1a, -0x91, 0x42, 0x2f, 0xdd, 0x81, 0x42, 0x22, 0xdd, 0x2c, 0xe0, 0x02, 0xb2, 0x05, 0x99, 0x04, 0x98, -0x88, 0x42, 0x2e, 0xd0, 0x82, 0x42, 0x28, 0xdd, 0xa0, 0x51, 0x2b, 0xe0, 0x40, 0x1e, 0x88, 0x42, -0x20, 0xd1, 0x03, 0x21, 0x06, 0x98, 0xfd, 0xf7, 0xc7, 0xff, 0x01, 0x46, 0x0d, 0x98, 0x41, 0x43, -0x03, 0x98, 0x42, 0x7a, 0x03, 0x7a, 0x10, 0x02, 0x18, 0x43, 0x42, 0x1a, 0x01, 0x9b, 0x00, 0x99, -0xcb, 0x5e, 0x0c, 0x99, 0x59, 0x18, 0x8a, 0x42, 0x0c, 0xda, 0x81, 0x42, 0x0a, 0xdc, 0x05, 0x21, -0x06, 0x98, 0xfd, 0xf7, 0xb1, 0xff, 0x17, 0x49, 0x49, 0x7b, 0x48, 0x43, 0xc0, 0x19, 0xd4, 0xe7, -0x18, 0xe0, 0x0d, 0xe0, 0x06, 0x98, 0x38, 0x18, 0xcf, 0xe7, 0x8a, 0x42, 0x01, 0xda, 0xa1, 0x51, -0x00, 0xe0, 0xa2, 0x51, 0x0f, 0x48, 0x6d, 0x1c, 0x00, 0x7a, 0xed, 0xb2, 0xa8, 0x42, 0x86, 0xd8, -0x02, 0x98, 0x40, 0x1c, 0xc0, 0xb2, 0x02, 0x90, 0x0a, 0x48, 0xc1, 0x79, 0x02, 0x98, 0x81, 0x42, -0x00, 0xd9, 0x6d, 0xe7, 0x0e, 0x98, 0x00, 0x28, 0x02, 0xd0, 0x0e, 0x99, 0x07, 0x98, 0x08, 0x80, -0x0f, 0xb0, 0xf0, 0xbd, 0x00, 0x48, 0x01, 0x20, 0x6c, 0x03, 0x01, 0x20, 0x00, 0x00, 0x12, 0xf0, -0x00, 0x08, 0x12, 0x10, 0xa8, 0x0c, 0x01, 0x20, 0xa8, 0x0d, 0x01, 0x20, 0xab, 0x0c, 0x01, 0x20, -0xf0, 0xb5, 0x9b, 0xb0, 0x9d, 0x48, 0x19, 0x90, 0xc0, 0x8b, 0x9d, 0x49, 0x00, 0x22, 0x88, 0x76, -0x9c, 0x49, 0x10, 0x91, 0x0a, 0x84, 0x05, 0x92, 0x00, 0x28, 0x72, 0xd9, 0x9a, 0x49, 0xc8, 0x79, -0x0f, 0x90, 0x08, 0x7a, 0x0e, 0x90, 0x0f, 0x98, 0x40, 0x1e, 0x18, 0x90, 0x0e, 0x98, 0x40, 0x1e, -0x17, 0x90, 0x08, 0x46, 0xa0, 0x30, 0x42, 0x7c, 0x0d, 0x92, 0x02, 0x7c, 0x0c, 0x92, 0xc2, 0x7c, -0x0b, 0x92, 0x80, 0x7c, 0xff, 0x31, 0x02, 0x31, 0x0a, 0x90, 0x48, 0x7e, 0x09, 0x7e, 0x00, 0x02, -0x08, 0x43, 0x40, 0x08, 0x03, 0x90, 0x05, 0x98, 0x02, 0x90, 0x00, 0x20, 0x84, 0x46, 0x04, 0x46, -0x04, 0x90, 0x0f, 0x98, 0x09, 0x90, 0x0e, 0x98, 0x08, 0x90, 0x02, 0x98, 0x87, 0x4b, 0xc0, 0x00, -0xc0, 0x18, 0x07, 0x90, 0x20, 0x30, 0x81, 0x7b, 0x01, 0x29, 0x01, 0xd8, 0x01, 0x25, 0x0c, 0xe0, -0x02, 0x9a, 0x52, 0x00, 0xd2, 0x18, 0xe0, 0x32, 0x12, 0x78, 0x55, 0x1a, 0x03, 0x2d, 0x02, 0xdb, -0xd2, 0x1e, 0xd5, 0xb2, 0x01, 0xe0, 0x49, 0x1e, 0xcd, 0xb2, 0x01, 0x7c, 0x18, 0x9a, 0x1e, 0x46, -0x16, 0x92, 0x91, 0x42, 0x02, 0xdb, 0x09, 0x99, 0x06, 0x91, 0x0d, 0xe0, 0x02, 0x9a, 0x52, 0x00, -0x92, 0x19, 0xe0, 0x32, 0x12, 0x78, 0x8b, 0x1a, 0x03, 0x2b, 0x02, 0xdb, 0xd2, 0x1c, 0xd1, 0xb2, -0x01, 0xe0, 0x49, 0x1c, 0xc9, 0xb2, 0x06, 0x91, 0xc1, 0x7b, 0x33, 0x46, 0x01, 0x29, 0x02, 0xd8, -0x01, 0x21, 0x00, 0x91, 0x0d, 0xe0, 0x02, 0x9a, 0x52, 0x00, 0xd2, 0x18, 0xe0, 0x32, 0x52, 0x78, -0x56, 0x1a, 0x03, 0x2e, 0x02, 0xdb, 0xd2, 0x1e, 0xd1, 0xb2, 0x01, 0xe0, 0x49, 0x1e, 0xc9, 0xb2, -0x00, 0x91, 0x40, 0x7c, 0x17, 0x99, 0x15, 0x91, 0x88, 0x42, 0x03, 0xdb, 0x08, 0x98, 0x01, 0x90, -0x0e, 0xe0, 0xb9, 0xe0, 0x02, 0x9a, 0x52, 0x00, 0xd1, 0x18, 0xe0, 0x31, 0x49, 0x78, 0x42, 0x1a, -0x03, 0x2a, 0x02, 0xdb, 0xc9, 0x1c, 0xc8, 0xb2, 0x01, 0xe0, 0x40, 0x1c, 0xc0, 0xb2, 0x01, 0x90, -0x02, 0x98, 0x41, 0x00, 0x59, 0x48, 0x08, 0x18, 0xe0, 0x30, 0x14, 0x90, 0x01, 0x78, 0x43, 0x78, -0x06, 0x98, 0x85, 0x42, 0x5e, 0xd8, 0x00, 0x9a, 0x01, 0x98, 0x82, 0x42, 0x55, 0xd8, 0x28, 0x46, -0x28, 0x26, 0x70, 0x43, 0x52, 0x4e, 0x80, 0x19, 0x13, 0x90, 0x68, 0x00, 0x40, 0x1e, 0x12, 0x90, -0x50, 0x00, 0x13, 0x9e, 0x11, 0x90, 0x30, 0x5e, 0x00, 0x28, 0x41, 0xdd, 0x80, 0x00, 0x02, 0x2b, -0x01, 0xd1, 0x02, 0x2a, 0x04, 0xd9, 0x15, 0x9e, 0xb3, 0x42, 0x06, 0xd1, 0x9a, 0x42, 0x04, 0xd3, -0x0d, 0x9e, 0x40, 0x2e, 0x01, 0xd0, 0x46, 0x43, 0xb0, 0x11, 0x01, 0x2b, 0x02, 0xd0, 0x08, 0x9e, -0xb3, 0x42, 0x06, 0xd1, 0x9a, 0x42, 0x04, 0xd1, 0x0c, 0x9e, 0x40, 0x2e, 0x01, 0xd0, 0x46, 0x43, -0xb0, 0x11, 0x02, 0x29, 0x01, 0xd1, 0x02, 0x2d, 0x04, 0xd9, 0x16, 0x9e, 0xb1, 0x42, 0x06, 0xd1, -0x8d, 0x42, 0x04, 0xd3, 0x0b, 0x9e, 0x40, 0x2e, 0x01, 0xd0, 0x46, 0x43, 0xb0, 0x11, 0x01, 0x29, -0x02, 0xd0, 0x09, 0x9e, 0xb1, 0x42, 0x06, 0xd1, 0x8d, 0x42, 0x04, 0xd1, 0x0a, 0x9e, 0x40, 0x2e, -0x01, 0xd0, 0x46, 0x43, 0xb0, 0x11, 0x12, 0x9e, 0xb7, 0xb2, 0x06, 0x46, 0x7e, 0x43, 0x04, 0x9f, -0xbe, 0x19, 0x04, 0x96, 0x11, 0x9e, 0x76, 0x1e, 0xb6, 0xb2, 0x46, 0x43, 0xb4, 0x44, 0x24, 0x18, -0x52, 0x1c, 0x01, 0x98, 0xd2, 0xb2, 0x82, 0x42, 0xb2, 0xd9, 0x6d, 0x1c, 0x06, 0x98, 0xed, 0xb2, -0x85, 0x42, 0xa0, 0xd9, 0x03, 0x9e, 0x04, 0x99, 0x60, 0x46, 0xc0, 0x01, 0x4e, 0x43, 0x00, 0x2c, -0x11, 0xd0, 0x21, 0x46, 0xfd, 0xf7, 0x6a, 0xfe, 0x02, 0x99, 0x0c, 0x22, 0x51, 0x43, 0x1f, 0x4a, -0x8d, 0x18, 0xff, 0x21, 0x3f, 0x31, 0x48, 0x53, 0x21, 0x46, 0x30, 0x46, 0xfd, 0xf7, 0x5e, 0xfe, -0xff, 0x35, 0x41, 0x35, 0x28, 0x80, 0x05, 0x99, 0x0c, 0x20, 0x41, 0x43, 0x17, 0x48, 0xff, 0x22, -0x08, 0x18, 0xff, 0x21, 0x3d, 0x31, 0x0a, 0x54, 0x07, 0x99, 0x8a, 0x8e, 0x01, 0x46, 0xff, 0x31, -0x41, 0x31, 0x4a, 0x80, 0x07, 0x9a, 0xff, 0x30, 0x52, 0x8e, 0x8a, 0x80, 0x14, 0x99, 0x43, 0x30, -0x09, 0x88, 0x81, 0x80, 0x10, 0x98, 0x01, 0x8c, 0x07, 0x98, 0x40, 0x8e, 0x81, 0x42, 0x01, 0xd2, -0x10, 0x99, 0x08, 0x84, 0x05, 0x98, 0x40, 0x1c, 0xc0, 0xb2, 0x05, 0x90, 0x19, 0x98, 0xc1, 0x8b, -0x05, 0x98, 0x81, 0x42, 0x00, 0xd9, 0xee, 0xe6, 0x1b, 0xb0, 0xf0, 0xbd, 0x04, 0x25, 0x01, 0x20, -0x64, 0x25, 0x01, 0x20, 0x84, 0x2d, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0x44, 0x24, 0x01, 0x20, -0x00, 0x50, 0x01, 0x20, 0xf0, 0xb5, 0x87, 0xb0, 0x0b, 0xf0, 0x0e, 0xfb, 0x04, 0xf0, 0x60, 0xfd, -0x56, 0x48, 0x00, 0x7c, 0x00, 0x28, 0x21, 0xd0, 0x55, 0x49, 0x08, 0x78, 0x01, 0x28, 0x1d, 0xd1, -0x54, 0x48, 0x56, 0x4f, 0x83, 0x7d, 0x54, 0x48, 0x55, 0x4a, 0x00, 0x90, 0x01, 0x2b, 0x19, 0xd0, -0x80, 0x7b, 0x00, 0x28, 0x12, 0xd0, 0xc8, 0x88, 0xd3, 0x8a, 0x18, 0x1a, 0x00, 0xd5, 0x40, 0x42, -0xbb, 0x7a, 0x98, 0x42, 0x0a, 0xda, 0x08, 0x89, 0x14, 0x8b, 0x20, 0x1a, 0x00, 0xd5, 0x40, 0x42, -0x98, 0x42, 0x03, 0xda, 0x50, 0x8b, 0xc8, 0x80, 0x90, 0x8b, 0x08, 0x81, 0xff, 0xf7, 0xae, 0xfb, -0x07, 0xb0, 0xf0, 0xbd, 0xf8, 0x7a, 0x00, 0x25, 0x00, 0x28, 0xf7, 0xd9, 0x45, 0x4e, 0x30, 0x46, -0xe1, 0x30, 0x02, 0x90, 0x80, 0x1c, 0xc2, 0x36, 0x01, 0x90, 0x38, 0x7b, 0x00, 0x24, 0x06, 0x90, -0x00, 0x28, 0x67, 0xd9, 0x02, 0x98, 0x32, 0x7b, 0x41, 0x7b, 0x00, 0x7b, 0x09, 0x02, 0x01, 0x43, -0x70, 0x7b, 0x00, 0x02, 0x10, 0x43, 0x68, 0x43, 0x09, 0x18, 0x35, 0x48, 0x01, 0x9a, 0xc0, 0x88, -0x05, 0x90, 0x08, 0x1a, 0x01, 0xb2, 0x48, 0x42, 0x04, 0x90, 0x53, 0x7b, 0x12, 0x7b, 0x1b, 0x02, -0x38, 0x78, 0x13, 0x43, 0x03, 0x93, 0x73, 0x7f, 0x32, 0x7f, 0x1b, 0x02, 0x13, 0x43, 0x2c, 0x4a, -0x9e, 0x46, 0x12, 0x89, 0x94, 0x46, 0x72, 0x46, 0x03, 0x9b, 0x62, 0x43, 0x9a, 0x18, 0x63, 0x46, -0xd2, 0x1a, 0x12, 0xb2, 0x00, 0x29, 0x01, 0xdb, 0x0b, 0x46, 0x00, 0xe0, 0x04, 0x9b, 0x83, 0x42, -0x33, 0xda, 0x00, 0x2a, 0x00, 0xda, 0x52, 0x42, 0x82, 0x42, 0x2e, 0xda, 0x00, 0x99, 0x01, 0x20, -0x88, 0x73, 0x23, 0x49, 0x05, 0x98, 0xc8, 0x82, 0x60, 0x46, 0x08, 0x83, 0x03, 0x20, 0x03, 0xf0, -0x55, 0xf8, 0x02, 0x99, 0x4a, 0x7b, 0x0b, 0x7b, 0x11, 0x02, 0x19, 0x43, 0x72, 0x7b, 0x33, 0x7b, -0x12, 0x02, 0x1a, 0x43, 0x6a, 0x43, 0x89, 0x18, 0x08, 0x1a, 0x15, 0x49, 0xc8, 0x80, 0x03, 0x20, -0x03, 0xf0, 0x44, 0xf8, 0x01, 0x99, 0x4a, 0x7b, 0x0b, 0x7b, 0x11, 0x02, 0x19, 0x43, 0x72, 0x7f, -0x33, 0x7f, 0x12, 0x02, 0x1a, 0x43, 0x62, 0x43, 0x89, 0x18, 0x40, 0x18, 0x0c, 0x49, 0x08, 0x81, -0xca, 0x88, 0x0f, 0x49, 0x4a, 0x83, 0x88, 0x83, 0x04, 0xe0, 0x64, 0x1c, 0x06, 0x9a, 0xe4, 0xb2, -0xa2, 0x42, 0xb8, 0xd8, 0x00, 0x98, 0x80, 0x7b, 0x00, 0x28, 0x00, 0xd0, 0x7e, 0xe7, 0x6d, 0x1c, -0xf8, 0x7a, 0xed, 0xb2, 0xa8, 0x42, 0x88, 0xd8, 0x78, 0xe7, 0x00, 0x00, 0x68, 0x0d, 0x01, 0x20, -0x68, 0x02, 0x01, 0x20, 0x44, 0x2d, 0x01, 0x20, 0xa4, 0x2d, 0x01, 0x20, 0x88, 0x0d, 0x01, 0x20, -0xcc, 0x00, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0xf8, 0xb5, 0x2f, 0x48, 0x00, 0x78, 0x04, 0x28, -0x02, 0xd3, 0x2e, 0x4d, 0x2e, 0x4c, 0x01, 0xe0, 0x2e, 0x4d, 0x2c, 0x1f, 0x2e, 0x49, 0x4b, 0x7c, -0x2e, 0x49, 0x2f, 0x4a, 0x00, 0x91, 0x01, 0x2b, 0x09, 0xd0, 0x2b, 0x49, 0x4b, 0x7c, 0x03, 0x2b, -0x36, 0xd0, 0x00, 0x98, 0x40, 0x7f, 0x01, 0x28, 0x42, 0xd0, 0x05, 0x20, 0x41, 0xe0, 0x29, 0x48, -0x47, 0x68, 0x06, 0x68, 0x26, 0x48, 0xc0, 0x69, 0xb0, 0x42, 0x04, 0xd0, 0x00, 0x21, 0x3a, 0x46, -0x08, 0x46, 0x02, 0xf0, 0x17, 0xfc, 0x22, 0x48, 0x00, 0x21, 0x81, 0x60, 0xc7, 0x60, 0x22, 0x48, -0x01, 0x21, 0x01, 0x70, 0x01, 0x79, 0xc9, 0x07, 0x05, 0xd0, 0x0b, 0xf0, 0xf1, 0xfd, 0x1e, 0x48, -0x00, 0x79, 0xc0, 0x07, 0xf9, 0xd1, 0x1a, 0x48, 0xc1, 0x69, 0xb1, 0x42, 0x08, 0xd0, 0x00, 0x98, -0x40, 0x7f, 0x01, 0x28, 0x02, 0xd0, 0x05, 0x20, 0x13, 0x49, 0x1a, 0xe0, 0x02, 0x20, 0xfb, 0xe7, -0x87, 0x62, 0xc6, 0x62, 0x27, 0x60, 0x2e, 0x60, 0x0f, 0x48, 0x03, 0x21, 0x01, 0x74, 0xf8, 0xbd, -0x21, 0x68, 0x91, 0x62, 0x29, 0x68, 0xd1, 0x62, 0x11, 0x49, 0x10, 0x4a, 0x0a, 0x60, 0x00, 0x22, -0x4a, 0x60, 0x04, 0x28, 0xf3, 0xd2, 0x28, 0x68, 0x88, 0x60, 0x20, 0x68, 0xc8, 0x60, 0xf8, 0xbd, -0x02, 0x20, 0x08, 0x74, 0xf8, 0xbd, 0x00, 0x00, 0xa8, 0x0c, 0x01, 0x20, 0xf8, 0x5f, 0x01, 0x20, -0xfc, 0x5f, 0x01, 0x20, 0xfc, 0xff, 0x08, 0x20, 0x00, 0x00, 0x03, 0x40, 0x08, 0x0e, 0x01, 0x20, -0x00, 0x40, 0x03, 0x40, 0x00, 0x70, 0x0b, 0x20, 0x20, 0x40, 0x03, 0x40, 0x5a, 0x55, 0x33, 0xcc, -0xf0, 0x5f, 0x01, 0x20, 0x70, 0xb5, 0x23, 0x4c, 0xff, 0x20, 0x23, 0x4b, 0x20, 0x76, 0x18, 0x78, -0x02, 0x25, 0x00, 0x07, 0x00, 0x0f, 0x06, 0x07, 0x05, 0x22, 0x20, 0x49, 0x00, 0x2e, 0x0f, 0xdb, -0x40, 0x07, 0x40, 0x0f, 0x01, 0x26, 0x00, 0x28, 0x20, 0xd0, 0x01, 0x28, 0x2f, 0xd0, 0x04, 0x28, -0x28, 0xd0, 0x05, 0x28, 0x28, 0xd0, 0x06, 0x28, 0x01, 0xd1, 0x22, 0x76, 0xce, 0x71, 0x70, 0xbd, -0x0a, 0x28, 0x01, 0xd0, 0x0b, 0x28, 0x03, 0xd1, 0x0a, 0x28, 0x09, 0xd0, 0x04, 0x20, 0x20, 0x76, -0x48, 0x7f, 0x01, 0x28, 0x06, 0xd0, 0x02, 0x28, 0x06, 0xd0, 0x00, 0x20, 0x18, 0x74, 0x70, 0xbd, -0x03, 0x20, 0xf4, 0xe7, 0x1d, 0x74, 0x70, 0xbd, 0x1a, 0x74, 0x70, 0xbd, 0x0c, 0x48, 0x26, 0x76, -0x72, 0xb6, 0x00, 0x22, 0x01, 0x21, 0xfe, 0xf7, 0xa9, 0xf9, 0x62, 0xb6, 0x40, 0x06, 0x06, 0xd5, -0x26, 0x76, 0x70, 0xbd, 0x03, 0x20, 0x00, 0xe0, 0x04, 0x20, 0x20, 0x76, 0x70, 0xbd, 0x25, 0x76, -0x70, 0xbd, 0x00, 0x00, 0x28, 0x0d, 0x01, 0x20, 0x00, 0x00, 0x03, 0x40, 0x08, 0x0e, 0x01, 0x20, -0xc1, 0xd5, 0x03, 0x40, 0x08, 0x48, 0x01, 0x22, 0x01, 0x7d, 0x08, 0x48, 0x00, 0x29, 0x09, 0xd0, -0x03, 0x29, 0x07, 0xd0, 0x00, 0x21, 0x41, 0x73, 0x05, 0x49, 0xc9, 0x7e, 0x00, 0x29, 0x00, 0xd0, -0x42, 0x73, 0x70, 0x47, 0x42, 0x73, 0xf7, 0xe7, 0xa8, 0x0c, 0x01, 0x20, 0x6c, 0x03, 0x01, 0x20, -0x28, 0x0d, 0x01, 0x20, 0xf0, 0xb5, 0x99, 0xb0, 0x73, 0x48, 0x15, 0x90, 0x01, 0x78, 0x73, 0x48, -0x0d, 0x90, 0x00, 0x29, 0x02, 0xd1, 0xc0, 0x7b, 0x00, 0x28, 0x04, 0xd0, 0x0d, 0x98, 0xc0, 0x7d, -0x05, 0x28, 0x02, 0xd2, 0x00, 0x20, 0x19, 0xb0, 0xf0, 0xbd, 0x00, 0x20, 0x6c, 0x4a, 0x0f, 0x90, -0x10, 0x90, 0x6b, 0x46, 0x06, 0xad, 0x11, 0x90, 0x41, 0x00, 0x40, 0x1c, 0x5a, 0x52, 0xc0, 0xb2, -0x6a, 0x52, 0x0b, 0x28, 0xf8, 0xd3, 0x00, 0x20, 0x04, 0x46, 0x13, 0x90, 0x0d, 0x98, 0x00, 0x25, -0xc0, 0x7d, 0x0c, 0x90, 0xc0, 0x1e, 0x18, 0x90, 0x0c, 0x98, 0x80, 0x1e, 0x17, 0x90, 0x0c, 0x98, -0x40, 0x1e, 0x16, 0x90, 0x60, 0x1c, 0x12, 0x90, 0x14, 0x20, 0x29, 0x46, 0x41, 0x43, 0x5d, 0x48, -0x0e, 0x18, 0xf0, 0x7c, 0x00, 0x28, 0x5c, 0xd0, 0x0f, 0xab, 0x58, 0x5d, 0x00, 0x28, 0x12, 0xd1, -0xf0, 0x88, 0x71, 0x89, 0x6a, 0x46, 0x40, 0x1a, 0x00, 0xb2, 0x69, 0x00, 0x50, 0x52, 0x32, 0x89, -0xb7, 0x89, 0xd2, 0x1b, 0x12, 0xb2, 0x06, 0xaf, 0x7a, 0x52, 0x00, 0x28, 0x03, 0xd0, 0x00, 0x2a, -0x01, 0xd0, 0x01, 0x20, 0x13, 0x90, 0x01, 0x20, 0x58, 0x55, 0x18, 0x98, 0xa0, 0x42, 0x20, 0xd1, -0x68, 0x00, 0x69, 0x46, 0x14, 0x90, 0x08, 0x5e, 0x0e, 0x90, 0x60, 0x43, 0x0c, 0x99, 0xfd, 0xf7, -0x33, 0xfc, 0x07, 0x46, 0x0c, 0x99, 0x0e, 0x98, 0xfd, 0xf7, 0x2e, 0xfc, 0x40, 0x10, 0x38, 0x18, -0x00, 0xb2, 0x0e, 0x90, 0x14, 0x98, 0x06, 0xa9, 0x08, 0x5e, 0x14, 0x90, 0x60, 0x43, 0x0c, 0x99, -0xfd, 0xf7, 0x22, 0xfc, 0x07, 0x46, 0x0c, 0x99, 0x14, 0x98, 0xfd, 0xf7, 0x1d, 0xfc, 0x40, 0x10, -0x5e, 0xe0, 0x17, 0x98, 0xa0, 0x42, 0x34, 0xd1, 0x6f, 0x00, 0x68, 0x46, 0xc0, 0x5f, 0x12, 0x99, -0x48, 0x43, 0x0c, 0x99, 0xfd, 0xf7, 0x10, 0xfc, 0x00, 0xb2, 0x0e, 0x90, 0x06, 0xa8, 0xc0, 0x5f, -0x12, 0x99, 0x48, 0x43, 0x0c, 0x99, 0xfd, 0xf7, 0x07, 0xfc, 0x72, 0x89, 0x0e, 0x99, 0x00, 0xb2, -0x51, 0x18, 0xf1, 0x80, 0xb1, 0x89, 0x08, 0x18, 0x30, 0x81, 0x00, 0x2c, 0x52, 0xd0, 0x02, 0x20, -0xb0, 0x74, 0x6d, 0x1c, 0xed, 0xb2, 0x0b, 0x2d, 0x96, 0xd3, 0x13, 0x98, 0x00, 0x28, 0x00, 0xd1, -0x71, 0xe7, 0x05, 0xf0, 0x8f, 0xfb, 0x15, 0x98, 0x40, 0x78, 0x01, 0xf0, 0x33, 0xf9, 0x12, 0x98, -0xc4, 0xb2, 0x0d, 0x98, 0xc0, 0x7d, 0xa0, 0x42, 0x00, 0xd3, 0x77, 0xe7, 0x01, 0x20, 0x19, 0xb0, -0xf0, 0xbd, 0x16, 0x98, 0xa0, 0x42, 0x25, 0xd1, 0x68, 0x00, 0x69, 0x46, 0x14, 0x90, 0x08, 0x5e, -0x0e, 0x90, 0x60, 0x43, 0x0c, 0x99, 0xfd, 0xf7, 0xd7, 0xfb, 0x07, 0x46, 0x0c, 0x99, 0x0e, 0x98, -0xfd, 0xf7, 0xd2, 0xfb, 0x80, 0x10, 0x41, 0x00, 0x40, 0x18, 0x38, 0x18, 0x00, 0xb2, 0x0e, 0x90, -0x14, 0x98, 0x06, 0xa9, 0x08, 0x5e, 0x14, 0x90, 0x60, 0x43, 0x0c, 0x99, 0xfd, 0xf7, 0xc4, 0xfb, -0x07, 0x46, 0x0c, 0x99, 0x14, 0x98, 0xfd, 0xf7, 0xbf, 0xfb, 0x80, 0x10, 0x41, 0x00, 0x40, 0x18, -0x38, 0x18, 0xb2, 0xe7, 0x6f, 0x00, 0x68, 0x46, 0xc0, 0x5f, 0x0c, 0x99, 0x60, 0x43, 0xfd, 0xf7, -0xb3, 0xfb, 0x00, 0xb2, 0x0e, 0x90, 0x06, 0xa8, 0xc0, 0x5f, 0x0c, 0x99, 0x60, 0x43, 0xfd, 0xf7, -0xab, 0xfb, 0xa2, 0xe7, 0x01, 0x20, 0xab, 0xe7, 0x08, 0x0e, 0x01, 0x20, 0xa8, 0x0d, 0x01, 0x20, -0xff, 0x1f, 0x00, 0x00, 0x68, 0x02, 0x01, 0x20, 0xf0, 0xb5, 0x07, 0x46, 0x85, 0xb0, 0x00, 0x20, -0x03, 0x90, 0x01, 0x90, 0x39, 0x48, 0x3a, 0x4c, 0x80, 0x7a, 0x01, 0x26, 0x00, 0x90, 0x01, 0x28, -0x5b, 0xd9, 0x35, 0x46, 0x06, 0x20, 0x45, 0x43, 0x35, 0x48, 0x29, 0x18, 0x02, 0x91, 0x08, 0x88, -0x22, 0x88, 0x80, 0x1a, 0x00, 0xd5, 0x40, 0x42, 0x82, 0xb2, 0x48, 0x88, 0x61, 0x88, 0x40, 0x1a, -0x00, 0xd5, 0x40, 0x42, 0x01, 0xb2, 0x10, 0xb2, 0xfe, 0xf7, 0x7e, 0xff, 0x1e, 0x28, 0x3f, 0xd3, -0x02, 0x98, 0x63, 0x88, 0x41, 0x88, 0x2a, 0x4a, 0x08, 0x46, 0x0a, 0x30, 0x98, 0x42, 0x47, 0xd3, -0x01, 0x98, 0x00, 0x28, 0x07, 0xd0, 0x00, 0x2f, 0x2d, 0xd0, 0x20, 0x88, 0x51, 0x5b, 0x0a, 0x30, -0x81, 0x42, 0x3d, 0xd8, 0x2b, 0xe0, 0x50, 0x5b, 0x23, 0x88, 0x00, 0x2f, 0x02, 0xd0, 0x98, 0x42, -0x02, 0xd8, 0x04, 0xe0, 0x98, 0x42, 0x02, 0xd2, 0x01, 0x20, 0x03, 0x90, 0x1f, 0xe0, 0x13, 0x88, -0x80, 0xb2, 0xc3, 0x1a, 0x50, 0x33, 0xa0, 0x2b, 0x0a, 0xd9, 0x52, 0x88, 0x89, 0x1a, 0x32, 0x31, -0x64, 0x29, 0x05, 0xd9, 0x03, 0x99, 0x00, 0x29, 0x02, 0xd0, 0x01, 0x20, 0x01, 0x90, 0x0e, 0xe0, -0x21, 0x88, 0x00, 0x2f, 0x03, 0xd0, 0x0a, 0x30, 0x88, 0x42, 0x19, 0xd3, 0x07, 0xe0, 0x0a, 0x31, -0x88, 0x42, 0x15, 0xd8, 0x03, 0xe0, 0x50, 0x5b, 0x21, 0x88, 0x88, 0x42, 0x10, 0xd3, 0x02, 0x9c, -0x76, 0x1c, 0x00, 0x98, 0xf6, 0xb2, 0x86, 0x42, 0xa3, 0xd3, 0x01, 0x46, 0x06, 0x20, 0x41, 0x43, -0x07, 0x48, 0x09, 0x18, 0x40, 0x39, 0x40, 0x88, 0x89, 0x8f, 0x50, 0x30, 0x81, 0x42, 0x02, 0xd2, -0x00, 0x20, 0x05, 0xb0, 0xf0, 0xbd, 0x01, 0x98, 0x05, 0xb0, 0xf0, 0xbd, 0x76, 0x00, 0x01, 0x20, -0xd4, 0x34, 0x01, 0x20, 0xf8, 0xb5, 0x3b, 0x4e, 0x00, 0x24, 0x30, 0x62, 0x00, 0x78, 0xff, 0x25, -0x05, 0x28, 0x03, 0xd0, 0x01, 0x20, 0xf0, 0x71, 0x00, 0x20, 0xf8, 0xbd, 0xff, 0xf7, 0x4a, 0xfa, -0xf0, 0x79, 0x00, 0x28, 0x1a, 0xd0, 0x00, 0x20, 0xf0, 0x71, 0xff, 0x20, 0x09, 0xf0, 0x32, 0xf8, -0x31, 0x4d, 0x32, 0x4f, 0x60, 0x00, 0x29, 0x5a, 0x39, 0x52, 0x20, 0x46, 0x14, 0x21, 0x48, 0x43, -0x31, 0x6a, 0x2f, 0x4a, 0x41, 0x18, 0x80, 0x18, 0x14, 0x22, 0x89, 0x1d, 0xfd, 0xf7, 0x84, 0xfa, -0x64, 0x1c, 0xe4, 0xb2, 0x05, 0x2c, 0xed, 0xd3, 0x00, 0x20, 0xf8, 0xbd, 0x02, 0xf0, 0x5e, 0xfd, -0x28, 0x4f, 0x04, 0x28, 0x02, 0xd0, 0x05, 0x28, 0x18, 0xd1, 0x0b, 0xe0, 0x04, 0x20, 0x09, 0xf0, -0x11, 0xf8, 0x25, 0x48, 0xb9, 0x7f, 0x00, 0x79, 0x88, 0x42, 0x0f, 0xd3, 0x30, 0x6a, 0x00, 0x78, -0x30, 0x30, 0x0a, 0xe0, 0x05, 0x20, 0x09, 0xf0, 0x05, 0xf8, 0x1f, 0x48, 0xf9, 0x7f, 0x40, 0x79, -0x88, 0x42, 0x03, 0xd3, 0x30, 0x6a, 0x00, 0x78, 0x40, 0x30, 0xc5, 0xb2, 0xff, 0x2d, 0x16, 0xd0, -0x16, 0x4e, 0x17, 0x4f, 0x14, 0x49, 0x60, 0x00, 0x09, 0x5a, 0x31, 0x52, 0x20, 0x46, 0x14, 0x21, -0x48, 0x43, 0x10, 0x49, 0x14, 0x22, 0x09, 0x6a, 0x41, 0x18, 0xc0, 0x19, 0x89, 0x1d, 0xfd, 0xf7, -0x4b, 0xfa, 0x64, 0x1c, 0xe4, 0xb2, 0x05, 0x2c, 0xec, 0xd3, 0x45, 0x2d, 0x0b, 0xd0, 0xff, 0x24, -0x0e, 0x48, 0x00, 0x78, 0x00, 0x28, 0x08, 0xd0, 0xff, 0x2c, 0x08, 0xd0, 0x21, 0x46, 0x0c, 0xa0, -0x0b, 0xf0, 0x16, 0xfe, 0x04, 0xe0, 0x40, 0x24, 0xf2, 0xe7, 0xff, 0x2c, 0x00, 0xd1, 0x00, 0x24, -0x20, 0x46, 0xf8, 0xbd, 0x38, 0x02, 0x01, 0x20, 0xc0, 0x34, 0x01, 0x20, 0xca, 0x34, 0x01, 0x20, -0x54, 0x38, 0x01, 0x20, 0x8c, 0x00, 0x01, 0x20, 0x61, 0x02, 0x01, 0x20, 0x74, 0x00, 0x01, 0x20, -0x4d, 0x75, 0x6c, 0x74, 0x69, 0x47, 0x73, 0x74, 0x72, 0x49, 0x44, 0x3a, 0x20, 0x25, 0x32, 0x78, -0x0a, 0x00, 0x00, 0x00, 0x10, 0xb5, 0x13, 0x48, 0x72, 0xb6, 0x00, 0x22, 0x01, 0x21, 0xfd, 0xf7, -0x75, 0xff, 0x62, 0xb6, 0x80, 0x07, 0x80, 0x0f, 0x0f, 0x49, 0x02, 0x28, 0x06, 0xd0, 0x01, 0x28, -0x06, 0xd0, 0x00, 0x28, 0x07, 0xd0, 0x03, 0x28, 0x0b, 0xd0, 0x0c, 0xe0, 0x0b, 0x48, 0x00, 0xe0, -0x0b, 0x48, 0x08, 0x60, 0x07, 0xe0, 0x0b, 0x48, 0x00, 0x7e, 0x01, 0x28, 0x03, 0xd0, 0x0a, 0x48, -0xf7, 0xe7, 0x0a, 0x48, 0xf5, 0xe7, 0x0a, 0x48, 0xc0, 0x79, 0x00, 0x28, 0x01, 0xd0, 0x09, 0x48, -0x08, 0x60, 0x10, 0xbd, 0x00, 0xd5, 0x03, 0x40, 0x34, 0x00, 0x01, 0x20, 0x00, 0x5a, 0x62, 0x02, -0x80, 0xf0, 0xfa, 0x02, 0x28, 0x0d, 0x01, 0x20, 0xe0, 0xee, 0xc8, 0x03, 0x20, 0x31, 0xd8, 0x03, -0x08, 0x0e, 0x01, 0x20, 0xa0, 0xc7, 0x70, 0x04, 0x00, 0x28, 0x00, 0xd0, 0x01, 0x20, 0x70, 0x47, -0x03, 0x49, 0x49, 0x79, 0x81, 0x42, 0x01, 0xd3, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, -0xac, 0x1b, 0x01, 0x20, 0xf0, 0xb5, 0x04, 0x46, 0x89, 0xb0, 0x00, 0x20, 0xfe, 0x4f, 0x02, 0x90, -0x38, 0x71, 0x0d, 0x46, 0x21, 0x7b, 0xfd, 0x48, 0x04, 0x90, 0x04, 0x29, 0x0c, 0xd0, 0xfc, 0x49, -0x08, 0x78, 0x00, 0x28, 0x7e, 0xd0, 0xf8, 0x78, 0xfa, 0x4e, 0x00, 0x28, 0x7b, 0xd0, 0x01, 0x28, -0x7a, 0xd0, 0x02, 0x28, 0x79, 0xd0, 0x65, 0xe2, 0x03, 0xf0, 0x5c, 0xf8, 0xf6, 0x48, 0x81, 0x88, -0xf1, 0x48, 0xc0, 0x89, 0x81, 0x42, 0x71, 0xd8, 0xef, 0x48, 0x00, 0x78, 0x00, 0x28, 0x6e, 0xd1, -0x01, 0x20, 0xff, 0xf7, 0x81, 0xfe, 0xf1, 0x4c, 0x00, 0x28, 0x12, 0xd0, 0x08, 0x20, 0x21, 0x18, -0x0a, 0x78, 0x10, 0x46, 0x4a, 0x78, 0x12, 0x02, 0x10, 0x43, 0x8a, 0x78, 0xc9, 0x78, 0x12, 0x04, -0x10, 0x43, 0x09, 0x06, 0x08, 0x43, 0x40, 0x05, 0x03, 0xd5, 0xe3, 0x48, 0x21, 0x21, 0x01, 0x71, -0x5c, 0xe1, 0x00, 0x20, 0xff, 0xf7, 0x68, 0xfe, 0x00, 0x28, 0x12, 0xd0, 0x08, 0x20, 0x21, 0x18, -0x0a, 0x78, 0x10, 0x46, 0x4a, 0x78, 0x12, 0x02, 0x10, 0x43, 0x8a, 0x78, 0xc9, 0x78, 0x12, 0x04, -0x10, 0x43, 0x09, 0x06, 0x08, 0x43, 0x00, 0x05, 0x03, 0xd5, 0xd7, 0x48, 0x20, 0x21, 0x01, 0x71, -0x44, 0xe1, 0x00, 0xf0, 0x55, 0xfb, 0x00, 0x28, 0x12, 0xd0, 0x08, 0x20, 0x21, 0x18, 0x0a, 0x78, -0x10, 0x46, 0x4a, 0x78, 0x12, 0x02, 0x10, 0x43, 0x8a, 0x78, 0xc9, 0x78, 0x12, 0x04, 0x10, 0x43, -0x09, 0x06, 0x08, 0x43, 0x80, 0x06, 0x03, 0xd5, 0xcb, 0x48, 0x13, 0x21, 0x01, 0x71, 0x2d, 0xe1, -0xcd, 0x48, 0x00, 0x25, 0x80, 0x7b, 0x00, 0x28, 0x72, 0xd1, 0xcd, 0x48, 0x06, 0x90, 0x00, 0x20, -0x05, 0x90, 0x04, 0x46, 0x01, 0x90, 0x00, 0x90, 0xca, 0x48, 0x07, 0x90, 0x0b, 0xf0, 0x80, 0xfa, -0x05, 0x98, 0x00, 0x28, 0x06, 0xd0, 0x60, 0x06, 0x40, 0x0e, 0x03, 0xd0, 0x80, 0x21, 0x08, 0x1a, -0x00, 0x19, 0x84, 0xb2, 0x06, 0x98, 0x02, 0x19, 0x15, 0x46, 0x00, 0x20, 0x11, 0x5c, 0x00, 0x29, -0x0c, 0xd0, 0x05, 0xe0, 0xbd, 0xe1, 0xbe, 0xe1, 0xd0, 0xe1, 0xe2, 0xe1, 0x68, 0xe1, 0x61, 0xe1, -0xff, 0x29, 0x03, 0xd0, 0x40, 0x1c, 0xc0, 0xb2, 0x80, 0x28, 0xef, 0xd3, 0x03, 0x90, 0x00, 0x28, -0x67, 0xd0, 0x06, 0x98, 0x00, 0x5d, 0xf1, 0x28, 0x2a, 0xd0, 0xf2, 0x28, 0x30, 0xd0, 0x03, 0x98, -0xb5, 0x4f, 0x40, 0x1c, 0xc3, 0xb2, 0x00, 0x20, 0x01, 0x46, 0x7a, 0x5c, 0x00, 0x2a, 0x05, 0xd0, -0xff, 0x2a, 0x03, 0xd0, 0x49, 0x1c, 0xc9, 0xb2, 0x80, 0x29, 0xf6, 0xd3, 0x8c, 0x46, 0x99, 0x42, -0x71, 0xd8, 0x00, 0x22, 0x00, 0x29, 0x0f, 0xd9, 0x29, 0x5c, 0x00, 0x23, 0xbe, 0x5c, 0x0f, 0x29, -0x1d, 0xd0, 0x8e, 0x42, 0x00, 0xd1, 0x01, 0x23, 0x40, 0x1c, 0xc0, 0xb2, 0x00, 0x2b, 0x62, 0xd0, -0x52, 0x1c, 0xd2, 0xb2, 0x62, 0x45, 0xef, 0xd3, 0x28, 0x5c, 0x00, 0x28, 0x19, 0xd0, 0x5a, 0xe0, -0x68, 0x78, 0x00, 0x90, 0x98, 0x48, 0x91, 0x78, 0x24, 0x1d, 0x01, 0x81, 0xa4, 0xb2, 0xa5, 0xe7, -0xa4, 0x1c, 0x05, 0x98, 0xa4, 0xb2, 0x00, 0x28, 0xa0, 0xd0, 0x00, 0x25, 0x2a, 0xe0, 0x40, 0x1c, -0xc0, 0xb2, 0x29, 0x5c, 0x8e, 0x42, 0x00, 0xd1, 0x01, 0x23, 0x0f, 0x29, 0xf7, 0xd1, 0xdb, 0xe7, -0x38, 0xe0, 0x00, 0x98, 0x16, 0x28, 0x05, 0xd0, 0x12, 0x28, 0x03, 0xd0, 0x01, 0x90, 0x00, 0x28, -0x17, 0xd1, 0x38, 0xe0, 0x91, 0x4b, 0x07, 0x99, 0x18, 0x88, 0x0a, 0x88, 0x80, 0x1a, 0x00, 0xd5, -0x40, 0x42, 0x82, 0xb2, 0x58, 0x88, 0x49, 0x88, 0x40, 0x1a, 0x00, 0xd5, 0x40, 0x42, 0x01, 0xb2, -0x10, 0xb2, 0xfe, 0xf7, 0x49, 0xfd, 0x84, 0x49, 0x89, 0x89, 0x81, 0x42, 0x1f, 0xd9, 0x13, 0x20, -0x01, 0x90, 0x01, 0x9d, 0x80, 0x49, 0x00, 0x2d, 0x0a, 0x78, 0x07, 0xd0, 0x28, 0x07, 0x00, 0x0f, -0x01, 0x23, 0x40, 0x1e, 0x83, 0x40, 0x13, 0x42, 0x00, 0xd0, 0x00, 0x25, 0x80, 0x48, 0x00, 0x78, -0x00, 0x28, 0x07, 0xd0, 0x7f, 0x48, 0x89, 0x7a, 0x02, 0x78, 0x7f, 0xa0, 0x49, 0x1c, 0x52, 0x1c, -0x0b, 0xf0, 0x8e, 0xfc, 0x70, 0x4c, 0x00, 0x2d, 0x25, 0x71, 0x09, 0xd0, 0x73, 0xe0, 0x00, 0x98, -0x01, 0x90, 0xc4, 0xe7, 0xff, 0xe7, 0x03, 0x98, 0x20, 0x18, 0x40, 0x1c, 0x84, 0xb2, 0x4d, 0xe7, -0x20, 0x78, 0x00, 0x28, 0x71, 0xd1, 0xe0, 0x78, 0x00, 0x28, 0x6e, 0xd0, 0x6a, 0x4e, 0x00, 0x25, -0x71, 0x78, 0x09, 0x06, 0x2f, 0xd4, 0x6f, 0x49, 0x09, 0x78, 0x00, 0x29, 0x03, 0xd1, 0x02, 0x28, -0x01, 0xd9, 0xe5, 0x70, 0x27, 0xe0, 0x72, 0x7c, 0xa1, 0x89, 0x8a, 0x42, 0x25, 0xd8, 0x72, 0x8a, -0x8a, 0x42, 0x22, 0xd3, 0x01, 0x28, 0x02, 0xd0, 0x03, 0x28, 0x03, 0xd0, 0x1b, 0xe0, 0x02, 0x20, -0xe0, 0x70, 0x18, 0xe0, 0x6c, 0x4a, 0x6d, 0x4f, 0x50, 0x88, 0x79, 0x88, 0x40, 0x1a, 0x01, 0xb2, -0x10, 0x88, 0x3a, 0x88, 0x80, 0x1a, 0x00, 0xb2, 0xfe, 0xf7, 0xee, 0xfc, 0x31, 0x7d, 0x88, 0x42, -0x02, 0xd2, 0x50, 0x20, 0x20, 0x71, 0x01, 0xe0, 0x01, 0x20, 0x60, 0x71, 0xe5, 0x70, 0x20, 0x79, -0x84, 0x46, 0x50, 0x28, 0x06, 0xd0, 0x25, 0x71, 0x37, 0xe0, 0x03, 0x28, 0xd1, 0xd1, 0x01, 0x20, -0x60, 0x71, 0xce, 0xe7, 0x01, 0x20, 0x20, 0x70, 0x4b, 0x48, 0x5b, 0x4e, 0x80, 0x88, 0xe0, 0x81, -0x4e, 0x49, 0x33, 0x88, 0x0b, 0x80, 0x5a, 0x48, 0x72, 0x88, 0x4a, 0x80, 0x43, 0x83, 0x05, 0x46, -0x82, 0x83, 0x2a, 0x8b, 0xc2, 0x83, 0x3b, 0x88, 0x8b, 0x81, 0x7a, 0x88, 0xca, 0x81, 0x04, 0x25, -0x35, 0x73, 0xc3, 0x84, 0x01, 0x46, 0x02, 0x85, 0x89, 0x8c, 0x41, 0x85, 0x3e, 0x48, 0x85, 0x72, -0x43, 0x48, 0x00, 0x78, 0x00, 0x28, 0x10, 0xd0, 0x61, 0x46, 0x4e, 0xa0, 0x0b, 0xf0, 0x18, 0xfc, -0x20, 0x79, 0x00, 0x28, 0x09, 0xd0, 0x20, 0x79, 0x50, 0x28, 0x06, 0xd0, 0x32, 0x4c, 0x20, 0x79, -0x00, 0xf0, 0x16, 0xff, 0x00, 0x28, 0x00, 0xd1, 0x20, 0x71, 0x33, 0x4d, 0xa8, 0x7a, 0x7f, 0x28, -0x0e, 0xd2, 0x36, 0x4b, 0x06, 0x21, 0x41, 0x43, 0xca, 0x18, 0x04, 0x99, 0x40, 0x1c, 0x8c, 0x89, -0x14, 0x80, 0xcc, 0x89, 0x54, 0x80, 0x09, 0x8a, 0xc0, 0xb2, 0x91, 0x80, 0x7f, 0x28, 0xf1, 0xd3, -0xa8, 0x7b, 0x00, 0x28, 0x2f, 0xd1, 0x24, 0x4e, 0x30, 0x79, 0x00, 0x28, 0x2b, 0xd0, 0x50, 0x28, -0x29, 0xd0, 0xff, 0x20, 0x29, 0x4f, 0x70, 0x70, 0x00, 0x24, 0x20, 0x46, 0x06, 0x21, 0x48, 0x43, -0x3a, 0x5a, 0xc1, 0x19, 0xc8, 0x88, 0x10, 0x1a, 0x4a, 0x88, 0x09, 0x89, 0x00, 0xb2, 0x51, 0x1a, -0x09, 0xb2, 0xfe, 0xf7, 0x79, 0xfc, 0x02, 0x99, 0x64, 0x1c, 0x40, 0x18, 0x80, 0xb2, 0x02, 0x90, -0xa8, 0x7a, 0xe4, 0xb2, 0xa0, 0x42, 0xe8, 0xd2, 0x33, 0x89, 0x02, 0x98, 0x98, 0x42, 0x01, 0xd8, -0x00, 0x20, 0x30, 0x71, 0x1a, 0x48, 0x00, 0x78, 0x00, 0x28, 0x13, 0xd0, 0x31, 0x79, 0x29, 0xa0, -0x02, 0x9a, 0x0b, 0xf0, 0xc5, 0xfb, 0x16, 0x48, 0x00, 0x78, 0x00, 0x28, 0x0a, 0xd0, 0x0a, 0x48, -0x01, 0x79, 0x00, 0x29, 0x06, 0xd1, 0x41, 0x78, 0xff, 0x29, 0x03, 0xd0, 0xff, 0x21, 0x41, 0x70, -0xfa, 0x21, 0x01, 0x71, 0x04, 0x48, 0xc1, 0x78, 0x00, 0x29, 0x01, 0xd1, 0x01, 0x21, 0x01, 0x70, -0x01, 0x48, 0x00, 0x21, 0x81, 0x71, 0x4b, 0xe0, 0x38, 0x02, 0x01, 0x20, 0xc2, 0x37, 0x01, 0x20, -0x68, 0x02, 0x01, 0x20, 0x84, 0x2d, 0x01, 0x20, 0x76, 0x00, 0x01, 0x20, 0x8c, 0x03, 0x01, 0x20, -0x48, 0xee, 0x00, 0x00, 0xce, 0x37, 0x01, 0x20, 0xd4, 0x37, 0x01, 0x20, 0xd4, 0x34, 0x01, 0x20, -0x74, 0x00, 0x01, 0x20, 0x5c, 0x02, 0x01, 0x20, 0x64, 0x72, 0x61, 0x77, 0x50, 0x74, 0x43, 0x6e, -0x74, 0x3a, 0x20, 0x25, 0x64, 0x3b, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x75, -0x6e, 0x74, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0xb8, 0x38, 0x01, 0x20, 0xcc, 0x38, 0x01, 0x20, -0xc0, 0x34, 0x01, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x3a, 0x20, 0x25, 0x78, 0x3b, 0x0a, -0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x3a, 0x20, 0x25, 0x78, 0x3b, 0x20, -0x64, 0x72, 0x61, 0x77, 0x44, 0x69, 0x73, 0x3a, 0x20, 0x25, 0x64, 0x3b, 0x20, 0x64, 0x72, 0x61, -0x77, 0x4d, 0x69, 0x6e, 0x44, 0x69, 0x73, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, -0x00, 0x79, 0x09, 0xb0, 0xf0, 0xbd, 0x78, 0x79, 0x00, 0x28, 0x2b, 0xd0, 0x48, 0x78, 0x00, 0x28, -0x28, 0xd1, 0x30, 0x8c, 0x28, 0x28, 0x25, 0xd2, 0x01, 0x20, 0xf8, 0x70, 0x00, 0x20, 0x78, 0x81, -0x14, 0x22, 0x21, 0x46, 0x96, 0x48, 0xfc, 0xf7, 0x6f, 0xff, 0x1b, 0xe0, 0x94, 0x48, 0x62, 0x88, -0x41, 0x88, 0x00, 0x88, 0x89, 0x1a, 0x22, 0x88, 0x09, 0xb2, 0x80, 0x1a, 0x00, 0xb2, 0xfe, 0xf7, -0xdb, 0xfb, 0x01, 0x46, 0x8f, 0x48, 0x00, 0x7d, 0x81, 0x42, 0x0b, 0xd9, 0x00, 0x20, 0xf8, 0x70, -0x08, 0xe0, 0x03, 0x20, 0xf8, 0x70, 0x14, 0x22, 0x21, 0x46, 0x8b, 0x48, 0xfc, 0xf7, 0x54, 0xff, -0x00, 0x20, 0x78, 0x71, 0x89, 0x48, 0x31, 0x8c, 0x00, 0x7d, 0x81, 0x42, 0x02, 0xd8, 0xb8, 0x79, -0x00, 0x28, 0x04, 0xd0, 0x00, 0x20, 0xf8, 0x70, 0x01, 0x20, 0xb8, 0x71, 0xfd, 0xe0, 0x84, 0x48, -0x84, 0x4a, 0x01, 0x78, 0x14, 0x20, 0x68, 0x43, 0x86, 0x18, 0x00, 0x90, 0x00, 0x29, 0x20, 0xd0, -0x7f, 0x4f, 0x01, 0x20, 0x78, 0x71, 0x00, 0x20, 0xb8, 0x81, 0x38, 0x70, 0x14, 0x22, 0x21, 0x46, -0x30, 0x46, 0xfc, 0xf7, 0x31, 0xff, 0xff, 0x20, 0x78, 0x70, 0x7b, 0x49, 0x00, 0x20, 0x48, 0x55, -0x7a, 0x49, 0x02, 0x46, 0x0a, 0x54, 0x40, 0x1c, 0xc0, 0xb2, 0x80, 0x28, 0xfa, 0xd3, 0x71, 0x49, -0x77, 0x48, 0x8a, 0x72, 0x22, 0x88, 0x02, 0x80, 0x62, 0x88, 0x42, 0x80, 0x01, 0x20, 0x88, 0x72, -0x3c, 0xe0, 0x6f, 0x4f, 0xf9, 0x89, 0x00, 0x29, 0x38, 0xd0, 0x72, 0x48, 0x00, 0x78, 0x00, 0x28, -0x02, 0xd0, 0x71, 0xa0, 0x0b, 0xf0, 0xec, 0xfa, 0x69, 0x48, 0x00, 0x21, 0x81, 0x81, 0x6a, 0x49, -0x48, 0x5d, 0x7f, 0x28, 0x04, 0xd2, 0x69, 0x4b, 0x09, 0x22, 0x1a, 0x54, 0x40, 0x1c, 0x48, 0x55, -0x60, 0x4f, 0xb8, 0x7a, 0x7f, 0x28, 0x19, 0xd2, 0x06, 0x21, 0x41, 0x43, 0x40, 0x1c, 0x64, 0x4a, -0xb8, 0x72, 0x04, 0x98, 0x89, 0x18, 0x82, 0x89, 0x0a, 0x80, 0xc2, 0x89, 0x4a, 0x80, 0x00, 0x8a, -0x88, 0x80, 0xb8, 0x7a, 0x06, 0x22, 0x01, 0x46, 0x50, 0x43, 0x5d, 0x4a, 0x63, 0x88, 0x82, 0x18, -0x53, 0x80, 0x5b, 0x4b, 0x22, 0x88, 0x1a, 0x52, 0x48, 0x1c, 0xb8, 0x72, 0x14, 0x22, 0x21, 0x46, -0x30, 0x46, 0xfc, 0xf7, 0xe1, 0xfe, 0x52, 0x49, 0x09, 0x20, 0x48, 0x70, 0x50, 0x49, 0x00, 0x20, -0xc8, 0x81, 0x50, 0x48, 0x00, 0x99, 0x27, 0x88, 0x40, 0x5a, 0x38, 0x1a, 0x00, 0xd5, 0x40, 0x42, -0x48, 0x49, 0x0b, 0x7a, 0x98, 0x42, 0x7d, 0xdb, 0x62, 0x88, 0x71, 0x88, 0x50, 0x1a, 0x00, 0xd5, -0x40, 0x42, 0x98, 0x42, 0x76, 0xdb, 0x00, 0x20, 0x01, 0x90, 0x30, 0x88, 0x38, 0x1a, 0x8f, 0x1a, -0x00, 0x90, 0x39, 0xb2, 0x00, 0xb2, 0x00, 0xf0, 0x37, 0xf9, 0x01, 0x46, 0x00, 0x98, 0x00, 0x28, -0x00, 0xda, 0x40, 0x42, 0x3b, 0x4a, 0x92, 0x79, 0x90, 0x42, 0x06, 0xda, 0x00, 0x2f, 0x00, 0xda, -0x7f, 0x42, 0x97, 0x42, 0x01, 0xda, 0x01, 0x98, 0x37, 0xe0, 0x16, 0x29, 0x0b, 0xd9, 0x43, 0x29, -0x01, 0xd8, 0x01, 0x20, 0x08, 0xe0, 0x70, 0x29, 0x01, 0xd8, 0x03, 0x20, 0x04, 0xe0, 0x9d, 0x29, -0x01, 0xd8, 0x02, 0x20, 0x00, 0xe0, 0x04, 0x20, 0x31, 0x4a, 0x53, 0x78, 0xff, 0x2b, 0x01, 0xd1, -0x50, 0x70, 0x91, 0x70, 0x53, 0x78, 0x9c, 0x46, 0x83, 0x42, 0x1e, 0xd0, 0x2c, 0x4a, 0xb4, 0x23, -0x92, 0x78, 0x2d, 0x29, 0x06, 0xd2, 0x87, 0x2a, 0x04, 0xd9, 0x9a, 0x1a, 0x52, 0x18, 0x0b, 0xd5, -0x52, 0x42, 0x09, 0xe0, 0x2d, 0x2a, 0x05, 0xd2, 0x87, 0x29, 0x03, 0xd9, 0x5b, 0x1a, 0x9a, 0x18, -0x02, 0xd5, 0xf5, 0xe7, 0x8a, 0x1a, 0xf3, 0xd4, 0x1e, 0x4b, 0xd2, 0xb2, 0xdb, 0x79, 0x93, 0x42, -0x01, 0xdd, 0x60, 0x46, 0x01, 0xe0, 0x1e, 0x4a, 0x91, 0x70, 0x1d, 0x49, 0x00, 0x28, 0x08, 0x71, -0x0f, 0xd0, 0x4a, 0x78, 0x82, 0x42, 0x03, 0xd1, 0x1b, 0x4a, 0x52, 0x5d, 0x00, 0x2a, 0x08, 0xd1, -0x19, 0x4b, 0x48, 0x70, 0x59, 0x5d, 0x19, 0x4a, 0x7f, 0x29, 0x50, 0x54, 0x01, 0xd2, 0x49, 0x1c, -0x59, 0x55, 0x14, 0x22, 0x21, 0x46, 0x30, 0x46, 0xfc, 0xf7, 0x5e, 0xfe, 0x0d, 0x4a, 0x90, 0x7a, -0x7f, 0x28, 0x0b, 0xd2, 0x06, 0x21, 0x12, 0x4b, 0x41, 0x43, 0x65, 0x88, 0xce, 0x18, 0x75, 0x80, -0x25, 0x88, 0x00, 0xe0, 0x09, 0xe0, 0x5d, 0x52, 0x40, 0x1c, 0x90, 0x72, 0x04, 0x20, 0x20, 0x73, -0x12, 0x48, 0x61, 0x88, 0x81, 0x87, 0x21, 0x88, 0x41, 0x87, 0x00, 0x20, 0x09, 0xb0, 0xf0, 0xbd, -0xb8, 0x38, 0x01, 0x20, 0x76, 0x00, 0x01, 0x20, 0xcc, 0x38, 0x01, 0x20, 0xe8, 0x0c, 0x01, 0x20, -0x38, 0x02, 0x01, 0x20, 0x54, 0x38, 0x01, 0x20, 0x5c, 0x02, 0x01, 0x20, 0xd4, 0x37, 0x01, 0x20, -0xd4, 0x34, 0x01, 0x20, 0x74, 0x00, 0x01, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x47, 0x73, 0x74, 0x72, -0x53, 0x70, 0x6c, 0x69, 0x74, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x94, 0x37, 0x01, 0x20, -0xf0, 0xb5, 0x3b, 0x48, 0x89, 0xb0, 0x01, 0x46, 0x20, 0x31, 0x1e, 0xc9, 0x6d, 0x46, 0x1e, 0xc5, -0x41, 0x6b, 0x00, 0x6b, 0x04, 0x90, 0x00, 0x20, 0x05, 0x91, 0x84, 0x46, 0x35, 0x48, 0x36, 0x49, -0x80, 0x7a, 0x0a, 0x88, 0x07, 0x92, 0x4a, 0x88, 0x06, 0x92, 0x06, 0x22, 0x50, 0x43, 0x40, 0x18, -0x40, 0x38, 0x86, 0x46, 0x60, 0x46, 0x81, 0x00, 0x68, 0x46, 0x0c, 0x18, 0x2f, 0x4e, 0x21, 0x46, -0x00, 0x22, 0x88, 0x5c, 0x00, 0x28, 0x05, 0xd0, 0xff, 0x28, 0x03, 0xd0, 0x52, 0x1c, 0xd2, 0xb2, -0x80, 0x2a, 0xf6, 0xd3, 0x00, 0x20, 0x33, 0x46, 0x07, 0x46, 0xd9, 0x5d, 0x00, 0x29, 0x05, 0xd0, -0xff, 0x29, 0x03, 0xd0, 0x7f, 0x1c, 0xff, 0xb2, 0x80, 0x2f, 0xf6, 0xd3, 0x97, 0x42, 0x37, 0xd8, -0x00, 0x22, 0x00, 0x2f, 0x0f, 0xd9, 0x21, 0x5c, 0x00, 0x23, 0xb5, 0x5c, 0x0f, 0x29, 0x0e, 0xd0, -0x8d, 0x42, 0x00, 0xd1, 0x01, 0x23, 0x40, 0x1c, 0xc0, 0xb2, 0x00, 0x2b, 0x28, 0xd0, 0x52, 0x1c, -0xd2, 0xb2, 0xba, 0x42, 0xef, 0xd3, 0x20, 0x5c, 0x00, 0x28, 0x09, 0xd0, 0x20, 0xe0, 0x40, 0x1c, -0xc0, 0xb2, 0x21, 0x5c, 0x8d, 0x42, 0x00, 0xd1, 0x01, 0x23, 0x0f, 0x29, 0xf7, 0xd1, 0xea, 0xe7, -0x72, 0x46, 0x53, 0x8f, 0x07, 0x99, 0x92, 0x8f, 0x06, 0x98, 0x99, 0x42, 0x01, 0xd9, 0xc9, 0x1a, -0x00, 0xe0, 0x59, 0x1a, 0x89, 0xb2, 0x90, 0x42, 0x01, 0xd9, 0x80, 0x1a, 0x00, 0xe0, 0x10, 0x1a, -0x80, 0xb2, 0x32, 0x29, 0x04, 0xd2, 0x32, 0x28, 0x02, 0xd2, 0x13, 0x20, 0x09, 0xb0, 0xf0, 0xbd, -0x60, 0x46, 0x40, 0x1c, 0x84, 0x46, 0x06, 0x28, 0xa4, 0xd3, 0x00, 0x20, 0x09, 0xb0, 0xf0, 0xbd, -0x7c, 0xee, 0x00, 0x00, 0x76, 0x00, 0x01, 0x20, 0xd4, 0x34, 0x01, 0x20, 0xd4, 0x37, 0x01, 0x20, -0x0a, 0x48, 0xc0, 0x78, 0x00, 0x28, 0x10, 0xd0, 0x09, 0x48, 0x00, 0x7d, 0x01, 0x28, 0x0c, 0xd1, -0x10, 0xb5, 0x08, 0x4c, 0x00, 0x20, 0x60, 0x70, 0x60, 0x78, 0x00, 0x28, 0x04, 0xd1, 0x0a, 0xf0, -0xbf, 0xfe, 0x60, 0x78, 0x00, 0x28, 0xfa, 0xd0, 0x10, 0xbd, 0x70, 0x47, 0x48, 0x0d, 0x01, 0x20, -0x6c, 0x03, 0x01, 0x20, 0x8c, 0x03, 0x01, 0x20, 0x70, 0xb5, 0x05, 0x46, 0x00, 0x20, 0x0c, 0x46, -0x00, 0x2d, 0x23, 0xd0, 0x08, 0x46, 0x64, 0x21, 0x48, 0x43, 0x29, 0x46, 0xfc, 0xf7, 0xf4, 0xfd, -0x00, 0x28, 0x00, 0xda, 0x40, 0x42, 0x02, 0x46, 0x10, 0x49, 0x00, 0x20, 0x43, 0x00, 0xcb, 0x5a, -0x93, 0x42, 0x03, 0xdc, 0x40, 0x1c, 0xc0, 0xb2, 0x2d, 0x28, 0xf7, 0xd3, 0x00, 0x2d, 0x04, 0xdd, -0x00, 0x2c, 0x07, 0xdc, 0xb4, 0x21, 0x08, 0x1a, 0x06, 0xe0, 0x00, 0x2c, 0x03, 0xdd, 0x5a, 0x21, -0x08, 0x1a, 0xc0, 0xb2, 0x70, 0xbd, 0x5a, 0x30, 0xc0, 0xb2, 0x70, 0xbd, 0x00, 0x2c, 0x01, 0xdd, -0x2d, 0x20, 0x70, 0xbd, 0x00, 0x29, 0xfc, 0xda, 0x87, 0x20, 0x70, 0xbd, 0xc0, 0xeb, 0x00, 0x00, -0xf8, 0xb5, 0x5b, 0x21, 0x31, 0x48, 0xfc, 0xf7, 0xb7, 0xfd, 0xe1, 0x21, 0x30, 0x48, 0xfc, 0xf7, -0xb3, 0xfd, 0x30, 0x48, 0x00, 0x27, 0x07, 0x60, 0x07, 0x71, 0x2f, 0x48, 0x2f, 0x4d, 0x07, 0x64, -0x47, 0x64, 0x87, 0x64, 0xc7, 0x64, 0x07, 0x65, 0xef, 0x75, 0x28, 0x4e, 0x37, 0x70, 0x2c, 0x4c, -0x0f, 0x20, 0xe0, 0x77, 0x77, 0x70, 0xb7, 0x70, 0x77, 0x71, 0x02, 0xf0, 0x07, 0xf8, 0x70, 0x72, -0x02, 0xf0, 0x02, 0xf8, 0xe8, 0x71, 0x99, 0x20, 0xb0, 0x72, 0x64, 0x20, 0xf0, 0x72, 0x25, 0x49, -0x0a, 0x78, 0x10, 0x46, 0x4a, 0x78, 0x12, 0x02, 0x10, 0x43, 0x8a, 0x78, 0xc9, 0x78, 0x12, 0x04, -0x10, 0x43, 0x09, 0x06, 0x08, 0x43, 0x01, 0x0a, 0x31, 0x73, 0x70, 0x73, 0x1e, 0x4a, 0x90, 0x7b, -0xb0, 0x73, 0xd0, 0x7b, 0xf0, 0x73, 0x01, 0x21, 0x21, 0x74, 0x1c, 0x48, 0x00, 0x7d, 0x60, 0x75, -0xb1, 0x64, 0x01, 0x28, 0x14, 0xd0, 0x02, 0x28, 0x12, 0xd0, 0x21, 0x72, 0x50, 0x7b, 0x28, 0x71, -0x10, 0x7b, 0xe8, 0x70, 0xaf, 0x73, 0x00, 0xf0, 0x0b, 0xfe, 0x15, 0x48, 0x01, 0x68, 0x15, 0x4a, -0x91, 0x42, 0x07, 0xd1, 0x00, 0x7c, 0x30, 0x74, 0x30, 0x7c, 0xff, 0x28, 0x02, 0xd0, 0x02, 0xe0, -0x27, 0x72, 0xeb, 0xe7, 0x37, 0x74, 0x10, 0x48, 0x07, 0x75, 0x00, 0xf0, 0x09, 0xfe, 0xf7, 0x71, -0x77, 0x62, 0xf7, 0x76, 0x27, 0x73, 0xe7, 0x75, 0xf8, 0xbd, 0x00, 0x00, 0x4c, 0x03, 0x01, 0x20, -0xa8, 0x03, 0x01, 0x20, 0x3c, 0x00, 0x01, 0x20, 0x4c, 0x04, 0x01, 0x20, 0x8c, 0x03, 0x01, 0x20, -0x6c, 0x03, 0x01, 0x20, 0x00, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xa8, 0x0c, 0x01, 0x20, -0x00, 0xb0, 0x0b, 0x20, 0x5a, 0xc3, 0x00, 0x00, 0x00, 0x40, 0x03, 0x40, 0x10, 0xb5, 0x0a, 0x4c, -0xfe, 0x20, 0x60, 0x72, 0x06, 0x20, 0x00, 0xf0, 0x8d, 0xfa, 0x00, 0x21, 0x07, 0x48, 0x00, 0xf0, -0xbe, 0xf9, 0xc8, 0x20, 0x00, 0xf0, 0x86, 0xfa, 0xff, 0x20, 0x60, 0x72, 0x06, 0x20, 0x00, 0xf0, -0x81, 0xfa, 0x00, 0x20, 0x20, 0x72, 0x10, 0xbd, 0x00, 0x00, 0x03, 0x40, 0x04, 0xc0, 0x03, 0x40, -0x10, 0xb5, 0xff, 0xf7, 0x9f, 0xfa, 0x19, 0x48, 0x17, 0x49, 0x00, 0x68, 0xfc, 0xf7, 0x1e, 0xfd, -0x17, 0x4a, 0x18, 0x4b, 0x00, 0x21, 0xcc, 0x00, 0x14, 0x5d, 0x84, 0x42, 0x01, 0xd8, 0x59, 0x71, -0x04, 0xe0, 0x49, 0x1c, 0x06, 0x29, 0xf6, 0xdb, 0x05, 0x20, 0x58, 0x71, 0x12, 0x48, 0x40, 0x7c, -0x12, 0x49, 0x01, 0x28, 0x58, 0x79, 0x12, 0xd0, 0xc0, 0x00, 0x80, 0x18, 0x40, 0x78, 0xc8, 0x74, -0x58, 0x79, 0xc0, 0x00, 0x80, 0x18, 0x82, 0x78, 0x8a, 0x74, 0x02, 0x79, 0x4a, 0x74, 0xc2, 0x78, -0x0a, 0x74, 0x0b, 0x49, 0x42, 0x79, 0x0a, 0x73, 0x80, 0x79, 0x48, 0x73, 0x10, 0xbd, 0xc0, 0x00, -0x80, 0x18, 0xc0, 0x79, 0xeb, 0xe7, 0x00, 0x00, 0x40, 0x42, 0x0f, 0x00, 0x34, 0x00, 0x01, 0x20, -0x49, 0xee, 0x00, 0x00, 0xcc, 0x00, 0x01, 0x20, 0x00, 0x00, 0x03, 0x40, 0x20, 0x00, 0x03, 0x40, -0x60, 0x00, 0x03, 0x40, 0xf0, 0xb4, 0x33, 0x4f, 0x8a, 0xb0, 0xff, 0x20, 0xf8, 0x73, 0x32, 0x49, -0x01, 0x26, 0x0e, 0x70, 0x0f, 0x20, 0xc8, 0x70, 0xc8, 0x73, 0x00, 0x20, 0x80, 0x25, 0x6b, 0x46, -0x02, 0x46, 0x42, 0x43, 0x44, 0x00, 0x12, 0x19, 0x1a, 0x54, 0x2a, 0x43, 0x1a, 0x54, 0x40, 0x1c, -0xc0, 0xb2, 0x27, 0x28, 0xf4, 0xd3, 0x00, 0x20, 0x26, 0x24, 0x22, 0x1a, 0x9a, 0x5c, 0x0a, 0x71, -0x1a, 0x5c, 0x4a, 0x71, 0x4e, 0x70, 0x00, 0x22, 0x4a, 0x70, 0x40, 0x1c, 0xc0, 0xb2, 0x27, 0x28, -0xf3, 0xd3, 0xf5, 0x20, 0xf8, 0x73, 0x20, 0x48, 0x01, 0x78, 0x49, 0x08, 0x49, 0x00, 0x01, 0x70, -0xff, 0x20, 0xf8, 0x73, 0x00, 0x20, 0x01, 0x46, 0x41, 0x43, 0x45, 0x00, 0x49, 0x19, 0x19, 0x54, -0x80, 0x25, 0x29, 0x43, 0x19, 0x54, 0x40, 0x1c, 0xc0, 0xb2, 0x27, 0x28, 0xf3, 0xd3, 0x16, 0x49, -0x0e, 0x70, 0x0f, 0x20, 0xc8, 0x70, 0xc8, 0x73, 0x00, 0x20, 0x25, 0x1a, 0x5d, 0x5d, 0x0d, 0x71, -0x1d, 0x5c, 0x4d, 0x71, 0x4e, 0x70, 0x4a, 0x70, 0x40, 0x1c, 0xc0, 0xb2, 0x27, 0x28, 0xf4, 0xd3, -0x7d, 0x23, 0xdb, 0x00, 0x00, 0x20, 0x00, 0xbf, 0x40, 0x1c, 0x98, 0x42, 0xfb, 0xd3, 0x00, 0x20, -0x0b, 0x7a, 0x4b, 0x7a, 0x4e, 0x70, 0x4a, 0x70, 0x40, 0x1c, 0xc0, 0xb2, 0x27, 0x28, 0xf7, 0xd3, -0xf5, 0x20, 0xf8, 0x73, 0x08, 0x78, 0x40, 0x08, 0x40, 0x00, 0x08, 0x70, 0x0a, 0xb0, 0xf0, 0xbc, -0x70, 0x47, 0x00, 0x00, 0xa0, 0x51, 0x03, 0x00, 0xa0, 0x51, 0x03, 0x40, 0xf0, 0xb5, 0x83, 0xb0, -0x00, 0x20, 0x69, 0x46, 0x88, 0x80, 0x49, 0x48, 0x47, 0x4d, 0x42, 0x7a, 0x01, 0x7a, 0x10, 0x06, -0x00, 0x14, 0xac, 0x7d, 0x08, 0x43, 0x02, 0x90, 0x28, 0x7d, 0x00, 0x28, 0x7e, 0xd0, 0x07, 0xf0, -0x59, 0xfd, 0x44, 0x4e, 0x01, 0x21, 0x42, 0x48, 0x37, 0x46, 0x41, 0x74, 0x80, 0x37, 0x42, 0x48, -0x01, 0x78, 0x00, 0x29, 0x02, 0xd0, 0x00, 0x78, 0x01, 0x28, 0x01, 0xd1, 0x0a, 0xf0, 0xcc, 0xfc, -0x07, 0xf0, 0x70, 0xfc, 0x0a, 0xf0, 0x42, 0xfc, 0x38, 0x7e, 0x01, 0x28, 0x30, 0xd0, 0x38, 0x49, -0x00, 0x20, 0x48, 0x74, 0x07, 0xf0, 0x3e, 0xfd, 0x00, 0x20, 0x69, 0x46, 0x88, 0x80, 0x00, 0x94, -0x7f, 0x20, 0x6a, 0x7d, 0x01, 0xab, 0x00, 0x02, 0x02, 0x99, 0xfe, 0xf7, 0xf9, 0xfb, 0x64, 0x1e, -0xe4, 0xb2, 0x01, 0xf0, 0xf5, 0xfb, 0x69, 0x46, 0x88, 0x88, 0x00, 0x28, 0x01, 0xd0, 0x00, 0x2c, -0xd5, 0xd1, 0x2e, 0x4f, 0xb8, 0x7c, 0x00, 0x28, 0x44, 0xd0, 0xf0, 0x79, 0x00, 0x25, 0x00, 0x28, -0x40, 0xd9, 0x28, 0x48, 0x00, 0x24, 0x00, 0x7a, 0x00, 0x28, 0x35, 0xd9, 0x12, 0x20, 0x2e, 0x46, -0x46, 0x43, 0x21, 0x46, 0x28, 0x46, 0x01, 0xf0, 0x63, 0xfe, 0x00, 0x28, 0x26, 0xd1, 0x1b, 0xe0, -0x1f, 0x48, 0x41, 0x7c, 0x00, 0x29, 0xcd, 0xd0, 0x00, 0x21, 0x41, 0x74, 0x30, 0x7d, 0x01, 0x28, -0x01, 0xd0, 0x02, 0x28, 0x04, 0xd1, 0x1e, 0x4a, 0x90, 0x7c, 0xcf, 0x21, 0x08, 0x40, 0x90, 0x74, -0x0a, 0xf0, 0x82, 0xfc, 0x30, 0x7d, 0x00, 0x28, 0x01, 0xd0, 0x03, 0x28, 0x01, 0xd1, 0x07, 0xf0, -0x21, 0xfc, 0x0a, 0xf0, 0xf3, 0xfb, 0xb5, 0xe7, 0x30, 0x19, 0x16, 0x4a, 0x80, 0x00, 0x11, 0x5c, -0x12, 0x23, 0x49, 0x06, 0xfb, 0x56, 0x49, 0x0e, 0xc9, 0x18, 0x11, 0x50, 0x0d, 0x48, 0x64, 0x1c, -0x00, 0x7a, 0xe4, 0xb2, 0xa0, 0x42, 0xcc, 0xd8, 0x0a, 0x48, 0x6d, 0x1c, 0xc0, 0x79, 0xed, 0xb2, -0xa8, 0x42, 0xbe, 0xd8, 0x01, 0xf0, 0xa4, 0xfb, 0x01, 0x20, 0x00, 0xe0, 0x01, 0xe0, 0x0a, 0x49, -0x88, 0x71, 0x03, 0xb0, 0xf0, 0xbd, 0x00, 0x00, 0xa8, 0x0d, 0x01, 0x20, 0xe9, 0x0c, 0x01, 0x20, -0xcc, 0x00, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, 0x08, 0x0e, 0x01, 0x20, -0x00, 0x50, 0x03, 0x40, 0x00, 0x40, 0x02, 0x20, 0x8c, 0x03, 0x01, 0x20, 0x10, 0xb5, 0x0d, 0x49, -0x0a, 0x7d, 0x0d, 0x49, 0x4c, 0x7a, 0x0b, 0x7a, 0x21, 0x06, 0x09, 0x14, 0x19, 0x43, 0x02, 0x2a, -0x04, 0xd0, 0x0a, 0x4a, 0x52, 0x79, 0x03, 0x2a, 0x03, 0xd0, 0x08, 0xe0, 0x49, 0x00, 0x09, 0xb2, -0x05, 0xe0, 0x07, 0x49, 0x4a, 0x7e, 0x0b, 0x7e, 0x11, 0x06, 0x09, 0x14, 0x19, 0x43, 0x08, 0xf0, -0x37, 0xf9, 0x10, 0xbd, 0x6c, 0x03, 0x01, 0x20, 0xe9, 0x0c, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, -0x08, 0x0e, 0x01, 0x20, 0x70, 0xb5, 0x0d, 0x4c, 0x00, 0x25, 0xa5, 0x70, 0x65, 0x71, 0x07, 0xf0, -0xd1, 0xfa, 0x65, 0x70, 0x0a, 0x48, 0x02, 0x21, 0xc1, 0x77, 0x20, 0x78, 0x02, 0x28, 0x08, 0xd1, -0x0a, 0xf0, 0x5e, 0xfc, 0x00, 0x21, 0x02, 0x20, 0x0a, 0xf0, 0x3a, 0xfc, 0x20, 0x78, 0x02, 0x28, -0xf6, 0xd0, 0xa5, 0x70, 0x01, 0x20, 0x60, 0x70, 0x70, 0xbd, 0x00, 0x00, 0x4c, 0x03, 0x01, 0x20, -0x6c, 0x03, 0x01, 0x20, 0x10, 0xb5, 0x07, 0xf0, 0x99, 0xff, 0x10, 0xbd, 0x10, 0xb5, 0x07, 0xf0, -0x95, 0xff, 0x10, 0xbd, 0x10, 0xb5, 0x07, 0xf0, 0x91, 0xff, 0x10, 0xbd, 0x70, 0x47, 0x10, 0xb5, -0x72, 0xb6, 0x00, 0x22, 0x01, 0x21, 0xfd, 0xf7, 0x71, 0xf8, 0x62, 0xb6, 0x10, 0xbd, 0x10, 0xb5, -0x72, 0xb6, 0x0a, 0x46, 0x00, 0x21, 0xfd, 0xf7, 0x69, 0xf8, 0x62, 0xb6, 0x10, 0xbd, 0x70, 0x47, -0x70, 0x47, 0x00, 0x00, 0x12, 0x48, 0x41, 0x79, 0x03, 0x29, 0x20, 0xd0, 0x41, 0x79, 0x01, 0x29, -0x1d, 0xd0, 0x00, 0x78, 0x00, 0x28, 0x1a, 0xd1, 0x10, 0xb5, 0x01, 0xf0, 0x89, 0xfd, 0x00, 0x22, -0x0c, 0x49, 0x0f, 0x28, 0x01, 0xd0, 0x8a, 0x70, 0x10, 0xbd, 0x88, 0x78, 0x40, 0x1c, 0xc0, 0xb2, -0x88, 0x70, 0x03, 0x28, 0xf8, 0xd1, 0x8a, 0x70, 0x07, 0x48, 0x52, 0x21, 0x01, 0x70, 0x53, 0x21, -0x41, 0x70, 0x54, 0x21, 0x81, 0x70, 0x05, 0x49, 0xfe, 0x20, 0x08, 0x72, 0x10, 0xbd, 0x70, 0x47, -0x4c, 0x03, 0x01, 0x20, 0x02, 0x00, 0x01, 0x20, 0xf0, 0x3f, 0x01, 0x20, 0x00, 0x00, 0x03, 0x40, -0x23, 0x48, 0x41, 0x79, 0x03, 0x29, 0x42, 0xd0, 0x41, 0x79, 0x01, 0x29, 0x3f, 0xd0, 0x00, 0x78, -0x00, 0x28, 0x3c, 0xd1, 0x1f, 0x48, 0x80, 0x7d, 0x03, 0x28, 0x38, 0xd1, 0xf8, 0xb5, 0x1e, 0x48, -0xff, 0xf7, 0xad, 0xff, 0x06, 0x46, 0x1d, 0x48, 0xff, 0xf7, 0xa9, 0xff, 0x1c, 0x48, 0xff, 0xf7, -0xa6, 0xff, 0x07, 0x46, 0x1b, 0x48, 0xff, 0xf7, 0xa2, 0xff, 0x00, 0x90, 0x1a, 0x48, 0xff, 0xf7, -0x9e, 0xff, 0x05, 0x46, 0x19, 0x48, 0xff, 0xf7, 0x9a, 0xff, 0x04, 0x06, 0x18, 0x48, 0xff, 0xf7, -0x96, 0xff, 0x00, 0x04, 0x04, 0x19, 0x17, 0x48, 0xff, 0xf7, 0x91, 0xff, 0x00, 0x02, 0x04, 0x19, -0x15, 0x48, 0xff, 0xf7, 0x8c, 0xff, 0x79, 0x06, 0x49, 0x0e, 0x02, 0x22, 0x00, 0x19, 0x11, 0x43, -0x9c, 0x2e, 0x02, 0xd0, 0xea, 0x43, 0x92, 0x07, 0x06, 0xd1, 0x00, 0x28, 0x04, 0xd0, 0x73, 0x29, -0x02, 0xd1, 0x00, 0x98, 0x80, 0x06, 0x01, 0xd5, 0x00, 0xf0, 0xfa, 0xf9, 0xf8, 0xbd, 0x70, 0x47, -0x4c, 0x03, 0x01, 0x20, 0xe8, 0x0d, 0x01, 0x20, 0x28, 0xc0, 0x03, 0x40, 0x27, 0xc0, 0x03, 0x40, -0x25, 0xc0, 0x03, 0x40, 0x26, 0xc0, 0x03, 0x40, 0x34, 0xc0, 0x03, 0x40, 0x83, 0xd0, 0x03, 0x40, -0x82, 0xd0, 0x03, 0x40, 0x81, 0xd0, 0x03, 0x40, 0x80, 0xd0, 0x03, 0x40, 0x10, 0xb5, 0x07, 0xf0, -0xee, 0xfe, 0x10, 0xbd, 0x10, 0xb5, 0x00, 0xf0, 0xcd, 0xf9, 0x07, 0x4c, 0x00, 0x20, 0x60, 0x70, -0x06, 0x48, 0x0f, 0x21, 0xc1, 0x77, 0x20, 0x78, 0x0f, 0x28, 0x04, 0xd1, 0x0a, 0xf0, 0x90, 0xfb, -0x20, 0x78, 0x0f, 0x28, 0xfa, 0xd0, 0x10, 0xbd, 0x4c, 0x03, 0x01, 0x20, 0x6c, 0x03, 0x01, 0x20, -0x00, 0x23, 0x00, 0x28, 0x11, 0xd9, 0x30, 0xb4, 0x08, 0x4d, 0x09, 0x4c, 0xe9, 0x7c, 0x0a, 0x5d, -0x00, 0x21, 0x00, 0x2a, 0x03, 0xd9, 0x00, 0xbf, 0x49, 0x1c, 0x91, 0x42, 0xfb, 0xd3, 0x5b, 0x1c, -0x9b, 0xb2, 0x83, 0x42, 0xf2, 0xd3, 0x30, 0xbc, 0x70, 0x47, 0x70, 0x47, 0x20, 0x00, 0x03, 0x40, -0xb6, 0xeb, 0x00, 0x00, 0xf8, 0xb5, 0x00, 0x24, 0x05, 0x46, 0x00, 0x28, 0x13, 0xd9, 0x0a, 0x4e, -0x0a, 0x4f, 0xf1, 0x7c, 0x38, 0x46, 0xfc, 0xf7, 0xa1, 0xfa, 0x01, 0x46, 0x00, 0x20, 0x00, 0x29, -0x03, 0xd9, 0x00, 0xbf, 0x40, 0x1c, 0x88, 0x42, 0xfb, 0xd3, 0x0a, 0xf0, 0x59, 0xfb, 0x64, 0x1c, -0xa4, 0xb2, 0xac, 0x42, 0xed, 0xd3, 0xf8, 0xbd, 0x20, 0x00, 0x03, 0x40, 0xf0, 0x50, 0x00, 0x00, -0x10, 0xb5, 0x02, 0x20, 0x01, 0xf0, 0x2c, 0xfc, 0x00, 0x28, 0x01, 0xd0, 0x07, 0xf0, 0xd0, 0xff, -0x10, 0xbd, 0x00, 0x00, 0xf0, 0xb5, 0x8d, 0xb0, 0x76, 0x48, 0x0b, 0x90, 0x80, 0x7e, 0x00, 0x28, -0x7a, 0xd0, 0x00, 0x20, 0x05, 0x90, 0x74, 0x48, 0x0a, 0x90, 0x00, 0x7e, 0x00, 0x28, 0x73, 0xd9, -0x72, 0x48, 0x06, 0x90, 0x72, 0x48, 0x09, 0x90, 0x05, 0x98, 0x0c, 0x21, 0x48, 0x43, 0x71, 0x49, -0x42, 0x18, 0x11, 0x20, 0x80, 0x01, 0x10, 0x18, 0x01, 0x90, 0x80, 0x7e, 0x03, 0x90, 0x08, 0x18, -0x09, 0x22, 0x12, 0x02, 0x08, 0x90, 0x80, 0x18, 0x80, 0x7d, 0x01, 0x28, 0x36, 0xd0, 0x04, 0x28, -0x34, 0xd0, 0x09, 0x9a, 0x00, 0x20, 0x93, 0x7b, 0x00, 0x2b, 0x75, 0xd9, 0x0d, 0x25, 0xad, 0x01, -0x0c, 0x22, 0x42, 0x43, 0x52, 0x18, 0x52, 0x19, 0x16, 0x7c, 0x03, 0x9a, 0x96, 0x42, 0x6c, 0xd1, -0x01, 0x9b, 0x1c, 0x22, 0x9a, 0x5e, 0x02, 0x92, 0x1e, 0x22, 0x9a, 0x5e, 0x07, 0x92, 0x0c, 0x22, -0x50, 0x43, 0x40, 0x18, 0x40, 0x19, 0x12, 0x21, 0x41, 0x5e, 0x14, 0x27, 0x00, 0x91, 0x02, 0x9a, -0xc7, 0x5f, 0x50, 0x1a, 0x00, 0xd5, 0x40, 0x42, 0x86, 0xb2, 0x07, 0x98, 0xc0, 0x1b, 0x00, 0xd5, -0x40, 0x42, 0x85, 0xb2, 0x29, 0xb2, 0x30, 0xb2, 0xfd, 0xf7, 0x3e, 0xfe, 0x04, 0x90, 0x0b, 0x98, -0x80, 0x7e, 0x02, 0x28, 0x0a, 0xd0, 0x01, 0x28, 0x48, 0xd0, 0x63, 0xe0, 0x03, 0x98, 0x00, 0x21, -0x4d, 0x4a, 0x40, 0x00, 0x11, 0x52, 0x4d, 0x4a, 0x11, 0x52, 0x7f, 0xe0, 0x06, 0x98, 0x41, 0x7e, -0x00, 0x7e, 0x09, 0x02, 0x01, 0x43, 0x04, 0x98, 0x81, 0x42, 0x02, 0xd8, 0xff, 0x24, 0x01, 0x34, -0x08, 0xe0, 0x00, 0x29, 0x03, 0xd0, 0x00, 0x02, 0xfc, 0xf7, 0x10, 0xfa, 0x84, 0xb2, 0x10, 0x2c, -0x00, 0xd2, 0x10, 0x24, 0x03, 0x98, 0x41, 0x4b, 0x40, 0x00, 0x1a, 0x5a, 0x04, 0x99, 0x8a, 0x42, -0x3d, 0x49, 0x02, 0xd9, 0x0c, 0x5a, 0x01, 0xe0, 0x6a, 0xe0, 0x0c, 0x52, 0x04, 0x99, 0x19, 0x52, -0xff, 0x20, 0x01, 0x30, 0x84, 0x42, 0x00, 0xd9, 0x04, 0x46, 0x31, 0x46, 0x22, 0x46, 0x4a, 0x43, -0x12, 0x02, 0x16, 0x0c, 0x28, 0x46, 0x22, 0x46, 0x42, 0x43, 0x12, 0x02, 0x15, 0x0c, 0x00, 0x2c, -0x28, 0xd0, 0x00, 0x2e, 0x02, 0xd1, 0x02, 0x29, 0x00, 0xd9, 0x01, 0x26, 0x00, 0x2d, 0x21, 0xd1, -0x02, 0x28, 0x1f, 0xd9, 0x01, 0x25, 0x1d, 0xe0, 0x40, 0xe0, 0x3a, 0xe0, 0x06, 0x98, 0x41, 0x7e, -0x02, 0x7e, 0x08, 0x02, 0x10, 0x43, 0x04, 0x99, 0xc2, 0x08, 0x8a, 0x42, 0x01, 0xd9, 0x04, 0x20, -0x0e, 0xe0, 0x82, 0x08, 0x8a, 0x42, 0x01, 0xd9, 0x03, 0x20, 0x09, 0xe0, 0x42, 0x08, 0x8a, 0x42, -0x01, 0xd9, 0x02, 0x20, 0x04, 0xe0, 0x88, 0x42, 0x01, 0xd9, 0x01, 0x20, 0x00, 0xe0, 0x00, 0x20, -0xc6, 0x40, 0xc5, 0x40, 0x25, 0x20, 0x08, 0x99, 0x80, 0x01, 0x08, 0x18, 0x80, 0x78, 0x01, 0x28, -0x11, 0xd0, 0x00, 0x99, 0x02, 0x98, 0x88, 0x42, 0x03, 0xdd, 0x88, 0x19, 0x00, 0xb2, 0x00, 0x90, -0x02, 0xe0, 0x88, 0x1b, 0x00, 0xb2, 0x00, 0x90, 0x07, 0x98, 0xb8, 0x42, 0x01, 0xdd, 0x78, 0x19, -0x00, 0xe0, 0x78, 0x1b, 0x07, 0xb2, 0x01, 0x99, 0x00, 0x98, 0x88, 0x83, 0x01, 0x98, 0xc7, 0x83, -0x04, 0xe0, 0x40, 0x1c, 0xc0, 0xb2, 0x83, 0x42, 0x00, 0xd9, 0x49, 0xe7, 0x05, 0x98, 0x40, 0x1c, -0xc0, 0xb2, 0x05, 0x90, 0x0a, 0x98, 0x01, 0x7e, 0x05, 0x98, 0x81, 0x42, 0x00, 0xd9, 0x23, 0xe7, -0x0d, 0xb0, 0xf0, 0xbd, 0x48, 0x0d, 0x01, 0x20, 0x84, 0x28, 0x01, 0x20, 0x4b, 0x0d, 0x01, 0x20, -0x84, 0x27, 0x01, 0x20, 0x44, 0x24, 0x01, 0x20, 0x2a, 0x18, 0x01, 0x20, 0x14, 0x18, 0x01, 0x20, -0x01, 0x20, 0x70, 0x47, 0x18, 0x48, 0x19, 0x4a, 0x01, 0x7d, 0x10, 0x23, 0x00, 0x7c, 0x01, 0x29, -0x02, 0xd0, 0x02, 0x29, 0x0f, 0xd0, 0x70, 0x47, 0x02, 0x28, 0xfc, 0xd1, 0x10, 0x78, 0x00, 0x09, -0x00, 0x01, 0x40, 0x1c, 0x10, 0x70, 0x10, 0x78, 0x00, 0x07, 0x00, 0x0f, 0x10, 0x70, 0x10, 0x78, -0x18, 0x43, 0x10, 0x70, 0x70, 0x47, 0x10, 0xb4, 0x01, 0x21, 0x0d, 0x4c, 0x02, 0x28, 0x10, 0xd0, -0x04, 0x28, 0x0c, 0xd1, 0x10, 0x78, 0x00, 0x09, 0x00, 0x01, 0xc0, 0x1c, 0x10, 0x70, 0xe1, 0x75, -0x10, 0x78, 0x00, 0x07, 0x00, 0x0f, 0x10, 0x70, 0x10, 0x78, 0x18, 0x43, 0x10, 0x70, 0x10, 0xbc, -0x70, 0x47, 0xe1, 0x75, 0x10, 0xbc, 0x70, 0x47, 0xa8, 0x0c, 0x01, 0x20, 0x80, 0x51, 0x03, 0x40, -0x00, 0x50, 0x03, 0x40, 0x02, 0x48, 0x01, 0x78, 0x49, 0x1c, 0x01, 0x70, 0x70, 0x47, 0x00, 0x00, -0x00, 0x00, 0x01, 0x20, 0x06, 0x49, 0x01, 0x20, 0x48, 0x70, 0x06, 0x49, 0x09, 0x7d, 0x00, 0x29, -0x05, 0xd1, 0x05, 0x49, 0x89, 0x78, 0x00, 0x29, 0x01, 0xd1, 0x04, 0x49, 0x88, 0x70, 0x70, 0x47, -0x8c, 0x03, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, 0x18, 0x00, 0x01, 0x20, -0x70, 0x47, 0x00, 0x00, 0x10, 0xb5, 0x04, 0x49, 0x02, 0x48, 0x48, 0x60, 0x0a, 0xf0, 0x1a, 0xf8, -0x10, 0xbd, 0x00, 0x00, 0xa0, 0x86, 0x01, 0x00, 0x00, 0x20, 0x03, 0x40, 0x06, 0x48, 0x01, 0x68, -0x03, 0x22, 0x11, 0x43, 0x01, 0x60, 0x05, 0x4a, 0x81, 0x14, 0x11, 0x60, 0x00, 0x21, 0x81, 0x60, -0x03, 0x49, 0x41, 0x60, 0x70, 0x47, 0x00, 0x00, 0x00, 0x20, 0x03, 0x40, 0x00, 0xe1, 0x00, 0xe0, -0xa0, 0x86, 0x01, 0x00, 0x04, 0x48, 0x01, 0x68, 0x89, 0x08, 0x89, 0x00, 0x01, 0x60, 0x03, 0x49, -0x80, 0x14, 0x08, 0x60, 0x70, 0x47, 0x00, 0x00, 0x00, 0x20, 0x03, 0x40, 0x80, 0xe1, 0x00, 0xe0, -0x12, 0x48, 0x80, 0x7d, 0x01, 0x28, 0x1f, 0xd0, 0x10, 0xb5, 0x11, 0xa0, 0x0a, 0xf0, 0x68, 0xfc, -0x12, 0x48, 0x52, 0x21, 0x01, 0x70, 0x53, 0x21, 0x41, 0x70, 0x54, 0x21, 0x81, 0x70, 0x10, 0x4c, -0xfe, 0x20, 0x60, 0x72, 0x06, 0x20, 0xff, 0xf7, 0x3d, 0xfe, 0x00, 0x21, 0x0d, 0x48, 0xff, 0xf7, -0x6e, 0xfd, 0xc8, 0x20, 0xff, 0xf7, 0x36, 0xfe, 0xff, 0x20, 0x60, 0x72, 0x06, 0x20, 0xff, 0xf7, -0x31, 0xfe, 0x00, 0x20, 0x20, 0x72, 0x10, 0xbd, 0x70, 0x47, 0x00, 0x00, 0xe8, 0x0d, 0x01, 0x20, -0x45, 0x53, 0x44, 0x20, 0x52, 0x45, 0x53, 0x45, 0x54, 0x21, 0x0a, 0x00, 0xf0, 0x3f, 0x01, 0x20, -0x00, 0x00, 0x03, 0x40, 0x04, 0xc0, 0x03, 0x40, 0xf0, 0xb5, 0x8d, 0xb0, 0x00, 0x24, 0xa6, 0x48, -0x08, 0x94, 0xc0, 0x7c, 0xc0, 0x07, 0x17, 0xd0, 0xa4, 0x48, 0x00, 0x7d, 0x00, 0x28, 0x13, 0xd0, -0x00, 0x20, 0x00, 0x90, 0xa2, 0x49, 0x01, 0x90, 0x02, 0x90, 0x03, 0x90, 0x04, 0x90, 0x05, 0x90, -0xa0, 0x4e, 0x4a, 0x8c, 0x71, 0x7d, 0x33, 0x7d, 0x09, 0x02, 0x19, 0x43, 0x8a, 0x42, 0x05, 0xd9, -0x9d, 0x49, 0x88, 0x71, 0x01, 0x20, 0x08, 0x72, 0x0d, 0xb0, 0xf0, 0xbd, 0x9b, 0x49, 0x09, 0x91, -0xca, 0x8b, 0x00, 0x2a, 0x0b, 0xd0, 0x98, 0x49, 0x09, 0x7a, 0x00, 0x29, 0xf4, 0xd1, 0x00, 0x2a, -0x7e, 0xd9, 0x97, 0x4d, 0x68, 0x46, 0x00, 0x5d, 0x00, 0x28, 0x7a, 0xd1, 0x07, 0xe0, 0x92, 0x4b, -0x18, 0x72, 0xd9, 0x79, 0x00, 0x29, 0xe7, 0xd0, 0x49, 0x1e, 0xd9, 0x71, 0xef, 0xe7, 0x91, 0x48, -0x61, 0x00, 0x08, 0x18, 0xe0, 0x30, 0x01, 0x78, 0x06, 0x91, 0x41, 0x78, 0x07, 0x91, 0x06, 0x99, -0x28, 0x20, 0x41, 0x43, 0x8c, 0x48, 0x08, 0x18, 0x07, 0x99, 0x0a, 0x90, 0x49, 0x00, 0x0b, 0x91, -0x41, 0x5e, 0x68, 0x7d, 0x2a, 0x7d, 0x00, 0x02, 0x10, 0x43, 0x81, 0x42, 0x59, 0xdd, 0x69, 0x7d, -0xd0, 0xb2, 0x09, 0x06, 0x0a, 0x14, 0x02, 0x43, 0x83, 0x4b, 0x07, 0x99, 0x06, 0x98, 0x07, 0xf0, -0x05, 0xfb, 0x06, 0x9a, 0x01, 0x21, 0x52, 0x1e, 0x12, 0x06, 0x08, 0x46, 0x12, 0x0e, 0x1b, 0xd0, -0x6b, 0x7d, 0x2f, 0x7d, 0x1b, 0x02, 0x3b, 0x43, 0x0c, 0x93, 0x77, 0x7d, 0x33, 0x7d, 0x3f, 0x02, -0x1f, 0x43, 0xbc, 0x46, 0x28, 0x27, 0x13, 0x46, 0x7b, 0x43, 0x77, 0x4f, 0xdf, 0x19, 0x0b, 0x9b, -0xfb, 0x5e, 0x0c, 0x9f, 0xbb, 0x42, 0x03, 0xdd, 0x63, 0x45, 0x01, 0xda, 0x40, 0x1c, 0xc0, 0xb2, -0x52, 0x1e, 0x12, 0x06, 0x12, 0x0e, 0xed, 0xd1, 0x06, 0x9a, 0x52, 0x1c, 0xd2, 0xb2, 0x20, 0x2a, -0x1b, 0xd8, 0x6b, 0x7d, 0x2f, 0x7d, 0x1b, 0x02, 0x3b, 0x43, 0x06, 0x93, 0x77, 0x7d, 0x33, 0x7d, -0x3f, 0x02, 0x1f, 0x43, 0xbc, 0x46, 0x28, 0x27, 0x13, 0x46, 0x7b, 0x43, 0x66, 0x4f, 0xdf, 0x19, -0x0b, 0x9b, 0xfb, 0x5e, 0x06, 0x9f, 0xbb, 0x42, 0x03, 0xdd, 0x63, 0x45, 0x01, 0xda, 0x40, 0x1c, -0xc0, 0xb2, 0x52, 0x1c, 0xd2, 0xb2, 0x20, 0x2a, 0xed, 0xd9, 0x07, 0x9a, 0x52, 0x1e, 0x12, 0x06, -0x12, 0x0e, 0x1a, 0xd0, 0x6b, 0x7d, 0x2f, 0x7d, 0x1b, 0x02, 0x3b, 0x43, 0x06, 0x93, 0x01, 0xe0, -0x6c, 0xe0, 0x4b, 0xe0, 0x77, 0x7d, 0x33, 0x7d, 0x3f, 0x02, 0x1f, 0x43, 0xbc, 0x46, 0x0a, 0x9b, -0x57, 0x00, 0xdb, 0x5f, 0x06, 0x9f, 0xbb, 0x42, 0x03, 0xdd, 0x63, 0x45, 0x01, 0xda, 0x49, 0x1c, -0xc9, 0xb2, 0x52, 0x1e, 0x12, 0x06, 0x12, 0x0e, 0xf1, 0xd1, 0x07, 0x9a, 0x52, 0x1c, 0xd2, 0xb2, -0x12, 0x2a, 0x17, 0xd8, 0x6b, 0x7d, 0x2f, 0x7d, 0x1b, 0x02, 0x3b, 0x43, 0x06, 0x93, 0x77, 0x7d, -0x33, 0x7d, 0x3f, 0x02, 0x1f, 0x43, 0xbc, 0x46, 0x0a, 0x9b, 0x57, 0x00, 0xdb, 0x5f, 0x06, 0x9f, -0xbb, 0x42, 0x03, 0xdd, 0x63, 0x45, 0x01, 0xda, 0x49, 0x1c, 0xc9, 0xb2, 0x52, 0x1c, 0xd2, 0xb2, -0x12, 0x2a, 0xf1, 0xd9, 0x81, 0x42, 0x01, 0xd9, 0x02, 0x46, 0x00, 0xe0, 0x0a, 0x46, 0x01, 0x2a, -0x03, 0xd1, 0x39, 0x4a, 0x92, 0x8d, 0x03, 0x2a, 0x0c, 0xd2, 0x81, 0x42, 0x00, 0xd8, 0x08, 0x46, -0x02, 0x28, 0x0b, 0xd1, 0x34, 0x48, 0x80, 0x8d, 0x08, 0x28, 0x07, 0xd3, 0x09, 0x98, 0xc0, 0x8b, -0x01, 0x28, 0x03, 0xd1, 0x01, 0x20, 0x69, 0x46, 0x08, 0x55, 0x08, 0x90, 0x09, 0x98, 0x64, 0x1c, -0xc0, 0x8b, 0xe4, 0xb2, 0xa0, 0x42, 0x00, 0xd9, 0x2c, 0xe7, 0x08, 0x98, 0x00, 0x28, 0x15, 0xd0, -0x29, 0x49, 0x88, 0x79, 0x00, 0x28, 0x08, 0xd1, 0x68, 0x7e, 0x2b, 0x7e, 0x02, 0x02, 0xc8, 0x79, -0x1a, 0x43, 0x82, 0x42, 0x07, 0xd8, 0x01, 0x20, 0x88, 0x71, 0x70, 0x7e, 0x32, 0x7e, 0x00, 0x02, -0x10, 0x43, 0xc8, 0x71, 0x0b, 0xe0, 0x40, 0x1c, 0xc8, 0x71, 0x2d, 0xe0, 0x1e, 0x49, 0xc8, 0x79, -0x00, 0x28, 0x13, 0xd0, 0x40, 0x1e, 0xc8, 0x71, 0x88, 0x79, 0x00, 0x28, 0x24, 0xd0, 0x09, 0x99, -0x00, 0x20, 0xcd, 0x8b, 0x00, 0x2d, 0x1f, 0xd9, 0x71, 0x7d, 0x32, 0x7d, 0x1a, 0x4f, 0x0e, 0x02, -0x16, 0x43, 0x6c, 0x46, 0x21, 0x5c, 0x00, 0x29, 0x12, 0xd1, 0x02, 0xe0, 0x00, 0x20, 0x88, 0x71, -0x12, 0xe0, 0x14, 0x49, 0x42, 0x00, 0x51, 0x18, 0xe0, 0x31, 0x0a, 0x78, 0x28, 0x23, 0x49, 0x78, -0x5a, 0x43, 0xd2, 0x19, 0x49, 0x00, 0x51, 0x5e, 0xb1, 0x42, 0x01, 0xda, 0x01, 0x21, 0x21, 0x54, -0x40, 0x1c, 0xc0, 0xb2, 0x85, 0x42, 0xe5, 0xd8, 0x0c, 0x4a, 0x68, 0x46, 0x11, 0x46, 0x04, 0xf0, -0xdb, 0xfd, 0x0d, 0xb0, 0xf0, 0xbd, 0x00, 0x00, 0xa8, 0x0d, 0x01, 0x20, 0x8c, 0x03, 0x01, 0x20, -0x84, 0x2d, 0x01, 0x20, 0xca, 0x0c, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, 0x04, 0x25, 0x01, 0x20, -0xc8, 0x0c, 0x01, 0x20, 0x44, 0x24, 0x01, 0x20, 0x00, 0x50, 0x01, 0x20, 0x22, 0x25, 0x01, 0x20, -0x04, 0x48, 0x05, 0x49, 0x40, 0x79, 0xc0, 0x00, 0x40, 0x18, 0x04, 0x49, 0xc0, 0x79, 0xc8, 0x74, -0x70, 0x47, 0x00, 0x00, 0xcc, 0x00, 0x01, 0x20, 0x49, 0xee, 0x00, 0x00, 0x20, 0x00, 0x03, 0x40, -0x06, 0x48, 0x40, 0x7c, 0x01, 0x28, 0x07, 0xd0, 0x05, 0x48, 0x06, 0x49, 0x40, 0x79, 0xc0, 0x00, -0x40, 0x18, 0x05, 0x49, 0x40, 0x78, 0xc8, 0x74, 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x03, 0x40, -0xcc, 0x00, 0x01, 0x20, 0x49, 0xee, 0x00, 0x00, 0x20, 0x00, 0x03, 0x40, 0x22, 0x48, 0x00, 0x7d, -0xc0, 0x09, 0x40, 0xd0, 0xf0, 0xb5, 0x21, 0x4f, 0x01, 0x23, 0xf8, 0x79, 0x86, 0x46, 0x01, 0x28, -0x2b, 0xd3, 0x38, 0x46, 0xff, 0x30, 0x63, 0x30, 0x41, 0x7f, 0x00, 0x7f, 0x0e, 0x02, 0x3c, 0x7a, -0x06, 0x43, 0xff, 0x37, 0x81, 0x37, 0x38, 0x78, 0x84, 0x46, 0x00, 0x22, 0x01, 0x20, 0x01, 0x2c, -0x11, 0xd3, 0x19, 0x46, 0x28, 0x25, 0x69, 0x43, 0x15, 0x4d, 0x4d, 0x19, 0x41, 0x00, 0x69, 0x5e, -0x00, 0x29, 0x00, 0xda, 0x49, 0x42, 0xb1, 0x42, 0x01, 0xdd, 0x52, 0x1c, 0xd2, 0xb2, 0x40, 0x1c, -0xc0, 0xb2, 0x84, 0x42, 0xf2, 0xd2, 0x94, 0x45, 0x03, 0xd8, 0x0e, 0x48, 0x79, 0x78, 0x41, 0x72, -0x09, 0xe0, 0x5b, 0x1c, 0xdb, 0xb2, 0x9e, 0x45, 0xdf, 0xd2, 0x0a, 0x49, 0x48, 0x7a, 0x00, 0x28, -0x08, 0xd0, 0x40, 0x1e, 0x48, 0x72, 0x07, 0x48, 0x40, 0x7a, 0x00, 0x28, 0x02, 0xd0, 0x06, 0x49, -0x01, 0x20, 0x88, 0x77, 0xf0, 0xbd, 0x70, 0x47, 0x48, 0x0d, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, -0x00, 0x50, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, 0x84, 0x2d, 0x01, 0x20, 0x70, 0xb5, 0x16, 0x48, -0x16, 0x4d, 0x00, 0x7d, 0x00, 0x28, 0x1a, 0xd0, 0xff, 0xf7, 0x70, 0xfa, 0x28, 0x7d, 0x00, 0x28, -0x01, 0xd0, 0x03, 0x28, 0x0c, 0xd1, 0x12, 0x4c, 0xa0, 0x78, 0x00, 0x28, 0x06, 0xd1, 0x09, 0xf0, -0x9f, 0xff, 0xfd, 0xf7, 0xc1, 0xf9, 0xa0, 0x78, 0x00, 0x28, 0xf8, 0xd0, 0x00, 0x20, 0xa0, 0x70, -0x06, 0xf0, 0xf0, 0xfe, 0x09, 0xf0, 0xc2, 0xfe, 0x07, 0xf0, 0x7a, 0xfe, 0x01, 0xe0, 0x09, 0xf0, -0xbd, 0xfe, 0x28, 0x7d, 0x01, 0x28, 0x01, 0xd0, 0x02, 0x28, 0x04, 0xd1, 0x05, 0x48, 0x81, 0x7c, -0xcf, 0x22, 0x11, 0x40, 0x81, 0x74, 0x70, 0xbd, 0xa8, 0x0d, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, -0x18, 0x00, 0x01, 0x20, 0x00, 0x50, 0x03, 0x40, 0x70, 0x47, 0x00, 0x00, 0x10, 0xb5, 0x09, 0x48, -0x00, 0x7f, 0x12, 0x28, 0x0a, 0xd0, 0x00, 0x21, 0xaa, 0x20, 0x07, 0xf0, 0xeb, 0xfa, 0xbc, 0x21, -0x05, 0x48, 0xff, 0xf7, 0x34, 0xfb, 0x00, 0xf0, 0x09, 0xf8, 0x10, 0xbd, 0xfd, 0xf7, 0x0a, 0xfd, -0x10, 0xbd, 0x00, 0x00, 0x28, 0x0d, 0x01, 0x20, 0x85, 0xd2, 0x03, 0x40, 0x70, 0x47, 0x00, 0x00, -0x10, 0xb5, 0x09, 0x48, 0x00, 0x7f, 0x12, 0x28, 0x0a, 0xd0, 0x00, 0x21, 0xaa, 0x20, 0x07, 0xf0, -0xd1, 0xfa, 0xbc, 0x21, 0x05, 0x48, 0xff, 0xf7, 0x1a, 0xfb, 0x00, 0xf0, 0x09, 0xf8, 0x10, 0xbd, -0xfd, 0xf7, 0x60, 0xfd, 0x10, 0xbd, 0x00, 0x00, 0x28, 0x0d, 0x01, 0x20, 0x85, 0xd2, 0x03, 0x40, -0x70, 0x47, 0x00, 0x00, 0xf8, 0xb5, 0x4f, 0xa0, 0x0a, 0xf0, 0xf2, 0xf9, 0xff, 0xf7, 0x52, 0xfd, -0x4f, 0x4e, 0x00, 0x27, 0xb7, 0x70, 0x77, 0x71, 0x77, 0x70, 0x4e, 0x4c, 0x01, 0x25, 0xa5, 0x75, -0x4d, 0x48, 0x87, 0x71, 0x87, 0x76, 0x06, 0xf0, 0x9d, 0xfd, 0xfe, 0xf7, 0xd3, 0xf9, 0x09, 0xf0, -0xe3, 0xfe, 0x06, 0xf0, 0x87, 0xfe, 0x60, 0x7b, 0x00, 0x28, 0x02, 0xd1, 0x01, 0x20, 0x09, 0xf0, -0x9f, 0xfd, 0xff, 0xf7, 0x73, 0xff, 0x09, 0xf0, 0xd7, 0xf9, 0x01, 0x20, 0xe0, 0x77, 0x09, 0xf0, -0xd3, 0xfe, 0x06, 0xf0, 0x69, 0xfe, 0xff, 0xf7, 0x39, 0xfd, 0x30, 0x78, 0x01, 0x28, 0x6a, 0xd1, -0x3e, 0x4d, 0x09, 0xf0, 0x15, 0xff, 0x01, 0xf0, 0x7b, 0xf8, 0x01, 0x28, 0x03, 0xd0, 0x01, 0xf0, -0x77, 0xf8, 0x00, 0x28, 0x02, 0xd1, 0x60, 0x7b, 0x00, 0x28, 0x17, 0xd0, 0xa0, 0x7d, 0x00, 0x28, -0x01, 0xd0, 0x06, 0xf0, 0x5f, 0xfe, 0x09, 0xf0, 0x31, 0xfe, 0x00, 0x28, 0x3e, 0xd0, 0x09, 0xf0, -0xb3, 0xfe, 0x06, 0xf0, 0x49, 0xfe, 0x28, 0x7d, 0x02, 0x28, 0x0d, 0xd0, 0x08, 0xf0, 0x9c, 0xfb, -0x03, 0xf0, 0x38, 0xf9, 0x68, 0x7e, 0xc1, 0x07, 0x0b, 0xd1, 0x08, 0xe0, 0xa0, 0x7d, 0x00, 0x28, -0x3a, 0xd1, 0x06, 0xf0, 0x1f, 0xff, 0x37, 0xe0, 0x08, 0xf0, 0x20, 0xfb, 0xf0, 0xe7, 0x80, 0x07, -0x05, 0xd5, 0x08, 0xf0, 0x8a, 0xfb, 0x00, 0xf0, 0xb1, 0xfb, 0x05, 0xf0, 0x85, 0xfa, 0x60, 0x7c, -0x00, 0x28, 0x03, 0xd1, 0x00, 0x21, 0x01, 0x20, 0x09, 0xf0, 0xba, 0xfe, 0x60, 0x7c, 0x00, 0x28, -0x01, 0xd1, 0x09, 0xf0, 0x39, 0xfd, 0x28, 0x7d, 0x01, 0x28, 0x01, 0xd0, 0x02, 0x28, 0x0d, 0xd1, -0x68, 0x7e, 0x01, 0x07, 0x03, 0xd5, 0xf7, 0x21, 0x08, 0x40, 0x68, 0x76, 0x06, 0xe0, 0x18, 0x4b, -0x99, 0x7c, 0x22, 0x7a, 0x10, 0x20, 0x90, 0x40, 0x81, 0x43, 0x99, 0x74, 0x60, 0x7c, 0x00, 0x28, -0x0a, 0xd0, 0x06, 0xf0, 0xef, 0xfe, 0x13, 0x49, 0x01, 0x20, 0x48, 0x75, 0x64, 0x20, 0x0a, 0xf0, -0x7b, 0xf8, 0x06, 0xf0, 0x0f, 0xfe, 0x67, 0x74, 0x05, 0xf0, 0xf2, 0xf8, 0x06, 0xf0, 0xfa, 0xfd, -0x30, 0x78, 0x01, 0x28, 0x95, 0xd0, 0x01, 0x20, 0x70, 0x70, 0xb7, 0x70, 0x06, 0xf0, 0xda, 0xfe, -0xf8, 0xbd, 0x00, 0x00, 0x0a, 0x0a, 0x46, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x0a, 0x00, 0x00, -0x4c, 0x03, 0x01, 0x20, 0x6c, 0x03, 0x01, 0x20, 0x8c, 0x03, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, -0x00, 0x50, 0x03, 0x40, 0xe0, 0x51, 0x03, 0x40, 0xf0, 0xb4, 0x09, 0x24, 0x00, 0x22, 0x08, 0x4d, -0x24, 0x02, 0x13, 0x27, 0xff, 0x01, 0x93, 0x00, 0x5b, 0x19, 0x1e, 0x19, 0xdb, 0x19, 0x52, 0x1c, -0x30, 0x64, 0xd2, 0xb2, 0x19, 0x60, 0x10, 0x2a, 0xf5, 0xd3, 0xf0, 0xbc, 0x70, 0x47, 0x00, 0x00, -0x00, 0x40, 0x02, 0x20, 0xf0, 0xb4, 0x1b, 0x4a, 0x00, 0x21, 0x13, 0x7e, 0x08, 0x46, 0x00, 0x2b, -0x2d, 0xd9, 0x11, 0x25, 0x18, 0x4f, 0xad, 0x01, 0x0c, 0x23, 0x43, 0x43, 0xdb, 0x19, 0x5c, 0x19, -0xa4, 0x7e, 0x3e, 0x19, 0x09, 0x24, 0x24, 0x02, 0x34, 0x19, 0xa4, 0x7d, 0x01, 0x2c, 0x03, 0xd0, -0x02, 0x2c, 0x01, 0xd0, 0x03, 0x2c, 0x15, 0xd1, 0x81, 0x42, 0x11, 0xd0, 0x0c, 0x24, 0x4c, 0x43, -0x0e, 0x4e, 0xe4, 0x19, 0xa4, 0x19, 0x9b, 0x19, 0x1e, 0x88, 0x26, 0x80, 0x5e, 0x88, 0x66, 0x80, -0x9e, 0x88, 0xa6, 0x80, 0xde, 0x88, 0xe6, 0x80, 0x1e, 0x89, 0x26, 0x81, 0x5e, 0x89, 0x66, 0x81, -0x49, 0x1c, 0xc9, 0xb2, 0x40, 0x1c, 0x13, 0x7e, 0xc0, 0xb2, 0x83, 0x42, 0xd4, 0xd8, 0x11, 0x76, -0xf0, 0xbc, 0x70, 0x47, 0x84, 0x28, 0x01, 0x20, 0x44, 0x24, 0x01, 0x20, 0x5a, 0x04, 0x00, 0x00, -0x10, 0xb5, 0xfc, 0xf7, 0x29, 0xfd, 0x08, 0xf0, 0xd7, 0xff, 0xfc, 0xf7, 0x13, 0xfc, 0x10, 0xbd, -0x10, 0xb5, 0x08, 0xf0, 0x55, 0xfb, 0x10, 0xbd, 0xf0, 0xb5, 0x4a, 0x48, 0x87, 0xb0, 0x40, 0x7e, -0x40, 0x07, 0x6e, 0xd4, 0x48, 0x48, 0x00, 0x90, 0x48, 0x4e, 0x42, 0x78, 0x70, 0x7b, 0x05, 0x90, -0x40, 0x06, 0x00, 0x21, 0x40, 0x0e, 0x8c, 0x46, 0x04, 0x90, 0x00, 0x2a, 0x55, 0xd0, 0x44, 0x48, -0x41, 0x4c, 0xc2, 0x8b, 0x03, 0x92, 0xa3, 0x78, 0x02, 0x93, 0x23, 0x79, 0x01, 0x93, 0x63, 0x79, -0xe4, 0x78, 0x00, 0x20, 0xd7, 0xb2, 0xa6, 0x46, 0x00, 0x2a, 0x16, 0xd9, 0x3d, 0x4a, 0x44, 0x00, -0xa4, 0x18, 0xe0, 0x34, 0x22, 0x78, 0x65, 0x78, 0x02, 0x9c, 0x94, 0x42, 0x08, 0xd8, 0x96, 0x45, -0x06, 0xd3, 0x01, 0x9a, 0xaa, 0x42, 0x03, 0xd8, 0xab, 0x42, 0x01, 0xd3, 0x7f, 0x1e, 0xff, 0xb2, -0x40, 0x1c, 0x03, 0x9a, 0xc0, 0xb2, 0x82, 0x42, 0xe8, 0xd8, 0x01, 0x2f, 0x1e, 0xd8, 0x02, 0x9a, -0x96, 0x45, 0x14, 0xd3, 0x01, 0x98, 0x83, 0x42, 0x0d, 0xd3, 0x28, 0x25, 0x14, 0x46, 0x6c, 0x43, -0x2d, 0x4d, 0x64, 0x19, 0x45, 0x00, 0x65, 0x5f, 0x00, 0x2d, 0x00, 0xdd, 0x69, 0x18, 0x40, 0x1c, -0xc0, 0xb2, 0x83, 0x42, 0xf6, 0xd2, 0x52, 0x1c, 0xd2, 0xb2, 0x96, 0x45, 0xea, 0xd2, 0x01, 0x2f, -0x16, 0xd0, 0x00, 0x98, 0x89, 0x08, 0xc0, 0x79, 0x81, 0x42, 0x01, 0xd9, 0x01, 0x20, 0x84, 0x46, -0xb0, 0x7b, 0x22, 0x4a, 0x03, 0x06, 0x90, 0x7a, 0x00, 0x24, 0x41, 0x1c, 0x00, 0x2b, 0xc9, 0xb2, -0x63, 0x46, 0x15, 0xda, 0x00, 0x2b, 0x20, 0xd1, 0x0c, 0xe0, 0x70, 0x73, 0x07, 0xb0, 0xf0, 0xbd, -0x1b, 0x48, 0x42, 0x7a, 0x03, 0x7a, 0x10, 0x02, 0x18, 0x43, 0x40, 0x00, 0x81, 0x42, 0xe5, 0xd8, -0xe6, 0xe7, 0x1a, 0xe0, 0x00, 0x9b, 0x5b, 0x7a, 0x83, 0x42, 0x0c, 0xd2, 0x04, 0x98, 0x08, 0xe0, -0x00, 0x2b, 0x0a, 0xd0, 0x00, 0x9b, 0x1b, 0x7a, 0x83, 0x42, 0x04, 0xd2, 0x05, 0x98, 0x80, 0x21, -0x08, 0x43, 0x70, 0x73, 0x02, 0xe0, 0x91, 0x72, 0x00, 0xe0, 0x94, 0x72, 0x70, 0x7b, 0x00, 0x06, -0xdc, 0xd5, 0x01, 0x20, 0xb0, 0x77, 0x07, 0xb0, 0xf0, 0xbd, 0x05, 0xf0, 0x37, 0xfc, 0x07, 0xb0, -0xf0, 0xbd, 0x00, 0x00, 0xa8, 0x0c, 0x01, 0x20, 0x88, 0x0d, 0x01, 0x20, 0x84, 0x2d, 0x01, 0x20, -0x04, 0x25, 0x01, 0x20, 0x44, 0x24, 0x01, 0x20, 0x00, 0x50, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, -0x28, 0x0d, 0x01, 0x20, 0x36, 0x48, 0xc1, 0x7a, 0x01, 0x29, 0x67, 0xd1, 0xf0, 0xb5, 0x36, 0x49, -0x34, 0x4a, 0x4b, 0x7a, 0x0c, 0x7a, 0x19, 0x02, 0x55, 0x8c, 0x21, 0x43, 0x00, 0x24, 0x33, 0x4b, -0x8d, 0x42, 0x08, 0xd8, 0x24, 0x25, 0x55, 0x5f, 0x49, 0x42, 0x8d, 0x42, 0x03, 0xdb, 0x30, 0x49, -0x09, 0x7c, 0x00, 0x29, 0x01, 0xd0, 0x1c, 0x70, 0x08, 0xe0, 0x01, 0x21, 0x19, 0x70, 0x41, 0x7f, -0x02, 0x7f, 0x09, 0x02, 0x11, 0x43, 0x59, 0x80, 0x40, 0x7c, 0x98, 0x80, 0x04, 0x20, 0x00, 0xf0, -0x47, 0xfe, 0x19, 0x78, 0x27, 0x4a, 0x00, 0x29, 0x03, 0xd0, 0x27, 0x49, 0x49, 0x78, 0x00, 0x29, -0x01, 0xd0, 0xd4, 0x83, 0xf0, 0xbd, 0xd1, 0x8b, 0x49, 0x1c, 0x89, 0xb2, 0xd1, 0x83, 0x5d, 0x88, -0x8d, 0x42, 0xf7, 0xd8, 0x86, 0x46, 0xd4, 0x83, 0x20, 0x48, 0x04, 0x24, 0xc1, 0x79, 0x1c, 0x5f, -0x01, 0x26, 0x01, 0x29, 0xee, 0xd3, 0x61, 0x42, 0x8c, 0x46, 0x1c, 0x48, 0x01, 0x23, 0x00, 0x7a, -0x01, 0x28, 0x1c, 0xd3, 0x1a, 0x49, 0x30, 0x46, 0x28, 0x22, 0x50, 0x43, 0x47, 0x18, 0x71, 0x46, -0x42, 0x18, 0x59, 0x00, 0x7d, 0x5e, 0xa5, 0x42, 0x03, 0xdd, 0x55, 0x5a, 0x2d, 0x19, 0x55, 0x52, -0x07, 0xe0, 0x65, 0x45, 0x02, 0xda, 0x55, 0x5a, 0x2d, 0x1b, 0x01, 0xe0, 0x50, 0x5a, 0x45, 0x19, -0x55, 0x52, 0x0e, 0x48, 0x5b, 0x1c, 0x00, 0x7a, 0xdb, 0xb2, 0x98, 0x42, 0xe9, 0xd2, 0x0b, 0x48, -0x76, 0x1c, 0xc0, 0x79, 0xf6, 0xb2, 0xb0, 0x42, 0xd7, 0xd2, 0xf0, 0xbd, 0x70, 0x47, 0x00, 0x00, -0x68, 0x0d, 0x01, 0x20, 0x84, 0x2d, 0x01, 0x20, 0x28, 0x0d, 0x01, 0x20, 0x14, 0x01, 0x01, 0x20, -0xa4, 0x2d, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, 0x88, 0x0d, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, -0x00, 0x50, 0x01, 0x20, 0x70, 0x47, 0x00, 0xb5, 0x04, 0xf0, 0xe6, 0xfd, 0x00, 0xbd, 0x00, 0x00, -0xf0, 0xb5, 0x00, 0x24, 0x47, 0x4f, 0x09, 0x26, 0x47, 0x4d, 0x83, 0xb0, 0x36, 0x02, 0x28, 0x19, -0x80, 0x19, 0x81, 0x7d, 0x01, 0x29, 0x0e, 0xd1, 0x00, 0x78, 0x6e, 0x21, 0x48, 0x43, 0x41, 0x19, -0x20, 0x46, 0x0a, 0x22, 0x50, 0x43, 0x09, 0x18, 0x42, 0x19, 0x40, 0x48, 0xc9, 0x19, 0x10, 0x18, -0x0a, 0x22, 0xfb, 0xf7, 0xc1, 0xfb, 0x64, 0x1c, 0xe4, 0xb2, 0x0b, 0x2c, 0xe7, 0xd3, 0x3c, 0x4f, -0x3c, 0x48, 0x00, 0x24, 0x00, 0x90, 0x38, 0x49, 0x09, 0x20, 0x0d, 0x19, 0x00, 0x02, 0x28, 0x18, -0x80, 0x7d, 0x02, 0x28, 0x06, 0xd0, 0x03, 0x28, 0x04, 0xd0, 0x01, 0x28, 0x57, 0xd0, 0x04, 0x28, -0x55, 0xd0, 0x59, 0xe0, 0x00, 0x98, 0x6e, 0x23, 0xc0, 0x7f, 0x2f, 0x49, 0x58, 0x43, 0x41, 0x18, -0x20, 0x46, 0x0a, 0x23, 0x58, 0x43, 0x00, 0x9a, 0x0b, 0x18, 0x19, 0x21, 0x92, 0x7f, 0x89, 0x01, -0x5e, 0x18, 0x01, 0x90, 0x33, 0x88, 0x71, 0x88, 0x9c, 0x46, 0x6e, 0x23, 0x5a, 0x43, 0x26, 0x4b, -0xd2, 0x18, 0x12, 0x18, 0x19, 0x20, 0x80, 0x01, 0x12, 0x18, 0x10, 0x88, 0x52, 0x88, 0x63, 0x46, -0x18, 0x1a, 0x89, 0x1a, 0x00, 0xb2, 0x09, 0xb2, 0xfc, 0xf7, 0xfe, 0xff, 0x79, 0x79, 0x3a, 0x79, -0x09, 0x02, 0x00, 0xb2, 0x11, 0x43, 0x81, 0x42, 0x05, 0xda, 0x49, 0x21, 0x02, 0x20, 0x49, 0x01, -0x69, 0x18, 0xc8, 0x75, 0x28, 0xe0, 0x49, 0x20, 0x40, 0x01, 0x2d, 0x18, 0xe8, 0x7d, 0x16, 0x49, -0x02, 0x28, 0x02, 0xd0, 0x00, 0x28, 0x03, 0xd0, 0x1e, 0xe0, 0x01, 0x20, 0xe8, 0x75, 0x1b, 0xe0, -0x01, 0x9b, 0x30, 0x88, 0x5b, 0x18, 0x15, 0x21, 0x89, 0x01, 0x59, 0x18, 0x8b, 0x8c, 0x72, 0x88, -0xc9, 0x8c, 0xc0, 0x1a, 0x51, 0x1a, 0x00, 0xb2, 0x09, 0xb2, 0xfc, 0xf7, 0xd5, 0xff, 0x79, 0x79, -0x3a, 0x79, 0x09, 0x02, 0x00, 0xb2, 0x11, 0x43, 0x81, 0x42, 0xe6, 0xdb, 0x04, 0xe0, 0x49, 0x21, -0x00, 0x20, 0x49, 0x01, 0x69, 0x18, 0xc8, 0x75, 0x64, 0x1c, 0xe4, 0xb2, 0x0b, 0x2c, 0x92, 0xd3, -0x03, 0xb0, 0xf0, 0xbd, 0x3e, 0x06, 0x00, 0x00, 0x44, 0x24, 0x01, 0x20, 0x62, 0x05, 0x00, 0x00, -0x69, 0x0d, 0x01, 0x20, 0x24, 0x2d, 0x01, 0x20, 0x10, 0xb5, 0x00, 0xf0, 0xa9, 0xfa, 0x10, 0xbd, -0x10, 0xb5, 0xff, 0xf7, 0x1f, 0xf9, 0x10, 0xbd, 0xf0, 0xb5, 0x3d, 0x48, 0x85, 0xb0, 0x44, 0x7c, -0x02, 0x2c, 0x5e, 0xd3, 0x05, 0x2c, 0x00, 0xd9, 0x05, 0x24, 0x00, 0x20, 0x00, 0x90, 0x39, 0x48, -0x02, 0x90, 0x00, 0x7e, 0x00, 0x28, 0x54, 0xd9, 0x00, 0x99, 0x0c, 0x20, 0x41, 0x43, 0x36, 0x48, -0x0a, 0x18, 0x11, 0x21, 0x89, 0x01, 0x56, 0x18, 0xb5, 0x7e, 0x09, 0x21, 0x40, 0x19, 0x09, 0x02, -0x41, 0x18, 0x89, 0x7d, 0x01, 0x29, 0x46, 0xd0, 0x04, 0x29, 0x39, 0xd0, 0x25, 0x21, 0x89, 0x01, -0x40, 0x18, 0x80, 0x78, 0x01, 0x28, 0x33, 0xd0, 0x14, 0x20, 0x2a, 0x46, 0x42, 0x43, 0x2b, 0x48, -0xb1, 0x8b, 0x13, 0x18, 0x2a, 0x48, 0x00, 0x22, 0x40, 0x5d, 0x01, 0x90, 0x80, 0x00, 0x19, 0x52, -0x18, 0x18, 0xf1, 0x8b, 0x41, 0x80, 0x17, 0x46, 0x10, 0x46, 0x00, 0x2c, 0x0b, 0xd9, 0x81, 0x00, -0x8c, 0x46, 0x59, 0x5a, 0x40, 0x1c, 0x8a, 0x18, 0x61, 0x46, 0x59, 0x18, 0x49, 0x88, 0xc0, 0xb2, -0xcf, 0x19, 0xa0, 0x42, 0xf3, 0xd3, 0x21, 0x46, 0x10, 0x46, 0xfb, 0xf7, 0x57, 0xfb, 0x03, 0x90, -0x21, 0x46, 0x38, 0x46, 0xfb, 0xf7, 0x52, 0xfb, 0x03, 0x99, 0xb1, 0x83, 0xf0, 0x83, 0x01, 0x98, -0x17, 0x49, 0x40, 0x1c, 0xc0, 0xb2, 0x48, 0x55, 0xa0, 0x42, 0x01, 0xd3, 0x00, 0x20, 0x48, 0x55, -0x00, 0x98, 0x40, 0x1c, 0xc0, 0xb2, 0x00, 0x90, 0x02, 0x98, 0x01, 0x7e, 0x00, 0x98, 0x81, 0x42, -0xaa, 0xd8, 0x05, 0xb0, 0xf0, 0xbd, 0x00, 0x20, 0x0d, 0x49, 0x00, 0x2c, 0x48, 0x55, 0xef, 0xd9, -0xb3, 0x8b, 0x14, 0x22, 0xf6, 0x8b, 0xdc, 0x39, 0x55, 0x43, 0x6a, 0x18, 0x81, 0x00, 0x53, 0x52, -0x51, 0x18, 0x40, 0x1c, 0xc0, 0xb2, 0x4e, 0x80, 0xa0, 0x42, 0xf7, 0xd3, 0xe0, 0xe7, 0x00, 0x00, -0x88, 0x0d, 0x01, 0x20, 0x84, 0x28, 0x01, 0x20, 0x44, 0x24, 0x01, 0x20, 0x40, 0x18, 0x01, 0x20, -0x1c, 0x19, 0x01, 0x20, 0x4c, 0x48, 0x40, 0x7f, 0x00, 0x28, 0x6e, 0xd0, 0x4b, 0x48, 0x00, 0x7e, -0x01, 0x28, 0x6a, 0xd1, 0xf0, 0xb5, 0x4a, 0x48, 0x4a, 0x4b, 0x85, 0x7f, 0xc6, 0x7f, 0x88, 0xb0, -0x98, 0x8a, 0x07, 0x90, 0x18, 0x8b, 0x06, 0x90, 0xd8, 0x8a, 0x05, 0x90, 0x58, 0x8b, 0x04, 0x90, -0x1c, 0x89, 0x00, 0x21, 0x80, 0x3c, 0x20, 0xb2, 0x03, 0x90, 0x43, 0x48, 0x42, 0x7e, 0x07, 0x7e, -0x10, 0x02, 0x38, 0x43, 0x42, 0x08, 0x58, 0x89, 0x40, 0x4b, 0x80, 0x1a, 0x84, 0x46, 0x00, 0xb2, -0x02, 0x90, 0x6e, 0x20, 0x45, 0x43, 0x3e, 0x48, 0x28, 0x18, 0x01, 0x90, 0x6e, 0x20, 0x46, 0x43, -0x3b, 0x48, 0x30, 0x18, 0x00, 0x90, 0x0a, 0x25, 0x0f, 0x46, 0x6f, 0x43, 0xc5, 0x19, 0x31, 0x20, -0x40, 0x01, 0x28, 0x18, 0x80, 0x7f, 0x02, 0x28, 0x54, 0xd1, 0x35, 0x48, 0x09, 0x26, 0x40, 0x18, -0x36, 0x02, 0x86, 0x19, 0xb6, 0x7d, 0x02, 0x2e, 0x01, 0xd0, 0x03, 0x2e, 0x4a, 0xd1, 0x49, 0x26, -0x76, 0x01, 0x80, 0x19, 0xc0, 0x7d, 0x01, 0x28, 0x01, 0xd0, 0x02, 0x28, 0x42, 0xd1, 0x19, 0x20, -0x80, 0x01, 0x28, 0x18, 0x05, 0x88, 0x07, 0x9e, 0xb5, 0x42, 0x09, 0xd3, 0x06, 0x9e, 0xb5, 0x42, -0x06, 0xd8, 0x45, 0x88, 0x05, 0x9e, 0xb5, 0x42, 0x02, 0xd3, 0x04, 0x9e, 0xb5, 0x42, 0x31, 0xd9, -0x05, 0x88, 0x46, 0x88, 0x01, 0x98, 0xb6, 0x46, 0xc6, 0x19, 0x19, 0x20, 0x80, 0x01, 0x30, 0x18, -0x06, 0x88, 0x6d, 0x00, 0xad, 0x1b, 0x40, 0x88, 0x76, 0x46, 0x76, 0x00, 0x30, 0x1a, 0x2d, 0xb2, -0x00, 0xb2, 0x80, 0x2d, 0x02, 0xda, 0x80, 0x25, 0x03, 0xe0, 0x23, 0xe0, 0xac, 0x42, 0x00, 0xda, -0x03, 0x9d, 0x82, 0x42, 0x01, 0xdd, 0x10, 0x46, 0x02, 0xe0, 0x84, 0x45, 0x00, 0xda, 0x02, 0x98, -0x9e, 0x7a, 0x0c, 0x27, 0x7e, 0x43, 0x12, 0x4f, 0xf7, 0x19, 0x11, 0x26, 0xb6, 0x01, 0xbe, 0x19, -0xb5, 0x83, 0x9d, 0x7a, 0x0c, 0x26, 0x75, 0x43, 0x0d, 0x4e, 0xae, 0x19, 0x11, 0x25, 0xad, 0x01, -0x75, 0x19, 0xe8, 0x83, 0x49, 0x1c, 0xc9, 0xb2, 0x0b, 0x29, 0x01, 0xd2, 0x00, 0x98, 0x9a, 0xe7, -0x08, 0xb0, 0xf0, 0xbd, 0x70, 0x47, 0x00, 0x00, 0x48, 0x0d, 0x01, 0x20, 0x84, 0x28, 0x01, 0x20, -0x24, 0x2d, 0x01, 0x20, 0x84, 0x2e, 0x01, 0x20, 0xa9, 0x0d, 0x01, 0x20, 0xa4, 0x2d, 0x01, 0x20, -0x44, 0x24, 0x01, 0x20, 0x10, 0xb5, 0x00, 0xf0, 0x8d, 0xff, 0x10, 0xbd, 0x10, 0xb5, 0xff, 0xf7, -0xef, 0xfc, 0xff, 0xf7, 0x1f, 0xfe, 0xff, 0xf7, 0x1e, 0xfe, 0xff, 0xf7, 0x21, 0xfe, 0xff, 0xf7, -0xbb, 0xfe, 0xff, 0xf7, 0xbd, 0xfe, 0xff, 0xf7, 0xbf, 0xfe, 0xff, 0xf7, 0x43, 0xff, 0xff, 0xf7, -0xe9, 0xff, 0xff, 0xf7, 0xe5, 0xfc, 0xff, 0xf7, 0xe7, 0xfc, 0xff, 0xf7, 0x8b, 0xfd, 0x10, 0xbd, -0xf0, 0xb5, 0x84, 0x48, 0x89, 0xb0, 0x40, 0x7e, 0x03, 0x90, 0x83, 0x48, 0x01, 0x21, 0x41, 0x71, -0x82, 0x48, 0x02, 0x90, 0x41, 0x75, 0x02, 0xf0, 0xc1, 0xf8, 0xfc, 0xf7, 0x9d, 0xfc, 0x81, 0x48, -0x1d, 0x24, 0x7f, 0x4d, 0x10, 0x26, 0x01, 0x90, 0x09, 0xf0, 0x30, 0xfa, 0xa9, 0x7c, 0x01, 0x98, -0x02, 0x7a, 0x30, 0x46, 0x90, 0x40, 0x81, 0x43, 0xa9, 0x74, 0x20, 0x46, 0x64, 0x1e, 0xe4, 0xb2, -0x00, 0x28, 0xf1, 0xd1, 0x20, 0x20, 0x00, 0xf0, 0xd3, 0xfb, 0x01, 0x46, 0x90, 0x22, 0x76, 0x48, -0xfb, 0xf7, 0xc2, 0xf9, 0x75, 0x4f, 0x76, 0x4c, 0x78, 0x7a, 0x00, 0x28, 0x07, 0xd0, 0x01, 0x20, -0x00, 0xf0, 0xc6, 0xfb, 0x09, 0x21, 0xc9, 0x01, 0x40, 0x18, 0x00, 0x88, 0x20, 0x81, 0x08, 0xf0, -0xa3, 0xfe, 0x7b, 0x7a, 0x6f, 0x48, 0x00, 0x90, 0x00, 0x2b, 0x01, 0xd0, 0x20, 0x89, 0x60, 0x81, -0x03, 0x98, 0x40, 0x10, 0x06, 0x90, 0x6c, 0x48, 0x05, 0x90, 0x6c, 0x48, 0x04, 0x90, 0x00, 0xf0, -0x1f, 0xfc, 0x01, 0x28, 0x7e, 0xd0, 0x00, 0xf0, 0x03, 0xfc, 0x00, 0x28, 0x7a, 0xd0, 0x09, 0xf0, -0xf5, 0xf9, 0x09, 0xf0, 0xc5, 0xfa, 0x5e, 0x49, 0x88, 0x7c, 0x01, 0x9a, 0x13, 0x7a, 0x10, 0x22, -0x9a, 0x40, 0x90, 0x43, 0x88, 0x74, 0x20, 0x20, 0x00, 0xf0, 0x9a, 0xfb, 0x01, 0x46, 0x90, 0x22, -0x59, 0x48, 0xfb, 0xf7, 0x89, 0xf9, 0x59, 0x4c, 0x60, 0x7a, 0x00, 0x28, 0x08, 0xd0, 0x01, 0x20, -0x00, 0xf0, 0x8e, 0xfb, 0x09, 0x21, 0xc9, 0x01, 0x40, 0x18, 0x01, 0x88, 0x54, 0x48, 0x01, 0x81, -0x52, 0x48, 0x00, 0x22, 0x03, 0x7a, 0x15, 0x46, 0x00, 0x20, 0x00, 0x2b, 0x19, 0xd9, 0x4e, 0x4c, -0x29, 0x46, 0x24, 0x26, 0x71, 0x43, 0x0c, 0x19, 0x07, 0x94, 0x51, 0x4c, 0x0c, 0x19, 0xa4, 0x46, -0x50, 0x4c, 0x0f, 0x19, 0x44, 0x00, 0x07, 0x99, 0x66, 0x46, 0x09, 0x5b, 0x36, 0x5b, 0x89, 0x1b, -0x09, 0xb2, 0x39, 0x53, 0x91, 0x42, 0x00, 0xdd, 0x0a, 0x46, 0x40, 0x1c, 0xc0, 0xb2, 0x83, 0x42, -0xf0, 0xd8, 0x6d, 0x1c, 0xed, 0xb2, 0x04, 0x2d, 0xde, 0xd3, 0x40, 0x48, 0x40, 0x7a, 0x00, 0x28, -0x08, 0xd0, 0x3f, 0x49, 0x08, 0x89, 0x4c, 0x89, 0x00, 0x1b, 0x00, 0xb2, 0x88, 0x81, 0x82, 0x42, -0x00, 0xda, 0x02, 0x46, 0x03, 0x98, 0x82, 0x42, 0x04, 0xdd, 0x39, 0x48, 0xc1, 0x78, 0x49, 0x1c, -0xc1, 0x70, 0x35, 0xe0, 0x36, 0x48, 0x00, 0x21, 0xc1, 0x70, 0x06, 0x98, 0x90, 0x42, 0x39, 0xdd, -0x05, 0x98, 0x44, 0x7c, 0x00, 0x98, 0x00, 0x7d, 0x00, 0x28, 0x33, 0xd0, 0x00, 0x26, 0x60, 0x42, -0x07, 0x90, 0x00, 0x22, 0x00, 0x2b, 0x1f, 0xd9, 0x32, 0x4d, 0x30, 0x46, 0x24, 0x27, 0x78, 0x43, -0x2f, 0x49, 0x45, 0x19, 0xac, 0x46, 0x41, 0x18, 0x65, 0x46, 0x50, 0x00, 0x2d, 0x5e, 0xa5, 0x42, -0x05, 0xdd, 0x00, 0xe0, 0x3a, 0xe0, 0x0d, 0x5a, 0x2d, 0x19, 0x0d, 0x52, 0x08, 0xe0, 0x07, 0x9f, -0xbd, 0x42, 0x02, 0xda, 0x0d, 0x5a, 0x2d, 0x1b, 0x01, 0xe0, 0x0f, 0x5a, 0x7d, 0x19, 0x0d, 0x52, -0x52, 0x1c, 0xd2, 0xb2, 0x93, 0x42, 0xe7, 0xd8, 0x76, 0x1c, 0xf6, 0xb2, 0x04, 0x2e, 0xd8, 0xd9, -0x1b, 0x48, 0xc0, 0x78, 0x00, 0x28, 0x05, 0xd0, 0x02, 0x99, 0x00, 0x20, 0x48, 0x75, 0x18, 0x49, -0xc8, 0x70, 0x1b, 0xe0, 0x02, 0x98, 0x40, 0x7d, 0x00, 0x28, 0x12, 0xd0, 0x14, 0x49, 0xc8, 0x88, -0x40, 0x1c, 0x80, 0xb2, 0xc8, 0x80, 0x04, 0x99, 0x4a, 0x7f, 0x0b, 0x7f, 0x11, 0x02, 0x19, 0x43, -0x81, 0x42, 0x06, 0xd1, 0x14, 0xa0, 0x09, 0xf0, 0xcb, 0xfc, 0x0d, 0x49, 0x00, 0x20, 0xc8, 0x80, -0x04, 0xe0, 0x00, 0x98, 0x00, 0x7e, 0xc0, 0x07, 0x00, 0xd0, 0x40, 0xe7, 0x05, 0xf0, 0xbc, 0xfc, -0x09, 0xb0, 0xf0, 0xbd, 0x28, 0x0d, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, 0x8c, 0x03, 0x01, 0x20, -0x00, 0x50, 0x03, 0x40, 0x6c, 0x03, 0x01, 0x20, 0xe4, 0x11, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, -0xb0, 0x00, 0x01, 0x20, 0xe8, 0x0d, 0x01, 0x20, 0x68, 0x0d, 0x01, 0x20, 0xc8, 0x0c, 0x01, 0x20, -0x74, 0x12, 0x01, 0x20, 0x04, 0x13, 0x01, 0x20, 0x67, 0x65, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, -0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x20, 0x74, 0x72, 0x61, 0x63, 0x65, -0x0a, 0x00, 0x00, 0x00, 0xf0, 0xb4, 0x94, 0x46, 0x0d, 0x4e, 0x02, 0x46, 0x30, 0x79, 0x01, 0x23, -0xc0, 0x07, 0x00, 0x28, 0x0a, 0xd0, 0x0b, 0x48, 0x0b, 0x4c, 0xc5, 0x7d, 0xfe, 0x27, 0xe8, 0x09, -0x01, 0xd0, 0x23, 0x76, 0x27, 0x76, 0x30, 0x79, 0xc0, 0x07, 0xf8, 0xd1, 0x07, 0x48, 0x03, 0x70, -0x41, 0x60, 0x82, 0x60, 0x61, 0x46, 0xc1, 0x60, 0x03, 0x74, 0xf0, 0xbc, 0x70, 0x47, 0x00, 0x00, -0x20, 0x40, 0x03, 0x40, 0xe8, 0x0d, 0x01, 0x20, 0x00, 0x00, 0x03, 0x40, 0x00, 0x40, 0x03, 0x40, -0xf0, 0xb5, 0x57, 0x49, 0x00, 0x24, 0x4a, 0x78, 0x87, 0xb0, 0x20, 0x46, 0x00, 0x2a, 0x71, 0xd0, -0x54, 0x4a, 0x95, 0x7f, 0xd3, 0x7f, 0x54, 0x4a, 0x56, 0x78, 0x17, 0x78, 0x32, 0x02, 0x3a, 0x43, -0x02, 0x92, 0x42, 0x22, 0x53, 0x43, 0x51, 0x4a, 0x9a, 0x18, 0x05, 0x92, 0x42, 0x22, 0x55, 0x43, -0x4e, 0x4a, 0xaa, 0x18, 0x03, 0x92, 0x89, 0x78, 0x00, 0x91, 0x06, 0x22, 0x27, 0x46, 0x05, 0x99, -0x57, 0x43, 0xca, 0x19, 0x1f, 0x21, 0x89, 0x01, 0x51, 0x18, 0x04, 0x91, 0x49, 0x8f, 0x05, 0x22, -0x52, 0x02, 0x01, 0x91, 0x91, 0x42, 0x07, 0xd9, 0x44, 0x4a, 0x04, 0x21, 0x13, 0x19, 0x09, 0x22, -0x12, 0x02, 0x9a, 0x18, 0x91, 0x75, 0x5e, 0xe0, 0x40, 0x49, 0x0a, 0x19, 0x09, 0x21, 0x09, 0x02, -0x56, 0x18, 0xb1, 0x7d, 0x02, 0x29, 0x01, 0xd0, 0x03, 0x29, 0x54, 0xd1, 0x25, 0x21, 0x89, 0x01, -0x55, 0x18, 0xa9, 0x78, 0x00, 0x29, 0x02, 0xd0, 0x01, 0x29, 0x17, 0xd0, 0x4b, 0xe0, 0x02, 0x9a, -0x01, 0x99, 0x91, 0x42, 0x47, 0xd9, 0x00, 0x99, 0x00, 0x29, 0x02, 0xd0, 0x01, 0x98, 0xfb, 0xf7, -0xad, 0xf8, 0x03, 0x99, 0xca, 0x19, 0x1f, 0x21, 0x89, 0x01, 0x51, 0x18, 0x49, 0x8f, 0x42, 0x08, -0x91, 0x42, 0x36, 0xd3, 0x81, 0x42, 0x31, 0xd2, 0x01, 0x21, 0x30, 0xe0, 0x00, 0x99, 0x00, 0x29, -0x08, 0xd0, 0x03, 0x98, 0xc1, 0x19, 0x1f, 0x20, 0x80, 0x01, 0x08, 0x18, 0x40, 0x8f, 0x00, 0x99, -0xfb, 0xf7, 0x94, 0xf8, 0x1f, 0x21, 0x01, 0x9a, 0x89, 0x01, 0x82, 0x42, 0x21, 0xd3, 0x03, 0x9a, -0xd2, 0x19, 0x53, 0x18, 0x36, 0x21, 0x59, 0x5e, 0x38, 0x22, 0x9a, 0x5e, 0x00, 0x29, 0x02, 0xdb, -0x0b, 0x46, 0x01, 0xe0, 0x31, 0xe0, 0x4b, 0x42, 0x17, 0x1e, 0x00, 0xda, 0x57, 0x42, 0xbb, 0x42, -0x06, 0xdd, 0x04, 0x9a, 0x36, 0x23, 0xd3, 0x5e, 0x59, 0x43, 0x00, 0x29, 0x06, 0xdc, 0x08, 0xe0, -0x04, 0x99, 0x38, 0x23, 0xcb, 0x5e, 0x5a, 0x43, 0x00, 0x2a, 0x02, 0xdd, 0x02, 0x21, 0xa9, 0x70, -0x01, 0xe0, 0x04, 0x21, 0xb1, 0x75, 0x64, 0x1c, 0xe4, 0xb2, 0x0b, 0x2c, 0x85, 0xd3, 0x00, 0x20, -0x09, 0x23, 0x1b, 0x02, 0x0d, 0x4c, 0x25, 0x25, 0x06, 0x46, 0xad, 0x01, 0x21, 0x18, 0xca, 0x18, -0x92, 0x7d, 0x01, 0x2a, 0x01, 0xd0, 0x04, 0x2a, 0x01, 0xd1, 0x49, 0x19, 0x8e, 0x70, 0x40, 0x1c, -0xc0, 0xb2, 0x0b, 0x28, 0xf2, 0xd3, 0xff, 0xf7, 0x95, 0xfa, 0x07, 0xb0, 0xf0, 0xbd, 0x00, 0x00, -0x68, 0x0d, 0x01, 0x20, 0x24, 0x2d, 0x01, 0x20, 0x6b, 0x0d, 0x01, 0x20, 0x44, 0x24, 0x01, 0x20, -0xf8, 0xb5, 0x29, 0x48, 0x00, 0x90, 0x29, 0x48, 0xc1, 0x7b, 0x0f, 0x22, 0x11, 0x43, 0xc1, 0x73, -0xc1, 0x78, 0x91, 0x43, 0xc1, 0x70, 0x26, 0x4b, 0x00, 0x21, 0x1a, 0x79, 0x58, 0x79, 0x25, 0x4e, -0x10, 0x18, 0x9a, 0x79, 0x86, 0x46, 0x80, 0x24, 0x00, 0x98, 0xc8, 0x40, 0xc0, 0x07, 0x1b, 0xd0, -0x01, 0x20, 0x84, 0x46, 0x70, 0x46, 0xc7, 0xb2, 0x00, 0x20, 0x00, 0x2a, 0x2f, 0xd9, 0x03, 0x46, -0x7b, 0x43, 0x65, 0x46, 0x00, 0x2d, 0x05, 0xd0, 0x5b, 0x18, 0x9b, 0x00, 0xf5, 0x5c, 0x6d, 0x06, -0x6d, 0x0e, 0x03, 0xe0, 0x5b, 0x18, 0x9b, 0x00, 0xf5, 0x58, 0x25, 0x43, 0x40, 0x1c, 0xc0, 0xb2, -0xf5, 0x50, 0x82, 0x42, 0xeb, 0xd8, 0x1a, 0xe0, 0x00, 0x20, 0x84, 0x46, 0x70, 0x46, 0xc7, 0xb2, -0x00, 0x20, 0x00, 0x2a, 0x13, 0xd9, 0x03, 0x46, 0x7b, 0x43, 0x65, 0x46, 0x00, 0x2d, 0x05, 0xd0, -0x5b, 0x18, 0x9b, 0x00, 0xf5, 0x5c, 0x6d, 0x06, 0x6d, 0x0e, 0x03, 0xe0, 0x5b, 0x18, 0x9b, 0x00, -0xf5, 0x58, 0x25, 0x43, 0x40, 0x1c, 0xc0, 0xb2, 0xf5, 0x50, 0x82, 0x42, 0xeb, 0xd8, 0x49, 0x1c, -0xc9, 0xb2, 0x12, 0x29, 0xc0, 0xd3, 0xf8, 0xbd, 0xff, 0xff, 0x03, 0x00, 0xa0, 0x51, 0x03, 0x40, -0xa8, 0x0c, 0x01, 0x20, 0x00, 0x40, 0x02, 0x20, 0xf0, 0xb5, 0x00, 0x20, 0x41, 0x1e, 0x8c, 0x46, -0x87, 0xb0, 0xac, 0x49, 0x05, 0x91, 0x49, 0x7b, 0x00, 0x29, 0x7d, 0xd1, 0xaa, 0x4a, 0xab, 0x4c, -0x52, 0x78, 0x00, 0x2a, 0x11, 0xd9, 0x65, 0x7d, 0x23, 0x7d, 0xa9, 0x4f, 0x2e, 0x02, 0x1e, 0x43, -0x4b, 0x00, 0xdb, 0x19, 0x1d, 0x7f, 0xdb, 0x7e, 0x2d, 0x02, 0x1d, 0x43, 0xb5, 0x42, 0x00, 0xd1, -0x08, 0x46, 0x49, 0x1c, 0xc9, 0xb2, 0x8a, 0x42, 0xf2, 0xd8, 0x9f, 0x49, 0x83, 0x00, 0x5b, 0x18, -0x45, 0x00, 0x69, 0x18, 0x1b, 0x8c, 0xc9, 0x8a, 0x59, 0x1a, 0x00, 0xd5, 0x49, 0x42, 0x05, 0x9b, -0x89, 0xb2, 0x19, 0x76, 0x0d, 0x0a, 0x5d, 0x76, 0x9a, 0x4d, 0x9b, 0x4b, 0xef, 0x7d, 0x9b, 0x8a, -0x04, 0x93, 0x5b, 0x1e, 0x9b, 0xb2, 0x03, 0x93, 0x98, 0x4b, 0x99, 0x4e, 0xdb, 0x79, 0x00, 0x93, -0xf3, 0x7d, 0x01, 0x93, 0x2d, 0x7e, 0x02, 0x95, 0x8f, 0x42, 0x26, 0xd2, 0x92, 0x4b, 0x9b, 0x78, -0x03, 0x2b, 0x1e, 0xd9, 0x2f, 0x46, 0x93, 0x4d, 0x8f, 0x42, 0x2d, 0x7c, 0x04, 0xd2, 0x8f, 0x4b, -0xdd, 0x71, 0x0a, 0x23, 0x8c, 0x4d, 0x1f, 0xe0, 0x8f, 0x4f, 0x00, 0x9b, 0xff, 0x7f, 0xab, 0x42, -0x09, 0xd1, 0x04, 0x9d, 0x88, 0x4b, 0x00, 0x2d, 0x02, 0xd0, 0x03, 0x9d, 0x9d, 0x82, 0x1b, 0xe0, -0x86, 0x4d, 0xef, 0x71, 0x18, 0xe0, 0x85, 0x4d, 0x0a, 0x23, 0xef, 0x71, 0x4e, 0x3d, 0xab, 0x82, -0x12, 0xe0, 0x81, 0x4d, 0x5b, 0x1c, 0xab, 0x70, 0x0e, 0xe0, 0x7f, 0x4d, 0x00, 0x27, 0xaf, 0x70, -0x04, 0x9b, 0x00, 0x2b, 0x02, 0xd0, 0x03, 0x9b, 0xab, 0x82, 0x05, 0xe0, 0x01, 0x9d, 0x00, 0x9b, -0x7a, 0x4f, 0xab, 0x42, 0x00, 0xd0, 0xfd, 0x71, 0x7c, 0x4d, 0x2f, 0x78, 0x3b, 0x46, 0x6f, 0x78, -0x3f, 0x02, 0x3b, 0x43, 0xaf, 0x78, 0xed, 0x78, 0x3f, 0x04, 0x3b, 0x43, 0x2d, 0x06, 0x2b, 0x43, -0x77, 0x4d, 0x8b, 0x42, 0x7c, 0xd9, 0x00, 0xe0, 0x6e, 0xe0, 0x6b, 0x4b, 0xda, 0x78, 0x94, 0x46, -0x92, 0x00, 0xd2, 0x18, 0x17, 0x8c, 0x62, 0x46, 0x52, 0x00, 0x00, 0x92, 0xd2, 0x18, 0xd2, 0x8a, -0xba, 0x1a, 0x00, 0xd5, 0x52, 0x42, 0x02, 0x9b, 0x92, 0xb2, 0x93, 0x42, 0x0c, 0xd9, 0x84, 0x45, -0x04, 0xd1, 0x66, 0x48, 0xc2, 0x79, 0x01, 0x98, 0x82, 0x42, 0x05, 0xd0, 0x8b, 0x42, 0x03, 0xd9, -0x61, 0x48, 0x41, 0x8d, 0x49, 0x1c, 0x01, 0xe0, 0x5f, 0x48, 0x00, 0x21, 0x41, 0x85, 0x65, 0x48, -0x40, 0x8c, 0x64, 0x28, 0x03, 0xd9, 0x5c, 0x49, 0x00, 0x20, 0x48, 0x85, 0x47, 0xe0, 0x5a, 0x49, -0xff, 0x23, 0x4a, 0x8d, 0xe1, 0x33, 0x9a, 0x42, 0x41, 0xd3, 0x64, 0x28, 0x3f, 0xd2, 0x00, 0x20, -0x48, 0x85, 0x51, 0x4f, 0x52, 0x49, 0x38, 0x79, 0x28, 0x75, 0x00, 0x0a, 0x68, 0x75, 0x00, 0x98, -0x40, 0x18, 0x01, 0x7f, 0xc2, 0x7e, 0x08, 0x02, 0x10, 0x43, 0x20, 0x75, 0x00, 0x0a, 0x60, 0x75, -0x06, 0xf0, 0x10, 0xf8, 0x05, 0xf0, 0xe0, 0xf9, 0x68, 0x7d, 0x29, 0x7d, 0x00, 0x02, 0x52, 0x4d, -0x08, 0x43, 0xa8, 0x80, 0x51, 0x49, 0xc8, 0x73, 0x00, 0xf0, 0x38, 0xfa, 0x61, 0x7d, 0x22, 0x7d, -0x09, 0x02, 0x11, 0x43, 0x7d, 0x22, 0x12, 0x01, 0x51, 0x43, 0xfa, 0xf7, 0x07, 0xff, 0xe8, 0x80, -0x42, 0x48, 0xf1, 0x7d, 0xc1, 0x71, 0x4a, 0x48, 0xf9, 0x79, 0x41, 0x76, 0x39, 0x7a, 0x01, 0x76, -0x78, 0x7a, 0xf0, 0x71, 0xb8, 0x7a, 0x70, 0x72, 0xf8, 0x7a, 0xb0, 0x72, 0x05, 0x99, 0x00, 0x20, -0x88, 0x76, 0x44, 0x49, 0x01, 0x20, 0x48, 0x74, 0x07, 0xb0, 0xf0, 0xbd, 0x08, 0xe0, 0x42, 0x48, -0x00, 0x21, 0x41, 0x64, 0x81, 0x64, 0xc1, 0x64, 0x01, 0x65, 0x41, 0x65, 0x07, 0xb0, 0xf0, 0xbd, -0x00, 0x21, 0x2d, 0x4b, 0x3d, 0x4e, 0x00, 0x96, 0x00, 0x2a, 0x12, 0xd9, 0x8e, 0x00, 0x4f, 0x00, -0xf6, 0x18, 0xff, 0x18, 0x36, 0x8c, 0xff, 0x8a, 0xf6, 0x1b, 0x00, 0xd5, 0x76, 0x42, 0xb6, 0xb2, -0x66, 0x45, 0x02, 0xd2, 0xb4, 0x46, 0x00, 0x9e, 0x71, 0x72, 0x49, 0x1c, 0xc9, 0xb2, 0x8a, 0x42, -0xec, 0xd8, 0x00, 0x99, 0x49, 0x7a, 0x81, 0x42, 0xd9, 0xd0, 0x21, 0x48, 0x49, 0x00, 0x0e, 0x18, -0x30, 0x7f, 0xf2, 0x7e, 0x01, 0x02, 0x11, 0x43, 0x2d, 0x48, 0xfa, 0xf7, 0xbf, 0xfe, 0x2e, 0x4a, -0x2c, 0x4f, 0x53, 0x7c, 0x12, 0x7c, 0x01, 0x46, 0x1b, 0x02, 0x78, 0x7b, 0x13, 0x43, 0xc0, 0x1a, -0x64, 0x22, 0x50, 0x43, 0xfa, 0xf7, 0xc0, 0xfe, 0x39, 0x7c, 0x40, 0x1a, 0x28, 0x75, 0x00, 0x0a, -0x68, 0x75, 0x30, 0x7f, 0xf1, 0x7e, 0x00, 0x02, 0x08, 0x43, 0x20, 0x75, 0x00, 0x0a, 0x60, 0x75, -0x05, 0xf0, 0x98, 0xff, 0x05, 0xf0, 0x68, 0xf9, 0x68, 0x7d, 0x29, 0x7d, 0x00, 0x02, 0x16, 0x4d, -0x08, 0x43, 0xa8, 0x80, 0x15, 0x49, 0xc8, 0x73, 0x00, 0xf0, 0xc0, 0xf9, 0x61, 0x7d, 0x22, 0x7d, -0x09, 0x02, 0x11, 0x43, 0x7d, 0x22, 0x12, 0x01, 0x51, 0x43, 0xfa, 0xf7, 0x8f, 0xfe, 0xe8, 0x80, -0x07, 0xb0, 0xf0, 0xbd, 0x8c, 0x03, 0x01, 0x20, 0xb8, 0x2d, 0x01, 0x20, 0xa9, 0x0c, 0x01, 0x20, -0xa8, 0x0c, 0x01, 0x20, 0xe8, 0x0c, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, 0x1a, 0x01, 0x01, 0x20, -0x68, 0x0d, 0x01, 0x20, 0xa8, 0x0d, 0x01, 0x20, 0x88, 0x0d, 0x01, 0x20, 0xb3, 0x0d, 0x01, 0x20, -0xab, 0x0c, 0x01, 0x20, 0x84, 0x2d, 0x01, 0x20, 0x00, 0x50, 0x03, 0x40, 0x80, 0x51, 0x03, 0x40, -0x48, 0x0d, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, 0x94, 0x2d, 0x01, 0x20, 0x78, 0x2e, 0x01, 0x20, -0xa0, 0x86, 0x01, 0x00, 0xe8, 0x0d, 0x01, 0x20, 0xa9, 0x0d, 0x01, 0x20, 0x70, 0x47, 0x00, 0x00, -0x01, 0x46, 0x00, 0x20, 0x1c, 0x4a, 0x01, 0x29, 0x0e, 0xd0, 0x02, 0x29, 0x16, 0xd0, 0x04, 0x29, -0x16, 0xd0, 0x08, 0x29, 0x24, 0xd0, 0x10, 0x29, 0x24, 0xd0, 0x20, 0x29, 0x03, 0xd1, 0x10, 0x7a, -0x00, 0x28, 0x26, 0xd0, 0x15, 0x48, 0x70, 0x47, 0x11, 0x7a, 0x00, 0x29, 0x04, 0xd0, 0x11, 0x7a, -0x01, 0x29, 0xf8, 0xd1, 0x12, 0x48, 0x70, 0x47, 0x12, 0x48, 0x70, 0x47, 0x12, 0x48, 0x70, 0x47, -0x12, 0x48, 0xc0, 0x7d, 0x80, 0x07, 0x09, 0xd5, 0x11, 0x48, 0x00, 0x7d, 0x02, 0x28, 0x05, 0xd1, -0x10, 0x48, 0x40, 0x78, 0x00, 0x28, 0x01, 0xd0, 0x0f, 0x48, 0x70, 0x47, 0x0f, 0x48, 0x70, 0x47, -0x0f, 0x48, 0x70, 0x47, 0x0f, 0x48, 0x00, 0x78, 0x00, 0x28, 0x0f, 0x48, 0xf9, 0xd0, 0x70, 0x30, -0x70, 0x47, 0x0e, 0x48, 0x70, 0x47, 0x00, 0x00, 0x6c, 0x03, 0x01, 0x20, 0xd0, 0x24, 0x02, 0x20, -0x00, 0x20, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x50, 0x01, 0x20, 0xe8, 0x0d, 0x01, 0x20, -0xa8, 0x0c, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, 0x00, 0x48, 0x01, 0x20, 0x00, 0x40, 0x01, 0x20, -0x00, 0x40, 0x02, 0x20, 0x88, 0x04, 0x01, 0x20, 0xa8, 0x03, 0x01, 0x20, 0xd0, 0x04, 0x02, 0x20, -0x70, 0xb5, 0x0a, 0x4e, 0x01, 0x25, 0x70, 0x78, 0x80, 0x07, 0xc4, 0x0f, 0x08, 0xf0, 0xc0, 0xfe, -0x00, 0x21, 0x70, 0x78, 0x80, 0x07, 0xc0, 0x0f, 0xa0, 0x42, 0xf3, 0xd1, 0x49, 0x1c, 0xc9, 0xb2, -0x03, 0x29, 0xf6, 0xd3, 0x00, 0x2d, 0xed, 0xd0, 0x20, 0x46, 0x70, 0xbd, 0x60, 0x00, 0x03, 0x40, -0x70, 0xb5, 0x0a, 0x4e, 0x01, 0x25, 0x70, 0x78, 0xc4, 0x07, 0xe4, 0x0f, 0x08, 0xf0, 0xa8, 0xfe, -0x00, 0x21, 0x70, 0x78, 0xc0, 0x07, 0xc0, 0x0f, 0xa0, 0x42, 0xf3, 0xd1, 0x49, 0x1c, 0xc9, 0xb2, -0x03, 0x29, 0xf6, 0xd3, 0x00, 0x2d, 0xed, 0xd0, 0x20, 0x46, 0x70, 0xbd, 0x60, 0x00, 0x03, 0x40, -0x70, 0xb5, 0x0a, 0x4e, 0x01, 0x25, 0x30, 0x78, 0x04, 0x07, 0x24, 0x0f, 0x08, 0xf0, 0x90, 0xfe, -0x00, 0x21, 0x30, 0x78, 0x00, 0x07, 0x00, 0x0f, 0xa0, 0x42, 0xf3, 0xd1, 0x49, 0x1c, 0xc9, 0xb2, -0x03, 0x29, 0xf6, 0xd3, 0x00, 0x2d, 0xed, 0xd0, 0x20, 0x46, 0x70, 0xbd, 0x60, 0x00, 0x03, 0x40, -0x1f, 0x28, 0x01, 0xd1, 0x11, 0x29, 0x03, 0xd0, 0x08, 0x43, 0x01, 0xd0, 0x00, 0x20, 0x70, 0x47, -0x01, 0x20, 0x70, 0x47, 0x04, 0x48, 0x00, 0x78, 0x80, 0x07, 0x01, 0xd5, 0x02, 0x20, 0x00, 0xe0, -0x01, 0x20, 0x02, 0x49, 0x48, 0x77, 0x70, 0x47, 0x00, 0x30, 0x03, 0x40, 0x08, 0x0e, 0x01, 0x20, -0x10, 0xb5, 0x20, 0x20, 0xff, 0xf7, 0x44, 0xff, 0x01, 0x46, 0x90, 0x22, 0x01, 0x48, 0xfa, 0xf7, -0x33, 0xfd, 0x10, 0xbd, 0xe4, 0x11, 0x01, 0x20, 0x10, 0x20, 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, -0x10, 0xb5, 0x04, 0x48, 0xc1, 0x7c, 0x04, 0x48, 0x00, 0x68, 0x40, 0x00, 0xfa, 0xf7, 0x8e, 0xfd, -0x10, 0xbd, 0x00, 0x00, 0x20, 0x00, 0x03, 0x40, 0x34, 0x00, 0x01, 0x20, 0x17, 0x49, 0xff, 0x20, -0x09, 0x6a, 0x17, 0x4a, 0x8c, 0x46, 0x09, 0x78, 0x02, 0x29, 0x05, 0xd0, 0x03, 0x29, 0x03, 0xd0, -0x04, 0x29, 0x01, 0xd0, 0x05, 0x29, 0x20, 0xd1, 0xf0, 0xb4, 0x54, 0x7d, 0x11, 0x4e, 0x95, 0x7d, -0x00, 0x21, 0x11, 0x4b, 0x4a, 0x00, 0x9b, 0x5a, 0xb2, 0x5a, 0x17, 0x19, 0x9f, 0x42, 0x01, 0xd2, -0x05, 0x20, 0x03, 0xe0, 0x5b, 0x19, 0x93, 0x42, 0x00, 0xd2, 0x04, 0x20, 0x14, 0x22, 0x4a, 0x43, -0x62, 0x44, 0x92, 0x7c, 0x03, 0x2a, 0x05, 0xd0, 0x49, 0x1c, 0xc9, 0xb2, 0x05, 0x29, 0xe8, 0xd3, -0xf0, 0xbc, 0x70, 0x47, 0xf0, 0xbc, 0xff, 0x20, 0x70, 0x47, 0x70, 0x47, 0x38, 0x02, 0x01, 0x20, -0x8c, 0x00, 0x01, 0x20, 0xca, 0x34, 0x01, 0x20, 0xc0, 0x34, 0x01, 0x20, 0x01, 0x46, 0x10, 0xb5, -0x02, 0x48, 0x40, 0x68, 0xfa, 0xf7, 0x4a, 0xfd, 0xc8, 0xb2, 0x10, 0xbd, 0x64, 0x00, 0x01, 0x20, -0x01, 0x28, 0x01, 0xd0, 0x00, 0x28, 0x51, 0xd1, 0x70, 0xb5, 0x06, 0x00, 0x28, 0x4a, 0x84, 0xb0, -0x56, 0x72, 0x28, 0x48, 0x10, 0x60, 0x36, 0xd0, 0x27, 0x48, 0x43, 0x7b, 0x01, 0x7b, 0x18, 0x06, -0x00, 0x14, 0x08, 0x43, 0x00, 0xd5, 0x40, 0x42, 0x00, 0xb2, 0x50, 0x81, 0x00, 0x2e, 0x01, 0xd0, -0x40, 0x42, 0x00, 0xb2, 0x21, 0x4c, 0x00, 0x21, 0x21, 0x80, 0x11, 0x79, 0x07, 0x25, 0xed, 0x02, -0x00, 0x95, 0x02, 0x91, 0x01, 0x90, 0x91, 0x79, 0x50, 0x79, 0x1d, 0x4b, 0x14, 0x22, 0xfb, 0xf7, -0xb7, 0xfa, 0x1c, 0x4d, 0x00, 0x2e, 0x19, 0xd0, 0x21, 0x88, 0x1b, 0x48, 0x81, 0x81, 0x20, 0x88, -0x00, 0x21, 0x88, 0x42, 0x0d, 0xd9, 0x48, 0x00, 0x02, 0x19, 0x96, 0x78, 0xd2, 0x78, 0x43, 0x19, -0xff, 0x33, 0x01, 0x33, 0x9e, 0x73, 0xda, 0x73, 0x49, 0x1c, 0x20, 0x88, 0x89, 0xb2, 0x88, 0x42, -0xf1, 0xd8, 0x04, 0xb0, 0x70, 0xbd, 0x11, 0x48, 0x80, 0x88, 0xcd, 0xe7, 0x20, 0x88, 0x0c, 0x23, -0xc1, 0xb2, 0xaa, 0x1c, 0xa0, 0x1c, 0x03, 0xf0, 0x93, 0xfb, 0x20, 0x88, 0x16, 0x28, 0x01, 0xd9, -0x16, 0x20, 0x00, 0xe0, 0x20, 0x88, 0x28, 0x80, 0x04, 0xb0, 0x70, 0xbd, 0x70, 0x47, 0x00, 0x00, -0xac, 0x1b, 0x01, 0x20, 0x00, 0x50, 0x01, 0x20, 0x68, 0x0d, 0x01, 0x20, 0x00, 0x58, 0x01, 0x20, -0x2a, 0x30, 0x00, 0x00, 0x44, 0x24, 0x01, 0x20, 0x44, 0x25, 0x01, 0x20, 0x1a, 0x01, 0x01, 0x20, -0x10, 0xb5, 0x00, 0x20, 0xff, 0xf7, 0x94, 0xff, 0x10, 0xbd, 0x00, 0x00, 0x10, 0xb5, 0x06, 0x48, -0x06, 0x49, 0x40, 0x79, 0xc0, 0x00, 0x40, 0x18, 0x81, 0x78, 0x05, 0x48, 0x00, 0x68, 0x40, 0x00, -0xfa, 0xf7, 0xcc, 0xfc, 0x10, 0xbd, 0x00, 0x00, 0xcc, 0x00, 0x01, 0x20, 0x49, 0xee, 0x00, 0x00, -0x34, 0x00, 0x01, 0x20, 0xf3, 0xb5, 0x89, 0xb0, 0x00, 0x21, 0x02, 0x91, 0x03, 0x91, 0x00, 0x91, -0x0a, 0x99, 0x01, 0x90, 0x88, 0x42, 0x7d, 0xd2, 0x95, 0x48, 0x96, 0x4c, 0x07, 0x90, 0x20, 0x46, -0x20, 0x30, 0x40, 0x34, 0x06, 0x90, 0x01, 0x98, 0x14, 0x21, 0x48, 0x43, 0x92, 0x4a, 0x05, 0x90, -0x10, 0x5c, 0x00, 0x28, 0x6f, 0xd0, 0x05, 0x99, 0x8e, 0x18, 0x02, 0x99, 0x33, 0x7d, 0x00, 0x29, -0x0c, 0xd1, 0x03, 0x9d, 0x01, 0x09, 0x2d, 0x09, 0x09, 0x01, 0x2d, 0x01, 0xa9, 0x42, 0x03, 0xd0, -0x1b, 0x09, 0x1b, 0x01, 0x99, 0x42, 0x01, 0xd1, 0x01, 0x21, 0x02, 0x91, 0x03, 0x90, 0x71, 0x68, -0xf0, 0x68, 0x88, 0x47, 0x31, 0x46, 0x80, 0x39, 0x08, 0x91, 0x89, 0x6f, 0x00, 0x27, 0x01, 0x40, -0x04, 0x91, 0x35, 0x7c, 0xff, 0x2d, 0x15, 0xd0, 0x00, 0x2d, 0x24, 0xd0, 0x7f, 0x49, 0x01, 0x20, -0xc8, 0x70, 0x00, 0x20, 0x60, 0x74, 0x7e, 0x48, 0x02, 0x7a, 0x02, 0x23, 0x1a, 0x43, 0x02, 0x72, -0xff, 0x21, 0x00, 0x20, 0x2a, 0x46, 0x82, 0x40, 0x12, 0x06, 0x41, 0xd5, 0x07, 0x21, 0x08, 0x1a, -0xc1, 0xb2, 0x41, 0xe0, 0x75, 0x49, 0x00, 0x20, 0xc8, 0x70, 0x75, 0x48, 0x01, 0x7a, 0xfd, 0x22, -0x11, 0x40, 0x01, 0x72, 0xfd, 0xf7, 0x5c, 0xfe, 0x05, 0xf0, 0x84, 0xfc, 0x08, 0xf0, 0x56, 0xfc, -0x05, 0xf0, 0x58, 0xfd, 0x6b, 0xe0, 0x01, 0x20, 0x6c, 0x49, 0x00, 0x25, 0xc8, 0x70, 0x65, 0x74, -0x6b, 0x48, 0x01, 0x7a, 0x02, 0x22, 0x11, 0x43, 0x01, 0x72, 0x78, 0x07, 0x68, 0x49, 0x40, 0x0f, -0xc8, 0x72, 0x07, 0x98, 0xc0, 0x78, 0x00, 0x28, 0x0c, 0xd0, 0x06, 0x98, 0x00, 0x7d, 0x01, 0x28, -0x08, 0xd1, 0x65, 0x70, 0x60, 0x78, 0x00, 0x28, 0x04, 0xd1, 0x08, 0xf0, 0x09, 0xfd, 0x60, 0x78, -0x00, 0x28, 0xfa, 0xd0, 0x05, 0xf0, 0x5e, 0xfc, 0x08, 0xf0, 0x30, 0xfc, 0x05, 0xf0, 0x32, 0xfd, -0x7f, 0x1c, 0x01, 0xe0, 0xaa, 0xe0, 0xa1, 0xe0, 0xff, 0xb2, 0x08, 0x2f, 0xdd, 0xd3, 0x3e, 0xe0, -0x40, 0x1c, 0xc0, 0xb2, 0x07, 0x28, 0xb5, 0xd9, 0xff, 0x29, 0x38, 0xd0, 0x01, 0x20, 0x88, 0x40, -0x85, 0x43, 0xff, 0x20, 0x84, 0x46, 0x2b, 0x46, 0x00, 0x20, 0x1a, 0x46, 0x82, 0x40, 0x12, 0x06, -0x04, 0xd5, 0x07, 0x22, 0x10, 0x1a, 0xc0, 0xb2, 0x84, 0x46, 0x03, 0xe0, 0x40, 0x1c, 0xc0, 0xb2, -0x07, 0x28, 0xf2, 0xd9, 0x60, 0x46, 0xff, 0x28, 0x02, 0xd1, 0x48, 0x4a, 0x01, 0x20, 0x10, 0x71, -0x47, 0x48, 0xc1, 0x72, 0x07, 0x98, 0xc0, 0x78, 0x00, 0x28, 0x0d, 0xd0, 0x06, 0x98, 0x00, 0x7d, -0x01, 0x28, 0x09, 0xd1, 0x00, 0x20, 0x60, 0x70, 0x60, 0x78, 0x00, 0x28, 0x04, 0xd1, 0x08, 0xf0, -0xc7, 0xfc, 0x60, 0x78, 0x00, 0x28, 0xfa, 0xd0, 0x05, 0xf0, 0x1c, 0xfc, 0x08, 0xf0, 0xee, 0xfb, -0x05, 0xf0, 0xf0, 0xfc, 0x7f, 0x1c, 0xff, 0xb2, 0x08, 0x2f, 0x00, 0xd2, 0x78, 0xe7, 0x02, 0x98, -0x01, 0x28, 0x02, 0xd0, 0x02, 0x28, 0x07, 0xd0, 0x0f, 0xe0, 0x01, 0x20, 0xff, 0xf7, 0x90, 0xfd, -0x00, 0x90, 0x02, 0x20, 0x02, 0x90, 0x51, 0xe0, 0x00, 0x20, 0x02, 0x90, 0x01, 0x20, 0xff, 0xf7, -0x87, 0xfd, 0xb3, 0x68, 0x04, 0x9a, 0x00, 0x99, 0x98, 0x47, 0x01, 0x20, 0xff, 0xf7, 0x80, 0xfd, -0x84, 0x46, 0x01, 0x99, 0x2b, 0x4b, 0x00, 0x20, 0x08, 0x29, 0x35, 0xd2, 0x00, 0x29, 0x02, 0xd0, -0x30, 0x46, 0x20, 0x38, 0x00, 0x7b, 0x24, 0x49, 0x05, 0x9a, 0x00, 0x09, 0x89, 0x5c, 0x00, 0x01, -0x09, 0x09, 0x09, 0x01, 0x81, 0x42, 0x04, 0xd1, 0x08, 0x98, 0xf1, 0x68, 0x80, 0x6f, 0x08, 0x43, -0x00, 0xe0, 0xf0, 0x68, 0x00, 0x22, 0xc7, 0x43, 0x1f, 0x48, 0xc1, 0x79, 0x00, 0x29, 0x1b, 0xd9, -0x38, 0x46, 0xd0, 0x40, 0xc0, 0x07, 0x11, 0xd0, 0x1b, 0x4e, 0x00, 0x21, 0x30, 0x7a, 0x00, 0x28, -0x0c, 0xd9, 0x10, 0x46, 0x24, 0x25, 0x68, 0x43, 0x65, 0x46, 0x45, 0x19, 0x30, 0x46, 0x4e, 0x00, -0xab, 0x53, 0x49, 0x1c, 0x06, 0x7a, 0xc9, 0xb2, 0x8e, 0x42, 0xf8, 0xd8, 0x12, 0x48, 0x52, 0x1c, -0xc0, 0x79, 0xd2, 0xb2, 0x90, 0x42, 0xe3, 0xd8, 0x06, 0x98, 0x00, 0x7d, 0x01, 0x28, 0x01, 0xd1, -0x04, 0xf0, 0x2e, 0xfb, 0x00, 0x21, 0x03, 0x20, 0x08, 0xf0, 0x3a, 0xfc, 0x01, 0x98, 0x0a, 0x99, -0x40, 0x1c, 0xc0, 0xb2, 0x01, 0x90, 0x88, 0x42, 0x00, 0xd2, 0xdc, 0xe6, 0x0b, 0xb0, 0xf0, 0xbd, -0x48, 0x0d, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, 0x24, 0x01, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, -0x40, 0x50, 0x03, 0x40, 0xc4, 0x09, 0x00, 0x00, 0xa8, 0x0c, 0x01, 0x20, 0x03, 0x49, 0x01, 0x28, -0x02, 0xd0, 0x05, 0x20, 0x08, 0x74, 0x70, 0x47, 0x02, 0x20, 0xfb, 0xe7, 0x00, 0x00, 0x03, 0x40, -0x0a, 0x28, 0x05, 0xd8, 0x03, 0x49, 0x8b, 0x88, 0x01, 0x22, 0x82, 0x40, 0x93, 0x43, 0x8b, 0x80, -0x70, 0x47, 0x00, 0x00, 0x00, 0x30, 0x03, 0x40, 0x70, 0xb5, 0x11, 0x4d, 0x69, 0x68, 0x11, 0x48, -0x01, 0x60, 0x29, 0x69, 0x41, 0x60, 0xa9, 0x69, 0x00, 0x24, 0x01, 0x26, 0x81, 0x60, 0x20, 0x46, -0x00, 0xf0, 0x48, 0xf8, 0x02, 0x28, 0x0d, 0xd1, 0x0a, 0x2c, 0x04, 0xd8, 0xa8, 0x8b, 0x32, 0x46, -0xa2, 0x40, 0x10, 0x43, 0xa8, 0x83, 0x0a, 0x2c, 0x04, 0xd8, 0x28, 0x8a, 0x32, 0x46, 0xa2, 0x40, -0x90, 0x43, 0x28, 0x82, 0x64, 0x1c, 0xe4, 0xb2, 0x0a, 0x2c, 0xe8, 0xd9, 0x70, 0xbd, 0x00, 0x00, -0x00, 0x30, 0x03, 0x40, 0xd0, 0x0e, 0x01, 0x20, 0x04, 0x48, 0x05, 0x49, 0x02, 0x68, 0x4a, 0x60, -0x42, 0x68, 0x0a, 0x61, 0x80, 0x68, 0x88, 0x61, 0x70, 0x47, 0x00, 0x00, 0xd0, 0x0e, 0x01, 0x20, -0x00, 0x30, 0x03, 0x40, 0x0a, 0x28, 0x09, 0xd8, 0x05, 0x4b, 0x01, 0x22, 0x82, 0x40, 0x98, 0x8b, -0x00, 0x29, 0x01, 0xd0, 0x10, 0x43, 0x00, 0xe0, 0x90, 0x43, 0x98, 0x83, 0x70, 0x47, 0x00, 0x00, -0x00, 0x30, 0x03, 0x40, 0x0a, 0x28, 0x09, 0xd8, 0x05, 0x4b, 0x01, 0x22, 0x82, 0x40, 0x18, 0x8a, -0x00, 0x29, 0x01, 0xd0, 0x10, 0x43, 0x00, 0xe0, 0x90, 0x43, 0x18, 0x82, 0x70, 0x47, 0x00, 0x00, -0x00, 0x30, 0x03, 0x40, 0x0a, 0x28, 0x02, 0xd9, 0x00, 0x20, 0xc0, 0x43, 0x70, 0x47, 0x30, 0xb5, -0x13, 0x4d, 0xa9, 0x88, 0x01, 0x24, 0x84, 0x40, 0xa1, 0x43, 0xa9, 0x80, 0x00, 0x21, 0xff, 0xf7, -0xd1, 0xff, 0x68, 0x8b, 0xa0, 0x43, 0x68, 0x83, 0x28, 0x8b, 0x20, 0x43, 0x28, 0x83, 0x69, 0x8a, -0xe0, 0xb2, 0x01, 0x40, 0x00, 0xd0, 0x01, 0x21, 0x00, 0x29, 0x01, 0xd0, 0x01, 0x20, 0x30, 0xbd, -0x29, 0x8b, 0xa1, 0x43, 0x29, 0x83, 0x69, 0x8b, 0x21, 0x43, 0x69, 0x83, 0x69, 0x8a, 0x01, 0x42, -0x01, 0xd0, 0x01, 0x20, 0x00, 0xe0, 0x00, 0x20, 0x00, 0x28, 0xf0, 0xd0, 0x02, 0x20, 0x30, 0xbd, -0x00, 0x30, 0x03, 0x40, 0xf0, 0xb5, 0x5c, 0x48, 0x5c, 0x4e, 0xc1, 0x7f, 0x89, 0xb0, 0x33, 0x7c, -0x5b, 0x48, 0x00, 0x25, 0x02, 0x90, 0x00, 0x7e, 0x2a, 0x46, 0x00, 0x2b, 0x01, 0xd0, 0x00, 0x28, -0x05, 0xd0, 0x01, 0x28, 0x05, 0xd9, 0xb3, 0x7a, 0x5b, 0x00, 0x03, 0x93, 0x04, 0xe0, 0x55, 0x4b, -0x9a, 0x73, 0x73, 0x7a, 0x5b, 0x00, 0x03, 0x93, 0x00, 0x27, 0x00, 0x28, 0x77, 0xd9, 0x52, 0x48, -0x05, 0x90, 0x6e, 0x20, 0x41, 0x43, 0x51, 0x48, 0x08, 0x18, 0x04, 0x90, 0x0c, 0x20, 0x39, 0x46, -0x41, 0x43, 0x4e, 0x48, 0x0a, 0x18, 0x11, 0x21, 0x89, 0x01, 0x54, 0x18, 0xa1, 0x7e, 0x09, 0x22, -0x40, 0x18, 0x86, 0x46, 0x12, 0x02, 0x80, 0x18, 0x01, 0x90, 0x80, 0x7d, 0x02, 0x28, 0x02, 0xd0, -0x01, 0x28, 0x72, 0xd0, 0x77, 0xe0, 0x05, 0x9a, 0x00, 0x20, 0x92, 0x7b, 0x94, 0x46, 0x00, 0x2a, -0x10, 0xd9, 0x0c, 0x23, 0x02, 0x46, 0x5a, 0x43, 0x40, 0x4b, 0xd3, 0x18, 0x0d, 0x22, 0x92, 0x01, -0x9a, 0x18, 0x12, 0x7c, 0x8a, 0x42, 0x01, 0xd1, 0x05, 0x46, 0x03, 0xe0, 0x40, 0x1c, 0xc0, 0xb2, -0x84, 0x45, 0xee, 0xd8, 0x84, 0x45, 0x5e, 0xd0, 0x0a, 0x22, 0x04, 0x98, 0x4a, 0x43, 0x82, 0x18, -0x19, 0x20, 0x80, 0x01, 0x10, 0x18, 0x02, 0x88, 0x07, 0x92, 0x40, 0x88, 0x06, 0x90, 0x25, 0x20, -0x80, 0x01, 0x70, 0x44, 0x00, 0x90, 0xc0, 0x7b, 0x00, 0x28, 0x10, 0xd1, 0x0c, 0x20, 0x2a, 0x46, -0x42, 0x43, 0x2e, 0x48, 0x12, 0x18, 0x0d, 0x20, 0x80, 0x01, 0x12, 0x18, 0x94, 0x46, 0x53, 0x8a, -0x2b, 0x4a, 0x48, 0x00, 0x13, 0x52, 0x62, 0x46, 0x2a, 0x4b, 0x92, 0x8a, 0x1a, 0x52, 0x48, 0x00, -0x28, 0x49, 0x0a, 0x5a, 0x06, 0x99, 0x89, 0x1a, 0x25, 0x4a, 0x09, 0xb2, 0x12, 0x5a, 0x07, 0x98, -0x80, 0x1a, 0x00, 0xb2, 0xfb, 0xf7, 0x70, 0xfe, 0x03, 0x99, 0x88, 0x42, 0x22, 0xd2, 0x00, 0x98, -0x32, 0x7a, 0xc0, 0x7b, 0x1d, 0x49, 0x90, 0x42, 0x0a, 0xd2, 0x00, 0x9a, 0x40, 0x1c, 0xd0, 0x73, -0xf0, 0x79, 0x02, 0x28, 0x1f, 0xd1, 0x01, 0x9a, 0x03, 0x20, 0x90, 0x75, 0x06, 0xe0, 0x21, 0xe0, -0x01, 0x9a, 0x03, 0x20, 0x90, 0x75, 0xf0, 0x79, 0x00, 0x28, 0x14, 0xd0, 0x0c, 0x20, 0x68, 0x43, -0x41, 0x18, 0x0d, 0x20, 0x80, 0x01, 0x08, 0x18, 0x41, 0x8a, 0xa1, 0x83, 0x80, 0x8a, 0xe0, 0x83, -0x09, 0xe0, 0x02, 0xe0, 0x00, 0x20, 0x00, 0x99, 0x04, 0xe0, 0x25, 0x22, 0x00, 0x20, 0x71, 0x46, -0x92, 0x01, 0x89, 0x18, 0xc8, 0x73, 0x02, 0x98, 0x7f, 0x1c, 0x00, 0x7e, 0xff, 0xb2, 0xb8, 0x42, -0x00, 0xd9, 0x6b, 0xe7, 0x09, 0xb0, 0xf0, 0xbd, 0x24, 0x2d, 0x01, 0x20, 0x68, 0x0d, 0x01, 0x20, -0x84, 0x28, 0x01, 0x20, 0xa4, 0x2d, 0x01, 0x20, 0x84, 0x27, 0x01, 0x20, 0x44, 0x24, 0x01, 0x20, -0x28, 0x19, 0x01, 0x20, 0x54, 0x19, 0x01, 0x20, 0xf8, 0xb5, 0x02, 0x25, 0x24, 0x4e, 0x00, 0x20, -0xb0, 0x70, 0x03, 0x21, 0x71, 0x71, 0x70, 0x70, 0x04, 0xf0, 0xf8, 0xfd, 0xfe, 0xf7, 0x02, 0xf9, -0x20, 0x4f, 0x04, 0x20, 0xf8, 0x77, 0x01, 0xe0, 0x08, 0xf0, 0xca, 0xfa, 0xff, 0xf7, 0x30, 0xfc, -0x00, 0x28, 0xf9, 0xd1, 0x70, 0x79, 0x03, 0x28, 0xf6, 0xd1, 0x1b, 0x48, 0x81, 0x7c, 0xef, 0x22, -0x11, 0x40, 0x81, 0x74, 0x81, 0x7c, 0xdf, 0x22, 0x11, 0x40, 0x81, 0x74, 0x17, 0x48, 0x00, 0x7d, -0xb8, 0x73, 0x05, 0xf0, 0x1f, 0xf9, 0x00, 0xf0, 0x33, 0xf8, 0xfb, 0xf7, 0x77, 0xfb, 0xfb, 0xf7, -0xff, 0xfa, 0x13, 0x4c, 0x0b, 0xe0, 0x60, 0x79, 0xa8, 0x42, 0x02, 0xd0, 0x00, 0xf0, 0x42, 0xfe, -0x65, 0x79, 0x00, 0xf0, 0x4f, 0xfe, 0x03, 0x21, 0x04, 0x20, 0x08, 0xf0, 0x81, 0xfa, 0x30, 0x78, -0x04, 0x28, 0x02, 0xd1, 0x70, 0x79, 0x03, 0x28, 0xed, 0xd0, 0x04, 0xf0, 0xb9, 0xfc, 0xb9, 0x7b, -0x06, 0x48, 0x01, 0x75, 0x01, 0x20, 0x70, 0x70, 0x00, 0x20, 0xb0, 0x70, 0xf8, 0xbd, 0x00, 0x00, -0x4c, 0x03, 0x01, 0x20, 0x6c, 0x03, 0x01, 0x20, 0x00, 0x50, 0x03, 0x40, 0xa8, 0x0c, 0x01, 0x20, -0x8c, 0x03, 0x01, 0x20, 0x01, 0x49, 0x00, 0x20, 0x88, 0x80, 0x70, 0x47, 0xc4, 0x00, 0x01, 0x20, -0xf8, 0xb5, 0x05, 0xf0, 0xaf, 0xfa, 0x33, 0x48, 0x00, 0x7e, 0x01, 0x28, 0x10, 0xd1, 0x32, 0x4c, -0x61, 0x79, 0x40, 0x20, 0x01, 0x43, 0x65, 0x1d, 0x28, 0x46, 0xfd, 0xf7, 0x38, 0xfe, 0x0a, 0x20, -0x08, 0xf0, 0x32, 0xfc, 0x61, 0x79, 0xbf, 0x20, 0x01, 0x40, 0x28, 0x46, 0xfd, 0xf7, 0x2f, 0xfe, -0x2a, 0x48, 0x08, 0x21, 0xc1, 0x70, 0x2a, 0x4f, 0x00, 0x26, 0x7e, 0x61, 0x29, 0x49, 0x01, 0x22, -0xbe, 0x61, 0x29, 0x4d, 0x4a, 0x70, 0x29, 0x7d, 0x91, 0x43, 0x29, 0x75, 0x27, 0x49, 0x0e, 0x75, -0x82, 0x78, 0xef, 0x23, 0x1a, 0x40, 0x82, 0x70, 0x25, 0x48, 0x42, 0x7a, 0xaa, 0x80, 0x25, 0x4b, -0xda, 0x73, 0x80, 0x7a, 0x02, 0x01, 0x10, 0x43, 0x18, 0x74, 0x23, 0x48, 0x23, 0x4c, 0xc0, 0x7d, -0xc0, 0x06, 0x00, 0x28, 0x0e, 0xda, 0x22, 0x48, 0xc0, 0x78, 0x40, 0x00, 0x40, 0x18, 0x01, 0x7f, -0xc0, 0x7e, 0x09, 0x02, 0x01, 0x43, 0x19, 0x48, 0x82, 0x7d, 0x43, 0x7d, 0x10, 0x02, 0x18, 0x43, -0x81, 0x42, 0x08, 0xd1, 0xff, 0xf7, 0x9a, 0xfc, 0xa1, 0x7b, 0x7d, 0x22, 0x12, 0x01, 0x51, 0x43, -0xfa, 0xf7, 0x6c, 0xf9, 0xe8, 0x80, 0x20, 0x7b, 0x16, 0x4c, 0x20, 0x70, 0x16, 0x48, 0x17, 0x49, -0xc0, 0x7c, 0x49, 0x7b, 0x82, 0x06, 0x16, 0x48, 0x02, 0xd5, 0x02, 0x22, 0x11, 0x43, 0x01, 0xe0, -0xfd, 0x22, 0x11, 0x40, 0xfd, 0xf7, 0xe3, 0xfd, 0x20, 0x7e, 0x78, 0x71, 0x11, 0x48, 0x86, 0x76, -0xf8, 0xbd, 0x00, 0x00, 0x28, 0x0d, 0x01, 0x20, 0x60, 0xd1, 0x03, 0x00, 0x20, 0x00, 0x03, 0x40, -0xb0, 0x00, 0x01, 0x20, 0xc4, 0x00, 0x01, 0x20, 0x00, 0x50, 0x03, 0x40, 0xa8, 0x0c, 0x01, 0x20, -0x48, 0x0d, 0x01, 0x20, 0x80, 0x51, 0x03, 0x40, 0xe8, 0x0d, 0x01, 0x20, 0x08, 0x0e, 0x01, 0x20, -0xb8, 0x2d, 0x01, 0x20, 0x20, 0x50, 0x03, 0x40, 0xa8, 0x0d, 0x01, 0x20, 0x80, 0xd1, 0x03, 0x40, -0x8d, 0xd1, 0x03, 0x40, 0x8c, 0x03, 0x01, 0x20, 0xf8, 0xb5, 0x08, 0x20, 0xff, 0xf7, 0xd0, 0xfa, -0x00, 0x90, 0x57, 0x48, 0x00, 0x25, 0xc5, 0x80, 0x00, 0xf0, 0xe8, 0xfa, 0x56, 0x4c, 0x55, 0x48, -0x01, 0x21, 0x27, 0x46, 0x00, 0x26, 0xa0, 0x37, 0x01, 0x70, 0x05, 0x46, 0x80, 0x34, 0x38, 0x78, -0x00, 0xf0, 0x28, 0xfd, 0x20, 0x7f, 0x12, 0x28, 0x31, 0xd0, 0x00, 0x21, 0xaa, 0x20, 0x05, 0xf0, -0x51, 0xfd, 0xbc, 0x21, 0x4d, 0x48, 0xfd, 0xf7, 0x9a, 0xfd, 0xfe, 0xf7, 0x89, 0xfa, 0x05, 0xf0, -0x29, 0xf9, 0x08, 0xf0, 0x61, 0xf9, 0x20, 0x7f, 0x12, 0x28, 0x23, 0xd0, 0x00, 0x21, 0xaa, 0x20, -0x05, 0xf0, 0x40, 0xfd, 0xbc, 0x21, 0x45, 0x48, 0xfd, 0xf7, 0x89, 0xfd, 0xfe, 0xf7, 0x5e, 0xfa, -0x20, 0x7e, 0x01, 0x28, 0x19, 0xd0, 0x00, 0x20, 0x28, 0x70, 0x30, 0x46, 0x76, 0x1e, 0xf6, 0xb2, -0x00, 0x28, 0xd4, 0xd1, 0x07, 0xf0, 0x68, 0xfc, 0x39, 0x48, 0x00, 0x21, 0x81, 0x70, 0xf9, 0x7d, -0x3b, 0x4f, 0x00, 0x29, 0x11, 0xd0, 0x01, 0x21, 0x01, 0x70, 0x03, 0x20, 0x56, 0xe0, 0xfb, 0xf7, -0xb9, 0xff, 0xd4, 0xe7, 0xfb, 0xf7, 0x46, 0xff, 0xe2, 0xe7, 0x28, 0x78, 0x00, 0x28, 0xe4, 0xd0, -0x00, 0x20, 0x76, 0x1c, 0x28, 0x70, 0xf6, 0xb2, 0xdf, 0xe7, 0x40, 0x78, 0x00, 0x28, 0x01, 0xd0, -0x02, 0x26, 0x00, 0xe0, 0x04, 0x26, 0x00, 0xf0, 0x35, 0xfc, 0x01, 0x20, 0x28, 0x70, 0x70, 0x1e, -0xc5, 0xb2, 0x00, 0x2e, 0x2c, 0xd0, 0x2b, 0x4e, 0xf0, 0x7e, 0x00, 0xf0, 0xd3, 0xfc, 0x20, 0x7f, -0x12, 0x28, 0x36, 0xd0, 0xaa, 0x21, 0x00, 0x20, 0x05, 0xf0, 0xfc, 0xfc, 0x3c, 0x21, 0x23, 0x48, -0xfd, 0xf7, 0x45, 0xfd, 0x00, 0xf0, 0xfa, 0xff, 0x05, 0xf0, 0xd4, 0xf8, 0x08, 0xf0, 0x0c, 0xf9, -0x20, 0x7f, 0x12, 0x28, 0x28, 0xd0, 0xaa, 0x21, 0x00, 0x20, 0x05, 0xf0, 0xeb, 0xfc, 0x3c, 0x21, -0x1a, 0x48, 0xfd, 0xf7, 0x34, 0xfd, 0x00, 0xf0, 0xcf, 0xff, 0x20, 0x7e, 0x01, 0x28, 0x1e, 0xd0, -0x14, 0x49, 0x00, 0x20, 0x08, 0x70, 0x28, 0x46, 0x6d, 0x1e, 0xed, 0xb2, 0x00, 0x28, 0xd3, 0xd1, -0x20, 0x20, 0xff, 0xf7, 0x3d, 0xfa, 0x01, 0x46, 0x90, 0x22, 0x13, 0x48, 0xfa, 0xf7, 0x2c, 0xf8, -0x07, 0xf0, 0x1a, 0xfd, 0x00, 0x98, 0x04, 0xf0, 0xd9, 0xfb, 0x02, 0x20, 0x38, 0x73, 0x01, 0x20, -0xf8, 0xbd, 0xfb, 0xf7, 0x5f, 0xff, 0xcf, 0xe7, 0xfb, 0xf7, 0xec, 0xfe, 0xdd, 0xe7, 0x05, 0x48, -0x01, 0x78, 0x00, 0x29, 0xdf, 0xd0, 0x00, 0x21, 0x6d, 0x1c, 0x01, 0x70, 0xed, 0xb2, 0xda, 0xe7, -0xc4, 0x00, 0x01, 0x20, 0xdd, 0x00, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0x85, 0xd2, 0x03, 0x40, -0x8c, 0x03, 0x01, 0x20, 0xe8, 0x0c, 0x01, 0x20, 0xe4, 0x11, 0x01, 0x20, 0xf0, 0xb5, 0x49, 0x4c, -0x83, 0xb0, 0x00, 0x20, 0x20, 0x71, 0x00, 0xf0, 0xcd, 0xfb, 0x47, 0x49, 0x01, 0x20, 0x08, 0x70, -0x00, 0xf0, 0xfa, 0xfa, 0x45, 0x49, 0x00, 0x91, 0x00, 0x28, 0x73, 0xd1, 0x44, 0x48, 0x02, 0x90, -0x44, 0x48, 0x01, 0x90, 0x08, 0xf0, 0x1c, 0xf9, 0xff, 0xf7, 0x82, 0xfa, 0x00, 0x28, 0x03, 0xd1, -0x41, 0x48, 0x40, 0x79, 0x03, 0x28, 0x05, 0xd0, 0x40, 0xa0, 0x08, 0xf0, 0xc1, 0xfb, 0x00, 0x20, -0x03, 0xb0, 0xf0, 0xbd, 0x00, 0x20, 0x84, 0x46, 0x01, 0x46, 0x01, 0x98, 0x00, 0x7a, 0x82, 0x07, -0x35, 0xd5, 0x02, 0x9b, 0x00, 0x22, 0x5c, 0x7a, 0x1b, 0x7a, 0x24, 0x06, 0x26, 0x14, 0x1e, 0x43, -0x87, 0x08, 0x3b, 0x48, 0x05, 0x7a, 0x00, 0x20, 0x00, 0x2d, 0x15, 0xd9, 0x24, 0x24, 0x13, 0x46, -0x63, 0x43, 0x38, 0x4c, 0x1b, 0x19, 0x44, 0x00, 0x1c, 0x5f, 0xb4, 0x42, 0x08, 0xda, 0x49, 0x1c, -0xc9, 0xb2, 0x8f, 0x42, 0x04, 0xd8, 0x27, 0x48, 0x01, 0x78, 0x49, 0x1c, 0x01, 0x70, 0x0c, 0xe0, -0x40, 0x1c, 0xc0, 0xb2, 0x85, 0x42, 0xee, 0xd8, 0x52, 0x1c, 0xd2, 0xb2, 0x04, 0x2a, 0xe2, 0xd3, -0x00, 0x29, 0x02, 0xd1, 0x1f, 0x49, 0x00, 0x20, 0x08, 0x70, 0x01, 0x98, 0xc1, 0x7a, 0x1d, 0x48, -0x02, 0x78, 0x91, 0x42, 0x03, 0xd8, 0x00, 0x21, 0x01, 0x70, 0x01, 0x20, 0x84, 0x46, 0x60, 0x46, -0x00, 0x28, 0x08, 0xd0, 0x00, 0x99, 0x01, 0x20, 0x08, 0x73, 0x23, 0x49, 0x00, 0x20, 0xc8, 0x80, -0x01, 0x20, 0x03, 0xb0, 0xf0, 0xbd, 0x20, 0x49, 0x12, 0x4a, 0xc8, 0x88, 0x40, 0x1c, 0x80, 0xb2, -0xc8, 0x80, 0x13, 0x79, 0x5b, 0x1c, 0x13, 0x71, 0x7d, 0x23, 0x1b, 0x01, 0x98, 0x42, 0x02, 0xd1, -0x08, 0x78, 0x00, 0x28, 0x0f, 0xd0, 0x10, 0x79, 0xfa, 0x28, 0x06, 0xd0, 0x00, 0xf0, 0x84, 0xfa, -0x00, 0x28, 0x8f, 0xd0, 0x14, 0x49, 0x00, 0x20, 0xc8, 0x80, 0x00, 0x99, 0x03, 0x20, 0x08, 0x73, -0x01, 0x20, 0x03, 0xb0, 0xf0, 0xbd, 0x00, 0x99, 0x01, 0x20, 0x08, 0x73, 0x0e, 0x49, 0x00, 0x20, -0xc8, 0x80, 0xf5, 0xe7, 0xb0, 0x00, 0x01, 0x20, 0xdd, 0x00, 0x01, 0x20, 0x8c, 0x03, 0x01, 0x20, -0x09, 0x0e, 0x01, 0x20, 0x08, 0x0e, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, 0x65, 0x78, 0x69, 0x74, -0x20, 0x67, 0x73, 0x74, 0x72, 0x20, 0x73, 0x74, 0x65, 0x70, 0x20, 0x32, 0x0a, 0x00, 0x00, 0x00, -0xa8, 0x0c, 0x01, 0x20, 0x04, 0x13, 0x01, 0x20, 0xc4, 0x00, 0x01, 0x20, 0xf8, 0xb5, 0x04, 0xf0, -0x25, 0xfb, 0x00, 0xf0, 0x7b, 0xf9, 0x26, 0x4d, 0x00, 0x20, 0x68, 0x70, 0x25, 0x49, 0x01, 0x20, -0x08, 0x70, 0x00, 0xf0, 0x5f, 0xf8, 0x24, 0x4c, 0x00, 0x28, 0x3e, 0xd1, 0x23, 0x4e, 0x24, 0x4d, -0x37, 0x46, 0xff, 0x36, 0xa0, 0x37, 0x61, 0x36, 0x08, 0xf0, 0x6a, 0xf8, 0xff, 0xf7, 0xd0, 0xf9, -0x00, 0x28, 0x03, 0xd1, 0x1f, 0x48, 0x40, 0x79, 0x03, 0x28, 0x04, 0xd0, 0x1e, 0xa0, 0x08, 0xf0, -0x0f, 0xfb, 0x00, 0x20, 0xf8, 0xbd, 0x16, 0x49, 0x88, 0x88, 0x40, 0x1c, 0x80, 0xb2, 0x88, 0x80, -0x3a, 0x78, 0xf3, 0x7c, 0x5a, 0x43, 0x82, 0x42, 0x02, 0xd2, 0x00, 0x20, 0x88, 0x80, 0x1c, 0xe0, -0x1a, 0x48, 0x00, 0x79, 0xfa, 0x28, 0x02, 0xd1, 0x88, 0x78, 0x00, 0x28, 0x04, 0xd0, 0x18, 0x48, -0x00, 0x78, 0x00, 0x28, 0x04, 0xd0, 0x0c, 0xe0, 0x02, 0x20, 0x20, 0x73, 0x01, 0x20, 0xf8, 0xbd, -0xe8, 0x7b, 0x00, 0x28, 0x05, 0xd0, 0x00, 0x20, 0xe8, 0x73, 0x03, 0x20, 0x20, 0x73, 0x01, 0x20, -0xf8, 0xbd, 0x00, 0xf0, 0x1f, 0xf8, 0x00, 0x28, 0xc6, 0xd0, 0x01, 0x20, 0x20, 0x73, 0xf8, 0xbd, -0xc4, 0x00, 0x01, 0x20, 0xdd, 0x00, 0x01, 0x20, 0x8c, 0x03, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, -0xa4, 0x2d, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, 0x65, 0x78, 0x69, 0x74, 0x20, 0x67, 0x73, 0x74, -0x72, 0x20, 0x73, 0x74, 0x65, 0x70, 0x20, 0x33, 0x0a, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x01, 0x20, -0x68, 0x02, 0x01, 0x20, 0xf0, 0xb5, 0x7d, 0x48, 0x83, 0xb0, 0x01, 0x78, 0x7c, 0x48, 0x01, 0x90, -0x00, 0x29, 0x05, 0xd0, 0x79, 0x48, 0x00, 0x21, 0x01, 0x70, 0xfa, 0xf7, 0x14, 0xfd, 0x02, 0xe0, -0x00, 0x78, 0x00, 0xf0, 0x4f, 0xfb, 0xfe, 0xf7, 0xa3, 0xf8, 0x04, 0xf0, 0x5b, 0xff, 0x07, 0xf0, -0x93, 0xff, 0xfe, 0xf7, 0x83, 0xf8, 0x73, 0x48, 0x02, 0x90, 0x01, 0x7e, 0x72, 0x48, 0x01, 0x29, -0x75, 0xd0, 0x00, 0x21, 0x01, 0x70, 0xfb, 0xf7, 0xb3, 0xfe, 0x70, 0x48, 0x70, 0x4d, 0xc0, 0x7c, -0xc0, 0x09, 0x23, 0xd0, 0x02, 0x20, 0xff, 0xf7, 0xcb, 0xf8, 0x04, 0x46, 0x28, 0x7a, 0x41, 0x00, -0x20, 0x46, 0x2a, 0x30, 0xf9, 0xf7, 0x1e, 0xff, 0x28, 0x7a, 0x28, 0x22, 0x41, 0x00, 0xe8, 0x79, -0x50, 0x43, 0x00, 0x19, 0x80, 0x1c, 0xf9, 0xf7, 0x15, 0xff, 0xe8, 0x79, 0x02, 0x21, 0x02, 0x28, -0x0c, 0xd9, 0x00, 0x20, 0x28, 0x22, 0x4a, 0x43, 0x12, 0x19, 0x50, 0x80, 0x2b, 0x7a, 0x49, 0x1c, -0x5b, 0x00, 0xd0, 0x52, 0xea, 0x79, 0xc9, 0xb2, 0x8a, 0x42, 0xf3, 0xd8, 0x5e, 0x48, 0x5d, 0x4e, -0x44, 0x7c, 0x02, 0x20, 0xff, 0xf7, 0xa4, 0xf8, 0x00, 0x90, 0x04, 0x20, 0xff, 0xf7, 0xa0, 0xf8, -0x86, 0x46, 0x57, 0x48, 0x01, 0x22, 0xc0, 0x79, 0x01, 0x28, 0x16, 0xd3, 0x54, 0x49, 0x0b, 0x7a, -0x01, 0x21, 0x01, 0x2b, 0x0d, 0xd3, 0x28, 0x27, 0x15, 0x46, 0x7d, 0x43, 0x00, 0x9f, 0xef, 0x19, -0x4d, 0x00, 0x7d, 0x5f, 0xb5, 0x42, 0x00, 0xdd, 0x2e, 0x46, 0x49, 0x1c, 0xc9, 0xb2, 0x8b, 0x42, -0xf6, 0xd2, 0x52, 0x1c, 0xd2, 0xb2, 0x90, 0x42, 0xea, 0xd2, 0x02, 0x99, 0x4b, 0x7a, 0x0a, 0x7a, -0x19, 0x06, 0x09, 0x14, 0x11, 0x43, 0xb1, 0x42, 0x35, 0xdb, 0x01, 0x26, 0x01, 0x28, 0x32, 0xd3, -0x60, 0x42, 0x84, 0x46, 0x42, 0x48, 0x01, 0x23, 0x00, 0x7a, 0x01, 0x28, 0x25, 0xd3, 0x30, 0x46, -0x28, 0x21, 0x48, 0x43, 0x00, 0x99, 0x47, 0x18, 0x71, 0x46, 0x42, 0x18, 0x59, 0x00, 0x7d, 0x5e, -0xa5, 0x42, 0x0c, 0xdd, 0x55, 0x5a, 0x2d, 0x19, 0x55, 0x52, 0x10, 0xe0, 0xff, 0xe7, 0x01, 0x78, -0x00, 0x29, 0x88, 0xd0, 0x00, 0x21, 0x01, 0x70, 0x08, 0x46, 0x03, 0xb0, 0xf0, 0xbd, 0x65, 0x45, -0x02, 0xda, 0x55, 0x5a, 0x2d, 0x1b, 0x01, 0xe0, 0x50, 0x5a, 0x45, 0x19, 0x55, 0x52, 0x30, 0x48, -0x5b, 0x1c, 0x00, 0x7a, 0xdb, 0xb2, 0x98, 0x42, 0xe0, 0xd2, 0x2d, 0x48, 0x76, 0x1c, 0xc0, 0x79, -0xf6, 0xb2, 0xb0, 0x42, 0xce, 0xd2, 0xff, 0xf7, 0xc3, 0xf9, 0x06, 0xf0, 0xff, 0xf9, 0x00, 0x28, -0x02, 0xd0, 0x01, 0x20, 0x03, 0xb0, 0xf0, 0xbd, 0x28, 0x48, 0x00, 0x7e, 0x80, 0x07, 0x02, 0xd0, -0x02, 0xf0, 0xf8, 0xf8, 0x01, 0xe0, 0x01, 0xf0, 0x2d, 0xf8, 0x05, 0xf0, 0xcf, 0xf9, 0x02, 0xf0, -0xbe, 0xfd, 0xfb, 0xf7, 0x1d, 0xff, 0xfa, 0xf7, 0x37, 0xfe, 0x07, 0xf0, 0xe5, 0xf8, 0xfa, 0xf7, -0x21, 0xfd, 0x03, 0xf0, 0x21, 0xf8, 0x01, 0x20, 0xfc, 0xf7, 0x5c, 0xf8, 0x00, 0xf0, 0x88, 0xfa, -0x1b, 0x48, 0x80, 0x7c, 0x00, 0x28, 0x07, 0xd0, 0x01, 0x98, 0x00, 0x7d, 0x40, 0x06, 0x03, 0xd5, -0x03, 0x21, 0x00, 0x20, 0x07, 0xf0, 0x14, 0xff, 0x01, 0xf0, 0x1c, 0xfe, 0x15, 0x48, 0x01, 0x78, -0x01, 0x20, 0x00, 0x29, 0x02, 0xd0, 0x09, 0x49, 0x88, 0x70, 0x02, 0xe0, 0x07, 0x49, 0x00, 0x22, -0x8a, 0x70, 0x11, 0x49, 0x89, 0x78, 0x00, 0x29, 0x04, 0xd0, 0x04, 0x49, 0x48, 0x70, 0x01, 0x20, -0x03, 0xb0, 0xf0, 0xbd, 0x00, 0x20, 0x03, 0xb0, 0xf0, 0xbd, 0x00, 0x00, 0xc4, 0x00, 0x01, 0x20, -0x48, 0x0d, 0x01, 0x20, 0x28, 0x0d, 0x01, 0x20, 0xdd, 0x00, 0x01, 0x20, 0xa8, 0x0d, 0x01, 0x20, -0xa8, 0x0c, 0x01, 0x20, 0xe0, 0xb1, 0xff, 0xff, 0x68, 0x0d, 0x01, 0x20, 0xa8, 0x0e, 0x01, 0x20, -0x4c, 0x03, 0x01, 0x20, 0x68, 0x02, 0x01, 0x20, 0x76, 0x00, 0x01, 0x20, 0xf0, 0xb5, 0x83, 0xb0, -0x08, 0x20, 0xfe, 0xf7, 0xdd, 0xff, 0x05, 0x46, 0x52, 0x49, 0x00, 0x20, 0x88, 0x80, 0x04, 0xf0, -0x29, 0xff, 0x51, 0x48, 0xc0, 0x7b, 0x00, 0x28, 0x57, 0xd0, 0x28, 0x46, 0x04, 0xf0, 0x76, 0xf9, -0x4e, 0x48, 0xc1, 0x79, 0x00, 0x7a, 0xfe, 0xf7, 0x57, 0xf8, 0x4d, 0x48, 0x41, 0x79, 0x4d, 0x48, -0x01, 0x76, 0x08, 0x21, 0x81, 0x76, 0x4c, 0x49, 0x0a, 0x7d, 0x52, 0x08, 0x52, 0x00, 0x0a, 0x75, -0x4a, 0x49, 0x01, 0x23, 0x8b, 0x72, 0x4a, 0x4c, 0x03, 0x22, 0x22, 0x75, 0x49, 0x4c, 0xcc, 0x83, -0x10, 0x24, 0x04, 0x75, 0xf3, 0x24, 0x84, 0x75, 0x47, 0x48, 0x00, 0x7e, 0x80, 0x1e, 0xfd, 0x28, -0x02, 0xd2, 0x48, 0x7d, 0x18, 0x43, 0x48, 0x75, 0x44, 0x49, 0xef, 0x20, 0x08, 0x74, 0x44, 0x49, -0x08, 0x74, 0x44, 0x49, 0xf0, 0x20, 0x08, 0x70, 0x43, 0x49, 0x08, 0x70, 0x43, 0x48, 0x00, 0x21, -0x01, 0x74, 0x02, 0x75, 0x42, 0x48, 0x43, 0x49, 0x00, 0x78, 0x08, 0x70, 0x0a, 0x79, 0x52, 0x09, -0x52, 0x01, 0x02, 0x43, 0x0a, 0x71, 0x40, 0x48, 0x41, 0x7e, 0x02, 0x7e, 0x08, 0x02, 0x10, 0x43, -0x69, 0x46, 0x08, 0x80, 0x32, 0x38, 0x48, 0x80, 0x28, 0x20, 0x88, 0x80, 0x14, 0x20, 0xc8, 0x71, -0x68, 0x46, 0x07, 0xf0, 0xb7, 0xfa, 0xe4, 0x21, 0x38, 0x48, 0xf9, 0xf7, 0xdb, 0xfd, 0x06, 0xf0, -0x75, 0xfc, 0x06, 0xf0, 0x7d, 0xfb, 0x03, 0xb0, 0xf0, 0xbd, 0x35, 0x4f, 0x00, 0x24, 0xf8, 0x79, -0x00, 0x28, 0xa5, 0xd9, 0x3e, 0x46, 0x81, 0x36, 0x32, 0x48, 0x40, 0x79, 0x03, 0x28, 0x1e, 0xd0, -0x39, 0x19, 0x02, 0x91, 0x5c, 0x22, 0x38, 0x79, 0x8a, 0x56, 0x81, 0x00, 0x48, 0x20, 0x60, 0x43, -0x40, 0x19, 0xf9, 0xf7, 0x9a, 0xfd, 0x12, 0x20, 0x39, 0x79, 0x60, 0x43, 0x40, 0x18, 0xff, 0x22, -0x02, 0x99, 0x23, 0x32, 0x8a, 0x56, 0x79, 0x79, 0x80, 0x00, 0x40, 0x19, 0x89, 0x00, 0xf9, 0xf7, -0x8c, 0xfd, 0x64, 0x1c, 0xf8, 0x79, 0xe4, 0xb2, 0xa0, 0x42, 0xdd, 0xd8, 0x80, 0xe7, 0x70, 0x7f, -0x31, 0x7f, 0x02, 0x02, 0x38, 0x79, 0x0a, 0x43, 0x81, 0x00, 0x48, 0x20, 0x60, 0x43, 0x40, 0x19, -0xf9, 0xf7, 0x7b, 0xfd, 0x12, 0x20, 0x39, 0x79, 0x60, 0x43, 0x40, 0x18, 0x72, 0x7f, 0x31, 0x7f, -0x12, 0x02, 0x0a, 0x43, 0x79, 0x79, 0x80, 0x00, 0x40, 0x19, 0x89, 0x00, 0xf9, 0xf7, 0x6d, 0xfd, -0xdf, 0xe7, 0x00, 0x00, 0xc4, 0x00, 0x01, 0x20, 0x8c, 0x03, 0x01, 0x20, 0xc8, 0x0c, 0x01, 0x20, -0xb0, 0x00, 0x01, 0x20, 0x20, 0x50, 0x03, 0x40, 0x40, 0x50, 0x03, 0x40, 0x00, 0x50, 0x03, 0x40, -0x40, 0x51, 0x03, 0x40, 0xff, 0x01, 0x00, 0x00, 0x28, 0x0d, 0x01, 0x20, 0x80, 0x11, 0x03, 0x40, -0x80, 0x13, 0x03, 0x40, 0x00, 0x11, 0x03, 0x40, 0x00, 0x13, 0x03, 0x40, 0x20, 0x14, 0x03, 0x40, -0xa8, 0x0d, 0x01, 0x20, 0x40, 0x14, 0x03, 0x40, 0x0b, 0x0e, 0x01, 0x20, 0x68, 0x02, 0x01, 0x20, -0xa8, 0x0c, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, 0xf0, 0xb5, 0x57, 0x48, 0x83, 0xb0, 0x80, 0x7c, -0x01, 0x90, 0x56, 0x49, 0x00, 0x20, 0x08, 0x70, 0x55, 0x48, 0x41, 0x78, 0x55, 0x48, 0x00, 0x90, -0x3c, 0x29, 0x02, 0xd3, 0x00, 0x7e, 0x40, 0x06, 0x7e, 0xd4, 0x53, 0x48, 0xc0, 0x7e, 0x00, 0xf0, -0x61, 0xf9, 0x00, 0xf0, 0x7b, 0xfc, 0x04, 0xf0, 0x6d, 0xfd, 0x07, 0xf0, 0xa5, 0xfd, 0x00, 0xf0, -0x5b, 0xfc, 0x4e, 0x48, 0x01, 0x7e, 0x4e, 0x48, 0x01, 0x29, 0x7f, 0xd0, 0x00, 0x21, 0x01, 0x70, -0x20, 0x20, 0xfe, 0xf7, 0xe5, 0xfe, 0x01, 0x46, 0x90, 0x22, 0x4a, 0x48, 0xf9, 0xf7, 0xd4, 0xfc, -0x49, 0x48, 0x00, 0x24, 0x01, 0x7a, 0x25, 0x46, 0x26, 0x46, 0x00, 0x20, 0x00, 0x29, 0x1e, 0xd9, -0x44, 0x4b, 0x32, 0x46, 0x24, 0x27, 0x7a, 0x43, 0xd3, 0x18, 0x02, 0x93, 0x43, 0x4b, 0x44, 0x4f, -0xd3, 0x18, 0xd2, 0x19, 0x9e, 0x46, 0x94, 0x46, 0x43, 0x00, 0x02, 0x9a, 0x77, 0x46, 0xd2, 0x5a, -0xff, 0x5a, 0xd2, 0x1b, 0x12, 0xb2, 0x67, 0x46, 0xfa, 0x52, 0xa2, 0x42, 0x00, 0xdd, 0x14, 0x46, -0xaa, 0x42, 0x00, 0xda, 0x15, 0x46, 0x40, 0x1c, 0xc0, 0xb2, 0x81, 0x42, 0xec, 0xd8, 0x76, 0x1c, -0xf6, 0xb2, 0x04, 0x2e, 0xd9, 0xd3, 0x37, 0x48, 0x00, 0x7a, 0x80, 0x07, 0x07, 0xd5, 0x36, 0x48, -0x43, 0x7a, 0x02, 0x7a, 0x18, 0x06, 0x00, 0x14, 0x10, 0x43, 0xa8, 0x42, 0x1e, 0xda, 0x01, 0x98, -0x40, 0x10, 0xa0, 0x42, 0x1a, 0xdd, 0x00, 0x25, 0x00, 0x20, 0x00, 0x29, 0x12, 0xd9, 0x2b, 0x4b, -0x2a, 0x46, 0x24, 0x27, 0x2a, 0x4e, 0x7a, 0x43, 0xd3, 0x18, 0x92, 0x19, 0x94, 0x46, 0x42, 0x00, -0x66, 0x46, 0xb6, 0x5e, 0x9f, 0x5a, 0x76, 0x10, 0xbf, 0x19, 0x40, 0x1c, 0xc0, 0xb2, 0x9f, 0x52, -0x81, 0x42, 0xf4, 0xd8, 0x6d, 0x1c, 0xed, 0xb2, 0x04, 0x2d, 0xe5, 0xd3, 0x00, 0x98, 0x00, 0x7e, -0x40, 0x06, 0x03, 0xd5, 0x16, 0x49, 0x48, 0x78, 0x40, 0x1c, 0x48, 0x70, 0x1f, 0x48, 0x80, 0x7c, -0x00, 0x28, 0x0a, 0xd0, 0x1e, 0x48, 0x01, 0xe0, 0x1a, 0xe0, 0x0f, 0xe0, 0x00, 0x7d, 0x40, 0x06, -0x03, 0xd5, 0x03, 0x21, 0x00, 0x20, 0x07, 0xf0, 0x73, 0xfd, 0x01, 0x98, 0x84, 0x42, 0x0c, 0xdd, -0x0a, 0x48, 0x01, 0x21, 0x01, 0x70, 0x08, 0x46, 0x03, 0xb0, 0xf0, 0xbd, 0x01, 0x78, 0x00, 0x29, -0x00, 0xd1, 0x7d, 0xe7, 0x00, 0x21, 0x01, 0x70, 0x02, 0xe0, 0x04, 0x49, 0x00, 0x20, 0x08, 0x70, -0x00, 0x20, 0x03, 0xb0, 0xf0, 0xbd, 0x00, 0x00, 0x88, 0x0d, 0x01, 0x20, 0xc4, 0x00, 0x01, 0x20, -0xb0, 0x00, 0x01, 0x20, 0xe8, 0x0d, 0x01, 0x20, 0xe8, 0x0c, 0x01, 0x20, 0x28, 0x0d, 0x01, 0x20, -0xdd, 0x00, 0x01, 0x20, 0xe4, 0x11, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0x74, 0x12, 0x01, 0x20, -0x04, 0x13, 0x01, 0x20, 0x08, 0x0e, 0x01, 0x20, 0x09, 0x0e, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, -0x48, 0x0d, 0x01, 0x20, 0xf8, 0xb5, 0x08, 0x20, 0xfe, 0xf7, 0x3a, 0xfe, 0x04, 0x46, 0x04, 0xf0, -0x89, 0xfd, 0x20, 0x46, 0xfb, 0xf7, 0x62, 0xf8, 0x2c, 0x48, 0x00, 0x90, 0x08, 0x20, 0xfe, 0xf7, -0x2f, 0xfe, 0x2b, 0x4e, 0x00, 0x22, 0x33, 0x7a, 0x00, 0x21, 0x00, 0x2b, 0x0c, 0xd9, 0x12, 0x23, -0x00, 0x9c, 0x53, 0x43, 0x1d, 0x19, 0x5f, 0x18, 0x6c, 0x5c, 0xbf, 0x00, 0xc4, 0x51, 0x49, 0x1c, -0x34, 0x7a, 0xc9, 0xb2, 0x8c, 0x42, 0xf6, 0xd8, 0x52, 0x1c, 0xd2, 0xb2, 0x04, 0x2a, 0xea, 0xd3, -0x20, 0x4c, 0x61, 0x7a, 0xa0, 0x7a, 0xfd, 0xf7, 0x9f, 0xfe, 0x1f, 0x49, 0x08, 0x7e, 0x02, 0x09, -0x1e, 0x48, 0x12, 0x01, 0x03, 0x7d, 0x9b, 0x06, 0x1b, 0x0f, 0x1a, 0x43, 0x0a, 0x76, 0x08, 0x22, -0x8a, 0x76, 0x1b, 0x4a, 0x13, 0x7d, 0x01, 0x25, 0x2b, 0x43, 0x13, 0x75, 0xff, 0x23, 0x13, 0x76, -0x93, 0x76, 0x18, 0x4a, 0x95, 0x72, 0x18, 0x4e, 0x03, 0x25, 0x35, 0x75, 0xd3, 0x83, 0x10, 0x22, -0x0a, 0x75, 0xf3, 0x22, 0x8a, 0x75, 0x15, 0x4a, 0xef, 0x21, 0x11, 0x74, 0x14, 0x4a, 0x11, 0x74, -0x14, 0x4a, 0xf0, 0x21, 0x11, 0x70, 0x14, 0x4a, 0x11, 0x70, 0x14, 0x49, 0x00, 0x22, 0x0a, 0x74, -0x0d, 0x75, 0x81, 0x78, 0x12, 0x48, 0x01, 0x70, 0x01, 0x79, 0x23, 0x7c, 0x49, 0x09, 0x49, 0x01, -0x19, 0x43, 0x01, 0x71, 0x0f, 0x48, 0xc2, 0x80, 0xf8, 0xbd, 0x00, 0x00, 0x30, 0x0e, 0x01, 0x20, -0xa8, 0x0c, 0x01, 0x20, 0xc8, 0x0c, 0x01, 0x20, 0x20, 0x50, 0x03, 0x40, 0x48, 0x0d, 0x01, 0x20, -0x40, 0x50, 0x03, 0x40, 0x00, 0x50, 0x03, 0x40, 0x40, 0x51, 0x03, 0x40, 0x80, 0x11, 0x03, 0x40, -0x80, 0x13, 0x03, 0x40, 0x00, 0x11, 0x03, 0x40, 0x00, 0x13, 0x03, 0x40, 0x20, 0x14, 0x03, 0x40, -0x40, 0x14, 0x03, 0x40, 0xc4, 0x00, 0x01, 0x20, 0x10, 0xb4, 0x0f, 0x4a, 0x04, 0x46, 0x00, 0x21, -0x53, 0x5c, 0x83, 0x42, 0x11, 0xd1, 0x0d, 0x4b, 0x18, 0x78, 0x02, 0x46, 0x58, 0x78, 0x00, 0x02, -0x02, 0x43, 0x98, 0x78, 0x00, 0x04, 0x02, 0x43, 0xd8, 0x78, 0x00, 0x06, 0x02, 0x43, 0x01, 0x20, -0x88, 0x40, 0x02, 0x42, 0x05, 0xd1, 0x00, 0x24, 0x03, 0xe0, 0x49, 0x1c, 0xc9, 0xb2, 0x20, 0x29, -0xe6, 0xd3, 0x20, 0x46, 0x10, 0xbc, 0x70, 0x47, 0x7c, 0xee, 0x00, 0x00, 0x94, 0x03, 0x01, 0x20, -0x70, 0x47, 0x00, 0x00, 0x70, 0xb5, 0x21, 0x4d, 0x04, 0x46, 0x28, 0x78, 0x04, 0x28, 0x18, 0xd0, -0x1f, 0x4a, 0x20, 0x4e, 0x10, 0x7d, 0x40, 0x06, 0x14, 0xd5, 0x21, 0x46, 0x30, 0x46, 0xf9, 0xf7, -0xe5, 0xfb, 0x44, 0x1e, 0x60, 0x1c, 0x07, 0xd0, 0x1b, 0x4e, 0x30, 0x46, 0x07, 0xf0, 0x64, 0xfe, -0x07, 0xf0, 0x9e, 0xfc, 0x64, 0x1e, 0xf8, 0xd2, 0x28, 0x78, 0x04, 0x28, 0x01, 0xd0, 0xfa, 0xf7, -0xa2, 0xf9, 0x70, 0xbd, 0x01, 0x20, 0x01, 0xf0, 0x3d, 0xfa, 0x21, 0x46, 0x30, 0x46, 0xf9, 0xf7, -0xcd, 0xfb, 0x12, 0x4c, 0xa0, 0x71, 0x61, 0x78, 0x01, 0x20, 0x01, 0x43, 0x61, 0x70, 0x20, 0x70, -0x30, 0x46, 0x07, 0xf0, 0x49, 0xfe, 0x10, 0x20, 0x20, 0x70, 0x00, 0x20, 0x01, 0xf0, 0x2a, 0xfa, -0x60, 0x78, 0x40, 0x08, 0x40, 0x00, 0x60, 0x70, 0x28, 0x78, 0x04, 0x28, 0x01, 0xd0, 0xfa, 0xf7, -0x82, 0xf9, 0x07, 0x49, 0x00, 0x20, 0x08, 0x70, 0x70, 0xbd, 0x00, 0x00, 0x4c, 0x03, 0x01, 0x20, -0x48, 0x0d, 0x01, 0x20, 0xe8, 0x03, 0x00, 0x00, 0x88, 0x13, 0x00, 0x00, 0x20, 0x00, 0x03, 0x40, -0x00, 0x00, 0x01, 0x20, 0x10, 0xb5, 0x06, 0x48, 0x41, 0x79, 0x00, 0x29, 0x05, 0xd0, 0x40, 0x79, -0x01, 0x28, 0x01, 0xd1, 0xff, 0xf7, 0x5a, 0xfd, 0x10, 0xbd, 0xff, 0xf7, 0xfb, 0xfe, 0x10, 0xbd, -0x8c, 0x03, 0x01, 0x20, 0x10, 0xb5, 0x0a, 0x20, 0xff, 0xf7, 0x9c, 0xff, 0x1f, 0x4c, 0x60, 0x79, -0x00, 0x28, 0x03, 0xd0, 0x60, 0x79, 0x01, 0x28, 0x03, 0xd0, 0x04, 0xe0, 0x00, 0xf0, 0xae, 0xfa, -0x01, 0xe0, 0xfd, 0xf7, 0xe5, 0xfc, 0x04, 0xf0, 0x9d, 0xfb, 0x07, 0xf0, 0xd5, 0xfb, 0x60, 0x79, -0x00, 0x28, 0x03, 0xd0, 0x60, 0x79, 0x01, 0x28, 0x03, 0xd0, 0x04, 0xe0, 0x00, 0xf0, 0x84, 0xfa, -0x01, 0xe0, 0xfd, 0xf7, 0xbb, 0xfc, 0x12, 0x48, 0x82, 0x7c, 0x12, 0x49, 0x0b, 0x7a, 0x10, 0x21, -0x99, 0x40, 0x8a, 0x43, 0x82, 0x74, 0x60, 0x79, 0x00, 0x28, 0x15, 0xd1, 0x20, 0x20, 0xfe, 0xf7, -0x07, 0xfd, 0x01, 0x46, 0x90, 0x22, 0x0c, 0x48, 0xf9, 0xf7, 0xf6, 0xfa, 0x01, 0x20, 0xfe, 0xf7, -0xff, 0xfc, 0x04, 0x46, 0x3f, 0x21, 0x09, 0x01, 0x90, 0x30, 0xf9, 0xf7, 0x53, 0xfb, 0x90, 0x22, -0x05, 0x49, 0x20, 0x46, 0xf9, 0xf7, 0xe8, 0xfa, 0x10, 0xbd, 0x00, 0x00, 0x8c, 0x03, 0x01, 0x20, -0x00, 0x50, 0x03, 0x40, 0x6c, 0x03, 0x01, 0x20, 0xe4, 0x11, 0x01, 0x20, 0x70, 0x47, 0x00, 0x00, -0xf8, 0xb5, 0x26, 0x4d, 0x28, 0x68, 0x80, 0x08, 0x80, 0x00, 0x28, 0x60, 0x24, 0x48, 0xaf, 0x14, -0x07, 0x60, 0xfe, 0xf7, 0x65, 0xfd, 0x23, 0x4c, 0x00, 0x28, 0x05, 0xd0, 0x60, 0x7b, 0x00, 0x28, -0x02, 0xd1, 0xa0, 0x7e, 0x00, 0x28, 0x37, 0xd0, 0x04, 0xf0, 0x24, 0xfc, 0xfa, 0xf7, 0xfa, 0xf8, -0xfe, 0xf7, 0xc2, 0xff, 0x1c, 0x4a, 0x08, 0x20, 0xd0, 0x70, 0x00, 0x26, 0x96, 0x80, 0x51, 0x78, -0xc9, 0x08, 0xc9, 0x00, 0x01, 0x43, 0x51, 0x70, 0x18, 0x49, 0x90, 0x20, 0x08, 0x73, 0x18, 0x4b, -0x58, 0x78, 0x80, 0x21, 0x08, 0x43, 0x58, 0x70, 0x01, 0x20, 0x10, 0x70, 0x64, 0x21, 0x00, 0x20, -0x00, 0xbf, 0x40, 0x1c, 0x88, 0x42, 0xfb, 0xd3, 0x50, 0x78, 0xf7, 0x21, 0x08, 0x40, 0x50, 0x70, -0x10, 0x20, 0x10, 0x70, 0x0f, 0x48, 0x46, 0x71, 0xa6, 0x76, 0xfa, 0xf7, 0xd4, 0xf8, 0xfe, 0xf7, -0xc3, 0xff, 0x28, 0x68, 0x03, 0x21, 0x08, 0x43, 0x28, 0x60, 0x0b, 0x48, 0x07, 0x60, 0xae, 0x60, -0x0a, 0x48, 0x68, 0x60, 0x04, 0xf0, 0x16, 0xfb, 0xf8, 0xbd, 0x00, 0x00, 0x00, 0x20, 0x03, 0x40, -0x80, 0xe1, 0x00, 0xe0, 0x6c, 0x03, 0x01, 0x20, 0x20, 0x00, 0x03, 0x40, 0x20, 0x80, 0x03, 0x40, -0x00, 0x80, 0x03, 0x40, 0x4c, 0x03, 0x01, 0x20, 0x00, 0xe1, 0x00, 0xe0, 0xa0, 0x86, 0x01, 0x00, -0x10, 0xb5, 0x0b, 0x49, 0x00, 0x20, 0x08, 0x81, 0x48, 0x81, 0x88, 0x81, 0x09, 0x49, 0x01, 0x22, -0x0a, 0x70, 0x09, 0x4a, 0x10, 0x70, 0x48, 0x70, 0x88, 0x70, 0x08, 0x71, 0xe4, 0x21, 0x07, 0x48, -0xf9, 0xf7, 0xd2, 0xfa, 0xfc, 0xf7, 0x14, 0xfd, 0x01, 0xf0, 0x7a, 0xfa, 0x10, 0xbd, 0x00, 0x00, -0x10, 0x00, 0x01, 0x20, 0x18, 0x00, 0x01, 0x20, 0x88, 0x04, 0x01, 0x20, 0x68, 0x02, 0x01, 0x20, -0x10, 0xb5, 0x01, 0x20, 0x00, 0xf0, 0x06, 0xf8, 0x10, 0xbd, 0x10, 0xb5, 0x02, 0x20, 0x00, 0xf0, -0x01, 0xf8, 0x10, 0xbd, 0x70, 0xb5, 0x04, 0x46, 0x19, 0x49, 0x02, 0x20, 0x19, 0x4d, 0x01, 0x2c, -0x15, 0xd0, 0x02, 0x2c, 0x2a, 0xd1, 0x08, 0x70, 0x17, 0x4e, 0xe8, 0x70, 0x30, 0x7e, 0x80, 0x07, -0x24, 0xd0, 0x31, 0x7d, 0xa8, 0x78, 0xea, 0x78, 0x90, 0x42, 0x0d, 0xd2, 0x00, 0x28, 0x09, 0xd0, -0x2a, 0x78, 0x12, 0x02, 0x51, 0x18, 0x29, 0x80, 0x40, 0x1c, 0xa8, 0x70, 0x13, 0xe0, 0x01, 0x22, -0x0a, 0x70, 0xe9, 0xe7, 0x29, 0x80, 0xf7, 0xe7, 0x01, 0x2c, 0x02, 0xd0, 0x02, 0x2c, 0x04, 0xd0, -0x06, 0xe0, 0x28, 0x88, 0x07, 0xf0, 0x6e, 0xfb, 0x02, 0xe0, 0x28, 0x88, 0x07, 0xf0, 0x66, 0xfb, -0x28, 0x88, 0x40, 0x1c, 0x28, 0x80, 0x30, 0x7e, 0x80, 0x07, 0xda, 0xd1, 0x70, 0xbd, 0x00, 0x00, -0x18, 0x00, 0x01, 0x20, 0x1e, 0x00, 0x01, 0x20, 0x00, 0x70, 0x03, 0x40, 0x10, 0xb5, 0x05, 0x4c, -0x20, 0x88, 0x03, 0xf0, 0x45, 0xfa, 0x04, 0x49, 0x08, 0x74, 0x20, 0x88, 0x40, 0x1c, 0x20, 0x80, -0x10, 0xbd, 0x00, 0x00, 0x1e, 0x00, 0x01, 0x20, 0x00, 0x70, 0x03, 0x40, 0x10, 0xb5, 0x05, 0x4c, -0x20, 0x88, 0x03, 0xf0, 0x33, 0xfc, 0x04, 0x49, 0x08, 0x74, 0x20, 0x88, 0x40, 0x1c, 0x20, 0x80, -0x10, 0xbd, 0x00, 0x00, 0x1e, 0x00, 0x01, 0x20, 0x00, 0x70, 0x03, 0x40, 0x10, 0xb4, 0xff, 0x21, -0x15, 0x48, 0x79, 0x31, 0x01, 0x80, 0xff, 0x21, 0x49, 0x31, 0x81, 0x80, 0x13, 0x49, 0x01, 0x22, -0x4a, 0x76, 0x4a, 0x77, 0x0b, 0x78, 0xfb, 0x24, 0x23, 0x40, 0x0b, 0x70, 0x10, 0x4b, 0x83, 0x81, -0x03, 0x23, 0x83, 0x73, 0x0f, 0x48, 0x00, 0x23, 0x02, 0x60, 0x0f, 0x4a, 0x02, 0x24, 0x13, 0x80, -0xd4, 0x70, 0x93, 0x70, 0x13, 0x71, 0x04, 0x60, 0x04, 0x22, 0x02, 0x60, 0x08, 0x22, 0x02, 0x60, -0x10, 0x22, 0x02, 0x60, 0x20, 0x22, 0x02, 0x60, 0x40, 0x22, 0x02, 0x60, 0x80, 0x22, 0x02, 0x60, -0x0f, 0x20, 0x48, 0x70, 0x10, 0xbc, 0x70, 0x47, 0x20, 0x70, 0x03, 0x40, 0x00, 0x70, 0x03, 0x40, -0x4f, 0x12, 0x00, 0x00, 0x00, 0xe1, 0x00, 0xe0, 0x1e, 0x00, 0x01, 0x20, 0x08, 0x4a, 0x01, 0x20, -0x10, 0x71, 0x08, 0x49, 0x00, 0x20, 0x0b, 0x79, 0x00, 0x2b, 0x02, 0xd0, 0x06, 0x4b, 0x58, 0x77, -0x08, 0x71, 0x88, 0x70, 0x51, 0x78, 0x00, 0x29, 0x00, 0xd0, 0x50, 0x70, 0x70, 0x47, 0x00, 0x00, -0x18, 0x00, 0x01, 0x20, 0x1e, 0x00, 0x01, 0x20, 0x00, 0x70, 0x03, 0x40, 0x70, 0xb5, 0x06, 0x48, -0x00, 0x25, 0x05, 0x71, 0x05, 0x4c, 0x20, 0x7e, 0x80, 0x07, 0x02, 0xd0, 0x01, 0x20, 0xff, 0xf7, -0x49, 0xff, 0x65, 0x77, 0x70, 0xbd, 0x00, 0x00, 0x18, 0x00, 0x01, 0x20, 0x00, 0x70, 0x03, 0x40, -0x70, 0xb5, 0x06, 0x48, 0x00, 0x25, 0x05, 0x71, 0x05, 0x4c, 0x20, 0x7e, 0x80, 0x07, 0x02, 0xd0, -0x02, 0x20, 0xff, 0xf7, 0x37, 0xff, 0x65, 0x77, 0x70, 0xbd, 0x00, 0x00, 0x18, 0x00, 0x01, 0x20, -0x00, 0x70, 0x03, 0x40, 0x00, 0xb5, 0x06, 0x48, 0x01, 0x7a, 0xef, 0x22, 0x11, 0x40, 0x01, 0x72, -0x01, 0x7a, 0x10, 0x22, 0x11, 0x43, 0x01, 0x72, 0xff, 0xf7, 0x80, 0xff, 0x00, 0xbd, 0x00, 0x00, -0x00, 0x00, 0x03, 0x40, 0x25, 0x48, 0x00, 0x22, 0x40, 0x7e, 0x80, 0x06, 0x45, 0xd5, 0xf0, 0xb4, -0x23, 0x4f, 0x00, 0x21, 0x24, 0x23, 0x4b, 0x43, 0xdc, 0x19, 0x28, 0x23, 0x21, 0x4d, 0x01, 0x20, -0x4b, 0x43, 0x5e, 0x19, 0x43, 0x00, 0xf5, 0x5e, 0xe3, 0x5e, 0xeb, 0x1a, 0x00, 0xd5, 0x5b, 0x42, -0x9b, 0xb2, 0x93, 0x42, 0x00, 0xd9, 0x1a, 0x46, 0x40, 0x1c, 0xc0, 0xb2, 0x13, 0x28, 0xf1, 0xd3, -0x49, 0x1c, 0xc9, 0xb2, 0x20, 0x29, 0xe5, 0xd3, 0xd0, 0x04, 0x00, 0x0e, 0x0e, 0x28, 0x00, 0xd9, -0x0e, 0x20, 0x15, 0x49, 0x0e, 0x5c, 0x80, 0x20, 0x80, 0x1b, 0xc0, 0xb2, 0x84, 0x46, 0x00, 0x23, -0x0f, 0x49, 0x24, 0x24, 0x5c, 0x43, 0x65, 0x18, 0x0e, 0x4a, 0x28, 0x21, 0x01, 0x20, 0x59, 0x43, -0x8c, 0x18, 0x41, 0x00, 0x62, 0x5e, 0x67, 0x46, 0x7a, 0x43, 0x6f, 0x5e, 0x40, 0x1c, 0x77, 0x43, -0xd2, 0x19, 0xd2, 0x11, 0x62, 0x52, 0xc0, 0xb2, 0x6a, 0x52, 0x13, 0x28, 0xf1, 0xd3, 0x5b, 0x1c, -0xdb, 0xb2, 0x20, 0x2b, 0xe4, 0xd3, 0xf0, 0xbc, 0x70, 0x47, 0x70, 0x47, 0xa8, 0x0c, 0x01, 0x20, -0x94, 0x13, 0x01, 0x20, 0x00, 0x50, 0x01, 0x20, 0x28, 0x02, 0x01, 0x20, 0xf8, 0xb5, 0x08, 0x20, -0xfe, 0xf7, 0x26, 0xfb, 0x04, 0x46, 0x04, 0xf0, 0x75, 0xfa, 0x20, 0x46, 0xfa, 0xf7, 0x4e, 0xfd, -0x37, 0x48, 0x00, 0x90, 0x08, 0x20, 0xfe, 0xf7, 0x1b, 0xfb, 0x36, 0x4c, 0x00, 0x22, 0x23, 0x7a, -0x00, 0x21, 0x00, 0x2b, 0x0c, 0xd9, 0x12, 0x23, 0x00, 0x9d, 0x53, 0x43, 0x5e, 0x19, 0x5f, 0x18, -0x75, 0x5c, 0xbf, 0x00, 0xc5, 0x51, 0x49, 0x1c, 0x25, 0x7a, 0xc9, 0xb2, 0x8d, 0x42, 0xf6, 0xd8, -0x52, 0x1c, 0xd2, 0xb2, 0x04, 0x2a, 0xea, 0xd3, 0x2b, 0x4d, 0x69, 0x7b, 0xa8, 0x7b, 0xfd, 0xf7, -0x8b, 0xfb, 0x2a, 0x49, 0x0a, 0x7d, 0x2a, 0x48, 0x02, 0x70, 0x0a, 0x7e, 0x42, 0x70, 0x8a, 0x7e, -0x82, 0x70, 0x28, 0x4a, 0x13, 0x78, 0xc3, 0x70, 0x13, 0x79, 0x03, 0x71, 0x26, 0x4b, 0x1b, 0x78, -0x43, 0x71, 0x26, 0x4b, 0x1b, 0x78, 0x26, 0x4e, 0x83, 0x71, 0xf3, 0x8b, 0x03, 0x81, 0xb3, 0x88, -0x24, 0x4f, 0x43, 0x81, 0x3b, 0x7c, 0x03, 0x73, 0xbb, 0x68, 0x03, 0x61, 0x10, 0x20, 0x08, 0x75, -0x21, 0x48, 0xc3, 0x7a, 0x0b, 0x76, 0x08, 0x23, 0x8b, 0x76, 0x01, 0x7b, 0x11, 0x70, 0x11, 0x79, -0xeb, 0x7b, 0x49, 0x09, 0x49, 0x01, 0xdb, 0x06, 0xdb, 0x0e, 0x19, 0x43, 0x11, 0x71, 0x16, 0x4a, -0xf0, 0x21, 0x11, 0x70, 0x15, 0x4a, 0x11, 0x70, 0x18, 0x49, 0xf1, 0x83, 0x21, 0x7d, 0x02, 0x29, -0x03, 0xd1, 0x00, 0x21, 0xb9, 0x60, 0x88, 0x21, 0x39, 0x74, 0x40, 0x7b, 0xb0, 0x80, 0xf8, 0x73, -0x13, 0x49, 0xff, 0x20, 0x08, 0x76, 0x88, 0x76, 0x12, 0x49, 0x01, 0x20, 0x08, 0x70, 0xb0, 0x7d, -0x10, 0x21, 0x08, 0x43, 0xb0, 0x75, 0xfc, 0xf7, 0x8d, 0xff, 0x04, 0xf0, 0x2b, 0xf9, 0xf8, 0xbd, -0x78, 0x0e, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0xc8, 0x0c, 0x01, 0x20, 0x20, 0x50, 0x03, 0x40, -0xa8, 0x2e, 0x01, 0x20, 0x40, 0x14, 0x03, 0x40, 0x00, 0x11, 0x03, 0x40, 0x00, 0x13, 0x03, 0x40, -0x00, 0x50, 0x03, 0x40, 0x80, 0x51, 0x03, 0x40, 0xe8, 0x0c, 0x01, 0x20, 0xff, 0x01, 0x00, 0x00, -0x40, 0x51, 0x03, 0x40, 0x60, 0x51, 0x03, 0x40, 0x10, 0xb5, 0x09, 0x48, 0x00, 0x7f, 0x12, 0x28, -0x0a, 0xd0, 0xaa, 0x21, 0x00, 0x20, 0x04, 0xf0, 0x25, 0xfd, 0x3c, 0x21, 0x05, 0x48, 0xfc, 0xf7, -0x6e, 0xfd, 0x00, 0xf0, 0x09, 0xf8, 0x10, 0xbd, 0xfa, 0xf7, 0x44, 0xff, 0x10, 0xbd, 0x00, 0x00, -0x28, 0x0d, 0x01, 0x20, 0x85, 0xd2, 0x03, 0x40, 0x70, 0x47, 0x00, 0x00, 0x10, 0xb5, 0x09, 0x48, -0x00, 0x7f, 0x12, 0x28, 0x0a, 0xd0, 0xaa, 0x21, 0x00, 0x20, 0x04, 0xf0, 0x0b, 0xfd, 0x3c, 0x21, -0x05, 0x48, 0xfc, 0xf7, 0x54, 0xfd, 0x00, 0xf0, 0x09, 0xf8, 0x10, 0xbd, 0xfa, 0xf7, 0x9a, 0xff, -0x10, 0xbd, 0x00, 0x00, 0x28, 0x0d, 0x01, 0x20, 0x85, 0xd2, 0x03, 0x40, 0x70, 0x47, 0x00, 0x00, -0xf1, 0xb5, 0x94, 0xb0, 0x01, 0x20, 0xba, 0x49, 0x12, 0x90, 0x08, 0x89, 0xff, 0x38, 0x01, 0x38, -0x80, 0xb2, 0x06, 0x90, 0x4a, 0x89, 0xb7, 0x48, 0x0d, 0x90, 0x43, 0x7e, 0x04, 0x7e, 0x18, 0x02, -0x20, 0x43, 0x10, 0x1a, 0x80, 0xb2, 0x05, 0x90, 0x00, 0x20, 0x08, 0x90, 0x14, 0x98, 0x00, 0x78, -0x00, 0x28, 0x7d, 0xd9, 0xb0, 0x4d, 0x28, 0x46, 0xc0, 0x30, 0x11, 0x90, 0xaf, 0x48, 0x10, 0x90, -0x06, 0x98, 0xff, 0x38, 0x01, 0x38, 0x0f, 0x90, 0x28, 0x46, 0x82, 0x30, 0x0c, 0x90, 0xbe, 0x30, -0x0b, 0x90, 0xc0, 0x38, 0x07, 0x90, 0x40, 0x38, 0x09, 0x90, 0x1e, 0x38, 0xa0, 0x35, 0x0e, 0x90, -0x08, 0x98, 0x0c, 0x21, 0x48, 0x43, 0x14, 0x99, 0x44, 0x18, 0xa1, 0x78, 0xa4, 0x48, 0x01, 0x91, -0x41, 0x18, 0x09, 0x20, 0x00, 0x02, 0x08, 0x18, 0x80, 0x7d, 0x04, 0x28, 0x1d, 0xd0, 0x00, 0x28, -0x1b, 0xd0, 0x12, 0x98, 0x00, 0x28, 0x6e, 0xd0, 0xa1, 0x88, 0xff, 0x22, 0x01, 0x32, 0x91, 0x42, -0x1b, 0xd8, 0x28, 0x7b, 0x10, 0x1a, 0x81, 0x42, 0x00, 0xd2, 0xa0, 0x80, 0xa0, 0x88, 0x29, 0x7b, -0x42, 0x18, 0x93, 0x48, 0xff, 0x3a, 0x80, 0x89, 0x01, 0x3a, 0x50, 0x43, 0x00, 0x29, 0x01, 0xd0, -0xf9, 0xf7, 0x64, 0xf8, 0x80, 0xb2, 0x00, 0x90, 0x35, 0xe0, 0x11, 0x98, 0x00, 0x7c, 0x00, 0x28, -0x6f, 0xd0, 0x10, 0x99, 0x00, 0x20, 0x88, 0x73, 0x05, 0xe1, 0x06, 0x98, 0x81, 0x42, 0x1a, 0xd9, -0x6a, 0x7b, 0x10, 0x18, 0x81, 0x42, 0x00, 0xd9, 0xa0, 0x80, 0x69, 0x7b, 0x06, 0x98, 0xa2, 0x88, -0x08, 0x18, 0x82, 0x1a, 0x07, 0x98, 0x43, 0x7c, 0x00, 0x7c, 0x1e, 0x02, 0x06, 0x43, 0x80, 0x48, -0xc0, 0x89, 0x30, 0x1a, 0x50, 0x43, 0x00, 0x29, 0x01, 0xd0, 0xf9, 0xf7, 0x3f, 0xf8, 0x30, 0x1a, -0x80, 0xb2, 0x00, 0x90, 0x0f, 0xe0, 0x7a, 0x48, 0xff, 0x39, 0xc3, 0x89, 0x86, 0x89, 0x01, 0x39, -0x98, 0x1b, 0x48, 0x43, 0x06, 0x99, 0x91, 0x42, 0x02, 0xd9, 0x0f, 0x99, 0xf9, 0xf7, 0x2e, 0xf8, -0x30, 0x18, 0x80, 0xb2, 0x00, 0x90, 0x0d, 0x99, 0xe0, 0x88, 0x4a, 0x7e, 0x0b, 0x7e, 0x00, 0xe0, -0xdb, 0xe0, 0x11, 0x02, 0x19, 0x43, 0x88, 0x42, 0x16, 0xd2, 0xaa, 0x7b, 0x89, 0x1a, 0x81, 0x42, -0x00, 0xdd, 0xe1, 0x80, 0xe0, 0x88, 0xa9, 0x7b, 0x42, 0x18, 0x0d, 0x98, 0x43, 0x7e, 0x06, 0x7e, -0x18, 0x02, 0x30, 0x43, 0x12, 0x1a, 0x66, 0x48, 0x00, 0x8a, 0x50, 0x43, 0x00, 0x29, 0x2e, 0xd0, -0xf9, 0xf7, 0x0c, 0xf8, 0x2b, 0xe0, 0x2b, 0xe0, 0x05, 0x9a, 0x90, 0x42, 0x1a, 0xd9, 0xea, 0x7b, -0x05, 0x99, 0x51, 0x18, 0x88, 0x42, 0x00, 0xd9, 0xe1, 0x80, 0xe9, 0x7b, 0x05, 0x98, 0xe2, 0x88, -0x08, 0x18, 0x82, 0x1a, 0x0c, 0x98, 0x43, 0x7c, 0x00, 0x7c, 0x1e, 0x02, 0x06, 0x43, 0x58, 0x48, -0x40, 0x8a, 0x30, 0x1a, 0x50, 0x43, 0x00, 0x29, 0x01, 0xd0, 0xf8, 0xf7, 0xef, 0xff, 0x30, 0x1a, -0x0d, 0xe0, 0x98, 0xe0, 0x42, 0x1a, 0x52, 0x48, 0x43, 0x8a, 0x06, 0x8a, 0x98, 0x1b, 0x50, 0x43, -0x05, 0x9a, 0x91, 0x42, 0x02, 0xd2, 0x51, 0x1a, 0xf8, 0xf7, 0xe0, 0xff, 0x30, 0x18, 0x87, 0xb2, -0x0b, 0x98, 0x00, 0x7e, 0x01, 0x07, 0x06, 0xd5, 0x0c, 0x99, 0x4a, 0x7c, 0x0b, 0x7c, 0x11, 0x02, -0x19, 0x43, 0xc9, 0x1b, 0x8f, 0xb2, 0x40, 0x07, 0x08, 0xd5, 0x07, 0x98, 0x41, 0x7c, 0x02, 0x7c, -0x08, 0x02, 0x00, 0x99, 0x10, 0x43, 0x40, 0x1a, 0x80, 0xb2, 0x00, 0x90, 0x07, 0x98, 0x00, 0x7d, -0x00, 0x28, 0x08, 0xd0, 0x01, 0x98, 0x14, 0x21, 0x48, 0x43, 0x42, 0x49, 0x40, 0x18, 0xc7, 0x80, -0x00, 0x99, 0x01, 0x81, 0x07, 0xe0, 0x01, 0x98, 0x14, 0x21, 0x48, 0x43, 0x3d, 0x49, 0x00, 0x9a, -0x40, 0x18, 0xc2, 0x80, 0x07, 0x81, 0x0b, 0x98, 0xc0, 0x7d, 0x40, 0x07, 0x51, 0xd5, 0x01, 0x98, -0x14, 0x21, 0x48, 0x43, 0x37, 0x49, 0x40, 0x18, 0x04, 0x90, 0x01, 0x89, 0x09, 0x98, 0x03, 0x91, -0x42, 0x78, 0x03, 0x78, 0x10, 0x02, 0x18, 0x43, 0x02, 0x90, 0x81, 0x42, 0x41, 0xd2, 0x04, 0x98, -0xc6, 0x88, 0x0e, 0x98, 0x41, 0x7f, 0x00, 0x7f, 0x09, 0x02, 0x01, 0x43, 0x8e, 0x42, 0x15, 0xd2, -0x09, 0x9a, 0x88, 0x1b, 0x92, 0x78, 0x50, 0x43, 0xf8, 0xf7, 0x90, 0xff, 0x03, 0x9a, 0x02, 0x99, -0x8a, 0x1a, 0x50, 0x43, 0xf8, 0xf7, 0x8a, 0xff, 0x86, 0x42, 0x03, 0xd3, 0x04, 0x99, 0x30, 0x1a, -0xc8, 0x80, 0x26, 0xe0, 0x04, 0x99, 0x00, 0x20, 0xc8, 0x80, 0x22, 0xe0, 0x07, 0x98, 0x42, 0x7c, -0x03, 0x7c, 0x10, 0x02, 0x18, 0x43, 0x0a, 0x90, 0x40, 0x1a, 0xb0, 0x42, 0x19, 0xda, 0x0a, 0x98, -0x72, 0x18, 0x10, 0x1a, 0x09, 0x9a, 0x92, 0x78, 0x50, 0x43, 0xf8, 0xf7, 0x6f, 0xff, 0x01, 0x46, -0x03, 0x9a, 0x02, 0x98, 0x80, 0x1a, 0x48, 0x43, 0x02, 0x99, 0xf8, 0xf7, 0x67, 0xff, 0x30, 0x18, -0x81, 0xb2, 0x04, 0x98, 0xc1, 0x80, 0x0a, 0x98, 0x40, 0x1e, 0x81, 0x42, 0x01, 0xdd, 0x04, 0x99, -0xc8, 0x80, 0x01, 0x99, 0x14, 0x20, 0x41, 0x43, 0x0e, 0x48, 0x08, 0x18, 0xa1, 0x89, 0x01, 0x83, -0x21, 0x89, 0x09, 0x11, 0x41, 0x74, 0x08, 0x98, 0x40, 0x1c, 0xc0, 0xb2, 0x08, 0x90, 0x14, 0x98, -0x01, 0x78, 0x08, 0x98, 0x81, 0x42, 0x00, 0xd9, 0xba, 0xe6, 0x15, 0xb0, 0xf0, 0xbd, 0x00, 0x00, -0x84, 0x2e, 0x01, 0x20, 0xa9, 0x0d, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0xa4, 0x2d, 0x01, 0x20, -0x44, 0x24, 0x01, 0x20, 0x68, 0x02, 0x01, 0x20, 0x02, 0x48, 0x01, 0x7a, 0xf7, 0x22, 0x11, 0x40, -0x01, 0x72, 0x70, 0x47, 0x00, 0x00, 0x03, 0x40, 0x10, 0xb5, 0x01, 0x20, 0xfe, 0xf7, 0xd0, 0xf8, -0x04, 0x46, 0x3f, 0x21, 0x09, 0x01, 0x90, 0x30, 0xf8, 0xf7, 0x24, 0xff, 0x90, 0x22, 0x02, 0x49, -0x20, 0x46, 0xf8, 0xf7, 0xb9, 0xfe, 0x10, 0xbd, 0xe4, 0x11, 0x01, 0x20, 0xf8, 0xb5, 0x17, 0xa0, -0x07, 0xf0, 0x8e, 0xfa, 0xfc, 0xf7, 0x0e, 0xfe, 0x17, 0x4e, 0x01, 0x20, 0x70, 0x71, 0x00, 0x20, -0x70, 0x70, 0x16, 0x4d, 0x05, 0x20, 0xe8, 0x77, 0xff, 0xf7, 0x88, 0xfd, 0xfa, 0xf7, 0x64, 0xf9, -0x30, 0x78, 0x05, 0x28, 0x16, 0xd1, 0x12, 0x4f, 0x10, 0x24, 0x06, 0xf0, 0xf7, 0xfe, 0x06, 0xf0, -0xc7, 0xff, 0xfe, 0xf7, 0x5d, 0xf9, 0xff, 0xf7, 0xcf, 0xff, 0x00, 0x21, 0x05, 0x20, 0x06, 0xf0, -0x9f, 0xff, 0xb8, 0x7c, 0x2a, 0x7a, 0x21, 0x46, 0x91, 0x40, 0x88, 0x43, 0xb8, 0x74, 0x30, 0x78, -0x05, 0x28, 0xea, 0xd0, 0x03, 0xf0, 0x60, 0xfa, 0xf8, 0xbd, 0x00, 0x00, 0x0a, 0x0a, 0x4d, 0x6e, -0x74, 0x44, 0x65, 0x62, 0x75, 0x67, 0x0a, 0x00, 0x4c, 0x03, 0x01, 0x20, 0x6c, 0x03, 0x01, 0x20, -0x00, 0x50, 0x03, 0x40, 0x70, 0xb5, 0x04, 0x46, 0x1e, 0x48, 0x41, 0x79, 0x1e, 0x4d, 0x00, 0x29, -0x06, 0xd0, 0x40, 0x79, 0x01, 0x28, 0x1c, 0xd1, 0x28, 0x78, 0x00, 0x28, 0x2d, 0xd1, 0x29, 0xe0, -0xfe, 0xf7, 0xfe, 0xf8, 0x00, 0x28, 0x03, 0xd1, 0x18, 0x48, 0x40, 0x7b, 0x00, 0x28, 0x10, 0xd0, -0x17, 0x49, 0xc8, 0x7e, 0x00, 0x28, 0x0c, 0xd0, 0x16, 0x48, 0x00, 0x22, 0x00, 0x7e, 0xc0, 0x07, -0x00, 0x28, 0x05, 0xd0, 0x28, 0x78, 0x00, 0x28, 0x02, 0xd1, 0xa8, 0x78, 0x00, 0x28, 0x01, 0xd0, -0x22, 0x80, 0x70, 0xbd, 0x20, 0x88, 0x40, 0x1c, 0x80, 0xb2, 0x20, 0x80, 0xc9, 0x7e, 0xc0, 0x08, -0x88, 0x42, 0x03, 0xd8, 0x0c, 0x48, 0x40, 0x7d, 0x00, 0x28, 0xf2, 0xd0, 0x22, 0x80, 0xfd, 0xf7, -0x57, 0xfc, 0x70, 0xbd, 0xa8, 0x78, 0x00, 0x28, 0xfb, 0xd0, 0x20, 0x46, 0xfc, 0xf7, 0xec, 0xff, -0x70, 0xbd, 0x00, 0x00, 0x4c, 0x03, 0x01, 0x20, 0x68, 0x02, 0x01, 0x20, 0x6c, 0x03, 0x01, 0x20, -0x68, 0x0d, 0x01, 0x20, 0xe8, 0x0d, 0x01, 0x20, 0x8c, 0x03, 0x01, 0x20, 0x40, 0x1c, 0xc0, 0xb2, -0x70, 0x47, 0x40, 0x1e, 0xc0, 0xb2, 0x70, 0x47, 0x72, 0xb6, 0x12, 0x48, 0x12, 0x49, 0x08, 0x60, -0x48, 0x60, 0x88, 0x60, 0xc8, 0x60, 0x08, 0x61, 0x48, 0x61, 0x88, 0x61, 0xc8, 0x61, 0x01, 0x22, -0x0e, 0x49, 0x52, 0x05, 0x0a, 0x60, 0x90, 0x12, 0x08, 0x60, 0x0d, 0x48, 0x00, 0x7d, 0x03, 0x28, -0x0b, 0xd0, 0xd3, 0x12, 0x0b, 0x60, 0x00, 0x28, 0x02, 0xd0, 0x02, 0x28, 0x02, 0xd0, 0x04, 0xe0, -0x0a, 0x60, 0x02, 0xe0, 0x01, 0x20, 0x80, 0x05, 0x08, 0x60, 0x01, 0x20, 0x00, 0x05, 0x08, 0x60, -0x62, 0xb6, 0x70, 0x47, 0x40, 0x40, 0x40, 0x40, 0x00, 0xe4, 0x00, 0xe0, 0x00, 0xe1, 0x00, 0xe0, -0xa8, 0x0c, 0x01, 0x20, 0x54, 0x48, 0x41, 0x7b, 0x00, 0x7b, 0x0b, 0x02, 0x03, 0x43, 0x53, 0x48, -0xc0, 0x7a, 0x01, 0x28, 0x77, 0xd1, 0xf0, 0xb5, 0x51, 0x4d, 0x87, 0xb0, 0x28, 0x7c, 0x00, 0x28, -0x6f, 0xd1, 0x51, 0x4c, 0x4f, 0x49, 0x60, 0x7a, 0x26, 0x7a, 0x4a, 0x8c, 0x00, 0x02, 0x30, 0x43, -0x82, 0x42, 0x04, 0xd9, 0x24, 0x22, 0x8a, 0x5e, 0x40, 0x42, 0x82, 0x42, 0x61, 0xdc, 0x04, 0x20, -0xfd, 0xf7, 0xe6, 0xff, 0x06, 0x90, 0x28, 0x7a, 0x69, 0x7a, 0x48, 0x4d, 0x48, 0x4a, 0x2e, 0x7c, -0x94, 0x46, 0x48, 0x4f, 0x00, 0x22, 0x00, 0x2e, 0x3a, 0xd0, 0x28, 0x24, 0x60, 0x43, 0xc0, 0x19, -0x49, 0x00, 0x40, 0x5e, 0x59, 0x08, 0x49, 0x42, 0x88, 0x42, 0x01, 0xdd, 0x2a, 0x74, 0x2a, 0x85, -0x41, 0x49, 0x01, 0x26, 0xc8, 0x79, 0x01, 0x28, 0x43, 0xd3, 0x18, 0x09, 0x05, 0x90, 0x40, 0x42, -0x04, 0x90, 0x98, 0x08, 0x03, 0x90, 0x58, 0x42, 0x86, 0x46, 0x40, 0x10, 0x02, 0x90, 0xd8, 0x08, -0x01, 0x90, 0x39, 0x49, 0x01, 0x20, 0x09, 0x7a, 0x01, 0x29, 0x53, 0xd3, 0x35, 0x4a, 0x31, 0x46, -0x28, 0x23, 0x59, 0x43, 0x8a, 0x18, 0x00, 0x92, 0x06, 0x9a, 0x34, 0x4b, 0x8a, 0x18, 0x14, 0x21, -0x71, 0x43, 0xcb, 0x18, 0x00, 0x9c, 0x41, 0x00, 0x64, 0x5e, 0x04, 0x9d, 0xac, 0x42, 0x39, 0xda, -0x67, 0x46, 0x1d, 0x5c, 0xff, 0x7a, 0xbd, 0x42, 0x21, 0xd2, 0x6d, 0x1c, 0x1d, 0x54, 0x33, 0xe0, -0x28, 0x23, 0x58, 0x43, 0xc0, 0x19, 0x49, 0x00, 0x41, 0x5e, 0x60, 0x7a, 0x23, 0x7a, 0x00, 0x02, -0x18, 0x43, 0x40, 0x42, 0x81, 0x42, 0x0f, 0xda, 0x28, 0x8d, 0x61, 0x46, 0x40, 0x1c, 0x80, 0xb2, -0x28, 0x85, 0xc9, 0x7a, 0x49, 0x00, 0x88, 0x42, 0x03, 0xd1, 0x01, 0x20, 0x20, 0x49, 0x28, 0x74, -0x48, 0x73, 0x07, 0xb0, 0xf0, 0xbd, 0x25, 0xe0, 0x2a, 0x85, 0x07, 0xb0, 0xf0, 0xbd, 0x74, 0x45, -0x04, 0xda, 0x57, 0x5a, 0x03, 0x9c, 0x3c, 0x1b, 0x54, 0x52, 0x0d, 0xe0, 0x02, 0x9f, 0xbc, 0x42, -0x57, 0x5a, 0x03, 0xda, 0x01, 0x9c, 0x3c, 0x1b, 0x54, 0x52, 0x05, 0xe0, 0x05, 0x9c, 0x3c, 0x1b, -0x54, 0x52, 0x01, 0xe0, 0x00, 0x21, 0x19, 0x54, 0x0f, 0x49, 0x40, 0x1c, 0x09, 0x7a, 0xc0, 0xb2, -0x81, 0x42, 0xb7, 0xd2, 0x0c, 0x48, 0x76, 0x1c, 0xc0, 0x79, 0xf6, 0xb2, 0xb0, 0x42, 0xa0, 0xd2, -0x07, 0xb0, 0xf0, 0xbd, 0x70, 0x47, 0x00, 0x00, 0x2a, 0x0d, 0x01, 0x20, 0x68, 0x0d, 0x01, 0x20, -0xa4, 0x2d, 0x01, 0x20, 0x84, 0x2d, 0x01, 0x20, 0x28, 0x0d, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, -0x48, 0x0d, 0x01, 0x20, 0x00, 0x50, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0x4c, 0x1c, 0x01, 0x20, -0x8c, 0x03, 0x01, 0x20, 0xf0, 0xb5, 0x8c, 0xb0, 0x00, 0x20, 0x00, 0x90, 0x4e, 0x4b, 0x01, 0x90, -0x02, 0x90, 0x03, 0x90, 0x04, 0x90, 0x05, 0x90, 0x18, 0x88, 0x01, 0x28, 0x75, 0xd9, 0x4b, 0x49, -0xff, 0x22, 0x58, 0x32, 0x52, 0x5c, 0x00, 0x20, 0xe0, 0x31, 0x0a, 0x92, 0xca, 0x7c, 0x07, 0x92, -0x0a, 0x7d, 0x06, 0x92, 0x4a, 0x7d, 0x89, 0x7d, 0x96, 0x46, 0x09, 0x91, 0x42, 0x4a, 0x41, 0x00, -0x89, 0x18, 0x02, 0x26, 0x03, 0x23, 0x8e, 0x57, 0xcb, 0x56, 0x41, 0x1c, 0x08, 0x91, 0x12, 0x88, -0xc9, 0xb2, 0x8a, 0x42, 0x6a, 0xd9, 0xc2, 0x00, 0x3b, 0x48, 0x10, 0x18, 0x84, 0x46, 0x20, 0x30, -0x6a, 0x46, 0x52, 0x5c, 0x00, 0x2a, 0x5b, 0xd1, 0x37, 0x4a, 0x4c, 0x00, 0xa4, 0x18, 0x02, 0x25, -0x65, 0x57, 0x03, 0x22, 0xa2, 0x56, 0x74, 0x1b, 0x64, 0xb2, 0x0b, 0x94, 0x9c, 0x1a, 0x0a, 0x9f, -0x64, 0xb2, 0xff, 0x07, 0x14, 0xd0, 0x07, 0x9f, 0xb7, 0x42, 0x11, 0xdb, 0xaf, 0x42, 0x0f, 0xdb, -0x06, 0x9f, 0x9f, 0x42, 0x0c, 0xdc, 0x9e, 0x45, 0x0a, 0xdb, 0x97, 0x42, 0x08, 0xdc, 0x96, 0x45, -0x06, 0xdb, 0x09, 0x9a, 0x00, 0x2c, 0x00, 0xda, 0x64, 0x42, 0xa2, 0x42, 0x07, 0xda, 0x37, 0xe0, -0x0b, 0x9a, 0x52, 0x1c, 0x02, 0x2a, 0x33, 0xd8, 0x64, 0x1c, 0x02, 0x2c, 0x30, 0xd8, 0x01, 0x22, -0x6c, 0x46, 0x62, 0x54, 0x20, 0x4a, 0xcc, 0x00, 0x87, 0x7b, 0xa2, 0x18, 0x0b, 0x92, 0x20, 0x32, -0x94, 0x7b, 0xa7, 0x42, 0x00, 0xd9, 0x84, 0x73, 0xc4, 0x7b, 0xd5, 0x7b, 0xac, 0x42, 0x06, 0xd9, -0x67, 0x1b, 0x02, 0x2f, 0x01, 0xda, 0xc5, 0x73, 0x01, 0xe0, 0x64, 0x1e, 0xc4, 0x73, 0x07, 0x7c, -0x14, 0x7c, 0xa7, 0x42, 0x00, 0xd2, 0x04, 0x74, 0x44, 0x7c, 0x52, 0x7c, 0x94, 0x42, 0x07, 0xd2, -0x17, 0x1b, 0x02, 0x2f, 0x02, 0xda, 0x42, 0x74, 0x02, 0xe0, 0x15, 0xe0, 0x64, 0x1c, 0x44, 0x74, -0x62, 0x46, 0x94, 0x8e, 0x0b, 0x9a, 0x92, 0x8e, 0x94, 0x42, 0x01, 0xd2, 0x64, 0x46, 0xa2, 0x86, -0x09, 0x4a, 0x49, 0x1c, 0x12, 0x88, 0xc9, 0xb2, 0x8a, 0x42, 0x99, 0xd8, 0x06, 0x49, 0x08, 0x98, -0x09, 0x88, 0xc0, 0xb2, 0x81, 0x42, 0x81, 0xd8, 0x05, 0x4a, 0x03, 0x49, 0x68, 0x46, 0x01, 0xf0, -0x63, 0xfb, 0x0c, 0xb0, 0xf0, 0xbd, 0x00, 0x00, 0x44, 0x24, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, -0x22, 0x25, 0x01, 0x20, 0x3e, 0x48, 0xc0, 0x7d, 0xc0, 0x06, 0x77, 0xd5, 0x3d, 0x48, 0x40, 0x78, -0x00, 0x28, 0x06, 0xd1, 0x3c, 0x48, 0x01, 0x7d, 0x02, 0x29, 0x02, 0xd1, 0x80, 0x7b, 0x01, 0x28, -0x6c, 0xd0, 0xf8, 0xb5, 0x01, 0x20, 0xfd, 0xf7, 0x8b, 0xfe, 0x4d, 0x21, 0x09, 0x01, 0x37, 0x4e, -0x45, 0x18, 0x30, 0x78, 0x01, 0x27, 0x00, 0x28, 0x38, 0xd0, 0x35, 0x48, 0x05, 0x71, 0x29, 0x0a, -0x41, 0x71, 0x29, 0x0c, 0x81, 0x71, 0x29, 0x0e, 0xc1, 0x71, 0x04, 0xf0, 0xef, 0xf8, 0x00, 0x24, -0x37, 0x46, 0xc0, 0x37, 0x72, 0x79, 0x00, 0x20, 0x92, 0x00, 0x92, 0x19, 0x10, 0x84, 0x01, 0x46, -0x4b, 0x00, 0xea, 0x5a, 0x9b, 0x19, 0x49, 0x1c, 0x10, 0x18, 0x89, 0xb2, 0x9a, 0x86, 0x48, 0x29, -0xf6, 0xd3, 0x48, 0x21, 0xf8, 0xf7, 0xc2, 0xfc, 0x02, 0x46, 0x00, 0x20, 0x01, 0x46, 0x4b, 0x00, -0x9b, 0x19, 0x9b, 0x8e, 0x9b, 0x1a, 0x00, 0xd5, 0x5b, 0x42, 0x49, 0x1c, 0x18, 0x18, 0x89, 0xb2, -0x48, 0x29, 0xf4, 0xd3, 0x48, 0x21, 0xf8, 0xf7, 0xb1, 0xfc, 0x71, 0x79, 0x80, 0xb2, 0x89, 0x00, -0x89, 0x19, 0x08, 0x84, 0xb1, 0x79, 0x00, 0x29, 0x04, 0xd0, 0x0a, 0xe0, 0x37, 0x70, 0x04, 0xf0, -0xbd, 0xf8, 0xf8, 0xbd, 0xb9, 0x7a, 0x00, 0x29, 0x03, 0xd1, 0x71, 0x79, 0x49, 0x00, 0x89, 0x19, -0xc8, 0x82, 0x70, 0x79, 0x40, 0x1c, 0xc0, 0xb2, 0x70, 0x71, 0x71, 0x78, 0x88, 0x42, 0x0f, 0xd1, -0xb0, 0x79, 0x40, 0x1c, 0x00, 0x06, 0x00, 0x0e, 0xb0, 0x71, 0x07, 0xd0, 0x01, 0x21, 0xb9, 0x72, -0x01, 0x28, 0x03, 0xd1, 0x00, 0x20, 0xb0, 0x71, 0xfd, 0xf7, 0x9e, 0xfc, 0x00, 0x20, 0x70, 0x71, -0x64, 0x1c, 0x24, 0x04, 0x24, 0x0c, 0xad, 0xd0, 0xf8, 0xbd, 0xff, 0xe7, 0x70, 0x47, 0x00, 0x00, -0xe8, 0x0d, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0xb8, 0x2d, 0x01, 0x20, -0x6c, 0x03, 0x01, 0x20, 0x4f, 0x48, 0xc0, 0x7d, 0xc0, 0x06, 0x7d, 0xd5, 0xf8, 0xb5, 0xcc, 0x21, -0x4d, 0x48, 0xf8, 0xf7, 0x69, 0xfc, 0x4d, 0x48, 0x4d, 0x49, 0x40, 0x79, 0x4d, 0x4a, 0xc0, 0x00, -0x40, 0x18, 0x00, 0x90, 0x10, 0x68, 0x00, 0x24, 0x47, 0x00, 0x4b, 0x48, 0x66, 0x00, 0x30, 0x18, -0x01, 0x7f, 0xc0, 0x7e, 0x0d, 0x02, 0x05, 0x43, 0x11, 0xd0, 0x00, 0x98, 0x81, 0x78, 0x38, 0x46, -0xf8, 0xf7, 0x54, 0xfc, 0x7d, 0x22, 0x29, 0x46, 0x12, 0x01, 0x51, 0x43, 0xf8, 0xf7, 0x4e, 0xfc, -0x3d, 0x49, 0x64, 0x1c, 0x71, 0x18, 0xe4, 0xb2, 0x88, 0x81, 0x05, 0x2c, 0xe5, 0xd3, 0x3a, 0x48, -0x3e, 0x49, 0x44, 0x70, 0x80, 0x20, 0x48, 0x76, 0x00, 0x21, 0x3d, 0x4f, 0xc9, 0x43, 0xb9, 0x63, -0x39, 0x4d, 0x3c, 0x4e, 0x29, 0x7d, 0x02, 0x29, 0x02, 0xd1, 0xa9, 0x7b, 0x01, 0x29, 0x00, 0xd1, -0x70, 0x75, 0x39, 0x48, 0x00, 0x79, 0x38, 0x70, 0xb8, 0x70, 0x38, 0x49, 0x08, 0x73, 0x48, 0x73, -0xaa, 0x20, 0x88, 0x74, 0xfd, 0xf7, 0x52, 0xff, 0x2f, 0x49, 0x8a, 0x7d, 0x49, 0x7d, 0x14, 0x02, -0x0c, 0x43, 0x7d, 0x21, 0x09, 0x01, 0x61, 0x43, 0xf8, 0xf7, 0x20, 0xfc, 0x80, 0xb2, 0x01, 0x04, -0x01, 0x43, 0x79, 0x60, 0x24, 0x4f, 0x00, 0x20, 0x7b, 0x78, 0x00, 0x2b, 0x0c, 0xd9, 0x41, 0x00, -0x49, 0x19, 0x0a, 0x7f, 0xc9, 0x7e, 0x12, 0x02, 0x0a, 0x43, 0xa2, 0x42, 0x00, 0xd1, 0xf8, 0x70, -0x40, 0x1c, 0xc0, 0xb2, 0x83, 0x42, 0xf2, 0xd8, 0x1f, 0x48, 0x01, 0x7e, 0xc2, 0x7d, 0x08, 0x02, -0x10, 0x43, 0x38, 0x71, 0x22, 0x48, 0x41, 0x7e, 0xf9, 0x71, 0x00, 0x7e, 0x38, 0x72, 0x21, 0x48, -0xc1, 0x79, 0x79, 0x72, 0x41, 0x7a, 0xb9, 0x72, 0x80, 0x7a, 0xf8, 0x72, 0x1e, 0x49, 0xc0, 0x20, -0x08, 0x71, 0x1e, 0x49, 0x08, 0x71, 0x00, 0xe0, 0x1a, 0xe0, 0x1d, 0x49, 0x01, 0x20, 0x08, 0x74, -0x1c, 0x49, 0x08, 0x74, 0x1c, 0x48, 0x42, 0x22, 0x02, 0x75, 0x1c, 0x49, 0x0a, 0x75, 0x1c, 0x4b, -0x55, 0x22, 0x1a, 0x76, 0x06, 0x22, 0x42, 0x71, 0x4a, 0x71, 0x28, 0x7d, 0x02, 0x28, 0x02, 0xd1, -0xa8, 0x7b, 0x01, 0x28, 0x02, 0xd0, 0x03, 0x20, 0x30, 0x75, 0xf8, 0xbd, 0x02, 0x20, 0xfb, 0xe7, -0x70, 0x47, 0x00, 0x00, 0xe8, 0x0d, 0x01, 0x20, 0xb8, 0x2d, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, -0x49, 0xee, 0x00, 0x00, 0x34, 0x00, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0x20, 0x50, 0x03, 0x40, -0x80, 0x50, 0x03, 0x40, 0xa0, 0x50, 0x03, 0x40, 0x08, 0x0e, 0x01, 0x20, 0x80, 0x51, 0x03, 0x40, -0x48, 0x0d, 0x01, 0x20, 0x68, 0x0d, 0x01, 0x20, 0x00, 0x11, 0x03, 0x40, 0x00, 0x13, 0x03, 0x40, -0xa0, 0x11, 0x03, 0x40, 0xa0, 0x13, 0x03, 0x40, 0x60, 0x11, 0x03, 0x40, 0x60, 0x13, 0x03, 0x40, -0x20, 0x14, 0x03, 0x40, 0x00, 0xb5, 0x0c, 0x48, 0xc0, 0x7d, 0xc0, 0x06, 0x03, 0xd5, 0x0b, 0x48, -0xc0, 0x7a, 0x00, 0x28, 0x01, 0xd0, 0x00, 0x20, 0x00, 0xbd, 0x05, 0xf0, 0xcf, 0xff, 0x08, 0x48, -0x00, 0x7d, 0x01, 0x28, 0x01, 0xd0, 0x02, 0x28, 0x04, 0xd1, 0x06, 0x48, 0x81, 0x7c, 0xcf, 0x22, -0x11, 0x40, 0x81, 0x74, 0x01, 0x20, 0x00, 0xbd, 0xe8, 0x0d, 0x01, 0x20, 0x78, 0x2e, 0x01, 0x20, -0xa8, 0x0c, 0x01, 0x20, 0x00, 0x50, 0x03, 0x40, 0xf0, 0xb4, 0x63, 0x4c, 0x20, 0x7a, 0x40, 0x08, -0x40, 0x00, 0x20, 0x72, 0x61, 0x48, 0x00, 0x27, 0x07, 0x74, 0x60, 0x49, 0x03, 0x20, 0x08, 0x75, -0x20, 0x7a, 0x40, 0x08, 0x40, 0x00, 0x20, 0x72, 0x5d, 0x48, 0x00, 0x79, 0xdd, 0x21, 0x08, 0x40, -0xc1, 0x21, 0x08, 0x43, 0x5a, 0x49, 0x08, 0x71, 0x5a, 0x48, 0x00, 0x79, 0xfd, 0x25, 0x28, 0x40, -0x01, 0x22, 0x58, 0x49, 0x10, 0x43, 0x08, 0x71, 0x55, 0x48, 0x00, 0x7b, 0x0f, 0x21, 0x08, 0x43, -0x53, 0x49, 0x08, 0x73, 0x53, 0x48, 0x00, 0x7b, 0x0f, 0x21, 0x08, 0x43, 0x51, 0x49, 0x08, 0x73, -0x51, 0x49, 0xe0, 0x20, 0x08, 0x70, 0x51, 0x49, 0x08, 0x70, 0x4f, 0x48, 0x01, 0x7c, 0xf7, 0x20, -0x4d, 0x4b, 0x01, 0x40, 0x19, 0x74, 0x4d, 0x49, 0x09, 0x7c, 0x01, 0x40, 0x4b, 0x48, 0x01, 0x74, -0x18, 0x7d, 0x00, 0x09, 0x00, 0x01, 0x18, 0x75, 0x48, 0x48, 0x00, 0x7d, 0x47, 0x49, 0x00, 0x09, -0x00, 0x01, 0x08, 0x75, 0x19, 0x7e, 0x40, 0x20, 0x01, 0x43, 0x19, 0x76, 0x43, 0x49, 0x09, 0x7e, -0x01, 0x43, 0x42, 0x48, 0x01, 0x76, 0x19, 0x7f, 0x05, 0x20, 0x01, 0x43, 0x19, 0x77, 0x3f, 0x49, -0x09, 0x7f, 0x01, 0x43, 0x3d, 0x48, 0x01, 0x77, 0x3d, 0x4b, 0x18, 0x78, 0x1f, 0x21, 0x08, 0x43, -0x18, 0x70, 0x3c, 0x4b, 0x18, 0x78, 0x08, 0x43, 0x18, 0x70, 0x34, 0x48, 0x00, 0x7e, 0x10, 0x26, -0x32, 0x4b, 0x30, 0x43, 0x18, 0x76, 0x38, 0x48, 0x03, 0x78, 0x0b, 0x43, 0x03, 0x70, 0x03, 0x79, -0x0b, 0x43, 0x03, 0x71, 0x35, 0x48, 0x02, 0x74, 0x35, 0x48, 0x02, 0x74, 0x35, 0x48, 0x81, 0x74, -0x06, 0x75, 0x33, 0x21, 0x81, 0x75, 0x01, 0x7e, 0x0f, 0x23, 0x19, 0x43, 0x01, 0x76, 0x81, 0x7e, -0x19, 0x43, 0x81, 0x76, 0x81, 0x7e, 0xf6, 0x23, 0x19, 0x40, 0x81, 0x76, 0x2e, 0x49, 0x0a, 0x74, -0x4b, 0x7c, 0x0f, 0x26, 0x33, 0x43, 0x4b, 0x74, 0x4b, 0x7c, 0xf4, 0x26, 0x33, 0x40, 0x4b, 0x74, -0x4b, 0x7c, 0xf0, 0x26, 0x33, 0x43, 0x4b, 0x74, 0x4b, 0x7c, 0x4f, 0x26, 0x33, 0x40, 0x4b, 0x74, -0x0b, 0x7f, 0xcf, 0x26, 0x33, 0x40, 0x0b, 0x77, 0x24, 0x49, 0x09, 0x7e, 0x89, 0x1e, 0xfd, 0x29, -0x1b, 0xd2, 0x21, 0x7a, 0x02, 0x23, 0x91, 0x43, 0x19, 0x43, 0x21, 0x72, 0x20, 0x49, 0x0e, 0x7a, -0xef, 0x24, 0x26, 0x40, 0x1e, 0x43, 0x0e, 0x72, 0x1e, 0x4b, 0x5e, 0x7f, 0x26, 0x40, 0x5e, 0x77, -0x5e, 0x7e, 0x26, 0x40, 0x5e, 0x76, 0x8b, 0x79, 0x13, 0x43, 0x8b, 0x71, 0x8a, 0x79, 0x2a, 0x40, -0x8a, 0x71, 0xc1, 0x7f, 0x20, 0x22, 0x11, 0x43, 0xc1, 0x77, 0x00, 0x20, 0x16, 0x4b, 0x17, 0x4c, -0x30, 0x22, 0x81, 0x00, 0xcd, 0x18, 0x2a, 0x64, 0x09, 0x19, 0x0f, 0x60, 0x40, 0x1c, 0xc0, 0xb2, -0x10, 0x28, 0xf6, 0xd3, 0xf0, 0xbc, 0x70, 0x47, 0x60, 0x51, 0x03, 0x40, 0x20, 0x14, 0x03, 0x40, -0x60, 0x11, 0x03, 0x40, 0x60, 0x13, 0x03, 0x40, 0x00, 0x11, 0x03, 0x40, 0x00, 0x13, 0x03, 0x40, -0x40, 0x11, 0x03, 0x40, 0x40, 0x13, 0x03, 0x40, 0x40, 0x14, 0x03, 0x40, 0x80, 0x11, 0x03, 0x40, -0x80, 0x13, 0x03, 0x40, 0x20, 0x50, 0x03, 0x40, 0xa0, 0x51, 0x03, 0x40, 0x28, 0x0d, 0x01, 0x20, -0x40, 0x50, 0x03, 0x40, 0xe0, 0x50, 0x03, 0x40, 0x00, 0x49, 0x02, 0x00, 0x80, 0x49, 0x02, 0x00, -0xf8, 0xb5, 0x79, 0xa0, 0x06, 0xf0, 0x0c, 0xfe, 0xfc, 0xf7, 0x6c, 0xf9, 0x7a, 0x48, 0x00, 0x27, -0x47, 0x70, 0x47, 0x71, 0x87, 0x74, 0x87, 0x70, 0x78, 0x4c, 0x01, 0x20, 0xa0, 0x75, 0x78, 0x4e, -0xb7, 0x71, 0xb7, 0x76, 0x03, 0xf0, 0xb6, 0xf9, 0xfa, 0xf7, 0xec, 0xfd, 0x75, 0x48, 0x76, 0x4d, -0x00, 0x7d, 0x01, 0x28, 0x09, 0xd1, 0xe8, 0x7d, 0x80, 0x06, 0x06, 0xd5, 0x19, 0x20, 0x40, 0x01, -0x05, 0xf0, 0xa4, 0xfc, 0x00, 0x20, 0x03, 0xf0, 0x8b, 0xfe, 0x06, 0xf0, 0xed, 0xfa, 0x03, 0xf0, -0x91, 0xfa, 0x60, 0x7b, 0x00, 0x28, 0x01, 0xd1, 0x06, 0xf0, 0xaa, 0xf9, 0xfc, 0xf7, 0x7e, 0xfb, -0x05, 0xf0, 0xe2, 0xfd, 0xe7, 0x77, 0x06, 0xf0, 0xdf, 0xfa, 0x03, 0xf0, 0x75, 0xfa, 0xfc, 0xf7, -0x45, 0xf9, 0x61, 0x48, 0x00, 0x78, 0x00, 0x28, 0x7e, 0xd1, 0x06, 0xf0, 0x21, 0xfb, 0x60, 0x7f, -0x00, 0x28, 0x03, 0xd0, 0xfb, 0xf7, 0x1c, 0xff, 0x00, 0x20, 0x60, 0x77, 0xb0, 0x7d, 0x00, 0x28, -0x03, 0xd0, 0xfb, 0xf7, 0xe7, 0xfe, 0x00, 0x20, 0xb0, 0x75, 0xfd, 0xf7, 0x79, 0xfc, 0x01, 0x28, -0x01, 0xd0, 0x00, 0x28, 0x02, 0xd1, 0x60, 0x7b, 0x00, 0x28, 0x17, 0xd0, 0xa0, 0x7d, 0x00, 0x28, -0x01, 0xd0, 0x03, 0xf0, 0x5f, 0xfa, 0x06, 0xf0, 0x31, 0xfa, 0x00, 0x28, 0x75, 0xd0, 0x06, 0xf0, -0xb3, 0xfa, 0x03, 0xf0, 0x49, 0xfa, 0x4f, 0x4f, 0x38, 0x7d, 0x02, 0x28, 0x0c, 0xd0, 0x04, 0xf0, -0x9b, 0xff, 0xff, 0xf7, 0x87, 0xfe, 0x00, 0x28, 0x7a, 0xd1, 0x08, 0xe0, 0xa0, 0x7d, 0x00, 0x28, -0x72, 0xd1, 0x03, 0xf0, 0x1f, 0xfb, 0x6f, 0xe0, 0x04, 0xf0, 0x20, 0xff, 0xf1, 0xe7, 0x42, 0x48, -0x40, 0x7c, 0x00, 0x28, 0x0f, 0xd0, 0x05, 0xf0, 0x97, 0xfd, 0x3f, 0x49, 0x00, 0x20, 0x48, 0x74, -0x38, 0x7d, 0x01, 0x28, 0x01, 0xd0, 0x02, 0x28, 0x62, 0xd1, 0x40, 0x48, 0x81, 0x7c, 0xcf, 0x22, -0x11, 0x40, 0x81, 0x74, 0x5c, 0xe0, 0x04, 0xf0, 0x78, 0xff, 0xff, 0xf7, 0x13, 0xfd, 0xfc, 0xf7, -0x9d, 0xff, 0x38, 0x7d, 0x01, 0x28, 0x04, 0xd1, 0xe8, 0x7d, 0x80, 0x06, 0x01, 0xd5, 0x00, 0x20, -0x00, 0xe0, 0x01, 0x20, 0xfa, 0xf7, 0xde, 0xfb, 0xfa, 0xf7, 0x7c, 0xfd, 0x00, 0x28, 0x01, 0xd1, -0x00, 0xf0, 0xa8, 0xf9, 0x2c, 0x48, 0x80, 0x7c, 0x00, 0x28, 0x0a, 0xd0, 0x78, 0x7e, 0xc1, 0x07, -0x01, 0xd1, 0x80, 0x07, 0x01, 0xd5, 0x01, 0xf0, 0x57, 0xfe, 0x00, 0x21, 0x08, 0x46, 0x06, 0xf0, -0x8f, 0xfa, 0x2a, 0x4b, 0x99, 0x7c, 0x22, 0x7a, 0x10, 0x20, 0x90, 0x40, 0x81, 0x43, 0x99, 0x74, -0x38, 0x7d, 0x01, 0x28, 0x15, 0xd1, 0x00, 0xe0, 0x2f, 0xe0, 0xe8, 0x7d, 0x80, 0x06, 0x10, 0xd5, -0x19, 0x20, 0x40, 0x01, 0x04, 0xf0, 0x1e, 0xfd, 0x06, 0xf0, 0x68, 0xfa, 0x04, 0xf0, 0x98, 0xfd, -0x01, 0x20, 0xfa, 0xf7, 0xaf, 0xfb, 0xfa, 0xf7, 0x4d, 0xfd, 0x00, 0x28, 0x01, 0xd1, 0x00, 0xf0, -0x79, 0xf9, 0x01, 0xf0, 0xa5, 0xfd, 0x06, 0xf0, 0xef, 0xf8, 0x60, 0x7c, 0x00, 0x28, 0x0b, 0xd0, -0x03, 0xf0, 0xb8, 0xfa, 0x16, 0x49, 0x01, 0x20, 0x48, 0x75, 0x64, 0x20, 0x06, 0xf0, 0x44, 0xfc, -0x03, 0xf0, 0xd8, 0xf9, 0x00, 0x20, 0x60, 0x74, 0x01, 0xf0, 0xba, 0xfc, 0x03, 0xf0, 0xc2, 0xf9, -0x09, 0x48, 0x00, 0x78, 0x00, 0x28, 0x00, 0xd1, 0x4f, 0xe7, 0x07, 0x49, 0x01, 0x20, 0x48, 0x70, -0x03, 0xf0, 0xa0, 0xfa, 0xf8, 0xbd, 0x00, 0x00, 0x0a, 0x0a, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, -0x57, 0x6f, 0x72, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x4c, 0x03, 0x01, 0x20, 0x6c, 0x03, 0x01, 0x20, -0x8c, 0x03, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0xe8, 0x0d, 0x01, 0x20, 0x00, 0x50, 0x03, 0x40, -0xe0, 0x51, 0x03, 0x40, 0xf0, 0xb4, 0x03, 0x26, 0x16, 0x4f, 0x17, 0x49, 0x17, 0x4a, 0x18, 0x4b, -0x18, 0x4c, 0x19, 0x4d, 0x36, 0x04, 0x00, 0x28, 0x15, 0xd0, 0x38, 0x7b, 0x08, 0x70, 0x10, 0x7a, -0x48, 0x70, 0x18, 0x79, 0x88, 0x70, 0x20, 0x7d, 0xc8, 0x70, 0x28, 0x7e, 0x08, 0x71, 0x70, 0x7f, -0x48, 0x71, 0xff, 0x20, 0x38, 0x73, 0x01, 0x20, 0x10, 0x72, 0x14, 0x21, 0x19, 0x71, 0x20, 0x75, -0x18, 0x21, 0x29, 0x76, 0x0a, 0xe0, 0x08, 0x78, 0x38, 0x73, 0x48, 0x78, 0x10, 0x72, 0x88, 0x78, -0x18, 0x71, 0xc8, 0x78, 0x20, 0x75, 0x08, 0x79, 0x28, 0x76, 0x48, 0x79, 0x70, 0x77, 0xf0, 0xbc, -0x70, 0x47, 0x00, 0x00, 0x20, 0x30, 0x03, 0x00, 0xbe, 0x00, 0x01, 0x20, 0x60, 0x60, 0x03, 0x00, -0x40, 0x11, 0x03, 0x00, 0x20, 0x50, 0x03, 0x00, 0x00, 0x11, 0x03, 0x00, 0x69, 0x48, 0xc0, 0x7d, -0x00, 0x07, 0x7a, 0xd5, 0xf8, 0xb5, 0x68, 0x4e, 0x00, 0x25, 0xb5, 0x70, 0x75, 0x70, 0x67, 0x48, -0x85, 0x70, 0x67, 0x48, 0x67, 0x4c, 0x00, 0x7d, 0xa0, 0x73, 0x21, 0x7d, 0x01, 0x29, 0x0a, 0xd0, -0x00, 0x28, 0x0a, 0xd0, 0x65, 0x73, 0x03, 0x20, 0xe0, 0x77, 0x03, 0xf0, 0x6b, 0xf8, 0x20, 0x7d, -0x01, 0x28, 0x05, 0xd0, 0x0c, 0xe0, 0x5e, 0x48, 0x05, 0x75, 0x01, 0x20, 0x60, 0x73, 0xf2, 0xe7, -0x80, 0x22, 0x11, 0x46, 0x5c, 0x48, 0xf8, 0xf7, 0x08, 0xf9, 0x5c, 0x49, 0x33, 0x20, 0x88, 0x75, -0x20, 0x7d, 0x5b, 0x4f, 0x01, 0x28, 0x20, 0xd1, 0xfd, 0xf7, 0x50, 0xfc, 0x54, 0x49, 0x7d, 0x22, -0xc9, 0x7b, 0x12, 0x01, 0x51, 0x43, 0xf8, 0xf7, 0x21, 0xf9, 0x56, 0x49, 0xc8, 0x80, 0x56, 0x48, -0x01, 0x79, 0x48, 0x08, 0x78, 0x81, 0x55, 0x4a, 0x10, 0x73, 0x50, 0x73, 0x90, 0x73, 0xd0, 0x73, -0xc8, 0x07, 0x53, 0x49, 0x11, 0xd0, 0x00, 0x22, 0x10, 0x46, 0x14, 0x23, 0x43, 0x43, 0x5b, 0x18, -0x40, 0x1c, 0xc0, 0xb2, 0x1a, 0x74, 0x0a, 0x28, 0xf7, 0xd9, 0x4e, 0x49, 0x00, 0x20, 0x08, 0x75, -0x41, 0x48, 0x00, 0x78, 0x03, 0x28, 0x0b, 0xd0, 0x68, 0xe0, 0xff, 0x22, 0x00, 0x20, 0x14, 0x23, -0x43, 0x43, 0x5b, 0x18, 0x40, 0x1c, 0xc0, 0xb2, 0x1a, 0x74, 0x0a, 0x28, 0xf7, 0xd9, 0xec, 0xe7, -0x45, 0x4e, 0x46, 0x4f, 0x06, 0xf0, 0xb4, 0xf9, 0x20, 0x7d, 0x02, 0x28, 0x03, 0xd0, 0x20, 0x7d, -0x01, 0x28, 0x13, 0xd0, 0x4e, 0xe0, 0xfb, 0xf7, 0xdb, 0xfa, 0x03, 0xf0, 0x03, 0xf9, 0x06, 0xf0, -0xd5, 0xf8, 0x03, 0xf0, 0xd7, 0xf9, 0x20, 0x7d, 0x01, 0x28, 0x01, 0xd1, 0x02, 0xf0, 0x70, 0xf8, -0x00, 0x21, 0x03, 0x20, 0x06, 0xf0, 0x7c, 0xf9, 0x3c, 0xe0, 0x51, 0xe0, 0x3d, 0x78, 0x38, 0xa0, -0x29, 0x46, 0x06, 0xf0, 0x45, 0xfc, 0x02, 0x2d, 0x04, 0xd0, 0x01, 0x2d, 0x08, 0xd0, 0x03, 0x2d, -0x0b, 0xd0, 0x0f, 0xe0, 0x2a, 0x48, 0x01, 0x7a, 0x10, 0x22, 0x11, 0x43, 0x01, 0x72, 0x09, 0xe0, -0x27, 0x48, 0x01, 0x7a, 0xef, 0x22, 0x11, 0x40, 0x03, 0xe0, 0x25, 0x48, 0x01, 0x7a, 0x10, 0x22, -0x11, 0x43, 0x01, 0x72, 0x30, 0x48, 0x82, 0x78, 0xdb, 0x21, 0x0a, 0x40, 0x82, 0x70, 0x38, 0x78, -0x01, 0x28, 0x04, 0xd0, 0x02, 0x28, 0x05, 0xd0, 0x03, 0x28, 0x08, 0xd0, 0x12, 0xe0, 0x0a, 0x21, -0x08, 0x20, 0x01, 0xe0, 0x08, 0x21, 0x00, 0x20, 0xfd, 0xf7, 0xe4, 0xfb, 0x08, 0xe0, 0x27, 0x48, -0x01, 0x7e, 0xcf, 0x22, 0x11, 0x40, 0x01, 0x76, 0x0c, 0x21, 0x0a, 0x20, 0xfd, 0xf7, 0xda, 0xfb, -0x00, 0x20, 0x38, 0x70, 0x0c, 0x48, 0x00, 0x78, 0x03, 0x28, 0xa3, 0xd0, 0x0a, 0x49, 0x01, 0x20, -0x48, 0x70, 0x00, 0x25, 0x8d, 0x70, 0xa1, 0x7b, 0x09, 0x48, 0x01, 0x75, 0x03, 0xf0, 0x82, 0xf9, -0x60, 0x7e, 0x00, 0x28, 0x02, 0xd0, 0x00, 0x20, 0x03, 0xf0, 0xac, 0xfe, 0x25, 0x75, 0xf8, 0xbd, -0x70, 0x47, 0x00, 0x00, 0xe8, 0x0d, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, 0x18, 0x00, 0x01, 0x20, -0xa8, 0x0c, 0x01, 0x20, 0x6c, 0x03, 0x01, 0x20, 0x40, 0x49, 0x02, 0x20, 0x20, 0x50, 0x03, 0x40, -0x40, 0x50, 0x03, 0x40, 0x00, 0x50, 0x03, 0x40, 0xe8, 0x0c, 0x01, 0x20, 0x80, 0x51, 0x03, 0x40, -0x24, 0x01, 0x01, 0x20, 0x40, 0x51, 0x03, 0x40, 0x48, 0x0d, 0x01, 0x20, 0x8c, 0x04, 0x01, 0x20, -0x75, 0x38, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x44, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, -0x3a, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x50, 0x03, 0x40, 0x20, 0x14, 0x03, 0x40, -0x70, 0x47, 0x00, 0x00, 0xf8, 0xb5, 0x86, 0x49, 0x00, 0x25, 0x86, 0x48, 0x0d, 0x70, 0x40, 0x79, -0x02, 0x28, 0x4a, 0xd0, 0x84, 0x48, 0x85, 0x4c, 0x00, 0x7e, 0x85, 0x4f, 0x80, 0x07, 0x01, 0x26, -0x00, 0x28, 0x53, 0xda, 0x83, 0x48, 0x01, 0x78, 0x7d, 0x20, 0xc0, 0x00, 0xf8, 0xf7, 0x3e, 0xf8, -0x04, 0xf0, 0xf2, 0xfd, 0x7b, 0x48, 0x40, 0x79, 0x03, 0x28, 0x09, 0xd0, 0x7e, 0x48, 0x00, 0x78, -0x00, 0x28, 0x43, 0xd0, 0x20, 0x46, 0xfa, 0xf7, 0x1d, 0xfd, 0x40, 0x28, 0x3a, 0xd0, 0x3d, 0xe0, -0xfd, 0xf7, 0x56, 0xfa, 0x00, 0x28, 0x28, 0xd1, 0x20, 0x78, 0x01, 0x28, 0x26, 0xd8, 0x00, 0x21, -0xa0, 0x1d, 0xfa, 0xf7, 0xe7, 0xfd, 0x75, 0x49, 0x88, 0x70, 0xfe, 0xf7, 0x05, 0xfc, 0x73, 0x49, -0x00, 0x28, 0x88, 0x70, 0x15, 0xd0, 0xa1, 0x78, 0x01, 0x43, 0xa1, 0x70, 0x00, 0x20, 0x03, 0xf0, -0xe5, 0xfc, 0x67, 0x48, 0x06, 0x70, 0x6e, 0x48, 0x00, 0x78, 0x00, 0x28, 0x1e, 0xd0, 0x6b, 0x49, -0x00, 0x20, 0x89, 0x7a, 0x81, 0x42, 0x19, 0xd3, 0x40, 0x1c, 0xc0, 0xb2, 0x80, 0x28, 0xf9, 0xd3, -0x14, 0xe0, 0x00, 0x20, 0x78, 0x70, 0x03, 0xf0, 0xd1, 0xfc, 0xf8, 0xbd, 0x02, 0xf0, 0xbe, 0xfa, -0x00, 0x20, 0x78, 0x70, 0x63, 0x48, 0xc6, 0x73, 0x63, 0x48, 0x06, 0x70, 0x00, 0x20, 0x03, 0xf0, -0xc5, 0xfc, 0xf8, 0xbd, 0xa0, 0x78, 0x40, 0x21, 0x08, 0x43, 0xa0, 0x70, 0x57, 0x48, 0x80, 0x78, -0x00, 0x28, 0x03, 0xd0, 0x7d, 0x20, 0xc0, 0x00, 0x06, 0xf0, 0x6e, 0xfa, 0x39, 0x78, 0x5b, 0x48, -0x01, 0x78, 0x71, 0x40, 0x01, 0x70, 0x10, 0x20, 0xfd, 0xf7, 0x82, 0xf9, 0x04, 0x1e, 0xe8, 0xd0, -0x70, 0x21, 0xf7, 0xf7, 0xd7, 0xff, 0x4d, 0x48, 0x00, 0x78, 0x00, 0x28, 0x0d, 0xd1, 0x4b, 0x48, -0x41, 0x78, 0x00, 0x29, 0x09, 0xd1, 0x81, 0x78, 0x00, 0x29, 0x06, 0xd1, 0xc0, 0x78, 0x00, 0x28, -0x03, 0xd1, 0x43, 0x48, 0x00, 0x78, 0x00, 0x28, 0x09, 0xd0, 0x38, 0x78, 0x01, 0x28, 0x00, 0xd0, -0x3e, 0x70, 0x43, 0x48, 0xa6, 0x46, 0x00, 0x78, 0x01, 0x28, 0x0b, 0xd0, 0x3d, 0xe0, 0x00, 0x20, -0x78, 0x70, 0x47, 0x4c, 0x20, 0x78, 0x00, 0x28, 0xc3, 0xd0, 0x00, 0x20, 0x03, 0xf0, 0x86, 0xfc, -0x26, 0x70, 0xf8, 0xbd, 0x39, 0x48, 0x43, 0x4a, 0x81, 0x78, 0x21, 0x70, 0xd3, 0x7c, 0x00, 0x21, -0xa4, 0x1c, 0x00, 0x2b, 0x25, 0xd9, 0x40, 0x4a, 0x94, 0x46, 0x14, 0x20, 0x0a, 0x46, 0x42, 0x43, -0x32, 0x48, 0x10, 0x18, 0x62, 0x46, 0x12, 0x78, 0x83, 0x7c, 0x00, 0x2a, 0x02, 0xd0, 0x02, 0x7c, -0x00, 0x2a, 0x10, 0xd1, 0x00, 0x2b, 0x0e, 0xd0, 0x21, 0x70, 0x87, 0x79, 0x67, 0x70, 0xc7, 0x79, -0xa7, 0x70, 0x07, 0x7a, 0xe7, 0x70, 0x42, 0x7a, 0x22, 0x71, 0x40, 0x7c, 0x6d, 0x1c, 0x60, 0x71, -0xa3, 0x71, 0xed, 0xb2, 0xe4, 0x1d, 0x2f, 0x48, 0x49, 0x1c, 0xc0, 0x7c, 0xc9, 0xb2, 0x88, 0x42, -0xdb, 0xd8, 0x00, 0x2d, 0xcd, 0xd0, 0x70, 0x46, 0x45, 0x70, 0x20, 0x48, 0x20, 0x4d, 0x81, 0x78, -0xc1, 0x70, 0x00, 0x24, 0xc8, 0x20, 0x06, 0xf0, 0xff, 0xf9, 0x28, 0x79, 0x00, 0x28, 0x03, 0xd0, -0x64, 0x1c, 0xe4, 0xb2, 0xc8, 0x2c, 0xf5, 0xd3, 0x6e, 0x70, 0x15, 0x4d, 0x23, 0x4c, 0x28, 0x78, -0x00, 0x28, 0x00, 0xd0, 0xa6, 0x70, 0x03, 0xf0, 0x65, 0xfc, 0x28, 0x78, 0x00, 0x28, 0xb0, 0xd0, -0x00, 0x26, 0x6e, 0x70, 0x6e, 0x60, 0xa0, 0x78, 0x00, 0x28, 0xaa, 0xd0, 0x1c, 0x4f, 0x06, 0xf0, -0x1f, 0xf8, 0x0a, 0x20, 0xfb, 0xf7, 0x94, 0xfc, 0x68, 0x68, 0xb8, 0x42, 0x08, 0xd1, 0x6e, 0x60, -0x68, 0x78, 0x40, 0x1c, 0xc0, 0xb2, 0x68, 0x70, 0x03, 0x28, 0x9a, 0xd0, 0x03, 0xf0, 0x4a, 0xfc, -0x68, 0x68, 0x40, 0x1c, 0x68, 0x60, 0xa0, 0x78, 0x00, 0x28, 0xe8, 0xd1, 0xf8, 0xbd, 0x00, 0x00, -0x10, 0x00, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, 0xe8, 0x0d, 0x01, 0x20, 0x68, 0x02, 0x01, 0x20, -0x18, 0x00, 0x01, 0x20, 0x48, 0x0d, 0x01, 0x20, 0x8c, 0x00, 0x01, 0x20, 0x76, 0x00, 0x01, 0x20, -0x74, 0x00, 0x01, 0x20, 0xa4, 0x2d, 0x01, 0x20, 0x38, 0x02, 0x01, 0x20, 0x88, 0x04, 0x01, 0x20, -0x03, 0x00, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0x08, 0x0e, 0x01, 0x20, 0x8c, 0x03, 0x01, 0x20, -0xb8, 0x0b, 0x00, 0x00, 0xf0, 0xb5, 0x8c, 0x46, 0x24, 0x49, 0x17, 0x46, 0x4a, 0x7f, 0x65, 0x46, -0x12, 0x06, 0x16, 0x14, 0x42, 0x1e, 0x96, 0x46, 0x12, 0x22, 0x50, 0x43, 0x20, 0x4a, 0x83, 0xb0, -0x82, 0x18, 0x62, 0x44, 0x94, 0x46, 0x09, 0x7f, 0x40, 0x3a, 0x01, 0x92, 0xd0, 0x7e, 0x62, 0x46, -0x20, 0x3a, 0x00, 0x92, 0x52, 0x7b, 0x0e, 0x43, 0x10, 0x1a, 0x84, 0x46, 0x00, 0x98, 0xf1, 0x17, -0x00, 0x7b, 0x6d, 0x1e, 0x10, 0x1a, 0x08, 0x9c, 0xf6, 0x1b, 0x99, 0x41, 0x17, 0xda, 0xa4, 0x45, -0x04, 0xdc, 0x01, 0x99, 0x49, 0x7a, 0x51, 0x1a, 0xa1, 0x42, 0x01, 0xdd, 0xa0, 0x42, 0x02, 0xdc, -0x09, 0x99, 0x88, 0x42, 0x09, 0xdd, 0x00, 0x98, 0xc0, 0x7f, 0x82, 0x42, 0x05, 0xd2, 0x70, 0x46, -0xe9, 0xb2, 0xc0, 0xb2, 0x0a, 0x4b, 0x03, 0xf0, 0x09, 0xf8, 0x03, 0xb0, 0xf0, 0xbd, 0xa4, 0x45, -0x04, 0xdc, 0x01, 0x99, 0x49, 0x7a, 0x51, 0x1a, 0xa1, 0x42, 0x01, 0xdd, 0xa0, 0x42, 0xee, 0xdc, -0x09, 0x99, 0x88, 0x42, 0xeb, 0xdc, 0x03, 0xb0, 0xf0, 0xbd, 0x00, 0x00, 0xa8, 0x0e, 0x01, 0x20, -0xa4, 0x0f, 0x01, 0x20, 0xf0, 0xb5, 0x8d, 0xb0, 0x89, 0x48, 0x0b, 0x90, 0x89, 0x48, 0x06, 0x90, -0x8a, 0x49, 0x00, 0x79, 0x88, 0x4c, 0x4a, 0x7c, 0x86, 0x46, 0x0b, 0x7c, 0x60, 0x8c, 0x11, 0x02, -0x19, 0x43, 0x88, 0x42, 0x86, 0x49, 0x0b, 0xd9, 0xa1, 0x31, 0x4a, 0x79, 0x09, 0x79, 0x16, 0x02, -0x0e, 0x43, 0x84, 0x49, 0x4a, 0x7c, 0x0b, 0x7c, 0x11, 0x02, 0x19, 0x43, 0x07, 0x91, 0x0a, 0xe0, -0xa3, 0x31, 0x4a, 0x79, 0x09, 0x79, 0x16, 0x02, 0x0e, 0x43, 0x7f, 0x49, 0x4a, 0x7d, 0x0b, 0x7d, -0x11, 0x02, 0x19, 0x43, 0x07, 0x91, 0x71, 0x46, 0x02, 0x29, 0x01, 0xd0, 0x03, 0x29, 0x6a, 0xd1, -0x00, 0x21, 0x7a, 0x4a, 0x0c, 0x91, 0x53, 0x7e, 0x12, 0x7e, 0x1b, 0x02, 0x13, 0x43, 0x98, 0x42, -0x7e, 0xd8, 0x06, 0x9a, 0x12, 0x7d, 0x0a, 0x92, 0xd3, 0x07, 0x75, 0x4a, 0x00, 0x2b, 0xd2, 0x7d, -0x08, 0x92, 0x74, 0x4a, 0x94, 0x46, 0x11, 0xd0, 0x73, 0x4a, 0x53, 0x7a, 0x12, 0x7a, 0x1b, 0x02, -0x13, 0x43, 0x98, 0x42, 0x07, 0xd9, 0x60, 0x46, 0x40, 0x7c, 0x08, 0x9a, 0x90, 0x42, 0x05, 0xd2, -0x62, 0x46, 0x40, 0x1c, 0x01, 0xe0, 0x00, 0x20, 0x62, 0x46, 0x50, 0x74, 0x64, 0x4b, 0x01, 0x22, -0xd8, 0x79, 0x09, 0x90, 0x01, 0x28, 0x17, 0xd3, 0x1f, 0x7a, 0x01, 0x20, 0x01, 0x2f, 0x0e, 0xd3, -0x28, 0x25, 0x13, 0x46, 0x6b, 0x43, 0x0b, 0x9d, 0x5b, 0x19, 0x45, 0x00, 0x5d, 0x5f, 0xb5, 0x42, -0x01, 0xdd, 0x49, 0x1c, 0x89, 0xb2, 0x40, 0x1c, 0xc0, 0xb2, 0x87, 0x42, 0xf5, 0xd2, 0x52, 0x1c, -0x09, 0x98, 0xd2, 0xb2, 0x90, 0x42, 0xe8, 0xd2, 0x53, 0x4a, 0x07, 0x9b, 0xd0, 0x7e, 0x92, 0x7e, -0x99, 0x42, 0x02, 0xd8, 0x0c, 0x99, 0x00, 0x29, 0x14, 0xd0, 0x00, 0x28, 0x02, 0xd0, 0x00, 0x2a, -0x03, 0xd0, 0x18, 0xe0, 0x01, 0x20, 0xe0, 0x76, 0x15, 0xe0, 0x60, 0x46, 0x41, 0x7c, 0x08, 0x98, -0x81, 0x42, 0x02, 0xd3, 0x0a, 0x98, 0xc0, 0x07, 0x0d, 0xd1, 0x01, 0x20, 0xa0, 0x76, 0x4f, 0x48, -0xc0, 0x7c, 0x02, 0xe0, 0x00, 0x28, 0x02, 0xd0, 0x40, 0x1e, 0xe0, 0x76, 0x03, 0xe0, 0x00, 0x2a, -0x01, 0xd0, 0x00, 0x20, 0xa0, 0x76, 0x70, 0x46, 0x01, 0x28, 0x01, 0xd0, 0x03, 0x28, 0x67, 0xd1, -0x00, 0x20, 0x00, 0x90, 0x01, 0x90, 0x02, 0x90, 0x03, 0x90, 0x04, 0x90, 0x05, 0x90, 0xa0, 0x85, -0x05, 0x46, 0x43, 0x48, 0x08, 0x90, 0xc0, 0x8b, 0x00, 0x28, 0x21, 0xd9, 0x30, 0xb2, 0x09, 0x90, -0x68, 0x46, 0x40, 0x5d, 0x00, 0x28, 0x15, 0xd1, 0x3e, 0x4e, 0x68, 0x00, 0x80, 0x19, 0x00, 0xe0, -0x5c, 0xe0, 0xe0, 0x30, 0x41, 0x78, 0x00, 0x78, 0x2d, 0x4b, 0x09, 0x9a, 0x03, 0xf0, 0xae, 0xf8, -0x06, 0x98, 0x00, 0x79, 0x01, 0x28, 0x10, 0xd0, 0x37, 0x48, 0xa1, 0x8d, 0x80, 0x8d, 0x81, 0x42, -0x00, 0xd2, 0xa0, 0x85, 0x08, 0x98, 0x6d, 0x1c, 0xc0, 0x8b, 0xed, 0xb2, 0xa8, 0x42, 0xdf, 0xd8, -0x06, 0x98, 0x00, 0x79, 0x01, 0x28, 0x2e, 0xd0, 0x32, 0xe0, 0x2f, 0x48, 0x81, 0x8d, 0x07, 0x98, -0x81, 0x42, 0xef, 0xd3, 0x08, 0x99, 0x68, 0x1c, 0xcf, 0x8b, 0xc0, 0xb2, 0x87, 0x42, 0x1e, 0xd9, -0x01, 0x26, 0x28, 0x49, 0x42, 0x00, 0x51, 0x18, 0xe0, 0x31, 0x4a, 0x78, 0x09, 0x78, 0x12, 0x23, -0x49, 0x1e, 0x59, 0x43, 0x49, 0x1e, 0x51, 0x18, 0x24, 0x4a, 0xcb, 0x10, 0xd2, 0x5c, 0xcb, 0x17, -0x5b, 0x0f, 0x5b, 0x18, 0xdb, 0x08, 0xdb, 0x00, 0xc9, 0x1a, 0x33, 0x46, 0x8b, 0x40, 0x1a, 0x42, -0x01, 0xd0, 0x69, 0x46, 0x0e, 0x54, 0x40, 0x1c, 0xc0, 0xb2, 0x87, 0x42, 0xe1, 0xd8, 0x01, 0x21, -0x68, 0x46, 0x41, 0x55, 0xc6, 0xe7, 0x1a, 0x4a, 0x68, 0x46, 0x11, 0x46, 0x00, 0xf0, 0x2c, 0xfc, -0xa0, 0x7e, 0x00, 0x28, 0x0a, 0xd0, 0x06, 0x98, 0x00, 0x79, 0x02, 0x28, 0x04, 0xd0, 0x03, 0x28, -0x04, 0xd1, 0xa0, 0x8d, 0x32, 0x28, 0x01, 0xd9, 0x01, 0x20, 0xa0, 0x77, 0x0d, 0xb0, 0xf0, 0xbd, -0x28, 0x2f, 0x01, 0x20, 0x48, 0x0d, 0x01, 0x20, 0x84, 0x2d, 0x01, 0x20, 0xe9, 0x0d, 0x01, 0x20, -0xa8, 0x0c, 0x01, 0x20, 0x6b, 0x0d, 0x01, 0x20, 0x69, 0x0d, 0x01, 0x20, 0x8a, 0x0d, 0x01, 0x20, -0x88, 0x0d, 0x01, 0x20, 0xa4, 0x2d, 0x01, 0x20, 0x28, 0x0d, 0x01, 0x20, 0xe8, 0x0d, 0x01, 0x20, -0x04, 0x25, 0x01, 0x20, 0x44, 0x24, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, 0x78, 0x34, 0x01, 0x20, -0x22, 0x25, 0x01, 0x20, 0xf0, 0xb5, 0xf9, 0x48, 0x95, 0xb0, 0x41, 0x7b, 0x02, 0x7b, 0x08, 0x02, -0x10, 0x43, 0x07, 0x90, 0x08, 0x20, 0xfc, 0xf7, 0x33, 0xff, 0x00, 0x25, 0x00, 0x95, 0x0f, 0x90, -0x08, 0x95, 0x01, 0x95, 0xf2, 0x48, 0x03, 0x95, 0x04, 0x95, 0x06, 0x95, 0x05, 0x90, 0x00, 0x7e, -0x2c, 0x46, 0x40, 0x07, 0x7e, 0xd5, 0xef, 0x48, 0x80, 0x7b, 0x00, 0x28, 0x03, 0xd0, 0xee, 0x48, -0x40, 0x79, 0x03, 0x28, 0x76, 0xd1, 0xed, 0x48, 0xc0, 0x7a, 0x01, 0x28, 0x72, 0xd1, 0xec, 0x4f, -0x38, 0x7c, 0x00, 0x28, 0x6e, 0xd1, 0xec, 0x4a, 0xea, 0x4e, 0x50, 0x7a, 0x12, 0x7a, 0x71, 0x8c, -0x00, 0x02, 0x10, 0x43, 0x81, 0x42, 0x04, 0xd9, 0x24, 0x22, 0xb2, 0x5e, 0x43, 0x42, 0x9a, 0x42, -0x60, 0xdc, 0x81, 0x42, 0x07, 0xd9, 0x03, 0x21, 0xf7, 0xf7, 0x60, 0xfd, 0x24, 0x21, 0x71, 0x5e, -0x40, 0x42, 0x88, 0x42, 0x56, 0xdc, 0xdb, 0x4a, 0x38, 0x7a, 0x13, 0x7b, 0x79, 0x7a, 0xdf, 0x4a, -0x0b, 0x92, 0xdf, 0x4a, 0x00, 0x2b, 0x7c, 0xd0, 0x28, 0x23, 0x58, 0x43, 0x80, 0x18, 0x49, 0x00, -0x41, 0x5e, 0x07, 0x98, 0x40, 0x08, 0x40, 0x42, 0x81, 0x42, 0x03, 0xdd, 0xd1, 0x49, 0x00, 0x20, -0x08, 0x73, 0xc8, 0x84, 0x01, 0x20, 0xfc, 0xf7, 0xe3, 0xfe, 0x02, 0x90, 0xd5, 0x48, 0x01, 0x22, -0xc0, 0x79, 0xd5, 0x49, 0x09, 0x91, 0x11, 0x90, 0x01, 0x28, 0x47, 0xd3, 0xd1, 0x48, 0x00, 0x7a, -0x0c, 0x90, 0x08, 0x46, 0x49, 0x7a, 0x03, 0x7a, 0x08, 0x06, 0x00, 0x14, 0x18, 0x43, 0x10, 0x90, -0x0c, 0x99, 0x01, 0x20, 0x01, 0x29, 0x34, 0xd3, 0xc9, 0x4b, 0x11, 0x46, 0x28, 0x26, 0x71, 0x43, -0xc9, 0x18, 0x0e, 0x91, 0x11, 0x46, 0x24, 0x23, 0x59, 0x43, 0x02, 0x9b, 0xc9, 0x18, 0x0d, 0x91, -0x0d, 0x9b, 0x41, 0x00, 0x5b, 0x18, 0x40, 0x3b, 0x1a, 0x26, 0x9e, 0x5f, 0x10, 0x9b, 0x08, 0x9f, -0xf3, 0x1a, 0x9e, 0x46, 0x5b, 0x43, 0xde, 0x17, 0x5d, 0x19, 0x7e, 0x41, 0x0e, 0x9b, 0x08, 0x96, -0x59, 0x5e, 0x00, 0x9e, 0x8c, 0x46, 0x49, 0x43, 0xcb, 0x17, 0x01, 0x9f, 0x89, 0x19, 0x7b, 0x41, -0x01, 0x93, 0x00, 0xe0, 0x5e, 0xe0, 0x00, 0x91, 0x73, 0x46, 0x61, 0x46, 0x4b, 0x43, 0xd9, 0x17, -0x03, 0x9e, 0x1c, 0x19, 0x71, 0x41, 0x03, 0x91, 0x40, 0x1c, 0x0c, 0x99, 0xc0, 0xb2, 0x81, 0x42, -0xd6, 0xd2, 0x52, 0x1c, 0x11, 0x98, 0xd2, 0xb2, 0x90, 0x42, 0xc1, 0xd2, 0x28, 0x46, 0x08, 0x99, -0xf9, 0xf7, 0x16, 0xf9, 0x06, 0x46, 0x00, 0x25, 0x01, 0x99, 0x00, 0x98, 0xf9, 0xf7, 0x10, 0xf9, -0x02, 0x46, 0x29, 0x46, 0x2b, 0x46, 0x30, 0x46, 0xf7, 0xf7, 0x26, 0xfc, 0x05, 0x46, 0x0e, 0x46, -0x64, 0x22, 0x00, 0x23, 0x20, 0x46, 0x03, 0x99, 0xf7, 0xf7, 0x1e, 0xfc, 0x33, 0x46, 0x2a, 0x46, -0x00, 0xe0, 0x17, 0xe0, 0xf7, 0xf7, 0x30, 0xfc, 0x02, 0x90, 0x05, 0x98, 0x03, 0x91, 0x41, 0x7f, -0x00, 0x7f, 0x09, 0x06, 0x0a, 0x14, 0x02, 0x43, 0xd3, 0x17, 0x02, 0x98, 0x03, 0x99, 0x1c, 0x46, -0x10, 0x1a, 0x8b, 0x41, 0x25, 0xda, 0x05, 0x99, 0x07, 0x98, 0x49, 0x7e, 0x80, 0x08, 0x49, 0x08, -0x0c, 0x91, 0x3b, 0xe0, 0x28, 0x23, 0x58, 0x43, 0x80, 0x18, 0x49, 0x00, 0x41, 0x5e, 0x0b, 0x98, -0x42, 0x7e, 0x03, 0x7e, 0x10, 0x02, 0x18, 0x43, 0x40, 0x42, 0x81, 0x42, 0x0c, 0xda, 0x85, 0x49, -0xc8, 0x8c, 0x40, 0x1c, 0x80, 0xb2, 0xc8, 0x84, 0x05, 0x9a, 0x52, 0x7e, 0x90, 0x42, 0x01, 0xd1, -0x01, 0x20, 0x08, 0x73, 0x15, 0xb0, 0xf0, 0xbd, 0x7e, 0x49, 0x00, 0x20, 0xc8, 0x84, 0x15, 0xb0, -0xf0, 0xbd, 0x0b, 0x98, 0x02, 0x9d, 0x43, 0x7f, 0x01, 0x7f, 0x18, 0x06, 0x00, 0x14, 0x08, 0x43, -0xc1, 0x17, 0x03, 0x9b, 0x40, 0x1b, 0x99, 0x41, 0x07, 0xda, 0x51, 0x1b, 0x9c, 0x41, 0x04, 0xdb, -0x07, 0x98, 0x05, 0x99, 0x80, 0x08, 0x49, 0x7e, 0x07, 0xe0, 0x05, 0x99, 0x07, 0x98, 0x49, 0x7e, -0x80, 0x08, 0x49, 0x08, 0x4a, 0x00, 0x89, 0x18, 0xc9, 0xb2, 0x0c, 0x91, 0x75, 0x49, 0x01, 0x26, -0xcb, 0x79, 0x0a, 0x46, 0xd1, 0x1d, 0xf9, 0x31, 0x0d, 0x91, 0x11, 0x21, 0x49, 0x01, 0x55, 0x18, -0x01, 0x2b, 0x72, 0xd3, 0x40, 0x42, 0x13, 0x90, 0x70, 0x48, 0x12, 0x90, 0x6d, 0x48, 0x01, 0x24, -0x00, 0x7a, 0x01, 0x28, 0x6a, 0xd3, 0x6e, 0x48, 0x14, 0x22, 0x72, 0x43, 0x10, 0x18, 0x08, 0x90, -0x30, 0x46, 0x28, 0x22, 0x66, 0x49, 0x50, 0x43, 0x11, 0x90, 0x40, 0x18, 0x0e, 0x90, 0x24, 0x20, -0x70, 0x43, 0x10, 0x90, 0x0e, 0x98, 0x67, 0x00, 0xc1, 0x5f, 0x13, 0x98, 0x81, 0x42, 0x7d, 0xda, -0x08, 0x98, 0x0c, 0x99, 0x00, 0x5d, 0x88, 0x42, 0x03, 0xd2, 0x08, 0x99, 0x40, 0x1c, 0x08, 0x55, -0x96, 0xe0, 0x08, 0x99, 0x00, 0x20, 0x08, 0x55, 0x0b, 0x98, 0x42, 0x7f, 0x01, 0x7f, 0x10, 0x06, -0x00, 0x14, 0x08, 0x43, 0x02, 0x99, 0xc3, 0x17, 0x03, 0x9a, 0x40, 0x1a, 0x93, 0x41, 0x7d, 0xda, -0x02, 0xf0, 0x30, 0xfd, 0x4b, 0x48, 0x40, 0x7b, 0x00, 0x28, 0x50, 0xd1, 0x0f, 0x98, 0xf9, 0xf7, -0x05, 0xf8, 0x08, 0x21, 0x53, 0x48, 0x01, 0xf0, 0x8a, 0xfb, 0x01, 0x2e, 0x3d, 0xd9, 0x4d, 0x48, -0xc1, 0x79, 0x49, 0x1c, 0xb1, 0x42, 0x38, 0xd9, 0x01, 0x2c, 0x36, 0xd9, 0x00, 0x7a, 0x40, 0x1c, -0xa0, 0x42, 0x32, 0xd9, 0x69, 0x78, 0x28, 0x78, 0x01, 0x91, 0x00, 0x90, 0x21, 0x46, 0x30, 0x46, -0x03, 0x9b, 0x02, 0x9a, 0xff, 0xf7, 0xf6, 0xfc, 0x05, 0x98, 0x03, 0x9b, 0x42, 0x7f, 0x01, 0x7f, -0x10, 0x06, 0x00, 0x14, 0x08, 0x43, 0x02, 0x99, 0xc2, 0x17, 0x40, 0x1a, 0x9a, 0x41, 0x0e, 0xda, -0x12, 0x98, 0x41, 0x78, 0x00, 0x78, 0x09, 0x02, 0x01, 0x43, 0x32, 0x48, 0x82, 0x8d, 0x91, 0x42, -0x19, 0xd2, 0x01, 0x21, 0x41, 0x73, 0xe8, 0x79, 0x0d, 0xe0, 0x75, 0xe0, 0x4f, 0xe0, 0x68, 0x79, -0x2a, 0x79, 0x01, 0x02, 0x2b, 0x48, 0x11, 0x43, 0x82, 0x8d, 0x91, 0x42, 0x0b, 0xd8, 0x01, 0x21, -0x41, 0x73, 0xe8, 0x79, 0x40, 0x08, 0x04, 0x90, 0x09, 0xe0, 0x26, 0x49, 0x01, 0x20, 0x48, 0x73, -0xe8, 0x79, 0x04, 0x90, 0x03, 0xe0, 0x23, 0x48, 0x40, 0x7b, 0x00, 0x28, 0x30, 0xd0, 0x01, 0x20, -0xfc, 0xf7, 0x86, 0xfd, 0x10, 0x99, 0x08, 0x18, 0xc0, 0x19, 0x40, 0x38, 0x1a, 0x21, 0x41, 0x5e, -0x09, 0x98, 0x43, 0x7a, 0x02, 0x7a, 0x18, 0x06, 0x00, 0x14, 0x01, 0xe0, 0x84, 0xe0, 0x15, 0xe0, -0x10, 0x43, 0x08, 0x1a, 0x01, 0xd4, 0x02, 0x46, 0x00, 0xe0, 0x42, 0x42, 0x0d, 0x99, 0x49, 0x7d, -0x8a, 0x42, 0x15, 0xdd, 0x00, 0x29, 0x03, 0xd0, 0xf7, 0xf7, 0xd6, 0xfb, 0x00, 0xb2, 0x0a, 0x90, -0x22, 0x46, 0x31, 0x46, 0x0a, 0x98, 0xf8, 0xf7, 0x11, 0xf9, 0x09, 0xe0, 0x04, 0x20, 0xfc, 0xf7, -0x5f, 0xfd, 0x11, 0x99, 0x0e, 0x9a, 0x08, 0x18, 0xc1, 0x5b, 0xd2, 0x5b, 0x89, 0x18, 0xc1, 0x53, -0x10, 0x48, 0x64, 0x1c, 0x00, 0x7a, 0xe4, 0xb2, 0xa0, 0x42, 0x00, 0xd3, 0x52, 0xe7, 0x0d, 0x48, -0x76, 0x1c, 0xc0, 0x79, 0xf6, 0xb2, 0xb0, 0x42, 0x1e, 0xd3, 0x37, 0xe7, 0x2a, 0x0d, 0x01, 0x20, -0xa8, 0x0e, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, 0x68, 0x0d, 0x01, 0x20, -0xa4, 0x2d, 0x01, 0x20, 0x84, 0x2d, 0x01, 0x20, 0x28, 0x0d, 0x01, 0x20, 0xaa, 0x0e, 0x01, 0x20, -0x00, 0x50, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0xe9, 0x0c, 0x01, 0x20, 0xca, 0x0e, 0x01, 0x20, -0x4c, 0x1c, 0x01, 0x20, 0xa4, 0x0f, 0x01, 0x20, 0x66, 0x48, 0x40, 0x7b, 0x00, 0x28, 0x64, 0xd0, -0x64, 0x48, 0x00, 0x21, 0x41, 0x73, 0xc1, 0x7b, 0x49, 0x1c, 0xc1, 0x73, 0x00, 0x20, 0x03, 0x90, -0x04, 0x98, 0x00, 0x28, 0x4e, 0xd9, 0x05, 0xf0, 0xef, 0xfb, 0x02, 0xf0, 0x93, 0xfb, 0x05, 0xf0, -0x65, 0xfb, 0x02, 0xf0, 0x67, 0xfc, 0x01, 0x20, 0xfc, 0xf7, 0x12, 0xfd, 0x02, 0x90, 0x5a, 0x48, -0x01, 0x26, 0xc1, 0x79, 0x01, 0x29, 0x36, 0xd3, 0x57, 0x48, 0x01, 0x24, 0x00, 0x7a, 0x01, 0x28, -0x2b, 0xd3, 0x24, 0x20, 0x02, 0x99, 0x70, 0x43, 0x47, 0x18, 0x61, 0x00, 0x78, 0x18, 0x40, 0x38, -0x1a, 0x21, 0x41, 0x5e, 0x09, 0x98, 0x43, 0x7a, 0x02, 0x7a, 0x18, 0x06, 0x00, 0x14, 0x10, 0x43, -0x08, 0x1a, 0x04, 0xd4, 0x02, 0x46, 0x03, 0xe0, 0x00, 0x20, 0x08, 0x99, 0xff, 0xe6, 0x42, 0x42, -0x0d, 0x99, 0x49, 0x7d, 0x8a, 0x42, 0x0a, 0xdd, 0x00, 0x29, 0x03, 0xd0, 0xf7, 0xf7, 0x54, 0xfb, -0x00, 0xb2, 0x0a, 0x90, 0x22, 0x46, 0x31, 0x46, 0x0a, 0x98, 0xf8, 0xf7, 0x8f, 0xf8, 0x42, 0x48, -0x64, 0x1c, 0x00, 0x7a, 0xe4, 0xb2, 0xa0, 0x42, 0xd7, 0xd2, 0x3f, 0x48, 0x76, 0x1c, 0xc0, 0x79, -0xf6, 0xb2, 0xb0, 0x42, 0xc8, 0xd2, 0x03, 0x98, 0x04, 0x99, 0x40, 0x1c, 0xc0, 0xb2, 0x03, 0x90, -0x88, 0x42, 0xb0, 0xd3, 0x05, 0xf0, 0xa0, 0xfb, 0x02, 0xf0, 0x44, 0xfb, 0x05, 0xf0, 0x16, 0xfb, -0x36, 0x49, 0x01, 0x20, 0x48, 0x74, 0x04, 0xf0, 0x97, 0xfe, 0x32, 0x48, 0xa9, 0x79, 0xc0, 0x7b, -0x81, 0x42, 0x3e, 0xd2, 0x01, 0x20, 0xfc, 0xf7, 0xbb, 0xfc, 0x02, 0x90, 0x2e, 0x48, 0x01, 0x24, -0xc1, 0x79, 0x01, 0x29, 0x35, 0xd3, 0x2e, 0x48, 0x00, 0x90, 0x07, 0x98, 0x80, 0x08, 0x46, 0x42, -0x29, 0x48, 0x01, 0x23, 0x00, 0x7a, 0x01, 0x28, 0x25, 0xd3, 0x28, 0x21, 0x27, 0x46, 0x29, 0x48, -0x4f, 0x43, 0x38, 0x18, 0x01, 0x90, 0x24, 0x20, 0x02, 0x99, 0x60, 0x43, 0x45, 0x18, 0x00, 0x98, -0xc0, 0x7d, 0x80, 0x07, 0x03, 0xd5, 0x20, 0x48, 0x00, 0x7d, 0x02, 0x28, 0x2a, 0xd0, 0x58, 0x00, -0x29, 0x18, 0x40, 0x39, 0x1a, 0x22, 0x8a, 0x5e, 0x01, 0x99, 0x08, 0x5e, 0x10, 0x1a, 0xb0, 0x42, -0x03, 0xdd, 0x06, 0x98, 0x40, 0x1c, 0x80, 0xb2, 0x06, 0x90, 0x17, 0x48, 0x5b, 0x1c, 0x00, 0x7a, -0xdb, 0xb2, 0x98, 0x42, 0xe3, 0xd2, 0x14, 0x48, 0x64, 0x1c, 0xc0, 0x79, 0xe4, 0xb2, 0xa0, 0x42, -0xce, 0xd2, 0x11, 0x48, 0xc1, 0x79, 0x00, 0x7a, 0x41, 0x43, 0x06, 0x98, 0x81, 0x42, 0x00, 0xd0, -0x35, 0xe6, 0x0e, 0x48, 0x40, 0x79, 0x03, 0x28, 0xfa, 0xd0, 0x0a, 0x49, 0x01, 0x20, 0x88, 0x73, -0x15, 0xb0, 0xf0, 0xbd, 0x04, 0x20, 0xfc, 0xf7, 0x6b, 0xfc, 0x84, 0x46, 0x59, 0x00, 0x68, 0x18, -0x40, 0x38, 0x1a, 0x22, 0x82, 0x5e, 0x60, 0x46, 0x38, 0x18, 0x40, 0x5e, 0x10, 0x1a, 0xb0, 0x42, -0xcf, 0xdc, 0xd2, 0xe7, 0xcc, 0x00, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, -0xe8, 0x0d, 0x01, 0x20, 0x00, 0x40, 0x01, 0x20, 0x70, 0x47, 0x00, 0x00, 0x10, 0xb5, 0x45, 0x22, -0xd2, 0x00, 0x02, 0x49, 0x02, 0x48, 0xf7, 0xf7, 0x9f, 0xf9, 0x10, 0xbd, 0x1c, 0xec, 0x00, 0x00, -0xa8, 0x0c, 0x01, 0x20, 0xf0, 0xb5, 0x45, 0x49, 0x87, 0xb0, 0x00, 0x20, 0x08, 0x67, 0x48, 0x67, -0x0a, 0x46, 0x88, 0x67, 0x70, 0x32, 0xc8, 0x67, 0x10, 0x61, 0x50, 0x61, 0x90, 0x61, 0xd0, 0x61, -0x10, 0x62, 0x3f, 0x48, 0x01, 0x7a, 0x0a, 0x02, 0x3e, 0x49, 0x0a, 0x81, 0x04, 0x92, 0xc3, 0x79, -0x3d, 0x48, 0x44, 0x7e, 0x00, 0x7e, 0x26, 0x02, 0x06, 0x43, 0x73, 0x43, 0x9f, 0xb2, 0x4f, 0x81, -0x3a, 0x49, 0x08, 0x7b, 0x4b, 0x7b, 0x05, 0x93, 0xc3, 0x18, 0xff, 0x3b, 0x01, 0x3b, 0xd2, 0x18, -0x94, 0xb2, 0x8a, 0x7b, 0x03, 0x92, 0xc9, 0x7b, 0x02, 0x91, 0x51, 0x18, 0xba, 0x1b, 0x51, 0x18, -0x8d, 0xb2, 0x33, 0x49, 0x01, 0x91, 0x4a, 0x7c, 0x0b, 0x7c, 0x11, 0x02, 0x19, 0x43, 0x80, 0x30, -0x48, 0x43, 0x00, 0x91, 0x00, 0x2c, 0x02, 0xd0, 0x21, 0x46, 0xf7, 0xf7, 0x67, 0xfa, 0x29, 0x49, -0x88, 0x81, 0x05, 0x98, 0x00, 0x99, 0x20, 0x1a, 0x80, 0x38, 0x48, 0x43, 0x00, 0x2c, 0x02, 0xd0, -0x21, 0x46, 0xf7, 0xf7, 0x5b, 0xfa, 0x23, 0x49, 0x26, 0x4c, 0xc8, 0x81, 0x70, 0x08, 0x03, 0x99, -0x00, 0x90, 0x08, 0x18, 0x61, 0x7c, 0x22, 0x7c, 0x0e, 0x02, 0x16, 0x43, 0x70, 0x43, 0x00, 0x2d, -0x02, 0xd0, 0x29, 0x46, 0xf7, 0xf7, 0x4a, 0xfa, 0x1a, 0x49, 0x08, 0x82, 0x00, 0x98, 0x29, 0x1a, -0x02, 0x98, 0x08, 0x1a, 0x70, 0x43, 0x00, 0x2d, 0x02, 0xd0, 0x29, 0x46, 0xf7, 0xf7, 0x3e, 0xfa, -0x14, 0x49, 0x48, 0x82, 0x18, 0x48, 0x42, 0x7f, 0x03, 0x7f, 0x10, 0x02, 0x18, 0x43, 0x88, 0x82, -0xc8, 0x82, 0x04, 0x9a, 0x12, 0x1a, 0x0a, 0x83, 0x38, 0x1a, 0x48, 0x83, 0x01, 0x98, 0x41, 0x7a, -0x00, 0x7a, 0x09, 0x02, 0x01, 0x43, 0x11, 0x48, 0x01, 0x80, 0x61, 0x79, 0x22, 0x79, 0x09, 0x02, -0x11, 0x43, 0x41, 0x80, 0x61, 0x7b, 0x22, 0x7b, 0x09, 0x02, 0x11, 0x43, 0x81, 0x80, 0x00, 0x21, -0x81, 0x71, 0x0b, 0x49, 0xc9, 0x7d, 0xc1, 0x71, 0x07, 0xb0, 0xf0, 0xbd, 0x14, 0x2e, 0x01, 0x20, -0xa8, 0x0c, 0x01, 0x20, 0x84, 0x2e, 0x01, 0x20, 0xa9, 0x0d, 0x01, 0x20, 0x48, 0x0d, 0x01, 0x20, -0x28, 0x0d, 0x01, 0x20, 0x2a, 0x0d, 0x01, 0x20, 0x4a, 0x0d, 0x01, 0x20, 0x1a, 0x01, 0x01, 0x20, -0x68, 0x0d, 0x01, 0x20, 0x01, 0x48, 0x01, 0x21, 0xc1, 0x73, 0x70, 0x47, 0x6c, 0x03, 0x01, 0x20, -0xf8, 0xb5, 0x0f, 0x46, 0x04, 0x46, 0x01, 0x78, 0x28, 0x20, 0x41, 0x43, 0x29, 0x48, 0x62, 0x78, -0x09, 0x18, 0x52, 0x00, 0x8a, 0x5e, 0xa1, 0x78, 0x28, 0x23, 0x59, 0x43, 0x08, 0x18, 0xe1, 0x78, -0x00, 0x26, 0x49, 0x00, 0x40, 0x5e, 0x82, 0x42, 0x04, 0xdd, 0x01, 0x22, 0x00, 0x21, 0x20, 0x46, -0x00, 0xf0, 0x6e, 0xf8, 0x02, 0x25, 0x02, 0x2f, 0x3a, 0xd9, 0x70, 0x00, 0x21, 0x5c, 0x28, 0x22, -0x51, 0x43, 0x00, 0x19, 0x1b, 0x4a, 0x40, 0x78, 0x89, 0x18, 0x40, 0x00, 0x09, 0x5e, 0x68, 0x00, -0x22, 0x5c, 0x28, 0x23, 0x5a, 0x43, 0x00, 0x19, 0x16, 0x4b, 0x40, 0x78, 0xd2, 0x18, 0x40, 0x00, -0x10, 0x5e, 0x81, 0x42, 0x00, 0xdd, 0x2e, 0x46, 0xad, 0x1c, 0xed, 0xb2, 0xbd, 0x42, 0xe4, 0xd3, -0x00, 0x2e, 0x1d, 0xd0, 0x32, 0x46, 0x00, 0x21, 0x20, 0x46, 0x00, 0xf0, 0x49, 0xf8, 0x70, 0x00, -0x22, 0x5c, 0x28, 0x21, 0x4a, 0x43, 0x00, 0x19, 0x0a, 0x49, 0x43, 0x78, 0x52, 0x18, 0x5b, 0x00, -0xd3, 0x5e, 0x82, 0x78, 0x28, 0x25, 0xc0, 0x78, 0x6a, 0x43, 0x51, 0x18, 0x40, 0x00, 0x08, 0x5e, -0x83, 0x42, 0x05, 0xdd, 0x70, 0x1c, 0xc2, 0xb2, 0x31, 0x46, 0x20, 0x46, 0x00, 0xf0, 0x30, 0xf8, -0xf8, 0xbd, 0x00, 0x00, 0x00, 0x50, 0x01, 0x20, 0xf0, 0xb4, 0x00, 0x24, 0x0d, 0x88, 0x23, 0x46, -0x00, 0x2d, 0x20, 0xd9, 0xc5, 0x5c, 0x00, 0x2d, 0x18, 0xd1, 0x5d, 0x00, 0x6e, 0x18, 0x65, 0x00, -0xad, 0x18, 0xb7, 0x78, 0xaf, 0x70, 0xf6, 0x78, 0xee, 0x70, 0x9c, 0x42, 0x0c, 0xd0, 0x0b, 0x4d, -0xe6, 0x00, 0x76, 0x19, 0xdf, 0x00, 0x7d, 0x19, 0xef, 0x8d, 0xf7, 0x85, 0x2f, 0x8e, 0x37, 0x86, -0x6f, 0x8e, 0x77, 0x86, 0xaf, 0x8e, 0xb7, 0x86, 0x64, 0x1c, 0xe4, 0xb2, 0x5b, 0x1c, 0x0d, 0x88, -0xdb, 0xb2, 0x9d, 0x42, 0xde, 0xd8, 0x14, 0x80, 0xf0, 0xbc, 0x70, 0x47, 0x44, 0x24, 0x01, 0x20, -0x49, 0x00, 0x10, 0xb4, 0x09, 0x18, 0x52, 0x00, 0x10, 0x18, 0x0b, 0x78, 0x4c, 0x78, 0x02, 0x78, -0x0a, 0x70, 0x42, 0x78, 0x4a, 0x70, 0x03, 0x70, 0x44, 0x70, 0x10, 0xbc, 0x70, 0x47, 0x00, 0x00, -0xff, 0xb5, 0x81, 0xb0, 0x05, 0x46, 0x04, 0x98, 0x14, 0x46, 0x0e, 0x46, 0x81, 0x42, 0x08, 0xd8, -0xa5, 0x42, 0x04, 0xd0, 0x4a, 0x00, 0x29, 0x46, 0x20, 0x46, 0xf7, 0xf7, 0xed, 0xf8, 0x05, 0xb0, -0xf0, 0xbd, 0xa5, 0x42, 0x04, 0xd0, 0x42, 0x00, 0x29, 0x46, 0x20, 0x46, 0xf7, 0xf7, 0xe4, 0xf8, -0x04, 0x99, 0x00, 0x20, 0x49, 0x1e, 0x8e, 0x46, 0x00, 0x29, 0x28, 0xdd, 0x41, 0x00, 0x62, 0x5c, -0x28, 0x23, 0x5a, 0x43, 0x26, 0x4b, 0x09, 0x19, 0xd2, 0x18, 0x4b, 0x78, 0x28, 0x27, 0x5b, 0x00, -0xd3, 0x5e, 0x8a, 0x78, 0xc9, 0x78, 0x7a, 0x43, 0x21, 0x4f, 0x49, 0x00, 0xd2, 0x19, 0x51, 0x5e, -0x8b, 0x42, 0x10, 0xdd, 0x02, 0x06, 0xd2, 0x0d, 0x12, 0x19, 0x41, 0x1c, 0x09, 0x06, 0x13, 0x78, -0xc9, 0x0d, 0x9c, 0x46, 0x09, 0x19, 0x53, 0x78, 0x0f, 0x78, 0x17, 0x70, 0x4f, 0x78, 0x57, 0x70, -0x62, 0x46, 0x0a, 0x70, 0x4b, 0x70, 0x80, 0x1c, 0x80, 0xb2, 0x70, 0x45, 0xd6, 0xdb, 0x20, 0x46, -0x04, 0x99, 0xff, 0xf7, 0x1d, 0xff, 0x04, 0x9f, 0xb7, 0x42, 0xc0, 0xd2, 0x78, 0x00, 0x29, 0x5c, -0x28, 0x22, 0x51, 0x43, 0x0e, 0x4a, 0x40, 0x19, 0x89, 0x18, 0x42, 0x78, 0x28, 0x23, 0x52, 0x00, -0x8a, 0x5e, 0x21, 0x78, 0x59, 0x43, 0x0a, 0x4b, 0xc9, 0x18, 0x63, 0x78, 0x5b, 0x00, 0xc9, 0x5e, -0x8a, 0x42, 0x07, 0xdd, 0x01, 0x78, 0x21, 0x70, 0x40, 0x78, 0x60, 0x70, 0x20, 0x46, 0x04, 0x99, -0xff, 0xf7, 0xfe, 0xfe, 0x7f, 0x1c, 0xbf, 0xb2, 0xb7, 0x42, 0xdf, 0xd3, 0x05, 0xb0, 0xf0, 0xbd, -0x00, 0x50, 0x01, 0x20, 0x10, 0xb5, 0x01, 0x20, 0x00, 0xf0, 0x28, 0xf8, 0x00, 0x28, 0x1d, 0xd0, -0x00, 0xf0, 0x6c, 0xf9, 0x00, 0x28, 0x19, 0xd0, 0x00, 0xf0, 0x6d, 0xf9, 0x00, 0x28, 0x15, 0xd0, -0x00, 0xf0, 0x6e, 0xf9, 0x00, 0x28, 0x11, 0xd0, 0x00, 0xf0, 0x70, 0xf9, 0x00, 0x28, 0x0d, 0xd0, -0x00, 0xf0, 0xfa, 0xf9, 0x00, 0x28, 0x09, 0xd0, 0x00, 0xf0, 0xfb, 0xf9, 0x00, 0x28, 0x05, 0xd0, -0x00, 0xf0, 0xb6, 0xf8, 0x00, 0x28, 0x01, 0xd0, 0x00, 0xf0, 0x3c, 0xf9, 0x10, 0xbd, 0x10, 0xb5, -0xfe, 0xf7, 0x28, 0xfb, 0x04, 0xf0, 0x08, 0xfa, 0x10, 0xbd, 0x00, 0x00, 0xf0, 0xb5, 0x87, 0xb0, -0x06, 0x46, 0xfb, 0xf7, 0x83, 0xf9, 0x48, 0x4f, 0xf8, 0x7e, 0xc0, 0x07, 0x74, 0xd0, 0x47, 0x48, -0x80, 0x7d, 0x01, 0x28, 0x70, 0xd0, 0x46, 0x49, 0x78, 0x7f, 0x3b, 0x7f, 0x4a, 0x8c, 0x00, 0x02, -0x18, 0x43, 0x82, 0x42, 0x04, 0xd2, 0x24, 0x22, 0x8a, 0x5e, 0x40, 0x42, 0x82, 0x42, 0x78, 0xdc, -0x01, 0x20, 0x00, 0x90, 0x3f, 0x48, 0x00, 0x25, 0xc1, 0x79, 0x01, 0x29, 0x71, 0xd3, 0x3f, 0x48, -0x01, 0x90, 0x3d, 0x49, 0x3e, 0x48, 0x05, 0x91, 0x04, 0x90, 0x3a, 0x48, 0x01, 0x24, 0x00, 0x7a, -0x01, 0x28, 0x5d, 0xd3, 0x00, 0x98, 0x3b, 0x49, 0x24, 0x22, 0x50, 0x43, 0x41, 0x18, 0x03, 0x91, -0x39, 0x49, 0x40, 0x18, 0x02, 0x90, 0x05, 0x98, 0x00, 0x7a, 0x01, 0x28, 0x24, 0xd0, 0x02, 0x98, -0x61, 0x00, 0x40, 0x18, 0x40, 0x38, 0x1a, 0x21, 0x41, 0x5e, 0x01, 0x98, 0x42, 0x7a, 0x03, 0x7a, -0x10, 0x06, 0x00, 0x14, 0x18, 0x43, 0x08, 0x1a, 0x00, 0xd5, 0x40, 0x42, 0x79, 0x7f, 0x3a, 0x7f, -0x09, 0x02, 0x11, 0x43, 0x88, 0x42, 0x01, 0xdd, 0x6d, 0x1c, 0xad, 0xb2, 0x04, 0x98, 0x41, 0x7f, -0x02, 0x7f, 0x08, 0x02, 0x10, 0x43, 0xa8, 0x42, 0x2c, 0xd2, 0x01, 0x2e, 0x1a, 0xd0, 0x02, 0x2e, -0x23, 0xd0, 0x03, 0x2e, 0x24, 0xd0, 0x25, 0xe0, 0x03, 0x98, 0x61, 0x00, 0x40, 0x18, 0x40, 0x38, -0x1a, 0x21, 0x41, 0x5e, 0x01, 0x98, 0x42, 0x7a, 0x03, 0x7a, 0x10, 0x06, 0x00, 0x14, 0x18, 0x43, -0x08, 0x1a, 0x00, 0xd5, 0x40, 0x42, 0x79, 0x7f, 0x3a, 0x7f, 0x09, 0x02, 0x11, 0x43, 0x88, 0x42, -0xda, 0xdc, 0xdb, 0xe7, 0x19, 0x48, 0x52, 0x21, 0x01, 0x70, 0x53, 0x21, 0x41, 0x70, 0x54, 0x21, -0x81, 0x70, 0xfa, 0xf7, 0x0b, 0xfb, 0x05, 0xe0, 0x13, 0xe0, 0x04, 0xf0, 0x9f, 0xfa, 0x01, 0xe0, -0xfe, 0xf7, 0x0a, 0xf9, 0x0b, 0x48, 0x64, 0x1c, 0x00, 0x7a, 0xe4, 0xb2, 0xa0, 0x42, 0xaa, 0xd2, -0x00, 0x98, 0x40, 0x1c, 0xc0, 0xb2, 0x00, 0x90, 0x06, 0x48, 0xc1, 0x79, 0x00, 0x98, 0x81, 0x42, -0x93, 0xd2, 0x01, 0x20, 0x07, 0xb0, 0xf0, 0xbd, 0xa8, 0x0d, 0x01, 0x20, 0xe8, 0x0d, 0x01, 0x20, -0x84, 0x2d, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0x6c, 0x03, 0x01, 0x20, 0xe9, 0x0c, 0x01, 0x20, -0xaa, 0x0d, 0x01, 0x20, 0x00, 0x20, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0xf0, 0x3f, 0x01, 0x20, -0xf0, 0xb5, 0x3f, 0x48, 0x9f, 0xb0, 0xc0, 0x7e, 0x40, 0x06, 0x76, 0xd5, 0x00, 0x20, 0x16, 0x90, -0x17, 0x90, 0x18, 0x90, 0x19, 0x90, 0x1a, 0x90, 0x1b, 0x90, 0x58, 0x21, 0x68, 0x46, 0xf7, 0xf7, -0x0b, 0xf8, 0x38, 0x48, 0x00, 0x68, 0x1d, 0x90, 0x00, 0x20, 0x1c, 0x90, 0x36, 0x48, 0xc4, 0x8b, -0x00, 0x2c, 0x5d, 0xd0, 0x00, 0x27, 0x00, 0x2c, 0x32, 0xd9, 0x34, 0x48, 0x79, 0x00, 0x09, 0x18, -0xe0, 0x31, 0x00, 0x20, 0x08, 0x56, 0x01, 0x25, 0x42, 0x1e, 0x4d, 0x57, 0x40, 0x1c, 0x00, 0x21, -0xd3, 0xb2, 0x86, 0x46, 0x73, 0x45, 0x18, 0xdc, 0x68, 0x1e, 0x84, 0x46, 0x6d, 0x1c, 0x60, 0x46, -0xc0, 0xb2, 0xa8, 0x42, 0x0d, 0xdc, 0x1a, 0x46, 0x28, 0x26, 0x72, 0x43, 0x1d, 0x9e, 0x96, 0x19, -0x42, 0x00, 0xb2, 0x5e, 0x00, 0x2a, 0x00, 0xdd, 0x51, 0x18, 0x40, 0x1c, 0xc0, 0xb2, 0xa8, 0x42, -0xf6, 0xdd, 0x5b, 0x1c, 0xdb, 0xb2, 0x73, 0x45, 0xe9, 0xdd, 0x1c, 0x98, 0x88, 0x42, 0x00, 0xd2, -0x1c, 0x91, 0xba, 0x00, 0x7f, 0x1c, 0x68, 0x46, 0xff, 0xb2, 0x81, 0x50, 0xbc, 0x42, 0xcc, 0xd8, -0x00, 0x25, 0x00, 0x2c, 0x24, 0xd9, 0x19, 0x4f, 0x25, 0x20, 0x80, 0x01, 0x38, 0x18, 0x40, 0x8c, -0x46, 0x08, 0x68, 0x00, 0xc0, 0x19, 0xe0, 0x30, 0x00, 0x21, 0x01, 0x22, 0x41, 0x56, 0x82, 0x56, -0x28, 0x20, 0x41, 0x43, 0x1d, 0x98, 0x08, 0x18, 0x51, 0x00, 0x40, 0x5e, 0xb0, 0x42, 0x0b, 0xda, -0x03, 0x21, 0x1c, 0x98, 0xf6, 0xf7, 0xb2, 0xff, 0xaa, 0x00, 0x69, 0x46, 0x89, 0x58, 0x88, 0x42, -0x02, 0xd9, 0x01, 0x20, 0x16, 0xa9, 0x48, 0x55, 0x6d, 0x1c, 0xed, 0xb2, 0xac, 0x42, 0xe0, 0xd8, -0x07, 0x4a, 0x16, 0xa8, 0x11, 0x46, 0xff, 0xf7, 0xff, 0xfd, 0x01, 0x20, 0x1f, 0xb0, 0xf0, 0xbd, -0xa8, 0x0d, 0x01, 0x20, 0xac, 0x1b, 0x01, 0x20, 0x04, 0x25, 0x01, 0x20, 0x44, 0x24, 0x01, 0x20, -0x22, 0x25, 0x01, 0x20, 0x10, 0xb5, 0x07, 0x4c, 0xe0, 0x8b, 0x0b, 0x28, 0x07, 0xd9, 0x06, 0x4a, -0xc1, 0xb2, 0x0b, 0x23, 0x10, 0x46, 0xff, 0xf7, 0x23, 0xfe, 0x0b, 0x20, 0xe0, 0x83, 0x01, 0x20, -0x10, 0xbd, 0x00, 0x00, 0x04, 0x25, 0x01, 0x20, 0x24, 0x25, 0x01, 0x20, 0x10, 0xb5, 0xfe, 0xf7, -0xd9, 0xf9, 0x01, 0x20, 0x10, 0xbd, 0x10, 0xb5, 0xff, 0xf7, 0xa4, 0xf8, 0x01, 0x20, 0x10, 0xbd, -0x10, 0xb5, 0x04, 0xf0, 0xb1, 0xf8, 0x01, 0x20, 0x10, 0xbd, 0x00, 0x00, 0xf0, 0xb5, 0x89, 0xb0, -0x3e, 0x48, 0x07, 0x90, 0xc0, 0x7f, 0x00, 0x28, 0x75, 0xd0, 0x00, 0x20, 0x00, 0x90, 0x01, 0x90, -0x02, 0x90, 0x03, 0x90, 0x04, 0x90, 0x04, 0x46, 0x05, 0x90, 0x39, 0x48, 0x06, 0x90, 0xc0, 0x8b, -0x00, 0x28, 0x63, 0xd9, 0x68, 0x46, 0x00, 0x5d, 0x00, 0x28, 0x59, 0xd1, 0x35, 0x4f, 0x60, 0x00, -0xc5, 0x19, 0xe0, 0x35, 0x28, 0x78, 0x28, 0x21, 0x84, 0x46, 0x48, 0x43, 0x32, 0x4e, 0x69, 0x78, -0x80, 0x19, 0x4a, 0x00, 0x80, 0x5e, 0x4d, 0x22, 0x50, 0x43, 0x07, 0x9b, 0xc2, 0x11, 0x58, 0x7a, -0x1b, 0x7a, 0x00, 0x02, 0x03, 0x43, 0x93, 0x42, 0x00, 0xdd, 0x1a, 0x46, 0x2a, 0x4b, 0x12, 0xb2, -0x60, 0x46, 0x02, 0xf0, 0xd3, 0xf9, 0x29, 0x48, 0x80, 0x8d, 0x14, 0x28, 0x38, 0xd3, 0x06, 0x99, -0x60, 0x1c, 0xc9, 0x8b, 0xc0, 0xb2, 0x8c, 0x46, 0x81, 0x42, 0x31, 0xd9, 0x21, 0x49, 0x42, 0x00, -0x51, 0x18, 0xe0, 0x31, 0x0a, 0x78, 0x4b, 0x78, 0x51, 0x1e, 0x12, 0x26, 0x71, 0x43, 0x49, 0x1e, -0x59, 0x18, 0x1f, 0x4e, 0xcf, 0x10, 0xf6, 0x5d, 0xcf, 0x17, 0x7f, 0x0f, 0x7f, 0x18, 0xff, 0x08, -0xff, 0x00, 0xcf, 0x1b, 0x01, 0x21, 0xb9, 0x40, 0x0e, 0x42, 0x15, 0xd0, 0x29, 0x78, 0x28, 0x26, -0x71, 0x43, 0x15, 0x4e, 0x6f, 0x78, 0x89, 0x19, 0x7f, 0x00, 0xc9, 0x5f, 0x28, 0x27, 0x7a, 0x43, -0x92, 0x19, 0x5b, 0x00, 0xd2, 0x5e, 0x91, 0x42, 0x03, 0xdd, 0x01, 0x21, 0x6a, 0x46, 0x11, 0x54, -0x02, 0xe0, 0x01, 0x21, 0x6a, 0x46, 0x11, 0x55, 0x40, 0x1c, 0xc0, 0xb2, 0x84, 0x45, 0xcd, 0xd8, -0x06, 0x98, 0x64, 0x1c, 0xc0, 0x8b, 0xe4, 0xb2, 0xa0, 0x42, 0x9b, 0xd8, 0x09, 0x4a, 0x68, 0x46, -0x11, 0x46, 0xff, 0xf7, 0x51, 0xfd, 0x01, 0x20, 0x09, 0xb0, 0xf0, 0xbd, 0x28, 0x0d, 0x01, 0x20, -0x04, 0x25, 0x01, 0x20, 0x44, 0x24, 0x01, 0x20, 0x00, 0x50, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, -0x78, 0x34, 0x01, 0x20, 0x22, 0x25, 0x01, 0x20, 0x10, 0xb5, 0xf8, 0xf7, 0x27, 0xfb, 0x01, 0x20, -0x10, 0xbd, 0x10, 0xb5, 0xfa, 0xf7, 0x10, 0xfe, 0x01, 0x20, 0x10, 0xbd, 0xf8, 0xb5, 0x01, 0x21, -0x0a, 0x20, 0xfc, 0xf7, 0x9f, 0xfb, 0x00, 0x20, 0x02, 0xf0, 0xa0, 0xfb, 0x0a, 0x20, 0xfc, 0xf7, -0x57, 0xfb, 0xfc, 0xf7, 0x35, 0xf9, 0x7d, 0x21, 0xc9, 0x00, 0xf6, 0xf7, 0xc7, 0xfe, 0x03, 0xf0, -0x8d, 0xfb, 0x28, 0x48, 0x28, 0x4c, 0x40, 0x7f, 0x01, 0x28, 0x0a, 0xd0, 0x02, 0x28, 0x0f, 0xd0, -0xfc, 0xf7, 0x3c, 0xfb, 0x25, 0x4f, 0x26, 0x4d, 0x38, 0x7d, 0x26, 0x4e, 0x03, 0x28, 0x0f, 0xd0, -0x18, 0xe0, 0xfd, 0xf7, 0x53, 0xfc, 0x60, 0x7d, 0x05, 0x28, 0xf3, 0xd1, 0x02, 0x20, 0x05, 0xe0, -0x03, 0xf0, 0x5e, 0xf9, 0x60, 0x7d, 0x02, 0x28, 0xec, 0xd1, 0x05, 0x20, 0x60, 0x75, 0xe9, 0xe7, -0xa9, 0x7e, 0x1d, 0x48, 0xf6, 0xf7, 0xa2, 0xfe, 0x1c, 0x49, 0x48, 0x43, 0x1a, 0x49, 0xf6, 0xf7, -0x9d, 0xfe, 0x70, 0x61, 0xfe, 0xf7, 0x08, 0xf8, 0xe0, 0x7d, 0xc0, 0x09, 0x02, 0xd0, 0x04, 0xf0, -0x65, 0xff, 0x01, 0xe0, 0x04, 0xf0, 0x4e, 0xff, 0x38, 0x7d, 0x03, 0x28, 0x16, 0xd1, 0x12, 0x4c, -0xa9, 0x7e, 0x20, 0x46, 0xf6, 0xf7, 0x8a, 0xfe, 0x31, 0x69, 0x03, 0x22, 0x11, 0x43, 0x31, 0x61, -0x01, 0x25, 0x0f, 0x4a, 0x69, 0x03, 0x11, 0x60, 0x00, 0x21, 0xb1, 0x61, 0x0b, 0x49, 0x48, 0x43, -0x21, 0x46, 0xf6, 0xf7, 0x7b, 0xfe, 0x70, 0x61, 0x0a, 0x48, 0x85, 0x70, 0x02, 0xf0, 0x2a, 0xfc, -0xf8, 0xbd, 0x00, 0x00, 0x08, 0x0e, 0x01, 0x20, 0xe8, 0x0d, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, -0x68, 0x0d, 0x01, 0x20, 0x00, 0x20, 0x03, 0x40, 0xa0, 0x86, 0x01, 0x00, 0x40, 0x42, 0x0f, 0x00, -0x00, 0xe1, 0x00, 0xe0, 0x18, 0x00, 0x01, 0x20, 0xf0, 0xb5, 0xa8, 0x48, 0x42, 0x23, 0xc1, 0x7f, -0xa7, 0x4e, 0x82, 0x7f, 0x4b, 0x43, 0x90, 0xb0, 0x9b, 0x19, 0x00, 0x93, 0x42, 0x23, 0x53, 0x43, -0x9b, 0x19, 0x9c, 0x46, 0x6e, 0x23, 0x5a, 0x43, 0x33, 0x46, 0xd7, 0x18, 0x00, 0x24, 0x6e, 0x22, -0x51, 0x43, 0x1a, 0x46, 0x89, 0x18, 0x25, 0x46, 0x20, 0x46, 0x05, 0x91, 0x9c, 0x49, 0x0a, 0x18, -0x09, 0x21, 0x09, 0x02, 0x51, 0x18, 0x89, 0x7d, 0x02, 0x29, 0x03, 0xd0, 0x03, 0x29, 0x01, 0xd0, -0x01, 0x29, 0x25, 0xd1, 0x0a, 0x21, 0x05, 0x9a, 0x41, 0x43, 0x53, 0x18, 0x31, 0x22, 0x52, 0x01, -0x9a, 0x18, 0x96, 0x7f, 0x00, 0x2e, 0x1b, 0xd1, 0x02, 0x26, 0x96, 0x77, 0x19, 0x26, 0xb6, 0x01, -0x79, 0x18, 0x89, 0x19, 0x0a, 0x88, 0x9b, 0x19, 0x1a, 0x80, 0x49, 0x88, 0x59, 0x80, 0x37, 0x21, -0x09, 0x01, 0x99, 0x80, 0x06, 0x21, 0x00, 0x9a, 0x41, 0x43, 0x52, 0x18, 0x89, 0x4b, 0x61, 0x44, -0xd2, 0x18, 0xc9, 0x18, 0x8b, 0x8a, 0x93, 0x82, 0xcb, 0x8a, 0xd3, 0x82, 0x09, 0x8b, 0x11, 0x83, -0x40, 0x1c, 0xc0, 0xb2, 0x0b, 0x28, 0xc9, 0xd3, 0x83, 0x48, 0x0f, 0x90, 0x83, 0x48, 0xb9, 0x22, -0x12, 0x5c, 0x0e, 0x92, 0x82, 0x4a, 0x83, 0x4b, 0x0d, 0x92, 0x1a, 0x89, 0x00, 0x21, 0x16, 0x46, -0x80, 0x3a, 0x92, 0xb2, 0xff, 0x3e, 0x0b, 0x92, 0x81, 0x3e, 0xff, 0x22, 0x0c, 0x96, 0x59, 0x32, -0x12, 0x5c, 0xff, 0x30, 0x02, 0x30, 0x0a, 0x92, 0x42, 0x7e, 0x06, 0x7e, 0x10, 0x02, 0x30, 0x43, -0x42, 0x08, 0x09, 0x92, 0x42, 0x00, 0x04, 0x92, 0x58, 0x89, 0x80, 0x1a, 0x08, 0x90, 0x70, 0x4a, -0x09, 0x20, 0x53, 0x18, 0x00, 0x02, 0x1b, 0x18, 0x98, 0x7d, 0x01, 0x28, 0x03, 0xd0, 0x02, 0x28, -0x01, 0xd0, 0x03, 0x28, 0x78, 0xd1, 0xd8, 0x7a, 0x06, 0x90, 0x08, 0x46, 0x0a, 0x27, 0x78, 0x43, -0x05, 0x9e, 0x03, 0x90, 0x30, 0x18, 0x31, 0x26, 0x84, 0x46, 0x76, 0x01, 0x80, 0x19, 0x80, 0x7f, -0x02, 0x28, 0x01, 0xd1, 0x0f, 0x98, 0x85, 0x72, 0x98, 0x7d, 0x01, 0x28, 0x16, 0xd0, 0x0c, 0x20, -0x68, 0x43, 0x87, 0x18, 0x11, 0x20, 0x80, 0x01, 0x19, 0x22, 0x38, 0x18, 0x92, 0x01, 0x81, 0x76, -0x62, 0x44, 0x16, 0x88, 0x86, 0x83, 0x56, 0x88, 0xc6, 0x83, 0x92, 0x88, 0x02, 0x84, 0x5e, 0x4a, -0x23, 0x20, 0x62, 0x44, 0x40, 0x01, 0x38, 0x18, 0x92, 0x88, 0x7f, 0xe0, 0x0c, 0x20, 0x54, 0x4a, -0x68, 0x43, 0x80, 0x18, 0x11, 0x22, 0x92, 0x01, 0x82, 0x18, 0x02, 0x90, 0x91, 0x76, 0x0e, 0x98, -0x00, 0x28, 0x5a, 0xd0, 0x0d, 0x98, 0x00, 0x79, 0x01, 0x28, 0x56, 0xd1, 0x06, 0x9e, 0x6e, 0x20, -0x46, 0x43, 0x4b, 0x48, 0x36, 0x18, 0x03, 0x98, 0x36, 0x18, 0x19, 0x20, 0x80, 0x01, 0x30, 0x18, -0x00, 0x26, 0x86, 0x5f, 0xb6, 0x46, 0x02, 0x26, 0x86, 0x5f, 0x01, 0x96, 0x19, 0x26, 0xb6, 0x01, -0x66, 0x44, 0x07, 0x96, 0x37, 0x88, 0x76, 0x46, 0xf6, 0x1b, 0x00, 0xd5, 0x76, 0x42, 0x36, 0xb2, -0x00, 0x96, 0x07, 0x9e, 0x77, 0x88, 0x01, 0x9e, 0xf6, 0x1b, 0x00, 0xd5, 0x76, 0x42, 0x36, 0xb2, -0x01, 0x96, 0x01, 0x27, 0x00, 0x9e, 0xbf, 0x02, 0xbe, 0x42, 0x02, 0xdc, 0x01, 0x9e, 0xbe, 0x42, -0x01, 0xdd, 0x00, 0x24, 0x44, 0xe0, 0x00, 0x9e, 0x64, 0x2e, 0x02, 0xdc, 0x01, 0x9e, 0x64, 0x2e, -0x23, 0xdd, 0x01, 0x9f, 0x00, 0x9e, 0xbe, 0x42, 0x0d, 0xdd, 0x06, 0x88, 0xff, 0x27, 0x81, 0x37, -0xbe, 0x42, 0x02, 0xd8, 0x80, 0x24, 0x04, 0xe0, 0x4f, 0xe0, 0x0c, 0x9f, 0xbe, 0x42, 0x14, 0xdb, -0x0b, 0x9c, 0x04, 0x80, 0x0f, 0xe0, 0x0a, 0x9e, 0x36, 0x07, 0x06, 0xd4, 0x47, 0x88, 0x04, 0x9e, -0xb7, 0x42, 0x0a, 0xd8, 0x09, 0x9c, 0x44, 0x80, 0x05, 0xe0, 0x08, 0x9e, 0x47, 0x88, 0xb6, 0xb2, -0xb7, 0x42, 0x02, 0xd3, 0x46, 0x80, 0x01, 0x24, 0x01, 0xe0, 0x00, 0x2c, 0x18, 0xd0, 0x06, 0x98, -0x6e, 0x26, 0x70, 0x43, 0x1e, 0x4e, 0x86, 0x19, 0x03, 0x98, 0x36, 0x18, 0x19, 0x20, 0x80, 0x01, -0x30, 0x18, 0x07, 0x88, 0x97, 0x83, 0x47, 0x88, 0xd7, 0x83, 0x80, 0x88, 0x10, 0x84, 0x1e, 0x48, -0x23, 0x22, 0x36, 0x18, 0x02, 0x98, 0x52, 0x01, 0x80, 0x18, 0xb2, 0x88, 0x82, 0x80, 0x11, 0xe0, -0x19, 0x20, 0x80, 0x01, 0x60, 0x44, 0x06, 0x88, 0x96, 0x83, 0x46, 0x88, 0xd6, 0x83, 0x80, 0x88, -0x10, 0x84, 0x15, 0x4a, 0x60, 0x46, 0x86, 0x18, 0x23, 0x20, 0x02, 0x9a, 0x40, 0x01, 0x10, 0x18, -0xb2, 0x88, 0x82, 0x80, 0xd8, 0x7a, 0x18, 0x70, 0x40, 0x1c, 0xc0, 0xb2, 0xd8, 0x72, 0x04, 0x28, -0x01, 0xd3, 0x00, 0x20, 0xd8, 0x72, 0x6d, 0x1c, 0xed, 0xb2, 0x49, 0x1c, 0xc9, 0xb2, 0x0b, 0x29, -0x00, 0xd2, 0x24, 0xe7, 0x09, 0x48, 0x05, 0x76, 0x10, 0xb0, 0xf0, 0xbd, 0x24, 0x2d, 0x01, 0x20, -0x44, 0x24, 0x01, 0x20, 0xe2, 0x07, 0x00, 0x00, 0xa4, 0x2d, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, -0x84, 0x26, 0x01, 0x20, 0x84, 0x2e, 0x01, 0x20, 0x42, 0x06, 0x00, 0x00, 0x84, 0x28, 0x01, 0x20, -0xf8, 0xb5, 0x57, 0x4f, 0x78, 0x7b, 0x57, 0x4d, 0x00, 0x28, 0x0a, 0xd1, 0xfb, 0xf7, 0x20, 0xff, -0x01, 0x28, 0x0c, 0xd0, 0xfb, 0xf7, 0x1c, 0xff, 0x00, 0x28, 0x08, 0xd0, 0x68, 0x79, 0x02, 0x28, -0x05, 0xd0, 0x01, 0xf0, 0x53, 0xf8, 0x28, 0x78, 0x00, 0x28, 0x03, 0xd0, 0x08, 0xe0, 0xff, 0xf7, -0xe1, 0xfa, 0xf8, 0xe7, 0x68, 0x79, 0x00, 0x28, 0x27, 0xd0, 0x68, 0x79, 0x01, 0x28, 0x24, 0xd0, -0x68, 0x79, 0x49, 0x4c, 0x02, 0x28, 0x24, 0xd0, 0x46, 0x48, 0x40, 0x79, 0x03, 0x28, 0x1f, 0xd1, -0x46, 0x4d, 0x28, 0x68, 0x80, 0x08, 0x80, 0x00, 0x28, 0x60, 0x45, 0x4e, 0xa8, 0x14, 0x30, 0x60, -0xfb, 0xf7, 0xf6, 0xfe, 0x00, 0x28, 0x02, 0xd0, 0x78, 0x7b, 0x00, 0x28, 0x10, 0xd0, 0xe0, 0x7d, -0x40, 0x4c, 0x81, 0x06, 0x40, 0x48, 0x02, 0xd5, 0x01, 0x7d, 0x01, 0x29, 0x12, 0xd0, 0x00, 0x7d, -0x03, 0x28, 0x3f, 0xd0, 0x00, 0x28, 0x3d, 0xd0, 0x11, 0xe0, 0x3c, 0x48, 0xfd, 0xf7, 0xd2, 0xfd, -0xf8, 0xbd, 0xfd, 0xf7, 0x6d, 0xf9, 0x20, 0x7e, 0xc0, 0x07, 0xf9, 0xd0, 0x38, 0x49, 0x00, 0x20, -0x88, 0x80, 0xf8, 0xbd, 0x28, 0x69, 0x80, 0x08, 0x80, 0x00, 0x28, 0x61, 0x34, 0x60, 0xfc, 0xf7, -0xe7, 0xfa, 0x34, 0x4d, 0x00, 0x24, 0x68, 0x78, 0x00, 0x28, 0x13, 0xdd, 0x32, 0x4e, 0x33, 0x4f, -0xf1, 0x7c, 0x38, 0x46, 0xf6, 0xf7, 0x9a, 0xfc, 0x01, 0x46, 0x00, 0x20, 0x00, 0x29, 0x03, 0xd9, -0x00, 0xbf, 0x40, 0x1c, 0x88, 0x42, 0xfb, 0xd3, 0x04, 0xf0, 0x52, 0xfd, 0x68, 0x78, 0x64, 0x1c, -0xa0, 0x42, 0xed, 0xdc, 0xf7, 0xf7, 0x12, 0xfe, 0xf7, 0xf7, 0x9a, 0xfd, 0x28, 0x4c, 0x01, 0x20, -0x20, 0x73, 0x1c, 0x4e, 0x70, 0x79, 0x03, 0x28, 0xd3, 0xd1, 0x00, 0x27, 0x20, 0x7b, 0x01, 0x28, -0x08, 0xd0, 0x0d, 0xe0, 0x04, 0xf0, 0x6a, 0xfc, 0x22, 0x48, 0x81, 0x7c, 0xcf, 0x22, 0x11, 0x40, -0x81, 0x74, 0xc7, 0xe7, 0x20, 0xa0, 0x04, 0xf0, 0xe3, 0xff, 0xa7, 0x76, 0xfc, 0xf7, 0x3c, 0xfb, -0x20, 0x7b, 0x02, 0x28, 0x04, 0xd1, 0xe8, 0x7d, 0x00, 0x28, 0x05, 0xd0, 0x03, 0x20, 0x20, 0x73, -0x20, 0x7b, 0x03, 0x28, 0x08, 0xd0, 0x0e, 0xe0, 0x19, 0xa0, 0x04, 0xf0, 0xd1, 0xff, 0xfc, 0xf7, -0xed, 0xfb, 0x00, 0x28, 0xad, 0xd0, 0xf3, 0xe7, 0x17, 0xa0, 0x04, 0xf0, 0xc9, 0xff, 0xfc, 0xf7, -0x95, 0xfc, 0x00, 0x28, 0xa5, 0xd0, 0x70, 0x79, 0x03, 0x28, 0xcf, 0xd0, 0xf8, 0xbd, 0x00, 0x00, -0x6c, 0x03, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, 0xe8, 0x0d, 0x01, 0x20, 0x00, 0x20, 0x03, 0x40, -0x80, 0xe1, 0x00, 0xe0, 0x00, 0x20, 0x00, 0x00, 0xa8, 0x0c, 0x01, 0x20, 0x06, 0x00, 0x01, 0x20, -0x02, 0x00, 0x01, 0x20, 0x48, 0x0d, 0x01, 0x20, 0x20, 0x00, 0x03, 0x40, 0xf0, 0x50, 0x00, 0x00, -0x8c, 0x03, 0x01, 0x20, 0x00, 0x50, 0x03, 0x40, 0x53, 0x54, 0x45, 0x50, 0x20, 0x31, 0x0a, 0x00, -0x53, 0x54, 0x45, 0x50, 0x20, 0x32, 0x0a, 0x00, 0x53, 0x54, 0x45, 0x50, 0x20, 0x33, 0x0a, 0x00, -0xf8, 0xb5, 0x3b, 0x4e, 0xf0, 0x7d, 0xc0, 0x06, 0x0b, 0xd5, 0x3a, 0x4a, 0x01, 0x21, 0x50, 0x8a, -0x39, 0x4c, 0x00, 0x28, 0x00, 0xd1, 0x61, 0x73, 0x38, 0x4b, 0x1b, 0x78, 0x00, 0x2b, 0x01, 0xd0, -0x51, 0x82, 0xf8, 0xbd, 0x40, 0x1c, 0x50, 0x82, 0x60, 0x7b, 0x00, 0x28, 0xf9, 0xd0, 0x01, 0xf0, -0x01, 0xfd, 0x33, 0x48, 0x81, 0x7f, 0x40, 0x7f, 0x0d, 0x02, 0x05, 0x43, 0x29, 0x46, 0x31, 0x48, -0xf6, 0xf7, 0x04, 0xfc, 0x01, 0x46, 0x30, 0x48, 0x72, 0x7b, 0x43, 0x7c, 0x07, 0x7c, 0x18, 0x02, -0x38, 0x43, 0x10, 0x1a, 0x64, 0x22, 0x50, 0x43, 0xf6, 0xf7, 0x06, 0xfc, 0x31, 0x7c, 0x2b, 0x4f, -0x40, 0x1a, 0xb8, 0x80, 0x2a, 0x49, 0xc8, 0x73, 0xfb, 0xf7, 0x18, 0xff, 0x7d, 0x21, 0x09, 0x01, -0x69, 0x43, 0xf6, 0xf7, 0xeb, 0xfb, 0xf8, 0x80, 0x01, 0xf0, 0x04, 0xfc, 0x04, 0xf0, 0xd6, 0xfb, -0x24, 0x4d, 0x01, 0x20, 0xfb, 0xf7, 0x84, 0xfd, 0xf1, 0x7d, 0xc9, 0x06, 0x15, 0xd5, 0x01, 0x22, -0x24, 0x23, 0x53, 0x43, 0x1f, 0x18, 0x14, 0x23, 0x01, 0x21, 0x53, 0x43, 0x5b, 0x19, 0x4e, 0x00, -0xbe, 0x19, 0x40, 0x3e, 0x76, 0x8b, 0x36, 0x11, 0x5e, 0x54, 0x49, 0x1c, 0xc9, 0xb2, 0x12, 0x29, -0xf5, 0xd9, 0x52, 0x1c, 0xd2, 0xb2, 0x20, 0x2a, 0xea, 0xd9, 0x00, 0x20, 0x60, 0x73, 0x01, 0xf0, -0xb9, 0xfc, 0x0f, 0x48, 0x11, 0x4c, 0x01, 0x7e, 0xc2, 0x7d, 0x08, 0x02, 0x10, 0x43, 0xa0, 0x80, -0x0f, 0x49, 0xc8, 0x73, 0xfb, 0xf7, 0xe2, 0xfe, 0x09, 0x49, 0x8a, 0x7d, 0x4b, 0x7d, 0x11, 0x02, -0x7d, 0x22, 0x19, 0x43, 0x12, 0x01, 0x51, 0x43, 0xf6, 0xf7, 0xb0, 0xfb, 0xe0, 0x80, 0xf8, 0xbd, -0xe8, 0x0d, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, 0x8c, 0x03, 0x01, 0x20, 0x68, 0x02, 0x01, 0x20, -0xa8, 0x0c, 0x01, 0x20, 0xa0, 0x86, 0x01, 0x00, 0xa9, 0x0d, 0x01, 0x20, 0x00, 0x50, 0x03, 0x40, -0x80, 0x51, 0x03, 0x40, 0x9c, 0x21, 0x01, 0x20, 0xf8, 0xb5, 0x01, 0x20, 0xfb, 0xf7, 0x38, 0xfd, -0x84, 0x46, 0x34, 0x48, 0x40, 0x79, 0x03, 0x28, 0x62, 0xd0, 0x33, 0x48, 0x40, 0x7e, 0x86, 0x46, -0x80, 0x07, 0x29, 0xd5, 0x2f, 0x48, 0x40, 0x79, 0x00, 0x28, 0x25, 0xd1, 0x2e, 0x49, 0x01, 0x25, -0xc8, 0x79, 0x01, 0x28, 0x20, 0xd3, 0x0f, 0x7a, 0x01, 0x22, 0x01, 0x2f, 0x18, 0xd3, 0x2b, 0x4b, -0x28, 0x21, 0x69, 0x43, 0xcb, 0x18, 0x54, 0x00, 0x19, 0x5f, 0x0e, 0x46, 0x09, 0x36, 0x12, 0x2e, -0x0a, 0xd9, 0x10, 0x36, 0x32, 0x2e, 0x01, 0xd8, 0x49, 0x10, 0x04, 0xe0, 0x0e, 0x46, 0x4f, 0x36, -0x9e, 0x2e, 0x01, 0xd8, 0x89, 0x10, 0x19, 0x53, 0x52, 0x1c, 0xd2, 0xb2, 0x97, 0x42, 0xea, 0xd2, -0x6d, 0x1c, 0xed, 0xb2, 0xa8, 0x42, 0xdf, 0xd2, 0x1b, 0x48, 0x71, 0x46, 0xc9, 0x07, 0x2f, 0xd0, -0x18, 0x49, 0x49, 0x79, 0x00, 0x29, 0x2b, 0xd1, 0xc1, 0x79, 0x00, 0x23, 0x00, 0x29, 0x22, 0xdd, -0x15, 0x48, 0x00, 0x21, 0x00, 0x7a, 0x00, 0x28, 0x18, 0xdd, 0x14, 0x4a, 0x18, 0x46, 0x28, 0x24, -0x60, 0x43, 0x87, 0x18, 0x12, 0x4a, 0x86, 0x18, 0x24, 0x20, 0x58, 0x43, 0x62, 0x46, 0x84, 0x18, -0x4a, 0x00, 0xb8, 0x18, 0x45, 0x8d, 0xb0, 0x18, 0x40, 0x8d, 0x49, 0x1c, 0x2d, 0x1a, 0xa0, 0x5a, -0x2d, 0x18, 0x09, 0x48, 0xa5, 0x52, 0x00, 0x7a, 0x88, 0x42, 0xf1, 0xdc, 0x06, 0x48, 0x5b, 0x1c, -0xc0, 0x79, 0x98, 0x42, 0xdc, 0xdc, 0x01, 0x20, 0xfb, 0xf7, 0xd2, 0xfc, 0xf9, 0xf7, 0x5e, 0xff, -0xf8, 0xbd, 0x00, 0x00, 0x4c, 0x03, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0x00, 0x50, 0x01, 0x20, -0x28, 0x2f, 0x01, 0x20, 0x10, 0xb5, 0xf8, 0xf7, 0xa3, 0xfa, 0x10, 0xbd, 0x06, 0x48, 0x00, 0x7d, -0xc0, 0x07, 0x08, 0xd0, 0x10, 0xb5, 0x55, 0x21, 0x09, 0x01, 0x04, 0x48, 0xf6, 0xf7, 0x12, 0xfb, -0xf7, 0xf7, 0x3e, 0xfe, 0x10, 0xbd, 0x70, 0x47, 0x48, 0x0d, 0x01, 0x20, 0x00, 0x5a, 0x01, 0x20, -0x10, 0xb5, 0xfa, 0xf7, 0x7d, 0xf8, 0x10, 0xbd, 0x10, 0xb5, 0x03, 0xf0, 0x4f, 0xfb, 0x10, 0xbd, -0x10, 0xb5, 0x00, 0x20, 0xfb, 0xf7, 0xbc, 0xfd, 0x01, 0x20, 0xfb, 0xf7, 0xb9, 0xfd, 0x10, 0xbd, -0x10, 0xb5, 0x03, 0xf0, 0x55, 0xfa, 0x10, 0xbd, 0x10, 0xb5, 0x05, 0x48, 0x00, 0x7e, 0x80, 0x07, -0x02, 0xd0, 0xfe, 0xf7, 0x57, 0xfd, 0x10, 0xbd, 0xfd, 0xf7, 0x8c, 0xfc, 0x10, 0xbd, 0x00, 0x00, -0xa8, 0x0e, 0x01, 0x20, 0x10, 0xb5, 0x01, 0xf0, 0x29, 0xfe, 0x10, 0xbd, 0x10, 0xb5, 0xff, 0xf7, -0xf1, 0xf9, 0x10, 0xbd, 0x12, 0x48, 0x80, 0x8a, 0x00, 0x28, 0x20, 0xd1, 0x11, 0x48, 0x80, 0x7b, -0x00, 0x28, 0x1c, 0xd0, 0x10, 0xb5, 0x10, 0x49, 0x10, 0x4c, 0xc9, 0x8b, 0x81, 0x42, 0x06, 0xd9, -0xe0, 0x79, 0x28, 0x28, 0x01, 0xd9, 0x28, 0x38, 0x00, 0xe0, 0x01, 0x20, 0xe0, 0x71, 0x00, 0x20, -0xfb, 0xf7, 0x86, 0xfd, 0x01, 0x20, 0xfb, 0xf7, 0x83, 0xfd, 0x03, 0xf0, 0x21, 0xfa, 0x01, 0xf0, -0x05, 0xfe, 0xff, 0xf7, 0xcf, 0xf9, 0x06, 0x48, 0xc0, 0x7d, 0xe0, 0x71, 0x10, 0xbd, 0x70, 0x47, -0xcc, 0x00, 0x01, 0x20, 0x84, 0x27, 0x01, 0x20, 0x04, 0x25, 0x01, 0x20, 0x1a, 0x01, 0x01, 0x20, -0x68, 0x0d, 0x01, 0x20, 0x10, 0xb5, 0xf8, 0xf7, 0x43, 0xfb, 0x10, 0xbd, 0x70, 0x47, 0x70, 0x47, -0xf8, 0xb5, 0x31, 0x48, 0x00, 0x79, 0x04, 0x28, 0x01, 0xd1, 0xfe, 0xf7, 0xf5, 0xff, 0x04, 0x20, -0xfb, 0xf7, 0x46, 0xfc, 0x2d, 0x4a, 0x00, 0x90, 0x50, 0x7e, 0x40, 0x06, 0x53, 0xd5, 0x2c, 0x48, -0x41, 0x7e, 0x03, 0x7e, 0x08, 0x02, 0x18, 0x43, 0x2a, 0x49, 0x32, 0x28, 0x02, 0xd9, 0xe1, 0x20, -0x80, 0x01, 0x03, 0xe0, 0xc8, 0x6b, 0x00, 0x28, 0x01, 0xd0, 0x40, 0x1e, 0xc8, 0x63, 0x26, 0x48, -0xc3, 0x79, 0x26, 0x48, 0xc0, 0x7d, 0x83, 0x42, 0x3d, 0xd1, 0xc8, 0x6b, 0x00, 0x28, 0x3a, 0xd1, -0xd0, 0x79, 0x01, 0x24, 0x01, 0x28, 0x36, 0xd3, 0x1c, 0x4b, 0x00, 0x21, 0x1d, 0x7a, 0x01, 0x22, -0x08, 0x46, 0x01, 0x2d, 0x13, 0xd3, 0x1e, 0x4b, 0x28, 0x26, 0x66, 0x43, 0xf6, 0x18, 0x53, 0x00, -0xf3, 0x5e, 0x1f, 0x46, 0x13, 0x37, 0x26, 0x2f, 0x01, 0xd8, 0x18, 0x18, 0x49, 0x1c, 0x52, 0x1c, -0xd2, 0xb2, 0x95, 0x42, 0xf3, 0xd2, 0x00, 0x29, 0x01, 0xd0, 0xf6, 0xf7, 0x75, 0xfa, 0x01, 0x21, -0x0e, 0x4f, 0x01, 0x2d, 0x12, 0xd3, 0x12, 0x4b, 0x22, 0x46, 0x28, 0x25, 0x6a, 0x43, 0xd5, 0x18, -0x00, 0x9b, 0xd3, 0x18, 0x4a, 0x00, 0x9e, 0x5a, 0x49, 0x1c, 0x36, 0x18, 0x9e, 0x52, 0xae, 0x5a, -0xc9, 0xb2, 0x36, 0x1a, 0xae, 0x52, 0x3a, 0x7a, 0x8a, 0x42, 0xf3, 0xd2, 0x64, 0x1c, 0xf8, 0x79, -0xe4, 0xb2, 0xa0, 0x42, 0xc8, 0xd2, 0xf8, 0xbd, 0x48, 0x0d, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, -0x8c, 0x03, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, 0x1a, 0x01, 0x01, 0x20, 0x68, 0x0d, 0x01, 0x20, -0x00, 0x50, 0x01, 0x20, 0x5b, 0x48, 0x80, 0x7d, 0x00, 0x28, 0x7c, 0xd0, 0x5a, 0x48, 0x80, 0x7e, -0x00, 0x28, 0x78, 0xd1, 0xf0, 0xb5, 0x59, 0x49, 0x89, 0xb0, 0xc8, 0x79, 0x0c, 0x7a, 0x58, 0x49, -0x05, 0x91, 0x14, 0x21, 0x00, 0x25, 0x04, 0x91, 0x06, 0x90, 0x00, 0x28, 0x6c, 0xd9, 0x60, 0x08, -0x07, 0x90, 0x00, 0x22, 0x11, 0x46, 0x94, 0x46, 0x10, 0x46, 0x00, 0x2c, 0x1e, 0xd9, 0x04, 0x9e, -0x2b, 0x46, 0x73, 0x43, 0x05, 0x9e, 0x5b, 0x00, 0x9e, 0x19, 0x43, 0x00, 0xf3, 0x5e, 0x1f, 0x46, -0x7f, 0x37, 0xfe, 0x2f, 0x01, 0xd9, 0x52, 0x1c, 0xd2, 0xb2, 0x0f, 0x33, 0x1e, 0x2b, 0x01, 0xd8, -0x49, 0x1c, 0xc9, 0xb2, 0x07, 0x9b, 0x9a, 0x42, 0x7b, 0xd2, 0x99, 0x42, 0x79, 0xd2, 0x40, 0x1c, -0xc0, 0xb2, 0xa0, 0x42, 0xe9, 0xd3, 0x60, 0x46, 0x00, 0x28, 0x72, 0xd1, 0x00, 0x20, 0x00, 0x90, -0x01, 0x90, 0x02, 0x90, 0x03, 0x90, 0x00, 0x2c, 0x16, 0xd9, 0x04, 0x9a, 0x29, 0x46, 0x51, 0x43, -0x05, 0x9a, 0x49, 0x00, 0x6b, 0x46, 0x8a, 0x18, 0x41, 0x00, 0x51, 0x5e, 0x0e, 0x46, 0x7f, 0x36, -0xfe, 0x2e, 0x05, 0xd8, 0x80, 0x31, 0x09, 0x05, 0x09, 0x0e, 0x5e, 0x5c, 0x76, 0x1c, 0x5e, 0x54, -0x40, 0x1c, 0xc0, 0xb2, 0xa0, 0x42, 0xef, 0xd3, 0x68, 0x46, 0x00, 0x21, 0x41, 0x56, 0x00, 0x23, -0x01, 0x20, 0x6e, 0x46, 0x32, 0x56, 0x8a, 0x42, 0x01, 0xdd, 0x11, 0x46, 0x03, 0x46, 0x40, 0x1c, -0xc0, 0xb2, 0x10, 0x28, 0xf6, 0xd3, 0x00, 0x20, 0x02, 0x46, 0x00, 0x2c, 0x12, 0xd9, 0x04, 0x9e, -0x05, 0x9f, 0x6e, 0x43, 0x76, 0x00, 0xf6, 0x19, 0xb4, 0x46, 0x67, 0x46, 0x56, 0x00, 0xbe, 0x5f, -0x37, 0x46, 0x80, 0x37, 0x3f, 0x11, 0x9f, 0x42, 0x00, 0xd1, 0x30, 0x18, 0x52, 0x1c, 0xd2, 0xb2, -0xa2, 0x42, 0xf2, 0xd3, 0x01, 0xe0, 0x34, 0xe0, 0x31, 0xe0, 0xf6, 0xf7, 0xc5, 0xf9, 0x00, 0x23, -0x00, 0x2c, 0x24, 0xd9, 0x04, 0x9a, 0x29, 0x46, 0x51, 0x43, 0x05, 0x9a, 0x49, 0x00, 0x8f, 0x18, -0x18, 0x49, 0x0e, 0x88, 0x59, 0x00, 0x7a, 0x18, 0x00, 0x21, 0x51, 0x5e, 0x00, 0x28, 0x05, 0xdd, -0x09, 0x1a, 0x09, 0xb2, 0x00, 0x29, 0x0d, 0xdc, 0x00, 0x21, 0x0b, 0xe0, 0x00, 0x29, 0x05, 0xdb, -0x8e, 0x42, 0x08, 0xda, 0x09, 0x1a, 0x11, 0x80, 0x05, 0xe0, 0x0a, 0xe0, 0x09, 0x1a, 0x09, 0xb2, -0x00, 0x29, 0xf1, 0xda, 0x11, 0x80, 0x5b, 0x1c, 0xdb, 0xb2, 0xa3, 0x42, 0xe2, 0xd3, 0x04, 0xf0, -0x4f, 0xfa, 0x6d, 0x1c, 0x06, 0x98, 0xed, 0xb2, 0x85, 0x42, 0x00, 0xd2, 0x61, 0xe7, 0x09, 0xb0, -0xf0, 0xbd, 0x70, 0x47, 0x28, 0x0d, 0x01, 0x20, 0x84, 0x2d, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, -0x2a, 0x50, 0x01, 0x20, 0x1a, 0x01, 0x01, 0x20, 0x5e, 0x48, 0xc0, 0x7d, 0x00, 0x28, 0x7d, 0xd0, -0x5d, 0x48, 0x80, 0x7e, 0x00, 0x28, 0x79, 0xd1, 0xf0, 0xb5, 0x5c, 0x48, 0x89, 0xb0, 0xc4, 0x79, -0x00, 0x7a, 0x01, 0x90, 0x00, 0x20, 0x00, 0x90, 0x01, 0x98, 0x59, 0x4d, 0x14, 0x26, 0x00, 0x28, -0x6d, 0xd9, 0x60, 0x08, 0x06, 0x90, 0x00, 0x22, 0x11, 0x46, 0x96, 0x46, 0x10, 0x46, 0x00, 0x2c, -0x1f, 0xd9, 0x00, 0x9b, 0x5b, 0x00, 0x9c, 0x46, 0x03, 0x46, 0x73, 0x43, 0x5b, 0x00, 0x5b, 0x19, -0x67, 0x46, 0xdb, 0x5f, 0x1f, 0x46, 0x7f, 0x37, 0xfe, 0x2f, 0x01, 0xd9, 0x52, 0x1c, 0xd2, 0xb2, -0x0f, 0x33, 0x1e, 0x2b, 0x01, 0xd8, 0x49, 0x1c, 0xc9, 0xb2, 0x06, 0x9b, 0x9a, 0x42, 0x7d, 0xd2, -0x99, 0x42, 0x7b, 0xd2, 0x40, 0x1c, 0xc0, 0xb2, 0xa0, 0x42, 0xe5, 0xd3, 0x70, 0x46, 0x00, 0x28, -0x74, 0xd1, 0x00, 0x20, 0x02, 0x90, 0x03, 0x90, 0x04, 0x90, 0x05, 0x90, 0x00, 0x2c, 0x15, 0xd9, -0x00, 0x99, 0x4f, 0x00, 0x01, 0x46, 0x71, 0x43, 0x49, 0x00, 0x49, 0x19, 0xc9, 0x5f, 0x0a, 0x46, -0x7f, 0x32, 0xfe, 0x2a, 0x06, 0xd8, 0x80, 0x31, 0x09, 0x05, 0x09, 0x0e, 0x02, 0xaa, 0x53, 0x5c, -0x5b, 0x1c, 0x53, 0x54, 0x40, 0x1c, 0xc0, 0xb2, 0xa0, 0x42, 0xeb, 0xd3, 0x68, 0x46, 0x08, 0x21, -0x41, 0x56, 0x00, 0x23, 0x01, 0x20, 0x02, 0xaf, 0x3a, 0x56, 0x8a, 0x42, 0x01, 0xdd, 0x11, 0x46, -0x03, 0x46, 0x40, 0x1c, 0xc0, 0xb2, 0x10, 0x28, 0xf6, 0xd3, 0x00, 0x20, 0x84, 0x46, 0x02, 0x46, -0x00, 0x2c, 0x12, 0xd9, 0x00, 0x98, 0x40, 0x00, 0x07, 0x90, 0x10, 0x46, 0x70, 0x43, 0x40, 0x00, -0x07, 0x9f, 0x40, 0x19, 0xc0, 0x5f, 0x86, 0x46, 0x80, 0x30, 0x07, 0x11, 0x9f, 0x42, 0x00, 0xd1, -0xf4, 0x44, 0x52, 0x1c, 0xd2, 0xb2, 0xa2, 0x42, 0xef, 0xd3, 0x01, 0xe0, 0x38, 0xe0, 0x35, 0xe0, -0x60, 0x46, 0xf6, 0xf7, 0x01, 0xf9, 0x00, 0x23, 0x00, 0x2c, 0x25, 0xd9, 0x00, 0x99, 0x49, 0x00, -0x8c, 0x46, 0x1c, 0x49, 0x0f, 0x88, 0x19, 0x46, 0x71, 0x43, 0x49, 0x00, 0x49, 0x19, 0x62, 0x46, -0x8a, 0x18, 0x00, 0x21, 0x51, 0x5e, 0x00, 0x28, 0x05, 0xdd, 0x09, 0x1a, 0x09, 0xb2, 0x00, 0x29, -0x0d, 0xdc, 0x00, 0x21, 0x0b, 0xe0, 0x00, 0x29, 0x05, 0xdb, 0x8f, 0x42, 0x08, 0xda, 0x09, 0x1a, -0x11, 0x80, 0x05, 0xe0, 0x0a, 0xe0, 0x09, 0x1a, 0x09, 0xb2, 0x00, 0x29, 0xf1, 0xda, 0x11, 0x80, -0x5b, 0x1c, 0xdb, 0xb2, 0xa3, 0x42, 0xde, 0xd3, 0x04, 0xf0, 0x8a, 0xf9, 0x00, 0x98, 0x01, 0x99, -0x40, 0x1c, 0xc0, 0xb2, 0x00, 0x90, 0x88, 0x42, 0x00, 0xd2, 0x5c, 0xe7, 0x09, 0xb0, 0xf0, 0xbd, -0x70, 0x47, 0x00, 0x00, 0x28, 0x0d, 0x01, 0x20, 0x84, 0x2d, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, -0x2a, 0x50, 0x01, 0x20, 0x1a, 0x01, 0x01, 0x20, 0x00, 0xb5, 0xfc, 0xf7, 0xd3, 0xfe, 0x00, 0xbd, -0x01, 0x49, 0x00, 0x20, 0x08, 0x74, 0x70, 0x47, 0xa4, 0x2d, 0x01, 0x20, 0x70, 0x47, 0xf0, 0xb5, -0x00, 0x26, 0x87, 0xb0, 0x07, 0x46, 0x00, 0x28, 0x2d, 0xd0, 0x01, 0x29, 0x2d, 0xd0, 0x08, 0x29, -0x29, 0xd1, 0x01, 0x20, 0x00, 0x24, 0xc1, 0x00, 0x45, 0x18, 0x12, 0x20, 0x60, 0x43, 0x09, 0x30, -0xb0, 0x40, 0x20, 0x21, 0x09, 0x1b, 0x12, 0x22, 0x51, 0x43, 0x09, 0x39, 0xb1, 0x40, 0x80, 0xb2, -0x89, 0xb2, 0x38, 0x18, 0x06, 0x91, 0x05, 0x90, 0x01, 0x46, 0x2a, 0x46, 0x68, 0x46, 0xf6, 0xf7, -0x1b, 0xf8, 0x06, 0x99, 0x05, 0x9b, 0x78, 0x18, 0x06, 0x90, 0x01, 0x46, 0x2a, 0x46, 0x18, 0x46, -0xf6, 0xf7, 0x12, 0xf8, 0x2a, 0x46, 0x69, 0x46, 0x06, 0x98, 0xf6, 0xf7, 0x0d, 0xf8, 0x64, 0x1c, -0xe4, 0xb2, 0x10, 0x2c, 0xd9, 0xd3, 0x07, 0xb0, 0xf0, 0xbd, 0x01, 0x26, 0x02, 0x20, 0xd1, 0xe7, -0x10, 0xb5, 0x01, 0x20, 0xfb, 0xf7, 0x0c, 0xfa, 0x15, 0x49, 0x04, 0x46, 0x08, 0x7d, 0x15, 0x4a, -0x00, 0x28, 0x02, 0xd0, 0x90, 0x79, 0x00, 0x28, 0x20, 0xd0, 0x13, 0x48, 0x43, 0x79, 0x03, 0x2b, -0x05, 0xd1, 0xcb, 0x7e, 0x9b, 0x06, 0x02, 0xd5, 0xd2, 0x7b, 0x00, 0x2a, 0x16, 0xd0, 0x40, 0x79, -0x01, 0x28, 0x13, 0xd0, 0x0d, 0x4a, 0xd0, 0x7f, 0x05, 0x28, 0x0f, 0xd0, 0xd0, 0x7f, 0x03, 0x28, -0x05, 0xd1, 0x10, 0x7d, 0x01, 0x28, 0x02, 0xd1, 0xc8, 0x7c, 0x40, 0x06, 0x06, 0xd5, 0x01, 0x21, -0x20, 0x46, 0xff, 0xf7, 0x9c, 0xff, 0x20, 0x46, 0xf9, 0xf7, 0x70, 0xfc, 0x10, 0xbd, 0x00, 0x00, -0xa8, 0x0d, 0x01, 0x20, 0x8c, 0x03, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, 0x6c, 0x03, 0x01, 0x20, -0xf8, 0xb5, 0x01, 0x27, 0x1f, 0x23, 0x3f, 0x03, 0x00, 0x21, 0xa6, 0x4a, 0xa6, 0x4e, 0xdb, 0x01, -0xa6, 0x4c, 0xb8, 0x42, 0x1d, 0xd2, 0x5b, 0x28, 0x06, 0xd2, 0x11, 0x18, 0x5b, 0x22, 0x10, 0x1a, -0x31, 0x60, 0x20, 0x80, 0x08, 0x78, 0xf8, 0xbd, 0x98, 0x42, 0x0f, 0xd3, 0xa0, 0x49, 0x49, 0x7f, -0x02, 0x29, 0x01, 0xd0, 0xff, 0x20, 0xf8, 0xbd, 0xc0, 0x1a, 0x9e, 0x49, 0x80, 0xb2, 0x09, 0x18, -0x04, 0x22, 0x10, 0x1a, 0x31, 0x60, 0x20, 0x80, 0x08, 0x78, 0xf8, 0xbd, 0x0f, 0x22, 0x12, 0x02, -0x04, 0xe1, 0x01, 0x25, 0x6d, 0x03, 0xa8, 0x42, 0x1f, 0xd2, 0xc0, 0x1b, 0x85, 0xb2, 0x96, 0x48, -0xc0, 0x7e, 0xc0, 0x06, 0x0d, 0xd5, 0x95, 0x48, 0x00, 0x78, 0x00, 0x28, 0x09, 0xd0, 0x64, 0x2d, -0x7d, 0xd2, 0x93, 0x48, 0x64, 0x21, 0x40, 0x19, 0x49, 0x1b, 0x30, 0x60, 0x21, 0x80, 0x00, 0x78, -0xf8, 0xbd, 0x70, 0x2d, 0x73, 0xd8, 0x10, 0x20, 0xfb, 0xf7, 0x92, 0xf9, 0x40, 0x19, 0x70, 0x21, -0x49, 0x1b, 0x30, 0x60, 0x21, 0x80, 0x00, 0x78, 0xf8, 0xbd, 0x03, 0x27, 0x3f, 0x03, 0xb8, 0x42, -0x1f, 0xd2, 0x40, 0x1b, 0x85, 0xb2, 0x87, 0x48, 0x00, 0x7d, 0x40, 0x06, 0x02, 0xd5, 0x50, 0x79, -0x03, 0x28, 0x0c, 0xd0, 0x09, 0x27, 0xff, 0x01, 0xbd, 0x42, 0x58, 0xd2, 0x01, 0x20, 0xfb, 0xf7, -0x77, 0xf9, 0x40, 0x19, 0x79, 0x1b, 0x30, 0x60, 0x21, 0x80, 0x00, 0x78, 0xf8, 0xbd, 0x90, 0x2d, -0x4d, 0xd2, 0x7d, 0x48, 0x90, 0x21, 0x40, 0x19, 0x49, 0x1b, 0x30, 0x60, 0x21, 0x80, 0x00, 0x78, -0xf8, 0xbd, 0x01, 0x25, 0x55, 0x27, 0xad, 0x03, 0x3f, 0x01, 0xa8, 0x42, 0x1f, 0xd2, 0x03, 0x22, -0x12, 0x03, 0x80, 0x1a, 0x85, 0xb2, 0xbd, 0x42, 0x08, 0xd2, 0x02, 0x20, 0xfb, 0xf7, 0x58, 0xf9, -0x40, 0x19, 0x79, 0x1b, 0x30, 0x60, 0x21, 0x80, 0x00, 0x78, 0xf8, 0xbd, 0x9d, 0x42, 0x2e, 0xd3, -0x6e, 0x48, 0x85, 0x42, 0x09, 0xd2, 0xe8, 0x1a, 0x6d, 0x49, 0x80, 0xb2, 0x09, 0x18, 0x04, 0x22, -0x10, 0x1a, 0x31, 0x60, 0x20, 0x80, 0x08, 0x78, 0xf8, 0xbd, 0x00, 0x20, 0xf8, 0xbd, 0x05, 0x23, -0x1b, 0x03, 0x98, 0x42, 0x0b, 0xd2, 0x40, 0x1b, 0x80, 0xb2, 0x90, 0x28, 0x17, 0xd2, 0x51, 0x6a, -0x90, 0x22, 0x09, 0x18, 0x10, 0x1a, 0x31, 0x60, 0x20, 0x80, 0x08, 0x78, 0xf8, 0xbd, 0x03, 0x22, -0x52, 0x03, 0x90, 0x42, 0x0c, 0xd2, 0xc0, 0x1a, 0x80, 0xb2, 0x14, 0x28, 0x7e, 0xd2, 0x5d, 0x49, -0x14, 0x22, 0x09, 0x18, 0x10, 0x1a, 0x31, 0x60, 0x20, 0x80, 0x08, 0x78, 0xf8, 0xbd, 0x75, 0xe0, -0x07, 0x23, 0x1b, 0x03, 0x98, 0x42, 0x0c, 0xd2, 0x80, 0x1a, 0x85, 0xb2, 0xbd, 0x42, 0x6d, 0xd2, -0x04, 0x20, 0xfb, 0xf7, 0x15, 0xf9, 0x40, 0x19, 0x79, 0x1b, 0x30, 0x60, 0x21, 0x80, 0x00, 0x78, -0xf8, 0xbd, 0x01, 0x22, 0xd2, 0x03, 0x90, 0x42, 0x29, 0xd2, 0xc0, 0x1a, 0x00, 0x04, 0x4e, 0x4a, -0x00, 0x0c, 0x11, 0xd0, 0x01, 0x28, 0x11, 0xd0, 0x07, 0x22, 0x52, 0x02, 0x90, 0x42, 0x11, 0xd3, -0x80, 0x1a, 0x80, 0xb2, 0x80, 0x28, 0x51, 0xd2, 0x48, 0x49, 0x80, 0x22, 0x09, 0x18, 0x10, 0x1a, -0x31, 0x60, 0x20, 0x80, 0x08, 0x78, 0xf8, 0xbd, 0x90, 0x78, 0xf8, 0xbd, 0x90, 0x7a, 0x40, 0x1c, -0xc0, 0xb2, 0xf8, 0xbd, 0x80, 0x1e, 0x03, 0x22, 0x80, 0xb2, 0x12, 0x02, 0x90, 0x42, 0x3d, 0xd2, -0x3f, 0x49, 0x09, 0x18, 0x10, 0x1a, 0x31, 0x60, 0x20, 0x80, 0x08, 0x78, 0xf8, 0xbd, 0x09, 0x23, -0x1b, 0x03, 0x98, 0x42, 0x0f, 0xd2, 0x80, 0x1a, 0x45, 0x22, 0x80, 0xb2, 0xd2, 0x00, 0x90, 0x42, -0x06, 0xd2, 0x38, 0x49, 0x09, 0x18, 0x10, 0x1a, 0x31, 0x60, 0x20, 0x80, 0x08, 0x78, 0xf8, 0xbd, -0x21, 0x80, 0x00, 0x20, 0xf8, 0xbd, 0x05, 0x22, 0x52, 0x03, 0x90, 0x42, 0x09, 0xd2, 0xc0, 0x1a, -0x82, 0xb2, 0x02, 0x2a, 0x1a, 0xd8, 0x30, 0x48, 0x03, 0x21, 0x40, 0x78, 0x89, 0x1a, 0x21, 0x80, -0xf8, 0xbd, 0x0b, 0x23, 0x1b, 0x03, 0x98, 0x42, 0x0c, 0xd2, 0x80, 0x1a, 0x09, 0x22, 0x80, 0xb2, -0x92, 0x01, 0x90, 0x42, 0x0a, 0xd2, 0x29, 0x49, 0x09, 0x18, 0x10, 0x1a, 0x31, 0x60, 0x20, 0x80, -0x08, 0x78, 0xf8, 0xbd, 0x03, 0x22, 0x92, 0x03, 0x90, 0x42, 0x02, 0xd2, 0x21, 0x80, 0xff, 0x20, -0xf8, 0xbd, 0x0f, 0x22, 0x12, 0x03, 0x01, 0x25, 0x90, 0x42, 0x09, 0xd2, 0x03, 0x21, 0x09, 0x04, -0x40, 0x18, 0xf9, 0xf7, 0x7c, 0xfb, 0x1e, 0x49, 0x08, 0x70, 0x31, 0x60, 0x25, 0x80, 0xf8, 0xbd, -0x80, 0x1a, 0xff, 0x23, 0x1b, 0x4a, 0x80, 0xb2, 0x13, 0x71, 0x21, 0x80, 0x05, 0x28, 0x07, 0xd2, -0x04, 0x28, 0x05, 0xd1, 0x10, 0x68, 0x00, 0x78, 0x10, 0x71, 0x17, 0x48, 0x30, 0x60, 0x25, 0x80, -0x10, 0x79, 0xf8, 0xbd, 0x4c, 0x03, 0x01, 0x20, 0x50, 0x00, 0x01, 0x20, 0x44, 0x00, 0x01, 0x20, -0x08, 0x0e, 0x01, 0x20, 0x54, 0x00, 0x01, 0x20, 0xa8, 0x0d, 0x01, 0x20, 0x02, 0x00, 0x01, 0x20, -0x3e, 0x0f, 0x01, 0x20, 0x48, 0x0d, 0x01, 0x20, 0xe4, 0x11, 0x01, 0x20, 0x84, 0x0f, 0x00, 0x00, -0x44, 0xee, 0x00, 0x00, 0x8c, 0x04, 0x01, 0x20, 0x76, 0x00, 0x01, 0x20, 0xd4, 0x37, 0x01, 0x20, -0xd4, 0x34, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0x38, 0x00, 0x01, 0x20, 0xa4, 0x0f, 0x01, 0x20, -0x60, 0x00, 0x01, 0x20, 0x3c, 0x00, 0x01, 0x20, 0x40, 0x00, 0x01, 0x20, 0x70, 0xb5, 0x35, 0x4c, -0x00, 0x21, 0x61, 0x5e, 0x00, 0x29, 0x01, 0xda, 0x00, 0x21, 0x21, 0x80, 0x01, 0x21, 0x49, 0x03, -0x42, 0x1a, 0x49, 0x10, 0x30, 0x4e, 0x31, 0x4d, 0x8a, 0x42, 0x46, 0xd3, 0x03, 0x22, 0x12, 0x03, -0x1f, 0x23, 0x82, 0x1a, 0xdb, 0x01, 0x9a, 0x42, 0x3f, 0xd3, 0x03, 0x22, 0x52, 0x03, 0x82, 0x1a, -0x8a, 0x42, 0x3a, 0xd3, 0x2a, 0x4b, 0x07, 0x22, 0x99, 0x7a, 0x12, 0x03, 0x49, 0x1c, 0xc9, 0xb2, -0x90, 0x42, 0x0a, 0xd1, 0x98, 0x78, 0x28, 0x70, 0x69, 0x70, 0x26, 0x4a, 0x22, 0x80, 0x26, 0x49, -0xa8, 0x1c, 0xf5, 0xf7, 0x21, 0xfe, 0xe5, 0x60, 0x27, 0xe0, 0x24, 0x4a, 0x90, 0x42, 0x07, 0xd1, -0x29, 0x70, 0x23, 0x4a, 0x22, 0x80, 0x20, 0x49, 0x68, 0x1c, 0xf5, 0xf7, 0x15, 0xfe, 0x10, 0xe0, -0x09, 0x21, 0x09, 0x03, 0x88, 0x42, 0x05, 0xd0, 0x49, 0x1c, 0x88, 0x42, 0x02, 0xd0, 0x49, 0x1c, -0x88, 0x42, 0x08, 0xd1, 0x1b, 0x48, 0x00, 0x21, 0x02, 0x78, 0x61, 0x5e, 0x13, 0x48, 0xf5, 0xf7, -0x44, 0xfe, 0xe5, 0x60, 0x09, 0xe0, 0xb0, 0x78, 0x00, 0x28, 0x19, 0xd0, 0x00, 0x22, 0xa2, 0x5e, -0x0e, 0x48, 0xe1, 0x68, 0xf5, 0xf7, 0xf8, 0xfd, 0xe5, 0x60, 0xb0, 0x78, 0x00, 0x28, 0x0f, 0xd0, -0xe0, 0x68, 0x11, 0x4e, 0xa8, 0x42, 0x09, 0xd1, 0x00, 0x20, 0xb1, 0x88, 0x20, 0x5e, 0x81, 0x42, -0x04, 0xdd, 0x09, 0x1a, 0x28, 0x18, 0xff, 0x22, 0xf5, 0xf7, 0x27, 0xfe, 0xb0, 0x88, 0x20, 0x80, -0x70, 0xbd, 0x00, 0x00, 0x44, 0x00, 0x01, 0x20, 0x4c, 0x00, 0x01, 0x20, 0xa0, 0x04, 0x01, 0x20, -0x76, 0x00, 0x01, 0x20, 0x02, 0x03, 0x00, 0x00, 0xd4, 0x34, 0x01, 0x20, 0x01, 0x70, 0x00, 0x00, -0x01, 0x03, 0x00, 0x00, 0x39, 0x00, 0x01, 0x20, 0x58, 0x00, 0x01, 0x20, 0x10, 0xb5, 0xff, 0xf7, -0xff, 0xfd, 0x10, 0xbd, 0xf0, 0xb4, 0x6a, 0x49, 0x65, 0x4a, 0x0b, 0x7e, 0x11, 0x46, 0x63, 0x4e, -0x64, 0x4d, 0x65, 0x4f, 0x65, 0x4c, 0x20, 0x31, 0x9b, 0x1e, 0x00, 0x28, 0x5f, 0xd0, 0x30, 0x7a, -0x10, 0x70, 0x28, 0x7c, 0x50, 0x70, 0x28, 0x7d, 0x90, 0x70, 0x38, 0x79, 0x3e, 0x46, 0x61, 0x4f, -0xd0, 0x70, 0x38, 0x79, 0x10, 0x71, 0x30, 0x7b, 0x50, 0x71, 0x38, 0x7b, 0x90, 0x71, 0x20, 0x78, -0xd0, 0x71, 0x5d, 0x48, 0x06, 0x78, 0x16, 0x72, 0x26, 0x7c, 0x56, 0x72, 0x06, 0x7c, 0x96, 0x72, -0x26, 0x7d, 0xd6, 0x72, 0x06, 0x7d, 0x16, 0x73, 0x26, 0x7e, 0x56, 0x73, 0x06, 0x7e, 0x96, 0x73, -0x24, 0x7f, 0xd4, 0x73, 0x00, 0x7f, 0x10, 0x74, 0x54, 0x48, 0x00, 0x78, 0x50, 0x74, 0x54, 0x48, -0x00, 0x78, 0x90, 0x74, 0x28, 0x7e, 0xd0, 0x74, 0x52, 0x48, 0x04, 0x78, 0x14, 0x75, 0x00, 0x79, -0x50, 0x75, 0x51, 0x48, 0x00, 0x7c, 0x90, 0x75, 0x50, 0x48, 0x00, 0x7c, 0xd0, 0x75, 0x50, 0x48, -0x00, 0x78, 0x10, 0x76, 0x4f, 0x48, 0x00, 0x78, 0x50, 0x76, 0x4f, 0x48, 0x84, 0x7c, 0x94, 0x76, -0x04, 0x7d, 0xd4, 0x76, 0x84, 0x7d, 0x14, 0x77, 0x04, 0x7e, 0x54, 0x77, 0x84, 0x7e, 0x94, 0x77, -0x4a, 0x4c, 0x25, 0x7c, 0xd5, 0x77, 0x62, 0x7c, 0x0a, 0x70, 0x22, 0x7f, 0x4a, 0x70, 0xfd, 0x2b, -0x0b, 0xd2, 0x47, 0x4a, 0x13, 0x7a, 0x8b, 0x70, 0x46, 0x4b, 0x5c, 0x7f, 0xcc, 0x70, 0x5b, 0x7e, -0x0b, 0x71, 0x92, 0x79, 0x4a, 0x71, 0xc0, 0x7f, 0x88, 0x71, 0xf0, 0xbc, 0x70, 0x47, 0x50, 0x78, -0x28, 0x74, 0x90, 0x78, 0x28, 0x75, 0x10, 0x78, 0x30, 0x72, 0xd0, 0x78, 0x38, 0x71, 0x31, 0x48, -0x16, 0x79, 0x06, 0x71, 0x56, 0x79, 0x3e, 0x73, 0x96, 0x79, 0x06, 0x73, 0xd0, 0x79, 0x20, 0x70, -0x2d, 0x48, 0x16, 0x7a, 0x06, 0x70, 0x56, 0x7a, 0x26, 0x74, 0x96, 0x7a, 0x06, 0x74, 0xd6, 0x7a, -0x26, 0x75, 0x16, 0x7b, 0x06, 0x75, 0x56, 0x7b, 0x26, 0x76, 0x96, 0x7b, 0x06, 0x76, 0xd6, 0x7b, -0x26, 0x77, 0x14, 0x7c, 0x04, 0x77, 0x25, 0x48, 0x54, 0x7c, 0x04, 0x70, 0x24, 0x48, 0x94, 0x7c, -0x04, 0x70, 0xd0, 0x7c, 0x28, 0x76, 0x23, 0x48, 0x14, 0x7d, 0x04, 0x70, 0x54, 0x7d, 0x04, 0x71, -0x21, 0x48, 0x94, 0x7d, 0x04, 0x74, 0x21, 0x48, 0xd4, 0x7d, 0x04, 0x74, 0x20, 0x48, 0x14, 0x7e, -0x04, 0x70, 0x20, 0x48, 0x54, 0x7e, 0x04, 0x70, 0x1f, 0x48, 0x94, 0x7e, 0x84, 0x74, 0xd4, 0x7e, -0x04, 0x75, 0x14, 0x7f, 0x84, 0x75, 0x54, 0x7f, 0x04, 0x76, 0x94, 0x7f, 0x84, 0x76, 0xd4, 0x7f, -0x1a, 0x4a, 0x14, 0x74, 0x0c, 0x78, 0x54, 0x74, 0x4c, 0x78, 0x14, 0x77, 0xfd, 0x2b, 0xac, 0xd2, -0x17, 0x4a, 0x8b, 0x78, 0x13, 0x72, 0x17, 0x4b, 0xcc, 0x78, 0x5c, 0x77, 0x0c, 0x79, 0x5c, 0x76, -0x4b, 0x79, 0x93, 0x71, 0x89, 0x79, 0xc1, 0x77, 0xf0, 0xbc, 0x70, 0x47, 0x60, 0x51, 0x03, 0x40, -0xa8, 0x2e, 0x01, 0x20, 0x20, 0x14, 0x03, 0x40, 0x60, 0x11, 0x03, 0x40, 0x00, 0x11, 0x03, 0x40, -0x28, 0x0d, 0x01, 0x20, 0x60, 0x13, 0x03, 0x40, 0x00, 0x13, 0x03, 0x40, 0x40, 0x11, 0x03, 0x40, -0x40, 0x13, 0x03, 0x40, 0x40, 0x14, 0x03, 0x40, 0x80, 0x11, 0x03, 0x40, 0x80, 0x13, 0x03, 0x40, -0x80, 0x49, 0x02, 0x20, 0x40, 0x49, 0x02, 0x20, 0x20, 0x50, 0x03, 0x40, 0xa0, 0x51, 0x03, 0x40, -0x40, 0x50, 0x03, 0x40, 0xe0, 0x50, 0x03, 0x40, 0x70, 0x47, 0x00, 0x00, 0x01, 0x49, 0x00, 0x20, -0xc8, 0x70, 0x70, 0x47, 0x38, 0x02, 0x01, 0x20, 0x09, 0x49, 0x00, 0x20, 0x48, 0x71, 0x88, 0x70, -0x08, 0x70, 0x88, 0x71, 0x07, 0x49, 0x48, 0x72, 0xc8, 0x72, 0x07, 0x49, 0x08, 0x60, 0x08, 0x71, -0x06, 0x49, 0x48, 0x64, 0x88, 0x64, 0xc8, 0x64, 0x08, 0x65, 0x48, 0x65, 0x70, 0x47, 0x00, 0x00, -0xb8, 0x2d, 0x01, 0x20, 0x78, 0x2e, 0x01, 0x20, 0x7c, 0x2e, 0x01, 0x20, 0x94, 0x2d, 0x01, 0x20, -0x10, 0xb5, 0x23, 0x4c, 0x23, 0x49, 0x20, 0x78, 0x88, 0x70, 0x23, 0x48, 0x61, 0x78, 0x01, 0x76, -0xa1, 0x78, 0x81, 0x76, 0x21, 0x49, 0xe2, 0x78, 0x0a, 0x75, 0x22, 0x79, 0x0a, 0x76, 0x62, 0x79, -0x8a, 0x76, 0x1f, 0x4a, 0xa1, 0x79, 0xd1, 0x73, 0x1e, 0x49, 0xe3, 0x79, 0x0b, 0x71, 0x23, 0x7a, -0x8b, 0x72, 0x63, 0x7a, 0x13, 0x74, 0x1c, 0x4b, 0xa2, 0x7a, 0x1a, 0x75, 0xe2, 0x7a, 0x8a, 0x77, -0x21, 0x7b, 0x41, 0x70, 0x61, 0x7b, 0x01, 0x75, 0xa1, 0x7b, 0x81, 0x75, 0x17, 0x49, 0xe0, 0x7b, -0x08, 0x74, 0x17, 0x49, 0x20, 0x7c, 0x08, 0x74, 0x16, 0x49, 0x60, 0x7c, 0x08, 0x70, 0x16, 0x49, -0xa0, 0x7c, 0x08, 0x70, 0x15, 0x48, 0xe1, 0x7c, 0x01, 0x74, 0x21, 0x7d, 0x01, 0x75, 0x14, 0x48, -0x61, 0x7d, 0x01, 0x70, 0xa1, 0x7d, 0x01, 0x71, 0x21, 0x7e, 0xe0, 0x7d, 0x01, 0xf0, 0x1a, 0xf9, -0x61, 0x7e, 0x10, 0x48, 0xf9, 0xf7, 0x63, 0xf9, 0x0f, 0x48, 0x00, 0x21, 0xc1, 0x73, 0x10, 0xbd, -0xa8, 0x2e, 0x01, 0x20, 0x20, 0x00, 0x03, 0x40, 0x20, 0x50, 0x03, 0x40, 0x40, 0x50, 0x03, 0x40, -0x80, 0x51, 0x03, 0x40, 0x00, 0x50, 0x03, 0x40, 0x40, 0x51, 0x03, 0x40, 0x80, 0x11, 0x03, 0x40, -0x80, 0x13, 0x03, 0x40, 0x00, 0x11, 0x03, 0x40, 0x00, 0x13, 0x03, 0x40, 0x20, 0x14, 0x03, 0x40, -0x40, 0x14, 0x03, 0x40, 0x85, 0xd2, 0x03, 0x40, 0x8c, 0x03, 0x01, 0x20, 0xf0, 0xb4, 0x0d, 0x4e, -0x00, 0x22, 0xf1, 0x79, 0x00, 0x29, 0x13, 0xdd, 0x33, 0x7a, 0x00, 0x21, 0x00, 0x2b, 0x0b, 0xdd, -0x09, 0x4c, 0x12, 0x23, 0x53, 0x43, 0x1d, 0x19, 0x5f, 0x18, 0x6c, 0x5c, 0xbf, 0x00, 0xc4, 0x51, -0x34, 0x7a, 0x49, 0x1c, 0x8c, 0x42, 0xf7, 0xdc, 0xf1, 0x79, 0x52, 0x1c, 0x91, 0x42, 0xeb, 0xdc, -0xf0, 0xbc, 0x70, 0x47, 0xa8, 0x0c, 0x01, 0x20, 0xa4, 0x0f, 0x01, 0x20, 0x01, 0x48, 0x00, 0x21, -0xc1, 0x73, 0x70, 0x47, 0x6c, 0x03, 0x01, 0x20, 0xf8, 0xb5, 0x08, 0x20, 0xfa, 0xf7, 0x30, 0xfe, -0x07, 0x46, 0x2e, 0x48, 0x41, 0x79, 0x00, 0x24, 0x01, 0x29, 0x00, 0xd1, 0x44, 0x71, 0x00, 0xf0, -0x79, 0xfd, 0x2b, 0x4e, 0x2b, 0x4d, 0x30, 0x7d, 0x2b, 0x49, 0x01, 0x28, 0x01, 0xd0, 0x02, 0x28, -0x04, 0xd1, 0xcc, 0x75, 0x28, 0x78, 0x00, 0x07, 0x00, 0x0f, 0x28, 0x70, 0x27, 0x48, 0x02, 0x7d, -0x52, 0x08, 0x52, 0x00, 0x02, 0x75, 0x26, 0x4a, 0x14, 0x76, 0x94, 0x76, 0x88, 0x7d, 0x0c, 0x46, -0xef, 0x21, 0x08, 0x40, 0xa0, 0x75, 0x38, 0x46, 0xff, 0xf7, 0xb0, 0xff, 0x21, 0x48, 0x22, 0x49, -0x02, 0x78, 0x0a, 0x75, 0x42, 0x78, 0x0a, 0x76, 0x82, 0x78, 0x8a, 0x76, 0x1f, 0x49, 0xc2, 0x78, -0x0a, 0x70, 0x02, 0x79, 0x0a, 0x71, 0x1e, 0x4a, 0x41, 0x79, 0x11, 0x70, 0x1d, 0x4a, 0x81, 0x79, -0x11, 0x70, 0x01, 0x89, 0xe1, 0x83, 0x41, 0x89, 0xa1, 0x80, 0x01, 0x7b, 0x29, 0x74, 0x00, 0x69, -0xa8, 0x60, 0x19, 0x48, 0xc1, 0x7a, 0x00, 0x7b, 0xf9, 0xf7, 0x76, 0xfe, 0x00, 0xf0, 0x62, 0xfc, -0x0b, 0x48, 0x01, 0x7e, 0xc2, 0x7d, 0x08, 0x02, 0x10, 0x43, 0xa0, 0x80, 0xe8, 0x73, 0x01, 0xf0, -0xe7, 0xfb, 0x30, 0x7d, 0x01, 0x28, 0x01, 0xd0, 0x02, 0x28, 0x03, 0xd1, 0xa0, 0x7c, 0xcf, 0x21, -0x08, 0x40, 0xa0, 0x74, 0x00, 0xf0, 0x4e, 0xfc, 0xf8, 0xbd, 0x00, 0x00, 0x4c, 0x03, 0x01, 0x20, -0xa8, 0x0c, 0x01, 0x20, 0x80, 0x51, 0x03, 0x40, 0x00, 0x50, 0x03, 0x40, 0x40, 0x50, 0x03, 0x40, -0x40, 0x51, 0x03, 0x40, 0xa8, 0x2e, 0x01, 0x20, 0x20, 0x50, 0x03, 0x40, 0x40, 0x14, 0x03, 0x40, -0x00, 0x11, 0x03, 0x40, 0x00, 0x13, 0x03, 0x40, 0xc8, 0x0c, 0x01, 0x20, 0x10, 0xb5, 0x24, 0x48, -0x80, 0x78, 0x24, 0x4c, 0x20, 0x70, 0x24, 0x48, 0x01, 0x7e, 0x61, 0x70, 0x81, 0x7e, 0xa1, 0x70, -0x22, 0x49, 0x0a, 0x7d, 0xe2, 0x70, 0x0a, 0x7e, 0x22, 0x71, 0x89, 0x7e, 0x20, 0x4a, 0x61, 0x71, -0xd1, 0x7b, 0xa1, 0x71, 0x1f, 0x49, 0x0b, 0x79, 0xe3, 0x71, 0x8b, 0x7a, 0x23, 0x72, 0x12, 0x7c, -0x62, 0x72, 0x1d, 0x4a, 0x12, 0x7d, 0xa2, 0x72, 0x89, 0x7f, 0xe1, 0x72, 0x41, 0x78, 0x21, 0x73, -0x01, 0x7d, 0x61, 0x73, 0x80, 0x7d, 0xa0, 0x73, 0x18, 0x48, 0x00, 0x7c, 0xe0, 0x73, 0x18, 0x48, -0x00, 0x7c, 0x20, 0x74, 0x17, 0x48, 0x00, 0x78, 0x60, 0x74, 0x17, 0x48, 0x00, 0x78, 0xa0, 0x74, -0x16, 0x48, 0x01, 0x7c, 0xe1, 0x74, 0x00, 0x7d, 0x20, 0x75, 0x15, 0x48, 0x01, 0x78, 0x61, 0x75, -0x00, 0x79, 0xa0, 0x75, 0x13, 0x48, 0xf9, 0xf7, 0x5a, 0xf8, 0xe0, 0x75, 0x12, 0x48, 0xf9, 0xf7, -0x56, 0xf8, 0x20, 0x76, 0x11, 0x48, 0xf9, 0xf7, 0x52, 0xf8, 0x60, 0x76, 0x10, 0xbd, 0x00, 0x00, -0x20, 0x00, 0x03, 0x40, 0xa8, 0x2e, 0x01, 0x20, 0x20, 0x50, 0x03, 0x40, 0x40, 0x50, 0x03, 0x40, -0x80, 0x51, 0x03, 0x40, 0x00, 0x50, 0x03, 0x40, 0x40, 0x51, 0x03, 0x40, 0x80, 0x11, 0x03, 0x40, -0x80, 0x13, 0x03, 0x40, 0x00, 0x11, 0x03, 0x40, 0x00, 0x13, 0x03, 0x40, 0x20, 0x14, 0x03, 0x40, -0x40, 0x14, 0x03, 0x40, 0x00, 0xd1, 0x03, 0x40, 0x0c, 0xd1, 0x03, 0x40, 0x85, 0xd2, 0x03, 0x40, -0xf0, 0xb4, 0x31, 0x4d, 0xe8, 0x7c, 0x83, 0x07, 0x9b, 0x0f, 0x00, 0x07, 0x84, 0x0f, 0x2f, 0x48, -0x01, 0x26, 0x46, 0x71, 0x2e, 0x48, 0x02, 0x7d, 0x2e, 0x49, 0x01, 0x2a, 0x02, 0xd1, 0x4a, 0x7c, -0x52, 0x1c, 0x4a, 0x74, 0x2c, 0x4a, 0x00, 0x27, 0x12, 0x7d, 0x01, 0x2a, 0x05, 0xd0, 0x02, 0x2a, -0x03, 0xd0, 0x02, 0x7d, 0x01, 0x2a, 0x41, 0xd1, 0x1f, 0xe0, 0xd9, 0x07, 0x05, 0xd0, 0x07, 0x72, -0xa8, 0x7c, 0x10, 0x21, 0x08, 0x43, 0xa8, 0x74, 0x06, 0xe0, 0x99, 0x07, 0x04, 0xd5, 0x06, 0x72, -0xa8, 0x7c, 0x20, 0x21, 0x08, 0x43, 0xa8, 0x74, 0x20, 0x48, 0xc0, 0x7d, 0x80, 0x07, 0x05, 0xd5, -0x02, 0x2a, 0x03, 0xd1, 0x1e, 0x48, 0xe1, 0x07, 0x02, 0xd0, 0x07, 0x70, 0xf0, 0xbc, 0x70, 0x47, -0xa1, 0x07, 0xfb, 0xd5, 0x06, 0x70, 0xf0, 0xbc, 0x70, 0x47, 0x02, 0x7d, 0x01, 0x2a, 0x03, 0xd1, -0x18, 0x4a, 0x12, 0x78, 0x00, 0x2a, 0x19, 0xd0, 0x4b, 0x7c, 0x17, 0x4a, 0x08, 0x2b, 0x02, 0xd2, -0x13, 0x78, 0x01, 0x2b, 0xef, 0xd1, 0x17, 0x70, 0x4f, 0x74, 0xaa, 0x7c, 0x04, 0x7a, 0x10, 0x21, -0x0b, 0x46, 0xa3, 0x40, 0x9a, 0x43, 0xaa, 0x74, 0x02, 0x7a, 0x72, 0x40, 0x02, 0x72, 0xaa, 0x7c, -0x00, 0x7a, 0x81, 0x40, 0x0a, 0x43, 0xaa, 0x74, 0xf0, 0xbc, 0x70, 0x47, 0x01, 0x7a, 0x71, 0x40, -0x01, 0x72, 0xf0, 0xbc, 0x70, 0x47, 0x00, 0x00, 0x00, 0x50, 0x03, 0x40, 0x18, 0x00, 0x01, 0x20, -0x6c, 0x03, 0x01, 0x20, 0x8c, 0x03, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0xe8, 0x0d, 0x01, 0x20, -0xcd, 0x00, 0x01, 0x20, 0xcf, 0x00, 0x01, 0x20, 0xd0, 0x00, 0x01, 0x20, 0xf0, 0xb5, 0xf9, 0x48, -0xf8, 0x49, 0x00, 0x79, 0x49, 0x79, 0x00, 0x02, 0x09, 0x03, 0x08, 0x18, 0xf5, 0x49, 0x83, 0xb0, -0x89, 0x79, 0x09, 0x06, 0x08, 0x18, 0xf4, 0x49, 0x08, 0x60, 0xf4, 0x48, 0x00, 0x90, 0x00, 0x7c, -0xc8, 0x72, 0x28, 0x20, 0xc8, 0x83, 0xfa, 0xf7, 0x49, 0xfe, 0xf1, 0x49, 0xf5, 0xf7, 0x1e, 0xfb, -0xf0, 0x49, 0x40, 0x1e, 0x4a, 0x7c, 0x0b, 0x7c, 0x11, 0x02, 0x19, 0x43, 0x48, 0x43, 0xee, 0x49, -0x80, 0x09, 0x08, 0x76, 0xfa, 0xf7, 0x3a, 0xfe, 0xe9, 0x49, 0xf5, 0xf7, 0x0f, 0xfb, 0xeb, 0x49, -0x40, 0x1e, 0x4a, 0x7a, 0x0b, 0x7a, 0x11, 0x02, 0x19, 0x43, 0x48, 0x43, 0xe6, 0x49, 0x80, 0x09, -0x88, 0x76, 0xe7, 0x4c, 0x60, 0x79, 0x01, 0x01, 0x08, 0x43, 0xe6, 0x49, 0x08, 0x74, 0xe6, 0x4e, -0x1f, 0x20, 0xb0, 0x74, 0xdb, 0x49, 0xdb, 0x48, 0x49, 0x79, 0x00, 0x79, 0x09, 0x01, 0x08, 0x18, -0xd8, 0x49, 0x89, 0x79, 0x09, 0x02, 0x08, 0x18, 0xe0, 0x49, 0x88, 0x81, 0xe0, 0x48, 0x40, 0x7f, -0x01, 0x21, 0x08, 0x43, 0xde, 0x49, 0x48, 0x77, 0xda, 0x48, 0x00, 0x27, 0x07, 0x75, 0x18, 0x20, -0xb0, 0x71, 0x30, 0x73, 0xb0, 0x73, 0xdb, 0x48, 0x01, 0x79, 0x49, 0x08, 0x49, 0x00, 0x01, 0x71, -0xd9, 0x4a, 0x50, 0x7d, 0x0f, 0x21, 0x08, 0x43, 0x50, 0x75, 0xca, 0x48, 0x01, 0x7e, 0xc3, 0x7d, -0x08, 0x02, 0xd0, 0x49, 0x18, 0x43, 0x08, 0x73, 0x48, 0x73, 0x88, 0x73, 0xc8, 0x73, 0x03, 0x21, -0x11, 0x75, 0xc5, 0x49, 0x88, 0x80, 0xfa, 0xf7, 0xf1, 0xfd, 0xd0, 0x49, 0x02, 0x91, 0x4a, 0x7d, -0x0b, 0x7d, 0x11, 0x02, 0x7d, 0x22, 0x19, 0x43, 0x12, 0x01, 0x51, 0x43, 0xf5, 0xf7, 0xbe, 0xfa, -0xbd, 0x49, 0xc8, 0x80, 0xbb, 0x48, 0x80, 0x7e, 0x30, 0x70, 0xc9, 0x48, 0x00, 0x78, 0xc9, 0x4d, -0x03, 0x28, 0x37, 0xd0, 0x20, 0x7e, 0x01, 0x28, 0x7e, 0xd0, 0x80, 0x1e, 0xfd, 0x28, 0x02, 0xd2, -0xc5, 0x49, 0x10, 0x20, 0x08, 0x72, 0x30, 0x7e, 0xc4, 0x49, 0x00, 0x07, 0x09, 0x7f, 0x00, 0x0f, -0x09, 0x01, 0x08, 0x43, 0x30, 0x76, 0xf0, 0x7f, 0x00, 0x09, 0x00, 0x01, 0xf0, 0x77, 0x30, 0x7e, -0x01, 0x09, 0xbf, 0x48, 0x09, 0x01, 0x00, 0x78, 0x01, 0x43, 0x31, 0x76, 0xa9, 0x48, 0x00, 0x7d, -0x68, 0x75, 0x00, 0x28, 0x7e, 0xd0, 0x03, 0x28, 0x7c, 0xd0, 0xa7, 0x49, 0x01, 0x22, 0x0a, 0x74, -0x0b, 0x7d, 0x13, 0x43, 0x0b, 0x75, 0x8b, 0x7c, 0x03, 0x25, 0x2b, 0x43, 0x8b, 0x74, 0xa9, 0x4b, -0x1f, 0x70, 0x01, 0x28, 0x6f, 0xd0, 0x4f, 0x75, 0x1f, 0x72, 0x5f, 0x72, 0x20, 0x7e, 0x01, 0x28, -0x6a, 0xd0, 0x25, 0xe1, 0x01, 0x20, 0x01, 0xf0, 0x9d, 0xf8, 0x28, 0x7d, 0x01, 0x28, 0x01, 0xd0, -0x28, 0x7d, 0xdb, 0xe7, 0xab, 0x48, 0x00, 0x7e, 0xeb, 0x21, 0x08, 0x40, 0x60, 0x21, 0x08, 0x43, -0xa8, 0x49, 0x08, 0x76, 0xa8, 0x48, 0x00, 0x78, 0x1f, 0x21, 0x08, 0x43, 0xa6, 0x49, 0x08, 0x70, -0x08, 0x79, 0x1f, 0x21, 0x08, 0x43, 0xa4, 0x49, 0x08, 0x71, 0x08, 0x7a, 0x10, 0x21, 0x08, 0x43, -0xa1, 0x49, 0x08, 0x72, 0x9f, 0x48, 0x07, 0x74, 0xa0, 0x49, 0x00, 0x20, 0x08, 0x74, 0x01, 0x46, -0x89, 0x48, 0x01, 0x72, 0x9b, 0x49, 0x03, 0x20, 0x08, 0x75, 0x9c, 0x49, 0x08, 0x75, 0x9c, 0x48, -0x01, 0x7c, 0x01, 0x20, 0x01, 0x43, 0x9a, 0x48, 0x01, 0x74, 0x9a, 0x48, 0x00, 0x7c, 0x01, 0x21, -0x08, 0x43, 0x98, 0x49, 0x08, 0x74, 0x98, 0x48, 0x00, 0x7e, 0x48, 0x21, 0x08, 0x43, 0x96, 0x49, -0x08, 0x76, 0x96, 0x48, 0x00, 0x7e, 0x48, 0x21, 0x08, 0x43, 0x94, 0x49, 0x08, 0x76, 0x94, 0x48, -0x00, 0x79, 0xdf, 0x21, 0x08, 0x40, 0x00, 0xe0, 0x88, 0xe0, 0x08, 0x21, 0x08, 0x43, 0x90, 0x49, -0x08, 0x71, 0x90, 0x48, 0x00, 0x79, 0xdf, 0x21, 0x08, 0x40, 0x08, 0x21, 0x08, 0x43, 0x8d, 0x49, -0x08, 0x71, 0x8d, 0x48, 0x81, 0x7a, 0x49, 0x08, 0x49, 0x00, 0x81, 0x72, 0x8b, 0x48, 0x81, 0x7a, -0x49, 0x08, 0x49, 0x00, 0x81, 0x72, 0x8a, 0x48, 0x01, 0x7b, 0x0d, 0x22, 0x11, 0x43, 0x01, 0x73, -0x88, 0x49, 0x02, 0xe0, 0x6d, 0xe0, 0x99, 0xe0, 0xab, 0xe0, 0x0b, 0x7b, 0x13, 0x43, 0x0b, 0x73, -0xc5, 0x22, 0x02, 0x71, 0x0a, 0x71, 0x7e, 0x4a, 0x12, 0x78, 0xef, 0x23, 0x1a, 0x40, 0x7c, 0x4b, -0x1a, 0x70, 0x7c, 0x4a, 0x12, 0x78, 0xef, 0x23, 0x1a, 0x40, 0x7a, 0x4b, 0x1a, 0x70, 0x02, 0x78, -0x94, 0x23, 0x1a, 0x40, 0x14, 0x23, 0x1a, 0x43, 0x02, 0x70, 0x08, 0x78, 0x94, 0x22, 0x10, 0x40, -0x18, 0x43, 0x08, 0x70, 0x58, 0x48, 0x05, 0x21, 0x01, 0x71, 0x5e, 0x48, 0x76, 0x49, 0xc1, 0x60, -0x1f, 0x20, 0xb0, 0x74, 0x33, 0x20, 0xb0, 0x75, 0x74, 0x49, 0x08, 0x20, 0x48, 0x73, 0x01, 0x46, -0x73, 0x48, 0x81, 0x74, 0x08, 0x21, 0x01, 0x74, 0x73, 0x49, 0x72, 0x48, 0x08, 0x82, 0x88, 0x82, -0x56, 0x48, 0x00, 0x78, 0x41, 0x08, 0x55, 0x48, 0x49, 0x00, 0x01, 0x70, 0x5a, 0x48, 0x00, 0x7a, -0x03, 0x21, 0x08, 0x43, 0x58, 0x49, 0x08, 0x72, 0x0a, 0x20, 0x03, 0xf0, 0x55, 0xfc, 0x4f, 0x48, -0xc0, 0x7b, 0x0f, 0x21, 0x08, 0x43, 0x4d, 0x49, 0xc8, 0x73, 0xc8, 0x78, 0x01, 0x09, 0x4b, 0x48, -0x09, 0x01, 0xc1, 0x70, 0x65, 0x48, 0xc0, 0x78, 0xc1, 0x06, 0x4f, 0x48, 0xc9, 0x0e, 0x41, 0x72, -0x80, 0x20, 0x84, 0x46, 0x01, 0x90, 0x00, 0x20, 0x83, 0x00, 0x61, 0x49, 0x01, 0x9a, 0x59, 0x18, -0x09, 0x23, 0x1b, 0x02, 0xcb, 0x18, 0x1a, 0x64, 0x13, 0x23, 0xdb, 0x01, 0xc9, 0x18, 0x40, 0x1c, -0x62, 0x46, 0xc0, 0xb2, 0x0a, 0x60, 0x10, 0x28, 0xee, 0xd3, 0x0f, 0xe7, 0x42, 0x48, 0x07, 0x72, -0xf9, 0xe6, 0x31, 0x49, 0x0f, 0x74, 0x0a, 0x7d, 0x52, 0x08, 0x52, 0x00, 0x0a, 0x75, 0x01, 0x22, -0x4a, 0x75, 0x8b, 0x7c, 0x9b, 0x08, 0x9b, 0x00, 0x8b, 0x74, 0x72, 0x77, 0x21, 0x7e, 0x89, 0x1e, -0xfd, 0x29, 0x06, 0xd2, 0x00, 0x99, 0x49, 0x7f, 0x31, 0x71, 0xb1, 0x71, 0x31, 0x73, 0xb1, 0x73, -0x04, 0xe0, 0x18, 0x21, 0x31, 0x71, 0xb1, 0x71, 0x31, 0x73, 0xb1, 0x73, 0x05, 0x46, 0xfa, 0xf7, -0xc7, 0xff, 0xfb, 0xf7, 0x43, 0xfb, 0x1f, 0x48, 0x03, 0x2d, 0x05, 0x75, 0x00, 0xd0, 0xfd, 0xe6, -0x1d, 0x48, 0x01, 0x7d, 0xfd, 0x22, 0x11, 0x40, 0x01, 0x75, 0xf7, 0xe6, 0x4a, 0x75, 0x72, 0x77, -0x20, 0x7e, 0x80, 0x1e, 0xfd, 0x28, 0x06, 0xd2, 0x00, 0x98, 0x40, 0x7f, 0x30, 0x71, 0xb0, 0x71, -0x30, 0x73, 0xb0, 0x73, 0xea, 0xe6, 0x18, 0x20, 0x30, 0x71, 0xb0, 0x71, 0x30, 0x73, 0xb0, 0x73, -0xe4, 0xe6, 0x38, 0x4d, 0x28, 0x7d, 0x01, 0x21, 0x08, 0x43, 0x28, 0x75, 0x28, 0x7d, 0x00, 0x28, -0x04, 0xd0, 0x03, 0xf0, 0x1d, 0xfa, 0x28, 0x7d, 0x00, 0x28, 0xfa, 0xd1, 0x1d, 0x20, 0xb0, 0x80, -0x08, 0x49, 0x88, 0x7b, 0x09, 0x7d, 0x02, 0x29, 0x66, 0xd1, 0x01, 0x28, 0x06, 0xd0, 0x03, 0x28, -0x5c, 0xd0, 0x04, 0x28, 0x5e, 0xd0, 0x02, 0x28, 0x5c, 0xd0, 0x5d, 0xe0, 0x09, 0x48, 0x2a, 0x49, -0x81, 0x60, 0x59, 0xe0, 0xa8, 0x0c, 0x01, 0x20, 0x00, 0x50, 0x03, 0x40, 0xe8, 0x0d, 0x01, 0x20, -0x40, 0x42, 0x0f, 0x00, 0xa9, 0x0d, 0x01, 0x20, 0xc0, 0x51, 0x03, 0x40, 0xea, 0x0d, 0x01, 0x20, -0x28, 0x0d, 0x01, 0x20, 0x80, 0x51, 0x03, 0x40, 0x20, 0x50, 0x03, 0x40, 0xa0, 0x51, 0x03, 0x40, -0xe0, 0x51, 0x03, 0x40, 0x60, 0x51, 0x03, 0x40, 0x40, 0x51, 0x03, 0x40, 0xa9, 0x0c, 0x01, 0x20, -0x4c, 0x03, 0x01, 0x20, 0x6c, 0x03, 0x01, 0x20, 0x40, 0x50, 0x03, 0x40, 0x88, 0x0d, 0x01, 0x20, -0xc8, 0x0d, 0x01, 0x20, 0x20, 0x14, 0x03, 0x40, 0x40, 0x14, 0x03, 0x40, 0x20, 0x12, 0x03, 0x40, -0xa0, 0x13, 0x03, 0x40, 0xa0, 0x11, 0x03, 0x40, 0x00, 0x13, 0x03, 0x40, 0x00, 0x11, 0x03, 0x40, -0x40, 0x13, 0x03, 0x40, 0x40, 0x11, 0x03, 0x40, 0x00, 0x16, 0x03, 0x40, 0x00, 0x15, 0x03, 0x40, -0x60, 0x13, 0x03, 0x40, 0x60, 0x11, 0x03, 0x40, 0x05, 0x05, 0x05, 0x05, 0x60, 0x00, 0x03, 0x40, -0x20, 0x00, 0x03, 0x40, 0x55, 0x55, 0x00, 0x00, 0xe0, 0x50, 0x03, 0x40, 0xe8, 0x0c, 0x01, 0x20, -0x00, 0x40, 0x02, 0x20, 0x60, 0x50, 0x03, 0x40, 0x55, 0x00, 0x55, 0x00, 0x0b, 0x48, 0x0a, 0x49, -0x81, 0x60, 0x01, 0xe0, 0x09, 0x48, 0x87, 0x60, 0x20, 0x7e, 0x80, 0x1e, 0xfd, 0x28, 0x00, 0xd2, -0xb7, 0x72, 0x02, 0x98, 0x41, 0x7d, 0x02, 0x7d, 0x08, 0x02, 0x05, 0x49, 0x10, 0x43, 0x08, 0x74, -0x00, 0x0a, 0x48, 0x74, 0x03, 0xb0, 0xf0, 0xbd, 0x55, 0x01, 0xaa, 0x00, 0x80, 0x51, 0x03, 0x40, -0x8e, 0x03, 0x01, 0x20, 0xf8, 0xb5, 0xf8, 0xf7, 0xed, 0xfb, 0x54, 0x4c, 0x00, 0x20, 0xa0, 0x76, -0x53, 0x48, 0x41, 0x7a, 0xfd, 0x22, 0x11, 0x40, 0x41, 0x72, 0x41, 0x7a, 0x02, 0x22, 0x11, 0x43, -0x41, 0x72, 0x05, 0x20, 0x03, 0xf0, 0x48, 0xfb, 0x01, 0x20, 0xa0, 0x76, 0x09, 0x24, 0xe4, 0x01, -0x21, 0x46, 0x4c, 0x48, 0xf5, 0xf7, 0xb6, 0xf8, 0x21, 0x46, 0x4b, 0x48, 0xf5, 0xf7, 0xb2, 0xf8, -0x55, 0x26, 0x36, 0x01, 0x31, 0x46, 0x49, 0x48, 0xf5, 0xf7, 0xac, 0xf8, 0x48, 0x48, 0x49, 0x4f, -0xc4, 0x7d, 0xe0, 0x06, 0x07, 0xd5, 0x39, 0x46, 0x47, 0x48, 0xf5, 0xf7, 0xa5, 0xf8, 0x39, 0x46, -0x46, 0x48, 0xf5, 0xf7, 0xa1, 0xf8, 0x46, 0x4d, 0xa0, 0x07, 0x06, 0xd5, 0x28, 0x7d, 0x02, 0x28, -0x03, 0xd1, 0x31, 0x46, 0x43, 0x48, 0xf5, 0xf7, 0x95, 0xf8, 0x31, 0x46, 0x42, 0x48, 0xf5, 0xf7, -0x91, 0xf8, 0x39, 0x46, 0x41, 0x48, 0xf5, 0xf7, 0x8f, 0xf8, 0x68, 0x7a, 0x00, 0x28, 0x0a, 0xd0, -0x12, 0x21, 0x3f, 0x48, 0xf5, 0xf7, 0x88, 0xf8, 0x12, 0x21, 0x3e, 0x48, 0xf5, 0xf7, 0x84, 0xf8, -0x3d, 0x49, 0x00, 0x20, 0x08, 0x70, 0xe8, 0x79, 0x00, 0x24, 0x00, 0x28, 0x1e, 0xd9, 0x3b, 0x4f, -0x2e, 0x19, 0x5c, 0x20, 0x82, 0x57, 0x28, 0x79, 0x48, 0x23, 0x81, 0x00, 0x20, 0x46, 0x58, 0x43, -0xc0, 0x19, 0xf5, 0xf7, 0x4a, 0xf8, 0x20, 0x46, 0x12, 0x21, 0x48, 0x43, 0x29, 0x79, 0xff, 0x22, -0x40, 0x18, 0x69, 0x79, 0x80, 0x00, 0x23, 0x32, 0xc0, 0x19, 0xb2, 0x56, 0x89, 0x00, 0xf5, 0xf7, -0x3c, 0xf8, 0x64, 0x1c, 0xe8, 0x79, 0xe4, 0xb2, 0xa0, 0x42, 0xe1, 0xd8, 0xa9, 0x7a, 0x2c, 0x48, -0x2c, 0x4c, 0x01, 0x29, 0x2d, 0xd0, 0x04, 0x22, 0xa2, 0x56, 0x40, 0x21, 0xf5, 0xf7, 0x2d, 0xf8, -0x29, 0x4d, 0x40, 0x21, 0x2a, 0x7b, 0x29, 0x48, 0xf5, 0xf7, 0x27, 0xf8, 0xea, 0x7a, 0x40, 0x21, -0x27, 0x48, 0xf5, 0xf7, 0x22, 0xf8, 0xfd, 0xf7, 0xa5, 0xfd, 0xf5, 0xf7, 0x15, 0xfe, 0xff, 0xf7, -0x0d, 0xfd, 0xfc, 0xf7, 0xcf, 0xfb, 0x01, 0xf0, 0xd9, 0xfe, 0x22, 0x49, 0x00, 0x20, 0x48, 0x61, -0x21, 0x7e, 0x89, 0x1e, 0xfd, 0x29, 0x09, 0xd2, 0x1f, 0x4a, 0x38, 0x21, 0x11, 0x70, 0x1f, 0x4a, -0x3b, 0x21, 0x11, 0x70, 0x1e, 0x49, 0x88, 0x72, 0x01, 0x20, 0x08, 0x77, 0xf9, 0xf7, 0xe8, 0xff, -0xf8, 0xbd, 0x7f, 0x22, 0x40, 0x21, 0xf5, 0xf7, 0x00, 0xf8, 0xd1, 0xe7, 0x20, 0x00, 0x03, 0x40, -0x00, 0x00, 0x03, 0x40, 0x00, 0x00, 0x02, 0x20, 0x00, 0x20, 0x02, 0x20, 0x00, 0x40, 0x01, 0x20, -0xe8, 0x0d, 0x01, 0x20, 0xa8, 0x02, 0x00, 0x00, 0xf4, 0x1e, 0x01, 0x20, 0x9c, 0x21, 0x01, 0x20, -0xa8, 0x0c, 0x01, 0x20, 0x00, 0x48, 0x01, 0x20, 0x00, 0x50, 0x01, 0x20, 0x4c, 0x1c, 0x01, 0x20, -0x24, 0x1c, 0x01, 0x20, 0x38, 0x1c, 0x01, 0x20, 0x39, 0x00, 0x01, 0x20, 0x00, 0x40, 0x02, 0x20, -0x00, 0x49, 0x02, 0x20, 0x28, 0x0d, 0x01, 0x20, 0xc8, 0x0c, 0x01, 0x20, 0x40, 0x49, 0x02, 0x20, -0x80, 0x49, 0x02, 0x20, 0x00, 0x40, 0x03, 0x40, 0x60, 0x11, 0x03, 0x00, 0x60, 0x13, 0x03, 0x00, -0x20, 0x50, 0x03, 0x00, 0x70, 0x47, 0x00, 0x00, 0x05, 0x48, 0x00, 0x7d, 0x00, 0x28, 0x01, 0xd0, -0x03, 0x28, 0x03, 0xd1, 0x10, 0xb5, 0x00, 0xf0, 0x05, 0xf8, 0x10, 0xbd, 0x70, 0x47, 0x00, 0x00, -0xa8, 0x0c, 0x01, 0x20, 0xf8, 0xb5, 0x00, 0xf0, 0xd5, 0xf8, 0x59, 0x48, 0x5a, 0x4f, 0x01, 0x7f, -0x58, 0x48, 0x00, 0x90, 0x1f, 0x29, 0x6c, 0xd1, 0x58, 0x48, 0x00, 0x78, 0xff, 0x28, 0x68, 0xd1, -0x57, 0x48, 0x58, 0x4e, 0x01, 0x78, 0x00, 0x29, 0x19, 0xd1, 0x03, 0xf0, 0x91, 0xf8, 0x30, 0x78, -0x01, 0x25, 0x04, 0x07, 0x24, 0x0f, 0x03, 0xf0, 0x8b, 0xf8, 0x00, 0x20, 0x31, 0x78, 0x09, 0x07, -0x09, 0x0f, 0xa1, 0x42, 0xf3, 0xd1, 0x40, 0x1c, 0xc0, 0xb2, 0x03, 0x28, 0xf6, 0xd3, 0x00, 0x2d, -0xed, 0xd0, 0x04, 0x2c, 0x03, 0xd0, 0x4a, 0x48, 0x00, 0x78, 0x00, 0x28, 0xe5, 0xd0, 0x4a, 0x48, -0x01, 0x78, 0x00, 0x29, 0x1f, 0xd0, 0x03, 0xf0, 0x73, 0xf8, 0x47, 0x48, 0x00, 0x78, 0x00, 0x28, -0x13, 0xd1, 0x30, 0x78, 0x01, 0x25, 0x04, 0x07, 0x24, 0x0f, 0x03, 0xf0, 0x69, 0xf8, 0x00, 0x20, -0x31, 0x78, 0x09, 0x07, 0x09, 0x0f, 0xa1, 0x42, 0xf3, 0xd1, 0x40, 0x1c, 0xc0, 0xb2, 0x03, 0x28, -0xf6, 0xd3, 0x00, 0x2d, 0xed, 0xd0, 0x04, 0x2c, 0x05, 0xd0, 0xf9, 0x7f, 0x3b, 0x48, 0x00, 0x78, -0x81, 0x42, 0xe0, 0xd0, 0x25, 0xe0, 0x3a, 0x4d, 0x28, 0x7d, 0x03, 0x28, 0x10, 0xd1, 0x39, 0x4c, -0x39, 0x4e, 0xa1, 0x7e, 0x30, 0x46, 0xf4, 0xf7, 0x89, 0xff, 0x02, 0xf0, 0xaf, 0xf9, 0xa1, 0x7e, -0x30, 0x46, 0xf4, 0xf7, 0x83, 0xff, 0x01, 0xf0, 0xc5, 0xfa, 0x34, 0x49, 0x01, 0x20, 0x88, 0x70, -0x28, 0x7d, 0x01, 0x28, 0x0d, 0xd1, 0x00, 0x98, 0xc0, 0x7d, 0x80, 0x06, 0x3f, 0xd5, 0x30, 0x48, -0x41, 0x7e, 0x02, 0x7e, 0x08, 0x02, 0x10, 0x43, 0x02, 0xf0, 0x98, 0xf9, 0x2d, 0x49, 0x00, 0x20, -0x08, 0x70, 0x27, 0x4a, 0x10, 0x7d, 0x00, 0x28, 0x01, 0xd0, 0x03, 0x28, 0x11, 0xd1, 0x3b, 0x7a, -0x29, 0x49, 0x01, 0x2b, 0x03, 0xd0, 0x3b, 0x7a, 0x00, 0x2b, 0x05, 0xd0, 0x09, 0xe0, 0x4b, 0x7c, -0x1b, 0x09, 0x1b, 0x01, 0x5b, 0x1d, 0x03, 0xe0, 0x4b, 0x7c, 0x1b, 0x09, 0x1b, 0x01, 0x9b, 0x1d, -0x4b, 0x74, 0x02, 0x28, 0x1b, 0xd1, 0x90, 0x7b, 0x01, 0x28, 0x01, 0xd0, 0x02, 0x28, 0x16, 0xd1, -0x00, 0x98, 0xc0, 0x7d, 0xc0, 0x06, 0x12, 0xd5, 0x1c, 0x4c, 0xff, 0x20, 0xa0, 0x70, 0xe0, 0x78, -0x03, 0x21, 0x08, 0x43, 0xe0, 0x70, 0x20, 0x78, 0x00, 0x09, 0x00, 0x01, 0x20, 0x70, 0x64, 0x20, -0x03, 0xf0, 0xc2, 0xf9, 0x20, 0x78, 0x00, 0x09, 0x00, 0x01, 0xc0, 0x1c, 0x20, 0x70, 0x0f, 0x49, -0x00, 0x20, 0x48, 0x71, 0x12, 0x4a, 0x01, 0x21, 0x11, 0x74, 0xb8, 0x75, 0xf8, 0xbd, 0x00, 0x00, -0x28, 0x0d, 0x01, 0x20, 0xe8, 0x0d, 0x01, 0x20, 0x6c, 0x03, 0x01, 0x20, 0x2c, 0x00, 0x01, 0x20, -0x2d, 0x00, 0x01, 0x20, 0x60, 0x00, 0x03, 0x40, 0x2e, 0x00, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, -0xa8, 0x0c, 0x01, 0x20, 0x68, 0x0d, 0x01, 0x20, 0xa0, 0x86, 0x01, 0x00, 0x18, 0x00, 0x01, 0x20, -0x88, 0x0d, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, 0x00, 0x50, 0x03, 0x40, 0x80, 0x51, 0x03, 0x40, -0x60, 0x50, 0x03, 0x40, 0x70, 0xb5, 0x01, 0x24, 0x0b, 0x48, 0xe5, 0x02, 0x05, 0x60, 0x64, 0x20, -0x03, 0xf0, 0x8a, 0xf9, 0x09, 0x48, 0x01, 0x7d, 0x21, 0x43, 0x01, 0x75, 0x08, 0x48, 0x81, 0x7c, -0xcf, 0x22, 0x11, 0x40, 0x81, 0x74, 0x07, 0x48, 0x05, 0x60, 0x07, 0x48, 0x84, 0x75, 0x07, 0x4a, -0x00, 0x21, 0x51, 0x71, 0x04, 0x74, 0x70, 0xbd, 0x80, 0xe1, 0x00, 0xe0, 0x60, 0x50, 0x03, 0x40, -0x00, 0x50, 0x03, 0x40, 0x00, 0xe1, 0x00, 0xe0, 0x6c, 0x03, 0x01, 0x20, 0x18, 0x00, 0x01, 0x20, -0x01, 0x48, 0x01, 0x21, 0x41, 0x74, 0x70, 0x47, 0x6c, 0x03, 0x01, 0x20, 0xff, 0xb5, 0x53, 0x4c, -0x83, 0xb0, 0x00, 0x20, 0x0f, 0x46, 0xa0, 0x85, 0x1e, 0x46, 0x48, 0x21, 0x50, 0x48, 0xf4, 0xf7, -0xd3, 0xfe, 0x01, 0x22, 0x39, 0x46, 0x03, 0x98, 0x00, 0xf0, 0x80, 0xfb, 0xa0, 0x8d, 0x40, 0x1c, -0xa0, 0x85, 0x03, 0x9d, 0x00, 0x2d, 0x1c, 0xdb, 0x01, 0x20, 0x69, 0x46, 0x08, 0x71, 0x49, 0x48, -0x3c, 0x46, 0x01, 0x7a, 0xa1, 0x42, 0x14, 0xdd, 0x00, 0x96, 0xe1, 0xb2, 0xe8, 0xb2, 0x01, 0xab, -0x05, 0x9a, 0x00, 0xf0, 0x57, 0xfa, 0x43, 0x48, 0x64, 0x1c, 0x00, 0x7a, 0x24, 0xb2, 0xa0, 0x42, -0xf2, 0xdc, 0x68, 0x46, 0x00, 0x79, 0x00, 0x28, 0x03, 0xd1, 0x6d, 0x1e, 0x2d, 0xb2, 0x00, 0x2d, -0xe2, 0xda, 0x3a, 0x48, 0x81, 0x8d, 0x3c, 0xa0, 0x03, 0xf0, 0x1a, 0xfa, 0x39, 0x48, 0x03, 0x9d, -0xc0, 0x79, 0x6d, 0x1c, 0xa8, 0x42, 0x1e, 0xdd, 0x01, 0x20, 0x69, 0x46, 0x08, 0x71, 0x35, 0x48, -0x3c, 0x46, 0x01, 0x7a, 0xa1, 0x42, 0x16, 0xdd, 0x00, 0x96, 0xe1, 0xb2, 0xe8, 0xb2, 0x01, 0xab, -0x05, 0x9a, 0x00, 0xf0, 0x2f, 0xfa, 0x2f, 0x48, 0x64, 0x1c, 0x00, 0x7a, 0x24, 0xb2, 0xa0, 0x42, -0xf2, 0xdc, 0x68, 0x46, 0x00, 0x79, 0x00, 0x28, 0x05, 0xd1, 0x2a, 0x48, 0x6d, 0x1c, 0xc0, 0x79, -0x2d, 0xb2, 0xa8, 0x42, 0xe0, 0xdc, 0x25, 0x48, 0x81, 0x8d, 0x2f, 0xa0, 0x03, 0xf0, 0xf0, 0xf9, -0x03, 0x9d, 0x6d, 0x1e, 0x17, 0xd4, 0x01, 0x20, 0x69, 0x46, 0x08, 0x71, 0x7c, 0x1e, 0x12, 0xd4, -0x00, 0x96, 0xe1, 0xb2, 0xe8, 0xb2, 0x01, 0xab, 0x05, 0x9a, 0x00, 0xf0, 0x0b, 0xfa, 0x64, 0x1e, -0x24, 0xb2, 0x00, 0x2c, 0xf4, 0xda, 0x68, 0x46, 0x00, 0x79, 0x00, 0x28, 0x03, 0xd1, 0x6d, 0x1e, -0x2d, 0xb2, 0x00, 0x2d, 0xe7, 0xda, 0x15, 0x48, 0x81, 0x8d, 0x27, 0xa0, 0x03, 0xf0, 0xd0, 0xf9, -0x14, 0x48, 0x03, 0x9c, 0xc1, 0x79, 0xa1, 0x42, 0x19, 0xdd, 0x01, 0x20, 0x69, 0x46, 0x08, 0x71, -0x7d, 0x1e, 0x14, 0xd4, 0x00, 0x96, 0xe9, 0xb2, 0xe0, 0xb2, 0x01, 0xab, 0x05, 0x9a, 0x00, 0xf0, -0xe9, 0xf9, 0x6d, 0x1e, 0x2d, 0xb2, 0x00, 0x2d, 0xf4, 0xda, 0x68, 0x46, 0x00, 0x79, 0x00, 0x28, -0x05, 0xd1, 0x08, 0x48, 0x64, 0x1c, 0xc0, 0x79, 0x24, 0xb2, 0xa0, 0x42, 0xe5, 0xdc, 0x03, 0x48, -0x81, 0x8d, 0x1d, 0xa0, 0x03, 0xf0, 0xac, 0xf9, 0x07, 0xb0, 0xf0, 0xbd, 0xcc, 0x00, 0x01, 0x20, -0x78, 0x34, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0x43, 0x6e, 0x65, 0x67, 0x20, 0x41, 0x72, 0x65, -0x61, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x51, 0x75, 0x61, 0x64, 0x72, 0x61, 0x6e, 0x74, -0x20, 0x31, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x43, 0x6e, 0x65, 0x67, 0x20, 0x41, 0x72, 0x65, -0x61, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x51, 0x75, 0x61, 0x64, 0x72, 0x61, 0x6e, 0x74, -0x20, 0x34, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x43, 0x6e, 0x65, 0x67, 0x20, 0x41, 0x72, 0x65, -0x61, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x51, 0x75, 0x61, 0x64, 0x72, 0x61, 0x6e, 0x74, -0x20, 0x32, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x43, 0x6e, 0x65, 0x67, 0x20, 0x41, 0x72, 0x65, -0x61, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x51, 0x75, 0x61, 0x64, 0x72, 0x61, 0x6e, 0x74, -0x20, 0x33, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x30, 0xb5, 0x17, 0x48, 0x17, 0x4a, 0x85, 0xb0, -0x51, 0x79, 0x03, 0x46, 0x19, 0x72, 0x91, 0x79, 0x59, 0x72, 0x01, 0x21, 0x99, 0x72, 0xd9, 0x72, -0x00, 0x21, 0x01, 0x80, 0x41, 0x80, 0xd1, 0x79, 0x28, 0x24, 0x11, 0x4d, 0x12, 0x7a, 0x4c, 0x43, -0x64, 0x19, 0x55, 0x00, 0x64, 0x5b, 0x9c, 0x80, 0x99, 0x71, 0xda, 0x71, 0x6b, 0x46, 0x19, 0x72, -0x5a, 0x72, 0x03, 0x90, 0x00, 0xf0, 0x1e, 0xf8, 0x0a, 0x48, 0x01, 0x90, 0x0a, 0x48, 0x00, 0x90, -0x68, 0x46, 0x01, 0xf0, 0x9b, 0xf9, 0x09, 0x48, 0x01, 0x90, 0x09, 0x48, 0x00, 0x90, 0x68, 0x46, -0x01, 0xf0, 0x94, 0xf9, 0x05, 0xb0, 0x30, 0xbd, 0xb8, 0x1b, 0x01, 0x20, 0xac, 0x1b, 0x01, 0x20, -0x00, 0x50, 0x01, 0x20, 0x29, 0x2f, 0x00, 0x00, 0x93, 0x76, 0x00, 0x00, 0x31, 0x2f, 0x00, 0x00, -0x8d, 0x76, 0x00, 0x00, 0xf7, 0xb5, 0x81, 0xb0, 0x14, 0x46, 0x05, 0x46, 0x21, 0x46, 0x00, 0x92, -0x02, 0x98, 0x02, 0xf0, 0x51, 0xfa, 0x02, 0x98, 0x28, 0x21, 0x48, 0x43, 0x1c, 0x49, 0x1d, 0x4e, -0x47, 0x18, 0x05, 0xe0, 0x64, 0x1c, 0xe4, 0xb2, 0x21, 0x46, 0x02, 0x98, 0x02, 0xf0, 0x44, 0xfa, -0x60, 0x00, 0x39, 0x18, 0x02, 0x20, 0x08, 0x5e, 0xb1, 0x8b, 0x88, 0x42, 0x03, 0xdb, 0x16, 0x48, -0x80, 0x79, 0xa0, 0x42, 0xee, 0xd2, 0x29, 0x88, 0x28, 0x46, 0x4c, 0x30, 0x0c, 0x54, 0x00, 0x9c, -0x05, 0xe0, 0x64, 0x1e, 0xe4, 0xb2, 0x21, 0x46, 0x02, 0x98, 0x02, 0xf0, 0x2d, 0xfa, 0x60, 0x00, -0x38, 0x18, 0x40, 0x38, 0x3e, 0x21, 0x41, 0x5e, 0xb0, 0x8b, 0x81, 0x42, 0x01, 0xdb, 0x00, 0x2c, -0xef, 0xd1, 0x29, 0x88, 0x28, 0x46, 0x2c, 0x30, 0x0c, 0x54, 0x2a, 0x88, 0x29, 0x46, 0x0c, 0x31, -0x02, 0x98, 0x50, 0x54, 0x28, 0x88, 0x40, 0x1c, 0x28, 0x80, 0x04, 0xb0, 0xf0, 0xbd, 0x00, 0x00, -0x00, 0x50, 0x01, 0x20, 0x84, 0x2d, 0x01, 0x20, 0xac, 0x1b, 0x01, 0x20, 0xff, 0xb5, 0x50, 0x4d, -0x83, 0xb0, 0x00, 0x20, 0x0e, 0x46, 0xa8, 0x85, 0x1c, 0x46, 0x48, 0x21, 0x4d, 0x48, 0xf4, 0xf7, -0x5b, 0xfd, 0x01, 0x22, 0x31, 0x46, 0x03, 0x98, 0x00, 0xf0, 0x08, 0xfa, 0xa8, 0x8d, 0x40, 0x1c, -0xa8, 0x85, 0x03, 0x9f, 0x00, 0x2f, 0x1e, 0xd0, 0x01, 0x20, 0x69, 0x46, 0x08, 0x71, 0x46, 0x48, -0x35, 0x46, 0x01, 0x7a, 0x49, 0x1c, 0xa9, 0x42, 0x15, 0xd9, 0x00, 0x94, 0x01, 0xab, 0x29, 0x46, -0x38, 0x46, 0x05, 0x9a, 0x00, 0xf0, 0x96, 0xf9, 0x3f, 0x48, 0x6d, 0x1c, 0x00, 0x7a, 0xed, 0xb2, -0x40, 0x1c, 0xa8, 0x42, 0xf1, 0xd8, 0x68, 0x46, 0x00, 0x79, 0x00, 0x28, 0x03, 0xd1, 0x7f, 0x1e, -0x3f, 0x06, 0x3f, 0x0e, 0xe0, 0xd1, 0x03, 0x98, 0x40, 0x1c, 0xc7, 0xb2, 0x36, 0x48, 0xc0, 0x79, -0x40, 0x1c, 0xb8, 0x42, 0x21, 0xd9, 0x01, 0x20, 0x69, 0x46, 0x08, 0x71, 0x32, 0x48, 0x35, 0x46, -0x01, 0x7a, 0x49, 0x1c, 0xa9, 0x42, 0x18, 0xd9, 0x00, 0x94, 0x01, 0xab, 0x29, 0x46, 0x38, 0x46, -0x05, 0x9a, 0x00, 0xf0, 0x6f, 0xf9, 0x2c, 0x48, 0x6d, 0x1c, 0x00, 0x7a, 0xed, 0xb2, 0x40, 0x1c, -0xa8, 0x42, 0xf1, 0xd8, 0x68, 0x46, 0x00, 0x79, 0x00, 0x28, 0x06, 0xd1, 0x26, 0x48, 0x7f, 0x1c, -0xc0, 0x79, 0xff, 0xb2, 0x40, 0x1c, 0xb8, 0x42, 0xdd, 0xd8, 0x03, 0x98, 0x76, 0x1e, 0x40, 0x1e, -0xc7, 0xb2, 0x00, 0x2f, 0x18, 0xd0, 0x01, 0x20, 0x69, 0x46, 0x35, 0x06, 0x08, 0x71, 0x2d, 0x0e, -0x12, 0xd0, 0x00, 0x94, 0x01, 0xab, 0x29, 0x46, 0x38, 0x46, 0x05, 0x9a, 0x00, 0xf0, 0x4a, 0xf9, -0x6d, 0x1e, 0x2d, 0x06, 0x2d, 0x0e, 0xf4, 0xd1, 0x68, 0x46, 0x00, 0x79, 0x00, 0x28, 0x03, 0xd1, -0x7f, 0x1e, 0x3f, 0x06, 0x3f, 0x0e, 0xe6, 0xd1, 0x13, 0x48, 0x03, 0x9f, 0xc1, 0x79, 0x49, 0x1c, -0xb9, 0x42, 0x1b, 0xd9, 0x01, 0x20, 0x69, 0x46, 0x35, 0x06, 0x08, 0x71, 0x2d, 0x0e, 0x15, 0xd0, -0x00, 0x94, 0x01, 0xab, 0x29, 0x46, 0x38, 0x46, 0x05, 0x9a, 0x00, 0xf0, 0x2b, 0xf9, 0x6d, 0x1e, -0x2d, 0x06, 0x2d, 0x0e, 0xf4, 0xd1, 0x68, 0x46, 0x00, 0x79, 0x00, 0x28, 0x06, 0xd1, 0x06, 0x48, -0x7f, 0x1c, 0xc0, 0x79, 0xff, 0xb2, 0x40, 0x1c, 0xb8, 0x42, 0xe3, 0xd8, 0x07, 0xb0, 0xf0, 0xbd, -0xcc, 0x00, 0x01, 0x20, 0x78, 0x34, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0xf8, 0xb5, 0x27, 0x48, -0x00, 0x24, 0x01, 0x88, 0x00, 0x29, 0x48, 0xd9, 0x25, 0x4e, 0x24, 0x48, 0x61, 0x00, 0x0d, 0x18, -0x24, 0x4a, 0xa8, 0x78, 0xd0, 0x71, 0xe9, 0x78, 0x11, 0x72, 0x28, 0x22, 0x50, 0x43, 0x22, 0x4a, -0x49, 0x00, 0x80, 0x18, 0x21, 0x4f, 0x41, 0x5e, 0xf8, 0x79, 0x48, 0x43, 0x64, 0x21, 0xf4, 0xf7, -0xa5, 0xfc, 0x39, 0x88, 0x81, 0x42, 0x01, 0xd2, 0xb0, 0x83, 0x00, 0xe0, 0xb1, 0x83, 0xff, 0xf7, -0xab, 0xfe, 0x16, 0x4a, 0xe7, 0x00, 0x1a, 0x4b, 0xba, 0x18, 0x17, 0x46, 0x19, 0x7a, 0x20, 0x37, -0x8e, 0x46, 0xb9, 0x73, 0x59, 0x7a, 0x38, 0x46, 0xf9, 0x73, 0x9f, 0x7a, 0x8c, 0x46, 0x07, 0x74, -0xd9, 0x7a, 0x41, 0x74, 0x58, 0x88, 0x50, 0x86, 0x9b, 0x88, 0x93, 0x86, 0x70, 0x46, 0x63, 0x46, -0x38, 0x1a, 0xca, 0x1a, 0x40, 0xb2, 0x52, 0xb2, 0x01, 0x28, 0x01, 0xdc, 0x01, 0x2a, 0x06, 0xdd, -0x70, 0x46, 0x38, 0x18, 0x40, 0x08, 0xa8, 0x70, 0xc8, 0x18, 0x40, 0x08, 0xe8, 0x70, 0x03, 0x48, -0x64, 0x1c, 0x00, 0x88, 0xe4, 0xb2, 0xa0, 0x42, 0xb7, 0xd8, 0xf8, 0xbd, 0x44, 0x24, 0x01, 0x20, -0x84, 0x2d, 0x01, 0x20, 0xac, 0x1b, 0x01, 0x20, 0x00, 0x50, 0x01, 0x20, 0x1a, 0x01, 0x01, 0x20, -0xb8, 0x1b, 0x01, 0x20, 0xff, 0xb5, 0x81, 0xb0, 0x12, 0x23, 0x43, 0x43, 0x0a, 0x9c, 0x1e, 0x46, -0x1b, 0x19, 0x5b, 0x5c, 0x93, 0x42, 0x5f, 0xdb, 0x28, 0x22, 0x30, 0x4b, 0x42, 0x43, 0xd2, 0x18, -0x4b, 0x00, 0xd3, 0x18, 0x2a, 0x22, 0x9a, 0x5e, 0x28, 0x23, 0xda, 0x42, 0x54, 0xda, 0x00, 0x28, -0x52, 0xd0, 0x2b, 0x4a, 0xd2, 0x79, 0x52, 0x1e, 0x82, 0x42, 0x4d, 0xdd, 0x00, 0x29, 0x4b, 0xd0, -0x8a, 0x42, 0x49, 0xdd, 0x82, 0x1e, 0x12, 0x23, 0x5a, 0x43, 0x53, 0x18, 0x5a, 0x1e, 0xd5, 0x17, -0x6d, 0x0f, 0x5b, 0x1e, 0xad, 0x18, 0xdb, 0x10, 0xed, 0x08, 0xed, 0x00, 0x21, 0x4c, 0x52, 0x1b, -0x01, 0x25, 0xe3, 0x5c, 0x2f, 0x46, 0x97, 0x40, 0x3b, 0x42, 0x2b, 0xd1, 0x73, 0x18, 0x5a, 0x1e, -0xd6, 0x17, 0x76, 0x0f, 0x5b, 0x1e, 0xb6, 0x18, 0xdb, 0x10, 0xf6, 0x08, 0xf6, 0x00, 0x92, 0x1b, -0xe3, 0x5c, 0x2e, 0x46, 0x96, 0x40, 0x33, 0x42, 0x1c, 0xd1, 0x42, 0x1e, 0x12, 0x23, 0x5a, 0x43, -0x52, 0x18, 0xd6, 0x17, 0x76, 0x0f, 0xb6, 0x18, 0xd3, 0x10, 0xf6, 0x08, 0xf6, 0x00, 0xe3, 0x5c, -0x96, 0x1b, 0x2f, 0x46, 0xb7, 0x40, 0x3b, 0x42, 0x0c, 0xd1, 0x93, 0x1e, 0x92, 0x1e, 0xd2, 0x10, -0xa2, 0x5c, 0xdc, 0x17, 0x64, 0x0f, 0xe4, 0x18, 0xe4, 0x08, 0xe4, 0x00, 0x1b, 0x1b, 0x9d, 0x40, -0x2a, 0x42, 0x09, 0xd0, 0x01, 0x22, 0x00, 0xf0, 0xb1, 0xf8, 0x07, 0x49, 0x88, 0x8d, 0x40, 0x1c, -0x88, 0x85, 0x04, 0x98, 0x00, 0x21, 0x01, 0x70, 0x05, 0xb0, 0xf0, 0xbd, 0x00, 0x50, 0x01, 0x20, -0xa8, 0x0c, 0x01, 0x20, 0x78, 0x34, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, 0x70, 0x47, 0x70, 0x47, -0x01, 0x49, 0x08, 0x70, 0x70, 0x47, 0x00, 0x00, 0xcc, 0x00, 0x01, 0x20, 0xf8, 0xb5, 0x10, 0x4d, -0x0d, 0x4e, 0x0e, 0x4f, 0x68, 0x78, 0x00, 0x24, 0x00, 0x90, 0x03, 0x20, 0x30, 0x80, 0x78, 0x73, -0x70, 0x80, 0x38, 0x73, 0xa8, 0x78, 0x41, 0x00, 0x49, 0x19, 0x89, 0x89, 0xb1, 0x80, 0xf1, 0x80, -0x40, 0x1c, 0xc0, 0xb2, 0x00, 0x99, 0xf4, 0xf7, 0xd1, 0xfb, 0x64, 0x1c, 0x24, 0x06, 0xa9, 0x70, -0x24, 0x0e, 0xea, 0xd0, 0xf8, 0xbd, 0x00, 0x00, 0x80, 0x50, 0x03, 0x40, 0x80, 0x51, 0x03, 0x40, -0xb8, 0x2d, 0x01, 0x20, 0xf3, 0xb5, 0x09, 0x4d, 0x09, 0x4e, 0x81, 0xb0, 0x07, 0x46, 0x00, 0x24, -0x39, 0x46, 0x60, 0x19, 0xf8, 0xf7, 0x43, 0xf8, 0xa0, 0x19, 0x02, 0x99, 0xf8, 0xf7, 0x3f, 0xf8, -0x64, 0x1c, 0xe4, 0xb2, 0x0c, 0x2c, 0xf3, 0xd3, 0x03, 0xb0, 0xf0, 0xbd, 0x00, 0xd1, 0x03, 0x40, -0x0c, 0xd1, 0x03, 0x40, 0xff, 0xb5, 0x81, 0xb0, 0x28, 0x24, 0x0a, 0x9b, 0x44, 0x43, 0xe3, 0x18, -0x4c, 0x00, 0x1b, 0x5f, 0x93, 0x42, 0x4b, 0xdb, 0x82, 0x1e, 0x12, 0x23, 0x5a, 0x43, 0x53, 0x18, -0x5a, 0x1e, 0xd5, 0x17, 0x6d, 0x0f, 0x5b, 0x1e, 0xad, 0x18, 0xdb, 0x10, 0xed, 0x08, 0xed, 0x00, -0x20, 0x4c, 0x56, 0x1b, 0x01, 0x25, 0xe3, 0x5c, 0x2a, 0x46, 0xb2, 0x40, 0x13, 0x42, 0x2d, 0xd1, -0x12, 0x22, 0x42, 0x43, 0x53, 0x18, 0x5a, 0x1e, 0xd6, 0x17, 0x76, 0x0f, 0x5b, 0x1e, 0xb6, 0x18, -0xdb, 0x10, 0xf6, 0x08, 0xf6, 0x00, 0x92, 0x1b, 0xe3, 0x5c, 0x2e, 0x46, 0x96, 0x40, 0x33, 0x42, -0x1c, 0xd1, 0x42, 0x1e, 0x12, 0x23, 0x5a, 0x43, 0x52, 0x18, 0xd6, 0x17, 0x76, 0x0f, 0xb6, 0x18, -0xd3, 0x10, 0xf6, 0x08, 0xf6, 0x00, 0xe3, 0x5c, 0x96, 0x1b, 0x2f, 0x46, 0xb7, 0x40, 0x3b, 0x42, -0x0c, 0xd1, 0x93, 0x1e, 0x92, 0x1e, 0xd2, 0x10, 0xa2, 0x5c, 0xdc, 0x17, 0x64, 0x0f, 0xe4, 0x18, -0xe4, 0x08, 0xe4, 0x00, 0x1b, 0x1b, 0x9d, 0x40, 0x2a, 0x42, 0x09, 0xd0, 0x01, 0x22, 0x00, 0xf0, -0x0d, 0xf8, 0x05, 0x49, 0x88, 0x8d, 0x40, 0x1c, 0x88, 0x85, 0x04, 0x98, 0x00, 0x21, 0x01, 0x70, -0x05, 0xb0, 0xf0, 0xbd, 0x78, 0x34, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, 0x12, 0x23, 0x40, 0x1e, -0x58, 0x43, 0x40, 0x18, 0x70, 0xb4, 0x0b, 0x4e, 0x43, 0x03, 0x0a, 0x49, 0x44, 0x03, 0xa4, 0x19, -0x59, 0x18, 0x24, 0x0c, 0x0b, 0x0c, 0xe6, 0x00, 0x80, 0x1b, 0x07, 0x4d, 0x01, 0x21, 0x40, 0x1e, -0x81, 0x40, 0x28, 0x5d, 0x00, 0x2a, 0x01, 0xd0, 0x08, 0x43, 0x00, 0xe0, 0x88, 0x43, 0xe8, 0x54, -0x70, 0xbc, 0x70, 0x47, 0x00, 0xe0, 0xff, 0xff, 0x78, 0x34, 0x01, 0x20, 0x12, 0x49, 0xc9, 0x7e, -0x00, 0x29, 0x20, 0xd1, 0x10, 0xb5, 0x11, 0x49, 0x11, 0x4c, 0x09, 0x7e, 0x00, 0x28, 0x0c, 0xd0, -0x00, 0x29, 0x05, 0xd0, 0x01, 0x21, 0x0a, 0x20, 0xf9, 0xf7, 0xfc, 0xff, 0x01, 0x20, 0x0b, 0xe0, -0x00, 0x21, 0x0a, 0x20, 0xf9, 0xf7, 0xf6, 0xff, 0xf8, 0xe7, 0x00, 0x29, 0x06, 0xd0, 0x00, 0x21, -0x0a, 0x20, 0xf9, 0xf7, 0xef, 0xff, 0x00, 0x20, 0x60, 0x70, 0x10, 0xbd, 0x01, 0x21, 0x0a, 0x20, -0xf9, 0xf7, 0xe8, 0xff, 0xf7, 0xe7, 0x70, 0x47, 0x4c, 0x03, 0x01, 0x20, 0x68, 0x0d, 0x01, 0x20, -0x02, 0x00, 0x01, 0x20, 0x70, 0xb5, 0x01, 0x20, 0xff, 0xf7, 0xd0, 0xff, 0x16, 0x4d, 0x00, 0x24, -0x68, 0x79, 0x29, 0x79, 0x00, 0x02, 0x08, 0x43, 0x81, 0x00, 0x40, 0x18, 0x64, 0x21, 0xf4, 0xf7, -0xf5, 0xfa, 0x00, 0x28, 0x15, 0xd9, 0x11, 0x4e, 0x02, 0x20, 0xf8, 0xf7, 0x29, 0xf8, 0x70, 0x78, -0x00, 0x28, 0x0e, 0xd0, 0x02, 0xf0, 0xac, 0xfb, 0x68, 0x79, 0x29, 0x79, 0x00, 0x02, 0x08, 0x43, -0x81, 0x00, 0x64, 0x1c, 0x40, 0x18, 0xe4, 0xb2, 0x64, 0x21, 0xf4, 0xf7, 0xdf, 0xfa, 0xa0, 0x42, -0xea, 0xd8, 0x00, 0x20, 0xff, 0xf7, 0xaa, 0xff, 0x05, 0x48, 0xc0, 0x7e, 0xc0, 0x06, 0x02, 0xd5, -0x04, 0x20, 0xf8, 0xf7, 0x27, 0xf8, 0x70, 0xbd, 0xeb, 0x0c, 0x01, 0x20, 0x18, 0x00, 0x01, 0x20, -0xa8, 0x0d, 0x01, 0x20, 0x10, 0xb4, 0x00, 0x21, 0x08, 0x4b, 0x0c, 0x46, 0x81, 0x42, 0x05, 0xd1, -0x5a, 0x5c, 0xf0, 0x2a, 0x03, 0xd8, 0x52, 0x1c, 0x5a, 0x54, 0x00, 0xe0, 0x5c, 0x54, 0x49, 0x1c, -0xc9, 0xb2, 0x06, 0x29, 0xf2, 0xd3, 0x10, 0xbc, 0x70, 0x47, 0x00, 0x00, 0x61, 0x02, 0x01, 0x20, -0xf0, 0xb5, 0x17, 0x49, 0x00, 0x20, 0x48, 0x84, 0x16, 0x4b, 0x88, 0x84, 0xd8, 0x79, 0x01, 0x22, -0x86, 0x46, 0x01, 0x28, 0x22, 0xd3, 0x18, 0x7a, 0x13, 0x4b, 0x84, 0x46, 0x01, 0x20, 0x64, 0x46, -0x01, 0x2c, 0x17, 0xd3, 0x28, 0x24, 0x11, 0x4d, 0x54, 0x43, 0x65, 0x19, 0x46, 0x00, 0xac, 0x5f, -0x4f, 0x8c, 0xbc, 0x42, 0x03, 0xdd, 0xae, 0x5b, 0x4e, 0x84, 0x9a, 0x71, 0xd8, 0x71, 0x24, 0x26, -0x8e, 0x5f, 0xb4, 0x42, 0x02, 0xda, 0x8c, 0x84, 0x1a, 0x72, 0x58, 0x72, 0x40, 0x1c, 0xc0, 0xb2, -0x84, 0x45, 0xeb, 0xd2, 0x52, 0x1c, 0xd2, 0xb2, 0x96, 0x45, 0xdf, 0xd2, 0xf0, 0xbd, 0x00, 0x00, -0x84, 0x2d, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0xa4, 0x2d, 0x01, 0x20, 0x00, 0x50, 0x01, 0x20, -0x01, 0x80, 0x41, 0x84, 0x70, 0x47, 0x00, 0x00, 0x14, 0x4a, 0x10, 0x28, 0x06, 0xd0, 0x01, 0x07, -0x10, 0x78, 0x09, 0x0f, 0xc0, 0x06, 0xc0, 0x0e, 0x0b, 0xd0, 0x0b, 0xe0, 0x10, 0x48, 0x00, 0x78, -0xc0, 0x06, 0xc0, 0x0e, 0x10, 0x70, 0x11, 0x79, 0x49, 0x09, 0x49, 0x01, 0x01, 0x43, 0x11, 0x71, -0x70, 0x47, 0x1f, 0x20, 0x81, 0x42, 0x09, 0xd2, 0x40, 0x1a, 0xc0, 0x06, 0xc0, 0x0e, 0x10, 0x70, -0x11, 0x79, 0x49, 0x09, 0x49, 0x01, 0x01, 0x43, 0x11, 0x71, 0x70, 0x47, 0x01, 0x20, 0x10, 0x70, -0x10, 0x79, 0x40, 0x09, 0x40, 0x01, 0x40, 0x1c, 0x10, 0x71, 0x70, 0x47, 0x40, 0x14, 0x03, 0x40, -0xa8, 0x0d, 0x01, 0x20, 0x01, 0x49, 0x10, 0x20, 0x48, 0x76, 0x70, 0x47, 0x00, 0x40, 0x03, 0x40, -0xf0, 0xb4, 0x17, 0x49, 0x84, 0x46, 0x00, 0x20, 0x0f, 0x7a, 0x02, 0x46, 0x00, 0x2f, 0x25, 0xd9, -0x14, 0x4e, 0x80, 0x24, 0x61, 0x46, 0xd1, 0x40, 0xc9, 0x07, 0x0c, 0xd0, 0x00, 0x21, 0x12, 0x23, -0x4b, 0x43, 0x9b, 0x18, 0x9b, 0x00, 0xf5, 0x58, 0x49, 0x1c, 0xa5, 0x43, 0xc9, 0xb2, 0xf5, 0x50, -0x20, 0x29, 0xf4, 0xd3, 0x0e, 0xe0, 0x01, 0x21, 0x91, 0x40, 0x08, 0x43, 0x00, 0x21, 0x12, 0x23, -0x4b, 0x43, 0x9b, 0x18, 0x9b, 0x00, 0xf5, 0x58, 0x49, 0x1c, 0x25, 0x43, 0xc9, 0xb2, 0xf5, 0x50, -0x20, 0x29, 0xf4, 0xd3, 0x52, 0x1c, 0xd2, 0xb2, 0x97, 0x42, 0xdb, 0xd8, 0xf0, 0xbc, 0x70, 0x47, -0xa8, 0x0c, 0x01, 0x20, 0x00, 0x40, 0x02, 0x20, 0xf0, 0xb5, 0x18, 0x49, 0x86, 0x46, 0xc9, 0x79, -0x00, 0x20, 0x02, 0x46, 0x8c, 0x46, 0x00, 0x29, 0x27, 0xd9, 0x15, 0x4e, 0x80, 0x24, 0x71, 0x46, -0xd1, 0x40, 0xc9, 0x07, 0x0d, 0xd0, 0x00, 0x21, 0x12, 0x23, 0x17, 0x46, 0x5f, 0x43, 0x7b, 0x18, -0x9b, 0x00, 0xf5, 0x58, 0x49, 0x1c, 0xa5, 0x43, 0xc9, 0xb2, 0xf5, 0x50, 0x12, 0x29, 0xf6, 0xd3, -0x0f, 0xe0, 0x01, 0x21, 0x91, 0x40, 0x08, 0x43, 0x00, 0x21, 0x12, 0x23, 0x17, 0x46, 0x5f, 0x43, -0x7b, 0x18, 0x9b, 0x00, 0xf5, 0x58, 0x49, 0x1c, 0x25, 0x43, 0xc9, 0xb2, 0xf5, 0x50, 0x12, 0x29, -0xf6, 0xd3, 0x52, 0x1c, 0xd2, 0xb2, 0x94, 0x45, 0xd9, 0xd8, 0xf0, 0xbd, 0xa8, 0x0c, 0x01, 0x20, -0x00, 0x40, 0x02, 0x20, 0xf0, 0xb4, 0x82, 0x4b, 0x82, 0x4a, 0x19, 0x46, 0x20, 0x31, 0x84, 0x46, -0x00, 0x28, 0x7e, 0x4f, 0x10, 0x7d, 0x78, 0xd0, 0x01, 0x28, 0x03, 0xd0, 0x10, 0x7d, 0x02, 0x28, -0x75, 0xd0, 0xee, 0xe0, 0xf8, 0x7a, 0x18, 0x70, 0x38, 0x7e, 0x58, 0x70, 0xb8, 0x7e, 0x98, 0x70, -0x79, 0x48, 0x04, 0x78, 0x00, 0x79, 0x00, 0x02, 0x04, 0x43, 0x78, 0x48, 0x9c, 0x80, 0x05, 0x7c, -0x04, 0x7f, 0x24, 0x06, 0x25, 0x43, 0x04, 0x7e, 0x00, 0x7d, 0x24, 0x04, 0x00, 0x02, 0x04, 0x43, -0x25, 0x43, 0x73, 0x48, 0x9d, 0x60, 0x04, 0x78, 0x05, 0x7b, 0x2d, 0x06, 0x2c, 0x43, 0x05, 0x7a, -0x06, 0x79, 0x2d, 0x04, 0x36, 0x02, 0x35, 0x43, 0x2c, 0x43, 0xdc, 0x60, 0x00, 0x7c, 0x18, 0x74, -0x6c, 0x48, 0x04, 0x79, 0x00, 0x78, 0x24, 0x02, 0x04, 0x43, 0x6b, 0x48, 0x5c, 0x82, 0x04, 0x79, -0x1c, 0x75, 0x00, 0x7b, 0x58, 0x75, 0x69, 0x48, 0x04, 0x78, 0x9c, 0x75, 0x00, 0x7a, 0xd8, 0x75, -0x67, 0x48, 0x04, 0x7c, 0x05, 0x7f, 0x2d, 0x06, 0x2c, 0x43, 0x05, 0x7e, 0x00, 0x7d, 0x2d, 0x04, -0x00, 0x02, 0x05, 0x43, 0x2c, 0x43, 0x63, 0x48, 0x9c, 0x61, 0x04, 0x78, 0x05, 0x7b, 0x2d, 0x06, -0x2c, 0x43, 0x05, 0x7a, 0x06, 0x79, 0x2d, 0x04, 0x36, 0x02, 0x35, 0x43, 0x2c, 0x43, 0xdc, 0x61, -0x00, 0x7c, 0x08, 0x70, 0x5c, 0x48, 0x04, 0x79, 0x00, 0x78, 0x24, 0x02, 0x04, 0x43, 0x5b, 0x48, -0x5c, 0x84, 0x04, 0x79, 0x0c, 0x71, 0x00, 0x7b, 0x48, 0x71, 0x59, 0x48, 0x04, 0x78, 0x8c, 0x71, -0x00, 0x7a, 0xc8, 0x71, 0x57, 0x48, 0x00, 0x7e, 0x08, 0x72, 0x57, 0x48, 0x04, 0x79, 0x8c, 0x73, -0x40, 0x79, 0xc8, 0x73, 0x55, 0x48, 0x04, 0x7a, 0x0c, 0x74, 0x84, 0x7a, 0x4c, 0x74, 0x80, 0x6b, -0x58, 0x63, 0x53, 0x48, 0x80, 0x78, 0x08, 0x76, 0x7b, 0xe0, 0x08, 0xe0, 0xff, 0xe7, 0x38, 0x7e, -0x58, 0x70, 0x4c, 0x48, 0x03, 0x7c, 0x8b, 0x73, 0x00, 0x7d, 0xc8, 0x73, 0x71, 0xe0, 0x3c, 0x4d, -0x6c, 0x78, 0x20, 0x35, 0xae, 0x7b, 0xed, 0x7b, 0x01, 0x28, 0x03, 0xd0, 0x10, 0x7d, 0x02, 0x28, -0x63, 0xd0, 0x66, 0xe0, 0x18, 0x78, 0xf8, 0x72, 0x3c, 0x76, 0x98, 0x78, 0xb8, 0x76, 0x9f, 0x88, -0x35, 0x48, 0xfc, 0x06, 0xe4, 0x0e, 0x04, 0x70, 0x3c, 0x0a, 0x04, 0x71, 0x33, 0x4f, 0x9c, 0x68, -0x3c, 0x74, 0x20, 0x0a, 0x38, 0x75, 0x20, 0x0c, 0x38, 0x76, 0x20, 0x0e, 0x38, 0x77, 0x30, 0x4f, -0xdc, 0x68, 0x3c, 0x70, 0x20, 0x0a, 0x38, 0x71, 0x20, 0x0c, 0x38, 0x72, 0x20, 0x0e, 0x38, 0x73, -0x18, 0x7c, 0x38, 0x74, 0x2b, 0x4c, 0x58, 0x8a, 0x20, 0x70, 0x00, 0x0a, 0x20, 0x71, 0x2a, 0x48, -0x1c, 0x7d, 0x04, 0x71, 0x5c, 0x7d, 0x04, 0x73, 0x28, 0x48, 0x9c, 0x7d, 0x04, 0x70, 0xdc, 0x7d, -0x04, 0x72, 0x27, 0x4f, 0x9c, 0x69, 0x3c, 0x74, 0x20, 0x0a, 0x38, 0x75, 0x20, 0x0c, 0x38, 0x76, -0x20, 0x0e, 0x38, 0x77, 0x23, 0x4f, 0xdc, 0x69, 0x3c, 0x70, 0x20, 0x0a, 0x38, 0x71, 0x20, 0x0c, -0x38, 0x72, 0x20, 0x0e, 0x38, 0x73, 0x08, 0x78, 0x38, 0x74, 0x1f, 0x4c, 0x58, 0x8c, 0x20, 0x70, -0x00, 0x0a, 0x20, 0x71, 0x1d, 0x48, 0x0c, 0x79, 0x04, 0x71, 0x4c, 0x79, 0x04, 0x73, 0x1c, 0x48, -0x8c, 0x79, 0x04, 0x70, 0xcc, 0x79, 0x04, 0x72, 0x1a, 0x48, 0x0c, 0x7a, 0x04, 0x76, 0x1a, 0x48, -0x06, 0x71, 0x45, 0x71, 0x19, 0x48, 0x0c, 0x7c, 0x04, 0x72, 0x4c, 0x7c, 0x84, 0x72, 0x5b, 0x6b, -0x83, 0x63, 0x08, 0x7e, 0x16, 0x49, 0x88, 0x70, 0x03, 0xe0, 0x12, 0x48, 0x06, 0x74, 0x05, 0x75, -0x3c, 0x76, 0x60, 0x46, 0x50, 0x76, 0xf0, 0xbc, 0x70, 0x47, 0x00, 0x00, 0x20, 0x50, 0x03, 0x40, -0xa8, 0x2e, 0x01, 0x20, 0x6c, 0x03, 0x01, 0x20, 0x40, 0x14, 0x03, 0x40, 0x00, 0x11, 0x03, 0x40, -0x20, 0x11, 0x03, 0x40, 0x40, 0x11, 0x03, 0x40, 0x60, 0x11, 0x03, 0x40, 0x80, 0x11, 0x03, 0x40, -0x00, 0x13, 0x03, 0x40, 0x20, 0x13, 0x03, 0x40, 0x40, 0x13, 0x03, 0x40, 0x60, 0x13, 0x03, 0x40, -0x80, 0x13, 0x03, 0x40, 0x20, 0x14, 0x03, 0x40, 0x60, 0x50, 0x03, 0x40, 0x40, 0x50, 0x03, 0x40, -0xe0, 0x50, 0x03, 0x40, 0xf0, 0xb4, 0x94, 0x46, 0x14, 0x4b, 0x02, 0x46, 0x00, 0x20, 0x1d, 0x7a, -0x04, 0x46, 0x00, 0x2d, 0x20, 0xd9, 0x63, 0x46, 0xe3, 0x40, 0xdb, 0x07, 0x13, 0xd0, 0x0f, 0x4d, -0x00, 0x23, 0xee, 0x79, 0x00, 0x2e, 0x11, 0xd9, 0x65, 0x00, 0x24, 0x27, 0x1e, 0x46, 0x7e, 0x43, -0x77, 0x18, 0x7f, 0x5b, 0xb6, 0x18, 0x77, 0x53, 0x08, 0x4e, 0x5b, 0x1c, 0xf6, 0x79, 0xdb, 0xb2, -0x9e, 0x42, 0xf2, 0xd8, 0x02, 0xe0, 0x01, 0x23, 0xa3, 0x40, 0x18, 0x43, 0x03, 0x4b, 0x64, 0x1c, -0x1b, 0x7a, 0xe4, 0xb2, 0xa3, 0x42, 0xde, 0xd8, 0xf0, 0xbc, 0x70, 0x47, 0xa8, 0x0c, 0x01, 0x20, -0xf7, 0xb5, 0x8c, 0x46, 0x15, 0x49, 0x86, 0x46, 0x00, 0x20, 0xca, 0x79, 0x03, 0x46, 0x00, 0x2a, -0x21, 0xd9, 0x02, 0x99, 0xd9, 0x40, 0xc9, 0x07, 0x14, 0xd0, 0x10, 0x4c, 0x00, 0x22, 0x21, 0x7a, -0x00, 0x29, 0x12, 0xd9, 0x24, 0x21, 0x1d, 0x46, 0x4d, 0x43, 0x61, 0x46, 0x6f, 0x18, 0x75, 0x44, -0x21, 0x46, 0x54, 0x00, 0x3e, 0x5b, 0x2e, 0x53, 0x52, 0x1c, 0x0c, 0x7a, 0xd2, 0xb2, 0x94, 0x42, -0xf7, 0xd8, 0x02, 0xe0, 0x01, 0x21, 0x99, 0x40, 0x08, 0x43, 0x04, 0x49, 0x5b, 0x1c, 0xc9, 0x79, -0xdb, 0xb2, 0x99, 0x42, 0xdd, 0xd8, 0x03, 0xb0, 0xf0, 0xbd, 0x00, 0x00, 0xa8, 0x0c, 0x01, 0x20, -0x0e, 0x48, 0x00, 0x7e, 0x01, 0x28, 0x17, 0xd1, 0x10, 0xb5, 0x0d, 0x4c, 0x20, 0x7d, 0x01, 0x28, -0x01, 0xd0, 0x02, 0x28, 0x04, 0xd1, 0x0b, 0x48, 0x81, 0x7c, 0xcf, 0x22, 0x11, 0x40, 0x81, 0x74, -0x02, 0xf0, 0xba, 0xf8, 0x20, 0x7d, 0x00, 0x28, 0x01, 0xd0, 0x03, 0x28, 0x01, 0xd1, 0xff, 0xf7, -0x59, 0xf8, 0x02, 0xf0, 0x2b, 0xf8, 0x10, 0xbd, 0x70, 0x47, 0x00, 0x00, 0x28, 0x0d, 0x01, 0x20, -0xa8, 0x0c, 0x01, 0x20, 0x00, 0x50, 0x03, 0x40, 0x70, 0x47, 0x00, 0x00, 0xf8, 0xb5, 0x58, 0x48, -0x80, 0x8a, 0x58, 0x49, 0x40, 0x05, 0x40, 0x0d, 0x08, 0x1a, 0x57, 0x4f, 0x57, 0x49, 0x86, 0xb2, -0x78, 0x78, 0x4c, 0x03, 0x64, 0x0b, 0x56, 0x4d, 0x00, 0x28, 0x12, 0xd0, 0x01, 0x28, 0x0f, 0xd1, -0x00, 0x22, 0x7a, 0x70, 0xa9, 0x5e, 0xe8, 0x68, 0x40, 0x18, 0x52, 0x49, 0x0b, 0x78, 0x03, 0x70, -0x49, 0x78, 0x41, 0x70, 0x4a, 0x48, 0x04, 0x60, 0x42, 0x60, 0x4f, 0x49, 0x01, 0x20, 0x48, 0x77, -0xf8, 0xbd, 0x07, 0x2e, 0xfc, 0xd3, 0x05, 0x21, 0x4c, 0x48, 0xf5, 0xf7, 0x55, 0xfe, 0x02, 0x46, -0x4a, 0x48, 0x01, 0x79, 0xc0, 0x78, 0x09, 0x02, 0x01, 0x43, 0x43, 0x48, 0x81, 0x80, 0x47, 0x48, -0x83, 0x79, 0x47, 0x79, 0x1b, 0x02, 0x3b, 0x43, 0x3f, 0x4f, 0xfb, 0x80, 0x87, 0x78, 0x40, 0x78, -0x3f, 0x02, 0x38, 0x43, 0x3c, 0x4f, 0x78, 0x80, 0x1f, 0x27, 0xff, 0x01, 0xc7, 0x1b, 0x80, 0x2f, -0x05, 0xd3, 0x93, 0x42, 0x01, 0xd1, 0x3e, 0x4f, 0x00, 0xe0, 0x3e, 0x4f, 0x2f, 0x61, 0x36, 0x4f, -0x93, 0x42, 0xd5, 0xd1, 0x39, 0x4a, 0x00, 0x29, 0x5f, 0xd0, 0x13, 0x78, 0x3b, 0x70, 0xf0, 0x2b, -0x2c, 0xd0, 0xf1, 0x2b, 0xcc, 0xd1, 0x01, 0x26, 0x7e, 0x70, 0xfd, 0xf7, 0xa1, 0xff, 0x78, 0x88, -0xfe, 0xf7, 0x1c, 0xf9, 0x28, 0x88, 0x81, 0xb2, 0xe8, 0x68, 0xf5, 0xf7, 0x1d, 0xfe, 0x00, 0x22, -0xaa, 0x5e, 0xe9, 0x68, 0x89, 0x18, 0x0b, 0x78, 0x2a, 0x4a, 0x13, 0x70, 0x4b, 0x78, 0x53, 0x70, -0x08, 0x70, 0x00, 0x0a, 0x48, 0x70, 0x22, 0x49, 0x0c, 0x60, 0x00, 0x20, 0x48, 0x60, 0x26, 0x4a, -0x56, 0x77, 0x28, 0x5e, 0x00, 0x28, 0xab, 0xdd, 0xeb, 0x68, 0x5b, 0x03, 0x5b, 0x0b, 0x0b, 0x60, -0x80, 0x1c, 0x40, 0x05, 0x40, 0x0d, 0x48, 0x60, 0x56, 0x77, 0xf8, 0xbd, 0x08, 0x46, 0x09, 0x30, -0xb0, 0x42, 0xfa, 0xd8, 0x14, 0x46, 0xd0, 0x1d, 0xf5, 0xf7, 0xf6, 0xfd, 0x02, 0x46, 0xb9, 0x88, -0x1d, 0x48, 0x0b, 0x18, 0x58, 0x78, 0x1b, 0x78, 0x00, 0x02, 0x18, 0x43, 0xf8, 0x80, 0x7e, 0x88, -0x1f, 0x23, 0xdb, 0x01, 0xf3, 0x1a, 0x80, 0x2b, 0x05, 0xd3, 0x90, 0x42, 0x01, 0xd1, 0x14, 0x4b, -0x00, 0xe0, 0x16, 0x4b, 0x2b, 0x61, 0x90, 0x42, 0xdf, 0xd1, 0x00, 0x25, 0x00, 0x29, 0xdc, 0xd9, -0x78, 0x88, 0x41, 0x1c, 0x79, 0x80, 0x61, 0x19, 0xc9, 0x79, 0x02, 0xf0, 0x63, 0xf8, 0x6d, 0x1c, -0xb8, 0x88, 0xad, 0xb2, 0xa8, 0x42, 0xf3, 0xd8, 0xf8, 0xbd, 0x10, 0x78, 0x38, 0x70, 0xf8, 0xbd, -0x40, 0x80, 0x03, 0x40, 0x02, 0x02, 0x00, 0x00, 0x58, 0x00, 0x01, 0x20, 0xa0, 0x04, 0x01, 0x20, -0x44, 0x00, 0x01, 0x20, 0x4a, 0x00, 0x01, 0x20, 0x00, 0x80, 0x03, 0x40, 0xa4, 0x0a, 0x01, 0x20, -0xaa, 0x55, 0xaa, 0x55, 0xbb, 0x44, 0xbb, 0x44, 0xab, 0x0a, 0x01, 0x20, 0xcc, 0x33, 0xcc, 0x33, -0xf8, 0xb5, 0x28, 0x4f, 0xb8, 0x8a, 0x28, 0x49, 0x40, 0x05, 0x40, 0x0d, 0x08, 0x1a, 0x27, 0x4e, -0x27, 0x49, 0x84, 0xb2, 0x70, 0x78, 0x4d, 0x03, 0x6d, 0x0b, 0x01, 0x23, 0x00, 0x28, 0x08, 0xd0, -0x01, 0x28, 0x05, 0xd1, 0x00, 0x20, 0x70, 0x70, 0x3d, 0x60, 0x78, 0x60, 0x21, 0x48, 0x43, 0x77, -0xf8, 0xbd, 0x03, 0x2c, 0xfc, 0xd3, 0x20, 0x48, 0x01, 0x78, 0x31, 0x70, 0x42, 0x78, 0x80, 0x78, -0x12, 0x02, 0x10, 0x18, 0x80, 0xb2, 0x70, 0x80, 0xf0, 0x29, 0x1a, 0xd0, 0xf1, 0x29, 0xef, 0xd1, -0x1c, 0x46, 0x73, 0x70, 0xfd, 0xf7, 0x04, 0xff, 0x70, 0x88, 0xfe, 0xf7, 0x7f, 0xf8, 0x3d, 0x60, -0x00, 0x20, 0x78, 0x60, 0x13, 0x4a, 0x54, 0x77, 0x14, 0x49, 0x08, 0x5e, 0x00, 0x28, 0xdf, 0xdd, -0xc9, 0x68, 0x49, 0x03, 0x49, 0x0b, 0x39, 0x60, 0x40, 0x05, 0x40, 0x0d, 0x78, 0x60, 0x54, 0x77, -0xf8, 0xbd, 0x00, 0x25, 0xe4, 0x1e, 0x00, 0x2c, 0xfa, 0xdd, 0x0b, 0x4f, 0x70, 0x88, 0x41, 0x1c, -0x71, 0x80, 0x79, 0x19, 0xc9, 0x78, 0x01, 0xf0, 0xf5, 0xff, 0x6d, 0x1c, 0xad, 0xb2, 0xa5, 0x42, -0xf4, 0xdb, 0xf8, 0xbd, 0x40, 0x80, 0x03, 0x40, 0x02, 0x02, 0x00, 0x00, 0x58, 0x00, 0x01, 0x20, -0xa0, 0x04, 0x01, 0x20, 0x00, 0x80, 0x03, 0x40, 0xa4, 0x0a, 0x01, 0x20, 0x44, 0x00, 0x01, 0x20, -0x70, 0xb5, 0x13, 0x48, 0x01, 0x25, 0x41, 0x78, 0x80, 0x78, 0x12, 0x4c, 0x00, 0x29, 0x0c, 0xd0, -0x00, 0x28, 0x19, 0xd0, 0xff, 0xf7, 0xca, 0xfe, 0x0f, 0x48, 0x10, 0x49, 0x42, 0x03, 0x10, 0x48, -0x52, 0x0b, 0x02, 0x61, 0x41, 0x61, 0x65, 0x76, 0x70, 0xbd, 0x00, 0x28, 0x09, 0xd0, 0x00, 0xf0, -0x1b, 0xf8, 0x65, 0x76, 0x20, 0x7e, 0x00, 0x06, 0xfc, 0xd4, 0x0a, 0x49, 0x00, 0x20, 0x48, 0x80, -0x70, 0xbd, 0x00, 0xf0, 0xdd, 0xf8, 0xf4, 0xe7, 0xff, 0xf7, 0x7a, 0xff, 0xe4, 0xe7, 0x00, 0x00, -0x4c, 0x00, 0x01, 0x20, 0x00, 0x80, 0x03, 0x40, 0xa4, 0x0a, 0x01, 0x20, 0x02, 0x02, 0x00, 0x00, -0x40, 0x80, 0x03, 0x40, 0x44, 0x00, 0x01, 0x20, 0xf8, 0xb5, 0x59, 0x4e, 0x30, 0x7e, 0x59, 0x4c, -0xc1, 0x06, 0xc9, 0x0e, 0x00, 0x20, 0x62, 0x88, 0x00, 0x29, 0x07, 0xd9, 0x56, 0x4b, 0x35, 0x7a, -0x17, 0x18, 0x40, 0x1c, 0x80, 0xb2, 0xdd, 0x55, 0x88, 0x42, 0xf8, 0xd3, 0x50, 0x18, 0x81, 0xb2, -0x52, 0x4d, 0x61, 0x80, 0x68, 0x78, 0x00, 0x28, 0x0f, 0xd0, 0x01, 0x28, 0x0c, 0xd1, 0x00, 0x20, -0x68, 0x70, 0x00, 0x21, 0x61, 0x5e, 0xe0, 0x68, 0x40, 0x18, 0x4d, 0x49, 0x0a, 0x78, 0x02, 0x70, -0x49, 0x78, 0x41, 0x70, 0x00, 0xf0, 0xf4, 0xf8, 0xf8, 0xbd, 0x07, 0x29, 0xfc, 0xd3, 0x05, 0x21, -0x45, 0x48, 0xf5, 0xf7, 0xf1, 0xfc, 0x44, 0x49, 0x0a, 0x79, 0xcb, 0x78, 0x11, 0x02, 0x19, 0x43, -0x41, 0x4b, 0xa9, 0x80, 0x9a, 0x79, 0x5f, 0x79, 0x12, 0x02, 0x3a, 0x43, 0xea, 0x80, 0x9f, 0x78, -0x5b, 0x78, 0x3f, 0x02, 0x1f, 0x43, 0x1f, 0x23, 0xdb, 0x01, 0xfb, 0x1a, 0x6f, 0x80, 0x80, 0x2b, -0x05, 0xd3, 0x82, 0x42, 0x01, 0xd1, 0x3b, 0x4b, 0x00, 0xe0, 0x3b, 0x4b, 0x23, 0x61, 0x82, 0x42, -0xda, 0xd1, 0x00, 0x29, 0xd8, 0xd0, 0x34, 0x48, 0x02, 0x78, 0x2a, 0x70, 0xf0, 0x2a, 0x2f, 0xd0, -0xf1, 0x2a, 0xd1, 0xd1, 0x01, 0x20, 0x68, 0x70, 0x38, 0x46, 0xfd, 0xf7, 0x41, 0xfe, 0x68, 0x88, -0xfd, 0xf7, 0xbc, 0xff, 0x20, 0x88, 0x81, 0xb2, 0xe0, 0x68, 0xf5, 0xf7, 0xbd, 0xfc, 0x00, 0x22, -0xa2, 0x5e, 0xe1, 0x68, 0x89, 0x18, 0x0b, 0x78, 0x29, 0x4a, 0x13, 0x70, 0x4b, 0x78, 0x53, 0x70, -0x08, 0x70, 0x00, 0x0a, 0x48, 0x70, 0xe1, 0x68, 0x00, 0x20, 0x0a, 0x5c, 0x32, 0x73, 0x40, 0x1c, -0x80, 0xb2, 0x07, 0x28, 0xf9, 0xd3, 0x07, 0x20, 0xa0, 0x80, 0x01, 0x21, 0x23, 0x48, 0x89, 0x06, -0x01, 0x60, 0x23, 0x4a, 0x11, 0x60, 0x89, 0x00, 0x01, 0x60, 0x22, 0x48, 0x01, 0x60, 0xf8, 0xbd, -0x0a, 0x46, 0x63, 0x88, 0x09, 0x32, 0x9a, 0x42, 0xf9, 0xd8, 0x06, 0x46, 0xc0, 0x1d, 0xf5, 0xf7, -0x93, 0xfc, 0x02, 0x46, 0xa9, 0x88, 0x1c, 0x48, 0x0b, 0x18, 0x58, 0x78, 0x1b, 0x78, 0x00, 0x02, -0x18, 0x43, 0xe8, 0x80, 0x6f, 0x88, 0x1f, 0x23, 0xdb, 0x01, 0xfb, 0x1a, 0x80, 0x2b, 0x05, 0xd3, -0x90, 0x42, 0x01, 0xd1, 0x0f, 0x4b, 0x00, 0xe0, 0x14, 0x4b, 0x23, 0x61, 0x90, 0x42, 0xde, 0xd1, -0x00, 0x24, 0x00, 0x29, 0xdb, 0xd9, 0x68, 0x88, 0x41, 0x1c, 0x69, 0x80, 0x31, 0x19, 0xc9, 0x79, -0x01, 0xf0, 0x00, 0xff, 0x64, 0x1c, 0xa8, 0x88, 0xa4, 0xb2, 0xa0, 0x42, 0xf3, 0xd8, 0xf8, 0xbd, -0x00, 0x80, 0x03, 0x40, 0x44, 0x00, 0x01, 0x20, 0xa4, 0x0a, 0x01, 0x20, 0x58, 0x00, 0x01, 0x20, -0x4a, 0x00, 0x01, 0x20, 0xaa, 0x55, 0xaa, 0x55, 0xbb, 0x44, 0xbb, 0x44, 0x80, 0xe2, 0x00, 0xe0, -0x00, 0xe1, 0x00, 0xe0, 0x80, 0xe1, 0x00, 0xe0, 0xab, 0x0a, 0x01, 0x20, 0xcc, 0x33, 0xcc, 0x33, -0xf8, 0xb5, 0x22, 0x4f, 0x38, 0x7e, 0x22, 0x4e, 0xc5, 0x06, 0x70, 0x78, 0xed, 0x0e, 0x00, 0x28, -0x06, 0xd0, 0x01, 0x28, 0x03, 0xd1, 0x00, 0x20, 0x70, 0x70, 0x00, 0xf0, 0x41, 0xf8, 0xf8, 0xbd, -0x03, 0x2d, 0xfc, 0xd3, 0x38, 0x7a, 0x30, 0x70, 0x38, 0x7a, 0x39, 0x7a, 0x00, 0x02, 0x40, 0x18, -0x70, 0x80, 0x30, 0x78, 0xf0, 0x28, 0x19, 0xd0, 0xf1, 0x28, 0xf0, 0xd1, 0x01, 0x20, 0x70, 0x70, -0x00, 0x24, 0x70, 0x88, 0x41, 0x1c, 0x71, 0x80, 0xfd, 0xf7, 0xaa, 0xfd, 0x38, 0x73, 0x64, 0x1c, -0xe4, 0xb2, 0x07, 0x2c, 0xf5, 0xd3, 0x01, 0x21, 0x0e, 0x48, 0x89, 0x06, 0x01, 0x60, 0x0e, 0x4a, -0x11, 0x60, 0x89, 0x00, 0x01, 0x60, 0x0d, 0x48, 0x01, 0x60, 0xf8, 0xbd, 0x00, 0x24, 0xed, 0x1e, -0x00, 0x2d, 0xfa, 0xdd, 0x70, 0x88, 0x41, 0x1c, 0x71, 0x80, 0x39, 0x7a, 0x01, 0xf0, 0xa2, 0xfe, -0x64, 0x1c, 0xe4, 0xb2, 0xac, 0x42, 0xf5, 0xdb, 0xf8, 0xbd, 0x00, 0x00, 0x00, 0x80, 0x03, 0x40, -0x58, 0x00, 0x01, 0x20, 0x80, 0xe2, 0x00, 0xe0, 0x00, 0xe1, 0x00, 0xe0, 0x80, 0xe1, 0x00, 0xe0, -0x08, 0x48, 0x01, 0x21, 0x41, 0x77, 0x01, 0x7f, 0x09, 0x06, 0xfc, 0xd4, 0x01, 0x20, 0x06, 0x49, -0x80, 0x06, 0x08, 0x60, 0x05, 0x4a, 0x10, 0x60, 0x80, 0x00, 0x08, 0x60, 0x04, 0x49, 0x08, 0x60, -0x70, 0x47, 0x00, 0x00, 0x00, 0x80, 0x03, 0x40, 0x80, 0xe2, 0x00, 0xe0, 0x80, 0xe1, 0x00, 0xe0, -0x00, 0xe1, 0x00, 0xe0, 0x20, 0x48, 0x41, 0x78, 0x00, 0x29, 0x3c, 0xd1, 0xf8, 0xb5, 0x1f, 0x4e, -0x31, 0x7e, 0x1f, 0x4f, 0xcd, 0x06, 0x82, 0x78, 0xed, 0x0e, 0x01, 0x21, 0x78, 0x78, 0x00, 0x2a, -0x06, 0xd0, 0x00, 0x28, 0x1f, 0xd0, 0x38, 0x78, 0xf1, 0x28, 0x00, 0xd1, 0x71, 0x76, 0xf8, 0xbd, -0x00, 0x28, 0xfb, 0xd1, 0x30, 0x7a, 0x38, 0x70, 0xf0, 0x28, 0xf8, 0xd1, 0x79, 0x70, 0x30, 0x7a, -0x31, 0x7a, 0x00, 0x02, 0x40, 0x18, 0x00, 0x24, 0xed, 0x1e, 0x78, 0x80, 0x00, 0x2d, 0xee, 0xdd, -0x78, 0x88, 0x41, 0x1c, 0x79, 0x80, 0x31, 0x7a, 0x01, 0xf0, 0x4c, 0xfe, 0x64, 0x1c, 0xe4, 0xb2, -0xac, 0x42, 0xf5, 0xdb, 0xf8, 0xbd, 0x0b, 0x4a, 0x00, 0x20, 0x51, 0x88, 0x00, 0x2d, 0x07, 0xd9, -0x09, 0x4b, 0x34, 0x7a, 0x0f, 0x18, 0x40, 0x1c, 0xc0, 0xb2, 0xdc, 0x55, 0xa8, 0x42, 0xf8, 0xd3, -0x48, 0x19, 0x50, 0x80, 0xf8, 0xbd, 0x70, 0x47, 0x4c, 0x00, 0x01, 0x20, 0x00, 0x80, 0x03, 0x40, -0x58, 0x00, 0x01, 0x20, 0x44, 0x00, 0x01, 0x20, 0xa4, 0x0a, 0x01, 0x20, 0x70, 0x47, 0x00, 0x00, -0x30, 0xb4, 0x00, 0x23, 0x1a, 0x48, 0x01, 0x22, 0x03, 0x70, 0x42, 0x70, 0x82, 0x70, 0x19, 0x48, -0x01, 0x78, 0xab, 0x24, 0x21, 0x40, 0x01, 0x70, 0x01, 0x78, 0xdf, 0x24, 0x21, 0x40, 0x0b, 0x24, -0x21, 0x43, 0x01, 0x70, 0x41, 0x78, 0xc9, 0x06, 0xc9, 0x0e, 0x80, 0x31, 0x41, 0x70, 0xc1, 0x78, -0x83, 0x24, 0x21, 0x43, 0xc1, 0x70, 0x10, 0x49, 0x0a, 0x71, 0xff, 0x24, 0x0c, 0x70, 0x0c, 0x7f, -0x53, 0x25, 0x24, 0x07, 0x24, 0x0f, 0x2c, 0x43, 0x0c, 0x77, 0x0c, 0x49, 0x0c, 0x4c, 0x4d, 0x03, -0x0c, 0x49, 0x6d, 0x0b, 0x0d, 0x61, 0x4c, 0x61, 0x42, 0x76, 0x0b, 0x48, 0x49, 0x06, 0x43, 0x70, -0x0a, 0x48, 0x01, 0x60, 0x41, 0x05, 0x01, 0x60, 0x62, 0xb6, 0x30, 0xbc, 0x70, 0x47, 0x00, 0x00, -0x4c, 0x00, 0x01, 0x20, 0x00, 0x80, 0x03, 0x40, 0x20, 0x80, 0x03, 0x40, 0xa4, 0x0a, 0x01, 0x20, -0x02, 0x02, 0x00, 0x00, 0x40, 0x80, 0x03, 0x40, 0x58, 0x00, 0x01, 0x20, 0x00, 0xe1, 0x00, 0xe0, -0x03, 0x48, 0x41, 0x78, 0x00, 0x29, 0x01, 0xd0, 0x00, 0x21, 0x41, 0x70, 0x70, 0x47, 0x00, 0x00, -0x18, 0x00, 0x01, 0x20, 0x1a, 0x48, 0x41, 0x78, 0x00, 0x29, 0x2f, 0xd1, 0xf8, 0xb5, 0x19, 0x4e, -0x31, 0x7f, 0x80, 0x78, 0xcd, 0x06, 0xed, 0x0e, 0x00, 0x28, 0x0e, 0xd0, 0x16, 0x4b, 0x00, 0x20, -0x99, 0x88, 0x2d, 0x1f, 0x00, 0x2d, 0x1e, 0xdd, 0xdc, 0x68, 0x1a, 0x5e, 0x64, 0x18, 0x92, 0x1c, -0x0f, 0x18, 0x97, 0x42, 0x11, 0xda, 0x27, 0x5c, 0x10, 0xe0, 0x00, 0x24, 0x2d, 0x1f, 0x00, 0x2d, -0x0a, 0xdd, 0x0e, 0x4f, 0x78, 0x88, 0x41, 0x1c, 0x79, 0x80, 0xfd, 0xf7, 0xa1, 0xfc, 0x30, 0x73, -0x64, 0x1c, 0xe4, 0xb2, 0xac, 0x42, 0xf5, 0xdb, 0xf8, 0xbd, 0xff, 0x27, 0x37, 0x73, 0x40, 0x1c, -0xc0, 0xb2, 0xa8, 0x42, 0xe4, 0xdb, 0x08, 0x18, 0x98, 0x80, 0xf8, 0xbd, 0x70, 0x47, 0x00, 0x00, -0x4c, 0x00, 0x01, 0x20, 0x00, 0x80, 0x03, 0x40, 0x44, 0x00, 0x01, 0x20, 0x58, 0x00, 0x01, 0x20, -0x70, 0x47, 0x00, 0x00, 0x10, 0xb5, 0x09, 0x4c, 0x21, 0x69, 0x03, 0x22, 0x11, 0x43, 0x21, 0x61, -0x01, 0x21, 0x07, 0x4a, 0x49, 0x03, 0x11, 0x60, 0x00, 0x21, 0xa1, 0x61, 0x05, 0x49, 0x48, 0x43, -0x05, 0x49, 0xf3, 0xf7, 0xab, 0xfc, 0x60, 0x61, 0x10, 0xbd, 0x00, 0x00, 0x00, 0x20, 0x03, 0x40, -0x00, 0xe1, 0x00, 0xe0, 0x40, 0x42, 0x0f, 0x00, 0xa0, 0x86, 0x01, 0x00, 0xf0, 0xb5, 0x00, 0x20, -0x83, 0xb0, 0x04, 0x46, 0x00, 0x90, 0x02, 0x20, 0xf8, 0xf7, 0x3a, 0xfe, 0x02, 0x90, 0x27, 0x48, -0x01, 0x90, 0x02, 0x7a, 0xd0, 0x07, 0x41, 0xd0, 0x25, 0x48, 0x00, 0x88, 0x00, 0x28, 0x02, 0xd0, -0x00, 0x21, 0x24, 0x48, 0x26, 0xe0, 0x24, 0x49, 0x08, 0x7a, 0x4d, 0x7a, 0x41, 0x1e, 0x40, 0x1c, -0xc9, 0xb2, 0x86, 0x46, 0x71, 0x45, 0x27, 0xd8, 0x68, 0x1e, 0x84, 0x46, 0x1f, 0x48, 0x97, 0x08, -0x43, 0x7a, 0x00, 0x7a, 0x1b, 0x06, 0x1e, 0x14, 0x06, 0x43, 0x6d, 0x1c, 0x60, 0x46, 0xc0, 0xb2, -0xa8, 0x42, 0x15, 0xd8, 0x28, 0x23, 0x0a, 0x46, 0x5a, 0x43, 0x02, 0x9b, 0xd2, 0x18, 0x43, 0x00, -0xd3, 0x5e, 0xb3, 0x42, 0x08, 0xda, 0x64, 0x1c, 0xe4, 0xb2, 0xa7, 0x42, 0x04, 0xd8, 0x11, 0x48, -0x81, 0x78, 0x49, 0x1c, 0x81, 0x70, 0x0a, 0xe0, 0x40, 0x1c, 0xc0, 0xb2, 0xa8, 0x42, 0xee, 0xd9, -0x49, 0x1c, 0xc9, 0xb2, 0x71, 0x45, 0xe1, 0xd9, 0x0a, 0x49, 0x00, 0x20, 0x88, 0x70, 0x01, 0x98, -0xc1, 0x7a, 0x08, 0x48, 0x82, 0x78, 0x91, 0x42, 0x02, 0xd9, 0x00, 0x98, 0x03, 0xb0, 0xf0, 0xbd, -0x00, 0x21, 0x81, 0x70, 0x01, 0x20, 0x00, 0x90, 0x03, 0xb0, 0xf0, 0xbd, 0x08, 0x0e, 0x01, 0x20, -0x44, 0x24, 0x01, 0x20, 0xb0, 0x00, 0x01, 0x20, 0xa4, 0x2d, 0x01, 0x20, 0x09, 0x0e, 0x01, 0x20, -0x04, 0x48, 0x01, 0x69, 0x89, 0x08, 0x89, 0x00, 0x01, 0x61, 0x01, 0x20, 0x02, 0x49, 0x40, 0x03, -0x08, 0x60, 0x70, 0x47, 0x00, 0x20, 0x03, 0x40, 0x80, 0xe1, 0x00, 0xe0, 0xf0, 0xb5, 0x05, 0x46, -0x8b, 0xb0, 0x00, 0x7a, 0x01, 0x90, 0x68, 0x7a, 0x03, 0x90, 0xe8, 0x68, 0x00, 0x90, 0x01, 0x20, -0x05, 0x90, 0x69, 0x68, 0x01, 0x98, 0x88, 0x47, 0x00, 0x28, 0x7d, 0xd0, 0x00, 0x98, 0x54, 0x4e, -0x20, 0x30, 0x0a, 0x90, 0x00, 0x98, 0x40, 0x30, 0x09, 0x90, 0x00, 0x98, 0x2b, 0x30, 0x08, 0x90, -0x00, 0x98, 0x4b, 0x30, 0x07, 0x90, 0x05, 0x98, 0x00, 0x28, 0x0b, 0xd0, 0x00, 0x20, 0x05, 0x90, -0x0a, 0x98, 0x00, 0x7b, 0x40, 0x1e, 0xc4, 0xb2, 0x09, 0x98, 0x00, 0x7b, 0x40, 0x1c, 0xc0, 0xb2, -0x04, 0x90, 0x0a, 0xe0, 0x00, 0x98, 0x08, 0x99, 0x00, 0x88, 0x41, 0x5c, 0x49, 0x1e, 0xcc, 0xb2, -0x07, 0x99, 0x40, 0x5c, 0x40, 0x1c, 0xc0, 0xb2, 0x04, 0x90, 0x00, 0x20, 0x06, 0x90, 0x02, 0x90, -0x04, 0x98, 0x84, 0x42, 0x79, 0xd2, 0x29, 0x68, 0x01, 0x98, 0x88, 0x47, 0x28, 0x21, 0x48, 0x43, -0x3c, 0x49, 0x67, 0x00, 0x40, 0x18, 0xc0, 0x5f, 0xb1, 0x8b, 0x88, 0x42, 0x16, 0xdd, 0x01, 0x20, -0x06, 0x90, 0x29, 0x68, 0x01, 0x98, 0x88, 0x47, 0x28, 0x21, 0x48, 0x43, 0x35, 0x49, 0x40, 0x18, -0xc1, 0x5f, 0x02, 0x98, 0x81, 0x42, 0x09, 0xdd, 0x29, 0x68, 0x01, 0x98, 0x88, 0x47, 0x28, 0x21, -0x48, 0x43, 0x30, 0x49, 0x40, 0x18, 0xc0, 0x5f, 0x03, 0x94, 0x02, 0x90, 0x64, 0x1c, 0x04, 0x98, -0xe4, 0xb2, 0x84, 0x42, 0xd7, 0xd3, 0x06, 0x98, 0x00, 0x28, 0x4e, 0xd0, 0x29, 0x68, 0x01, 0x98, -0x88, 0x47, 0x03, 0x9c, 0x01, 0x90, 0x00, 0x9f, 0x02, 0x90, 0x21, 0x46, 0x06, 0x94, 0x01, 0xf0, -0x63, 0xf8, 0x02, 0x98, 0x23, 0x49, 0x28, 0x22, 0x50, 0x43, 0x40, 0x18, 0x04, 0x90, 0x06, 0xe0, -0x64, 0x1c, 0xe4, 0xb2, 0x21, 0x46, 0x02, 0x98, 0x01, 0xf0, 0x56, 0xf8, 0x04, 0x98, 0x61, 0x00, -0x41, 0x18, 0x02, 0x20, 0x08, 0x5e, 0xb1, 0x8b, 0x88, 0x42, 0x03, 0xdb, 0x1a, 0x48, 0x80, 0x79, -0xa0, 0x42, 0xed, 0xd2, 0x39, 0x88, 0x00, 0xe0, 0x27, 0xe0, 0x38, 0x46, 0x4c, 0x30, 0x0c, 0x54, -0x06, 0x9c, 0x05, 0xe0, 0x64, 0x1e, 0xe4, 0xb2, 0x21, 0x46, 0x02, 0x98, 0x01, 0xf0, 0x3c, 0xf8, -0x04, 0x98, 0x61, 0x00, 0x40, 0x18, 0x40, 0x38, 0x3e, 0x21, 0x41, 0x5e, 0xb0, 0x8b, 0x81, 0x42, -0x01, 0xdb, 0x00, 0x2c, 0xee, 0xd1, 0x39, 0x88, 0x38, 0x46, 0x2c, 0x30, 0x0c, 0x54, 0x3a, 0x88, -0x39, 0x46, 0x0c, 0x31, 0x02, 0x98, 0x50, 0x54, 0x38, 0x88, 0x40, 0x1c, 0x38, 0x80, 0x69, 0x68, -0x01, 0x98, 0x88, 0x47, 0x00, 0x28, 0x00, 0xd0, 0x65, 0xe7, 0x0b, 0xb0, 0xf0, 0xbd, 0x00, 0x00, -0x84, 0x2d, 0x01, 0x20, 0x00, 0x50, 0x01, 0x20, 0xac, 0x1b, 0x01, 0x20, 0xf8, 0xb5, 0x18, 0x4d, -0x00, 0x26, 0x68, 0x78, 0x00, 0x28, 0x1a, 0xd0, 0x28, 0x78, 0x40, 0x1c, 0xc4, 0xb2, 0x15, 0x48, -0x2c, 0x70, 0x41, 0x79, 0x02, 0x79, 0x08, 0x02, 0x7d, 0x21, 0x10, 0x43, 0xc9, 0x00, 0xf3, 0xf7, -0x5d, 0xfb, 0x11, 0x4f, 0xa0, 0x42, 0x05, 0xd1, 0x00, 0x20, 0xff, 0xf7, 0x27, 0xf8, 0x01, 0x20, -0x38, 0x70, 0x04, 0xe0, 0x06, 0x2c, 0x02, 0xd1, 0x6e, 0x70, 0x2e, 0x70, 0x3e, 0x70, 0x68, 0x68, -0x40, 0x1c, 0x68, 0x60, 0xa8, 0x78, 0x00, 0x28, 0x08, 0xd0, 0xa8, 0x68, 0x40, 0x1c, 0xa8, 0x60, -0xe9, 0x68, 0x88, 0x42, 0x02, 0xd1, 0xae, 0x60, 0x01, 0xf0, 0x20, 0xf8, 0xf8, 0xbd, 0x00, 0x00, -0x64, 0x00, 0x01, 0x20, 0xeb, 0x0c, 0x01, 0x20, 0x03, 0x00, 0x01, 0x20, 0xf0, 0xb4, 0x00, 0x21, -0x03, 0x23, 0x11, 0x4d, 0x9b, 0x07, 0x11, 0x4c, 0x07, 0x26, 0x0f, 0x46, 0x40, 0x1e, 0x0a, 0x46, -0x49, 0x1c, 0xc9, 0xb2, 0x03, 0x2a, 0x0f, 0xd2, 0x0d, 0x4a, 0x90, 0x42, 0x01, 0xd9, 0x01, 0x22, -0x08, 0xe0, 0x60, 0x61, 0xea, 0x69, 0x12, 0x02, 0x12, 0x0a, 0x1a, 0x43, 0xea, 0x61, 0xa7, 0x61, -0x26, 0x61, 0x00, 0x22, 0x00, 0x2a, 0xea, 0xd1, 0x20, 0x69, 0x01, 0x21, 0x08, 0x43, 0x20, 0x61, -0x04, 0x48, 0x47, 0x60, 0xf0, 0xbc, 0x70, 0x47, 0x04, 0xed, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xe0, -0xff, 0xff, 0xff, 0x00, 0x64, 0x00, 0x01, 0x20, 0x70, 0x47, 0x00, 0x00, 0x2e, 0x48, 0x81, 0x7d, -0x40, 0x7d, 0x09, 0x02, 0x01, 0x43, 0x2d, 0x48, 0x42, 0x7c, 0x03, 0x7c, 0x10, 0x02, 0x18, 0x43, -0x81, 0x42, 0x50, 0xd1, 0x2a, 0x48, 0xc0, 0x7d, 0x80, 0x07, 0x4c, 0xd5, 0x29, 0x48, 0x40, 0x78, -0x01, 0x28, 0x48, 0xd1, 0x28, 0x48, 0x80, 0x7e, 0x00, 0x28, 0x44, 0xd0, 0xf0, 0xb5, 0x22, 0x4d, -0x85, 0xb0, 0x28, 0x7d, 0x02, 0x28, 0x34, 0xd1, 0x24, 0x4c, 0x20, 0x7a, 0x00, 0x28, 0x32, 0xd0, -0x04, 0x20, 0x09, 0x26, 0x00, 0x07, 0x76, 0x04, 0x83, 0x19, 0x21, 0x48, 0x21, 0x7a, 0x00, 0x29, -0x2b, 0xd0, 0x04, 0x21, 0x09, 0x07, 0x00, 0x27, 0x89, 0x19, 0x01, 0x97, 0x03, 0x97, 0x02, 0x91, -0x00, 0x90, 0x29, 0x7a, 0xe8, 0x79, 0x01, 0x22, 0xf4, 0xf7, 0x3c, 0xf8, 0x20, 0x7a, 0x00, 0x28, -0x1d, 0xd0, 0x04, 0x20, 0x00, 0x07, 0x83, 0x19, 0x16, 0x49, 0x20, 0x7a, 0x00, 0x28, 0x18, 0xd0, -0x04, 0x20, 0x00, 0x07, 0x80, 0x19, 0x01, 0x97, 0x03, 0x97, 0x00, 0x91, 0x02, 0x90, 0x29, 0x7a, -0xe8, 0x79, 0x00, 0x22, 0xf4, 0xf7, 0x26, 0xf8, 0x01, 0x20, 0xf8, 0xf7, 0x59, 0xfc, 0xf6, 0xf7, -0xe5, 0xfe, 0x05, 0xb0, 0xf0, 0xbd, 0x03, 0x20, 0xcb, 0xe7, 0x03, 0x21, 0xd2, 0xe7, 0x03, 0x20, -0xe0, 0xe7, 0x03, 0x20, 0xe5, 0xe7, 0x70, 0x47, 0xa8, 0x0c, 0x01, 0x20, 0x8e, 0x03, 0x01, 0x20, -0xe8, 0x0d, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, 0x8c, 0x03, 0x01, 0x20, 0x6c, 0x03, 0x01, 0x20, -0x2a, 0x08, 0x14, 0x10, 0x2a, 0x00, 0x14, 0x10, 0x70, 0x47, 0x10, 0xb5, 0xfc, 0xf7, 0x72, 0xff, -0xfc, 0xf7, 0xe4, 0xff, 0xfc, 0xf7, 0xe3, 0xff, 0xfc, 0xf7, 0xe2, 0xff, 0xfd, 0xf7, 0x52, 0xf8, -0xfd, 0xf7, 0x12, 0xf9, 0xfd, 0xf7, 0xd8, 0xf9, 0xfd, 0xf7, 0xda, 0xf9, 0xfc, 0xf7, 0x66, 0xff, -0xfc, 0xf7, 0x76, 0xff, 0xfc, 0xf7, 0x78, 0xff, 0xfc, 0xf7, 0x7a, 0xff, 0xfc, 0xf7, 0x80, 0xff, -0xfc, 0xf7, 0x82, 0xff, 0xfc, 0xf7, 0x8e, 0xff, 0xfc, 0xf7, 0x90, 0xff, 0xfc, 0xf7, 0x92, 0xff, -0xfc, 0xf7, 0xc0, 0xff, 0x10, 0xbd, 0x00, 0x00, 0x07, 0x48, 0x00, 0x7e, 0x80, 0x07, 0x0a, 0xd5, -0x10, 0xb5, 0x06, 0x48, 0xc1, 0x79, 0x49, 0x08, 0xc1, 0x71, 0x41, 0x7a, 0x49, 0x08, 0x41, 0x72, -0x00, 0xf0, 0x06, 0xf8, 0x10, 0xbd, 0x70, 0x47, 0xe8, 0x0d, 0x01, 0x20, 0x76, 0x00, 0x01, 0x20, -0x00, 0xb5, 0x08, 0x48, 0x01, 0x22, 0x02, 0x70, 0xc2, 0x71, 0x00, 0x21, 0xc1, 0x70, 0x41, 0x81, -0x81, 0x81, 0xc1, 0x81, 0x01, 0x71, 0x42, 0x71, 0x81, 0x71, 0x08, 0x46, 0x00, 0xf0, 0x04, 0xf8, -0x00, 0xbd, 0x00, 0x00, 0x38, 0x02, 0x01, 0x20, 0x11, 0x49, 0x49, 0x79, 0x03, 0x29, 0x1e, 0xd1, -0x10, 0x49, 0xff, 0x23, 0x09, 0x78, 0x1b, 0x02, 0x0f, 0x4a, 0x00, 0x29, 0x05, 0xd0, 0x91, 0x89, -0x99, 0x42, 0x07, 0xd2, 0x09, 0x18, 0x91, 0x81, 0x04, 0xe0, 0xd1, 0x89, 0x99, 0x42, 0x01, 0xd2, -0x09, 0x18, 0xd1, 0x81, 0xd1, 0x78, 0x02, 0x29, 0x09, 0xd1, 0x51, 0x89, 0x08, 0x18, 0x80, 0xb2, -0x06, 0x49, 0x50, 0x81, 0x49, 0x8a, 0x81, 0x42, 0x01, 0xd2, 0x00, 0x20, 0xd0, 0x70, 0x70, 0x47, -0x4c, 0x03, 0x01, 0x20, 0x68, 0x02, 0x01, 0x20, 0x38, 0x02, 0x01, 0x20, 0x76, 0x00, 0x01, 0x20, -0xf0, 0xb5, 0x87, 0xb0, 0x53, 0x48, 0x03, 0x90, 0xc0, 0x7b, 0x00, 0x28, 0x74, 0xd0, 0x52, 0x48, -0xc1, 0x7f, 0x03, 0x98, 0xc0, 0x7e, 0xc2, 0x09, 0x50, 0x48, 0x06, 0x90, 0x80, 0x7d, 0x00, 0x2a, -0x22, 0xd0, 0x40, 0x00, 0x01, 0x90, 0x00, 0x20, 0x02, 0x90, 0x4d, 0x48, 0x05, 0x90, 0x00, 0x7e, -0x00, 0x28, 0x61, 0xd9, 0x6e, 0x20, 0x41, 0x43, 0x4a, 0x48, 0x08, 0x18, 0x04, 0x90, 0x02, 0x98, -0x0c, 0x21, 0x48, 0x43, 0x47, 0x49, 0x42, 0x18, 0x11, 0x20, 0x80, 0x01, 0x14, 0x18, 0xa0, 0x7e, -0x0a, 0x18, 0x09, 0x21, 0x09, 0x02, 0x51, 0x18, 0x89, 0x7d, 0x01, 0x29, 0x06, 0xd0, 0x02, 0x29, -0x10, 0xd0, 0x03, 0x29, 0x0e, 0xd0, 0x69, 0xe0, 0x01, 0x90, 0xdc, 0xe7, 0x06, 0x21, 0x3e, 0x4b, -0x00, 0x22, 0x48, 0x43, 0xc1, 0x18, 0x0a, 0x71, 0x4a, 0x71, 0xa2, 0x8b, 0x1a, 0x52, 0xe0, 0x8b, -0x48, 0x80, 0x5b, 0xe0, 0x06, 0x21, 0x06, 0x46, 0x37, 0x4f, 0x4e, 0x43, 0xf5, 0x19, 0x69, 0x79, -0x00, 0x29, 0x53, 0xd1, 0x06, 0x9a, 0x29, 0x79, 0x52, 0x7d, 0x91, 0x42, 0x01, 0xd9, 0xff, 0x21, -0x00, 0xe0, 0x49, 0x1c, 0x29, 0x71, 0x0a, 0x22, 0x04, 0x99, 0x50, 0x43, 0x09, 0x18, 0x19, 0x20, -0x80, 0x01, 0x08, 0x18, 0x02, 0x88, 0x40, 0x88, 0x69, 0x88, 0x40, 0x1a, 0x01, 0xb2, 0xb8, 0x5b, -0x10, 0x1a, 0x00, 0xb2, 0xf4, 0xf7, 0xc8, 0xfd, 0x00, 0x90, 0xbf, 0x5b, 0x01, 0x99, 0x6e, 0x88, -0x88, 0x42, 0x31, 0xd2, 0x28, 0x79, 0xff, 0x28, 0x30, 0xd2, 0x03, 0x98, 0xc0, 0x7e, 0xc0, 0x09, -0x0b, 0xd0, 0xa0, 0x8b, 0xb8, 0x42, 0x0b, 0xd9, 0x00, 0x99, 0xc0, 0x1b, 0x48, 0x43, 0x01, 0x99, -0xf3, 0xf7, 0xb2, 0xf9, 0xc0, 0x19, 0x0a, 0xe0, 0x2a, 0xe0, 0xa7, 0x83, 0xe6, 0x83, 0x1d, 0xe0, -0x00, 0x99, 0x38, 0x1a, 0x48, 0x43, 0x01, 0x99, 0xf3, 0xf7, 0xa6, 0xf9, 0x38, 0x1a, 0xa0, 0x83, -0xe0, 0x8b, 0xb0, 0x42, 0x07, 0xd9, 0x00, 0x99, 0x80, 0x1b, 0x48, 0x43, 0x01, 0x99, 0xf3, 0xf7, -0x9b, 0xf9, 0x80, 0x19, 0x06, 0xe0, 0x00, 0x99, 0x30, 0x1a, 0x48, 0x43, 0x01, 0x99, 0xf3, 0xf7, -0x93, 0xf9, 0x30, 0x1a, 0xe0, 0x83, 0x01, 0xe0, 0x01, 0x20, 0x68, 0x71, 0x02, 0x98, 0x40, 0x1c, -0xc0, 0xb2, 0x02, 0x90, 0x05, 0x98, 0x01, 0x7e, 0x02, 0x98, 0x81, 0x42, 0x00, 0xd9, 0x76, 0xe7, -0x07, 0xb0, 0xf0, 0xbd, 0xa8, 0x0d, 0x01, 0x20, 0x24, 0x2d, 0x01, 0x20, 0x48, 0x0d, 0x01, 0x20, -0x84, 0x28, 0x01, 0x20, 0x44, 0x24, 0x01, 0x20, 0xe4, 0x2e, 0x01, 0x20, 0xf8, 0xb5, 0x2c, 0x49, -0x2c, 0x48, 0xf3, 0xf7, 0x61, 0xf9, 0x42, 0x21, 0x2b, 0x48, 0xf3, 0xf7, 0x5d, 0xf9, 0x00, 0x24, -0x2a, 0x48, 0x19, 0x23, 0xc4, 0x77, 0x2a, 0x48, 0x21, 0x46, 0xc4, 0x77, 0x9b, 0x01, 0x25, 0x4d, -0x42, 0x22, 0x4a, 0x43, 0x57, 0x19, 0x6e, 0x22, 0x00, 0x20, 0x4a, 0x43, 0x56, 0x19, 0x0a, 0x22, -0x42, 0x43, 0xb5, 0x18, 0x31, 0x22, 0x52, 0x01, 0xaa, 0x18, 0x94, 0x77, 0x21, 0x4a, 0xed, 0x18, -0x2a, 0x80, 0x6a, 0x80, 0x06, 0x22, 0x42, 0x43, 0xac, 0x80, 0xbd, 0x18, 0x1f, 0x22, 0x92, 0x01, -0xaa, 0x18, 0xd4, 0x86, 0x40, 0x1c, 0x14, 0x87, 0xc0, 0xb2, 0x54, 0x87, 0x0b, 0x28, 0xe6, 0xd3, -0x49, 0x1c, 0xc9, 0xb2, 0x04, 0x29, 0xda, 0xd3, 0x0b, 0x21, 0x17, 0x48, 0xf3, 0xf7, 0x2a, 0xf9, -0x17, 0x49, 0x16, 0x48, 0x08, 0x60, 0x2c, 0x20, 0x08, 0x71, 0x16, 0x48, 0xc2, 0x79, 0x4a, 0x71, -0x00, 0x7a, 0x88, 0x71, 0x14, 0x48, 0x4c, 0x72, 0x43, 0x7b, 0x02, 0x7b, 0x18, 0x06, 0x00, 0x14, -0x10, 0x43, 0x48, 0x81, 0x11, 0x48, 0x04, 0x80, 0x11, 0x48, 0x14, 0x21, 0x44, 0x80, 0x04, 0x80, -0x84, 0x80, 0x10, 0x48, 0x04, 0x81, 0x84, 0x81, 0x0f, 0x48, 0x04, 0x70, 0x41, 0x80, 0xf8, 0xbd, -0x74, 0x09, 0x00, 0x00, 0x44, 0x24, 0x01, 0x20, 0xe4, 0x2e, 0x01, 0x20, 0x84, 0x2d, 0x01, 0x20, -0x24, 0x2d, 0x01, 0x20, 0xff, 0x7f, 0x00, 0x00, 0x5a, 0x2d, 0x01, 0x20, 0x00, 0x50, 0x01, 0x20, -0xac, 0x1b, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0x2a, 0x0d, 0x01, 0x20, 0x00, 0x58, 0x01, 0x20, -0xb8, 0x1b, 0x01, 0x20, 0x0c, 0x01, 0x01, 0x20, 0x14, 0x01, 0x01, 0x20, 0xf8, 0xb5, 0x1c, 0x4e, -0x00, 0x20, 0x70, 0x71, 0x1b, 0x4d, 0x06, 0x21, 0xe9, 0x77, 0x70, 0x70, 0xb0, 0x70, 0xf6, 0xf7, -0xd9, 0xff, 0x30, 0x78, 0x06, 0x28, 0x2a, 0xd1, 0x34, 0x46, 0x17, 0x4f, 0x40, 0x34, 0x20, 0x7c, -0x01, 0x28, 0x21, 0xd1, 0x38, 0x7d, 0xa8, 0x73, 0x03, 0x20, 0x38, 0x75, 0x01, 0x20, 0xfd, 0xf7, -0xa1, 0xfa, 0xfd, 0xf7, 0xff, 0xff, 0xfa, 0xf7, 0x47, 0xfd, 0x10, 0xa0, 0x01, 0xf0, 0x40, 0xfc, -0x07, 0xe0, 0xfe, 0xf7, 0xe7, 0xf8, 0x01, 0xf0, 0xb9, 0xf8, 0x00, 0x21, 0x06, 0x20, 0x01, 0xf0, -0x67, 0xf9, 0x20, 0x7c, 0x01, 0x28, 0x02, 0xd1, 0x30, 0x78, 0x06, 0x28, 0xf1, 0xd0, 0x00, 0x20, -0xfd, 0xf7, 0x88, 0xfa, 0xa8, 0x7b, 0x38, 0x75, 0x30, 0x78, 0x06, 0x28, 0xd7, 0xd0, 0xf8, 0xbd, -0x4c, 0x03, 0x01, 0x20, 0x6c, 0x03, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0x73, 0x74, 0x61, 0x72, -0x74, 0x20, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x20, 0x74, 0x65, 0x73, 0x74, 0x0a, 0x00, 0x00, 0x00, -0xf0, 0xb5, 0x85, 0xb0, 0x00, 0x20, 0x03, 0x90, 0x6b, 0x48, 0x6d, 0x4e, 0x86, 0x46, 0x05, 0x7b, -0x6a, 0x48, 0x00, 0x88, 0x01, 0x96, 0x84, 0x46, 0x70, 0x7a, 0x31, 0x7a, 0x03, 0x02, 0x74, 0x7d, -0x68, 0x48, 0x00, 0x90, 0x0b, 0x43, 0x42, 0x8c, 0xc1, 0x7f, 0x70, 0x7b, 0x36, 0x7b, 0x00, 0x02, -0x30, 0x43, 0x00, 0x2d, 0x19, 0xd0, 0x00, 0x9d, 0xae, 0x8d, 0x63, 0x4d, 0x6f, 0x7d, 0x2d, 0x7d, -0x3f, 0x02, 0x2f, 0x43, 0xbe, 0x42, 0x10, 0xd9, 0x5d, 0x00, 0xaa, 0x42, 0x0d, 0xd2, 0x00, 0x2c, -0x04, 0xd0, 0x02, 0x29, 0x02, 0xd0, 0x00, 0x99, 0x02, 0x22, 0xca, 0x77, 0x57, 0x49, 0x84, 0x45, -0x01, 0xd0, 0x08, 0x80, 0x48, 0x80, 0x05, 0xb0, 0xf0, 0xbd, 0x58, 0x4e, 0x02, 0x96, 0x75, 0x79, -0x36, 0x79, 0x2d, 0x02, 0x35, 0x43, 0x00, 0x2c, 0x04, 0xd1, 0x50, 0x4c, 0x84, 0x45, 0x01, 0xd1, -0x23, 0x80, 0x65, 0x80, 0x00, 0x29, 0x7d, 0xd0, 0x01, 0x29, 0x7b, 0xd0, 0x50, 0x49, 0x09, 0x88, -0x8c, 0x46, 0x02, 0x29, 0x76, 0xd3, 0x69, 0x00, 0x8a, 0x42, 0x6f, 0xd2, 0x82, 0x42, 0x3f, 0xd3, -0x71, 0x46, 0x09, 0x7e, 0xc9, 0x06, 0x6d, 0xd4, 0x44, 0x49, 0x88, 0x80, 0x00, 0x20, 0xf8, 0xf7, -0x07, 0xfb, 0x01, 0x20, 0xf8, 0xf7, 0x04, 0xfb, 0x45, 0x4b, 0x00, 0x26, 0x18, 0x88, 0x34, 0x46, -0x31, 0x46, 0x84, 0x46, 0x02, 0x28, 0x71, 0xd3, 0x00, 0x22, 0x00, 0x20, 0x63, 0x46, 0x00, 0x2b, -0x1d, 0xd9, 0x3f, 0x4d, 0x53, 0x00, 0x5d, 0x19, 0x82, 0x42, 0x14, 0xd0, 0x3c, 0x49, 0x43, 0x00, -0x5b, 0x18, 0xaf, 0x78, 0x99, 0x78, 0x79, 0x1a, 0x00, 0xd5, 0x49, 0x42, 0xc9, 0xb2, 0xb1, 0x42, -0x00, 0xd9, 0x0e, 0x46, 0xef, 0x78, 0xdb, 0x78, 0xfb, 0x1a, 0x00, 0xd5, 0x5b, 0x42, 0xdb, 0xb2, -0xa3, 0x42, 0x00, 0xd9, 0x1c, 0x46, 0x40, 0x1c, 0xc0, 0xb2, 0x84, 0x45, 0xe4, 0xd8, 0x52, 0x1c, -0xd2, 0xb2, 0x94, 0x45, 0xd9, 0xd8, 0x01, 0x2c, 0x30, 0xd8, 0x01, 0x29, 0x2e, 0xd8, 0x2a, 0xe0, -0x2c, 0x48, 0x7f, 0x21, 0x83, 0x8a, 0x40, 0x8a, 0x1b, 0x0a, 0x00, 0x22, 0x00, 0x0a, 0x46, 0xb2, -0x5f, 0xb2, 0x10, 0x46, 0x26, 0x4b, 0x44, 0x00, 0xe4, 0x18, 0x02, 0x23, 0xe3, 0x56, 0xdb, 0x1b, -0x00, 0xd5, 0x5b, 0x42, 0x03, 0x25, 0x65, 0x57, 0x5b, 0xb2, 0xac, 0x1b, 0x00, 0xd5, 0x64, 0x42, -0x1b, 0x19, 0x5b, 0xb2, 0x8b, 0x42, 0x01, 0xda, 0xd9, 0xb2, 0x02, 0x46, 0x40, 0x1c, 0xc0, 0xb2, -0x84, 0x45, 0xe7, 0xd8, 0x1a, 0x49, 0x01, 0x20, 0x08, 0x80, 0x50, 0x00, 0x40, 0x18, 0x82, 0x78, -0x8a, 0x70, 0xc0, 0x78, 0xc8, 0x70, 0x03, 0x98, 0x00, 0x28, 0x17, 0xd0, 0x01, 0x98, 0x42, 0x7a, -0x01, 0x7a, 0x00, 0xe0, 0x12, 0xe0, 0x10, 0x02, 0x08, 0x43, 0x0c, 0x49, 0x08, 0x80, 0x02, 0x98, -0x42, 0x79, 0x03, 0x79, 0x10, 0x02, 0x18, 0x43, 0x48, 0x80, 0x02, 0x98, 0x42, 0x7b, 0x03, 0x7b, -0x10, 0x02, 0x18, 0x43, 0x88, 0x80, 0x00, 0x98, 0x00, 0x21, 0xc1, 0x77, 0x00, 0x98, 0x0a, 0x49, -0xc0, 0x7f, 0x48, 0x77, 0x05, 0xb0, 0xf0, 0xbd, 0xe8, 0x0d, 0x01, 0x20, 0x1a, 0x01, 0x01, 0x20, -0x28, 0x0d, 0x01, 0x20, 0x84, 0x2d, 0x01, 0x20, 0x69, 0x0d, 0x01, 0x20, 0x2a, 0x0d, 0x01, 0x20, -0x44, 0x24, 0x01, 0x20, 0x84, 0x27, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, 0xf0, 0xb5, 0x6f, 0x4f, -0x6f, 0x4c, 0x78, 0x7d, 0xe1, 0x7f, 0x6f, 0x4d, 0x83, 0xb0, 0x00, 0x28, 0x04, 0xd0, 0x01, 0x28, -0x09, 0xd0, 0x02, 0x28, 0x0f, 0xd0, 0xaf, 0xe0, 0x00, 0x29, 0x78, 0xd0, 0x6a, 0x48, 0x01, 0x21, -0x81, 0x71, 0x00, 0x20, 0x05, 0xe0, 0x02, 0x29, 0x71, 0xd0, 0x67, 0x48, 0x01, 0x21, 0x81, 0x71, -0x02, 0x20, 0xe0, 0x77, 0xa4, 0xe0, 0x65, 0x48, 0x60, 0x4e, 0x00, 0x8c, 0x00, 0x90, 0x72, 0x7a, -0x33, 0x7a, 0x12, 0x02, 0x1a, 0x43, 0x40, 0x1c, 0xb3, 0x1c, 0x80, 0xb2, 0x5e, 0x7b, 0x84, 0x46, -0x1b, 0x7b, 0x5b, 0x48, 0x36, 0x02, 0x1e, 0x43, 0x40, 0x8c, 0xb6, 0x46, 0x00, 0x29, 0x04, 0xd0, -0x01, 0x29, 0x14, 0xd0, 0x02, 0x29, 0x5c, 0xd0, 0x86, 0xe0, 0x90, 0x42, 0x0b, 0xd8, 0x70, 0x45, -0x09, 0xd3, 0x56, 0x49, 0x60, 0x46, 0x08, 0x84, 0x05, 0x28, 0x7d, 0xd9, 0x00, 0x20, 0x08, 0x84, -0x01, 0x20, 0xe0, 0x77, 0x78, 0xe0, 0x51, 0x49, 0x00, 0x20, 0x08, 0x84, 0x74, 0xe0, 0x00, 0x99, -0x4e, 0x48, 0x03, 0x29, 0x30, 0xd0, 0x61, 0x46, 0x01, 0x84, 0x4d, 0x4a, 0x06, 0x46, 0x00, 0x23, -0x53, 0x72, 0x4c, 0x48, 0x10, 0x60, 0x68, 0x7b, 0x29, 0x7b, 0x00, 0x06, 0x00, 0x14, 0x08, 0x43, -0x19, 0x46, 0x49, 0x4b, 0x50, 0x81, 0x19, 0x80, 0x13, 0x79, 0x07, 0x21, 0xc9, 0x02, 0x02, 0x93, -0x00, 0x91, 0x01, 0x90, 0x91, 0x79, 0x50, 0x79, 0x44, 0x4b, 0x14, 0x22, 0xf3, 0xf7, 0xe8, 0xfc, -0x41, 0x48, 0x00, 0x88, 0x00, 0x28, 0x21, 0xd0, 0xb1, 0x8c, 0x49, 0x1c, 0xb1, 0x84, 0x78, 0x7a, -0x3a, 0x7a, 0x61, 0x8c, 0x00, 0x02, 0x10, 0x43, 0x81, 0x42, 0x45, 0xd3, 0x36, 0x49, 0x01, 0x20, -0x88, 0x71, 0x00, 0x20, 0xe0, 0x77, 0x43, 0xe0, 0x00, 0x23, 0x03, 0x84, 0x81, 0x8c, 0x03, 0x29, -0x06, 0xd3, 0x31, 0x4a, 0x01, 0x21, 0x91, 0x71, 0x02, 0x21, 0xe1, 0x77, 0x04, 0xe0, 0x33, 0xe0, -0x2d, 0x4a, 0x01, 0x21, 0x91, 0x71, 0xe3, 0x77, 0x83, 0x84, 0x31, 0xe0, 0x00, 0x20, 0xb0, 0x84, -0x2a, 0xe0, 0x2f, 0x49, 0x09, 0x7b, 0x00, 0x29, 0x0a, 0xd0, 0x2e, 0x49, 0xa3, 0x8d, 0x4e, 0x7d, -0x09, 0x7d, 0x36, 0x02, 0x0e, 0x43, 0xb3, 0x42, 0x02, 0xd9, 0x51, 0x00, 0x88, 0x42, 0x34, 0xd3, -0x22, 0x4e, 0xf1, 0x7a, 0x01, 0x29, 0x02, 0xd0, 0x00, 0x21, 0x71, 0x84, 0x0c, 0xe0, 0x71, 0x8c, -0x49, 0x1c, 0x89, 0xb2, 0x71, 0x84, 0x0a, 0x29, 0x06, 0xd9, 0x00, 0x21, 0x71, 0x84, 0x1a, 0x4b, -0x01, 0x21, 0x99, 0x71, 0x00, 0x21, 0xe1, 0x77, 0x90, 0x42, 0x01, 0xd2, 0x70, 0x45, 0x01, 0xd8, -0x01, 0x20, 0x00, 0xe0, 0x00, 0x20, 0xf0, 0x72, 0x13, 0x48, 0x80, 0x79, 0x00, 0x28, 0x14, 0xd0, -0x11, 0x49, 0x00, 0x20, 0x88, 0x71, 0xe0, 0x7f, 0x02, 0x28, 0x10, 0xd0, 0x78, 0x7a, 0x3a, 0x7a, -0x00, 0x02, 0x10, 0x43, 0x08, 0x80, 0x68, 0x79, 0x2a, 0x79, 0x00, 0x02, 0x10, 0x43, 0x48, 0x80, -0x68, 0x7b, 0x2a, 0x7b, 0x00, 0x02, 0x10, 0x43, 0x88, 0x80, 0x03, 0xb0, 0xf0, 0xbd, 0x78, 0x7b, -0x3a, 0x7b, 0x00, 0x02, 0x10, 0x43, 0x08, 0x80, 0x48, 0x80, 0xf5, 0xe7, 0x28, 0x0d, 0x01, 0x20, -0x84, 0x2d, 0x01, 0x20, 0x2a, 0x0d, 0x01, 0x20, 0x1a, 0x01, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, -0xac, 0x1b, 0x01, 0x20, 0x00, 0x50, 0x01, 0x20, 0x00, 0x58, 0x01, 0x20, 0x2a, 0x30, 0x00, 0x00, -0xe8, 0x0d, 0x01, 0x20, 0x69, 0x0d, 0x01, 0x20, 0xf0, 0xb5, 0x54, 0x4c, 0x86, 0xb0, 0x61, 0x79, -0x53, 0x48, 0x03, 0x29, 0xc2, 0x8b, 0x0d, 0xd0, 0x52, 0x48, 0xc0, 0x7f, 0x02, 0x28, 0x52, 0x48, -0x0e, 0xd0, 0xff, 0x30, 0x02, 0x30, 0x01, 0x2a, 0x10, 0xd8, 0x41, 0x78, 0x03, 0x78, 0x08, 0x02, -0x18, 0x43, 0x16, 0xe0, 0x4d, 0x48, 0x41, 0x7e, 0x03, 0x7e, 0x08, 0x02, 0x18, 0x43, 0x10, 0xe0, -0x80, 0x30, 0x41, 0x7b, 0x03, 0x7b, 0x08, 0x02, 0x18, 0x43, 0x0a, 0xe0, 0x48, 0x49, 0x02, 0x2a, -0x13, 0xd0, 0x03, 0x2a, 0x16, 0xd0, 0x04, 0x2a, 0x19, 0xd0, 0x41, 0x7a, 0x03, 0x7a, 0x08, 0x02, -0x18, 0x43, 0xe5, 0x79, 0x43, 0x49, 0x44, 0x4b, 0x8f, 0x7b, 0x00, 0x2d, 0x14, 0xd0, 0x59, 0x7a, -0x18, 0x7a, 0x09, 0x06, 0x09, 0x14, 0x01, 0x43, 0x22, 0xe0, 0x48, 0x78, 0x09, 0x78, 0x00, 0x02, -0x08, 0x43, 0xee, 0xe7, 0x41, 0x79, 0x03, 0x79, 0x08, 0x02, 0x18, 0x43, 0xe9, 0xe7, 0x48, 0x79, -0x09, 0x79, 0x00, 0x02, 0x08, 0x43, 0xe4, 0xe7, 0x00, 0x2f, 0x10, 0xd0, 0x61, 0x79, 0x03, 0x29, -0x0d, 0xd0, 0x14, 0x38, 0x01, 0xb2, 0x58, 0x79, 0x1c, 0x79, 0x00, 0x02, 0x20, 0x43, 0x88, 0x42, -0x06, 0xdd, 0x59, 0x79, 0xe0, 0xb2, 0x09, 0x06, 0x09, 0x14, 0x01, 0x43, 0x00, 0xe0, 0x01, 0xb2, -0x2e, 0x48, 0x00, 0x7d, 0x00, 0x28, 0x0f, 0xd0, 0x2d, 0x48, 0xc0, 0x7c, 0xc0, 0x07, 0x0b, 0xd0, -0x2c, 0x48, 0x43, 0x7c, 0x04, 0x7c, 0x1b, 0x02, 0x23, 0x43, 0x8b, 0x42, 0x04, 0xdd, 0x41, 0x7c, -0xe0, 0xb2, 0x09, 0x06, 0x09, 0x14, 0x01, 0x43, 0x00, 0x20, 0x00, 0x90, 0x26, 0x4b, 0x01, 0x90, -0x02, 0x90, 0x03, 0x90, 0x04, 0x90, 0x05, 0x90, 0x98, 0x74, 0x00, 0x2a, 0x1b, 0xd9, 0x1a, 0x4c, -0x22, 0x4e, 0x24, 0x7a, 0x64, 0x1e, 0xa4, 0x46, 0xc4, 0x00, 0xa4, 0x19, 0xa4, 0x8e, 0x8c, 0x42, -0x02, 0xda, 0x01, 0x24, 0x6d, 0x46, 0x2c, 0x54, 0x44, 0x00, 0xa4, 0x19, 0xe0, 0x34, 0x64, 0x78, -0x02, 0x2c, 0x04, 0xd9, 0x64, 0x45, 0x02, 0xda, 0x9c, 0x7c, 0x64, 0x1c, 0x9c, 0x74, 0x40, 0x1c, -0xc0, 0xb2, 0x82, 0x42, 0xe8, 0xd8, 0x00, 0x2a, 0x06, 0xd0, 0x98, 0x7c, 0x90, 0x42, 0x05, 0xd1, -0x00, 0x2f, 0x03, 0xd1, 0x01, 0x20, 0x00, 0xe0, 0x00, 0x20, 0xd8, 0x74, 0x10, 0x4a, 0x68, 0x46, -0x11, 0x46, 0xfb, 0xf7, 0x79, 0xfc, 0x06, 0xb0, 0xf0, 0xbd, 0x00, 0x00, 0x4c, 0x03, 0x01, 0x20, -0x04, 0x25, 0x01, 0x20, 0x84, 0x2d, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0x0b, 0x0e, 0x01, 0x20, -0xab, 0x0d, 0x01, 0x20, 0x84, 0x27, 0x01, 0x20, 0x2a, 0x0d, 0x01, 0x20, 0x8c, 0x03, 0x01, 0x20, -0xa8, 0x0d, 0x01, 0x20, 0xca, 0x0c, 0x01, 0x20, 0xa4, 0x2d, 0x01, 0x20, 0x44, 0x24, 0x01, 0x20, -0x22, 0x25, 0x01, 0x20, 0x0d, 0x48, 0x80, 0x7d, 0x01, 0x28, 0x0b, 0xd0, 0x0c, 0x49, 0x00, 0x22, -0x08, 0x78, 0x01, 0x23, 0x40, 0x1c, 0xc0, 0xb2, 0x08, 0x70, 0x0a, 0x28, 0x03, 0xd2, 0x09, 0x48, -0x43, 0x77, 0x0a, 0x70, 0x70, 0x47, 0x48, 0x78, 0x40, 0x1c, 0xc0, 0xb2, 0x48, 0x70, 0x03, 0x28, -0xf8, 0xd3, 0x05, 0x48, 0x4a, 0x70, 0x83, 0x75, 0x70, 0x47, 0x00, 0x00, 0xe8, 0x0d, 0x01, 0x20, -0x2f, 0x00, 0x01, 0x20, 0x6c, 0x03, 0x01, 0x20, 0x8c, 0x03, 0x01, 0x20, 0x04, 0x49, 0x10, 0xb5, -0x48, 0x43, 0x04, 0x49, 0xf2, 0xf7, 0xd2, 0xfd, 0x03, 0x49, 0x48, 0x61, 0x10, 0xbd, 0x00, 0x00, -0x40, 0x42, 0x0f, 0x00, 0xa0, 0x86, 0x01, 0x00, 0x00, 0x20, 0x03, 0x40, 0x0b, 0x48, 0x00, 0x7d, -0x03, 0x28, 0x06, 0xd0, 0x01, 0x28, 0x03, 0xd1, 0x09, 0x48, 0xc0, 0x7d, 0x80, 0x06, 0x08, 0xd4, -0x70, 0x47, 0x08, 0x48, 0x80, 0x78, 0x00, 0x28, 0xfa, 0xd1, 0x07, 0x49, 0x01, 0x20, 0x88, 0x70, -0x70, 0x47, 0x10, 0xb5, 0x01, 0x20, 0xfe, 0xf7, 0xc3, 0xf9, 0x10, 0xbd, 0xa8, 0x0c, 0x01, 0x20, -0xe8, 0x0d, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, 0x18, 0x00, 0x01, 0x20, 0x01, 0x49, 0xfd, 0x20, -0x08, 0x72, 0x70, 0x47, 0x00, 0x00, 0x03, 0x40, 0xf0, 0xb5, 0x50, 0x48, 0x85, 0xb0, 0xc1, 0x7f, -0x81, 0x77, 0x03, 0x91, 0x49, 0x1c, 0xc9, 0xb2, 0x00, 0x22, 0xc1, 0x77, 0x04, 0x29, 0x00, 0xd3, -0xc2, 0x77, 0xc5, 0x7f, 0x00, 0x20, 0x00, 0x90, 0x01, 0x90, 0x01, 0x46, 0x02, 0x90, 0x48, 0x48, -0x86, 0x46, 0x00, 0x79, 0x00, 0x28, 0x2a, 0xd9, 0x6e, 0x20, 0x46, 0x4a, 0x01, 0x27, 0x68, 0x43, -0x80, 0x18, 0x84, 0x46, 0x0c, 0x20, 0x0a, 0x46, 0x42, 0x43, 0x42, 0x48, 0x0a, 0x24, 0x12, 0x18, -0x09, 0x20, 0x80, 0x01, 0x10, 0x18, 0x82, 0x79, 0x31, 0x23, 0x54, 0x43, 0x64, 0x44, 0x5b, 0x01, -0xe6, 0x18, 0x19, 0x23, 0xb7, 0x77, 0x9b, 0x01, 0x06, 0x89, 0xe3, 0x18, 0x1e, 0x80, 0x46, 0x89, -0x5e, 0x80, 0x86, 0x89, 0x9e, 0x80, 0x38, 0x4b, 0x00, 0x8a, 0xe3, 0x18, 0x98, 0x80, 0x68, 0x46, -0x87, 0x54, 0x70, 0x46, 0x49, 0x1c, 0x00, 0x79, 0xc9, 0xb2, 0x88, 0x42, 0xda, 0xd8, 0x00, 0x20, -0x6e, 0x22, 0x30, 0x4b, 0x31, 0x49, 0x6a, 0x43, 0x6f, 0x46, 0x06, 0x46, 0xd4, 0x18, 0x3a, 0x5c, -0x00, 0x2a, 0x0c, 0xd1, 0x0a, 0x22, 0x42, 0x43, 0x31, 0x23, 0xa2, 0x18, 0x5b, 0x01, 0xd3, 0x18, -0x9e, 0x77, 0x19, 0x23, 0x9b, 0x01, 0xd2, 0x18, 0x11, 0x80, 0x51, 0x80, 0x96, 0x80, 0x40, 0x1c, -0xc0, 0xb2, 0x0b, 0x28, 0xeb, 0xd3, 0x42, 0x20, 0x45, 0x43, 0x22, 0x49, 0x03, 0x98, 0x6e, 0x22, -0x00, 0x27, 0x6e, 0x18, 0x50, 0x43, 0x40, 0x18, 0x03, 0x90, 0x38, 0x46, 0x0a, 0x21, 0x48, 0x43, -0x31, 0x21, 0x22, 0x18, 0x49, 0x01, 0x53, 0x18, 0x9b, 0x7f, 0x00, 0x2b, 0x1d, 0xd0, 0x03, 0x9b, -0x18, 0x18, 0x41, 0x18, 0x89, 0x7f, 0x00, 0x29, 0x17, 0xd0, 0x19, 0x21, 0x89, 0x01, 0x52, 0x18, -0x41, 0x18, 0x13, 0x88, 0x08, 0x88, 0x18, 0x1a, 0x06, 0x23, 0x7b, 0x43, 0xf5, 0x18, 0x1f, 0x23, -0x9b, 0x01, 0x00, 0xb2, 0xed, 0x18, 0xe8, 0x86, 0x52, 0x88, 0x49, 0x88, 0x51, 0x1a, 0x09, 0xb2, -0x29, 0x87, 0xf4, 0xf7, 0x21, 0xf9, 0x68, 0x87, 0x09, 0xe0, 0x06, 0x20, 0x78, 0x43, 0x32, 0x18, -0x1f, 0x20, 0x00, 0x21, 0x80, 0x01, 0x10, 0x18, 0xc1, 0x86, 0x01, 0x87, 0x41, 0x87, 0x7f, 0x1c, -0xff, 0xb2, 0x0b, 0x2f, 0xc9, 0xd3, 0x05, 0xb0, 0xf0, 0xbd, 0x00, 0x00, 0x24, 0x2d, 0x01, 0x20, -0x84, 0x26, 0x01, 0x20, 0x44, 0x24, 0x01, 0x20, 0x42, 0x06, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, -0x70, 0x47, 0x00, 0x00, 0x70, 0xb5, 0x0d, 0x46, 0x04, 0x46, 0xf7, 0xf7, 0x59, 0xff, 0x0b, 0x49, -0x09, 0x7e, 0x89, 0x06, 0x10, 0xd5, 0x01, 0x26, 0x0a, 0x2c, 0x05, 0xd8, 0x08, 0x4b, 0x99, 0x88, -0x32, 0x46, 0xa2, 0x40, 0x11, 0x43, 0x99, 0x80, 0x29, 0x46, 0xf2, 0xf7, 0xdf, 0xfc, 0x05, 0x49, -0x48, 0x80, 0x08, 0x78, 0x30, 0x43, 0x08, 0x70, 0x70, 0xbd, 0x00, 0x00, 0xe8, 0x0d, 0x01, 0x20, -0x00, 0x30, 0x03, 0x40, 0x20, 0x20, 0x03, 0x40, 0x10, 0xb5, 0x1b, 0x49, 0x09, 0x7e, 0x89, 0x06, -0x06, 0xd5, 0x00, 0x28, 0x04, 0xd0, 0x19, 0x49, 0x08, 0x71, 0x0a, 0x7a, 0xd2, 0x07, 0xfc, 0xd1, -0x17, 0x49, 0xc9, 0x7e, 0xc9, 0x06, 0x00, 0x29, 0x25, 0xda, 0xef, 0xf3, 0x05, 0x81, 0x00, 0x29, -0x21, 0xd1, 0x14, 0x4c, 0x00, 0x28, 0x06, 0xd0, 0x13, 0x4a, 0x21, 0x78, 0x50, 0x54, 0x49, 0x1c, -0x21, 0x70, 0x0a, 0x28, 0x02, 0xd0, 0x20, 0x78, 0x62, 0x28, 0x14, 0xd3, 0x0f, 0x48, 0x60, 0x21, -0x01, 0x70, 0x22, 0x78, 0x42, 0x70, 0x0c, 0x49, 0x80, 0x1c, 0xf2, 0xf7, 0x3d, 0xfc, 0x0c, 0x49, -0x01, 0x20, 0x08, 0x70, 0xfe, 0xf7, 0x72, 0xf9, 0x00, 0x20, 0x20, 0x70, 0x00, 0xf0, 0x4a, 0xfc, -0x08, 0x48, 0x00, 0xf0, 0x21, 0xff, 0x10, 0xbd, 0xe8, 0x0d, 0x01, 0x20, 0x20, 0x20, 0x03, 0x40, -0xa8, 0x0d, 0x01, 0x20, 0xad, 0x00, 0x01, 0x20, 0xdc, 0x0e, 0x01, 0x20, 0x3e, 0x0f, 0x01, 0x20, -0x02, 0x00, 0x01, 0x20, 0x10, 0x27, 0x00, 0x00, 0xf0, 0xb5, 0x87, 0xb0, 0x4e, 0x48, 0x05, 0x90, -0x80, 0x7e, 0x00, 0x28, 0x03, 0xd0, 0x4d, 0x48, 0x40, 0x7c, 0x00, 0x28, 0x7e, 0xd0, 0x4c, 0x48, -0x09, 0x22, 0x03, 0x7d, 0x4b, 0x48, 0x4c, 0x4d, 0x00, 0x21, 0x52, 0x04, 0x04, 0x90, 0x02, 0x2b, -0x4d, 0xd1, 0xc0, 0x7d, 0x80, 0x07, 0x4a, 0xd5, 0x48, 0x4f, 0x03, 0x24, 0x78, 0x78, 0x00, 0x28, -0x26, 0xd0, 0x47, 0x48, 0x7a, 0x78, 0x01, 0x26, 0x31, 0x46, 0x91, 0x40, 0x21, 0x42, 0x14, 0xd0, -0x29, 0x7a, 0x00, 0x29, 0x1e, 0xd0, 0x04, 0x21, 0x0a, 0x07, 0x09, 0x21, 0x49, 0x04, 0x53, 0x18, -0x40, 0x49, 0x04, 0x22, 0x40, 0x18, 0x00, 0x21, 0x02, 0x90, 0x39, 0x48, 0x00, 0x91, 0x01, 0x91, -0x03, 0x91, 0x01, 0x7a, 0xc0, 0x79, 0xf3, 0xf7, 0xbd, 0xf9, 0x78, 0x78, 0x86, 0x40, 0xb4, 0x43, -0x15, 0xd0, 0x33, 0x48, 0x00, 0x7d, 0x01, 0x28, 0x06, 0xd0, 0x02, 0x28, 0x04, 0xd0, 0x08, 0xe0, -0x2a, 0x20, 0xd7, 0xe7, 0x03, 0x21, 0xdf, 0xe7, 0x33, 0x48, 0x81, 0x7c, 0xcf, 0x22, 0x11, 0x40, -0x81, 0x74, 0x00, 0xf0, 0xb1, 0xfc, 0x00, 0xf0, 0x29, 0xfc, 0x00, 0x28, 0xc6, 0xd1, 0x28, 0x48, -0x00, 0x7d, 0x01, 0x28, 0x01, 0xd0, 0x02, 0x28, 0x04, 0xd1, 0x2b, 0x48, 0x81, 0x7c, 0xcf, 0x22, -0x11, 0x40, 0x81, 0x74, 0x00, 0xf0, 0xa0, 0xfc, 0xfd, 0xf7, 0x44, 0xfc, 0x10, 0xe0, 0x28, 0x7a, -0x00, 0x28, 0x37, 0xd0, 0x04, 0x20, 0x00, 0x07, 0x83, 0x18, 0x24, 0x48, 0x02, 0x90, 0x1c, 0x48, -0x00, 0x91, 0x01, 0x91, 0x03, 0x91, 0x01, 0x7a, 0xc0, 0x79, 0x04, 0x22, 0xf3, 0xf7, 0x82, 0xf9, -0x05, 0x98, 0x01, 0x27, 0x87, 0x76, 0x04, 0x98, 0xc0, 0x7d, 0xc0, 0x06, 0x20, 0xd5, 0x14, 0x48, -0x01, 0x21, 0xc6, 0x79, 0x01, 0x2e, 0x19, 0xd3, 0x04, 0x7a, 0x01, 0x20, 0x01, 0x2c, 0x11, 0xd3, -0x28, 0x22, 0x17, 0x4b, 0x4a, 0x43, 0xd5, 0x18, 0x14, 0x22, 0x00, 0xe0, 0x10, 0xe0, 0x15, 0x4b, -0x4a, 0x43, 0xd2, 0x18, 0x43, 0x00, 0xeb, 0x5a, 0x1b, 0x11, 0x13, 0x54, 0x40, 0x1c, 0xc0, 0xb2, -0x84, 0x42, 0xf7, 0xd2, 0x49, 0x1c, 0xc9, 0xb2, 0x8e, 0x42, 0xe6, 0xd2, 0x0e, 0x48, 0xc7, 0x72, -0x07, 0xb0, 0xf0, 0xbd, 0x03, 0x20, 0xc6, 0xe7, 0x8c, 0x03, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, -0xa8, 0x0c, 0x01, 0x20, 0xe8, 0x0d, 0x01, 0x20, 0x6c, 0x03, 0x01, 0x20, 0xcc, 0x00, 0x01, 0x20, -0x2a, 0x08, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0x00, 0x50, 0x03, 0x40, 0x2a, 0x00, 0x14, 0x10, -0x00, 0x40, 0x01, 0x20, 0xf4, 0x1e, 0x01, 0x20, 0x78, 0x2e, 0x01, 0x20, 0x24, 0x48, 0xc0, 0x7d, -0xc0, 0x06, 0x43, 0xd5, 0xf0, 0xb5, 0x23, 0x4c, 0x82, 0xb0, 0xe0, 0x79, 0x01, 0x21, 0x01, 0x90, -0x01, 0x28, 0x36, 0xd3, 0x20, 0x7f, 0xe2, 0x7e, 0x00, 0x02, 0x10, 0x43, 0x00, 0x90, 0xa2, 0x7d, -0x65, 0x7d, 0x13, 0x02, 0x2b, 0x43, 0xa2, 0x7f, 0x65, 0x7f, 0x10, 0x02, 0x28, 0x43, 0x26, 0x7a, -0x86, 0x46, 0x01, 0x20, 0x01, 0x2e, 0x1f, 0xd3, 0x14, 0x24, 0x0d, 0x46, 0x16, 0x4a, 0x65, 0x43, -0xaa, 0x18, 0x94, 0x46, 0x28, 0x24, 0x0a, 0x46, 0x62, 0x43, 0x14, 0x4c, 0x14, 0x4f, 0x12, 0x19, -0xef, 0x19, 0x00, 0x9d, 0xab, 0x42, 0x05, 0xd1, 0x65, 0x46, 0x2d, 0x5c, 0x2c, 0x01, 0x45, 0x00, -0x54, 0x53, 0x05, 0xe0, 0x73, 0x45, 0x03, 0xd1, 0x3d, 0x5c, 0x2c, 0x01, 0x45, 0x00, 0x54, 0x53, -0x40, 0x1c, 0xc0, 0xb2, 0x86, 0x42, 0xec, 0xd2, 0x49, 0x1c, 0x01, 0x98, 0xc9, 0xb2, 0x88, 0x42, -0xd7, 0xd2, 0x08, 0x48, 0x01, 0x21, 0xc1, 0x72, 0x02, 0xb0, 0xf0, 0xbd, 0x70, 0x47, 0x00, 0x00, -0xe8, 0x0d, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0xf4, 0x1e, 0x01, 0x20, 0x00, 0x40, 0x01, 0x20, -0x9c, 0x21, 0x01, 0x20, 0x78, 0x2e, 0x01, 0x20, 0xf0, 0xb4, 0x0c, 0x48, 0x0c, 0x4f, 0x05, 0x7a, -0x00, 0x21, 0x00, 0x20, 0x00, 0x2d, 0x0b, 0xd9, 0x24, 0x22, 0x4a, 0x43, 0x09, 0x4b, 0xd6, 0x19, -0xd3, 0x18, 0x42, 0x00, 0x40, 0x1c, 0xb4, 0x5a, 0xc0, 0xb2, 0x9c, 0x52, 0x85, 0x42, 0xf8, 0xd8, -0x49, 0x1c, 0xc9, 0xb2, 0x04, 0x29, 0xec, 0xd3, 0xf0, 0xbc, 0x70, 0x47, 0xa8, 0x0c, 0x01, 0x20, -0xe4, 0x11, 0x01, 0x20, 0x74, 0x12, 0x01, 0x20, 0x70, 0xb4, 0x28, 0x22, 0x12, 0x4b, 0x42, 0x43, -0xd4, 0x18, 0x12, 0x4d, 0x4b, 0x00, 0xe2, 0x5e, 0xad, 0x8b, 0x11, 0x4e, 0xaa, 0x42, 0x09, 0xdb, -0x75, 0x88, 0x6d, 0x1c, 0x75, 0x80, 0xb5, 0x88, 0xaa, 0x42, 0x03, 0xdd, 0xe2, 0x5a, 0xb2, 0x80, -0xb0, 0x71, 0xf1, 0x71, 0x32, 0x7a, 0x82, 0x42, 0x00, 0xd9, 0x30, 0x72, 0x72, 0x7a, 0x8a, 0x42, -0x00, 0xd9, 0x71, 0x72, 0xb2, 0x7a, 0x82, 0x42, 0x00, 0xd2, 0xb0, 0x72, 0xf0, 0x7a, 0x88, 0x42, -0x00, 0xd2, 0xf1, 0x72, 0x70, 0xbc, 0x70, 0x47, 0x00, 0x50, 0x01, 0x20, 0x84, 0x2d, 0x01, 0x20, -0xb8, 0x1b, 0x01, 0x20, 0x04, 0x49, 0x82, 0x88, 0x8a, 0x80, 0x02, 0x88, 0x0a, 0x80, 0x42, 0x88, -0x4a, 0x80, 0xc0, 0x79, 0xc8, 0x71, 0x70, 0x47, 0x1a, 0x01, 0x01, 0x20, 0x10, 0xb5, 0x02, 0xa0, -0x00, 0xf0, 0x8e, 0xfe, 0x10, 0xbd, 0x00, 0x00, 0x54, 0x69, 0x6d, 0x65, 0x72, 0x33, 0x20, 0x41, -0x72, 0x72, 0x69, 0x76, 0x65, 0x0a, 0x00, 0x00, 0xf1, 0xb5, 0x92, 0xb0, 0xe8, 0x48, 0x00, 0x90, -0x01, 0x90, 0xe8, 0x48, 0x01, 0x7d, 0xe8, 0x48, 0x10, 0x90, 0xe8, 0x48, 0x04, 0x90, 0x01, 0x29, -0x7e, 0xd1, 0x10, 0x98, 0xc0, 0x7d, 0x80, 0x06, 0x7a, 0xd5, 0x12, 0x98, 0x00, 0x28, 0x77, 0xd1, -0x04, 0x98, 0x01, 0x90, 0x00, 0x20, 0x07, 0x90, 0x01, 0x98, 0x00, 0x78, 0x00, 0x28, 0x6f, 0xd9, -0xdf, 0x48, 0x0f, 0x90, 0x00, 0x20, 0x06, 0x90, 0x0f, 0x98, 0x00, 0x7e, 0x00, 0x28, 0x68, 0xd9, -0x07, 0x98, 0x0c, 0x21, 0x48, 0x43, 0xdb, 0x49, 0x0d, 0x22, 0x41, 0x18, 0x92, 0x01, 0x89, 0x18, -0x0e, 0x91, 0x01, 0x99, 0x45, 0x18, 0x06, 0x98, 0x0c, 0x21, 0x48, 0x43, 0xd5, 0x49, 0x42, 0x18, -0x11, 0x20, 0x80, 0x01, 0x17, 0x18, 0xba, 0x7e, 0xa8, 0x78, 0x82, 0x42, 0x7e, 0xd1, 0x02, 0x90, -0x78, 0x8c, 0x68, 0x81, 0x38, 0x8c, 0x28, 0x81, 0x02, 0x98, 0x09, 0x18, 0x09, 0x20, 0x00, 0x02, -0x08, 0x18, 0x80, 0x7d, 0x02, 0x28, 0x04, 0xd0, 0xcb, 0x49, 0x02, 0x9a, 0x00, 0x20, 0x88, 0x54, -0xbd, 0xe0, 0xca, 0x48, 0x02, 0x99, 0x40, 0x5c, 0x02, 0x28, 0x04, 0xd0, 0xc6, 0x4a, 0x02, 0x98, -0x01, 0x21, 0x11, 0x54, 0xb3, 0xe0, 0xc4, 0x49, 0x02, 0x98, 0x02, 0x9a, 0x08, 0x5c, 0x40, 0x1c, -0xc0, 0xb2, 0x88, 0x54, 0x05, 0x28, 0x03, 0xd3, 0x02, 0x9a, 0x05, 0x20, 0x88, 0x54, 0x01, 0xe0, -0x04, 0x28, 0x7d, 0xd3, 0x00, 0x20, 0x05, 0x90, 0xbd, 0x48, 0x01, 0x78, 0x00, 0x29, 0x4d, 0xd9, -0xbc, 0x48, 0x00, 0x24, 0x01, 0x78, 0x00, 0x29, 0x73, 0xd9, 0x05, 0x98, 0xb8, 0x49, 0x0c, 0x22, -0x50, 0x43, 0x46, 0x18, 0x0c, 0x21, 0xb7, 0x4a, 0x61, 0x43, 0xb0, 0x78, 0x89, 0x18, 0x03, 0x91, -0x89, 0x78, 0x88, 0x42, 0x79, 0xd1, 0x02, 0x99, 0x88, 0x42, 0x76, 0xd1, 0xb8, 0x8b, 0xf2, 0xf7, -0x7e, 0xfd, 0xb1, 0x4a, 0xb1, 0x4b, 0xf2, 0xf7, 0x7d, 0xfd, 0x0d, 0x91, 0x0c, 0x90, 0x01, 0xe0, -0x9b, 0xe0, 0x90, 0xe0, 0x0e, 0x98, 0x40, 0x8a, 0xf2, 0xf7, 0x71, 0xfd, 0xac, 0x4a, 0xad, 0x4b, -0xf2, 0xf7, 0x70, 0xfd, 0x0b, 0x91, 0x0a, 0x90, 0xb0, 0x88, 0xf2, 0xf7, 0x68, 0xfd, 0xaa, 0x4a, -0xaa, 0x4b, 0xf2, 0xf7, 0x67, 0xfd, 0x08, 0x90, 0x03, 0x98, 0x09, 0x91, 0x80, 0x88, 0xf2, 0xf7, -0x5e, 0xfd, 0xa7, 0x4a, 0xa7, 0x4b, 0xf2, 0xf7, 0x5d, 0xfd, 0x09, 0x9b, 0x08, 0x9a, 0xf2, 0xf7, -0xd9, 0xfc, 0x0b, 0x9b, 0x0a, 0x9a, 0xf2, 0xf7, 0xd5, 0xfc, 0x0d, 0x9b, 0x0c, 0x9a, 0xf2, 0xf7, -0xd1, 0xfc, 0x00, 0x22, 0xa0, 0x4b, 0xf2, 0xf7, 0xcd, 0xfc, 0x00, 0xe0, 0x59, 0xe0, 0xf2, 0xf7, -0xf9, 0xfc, 0xa8, 0x80, 0xf8, 0x8b, 0xf2, 0xf7, 0x42, 0xfd, 0x93, 0x4a, 0x93, 0x4b, 0xf2, 0xf7, -0x41, 0xfd, 0x0c, 0x90, 0x0e, 0x98, 0x0d, 0x91, 0x80, 0x8a, 0xf2, 0xf7, 0x38, 0xfd, 0x90, 0x4a, -0x90, 0x4b, 0xf2, 0xf7, 0x37, 0xfd, 0x0b, 0x91, 0x0a, 0x90, 0xf0, 0x88, 0xf2, 0xf7, 0x2f, 0xfd, -0x8d, 0x4a, 0x8e, 0x4b, 0xf2, 0xf7, 0x2e, 0xfd, 0x08, 0x90, 0x03, 0x98, 0x09, 0x91, 0xc0, 0x88, -0xf2, 0xf7, 0x25, 0xfd, 0x8a, 0x4a, 0x8b, 0x4b, 0xf2, 0xf7, 0x24, 0xfd, 0x09, 0x9b, 0x02, 0xe0, -0x25, 0xe0, 0x19, 0xe0, 0x11, 0xe0, 0x08, 0x9a, 0xf2, 0xf7, 0x9c, 0xfc, 0x0b, 0x9b, 0x0a, 0x9a, -0xf2, 0xf7, 0x98, 0xfc, 0x0d, 0x9b, 0x0c, 0x9a, 0xf2, 0xf7, 0x94, 0xfc, 0x00, 0x22, 0x82, 0x4b, -0xf2, 0xf7, 0x90, 0xfc, 0xf2, 0xf7, 0xbe, 0xfc, 0xe8, 0x80, 0x76, 0x48, 0x64, 0x1c, 0x00, 0x78, -0xe4, 0xb2, 0xa0, 0x42, 0x00, 0xd9, 0x75, 0xe7, 0x05, 0x98, 0x40, 0x1c, 0xc0, 0xb2, 0x05, 0x90, -0x6f, 0x48, 0x01, 0x78, 0x05, 0x98, 0x81, 0x42, 0x00, 0xd9, 0x61, 0xe7, 0x09, 0xe0, 0xb8, 0x8b, -0xa9, 0x88, 0x40, 0x18, 0x40, 0x08, 0xa8, 0x80, 0xf8, 0x8b, 0xe9, 0x88, 0x40, 0x18, 0x40, 0x08, -0xe8, 0x80, 0x06, 0x98, 0x40, 0x1c, 0xc0, 0xb2, 0x06, 0x90, 0x0f, 0x98, 0x01, 0x7e, 0x06, 0x98, -0x81, 0x42, 0x00, 0xd9, 0x0f, 0xe7, 0x07, 0x98, 0x40, 0x1c, 0xc0, 0xb2, 0x07, 0x90, 0x01, 0x98, -0x01, 0x78, 0x07, 0x98, 0x81, 0x42, 0x00, 0xd9, 0xf4, 0xe6, 0x68, 0x48, 0xc0, 0x7b, 0x68, 0x4b, -0x00, 0x28, 0x02, 0xd0, 0x01, 0x20, 0x98, 0x77, 0x02, 0xe0, 0x98, 0x7f, 0x00, 0x28, 0x16, 0xd0, -0x00, 0x20, 0x04, 0x27, 0x09, 0x24, 0x53, 0x4d, 0x24, 0x02, 0x06, 0x46, 0x29, 0x18, 0x0a, 0x19, -0x91, 0x7d, 0x01, 0x29, 0x04, 0xd0, 0x02, 0x29, 0x04, 0xd0, 0x03, 0x29, 0x02, 0xd0, 0x02, 0xe0, -0x96, 0x75, 0x00, 0xe0, 0x97, 0x75, 0x40, 0x1c, 0xc0, 0xb2, 0x0b, 0x28, 0xee, 0xd3, 0x01, 0x98, -0x58, 0x4c, 0x00, 0x78, 0x20, 0x70, 0x58, 0x48, 0x81, 0x7b, 0x61, 0x70, 0x58, 0x7b, 0xa0, 0x70, -0x10, 0x98, 0xc7, 0x7d, 0xb8, 0x06, 0x03, 0xd5, 0x3e, 0x48, 0x00, 0x7d, 0x01, 0x28, 0x21, 0xd0, -0x00, 0x20, 0x09, 0x26, 0x3f, 0x4d, 0x36, 0x02, 0x2a, 0x18, 0x14, 0x23, 0x43, 0x43, 0x92, 0x19, -0x1b, 0x19, 0x40, 0x1c, 0x92, 0x7d, 0xc0, 0xb2, 0x9a, 0x74, 0x0b, 0x28, 0xf4, 0xd3, 0x00, 0x20, -0x00, 0x29, 0x40, 0xd9, 0x37, 0x4b, 0x00, 0x25, 0x0c, 0x22, 0x42, 0x43, 0xd6, 0x18, 0x0d, 0x22, -0x92, 0x01, 0xb2, 0x18, 0x12, 0x7c, 0x14, 0x26, 0x72, 0x43, 0x12, 0x19, 0x96, 0x7c, 0x04, 0x2e, -0x2c, 0xd0, 0x2c, 0xe0, 0x00, 0x20, 0x2f, 0x4d, 0x06, 0x46, 0x12, 0x9a, 0x00, 0x2a, 0x0b, 0xd0, -0x09, 0x22, 0x2b, 0x18, 0x12, 0x02, 0x9a, 0x18, 0x92, 0x7d, 0x04, 0x2a, 0x15, 0xd0, 0x14, 0x23, -0x43, 0x43, 0x1b, 0x19, 0x9a, 0x74, 0x14, 0xe0, 0x28, 0x4a, 0x12, 0x5c, 0x00, 0x2a, 0x06, 0xd1, -0x09, 0x22, 0x2b, 0x18, 0x12, 0x02, 0x9a, 0x18, 0x92, 0x7d, 0x01, 0x2a, 0x05, 0xd0, 0x09, 0x22, -0x2b, 0x18, 0x12, 0x02, 0x9a, 0x18, 0x92, 0x7d, 0xe9, 0xe7, 0x14, 0x22, 0x42, 0x43, 0x12, 0x19, -0x96, 0x74, 0x40, 0x1c, 0xc0, 0xb2, 0x0b, 0x28, 0xd7, 0xd3, 0xc0, 0xe7, 0x55, 0x74, 0x40, 0x1c, -0xc0, 0xb2, 0x81, 0x42, 0xc0, 0xd8, 0x29, 0x4a, 0xb8, 0x06, 0x03, 0xd5, 0x11, 0x48, 0x00, 0x7d, -0x01, 0x28, 0x02, 0xd0, 0x00, 0x99, 0x04, 0x98, 0x14, 0xe0, 0x12, 0x98, 0x00, 0x28, 0x13, 0xd0, -0x14, 0x46, 0x13, 0x49, 0x13, 0x48, 0xf2, 0xf7, 0xe7, 0xf8, 0x22, 0x46, 0x10, 0x48, 0x04, 0x99, -0xf2, 0xf7, 0xe2, 0xf8, 0x22, 0x46, 0x00, 0x99, 0x04, 0x98, 0xf2, 0xf7, 0xdd, 0xf8, 0x0b, 0x22, -0x1b, 0x49, 0x0a, 0x48, 0xf2, 0xf7, 0xd8, 0xf8, 0x01, 0x98, 0x13, 0xb0, 0xf0, 0xbd, 0x00, 0x00, -0x9c, 0x28, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0xe8, 0x0d, 0x01, 0x20, 0x92, 0x27, 0x01, 0x20, -0x84, 0x28, 0x01, 0x20, 0x44, 0x24, 0x01, 0x20, 0x94, 0x1b, 0x01, 0x20, 0x9f, 0x1b, 0x01, 0x20, -0x80, 0x19, 0x01, 0x20, 0x8a, 0x1a, 0x01, 0x20, 0xa0, 0x1a, 0x2f, 0xdd, 0x24, 0x06, 0xdd, 0x3f, -0xb4, 0xc8, 0x76, 0xbe, 0x9f, 0x1a, 0xe1, 0x3f, 0x3f, 0x35, 0x5e, 0xba, 0x49, 0x0c, 0xb2, 0x3f, -0xc1, 0xca, 0xa1, 0x45, 0xb6, 0xf3, 0xad, 0xbf, 0x00, 0x00, 0xe0, 0x3f, 0x6c, 0x03, 0x01, 0x20, -0x84, 0x2d, 0x01, 0x20, 0x68, 0x02, 0x01, 0x20, 0x84, 0x27, 0x01, 0x20, 0x0a, 0x01, 0x00, 0x00, -0x5a, 0x2d, 0x01, 0x20, 0x13, 0x48, 0x80, 0x7d, 0x01, 0x28, 0x22, 0xd0, 0x10, 0xb5, 0x12, 0x4c, -0x20, 0x78, 0x52, 0x28, 0x05, 0xd0, 0x60, 0x78, 0x53, 0x28, 0x02, 0xd0, 0xa0, 0x78, 0x54, 0x28, -0x12, 0xd1, 0xf7, 0xf7, 0x25, 0xfb, 0x04, 0x28, 0x0e, 0xd0, 0x00, 0x21, 0x0b, 0x48, 0xf5, 0xf7, -0x7e, 0xfd, 0x00, 0x21, 0x0a, 0x48, 0xf5, 0xf7, 0x7a, 0xfd, 0xc8, 0x20, 0xf5, 0xf7, 0x42, 0xfe, -0x00, 0x21, 0x08, 0x48, 0xf5, 0xf7, 0x73, 0xfd, 0x00, 0x20, 0x20, 0x70, 0x60, 0x70, 0xa0, 0x70, -0x10, 0xbd, 0x70, 0x47, 0xe8, 0x0d, 0x01, 0x20, 0xf0, 0x3f, 0x01, 0x20, 0xd4, 0xc0, 0x03, 0x40, -0x44, 0xc0, 0x03, 0x40, 0xa4, 0xc0, 0x03, 0x40, 0x10, 0xb5, 0x08, 0x4c, 0xa0, 0x7b, 0x00, 0x28, -0x0a, 0xd0, 0x64, 0x21, 0x00, 0x20, 0x00, 0xbf, 0x40, 0x1c, 0x88, 0x42, 0xfb, 0xd3, 0x00, 0xf0, -0x8f, 0xf9, 0xa0, 0x7b, 0x00, 0x28, 0xf4, 0xd1, 0x10, 0xbd, 0x00, 0x00, 0x8c, 0x03, 0x01, 0x20, -0xf1, 0xb5, 0x2e, 0x4f, 0x7c, 0x79, 0x2e, 0x48, 0x00, 0x68, 0x2e, 0x4d, 0x2e, 0x4e, 0x26, 0xe0, -0x00, 0xf0, 0x7e, 0xf9, 0x00, 0xf0, 0xaa, 0xf8, 0x30, 0x7d, 0x00, 0x28, 0x01, 0xd0, 0x03, 0x28, -0x0b, 0xd1, 0xa8, 0x78, 0x00, 0x28, 0x06, 0xd1, 0x00, 0xf0, 0x72, 0xf9, 0xf3, 0xf7, 0x94, 0xfb, -0xa8, 0x78, 0x00, 0x28, 0xf8, 0xd0, 0x00, 0x20, 0xa8, 0x70, 0xfd, 0xf7, 0xb5, 0xf8, 0x30, 0x7d, -0x01, 0x28, 0x01, 0xd0, 0x02, 0x28, 0x04, 0xd1, 0x20, 0x4a, 0x90, 0x7c, 0xcf, 0x21, 0x08, 0x40, -0x90, 0x74, 0x78, 0x79, 0xa0, 0x42, 0x02, 0xd0, 0x7c, 0x79, 0xfb, 0xf7, 0x99, 0xfb, 0xf7, 0xf7, -0xbf, 0xfa, 0x04, 0x28, 0x03, 0xd0, 0x39, 0x78, 0x00, 0x98, 0x81, 0x42, 0xd0, 0xd0, 0x18, 0x48, -0x00, 0x7e, 0x80, 0x1e, 0xfd, 0x28, 0x07, 0xd2, 0x15, 0x21, 0x16, 0x48, 0xf5, 0xf7, 0x0f, 0xfd, -0x02, 0x21, 0x15, 0x48, 0xf5, 0xf7, 0x0b, 0xfd, 0x30, 0x7d, 0x02, 0x28, 0x14, 0xd1, 0xb0, 0x7b, -0x01, 0x28, 0x01, 0xd0, 0x02, 0x28, 0x0f, 0xd1, 0x10, 0x48, 0xc0, 0x7d, 0xc0, 0x06, 0x0b, 0xd5, -0x0f, 0x48, 0xff, 0x21, 0x81, 0x70, 0xc1, 0x78, 0x03, 0x22, 0x11, 0x43, 0xc1, 0x70, 0x01, 0x78, -0x09, 0x09, 0x09, 0x01, 0xc9, 0x1c, 0x01, 0x70, 0xf8, 0xbd, 0x00, 0x00, 0x4c, 0x03, 0x01, 0x20, -0x68, 0x00, 0x01, 0x20, 0x18, 0x00, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, 0x00, 0x50, 0x03, 0x40, -0x28, 0x0d, 0x01, 0x20, 0x67, 0xd1, 0x03, 0x40, 0x06, 0xe0, 0x03, 0x40, 0xe8, 0x0d, 0x01, 0x20, -0x80, 0x51, 0x03, 0x40, 0xf8, 0xb5, 0x1c, 0x4f, 0x00, 0x24, 0x78, 0x78, 0x00, 0x28, 0x30, 0xd0, -0x1a, 0x4e, 0x1b, 0x4d, 0x20, 0x46, 0x64, 0x1c, 0xff, 0x21, 0xf5, 0x31, 0xa4, 0xb2, 0x88, 0x42, -0x13, 0xd3, 0x18, 0x48, 0xc0, 0x7e, 0x00, 0x28, 0x23, 0xd1, 0x17, 0x48, 0x00, 0x7e, 0x00, 0x28, -0x06, 0xd0, 0x00, 0x21, 0x0a, 0x20, 0xf7, 0xf7, 0x15, 0xfd, 0x00, 0x20, 0x78, 0x70, 0x18, 0xe0, -0x01, 0x21, 0x0a, 0x20, 0xf7, 0xf7, 0x0e, 0xfd, 0xf7, 0xe7, 0x14, 0x23, 0x00, 0x22, 0xf0, 0x7c, -0x41, 0x5d, 0x00, 0x20, 0x00, 0x29, 0x03, 0xd9, 0x00, 0xbf, 0x40, 0x1c, 0x88, 0x42, 0xfb, 0xd3, -0x52, 0x1c, 0x92, 0xb2, 0x9a, 0x42, 0xf2, 0xd3, 0x00, 0xf0, 0xe2, 0xf8, 0x78, 0x78, 0x00, 0x28, -0xd0, 0xd1, 0x00, 0x20, 0x38, 0x70, 0xf8, 0xbd, 0x02, 0x00, 0x01, 0x20, 0x20, 0x00, 0x03, 0x40, -0xb6, 0xeb, 0x00, 0x00, 0x4c, 0x03, 0x01, 0x20, 0x68, 0x0d, 0x01, 0x20, 0xf8, 0xb5, 0x01, 0x20, -0x00, 0x90, 0x2b, 0x48, 0x40, 0x79, 0x2b, 0x4d, 0x00, 0x28, 0x44, 0xd1, 0x2a, 0x4e, 0x68, 0x7c, -0x00, 0x28, 0x02, 0xd0, 0x00, 0x20, 0x00, 0x90, 0x3d, 0xe0, 0x30, 0x78, 0x01, 0x27, 0x04, 0x07, -0x24, 0x0f, 0x00, 0xf0, 0xbd, 0xf8, 0x00, 0x20, 0x31, 0x78, 0x09, 0x07, 0x09, 0x0f, 0xa1, 0x42, -0xf3, 0xd1, 0x40, 0x1c, 0xc0, 0xb2, 0x03, 0x28, 0xf6, 0xd3, 0x00, 0x2f, 0xed, 0xd0, 0x01, 0x2c, -0x13, 0xd0, 0x30, 0x78, 0x01, 0x27, 0x04, 0x07, 0x24, 0x0f, 0x00, 0xf0, 0xa9, 0xf8, 0x00, 0x20, -0x31, 0x78, 0x09, 0x07, 0x09, 0x0f, 0xa1, 0x42, 0xf3, 0xd1, 0x40, 0x1c, 0xc0, 0xb2, 0x03, 0x28, -0xf6, 0xd3, 0x00, 0x2f, 0xed, 0xd0, 0x00, 0x2c, 0x0a, 0xd1, 0x68, 0x7b, 0x00, 0x28, 0x07, 0xd1, -0x12, 0x48, 0x00, 0x78, 0x03, 0x28, 0x03, 0xd0, 0x11, 0x48, 0x00, 0x7d, 0x03, 0x28, 0xc9, 0xd1, -0x00, 0xf0, 0x8e, 0xf8, 0x28, 0x7c, 0x00, 0x28, 0x01, 0xd1, 0xf3, 0xf7, 0xad, 0xfa, 0x08, 0x48, -0x40, 0x79, 0x00, 0x28, 0xbb, 0xd0, 0x06, 0x49, 0x00, 0x20, 0x48, 0x71, 0x28, 0x74, 0x09, 0x49, -0x88, 0x77, 0x28, 0x7d, 0x01, 0x28, 0x01, 0xd0, 0xfb, 0xf7, 0x4a, 0xff, 0x00, 0x98, 0xf8, 0xbd, -0x18, 0x00, 0x01, 0x20, 0x6c, 0x03, 0x01, 0x20, 0x60, 0x00, 0x03, 0x40, 0x4c, 0x03, 0x01, 0x20, -0xa8, 0x0c, 0x01, 0x20, 0x84, 0x2d, 0x01, 0x20, 0x10, 0xb5, 0x0b, 0x4c, 0x60, 0x79, 0x00, 0x28, -0x04, 0xd1, 0x00, 0xf0, 0x65, 0xf8, 0x60, 0x79, 0x00, 0x28, 0xfa, 0xd0, 0x07, 0x48, 0x00, 0x78, -0x00, 0x20, 0x60, 0x71, 0x06, 0x49, 0x08, 0x74, 0x06, 0x48, 0x00, 0x7d, 0xc0, 0x07, 0x01, 0xd1, -0xfb, 0xf7, 0x26, 0xff, 0x10, 0xbd, 0x00, 0x00, 0x18, 0x00, 0x01, 0x20, 0x4c, 0x03, 0x01, 0x20, -0x6c, 0x03, 0x01, 0x20, 0x40, 0x50, 0x03, 0x40, 0x0a, 0x48, 0x00, 0x7d, 0x00, 0x28, 0x01, 0xd0, -0x03, 0x28, 0x0e, 0xd1, 0x10, 0xb5, 0x08, 0x4c, 0xa0, 0x78, 0x00, 0x28, 0x06, 0xd1, 0x00, 0xf0, -0x3f, 0xf8, 0xf3, 0xf7, 0x61, 0xfa, 0xa0, 0x78, 0x00, 0x28, 0xf8, 0xd0, 0x00, 0x20, 0xa0, 0x70, -0x10, 0xbd, 0x70, 0x47, 0xa8, 0x0c, 0x01, 0x20, 0x18, 0x00, 0x01, 0x20, 0x10, 0xb5, 0x07, 0x4c, -0x20, 0x78, 0x00, 0x28, 0x07, 0xd1, 0x05, 0x20, 0x00, 0xf0, 0xee, 0xf9, 0x00, 0xf0, 0x28, 0xf8, -0x20, 0x78, 0x00, 0x28, 0xf7, 0xd0, 0x00, 0x20, 0x20, 0x70, 0x10, 0xbd, 0xcc, 0x00, 0x01, 0x20, -0x70, 0xb5, 0x06, 0x46, 0x0a, 0x4c, 0x01, 0x20, 0x0d, 0x46, 0xa0, 0x70, 0xa0, 0x78, 0x00, 0x28, -0x0c, 0xd0, 0x00, 0xf0, 0x15, 0xf8, 0x20, 0x78, 0xb0, 0x42, 0x02, 0xd1, 0x60, 0x79, 0xa8, 0x42, -0x01, 0xd0, 0x00, 0x20, 0x70, 0xbd, 0xa0, 0x78, 0x00, 0x28, 0xf2, 0xd1, 0x01, 0x20, 0x70, 0xbd, -0x4c, 0x03, 0x01, 0x20, 0x01, 0x49, 0x00, 0x20, 0x48, 0x61, 0x70, 0x47, 0x00, 0x00, 0x03, 0x40, -0x04, 0x48, 0xc0, 0x7d, 0xc0, 0x09, 0x04, 0xd0, 0x03, 0x48, 0x01, 0x21, 0x01, 0x76, 0xfe, 0x21, -0x01, 0x76, 0x70, 0x47, 0xe8, 0x0d, 0x01, 0x20, 0x00, 0x00, 0x03, 0x40, 0x02, 0x49, 0x01, 0x48, -0x48, 0x61, 0x70, 0x47, 0x10, 0x02, 0x00, 0x01, 0x00, 0x00, 0x03, 0x40, 0x10, 0xb5, 0x00, 0xf0, -0x01, 0xf8, 0x10, 0xbd, 0xf8, 0xb5, 0x0c, 0x46, 0x01, 0x21, 0x09, 0x03, 0x88, 0x42, 0x7d, 0xd2, -0x1f, 0x21, 0xc9, 0x01, 0x88, 0x42, 0x1d, 0xd2, 0x0f, 0x21, 0x09, 0x02, 0x88, 0x42, 0x19, 0xd2, -0x1d, 0x21, 0xc9, 0x01, 0x88, 0x42, 0x15, 0xd2, 0x5b, 0x28, 0x13, 0xd2, 0xbe, 0x4e, 0x35, 0x46, -0x29, 0x46, 0x32, 0x18, 0x20, 0x31, 0x40, 0x35, 0x33, 0x28, 0x68, 0xd0, 0x17, 0xdc, 0x01, 0x27, -0x04, 0x28, 0x2e, 0xd0, 0x07, 0xdc, 0x00, 0x28, 0x25, 0xd0, 0x01, 0x28, 0x02, 0xd0, 0x02, 0x28, -0x00, 0xd1, 0xb4, 0x70, 0xf8, 0xbd, 0x22, 0x28, 0x72, 0xd0, 0x23, 0x28, 0x71, 0xd0, 0x2d, 0x28, -0x70, 0xd0, 0x32, 0x28, 0xf6, 0xd1, 0xb1, 0x49, 0x48, 0x80, 0x0c, 0x70, 0xf8, 0xbd, 0x49, 0x28, -0x69, 0xd0, 0x08, 0xdc, 0x34, 0x28, 0x67, 0xd0, 0x35, 0x28, 0x6e, 0xd0, 0x45, 0x28, 0x6d, 0xd0, -0x48, 0x28, 0xf3, 0xd1, 0xf3, 0xe0, 0x4a, 0x28, 0x5d, 0xd0, 0x4b, 0x28, 0x5b, 0xd0, 0x50, 0x28, -0xec, 0xd1, 0x2c, 0x74, 0xf8, 0xbd, 0x30, 0x78, 0xa0, 0x42, 0xfb, 0xd0, 0x77, 0x70, 0x34, 0x70, -0xf8, 0xbd, 0x01, 0x2c, 0x0b, 0xd0, 0x02, 0x2c, 0x6f, 0xd0, 0x08, 0x2c, 0x0a, 0xd0, 0x20, 0x46, -0x10, 0x38, 0x06, 0x28, 0x0a, 0xd8, 0x20, 0x46, 0xfd, 0xf7, 0x4e, 0xfc, 0xb5, 0xe0, 0xf8, 0xf7, -0x8b, 0xff, 0xb2, 0xe0, 0x02, 0x20, 0x70, 0x71, 0x8f, 0x76, 0xae, 0xe0, 0x00, 0x20, 0x20, 0x2c, -0x3b, 0xd0, 0x30, 0x2c, 0x3b, 0xd0, 0x55, 0x2c, 0x3b, 0xd0, 0x66, 0x2c, 0x3b, 0xd0, 0x57, 0x2c, -0x3d, 0xd0, 0x58, 0x2c, 0x3d, 0xd0, 0x21, 0x2c, 0x3d, 0xd0, 0x91, 0x49, 0x8a, 0x2c, 0x3d, 0xd0, -0x8b, 0x2c, 0x3e, 0xd0, 0x8f, 0x49, 0x90, 0x2c, 0x40, 0xd0, 0x91, 0x2c, 0x41, 0xd0, 0x8e, 0x49, -0xa0, 0x2c, 0x40, 0xd0, 0xa1, 0x2c, 0x41, 0xd0, 0x05, 0x2c, 0x01, 0xe0, 0xb3, 0xe0, 0x9d, 0xe0, -0x3e, 0xd0, 0x06, 0x2c, 0x42, 0xd0, 0x07, 0x2c, 0x46, 0xd0, 0x88, 0x4a, 0x86, 0x2c, 0xd1, 0x7e, -0x47, 0xd0, 0x87, 0x2c, 0x48, 0xd0, 0x40, 0x2c, 0x4a, 0xd0, 0x41, 0x2c, 0x59, 0xd0, 0x44, 0x2c, -0x5d, 0xd0, 0xe0, 0x2c, 0x5d, 0xd0, 0x88, 0x2c, 0x5f, 0xd0, 0x89, 0x2c, 0x68, 0xd0, 0x74, 0xe0, -0x75, 0xe0, 0x76, 0xe0, 0x77, 0xe0, 0x92, 0xe0, 0x7c, 0xe0, 0xb7, 0x74, 0x0c, 0xe0, 0x77, 0x74, -0x6b, 0xe0, 0xf7, 0x71, 0x69, 0xe0, 0xf0, 0x71, 0x67, 0xe0, 0x75, 0xe0, 0x89, 0xe0, 0x2f, 0x75, -0x63, 0xe0, 0x28, 0x75, 0x61, 0xe0, 0xb0, 0x74, 0xb0, 0x70, 0x5e, 0xe0, 0x08, 0x69, 0x38, 0x43, -0x02, 0xe0, 0x08, 0x69, 0x40, 0x08, 0x40, 0x00, 0x08, 0x61, 0x56, 0xe0, 0x02, 0x20, 0x48, 0x75, -0x53, 0xe0, 0x48, 0x75, 0x51, 0xe0, 0x4f, 0x70, 0x4f, 0xe0, 0x25, 0xe0, 0x48, 0x70, 0x4c, 0xe0, -0xf7, 0x76, 0x01, 0x21, 0x0a, 0x20, 0xf7, 0xf7, 0x35, 0xfb, 0x46, 0xe0, 0xf7, 0x76, 0x00, 0x21, -0x0a, 0x20, 0xf7, 0xf7, 0x2f, 0xfb, 0x40, 0xe0, 0xf0, 0x76, 0x00, 0x20, 0xfd, 0xf7, 0x1e, 0xfb, -0x3b, 0xe0, 0x10, 0x20, 0x01, 0x43, 0x01, 0xe0, 0xef, 0x20, 0x01, 0x40, 0xd1, 0x76, 0x34, 0xe0, -0x5f, 0x49, 0x09, 0x7e, 0x89, 0x07, 0x07, 0xd5, 0x03, 0x21, 0x71, 0x71, 0xa8, 0x70, 0xf5, 0xf7, -0x31, 0xfd, 0x5c, 0x48, 0x07, 0x70, 0x28, 0xe0, 0xf5, 0xf7, 0x2c, 0xfd, 0x02, 0x20, 0x70, 0x71, -0x23, 0xe0, 0x59, 0x49, 0x09, 0x7d, 0x49, 0x06, 0x1f, 0xd4, 0x70, 0x71, 0x1d, 0xe0, 0xa8, 0x70, -0x1b, 0xe0, 0x00, 0x20, 0xfd, 0xf7, 0xfa, 0xfa, 0x17, 0xe0, 0xfc, 0xf7, 0x1b, 0xff, 0x53, 0x48, -0x10, 0x22, 0x41, 0x7e, 0x11, 0x43, 0x41, 0x76, 0xf3, 0xf7, 0x10, 0xfa, 0xaf, 0x73, 0x0c, 0xe0, -0xa8, 0x73, 0x08, 0x20, 0xf6, 0xf7, 0xbc, 0xff, 0xf3, 0xf7, 0xe8, 0xf9, 0xfc, 0xf7, 0x32, 0xfe, -0x4a, 0x48, 0x08, 0x22, 0x41, 0x7e, 0x11, 0x43, 0x41, 0x76, 0x40, 0x48, 0x3d, 0xe0, 0x8c, 0x70, -0xf8, 0xbd, 0xcc, 0x70, 0xf8, 0xbd, 0x00, 0x2c, 0x01, 0xd0, 0x01, 0x20, 0x00, 0xe0, 0x00, 0x20, -0x48, 0x73, 0xf8, 0xbd, 0x0c, 0x75, 0xf8, 0xbd, 0x4c, 0x75, 0xf8, 0xbd, 0x37, 0x48, 0x41, 0x88, -0x32, 0x29, 0xfa, 0xd1, 0x00, 0x78, 0x21, 0x02, 0x08, 0x18, 0x84, 0xb2, 0x70, 0x8e, 0x00, 0x28, -0x03, 0xd0, 0x00, 0x2c, 0x01, 0xd1, 0xfc, 0xf7, 0xb7, 0xf8, 0x74, 0x86, 0xf8, 0xbd, 0x14, 0x70, -0xf8, 0xbd, 0x6c, 0x71, 0xf8, 0xbd, 0x01, 0x21, 0x49, 0x03, 0x88, 0x42, 0xfa, 0xd3, 0x03, 0x21, -0x09, 0x03, 0x88, 0x42, 0xf6, 0xd3, 0x01, 0x21, 0x89, 0x03, 0x88, 0x42, 0xf2, 0xd3, 0x05, 0x21, -0x09, 0x03, 0x88, 0x42, 0xee, 0xd3, 0x03, 0x22, 0x52, 0x03, 0x90, 0x42, 0x07, 0xd2, 0x40, 0x1a, -0x80, 0xb2, 0x14, 0x28, 0xe6, 0xd2, 0x2a, 0x49, 0x08, 0x18, 0x04, 0x70, 0xf8, 0xbd, 0x07, 0x21, -0x09, 0x03, 0x88, 0x42, 0xfa, 0xd3, 0x01, 0x21, 0xc9, 0x03, 0x88, 0x42, 0xf6, 0xd3, 0x09, 0x22, -0x12, 0x03, 0x90, 0x42, 0x09, 0xd2, 0x40, 0x1a, 0x45, 0x21, 0x80, 0xb2, 0xc9, 0x00, 0x88, 0x42, -0xec, 0xd2, 0x1e, 0x49, 0x08, 0x18, 0x04, 0x70, 0xf8, 0xbd, 0x03, 0x21, 0x89, 0x03, 0x88, 0x42, -0xfa, 0xd3, 0x0f, 0x21, 0x09, 0x03, 0x88, 0x42, 0x06, 0xd2, 0x03, 0x22, 0x12, 0x04, 0x21, 0x46, -0x80, 0x18, 0xf5, 0xf7, 0x34, 0xfa, 0xf8, 0xbd, 0x40, 0x1a, 0x80, 0xb2, 0x05, 0x28, 0xfa, 0xd2, -0x14, 0x4d, 0x29, 0x18, 0x04, 0x28, 0x01, 0xd0, 0x0c, 0x70, 0xf8, 0xbd, 0x28, 0x68, 0x05, 0x22, -0x01, 0x03, 0x09, 0x0b, 0x52, 0x04, 0x91, 0x42, 0xc7, 0xd3, 0xf5, 0xf7, 0x31, 0xfe, 0x28, 0x68, -0x04, 0x70, 0xf5, 0xf7, 0x3d, 0xfe, 0xf8, 0xbd, 0x4c, 0x03, 0x01, 0x20, 0x38, 0x00, 0x01, 0x20, -0x00, 0xe0, 0x00, 0xe0, 0x28, 0x0d, 0x01, 0x20, 0x88, 0x0d, 0x01, 0x20, 0xa8, 0x0d, 0x01, 0x20, -0xe8, 0x0d, 0x01, 0x20, 0x38, 0x02, 0x01, 0x20, 0x48, 0x0d, 0x01, 0x20, 0xa8, 0x0c, 0x01, 0x20, -0x8c, 0x04, 0x01, 0x20, 0x3c, 0x00, 0x01, 0x20, 0x00, 0x21, 0x00, 0x28, 0x03, 0xd9, 0x00, 0xbf, -0x49, 0x1c, 0x81, 0x42, 0xfb, 0xd3, 0x70, 0x47, 0xff, 0xb5, 0x02, 0x46, 0x8b, 0xb0, 0x00, 0x20, -0x05, 0x46, 0x09, 0x90, 0x14, 0x9f, 0x01, 0x20, 0x0a, 0x90, 0x00, 0x20, 0x00, 0x90, 0x01, 0x90, -0x02, 0x90, 0x03, 0x90, 0x04, 0x90, 0x05, 0x90, 0x06, 0x90, 0x07, 0x90, 0x08, 0x90, 0x0e, 0x98, -0x0e, 0x46, 0x00, 0x28, 0x00, 0xd1, 0x0a, 0x90, 0x0d, 0x98, 0x6c, 0x46, 0x40, 0x1e, 0x10, 0x28, -0x06, 0xd3, 0x2a, 0x20, 0x30, 0x70, 0x00, 0x21, 0x71, 0x70, 0xb0, 0x1c, 0x0f, 0xb0, 0xf0, 0xbd, -0x00, 0x2a, 0x01, 0xdb, 0x09, 0x98, 0x04, 0xe0, 0x0d, 0x98, 0x0a, 0x28, 0x04, 0xd0, 0x02, 0x20, -0x09, 0x90, 0x02, 0x28, 0x04, 0xd0, 0x1f, 0xe0, 0x01, 0x20, 0x52, 0x42, 0x09, 0x90, 0x1b, 0xe0, -0x10, 0x09, 0x00, 0x01, 0x50, 0x40, 0xc0, 0xb2, 0x24, 0xa3, 0x18, 0x5c, 0x20, 0x70, 0x12, 0x09, -0x01, 0x25, 0x64, 0x1c, 0x10, 0xe0, 0x10, 0x46, 0x0d, 0x99, 0xf1, 0xf7, 0x2f, 0xfd, 0x1f, 0xa2, -0x51, 0x5c, 0x21, 0x70, 0x02, 0x46, 0x6d, 0x1c, 0x0a, 0x98, 0x64, 0x1c, 0xed, 0xb2, 0x00, 0x28, -0x02, 0xd0, 0x0e, 0x98, 0x85, 0x42, 0x04, 0xd2, 0x00, 0x2a, 0xec, 0xd1, 0x68, 0x46, 0x84, 0x42, -0xe9, 0xd0, 0x09, 0x98, 0x01, 0x28, 0x04, 0xd1, 0x2d, 0x20, 0x6d, 0x1c, 0x20, 0x70, 0xed, 0xb2, -0x64, 0x1c, 0x00, 0x2f, 0x08, 0xd0, 0x30, 0x20, 0x20, 0x70, 0x7f, 0x1e, 0x6d, 0x1c, 0xff, 0xb2, -0x64, 0x1c, 0xed, 0xb2, 0x00, 0x2f, 0xf7, 0xd1, 0x0e, 0x98, 0x85, 0x42, 0x07, 0xd2, 0x20, 0x21, -0x21, 0x70, 0x6d, 0x1c, 0x0e, 0x98, 0xed, 0xb2, 0x64, 0x1c, 0x85, 0x42, 0xf8, 0xd3, 0x68, 0x46, -0x84, 0x42, 0x05, 0xd0, 0x64, 0x1e, 0x21, 0x78, 0x31, 0x70, 0x76, 0x1c, 0x84, 0x42, 0xf9, 0xd1, -0x00, 0x20, 0x30, 0x70, 0x30, 0x46, 0x0f, 0xb0, 0xf0, 0xbd, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33, -0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x00, 0x00, 0x00, 0x00, -0x24, 0x48, 0x0f, 0x21, 0xc1, 0x77, 0xfa, 0xf7, 0x31, 0xfa, 0xf6, 0xf7, 0x2b, 0xff, 0xf3, 0xf7, -0xf1, 0xff, 0xf3, 0xf7, 0x79, 0xff, 0xfe, 0xf7, 0xe3, 0xff, 0xf4, 0xf7, 0xb1, 0xff, 0xf5, 0xf7, -0x7f, 0xfd, 0xe1, 0x21, 0x49, 0x02, 0x01, 0x20, 0xfe, 0xf7, 0xdc, 0xff, 0xf8, 0xf7, 0xe8, 0xf9, -0xfa, 0xf7, 0xf4, 0xfd, 0xfe, 0xf7, 0x58, 0xfa, 0x17, 0xa0, 0x00, 0xf0, 0x39, 0xf8, 0x1b, 0x4c, -0x20, 0x78, 0x10, 0x28, 0xfc, 0xd2, 0x01, 0x00, 0x79, 0x44, 0x09, 0x79, 0x49, 0x18, 0x8f, 0x44, -0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17, 0x1a, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x1d, -0xee, 0xe7, 0xf9, 0xf7, 0x15, 0xfa, 0xeb, 0xe7, 0xf5, 0xf7, 0x2c, 0xfe, 0xe8, 0xe7, 0xf5, 0xf7, -0x01, 0xf9, 0xe5, 0xe7, 0xf9, 0xf7, 0x52, 0xfb, 0xe2, 0xe7, 0xf7, 0xf7, 0x8d, 0xfa, 0xdf, 0xe7, -0xf8, 0xf7, 0x84, 0xfd, 0xdc, 0xe7, 0xfe, 0xf7, 0xb1, 0xfb, 0xd9, 0xe7, 0xf5, 0xf7, 0xc2, 0xf9, -0xd6, 0xe7, 0x00, 0x00, 0x6c, 0x03, 0x01, 0x20, 0x49, 0x43, 0x4e, 0x4c, 0x39, 0x39, 0x31, 0x31, -0x53, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x03, 0x01, 0x20, -0x0f, 0xb4, 0xf0, 0xb5, 0x42, 0x48, 0x8b, 0xb0, 0x00, 0x7e, 0x80, 0x06, 0x03, 0xd4, 0x41, 0x48, -0xc0, 0x7e, 0xc0, 0x06, 0x44, 0xd5, 0x10, 0x98, 0x00, 0x24, 0x00, 0x78, 0x26, 0x46, 0x11, 0xad, -0x00, 0x28, 0x3d, 0xd0, 0x10, 0x99, 0x08, 0x78, 0x25, 0x28, 0x01, 0xd0, 0x00, 0x2c, 0x13, 0xd0, -0x49, 0x1c, 0x10, 0x91, 0x08, 0x78, 0x37, 0x28, 0x37, 0xd0, 0x19, 0xdc, 0x02, 0x46, 0x2e, 0x3a, -0x09, 0x2a, 0x23, 0xd2, 0x13, 0x00, 0x7b, 0x44, 0x1b, 0x79, 0xdb, 0x18, 0x9f, 0x44, 0x30, 0x1e, -0x1e, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x00, 0x0a, 0x28, 0x02, 0xd1, 0x0d, 0x20, 0xfe, 0xf7, -0x8b, 0xff, 0x10, 0x99, 0x08, 0x78, 0x49, 0x1c, 0x10, 0x91, 0xfe, 0xf7, 0x85, 0xff, 0x13, 0xe0, -0x58, 0x28, 0x38, 0xd0, 0x06, 0xdc, 0x38, 0x28, 0x17, 0xd0, 0x39, 0x28, 0x15, 0xd0, 0x44, 0x28, -0x04, 0xd1, 0x1b, 0xe0, 0x64, 0x28, 0x19, 0xd0, 0x78, 0x28, 0x2c, 0xd0, 0xfe, 0xf7, 0x74, 0xff, -0x00, 0x24, 0x10, 0x98, 0x40, 0x1c, 0x10, 0x90, 0x10, 0x98, 0x00, 0x78, 0x00, 0x28, 0xc1, 0xd1, -0x0b, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x04, 0xb0, 0x18, 0x47, 0x30, 0x38, 0xc4, 0xb2, 0xf3, 0xe7, -0x49, 0x1c, 0x10, 0x91, 0x08, 0x78, 0x30, 0x38, 0xc6, 0xb2, 0xed, 0xe7, 0x01, 0xcd, 0x23, 0x46, -0x0a, 0x22, 0x02, 0xa9, 0x00, 0x96, 0xff, 0xf7, 0xb7, 0xfe, 0x68, 0x46, 0x00, 0x7a, 0x00, 0x24, -0x02, 0xaf, 0x00, 0x28, 0xdd, 0xd0, 0x38, 0x78, 0xfe, 0xf7, 0x4e, 0xff, 0x78, 0x78, 0x7f, 0x1c, -0x00, 0x28, 0xf8, 0xd1, 0xd5, 0xe7, 0x01, 0xcd, 0x23, 0x46, 0x10, 0x22, 0x02, 0xa9, 0x00, 0x96, -0xff, 0xf7, 0xa2, 0xfe, 0x68, 0x46, 0x00, 0x7a, 0x00, 0x24, 0x02, 0xaf, 0x00, 0x28, 0xc8, 0xd0, -0x38, 0x78, 0xfe, 0xf7, 0x39, 0xff, 0x78, 0x78, 0x7f, 0x1c, 0x00, 0x28, 0xf8, 0xd1, 0xc0, 0xe7, -0xe8, 0x0d, 0x01, 0x20, 0xa8, 0x0d, 0x01, 0x20, 0x67, 0x42, 0x31, 0x26, 0x1f, 0x19, 0x16, 0x00, -0x01, 0x00, 0x05, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x17, 0x00, 0x1a, 0x00, -0x1e, 0x00, 0x22, 0x00, 0x26, 0x00, 0x2a, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x37, 0x00, 0x3c, 0x00, -0x40, 0x00, 0x46, 0x00, 0x4b, 0x00, 0x50, 0x00, 0x56, 0x00, 0x5d, 0x00, 0x63, 0x00, 0x6b, 0x00, -0x73, 0x00, 0x7b, 0x00, 0x84, 0x00, 0x8e, 0x00, 0x99, 0x00, 0xa6, 0x00, 0xb4, 0x00, 0xc4, 0x00, -0xd6, 0x00, 0xeb, 0x00, 0x04, 0x01, 0x22, 0x01, 0x47, 0x01, 0x75, 0x01, 0xb1, 0x01, 0x02, 0x02, -0x77, 0x02, 0x2e, 0x03, 0x77, 0x04, 0x74, 0x07, 0x60, 0x16, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, -0x09, 0x09, 0x20, 0x20, 0x12, 0x00, 0x00, 0xfb, 0x09, 0x0c, 0x01, 0x46, 0x02, 0x3c, 0x32, 0x05, -0x02, 0x64, 0x00, 0x04, 0x00, 0x00, 0x03, 0x64, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x7f, 0x36, 0x41, 0x20, 0x7f, 0x0c, 0x11, 0x0a, 0xc8, 0x00, -0x32, 0x00, 0xc8, 0x00, 0x02, 0x00, 0x14, 0x00, 0xc8, 0x00, 0x68, 0x01, 0x42, 0x00, 0x0f, 0x01, -0x0b, 0xc8, 0x00, 0xb8, 0x0b, 0x4c, 0x04, 0x0e, 0x0c, 0x07, 0x40, 0x06, 0x46, 0xd0, 0x07, 0x1e, -0x64, 0x32, 0x00, 0x0f, 0x14, 0x0e, 0xee, 0x19, 0x4e, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, -0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, -0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x7f, 0x07, 0x50, 0x00, 0x64, 0x00, 0x96, 0x00, 0x3c, 0x00, 0x28, 0x00, 0xcf, 0x02, 0x3f, 0x06, -0x00, 0x00, 0x01, 0x00, 0xff, 0x50, 0x00, 0x00, 0x2b, 0x3a, 0x00, 0x00, 0x28, 0xc8, 0x11, 0x01, -0x00, 0x64, 0x00, 0x46, 0x00, 0x0b, 0x06, 0x0a, 0x60, 0x60, 0x80, 0x60, 0x32, 0x3c, 0x3c, 0x3c, -0x34, 0x3c, 0x20, 0x00, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x00, 0x02, 0x80, 0x01, 0x05, 0x00, -0x02, 0x00, 0x01, 0x01, 0x32, 0x1e, 0x20, 0x01, 0xc4, 0xff, 0xa6, 0x00, 0x00, 0x01, 0x01, 0x3c, -0x00, 0x28, 0x00, 0x50, 0x00, 0x01, 0x3c, 0x64, 0x14, 0x00, 0xe6, 0x00, 0x14, 0x00, 0x01, 0x03, -0x05, 0x07, 0xc8, 0xc8, 0x0f, 0x01, 0x0a, 0x05, 0x07, 0x1c, 0x00, 0x1c, 0x00, 0x03, 0x78, 0x02, -0x07, 0x0c, 0x03, 0x64, 0x20, 0x03, 0x2c, 0x01, 0x00, 0xc8, 0x00, 0x02, 0x1e, 0x64, 0x00, 0x64, -0x00, 0x64, 0x00, 0x64, 0x00, 0x64, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0f, 0x00, 0x20, -0x01, 0x50, 0x03, 0x05, 0xd1, 0x00, 0x01, 0xac, 0xd0, 0x07, 0x64, 0x00, 0x04, 0x00, 0x32, 0x32, -0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, -0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x4e, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x64, 0x04, 0x05, 0x00, 0x96, 0x00, 0x1e, -0x01, 0x05, 0x01, 0x8a, 0x06, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x14, 0x14, -0x03, 0x00, 0x00, 0x00, 0x0b, 0xb0, 0xff, 0x03, 0x03, 0x08, 0x64, 0x08, 0x32, 0x00, 0x00, 0x06, -0x28, 0x00, 0x09, 0x09, 0xd0, 0x07, 0xb4, 0xc8, 0x00, 0x00, 0xc8, 0x00, 0x06, 0x0a, 0x02, 0x02, -0x02, 0x06, 0x14, 0x00, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, -0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, -0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, -0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, -0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x5f, 0x5f, 0x5f, 0x5f, -0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, -0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, -0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, -0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, -0x5f, 0x5f, 0x5f, 0x5f, 0x04, 0x0a, 0x32, 0x00, 0x32, 0x00, 0x04, 0x00, 0x01, 0x02, 0x02, 0x00, -0x01, 0x00, 0x50, 0x02, 0xaa, 0x55, 0x04, 0x01, 0x00, 0x46, 0x04, 0x08, 0x08, 0x08, 0x02, 0x08, -0x08, 0x3c, 0x04, 0x08, 0x08, 0x08, 0x02, 0x08, 0x08, 0x32, 0x04, 0x08, 0x06, 0x08, 0x02, 0x08, -0x08, 0x28, 0x03, 0x06, 0x06, 0x06, 0x02, 0x06, 0x06, 0x1e, 0x03, 0x05, 0x05, 0x05, 0x02, 0x05, -0x06, 0x14, 0x02, 0x04, 0x04, 0x04, 0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x50, 0x11, 0x22, 0x23, -0x24, 0x13, 0x14, 0x15, 0x1e, 0x1f, 0x21, 0x20, 0x25, 0x12, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, -0x1c, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, -0x02, 0x01, 0x03, 0x00, 0x03, 0x02, 0x01, 0x00, 0x02, 0x04, 0x01, 0x00, 0x03, 0x04, 0x03, 0x00, -0x04, 0x03, 0x04, 0x00, 0xd4, 0xee, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x68, 0x02, 0x00, 0x00, -0x52, 0x0d, 0x00, 0x00, 0x84, 0xef, 0x00, 0x00, 0x68, 0x02, 0x01, 0x20, 0xd8, 0x3a, 0x00, 0x00, -0x64, 0x01, 0x00, 0x00, 0x81, 0x12, 0x96, 0x14, 0x08, 0x02, 0x46, 0x02, 0x25, 0x5a, 0x05, 0x3f, -0xe0, 0xee, 0xc8, 0x03, 0x42, 0x0e, 0x25, 0x1e, 0x14, 0x05, 0x0a, 0x32, 0xb4, 0x12, 0x0c, 0x24, -0xf4, 0x01, 0x3c, 0x24, 0x64, 0x64, 0x64, 0x5c, 0x32, 0x32, 0x32, 0x0a, 0x59, 0x0f, 0x18, 0x08, -0x64, 0x2d, 0xaa, 0x3c, 0x04, 0x03, 0x02, 0x01, 0x41, 0x02, 0x1d, 0x01, 0x09, 0x1c, 0x1e, 0x09, -0x10, 0x2f, 0x04, 0x22, 0x02, 0x04, 0x08, 0x32, 0x10, 0x6b, 0x99, 0xbf, 0x33, 0x34, 0x01, 0x01, -0x81, 0x5a, 0x11, 0x14, 0x23, 0xb1, 0xc2, 0x45, 0xff, 0xfe, 0xfe, 0xfe, 0x9a, 0x30, 0x28, 0x1a, -0xff, 0x02, 0x41, 0x9a, 0x40, 0x28, 0x69, 0x15, 0xba, 0x50, 0x50, 0x21, 0x32, 0x80, 0xba, 0x51, -0x50, 0x61, 0xaa, 0x60, 0x28, 0x19, 0x2a, 0x29, 0x28, 0xaa, 0x61, 0x50, 0x59, 0x2a, 0x29, 0x18, -0x5a, 0x31, 0x28, 0x54, 0xaa, 0xaa, 0x02, 0x29, 0xa4, 0x29, 0x14, 0x1a, 0x55, 0x28, 0x1b, 0x55, -0x55, 0x65, 0x09, 0x29, 0xc8, 0x01, 0x10, 0x29, 0xb5, 0x10, 0x10, 0x60, 0x47, 0x34, 0x27, 0x1c, -0x15, 0x0f, 0x0b, 0x08, 0x06, 0x05, 0x03, 0x02, 0x02, 0x01, 0x1b, 0x01, 0xff, 0x16, 0x19, 0x07, -0x01, 0x28, 0x00, 0x00 -}; - -const static struct cts_firmware cts_driver_builtin_firmwares[] = { - { - .name = "OEM-Project", /* MUST set non-NULL */ - .hwid = CTS_DEV_HWID_ICNL9911, - .fwid = CTS_DEV_FWID_ICNL9911, - .data = icnl9911_driver_builtin_firmware, - .size = ARRAY_SIZE(icnl9911_driver_builtin_firmware), - }, -}; - +static u8 icnl9911s_driver_builtin_firmware[] = { +}; + +const static struct cts_firmware cts_driver_builtin_firmwares[] = { + { + .name = "OEM-Project", /* MUST set non-NULL */ + .hwid = CTS_DEV_HWID_ICNL9911S, + .fwid = CTS_DEV_FWID_ICNL9911S, + .data = icnl9911s_driver_builtin_firmware, + .size = ARRAY_SIZE(icnl9911s_driver_builtin_firmware), + }, +}; diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_charger_detect.c b/drivers/input/touchscreen/chipone_tddi_mmi/cts_charger_detect.c new file mode 100644 index 000000000000..b86222aa8b6a --- /dev/null +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_charger_detect.c @@ -0,0 +1,1047 @@ +#define LOG_TAG "Charger" + +#include "cts_config.h" +#include "cts_platform.h" +#include "cts_core.h" +#include "cts_sysfs.h" + +#ifdef CONFIG_CTS_CHARGER_DETECT + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0) +#define CFG_CTS_CHARGER_DETECT_PSY_NOTIFY +#endif +#define CFG_CTS_CHARGER_DETECT_PSY_POLL + +#include +#include + +enum cts_charger_detect_type { + CTS_CHGR_DET_TYPE_NONE = 0, + CTS_CHGR_DET_TYPE_PSY_NOTIFY, + CTS_CHGR_DET_TYPE_POLL_PSP, + CTS_CHGR_DET_TYPE_MAX +}; + +/* Over-written setting for DTS */ +#define CFG_CTS_DEF_CHGR_DET_ENABLE + +/* Default settings */ +#ifdef CFG_CTS_CHARGER_DETECT_PSY_NOTIFY +#define CFG_CTS_DEF_CHGR_DET_TYPE CTS_CHGR_DET_TYPE_PSY_NOTIFY +#else /* CFG_CTS_CHARGER_DETECT_PSY_NOTIFY */ +#define CFG_CTS_DEF_CHGR_DET_TYPE CTS_CHGR_DET_TYPE_POLL_PSP +#endif /* CFG_CTS_CHARGER_DETECT_PSY_NOTIFY */ + +#define CFG_CTS_DEF_CHGR_DET_PSY_NAME "usb" +#define CFG_CTS_DEF_CHGR_DET_PSY_PROP POWER_SUPPLY_PROP_PRESENT +#define CFG_CTS_DEF_CHGR_DET_PSP_POLL_INTERVAL 2000u + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0) +/* Lower version has no power_supply_get_property() */ +#define POWER_SUPPLY_GET_PROPERTY(psy, psp, val) \ + power_supply_get_property(psy, psp, val) +#else +#define POWER_SUPPLY_GET_PROPERTY(psy, psp, val) \ + psy->get_property(psy, psp, val) +#endif + +struct cts_charger_detect_data { + bool enable; + bool running; + bool charger_attached; + + /* Parameter */ + enum cts_charger_detect_type type; + const char *psy_name; + enum power_supply_property psp; + u32 psp_poll_interval; /* Unit is ms */ + + /* Power supply notify */ +#ifdef CFG_CTS_CHARGER_DETECT_PSY_NOTIFY + bool notifier_registered; + struct notifier_block psy_notifier; +#endif /* CFG_CTS_CHARGER_DETECT_PSY_NOTIFY */ + +#ifdef CFG_CTS_CHARGER_DETECT_PSY_POLL + /* Polling power supply property */ + struct delayed_work psp_poll_work; +#endif /* CFG_CTS_CHARGER_DETECT_PSY_POLL */ + + struct work_struct set_charger_state_work; + + /* Sysfs */ + bool sysfs_created; + + struct chipone_ts_data *cts_data; + +}; + +#define POWER_SUPPLY_PROP_PREFIX "POWER_SUPPLY_PROP_" +#define POWER_SUPPLY_PROP_TOKEN(property) \ + {.prop = POWER_SUPPLY_PROP_ ##property, \ + .name = POWER_SUPPLY_PROP_PREFIX #property} + +const static struct { + enum power_supply_property prop; + const char *name; +} power_supply_prop_token [] = { + POWER_SUPPLY_PROP_TOKEN(STATUS), + POWER_SUPPLY_PROP_TOKEN(PRESENT), + POWER_SUPPLY_PROP_TOKEN(ONLINE), +}; + +static const char *power_supply_prop_str(enum power_supply_property prop) +{ + int i; + + for (i = 0; i < sizeof(power_supply_prop_token); i++) { + if (prop == power_supply_prop_token[i].prop) { + return power_supply_prop_token[i].name; + } + } + + return "Unknown"; +} + +static enum power_supply_property power_supply_prop_from_name(const char *name) +{ + size_t offset = strlen(POWER_SUPPLY_PROP_PREFIX); + int i; + + for (i = 0; i < ARRAY_SIZE(power_supply_prop_token); i++) { + if (strcasecmp(power_supply_prop_token[i].name + offset, name) == 0 || + strcasecmp(power_supply_prop_token[i].name, name) == 0) { + return power_supply_prop_token[i].prop; + } + } + + return -ENOENT; +} + +static const char *charger_detect_type_text[] = { + "none", "notify", "poll", +}; + +static const char *charger_detect_type_str(enum cts_charger_detect_type type) +{ + return type < ARRAY_SIZE(charger_detect_type_text) ? + charger_detect_type_text[type] : "Unknown"; +} + +static int parse_charger_detect_dt(struct cts_charger_detect_data *cd_data, + struct device_node *np) +{ + const char *psy_name; + const char *type_str; + const char *psp_str; + int ret; + + cts_info("Parse charger detect dt"); + +#ifdef CFG_CTS_DEF_CHGR_DET_ENABLE + cd_data->enable = true; +#else /* CFG_CTS_DEF_CHGR_DET_ENABLE */ + cd_data->enable = + of_property_read_bool(np, "chipone-ts,charger-detect-enable"); +#endif /* CFG_CTS_DEF_CHGR_DET_ENABLE */ + + cd_data->type = CFG_CTS_DEF_CHGR_DET_TYPE; + ret = of_property_read_string(np, + "chipone-ts,charger-detect-type", &type_str); + if (ret) { + cts_warn("Parse charger detect type failed %d", ret); + } else { + int type = match_string(charger_detect_type_text, + ARRAY_SIZE(charger_detect_type_text), type_str); + if (type < 0) { + cts_err("Parse charger detect type '%s' invalid", type_str); + } else { + cd_data->type = type; + } + } + + ret = of_property_read_string(np, + "chipone-ts,charger-detect-psy-name", &psy_name); + if (ret) { + cts_warn("Parse charger detect psy name failed %d", ret); + psy_name = CFG_CTS_DEF_CHGR_DET_PSY_NAME; + } else { + if (power_supply_get_by_name(psy_name) == NULL) { + cts_warn("Power supply '%s' not found", psy_name); + psy_name = CFG_CTS_DEF_CHGR_DET_PSY_NAME; + } + } + cd_data->psy_name = kstrdup(psy_name, GFP_KERNEL); + if (cd_data->psy_name == NULL) { + cts_err("Alloc mem for psy name failed"); + return -ENOMEM; + } + + cd_data->psp = CFG_CTS_DEF_CHGR_DET_PSY_PROP; + ret = of_property_read_string(np, + "chipone-ts,charger-detect-psp", &psp_str); + if (ret) { + cts_warn("Parse charger detect psp failed %d", ret); + } else { + struct power_supply *psy; + enum power_supply_property psp; + union power_supply_propval val; + + psp = power_supply_prop_from_name(psp_str); + if (psp < 0) { + cts_warn("Parse charger detect psp: '%s' invalid", + psp_str); + } else { + psy = power_supply_get_by_name(cd_data->psy_name); + if (psy != NULL && + POWER_SUPPLY_GET_PROPERTY(psy, psp, &val) >=0) { + cts_err("Parse charger detect psp invalid"); + } else { + cd_data->psp = psp; + } + } + } + + cd_data->psp_poll_interval = CFG_CTS_DEF_CHGR_DET_PSP_POLL_INTERVAL; + ret = of_property_read_u32(np, + "chipone-ts,charger-detect-psp-poll-interval", + &cd_data->psp_poll_interval); + if (ret) { + cts_warn("Parse charger detect psp poll interval failed %d", ret); + } + + cts_info("Charger Detect: %sABLED", cd_data->enable ? "EN" : "DIS"); + cts_info(" Type : %s", charger_detect_type_str(cd_data->type)); + cts_info(" PSY Name: %s, prop: %d(%s)", cd_data->psy_name, + cd_data->psp, power_supply_prop_str(cd_data->psp)); + cts_info(" Poll Int: %dms", cd_data->psp_poll_interval); + + return 0; +} + +static int start_charger_detect(struct cts_charger_detect_data *cd_data) +{ + cts_info("Start charger detect type: %d(%s)", + cd_data->type, charger_detect_type_str(cd_data->type)); + + if (!cd_data->enable) { + cts_warn("Start charger detect while NOT enabled"); + return 0; + } + + if (cd_data->running) { + cts_warn("Start charger detect while already RUNNING"); + return 0; + } + +#ifdef CFG_CTS_CHARGER_DETECT_PSY_NOTIFY + if(cd_data->type == CTS_CHGR_DET_TYPE_PSY_NOTIFY) { + int ret = power_supply_reg_notifier(&cd_data->psy_notifier); + if (ret) { + cts_err("Register charger detect notifier failed: %d", ret); + return ret; + } + cd_data->notifier_registered = true; + + cd_data->running = true; + + return 0; + } +#endif /* CFG_CTS_CHARGER_DETECT_PSY_NOTIFY */ + +#ifdef CFG_CTS_CHARGER_DETECT_PSY_POLL + if(cd_data->type == CTS_CHGR_DET_TYPE_POLL_PSP) { + if (!queue_delayed_work(cd_data->cts_data->workqueue, + &cd_data->psp_poll_work, + msecs_to_jiffies(cd_data->psp_poll_interval))) { + cts_warn("Queue charger detect work while already on the queue"); + } + cd_data->running = true; + + return 0; + } +#endif /* CFG_CTS_CHARGER_DETECT_PSY_POLL */ + + return -ENOTSUPP; +} + +static int stop_charger_detect(struct cts_charger_detect_data *cd_data) +{ + cts_info("Stop charger detect type: %d(%s)", + cd_data->type, charger_detect_type_str(cd_data->type)); + + if (!cd_data->running) { + cts_warn("Stop charger detect while NOT running"); + return 0; + } + +#ifdef CFG_CTS_CHARGER_DETECT_PSY_NOTIFY + if(cd_data->type == CTS_CHGR_DET_TYPE_PSY_NOTIFY) { + if (cd_data->notifier_registered) { + power_supply_unreg_notifier(&cd_data->psy_notifier); + cd_data->notifier_registered = false; + } + cd_data->running = false; + + return 0; + } +#endif /* CFG_CTS_CHARGER_DETECT_PSY_NOTIFY */ + +#ifdef CFG_CTS_CHARGER_DETECT_PSY_POLL + if(cd_data->type == CTS_CHGR_DET_TYPE_POLL_PSP) { + if (!cancel_delayed_work_sync(&cd_data->psp_poll_work)) { + cts_warn("PSY poll prop work is NOT pending"); + } + cd_data->running = false; + + return 0; + } +#endif /* CFG_CTS_CHARGER_DETECT_PSY_POLL */ + + return 0; +} + +static int enable_charger_detect(struct cts_charger_detect_data *cd_data) +{ + cts_info("Enable charger detect type: %d(%s)", + cd_data->type, charger_detect_type_str(cd_data->type)); + + cd_data->enable = true; + + return 0; +} + +static int disable_charger_detect(struct cts_charger_detect_data *cd_data) +{ + int ret; + + cts_info("Disable charger detect type: %d(%s)", + cd_data->type, charger_detect_type_str(cd_data->type)); + + ret = stop_charger_detect(cd_data); + if (ret) { + cts_err("Disable charger detect failed %d", ret); + } + + cd_data->enable = false; + + return 0; +} + +static int get_charger_state(struct cts_charger_detect_data *cd_data) +{ + struct power_supply *psy; + union power_supply_propval propval; + int ret; + + cts_dbg("Get charger state from psy: '%s' prop: %d(%s)", + cd_data->psy_name, cd_data->psp, + power_supply_prop_str(cd_data->psp)); + + if (cd_data->psy_name == NULL || + (psy = power_supply_get_by_name(cd_data->psy_name)) == NULL) { + cts_err("Get charger state from psy: '%s' not found", + cd_data->psy_name); + return -EINVAL; + } + + ret = POWER_SUPPLY_GET_PROPERTY(psy, cd_data->psp, &propval); + if (ret < 0) { + cts_err("Get charger state from psy: '%s' prop: %d(%s) failed", + cd_data->psy_name, cd_data->psp, + power_supply_prop_str(cd_data->psp)); + return -EINVAL; + } + + /* ONLY for bool type */ + cd_data->charger_attached = !!propval.intval; + + cts_dbg("Charger state: %s", + cd_data->charger_attached ? "ATTACHED" : "DETACHED"); + + return 0; +} + +static int switch_charger_detect_type(struct cts_charger_detect_data *cd_data, + enum cts_charger_detect_type type) +{ + bool running; + + cts_info("Switch charger detect type to %d(%s)", + type, charger_detect_type_str(type)); + + if (type >= CTS_CHGR_DET_TYPE_MAX) { + cts_err("Switch charger detect type %d invalid", type); + return -EINVAL; + } + + if (cd_data->type == type) { + cts_warn("Switch charger detect type equal"); + return 0; + } + + running = cd_data->running; + + if (running) { + int ret = stop_charger_detect(cd_data); + if (ret) { + cts_err("Stop charger detect failed %d", ret); + return ret; + } + } + + cd_data->type = type; + + if (running) { + int ret = start_charger_detect(cd_data); + if (ret) { + cts_err("Start charger detect failed %d", ret); + cd_data->type = CTS_CHGR_DET_TYPE_NONE; + return ret; + } + } + + return 0; +} + +static void set_dev_charger_state_work(struct work_struct *work) +{ + struct cts_charger_detect_data *cd_data; + + cd_data = container_of(work, struct cts_charger_detect_data, + set_charger_state_work); + + if (get_charger_state(cd_data)) { + cts_err("Check charger attached failed"); + return; + } + + cts_lock_device(&cd_data->cts_data->cts_dev); + + if (cd_data->charger_attached) { + cts_charger_plugin(&cd_data->cts_data->cts_dev); + } else { + cts_charger_plugout(&cd_data->cts_data->cts_dev); + } + cts_unlock_device(&cd_data->cts_data->cts_dev); +} + +#ifdef CFG_CTS_CHARGER_DETECT_PSY_NOTIFY +static int psy_notify_callback(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct cts_charger_detect_data *cd_data; + int ret; + + if (nb == NULL) { + cts_err("PSY notify callback with notifier_block = NULL"); + return NOTIFY_DONE; + } + + if (action != PSY_EVENT_PROP_CHANGED) { + cts_dbg("PSY notify event %ld not care", action); + return NOTIFY_DONE; + } + + cd_data = container_of(nb, struct cts_charger_detect_data, psy_notifier); + + ret = get_charger_state(cd_data); + if (ret < 0) { + cts_err("Get charger state failed %d", ret); + return NOTIFY_DONE; + } + + if (!queue_work(cd_data->cts_data->workqueue, + &cd_data->set_charger_state_work)) { + cts_warn("Set device charger state work is PENDING"); + } + + return NOTIFY_OK; +} +#endif /* CFG_CTS_CHARGER_DETECT_PSY_NOTIFY */ + +#ifdef CFG_CTS_CHARGER_DETECT_PSY_POLL +static void poll_psp_work(struct work_struct *work) +{ + struct cts_charger_detect_data *cd_data; + bool last_attached; + int ret; + + cts_dbg("Poll psp work"); + + cd_data = container_of(work, struct cts_charger_detect_data, + psp_poll_work.work); + + last_attached = cd_data->charger_attached; + + ret = get_charger_state(cd_data); + if (ret < 0) { + cts_err("Get charger state failed %d", ret); + } + + if (cd_data->charger_attached != last_attached) { + cts_info("Charger state changed: %s -> %s", + last_attached ? "ATTACHED" : "DETACHED", + cd_data->charger_attached ? "ATTACHED" : "DETACHED"); + + if (!queue_work(cd_data->cts_data->workqueue, + &cd_data->set_charger_state_work)) { + cts_warn("Set device charger state work is PENDING"); + } + } + + if (!queue_delayed_work(cd_data->cts_data->workqueue, + &cd_data->psp_poll_work, + msecs_to_jiffies(cd_data->psp_poll_interval))) { + cts_warn("Queue charger detech work while already on the queue"); + } +} +#endif /* CFG_CTS_CHARGER_DETECT_PSY_POLL */ + +static int init_charger_detect(struct cts_charger_detect_data *cd_data) +{ + int ret; + +#ifdef CFG_CTS_CHARGER_DETECT_PSY_NOTIFY + cd_data->psy_notifier.notifier_call = psy_notify_callback; +#endif /* CFG_CTS_CHARGER_DETECT_PSY_NOTIFY */ + +#ifdef CFG_CTS_CHARGER_DETECT_PSY_POLL + INIT_DELAYED_WORK(&cd_data->psp_poll_work, poll_psp_work); +#endif /* CFG_CTS_CHARGER_DETECT_PSY_POLL */ + + INIT_WORK(&cd_data->set_charger_state_work, set_dev_charger_state_work); + + ret = get_charger_state(cd_data); + if (ret) { + cts_err("Get charger state failed %d", ret); + } + + return 0; +} + +/* Sysfs */ +#ifdef CONFIG_CTS_SYSFS +extern int argc; +extern char *argv[]; +extern int parse_arg(const char *buf, size_t count); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) +/* From lib/kstrtox.c */ +/** + * kstrtobool - convert common user inputs into boolean values + * @s: input string + * @res: result + * + * This routine returns 0 iff the first character is one of 'Yy1Nn0', or + * [oO][NnFf] for "on" and "off". Otherwise it will return -EINVAL. Value + * pointed to by res is updated upon finding a match. + */ +int kstrtobool(const char *s, bool *res) +{ + if (!s) + return -EINVAL; + + switch (s[0]) { + case 'y': + case 'Y': + case '1': + *res = true; + return 0; + case 'n': + case 'N': + case '0': + *res = false; + return 0; + case 'o': + case 'O': + switch (s[1]) { + case 'n': + case 'N': + *res = true; + return 0; + case 'f': + case 'F': + *res = false; + return 0; + default: + break; + } + default: + break; + } + + return -EINVAL; +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) +/** + * match_string - matches given string in an array + * @array: array of strings + * @n: number of strings in the array or -1 for NULL terminated arrays + * @string: string to match with + * + * Return: + * index of a @string in the @array if matches, or %-EINVAL otherwise. + */ +int match_string(const char * const *array, size_t n, const char *string) +{ + int index; + const char *item; + + for (index = 0; index < n; index++) { + item = array[index]; + if (!item) + break; + if (!strcmp(item, string)) + return index; + } + + return -EINVAL; +} +#endif + +#define CHARGER_DET_SYSFS_GROUP_NAME "charger-det" + +static ssize_t charger_detect_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_charger_detect_data *cd_data = cts_data->cd_data; + + cts_info("Read sysfs '"CHARGER_DET_SYSFS_GROUP_NAME"/%s'", + attr->attr.name); + + return scnprintf(buf, PAGE_SIZE, + "Charger detect: %s\n", + cd_data->enable ? "ENABLED" : "DISABLED"); +} + +/* Echo 0/n/N/of/Of/Of/OF/1/y/Y/on/oN/On/ON > enable */ +static ssize_t charger_detect_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_charger_detect_data *cd_data = cts_data->cd_data; + bool enable; + int ret; + + cts_info("Write sysfs '"CHARGER_DET_SYSFS_GROUP_NAME"/%s' size %zu", + attr->attr.name, count); + + parse_arg(buf, count); + + if (argc != 1) { + cts_err("Invalid num of args"); + return -EINVAL; + } + + ret = kstrtobool(argv[0], &enable); + if (ret) { + cts_err("Invalid param of enable"); + return ret; + } + + if (enable) { + ret = enable_charger_detect(cd_data); + } else { + ret = disable_charger_detect(cd_data); + } + if (ret) { + cts_err("%s charger detect failed %d", + enable ? "Enable" : "Disable", ret); + return ret; + } + + return count; +} +static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, + charger_detect_enable_show, charger_detect_enable_store); + +static ssize_t charger_detect_running_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_charger_detect_data *cd_data = cts_data->cd_data; + + cts_info("Read sysfs '"CHARGER_DET_SYSFS_GROUP_NAME"/%s'", + attr->attr.name); + + return scnprintf(buf, PAGE_SIZE, + "Charger detect: %sRunning\n", + cd_data->running ? "" : "Not-"); +} + +/* Echo 0/n/N/of/Of/Of/OF/1/y/Y/on/oN/On/ON > runing */ +static ssize_t charger_detect_running_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_charger_detect_data *cd_data = cts_data->cd_data; + bool running; + int ret; + + cts_info("Write sysfs '"CHARGER_DET_SYSFS_GROUP_NAME"/%s' size %zu", + attr->attr.name, count); + + parse_arg(buf, count); + + if (argc != 1) { + cts_err("Invalid num of args"); + return -EINVAL; + } + + ret = kstrtobool(argv[0], &running); + if (ret) { + cts_err("Invalid param of running"); + return ret; + } + + if (running) { + ret = start_charger_detect(cd_data); + } else { + ret = stop_charger_detect(cd_data); + } + if (ret) { + cts_err("%s charger detect failed %d", + running ? "Start" : "Stop", ret); + return ret; + } + + return count; +} +static DEVICE_ATTR(running, S_IWUSR | S_IRUGO, + charger_detect_running_show, charger_detect_running_store); + +static ssize_t charger_detect_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_charger_detect_data *cd_data = cts_data->cd_data; + + cts_info("Read sysfs '"CHARGER_DET_SYSFS_GROUP_NAME"/%s'", + attr->attr.name); + + return scnprintf(buf, PAGE_SIZE, + "Charger detect type: %d(%s)\n", + cd_data->type, charger_detect_type_str(cd_data->type)); +} + +/* echo charger_detect_type > type */ +static ssize_t charger_detect_type_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_charger_detect_data *cd_data = cts_data->cd_data; + int type, ret; + + cts_info("Write sysfs '"CHARGER_DET_SYSFS_GROUP_NAME"/%s' size %zu", + attr->attr.name, count); + + parse_arg(buf, count); + + if (argc != 1) { + cts_err(""); + return -EINVAL; + } + + type = match_string(charger_detect_type_text, + ARRAY_SIZE(charger_detect_type_text), argv[0]); + if (type < 0) { + cts_err("Invalid charger detect type: '%s'", argv[0]); + return -EINVAL; + } + + ret = switch_charger_detect_type(cd_data, type); + if (ret) { + cts_err("Switch charger detect type failed %d", ret); + return ret; + } + + return count; +} +static DEVICE_ATTR(type, S_IWUSR | S_IRUGO, + charger_detect_type_show, charger_detect_type_store); + +static ssize_t charger_attached_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_charger_detect_data *cd_data = cts_data->cd_data; + int ret; + + cts_info("Read sysfs '"CHARGER_DET_SYSFS_GROUP_NAME"/%s'", + attr->attr.name); + + ret = get_charger_state(cd_data); + if (ret) { + return scnprintf(buf, PAGE_SIZE, + "Get charge state failed %d\n", ret); + } + + return scnprintf(buf, PAGE_SIZE, + "Charger: %s\n", + cd_data->charger_attached ? "ATTACHED" : "DETACHED"); +} +static DEVICE_ATTR(attached, S_IRUGO, charger_attached_show, NULL); + +static ssize_t charger_detect_param_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_charger_detect_data *cd_data = cts_data->cd_data; + struct power_supply *psy; + + cts_info("Read sysfs '"CHARGER_DET_SYSFS_GROUP_NAME"/%s'", + attr->attr.name); + + psy = power_supply_get_by_name(cd_data->psy_name); + + return scnprintf(buf, PAGE_SIZE, + "Power supply name: %s(%sExist)\n" + "Power supply prop: %d(%s)\n" + "Poll interval : %dms\n", + cd_data->psy_name, psy == NULL ? "Non-" : "", + cd_data->psp, power_supply_prop_str(cd_data->psp), + cd_data->psp_poll_interval); +} + +/* echo psy_name psy_property [interval] > param */ +static ssize_t charger_detect_param_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_charger_detect_data *cd_data = cts_data->cd_data; + struct power_supply *psy; + union power_supply_propval propval; + enum power_supply_property psp; + int ret; + + cts_info("Write sysfs '"CHARGER_DET_SYSFS_GROUP_NAME"/%s' size %zu", + attr->attr.name, count); + + parse_arg(buf, count); + + if (argc < 2 || argc > 3) { + cts_err("Invalid num of args"); + return -EINVAL; + } + + if ((psy = power_supply_get_by_name(argv[0])) == NULL) { + cts_err("Power supply '%s' not found", argv[0]); + return -EINVAL; + } + + psp = power_supply_prop_from_name(argv[1]); + if (psp < 0 || + POWER_SUPPLY_GET_PROPERTY(psy, psp, &propval) < 0) { + cts_err("Power supply '%s' property '%s' not valid", + argv[0], power_supply_prop_str(psp)); + return -EINVAL; + } + + if (argc > 2) { + int interval; + + ret = kstrtoint(argv[2], 0, &interval); + if (ret) { + cts_err("Arg interval is invalid"); + return -EINVAL; + } + cd_data->psp_poll_interval = interval; + } + + if (cd_data->psy_name) { + kfree(cd_data->psy_name); + } + cd_data->psy_name = kstrdup(argv[0], GFP_KERNEL); + if (cd_data->psy_name == NULL) { + cts_err("Alloc psy name failed"); + return -ENOMEM; + } + + cd_data->psp = psp; + + return count; +} +static DEVICE_ATTR(param, S_IWUSR | S_IRUGO, + charger_detect_param_show, charger_detect_param_store); + +static struct attribute *charger_detect_attrs[] = { + &dev_attr_enable.attr, + &dev_attr_running.attr, + &dev_attr_type.attr, + &dev_attr_attached.attr, + &dev_attr_param.attr, + NULL +}; + +static const struct attribute_group charger_detect_attr_group = { + .name = CHARGER_DET_SYSFS_GROUP_NAME, + .attrs = charger_detect_attrs, +}; +#endif /* CONFIG_CTS_SYSFS */ + +int cts_charger_detect_init(struct chipone_ts_data *cts_data) +{ + struct cts_charger_detect_data *cd_data; + int ret; + + cts_info("Charger detect init"); + + if (cts_data == NULL) { + cts_err("Init charger detect while cts_data = NULL"); + return -EFAULT; + } + + cd_data = kzalloc(sizeof(*cd_data), GFP_KERNEL); + if (cd_data == NULL) { + cts_err("Alloc charger detect data failed"); + return -ENOMEM; + } + + parse_charger_detect_dt(cd_data, cts_data->device->of_node); + + ret = init_charger_detect(cd_data); + if (ret) { + cts_err("Init charger detect failed %d", ret); + goto free_cd_data; + } + +#ifdef CONFIG_CTS_SYSFS + ret = sysfs_create_group(&cts_data->device->kobj, + &charger_detect_attr_group); + if (ret) { + cts_warn("Create sysfs files failed %d", ret); + } else { + cd_data->sysfs_created = true; + } +#endif /* CONFIG_CTS_SYSFS */ + + cts_data->cd_data = cd_data; + cd_data->cts_data = cts_data; + + return 0; + +free_cd_data: + kfree(cd_data); + return ret; +} + +int cts_charger_detect_deinit(struct chipone_ts_data *cts_data) +{ + struct cts_charger_detect_data *cd_data; + int ret; + + cts_info("Charger detect deinit"); + + if (cts_data == NULL) { + cts_err("Deinit charger detect while cts_data = NULL"); + return -EFAULT; + } + + cd_data = cts_data->cd_data; + if (cd_data == NULL) { + cts_warn("Deinit charger detect cd_data = NULL"); + return 0; + } + + if (cd_data->running) { + ret = stop_charger_detect(cd_data); + if (ret) { + cts_err("Disable charger detect failed %d", ret); + } + } + +#ifdef CONFIG_CTS_SYSFS + if (cd_data->sysfs_created) { + cts_info("Remove sysfs group"); + sysfs_remove_group(&cts_data->device->kobj, + &charger_detect_attr_group); + cd_data->sysfs_created = false; + } +#endif /* CONFIG_CTS_SYSFS */ + + if (cd_data->psy_name) { + kfree(cd_data->psy_name); + cd_data->psy_name = NULL; + } + + kfree(cd_data); + cts_data->cd_data = NULL; + + return 0; +} + +int cts_is_charger_attached(struct chipone_ts_data *cts_data, bool *attached) +{ + struct cts_charger_detect_data *cd_data; + int ret; + + if (cts_data == NULL) { + cts_err("Check charger attached while cts_data = NULL"); + return -EFAULT; + } + + cd_data = cts_data->cd_data; + if (cd_data == NULL) { + cts_err("Check charger attached while cd_data = NULL"); + return -ENODEV; + } + + cts_info("Check charger attached using type %d(%s) param", + cd_data->type, charger_detect_type_str(cd_data->type)); + + ret = get_charger_state(cd_data); + if (ret) { + cts_err("Check charger attached failed %d", ret); + return ret; + } + + *attached = cd_data->charger_attached; + + return 0; +} + +int cts_start_charger_detect(struct chipone_ts_data *cts_data) +{ + struct cts_charger_detect_data *cd_data; + + cts_info("Start charger detect"); + + if (cts_data == NULL) { + cts_err("Start charger detect while cts_data = NULL"); + return -EFAULT; + } + + cd_data = cts_data->cd_data; + if (cd_data == NULL) { + cts_err("Start charger detect while cd_data = NULL"); + return -ENODEV; + } + + return start_charger_detect(cd_data); +} + +int cts_stop_charger_detect(struct chipone_ts_data *cts_data) +{ + struct cts_charger_detect_data *cd_data; + + cts_info("Stop charger detect"); + + if (cts_data == NULL) { + cts_err("Stop charger detect while cts_data = NULL"); + return -EFAULT; + } + + cd_data = cts_data->cd_data; + if (cd_data == NULL) { + cts_err("Stop charger detect while cd_data = NULL"); + return -ENODEV; + } + + return stop_charger_detect(cd_data); +} +#endif /* CONFIG_CTS_CHARGER_DETECT */ + diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_charger_detect.h b/drivers/input/touchscreen/chipone_tddi_mmi/cts_charger_detect.h new file mode 100644 index 000000000000..5eb27679cf85 --- /dev/null +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_charger_detect.h @@ -0,0 +1,40 @@ +#ifndef CTS_CHARGER_DETECT_H +#define CTS_CHARGER_DETECT_H + +#include "cts_config.h" + +struct chipone_ts_data; + +#ifdef CONFIG_CTS_CHARGER_DETECT +extern int cts_charger_detect_init(struct chipone_ts_data *cts_data); +extern int cts_charger_detect_deinit(struct chipone_ts_data *cts_data); +extern int cts_start_charger_detect(struct chipone_ts_data *cts_data); +extern int cts_stop_charger_detect(struct chipone_ts_data *cts_data); +extern int cts_is_charger_attached(struct chipone_ts_data *cts_data, + bool *attached); +#else /* CONFIG_CTS_CHARGER_DETECT */ +static inline int cts_charger_detect_init(struct chipone_ts_data *cts_data) +{ + return -ENOTSUPP; +} +static inline int cts_charger_detect_deinit(struct chipone_ts_data *cts_data) +{ + return -ENOTSUPP; +} +static inline int cts_start_charger_detect(struct chipone_ts_data *cts_data) +{ + return -ENODEV; +} +static inline int cts_stop_charger_detect(struct chipone_ts_data *cts_data) +{ + return -ENODEV; +} +static inline int cts_is_charger_attached(struct chipone_ts_data *cts_data, + bool *attached) +{ + return -ENODEV; +} +#endif /*CONFIG_CTS_CHARGER_DETECT */ + +#endif /* CTS_CHARGER_DETECT_H */ + diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_config.h b/drivers/input/touchscreen/chipone_tddi_mmi/cts_config.h old mode 100755 new mode 100644 index c7166030e891..520791333737 --- a/drivers/input/touchscreen/chipone_tddi_mmi/cts_config.h +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_config.h @@ -4,9 +4,9 @@ /** Driver version */ #define CFG_CTS_DRIVER_MAJOR_VERSION 1 #define CFG_CTS_DRIVER_MINOR_VERSION 2 -#define CFG_CTS_DRIVER_PATCH_VERSION 5 +#define CFG_CTS_DRIVER_PATCH_VERSION 7 -#define CFG_CTS_DRIVER_VERSION "v1.2.5" +#define CFG_CTS_DRIVER_VERSION "v1.2.7" /** Whether reset pin is used */ #define CFG_CTS_HAS_RESET_PIN @@ -18,44 +18,54 @@ #define CFG_CTS_HAS_RESET_PIN #endif -#define CFG_CTS_SPI_SPEED_KHZ 4000 +#define CFG_CTS_SPI_SPEED_KHZ 6000 #endif -//#define CFG_CTS_FORCE_UP - +#define CFG_CTS_FORCE_UP +#define CONFIG_GENERIC_HARDIRQS //#define CFG_CTS_FW_LOG_REDIRECT /** Whether force download firmware to chip */ //#define CFG_CTS_FIRMWARE_FORCE_UPDATE /** Use build in firmware or firmware file in fs*/ -#define CFG_CTS_DRIVER_BUILTIN_FIRMWARE -#define CFG_CTS_KERNEL_BUILTIN_FIRMWARE +//#define CFG_CTS_DRIVER_BUILTIN_FIRMWARE #define CFG_CTS_FIRMWARE_IN_FS #ifdef CFG_CTS_FIRMWARE_IN_FS - #define CFG_CTS_FIRMWARE_FILENAME "ICNL9911.bin" - #define CFG_CTS_FIRMWARE_FILEPATH "/vendor/firmware/ICNL9911.bin" +//#define CFG_CTS_FW_UPDATE_SYS // Add FW custom process. +//#define CFG_CTS_FW_UPDATE_FILE_LOAD // Load config fw bin as default. +#ifdef CFG_CTS_FW_UPDATE_FILE_LOAD +#define CFG_CTS_FW_FILE_NAME_MAX_LEN 128 +#define CFG_CTS_FW_FILE_PATH "/vendor/firmware/" +#define CFG_CTS_FW_FILE_NAME_VENDOR "chipone" +#endif /*CFG_CTS_FW_UPDATE_FILE_LOAD*/ + +#define CFG_CTS_FIRMWARE_FILENAME "ICNL9911.bin" +#define CFG_CTS_FIRMWARE_FILEPATH "/vendor/firmware/ICNL9911.bin" #endif /* CFG_CTS_FIRMWARE_IN_FS */ +/* IC type support */ +#define CFG_CTS_CHIP_NAME "ICNL9911S" + #ifdef CONFIG_PROC_FS /* Proc FS for backward compatibility for APK tool com.ICN85xx */ - #define CONFIG_CTS_LEGACY_TOOL +#define CONFIG_CTS_LEGACY_TOOL #endif /* CONFIG_PROC_FS */ #ifdef CONFIG_SYSFS /* Sys FS for gesture report, debug feature etc. */ -// #define CONFIG_CTS_SYSFS +#define CONFIG_CTS_SYSFS #endif /* CONFIG_SYSFS */ -#define CFG_CTS_MAX_TOUCH_NUM (5) +#define CFG_CTS_MAX_TOUCH_NUM (10) // 5 /* Virtual key support */ //#define CONFIG_CTS_VIRTUALKEY #ifdef CONFIG_CTS_VIRTUALKEY - #define CFG_CTS_MAX_VKEY_NUM (4) - #define CFG_CTS_NUM_VKEY (3) - #define CFG_CTS_VKEY_KEYCODES {KEY_BACK, KEY_HOME, KEY_MENU} +#define CFG_CTS_MAX_VKEY_NUM (4) +#define CFG_CTS_NUM_VKEY (3) +#define CFG_CTS_VKEY_KEYCODES {KEY_BACK, KEY_HOME, KEY_MENU} #endif /* CONFIG_CTS_VIRTUALKEY */ /* Gesture wakeup */ @@ -75,42 +85,42 @@ #define GESTURE_LEFT 0x23 #define GESTURE_RIGHT 0x24 - #define CFG_CTS_NUM_GESTURE (13u) - #define CFG_CTS_GESTURE_REPORT_KEY - #define CFG_CTS_GESTURE_KEYMAP \ - {{GESTURE_C, KEY_C,}, \ - {GESTURE_W, KEY_W,}, \ - {GESTURE_V, KEY_V,}, \ - {GESTURE_D_TAP, KEY_F1,}, \ - {GESTURE_Z, KEY_Z,}, \ - {GESTURE_M, KEY_M,}, \ - {GESTURE_O, KEY_O,}, \ - {GESTURE_E, KEY_E,}, \ - {GESTURE_S, KEY_S,}, \ - {GESTURE_UP, KEY_UP,}, \ - {GESTURE_DOWN, KEY_DOWN,}, \ - {GESTURE_LEFT, KEY_LEFT,}, \ - {GESTURE_RIGHT, KEY_RIGHT,}, \ - } - #define CFG_CTS_GESTURE_REPORT_TRACE 0 +#define CFG_CTS_NUM_GESTURE (13u) +#define CFG_CTS_GESTURE_REPORT_KEY +#define CFG_CTS_GESTURE_KEYMAP \ + {{GESTURE_C, KEY_C,}, \ + {GESTURE_W, KEY_W,}, \ + {GESTURE_V, KEY_V,}, \ + {GESTURE_D_TAP, KEY_F1,}, \ + {GESTURE_Z, KEY_Z,}, \ + {GESTURE_M, KEY_M,}, \ + {GESTURE_O, KEY_O,}, \ + {GESTURE_E, KEY_E,}, \ + {GESTURE_S, KEY_S,}, \ + {GESTURE_UP, KEY_UP,}, \ + {GESTURE_DOWN, KEY_DOWN,}, \ + {GESTURE_LEFT, KEY_LEFT,}, \ + {GESTURE_RIGHT, KEY_RIGHT,}, \ + } +#define CFG_CTS_GESTURE_REPORT_TRACE 0 #endif /* CFG_CTS_GESTURE */ //#define CONFIG_CTS_GLOVE -//#define CONFIG_CTS_CHARGER_DETECT +#define CONFIG_CTS_CHARGER_DETECT /* ESD protection */ //#define CONFIG_CTS_ESD_PROTECTION #ifdef CONFIG_CTS_ESD_PROTECTION - #define CFG_CTS_ESD_PROTECTION_CHECK_PERIOD (2 * HZ) - #define CFG_CTS_ESD_FAILED_CONFIRM_CNT 3 +#define CFG_CTS_ESD_PROTECTION_CHECK_PERIOD (2 * HZ) +#define CFG_CTS_ESD_FAILED_CONFIRM_CNT 3 #endif /* CONFIG_CTS_ESD_PROTECTION */ /* Use slot protocol (protocol B), comment it if use protocol A. */ #define CONFIG_CTS_SLOTPROTOCOL #ifdef CONFIG_CTS_LEGACY_TOOL - #define CFG_CTS_TOOL_PROC_FILENAME "icn85xx_tool" +#define CFG_CTS_TOOL_PROC_FILENAME "icn85xx_tool" #endif /* CONFIG_CTS_LEGACY_TOOL */ #define CFG_CTS_UPDATE_CRCCHECK @@ -121,4 +131,3 @@ #include "cts_plat_qcom_config.h" #endif /* CTS_CONFIG_H */ - diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_core.c b/drivers/input/touchscreen/chipone_tddi_mmi/cts_core.c old mode 100755 new mode 100644 index 53322f8b1ab4..95b4f7792ee5 --- a/drivers/input/touchscreen/chipone_tddi_mmi/cts_core.c +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_core.c @@ -5,1336 +5,1448 @@ #include "cts_core.h" #include "cts_sfctrl.h" #include "cts_spi_flash.h" +#include "cts_sysfs.h" #include "cts_firmware.h" +#include "cts_charger_detect.h" #ifdef CONFIG_CTS_I2C_HOST static int cts_i2c_writeb(const struct cts_device *cts_dev, - u32 addr, u8 b, int retry, int delay) + u32 addr, u8 b, int retry, int delay) { - u8 buff[8]; + u8 buff[8]; - cts_dbg("Write to slave_addr: 0x%02x reg: 0x%0*x val: 0x%02x", - cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, addr, b); + cts_dbg("Write to slave_addr: 0x%02x reg: 0x%0*x val: 0x%02x", + cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, + addr, b); - if (cts_dev->rtdata.addr_width == 2) { - put_unaligned_be16(addr, buff); - } else if (cts_dev->rtdata.addr_width == 3) { - put_unaligned_be24(addr, buff); - } else { - cts_err("Writeb invalid address width %u", - cts_dev->rtdata.addr_width); - return -EINVAL; - } - buff[cts_dev->rtdata.addr_width] = b; + if (cts_dev->rtdata.addr_width == 2) { + put_unaligned_be16(addr, buff); + } else if (cts_dev->rtdata.addr_width == 3) { + put_unaligned_be24(addr, buff); + } else { + cts_err("Writeb invalid address width %u", + cts_dev->rtdata.addr_width); + return -EINVAL; + } + buff[cts_dev->rtdata.addr_width] = b; - return cts_plat_i2c_write(cts_dev->pdata, cts_dev->rtdata.slave_addr, - buff, cts_dev->rtdata.addr_width + 1, retry ,delay); + return cts_plat_i2c_write(cts_dev->pdata, cts_dev->rtdata.slave_addr, + buff, cts_dev->rtdata.addr_width + 1, retry, + delay); } static int cts_i2c_writew(const struct cts_device *cts_dev, - u32 addr, u16 w, int retry, int delay) + u32 addr, u16 w, int retry, int delay) { - u8 buff[8]; + u8 buff[8]; - cts_dbg("Write to slave_addr: 0x%02x reg: 0x%0*x val: 0x%04x", - cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, addr, w); + cts_dbg("Write to slave_addr: 0x%02x reg: 0x%0*x val: 0x%04x", + cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, + addr, w); - if (cts_dev->rtdata.addr_width == 2) { - put_unaligned_be16(addr, buff); - } else if (cts_dev->rtdata.addr_width == 3) { - put_unaligned_be24(addr, buff); - } else { - cts_err("Writew invalid address width %u", - cts_dev->rtdata.addr_width); - return -EINVAL; - } + if (cts_dev->rtdata.addr_width == 2) { + put_unaligned_be16(addr, buff); + } else if (cts_dev->rtdata.addr_width == 3) { + put_unaligned_be24(addr, buff); + } else { + cts_err("Writew invalid address width %u", + cts_dev->rtdata.addr_width); + return -EINVAL; + } - put_unaligned_le16(w, buff + cts_dev->rtdata.addr_width); + put_unaligned_le16(w, buff + cts_dev->rtdata.addr_width); - return cts_plat_i2c_write(cts_dev->pdata, cts_dev->rtdata.slave_addr, - buff, cts_dev->rtdata.addr_width + 2, retry, delay); + return cts_plat_i2c_write(cts_dev->pdata, cts_dev->rtdata.slave_addr, + buff, cts_dev->rtdata.addr_width + 2, retry, + delay); } static int cts_i2c_writel(const struct cts_device *cts_dev, - u32 addr, u32 l, int retry, int delay) + u32 addr, u32 l, int retry, int delay) { - u8 buff[8]; + u8 buff[8]; - cts_dbg("Write to slave_addr: 0x%02x reg: 0x%0*x val: 0x%08x", - cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, addr, l); + cts_dbg("Write to slave_addr: 0x%02x reg: 0x%0*x val: 0x%08x", + cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, + addr, l); - if (cts_dev->rtdata.addr_width == 2) { - put_unaligned_be16(addr, buff); - } else if (cts_dev->rtdata.addr_width == 3) { - put_unaligned_be24(addr, buff); - } else { - cts_err("Writel invalid address width %u", - cts_dev->rtdata.addr_width); - return -EINVAL; - } + if (cts_dev->rtdata.addr_width == 2) { + put_unaligned_be16(addr, buff); + } else if (cts_dev->rtdata.addr_width == 3) { + put_unaligned_be24(addr, buff); + } else { + cts_err("Writel invalid address width %u", + cts_dev->rtdata.addr_width); + return -EINVAL; + } - put_unaligned_le32(l, buff + cts_dev->rtdata.addr_width); + put_unaligned_le32(l, buff + cts_dev->rtdata.addr_width); - return cts_plat_i2c_write(cts_dev->pdata, cts_dev->rtdata.slave_addr, - buff, cts_dev->rtdata.addr_width + 4, retry, delay); + return cts_plat_i2c_write(cts_dev->pdata, cts_dev->rtdata.slave_addr, + buff, cts_dev->rtdata.addr_width + 4, retry, + delay); } static int cts_i2c_writesb(const struct cts_device *cts_dev, u32 addr, - const u8 *src, size_t len, int retry, int delay) + const u8 *src, size_t len, int retry, int delay) { - int ret; - u8 *data; - size_t max_xfer_size; - size_t payload_len; - size_t xfer_len; + int ret; + u8 *data; + size_t max_xfer_size; + size_t payload_len; + size_t xfer_len; - cts_dbg("Write to slave_addr: 0x%02x reg: 0x%0*x len: %zu", - cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, addr, len); + cts_dbg("Write to slave_addr: 0x%02x reg: 0x%0*x len: %zu", + cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, + addr, len); - max_xfer_size = cts_plat_get_max_i2c_xfer_size(cts_dev->pdata); - data = cts_plat_get_i2c_xfer_buf(cts_dev->pdata, len); - while (len) { - payload_len = - min((size_t)(max_xfer_size - cts_dev->rtdata.addr_width), len); - xfer_len = payload_len + cts_dev->rtdata.addr_width; + max_xfer_size = cts_plat_get_max_i2c_xfer_size(cts_dev->pdata); + data = cts_plat_get_i2c_xfer_buf(cts_dev->pdata, len); + while (len) { + payload_len = + min((size_t) (max_xfer_size - cts_dev->rtdata.addr_width), + len); + xfer_len = payload_len + cts_dev->rtdata.addr_width; - if (cts_dev->rtdata.addr_width == 2) { - put_unaligned_be16(addr, data); - } else if (cts_dev->rtdata.addr_width == 3) { - put_unaligned_be24(addr, data); - } else { - cts_err("Writesb invalid address width %u", - cts_dev->rtdata.addr_width); - return -EINVAL; - } + if (cts_dev->rtdata.addr_width == 2) { + put_unaligned_be16(addr, data); + } else if (cts_dev->rtdata.addr_width == 3) { + put_unaligned_be24(addr, data); + } else { + cts_err("Writesb invalid address width %u", + cts_dev->rtdata.addr_width); + return -EINVAL; + } - memcpy(data + cts_dev->rtdata.addr_width, src, payload_len); + memcpy(data + cts_dev->rtdata.addr_width, src, payload_len); - ret = cts_plat_i2c_write(cts_dev->pdata, cts_dev->rtdata.slave_addr, - data, xfer_len, retry, delay); - if (ret) { - cts_err("Platform i2c write failed %d", ret); - return ret; - } + ret = + cts_plat_i2c_write(cts_dev->pdata, + cts_dev->rtdata.slave_addr, data, + xfer_len, retry, delay); + if (ret) { + cts_err("Platform i2c write failed %d", ret); + return ret; + } - src += payload_len; - len -= payload_len; - addr += payload_len; - } + src += payload_len; + len -= payload_len; + addr += payload_len; + } - return 0; + return 0; } static int cts_i2c_readb(const struct cts_device *cts_dev, - u32 addr, u8 *b, int retry, int delay) + u32 addr, u8 *b, int retry, int delay) { - u8 addr_buf[4]; + u8 addr_buf[4]; - cts_dbg("Readb from slave_addr: 0x%02x reg: 0x%0*x", - cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, addr); + cts_dbg("Readb from slave_addr: 0x%02x reg: 0x%0*x", + cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, + addr); - if (cts_dev->rtdata.addr_width == 2) { - put_unaligned_be16(addr, addr_buf); - } else if (cts_dev->rtdata.addr_width == 3) { - put_unaligned_be24(addr, addr_buf); - } else { - cts_err("Readb invalid address width %u", - cts_dev->rtdata.addr_width); - return -EINVAL; - } + if (cts_dev->rtdata.addr_width == 2) { + put_unaligned_be16(addr, addr_buf); + } else if (cts_dev->rtdata.addr_width == 3) { + put_unaligned_be24(addr, addr_buf); + } else { + cts_err("Readb invalid address width %u", + cts_dev->rtdata.addr_width); + return -EINVAL; + } - return cts_plat_i2c_read(cts_dev->pdata, cts_dev->rtdata.slave_addr, - addr_buf, cts_dev->rtdata.addr_width, b, 1, retry, delay); + return cts_plat_i2c_read(cts_dev->pdata, cts_dev->rtdata.slave_addr, + addr_buf, cts_dev->rtdata.addr_width, b, 1, + retry, delay); } static int cts_i2c_readw(const struct cts_device *cts_dev, - u32 addr, u16 *w, int retry, int delay) + u32 addr, u16 *w, int retry, int delay) { - int ret; - u8 addr_buf[4]; - u8 buff[2]; + int ret; + u8 addr_buf[4]; + u8 buff[2]; - cts_dbg("Readw from slave_addr: 0x%02x reg: 0x%0*x", - cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, addr); + cts_dbg("Readw from slave_addr: 0x%02x reg: 0x%0*x", + cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, + addr); - if (cts_dev->rtdata.addr_width == 2) { - put_unaligned_be16(addr, addr_buf); - } else if (cts_dev->rtdata.addr_width == 3) { - put_unaligned_be24(addr, addr_buf); - } else { - cts_err("Readw invalid address width %u", - cts_dev->rtdata.addr_width); - return -EINVAL; - } + if (cts_dev->rtdata.addr_width == 2) { + put_unaligned_be16(addr, addr_buf); + } else if (cts_dev->rtdata.addr_width == 3) { + put_unaligned_be24(addr, addr_buf); + } else { + cts_err("Readw invalid address width %u", + cts_dev->rtdata.addr_width); + return -EINVAL; + } - ret = cts_plat_i2c_read(cts_dev->pdata, cts_dev->rtdata.slave_addr, - addr_buf, cts_dev->rtdata.addr_width, buff, 2, retry, delay); - if (ret == 0) { - *w = get_unaligned_le16(buff); - } + ret = cts_plat_i2c_read(cts_dev->pdata, cts_dev->rtdata.slave_addr, + addr_buf, cts_dev->rtdata.addr_width, buff, 2, + retry, delay); + if (ret == 0) { + *w = get_unaligned_le16(buff); + } - return ret; + return ret; } static int cts_i2c_readl(const struct cts_device *cts_dev, - u32 addr, u32 *l, int retry, int delay) + u32 addr, u32 *l, int retry, int delay) { - int ret; - u8 addr_buf[4]; - u8 buff[4]; + int ret; + u8 addr_buf[4]; + u8 buff[4]; - cts_dbg("Readl from slave_addr: 0x%02x reg: 0x%0*x", - cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, addr); + cts_dbg("Readl from slave_addr: 0x%02x reg: 0x%0*x", + cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, + addr); - if (cts_dev->rtdata.addr_width == 2) { - put_unaligned_be16(addr, addr_buf); - } else if (cts_dev->rtdata.addr_width == 3) { - put_unaligned_be24(addr, addr_buf); - } else { - cts_err("Readl invalid address width %u", - cts_dev->rtdata.addr_width); - return -EINVAL; - } + if (cts_dev->rtdata.addr_width == 2) { + put_unaligned_be16(addr, addr_buf); + } else if (cts_dev->rtdata.addr_width == 3) { + put_unaligned_be24(addr, addr_buf); + } else { + cts_err("Readl invalid address width %u", + cts_dev->rtdata.addr_width); + return -EINVAL; + } - ret = cts_plat_i2c_read(cts_dev->pdata, cts_dev->rtdata.slave_addr, - addr_buf, cts_dev->rtdata.addr_width, buff, 4, retry, delay); - if (ret == 0) { - *l = get_unaligned_le32(buff); - } + ret = cts_plat_i2c_read(cts_dev->pdata, cts_dev->rtdata.slave_addr, + addr_buf, cts_dev->rtdata.addr_width, buff, 4, + retry, delay); + if (ret == 0) { + *l = get_unaligned_le32(buff); + } - return ret; + return ret; } static int cts_i2c_readsb(const struct cts_device *cts_dev, - u32 addr, void *dst, size_t len, int retry, int delay) + u32 addr, void *dst, size_t len, int retry, int delay) { - int ret; - u8 addr_buf[4]; - size_t max_xfer_size, xfer_len; + int ret; + u8 addr_buf[4]; + size_t max_xfer_size, xfer_len; - cts_dbg("Readsb from slave_addr: 0x%02x reg: 0x%0*x len: %zu", - cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, addr, len); + cts_dbg("Readsb from slave_addr: 0x%02x reg: 0x%0*x len: %zu", + cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, + addr, len); - max_xfer_size = cts_plat_get_max_i2c_xfer_size(cts_dev->pdata); - while (len) { - xfer_len = min(max_xfer_size, len); + max_xfer_size = cts_plat_get_max_i2c_xfer_size(cts_dev->pdata); + while (len) { + xfer_len = min(max_xfer_size, len); - if (cts_dev->rtdata.addr_width == 2) { - put_unaligned_be16(addr, addr_buf); - } else if (cts_dev->rtdata.addr_width == 3) { - put_unaligned_be24(addr, addr_buf); - } else { - cts_err("Readsb invalid address width %u", - cts_dev->rtdata.addr_width); - return -EINVAL; - } + if (cts_dev->rtdata.addr_width == 2) { + put_unaligned_be16(addr, addr_buf); + } else if (cts_dev->rtdata.addr_width == 3) { + put_unaligned_be24(addr, addr_buf); + } else { + cts_err("Readsb invalid address width %u", + cts_dev->rtdata.addr_width); + return -EINVAL; + } - ret = cts_plat_i2c_read(cts_dev->pdata, cts_dev->rtdata.slave_addr, - addr_buf, cts_dev->rtdata.addr_width, dst, xfer_len, retry, delay); - if (ret) { - cts_err("Platform i2c read failed %d", ret); - return ret; - } + ret = + cts_plat_i2c_read(cts_dev->pdata, + cts_dev->rtdata.slave_addr, addr_buf, + cts_dev->rtdata.addr_width, dst, xfer_len, + retry, delay); + if (ret) { + cts_err("Platform i2c read failed %d", ret); + return ret; + } - dst += xfer_len; - len -= xfer_len; - addr += xfer_len; - } + dst += xfer_len; + len -= xfer_len; + addr += xfer_len; + } - return 0; + return 0; } #else static int cts_spi_writeb(const struct cts_device *cts_dev, - u32 addr, u8 b, int retry, int delay) + u32 addr, u8 b, int retry, int delay) { - u8 buff[8]; + u8 buff[8]; // cts_dbg("Write to slave_addr: 0x%02x reg: 0x%0*x val: 0x%02x", // cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, addr, b); - if (cts_dev->rtdata.addr_width == 2) { - put_unaligned_be16(addr, buff); - } else if (cts_dev->rtdata.addr_width == 3) { - put_unaligned_be24(addr, buff); - } else { - cts_err("Writeb invalid address width %u", - cts_dev->rtdata.addr_width); - return -EINVAL; - } - buff[cts_dev->rtdata.addr_width] = b; + if (cts_dev->rtdata.addr_width == 2) { + put_unaligned_be16(addr, buff); + } else if (cts_dev->rtdata.addr_width == 3) { + put_unaligned_be24(addr, buff); + } else { + cts_err("Writeb invalid address width %u", + cts_dev->rtdata.addr_width); + return -EINVAL; + } + buff[cts_dev->rtdata.addr_width] = b; - return cts_plat_spi_write(cts_dev->pdata, cts_dev->rtdata.slave_addr, buff, - cts_dev->rtdata.addr_width + 1, retry ,delay); + return cts_plat_spi_write(cts_dev->pdata, cts_dev->rtdata.slave_addr, + buff, cts_dev->rtdata.addr_width + 1, retry, + delay); return 0; } static int cts_spi_writew(const struct cts_device *cts_dev, - u32 addr, u16 w, int retry, int delay) + u32 addr, u16 w, int retry, int delay) { - u8 buff[8]; + u8 buff[8]; // cts_dbg("Write to slave_addr: 0x%02x reg: 0x%0*x val: 0x%04x", // cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, addr, w); - if (cts_dev->rtdata.addr_width == 2) { - put_unaligned_be16(addr, buff); - } else if (cts_dev->rtdata.addr_width == 3) { - put_unaligned_be24(addr, buff); - } else { - cts_err("Writew invalid address width %u", - cts_dev->rtdata.addr_width); - return -EINVAL; - } + if (cts_dev->rtdata.addr_width == 2) { + put_unaligned_be16(addr, buff); + } else if (cts_dev->rtdata.addr_width == 3) { + put_unaligned_be24(addr, buff); + } else { + cts_err("Writew invalid address width %u", + cts_dev->rtdata.addr_width); + return -EINVAL; + } - put_unaligned_le16(w, buff + cts_dev->rtdata.addr_width); + put_unaligned_le16(w, buff + cts_dev->rtdata.addr_width); - return cts_plat_spi_write(cts_dev->pdata, cts_dev->rtdata.slave_addr, - buff, cts_dev->rtdata.addr_width + 2, retry, delay); + return cts_plat_spi_write(cts_dev->pdata, cts_dev->rtdata.slave_addr, + buff, cts_dev->rtdata.addr_width + 2, retry, + delay); return 0; } static int cts_spi_writel(const struct cts_device *cts_dev, - u32 addr, u32 l, int retry, int delay) + u32 addr, u32 l, int retry, int delay) { - u8 buff[8]; + u8 buff[8]; // cts_dbg("Write to slave_addr: 0x%02x reg: 0x%0*x val: 0x%08x", // cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, addr, l); - if (cts_dev->rtdata.addr_width == 2) { - put_unaligned_be16(addr, buff); - } else if (cts_dev->rtdata.addr_width == 3) { - put_unaligned_be24(addr, buff); - } else { - cts_err("Writel invalid address width %u", - cts_dev->rtdata.addr_width); - return -EINVAL; - } + if (cts_dev->rtdata.addr_width == 2) { + put_unaligned_be16(addr, buff); + } else if (cts_dev->rtdata.addr_width == 3) { + put_unaligned_be24(addr, buff); + } else { + cts_err("Writel invalid address width %u", + cts_dev->rtdata.addr_width); + return -EINVAL; + } - put_unaligned_le32(l, buff + cts_dev->rtdata.addr_width); + put_unaligned_le32(l, buff + cts_dev->rtdata.addr_width); - return cts_plat_spi_write(cts_dev->pdata, cts_dev->rtdata.slave_addr, - buff, cts_dev->rtdata.addr_width + 4, retry, delay); + return cts_plat_spi_write(cts_dev->pdata, cts_dev->rtdata.slave_addr, + buff, cts_dev->rtdata.addr_width + 4, retry, + delay); return 0; } static int cts_spi_writesb(const struct cts_device *cts_dev, u32 addr, - const u8 *src, size_t len, int retry, int delay) + const u8 *src, size_t len, int retry, int delay) { #if 1 - int ret; - u8 *data; - size_t max_xfer_size; - size_t payload_len; - size_t xfer_len; + int ret; + u8 *data; + size_t max_xfer_size; + size_t payload_len; + size_t xfer_len; // cts_dbg("Write to slave_addr: 0x%02x reg: 0x%0*x len: %zu", // cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, addr, len); - max_xfer_size = cts_plat_get_max_spi_xfer_size(cts_dev->pdata); - data = cts_plat_get_spi_xfer_buf(cts_dev->pdata, len); - while (len) { - payload_len = - min((size_t)(max_xfer_size - cts_dev->rtdata.addr_width), len); - xfer_len = payload_len + cts_dev->rtdata.addr_width; + max_xfer_size = cts_plat_get_max_spi_xfer_size(cts_dev->pdata); + data = cts_plat_get_spi_xfer_buf(cts_dev->pdata, len); + while (len) { + payload_len = + min((size_t) (max_xfer_size - cts_dev->rtdata.addr_width), + len); + xfer_len = payload_len + cts_dev->rtdata.addr_width; - if (cts_dev->rtdata.addr_width == 2) { - put_unaligned_be16(addr, data); - } else if (cts_dev->rtdata.addr_width == 3) { - put_unaligned_be24(addr, data); - } else { - cts_err("Writesb invalid address width %u", - cts_dev->rtdata.addr_width); - return -EINVAL; - } + if (cts_dev->rtdata.addr_width == 2) { + put_unaligned_be16(addr, data); + } else if (cts_dev->rtdata.addr_width == 3) { + put_unaligned_be24(addr, data); + } else { + cts_err("Writesb invalid address width %u", + cts_dev->rtdata.addr_width); + return -EINVAL; + } - memcpy(data + cts_dev->rtdata.addr_width, src, payload_len); + memcpy(data + cts_dev->rtdata.addr_width, src, payload_len); - ret = cts_plat_spi_write(cts_dev->pdata, cts_dev->rtdata.slave_addr, - data, xfer_len, retry, delay); - if (ret) { - cts_err("Platform i2c write failed %d", ret); - return ret; - } + ret = + cts_plat_spi_write(cts_dev->pdata, + cts_dev->rtdata.slave_addr, data, + xfer_len, retry, delay); + if (ret) { + cts_err("Platform i2c write failed %d", ret); + return ret; + } - src += payload_len; - len -= payload_len; - addr += payload_len; - } + src += payload_len; + len -= payload_len; + addr += payload_len; + } #endif - return 0; + return 0; } static int cts_spi_readb(const struct cts_device *cts_dev, - u32 addr, u8 *b, int retry, int delay) + u32 addr, u8 *b, int retry, int delay) { - u8 addr_buf[4]; + u8 addr_buf[4]; // cts_dbg("Readb from slave_addr: 0x%02x reg: 0x%0*x", // cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, addr); - if (cts_dev->rtdata.addr_width == 2) { - put_unaligned_be16(addr, addr_buf); - } else if (cts_dev->rtdata.addr_width == 3) { - put_unaligned_be24(addr, addr_buf); - } else { - cts_err("Readb invalid address width %u", - cts_dev->rtdata.addr_width); - return -EINVAL; - } + if (cts_dev->rtdata.addr_width == 2) { + put_unaligned_be16(addr, addr_buf); + } else if (cts_dev->rtdata.addr_width == 3) { + put_unaligned_be24(addr, addr_buf); + } else { + cts_err("Readb invalid address width %u", + cts_dev->rtdata.addr_width); + return -EINVAL; + } - return cts_plat_spi_read(cts_dev->pdata, cts_dev->rtdata.slave_addr, - addr_buf, cts_dev->rtdata.addr_width, b, 1, retry, delay); + return cts_plat_spi_read(cts_dev->pdata, cts_dev->rtdata.slave_addr, + addr_buf, cts_dev->rtdata.addr_width, b, 1, + retry, delay); } static int cts_spi_readw(const struct cts_device *cts_dev, - u32 addr, u16 *w, int retry, int delay) + u32 addr, u16 *w, int retry, int delay) { - int ret; - u8 addr_buf[4]; - u8 buff[2]; + int ret; + u8 addr_buf[4]; + u8 buff[2]; // cts_dbg("Readw from slave_addr: 0x%02x reg: 0x%0*x", // cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, addr); - if (cts_dev->rtdata.addr_width == 2) { - put_unaligned_be16(addr, addr_buf); - } else if (cts_dev->rtdata.addr_width == 3) { - put_unaligned_be24(addr, addr_buf); - } else { - cts_err("Readw invalid address width %u", - cts_dev->rtdata.addr_width); - return -EINVAL; - } + if (cts_dev->rtdata.addr_width == 2) { + put_unaligned_be16(addr, addr_buf); + } else if (cts_dev->rtdata.addr_width == 3) { + put_unaligned_be24(addr, addr_buf); + } else { + cts_err("Readw invalid address width %u", + cts_dev->rtdata.addr_width); + return -EINVAL; + } - ret = cts_plat_spi_read(cts_dev->pdata, cts_dev->rtdata.slave_addr, - addr_buf, cts_dev->rtdata.addr_width, buff, 2, retry, delay); - if (ret == 0) { - *w = get_unaligned_le16(buff); - } + ret = cts_plat_spi_read(cts_dev->pdata, cts_dev->rtdata.slave_addr, + addr_buf, cts_dev->rtdata.addr_width, buff, 2, + retry, delay); + if (ret == 0) { + *w = get_unaligned_le16(buff); + } - return ret; + return ret; } static int cts_spi_readl(const struct cts_device *cts_dev, - u32 addr, u32 *l, int retry, int delay) + u32 addr, u32 *l, int retry, int delay) { - int ret; - u8 addr_buf[4]; - u8 buff[4]; + int ret; + u8 addr_buf[4]; + u8 buff[4]; // cts_dbg("Readl from slave_addr: 0x%02x reg: 0x%0*x", // cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, addr); - if (cts_dev->rtdata.addr_width == 2) { - put_unaligned_be16(addr, addr_buf); - } else if (cts_dev->rtdata.addr_width == 3) { - put_unaligned_be24(addr, addr_buf); - } else { - cts_err("Readl invalid address width %u", - cts_dev->rtdata.addr_width); - return -EINVAL; - } + if (cts_dev->rtdata.addr_width == 2) { + put_unaligned_be16(addr, addr_buf); + } else if (cts_dev->rtdata.addr_width == 3) { + put_unaligned_be24(addr, addr_buf); + } else { + cts_err("Readl invalid address width %u", + cts_dev->rtdata.addr_width); + return -EINVAL; + } - ret = cts_plat_spi_read(cts_dev->pdata, cts_dev->rtdata.slave_addr, - addr_buf, cts_dev->rtdata.addr_width, buff, 4, retry, delay); - if (ret == 0) { - *l = get_unaligned_le32(buff); - } + ret = cts_plat_spi_read(cts_dev->pdata, cts_dev->rtdata.slave_addr, + addr_buf, cts_dev->rtdata.addr_width, buff, 4, + retry, delay); + if (ret == 0) { + *l = get_unaligned_le32(buff); + } - return ret; + return ret; return 0; } static int cts_spi_readsb(const struct cts_device *cts_dev, - u32 addr, void *dst, size_t len, int retry, int delay) + u32 addr, void *dst, size_t len, int retry, int delay) { - int ret; - u8 addr_buf[4]; - size_t max_xfer_size, xfer_len; + int ret; + u8 addr_buf[4]; + size_t max_xfer_size, xfer_len; // cts_dbg("Readsb from slave_addr: 0x%02x reg: 0x%0*x len: %zu", // cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, addr, len); - max_xfer_size = cts_plat_get_max_spi_xfer_size(cts_dev->pdata); - while (len) { - xfer_len = min(max_xfer_size, len); + max_xfer_size = cts_plat_get_max_spi_xfer_size(cts_dev->pdata); + while (len) { + xfer_len = min(max_xfer_size, len); - if (cts_dev->rtdata.addr_width == 2) { - put_unaligned_be16(addr, addr_buf); - } else if (cts_dev->rtdata.addr_width == 3) { - put_unaligned_be24(addr, addr_buf); - } else { - cts_err("Readsb invalid address width %u", - cts_dev->rtdata.addr_width); - return -EINVAL; - } + if (cts_dev->rtdata.addr_width == 2) { + put_unaligned_be16(addr, addr_buf); + } else if (cts_dev->rtdata.addr_width == 3) { + put_unaligned_be24(addr, addr_buf); + } else { + cts_err("Readsb invalid address width %u", + cts_dev->rtdata.addr_width); + return -EINVAL; + } - ret = cts_plat_spi_read(cts_dev->pdata, cts_dev->rtdata.slave_addr, - addr_buf, cts_dev->rtdata.addr_width, dst, xfer_len, retry, delay); - if (ret) { - cts_err("Platform i2c read failed %d", ret); - return ret; - } + ret = + cts_plat_spi_read(cts_dev->pdata, + cts_dev->rtdata.slave_addr, addr_buf, + cts_dev->rtdata.addr_width, dst, xfer_len, + retry, delay); + if (ret) { + cts_err("Platform i2c read failed %d", ret); + return ret; + } - dst += xfer_len; - len -= xfer_len; - addr += xfer_len; - } - return 0; + dst += xfer_len; + len -= xfer_len; + addr += xfer_len; + } + return 0; } static int cts_spi_readsb_delay_idle(const struct cts_device *cts_dev, - u32 addr, void *dst, size_t len, int retry, int delay, int idle) + u32 addr, void *dst, size_t len, int retry, + int delay, int idle) { - int ret; - u8 addr_buf[4]; - size_t max_xfer_size, xfer_len; + int ret; + u8 addr_buf[4]; + size_t max_xfer_size, xfer_len; // cts_dbg("Readsb from slave_addr: 0x%02x reg: 0x%0*x len: %zu", // cts_dev->rtdata.slave_addr, cts_dev->rtdata.addr_width * 2, addr, len); - max_xfer_size = cts_plat_get_max_spi_xfer_size(cts_dev->pdata); - while (len) { - xfer_len = min(max_xfer_size, len); + max_xfer_size = cts_plat_get_max_spi_xfer_size(cts_dev->pdata); + while (len) { + xfer_len = min(max_xfer_size, len); - if (cts_dev->rtdata.addr_width == 2) { - put_unaligned_be16(addr, addr_buf); - } else if (cts_dev->rtdata.addr_width == 3) { - put_unaligned_be24(addr, addr_buf); - } else { - cts_err("Readsb invalid address width %u", - cts_dev->rtdata.addr_width); - return -EINVAL; - } + if (cts_dev->rtdata.addr_width == 2) { + put_unaligned_be16(addr, addr_buf); + } else if (cts_dev->rtdata.addr_width == 3) { + put_unaligned_be24(addr, addr_buf); + } else { + cts_err("Readsb invalid address width %u", + cts_dev->rtdata.addr_width); + return -EINVAL; + } - ret = cts_plat_spi_read_delay_idle(cts_dev->pdata, cts_dev->rtdata.slave_addr, - addr_buf, cts_dev->rtdata.addr_width, dst, xfer_len, retry, delay, idle); - if (ret) { - cts_err("Platform i2c read failed %d", ret); - return ret; - } + ret = + cts_plat_spi_read_delay_idle(cts_dev->pdata, + cts_dev->rtdata.slave_addr, + addr_buf, + cts_dev->rtdata.addr_width, + dst, xfer_len, retry, delay, + idle); + if (ret) { + cts_err("Platform i2c read failed %d", ret); + return ret; + } - dst += xfer_len; - len -= xfer_len; - addr += xfer_len; - } - return 0; + dst += xfer_len; + len -= xfer_len; + addr += xfer_len; + } + return 0; } #endif /* CONFIG_CTS_I2C_HOST */ static inline int cts_dev_writeb(const struct cts_device *cts_dev, - u32 addr, u8 b, int retry, int delay) + u32 addr, u8 b, int retry, int delay) { #ifdef CONFIG_CTS_I2C_HOST - return cts_i2c_writeb(cts_dev, addr, b, retry, delay); + return cts_i2c_writeb(cts_dev, addr, b, retry, delay); #else /* CONFIG_CTS_I2C_HOST */ - return cts_spi_writeb(cts_dev, addr, b, retry, delay); + return cts_spi_writeb(cts_dev, addr, b, retry, delay); #endif /* CONFIG_CTS_I2C_HOST */ } static inline int cts_dev_writew(const struct cts_device *cts_dev, - u32 addr, u16 w, int retry, int delay) + u32 addr, u16 w, int retry, int delay) { #ifdef CONFIG_CTS_I2C_HOST - return cts_i2c_writew(cts_dev, addr, w, retry, delay); + return cts_i2c_writew(cts_dev, addr, w, retry, delay); #else /* CONFIG_CTS_I2C_HOST */ - return cts_spi_writew(cts_dev, addr, w, retry, delay); + return cts_spi_writew(cts_dev, addr, w, retry, delay); #endif /* CONFIG_CTS_I2C_HOST */ } static inline int cts_dev_writel(const struct cts_device *cts_dev, - u32 addr, u32 l, int retry, int delay) + u32 addr, u32 l, int retry, int delay) { #ifdef CONFIG_CTS_I2C_HOST - return cts_i2c_writel(cts_dev, addr, l, retry, delay); + return cts_i2c_writel(cts_dev, addr, l, retry, delay); #else /* CONFIG_CTS_I2C_HOST */ - return cts_spi_writel(cts_dev, addr, l, retry, delay); + return cts_spi_writel(cts_dev, addr, l, retry, delay); #endif /* CONFIG_CTS_I2C_HOST */ } static inline int cts_dev_writesb(const struct cts_device *cts_dev, u32 addr, - const u8 *src, size_t len, int retry, int delay) + const u8 *src, size_t len, int retry, + int delay) { #ifdef CONFIG_CTS_I2C_HOST - return cts_i2c_writesb(cts_dev, addr, src, len, retry, delay); + return cts_i2c_writesb(cts_dev, addr, src, len, retry, delay); #else /* CONFIG_CTS_I2C_HOST */ - return cts_spi_writesb(cts_dev, addr, src, len, retry, delay); + return cts_spi_writesb(cts_dev, addr, src, len, retry, delay); #endif /* CONFIG_CTS_I2C_HOST */ } static inline int cts_dev_readb(const struct cts_device *cts_dev, - u32 addr, u8 *b, int retry, int delay) + u32 addr, u8 *b, int retry, int delay) { #ifdef CONFIG_CTS_I2C_HOST - return cts_i2c_readb(cts_dev, addr, b, retry, delay); + return cts_i2c_readb(cts_dev, addr, b, retry, delay); #else /* CONFIG_CTS_I2C_HOST */ - return cts_spi_readb(cts_dev, addr, b, retry, delay); + return cts_spi_readb(cts_dev, addr, b, retry, delay); #endif /* CONFIG_CTS_I2C_HOST */ } static inline int cts_dev_readw(const struct cts_device *cts_dev, - u32 addr, u16 *w, int retry, int delay) + u32 addr, u16 *w, int retry, int delay) { #ifdef CONFIG_CTS_I2C_HOST - return cts_i2c_readw(cts_dev, addr, w, retry, delay); + return cts_i2c_readw(cts_dev, addr, w, retry, delay); #else /* CONFIG_CTS_I2C_HOST */ - return cts_spi_readw(cts_dev, addr, w, retry, delay);; + return cts_spi_readw(cts_dev, addr, w, retry, delay);; #endif /* CONFIG_CTS_I2C_HOST */ } static inline int cts_dev_readl(const struct cts_device *cts_dev, - u32 addr, u32 *l, int retry, int delay) + u32 addr, u32 *l, int retry, int delay) { #ifdef CONFIG_CTS_I2C_HOST - return cts_i2c_readl(cts_dev, addr, l, retry, delay); + return cts_i2c_readl(cts_dev, addr, l, retry, delay); #else /* CONFIG_CTS_I2C_HOST */ - return cts_spi_readl(cts_dev, addr, l, retry, delay); + return cts_spi_readl(cts_dev, addr, l, retry, delay); #endif /* CONFIG_CTS_I2C_HOST */ } static inline int cts_dev_readsb(const struct cts_device *cts_dev, - u32 addr, void *dst, size_t len, int retry, int delay) + u32 addr, void *dst, size_t len, int retry, + int delay) { #ifdef CONFIG_CTS_I2C_HOST - return cts_i2c_readsb(cts_dev, addr, dst, len, retry, delay); + return cts_i2c_readsb(cts_dev, addr, dst, len, retry, delay); #else /* CONFIG_CTS_I2C_HOST */ - return cts_spi_readsb(cts_dev, addr, dst, len, retry, delay); + return cts_spi_readsb(cts_dev, addr, dst, len, retry, delay); #endif /* CONFIG_CTS_I2C_HOST */ } static inline int cts_dev_readsb_delay_idle(const struct cts_device *cts_dev, - u32 addr, void *dst, size_t len, int retry, int delay, int idle) + u32 addr, void *dst, size_t len, + int retry, int delay, int idle) { #ifdef CONFIG_CTS_I2C_HOST - return cts_i2c_readsb(cts_dev, addr, dst, len, retry, delay); + return cts_i2c_readsb(cts_dev, addr, dst, len, retry, delay); #else /* CONFIG_CTS_I2C_HOST */ - return cts_spi_readsb_delay_idle(cts_dev, addr, dst, len, retry, delay, idle); + return cts_spi_readsb_delay_idle(cts_dev, addr, dst, len, retry, delay, + idle); #endif /* CONFIG_CTS_I2C_HOST */ } - #ifdef CFG_CTS_UPDATE_CRCCHECK int cts_sram_writesb_boot_crc_retry(const struct cts_device *cts_dev, - size_t len, u32 crc, int retry) + size_t len, u32 crc, int retry) { - int ret = 0, retries; + int ret = 0, retries; - retries = 0; - do { - if ((ret = cts_dev_writel(cts_dev, 0x015ff0, 0xCC33555A, 3, 1)) != 0) { - cts_err("SRAM writesb failed %d", ret); - continue; - } + retries = 0; + do { + ret = cts_dev_writel(cts_dev, 0x015ff0, 0xCC33555A, 3, 1); + if (ret != 0) { + cts_err("SRAM writesb failed %d", ret); + continue; + } - if ((ret = cts_dev_writel(cts_dev, 0x08fffc, crc, 3, 1)) != 0) { - cts_err("SRAM writesb failed %d", ret); - continue; - } + ret = cts_dev_writel(cts_dev, 0x08fffc, crc, 3, 1); + if (ret != 0) { + cts_err("SRAM writesb failed %d", ret); + continue; + } - if ((ret = cts_dev_writel(cts_dev, 0x08fff8, len, 3, 1)) != 0) { - cts_err("SRAM writesb failed %d", ret); - continue; - } + ret = cts_dev_writel(cts_dev, 0x08fff8, len, 3, 1); + if (ret != 0) { + cts_err("SRAM writesb failed %d", ret); + continue; + } - break; - }while (retries++ < retry); + break; + } while (retries++ < retry); - return ret; + return ret; } #endif static int cts_write_sram_normal_mode(const struct cts_device *cts_dev, - u32 addr, const void *src, size_t len, int retry, int delay) + u32 addr, const void *src, size_t len, + int retry, int delay) { - int i, ret; - u8 buff[5]; + int i, ret; + u8 buff[5]; - for (i = 0; i < len; i++) { - put_unaligned_le32(addr, buff); - buff[4] = *(u8 *)src; + for (i = 0; i < len; i++) { + put_unaligned_le32(addr, buff); + buff[4] = *(u8 *) src; - addr++; - src++; + addr++; + src++; - ret = cts_dev_writesb(cts_dev, - CTS_DEVICE_FW_REG_DEBUG_INTF, buff, 5, retry, delay); - if (ret) { - cts_err("Write rDEBUG_INTF len=5B failed %d", - ret); - return ret; - } - } + ret = cts_dev_writesb(cts_dev, + CTS_DEVICE_FW_REG_DEBUG_INTF, buff, 5, + retry, delay); + if (ret) { + cts_err("Write rDEBUG_INTF len=5B failed %d", ret); + return ret; + } + } - return 0; + return 0; } int cts_sram_writeb_retry(const struct cts_device *cts_dev, - u32 addr, u8 b, int retry, int delay) + u32 addr, u8 b, int retry, int delay) { - if (cts_dev->rtdata.program_mode) { - return cts_dev_writeb(cts_dev, addr, b, retry, delay); - } else { - return cts_write_sram_normal_mode(cts_dev, addr, &b, 1, retry, delay); - } + if (cts_dev->rtdata.program_mode) { + return cts_dev_writeb(cts_dev, addr, b, retry, delay); + } else { + return cts_write_sram_normal_mode(cts_dev, addr, &b, 1, retry, + delay); + } } int cts_sram_writew_retry(const struct cts_device *cts_dev, - u32 addr, u16 w, int retry, int delay) + u32 addr, u16 w, int retry, int delay) { - u8 buff[2]; + u8 buff[2]; - if (cts_dev->rtdata.program_mode) { - return cts_dev_writew(cts_dev, addr, w, retry, delay); - } else { - put_unaligned_le16(w, buff); + if (cts_dev->rtdata.program_mode) { + return cts_dev_writew(cts_dev, addr, w, retry, delay); + } else { + put_unaligned_le16(w, buff); - return cts_write_sram_normal_mode(cts_dev, addr, buff, 2, retry, delay); - } + return cts_write_sram_normal_mode(cts_dev, addr, buff, 2, retry, + delay); + } } int cts_sram_writel_retry(const struct cts_device *cts_dev, - u32 addr, u32 l, int retry, int delay) + u32 addr, u32 l, int retry, int delay) { - u8 buff[4]; + u8 buff[4]; - if (cts_dev->rtdata.program_mode) { - return cts_dev_writel(cts_dev, addr, l, retry, delay); - } else { - put_unaligned_le32(l, buff); + if (cts_dev->rtdata.program_mode) { + return cts_dev_writel(cts_dev, addr, l, retry, delay); + } else { + put_unaligned_le32(l, buff); - return cts_write_sram_normal_mode(cts_dev, addr, buff, 4, retry, delay); - } + return cts_write_sram_normal_mode(cts_dev, addr, buff, 4, retry, + delay); + } } int cts_sram_writesb_retry(const struct cts_device *cts_dev, - u32 addr, const void *src, size_t len, int retry, int delay) + u32 addr, const void *src, size_t len, int retry, + int delay) { - if (cts_dev->rtdata.program_mode) { - return cts_dev_writesb(cts_dev, addr, src, len, retry, delay); - } else { - return cts_write_sram_normal_mode(cts_dev, addr, src, len, retry, delay); - } + if (cts_dev->rtdata.program_mode) { + return cts_dev_writesb(cts_dev, addr, src, len, retry, delay); + } else { + return cts_write_sram_normal_mode(cts_dev, addr, src, len, + retry, delay); + } } static int cts_calc_sram_crc(const struct cts_device *cts_dev, - u32 sram_addr, size_t size, u32 *crc) + u32 sram_addr, size_t size, u32 *crc) { - cts_info("Calc crc from sram 0x%06x size %zu", sram_addr, size); + cts_info("Calc crc from sram 0x%06x size %zu", sram_addr, size); - return cts_dev->hwdata->sfctrl->ops->calc_sram_crc(cts_dev, - sram_addr, size, crc); + return cts_dev->hwdata->sfctrl->ops->calc_sram_crc(cts_dev, + sram_addr, size, + crc); } int cts_sram_writesb_check_crc_retry(const struct cts_device *cts_dev, - u32 addr, const void *src, size_t len, u32 crc, int retry) + u32 addr, const void *src, size_t len, + u32 crc, int retry) { - int ret, retries; + int ret, retries; - retries = 0; - do { - u32 crc_sram; + retries = 0; + do { + u32 crc_sram; - retries++; + retries++; - if ((ret = cts_sram_writesb(cts_dev, 0, src, len)) != 0) { - cts_err("SRAM writesb failed %d", ret); - continue; - } + ret = cts_sram_writesb(cts_dev, 0, src, len); + if (ret != 0) { + cts_err("SRAM writesb failed %d", ret); + continue; + } - if ((ret = cts_calc_sram_crc(cts_dev, 0, len, &crc_sram)) != 0) { - cts_err("Get CRC for sram writesb failed %d retries %d", - ret, retries); - continue; - } + ret = cts_calc_sram_crc(cts_dev, 0, len, &crc_sram); + if (ret != 0) { + cts_err("Get CRC for sram writesb failed %d retries %d", + ret, retries); + continue; + } - if (crc == crc_sram) { - return 0; - } + if (crc == crc_sram) { + return 0; + } - cts_err("Check CRC for sram writesb mismatch %x != %x retries %d", - crc, crc_sram, retries); - ret = -EFAULT; - }while (retries < retry); + cts_err + ("Check CRC for sram writesb mismatch %x != %x retries %d", + crc, crc_sram, retries); + ret = -EFAULT; + } while (retries < retry); - return ret; + return ret; } static int cts_read_sram_normal_mode(const struct cts_device *cts_dev, - u32 addr, void *dst, size_t len, int retry, int delay) + u32 addr, void *dst, size_t len, int retry, + int delay) { - int i, ret; + int i, ret; - for (i = 0; i < len; i++) { - ret = cts_dev_writel(cts_dev, - CTS_DEVICE_FW_REG_DEBUG_INTF, addr, retry, delay); - if (ret) { - cts_err("Write addr to rDEBUG_INTF failed %d", ret); - return ret; - } + for (i = 0; i < len; i++) { + ret = cts_dev_writel(cts_dev, + CTS_DEVICE_FW_REG_DEBUG_INTF, addr, retry, + delay); + if (ret) { + cts_err("Write addr to rDEBUG_INTF failed %d", ret); + return ret; + } - ret = cts_dev_readb(cts_dev, - CTS_DEVICE_FW_REG_DEBUG_INTF + 4, (u8 *)dst, retry, delay); - if (ret) { - cts_err("Read value from rDEBUG_INTF + 4 failed %d", - ret); - return ret; - } + ret = cts_dev_readb(cts_dev, + CTS_DEVICE_FW_REG_DEBUG_INTF + 4, + (u8 *) dst, retry, delay); + if (ret) { + cts_err("Read value from rDEBUG_INTF + 4 failed %d", + ret); + return ret; + } - addr++; - dst++; - } + addr++; + dst++; + } - return 0; + return 0; } int cts_sram_readb_retry(const struct cts_device *cts_dev, - u32 addr, u8 *b, int retry, int delay) + u32 addr, u8 *b, int retry, int delay) { - if (cts_dev->rtdata.program_mode) { - return cts_dev_readb(cts_dev, addr, b, retry, delay); - } else { - return cts_read_sram_normal_mode(cts_dev, addr, b, 1, retry, delay); - } + if (cts_dev->rtdata.program_mode) { + return cts_dev_readb(cts_dev, addr, b, retry, delay); + } else { + return cts_read_sram_normal_mode(cts_dev, addr, b, 1, retry, + delay); + } } int cts_sram_readw_retry(const struct cts_device *cts_dev, - u32 addr, u16 *w, int retry, int delay) + u32 addr, u16 *w, int retry, int delay) { - int ret; - u8 buff[2]; + int ret; + u8 buff[2]; - if (cts_dev->rtdata.program_mode) { - return cts_dev_readw(cts_dev, addr, w, retry, delay); - } else { - ret = cts_read_sram_normal_mode(cts_dev, addr, buff, 2, retry, delay); - if (ret) { - cts_err("SRAM readw in normal mode failed %d", ret); - return ret; - } + if (cts_dev->rtdata.program_mode) { + return cts_dev_readw(cts_dev, addr, w, retry, delay); + } else { + ret = + cts_read_sram_normal_mode(cts_dev, addr, buff, 2, retry, + delay); + if (ret) { + cts_err("SRAM readw in normal mode failed %d", ret); + return ret; + } - *w = get_unaligned_le16(buff); + *w = get_unaligned_le16(buff); - return 0; - } + return 0; + } } int cts_sram_readl_retry(const struct cts_device *cts_dev, - u32 addr, u32 *l, int retry, int delay) + u32 addr, u32 *l, int retry, int delay) { - int ret; - u8 buff[4]; + int ret; + u8 buff[4]; - if (cts_dev->rtdata.program_mode) { - return cts_dev_readl(cts_dev, addr, l, retry, delay); - } else { - ret = cts_read_sram_normal_mode(cts_dev, addr, buff, 4, retry, delay); - if (ret) { - cts_err("SRAM readl in normal mode failed %d", ret); - return ret; - } + if (cts_dev->rtdata.program_mode) { + return cts_dev_readl(cts_dev, addr, l, retry, delay); + } else { + ret = + cts_read_sram_normal_mode(cts_dev, addr, buff, 4, retry, + delay); + if (ret) { + cts_err("SRAM readl in normal mode failed %d", ret); + return ret; + } - *l = get_unaligned_le32(buff); + *l = get_unaligned_le32(buff); - return 0; - } + return 0; + } } int cts_sram_readsb_retry(const struct cts_device *cts_dev, - u32 addr, void *dst, size_t len, int retry, int delay) + u32 addr, void *dst, size_t len, int retry, int delay) { - if (cts_dev->rtdata.program_mode) { - return cts_dev_readsb(cts_dev, addr, dst, len, retry, delay); - } else { - return cts_read_sram_normal_mode(cts_dev, addr, dst, len, retry, delay); - } + if (cts_dev->rtdata.program_mode) { + return cts_dev_readsb(cts_dev, addr, dst, len, retry, delay); + } else { + return cts_read_sram_normal_mode(cts_dev, addr, dst, len, retry, + delay); + } } int cts_fw_reg_writeb_retry(const struct cts_device *cts_dev, - u32 reg_addr, u8 b, int retry, int delay) + u32 reg_addr, u8 b, int retry, int delay) { - if (cts_dev->rtdata.program_mode) { - cts_err("Writeb to fw reg 0x%04x under program mode", reg_addr); - return -ENODEV; - } + if (cts_dev->rtdata.program_mode) { + cts_err("Writeb to fw reg 0x%04x under program mode", reg_addr); + return -ENODEV; + } - return cts_dev_writeb(cts_dev, reg_addr, b, retry, delay); + return cts_dev_writeb(cts_dev, reg_addr, b, retry, delay); } int cts_fw_reg_writew_retry(const struct cts_device *cts_dev, - u32 reg_addr, u16 w, int retry, int delay) + u32 reg_addr, u16 w, int retry, int delay) { - if (cts_dev->rtdata.program_mode) { - cts_err("Writew to fw reg 0x%04x under program mode", reg_addr); - return -ENODEV; - } + if (cts_dev->rtdata.program_mode) { + cts_err("Writew to fw reg 0x%04x under program mode", reg_addr); + return -ENODEV; + } - return cts_dev_writew(cts_dev, reg_addr, w, retry, delay); + return cts_dev_writew(cts_dev, reg_addr, w, retry, delay); } int cts_fw_reg_writel_retry(const struct cts_device *cts_dev, - u32 reg_addr, u32 l, int retry, int delay) + u32 reg_addr, u32 l, int retry, int delay) { - if (cts_dev->rtdata.program_mode) { - cts_err("Writel to fw reg 0x%04x under program mode", reg_addr); - return -ENODEV; - } + if (cts_dev->rtdata.program_mode) { + cts_err("Writel to fw reg 0x%04x under program mode", reg_addr); + return -ENODEV; + } - return cts_dev_writel(cts_dev, reg_addr, l, retry, delay); + return cts_dev_writel(cts_dev, reg_addr, l, retry, delay); } int cts_fw_reg_writesb_retry(const struct cts_device *cts_dev, - u32 reg_addr, const void *src, size_t len, int retry, int delay) + u32 reg_addr, const void *src, size_t len, + int retry, int delay) { - if (cts_dev->rtdata.program_mode) { - cts_err("Writesb to fw reg 0x%04x under program mode", reg_addr); - return -ENODEV; - } + if (cts_dev->rtdata.program_mode) { + cts_err("Writesb to fw reg 0x%04x under program mode", + reg_addr); + return -ENODEV; + } - return cts_dev_writesb(cts_dev, reg_addr, src, len, retry, delay); + return cts_dev_writesb(cts_dev, reg_addr, src, len, retry, delay); } int cts_fw_reg_readb_retry(const struct cts_device *cts_dev, - u32 reg_addr, u8 *b, int retry, int delay) + u32 reg_addr, u8 *b, int retry, int delay) { - if (cts_dev->rtdata.program_mode) { - cts_err("Readb from fw reg under program mode"); - return -ENODEV; - } + if (cts_dev->rtdata.program_mode) { + cts_err("Readb from fw reg under program mode"); + return -ENODEV; + } - return cts_dev_readb(cts_dev, reg_addr, b, retry, delay); + return cts_dev_readb(cts_dev, reg_addr, b, retry, delay); } int cts_fw_reg_readw_retry(const struct cts_device *cts_dev, - u32 reg_addr, u16 *w, int retry, int delay) + u32 reg_addr, u16 *w, int retry, int delay) { - if (cts_dev->rtdata.program_mode) { - cts_err("Readw from fw reg under program mode"); - return -ENODEV; - } + if (cts_dev->rtdata.program_mode) { + cts_err("Readw from fw reg under program mode"); + return -ENODEV; + } - return cts_dev_readw(cts_dev, reg_addr, w, retry, delay); + return cts_dev_readw(cts_dev, reg_addr, w, retry, delay); } int cts_fw_reg_readl_retry(const struct cts_device *cts_dev, - u32 reg_addr, u32 *l, int retry, int delay) + u32 reg_addr, u32 *l, int retry, int delay) { - if (cts_dev->rtdata.program_mode) { - cts_err("Readl from fw reg under program mode"); - return -ENODEV; - } + if (cts_dev->rtdata.program_mode) { + cts_err("Readl from fw reg under program mode"); + return -ENODEV; + } - return cts_dev_readl(cts_dev, reg_addr, l, retry, delay); + return cts_dev_readl(cts_dev, reg_addr, l, retry, delay); } int cts_fw_reg_readsb_retry(const struct cts_device *cts_dev, - u32 reg_addr, void *dst, size_t len, int retry, int delay) + u32 reg_addr, void *dst, size_t len, int retry, + int delay) { - if (cts_dev->rtdata.program_mode) { - cts_err("Readsb from fw reg under program mode"); - return -ENODEV; - } + if (cts_dev->rtdata.program_mode) { + cts_err("Readsb from fw reg under program mode"); + return -ENODEV; + } - return cts_dev_readsb(cts_dev, reg_addr, dst, len, retry, delay); + return cts_dev_readsb(cts_dev, reg_addr, dst, len, retry, delay); } + int cts_fw_reg_readsb_retry_delay_idle(const struct cts_device *cts_dev, - u32 reg_addr, void *dst, size_t len, int retry, int delay, int idle) + u32 reg_addr, void *dst, size_t len, + int retry, int delay, int idle) { - if (cts_dev->rtdata.program_mode) { - cts_err("Readsb from fw reg under program mode"); - return -ENODEV; - } + if (cts_dev->rtdata.program_mode) { + cts_err("Readsb from fw reg under program mode"); + return -ENODEV; + } - return cts_dev_readsb_delay_idle(cts_dev, reg_addr, dst, len, retry, delay, idle); + return cts_dev_readsb_delay_idle(cts_dev, reg_addr, dst, len, retry, + delay, idle); } - int cts_hw_reg_writeb_retry(const struct cts_device *cts_dev, - u32 reg_addr, u8 b, int retry, int delay) + u32 reg_addr, u8 b, int retry, int delay) { - return cts_sram_writeb_retry(cts_dev, reg_addr, b, retry, delay); + return cts_sram_writeb_retry(cts_dev, reg_addr, b, retry, delay); } int cts_hw_reg_writew_retry(const struct cts_device *cts_dev, - u32 reg_addr, u16 w, int retry, int delay) + u32 reg_addr, u16 w, int retry, int delay) { - return cts_sram_writew_retry(cts_dev, reg_addr, w, retry, delay); + return cts_sram_writew_retry(cts_dev, reg_addr, w, retry, delay); } int cts_hw_reg_writel_retry(const struct cts_device *cts_dev, - u32 reg_addr, u32 l, int retry, int delay) + u32 reg_addr, u32 l, int retry, int delay) { - return cts_sram_writel_retry(cts_dev, reg_addr, l, retry, delay); + return cts_sram_writel_retry(cts_dev, reg_addr, l, retry, delay); } int cts_hw_reg_writesb_retry(const struct cts_device *cts_dev, - u32 reg_addr, const void *src, size_t len, int retry, int delay) + u32 reg_addr, const void *src, size_t len, + int retry, int delay) { - return cts_sram_writesb_retry(cts_dev, reg_addr, src, len, retry, delay); + return cts_sram_writesb_retry(cts_dev, reg_addr, src, len, retry, + delay); } int cts_hw_reg_readb_retry(const struct cts_device *cts_dev, - u32 reg_addr, u8 *b, int retry, int delay) + u32 reg_addr, u8 *b, int retry, int delay) { - return cts_sram_readb_retry(cts_dev, reg_addr, b, retry, delay); + return cts_sram_readb_retry(cts_dev, reg_addr, b, retry, delay); } int cts_hw_reg_readw_retry(const struct cts_device *cts_dev, - u32 reg_addr, u16 *w, int retry, int delay) + u32 reg_addr, u16 *w, int retry, int delay) { - return cts_sram_readw_retry(cts_dev, reg_addr, w, retry, delay); + return cts_sram_readw_retry(cts_dev, reg_addr, w, retry, delay); } int cts_hw_reg_readl_retry(const struct cts_device *cts_dev, - u32 reg_addr, u32 *l, int retry, int delay) + u32 reg_addr, u32 *l, int retry, int delay) { - return cts_sram_readl_retry(cts_dev, reg_addr, l, retry, delay); + return cts_sram_readl_retry(cts_dev, reg_addr, l, retry, delay); } int cts_hw_reg_readsb_retry(const struct cts_device *cts_dev, - u32 reg_addr, void *dst, size_t len, int retry, int delay) + u32 reg_addr, void *dst, size_t len, int retry, + int delay) { - return cts_sram_readsb_retry(cts_dev, reg_addr, dst, len, retry, delay); + return cts_sram_readsb_retry(cts_dev, reg_addr, dst, len, retry, delay); } const static struct cts_sfctrl icnl9911_sfctrl = { - .reg_base = 0x34000, - .xchg_sram_base = (80 - 1) * 1024, - .xchg_sram_size = 1024, /* For non firmware programming */ - .ops = &cts_sfctrlv2_ops + .reg_base = 0x34000, + .xchg_sram_base = (80 - 1) * 1024, + .xchg_sram_size = 1024, /* For non firmware programming */ + .ops = &cts_sfctrlv2_ops }; const static struct cts_sfctrl icnl9911s_sfctrl = { - .reg_base = 0x34000, - .xchg_sram_base = (64 - 1) * 1024, - .xchg_sram_size = 1024, /* For non firmware programming */ - .ops = &cts_sfctrlv2_ops + .reg_base = 0x34000, + .xchg_sram_base = (64 - 1) * 1024, + .xchg_sram_size = 1024, /* For non firmware programming */ + .ops = &cts_sfctrlv2_ops }; const static struct cts_device_hwdata cts_device_hwdatas[] = { - { - .name = "ICNL9911", - .hwid = CTS_DEV_HWID_ICNL9911, - .fwid = CTS_DEV_FWID_ICNL9911, - .num_row = 32, - .num_col = 18, - .sram_size = 80 * 1024, + { + .name = "ICNL9911", + .hwid = CTS_DEV_HWID_ICNL9911, + .fwid = CTS_DEV_FWID_ICNL9911, + .num_row = 32, + .num_col = 18, + .sram_size = 80 * 1024, - .program_addr_width = 3, + .program_addr_width = 3, - .sfctrl = &icnl9911_sfctrl, - }, - { - .name = "ICNL9911S", - .hwid = CTS_DEV_HWID_ICNL9911S, - .fwid = CTS_DEV_FWID_ICNL9911S, - .num_row = 32, - .num_col = 18, - .sram_size = 64 * 1024, + .sfctrl = &icnl9911_sfctrl, + }, + { + .name = "ICNL9911S", + .hwid = CTS_DEV_HWID_ICNL9911S, + .fwid = CTS_DEV_FWID_ICNL9911S, + .num_row = 32, + .num_col = 18, + .sram_size = 64 * 1024, - .program_addr_width = 3, + .program_addr_width = 3, - .sfctrl = &icnl9911s_sfctrl, - } + .sfctrl = &icnl9911s_sfctrl, + } }; static int cts_init_device_hwdata(struct cts_device *cts_dev, - u32 hwid, u16 fwid) + u32 hwid, u16 fwid) { - int i; + int i; - cts_info("Init hardware data hwid: %06x fwid: %04x", hwid, fwid); + cts_info("Init hardware data hwid: %06x fwid: %04x", hwid, fwid); - for (i = 0; i < ARRAY_SIZE(cts_device_hwdatas); i++) { - if (hwid == cts_device_hwdatas[i].hwid || - fwid == cts_device_hwdatas[i].fwid) { - cts_dev->hwdata = &cts_device_hwdatas[i]; - return 0; - } - } + for (i = 0; i < ARRAY_SIZE(cts_device_hwdatas); i++) { + if (hwid == cts_device_hwdatas[i].hwid || + fwid == cts_device_hwdatas[i].fwid) { + cts_dev->hwdata = &cts_device_hwdatas[i]; + return 0; + } + } - return -EINVAL; + return -EINVAL; } void cts_lock_device(const struct cts_device *cts_dev) { - cts_dbg("*** Lock ***"); + cts_dbg("*** Lock ***"); - rt_mutex_lock(&cts_dev->pdata->dev_lock); + rt_mutex_lock(&cts_dev->pdata->dev_lock); } void cts_unlock_device(const struct cts_device *cts_dev) { - cts_dbg("### Un-Lock ###"); + cts_dbg("### Un-Lock ###"); - rt_mutex_unlock(&cts_dev->pdata->dev_lock); + rt_mutex_unlock(&cts_dev->pdata->dev_lock); } int cts_set_work_mode(const struct cts_device *cts_dev, u8 mode) { - cts_info("Set work mode to %u", mode); + cts_info("Set work mode to %u", mode); - return cts_fw_reg_writeb(cts_dev, CTS_DEVICE_FW_REG_WORK_MODE, mode); + return cts_fw_reg_writeb(cts_dev, CTS_DEVICE_FW_REG_WORK_MODE, mode); } int cts_get_work_mode(const struct cts_device *cts_dev, u8 *mode) { - return cts_fw_reg_readb(cts_dev, CTS_DEVICE_FW_REG_WORK_MODE, mode); + return cts_fw_reg_readb(cts_dev, CTS_DEVICE_FW_REG_WORK_MODE, mode); } int cts_get_firmware_version(const struct cts_device *cts_dev, u16 *version) { - int ret = cts_fw_reg_readw(cts_dev, CTS_DEVICE_FW_REG_VERSION, version); + int ret = cts_fw_reg_readw(cts_dev, CTS_DEVICE_FW_REG_VERSION, version); - if (ret) { - *version = 0; - } else { - *version = be16_to_cpup(version); - } + if (ret) { + *version = 0; + } else { + *version = be16_to_cpup(version); + } - return ret; + return ret; } int cts_get_ddi_version(const struct cts_device *cts_dev, u8 *version) { - int ret = cts_fw_reg_readb(cts_dev, CTS_DEVICE_FW_REG_DDI_VERSION, version); + int ret = + cts_fw_reg_readb(cts_dev, CTS_DEVICE_FW_REG_DDI_VERSION, version); - if (ret) { - *version = 0; - } - return ret; + if (ret) { + *version = 0; + } + return ret; } int cts_get_lib_version(const struct cts_device *cts_dev, u16 *lib_version) { - u8 main_version, sub_version; - int ret; + u8 main_version, sub_version; + int ret; - ret = cts_fw_reg_readb(cts_dev, CTS_DEVICE_FW_REG_FW_LIB_MAIN_VERSION, &main_version); - if (ret) { - cts_err("Get fw lib main version failed %d", ret); - return ret; - } + ret = + cts_fw_reg_readb(cts_dev, CTS_DEVICE_FW_REG_FW_LIB_MAIN_VERSION, + &main_version); + if (ret) { + cts_err("Get fw lib main version failed %d", ret); + return ret; + } - ret = cts_fw_reg_readb(cts_dev, CTS_DEVICE_FW_REG_FW_LIB_SUB_VERSION, &sub_version); - if (ret) { - cts_err("Get fw lib sub version failed %d", ret); - return ret; - } + ret = + cts_fw_reg_readb(cts_dev, CTS_DEVICE_FW_REG_FW_LIB_SUB_VERSION, + &sub_version); + if (ret) { + cts_err("Get fw lib sub version failed %d", ret); + return ret; + } - *lib_version = (main_version << 8) + sub_version; - return 0; + *lib_version = (main_version << 8) + sub_version; + return 0; } - int cts_get_data_ready_flag(const struct cts_device *cts_dev, u8 *flag) { - return cts_fw_reg_readb(cts_dev, CTS_DEVICE_FW_REG_DATA_READY, flag); + return cts_fw_reg_readb(cts_dev, CTS_DEVICE_FW_REG_DATA_READY, flag); } int cts_clr_data_ready_flag(const struct cts_device *cts_dev) { - return cts_fw_reg_writeb(cts_dev, CTS_DEVICE_FW_REG_DATA_READY, 0); + return cts_fw_reg_writeb(cts_dev, CTS_DEVICE_FW_REG_DATA_READY, 0); } int cts_send_command(const struct cts_device *cts_dev, u8 cmd) { - cts_info("Send command 0x%02x", cmd); + cts_info("Send command 0x%02x", cmd); - if (cts_dev->rtdata.program_mode) { - cts_warn("Send command %u while chip in program mode", cmd); - return -ENODEV; - } + if (cts_dev->rtdata.program_mode) { + cts_warn("Send command %u while chip in program mode", cmd); + return -ENODEV; + } - return cts_fw_reg_writeb_retry(cts_dev, CTS_DEVICE_FW_REG_CMD, cmd, 3, 0); + return cts_fw_reg_writeb_retry(cts_dev, CTS_DEVICE_FW_REG_CMD, cmd, 3, + 0); } static int cts_get_touchinfo(const struct cts_device *cts_dev, - struct cts_device_touch_info *touch_info) + struct cts_device_touch_info *touch_info) { - cts_dbg("Get touch info"); + cts_dbg("Get touch info"); - if (cts_dev->rtdata.program_mode) { - cts_warn("Get touch info in program mode"); - return -ENODEV; - } + if (cts_dev->rtdata.program_mode) { + cts_warn("Get touch info in program mode"); + return -ENODEV; + } - if (cts_dev->rtdata.suspended) { - cts_warn("Get touch info while is suspended"); - return -ENODEV; - } + if (cts_dev->rtdata.suspended) { + cts_warn("Get touch info while is suspended"); + return -ENODEV; + } - return cts_fw_reg_readsb(cts_dev, CTS_DEVICE_FW_REG_TOUCH_INFO, - touch_info, sizeof(*touch_info)); + return cts_fw_reg_readsb(cts_dev, CTS_DEVICE_FW_REG_TOUCH_INFO, + touch_info, sizeof(*touch_info)); } int cts_get_panel_param(const struct cts_device *cts_dev, - void *param, size_t size) + void *param, size_t size) { - cts_info("Get panel parameter"); + cts_info("Get panel parameter"); - if (cts_dev->rtdata.program_mode) { - cts_warn("Get panel parameter in program mode"); - return -ENODEV; - } + if (cts_dev->rtdata.program_mode) { + cts_warn("Get panel parameter in program mode"); + return -ENODEV; + } - return cts_fw_reg_readsb(cts_dev, - CTS_DEVICE_FW_REG_PANEL_PARAM, param, size); + return cts_fw_reg_readsb(cts_dev, + CTS_DEVICE_FW_REG_PANEL_PARAM, param, size); } int cts_set_panel_param(const struct cts_device *cts_dev, - const void *param, size_t size) + const void *param, size_t size) { - cts_info("Set panel parameter"); + cts_info("Set panel parameter"); - if (cts_dev->rtdata.program_mode) { - cts_warn("Set panel parameter in program mode"); - return -ENODEV; - } - return cts_fw_reg_writesb(cts_dev, - CTS_DEVICE_FW_REG_PANEL_PARAM, param, size); + if (cts_dev->rtdata.program_mode) { + cts_warn("Set panel parameter in program mode"); + return -ENODEV; + } + return cts_fw_reg_writesb(cts_dev, + CTS_DEVICE_FW_REG_PANEL_PARAM, param, size); } int cts_get_x_resolution(const struct cts_device *cts_dev, u16 *resolution) { - return cts_fw_reg_readw(cts_dev, CTS_DEVICE_FW_REG_X_RESOLUTION, resolution); + return cts_fw_reg_readw(cts_dev, CTS_DEVICE_FW_REG_X_RESOLUTION, + resolution); } int cts_get_y_resolution(const struct cts_device *cts_dev, u16 *resolution) { - return cts_fw_reg_readw(cts_dev, CTS_DEVICE_FW_REG_Y_RESOLUTION, resolution); + return cts_fw_reg_readw(cts_dev, CTS_DEVICE_FW_REG_Y_RESOLUTION, + resolution); } int cts_get_num_rows(const struct cts_device *cts_dev, u8 *num_rows) { - return cts_fw_reg_readb(cts_dev, CTS_DEVICE_FW_REG_NUM_TX, num_rows); + return cts_fw_reg_readb(cts_dev, CTS_DEVICE_FW_REG_NUM_TX, num_rows); } int cts_get_num_cols(const struct cts_device *cts_dev, u8 *num_cols) { - return cts_fw_reg_readb(cts_dev, CTS_DEVICE_FW_REG_NUM_RX, num_cols); + return cts_fw_reg_readb(cts_dev, CTS_DEVICE_FW_REG_NUM_RX, num_cols); } #ifdef CONFIG_CTS_LEGACY_TOOL int cts_enable_get_rawdata(const struct cts_device *cts_dev) { - cts_info("Enable get raw/diff data"); - return cts_send_command(cts_dev, CTS_CMD_ENABLE_READ_RAWDATA); + cts_info("Enable get raw/diff data"); + return cts_send_command(cts_dev, CTS_CMD_ENABLE_READ_RAWDATA); } int cts_disable_get_rawdata(const struct cts_device *cts_dev) { - cts_info("Disable get raw/diff data"); - return cts_send_command(cts_dev, CTS_CMD_DISABLE_READ_RAWDATA); + cts_info("Disable get raw/diff data"); + return cts_send_command(cts_dev, CTS_CMD_DISABLE_READ_RAWDATA); } int cts_get_rawdata(const struct cts_device *cts_dev, void *buf) { - int i, ret; - u8 ready; - u8 retries = 5; + int i, ret; + u8 ready; + u8 retries = 5; + + cts_info("Get rawdata"); - cts_info("Get rawdata"); /** - Wait data ready flag set */ - for (i = 0; i < 1000; i++) { - mdelay(1); - ret = cts_get_data_ready_flag(cts_dev, &ready); - if (ret) { - cts_err("Get data ready flag failed %d", ret); - goto get_raw_exit; - } - if (ready) { - break; - } - } - if (i == 1000) { - ret = -ENODEV; - goto get_raw_exit; - } - do { - ret = cts_fw_reg_readsb_delay_idle(cts_dev, CTS_DEVICE_FW_REG_RAW_DATA, - buf,cts_dev->fwdata.rows*cts_dev->fwdata.cols*2, 500); - if (ret) { - cts_err("Read rawdata failed %d", ret); - } - } while (--retries > 0 && ret != 0); + for (i = 0; i < 100; i++) { + mdelay(10); + ret = cts_get_data_ready_flag(cts_dev, &ready); + if (ret) { + cts_err("Get data ready flag failed %d", ret); + continue; + } + if (ready) { + goto read_rawdata; + } + } + cts_err("Wait data ready timeout"); + return -ETIMEDOUT; - if (cts_clr_data_ready_flag(cts_dev)) { - cts_err("Clear data ready flag failed"); - ret = -ENODEV; + /* Read rawdata */ +read_rawdata: + do { + ret = + cts_fw_reg_readsb_delay_idle(cts_dev, + CTS_DEVICE_FW_REG_RAW_DATA, + buf, + cts_dev->fwdata.rows * + cts_dev->fwdata.cols * 2, 500); + if (ret) { + cts_err("Read rawdata failed %d", ret); + } else { + break; + } + } while (--retries > 0); + + for (i = 0; i < 5; i++) { + int r = cts_clr_data_ready_flag(cts_dev); + if (r) { + cts_err("Clear data ready flag failed %d", r); + } else { + break; + } } -get_raw_exit: - return ret; + + return ret; } int cts_get_diffdata(const struct cts_device *cts_dev, void *buf) { - int i, j, ret; - u8 ready; - u8 retries = 5; - u8 *cache_buf; + int i, j, ret; + u8 ready; + u8 retries = 5; + u8 *cache_buf; - cts_info("Get diffdata"); - cache_buf = kzalloc( - (cts_dev->fwdata.rows + 2) * (cts_dev->fwdata.cols + 2) * 2, GFP_KERNEL); - if (cache_buf == NULL) { - cts_err("Get diffdata: malloc error"); - ret = -ENOMEM; - goto get_diff_exit; - } + cts_info("Get diffdata"); + cache_buf = kzalloc((cts_dev->fwdata.rows + 2) * (cts_dev->fwdata.cols + + 2) * 2, GFP_KERNEL); + if (cache_buf == NULL) { + cts_err("Get diffdata: malloc error"); + ret = -ENOMEM; + goto get_diff_exit; + } /** - Wait data ready flag set */ - for (i = 0; i < 1000; i++) { - mdelay(1); - ret = cts_get_data_ready_flag(cts_dev, &ready); - if (ret) { - cts_err("Get data ready flag failed %d", ret); - goto get_diff_free_buf; - } - if (ready) { - break; - } - } - if (i == 1000) { - ret = -ENODEV; - goto get_diff_free_buf; - } - do { - ret = cts_fw_reg_readsb_delay_idle(cts_dev, CTS_DEVICE_FW_REG_DIFF_DATA, - cache_buf,(cts_dev->fwdata.rows+2)*(cts_dev->fwdata.cols+2)*2, 500); - if (ret) { - cts_err("Read diffdata failed %d", ret); - } - } while (--retries > 0 && ret != 0); + for (i = 0; i < 1000; i++) { + mdelay(1); + ret = cts_get_data_ready_flag(cts_dev, &ready); + if (ret) { + cts_err("Get data ready flag failed %d", ret); + goto get_diff_free_buf; + } + if (ready) { + break; + } + } + if (i == 1000) { + ret = -ETIMEDOUT; + goto get_diff_free_buf; + } + do { + ret = + cts_fw_reg_readsb_delay_idle(cts_dev, + CTS_DEVICE_FW_REG_DIFF_DATA, + cache_buf, + (cts_dev->fwdata.rows + + 2) * (cts_dev->fwdata.cols + + 2) * 2, 500); + if (ret) { + cts_err("Read diffdata failed %d", ret); + } else { + break; + } + } while (--retries > 0); - for (i = 0; i < cts_dev->fwdata.rows; i++) { - for (j = 0; j < cts_dev->fwdata.cols; j++) { - ((u8 *)buf)[2 * (i * cts_dev->fwdata.cols + j)] = - cache_buf[2 * ((i+1)*(cts_dev->fwdata.cols+2)+j+1)]; - ((u8 *)buf)[2*(i*cts_dev->fwdata.cols + j)+1] = - cache_buf[2*((i+1)*(cts_dev->fwdata.cols+2)+j+1)+1]; - } + if (ret == 0) { + for (i = 0; i < cts_dev->fwdata.rows; i++) { + for (j = 0; j < cts_dev->fwdata.cols; j++) { + ((u8 *) buf)[2 * (i * cts_dev->fwdata.cols + j)] = + cache_buf[2 * + ((i + 1) * (cts_dev->fwdata.cols + 2) + + j + 1)]; + ((u8 *) buf)[2 * (i * cts_dev->fwdata.cols + j) + 1] = + cache_buf[2 * + ((i + 1) * (cts_dev->fwdata.cols + 2) + + j + 1) + 1]; + } + } + } + + for (i = 0; i < 5; i++) { + int r = cts_clr_data_ready_flag(cts_dev); + if (r) { + cts_err("Clear data ready flag failed %d", r); + } else { + break; + } } - if (cts_clr_data_ready_flag(cts_dev)) { - cts_err("Clear data ready flag failed"); - ret = -ENODEV; - } get_diff_free_buf: - kfree(cache_buf); + kfree(cache_buf); get_diff_exit: - return ret; + return ret; } #endif /* CONFIG_CTS_LEGACY_TOOL */ static int cts_get_dev_boot_mode(const struct cts_device *cts_dev, - u8 *boot_mode) + u8 *boot_mode) { int ret; ret = cts_hw_reg_readb_retry(cts_dev, - CTS_DEV_HW_REG_CURRENT_MODE, boot_mode, 5, 10); + CTS_DEV_HW_REG_CURRENT_MODE, boot_mode, 5, + 10); if (ret) { cts_err("Read boot mode failed %d", ret); return ret; @@ -1343,550 +1455,584 @@ static int cts_get_dev_boot_mode(const struct cts_device *cts_dev, *boot_mode &= CTS_DEV_BOOT_MODE_MASK; cts_info("Curr dev boot mode: %u(%s)", *boot_mode, - cts_dev_boot_mode2str(*boot_mode)); - return 0; + cts_dev_boot_mode2str(*boot_mode)); + return 0; } -static int cts_set_dev_boot_mode(const struct cts_device *cts_dev, - u8 boot_mode) +static int cts_set_dev_boot_mode(const struct cts_device *cts_dev, u8 boot_mode) { - int ret; + int ret; - cts_info("Set dev boot mode to %u(%s)", boot_mode, - cts_dev_boot_mode2str(boot_mode)); + cts_info("Set dev boot mode to %u(%s)", boot_mode, + cts_dev_boot_mode2str(boot_mode)); - ret = cts_hw_reg_writeb_retry(cts_dev, CTS_DEV_HW_REG_BOOT_MODE, - boot_mode, 5, 5); - if (ret) { - cts_err("Write hw register BOOT_MODE failed %d", ret); - return ret; - } + ret = cts_hw_reg_writeb_retry(cts_dev, CTS_DEV_HW_REG_BOOT_MODE, + boot_mode, 5, 5); + if (ret) { + cts_err("Write hw register BOOT_MODE failed %d", ret); + return ret; + } - cts_info("cts_set_dev_boot_mode exit"); + cts_info("cts_set_dev_boot_mode exit"); - return 0; + return 0; } static int cts_init_fwdata(struct cts_device *cts_dev) { - int ret; + int ret; - cts_info("Init firmware data"); + cts_info("Init firmware data"); - if (cts_dev->rtdata.program_mode) { - cts_err("Init firmware data while in program mode"); - return -EINVAL; - } + if (cts_dev->rtdata.program_mode) { + cts_err("Init firmware data while in program mode"); + return -EINVAL; + } - ret = cts_get_firmware_version(cts_dev, &cts_dev->fwdata.version); - if (ret) { - cts_err("Read firmware version failed %d", ret); - return ret; - } - cts_info(" %-16s: %04x", "Firmware version", cts_dev->fwdata.version); + ret = cts_get_firmware_version(cts_dev, &cts_dev->fwdata.version); + if (ret) { + cts_err("Read firmware version failed %d", ret); + return ret; + } + cts_info(" %-16s: %04x", "Firmware version", cts_dev->fwdata.version); - ret = cts_get_ddi_version(cts_dev, &cts_dev->fwdata.ddi_version); - if (ret) { - cts_err("Read ddi version failed %d", ret); - return ret; - } - cts_info(" %-16s: %02x", "Ddi verion", cts_dev->fwdata.ddi_version); + ret = cts_get_ddi_version(cts_dev, &cts_dev->fwdata.ddi_version); + if (ret) { + cts_err("Read ddi version failed %d", ret); + return ret; + } + cts_info(" %-16s: %02x", "Ddi verion", cts_dev->fwdata.ddi_version); - ret = cts_get_x_resolution(cts_dev, &cts_dev->fwdata.res_x); - if (ret) { - cts_err("Read firmware X resoltion failed %d", ret); - return ret; - } - cts_info(" %-16s: %u", "X resolution", cts_dev->fwdata.res_x); + ret = cts_get_x_resolution(cts_dev, &cts_dev->fwdata.res_x); + if (ret) { + cts_err("Read firmware X resoltion failed %d", ret); + return ret; + } + cts_info(" %-16s: %u", "X resolution", cts_dev->fwdata.res_x); - ret = cts_get_y_resolution(cts_dev, &cts_dev->fwdata.res_y); - if (ret) { - cts_err("Read firmware Y resoltion failed %d", ret); - return ret; - } - cts_info(" %-16s: %u", "Y resolution", cts_dev->fwdata.res_y); + ret = cts_get_y_resolution(cts_dev, &cts_dev->fwdata.res_y); + if (ret) { + cts_err("Read firmware Y resoltion failed %d", ret); + return ret; + } + cts_info(" %-16s: %u", "Y resolution", cts_dev->fwdata.res_y); - ret = cts_get_num_rows(cts_dev, &cts_dev->fwdata.rows); - if (ret) { - cts_err("Read firmware num TX failed %d", ret); - return ret; - } - cts_info(" %-16s: %u", "Num rows", cts_dev->fwdata.rows); + ret = cts_get_num_rows(cts_dev, &cts_dev->fwdata.rows); + if (ret) { + cts_err("Read firmware num TX failed %d", ret); + return ret; + } + cts_info(" %-16s: %u", "Num rows", cts_dev->fwdata.rows); - ret = cts_get_num_cols(cts_dev, &cts_dev->fwdata.cols); - if (ret) { - cts_err("Read firmware num RX failed %d", ret); - return ret; - } - cts_info(" %-16s: %u", "Num cols", cts_dev->fwdata.cols); + ret = cts_get_num_cols(cts_dev, &cts_dev->fwdata.cols); + if (ret) { + cts_err("Read firmware num RX failed %d", ret); + return ret; + } + cts_info(" %-16s: %u", "Num cols", cts_dev->fwdata.cols); - ret = cts_fw_reg_readb(cts_dev, 0x8000+216, &cts_dev->fwdata.int_mode); + ret = + cts_fw_reg_readb(cts_dev, 0x8000 + 216, &cts_dev->fwdata.int_mode); if (ret) { cts_err("Read firmware Int mode failed %d", ret); return ret; } - cts_info(" %-16s: %s", "Int mode", (cts_dev->fwdata.int_mode==0)? - "LOW" : "HIGH"); + cts_info(" %-16s: %s", "Int mode", (cts_dev->fwdata.int_mode == 0) ? + "LOW" : "HIGH"); - ret = cts_fw_reg_readw(cts_dev, 0x8000+71, &cts_dev->fwdata.int_keep_time); + ret = + cts_fw_reg_readw(cts_dev, 0x8000 + 71, + &cts_dev->fwdata.int_keep_time); if (ret) { cts_err("Read firmware Int keep time failed %d", ret); return ret; } - cts_info(" %-16s: %d", "Int keep time", cts_dev->fwdata.int_keep_time); + cts_info(" %-16s: %d", "Int keep time", cts_dev->fwdata.int_keep_time); - ret = cts_fw_reg_readw(cts_dev, 0x8000+73, &cts_dev->fwdata.rawdata_target); + ret = + cts_fw_reg_readw(cts_dev, 0x8000 + 73, + &cts_dev->fwdata.rawdata_target); if (ret) { cts_err("Read firmware Raw dest value failed %d", ret); return ret; } - cts_info(" %-16s: %d", "Raw dest value", cts_dev->fwdata.rawdata_target); + cts_info(" %-16s: %d", "Raw dest value", + cts_dev->fwdata.rawdata_target); ret = cts_get_lib_version(cts_dev, &cts_dev->fwdata.lib_version); if (ret) { cts_err("Read firmware Lib version failed %d", ret); } - cts_info(" %-16s: %04x", "Lib verion", cts_dev->fwdata.lib_version); + cts_info(" %-16s: %04x", "Lib verion", cts_dev->fwdata.lib_version); - ret = cts_fw_reg_readb(cts_dev, 0x8000+342, &cts_dev->fwdata.esd_method); + ret = + cts_fw_reg_readb(cts_dev, 0x8000 + 342, + &cts_dev->fwdata.esd_method); if (ret) { cts_err("Read firmware Esd method failed %d", ret); return ret; } - cts_info(" %-16s: %d", "Esd method", cts_dev->fwdata.esd_method); + cts_info(" %-16s: %d", "Esd method", cts_dev->fwdata.esd_method); - return 0; + return 0; } #if 0 static int cts_post_reset_device(struct cts_device *cts_dev) { - int ret; + int ret; - /* Reset all flags */ - cts_dev->rtdata.program_mode = false; - cts_dev->rtdata.suspended = false; - cts_dev->rtdata.updating = false; - cts_dev->rtdata.testing = false; + /* Reset all flags */ + cts_dev->rtdata.program_mode = false; + cts_dev->rtdata.suspended = false; + cts_dev->rtdata.updating = false; + cts_dev->rtdata.testing = false; #if 0 #ifdef CONFIG_CTS_I2C_HOST - /* Check whether device is in normal mode */ - if (!cts_plat_is_i2c_online(cts_dev->pdata, - CTS_DEV_NORMAL_MODE_I2CADDR)) { + /* Check whether device is in normal mode */ + if (!cts_plat_is_i2c_online(cts_dev->pdata, + CTS_DEV_NORMAL_MODE_I2CADDR)) { #else if (!cts_plat_is_normal_mode(cts_dev->pdata)) { #endif /* CONFIG_CTS_I2C_HOST */ - const struct cts_firmware *firmware; + const struct cts_firmware *firmware; - cts_err("Normal mode i2c addr is offline"); + cts_err("Normal mode i2c addr is offline"); #ifdef CONFIG_CTS_I2C_HOST - if (!cts_plat_is_i2c_online(cts_dev->pdata, - CTS_DEV_PROGRAM_MODE_I2CADDR)) { - cts_err("Program mode i2c addr is offline"); - return -EFAULT; - } + if (!cts_plat_is_i2c_online(cts_dev->pdata, + CTS_DEV_PROGRAM_MODE_I2CADDR)) { + cts_err("Program mode i2c addr is offline"); + return -EFAULT; + } #endif #ifdef CONFIG_CTS_I2C_HOST - cts_dev->rtdata.slave_addr = CTS_DEV_PROGRAM_MODE_I2CADDR; + cts_dev->rtdata.slave_addr = CTS_DEV_PROGRAM_MODE_I2CADDR; #endif - cts_dev->rtdata.addr_width = CTS_DEV_PROGRAM_MODE_ADDR_WIDTH; - cts_dev->rtdata.program_mode = true; + cts_dev->rtdata.addr_width = CTS_DEV_PROGRAM_MODE_ADDR_WIDTH; + cts_dev->rtdata.program_mode = true; - firmware = cts_request_firmware(cts_dev->hwdata->hwid, - cts_dev->hwdata->fwid, 0); - if (firmware) { - ret = cts_update_firmware(cts_dev, firmware, true); - cts_release_firmware(firmware); + firmware = cts_request_firmware(cts_dev->hwdata->hwid, + cts_dev->hwdata->fwid, 0); + if (firmware) { + ret = cts_update_firmware(cts_dev, firmware, true); + cts_release_firmware(firmware); - if (ret) { - cts_err("Update default firmware failed %d", ret); - return ret; - } - } else { - cts_err("Request default firmware failed %d, " - "please update manually!!", ret); + if (ret) { + cts_err("Update default firmware failed %d", + ret); + return ret; + } + } else { + cts_err("Request default firmware failed %d, " + "please update manually!!", ret); - return ret; - } + return ret; + } - return -ENODEV; - } + return -ENODEV; + } - ret = cts_init_fwdata(cts_dev); - if (ret) { - cts_err("Init fwdata failed %d", ret); - return ret; - } + ret = cts_init_fwdata(cts_dev); + if (ret) { + cts_err("Init fwdata failed %d", ret); + return ret; + } #endif #ifdef CONFIG_CTS_CHARGER_DETECT - if (cts_is_charger_exist(cts_dev)) { - int r = cts_set_dev_charger_state(cts_dev, true); - if (r) { - cts_err("Set charger state ATTACHED failed %d", r); - // Ignore - } - } + if (cts_is_charger_exist(cts_dev)) { + int r = cts_set_dev_charger_state(cts_dev, true); + if (r) { + cts_err("Set charger state ATTACHED failed %d", r); + // Ignore + } + } #endif /* CONFIG_CTS_CHARGER_DETECT */ #ifdef CONFIG_CTS_GLOVE_MODE - if (cts_is_glove_mode_enabled(cts_dev)) { - int r = cts_set_dev_glove_mode(cts_dev, true); - if (r) { - cts_err("Enable glove mode failed %d", r); - // Ignore - } - } + if (cts_is_glove_mode_enabled(cts_dev)) { + int r = cts_set_dev_glove_mode(cts_dev, true); + if (r) { + cts_err("Enable glove mode failed %d", r); + // Ignore + } + } #endif /* CONFIG_CTS_GLOVE_MODE */ #ifdef CONFIG_CTS_FW_LOG_REDIRECT - if (cts_is_fw_log_redirect_enabled(cts_dev)) { - int r = cts_set_dev_fw_log_redirect(cts_dev, true); - if (r) { - cts_err("Enable fw log redirect failed %d", r); - // Ignore - } - } + if (cts_is_fw_log_redirect_enabled(cts_dev)) { + int r = cts_set_dev_fw_log_redirect(cts_dev, true); + if (r) { + cts_err("Enable fw log redirect failed %d", r); + // Ignore + } + } #endif /* CONFIG_CTS_FW_LOG_REDIRECT */ - return 0; + return 0; } int cts_reset_device(struct cts_device *cts_dev) { - cts_info("Reset device"); + cts_info("Reset device"); #ifdef CFG_CTS_HAS_RESET_PIN - cts_plat_reset_device(cts_dev->pdata); + cts_plat_reset_device(cts_dev->pdata); #else /* CFG_CTS_HAS_RESET_PIN */ #ifdef CONFIG_CTS_I2C_HOST - if (cts_plat_is_i2c_online(cts_dev->pdata, CTS_DEV_NORMAL_MODE_I2CADDR)) { - cts_dev->rtdata.program_mode = false; - cts_dev->rtdata.slave_addr = CTS_DEV_NORMAL_MODE_I2CADDR; - cts_dev->rtdata.addr_width = CTS_DEV_NORMAL_MODE_ADDR_WIDTH; - } else if (cts_plat_is_i2c_online(cts_dev->pdata, CTS_DEV_PROGRAM_MODE_I2CADDR)) { - cts_dev->rtdata.program_mode = true; - cts_dev->rtdata.slave_addr = CTS_DEV_PROGRAM_MODE_I2CADDR; - cts_dev->rtdata.addr_width = CTS_DEV_PROGRAM_MODE_ADDR_WIDTH; - } else { - cts_err("Both i2c addr is offline"); - return -ENODEV; - } + if (cts_plat_is_i2c_online(cts_dev->pdata, CTS_DEV_NORMAL_MODE_I2CADDR)) { + cts_dev->rtdata.program_mode = false; + cts_dev->rtdata.slave_addr = CTS_DEV_NORMAL_MODE_I2CADDR; + cts_dev->rtdata.addr_width = CTS_DEV_NORMAL_MODE_ADDR_WIDTH; + } else + if (cts_plat_is_i2c_online + (cts_dev->pdata, CTS_DEV_PROGRAM_MODE_I2CADDR)) { + cts_dev->rtdata.program_mode = true; + cts_dev->rtdata.slave_addr = CTS_DEV_PROGRAM_MODE_I2CADDR; + cts_dev->rtdata.addr_width = CTS_DEV_PROGRAM_MODE_ADDR_WIDTH; + } else { + cts_err("Both i2c addr is offline"); + return -ENODEV; + } #else #endif /* CONFIG_CTS_I2C_HOST */ - /* Ignore return value, as I2C will always response NAK */ - cts_hw_reg_writew(cts_dev, CTS_DEV_HW_REG_RESET_CONFIG, 0x0101); - mdelay(50); + /* Ignore return value, as I2C will always response NAK */ + cts_hw_reg_writew(cts_dev, CTS_DEV_HW_REG_RESET_CONFIG, 0x0101); + mdelay(50); #endif /* CFG_CTS_HAS_RESET_PIN */ - return cts_post_reset_device(cts_dev); + return cts_post_reset_device(cts_dev); } #endif #ifdef CFG_CTS_FW_LOG_REDIRECT void cts_show_fw_log(struct cts_device *cts_dev) { - u8 len, max_len; - int ret; - u8 *data; + u8 len, max_len; + int ret; + u8 *data; - max_len = cts_plat_get_max_fw_log_size(cts_dev->pdata); - data = cts_plat_get_fw_log_buf(cts_dev->pdata, max_len); - ret = cts_fw_reg_readsb(cts_dev, CTS_DEVICE_FW_REG_TOUCH_INFO+1, &len, 1); - if (ret) { - cts_err("Get i2c print buf len error"); - return; - } - if (len >= max_len) { - len = max_len - 1; - } - ret = cts_fw_reg_readsb(cts_dev, CTS_DEVICE_FW_REG_TOUCH_INFO+2, data, len); - if (ret) { - cts_err("Get i2c print buf error"); - return; - } - data[len] = '\0'; - printk("CTS-FW_LOG %s", data); - cts_fw_log_show_finish(cts_dev); + max_len = cts_plat_get_max_fw_log_size(cts_dev->pdata); + data = cts_plat_get_fw_log_buf(cts_dev->pdata, max_len); + ret = + cts_fw_reg_readsb(cts_dev, CTS_DEVICE_FW_REG_TOUCH_INFO + 1, &len, + 1); + if (ret) { + cts_err("Get i2c print buf len error"); + return; + } + if (len >= max_len) { + len = max_len - 1; + } + ret = + cts_fw_reg_readsb(cts_dev, CTS_DEVICE_FW_REG_TOUCH_INFO + 2, data, + len); + if (ret) { + cts_err("Get i2c print buf error"); + return; + } + data[len] = '\0'; + printk("CTS-FW_LOG %s", data); + cts_fw_log_show_finish(cts_dev); } #endif int cts_irq_handler(struct cts_device *cts_dev) { - int ret; + int ret; - cts_dbg("Enter IRQ handler"); + cts_dbg("Enter IRQ handler"); - if (cts_dev->rtdata.program_mode) { - cts_err("IRQ triggered in program mode"); - return -EINVAL; - } + if (cts_dev->rtdata.program_mode) { + cts_err("IRQ triggered in program mode"); + return -EINVAL; + } - if (unlikely(cts_dev->rtdata.suspended)) { + if (unlikely(cts_dev->rtdata.suspended)) { #ifdef CFG_CTS_GESTURE - if (cts_dev->rtdata.gesture_wakeup_enabled) { - struct cts_device_gesture_info gesture_info; + if (cts_dev->rtdata.gesture_wakeup_enabled) { + struct cts_device_gesture_info gesture_info; - ret = cts_get_gesture_info(cts_dev, - &gesture_info, CFG_CTS_GESTURE_REPORT_TRACE); - if (ret) { - cts_warn("Get gesture info failed %d", ret); - //return ret; - } + ret = cts_get_gesture_info(cts_dev, + &gesture_info, + CFG_CTS_GESTURE_REPORT_TRACE); + if (ret) { + cts_warn("Get gesture info failed %d", ret); + //return ret; + } - /** - Issure another suspend with gesture wakeup command to device - * after get gesture info. - */ - cts_send_command(cts_dev, CTS_CMD_SUSPEND_WITH_GESTURE); + /** - Issure another suspend with gesture wakeup command to device + * after get gesture info. + */ + cts_send_command(cts_dev, CTS_CMD_SUSPEND_WITH_GESTURE); - ret = cts_plat_process_gesture_info(cts_dev->pdata, &gesture_info); - if (ret) { - cts_err("Process gesture info failed %d", ret); - return ret; - } - } else { - cts_warn("IRQ triggered while device suspended " - "without gesture wakeup enable"); - } + ret = + cts_plat_process_gesture_info(cts_dev->pdata, + &gesture_info); + if (ret) { + cts_err("Process gesture info failed %d", ret); + return ret; + } + } else { + cts_warn("IRQ triggered while device suspended " + "without gesture wakeup enable"); + } #endif /* CFG_CTS_GESTURE */ - } else { - struct cts_device_touch_info *touch_info; + } else { + struct cts_device_touch_info *touch_info; - touch_info = &cts_dev->pdata->touch_info; + touch_info = &cts_dev->pdata->touch_info; #ifdef CFG_CTS_FW_LOG_REDIRECT - ret = cts_fw_reg_readsb(cts_dev, CTS_DEVICE_FW_REG_TOUCH_INFO, touch_info, 1); - if (ret) { - cts_err("Get vkey_state failed %d", ret); - return ret; - } + ret = + cts_fw_reg_readsb(cts_dev, CTS_DEVICE_FW_REG_TOUCH_INFO, + touch_info, 1); + if (ret) { + cts_err("Get vkey_state failed %d", ret); + return ret; + } - if (touch_info->vkey_state == CTS_FW_LOG_REDIRECT_SIGN) { - if (cts_is_fw_log_redirect(cts_dev)) { - cts_show_fw_log(cts_dev); - } - return 0; - } + if (touch_info->vkey_state == CTS_FW_LOG_REDIRECT_SIGN) { + if (cts_is_fw_log_redirect(cts_dev)) { + cts_show_fw_log(cts_dev); + } + return 0; + } #endif - ret = cts_get_touchinfo(cts_dev, touch_info); - if (ret) { - cts_err("Get touch info failed %d", ret); - return ret; - } + ret = cts_get_touchinfo(cts_dev, touch_info); + if (ret) { + cts_err("Get touch info failed %d", ret); + return ret; + } - cts_dbg("Touch info: vkey_state %x, num_msg %u", - touch_info->vkey_state, touch_info->num_msg); - - ret = cts_plat_process_touch_msg(cts_dev->pdata, - touch_info->msgs, touch_info->num_msg); - if (ret) { - cts_err("Process touch msg failed %d", ret); - return ret; - } + cts_dbg("Touch info: vkey_state %x, num_msg %u", + touch_info->vkey_state, touch_info->num_msg); + ret = cts_plat_process_touch_msg(cts_dev->pdata, + touch_info->msgs, + touch_info->num_msg); + if (ret) { + cts_err("Process touch msg failed %d", ret); + return ret; + } #ifdef CONFIG_CTS_VIRTUALKEY - ret = cts_plat_process_vkey(cts_dev->pdata, touch_info->vkey_state); - if (ret) { - cts_err("Process vkey failed %d", ret); - return ret; - } + ret = + cts_plat_process_vkey(cts_dev->pdata, + touch_info->vkey_state); + if (ret) { + cts_err("Process vkey failed %d", ret); + return ret; + } #endif /* CONFIG_CTS_VIRTUALKEY */ - } + } - return 0; + return 0; } bool cts_is_device_suspended(const struct cts_device *cts_dev) { - return cts_dev->rtdata.suspended; + return cts_dev->rtdata.suspended; } int cts_suspend_device(struct cts_device *cts_dev) { - int ret; + int ret; - cts_info("Suspend device"); + cts_info("Suspend device"); - if (cts_dev->rtdata.suspended) { - cts_warn("Suspend device while already suspended"); - return 0; - } - if (cts_dev->rtdata.program_mode) { - cts_info("Quit programming mode before suspend"); - ret = cts_enter_normal_mode(cts_dev); - if (ret) { - cts_err("Failed to exit program mode before suspend:%d", ret); - return ret; - } - } - ret = cts_send_command(cts_dev, - cts_dev->rtdata.gesture_wakeup_enabled ? - CTS_CMD_SUSPEND_WITH_GESTURE : CTS_CMD_SUSPEND); + if (cts_dev->rtdata.suspended) { + cts_warn("Suspend device while already suspended"); + return 0; + } + if (cts_dev->rtdata.program_mode) { + cts_info("Quit programming mode before suspend"); + ret = cts_enter_normal_mode(cts_dev); + if (ret) { + cts_err("Failed to exit program mode before suspend:%d", + ret); + return ret; + } + } + ret = cts_send_command(cts_dev, + cts_dev->rtdata.gesture_wakeup_enabled ? + CTS_CMD_SUSPEND_WITH_GESTURE : CTS_CMD_SUSPEND); - if (ret){ - cts_err("Suspend device failed %d", ret); + if (ret) { + cts_err("Suspend device failed %d", ret); - return ret; - } + return ret; + } - cts_info("Device suspended ..."); - cts_dev->rtdata.suspended = true; +#ifdef CFG_CTS_HAS_RESET_PIN + //cts_plat_set_reset(cts_dev->pdata, 0); +#endif - return 0; + cts_info("Device suspended ..."); + cts_dev->rtdata.suspended = true; + + return 0; } int cts_resume_device(struct cts_device *cts_dev) { - int ret = 0; + int ret = 0; int retries = 3; - cts_info("Resume device"); + cts_info("Resume device"); - /* Check whether device is in normal mode */ + /* Check whether device is in normal mode */ while (--retries >= 0) { #ifdef CFG_CTS_HAS_RESET_PIN - cts_plat_reset_device(cts_dev->pdata); + cts_plat_reset_device(cts_dev->pdata); #endif cts_set_normal_addr(cts_dev); #ifdef CONFIG_CTS_I2C_HOST - if (cts_plat_is_i2c_online(cts_dev->pdata, CTS_DEV_NORMAL_MODE_I2CADDR)) + if (cts_plat_is_i2c_online + (cts_dev->pdata, CTS_DEV_NORMAL_MODE_I2CADDR)) #else - if (cts_plat_is_normal_mode(cts_dev->pdata)) + if (cts_plat_is_normal_mode(cts_dev->pdata)) #endif - { + { break; } } if (retries < 0) { - const struct cts_firmware *firmware; + const struct cts_firmware *firmware = NULL; - cts_info("Need update firmware when resume"); - firmware = cts_request_firmware(cts_dev->hwdata->hwid, - cts_dev->hwdata->fwid, 0); - if (firmware) { - ret = cts_update_firmware(cts_dev, firmware, true); - cts_release_firmware(firmware); + cts_info("Need update firmware when resume"); - if (ret) { - cts_err("Update default firmware failed %d", ret); - goto err_set_program_mode; - } - } else { - cts_err("Request default firmware failed %d, " - "please update manually!!", ret); +#ifdef CFG_CTS_FW_UPDATE_FILE_LOAD + if (cts_dev->config_fw_name[0] != '\0') { + firmware = cts_request_firmware_from_fs(cts_dev, + cts_dev->config_fw_name); + } +#else + firmware = cts_request_firmware(cts_dev, + cts_dev->hwdata->hwid, cts_dev->hwdata->fwid, 0); +#endif + if (firmware) { + ret = cts_update_firmware(cts_dev, firmware, false); + cts_release_firmware(firmware); - goto err_set_program_mode; - } - } + if (ret) { + cts_err("Update default firmware failed %d", + ret); + goto err_set_program_mode; + } + } else { + cts_err("Request default firmware failed %d, " + "please update manually!!", ret); + goto err_set_program_mode; + } + } #ifdef CONFIG_CTS_CHARGER_DETECT - if (cts_is_charger_exist(cts_dev)) { - cts_charger_plugin(cts_dev); - } + if (cts_is_charger_exist(cts_dev)) { + cts_charger_plugin(cts_dev); + } #endif /* CONFIG_CTS_CHARGER_DETECT */ #ifdef CONFIG_CTS_GLOVE - if (cts_is_glove_enabled(cts_dev)) { - cts_enter_glove_mode(cts_dev); - } + if (cts_is_glove_enabled(cts_dev)) { + cts_enter_glove_mode(cts_dev); + } #endif #ifdef CFG_CTS_FW_LOG_REDIRECT - if (cts_is_fw_log_redirect(cts_dev)) { - cts_enable_fw_log_redirect(cts_dev); - } + if (cts_is_fw_log_redirect(cts_dev)) { + cts_enable_fw_log_redirect(cts_dev); + } #endif - cts_dev->rtdata.suspended = false; - return 0; + cts_dev->rtdata.suspended = false; + return 0; err_set_program_mode: - cts_dev->rtdata.program_mode = true; - cts_dev->rtdata.slave_addr = CTS_DEV_PROGRAM_MODE_I2CADDR; - cts_dev->rtdata.addr_width = CTS_DEV_PROGRAM_MODE_ADDR_WIDTH; + cts_dev->rtdata.program_mode = true; + cts_dev->rtdata.slave_addr = CTS_DEV_PROGRAM_MODE_I2CADDR; + cts_dev->rtdata.addr_width = CTS_DEV_PROGRAM_MODE_ADDR_WIDTH; - return ret; + return ret; } bool cts_is_device_program_mode(const struct cts_device *cts_dev) { - return cts_dev->rtdata.program_mode; + return cts_dev->rtdata.program_mode; } static inline void cts_init_rtdata_with_normal_mode(struct cts_device *cts_dev) { - memset(&cts_dev->rtdata, 0, sizeof(cts_dev->rtdata)); + memset(&cts_dev->rtdata, 0, sizeof(cts_dev->rtdata)); - cts_set_normal_addr(cts_dev); - cts_dev->rtdata.suspended = false; - cts_dev->rtdata.updating = false; - cts_dev->rtdata.testing = false; - cts_dev->rtdata.fw_log_redirect_enabled = false; - cts_dev->rtdata.glove_mode_enabled = false; + cts_set_normal_addr(cts_dev); + cts_dev->rtdata.suspended = false; + cts_dev->rtdata.updating = false; + cts_dev->rtdata.testing = false; + cts_dev->rtdata.fw_log_redirect_enabled = false; + cts_dev->rtdata.glove_mode_enabled = false; } int cts_enter_program_mode(struct cts_device *cts_dev) { - const static u8 magic_num[] = {0xCC, 0x33, 0x55, 0x5A}; - u8 boot_mode; - int ret; + const static u8 magic_num[] = { 0xCC, 0x33, 0x55, 0x5A }; + u8 boot_mode; + int ret; - cts_info("Enter program mode"); - - if (cts_dev->rtdata.program_mode) { - cts_warn("Enter program mode while alredy in"); - //return 0; - } + cts_info("Enter program mode"); + if (cts_dev->rtdata.program_mode) { + cts_warn("Enter program mode while alredy in"); + //return 0; + } #ifdef CONFIG_CTS_I2C_HOST - ret = cts_plat_i2c_write(cts_dev->pdata, - CTS_DEV_PROGRAM_MODE_I2CADDR, magic_num, 4, 5, 10); - if (ret) { - cts_err("Write magic number to i2c_dev: 0x%02x failed %d", - CTS_DEV_PROGRAM_MODE_I2CADDR, ret); - return ret; - } + ret = cts_plat_i2c_write(cts_dev->pdata, + CTS_DEV_PROGRAM_MODE_I2CADDR, magic_num, 4, 5, + 10); + if (ret) { + cts_err("Write magic number to i2c_dev: 0x%02x failed %d", + CTS_DEV_PROGRAM_MODE_I2CADDR, ret); + return ret; + } - cts_set_program_addr(cts_dev); - /* Write i2c deglitch register */ - ret = cts_hw_reg_writeb_retry(cts_dev, 0x37001, 0x0F, 5, 1); - if (ret) { - cts_err("Write i2c deglitch register failed\n"); - // FALL through - } + cts_set_program_addr(cts_dev); + /* Write i2c deglitch register */ + ret = cts_hw_reg_writeb_retry(cts_dev, 0x37001, 0x0F, 5, 1); + if (ret) { + cts_err("Write i2c deglitch register failed\n"); + // FALL through + } #else - cts_set_program_addr(cts_dev); + cts_set_program_addr(cts_dev); cts_plat_reset_device(cts_dev->pdata); - ret = cts_plat_spi_write(cts_dev->pdata, - 0xcc, &magic_num[1], 3, 5, 10); + ret = cts_plat_spi_write(cts_dev->pdata, 0xcc, &magic_num[1], 3, 5, 10); if (ret) { cts_err("Write magic number to i2c_dev: 0x%02x failed %d", CTS_DEV_PROGRAM_MODE_SPIADDR, ret); return ret; } #endif /* CONFIG_CTS_I2C_HOST */ - ret = cts_get_dev_boot_mode(cts_dev, &boot_mode); - if (ret) { - cts_err("Read BOOT_MODE failed %d", ret); - return ret; - } - + ret = cts_get_dev_boot_mode(cts_dev, &boot_mode); + if (ret) { + cts_err("Read BOOT_MODE failed %d", ret); + return ret; + } #ifdef CONFIG_CTS_I2C_HOST - if (boot_mode != CTS_DEV_BOOT_MODE_I2C_PROGRAM) + if (boot_mode != CTS_DEV_BOOT_MODE_I2C_PROGRAM) #else if (boot_mode != CTS_DEV_BOOT_MODE_SPI_PROGRAM) #endif - { - cts_err("BOOT_MODE readback %u != I2C/SPI PROMGRAM mode", boot_mode); - return -EFAULT; - } + { + cts_err("BOOT_MODE readback %u != I2C/SPI PROMGRAM mode", + boot_mode); + return -EFAULT; + } - return 0; + return 0; } const char *cts_dev_boot_mode2str(u8 boot_mode) @@ -1894,32 +2040,33 @@ const char *cts_dev_boot_mode2str(u8 boot_mode) #define case_boot_mode(mode) \ case CTS_DEV_BOOT_MODE_ ## mode: return #mode "-BOOT" - switch (boot_mode) { - case_boot_mode(FLASH); - case_boot_mode(I2C_PROGRAM); - case_boot_mode(SRAM); + switch (boot_mode) { + case_boot_mode(FLASH); + case_boot_mode(I2C_PROGRAM); + case_boot_mode(SRAM); case_boot_mode(SPI_PROGRAM); - default: return "INVALID"; - } + default: + return "INVALID"; + } #undef case_boot_mode } int cts_enter_normal_mode(struct cts_device *cts_dev) { - int ret = 0; - u8 boot_mode; + int ret = 0; + u8 boot_mode; int retries; - u16 fwid = CTS_DEV_FWID_INVALID; - u8 auto_boot = 0; - u8 first_boot = 1; + u16 fwid = CTS_DEV_FWID_INVALID; + u8 auto_boot = 0; + u8 first_boot = 1; - cts_info("Enter normal mode"); + cts_info("Enter normal mode"); - if (!cts_dev->rtdata.program_mode) { - cts_warn("Enter normal mode while already in"); - return 0; - } + if (!cts_dev->rtdata.program_mode) { + cts_warn("Enter normal mode while already in"); + return 0; + } if (cts_dev->rtdata.has_flash) { auto_boot = 1; @@ -1929,623 +2076,658 @@ int cts_enter_normal_mode(struct cts_device *cts_dev) auto_boot = 1; } #endif - for(retries = 5; retries >= 0; retries--) { - if (first_boot == 1 || auto_boot == 0) { - cts_set_program_addr(cts_dev); - ret = cts_set_dev_boot_mode(cts_dev, CTS_DEV_BOOT_MODE_SRAM); - if (ret) { - cts_err("Set BOOT_MODE to SRAM failed %d, try to reset device", ret); - } - mdelay(30); - } + for (retries = 5; retries >= 0; retries--) { + if (first_boot == 1 || auto_boot == 0) { + cts_set_program_addr(cts_dev); + ret = + cts_set_dev_boot_mode(cts_dev, + CTS_DEV_BOOT_MODE_SRAM); + if (ret) { + cts_err + ("Set BOOT_MODE to SRAM failed %d, try to reset device", + ret); + } + mdelay(30); + } first_boot = 0; #ifdef CONFIG_CTS_I2C_HOST - if (cts_plat_is_i2c_online(cts_dev->pdata, CTS_DEV_NORMAL_MODE_I2CADDR)) { - cts_set_normal_addr(cts_dev); - } + if (cts_plat_is_i2c_online + (cts_dev->pdata, CTS_DEV_NORMAL_MODE_I2CADDR)) { + cts_set_normal_addr(cts_dev); + } #else - cts_set_normal_addr(cts_dev); + cts_set_normal_addr(cts_dev); #endif - ret = cts_get_dev_boot_mode(cts_dev, &boot_mode); - if (ret) { - cts_err("Get BOOT_MODE failed %d", ret); - } - if (boot_mode != CTS_DEV_BOOT_MODE_SRAM) { - cts_err("Curr boot mode %u(%s) != SRAM_BOOT", - boot_mode, cts_dev_boot_mode2str(boot_mode)); - } - else { - break; - } + ret = cts_get_dev_boot_mode(cts_dev, &boot_mode); + if (ret) { + cts_err("Get BOOT_MODE failed %d", ret); + } + if (boot_mode != CTS_DEV_BOOT_MODE_SRAM) { + cts_err("Curr boot mode %u(%s) != SRAM_BOOT", + boot_mode, cts_dev_boot_mode2str(boot_mode)); + } else { + break; + } ret = cts_get_fwid(cts_dev, &fwid); if (ret) { - cts_err("Get firmware id failed %d, retries %d", ret, retries); + cts_err("Get firmware id failed %d, retries %d", ret, + retries); } else { - if (fwid == CTS_DEV_FWID_ICNL9911 || fwid == CTS_DEV_FWID_ICNL9911S) - { - cts_info("Get firmware id successful 0x%02x", fwid); + if (fwid == CTS_DEV_FWID_ICNL9911 + || fwid == CTS_DEV_FWID_ICNL9911S) { + cts_info("Get firmware id successful 0x%02x", + fwid); break; } } - cts_plat_reset_device(cts_dev->pdata); + cts_plat_reset_device(cts_dev->pdata); } if (retries >= 0) { - ret = cts_init_fwdata(cts_dev); - if (ret) { - cts_err("Device init firmware data failed %d", ret); - return ret; - } - return 0; - } - cts_set_program_addr(cts_dev); - return ret; + ret = cts_init_fwdata(cts_dev); + if (ret) { + cts_err("Device init firmware data failed %d", ret); + return ret; + } + return 0; + } + cts_set_program_addr(cts_dev); + return ret; } bool cts_is_device_enabled(const struct cts_device *cts_dev) { - return cts_dev->enabled; + return cts_dev->enabled; } int cts_start_device(struct cts_device *cts_dev) { +#if defined(CONFIG_CTS_ESD_PROTECTION) || defined(CONFIG_CTS_CHARGER_DETECT) + struct chipone_ts_data *cts_data = + container_of(cts_dev, struct chipone_ts_data, cts_dev); +#endif + int ret; + + cts_info("Start device..."); + + if (cts_is_device_enabled(cts_dev)) { + cts_warn("Start device while already started"); + return 0; + } #ifdef CONFIG_CTS_ESD_PROTECTION - struct chipone_ts_data *cts_data = - container_of(cts_dev, struct chipone_ts_data, cts_dev); -#endif /* CONFIG_CTS_ESD_PROTECTION */ - int ret; - - cts_info("Start device..."); - - if (cts_is_device_enabled(cts_dev)) { - cts_warn("Start device while already started"); - return 0; - } - -#ifdef CONFIG_CTS_ESD_PROTECTION - cts_enable_esd_protection(cts_data); + cts_enable_esd_protection(cts_data); #endif /* CONFIG_CTS_ESD_PROTECTION */ - if ((ret = cts_plat_enable_irq(cts_dev->pdata)) < 0) { - cts_err("Enable IRQ failed %d", ret); - return ret; - } +#ifdef CONFIG_CTS_CHARGER_DETECT + cts_start_charger_detect(cts_data); +#endif /* CONFIG_CTS_CHARGER_DETECT */ - cts_dev->enabled = true; + ret = cts_plat_enable_irq(cts_dev->pdata); + if (ret < 0) { + cts_err("Enable IRQ failed %d", ret); + return ret; + } - cts_info("Start device successfully"); + cts_dev->enabled = true; - return 0; + cts_info("Start device successfully"); + + return 0; } int cts_stop_device(struct cts_device *cts_dev) { - struct chipone_ts_data *cts_data = - container_of(cts_dev, struct chipone_ts_data, cts_dev); - int ret; + struct chipone_ts_data *cts_data = + container_of(cts_dev, struct chipone_ts_data, cts_dev); + int ret; - cts_info("Stop device..."); + cts_info("Stop device..."); - if (!cts_is_device_enabled(cts_dev)) { - cts_warn("Stop device while halted"); - return 0; - } + if (!cts_is_device_enabled(cts_dev)) { + cts_warn("Stop device while halted"); + return 0; + } - if (cts_is_firmware_updating(cts_dev)) { - cts_warn("Stop device while firmware updating, please try again"); - return -EAGAIN; - } + if (cts_is_firmware_updating(cts_dev)) { + cts_warn + ("Stop device while firmware updating, please try again"); + return -EAGAIN; + } - if ((ret = cts_plat_disable_irq(cts_dev->pdata)) < 0) { - cts_err("Disable IRQ failed %d", ret); - return ret; - } + ret = cts_plat_disable_irq(cts_dev->pdata); + if (ret < 0) { + cts_err("Disable IRQ failed %d", ret); + return ret; + } - cts_dev->enabled = false; + cts_dev->enabled = false; #ifdef CONFIG_CTS_ESD_PROTECTION - cts_disable_esd_protection(cts_data); + cts_disable_esd_protection(cts_data); #endif /* CONFIG_CTS_ESD_PROTECTION */ - flush_workqueue(cts_data->workqueue); +#ifdef CONFIG_CTS_CHARGER_DETECT + cts_stop_charger_detect(cts_data); +#endif /* CONFIG_CTS_CHARGER_DETECT */ - ret = cts_plat_release_all_touch(cts_dev->pdata); - if (ret) { - cts_err("Release all touch failed %d", ret); - return ret; +#ifndef CONFIG_GENERIC_HARDIRQS + if (work_pending(&cts_data->pdata->ts_irq_work)) { + cts_warn("IRQ work is pending .... flush it"); + flush_work(&cts_data->pdata->ts_irq_work); + } else { + cts_info("None IRQ work is pending"); } +#endif + cts_info("Flush workqueue..."); + flush_workqueue(cts_data->workqueue); + ret = cts_plat_release_all_touch(cts_dev->pdata); + if (ret) { + cts_err("Release all touch failed %d", ret); + return ret; + } #ifdef CONFIG_CTS_VIRTUALKEY - ret = cts_plat_release_all_vkey(cts_dev->pdata); - if (ret) { - cts_err("Release all vkey failed %d", ret); - return ret; - } + ret = cts_plat_release_all_vkey(cts_dev->pdata); + if (ret) { + cts_err("Release all vkey failed %d", ret); + return ret; + } #endif /* CONFIG_CTS_VIRTUALKEY */ - return 0; + return 0; } #ifdef CONFIG_CTS_ESD_PROTECTION int cts_start_device_esdrecover(struct cts_device *cts_dev) { #ifdef CONFIG_CTS_ESD_PROTECTION - struct chipone_ts_data *cts_data = - container_of(cts_dev, struct chipone_ts_data, cts_dev); + struct chipone_ts_data *cts_data = + container_of(cts_dev, struct chipone_ts_data, cts_dev); #endif /* CONFIG_CTS_ESD_PROTECTION */ - int ret; + int ret; - cts_info("Start device..."); + cts_info("Start device..."); - if (cts_is_device_enabled(cts_dev)) { - cts_warn("Start device while already started"); - return 0; - } + if (cts_is_device_enabled(cts_dev)) { + cts_warn("Start device while already started"); + return 0; + } - if ((ret = cts_plat_enable_irq(cts_dev->pdata)) < 0) { - cts_err("Enable IRQ failed %d", ret); - return ret; - } + ret = cts_plat_enable_irq(cts_dev->pdata); + if (ret < 0) { + cts_err("Enable IRQ failed %d", ret); + return ret; + } - cts_dev->enabled = true; + cts_dev->enabled = true; - cts_info("Start device successfully"); + cts_info("Start device successfully"); - return 0; + return 0; } int cts_stop_device_esdrecover(struct cts_device *cts_dev) { - struct chipone_ts_data *cts_data = - container_of(cts_dev, struct chipone_ts_data, cts_dev); - int ret; + struct chipone_ts_data *cts_data = + container_of(cts_dev, struct chipone_ts_data, cts_dev); + int ret; - cts_info("Stop device..."); + cts_info("Stop device..."); - if (!cts_is_device_enabled(cts_dev)) { - cts_warn("Stop device while halted"); - return 0; - } + if (!cts_is_device_enabled(cts_dev)) { + cts_warn("Stop device while halted"); + return 0; + } - if (cts_is_firmware_updating(cts_dev)) { - cts_warn("Stop device while firmware updating, please try again"); - return -EAGAIN; - } + if (cts_is_firmware_updating(cts_dev)) { + cts_warn + ("Stop device while firmware updating, please try again"); + return -EAGAIN; + } - if ((ret = cts_plat_disable_irq(cts_dev->pdata)) < 0) { - cts_err("Disable IRQ failed %d", ret); - return ret; - } + ret = cts_plat_disable_irq(cts_dev->pdata); + if (ret < 0) { + cts_err("Disable IRQ failed %d", ret); + return ret; + } - cts_dev->enabled = false; + cts_dev->enabled = false; - flush_workqueue(cts_data->workqueue); - - ret = cts_plat_release_all_touch(cts_dev->pdata); - if (ret) { - cts_err("Release all touch failed %d", ret); - return ret; - } + flush_workqueue(cts_data->workqueue); + ret = cts_plat_release_all_touch(cts_dev->pdata); + if (ret) { + cts_err("Release all touch failed %d", ret); + return ret; + } #ifdef CONFIG_CTS_VIRTUALKEY - ret = cts_plat_release_all_vkey(cts_dev->pdata); - if (ret) { - cts_err("Release all vkey failed %d", ret); - return ret; - } + ret = cts_plat_release_all_vkey(cts_dev->pdata); + if (ret) { + cts_err("Release all vkey failed %d", ret); + return ret; + } #endif /* CONFIG_CTS_VIRTUALKEY */ - return 0; + return 0; } #endif bool cts_is_fwid_valid(u16 fwid) { - int i; + int i; - for (i = 0; i < ARRAY_SIZE(cts_device_hwdatas); i++) { - if (cts_device_hwdatas[i].fwid == fwid) { - return true; - } - } + for (i = 0; i < ARRAY_SIZE(cts_device_hwdatas); i++) { + if (cts_device_hwdatas[i].fwid == fwid) { + return true; + } + } - return false; + return false; } static bool cts_is_hwid_valid(u32 hwid) { - int i; + int i; - for (i = 0; i < ARRAY_SIZE(cts_device_hwdatas); i++) { - if (cts_device_hwdatas[i].hwid == hwid) { - return true; - } - } + for (i = 0; i < ARRAY_SIZE(cts_device_hwdatas); i++) { + if (cts_device_hwdatas[i].hwid == hwid) { + return true; + } + } - return false; + return false; } int cts_get_fwid(struct cts_device *cts_dev, u16 *fwid) { - int ret; + int ret; - cts_info("Get device firmware id"); + cts_info("Get device firmware id"); - if (cts_dev->hwdata) { - *fwid = cts_dev->hwdata->fwid; - return 0; - } + if (cts_dev->hwdata) { + *fwid = cts_dev->hwdata->fwid; + return 0; + } - if (cts_dev->rtdata.program_mode) { - cts_err("Get device firmware id while in program mode"); - ret = -ENODEV; - goto err_out; - } + if (cts_dev->rtdata.program_mode) { + cts_err("Get device firmware id while in program mode"); + ret = -ENODEV; + goto err_out; + } - ret = cts_fw_reg_readw_retry(cts_dev, - CTS_DEVICE_FW_REG_CHIP_TYPE, fwid, 5, 1); - if (ret) { - goto err_out; - } + ret = cts_fw_reg_readw_retry(cts_dev, + CTS_DEVICE_FW_REG_CHIP_TYPE, fwid, 5, 1); + if (ret) { + goto err_out; + } - *fwid = be16_to_cpu(*fwid); + *fwid = be16_to_cpu(*fwid); - cts_info("Device firmware id: %04x", *fwid); + cts_info("Device firmware id: %04x", *fwid); - if (!cts_is_fwid_valid(*fwid)) { - cts_warn("Get invalid firmware id %04x", *fwid); - ret = -EINVAL; - goto err_out; - } + if (!cts_is_fwid_valid(*fwid)) { + cts_warn("Get invalid firmware id %04x", *fwid); + ret = -EINVAL; + goto err_out; + } - return 0; + return 0; err_out: - *fwid = CTS_DEV_FWID_INVALID; - return ret; + *fwid = CTS_DEV_FWID_INVALID; + return ret; } int cts_get_hwid(struct cts_device *cts_dev, u32 *hwid) { - int ret; + int ret; - cts_info("Get device hardware id"); + cts_info("Get device hardware id"); - if (cts_dev->hwdata) { - *hwid = cts_dev->hwdata->hwid; - return 0; - } + if (cts_dev->hwdata) { + *hwid = cts_dev->hwdata->hwid; + return 0; + } - cts_info("Device hardware data not initialized, try to read from register"); + cts_info + ("Device hardware data not initialized, try to read from register"); - if (!cts_dev->rtdata.program_mode) { - ret = cts_enter_program_mode(cts_dev); - if (ret) { - cts_err("Enter program mode failed %d", ret); - goto err_out; - } - } + if (!cts_dev->rtdata.program_mode) { + ret = cts_enter_program_mode(cts_dev); + if (ret) { + cts_err("Enter program mode failed %d", ret); + goto err_out; + } + } - ret = cts_hw_reg_readl_retry(cts_dev, CTS_DEV_HW_REG_HARDWARE_ID, hwid, 5, 0); - if (ret) { - goto err_out; - } + ret = + cts_hw_reg_readl_retry(cts_dev, CTS_DEV_HW_REG_HARDWARE_ID, hwid, 5, + 0); + if (ret) { + goto err_out; + } - *hwid = le32_to_cpu(*hwid); - *hwid &= 0XFFFFFFF0; - cts_info("Device hardware id: %04x", *hwid); + *hwid = le32_to_cpu(*hwid); + *hwid &= 0XFFFFFFF0; + cts_info("Device hardware id: %04x", *hwid); - if (!cts_is_hwid_valid(*hwid)) { - cts_warn("Device hardware id %04x invalid", *hwid); - ret = -EINVAL; - goto err_out; - } + if (!cts_is_hwid_valid(*hwid)) { + cts_warn("Device hardware id %04x invalid", *hwid); + ret = -EINVAL; + goto err_out; + } - return 0; + return 0; err_out: - *hwid = CTS_DEV_HWID_INVALID; - return ret; + *hwid = CTS_DEV_HWID_INVALID; + return ret; } int cts_probe_device(struct cts_device *cts_dev) { - int ret, retries = 0; - u16 fwid = CTS_DEV_FWID_INVALID; - u32 hwid = CTS_DEV_HWID_INVALID; - u16 device_fw_ver = 0; - const struct cts_firmware *firmware = NULL; - - cts_info("Probe device"); + int ret, retries = 0; + u16 fwid = CTS_DEV_FWID_INVALID; + u32 hwid = CTS_DEV_HWID_INVALID; + u16 device_fw_ver = 0; + cts_info("Probe device"); read_fwid: #ifdef CONFIG_CTS_I2C_HOST - if (!cts_plat_is_i2c_online(cts_dev->pdata, CTS_DEV_NORMAL_MODE_I2CADDR)) { - cts_warn("Normal mode i2c addr is offline"); - } else + if (!cts_plat_is_i2c_online + (cts_dev->pdata, CTS_DEV_NORMAL_MODE_I2CADDR)) { + cts_warn("Normal mode i2c addr is offline"); + } else #else - if (!cts_plat_is_normal_mode(cts_dev->pdata)) { - cts_warn("Normal mode spi addr is offline"); - } else + if (!cts_plat_is_normal_mode(cts_dev->pdata)) { + cts_warn("Normal mode spi addr is offline"); + } else #endif - { - cts_init_rtdata_with_normal_mode(cts_dev); - ret = cts_get_fwid(cts_dev, &fwid); - if (ret) { - cts_err("Get firmware id failed %d, retries %d", ret, retries); - } else { - ret = cts_fw_reg_readw_retry(cts_dev, - CTS_DEVICE_FW_REG_VERSION, &device_fw_ver, 5, 0); - if (ret) { - cts_err("Read firmware version failed %d", ret); - device_fw_ver = 0; - // TODO: Handle this error - } else { - device_fw_ver = be16_to_cpu(device_fw_ver); - cts_info("Device firmware version: %04x", device_fw_ver); - } - goto init_hwdata; - } - } + { + cts_init_rtdata_with_normal_mode(cts_dev); + ret = cts_get_fwid(cts_dev, &fwid); + if (ret) { + cts_err("Get firmware id failed %d, retries %d", ret, + retries); + } else { + ret = cts_fw_reg_readw_retry(cts_dev, + CTS_DEVICE_FW_REG_VERSION, + &device_fw_ver, 5, 0); + if (ret) { + cts_err("Read firmware version failed %d", ret); + device_fw_ver = 0; + // TODO: Handle this error + } else { + device_fw_ver = be16_to_cpu(device_fw_ver); + cts_info("Device firmware version: %04x", + device_fw_ver); + } + goto init_hwdata; + } + } /** - Try to read hardware id, - it will enter program mode as normal */ - ret = cts_get_hwid(cts_dev, &hwid); - if (ret || hwid == CTS_DEV_HWID_INVALID) { - retries++; + it will enter program mode as normal */ + ret = cts_get_hwid(cts_dev, &hwid); + if (ret || hwid == CTS_DEV_HWID_INVALID) { + retries++; - cts_err("Get hardware id failed %d retries %d", ret, retries); + cts_err("Get hardware id failed %d retries %d", ret, retries); - if (retries < 3) { - cts_plat_reset_device(cts_dev->pdata); - goto read_fwid; - } else { - return -ENODEV; - } - } + if (retries < 3) { + cts_plat_reset_device(cts_dev->pdata); + goto read_fwid; + } else { + return -ENODEV; + } + } init_hwdata: - ret = cts_init_device_hwdata(cts_dev, hwid, fwid); - if (ret) { - cts_err("Device hwid: %06x fwid: %04x not found", hwid, fwid); - return -ENODEV; - } + ret = cts_init_device_hwdata(cts_dev, hwid, fwid); + if (ret) { + cts_err("Device hwid: %06x fwid: %04x not found", hwid, fwid); + return -ENODEV; + } +#if 0 #ifdef CFG_CTS_FIRMWARE_FORCE_UPDATE - cts_warn("Force update firmware"); - firmware = cts_request_firmware(CTS_DEV_HWID_ANY, CTS_DEV_FWID_ANY, 0); + cts_warn("Force update firmware"); + firmware = cts_request_firmware(cts_dev, + CTS_DEV_HWID_ANY, CTS_DEV_FWID_ANY, 0); #else /* CFG_CTS_FIRMWARE_FORCE_UPDATE */ - firmware = cts_request_firmware(hwid, fwid, device_fw_ver); + firmware = cts_request_firmware(cts_dev, hwid, fwid, device_fw_ver); #endif /* CFG_CTS_FIRMWARE_FORCE_UPDATE */ - - retries = 0; + retries = 0; update_firmware: - if (firmware) { - ++retries; - ret = cts_update_firmware(cts_dev, firmware, true); - if (ret) { - cts_err("Update firmware failed %d retries %d", ret, retries); + if (firmware) { + ++retries; + ret = cts_update_firmware(cts_dev, firmware, true); + if (ret) { + cts_err("Update firmware failed %d retries %d", ret, + retries); - if (retries < 3) { - cts_plat_reset_device(cts_dev->pdata); - goto update_firmware; - } else { - cts_release_firmware(firmware); - return ret; - } - } else { - cts_release_firmware(firmware); - } - } else { - if (fwid == CTS_DEV_FWID_INVALID) { - /* Device without firmware running && no updatable firmware found */ - return -ENODEV; - } else { - ret = cts_init_fwdata(cts_dev); - if (ret) { - cts_err("Device init firmware data failed %d", ret); - return ret; - } - } - } - - return 0; + if (retries < 3) { + cts_plat_reset_device(cts_dev->pdata); + goto update_firmware; + } + } + cts_release_firmware(firmware); + } else { + if (fwid != CTS_DEV_FWID_INVALID) { + ret = cts_init_fwdata(cts_dev); + if (ret) { + cts_err("Device init firmware data failed %d", ret); + } + } + } +#endif + return 0; } #ifdef CFG_CTS_GESTURE void cts_enable_gesture_wakeup(struct cts_device *cts_dev) { - cts_info("Enable gesture wakeup"); - cts_dev->rtdata.gesture_wakeup_enabled = true; + cts_info("Enable gesture wakeup"); + cts_dev->rtdata.gesture_wakeup_enabled = true; } void cts_disable_gesture_wakeup(struct cts_device *cts_dev) { - cts_info("Disable gesture wakeup"); - cts_dev->rtdata.gesture_wakeup_enabled = false; + cts_info("Disable gesture wakeup"); + cts_dev->rtdata.gesture_wakeup_enabled = false; } bool cts_is_gesture_wakeup_enabled(const struct cts_device *cts_dev) { - return cts_dev->rtdata.gesture_wakeup_enabled; + return cts_dev->rtdata.gesture_wakeup_enabled; } int cts_get_gesture_info(const struct cts_device *cts_dev, - void *gesture_info, bool trace_point) + void *gesture_info, bool trace_point) { - int ret; + int ret; - cts_info("Get gesture info"); + cts_info("Get gesture info"); - if (cts_dev->rtdata.program_mode) { - cts_warn("Get gesture info in program mode"); - return -ENODEV; - } + if (cts_dev->rtdata.program_mode) { + cts_warn("Get gesture info in program mode"); + return -ENODEV; + } - if (!cts_dev->rtdata.suspended) { - cts_warn("Get gesture info while not suspended"); - return -ENODEV; - } + if (!cts_dev->rtdata.suspended) { + cts_warn("Get gesture info while not suspended"); + return -ENODEV; + } - if (!cts_dev->rtdata.gesture_wakeup_enabled) { - cts_warn("Get gesture info while gesture wakeup not enabled"); - return -ENODEV; - } + if (!cts_dev->rtdata.gesture_wakeup_enabled) { + cts_warn("Get gesture info while gesture wakeup not enabled"); + return -ENODEV; + } - ret = cts_fw_reg_readsb(cts_dev, - CTS_DEVICE_FW_REG_GESTURE_INFO, gesture_info, 2); - if(ret) { - cts_err("Read gesture info header failed %d", ret); - return ret; - } + ret = cts_fw_reg_readsb(cts_dev, + CTS_DEVICE_FW_REG_GESTURE_INFO, gesture_info, + 2); + if (ret) { + cts_err("Read gesture info header failed %d", ret); + return ret; + } - if (trace_point) { - ret = cts_fw_reg_readsb(cts_dev, CTS_DEVICE_FW_REG_GESTURE_INFO + 2, - gesture_info + 2, - (((u8 *)gesture_info))[1] * sizeof(struct cts_device_gesture_point)); - if(ret) { - cts_err("Read gesture trace points failed %d", ret); - return ret; - } - } + if (trace_point) { + ret = + cts_fw_reg_readsb(cts_dev, + CTS_DEVICE_FW_REG_GESTURE_INFO + 2, + gesture_info + 2, + (((u8 *) gesture_info))[1] * + sizeof(struct cts_device_gesture_point)); + if (ret) { + cts_err("Read gesture trace points failed %d", ret); + return ret; + } + } - return 0; + return 0; } #endif /* CFG_CTS_GESTURE */ #ifdef CONFIG_CTS_ESD_PROTECTION static void cts_esd_protection_work(struct work_struct *work) { - struct chipone_ts_data *cts_data; - int ret; + struct chipone_ts_data *cts_data; + int ret; - cts_info("ESD protection work"); - cts_data = container_of(work, struct chipone_ts_data, esd_work.work); - cts_lock_device(&cts_data->cts_dev); + cts_info("ESD protection work"); + cts_data = container_of(work, struct chipone_ts_data, esd_work.work); + cts_lock_device(&cts_data->cts_dev); #ifdef CONFIG_CTS_I2C_HOST - if (!cts_plat_is_i2c_online(cts_data->pdata, CTS_DEV_NORMAL_MODE_I2CADDR)) + if (!cts_plat_is_i2c_online + (cts_data->pdata, CTS_DEV_NORMAL_MODE_I2CADDR)) #else - if (!cts_plat_is_normal_mode(cts_data->pdata)) + if (!cts_plat_is_normal_mode(cts_data->pdata)) #endif - { - cts_data->esd_check_fail_cnt++; - /*reset chip next time*/ - if ((cts_data->esd_check_fail_cnt % 2) == 0) { - cts_err("ESD protection read normal mode failed, reset chip!"); - ret = cts_plat_reset_device(cts_data->pdata); - if (ret) { - cts_err("ESD protection reset chip failed %d", ret); - } - } - } else { - cts_data->esd_check_fail_cnt = 0; - } + { + cts_data->esd_check_fail_cnt++; + /*reset chip next time */ + if ((cts_data->esd_check_fail_cnt % 2) == 0) { + cts_err + ("ESD protection read normal mode failed, reset chip!"); + ret = cts_plat_reset_device(cts_data->pdata); + if (ret) { + cts_err("ESD protection reset chip failed %d", + ret); + } + } + } else { + cts_data->esd_check_fail_cnt = 0; + } - if (cts_data->esd_check_fail_cnt >= CFG_CTS_ESD_FAILED_CONFIRM_CNT) { - const struct cts_firmware *firmware; + if (cts_data->esd_check_fail_cnt >= CFG_CTS_ESD_FAILED_CONFIRM_CNT) { + const struct cts_firmware *firmware; - cts_warn("ESD protection check failed, update firmware!!!"); - cts_stop_device_esdrecover(&cts_data->cts_dev); - firmware = cts_request_firmware(cts_data->cts_dev.hwdata->hwid, - cts_data->cts_dev.hwdata->fwid, 0); - if (firmware) { - cts_unlock_device(&cts_data->cts_dev); - ret = cts_update_firmware(&cts_data->cts_dev, firmware, true); - cts_lock_device(&cts_data->cts_dev); - cts_release_firmware(firmware); + cts_warn("ESD protection check failed, update firmware!!!"); + cts_stop_device_esdrecover(&cts_data->cts_dev); + firmware = cts_request_firmware(&cts_data->cts_dev, + cts_data->cts_dev.hwdata->hwid, + cts_data->cts_dev.hwdata->fwid, + 0); + if (firmware) { + ret = + cts_update_firmware(&cts_data->cts_dev, firmware, + true); + cts_release_firmware(firmware); - if (ret) { - cts_err("Update default firmware failed %d", ret); - } - } else { - cts_err("Request default firmware failed %d, " - "please update manually!!", ret); - } - cts_start_device_esdrecover(&cts_data->cts_dev); - cts_data->esd_check_fail_cnt = 0; - } + if (ret) { + cts_err("Update default firmware failed %d", + ret); + } + } else { + cts_err("Request default firmware failed %d, " + "please update manually!!", ret); + } + cts_start_device_esdrecover(&cts_data->cts_dev); + cts_data->esd_check_fail_cnt = 0; + } queue_delayed_work(cts_data->esd_workqueue, - &cts_data->esd_work, CFG_CTS_ESD_PROTECTION_CHECK_PERIOD); + &cts_data->esd_work, + CFG_CTS_ESD_PROTECTION_CHECK_PERIOD); - cts_unlock_device(&cts_data->cts_dev); + cts_unlock_device(&cts_data->cts_dev); } void cts_enable_esd_protection(struct chipone_ts_data *cts_data) { - if (cts_data->esd_workqueue && !cts_data->esd_enabled) { - cts_info("ESD protection enable"); + if (cts_data->esd_workqueue && !cts_data->esd_enabled) { + cts_info("ESD protection enable"); - cts_data->esd_enabled = true; - cts_data->esd_check_fail_cnt = 0; - queue_delayed_work(cts_data->esd_workqueue, - &cts_data->esd_work, CFG_CTS_ESD_PROTECTION_CHECK_PERIOD); - } + cts_data->esd_enabled = true; + cts_data->esd_check_fail_cnt = 0; + queue_delayed_work(cts_data->esd_workqueue, + &cts_data->esd_work, + CFG_CTS_ESD_PROTECTION_CHECK_PERIOD); + } } void cts_disable_esd_protection(struct chipone_ts_data *cts_data) { - if (cts_data->esd_workqueue && cts_data->esd_enabled) { - cts_info("ESD protection disable"); + if (cts_data->esd_workqueue && cts_data->esd_enabled) { + cts_info("ESD protection disable"); - cts_data->esd_enabled = false; - cancel_delayed_work(&cts_data->esd_work); - flush_workqueue(cts_data->esd_workqueue); - } + cts_data->esd_enabled = false; + cancel_delayed_work(&cts_data->esd_work); + flush_workqueue(cts_data->esd_workqueue); + } } void cts_init_esd_protection(struct chipone_ts_data *cts_data) { - cts_info("Init ESD protection"); + cts_info("Init ESD protection"); - INIT_DELAYED_WORK(&cts_data->esd_work, cts_esd_protection_work); + INIT_DELAYED_WORK(&cts_data->esd_work, cts_esd_protection_work); - cts_data->esd_enabled = false; - cts_data->esd_check_fail_cnt = 0; + cts_data->esd_enabled = false; + cts_data->esd_check_fail_cnt = 0; } void cts_deinit_esd_protection(struct chipone_ts_data *cts_data) { - cts_info("De-Init ESD protection"); + cts_info("De-Init ESD protection"); - if (cts_data->esd_workqueue && cts_data->esd_enabled) { - cts_data->esd_enabled = false; - cancel_delayed_work(&cts_data->esd_work); - } + if (cts_data->esd_workqueue && cts_data->esd_enabled) { + cts_data->esd_enabled = false; + cancel_delayed_work(&cts_data->esd_work); + } } #endif /* CONFIG_CTS_ESD_PROTECTION */ #ifdef CONFIG_CTS_GLOVE int cts_enter_glove_mode(const struct cts_device *cts_dev) { - cts_info("Enter glove mode"); + cts_info("Enter glove mode"); - ret = cts_fw_reg_writeb(cts_dev, 0x8000 + 149, 1); - if (ret) { - cts_err("Enable Glove mode err"); - } - else { - cts_dev->rtdata.glove_mode_enabled = true; - } - return ret; + ret = cts_fw_reg_writeb(cts_dev, 0x8000 + 149, 1); + if (ret) { + cts_err("Enable Glove mode err"); + } else { + cts_dev->rtdata.glove_mode_enabled = true; + } + return ret; } int cts_exit_glove_mode(const struct cts_device *cts_dev) { - cts_info("Exit glove mode"); + cts_info("Exit glove mode"); - ret = cts_fw_reg_writeb(cts_dev, 0x8000 + 149, 0); - if (ret) { - cts_err("Exit Glove mode err"); - } - else { - cts_dev->rtdata.glove_mode_enabled = false; - } - return ret; + ret = cts_fw_reg_writeb(cts_dev, 0x8000 + 149, 0); + if (ret) { + cts_err("Exit Glove mode err"); + } else { + cts_dev->rtdata.glove_mode_enabled = false; + } + return ret; } int cts_is_glove_enabled(const struct cts_device *cts_dev) { - return cts_dev->rtdata.glove_mode_enabled; + return cts_dev->rtdata.glove_mode_enabled; } #endif /* CONFIG_CTS_GLOVE */ @@ -2553,105 +2735,160 @@ int cts_is_glove_enabled(const struct cts_device *cts_dev) #ifdef CONFIG_CTS_CHARGER_DETECT bool cts_is_charger_exist(struct cts_device *cts_dev) { - return cts_dev->rtdata.charger_exist; + struct chipone_ts_data *cts_data; + bool attached = false; + int ret; + + cts_data = container_of(cts_dev, struct chipone_ts_data, cts_dev); + + ret = cts_is_charger_attached(cts_data, &attached); + if (ret) { + cts_err("Get charger state failed %d", ret); + } + + cts_dev->rtdata.charger_exist = attached; + + return attached; } int cts_charger_plugin(struct cts_device *cts_dev) { - int ret; + int ret; - cts_info("Charger plugin"); - ret = cts_send_command(cts_dev, CTS_CMD_CHARGER_PLUG_IN); - if (ret) { - cts_err("Send CMD_CHARGER_PLUG_IN failed %d", ret); - } else { - cts_dev->rtdata.charger_exist = true; - } - return 0; + cts_info("Set dev charger plugin"); + ret = cts_send_command(cts_dev, CTS_CMD_CHARGER_PLUG_IN); + if (ret) { + cts_err("Send CMD_CHARGER_PLUG_IN failed %d", ret); + } else { + cts_dev->rtdata.charger_exist = true; + } + return 0; } int cts_charger_plugout(struct cts_device *cts_dev) { - int ret; + int ret; - cts_info("Charger plugout"); - ret = cts_send_command(cts_dev, CTS_CMD_CHARGER_PLUG_OUT); - if (ret) { - cts_err("Send CMD_CHARGER_PLUG_OUT failed %d", ret); - } else { - cts_dev->rtdata.charger_exist = false; - } - return 0; + cts_info("Set dev charger plugout"); + ret = cts_send_command(cts_dev, CTS_CMD_CHARGER_PLUG_OUT); + if (ret) { + cts_err("Send CMD_CHARGER_PLUG_OUT failed %d", ret); + } else { + cts_dev->rtdata.charger_exist = false; + } + return 0; } #endif /* CONFIG_CTS_CHARGER_DETECT */ int cts_enable_fw_log_redirect(struct cts_device *cts_dev) { - int ret; + int ret; - cts_info("Fw log redirect enable"); - ret = cts_send_command(cts_dev, CTS_CMD_ENABLE_FW_LOG_REDIRECT); - if (ret) { - cts_err("Send CTS_CMD_ENABLE_FW_LOG_REDIRECT failed %d", ret); - } - else { - cts_dev->rtdata.fw_log_redirect_enabled = true; - } - return 0; + cts_info("Fw log redirect enable"); + ret = cts_send_command(cts_dev, CTS_CMD_ENABLE_FW_LOG_REDIRECT); + if (ret) { + cts_err("Send CTS_CMD_ENABLE_FW_LOG_REDIRECT failed %d", ret); + } else { + cts_dev->rtdata.fw_log_redirect_enabled = true; + } + return 0; } int cts_disable_fw_log_redirect(struct cts_device *cts_dev) { - int ret; + int ret; - cts_info("Fw log redirect disable"); - ret = cts_send_command(cts_dev, CTS_CMD_DISABLE_FW_LOG_REDIRECT); - if (ret) { - cts_err("Send CTS_CMD_DISABLE_FW_LOG_REDIRECT failed %d", ret); - } - else { - cts_dev->rtdata.fw_log_redirect_enabled = false; - } - return 0; + cts_info("Fw log redirect disable"); + ret = cts_send_command(cts_dev, CTS_CMD_DISABLE_FW_LOG_REDIRECT); + if (ret) { + cts_err("Send CTS_CMD_DISABLE_FW_LOG_REDIRECT failed %d", ret); + } else { + cts_dev->rtdata.fw_log_redirect_enabled = false; + } + return 0; } bool cts_is_fw_log_redirect(struct cts_device *cts_dev) { - return cts_dev->rtdata.fw_log_redirect_enabled; + return cts_dev->rtdata.fw_log_redirect_enabled; } int cts_fw_log_show_finish(struct cts_device *cts_dev) { - int ret; + int ret; - ret = cts_send_command(cts_dev, CTS_CMD_FW_LOG_SHOW_FINISH); - if (ret) { - cts_err("Send CTS_CMD_FW_LOG_SHOW_FINISH failed %d", ret); - } + ret = cts_send_command(cts_dev, CTS_CMD_FW_LOG_SHOW_FINISH); + if (ret) { + cts_err("Send CTS_CMD_FW_LOG_SHOW_FINISH failed %d", ret); + } - return ret; + return ret; } int cts_enable_get_compensate_cap(const struct cts_device *cts_dev) { - cts_info("cts_enable_get_compensate_cap"); + cts_info("cts_enable_get_compensate_cap"); - return cts_send_command(cts_dev,CTS_CMD_ENABLE_READ_CNEG); + return cts_send_command(cts_dev, CTS_CMD_ENABLE_READ_CNEG); } int cts_disable_get_compensate_cap(const struct cts_device *cts_dev) { - cts_info("cts_disable_get_compensate_cap"); + cts_info("cts_disable_get_compensate_cap"); - return cts_send_command(cts_dev,CTS_CMD_DISABLE_READ_CNEG); + return cts_send_command(cts_dev, CTS_CMD_DISABLE_READ_CNEG); } int cts_get_compensate_cap(const struct cts_device *cts_dev, u8 *cap) { + cts_info("Get compensate cap"); - cts_info("Get compensate cap"); - - /* Use hardware row & col here */ - return cts_fw_reg_readsb_delay_idle(cts_dev, CTS_DEVICE_FW_REG_COMPENSATE_CAP, cap, - cts_dev->hwdata->num_row *cts_dev->hwdata->num_col, 500); + /* Use hardware row & col here */ + return cts_fw_reg_readsb_delay_idle(cts_dev, + CTS_DEVICE_FW_REG_COMPENSATE_CAP, + cap, + cts_dev->hwdata->num_row * + cts_dev->hwdata->num_col, 500); } + +void cts_firmware_upgrade_work(struct work_struct *work) +{ + struct chipone_ts_data *cts_data; + struct cts_device *cts_dev; + const struct cts_firmware *firmware; + int retries; + int ret; + + cts_info("Firmware upgrade work"); + + cts_data = container_of(work, struct chipone_ts_data, + fw_upgrade_work.work); + cts_dev = &cts_data->cts_dev; + + firmware = cts_request_firmware(cts_dev, cts_dev->hwdata->hwid, + CTS_DEV_FWID_ANY, cts_dev->fwdata.version); + if (firmware == NULL) { + cts_err("Request firmware failed"); + return ; + } + + retries = 0; + do { + ret = cts_update_firmware(cts_dev, firmware, true); + if (ret) { + cts_err("Update firmware failed %d retries %d", ret, + retries); + + cts_plat_reset_device(cts_dev->pdata); + } else { + break; + } + } while (++retries < 3); + + cts_release_firmware(firmware); + + if (ret == 0) { + cts_start_device(cts_dev); + } +} + diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_core.h b/drivers/input/touchscreen/chipone_tddi_mmi/cts_core.h old mode 100755 new mode 100644 index 78056bc0a353..c3eec721a79e --- a/drivers/input/touchscreen/chipone_tddi_mmi/cts_core.h +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_core.h @@ -3,21 +3,20 @@ #include "cts_config.h" - enum cts_dev_hw_reg { - CTS_DEV_HW_REG_HARDWARE_ID = 0x30000u, - CTS_DEV_HW_REG_CLOCK_GATING = 0x30004u, - CTS_DEV_HW_REG_RESET_CONFIG = 0x30008u, - CTS_DEV_HW_REG_BOOT_MODE = 0x30010u, + CTS_DEV_HW_REG_HARDWARE_ID = 0x30000u, + CTS_DEV_HW_REG_CLOCK_GATING = 0x30004u, + CTS_DEV_HW_REG_RESET_CONFIG = 0x30008u, + CTS_DEV_HW_REG_BOOT_MODE = 0x30010u, CTS_DEV_HW_REG_CURRENT_MODE = 0x30011u, }; enum cts_dev_boot_mode { - CTS_DEV_BOOT_MODE_FLASH = 1, - CTS_DEV_BOOT_MODE_I2C_PROGRAM = 2, - CTS_DEV_BOOT_MODE_SRAM = 3, - CTS_DEV_BOOT_MODE_SPI_PROGRAM = 5, - CTS_DEV_BOOT_MODE_MASK = 7, + CTS_DEV_BOOT_MODE_FLASH = 1, + CTS_DEV_BOOT_MODE_I2C_PROGRAM = 2, + CTS_DEV_BOOT_MODE_SRAM = 3, + CTS_DEV_BOOT_MODE_SPI_PROGRAM = 5, + CTS_DEV_BOOT_MODE_MASK = 7, }; /** I2C addresses(7bits), transfer size and bitrate */ @@ -30,86 +29,88 @@ enum cts_dev_boot_mode { /** Chipone firmware register addresses under normal mode */ enum cts_device_fw_reg { - CTS_DEVICE_FW_REG_WORK_MODE = 0x0000, - CTS_DEVICE_FW_REG_DATA_READY = 0x0002, - CTS_DEVICE_FW_REG_CMD = 0x0004, - CTS_DEVICE_FW_REG_CHIP_TYPE = 0x000A, - CTS_DEVICE_FW_REG_VERSION = 0x000C, - CTS_DEVICE_FW_REG_FW_LIB_MAIN_VERSION = 0x09, - CTS_DEVICE_FW_REG_DDI_VERSION = 0x0010, - CTS_DEVICE_FW_REG_FW_LIB_SUB_VERSION = 0x47, + CTS_DEVICE_FW_REG_WORK_MODE = 0x0000, + CTS_DEVICE_FW_REG_DATA_READY = 0x0002, + CTS_DEVICE_FW_REG_CMD = 0x0004, + CTS_DEVICE_FW_REG_CHIP_TYPE = 0x000A, + CTS_DEVICE_FW_REG_VERSION = 0x000C, + CTS_DEVICE_FW_REG_FW_LIB_MAIN_VERSION = 0x09, + CTS_DEVICE_FW_REG_DDI_VERSION = 0x0010, + CTS_DEVICE_FW_REG_GET_WORK_MODE = 0x003F, + CTS_DEVICE_FW_REG_FW_LIB_SUB_VERSION = 0x0047, - CTS_DEVICE_FW_REG_TOUCH_INFO = 0x1000, - CTS_DEVICE_FW_REG_RAW_DATA = 0x2000, - CTS_DEVICE_FW_REG_DIFF_DATA = 0x3000, - CTS_DEVICE_FW_REG_GESTURE_INFO = 0x7000, + CTS_DEVICE_FW_REG_TOUCH_INFO = 0x1000, + CTS_DEVICE_FW_REG_RAW_DATA = 0x2000, + CTS_DEVICE_FW_REG_DIFF_DATA = 0x3000, + CTS_DEVICE_FW_REG_GESTURE_INFO = 0x7000, - CTS_DEVICE_FW_REG_PANEL_PARAM = 0x8000, - CTS_DEVICE_FW_REG_X_RESOLUTION = 0x8090, - CTS_DEVICE_FW_REG_Y_RESOLUTION = 0x8092, - CTS_DEVICE_FW_REG_NUM_TX = 0x8007, - CTS_DEVICE_FW_REG_NUM_RX = 0x8008, + CTS_DEVICE_FW_REG_PANEL_PARAM = 0x8000, + CTS_DEVICE_FW_REG_X_RESOLUTION = 0x8090, + CTS_DEVICE_FW_REG_Y_RESOLUTION = 0x8092, + CTS_DEVICE_FW_REG_NUM_TX = 0x8007, + CTS_DEVICE_FW_REG_NUM_RX = 0x8008, - CTS_DEVICE_FW_REG_COMPENSATE_CAP = 0xA000, - CTS_DEVICE_FW_REG_DEBUG_INTF = 0xF000, + CTS_DEVICE_FW_REG_COMPENSATE_CAP = 0xA000, + CTS_DEVICE_FW_REG_DEBUG_INTF = 0xF000, }; /** Hardware IDs, read from hardware id register */ enum cts_dev_hwid { - CTS_DEV_HWID_ICNL9911 = 0x990100u, - CTS_DEV_HWID_ICNL9911S = 0x990110u, + CTS_DEV_HWID_ICNL9911 = 0x990100u, + CTS_DEV_HWID_ICNL9911S = 0x990110u, - CTS_DEV_HWID_ANY = 0, - CTS_DEV_HWID_INVALID = 0xFFFFFFFFu, + CTS_DEV_HWID_ANY = 0, + CTS_DEV_HWID_INVALID = 0xFFFFFFFFu, }; /* Firmware IDs, read from firmware register @ref CTS_DEV_FW_REG_CHIP_TYPE under normal mode */ enum cts_dev_fwid { - CTS_DEV_FWID_ICNL9911 = 0x9911u, - CTS_DEV_FWID_ICNL9911S = 0x9964u, + CTS_DEV_FWID_ICNL9911 = 0x9911u, + CTS_DEV_FWID_ICNL9911S = 0x9964u, - CTS_DEV_FWID_ANY = 0u, - CTS_DEV_FWID_INVALID = 0xFFFFu + CTS_DEV_FWID_ANY = 0u, + CTS_DEV_FWID_INVALID = 0xFFFFu }; /** Commands written to firmware register @ref CTS_DEVICE_FW_REG_CMD under normal mode */ enum cts_firmware_cmd { - CTS_CMD_RESET = 1, - CTS_CMD_SUSPEND = 2, - CTS_CMD_ENTER_WRITE_PARA_TO_FLASH_MODE = 3, - CTS_CMD_WRITE_PARA_TO_FLASH = 4, - CTS_CMD_WRTITE_INT_HIGH = 5, - CTS_CMD_WRTITE_INT_LOW = 6, - CTS_CMD_RELASE_INT_TEST = 7, - CTS_CMD_RECOVERY_TX_VOL = 0x10, - CTS_CMD_DEC_TX_VOL_1 = 0x11, - CTS_CMD_DEC_TX_VOL_2 = 0x12, - CTS_CMD_DEC_TX_VOL_3 = 0x13, - CTS_CMD_DEC_TX_VOL_4 = 0x14, - CTS_CMD_DEC_TX_VOL_5 = 0x15, - CTS_CMD_DEC_TX_VOL_6 = 0x16, - CTS_CMD_ENABLE_READ_RAWDATA = 0x20, - CTS_CMD_DISABLE_READ_RAWDATA = 0x21, - CTS_CMD_SUSPEND_WITH_GESTURE = 0x40, - CTS_CMD_QUIT_GESTURE_MONITOR = 0x41, - CTS_CMD_CHARGER_PLUG_IN = 0x55, - CTS_CMD_CHARGER_PLUG_OUT = 0x66, - CTS_CMD_ENABLE_FW_LOG_REDIRECT = 0x86, - CTS_CMD_DISABLE_FW_LOG_REDIRECT = 0x87, - CTS_CMD_ENABLE_READ_CNEG = 0x88, - CTS_CMD_DISABLE_READ_CNEG = 0x89, - CTS_CMD_FW_LOG_SHOW_FINISH = 0xE0, + CTS_CMD_RESET = 1, + CTS_CMD_SUSPEND = 2, + CTS_CMD_ENTER_WRITE_PARA_TO_FLASH_MODE = 3, + CTS_CMD_WRITE_PARA_TO_FLASH = 4, + CTS_CMD_WRTITE_INT_HIGH = 5, + CTS_CMD_WRTITE_INT_LOW = 6, + CTS_CMD_RELASE_INT_TEST = 7, + CTS_CMD_RECOVERY_TX_VOL = 0x10, + CTS_CMD_DEC_TX_VOL_1 = 0x11, + CTS_CMD_DEC_TX_VOL_2 = 0x12, + CTS_CMD_DEC_TX_VOL_3 = 0x13, + CTS_CMD_DEC_TX_VOL_4 = 0x14, + CTS_CMD_DEC_TX_VOL_5 = 0x15, + CTS_CMD_DEC_TX_VOL_6 = 0x16, + CTS_CMD_ENABLE_READ_RAWDATA = 0x20, + CTS_CMD_DISABLE_READ_RAWDATA = 0x21, + CTS_CMD_SUSPEND_WITH_GESTURE = 0x40, + CTS_CMD_QUIT_GESTURE_MONITOR = 0x41, + CTS_CMD_CHARGER_PLUG_IN = 0x55, + CTS_CMD_CHARGER_PLUG_OUT = 0x66, + CTS_CMD_ENABLE_FW_LOG_REDIRECT = 0x86, + CTS_CMD_DISABLE_FW_LOG_REDIRECT = 0x87, + CTS_CMD_ENABLE_READ_CNEG = 0x88, + CTS_CMD_DISABLE_READ_CNEG = 0x89, + CTS_CMD_FW_LOG_SHOW_FINISH = 0xE0, + }; #pragma pack(1) /** Touch message read back from chip */ struct cts_device_touch_msg { - u8 id; - __le16 x; - __le16 y; - u8 pressure; - u8 event; + u8 id; + __le16 x; + __le16 y; + u8 pressure; + u8 event; #define CTS_DEVICE_TOUCH_EVENT_NONE (0) #define CTS_DEVICE_TOUCH_EVENT_DOWN (1) @@ -121,23 +122,23 @@ struct cts_device_touch_msg { /** Touch information read back from chip */ struct cts_device_touch_info { - u8 vkey_state; - u8 num_msg; + u8 vkey_state; + u8 num_msg; - struct cts_device_touch_msg msgs[CFG_CTS_MAX_TOUCH_NUM]; + struct cts_device_touch_msg msgs[CFG_CTS_MAX_TOUCH_NUM]; }; /** Gesture trace point read back from chip */ struct cts_device_gesture_point { - __le16 x; - __le16 y; - u8 pressure; - u8 event; + __le16 x; + __le16 y; + u8 pressure; + u8 event; }; /** Gesture information read back from chip */ struct cts_device_gesture_info { - u8 gesture_id; + u8 gesture_id; #define CTS_GESTURE_UP (0x11) #define CTS_GESTURE_C (0x12) #define CTS_GESTURE_O (0x13) @@ -154,48 +155,48 @@ struct cts_device_gesture_info { #define CTS_GESTURE_V (0x1E) #define CTS_GESTURE_D_TAP (0x50) - u8 num_points; + u8 num_points; #define CTS_CHIP_MAX_GESTURE_TRACE_POINT (64u) - struct cts_device_gesture_point points[CTS_CHIP_MAX_GESTURE_TRACE_POINT]; + struct cts_device_gesture_point + points[CTS_CHIP_MAX_GESTURE_TRACE_POINT]; }; #pragma pack() - struct cts_device; enum cts_crc_type { - CTS_CRC16 = 1, - CTS_CRC32 = 2, + CTS_CRC16 = 1, + CTS_CRC32 = 2, }; /** Chip hardware data, will never change */ struct cts_device_hwdata { - const char *name; - u32 hwid; - u16 fwid; - u8 num_row; - u8 num_col; - u32 sram_size; + const char *name; + u32 hwid; + u16 fwid; + u8 num_row; + u8 num_col; + u32 sram_size; - /* Address width under program mode */ - u8 program_addr_width; + /* Address width under program mode */ + u8 program_addr_width; - const struct cts_sfctrl *sfctrl; + const struct cts_sfctrl *sfctrl; }; /** Chip firmware data */ struct cts_device_fwdata { - u16 version; - u16 res_x; - u16 res_y; - u8 rows; - u8 cols; - u8 ddi_version; - u8 int_mode; - u8 esd_method; + u16 version; + u16 res_x; + u16 res_y; + u8 rows; + u8 cols; + u8 ddi_version; + u8 int_mode; + u8 esd_method; u16 lib_version; u16 int_keep_time; u16 rawdata_target; @@ -203,307 +204,344 @@ struct cts_device_fwdata { /** Chip runtime data */ struct cts_device_rtdata { - u8 slave_addr; - int addr_width; - bool program_mode; - bool has_flash; + u8 slave_addr; + int addr_width; + bool program_mode; + bool has_flash; - bool suspended; - bool updating; - bool testing; + bool suspended; + bool updating; + bool testing; - bool gesture_wakeup_enabled; - bool charger_exist; - bool fw_log_redirect_enabled; - bool glove_mode_enabled; + bool gesture_wakeup_enabled; + bool charger_exist; + bool fw_log_redirect_enabled; + bool glove_mode_enabled; }; struct cts_device { - struct cts_platform_data *pdata; - - const struct cts_device_hwdata *hwdata; - struct cts_device_fwdata fwdata; - struct cts_device_rtdata rtdata; - const struct cts_flash *flash; - bool enabled; + struct cts_platform_data *pdata; + const struct cts_device_hwdata *hwdata; + struct cts_device_fwdata fwdata; + struct cts_device_rtdata rtdata; + const struct cts_flash *flash; + bool enabled; +#ifdef CFG_CTS_FW_UPDATE_FILE_LOAD + char config_fw_name[CFG_CTS_FW_FILE_NAME_MAX_LEN + 1]; +#endif /* CFG_CTS_FW_UPDATE_FILE_LOAD */ }; struct cts_platform_data; struct chipone_ts_data { #ifdef CONFIG_CTS_I2C_HOST - struct i2c_client *i2c_client; + struct i2c_client *i2c_client; #else struct spi_device *spi_client; -#endif /* CONFIG_CTS_I2C_HOST */ - - struct cts_device cts_dev; - - struct cts_platform_data *pdata; - - struct workqueue_struct *workqueue; +#endif /* CONFIG_CTS_I2C_HOST */ + struct device *device; + struct cts_device cts_dev; + struct cts_platform_data *pdata; + struct workqueue_struct *workqueue; + struct delayed_work fw_upgrade_work; + struct work_struct ts_resume_work; +#ifdef CONFIG_CTS_CHARGER_DETECT + void *cd_data; +#endif /* CONFIG_CTS_CHARGER_DETECT */ #ifdef CONFIG_CTS_ESD_PROTECTION - struct workqueue_struct *esd_workqueue; - struct delayed_work esd_work; - bool esd_enabled; - int esd_check_fail_cnt; -#endif /* CONFIG_CTS_ESD_PROTECTION */ + struct workqueue_struct *esd_workqueue; + struct delayed_work esd_work; + bool esd_enabled; + int esd_check_fail_cnt; +#endif /* CONFIG_CTS_ESD_PROTECTION */ #ifdef CONFIG_CTS_LEGACY_TOOL - struct proc_dir_entry *procfs_entry; -#endif /* CONFIG_CTS_LEGACY_TOOL */ + struct proc_dir_entry *procfs_entry; +#endif /* CONFIG_CTS_LEGACY_TOOL */ + + bool force_reflash; }; static inline u32 get_unaligned_le24(const void *p) { - const u8 *puc = (const u8 *)p; - return (puc[0] | (puc[1] << 8) | (puc[2] << 16)); + const u8 *puc = (const u8 *)p; + return (puc[0] | (puc[1] << 8) | (puc[2] << 16)); } static inline u32 get_unaligned_be24(const void *p) { - const u8 *puc = (const u8 *)p; - return (puc[2] | (puc[1] << 8) | (puc[0] << 16)); + const u8 *puc = (const u8 *)p; + return (puc[2] | (puc[1] << 8) | (puc[0] << 16)); } static inline void put_unaligned_be24(u32 v, void *p) { - u8 *puc = (u8 *)p; + u8 *puc = (u8 *) p; - puc[0] = (v >> 16) & 0xFF; - puc[1] = (v >> 8 ) & 0xFF; - puc[2] = (v >> 0 ) & 0xFF; + puc[0] = (v >> 16) & 0xFF; + puc[1] = (v >> 8) & 0xFF; + puc[2] = (v >> 0) & 0xFF; } -#define wrap(max,x) ((max) - 1 - (x)) +#define wrap(max, x) ((max) - 1 - (x)) extern void cts_lock_device(const struct cts_device *cts_dev); extern void cts_unlock_device(const struct cts_device *cts_dev); extern int cts_sram_writeb_retry(const struct cts_device *cts_dev, - u32 addr, u8 b, int retry, int delay); + u32 addr, u8 b, int retry, int delay); extern int cts_sram_writew_retry(const struct cts_device *cts_dev, - u32 addr, u16 w, int retry, int delay); + u32 addr, u16 w, int retry, int delay); extern int cts_sram_writel_retry(const struct cts_device *cts_dev, - u32 addr, u32 l, int retry, int delay); + u32 addr, u32 l, int retry, int delay); extern int cts_sram_writesb_retry(const struct cts_device *cts_dev, - u32 addr, const void *src, size_t len, int retry, int delay); + u32 addr, const void *src, size_t len, + int retry, int delay); extern int cts_sram_writesb_check_crc_retry(const struct cts_device *cts_dev, - u32 addr, const void *src, size_t len, u32 crc, int retry); + u32 addr, const void *src, + size_t len, u32 crc, int retry); extern int cts_sram_readb_retry(const struct cts_device *cts_dev, - u32 addr, u8 *b, int retry, int delay); + u32 addr, u8 *b, int retry, int delay); extern int cts_sram_readw_retry(const struct cts_device *cts_dev, - u32 addr, u16 *w, int retry, int delay); + u32 addr, u16 *w, int retry, int delay); extern int cts_sram_readl_retry(const struct cts_device *cts_dev, - u32 addr, u32 *l, int retry, int delay); + u32 addr, u32 *l, int retry, int delay); extern int cts_sram_readsb_retry(const struct cts_device *cts_dev, - u32 addr, void *dst, size_t len, int retry, int delay); + u32 addr, void *dst, size_t len, int retry, + int delay); extern int cts_fw_reg_writeb_retry(const struct cts_device *cts_dev, - u32 reg_addr, u8 b, int retry, int delay); + u32 reg_addr, u8 b, int retry, int delay); extern int cts_fw_reg_writew_retry(const struct cts_device *cts_dev, - u32 reg_addr, u16 w, int retry, int delay); + u32 reg_addr, u16 w, int retry, int delay); extern int cts_fw_reg_writel_retry(const struct cts_device *cts_dev, - u32 reg_addr, u32 l, int retry, int delay); + u32 reg_addr, u32 l, int retry, int delay); extern int cts_fw_reg_writesb_retry(const struct cts_device *cts_dev, - u32 reg_addr, const void *src, size_t len, int retry, int delay); + u32 reg_addr, const void *src, size_t len, + int retry, int delay); extern int cts_fw_reg_readb_retry(const struct cts_device *cts_dev, - u32 reg_addr, u8 *b, int retry, int delay); + u32 reg_addr, u8 *b, int retry, int delay); extern int cts_fw_reg_readw_retry(const struct cts_device *cts_dev, - u32 reg_addr, u16 *w, int retry, int delay); + u32 reg_addr, u16 *w, int retry, int delay); extern int cts_fw_reg_readl_retry(const struct cts_device *cts_dev, - u32 reg_addr, u32 *l, int retry, int delay); + u32 reg_addr, u32 *l, int retry, int delay); extern int cts_fw_reg_readsb_retry(const struct cts_device *cts_dev, - u32 reg_addr, void *dst, size_t len, int retry, int delay); + u32 reg_addr, void *dst, size_t len, + int retry, int delay); extern int cts_fw_reg_readsb_retry_delay_idle(const struct cts_device *cts_dev, - u32 reg_addr, void *dst, size_t len, int retry, int delay, int idle); + u32 reg_addr, void *dst, + size_t len, int retry, int delay, + int idle); extern int cts_hw_reg_writeb_retry(const struct cts_device *cts_dev, - u32 reg_addr, u8 b, int retry, int delay); + u32 reg_addr, u8 b, int retry, int delay); extern int cts_hw_reg_writew_retry(const struct cts_device *cts_dev, - u32 reg_addr, u16 w, int retry, int delay); + u32 reg_addr, u16 w, int retry, int delay); extern int cts_hw_reg_writel_retry(const struct cts_device *cts_dev, - u32 reg_addr, u32 l, int retry, int delay); + u32 reg_addr, u32 l, int retry, int delay); extern int cts_hw_reg_writesb_retry(const struct cts_device *cts_dev, - u32 reg_addr, const void *src, size_t len, int retry, int delay); + u32 reg_addr, const void *src, size_t len, + int retry, int delay); extern int cts_hw_reg_readb_retry(const struct cts_device *cts_dev, - u32 reg_addr, u8 *b, int retry, int delay); + u32 reg_addr, u8 *b, int retry, int delay); extern int cts_hw_reg_readw_retry(const struct cts_device *cts_dev, - u32 reg_addr, u16 *w, int retry, int delay); + u32 reg_addr, u16 *w, int retry, int delay); extern int cts_hw_reg_readl_retry(const struct cts_device *cts_dev, - u32 reg_addr, u32 *l, int retry, int delay); + u32 reg_addr, u32 *l, int retry, int delay); extern int cts_hw_reg_readsb_retry(const struct cts_device *cts_dev, - u32 reg_addr, void *dst, size_t len, int retry, int delay); + u32 reg_addr, void *dst, size_t len, + int retry, int delay); -static inline int cts_fw_reg_writeb(const struct cts_device *cts_dev, u32 reg_addr, u8 b) +static inline int cts_fw_reg_writeb(const struct cts_device *cts_dev, + u32 reg_addr, u8 b) { - return cts_fw_reg_writeb_retry(cts_dev, reg_addr, b, 1, 0); + return cts_fw_reg_writeb_retry(cts_dev, reg_addr, b, 1, 0); } -static inline int cts_fw_reg_writew(const struct cts_device *cts_dev, u32 reg_addr, u16 w) +static inline int cts_fw_reg_writew(const struct cts_device *cts_dev, + u32 reg_addr, u16 w) { - return cts_fw_reg_writew_retry(cts_dev, reg_addr, w, 1, 0); + return cts_fw_reg_writew_retry(cts_dev, reg_addr, w, 1, 0); } -static inline int cts_fw_reg_writel(const struct cts_device *cts_dev, u32 reg_addr, u32 l) +static inline int cts_fw_reg_writel(const struct cts_device *cts_dev, + u32 reg_addr, u32 l) { - return cts_fw_reg_writel_retry(cts_dev, reg_addr, l, 1, 0); + return cts_fw_reg_writel_retry(cts_dev, reg_addr, l, 1, 0); } -static inline int cts_fw_reg_writesb(const struct cts_device *cts_dev, u32 reg_addr, - const void *src, size_t len) +static inline int cts_fw_reg_writesb(const struct cts_device *cts_dev, + u32 reg_addr, const void *src, size_t len) { - return cts_fw_reg_writesb_retry(cts_dev, reg_addr, src, len, 1, 0); + return cts_fw_reg_writesb_retry(cts_dev, reg_addr, src, len, 1, 0); } -static inline int cts_fw_reg_readb(const struct cts_device *cts_dev, u32 reg_addr, u8 *b) +static inline int cts_fw_reg_readb(const struct cts_device *cts_dev, + u32 reg_addr, u8 *b) { - return cts_fw_reg_readb_retry(cts_dev, reg_addr, b, 1, 0); + return cts_fw_reg_readb_retry(cts_dev, reg_addr, b, 1, 0); } -static inline int cts_fw_reg_readw(const struct cts_device *cts_dev, u32 reg_addr, u16 *w) +static inline int cts_fw_reg_readw(const struct cts_device *cts_dev, + u32 reg_addr, u16 *w) { - return cts_fw_reg_readw_retry(cts_dev, reg_addr, w, 1, 0); + return cts_fw_reg_readw_retry(cts_dev, reg_addr, w, 1, 0); } -static inline int cts_fw_reg_readl(const struct cts_device *cts_dev, u32 reg_addr, u32 *l) +static inline int cts_fw_reg_readl(const struct cts_device *cts_dev, + u32 reg_addr, u32 *l) { - return cts_fw_reg_readl_retry(cts_dev, reg_addr, l, 1, 0); + return cts_fw_reg_readl_retry(cts_dev, reg_addr, l, 1, 0); } static inline int cts_fw_reg_readsb(const struct cts_device *cts_dev, - u32 reg_addr, void *dst, size_t len) + u32 reg_addr, void *dst, size_t len) { - return cts_fw_reg_readsb_retry(cts_dev, reg_addr, dst, len, 1, 0); + return cts_fw_reg_readsb_retry(cts_dev, reg_addr, dst, len, 1, 0); } static inline int cts_fw_reg_readsb_delay_idle(const struct cts_device *cts_dev, - u32 reg_addr, void *dst, size_t len, int idle) + u32 reg_addr, void *dst, + size_t len, int idle) { - return cts_fw_reg_readsb_retry_delay_idle(cts_dev, reg_addr, dst, len, 1, 0, idle); + return cts_fw_reg_readsb_retry_delay_idle(cts_dev, reg_addr, dst, len, + 1, 0, idle); } -static inline int cts_hw_reg_writeb(const struct cts_device *cts_dev, u32 reg_addr, u8 b) +static inline int cts_hw_reg_writeb_relaxed(const struct cts_device *cts_dev, + u32 reg_addr, u8 b) { - return cts_hw_reg_writeb_retry(cts_dev, reg_addr, b, 1, 0); + return cts_hw_reg_writeb_retry(cts_dev, reg_addr, b, 1, 0); } -static inline int cts_hw_reg_writew(const struct cts_device *cts_dev, u32 reg_addr, u16 w) +static inline int cts_hw_reg_writew_relaxed(const struct cts_device *cts_dev, + u32 reg_addr, u16 w) { - return cts_hw_reg_writew_retry(cts_dev, reg_addr, w, 1, 0); + return cts_hw_reg_writew_retry(cts_dev, reg_addr, w, 1, 0); } -static inline int cts_hw_reg_writel(const struct cts_device *cts_dev, u32 reg_addr, u32 l) +static inline int cts_hw_reg_writel_relaxed(const struct cts_device *cts_dev, + u32 reg_addr, u32 l) { - return cts_hw_reg_writel_retry(cts_dev, reg_addr, l, 1, 0); + return cts_hw_reg_writel_retry(cts_dev, reg_addr, l, 1, 0); } -static inline int cts_hw_reg_writesb(const struct cts_device *cts_dev, u32 reg_addr, - const void *src, size_t len) +static inline int cts_hw_reg_writesb(const struct cts_device *cts_dev, + u32 reg_addr, const void *src, size_t len) { - return cts_hw_reg_writesb_retry(cts_dev, reg_addr, src, len, 1, 0); + return cts_hw_reg_writesb_retry(cts_dev, reg_addr, src, len, 1, 0); } -static inline int cts_hw_reg_readb(const struct cts_device *cts_dev, u32 reg_addr, u8 *b) +static inline int cts_hw_reg_readb_relaxed(const struct cts_device *cts_dev, + u32 reg_addr, u8 *b) { - return cts_hw_reg_readb_retry(cts_dev, reg_addr, b, 1, 0); + return cts_hw_reg_readb_retry(cts_dev, reg_addr, b, 1, 0); } -static inline int cts_hw_reg_readw(const struct cts_device *cts_dev, u32 reg_addr, u16 *w) +static inline int cts_hw_reg_readw_relaxed(const struct cts_device *cts_dev, + u32 reg_addr, u16 *w) { - return cts_hw_reg_readw_retry(cts_dev, reg_addr, w, 1, 0); + return cts_hw_reg_readw_retry(cts_dev, reg_addr, w, 1, 0); } -static inline int cts_hw_reg_readl(const struct cts_device *cts_dev, u32 reg_addr, u32 *l) +static inline int cts_hw_reg_readl_relaxed(const struct cts_device *cts_dev, + u32 reg_addr, u32 *l) { - return cts_hw_reg_readl_retry(cts_dev, reg_addr, l, 1, 0); + return cts_hw_reg_readl_retry(cts_dev, reg_addr, l, 1, 0); } static inline int cts_hw_reg_readsb(const struct cts_device *cts_dev, - u32 reg_addr, void *dst, size_t len) + u32 reg_addr, void *dst, size_t len) { - return cts_hw_reg_readsb_retry(cts_dev, reg_addr, dst, len, 1, 0); + return cts_hw_reg_readsb_retry(cts_dev, reg_addr, dst, len, 1, 0); } -static inline int cts_sram_writeb(const struct cts_device *cts_dev, u32 addr, u8 b) +static inline int cts_sram_writeb(const struct cts_device *cts_dev, u32 addr, + u8 b) { - return cts_sram_writeb_retry(cts_dev, addr, b, 1, 0); + return cts_sram_writeb_retry(cts_dev, addr, b, 1, 0); } -static inline int cts_sram_writew(const struct cts_device *cts_dev, u32 addr, u16 w) +static inline int cts_sram_writew(const struct cts_device *cts_dev, u32 addr, + u16 w) { - return cts_sram_writew_retry(cts_dev, addr, w, 1, 0); + return cts_sram_writew_retry(cts_dev, addr, w, 1, 0); } -static inline int cts_sram_writel(const struct cts_device *cts_dev, u32 addr, u32 l) +static inline int cts_sram_writel(const struct cts_device *cts_dev, u32 addr, + u32 l) { - return cts_sram_writel_retry(cts_dev, addr, l, 1, 0); + return cts_sram_writel_retry(cts_dev, addr, l, 1, 0); } static inline int cts_sram_writesb(const struct cts_device *cts_dev, u32 addr, - const void *src, size_t len) + const void *src, size_t len) { - return cts_sram_writesb_retry(cts_dev, addr, src, len, 1, 0); + return cts_sram_writesb_retry(cts_dev, addr, src, len, 1, 0); } -static inline int cts_sram_readb(const struct cts_device *cts_dev, u32 addr, u8 *b) +static inline int cts_sram_readb(const struct cts_device *cts_dev, u32 addr, + u8 *b) { - return cts_sram_readb_retry(cts_dev, addr, b, 1, 0); + return cts_sram_readb_retry(cts_dev, addr, b, 1, 0); } -static inline int cts_sram_readw(const struct cts_device *cts_dev, u32 addr, u16 *w) +static inline int cts_sram_readw(const struct cts_device *cts_dev, u32 addr, + u16 *w) { - return cts_sram_readw_retry(cts_dev, addr, w, 1, 0); + return cts_sram_readw_retry(cts_dev, addr, w, 1, 0); } -static inline int cts_sram_readl(const struct cts_device *cts_dev, u32 addr, u32 *l) +static inline int cts_sram_readl(const struct cts_device *cts_dev, u32 addr, + u32 *l) { - return cts_sram_readl_retry(cts_dev, addr, l, 1, 0); + return cts_sram_readl_retry(cts_dev, addr, l, 1, 0); } static inline int cts_sram_readsb(const struct cts_device *cts_dev, - u32 addr, void *dst, size_t len) + u32 addr, void *dst, size_t len) { - return cts_sram_readsb_retry(cts_dev, addr, dst, len, 1, 0); + return cts_sram_readsb_retry(cts_dev, addr, dst, len, 1, 0); } #ifdef CONFIG_CTS_I2C_HOST static inline void cts_set_program_addr(struct cts_device *cts_dev) { - cts_dev->rtdata.slave_addr = CTS_DEV_PROGRAM_MODE_I2CADDR; - cts_dev->rtdata.program_mode = true; - cts_dev->rtdata.addr_width = CTS_DEV_PROGRAM_MODE_ADDR_WIDTH; + cts_dev->rtdata.slave_addr = CTS_DEV_PROGRAM_MODE_I2CADDR; + cts_dev->rtdata.program_mode = true; + cts_dev->rtdata.addr_width = CTS_DEV_PROGRAM_MODE_ADDR_WIDTH; } static inline void cts_set_normal_addr(struct cts_device *cts_dev) { - cts_dev->rtdata.slave_addr = CTS_DEV_NORMAL_MODE_I2CADDR; - cts_dev->rtdata.program_mode = false; - cts_dev->rtdata.addr_width = CTS_DEV_NORMAL_MODE_ADDR_WIDTH; + cts_dev->rtdata.slave_addr = CTS_DEV_NORMAL_MODE_I2CADDR; + cts_dev->rtdata.program_mode = false; + cts_dev->rtdata.addr_width = CTS_DEV_NORMAL_MODE_ADDR_WIDTH; } #else static inline void cts_set_program_addr(struct cts_device *cts_dev) { - cts_dev->rtdata.slave_addr = CTS_DEV_PROGRAM_MODE_SPIADDR; - cts_dev->rtdata.program_mode = true; - cts_dev->rtdata.addr_width = CTS_DEV_PROGRAM_MODE_ADDR_WIDTH; + cts_dev->rtdata.slave_addr = CTS_DEV_PROGRAM_MODE_SPIADDR; + cts_dev->rtdata.program_mode = true; + cts_dev->rtdata.addr_width = CTS_DEV_PROGRAM_MODE_ADDR_WIDTH; } static inline void cts_set_normal_addr(struct cts_device *cts_dev) { - cts_dev->rtdata.slave_addr = CTS_DEV_NORMAL_MODE_SPIADDR; - cts_dev->rtdata.program_mode = false; - cts_dev->rtdata.addr_width = CTS_DEV_NORMAL_MODE_ADDR_WIDTH; + cts_dev->rtdata.slave_addr = CTS_DEV_NORMAL_MODE_SPIADDR; + cts_dev->rtdata.program_mode = false; + cts_dev->rtdata.addr_width = CTS_DEV_NORMAL_MODE_ADDR_WIDTH; } #endif extern int cts_irq_handler(struct cts_device *cts_dev); +extern void cts_firmware_upgrade_work(struct work_struct *work); extern bool cts_is_device_suspended(const struct cts_device *cts_dev); extern int cts_suspend_device(struct cts_device *cts_dev); @@ -516,18 +554,22 @@ extern int cts_enter_normal_mode(struct cts_device *cts_dev); extern int cts_probe_device(struct cts_device *cts_dev); extern int cts_set_work_mode(const struct cts_device *cts_dev, u8 mode); extern int cts_get_work_mode(const struct cts_device *cts_dev, u8 *mode); -extern int cts_get_firmware_version(const struct cts_device *cts_dev, u16 *version); +extern int cts_get_firmware_version(const struct cts_device *cts_dev, + u16 *version); extern int cts_get_ddi_version(const struct cts_device *cts_dev, u8 *version); -extern int cts_get_lib_version(const struct cts_device *cts_dev, u16 *lib_version); +extern int cts_get_lib_version(const struct cts_device *cts_dev, + u16 *lib_version); extern int cts_get_data_ready_flag(const struct cts_device *cts_dev, u8 *flag); extern int cts_clr_data_ready_flag(const struct cts_device *cts_dev); extern int cts_send_command(const struct cts_device *cts_dev, u8 cmd); extern int cts_get_panel_param(const struct cts_device *cts_dev, - void *param, size_t size); + void *param, size_t size); extern int cts_set_panel_param(const struct cts_device *cts_dev, - const void *param, size_t size); -extern int cts_get_x_resolution(const struct cts_device *cts_dev, u16 *resolution); -extern int cts_get_y_resolution(const struct cts_device *cts_dev, u16 *resolution); + const void *param, size_t size); +extern int cts_get_x_resolution(const struct cts_device *cts_dev, + u16 *resolution); +extern int cts_get_y_resolution(const struct cts_device *cts_dev, + u16 *resolution); extern int cts_get_num_rows(const struct cts_device *cts_dev, u8 *num_rows); extern int cts_get_num_cols(const struct cts_device *cts_dev, u8 *num_cols); extern int cts_enable_get_rawdata(const struct cts_device *cts_dev); @@ -544,8 +586,8 @@ extern int cts_get_hwid(struct cts_device *cts_dev, u32 *hwid); extern void cts_enable_gesture_wakeup(struct cts_device *cts_dev); extern void cts_disable_gesture_wakeup(struct cts_device *cts_dev); extern bool cts_is_gesture_wakeup_enabled(const struct cts_device *cts_dev); -extern int cts_get_gesture_info(const struct cts_device *cts_dev, - void *gesture_info, bool trace_point); +extern int cts_get_gesture_info(const struct cts_device *cts_dev, + void *gesture_info, bool trace_point); #endif /* CFG_CTS_GESTURE */ #ifdef CONFIG_CTS_ESD_PROTECTION @@ -554,10 +596,21 @@ extern void cts_enable_esd_protection(struct chipone_ts_data *cts_data); extern void cts_disable_esd_protection(struct chipone_ts_data *cts_data); extern void cts_deinit_esd_protection(struct chipone_ts_data *cts_data); #else /* CONFIG_CTS_ESD_PROTECTION */ -static inline void cts_init_esd_protection(struct chipone_ts_data *cts_data) {} -static inline void cts_enable_esd_protection(struct chipone_ts_data *cts_data) {} -static inline void cts_disable_esd_protection(struct chipone_ts_data *cts_data) {} -static inline void cts_deinit_esd_protection(struct chipone_ts_data *cts_data) {} +static inline void cts_init_esd_protection(struct chipone_ts_data *cts_data) +{ +} + +static inline void cts_enable_esd_protection(struct chipone_ts_data *cts_data) +{ +} + +static inline void cts_disable_esd_protection(struct chipone_ts_data *cts_data) +{ +} + +static inline void cts_deinit_esd_protection(struct chipone_ts_data *cts_data) +{ +} #endif /* CONFIG_CTS_ESD_PROTECTION */ #ifdef CONFIG_CTS_GLOVE @@ -565,9 +618,20 @@ extern int cts_enter_glove_mode(struct cts_device *cts_dev); extern int cts_exit_glove_mode(struct cts_device *cts_dev); int cts_is_glove_enabled(const struct cts_device *cts_dev); #else -static inline int cts_enter_glove_mode(struct cts_device *cts_dev) {return 0;} -static inline int cts_exit_glove_mode(struct cts_device *cts_dev) {return 0;} -static inline int cts_is_glove_enabled(const struct cts_device *cts_dev) {return 0;} +static inline int cts_enter_glove_mode(struct cts_device *cts_dev) +{ + return 0; +} + +static inline int cts_exit_glove_mode(struct cts_device *cts_dev) +{ + return 0; +} + +static inline int cts_is_glove_enabled(const struct cts_device *cts_dev) +{ + return 0; +} #endif #ifdef CONFIG_CTS_CHARGER_DETECT @@ -575,17 +639,34 @@ extern bool cts_is_charger_exist(struct cts_device *cts_dev); extern int cts_charger_plugin(struct cts_device *cts_dev); extern int cts_charger_plugout(struct cts_device *cts_dev); #else /* CONFIG_CTS_CHARGER_DETECT */ -static inline bool cts_is_charger_exist(struct cts_device *cts_dev) {return false;} -static inline int cts_charger_plugin(struct cts_device *cts_dev) {return 0;} -static inline int cts_charger_plugout(struct cts_device *cts_dev) {return 0;} +static inline bool cts_is_charger_exist(struct cts_device *cts_dev) +{ + return false; +} + +static inline int cts_charger_plugin(struct cts_device *cts_dev) +{ + return 0; +} + +static inline int cts_charger_plugout(struct cts_device *cts_dev) +{ + return 0; +} #endif /* CONFIG_CTS_CHARGER_DETECT */ #ifdef CONFIG_CTS_LEGACY_TOOL -extern int cts_tool_init(struct chipone_ts_data *cts_data); +extern int cts_tool_init(struct chipone_ts_data *cts_data); extern void cts_tool_deinit(struct chipone_ts_data *data); #else /* CONFIG_CTS_LEGACY_TOOL */ -static inline int cts_tool_init(struct chipone_ts_data *cts_data) {return 0;} -static inline void cts_tool_deinit(struct chipone_ts_data *data) {} +static inline int cts_tool_init(struct chipone_ts_data *cts_data) +{ + return 0; +} + +static inline void cts_tool_deinit(struct chipone_ts_data *data) +{ +} #endif /* CONFIG_CTS_LEGACY_TOOL */ extern bool cts_is_device_enabled(const struct cts_device *cts_dev); @@ -601,11 +682,10 @@ extern int cts_fw_log_show_finish(struct cts_device *cts_dev); #ifdef CFG_CTS_UPDATE_CRCCHECK extern int cts_sram_writesb_boot_crc_retry(const struct cts_device *cts_dev, - size_t len, u32 crc, int retry); + size_t len, u32 crc, int retry); #endif extern const char *cts_dev_boot_mode2str(u8 boot_mode); extern bool cts_is_fwid_valid(u16 fwid); #endif /* CTS_CORE_H */ - diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_firmware.c b/drivers/input/touchscreen/chipone_tddi_mmi/cts_firmware.c old mode 100755 new mode 100644 index c818f02cd8ec..42e662a2b7e0 --- a/drivers/input/touchscreen/chipone_tddi_mmi/cts_firmware.c +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_firmware.c @@ -1,888 +1,1096 @@ -#define LOG_TAG "Firmware" - -#include "cts_config.h" -#include "cts_platform.h" -#include "cts_core.h" -#include "cts_sfctrl.h" -#include "cts_spi_flash.h" -#include "cts_firmware.h" -#include -#include -#include -#include - - -#ifdef CFG_CTS_DRIVER_BUILTIN_FIRMWARE -#include "cts_builtin_firmware.h" -#define NUM_DRIVER_BUILTIN_FIRMWARE ARRAY_SIZE(cts_driver_builtin_firmwares) -#endif /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */ - -#define CTS_FIRMWARE_MULTI_SECTION_FILE_SIZE (0x20000) -#define CTS_SECTION_ENABLE_FLAG (0x0000C35A) - -enum cts_firmware_section_offset { - CTS_FIRMWARE_SECTION_OFFSET = 0x00000000, - CTS_FIRMWARE_CRC_SECTION_OFFSET = 0x17000, - CTS_DDIPARAM_SECTION_OFFSET = 0x00019000, - CTS_DDIPARAM_CRC_SECTION_OFFSET = 0x1B000, - -}; - -struct cts_firmware_sect_info { - const u8 *firmware_sect; - size_t firmware_sect_size; - const u8 *firmware_crc_sect; - size_t firmware_crc_sect_size; - u32 firmware_sect_crc; - - const u8 *ddiparam_sect; - size_t ddiparam_sect_size; - const u8 *ddiparam_crc_sect; - size_t ddiparam_crc_sect_size; - u32 ddiparam_sect_crc; - -}; - -#define FIRMWARE_SECTION(firmware) \ - ((firmware)->data) -#define FIRMWARE_CRC_SECTION(firmware) \ - ((firmware)->data + CTS_FIRMWARE_CRC_SECTION_OFFSET) -#define DDIPARAM_SECTION(firmware) \ - ((firmware)->data + CTS_DDIPARAM_SECTION_OFFSET) -#define DDIPARAM_CRC_SECTION(firmware) \ - ((firmware)->data + CTS_DDIPARAM_CRC_SECTION_OFFSET) - -#define FIRMWARE_SECTION_CRC(firmware) \ - (get_unaligned_le32(FIRMWARE_CRC_SECTION(firmware))) -#define FIRMWARE_SECTION_SIZE(firmware) \ - (get_unaligned_le32(FIRMWARE_CRC_SECTION(firmware) + 4)) -#define FIRMWARE_SECTION_CRC_ENABLE(firmware) \ - (get_unaligned_le32(FIRMWARE_CRC_SECTION(firmware) + 8)) -#define FIRMWARE_CRC_SECTION_SIZE (12) - -#define DDIPARAM_SECTION_ENABLE(firmware) \ - (get_unaligned_le32(DDIPARAM_CRC_SECTION(firmware))) -#define DDIPARAM_SECTION_CRC_ENABLE(firmware) \ - (get_unaligned_le32(DDIPARAM_CRC_SECTION(firmware) + 4)) -#define DDIPARAM_SECTION_CRC(firmware) \ - (get_unaligned_le32(DDIPARAM_CRC_SECTION(firmware) + 8)) -#define DDIPARAM_SECTION_SIZE(firmware) \ - (get_unaligned_le32(DDIPARAM_CRC_SECTION(firmware) + 12)) -#define DDIPARAM_CRC_SECTION_SIZE (17) - -u32 crc32(const u8 *data, size_t len) -{ - const static u32 crc32_table[] = { - 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, - 0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, - 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, 0x4C11DB70, 0x48D0C6C7, - 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75, - 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, - 0x709F7B7A, 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, - 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58, 0xBAEA46EF, - 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D, - 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB, - 0xCEB42022, 0xCA753D95, 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, - 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0, - 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072, - 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4, - 0x0808D07D, 0x0CC9CDCA, 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, - 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, - 0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, - 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC, - 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, - 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, 0xE0B41DE7, 0xE4750050, - 0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, - 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34, - 0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, - 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, 0x4F040D56, 0x4BC510E1, - 0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53, - 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, - 0x3F9B762C, 0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, - 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E, 0xF5EE4BB9, - 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B, - 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, - 0xCDA1F604, 0xC960EBB3, 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, - 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71, - 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3, - 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2, - 0x470CDD2B, 0x43CDC09C, 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, - 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, - 0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC, - 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A, - 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, - 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, 0xE3A1CBC1, 0xE760D676, - 0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, - 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, - 0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, - 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4 - }; - - u32 crc = 0; - while (len) { - crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *data) & 0xFF]; - - data++; - len--; - } - - return crc; -} - -static int calc_crc_in_flash(const struct cts_device *cts_dev, - u32 flash_addr, size_t size, u32 *crc) -{ - return cts_dev->hwdata->sfctrl->ops->calc_flash_crc(cts_dev, - flash_addr, size, crc); -} - -static bool is_multi_section_firmware(const struct cts_firmware *firmware) -{ - return (firmware->size == CTS_FIRMWARE_MULTI_SECTION_FILE_SIZE); -} - -static bool is_single_section_firmware(const struct cts_firmware *firmware) -{ - return !(is_multi_section_firmware(firmware)); -} - -static bool is_firmware_size_valid(const struct cts_firmware *firmware) -{ - return (firmware->size > 0x102 && - firmware->size <= CTS_FIRMWARE_MULTI_SECTION_FILE_SIZE); -} - -static bool is_multi_section_firmware_valid( - const struct cts_firmware *firmware) -{ - u32 crc; - - crc = crc32(FIRMWARE_SECTION(firmware), FIRMWARE_SECTION_SIZE(firmware)); - if (crc != FIRMWARE_SECTION_CRC(firmware)) { - cts_err("Firmware-section crc mismatch crc-section %08x != %08x" - ", File maybe broken!!!", - crc, FIRMWARE_SECTION_CRC(firmware)); - return false; - } - - if (DDIPARAM_SECTION_ENABLE(firmware) == CTS_SECTION_ENABLE_FLAG) { - crc = crc32(DDIPARAM_SECTION(firmware), DDIPARAM_SECTION_SIZE(firmware)); - if (crc != DDIPARAM_SECTION_CRC(firmware)) { - cts_err("DDIParam-section crc mismatch crc-section %08x != %08x" - ", File maybe broken!!!", - crc, DDIPARAM_SECTION_CRC(firmware)); - return false; - } - } else { - cts_info("DDIParam-section is NOT enabled"); - } - - return true; -} - -static bool is_firmware_valid(const struct cts_firmware *firmware) -{ - if (firmware && firmware->data && is_firmware_size_valid(firmware)) { - if (is_single_section_firmware(firmware) || - is_multi_section_firmware_valid(firmware)) { - return true; - } - } - - return false; -} - -static void parse_single_section_firmware( - const struct cts_firmware *firmware, - struct cts_firmware_sect_info *info) -{ - static u8 crc_sect[12]; - - info->firmware_sect = firmware->data; - info->firmware_sect_size = firmware->size; - info->firmware_sect_crc = crc32(firmware->data, firmware->size); - - put_unaligned_le32(info->firmware_sect_crc, crc_sect); - put_unaligned_le32(info->firmware_sect_size, crc_sect + 4); - put_unaligned_le32(~0x0000C35A, crc_sect + 8); /* Enable CRC check */ - info->firmware_crc_sect = crc_sect; - info->firmware_crc_sect_size = sizeof(crc_sect); -} - -static void parse_multi_section_firmware( - const struct cts_firmware *firmware, - struct cts_firmware_sect_info *info) -{ - info->firmware_sect = FIRMWARE_SECTION(firmware); - info->firmware_sect_size = FIRMWARE_SECTION_SIZE(firmware); - info->firmware_crc_sect = FIRMWARE_CRC_SECTION(firmware); - info->firmware_crc_sect_size = FIRMWARE_CRC_SECTION_SIZE; - info->firmware_sect_crc = FIRMWARE_SECTION_CRC(firmware); - - if (DDIPARAM_SECTION_ENABLE(firmware) == CTS_SECTION_ENABLE_FLAG) { - info->ddiparam_sect = DDIPARAM_SECTION(firmware); - info->ddiparam_sect_size = DDIPARAM_SECTION_SIZE(firmware); - info->ddiparam_crc_sect = DDIPARAM_CRC_SECTION(firmware); - info->ddiparam_crc_sect_size = DDIPARAM_CRC_SECTION_SIZE; - info->ddiparam_sect_crc = DDIPARAM_SECTION_CRC(firmware); - } -} - -static int parse_firmware(const struct cts_firmware *firmware, - struct cts_firmware_sect_info *info) -{ - memset(info, 0, sizeof(*info)); - - if (is_multi_section_firmware(firmware)) { - parse_multi_section_firmware(firmware, info); - } else { - parse_single_section_firmware(firmware, info); - } - - cts_info(" Firmware section size: %zu", info->firmware_sect_size); - if (info->ddiparam_crc_sect) { - cts_info(" DDIParam section size: %zu", info->ddiparam_sect_size); - } - - return 0; -} - -#ifdef CFG_CTS_DRIVER_BUILTIN_FIRMWARE -#ifdef CONFIG_CTS_SYSFS -int cts_get_num_driver_builtin_firmware(void) -{ - return NUM_DRIVER_BUILTIN_FIRMWARE; -} - -const struct cts_firmware *cts_request_driver_builtin_firmware_by_name(const char *name) -{ - const struct cts_firmware *firmware; - int i; - - cts_info("Request driver builtin by name '%s'", name); - - firmware = cts_driver_builtin_firmwares; - for (i = 0; i < NUM_DRIVER_BUILTIN_FIRMWARE; i++, firmware++) { - if (strcmp(firmware->name, name) == 0) { - if (is_firmware_valid(firmware)) { - cts_info("Found driver builtin '%s' " - "hwid: %06x fwid: %04x size: %zu ver: %04x", - firmware->name, firmware->hwid, firmware->fwid, - firmware->size, FIRMWARE_VERSION(firmware)); - return firmware; - } - - cts_warn("Found driver builtin '%s' " - "hwid: %06x fwid: %04x size: %zu invalid", - firmware->name, firmware->hwid, firmware->hwid, firmware->size); - } - } - - return NULL; -} - -const struct cts_firmware *cts_request_driver_builtin_firmware_by_index(u32 index) -{ - const struct cts_firmware *firmware; - - cts_info("Request driver builtin by index %u", index); - - if (index < NUM_DRIVER_BUILTIN_FIRMWARE) { - firmware = cts_driver_builtin_firmwares + index; - if (is_firmware_valid(firmware)) { - cts_info("Found driver builtin '%s' " - "hwid: %06x fwid: %04x size: %zu ver: %04x", - firmware->name, firmware->hwid, firmware->fwid, - firmware->size, FIRMWARE_VERSION(firmware)); - return firmware; - } - cts_warn("Found driver builtin '%s' " - "hwid: %06x fwid: %04x size: %zu INVALID", - firmware->name, firmware->hwid, firmware->hwid, firmware->size); - } else { - cts_warn("Request driver builtin by index %u too large >= %zu", - index, NUM_DRIVER_BUILTIN_FIRMWARE); - } - - return NULL; -} -#endif /* CONFIG_CTS_SYSFS */ - -static const struct cts_firmware * cts_request_newer_driver_builtin_firmware( - u32 hwid, u16 fwid, u16 device_fw_ver) -{ -#define MATCH_HWID(firmware, hwid) \ - ((hwid) == CTS_DEV_HWID_ANY || (firmware)->hwid == (hwid)) -#define MATCH_FWID(firmware, fwid) \ - ((fwid) == CTS_DEV_FWID_ANY || (firmware)->fwid == (fwid)) - - const struct cts_firmware *firmware = NULL; - int i; - - cts_info("Request driver builtin if match hwid: %06x fwid: %04x && ver > %04x", - hwid, fwid, device_fw_ver); - - firmware = cts_driver_builtin_firmwares; - for (i = 0; i < ARRAY_SIZE(cts_driver_builtin_firmwares); i++, firmware++) { -// if (MATCH_HWID(firmware, hwid) && MATCH_FWID(firmware, fwid)) { - if (1) { - if (!is_firmware_valid(firmware)) { - cts_err("Found driver builtin '%s' " - "hwid: %06x fwid: %04x INVALID", - firmware->name, firmware->hwid, firmware->fwid); - continue; - } - - cts_info("Found matched driver builtin '%s' " - "hwid: %06x fwid: %04x size: %zu ver: %04x", - firmware->name, firmware->hwid, firmware->fwid, - firmware->size, FIRMWARE_VERSION(firmware)); - -// if(FIRMWARE_VERSION(firmware) > device_fw_ver) { - if(1) { - cts_info("Found newer driver builtin '%s' " - "hwid: %06x fwid: %04x size: %zu ver: %04x > %04x", - firmware->name, firmware->hwid, firmware->fwid, - firmware->size, FIRMWARE_VERSION(firmware), device_fw_ver); - return firmware; - } - } - } - - cts_info("No newer driver builtin found"); - - return NULL; - -#undef MATCH_HWID -#undef MATCH_FWID -} -#endif /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */ - -#ifdef CFG_CTS_FIRMWARE_IN_FS -bool is_filesystem_mounted(const char *filepath) -{ - struct path root_path; - struct path path; - int ret; - - ret = kern_path("/", LOOKUP_FOLLOW, &root_path); - if (ret) { - return false; - } - - ret = kern_path(filepath, LOOKUP_FOLLOW, &path); - if (ret) { - goto err_put_root_path; - } - - if (path.mnt->mnt_sb == root_path.mnt->mnt_sb) { - /* not mounted */ - ret = false; - } else { - ret = true; - } - - path_put(&path); -err_put_root_path: - path_put(&root_path); - - return !!ret; -} - -const struct cts_firmware *cts_request_newer_firmware_from_fs( - const char *filepath, u16 curr_version) -{ - struct cts_firmware *firmware; - struct file *file; - int ret, read_size; - u8 buff[2]; - u16 version; - loff_t pos = 0; - - cts_info("Request from file '%s' if version > %04x", - filepath, curr_version); - - firmware = (struct cts_firmware *)kzalloc(sizeof(*firmware), GFP_KERNEL); - if (firmware == NULL) { - cts_err("Request from file alloc struct firmware failed"); - return NULL; - } - - file = filp_open(filepath, O_RDONLY, 0); - if (IS_ERR(file)) { - cts_err("Open file '%s' failed %ld", filepath, PTR_ERR(file)); - goto err_free_firmware; - } - - firmware->size = file_inode(file)->i_size; - if (!is_firmware_size_valid(firmware)) { - cts_info("File '%s' size: %zu invalid", filepath, firmware->size); - goto err_close_file; - } - - pos = FIRMWARE_VERSION_OFFSET; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0) - read_size = kernel_read(file, buff, 2, &pos); -#else - read_size = kernel_read(file, pos, buff, 2); -#endif - if (read_size < 0) { - cts_err("Read version from offset 0x100 failed"); - goto err_close_file; - } - version = get_unaligned_le16(buff); - - if (version <= curr_version) { - cts_info("File '%s' size: %zu version: %04x <= %04x", - filepath, firmware->size, version, curr_version); - goto err_close_file; - } - - cts_info("File '%s' size: %zu version: %04x", - filepath, firmware->size, version); - - firmware->data = (u8 *)vmalloc(firmware->size); - if (firmware->data == NULL) { - cts_err("Request form fs alloc firmware data failed"); - goto err_close_file; - } - - pos = 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0) - read_size = kernel_read(file, firmware->data, firmware->size, &pos); -#else - read_size = kernel_read(file, pos, firmware->data, firmware->size); -#endif - if (read_size < 0 || read_size != firmware->size) { - cts_err("Request from fs read whole file failed %d", read_size); - goto err_free_firmware_data; - } - - ret = filp_close(file, NULL); - if (ret) { - cts_warn("Close file '%s' failed %d", filepath, ret); - } - - return firmware; - -err_free_firmware_data: - vfree(firmware->data); -err_close_file: - filp_close(file, NULL); -err_free_firmware: - kfree(firmware); - firmware = NULL; - - return NULL; -} - -const struct cts_firmware *cts_request_firmware_from_fs(const char *filepath) -{ - cts_info("Request from file '%s'", filepath); - - return cts_request_newer_firmware_from_fs(filepath, 0); -} - -int cts_update_firmware_from_file(struct cts_device *cts_dev, - const char *filepath, bool to_flash) -{ - const struct cts_firmware *firmware; - int ret; - - cts_info("Update from file '%s' to %s", filepath, - to_flash ? "flash" : "sram"); - - firmware = cts_request_firmware_from_fs(filepath); - if(firmware == NULL) { - cts_err("Request from file '%s' failed", filepath); - return -EFAULT; - } - - ret = cts_update_firmware(cts_dev, firmware, to_flash); - if (ret) { - cts_err("Update to %s from file failed %d", - to_flash ? "flash" : "sram", ret); - goto err_release_firmware; - } - - cts_info("Update from file success"); - -err_release_firmware: - cts_release_firmware(firmware); - - return ret; -} -#endif /*CFG_CTS_FIRMWARE_IN_FS*/ - -const struct cts_firmware *cts_request_firmware( - u32 hwid, u16 fwid, u16 curr_firmware_ver) -{ - const struct cts_firmware *firmware_builtin = NULL; - const struct cts_firmware *firmware_from_file = NULL; - - if (hwid == CTS_DEV_HWID_INVALID) { - hwid = CTS_DEV_HWID_ANY; - } - if (fwid == CTS_DEV_FWID_INVALID) { - fwid = CTS_DEV_FWID_ANY; - } - - cts_info("Request newer if match hwid: %06x fwid: %04x && ver > %04x", - hwid, fwid, curr_firmware_ver); - -#ifdef CFG_CTS_DRIVER_BUILTIN_FIRMWARE - firmware_builtin = cts_request_newer_driver_builtin_firmware( - hwid, fwid, curr_firmware_ver); -#endif /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */ - -#ifdef CFG_CTS_KERNEL_BUILTIN_FIRMWARE - -#endif /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */ - -#ifdef CFG_CTS_FIRMWARE_IN_FS - /* Check firmware in file system when probe only when build to .ko */ - if (is_filesystem_mounted(CFG_CTS_FIRMWARE_FILEPATH)) { - firmware_from_file = cts_request_newer_firmware_from_fs( - CFG_CTS_FIRMWARE_FILEPATH, - firmware_builtin ? FIRMWARE_VERSION(firmware_builtin) : - curr_firmware_ver); - } -#endif /* CFG_CTS_FIRMWARE_IN_FS */ - - return firmware_from_file ? firmware_from_file : firmware_builtin; -} - -void cts_release_firmware(const struct cts_firmware *firmware) -{ - cts_info("Release firmware"); - - /* Builtin firmware with non-NULL name, no need to free*/ - if (firmware && firmware->name == NULL) { - vfree(firmware->data); - kfree(firmware); - } -} - -static int validate_flash_data(const struct cts_device *cts_dev, - u32 flash_addr, const u8 *data, size_t size, - u8 *buf, bool calc_crc, u32 crc) -{ - int ret, i; - bool free_data = false; - u32 crc_flash; - - cts_info("Validate flash data from 0x%06x size %zu by %s", - flash_addr, size, calc_crc ? "check-crc" : "direct-readback"); - - if (calc_crc) { - ret = calc_crc_in_flash(cts_dev, flash_addr, size, &crc_flash); - if (ret) { - cts_err("Calc data in flash from 0x%06x size %zu crc failed %d, " - "try to validate by direct readback", - flash_addr, size, ret); - // FALL through by direct compare data read back - } else { - if (crc_flash != crc) { - cts_err("Crc in flash from 0x%06x size %zu mismatch 0x%08x != 0x%08x", - flash_addr, size, crc_flash, crc); - // FALL through by direct compare data read back - } else { - cts_info("Flash data crc correct"); - return 0; - } - } - } - - if (buf == NULL) { - buf = (u8 *)kmalloc(size, GFP_KERNEL); - if (buf == NULL) { - cts_err("Validate flash data allocate mem failed"); - return -ENOMEM; - } - - free_data = true; - } - - ret = cts_read_flash(cts_dev, flash_addr, buf, size); - if (ret) { - cts_err("Read flash from 0x%06x size %zu failed %d", - flash_addr, size, ret); - goto err_free_buf; - } - - for (i = 0; i < size; i++) { - if (buf[i] != data[i]) { - if (ret == 0) { - cts_err("Flash data from 0x%06x size %zu first bytes diff:\n", - flash_addr, size); - } - - if (ret < 100) { - cts_err(" 0x%06x: %02x %02x", i, buf[i], data[i]); - } else if (ret == 100) { - cts_err(" ..."); - } - ret++; - } - } - -err_free_buf: - if (free_data) { - kfree(buf); - } - - return ret; -} - -static int cts_program_firmware(const struct cts_device *cts_dev, - const struct cts_firmware_sect_info *firmware_info) -{ - int ret; - u8 crc_sect_buf[FIRMWARE_CRC_SECTION_SIZE]; - - cts_info("Program firmware size %zu", firmware_info->firmware_sect_size); - - /* Write firmware to SRAM for easy enter normal mode after update */ - cts_info("Write firmware section to sram"); - ret = cts_sram_writesb_check_crc_retry(cts_dev, - 0, firmware_info->firmware_sect, firmware_info->firmware_sect_size, - firmware_info->firmware_sect_crc, 3); - if (ret) { - cts_err("Write firmware section to sram failed %d", ret); - return ret; - } - - ret = cts_program_flash_from_sram(cts_dev, - 4, 4, firmware_info->firmware_sect_size - 4); - if (ret) { - cts_err("Program firmware section from sram failed %d", ret); - return ret; - } - - ret = cts_program_flash(cts_dev, - CTS_FIRMWARE_CRC_SECTION_OFFSET, - firmware_info->firmware_crc_sect, - firmware_info->firmware_crc_sect_size); - if (ret) { - cts_err("Program firmware crc section failed %d", ret); - return ret; - } - - ret = validate_flash_data(cts_dev, - CTS_FIRMWARE_CRC_SECTION_OFFSET, firmware_info->firmware_crc_sect, - firmware_info->firmware_crc_sect_size, crc_sect_buf, false, 0); - if (ret) { - cts_err("Validate Firmware-CRC section failed %d", ret); - return ret; - } - - ret = cts_program_flash(cts_dev, 0, firmware_info->firmware_sect, 4); - if (ret) { - cts_err("Program firmware section fist 4bytes failed %d", ret); - return ret; - } - - ret = validate_flash_data(cts_dev, - CTS_FIRMWARE_SECTION_OFFSET, firmware_info->firmware_sect, - firmware_info->firmware_sect_size, NULL, - true, firmware_info->firmware_sect_crc); - if (ret) { - cts_err("Validate firmware section failed %d", ret); - return ret; - } - - return 0; -} - -static int cts_program_ddiparam(const struct cts_device *cts_dev, - const struct cts_firmware_sect_info *firmware_info) -{ - int ret; - u8 crc_sect_buf[DDIPARAM_CRC_SECTION_SIZE]; - - cts_info("Program DDIParam size: %zu", firmware_info->ddiparam_sect_size); - - ret = cts_program_flash(cts_dev, CTS_DDIPARAM_SECTION_OFFSET, - firmware_info->ddiparam_sect, firmware_info->ddiparam_sect_size); - if (ret) { - cts_err("Program DDIParam section failed %d", ret); - return ret; - } - - ret = validate_flash_data(cts_dev, - CTS_DDIPARAM_SECTION_OFFSET, firmware_info->ddiparam_sect, - firmware_info->ddiparam_sect_size, NULL, - true, firmware_info->ddiparam_sect_crc); - if (ret) { - cts_err("Validate DDIParam section failed %d", ret); - return ret; - } - - ret = cts_program_flash(cts_dev, CTS_DDIPARAM_CRC_SECTION_OFFSET, - firmware_info->ddiparam_crc_sect, - firmware_info->ddiparam_crc_sect_size); - if (ret) { - cts_err("Program DDIParam-CRC section failed %d", ret); - return ret; - } - - ret = validate_flash_data(cts_dev, - CTS_DDIPARAM_CRC_SECTION_OFFSET, firmware_info->ddiparam_crc_sect, - firmware_info->ddiparam_crc_sect_size, crc_sect_buf, false, 0); - if (ret) { - cts_err("Validate DDIParam-CRC section failed %d", ret); - return ret; - } - - return 0; -} - - -int cts_update_firmware(struct cts_device *cts_dev, - const struct cts_firmware *firmware, bool to_flash) -{ - struct cts_firmware_sect_info firmware_info; - int ret, retries; - - cts_info("Update firmware to %s ver: %04x size: %zu", - to_flash ? "flash" : "sram", - FIRMWARE_VERSION(firmware), firmware->size); - - if (parse_firmware(firmware, &firmware_info)) { - cts_err("Parse firmware failed"); - return -EINVAL; - } - - cts_lock_device(cts_dev); - - cts_dev->rtdata.updating = true; - - ret = cts_enter_program_mode(cts_dev); - if (ret) { - cts_err("Device enter program mode failed %d", ret); - goto out; - } - - ret = cts_prepare_flash_operation(cts_dev); - if (ret) { - cts_warn("Prepare flash operation failed %d", ret); - // Go through and try - } - - if (!to_flash || !cts_dev->rtdata.has_flash) { - cts_info("Write firmware section to sram size %zu", - firmware_info.firmware_sect_size); - ret = cts_sram_writesb_check_crc_retry(cts_dev, - 0, firmware_info.firmware_sect, firmware_info.firmware_sect_size, - firmware_info.firmware_sect_crc, 3); - if (ret) { - cts_err("Write firmware section to sram failed %d", ret); - } -#ifdef CFG_CTS_UPDATE_CRCCHECK - if (cts_dev->hwdata->hwid == CTS_DEV_HWID_ICNL9911S) { - cts_sram_writesb_boot_crc_retry(cts_dev, - firmware_info.firmware_sect_size, - firmware_info.firmware_sect_crc, - 3); - } -#endif - goto out; - } - - retries = 0; - do { - retries++; - - ret = cts_erase_flash(cts_dev, CTS_FIRMWARE_CRC_SECTION_OFFSET, - firmware_info.firmware_crc_sect_size); - if (ret) { - cts_err("Erase firmware crc section failed %d retries %d", - ret, retries); - continue; - } - - ret = cts_erase_flash(cts_dev, 0, firmware_info.firmware_sect_size); - if (ret) { - cts_err("Erase firmware section failed %d retries %d", - ret, retries); - continue; - } - - ret = cts_program_firmware(cts_dev, &firmware_info); - if (ret) { - cts_err("Program firmware & crc section failed %d retries %d", - ret, retries); - } - } while (ret && retries < 3); - - if (ret == 0 && firmware_info.ddiparam_sect_size != 0) { - retries = 0; - do { - retries++; - - ret = cts_erase_flash(cts_dev, CTS_DDIPARAM_CRC_SECTION_OFFSET, - firmware_info.ddiparam_crc_sect_size); - if (ret) { - cts_err("Erase DDIParam crc secction failed %d, retries %d", - ret, retries); - continue; - } - - ret = cts_erase_flash(cts_dev, CTS_DDIPARAM_SECTION_OFFSET, - firmware_info.ddiparam_sect_size); - if (ret) { - cts_err("Erase DDIParam section failed %d, retries %d", - ret, retries); - continue; - } - - ret = cts_program_ddiparam(cts_dev, &firmware_info); - if (ret) { - cts_err("Program DDIParam & crc section failed %d retries %d", - ret, retries); - } - } while (ret && retries < 3); - } - - cts_post_flash_operation(cts_dev); - -out: - cts_dev->rtdata.updating = false; - - if (ret == 0) { - if (firmware_info.firmware_sect_size <= - cts_dev->hwdata->sfctrl->xchg_sram_base) { - ret = cts_enter_normal_mode(cts_dev); - if (ret) { - cts_err("Enter normal mode failed %d", ret); - //return ret; - } - } - } - cts_unlock_device(cts_dev); -#ifdef CONFIG_CTS_CHARGER_DETECT - if (cts_is_charger_exist(cts_dev)) { - cts_charger_plugin(cts_dev); - } -#endif /* CONFIG_CTS_CHARGER_DETECT */ - -#ifdef CONFIG_CTS_GLOVE - if (cts_is_glove_enabled(cts_dev)) { - cts_enter_glove_mode(cts_dev); - } -#endif - -#ifdef CFG_CTS_FW_LOG_REDIRECT - if (cts_is_fw_log_redirect(cts_dev)) { - cts_enable_fw_log_redirect(cts_dev); - } -#endif - - return ret; -} - -bool cts_is_firmware_updating(const struct cts_device *cts_dev) -{ - return cts_dev->rtdata.updating; -} - +#define LOG_TAG "Firmware" + +#include "cts_config.h" +#include "cts_platform.h" +#include "cts_core.h" +#include "cts_sfctrl.h" +#include "cts_spi_flash.h" +#include "cts_firmware.h" +#include +#include +#include +#include + +#ifdef CFG_CTS_DRIVER_BUILTIN_FIRMWARE +#include "cts_builtin_firmware.h" +#define NUM_DRIVER_BUILTIN_FIRMWARE ARRAY_SIZE(cts_driver_builtin_firmwares) +#endif /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */ + +#define CTS_FIRMWARE_MULTI_SECTION_FILE_SIZE (0x20000) +#define CTS_SECTION_ENABLE_FLAG (0x0000C35A) + +enum cts_firmware_section_offset { + CTS_FIRMWARE_SECTION_OFFSET = 0x00000000, + CTS_FIRMWARE_CRC_SECTION_OFFSET = 0x17000, + CTS_DDIPARAM_SECTION_OFFSET = 0x00019000, + CTS_DDIPARAM_CRC_SECTION_OFFSET = 0x1B000, + +}; + +struct cts_firmware_sect_info { + const u8 *firmware_sect; + size_t firmware_sect_size; + const u8 *firmware_crc_sect; + size_t firmware_crc_sect_size; + u32 firmware_sect_crc; + + const u8 *ddiparam_sect; + size_t ddiparam_sect_size; + const u8 *ddiparam_crc_sect; + size_t ddiparam_crc_sect_size; + u32 ddiparam_sect_crc; + +}; + +#define FIRMWARE_SECTION(firmware) \ + ((firmware)->data) +#define FIRMWARE_CRC_SECTION(firmware) \ + ((firmware)->data + CTS_FIRMWARE_CRC_SECTION_OFFSET) +#define DDIPARAM_SECTION(firmware) \ + ((firmware)->data + CTS_DDIPARAM_SECTION_OFFSET) +#define DDIPARAM_CRC_SECTION(firmware) \ + ((firmware)->data + CTS_DDIPARAM_CRC_SECTION_OFFSET) + +#define FIRMWARE_SECTION_CRC(firmware) \ + (get_unaligned_le32(FIRMWARE_CRC_SECTION(firmware))) +#define FIRMWARE_SECTION_SIZE(firmware) \ + (get_unaligned_le32(FIRMWARE_CRC_SECTION(firmware) + 4)) +#define FIRMWARE_SECTION_CRC_ENABLE(firmware) \ + (get_unaligned_le32(FIRMWARE_CRC_SECTION(firmware) + 8)) +#define FIRMWARE_CRC_SECTION_SIZE (12) + +#define DDIPARAM_SECTION_ENABLE(firmware) \ + (get_unaligned_le32(DDIPARAM_CRC_SECTION(firmware))) +#define DDIPARAM_SECTION_CRC_ENABLE(firmware) \ + (get_unaligned_le32(DDIPARAM_CRC_SECTION(firmware) + 4)) +#define DDIPARAM_SECTION_CRC(firmware) \ + (get_unaligned_le32(DDIPARAM_CRC_SECTION(firmware) + 8)) +#define DDIPARAM_SECTION_SIZE(firmware) \ + (get_unaligned_le32(DDIPARAM_CRC_SECTION(firmware) + 12)) +#define DDIPARAM_CRC_SECTION_SIZE (17) + +u32 crc32(const u8 *data, size_t len) +{ + const static u32 crc32_table[] = { + 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, + 0x17C56B6B, + 0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, + 0x2B4BCB61, + 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, 0x4C11DB70, + 0x48D0C6C7, + 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, + 0x52568B75, + 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, + 0x7DDC5DA3, + 0x709F7B7A, 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, + 0x95609039, + 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58, + 0xBAEA46EF, + 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, + 0xA06C0B5D, + 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, + 0xC3F706FB, + 0xCEB42022, 0xCA753D95, 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, + 0xFF79A6F1, + 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, + 0x30476DC0, + 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, + 0x2AC12072, + 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, + 0x054BF6A4, + 0x0808D07D, 0x0CC9CDCA, 0x7897AB07, 0x7C56B6B0, 0x71159069, + 0x75D48DDE, + 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, + 0x5A5E5B08, + 0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, + 0x40D816BA, + 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, + 0xBB60ADFC, + 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, + 0x87EE0DF6, + 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, 0xE0B41DE7, + 0xE4750050, + 0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, + 0xFEF34DE2, + 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, + 0xD1799B34, + 0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, + 0x644FC637, + 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, 0x4F040D56, + 0x4BC510E1, + 0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, + 0x51435D53, + 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, + 0x32D850F5, + 0x3F9B762C, 0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, + 0x0E56F0FF, + 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E, + 0xF5EE4BB9, + 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, + 0xEF68060B, + 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, + 0xC0E2D0DD, + 0xCDA1F604, 0xC960EBB3, 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, + 0xB07DABA7, + 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, + 0x9FF77D71, + 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, + 0x857130C3, + 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, + 0x4A4FFBF2, + 0x470CDD2B, 0x43CDC09C, 0x7B827D21, 0x7F436096, 0x7200464F, + 0x76C15BF8, + 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, 0x119B4BE9, + 0x155A565E, + 0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, + 0x0FDC1BEC, + 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, + 0x2056CD3A, + 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, + 0xC8EA00A0, + 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, 0xE3A1CBC1, + 0xE760D676, + 0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, + 0xFDE69BC4, + 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, + 0x9E7D9662, + 0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF, + 0xA2F33668, + 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4 + }; + + u32 crc = 0; + while (len) { + crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *data) & 0xFF]; + + data++; + len--; + } + + return crc; +} + +static int calc_crc_in_flash(const struct cts_device *cts_dev, + u32 flash_addr, size_t size, u32 *crc) +{ + return cts_dev->hwdata->sfctrl->ops->calc_flash_crc(cts_dev, + flash_addr, size, + crc); +} + +static bool is_multi_section_firmware(const struct cts_firmware *firmware) +{ + return (firmware->size == CTS_FIRMWARE_MULTI_SECTION_FILE_SIZE); +} + +static bool is_single_section_firmware(const struct cts_firmware *firmware) +{ + return !(is_multi_section_firmware(firmware)); +} + +static bool is_firmware_size_valid(const struct cts_firmware *firmware) +{ + return (firmware->size > 0x102 && + firmware->size <= CTS_FIRMWARE_MULTI_SECTION_FILE_SIZE); +} + +static bool is_multi_section_firmware_valid(const struct cts_firmware *firmware) +{ + u32 crc; + + crc = + crc32(FIRMWARE_SECTION(firmware), FIRMWARE_SECTION_SIZE(firmware)); + if (crc != FIRMWARE_SECTION_CRC(firmware)) { + cts_err("Firmware-section crc mismatch crc-section %08x != %08x" + ", File maybe broken!!!", + crc, FIRMWARE_SECTION_CRC(firmware)); + return false; + } + + if (DDIPARAM_SECTION_ENABLE(firmware) == CTS_SECTION_ENABLE_FLAG) { + crc = + crc32(DDIPARAM_SECTION(firmware), + DDIPARAM_SECTION_SIZE(firmware)); + if (crc != DDIPARAM_SECTION_CRC(firmware)) { + cts_err + ("DDIParam-section crc mismatch crc-section %08x != %08x" + ", File maybe broken!!!", crc, + DDIPARAM_SECTION_CRC(firmware)); + return false; + } + } else { + cts_info("DDIParam-section is NOT enabled"); + } + + return true; +} + +static bool is_firmware_valid(const struct cts_firmware *firmware) +{ + if (firmware && firmware->data && is_firmware_size_valid(firmware)) { + if (is_single_section_firmware(firmware) || + is_multi_section_firmware_valid(firmware)) { + return true; + } + } + + return false; +} + +static void parse_single_section_firmware(const struct cts_firmware *firmware, + struct cts_firmware_sect_info *info) +{ + static u8 crc_sect[12]; + + info->firmware_sect = firmware->data; + info->firmware_sect_size = firmware->size; + info->firmware_sect_crc = crc32(firmware->data, firmware->size); + + put_unaligned_le32(info->firmware_sect_crc, crc_sect); + put_unaligned_le32(info->firmware_sect_size, crc_sect + 4); + put_unaligned_le32(~0x0000C35A, crc_sect + 8); /* Enable CRC check */ + info->firmware_crc_sect = crc_sect; + info->firmware_crc_sect_size = sizeof(crc_sect); +} + +static void parse_multi_section_firmware(const struct cts_firmware *firmware, + struct cts_firmware_sect_info *info) +{ + info->firmware_sect = FIRMWARE_SECTION(firmware); + info->firmware_sect_size = FIRMWARE_SECTION_SIZE(firmware); + info->firmware_crc_sect = FIRMWARE_CRC_SECTION(firmware); + info->firmware_crc_sect_size = FIRMWARE_CRC_SECTION_SIZE; + info->firmware_sect_crc = FIRMWARE_SECTION_CRC(firmware); + + if (DDIPARAM_SECTION_ENABLE(firmware) == CTS_SECTION_ENABLE_FLAG) { + info->ddiparam_sect = DDIPARAM_SECTION(firmware); + info->ddiparam_sect_size = DDIPARAM_SECTION_SIZE(firmware); + info->ddiparam_crc_sect = DDIPARAM_CRC_SECTION(firmware); + info->ddiparam_crc_sect_size = DDIPARAM_CRC_SECTION_SIZE; + info->ddiparam_sect_crc = DDIPARAM_SECTION_CRC(firmware); + } +} + +static int parse_firmware(const struct cts_firmware *firmware, + struct cts_firmware_sect_info *info) +{ + memset(info, 0, sizeof(*info)); + + if (is_multi_section_firmware(firmware)) { + parse_multi_section_firmware(firmware, info); + } else { + parse_single_section_firmware(firmware, info); + } + + cts_info(" Firmware section size: %zu", info->firmware_sect_size); + if (info->ddiparam_crc_sect) { + cts_info(" DDIParam section size: %zu", + info->ddiparam_sect_size); + } + + return 0; +} + +#ifdef CFG_CTS_DRIVER_BUILTIN_FIRMWARE +#ifdef CONFIG_CTS_SYSFS +int cts_get_num_driver_builtin_firmware(void) +{ + return NUM_DRIVER_BUILTIN_FIRMWARE; +} + +const struct cts_firmware *cts_request_driver_builtin_firmware_by_name(const + char + *name) +{ + const struct cts_firmware *firmware; + int i; + + cts_info("Request driver builtin by name '%s'", name); + + firmware = cts_driver_builtin_firmwares; + for (i = 0; i < NUM_DRIVER_BUILTIN_FIRMWARE; i++, firmware++) { + if (strcmp(firmware->name, name) == 0) { + if (is_firmware_valid(firmware)) { + cts_info("Found driver builtin '%s' " + "hwid: %06x fwid: %04x size: %zu ver: %04x", + firmware->name, firmware->hwid, + firmware->fwid, firmware->size, + FIRMWARE_VERSION(firmware)); + return firmware; + } + + cts_warn("Found driver builtin '%s' " + "hwid: %06x fwid: %04x size: %zu invalid", + firmware->name, firmware->hwid, firmware->hwid, + firmware->size); + } + } + + return NULL; +} + +const struct cts_firmware *cts_request_driver_builtin_firmware_by_index(u32 + index) +{ + const struct cts_firmware *firmware; + + cts_info("Request driver builtin by index %u", index); + + if (index < NUM_DRIVER_BUILTIN_FIRMWARE) { + firmware = cts_driver_builtin_firmwares + index; + if (is_firmware_valid(firmware)) { + cts_info("Found driver builtin '%s' " + "hwid: %06x fwid: %04x size: %zu ver: %04x", + firmware->name, firmware->hwid, firmware->fwid, + firmware->size, FIRMWARE_VERSION(firmware)); + return firmware; + } + cts_warn("Found driver builtin '%s' " + "hwid: %06x fwid: %04x size: %zu INVALID", + firmware->name, firmware->hwid, firmware->hwid, + firmware->size); + } else { + cts_warn("Request driver builtin by index %u too large >= %zu", + index, NUM_DRIVER_BUILTIN_FIRMWARE); + } + + return NULL; +} +#endif /* CONFIG_CTS_SYSFS */ + +static const struct cts_firmware *cts_request_newer_driver_builtin_firmware(u32 + hwid, + u16 + fwid, + u16 + device_fw_ver) +{ +#define MATCH_HWID(firmware, hwid) \ + ((hwid) == CTS_DEV_HWID_ANY || (firmware)->hwid == (hwid)) +#define MATCH_FWID(firmware, fwid) \ + ((fwid) == CTS_DEV_FWID_ANY || (firmware)->fwid == (fwid)) + + const struct cts_firmware *firmware = NULL; + int i; + + cts_info + ("Request driver builtin if match hwid: %06x fwid: %04x && ver > %04x", + hwid, fwid, device_fw_ver); + + firmware = cts_driver_builtin_firmwares; + for (i = 0; i < ARRAY_SIZE(cts_driver_builtin_firmwares); + i++, firmware++) { +// if (MATCH_HWID(firmware, hwid) && MATCH_FWID(firmware, fwid)) { + if (1) { + if (!is_firmware_valid(firmware)) { + cts_err("Found driver builtin '%s' " + "hwid: %06x fwid: %04x data: %p size: %zu INVALID", + firmware->name, firmware->hwid, + firmware->fwid, firmware->data, + firmware->size); + continue; + } + + cts_info("Found matched driver builtin '%s' " + "hwid: %06x fwid: %04x size: %zu ver: %04x", + firmware->name, firmware->hwid, firmware->fwid, + firmware->size, FIRMWARE_VERSION(firmware)); + +// if(FIRMWARE_VERSION(firmware) > device_fw_ver) { + if(1) { + cts_info("Found newer driver builtin '%s' " + "hwid: %06x fwid: %04x size: %zu ver: %04x > %04x", + firmware->name, firmware->hwid, + firmware->fwid, firmware->size, + FIRMWARE_VERSION(firmware), + device_fw_ver); + return firmware; + } + } + } + + cts_info("No newer driver builtin found"); + + return NULL; + +#undef MATCH_HWID +#undef MATCH_FWID +} +#endif /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */ + +#ifdef CFG_CTS_FIRMWARE_IN_FS +bool is_filesystem_mounted(const char *filepath) +{ + struct path root_path; + struct path path; + int ret; + + ret = kern_path("/", LOOKUP_FOLLOW, &root_path); + if (ret) { + return false; + } + + ret = kern_path(filepath, LOOKUP_FOLLOW, &path); + if (ret) { + goto err_put_root_path; + } + + if (path.mnt->mnt_sb == root_path.mnt->mnt_sb) { + /* not mounted */ + ret = false; + } else { + ret = true; + } + + path_put(&path); +err_put_root_path: + path_put(&root_path); + + return !!ret; +} + +static int cts_request_firmware_full_filepath(struct cts_firmware *firmware, + const char *filepath, + int curr_version) +{ + struct file *file; + u16 version; + u8 buff[2]; + loff_t pos = 0; + int read_size; + int ret = 0; + + file = filp_open(filepath, O_RDONLY, 0); + if (IS_ERR(file)) { + cts_err("Open file '%s' failed %ld", filepath, PTR_ERR(file)); + return PTR_ERR(file); + } + + firmware->size = file_inode(file)->i_size; + if (!is_firmware_size_valid(firmware)) { + cts_info("File '%s' size: %zu invalid", filepath, + firmware->size); + ret = -EINVAL; + goto err_close_file; + } + + pos = FIRMWARE_VERSION_OFFSET; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) + read_size = kernel_read(file, buff, 2, &pos); +#else + read_size = kernel_read(file, pos, buff, 2); +#endif + if (read_size < 0) { + cts_err("Read version from offset 0x100 failed"); + ret = -EIO; + goto err_close_file; + } + version = get_unaligned_le16(buff); + + if (version <= curr_version) { + cts_info("File '%s' size: %zu version: %04x <= %04x", + filepath, firmware->size, version, curr_version); + ret = -EINVAL; + goto err_close_file; + } + + cts_info("File '%s' size: %zu version: %04x", + filepath, firmware->size, version); + + firmware->data = (u8 *) vmalloc(firmware->size); + if (firmware->data == NULL) { + cts_err("Request form fs alloc firmware data failed"); + ret = -ENOMEM; + goto err_close_file; + } + + pos = 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) + read_size = kernel_read(file, firmware->data, firmware->size, &pos); +#else + read_size = kernel_read(file, pos, firmware->data, firmware->size); +#endif + if (read_size < 0 || read_size != firmware->size) { + cts_err("Request from fs read whole file failed %d", read_size); + ret = -EIO; + goto err_free_firmware_data; + } + + { + int r = filp_close(file, NULL); + if (r) { + cts_warn("Close file '%s' failed %d", filepath, r); + } + } + + return 0; + +err_free_firmware_data: + vfree(firmware->data); + firmware->data = NULL; + +err_close_file:{ + int r = filp_close(file, NULL); + if (r) { + cts_warn("Close file '%s' failed %d", filepath, r); + } + } + + return ret; +} + +static int cts_wrap_request_firmware(struct cts_firmware *firmware, + const char *name, struct device *device, + int curr_version) +{ + int ret; + + ret = request_firmware(&firmware->fw, name, device); + if (ret) { + cts_err("Could not load firmware from %s: %d", name, ret); + return ret; + } + + /* Map firmware structure to cts_firmware */ + firmware->data = (u8 *) firmware->fw->data; + firmware->size = firmware->fw->size; + + /* Check firmware */ + if (!is_firmware_valid(firmware)) { + cts_err("Request firmware file INVALID, size %zu", + firmware->size); + ret = -EINVAL; + goto err_release_firmware; + } + + /* Check firmware version */ + if (curr_version > 0 && curr_version >= FIRMWARE_VERSION(firmware)) { + cts_info("Request firmware file with version 0x%04x < 0x%04x", + FIRMWARE_VERSION(firmware), curr_version); + ret = -EINVAL; + goto err_release_firmware; + } + + return 0; + +err_release_firmware: + release_firmware(firmware->fw); + + return ret; +} + +const struct cts_firmware *cts_request_newer_firmware_from_fs(const struct + cts_device + *cts_dev, + const char + *filepath, + u16 curr_version) +{ + struct cts_firmware *firmware = NULL; + int ret = 0; + + cts_info("Request from file '%s' if version > %04x", + filepath, curr_version); + + if (filepath == NULL || filepath[0] == '\0') { + cts_err("Request from file path INVALID %p", filepath); + return NULL; + } + + firmware = + (struct cts_firmware *)kzalloc(sizeof(*firmware), GFP_KERNEL); + if (firmware == NULL) { + cts_err("Request from file alloc struct cts_firmware failed"); + return NULL; + } + + if (strchr(filepath, '/') != NULL) { /* Full path */ + cts_info("Filepath is fullpath, direct read it out"); + ret = cts_request_firmware_full_filepath(firmware, + filepath, + curr_version); + } else { /* ONLY file name is givin */ + cts_info("Filepath is only filename, use request_firmware()"); + ret = cts_wrap_request_firmware(firmware, filepath, + &cts_dev->pdata->ts_input_dev-> + dev, curr_version); + } + + if (ret) { + cts_err("Request from file '%s' failed %d", filepath, ret); + kfree(firmware); + return NULL; + } else { + return firmware; + } +} + +const struct cts_firmware *cts_request_firmware_from_fs(const struct cts_device + *cts_dev, + const char *filepath) +{ + cts_info("Request from file '%s'", filepath); + + return cts_request_newer_firmware_from_fs(cts_dev, filepath, 0); +} + +int cts_update_firmware_from_file(struct cts_device *cts_dev, + const char *filepath, bool to_flash) +{ + const struct cts_firmware *firmware; + int ret; + + cts_info("Update from file '%s' to %s", filepath, + to_flash ? "flash" : "sram"); + + firmware = cts_request_firmware_from_fs(cts_dev, filepath); + if (firmware == NULL) { + cts_err("Request from file '%s' failed", filepath); + return -EFAULT; + } + + ret = cts_update_firmware(cts_dev, firmware, to_flash); + if (ret) { + cts_err("Update to %s from file failed %d", + to_flash ? "flash" : "sram", ret); + goto err_release_firmware; + } + + cts_info("Update from file success"); + +err_release_firmware: + cts_release_firmware(firmware); + + return ret; +} +#endif /*CFG_CTS_FIRMWARE_IN_FS */ + +const struct cts_firmware *cts_request_firmware(const struct cts_device + *cts_dev, u32 hwid, u16 fwid, + u16 curr_firmware_ver) +{ + const struct cts_firmware *firmware_builtin = NULL; + const struct cts_firmware *firmware_from_file = NULL; + + if (hwid == CTS_DEV_HWID_INVALID) { + hwid = CTS_DEV_HWID_ANY; + } + if (fwid == CTS_DEV_FWID_INVALID) { + fwid = CTS_DEV_FWID_ANY; + } + + cts_info("Request newer if match hwid: %06x fwid: %04x && ver > %04x", + hwid, fwid, curr_firmware_ver); + +#ifdef CFG_CTS_DRIVER_BUILTIN_FIRMWARE + firmware_builtin = + cts_request_newer_driver_builtin_firmware(hwid, fwid, + curr_firmware_ver); +#endif /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */ + +#ifdef CFG_CTS_FIRMWARE_IN_FS + /* Check firmware in file system when probe only when build to .ko */ + if (is_filesystem_mounted(CFG_CTS_FIRMWARE_FILEPATH)) { + firmware_from_file = cts_request_newer_firmware_from_fs(cts_dev, +#ifdef CFG_CTS_FW_UPDATE_FILE_LOAD + cts_dev-> + config_fw_name + [0] ? + cts_dev-> + config_fw_name + : +// CFG_CTS_FIRMWARE_FILEPATH, + CFG_CTS_FIRMWARE_FILENAME, +#else /* CFG_CTS_FW_UPDATE_FILE_LOAD */ +// CFG_CTS_FIRMWARE_FILEPATH, + CFG_CTS_FIRMWARE_FILENAME, +#endif /* CFG_CTS_FW_UPDATE_FILE_LOAD */ + firmware_builtin + ? + FIRMWARE_VERSION + (firmware_builtin) + : + curr_firmware_ver); + } +#endif /* CFG_CTS_FIRMWARE_IN_FS */ + + return firmware_from_file ? firmware_from_file : firmware_builtin; +} + +void cts_release_firmware(const struct cts_firmware *firmware) +{ + cts_info("Release firmware %p", firmware); + + if (firmware) { + if (firmware->fw) { + /* Use request_firmware() get struct firmware * */ + cts_info("Release firmware from request_firmware"); + release_firmware(firmware->fw); + kfree(firmware); + } else if (firmware->name == NULL) { + /* Direct read from file */ + cts_info("Release firmware from direct-load"); + vfree(firmware->data); + kfree(firmware); + } else { + /* Builtin firmware with non-NULL name, no need to free */ + cts_info("Release firmware from driver built-in"); + } + } +} + +static int validate_flash_data(const struct cts_device *cts_dev, + u32 flash_addr, const u8 *data, size_t size, + u8 *buf, bool calc_crc, u32 crc) +{ + int ret, i; + bool free_data = false; + u32 crc_flash; + + cts_info("Validate flash data from 0x%06x size %zu by %s", + flash_addr, size, calc_crc ? "check-crc" : "direct-readback"); + + if (calc_crc) { + ret = calc_crc_in_flash(cts_dev, flash_addr, size, &crc_flash); + if (ret) { + cts_err + ("Calc data in flash from 0x%06x size %zu crc failed %d, " + "try to validate by direct readback", flash_addr, + size, ret); + // FALL through by direct compare data read back + } else { + if (crc_flash != crc) { + cts_err + ("Crc in flash from 0x%06x size %zu mismatch 0x%08x != 0x%08x", + flash_addr, size, crc_flash, crc); + // FALL through by direct compare data read back + } else { + cts_info("Flash data crc correct"); + return 0; + } + } + } + + if (buf == NULL) { + buf = (u8 *) kmalloc(size, GFP_KERNEL); + if (buf == NULL) { + cts_err("Validate flash data allocate mem failed"); + return -ENOMEM; + } + + free_data = true; + } + + ret = cts_read_flash(cts_dev, flash_addr, buf, size); + if (ret) { + cts_err("Read flash from 0x%06x size %zu failed %d", + flash_addr, size, ret); + goto err_free_buf; + } + + for (i = 0; i < size; i++) { + if (buf[i] != data[i]) { + if (ret == 0) { + cts_err + ("Flash data from 0x%06x size %zu first bytes diff:", + flash_addr, size); + } + + if (ret < 100) { + cts_err(" 0x%06x: %02x %02x", i, buf[i], + data[i]); + } else if (ret == 100) { + cts_err(" ..."); + } + ret++; + } + } + +err_free_buf: + if (free_data) { + kfree(buf); + } + + return ret; +} + +static int cts_program_firmware(const struct cts_device *cts_dev, const struct cts_firmware_sect_info + *firmware_info) +{ + int ret; + u8 crc_sect_buf[FIRMWARE_CRC_SECTION_SIZE]; + + cts_info("Program firmware size %zu", + firmware_info->firmware_sect_size); + + /* Write firmware to SRAM for easy enter normal mode after update */ + cts_info("Write firmware section to sram"); + ret = cts_sram_writesb_check_crc_retry(cts_dev, + 0, firmware_info->firmware_sect, + firmware_info-> + firmware_sect_size, + firmware_info->firmware_sect_crc, + 3); + if (ret) { + cts_err("Write firmware section to sram failed %d", ret); + return ret; + } + + ret = cts_program_flash_from_sram(cts_dev, + 4, 4, + firmware_info->firmware_sect_size - + 4); + if (ret) { + cts_err("Program firmware section from sram failed %d", ret); + return ret; + } + + ret = cts_program_flash(cts_dev, + CTS_FIRMWARE_CRC_SECTION_OFFSET, + firmware_info->firmware_crc_sect, + firmware_info->firmware_crc_sect_size); + if (ret) { + cts_err("Program firmware crc section failed %d", ret); + return ret; + } + + ret = validate_flash_data(cts_dev, + CTS_FIRMWARE_CRC_SECTION_OFFSET, + firmware_info->firmware_crc_sect, + firmware_info->firmware_crc_sect_size, + crc_sect_buf, false, 0); + if (ret) { + cts_err("Validate Firmware-CRC section failed %d", ret); + return ret; + } + + ret = cts_program_flash(cts_dev, 0, firmware_info->firmware_sect, 4); + if (ret) { + cts_err("Program firmware section fist 4bytes failed %d", ret); + return ret; + } + + ret = validate_flash_data(cts_dev, + CTS_FIRMWARE_SECTION_OFFSET, + firmware_info->firmware_sect, + firmware_info->firmware_sect_size, NULL, true, + firmware_info->firmware_sect_crc); + if (ret) { + cts_err("Validate firmware section failed %d", ret); + return ret; + } + + return 0; +} + +static int cts_program_ddiparam(const struct cts_device *cts_dev, const struct cts_firmware_sect_info + *firmware_info) +{ + int ret; + u8 crc_sect_buf[DDIPARAM_CRC_SECTION_SIZE]; + + cts_info("Program DDIParam size: %zu", + firmware_info->ddiparam_sect_size); + + ret = cts_program_flash(cts_dev, CTS_DDIPARAM_SECTION_OFFSET, + firmware_info->ddiparam_sect, + firmware_info->ddiparam_sect_size); + if (ret) { + cts_err("Program DDIParam section failed %d", ret); + return ret; + } + + ret = validate_flash_data(cts_dev, + CTS_DDIPARAM_SECTION_OFFSET, + firmware_info->ddiparam_sect, + firmware_info->ddiparam_sect_size, NULL, true, + firmware_info->ddiparam_sect_crc); + if (ret) { + cts_err("Validate DDIParam section failed %d", ret); + return ret; + } + + ret = cts_program_flash(cts_dev, CTS_DDIPARAM_CRC_SECTION_OFFSET, + firmware_info->ddiparam_crc_sect, + firmware_info->ddiparam_crc_sect_size); + if (ret) { + cts_err("Program DDIParam-CRC section failed %d", ret); + return ret; + } + + ret = validate_flash_data(cts_dev, + CTS_DDIPARAM_CRC_SECTION_OFFSET, + firmware_info->ddiparam_crc_sect, + firmware_info->ddiparam_crc_sect_size, + crc_sect_buf, false, 0); + if (ret) { + cts_err("Validate DDIParam-CRC section failed %d", ret); + return ret; + } + + return 0; +} + +int cts_update_firmware(struct cts_device *cts_dev, + const struct cts_firmware *firmware, bool to_flash) +{ + struct cts_firmware_sect_info firmware_info; + int ret, retries; + + cts_info("Update firmware to %s ver: %04x size: %zu", + to_flash ? "flash" : "sram", + FIRMWARE_VERSION(firmware), firmware->size); + + if (parse_firmware(firmware, &firmware_info)) { + cts_err("Parse firmware failed"); + return -EINVAL; + } + + cts_dev->rtdata.updating = true; + + ret = cts_enter_program_mode(cts_dev); + if (ret) { + cts_err("Device enter program mode failed %d", ret); + goto out; + } + + ret = cts_prepare_flash_operation(cts_dev); + if (ret) { + cts_warn("Prepare flash operation failed %d", ret); + // Go through and try + } + + if (!to_flash || !cts_dev->rtdata.has_flash) { + cts_info("Write firmware section to sram size %zu", + firmware_info.firmware_sect_size); + ret = cts_sram_writesb_check_crc_retry(cts_dev, + 0, + firmware_info. + firmware_sect, + firmware_info. + firmware_sect_size, + firmware_info. + firmware_sect_crc, 3); + if (ret) { + cts_err("Write firmware section to sram failed %d", + ret); + } +#ifdef CFG_CTS_UPDATE_CRCCHECK + if (cts_dev->hwdata->hwid == CTS_DEV_HWID_ICNL9911S) { + cts_sram_writesb_boot_crc_retry(cts_dev, + firmware_info. + firmware_sect_size, + firmware_info. + firmware_sect_crc, 3); + } +#endif + goto out; + } + + retries = 0; + do { + retries++; + + ret = cts_erase_flash(cts_dev, CTS_FIRMWARE_CRC_SECTION_OFFSET, + firmware_info.firmware_crc_sect_size); + if (ret) { + cts_err + ("Erase firmware crc section failed %d retries %d", + ret, retries); + continue; + } + + ret = + cts_erase_flash(cts_dev, 0, + firmware_info.firmware_sect_size); + if (ret) { + cts_err("Erase firmware section failed %d retries %d", + ret, retries); + continue; + } + + ret = cts_program_firmware(cts_dev, &firmware_info); + if (ret) { + cts_err + ("Program firmware & crc section failed %d retries %d", + ret, retries); + } + } while (ret && retries < 3); + + if (ret == 0 && firmware_info.ddiparam_sect_size != 0) { + retries = 0; + do { + retries++; + + ret = + cts_erase_flash(cts_dev, + CTS_DDIPARAM_CRC_SECTION_OFFSET, + firmware_info.ddiparam_crc_sect_size); + if (ret) { + cts_err + ("Erase DDIParam crc secction failed %d, retries %d", + ret, retries); + continue; + } + + ret = + cts_erase_flash(cts_dev, + CTS_DDIPARAM_SECTION_OFFSET, + firmware_info.ddiparam_sect_size); + if (ret) { + cts_err + ("Erase DDIParam section failed %d, retries %d", + ret, retries); + continue; + } + + ret = cts_program_ddiparam(cts_dev, &firmware_info); + if (ret) { + cts_err + ("Program DDIParam & crc section failed %d retries %d", + ret, retries); + } + } while (ret && retries < 3); + } + + cts_post_flash_operation(cts_dev); + +out: + cts_dev->rtdata.updating = false; + + if (ret == 0) { + if (firmware_info.firmware_sect_size <= + cts_dev->hwdata->sfctrl->xchg_sram_base) { + ret = cts_enter_normal_mode(cts_dev); + if (ret) { + cts_err("Enter normal mode failed %d", ret); + //return ret; + } + } + } + +#ifdef CONFIG_CTS_CHARGER_DETECT + if (cts_is_charger_exist(cts_dev)) { + cts_charger_plugin(cts_dev); + } +#endif /* CONFIG_CTS_CHARGER_DETECT */ + +#ifdef CONFIG_CTS_GLOVE + if (cts_is_glove_enabled(cts_dev)) { + cts_enter_glove_mode(cts_dev); + } +#endif + +#ifdef CFG_CTS_FW_LOG_REDIRECT + if (cts_is_fw_log_redirect(cts_dev)) { + cts_enable_fw_log_redirect(cts_dev); + } +#endif + + return ret; +} + +bool cts_is_firmware_updating(const struct cts_device *cts_dev) +{ + return cts_dev->rtdata.updating; +} diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_firmware.h b/drivers/input/touchscreen/chipone_tddi_mmi/cts_firmware.h old mode 100755 new mode 100644 index bde43ac94ac4..2039b9dd8556 --- a/drivers/input/touchscreen/chipone_tddi_mmi/cts_firmware.h +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_firmware.h @@ -1,49 +1,68 @@ -#ifndef CTS_FIRMWARE_H -#define CTS_FIRMWARE_H - -#include "cts_config.h" - -struct cts_firmware { - const char *name; /* MUST set to non-NULL if driver builtin firmware */ - u32 hwid; - u16 fwid; - - u8 *data; - size_t size; - -}; - -#define FIRMWARE_VERSION_OFFSET 0x100 -#define FIRMWARE_VERSION(firmware) \ - get_unaligned_le16((firmware)->data + FIRMWARE_VERSION_OFFSET) - -struct cts_device; - -extern const struct cts_firmware *cts_request_firmware( - u32 hwid, u16 fwid, u16 device_fw_ver); -extern void cts_release_firmware(const struct cts_firmware *firmware); - -#ifdef CFG_CTS_DRIVER_BUILTIN_FIRMWARE -extern int cts_get_num_driver_builtin_firmware(void); -extern const struct cts_firmware *cts_request_driver_builtin_firmware_by_name(const char *name); -extern const struct cts_firmware *cts_request_driver_builtin_firmware_by_index(u32 index); -#else /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */ -static inline int cts_get_num_driver_builtin_firmware(void) {return 0;} -static inline const struct cts_firmware *cts_request_driver_builtin_firmware_by_name(const char *name) {return NULL;} -static inline const struct cts_firmware *cts_request_driver_builtin_firmware_by_index(u32 index) {return NULL;} -#endif /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */ -extern bool cts_is_firmware_updating(const struct cts_device *cts_dev); - -extern int cts_update_firmware(struct cts_device *cts_dev, - const struct cts_firmware *firmware, bool to_flash); - -#ifdef CFG_CTS_FIRMWARE_IN_FS -extern const struct cts_firmware *cts_request_firmware_from_fs(const char *filepath); -extern int cts_update_firmware_from_file( - struct cts_device *cts_dev, const char *filepath, bool to_flash); -#endif /* CFG_CTS_FIRMWARE_IN_FS */ - -extern u32 crc32(const u8 *data, size_t len); - -#endif /* CTS_FIRMWARE_H */ - +#ifndef CTS_FIRMWARE_H +#define CTS_FIRMWARE_H + +#include "cts_config.h" +#include + +struct cts_firmware { + const char *name; /* MUST set to non-NULL if driver builtin firmware */ + u32 hwid; + u16 fwid; + + u8 *data; + size_t size; + const struct firmware *fw; +}; + +#define FIRMWARE_VERSION_OFFSET 0x100 +#define FIRMWARE_VERSION(firmware) \ + get_unaligned_le16((firmware)->data + FIRMWARE_VERSION_OFFSET) + +struct cts_device; + +extern const struct cts_firmware *cts_request_firmware( + const struct cts_device *cts_dev, + u32 hwid, u16 fwid, u16 device_fw_ver); +extern void cts_release_firmware(const struct cts_firmware *firmware); + +#ifdef CFG_CTS_DRIVER_BUILTIN_FIRMWARE +extern int cts_get_num_driver_builtin_firmware(void); +extern const struct cts_firmware + *cts_request_driver_builtin_firmware_by_name(const char *name); +extern const struct cts_firmware + *cts_request_driver_builtin_firmware_by_index(u32 index); +#else /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */ +static inline int cts_get_num_driver_builtin_firmware(void) +{ + return 0; +} + +static inline const struct cts_firmware + *cts_request_driver_builtin_firmware_by_name(const char *name) +{ + return NULL; +} + +static inline const struct cts_firmware + *cts_request_driver_builtin_firmware_by_index(u32 index) +{ + return NULL; +} +#endif /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */ +extern bool cts_is_firmware_updating(const struct cts_device *cts_dev); + +extern int cts_update_firmware(struct cts_device *cts_dev, + const struct cts_firmware *firmware, + bool to_flash); + +#ifdef CFG_CTS_FIRMWARE_IN_FS +extern const struct cts_firmware *cts_request_firmware_from_fs( + const struct cts_device *cts_dev, const char *filepath); +extern int cts_update_firmware_from_file(struct cts_device *cts_dev, + const char *filepath, bool to_flash); + +#endif /* CFG_CTS_FIRMWARE_IN_FS */ + +extern u32 crc32(const u8 *data, size_t len); + +#endif /* CTS_FIRMWARE_H */ diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_i2c_driver.c b/drivers/input/touchscreen/chipone_tddi_mmi/cts_i2c_driver.c old mode 100755 new mode 100644 index d500058ea049..c9328fdb6c98 --- a/drivers/input/touchscreen/chipone_tddi_mmi/cts_i2c_driver.c +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_i2c_driver.c @@ -4,100 +4,112 @@ #include "cts_platform.h" #include "cts_core.h" #include "cts_sysfs.h" +#include "cts_charger_detect.h" + #ifdef CFG_CTS_DRM_NOTIFIER #include static struct drm_panel *active_panel; static int check_dt(struct device_node *np); -//static int chipone_drm_notifier_callback(struct notifier_block *self, unsigned long event, void *data); +static void cts_resume_work_func(struct work_struct *work); #endif bool cts_show_debug_log = false; + module_param_named(debug_log, cts_show_debug_log, bool, 0660); MODULE_PARM_DESC(debug_log, "Show debug log control"); static int cts_suspend(struct chipone_ts_data *cts_data) { - int ret; + int ret; - cts_info("Suspend"); + cts_info("Suspend"); - cts_lock_device(&cts_data->cts_dev); - ret = cts_suspend_device(&cts_data->cts_dev); - cts_unlock_device(&cts_data->cts_dev); + cts_lock_device(&cts_data->cts_dev); + ret = cts_suspend_device(&cts_data->cts_dev); + cts_unlock_device(&cts_data->cts_dev); - if (ret) { - cts_err("Suspend device failed %d", ret); - // TODO: - //return ret; - } - - ret = cts_stop_device(&cts_data->cts_dev); - if (ret) { - cts_err("Stop device failed %d", ret); - return ret; - } + if (ret) { + cts_err("Suspend device failed %d", ret); + // TODO: + //return ret; + } + ret = cts_stop_device(&cts_data->cts_dev); + if (ret) { + cts_err("Stop device failed %d", ret); + return ret; + } #ifdef CFG_CTS_GESTURE - /* Enable IRQ wake if gesture wakeup enabled */ - if (cts_is_gesture_wakeup_enabled(&cts_data->cts_dev)) { - ret = cts_plat_enable_irq_wake(cts_data->pdata); - if (ret) { - cts_err("Enable IRQ wake failed %d", ret); - return ret; - } - ret = cts_plat_enable_irq(cts_data->pdata); - if (ret){ - cts_err("Enable IRQ failed %d",ret); - return ret; - } - } + /* Enable IRQ wake if gesture wakeup enabled */ + if (cts_is_gesture_wakeup_enabled(&cts_data->cts_dev)) { + ret = cts_plat_enable_irq_wake(cts_data->pdata); + if (ret) { + cts_err("Enable IRQ wake failed %d", ret); + return ret; + } + ret = cts_plat_enable_irq(cts_data->pdata); + if (ret) { + cts_err("Enable IRQ failed %d", ret); + return ret; + } + } #endif /* CFG_CTS_GESTURE */ /** - To avoid waking up while not sleeping, - delay 20ms to ensure reliability */ - msleep(20); + delay 20ms to ensure reliability */ + msleep(20); - return 0; + return 0; } static int cts_resume(struct chipone_ts_data *cts_data) { - int ret; + int ret; - cts_info("Resume"); + cts_info("Resume"); #ifdef CFG_CTS_GESTURE - if (cts_is_gesture_wakeup_enabled(&cts_data->cts_dev)) { - ret = cts_plat_disable_irq_wake(cts_data->pdata); - if (ret) { - cts_warn("Disable IRQ wake failed %d", ret); - //return ret; - } - if ((ret = cts_plat_disable_irq(cts_data->pdata)) < 0) { - cts_err("Disable IRQ failed %d", ret); - //return ret; - } - } + if (cts_is_gesture_wakeup_enabled(&cts_data->cts_dev)) { + ret = cts_plat_disable_irq_wake(cts_data->pdata); + if (ret) { + cts_warn("Disable IRQ wake failed %d", ret); + //return ret; + } + ret = cts_plat_disable_irq(cts_data->pdata); + if (ret < 0) { + cts_err("Disable IRQ failed %d", ret); + //return ret; + } + } #endif /* CFG_CTS_GESTURE */ - ret = cts_resume_device(&cts_data->cts_dev); - if(ret) { - cts_warn("Resume device failed %d", ret); - return ret; - } + cts_lock_device(&cts_data->cts_dev); + ret = cts_resume_device(&cts_data->cts_dev); + cts_unlock_device(&cts_data->cts_dev); + if (ret) { + cts_warn("Resume device failed %d", ret); + return ret; + } - ret = cts_start_device(&cts_data->cts_dev); - if (ret) { - cts_err("Start device failed %d", ret); - return ret; - } + ret = cts_start_device(&cts_data->cts_dev); + if (ret) { + cts_err("Start device failed %d", ret); + return ret; + } - return 0; + return 0; } #ifdef CONFIG_CTS_PM_FB_NOTIFIER #ifdef CFG_CTS_DRM_NOTIFIER +static void cts_resume_work_func(struct work_struct *work) +{ + struct chipone_ts_data *cts_data = + container_of(work, struct chipone_ts_data, ts_resume_work); + cts_info("%s", __func__); + cts_resume(cts_data); +} static int fb_notifier_callback(struct notifier_block *nb, - unsigned long action, void *data) + unsigned long action, void *data) { volatile int blank; const struct cts_platform_data *pdata = @@ -120,8 +132,9 @@ static int fb_notifier_callback(struct notifier_block *nb, } else if (evdata->data) { blank = *(int *)evdata->data; if (action == DRM_PANEL_EVENT_BLANK) { - if (blank == DRM_PANEL_BLANK_UNBLANK) { - cts_resume(cts_data); + if (blank == DRM_PANEL_BLANK_UNBLANK) { +// cts_resume(cts_data); + queue_work(cts_data->workqueue, &cts_data->ts_resume_work); } } } @@ -130,46 +143,46 @@ static int fb_notifier_callback(struct notifier_block *nb, } #else static int fb_notifier_callback(struct notifier_block *nb, - unsigned long action, void *data) + unsigned long action, void *data) { - volatile int blank; - const struct cts_platform_data *pdata = - container_of(nb, struct cts_platform_data, fb_notifier); - struct chipone_ts_data *cts_data = - container_of(pdata->cts_dev, struct chipone_ts_data, cts_dev); + volatile int blank; + const struct cts_platform_data *pdata = + container_of(nb, struct cts_platform_data, fb_notifier); + struct chipone_ts_data *cts_data = + container_of(pdata->cts_dev, struct chipone_ts_data, cts_dev); struct fb_event *evdata = data; - cts_info("FB notifier callback"); + cts_info("FB notifier callback"); - if (evdata && evdata->data) { - if (action == FB_EVENT_BLANK) { - blank = *(int *)evdata->data; - if (blank == FB_BLANK_UNBLANK) { - cts_resume(cts_data); - return NOTIFY_OK; - } - } else if (action == FB_EARLY_EVENT_BLANK) { - blank = *(int *)evdata->data; - if (blank == FB_BLANK_POWERDOWN) { - cts_suspend(cts_data); - return NOTIFY_OK; - } - } - } + if (evdata && evdata->data) { + if (action == FB_EVENT_BLANK) { + blank = *(int *)evdata->data; + if (blank == FB_BLANK_UNBLANK) { + cts_resume(cts_data); + return NOTIFY_OK; + } + } else if (action == FB_EARLY_EVENT_BLANK) { + blank = *(int *)evdata->data; + if (blank == FB_BLANK_POWERDOWN) { + cts_suspend(cts_data); + return NOTIFY_OK; + } + } + } - return NOTIFY_DONE; + return NOTIFY_DONE; } #endif -static int cts_init_pm_fb_notifier(struct chipone_ts_data * cts_data) +static int cts_init_pm_fb_notifier(struct chipone_ts_data *cts_data) { - cts_info("Init FB notifier"); + cts_info("Init FB notifier"); - cts_data->pdata->fb_notifier.notifier_call = fb_notifier_callback; + cts_data->pdata->fb_notifier.notifier_call = fb_notifier_callback; #ifdef CFG_CTS_DRM_NOTIFIER { - int ret = -1; + int ret = -ENODEV; if (active_panel) { ret = drm_panel_notifier_register(active_panel, &cts_data->pdata->fb_notifier); if(ret) { @@ -179,13 +192,13 @@ static int cts_init_pm_fb_notifier(struct chipone_ts_data * cts_data) return ret; } #else - return fb_register_client(&cts_data->pdata->fb_notifier); + return fb_register_client(&cts_data->pdata->fb_notifier); #endif -} +} -static int cts_deinit_pm_fb_notifier(struct chipone_ts_data * cts_data) +static int cts_deinit_pm_fb_notifier(struct chipone_ts_data *cts_data) { - cts_info("Deinit FB notifier"); + cts_info("Deinit FB notifier"); #ifdef CFG_CTS_DRM_NOTIFIER { int ret = 0; @@ -197,10 +210,11 @@ static int cts_deinit_pm_fb_notifier(struct chipone_ts_data * cts_data) return ret; } #else - return fb_unregister_client(&cts_data->pdata->fb_notifier); + return fb_unregister_client(&cts_data->pdata->fb_notifier); #endif -} +} #endif /* CONFIG_CTS_PM_FB_NOTIFIER */ + static int check_dt(struct device_node *np) { int i; @@ -226,11 +240,16 @@ static int check_dt(struct device_node *np) return -ENODEV; } -struct chipone_ts_data *g_cts_data; +#ifdef CONFIG_CTS_I2C_HOST +static int cts_driver_probe(struct i2c_client *client, + const struct i2c_device_id *id) +#else static int cts_driver_probe(struct spi_device *client) +#endif { - struct chipone_ts_data *cts_data = NULL; - int ret = 0; + struct chipone_ts_data *cts_data = NULL; + int ret = 0; + { struct device_node *dp = client->dev.of_node; if (check_dt(dp)) { @@ -238,222 +257,267 @@ static int cts_driver_probe(struct spi_device *client) return -ENODEV; } } +#ifdef CONFIG_CTS_I2C_HOST + cts_info("Probe i2c client: name='%s' addr=0x%02x flags=0x%02x irq=%d", + client->name, client->addr, client->flags, client->irq); +#if !defined(CONFIG_MTK_PLATFORM) + if (client->addr != CTS_DEV_NORMAL_MODE_I2CADDR) { + cts_err("Probe i2c addr 0x%02x != driver config addr 0x%02x", + client->addr, CTS_DEV_NORMAL_MODE_I2CADDR); + return -ENODEV; + }; +#endif - cts_data = (struct chipone_ts_data *)kzalloc(sizeof(*cts_data), GFP_KERNEL); - if (cts_data == NULL) { - cts_err("Allocate chipone_ts_data failed"); - return -ENOMEM; - } -g_cts_data = cts_data; - cts_data->pdata = (struct cts_platform_data *)kzalloc( - sizeof(struct cts_platform_data), GFP_KERNEL); - if (cts_data->pdata == NULL) { - cts_err("Allocate cts_platform_data failed"); - ret = -ENOMEM; - goto err_free_cts_data; - } + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + cts_err("Check functionality failed"); + return -ENODEV; + } +#endif + cts_data = + (struct chipone_ts_data *)kzalloc(sizeof(*cts_data), GFP_KERNEL); + if (cts_data == NULL) { + cts_err("Allocate chipone_ts_data failed"); + return -ENOMEM; + } + cts_data->pdata = + (struct cts_platform_data *) + kzalloc(sizeof(struct cts_platform_data), GFP_KERNEL); + if (cts_data->pdata == NULL) { + cts_err("Allocate cts_platform_data failed"); + ret = -ENOMEM; + goto err_free_cts_data; + } +#ifdef CONFIG_CTS_I2C_HOST + i2c_set_clientdata(client, cts_data); + cts_data->i2c_client = client; + cts_data->device = &client->dev; +#else spi_set_drvdata(client, cts_data); cts_data->spi_client = client; - - - cts_init_platform_data(cts_data->pdata, client); - - cts_data->cts_dev.pdata = cts_data->pdata; - cts_data->pdata->cts_dev = &cts_data->cts_dev; - - cts_data->workqueue = create_singlethread_workqueue(CFG_CTS_DEVICE_NAME "-workqueue"); - if (cts_data->workqueue == NULL) { - cts_err("Create workqueue failed"); - ret = -ENOMEM; - goto err_deinit_platform_data; - } - -#ifdef CONFIG_CTS_ESD_PROTECTION - cts_data->esd_workqueue = create_singlethread_workqueue(CFG_CTS_DEVICE_NAME "-esd_workqueue"); - if (cts_data->esd_workqueue == NULL) { - cts_err("Create esd workqueue failed"); - ret = -ENOMEM; - goto err_destroy_workqueue; - } + cts_data->device = &client->dev; #endif - ret = cts_plat_request_resource(cts_data->pdata); - if (ret < 0) { - cts_err("Request resource failed %d", ret); - goto err_destroy_esd_workqueue; - } - ret = cts_plat_reset_device(cts_data->pdata); - if (ret < 0) { - cts_err("Reset device failed %d", ret); - goto err_free_resource; - } + cts_init_platform_data(cts_data->pdata, client); - ret = cts_probe_device(&cts_data->cts_dev); - if (ret) { - cts_err("Probe device failed %d", ret); - goto err_free_resource; - } + cts_data->cts_dev.pdata = cts_data->pdata; + cts_data->pdata->cts_dev = &cts_data->cts_dev; - ret = cts_plat_init_touch_device(cts_data->pdata); - if (ret < 0) { - cts_err("Init touch device failed %d", ret); - goto err_free_resource; - } + cts_data->workqueue = + create_singlethread_workqueue(CFG_CTS_DEVICE_NAME "-workqueue"); + if (cts_data->workqueue == NULL) { + cts_err("Create workqueue failed"); + ret = -ENOMEM; + goto err_deinit_platform_data; + } +#ifdef CONFIG_CTS_ESD_PROTECTION + cts_data->esd_workqueue = + create_singlethread_workqueue(CFG_CTS_DEVICE_NAME "-esd_workqueue"); + if (cts_data->esd_workqueue == NULL) { + cts_err("Create esd workqueue failed"); + ret = -ENOMEM; + goto err_destroy_workqueue; + } +#endif + ret = cts_plat_request_resource(cts_data->pdata); + if (ret < 0) { + cts_err("Request resource failed %d", ret); + goto err_destroy_esd_workqueue; + } - ret = cts_plat_init_vkey_device(cts_data->pdata); - if (ret < 0) { - cts_err("Init vkey device failed %d", ret); - goto err_deinit_touch_device; - } + ret = cts_plat_reset_device(cts_data->pdata); + if (ret < 0) { + cts_err("Reset device failed %d", ret); + goto err_free_resource; + } - ret = cts_plat_init_gesture(cts_data->pdata); - if (ret < 0) { - cts_err("Init gesture failed %d", ret); - goto err_deinit_vkey_device; - } + ret = cts_probe_device(&cts_data->cts_dev); + if (ret) { + cts_err("Probe device failed %d", ret); + goto err_free_resource; + } - cts_init_esd_protection(cts_data); + ret = cts_plat_init_touch_device(cts_data->pdata); + if (ret < 0) { + cts_err("Init touch device failed %d", ret); + goto err_free_resource; + } - ret = cts_tool_init(cts_data); - if (ret < 0) { - cts_warn("Init tool node failed %d", ret); - } + ret = cts_plat_init_vkey_device(cts_data->pdata); + if (ret < 0) { + cts_err("Init vkey device failed %d", ret); + goto err_deinit_touch_device; + } - ret = cts_sysfs_add_device(&client->dev); - if (ret < 0) { - cts_warn("Add sysfs entry for device failed %d", ret); - } + ret = cts_plat_init_gesture(cts_data->pdata); + if (ret < 0) { + cts_err("Init gesture failed %d", ret); + goto err_deinit_vkey_device; + } + + cts_init_esd_protection(cts_data); + + ret = cts_tool_init(cts_data); + if (ret < 0) { + cts_warn("Init tool node failed %d", ret); + } + + ret = cts_sysfs_add_device(&client->dev); + if (ret < 0) { + cts_warn("Add sysfs entry for device failed %d", ret); + } #ifdef CONFIG_CTS_PM_FB_NOTIFIER - ret = cts_init_pm_fb_notifier(cts_data); - if (ret) { - cts_err("Init FB notifier failed %d", ret); - goto err_deinit_sysfs; - } + ret = cts_init_pm_fb_notifier(cts_data); + if (ret) { + cts_err("Init FB notifier failed %d", ret); + goto err_deinit_sysfs; + } #endif /* CONFIG_CTS_PM_FB_NOTIFIER */ - ret = cts_plat_request_irq(cts_data->pdata); - if (ret < 0) { - cts_err("Request IRQ failed %d", ret); - goto err_register_fb; - } + ret = cts_plat_request_irq(cts_data->pdata); + if (ret < 0) { + cts_err("Request IRQ failed %d", ret); + goto err_register_fb; + } - ret = cts_start_device(&cts_data->cts_dev); + ret = cts_charger_detect_init(cts_data); if (ret) { - cts_err("Start device failed %d", ret); - goto err_free_irq; + cts_err("Init charger detect failed %d", ret); + // Ignore this error } - return 0; + /* Init firmware upgrade work and schedule */ + INIT_DELAYED_WORK(&cts_data->fw_upgrade_work, cts_firmware_upgrade_work); + queue_delayed_work(cts_data->workqueue, &cts_data->fw_upgrade_work, msecs_to_jiffies(15*1000)); -err_free_irq: - cts_plat_free_irq(cts_data->pdata); + INIT_WORK(&cts_data->ts_resume_work, cts_resume_work_func); +#if 0 + ret = cts_start_device(&cts_data->cts_dev); + if (ret) { + cts_err("Start device failed %d", ret); + goto err_free_irq; + } +#endif + return 0; + +//err_free_irq: +// cts_plat_free_irq(cts_data->pdata); err_register_fb: #ifdef CONFIG_CTS_PM_FB_NOTIFIER - cts_deinit_pm_fb_notifier(cts_data); + cts_deinit_pm_fb_notifier(cts_data); err_deinit_sysfs: #endif /* CONFIG_CTS_PM_FB_NOTIFIER */ - cts_sysfs_remove_device(&client->dev); + cts_sysfs_remove_device(&client->dev); #ifdef CONFIG_CTS_LEGACY_TOOL - cts_tool_deinit(cts_data); + cts_tool_deinit(cts_data); #endif /* CONFIG_CTS_LEGACY_TOOL */ #ifdef CONFIG_CTS_ESD_PROTECTION - cts_deinit_esd_protection(cts_data); + cts_deinit_esd_protection(cts_data); #endif /* CONFIG_CTS_ESD_PROTECTION */ #ifdef CFG_CTS_GESTURE - cts_plat_deinit_gesture(cts_data->pdata); + cts_plat_deinit_gesture(cts_data->pdata); #endif /* CFG_CTS_GESTURE */ err_deinit_vkey_device: #ifdef CONFIG_CTS_VIRTUALKEY - cts_plat_deinit_vkey_device(cts_data->pdata); + cts_plat_deinit_vkey_device(cts_data->pdata); #endif /* CONFIG_CTS_VIRTUALKEY */ err_deinit_touch_device: - cts_plat_deinit_touch_device(cts_data->pdata); + cts_plat_deinit_touch_device(cts_data->pdata); err_free_resource: - cts_plat_free_resource(cts_data->pdata); + cts_plat_free_resource(cts_data->pdata); err_destroy_esd_workqueue: #ifdef CONFIG_CTS_ESD_PROTECTION - destroy_workqueue(cts_data->esd_workqueue); + destroy_workqueue(cts_data->esd_workqueue); err_destroy_workqueue: #endif - destroy_workqueue(cts_data->workqueue); + destroy_workqueue(cts_data->workqueue); err_deinit_platform_data: - cts_deinit_platform_data(cts_data->pdata); + cts_deinit_platform_data(cts_data->pdata); //err_free_pdata: - kfree(cts_data->pdata); + kfree(cts_data->pdata); err_free_cts_data: - kfree(cts_data); + kfree(cts_data); - cts_err("Probe failed %d", ret); + cts_err("Probe failed %d", ret); - return ret; + return ret; } +#ifdef CONFIG_CTS_I2C_HOST +static int cts_driver_remove(struct i2c_client *client) +#else static int cts_driver_remove(struct spi_device *client) +#endif { - struct chipone_ts_data *cts_data; - int ret = 0; + struct chipone_ts_data *cts_data; + int ret = 0; - cts_info("Remove"); + cts_info("Remove"); - cts_data = (struct chipone_ts_data *)spi_get_drvdata(client); +#ifdef CONFIG_CTS_I2C_HOST + cts_data = (struct chipone_ts_data *)i2c_get_clientdata(client); +#else + cts_data = (struct chipone_ts_data *)spi_get_drvdata(client); +#endif + if (cts_data) { + ret = cts_stop_device(&cts_data->cts_dev); + if (ret) { + cts_warn("Stop device failed %d", ret); + } - if (cts_data) { - ret = cts_stop_device(&cts_data->cts_dev); - if (ret) { - cts_warn("Stop device failed %d", ret); - } + cts_charger_detect_deinit(cts_data); - cts_plat_free_irq(cts_data->pdata); + cts_plat_free_irq(cts_data->pdata); #ifdef CONFIG_CTS_PM_FB_NOTIFIER - cts_deinit_pm_fb_notifier(cts_data); + cts_deinit_pm_fb_notifier(cts_data); #endif /* CONFIG_CTS_PM_FB_NOTIFIER */ - cts_tool_deinit(cts_data); + cts_tool_deinit(cts_data); - cts_sysfs_remove_device(&client->dev); + cts_sysfs_remove_device(&client->dev); - cts_deinit_esd_protection(cts_data); + cts_deinit_esd_protection(cts_data); - cts_plat_deinit_touch_device(cts_data->pdata); + cts_plat_deinit_touch_device(cts_data->pdata); - cts_plat_deinit_vkey_device(cts_data->pdata); + cts_plat_deinit_vkey_device(cts_data->pdata); - cts_plat_deinit_gesture(cts_data->pdata); + cts_plat_deinit_gesture(cts_data->pdata); - cts_plat_free_resource(cts_data->pdata); + cts_plat_free_resource(cts_data->pdata); #ifdef CONFIG_CTS_ESD_PROTECTION - if (cts_data->esd_workqueue) { - destroy_workqueue(cts_data->esd_workqueue); - } + if (cts_data->esd_workqueue) { + destroy_workqueue(cts_data->esd_workqueue); + } #endif - if (cts_data->workqueue) { - destroy_workqueue(cts_data->workqueue); - } + if (cts_data->workqueue) { + destroy_workqueue(cts_data->workqueue); + } - cts_deinit_platform_data(cts_data->pdata); + cts_deinit_platform_data(cts_data->pdata); - if (cts_data->pdata) { - kfree(cts_data->pdata); - } - kfree(cts_data); - }else { - cts_warn("Chipone i2c driver remove while NULL chipone_ts_data"); - return -EINVAL; - } + if (cts_data->pdata) { + kfree(cts_data->pdata); + } + kfree(cts_data); + } else { + cts_warn + ("Chipone i2c driver remove while NULL chipone_ts_data"); + return -EINVAL; + } - return ret; + return ret; } #ifdef CONFIG_CTS_PM_LEGACY @@ -493,215 +557,300 @@ static const struct dev_pm_ops cts_i2c_driver_pm_ops = { #ifdef CONFIG_CTS_SYSFS static ssize_t reset_pin_show(struct device_driver *driver, char *buf) { - return sprintf(buf, "CFG_CTS_HAS_RESET_PIN: %c\n", + return snprintf(buf, PAGE_SIZE, "CFG_CTS_HAS_RESET_PIN: %c\n", #ifdef CFG_CTS_HAS_RESET_PIN - 'Y' + 'Y' #else - 'N' + 'N' #endif ); } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) static DRIVER_ATTR(reset_pin, S_IRUGO, reset_pin_show, NULL); +#else +static DRIVER_ATTR_RO(reset_pin); +#endif static ssize_t swap_xy_show(struct device_driver *dev, char *buf) { - return sprintf(buf, "CFG_CTS_SWAP_XY: %c\n", + return snprintf(buf, PAGE_SIZE, "CFG_CTS_SWAP_XY: %c\n", #ifdef CFG_CTS_SWAP_XY - 'Y' + 'Y' #else - 'N' + 'N' #endif ); } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) static DRIVER_ATTR(swap_xy, S_IRUGO, swap_xy_show, NULL); +#else +static DRIVER_ATTR_RO(swap_xy); +#endif static ssize_t wrap_x_show(struct device_driver *dev, char *buf) { - return sprintf(buf, "CFG_CTS_WRAP_X: %c\n", + return snprintf(buf, PAGE_SIZE, "CFG_CTS_WRAP_X: %c\n", #ifdef CFG_CTS_WRAP_X - 'Y' + 'Y' #else - 'N' + 'N' #endif ); } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) static DRIVER_ATTR(wrap_x, S_IRUGO, wrap_x_show, NULL); +#else +static DRIVER_ATTR_RO(wrap_x); +#endif static ssize_t wrap_y_show(struct device_driver *dev, char *buf) { - return sprintf(buf, "CFG_CTS_WRAP_Y: %c\n", + return snprintf(buf, PAGE_SIZE, "CFG_CTS_WRAP_Y: %c\n", #ifdef CFG_CTS_WRAP_Y - 'Y' + 'Y' #else - 'N' + 'N' #endif ); } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) static DRIVER_ATTR(wrap_y, S_IRUGO, wrap_y_show, NULL); +#else +static DRIVER_ATTR_RO(wrap_y); +#endif static ssize_t force_update_show(struct device_driver *dev, char *buf) { - return sprintf(buf, "CFG_CTS_HAS_RESET_PIN: %c\n", + return snprintf(buf, PAGE_SIZE, "CFG_CTS_HAS_RESET_PIN: %c\n", #ifdef CFG_CTS_FIRMWARE_FORCE_UPDATE - 'Y' + 'Y' #else - 'N' + 'N' #endif ); } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) static DRIVER_ATTR(force_update, S_IRUGO, force_update_show, NULL); +#else +static DRIVER_ATTR_RO(force_update); +#endif static ssize_t max_touch_num_show(struct device_driver *dev, char *buf) { - return sprintf(buf, "CFG_CTS_MAX_TOUCH_NUM: %d\n", - CFG_CTS_MAX_TOUCH_NUM); + return snprintf(buf, PAGE_SIZE, "CFG_CTS_MAX_TOUCH_NUM: %d\n", + CFG_CTS_MAX_TOUCH_NUM); } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) static DRIVER_ATTR(max_touch_num, S_IRUGO, max_touch_num_show, NULL); +#else +static DRIVER_ATTR_RO(max_touch_num); +#endif static ssize_t vkey_show(struct device_driver *dev, char *buf) { - return sprintf(buf, "CONFIG_CTS_VIRTUALKEY: %c\n", + return snprintf(buf, PAGE_SIZE, "CONFIG_CTS_VIRTUALKEY: %c\n", #ifdef CONFIG_CTS_VIRTUALKEY - 'Y' + 'Y' #else - 'N' + 'N' #endif ); } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) static DRIVER_ATTR(vkey, S_IRUGO, vkey_show, NULL); +#else +static DRIVER_ATTR_RO(vkey); +#endif static ssize_t gesture_show(struct device_driver *dev, char *buf) { - return sprintf(buf, "CFG_CTS_GESTURE: %c\n", + return snprintf(buf, PAGE_SIZE, "CFG_CTS_GESTURE: %c\n", #ifdef CFG_CTS_GESTURE - 'Y' + 'Y' #else - 'N' + 'N' #endif ); } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) static DRIVER_ATTR(gesture, S_IRUGO, gesture_show, NULL); +#else +static DRIVER_ATTR_RO(gesture); +#endif static ssize_t esd_protection_show(struct device_driver *dev, char *buf) { - return sprintf(buf, "CONFIG_CTS_ESD_PROTECTION: %c\n", + return snprintf(buf, PAGE_SIZE, "CONFIG_CTS_ESD_PROTECTION: %c\n", #ifdef CONFIG_CTS_ESD_PROTECTION - 'Y' + 'Y' #else - 'N' + 'N' #endif ); } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) static DRIVER_ATTR(esd_protection, S_IRUGO, esd_protection_show, NULL); +#else +static DRIVER_ATTR_RO(esd_protection); +#endif static ssize_t slot_protocol_show(struct device_driver *dev, char *buf) { - return sprintf(buf, "CONFIG_CTS_SLOTPROTOCOL: %c\n", + return snprintf(buf, PAGE_SIZE, "CONFIG_CTS_SLOTPROTOCOL: %c\n", #ifdef CONFIG_CTS_SLOTPROTOCOL - 'Y' + 'Y' #else - 'N' + 'N' #endif ); } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) static DRIVER_ATTR(slot_protocol, S_IRUGO, slot_protocol_show, NULL); +#else +static DRIVER_ATTR_RO(slot_protocol); +#endif static ssize_t max_xfer_size_show(struct device_driver *dev, char *buf) { - return sprintf(buf, "CFG_CTS_MAX_SPI_XFER_SIZE: %d\n", - CFG_CTS_MAX_SPI_XFER_SIZE); +#ifdef CONFIG_CTS_I2C_HOST + return snprintf(buf, PAGE_SIZE, "CFG_CTS_MAX_I2C_XFER_SIZE: %d\n", + CFG_CTS_MAX_I2C_XFER_SIZE); +#else + return snprintf(buf, PAGE_SIZE, "CFG_CTS_MAX_SPI_XFER_SIZE: %d\n", + CFG_CTS_MAX_SPI_XFER_SIZE); +#endif } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) static DRIVER_ATTR(max_xfer_size, S_IRUGO, max_xfer_size_show, NULL); +#else +static DRIVER_ATTR_RO(max_xfer_size); +#endif static ssize_t driver_info_show(struct device_driver *dev, char *buf) { - return sprintf(buf, "Driver version: %s\n", CFG_CTS_DRIVER_VERSION); + return snprintf(buf, PAGE_SIZE, "Driver version: %s\n", CFG_CTS_DRIVER_VERSION); } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) static DRIVER_ATTR(driver_info, S_IRUGO, driver_info_show, NULL); +#else +static DRIVER_ATTR_RO(driver_info); +#endif static struct attribute *cts_i2c_driver_config_attrs[] = { - &driver_attr_reset_pin.attr, - &driver_attr_swap_xy.attr, - &driver_attr_wrap_x.attr, - &driver_attr_wrap_y.attr, - &driver_attr_force_update.attr, + &driver_attr_reset_pin.attr, + &driver_attr_swap_xy.attr, + &driver_attr_wrap_x.attr, + &driver_attr_wrap_y.attr, + &driver_attr_force_update.attr, &driver_attr_max_touch_num.attr, &driver_attr_vkey.attr, - &driver_attr_gesture.attr, + &driver_attr_gesture.attr, &driver_attr_esd_protection.attr, - &driver_attr_slot_protocol.attr, - &driver_attr_max_xfer_size.attr, - &driver_attr_driver_info.attr, + &driver_attr_slot_protocol.attr, + &driver_attr_max_xfer_size.attr, + &driver_attr_driver_info.attr, NULL }; static const struct attribute_group cts_i2c_driver_config_group = { - .name = "config", + .name = "config", .attrs = cts_i2c_driver_config_attrs, }; static const struct attribute_group *cts_i2c_driver_config_groups[] = { - &cts_i2c_driver_config_group, - NULL, + &cts_i2c_driver_config_group, + NULL, }; #endif /* CONFIG_CTS_SYSFS */ #ifdef CONFIG_CTS_OF static const struct of_device_id cts_i2c_of_match_table[] = { - {.compatible = CFG_CTS_OF_DEVICE_ID_NAME,}, - { }, + {.compatible = CFG_CTS_OF_DEVICE_ID_NAME,}, + {}, }; + MODULE_DEVICE_TABLE(of, cts_i2c_of_match_table); #endif /* CONFIG_CTS_OF */ -static const struct spi_device_id cts_device_id_table[] = { - {CFG_CTS_DEVICE_NAME, 0}, - {} +#ifdef CONFIG_CTS_I2C_HOST +static const struct i2c_device_id cts_device_id_table[] = { + {CFG_CTS_DEVICE_NAME, 0}, + {} }; +#else +static const struct spi_device_id cts_device_id_table[] = { + {CFG_CTS_DEVICE_NAME, 0}, + {} +}; +#endif +#ifdef CONFIG_CTS_I2C_HOST +static struct i2c_driver cts_i2c_driver = { +#else static struct spi_driver cts_spi_driver = { - .probe = cts_driver_probe, - .remove = cts_driver_remove, - .driver = { - .name = CFG_CTS_DRIVER_NAME, - .owner = THIS_MODULE, +#endif + .probe = cts_driver_probe, + .remove = cts_driver_remove, + .driver = { + .name = CFG_CTS_DRIVER_NAME, + .owner = THIS_MODULE, #ifdef CONFIG_CTS_OF - .of_match_table = of_match_ptr(cts_i2c_of_match_table), + .of_match_table = of_match_ptr(cts_i2c_of_match_table), #endif /* CONFIG_CTS_OF */ #ifdef CONFIG_CTS_SYSFS - .groups = cts_i2c_driver_config_groups, + .groups = cts_i2c_driver_config_groups, #endif /* CONFIG_CTS_SYSFS */ #ifdef CONFIG_CTS_PM_LEGACY - .suspend = cts_i2c_driver_suspend, - .resume = cts_i2c_driver_resume, + .suspend = cts_i2c_driver_suspend, + .resume = cts_i2c_driver_resume, #endif /* CONFIG_CTS_PM_LEGACY */ #ifdef CONFIG_CTS_PM_GENERIC - .pm = &cts_i2c_driver_pm_ops, + .pm = &cts_i2c_driver_pm_ops, #endif /* CONFIG_CTS_PM_GENERIC */ - }, - .id_table = cts_device_id_table, + }, + .id_table = cts_device_id_table, }; static int __init cts_driver_init(void) { - cts_info("Init"); - return spi_register_driver(&cts_spi_driver); + cts_info("Init"); + +#ifdef CONFIG_CTS_I2C_HOST + return i2c_add_driver(&cts_i2c_driver); +#else + pr_err("wj---spi"); + return spi_register_driver(&cts_spi_driver); +#endif } static void __exit cts_driver_exit(void) { - cts_info("Exit"); - spi_unregister_driver(&cts_spi_driver); + cts_info("Exit"); +#ifdef CONFIG_CTS_I2C_HOST + i2c_del_driver(&cts_i2c_driver); +#else + spi_unregister_driver(&cts_spi_driver); +#endif } -//module_init(cts_driver_init); -late_initcall(cts_driver_init); +module_init(cts_driver_init); module_exit(cts_driver_exit); MODULE_DESCRIPTION("Chipone TDDI touchscreen Driver for QualComm platform"); MODULE_VERSION(CFG_CTS_DRIVER_VERSION); MODULE_AUTHOR("Miao Defang "); MODULE_LICENSE("GPL"); - diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_plat_qcom_config.h b/drivers/input/touchscreen/chipone_tddi_mmi/cts_plat_qcom_config.h old mode 100755 new mode 100644 index efb4efe4ed73..cc0cb49c3052 --- a/drivers/input/touchscreen/chipone_tddi_mmi/cts_plat_qcom_config.h +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_plat_qcom_config.h @@ -1,50 +1,53 @@ -#ifndef CTS_PLAT_QCOM_CONFIG_H -#define CTS_PLAT_QCOM_CONFIG_H - -#define CONFIG_CTS_PM_FB_NOTIFIER - -#ifdef CONFIG_CTS_PM_FB_NOTIFIER -#ifdef CONFIG_DRM -#define CFG_CTS_DRM_NOTIFIER -#endif/*CONFIG_DRM_MSM*/ -#else/*CONFIG_CTS_PM_FB_NOTIFIER*/ -#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PM_SUSPEND) - //#define CONFIG_CTS_PM_GENERIC -#endif /* CONFIG_PM_SLEEP */ - -#if !defined(CONFIG_CTS_PM_GENERIC) - #define CONFIG_CTS_PM_LEGACY -#endif/*CONFIG_CTS_PM_GENERIC*/ -#endif/*CONFIG_CTS_PM_FB_NOTIFIER*/ - -#define CFG_CTS_MAX_I2C_XFER_SIZE (48u) -#define CFG_CTS_MAX_SPI_XFER_SIZE (1400u) - -#define CTS_FW_LOG_REDIRECT_SIGN 0x60 -#define CTS_FW_LOG_BUF_LEN 128 - -//#define CFG_CTS_SWAP_XY -//#define CFG_CTS_WRAP_X -//#define CFG_CTS_WRAP_Y - -#define CFG_CTS_DEVICE_NAME "chipone-tddi" -#define CFG_CTS_DRIVER_NAME "chipone-tddi" - -#if CFG_CTS_MAX_I2C_XFER_SIZE < 8 -#error "I2C transfer size should large than 8" -#endif - -#ifdef CONFIG_OF -#define CONFIG_CTS_OF -#endif -#ifdef CONFIG_CTS_OF - #define CFG_CTS_OF_DEVICE_ID_NAME "chipone-tddi" - - #define CFG_CTS_OF_INT_GPIO_NAME "chipone,irq-gpio" - #define CFG_CTS_OF_RST_GPIO_NAME "chipone,rst-gpio" - #define CFG_CTS_OF_X_RESOLUTION_NAME "chipone,x-res" - #define CFG_CTS_OF_Y_RESOLUTION_NAME "chipone,y-res" -#endif /* CONFIG_CTS_OF */ - -#endif /* CTS_PLAT_QCOM_CONFIG_H */ - +#ifndef CTS_PLAT_QCOM_CONFIG_H +#define CTS_PLAT_QCOM_CONFIG_H + +#define CONFIG_CTS_PM_FB_NOTIFIER + +#ifdef CONFIG_CTS_PM_FB_NOTIFIER +#ifdef CONFIG_DRM +#define CFG_CTS_DRM_NOTIFIER +#endif /*CONFIG_DRM_MSM */ +#else /*CONFIG_CTS_PM_FB_NOTIFIER */ +#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PM_SUSPEND) + //#define CONFIG_CTS_PM_GENERIC +#endif /* CONFIG_PM_SLEEP */ + +#if !defined(CONFIG_CTS_PM_GENERIC) +#define CONFIG_CTS_PM_LEGACY +#endif /*CONFIG_CTS_PM_GENERIC */ +#endif /*CONFIG_CTS_PM_FB_NOTIFIER */ + +#define CFG_CTS_MAX_I2C_XFER_SIZE (48u) +#define CFG_CTS_MAX_SPI_XFER_SIZE (1400u) + +#define CTS_FW_LOG_REDIRECT_SIGN 0x60 +#define CTS_FW_LOG_BUF_LEN 128 + +//#define CFG_CTS_SWAP_XY +//#define CFG_CTS_WRAP_X +//#define CFG_CTS_WRAP_Y + +#define CFG_CTS_DEVICE_NAME "chipone-tddi" +#define CFG_CTS_DRIVER_NAME "chipone-tddi" + +#if CFG_CTS_MAX_I2C_XFER_SIZE < 8 +#error "I2C transfer size should large than 8" +#endif + +#ifdef CONFIG_OF +#define CONFIG_CTS_OF +#endif +#ifdef CONFIG_CTS_OF +#define CFG_CTS_OF_DEVICE_ID_NAME "chipone-tddi" + +#define CFG_CTS_OF_INT_GPIO_NAME "chipone,irq-gpio" +#define CFG_CTS_OF_RST_GPIO_NAME "chipone,rst-gpio" +#define CFG_CTS_OF_X_RESOLUTION_NAME "chipone,x-res" +#define CFG_CTS_OF_Y_RESOLUTION_NAME "chipone,y-res" + +#ifdef CFG_CTS_FW_UPDATE_SYS +#define CFG_CTS_OF_PANEL_SUPPLIER "chipone,panel-supplier" +#endif +#endif /* CONFIG_CTS_OF */ + +#endif /* CTS_PLAT_QCOM_CONFIG_H */ diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_platform.c b/drivers/input/touchscreen/chipone_tddi_mmi/cts_platform.c old mode 100755 new mode 100644 index 4c7dc8dc70ad..06210f16d0d7 --- a/drivers/input/touchscreen/chipone_tddi_mmi/cts_platform.c +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_platform.c @@ -4,344 +4,379 @@ #include "cts_platform.h" #include "cts_core.h" #include "cts_firmware.h" +#include "cts_sysfs.h" #ifdef CFG_CTS_FW_LOG_REDIRECT size_t cts_plat_get_max_fw_log_size(struct cts_platform_data *pdata) { - return CTS_FW_LOG_BUF_LEN; + return CTS_FW_LOG_BUF_LEN; } -u8 *cts_plat_get_fw_log_buf(struct cts_platform_data *pdata, - size_t size) +u8 *cts_plat_get_fw_log_buf(struct cts_platform_data *pdata, size_t size) { - return pdata->fw_log_buf; + return pdata->fw_log_buf; } #endif size_t cts_plat_get_max_i2c_xfer_size(struct cts_platform_data *pdata) { - return CFG_CTS_MAX_I2C_XFER_SIZE; + return CFG_CTS_MAX_I2C_XFER_SIZE; } #ifdef CONFIG_CTS_I2C_HOST u8 *cts_plat_get_i2c_xfer_buf(struct cts_platform_data *pdata, - size_t xfer_size) + size_t xfer_size) { - return pdata->i2c_fifo_buf; + return pdata->i2c_fifo_buf; } int cts_plat_i2c_write(struct cts_platform_data *pdata, u8 i2c_addr, - const void *src, size_t len, int retry, int delay) + const void *src, size_t len, int retry, int delay) { - int ret = 0, retries = 0; + int ret = 0, retries = 0; - struct i2c_msg msg = { - .flags = 0, - .addr = i2c_addr, - .buf = (u8 *)src, - .len = len, - }; + struct i2c_msg msg = { + .flags = 0, + .addr = i2c_addr, + .buf = (u8 *) src, + .len = len, + }; - do { - ret = i2c_transfer(pdata->i2c_client->adapter, &msg, 1); - if (ret != 1) { - if (ret >= 0) { - ret = -EIO; - } + do { + ret = i2c_transfer(pdata->i2c_client->adapter, &msg, 1); + if (ret != 1) { + if (ret >= 0) { + ret = -EIO; + } - if (delay) { - mdelay(delay); - } - continue; - } else { - return 0; - } - } while (++retries < retry); + if (delay) { + mdelay(delay); + } + continue; + } else { + return 0; + } + } while (++retries < retry); - return ret; + return ret; } int cts_plat_i2c_read(struct cts_platform_data *pdata, u8 i2c_addr, - const u8 *wbuf, size_t wlen, void *rbuf, size_t rlen, - int retry, int delay) + const u8 *wbuf, size_t wlen, void *rbuf, size_t rlen, + int retry, int delay) { - int num_msg, ret = 0, retries = 0; + int num_msg, ret = 0, retries = 0; - struct i2c_msg msgs[2] = { - { - .addr = i2c_addr, - .flags = 0, - .buf = (u8 *)wbuf, - .len = wlen - }, - { - .addr = i2c_addr, - .flags = I2C_M_RD, - .buf = (u8 *)rbuf, - .len = rlen - } - }; + struct i2c_msg msgs[2] = { + { + .addr = i2c_addr, + .flags = 0, + .buf = (u8 *) wbuf, + .len = wlen}, + { + .addr = i2c_addr, + .flags = I2C_M_RD, + .buf = (u8 *) rbuf, + .len = rlen} + }; - if (wbuf == NULL || wlen == 0) { - num_msg = 1; - } else { - num_msg = 2; - } + if (wbuf == NULL || wlen == 0) { + num_msg = 1; + } else { + num_msg = 2; + } - do { - ret = i2c_transfer(pdata->i2c_client->adapter, - msgs + ARRAY_SIZE(msgs) - num_msg, num_msg); + do { + ret = i2c_transfer(pdata->i2c_client->adapter, + msgs + ARRAY_SIZE(msgs) - num_msg, num_msg); - if (ret != num_msg) { - if (ret >= 0) { - ret = -EIO; - } + if (ret != num_msg) { + if (ret >= 0) { + ret = -EIO; + } - if (delay) { - mdelay(delay); - } - continue; - } else { - return 0; - } - } while (++retries < retry); + if (delay) { + mdelay(delay); + } + continue; + } else { + return 0; + } + } while (++retries < retry); - return ret; + return ret; } int cts_plat_is_i2c_online(struct cts_platform_data *pdata, u8 i2c_addr) { - u8 dummy_bytes[2] = {0x00, 0x00}; - int ret; + u8 dummy_bytes[2] = { 0x00, 0x00 }; + int ret; - ret = cts_plat_i2c_write(pdata, i2c_addr, dummy_bytes, sizeof(dummy_bytes), 5, 2); - if (ret) { - cts_err("!!! I2C addr 0x%02x is offline !!!", i2c_addr); - return false; - } else { - cts_dbg("I2C addr 0x%02x is online", i2c_addr); - return true; - } + ret = + cts_plat_i2c_write(pdata, i2c_addr, dummy_bytes, + sizeof(dummy_bytes), 5, 2); + if (ret) { + cts_err("!!! I2C addr 0x%02x is offline !!!", i2c_addr); + return false; + } else { + cts_dbg("I2C addr 0x%02x is online", i2c_addr); + return true; + } } #else -int cts_spi_send_recv(struct cts_platform_data *pdata, size_t len , u8 *tx_buffer, u8 *rx_buffer) +int cts_spi_send_recv(struct cts_platform_data *pdata, size_t len, + u8 *tx_buffer, u8 *rx_buffer) { - struct chipone_ts_data *cts_data; - struct spi_message msg; - struct spi_transfer cmd = { - .cs_change = 0, - .delay_usecs = 0, - .speed_hz = pdata->spi_speed * 1000u, - .tx_buf = tx_buffer, - .rx_buf = rx_buffer, - .len = len, - //.tx_dma = 0, - //.rx_dma = 0, - .bits_per_word = 8, - }; - int error = 0 ; - cts_data = container_of(pdata->cts_dev, struct chipone_ts_data, cts_dev); + struct chipone_ts_data *cts_data; + struct spi_message msg; + struct spi_transfer cmd = { + .cs_change = 0, + .delay_usecs = 0, + //.speed_hz = pdata->spi_speed * 1000u, + .speed_hz = speed * 1000u, + .tx_buf = tx_buffer, + .rx_buf = rx_buffer, + .len = len, + //.tx_dma = 0, + //.rx_dma = 0, + .bits_per_word = 8, + }; + int ret = 0; + cts_data = + container_of(pdata->cts_dev, struct chipone_ts_data, cts_dev); + + //cts_info("spi_speed=%d", speed); - //fpsensor_spi_set_mode(fpsensor->spi, (u32)fpsensor->spi_freq_khz, 0); - spi_message_init(&msg); #if 1 //#ifdef CFG_CTS_MANUAL_CS -// cts_plat_set_cs(pdata, 0); - cts_data->spi_client->chip_select = 0; +// cts_plat_set_cs(pdata, 0); + cts_data->spi_client->chip_select = 0; #endif - spi_message_add_tail(&cmd, &msg); - error = spi_sync(cts_data->spi_client, &msg); - if (error) { - cts_err("spi_sync failed.\n"); - } -#if 0 // FPSENSOR_MANUAL_CS - cts_plat_set_cs(pdata, 1); + spi_message_init(&msg); + spi_message_add_tail(&cmd, &msg); + ret = spi_sync(cts_data->spi_client, &msg); + if (ret) { + cts_err("spi sync failed %d", ret); + } +#ifdef CFG_CTS_MANUAL_CS + cts_plat_set_cs(pdata, 1); #endif - return error; + return ret; } size_t cts_plat_get_max_spi_xfer_size(struct cts_platform_data *pdata) { - return CFG_CTS_MAX_SPI_XFER_SIZE; + return CFG_CTS_MAX_SPI_XFER_SIZE; } u8 *cts_plat_get_spi_xfer_buf(struct cts_platform_data *pdata, - size_t xfer_size) + size_t xfer_size) { - return pdata->spi_cache_buf; + return pdata->spi_cache_buf; } int cts_plat_spi_write(struct cts_platform_data *pdata, u8 dev_addr, - const void *src, size_t len, int retry, int delay) + const void *src, size_t len, int retry, int delay) { - int ret = 0, retries = 0; - u16 crc; - size_t data_len; + int ret = 0, retries = 0; + u16 crc; + size_t data_len; if (len > CFG_CTS_MAX_SPI_XFER_SIZE) { - cts_err("write too much data:wlen=%zd\n", len); + cts_err("write too much data:wlen=%zu\n", len); return -EIO; } - if (pdata->cts_dev->rtdata.program_mode) { - pdata->spi_tx_buf[0] = dev_addr; - memcpy(&pdata->spi_tx_buf[1], src, len); - - do { - ret = cts_spi_send_recv(pdata, len + 1, pdata->spi_tx_buf, pdata->spi_rx_buf); - if (ret) { - if (delay) { - mdelay(delay); - } - } else { - return 0; - } - } while (++retries < retry); - } - else { - data_len = len - 2; - pdata->spi_tx_buf[0] = dev_addr; - pdata->spi_tx_buf[1] = *((u8 *)src + 1); - pdata->spi_tx_buf[2] = *((u8 *)src); - put_unaligned_le16(data_len, &pdata->spi_tx_buf[3]); - crc = (u16)crc32(pdata->spi_tx_buf, 5); - put_unaligned_le16(crc, &pdata->spi_tx_buf[5]); - memcpy(&pdata->spi_tx_buf[7], (char *)src + 2, data_len); - crc = (u16)crc32((char *)src + 2, data_len); - put_unaligned_le16(crc, &pdata->spi_tx_buf[7+data_len]); - do { - ret = cts_spi_send_recv(pdata, len + 7, pdata->spi_tx_buf, pdata->spi_rx_buf); - if (ret) { - if (delay) { - mdelay(delay); - } - } else { - return 0; - } - } while (++retries < retry); - } - return ret; + if (pdata->cts_dev->rtdata.program_mode) { + pdata->spi_tx_buf[0] = dev_addr; + memcpy(&pdata->spi_tx_buf[1], src, len); + + do { + ret = + cts_spi_send_recv(pdata, len + 1, pdata->spi_tx_buf, + pdata->spi_rx_buf); + if (ret) { + cts_err("SPI write failed %d", ret); + if (delay) { + mdelay(delay); + } + } else { + return 0; + } + } while (++retries < retry); + } else { + data_len = len - 2; + pdata->spi_tx_buf[0] = dev_addr; + pdata->spi_tx_buf[1] = *((u8 *) src + 1); + pdata->spi_tx_buf[2] = *((u8 *) src); + put_unaligned_le16(data_len, &pdata->spi_tx_buf[3]); + crc = (u16) crc32(pdata->spi_tx_buf, 5); + put_unaligned_le16(crc, &pdata->spi_tx_buf[5]); + memcpy(&pdata->spi_tx_buf[7], (char *)src + 2, data_len); + crc = (u16) crc32((char *)src + 2, data_len); + put_unaligned_le16(crc, &pdata->spi_tx_buf[7 + data_len]); + do { + ret = + cts_spi_send_recv(pdata, len + 7, pdata->spi_tx_buf, + pdata->spi_rx_buf); + udelay(10 * data_len); + if (ret) { + cts_err("SPI write failed %d", ret); + if (delay) { + mdelay(delay); + } + } else { + return 0; + } + } while (++retries < retry); + } + return ret; } int cts_plat_spi_read(struct cts_platform_data *pdata, u8 dev_addr, - const u8 *wbuf, size_t wlen, void *rbuf, size_t rlen, - int retry, int delay) + const u8 *wbuf, size_t wlen, void *rbuf, size_t rlen, + int retry, int delay) { - int ret = 0, retries = 0; - u16 crc; + int ret = 0, retries = 0; + u16 crc; - if (wlen > CFG_CTS_MAX_SPI_XFER_SIZE || rlen > CFG_CTS_MAX_SPI_XFER_SIZE) { - cts_err("write/read too much data:wlen=%zd, rlen=%zd", wlen, rlen); + if (wlen > CFG_CTS_MAX_SPI_XFER_SIZE + || rlen > CFG_CTS_MAX_SPI_XFER_SIZE) { + cts_err("write/read too much data:wlen=%zd, rlen=%zd", wlen, + rlen); return -EIO; - } + } - if (pdata->cts_dev->rtdata.program_mode) - { + if (pdata->cts_dev->rtdata.program_mode) { pdata->spi_tx_buf[0] = dev_addr | 0x01; memcpy(&pdata->spi_tx_buf[1], wbuf, wlen); do { - ret = cts_spi_send_recv(pdata, rlen + 5, pdata->spi_tx_buf, pdata->spi_rx_buf); + ret = + cts_spi_send_recv(pdata, rlen + 5, + pdata->spi_tx_buf, + pdata->spi_rx_buf); if (ret) { + cts_err("SPI read failed %d", ret); if (delay) { mdelay(delay); } continue; } - memcpy(rbuf, pdata->spi_rx_buf+5, rlen); + memcpy(rbuf, pdata->spi_rx_buf + 5, rlen); return 0; - } while(++retries < retry); - } - else { + } while (++retries < retry); + } else { do { if (wlen != 0) { - pdata->spi_tx_buf[0] = dev_addr | 0x01; - pdata->spi_tx_buf[1] = wbuf[1]; - pdata->spi_tx_buf[2] = wbuf[0]; - put_unaligned_le16(rlen, &pdata->spi_tx_buf[3]); - crc = (u16)crc32(pdata->spi_tx_buf, 5); - put_unaligned_le16(crc, &pdata->spi_tx_buf[5]); - ret = cts_spi_send_recv(pdata, 7, pdata->spi_tx_buf, pdata->spi_rx_buf); + pdata->spi_tx_buf[0] = dev_addr | 0x01; + pdata->spi_tx_buf[1] = wbuf[1]; + pdata->spi_tx_buf[2] = wbuf[0]; + put_unaligned_le16(rlen, &pdata->spi_tx_buf[3]); + crc = (u16) crc32(pdata->spi_tx_buf, 5); + put_unaligned_le16(crc, &pdata->spi_tx_buf[5]); + ret = + cts_spi_send_recv(pdata, 7, + pdata->spi_tx_buf, + pdata->spi_rx_buf); if (ret) { + cts_err("SPI read failed %d", ret); if (delay) { mdelay(delay); } continue; - } + } } memset(pdata->spi_tx_buf, 0, 7); - pdata->spi_tx_buf[0] = dev_addr | 0x01; - udelay(100); - ret = cts_spi_send_recv(pdata, rlen + 2, pdata->spi_tx_buf, pdata->spi_rx_buf); + pdata->spi_tx_buf[0] = dev_addr | 0x01; + udelay(100); + ret = + cts_spi_send_recv(pdata, rlen + 2, + pdata->spi_tx_buf, + pdata->spi_rx_buf); if (ret) { + cts_err("SPI read failed %d", ret); if (delay) { mdelay(delay); } continue; } memcpy(rbuf, pdata->spi_rx_buf, rlen); - crc = (u16)crc32(pdata->spi_rx_buf, rlen); - if (get_unaligned_le16(&pdata->spi_rx_buf[rlen]) != crc) { - continue; + crc = (u16) crc32(pdata->spi_rx_buf, rlen); + if (get_unaligned_le16(&pdata->spi_rx_buf[rlen]) != crc) { + cts_err("SPI RX CRC error: rx_crc %04x != %04x", + get_unaligned_le16(&pdata->spi_rx_buf[rlen]), crc); + continue; } return 0; - } while (++retries < retry); + } while (++retries < retry); } if (retries >= retry) { - cts_err("cts_plat_spi_read error"); + cts_err("SPI read too much retry"); } - - return -ENODEV; + + return -EIO; } int cts_plat_spi_read_delay_idle(struct cts_platform_data *pdata, u8 dev_addr, - const u8 *wbuf, size_t wlen, void *rbuf, size_t rlen, - int retry, int delay, int idle) + const u8 *wbuf, size_t wlen, void *rbuf, + size_t rlen, int retry, int delay, int idle) { - int ret = 0, retries = 0; - u16 crc; + int ret = 0, retries = 0; + u16 crc; - if (wlen > CFG_CTS_MAX_SPI_XFER_SIZE || rlen > CFG_CTS_MAX_SPI_XFER_SIZE) { - cts_err("write/read too much data:wlen=%zd, rlen=%zd", wlen, rlen); - return -EIO; - } + if (wlen > CFG_CTS_MAX_SPI_XFER_SIZE || + rlen > CFG_CTS_MAX_SPI_XFER_SIZE) { + cts_err("write/read too much data:wlen=%zu, rlen=%zu", wlen, + rlen); + return -E2BIG; + } - if (pdata->cts_dev->rtdata.program_mode) - { + if (pdata->cts_dev->rtdata.program_mode) { pdata->spi_tx_buf[0] = dev_addr | 0x01; memcpy(&pdata->spi_tx_buf[1], wbuf, wlen); do { - ret = cts_spi_send_recv(pdata, rlen + 5, pdata->spi_tx_buf, pdata->spi_rx_buf); + ret = + cts_spi_send_recv(pdata, rlen + 5, + pdata->spi_tx_buf, + pdata->spi_rx_buf); if (ret) { + cts_err("SPI read failed %d", ret); if (delay) { mdelay(delay); } continue; } - memcpy(rbuf, pdata->spi_rx_buf+5, rlen); + memcpy(rbuf, pdata->spi_rx_buf + 5, rlen); return 0; - } while(++retries < retry); - } - else { + } while (++retries < retry); + } else { do { if (wlen != 0) { - pdata->spi_tx_buf[0] = dev_addr | 0x01; - pdata->spi_tx_buf[1] = wbuf[1]; - pdata->spi_tx_buf[2] = wbuf[0]; - put_unaligned_le16(rlen, &pdata->spi_tx_buf[3]); - crc = (u16)crc32(pdata->spi_tx_buf, 5); - put_unaligned_le16(crc, &pdata->spi_tx_buf[5]); - ret = cts_spi_send_recv(pdata, 7, pdata->spi_tx_buf, pdata->spi_rx_buf); + pdata->spi_tx_buf[0] = dev_addr | 0x01; + pdata->spi_tx_buf[1] = wbuf[1]; + pdata->spi_tx_buf[2] = wbuf[0]; + put_unaligned_le16(rlen, &pdata->spi_tx_buf[3]); + crc = (u16) crc32(pdata->spi_tx_buf, 5); + put_unaligned_le16(crc, &pdata->spi_tx_buf[5]); + ret = + cts_spi_send_recv(pdata, 7, + pdata->spi_tx_buf, + pdata->spi_rx_buf); if (ret) { + cts_err("SPI read failed %d", ret); if (delay) { mdelay(delay); } continue; - } + } } memset(pdata->spi_tx_buf, 0, 7); - pdata->spi_tx_buf[0] = dev_addr | 0x01; - udelay(idle); - ret = cts_spi_send_recv(pdata, rlen + 2, pdata->spi_tx_buf, pdata->spi_rx_buf); + pdata->spi_tx_buf[0] = dev_addr | 0x01; + udelay(idle); + ret = + cts_spi_send_recv(pdata, rlen + 2, + pdata->spi_tx_buf, + pdata->spi_rx_buf); if (ret) { if (delay) { mdelay(delay); @@ -349,122 +384,130 @@ int cts_plat_spi_read_delay_idle(struct cts_platform_data *pdata, u8 dev_addr, continue; } memcpy(rbuf, pdata->spi_rx_buf, rlen); - crc = (u16)crc32(pdata->spi_rx_buf, rlen); + crc = (u16) crc32(pdata->spi_rx_buf, rlen); if (get_unaligned_le16(&pdata->spi_rx_buf[rlen]) != crc) { - continue; + continue; } return 0; - } while (++retries < retry); + } while (++retries < retry); } if (retries >= retry) { - cts_err("cts_plat_spi_read error"); + cts_err("cts_plat_spi_read error"); } - - return -ENODEV; + + return -EIO; } int cts_plat_is_normal_mode(struct cts_platform_data *pdata) { struct chipone_ts_data *cts_data; - u8 tx_buf[4] = {0}; + u8 tx_buf[4] = { 0 }; u16 fwid; u32 addr; int ret; - - cts_set_normal_addr(pdata->cts_dev); - cts_data = container_of(pdata->cts_dev, struct chipone_ts_data, cts_dev); - addr = CTS_DEVICE_FW_REG_CHIP_TYPE; - put_unaligned_be16(addr, tx_buf); - ret = cts_plat_spi_read(pdata, CTS_DEV_NORMAL_MODE_SPIADDR, tx_buf, 2, &fwid, 2, 3, 10); - fwid = be16_to_cpu(fwid); - if (ret || !cts_is_fwid_valid(fwid)) { - return false; - } - return true; + cts_set_normal_addr(pdata->cts_dev); + cts_data = + container_of(pdata->cts_dev, struct chipone_ts_data, cts_dev); + addr = CTS_DEVICE_FW_REG_CHIP_TYPE; + put_unaligned_be16(addr, tx_buf); + ret = + cts_plat_spi_read(pdata, CTS_DEV_NORMAL_MODE_SPIADDR, tx_buf, 2, + &fwid, 2, 3, 10); + fwid = be16_to_cpu(fwid); + if (ret || !cts_is_fwid_valid(fwid)) { + return false; + } + + return true; } #endif static void cts_plat_handle_irq(struct cts_platform_data *pdata) { - int ret; + int ret; - cts_dbg("Handle IRQ"); + cts_dbg("Handle IRQ"); - cts_lock_device(pdata->cts_dev); - ret = cts_irq_handler(pdata->cts_dev); - if (ret) { - cts_err("Device handle IRQ failed %d", ret); - } - cts_unlock_device(pdata->cts_dev); + cts_lock_device(pdata->cts_dev); + ret = cts_irq_handler(pdata->cts_dev); + if (ret) { + cts_err("Device handle IRQ failed %d", ret); + } + cts_unlock_device(pdata->cts_dev); } static irqreturn_t cts_plat_irq_handler(int irq, void *dev_id) { - struct cts_platform_data *pdata; + struct cts_platform_data *pdata; #ifndef CONFIG_GENERIC_HARDIRQS - struct chipone_ts_data *cts_data; + struct chipone_ts_data *cts_data; #endif /* CONFIG_GENERIC_HARDIRQS */ - cts_dbg("IRQ handler"); - - pdata = (struct cts_platform_data *)dev_id; - if (pdata == NULL) { - cts_err("IRQ handler with NULL dev_id"); - return IRQ_NONE; - } + cts_dbg("IRQ handler"); + pdata = (struct cts_platform_data *)dev_id; + if (pdata == NULL) { + cts_err("IRQ handler with NULL dev_id"); + return IRQ_NONE; + } #ifdef CONFIG_GENERIC_HARDIRQS - cts_plat_handle_irq(pdata); + cts_plat_handle_irq(pdata); #else /* CONFIG_GENERIC_HARDIRQS */ - cts_data = container_of(pdata->cts_dev, struct chipone_ts_data, cts_dev); + cts_data = + container_of(pdata->cts_dev, struct chipone_ts_data, cts_dev); - cts_plat_disable_irq(pdata); - - queue_work(cts_data->workqueue, &pdata->ts_irq_work); + if (queue_work(cts_data->workqueue, &pdata->ts_irq_work)) { + cts_dbg("IRQ queue work"); + cts_plat_disable_irq(pdata); + } else { + cts_warn("IRQ handler queue work failed as already on the queue"); + } #endif /* CONFIG_GENERIC_HARDIRQS */ - return IRQ_HANDLED; + return IRQ_HANDLED; } #ifndef CONFIG_GENERIC_HARDIRQS static void cts_plat_touch_dev_irq_work(struct work_struct *work) { - struct cts_platform_data *pdata = - container_of(work, struct cts_platform_data, ts_irq_work); + struct cts_platform_data *pdata = + container_of(work, struct cts_platform_data, ts_irq_work); - cts_dbg("IRQ work"); + cts_dbg("IRQ work"); - cts_plat_handle_irq(pdata); + cts_plat_handle_irq(pdata); - cts_plat_enable_irq(pdata); + cts_plat_enable_irq(pdata); } #endif /* CONFIG_GENERIC_HARDIRQS */ #ifdef CONFIG_CTS_OF static int cts_plat_parse_dt(struct cts_platform_data *pdata, - struct device_node *dev_node) + struct device_node *dev_node) { int ret = 0; cts_info("Parse device tree"); - pdata->int_gpio = of_get_named_gpio(dev_node, CFG_CTS_OF_INT_GPIO_NAME, 0); + pdata->int_gpio = + of_get_named_gpio(dev_node, CFG_CTS_OF_INT_GPIO_NAME, 0); if (!gpio_is_valid(pdata->int_gpio)) { cts_err("Parse INT GPIO from dt failed %d", pdata->int_gpio); pdata->int_gpio = -1; } cts_info(" %-12s: %d", "int gpio", pdata->int_gpio); - pdata->irq = gpio_to_irq(pdata->int_gpio); - if (pdata->irq < 0) { - cts_err("Parse irq failed %d", ret); - return pdata->irq; - } + pdata->irq = gpio_to_irq(pdata->int_gpio); + if (pdata->irq < 0) { + cts_err("Parse irq failed %d", ret); + return pdata->irq; + } cts_info(" %-12s: %d", "irq num", pdata->irq); #ifdef CFG_CTS_HAS_RESET_PIN - pdata->rst_gpio = of_get_named_gpio(dev_node, CFG_CTS_OF_RST_GPIO_NAME, 0); + pdata->rst_gpio = + of_get_named_gpio(dev_node, CFG_CTS_OF_RST_GPIO_NAME, 0); if (!gpio_is_valid(pdata->rst_gpio)) { cts_err("Parse RST GPIO from dt failed %d", pdata->rst_gpio); pdata->rst_gpio = -1; @@ -473,7 +516,7 @@ static int cts_plat_parse_dt(struct cts_platform_data *pdata, #endif /* CFG_CTS_HAS_RESET_PIN */ ret = of_property_read_u32(dev_node, CFG_CTS_OF_X_RESOLUTION_NAME, - &pdata->res_x); + &pdata->res_x); if (ret) { cts_warn("Parse X resolution from dt failed %d", ret); //return ret; @@ -481,66 +524,79 @@ static int cts_plat_parse_dt(struct cts_platform_data *pdata, cts_info(" %-12s: %d", "X resolution", pdata->res_x); ret = of_property_read_u32(dev_node, CFG_CTS_OF_Y_RESOLUTION_NAME, - &pdata->res_y); + &pdata->res_y); if (ret) { cts_warn("Parse Y resolution from dt failed %d", ret); //return ret; } cts_info(" %-12s: %d", "Y resolution", pdata->res_y); +#ifdef CFG_CTS_FW_UPDATE_SYS + ret = of_property_read_string(dev_node, CFG_CTS_OF_PANEL_SUPPLIER, + &pdata->panel_supplier); + if (ret) { + pdata->panel_supplier = NULL; + cts_warn("read panel supplier failed, ret=%d\n", ret); + } else { + cts_info("panel supplier=%s", (char *)pdata->panel_supplier); + } +#endif + return 0; } #endif /* CONFIG_CTS_OF */ #ifdef CFG_CTS_FORCE_UP -static void cts_plat_touch_event_timeout(unsigned long arg) +static void cts_plat_touch_event_timeout_work(struct work_struct *work) { - cts_warn("Touch event timeout"); + struct cts_platform_data *pdata = container_of + (work, struct cts_platform_data, touch_event_timeout_work.work); - cts_plat_release_all_touch((struct cts_platform_data *)arg); + cts_warn("Touch event timeout work"); + + cts_plat_release_all_touch(pdata); } #endif #ifdef CONFIG_CTS_I2C_HOST int cts_init_platform_data(struct cts_platform_data *pdata, - struct i2c_client *i2c_client) + struct i2c_client *i2c_client) #else int cts_init_platform_data(struct cts_platform_data *pdata, - struct spi_device *spi) - + struct spi_device *spi) #endif { struct input_dev *input_dev; - int ret; + int ret = 0; - cts_info("Init"); + cts_info("Init"); #ifdef CONFIG_CTS_OF - { - struct device *dev; + { + struct device *dev; #ifdef CONFIG_CTS_I2C_HOST - dev = &i2c_client->dev; + dev = &i2c_client->dev; #else dev = &spi->dev; #endif /* CONFIG_CTS_I2C_HOST */ - ret = cts_plat_parse_dt(pdata, dev->of_node); - if (ret) { - cts_err("Parse dt failed %d", ret); - return ret; - } - } + ret = cts_plat_parse_dt(pdata, dev->of_node); + if (ret) { + cts_err("Parse dt failed %d", ret); + return ret; + } + } #endif /* CONFIG_CTS_OF */ #ifdef CONFIG_CTS_I2C_HOST - pdata->i2c_client = i2c_client; - pdata->i2c_client->irq = pdata->irq; + pdata->i2c_client = i2c_client; + pdata->i2c_client->irq = pdata->irq; #else pdata->spi_client = spi; pdata->spi_client->irq = pdata->irq; #endif /* CONFIG_CTS_I2C_HOST */ - rt_mutex_init(&pdata->dev_lock); - spin_lock_init(&pdata->irq_lock); + rt_mutex_init(&pdata->dev_lock); + spin_lock_init(&pdata->irq_lock); input_dev = input_allocate_device(); if (input_dev == NULL) { @@ -550,32 +606,32 @@ int cts_init_platform_data(struct cts_platform_data *pdata, /** - Init input device */ input_dev->name = CFG_CTS_DEVICE_NAME; - input_dev->name = CFG_CTS_DEVICE_NAME; + input_dev->name = CFG_CTS_DEVICE_NAME; #ifdef CONFIG_CTS_I2C_HOST - input_dev->id.bustype = BUS_I2C; - input_dev->dev.parent = &pdata->i2c_client->dev; + input_dev->id.bustype = BUS_I2C; + input_dev->dev.parent = &pdata->i2c_client->dev; #else input_dev->id.bustype = BUS_SPI; input_dev->dev.parent = &pdata->spi_client->dev; #endif /* CONFIG_CTS_I2C_HOST */ - input_dev->evbit[0] = BIT_MASK(EV_SYN) | - BIT_MASK(EV_KEY) | - BIT_MASK(EV_ABS); + input_dev->evbit[0] = BIT_MASK(EV_SYN) | + BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); #ifdef CFG_CTS_SWAP_XY - input_set_abs_params(input_dev, ABS_MT_POSITION_X, - 0, pdata->res_y, 0, 0); - input_set_abs_params(input_dev, ABS_MT_POSITION_Y, - 0, pdata->res_x, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_X, + 0, pdata->res_y, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, + 0, pdata->res_x, 0, 0); #else /* CFG_CTS_SWAP_XY */ - input_set_abs_params(input_dev, ABS_MT_POSITION_X, - 0, pdata->res_x, 0, 0); - input_set_abs_params(input_dev, ABS_MT_POSITION_Y, - 0, pdata->res_y, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_X, + 0, pdata->res_x, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, + 0, pdata->res_y, 0, 0); #endif /* CFG_CTS_SWAP_XY */ input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0); - input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,0, 255, 0, 0); - input_set_abs_params(input_dev, ABS_MT_TRACKING_ID,0, CFG_CTS_MAX_TOUCH_NUM * 2, 0, 0); + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); + input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, + CFG_CTS_MAX_TOUCH_NUM * 2, 0, 0); input_set_capability(input_dev, EV_KEY, BTN_TOUCH); @@ -584,360 +640,356 @@ int cts_init_platform_data(struct cts_platform_data *pdata, #endif /* CONFIG_CTS_SLOTPROTOCOL */ __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); __set_bit(EV_ABS, input_dev->evbit); - input_set_drvdata(input_dev, pdata); - ret = input_register_device(input_dev); - if (ret) { - cts_err("Failed to register input device"); - return ret; - } + input_set_drvdata(input_dev, pdata); + ret = input_register_device(input_dev); + if (ret) { + cts_err("Failed to register input device"); + return ret; + } - pdata->ts_input_dev = input_dev; + pdata->ts_input_dev = input_dev; #if !defined(CONFIG_GENERIC_HARDIRQS) - INIT_WORK(&pdata->ts_irq_work, cts_plat_touch_dev_irq_work); + INIT_WORK(&pdata->ts_irq_work, cts_plat_touch_dev_irq_work); #endif /* CONFIG_GENERIC_HARDIRQS */ #ifdef CONFIG_CTS_VIRTUALKEY - { - u8 vkey_keymap[CFG_CTS_NUM_VKEY] = CFG_CTS_VKEY_KEYCODES; - memcpy(pdata->vkey_keycodes, vkey_keymap, sizeof(vkey_keymap)); - pdata->vkey_num = CFG_CTS_NUM_VKEY; - } + { + u8 vkey_keymap[CFG_CTS_NUM_VKEY] = CFG_CTS_VKEY_KEYCODES; + memcpy(pdata->vkey_keycodes, vkey_keymap, sizeof(vkey_keymap)); + pdata->vkey_num = CFG_CTS_NUM_VKEY; + } #endif /* CONFIG_CTS_VIRTUALKEY */ #ifdef CFG_CTS_GESTURE - { - u8 gesture_keymap[CFG_CTS_NUM_GESTURE][2] = CFG_CTS_GESTURE_KEYMAP; - memcpy(pdata->gesture_keymap, gesture_keymap, sizeof(gesture_keymap)); - pdata->gesture_num = CFG_CTS_NUM_GESTURE; - } + { + u8 gesture_keymap[CFG_CTS_NUM_GESTURE][2] = + CFG_CTS_GESTURE_KEYMAP; + memcpy(pdata->gesture_keymap, gesture_keymap, + sizeof(gesture_keymap)); + pdata->gesture_num = CFG_CTS_NUM_GESTURE; + } #endif /* CFG_CTS_GESTURE */ #ifdef CFG_CTS_FORCE_UP - setup_timer(&pdata->touch_event_timeout_timer, - cts_plat_touch_event_timeout, (unsigned long)pdata); + INIT_DELAYED_WORK(&pdata->touch_event_timeout_work, + cts_plat_touch_event_timeout_work); #endif #ifndef CONFIG_CTS_I2C_HOST - pdata->spi_speed = CFG_CTS_SPI_SPEED_KHZ; + pdata->spi_speed = CFG_CTS_SPI_SPEED_KHZ; #endif - return 0; + return 0; } int cts_deinit_platform_data(struct cts_platform_data *pdata) { - cts_info("De-Init platform_data"); - input_unregister_device(pdata->ts_input_dev); - return 0; + cts_info("De-Init platform_data"); + input_unregister_device(pdata->ts_input_dev); + return 0; } int cts_plat_request_resource(struct cts_platform_data *pdata) { - int ret; + int ret; - cts_info("Request resource"); - - ret = gpio_request_one(pdata->int_gpio, GPIOF_IN, - CFG_CTS_DEVICE_NAME "-int"); - if (ret) { - cts_err("Request INT gpio (%d) failed %d", pdata->int_gpio, ret); - goto err_out; - } + cts_info("Request resource"); + ret = gpio_request_one(pdata->int_gpio, GPIOF_IN, + CFG_CTS_DEVICE_NAME "-int"); + if (ret) { + cts_err("Request INT gpio (%d) failed %d", pdata->int_gpio, + ret); + goto err_out; + } #ifdef CFG_CTS_HAS_RESET_PIN - ret = gpio_request_one(pdata->rst_gpio, GPIOF_OUT_INIT_HIGH, - CFG_CTS_DEVICE_NAME "-rst"); - if (ret) { - cts_err("Request RST gpio (%d) failed %d", pdata->rst_gpio, ret); - goto err_free_int; - } + ret = gpio_request_one(pdata->rst_gpio, GPIOF_OUT_INIT_HIGH, + CFG_CTS_DEVICE_NAME "-rst"); + if (ret) { + cts_err("Request RST gpio (%d) failed %d", pdata->rst_gpio, + ret); + goto err_free_int; + } #endif /* CFG_CTS_HAS_RESET_PIN */ - - return 0; + return 0; #ifdef CONFIG_CTS_REGULATOR err_free_rst: #endif /* CONFIG_CTS_REGULATOR */ #ifdef CFG_CTS_HAS_RESET_PIN - gpio_free(pdata->rst_gpio); + gpio_free(pdata->rst_gpio); err_free_int: #endif /* CFG_CTS_HAS_RESET_PIN */ - gpio_free(pdata->int_gpio); + gpio_free(pdata->int_gpio); err_out: - return ret; + return ret; } void cts_plat_free_resource(struct cts_platform_data *pdata) { - cts_info("Free resource"); + cts_info("Free resource"); - if (gpio_is_valid(pdata->int_gpio)) { - gpio_free(pdata->int_gpio); - } + if (gpio_is_valid(pdata->int_gpio)) { + gpio_free(pdata->int_gpio); + } #ifdef CFG_CTS_HAS_RESET_PIN - if (gpio_is_valid(pdata->rst_gpio)) { - gpio_free(pdata->rst_gpio); - } + if (gpio_is_valid(pdata->rst_gpio)) { + gpio_free(pdata->rst_gpio); + } #endif /* CFG_CTS_HAS_RESET_PIN */ } int cts_plat_request_irq(struct cts_platform_data *pdata) { - int ret; - struct cts_device *cts_dev = pdata->cts_dev; - struct cts_device_fwdata *fwdata = &cts_dev->fwdata; - u8 int_mode; + int ret; + + cts_info("Request IRQ"); - cts_info("Request IRQ"); - int_mode = fwdata->int_mode; - cts_info("Get fw int mode:%d, request %s IRQ", int_mode, - int_mode==0?"falling" : "rising"); #ifdef CONFIG_GENERIC_HARDIRQS - if (int_mode) { - ret = request_threaded_irq(pdata->irq, NULL, - cts_plat_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT, - CFG_CTS_DRIVER_NAME, pdata); - } - else { - ret = request_threaded_irq(pdata->irq, NULL, - cts_plat_irq_handler, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - CFG_CTS_DRIVER_NAME, pdata); - } + ret = request_threaded_irq(pdata->irq, NULL, + cts_plat_irq_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + CFG_CTS_DRIVER_NAME, pdata); #else /* CONFIG_GENERIC_HARDIRQS */ - if (int_mode) { - ret = request_irq(pdata->irq, - cts_plat_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT, - CFG_CTS_DRIVER_NAME, pdata); - } - else { - ret = request_irq(pdata->irq, - cts_plat_irq_handler, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - CFG_CTS_DRIVER_NAME, pdata); - } + ret = request_irq(pdata->irq, + cts_plat_irq_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + CFG_CTS_DRIVER_NAME, pdata); #endif /* CONFIG_GENERIC_HARDIRQS */ - if (ret) { - cts_err("Request IRQ failed %d", ret); - return ret; - } + if (ret) { + cts_err("Request IRQ failed %d", ret); + return ret; + } - cts_plat_disable_irq(pdata); + cts_plat_disable_irq(pdata); - return 0; + return 0; } void cts_plat_free_irq(struct cts_platform_data *pdata) { - free_irq(pdata->irq, pdata); + free_irq(pdata->irq, pdata); } int cts_plat_enable_irq(struct cts_platform_data *pdata) { - unsigned long irqflags; + unsigned long irqflags; - cts_dbg("Enable IRQ"); + cts_dbg("Enable IRQ"); - if (pdata->irq > 0) { - spin_lock_irqsave(&pdata->irq_lock, irqflags); - if (pdata->irq_is_disable)/* && !cts_is_device_suspended(pdata->chip)) */{ - cts_dbg("Real enable IRQ"); - enable_irq(pdata->irq); - pdata->irq_is_disable = false; - } - spin_unlock_irqrestore(&pdata->irq_lock, irqflags); + if (pdata->irq > 0) { + spin_lock_irqsave(&pdata->irq_lock, irqflags); + if (pdata->irq_is_disable) { /* && !cts_is_device_suspended(pdata->chip)) */ + cts_dbg("Real enable IRQ"); + enable_irq(pdata->irq); + pdata->irq_is_disable = false; + } + spin_unlock_irqrestore(&pdata->irq_lock, irqflags); - return 0; - } + return 0; + } - return -ENODEV; + return -ENODEV; } int cts_plat_disable_irq(struct cts_platform_data *pdata) { - unsigned long irqflags; + unsigned long irqflags; - cts_dbg("Disable IRQ"); + cts_dbg("Disable IRQ"); - if (pdata->irq > 0) { - spin_lock_irqsave(&pdata->irq_lock, irqflags); - if (!pdata->irq_is_disable) { - cts_dbg("Real disable IRQ"); - disable_irq_nosync(pdata->irq); - pdata->irq_is_disable = true; - } - spin_unlock_irqrestore(&pdata->irq_lock, irqflags); + if (pdata->irq > 0) { + spin_lock_irqsave(&pdata->irq_lock, irqflags); + if (!pdata->irq_is_disable) { + cts_dbg("Real disable IRQ"); + disable_irq_nosync(pdata->irq); + pdata->irq_is_disable = true; + } + spin_unlock_irqrestore(&pdata->irq_lock, irqflags); - return 0; - } + return 0; + } - return -ENODEV; + return -ENODEV; } #ifdef CFG_CTS_HAS_RESET_PIN int cts_plat_reset_device(struct cts_platform_data *pdata) { - /* !!!can not be modified*/ - /* !!!can not be modified*/ - /* !!!can not be modified*/ - cts_info("Reset device"); + /* !!!can not be modified */ + /* !!!can not be modified */ + /* !!!can not be modified */ + cts_info("Reset device"); - gpio_set_value(pdata->rst_gpio, 1); - mdelay(1); - gpio_set_value(pdata->rst_gpio, 0); - mdelay(10); - gpio_set_value(pdata->rst_gpio, 1); - mdelay(40); + gpio_set_value(pdata->rst_gpio, 1); + mdelay(1); + gpio_set_value(pdata->rst_gpio, 0); + mdelay(10); + gpio_set_value(pdata->rst_gpio, 1); + mdelay(40); - return 0; + return 0; } int cts_plat_set_reset(struct cts_platform_data *pdata, int val) { - cts_info("Set Reset"); - if (val) { - gpio_set_value(pdata->rst_gpio, 1); - } - else { - gpio_set_value(pdata->rst_gpio, 0); - } - return 0; + cts_info("Set Reset to %s", val ? "HIGH" : "LOW"); + if (val) { + gpio_set_value(pdata->rst_gpio, 1); + } else { + gpio_set_value(pdata->rst_gpio, 0); + } + return 0; } #endif /* CFG_CTS_HAS_RESET_PIN */ +int cts_plat_get_int_pin(struct cts_platform_data *pdata) +{ + return gpio_get_value(pdata->int_gpio); +} + int cts_plat_power_up_device(struct cts_platform_data *pdata) { - cts_info("Power up device"); + cts_info("Power up device"); - return 0; + return 0; } int cts_plat_power_down_device(struct cts_platform_data *pdata) { - cts_info("Power down device"); + cts_info("Power down device"); - return 0; + return 0; } int cts_plat_init_touch_device(struct cts_platform_data *pdata) { - cts_info("Init touch device"); + cts_info("Init touch device"); - return 0; + return 0; } void cts_plat_deinit_touch_device(struct cts_platform_data *pdata) { - cts_info("De-init touch device"); + cts_info("De-init touch device"); #ifndef CONFIG_GENERIC_HARDIRQS - if (work_pending(&pdata->ts_irq_work)) { - cancel_work_sync(&pdata->ts_irq_work); - } + if (work_pending(&pdata->ts_irq_work)) { + cancel_work_sync(&pdata->ts_irq_work); + } #endif /* CONFIG_GENERIC_HARDIRQS */ } int cts_plat_process_touch_msg(struct cts_platform_data *pdata, - struct cts_device_touch_msg *msgs, int num) + struct cts_device_touch_msg *msgs, int num) { - struct input_dev *input_dev = pdata->ts_input_dev; - int i; - int contact = 0; + struct input_dev *input_dev = pdata->ts_input_dev; + int i; + int contact = 0; #ifdef CONFIG_CTS_SLOTPROTOCOL - static unsigned char finger_last[CFG_CTS_MAX_TOUCH_NUM] = {0}; - unsigned char finger_current[CFG_CTS_MAX_TOUCH_NUM] = {0}; + static unsigned char finger_last[CFG_CTS_MAX_TOUCH_NUM] = { 0 }; + unsigned char finger_current[CFG_CTS_MAX_TOUCH_NUM] = { 0 }; #endif - cts_dbg("Process touch %d msgs", num); - if (num ==0 || num > CFG_CTS_MAX_TOUCH_NUM) { - return 0; - } + cts_dbg("Process touch %d msgs", num); + if (num == 0 || num > CFG_CTS_MAX_TOUCH_NUM) { + return 0; + } - for (i = 0; i < num; i++) { - u16 x, y; + for (i = 0; i < num; i++) { + u16 x, y; - x = le16_to_cpu(msgs[i].x); - y = le16_to_cpu(msgs[i].y); + x = le16_to_cpu(msgs[i].x); + y = le16_to_cpu(msgs[i].y); #ifdef CFG_CTS_SWAP_XY - swap(x,y); + swap(x, y); #endif /* CFG_CTS_SWAP_XY */ #ifdef CFG_CTS_WRAP_X - x = wrap(pdata->res_x,x); + x = wrap(pdata->res_x, x); #endif /* CFG_CTS_WRAP_X */ #ifdef CFG_CTS_WRAP_Y - y = wrap(pdata->res_y,y); + y = wrap(pdata->res_y, y); #endif /* CFG_CTS_WRAP_Y */ - cts_dbg(" Process touch msg[%d]: id[%u] ev=%u x=%u y=%u p=%u", - i, msgs[i].id, msgs[i].event, x, y, msgs[i].pressure); + cts_dbg(" Process touch msg[%d]: id[%u] ev=%u x=%u y=%u p=%u", + i, msgs[i].id, msgs[i].event, x, y, msgs[i].pressure); if (msgs[i].event == CTS_DEVICE_TOUCH_EVENT_DOWN - || msgs[i].event == CTS_DEVICE_TOUCH_EVENT_MOVE - || msgs[i].event == CTS_DEVICE_TOUCH_EVENT_STAY) { + || msgs[i].event == CTS_DEVICE_TOUCH_EVENT_MOVE + || msgs[i].event == CTS_DEVICE_TOUCH_EVENT_STAY) { if (msgs[i].id < CFG_CTS_MAX_TOUCH_NUM) { finger_current[msgs[i].id] = 1; - } + } } #ifdef CONFIG_CTS_SLOTPROTOCOL //input_mt_slot(input_dev, msgs[i].id); - switch (msgs[i].event) { - case CTS_DEVICE_TOUCH_EVENT_DOWN: - case CTS_DEVICE_TOUCH_EVENT_MOVE: - case CTS_DEVICE_TOUCH_EVENT_STAY: - contact++; - input_mt_slot(input_dev, msgs[i].id); - input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, true); - input_report_abs(input_dev, ABS_MT_POSITION_X, x); - input_report_abs(input_dev, ABS_MT_POSITION_Y, y); - input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, msgs[i].pressure); - input_report_abs(input_dev, ABS_MT_PRESSURE, msgs[i].pressure); - break; + switch (msgs[i].event) { + case CTS_DEVICE_TOUCH_EVENT_DOWN: + case CTS_DEVICE_TOUCH_EVENT_MOVE: + case CTS_DEVICE_TOUCH_EVENT_STAY: + contact++; + input_mt_slot(input_dev, msgs[i].id); + input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, + true); + input_report_abs(input_dev, ABS_MT_POSITION_X, x); + input_report_abs(input_dev, ABS_MT_POSITION_Y, y); + input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, + msgs[i].pressure); + input_report_abs(input_dev, ABS_MT_PRESSURE, + msgs[i].pressure); + break; - case CTS_DEVICE_TOUCH_EVENT_UP: - //input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, false); - break; + case CTS_DEVICE_TOUCH_EVENT_UP: + //input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, false); + break; - default: - cts_warn("Process touch msg with unknwon event %u id %u", - msgs[i].event, msgs[i].id); - break; - } + default: + cts_warn + ("Process touch msg with unknwon event %u id %u", + msgs[i].event, msgs[i].id); + break; + } #else /* CONFIG_CTS_SLOTPROTOCOL */ - /** - * If the driver reports one of BTN_TOUCH or ABS_PRESSURE - * in addition to the ABS_MT events, the last SYN_MT_REPORT event - * may be omitted. Otherwise, the last SYN_REPORT will be dropped - * by the input core, resulting in no zero-contact event - * reaching userland. - */ - switch (msgs[i].event) { - case CTS_DEVICE_TOUCH_EVENT_DOWN: - case CTS_DEVICE_TOUCH_EVENT_MOVE: - case CTS_DEVICE_TOUCH_EVENT_STAY: - contact++; - input_report_abs(input_dev, ABS_MT_PRESSURE, msgs[i].pressure); - input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, msgs[i].pressure); - input_report_key(input_dev, BTN_TOUCH, 1); - input_report_abs(input_dev, ABS_MT_POSITION_X, x); - input_report_abs(input_dev, ABS_MT_POSITION_Y, y); - input_mt_sync(input_dev); - break; + /** + * If the driver reports one of BTN_TOUCH or ABS_PRESSURE + * in addition to the ABS_MT events, the last SYN_MT_REPORT event + * may be omitted. Otherwise, the last SYN_REPORT will be dropped + * by the input core, resulting in no zero-contact event + * reaching userland. + */ + switch (msgs[i].event) { + case CTS_DEVICE_TOUCH_EVENT_DOWN: + case CTS_DEVICE_TOUCH_EVENT_MOVE: + case CTS_DEVICE_TOUCH_EVENT_STAY: + contact++; + input_report_abs(input_dev, ABS_MT_PRESSURE, + msgs[i].pressure); + input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, + msgs[i].pressure); + input_report_key(input_dev, BTN_TOUCH, 1); + input_report_abs(input_dev, ABS_MT_POSITION_X, x); + input_report_abs(input_dev, ABS_MT_POSITION_Y, y); + input_mt_sync(input_dev); + break; - case CTS_DEVICE_TOUCH_EVENT_UP: - break; - default: - cts_warn("Process touch msg with unknwon event %u id %u", - msgs[i].event, msgs[i].id); - break; - } + case CTS_DEVICE_TOUCH_EVENT_UP: + break; + default: + cts_warn + ("Process touch msg with unknwon event %u id %u", + msgs[i].event, msgs[i].id); + break; + } #endif /* CONFIG_CTS_SLOTPROTOCOL */ - } - + } #ifdef CONFIG_CTS_SLOTPROTOCOL for (i = 0; i < CFG_CTS_MAX_TOUCH_NUM; i++) { if (finger_last[i] != 0 && finger_current[i] == 0) { input_mt_slot(input_dev, i); - input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, false); - } + input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, + false); + } finger_last[i] = finger_current[i]; } input_report_key(input_dev, BTN_TOUCH, contact > 0); @@ -945,195 +997,205 @@ int cts_plat_process_touch_msg(struct cts_platform_data *pdata, if (contact == 0) { input_report_key(input_dev, BTN_TOUCH, 0); input_mt_sync(input_dev); - } + } #endif - input_sync(input_dev); + input_sync(input_dev); #ifdef CFG_CTS_FORCE_UP if (contact) { - mod_timer(&pdata->touch_event_timeout_timer, jiffies + msecs_to_jiffies(100)); - } else { - del_timer(&pdata->touch_event_timeout_timer); - } -#endif - return 0; + struct chipone_ts_data *cts_data; + cts_data = container_of(pdata->cts_dev, struct chipone_ts_data, cts_dev); + + if (delayed_work_pending(&pdata->touch_event_timeout_work)) { + mod_delayed_work(cts_data->workqueue, + &pdata->touch_event_timeout_work, + msecs_to_jiffies(100)); + } else { + queue_delayed_work(cts_data->workqueue, + &pdata->touch_event_timeout_work, + msecs_to_jiffies(100)); + } + } else { + cancel_delayed_work_sync(&pdata->touch_event_timeout_work); + } +#endif + return 0; } int cts_plat_release_all_touch(struct cts_platform_data *pdata) { - struct input_dev *input_dev = pdata->ts_input_dev; + struct input_dev *input_dev = pdata->ts_input_dev; #if defined(CONFIG_CTS_SLOTPROTOCOL) - int id; + int id; #endif /* CONFIG_CTS_SLOTPROTOCOL */ - cts_info("Release all touch"); + cts_info("Release all touch"); #ifdef CONFIG_CTS_SLOTPROTOCOL - for (id = 0; id < CFG_CTS_MAX_TOUCH_NUM; id++) { - input_mt_slot(input_dev, id); - input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, false); - } - input_report_key(input_dev, BTN_TOUCH, 0); + for (id = 0; id < CFG_CTS_MAX_TOUCH_NUM; id++) { + input_mt_slot(input_dev, id); + input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, false); + } + input_report_key(input_dev, BTN_TOUCH, 0); #else - input_report_key(input_dev, BTN_TOUCH, 0); - input_mt_sync(input_dev); + input_report_key(input_dev, BTN_TOUCH, 0); + input_mt_sync(input_dev); #endif /* CONFIG_CTS_SLOTPROTOCOL */ - input_sync(input_dev); -#ifdef CFG_CTS_FORCE_UP - del_timer(&pdata->touch_event_timeout_timer); -#endif - return 0; + input_sync(input_dev); + + return 0; } #ifdef CONFIG_CTS_VIRTUALKEY int cts_plat_init_vkey_device(struct cts_platform_data *pdata) { - int i; + int i; - cts_info("Init VKey"); + cts_info("Init VKey"); - pdata->vkey_state = 0; + pdata->vkey_state = 0; - for (i = 0; i < pdata->vkey_num; i++) { - input_set_capability(pdata->ts_input_dev, - EV_KEY, pdata->vkey_keycodes[i]); - } + for (i = 0; i < pdata->vkey_num; i++) { + input_set_capability(pdata->ts_input_dev, + EV_KEY, pdata->vkey_keycodes[i]); + } - return 0; + return 0; } void cts_plat_deinit_vkey_device(struct cts_platform_data *pdata) { - cts_info("De-init VKey"); + cts_info("De-init VKey"); - pdata->vkey_state = 0; + pdata->vkey_state = 0; } int cts_plat_process_vkey(struct cts_platform_data *pdata, u8 vkey_state) { - u8 event; - int i; + u8 event; + int i; - event = pdata->vkey_state ^ vkey_state; + event = pdata->vkey_state ^ vkey_state; - cts_dbg("Process vkey state=0x%02x, event=0x%02x", vkey_state, event); + cts_dbg("Process vkey state=0x%02x, event=0x%02x", vkey_state, event); - for (i = 0; i < pdata->vkey_num; i++) { - input_report_key(pdata->ts_input_dev, - pdata->vkey_keycodes[i], vkey_state & BIT(i) ? 1 : 0); - } + for (i = 0; i < pdata->vkey_num; i++) { + input_report_key(pdata->ts_input_dev, + pdata->vkey_keycodes[i], + vkey_state & BIT(i) ? 1 : 0); + } - pdata->vkey_state = vkey_state; + pdata->vkey_state = vkey_state; - return 0; + return 0; } int cts_plat_release_all_vkey(struct cts_platform_data *pdata) { - int i; + int i; - cts_info("Release all vkeys"); + cts_info("Release all vkeys"); - for (i = 0; i < pdata->vkey_num; i++) { - if (pdata->vkey_state & BIT(i)) { - input_report_key(pdata->ts_input_dev, pdata->vkey_keycodes[i], 0); - } - } + for (i = 0; i < pdata->vkey_num; i++) { + if (pdata->vkey_state & BIT(i)) { + input_report_key(pdata->ts_input_dev, + pdata->vkey_keycodes[i], 0); + } + } - pdata->vkey_state = 0; + pdata->vkey_state = 0; - return 0; + return 0; } #endif /* CONFIG_CTS_VIRTUALKEY */ #ifdef CFG_CTS_GESTURE int cts_plat_enable_irq_wake(struct cts_platform_data *pdata) { - cts_info("Enable IRQ wake"); + cts_info("Enable IRQ wake"); - if (pdata->irq > 0) { - if (!pdata->irq_wake_enabled) { - pdata->irq_wake_enabled = true; - return enable_irq_wake(pdata->irq); - } + if (pdata->irq > 0) { + if (!pdata->irq_wake_enabled) { + pdata->irq_wake_enabled = true; + return enable_irq_wake(pdata->irq); + } - cts_warn("Enable irq wake while already disabled"); - return -EINVAL; - } + cts_warn("Enable irq wake while already disabled"); + return -EINVAL; + } - cts_warn("Enable irq wake while irq invalid %d", pdata->irq); - return -ENODEV; + cts_warn("Enable irq wake while irq invalid %d", pdata->irq); + return -ENODEV; } int cts_plat_disable_irq_wake(struct cts_platform_data *pdata) { - cts_info("Disable IRQ wake"); + cts_info("Disable IRQ wake"); - if (pdata->irq > 0) { - if (pdata->irq_wake_enabled) { - pdata->irq_wake_enabled = false; - return disable_irq_wake(pdata->irq); - } + if (pdata->irq > 0) { + if (pdata->irq_wake_enabled) { + pdata->irq_wake_enabled = false; + return disable_irq_wake(pdata->irq); + } - cts_warn("Disable irq wake while already disabled"); - return -EINVAL; - } + cts_warn("Disable irq wake while already disabled"); + return -EINVAL; + } - cts_warn("Disable irq wake while irq invalid %d", pdata->irq); - return -ENODEV; + cts_warn("Disable irq wake while irq invalid %d", pdata->irq); + return -ENODEV; } int cts_plat_init_gesture(struct cts_platform_data *pdata) { - int i; + int i; - cts_info("Init gesture"); + cts_info("Init gesture"); - // TODO: If system will issure enable/disable command, comment following line. - //cts_enable_gesture_wakeup(pdata->cts_dev); + // TODO: If system will issure enable/disable command, comment following line. + //cts_enable_gesture_wakeup(pdata->cts_dev); - for (i = 0; i < pdata->gesture_num; i ++) { - input_set_capability(pdata->ts_input_dev, EV_KEY, - pdata->gesture_keymap[i][1]); - } + for (i = 0; i < pdata->gesture_num; i++) { + input_set_capability(pdata->ts_input_dev, EV_KEY, + pdata->gesture_keymap[i][1]); + } - return 0; + return 0; } void cts_plat_deinit_gesture(struct cts_platform_data *pdata) { - cts_info("De-init gesture"); + cts_info("De-init gesture"); } int cts_plat_process_gesture_info(struct cts_platform_data *pdata, - struct cts_device_gesture_info *gesture_info) + struct cts_device_gesture_info *gesture_info) { - int i; + int i; - cts_info("Process gesture, id=0x%02x", gesture_info->gesture_id); + cts_info("Process gesture, id=0x%02x", gesture_info->gesture_id); #if defined(CFG_CTS_GESTURE_REPORT_KEY) - for (i = 0; i < CFG_CTS_NUM_GESTURE; i++) { - if (gesture_info->gesture_id == pdata->gesture_keymap[i][0]) { - cts_info("Report key[%u]", pdata->gesture_keymap[i][1]); - input_report_key(pdata->ts_input_dev, - pdata->gesture_keymap[i][1], 1); - input_sync(pdata->ts_input_dev); + for (i = 0; i < CFG_CTS_NUM_GESTURE; i++) { + if (gesture_info->gesture_id == pdata->gesture_keymap[i][0]) { + cts_info("Report key[%u]", pdata->gesture_keymap[i][1]); + input_report_key(pdata->ts_input_dev, + pdata->gesture_keymap[i][1], 1); + input_sync(pdata->ts_input_dev); - input_report_key(pdata->ts_input_dev, - pdata->gesture_keymap[i][1], 0); - input_sync(pdata->ts_input_dev); + input_report_key(pdata->ts_input_dev, + pdata->gesture_keymap[i][1], 0); + input_sync(pdata->ts_input_dev); - return 0; - } - } + return 0; + } + } #endif /* CFG_CTS_GESTURE_REPORT_KEY */ - cts_warn("Process unrecognized gesture id=%u", - gesture_info->gesture_id); + cts_warn("Process unrecognized gesture id=%u", + gesture_info->gesture_id); - return -EINVAL; + return -EINVAL; } #endif /* CFG_CTS_GESTURE */ - diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_platform.h b/drivers/input/touchscreen/chipone_tddi_mmi/cts_platform.h old mode 100755 new mode 100644 index e7d997beabc7..d492f2659f20 --- a/drivers/input/touchscreen/chipone_tddi_mmi/cts_platform.h +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_platform.h @@ -60,105 +60,114 @@ extern bool cts_show_debug_log; printk("CTS-" LOG_TAG " " fmt"\n", ##__VA_ARGS__) #define cts_dbg(fmt, ...) \ do { \ - if (cts_show_debug_log) \ - printk("CTS-" LOG_TAG " "fmt"\n", ##__VA_ARGS__); \ - } while(0) + if (cts_show_debug_log) \ + printk("CTS-" LOG_TAG " "fmt"\n", ##__VA_ARGS__); \ + } while (0) struct cts_device; struct cts_device_touch_msg; struct cts_device_gesture_info; struct cts_platform_data { - int irq; - int int_gpio; + int irq; + int int_gpio; #ifdef CFG_CTS_HAS_RESET_PIN - int rst_gpio; -#endif /* CFG_CTS_HAS_RESET_PIN */ + int rst_gpio; +#endif /* CFG_CTS_HAS_RESET_PIN */ - u32 res_x; - u32 res_y; + u32 res_x; + u32 res_y; #ifdef CONFIG_CTS_VIRTUALKEY - u8 vkey_num; - u8 vkey_state; - u8 vkey_keycodes[CFG_CTS_MAX_VKEY_NUM]; -#endif /* CONFIG_CTS_VIRTUALKEY */ + u8 vkey_num; + u8 vkey_state; + u8 vkey_keycodes[CFG_CTS_MAX_VKEY_NUM]; +#endif /* CONFIG_CTS_VIRTUALKEY */ - struct cts_device *cts_dev; +#ifdef CFG_CTS_FW_UPDATE_SYS + const char *panel_supplier; +#endif - struct input_dev *ts_input_dev; + struct cts_device *cts_dev; + + struct input_dev *ts_input_dev; #ifndef CONFIG_GENERIC_HARDIRQS - struct work_struct ts_irq_work; -#endif /* CONFIG_GENERIC_HARDIRQS */ + struct work_struct ts_irq_work; +#endif /* CONFIG_GENERIC_HARDIRQS */ - struct rt_mutex dev_lock; - struct spinlock irq_lock; - bool irq_is_disable; + struct rt_mutex dev_lock; + struct spinlock irq_lock; + bool irq_is_disable; #ifdef CFG_CTS_GESTURE - u8 gesture_num; - u8 gesture_keymap[CFG_CTS_NUM_GESTURE][2]; - bool irq_wake_enabled; -#endif /* CFG_CTS_GESTURE */ + u8 gesture_num; + u8 gesture_keymap[CFG_CTS_NUM_GESTURE][2]; + bool irq_wake_enabled; +#endif /* CFG_CTS_GESTURE */ #ifdef CONFIG_CTS_PM_FB_NOTIFIER - struct notifier_block fb_notifier; -#endif /* CONFIG_CTS_PM_FB_NOTIFIER */ + struct notifier_block fb_notifier; +#endif /* CONFIG_CTS_PM_FB_NOTIFIER */ #ifdef CFG_CTS_FORCE_UP - struct timer_list touch_event_timeout_timer; + struct delayed_work touch_event_timeout_work; #endif #ifdef CFG_CTS_FW_LOG_REDIRECT - u8 fw_log_buf[CTS_FW_LOG_BUF_LEN]; + u8 fw_log_buf[CTS_FW_LOG_BUF_LEN]; #endif #ifdef CONFIG_CTS_I2C_HOST - struct i2c_client *i2c_client; - u8 i2c_fifo_buf[CFG_CTS_MAX_I2C_XFER_SIZE]; + struct i2c_client *i2c_client; + u8 i2c_fifo_buf[CFG_CTS_MAX_I2C_XFER_SIZE]; #else struct spi_device *spi_client; - u8 spi_cache_buf[ALIGN(CFG_CTS_MAX_SPI_XFER_SIZE+10,4)]; - u8 spi_rx_buf[ALIGN(CFG_CTS_MAX_SPI_XFER_SIZE+10,4)]; - u8 spi_tx_buf[ALIGN(CFG_CTS_MAX_SPI_XFER_SIZE+10,4)]; + u8 spi_cache_buf[ALIGN(CFG_CTS_MAX_SPI_XFER_SIZE + 10, 4)]; + u8 spi_rx_buf[ALIGN(CFG_CTS_MAX_SPI_XFER_SIZE + 10, 4)]; + u8 spi_tx_buf[ALIGN(CFG_CTS_MAX_SPI_XFER_SIZE + 10, 4)]; u32 spi_speed; -#endif /* CONFIG_CTS_I2C_HOST */ +#endif /* CONFIG_CTS_I2C_HOST */ - struct cts_device_touch_info touch_info; + struct cts_device_touch_info touch_info; }; #ifdef CONFIG_CTS_I2C_HOST extern size_t cts_plat_get_max_i2c_xfer_size(struct cts_platform_data *pdata); extern u8 *cts_plat_get_i2c_xfer_buf(struct cts_platform_data *pdata, - size_t xfer_size); + size_t xfer_size); extern int cts_plat_i2c_write(struct cts_platform_data *pdata, u8 i2c_addr, - const void *src, size_t len, int retry, int delay); + const void *src, size_t len, int retry, + int delay); extern int cts_plat_i2c_read(struct cts_platform_data *pdata, u8 i2c_addr, - const u8 *wbuf, size_t wlen, void *rbuf, size_t rlen, - int retry, int delay); + const u8 *wbuf, size_t wlen, void *rbuf, + size_t rlen, int retry, int delay); extern int cts_plat_is_i2c_online(struct cts_platform_data *pdata, u8 i2c_addr); #else /* CONFIG_CTS_I2C_HOST */ extern size_t cts_plat_get_max_spi_xfer_size(struct cts_platform_data *pdata); -extern u8 *cts_plat_get_spi_xfer_buf(struct cts_platform_data *pdata, size_t xfer_size); -extern int cts_plat_spi_write(struct cts_platform_data *pdata, u8 i2c_addr, const void *src, - size_t len, int retry, int delay); +extern u8 *cts_plat_get_spi_xfer_buf(struct cts_platform_data *pdata, + size_t xfer_size); +extern int cts_plat_spi_write(struct cts_platform_data *pdata, u8 i2c_addr, + const void *src, size_t len, int retry, + int delay); extern int cts_plat_spi_read(struct cts_platform_data *pdata, u8 i2c_addr, - const u8 *wbuf, size_t wlen, void *rbuf, size_t rlen, - int retry, int delay); -extern int cts_plat_spi_read_delay_idle(struct cts_platform_data *pdata, u8 dev_addr, - const u8 *wbuf, size_t wlen, void *rbuf, size_t rlen, - int retry, int delay, int idle); -extern int cts_spi_send_recv(struct cts_platform_data *pdata, size_t len , u8 *tx_buffer, u8 *rx_buffer); + const u8 *wbuf, size_t wlen, void *rbuf, + size_t rlen, int retry, int delay); +extern int cts_plat_spi_read_delay_idle(struct cts_platform_data *pdata, + u8 dev_addr, const u8 *wbuf, + size_t wlen, void *rbuf, size_t rlen, + int retry, int delay, int idle); +extern int cts_spi_send_recv(struct cts_platform_data *pdata, size_t len, + u8 *tx_buffer, u8 *rx_buffer); #endif /* CONFIG_CTS_I2C_HOST */ #ifdef CONFIG_CTS_I2C_HOST extern int cts_init_platform_data(struct cts_platform_data *pdata, - struct i2c_client *i2c_client); + struct i2c_client *i2c_client); #else extern int cts_plat_is_normal_mode(struct cts_platform_data *pdata); extern int cts_init_platform_data(struct cts_platform_data *pdata, - struct spi_device *spi); + struct spi_device *spi); #endif extern int cts_deinit_platform_data(struct cts_platform_data *pdata); @@ -173,25 +182,45 @@ extern int cts_plat_disable_irq(struct cts_platform_data *pdata); #ifdef CFG_CTS_HAS_RESET_PIN extern int cts_plat_reset_device(struct cts_platform_data *pdata); #else /* CFG_CTS_HAS_RESET_PIN */ -static inline int cts_plat_reset_device(struct cts_platform_data *pdata) {return 0;} +static inline int cts_plat_reset_device(struct cts_platform_data *pdata) +{ + return 0; +} #endif /* CFG_CTS_HAS_RESET_PIN */ extern int cts_plat_init_touch_device(struct cts_platform_data *pdata); extern void cts_plat_deinit_touch_device(struct cts_platform_data *pdata); extern int cts_plat_process_touch_msg(struct cts_platform_data *pdata, - struct cts_device_touch_msg *msgs, int num); + struct cts_device_touch_msg *msgs, + int num); extern int cts_plat_release_all_touch(struct cts_platform_data *pdata); #ifdef CONFIG_CTS_VIRTUALKEY extern int cts_plat_init_vkey_device(struct cts_platform_data *pdata); extern void cts_plat_deinit_vkey_device(struct cts_platform_data *pdata); -extern int cts_plat_process_vkey(struct cts_platform_data *pdata, u8 vkey_state); +extern int cts_plat_process_vkey(struct cts_platform_data *pdata, + u8 vkey_state); extern int cts_plat_release_all_vkey(struct cts_platform_data *pdata); #else /* CONFIG_CTS_VIRTUALKEY */ -static inline int cts_plat_init_vkey_device(struct cts_platform_data *pdata) {return 0;} -static inline void cts_plat_deinit_vkey_device(struct cts_platform_data *pdata) {} -static inline int cts_plat_process_vkey(struct cts_platform_data *pdata, u8 vkey_state) {return 0;} -static inline int cts_plat_release_all_vkey(struct cts_platform_data *pdata) {return 0;} +static inline int cts_plat_init_vkey_device(struct cts_platform_data *pdata) +{ + return 0; +} + +static inline void cts_plat_deinit_vkey_device(struct cts_platform_data *pdata) +{ +} + +static inline int cts_plat_process_vkey(struct cts_platform_data *pdata, + u8 vkey_state) +{ + return 0; +} + +static inline int cts_plat_release_all_vkey(struct cts_platform_data *pdata) +{ + return 0; +} #endif /* CONFIG_CTS_VIRTUALKEY */ #ifdef CFG_CTS_GESTURE @@ -201,17 +230,27 @@ extern int cts_plat_disable_irq_wake(struct cts_platform_data *pdata); extern int cts_plat_init_gesture(struct cts_platform_data *pdata); extern void cts_plat_deinit_gesture(struct cts_platform_data *pdata); extern int cts_plat_process_gesture_info(struct cts_platform_data *pdata, - struct cts_device_gesture_info *gesture_info); + struct cts_device_gesture_info + *gesture_info); #else /* CFG_CTS_GESTURE */ -static inline int cts_plat_init_gesture(struct cts_platform_data *pdata) {return 0;} -static inline void cts_plat_deinit_gesture(struct cts_platform_data *pdata) {} -#endif /* CFG_CTS_GESTURE */ +static inline int cts_plat_init_gesture(struct cts_platform_data *pdata) +{ + return 0; +} -#endif /* CTS_PLATFORM_H */ +static inline void cts_plat_deinit_gesture(struct cts_platform_data *pdata) +{ +} +#endif /* CFG_CTS_GESTURE */ #ifdef CFG_CTS_FW_LOG_REDIRECT extern size_t cts_plat_get_max_fw_log_size(struct cts_platform_data *pdata); -extern u8 *cts_plat_get_fw_log_buf(struct cts_platform_data *pdata, size_t size); +extern u8 *cts_plat_get_fw_log_buf(struct cts_platform_data *pdata, + size_t size); #endif extern int cts_plat_set_reset(struct cts_platform_data *pdata, int val); +extern int cts_plat_get_int_pin(struct cts_platform_data *pdata); + +#endif /* CTS_PLATFORM_H */ + diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_sfctrl.h b/drivers/input/touchscreen/chipone_tddi_mmi/cts_sfctrl.h old mode 100755 new mode 100644 index fbece22161ac..81a8c63c5a17 --- a/drivers/input/touchscreen/chipone_tddi_mmi/cts_sfctrl.h +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_sfctrl.h @@ -1,39 +1,38 @@ -#ifndef CTS_SFCTRL_H -#define CTS_SFCTRL_H - -#include "cts_core.h" -#include "cts_spi_flash.h" - -struct cts_device; - -struct cts_sfctrl_ops { - int (*rdid)(const struct cts_device *cts_dev, u32 *id); - int (*se)(const struct cts_device *cts_dev, u32 sector_addr); - int (*be)(const struct cts_device *cts_dev, u32 sector_addr); - int (*read)(const struct cts_device *cts_dev, - u32 flash_addr, void *dst, size_t len); - int (*read_to_sram)(const struct cts_device *cts_dev, - u32 flash_addr, u32 sram_addr, size_t len); - int (*program)(const struct cts_device *cts_dev, - u32 flash_addr, const void *src, size_t len); - int (*program_from_sram)(const struct cts_device *cts_dev, - u32 flash_addr, u32 sram_addr, size_t len); - int (*calc_sram_crc)(const struct cts_device *cts_dev, - u32 sram_addr, size_t len, u32 *crc); - int (*calc_flash_crc)(const struct cts_device *cts_dev, - u32 flash_addr, size_t len, u32 *crc); - -}; - -struct cts_sfctrl { - u32 reg_base; - u32 xchg_sram_base; - size_t xchg_sram_size; - - const struct cts_sfctrl_ops *ops; -}; - -extern const struct cts_sfctrl_ops cts_sfctrlv2_ops; - -#endif /* CTS_SFCTRL_H */ - +#ifndef CTS_SFCTRL_H +#define CTS_SFCTRL_H + +#include "cts_core.h" +#include "cts_spi_flash.h" + +struct cts_device; + +struct cts_sfctrl_ops { + int (*rdid) (const struct cts_device *cts_dev, u32 *id); + int (*se) (const struct cts_device *cts_dev, u32 sector_addr); + int (*be) (const struct cts_device *cts_dev, u32 sector_addr); + int (*read) (const struct cts_device *cts_dev, + u32 flash_addr, void *dst, size_t len); + int (*read_to_sram) (const struct cts_device *cts_dev, + u32 flash_addr, u32 sram_addr, size_t len); + int (*program) (const struct cts_device *cts_dev, + u32 flash_addr, const void *src, size_t len); + int (*program_from_sram) (const struct cts_device *cts_dev, + u32 flash_addr, u32 sram_addr, size_t len); + int (*calc_sram_crc) (const struct cts_device *cts_dev, + u32 sram_addr, size_t len, u32 *crc); + int (*calc_flash_crc) (const struct cts_device *cts_dev, + u32 flash_addr, size_t len, u32 *crc); + +}; + +struct cts_sfctrl { + u32 reg_base; + u32 xchg_sram_base; + size_t xchg_sram_size; + + const struct cts_sfctrl_ops *ops; +}; + +extern const struct cts_sfctrl_ops cts_sfctrlv2_ops; + +#endif /* CTS_SFCTRL_H */ diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_sfctrlv2.c b/drivers/input/touchscreen/chipone_tddi_mmi/cts_sfctrlv2.c old mode 100755 new mode 100644 index b70d8aadcce9..3b0f1a06c700 --- a/drivers/input/touchscreen/chipone_tddi_mmi/cts_sfctrlv2.c +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_sfctrlv2.c @@ -1,333 +1,347 @@ -#define LOG_TAG "SFCtrl" - -#include "cts_config.h" -#include "cts_platform.h" -#include "cts_core.h" -#include "cts_sfctrl.h" - -#define rSFCTRLv2_CMD_SEL (0x0000) -#define rSFCTRLv2_FLASH_ADDR (0x0004) -#define rSFCTRLv2_SRAM_ADDR (0x0008) -#define rSFCTRLv2_DATA_LENGTH (0x000C) -#define rSFCTRLv2_START_DEXC (0x0010) -#define rSFCTRLv2_RELEASE_FLASH (0x0014) -#define rSFCTRLv2_HW_STATE (0x0018) -#define rSFCTRLv2_CRC_RESULT (0x001C) -#define rSFCTRLv2_SRAM_CRC_START (0x0020) -#define rSFCTRLv2_FLASH_CRC_START (0x0022) -#define rSFCTRLv2_SF_BUSY (0x0024) - -/** Constants for register @ref rSFCTRLv2_CMD_SEL */ -enum sfctrlv2_cmd { - SFCTRLv2_CMD_FAST_READ = 0x01u, - SFCTRLv2_CMD_SE = 0x02u, - SFCTRLv2_CMD_BE = 0x03u, - SFCTRLv2_CMD_PP = 0x04u, - SFCTRLv2_CMD_RDSR = 0x05u, - SFCTRLv2_CMD_RDID = 0x06u -}; - -/** SPI flash controller v2 operation flags. */ -enum sfctrlv2_opflags { - SFCTRLv2_OPFLAG_READ = BIT(0), - SFCTRLv2_OPFLAG_SET_FLASH_ADDR = BIT(1), - SFCTRLv2_OPFLAG_SRAM_DATA_XCHG = BIT(2), - SFCTRLv2_OPFLAG_SET_DATA_LENGTH = BIT(3), - SFCTRLv2_OPFLAG_WAIT_WIP_CLR = BIT(4), - -}; - -#define SFCTRLv2_CMD_RDID_FLAGS \ - (SFCTRLv2_OPFLAG_READ | \ - SFCTRLv2_OPFLAG_SRAM_DATA_XCHG) - -#define SFCTRLv2_CMD_RDSR_FLAGS \ - (SFCTRLv2_OPFLAG_READ | \ - SFCTRLv2_OPFLAG_SRAM_DATA_XCHG) - -#define SFCTRLv2_CMD_SE_FLAGS \ - (SFCTRLv2_OPFLAG_SET_FLASH_ADDR | \ - SFCTRLv2_OPFLAG_WAIT_WIP_CLR) - -#define SFCTRLv2_CMD_BE_FLAGS \ - (SFCTRLv2_OPFLAG_SET_FLASH_ADDR | \ - SFCTRLv2_OPFLAG_WAIT_WIP_CLR) - -#define SFCTRLv2_CMD_PP_FLAGS \ - (SFCTRLv2_OPFLAG_SET_FLASH_ADDR | \ - SFCTRLv2_OPFLAG_SRAM_DATA_XCHG | \ - SFCTRLv2_OPFLAG_SET_DATA_LENGTH | \ - SFCTRLv2_OPFLAG_WAIT_WIP_CLR) - -#define SFCTRLv2_CMD_FAST_READ_FLAGS \ - (SFCTRLv2_OPFLAG_READ | \ - SFCTRLv2_OPFLAG_SET_FLASH_ADDR | \ - SFCTRLv2_OPFLAG_SRAM_DATA_XCHG | \ - SFCTRLv2_OPFLAG_SET_DATA_LENGTH) - -#define sfctrl_reg_addr(cts_dev, offset) \ - ((cts_dev)->hwdata->sfctrl->reg_base + offset) - -#define DEFINE_SFCTRL_REG_ACCESS_FUNC(access_type, data_type) \ - static inline int sfctrl_reg_ ## access_type(const struct cts_device *cts_dev, \ - u32 reg, data_type data) { \ - return cts_hw_reg_ ## access_type(cts_dev, sfctrl_reg_addr(cts_dev, reg), data); \ - } - -DEFINE_SFCTRL_REG_ACCESS_FUNC(writeb, u8) -DEFINE_SFCTRL_REG_ACCESS_FUNC(writew, u16) -DEFINE_SFCTRL_REG_ACCESS_FUNC(writel, u32) -DEFINE_SFCTRL_REG_ACCESS_FUNC(readb, u8 *) -DEFINE_SFCTRL_REG_ACCESS_FUNC(readw, u16 *) -DEFINE_SFCTRL_REG_ACCESS_FUNC(readl, u32 *) - -#define sfctrl_write_reg_check_ret(access_type, reg, val) \ - do { \ - int ret; \ - cts_dbg("Write " #reg " to 0x%x", val); \ - ret = sfctrl_reg_ ## access_type(cts_dev, reg, val); \ - if (ret) { \ - cts_err("Write " #reg " failed %d", ret); \ - return ret; \ - } \ - } while (0) - -#define sfctrl_read_reg_check_ret(access_type, reg, val) \ - do { \ - int ret; \ - cts_dbg("Read " #reg ""); \ - ret = sfctrl_reg_ ## access_type(cts_dev, reg, val); \ - if (ret) { \ - cts_err("Read " #reg " failed %d", ret); \ - return ret; \ - } \ - } while (0) - -static int wait_sfctrl_xfer_comp(const struct cts_device *cts_dev) -{ - int retries = 0; - u8 status; - - do { - sfctrl_read_reg_check_ret(readb, rSFCTRLv2_SF_BUSY, &status); - if(status == 0) { - return 0; - } - - mdelay(1); - } while(status && retries++ < 1000); - - return -ETIMEDOUT; -} - -static int sfctrlv2_rdsr(const struct cts_device *cts_dev, u8 *status) -{ -#define RDSR_XCHG_SRAM_ADDR (cts_dev->hwdata->sram_size - 1) - - int ret; - - sfctrl_write_reg_check_ret(writeb, rSFCTRLv2_CMD_SEL, SFCTRLv2_CMD_RDSR); - sfctrl_write_reg_check_ret(writel, rSFCTRLv2_SRAM_ADDR, RDSR_XCHG_SRAM_ADDR); - sfctrl_write_reg_check_ret(writeb, rSFCTRLv2_START_DEXC, 1); - - if((ret = wait_sfctrl_xfer_comp(cts_dev)) != 0) { - cts_err("Wait sfctrl ready failed %d", ret); - return ret; - } - - ret = cts_sram_readb(cts_dev, RDSR_XCHG_SRAM_ADDR, status); - if (ret) { - cts_err("Read exchange sram failed %d", ret); - return ret; - } -#undef RDSR_XCHG_SRAM_ADDR - - return 0; -} - -static int wait_flash_wip_clear(const struct cts_device *cts_dev) -{ -#define FLASH_SR_WIP BIT(0) /*!< Write in progress */ - - int ret, retries = 0; - u8 status; - - do { - ret = sfctrlv2_rdsr(cts_dev, &status); - if (ret) { - cts_err("Read flash status register failed %d", ret); - return ret; - } - - if (status & FLASH_SR_WIP) { - mdelay(1); - } else { - return 0; - } - } while (status & FLASH_SR_WIP && retries++ < 1000); - - return -ETIMEDOUT; -#undef FLASH_SR_WIP -} - -static int sfctrlv2_transfer(const struct cts_device *cts_dev, - u8 cmd, void *data, u32 flash_addr, u32 sram_addr, size_t size, u32 flags) -{ - int ret; - - sfctrl_write_reg_check_ret(writeb, rSFCTRLv2_CMD_SEL, cmd); - - if (flags & SFCTRLv2_OPFLAG_SRAM_DATA_XCHG) { - sfctrl_write_reg_check_ret(writel, rSFCTRLv2_SRAM_ADDR, sram_addr); - - /** - Write data to exchange SRAM if operation is write and - * data != NULL(data not in SRAM) */ - if ((!(flags & SFCTRLv2_OPFLAG_READ)) && data) { - ret = cts_sram_writesb(cts_dev, sram_addr, data, size); - if (ret) { - cts_err("Write data to exchange sram 0x%06x size %zu failed %d", - sram_addr, size, ret); - return ret; - } - } - } - - if (flags & SFCTRLv2_OPFLAG_SET_FLASH_ADDR) { - sfctrl_write_reg_check_ret(writel, rSFCTRLv2_FLASH_ADDR, flash_addr); - } - if (flags & SFCTRLv2_OPFLAG_SET_DATA_LENGTH) { - sfctrl_write_reg_check_ret(writel, rSFCTRLv2_DATA_LENGTH, (u32)size); - } - - sfctrl_write_reg_check_ret(writeb, rSFCTRLv2_START_DEXC, 1); - - if((ret = wait_sfctrl_xfer_comp(cts_dev)) != 0) { - cts_err("Wait sfctrl ready failed %d", ret); - return ret; - } - - if (flags & SFCTRLv2_OPFLAG_WAIT_WIP_CLR && - (ret = wait_flash_wip_clear(cts_dev)) != 0) { - cts_err("Wait WIP clear failed %d", ret); - return ret; - } - - if ((flags & SFCTRLv2_OPFLAG_READ) && data) { - ret = cts_sram_readsb(cts_dev, sram_addr, data, size); - if (ret) { - cts_err("Read data from exchange sram 0x%06x size %zu failed %d", - sram_addr, size, ret); - return ret; - } - } - - return 0; -} - -static int sfctrlv2_rdid(const struct cts_device *cts_dev, u32 *id) -{ - int ret; - u8 buf[4]; - - ret = sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_RDID, buf, - 0, cts_dev->hwdata->sfctrl->xchg_sram_base, 3, - SFCTRLv2_CMD_RDID_FLAGS); - *id = ret ? 0 : get_unaligned_be24(buf); - - return ret; -} - -static int sfctrlv2_se(const struct cts_device *cts_dev, u32 sector_addr) -{ - return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_SE, NULL, - sector_addr, 0, 0, SFCTRLv2_CMD_SE_FLAGS); -} - -static int sfctrlv2_be(const struct cts_device *cts_dev, u32 block_addr) -{ - return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_BE, NULL, - block_addr, 0, 0, SFCTRLv2_CMD_BE_FLAGS); -} - -static int sfctrlv2_pp(const struct cts_device *cts_dev, - u32 flash_addr, const void *src, size_t size) -{ - return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_PP, (void *)src, - flash_addr, cts_dev->hwdata->sfctrl->xchg_sram_base, size, - SFCTRLv2_CMD_PP_FLAGS); -} - -static int sfctrlv2_program_flash_from_sram(const struct cts_device *cts_dev, - u32 flash_addr, u32 sram_addr, size_t len) -{ - return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_PP, NULL, - flash_addr, sram_addr, len, SFCTRLv2_CMD_PP_FLAGS); -} - -static int sfctrlv2_read(const struct cts_device *cts_dev, - u32 flash_addr, void *dst, size_t size) -{ - return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_FAST_READ, dst, - flash_addr, cts_dev->hwdata->sfctrl->xchg_sram_base, size, - SFCTRLv2_CMD_FAST_READ_FLAGS); -} - -static int sfctrlv2_read_flash_to_sram(const struct cts_device *cts_dev, - u32 flash_addr, u32 sram_addr, size_t size) -{ - return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_FAST_READ, NULL, - flash_addr, sram_addr, size, SFCTRLv2_CMD_FAST_READ_FLAGS); -} - -int sfctrlv2_calc_sram_crc(const struct cts_device *cts_dev, - u32 sram_addr, size_t size, u32 *crc) -{ - int ret; - - sfctrl_write_reg_check_ret(writel, rSFCTRLv2_SRAM_ADDR, sram_addr); - sfctrl_write_reg_check_ret(writel, rSFCTRLv2_DATA_LENGTH, (u32)size); - sfctrl_write_reg_check_ret(writeb, rSFCTRLv2_SRAM_CRC_START, 1); - - if((ret = wait_sfctrl_xfer_comp(cts_dev)) != 0) { - cts_err("Wait sfctrl ready failed %d", ret); - return ret; - } - - sfctrl_read_reg_check_ret(readl, rSFCTRLv2_CRC_RESULT, crc); - - return 0; -} - -int sfctrlv2_calc_flash_crc(const struct cts_device *cts_dev, - u32 flash_addr, size_t size, u32 *crc) -{ - int ret; - - cts_info("Calc crc from flash 0x%06x size %zu", flash_addr, size); - - sfctrl_write_reg_check_ret(writel, rSFCTRLv2_FLASH_ADDR, flash_addr); - sfctrl_write_reg_check_ret(writel, rSFCTRLv2_DATA_LENGTH, (u32)size); - sfctrl_write_reg_check_ret(writeb, rSFCTRLv2_FLASH_CRC_START, 1); - - if((ret = wait_sfctrl_xfer_comp(cts_dev)) != 0) { - cts_err("Wait sfctrl ready failed %d", ret); - return ret; - } - - sfctrl_read_reg_check_ret(readl, rSFCTRLv2_CRC_RESULT, crc); - - return 0; -} - -const struct cts_sfctrl_ops cts_sfctrlv2_ops = { - .rdid = sfctrlv2_rdid, - .se = sfctrlv2_se, - .be = sfctrlv2_be, - .read = sfctrlv2_read, - .read_to_sram = sfctrlv2_read_flash_to_sram, - .program = sfctrlv2_pp, - .program_from_sram = sfctrlv2_program_flash_from_sram, - .calc_sram_crc = sfctrlv2_calc_sram_crc, - .calc_flash_crc = sfctrlv2_calc_flash_crc, -}; - +#define LOG_TAG "SFCtrl" + +#include "cts_config.h" +#include "cts_platform.h" +#include "cts_core.h" +#include "cts_sfctrl.h" + +#define rSFCTRLv2_CMD_SEL (0x0000) +#define rSFCTRLv2_FLASH_ADDR (0x0004) +#define rSFCTRLv2_SRAM_ADDR (0x0008) +#define rSFCTRLv2_DATA_LENGTH (0x000C) +#define rSFCTRLv2_START_DEXC (0x0010) +#define rSFCTRLv2_RELEASE_FLASH (0x0014) +#define rSFCTRLv2_HW_STATE (0x0018) +#define rSFCTRLv2_CRC_RESULT (0x001C) +#define rSFCTRLv2_SRAM_CRC_START (0x0020) +#define rSFCTRLv2_FLASH_CRC_START (0x0022) +#define rSFCTRLv2_SF_BUSY (0x0024) + +/** Constants for register @ref rSFCTRLv2_CMD_SEL */ +enum sfctrlv2_cmd { + SFCTRLv2_CMD_FAST_READ = 0x01u, + SFCTRLv2_CMD_SE = 0x02u, + SFCTRLv2_CMD_BE = 0x03u, + SFCTRLv2_CMD_PP = 0x04u, + SFCTRLv2_CMD_RDSR = 0x05u, + SFCTRLv2_CMD_RDID = 0x06u +}; + +/** SPI flash controller v2 operation flags. */ +enum sfctrlv2_opflags { + SFCTRLv2_OPFLAG_READ = BIT(0), + SFCTRLv2_OPFLAG_SET_FLASH_ADDR = BIT(1), + SFCTRLv2_OPFLAG_SRAM_DATA_XCHG = BIT(2), + SFCTRLv2_OPFLAG_SET_DATA_LENGTH = BIT(3), + SFCTRLv2_OPFLAG_WAIT_WIP_CLR = BIT(4), + +}; + +#define SFCTRLv2_CMD_RDID_FLAGS \ + (SFCTRLv2_OPFLAG_READ | \ + SFCTRLv2_OPFLAG_SRAM_DATA_XCHG) + +#define SFCTRLv2_CMD_RDSR_FLAGS \ + (SFCTRLv2_OPFLAG_READ | \ + SFCTRLv2_OPFLAG_SRAM_DATA_XCHG) + +#define SFCTRLv2_CMD_SE_FLAGS \ + (SFCTRLv2_OPFLAG_SET_FLASH_ADDR | \ + SFCTRLv2_OPFLAG_WAIT_WIP_CLR) + +#define SFCTRLv2_CMD_BE_FLAGS \ + (SFCTRLv2_OPFLAG_SET_FLASH_ADDR | \ + SFCTRLv2_OPFLAG_WAIT_WIP_CLR) + +#define SFCTRLv2_CMD_PP_FLAGS \ + (SFCTRLv2_OPFLAG_SET_FLASH_ADDR | \ + SFCTRLv2_OPFLAG_SRAM_DATA_XCHG | \ + SFCTRLv2_OPFLAG_SET_DATA_LENGTH | \ + SFCTRLv2_OPFLAG_WAIT_WIP_CLR) + +#define SFCTRLv2_CMD_FAST_READ_FLAGS \ + (SFCTRLv2_OPFLAG_READ | \ + SFCTRLv2_OPFLAG_SET_FLASH_ADDR | \ + SFCTRLv2_OPFLAG_SRAM_DATA_XCHG | \ + SFCTRLv2_OPFLAG_SET_DATA_LENGTH) + +#define sfctrl_reg_addr(cts_dev, offset) \ + ((cts_dev)->hwdata->sfctrl->reg_base + offset) + +#define DEFINE_SFCTRL_REG_ACCESS_FUNC(access_type, data_type) \ + static inline int sfctrl_reg_ ## access_type(const struct cts_device *cts_dev, \ + u32 reg, data_type data) { \ + return cts_hw_reg_ ## access_type(cts_dev, sfctrl_reg_addr(cts_dev, reg), data); \ + } + +DEFINE_SFCTRL_REG_ACCESS_FUNC(writeb_relaxed, u8) + DEFINE_SFCTRL_REG_ACCESS_FUNC(writew_relaxed, u16) + DEFINE_SFCTRL_REG_ACCESS_FUNC(writel_relaxed, u32) + DEFINE_SFCTRL_REG_ACCESS_FUNC(readb_relaxed, u8 *) + DEFINE_SFCTRL_REG_ACCESS_FUNC(readw_relaxed, u16 *) + DEFINE_SFCTRL_REG_ACCESS_FUNC(readl_relaxed, u32 *) +#define sfctrl_write_reg_check_ret(access_type, reg, val) \ + do { \ + int ret; \ + cts_dbg("Write " #reg " to 0x%x", val); \ + ret = sfctrl_reg_ ## access_type(cts_dev, reg, val); \ + if (ret) { \ + cts_err("Write " #reg " failed %d", ret); \ + return ret; \ + } \ + } while (0) +#define sfctrl_read_reg_check_ret(access_type, reg, val) \ + do { \ + int ret; \ + cts_dbg("Read " #reg ""); \ + ret = sfctrl_reg_ ## access_type(cts_dev, reg, val); \ + if (ret) { \ + cts_err("Read " #reg " failed %d", ret); \ + return ret; \ + } \ + } while (0) +static int wait_sfctrl_xfer_comp(const struct cts_device *cts_dev) +{ + int retries = 0; + u8 status; + + do { + sfctrl_read_reg_check_ret(readb_relaxed, rSFCTRLv2_SF_BUSY, &status); + if (status == 0) { + return 0; + } + + mdelay(1); + } while (status && retries++ < 1000); + + return -ETIMEDOUT; +} + +static int sfctrlv2_rdsr(const struct cts_device *cts_dev, u8 *status) +{ +#define RDSR_XCHG_SRAM_ADDR (cts_dev->hwdata->sram_size - 1) + + int ret; + + sfctrl_write_reg_check_ret(writeb_relaxed, rSFCTRLv2_CMD_SEL, + SFCTRLv2_CMD_RDSR); + sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_SRAM_ADDR, + RDSR_XCHG_SRAM_ADDR); + sfctrl_write_reg_check_ret(writeb_relaxed, rSFCTRLv2_START_DEXC, 1); + + ret = wait_sfctrl_xfer_comp(cts_dev); + if (ret != 0) { + cts_err("Wait sfctrl ready failed %d", ret); + return ret; + } + + ret = cts_sram_readb(cts_dev, RDSR_XCHG_SRAM_ADDR, status); + if (ret) { + cts_err("Read exchange sram failed %d", ret); + return ret; + } +#undef RDSR_XCHG_SRAM_ADDR + + return 0; +} + +static int wait_flash_wip_clear(const struct cts_device *cts_dev) +{ +#define FLASH_SR_WIP BIT(0) /*!< Write in progress */ + + int ret, retries = 0; + u8 status; + + do { + ret = sfctrlv2_rdsr(cts_dev, &status); + if (ret) { + cts_err("Read flash status register failed %d", ret); + return ret; + } + + if (status & FLASH_SR_WIP) { + mdelay(1); + } else { + return 0; + } + } while (status & FLASH_SR_WIP && retries++ < 1000); + + return -ETIMEDOUT; +#undef FLASH_SR_WIP +} + +static int sfctrlv2_transfer(const struct cts_device *cts_dev, + u8 cmd, void *data, u32 flash_addr, u32 sram_addr, + size_t size, u32 flags) +{ + int ret; + + sfctrl_write_reg_check_ret(writeb_relaxed, rSFCTRLv2_CMD_SEL, cmd); + + if (flags & SFCTRLv2_OPFLAG_SRAM_DATA_XCHG) { + sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_SRAM_ADDR, + sram_addr); + + /** - Write data to exchange SRAM if operation is write and + * data != NULL(data not in SRAM) */ + if ((!(flags & SFCTRLv2_OPFLAG_READ)) && data) { + ret = cts_sram_writesb(cts_dev, sram_addr, data, size); + if (ret) { + cts_err + ("Write data to exchange sram 0x%06x size %zu failed %d", + sram_addr, size, ret); + return ret; + } + } + } + + if (flags & SFCTRLv2_OPFLAG_SET_FLASH_ADDR) { + sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_FLASH_ADDR, + flash_addr); + } + if (flags & SFCTRLv2_OPFLAG_SET_DATA_LENGTH) { + sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_DATA_LENGTH, + (u32) size); + } + + sfctrl_write_reg_check_ret(writeb_relaxed, rSFCTRLv2_START_DEXC, 1); + + ret = wait_sfctrl_xfer_comp(cts_dev); + if (ret != 0) { + cts_err("Wait sfctrl ready failed %d", ret); + return ret; + } + + ret = wait_flash_wip_clear(cts_dev); + if (flags & SFCTRLv2_OPFLAG_WAIT_WIP_CLR && ret != 0) { + cts_err("Wait WIP clear failed %d", ret); + return ret; + } + + if ((flags & SFCTRLv2_OPFLAG_READ) && data) { + ret = cts_sram_readsb(cts_dev, sram_addr, data, size); + if (ret) { + cts_err + ("Read data from exchange sram 0x%06x size %zu failed %d", + sram_addr, size, ret); + return ret; + } + } + + return 0; +} + +static int sfctrlv2_rdid(const struct cts_device *cts_dev, u32 *id) +{ + int ret; + u8 buf[4]; + + ret = sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_RDID, buf, + 0, cts_dev->hwdata->sfctrl->xchg_sram_base, 3, + SFCTRLv2_CMD_RDID_FLAGS); + *id = ret ? 0 : get_unaligned_be24(buf); + + return ret; +} + +static int sfctrlv2_se(const struct cts_device *cts_dev, u32 sector_addr) +{ + return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_SE, NULL, + sector_addr, 0, 0, SFCTRLv2_CMD_SE_FLAGS); +} + +static int sfctrlv2_be(const struct cts_device *cts_dev, u32 block_addr) +{ + return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_BE, NULL, + block_addr, 0, 0, SFCTRLv2_CMD_BE_FLAGS); +} + +static int sfctrlv2_pp(const struct cts_device *cts_dev, + u32 flash_addr, const void *src, size_t size) +{ + return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_PP, (void *)src, + flash_addr, + cts_dev->hwdata->sfctrl->xchg_sram_base, size, + SFCTRLv2_CMD_PP_FLAGS); +} + +static int sfctrlv2_program_flash_from_sram(const struct cts_device *cts_dev, + u32 flash_addr, u32 sram_addr, + size_t len) +{ + return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_PP, NULL, + flash_addr, sram_addr, len, + SFCTRLv2_CMD_PP_FLAGS); +} + +static int sfctrlv2_read(const struct cts_device *cts_dev, + u32 flash_addr, void *dst, size_t size) +{ + return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_FAST_READ, dst, + flash_addr, + cts_dev->hwdata->sfctrl->xchg_sram_base, size, + SFCTRLv2_CMD_FAST_READ_FLAGS); +} + +static int sfctrlv2_read_flash_to_sram(const struct cts_device *cts_dev, + u32 flash_addr, u32 sram_addr, + size_t size) +{ + return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_FAST_READ, NULL, + flash_addr, sram_addr, size, + SFCTRLv2_CMD_FAST_READ_FLAGS); +} + +int sfctrlv2_calc_sram_crc(const struct cts_device *cts_dev, + u32 sram_addr, size_t size, u32 *crc) +{ + int ret; + + sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_SRAM_ADDR, sram_addr); + sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_DATA_LENGTH, (u32) size); + sfctrl_write_reg_check_ret(writeb_relaxed, rSFCTRLv2_SRAM_CRC_START, 1); + + ret = wait_sfctrl_xfer_comp(cts_dev); + if (ret != 0) { + cts_err("Wait sfctrl ready failed %d", ret); + return ret; + } + + sfctrl_read_reg_check_ret(readl_relaxed, rSFCTRLv2_CRC_RESULT, crc); + + return 0; +} + +int sfctrlv2_calc_flash_crc(const struct cts_device *cts_dev, + u32 flash_addr, size_t size, u32 *crc) +{ + int ret; + + cts_info("Calc crc from flash 0x%06x size %zu", flash_addr, size); + + sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_FLASH_ADDR, flash_addr); + sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_DATA_LENGTH, (u32) size); + sfctrl_write_reg_check_ret(writeb_relaxed, rSFCTRLv2_FLASH_CRC_START, 1); + + ret = wait_sfctrl_xfer_comp(cts_dev); + if (ret != 0) { + cts_err("Wait sfctrl ready failed %d", ret); + return ret; + } + + sfctrl_read_reg_check_ret(readl_relaxed, rSFCTRLv2_CRC_RESULT, crc); + + return 0; +} + +const struct cts_sfctrl_ops cts_sfctrlv2_ops = { + .rdid = sfctrlv2_rdid, + .se = sfctrlv2_se, + .be = sfctrlv2_be, + .read = sfctrlv2_read, + .read_to_sram = sfctrlv2_read_flash_to_sram, + .program = sfctrlv2_pp, + .program_from_sram = sfctrlv2_program_flash_from_sram, + .calc_sram_crc = sfctrlv2_calc_sram_crc, + .calc_flash_crc = sfctrlv2_calc_flash_crc, +}; diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_spi_flash.c b/drivers/input/touchscreen/chipone_tddi_mmi/cts_spi_flash.c old mode 100755 new mode 100644 index 3d29f8a9cf29..125d7983eff9 --- a/drivers/input/touchscreen/chipone_tddi_mmi/cts_spi_flash.c +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_spi_flash.c @@ -1,597 +1,620 @@ -#define LOG_TAG "Flash" - -#include "cts_config.h" -#include "cts_platform.h" -#include "cts_core.h" -#include "cts_sfctrl.h" -#include "cts_spi_flash.h" - -/* NOTE: double check command sets and memory organization when you add - * more flash chips. This current list focusses on newer chips, which - * have been converging on command sets which including JEDEC ID. - */ -static const struct cts_flash cts_flashes[] = { - /* Winbond */ - { "W25Q10EW", 0xEF6011, 256, 0x1000, 0x8000, 0x20000}, - { "W25Q20EW", 0xEF6012, 256, 0x1000, 0x8000, 0x40000}, - { "W25Q40EW", 0xEF6013, 256, 0x1000, 0x8000, 0x80000}, - { "W25Q20BW", 0xEF5012, 256, 0x1000, 0x8000, 0x40000}, - { "W25Q40BW", 0xEF5013, 256, 0x1000, 0x8000, 0x80000}, - - /* Giga device */ - { "GD25LQ10B", 0xC86011, 256, 0x1000, 0x8000, 0x20000}, - { "GD25LD20CEIGR", 0xC86012, 256, 0x1000, 0x8000, 0x40000}, - { "GD25LD40CEIGR", 0xC86013, 256, 0x1000, 0x8000, 0x80000}, - - /* Macronix */ - { "MX25U1001E", 0xC22531, 32, 0x1000, 0x10000, 0x20000}, - { "MX25R2035F", 0xC22812, 256, 0x1000, 0x8000, 0x40000}, - - /* Puya-Semi */ - { "P25Q20LUVHIR", 0x856012, 256, 0x1000, 0x8000, 0x40000}, - { "P25Q40LUXHIR", 0x856013, 256, 0x1000, 0x8000, 0x80000}, - { "P25Q11L", 0x854011, 256, 0x1000, 0x8000, 0x20000}, - { "P25Q21L", 0x854012, 256, 0x1000, 0x8000, 0x40000}, - - /* Boya */ - { "BY25D10", 0x684011, 256, 0x1000, 0x8000, 0x20000}, - - /* EON */ - { "EN25S20A", 0x1C3812, 256, 0x1000, 0x8000, 0x40000}, - - /* XTXTECH */ - { "XT25Q01", 0x0B6011, 256, 0x1000, 0, 0x20000}, - { "XT25Q02", 0x0B6012, 256, 0x1000, 0, 0x40000}, - - /* Xinxin-Semi */ - { "XM25QU20B", 0x205012, 256, 0x1000, 0x8000, 0x40000}, - { "XM25QU40B", 0x205013, 256, 0x1000, 0x8000, 0x80000}, -}; - -static const struct cts_flash *find_flash_by_jedec_id(u32 jedec_id) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(cts_flashes); i++) { - if (cts_flashes[i].jedec_id == jedec_id) { - return &cts_flashes[i]; - } - } - - return NULL; -} - -static int probe_flash(struct cts_device *cts_dev) -{ - int ret; - - cts_info("Probe flash"); - - if (cts_dev->hwdata->sfctrl->ops->rdid != NULL) { - u32 id; - - cts_info("Read JEDEC ID"); - - ret = cts_dev->hwdata->sfctrl->ops->rdid(cts_dev, &id); - if (ret) { - cts_err("Read JEDEC ID failed %d", ret); - return ret; - } - - cts_dev->flash = find_flash_by_jedec_id(id); - if (cts_dev->flash == NULL) { - cts_err("Unknown JEDEC ID: %06x", id); - return -ENODEV; - } - - cts_info("Flash type: '%s'", cts_dev->flash->name); - return 0; - } else { - cts_err("Probe flash while rdid == NULL"); - return -ENOTSUPP; - } -} - -/** Make sure sector addr is sector aligned && < flash total size */ -static int erase_sector_retry(const struct cts_device *cts_dev, - u32 sector_addr, int retry) -{ - int ret, retries; - - cts_info(" Erase sector 0x%06x", sector_addr); - - retries = 0; - do { - retries++; - ret = cts_dev->hwdata->sfctrl->ops->se(cts_dev, sector_addr); - if (ret) { - cts_err("Erase sector 0x%06x failed %d retries %d", - sector_addr, ret, retries); - continue; - } - } while (retries < retry); - - return ret; -} - -/** Make sure sector addr is sector aligned && < flash total size */ -static inline int erase_sector(const struct cts_device *cts_dev, - u32 sector_addr) -{ - return erase_sector_retry(cts_dev, sector_addr, CTS_FLASH_ERASE_DEFAULT_RETRY); -} - -/** Make sure block addr is block aligned && < flash total size */ -static int erase_block_retry(const struct cts_device *cts_dev, - u32 block_addr, int retry) -{ - int ret, retries; - - cts_info(" Erase block 0x%06x", block_addr); - - retries = 0; - do { - retries++; - - ret = cts_dev->hwdata->sfctrl->ops->be(cts_dev, block_addr); - if (ret) { - cts_err("Erase block 0x%06x failed %d retries %d", - block_addr, ret, retries); - continue; - } - } while (retries < retry); - - return ret; -} - -/** Make sure block addr is block aligned && < flash total size */ -static inline int erase_block(const struct cts_device *cts_dev, - u32 block_addr) -{ - return erase_block_retry(cts_dev, block_addr, CTS_FLASH_ERASE_DEFAULT_RETRY); -} - -int cts_prepare_flash_operation(struct cts_device *cts_dev) -{ - int ret; - u8 diva = 0; - bool program_mode = cts_is_device_program_mode(cts_dev); - bool enabled = cts_is_device_enabled(cts_dev); - - cts_info("Prepare for flash operation"); - - if (enabled) { - ret = cts_stop_device(cts_dev); - if (ret) { - cts_err("Stop device failed %d", ret); - return ret; - } - } - - if (!program_mode) { - ret = cts_enter_program_mode(cts_dev); - if (ret) { - cts_err("Enter program mode failed %d", ret); - goto err_start_device; - } - } - - ret = cts_hw_reg_readb_retry(cts_dev, 0x30033, &diva, 5, 0); - if (ret) { - cts_warn("Read DIVA failed %d", ret); - } else { - cts_dbg("Device DIVA = %d", diva); - } - - if (ret == 0 && diva == 0x0C) { - cts_info("DIVA is ready already"); - } else { - int retries; - - /* Set HCLK to 10MHz */ - ret = cts_hw_reg_writeb_retry(cts_dev, 0x30033, 0x0C, 5, 0); - if (ret) { - cts_err("Write DIVA failed %d", ret); - goto err_enter_normal_mode; - } - - /* Reset SFCTL */ - ret = cts_hw_reg_writeb_retry(cts_dev, 0x30008, 0xFB, 5, 0); - if (ret) { - cts_err("Reset sfctl failed %d", ret); - goto err_enter_normal_mode; - } - - retries = 0; - do { - u8 state; - - ret = cts_hw_reg_readb(cts_dev, 0x3401B, &state); - if (ret == 0 && (state & 0x40) != 0) { - goto init_flash; - } - - mdelay(2); - } while(++retries < 1000); - - cts_warn("Wait SFCTRL ready failed %d", ret); - // Go through and try - } - -init_flash: - if (cts_dev->flash == NULL) { - cts_info("Flash is not initialized, try to probe..."); - if ((ret = probe_flash(cts_dev)) != 0) { - cts_dev->rtdata.has_flash = false; - cts_warn("Probe flash failed %d", ret); - //dzy goto err_enter_normal_mode; - return 0; - } - } - cts_dev->rtdata.has_flash = true; - return 0; - -err_enter_normal_mode: - if (!program_mode) { - int r = cts_enter_normal_mode(cts_dev); - if (r) { - cts_err("Enter normal mode failed %d", r); - } - } -err_start_device: - if (enabled) { - int r = cts_start_device(cts_dev); - if (r) { - cts_err("Start device failed %d", r); - } - } - - return ret; -} - -int cts_post_flash_operation(struct cts_device *cts_dev) -{ - cts_info("Post flash operation"); - - return cts_hw_reg_writeb_retry(cts_dev, 0x30033, 4, 5, 0); -} - -int cts_read_flash_retry(const struct cts_device *cts_dev, - u32 flash_addr, void *dst, size_t size, int retry) -{ - const struct cts_sfctrl *sfctrl; - const struct cts_flash *flash; - int ret; - - cts_info("Read from 0x%06x size %zu", flash_addr, size); - - sfctrl = cts_dev->hwdata->sfctrl; - flash = cts_dev->flash; - - if (flash == NULL || - sfctrl == NULL || - sfctrl->ops == NULL || - sfctrl->ops->read == NULL) { - cts_err("Read not supported"); - return -ENOTSUPP; - } - - if (flash_addr > flash->total_size) { - cts_err("Read from 0x%06x > flash size 0x%06zx", - flash_addr, flash->total_size); - return -EINVAL; - } - size = min(size, flash->total_size - flash_addr); - - cts_info("Read actually from 0x%06x size %zu", flash_addr, size); - - while (size) { - size_t l; - - l = min(sfctrl->xchg_sram_size, size); - - ret = sfctrl->ops->read(cts_dev, flash_addr, dst, l); - if(ret < 0) { - cts_err("Read from 0x%06x size %zu failed %d", - flash_addr, size, ret); - return ret; - } - - dst += l; - size -= l; - flash_addr += l; - } - - return 0; -} - -int cts_read_flash_to_sram_retry(const struct cts_device *cts_dev, - u32 flash_addr, u32 sram_addr, size_t size, int retry) -{ - const struct cts_sfctrl *sfctrl; - const struct cts_flash *flash; - int ret, retries; - - cts_info("Read from 0x%06x to sram 0x%06x size %zu", - flash_addr, sram_addr, size); - - sfctrl = cts_dev->hwdata->sfctrl; - flash = cts_dev->flash; - - if (flash == NULL || - sfctrl == NULL || - sfctrl->ops == NULL || - sfctrl->ops->read_to_sram == NULL) { - cts_err("Read to sram not supported"); - return -ENOTSUPP; - } - - if (flash_addr > flash->total_size) { - cts_err("Read to sram from 0x%06x > flash size 0x%06zx", - flash_addr, flash->total_size); - return -EINVAL; - } - size = min(size, flash->total_size - flash_addr); - - cts_info("Read to sram actually from 0x%06x size %zu", flash_addr, size); - - retries = 0; - do { - retries++; - ret = sfctrl->ops->read_to_sram(cts_dev, flash_addr, sram_addr, size); - if(ret) { - cts_err("Read from 0x%06x to sram 0x%06x size %zu failed %d retries %d", - flash_addr, sram_addr, size, ret, retries); - continue; - } - } while (retries < retry); - - return ret; -} - -int cts_read_flash_to_sram_check_crc_retry(const struct cts_device *cts_dev, - u32 flash_addr, u32 sram_addr, size_t size, u32 crc, int retry) -{ - const struct cts_sfctrl *sfctrl; - const struct cts_flash *flash; - int ret, retries; - - cts_info("Read from 0x%06x to sram 0x%06x size %zu with crc check", - flash_addr, sram_addr, size); - - sfctrl = cts_dev->hwdata->sfctrl; - flash = cts_dev->flash; - - if (flash == NULL || - sfctrl == NULL || - sfctrl->ops == NULL || - sfctrl->ops->read_to_sram == NULL || - sfctrl->ops->calc_sram_crc == NULL) { - cts_err("Read to sram check crc not supported"); - return -ENOTSUPP; - } - - if (flash_addr > flash->total_size) { - cts_err("Read to sram from 0x%06x > flash size 0x%06zx", - flash_addr, flash->total_size); - return -EINVAL; - } - size = min(size, flash->total_size - flash_addr); - - cts_info("Read to sram actually from 0x%06x size %zu with crc check", - flash_addr, size); - - retries = 0; - do { - u32 crc_sram; - - retries++; - - ret = sfctrl->ops->read_to_sram(cts_dev, flash_addr, sram_addr, size); - if(ret) { - cts_err("Read from 0x%06x to sram 0x%06x size %zu failed %d retries %d", - flash_addr, sram_addr, size, ret, retries); - continue; - } - - ret = sfctrl->ops->calc_sram_crc(cts_dev, sram_addr, size, &crc_sram); - if (ret) { - cts_err("Get crc for read from 0x%06x to sram 0x%06x size %zu " - "failed %d retries %d", - flash_addr, sram_addr, size, ret, retries); - continue; - } - - if (crc == crc_sram) { - return 0; - } - - cts_err("Check crc for read from 0x%06x to sram 0x%06x size %zu " - "mismatch %x != %x, retries %d", - flash_addr, sram_addr, size, crc, crc_sram, retries); - ret = -EFAULT; - } while (retries < retry); - - return ret; -} - -int cts_program_flash(const struct cts_device *cts_dev, - u32 flash_addr, const void *src, size_t size) -{ - const struct cts_sfctrl *sfctrl; - const struct cts_flash *flash; - int ret; - - cts_info("Program to 0x%06x size %zu", flash_addr, size); - - sfctrl = cts_dev->hwdata->sfctrl; - flash = cts_dev->flash; - - if (flash == NULL || - sfctrl == NULL || - sfctrl->ops == NULL || - sfctrl->ops->program == NULL) { - cts_err("Program not supported"); - return -ENOTSUPP; - } - - if (flash_addr >= flash->total_size) { - cts_err("Program from 0x%06x >= flash size 0x%06zx", - flash_addr, flash->total_size); - return -EINVAL; - } - size = min(size, flash->total_size - flash_addr); - - cts_info("Program actually to 0x%06x size %zu", flash_addr, size); - - while (size) { - size_t l, offset; - - l = min(flash->page_size, size); - offset = flash_addr & (flash->page_size - 1); - - if (offset) { - l = min(flash->page_size - offset, l); - } - - ret = sfctrl->ops->program(cts_dev, flash_addr, src, l); - if(ret) { - cts_err("Program to 0x%06x size %zu failed %d", flash_addr, l, ret); - return ret; - } - - src += l; - size -= l; - flash_addr += l; - } - - return 0; -} - -int cts_program_flash_from_sram(const struct cts_device *cts_dev, - u32 flash_addr, u32 sram_addr, size_t size) -{ - const struct cts_sfctrl *sfctrl; - const struct cts_flash *flash; - int ret; - - cts_info("Program to 0x%06x from sram 0x%06x size %zu", - flash_addr, sram_addr, size); - - sfctrl = cts_dev->hwdata->sfctrl; - flash = cts_dev->flash; - - if (flash == NULL || - sfctrl == NULL || - sfctrl->ops == NULL || - sfctrl->ops->program_from_sram == NULL) { - cts_err("Program from sram not supported"); - return -ENOTSUPP; - } - - if (flash_addr >= flash->total_size) { - cts_err("Program from 0x%06x >= flash size 0x%06zx", - flash_addr, flash->total_size); - return -EINVAL; - } - size = min(size, flash->total_size - flash_addr); - - cts_info("Program actually to 0x%06x from sram 0x%06x size %zu", - flash_addr, sram_addr, size); - - while (size) { - size_t l, offset; - - l = min(flash->page_size, size); - offset = flash_addr & (flash->page_size - 1); - - if (offset) { - l = min(flash->page_size - offset, l); - } - - ret = sfctrl->ops->program_from_sram(cts_dev, flash_addr, sram_addr, l); - if(ret) { - cts_err("Program to 0x%06x from sram 0x%06x size %zu failed %d", - flash_addr, sram_addr, l, ret); - return ret; - } - - size -= l; - flash_addr += l; - sram_addr += l; - } - - return 0; -} - -int cts_erase_flash(const struct cts_device *cts_dev, u32 addr, size_t size) -{ - const struct cts_sfctrl *sfctrl; - const struct cts_flash *flash; - int ret; - - cts_info("Erase from 0x%06x size %zu", addr, size); - - sfctrl = cts_dev->hwdata->sfctrl; - flash = cts_dev->flash; - - if (flash == NULL || - sfctrl == NULL || sfctrl->ops == NULL || - sfctrl->ops->se == NULL || sfctrl->ops->be == NULL || - flash == NULL) { - cts_err("Oops"); - return -EINVAL; - } - - /* Addr and size MUST sector aligned */ - addr = rounddown(addr, flash->sector_size); - size = roundup(size, flash->sector_size); - - if (addr > flash->total_size) { - cts_err("Erase from 0x%06x > flash size 0x%06zx", - addr, flash->total_size); - return -EINVAL; - } - size = min(size, flash->total_size - addr); - - cts_info("Erase actually from 0x%06x size %zu", addr, size); - - if (flash->block_size) { - while (addr != ALIGN(addr, flash->block_size) && - size >= flash->sector_size) { - ret = erase_sector(cts_dev, addr); - if (ret) { - cts_err("Erase sector 0x%06x size 0x%04zx failed %d", - addr, flash->sector_size, ret); - return ret; - } - addr += flash->sector_size; - size -= flash->sector_size; - } - - while (size >= flash->block_size) { - ret = erase_block(cts_dev, addr); - if (ret) { - cts_err("Erase block 0x%06x size 0x%04zx failed %d", - addr, flash->block_size, ret); - return ret; - } - addr += flash->block_size; - size -= flash->block_size; - } - } - - while (size >= flash->sector_size) { - ret = erase_sector(cts_dev, addr); - if (ret) { - cts_err("Erase sector 0x%06x size 0x%04zx failed %d", - addr, flash->sector_size, ret); - return ret; - } - addr += flash->sector_size; - size -= flash->sector_size; - } - - return 0; -} - +#define LOG_TAG "Flash" + +#include "cts_config.h" +#include "cts_platform.h" +#include "cts_core.h" +#include "cts_sfctrl.h" +#include "cts_spi_flash.h" + +/* NOTE: double check command sets and memory organization when you add + * more flash chips. This current list focusses on newer chips, which + * have been converging on command sets which including JEDEC ID. + */ + #if 0 +static const struct cts_flash cts_flashes[] = { + /* Winbond */ + {"W25Q10EW", 0xEF6011, 256, 0x1000, 0x8000, 0x20000}, + {"W25Q20EW", 0xEF6012, 256, 0x1000, 0x8000, 0x40000}, + {"W25Q40EW", 0xEF6013, 256, 0x1000, 0x8000, 0x80000}, + {"W25Q20BW", 0xEF5012, 256, 0x1000, 0x8000, 0x40000}, + {"W25Q40BW", 0xEF5013, 256, 0x1000, 0x8000, 0x80000}, + + /* Giga device */ + {"GD25LQ10B", 0xC86011, 256, 0x1000, 0x8000, 0x20000}, + {"GD25LD20CEIGR", 0xC86012, 256, 0x1000, 0x8000, 0x40000}, + {"GD25LD40CEIGR", 0xC86013, 256, 0x1000, 0x8000, 0x80000}, + + /* Macronix */ + {"MX25U1001E", 0xC22531, 32, 0x1000, 0x10000, 0x20000}, + {"MX25R2035F", 0xC22812, 256, 0x1000, 0x8000, 0x40000}, + + /* Puya-Semi */ + {"P25Q20LUVHIR", 0x856012, 256, 0x1000, 0x8000, 0x40000}, + {"P25Q40LUXHIR", 0x856013, 256, 0x1000, 0x8000, 0x80000}, + {"P25Q11L", 0x854011, 256, 0x1000, 0x8000, 0x20000}, + {"P25Q21L", 0x854012, 256, 0x1000, 0x8000, 0x40000}, + + /* Boya */ + {"BY25D10", 0x684011, 256, 0x1000, 0x8000, 0x20000}, + + /* EON */ + {"EN25S20A", 0x1C3812, 256, 0x1000, 0x8000, 0x40000}, + + /* XTXTECH */ + {"XT25Q01", 0x0B6011, 256, 0x1000, 0, 0x20000}, + {"XT25Q02", 0x0B6012, 256, 0x1000, 0, 0x40000}, + + /* Xinxin-Semi */ + {"XM25QU20B", 0x205012, 256, 0x1000, 0x8000, 0x40000}, + {"XM25QU40B", 0x205013, 256, 0x1000, 0x8000, 0x80000}, +}; +#endif +/* +static const struct cts_flash *find_flash_by_jedec_id(u32 jedec_id) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(cts_flashes); i++) { + if (cts_flashes[i].jedec_id == jedec_id) { + return &cts_flashes[i]; + } + } + + return NULL; +} +*/ +static int probe_flash(struct cts_device *cts_dev) +{ + //for no-flash project + return -ENODEV; + + /* + int ret; + + cts_info("Probe flash"); + + if (cts_dev->hwdata->sfctrl->ops->rdid != NULL) { + u32 id; + + cts_info("Read JEDEC ID"); + + ret = cts_dev->hwdata->sfctrl->ops->rdid(cts_dev, &id); + if (ret) { + cts_err("Read JEDEC ID failed %d", ret); + return ret; + } + + cts_dev->flash = find_flash_by_jedec_id(id); + if (cts_dev->flash == NULL) { + cts_err("Unknown JEDEC ID: %06x", id); + return -ENODEV; + } + + cts_info("Flash type: '%s'", cts_dev->flash->name); + return 0; + } else { + cts_err("Probe flash while rdid == NULL"); + return -ENOTSUPP; + } + */ +} + +/** Make sure sector addr is sector aligned && < flash total size */ +static int erase_sector_retry(const struct cts_device *cts_dev, + u32 sector_addr, int retry) +{ + int ret, retries; + + cts_info(" Erase sector 0x%06x", sector_addr); + + retries = 0; + do { + retries++; + ret = cts_dev->hwdata->sfctrl->ops->se(cts_dev, sector_addr); + if (ret) { + cts_err("Erase sector 0x%06x failed %d retries %d", + sector_addr, ret, retries); + continue; + } + } while (retries < retry); + + return ret; +} + +/** Make sure sector addr is sector aligned && < flash total size */ +static inline int erase_sector(const struct cts_device *cts_dev, + u32 sector_addr) +{ + return erase_sector_retry(cts_dev, sector_addr, + CTS_FLASH_ERASE_DEFAULT_RETRY); +} + +/** Make sure block addr is block aligned && < flash total size */ +static int erase_block_retry(const struct cts_device *cts_dev, + u32 block_addr, int retry) +{ + int ret, retries; + + cts_info(" Erase block 0x%06x", block_addr); + + retries = 0; + do { + retries++; + + ret = cts_dev->hwdata->sfctrl->ops->be(cts_dev, block_addr); + if (ret) { + cts_err("Erase block 0x%06x failed %d retries %d", + block_addr, ret, retries); + continue; + } + } while (retries < retry); + + return ret; +} + +/** Make sure block addr is block aligned && < flash total size */ +static inline int erase_block(const struct cts_device *cts_dev, u32 block_addr) +{ + return erase_block_retry(cts_dev, block_addr, + CTS_FLASH_ERASE_DEFAULT_RETRY); +} + +int cts_prepare_flash_operation(struct cts_device *cts_dev) +{ + int ret; + u8 diva = 0; + bool program_mode = cts_is_device_program_mode(cts_dev); + bool enabled = cts_is_device_enabled(cts_dev); + + cts_info("Prepare for flash operation"); + + if (enabled) { + ret = cts_stop_device(cts_dev); + if (ret) { + cts_err("Stop device failed %d", ret); + return ret; + } + } + + if (!program_mode) { + ret = cts_enter_program_mode(cts_dev); + if (ret) { + cts_err("Enter program mode failed %d", ret); + goto err_start_device; + } + } + + ret = cts_hw_reg_readb_retry(cts_dev, 0x30033, &diva, 5, 0); + if (ret) { + cts_warn("Read DIVA failed %d", ret); + } else { + cts_dbg("Device DIVA = %d", diva); + } + + if (ret == 0 && diva == 0x0C) { + cts_info("DIVA is ready already"); + } else { + int retries; + + /* Set HCLK to 10MHz */ + ret = cts_hw_reg_writeb_retry(cts_dev, 0x30033, 0x0C, 5, 0); + if (ret) { + cts_err("Write DIVA failed %d", ret); + goto err_enter_normal_mode; + } + + /* Reset SFCTL */ + ret = cts_hw_reg_writeb_retry(cts_dev, 0x30008, 0xFB, 5, 0); + if (ret) { + cts_err("Reset sfctl failed %d", ret); + goto err_enter_normal_mode; + } + + retries = 0; + do { + u8 state; + + ret = cts_hw_reg_readb_relaxed(cts_dev, 0x3401B, &state); + if (ret == 0 && (state & 0x40) != 0) { + goto init_flash; + } + + mdelay(2); + } while (++retries < 1000); + + cts_warn("Wait SFCTRL ready failed %d", ret); + // Go through and try + } + +init_flash: + if (cts_dev->flash == NULL) { + cts_info("Flash is not initialized, try to probe..."); + ret = probe_flash(cts_dev); + if (ret != 0) { + cts_dev->rtdata.has_flash = false; + cts_warn("Probe flash failed %d", ret); + //dzy goto err_enter_normal_mode; + return 0; + } + } + cts_dev->rtdata.has_flash = true; + return 0; + +err_enter_normal_mode: + if (!program_mode) { + int r = cts_enter_normal_mode(cts_dev); + if (r) { + cts_err("Enter normal mode failed %d", r); + } + } +err_start_device: + if (enabled) { + int r = cts_start_device(cts_dev); + if (r) { + cts_err("Start device failed %d", r); + } + } + + return ret; +} + +int cts_post_flash_operation(struct cts_device *cts_dev) +{ + cts_info("Post flash operation"); + + return cts_hw_reg_writeb_retry(cts_dev, 0x30033, 4, 5, 0); +} + +int cts_read_flash_retry(const struct cts_device *cts_dev, + u32 flash_addr, void *dst, size_t size, int retry) +{ + const struct cts_sfctrl *sfctrl; + const struct cts_flash *flash; + int ret; + + cts_info("Read from 0x%06x size %zu", flash_addr, size); + + sfctrl = cts_dev->hwdata->sfctrl; + flash = cts_dev->flash; + + if (flash == NULL || + sfctrl == NULL || + sfctrl->ops == NULL || sfctrl->ops->read == NULL) { + cts_err("Read not supported"); + return -ENOTSUPP; + } + + if (flash_addr > flash->total_size) { + cts_err("Read from 0x%06x > flash size 0x%06zx", + flash_addr, flash->total_size); + return -EINVAL; + } + size = min(size, flash->total_size - flash_addr); + + cts_info("Read actually from 0x%06x size %zu", flash_addr, size); + + while (size) { + size_t l; + + l = min(sfctrl->xchg_sram_size, size); + + ret = sfctrl->ops->read(cts_dev, flash_addr, dst, l); + if (ret < 0) { + cts_err("Read from 0x%06x size %zu failed %d", + flash_addr, size, ret); + return ret; + } + + dst += l; + size -= l; + flash_addr += l; + } + + return 0; +} + +int cts_read_flash_to_sram_retry(const struct cts_device *cts_dev, + u32 flash_addr, u32 sram_addr, size_t size, + int retry) +{ + const struct cts_sfctrl *sfctrl; + const struct cts_flash *flash; + int ret, retries; + + cts_info("Read from 0x%06x to sram 0x%06x size %zu", + flash_addr, sram_addr, size); + + sfctrl = cts_dev->hwdata->sfctrl; + flash = cts_dev->flash; + + if (flash == NULL || + sfctrl == NULL || + sfctrl->ops == NULL || sfctrl->ops->read_to_sram == NULL) { + cts_err("Read to sram not supported"); + return -ENOTSUPP; + } + + if (flash_addr > flash->total_size) { + cts_err("Read to sram from 0x%06x > flash size 0x%06zx", + flash_addr, flash->total_size); + return -EINVAL; + } + size = min(size, flash->total_size - flash_addr); + + cts_info("Read to sram actually from 0x%06x size %zu", flash_addr, + size); + + retries = 0; + do { + retries++; + ret = + sfctrl->ops->read_to_sram(cts_dev, flash_addr, sram_addr, + size); + if (ret) { + cts_err + ("Read from 0x%06x to sram 0x%06x size %zu failed %d retries %d", + flash_addr, sram_addr, size, ret, retries); + continue; + } + } while (retries < retry); + + return ret; +} + +int cts_read_flash_to_sram_check_crc_retry(const struct cts_device *cts_dev, + u32 flash_addr, u32 sram_addr, + size_t size, u32 crc, int retry) +{ + const struct cts_sfctrl *sfctrl; + const struct cts_flash *flash; + int ret, retries; + + cts_info("Read from 0x%06x to sram 0x%06x size %zu with crc check", + flash_addr, sram_addr, size); + + sfctrl = cts_dev->hwdata->sfctrl; + flash = cts_dev->flash; + + if (flash == NULL || + sfctrl == NULL || + sfctrl->ops == NULL || + sfctrl->ops->read_to_sram == NULL || + sfctrl->ops->calc_sram_crc == NULL) { + cts_err("Read to sram check crc not supported"); + return -ENOTSUPP; + } + + if (flash_addr > flash->total_size) { + cts_err("Read to sram from 0x%06x > flash size 0x%06zx", + flash_addr, flash->total_size); + return -EINVAL; + } + size = min(size, flash->total_size - flash_addr); + + cts_info("Read to sram actually from 0x%06x size %zu with crc check", + flash_addr, size); + + retries = 0; + do { + u32 crc_sram; + + retries++; + + ret = + sfctrl->ops->read_to_sram(cts_dev, flash_addr, sram_addr, + size); + if (ret) { + cts_err + ("Read from 0x%06x to sram 0x%06x size %zu failed %d retries %d", + flash_addr, sram_addr, size, ret, retries); + continue; + } + + ret = + sfctrl->ops->calc_sram_crc(cts_dev, sram_addr, size, + &crc_sram); + if (ret) { + cts_err + ("Get crc for read from 0x%06x to sram 0x%06x size %zu " + "failed %d retries %d", flash_addr, sram_addr, + size, ret, retries); + continue; + } + + if (crc == crc_sram) { + return 0; + } + + cts_err + ("Check crc for read from 0x%06x to sram 0x%06x size %zu " + "mismatch %x != %x, retries %d", flash_addr, sram_addr, + size, crc, crc_sram, retries); + ret = -EFAULT; + } while (retries < retry); + + return ret; +} + +int cts_program_flash(const struct cts_device *cts_dev, + u32 flash_addr, const void *src, size_t size) +{ + const struct cts_sfctrl *sfctrl; + const struct cts_flash *flash; + int ret; + + cts_info("Program to 0x%06x size %zu", flash_addr, size); + + sfctrl = cts_dev->hwdata->sfctrl; + flash = cts_dev->flash; + + if (flash == NULL || + sfctrl == NULL || + sfctrl->ops == NULL || sfctrl->ops->program == NULL) { + cts_err("Program not supported"); + return -ENOTSUPP; + } + + if (flash_addr >= flash->total_size) { + cts_err("Program from 0x%06x >= flash size 0x%06zx", + flash_addr, flash->total_size); + return -EINVAL; + } + size = min(size, flash->total_size - flash_addr); + + cts_info("Program actually to 0x%06x size %zu", flash_addr, size); + + while (size) { + size_t l, offset; + + l = min(flash->page_size, size); + offset = flash_addr & (flash->page_size - 1); + + if (offset) { + l = min(flash->page_size - offset, l); + } + + ret = sfctrl->ops->program(cts_dev, flash_addr, src, l); + if (ret) { + cts_err("Program to 0x%06x size %zu failed %d", + flash_addr, l, ret); + return ret; + } + + src += l; + size -= l; + flash_addr += l; + } + + return 0; +} + +int cts_program_flash_from_sram(const struct cts_device *cts_dev, + u32 flash_addr, u32 sram_addr, size_t size) +{ + const struct cts_sfctrl *sfctrl; + const struct cts_flash *flash; + int ret; + + cts_info("Program to 0x%06x from sram 0x%06x size %zu", + flash_addr, sram_addr, size); + + sfctrl = cts_dev->hwdata->sfctrl; + flash = cts_dev->flash; + + if (flash == NULL || + sfctrl == NULL || + sfctrl->ops == NULL || sfctrl->ops->program_from_sram == NULL) { + cts_err("Program from sram not supported"); + return -ENOTSUPP; + } + + if (flash_addr >= flash->total_size) { + cts_err("Program from 0x%06x >= flash size 0x%06zx", + flash_addr, flash->total_size); + return -EINVAL; + } + size = min(size, flash->total_size - flash_addr); + + cts_info("Program actually to 0x%06x from sram 0x%06x size %zu", + flash_addr, sram_addr, size); + + while (size) { + size_t l, offset; + + l = min(flash->page_size, size); + offset = flash_addr & (flash->page_size - 1); + + if (offset) { + l = min(flash->page_size - offset, l); + } + + ret = + sfctrl->ops->program_from_sram(cts_dev, flash_addr, + sram_addr, l); + if (ret) { + cts_err + ("Program to 0x%06x from sram 0x%06x size %zu failed %d", + flash_addr, sram_addr, l, ret); + return ret; + } + + size -= l; + flash_addr += l; + sram_addr += l; + } + + return 0; +} + +int cts_erase_flash(const struct cts_device *cts_dev, u32 addr, size_t size) +{ + const struct cts_sfctrl *sfctrl; + const struct cts_flash *flash; + int ret; + + cts_info("Erase from 0x%06x size %zu", addr, size); + + sfctrl = cts_dev->hwdata->sfctrl; + flash = cts_dev->flash; + + if (flash == NULL || + sfctrl == NULL || sfctrl->ops == NULL || + sfctrl->ops->se == NULL || sfctrl->ops->be == NULL || + flash == NULL) { + cts_err("Oops"); + return -EINVAL; + } + + /* Addr and size MUST sector aligned */ + addr = rounddown(addr, flash->sector_size); + size = roundup(size, flash->sector_size); + + if (addr > flash->total_size) { + cts_err("Erase from 0x%06x > flash size 0x%06zx", + addr, flash->total_size); + return -EINVAL; + } + size = min(size, flash->total_size - addr); + + cts_info("Erase actually from 0x%06x size %zu", addr, size); + + if (flash->block_size) { + while (addr != ALIGN(addr, flash->block_size) && + size >= flash->sector_size) { + ret = erase_sector(cts_dev, addr); + if (ret) { + cts_err + ("Erase sector 0x%06x size 0x%04zx failed %d", + addr, flash->sector_size, ret); + return ret; + } + addr += flash->sector_size; + size -= flash->sector_size; + } + + while (size >= flash->block_size) { + ret = erase_block(cts_dev, addr); + if (ret) { + cts_err + ("Erase block 0x%06x size 0x%04zx failed %d", + addr, flash->block_size, ret); + return ret; + } + addr += flash->block_size; + size -= flash->block_size; + } + } + + while (size >= flash->sector_size) { + ret = erase_sector(cts_dev, addr); + if (ret) { + cts_err("Erase sector 0x%06x size 0x%04zx failed %d", + addr, flash->sector_size, ret); + return ret; + } + addr += flash->sector_size; + size -= flash->sector_size; + } + + return 0; +} diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_spi_flash.h b/drivers/input/touchscreen/chipone_tddi_mmi/cts_spi_flash.h old mode 100755 new mode 100644 index b98b42a0200b..e610bdcb75ac --- a/drivers/input/touchscreen/chipone_tddi_mmi/cts_spi_flash.h +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_spi_flash.h @@ -2,13 +2,13 @@ #define CTS_SPI_FLASH_H struct cts_flash { - const char *name; - u32 jedec_id; /* Device ID by command 0x9F */ - size_t page_size; /* Page size by command 0x02 */ - size_t sector_size; /* Sector size by command 0x20 */ - size_t block_size; /* Block size by command 0x52, - if 0 means block erase NOT supported */ - size_t total_size; + const char *name; + u32 jedec_id; /* Device ID by command 0x9F */ + size_t page_size; /* Page size by command 0x02 */ + size_t sector_size; /* Sector size by command 0x20 */ + size_t block_size; /* Block size by command 0x52, + if 0 means block erase NOT supported */ + size_t total_size; }; @@ -21,38 +21,50 @@ extern int cts_prepare_flash_operation(struct cts_device *cts_dev); extern int cts_post_flash_operation(struct cts_device *cts_dev); extern int cts_read_flash_retry(const struct cts_device *cts_dev, - u32 flash_addr, void *dst, size_t size, int retry); + u32 flash_addr, void *dst, size_t size, + int retry); static inline int cts_read_flash(const struct cts_device *cts_dev, - u32 flash_addr, void *dst, size_t size) + u32 flash_addr, void *dst, size_t size) { - return cts_read_flash_retry(cts_dev, - flash_addr, dst, size, CTS_FLASH_READ_DEFAULT_RETRY); + return cts_read_flash_retry(cts_dev, + flash_addr, dst, size, + CTS_FLASH_READ_DEFAULT_RETRY); } extern int cts_read_flash_to_sram_retry(const struct cts_device *cts_dev, - u32 flash_addr, u32 sram_addr, size_t size, int retry); + u32 flash_addr, u32 sram_addr, + size_t size, int retry); static inline int cts_read_flash_to_sram(const struct cts_device *cts_dev, - u32 flash_addr, u32 sram_addr, size_t size) + u32 flash_addr, u32 sram_addr, + size_t size) { - return cts_read_flash_to_sram_retry(cts_dev, - flash_addr, sram_addr, size, CTS_FLASH_READ_DEFAULT_RETRY); + return cts_read_flash_to_sram_retry(cts_dev, + flash_addr, sram_addr, size, + CTS_FLASH_READ_DEFAULT_RETRY); } -extern int cts_read_flash_to_sram_check_crc_retry(const struct cts_device *cts_dev, - u32 flash_addr, u32 sram_addr, size_t size, u32 crc, int retry); -static inline int cts_read_flash_to_sram_check_crc(const struct cts_device *cts_dev, - u32 flash_addr, u32 sram_addr, size_t size, u32 crc) +extern int cts_read_flash_to_sram_check_crc_retry(const struct cts_device + *cts_dev, u32 flash_addr, + u32 sram_addr, size_t size, + u32 crc, int retry); +static inline int cts_read_flash_to_sram_check_crc(const struct cts_device + *cts_dev, u32 flash_addr, + u32 sram_addr, size_t size, + u32 crc) { - return cts_read_flash_to_sram_check_crc_retry(cts_dev, - flash_addr, sram_addr, size, crc, CTS_FLASH_READ_DEFAULT_RETRY); + return cts_read_flash_to_sram_check_crc_retry(cts_dev, + flash_addr, sram_addr, + size, crc, + CTS_FLASH_READ_DEFAULT_RETRY); } -extern int cts_erase_flash(const struct cts_device *cts_dev, u32 addr, size_t size); +extern int cts_erase_flash(const struct cts_device *cts_dev, u32 addr, + size_t size); extern int cts_program_flash(const struct cts_device *cts_dev, - u32 flash_addr, const void *src, size_t size); + u32 flash_addr, const void *src, size_t size); extern int cts_program_flash_from_sram(const struct cts_device *cts_dev, - u32 flash_addr, u32 sram_addr, size_t size); + u32 flash_addr, u32 sram_addr, + size_t size); #endif /* CTS_SPI_FLASH_H */ - diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_sysfs.c b/drivers/input/touchscreen/chipone_tddi_mmi/cts_sysfs.c old mode 100755 new mode 100644 index 94fd491ec7d3..c24c61cb2b6d --- a/drivers/input/touchscreen/chipone_tddi_mmi/cts_sysfs.c +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_sysfs.c @@ -1,2061 +1,2761 @@ -#define LOG_TAG "Sysfs" - -#include "cts_config.h" -#include "cts_platform.h" -#include "cts_core.h" -#include "cts_test.h" -#include "cts_sfctrl.h" -#include "cts_spi_flash.h" -#include "cts_firmware.h" - -#ifdef CONFIG_CTS_SYSFS - -#define SPLIT_LINE_STR \ - "-----------------------------------------------------------------------------------------------\n" -#define ROW_NUM_FORMAT_STR "%2d | " -#define COL_NUM_FORMAT_STR "%4u " -#define DATA_FORMAT_STR "%5d" - - -#define DIFFDATA_BUFFER_SIZE(cts_dev) \ - (cts_dev->fwdata.rows * cts_dev->fwdata.cols * 2) - -#define MAX_ARG_NUM (100) -#define MAX_ARG_LENGTH (1024) -#define HW_STUB_ADDR (0XF000) - -static char cmdline_param[MAX_ARG_LENGTH + 1]; -static int argc; -static char *argv[MAX_ARG_NUM]; - -static int jitter_test_frame = 10; -static s16 *manualdiff_base = NULL; - -static int parse_arg(const char *buf, size_t count) -{ - char *p; - - memcpy(cmdline_param, buf, min((size_t)MAX_ARG_LENGTH, count)); - cmdline_param[count] = '\0'; - - argc = 0; - p = strim(cmdline_param); - if (p == NULL || p[0] == '\0') { - return 0; - } - - while (p && p[0] != '\0' && argc < MAX_ARG_NUM) { - argv[argc++] = strsep(&p, " ,"); - } - - return argc; -} - -/* echo addr value1 value2 value3 ... valueN > write_reg */ -static ssize_t write_firmware_register_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - u16 addr; - int i, ret; - u8 *data = NULL; - - parse_arg(buf, count); - - cts_info("Write firmware register '%.*s'", (int)count, buf); - - if (argc < 2) { - cts_err("Too few args %d", argc); - return -EFAULT; - } - - ret = kstrtou16(argv[0], 0, &addr); - if (ret) { - cts_err("Invalid address %s", argv[0]); - return -EINVAL; - } - - data = (u8 *)kmalloc(argc - 1, GFP_KERNEL); - if (data == NULL) { - cts_err("Allocate buffer for write data failed\n"); - return -ENOMEM; - } - - for (i = 1; i < argc; i++) { - ret = kstrtou8(argv[i], 0, data + i - 1); - if (ret) { - cts_err("Invalid value %s", argv[i]); - goto free_data; - } - } - - ret = cts_fw_reg_writesb(cts_dev, addr, data, argc - 1); - if (ret) { - cts_err("Write firmware register addr: 0x%04x size: %d failed", - addr, argc - 1); - goto free_data; - } - -free_data: - kfree(data); - - return (ret < 0 ? ret : count); -} -static DEVICE_ATTR(write_reg, S_IWUSR, NULL, write_firmware_register_store); - -static ssize_t read_firmware_register_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ -#define PRINT_ROW_SIZE (16) - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - u16 addr, size, i, remaining; - u8 *data = NULL; - ssize_t count = 0; - int ret; - - cts_info("Read firmware register "); - - if (argc != 2) { - return sprintf(buf, - "Invalid num args %d\n" - " 1. echo addr size > read_reg\n" - " 2. cat read_reg\n", argc); - } - - ret = kstrtou16(argv[0], 0, &addr); - if (ret) { - return sprintf(buf, "Invalid address: %s\n", argv[0]); - } - ret = kstrtou16(argv[1], 0, &size); - if (ret) { - return sprintf(buf, "Invalid size: %s\n", argv[1]); - } - - data = (u8 *)kmalloc(size, GFP_KERNEL); - if (data == NULL) { - return sprintf(buf, "Allocate buffer for read data failed\n"); - } - - cts_info("Read firmware register from 0x%04x size %u", addr, size); - cts_lock_device(cts_dev); - ret = cts_fw_reg_readsb(cts_dev, addr, data, (size_t)size); - cts_unlock_device(cts_dev); - if (ret) { - count = sprintf(buf, - "Read firmware register from 0x%04x size %u failed %d\n", - addr, size, ret); - goto err_free_data; - } - - remaining = size; - for (i = 0; i < size && count <= PAGE_SIZE; i += PRINT_ROW_SIZE) { - size_t linelen = min((size_t)remaining, (size_t)PRINT_ROW_SIZE); - remaining -= PRINT_ROW_SIZE; - - count += snprintf(buf + count, PAGE_SIZE - count, "%04x: ", addr); - - /* Lower version kernel return void */ - hex_dump_to_buffer(data + i, linelen, PRINT_ROW_SIZE, 1, - buf + count, PAGE_SIZE - count, true); - count += strlen(buf + count); - - if (count < PAGE_SIZE) { - buf[count++] = '\n'; - addr += PRINT_ROW_SIZE; - } else { - break; - } - } - -err_free_data: - kfree(data); - - return count; -#undef PRINT_ROW_SIZE -} - -/* echo addr size > read_reg */ -static ssize_t read_firmware_register_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - parse_arg(buf, count); - - return (argc == 0 ? 0 : count); -} -static DEVICE_ATTR(read_reg, S_IWUSR | S_IRUSR, - read_firmware_register_show, read_firmware_register_store); - - - -static ssize_t read_hw_reg_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ -#define PRINT_ROW_SIZE (16) - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - u32 addr, size, i, remaining; - u8 *data = NULL; - ssize_t count = 0; - int ret; - - cts_info("Read hw register"); - - if (argc != 2) { - return sprintf(buf, - "Invalid num args %d\n" - " 1. echo addr size > read_hw_reg\n" - " 2. cat read_hw_reg\n", argc); - } - - ret = kstrtou32(argv[0], 0, &addr); - if (ret) { - return sprintf(buf, "Invalid address: %s\n", argv[0]); - } - ret = kstrtou32(argv[1], 0, &size); - if (ret) { - return sprintf(buf, "Invalid size: %s\n", argv[1]); - } - - data = (u8 *)kmalloc(size, GFP_KERNEL); - if (data == NULL) { - return sprintf(buf, "Allocate buffer for read data failed\n"); - } - - cts_info("Read hw register from 0x%04x size %u", addr, size); - cts_lock_device(cts_dev); - - for (i = 0; i < size; i++) - { - ret = cts_fw_reg_writel_retry(cts_dev, HW_STUB_ADDR, addr + i, 3, 10); - if (ret) { - count = sprintf(buf,"Write hw register error\n"); - goto err_free_data; - } - - ret = cts_fw_reg_readsb(cts_dev, HW_STUB_ADDR+4, data+i, 1); - if (ret) { - count = sprintf(buf, "Read hw register error\n"); - goto err_free_data; - } - } - remaining = size; - for (i = 0; i < size && count <= PAGE_SIZE; i += PRINT_ROW_SIZE) { - size_t linelen = min((size_t)remaining, (size_t)PRINT_ROW_SIZE); - remaining -= PRINT_ROW_SIZE; - - count += snprintf(buf + count, PAGE_SIZE - count, "%04x: ", addr); - - /* Lower version kernel return void */ - hex_dump_to_buffer(data + i, linelen, PRINT_ROW_SIZE, 1, - buf + count, PAGE_SIZE - count, true); - count += strlen(buf + count); - - if (count < PAGE_SIZE) { - buf[count++] = '\n'; - addr += PRINT_ROW_SIZE; - } else { - break; - } - } - -err_free_data: - cts_unlock_device(cts_dev); - kfree(data); - - return count; -#undef PRINT_ROW_SIZE -} - -/* echo addr size > read_reg */ -static ssize_t read_hw_reg_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - parse_arg(buf, count); - - return (argc == 0 ? 0 : count); -} - -static DEVICE_ATTR(read_hw_reg, S_IRUSR | S_IWUSR, read_hw_reg_show, read_hw_reg_store); - -static ssize_t write_hw_reg_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - u32 addr; - int i, ret; - u8 *data = NULL; - - parse_arg(buf, count); - - cts_info("Write hw register"); - - if (argc < 2) { - cts_err("Too few args %d", argc); - return -EFAULT; - } - - ret = kstrtou32(argv[0], 0, &addr); - if (ret) { - cts_err("Invalid address %s", argv[0]); - return -EINVAL; - } - - data = (u8 *)kmalloc(argc - 1, GFP_KERNEL); - if (data == NULL) { - cts_err("Allocate buffer for write data failed\n"); - return -ENOMEM; - } - - for (i = 1; i < argc; i++) { - ret = kstrtou8(argv[i], 0, data + i - 1); - if (ret) { - cts_err("Invalid value %s", argv[i]); - goto free_data; - } - } - - cts_lock_device(cts_dev); - for (i = 0; i < argc - 1; i++) - { - ret = cts_fw_reg_writel_retry(cts_dev, HW_STUB_ADDR, addr + i, 3, 10); - if (ret) { - cts_err("Write hw register error"); - break; - } - ret = cts_fw_reg_writeb_retry(cts_dev, HW_STUB_ADDR + 4, data[i], 3, 10); - if (ret) { - cts_err("Write hw register error"); - break; - } - } - cts_unlock_device(cts_dev); -free_data: - kfree(data); - - return (ret < 0 ? ret : count); -} - -static DEVICE_ATTR(write_hw_reg, S_IWUSR, NULL, write_hw_reg_store); - - -static ssize_t curr_firmware_version_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - - return sprintf(buf, "Current firmware version: %04x\n", - cts_data->cts_dev.fwdata.version); -} -static DEVICE_ATTR(curr_version, S_IRUGO, curr_firmware_version_show, NULL); - -static ssize_t curr_ddi_version_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - - return sprintf(buf, "Current ddi version: %02x\n", - cts_data->cts_dev.fwdata.ddi_version); -} -static DEVICE_ATTR(curr_ddi_version, S_IRUGO, curr_ddi_version_show, NULL); - -static ssize_t rows_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - - return sprintf(buf, "Num rows: %u\n", - cts_data->cts_dev.fwdata.rows); -} -static DEVICE_ATTR(rows, S_IRUGO, rows_show, NULL); - -static ssize_t cols_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - - return sprintf(buf, "Num cols: %u\n", - cts_data->cts_dev.fwdata.cols); -} -static DEVICE_ATTR(cols, S_IRUGO, cols_show, NULL); - -static ssize_t res_x_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - - return sprintf(buf, "X Resolution: %u\n", - cts_data->cts_dev.fwdata.res_x); -} -static DEVICE_ATTR(res_x, S_IRUGO, res_x_show, NULL); - -static ssize_t res_y_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - - return sprintf(buf, "Y Resolution: %u\n", - cts_data->cts_dev.fwdata.res_y); -} -static DEVICE_ATTR(res_y, S_IRUGO, res_y_show, NULL); - -static ssize_t esd_protection_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - int ret; - u8 esd_protection; - - cts_lock_device(cts_dev); - ret = cts_fw_reg_readb(&cts_data->cts_dev, 0x8000 + 342, &esd_protection); - cts_unlock_device(cts_dev); - if (ret) { - return sprintf(buf, "Read firmware ESD protection register failed %d\n", ret); - } - - return sprintf(buf, "ESD protection: %u\n", esd_protection); -} -static DEVICE_ATTR(esd_protection, S_IRUGO, esd_protection_show, NULL); - -static ssize_t monitor_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - int ret; - u8 value; - - cts_lock_device(cts_dev); - ret = cts_fw_reg_readb(&cts_data->cts_dev, 0x8000 + 344, &value); - cts_unlock_device(cts_dev); - if (ret) { - return sprintf(buf, "Read firmware monitor enable register failed %d\n", ret); - } - - return sprintf(buf, "Monitor mode: %s\n", - value & BIT(0) ? "Enable" : "Disable"); -} - -static ssize_t monitor_mode_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - int ret; - u8 value, enable = 0; - - if (buf[0] == 'Y' || buf[0] == 'y' || buf[0] == '1') { - enable = 1; - } - - cts_info("Write firmware monitor mode to '%c', %s", - buf[0], enable ? "Enable" : "Disable"); - - cts_lock_device(cts_dev); - ret = cts_fw_reg_readb(&cts_data->cts_dev, 0x8000 + 344, &value); - cts_unlock_device(cts_dev); - if (ret) { - cts_err("Write firmware monitor enable register failed %d", ret); - return -EIO; - } - - if ((value & BIT(0)) && enable) { - cts_info("Monitor mode already enabled"); - } else if ((value & BIT(0)) == 0 && enable == 0) { - cts_info("Monitor mode already disabled"); - } else { - if (enable) { - value |= BIT(0); - } else { - value &= ~BIT(0); - } - - cts_lock_device(cts_dev); - ret = cts_fw_reg_writeb(&cts_data->cts_dev, 0x8000 + 344, value); - cts_unlock_device(cts_dev); - if (ret) { - cts_err("Write firmware monitor enable register failed %d", ret); - return -EIO; - } - } - - return count; -} -static DEVICE_ATTR(monitor_mode, S_IRUGO, monitor_mode_show, monitor_mode_store); - -static ssize_t auto_compensate_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - int ret; - u8 value; - - cts_lock_device(cts_dev); - ret = cts_fw_reg_readb(&cts_data->cts_dev, 0x8000 + 276, &value); - cts_unlock_device(cts_dev); - if (ret) { - return sprintf(buf, "Read auto compensate enable register failed %d\n", ret); - } - - return sprintf(buf, "Auto compensate: %s\n", value ? "Enable" : "Disable"); -} -static DEVICE_ATTR(auto_compensate, S_IRUGO, auto_compensate_show, NULL); - -#ifdef CFG_CTS_DRIVER_BUILTIN_FIRMWARE -static ssize_t driver_builtin_firmware_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int i, count = 0; - - count += snprintf(buf + count, PAGE_SIZE - count, - "Total %d builtin firmware:\n", - cts_get_num_driver_builtin_firmware()); - - for (i = 0; i < cts_get_num_driver_builtin_firmware(); i++) { - const struct cts_firmware *firmware = - cts_request_driver_builtin_firmware_by_index(i); - if (firmware) { - count += snprintf(buf + count, PAGE_SIZE - count, - "%-2d: hwid: %04x fwid: %04x ver: %04x size: %6zu desc: %s\n", - i, firmware->hwid, firmware->fwid, FIRMWARE_VERSION(firmware), - firmware->size, firmware->name); - } else { - count += snprintf(buf + count, PAGE_SIZE - count, - "%-2d: INVALID\n", i); - } - } - - return count; -} - -/* echo index/name [flash/sram] > driver_builtin_firmware */ -static ssize_t driver_builtin_firmware_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - const struct cts_firmware *firmware; - bool to_flash = true; - int ret, index = -1; - - parse_arg(buf, count); - - if (argc != 1 && argc != 2) { - cts_err("Invalid num args %d\n" - " echo index/name [flash/sram] > driver_builtin_firmware\n", argc); - return -EFAULT; - } - - if (isdigit(*argv[0])) { - index = simple_strtoul(argv[0], NULL, 0); - } - - if (argc > 1) { - if (strncasecmp(argv[1], "flash", 5) == 0) { - to_flash = true; - } else if (strncasecmp(argv[1], "sram", 4) == 0) { - to_flash = false; - } else { - cts_err("Invalid location '%s', must be 'flash' or 'sram'", argv[1]); - return -EINVAL; - } - } - - cts_info("Update driver builtin firmware '%s' to %s", - argv[1], to_flash ? "flash" : "sram"); - - if (index >= 0 && index < cts_get_num_driver_builtin_firmware()) { - firmware = cts_request_driver_builtin_firmware_by_index(index); - } else { - firmware = cts_request_driver_builtin_firmware_by_name(argv[0]); - } - - if (firmware) { - ret = cts_stop_device(cts_dev); - if (ret) { - cts_err("Stop device failed %d", ret); - return ret; - } - - ret = cts_update_firmware(cts_dev, firmware, to_flash); - if (ret) { - cts_err("Update firmware failed %d", ret); - goto err_start_device; - } - - ret = cts_start_device(cts_dev); - if (ret) { - cts_err("Start device failed %d", ret); - return ret; - } - } else { - cts_err("Firmware '%s' NOT found", argv[0]); - return -ENOENT; - } - - return count; - -err_start_device: - cts_start_device(cts_dev); - - return ret; -} -static DEVICE_ATTR(driver_builtin_firmware, S_IWUSR | S_IRUGO, - driver_builtin_firmware_show, driver_builtin_firmware_store); -#endif /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */ - -#ifdef CFG_CTS_FIRMWARE_IN_FS -/* echo filepath [flash/sram] > update_firmware_from_file */ -static ssize_t update_firmware_from_file_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - const struct cts_firmware *firmware; - bool to_flash = true; - int ret; - // int index; - - parse_arg(buf, count); - - if (argc > 2) { - cts_err("Invalid num args %d\n" - " echo filepath [flash/sram] > update_from_file\n", argc); - return -EFAULT; - } else if (argc > 1) { - if (strncasecmp(argv[1], "flash", 5) == 0) { - to_flash = true; - } else if (strncasecmp(argv[1], "sram", 4) == 0) { - to_flash = false; - } else { - cts_err("Invalid location '%s', must be 'flash' or 'sram'", argv[1]); - return -EINVAL; - } - } - - cts_info("Update firmware from file '%s'", argv[0]); - - firmware = cts_request_firmware_from_fs(argv[0]); - if (firmware == NULL) { - cts_err("Request firmware from file '%s' failed", argv[0]); - return -ENOENT; - } - - ret = cts_stop_device(cts_dev); - if (ret) { - cts_err("Stop device failed %d", ret); - goto err_release_firmware; - } - - ret = cts_update_firmware(cts_dev, firmware, to_flash); - if (ret) { - cts_err("Update firmware failed %d", ret); - goto err_release_firmware; - } - - ret = cts_start_device(cts_dev); - if (ret) { - cts_err("Start device failed %d", ret); - goto err_release_firmware; - } - - return count; - -err_release_firmware: - cts_release_firmware(firmware); - - return ret; -} -static DEVICE_ATTR(update_from_file, S_IWUSR, NULL, update_firmware_from_file_store); -#endif /* CFG_CTS_FIRMWARE_IN_FS */ - -static ssize_t updating_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - - return sprintf(buf, "Updating: %s\n", - cts_data->cts_dev.rtdata.updating ? "Y" : "N"); -} -static DEVICE_ATTR(updating, S_IRUGO, updating_show, NULL); - -static struct attribute *cts_dev_firmware_atts[] = { - &dev_attr_curr_version.attr, - &dev_attr_curr_ddi_version.attr, - &dev_attr_rows.attr, - &dev_attr_cols.attr, - &dev_attr_res_x.attr, - &dev_attr_res_y.attr, - &dev_attr_esd_protection.attr, - &dev_attr_monitor_mode.attr, - &dev_attr_auto_compensate.attr, -#ifdef CFG_CTS_DRIVER_BUILTIN_FIRMWARE - &dev_attr_driver_builtin_firmware.attr, -#endif /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */ -#ifdef CFG_CTS_FIRMWARE_IN_FS - &dev_attr_update_from_file.attr, -#endif /* CFG_CTS_FIRMWARE_IN_FS */ - &dev_attr_updating.attr, - NULL -}; - -static const struct attribute_group cts_dev_firmware_attr_group = { - .name = "cts_firmware", - .attrs = cts_dev_firmware_atts, -}; - -static ssize_t flash_info_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - const struct cts_flash *flash; - - if (cts_dev->flash == NULL) { - bool program_mode; - bool enabled; - int ret; - - program_mode = cts_is_device_program_mode(cts_dev); - enabled = cts_is_device_enabled(cts_dev); - - ret = cts_prepare_flash_operation(cts_dev); - if (ret) { - return sprintf(buf, "Prepare flash operation failed %d", ret); - } - - cts_post_flash_operation(cts_dev); - - if (!program_mode) { - ret = cts_enter_normal_mode(cts_dev); - if (ret) { - return sprintf(buf, "Enter normal mode failed %d", ret); - } - } - - if (enabled) { - ret = cts_start_device(cts_dev); - if (ret) { - return sprintf(buf, "Start device failed %d", ret); - } - } - - if (cts_dev->flash == NULL) { - return sprintf(buf, "Flash not found\n"); - } - } - - flash = cts_dev->flash; - return snprintf(buf, PAGE_SIZE, - "%s:\n" - " JEDEC ID : %06X\n" - " Page size : 0x%zx\n" - " Sector size: 0x%zx\n" - " Block size : 0x%zx\n" - " Total size : 0x%zx\n", - flash->name, flash->jedec_id, flash->page_size, - flash->sector_size, flash->block_size, flash->total_size); -} -static DEVICE_ATTR(info, S_IRUGO, flash_info_show, NULL); - -static ssize_t read_flash_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - u32 flash_addr, size, i, remaining; - u8 *data = NULL; - ssize_t count = 0; - int ret; - bool program_mode; - bool enabled; - loff_t pos = 0; - - if (argc != 2 && argc != 3) { - return sprintf(buf, "Invalid num args %d\n", argc); - } - - ret = kstrtou32(argv[0], 0, &flash_addr); - if (ret) { - return sprintf(buf, "Invalid flash addr: %s\n", argv[0]); - } - ret = kstrtou32(argv[1], 0, &size); - if (ret) { - return sprintf(buf, "Invalid size: %s\n", argv[1]); - } - - data = (u8 *)kmalloc(size, GFP_KERNEL); - if (data == NULL) { - return sprintf(buf, "Allocate buffer for read data failed\n"); - } - - cts_info("Read flash from 0x%06x size %u%s%s", - flash_addr, size, argc == 3 ? " to file " : "", - argc == 3 ? argv[2] : ""); - - cts_lock_device(cts_dev); - program_mode = cts_is_device_program_mode(cts_dev); - enabled = cts_is_device_enabled(cts_dev); - - ret = cts_prepare_flash_operation(cts_dev); - if (ret) { - count += sprintf(buf, "Prepare flash operation failed %d", ret); - goto err_free_data; - } - - ret = cts_read_flash(cts_dev, flash_addr, data, size); - if (ret) { - count = sprintf(buf, "Read flash data failed %d\n", ret); - goto err_post_flash_operation; - } - - if (argc == 3) { - struct file *file; - - cts_info("Write flash data to file '%s'", argv[2]); - - file = filp_open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0666); - if (IS_ERR(file)) { - count += sprintf(buf, "Open file '%s' failed %ld", - argv[2], PTR_ERR(file)); - goto err_post_flash_operation; - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0) - ret = kernel_write(file, data, size, &pos); -#else - ret = kernel_write(file, data, size, pos); -#endif - if (ret != size) { - count += sprintf(buf, "Write flash data to file '%s' failed %d", - argv[2], ret); - } - - ret = filp_close(file, NULL); - if (ret) { - count += sprintf(buf, "Close file '%s' failed %d", argv[2], ret); - } - } else { -#define PRINT_ROW_SIZE (16) - remaining = size; - for (i = 0; i < size && count <= PAGE_SIZE; i += PRINT_ROW_SIZE) { - size_t linelen = min((size_t)remaining, (size_t)PRINT_ROW_SIZE); - remaining -= PRINT_ROW_SIZE; - - count += snprintf(buf + count, PAGE_SIZE - count - 1, - "%04x-%04x: ", flash_addr >> 16, flash_addr & 0xFFFF); - /* Lower version kernel return void */ - hex_dump_to_buffer(data + i, linelen, PRINT_ROW_SIZE, 1, - buf + count, PAGE_SIZE - count - 1, true); - count += strlen(buf + count); - buf[count++] = '\n'; - flash_addr += linelen; -#undef PRINT_ROW_SIZE - } - } - -err_post_flash_operation: - cts_post_flash_operation(cts_dev); - - if (!program_mode) { - int r = cts_enter_normal_mode(cts_dev); - if (r) { - count += sprintf(buf, "Enter normal mode failed %d", r); - } - } - - if (enabled) { - int r = cts_start_device(cts_dev); - if (r) { - cts_unlock_device(cts_dev); - return sprintf(buf, "Start device failed %d", r); - } - } -err_free_data: - cts_unlock_device(cts_dev); - kfree(data); - - return (ret < 0 ? ret : count); -} - -/* echo start_addr size [filepath] > read */ -static ssize_t read_flash_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - parse_arg(buf, count); - - return count; -} -static DEVICE_ATTR(read, S_IWUSR | S_IRUGO, read_flash_show, read_flash_store); - -/* echo addr size > erase */ -static ssize_t erase_flash_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - u32 flash_addr, size; - int ret; - bool program_mode; - bool enabled; - - parse_arg(buf, count); - - if (argc != 2) { - cts_err("Invalid num args %d", argc); - return -EFAULT; - } - - ret = kstrtou32(argv[0], 0, &flash_addr); - if (ret) { - cts_err("Invalid flash addr: %s", argv[0]); - return -EINVAL; - } - ret = kstrtou32(argv[1], 0, &size); - if (ret) { - cts_err("Invalid size: %s", argv[1]); - return -EINVAL; - } - - cts_info("Erase flash from 0x%06x size %u", flash_addr, size); - - cts_lock_device(cts_dev); - program_mode = cts_is_device_program_mode(cts_dev); - enabled = cts_is_device_enabled(cts_dev); - - ret = cts_prepare_flash_operation(cts_dev); - if (ret) { - cts_err("Prepare flash operation failed %d", ret); - cts_unlock_device(cts_dev); - return ret; - } - - ret = cts_erase_flash(cts_dev, flash_addr, size); - if (ret) { - cts_err("Erase flash from 0x%06x size %u failed %d", - flash_addr, size, ret); - goto err_post_flash_operation; - } - -err_post_flash_operation: - cts_post_flash_operation(cts_dev); - - if (!program_mode) { - int r = cts_enter_normal_mode(cts_dev); - if (r) { - cts_err("Enter normal mode failed %d", r); - } - } - - if (enabled) { - int r = cts_start_device(cts_dev); - if (r) { - cts_err("Start device failed %d", r); - } - } - cts_unlock_device(cts_dev); - - return (ret < 0 ? ret : count); -} -static DEVICE_ATTR(erase, S_IWUSR, NULL, erase_flash_store); - -static struct attribute *cts_dev_flash_attrs[] = { - &dev_attr_info.attr, - &dev_attr_read.attr, - &dev_attr_erase.attr, - - NULL -}; - -static const struct attribute_group cts_dev_flash_attr_group = { - .name = "flash", - .attrs = cts_dev_flash_attrs, -}; - -static ssize_t open_test_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - u16 threshold; - int ret; - - if (argc != 1) { - return sprintf(buf, "Invalid num args %d\n", argc); - } - - ret = kstrtou16(argv[0], 0, &threshold); - if (ret) { - return sprintf(buf, "Invalid threshold: %s\n", argv[0]); - } - - cts_info("Open test, threshold = %u", threshold); - - ret = cts_open_test(cts_dev, threshold); - if (ret) { - return sprintf(buf, "Open test FAILED %d, threshold = %u\n", - ret, threshold); - } else { - return sprintf(buf, "Open test PASSED, threshold = %u\n", - threshold); - } -} - -/* echo threshod > open_test */ -static ssize_t open_test_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - parse_arg(buf, count); - - return count; -} -static DEVICE_ATTR(open_test, S_IWUSR | S_IRUGO, open_test_show, open_test_store); - -static ssize_t short_test_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - u16 threshold; - int ret; - - if (argc != 1) { - return sprintf(buf, "Invalid num args %d\n", argc); - } - - ret = kstrtou16(argv[0], 0, &threshold); - if (ret) { - return sprintf(buf, "Invalid threshold: %s\n", argv[0]); - } - - cts_info("Short test, threshold = %u", threshold); - - ret = cts_short_test(cts_dev, threshold); - if (ret) { - return sprintf(buf, "Short test FAILED %d, threshold = %u\n", - ret, threshold); - } else { - return sprintf(buf, "Short test PASSED, threshold = %u\n", - threshold); - } -} - -/* echo threshod > short_test */ -static ssize_t short_test_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - parse_arg(buf, count); - - return count; -} -static DEVICE_ATTR(short_test, S_IWUSR | S_IRUGO, - short_test_show, short_test_store); - -static ssize_t testing_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - - return sprintf(buf, "Testting: %s\n", - cts_data->cts_dev.rtdata.testing ? "Y" : "N"); -} -static DEVICE_ATTR(testing, S_IRUGO, testing_show, NULL); - -#ifdef CFG_CTS_HAS_RESET_PIN -static ssize_t reset_test_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - int ret; - int count; - - ret = cts_reset_test(cts_dev); - if (ret == 0) { - count = sprintf(buf, "reset pin test sucessful\n"); - } - else { - count = sprintf(buf, "reset pin test failed\n"); - } - - return count; -} -static DEVICE_ATTR(reset_test, S_IRUGO, reset_test_show, NULL); -#endif - -static ssize_t compensate_cap_test_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - u8 min_thres, max_thres; - int ret; - - if (argc != 2) { - return sprintf(buf, "Invalid num args\n" - "USAGE:\n" - " 1. echo min max > compensate_cap_test\n" - " 2. cat compensate_cap_test\n"); - } - - ret = kstrtou8(argv[0], 0, &min_thres); - if (ret) { - return sprintf(buf, "Invalid min_thres: %s\n", argv[0]); - } - - ret = kstrtou8(argv[1], 0, &max_thres); - if (ret) { - return sprintf(buf, "Invalid max_thres: %s\n", argv[1]); - } - - cts_info("Compensate cap test, min_thres = %u, max_thres = %u", min_thres, max_thres); - - ret = cts_compensate_cap_test(cts_dev, min_thres, max_thres); - if (ret) { - return sprintf(buf, "Compensate cap test FAILED, min_thres = %u, max_thres=%u\n", - min_thres, max_thres); - } else { - return sprintf(buf, "Compensate cap test PASSED, min_thres = %u, max_thres=%u\n", - min_thres, max_thres); - } -} - -/* echo threshod > short_test */ -static ssize_t compensate_cap_test_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - parse_arg(buf, count); - - return count; -} -static DEVICE_ATTR(compensate_cap_test, S_IWUSR | S_IRUGO, - compensate_cap_test_show, compensate_cap_test_store); - -static ssize_t rawdata_test_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - u16 min_thres, max_thres; - int ret; - - if (argc != 2) { - return sprintf(buf, "Invalid num args\n" - "USAGE:\n" - " 1. echo min max > rawdata_test\n" - " 2. cat rawdata_test\n"); - } - - ret = kstrtou16(argv[0], 0, &min_thres); - if (ret) { - return sprintf(buf, "Invalid min_thres: %s\n", argv[0]); - } - - ret = kstrtou16(argv[1], 0, &max_thres); - if (ret) { - return sprintf(buf, "Invalid max_thres: %s\n", argv[1]); - } - - cts_info("Rawdata test, min_thres = %u, max_thres = %u", min_thres, max_thres); - - ret = cts_rawdata_test(cts_dev, min_thres, max_thres); - if (ret) { - return sprintf(buf, "Rawdata test FAILED, min_thres = %u, max_thres=%u\n", - min_thres, max_thres); - } else { - return sprintf(buf, "Rawdata test PASSED, min_thres = %u, max_thres=%u\n", - min_thres, max_thres); - } -} - -/* echo threshod > short_test */ -static ssize_t rawdata_test_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - parse_arg(buf, count); - - return count; -} -static DEVICE_ATTR(rawdata_test, S_IWUSR | S_IRUGO, - rawdata_test_show, rawdata_test_store); - -static struct attribute *cts_dev_test_atts[] = { - &dev_attr_open_test.attr, - &dev_attr_short_test.attr, - &dev_attr_testing.attr, -#ifdef CFG_CTS_HAS_RESET_PIN - &dev_attr_reset_test.attr, -#endif - &dev_attr_compensate_cap_test.attr, - &dev_attr_rawdata_test.attr, - NULL -}; - -static const struct attribute_group cts_dev_test_attr_group = { - .name = "test", - .attrs = cts_dev_test_atts, -}; - -static ssize_t ic_type_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - - return sprintf(buf, "IC Type : %s\n", - cts_data->cts_dev.hwdata->name); -} -static DEVICE_ATTR(ic_type, S_IRUGO, ic_type_show, NULL); - -static ssize_t program_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - - return sprintf(buf, "Program mode: %s\n", - cts_data->cts_dev.rtdata.program_mode ? "Y" : "N"); -} -static ssize_t program_mode_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - int ret; - parse_arg(buf, count); - - if (argc != 1) { - cts_err("Invalid num args %d", argc); - return -EFAULT; - } - - if (*argv[0] == '1' || tolower(*argv[0]) == 'y') { - ret = cts_enter_program_mode(&cts_data->cts_dev); - if (ret) { - cts_err("Enter program mode failed %d", ret); - return ret; - } - } - else if (*argv[0] == '0' || tolower(*argv[0]) == 'n') { - ret = cts_enter_normal_mode(&cts_data->cts_dev); - if (ret) { - cts_err("Exit program mode failed %d", ret); - return ret; - } - } else { - cts_err("Invalid args"); - } - - return count; -} -static DEVICE_ATTR(program_mode, S_IWUSR | S_IRUGO, - program_mode_show, program_mode_store); - -static ssize_t rawdata_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ -#define RAWDATA_BUFFER_SIZE(cts_dev) \ - (cts_dev->fwdata.rows * cts_dev->fwdata.cols * 2) - - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - u16 *rawdata = NULL; - int ret, r, c, count = 0; - u32 max, min, sum, average; - int max_r, max_c, min_r, min_c; - bool data_valid = true; - - cts_info("Show rawdata"); - - rawdata = (u16 *)kmalloc(RAWDATA_BUFFER_SIZE(cts_dev), GFP_KERNEL); - if (rawdata == NULL) { - return sprintf(buf, "Allocate memory for rawdata failed\n"); - } - - cts_lock_device(cts_dev); - ret = cts_enable_get_rawdata(cts_dev); - if (ret) { - count += sprintf(buf, "Enable read raw data failed %d\n", ret); - goto err_free_rawdata; - } - - ret = cts_send_command(cts_dev, CTS_CMD_QUIT_GESTURE_MONITOR); - if (ret) { - count += sprintf(buf, "Send cmd QUIT_GESTURE_MONITOR failed %d\n", ret); - goto err_free_rawdata; - } - msleep(50); - - ret = cts_get_rawdata(cts_dev, rawdata); - if(ret) { - count += sprintf(buf, "Get raw data failed %d\n", ret); - data_valid = false; - // Fall through to disable get rawdata - } - ret = cts_disable_get_rawdata(cts_dev); - if (ret) { - count += sprintf(buf, "Disable read raw data failed %d\n", ret); - // Fall through to show rawdata - } - - if (data_valid) { - max = min = rawdata[0]; - sum = 0; - max_r = max_c = min_r = min_c = 0; - for (r = 0; r < cts_dev->fwdata.rows; r++) { - for (c = 0; c < cts_dev->fwdata.cols; c++) { - u16 val = rawdata[r * cts_dev->fwdata.cols + c]; - sum += val; - if (val > max) { - max = val; - max_r = r; - max_c = c; - } else if (val < min) { - min = val; - min_r = r; - min_c = c; - } - } - } - average = sum / (cts_dev->fwdata.rows * cts_dev->fwdata.cols); - - count += sprintf(buf + count, - SPLIT_LINE_STR - "Raw data MIN: [%d][%d]=%u, MAX: [%d][%d]=%u, AVG=%u\n" - SPLIT_LINE_STR - " | ", min_r, min_c, min, max_r, max_c, max, average); - for (c = 0; c < cts_dev->fwdata.cols; c++) { - count += sprintf(buf + count, COL_NUM_FORMAT_STR, c); - } - count += sprintf(buf + count, "\n" SPLIT_LINE_STR); - - for (r = 0; r < cts_dev->fwdata.rows && count < PAGE_SIZE; r++) { - count += sprintf(buf + count, ROW_NUM_FORMAT_STR, r); - for (c = 0; c < cts_dev->fwdata.cols && count < PAGE_SIZE; c++) { - count += snprintf(buf + count, PAGE_SIZE - count - 1, - DATA_FORMAT_STR, rawdata[r * cts_dev->fwdata.cols + c]); - } - buf[count++] = '\n'; - } - } - -err_free_rawdata: - cts_unlock_device(cts_dev); - kfree(rawdata); - - return (data_valid ? count : ret); - -#undef RAWDATA_BUFFER_SIZE -} -static DEVICE_ATTR(rawdata, S_IRUGO, rawdata_show, NULL); - -static ssize_t diffdata_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - s16 *diffdata = NULL; - int ret, r, c, count = 0; - int max, min, sum, average; - int max_r, max_c, min_r, min_c; - bool data_valid = true; - - cts_info("Show diffdata"); - - diffdata = (s16 *)kmalloc(DIFFDATA_BUFFER_SIZE(cts_dev), GFP_KERNEL); - if (diffdata == NULL) { - cts_err("Allocate memory for diffdata failed"); - return -ENOMEM; - } - - cts_lock_device(cts_dev); - ret = cts_enable_get_rawdata(cts_dev); - if (ret) { - cts_err("Enable read diff data failed %d", ret); - goto err_free_diffdata; - } - - ret = cts_send_command(cts_dev, CTS_CMD_QUIT_GESTURE_MONITOR); - if (ret) { - cts_err("Send cmd QUIT_GESTURE_MONITOR failed %d", ret); - goto err_free_diffdata; - } - msleep(50); - - ret = cts_get_diffdata(cts_dev, diffdata); - if(ret) { - cts_err("Get diff data failed %d", ret); - data_valid = false; - // Fall through to disable get diffdata - } - ret = cts_disable_get_rawdata(cts_dev); - if (ret) { - cts_err("Disable read diff data failed %d", ret); - // Fall through to show diffdata - } - - if (data_valid) { - max = min = diffdata[0]; - sum = 0; - max_r = max_c = min_r = min_c = 0; - for (r = 0; r < cts_dev->fwdata.rows; r++) { - for (c = 0; c < cts_dev->fwdata.cols; c++) { - s16 val = diffdata[r * cts_dev->fwdata.cols + c]; - - sum += val; - if (val > max) { - max = val; - max_r = r; - max_c = c; - } else if (val < min) { - min = val; - min_r = r; - min_c = c; - } - } - } - average = sum / (cts_dev->fwdata.rows * cts_dev->fwdata.cols); - - count += sprintf(buf + count, - SPLIT_LINE_STR - "Diff data MIN: [%d][%d]=%d, MAX: [%d][%d]=%d, AVG=%d\n" - SPLIT_LINE_STR - " | ", min_r, min_c, min, max_r, max_c, max, average); - for (c = 0; c < cts_dev->fwdata.cols; c++) { - count += sprintf(buf + count, COL_NUM_FORMAT_STR, c); - } - count += sprintf(buf + count, "\n" SPLIT_LINE_STR); - - for (r = 0; r < cts_dev->fwdata.rows; r++) { - count += sprintf(buf + count, ROW_NUM_FORMAT_STR, r); - for (c = 0; c < cts_dev->fwdata.cols; c++) { - count += snprintf(buf + count, PAGE_SIZE - count, - DATA_FORMAT_STR, diffdata[r * cts_dev->fwdata.cols + c]); - } - buf[count++] = '\n'; - } - } - -err_free_diffdata: - cts_unlock_device(cts_dev); - kfree(diffdata); - - return (data_valid ? count : ret); -} -static DEVICE_ATTR(diffdata, S_IRUGO, diffdata_show, NULL); - -static ssize_t manualdiffdata_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - s16 *rawdata = NULL; - int ret, r, c, count = 0; - int max, min, sum, average; - int max_r, max_c, min_r, min_c; - bool data_valid = true; - int frame; - struct file *file; - int i; - loff_t pos = 0; - - cts_info("Show manualdiff"); - - if (argc != 1 && argc != 2) { - return sprintf(buf, "Invalid num args\n" - "USAGE:\n" - " 1. echo updatebase > manualdiff\n" - " 2. cat manualdiff\n" - " or\n" - " 1. echo updatebase > manualdiff\n" - " 2. echo frame file > manualdiff\n" - " 3. cat manualdiff\n"); - } - - if (argc == 2) { - ret = kstrtou32(argv[0], 0, &frame); - if (ret) { - return sprintf(buf, "Invalid frame num\n"); - } - file = filp_open(argv[1], O_RDWR | O_CREAT | O_TRUNC, 0666); - if (IS_ERR(file)) { - return sprintf(buf, "Can't open file:%s", argv[1]); - } - } - else { - frame = 1; - } - - rawdata = (s16 *)kmalloc(DIFFDATA_BUFFER_SIZE(cts_dev), GFP_KERNEL); - if (rawdata == NULL) { - cts_err("Allocate memory for rawdata failed"); - filp_close(file, NULL); - return -ENOMEM; - } - - cts_lock_device(cts_dev); - ret = cts_enable_get_rawdata(cts_dev); - if (ret) { - cts_err("Enable read raw data failed %d", ret); - goto err_free_diffdata; - } - - ret = cts_send_command(cts_dev, CTS_CMD_QUIT_GESTURE_MONITOR); - if (ret) { - cts_err("Send cmd QUIT_GESTURE_MONITOR failed %d", ret); - goto err_free_diffdata; - } - msleep(50); - - cts_info("frame %d, file:%s", frame, argv[1]); - for (i = 0; i < frame; i++) { - ret = cts_get_rawdata(cts_dev, rawdata); - if(ret) { - cts_err("Get raw data failed %d", ret); - data_valid = false; - } - else { - data_valid = true; - } - msleep(50); - - if (data_valid) { - max = -32768; - min = 32767; - sum = 0; - max_r = max_c = min_r = min_c = 0; - for (r = 0; r < cts_dev->fwdata.rows; r++) { - for (c = 0; c < cts_dev->fwdata.cols; c++) { - s16 val; - - rawdata[r * cts_dev->fwdata.cols + c] -= manualdiff_base[r * cts_dev->fwdata.cols + c]; - val = rawdata[r * cts_dev->fwdata.cols + c]; - sum += val; - if (val > max) { - max = val; - max_r = r; - max_c = c; - } else if (val < min) { - min = val; - min_r = r; - min_c = c; - } - } - } - average = sum / (cts_dev->fwdata.rows * cts_dev->fwdata.cols); - count += sprintf(buf + count, - SPLIT_LINE_STR - "Manualdiff data MIN: [%d][%d]=%d, MAX: [%d][%d]=%d, AVG=%d\n" - SPLIT_LINE_STR - " | ", min_r, min_c, min, max_r, max_c, max, average); - for (c = 0; c < cts_dev->fwdata.cols; c++) { - count += sprintf(buf + count, COL_NUM_FORMAT_STR, c); - } - count += sprintf(buf + count, "\n" SPLIT_LINE_STR); - - for (r = 0; r < cts_dev->fwdata.rows; r++) { - count += sprintf(buf + count, ROW_NUM_FORMAT_STR, r); - for (c = 0; c < cts_dev->fwdata.cols; c++) { - count += snprintf(buf + count, PAGE_SIZE - count, - DATA_FORMAT_STR, rawdata[r * cts_dev->fwdata.cols + c]); - } - buf[count++] = '\n'; - } - //cts_info("manualdiffdata_show:%d, %d", i, frame); - if (argc == 2) { - pos = file->f_pos; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0) - ret = kernel_write(file, buf, count, &pos); -#else - ret = kernel_write(file, buf, count, pos); -#endif - if (ret != count) { - cts_err("Write data to file '%s' failed %d", argv[1], ret); - } - file->f_pos += count; - count = 0; - } - } - } - if (argc == 2) { - filp_close(file, NULL); - } - - ret = cts_disable_get_rawdata(cts_dev); - if (ret) { - cts_err("Disable read raw data failed %d", ret); - // Fall through to show diffdata - } - -err_free_diffdata: - cts_unlock_device(cts_dev); - kfree(rawdata); - - return (data_valid ? count : ret); -} - -static ssize_t manualdiffdata_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - int ret; - - parse_arg(buf, count); - - cts_lock_device(cts_dev); - if (strncasecmp("updatebase", argv[0], 10) == 0) { - ret = cts_enable_get_rawdata(cts_dev); - if (ret) { - cts_err("Enable read raw data failed %d", ret); - goto err_manual_diff_store; - } - - ret = cts_send_command(cts_dev, CTS_CMD_QUIT_GESTURE_MONITOR); - if (ret) { - cts_err("Send cmd QUIT_GESTURE_MONITOR failed %d", ret); - goto err_manual_diff_store; - } - msleep(50); - - if (manualdiff_base != NULL) { - ret = cts_get_rawdata(cts_dev, manualdiff_base); - if(ret) { - cts_err("Get raw data failed %d", ret); - } - } - //cts_info("update base successful"); - ret = cts_disable_get_rawdata(cts_dev); - if (ret) { - cts_err("Disable read raw data failed %d", ret); - } - } -err_manual_diff_store: - cts_unlock_device(cts_dev); - return count; -} - -static DEVICE_ATTR(manualdiff, S_IRUSR|S_IWUSR, manualdiffdata_show, manualdiffdata_store); - -static ssize_t jitter_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - u16 cnt; - int ret; - - parse_arg(buf, count); - - if (argc != 1) { - cts_err("Invalid num args %d", argc); - return -EFAULT; - } - - ret = kstrtou16(argv[0], 0, &cnt); - if (ret == 0) { - if (cnt > 2 || cnt < 10000) { - jitter_test_frame = cnt; - } - } - - cts_info("jitter test frame: %d", jitter_test_frame); - return count; -} - -static ssize_t jitter_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - s16 *rawdata = NULL; - s16 *rawdata_min = NULL; - s16 *rawdata_max = NULL; - int ret, r, c, count = 0; - int max, min, sum, average; - int max_r, max_c, min_r, min_c; - bool data_valid = false; - int i; - - cts_info("Show jitter"); - cts_lock_device(cts_dev); - rawdata = (s16 *)kmalloc(DIFFDATA_BUFFER_SIZE(cts_dev), GFP_KERNEL); - if (rawdata == NULL) { - cts_err("Allocate memory for rawdata failed"); - ret = -ENOMEM; - goto err_jitter_show_exit; - } - rawdata_min = (s16 *)kmalloc(DIFFDATA_BUFFER_SIZE(cts_dev), GFP_KERNEL); - if (rawdata_min == NULL) { - cts_err("Allocate memory for rawdata failed"); - ret = -ENOMEM; - goto err_free_rawdata; - } - rawdata_max = (s16 *)kmalloc(DIFFDATA_BUFFER_SIZE(cts_dev), GFP_KERNEL); - if (rawdata_max == NULL) { - cts_err("Allocate memory for rawdata failed"); - ret = -ENOMEM; - goto err_free_rawdata_min; - } - - for (i = 0; i < DIFFDATA_BUFFER_SIZE(cts_dev)/2; i++) { - rawdata_min[i] = 32767; - rawdata_max[i] = -32768; - } - - ret = cts_enable_get_rawdata(cts_dev); - if (ret) { - cts_err("Enable read raw data failed %d", ret); - goto err_free_rawdata_max; - } - - ret = cts_send_command(cts_dev, CTS_CMD_QUIT_GESTURE_MONITOR); - if (ret) { - cts_err("Send cmd QUIT_GESTURE_MONITOR failed %d", ret); - goto err_free_rawdata_max; - } - msleep(50); - data_valid = true; - for (i = 0; i < jitter_test_frame; i++) - { - ret = cts_get_rawdata(cts_dev, rawdata); - if(ret) { - cts_err("Get raw data failed %d", ret); - continue; - } - for (r = 0; r < cts_dev->fwdata.rows; r++) { - for (c = 0; c < cts_dev->fwdata.cols; c++) { - int index; - index = r * cts_dev->fwdata.cols + c; - if (rawdata_min[index] > rawdata[index]) - rawdata_min[index] = rawdata[index]; - else if (rawdata_max[index] < rawdata[index]) - rawdata_max[index] = rawdata[index]; - } - } - msleep(1); - } - ret = cts_disable_get_rawdata(cts_dev); - if (ret) { - cts_err("Disable read raw data failed %d", ret); - } - - if (data_valid) { - max = -32768; - min = 32767; - sum = 0; - max_r = max_c = min_r = min_c = 0; - for (r = 0; r < cts_dev->fwdata.rows; r++) { - for (c = 0; c < cts_dev->fwdata.cols; c++) { - s16 val; - int index = r * cts_dev->fwdata.cols + c; - - val = rawdata_max[index] - rawdata_min[index]; - rawdata[index] = val; - sum += val; - if (val > max) { - max = val; - max_r = r; - max_c = c; - } else if (val < min) { - min = val; - min_r = r; - min_c = c; - } - } - } - average = sum / (cts_dev->fwdata.rows * cts_dev->fwdata.cols); - - count += sprintf(buf + count, - SPLIT_LINE_STR - "Jitter data MIN: [%d][%d]=%d, MAX: [%d][%d]=%d, AVG=%d, TOTAL FRAME=%d\n" - SPLIT_LINE_STR - " | ", min_r, min_c, min, max_r, max_c, max, average, jitter_test_frame); - for (c = 0; c < cts_dev->fwdata.cols; c++) { - count += sprintf(buf + count, COL_NUM_FORMAT_STR, c); - } - count += sprintf(buf + count, "\n" SPLIT_LINE_STR); - - for (r = 0; r < cts_dev->fwdata.rows; r++) { - count += sprintf(buf + count, ROW_NUM_FORMAT_STR, r); - for (c = 0; c < cts_dev->fwdata.cols; c++) { - count += snprintf(buf + count, PAGE_SIZE - count, - DATA_FORMAT_STR, rawdata[r * cts_dev->fwdata.cols + c]); - } - buf[count++] = '\n'; - } - } - -err_free_rawdata_max: - kfree(rawdata_max); -err_free_rawdata_min: - kfree(rawdata_min); -err_free_rawdata: - kfree(rawdata); -err_jitter_show_exit: - cts_unlock_device(cts_dev); - return (data_valid ? count : ret); -} - -static DEVICE_ATTR(jitter, S_IRUSR|S_IWUSR, jitter_show, jitter_store); - -static ssize_t compensate_cap_show(struct device *dev, - struct device_attribute *attr, char *buf) +#define LOG_TAG "Sysfs" + +#include "cts_config.h" +#include "cts_platform.h" +#include "cts_core.h" +#include "cts_test.h" +#include "cts_sfctrl.h" +#include "cts_spi_flash.h" +#include "cts_firmware.h" + +#ifdef CONFIG_CTS_SYSFS + +#define SPLIT_LINE_STR \ + "-----------------------------------------------------------------------------------------------\n" +#define ROW_NUM_FORMAT_STR "%2d | " +#define COL_NUM_FORMAT_STR "%4u " +#define DATA_FORMAT_STR "%5d" + +#define DIFFDATA_BUFFER_SIZE(cts_dev) \ + (cts_dev->fwdata.rows * cts_dev->fwdata.cols * 2) + +#define MAX_ARG_NUM (100) +#define MAX_ARG_LENGTH (1024) +#define HW_STUB_ADDR (0XF000) + +static char cmdline_param[MAX_ARG_LENGTH + 1]; +int argc; +char *argv[MAX_ARG_NUM]; + +static int jitter_test_frame = 10; +static s16 *manualdiff_base; + +u16 speed = 1000; + +int parse_arg(const char *buf, size_t count) { - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - u8 *cap = NULL; - int ret; - ssize_t count = 0; - bool data_valid = false; - u8 r, c; + char *p; - cts_info("compensate_cap_show"); + memcpy(cmdline_param, buf, min((size_t) MAX_ARG_LENGTH, count)); + cmdline_param[count] = '\0'; - cts_lock_device(cts_dev); - ret = cts_enable_get_compensate_cap(cts_dev); - if (ret) { - count = sprintf(buf, "Enable get compensate cap failed %d\n", ret); - goto unlock_device; - } + argc = 0; + p = strim(cmdline_param); + if (p == NULL || p[0] == '\0') { + return 0; + } - cap = kzalloc(cts_dev->hwdata->num_row * cts_dev->hwdata->num_col, GFP_KERNEL); - if (cap == NULL) { - count = sprintf(buf, "Allocate mem for cap failed\n"); - goto unlock_device; - } + while (p && p[0] != '\0' && argc < MAX_ARG_NUM) { + argv[argc++] = strsep(&p, " ,"); + } - ret = cts_get_compensate_cap(cts_dev, cap); - if (ret) { - count = sprintf(buf, "Get compensate cap failed %d\n", ret); - goto unlock_device; - } - - ret = cts_disable_get_compensate_cap(cts_dev); - if (ret) { - count = sprintf(buf, "Disable get compensate cap failed %d\n", ret); - goto unlock_device; - } - - data_valid = true; -unlock_device: - cts_unlock_device(cts_dev); - - if (data_valid) { - count += sprintf(buf + count, SPLIT_LINE_STR " "); - - for (c = 0; c < cts_dev->fwdata.cols; c++) { - count += sprintf(buf + count, COL_NUM_FORMAT_STR, c); - } - count += sprintf(buf + count, "\n" SPLIT_LINE_STR); - - for (r = 0; r < cts_dev->fwdata.rows; r++) { - count += sprintf(buf + count, ROW_NUM_FORMAT_STR, r); - for (c = 0; c < cts_dev->fwdata.cols; c++) { - count += snprintf(buf + count, PAGE_SIZE - count, - DATA_FORMAT_STR, cap[r * cts_dev->fwdata.cols + c]); - } - buf[count++] = '\n'; - } - } - - if (cap) { - kfree(cap); - } - return count; + return argc; } -static DEVICE_ATTR(compensate_cap, S_IRUGO, compensate_cap_show, NULL); - -#ifdef CFG_CTS_HAS_RESET_PIN -static ssize_t reset_pin_show(struct device *dev, - struct device_attribute *attr, char *buf) + +/* echo addr value1 value2 value3 ... valueN > write_reg */ +static ssize_t write_firmware_register_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + u16 addr; + int i, ret; + u8 *data = NULL; - cts_info("Read RESET-PIN"); + parse_arg(buf, count); - return snprintf(buf, PAGE_SIZE, - "Reset pin: %d, status: %d\n", - cts_data->pdata->rst_gpio, - gpio_get_value(cts_data->pdata->rst_gpio)); + cts_info("Write firmware register '%.*s'", (int)count, buf); + + if (argc < 2) { + cts_err("Too few args %d", argc); + return -EFAULT; + } + + ret = kstrtou16(argv[0], 0, &addr); + if (ret) { + cts_err("Invalid address %s", argv[0]); + return -EINVAL; + } + + data = (u8 *) kmalloc(argc - 1, GFP_KERNEL); + if (data == NULL) { + cts_err("Allocate buffer for write data failed\n"); + return -ENOMEM; + } + + for (i = 1; i < argc; i++) { + ret = kstrtou8(argv[i], 0, data + i - 1); + if (ret) { + cts_err("Invalid value %s", argv[i]); + goto free_data; + } + } + + ret = cts_fw_reg_writesb(cts_dev, addr, data, argc - 1); + if (ret) { + cts_err("Write firmware register addr: 0x%04x size: %d failed", + addr, argc - 1); + goto free_data; + } + +free_data: + kfree(data); + + return (ret < 0 ? ret : count); +} + +#ifdef CFG_CTS_FW_UPDATE_SYS +/* +static ssize_t drv_irq_show( + struct device *dev, struct device_attribute *attr, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%s\n", + cts_data->irq_disabled? "DISABLED" : "ENABLED"); +} + +static ssize_t drv_irq_store( + struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct input_dev *input_dev = cts_data->input_dev; + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + + //TBD. + cts_lock_device(dev); + if (buf[0] == '1') { + cts_info("drv_irq_store: enable irq"); + cts_plat_enable_irq(); + } else if (buf[0] == '0') { + cts_info("drv_irq_store: disable irq"); + ret = cts_plat_disable_irq(cts_data->cts_dev->pdata); + if (ret < 0) { + cts_err("Disable IRQ failed %d", ret); + return ret; + } + } + cts_unlock_device(dev); + return count; +} + +static ssize_t reset_store( + struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + if ('1' != buf[0]) { + pr_err("Invalid argument for reset\n"); + return -EINVAL; + } + + cts_lock_device(dev); + //TBD + //cts_reset_proc(); + cts_unlock_device(dev); + + return count; +} +*/ + +static ssize_t cts_panel_supplier_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *data = dev_get_drvdata(dev); + + if (data->pdata && data->pdata->panel_supplier) { + return scnprintf(buf, PAGE_SIZE, "%s\n", + data->pdata->panel_supplier); + } + return 0; +} + +static ssize_t buildid_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "0000-%04x\n", + cts_data->cts_dev.fwdata.version); +} + +static ssize_t forcereflash_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + unsigned int input; + + if (kstrtouint(buf, 10, &input) != 0) + return -EINVAL; + + cts_data->force_reflash = (input == 0) ? false : true; + + cts_info("forcereflash_store force_reflash=%d, count=%zu", + cts_data->force_reflash, count); + return count; +} + +static ssize_t flashprog_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%d\n", + cts_is_firmware_updating(&cts_data->cts_dev) ? 1 : 0); +} + +static bool is_reflash_filename_valid(const struct chipone_ts_data *cts_data, + const char *filename) +{ + char prefix[CFG_CTS_FW_FILE_NAME_MAX_LEN]; + + if(NULL != cts_data->pdata->panel_supplier) { + snprintf(prefix, sizeof(prefix), "%s-%s-%s-", + CFG_CTS_FW_FILE_NAME_VENDOR, + cts_data->pdata->panel_supplier, + cts_data->cts_dev.hwdata->name); + } else { + // panel supplier not set, just check vendor. + snprintf(prefix, sizeof(prefix), "%s", + CFG_CTS_FW_FILE_NAME_VENDOR); + } + + cts_info("is_reflash_filename_valid: prefix=%s", prefix); + if (strncmp(filename, prefix, strlen(prefix))) { + cts_err("is_reflash_filename_valid: invalid FW file."); + return false; + } + + return true; +} + +static ssize_t doreflash_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + int ret; + + cts_info("doreflash FW filename: %s len: %zu", buf, count); + + if (count > CFG_CTS_FW_FILE_NAME_MAX_LEN) { + cts_err("doreflash FW filename is too long %zu > %d", + count, CFG_CTS_FW_FILE_NAME_MAX_LEN); + return -EINVAL; + } + + if (cts_is_device_suspended(&cts_data->cts_dev)) { + cts_err("In suspend state, try again later"); + return -EAGAIN; + } + + if (cts_is_firmware_updating(&cts_data->cts_dev)) { + cts_err("In FW flashing state, try again later"); + return -EAGAIN; + } + + if (!cts_data->force_reflash) { + /* Check filename if force_reflash is false */ + if (!is_reflash_filename_valid(cts_data, buf)) { + cts_err("Invalid firmware filename '%*.s'", + (int)count, buf); + return -EINVAL; + } + } + + strncpy(cts_data->cts_dev.config_fw_name, buf, count); + + /* If use echo xxx > doreflash, 0x0A will append to the string, + if use echo -n xxx > doreflash, nothing will append. */ + if (cts_data->cts_dev.config_fw_name[count - 1] == '\n') { + cts_data->cts_dev.config_fw_name[count - 1] = '\0'; + } else { + cts_data->cts_dev.config_fw_name[count] = '\0'; + } + + cts_stop_device(&cts_data->cts_dev); + + cts_lock_device(&cts_data->cts_dev); + ret = cts_update_firmware_from_file(&cts_data->cts_dev, + cts_data->cts_dev.config_fw_name, + false); + cts_unlock_device(&cts_data->cts_dev); + + if (ret) { + cts_err("Update firmware from file '%s' failed %d", + cts_data->cts_dev.config_fw_name, ret); + } + + cts_start_device(&cts_data->cts_dev); + + cts_data->force_reflash = false; + + cts_info("doreflash_store: end"); + + return ret ? ret : count; +} + +static ssize_t cts_poweron_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + bool val; + + //TBD: check if cts is power to ready for flash. set "1" if power on ready. + val = cts_is_device_suspended(&cts_data->cts_dev); + return scnprintf(buf, PAGE_SIZE, "%d\n", val == false); +} + +static ssize_t cts_productinfo_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + //set chip IC type to productinfo + return scnprintf(buf, PAGE_SIZE, "%s\n", + cts_data->cts_dev.hwdata->name); +} + +//add sys entries for FW update +//static DEVICE_ATTR(drv_irq, S_IRUGO | S_IWUSR, drv_irq_show, drv_irq_store); +//static DEVICE_ATTR(reset, S_IWUSR | S_IWGRP, NULL, reset_store); +static DEVICE_ATTR(panel_supplier, 0444, cts_panel_supplier_show, NULL); +static DEVICE_ATTR(buildid, S_IRUGO, buildid_show, NULL); +static DEVICE_ATTR(forcereflash, S_IWUSR | S_IWGRP, NULL, forcereflash_store); +static DEVICE_ATTR(flashprog, S_IRUGO, flashprog_show, NULL); +static DEVICE_ATTR(doreflash, S_IWUSR | S_IWGRP, NULL, doreflash_store); +static DEVICE_ATTR(poweron, S_IRUGO, cts_poweron_show, NULL); +static DEVICE_ATTR(productinfo, S_IRUGO, cts_productinfo_show, NULL); +#endif + +static DEVICE_ATTR(write_reg, S_IWUSR, NULL, write_firmware_register_store); + +static ssize_t read_firmware_register_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ +#define PRINT_ROW_SIZE (16) + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + u16 addr, size, i, remaining; + u8 *data = NULL; + ssize_t count = 0; + int ret; + + cts_info("Read firmware register "); + + if (argc != 2) { + return snprintf(buf, PAGE_SIZE, + "Invalid num args %d\n" + " 1. echo addr size > read_reg\n" + " 2. cat read_reg\n", argc); + } + + ret = kstrtou16(argv[0], 0, &addr); + if (ret) { + return snprintf(buf, PAGE_SIZE, "Invalid address: %s\n", + argv[0]); + } + ret = kstrtou16(argv[1], 0, &size); + if (ret) { + return snprintf(buf, PAGE_SIZE, "Invalid size: %s\n", argv[1]); + } + + data = (u8 *) kmalloc(size, GFP_KERNEL); + if (data == NULL) { + return snprintf(buf, PAGE_SIZE, + "Allocate buffer for read data failed\n"); + } + + cts_info("Read firmware register from 0x%04x size %u", addr, size); + cts_lock_device(cts_dev); + ret = cts_fw_reg_readsb(cts_dev, addr, data, (size_t) size); + cts_unlock_device(cts_dev); + if (ret) { + count = snprintf(buf, PAGE_SIZE, + "Read firmware register from 0x%04x size %u failed %d\n", + addr, size, ret); + goto err_free_data; + } + + remaining = size; + for (i = 0; i < size && count <= PAGE_SIZE; i += PRINT_ROW_SIZE) { + size_t linelen = + min((size_t) remaining, (size_t) PRINT_ROW_SIZE); + remaining -= PRINT_ROW_SIZE; + + count += + snprintf(buf + count, PAGE_SIZE - count, "%04x: ", addr); + + /* Lower version kernel return void */ + hex_dump_to_buffer(data + i, linelen, PRINT_ROW_SIZE, 1, + buf + count, PAGE_SIZE - count, true); + count += strlen(buf + count); + + if (count < PAGE_SIZE) { + buf[count++] = '\n'; + addr += PRINT_ROW_SIZE; + } else { + break; + } + } + +err_free_data: + kfree(data); + + return count; +#undef PRINT_ROW_SIZE +} + +/* echo addr size > read_reg */ +static ssize_t read_firmware_register_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + parse_arg(buf, count); + + return (argc == 0 ? 0 : count); +} + +static DEVICE_ATTR(read_reg, S_IWUSR | S_IRUSR, + read_firmware_register_show, read_firmware_register_store); + +static ssize_t read_hw_reg_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ +#define PRINT_ROW_SIZE (16) + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + u32 addr, size, i, remaining; + u8 *data = NULL; + ssize_t count = 0; + int ret; + + cts_info("Read hw register"); + + if (argc != 2) { + return snprintf(buf, PAGE_SIZE, + "Invalid num args %d\n" + " 1. echo addr size > read_hw_reg\n" + " 2. cat read_hw_reg\n", argc); + } + + ret = kstrtou32(argv[0], 0, &addr); + if (ret) { + return snprintf(buf, PAGE_SIZE, "Invalid address: %s\n", + argv[0]); + } + ret = kstrtou32(argv[1], 0, &size); + if (ret) { + return snprintf(buf, PAGE_SIZE, "Invalid size: %s\n", argv[1]); + } + + data = (u8 *) kmalloc(size, GFP_KERNEL); + if (data == NULL) { + return snprintf(buf, PAGE_SIZE, + "Allocate buffer for read data failed\n"); + } + + cts_info("Read hw register from 0x%04x size %u", addr, size); + cts_lock_device(cts_dev); + + for (i = 0; i < size; i++) { + ret = + cts_fw_reg_writel_retry(cts_dev, HW_STUB_ADDR, addr + i, 3, + 10); + if (ret) { + count = + snprintf(buf, PAGE_SIZE, + "Write hw register error\n"); + goto err_free_data; + } + + ret = cts_fw_reg_readsb(cts_dev, HW_STUB_ADDR + 4, data + i, 1); + if (ret) { + count = + snprintf(buf, PAGE_SIZE, + "Read hw register error\n"); + goto err_free_data; + } + } + remaining = size; + for (i = 0; i < size && count <= PAGE_SIZE; i += PRINT_ROW_SIZE) { + size_t linelen = + min((size_t) remaining, (size_t) PRINT_ROW_SIZE); + remaining -= PRINT_ROW_SIZE; + + count += + snprintf(buf + count, PAGE_SIZE - count, "%04x: ", addr); + + /* Lower version kernel return void */ + hex_dump_to_buffer(data + i, linelen, PRINT_ROW_SIZE, 1, + buf + count, PAGE_SIZE - count, true); + count += strlen(buf + count); + + if (count < PAGE_SIZE) { + buf[count++] = '\n'; + addr += PRINT_ROW_SIZE; + } else { + break; + } + } + +err_free_data: + cts_unlock_device(cts_dev); + kfree(data); + + return count; +#undef PRINT_ROW_SIZE +} + +/* echo addr size > read_reg */ +static ssize_t read_hw_reg_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + parse_arg(buf, count); + + return (argc == 0 ? 0 : count); +} + +static DEVICE_ATTR(read_hw_reg, S_IRUSR | S_IWUSR, read_hw_reg_show, + read_hw_reg_store); + +static ssize_t write_hw_reg_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + u32 addr; + int i, ret; + u8 *data = NULL; + + parse_arg(buf, count); + + cts_info("Write hw register"); + + if (argc < 2) { + cts_err("Too few args %d", argc); + return -EFAULT; + } + + ret = kstrtou32(argv[0], 0, &addr); + if (ret) { + cts_err("Invalid address %s", argv[0]); + return -EINVAL; + } + + data = (u8 *) kmalloc(argc - 1, GFP_KERNEL); + if (data == NULL) { + cts_err("Allocate buffer for write data failed\n"); + return -ENOMEM; + } + + for (i = 1; i < argc; i++) { + ret = kstrtou8(argv[i], 0, data + i - 1); + if (ret) { + cts_err("Invalid value %s", argv[i]); + goto free_data; + } + } + + cts_lock_device(cts_dev); + for (i = 0; i < argc - 1; i++) { + ret = + cts_fw_reg_writel_retry(cts_dev, HW_STUB_ADDR, addr + i, 3, + 10); + if (ret) { + cts_err("Write hw register error"); + break; + } + ret = + cts_fw_reg_writeb_retry(cts_dev, HW_STUB_ADDR + 4, data[i], + 3, 10); + if (ret) { + cts_err("Write hw register error"); + break; + } + } + cts_unlock_device(cts_dev); +free_data: + kfree(data); + + return (ret < 0 ? ret : count); +} + +static DEVICE_ATTR(write_hw_reg, S_IWUSR, NULL, write_hw_reg_store); + +static ssize_t curr_firmware_version_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "Current firmware version: %04x\n", + cts_data->cts_dev.fwdata.version); +} + +static DEVICE_ATTR(curr_version, S_IRUGO, curr_firmware_version_show, NULL); + +static ssize_t curr_ddi_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "Current ddi version: %02x\n", + cts_data->cts_dev.fwdata.ddi_version); +} + +static DEVICE_ATTR(curr_ddi_version, S_IRUGO, curr_ddi_version_show, NULL); + +static ssize_t rows_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "Num rows: %u\n", + cts_data->cts_dev.fwdata.rows); +} + +static DEVICE_ATTR(rows, S_IRUGO, rows_show, NULL); + +static ssize_t cols_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "Num cols: %u\n", + cts_data->cts_dev.fwdata.cols); +} + +static DEVICE_ATTR(cols, S_IRUGO, cols_show, NULL); + +static ssize_t res_x_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "X Resolution: %u\n", + cts_data->cts_dev.fwdata.res_x); +} + +static DEVICE_ATTR(res_x, S_IRUGO, res_x_show, NULL); + +static ssize_t res_y_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "Y Resolution: %u\n", + cts_data->cts_dev.fwdata.res_y); +} + +static DEVICE_ATTR(res_y, S_IRUGO, res_y_show, NULL); + +static ssize_t esd_protection_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + int ret; + u8 esd_protection; + + cts_lock_device(cts_dev); + ret = + cts_fw_reg_readb(&cts_data->cts_dev, 0x8000 + 342, &esd_protection); + cts_unlock_device(cts_dev); + if (ret) { + return snprintf(buf, PAGE_SIZE, + "Read firmware ESD protection register failed %d\n", + ret); + } + + return snprintf(buf, PAGE_SIZE, "ESD protection: %u\n", esd_protection); +} + +static DEVICE_ATTR(esd_protection, S_IRUGO, esd_protection_show, NULL); + +static ssize_t monitor_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + int ret; + u8 value; + + cts_lock_device(cts_dev); + ret = cts_fw_reg_readb(&cts_data->cts_dev, 0x8000 + 344, &value); + cts_unlock_device(cts_dev); + if (ret) { + return snprintf(buf, PAGE_SIZE, + "Read firmware monitor enable register failed %d\n", + ret); + } + + return snprintf(buf, PAGE_SIZE, "Monitor mode: %s\n", + value & BIT(0) ? "Enable" : "Disable"); +} + +static ssize_t monitor_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + int ret; + u8 value, enable = 0; + + if (buf[0] == 'Y' || buf[0] == 'y' || buf[0] == '1') { + enable = 1; + } + + cts_info("Write firmware monitor mode to '%c', %s", + buf[0], enable ? "Enable" : "Disable"); + + cts_lock_device(cts_dev); + ret = cts_fw_reg_readb(&cts_data->cts_dev, 0x8000 + 344, &value); + cts_unlock_device(cts_dev); + if (ret) { + cts_err("Write firmware monitor enable register failed %d", + ret); + return -EIO; + } + + if ((value & BIT(0)) && enable) { + cts_info("Monitor mode already enabled"); + } else if ((value & BIT(0)) == 0 && enable == 0) { + cts_info("Monitor mode already disabled"); + } else { + if (enable) { + value |= BIT(0); + } else { + value &= ~BIT(0); + } + + cts_lock_device(cts_dev); + ret = + cts_fw_reg_writeb(&cts_data->cts_dev, 0x8000 + 344, value); + cts_unlock_device(cts_dev); + if (ret) { + cts_err + ("Write firmware monitor enable register failed %d", + ret); + return -EIO; + } + } + + return count; +} + +static DEVICE_ATTR(monitor_mode, S_IRUGO, monitor_mode_show, + monitor_mode_store); + +static ssize_t auto_compensate_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + int ret; + u8 value; + + cts_lock_device(cts_dev); + ret = cts_fw_reg_readb(&cts_data->cts_dev, 0x8000 + 276, &value); + cts_unlock_device(cts_dev); + if (ret) { + return snprintf(buf, PAGE_SIZE, + "Read auto compensate enable register failed %d\n", + ret); + } + + return snprintf(buf, PAGE_SIZE, "Auto compensate: %s\n", + value ? "Enable" : "Disable"); +} + +static DEVICE_ATTR(auto_compensate, S_IRUGO, auto_compensate_show, NULL); + +#ifdef CFG_CTS_DRIVER_BUILTIN_FIRMWARE +static ssize_t driver_builtin_firmware_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int i, count = 0; + + count += snprintf(buf + count, PAGE_SIZE - count, + "Total %d builtin firmware:\n", + cts_get_num_driver_builtin_firmware()); + + for (i = 0; i < cts_get_num_driver_builtin_firmware(); i++) { + const struct cts_firmware *firmware = + cts_request_driver_builtin_firmware_by_index(i); + if (firmware) { + count += snprintf(buf + count, PAGE_SIZE - count, + "%-2d: hwid: %04x fwid: %04x ver: %04x size: %6zu desc: %s\n", + i, firmware->hwid, firmware->fwid, + FIRMWARE_VERSION(firmware), + firmware->size, firmware->name); + } else { + count += snprintf(buf + count, PAGE_SIZE - count, + "%-2d: INVALID\n", i); + } + } + + return count; +} + +/* echo index/name [flash/sram] > driver_builtin_firmware */ +static ssize_t driver_builtin_firmware_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + const struct cts_firmware *firmware; + bool to_flash = true; + int ret, index = -1; + + parse_arg(buf, count); + + if (argc != 1 && argc != 2) { + cts_err("Invalid num args %d\n" + " echo index/name [flash/sram] > driver_builtin_firmware\n", + argc); + return -EFAULT; + } + + if (isdigit(*argv[0])) { + index = simple_strtoul(argv[0], NULL, 0); + } + + if (argc > 1) { + if (strncasecmp(argv[1], "flash", 5) == 0) { + to_flash = true; + } else if (strncasecmp(argv[1], "sram", 4) == 0) { + to_flash = false; + } else { + cts_err + ("Invalid location '%s', must be 'flash' or 'sram'", + argv[1]); + return -EINVAL; + } + } + + cts_info("Update driver builtin firmware '%s' to %s", + argv[1], to_flash ? "flash" : "sram"); + + if (index >= 0 && index < cts_get_num_driver_builtin_firmware()) { + firmware = cts_request_driver_builtin_firmware_by_index(index); + } else { + firmware = cts_request_driver_builtin_firmware_by_name(argv[0]); + } + + if (firmware) { + ret = cts_stop_device(cts_dev); + if (ret) { + cts_err("Stop device failed %d", ret); + return ret; + } + + cts_lock_device(cts_dev); + ret = cts_update_firmware(cts_dev, firmware, to_flash); + cts_unlock_device(cts_dev); + + if (ret) { + cts_err("Update firmware failed %d", ret); + goto err_start_device; + } + + ret = cts_start_device(cts_dev); + if (ret) { + cts_err("Start device failed %d", ret); + return ret; + } + } else { + cts_err("Firmware '%s' NOT found", argv[0]); + return -ENOENT; + } + + return count; + +err_start_device: + cts_start_device(cts_dev); + + return ret; +} + +static DEVICE_ATTR(driver_builtin_firmware, S_IWUSR | S_IRUGO, + driver_builtin_firmware_show, driver_builtin_firmware_store); +#endif /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */ + +#ifdef CFG_CTS_FIRMWARE_IN_FS +/* echo filepath [flash/sram] > update_firmware_from_file */ +static ssize_t update_firmware_from_file_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + const struct cts_firmware *firmware; + bool to_flash = true; + int ret; + // int index; + + parse_arg(buf, count); + + if (argc > 2) { + cts_err("Invalid num args %d\n" + " echo filepath [flash/sram] > update_from_file\n", + argc); + return -EFAULT; + } else if (argc > 1) { + if (strncasecmp(argv[1], "flash", 5) == 0) { + to_flash = true; + } else if (strncasecmp(argv[1], "sram", 4) == 0) { + to_flash = false; + } else { + cts_err + ("Invalid location '%s', must be 'flash' or 'sram'", + argv[1]); + return -EINVAL; + } + } + + cts_info("Update firmware from file '%s'", argv[0]); + + firmware = cts_request_firmware_from_fs(cts_dev, argv[0]); + if (firmware == NULL) { + cts_err("Request firmware from file '%s' failed", argv[0]); + return -ENOENT; + } + + ret = cts_stop_device(cts_dev); + if (ret) { + cts_err("Stop device failed %d", ret); + goto err_release_firmware; + } + + cts_lock_device(cts_dev); + ret = cts_update_firmware(cts_dev, firmware, to_flash); + cts_unlock_device(cts_dev); + + if (ret) { + cts_err("Update firmware failed %d", ret); + goto err_release_firmware; + } + + ret = cts_start_device(cts_dev); + if (ret) { + cts_err("Start device failed %d", ret); + goto err_release_firmware; + } + + return count; + +err_release_firmware: + cts_release_firmware(firmware); + + return ret; +} + +static DEVICE_ATTR(update_from_file, S_IWUSR, NULL, + update_firmware_from_file_store); +#endif /* CFG_CTS_FIRMWARE_IN_FS */ + +static ssize_t updating_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "Updating: %s\n", + cts_data->cts_dev.rtdata.updating ? "Y" : "N"); +} + +static DEVICE_ATTR(updating, S_IRUGO, updating_show, NULL); + +static struct attribute *cts_dev_firmware_atts[] = { + &dev_attr_curr_version.attr, + &dev_attr_curr_ddi_version.attr, + &dev_attr_rows.attr, + &dev_attr_cols.attr, + &dev_attr_res_x.attr, + &dev_attr_res_y.attr, + &dev_attr_esd_protection.attr, + &dev_attr_monitor_mode.attr, + &dev_attr_auto_compensate.attr, +#ifdef CFG_CTS_DRIVER_BUILTIN_FIRMWARE + &dev_attr_driver_builtin_firmware.attr, +#endif /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */ +#ifdef CFG_CTS_FIRMWARE_IN_FS + &dev_attr_update_from_file.attr, +#endif /* CFG_CTS_FIRMWARE_IN_FS */ + &dev_attr_updating.attr, + NULL +}; + +static const struct attribute_group cts_dev_firmware_attr_group = { + .name = "cts_firmware", + .attrs = cts_dev_firmware_atts, +}; + +static ssize_t flash_info_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + const struct cts_flash *flash; + + if (cts_dev->flash == NULL) { + bool program_mode; + bool enabled; + int ret; + + program_mode = cts_is_device_program_mode(cts_dev); + enabled = cts_is_device_enabled(cts_dev); + + ret = cts_prepare_flash_operation(cts_dev); + if (ret) { + return snprintf(buf, PAGE_SIZE, + "Prepare flash operation failed %d", + ret); + } + + cts_post_flash_operation(cts_dev); + + if (!program_mode) { + ret = cts_enter_normal_mode(cts_dev); + if (ret) { + return snprintf(buf, PAGE_SIZE, + "Enter normal mode failed %d", + ret); + } + } + + if (enabled) { + ret = cts_start_device(cts_dev); + if (ret) { + return snprintf(buf, PAGE_SIZE, + "Start device failed %d", ret); + } + } + + if (cts_dev->flash == NULL) { + return snprintf(buf, PAGE_SIZE, "Flash not found\n"); + } + } + + flash = cts_dev->flash; + return snprintf(buf, PAGE_SIZE, + "%s:\n" + " JEDEC ID : %06X\n" + " Page size : 0x%zx\n" + " Sector size: 0x%zx\n" + " Block size : 0x%zx\n" + " Total size : 0x%zx\n", + flash->name, flash->jedec_id, flash->page_size, + flash->sector_size, flash->block_size, + flash->total_size); +} + +static DEVICE_ATTR(info, S_IRUGO, flash_info_show, NULL); + +static ssize_t read_flash_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + u32 flash_addr, size, i, remaining; + u8 *data = NULL; + ssize_t count = 0; + int ret; + bool program_mode; + bool enabled; + loff_t pos = 0; + + if (argc != 2 && argc != 3) { + return snprintf(buf, PAGE_SIZE, "Invalid num args %d\n", argc); + } + + ret = kstrtou32(argv[0], 0, &flash_addr); + if (ret) { + return snprintf(buf, PAGE_SIZE, "Invalid flash addr: %s\n", + argv[0]); + } + ret = kstrtou32(argv[1], 0, &size); + if (ret) { + return snprintf(buf, PAGE_SIZE, "Invalid size: %s\n", argv[1]); + } + + data = (u8 *) kmalloc(size, GFP_KERNEL); + if (data == NULL) { + return snprintf(buf, PAGE_SIZE, + "Allocate buffer for read data failed\n"); + } + + cts_info("Read flash from 0x%06x size %u%s%s", + flash_addr, size, argc == 3 ? " to file " : "", + argc == 3 ? argv[2] : ""); + + cts_lock_device(cts_dev); + program_mode = cts_is_device_program_mode(cts_dev); + enabled = cts_is_device_enabled(cts_dev); + + ret = cts_prepare_flash_operation(cts_dev); + if (ret) { + count += + snprintf(buf, PAGE_SIZE, + "Prepare flash operation failed %d", ret); + goto err_free_data; + } + + ret = cts_read_flash(cts_dev, flash_addr, data, size); + if (ret) { + count = + snprintf(buf, PAGE_SIZE, "Read flash data failed %d\n", + ret); + goto err_post_flash_operation; + } + + if (argc == 3) { + struct file *file; + + cts_info("Write flash data to file '%s'", argv[2]); + + file = filp_open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0666); + if (IS_ERR(file)) { + count += + snprintf(buf, PAGE_SIZE, + "Open file '%s' failed %ld", argv[2], + PTR_ERR(file)); + goto err_post_flash_operation; + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) + ret = kernel_write(file, data, size, &pos); +#else + ret = kernel_write(file, data, size, pos); +#endif + if (ret != size) { + count += + snprintf(buf, PAGE_SIZE, + "Write flash data to file '%s' failed %d", + argv[2], ret); + } + + ret = filp_close(file, NULL); + if (ret) { + count += + snprintf(buf, PAGE_SIZE, + "Close file '%s' failed %d", argv[2], ret); + } + } else { +#define PRINT_ROW_SIZE (16) + remaining = size; + for (i = 0; i < size && count <= PAGE_SIZE; i += PRINT_ROW_SIZE) { + size_t linelen = + min((size_t) remaining, (size_t) PRINT_ROW_SIZE); + remaining -= PRINT_ROW_SIZE; + + count += snprintf(buf + count, PAGE_SIZE - count - 1, + "%04x-%04x: ", flash_addr >> 16, + flash_addr & 0xFFFF); + /* Lower version kernel return void */ + hex_dump_to_buffer(data + i, linelen, PRINT_ROW_SIZE, 1, + buf + count, PAGE_SIZE - count - 1, + true); + count += strlen(buf + count); + buf[count++] = '\n'; + flash_addr += linelen; +#undef PRINT_ROW_SIZE + } + } + +err_post_flash_operation: + cts_post_flash_operation(cts_dev); + + if (!program_mode) { + int r = cts_enter_normal_mode(cts_dev); + if (r) { + count += + snprintf(buf, PAGE_SIZE, + "Enter normal mode failed %d", r); + } + } + + if (enabled) { + int r = cts_start_device(cts_dev); + if (r) { + cts_unlock_device(cts_dev); + return snprintf(buf, PAGE_SIZE, + "Start device failed %d", r); + } + } +err_free_data: + cts_unlock_device(cts_dev); + kfree(data); + + return (ret < 0 ? ret : count); +} + +/* echo start_addr size [filepath] > read */ +static ssize_t read_flash_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + parse_arg(buf, count); + + return count; +} + +static DEVICE_ATTR(read, S_IWUSR | S_IRUGO, read_flash_show, read_flash_store); + +/* echo addr size > erase */ +static ssize_t erase_flash_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + u32 flash_addr, size; + int ret; + bool program_mode; + bool enabled; + + parse_arg(buf, count); + + if (argc != 2) { + cts_err("Invalid num args %d", argc); + return -EFAULT; + } + + ret = kstrtou32(argv[0], 0, &flash_addr); + if (ret) { + cts_err("Invalid flash addr: %s", argv[0]); + return -EINVAL; + } + ret = kstrtou32(argv[1], 0, &size); + if (ret) { + cts_err("Invalid size: %s", argv[1]); + return -EINVAL; + } + + cts_info("Erase flash from 0x%06x size %u", flash_addr, size); + + cts_lock_device(cts_dev); + program_mode = cts_is_device_program_mode(cts_dev); + enabled = cts_is_device_enabled(cts_dev); + + ret = cts_prepare_flash_operation(cts_dev); + if (ret) { + cts_err("Prepare flash operation failed %d", ret); + cts_unlock_device(cts_dev); + return ret; + } + + ret = cts_erase_flash(cts_dev, flash_addr, size); + if (ret) { + cts_err("Erase flash from 0x%06x size %u failed %d", + flash_addr, size, ret); + goto err_post_flash_operation; + } + +err_post_flash_operation: + cts_post_flash_operation(cts_dev); + + if (!program_mode) { + int r = cts_enter_normal_mode(cts_dev); + if (r) { + cts_err("Enter normal mode failed %d", r); + } + } + + if (enabled) { + int r = cts_start_device(cts_dev); + if (r) { + cts_err("Start device failed %d", r); + } + } + cts_unlock_device(cts_dev); + + return (ret < 0 ? ret : count); +} + +static DEVICE_ATTR(erase, S_IWUSR, NULL, erase_flash_store); + +static struct attribute *cts_dev_flash_attrs[] = { + &dev_attr_info.attr, + &dev_attr_read.attr, + &dev_attr_erase.attr, + + NULL +}; + +static const struct attribute_group cts_dev_flash_attr_group = { + .name = "flash", + .attrs = cts_dev_flash_attrs, +}; + +static ssize_t open_test_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + u16 threshold; + int ret; + + if (argc != 1) { + return snprintf(buf, PAGE_SIZE, "Invalid num args %d\n", argc); + } + + ret = kstrtou16(argv[0], 0, &threshold); + if (ret) { + return snprintf(buf, PAGE_SIZE, "Invalid threshold: %s\n", + argv[0]); + } + + cts_info("Open test, threshold = %u", threshold); + + ret = cts_open_test(cts_dev, threshold); + if (ret) { + return snprintf(buf, PAGE_SIZE, + "Open test FAILED %d, threshold = %u\n", ret, + threshold); + } else { + return snprintf(buf, PAGE_SIZE, + "Open test PASSED, threshold = %u\n", + threshold); + } +} + +/* echo threshod > open_test */ +static ssize_t open_test_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + parse_arg(buf, count); + + return count; +} + +static DEVICE_ATTR(open_test, S_IWUSR | S_IRUGO, open_test_show, + open_test_store); + +static ssize_t short_test_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + u16 threshold; + int ret; + + if (argc != 1) { + return snprintf(buf, PAGE_SIZE, "Invalid num args %d\n", argc); + } + + ret = kstrtou16(argv[0], 0, &threshold); + if (ret) { + return snprintf(buf, PAGE_SIZE, "Invalid threshold: %s\n", + argv[0]); + } + + cts_info("Short test, threshold = %u", threshold); + + ret = cts_short_test(cts_dev, threshold); + if (ret) { + return snprintf(buf, PAGE_SIZE, + "Short test FAILED %d, threshold = %u\n", ret, + threshold); + } else { + return snprintf(buf, PAGE_SIZE, + "Short test PASSED, threshold = %u\n", + threshold); + } +} + +/* echo threshod > short_test */ +static ssize_t short_test_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + parse_arg(buf, count); + + return count; +} + +static DEVICE_ATTR(short_test, S_IWUSR | S_IRUGO, + short_test_show, short_test_store); + +static ssize_t testing_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "Testting: %s\n", + cts_data->cts_dev.rtdata.testing ? "Y" : "N"); +} + +static DEVICE_ATTR(testing, S_IRUGO, testing_show, NULL); + +#ifdef CFG_CTS_HAS_RESET_PIN +static ssize_t reset_test_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + int ret; + int count; + + ret = cts_reset_test(cts_dev); + if (ret == 0) { + count = snprintf(buf, PAGE_SIZE, "reset pin test sucessful\n"); + } else { + count = snprintf(buf, PAGE_SIZE, "reset pin test failed\n"); + } + + return count; +} + +static DEVICE_ATTR(reset_test, S_IRUGO, reset_test_show, NULL); +#endif + +static ssize_t compensate_cap_test_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + u8 min_thres, max_thres; + int ret; + + if (argc != 2) { + return snprintf(buf, PAGE_SIZE, "Invalid num args\n" + "USAGE:\n" + " 1. echo min max > compensate_cap_test\n" + " 2. cat compensate_cap_test\n"); + } + + ret = kstrtou8(argv[0], 0, &min_thres); + if (ret) { + return snprintf(buf, PAGE_SIZE, "Invalid min_thres: %s\n", + argv[0]); + } + + ret = kstrtou8(argv[1], 0, &max_thres); + if (ret) { + return snprintf(buf, PAGE_SIZE, "Invalid max_thres: %s\n", + argv[1]); + } + + cts_info("Compensate cap test, min_thres = %u, max_thres = %u", + min_thres, max_thres); + + ret = cts_compensate_cap_test(cts_dev, min_thres, max_thres); + if (ret) { + return snprintf(buf, PAGE_SIZE, + "Compensate cap test FAILED, min_thres = %u, max_thres=%u\n", + min_thres, max_thres); + } else { + return snprintf(buf, PAGE_SIZE, + "Compensate cap test PASSED, min_thres = %u, max_thres=%u\n", + min_thres, max_thres); + } +} + +/* echo threshod > short_test */ +static ssize_t compensate_cap_test_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + parse_arg(buf, count); + + return count; +} + +static DEVICE_ATTR(compensate_cap_test, S_IWUSR | S_IRUGO, + compensate_cap_test_show, compensate_cap_test_store); + +static ssize_t rawdata_test_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + u16 min_thres, max_thres; + int ret; + + if (argc != 2) { + return snprintf(buf, PAGE_SIZE, "Invalid num args\n" + "USAGE:\n" + " 1. echo min max > rawdata_test\n" + " 2. cat rawdata_test\n"); + } + + ret = kstrtou16(argv[0], 0, &min_thres); + if (ret) { + return snprintf(buf, PAGE_SIZE, "Invalid min_thres: %s\n", + argv[0]); + } + + ret = kstrtou16(argv[1], 0, &max_thres); + if (ret) { + return snprintf(buf, PAGE_SIZE, "Invalid max_thres: %s\n", + argv[1]); + } + + cts_info("Rawdata test, min_thres = %u, max_thres = %u", min_thres, + max_thres); + + ret = cts_rawdata_test(cts_dev, min_thres, max_thres); + if (ret) { + return snprintf(buf, PAGE_SIZE, + "Rawdata test FAILED, min_thres = %u, max_thres=%u\n", + min_thres, max_thres); + } else { + return snprintf(buf, PAGE_SIZE, + "Rawdata test PASSED, min_thres = %u, max_thres=%u\n", + min_thres, max_thres); + } +} + +/* echo threshod > short_test */ +static ssize_t rawdata_test_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + parse_arg(buf, count); + + return count; +} + +static DEVICE_ATTR(rawdata_test, S_IWUSR | S_IRUGO, + rawdata_test_show, rawdata_test_store); + +static struct attribute *cts_dev_test_atts[] = { + &dev_attr_open_test.attr, + &dev_attr_short_test.attr, + &dev_attr_testing.attr, +#ifdef CFG_CTS_HAS_RESET_PIN + &dev_attr_reset_test.attr, +#endif + &dev_attr_compensate_cap_test.attr, + &dev_attr_rawdata_test.attr, + NULL +}; + +static const struct attribute_group cts_dev_test_attr_group = { + .name = "test", + .attrs = cts_dev_test_atts, +}; + +static ssize_t ic_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "IC Type : %s\n", + cts_data->cts_dev.hwdata->name); +} + +static DEVICE_ATTR(ic_type, S_IRUGO, ic_type_show, NULL); + +static ssize_t program_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "Program mode: %s\n", + cts_data->cts_dev.rtdata.program_mode ? "Y" : "N"); +} + +static ssize_t program_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + int ret; + parse_arg(buf, count); + + if (argc != 1) { + cts_err("Invalid num args %d", argc); + return -EFAULT; + } + + if (*argv[0] == '1' || tolower(*argv[0]) == 'y') { + ret = cts_enter_program_mode(&cts_data->cts_dev); + if (ret) { + cts_err("Enter program mode failed %d", ret); + return ret; + } + } else if (*argv[0] == '0' || tolower(*argv[0]) == 'n') { + ret = cts_enter_normal_mode(&cts_data->cts_dev); + if (ret) { + cts_err("Exit program mode failed %d", ret); + return ret; + } + } else { + cts_err("Invalid args"); + } + + return count; +} + +static DEVICE_ATTR(program_mode, S_IWUSR | S_IRUGO, + program_mode_show, program_mode_store); + +static ssize_t rawdata_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ +#define RAWDATA_BUFFER_SIZE(cts_dev) \ + (cts_dev->fwdata.rows * cts_dev->fwdata.cols * 2) + + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + u16 *rawdata = NULL; + int ret, r, c, count = 0; + u32 max, min, sum, average; + int max_r, max_c, min_r, min_c; + bool data_valid = true; + + cts_info("Show rawdata"); + + rawdata = (u16 *) kmalloc(RAWDATA_BUFFER_SIZE(cts_dev), GFP_KERNEL); + if (rawdata == NULL) { + return snprintf(buf, PAGE_SIZE, + "Allocate memory for rawdata failed\n"); + } + + cts_lock_device(cts_dev); + ret = cts_enable_get_rawdata(cts_dev); + if (ret) { + count += + snprintf(buf, PAGE_SIZE, "Enable read raw data failed %d\n", + ret); + goto err_free_rawdata; + } + + ret = cts_send_command(cts_dev, CTS_CMD_QUIT_GESTURE_MONITOR); + if (ret) { + count += + snprintf(buf, PAGE_SIZE, + "Send cmd QUIT_GESTURE_MONITOR failed %d\n", ret); + goto err_free_rawdata; + } + msleep(50); + + ret = cts_get_rawdata(cts_dev, rawdata); + if (ret) { + count += + snprintf(buf, PAGE_SIZE, "Get raw data failed %d\n", ret); + data_valid = false; + // Fall through to disable get rawdata + } + ret = cts_disable_get_rawdata(cts_dev); + if (ret) { + count += + snprintf(buf, PAGE_SIZE, + "Disable read raw data failed %d\n", ret); + // Fall through to show rawdata + } + + if (data_valid) { + max = min = rawdata[0]; + sum = 0; + max_r = max_c = min_r = min_c = 0; + for (r = 0; r < cts_dev->fwdata.rows; r++) { + for (c = 0; c < cts_dev->fwdata.cols; c++) { + u16 val = rawdata[r * cts_dev->fwdata.cols + c]; + sum += val; + if (val > max) { + max = val; + max_r = r; + max_c = c; + } else if (val < min) { + min = val; + min_r = r; + min_c = c; + } + } + } + average = sum / (cts_dev->fwdata.rows * cts_dev->fwdata.cols); + + count += snprintf(buf + count, PAGE_SIZE - count, + SPLIT_LINE_STR + "Raw data MIN: [%d][%d]=%u, MAX: [%d][%d]=%u, AVG=%u\n" + SPLIT_LINE_STR + " | ", min_r, min_c, min, max_r, max_c, + max, average); + for (c = 0; c < cts_dev->fwdata.cols; c++) { + count += + snprintf(buf + count, PAGE_SIZE - count, + COL_NUM_FORMAT_STR, c); + } + count += + snprintf(buf + count, PAGE_SIZE - count, + "\n" SPLIT_LINE_STR); + + for (r = 0; r < cts_dev->fwdata.rows && count < PAGE_SIZE; r++) { + count += + snprintf(buf + count, PAGE_SIZE - count, + ROW_NUM_FORMAT_STR, r); + for (c = 0; + c < cts_dev->fwdata.cols && count < PAGE_SIZE; + c++) { + count += + snprintf(buf + count, PAGE_SIZE - count - 1, + DATA_FORMAT_STR, + rawdata[r * cts_dev->fwdata.cols + + c]); + } + buf[count++] = '\n'; + } + } + +err_free_rawdata: + cts_unlock_device(cts_dev); + kfree(rawdata); + + return data_valid ? count : ret; + +#undef RAWDATA_BUFFER_SIZE +} + +static DEVICE_ATTR(rawdata, S_IRUGO, rawdata_show, NULL); + +static ssize_t diffdata_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + s16 *diffdata = NULL; + int ret, r, c, count = 0; + int max, min, sum, average; + int max_r, max_c, min_r, min_c; + bool data_valid = true; + + cts_info("Show diffdata"); + + diffdata = (s16 *) kmalloc(DIFFDATA_BUFFER_SIZE(cts_dev), GFP_KERNEL); + if (diffdata == NULL) { + cts_err("Allocate memory for diffdata failed"); + return -ENOMEM; + } + + cts_lock_device(cts_dev); + ret = cts_enable_get_rawdata(cts_dev); + if (ret) { + cts_err("Enable read diff data failed %d", ret); + goto err_free_diffdata; + } + + ret = cts_send_command(cts_dev, CTS_CMD_QUIT_GESTURE_MONITOR); + if (ret) { + cts_err("Send cmd QUIT_GESTURE_MONITOR failed %d", ret); + goto err_free_diffdata; + } + msleep(50); + + ret = cts_get_diffdata(cts_dev, diffdata); + if (ret) { + cts_err("Get diff data failed %d", ret); + data_valid = false; + // Fall through to disable get diffdata + } + ret = cts_disable_get_rawdata(cts_dev); + if (ret) { + cts_err("Disable read diff data failed %d", ret); + // Fall through to show diffdata + } + + if (data_valid) { + max = min = diffdata[0]; + sum = 0; + max_r = max_c = min_r = min_c = 0; + for (r = 0; r < cts_dev->fwdata.rows; r++) { + for (c = 0; c < cts_dev->fwdata.cols; c++) { + s16 val = + diffdata[r * cts_dev->fwdata.cols + c]; + + sum += val; + if (val > max) { + max = val; + max_r = r; + max_c = c; + } else if (val < min) { + min = val; + min_r = r; + min_c = c; + } + } + } + average = sum / (cts_dev->fwdata.rows * cts_dev->fwdata.cols); + + count += snprintf(buf + count, PAGE_SIZE - count, + SPLIT_LINE_STR + "Diff data MIN: [%d][%d]=%d, MAX: [%d][%d]=%d, AVG=%d\n" + SPLIT_LINE_STR + " | ", min_r, min_c, min, max_r, max_c, + max, average); + for (c = 0; c < cts_dev->fwdata.cols; c++) { + count += + snprintf(buf + count, PAGE_SIZE - count, + COL_NUM_FORMAT_STR, c); + } + count += + snprintf(buf + count, PAGE_SIZE - count, + "\n" SPLIT_LINE_STR); + + for (r = 0; r < cts_dev->fwdata.rows; r++) { + count += + snprintf(buf + count, PAGE_SIZE - count, + ROW_NUM_FORMAT_STR, r); + for (c = 0; c < cts_dev->fwdata.cols; c++) { + count += + snprintf(buf + count, PAGE_SIZE - count, + DATA_FORMAT_STR, + diffdata[r * cts_dev->fwdata.cols + + c]); + } + buf[count++] = '\n'; + } + } + +err_free_diffdata: + cts_unlock_device(cts_dev); + kfree(diffdata); + + return data_valid ? count : ret; +} + +static DEVICE_ATTR(diffdata, S_IRUGO, diffdata_show, NULL); + +static ssize_t manualdiffdata_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + s16 *rawdata = NULL; + int ret, r, c, count = 0; + int max, min, sum, average; + int max_r, max_c, min_r, min_c; + bool data_valid = true; + int frame; + struct file *file = NULL; + int i; + loff_t pos = 0; + + cts_info("Show manualdiff"); + + if (argc != 1 && argc != 2) { + return snprintf(buf, PAGE_SIZE, "Invalid num args\n" + "USAGE:\n" + " 1. echo updatebase > manualdiff\n" + " 2. cat manualdiff\n" + " or\n" + " 1. echo updatebase > manualdiff\n" + " 2. echo frame file > manualdiff\n" + " 3. cat manualdiff\n"); + } + + if (argc == 2) { + ret = kstrtou32(argv[0], 0, &frame); + if (ret) { + return snprintf(buf, PAGE_SIZE, "Invalid frame num\n"); + } + file = filp_open(argv[1], O_RDWR | O_CREAT | O_TRUNC, 0666); + if (IS_ERR(file)) { + return snprintf(buf, PAGE_SIZE, "Can't open file:%s", + argv[1]); + } + } else { + frame = 1; + } + + rawdata = (s16 *) kmalloc(DIFFDATA_BUFFER_SIZE(cts_dev), GFP_KERNEL); + if (rawdata == NULL) { + cts_err("Allocate memory for rawdata failed"); + filp_close(file, NULL); + return -ENOMEM; + } + + cts_lock_device(cts_dev); + ret = cts_enable_get_rawdata(cts_dev); + if (ret) { + cts_err("Enable read raw data failed %d", ret); + goto err_free_diffdata; + } + + ret = cts_send_command(cts_dev, CTS_CMD_QUIT_GESTURE_MONITOR); + if (ret) { + cts_err("Send cmd QUIT_GESTURE_MONITOR failed %d", ret); + goto err_free_diffdata; + } + msleep(50); + + cts_info("frame %d, file:%s", frame, argv[1]); + for (i = 0; i < frame; i++) { + ret = cts_get_rawdata(cts_dev, rawdata); + if (ret) { + cts_err("Get raw data failed %d", ret); + data_valid = false; + } else { + data_valid = true; + } + msleep(50); + + if (data_valid) { + max = -32768; + min = 32767; + sum = 0; + max_r = max_c = min_r = min_c = 0; + for (r = 0; r < cts_dev->fwdata.rows; r++) { + for (c = 0; c < cts_dev->fwdata.cols; c++) { + s16 val; + + rawdata[r * cts_dev->fwdata.cols + c] -= + manualdiff_base[r * + cts_dev-> + fwdata.cols + c]; + val = + rawdata[r * cts_dev->fwdata.cols + + c]; + sum += val; + if (val > max) { + max = val; + max_r = r; + max_c = c; + } else if (val < min) { + min = val; + min_r = r; + min_c = c; + } + } + } + average = + sum / (cts_dev->fwdata.rows * cts_dev->fwdata.cols); + count += + snprintf(buf + count, PAGE_SIZE - count, + SPLIT_LINE_STR + "Manualdiff data MIN: [%d][%d]=%d, MAX: [%d][%d]=%d, AVG=%d\n" + SPLIT_LINE_STR " | ", min_r, min_c, min, + max_r, max_c, max, average); + for (c = 0; c < cts_dev->fwdata.cols; c++) { + count += + snprintf(buf + count, PAGE_SIZE - count, + COL_NUM_FORMAT_STR, c); + } + count += + snprintf(buf + count, PAGE_SIZE - count, + "\n" SPLIT_LINE_STR); + + for (r = 0; r < cts_dev->fwdata.rows; r++) { + count += + snprintf(buf + count, PAGE_SIZE - count, + ROW_NUM_FORMAT_STR, r); + for (c = 0; c < cts_dev->fwdata.cols; c++) { + count += + snprintf(buf + count, + PAGE_SIZE - count, + DATA_FORMAT_STR, + rawdata[r * + cts_dev-> + fwdata.cols + c]); + } + buf[count++] = '\n'; + } + //cts_info("manualdiffdata_show:%d, %d", i, frame); + if (argc == 2) { + pos = file->f_pos; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) + ret = kernel_write(file, buf, count, &pos); +#else + ret = kernel_write(file, buf, count, pos); +#endif + if (ret != count) { + cts_err + ("Write data to file '%s' failed %d", + argv[1], ret); + } + file->f_pos += count; + count = 0; + } + } + } + if (argc == 2) { + filp_close(file, NULL); + } + + ret = cts_disable_get_rawdata(cts_dev); + if (ret) { + cts_err("Disable read raw data failed %d", ret); + // Fall through to show diffdata + } + +err_free_diffdata: + cts_unlock_device(cts_dev); + kfree(rawdata); + + return data_valid ? count : ret; +} + +static ssize_t manualdiffdata_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + int ret; + + parse_arg(buf, count); + + cts_lock_device(cts_dev); + if (strncasecmp("updatebase", argv[0], 10) == 0) { + ret = cts_enable_get_rawdata(cts_dev); + if (ret) { + cts_err("Enable read raw data failed %d", ret); + goto err_manual_diff_store; + } + + ret = cts_send_command(cts_dev, CTS_CMD_QUIT_GESTURE_MONITOR); + if (ret) { + cts_err("Send cmd QUIT_GESTURE_MONITOR failed %d", ret); + goto err_manual_diff_store; + } + msleep(50); + + if (manualdiff_base != NULL) { + ret = cts_get_rawdata(cts_dev, manualdiff_base); + if (ret) { + cts_err("Get raw data failed %d", ret); + } + } + //cts_info("update base successful"); + ret = cts_disable_get_rawdata(cts_dev); + if (ret) { + cts_err("Disable read raw data failed %d", ret); + } + } +err_manual_diff_store: + cts_unlock_device(cts_dev); + return count; +} + +static DEVICE_ATTR(manualdiff, S_IRUSR | S_IWUSR, manualdiffdata_show, + manualdiffdata_store); + +static ssize_t jitter_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + u16 cnt; + int ret; + + parse_arg(buf, count); + + if (argc != 1) { + cts_err("Invalid num args %d", argc); + return -EFAULT; + } + + ret = kstrtou16(argv[0], 0, &cnt); + if (ret == 0) { + if (cnt > 2 || cnt < 10000) { + jitter_test_frame = cnt; + } + } + + cts_info("jitter test frame: %d", jitter_test_frame); + return count; +} + +static ssize_t jitter_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + s16 *rawdata = NULL; + s16 *rawdata_min = NULL; + s16 *rawdata_max = NULL; + int ret, r, c, count = 0; + int max, min, sum, average; + int max_r, max_c, min_r, min_c; + bool data_valid = false; + int i; + + cts_info("Show jitter"); + cts_lock_device(cts_dev); + rawdata = (s16 *) kmalloc(DIFFDATA_BUFFER_SIZE(cts_dev), GFP_KERNEL); + if (rawdata == NULL) { + cts_err("Allocate memory for rawdata failed"); + ret = -ENOMEM; + goto err_jitter_show_exit; + } + rawdata_min = + (s16 *) kmalloc(DIFFDATA_BUFFER_SIZE(cts_dev), GFP_KERNEL); + if (rawdata_min == NULL) { + cts_err("Allocate memory for rawdata failed"); + ret = -ENOMEM; + goto err_free_rawdata; + } + rawdata_max = + (s16 *) kmalloc(DIFFDATA_BUFFER_SIZE(cts_dev), GFP_KERNEL); + if (rawdata_max == NULL) { + cts_err("Allocate memory for rawdata failed"); + ret = -ENOMEM; + goto err_free_rawdata_min; + } + + for (i = 0; i < DIFFDATA_BUFFER_SIZE(cts_dev) / 2; i++) { + rawdata_min[i] = 32767; + rawdata_max[i] = -32768; + } + + ret = cts_enable_get_rawdata(cts_dev); + if (ret) { + cts_err("Enable read raw data failed %d", ret); + goto err_free_rawdata_max; + } + + ret = cts_send_command(cts_dev, CTS_CMD_QUIT_GESTURE_MONITOR); + if (ret) { + cts_err("Send cmd QUIT_GESTURE_MONITOR failed %d", ret); + goto err_free_rawdata_max; + } + msleep(50); + data_valid = true; + for (i = 0; i < jitter_test_frame; i++) { + ret = cts_get_rawdata(cts_dev, rawdata); + if (ret) { + cts_err("Get raw data failed %d", ret); + continue; + } + for (r = 0; r < cts_dev->fwdata.rows; r++) { + for (c = 0; c < cts_dev->fwdata.cols; c++) { + int index; + index = r * cts_dev->fwdata.cols + c; + if (rawdata_min[index] > rawdata[index]) + rawdata_min[index] = rawdata[index]; + else if (rawdata_max[index] < rawdata[index]) + rawdata_max[index] = rawdata[index]; + } + } + msleep(1); + } + ret = cts_disable_get_rawdata(cts_dev); + if (ret) { + cts_err("Disable read raw data failed %d", ret); + } + + if (data_valid) { + max = -32768; + min = 32767; + sum = 0; + max_r = max_c = min_r = min_c = 0; + for (r = 0; r < cts_dev->fwdata.rows; r++) { + for (c = 0; c < cts_dev->fwdata.cols; c++) { + s16 val; + int index = r * cts_dev->fwdata.cols + c; + + val = rawdata_max[index] - rawdata_min[index]; + rawdata[index] = val; + sum += val; + if (val > max) { + max = val; + max_r = r; + max_c = c; + } else if (val < min) { + min = val; + min_r = r; + min_c = c; + } + } + } + average = sum / (cts_dev->fwdata.rows * cts_dev->fwdata.cols); + + count += snprintf(buf + count, PAGE_SIZE - count, + SPLIT_LINE_STR + "Jitter data MIN: [%d][%d]=%d, MAX: [%d][%d]=%d, AVG=%d, TOTAL FRAME=%d\n" + SPLIT_LINE_STR + " | ", min_r, min_c, min, max_r, max_c, + max, average, jitter_test_frame); + for (c = 0; c < cts_dev->fwdata.cols; c++) { + count += + snprintf(buf + count, PAGE_SIZE - count, + COL_NUM_FORMAT_STR, c); + } + count += + snprintf(buf + count, PAGE_SIZE - count, + "\n" SPLIT_LINE_STR); + + for (r = 0; r < cts_dev->fwdata.rows; r++) { + count += + snprintf(buf + count, PAGE_SIZE - count, + ROW_NUM_FORMAT_STR, r); + for (c = 0; c < cts_dev->fwdata.cols; c++) { + count += + snprintf(buf + count, PAGE_SIZE - count, + DATA_FORMAT_STR, + rawdata[r * cts_dev->fwdata.cols + + c]); + } + buf[count++] = '\n'; + } + } + +err_free_rawdata_max: + kfree(rawdata_max); +err_free_rawdata_min: + kfree(rawdata_min); +err_free_rawdata: + kfree(rawdata); +err_jitter_show_exit: + cts_unlock_device(cts_dev); + return data_valid ? count : ret; +} + +static DEVICE_ATTR(jitter, S_IRUSR | S_IWUSR, jitter_show, jitter_store); + +static ssize_t compensate_cap_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + u8 *cap = NULL; + int ret; + ssize_t count = 0; + bool data_valid = false; + u8 r, c; + + cts_info("compensate_cap_show"); + + cts_lock_device(cts_dev); + ret = cts_enable_get_compensate_cap(cts_dev); + if (ret) { + count = + snprintf(buf, PAGE_SIZE, + "Enable get compensate cap failed %d\n", ret); + goto unlock_device; + } + + cap = + kzalloc(cts_dev->hwdata->num_row * cts_dev->hwdata->num_col, + GFP_KERNEL); + if (cap == NULL) { + count = + snprintf(buf, PAGE_SIZE, "Allocate mem for cap failed\n"); + goto unlock_device; + } + + mdelay(10); + + ret = cts_get_compensate_cap(cts_dev, cap); + if (ret) { + count = + snprintf(buf, PAGE_SIZE, "Get compensate cap failed %d\n", + ret); + goto unlock_device; + } + + ret = cts_disable_get_compensate_cap(cts_dev); + if (ret) { + count = + snprintf(buf, PAGE_SIZE, + "Disable get compensate cap failed %d\n", ret); + goto unlock_device; + } + + data_valid = true; +unlock_device: + cts_unlock_device(cts_dev); + + if (data_valid) { + count += + snprintf(buf + count, PAGE_SIZE - count, + SPLIT_LINE_STR " "); + + for (c = 0; c < cts_dev->fwdata.cols; c++) { + count += + snprintf(buf + count, PAGE_SIZE - count, + COL_NUM_FORMAT_STR, c); + } + count += + snprintf(buf + count, PAGE_SIZE - count, + "\n" SPLIT_LINE_STR); + + for (r = 0; r < cts_dev->fwdata.rows; r++) { + count += + snprintf(buf + count, PAGE_SIZE - count, + ROW_NUM_FORMAT_STR, r); + for (c = 0; c < cts_dev->fwdata.cols; c++) { + count += + snprintf(buf + count, PAGE_SIZE - count, + DATA_FORMAT_STR, + cap[r * cts_dev->fwdata.cols + c]); + } + buf[count++] = '\n'; + } + } + + if (cap) { + kfree(cap); + } + return count; +} + +static DEVICE_ATTR(compensate_cap, S_IRUGO, compensate_cap_show, NULL); + +#ifdef CFG_CTS_HAS_RESET_PIN +static ssize_t reset_pin_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + + cts_info("Read RESET-PIN"); + + return snprintf(buf, PAGE_SIZE, + "Reset pin: %d, status: %d\n", + cts_data->pdata->rst_gpio, + gpio_get_value(cts_data->pdata->rst_gpio)); } static ssize_t reset_pin_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) + struct device_attribute *attr, const char *buf, + size_t count) { - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; - cts_info("Write RESET-PIN"); - cts_info("Chip staus maybe changed"); - - cts_plat_set_reset(cts_dev->pdata, (buf[0] == '1') ? 1 : 0); - return count; + cts_info("Write RESET-PIN"); + cts_info("Chip staus maybe changed"); + + cts_plat_set_reset(cts_dev->pdata, (buf[0] == '1') ? 1 : 0); + return count; } -static DEVICE_ATTR(reset_pin, S_IRUSR | S_IWUSR, reset_pin_show, reset_pin_store); -#endif - + +static DEVICE_ATTR(reset_pin, S_IRUSR | S_IWUSR, reset_pin_show, + reset_pin_store); +#endif + static ssize_t irq_pin_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, char *buf) { - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - cts_info("Read IRQ-PIN"); + cts_info("Read IRQ-PIN"); - return snprintf(buf, PAGE_SIZE, - "IRQ pin: %d, status: %d\n", - cts_data->pdata->int_gpio, - gpio_get_value(cts_data->pdata->int_gpio)); + return snprintf(buf, PAGE_SIZE, + "IRQ pin: %d, status: %d\n", + cts_data->pdata->int_gpio, + gpio_get_value(cts_data->pdata->int_gpio)); } + static DEVICE_ATTR(irq_pin, S_IRUGO, irq_pin_show, NULL); - + static ssize_t irq_info_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, char *buf) { - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct irq_desc *desc; + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct irq_desc *desc; - cts_info("Read IRQ-INFO"); + cts_info("Read IRQ-INFO"); - desc = irq_to_desc(cts_data->pdata->irq); - if (desc == NULL) { - return snprintf(buf, PAGE_SIZE, "IRQ: %d descriptor not found\n", - cts_data->pdata->irq); - } - - return snprintf(buf, PAGE_SIZE, - "IRQ num: %d, depth: %u, " - "count: %u, unhandled: %u, last unhandled eslape: %lu\n", - cts_data->pdata->irq, desc->depth, - desc->irq_count, desc->irqs_unhandled, desc->last_unhandled); + desc = irq_to_desc(cts_data->pdata->irq); + if (desc == NULL) { + return snprintf(buf, PAGE_SIZE, + "IRQ: %d descriptor not found\n", + cts_data->pdata->irq); + } + + return snprintf(buf, PAGE_SIZE, + "IRQ num: %d, depth: %u, " + "count: %u, unhandled: %u, last unhandled eslape: %lu\n", + cts_data->pdata->irq, desc->depth, + desc->irq_count, desc->irqs_unhandled, + desc->last_unhandled); } + static DEVICE_ATTR(irq_info, S_IRUGO, irq_info_show, NULL); - -#ifdef CFG_CTS_FW_LOG_REDIRECT + +#ifdef CFG_CTS_FW_LOG_REDIRECT static ssize_t fw_log_redirect_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - - return sprintf(buf, "Fw log redirect is %s\n", - cts_is_fw_log_redirect(cts_dev)? "enable":"disable"); -} - -static ssize_t fw_log_redirect_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - u8 enable = 0; - - if (buf[0] == 'Y' || buf[0] == 'y' || buf[0] == '1') { - enable = 1; - } - if (enable) { - cts_enable_fw_log_redirect(cts_dev); - } - else { - cts_disable_fw_log_redirect(cts_dev); - } - - return count; -} -static DEVICE_ATTR(fw_log_redirect, S_IRUSR|S_IWUSR, fw_log_redirect_show, fw_log_redirect_store); -#endif - -static struct attribute *cts_dev_misc_atts[] = { - &dev_attr_ic_type.attr, - &dev_attr_program_mode.attr, - &dev_attr_rawdata.attr, - &dev_attr_diffdata.attr, - &dev_attr_manualdiff.attr, - &dev_attr_jitter.attr, -#ifdef CFG_CTS_HAS_RESET_PIN - &dev_attr_reset_pin.attr, -#endif - &dev_attr_irq_pin.attr, - &dev_attr_irq_info.attr, -#ifdef CFG_CTS_FW_LOG_REDIRECT - &dev_attr_fw_log_redirect.attr, -#endif - &dev_attr_compensate_cap.attr, - &dev_attr_read_reg.attr, - &dev_attr_write_reg.attr, - &dev_attr_read_hw_reg.attr, - &dev_attr_write_hw_reg.attr, - NULL -}; - -static const struct attribute_group cts_dev_misc_attr_group = { - .name = "misc", - .attrs = cts_dev_misc_atts, -}; - -static const struct attribute_group *cts_dev_attr_groups[] = { - &cts_dev_firmware_attr_group, - &cts_dev_flash_attr_group, - &cts_dev_test_attr_group, - &cts_dev_misc_attr_group, - NULL -}; - -int cts_sysfs_add_device(struct device *dev) -{ - struct chipone_ts_data *cts_data = dev_get_drvdata(dev); - struct cts_device *cts_dev = &cts_data->cts_dev; - int ret, i; - - cts_info("Add device attr groups"); - - // Low version kernel NOT support sysfs_create_groups() - for (i = 0; cts_dev_attr_groups[i]; i++) { - ret = sysfs_create_group(&dev->kobj, cts_dev_attr_groups[i]); - if (ret) { - while (--i >= 0) { - sysfs_remove_group(&dev->kobj, cts_dev_attr_groups[i]); - } - break; - } - } - - if (ret) { - cts_err("Add device attr failed %d", ret); - return ret; - } - - manualdiff_base = (s16 *)kzalloc(DIFFDATA_BUFFER_SIZE(cts_dev), GFP_KERNEL); - if (manualdiff_base == NULL) { - cts_err("Malloc manualdiff_base failed"); - return -ENOMEM; - } - - ret = sysfs_create_link(NULL, &dev->kobj, "chipone-tddi"); - if (ret) { - cts_err("Create sysfs link error:%d", ret); - } - return 0; -} - -void cts_sysfs_remove_device(struct device *dev) -{ - int i; - - cts_info("Remove device attr groups"); - - if (manualdiff_base != NULL) { - kfree(manualdiff_base); - manualdiff_base = NULL; - } - - sysfs_remove_link(NULL, "chipone-tddi"); - // Low version kernel NOT support sysfs_remove_groups() - for (i = 0; cts_dev_attr_groups[i]; i++) { - sysfs_remove_group(&dev->kobj, cts_dev_attr_groups[i]); - } -} - -#undef SPLIT_LINE_STR -#undef ROW_NUM_FORMAT_STR -#undef COL_NUM_FORMAT_STR -#undef DATA_FORMAT_STR - -#endif /* CONFIG_CTS_SYSFS */ + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + + return snprintf(buf, PAGE_SIZE, "Fw log redirect is %s\n", + cts_is_fw_log_redirect(cts_dev) ? "enable" : "disable"); +} + +static ssize_t fw_log_redirect_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + u8 enable = 0; + + if (buf[0] == 'Y' || buf[0] == 'y' || buf[0] == '1') { + enable = 1; + } + if (enable) { + cts_enable_fw_log_redirect(cts_dev); + } else { + cts_disable_fw_log_redirect(cts_dev); + } + + return count; +} + +static DEVICE_ATTR(fw_log_redirect, S_IRUSR | S_IWUSR, fw_log_redirect_show, + fw_log_redirect_store); +#endif + +static ssize_t debug_spi_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + //struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + //struct cts_device *cts_dev = &cts_data->cts_dev; + + return snprintf(buf, PAGE_SIZE, "spi_speed=%d\n", speed); +} + +static ssize_t debug_spi_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + u16 s = 0; + int ret = 0; + + parse_arg(buf, count); + + if (argc != 1) { + cts_err("Invalid num args %d", argc); + return -EFAULT; + } + + ret = kstrtou16(argv[0], 0, &s); + if (ret) { + cts_err("Invalid spi speed: %s", argv[0]); + return -EINVAL; + } + + speed = s; + + return count; +} + +static DEVICE_ATTR(debug_spi, S_IRUSR | S_IWUSR, debug_spi_show, + debug_spi_store); + +#ifdef CFG_CTS_GESTURE +static ssize_t gesture_en_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + + return sprintf(buf, "Gesture wakup is %s\n", + cts_is_gesture_wakeup_enabled(cts_dev) ? "enable" : + "disable"); +} + +static ssize_t gesture_en_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + u8 enable = 0; + + if (buf[0] == 'Y' || buf[0] == 'y' || buf[0] == '1') { + enable = 1; + } + if (enable) { + cts_enable_gesture_wakeup(cts_dev); + } else { + cts_disable_gesture_wakeup(cts_dev); + } + + return count; +} + +static DEVICE_ATTR(gesture_en, S_IRUSR | S_IWUSR, gesture_en_show, + gesture_en_store); +#endif + +static struct attribute *cts_dev_misc_atts[] = { + &dev_attr_ic_type.attr, + &dev_attr_program_mode.attr, + &dev_attr_rawdata.attr, + &dev_attr_diffdata.attr, + &dev_attr_manualdiff.attr, + &dev_attr_jitter.attr, +#ifdef CFG_CTS_HAS_RESET_PIN + &dev_attr_reset_pin.attr, +#endif + &dev_attr_irq_pin.attr, + &dev_attr_irq_info.attr, +#ifdef CFG_CTS_FW_LOG_REDIRECT + &dev_attr_fw_log_redirect.attr, +#endif + &dev_attr_compensate_cap.attr, + &dev_attr_read_reg.attr, + &dev_attr_write_reg.attr, + &dev_attr_read_hw_reg.attr, + &dev_attr_write_hw_reg.attr, + &dev_attr_debug_spi.attr, +#ifdef CFG_CTS_GESTURE + &dev_attr_gesture_en.attr, +#endif /* CFG_CTS_GESTURE */ + NULL +}; + +static const struct attribute_group cts_dev_misc_attr_group = { + .name = "misc", + .attrs = cts_dev_misc_atts, +}; + +#ifdef CFG_CTS_FW_UPDATE_SYS +static struct attribute *cts_dev_fw_up_atts[] = { +// &dev_attr_drv_irq.attr, +// &dev_attr_reset.attr, + &dev_attr_buildid.attr, + &dev_attr_forcereflash.attr, + &dev_attr_flashprog.attr, + &dev_attr_doreflash.attr, + &dev_attr_poweron.attr, + &dev_attr_productinfo.attr, + &dev_attr_panel_supplier.attr, + NULL +}; + +static const struct attribute_group cts_dev_fw_up_attr_group = { + .attrs = cts_dev_fw_up_atts, +}; +#endif + +static const struct attribute_group *cts_dev_attr_groups[] = { + &cts_dev_firmware_attr_group, +#ifdef CFG_CTS_FW_UPDATE_SYS + &cts_dev_fw_up_attr_group, +#endif + &cts_dev_flash_attr_group, + &cts_dev_test_attr_group, + &cts_dev_misc_attr_group, + NULL +}; + +#include +#include + +/* Attribute: path (RO) */ +static ssize_t path_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct chipone_ts_data *data = dev_get_drvdata(dev); + ssize_t blen; + const char *path; + + if (!data) { + cts_err("Read 'path' with chipone_ts_data NULL"); + return (ssize_t) 0; + } +#ifdef CONFIG_CTS_I2C_HOST + path = kobject_get_path(&data->i2c_client->dev.kobj, GFP_KERNEL); +#else + path = kobject_get_path(&data->spi_client->dev.kobj, GFP_KERNEL); +#endif + blen = scnprintf(buf, PAGE_SIZE, "%s", path ? path : "na"); + kfree(path); + return blen; +} + +/* Attribute: vendor (RO) */ +static ssize_t vendor_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "chipone"); +} + +static struct device_attribute touchscreen_attributes[] = { + __ATTR_RO(path), + __ATTR_RO(vendor), + __ATTR_NULL +}; + +#define TSDEV_MINOR_BASE 128 +#define TSDEV_MINOR_MAX 32 + +/******************************************************* +Description: + Chipone touchscreen FW function class. file node + initial function. + +return: + Executive outcomes. 0---succeed. -1---failed. +*******************************************************/ +static int cts_fw_class_init(void *_data, bool create) +{ + struct chipone_ts_data *data = _data; + struct device_attribute *attrs = touchscreen_attributes; + int i, error = 0; + static struct class *touchscreen_class; + static struct device *ts_class_dev; + static int minor; + + cts_info("%s touchscreen class files", create ? "Add" : "Remove"); + + if (create) { +#ifdef CONFIG_CTS_I2C_HOST + minor = input_get_new_minor(data->i2c_client->addr, 1, false); +#else + minor = input_get_new_minor(data->spi_client->chip_select, + 1, false); +#endif + if (minor < 0) { + cts_info + ("Alloc input minor num failed %d, use dynamic mode", + minor); + minor = + input_get_new_minor(TSDEV_MINOR_BASE, + TSDEV_MINOR_MAX, true); + } + cts_info("Assigned input device minor %d", minor); + + cts_info("Create class 'touchscreen'"); + touchscreen_class = class_create(THIS_MODULE, "touchscreen"); + if (IS_ERR(touchscreen_class)) { + cts_err("Create class 'touchscreen' failed %ld", + PTR_ERR(touchscreen_class)); + error = PTR_ERR(touchscreen_class); + touchscreen_class = NULL; + return error; + } + + if(NULL != data->cts_dev.hwdata->name) { + ts_class_dev = device_create(touchscreen_class, NULL, + MKDEV(INPUT_MAJOR, minor), + data, "%s", data->cts_dev.hwdata->name); + cts_info("Create device for IC: %s", data->cts_dev.hwdata->name); + } else { + ts_class_dev = device_create(touchscreen_class, NULL, + MKDEV(INPUT_MAJOR, minor), + data, "%s", CFG_CTS_CHIP_NAME); + cts_info("Create device '" CFG_CTS_CHIP_NAME "'"); + } + if (IS_ERR(ts_class_dev)) { + cts_err("Create device '" CFG_CTS_CHIP_NAME + "'failed %ld", PTR_ERR(ts_class_dev)); + error = PTR_ERR(ts_class_dev); + ts_class_dev = NULL; + return error; + } + + cts_info("Create attr files"); + for (i = 0; attrs[i].attr.name != NULL; ++i) { + cts_info(" Create attr file '%s'", attrs[i].attr.name); + error = device_create_file(ts_class_dev, &attrs[i]); + if (error) { + cts_err("Create attr file '%s' failed %d", + attrs[i].attr.name, error); + break; + } + } + + if (error) { + goto device_destroy; + } else { + cts_info("Create /sys/class/touchscreen/ Succeeded"); + } + } else { + if (!touchscreen_class || !ts_class_dev) + return -ENODEV; + + for (i = 0; attrs[i].attr.name != NULL; ++i) { + cts_info("Remove device file '%s'", attrs[i].attr.name); + device_remove_file(ts_class_dev, &attrs[i]); + } + device_unregister(ts_class_dev); + class_unregister(touchscreen_class); + } + + return 0; + +device_destroy: + for (--i; i >= 0; --i) + device_remove_file(ts_class_dev, &attrs[i]); + device_destroy(touchscreen_class, MKDEV(INPUT_MAJOR, minor)); + ts_class_dev = NULL; + class_unregister(touchscreen_class); + cts_err("Creating touchscreen class failed %d", error); + + return -ENODEV; +} + +int cts_sysfs_add_device(struct device *dev) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + struct cts_device *cts_dev = &cts_data->cts_dev; + int ret, i; + + cts_info("Add device attr groups"); + + // Low version kernel NOT support sysfs_create_groups() + for (i = 0; cts_dev_attr_groups[i]; i++) { + ret = sysfs_create_group(&dev->kobj, cts_dev_attr_groups[i]); + if (ret) { + while (--i >= 0) { + sysfs_remove_group(&dev->kobj, + cts_dev_attr_groups[i]); + } + break; + } + } + + if (ret) { + cts_err("Add device attr failed %d", ret); + return ret; + } + + manualdiff_base = + (s16 *) kzalloc(DIFFDATA_BUFFER_SIZE(cts_dev), GFP_KERNEL); + if (manualdiff_base == NULL) { + cts_err("Malloc manualdiff_base failed"); + return -ENOMEM; + } + + ret = sysfs_create_link(NULL, &dev->kobj, "chipone-tddi"); + if (ret) { + cts_err("Create sysfs link error:%d", ret); + } + + ret = cts_fw_class_init(cts_data, true); + if (ret) { + cts_err("Create touchscreen class failed. ret=%d\n", ret); + return ret; + } + + return 0; +} + +void cts_sysfs_remove_device(struct device *dev) +{ + struct chipone_ts_data *cts_data = dev_get_drvdata(dev); + int i; + + cts_info("Remove device attr groups"); + + if (manualdiff_base != NULL) { + kfree(manualdiff_base); + manualdiff_base = NULL; + } + + sysfs_remove_link(NULL, "chipone-tddi"); + // Low version kernel NOT support sysfs_remove_groups() + for (i = 0; cts_dev_attr_groups[i]; i++) { + sysfs_remove_group(&dev->kobj, cts_dev_attr_groups[i]); + } + cts_fw_class_init(cts_data, false); +} + +#undef SPLIT_LINE_STR +#undef ROW_NUM_FORMAT_STR +#undef COL_NUM_FORMAT_STR +#undef DATA_FORMAT_STR + +#endif /* CONFIG_CTS_SYSFS */ diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_sysfs.h b/drivers/input/touchscreen/chipone_tddi_mmi/cts_sysfs.h old mode 100755 new mode 100644 index 2ae20e7fb2f5..7bf99c347703 --- a/drivers/input/touchscreen/chipone_tddi_mmi/cts_sysfs.h +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_sysfs.h @@ -1,17 +1,24 @@ -#ifndef CTS_SYSFS_H -#define CTS_SYSFS_H - -#include "cts_config.h" - -struct device; - -#ifdef CONFIG_CTS_SYSFS -extern int cts_sysfs_add_device(struct device *dev); -extern void cts_sysfs_remove_device(struct device *dev); -#else /* CONFIG_CTS_SYSFS */ -static inline int cts_sysfs_add_device(struct device *dev) {return -ENOTSUPP;} -static inline void cts_sysfs_remove_device(struct device *dev) {} -#endif /* CONFIG_CTS_SYSFS */ - -#endif /* CTS_SYSFS_H */ - +#ifndef CTS_SYSFS_H +#define CTS_SYSFS_H + +#include "cts_config.h" + +struct device; + +extern u16 speed; + +#ifdef CONFIG_CTS_SYSFS +extern int cts_sysfs_add_device(struct device *dev); +extern void cts_sysfs_remove_device(struct device *dev); +#else /* CONFIG_CTS_SYSFS */ +static inline int cts_sysfs_add_device(struct device *dev) +{ + return -ENOTSUPP; +} + +static inline void cts_sysfs_remove_device(struct device *dev) +{ +} +#endif /* CONFIG_CTS_SYSFS */ + +#endif /* CTS_SYSFS_H */ diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_test.c b/drivers/input/touchscreen/chipone_tddi_mmi/cts_test.c old mode 100755 new mode 100644 index a2d309e524ed..6b303317fb9b --- a/drivers/input/touchscreen/chipone_tddi_mmi/cts_test.c +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_test.c @@ -1,1021 +1,1430 @@ -#define LOG_TAG "Test" - -#include "cts_config.h" -#include "cts_platform.h" -#include "cts_core.h" - -#define CTS_FIRMWARE_WORK_MODE_NORMAL (0x00) -#define CTS_FIRMWARE_WORK_MODE_FACTORY (0x01) -#define CTS_FIRMWARE_WORK_MODE_CONFIG (0x02) -#define CTS_FIRMWARE_WORK_MODE_TEST (0x03) - -#define CTS_TEST_SHORT (0x01) -#define CTS_TEST_OPEN (0x02) - -#define CTS_SHORT_TEST_UNDEFINED (0x00) -#define CTS_SHORT_TEST_BETWEEN_COLS (0x01) -#define CTS_SHORT_TEST_BETWEEN_ROWS (0x02) -#define CTS_SHORT_TEST_BETWEEN_GND (0x03) - -#define TEST_RESULT_BUFFER_SIZE(cts_dev) \ - (cts_dev->fwdata.rows * cts_dev->fwdata.cols * 2) - -#define RAWDATA_BUFFER_SIZE(cts_dev) \ - (cts_dev->fwdata.rows * cts_dev->fwdata.cols * 2) - -static int disable_fw_esd_protection(struct cts_device *cts_dev) -{ - return cts_fw_reg_writeb(cts_dev, 0x8000 + 342, 1); -} - -static int disable_fw_monitor_mode(struct cts_device *cts_dev) -{ - int ret; - u8 value; - - ret = cts_fw_reg_readb(cts_dev, 0x8000 + 344, &value); - if (ret) { - return ret; - } - - if (value & BIT(0)) { - return cts_fw_reg_writeb(cts_dev, 0x8000 + 344, value & (~BIT(0))); - } - - return 0; -} - -static int disable_fw_auto_compensate(struct cts_device *cts_dev) -{ - return cts_fw_reg_writeb(cts_dev, 0x8000 + 276, 1); -} - -static int set_fw_work_mode(struct cts_device *cts_dev, u8 mode) -{ - int ret, retries; - u8 pwr_mode; - - cts_info("Set firmware work mode to %u", mode); - - ret = cts_fw_reg_writeb(cts_dev, CTS_DEVICE_FW_REG_WORK_MODE, mode); - if (ret) { - cts_err("Write firmware work mode register failed %d", ret); - return ret; - } - - ret = cts_fw_reg_readb(cts_dev, 0x05, &pwr_mode); - if (ret) { - cts_err("Read firmware power mode register failed %d", ret); - return ret; - } - - if (pwr_mode == 1) { - ret = cts_send_command(cts_dev, CTS_CMD_QUIT_GESTURE_MONITOR); - if (ret) { - cts_err("Send cmd QUIT_GESTURE_MONITOR failed %d", ret); - return ret; - } - - msleep(50); - } - - retries = 0; - do { - u8 sys_busy, curr_mode; - - msleep(10); - - ret = cts_fw_reg_readb(cts_dev, 0x01, &sys_busy); - if (ret) { - cts_err("Read firmware system busy register failed %d", ret); - return ret; - } - if (sys_busy) - continue; - - ret = cts_fw_reg_readb(cts_dev, 0x3F, &curr_mode); - if (ret) { - cts_err("Read firmware current work mode failed %d", ret); - return ret; - } - - if (curr_mode == mode || curr_mode == 0xFF) { - break; - } - } while (retries++ < 1000); - - return (retries >= 1000 ? -ETIMEDOUT : 0); -} - -static int set_display_state(struct cts_device *cts_dev, bool active) -{ - int ret; - u8 access_flag; - - cts_info("Set display state to %s", active ? "ACTIVE" : "SLEEP"); - - ret = cts_hw_reg_readb(cts_dev, 0x3002C, &access_flag); - if (ret) { - cts_err("Read display access flag failed %d", ret); - return ret; - } - - ret = cts_hw_reg_writeb(cts_dev, 0x3002C, access_flag | 0x01); - if (ret) { - cts_err("Write display access flag %02x failed %d", access_flag, ret); - return ret; - } - - if (active) { - ret = cts_hw_reg_writeb(cts_dev, 0x3C044, 0x55); - if (ret) { - cts_err("Write DCS-CMD11 fail"); - return ret; - } - - msleep(100); - - ret = cts_hw_reg_writeb(cts_dev, 0x3C0A4, 0x55); - if (ret) { - cts_err("Write DCS-CMD29 fail"); - return ret; - } - - msleep(100); - } else { - ret = cts_hw_reg_writeb(cts_dev, 0x3C0A0, 0x55); - if (ret) { - cts_err("Write DCS-CMD28 fail"); - return ret; - } - - msleep(100); - - ret = cts_hw_reg_writeb(cts_dev, 0x3C040, 0x55); - if (ret) { - cts_err("Write DCS-CMD10 fail"); - return ret; - } - - msleep(100); - } - - ret = cts_hw_reg_writeb(cts_dev, 0x3002C, access_flag); - if (ret) { - cts_err("Restore display access flag %02x failed %d", access_flag, ret); - return ret; - } - - return 0; -} - -static int wait_test_complete(struct cts_device *cts_dev, int skip_frames) -{ - int ret, i, j; - - cts_info("Wait test complete skip %d frames", skip_frames); - - for(i = 0; i < (skip_frames + 1); i++) { - u8 ready; - - ret = cts_clr_data_ready_flag(cts_dev); - if (ret) { - cts_err("Clear data ready flag failed %d", ret); - return ret; - } - - for (j = 0; j < 1000; j++) { - mdelay(1); - - ready = 0; - ret = cts_get_data_ready_flag(cts_dev, &ready); - if (ret) { - cts_err("Get data ready flag failed %d", ret); - return ret; - } - - if (ready) { - break; - } - } - - if (ready == 0) { - return -ETIMEDOUT; - } - } - - return 0; -} - -static int get_test_result(struct cts_device *cts_dev, u16 *result) -{ - int ret; - - ret = cts_fw_reg_readsb(cts_dev, CTS_DEVICE_FW_REG_RAW_DATA, result, - TEST_RESULT_BUFFER_SIZE(cts_dev)); - if (ret) { - cts_err("Get test result data failed %d", ret); - return ret; - } - - ret = cts_clr_data_ready_flag(cts_dev); - if (ret) { - cts_err("Clear data ready flag failed %d", ret); - return ret; - } - - return 0; -} - -static int set_fw_test_type(struct cts_device *cts_dev, u8 type) -{ - int ret, retries = 0; - u8 sys_busy; - u8 type_readback; - - cts_info("Set test type %d", type); - - ret = cts_fw_reg_writeb(cts_dev, 0x34, type); - if (ret) { - cts_err("Write test type register to failed %d", ret); - return ret; - } - - do { - msleep(1); - - ret = cts_fw_reg_readb(cts_dev, 0x01, &sys_busy); - if (ret) { - cts_err("Read system busy register failed %d", ret); - return ret; - } - } while (sys_busy && retries++ < 1000); - - if (retries >= 1000) { - cts_err("Wait system ready timeout"); - return -ETIMEDOUT; - } - - ret = cts_fw_reg_readb(cts_dev, 0x34, &type_readback); - if (ret) { - cts_err("Read test type register failed %d", ret); - return ret; - } - - if (type != type_readback) { - cts_err("Set test type %u != readback %u", type, type_readback); - return -EFAULT; - } - - return 0; -} - -static bool set_short_test_type(struct cts_device *cts_dev, u8 type) -{ - static struct fw_short_test_param { - u8 type; - u32 col_pattern[2]; - u32 row_pattern[2]; - } param = { - .type = CTS_SHORT_TEST_BETWEEN_COLS, - .col_pattern = {0, 0}, - .row_pattern = {0, 0} - }; - int ret; - - cts_info("Set short test type to %u", type); - - param.type = type; - ret = cts_fw_reg_writesb(cts_dev, 0x5000, ¶m, sizeof(param)); - if (ret) { - cts_err("Set short test type to %u failed %d", type, ret); - return ret; - } - - return 0; -} - -static void dump_test_data(struct cts_device *cts_dev, - const char *desc, const u16 *data) -{ -#define SPLIT_LINE_STR \ - "----------------------------------------------------------------------------------------------------------------\n" -#define ROW_NUM_FORMAT_STR "%2d | " -#define COL_NUM_FORMAT_STR "%-5u " -#define DATA_FORMAT_STR "%-5u " - - int r, c; - u32 max, min, sum, average; - int max_r, max_c, min_r, min_c; - - max = min = data[0]; - sum = 0; - max_r = max_c = min_r = min_c = 0; - for (r = 0; r < cts_dev->fwdata.rows; r++) { - for (c = 0; c < cts_dev->fwdata.cols; c++) { - u16 val = data[r * cts_dev->fwdata.cols + c]; - - sum += val; - if (val > max) { - max = val; - max_r = r; - max_c = c; - } else if (val < min) { - min = val; - min_r = r; - min_c = c; - } - } - } - average = sum / (cts_dev->fwdata.rows * cts_dev->fwdata.cols); - - printk(SPLIT_LINE_STR - "%s test data MIN: [%u][%u]=%u, MAX: [%u][%u]=%u, AVG=%u\n" - SPLIT_LINE_STR - " | ", desc, min_r, min_c, min, max_r, max_c, max, average); - for (c = 0; c < cts_dev->fwdata.cols; c++) { - printk(COL_NUM_FORMAT_STR, c); - } - printk("\n" SPLIT_LINE_STR); - - for (r = 0; r < cts_dev->fwdata.rows; r++) { - printk(ROW_NUM_FORMAT_STR, r); - for (c = 0; c < cts_dev->fwdata.cols; c++) { - printk(DATA_FORMAT_STR, data[r * cts_dev->fwdata.cols + c]); - } - printk("\n"); - } - printk(SPLIT_LINE_STR); - -#undef SPLIT_LINE_STR -#undef ROW_NUM_FORMAT_STR -#undef COL_NUM_FORMAT_STR -#undef DATA_FORMAT_STR -} - -/* Return number of failed nodes */ -static int validate_test_result(struct cts_device *cts_dev, - const char *desc, u16 *test_result, u16 threshold) -{ -#define SPLIT_LINE_STR \ - "------------------------------\n" - - int r, c; - int failed_cnt = 0; - - for (r = 0; r < cts_dev->fwdata.rows; r++) { - for (c = 0; c < cts_dev->fwdata.cols; c++) { - if (test_result[r * cts_dev->fwdata.cols + c] < threshold) { - if (failed_cnt == 0) { - printk("%s failed nodes:\n" - SPLIT_LINE_STR, desc); - } - failed_cnt++; - - printk(" %3d: [%-2d][%-2d] = %u\n", failed_cnt, r, c, - test_result[r * cts_dev->fwdata.cols + c]); - } - } - } - - printk("%s" - "%s test %d node total failed\n", - failed_cnt ? SPLIT_LINE_STR : "", desc, failed_cnt); - - return failed_cnt; - -#undef SPLIT_LINE_STR -} - -static int test_short_to_gnd(struct cts_device *cts_dev, - u8 feature_ver, u16 *test_result, u16 threshold) -{ - int ret; - - cts_info("Test short to GND"); - - ret = set_short_test_type(cts_dev, CTS_SHORT_TEST_UNDEFINED); - if (ret) { - cts_err("Set short test type to UNDEFINED failed %d", ret); - return ret; - } - - ret = set_fw_test_type(cts_dev, CTS_TEST_SHORT); - if (ret) { - cts_err("Set test type to SHORT failed %d", ret); - return ret; - } - - ret = set_fw_work_mode(cts_dev, CTS_FIRMWARE_WORK_MODE_TEST); - if (ret) { - cts_err("Set firmware work mode to WORK_MODE_TEST failed %d", ret); - return ret; - } - - if (feature_ver <= 3) { - u8 val; - ret = cts_hw_reg_readb(cts_dev, 0x350E2, &val); - if (ret) { - cts_err("Read 0x350E2 failed %d", ret); - return ret; - } - ret = cts_hw_reg_writeb(cts_dev, 0x350E2, val & 0xDB); - if (ret) { - cts_err("Write 0x350E2 failed %d", ret); - return ret; - } - } - - ret = set_short_test_type(cts_dev, CTS_SHORT_TEST_BETWEEN_GND); - if (ret) { - cts_err("Set short test type to SHORT_TO_GND failed %d", ret); - return ret; - } - - ret = wait_test_complete(cts_dev, 0); - if (ret) { - cts_err("Wait test complete failed %d", ret); - return ret; - } - - ret = get_test_result(cts_dev, test_result); - if (ret) { - cts_err("Read test result failed %d", ret); - return ret; - } - - dump_test_data(cts_dev, "GND-short", test_result); - - return validate_test_result(cts_dev, "GND-short", test_result, threshold); -} - -static int test_short_to_gnd_legacy(struct cts_device *cts_dev, - u16 *test_result, u16 threshold) -{ - int ret; - - cts_info("Test short to GND"); - - ret = cts_send_command(cts_dev, CTS_CMD_RECOVERY_TX_VOL); - if (ret) { - cts_err("Send command RECOVERY_TX_VOL failed %d", ret); - return ret; - } - - ret = wait_test_complete(cts_dev, 2); - if (ret) { - cts_err("Wait test complete failed %d", ret); - return ret; - } - - ret = get_test_result(cts_dev, test_result); - if (ret) { - cts_err("Read test result failed %d", ret); - return ret; - } - - dump_test_data(cts_dev, "GND-short", test_result); - - return validate_test_result(cts_dev, "GND-short", test_result, threshold); -} - -static int test_short_between_cols(struct cts_device *cts_dev, - u16 *test_result, u16 threshold, bool skip_first_frame) -{ - int ret; - - cts_info("Test short between columns"); - - ret = set_fw_test_type(cts_dev, CTS_TEST_SHORT); - if (ret) { - cts_err("Set test type to SHORT failed %d", ret); - return ret; - } - - ret = set_short_test_type(cts_dev, CTS_SHORT_TEST_BETWEEN_COLS); - if (ret) { - cts_err("Set short test type to BETWEEN_COLS failed %d", ret); - return ret; - } - - ret = set_fw_work_mode(cts_dev, CTS_FIRMWARE_WORK_MODE_TEST); - if (ret) { - cts_err("Set firmware work mode to WORK_MODE_TEST failed %d", ret); - return ret; - } - - if (skip_first_frame) { - cts_info("Skip first frame data"); - - ret = wait_test_complete(cts_dev, 0); - if (ret) { - cts_err("Wait test complete failed %d", ret); - return ret; - } - - ret = get_test_result(cts_dev, test_result); - if (ret) { - cts_err("Read skip test result failed %d", ret); - return ret; - } - - ret = set_short_test_type(cts_dev, CTS_SHORT_TEST_BETWEEN_COLS); - if (ret) { - cts_err("Set short test type to BETWEEN_COLS failed %d", ret); - return ret; - } - } - - ret = wait_test_complete(cts_dev, 0); - if (ret) { - cts_err("Wait test complete failed %d", ret); - return ret; - } - - ret = get_test_result(cts_dev, test_result); - if (ret) { - cts_err("Read test result failed %d", ret); - return ret; - } - - dump_test_data(cts_dev, "Col-short", test_result); - - return validate_test_result(cts_dev, "Col-short", test_result, threshold); -} - -static int test_short_between_rows(struct cts_device *cts_dev, - u16 *test_result, u16 threshold) -{ - int ret; - int loopcnt; - - cts_info("Test short between rows"); - - ret = set_short_test_type(cts_dev, CTS_SHORT_TEST_BETWEEN_ROWS); - if (ret) { - cts_err("Set short test type to BETWEEN_ROWS failed %d", ret); - return ret; - } - - loopcnt = cts_dev->hwdata->num_row; - while (loopcnt > 1) { - ret = wait_test_complete(cts_dev, 0); - if (ret) { - cts_err("Wait test complete failed %d", ret); - return ret; - } - - ret = get_test_result(cts_dev, test_result); - if (ret) { - cts_err("Read test result failed %d", ret); - return ret; - } - - dump_test_data(cts_dev, "Row-short", test_result); - - if ((ret = validate_test_result(cts_dev, - "Row-short", test_result,threshold)) != 0) { - break; - } - - loopcnt += loopcnt % 2; - loopcnt = loopcnt >> 1; - } - - return ret; -} - -static int prepare_test(struct cts_device *cts_dev) -{ - int ret; - - cts_info("Prepare test"); - - cts_plat_reset_device(cts_dev->pdata); - - ret = disable_fw_esd_protection(cts_dev); - if (ret) { - cts_err("Disable firmware ESD protection failed %d", ret); - return ret; - } - - ret = disable_fw_monitor_mode(cts_dev); - if (ret) { - cts_err("Disable firmware monitor mode failed %d", ret); - return ret; - } - - ret = disable_fw_auto_compensate(cts_dev); - if (ret) { - cts_err("Disable firmware auto compensate failed %d", ret); - return ret; - } - - ret = set_fw_work_mode(cts_dev, CTS_FIRMWARE_WORK_MODE_FACTORY); - if (ret) { - cts_err("Set firmware work mode to WORK_MODE_FACTORY failed %d", ret); - return ret; - } - - cts_dev->rtdata.testing = true; - - return 0; -} - -static void post_test(struct cts_device *cts_dev) -{ - int ret; - - cts_info("Post test"); - - cts_plat_reset_device(cts_dev->pdata); - - ret = set_fw_work_mode(cts_dev, CTS_FIRMWARE_WORK_MODE_NORMAL); - if (ret) { - cts_err("Set firmware work mode to WORK_MODE_NORMAL failed %d", ret); - } - - cts_dev->rtdata.testing = false; -} - -/* Return 0 success - negative value while error occurs - positive value means how many nodes fail */ -int cts_short_test(struct cts_device *cts_dev, u16 threshold) -{ - int ret; - u16 *test_result = NULL; - bool recovery_display_state = false; - u8 need_display_on; - u8 feature_ver; - - cts_info("Start short test, threshold = %u", threshold); - - test_result = (u16 *)kmalloc(TEST_RESULT_BUFFER_SIZE(cts_dev), GFP_KERNEL); - if (test_result == NULL) { - cts_err("Allocate test result buffer failed"); - return -ENOMEM; - } - - cts_lock_device(cts_dev); - - ret = prepare_test(cts_dev); - if (ret) { - cts_err("Prepare test failed %d", ret); - goto err_free_test_result; - } - - ret = cts_sram_readb(cts_dev, 0xE8, &feature_ver); - if (ret) { - cts_err("Read firmware feature version failed %d", ret); - goto err_free_test_result; - } - cts_info("Feature version: %u", feature_ver); - - if (feature_ver > 0) { - ret = test_short_to_gnd(cts_dev, feature_ver, test_result, threshold); - } else { - ret = test_short_to_gnd_legacy(cts_dev, test_result, threshold); - } - if (ret) { - cts_err("Short to GND test failed %d", ret); - goto err_free_test_result; - } - - ret = cts_fw_reg_readb(cts_dev, 0x8000 + 163, &need_display_on); - if (ret) { - cts_err("Read need display on register failed %d", ret); - goto err_free_test_result; - } - - if (need_display_on == 0) { - ret = set_display_state(cts_dev, false); - if (ret) { - cts_err("Set display state to SLEEP failed %d", ret); - goto err_free_test_result; - } - recovery_display_state = true; - } - - ret = test_short_between_cols(cts_dev, - test_result, threshold, need_display_on == 0); - if (ret) { - cts_err("Short between columns test failed %d", ret); - goto err_recovery_display_state; - } - - ret = test_short_between_rows(cts_dev, test_result, threshold); - if (ret) { - cts_err("Short between columns test failed %d", ret); - goto err_recovery_display_state; - } - -err_recovery_display_state: - if (recovery_display_state) { - int r = set_display_state(cts_dev, true); - if (r) { - cts_err("Set display state to ACTIVE failed %d", r); - } - } -err_free_test_result: - kfree(test_result); - post_test(cts_dev); - - cts_unlock_device(cts_dev); - - cts_info("Short test %s", ret ? "FAILED" : "PASSED"); - - return ret; -} - -/* Return 0 success - negative value while error occurs - positive value means how many nodes fail */ -int cts_open_test(struct cts_device *cts_dev, u16 threshold) -{ - int ret; - u16 *test_result = NULL; - bool recovery_display_state = false; - u8 need_display_on; - - cts_info("Start open test, threshold = %u", threshold); - - test_result = (u16 *)kmalloc(TEST_RESULT_BUFFER_SIZE(cts_dev), GFP_KERNEL); - if (test_result == NULL) { - cts_err("Allocate memory for test result faild"); - return -ENOMEM; - } - - cts_lock_device(cts_dev); - ret = prepare_test(cts_dev); - if (ret) { - cts_err("Prepare test failed %d", ret); - goto err_free_test_result; - } - - ret = cts_fw_reg_readb(cts_dev, 0x8000 + 163, &need_display_on); - if (ret) { - cts_err("Read need display on register failed %d", ret); - goto err_free_test_result; - } - - if (need_display_on == 0) { - ret = set_display_state(cts_dev, false); - if (ret) { - cts_err("Set display state to SLEEP failed %d", ret); - goto err_free_test_result; - } - recovery_display_state = true; - } - - ret = cts_send_command(cts_dev, CTS_CMD_RECOVERY_TX_VOL); - if (ret) { - cts_err("Recovery tx voltage failed %d", ret); - goto err_recovery_display_state; - } - - ret = set_fw_test_type(cts_dev, CTS_TEST_OPEN); - if (ret) { - cts_err("Set test type to OPEN_TEST failed %d", ret); - goto err_recovery_display_state; - } - - ret = set_fw_work_mode(cts_dev, CTS_FIRMWARE_WORK_MODE_TEST); - if (ret) { - cts_err("Set firmware work mode to WORK_MODE_TEST failed %d", ret); - goto err_recovery_display_state; - } - - ret = wait_test_complete(cts_dev, 2); - if (ret) { - cts_err("Wait test complete failed %d", ret); - goto err_recovery_display_state; - } - - ret = get_test_result(cts_dev, test_result); - if (ret) { - cts_err("Read test result failed %d", ret); - goto err_recovery_display_state; - } - - dump_test_data(cts_dev, "Open-circuit", test_result); - - ret = validate_test_result(cts_dev, "Open-circuit", test_result, threshold); - -err_recovery_display_state: - if (recovery_display_state) { - int r = set_display_state(cts_dev, true); - if (r) { - cts_err("Set display state to ACTIVE failed %d", r); - } - } -err_free_test_result: - kfree(test_result); - post_test(cts_dev); - - cts_unlock_device(cts_dev); - cts_info("Open test %s", ret ? "FAILED" : "PASSED"); - - return ret; -} - -#ifdef CFG_CTS_HAS_RESET_PIN -int cts_reset_test(struct cts_device *cts_dev) -{ - int ret; - int val = 0; - - cts_lock_device(cts_dev); - ret = cts_stop_device(cts_dev); - if (ret) { - cts_err("Stop device failed %d", ret); - } - cts_plat_set_reset(cts_dev->pdata, 0); - mdelay(50); -#ifdef CONFIG_CTS_I2C_HOST - /* Check whether device is in normal mode */ - if (!cts_plat_is_i2c_online(cts_dev->pdata, - CTS_DEV_NORMAL_MODE_I2CADDR)) { -#else - if (!cts_plat_is_normal_mode(cts_dev->pdata)) { -#endif /* CONFIG_CTS_I2C_HOST */ - val++; - } - cts_plat_set_reset(cts_dev->pdata, 1); - mdelay(50); -#ifdef CONFIG_CTS_I2C_HOST - /* Check whether device is in normal mode */ - if (cts_plat_is_i2c_online(cts_dev->pdata, - CTS_DEV_NORMAL_MODE_I2CADDR)) { -#else - if (cts_plat_is_normal_mode(cts_dev->pdata)) { -#endif /* CONFIG_CTS_I2C_HOST */ - val ++; - } - ret = cts_start_device(cts_dev); - if (ret) { - cts_err("Stop device failed %d", ret); - } -#ifdef CONFIG_CTS_CHARGER_DETECT - if (cts_is_charger_exist(cts_dev)) { - cts_charger_plugin(cts_dev); - } -#endif /* CONFIG_CTS_CHARGER_DETECT */ - -#ifdef CONFIG_CTS_GLOVE - if (cts_is_glove_enabled(cts_dev)) { - cts_enter_glove_mode(cts_dev); - } -#endif - -#ifdef CFG_CTS_FW_LOG_REDIRECT - if (cts_is_fw_log_redirect(cts_dev)) { - cts_enable_fw_log_redirect(cts_dev); - } -#endif - - cts_unlock_device(cts_dev); - if (val == 2) { - if (!cts_dev->rtdata.program_mode) { - cts_set_normal_addr(cts_dev); - } - return 0; - } - return -1; -} -#endif - -int cts_compensate_cap_test(struct cts_device *cts_dev, u8 min_thres, u8 max_thres) -{ - u8 *cap = NULL; - int ret = 0; - bool data_valid = false; - u8 r, c; - int test_result = -1; - - cts_info("cts_compensate_cap_test"); - - cap = kzalloc(cts_dev->hwdata->num_row * cts_dev->hwdata->num_col, GFP_KERNEL); - if (cap == NULL) { - cts_err("Allocate mem for cap failed %d", ret); - return -ENOMEM; - } - - cts_lock_device(cts_dev); - ret = cts_enable_get_compensate_cap(cts_dev); - if (ret) { - cts_err("Enable get compensate cap failed %d", ret); - goto unlock_device; - } - - ret = cts_get_compensate_cap(cts_dev, cap); - if (ret) { - cts_err("Get compensate cap failed %d", ret); - goto unlock_device; - } - - ret = cts_disable_get_compensate_cap(cts_dev); - if (ret) { - cts_err("Disable get compensate cap failed %d", ret); - goto unlock_device; - } - - data_valid = true; -unlock_device: - cts_unlock_device(cts_dev); - - if (data_valid) { - test_result = 0; - for (r = 0; r < cts_dev->fwdata.rows; r++) { - for (c = 0; c < cts_dev->fwdata.cols; c++) { - if (cap[r * cts_dev->fwdata.cols + c] > max_thres - || cap[r * cts_dev->fwdata.cols + c] < min_thres) - { - test_result = -1; - break; - } - } - if (test_result == -1) - { - break; - } - } - } - kfree(cap); - return test_result; -} - -int cts_rawdata_test(struct cts_device *cts_dev, u16 min_thres, u16 max_thres) -{ - int ret; - bool data_valid = false; - u8 r, c; - int test_result = -1; - u16 *rawdata; - int i; - - cts_info("cts_rawdata_test"); - rawdata = (u16 *)kmalloc(RAWDATA_BUFFER_SIZE(cts_dev), GFP_KERNEL); - if (rawdata == NULL) { - cts_err("Allocate memory for rawdata failed"); - return -ENOMEM; - } - - cts_lock_device(cts_dev); - ret = cts_enable_get_rawdata(cts_dev); - if (ret) { - cts_err("can not enable get rawdata"); - goto unlock_device; - } - - ret = cts_send_command(cts_dev, CTS_CMD_QUIT_GESTURE_MONITOR); - if (ret) { - cts_err("send quit gesture monitor err"); - } - - msleep(50); - for (i = 0; i < 3; i++) { - ret = cts_get_rawdata(cts_dev, rawdata); - if (ret) { - cts_err("get rawdata err"); - } - else { - break; - } - mdelay(30); - } - ret = cts_disable_get_rawdata(cts_dev); - if (ret) { - cts_err("disable get rawdata err"); - return -EPERM; - } - if (i < 3) { - data_valid = true; - } -unlock_device: - cts_unlock_device(cts_dev); - - if (data_valid) { - test_result = 0; - for (r = 0; r < cts_dev->fwdata.rows; r++) { - for (c = 0; c < cts_dev->fwdata.cols; c++) { - if (rawdata[r * cts_dev->fwdata.cols + c] > max_thres - || rawdata[r * cts_dev->fwdata.cols + c] < min_thres) - { - test_result = -1; - break; - } - } - if (test_result == -1) - { - break; - } - } - } - kfree(rawdata); - return test_result; -} - - - - +#define LOG_TAG "Test" + +#include "cts_config.h" +#include "cts_platform.h" +#include "cts_core.h" + +#define CTS_FIRMWARE_WORK_MODE_NORMAL (0x00) +#define CTS_FIRMWARE_WORK_MODE_FACTORY (0x01) +#define CTS_FIRMWARE_WORK_MODE_CONFIG (0x02) +#define CTS_FIRMWARE_WORK_MODE_TEST (0x03) + +#define CTS_TEST_SHORT (0x01) +#define CTS_TEST_OPEN (0x02) + +#define CTS_SHORT_TEST_UNDEFINED (0x00) +#define CTS_SHORT_TEST_BETWEEN_COLS (0x01) +#define CTS_SHORT_TEST_BETWEEN_ROWS (0x02) +#define CTS_SHORT_TEST_BETWEEN_GND (0x03) + +#define TEST_RESULT_BUFFER_SIZE(cts_dev) \ + (cts_dev->fwdata.rows * cts_dev->fwdata.cols * 2) + +#define RAWDATA_BUFFER_SIZE(cts_dev) \ + (cts_dev->fwdata.rows * cts_dev->fwdata.cols * 2) + +static int disable_fw_esd_protection(struct cts_device *cts_dev) +{ + return cts_fw_reg_writeb(cts_dev, 0x8000 + 342, 1); +} + +static int disable_fw_monitor_mode(struct cts_device *cts_dev) +{ + int ret; + u8 value; + + ret = cts_fw_reg_readb(cts_dev, 0x8000 + 344, &value); + if (ret) { + return ret; + } + + if (value & BIT(0)) { + return cts_fw_reg_writeb(cts_dev, 0x8000 + 344, + value & (~BIT(0))); + } + + return 0; +} + +static int disable_fw_auto_compensate(struct cts_device *cts_dev) +{ + return cts_fw_reg_writeb(cts_dev, 0x8000 + 276, 1); +} + +static int set_fw_work_mode(struct cts_device *cts_dev, u8 mode) +{ + int ret, retries; + u8 pwr_mode; + + cts_info("Set firmware work mode to %u", mode); + + ret = cts_fw_reg_writeb(cts_dev, CTS_DEVICE_FW_REG_WORK_MODE, mode); + if (ret) { + cts_err("Write firmware work mode register failed %d", ret); + return ret; + } + + ret = cts_fw_reg_readb(cts_dev, 0x05, &pwr_mode); + if (ret) { + cts_err("Read firmware power mode register failed %d", ret); + return ret; + } + + if (pwr_mode == 1) { + ret = cts_send_command(cts_dev, CTS_CMD_QUIT_GESTURE_MONITOR); + if (ret) { + cts_err("Send cmd QUIT_GESTURE_MONITOR failed %d", ret); + return ret; + } + + msleep(50); + } + + retries = 0; + do { + u8 sys_busy, curr_mode; + + msleep(10); + + ret = cts_fw_reg_readb(cts_dev, 0x01, &sys_busy); + if (ret) { + cts_err("Read firmware system busy register failed %d", + ret); + return ret; + } + if (sys_busy) + continue; + + ret = cts_fw_reg_readb(cts_dev, 0x3F, &curr_mode); + if (ret) { + cts_err("Read firmware current work mode failed %d", + ret); + return ret; + } + + if (curr_mode == mode || curr_mode == 0xFF) { + break; + } + } while (retries++ < 1000); + + return (retries >= 1000 ? -ETIMEDOUT : 0); +} + +static int set_display_state(struct cts_device *cts_dev, bool active) +{ + int ret; + u8 access_flag; + + cts_info("Set display state to %s", active ? "ACTIVE" : "SLEEP"); + + ret = cts_hw_reg_readb_relaxed(cts_dev, 0x3002C, &access_flag); + if (ret) { + cts_err("Read display access flag failed %d", ret); + return ret; + } + + ret = cts_hw_reg_writeb_relaxed(cts_dev, 0x3002C, access_flag | 0x01); + if (ret) { + cts_err("Write display access flag %02x failed %d", access_flag, + ret); + return ret; + } + + if (active) { + ret = cts_hw_reg_writeb_relaxed(cts_dev, 0x3C044, 0x55); + if (ret) { + cts_err("Write DCS-CMD11 fail"); + return ret; + } + + msleep(100); + + ret = cts_hw_reg_writeb_relaxed(cts_dev, 0x3C0A4, 0x55); + if (ret) { + cts_err("Write DCS-CMD29 fail"); + return ret; + } + + msleep(100); + } else { + ret = cts_hw_reg_writeb_relaxed(cts_dev, 0x3C0A0, 0x55); + if (ret) { + cts_err("Write DCS-CMD28 fail"); + return ret; + } + + msleep(100); + + ret = cts_hw_reg_writeb_relaxed(cts_dev, 0x3C040, 0x55); + if (ret) { + cts_err("Write DCS-CMD10 fail"); + return ret; + } + + msleep(100); + } + + ret = cts_hw_reg_writeb_relaxed(cts_dev, 0x3002C, access_flag); + if (ret) { + cts_err("Restore display access flag %02x failed %d", + access_flag, ret); + return ret; + } + + return 0; +} + +static int wait_test_complete(struct cts_device *cts_dev, int skip_frames) +{ + int ret, i, j; + + cts_info("Wait test complete skip %d frames", skip_frames); + + for (i = 0; i < (skip_frames + 1); i++) { + u8 ready; + + for (j = 0; j < 1000; j++) { + mdelay(1); + + ready = 0; + ret = cts_get_data_ready_flag(cts_dev, &ready); + if (ret) { + cts_err("Get data ready flag failed %d", ret); + return ret; + } + + if (ready) { + break; + } + } + + if (ready == 0) { + return -ETIMEDOUT; + } + if (i < skip_frames) { + ret = cts_clr_data_ready_flag(cts_dev); + if (ret) { + cts_err("Clr data ready flag failed %d", ret); + return ret; + } + } + } + + return 0; +} + +static int get_test_result(struct cts_device *cts_dev, u16 *result) +{ + int ret; + + ret = cts_fw_reg_readsb(cts_dev, CTS_DEVICE_FW_REG_RAW_DATA, result, + TEST_RESULT_BUFFER_SIZE(cts_dev)); + if (ret) { + cts_err("Get test result data failed %d", ret); + return ret; + } + + ret = cts_clr_data_ready_flag(cts_dev); + if (ret) { + cts_err("Clear data ready flag failed %d", ret); + return ret; + } + + return 0; +} + +static int set_fw_test_type(struct cts_device *cts_dev, u8 type) +{ + int i, ret; + + cts_info("Set test type %d", type); + + for (i = 0; i < 5; i++) { + u8 type_readback; + + ret = cts_fw_reg_writeb(cts_dev, 0x34, type); + if (ret) { + cts_err("Write test type register to failed %d", ret); + continue; + } + + ret = cts_fw_reg_readb(cts_dev, 0x34, &type_readback); + if (ret) { + cts_err("Read test type register failed %d", ret); + continue; + } + + if (type != type_readback) { + cts_err("Set test type %u != readback %u", type, + type_readback); + ret = -EFAULT; + continue; + } + } + + return ret; +} + +struct cts_fw_short_test_param { + u8 type; + u32 col_pattern[2]; + u32 row_pattern[2]; +}; + +static bool set_short_test_type(struct cts_device *cts_dev, u8 type) +{ + static struct cts_fw_short_test_param param = { + .type = CTS_SHORT_TEST_BETWEEN_COLS, + .col_pattern = {0, 0}, + .row_pattern = {0, 0} + }; + int i, ret; + + cts_info("Set short test type to %u", type); + + param.type = type; + for (i = 0; i < 5; i++) { + u8 type_readback; + + ret = + cts_fw_reg_writesb(cts_dev, 0x5000, ¶m, sizeof(param)); + if (ret) { + cts_err("Set short test type to %u failed %d", type, + ret); + continue; + } + ret = cts_fw_reg_readb(cts_dev, 0x5000, &type_readback); + if (ret) { + cts_err("Get short test type failed %d", ret); + continue; + } + if (type == type_readback) { + return 0; + } else { + cts_err("Set test type %u != readback %u", type, + type_readback); + continue; + } + } + + return ret; +} + +static void dump_test_data(struct cts_device *cts_dev, + const char *desc, const u16 *data) +{ +#define SPLIT_LINE_STR \ + "----------------------------------------------------------------------------------------------------------------" +#define ROW_NUM_FORMAT_STR "%2d | " +#define COL_NUM_FORMAT_STR "%-5u " +#define DATA_FORMAT_STR "%-5u " + + int r, c; + u32 max, min, sum, average; + int max_r, max_c, min_r, min_c; + char line_buf[128]; + int count = 0; + + max = min = data[0]; + sum = 0; + max_r = max_c = min_r = min_c = 0; + for (r = 0; r < cts_dev->fwdata.rows; r++) { + for (c = 0; c < cts_dev->fwdata.cols; c++) { + u16 val = data[r * cts_dev->fwdata.cols + c]; + + sum += val; + if (val > max) { + max = val; + max_r = r; + max_c = c; + } else if (val < min) { + min = val; + min_r = r; + min_c = c; + } + } + } + average = sum / (cts_dev->fwdata.rows * cts_dev->fwdata.cols); + + cts_info(SPLIT_LINE_STR); + count += snprintf(line_buf + count, sizeof(line_buf) - count, + " %s test data MIN: [%u][%u]=%u, MAX: [%u][%u]=%u, AVG=%u", + desc, min_r, min_c, min, max_r, max_c, max, average); + cts_info("%s", line_buf); + cts_info(SPLIT_LINE_STR); + + count = 0; + count += snprintf(line_buf + count, sizeof(line_buf) - count, " | "); + for (c = 0; c < cts_dev->fwdata.cols; c++) { + count += snprintf(line_buf + count, sizeof(line_buf) - count, + COL_NUM_FORMAT_STR, c); + } + cts_info("%s", line_buf); + cts_info(SPLIT_LINE_STR); + + for (r = 0; r < cts_dev->fwdata.rows; r++) { + count = 0; + count += snprintf(line_buf + count, sizeof(line_buf) - count, + ROW_NUM_FORMAT_STR, r); + for (c = 0; c < cts_dev->fwdata.cols; c++) { + count += + snprintf(line_buf + count, sizeof(line_buf) - count, + DATA_FORMAT_STR, + data[r * cts_dev->fwdata.cols + c]); + } + cts_info("%s", line_buf); + } + cts_info(SPLIT_LINE_STR); + +#undef SPLIT_LINE_STR +#undef ROW_NUM_FORMAT_STR +#undef COL_NUM_FORMAT_STR +#undef DATA_FORMAT_STR +} + +/* Return number of failed nodes */ +static int validate_test_result(struct cts_device *cts_dev, + const char *desc, u16 *test_result, + u16 min, u16 max) +{ +#define SPLIT_LINE_STR \ + "------------------------------" + + int r, c; + int failed_cnt = 0; + + for (r = 0; r < cts_dev->fwdata.rows; r++) { + for (c = 0; c < cts_dev->fwdata.cols; c++) { + if (test_result[r * cts_dev->fwdata.cols + c] < min || + test_result[r * cts_dev->fwdata.cols + c] > max) { + if (failed_cnt == 0) { + cts_info(SPLIT_LINE_STR); + cts_info("%s failed nodes:", desc); + } + failed_cnt++; + + cts_info(" %3d: [%-2d][%-2d] = %u", failed_cnt, + r, c, + test_result[r * cts_dev->fwdata.cols + + c]); + } + } + } + + if (failed_cnt) { + cts_info(SPLIT_LINE_STR); + } + cts_info("%s test %d node total failed", desc, failed_cnt); + + return failed_cnt; + +#undef SPLIT_LINE_STR +} + +static int test_short_to_gnd(struct cts_device *cts_dev, + u8 feature_ver, u16 *test_result, u16 threshold) +{ + int ret; + + cts_info("Test short to GND"); + + ret = set_short_test_type(cts_dev, CTS_SHORT_TEST_UNDEFINED); + if (ret) { + cts_err("Set short test type to UNDEFINED failed %d", ret); + return ret; + } + + ret = set_fw_test_type(cts_dev, CTS_TEST_SHORT); + if (ret) { + cts_err("Set test type to SHORT failed %d", ret); + return ret; + } + + ret = set_fw_work_mode(cts_dev, CTS_FIRMWARE_WORK_MODE_TEST); + if (ret) { + cts_err("Set firmware work mode to WORK_MODE_TEST failed %d", + ret); + return ret; + } + + if (feature_ver <= 3) { + u8 val; + ret = cts_hw_reg_readb_relaxed(cts_dev, 0x350E2, &val); + if (ret) { + cts_err("Read 0x350E2 failed %d", ret); + return ret; + } + ret = cts_hw_reg_writeb_relaxed(cts_dev, 0x350E2, val & 0xDB); + if (ret) { + cts_err("Write 0x350E2 failed %d", ret); + return ret; + } + } + + ret = set_short_test_type(cts_dev, CTS_SHORT_TEST_BETWEEN_GND); + if (ret) { + cts_err("Set short test type to SHORT_TO_GND failed %d", ret); + return ret; + } + + ret = wait_test_complete(cts_dev, 0); + if (ret) { + cts_err("Wait test complete failed %d", ret); + return ret; + } + + ret = get_test_result(cts_dev, test_result); + if (ret) { + cts_err("Read test result failed %d", ret); + return ret; + } + + dump_test_data(cts_dev, "GND-short", test_result); + + return validate_test_result(cts_dev, "GND-short", test_result, + threshold, USHRT_MAX); +} + +static int test_short_to_gnd_legacy(struct cts_device *cts_dev, + u16 *test_result, u16 threshold) +{ + int ret; + + cts_info("Test short to GND"); + + ret = cts_send_command(cts_dev, CTS_CMD_RECOVERY_TX_VOL); + if (ret) { + cts_err("Send command RECOVERY_TX_VOL failed %d", ret); + return ret; + } + + ret = wait_test_complete(cts_dev, 2); + if (ret) { + cts_err("Wait test complete failed %d", ret); + return ret; + } + + ret = get_test_result(cts_dev, test_result); + if (ret) { + cts_err("Read test result failed %d", ret); + return ret; + } + + dump_test_data(cts_dev, "GND-short", test_result); + + return validate_test_result(cts_dev, "GND-short", test_result, + threshold, USHRT_MAX); +} + +static int test_short_between_cols(struct cts_device *cts_dev, + u16 *test_result, u16 threshold, + bool skip_first_frame) +{ + int ret; + + cts_info("Test short between columns"); + + ret = set_fw_test_type(cts_dev, CTS_TEST_SHORT); + if (ret) { + cts_err("Set test type to SHORT failed %d", ret); + return ret; + } + + ret = set_short_test_type(cts_dev, CTS_SHORT_TEST_BETWEEN_COLS); + if (ret) { + cts_err("Set short test type to BETWEEN_COLS failed %d", ret); + return ret; + } + + ret = set_fw_work_mode(cts_dev, CTS_FIRMWARE_WORK_MODE_TEST); + if (ret) { + cts_err("Set firmware work mode to WORK_MODE_TEST failed %d", + ret); + return ret; + } + + if (skip_first_frame) { + cts_info("Skip first frame data"); + + ret = wait_test_complete(cts_dev, 0); + if (ret) { + cts_err("Wait test complete failed %d", ret); + return ret; + } + + ret = get_test_result(cts_dev, test_result); + if (ret) { + cts_err("Read skip test result failed %d", ret); + return ret; + } + + ret = set_short_test_type(cts_dev, CTS_SHORT_TEST_BETWEEN_COLS); + if (ret) { + cts_err("Set short test type to BETWEEN_COLS failed %d", + ret); + return ret; + } + } + + ret = wait_test_complete(cts_dev, 0); + if (ret) { + cts_err("Wait test complete failed %d", ret); + return ret; + } + + ret = get_test_result(cts_dev, test_result); + if (ret) { + cts_err("Read test result failed %d", ret); + return ret; + } + + dump_test_data(cts_dev, "Col-short", test_result); + + return validate_test_result(cts_dev, "Col-short", test_result, + threshold, USHRT_MAX); +} + +static int test_short_between_rows(struct cts_device *cts_dev, + u16 *test_result, u16 threshold) +{ + int ret; + int loopcnt; + + cts_info("Test short between rows"); + + ret = set_short_test_type(cts_dev, CTS_SHORT_TEST_BETWEEN_ROWS); + if (ret) { + cts_err("Set short test type to BETWEEN_ROWS failed %d", ret); + return ret; + } + + loopcnt = cts_dev->hwdata->num_row; + while (loopcnt > 1) { + ret = wait_test_complete(cts_dev, 0); + if (ret) { + cts_err("Wait test complete failed %d", ret); + return ret; + } + + ret = get_test_result(cts_dev, test_result); + if (ret) { + cts_err("Read test result failed %d", ret); + return ret; + } + + dump_test_data(cts_dev, "Row-short", test_result); + + ret = + validate_test_result(cts_dev, "Row-short", test_result, + threshold, USHRT_MAX); + if (ret != 0) { + break; + } + + loopcnt += loopcnt % 2; + loopcnt = loopcnt >> 1; + } + + return ret; +} + +static int wait_fw_to_normal_work(struct cts_device *cts_dev) +{ + int i = 0; + int ret; + + cts_info("Wait fw to normal work"); + + do { + u8 work_mode; + + ret = cts_fw_reg_readb(cts_dev, + CTS_DEVICE_FW_REG_GET_WORK_MODE, + &work_mode); + if (ret) { + cts_err("Get fw curr work mode failed %d", work_mode); + continue; + } else { + if (work_mode == CTS_FIRMWARE_WORK_MODE_NORMAL) { + return 0; + } + } + + mdelay(10); + } while (++i < 100); + + return ret ? ret : -ETIMEDOUT; +} + +static int prepare_test(struct cts_device *cts_dev) +{ + int ret; + + cts_info("Prepare test"); + + cts_plat_reset_device(cts_dev->pdata); + + ret = wait_fw_to_normal_work(cts_dev); + if (ret) { + cts_err("Wait fw to normal work failed %d", ret); + return ret; + } + + ret = disable_fw_esd_protection(cts_dev); + if (ret) { + cts_err("Disable firmware ESD protection failed %d", ret); + return ret; + } + + ret = disable_fw_monitor_mode(cts_dev); + if (ret) { + cts_err("Disable firmware monitor mode failed %d", ret); + return ret; + } + + ret = disable_fw_auto_compensate(cts_dev); + if (ret) { + cts_err("Disable firmware auto compensate failed %d", ret); + return ret; + } + + ret = set_fw_work_mode(cts_dev, CTS_FIRMWARE_WORK_MODE_CONFIG); + if (ret) { + cts_err("Set firmware work mode to WORK_MODE_CONFIG failed %d", + ret); + return ret; + } + + cts_dev->rtdata.testing = true; + + return 0; +} + +static void post_test(struct cts_device *cts_dev) +{ + int ret; + + cts_info("Post test"); + + cts_plat_reset_device(cts_dev->pdata); + + ret = set_fw_work_mode(cts_dev, CTS_FIRMWARE_WORK_MODE_NORMAL); + if (ret) { + cts_err("Set firmware work mode to WORK_MODE_NORMAL failed %d", + ret); + } + + ret = wait_fw_to_normal_work(cts_dev); + if (ret) { + cts_err("Wait fw to normal work failed %d", ret); + //return ret; + } + + cts_dev->rtdata.testing = false; +} + +/* Return 0 success + negative value while error occurs + positive value means how many nodes fail */ +int cts_short_test(struct cts_device *cts_dev, u16 threshold) +{ + int ret; + u16 *test_result = NULL; + bool recovery_display_state = false; + u8 need_display_on; + u8 feature_ver; + + cts_info("Start short test, threshold = %u", threshold); + + test_result = + (u16 *) kmalloc(TEST_RESULT_BUFFER_SIZE(cts_dev), GFP_KERNEL); + if (test_result == NULL) { + cts_err("Allocate test result buffer failed"); + return -ENOMEM; + } + + ret = cts_stop_device(cts_dev); + if (ret) { + cts_err("Stop device failed %d", ret); + return ret; + } + + cts_lock_device(cts_dev); + + ret = prepare_test(cts_dev); + if (ret) { + cts_err("Prepare test failed %d", ret); + goto err_free_test_result; + } + + ret = cts_sram_readb(cts_dev, 0xE8, &feature_ver); + if (ret) { + cts_err("Read firmware feature version failed %d", ret); + goto err_free_test_result; + } + cts_info("Feature version: %u", feature_ver); + + if (feature_ver > 0) { + ret = + test_short_to_gnd(cts_dev, feature_ver, test_result, + threshold); + } else { + ret = test_short_to_gnd_legacy(cts_dev, test_result, threshold); + } + if (ret) { + cts_err("Short to GND test failed %d", ret); + goto err_free_test_result; + } + + ret = cts_fw_reg_readb(cts_dev, 0x8000 + 163, &need_display_on); + if (ret) { + cts_err("Read need display on register failed %d", ret); + goto err_free_test_result; + } + + if (need_display_on == 0) { + ret = set_display_state(cts_dev, false); + if (ret) { + cts_err("Set display state to SLEEP failed %d", ret); + goto err_free_test_result; + } + recovery_display_state = true; + } + + ret = test_short_between_cols(cts_dev, + test_result, threshold, + need_display_on == 0); + if (ret) { + cts_err("Short between columns test failed %d", ret); + goto err_recovery_display_state; + } + + ret = test_short_between_rows(cts_dev, test_result, threshold); + if (ret) { + cts_err("Short between columns test failed %d", ret); + goto err_recovery_display_state; + } + +err_recovery_display_state: + if (recovery_display_state) { + int r = set_display_state(cts_dev, true); + if (r) { + cts_err("Set display state to ACTIVE failed %d", r); + } + } +err_free_test_result: + kfree(test_result); + post_test(cts_dev); + + cts_unlock_device(cts_dev); + + cts_info("Short test %s", ret ? "FAILED" : "PASSED"); + + cts_start_device(cts_dev); + + return ret; +} + +/* Return 0 success + negative value while error occurs + positive value means how many nodes fail */ +int cts_open_test(struct cts_device *cts_dev, u16 threshold) +{ + int ret; + u16 *test_result = NULL; + bool recovery_display_state = false; + u8 need_display_on; + + cts_info("Start open test, threshold = %u", threshold); + + test_result = + (u16 *) kmalloc(TEST_RESULT_BUFFER_SIZE(cts_dev), GFP_KERNEL); + if (test_result == NULL) { + cts_err("Allocate memory for test result faild"); + return -ENOMEM; + } + + ret = cts_stop_device(cts_dev); + if (ret) { + cts_err("Stop device failed %d", ret); + return ret; + } + + cts_lock_device(cts_dev); + ret = prepare_test(cts_dev); + if (ret) { + cts_err("Prepare test failed %d", ret); + goto err_free_test_result; + } + + ret = cts_fw_reg_readb(cts_dev, 0x8000 + 163, &need_display_on); + if (ret) { + cts_err("Read need display on register failed %d", ret); + goto err_free_test_result; + } + + if (need_display_on == 0) { + ret = set_display_state(cts_dev, false); + if (ret) { + cts_err("Set display state to SLEEP failed %d", ret); + goto err_free_test_result; + } + recovery_display_state = true; + } + + ret = cts_send_command(cts_dev, CTS_CMD_RECOVERY_TX_VOL); + if (ret) { + cts_err("Recovery tx voltage failed %d", ret); + goto err_recovery_display_state; + } + + ret = set_fw_test_type(cts_dev, CTS_TEST_OPEN); + if (ret) { + cts_err("Set test type to OPEN_TEST failed %d", ret); + goto err_recovery_display_state; + } + + ret = set_fw_work_mode(cts_dev, CTS_FIRMWARE_WORK_MODE_TEST); + if (ret) { + cts_err("Set firmware work mode to WORK_MODE_TEST failed %d", + ret); + goto err_recovery_display_state; + } + + ret = wait_test_complete(cts_dev, 2); + if (ret) { + cts_err("Wait test complete failed %d", ret); + goto err_recovery_display_state; + } + + ret = get_test_result(cts_dev, test_result); + if (ret) { + cts_err("Read test result failed %d", ret); + goto err_recovery_display_state; + } + + dump_test_data(cts_dev, "Open-circuit", test_result); + + ret = + validate_test_result(cts_dev, "Open-circuit", test_result, + threshold, USHRT_MAX); + +err_recovery_display_state: + if (recovery_display_state) { + int r = set_display_state(cts_dev, true); + if (r) { + cts_err("Set display state to ACTIVE failed %d", r); + } + } +err_free_test_result: + kfree(test_result); + post_test(cts_dev); + + cts_unlock_device(cts_dev); + cts_info("Open test %s", ret ? "FAILED" : "PASSED"); + + cts_start_device(cts_dev); + + return ret; +} + +#ifdef CFG_CTS_HAS_RESET_PIN +int cts_reset_test(struct cts_device *cts_dev) +{ + int ret; + int val = 0; + + cts_info("Reset Pin"); + + ret = cts_stop_device(cts_dev); + if (ret) { + cts_err("Stop device failed %d", ret); + return ret; + } + + cts_lock_device(cts_dev); + + cts_plat_set_reset(cts_dev->pdata, 0); + mdelay(50); +#ifdef CONFIG_CTS_I2C_HOST + /* Check whether device is in normal mode */ + if (!cts_plat_is_i2c_online(cts_dev->pdata, + CTS_DEV_NORMAL_MODE_I2CADDR)) { +#else + if (!cts_plat_is_normal_mode(cts_dev->pdata)) { +#endif /* CONFIG_CTS_I2C_HOST */ + val++; + } else { + cts_err("Device is alive while reset is low"); + } + cts_plat_set_reset(cts_dev->pdata, 1); + mdelay(50); + + ret = wait_fw_to_normal_work(cts_dev); + if (ret) { + cts_err("Wait fw to normal work failed %d", ret); + } +#ifdef CONFIG_CTS_I2C_HOST + /* Check whether device is in normal mode */ + if (cts_plat_is_i2c_online(cts_dev->pdata, CTS_DEV_NORMAL_MODE_I2CADDR)) { +#else + if (cts_plat_is_normal_mode(cts_dev->pdata)) { +#endif /* CONFIG_CTS_I2C_HOST */ + val++; + } else { + cts_err("Device is offline while reset is high"); + } +#ifdef CONFIG_CTS_CHARGER_DETECT + if (cts_is_charger_exist(cts_dev)) { + cts_charger_plugin(cts_dev); + } +#endif /* CONFIG_CTS_CHARGER_DETECT */ + +#ifdef CONFIG_CTS_GLOVE + if (cts_is_glove_enabled(cts_dev)) { + cts_enter_glove_mode(cts_dev); + } +#endif + +#ifdef CFG_CTS_FW_LOG_REDIRECT + if (cts_is_fw_log_redirect(cts_dev)) { + cts_enable_fw_log_redirect(cts_dev); + } +#endif + + cts_unlock_device(cts_dev); + + ret = cts_start_device(cts_dev); + if (ret) { + cts_err("Stop device failed %d", ret); + } + + cts_info("Reset-Pin test %s", val == 2 ? "PASS" : "FAIL"); + if (val == 2) { + if (!cts_dev->rtdata.program_mode) { + cts_set_normal_addr(cts_dev); + } + return 0; + } + + return -EFAULT; +} +#endif + +int cts_test_int_pin(struct cts_device *cts_dev) +{ + int ret; + + cts_info("INT-pin"); + + ret = cts_stop_device(cts_dev); + if (ret) { + cts_err("Stop device failed %d", ret); + return ret; + } + + cts_lock_device(cts_dev); + + ret = cts_send_command(cts_dev, CTS_CMD_WRTITE_INT_HIGH); + if (ret) { + cts_err("Send command WRTITE_INT_HIGH failed %d", ret); + goto unlock_device; + } + mdelay(10); + if (cts_plat_get_int_pin(cts_dev->pdata) == 0) { + cts_err("INT pin state != HIGH"); + ret = -EFAULT; + goto unlock_device; + } + + ret = cts_send_command(cts_dev, CTS_CMD_WRTITE_INT_LOW); + if (ret) { + cts_err("Send command WRTITE_INT_LOW failed %d", ret); + goto unlock_device; + } + mdelay(10); + if (cts_plat_get_int_pin(cts_dev->pdata) != 0) { + cts_err("INT pin state != LOW"); + ret = -EFAULT; + goto unlock_device; + } + + ret = cts_send_command(cts_dev, CTS_CMD_RELASE_INT_TEST); + if (ret) { + cts_err("Send command RELASE_INT_TEST failed %d", ret); + ret = 0; // Ignore this error + } + mdelay(10); + +unlock_device: + cts_unlock_device(cts_dev); + + ret = cts_start_device(cts_dev); + if (ret) { + cts_err("Start device failed %d", ret); + ret = 0; // Ignore this error + } + + cts_info("Int-Pin test %s", ret == 0 ? "PASS" : "FAIL"); + return ret; +} + +void dump_compensate_cap(struct cts_device *cts_dev, u8 *cap) +{ +#define SPLIT_LINE_STR \ + "-----------------------------------------------------------------------------" +#define ROW_NUM_FORMAT_STR "%2d | " +#define COL_NUM_FORMAT_STR "%3u " +#define DATA_FORMAT_STR "%4d" + + int r, c; + char line_buf[128]; + int count = 0; + + cts_info(SPLIT_LINE_STR); + count += snprintf(line_buf + count, sizeof(line_buf) - count, " "); + for (c = 0; c < cts_dev->fwdata.cols; c++) { + count += snprintf(line_buf + count, sizeof(line_buf) - count, + COL_NUM_FORMAT_STR, c); + } + cts_info("%s", line_buf); + cts_info(SPLIT_LINE_STR); + + for (r = 0; r < cts_dev->fwdata.rows; r++) { + count = 0; + count += snprintf(line_buf + count, sizeof(line_buf) - count, + ROW_NUM_FORMAT_STR, r); + for (c = 0; c < cts_dev->fwdata.cols; c++) { + count += snprintf(line_buf + count, + sizeof(line_buf) - count, + DATA_FORMAT_STR, + cap[r * cts_dev->fwdata.cols + c]); + } + cts_info("%s", line_buf); + } + cts_info(SPLIT_LINE_STR); +#undef SPLIT_LINE_STR +#undef ROW_NUM_FORMAT_STR +#undef COL_NUM_FORMAT_STR +#undef DATA_FORMAT_STR +} + +static int validate_compensate_cap(struct cts_device *cts_dev, + const char *desc, u8 *test_result, + u16 min, u16 max) +{ +#define SPLIT_LINE_STR \ + "------------------------------" + + int r, c; + int failed_cnt = 0; + + for (r = 0; r < cts_dev->fwdata.rows; r++) { + for (c = 0; c < cts_dev->fwdata.cols; c++) { + if (test_result[r * cts_dev->fwdata.cols + c] < min || + test_result[r * cts_dev->fwdata.cols + c] > max) { + if (failed_cnt == 0) { + cts_info(SPLIT_LINE_STR); + cts_info("%s failed nodes:", desc); + } + failed_cnt++; + + cts_info(" %3d: [%-2d][%-2d] = %u", failed_cnt, + r, c, + test_result[r * cts_dev->fwdata.cols + + c]); + } + } + } + + if (failed_cnt) { + cts_info("%s", SPLIT_LINE_STR); + } + cts_info("%s test %d node total failed", desc, failed_cnt); + + return failed_cnt; + +#undef SPLIT_LINE_STR +} + +int cts_compensate_cap_test(struct cts_device *cts_dev, u8 min_thres, + u8 max_thres) +{ + u8 *cap = NULL; + int ret = 0; + bool data_valid = false; + + cts_info("Compensate cap, threshold [%u, %u]", min_thres, max_thres); + + cap = + kzalloc(cts_dev->hwdata->num_row * cts_dev->hwdata->num_col, + GFP_KERNEL); + if (cap == NULL) { + cts_err("Allocate mem for cap failed %d", ret); + return -ENOMEM; + } + + cts_lock_device(cts_dev); + ret = cts_enable_get_compensate_cap(cts_dev); + if (ret) { + cts_err("Enable get compensate cap failed %d", ret); + goto unlock_device; + } + + mdelay(10); + + ret = cts_get_compensate_cap(cts_dev, cap); + if (ret) { + cts_err("Get compensate cap failed %d", ret); + goto unlock_device; + } + + ret = cts_disable_get_compensate_cap(cts_dev); + if (ret) { + cts_err("Disable get compensate cap failed %d", ret); + goto unlock_device; + } + + data_valid = true; +unlock_device: + cts_unlock_device(cts_dev); + + if (data_valid) { + dump_compensate_cap(cts_dev, cap); + ret = + validate_compensate_cap(cts_dev, "Compensate-Cap", cap, + min_thres, max_thres); + } + kfree(cap); + + cts_info("Compensate-Cap test %s", ret == 0 ? "PASS" : "FAIL"); + return ret; +} + +int cts_rawdata_test(struct cts_device *cts_dev, u16 min, u16 max) +{ + int ret; + bool data_valid = false; + u16 *rawdata; + int i; + + cts_info("Rawdata, threshold[%u, %u]", min, max); + + rawdata = (u16 *) kmalloc(RAWDATA_BUFFER_SIZE(cts_dev), GFP_KERNEL); + if (rawdata == NULL) { + cts_err("Allocate memory for rawdata failed"); + return -ENOMEM; + } + + cts_lock_device(cts_dev); + + for (i = 0; i < 5; i++) { + int r; + u8 val; + r = cts_enable_get_rawdata(cts_dev); + if (r) { + cts_err("Enable get ts data failed %d", r); + continue; + } + mdelay(1); + r = cts_fw_reg_readb(cts_dev, 0x12, &val); + if (r) { + cts_err("Read enable get ts data failed %d", r); + continue; + } + if (val != 0) { + break; + } + } + + if (i >= 5) { + cts_err("Enable read tsdata failed"); + ret = -EIO; + goto unlock_device; + } + + ret = cts_send_command(cts_dev, CTS_CMD_QUIT_GESTURE_MONITOR); + if (ret) { + cts_err("Send CMD_QUIT_GESTURE_MONITOR failed %d", ret); + } + + msleep(50); + for (i = 0; i < 3; i++) { + ret = cts_get_rawdata(cts_dev, rawdata); + if (ret) { + cts_err("Get rawdata failed %d", ret); + continue; + } else { + data_valid = true; + break; + } + mdelay(30); + } + + if (i >= 3) { + cts_err("Read rawdata failed"); + ret = -EIO; + } + + for (i = 0; i < 5; i++) { + int r = cts_disable_get_rawdata(cts_dev); + if (r) { + cts_err("Disable get rawdata failed %d", r); + continue; + } else { + break; + } + } + +unlock_device: + cts_unlock_device(cts_dev); + + if (data_valid) { + dump_test_data(cts_dev, "Rawdata", rawdata); + ret = validate_test_result(cts_dev, "Rawdata", + rawdata, min, max); + } + kfree(rawdata); + + cts_info("Rawdata test %s", + (data_valid && (ret == 0)) ? "PASS" : "FAIL"); + + return ret; +} + +int cts_noise_test(struct cts_device *cts_dev, u32 frames, u16 max) +{ + u16 *curr_rawdata = NULL; + u16 *max_rawdata = NULL; + u16 *min_rawdata = NULL; + u16 *noise = NULL; + bool first_frame = true; + bool data_valid = false; + u16 i; + int ret; + + cts_info("Noise frames: %u, threshold: %u", frames, max); + + curr_rawdata = + (u16 *) kmalloc(TEST_RESULT_BUFFER_SIZE(cts_dev) * 4, GFP_KERNEL); + if (curr_rawdata == NULL) { + cts_err("Alloc mem for rawdata failed"); + return -ENOMEM; + } + max_rawdata = + curr_rawdata + cts_dev->fwdata.rows * cts_dev->fwdata.cols; + min_rawdata = max_rawdata + cts_dev->fwdata.rows * cts_dev->fwdata.cols; + noise = min_rawdata + cts_dev->fwdata.rows * cts_dev->fwdata.cols; + + cts_lock_device(cts_dev); + + for (i = 0; i < 5; i++) { + int r; + u8 val; + r = cts_enable_get_rawdata(cts_dev); + if (r) { + cts_err("Enable get ts data failed %d", r); + continue; + } + mdelay(1); + r = cts_fw_reg_readb(cts_dev, 0x12, &val); + if (r) { + cts_err("Read enable get ts data failed %d", r); + continue; + } + if (val != 0) { + break; + } + } + + if (i >= 5) { + cts_err("Enable read tsdata failed"); + ret = -EIO; + goto unlock_device; + } + + ret = cts_send_command(cts_dev, CTS_CMD_QUIT_GESTURE_MONITOR); + if (ret) { + cts_err("send quit gesture monitor err"); + // Ignore this error + } + + msleep(50); + + while (frames--) { + for (i = 0; i < 3; i++) { + int r; + r = cts_get_rawdata(cts_dev, curr_rawdata); + if (r) { + cts_err("Get rawdata failed %d", r); + continue; + } else { + break; + } + mdelay(30); + } + + if (i >= 3) { + cts_err("Read rawdata failed"); + ret = -EIO; + goto disable_get_tsdata; + } + + /* Dump raw data */ + dump_test_data(cts_dev, "Noise-rawdata", curr_rawdata); + + if (unlikely(first_frame)) { + memcpy(max_rawdata, curr_rawdata, + TEST_RESULT_BUFFER_SIZE(cts_dev)); + memcpy(min_rawdata, curr_rawdata, + TEST_RESULT_BUFFER_SIZE(cts_dev)); + first_frame = false; + + continue; + } else { + for (i = 0; + i < cts_dev->fwdata.rows * cts_dev->fwdata.cols; + i++) { + if (curr_rawdata[i] > max_rawdata[i]) { + max_rawdata[i] = curr_rawdata[i]; + } else if (curr_rawdata[i] < min_rawdata[i]) { + min_rawdata[i] = curr_rawdata[i]; + } + } + } + } + + data_valid = true; + +disable_get_tsdata: + for (i = 0; i < 5; i++) { + int r = cts_disable_get_rawdata(cts_dev); + if (r) { + cts_err("Disable get rawdata failed %d", r); + continue; + } else { + break; + } + } + +unlock_device: + cts_unlock_device(cts_dev); + + if (data_valid) { + for (i = 0; i < cts_dev->fwdata.rows * cts_dev->fwdata.cols; + i++) { + noise[i] = max_rawdata[i] - min_rawdata[i]; + } + + dump_test_data(cts_dev, "Noise", noise); + + ret = + validate_test_result(cts_dev, "Noise test", noise, 0, max); + } + + kfree(curr_rawdata); + + cts_info("Noise test %s", (data_valid && (ret == 0)) ? "PASS" : "FAIL"); + + return ret; +} diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_test.h b/drivers/input/touchscreen/chipone_tddi_mmi/cts_test.h old mode 100755 new mode 100644 index e5872298f62b..3f47b5505c2c --- a/drivers/input/touchscreen/chipone_tddi_mmi/cts_test.h +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_test.h @@ -1,13 +1,16 @@ -#ifndef CTS_TEST_H -#define CTS_TEST_H - -struct cts_device; - -extern int cts_short_test(struct cts_device *cts_dev, u16 threshold); -extern int cts_open_test(struct cts_device *cts_dev, u16 threshold); -extern int cts_reset_test(struct cts_device *cts_dev); -extern int cts_compensate_cap_test(struct cts_device *cts_dev, u8 min_thres, u8 max_thres); -extern int cts_rawdata_test(struct cts_device *cts_dev, u16 min_thres, u16 max_thres); - -#endif /* CTS_TEST_H */ - +#ifndef CTS_TEST_H +#define CTS_TEST_H + +struct cts_device; + +extern int cts_short_test(struct cts_device *cts_dev, u16 threshold); +extern int cts_open_test(struct cts_device *cts_dev, u16 threshold); +extern int cts_reset_test(struct cts_device *cts_dev); +extern int cts_compensate_cap_test(struct cts_device *cts_dev, u8 min_thres, + u8 max_thres); +extern int cts_rawdata_test(struct cts_device *cts_dev, u16 min_thres, + u16 max_thres); +extern int cts_noise_test(struct cts_device *cts_dev, u32 frames, u16 max); +extern int cts_test_int_pin(struct cts_device *cts_dev); + +#endif /* CTS_TEST_H */ diff --git a/drivers/input/touchscreen/chipone_tddi_mmi/cts_tool.c b/drivers/input/touchscreen/chipone_tddi_mmi/cts_tool.c old mode 100755 new mode 100644 index 58ce85173956..eeb30cd04ba5 --- a/drivers/input/touchscreen/chipone_tddi_mmi/cts_tool.c +++ b/drivers/input/touchscreen/chipone_tddi_mmi/cts_tool.c @@ -4,21 +4,22 @@ #include "cts_platform.h" #include "cts_core.h" #include "cts_firmware.h" +#include "cts_test.h" #ifdef CONFIG_CTS_LEGACY_TOOL #pragma pack(1) /** Tool command structure */ struct cts_tool_cmd { - u8 cmd; - u8 flag; - u8 circle; - u8 times; - u8 retry; - u32 data_len; - u8 addr_len; - u8 addr[2]; - u8 data[PAGE_SIZE]; + u8 cmd; + u8 flag; + u8 circle; + u8 times; + u8 retry; + u32 data_len; + u8 addr_len; + u8 addr[2]; + u8 data[PAGE_SIZE]; }; #pragma pack() @@ -26,515 +27,723 @@ struct cts_tool_cmd { #define CTS_TOOL_CMD_HEADER_LENGTH (12) enum cts_tool_cmd_code { - CTS_TOOL_CMD_GET_PANEL_PARAM = 0, - CTS_TOOL_CMD_GET_DOWNLOAD_STATUS = 2, - CTS_TOOL_CMD_GET_RAW_DATA = 4, - CTS_TOOL_CMD_GET_DIFF_DATA = 6, - CTS_TOOL_CMD_READ_HOSTCOMM = 12, - CTS_TOOL_CMD_READ_ADC_STATUS = 14, - CTS_TOOL_CMD_READ_GESTURE_INFO = 16, - CTS_TOOL_CMD_READ_HOSTCOMM_MULTIBYTE = 18, - CTS_TOOL_CMD_READ_PROGRAM_MODE_MULTIBYTE = 20, - CTS_TOOL_CMD_READ_ICTYPE = 22, - CTS_TOOL_CMD_I2C_DIRECT_READ = 24, - CTS_TOOL_CMD_GET_DRIVER_INFO = 26, + CTS_TOOL_CMD_GET_PANEL_PARAM = 0, + CTS_TOOL_CMD_GET_DOWNLOAD_STATUS = 2, + CTS_TOOL_CMD_GET_RAW_DATA = 4, + CTS_TOOL_CMD_GET_DIFF_DATA = 6, + CTS_TOOL_CMD_READ_HOSTCOMM = 12, + CTS_TOOL_CMD_READ_ADC_STATUS = 14, + CTS_TOOL_CMD_READ_GESTURE_INFO = 16, + CTS_TOOL_CMD_READ_HOSTCOMM_MULTIBYTE = 18, + CTS_TOOL_CMD_READ_PROGRAM_MODE_MULTIBYTE = 20, + CTS_TOOL_CMD_READ_ICTYPE = 22, + CTS_TOOL_CMD_I2C_DIRECT_READ = 24, + CTS_TOOL_CMD_GET_DRIVER_INFO = 26, - CTS_TOOL_CMD_UPDATE_PANEL_PARAM_IN_SRAM = 1, - CTS_TOOL_CMD_DOWNLOAD_FIRMWARE_WITH_FILENAME = 3, - CTS_TOOL_CMD_DOWNLOAD_FIRMWARE = 5, - CTS_TOOL_CMD_WRITE_HOSTCOMM = 11, - CTS_TOOL_CMD_WRITE_HOSTCOMM_MULTIBYTE = 15, - CTS_TOOL_CMD_WRITE_PROGRAM_MODE_MULTIBYTE = 17, - CTS_TOOL_CMD_I2C_DIRECT_WRITE = 19, + CTS_TOOL_CMD_UPDATE_PANEL_PARAM_IN_SRAM = 1, + CTS_TOOL_CMD_DOWNLOAD_FIRMWARE_WITH_FILENAME = 3, + CTS_TOOL_CMD_DOWNLOAD_FIRMWARE = 5, + CTS_TOOL_CMD_WRITE_HOSTCOMM = 11, + CTS_TOOL_CMD_WRITE_HOSTCOMM_MULTIBYTE = 15, + CTS_TOOL_CMD_WRITE_PROGRAM_MODE_MULTIBYTE = 17, + CTS_TOOL_CMD_I2C_DIRECT_WRITE = 19, }; +struct cts_test_rawdata_ioctl_data { + int frames; + int min; + int max; +}; + +struct cts_test_noise_ioctl_data { + int frames; + int max; +}; + +struct cts_test_open_ioctl_data { + int min; + int max; +}; + +struct cts_test_short_ioctl_data { + int min; + int max; + bool display_on; + bool disable_gas; +}; + +struct cts_test_comp_cap_ioctl_data { + int min; + int max; +}; + +#define CTS_TOOL_IOCTL_GET_DRIVER_VERSION _IOR('C', 0x00, unsigned int) +#define CTS_TOOL_IOCTL_GET_DEVICE_TYPE _IOR('C', 0x01, unsigned int) +#define CTS_TOOL_IOCTL_GET_FW_VERSION _IOR('C', 0x02, unsigned short) + +#define CTS_TOOL_IOCTL_TEST_RESET_PIN _IO('C', 0x11) +#define CTS_TOOL_IOCTL_TEST_INT_PIN _IO('C', 0x12) +#define CTS_TOOL_IOCTL_TEST_DEVICE_TYPE _IOW('C', 0x13, unsigned int) +#define CTS_TOOL_IOCTL_TEST_FW_VERSION _IOW('C', 0x14, unsigned short) +#define CTS_TOOL_IOCTL_TEST_RAWDATA _IOW('C', 0x15, struct cts_test_rawdata_ioctl_data *) +#define CTS_TOOL_IOCTL_TEST_NOISE _IOW('C', 0x16, struct cts_test_noise_ioctl_data *) +#define CTS_TOOL_IOCTL_TEST_OPEN _IOW('C', 0x17, struct cts_test_open_ioctl_data *) +#define CTS_TOOL_IOCTL_TEST_SHORT _IOW('C', 0x18, struct cts_test_short_ioctl_data *) +#define CTS_TOOL_IOCTL_TEST_COMP_CAP _IOW('C', 0x19, struct cts_test_comp_cap_ioctl_data *) + +#define CTS_DRIVER_VERSION_CODE ((CFG_CTS_DRIVER_MAJOR_VERSION << 16) | \ + (CFG_CTS_DRIVER_MINOR_VERSION << 8) | \ + (CFG_CTS_DRIVER_PATCH_VERSION << 0)) + static struct cts_tool_cmd cts_tool_cmd; static char cts_tool_firmware_filepath[PATH_MAX]; /* If CFG_CTS_MAX_I2C_XFER_SIZE < 58(PC tool length), this is neccessary */ #ifdef CONFIG_CTS_I2C_HOST -static u32 cts_tool_direct_access_addr = 0; -#endif +//static u32 cts_tool_direct_access_addr = 0; +#endif /* CONFIG_CTS_I2C_HOST */ static int cts_tool_open(struct inode *inode, struct file *file) { - file->private_data = PDE_DATA(inode); - return 0; + file->private_data = PDE_DATA(inode); + return 0; } static ssize_t cts_tool_read(struct file *file, - char __user *buffer, size_t count, loff_t *ppos) + char __user *buffer, size_t count, loff_t *ppos) { - struct chipone_ts_data *cts_data; - struct cts_tool_cmd *cmd; - struct cts_device *cts_dev; - int ret = 0; + struct chipone_ts_data *cts_data; + struct cts_tool_cmd *cmd; + struct cts_device *cts_dev; + int ret = 0; - cts_data = (struct chipone_ts_data *)file->private_data; - if (cts_data == NULL) { - cts_err("Read with private_data = NULL"); - return -EIO; - } + cts_data = (struct chipone_ts_data *)file->private_data; + if (cts_data == NULL) { + cts_err("Read with private_data = NULL"); + return -EIO; + } - cmd = &cts_tool_cmd; - cts_dev = &cts_data->cts_dev; - cts_lock_device(cts_dev); + cmd = &cts_tool_cmd; + cts_dev = &cts_data->cts_dev; + cts_lock_device(cts_dev); - switch (cmd->cmd) { - case CTS_TOOL_CMD_GET_PANEL_PARAM: - cts_info("Get panel param len: %u", cmd->data_len); - ret = cts_get_panel_param(cts_dev, cmd->data, cmd->data_len); - if (ret) { - cts_err("Get panel param len: %u failed %d", cmd->data_len, ret); - } - break; + switch (cmd->cmd) { + case CTS_TOOL_CMD_GET_PANEL_PARAM: + cts_info("Get panel param len: %u", cmd->data_len); + ret = cts_get_panel_param(cts_dev, cmd->data, cmd->data_len); + if (ret) { + cts_err("Get panel param len: %u failed %d", + cmd->data_len, ret); + } + break; - case CTS_TOOL_CMD_GET_DOWNLOAD_STATUS: - cmd->data[0] = 100; - cts_info("Get update status = %hhu", cmd->data[0]); - break; + case CTS_TOOL_CMD_GET_DOWNLOAD_STATUS: + cmd->data[0] = 100; + cts_info("Get update status = %hhu", cmd->data[0]); + break; - case CTS_TOOL_CMD_GET_RAW_DATA: - case CTS_TOOL_CMD_GET_DIFF_DATA: - cts_dbg("Get %s data row: %u col: %u len: %u", - cmd->cmd == CTS_TOOL_CMD_GET_RAW_DATA ? "raw" : "diff", - cmd->addr[1], cmd->addr[0], cmd->data_len); + case CTS_TOOL_CMD_GET_RAW_DATA: + case CTS_TOOL_CMD_GET_DIFF_DATA: + cts_dbg("Get %s data row: %u col: %u len: %u", + cmd->cmd == CTS_TOOL_CMD_GET_RAW_DATA ? "raw" : "diff", + cmd->addr[1], cmd->addr[0], cmd->data_len); - ret = cts_enable_get_rawdata(cts_dev); - if (ret) { - cts_err("Enable read raw/diff data failed %d", ret); - break; - } - mdelay(1); + ret = cts_enable_get_rawdata(cts_dev); + if (ret) { + cts_err("Enable read raw/diff data failed %d", ret); + break; + } + mdelay(1); - if (cmd->cmd == CTS_TOOL_CMD_GET_RAW_DATA) { - ret = cts_get_rawdata(cts_dev, cmd->data); - } else if (cmd->cmd == CTS_TOOL_CMD_GET_DIFF_DATA) { - ret = cts_get_diffdata(cts_dev, cmd->data); - } - if(ret) { - cts_err("Get %s data failed %d", - cmd->cmd == CTS_TOOL_CMD_GET_RAW_DATA ? "raw" : "diff", ret); - break; - } + if (cmd->cmd == CTS_TOOL_CMD_GET_RAW_DATA) { + ret = cts_get_rawdata(cts_dev, cmd->data); + } else if (cmd->cmd == CTS_TOOL_CMD_GET_DIFF_DATA) { + ret = cts_get_diffdata(cts_dev, cmd->data); + } + if (ret) { + cts_err("Get %s data failed %d", + cmd->cmd == + CTS_TOOL_CMD_GET_RAW_DATA ? "raw" : "diff", + ret); + break; + } - ret = cts_disable_get_rawdata(cts_dev); - if (ret) { - cts_err("Disable read raw/diff data failed %d", ret); - break; - } + ret = cts_disable_get_rawdata(cts_dev); + if (ret) { + cts_err("Disable read raw/diff data failed %d", ret); + break; + } - break; + break; - case CTS_TOOL_CMD_READ_HOSTCOMM: - ret = cts_fw_reg_readb(cts_dev, - get_unaligned_le16(cmd->addr), cmd->data); - if (ret) { - cts_err("Read firmware reg addr 0x%04x failed %d", - get_unaligned_le16(cmd->addr), ret); - } else { - cts_dbg("Read firmware reg addr 0x%04x, val=0x%02x", - get_unaligned_le16(cmd->addr), cmd->data[0]); - } - break; + case CTS_TOOL_CMD_READ_HOSTCOMM: + ret = cts_fw_reg_readb(cts_dev, + get_unaligned_le16(cmd->addr), + cmd->data); + if (ret) { + cts_err("Read firmware reg addr 0x%04x failed %d", + get_unaligned_le16(cmd->addr), ret); + } else { + cts_dbg("Read firmware reg addr 0x%04x, val=0x%02x", + get_unaligned_le16(cmd->addr), cmd->data[0]); + } + break; #ifdef CFG_CTS_GESTURE - case CTS_TOOL_CMD_READ_GESTURE_INFO: - ret = cts_get_gesture_info(cts_dev, cmd->data, true); - if (ret) { - cts_err("Get gesture info failed %d", ret); - } - break; + case CTS_TOOL_CMD_READ_GESTURE_INFO: + ret = cts_get_gesture_info(cts_dev, cmd->data, true); + if (ret) { + cts_err("Get gesture info failed %d", ret); + } + break; #endif /* CFG_CTS_GESTURE */ - case CTS_TOOL_CMD_READ_HOSTCOMM_MULTIBYTE: - cmd->data_len = min((size_t)cmd->data_len, sizeof(cmd->data)); - ret = cts_fw_reg_readsb(cts_dev, get_unaligned_le16(cmd->addr), - cmd->data, cmd->data_len); - if (ret) { - cts_err("Read firmware reg addr 0x%04x len %u failed %d", - get_unaligned_le16(cmd->addr), cmd->data_len, ret); - } else { - cts_dbg("Read firmware reg addr 0x%04x len %u", - get_unaligned_le16(cmd->addr), cmd->data_len); - } - break; + case CTS_TOOL_CMD_READ_HOSTCOMM_MULTIBYTE: + cmd->data_len = min((size_t) cmd->data_len, sizeof(cmd->data)); + ret = cts_fw_reg_readsb(cts_dev, get_unaligned_le16(cmd->addr), + cmd->data, cmd->data_len); + if (ret) { + cts_err + ("Read firmware reg addr 0x%04x len %u failed %d", + get_unaligned_le16(cmd->addr), cmd->data_len, ret); + } else { + cts_dbg("Read firmware reg addr 0x%04x len %u", + get_unaligned_le16(cmd->addr), cmd->data_len); + } + break; - case CTS_TOOL_CMD_READ_PROGRAM_MODE_MULTIBYTE: - cts_dbg("Read under program mode addr 0x%06x len %u", - (cmd->flag << 16) | get_unaligned_le16(cmd->addr), - cmd->data_len); - ret = cts_enter_program_mode(cts_dev); - if (ret) { - cts_err("Enter program mode failed %d", ret); - break; - } + case CTS_TOOL_CMD_READ_PROGRAM_MODE_MULTIBYTE: + cts_dbg("Read under program mode addr 0x%06x len %u", + (cmd->flag << 16) | get_unaligned_le16(cmd->addr), + cmd->data_len); + ret = cts_enter_program_mode(cts_dev); + if (ret) { + cts_err("Enter program mode failed %d", ret); + break; + } - ret = cts_sram_readsb(&cts_data->cts_dev, - get_unaligned_le16(cmd->addr), cmd->data, cmd->data_len); - if (ret) { - cts_err("Read under program mode I2C xfer failed %d", ret); - //break; - } + ret = cts_sram_readsb(&cts_data->cts_dev, + get_unaligned_le16(cmd->addr), cmd->data, + cmd->data_len); + if (ret) { + cts_err("Read under program mode I2C xfer failed %d", + ret); + //break; + } - ret = cts_enter_normal_mode(cts_dev); - if (ret) { - cts_err("Enter normal mode failed %d", ret); - break; - } - break; + ret = cts_enter_normal_mode(cts_dev); + if (ret) { + cts_err("Enter normal mode failed %d", ret); + break; + } + break; - case CTS_TOOL_CMD_READ_ICTYPE: - cts_info("Get IC type"); - if (cts_dev->hwdata) { - switch(cts_dev->hwdata->hwid) { - case CTS_DEV_HWID_ICNL9911: cmd->data[0] = 0x91; break; - case CTS_DEV_HWID_ICNL9911S: cmd->data[0] = 0x91; break; - default: cmd->data[0] = 0x00; break; - } - } else { - cmd->data[0] = 0x10; - } - break; + case CTS_TOOL_CMD_READ_ICTYPE: + cts_info("Get IC type"); + if (cts_dev->hwdata) { + switch (cts_dev->hwdata->hwid) { + case CTS_DEV_HWID_ICNL9911: + cmd->data[0] = 0x91; + break; + case CTS_DEV_HWID_ICNL9911S: + cmd->data[0] = 0x91; + break; + default: + cmd->data[0] = 0x00; + break; + } + } else { + cmd->data[0] = 0x10; + } + break; #ifdef CONFIG_CTS_I2C_HOST - case CTS_TOOL_CMD_I2C_DIRECT_READ: - { - u32 addr_width; - char *wr_buff = NULL; - u8 addr_buff[4]; - size_t left_size, max_xfer_size; - u8 *data; + case CTS_TOOL_CMD_I2C_DIRECT_READ: + { + u32 addr_width; + char *wr_buff = NULL; + u8 addr_buff[4]; + size_t left_size, max_xfer_size; + u8 *data; - if (cmd->addr[0] != CTS_DEV_PROGRAM_MODE_I2CADDR) { - cmd->addr[0] = CTS_DEV_NORMAL_MODE_I2CADDR; - addr_width = 2; - } else { - addr_width = cts_dev->hwdata->program_addr_width; - } + if (cmd->addr[0] != CTS_DEV_PROGRAM_MODE_I2CADDR) { + cmd->addr[0] = CTS_DEV_NORMAL_MODE_I2CADDR; + addr_width = 2; + } else { + addr_width = + cts_dev->hwdata->program_addr_width; + } - cts_dbg("Direct read from i2c_addr 0x%02x addr 0x%06x size %u", - cmd->addr[0], cts_tool_direct_access_addr, cmd->data_len); + cts_dbg + ("Direct read from i2c_addr 0x%02x addr 0x%06x size %u", + cmd->addr[0], cts_tool_direct_access_addr, + cmd->data_len); - left_size = cmd->data_len; - max_xfer_size = cts_plat_get_max_i2c_xfer_size(cts_dev->pdata); - data = cmd->data; - while (left_size) { - size_t xfer_size = min(left_size, max_xfer_size); - ret = cts_plat_i2c_read(cts_data->pdata, cmd->addr[0], - wr_buff, addr_width, data, xfer_size, 1, 0); - if (ret) { - cts_err("Direct read i2c_addr 0x%02x addr 0x%06x len %zu failed %d", - cmd->addr[0], cts_tool_direct_access_addr, xfer_size, ret); - break; - } + left_size = cmd->data_len; + max_xfer_size = + cts_plat_get_max_i2c_xfer_size(cts_dev->pdata); + data = cmd->data; + while (left_size) { + size_t xfer_size = + min(left_size, max_xfer_size); + ret = + cts_plat_i2c_read(cts_data->pdata, + cmd->addr[0], wr_buff, + addr_width, data, + xfer_size, 1, 0); + if (ret) { + cts_err + ("Direct read i2c_addr 0x%02x addr 0x%06x len %zu failed %d", + cmd->addr[0], + cts_tool_direct_access_addr, + xfer_size, ret); + break; + } - left_size -= xfer_size; - if (left_size) { - data += xfer_size; - cts_tool_direct_access_addr += xfer_size; - if (addr_width == 2) { - put_unaligned_be16(cts_tool_direct_access_addr, addr_buff); - } else if (addr_width == 3) { - put_unaligned_be24(cts_tool_direct_access_addr, addr_buff); - } - wr_buff = addr_buff; - } - } - } - break; + left_size -= xfer_size; + if (left_size) { + data += xfer_size; + cts_tool_direct_access_addr += + xfer_size; + if (addr_width == 2) { + put_unaligned_be16 + (cts_tool_direct_access_addr, + addr_buff); + } else if (addr_width == 3) { + put_unaligned_be24 + (cts_tool_direct_access_addr, + addr_buff); + } + wr_buff = addr_buff; + } + } + } + break; #endif - case CTS_TOOL_CMD_GET_DRIVER_INFO: - break; + case CTS_TOOL_CMD_GET_DRIVER_INFO: + break; - default: - cts_warn("Read unknown command %u", cmd->cmd); - ret = -EINVAL; - break; - } + default: + cts_warn("Read unknown command %u", cmd->cmd); + ret = -EINVAL; + break; + } - cts_unlock_device(cts_dev); + cts_unlock_device(cts_dev); - if (ret == 0) { - if(cmd->cmd == CTS_TOOL_CMD_I2C_DIRECT_READ) { - ret = copy_to_user(buffer + CTS_TOOL_CMD_HEADER_LENGTH, - cmd->data, cmd->data_len); - } else { - ret = copy_to_user(buffer, cmd->data, cmd->data_len); - } - if (ret) { - cts_err("Copy data to user buffer failed %d", ret); - return 0; - } + if (ret == 0) { + if (cmd->cmd == CTS_TOOL_CMD_I2C_DIRECT_READ) { + ret = copy_to_user(buffer + CTS_TOOL_CMD_HEADER_LENGTH, + cmd->data, cmd->data_len); + } else { + ret = copy_to_user(buffer, cmd->data, cmd->data_len); + } + if (ret) { + cts_err("Copy data to user buffer failed %d", ret); + return 0; + } - return cmd->data_len; - } + return cmd->data_len; + } - return 0; + return 0; } static ssize_t cts_tool_write(struct file *file, - const char __user * buffer, size_t count, loff_t * ppos) + const char __user *buffer, size_t count, + loff_t *ppos) { - struct chipone_ts_data *cts_data; - struct cts_device *cts_dev; - struct cts_tool_cmd *cmd; - int ret = 0; + struct chipone_ts_data *cts_data; + struct cts_device *cts_dev; + struct cts_tool_cmd *cmd; + int ret = 0; - if (count < CTS_TOOL_CMD_HEADER_LENGTH || count > PAGE_SIZE) { - cts_err("Write len %zu invalid", count); - return -EFAULT; - } + if (count < CTS_TOOL_CMD_HEADER_LENGTH || count > PAGE_SIZE) { + cts_err("Write len %zu invalid", count); + return -EFAULT; + } - cts_data = (struct chipone_ts_data *)file->private_data; - if (cts_data == NULL) { - cts_err("Write with private_data = NULL"); - return -EIO; - } + cts_data = (struct chipone_ts_data *)file->private_data; + if (cts_data == NULL) { + cts_err("Write with private_data = NULL"); + return -EIO; + } - cmd = &cts_tool_cmd; - ret = copy_from_user(cmd, buffer, CTS_TOOL_CMD_HEADER_LENGTH); - if (ret) { - cts_err("Copy command header from user buffer failed %d", ret); - return -EIO; - } else { - ret = CTS_TOOL_CMD_HEADER_LENGTH; - } + cmd = &cts_tool_cmd; + ret = copy_from_user(cmd, buffer, CTS_TOOL_CMD_HEADER_LENGTH); + if (ret) { + cts_err("Copy command header from user buffer failed %d", ret); + return -EIO; + } else { + ret = CTS_TOOL_CMD_HEADER_LENGTH; + } - if (cmd->data_len > PAGE_SIZE) { - cts_err("Write with invalid count %d", cmd->data_len); - return -EIO; - } + if (cmd->data_len > PAGE_SIZE) { + cts_err("Write with invalid count %d", cmd->data_len); + return -EIO; + } - if(cmd->cmd & BIT(0)) { - if(cmd->data_len) { - ret = copy_from_user(cmd->data, - buffer + CTS_TOOL_CMD_HEADER_LENGTH, cmd->data_len); - if (ret) { - cts_err("Copy command payload from user buffer len %u failed %d", - cmd->data_len, ret); - return -EIO; - } - } - } else { - /* Prepare for read command */ - cts_dbg("Write read command(%d) header, prepare read size: %d", - cmd->cmd, cmd->data_len); - return CTS_TOOL_CMD_HEADER_LENGTH + cmd->data_len; - } + if (cmd->cmd & BIT(0)) { + if (cmd->data_len) { + ret = copy_from_user(cmd->data, + buffer + + CTS_TOOL_CMD_HEADER_LENGTH, + cmd->data_len); + if (ret) { + cts_err + ("Copy command payload from user buffer len %u failed %d", + cmd->data_len, ret); + return -EIO; + } + } + } else { + /* Prepare for read command */ + cts_dbg("Write read command(%d) header, prepare read size: %d", + cmd->cmd, cmd->data_len); + return CTS_TOOL_CMD_HEADER_LENGTH + cmd->data_len; + } - cts_dev = &cts_data->cts_dev; - cts_lock_device(cts_dev); + cts_dev = &cts_data->cts_dev; + cts_lock_device(cts_dev); - switch (cmd->cmd) { - case CTS_TOOL_CMD_UPDATE_PANEL_PARAM_IN_SRAM: - cts_info("Write panel param len %u data\n", cmd->data_len); - ret = cts_fw_reg_writesb(cts_dev, CTS_DEVICE_FW_REG_PANEL_PARAM, - cmd->data, cmd->data_len); - if (ret) { - cts_err("Write panel param failed %d", ret); - break; - } + switch (cmd->cmd) { + case CTS_TOOL_CMD_UPDATE_PANEL_PARAM_IN_SRAM: + cts_info("Write panel param len %u data\n", cmd->data_len); + ret = cts_fw_reg_writesb(cts_dev, CTS_DEVICE_FW_REG_PANEL_PARAM, + cmd->data, cmd->data_len); + if (ret) { + cts_err("Write panel param failed %d", ret); + break; + } - ret = cts_send_command(cts_dev, CTS_CMD_RESET); - if (ret) { + ret = cts_send_command(cts_dev, CTS_CMD_RESET); + if (ret) { - } + } - ret = cts_set_work_mode(cts_dev, 1); - if (ret) { + ret = cts_set_work_mode(cts_dev, 1); + if (ret) { - } + } - mdelay(100); + mdelay(100); - ret = cts_set_work_mode(cts_dev, 0); - if (ret) { + ret = cts_set_work_mode(cts_dev, 0); + if (ret) { - } - mdelay(100); + } + mdelay(100); - break; + break; - case CTS_TOOL_CMD_DOWNLOAD_FIRMWARE_WITH_FILENAME: - cts_info("Write firmware path: '%.*s'", - cmd->data_len, cmd->data); + case CTS_TOOL_CMD_DOWNLOAD_FIRMWARE_WITH_FILENAME: + cts_info("Write firmware path: '%.*s'", + cmd->data_len, cmd->data); - memcpy(cts_tool_firmware_filepath, cmd->data, cmd->data_len); - cts_tool_firmware_filepath[cmd->data_len] = '\0'; - break; + memcpy(cts_tool_firmware_filepath, cmd->data, cmd->data_len); + cts_tool_firmware_filepath[cmd->data_len] = '\0'; + break; - case CTS_TOOL_CMD_DOWNLOAD_FIRMWARE: - cts_info("Start download firmware path: '%s'", - cts_tool_firmware_filepath); + case CTS_TOOL_CMD_DOWNLOAD_FIRMWARE: + cts_info("Start download firmware path: '%s'", + cts_tool_firmware_filepath); - ret = cts_stop_device(cts_dev); - if (ret) { - cts_err("Stop device failed %d", ret); - break; - } + ret = cts_stop_device(cts_dev); + if (ret) { + cts_err("Stop device failed %d", ret); + break; + } + // TODO: Use async mode such as thread, otherwise, host can not get update status. + ret = + cts_update_firmware_from_file(cts_dev, + cts_tool_firmware_filepath, + true); + if (ret) { + cts_err("Updata firmware failed %d", ret); + //break; + } - // TODO: Use async mode such as thread, otherwise, host can not get update status. - cts_unlock_device(cts_dev); - ret = cts_update_firmware_from_file(cts_dev, cts_tool_firmware_filepath, true); - if (ret) { - cts_err("Updata firmware failed %d", ret); - //break; - } - cts_lock_device(cts_dev); + ret = cts_start_device(cts_dev); + if (ret) { + cts_err("Start device failed %d", ret); + break; + } + break; - ret = cts_start_device(cts_dev); - if (ret) { - cts_err("Start device failed %d", ret); - break; - } - break; + case CTS_TOOL_CMD_WRITE_HOSTCOMM: + cts_dbg("Write firmware reg addr: 0x%04x val=0x%02x", + get_unaligned_le16(cmd->addr), cmd->data[0]); - case CTS_TOOL_CMD_WRITE_HOSTCOMM: - cts_dbg("Write firmware reg addr: 0x%04x val=0x%02x", - get_unaligned_le16(cmd->addr), cmd->data[0]); + ret = cts_fw_reg_writeb(cts_dev, + get_unaligned_le16(cmd->addr), + cmd->data[0]); + if (ret) { + cts_err + ("Write firmware reg addr: 0x%04x val=0x%02x failed %d", + get_unaligned_le16(cmd->addr), cmd->data[0], ret); + } + break; - ret = cts_fw_reg_writeb(cts_dev, - get_unaligned_le16(cmd->addr), cmd->data[0]); - if (ret) { - cts_err("Write firmware reg addr: 0x%04x val=0x%02x failed %d", - get_unaligned_le16(cmd->addr), cmd->data[0], ret); - } - break; + case CTS_TOOL_CMD_WRITE_HOSTCOMM_MULTIBYTE: + cts_dbg("Write firmare reg addr: 0x%04x len %u", + get_unaligned_le16(cmd->addr), cmd->data_len); + ret = cts_fw_reg_writesb(cts_dev, get_unaligned_le16(cmd->addr), + cmd->data, cmd->data_len); + if (ret) { + cts_err + ("Write firmare reg addr: 0x%04x len %u failed %d", + get_unaligned_le16(cmd->addr), cmd->data_len, ret); + } + break; - case CTS_TOOL_CMD_WRITE_HOSTCOMM_MULTIBYTE: - cts_dbg("Write firmare reg addr: 0x%04x len %u", - get_unaligned_le16(cmd->addr), cmd->data_len); - ret = cts_fw_reg_writesb(cts_dev, get_unaligned_le16(cmd->addr), - cmd->data, cmd->data_len); - if (ret) { - cts_err("Write firmare reg addr: 0x%04x len %u failed %d", - get_unaligned_le16(cmd->addr), cmd->data_len, ret); - } - break; + case CTS_TOOL_CMD_WRITE_PROGRAM_MODE_MULTIBYTE: + cts_dbg("Write to addr 0x%06x size %u under program mode", + (cmd->flag << 16) | (cmd->addr[1] << 8) | cmd->addr[0], + cmd->data_len); + ret = cts_enter_program_mode(cts_dev); + if (ret) { + cts_err("Enter program mode failed %d", ret); + break; + } - case CTS_TOOL_CMD_WRITE_PROGRAM_MODE_MULTIBYTE: - cts_dbg("Write to addr 0x%06x size %u under program mode", - (cmd->flag << 16) | (cmd->addr[1] << 8) | cmd->addr[0], - cmd->data_len); - ret = cts_enter_program_mode(cts_dev); - if (ret) { - cts_err("Enter program mode failed %d", ret); - break; - } + ret = cts_sram_writesb(cts_dev, + (cmd->flag << 16) | (cmd->addr[1] << 8) | + cmd->addr[0], cmd->data, cmd->data_len); + if (ret) { + cts_err("Write program mode multibyte failed %d", ret); + //break; + } - ret = cts_sram_writesb(cts_dev, - (cmd->flag << 16) | (cmd->addr[1] << 8) | cmd->addr[0], - cmd->data, cmd->data_len); - if (ret) { - cts_err("Write program mode multibyte failed %d", ret); - //break; - } + ret = cts_enter_normal_mode(cts_dev); + if (ret) { + cts_err("Enter normal mode failed %d", ret); + break; + } - ret = cts_enter_normal_mode(cts_dev); - if (ret) { - cts_err("Enter normal mode failed %d", ret); - break; - } - - break; + break; #ifdef CONFIG_CTS_I2C_HOST - case CTS_TOOL_CMD_I2C_DIRECT_WRITE: - { - u32 addr_width; - size_t left_payload_size; /* Payload exclude address field */ - size_t max_xfer_size; - char *payload; + case CTS_TOOL_CMD_I2C_DIRECT_WRITE: + { + u32 addr_width; + size_t left_payload_size; /* Payload exclude address field */ + size_t max_xfer_size; + char *payload; - if (cmd->addr[0] != CTS_DEV_PROGRAM_MODE_I2CADDR) { - cmd->addr[0] = CTS_DEV_NORMAL_MODE_I2CADDR; - addr_width = 2; - cts_tool_direct_access_addr = get_unaligned_be16(cmd->data); - } else { - addr_width = cts_dev->hwdata->program_addr_width; - cts_tool_direct_access_addr = get_unaligned_be24(cmd->data); - } + if (cmd->addr[0] != CTS_DEV_PROGRAM_MODE_I2CADDR) { + cmd->addr[0] = CTS_DEV_NORMAL_MODE_I2CADDR; + addr_width = 2; + cts_tool_direct_access_addr = + get_unaligned_be16(cmd->data); + } else { + addr_width = + cts_dev->hwdata->program_addr_width; + cts_tool_direct_access_addr = + get_unaligned_be24(cmd->data); + } - if (cmd->data_len < addr_width) { - cts_err("Direct write too short %d < address width %d", - cmd->data_len, addr_width); - ret = -EINVAL; - break; - } + if (cmd->data_len < addr_width) { + cts_err + ("Direct write too short %d < address width %d", + cmd->data_len, addr_width); + ret = -EINVAL; + break; + } - cts_dbg("Direct write to i2c_addr 0x%02x addr 0x%06x size %u", - cmd->addr[0], cts_tool_direct_access_addr, cmd->data_len); + cts_dbg + ("Direct write to i2c_addr 0x%02x addr 0x%06x size %u", + cmd->addr[0], cts_tool_direct_access_addr, + cmd->data_len); - left_payload_size = cmd->data_len - addr_width; - max_xfer_size = cts_plat_get_max_i2c_xfer_size(cts_dev->pdata); - payload = cmd->data + addr_width; - do { - size_t xfer_payload_size = min(left_payload_size, - max_xfer_size - addr_width); - size_t xfer_len = xfer_payload_size + addr_width; + left_payload_size = cmd->data_len - addr_width; + max_xfer_size = + cts_plat_get_max_i2c_xfer_size(cts_dev->pdata); + payload = cmd->data + addr_width; + do { + size_t xfer_payload_size = + min(left_payload_size, + max_xfer_size - addr_width); + size_t xfer_len = + xfer_payload_size + addr_width; - ret = cts_plat_i2c_write(cts_data->pdata, cmd->addr[0], - payload - addr_width, xfer_len, 1, 0); - if (ret) { - cts_err("Direct write i2c_addr 0x%02x addr 0x%06x len %zu failed %d", - cmd->addr[0], cts_tool_direct_access_addr, xfer_len, ret); - break; - } + ret = + cts_plat_i2c_write(cts_data->pdata, + cmd->addr[0], + payload - addr_width, + xfer_len, 1, 0); + if (ret) { + cts_err + ("Direct write i2c_addr 0x%02x addr 0x%06x len %zu failed %d", + cmd->addr[0], + cts_tool_direct_access_addr, + xfer_len, ret); + break; + } - left_payload_size -= xfer_payload_size; - if (left_payload_size) { - payload += xfer_payload_size; - cts_tool_direct_access_addr += xfer_payload_size; - if (addr_width == 2) { - put_unaligned_be16(cts_tool_direct_access_addr, payload - addr_width); - } else if (addr_width == 3) { - put_unaligned_be24(cts_tool_direct_access_addr, payload - addr_width); - } - } - } while (left_payload_size); - } - break; + left_payload_size -= xfer_payload_size; + if (left_payload_size) { + payload += xfer_payload_size; + cts_tool_direct_access_addr += + xfer_payload_size; + if (addr_width == 2) { + put_unaligned_be16 + (cts_tool_direct_access_addr, + payload - addr_width); + } else if (addr_width == 3) { + put_unaligned_be24 + (cts_tool_direct_access_addr, + payload - addr_width); + } + } + } while (left_payload_size); + } + break; #endif - default: - cts_warn("Write unknown command %u", cmd->cmd); - ret = -EINVAL; - break; - } + default: + cts_warn("Write unknown command %u", cmd->cmd); + ret = -EINVAL; + break; + } - cts_unlock_device(cts_dev); + cts_unlock_device(cts_dev); - return ret ? 0 : cmd->data_len + CTS_TOOL_CMD_HEADER_LENGTH; + return ret ? 0 : cmd->data_len + CTS_TOOL_CMD_HEADER_LENGTH; +} + +static long cts_tool_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct chipone_ts_data *cts_data; + struct cts_device *cts_dev; + + cts_info("ioctl, cmd=0x%04x, arg=0x%02lx", cmd, arg); + + cts_data = file->private_data; + if (cts_data == NULL) { + cts_err("IOCTL with private data = NULL"); + return -EFAULT; + } + + cts_dev = &cts_data->cts_dev; + + switch (cmd) { + case CTS_TOOL_IOCTL_GET_DRIVER_VERSION: + return put_user(CTS_DRIVER_VERSION_CODE, + (unsigned int __user *)arg); + case CTS_TOOL_IOCTL_GET_DEVICE_TYPE: + return put_user(cts_dev->hwdata->hwid, + (unsigned int __user *)arg); + case CTS_TOOL_IOCTL_GET_FW_VERSION: + return put_user(cts_dev->fwdata.version, + (unsigned short __user *)arg); + + case CTS_TOOL_IOCTL_TEST_RESET_PIN:{ + return cts_reset_test(cts_dev); + } + case CTS_TOOL_IOCTL_TEST_INT_PIN:{ + return cts_test_int_pin(cts_dev); + } + case CTS_TOOL_IOCTL_TEST_DEVICE_TYPE:{ + if (cts_dev->hwdata->hwid == (u32) arg) { + return 0; + } + return -EINVAL; + } + case CTS_TOOL_IOCTL_TEST_FW_VERSION:{ + if (cts_dev->fwdata.version == (u16) arg) { + return 0; + } + return -EINVAL; + } + case CTS_TOOL_IOCTL_TEST_RAWDATA:{ + struct cts_test_rawdata_ioctl_data param; + + if (copy_from_user(¶m, + (struct cts_test_rawdata_ioctl_data + __user *)arg, sizeof(param))) + return -EFAULT; + + return cts_rawdata_test(cts_dev, param.min, param.max); + } + case CTS_TOOL_IOCTL_TEST_NOISE:{ + struct cts_test_noise_ioctl_data param; + + if (copy_from_user(¶m, + (struct cts_test_noise_ioctl_data + __user *)arg, sizeof(param))) + return -EFAULT; + + return cts_noise_test(cts_dev, param.frames, param.max); + } + case CTS_TOOL_IOCTL_TEST_OPEN:{ + struct cts_test_open_ioctl_data param; + + if (copy_from_user(¶m, + (struct cts_test_open_ioctl_data + __user *)arg, sizeof(param))) + return -EFAULT; + + return cts_open_test(cts_dev, param.max); + } + case CTS_TOOL_IOCTL_TEST_SHORT:{ + struct cts_test_short_ioctl_data param; + + if (copy_from_user(¶m, + (struct cts_test_short_ioctl_data + __user *)arg, sizeof(param))) + return -EFAULT; + + return cts_short_test(cts_dev, param.max); + } + case CTS_TOOL_IOCTL_TEST_COMP_CAP:{ + struct cts_test_comp_cap_ioctl_data param; + + if (copy_from_user(¶m, + (struct cts_test_comp_cap_ioctl_data + __user *)arg, sizeof(param))) + return -EFAULT; + + return cts_compensate_cap_test(cts_dev, param.min, + param.max); + } + + default: + break; + } + + return -ENOTSUPP; } static struct file_operations cts_tool_fops = { - .owner = THIS_MODULE, - .open = cts_tool_open, - .read = cts_tool_read, - .write = cts_tool_write, + .owner = THIS_MODULE, + .llseek = no_llseek, + .open = cts_tool_open, + .read = cts_tool_read, + .write = cts_tool_write, + .unlocked_ioctl = cts_tool_ioctl, }; int cts_tool_init(struct chipone_ts_data *cts_data) { - cts_info("Init"); + cts_info("Init"); - cts_data->procfs_entry = proc_create_data(CFG_CTS_TOOL_PROC_FILENAME, - 0666, NULL, &cts_tool_fops, cts_data); - if (cts_data->procfs_entry == NULL) { - cts_err("Create proc entry failed"); - return -EFAULT; - } + cts_data->procfs_entry = proc_create_data(CFG_CTS_TOOL_PROC_FILENAME, + 0666, NULL, &cts_tool_fops, + cts_data); + if (cts_data->procfs_entry == NULL) { + cts_err("Create proc entry failed"); + return -EFAULT; + } - return 0; + return 0; } void cts_tool_deinit(struct chipone_ts_data *data) { - cts_info("Deinit"); + cts_info("Deinit"); - if (data->procfs_entry) { - remove_proc_entry(CFG_CTS_TOOL_PROC_FILENAME, NULL); - } + if (data->procfs_entry) { + remove_proc_entry(CFG_CTS_TOOL_PROC_FILENAME, NULL); + } } #endif /* CONFIG_CTS_LEGACY_TOOL */ -