RK3399 android10 移植SiS-USB触摸驱动

news2024/11/23 22:35:58

一,SiS USB触摸简介

SiS USB 触摸屏通常是一种外接式触摸屏设备,通过 USB 接口连接到计算机或其他设备上。这种触摸屏设备可以提供触摸输入功能,用户可以通过手指或触控笔在屏幕上进行操作,实现点击、拖动、缩放等操作。
SiS USB 触摸屏通常需要安装相应的驱动程序才能正常工作,在计算机系统中被识别为触摸输入设备。驱动程序会将触摸屏输入转换为计算机可识别的信号,从而实现触摸屏在操作系统中的正常使用。


二,驱动文件配置

1. hid_sis内核模块驱动文件

在这里插入图片描述

hid-sis_ctrl.c :在Linux内核中,HID设备驱动程序负责与各种输入设备(如键盘、鼠标、游戏手柄等)进行通信和管理。包含与特定类型的HID设备通信的代码实现,包括设备的初始化、数据传输、事件处理等功能。这个文件可能会被编译到内核中,以便在系统启动时加载并与相应的HID设备进行交互。

/*
 *  Character device driver for SIS multitouch panels control
 *
 *  Copyright (c) 2023 SIS, Ltd.
 *
 */

/*
 * 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.
 */

#include <linux/hid.h>
#include <linux/module.h>
#include <linux/usb.h>
#include "usbhid/usbhid.h"
#include <linux/init.h>

//update FW
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>				//copy_from_user() & copy_to_user()

#include "hid-ids.h"
#include "hid-sis_ctrl.h"

static int sis_char_devs_count = 1;        		/* device count */
static int sis_char_major = 0;
static struct cdev sis_char_cdev;
static struct class *sis_char_class = NULL;

static struct hid_device *hid_dev_backup = NULL;	//backup address
static struct urb *backup_urb = NULL;

#define	REPORTID_21_LEN	64
#define	REPORTID_25_LEN	320
#define	REPORTID_29_LEN	576
#define	REPORTID_2D_LEN	832

#ifdef CONFIG_DEBUG_HID_SIS_UPDATE_FW
	#define DBG_FW(fmt, arg...)	printk( fmt, ##arg )
	void sis_dbg_dump_array( u8 *ptr, u32 size)
	{
		u32 i;
		for (i=0; i<size; i++)  
		{
			DBG_FW ("%02X ", ptr[i]);
			if( ((i+1)&0xF) == 0)
				DBG_FW ("\n");
		}
		if( size & 0xF)
			DBG_FW ("\n");
	}
#else
	#define DBG_FW(...)
	#define sis_dbg_dump_array(...)
#endif	// CONFIG_DEBUG_HID_SIS_UPDATE_FW


int sis_cdev_open(struct inode *inode, struct file *filp)	//20120306 Yuger ioctl for tool
{
	struct usbhid_device *usbhid; 

	DBG_FW( "%s\n" , __FUNCTION__ );
	//20110511, Yuger, kill current urb by method of usbhid_stop
	if ( !hid_dev_backup )
	{
		printk( KERN_INFO "(stop)hid_dev_backup is not initialized yet" );
		return -1;
	}

	usbhid = hid_dev_backup->driver_data;

	printk( KERN_INFO "sys_sis_HID_stop\n" );

	//printk( KERN_INFO "hid_dev_backup->vendor, hid_dev_backup->product = %x %x\n", hid_dev_backup->vendor, hid_dev_backup->product );

	//20110602, Yuger, fix bug: not contact usb cause kernel panic
	if( !usbhid )
	{
		printk( KERN_INFO "(stop)usbhid is not initialized yet" );
		return -1;
	}
	else if ( !usbhid->urbin )
	{
		printk( KERN_INFO "(stop)usbhid->urbin is not initialized yet" );
		return -1;
	}
	else if (hid_dev_backup->vendor == USB_VENDOR_ID_SIS_TOUCH)
	{
		usb_fill_int_urb(backup_urb, usbhid->urbin->dev, usbhid->urbin->pipe,
			usbhid->urbin->transfer_buffer, usbhid->urbin->transfer_buffer_length,
			usbhid->urbin->complete, usbhid->urbin->context, usbhid->urbin->interval);

                clear_bit( HID_STARTED, &usbhid->iofl );
                set_bit( HID_DISCONNECTED, &usbhid->iofl );

                usb_kill_urb( usbhid->urbin );
                usb_free_urb( usbhid->urbin );
                usbhid->urbin = NULL;
		return 0;
	}
    else	
	{
		printk (KERN_INFO "This is not a SiS device");
		return -801;
	}
}

int sis_cdev_release(struct inode *inode, struct file *filp)
{
	//20110505, Yuger, rebuild the urb which is at the same urb address, then re-submit it

	int ret;
	struct usbhid_device *usbhid;
	unsigned long flags;
	
	DBG_FW( "%s: " , __FUNCTION__ );
	
	if ( !hid_dev_backup )
	{
		printk( KERN_INFO "(stop)hid_dev_backup is not initialized yet" );
		return -1;
	}

	usbhid = hid_dev_backup->driver_data;

	printk( KERN_INFO "sys_sis_HID_start" );

	if( !usbhid )
	{
		printk( KERN_INFO "(start)usbhid is not initialized yet" );
		return -1;
	}

	if( !backup_urb )
	{
		printk( KERN_INFO "(start)backup_urb is not initialized yet" );
		return -1;
	}

	clear_bit( HID_DISCONNECTED, &usbhid->iofl );
	usbhid->urbin = usb_alloc_urb( 0, GFP_KERNEL );

	if( !backup_urb->interval )
	{
		printk( KERN_INFO "(start)backup_urb->interval does not exist" );
		return -1;
	}

	usb_fill_int_urb(usbhid->urbin, backup_urb->dev, backup_urb->pipe, 
		backup_urb->transfer_buffer, backup_urb->transfer_buffer_length, 
		backup_urb->complete, backup_urb->context, backup_urb->interval);
	usbhid->urbin->transfer_dma = usbhid->inbuf_dma;
	usbhid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	set_bit( HID_STARTED, &usbhid->iofl );

	//method at hid_start_in
	spin_lock_irqsave( &usbhid->lock, flags );		
	ret = usb_submit_urb( usbhid->urbin, GFP_ATOMIC );
	spin_unlock_irqrestore( &usbhid->lock, flags );
	//yy

	DBG_FW( "ret = %d", ret );

	return ret;
}

ssize_t sis_cdev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
	int timeout = 0;
	u8 *rep_data = NULL;
	u8 *temp_data = NULL;
	u16 size = 0;
	long rep_ret;
	struct usb_interface *intf = to_usb_interface(hid_dev_backup->dev.parent);
	struct usb_device *dev = interface_to_usbdev(intf);
#if IS_ENABLED(CONFIG_HID_SIS95XX_SIS98XX)
	u16 reportID = 0;
#else
	int actual_length = 0;
#endif

	DBG_FW( "%s\n", __FUNCTION__ );
	
	temp_data = kzalloc(count, GFP_KERNEL);
	
	if(!temp_data) {
        printk( KERN_INFO "kzalloc temp_data fail\n");
        return (-12);
    }
        
    if ( copy_from_user( temp_data, (void*)buf, count) ) {
		printk( KERN_INFO "copy_from_user(temp_data) fail\n" );
		//free allocated data
		kfree( temp_data );
		temp_data = NULL;
		return -19;
	}

#if IS_ENABLED(CONFIG_HID_SIS95XX_SIS98XX)
	switch (temp_data[0]) {
	case 0x21:
		size = (((u16)(temp_data[REPORTID_21_LEN] & 0xff)) << 24)
			+ (((u16)(temp_data[REPORTID_21_LEN + 1] & 0xff)) << 16)
			+ (((u16)(temp_data[REPORTID_21_LEN + 2] & 0xff)) << 8)
			+ (u16)(temp_data[REPORTID_21_LEN + 3] & 0xff);
		timeout = (((int)(temp_data[REPORTID_21_LEN + 4] & 0xff)) << 24)
			+ (((int)(temp_data[REPORTID_21_LEN + 5] & 0xff)) << 16)
			+ (((int)(temp_data[REPORTID_21_LEN + 6 ] & 0xff)) << 8)
			+ (int)(temp_data[REPORTID_21_LEN + 7] & 0xff);
		reportID = 0x0321;
		DBG_FW("%s Report ID : 0x21\n" , __FUNCTION__);
		break;
	case 0x25:
		size = (((u16)(temp_data[REPORTID_25_LEN] & 0xff)) << 24)
			+ (((u16)(temp_data[REPORTID_25_LEN + 1] & 0xff)) << 16)
			+ (((u16)(temp_data[REPORTID_25_LEN + 2] & 0xff)) << 8)
			+ (u16)(temp_data[REPORTID_25_LEN + 3] & 0xff);
		timeout = (((int)(temp_data[REPORTID_25_LEN + 4] & 0xff)) << 24)
			+ (((int)(temp_data[REPORTID_25_LEN + 5] & 0xff)) << 16)
			+ (((int)(temp_data[REPORTID_25_LEN + 6 ] & 0xff)) << 8)
			+ (int)(temp_data[REPORTID_25_LEN + 7] & 0xff);
		reportID = 0x0325;
		DBG_FW("%s Report ID : 0x25\n" , __FUNCTION__);
		break;
	case 0x29:
		size = (((u16)(temp_data[REPORTID_29_LEN] & 0xff)) << 24)
			+ (((u16)(temp_data[REPORTID_29_LEN + 1] & 0xff)) << 16)
			+ (((u16)(temp_data[REPORTID_29_LEN + 2] & 0xff)) << 8)
			+ (u16)(temp_data[REPORTID_29_LEN + 3] & 0xff);
		timeout = (((int)(temp_data[REPORTID_29_LEN + 4] & 0xff)) << 24)
			+ (((int)(temp_data[REPORTID_29_LEN + 5] & 0xff)) << 16)
			+ (((int)(temp_data[REPORTID_29_LEN + 6 ] & 0xff)) << 8)
			+ (int)(temp_data[REPORTID_29_LEN + 7] & 0xff);
		reportID = 0x0329;
		DBG_FW("%s Report ID : 0x29\n" , __FUNCTION__);
		break;
	case 0x2d:
		size = (((u16)(temp_data[REPORTID_2D_LEN] & 0xff)) << 24)
			+ (((u16)(temp_data[REPORTID_2D_LEN + 1] & 0xff)) << 16)
			+ (((u16)(temp_data[REPORTID_2D_LEN + 2] & 0xff)) << 8)
			+ (u16)(temp_data[REPORTID_2D_LEN + 3] & 0xff);
		timeout = (((int)(temp_data[REPORTID_2D_LEN + 4] & 0xff)) << 24)
			+ (((int)(temp_data[REPORTID_2D_LEN + 5] & 0xff)) << 16)
			+ (((int)(temp_data[REPORTID_2D_LEN + 6 ] & 0xff)) << 8)
			+ (int)(temp_data[REPORTID_2D_LEN + 7] & 0xff);
		reportID = 0x032d;
		DBG_FW( "%s Report ID : 0x2d\n" , __FUNCTION__ );
		break;
	default:
		break;
	}
#else
	size = (((u16)(temp_data[64] & 0xff)) << 24) + (((u16)(temp_data[65] & 0xff)) << 16) + 
		(((u16)(temp_data[66] & 0xff)) << 8) + (u16)(temp_data[67] & 0xff);
	timeout = (((int)(temp_data[68] & 0xff)) << 24) + (((int)(temp_data[69] & 0xff)) << 16) + 
		(((int)(temp_data[70] & 0xff)) << 8) + (int)(temp_data[71] & 0xff);
	DBG_FW("%s Report ID : 0x0a\n" , __FUNCTION__);	
#endif

	kfree(temp_data);
    temp_data = NULL;

	DBG_FW("timeout = %d, size %d\n", timeout, size);

#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
	if (!access_ok(VERIFY_WRITE, buf, size)) {
#else
	if (!access_ok(buf, size)) {
#endif
		printk(KERN_INFO "cannot access user space memory\n");
		return -11;
	}

	rep_data = kzalloc(size, GFP_KERNEL);
    if (!rep_data) {
        printk(KERN_INFO "kzalloc rep_data fail\n");
        return -12;
    }

	if (copy_from_user(rep_data, (void*)buf, size)) {
		printk(KERN_INFO "copy_to_user fail(rep_data)\n");
		//free allocated data
		kfree(rep_data);
		rep_data = NULL;
		return -19;
	}

#if IS_ENABLED(CONFIG_HID_SIS95XX_SIS98XX)
	rep_ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 
		0x01, (USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE), 
		reportID, 0, rep_data, size, timeout);

	DBG_FW("%s: rep_data = ", __FUNCTION__);
	sis_dbg_dump_array(rep_data, 8);

	if (copy_to_user((void*)buf, rep_data, rep_ret)) {
		printk(KERN_INFO "copy_to_user fail(buf)\n");
		//free allocated data
		kfree(rep_data);
		rep_data = NULL;
		return -19;
	}
#else
	rep_ret = usb_interrupt_msg(dev, backup_urb->pipe,
		rep_data, size, &actual_length, timeout);

	DBG_FW("%s: rep_data = ", __FUNCTION__);
	sis_dbg_dump_array(rep_data, 8);

	if (rep_ret == 0) {
		if (copy_to_user((void*)buf, rep_data, actual_length)) {
			printk(KERN_INFO "copy_to_user fail(buf)\n");
			//free allocated data
			kfree(rep_data);
			rep_data = NULL;
			return -19;
		}
	}
#endif

	//free allocated data
	kfree(rep_data);
	rep_data = NULL;
	DBG_FW("%s: rep_ret = %ld\n", __FUNCTION__, rep_ret);
	return rep_ret;
}

ssize_t sis_cdev_write(struct file *file, const char __user *buf, size_t count, loff_t *f_pos)
{
	int timeout = 0;
	u8 *rep_data = NULL;
	u8 *temp_data = NULL;
	u16 size = 0;
	long rep_ret;
	struct usb_interface *intf = to_usb_interface(hid_dev_backup->dev.parent);
	struct usb_device *dev = interface_to_usbdev(intf);
#if IS_ENABLED(CONFIG_HID_SIS95XX_SIS98XX)
	u16 reportID = 0;
#else
	int actual_length = 0;
	struct usbhid_device *usbhid = hid_dev_backup->driver_data;
#endif
	
	DBG_FW( "%s\n", __FUNCTION__ );
	
	temp_data = kzalloc(count, GFP_KERNEL);
	
	if(!temp_data)
    {
        printk( KERN_INFO "kzalloc temp_data fail\n");
        return (-12);
    }
        
    if ( copy_from_user( temp_data, (void*)buf, count) ) 
	{
		printk( KERN_INFO "copy_from_user(temp_data) fail\n" );
		//free allocated data
		kfree( temp_data );
		temp_data = NULL;
		return -19;
	}

#if IS_ENABLED(CONFIG_HID_SIS95XX_SIS98XX)
	switch (temp_data[0]) {
	case 0x21:
		size = (((u16)(temp_data[REPORTID_21_LEN] & 0xff)) << 24)
			+ (((u16)(temp_data[REPORTID_21_LEN + 1] & 0xff)) << 16)
			+ (((u16)(temp_data[REPORTID_21_LEN + 2] & 0xff)) << 8)
			+ (u16)(temp_data[REPORTID_21_LEN + 3] & 0xff);
		timeout = (((int)(temp_data[REPORTID_21_LEN + 4] & 0xff)) << 24)
			+ (((int)(temp_data[REPORTID_21_LEN + 5] & 0xff)) << 16)
			+ (((int)(temp_data[REPORTID_21_LEN + 6 ] & 0xff)) << 8)
			+ (int)(temp_data[REPORTID_21_LEN + 7] & 0xff);
		reportID = 0x0321;
		DBG_FW("%s Report ID : 0x21\n" , __FUNCTION__);
		break;
	case 0x25:
		size = (((u16)(temp_data[REPORTID_25_LEN] & 0xff)) << 24)
			+ (((u16)(temp_data[REPORTID_25_LEN + 1] & 0xff)) << 16)
			+ (((u16)(temp_data[REPORTID_25_LEN + 2] & 0xff)) << 8)
			+ (u16)(temp_data[REPORTID_25_LEN + 3] & 0xff);
		timeout = (((int)(temp_data[REPORTID_25_LEN + 4] & 0xff)) << 24)
			+ (((int)(temp_data[REPORTID_25_LEN + 5] & 0xff)) << 16)
			+ (((int)(temp_data[REPORTID_25_LEN + 6 ] & 0xff)) << 8)
			+ (int)(temp_data[REPORTID_25_LEN + 7] & 0xff);
		reportID = 0x0325;
		DBG_FW("%s Report ID : 0x25\n" , __FUNCTION__);
		break;
	case 0x29:
		size = (((u16)(temp_data[REPORTID_29_LEN] & 0xff)) << 24)
			+ (((u16)(temp_data[REPORTID_29_LEN + 1] & 0xff)) << 16)
			+ (((u16)(temp_data[REPORTID_29_LEN + 2] & 0xff)) << 8)
			+ (u16)(temp_data[REPORTID_29_LEN + 3] & 0xff);
		timeout = (((int)(temp_data[REPORTID_29_LEN + 4] & 0xff)) << 24)
			+ (((int)(temp_data[REPORTID_29_LEN + 5] & 0xff)) << 16)
			+ (((int)(temp_data[REPORTID_29_LEN + 6 ] & 0xff)) << 8)
			+ (int)(temp_data[REPORTID_29_LEN + 7] & 0xff);
		reportID = 0x0329;
		DBG_FW("%s Report ID : 0x29\n" , __FUNCTION__);
		break;
	case 0x2d:
		size = (((u16)(temp_data[REPORTID_2D_LEN] & 0xff)) << 24)
			+ (((u16)(temp_data[REPORTID_2D_LEN + 1] & 0xff)) << 16)
			+ (((u16)(temp_data[REPORTID_2D_LEN + 2] & 0xff)) << 8)
			+ (u16)(temp_data[REPORTID_2D_LEN + 3] & 0xff);
		timeout = (((int)(temp_data[REPORTID_2D_LEN + 4] & 0xff)) << 24)
			+ (((int)(temp_data[REPORTID_2D_LEN + 5] & 0xff)) << 16)
			+ (((int)(temp_data[REPORTID_2D_LEN + 6 ] & 0xff)) << 8)
			+ (int)(temp_data[REPORTID_2D_LEN + 7] & 0xff);
		reportID = 0x032d;
		DBG_FW("%s Report ID : 0x2d\n" , __FUNCTION__);
		break;
	default:
		break;
	}
#else
	size = (((u16)(temp_data[64] & 0xff)) << 24) + (((u16)(temp_data[65] & 0xff)) << 16) + 
		(((u16)(temp_data[66] & 0xff)) << 8) + (u16)(temp_data[67] & 0xff);
	timeout = (((int)(temp_data[68] & 0xff)) << 24) + (((int)(temp_data[69] & 0xff)) << 16) + 
		(((int)(temp_data[70] & 0xff)) << 8) + (int)(temp_data[71] & 0xff);
	DBG_FW("%s Report ID : 0x09\n" , __FUNCTION__);
#endif

	DBG_FW("timeout = %d, size %d\n", timeout, size);
	
	kfree(temp_data);
    temp_data = NULL;

#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
	if (!access_ok(VERIFY_WRITE, buf, size)) {
#else
	if (!access_ok(buf, size)) {
#endif
		printk(KERN_INFO "cannot access user space memory\n");
		return -11;
	}

	rep_data = kzalloc(size, GFP_KERNEL);
	if (!rep_data) {
        printk(KERN_INFO "kzalloc rep_data fail\n");
        return -12;
    }

	if (copy_from_user(rep_data, (void*)buf, size)) {
		printk(KERN_INFO "copy_to_user fail(rep_data)\n");
		//free allocated data
		kfree(rep_data);
		rep_data = NULL;
		return -19;
	}

#if IS_ENABLED(CONFIG_HID_SIS95XX_SIS98XX)
	rep_ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 
		0x09, (USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE), 
		reportID, 0, rep_data, size, timeout);

	DBG_FW("%s: rep_data = ", __FUNCTION__);
	sis_dbg_dump_array(rep_data, 8);

	if (copy_to_user((void*)buf, rep_data, rep_ret)) {
		printk(KERN_INFO "copy_to_user fail(buf)\n");
		//free allocated data
		kfree(rep_data);
		rep_data = NULL;
		return -19;
	}
#else
	rep_ret = usb_interrupt_msg(dev, usbhid->urbout->pipe,
		rep_data, size, &actual_length, timeout);

	DBG_FW("%s: rep_data = ", __FUNCTION__);
	sis_dbg_dump_array(rep_data, size);
	
	if (rep_ret == 0) {
		if (copy_to_user((void*)buf, rep_data, actual_length)) {
			printk(KERN_INFO "copy_to_user fail(buf)\n");
			//free allocated data
			kfree(rep_data);
			rep_data = NULL;
			return -19;
		}
	}
#endif		

	DBG_FW("%s: rep_ret = %ld\n", __FUNCTION__, rep_ret);
	//free allocated data
	kfree(rep_data);
	rep_data = NULL;
	DBG_FW("End of sys_sis_HID_IO\n");
	return rep_ret;
}


//for ioctl
static const struct file_operations sis_cdev_fops = {
	.owner	= THIS_MODULE,
	.read	= sis_cdev_read,
	.write	= sis_cdev_write,
	.open	= sis_cdev_open,
	.release= sis_cdev_release,
};

//for ioctl
int sis_setup_chardev(struct hid_device *hdev)
{
	
	dev_t dev = MKDEV(sis_char_major, 0);
	int alloc_ret = 0;
	int cdev_err = 0;
	int input_err = 0;
	struct device *class_dev = NULL;
	void *ptr_err;
	
	printk("sis_setup_chardev.\n");

	hid_dev_backup = hdev;
	
	backup_urb = usb_alloc_urb(0, GFP_KERNEL); //0721test
	if (!backup_urb) {
		dev_err(&hdev->dev, "cannot allocate backup_urb\n");
		return -ENOMEM;
	}

	// dynamic allocate driver handle
#ifdef SIS_BRIDGE_ENABLED
		alloc_ret = alloc_chrdev_region(&dev, 0, sis_char_devs_count, SIS_BRIDGE_DEVICE_NAME);
#else
		alloc_ret = alloc_chrdev_region(&dev, 0, sis_char_devs_count, SIS_DEVICE_NAME);
#endif		
	if (alloc_ret)
		goto error;
		
	sis_char_major  = MAJOR(dev);
	cdev_init(&sis_char_cdev, &sis_cdev_fops);
	sis_char_cdev.owner = THIS_MODULE;
	cdev_err = cdev_add(&sis_char_cdev, MKDEV(sis_char_major, 0), sis_char_devs_count);
	if (cdev_err) 
		goto error;

#ifdef SIS_BRIDGE_ENABLED
		printk(KERN_INFO "%s driver(major %d) installed.\n", SIS_BRIDGE_DEVICE_NAME, sis_char_major);
#else
		printk(KERN_INFO "%s driver(major %d) installed.\n", SIS_DEVICE_NAME, sis_char_major);
#endif

	// register class
#ifdef SIS_BRIDGE_ENABLED
#if LINUX_VERSION_CODE < KERNEL_VERSION(6,4,0)
		sis_char_class = class_create(THIS_MODULE, SIS_BRIDGE_DEVICE_NAME);
#else
		sis_char_class = class_create(SIS_BRIDGE_DEVICE_NAME);
#endif //LINUX_VERSION_CODE < KERNEL_VERSION(6,4,0)
#else
#if LINUX_VERSION_CODE < KERNEL_VERSION(6,4,0)
		sis_char_class = class_create(THIS_MODULE, SIS_DEVICE_NAME);
#else
		sis_char_class = class_create(SIS_DEVICE_NAME);
#endif //LINUX_VERSION_CODE < KERNEL_VERSION(6,4,0)
#endif //SIS_BRIDGE_ENABLED

	if (IS_ERR(ptr_err = sis_char_class))
		goto err2;

#ifdef SIS_BRIDGE_ENABLED
		class_dev = device_create(sis_char_class, NULL, MKDEV(sis_char_major, 0), NULL, SIS_BRIDGE_DEVICE_NAME);
#else
		class_dev = device_create(sis_char_class, NULL, MKDEV(sis_char_major, 0), NULL, SIS_DEVICE_NAME);
#endif

	if (IS_ERR(ptr_err = class_dev)) 
		goto err;
	
	return 0;
error:
	if (cdev_err == 0)
		cdev_del(&sis_char_cdev);
	if (alloc_ret == 0)
		unregister_chrdev_region(MKDEV(sis_char_major, 0), sis_char_devs_count);
	if (input_err != 0)
		printk("sis_ts_bak error!\n");
err:
	device_destroy(sis_char_class, MKDEV(sis_char_major, 0));
err2:
	class_destroy(sis_char_class);
	return -1;
}
EXPORT_SYMBOL(sis_setup_chardev);

void sis_deinit_chardev(struct hid_device *hdev)
{
	//for ioctl
	dev_t dev;
	printk(KERN_INFO "sis_deinit\n");

	dev = MKDEV(sis_char_major, 0);
	cdev_del(&sis_char_cdev);
	unregister_chrdev_region(dev, sis_char_devs_count);
	device_destroy(sis_char_class, MKDEV(sis_char_major, 0));
	class_destroy(sis_char_class);
	usb_kill_urb(backup_urb);
	usb_free_urb(backup_urb);
	backup_urb = NULL;
	hid_dev_backup = NULL;
	
}
EXPORT_SYMBOL(sis_deinit_chardev);

MODULE_DESCRIPTION("SiS Touchscreen Control Driver");
MODULE_LICENSE("GPL");

hid-sis_ctrl.h :包含了与 HID 设备通信和控制相关的宏定义、结构体定义、函数声明等内容。这些内容通常用于描述 HID 设备的特性、命令格式、数据结构等,以便在驱动程序中使用。

#ifndef __HID_SIS_CTRL_H__
#define __HID_SIS_CTRL_H__

#include <linux/version.h>	//LINUX_VERSION_CODE & KERNEL_VERSION

#if LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0)
#include <asm/uaccess.h>	//copy_from_user() & copy_to_user()
#else
#include <linux/uaccess.h>	//copy_from_user() & copy_to_user()
#endif

/* ID-table */
#define USB_VENDOR_ID_SIS_TOUCH	0x0457
#define USB_DEVICE_ID_SIS_TOUCH 0x1905

/* Device node name */
#define HID_SIS95XX			// ON/OFF: SiS hydra(6596)/SiS aegis(817)
//#define DEBUG_HID_SIS_UPDATE_FW	// ON/OFF
//#define SIS_BRIDGE_ENABLED		// ON/OFF

#if IS_ENABLED(CONFIG_HID_SIS95XX_SIS98XX)			//6596
#define SIS_DEVICE_NAME "sis_hydra_hid_touch_device"
#define SIS_BRIDGE_DEVICE_NAME "sis_hydra_hid_bridge_touch_device"
#else					//817
#define SIS_DEVICE_NAME "sis_aegis_hid_touch_device"
#define SIS_BRIDGE_DEVICE_NAME "sis_aegis_hid_bridge_touch_device"
#endif

/* Report id length */
#define	REPORTID_21_LEN	64
#define	REPORTID_25_LEN	320
#define	REPORTID_29_LEN	576
#define	REPORTID_2D_LEN	832

#define CTRL 0
#define ENDP_01 1
#define ENDP_02 2
#define DIR_IN 0x1

int sis_cdev_open(struct inode *inode, struct file *filp);
int sis_cdev_release(struct inode *inode, struct file *filp);
ssize_t sis_cdev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos);
ssize_t sis_cdev_write( struct file *file, const char __user *buf, size_t count, loff_t *f_pos );
int sis_setup_chardev(struct hid_device *hdev);
void sis_deinit_chardev(struct hid_device *hdev);


#endif	// __HID_SIS_CTRL_H__

2. 修改专用驱动程序列表

kernel version is >= 4.16

a.hid-multitouch.c修改

引用文件,类定义,启动功能,完成功能,添加设备列表

diff --git a/kernel/drivers/hid/hid-multitouch.c b/kernel/drivers/hid/hid-multitouch.c
index 19dfd8acd0..66399569ce 100644
--- a/kernel/drivers/hid/hid-multitouch.c
+++ b/kernel/drivers/hid/hid-multitouch.c
@@ -43,7 +43,9 @@
#include <linux/jiffies.h>
#include <linux/string.h>
#include <linux/timer.h>
-
+/* SiSdrv Start */
+#include "hid-sis_ctrl.h"
+/* SiSdrv End */
MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
@@ -207,6 +209,9 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app);
#define MT_CLS_VTL                0x0110
#define MT_CLS_GOOGLE                0x0111
#define MT_CLS_RAZER_BLADE_STEALTH        0x0112
+/* SiSdrv Start */
+#define MT_CLS_SIS              0x0457
+/* SiSdrv End */
#define MT_DEFAULT_MAXCONTACT    10
#define MT_MAX_MAXCONTACT    250
@@ -357,6 +362,12 @@ static const struct mt_class mt_classes[] = {
             MT_QUIRK_CONTACT_CNT_ACCURATE |
             MT_QUIRK_WIN8_PTP_BUTTONS,
     },
+    /* SiSdrv Start */
+    { .name = MT_CLS_SIS,
+        .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
+            MT_QUIRK_CONTACT_CNT_ACCURATE
+    },
+    /* SiSdrv End */
     { }
};
@@ -1716,6 +1727,18 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
     if (mtclass->quirks & MT_QUIRK_FIX_CONST_CONTACT_ID)
         mt_fix_const_fields(hdev, HID_DG_CONTACTID);
+    /* SiSdrv Start */
+    if (hdev->vendor == USB_VENDOR_ID_SIS_TOUCH) {
+        hdev->quirks |= HID_QUIRK_NOGET;
+        printk(KERN_INFO "sis:sis-probe: quirk = %x\n", hdev->quirks);
+    #ifdef CONFIG_HID_SIS_CTRL
+        ret = sis_setup_chardev(hdev);
+        if (ret)
+            printk( KERN_INFO "sis_setup_chardev fail\n");
+    #endif  //CONFIG_HID_SIS_CTRL
+    }
+    /* SiSdrv End */
+
     ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
     if (ret)
         return ret;
@@ -1757,6 +1780,13 @@ static void mt_remove(struct hid_device *hdev)
     del_timer_sync(&td->release_timer);
     sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
+
+    /* SiSdrv Start */
+    if (hdev->vendor == USB_VENDOR_ID_SIS_TOUCH) {
+        sis_deinit_chardev(hdev);
+    }
+    /* SiSdrv End */
+
     hid_hw_stop(hdev);
}
@@ -2103,6 +2133,12 @@ static const struct hid_device_id mt_devices[] = {
         HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_GOOGLE,
             USB_DEVICE_ID_GOOGLE_TOUCH_ROSE) },
+    /* SiSdrv Start */
+    { .driver_data = MT_CLS_SIS,
+        HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_SIS_TOUCH,
+            HID_ANY_ID) },
+    /* SiSdrv End */
+
     /* Generic MT device */
     { HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) },

b.hid-quirks.c修改

将usb触摸vid添加特殊设备列表中

diff --git a/kernel/drivers/hid/hid-quirks.c b/kernel/drivers/hid/hid-quirks.c
index b9529bed4d..c913bfd889 100644
--- a/kernel/drivers/hid/hid-quirks.c
+++ b/kernel/drivers/hid/hid-quirks.c
@@ -720,6 +720,11 @@ static const struct hid_device_id hid_have_special_driver[] = {
#if IS_ENABLED(CONFIG_HID_ZYDACRON)
     { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) },
#endif
+/* SiSdrv Start */
+#if IS_ENABLED(CONFIG_HID_SIS92XX) || IS_ENABLED(CONFIG_HID_SIS95XX_SIS98XX)
+    { HID_USB_DEVICE(0x0457, HID_ANY_ID) },
+#endif
+/* SiSdrv End */
     { }
};

3. 移植hid_sis驱动

a. 将驱动(hid-sis_ctrl.c,hid-sis_ctrl.h)拷贝到下面的文件夹:

kernel/drivers/hid/

b. 在 Makefile 中添加hid-sis_ctrl设备

kernel/drivers/hid/Makefile:

#/  SiSdrv Start    /
obj-$(CONFIG_HID_SIS_CTRL)  += hid-sis_ctrl.o
#/  SiSdrv End  /

c. 在 Kconfig 中添加hid-sis_ctrl

kernel/drivers/hid/Kconfig:


#/  SiSdrv Start    /   
config HID_SIS_CTRL
    tristate "SiS Touch Device Controller"
    depends on HID_MULTITOUCH
    default y
    help
    Support for SiS Touch devices update FW.


menu "SiS touchscreen series"
choice
    depends on USB_HID
    depends on HID_SIS_CTRL
    prompt "SiS controller select"


config HID_SIS95XX_SIS98XX
    depends on HID_SIS_CTRL
    tristate "SiS 95xx and 98xx series Touch Device"
    help
    Support for SiS Touch devices that are fully compliant with HID standard.
    
config HID_SIS92XX
    depends on HID_SIS_CTRL
    tristate "SiS 92xx series Touch Device"
    help
    Support for SiS Touch devices that are fully compliant with HID standard.


endchoice


config DEBUG_HID_SIS_UPDATE_FW
    bool "SiS Touch device update firmware support debug message enable"
    depends on HID_SIS_CTRL
    default n
    help
      Say Y here if you want to enable debug message of
      firmware updating for SiS Touch
          devices.

endmenu
#/  SiSdrv End  /

d. 内核中加载驱动

kernel/arch/arm64/configs/rockchip_defconfig:

CONFIG_HID_SIS95XX_SIS98XX=m

三,系统配置

1.授予sis节点权限

diff --git a/system/core/rootdir/ueventd.rc b/system/core/rootdir/ueventd.rc
index 451f5adf33..28c3d83eb7 100644
--- a/system/core/rootdir/ueventd.rc
+++ b/system/core/rootdir/ueventd.rc
@@ -40,6 +40,10 @@ subsystem sound
/dev/pmsg0                0222   root       log
+#sis device SiS95xx
+/dev/sis_hydra_hid_touch_device 0666 root root
+/dev/sis_hydra_hid_bridge_touch_device 0666 root root
+
# kms driver for drm based gpu
/dev/dri/*                0666   root       graphics

2. idc文件拷贝到 系统system/usr/idc/目录

rc文件中添加:

PRODUCT_COPY_FILES += \
    device/rockchip/rk3399/Vendor_0457_Product_0819.idc:system/usr/idc/Vendor_0457_Product_0819.idc
Vendor_0457_Product_0819.idc:

# Basic Parameters
touch.deviceType = touchScreen
touch.orientationAware = 1
device.internal = 1

四,调试

1.dmesg日志

dmesg | grep sis //检查sis驱动程序加载

在这里插入图片描述

2.设备节点

ls -l /dev/sis*

在这里插入图片描述

cat /proc/bus/input/devices

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1532333.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

腾讯云GPU云服务器简介_GPU服务器购买指南_GPU云服务器操作

腾讯云GPU服务器是提供GPU算力的弹性计算服务&#xff0c;腾讯云GPU服务器具有超强的并行计算能力&#xff0c;可用于深度学习训练、科学计算、图形图像处理、视频编解码等场景&#xff0c;腾讯云百科txybk.com整理腾讯云GPU服务器租用价格表、GPU实例优势、GPU解决方案、GPU软…

学点儿Java_Day7_在实体类当中IDEA无法进行单元测试(@Test没有启动按钮)

在敲代码体会继承和访问修饰符的时候忽然遇到了单元测试不管用的情况&#xff0c;表现为没有启动按钮   经过一番折腾&#xff0c;发现我的测试是在具有构造函数的实体类Person当中进行的&#xff0c;当我把所有的构造函数删除后&#xff0c;启动按钮又出来了&#xff0c;加…

Pycharm实用快捷键

Pycharm实用快捷键 1.代码/函数提示2.查找同一变量位置3.添加类型提示4.一键代码规范化5.任意位置切换到下一行6.快速运行7.多行快速注释8.展开/折叠代码块9.全局搜索10.变量用过的地方11.快速包围12.跳到文件成员13.在项目内查找14.快速选中15.导入优化16.扩展 / 缩小选中17.复…

【SQL】1141. 查询近30天活跃用户数(常规写法;date_add())

前述 mysql中date_add()函数的使用 题目描述 leetcode题目&#xff1a;1141. 查询近30天活跃用户数 Code 写法一 select activity_date as day, count(distinct user_id) as active_users from Activity where activity_date > 2019-06-27 and activity_date < 2019…

北斗短报文+4G应急广播系统:全面预警灾害信息 构建安全美好乡村

建设社会主义新农村是确保小康社会宏伟目标如期实现的必然要求&#xff0c;是构建和谐社会的重要内容。针对现代农业发展的要求&#xff0c;通过完善专业化监测预报技术&#xff0c;提高精细化的灾害监测预警能力&#xff0c;建设广覆盖的预警信息发布网络&#xff0c;建设有效…

Linux快速入门,上手开发 01.学习路线

少时曾许凌云志&#xff0c;当取世间第一流 再见少年拉满弓&#xff0c;不惧岁月不飓风 —— 24.3.20 1.Linux的发展历史 2.VM虚拟机的Linux初体验 3.图形化页面设置系统——快速上手 4.命令行操作——向专业前进 5.核心操作命令——必知必会&#xff08;管理企业级权限/定位b…

【web算法】列车车厢重排问题

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

【Unity】Plastic云同步总是password error

【背景】 Plastic是Unity的项目版本控制功能&#xff0c;可以方便在多个地点同步项目进度。原本用得挺爽的&#xff0c;结果今天遇到糟心事&#xff0c;明明Hub也正常登着&#xff0c;可Plastic的一个update的dll就是不停反复运行并报Password invalid。 【问题分析】 听说I…

常见六大WEB安全问题

一、XSS跨站脚本攻击 1.Cross-Site Scripting&#xff08;跨站脚本攻击&#xff09;简称 XSS&#xff08;因为缩写和 CSS重叠&#xff0c;所以只能叫 XSS&#xff09;&#xff0c;是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本&#xff0c;使之在用户的浏览器上运行…

流畅的 Python 第二版(GPT 重译)(十)

第十八章&#xff1a;with、match 和 else 块 上下文管理器可能几乎与子例程本身一样重要。我们只是初步了解了它们。[…] Basic 有一个 with 语句&#xff0c;在许多语言中都有 with 语句。但它们的功能不同&#xff0c;它们都只是做一些非常浅显的事情&#xff0c;它们可以避…

关于v1.29.2 版本的Maxwell存在于mysql8.0后版本部分源码字符集处理确实问题

1. 先去GitHub下载源码.zip文件2. 找到上图中的这个 StringColumnDef.java 做如下修改 eg: 3.然后是pom文件部分的修改&#xff1a; 将这个org.jgroups的版本降低到0.5.2.Final 然后再去注释掉一个类的引用&#xff1a; MaxwellHA.java 3.1 还可以不用降低这个org.jgro…

大模型学习笔记七:LLM应用

文章目录 一、维护生产级别的LLM应用,需要做的事二、符合需求的LLM App维护平台三、LangFuse1)替换OpenAI客户端(把跟OpenAI交互记录到LangFuse)1.1)几个基本概念2)通过LangChain的回调函数触发记录(上面用的原生OpenAI接口,下面是调用LangChain的接口)3)构建一个实际…

3.20刷题--备赛ing

距离十五届蓝桥杯还有23天&#xff0c;奶奶的拼了。备赛ing 今天刷题 5道 有序分数递归方法 如何1/2 2/4都是相同的结果&#xff0c;但是需要的是1/2&#xff0c;如何解决这个问题呢&#xff0c;可以看出分子和分母约分最简的时候&#xff0c;他们的gcd1&#xff0c;所以求…

Socket类

2.2 Socket类 Socket 类&#xff1a;该类实现客户端套接字&#xff0c;套接字指的是两台设备之间通讯的端点。 构造方法 public Socket(String host, int port) :创建套接字对象并将其连接到指定主机上的指定端口号。如果指定的host是null &#xff0c;则相当于指定地址为回送…

【HTML】悄悄分享两个好玩的html代码

最近整理U盘资源&#xff0c;本来打算清理掉一些“无用”的文件&#xff0c;结果翻到了之前保存的一个保存着好玩代码的文件夹&#xff0c;默默点开了命名为"大佬做的html.html”这个文件&#xff08;谁还不是一个中二少年呢&#xff09;话不多说&#xff0c;上代码&#…

0301taildir-source报错-flume-大数据

1 基础环境简介 linux系统&#xff1a;centos&#xff0c;前置安装&#xff1a;jdk、hadoop、zookeeper、kafka&#xff0c;版本如下 软件版本描述centos7linux系统发行版jdk1.8java开发工具集hadoop2.10.0大数据生态基础组件zookeeper3.5.7分布式应用程序协调服务kafka3.0分…

成都正信晟锦:亲戚借了钱不认账怎么办是现金

在人际交往中&#xff0c;金钱往来往往是敏感而复杂的议题&#xff0c;尤其是与亲戚间的借贷。若遭遇亲戚借了钱却不认账的尴尬局面&#xff0c;我们该如何妥善处理呢? 沟通始终是解决问题的第一步。尝试与该亲戚进行坦诚的对话&#xff0c;了解不认账的原因。可能是对方遇到了…

基于springboot的车辆充电桩管理平台

技术&#xff1a;springbootmysqlvue 一、背景 科学技术日新月异的如今&#xff0c;计算机在生活各个领域都占有重要的作用&#xff0c;尤其在信息管理方面&#xff0c;在这样的大背景下&#xff0c;学习计算机知识不仅仅是为了掌握一种技能&#xff0c;更重要的是能够让它真正…

【深度学习】手动实现RNN循环神经网络

&#x1f33b;个人主页&#xff1a;相洋同学 &#x1f947;学习在于行动、总结和坚持&#xff0c;共勉&#xff01; 目录 01 回顾 02 RNN神经网络原理 03 RNN神经网络实现 04 RNN神经网络实验 RNN的特别结构使得RNN具备了短期记忆能力&#xff0c;使其能够学习部分语义信息…

php 对接IronSource海外广告平台收益接口Reporting API

今天对接的是IronSource广告reporting api接口&#xff0c;拉取广告收益回来自己做统计。记录分享给大家 首先是文档地址,进入到IronSource后台就能看到文档地址以及参数&#xff1a; 文档地址&#xff1a;https://developers.is.com/ironsource-mobile/air/reporting/ 在这里插…