GSLX680触摸屏驱动移植
- GSLX680 触摸屏
触摸屏按照触摸屏的工作原理和传输信息的介质,可以分为四种,它们分别为电阻式、电容感应式、红外线式以及表面声波式。GSLX680 为电容式触摸屏,挂接在I2C总线上,通过I2C总线来传输触摸屏数据。该芯片的连接方式如所示及与T3板子的I2C连接如所示。
- SylixOS 电容式触摸屏分析
SylixOS下将电容式触摸屏封装成一个字符设备,应用程序只需通过read函数读取触摸屏设备,即可获取到填充有触摸坐标信息的mouse_event_notify 结构体。
- 电容屏初始化
{ struct file_operations fileOper; INT iDrvNum; lib_memset(&fileOper, 0, sizeof(struct file_operations)); fileOper.owner = THIS_MODULE; fileOper.fo_create = __touchOpen; fileOper.fo_open = __touchOpen; fileOper.fo_close = __touchClose; fileOper.fo_read = __touchRead; fileOper.fo_lstat = __touchLstat; fileOper.fo_ioctl = __touchIoctl; iDrvNum = iosDrvInstallEx2(&fileOper, LW_DRV_TYPE_NEW_1); DRIVER_LICENSE(iDrvNum, "Dual BSD/GPL->Ver 1.0"); DRIVER_AUTHOR(iDrvNum, "Xu.Guizhou"); DRIVER_DESCRIPTION(iDrvNum, "touch driver.") return (iDrvNum); } |
创建触摸屏设备的逻辑如下:
iError = iosDevAddEx(&pTouchDev->TOUCH_devHdr, pcName, iDrvNum, DT_CHR); if (iError) { _ErrorHandle(ERROR_SYSTEM_LOW_MEMORY); __SHEAP_FREE(pTouchDev); printk(KERN_ERR "touchDevCreate(): failed to create touch device %s!\n", pcName); return (PX_ERROR); } |
- 电容触摸屏事件上抛线程
触摸事件提交分为上下半程处理,下半程线程会阻塞等待触摸中断事件产生。当产生了触摸中断时,会调用__touchHandleEvents 获取坐标值,并将获取到的坐标值填入mouse_event_notify 结构体,最终通过消息队列传送到触摸屏定义的 read 函数中。用户调用触摸驱动的 read 函数时,即可获取到触摸事件信息。
static PVOID __touchThread (PVOID pvArg) { INT iEventNum; PTOUCH_DEV pTouchDev = (PTOUCH_DEV)pvArg; while (!pTouchDev->TOUCH_bQuit) { API_SemaphoreBPend(pTouchDev->TOUCH_hSignal, LW_OPTION_WAIT_INFINITE); if (pTouchDev->TOUCH_bQuit) { break; } iEventNum = __touchHandleEvents(pTouchDev); if (iEventNum == PX_ERROR) { printk(KERN_ERR "touch: handle touch event fail!\n"); } else if (iEventNum > 0) { SEL_WAKE_UP_ALL(&pTouchDev->TOUCH_selList, SELREAD); } } return (LW_NULL); } |
3. 电容触摸屏触摸中断产生
手指触摸时中断处理逻辑如下:
static irqreturn_t __touchIsr (PTOUCH_DEV pTouchDev, ULONG ulVector) { irqreturn_t irqreturn; irqreturn = API_GpioSvrIrq(pTouchDev->TOUCH_data.T_uiIrq); if (irqreturn == LW_IRQ_HANDLED) { API_GpioClearIrq(pTouchDev->TOUCH_data.T_uiIrq); API_SemaphoreBPost(pTouchDev->TOUCH_hSignal); } return (irqreturn); } |
- 移植GSLX680 触摸屏
将Linux下的驱动代码移植到SylixOS下,需要将硬件初始化动作及获取触摸屏坐标值。
- 硬件初始化动作放在设备的open动作下,包括创建I2C子设备,GPIO中断申请,芯片初始化:
static INT __touchHwInit (PTOUCH_DEV pTouchDev, PCHAR pcName) { INT iError; pTouchDev->TOUCH_pI2cDevice = API_I2cDeviceCreate(pTouchDev->TOUCH_data.T_pcBusName, pcName, pTouchDev->TOUCH_data.T_usAddr, 0); if (pTouchDev->TOUCH_pI2cDevice == LW_NULL) { printk(KERN_ERR "__touchHwInit(): failed to create i2c device %s, slave addr 0x%x!\n", pTouchDev->TOUCH_data.T_pcBusName, pTouchDev->TOUCH_data.T_usAddr); goto __error_handle; } /* * 设置触摸屏中断 */
iError = API_GpioRequestOne(pTouchDev->TOUCH_data.T_uiIrq, pTouchDev->TOUCH_data.T_uiIrqCfg, "touch_eint"); if (iError != ERROR_NONE) { printk(KERN_ERR "__touchHwInit(): failed to request irq gpio!\n"); goto __error_handle; } iError = API_GpioSetupIrq(pTouchDev->TOUCH_data.T_uiIrq, pTouchDev->TOUCH_data.T_uiIrqCfg, 1); if (iError == PX_ERROR) { printk(KERN_ERR "__touchHwInit(): failed to setup gpio irq!\n"); goto __error_handle; } pTouchDev->TOUCH_ulVector = (ULONG)iError; printk("__touchHwInit %d\n\r",iError); /* * 申请触摸屏复位管脚 */ iError = API_GpioRequestOne(pTouchDev->TOUCH_data.T_uiReset, pTouchDev->TOUCH_data.T_uiRstVal | LW_GPIOF_DIR_OUT, "touch_reset"); if (iError != ERROR_NONE) { printk(KERN_ERR "__touchHwInit(): failed to request rst gpio!\n"); goto __error_handle; } __touchReset(pTouchDev); /* Reset Touch Screen */ if (pTouchDev->pDrvFunc->init) { /* Init Touch Screen */ pTouchDev->pDrvFunc->init(pTouchDev); } return (ERROR_NONE); __error_handle: API_GpioFree(pTouchDev->TOUCH_data.T_uiIrq); API_GpioFree(pTouchDev->TOUCH_data.T_uiReset);
if (pTouchDev->TOUCH_pI2cDevice) { API_I2cDeviceDelete(pTouchDev->TOUCH_pI2cDevice); pTouchDev->TOUCH_pI2cDevice = LW_NULL; } return (PX_ERROR); } |
- 获取坐标事件函数,gslX680GetEvent 将获取的坐标上报:
static TOUCH_DRV_FUNC _G_Gsl680DrvFunc = { .getevent = gslX680GetEvent, .init = gslX680Init, .deinit = NULL, .reset = NULL, }; INT gslX680GetEvent (PTOUCH_DEV pTouchDev, mouse_event_notify events[]) { INT iError; UCHAR ucBuffer[36]; u8 read_buf[4] = {0};
iError = gsl_ts_read(pTouchDev, 0x80, ucBuffer, GSL_CONTACT_SIZE); if (iError == PX_ERROR) { printk(KERN_WARNING "touch: get touch point error!\n"); return (PX_ERROR); }
if(ucBuffer[0] == 0xff) { return (iError); }
iError = gsl_ts_read( pTouchDev, 0xbc, read_buf, sizeof(read_buf));
if (iError == PX_ERROR) { printk(KERN_WARNING "touch: read 0xbc failed!\n"); return (iError); }
if (read_buf[3] == 0 && read_buf[2] == 0 && read_buf[1] == 0 && read_buf[0] == 0){ iError = process_gslX680_data(pTouchDev,events,ucBuffer); } else { reset_chip(pTouchDev); startup_chip(pTouchDev); iError = 0; }
return (iError); } |
《SylixOS应用程序开发手册》