本篇记录在友善之臂 mini2440 平台上挂载I2C接口触摸屏的驱动开发过程。

内核版本linux-2.6.32.2,
平台是ARM9 S3C2440+I2C接口的触摸屏

如上篇 Linux的I2C驱动体系结构讲述
http://www.lupaworld.com/273398/viewspace-204237.html

要挂载新的I2C设备,需要实现3部分:

1) 适配器的硬件驱动:
内核中已经实现mini2440,i2c适配器驱动,可以在如下目录i2c-s3c2410.c中看到相关代码
linux-2.6.32.2/drivers/i2c/busses/i2c-s3c2410.c

2) I2C 设配器的algorithm
同样在inux-2.6.32.2/drivers/i2c/busses/i2c-s3c2410.c文件中实现。

以上两部分无须做任何更改

3) I2C设备驱动,可以以linux-2.6.32.2/drivers/input/touchscreen/migor_ts.c为例,分析如下:
//-------------------------------------------------------------------//
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <linux/i2c.h>
#include <linux/timer.h>
#include <linux/delay.h>

/*resolution definion according to touch screen */
#define MIN_X_COORDINATE    0
#define MAX_X_COORDINATE    1024   
#define MIN_Y_COORDINATE    0
#define MAX_Y_COORDINATE    768

/* touch screen data structure */
struct i2c_ts_priv {
    struct i2c_client *client;
    struct input_dev *input;
    struct delayed_work work;
    int irq;
};

static void i2c_ts_poscheck(struct work_struct *work)
{
    struct i2c_ts_priv *priv = container_of(work, struct i2c_ts_priv, work.work);
    /* buffer for storing data */
    char buf[6];
    int number;
    int xpos, ypos;

memset(buf, 0, sizeof(buf));

/* Now do Page Read */
    if (i2c_master_recv(priv->client, buf,6) != 6) {
        dev_err(&priv->client->dev, "Unable to read i2c page\n");
        goto out;
    }
       
    /* convert coordinate */
    number = buf[0]&0x07;
    xpos = ((buf[3] << 8) | buf[2]);
    ypos = ((buf[5] << 8) | buf[4]);
   
     /* report input event */
    if ((number != 0) && (xpos != 0) && (ypos != 0)) {
        input_report_key(priv->input, BTN_TOUCH, 1);
        input_report_abs(priv->input, ABS_X, xpos);
        input_report_abs(priv->input, ABS_Y, ypos);
        input_sync(priv->input);
    } else if (number == 0) {
        input_report_key(priv->input, BTN_TOUCH, 0);
        input_sync(priv->input);
    }

out:
    enable_irq(priv->irq);
}

/* read finger numbers and coordinate and report input event */
static irqreturn_t i2c_ts_isr(int irq, void *dev_id)
{
    struct i2c_ts_priv *priv = dev_id;
      
    /* disable irq */
    disable_irq_nosync(irq);
    schedule_delayed_work(&priv->work, HZ/100);   
    return IRQ_HANDLED;
}

static int i2c_ts_open(struct input_dev *dev)
{
    return 0;
}

static void i2c_ts_close(struct input_dev *dev)
{

}

static int i2c_ts_probe(struct i2c_client *client,
              const struct i2c_device_id *idp)
{
    struct i2c_ts_priv *priv;
    struct input_dev *input;
    int error;
    char buf[2];

priv = kzalloc(sizeof(*priv), GFP_KERNEL);
    if (!priv) {
        dev_err(&client->dev, "failed to allocate driver data\n");
        error = -ENOMEM;
        goto err0;
    }

dev_set_drvdata(&client->dev, priv);

input = input_allocate_device();
    if (!input) {
        dev_err(&client->dev, "Failed to allocate input device.\n");
        error = -ENOMEM;
        goto err1;
    }

input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
    input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);

input_set_abs_params(input, ABS_X, MIN_X_COORDINATE, MAX_X_COORDINATE, 0, 0);
    input_set_abs_params(input, ABS_Y, MIN_Y_COORDINATE, MAX_Y_COORDINATE, 0, 0);

input->name = client->name;
    input->id.bustype = BUS_I2C;
    input->dev.parent = &client->dev;

input->open = i2c_ts_open;
    input->close = i2c_ts_close;

input_set_drvdata(input, priv);

priv->client = client;
    priv->input = input;
    INIT_DELAYED_WORK(&priv->work, i2c_ts_poscheck);
    priv->irq = client->irq;

error = input_register_device(input);
    if (error)
        goto err1;

error = request_irq(priv->irq, i2c_ts_isr, IRQF_TRIGGER_FALLING,
                client->name, priv);
    if (error) {
        dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
        goto err2;
    }

device_init_wakeup(&client->dev,1);
   
    return 0;

err2:
    input_unregister_device(input);
    input = NULL; /* so we dont try to free it below */
 err1:
    input_free_device(input);
    kfree(priv);
 err0:
    dev_set_drvdata(&client->dev, NULL);
    return error;
}

static int i2c_ts_remove(struct i2c_client *client)
{
    struct i2c_ts_priv *priv = dev_get_drvdata(&client->dev);

free_irq(priv->irq, priv);
    input_unregister_device(priv->input);
    kfree(priv);

dev_set_drvdata(&client->dev, NULL);

return 0;
}

static int i2c_ts_suspend(struct i2c_client *client, pm_message_t mesg)
{
    struct i2c_ts_priv *priv = dev_get_drvdata(&client->dev);
    if(device_may_wakeup(&client->dev))
    enable_irq_wake(priv->irq);
    return 0;
}

static int i2c_ts_resume(struct i2c_client *client)
{
    struct i2c_ts_priv *priv = dev_get_drvdata(&client->dev);
    if(device_may_wakeup(&client->dev))
    disable_irq_wake(priv->irq);
    return 0;
}

static const struct i2c_device_id i2c_ts_id[] = {
    { "i2c-ts", 0 },
    { }
};
MODULE_DEVICE_TABLE(i2c, i2c_ts_id);

static struct i2c_driver i2c_ts_driver = {
    .driver = {
        .name = "i2c-ts",
    },
    .probe = i2c_ts_probe,
    .remove = i2c_ts_remove,
    .suspend = i2c_ts_suspend,
    .resume = i2c_ts_resume,
    .id_table = i2c_ts_id,
};

static int __init i2c_ts_init(void)
{
    return i2c_add_driver(&i2c_ts_driver);
}

static void __exit i2c_ts_exit(void)
{
    i2c_del_driver(&i2c_ts_driver);
}

MODULE_DESCRIPTION("i2c Touchscreen driver");
MODULE_AUTHOR("ALlen <allen.p.wang@gmail.com>");
MODULE_LICENSE("GPL");

module_init(i2c_ts_init);
module_exit(i2c_ts_exit);

4).实现如上步骤后,还需要创建和配置I2C 设备,设置文件位于
linux-2.6.32.2/arch/arm/mach-s3c2440/mach-mini2440.c中,
添加如下代码:
..................................................
+/* I2C touch screen devices. */
+/* bus configuration */
+static struct s3c2410_platform_i2c i2c_touchscreen_cfg __initdata = {
+   .flags        = 0,
+    .slave_addr    = 0x5c,
+   .frequency    = 100*1000,
+    .sda_delay    = 2,
+};

+/* i2c device name is "i2c_ts", address is 0x5c, interrupt is eint20 */
+static struct i2c_board_info touchscreen_i2c_devs[] __initdata = {
+    {
+        I2C_BOARD_INFO("i2c-ts", 0x5c),
+        .irq    = IRQ_EINT20,
+    },
+};
...................................................

static void __init mini2440_machine_init(void)
{
..................................................
 +   /* i2c touch screen devices */
 +   s3c_i2c0_set_platdata(&i2c_touchscreen_cfg);
 +  i2c_register_board_info(0, touchscreen_i2c_devs,  +ARRAY_SIZE(touchscreen_i2c_devs));
...................................................
}

此处I2C_BOARD_INFO("i2c-ts",0x5c), “i2c-ts” 要和i2c设备驱动中i2c_ts_id一致。
才能保证i2c设备驱动成功加载。

Linux的I2C 设备驱动 -- mini2440 上i2c接口触摸屏驱动相关推荐

  1. 在linux(ubuntu16.04)系统上安装RTL8822CE网卡驱动

    在linux(ubuntu16.04)系统上安装RTL8822CE网卡驱动 1.下载8822CE驱动https://github.com/alanfox2000/realtek-linux/tree/ ...

  2. android4 触摸屏驱动,android中如何设计触摸屏驱动touch screen driver

    以下内容是来自android官方的文档,详细说明了android上层关心的event事件,如果要做一个好的TP驱动,这些信息是必须清楚的,另外现在的android2.3已经完全支持了virtualke ...

  3. Linux驱动开发学习笔记-电容触摸屏驱动

    <电容触摸屏驱动框架> 电容触摸屏驱动其实是以下几种 linux 驱动框架的组合: ① IIC 设备驱动,因为电容触摸 IC 基本都是 IIC 接口的,因此大框架就是 IIC 设备驱动. ...

  4. usb 接口触摸屏驱动

    以前写的 USB 接口的触摸屏驱动,那段时间简单的看了下 USB 协议的一些东西,主要是 HID 相关的,代码记录: /*Created by_fire 2012.2.13 */ #include & ...

  5. linux 1号硬盘不能用,linux 挂载硬盘的疑问 : IDE1 上的接口无法使用.

    状况说明: 我将在linux系统上挂载多块硬盘(目前是redhat9).我通过3块硬盘试验.问题出现:无论如何链接 IDE1 上的硬盘, /dev/hdc 都无法 mount. 数据: 1. 使用 f ...

  6. 手把手教你写Linux I2C设备驱动

    手把手教你写Linux I2C设备驱动 标签:Linux 设备 驱动 详解 i2c 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http:/ ...

  7. linux探测i2c设备连接状态,手把手教你写Linux I2C设备驱动

    Linux I2C驱动是嵌入式Linux驱动开发人员经常需要编写的一种驱动,因为凡是系统中使用到的I2C设备,几乎都需要编写相应的I2C驱动去配置和控制它,例如 RTC实时时钟芯片.音视频采集芯片.音 ...

  8. 手把手教你写Linux I2C设备驱动 tvp5158

    Linux I2C驱动是嵌入式Linux驱动开发人员经常需要编写的一种驱动,因为凡是系统中使用到的I2C设备,几乎都需要编写相应的I2C驱动去配置和控制它,例如 RTC实时时钟芯片.音视频采集芯片.音 ...

  9. linux I2C设备驱动

    linux内核的总线-设备-驱动模型,当总线上的设备与总线上的驱动匹配时,就会调用驱动的probe函数,完成一系列的操作 I2C也是内核的一种总线 一.I2C设备的4种构建方法 1.静态注册设备 (1 ...

最新文章

  1. 黑洞最新照片来了:只多了炫酷光纹,却让物理学家解开喷流大谜题
  2. Jetson TX2 学习资料整理
  3. 安装kibana,X-pack和elasticsearch插件的全过程
  4. Node Capital生态布局初成,部分项目差强人意
  5. lintcode:最小编辑距离
  6. vant toast loading 倒计时_日期倒计时软件哪个好 苹果日期倒计时软件推荐
  7. 如何导出无水印_抖音视频怎么去水印 抖音怎么导出无水印视频
  8. Redis报错#MISCONF Redis is configured to save RDB snapshots, but is currently not
  9. 用 Javascript 生成二维码
  10. 世界杯运营:时隔2年,这个教科书般的Push,看完依然泪奔
  11. 用手机写一个抓cookie软件
  12. 康涅狄格大学计算机科学排名,康涅狄格大学的计算机科学排名,不可忽视的重点信息...
  13. RocketMQ学习笔记:基础知识和安装启动
  14. 你必需知道的5个开源游戏引擎
  15. sql server 里面的主要数据文件和次要数据文件有什么区别呢
  16. 电脑市场GHOST XP SP3_V9.9
  17. oracle数据库无法查询,【案例】Oracle报错ORA-01194 ORA-01110 由于数据库SCN不一致导致无法启动...
  18. 等风来不如追风去,贵阳校区小哥哥转行软件测试获12k,做职场最靓的仔~
  19. 古道西风,我是那绝望的断肠人
  20. FSC-COC供应链管理体系认证、认证培训标准、审核清单、认证公司

热门文章

  1. VS 调用外部DLL时提示“无法嵌入互操作类型”
  2. 使用ArrayList时设置初始容量的重要性
  3. 26 | 红黑树(下):掌握这些技巧,你也可以实现一个红黑树
  4. 实战CGLib系列之proxy:方法拦截MethodInterceptor
  5. index.html乱码问题,用apache打开文件index显示乱码为什么
  6. 自定义泛型集合,接口
  7. MySQL 表和列的注释
  8. MySQL系列--4.使用Python3访问数据库
  9. Hadoop学习笔记
  10. Windows中断那些事儿