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

本篇记录在友善之臂 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设备驱动成功加载。

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

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

相关文章

十六进制字符串转整形

System.Convert.ToInt32( "字符串 ",16); 转载于:https://www.cnblogs.com/dashi/archive/2011/12/22/4034737.html

gridview databind 会导致页面刷新马_Innodb批量页面刷盘情况下的quot;两次写quot;

//Innodb批量页面刷盘情况下的"两次写"//之前的文章中&#xff0c;我们介绍过innodb的两次写特性&#xff0c;这里给出链接&#xff1a;InnoDB的两次写特性今天我们完善一下这部分的内容。我们知道innodb数据页的默认大小是16kb&#xff0c;磁盘和内存通过数据页进行…

linux内核I2C子系统学习(一)

这部分准备分几个部分进行分析总结 因为I2C的通信肯定至少要有2个芯片完成&#xff0c;所以它的驱动是由2大部分组成&#xff1a;主芯片的i2c的驱动从芯片的i2c的驱动 注&#xff1a;万一选的都不支持咋办&#xff1f;&#xff1f;&#xff1f;&#xff08;惨了&#xff0c;只能…

【转】excel表格导出集锦repeater实用,和普通用法

【http://www.cnblogs.com/s-y-l/archive/2011/12/23/2299008.html】下面导出excel主要解决repeater产生乱码的问题publicvoid CreateExcel(DataSet ds,string typeid,string FileName) { HttpResponse resp; resp Page.Response; …

什么是流量攻击? 流量攻击怎么处理?

由于DDoS攻击往往采取合法的数据请求技术&#xff0c;再加上傀儡机器&#xff0c;造成DDoS攻击成为最难防御的网络攻击之一。据美国最新的安全损失调查报告&#xff0c;DDoS攻击所造成的经济损失已经跃居第一。 传统的网络设备和周边安全技术&#xff0c;例如防火墙和IDSs(Intr…

django批量修改table_django-formset实现数据表的批量操作

什么是formset我们知道forms组件是用来做表单验证&#xff0c;更准确一点说&#xff0c;forms组件是用来做数据库表中一行记录的验证。有forms组件不同&#xff0c;formset是同科同时验证表中的多行记录&#xff0c;即formset是做表单批量验证的组件。批量添加首先要实例化form…

linux内核I2C子系统学习(二)

下面具体分析如何写第一部分&#xff1a;主控芯片的i2c驱动分为2个步骤&#xff1a;写总线驱动&#xff1a;选了个主控芯片&#xff0c;比如&#xff1a;S3C8900&#xff08;自己瞎编的芯片&#xff09;在driver/i2c/busses/i2c-s3c2410.c中没有找到这个芯片的I2C支持(总线驱动…

20111228_给窗体设置默认输入法

//给窗体设置默认输入法 //新建一个窗体类ImeForm&#xff0c;设置Form1:ImeForm public class ImeForm:System.Windows.Forms.Form { [DllImport("imm32.dll")] public static extern IntPtr ImmGetContext(IntPtr hWnd); [DllImport("imm32.dll")] publ…

efishell无法开机shell_开机出现efi shell卡住不动了解决方法全集

[文章导读] 最近有很多网友问我&#xff0c;为什么我的电脑开机后出现efi shell提示进不了系统&#xff0c;开机出现efi shell提示时&#xff0c;一般是由于第一启动项设置的是efi shell启动的&#xff0c;有的网友告诉我&#xff0c;我第一启动项明明设置的是硬盘启动&#xf…

linux内核I2C子系统学习(三)

写设备驱动&#xff1a;四部曲&#xff1a;构建i2c_driver注册i2c_driver构建i2c_client &#xff08; 第一种方法&#xff1a;注册字符设备驱动、第二种方法&#xff1a;通过板文件的i2c_board_info填充&#xff0c;然后注册&#xff09; 注销i2c_driver 具体如下&#xff1a;…

Delphi环境中编写调用DLL的方法和技巧

Delphi环境中编写调用DLL的方法和技巧第一章 为什么要使用动态链接库&#xff08;DLL&#xff09; top 提起DLL您一定不会陌生&#xff0c;在Windows中有着大量的以DLL为后缀的文件&#xff0c;它们是保证Windows正常运行和维护升级的重要保证。&#xff08;举个例子&#xff0…

信道容量受哪三个要素_影响信道容量的主要因素有哪些

匿名用户 1级 2015-03-23 回答 化。编码器输出的数字序列与到译码器输入的数字序列之间的关系,通常用多端口网络的转移概率作为编码信道的数学模型进行描述。 三、信道的数学模型 (一)调制信道模型 调制信道模型描述的是调制信道的输出信号和输入信号之间的数学关系。调制信道…

实例解析linux内核I2C体系结构(1)

作者&#xff1a;刘洪涛,华清远见嵌入式学院讲师。 一、概述 谈到在linux系统下编写I2C驱动&#xff0c;目前主要有两种方式&#xff0c;一种是把I2C设备当作一个普通的字符设备来处理&#xff0c;另一种是利用linux I2C驱动体系结构来完成。下面比较下这两种驱动。 第一种方…

git hook分支_编写一个git post-receive hook来处理特定的分支

来自pauljz的答案适用于某些git钩子&#xff0c;如pre-push&#xff0c;但pre-commit无法访问这些变量oldrev newrev refname所以我创建了这个替代版本&#xff0c;适用于预提交&#xff0c;或者真正和钩子。这是一个pre-commit挂钩&#xff0c;如果我们不在master分支上&#…

★ Flex を使って Scalable Vector Graphics とビットマップを描画する

from: http://www.ibm.com/developerworks/jp/web/library/wa-svgbitmap/Flex を使って Scalable Vector Graphics とビットマップを描画するSandeep Malik, Tech Lead, IBM 概要&#xff1a; SVG (Scalable Vector Graphics) はグラフィックスの領域で最も重要な技術の 1 つで…

g5420 win7集显驱动_台式机装WIN7?雷我已经趟完了

注&#xff1a;本文只用于PC爱好者交流测试&#xff0c;文中所有测试版系统均只用于测试&#xff0c;不得用于个人或商业用途。Windows全面更新至win10版本后&#xff0c;改装Win7系统逐渐变得越来越艰难。厂商BIOS中逐渐舍弃了原始界面改为图形化&#xff0c;传统Legacy模式无…

实例解析linux内核I2C体系结构(2)

作者&#xff1a;刘洪涛,华清远见嵌入式学院讲师。 四、在内核里写i2c设备驱动的两种方式 前文介绍了利用/dev/i2c-0在应用层完成对i2c设备的操作&#xff0c;但很多时候我们还是习惯为i2c设备在内核层编写驱动程序。目前内核支持两种编写i2c驱动程序的方式。下面分别介绍这两种…

制作完整的java可执行文件

帮教务处的老师做了一个小软件&#xff0c;所以学习了一下制作java可执行文件&#xff0c;在此分享一下。 说明&#xff1a;因为是做完很长一段时间后再截的图&#xff0c;可能有点纰漏&#xff0c;大体应该没什么问题。 我的eclipse工程文件目录: bin | images&#xff08;放图…

I2C设备驱动编写,struct i2c_device_id,struct i2c_driver,i2c_add_driver,i2c_register_board_info

我的理念&#xff1a;简单实用即可&#xff0c;不要搞一堆源码出来&#xff0c;结果让人看了以后还不知道怎么用&#xff0c;看我的&#xff1a; 1、在arch/arm/mach-xxx/ 自己的平台文件里添加i2c信息&#xff0c;美其名曰&#xff1a;i2c_board_info 例如&#xff1a; stat…

ajax中async_小猿圈web前端之ajax的同步和异步有怎样的区别?

对于ajax我们应该知道ajax是主要用来在前端页面中向服务器后端请求数据&#xff0c;ajax中根据async的值不同分为同步&#xff08;async false&#xff09;和异步&#xff08;async true&#xff09;两种执行方式&#xff0c;那么&#xff0c;ajax的同步和异步请求两种方式有…