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");
阅读(2122) | 评论(1) | 转发(0) |