UT4412BV03矩阵键盘驱动分析.docx

上传人:b****2 文档编号:17183016 上传时间:2023-04-24 格式:DOCX 页数:12 大小:201.20KB
下载 相关 举报
UT4412BV03矩阵键盘驱动分析.docx_第1页
第1页 / 共12页
UT4412BV03矩阵键盘驱动分析.docx_第2页
第2页 / 共12页
UT4412BV03矩阵键盘驱动分析.docx_第3页
第3页 / 共12页
UT4412BV03矩阵键盘驱动分析.docx_第4页
第4页 / 共12页
UT4412BV03矩阵键盘驱动分析.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

UT4412BV03矩阵键盘驱动分析.docx

《UT4412BV03矩阵键盘驱动分析.docx》由会员分享,可在线阅读,更多相关《UT4412BV03矩阵键盘驱动分析.docx(12页珍藏版)》请在冰豆网上搜索。

UT4412BV03矩阵键盘驱动分析.docx

UT4412BV03矩阵键盘驱动分析

UT4412BV03矩阵键盘驱动分析

一.UT4412BV03开发板外接了一个3*3的矩阵键盘,通过对矩阵键盘的驱动的编写来实现按键的功能linux内核中已经包含了一个矩阵键盘的驱动,用户只需要简单修改就能实现按键的功能。

UT4412BV03矩阵键盘原理图

如图:

在默认倩况下,矩阵键盘的行线被电阻上拉到高电平。

如果某个按键被按下则其对应的行线和列线都为低电平

 

软件流程图

二.矩阵键盘驱动分析

 1.矩阵键盘对应的IO管脚的初始化

   linux/arch/arm/mach-exynos/setup-keypad.c

voidsamsung_keypad_cfg_gpio(unsignedintrows,unsignedintcols)

{

 if(rows>8){ 

 /*SetallthenecessaryGPX2pins:

KP_ROW[0~7]*/

 s3c_gpio_cfgall_range(EXYNOS4_GPX2(0),8,

   S3C_GPIO_SFN(3),S3C_GPIO_PULL_UP);

 /*SetallthenecessaryGPX3pins:

KP_ROW[8~]*/

 s3c_gpio_cfgall_range(EXYNOS4_GPX3(0),(rows-8),

   S3C_GPIO_SFN(3),S3C_GPIO_PULL_UP);

 }else{

 /*SetallthenecessaryGPX2pins:

KP_ROW[x]*/

 s3c_gpio_cfgall_range(EXYNOS4_GPX2(0),rows,

   S3C_GPIO_SFN(3),S3C_GPIO_PULL_UP);

 }

 /*SetallthenecessaryGPX1pinstospecial-function3:

KP_COL[x]*/

 s3c_gpio_cfgrange_nopull(EXYNOS4_GPX1(0),cols,S3C_GPIO_SFN(3));

}

2.矩阵键盘平台设备和平台资源的初始化

linux/arch/arm/plat-samsung/dev-keypad.c

staticstructresourcesamsung_keypad_resources[]={

 [0]={

 .start=SAMSUNG_PA_KEYPAD,

 .end=SAMSUNG_PA_KEYPAD+0x20-1,

 .flags=IORESOURCE_MEM,

 },

 [1]={

 .start=IRQ_KEYPAD,

 .end=IRQ_KEYPAD,

 .flags=IORESOURCE_IRQ,

 },

};

structplatform_devicesamsung_device_keypad={

 .name="samsung-keypad",

 .id=-1,

 .num_resources=ARRAY_SIZE(samsung_keypad_resources),

 .resource=samsung_keypad_resources,

};

3. SamSung-keypd.c矩阵键盘驱动分析

//填充一个平台驱动结构体

 staticstructplatform_driversamsung_keypad_driver={

 .probe=samsung_keypad_probe, //按键探测函数,驱动注册后最先执行的函数

 .remove=__devexit_p(samsung_keypad_remove),

 .driver={

 .name="samsung-keypad", //平台驱动的名字

 .owner=THIS_MODULE,

#ifdefCONFIG_PM

 .pm=&samsung_keypad_pm_ops,

#endif

 },

 .id_table=samsung_keypad_driver_ids,

};

//注册一个平台驱动

staticint__initsamsung_keypad_init(void)

{

 returnplatform_driver_register(&samsung_keypad_driver);

}

//驱动注册后最先执行的探测函数分析

staticint__devinitsamsung_keypad_probe(structplatform_device*pdev)

{

 conststructsamsung_keypad_platdata*pdata;

 conststructmatrix_keymap_data*keymap_data;

 structsamsung_keypad*keypad;

 structresource*res;

 structinput_dev*input_dev;

 unsignedintrow_shift;

 unsignedintkeymap_size;

 interror;

#ifdefCONFIG_WAKELOCK_KEEP

 wake_lock_init(&s_ut_wake_lock2, WAKE_LOCK_SUSPEND,"holdwakebuttom");

 keep_wakeup_timeout

(2);

#endif

 pdata=pdev->dev.platform_data; //获取平台私有数据

 if(!

pdata){

 dev_err(&pdev->dev,"noplatformdatadefined\n");

 return-EINVAL;

 }

 keymap_data=pdata->keymap_data;

 if(!

keymap_data){

 dev_err(&pdev->dev,"nokeymapdatadefined\n");

 return-EINVAL;

 }

 if(!

pdata->rows||pdata->rows>SAMSUNG_MAX_ROWS)

 return-EINVAL;

 if(!

pdata->cols||pdata->cols>SAMSUNG_MAX_COLS)

 return-EINVAL;

 /*initializethegpio*/

 if(pdata->cfg_gpio)

 //调用GPIO初始化函数,设置对应引脚为按键模式

 pdata->cfg_gpio(pdata->rows,pdata->cols);

 row_shift=get_count_order(pdata->cols);

 keymap_size=(pdata->rows<keycodes[0]);

 keypad=kzalloc(sizeof(*keypad)+keymap_size,GFP_KERNEL);

 input_dev=input_allocate_device();

 if(!

keypad||!

input_dev){

 error=-ENOMEM;

 gotoerr_free_mem;

 }

 res=platform_get_resource(pdev,IORESOURCE_MEM,0);

 if(!

res){

 error=-ENODEV;

 gotoerr_free_mem;

 }

 keypad->base=ioremap(res->start,resource_size(res));

 if(!

keypad->base){

 error=-EBUSY;

 gotoerr_free_mem;

 }

 keypad->clk=clk_get(&pdev->dev,"keypad");

 if(IS_ERR(keypad->clk)){

 dev_err(&pdev->dev,"failedtogetkeypadclk\n");

 error=PTR_ERR(keypad->clk);

 gotoerr_unmap_base;

 }

//初始化keypad结构体

 keypad->input_dev=input_dev;

 keypad->row_shift=row_shift;

 keypad->rows=pdata->rows;

 keypad->cols=pdata->cols;

 init_waitqueue_head(&keypad->wait);

 input_dev->name=pdev->name;

 input_dev->id.bustype=BUS_HOST;

 input_dev->dev.parent=&pdev->dev;

 input_set_drvdata(input_dev,keypad);

 input_dev->open=samsung_keypad_open;

 input_dev->close=samsung_keypad_close;

 input_dev->evbit[0]=BIT_MASK(EV_KEY); //表示输入设备为按键

 if(!

pdata->no_autorepeat)

 input_dev->evbit[0]|=BIT_MASK(EV_REP);

 input_set_capability(input_dev,EV_MSC,MSC_SCAN);

 input_dev->keycode=keypad->keycodes;

 input_dev->keycodesize=sizeof(keypad->keycodes[0]);

 input_dev->keycodemax=pdata->rows<

 matrix_keypad_build_keymap(keymap_data,row_shift,

  input_dev->keycode,input_dev->keybit);

 keypad->irq=platform_get_irq(pdev,0);

 if(keypad->irq<0){

 error=keypad->irq;

 gotoerr_put_clk;

 }

//注册一个按键中断,当有按键按下时,将触发samsung_keypad_irq函数的执行

 error=request_threaded_irq(keypad->irq,NULL, samsung_keypad_irq,

  IRQF_ONESHOT,dev_name(&pdev->dev),keypad);

 if(error){

 dev_err(&pdev->dev,"failedtoregisterkeypadinterrupt\n");

 gotoerr_put_clk;

 }

 error=input_register_device(keypad->input_dev);

 if(error)

 gotoerr_free_irq;

 device_init_wakeup(&pdev->dev,pdata->wakeup);

 platform_set_drvdata(pdev,keypad);

 return0;

err_free_irq:

 free_irq(keypad->irq,keypad);

err_put_clk:

 clk_put(keypad->clk);

err_unmap_base:

 iounmap(keypad->base);

err_free_mem:

 input_free_device(input_dev);

 kfree(keypad);

 returnerror;

}

//矩阵键盘按键使能函数

staticvoidsamsung_keypad_start(structsamsung_keypad*keypad)

{

 unsignedintval;

 /*TellIRQthreadthatitmaypollthedevice.*/

 keypad->stopped=false;

 clk_enable(keypad->clk);

 /*Enableinterruptbits.*/

 val=readl(keypad->base+SAMSUNG_KEYIFCON);

//使能按键在上升沿和下降沿出发按键中断

 val|=SAMSUNG_KEYIFCON_INT_F_EN|SAMSUNG_KEYIFCON_INT_R_EN;

 writel(val,keypad->base+SAMSUNG_KEYIFCON);

 /*KEYIFCOLregclear.*/

//KEYIFCOL寄存器写零,使每个行输入引脚为正常输入模式

 writel(0,keypad->base+SAMSUNG_KEYIFCOL);

}

//按键中断函数

staticirqreturn_tsamsung_keypad_irq(intirq,void*dev_id)

{

 structsamsung_keypad*keypad=dev_id;

 unsignedintrow_state[SAMSUNG_MAX_COLS];

 unsignedintval;

 boolkey_down;

 do{

 val=readl(keypad->base+SAMSUNG_KEYIFSTSCLR);

 //清除中断标志位

 writel(~0x0,keypad->base+SAMSUNG_KEYIFSTSCLR);

 //调用按键扫描函数

 samsung_keypad_scan(keypad,row_state);

//按键值上报到android用户空间

 key_down=samsung_keypad_report(keypad,row_state);

 if(key_down)

 //当按键按下时调用下面函数来达到消斗动作用

  wait_event_timeout(keypad->wait,keypad->stopped,

    msecs_to_jiffies(50));

 }while(key_down&&!

keypad->stopped); //等待按键释放

 returnIRQ_HANDLED;

4.按键值的定义

 //linux/arch/arm/mach-exynos/mach-smdk4x12.c

按键值定义在input.h中,并且最终按键值要和android中定义的键值匹配才行

staticuint32_tsmdk4x12_keymap0[]__initdata={

          158                172                   108

 KEY(0,0,KEY_BACK),    KEY(0,1,KEY_HOMEPAGE), KEY(0,2,KEY_DOWN),

          114                139                  115

 KEY(1,0,KEY_VOLUMEDOWN), KEY(1,1,KEY_MENU),   KEY(1,2,KEY_VOLUMEUP),

          103                105                   106

 KEY(2,0,KEY_UP),     KEY(2,1,KEY_LEFT),   KEY(2,2,KEY_RIGHT),

};

staticstructmatrix_keymap_datasmdk4x12_keymap_data0__initdata={

 .keymap=smdk4x12_keymap0,

 .keymap_size=ARRAY_SIZE(smdk4x12_keymap0),

};

staticstructsamsung_keypad_platdatasmdk4x12_keypad_data0__initdata={

 .keymap_data=&smdk4x12_keymap_data0,

 .rows=3,  //3行

 .cols=3, //3列

};

android代码中定义的按键值如下

kernel中定义的键值要和android中定义的键值一一对应

/device/samsung/smdk4x12$

key103   DPAD_UP         WAKE_DROPPED

key3     DPAD_CENTER     WAKE_DROPPED

key108   DPAD_DOWN      WAKE_DROPPED

key106   DPAD_RIGHT       WAKE_DROPPED

key105   DPAD_LEFT         WAKE_DROPPED

key114   VOLUME_DOWN     WAKE

key172   HOME              WAKE_DROPPED

key139   MENU              WAKE_DROPPED

key115   VOLUME_UP         WAKE

key158   BACK               WAKE_DROPPED

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 建筑土木

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1