#include "linux/module.h" #define GESTURE_LICH 1 #ifndef GSL_VERSION #define GSL_VERSION 0x20140829 #endif #ifndef NULL #define NULL ((void *)0) #endif #ifndef UINT #define UINT unsigned int #endif #define POINT_MAX 10 #define PP_DEEP 10 #define PS_DEEP 10 #define PR_DEEP 10 #define POINT_DEEP (PP_DEEP + PS_DEEP + PR_DEEP) #define PRESSURE_DEEP 8 #define CONFIG_LENGTH 512 #define TRUE 1 #define FALSE 0 #define FLAG_ABLE (0x4 << 12) #define FLAG_FILL (0x2 << 12) #define FLAG_KEY (0x1 << 12) #define FLAG_COOR (0x0fff0fff) #define FLAG_COOR_EX (0xffff0fff) #define FLAG_ID (0xf0000000) struct gsl_touch_info { int x[10]; int y[10]; int id[10]; int finger_num; }; typedef struct { unsigned int i; unsigned int j; unsigned int min; unsigned int d[POINT_MAX][POINT_MAX]; } gsl_DISTANCE_TYPE; typedef union { struct { unsigned y:12; unsigned key:1; unsigned fill:1; unsigned able:1; unsigned predict:1; unsigned x:16; }; struct { unsigned y:13; unsigned rev_2:3; unsigned x:16; } dis; unsigned int all; } gsl_POINT_TYPE; typedef union { struct { unsigned delay:8; unsigned report:8; unsigned rev_1:14; unsigned able:1; unsigned init:1; }; unsigned int all; } gsl_DELAY_TYPE; typedef union { struct { unsigned rev_0:8; unsigned rev_1:8; unsigned rev_2:7; unsigned ex:1; unsigned interpolation:4; unsigned rev_3:1; unsigned only:1; unsigned mask:1; unsigned reset:1; }; unsigned int all; } gsl_STATE_TYPE; typedef struct { unsigned int rate; unsigned int dis; gsl_POINT_TYPE coor; } gsl_EDGE_TYPE; typedef union { struct { short y; short x; }; unsigned int all; } gsl_DECIMAL_TYPE; typedef union { struct { unsigned over_report_mask:1; unsigned opposite_x:1; unsigned opposite_y:1; unsigned opposite_xy:1; unsigned line:1; unsigned line_neg:1; unsigned line_half:1; unsigned middle_drv:1; unsigned key_only_one:1; unsigned key_line:1; unsigned refe_rt:1; unsigned refe_var:1; unsigned base_median:1; unsigned key_rt:1; unsigned refe_reset:1; unsigned sub_cross:1; unsigned row_neg:1; unsigned sub_line_coe:1; unsigned sub_row_coe:1; unsigned c2f_able:1; unsigned thumb:1; unsigned graph_h:1; unsigned init_repeat:1; unsigned near_reset_able:1; unsigned emb_dead:1; unsigned emb_point_mask:1; unsigned interpolation:1; unsigned sum2_able:1; unsigned reduce_pin:1; unsigned drv_order_ex:1; unsigned id_over:1; unsigned rev_1:1; }; unsigned int all; } gsl_FLAG_TYPE; static gsl_POINT_TYPE point_array[POINT_DEEP][POINT_MAX]; static gsl_POINT_TYPE *point_pointer[PP_DEEP]; static gsl_POINT_TYPE *point_stretch[PS_DEEP]; static gsl_POINT_TYPE *point_report[PR_DEEP]; static gsl_POINT_TYPE point_now[POINT_MAX]; static gsl_DELAY_TYPE point_delay[POINT_MAX]; static int filter_deep[POINT_MAX]; static gsl_EDGE_TYPE point_edge; static gsl_DECIMAL_TYPE point_decimal[POINT_MAX]; static unsigned int pressure_now[POINT_MAX]; static unsigned int pressure_array[PRESSURE_DEEP][POINT_MAX]; static unsigned int pressure_report[POINT_MAX]; static unsigned int *pressure_pointer[PRESSURE_DEEP]; #define pp point_pointer #define ps point_stretch #define pr point_report #define point_predict pp[0] #define pa pressure_pointer static gsl_STATE_TYPE global_state; static int inte_count; static unsigned int csensor_count; static unsigned int click_count[4]; static gsl_POINT_TYPE point_click[4]; static unsigned int double_click; static int point_n; static int point_num; static int prev_num; static int point_near; static unsigned int point_shake; static unsigned int reset_mask_send; static unsigned int reset_mask_max; static unsigned int reset_mask_count; static gsl_FLAG_TYPE global_flag; static unsigned int id_first_coe; static unsigned int id_speed_coe; static unsigned int id_static_coe; static unsigned int average; static unsigned int soft_average; static unsigned int report_delay; static unsigned int report_ahead; static unsigned char median_dis[4]; static unsigned int shake_min; static int match_y[2]; static int match_x[2]; static int ignore_y[2]; static int ignore_x[2]; static int screen_y_max; static int screen_x_max; static int point_num_max; static unsigned int drv_num; static unsigned int sen_num; static unsigned int drv_num_nokey; static unsigned int sen_num_nokey; static unsigned int coordinate_correct_able; static unsigned int coordinate_correct_coe_x[64]; static unsigned int coordinate_correct_coe_y[64]; static unsigned int edge_cut[4]; static unsigned int stretch_array[4*4*2]; static unsigned int shake_all_array[2*8]; static unsigned int reset_mask_dis; static unsigned int reset_mask_type; static unsigned int key_map_able; static unsigned int key_range_array[8*3]; static int filter_able; static unsigned int filter_coe[4]; static unsigned int multi_x_array[4], multi_y_array[4]; static unsigned int multi_group[4][64]; static int ps_coe[4][8], pr_coe[4][8]; static int point_repeat[2]; static int near_set[2]; static int diagonal; static int point_extend; /* unsigned int key_dead_time; * unsigned int point_dead_time; * unsigned int point_dead_time2; * unsigned int point_dead_distance; * unsigned int point_dead_distance2; * unsigned int pressure_able; * unsigned int pressure_save[POINT_MAX]; */ static unsigned int edge_first; static unsigned int edge_first_coe; static unsigned int point_corner; static unsigned int config_static[CONFIG_LENGTH]; #ifdef GESTURE_LICH #define GESTURE_BUF_SIZE 256 #define GESTURE_SIZE_REFE 255 #define GESTURE_SIZE_NUM 32 #define GESTURE_XY 0x1 #define GESTURE_DEAL 0x2 #define GESTURE_LRUD 0x4 #define GESTURE_ALL 0x7fffffff typedef union { struct { unsigned y:12; unsigned rev:4; unsigned x:16; }; unsigned int all; } GESTURE_POINT_TYPE; typedef struct { int coe; int out; unsigned int coor[GESTURE_SIZE_NUM/2]; } GESTURE_MODEL_TYPE; #define gesture_buf ((GESTURE_POINT_TYPE *)config_static) #define gesture_standard ((GESTURE_POINT_TYPE *)(&config_static[GESTURE_BUF_SIZE])) static int gesture_num, gesture_num_last; static int gesture_dis_min; static int gesture_deal; static int gesture_last = 0, gesture_value; static int gesture_threshold[2]; static int x_scale; static int y_scale; static int double_down, double_up; typedef struct { int dis; int count; } GESTURE_MULTI_TYPE; static GESTURE_MULTI_TYPE multi_x[5]; static GESTURE_MULTI_TYPE multi_o[5]; static int gesture_multi; static unsigned int multi_set; static unsigned int gesture_flag; static const GESTURE_MODEL_TYPE *model_extern; static int model_extern_len; static int GestureSqrt(int d); static int GestureDistance(GESTURE_POINT_TYPE *d1, GESTURE_POINT_TYPE *d2, int sqrt_able); static int GesturePush(GESTURE_POINT_TYPE *data); static int GestureStretch(void); static int GestureLength(void); static int GestureDeal(void); static int GestureModel(const GESTURE_MODEL_TYPE *model, int len, int threshold, int *out); static int GestureMain(unsigned int data[], unsigned int pn); static void GestureStandard(void); static void GestureInit(void); static void ChangeXY(void); static int GestureLRUD(void); static void GestureSet(unsigned int conf[]); static int GestureMulti(unsigned int *data_in); static void GestureOrientation(int ori); static int GestureJoint(void); static unsigned int (*ReadIICInt)(unsigned int *data, unsigned int addr, unsigned int len); static const GESTURE_MODEL_TYPE model_default[] = { {0x10, '3', { 0x37170105, 0x78580000, 0xba990a03, 0xedd92e14, 0xb9d85347, 0x7798655b, 0x3657716b, 0x1f156d74, 0x60406969, 0xa2816f69, 0xe3c28075, 0xf9fbb899, 0xc3e3e0d2, 0x83a4f6ee, 0x4262fffc, 0x0021f7fd,} }, {0x10, '6', { 0xa2be0400, 0x70881f10, 0x4258402e, 0x1d2e6c54, 0x040ea084, 0x0a01d6bc, 0x381df9ec, 0x7054fffd, 0xa88cfafe, 0xdac2ddef, 0xfff0b2cb, 0xe2f78497, 0xaac7747a, 0x728e7472, 0x3b56817b, 0x0420968b,} }, {0x10, '7', { 0x12000001, 0x37240000, 0x5b490000, 0x806e0000, 0xa5930000, 0xcab70000, 0xefdc0300, 0xf9fd1f0e, 0xe2ee3d30, 0xc5d4564a, 0xa7b76c61, 0x8c9a8579, 0x717e9f93, 0x5863bbad, 0x434cdbc9, 0x3c3dffec,} }, {0x10, '8', { 0xdaff030c, 0x8eb40000, 0x41670c06, 0x001c3116, 0x431e5448, 0x8f69635d, 0xd1b58a6f, 0xcedfd0af, 0x88acf5e6, 0x3c62fffd, 0x0718cdf1, 0x341493aa, 0x7a556d7d, 0xc19e4f60, 0xf9e51c3c, 0xb5dc0005,} }, {0x10, '8', { 0x627d231e, 0x2f49382c, 0x03175a48, 0x21098172, 0x563c958c, 0x856eb0a2, 0x8f99dac4, 0x5b76eee5, 0x243ffdf5, 0x090ddbf4, 0x2918acc2, 0x4d3a8497, 0x78636172, 0xa38e4050, 0xd0ba1f2e, 0xffe7000f,} }, {0x10, '9', { 0xe8ff0715, 0xb4ce0001, 0x819a0500, 0x4f68150c, 0x1e362a1e, 0x000c543c, 0x270d7169, 0x5b417273, 0x9076666d, 0xbda74a5a, 0xddcf1e36, 0xc8d7321b, 0xb4be634b, 0xa4ac967d, 0x959ccab0, 0x898fffe4,} }, {0x10, 'A', { 0xaeca000b, 0x74900e02, 0x41582d1b, 0x182a5942, 0x02099375, 0x0600cfb1, 0x2c15fcea, 0x664af1fe, 0x957ec8dd, 0xb5a894b0, 0xc9bf5876, 0xd7d31c3a, 0xd4d75134, 0xd3d38d6f, 0xdbd4c9ab, 0xffe9fce6,} }, {0x10, 'A', { 0x8eab0102, 0x56711307, 0x2c3f3a25, 0x0e1b6b51, 0x0004a689, 0x0e02ddc2, 0x3e22fbf2, 0x725be8fa, 0x9284b6d0, 0xa69d7f9b, 0xb3ae4562, 0xb7b80b28, 0xa7a6290c, 0xb1aa6346, 0xd0be947d, 0xffe7bba7,} }, {0x10, 'B', { 0x56591a00, 0x474e4e35, 0x343f8168, 0x242cb59c, 0x0f1be7ce, 0x170ddbf4, 0x3c25b4c4, 0x6e549ca6, 0xa3889799, 0xd8bd9d96, 0xfcf1bea8, 0xd3e9e4d4, 0xa0baf6f0, 0x6b85fcfa, 0x3650fffd, 0x001bfbff,} }, {0x10, 'C', { 0xfaff2337, 0xdaec0913, 0xb0c50003, 0x879c0500, 0x5f720f09, 0x3b4c271a, 0x1d2b4534, 0x08116a56, 0x0003937f, 0x0a03bca8, 0x2515ddce, 0x4b38f2e8, 0x7560fff9, 0x9e89f7fd, 0xc6b2e8f0, 0xeed9d7df,} }, {0x10, 'C', { 0xacbf0100, 0x86990a04, 0x64751b12, 0x45533225, 0x2b375141, 0x17217160, 0x080f9582, 0x0103bba8, 0x0200e2cf, 0x200ff9f1, 0x4633fefc, 0x6c59ffff, 0x9380fcfd, 0xb9a6f4f9, 0xdccbe4ed, 0xffeeceda,} }, {0x10, 'C', { 0x57670a00, 0x3a492116, 0x222d3d2e, 0x0f175e4d, 0x0408816f, 0x0001a693, 0x0300cab8, 0x0e07eddc, 0x2f1dfefb, 0x5241f5fc, 0x7362e2ec, 0x8e80c9d6, 0xa89bafbc, 0xc3b594a1, 0xe1d27e89, 0xfff06673,} }, {0x10, 'D', { 0x99b5858f, 0x5f7c8883, 0x28429c8f, 0x010fc6ab, 0x240cf4e1, 0x5d41fefb, 0x957af1fc, 0xc1adcbe0, 0xd2cc92af, 0xd3d25875, 0xd7d71f3b, 0xd7d71b02, 0xd4d75538, 0xd4d48f72, 0xe1d9c9ac, 0xffe6f4e6,} }, {0x10, 'E', { 0x391c948f, 0x73569595, 0xad908a92, 0xddc8677e, 0xf1ee304d, 0xc3dd0d1b, 0x89a70002, 0x536d1304, 0x233b3a25, 0x08137053, 0x0301aa8d, 0x220edcc6, 0x573af7ee, 0x9174fffc, 0xcaaef6ff, 0xffe5dbeb,} }, {0x10, 'G', { 0xaaca0000, 0x698a0000, 0x2a491106, 0x000f4226, 0x23067061, 0x64437674, 0xa3836874, 0xdac04759, 0xfaec0b2a, 0xfefb401f, 0xffff8160, 0xf5fdc0a1, 0xc9e9eedf, 0x89a9fff9, 0x4869faff, 0x0928e3f3,} }, {0x10, 'G', { 0xeaff1421, 0xb9d20308, 0x88a00000, 0x57700f05, 0x2b3f2618, 0x09174d37, 0x00037f66, 0x0d05af97, 0x2a1adac7, 0x5940ede5, 0x8b72f2f3, 0xbca4e9ee, 0xe4d2cbde, 0xfbf09cb3, 0xf5f8ceb5, 0xe9f1ffe6,} }, {0x10, 'H', { 0x03021300, 0x06053a26, 0x0b0a604d, 0x0b0b8774, 0x0a0bae9a, 0x0506d4c1, 0x0002fbe8, 0x1104e0f0, 0x2e1ec3d1, 0x503dadb5, 0x7764a5a7, 0x9e8aa1a2, 0xc4b1a3a0, 0xead8ada8, 0xfff8d1bd, 0xfffff8e4,} }, {0x10, 'K', { 0x1d1a2000, 0x171a6040, 0x1114a080, 0x060edfc0, 0x1100e2ff, 0x3420a8c5, 0x6f4f8b95, 0xaf8f8285, 0xefcf8683, 0xe1fcb3a0, 0xa0c1c2bb, 0x6080c6c5, 0x2c40c9c7, 0x6c4cd8d1, 0xac8ceadf, 0xedccfef3,} }, {0x10, 'K', { 0x22341900, 0x15185436, 0x0e119072, 0x0c0cccae, 0x0709f6ea, 0x0a07b9d8, 0x2918859e, 0x5b406170, 0x90796658, 0x627c8b7c, 0x2a47a79a, 0x110db8b1, 0x4d2fbfbc, 0x896bcac4, 0xc3a6d9d1, 0xffe1ede2,} }, {0x10, 'L', { 0x3f4a0c00, 0x35372c1c, 0x2c314d3d, 0x26296e5d, 0x1b218e7e, 0x1316af9f, 0x0910cfc0, 0x0004f1e0, 0x1605ffff, 0x3727ffff, 0x5848ffff, 0x7a69fdff, 0x9b8afcfd, 0xbcabfcfc, 0xddcdfafb, 0xffeef9f9,} }, {0x10, 'M', { 0x0900e0ff, 0x2017a0c0, 0x3a296381, 0x4e442443, 0x5a583010, 0x6b5f6f4f, 0x7471ae8f, 0x7977eece, 0x8c80c5e5, 0xa19886a5, 0xbaad4766, 0xd3c70a29, 0xddda3516, 0xe7e17555, 0xf4f0b494, 0xfffaf4d4,} }, {0x10, 'M', { 0x0e00421a, 0x1414936a, 0x1416e3bb, 0x1813c0e8, 0x201b6f97, 0x2f261e47, 0x664d2c09, 0x7a737c54, 0x7c7bcda5, 0x7e7accf5, 0x8b847ba4, 0x9c932b53, 0xd5b30d09, 0xece25d35, 0xfaf5ae85, 0xfffdffd6,} }, {0x10, 'M'+0x100, { 0xf1ffe0ff, 0xdce8a2c0, 0xc8d16282, 0xbbc12343, 0xaab22a0b, 0x9fa46a4a, 0x9298a989, 0x808ae8c9, 0x6f74bfde, 0x61697f9f, 0x555b4060, 0x464f0120, 0x363d3f1f, 0x282f7e5e, 0x151fbc9e, 0x000afcdc,} }, {0x10, 'N', { 0x0400e7ff, 0x130bb8cf, 0x281e89a1, 0x38305a71, 0x51452c43, 0x675d1d13, 0x68684e36, 0x6b697f66, 0x726fb097, 0x7875e0c8, 0x907ee8f8, 0xa79ebbd2, 0xbfb38fa4, 0xd1c95f77, 0xe6da3148, 0xfff20019,} }, {0x0c, 'O', { 0x2e3f311f, 0x101e5c46, 0x03088f76, 0x0001c2a8, 0x1e08e7da, 0x4f35fdf4, 0x8168fcff, 0xb39beef5, 0xdac7cedf, 0xf3e9a0b8, 0xfef96d87, 0xf9ff3c54, 0xdaec1326, 0xaac30108, 0x77900100, 0x465e1407,} }, {0x0c, 'O', { 0x8670020b, 0xb8a01307, 0xe3ce3423, 0xf8f0664c, 0xfffc9b81, 0xf1faceb5, 0xcee4f4e5, 0x9ab4fffb, 0x657fffff, 0x364ceaf8, 0x1623c0d7, 0x00098ea7, 0x06015973, 0x24122e41, 0x4d380c1c, 0x82670104,} }, {0x0c, 'O', { 0xd0e30213, 0x9cb60000, 0x68820c05, 0x384f2416, 0x17254c36, 0x040c8066, 0x0001b49a, 0x1305e4ce, 0x442bfaf0, 0x785efffe, 0xab92f1f9, 0xd3c1cfe3, 0xf1e3a1b9, 0xfffa6e88, 0xf8ff3b54, 0xd5e81024,} }, {0x0c, 'O', { 0x000f768a, 0x0900455d, 0x2b171e30, 0x5a420611, 0x8d740100, 0xbca5170b, 0xe3d23824, 0xfcf2644c, 0xfaff977e, 0xe3f0c4af, 0xbdd2e6d7, 0x8ea7faf2, 0x5b74fefe, 0x2e44e9f6, 0x0a1bc2d6, 0x02028fa9,} }, {0x0c, 'O', { 0x040e8a71, 0x0b03bca4, 0x2c19e7d4, 0x5d43fef5, 0x9077f9fe, 0xbea8deee, 0xdfcfb6cb, 0xf7ed859f, 0xfefd516b, 0xe6f62237, 0xb7d00812, 0x839d0002, 0x4f690701, 0x20371f11, 0x040e4e34, 0x00028268,} }, {0x0c, 'O', { 0x829c0900, 0x4e682315, 0x24384a34, 0x08157c61, 0x0002b598, 0x0d03edd1, 0x4326fffd, 0x7a5feef8, 0xab93cfe0, 0xd5c1a7bd, 0xf4e67690, 0xfbff3d5a, 0xcfec1b26, 0x96b31818, 0x5e7a251d, 0x28433b2f,} }, {0x0c, 'O', { 0x381e5e68, 0x6e535156, 0xa388504f, 0xd8be5e56, 0xf9ed876d, 0xf9fcbaa1, 0xd8ece5d2, 0xa5c0f9f2, 0x708bfffd, 0x3b55fbfe, 0x1423d7ed, 0x0006a4bf, 0x09027089, 0x26154157, 0x50391e2e, 0x7e670010,} }, {0x10, 'Q', { 0xc9e4020f, 0x8dab0000, 0x516f0802, 0x18341f11, 0x02065537, 0x35186f68, 0x71536b6f, 0xaa8e5963, 0xdec53a4b, 0xfef40924, 0xe1ef3e24, 0xc0d07157, 0xabb4ac8e, 0x9da4e8ca, 0xc5aaeffd, 0xfde0d6e2,} }, {0x10, 'S', { 0xb7cf0001, 0x869e0301, 0x556d0905, 0x273e1f12, 0x0311442c, 0x2009665a, 0x5138726b, 0x826a7876, 0xb39b807b, 0xdfcb998b, 0xfff5bea7, 0xdcf2ded0, 0xadc6f1e8, 0x7c94fbf7, 0x4b63fffd, 0x1932ffff,} }, {0x10, 'S', { 0xcbde0200, 0xa8ba1209, 0x8597241a, 0x6a753f2f, 0x806c5751, 0xa6935e5b, 0xccb96662, 0xf2e0746b, 0xfcff9482, 0xe0f0b2a6, 0xbdcfc2bb, 0x97abd1c9, 0x7385ddd7, 0x4c60e8e3, 0x273af4ee, 0x0014fff9,} }, {0x10, 'U', { 0x050d2209, 0x0001573c, 0x03008c71, 0x1106bfa6, 0x2f1bebda, 0x604ae1f0, 0x8873bccd, 0xa59990a8, 0xbcb05f78, 0xcdc72c46, 0xd0d00911, 0xc9cb3e24, 0xc6c87359, 0xc9c6a88d, 0xd8d2ddc2, 0xffe4fff6,} }, {0x10, 'V', { 0x09000f00, 0x1911301f, 0x27205240, 0x342d7563, 0x413a9785, 0x4f47b9a8, 0x6057d9c9, 0x7569f9ea, 0x9486f4ff, 0xa99fd5e5, 0xb8b0b4c5, 0xc9c093a3, 0xdbd17484, 0xe9e35263, 0xf5ef2f41, 0xfff90b1d,} }, {0x10, 'V', { 0x07008274, 0x170f9d90, 0x271fb6aa, 0x382fd0c2, 0x463febdd, 0x534df7fa, 0x635bdbe9, 0x716ac1ce, 0x827aa7b4, 0x928a8e9a, 0xa39a7682, 0xb6ac5e6a, 0xc8bf4753, 0xdad1303b, 0xede41924, 0xfff4000d,} }, {0x10, 'W', { 0x06001f00, 0x110c5f3f, 0x1c189f7f, 0x2822debe, 0x4131e3fd, 0x554ba4c3, 0x655c6484, 0x786f2444, 0x847f2f0f, 0x8a866f4f, 0x928eae8f, 0x9e99eece, 0xbaacd0ee, 0xd5c893b3, 0xebe05373, 0xfff61333,} }, {0x10, 'W', { 0x0c00240b, 0x2015563d, 0x332b8970, 0x4b416b84, 0x5b533851, 0x6a63061f, 0x78722d14, 0x817c5f46, 0x8b869279, 0x9791c4ab, 0xa39ef7de, 0xb6aed5ee, 0xc6bea2bb, 0xd8cf7089, 0xede33d56, 0xfff60a24,} }, {0x10, 'W', { 0x0d003219, 0x1e15654b, 0x2c24987e, 0x3732cbb1, 0x453dfee4, 0x564dcde7, 0x675d9bb4, 0x7b706882, 0x9084354f, 0xa39b021c, 0xada83117, 0xbab2644a, 0xc8c0977d, 0xded47791, 0xf1e7445e, 0xfff7112b,} }, {0x10, 'W', { 0x00002d0b, 0x0001714f, 0x0902b593, 0x2816f3d4, 0x5844d4f1, 0x796997b6, 0x8a845375, 0x858a0f31, 0x7f804a28, 0x7e7e8e6c, 0x8a82d2b0, 0xb596fcf4, 0xe4d0cae7, 0xfcf489ab, 0xfffe4567, 0xf9fd0023,} }, {0x10, 'W'+0x100, { 0xf7ff2000, 0xe4ed6040, 0xd5dba181, 0xbdcbe0c0, 0xa0aad3f3, 0x909892b3, 0x848a5272, 0x80811131, 0x777d3d1d, 0x636d7e5e, 0x535bbf9e, 0x3c48fdde, 0x272fc1e2, 0x121a82a2, 0x030a4161, 0x00020021,} }, {0x10, 'Y', { 0x16000b13, 0x442d0303, 0x4b48341b, 0x61505e4b, 0x91795c62, 0xbca74551, 0xe1d02637, 0xfcf40c14, 0xe8f13922, 0xdbe16951, 0xd6d99a82, 0xced3cbb2, 0xb0c4f0e1, 0x7f98fbf7, 0x4e67fefd, 0x1d36fdff,} }, {0x10, 'Z', { 0x30160200, 0x644a0403, 0x997f0303, 0xcdb30202, 0xe7e80d00, 0xc4d63622, 0x9bb05c4a, 0x73857f6c, 0x5061a893, 0x293eccbb, 0x0013f2dd, 0x2d13fcfd, 0x6248f6f8, 0x967cf1f3, 0xcbb1edef, 0xffe5f1ec,} }, {0x10, '<', { 0xf0ff0b00, 0xd1e11c14, 0xb0c02c24, 0x90a13c33, 0x71804c44, 0x51605c54, 0x2f406d64, 0x0d1e7c75, 0x16058d86, 0x38279b94, 0x5747a9a2, 0x7768b9b1, 0x9686c9c0, 0xb5a6dad1, 0xd5c6ece3, 0xf5e4fff6,} }, {0x10, '>', { 0x17070600, 0x3928160f, 0x5949271f, 0x796a372f, 0x9a8a483f, 0xb9aa5951, 0xd8c86b62, 0xfae97e74, 0xe3f48d85, 0xc1d29c95, 0x9fb0aca4, 0x7e8ebab3, 0x5d6dcbc2, 0x3c4cdbd3, 0x1f2dece4, 0x0010fff5,} }, {0x10, 0x1001, { 0x0003ecff, 0x0502c6d9, 0x0b099fb2, 0x1410788c, 0x221b5265, 0x362b2f40, 0x5341121d, 0x7966020a, 0xa08d0100, 0xc3b3170b, 0xd9ce3a28, 0xede25f4d, 0xf4f28672, 0xfaf6ac99, 0xfffdd3c0, 0xfffffae6,} }, {0x10, 0x1002, { 0x1900847d, 0x4c328785, 0x7f658b88, 0xb198898b, 0xe3cb7f88, 0xf8f24f68, 0xecf81d35, 0xbfd9010b, 0x90a61504, 0x8186462d, 0x7c7d7960, 0x7f7bac93, 0x8883dfc6, 0xaf97fff4, 0xdcc7eafa, 0xffeec1d7,} }, {0x10, 0x1003, { 0x7543141a, 0xd7a82e17, 0xf8f78f5c, 0xc6e6e9bf, 0x6497f8fa, 0x1338b3db, 0x03024f82, 0x4a1c0620, 0xaf7c1001, 0xf8da582b, 0xeafebc8b, 0x9acbfbe6, 0x3868eeff, 0x0a1892c4, 0x2712305f, 0x85520e11,} }, {0x10, 0x1004, { 0x04003204, 0x120b8e60, 0x1714ebbd, 0x2f27b8e6, 0x43385b89, 0x5b4c032d, 0x6a666032, 0x7770bc8e, 0x8c82b8e6, 0x9b945c8a, 0xaea2012d, 0xbbb75d2f, 0xc9c1ba8c, 0xe3d5bce7, 0xf1ea5f8d, 0xfff50231,} }, {0x10, 0x1005, { 0x1900020a, 0x4d330400, 0x7c65180a, 0xa18f3f2b, 0xb3ac7258, 0xbcb8a58b, 0xb0b9d7bf, 0x8aa0fcec, 0x5971f2fd, 0x414bc2db, 0x433f8ea8, 0x534a5d76, 0x71613246, 0x9d85101e, 0xd0b60609, 0xffea1409,} }, {0x10, 0x1006, { 0xdeff0714, 0x9abc0002, 0x57790a02, 0x1d373018, 0x01076d4b, 0x2f0f988a, 0x72519c9c, 0xb2948b9c, 0xa3bc576b, 0x60815653, 0x26417963, 0x020eb191, 0x2005e7d3, 0x6442fbf4, 0xa785fbff, 0xebc9e7f3,} }, {0x10, 0x1007, { 0xf6ff0600, 0xe4ed140c, 0xd5dd261d, 0xc5cd362e, 0xb3bc463e, 0xa2aa574e, 0x939a6860, 0x83897970, 0x747c8a82, 0x646c9c93, 0x525baca4, 0x434abdb4, 0x333bcfc6, 0x222addd5, 0x121beee6, 0x0009fff6,} }, {0x10, 0x1008, { 0x09000900, 0x19111b13, 0x28202d24, 0x39303d35, 0x49424e45, 0x5a515d56, 0x6b626d65, 0x7d747b74, 0x8e868b82, 0x9d969c93, 0xaca4aea5, 0xbcb4bfb6, 0xcac4d1c7, 0xdbd2e1d9, 0xece3f1e9, 0xfff5fff8,} }, {0x10, 0x1009, { 0x0a00faff, 0x1d14edf4, 0x2e25dce5, 0x3e36cbd4, 0x4e44bac2, 0x5f57aab2, 0x6f679aa2, 0x7f778890, 0x8c85757e, 0x9c94636b, 0xaba3515a, 0xbbb2414a, 0xcbc33039, 0xddd31f28, 0xeee51119, 0xfff7000a,} }, {0x10, 0x100a, { 0xf4fffaff, 0xe1eaeff6, 0xd1d9dde6, 0xc1cacdd5, 0xb4bbbac3, 0xa2aca8b0, 0x929a99a1, 0x83888791, 0x767d747d, 0x666e636b, 0x535c545e, 0x444d424b, 0x333d323a, 0x242b212a, 0x141c0f18, 0x000a0008,} }, {0x10, 0x100b, { 0x30000208, 0x90600200, 0xf1c11e0c, 0xb5e64d3f, 0x55855653, 0x32245556, 0x93625756, 0xf1c3745e, 0xbaeaa997, 0x598ab2b0, 0x0f29aab1, 0x7040a8a7, 0xd1a0b8ae, 0xd0f8ecd0, 0x6f9ffcf5, 0x0e3ffcff,} }, {0x10, 0x100c, { 0x2600140c, 0x66494226, 0x827c8d66, 0x6d80d8b4, 0x284ffaf4, 0x0a0ab9e0, 0x411f8097, 0x8e689182, 0xd6b47f94, 0xf9f23960, 0xd5f80012, 0x91af270a, 0x7e83734c, 0x7e7dc19a, 0xb490fae5, 0xffdbe9fe,} }, {0x10, 0x100d, { 0x768e0c00, 0x465e2619, 0x192f4635, 0x0107745a, 0x32178a85, 0x674d858a, 0x9b81747d, 0xccb45c69, 0xf7e33b4d, 0xebfd0d21, 0xb6d00004, 0x939e270d, 0x888d5d42, 0x83859378, 0x7c80c9ae, 0x6c75ffe4,} }, /*{0x10, 0x100e, { *0xb3bd1000, 0x9ea82d1e, 0x87924a3b, 0x6f7b6658, 0x56628375, *0x3e4a9e91, 0x2934bcad, 0x1720ddcd, 0x010bfced, 0x2513ffff, *0x4937fdff, 0x6d5bf9fa, 0x9280f4f7, 0xb6a4f0f1, 0xdac8eeef, *0xffececed,}}, */ }; #endif static void SortBubble(int t[], int size) { int temp = 0; int m, n; for (m = 0; m < size; m++) { for (n = m + 1; n < size; n++) { temp = t[m]; if (temp > t[n]) { t[m] = t[n]; t[n] = temp; } } } } static int Sqrt(int d) { int ret = 0; int i; for (i = 14; i >= 0; i--) { if ((ret + (0x1 << i)) * (ret + (0x1 << i)) <= d) ret |= (0x1 << i); } return ret; } static UINT PointRange(int x0, int y0, int x1, int y1) { if (x0 < 1) { if (x0 != x1) y0 = y1 + (y0 - y1) * (1 - x1) / (x0 - x1); x0 = 1; } if (x0 >= (int)drv_num_nokey*64) { if (x0 != x1) y0 = y1 + (y0 - y1) * ((int)drv_num_nokey * 64 - x1) / (x0 - x1); x0 = drv_num_nokey * 64-1; } if (y0 < 1) { if (y0 != y1) x0 = x1 + (x0 - x1) * (1 - y1) / (y0 - y1); y0 = 1; } if (y0 >= (int)sen_num_nokey*64) { if (y0 != y1) x0 = x1 + (x0 - x1) * ((int)sen_num_nokey * 64 - y1) / (y0 - y1); y0 = sen_num_nokey * 64-1; } if (x0 < 1) x0 = 1; if (x0 >= (int)drv_num_nokey * 64) x0 = drv_num_nokey * 64 - 1; if (y0 < 1) y0 = 1; if (y0 >= (int)sen_num_nokey * 64) y0 = sen_num_nokey * 64 - 1; return (x0 << 16) + y0; } static void PointCoor(void) { int i; point_num &= 0xff; for (i = 0; i < point_num; i++) { if (global_state.ex) point_now[i].all &= (FLAG_COOR_EX | FLAG_KEY | FLAG_ABLE); else point_now[i].all &= (FLAG_COOR | FLAG_KEY | FLAG_ABLE); } } static void PointRepeat(void) { int i, j; int x, y; int x_min, x_max, y_min, y_max; int pn; if (point_near) point_near--; if (prev_num > point_num) point_near = 8; if (point_repeat[0] == 0 || point_repeat[1] == 0) { if (point_near) pn = 96; else pn = 32; } else { if (point_near) pn = point_repeat[1]; else pn = point_repeat[0]; } for (i = 0; i < POINT_MAX; i++) { if (point_now[i].all == 0) continue; if (point_now[i].key) continue; x_min = point_now[i].x - pn; x_max = point_now[i].x + pn; y_min = point_now[i].y - pn; y_max = point_now[i].y + pn; for (j = i + 1; j < POINT_MAX; j++) { if (point_now[j].all == 0) continue; if (point_now[j].key) continue; x = point_now[j].x; y = point_now[j].y; if (x > x_min && x < x_max && y > y_min && y < y_max) { point_now[i].x = (point_now[i].x + point_now[j].x + 1) / 2; point_now[i].y = (point_now[i].y + point_now[j].y + 1) / 2; point_now[j].all = 0; i--; point_near = 8; break; } } } } static void PointPointer(void) { int i, pn; point_n++; if (point_n >= PP_DEEP * PS_DEEP * PR_DEEP * PRESSURE_DEEP) point_n = 0; pn = point_n % PP_DEEP; for (i = 0; i < PP_DEEP; i++) { pp[i] = point_array[pn]; if (pn == 0) pn = PP_DEEP - 1; else pn--; } pn = point_n % PS_DEEP; for (i = 0; i < PS_DEEP; i++) { ps[i] = point_array[pn+PP_DEEP]; if (pn == 0) pn = PS_DEEP - 1; else pn--; } pn = point_n % PR_DEEP; for (i = 0; i < PR_DEEP; i++) { pr[i] = point_array[pn+PP_DEEP+PS_DEEP]; if (pn == 0) pn = PR_DEEP - 1; else pn--; } pn = point_n % PRESSURE_DEEP; for (i = 0; i < PRESSURE_DEEP; i++) { pa[i] = pressure_array[pn]; if (pn == 0) pn = PRESSURE_DEEP - 1; else pn--; } pn = 0; for (i = 0; i < POINT_MAX; i++) { if (point_now[i].all) point_now[pn++].all = point_now[i].all; pp[0][i].all = 0; ps[0][i].all = 0; pr[0][i].all = 0; } point_num = pn; for (i = pn; i < POINT_MAX; i++) point_now[i].all = 0; } static unsigned int CCO(unsigned int x, unsigned int coe[], int k) { if (k == 0) { if (x & 32) return (x & ~31) + (31 - (coe[31 - (x & 31)] & 31)); else return (x & ~31) + (coe[x & 31] & 31); } if (k == 1) { if (x & 64) return (x & ~63) + (63 - (coe[63 - (x & 63)] & 63)); else return (x & ~63) + (coe[x & 63] & 63); } if (k == 2) return (x & ~63) + (coe[x & 63] & 63); return 0; } static void CoordinateCorrect(void) { typedef struct { unsigned int range; unsigned int group; } MULTI_TYPE; #ifdef LINE_MULTI_SIZE #define LINE_SIZE LINE_MULTI_SIZE #else #define LINE_SIZE 4 #endif int i, j; unsigned int *px[LINE_SIZE+1], *py[LINE_SIZE+1]; MULTI_TYPE multi_x[LINE_SIZE], multi_y[LINE_SIZE]; unsigned int edge_size = 64; int kx, ky; if ((coordinate_correct_able & 0xf) == 0) return; kx = (coordinate_correct_able >> 4) & 0xf; ky = (coordinate_correct_able >> 8) & 0xf; px[0] = coordinate_correct_coe_x; py[0] = coordinate_correct_coe_y; for (i = 0; i < LINE_SIZE; i++) { px[i+1] = NULL; py[i+1] = NULL; } if (kx == 3 || ky == 3) { i = 0; if (((coordinate_correct_able >> 4) & 0xf) == 3) px[1] = multi_group[i++]; if (((coordinate_correct_able >> 8) & 0xf) == 3) py[1] = multi_group[i++]; } else { for (i = 0; i < LINE_SIZE; i++) { multi_x[i].range = multi_x_array[i] & 0xffff; multi_x[i].group = multi_x_array[i] >> 16; multi_y[i].range = multi_y_array[i] & 0xffff; multi_y[i].group = multi_y_array[i] >> 16; } j = 1; for (i = 0; i < LINE_SIZE; i++) if (multi_x[i].range && multi_x[i].group < LINE_SIZE) px[j++] = multi_group[multi_x[i].group]; j = 1; for (i = 0; i < LINE_SIZE; i++) if (multi_y[i].range && multi_y[i].group < LINE_SIZE) py[j++] = multi_group[multi_y[i].group]; } for (i = 0; i < (int)point_num && i < POINT_MAX; i++) { if (point_now[i].all == 0) break; if (point_now[i].key != 0) continue; if (point_now[i].x >= edge_size && point_now[i].x <= drv_num_nokey * 64 - edge_size) { if (kx == 3) { if (point_now[i].x & 64) point_now[i].x = CCO(point_now[i].x, px[0], 2); else point_now[i].x = CCO(point_now[i].x, px[1], 2); } else { for (j = 0; j < LINE_SIZE + 1; j++) { if (!(j >= LINE_SIZE || px[j+1] == NULL || multi_x[j].range == 0 || point_now[i].x < multi_x[j].range)) continue; point_now[i].x = CCO(point_now[i].x, px[j], kx); break; } } } if (point_now[i].y >= edge_size && point_now[i].y <= sen_num_nokey * 64 - edge_size) { if (ky == 3) { if (point_now[i].y & 64) point_now[i].y = CCO(point_now[i].y, py[0], 2); else point_now[i].y = CCO(point_now[i].y, py[1], 2); } else { for (j = 0; j < LINE_SIZE + 1; j++) { if (!(j >= LINE_SIZE || py[j+1] == NULL || multi_y[j].range == 0 || point_now[i].y < multi_y[j].range)) continue; point_now[i].y = CCO(point_now[i].y, py[j], ky); break; } } } } #undef LINE_SIZE } static void PointPredictOne(unsigned int n) { pp[0][n].all = pp[1][n].all & FLAG_COOR; pp[0][n].predict = 0; } static void PointPredictTwo(unsigned int n) { int x, y; x = pp[1][n].x * 2 - pp[2][n].x; y = pp[1][n].y * 2 - pp[2][n].y; pp[0][n].all = PointRange(x, y, pp[1][n].x, pp[1][n].y); pp[0][n].predict = 1; } static void PointPredictThree(unsigned int n) { int x, y; x = pp[1][n].x * 5 + pp[3][n].x - pp[2][n].x * 4; x /= 2; y = pp[1][n].y * 5 + pp[3][n].y - pp[2][n].y * 4; y /= 2; pp[0][n].all = PointRange(x, y, pp[1][n].x, pp[1][n].y); pp[0][n].predict = 1; } static void PointPredict(void) { int i; for (i = 0; i < POINT_MAX; i++) { if (pp[1][i].all != 0) { if (global_state.interpolation || pp[2][i].all == 0 || pp[2][i].fill != 0 || pp[3][i].fill != 0 || pp[1][i].key != 0 || global_state.only) { PointPredictOne(i); } else if (pp[2][i].all != 0) { if (pp[3][i].all != 0) PointPredictThree(i); else PointPredictTwo(i); } pp[0][i].all |= FLAG_FILL; pa[0][i] = pa[1][i]; } else pp[0][i].all = 0x0fff0fff; if (pp[1][i].key) pp[0][i].all |= FLAG_KEY; } } static unsigned int PointDistance(gsl_POINT_TYPE *p1, gsl_POINT_TYPE *p2) { int a, b, ret; a = p1->dis.x; b = p2->dis.x; ret = (a - b) * (a - b); a = p1->dis.y; b = p2->dis.y; ret += (a - b) * (a - b); return ret; } static void DistanceInit(gsl_DISTANCE_TYPE *p) { int i; unsigned int *p_int = &(p->d[0][0]); for (i = 0; i < POINT_MAX * POINT_MAX; i++) *p_int++ = 0x7fffffff; } static int DistanceMin(gsl_DISTANCE_TYPE *p) { int i, j; p->min = 0x7fffffff; for (j = 0; j < POINT_MAX; j++) { for (i = 0; i < POINT_MAX; i++) { if (p->d[j][i] < p->min) { p->i = i; p->j = j; p->min = p->d[j][i]; } } } if (p->min == 0x7fffffff) return 0; return 1; } static void DistanceIgnore(gsl_DISTANCE_TYPE *p) { int i, j; for (i = 0; i < POINT_MAX; i++) p->d[p->j][i] = 0x7fffffff; for (j = 0; j < POINT_MAX; j++) p->d[j][p->i] = 0x7fffffff; } static int SpeedGet(int d) { int i; for (i = 8; i > 0; i--) { if (d > 0x100 << i) break; } return i; } static void PointId(void) { int i, j; gsl_DISTANCE_TYPE distance; unsigned int id_speed[POINT_MAX]; DistanceInit(&distance); for (i = 0; i < POINT_MAX; i++) { if (pp[0][i].predict == 0 || pp[1][i].fill != 0) id_speed[i] = id_first_coe; else id_speed[i] = SpeedGet(PointDistance(&pp[1][i], &pp[0][i])); } for (i = 0; i < POINT_MAX; i++) { if (pp[0][i].all == FLAG_COOR) continue; for (j = 0; j < point_num && j < POINT_MAX; j++) distance.d[j][i] = PointDistance(&point_now[j], &pp[0][i]); } if (point_num == 0) return; if (global_state.only) { do { if (DistanceMin(&distance)) { if (pp[1][0].all != 0 && pp[1][0].key != point_now[distance.j].key) { DistanceIgnore(&distance); continue; } pp[0][0].all = point_now[distance.j].all; } else pp[0][0].all = point_now[0].all; for (i = 0; i < POINT_MAX; i++) point_now[i].all = 0; } while (0); point_num = 1; } else { for (j = 0; j < point_num && j < POINT_MAX; j++) { if (DistanceMin(&distance) == 0) break; /* average/(soft_average+1) */ if (distance.min >= (id_static_coe + id_speed[distance.i] * id_speed_coe)) /* point_now[distance.j].id = 0xf; new id */ continue; pp[0][distance.i].all = point_now[distance.j].all; pa[0][distance.i] = pressure_now[distance.j]; point_now[distance.j].all = 0; DistanceIgnore(&distance); } } } static int ClearLenPP(int i) { int n; for (n = 0; n < PP_DEEP; n++) { if (pp[n][i].all) break; } return n; } static void PointNewId(void) { int id, j; for (j = 0; j < POINT_MAX; j++) if ((pp[0][j].all & FLAG_COOR) == FLAG_COOR) pp[0][j].all = 0; for (j = 0; j < POINT_MAX; j++) { if (point_now[j].all != 0) { if (point_now[j].able) continue; for (id = 1; id <= POINT_MAX; id++) { if (ClearLenPP(id - 1) > (int)(1 + 1)) { pp[0][id-1].all = point_now[j].all; pa[0][id-1] = pressure_now[j]; point_now[j].all = 0; break; } } } } } static void PointOrder(void) { int i; for (i = 0; i < POINT_MAX; i++) { if (pp[0][i].fill == 0) continue; if (pp[1][i].all == 0 || pp[1][i].fill != 0 || filter_able == 0 || filter_able == 1) { pp[0][i].all = 0; pressure_now[i] = 0; } } } static void PointCross(void) { unsigned int i, j; unsigned int t; for (j = 0; j < POINT_MAX; j++) { for (i = j + 1; i < POINT_MAX; i++) { if (pp[0][i].all == 0 || pp[0][j].all == 0 || pp[1][i].all == 0 || pp[1][j].all == 0) continue; if (((pp[0][j].x < pp[0][i].x && pp[1][j].x > pp[1][i].x) || (pp[0][j].x > pp[0][i].x && pp[1][j].x < pp[1][i].x)) && ((pp[0][j].y < pp[0][i].y && pp[1][j].y > pp[1][i].y) || (pp[0][j].y > pp[0][i].y && pp[1][j].y < pp[1][i].y))) { t = pp[0][i].x; pp[0][i].x = pp[0][j].x; pp[0][j].x = t; t = pp[0][i].y; pp[0][i].y = pp[0][j].y; pp[0][j].y = t; } } } } static void GetPointNum(gsl_POINT_TYPE *pt) { int i; point_num = 0; for (i = 0; i < POINT_MAX; i++) if (pt[i].all != 0) point_num++; } static void PointDelay(void) { int i, j; for (i = 0; i < POINT_MAX; i++) { if (report_delay == 0) { point_delay[i].all = 0; if (pp[0][i].all) point_delay[i].able = 1; continue; } if (pp[0][i].all != 0 && point_delay[i].init == 0 && point_delay[i].able == 0) { if (point_num == 0) continue; point_delay[i].delay = (report_delay >> 3* ((point_num > 10 ? 10 : point_num) - 1)) & 0x7; point_delay[i].report = (report_ahead >> 3* ((point_num > 10 ? 10 : point_num) - 1)) & 0x7; if (point_delay[i].report > point_delay[i].delay) point_delay[i].report = point_delay[i].delay; point_delay[i].init = 1; } if (pp[0][i].all == 0) point_delay[i].init = 0; if (point_delay[i].able == 0 && point_delay[i].init != 0) { for (j = 0; j <= (int)point_delay[i].delay; j++) if (pp[j][i].all == 0 || pp[j][i].fill != 0 || pp[j][i].able != 0) break; if (j <= (int)point_delay[i].delay) continue; point_delay[i].able = 1; } if (pp[point_delay[i].report][i].all == 0) { point_delay[i].able = 0; continue; } if (point_delay[i].able == 0) continue; if (point_delay[i].report) { if (PointDistance(&pp[point_delay[i].report][i], &pp[point_delay[i].report - 1][i]) < 3 * 3) point_delay[i].report--; } } } static void FilterOne(int i, int *ps_c, int *pr_c, int denominator) { int j; int x = 0, y = 0; pr[0][i].all = ps[0][i].all; if (pr[0][i].all == 0) return; if (denominator <= 0) return; for (j = 0; j < 8; j++) { x += (int)pr[j][i].x * (int)pr_c[j] + (int)ps[j][i].x * (int)ps_c[j]; y += (int)pr[j][i].y * (int)pr_c[j] + (int)ps[j][i].y * (int)ps_c[j]; } x = (x + denominator/2) / denominator; y = (y + denominator/2) / denominator; if (x < 0) x = 0; if (x > 0xffff) x = 0xffff; if (y < 0) y = 0; if (y > 0xfff) y = 0xfff; pr[0][i].x = x; pr[0][i].y = y; } static unsigned int FilterSpeed(int i) { return (Sqrt(PointDistance(&ps[0][i], &ps[1][i])) + Sqrt(PointDistance(&ps[1][i], &ps[2][i])))/2; } static int MedianSpeedOver(int id, int deep) { int i; unsigned int dis; int speed_over = 0; deep = deep / 2 - 1; if (deep < 0 || deep > 3) return TRUE; dis = median_dis[deep] * median_dis[deep]; for (i = 0; i <= deep && i < POINT_DEEP; i++) { if (PointDistance(&ps[i][id], &ps[i+1][id]) > dis) speed_over++; } if (speed_over >= 2) return TRUE; return FALSE; } static void PointMedian(void) { int i, j; int deep; int buf_x[PS_DEEP], buf_y[PS_DEEP]; for (i = 0; i < POINT_MAX; i++) { if (filter_deep[i] < 3) deep = 3; else deep = filter_deep[i] + 2; if (deep >= PS_DEEP) deep = PS_DEEP-1; deep |= 1; for (; deep >= 3; deep -= 2) { if (MedianSpeedOver(i, deep)) continue; for (j = 0; j < deep; j++) { buf_x[j] = ps[j][i].x; buf_y[j] = ps[j][i].y; } SortBubble(buf_x, deep); SortBubble(buf_y, deep); pr[0][i].x = buf_x[deep / 2]; pr[0][i].y = buf_y[deep / 2]; } filter_deep[i] = deep; } } static void PointFilter(void) { int i, j; int speed_now; int filter_speed[6]; int ps_c[8]; int pr_c[8]; for (i = 0; i < POINT_MAX; i++) pr[0][i].all = ps[0][i].all; for (i = 0; i < POINT_MAX; i++) { if (pr[0][i].all != 0 && pr[1][i].all == 0) { for (j = 1; j < PR_DEEP; j++) pr[j][i].all = ps[0][i].all; for (j = 1; j < PS_DEEP; j++) ps[j][i].all = ps[0][i].all; } } if (filter_able >= 0 && filter_able <= 1) return; if (filter_able > 1) { for (i = 0; i < 8; i++) { ps_c[i] = (filter_coe[i / 4] >> ((i % 4) * 8)) & 0xff; pr_c[i] = (filter_coe[i / 4 + 2] >> ((i % 4) * 8)) & 0xff; if (ps_c[i] >= 0x80) ps_c[i] |= 0xffffff00; if (pr_c[i] >= 0x80) pr_c[i] |= 0xffffff00; } for (i = 0; i < POINT_MAX; i++) FilterOne(i, ps_c, pr_c, filter_able); } else if (filter_able == -1) PointMedian(); else if (filter_able < 0) { for (i = 0; i < 4; i++) filter_speed[i+1] = median_dis[i]; filter_speed[0] = median_dis[0] * 2 - median_dis[1]; filter_speed[5] = median_dis[3] / 2; for (i = 0; i < POINT_MAX; i++) { if (pr[0][i].all == 0) { filter_deep[i] = 0; continue; } speed_now = FilterSpeed(i); if (filter_deep[i] > 0 && speed_now > filter_speed[filter_deep[i]+1 - 2]) filter_deep[i]--; else if (filter_deep[i] < 3 && speed_now < filter_speed[filter_deep[i]+1 + 2]) filter_deep[i]++; FilterOne(i, ps_coe[filter_deep[i]], pr_coe[filter_deep[i]], 0-filter_able); } } } static unsigned int KeyMap(int *drv, int *sen) { typedef struct { unsigned int up_down, left_right; unsigned int coor; } KEY_TYPE_RANGE; KEY_TYPE_RANGE *key_range = (KEY_TYPE_RANGE *)key_range_array; int i; for (i = 0; i < 8; i++) { if ((unsigned int)*drv >= (key_range[i].up_down >> 16) && (unsigned int)*drv <= (key_range[i].up_down & 0xffff) && (unsigned int)*sen >= (key_range[i].left_right >> 16) && (unsigned int)*sen <= (key_range[i].left_right & 0xffff)) { *sen = key_range[i].coor >> 16; *drv = key_range[i].coor & 0xffff; return key_range[i].coor; } } return 0; } static unsigned int ScreenResolution(gsl_POINT_TYPE *p) { int x, y; x = p->x; y = p->y; if (p->key == FALSE) { y = ((y - match_y[1]) * match_y[0] + 2048) / 4096; x = ((x - match_x[1]) * match_x[0] + 2048) / 4096; } y = y * (int)screen_y_max / ((int)sen_num_nokey * 64); x = x * (int)screen_x_max / ((int)drv_num_nokey * 64); if (p->key == FALSE) { if ((ignore_y[0] != 0 || ignore_y[1] != 0)) { if (y < ignore_y[0]) return 0; if (ignore_y[1] <= screen_y_max/2 && y > screen_y_max - ignore_y[1]) return 0; if (ignore_y[1] >= screen_y_max/2 && y > ignore_y[1]) return 0; } if (ignore_x[0] != 0 || ignore_x[1] != 0) { if (x < ignore_x[0]) return 0; if (ignore_x[1] <= screen_y_max/2 && x > screen_x_max - ignore_x[1]) return 0; if (ignore_x[1] >= screen_y_max/2 && x > ignore_x[1]) return 0; } if (y <= (int)edge_cut[2]) y = (int)edge_cut[2] + 1; if (y >= screen_y_max - (int)edge_cut[3]) y = screen_y_max - (int)edge_cut[3] - 1; if (x <= (int)edge_cut[0]) x = (int)edge_cut[0] + 1; if (x >= screen_x_max - (int)edge_cut[1]) x = screen_x_max - (int)edge_cut[1] - 1; if (global_flag.opposite_x) y = screen_y_max - y; if (global_flag.opposite_y) x = screen_x_max - x; if (global_flag.opposite_xy) { y ^= x; x ^= y; y ^= x; } } else { if (y < 0) y = 0; if (x < 0) x = 0; if ((key_map_able & 0x1) != FALSE && KeyMap(&x, &y) == 0) return 0; } return ((y << 16) & 0x0fff0000) + (x & 0x0000ffff); } static void PointReport(struct gsl_touch_info *cinfo) { int i; unsigned int data[POINT_MAX]; int num = 0; if (point_num > point_num_max && global_flag.over_report_mask != 0) { point_num = 0; cinfo->finger_num = 0; return; } for (i = 0; i < POINT_MAX; i++) data[i] = 0; num = 0; if (global_flag.id_over) { for (i = 0; i < POINT_MAX && num < point_num_max; i++) { if (point_delay[i].able == 0) continue; if (point_delay[i].report >= PR_DEEP-1) continue; if (pr[point_delay[i].report+1][i].able == 0) continue; if (pr[point_delay[i].report][i].all) { pr[point_delay[i].report][i].able = 1; data[i] = ScreenResolution(&pr[point_delay[i].report][i]); if (data[i]) { data[i] |= (i+1) << 28; num++; } } } for (i = 0; i < POINT_MAX && num < point_num_max; i++) { if (point_delay[i].able == 0) continue; if (point_delay[i].report >= PR_DEEP) continue; if (pr[point_delay[i].report][i].all == 0) continue; if (pr[point_delay[i].report][i].able == 0) { pr[point_delay[i].report][i].able = 1; data[i] = ScreenResolution(&pr[point_delay[i].report][i]); if (data[i]) { data[i] |= (i + 1) << 28; num++; } } } } else { num = 0; for (i = 0; i < point_num_max && i < POINT_MAX; i++) { if (point_delay[i].able == 0) continue; if (point_delay[i].report >= PR_DEEP) continue; data[num] = ScreenResolution(&pr[point_delay[i].report][i]); if (data[num]) data[num++] |= (i + 1) << 28; } } num = 0; for (i = 0; i < POINT_MAX; i++) { if (data[i] == 0) continue; point_now[num].all = data[i]; cinfo->x[num] = (data[i] >> 16) & 0xfff; cinfo->y[num] = data[i] & 0xfff; cinfo->id[num] = data[i] >> 28; pressure_now[num] = pressure_report[i]; num++; } for (i = num; i < POINT_MAX; i++) { point_now[i].all = 0; pressure_now[i] = 0; } point_num = num; cinfo->finger_num = num; } static void PointEdge(void) { typedef struct { int range; int coe; } STRETCH_TYPE; typedef struct { STRETCH_TYPE up[4]; STRETCH_TYPE down[4]; STRETCH_TYPE left[4]; STRETCH_TYPE right[4]; } STRETCH_TYPE_ALL; STRETCH_TYPE_ALL *stretch; int i, id; int data[2]; int x, y; int sac[4 * 4 * 2]; if (screen_x_max == 0 || screen_y_max == 0) return; id = 0; for (i = 0; i < 4*4*2; i++) { sac[i] = stretch_array[i]; if (sac[i]) id++; } if (id == 0) return; stretch = (STRETCH_TYPE_ALL *)sac; for (i = 0; i < 4; i++) { if (stretch->right[i].range > screen_y_max * 64 / 128 || stretch->down[i].range > screen_x_max * 64 / 128) { for (i = 0; i < 4; i++) { if (stretch->up[i].range) stretch->up[i].range = stretch->up[i].range * drv_num_nokey * 64 / screen_x_max; if (stretch->down[i].range) stretch->down[i].range = (screen_x_max - stretch->down[i].range) * drv_num_nokey * 64 / screen_x_max; if (stretch->left[i].range) stretch->left[i].range = stretch->left[i].range * sen_num_nokey * 64 / screen_y_max; if (stretch->right[i].range) stretch->right[i].range = (screen_y_max - stretch->right[i].range) * sen_num_nokey * 64 / screen_y_max; } break; } } for (id = 0; id < POINT_MAX; id++) { if (point_now[id].all == 0 || point_now[id].key != 0) continue; x = point_now[id].x; y = point_now[id].y; data[0] = 0; data[1] = y; for (i = 0; i < 4; i++) { if (stretch->left[i].range == 0) break; if (data[1] < stretch->left[i].range) { data[0] += (stretch->left[i].range - data[1]) * stretch->left[i].coe / 128; data[1] = stretch->left[i].range; } } y = data[1] - data[0]; if (y <= 0) y = 1; if (y >= (int)sen_num_nokey * 64) y = sen_num_nokey * 64 - 1; data[0] = 0; data[1] = sen_num_nokey * 64 - y; for (i = 0; i < 4; i++) { if (stretch->right[i].range == 0) break; if (data[1] < stretch->right[i].range) { data[0] += (stretch->right[i].range - data[1]) * stretch->right[i].coe / 128; data[1] = stretch->right[i].range; } } y = sen_num_nokey * 64 - (data[1] - data[0]); if (y <= 0) y = 1; if (y >= (int)sen_num_nokey * 64) y = sen_num_nokey * 64 - 1; data[0] = 0; data[1] = x; for (i = 0; i < 4; i++) { if (stretch->up[i].range == 0) break; if (data[1] < stretch->up[i].range) { data[0] += (stretch->up[i].range - data[1]) * stretch->up[i].coe / 128; data[1] = stretch->up[i].range; } } x = data[1] - data[0]; if (x <= 0) x = 1; if (x >= (int)drv_num_nokey * 64) x = drv_num_nokey * 64 - 1; data[0] = 0; data[1] = drv_num_nokey * 64 - x; for (i = 0; i < 4; i++) { if (stretch->down[i].range == 0) break; if (data[1] < stretch->down[i].range) { data[0] += (stretch->down[i].range - data[1]) * stretch->down[i].coe / 128; data[1] = stretch->down[i].range; } } x = drv_num_nokey * 64 - (data[1] - data[0]); if (x <= 0) x = 1; if (x >= (int)drv_num_nokey * 64) x = drv_num_nokey * 64 - 1; point_now[id].x = x; point_now[id].y = y; } } static void PointStretch(void) { static int save_dr[POINT_MAX], save_dn[POINT_MAX]; typedef struct { int dis; int coe; } SHAKE_TYPE; SHAKE_TYPE *shake_all = (SHAKE_TYPE *)shake_all_array; int i, j; int dn; int dr; int dc[9], ds[9]; int len = 8; unsigned int temp; for (i = 0; i < POINT_MAX; i++) ps[0][i].all = pp[0][i].all; for (i = 0; i < POINT_MAX; i++) { if (pp[0][i].all == 0 || pp[0][i].key) { point_shake &= ~(0x1 << i); if (i == 0) point_edge.rate = 0; continue; } if (i == 0) { if (edge_first != 0 && ps[1][i].all == 0) { point_edge.coor.all = ps[0][i].all; if (point_edge.coor.x < (unsigned int)((edge_first >> 24) & 0xff)) point_edge.coor.x = ((edge_first >> 24) & 0xff); if (point_edge.coor.x > drv_num_nokey * 64 - ((edge_first >> 16) & 0xff)) point_edge.coor.x = drv_num_nokey*64 - ((edge_first >> 16) & 0xff); if (point_edge.coor.y < (unsigned int)((edge_first >> 8) & 0xff)) point_edge.coor.y = ((edge_first >> 8) & 0xff); if (point_edge.coor.y > sen_num_nokey * 64 - ((edge_first >> 0) & 0xff)) point_edge.coor.y = sen_num_nokey * 64 - ((edge_first >> 0) & 0xff); if (point_edge.coor.all != ps[0][i].all) { point_edge.dis = PointDistance(&ps[0][i], &point_edge.coor); if (point_edge.dis) point_edge.rate = 0x1000; } } if (point_edge.rate != 0 && point_edge.dis != 0) { temp = PointDistance(&ps[0][i], &point_edge.coor); if (temp >= point_edge.dis * edge_first_coe / 0x80) { point_edge.rate = 0; } else if (temp > point_edge.dis) { temp = (point_edge.dis * edge_first_coe / 0x80 - temp) * 0x1000/point_edge.dis; if (temp < point_edge.rate) point_edge.rate = temp; } ps[0][i].x = point_edge.coor.x + (ps[0][i].x - point_edge.coor.x) * (0x1000 - point_edge.rate) / 0x1000; ps[0][i].y = point_edge.coor.y + (ps[0][i].y - point_edge.coor.y) * (0x1000 - point_edge.rate) / 0x1000; } } if (ps[1][i].all == 0) continue; else if ((point_shake & (0x1 << i)) == 0) { if (PointDistance(&ps[0][i], &ps[1][i]) < (unsigned int)shake_min) { ps[0][i].all = ps[1][i].all; continue; } else point_shake |= (0x1 << i); } } for (i = 0; i < len; i++) { if (shake_all[i].dis == 0) { len = i; break; } } if (len == 1) { ds[0] = shake_all[0].dis; dc[0] = (shake_all[0].coe*100+64)/128; for (i = 0; i < POINT_MAX; i++) { if (ps[1][i].all == 0) { for (j = 1; j < PS_DEEP; j++) ps[j][i].all = ps[0][i].all; continue; } if ((point_shake & (0x1 << i)) == 0) continue; dn = PointDistance(&pp[0][i], &ps[1][i]); dn = Sqrt(dn); dr = dn > ds[0] ? dn-ds[0] : 0; temp = ps[0][i].all; if (dn == 0 || dr == 0) { ps[0][i].x = ps[1][i].x; ps[0][i].y = ps[1][i].y; } else { ps[0][i].x = (int)ps[1][i].x + ((int)pp[0][i].x - (int)ps[1][i].x) * dr / dn; ps[0][i].y = (int)ps[1][i].y + ((int)pp[0][i].y - (int)ps[1][i].y) * dr / dn; } if (dc[0] > 0) { if (ps[0][i].all == ps[1][i].all && temp != ps[0][i].all) { ps[0][i].all = temp; point_decimal[i].x += ps[0][i].x - ps[1][i].x; point_decimal[i].y += ps[0][i].y - ps[1][i].y; ps[0][i].x = ps[1][i].x; ps[0][i].y = ps[1][i].y; if (point_decimal[i].x > dc[0] && ps[1][i].x < 0xffff) { ps[0][i].x += 1; point_decimal[i].x = 0; } if (point_decimal[i].x < -dc[0] && ps[1][i].x > 0) { ps[0][i].x -= 1; point_decimal[i].x = 0; } if (point_decimal[i].y > dc[0] && ps[1][i].y < 0xffff) { ps[0][i].y += 1; point_decimal[i].y = 0; } if (point_decimal[i].y < -dc[0] && ps[1][i].y > 0) { ps[0][i].y -= 1; point_decimal[i].y = 0; } } else { point_decimal[i].x = 0; point_decimal[i].y = 0; } } } } else if (len >= 2) { for (i = 0; i < 8 && i < len; i++) { ds[i+1] = shake_all[i].dis; dc[i+1] = shake_all[i].coe; } if (shake_all[0].coe >= 128 || shake_all[0].coe <= shake_all[1].coe) { ds[0] = ds[1]; dc[0] = dc[1]; } else { ds[0] = ds[1] + (128 - shake_all[0].coe) * (ds[1]-ds[2]) / (shake_all[0].coe - shake_all[1].coe); dc[0] = 128; } for (i = 0; i < POINT_MAX; i++) { if (ps[1][i].all == 0) { for (j = 1; j < PS_DEEP; j++) ps[j][i].all = ps[0][i].all; save_dr[i] = 128; save_dn[i] = 0; continue; } if ((point_shake & (0x1 << i)) == 0) continue; dn = PointDistance(&pp[0][i], &ps[1][i]); dn = Sqrt(dn); if (dn >= ds[0]) continue; if (dn < save_dn[i]) { dr = save_dr[i]; save_dn[i] = dn; ps[0][i].x = (int)ps[1][i].x + (((int)pp[0][i].x - (int)ps[1][i].x) * dr) / 128; ps[0][i].y = (int)ps[1][i].y + (((int)pp[0][i].y - (int)ps[1][i].y) * dr) / 128; continue; } for (j = 0; j <= len; j++) { if (j == len || dn == 0) { ps[0][i].x = ps[1][i].x; ps[0][i].y = ps[1][i].y; break; } else if (ds[j] > dn && dn >= ds[j+1]) { dr = dc[j+1] + ((dn - ds[j+1]) * (dc[j] - dc[j+1])) / (ds[j] - ds[j+1]); save_dr[i] = dr; save_dn[i] = dn; /* ps[0][i].x = (int)ps[1][i].x + ((int)pp[0][i].x - (int)ps[1][i].x) * dr / dn / 128;*/ /* ps[0][i].y = (int)ps[1][i].y + ((int)pp[0][i].y - (int)ps[1][i].y) * dr / dn / 128;*/ ps[0][i].x = (int)ps[1][i].x + (((int)pp[0][i].x - (int)ps[1][i].x) * dr+64) / 128; ps[0][i].y = (int)ps[1][i].y + (((int)pp[0][i].y - (int)ps[1][i].y) * dr+64) / 128; break; } } } } else return; } static void ResetMask(void) { if (reset_mask_send) reset_mask_send = 0; if (global_state.mask) return; if (reset_mask_dis == 0 || reset_mask_type == 0) return; if (reset_mask_max == 0xfffffff1) { if (point_num == 0) reset_mask_max = 0xf0000000 + 1; return; } if (reset_mask_max > 0xf0000000) { reset_mask_max--; if (reset_mask_max == 0xf0000000) { reset_mask_send = reset_mask_type; global_state.mask = 1; } return; } if (point_num > 1 || pp[0][0].all == 0) { reset_mask_count = 0; reset_mask_max = 0; reset_mask_count = 0; return; } reset_mask_count++; if (reset_mask_max == 0) reset_mask_max = pp[0][0].all; else if (PointDistance((gsl_POINT_TYPE *)(&reset_mask_max), pp[0]) > (((unsigned int)reset_mask_dis) & 0xffffff) && reset_mask_count > (((unsigned int)reset_mask_dis) >> 24)) reset_mask_max = 0xfffffff1; } static int ConfigCoorMulti(int data[]) { int i, j; int n = 0; for (i = 0; i < 4; i++) { if (data[247+i] != 0) { if ((data[247 + i] & 63) == 0 && (data[247 + i] >> 16) < 4) n++; else return FALSE; } if (data[251 + i] != 0) { if ((data[251 + i] & 63) == 0 && (data[251 + i] >> 16) < 4) n++; else return FALSE; } } if (n == 0 || n > 4) return FALSE; for (j = 0; j < n; j++) { for (i = 0; i < 64; i++) { if (data[256 + j * 64 + i] >= 64) return FALSE; if (i) { if (data[256 + j * 64 + i] < data[256 + j * 64 + i - 1]) return FALSE; } } } return TRUE; } static int ConfigFilter(unsigned int data[]) { int i; unsigned int ps_c[8]; unsigned int pr_c[8]; unsigned int sum = 0; if (data[242] > 1 && (data[255] >= 0 && data[255] <= 256)) { for (i = 0; i < 8; i++) { ps_c[i] = (data[243 + i / 4] >> ((i % 4) * 8)) & 0xff; pr_c[i] = (data[243 + i / 4 + 2] >> ((i % 4) * 8)) & 0xff; if (ps_c[i] >= 0x80) ps_c[i] |= 0xffffff00; if (pr_c[i] >= 0x80) pr_c[i] |= 0xffffff00; sum += ps_c[i]; sum += pr_c[i]; } if (sum == data[242] || sum + data[242] == 0) return TRUE; } return FALSE; } static int ConfigKeyMap(int data[]) { int i; if (data[217] != 1) return FALSE; for (i = 0; i < 8; i++) { if (data[218 + 2] == 0) return FALSE; if ((data[218+i*3+0] >> 16) > (data[218+i*3+0]&0xffff)) return FALSE; if ((data[218+i*3+1] >> 16) > (data[218+i*3+1]&0xffff)) return FALSE; } return TRUE; } static int DiagonalDistance(gsl_POINT_TYPE *p, int type) { int divisor, square; divisor = ((int)sen_num_nokey * (int)sen_num_nokey + (int)drv_num_nokey * (int)drv_num_nokey) / 16; if (divisor == 0) divisor = 1; if (type == 0) square = ((int)sen_num_nokey * (int)(p->x) - (int)drv_num_nokey * (int)(p->y)) / 4; else square = ((int)sen_num_nokey * (int)(p->x) + (int)drv_num_nokey * (int)(p->y) - (int)sen_num_nokey * (int)drv_num_nokey * 64) / 4; return square * square / divisor; } static void DiagonalCompress(gsl_POINT_TYPE *p, int type, int dis, int dis_max) { int x, y; int tx, ty; int cp_ceof; if (dis_max == 0) return; if (dis > dis_max) cp_ceof = (dis - dis_max)*128/(3*dis_max) + 128; else cp_ceof = 128; if (cp_ceof > 256) cp_ceof = 256; x = p->x; y = p->y; if (type) y = (int)sen_num_nokey*64 - y; x *= (int)sen_num_nokey; y *= (int)drv_num_nokey; tx = x; ty = y; x = ((tx+ty)+(tx-ty)*cp_ceof/256)/2; y = ((tx+ty)+(ty-tx)*cp_ceof/256)/2; x /= (int)sen_num_nokey; y /= (int)drv_num_nokey; if (type) y = sen_num_nokey*64 - y; if (x < 1) x = 1; if (y < 1) y = 1; if (x >= (int)drv_num_nokey*64) x = drv_num_nokey*64 - 1; if (y >= (int)sen_num_nokey*64) y = (int)sen_num_nokey*64 - 1; p->x = x; p->y = y; } static void PointDiagonal(void) { int i; int diagonal_size; int dis; unsigned int diagonal_start; if (diagonal == 0) return; diagonal_size = diagonal * diagonal; diagonal_start = diagonal * 3 / 2; for (i = 0; i < POINT_MAX; i++) { if (ps[0][i].all == 0 || ps[0][i].key != 0) { point_corner &= ~(0x3 << i*2); continue; } else if ((point_corner & (0x3 << i*2)) == 0) { if ((ps[0][i].x <= diagonal_start && ps[0][i].y <= diagonal_start) || (ps[0][i].x >= drv_num_nokey * 64 - diagonal_start && ps[0][i].y >= sen_num_nokey*64 - diagonal_start)) point_corner |= 0x2 << i*2; else if ((ps[0][i].x <= diagonal_start && ps[0][i].y >= sen_num_nokey * 64 - diagonal_start) || (ps[0][i].x >= drv_num_nokey*64 - diagonal_start && ps[0][i].y <= diagonal_start)) point_corner |= 0x3 << i*2; else point_corner |= 0x1 << i*2; } if (point_corner & (0x2 << i*2)) { dis = DiagonalDistance(&(ps[0][i]), point_corner & (0x1 << i*2)); if (dis <= diagonal_size * 4) { DiagonalCompress(&(ps[0][i]), point_corner & (0x1 << i*2), dis, diagonal_size); } else if (dis > diagonal_size * 4) { point_corner &= ~(0x3 << i * 2); point_corner |= 0x1 << i * 2; } } } } static int PointSlope(int i, int j) { int x, y; x = pr[j][i].x - pr[j+1][i].x; x = x*x; y = pr[j][i].y - pr[j+1][i].y; y = y * y; if (x + y == 0) return -1; if (x > y) return x * 1024 / (x + y); else return y * 1024 / (x + y); } static void PointExtend(void) { int i, j; int x, y; int t, t2; int extend_len = 5; if (point_extend == 0) return; for (i = 0; i < POINT_MAX; i++) { if (pr[0][i].fill == 0) continue; for (j = 0; j < extend_len; j++) { if (pr[j][i].all == 0) break; } if (j < extend_len) continue; if (PointDistance(&pr[1][i], &pr[2][i]) < 16*16) continue; t = PointSlope(i, 1); for (j = 2; j < extend_len-1; j++) { t2 = PointSlope(i, j); if (t2 < 0 || t2 < t * (128 - point_extend) / 128 || t2 > t * (128 + point_extend) / 128) break; } if (j < extend_len - 1) continue; x = 3*pr[1][i].x - 2*pr[2][i].x; y = 3*pr[1][i].y - 2*pr[2][i].y; pr[0][i].all = PointRange(x, y, pr[1][i].x, pr[1][i].y); } } static void PressureSave(void) { int i; if ((point_num & 0x1000) == 0) return; for (i = 0; i < POINT_MAX; i++) { pressure_now[i] = point_now[i].all >> 28; point_now[i].all &= ~(0xf << 28); } } static void PointPressure(void) { int i, j; for (i = 0; i < POINT_MAX; i++) { if (pa[0][i] != 0 && pa[1][i] == 0) { pressure_report[i] = pa[0][i] * 5; for (j = 1; j < PRESSURE_DEEP; j++) pa[j][i] = pa[0][i]; continue; } j = (pressure_report[i]+1) / 2 + pa[0][i] + pa[1][i] + (pa[2][i]+1) / 2 - pressure_report[i]; if (j >= 2) j -= 2; else if (j <= -2) j += 2; else j = 0; pressure_report[i] = pressure_report[i]+j; } } void gsl_ReportPressure(unsigned int *p) { int i; for (i = 0; i < POINT_MAX; i++) { if (i < point_num) { if (pressure_now[i] == 0) p[i] = 0; else if (pressure_now[i] <= 7) p[i] = 1; else if (pressure_now[i] > 63+7) p[i] = 63; else p[i] = pressure_now[i] - 7; } else p[i] = 0; } } EXPORT_SYMBOL(gsl_ReportPressure); int gsl_TouchNear(void) { return 0; } EXPORT_SYMBOL(gsl_TouchNear); static void DoubleClick(void) { int i; unsigned int width[3]; double_click = 0; if (point_num >= 2 || (point_num == 1 && pp[0][0].all == 0) || pp[0][0].key) { for (i = 0; i < ARRAY_SIZE(click_count); i++) click_count[i] = 0; return; } if (point_num != 0 && prev_num == 0) { for (i = ARRAY_SIZE(click_count) - 1; i > 0; i--) click_count[i] = click_count[i-1]; click_count[0] = csensor_count; for (i = ARRAY_SIZE(point_click) - 1; i > 1; i--) point_click[i].all = point_click[i-2].all; point_click[0].all = pp[0][0].all; point_click[1].all = pp[0][0].all; } if (point_num != 0 && prev_num != 0) { if (PointDistance(&point_click[1], &pp[0][0]) > PointDistance(&point_click[1], &point_click[0])) point_click[0].all = pp[0][0].all; } if (point_num == 0 && prev_num != 0) { for (i = ARRAY_SIZE(click_count) - 1; i > 0; i--) click_count[i] = click_count[i-1]; click_count[0] = csensor_count; for (i = 0; i < ARRAY_SIZE(click_count) - 1; i++) width[i] = (click_count[i] - click_count[i+1]) & 0xffff; if (!(width[0] >= double_down*average && width[2] >= double_down * average && width[1] <= double_up*average)) return; if (PointDistance(&point_click[0], &point_click[1]) > 64*64 || PointDistance(&point_click[2], &point_click[3]) > 64*64 || PointDistance(&point_click[1], &point_click[3]) > 128*128) return; for (i = 0; i < ARRAY_SIZE(click_count); i++) click_count[i] = 0; double_click = '*'; } } static void gsl_id_reg_init(int flag) { int i, j; for (j = 0; j < POINT_DEEP; j++) for (i = 0; i < POINT_MAX; i++) point_array[j][i].all = 0; for (j = 0; j < PRESSURE_DEEP; j++) for (i = 0; i < POINT_MAX; i++) pressure_array[j][i] = 0; for (i = 0; i < POINT_MAX; i++) { point_delay[i].all = 0; filter_deep[i] = 0; point_decimal[i].all = 0; } point_edge.rate = 0; point_n = 0; if (flag) point_num = 0; prev_num = 0; point_shake = 0; reset_mask_send = 0; reset_mask_max = 0; reset_mask_count = 0; point_near = 0; point_corner = 0; global_state.all = 0; double_click = 0; inte_count = 0; csensor_count = 0; #ifdef GESTURE_LICH GestureInit(); #endif } static int DataCheck(void) { if (drv_num == 0 || drv_num_nokey == 0 || sen_num == 0 || sen_num_nokey == 0) return 0; if (screen_x_max == 0 || screen_y_max == 0) return 0; return 1; } void gsl_DataInit(unsigned int *conf_in) { int i; unsigned int *conf; int len; gsl_id_reg_init(1); for (i = 0; i < POINT_MAX; i++) point_now[i].all = 0; conf = config_static; coordinate_correct_able = 0; for (i = 0; i < 32; i++) { coordinate_correct_coe_x[i] = i; coordinate_correct_coe_y[i] = i; } id_first_coe = 8; id_speed_coe = 128 * 128; id_static_coe = 64 * 64; average = 3 + 1; soft_average = 3; report_delay = 0; report_ahead = 0x9249249; for (i = 0; i < 4; i++) median_dis[i] = 0; shake_min = 0*0; for (i = 0; i < 2; i++) { match_y[i] = 0; match_x[i] = 0; ignore_y[i] = 0; ignore_x[i] = 0; } match_y[0] = 4096; match_x[0] = 4096; screen_y_max = 480; screen_x_max = 800; point_num_max = 10; drv_num = 16; sen_num = 10; drv_num_nokey = 16; sen_num_nokey = 10; for (i = 0; i < 4; i++) edge_cut[i] = 0; for (i = 0; i < 32; i++) stretch_array[i] = 0; for (i = 0; i < 16; i++) shake_all_array[i] = 0; reset_mask_dis = 0; reset_mask_type = 0; diagonal = 0; point_extend = 0; key_map_able = 0; for (i = 0; i < 8 * 3; i++) key_range_array[i] = 0; filter_able = 0; filter_coe[0] = (0 << 6*4)+(0 << 6*3)+(0 << 6*2)+(40 << 6*1)+(24 << 6*0); filter_coe[1] = (0 << 6*4)+(0 << 6*3)+(16 << 6*2)+(24 << 6*1)+(24 << 6*0); filter_coe[2] = (0 << 6*4)+(16 << 6*3)+(24 << 6*2)+(16 << 6*1)+(8 << 6*0); filter_coe[3] = (6 << 6*4)+(16 << 6*3)+(24 << 6*2)+(12 << 6*1)+(6 << 6*0); for (i = 0; i < 4; i++) { multi_x_array[i] = 0; multi_y_array[i] = 0; } point_repeat[0] = 32; point_repeat[1] = 96; edge_first = 0; edge_first_coe = 0x80; if (conf_in == NULL) return; if (conf_in[0] <= 0xfff) { if (ConfigCoorMulti(conf_in)) len = 512; else if (ConfigFilter(conf_in)) len = 256; else if (ConfigKeyMap(conf_in)) len = 241; else len = 215; } else if (conf_in[1] <= CONFIG_LENGTH) len = conf_in[1]; else len = CONFIG_LENGTH; for (i = 0; i < len; i++) conf[i] = conf_in[i]; for (; i < CONFIG_LENGTH; i++) conf[i] = 0; if (conf_in[0] <= 0xfff) { coordinate_correct_able = conf[0]; drv_num = conf[1]; sen_num = conf[2]; drv_num_nokey = conf[3]; sen_num_nokey = conf[4]; id_first_coe = conf[5]; id_speed_coe = conf[6]; id_static_coe = conf[7]; average = conf[8]; soft_average = conf[9]; report_delay = conf[13]; shake_min = conf[14]; screen_y_max = conf[15]; screen_x_max = conf[16]; point_num_max = conf[17]; global_flag.all = conf[18]; for (i = 0; i < 4; i++) median_dis[i] = conf[19+i]; for (i = 0; i < 2; i++) { match_y[i] = conf[23+i]; match_x[i] = conf[25+i]; ignore_y[i] = conf[27+i]; ignore_x[i] = conf[29+i]; } for (i = 0; i < 64; i++) { coordinate_correct_coe_x[i] = conf[31+i]; coordinate_correct_coe_y[i] = conf[95+i]; } for (i = 0; i < 4; i++) edge_cut[i] = conf[159+i]; for (i = 0; i < 32; i++) stretch_array[i] = conf[163+i]; for (i = 0; i < 16; i++) shake_all_array[i] = conf[195+i]; reset_mask_dis = conf[213]; reset_mask_type = conf[214]; key_map_able = conf[217]; for (i = 0; i < 8*3; i++) key_range_array[i] = conf[218+i]; filter_able = conf[242]; for (i = 0; i < 4; i++) filter_coe[i] = conf[243+i]; for (i = 0; i < 4; i++) multi_x_array[i] = conf[247+i]; for (i = 0; i < 4; i++) multi_y_array[i] = conf[251+i]; diagonal = conf[255]; for (i = 0; i < 256; i++) *(multi_group[0]+i) = conf[256+i]; for (i = 0; i < 32; i++) { *(ps_coe[0] + i) = conf[256 + 64 * 3 + i]; *(pr_coe[0] + i) = conf[256 + 64 * 3 + i + 32]; } near_set[0] = 0; near_set[1] = 0; } else { global_flag.all = conf[0x10]; point_num_max = conf[0x11]; drv_num = conf[0x12] & 0xffff; sen_num = conf[0x12] >> 16; drv_num_nokey = conf[0x13] & 0xffff; sen_num_nokey = conf[0x13] >> 16; screen_x_max = conf[0x14] & 0xffff; screen_y_max = conf[0x14] >> 16; average = conf[0x15]; reset_mask_dis = conf[0x16]; reset_mask_type = conf[0x17]; point_repeat[0] = conf[0x18] >> 16; point_repeat[1] = conf[0x18] & 0xffff; near_set[0] = conf[0x19] >> 16; near_set[1] = conf[0x19] & 0xffff; diagonal = conf[0x1a]; point_extend = conf[0x1b]; id_first_coe = conf[0x20]; id_speed_coe = conf[0x21]; id_static_coe = conf[0x22]; match_y[0] = conf[0x23] >> 16; match_y[1] = conf[0x23] & 0xffff; match_x[0] = conf[0x24] >> 16; match_x[1] = conf[0x24] & 0xffff; ignore_y[0] = conf[0x25] >> 16; ignore_y[1] = conf[0x25] & 0xffff; ignore_x[0] = conf[0x26] >> 16; ignore_x[1] = conf[0x26] & 0xffff; edge_cut[0] = (conf[0x27] >> 24) & 0xff; edge_cut[1] = (conf[0x27] >> 16) & 0xff; edge_cut[2] = (conf[0x27] >> 8) & 0xff; edge_cut[3] = (conf[0x27] >> 0) & 0xff; report_delay = conf[0x28]; shake_min = conf[0x29]; for (i = 0; i < 16; i++) { stretch_array[i * 2 + 0] = conf[0x2a+i] & 0xffff; stretch_array[i * 2 + 1] = conf[0x2a+i] >> 16; } for (i = 0; i < 8; i++) { shake_all_array[i * 2 + 0] = conf[0x3a + i] & 0xffff; shake_all_array[i * 2 + 1] = conf[0x3a + i] >> 16; } report_ahead = conf[0x42]; /* key_dead_time = conf[0x43]; * point_dead_time = conf[0x44]; * point_dead_time2 = conf[0x45]; * point_dead_distance = conf[0x46]; * point_dead_distance2 = conf[0x47]; */ edge_first = conf[0x48]; edge_first_coe = conf[0x49]; key_map_able = conf[0x60]; for (i = 0; i < 8 * 3; i++) key_range_array[i] = conf[0x61+i]; coordinate_correct_able = conf[0x100]; for (i = 0; i < 4; i++) { multi_x_array[i] = conf[0x101 + i]; multi_y_array[i] = conf[0x105 + i]; } for (i = 0; i < 64; i++) { coordinate_correct_coe_x[i] = (conf[0x109 + i / 4] >> (i % 4 * 8)) & 0xff; coordinate_correct_coe_y[i] = (conf[0x109 + 64 / 4 + i / 4] >> (i % 4 * 8)) & 0xff; } for (i = 0; i < 256; i++) { /*multi_group[0][i] = (conf[0x109+64/4*2+i/4] >> (i%4*8)) & 0xff;*/ *(multi_group[0]+i) = (conf[0x109+64/4*2+i/4] >> (i%4*8)) & 0xff; } filter_able = conf[0x180]; for (i = 0; i < 4; i++) filter_coe[i] = conf[0x181 + i]; for (i = 0; i < 4; i++) median_dis[i] = conf[0x185 + i]; for (i = 0; i < 32; i++) { *(ps_coe[0]+i) = conf[0x189 + i]; *(pr_coe[0]+i) = conf[0x189 + i + 32]; } #ifdef GESTURE_LICH GestureSet(&conf[0x189 + 64]); #endif } if (average == 0) average = 4; for (i = 0; i < 8; i++) { if (shake_all_array[i * 2] & 0x8000) shake_all_array[i * 2] = shake_all_array[i * 2] & ~0x8000; else shake_all_array[i * 2] = Sqrt(shake_all_array[i * 2]); } for (i = 0; i < 2; i++) { if (match_x[i] & 0x8000) match_x[i] |= 0xffff0000; if (match_y[i] & 0x8000) match_y[i] |= 0xffff0000; if (ignore_x[i] & 0x8000) ignore_x[i] |= 0xffff0000; if (ignore_y[i] & 0x8000) ignore_y[i] |= 0xffff0000; } for (i = 0; i < CONFIG_LENGTH; i++) config_static[i] = 0; } EXPORT_SYMBOL(gsl_DataInit); unsigned int gsl_version_id(void) { return GSL_VERSION; } EXPORT_SYMBOL(gsl_version_id); unsigned int gsl_mask_tiaoping(void) { return reset_mask_send; } EXPORT_SYMBOL(gsl_mask_tiaoping); static void GetFlag(void) { int i = 0; int num_save; if ((point_num & 0x8000) != 0) { if ((point_num&0xff000000) == 0x5a000000) gesture_last = (point_num >> 16) & 0xff; } if (((point_num & 0x100) != 0) || ((point_num & 0x200) != 0 && global_state.reset == 1)) gsl_id_reg_init(0); if ((point_num & 0x300) == 0) global_state.reset = 1; if (point_num & 0x400) global_state.only = 1; else global_state.only = 0; if (point_num & 0x2000) global_state.interpolation = 0xf; else if (global_state.interpolation) global_state.interpolation--; if (point_num & 0x4000) global_state.ex = 1; else global_state.ex = 0; inte_count++; csensor_count = ((unsigned int)point_num) >> 16; num_save = point_num & 0xff; if (num_save > POINT_MAX) num_save = POINT_MAX; for (i = 0; i < POINT_MAX; i++) { if (i >= num_save) point_now[i].all = 0; } point_num = (point_num & (~0xff)) + num_save; } void gsl_FunIICRead(unsigned int (*fun) (unsigned int *, unsigned int, unsigned int)) { ReadIICInt = fun; } EXPORT_SYMBOL(gsl_FunIICRead); static int GestureJoint(void) { unsigned int buf[128]; unsigned int len = 0; unsigned int addr = 0; unsigned int i; if ((point_num & 0x8000) == 0) return FALSE; if ((point_num & 0xff000000) != 0x5b000000) return FALSE; if (ReadIICInt == NULL) return FALSE; addr = point_now[0].all; len = point_now[1].all; if (len > 128) len = 128; ReadIICInt(buf, addr, len); if (len < 8) { gesture_last = 0x7fffffff; return TRUE; } for (i = 0; i < POINT_MAX; i++) point_now[i].all = 0; GestureInit(); for (i = 0; i < len+5; i++) { if (i < len) { point_num = 1; point_now[0].all = buf[i]; if (buf[i] == 0 || (buf[i] & 0xe000b000) != 0) { GestureInit(); break; } } else { point_num = 0; point_now[0].all = 0; } PointCoor(); CoordinateCorrect(); PointEdge(); PointPointer(); PointPredict(); PointId(); PointNewId(); PointOrder(); PointStretch(); PointFilter(); GetPointNum(pr[0]); if (i < len + 2) GestureMain(&(pr[0][0].all), point_num); } point_num = 0; for (i = 0; i < POINT_MAX; i++) point_now[i].all = 0; return TRUE; } void gsl_alg_id_main(struct gsl_touch_info *cinfo) { int i; point_num = cinfo->finger_num; for (i = 0; i < POINT_MAX; i++) point_now[i].all = (cinfo->id[i] << 28) | (cinfo->x[i] << 16) | cinfo->y[i]; if (GestureJoint()) { cinfo->finger_num = 0; for (i = 0; i < POINT_MAX; i++) { cinfo->id[i] = 0; cinfo->x[i] = 0; cinfo->y[i] = 0; } return; } GetFlag(); if (DataCheck() == 0) { point_num = 0; cinfo->finger_num = 0; return; } PressureSave(); PointCoor(); CoordinateCorrect(); PointEdge(); PointRepeat(); GetPointNum(point_now); PointPointer(); PointPredict(); PointId(); PointNewId(); PointOrder(); PointCross(); GetPointNum(pp[0]); DoubleClick(); prev_num = point_num; ResetMask(); PointStretch(); PointDiagonal(); PointFilter(); GetPointNum(pr[0]); #ifdef GESTURE_LICH GestureMain(&(pr[0][0].all), point_num); #endif PointDelay(); PointExtend(); PointPressure(); PointReport(cinfo); } EXPORT_SYMBOL(gsl_alg_id_main); #ifdef GESTURE_LICH int gsl_obtain_gesture(void) { return GestureDeal(); } EXPORT_SYMBOL(gsl_obtain_gesture); static int GestureMain(unsigned int data_coor[], unsigned int num) { gesture_deal = FALSE; if (gesture_dis_min == 0) return FALSE; gesture_multi = GestureMulti(data_coor); if (gesture_multi) { gesture_deal = GESTURE_DEAL; return TRUE; } if (num == 0) { if (gesture_num == 0) return FALSE; if (gesture_num <= 8) { GestureInit(); return FALSE; } gesture_deal = GESTURE_ALL; return TRUE; } else if (gesture_num < 0) return FALSE; else if (num == 1 && data_coor[0] != 0) { GesturePush((GESTURE_POINT_TYPE *)data_coor); return FALSE; } else { gesture_num = -1; return FALSE; } return TRUE; } static int GestureSqrt(int d) { int ret = 0; int i; for (i = 14; i >= 0; i--) { if ((ret + (0x1 << i)) * (ret + (0x1 << i)) <= d) ret |= (0x1 << i); } return ret; } static int GestureDistance(GESTURE_POINT_TYPE *d1, GESTURE_POINT_TYPE *d2, int sqrt_able) { if (sqrt_able) return GestureSqrt((d1->x-d2->x)*(d1->x-d2->x) + (d1->y-d2->y)*(d1->y-d2->y)); else return (d1->x-d2->x)*(d1->x-d2->x) + (d1->y-d2->y)*(d1->y-d2->y); } static int GesturePush(GESTURE_POINT_TYPE *data) { unsigned int data_i = data->all & 0xffff0fff; if (gesture_num >= GESTURE_BUF_SIZE) return FALSE; if (gesture_flag & 0x2) data_i = ((drv_num_nokey * 64 - (data_i >> 16)) << 16) + (data_i & 0xffff); if (gesture_flag & 0x4) data_i = (data_i & 0xffff0000) + ((sen_num_nokey * 64 - (data_i & 0xffff)) & 0xffff); if (gesture_flag & 0x8) data_i = ((data_i & 0xfff) << 16) + ((data_i >> 16) & 0xfff); if (gesture_num == 0) { gesture_buf[gesture_num++].all = data_i; return TRUE; } if (GestureDistance(data, &gesture_buf[gesture_num-1], TRUE) <= gesture_dis_min) return FALSE; gesture_buf[gesture_num++].all = data_i; return TRUE; } static void GestureInit(void) { int i; gesture_num_last = gesture_num; gesture_num = 0; gesture_deal = FALSE; if (gesture_dis_min < 0 || gesture_dis_min > 64) gesture_dis_min = 2; for (i = 0; i < 5; i++) { multi_x[i].count = 0; multi_o[i].count = 0; } } static int GestureStretch(void) { unsigned int x_max = 0, x_min = 0xffff, y_max = 0, y_min = 0xffff; int i; /*if (gesture_num <= GESTURE_SIZE_NUM/2)*/ /*return FALSE; */ if (gesture_num >= GESTURE_BUF_SIZE) return FALSE; for (i = 0; i < gesture_num; i++) { if (gesture_buf[i].x > x_max) x_max = gesture_buf[i].x; if (gesture_buf[i].x < x_min) x_min = gesture_buf[i].x; if (gesture_buf[i].y > y_max) y_max = gesture_buf[i].y; if (gesture_buf[i].y < y_min) y_min = gesture_buf[i].y; } if (x_max < x_min+64*2 || y_max < y_min+64*3) return FALSE; for (i = 0; i < gesture_num; i++) { gesture_buf[i].x = (gesture_buf[i].x - x_min) * GESTURE_SIZE_REFE / (x_max - x_min); gesture_buf[i].y = (gesture_buf[i].y - y_min) * GESTURE_SIZE_REFE / (y_max - y_min); } return TRUE; } static int GestureLength(void) { int i; int len = 0; for (i = 1; i < gesture_num; i++) len += GestureDistance(&gesture_buf[i], &gesture_buf[i-1], TRUE); return len; } static void GestureStandard(void) { int i, n, t; int len_now = 0; int len_his = 0; int len_total = GestureLength(); gesture_standard[0].all = gesture_buf[0].all & 0x0fffffff; gesture_standard[GESTURE_SIZE_NUM - 1].all = gesture_buf[gesture_num - 1].all & 0x0fffffff; for (i = 1, n = 0; i < GESTURE_SIZE_NUM-1; i++) { while (++n < gesture_num) { len_now = GestureDistance(&gesture_buf[n], &gesture_buf[n - 1], TRUE); len_his += len_now; if (len_his*(GESTURE_SIZE_NUM-1) >= len_total*i) break; } if (n >= gesture_num || len_now == 0) break; gesture_standard[i].all = 0; t = (int)gesture_buf[n-1].x + ((int)gesture_buf[n].x - (int)gesture_buf[n-1].x) * ((int)len_total*i/(GESTURE_SIZE_NUM-1) - (int)len_his + (int)len_now) / (int)len_now ; if (t < 0) t = 0; gesture_standard[i].x = t; t = (int)gesture_buf[n-1].y + ((int)gesture_buf[n].y - (int)gesture_buf[n-1].y) * ((int)len_total*i/(GESTURE_SIZE_NUM-1) - (int)len_his + (int)len_now) / (int)len_now ; if (t < 0) t = 0; gesture_standard[i].y = t; n--; len_his -= len_now; } } static int GestureModel(const GESTURE_MODEL_TYPE *model, int len, int threshold, int *out) { int offset[] = {-2, -1, 0, 1, 2}; int ret_offset; int i, j, k, n; int min, min_n; GESTURE_POINT_TYPE model_coor; if (model == NULL || threshold <= 0 || len <= 0) { *out = 0x7fffffff; return 0x7fffffff; } min = 0x7fffffff; min_n = 0; for (j = 0; j < len; j++) { for (k = 0; k < ARRAY_SIZE(offset); k++) { n = 0; ret_offset = 0; for (i = 0; i < GESTURE_SIZE_NUM; i++) { if (i + offset[k] < 0 || i+offset[k] >= GESTURE_SIZE_NUM) continue; if ((i&1) == 0) model_coor.all = model[j].coor[i / 2] & 0x00ff00ff; else model_coor.all = (model[j].coor[i / 2] >> 8) & 0x00ff00ff; ret_offset += GestureDistance(&gesture_standard[i+offset[k]], &model_coor, FALSE); n++; } if (n == 0) continue; ret_offset = ret_offset / n * model[j].coe / 0x10; if (ret_offset < min) { min_n = j; min = ret_offset; } } } if (min < threshold) *out = model[min_n].out; else *out = 0x7fffffff; return min; } static void ChangeXY(void) { int i; for (i = 0; i < gesture_num && i < GESTURE_BUF_SIZE; i++) gesture_buf[i].all = ((gesture_buf[i].all & 0xfff) << 16) + ((gesture_buf[i].all >> 16) & 0xffff); } static void GestureSet(unsigned int conf[]) { if (conf == NULL) return; if (conf[0] >= 0 && conf[0] <= 64) gesture_dis_min = conf[0]; else gesture_dis_min = 0; if (conf[1] != 0) gesture_threshold[0] = conf[1]; else gesture_threshold[0] = 0xfff; gesture_threshold[1] = conf[2]; x_scale = (conf[3] == 0) ? 4 : conf[3]; y_scale = (conf[4] == 0) ? 4 : conf[4]; if (conf[5] == 0) { double_down = 2; double_up = 30; } else { double_down = conf[5] & 0xffff; double_up = conf[5] >> 16; } multi_set = conf[6]; gesture_flag = conf[7]; } static void GestureOrientation(int ori) { int i, t; if (ori == 0) return; if (ori == 2) { for (i = 0; i < GESTURE_SIZE_NUM; i++) { t = GESTURE_SIZE_REFE - gesture_standard[i].x; gesture_standard[i].x = gesture_standard[i].y; gesture_standard[i].y = t; } } else if (ori == 1 || ori == 3) { for (i = 0; i < GESTURE_SIZE_NUM; i++) { gesture_standard[i].x = GESTURE_SIZE_REFE - gesture_standard[i].x; gesture_standard[i].y = GESTURE_SIZE_REFE - gesture_standard[i].y; } } else if (ori == 4) { for (i = 0; i < GESTURE_SIZE_NUM; i++) { t = GESTURE_SIZE_REFE - gesture_standard[i].y; gesture_standard[i].y = gesture_standard[i].x; gesture_standard[i].x = t; } } } static int GestureDeal(void) { int i, j; int gesture_out[2]; int gesture_val[2]; int gl[4]; int gv[4]; while (1) { if (gesture_last) break; gesture_last = gesture_multi; if (gesture_last) break; gesture_last = double_click; if (gesture_last) break; if (gesture_deal & GESTURE_XY) { gesture_deal &= ~GESTURE_XY; ChangeXY(); } if ((gesture_deal & GESTURE_DEAL) == 0) return FALSE; gesture_deal &= ~GESTURE_DEAL; gesture_last = GestureLRUD(); if (gesture_last) break; if (GestureStretch() == FALSE) break; GestureStandard(); for (j = 0; j < 4; j++) { gv[j] = 0x7fffffff; GestureOrientation(j); if (((gesture_flag & 0xf0) == 0 && j == 0) || ((gesture_flag & 0xf0) != 0 && (gesture_flag & (0x10 << j)) != 0)) { gesture_val[0] = GestureModel(model_default, sizeof(model_default) / sizeof(model_default[0]), gesture_threshold[0], &gesture_out[0]); gesture_val[1] = GestureModel(model_extern, model_extern_len, gesture_threshold[1], &gesture_out[1]); for (i = 0; i < 2; i++) { if (gesture_val[i] <= gv[j]) { gv[j] = gesture_val[i]; gl[j] = gesture_out[i]; } } } } gesture_value = 0x7fffffff; for (j = 0; j < 4; j++) { if (gl[j] >= 'A' && gl[j] <= 'Z' && gv[j] < gesture_value) { gesture_value = gv[j]; gesture_last = gl[j]; } } if (gesture_value < 0x7fffffff) break; for (j = 0; j < 4; j++) { if (gv[j] < gesture_value) { gesture_value = gv[j]; gesture_last = gl[j]; } } break; } GestureInit(); i = gesture_last; gesture_last = 0; return i; } void gsl_GestureExtern(const GESTURE_MODEL_TYPE *model, int len) { model_extern = model; model_extern_len = len; } EXPORT_SYMBOL(gsl_GestureExtern); static int GestureLRUD(void) { int x1 = 0, y1 = 0, x2 = 0, y2 = 0, i = 0; int flag3 = 0; int middle_x; int middle_y; int min_scale = 5; if (gesture_deal & GESTURE_XY) { gesture_deal &= ~GESTURE_XY; ChangeXY(); } if ((gesture_deal & GESTURE_LRUD) == 0) return FALSE; gesture_deal &= ~GESTURE_LRUD; /* int screen_x_max = 0, screen_y_max = 0;*/ x1 = gesture_buf[0].x; y1 = gesture_buf[0].y; x2 = gesture_buf[gesture_num - 1].x; y2 = gesture_buf[gesture_num - 1].y; middle_x = (x1 + x2) / 2; middle_y = (y1 + y2) / 2; for (i = 1; i < gesture_num; i++) { if (abs(gesture_buf[i].x-middle_x) < (int)sen_num_nokey * 64 / x_scale) flag3 |= 0x1; else flag3 |= 0x2; if (abs(gesture_buf[i].y-middle_y) < (int)drv_num_nokey*64/y_scale) flag3 |= (0x1 << 4); else flag3 |= (0x2 << 4); if ((int)gesture_buf[i].x-(int)gesture_buf[i-1].x > min_scale) flag3 |= (0x1 << 8); else if ((int)gesture_buf[i].x-(int)gesture_buf[i-1].x < -min_scale) flag3 |= (0x2 << 8); if ((int)gesture_buf[i].y-(int)gesture_buf[i-1].y > min_scale) flag3 |= (0x1 << 12); else if ((int)gesture_buf[i].y-(int)gesture_buf[i-1].y < -min_scale) flag3 |= (0x2 << 12); } if (1) { if ((flag3 == 0x2031 || flag3 == 0x2131 || flag3 == 0x2231 || flag3 == 0x2331)) return 0xa1fc; else if ((flag3 == 0x1031 || flag3 == 0x1131 || flag3 == 0x1231 || flag3 == 0x1331)) return 0xa1fd; else if ((flag3 == 0x213 || flag3 == 0x1213 || flag3 == 0x2213 || flag3 == 0x2213)) return 0xa1fb; else if ((flag3 == 0x113 || flag3 == 0x1113 || flag3 == 0x2113 || flag3 == 0x3113)) return 0xa1fa; } return FALSE; } static int GestureMulti(unsigned int *data_in) { #ifndef POINT_MAX #define POINT_MAX 10 #endif GESTURE_POINT_TYPE *data = (GESTURE_POINT_TYPE *)data_in; GESTURE_POINT_TYPE centre; int n = 0; int sum_x = 0, sum_y = 0, s = 0; int i; int msc, mse, msi; /*multi_set_count, effective, invalid*/ if (multi_set == 0) { msc = 5; mse = 8; msi = 16; } else { msc = (multi_set >> 0) & 0xff; mse = (multi_set >> 8) & 0xff; msi = (multi_set >> 16) & 0xff; } for (i = 0; i < POINT_MAX; i++) { if (data[i].all == 0) continue; n++; sum_x += data[i].x; sum_y += data[i].y; } if (n == 0) { s = FALSE; if (multi_x[5-1].count >= 0 && multi_x[4-1].count >= 0 && multi_x[5-1].count + multi_x[4-1].count >= msc) s |= 0xbacf; if (multi_o[5-1].count >= 0 && multi_o[4-1].count >= 0 && multi_o[5-1].count + multi_o[4-1].count >= msc) s |= 0xb7d6; if (s != 0xbacf && s != 0xb7d6) s = FALSE; for (i = 0; i < 5; i++) { multi_x[i].count = 0; multi_o[i].count = 0; } return s; } if (n == 1 || n > 5) return FALSE; sum_x /= n; sum_y /= n; centre.all = 0; centre.x = sum_x; centre.y = sum_y; s = 0; for (i = 0; i < POINT_MAX; i++) { if (data[i].all == 0) continue; s += GestureDistance(&data[i], ¢re, TRUE); } s /= n; n--; while (1) { if (multi_x[n].count == 0) { multi_x[n].count++; multi_x[n].dis = s; break; } if (multi_x[n].count < 0) break; if (s > multi_x[n].dis + msi) { multi_x[n].count = -1; break; } if (s + mse < multi_x[n].dis) { multi_x[n].count++; multi_x[n].dis = s; break; } break; } while (1) { if (multi_o[n].count == 0) { multi_o[n].count++; multi_o[n].dis = s; break; } if (multi_o[n].count < 0) break; if (s + msi < multi_o[n].dis) { multi_o[n].count = -1; break; } if (s > multi_o[n].dis + mse) { multi_o[n].count++; multi_o[n].dis = s; break; } break; } return FALSE; } unsigned int gsl_GestureBuffer(unsigned int **buf) { int i; if (gesture_num_last >= GESTURE_BUF_SIZE) gesture_num_last = GESTURE_BUF_SIZE - 1; for (i = 0; i < gesture_num_last; i++) gesture_buf[i].all = ScreenResolution((gsl_POINT_TYPE *)(&gesture_buf[i].all)); *buf = &(gesture_buf[0].all); return gesture_num_last; } EXPORT_SYMBOL(gsl_GestureBuffer); #endif