linux Gsensor驅動(bma250爲…

               

1 Gsensor驅動概述

 本文以Bma250驅動爲例子,詳細介紹Gsensor設計的一個模板。

 gsensor驅動在系統中的層次如下圖所示:

linux <wbr>Gsensor驅動(bma250爲例子)

圖中包含三個部分:hardware,driver, input

n        Hardware:其實我們可以認爲Gsensor也是一個I2C設備。整個Gsensor芯片分爲兩部分,一個是sensor傳感器,另一個是controller控制器,用於將sensor掛載在linux系統的I2C上。驅動程序則通過I2CGsensor做通信。

n        GsensorDriver:是駐留於操作系統中,爲gsensor hardware服務的一個內核模塊;它將gsensor hardware採集到的原始數據,進行降噪,濾波,獲得當前平板的空間狀態,並按照操作系統的要求,將這些信息通過input core上報給操作系統。

n        Input core: linux爲簡化設備驅動程序開發,而開發的一個內核子系統;發給input core的數據將提供給操作系統使用。

實際使用時,驅動按照一定的時間間隔,通過數據總線,獲取gsensor hardware採集到的數據,並按照操作系統的要求,將這些信息通過input core上報給操作系統。

2Gsensor驅動設計要求

gsensor驅動在系統中的層次,上有Input core,下有I2C,驅動需要通過I2C採集信息,並準確及時的上報數據至input core。驅動上報的數據,是被input core管理並被上層使用的,應符合input core和上層應用框架的要求;

2.1符合Input輸入子系統的設計規範

n        接口:Gsensor驅動,在設計上,不應自行決定是否上報,上報頻率等,應提供接口,供上層應用控制驅動的運行和數據上報:包括使能控制Enable上報時延delay等;通常通過sysfs文件系統提供,這部分實現,遵循標準的linux規範;

n        上報數據的方式:或者提供接口供上層訪問(eg:ioctl),或者掛接在系統子系統上,使用系統子系統的接口,供上層使用(eg: input core)

n        讀取數據的支持:應滿足讀取數據的要求,進行相應的配置;本文以i2c總線爲例,簡要說明在A1x平臺上,配置總線傳輸相關信息;

2.2I2c總線的配置

要使用i2c總線進行數據傳輸,需註冊i2c driver,創建i2c-client,以便使用i2c-adapter進行數據傳輸;

要成功註冊i2cdriver有兩種方式:

n        使用i2c_register_board_info:此方式,需要在系統啓動時,進行相關信息的註冊,不利於模塊化開發,現已不推薦;目前,在2.6內核上,還支持此方式,在3.0上已不再支持;

n        使用detect方式:在模塊加載時,進行檢測,在條件成立時,註冊i2c設備相關信息,創建i2c-client,並註冊i2c driver,執行probe操作;

 

需要說明的是,此兩種方式可共存,目前2.6就是這樣的;在共存時,以i2c_register_board_info信息爲更高優先級,在i2c_register_board_info已經佔用設備的前提下,內核發現設備被佔用,不會執行detect, 因而不會有衝突。

3gsensor模塊硬件說明

n        gsensor硬件,負責獲取gsensor傳感器所處的空間狀態信息,存放於fifo中,供主控使用,不同的硬件平臺,數據準備好後,告知主控的方式及主控獲取數據的方式略有不同。

n        告知主控的方式:gsensor作爲傳感器,本身無法區分哪些數據是應該上報的,哪些數據是無效的,它只能接受主控的控制,以主控主動查詢爲主;

n        主控獲取數據的方式:通過ahb, i2c,spi,usb等方式獲取都是可能的。以下以一種典型的硬件連接爲例,描述gsensor 傳感器,gsensor ic,主控之間的連接關係;

3.1gsensor硬件連接

linux <wbr>Gsensor驅動(bma250爲例子)

Gsensor在硬件上,只有i2c連接,這些連接信息,需要事先告知驅動,從而從指定的設備上讀取數據;這些連接信息,通過sysconfig1描述,在驅動中使用;

4 驅動設計

4.1 支持模組列表

A1x平臺上支持Gsensor列表如下:

支持的

模組

Chip ID

寄存器

Chip ID

I2C地址

I2C設備註冊

名稱

unuse_name

bma250

0x00

3

0x18

bma250

bma250

bma222

0x00

3

0x08

bma250

bma222

bma150

0x00

2

0x38

bma250

bma150

kxtik-1004

0x0f

0x05

0x0f

kxtik

kxtik

kxtj9-1005

0x0f

0x08

0x0f

kxtik

kxtik

dmard06

0x0f

0x06

0x1c

dmard06

dmard06

mma7660

0x4c

mma7660

mma7660

mma8452

0x0d

0x2a

SA0 = 0: 0x1c

mma8452

mma8452c

SA0 = 1: 0x1d

Mma8452d

afa750

0x37

0x3d or 0x3c

0x3d

afa750

afa750

mxc6225

0x15

mxc622x

mxc622x

4.2Gsensor配置

A1x的方案中,Gsensor的配置在sys_config1.fex文件中:

 [gsensor_para]

gsensor_used            =1         //是否使用gsensor

gsensor_name            = "bma250"  //名稱

gsensor_twi_id          =1          //使用哪組I2C

gsensor_twi_addr        =0x18       // I2C設備地址(7位地址)

 

 

4.3 關鍵數據結構

4.3.1 i2c_driver

static struct i2c_driverbma250_driver = {

             .class = I2C_CLASS_HWMON,

             .driver = {

                            .owner    =THIS_MODULE,

                            .name     = SENSOR_NAME,

             },

             .id_table   =bma250_id,

             .probe                   = bma250_probe,

             .remove                = bma250_remove,

             .address_list          = u_i2c_addr.normal_i2c,

};

在驅動程序中,靜態初始化i2c_driver結構體給bma250_driver變量,該變量完成gsensor驅動的主要工作,匹配設備名,設備的偵測等,文件操作結構體如上所示。

4.3.2 bma250_data

struct bma250_data{

             struct i2c_client *bma250_client;

             atomic_t delay;

             atomic_t enable;

             unsigned char mode;

             struct input_dev *input;

             struct bma250acc value;

             struct mutex value_mutex;

             struct mutex enable_mutex;

             struct mutex mode_mutex;

             struct delayed_work work;

             struct work_struct irq_work;

#ifdefCONFIG_HAS_EARLYSUSPEND

             struct early_suspend early_suspend;

#endif

};

代表了gsensor驅動所需要的信息的集合,用於幫助實現對採樣信息的處理。

4.3.3 delayed_work

struct delayed_work{

             struct work_struct work;

             struct timer_list timer;

};

Delayed_work一般用來觸發定時的操作,在定時時間到後,完成指定操作,通過不斷的觸發定時操作,實現按照一定頻率的執行指定操作;

4.3.4 bma250acc

struct bma250acc{

             s16        x,

                            y,

                            z;

} ;

用於記錄採樣時獲得的信息。

5 驅動流程解析

5.1模塊加載

static struct i2c_driverbma250_driver = {

             .class = I2C_CLASS_HWMON,

             .driver = {

                            .owner    =THIS_MODULE,

                            .name     = SENSOR_NAME,

             },

             .id_table   =bma250_id,

             .probe                   =bma250_probe,        //註冊完成時調用

             .remove                = bma250_remove,

             .address_list          = u_i2c_addr.normal_i2c,  //IIC地址

};

static int __initBMA250_init(void)

{            

             if(gsensor_fetch_sysconfig_para()){      //解析sys_config1.fex文件

                            printk("%s: err.\n", __func__);

                            return -1;

             }

 

             bma250_driver.detect = gsensor_detect;

             ret = i2c_add_driver(&bma250_driver);  //開始向IIC註冊

}

static void __exitBMA250_exit(void)

{

             i2c_del_driver(&bma250_driver);

}

module_init(BMA250_init);

module_exit(BMA250_exit);

 內核加載驅動模塊的時候將調用到BMA250_init()方法

n        初始化了i2c_driver結構體給bma250_driver變量,將用於將設備註冊到IIC。關鍵在於結構體中的probe()方法,註冊完成的時候將調用

n        調用gsensor_fetch_sysconfig_para()解析sys_config1.fex文件,讀取到IIC的地址,並賦值給u_i2c_addr.normal_i2c

n        調用i2c_add_driver開始向IIC註冊driver,完成註冊後將調用bm250_probe()方法

5.2bma250初始化工作-probe

static intbma250_probe(struct i2c_client *client,

                            const struct i2c_device_id *id)

{

             int err = 0;

             int tempvalue;

             struct bma250_data *data;

   ……

             data = kzalloc(sizeof(struct bma250_data), GFP_KERNEL);//bma250_data結構體申請內存

             

             tempvalue = 0;

             tempvalue = i2c_smbus_read_word_data(client,BMA250_CHIP_ID_REG);

 

             if ((tempvalue&0x00FF) == BMA250_CHIP_ID){

                            printk(KERN_INFO "Bosch Sensortec Device detected!\n" \

                                                        "BMA250 registered I2C driver!\n");

             } else if ((tempvalue&0x00FF) == BMA150_CHIP_ID){

                            printk(KERN_INFO "Bosch Sensortec Device detected!\n" \

                                                        "BMA150 registered I2C driver!\n");

             }

   ……

             i2c_set_clientdata(client, data);//將設備驅動的私有數據連接到設備client

             data->bma250_client = client;

             mutex_init(&data->value_mutex);

             mutex_init(&data->mode_mutex);

             mutex_init(&data->enable_mutex);

             bma250_set_bandwidth(client, BMA250_BW_SET);

             bma250_set_range(client, BMA250_RANGE_SET);

 

             INIT_DELAYED_WORK(&data->work,bma250_work_func);//創建工作隊列

             bma_dbg("bma: INIT_DELAYED_WORK\n");

             atomic_set(&data->delay,BMA250_MAX_DELAY);

             atomic_set(&data->enable,0);

             err = bma250_input_init(data); //Input子系統註冊

   …...

             err = sysfs_create_group(&data->input->dev.kobj,//創建sysfs接口

                                                                                      &bma250_attribute_group);

}

bma250_probe函數中,主要完成了以下幾件事:

n        爲驅動私有數據結構體bma250_data分配內存空間

n        讀取IIC chip id

n        將設備驅動的私有數據(bma250_data)連接到設備client(i2c_client)

n        創建工作隊列

n        bma250驅動註冊到linux input子系統

n        創建sysfs接口

下面對以上這些工作做詳細解釋,分配數據內存空間就不講了

5.2.1 讀取IICchip id

4.1的列表中,我們可以看到bma250chip ID寄存器爲0x00chip ID的值爲3。而上面代碼有兩個宏的定義:

#defineBMA250_CHIP_ID_REG  0x00

#defineBMA250_CHIP_ID      3

調用IIC接口i2c_smbus_read_word_data()讀取IICbma250chip id,返回的值tempvalue=3的時候,說明是正確的!

 

5.2.2 初始化工作隊列

先提一個問題,爲什麼要創建工作隊列?在前面的介紹中我們知道,sensor傳感器獲取數據後,將數據傳給controller的寄存器中,供主控去查詢讀取數據。所以這裏創建的工作隊列,就是在一個工作者線程,通過IIC不斷的去查詢讀取controller上的數據。

工作隊列的作用就是把工作推後,交由一個內核線程去執行,更直接的說就是如果寫了一個函數,而現在不想馬上執行它,想在將來某個時刻去執行它,那用工作隊列準沒錯.大概會想到中斷也是這樣,提供一箇中斷服務函數,在發生中斷的時候去執行,沒錯,和中斷相比,工作隊列最大的好處就是可以調度可以睡眠,靈活性更好。

上面代碼中我們看到INIT_DELAYED_WORK(&data->work,bma250_work_func),其實是一個宏的定義,在include/linux/workqueue.h中。bma250_work_func()就是我們定義的功能函數,用於查詢讀取Sensor數據的,並上報Input子系統,代碼如下:

static voidbma250_work_func(struct work_struct *work)

{

             struct bma250_data *bma250 = container_of((struct delayed_work*)work,

                                          struct bma250_data, work);

             static struct bma250acc acc;

             unsigned long delay =msecs_to_jiffies(atomic_read(&bma250->delay));//延時時間

 

             bma250_read_accel_xyz(bma250->bma250_client,&acc); //讀取Sensor數據

             input_report_abs(bma250->input, ABS_X,acc.x);

             input_report_abs(bma250->input, ABS_Y,acc.y);

             input_report_abs(bma250->input, ABS_Z,acc.z);

             bma_dbg("acc.x %d, acc.y %d, acc.z %d\n", acc.x, acc.y,acc.z);

             input_sync(bma250->input);

             mutex_lock(&bma250->value_mutex);

             bma250->value = acc;

             mutex_unlock(&bma250->value_mutex);

             schedule_delayed_work(&bma250->work,delay); //設定delay時間後再次執行這個函數

}

我們調用INIT_DELAYED_WORK()宏初始化了工作隊列之後,那麼什麼時候將執行我們定義的功能函數bma250_work_func()呢?那麼只需要調用schedule_delayed_work()即可在delay時間後執行功能函數。

在驅動設計中,我們在Sensor使能函數中調用schedule_delayed_work()開始啓動工作隊列,調用cancel_delayed_work_sync()停止工作隊列。而我們在上面的功能函數bma250_work_func()中也調用了schedule_delayed_work(),這樣功能函數將被重複調用,也就可以按照一個設定的頻率查詢讀取Sensor數據了。然後通過input系統提供的接口函數input_report_abs(),向input系統報告新的數據。

5.2.3input系統註冊

Gsensor作爲一個輸入設備,按照linux設計標準,需要將Gsensor驅動註冊到Input子系統中,註冊代碼如下:

static intbma250_input_init(struct bma250_data *bma250)

{

             struct input_dev *dev;

             int err;

 

      dev = input_allocate_device();

             if (!dev)

                            return -ENOMEM;

             dev->name = SENSOR_NAME;

             dev->id.bustype = BUS_I2C;

 

             input_set_capability(dev, EV_ABS, ABS_MISC);

             input_set_abs_params(dev, ABS_X,ABSMIN_2G, ABSMAX_2G, 0, 0);

             input_set_abs_params(dev, ABS_Y, ABSMIN_2G, ABSMAX_2G, 0,0);

             input_set_abs_params(dev, ABS_Z, ABSMIN_2G, ABSMAX_2G, 0,0);

             input_set_drvdata(dev, bma250);

      err = input_register_device(dev);

 

             bma250->input = dev;

}

就是由上面的代碼,完成了Gsensor驅動向Input子系統註冊,又三個步驟:

n        申請一個新的input設備,即爲一個input_dev申請內存空間

n        設置input設備支持的數據類型

n        input系統註冊

5.2.4 創建sysfs接口

爲什麼要創建sysfs接口?在驅動層創建了sysfs接口,HAL層通過這些sysfs接口,對Sensor進行操作,如使能、設置delay等。

5.2.4.1 sysfs接口函數的建立DEVICE_ATTR  

說道sysfs接口,就不得不提到函數宏 DEVICE_ATTR,原型在<include/linux/device.h> 

#define DEVICE_ATTR(_name,_mode, _show, _store) \

struct device_attributedev_attr_##_name = __ATTR(_name, _mode, _show, _store)

函數宏DEVICE_ATTR內封裝的是__ATTR(_name,_mode,_show,_stroe)方法:

n        _show:表示的是讀方法,

n        _stroe表示的是寫方法。

當然_ATTR不是獨生子女,他還有一系列的姊妹__ATTR_RO宏只有讀方法,__ATTR_NULL等等:

n        對設備的使用       DEVICE_ATTR   

n        對驅動使用              DRIVER_ATTR

n        對總線使用             BUS_ATTR 

n        對類別 (class) 使用  CLASS_ATTR

對於DEVICE_ATTR(_name,_mode, _show, _store)的四個參數,分別是名稱、權限位、讀函數、寫函數。其中讀函數和寫函數是讀寫功能函數的函數名。

如果你完成了DEVICE_ATTR函數宏的填充,下面就需要創建接口了。例如如下:

1)        

 staticDEVICE_ATTR(polling, S_IRUGO |S_IWUSR, show_polling, set_polling);
    static struct attribute*dev_attrs[] = {
          &dev_attr_polling.attr,
          NULL,
    };

 

  

2)       當你想要實現的接口名字是polling的時候,需要實現結構體structattribute *dev_attrs[]。其中成員變量的名字必須是&dev_attr_polling.attr。然後再封裝:

       static struct attribute_group dev_attr_grp ={
           .attrs =dev_attrs,
       };

3)       在利用sysfs_create_group(&pdev->dev.kobj,&dev_attr_grp);創建接口

      通過以上簡單的三個步驟,就可以在adb shell 終端查看到接口了。當我們將數據 echo 到接口中時,在上層實際上完成了一次 write 操作,對應到 kernel ,調用了驅動中的 “store”。同理,當我們cat 一個 接口時則會調用 “show” 。到這裏,只是簡單的建立了 android 層到 kernel 的橋樑,真正實現對硬件操作的,還是在 "show"  "store" 中完成的。

5.2.4.2 bma250驅動sysfs接口建立

Bma250驅動sysfs接口建立,按照5.2.4.1上面介紹的三個步驟來實現。

n        調用宏DEVICE_ATTR完成對功能函數的註冊

    

static DEVICE_ATTR(delay,S_IRUGO|S_IWUSR|S_IWGRP,

                            bma250_delay_show, bma250_delay_store);

static DEVICE_ATTR(enable,S_IRUGO|S_IWUSR|S_IWGRP,

                            bma250_enable_show, bma250_enable_store);

 

static struct attribute*bma250_attributes[] = {

             &dev_attr_delay.attr,

             &dev_attr_enable.attr,

             NULL

};

   對於bma250Gsensor,我們需要用到的接口是對Gsensor使能和設置delay。設置delay的功能函數——讀、寫分別是bma250_delay_showbma250_delay_store。使能的功能函數——讀寫分別是bma250_enable_showbma250_enable_store。這裏提到的四個函數,是需要在Gsensor驅動中實現的。

n        封裝bma250_attributes數據結構

static structattribute_group bma250_attribute_group = {

             .attrs = bma250_attributes

};

n        真正創建接口

bma250的初始化函數probe中——bma250_probe(),調用:

errsysfs_create_group(&data->input->dev.kobj,&bma250_attribute_group);

 

到此,完成了sysfs接口的創建,我們可以在根文件系統中看到/sys/class/input/input3/目錄,在該目錄下我們可以看到多個節點,其中就包含了enabledelay。我們以enable爲例子,可以有兩種方法完成對Gsensor的使能工作:

1)       直接使用shell命令

$cd/sys/class/input/input3

$echo 1 >enable

1寫到enable節點,那麼將“1”作爲參數調用到驅動的bma250_enable_store()方法,完成對Gsensor的使能工作。

2)       代碼寫設備節點

char buffer[20];

int len = sprintf(buffer,"%d\n", 1);

fd =open(“/sys/class/input/input3/enable”, O_RDWR);

write(fd, value,len)

 

5.3 讀取並上報數據

AndroidHAL層,通過對/sys/class/input/input3/enable節點的寫操作,使能Gsensor。調用到的方法是bma250_enable_store():

static ssize_tbma250_enable_store(struct device *dev,

                            struct device_attribute *attr,

                            const char *buf, size_t count)

{

             ……

                            bma250_set_enable(dev,data);

   ……

             return count;

}

static voidbma250_set_enable(struct device *dev, int enable)

{

             struct i2c_client *client = to_i2c_client(dev);

             struct bma250_data *bma250 = i2c_get_clientdata(client);

             int pre_enable =atomic_read(&bma250->enable);

 

             mutex_lock(&bma250->enable_mutex);

             if (enable) {

                            if (pre_enable ==0) {

                                          bma250_set_mode(bma250->bma250_client,

                                                                                                  BMA250_MODE_NORMAL);

                                          schedule_delayed_work(&bma250->work,

                                                        msecs_to_jiffies(atomic_read(&bma250->delay)));

                                          atomic_set(&bma250->enable,1);

                            }

                            

             }……     

}

我們看到了,在使能函數中,調用了schedule_delayed_work()開始工作隊列,於是調用了功能函數bma250_work_func()

static voidbma250_work_func(struct work_struct *work)

{

             struct bma250_data *bma250 = container_of((struct delayed_work*)work,

                                          struct bma250_data, work);

             static struct bma250acc acc;

             unsigned long delay =msecs_to_jiffies(atomic_read(&bma250->delay));

 

             bma250_read_accel_xyz(bma250->bma250_client,&acc);//讀取數據

             input_report_abs(bma250->input, ABS_X,acc.x);  //上報數據

             input_report_abs(bma250->input, ABS_Y,acc.y);

             input_report_abs(bma250->input, ABS_Z,acc.z);

             bma_dbg("acc.x %d, acc.y %d, acc.z %d\n", acc.x, acc.y,acc.z);

             input_sync(bma250->input);

             mutex_lock(&bma250->value_mutex);

             bma250->value = acc;

             mutex_unlock(&bma250->value_mutex);

             schedule_delayed_work(&bma250->work,delay); //繼續開始下一個工作隊列

}

在上面代碼中,調用bma250_read_accel_xyz()方法讀取Gsensor的三個數據,然後調用Input系統的接口函數input_report_abs()進行數據的上報。可以看到,當讀取一次數據後,繼續調用schedule_delayed_work()開始下一個工作隊列,由此,功能函數bma250_work_func()將會按照一個的頻率被執行。

那麼對於HAL層,將通過/dev/input/event3設備節點讀取到Gsensor數據。到此,Gsensor驅動的工作流程完畢。應該很好理解吧!

6 驅動調試

1)確保硬件各個管腳的連接順序正確;

2)上電,測試各個管腳信號的電壓正常,只有在保證硬件正常的情況下,進行軟件驅動調試,方可保證驅動能夠正常工作(該處最容易被很多軟件開發人員忽視,務必注意,方可節省大部分時間)

3)將串口打印信息打開,串口打印信息設置:在打包工具中的crane-win-v2\wboot\bootfs\linux目錄下的paramsparamsr兩個文件中的語句的最後加入loglevel=9即可。gsensor驅動中所有的打印信息打開,查看驅動程序的配置信息讀取狀態以及I2C的初始化狀態。

4)查看probe是否成功,如probe不成功,根據打印信息定位驅動的運行情況,是因爲什麼原因導致失敗。

5)當probe成功之後,gsensor沒反應,查看打印信息,是否enable,確保enable

6)查看i2c通信狀態,當串口打印信息顯示i2C通信失敗時,主要有以下兩個原因,一是硬件上的,各個信號線接觸不良,所以出現通信失敗時,檢查各引腳接觸情況和電壓情況。二是因爲I2C的地址不正確導致,因爲i2C地址爲7位地址,所以可能是因爲在配置的時候沒有移位或者是主控IC有多個I2C地址,導致地址不匹配。在已知i2C地址的情況下,可以通過嘗試的方法,進行I2C地址的匹配;在不知道I2C地址的情況下,可以通過掃描的方法查看在哪一個地址時,有應答,即可知道I2C通信地址,在將正確的地址填寫sysconfig配置文件中即掃描i2c地址的示例代碼如下所示:

static int goodix_iic_test(struct i2c_client *client)

{

      struct i2c_msg msg;

      int ret=-1;

      uint8_t data[0];

      int i;

      for(i =0; i<256;i++)

      {

      msg.flags = !I2C_M_RD;//寫消息

      msg.addr = i;

      msg.len = 1;

      msg.buf =data;                  

      

      ret=i2c_transfer(client->adapter,&msg,1);

      if(ret == 1)

      {

        printk("IIC TEST OK addr = %x\n",i);

        break;

      }

      mdelay(1000);

   }

      return ret;

}

 

 

若以上兩種方法都不能正確進行i2c傳輸,則打開i2c傳輸打印,查看傳輸打印狀態,在編譯服務器上,目錄爲workspace\exdroid\lichee\linux-2.6.36上,輸入命令:

make ARCH=arm menuconfig 選擇Device Drivers->I2Csupport->I2C Hardware Bussupport->SUN4I_IIC_PRINT_TRANSFER_INFO,輸入Y進入bus num id(accepatableinput:0,1,2)(new),輸入數值,,若希望打印信息,數值對應相應的IIC號,gsensorIC用的是第二組,因此選擇數值爲2,若不希望打印信息,輸入N退出保存即可。進行修改後,需要重新編譯打包之後才能生效。

linux <wbr>Gsensor驅動(bma250爲例子)

 

7)可使用adb工具查看驅動是否加載以及gsensor是否有反應,adb工具需要安裝設備對應的驅動。使用adb shell工具查看驅動是否存在於機器中以及驅動是否已經加載,以及gsensor之後是否有反應。同時可以作爲簡單的調試工具,修改好的驅動PUSH到機器中,重啓系統之後即可運行新的驅動,不用重新打包(配置文件內容除外)。使用到的命令如下所示:

adbshell   登錄設備的shell

adb push xx.ko/drv     將觸摸驅動通過adb工具push到機器中

cd   /drv  進入drv目錄

ls   *.ko  查看機器中已經有了那些驅動

lsmod  查看系統中已經加載了那些模塊

rmmod ** 卸載驅動(注:不用加後綴)

insmod **.ko  加載驅動

getevent 查看系統中已經註冊了那些input設備(當觸摸有效時,觸摸屏幕,會有相應的打印信息)

 


參考:

工作隊列:http://blog.csdn.net/zchill/article/details/7076561

SYsfs接口:http://blog.csdn.net/manshq163com/article/details/7848714         


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章