📄 touchscreen.c
字号:
/* -*- linux-c -*- *//* * Driver for USB Touchscreen (Microtech - IBM SurePos 4820) * * Copyright (C) 2000 Wojciech Woziwodzki * Written by Radoslaw Garbacz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Originally based upon scanner.c (David E. Nelson). * * History * * 0.1 06/05/2000 (RGA) * Development work was begun. * * 0.2 09/05/2000 (RGA) * Documentation about MicroTouch controller was arrived. * */#include <linux/version.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <asm/uaccess.h>#include <linux/init.h>#include <linux/malloc.h>#include <linux/delay.h>#include <linux/ioctl.h>#include <linux/config.h>#include <linux/interrupt.h>#include <linux/ptrace.h>#include <linux/poll.h>#include <linux/in.h>#include <linux/malloc.h>#include <linux/tty.h>#include <linux/errno.h>#include <linux/string.h> /* used in new tty drivers */#include <linux/signal.h> /* used in new tty drivers */#include <asm/system.h>#include <asm/bitops.h>#include <asm/termios.h>#include <linux/if.h>#ifdef CONFIG_KERNELD#include <linux/kerneld.h>#endif//#define DEBUG#define TSCRN_IOCTL//#define __TEST_NO_DEVICE__#define TSCRN_MAX_MNR 16 /* We're allocated 16 minors */#define TSCRN_BASE_MNR 48 /* USB Scanners start at minor 48 */#define IS_EP_BULK(ep) ((ep).bmAttributes == USB_ENDPOINT_XFER_BULK ? 1 : 0)#define IS_EP_BULK_IN(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)#define IS_EP_INTR(ep) ((ep).bmAttributes == USB_ENDPOINT_XFER_INT ? 1 : 0)#define IS_EP_INTR_IN(ep) (IS_EP_INTR(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)#define IS_EP_INTR_OUT(ep) (IS_EP_INTR(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)#define USB_TSCRN_MINOR(X) MINOR((X)->i_rdev) - TSCRN_BASE_MNR#ifdef DEBUG#define TSCRN_DEBUG(X) X#else#define TSCRN_DEBUG(X)#endif#include <linux/usb.h>#include <linux/input.h>#include "touchscreen.h"struct tscrn_usb_data{ struct usb_device *dev; wait_queue_head_t wait; struct urb irq; struct urb ctrlin; struct urb ctrlout; devrequest *setup_packet; // for control transfers unsigned int ifnum; // Interface number of the USB device kdev_t minor; // TouchScreen minor - used in disconnect() unsigned char data[TSCRN_USB_RAPORT_SIZE_DATA]; // Data buffer X-Y, and button int nLoopCounter; // number of data packet last received +1 char isopen; // Not zero if the device is open char present; // Not zero if device is present unsigned char *obuf, *ibuf; // transfer buffers unsigned char *pToRead,*pToWrite;// pointers to toRead cell of buffer and to toWrite one char intr_ep; // Endpoint assignments struct input_dev input_dev; // to work as an input device driver};static struct tscrn_usb_data *p_tscrn_table[TSCRN_MAX_MNR] = { NULL, /* ... */};MODULE_AUTHOR("Radoslaw Garbacz, garbacz@posexperts.com.pl");MODULE_DESCRIPTION("USB touchscreen driver");static __s32 vendor=-1, product=-1;MODULE_PARM(vendor, "i");MODULE_PARM_DESC(vendor, "User specified USB idVendor");MODULE_PARM(product, "i");MODULE_PARM_DESC(product, "User specified USB idProduct");/* Forward declarations */static struct usb_driver touchscreen_driver;/* Procedures *//** * Runs after ctrl requests. */static void ctrl_touchscreen(struct urb *urb){ struct tscrn_usb_data *tscrn = urb->context; dbg("ctrl_touchscreen(%d): status=%d", tscrn->minor, urb->status); if (waitqueue_active(&tscrn->wait)) wake_up_interruptible(&tscrn->wait); return;};/** * Runs on new data received from device * The buffer should keep the last state of device, thus the buffer overflow * can occurre * The client can't read data when pToRead == pToWrite */static void irq_touchscreen(struct urb *urb){ /* * data raports... */ struct tscrn_usb_data *tscrn = urb->context; struct tscrn_usb_data_report *data = (struct tscrn_usb_data_report *)tscrn->data; if (urb->status) return; //return when driver was clesed if(!tscrn->isopen) return; // increase loop counter // !!! Unfortunately the data was lost to seldom !!! //if((int)GET_LOOP(data) != tscrn->nLoopCounter) // warn("warn:Lost data new loop %d previous loop %d",(int)GET_LOOP(data),(int)tscrn->nLoopCounter); input_report_key(&tscrn->input_dev, BTN_LEFT, IS_TOUCHED(data)); input_report_abs(&tscrn->input_dev, ABS_X, GET_XC(data)); input_report_abs(&tscrn->input_dev, ABS_Y, GET_YC(data)); tscrn->nLoopCounter = (GET_LOOP(data))+1; // store data to buffer memcpy(tscrn->pToWrite,data,TSCRN_USB_RAPORT_SIZE_DATA); // next data to next cell if(tscrn->pToRead == NULL) tscrn->pToRead = tscrn->pToWrite; tscrn->pToWrite += TSCRN_USB_RAPORT_SIZE_DATA; if(tscrn->pToWrite >= tscrn->obuf+OBUF_SIZE) tscrn->pToWrite = tscrn->obuf; if (waitqueue_active(&tscrn->wait)) wake_up_interruptible(&tscrn->wait); //dbg("irq_touchscreen(): GET_Data 0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x status=%d", (int)data[0],(int)data[1],(int)data[2],(int)data[3],(int)data[4],(int)data[5],(int)data[6],(int)data[7],(int)data[8],(int)data[9],(int)data[10], tscrn->ctrlout.status); return;}static int open_touchscreen(struct inode * inode, struct file * file){ struct tscrn_usb_data *tscrn; struct usb_device *dev; kdev_t minor;#ifdef __TEST_NO_DEVICE__ return -ENODEV;#endif minor = USB_TSCRN_MINOR(inode); dbg("open_touchscreen: tscrn_minor:%d", minor); if (!p_tscrn_table[minor]) { err("open_touchscreen(%d): invalid tscrn_minor", minor); return -ENODEV; } tscrn = p_tscrn_table[minor]; dev = tscrn->dev; if (!dev) { return -ENODEV; } if (!tscrn->present) { return -ENODEV; } if (tscrn->isopen) { return -EBUSY; } //clear up the data buffer memset(tscrn->obuf, 0x0, OBUF_SIZE); tscrn->pToRead = NULL; tscrn->pToWrite = tscrn->obuf; tscrn->isopen = 1; file->private_data = tscrn; /* Used by the read and write metheds */ MOD_INC_USE_COUNT; return 0;}static int close_touchscreen(struct inode * inode, struct file * file){ struct tscrn_usb_data *tscrn; kdev_t minor;#ifdef __TEST_NO_DEVICE__ return -ENODEV;#endif minor = USB_TSCRN_MINOR (inode); dbg("close_touchscreen: tscrn_minor:%d", minor); if (!p_tscrn_table[minor]) { err("close_touchscreen(%d): invalid tscrn_minor", minor); return -ENODEV; } tscrn = p_tscrn_table[minor]; tscrn->isopen = 0; file->private_data = NULL; MOD_DEC_USE_COUNT; return 0;}static ssize_t read_touchscreen(struct file * file, char * buffer, size_t count, loff_t *ppos){ struct tscrn_usb_data *tscrn; struct usb_device *dev; ssize_t bytes_read; /* Overall count of bytes_read */ ssize_t ret; kdev_t minor; int partial; /* Number of bytes successfully read */ int this_read; /* Max number of bytes to read */ //int result; unsigned char *buf, *pToRead;#ifdef __TEST_NO_DEVICE__ return -ENODEV;#endif tscrn = file->private_data; minor = tscrn->minor; buf = tscrn->obuf; pToRead = tscrn->pToRead; dev = tscrn->dev; bytes_read = 0; ret = 0; if((tscrn->pToWrite == tscrn->pToRead) || (tscrn->pToRead == NULL)) return 0; // no new data if (signal_pending(current)) { ret = -EINTR; return ret; } this_read = (count >= TSCRN_USB_RAPORT_SIZE_DATA) ? TSCRN_USB_RAPORT_SIZE_DATA: count; partial = this_read; //dbg("read stats(%d): result:%d this_read:%d partial:%d", minor, result, this_read, partial); dbg("read count=%d", count); if (partial) { /* Data returned */ if (copy_to_user(buffer, tscrn->pToRead, this_read)) { ret = -EFAULT; return ret;//break; } count -= partial; bytes_read += partial; buffer += partial; tscrn->pToRead += partial; if(tscrn->pToRead >= tscrn->obuf+OBUF_SIZE) tscrn->pToRead = tscrn->obuf; } dbg("read ended bytes_read(%d)", bytes_read);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -