linux 串口触摸屏调试记录

ゝ一纸荒年。 2022-07-26 04:23 479阅读 0赞

这几天在调试串口触摸屏,网上找了下似乎说的都不大清楚,这里记录下.

实现方法网上说有好几种,这里是将串口作为一个serio总线设备,利用linux内核提供serio总线驱动,通过设置对应的串口,调用serport提供的函数将串口当做serio总线设备,在驱动里面需要按照serio总线设备驱动的框架来实现,在内核源码drivers/input/touchscreen下提供了两个例子,touchright.c和touchit123.c,可以参考这两个例子编写驱动.我的驱动是在网上抄的,源码如下

  1. /*
  2. *Egalax serial touchscreen driver
  3. *
  4. * Copyright (c) 2004-2016
  5. *
  6. * Based on Touchright driver (drivers/input/touchscreen/touchit213.c)
  7. *
  8. * Zolt??n B??sz??rm??nyi <zboszor@xxxxx>
  9. */
  10. /*
  11. * This program is free software; you can redistribute it and/or modify it
  12. * under the terms of the GNU General Public License version 2 as published
  13. * by the Free Software Foundation.
  14. */
  15. #include <linux/errno.h>
  16. #include <linux/kernel.h>
  17. #include <linux/module.h>
  18. #include <linux/slab.h>
  19. #include <linux/input.h>
  20. #include <linux/serio.h>
  21. #include <linux/init.h>
  22. #define DRIVER_DESC "EETI Egalax serial touchscreen driver"
  23. MODULE_AUTHOR("Zolt??n B??sz??rm??nyi <zboszor@xxxxx>");
  24. MODULE_DESCRIPTION(DRIVER_DESC);
  25. MODULE_LICENSE("GPL");
  26. /*
  27. * Definitions & global arrays.
  28. */
  29. #define SERIO_EGALAX 0x3f
  30. #define EGALAX_FORMAT_MAX_LENGTH 6
  31. #define EGALAX_RESPONSE_BEGIN_BYTE 0x80
  32. #define EGALAX_FORMAT_PRESSURE_BIT 0x40
  33. #define EGALAX_FORMAT_TOUCH_BIT 0x01
  34. #define EGALAX_FORMAT_RESOLUTION 0x06
  35. #define EGALAX_MIN_XC 0
  36. #define EGALAX_MAX_XC 0x4000
  37. #define EGALAX_MIN_YC 0
  38. #define EGALAX_MAX_YC 0x4000
  39. #define EGALAX_GET_XC(data, resbits, shift) ((((data[1] & (resbits)) << 7) | (data[2] & 0x7f)) << shift)
  40. #define EGALAX_GET_YC(data, resbits, shift) ((((data[3] & (resbits)) << 7) | (data[4] & 0x7f)) << shift)
  41. #define EGALAX_GET_TOUCHED(data) (EGALAX_FORMAT_TOUCH_BIT & data[0])
  42. /*
  43. * Per-touchscreen data.
  44. */
  45. struct egalax {
  46. struct input_dev *dev;
  47. struct serio *serio;
  48. int idx;
  49. int bytes;
  50. int resbits;
  51. int shift;
  52. unsigned char data[EGALAX_FORMAT_MAX_LENGTH];
  53. char phys[32];
  54. };
  55. static void egalax_process_data(struct egalax *pegalax)
  56. {
  57. struct input_dev *dev = pegalax->dev;
  58. if (++pegalax->idx == pegalax->bytes) {
  59. input_report_abs(dev, ABS_X, EGALAX_GET_XC(pegalax->data, pegalax->resbits, pegalax->shift));
  60. input_report_abs(dev, ABS_Y, EGALAX_GET_YC(pegalax->data, pegalax->resbits, pegalax->shift));
  61. //input_report_key(dev, BTN_TOUCH, EGALAX_GET_TOUCHED(pegalax->data));
  62. input_report_abs(dev, ABS_PRESSURE, EGALAX_GET_TOUCHED(pegalax->data));
  63. input_sync(dev);
  64. pegalax->idx = 0;
  65. }
  66. }
  67. static irqreturn_t egalax_interrupt(struct serio *serio,
  68. unsigned char data, unsigned int flags)
  69. {
  70. struct egalax *pegalax = serio_get_drvdata(serio);
  71. pegalax->data[pegalax->idx] = data;
  72. if (EGALAX_RESPONSE_BEGIN_BYTE & pegalax->data[0]) {
  73. pegalax->bytes = (EGALAX_FORMAT_PRESSURE_BIT & pegalax->data[0] ? 6 : 5);
  74. switch ((EGALAX_FORMAT_RESOLUTION & pegalax->data[0]) >> 1) {
  75. case 0:
  76. pegalax->resbits = 0x0f;
  77. pegalax->shift = 3;
  78. break;
  79. case 1:
  80. pegalax->resbits = 0x1f;
  81. pegalax->shift = 2;
  82. break;
  83. case 2:
  84. pegalax->resbits = 0x3f;
  85. pegalax->shift = 1;
  86. break;
  87. default:
  88. pegalax->resbits = 0x7f;
  89. pegalax->shift = 0;
  90. break;
  91. }
  92. egalax_process_data(pegalax);
  93. }
  94. else
  95. dev_dbg(&serio->dev, "unknown/unsynchronized data: %x\n",
  96. pegalax->data[0]);
  97. return IRQ_HANDLED;
  98. }
  99. static void egalax_disconnect(struct serio *serio)
  100. {
  101. struct egalax *pegalax = serio_get_drvdata(serio);
  102. input_get_device(pegalax->dev);
  103. input_unregister_device(pegalax->dev);
  104. serio_close(serio);
  105. serio_set_drvdata(serio, NULL);
  106. input_put_device(pegalax->dev);
  107. kfree(pegalax);
  108. }
  109. /*
  110. * egalax_connect() is the routine that is called when someone adds a
  111. * new serio device that supports egalax protocol and registers it as
  112. * an input device. This is usually accomplished using inputattach.
  113. */
  114. static int egalax_connect(struct serio *serio, struct serio_driver *drv)
  115. {
  116. struct egalax *pegalax;
  117. struct input_dev *input_dev;
  118. int err;
  119. pegalax = kzalloc(sizeof(struct egalax), GFP_KERNEL);
  120. input_dev = input_allocate_device();
  121. if (!pegalax || !input_dev) {
  122. err = -ENOMEM;
  123. goto fail1;
  124. }
  125. pegalax->serio = serio;
  126. pegalax->dev = input_dev;
  127. snprintf(pegalax->phys, sizeof(pegalax->phys),
  128. "%s/input1", serio->phys);
  129. input_dev->name = "EETI eGalaxTouch Serial TouchScreen";
  130. input_dev->phys = pegalax->phys;
  131. input_dev->id.bustype = BUS_RS232;
  132. input_dev->id.vendor = SERIO_EGALAX;
  133. input_dev->id.product = 0;
  134. input_dev->id.version = 0x0001;
  135. input_dev->dev.parent = &serio->dev;
  136. input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
  137. //input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
  138. input_set_abs_params(pegalax->dev, ABS_X,
  139. EGALAX_MIN_XC, EGALAX_MAX_XC, 0, 0);
  140. input_set_abs_params(pegalax->dev, ABS_Y,
  141. EGALAX_MIN_YC, EGALAX_MAX_YC, 0, 0);
  142. input_set_abs_params(pegalax->dev, ABS_PRESSURE, 0, 1, 0, 0);
  143. serio_set_drvdata(serio, pegalax);
  144. err = serio_open(serio, drv);
  145. if (err)
  146. goto fail2;
  147. err = input_register_device(pegalax->dev);
  148. if (err)
  149. goto fail3;
  150. return 0;
  151. fail3: serio_close(serio);
  152. fail2: serio_set_drvdata(serio, NULL);
  153. fail1: input_free_device(input_dev);
  154. kfree(pegalax);
  155. return err;
  156. }
  157. /*
  158. * The serio driver structure.
  159. */
  160. static struct serio_device_id egalax_serio_ids[] = {
  161. {
  162. .type = SERIO_RS232,
  163. .proto = SERIO_EGALAX,
  164. .id = SERIO_ANY,
  165. .extra = SERIO_ANY,
  166. },
  167. { 0 }
  168. };
  169. MODULE_DEVICE_TABLE(serio, egalax_serio_ids);
  170. static struct serio_driver egalax_drv = {
  171. .driver = {
  172. .name = "egalax",
  173. },
  174. .description = DRIVER_DESC,
  175. .id_table = egalax_serio_ids,
  176. .interrupt = egalax_interrupt,
  177. .connect = egalax_connect,
  178. .disconnect = egalax_disconnect,
  179. };
  180. /*
  181. * The functions for inserting/removing us as a module.
  182. */
  183. static int __init egalax_init(void)
  184. {
  185. return serio_register_driver(&egalax_drv);
  186. }
  187. static void __exit egalax_exit(void)
  188. {
  189. serio_unregister_driver(&egalax_drv);
  190. }
  191. module_init(egalax_init);
  192. module_exit(egalax_exit);

只是修改了最后一点,其中egalax_serio_ids中的几个参数在应用程序中需要用到,加上驱动编译内核更新后,此时这个驱动是没有起作用的,需要通过应用程序将串口与之绑定,后才能正常工作.

应用程序如下,这个代码网上也有

  1. /*************************************
  2. NAME:seriotouch.c
  3. *************************************/
  4. #include <stdio.h>
  5. #include <unistd.h>
  6. #include <stdlib.h>
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include <sys/ioctl.h>
  10. #include <fcntl.h>
  11. #include <linux/fs.h>
  12. #include <errno.h>
  13. #include <string.h>
  14. #include <linux/fb.h>
  15. #include <malloc.h>
  16. #include <sys/mman.h>
  17. #include <termio.h>
  18. #include <linux/serio.h>
  19. #define SERIO_ANY 0xff
  20. #define SERIO_EGALAX 0x3f
  21. int main(int argc, char* argv[])
  22. {
  23. int dev,ret;
  24. char comdev[20];
  25. int ldisc;
  26. unsigned long type;
  27. struct termios option;
  28. int fd = -1;
  29. if(argc != 2)
  30. {
  31. printf("-----------------------------------------\n");
  32. printf("\nUsage: %s [serial device(1-5)]\n", argv[0]);
  33. printf("Example: %s 5 n", argv[0]);
  34. printf("-----------------------------------------\n");
  35. return 0;
  36. }
  37. dev = strtol(argv[1],NULL,10);
  38. sprintf(comdev,"/dev/ttyAMA%d",dev);
  39. fd = open(comdev,O_RDWR|O_NONBLOCK|O_NOCTTY);
  40. if (fd < 0) {
  41. perror(comdev);
  42. exit(1);
  43. }
  44. tcgetattr(fd, &option);
  45. option.c_iflag = IGNPAR | IGNBRK;
  46. option.c_cflag = HUPCL | CS8 | CREAD | CLOCAL | B9600;
  47. option.c_cc[VMIN] = 1;
  48. option.c_cc[VTIME] = 0;
  49. cfsetispeed(&option,B9600);
  50. cfsetospeed(&option,B9600);
  51. ret = tcsetattr(fd, TCSANOW, &option);
  52. if(ret < 0) {
  53. perror("TCSANOW");
  54. exit(1);
  55. }
  56. ldisc = N_MOUSE;
  57. ret = ioctl(fd,TIOCSETD,&ldisc);
  58. if(ret) {
  59. perror("TIOCSETD");
  60. }
  61. type = SERIO_EGALAX | (SERIO_ANY << 8) | (SERIO_ANY << 16);
  62. ret = ioctl(fd,SPIOCSTYPE, &type);
  63. if(ret) {
  64. perror("SPIOCSTYPE");
  65. }
  66. read(fd,NULL,0);
  67. //close(fd);
  68. return 0;
  69. }

需要注意的是,应用程序最后这个read一定要执行,不然驱动里不会进行连接.

编译生成可执行文件seriotouch

应用程序配制完串口后需要与之前的驱动连接,看设置spiocstype的设置,需要保证这里的几个参数与驱动进行对应。

系统启动后执行seriotouch 5 &

后面这个5对应的是串口号,执行这个后会看到驱动里的connect执行了,同时会生成一个input节点,如下图

SouthEast

此时将tslib里的tsdevice修改为这个,进行校准后,就可以正常使用了

发表评论

表情:
评论列表 (有 0 条评论,479人围观)

还没有评论,来说两句吧...

相关阅读

    相关 串口调试

    命令行下: 查看所有串口   ls dev/tty\ 查看串口信息                stty -F  dev/ttyTHS1 -a 配置串口信息