Chinaunix首页 | 论坛 | 博客
  • 博客访问: 950775
  • 博文数量: 113
  • 博客积分: 7235
  • 博客等级: 少将
  • 技术积分: 2101
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-14 11:24
文章分类

全部博文(113)

文章存档

2013年(7)

2012年(5)

2011年(6)

2010年(8)

2009年(15)

2008年(72)

分类: LINUX

2012-11-10 18:26:35

由于需要在GTK程序中实现触摸屏校准功能,所以最开始尝试通过popen和execl等调用ts_calibrate程序实现,校准是没有问题,但校准完成后,GTK界面却没了,看了ts_calibrate的代码,发现其实现是直接写framebuffer,所以造成GTK的界面消失。因此特写了一个使用GTK实现的触摸屏校准工具,代码如下:

点击(此处)折叠或打开

  1. /**
  2. * @file a.c
  3. *

    License

  4. * Copyright (c) 2011-2012 niu.tao
  5. *
  6. * This source code is released under the terms of GNU
  7. *
  8. * @author niu.tao
  9. * @version v1.0
  10. * @date Sat Nov 10 18:28:01 CST 2012
  11. *
  12. * @brief
  13. */
  14. #include
  15. #include
  16. #include
  17. #include
  18. #include
  19. #include
  20. #include
  21. #include
  22. #include
  23. #include
  24. #include
  25. #include
  26. #include
  27. #include
  28. typedef struct {
  29. int x[5], xfb[5];
  30. int y[5], yfb[5];
  31. int a[7];
  32. } calibration;
  33. #define TSLIB_TSDEVICE "/dev/input/ts0"
  34. #define DISPLAY "0:0"
  35. #define TSLIB_CALIBFILE "/usr/etc/pointercal"
  36. static __u32 xres, yres;
  37. static char *defaultfbdevice = "/dev/fb0";
  38. static char *fbdevice = NULL;
  39. static struct tsdev *ts;
  40. static calibration cal;
  41. static int cal_fd;
  42. GtkWidget *da;
  43. GdkGC *gc_red;
  44. GdkFont *font;
  45. struct ts_struct {
  46. int index;
  47. int x;
  48. int y;
  49. };
  50. struct ts_struct ts_s;
  51. static int step = 0;
  52. static void gtk_ts_calibrate_expose_event(GtkWidget * widget, GdkEventExpose * event, gpointer data);
  53. static void put_string(int x, int y, char *s)
  54. {
  55. gdk_draw_text(da->window, font, gc_red, x, y, s, strlen(s));
  56. }
  57. static void put_string_center(int x, int y, char *s)
  58. {
  59. int len = strlen(s);
  60. put_string(x - len / 2 * 6, y - 4, s);
  61. }
  62. static void line(int x1, int y1, int x2, int y2)
  63. {
  64. gdk_draw_line(da->window, gc_red, x1, y1, x2, y2);
  65. }
  66. static void put_cross(int x, int y)
  67. {
  68. gtk_ts_calibrate_expose_event(da, NULL, NULL);
  69. put_string_center(xres / 2, yres / 4, "TSLIB calibration utility");
  70. put_string_center(xres / 2, yres / 4 + 20, "Touch crosshair to calibrate");
  71. line(x - 10, y, x - 2, y);
  72. line(x + 2, y, x + 10, y);
  73. line(x, y - 10, x, y - 2);
  74. line(x, y + 2, x, y + 10);
  75. line(x - 6, y - 9, x - 9, y - 9);
  76. line(x - 9, y - 8, x - 9, y - 6);
  77. line(x - 9, y + 6, x - 9, y + 9);
  78. line(x - 8, y + 9, x - 6, y + 9);
  79. line(x + 6, y + 9, x + 9, y + 9);
  80. line(x + 9, y + 8, x + 9, y + 6);
  81. line(x + 9, y - 6, x + 9, y - 9);
  82. line(x + 8, y - 9, x + 6, y - 9);
  83. }
  84. static int sort_by_x(const void *a, const void *b)
  85. {
  86. return (((struct ts_sample *)a)->x - ((struct ts_sample *)b)->x);
  87. }
  88. static int sort_by_y(const void *a, const void *b)
  89. {
  90. return (((struct ts_sample *)a)->y - ((struct ts_sample *)b)->y);
  91. }
  92. int getxy(struct tsdev *ts, int *x, int *y)
  93. {
  94. #define MAX_SAMPLES 128
  95. struct ts_sample samp[MAX_SAMPLES];
  96. int index, middle;
  97. do {
  98. if (ts_read_raw(ts, &samp[0], 1) < 0) {
  99. perror("ts_read");
  100. return 1;
  101. }
  102. } while (samp[0].pressure == 0);
  103. /* Now collect up to MAX_SAMPLES touches into the samp array. */
  104. index = 0;
  105. do {
  106. if (index < MAX_SAMPLES - 1)
  107. index++;
  108. if (ts_read_raw(ts, &samp[index], 1) < 0) {
  109. perror("ts_read");
  110. return 1;
  111. }
  112. } while (samp[index].pressure > 0);
  113. printf("Took %d samples...\n", index);
  114. /*
  115. * At this point, we have samples in indices zero to (index-1)
  116. * which means that we have (index) number of samples. We want
  117. * to calculate the median of the samples so that wild outliers
  118. * don't skew the result. First off, let's assume that arrays
  119. * are one-based instead of zero-based. If this were the case
  120. * and index was odd, we would need sample number ((index+1)/2)
  121. * of a sorted array; if index was even, we would need the
  122. * average of sample number (index/2) and sample number
  123. * ((index/2)+1). To turn this into something useful for the
  124. * real world, we just need to subtract one off of the sample
  125. * numbers. So for when index is odd, we need sample number
  126. * (((index+1)/2)-1). Due to integer division truncation, we
  127. * can simplify this to just (index/2). When index is even, we
  128. * need the average of sample number ((index/2)-1) and sample
  129. * number (index/2). Calculate (index/2) now and we'll handle
  130. * the even odd stuff after we sort.
  131. */
  132. middle = index / 2;
  133. if (x) {
  134. qsort(samp, index, sizeof(struct ts_sample), sort_by_x);
  135. if (index & 1)
  136. *x = samp[middle].x;
  137. else
  138. *x = (samp[middle - 1].x + samp[middle].x) / 2;
  139. }
  140. if (y) {
  141. qsort(samp, index, sizeof(struct ts_sample), sort_by_y);
  142. if (index & 1)
  143. *y = samp[middle].y;
  144. else
  145. *y = (samp[middle - 1].y + samp[middle].y) / 2;
  146. }
  147. return 0;
  148. }
  149. void ts_flush(struct tsdev *ts)
  150. {
  151. /* Read all unread touchscreen data,
  152. * so that we are sure that the next data that we read
  153. * have been input after this flushing.
  154. */
  155. #define TS_BUFFER_MAX 32768
  156. static char buffer[TS_BUFFER_MAX];
  157. read(ts_fd(ts), buffer, TS_BUFFER_MAX);
  158. }
  159. static int perform_calibration(calibration * cal)
  160. {
  161. int j;
  162. float n, x, y, x2, y2, xy, z, zx, zy;
  163. float det, a, b, c, e, f, i;
  164. float scaling = 65536.0;
  165. // Get sums for matrix
  166. n = x = y = x2 = y2 = xy = 0;
  167. for (j = 0; j < 5; j++) {
  168. n += 1.0;
  169. x += (float)cal->x[j];
  170. y += (float)cal->y[j];
  171. x2 += (float)(cal->x[j] * cal->x[j]);
  172. y2 += (float)(cal->y[j] * cal->y[j]);
  173. xy += (float)(cal->x[j] * cal->y[j]);
  174. }
  175. // Get determinant of matrix -- check if determinant is too small
  176. det = n * (x2 * y2 - xy * xy) + x * (xy * y - x * y2) + y * (x * xy - y * x2);
  177. if (det < 0.1 && det > -0.1) {
  178. printf("ts_calibrate: determinant is too small -- %f\n", det);
  179. return 0;
  180. }
  181. // Get elements of inverse matrix
  182. a = (x2 * y2 - xy * xy) / det;
  183. b = (xy * y - x * y2) / det;
  184. c = (x * xy - y * x2) / det;
  185. e = (n * y2 - y * y) / det;
  186. f = (x * y - n * xy) / det;
  187. i = (n * x2 - x * x) / det;
  188. // Get sums for x calibration
  189. z = zx = zy = 0;
  190. for (j = 0; j < 5; j++) {
  191. z += (float)cal->xfb[j];
  192. zx += (float)(cal->xfb[j] * cal->x[j]);
  193. zy += (float)(cal->xfb[j] * cal->y[j]);
  194. }
  195. // Now multiply out to get the calibration for framebuffer x coord
  196. cal->a[0] = (int)((a * z + b * zx + c * zy) * (scaling));
  197. cal->a[1] = (int)((b * z + e * zx + f * zy) * (scaling));
  198. cal->a[2] = (int)((c * z + f * zx + i * zy) * (scaling));
  199. printf("%f %f %f\n", (a * z + b * zx + c * zy), (b * z + e * zx + f * zy), (c * z + f * zx + i * zy));
  200. // Get sums for y calibration
  201. z = zx = zy = 0;
  202. for (j = 0; j < 5; j++) {
  203. z += (float)cal->yfb[j];
  204. zx += (float)(cal->yfb[j] * cal->x[j]);
  205. zy += (float)(cal->yfb[j] * cal->y[j]);
  206. }
  207. // Now multiply out to get the calibration for framebuffer y coord
  208. cal->a[3] = (int)((a * z + b * zx + c * zy) * (scaling));
  209. cal->a[4] = (int)((b * z + e * zx + f * zy) * (scaling));
  210. cal->a[5] = (int)((c * z + f * zx + i * zy) * (scaling));
  211. printf("%f %f %f\n", (a * z + b * zx + c * zy), (b * z + e * zx + f * zy), (c * z + f * zx + i * zy));
  212. // If we got here, we're OK, so assign scaling to a[6] and return
  213. cal->a[6] = (int)scaling;
  214. return 1;
  215. }
  216. gboolean __getxy(gpointer user_data)
  217. {
  218. int index;
  219. int x;
  220. int y;
  221. index = ts_s.index;
  222. x = ts_s.x;
  223. y = ts_s.y;
  224. getxy(ts, &cal.x[index], &cal.y[index]);
  225. put_cross(x, y);
  226. cal.xfb[index] = x;
  227. cal.yfb[index] = y;
  228. printf("X = %4d Y = %4d\n", cal.x[index], cal.y[index]);
  229. return FALSE;
  230. }
  231. static void get_sample(struct tsdev *ts, calibration * cal, int index, int x, int y, char *name)
  232. {
  233. ts_s.index = index;
  234. ts_s.x = x;
  235. ts_s.y = y;
  236. put_cross(x, y);
  237. g_timeout_add(10, __getxy, NULL);
  238. }
  239. gboolean ts_calibrate(gpointer user_data);
  240. int gkt_ts_calibrate_open(void)
  241. {
  242. int fb_fd = 0;
  243. char *tsdevice = NULL;
  244. struct fb_fix_screeninfo fix;
  245. struct fb_var_screeninfo var;
  246. if ((tsdevice = getenv("TSLIB_TSDEVICE")) != NULL) {
  247. ts = ts_open(tsdevice, 0);
  248. } else {
  249. ts = ts_open("/dev/input/event0", 0);
  250. }
  251. if (!ts) {
  252. perror("ts_open");
  253. return -11;
  254. }
  255. if (ts_config(ts)) {
  256. perror("ts_config");
  257. return -1;
  258. }
  259. if ((fbdevice = getenv("TSLIB_FBDEVICE")) == NULL)
  260. fbdevice = defaultfbdevice;
  261. fb_fd = open(fbdevice, O_RDWR);
  262. if (fb_fd == -1) {
  263. perror("open fbdevice");
  264. return -1;
  265. }
  266. if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fix) < 0) {
  267. perror("ioctl FBIOGET_FSCREENINFO");
  268. close(fb_fd);
  269. return -1;
  270. }
  271. if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &var) < 0) {
  272. perror("ioctl FBIOGET_VSCREENINFO");
  273. close(fb_fd);
  274. return -1;
  275. }
  276. close(fb_fd);
  277. xres = var.xres;
  278. yres = var.yres;
  279. return 0;
  280. }
  281. int gtk_ts_calibrate_save_conf(void)
  282. {
  283. char cal_buffer[256];
  284. unsigned int i;
  285. char *calfile = NULL;
  286. if (perform_calibration(&cal)) {
  287. printf("Calibration constants: ");
  288. for (i = 0; i < 7; i++)
  289. printf("%d ", cal.a[i]);
  290. printf("\n");
  291. if ((calfile = getenv("TSLIB_CALIBFILE")) != NULL) {
  292. cal_fd = open(calfile, O_CREAT | O_RDWR);
  293. } else {
  294. cal_fd = open("/etc/pointercal", O_CREAT | O_RDWR);
  295. }
  296. sprintf(cal_buffer, "%d %d %d %d %d %d %d",
  297. cal.a[1], cal.a[2], cal.a[0], cal.a[4], cal.a[5], cal.a[3], cal.a[6]);
  298. write(cal_fd, cal_buffer, strlen(cal_buffer) + 1);
  299. close(cal_fd);
  300. i = 0;
  301. } else {
  302. printf("Calibration failed.\n");
  303. i = -1;
  304. }
  305. return 0;
  306. }
  307. static void gtk_ts_calibrate_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
  308. {
  309. gdk_draw_rectangle(da->window, widget->style->black_gc, TRUE,
  310. 0, 0, widget->allocation.width, widget->allocation.height);
  311. }
  312. static gboolean gtk_ts_calibrate_configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer user_data)
  313. {
  314. gc_red = gdk_gc_new(da->window);
  315. GdkColor color;
  316. color.red = 0xFFFF;
  317. color.green = 0;
  318. color.blue = 0;
  319. gdk_gc_set_rgb_fg_color(gc_red, &color);
  320. PangoFontDescription *pfont;
  321. pfont = pango_font_description_from_string("Liberation Sans");
  322. font = gdk_font_from_description(pfont);
  323. return TRUE;
  324. }
  325. gboolean ts_calibrate(gpointer user_data)
  326. {
  327. switch (step) {
  328. case 0:
  329. get_sample(ts, &cal, 0, 50, 50, "Top left");
  330. break;
  331. case 1:
  332. get_sample(ts, &cal, 1, xres - 50, 50, "Top right");
  333. break;
  334. case 2:
  335. get_sample(ts, &cal, 2, xres - 50, yres - 50, "Bot right");
  336. break;
  337. case 3:
  338. get_sample(ts, &cal, 3, 50, yres - 50, "Bot left");
  339. break;
  340. case 4:
  341. get_sample(ts, &cal, 4, xres / 2, yres / 2, "Center");
  342. break;
  343. default:
  344. gtk_ts_calibrate_save_conf();
  345. gtk_main_quit();
  346. }
  347. printf("step = %d\n", step);
  348. step++;
  349. g_timeout_add(10, ts_calibrate, NULL);
  350. return FALSE;
  351. }
  352. int main(int argc, char *argv[])
  353. {
  354. GtkWidget *window;
  355. GtkWidget *fixed;
  356. if (getenv("DISPLAY") == NULL)
  357. setenv("DISPLAY", DISPLAY, 1);
  358. if (getenv("TSLIB_TSDEVICE") == NULL)
  359. setenv("TSLIB_TSDEVICE", TSLIB_TSDEVICE, 1);
  360. if (getenv("TSLIB_CALIBFILE") == NULL)
  361. setenv("TSLIB_CALIBFILE", TSLIB_TSDEVICE, 1);
  362. if (!g_thread_supported())
  363. g_thread_init(NULL);
  364. setlocale(LC_ALL, "");
  365. bindtextdomain("gtk_ts_calibrate", ".");
  366. textdomain("gtk_ts_calibrate");
  367. gtk_set_locale();
  368. g_type_init();
  369. gtk_init(&argc, &argv);
  370. gkt_ts_calibrate_open();
  371. window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  372. gtk_widget_set_uposition(GTK_WIDGET(window), 0, 0);
  373. gtk_widget_set_usize(GTK_WIDGET(window), xres, yres);
  374. fixed = gtk_fixed_new();
  375. gtk_container_add(GTK_CONTAINER(window), fixed);
  376. da = gtk_drawing_area_new();
  377. gtk_widget_set_usize(GTK_WIDGET(da), xres, yres);
  378. gtk_fixed_put(GTK_FIXED(fixed), da, 0, 0);
  379. g_signal_connect((gpointer) da, "configure_event", G_CALLBACK(gtk_ts_calibrate_configure_event), NULL);
  380. g_signal_connect(G_OBJECT(da), "expose_event", GTK_SIGNAL_FUNC(gtk_ts_calibrate_expose_event), 0);
  381. gtk_widget_show_all(window);
  382. step = 0;
  383. printf("xres = %d, yres = %d\n", xres, yres);
  384. g_timeout_add(1000, ts_calibrate, NULL);
  385. gtk_main();
  386. return 0;
  387. }

阅读(3042) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

Helianthus_lu2012-12-12 19:55:59

学长真牛!向你学习