Chinaunix首页 | 论坛 | 博客
  • 博客访问: 99084
  • 博文数量: 23
  • 博客积分: 516
  • 博客等级: 中士
  • 技术积分: 315
  • 用 户 组: 普通用户
  • 注册时间: 2011-10-29 16:45
文章分类
文章存档

2012年(11)

2011年(12)

分类: LINUX

2012-01-05 11:35:08

platform:Renesas_emev
kernel version:2.6.35.7
android version:2.3.4
description:采用轮询操作,并用两种内核定时器实现,一种us级,一种ns级。
                   按键处理也用两种发放实现,具体见代码。
                   代码用于产品可正常使用。
code:

//#include
#include
#include
#include
#include
#include
#include

#include
#include
#include
#include

#include
#include
#include
#include


#define I2C_SLAVE_HA2605_NAME    "ha2605"

#define HA_POLL_DELAY (100*1000*1000)

#define RESTRAINT_LEVEL            0
#define SENSITIVITY_LEVEL        31

#define KEY_CFG_WORD            ((RESTRAINT_LEVEL<<5) | SENSITIVITY_LEVEL)

#define HA2605_DELAY                    100
#define HA2605_CFG_NUM                12

#define HA2605_MSG_HEADE            0x88        //fixed
#define HA2605_SPEC_WORD            0x05        //fixed
#define HA2605_CFG1_WORD            KEY_CFG_WORD        //key1     /*High 3bit is rejection ratio*/
#define HA2605_CFG2_WORD            KEY_CFG_WORD        //key2    /*and low    5bit is sensitivity.*/
#define HA2605_CFG3_WORD            KEY_CFG_WORD        //key3    /*More big the sensitivity is */
#define HA2605_CFG4_WORD            KEY_CFG_WORD        //key4    /*more sensitive and the             */
#define HA2605_CFG5_WORD            KEY_CFG_WORD        //key5    /*rejection ratio to be.            */
#define HA2605_SELT_WORD            0xf8        //High 5 bit is the key select. bit7 to key1,bit6 to key2 ... ...
#define HA2605_EXP1_WORD            0x00        //fixed
#define HA2605_PARA_WORD            0x05        //fixed //0x40 0x00 0x0d
#define HA2605_EXP2_WORD            0x00        //fixed 
#define HA2605_VERy_WORD            (HA2605_SPEC_WORD+HA2605_CFG1_WORD+HA2605_CFG2_WORD    \
                                                            +HA2605_CFG3_WORD+HA2605_CFG4_WORD+HA2605_CFG5_WORD    \
                                                            +HA2605_SELT_WORD+HA2605_EXP1_WORD+HA2605_PARA_WORD \
                                                            +HA2605_EXP2_WORD)

static unsigned int buttons[3] = {KEY_BACK,KEY_HOME,KEY_MENU};


static char ha2605_cfg[HA2605_CFG_NUM] = {
    HA2605_MSG_HEADE,    HA2605_SPEC_WORD, HA2605_CFG1_WORD, HA2605_CFG2_WORD,
    HA2605_CFG3_WORD,    HA2605_CFG4_WORD, HA2605_CFG5_WORD, HA2605_SELT_WORD,
    HA2605_EXP1_WORD,    HA2605_PARA_WORD, HA2605_EXP2_WORD, HA2605_VERy_WORD};

struct ha2605{
    struct device             *dev;
    struct i2c_client        *client;
    struct delayed_work    work;
    struct input_dev         *input_dev;   
    struct hrtimer    timer;    /*monitor interrupt pin*/
    struct work_struct works;
};

static int ha2605_i2c_read(struct ha2605 *ha, int bytes, void *dest)
{
    int ret;
    struct i2c_client *client = ha->client;
    ret = i2c_master_recv(client, dest, bytes);
    if (ret < 0 || ret != bytes)
        return -EIO;
   
    return 0;
}


static int ha2605_i2c_write(struct ha2605 *ha, int bytes, char *src)
{
    struct i2c_client *client = ha->client;
    int ret;
    ret = i2c_master_send(client, src, bytes);
   
    if (ret < 0 || ret < bytes)
        return -EIO;
       
    return 0;
}

static void ha2605_work(struct work_struct *work)
{
//    struct ha2605 *ha = container_of(to_delayed_work(work), struct ha2605, work);
    struct ha2605 *ha = container_of(work, struct ha2605, works);

    struct input_dev *input_dev = ha->input_dev;   
    int ret;
#if 0
    unsigned char keyval = 0,keycode;
    static unsigned char key_status=0;
    static unsigned char key_old_status=0;
    ret=ha2605_i2c_read(ha, 1, &keyval);
    if(keyval == 0xff)
    {
        key_status = 0;
        if(key_status != key_old_status)
        {
            keycode = buttons[key_old_status - 1];
            input_report_key(input_dev, keycode, 0);
            input_sync(input_dev);
            key_old_status = 0;
        }
    }
    else
    {
        if(keyval == 3)
            key_status = 1;
        else if(keyval == 4)
            key_status = 2;
        else if(keyval == 5)
            key_status = 3;

        if((key_status != key_old_status) && key_status)
        {
            keycode = buttons[key_status - 1];
            input_report_key(input_dev, keycode, 1);
            input_sync(input_dev);
            key_old_status = key_status;
        }
    }
//    schedule_delayed_work(&ha->work, msecs_to_jiffies(HA2605_DELAY));
    hrtimer_start(&ha->timer,ktime_set(0,HA_POLL_DELAY),HRTIMER_MODE_REL);   
#else
    unsigned char keyval = 0;
    static unsigned char keycode=0;
    static unsigned char PreKeycode=0;
   
    ret=ha2605_i2c_read(ha, 1, &keyval);

    if(keyval==0xff)
    {
        if(PreKeycode != 0)
        {
       
            input_report_key(input_dev,PreKeycode,0);
            input_sync(input_dev);
            PreKeycode=0;
        }
    }
    else
    {
        if(keyval==3) keycode=KEY_BACK;
        else if(keyval==4) keycode=KEY_HOME;
        else if(keyval==5) keycode=KEY_MENU;
        else keycode=0;

        if(keycode != 0)
        {
            input_report_key(input_dev,keycode,1);
            input_sync(input_dev);
            PreKeycode=keycode;
        }
    }
    hrtimer_start(&ha->timer,ktime_set(0,HA_POLL_DELAY),HRTIMER_MODE_REL);   
#endif
}

static int ha2605_initial(struct ha2605 *ha, int bytes, char *src)
{
    return ha2605_i2c_write(ha, bytes, src);
}

static enum hrtimer_restart ha2605_hrtimer(struct hrtimer *handle)
{
    struct ha2605 *hadata = container_of(handle, struct ha2605, timer);

    //queue_work(ekt2201_wq, &tsdata->work.work);
    schedule_work(&hadata->works);
    return HRTIMER_NORESTART;
}


static int __devinit ha2605_i2c_probe(struct i2c_client *client,
                   const struct i2c_device_id *id)
{
    int ret;
    struct ha2605 *ha;
    struct input_dev *input_dev;
    ha = kzalloc(sizeof(struct ha2605), GFP_KERNEL);
    if (!ha) {       
        ret = -ENOMEM;
        goto err0;   
    }
   
    ha->dev                             = &client->dev;   
    ha->client                         = client;
    ret = ha2605_initial(ha, HA2605_CFG_NUM, ha2605_cfg);
    if (ret) {
        dev_err(ha->dev, "Ha2605 touch key init failed: %d\n", ret);
    }
   
    input_dev = input_allocate_device();
    if (!input_dev) {
        ret = -ENOMEM;
        dev_err(ha->dev, "Ha2605 failed to allocate input mem: %d\n", ret);
        goto err1;
    }   
   
    ha->input_dev                 = input_dev;   
    input_dev->name             = I2C_SLAVE_HA2605_NAME;
    input_dev->id.bustype = BUS_I2C;
    input_dev->id.version = 0x0001;

    input_set_capability(input_dev, EV_KEY, KEY_HOME);   
    input_set_capability(input_dev, EV_KEY, KEY_MENU);   
    input_set_capability(input_dev, EV_KEY, KEY_BACK);   

    input_set_drvdata(input_dev, ha);
   
    ret = input_register_device(input_dev);
    if (ret) {
        dev_err(ha->dev, "Ha2605 failed to register input dev: %d\n", ret);
        goto err2;
    }   
//    INIT_DELAYED_WORK(&ha->work, ha2605_work);
    i2c_set_clientdata(client, ha);   
//    schedule_delayed_work(&ha->work, msecs_to_jiffies(HA2605_DELAY));
    INIT_WORK(&ha->works, ha2605_work);
    hrtimer_init(&ha->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    ha->timer.function = ha2605_hrtimer;
    hrtimer_start(&ha->timer,ktime_set(0,HA_POLL_DELAY),HRTIMER_MODE_REL);   
    return 0;   
   
err2:
    input_free_device(input_dev);
err1:
    kfree(ha);
err0:
    return ret;
}

static int __devexit ha2605_i2c_remove(struct i2c_client *client)
{
    struct ha2605 *ha = i2c_get_clientdata(client);
    cancel_delayed_work_sync(&ha->work);
    input_unregister_device(ha->input_dev);
    input_free_device(ha->input_dev);
    kfree(ha);
   
    return 0;   
}

#ifdef CONFIG_PM

static int ha2605_i2c_resume(struct i2c_client *client)
{
    struct ha2605 *ha = i2c_get_clientdata(client);
    schedule_delayed_work(&ha->work, msecs_to_jiffies(HA2605_DELAY));
   
    return 0;   
}

static int ha2605_i2c_suspend(struct i2c_client *client,
                            pm_message_t mesg)
{
    struct ha2605 *ha = i2c_get_clientdata(client);
    cancel_delayed_work_sync(&ha->work);
   
    return 0;   
}

#endif

static const struct i2c_device_id ha2605_i2c_id[] = {
    { I2C_SLAVE_HA2605_NAME, 0 },   
    { }
};
MODULE_DEVICE_TABLE(i2c, ha2605_i2c_id);

static struct i2c_driver ha2605_i2c_driver = {
    .driver = {   
           .owner = THIS_MODULE,
           .name = I2C_SLAVE_HA2605_NAME,
    },
    .probe = ha2605_i2c_probe,
    .remove = ha2605_i2c_remove,
#ifdef CONFIG_PM
    .suspend = ha2605_i2c_suspend,
    .resume = ha2605_i2c_resume,
#endif
    .id_table = ha2605_i2c_id,
};

static int __init ha2605_init(void)
{
    return i2c_add_driver(&ha2605_i2c_driver);
}

static void __exit ha2605_exit(void)
{
    i2c_del_driver(&ha2605_i2c_driver);
}

module_init(ha2605_init);
module_exit(ha2605_exit);
MODULE_DESCRIPTION("SMALLART TOUCH KEY Driver");
MODULE_LICENSE("GPL");



阅读(2109) | 评论(1) | 转发(0) |
0

上一篇:battery capacity check

下一篇:cpufreq patch

给主人留下些什么吧!~~