1. 程式人生 > >arm9+linux fl2440之按鍵驅動 plat_button.c

arm9+linux fl2440之按鍵驅動 plat_button.c

        if( result )
        {
            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函數