arm9+linux fl2440之按鍵驅動 plat_button.c
{
result = -EBUSY;
goto ERROR1;
}
}
return 0;
ERROR1:
kfree((unsigned char *)pdev->status);
while(--i)
{
disable_irq(pdata->buttons[i].nIRQ);
free_irq(pdata->buttons[i].nIRQ, (void *)i);
}
ERROR:
kfree(pdev->timers);
return result;
}
static int button_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
struct button_device *pdev = file->private_data;
struct s3c_button_platform_data *pdata;
int i, ret;
unsigned int status = 0;
pdata = pdev->data;
dbg_print("ev_press: %d\n", pdev->ev_press);
if(!pdev->ev_press)
{
if(file->f_flags & O_NONBLOCK)
//使I/O變成非擱置模式,在讀取不到資料或是寫入緩衝區已滿馬上return,而不會擱置程式動作,知道有資料或寫入完成。
{
dbg_print("read() without block mode.\n");
return -EAGAIN;
/* 從字面上看,是提示再試一次的意思。這個錯誤經常出現在當應用程式進行一些非阻塞(non-blocking)操作(對檔案或socket)的時候。
*/
}
else
{
/* Read() will be blocked here */
dbg_print("read() blocked here now.\n");
wait_event_interruptible(pdev->waitq, pdev->ev_press);
/*
這個函式先將當前程序的狀態設定成TASK_INTERRUPTIBLE, 然後呼叫schedule(), 而schedule()會將位於TASK_INTERRUPTIBLE狀態的當前程序從runqueue佇列中刪除。從runqueue佇列中刪除的結果是,當前這個程序將不再參與排程,除非通過其他函式將這個程序重新放入到runqueue佇列中,這就是wake_up()的作用。
*/
}
}
pdev->ev_press = 0;
for(i=0; i<pdata->nbuttons; i++)
{
dbg_print("button[%d] status=%d\n", i, pdev->status[i]);
status |= (pdev->status[i]<<i);
}
ret = copy_to_user(buf, (void *)&status, min(sizeof(status), count));
return ret ? -EFAULT : min(sizeof(status), count);
}
static unsigned int button_poll(struct file *file, poll_table * wait)
{
struct button_device *pdev = file->private_data;
unsigned int mask = 0;
poll_wait(file, &(pdev->waitq), wait);
/* poll_wait()是用在select系統呼叫中的。一般你的程式碼有一個struct
* file_operations結構,其中fop->poll函式指標指向一個你自己的函式,在這個函式裡應該呼叫poll_wait().當用戶呼叫select系統呼叫時,select系統呼叫會先呼叫poll_initwait(&table);然後呼叫你的fop->poll();從而將current加到某個等待佇列(這裡呼叫poll_wait());並檢查是否有效,如果無效就呼叫schedule_timeout()去睡眠。事件發生後,schedule_timeout()回來,呼叫fop->poll();檢查到可以執行,就呼叫poll_freewait(&table);從而完成select呼叫。重要的是fop->poll()裡面要檢查是否就緒。如果是,要返回相應標誌。
*/
if(pdev->ev_press)
{
mask |= POLLIN | POLLRDNORM; /* The data aviable */
//POLLIN普通或優先順序帶資料可讀;POLLRDNORM普通資料可讀
}
return mask;
}
static int button_release(struct inode *inode, struct file *file)
{
int i;
struct button_device *pdev = file->private_data;
struct s3c_button_platform_data *pdata;
pdata = pdev->data;
for(i=0; i<pdata->nbuttons; i++)
{
disable_irq(pdata->buttons[i].nIRQ);
free_irq(pdata->buttons[i].nIRQ, (void *)i);
del_timer(&(pdev->timers[i]));
}
kfree(pdev->timers);
kfree((unsigned char *)pdev->status);
return 0;
}
static struct file_operations button_fops = {
.owner = THIS_MODULE,
.open = button_open,
.read = button_read,
.poll = button_poll,
.release = button_release,
};
static int s3c_button_probe(struct platform_device *dev)
{
int result = 0;
dev_t devno;
/* Alloc the device for driver */
if (0 != dev_major)
{
devno = MKDEV(dev_major, dev_minor);
result = register_chrdev_region(devno, 1, DEV_NAME);
}
else
{
result = alloc_chrdev_region(&devno, dev_minor, 1, DEV_NAME);
dev_major = MAJOR(devno);
}
/* Alloc for device major failure */
if (result < 0)
{
printk("%s driver can't get major %d\n", DEV_NAME, dev_major);
return result;
}
/* Initialize button_device structure and register cdev*/
memset(&button_device, 0, sizeof(button_device));
button_device.data = dev->dev.platform_data;
cdev_init (&(button_device.cdev), &button_fops);
button_device.cdev.owner = THIS_MODULE;
result = cdev_add (&(button_device.cdev), devno , 1);
if (result)
{
printk (KERN_NOTICE "error %d add %s device", result, DEV_NAME);
goto ERROR;
}
button_device.dev_class = class_create(THIS_MODULE, DEV_NAME);
if(IS_ERR(button_device.dev_class))
{
printk("%s driver create class failture\n",DEV_NAME);
result = -ENOMEM;
goto ERROR;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
device_create(button_device.dev_class, NULL, devno, NULL, DEV_NAME);
#else
device_create (button_device.dev_class, NULL, devno, DEV_NAME);
#endif
printk("S3C %s driver version %d.%d.%d initiliazed.\n", DEV_NAME, DRV_MAJOR_VER, DRV_MINOR_VER, DRV_REVER_VER);
return 0;
ERROR:
printk("S3C %s driver version %d.%d.%d install failure.\n", DEV_NAME, DRV_MAJOR_VER, DRV_MINOR_VER, DRV_REVER_VER);
cdev_del(&(button_device.cdev));
unregister_chrdev_region(devno, 1);
return result;
}
static int s3c_button_remove(struct platform_device *dev)
{
dev_t devno = MKDEV(dev_major, dev_minor);
cdev_del(&(button_device.cdev));
device_destroy(button_device.dev_class, devno);
class_destroy(button_device.dev_class);
unregister_chrdev_region(devno, 1);
printk("S3C %s driver removed\n", DEV_NAME);
return 0;
}
/*===================== Platform Device and driver regist part ===========================*/
static struct platform_driver s3c_button_driver = {
.probe = s3c_button_probe,
.remove = s3c_button_remove,
.driver = {
.name = "s3c_button",
.owner = THIS_MODULE,
},
};
static int __init s3c_button_init(void)
{
int ret = 0;
ret = platform_device_register(&s3c_button_device);
if(ret)
{
printk(KERN_ERR "%s: Can't register platform device %d\n", __FUNCTION__, ret);
goto fail_reg_plat_dev;
}
dbg_print("Regist S3C %s Device successfully.\n", DEV_NAME);
ret = platform_driver_register(&s3c_button_driver);
if(ret)
{
printk(KERN_ERR "%s: Can't register platform driver %d\n", __FUNCTION__, ret);
goto fail_reg_plat_drv;
}
dbg_print("Regist S3C %s Driver successfully.\n", DEV_NAME);
return 0;
fail_reg_plat_drv:
platform_driver_unregister(&s3c_button_driver);
fail_reg_plat_dev:
return ret;
}
static void s3c_button_exit(void)
{
platform_driver_unregister(&s3c_button_driver);
dbg_print("S3C %s platform device removed.\n", DEV_NAME);
platform_device_unregister(&s3c_button_device);
dbg_print("S3C %s platform driver removed.\n", DEV_NAME);
}
module_init(s3c_button_init);
module_exit(s3c_button_exit);
module_param(debug, int, S_IRUGO);
module_param(dev_major, int, S_IRUGO);
module_param(dev_minor, int, S_IRUGO);
MODULE_AUTHOR(DRV_AUTHOR);
MODULE_DESCRIPTION(DRV_DESC);
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:S3C24XX_button");
相關推薦
arm9+linux fl2440之按鍵驅動 plat_button.c
if( result ) { result = -EBUSY; goto ERROR1; } } return 0; ERROR1: kfree((unsigned char *)pdev
arm9+linux fl2440 的編譯驅動時遇到的問題
出現的問題: make -C /lib/modules/`uname -r`/build M=`pwd` modules make: *** /lib/modules/2.6.32-573.el6.x86_64/build: No such file o
linux核心之USB驅動分析
第一部分 USB驅動程式框架 app: ------------------------------------------- USB裝置驅動程式 // 知道資料含義 核心 -------------------------------------- USB匯流
4---linux中斷之按鍵查詢
上一篇中我們用了簡單的字元裝置驅動來點亮led燈,這一篇我們來搞一搞中斷。 為了引入中斷,我們先看一看這麼一個程式 ******led.c****** #include <linux/module.h> #include <linux/kernel.h> #
LINUX下ADC按鍵驅動程式
ADC按鍵驅動 Adc鍵盤原理圖如下,將串聯電阻之間分別用按鍵引出來與地相連,當按鍵按下時端電壓會發生改變。基本思想是在ADC驅動基礎上,對取樣電壓進行判斷,檢測是哪一個按鍵按下。 1. ADC驅動分析 在init()函式中,首先獲取adc的時鐘,並用clk_e
arm9+linux fl2440 實現RT3070無線網絡卡AP模式並使開發板接入Wifi上網
----------------------------------------------------------------------------------------------------
arm9+linux fl2440 GPS 資料採集和處理
======================================================================= 主機作業系統:centos 6.7
fl2440 platform 按鍵驅動的製作和測試
在led驅動的基礎上,繼續學習按鍵驅動 Makefile 1 2 obj-m := s3c_button.o 3 KERNEL_DIR := ~/fl2440/kernel/linux-3.0.54/ 4 PWD := $(shell pwd) 5 a
和菜鳥一起學android4.0.3原始碼之按鍵驅動短長按功能
第一:按鍵ADB除錯 通過使用adb shell getevent,可以得到如下裝置操作後的指令,具體表示的含義,可以參考網上很多的文章,這裡就不再敘述 這裡的0035和0036分別表示螢幕上的X座標和Y座標,後面的值表示具體的座標點
arm9+linux fl2440 第一次開機燒錄
一、燒錄相關軟體下載 USB轉串列埠相關晶片驅動 : CH341SER.ZIP J-link驅動 : Setup_JLinkARM_V410i.exe windows下t
linux基礎之spi驅動程式理解
1.1 重要的資料結構 1. spi_device 雖然使用者空間不需要直接用到spi_device結構體,但是這個結構體和使用者空間的程式有密切的關係,理解它的成員有助於理解SPI裝置節點的IOCTL命令,所以首先來介紹它。 在核心中,每個spi_device
android系統移植之按鍵驅動篇
平臺:MX53_QSB開發板 MX53_QSB開發板上一起有四個按鍵,分別為RESET,POWER,USER1,USER2。其中RESET為純硬體復位按鍵,無須軟體控制。POWER,USER1,USER2三個按鍵均需要程式控制。預設BSP包中將三個按鈕全設定為上升和下降沿
《5.linux驅動開發-第5部分-5.8.input子系統基礎之按鍵》
《5.linux驅動開發-第5部分-5.8.input子系統基礎之按鍵》 第一部分、章節目錄 5.8.1.什麼是input子系統 5.8.2.input裝置應用層程式設計實踐1 5.8.3.input裝置應用層程式設計實踐2 5.8.4.input子系統架構總覽1 5.8.5.input
Linux裝置驅動之button按鍵驅動學習與小結
button按鍵驅動,相對於前面的LED驅動來說。增加了中斷處理以及阻塞與非阻塞方式等新知識點。 先上學習的驅動程式碼。 核心:linux3.0 板子:fl2440 /***************************************************
linux驅動開發fl2440開發板按鍵驅動
——————————————————————————————————————— 主機作業系統:Centos 6.7交叉編譯器環境:arm-linux-gcc-4.5.4 開發板平臺: FL2440 Linux核心版本: linux-3.0 開發模組: LED_BUTTON郵
linux字元驅動之poll機制按鍵驅動
在上一節中,我們講解了如何自動建立裝置節點,實現一箇中斷方式的按鍵驅動。雖然中斷式的驅動,效率是蠻高的,但是大家有沒有發現,應用程式的死迴圈裡的讀函式是一直在讀的;在實際的應用場所裡,有沒有那麼一種情況,偶爾有資料、偶爾沒有資料,答案當然是有的。我們理想當然的就會想到,當
Linux裝置驅動工程師之路——platform型別按鍵驅動
Linux裝置驅動工程師之路——platform按鍵驅動 Y-Kee 轉載請註明來自於衡陽師範學院08電2 Y-Kee http://blog.csdn.net/ayangke,QQ:843308498 一 、重要知識點: 1.platform裝置模型
嵌入式Linux裝置驅動開發之:按鍵驅動程式例項
11.6 按鍵驅動程式例項 11.6.1 按鍵工作原理 高電平和低電平相接怎麼會變成低電平呢 就像你把電源正極的負極相連一樣會把電壓拉低。大電流會從高電平引腳流向低電平引腳,把高電平引腳拉低。 LED和蜂鳴器是最簡單的GPIO的應用,都不需要任何外部
linux設備驅動之misc驅動框架源碼分析(一)
linux驅動開發misc設備驅動 1、misc設備驅動框架源碼部分是由內核開發者實現提供的,主要是創建misc類和為驅動開發者提供misc_register函數,來進行創建misc設備。 這部分的源碼在/drvier/char/misc.c裏,代碼如下:/* * linux/drivers/c
linux設備驅動之misc驅動框架源碼分析(二)
linux驅動開發misc設備驅動1、misc_open函數分析 該函數在driver/char/misc.c中,misc.c是驅動框架實現的,這裏面的misc_Open函數是misc驅動框架為應用層提供的一個打開misc設備的一個接口。 1、首先我們要知道在misc.c中的misc_init函數