Android容量スクリーン——駆動デバッグの多点タッチドライバ分析編


本人用タッチパネルICはFocalTech社のft 5306で、i 2 cの容量スクリーンマルチタッチチップです.その全体的な駆動については、タッチスクリーンとボタン部分のコードについて説明します.その中で注意すべき点を説明します.
すべてのinputデバイスについて、inputイベントをレポートするときは、probeファイルでデバイスが送信するイベントタイプ、キータイプ、デバイスのプロパティ情報を設定します.その後、イベントを送信するときにprobeの設定に従ってイベントを送信します.そうしないと、無効無視と判定されます.
一、タッチパネル部分
1.デバイス構成
タッチパネルでサポートする必要があるイベントのタイプは、次の3つです.
__set_bit(EV_SYN, input_dev->evbit);//デバイス同期、タッチが完了するたびに同期イベントを送信し、タッチが完了したことを示す_set_bit(EV_ABS, input_dev->evbit);//絶対座標イベント、タッチパネルが送信する座標は毎回絶対座標であり、マウスの相対座標とは異なる_set_bit(EV_KEY, input_dev->evbit);//キーイベント、タッチするたびにBTN_TOUCHのキーイベント
タッチパネルでサポートする必要があるキーの種類
__set_bit(BTN_TOUCH, input_dev->keybit);//touchタイプキータッチパネル属性設定input_mt_init_slots(input_dev, CFG_MAX_TOUCH_POINTS);//レポート最大サポートポイント数input_set_abs_params(input_dev,ABS_MT_TOUCH_MAJOR, 0, PRESS_MAX, 0, 0);//タッチポイントを楕円と見なし、長軸の長さです.これはオプションで、正常な使用には影響しません.input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, ft5x0x_ts->x_max, 0, 0);//x座標値範囲input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, ft5x0x_ts->y_max, 0, 0);//y座標取値範囲
2.イベント送信
タッチが完了するたびに、今回のタッチの完了を示す同期イベント(EV_SYN)が送信されることが知られている.では、マルチタッチのスクリーンイベント送信には、2つの方法があります.1つは、イベントが同期するたびに複数のポイントを含むことです.1つは、イベントが同期するたびに1つのポイントのみを含むことです.
まず複数の点を含む
static void ft5x0x_report_value(struct ft5x0x_ts_data *data)  
{  
    struct ts_event *event = &data->event;  
    int i;  
    int uppoint = 0;    //         
  
    for (i = 0; i touch_point; i++)  //              
    {  
        input_mt_slot(data->input_dev, event->au8_finger_id[i]);  //    ID  
          
        if (event->au8_touch_event[i]== 0 || event->au8_touch_event[i] == 2)  //       
        {  
            input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,  true);  //      
            input_report_abs(data->input_dev,ABS_MT_POSITION_X,event->au16_x[i]); //x       
            input_report_abs(data->input_dev, ABS_MT_POSITION_Y,event->au16_y[i]);    //y    
            input_report_abs(data->input_dev,ABS_MT_TOUCH_MAJOR,event->pressure); //         
        }  
        else  
        {  
            uppoint++;                              //    ,             
            input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,false);   //        
        }  
          
  
    }  
  
        if(event->touch_point == uppoint)              
        {  
            input_report_key(data->input_dev, BTN_TOUCH, 0); //           BTN_TOUCH       
  
        }  
        else  
        {  
            input_report_key(data->input_dev, BTN_TOUCH, event->touch_point > 0);//       ,  BTN_TOUCH         
  
        }  
        input_sync(data->input_dev); //sync       
          
}  

 
次に、同期ごとに1つのポイントのみが送信されます.
static ft5x0x_report_value(struct ft5x0x_ts_data *data)  
  
{  
    struct ts_event *event = &data->event;  
    int i;  
  
    for (i = 0; i touch_point; i++)  //              
    {  
        input_mt_slot(data->input_dev, event->au8_finger_id[i]);  //    ID  
        if (event->au8_touch_event[i]== 0 || event->au8_touch_event[i] == 2)  //       
        {  
            input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,  true);  //      
            input_report_abs(data->input_dev,ABS_MT_POSITION_X,event->au16_x[i]); //x       
            input_report_abs(data->input_dev, ABS_MT_POSITION_Y,event->au16_y[i]);    //y    
            input_report_abs(data->input_dev,ABS_MT_TOUCH_MAJOR,event->pressure); //         
        }  
        else  
        {  
            input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,false);   //      
        }  
          
  
        input_mt_report_pointer_emulation(input_dev, true);//       ,           。  
        input_sync(data->input_dev); //sync       
          
    }  
}  

どちらの方法も可能ですが、上記のものを選ぶことをお勧めします.効率が高いです. 
二、タッチボタン部分
タッチキーの送信には、androidが提供するvirtualkey'sアーキテクチャ方法と、key eventを直接報告する方法の2つの方法に分けることができる.ちょっと見てみましょう
1.key eventメソッドのレポート
Probeにサポートされているボタンタイプを追加すると、本人用のタッチパネルに3つのボタンがあるので
レポートサポートイベントタイプ
__set_bit(EV_SYN, input_dev->evbit); 
__set_bit(EV_KEY, input_dev->evbit);サポートされているキーのレポート
__set_bit(KEY_HOME, input_dev->keybit);    __set_bit(KEY_BACK, input_dev->keybit);   __set_bit(KEY_MENU, input_dev->keybit);
タッチパネルの3つのボタンに対応する座標
(KEY_BACK)  120:1400   (KEY_HOME) 360:1400(KEY_MENU)  500:1400
key eventのレポート方法は簡単です.対応するkeyとデバイスの同期syncをレポートすればいいです.
static void ft5x0x_report_value(struct ft5x0x_ts_data *data)  
{  
    struct ts_event *event = &data->event;  
    int i;  
    for (i = 0; i touch_point; i++)  
    {  
        if (event->au16_y[i]==1400)  
        {  
            if(event->au8_touch_event[i]== 0 || event->au8_touch_event[i] == 2)  
            {  
  
                switch(event->au16_x[i])  
                {  
                case 120:  
                    input_report_key(data->input_dev, KEY_BACK, 1);  
                    break;  
                case 360:   
                    input_report_key(data->input_dev, KEY_HOME, 1);  
                    break;  
                case 500:   
                    input_report_key(data->input_dev, KEY_MENU, 1);  
                    break;    
                default: break;  
                }  
                  
            }  
            else  
            {  
  
                switch(event->au16_x[i])  
                {  
                case 120:  
                    input_report_key(data->input_dev, KEY_BACK, 0);  
                    break;  
                case 360:   
                    input_report_key(data->input_dev, KEY_HOME, 0);  
                    break;  
                case 500:   
                    input_report_key(data->input_dev, KEY_MENU, 0);  
                    break;    
                default: break;  
                }  
                  
            }  
            input_sync(data->input_dev);  
            return;  
        }  
}  

この方法にはバグがあり,イベント送信上,システムはタッチスクリーン送信のボタンとは考えず,システムのタッチスクリーン振動フィードバックは機能しない.これは標準的なandroidタッチデバイスの標準に合致しない.具体的にどのように私を破って比较して野菜は方法を探し当てていないで、大神达は谁が知っていて破れます.
2.virtualkeysメソッド
virtualkeysはandroidが提供するアーキテクチャで使いやすく、おすすめです.ダイレクトコード
static ssize_t ft5x06_virtual_keys_show(struct kobject *kobj,       //       
                    struct kobj_attribute *attr, char *buf)  
{  
    return sprintf(buf,  
        __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":120:1400:8:8"   //   :  :      x  :      y  :     :       
        ":" __stringify(EV_KEY) ":"  
                    __stringify(KEY_HOME) ":360:1400:8:8"  
        ":" __stringify(EV_KEY) ":"  
                    __stringify(KEY_MENU) ":500:1400:8:8"  
        "
");   }      static struct kobj_attribute ft5x06_virtual_keys_attr = {       .attr = {           .name = "virtualkeys.Ft5x0x_Touch_Screen",  // virtualkeys.               .mode = S_IRUGO,       },       .show = &ft5x06_virtual_keys_show,   };      static struct attribute *ft5x06_properties_attrs[] = {       &ft5x06_virtual_keys_attr.attr,       NULL,   };      static struct attribute_group ft5x06_properties_attr_group = {       .attrs = ft5x06_properties_attrs,   };      static void ft5x06_virtual_keys_init(void)   {       struct kobject *properties_kobj;       int ret;          properties_kobj = kobject_create_and_add("board_properties", NULL);// board_properties          if (properties_kobj)           ret = sysfs_create_group(properties_kobj,// /sys/board_properties/virtualkeys.Ft5x0x_Touch_Screen                &ft5x06_properties_attr_group); //  cat /sys/board_properties/virtualkeys.Ft5x0x_Touch_Screen        if (!properties_kobj || ret)           pr_err("failed to create board_properties
");   }  

 
そしてft 5 x 06_virtual_keys_Init()はタッチスクリーンのinitまたはprobe関数に追加され、タッチキーが使用できます.
 
三、タッチスクリーン駆動プロセス
i 2 cにプラットフォーム初期化コードを追加
static struct ft5x0x_platform_data  ft5x0x_platform_i2c_data = {  
    .x_max=540,  
    .y_max=960,  
    .irq= SABRESD_CHARGE_FLT_1_B, //      
    .reset=SABRESD_DISP0_RST_B,   //      
};  

タッチパネル駆動初期化
static int __init ft5x0x_ts_init(void)  
{  
    int ret;  
    ret = i2c_add_driver(&ft5x0x_ts_driver);  
    if (ret) {  
        printk(KERN_WARNING "Adding ft5x0x driver failed "  
               "(errno = %d)
", ret);       } else {           pr_info("Successfully added driver %s
",                      ft5x0x_ts_driver.driver.name);       }       return ret;   }  

probe関数
#define VIRTUAL_LI      0  
#define EVENT_LI        1  
#define TOUCH_KEY       VIRTUAL_LI    
static int ft5x0x_ts_probe(struct i2c_client *client,  
               const struct i2c_device_id *id)  
{  
    。。。。。。。。。。  
    ft5x0x_ts = kzalloc(sizeof(struct ft5x0x_ts_data), GFP_KERNEL);//        
  
    ..........  
    i2c_set_clientdata(client, ft5x0x_ts);      i2c     
  
             
    ft5x0x_ts->irq = client->irq;   
    ft5x0x_ts->client = client;  
    ft5x0x_ts->pdata = pdata;  
    ft5x0x_ts->x_max = pdata->x_max - 1;  
    ft5x0x_ts->y_max = pdata->y_max - 1;  
    ft5x0x_ts->pdata->reset = FT5X0X_RESET_PIN;  
    ft5x0x_ts->pdata->irq = ft5x0x_ts->irq;  
.....................  
    err = request_threaded_irq(client->irq, NULL, ft5x0x_ts_interrupt,   //          
                   IRQF_TRIGGER_FALLING, client->dev.driver->name,  
                   ft5x0x_ts);  
    。、、、、、、、、、、、、  
    input_dev = input_allocate_device();//      
...........................................  
    __set_bit(EV_SYN, input_dev->evbit);  //      event    
    __set_bit(EV_ABS, input_dev->evbit);  
    __set_bit(EV_KEY, input_dev->evbit);  
    __set_bit(BTN_TOUCH, input_dev->keybit);  
#if TOUCH_KEY == EVENT_LI               //    event key     
    __set_bit(KEY_HOME, input_dev->keybit);     
    __set_bit(KEY_BACK, input_dev->keybit);    
    __set_bit(KEY_MENU, input_dev->keybit);  
#endif    
    input_mt_init_slots(input_dev, CFG_MAX_TOUCH_POINTS);   //      
    input_set_abs_params(input_dev,ABS_MT_TOUCH_MAJOR,  
                 0, PRESS_MAX, 0, 0);  
    input_set_abs_params(input_dev, ABS_MT_POSITION_X,  
                 0, ft5x0x_ts->x_max, 0, 0);  
    input_set_abs_params(input_dev, ABS_MT_POSITION_Y,  
                 0, ft5x0x_ts->y_max, 0, 0);  
  
      
  
    input_dev->name ="Ft5x0x_Touch_Screen";//lijianzhang  
    err = input_register_device(input_dev);         //    input    
    。。。。。。。。。。。  
#if TOUCH_KEY == VIRTUAL_LI     //            
  
    ft5x06_virtual_keys_init();       
#endif  
。。。。。。。。。。。。。。。。。。。。。  
}  

 
わりこみしょり
static irqreturn_t ft5x0x_ts_interrupt(int irq, void *dev_id)  
{  
    struct ft5x0x_ts_data *ft5x0x_ts = dev_id;  
    int ret = 0;  
    disable_irq_nosync(ft5x0x_ts->irq);  
    ret = ft5x0x_read_Touchdata(ft5x0x_ts); //      
    if (ret == 0)  
        ft5x0x_report_value(ft5x0x_ts);//      
  
    enable_irq(ft5x0x_ts->irq);  
  
    return IRQ_HANDLED;  
}  

 
イベントのレポート
static void ft5x0x_report_value(struct ft5x0x_ts_data *data)  
{  
    struct ts_event *event = &data->event;  
    int i;  
    int uppoint = 0;  
  
    /*protocol B*/    
    for (i = 0; i touch_point; i++)  
    {  
#if TOUCH_KEY == EVENT_LI       //     key event    
        if (event->au16_y[i]==1400)  
        {  
            if(event->au8_touch_event[i]== 0 || event->au8_touch_event[i] == 2)  
            {  
  
                switch(event->au16_x[i])  
                {  
                case 120:  
                    input_report_key(data->input_dev, KEY_BACK, 1);  
                    break;  
                case 360:   
                    input_report_key(data->input_dev, KEY_HOME, 1);  
                    break;  
                case 500:   
                    input_report_key(data->input_dev, KEY_MENU, 1);  
                    break;    
                default: break;  
                }  
                  
            }  
            else  
            {  
  
                switch(event->au16_x[i])  
                {  
                case 120:  
                    input_report_key(data->input_dev, KEY_BACK, 0);  
                    break;  
                case 360:   
                    input_report_key(data->input_dev, KEY_HOME, 0);  
                    break;  
                case 500:   
                    input_report_key(data->input_dev, KEY_MENU, 0);  
                    break;    
                default: break;  
                }  
                uppoint++;  
                  
            }  
            input_sync(data->input_dev);  
            return;  
        }  
  
#endif  
      
        input_mt_slot(data->input_dev, event->au8_finger_id[i]);  
          
          
        if (event->au8_touch_event[i]== 0 || event->au8_touch_event[i] == 2)  
        {  
            input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,  true);  
            input_report_abs(data->input_dev,ABS_MT_POSITION_X,event->au16_x[i]);     //lijianzhang  
            input_report_abs(data->input_dev, ABS_MT_POSITION_Y,event->au16_y[i]);  
            input_report_abs(data->input_dev,ABS_MT_TOUCH_MAJOR,event->pressure);  
        }  
        else  
        {  
            uppoint++;  
            input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,  false);  
        }  
          
  
    }  
  
        if(event->touch_point == uppoint)  
        {  
            input_report_key(data->input_dev, BTN_TOUCH, 0);  
        }  
        else  
        {  
            input_report_key(data->input_dev, BTN_TOUCH, event->touch_point > 0);  
        }  
        input_sync(data->input_dev);  
          
}  

 
ここで駆動プロセスを簡単に説明し、肝心なコードが貼られています.デバイスに関するコードはメーカーからあまり参考価値がない.
Android inputのプロセス分析から、駆動コンパイルが完了した後、タッチスクリーンを動作させるには、タッチスクリーンプロファイル(idcファイル、タッチスクリーンのいくつかの属性を構成するために使用される)、keylayoutファイル(klファイル、アンドロイドレベルのキーマッピングファイル)、characterMapファイル(kcmファイル、アンドロイドレベルの文字マッピングファイル)この3つのファイルを見てみましょう
1.タッチパネルプロファイル
ファイルが存在するディレクトリへのアクセス順序:
まずはANDROID_ROOT/usr/idcディレクトリは、適切な名前のファイルを探して完全なパス名を返します.見つからない場合はANDROIDからDATA/system/devices/idc次は探して、ここANDROID_ROOTは一般的に/systemディレクトリ、ANDROID_を指しますDATAは一般に/dataディレクトリを指す.
ファイル名の検索順はまずVendor_XXXX_Product_XXXX_Version_XXXX.idc、そしてVendor_XXXX_Product_XXXX.idc最後はDEVICE_NAME.idc
まとめてみると、Androidは入力デバイスのプロファイルを開くために順次アクセスします.
/system/usr/idc/Vendor_XXXX_Product_XXXX_Version_XXXX.idc
/system/usr/idc/Vendor_XXXX_Product_XXXX.idc
/system/usr/idc/DEVICE_NAME.idc
/data/system/devices/idc/Vendor_XXXX_Product_XXXX_Version_XXXX.idc
/data/system/devices/idc/Vendor_XXXX_Product_XXXX.idc
/data/system/devices/idc/DEVICE_NAME.idc

ドライバにはバージョン番号などの情報は書かれていませんので、デバイスがアクセスするidcファイルは/system/usr/idc/DEVESICE_になります.NAME.idc.そこで、このディレクトリの下にファイルFt 5 x 0 x_を追加します.Touch_Screen.idc.idcファイルの内容については、以下は私が使用しているidcファイルの具体的な内容です.参考までに.
touch.deviceType = touchScreen  
touch.orientationAware = 1  
  
touch.size.calibration = none  
touch.orientation.calibration = none   

                                
2.key layoutファイル
key layoutファイルはandroidレベルのキーマッピングファイルであり,このファイルによりkernelから送信されたキー機能をユーザが再定義することができる.つまり、kernelはホームキーを送信し、ここでbackキーや他のキーにマッピングすることができます.一般的にはこのファイルは変更されませんので、デフォルトのプロファイルを完全に使用できますか?
このファイルのアクセス順
/system/usr/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl
/system/usr/keylayout/Vendor_XXXX_Product_XXXX.kl
/system/usr/keylayout/DEVICE_NAME.kl
/data/system/devices/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl
/data/system/devices/keylayout/Vendor_XXXX_Product_XXXX.kl
/data/system/devices/keylayout/DEVICE_NAME.kl
/system/usr/keylayout/Generic.kl
/data/system/devices/keylayout/Generic.kl

ここは修正しなくてもいいので変更しなくてもいいです
3.characterMapファイル
characterMapファイルはandroidレベルの文字マッピングファイルです.例えば、「e」キーを押して、普段は「e」を表し、shift+「e」は「E」を表し、casplk+「e」は「E」を表し、alt+「e」は別の意味を表す可能性があります.このプロファイルは、これらのマッピングを行うものです.一般的にこの書類も修正する必要はありません.デフォルトを使えばいいです.このファイルのアクセス順:
/system/usr/keychars/Vendor_XXXX_Product_XXXX_Version_XXXX.kcm
/system/usr/keychars/Vendor_XXXX_Product_XXXX.kcm
/system/usr/keychars/DEVICE_NAME.kcm
/data/system/devices/keychars/Vendor_XXXX_Product_XXXX_Version_XXXX.kcm
/data/system/devices/keychars/Vendor_XXXX_Product_XXXX.kcm
/data/system/devices/keychars/DEVICE_NAME.kcm
/system/usr/keychars/Generic.kcm
/data/system/devices/keychars/Generic.kcm
/system/usr/keychars/Virtual.kcm
/data/system/devices/keychars/Virtual.kcm

ここまで来たらタッチパネルが完成したので、焼き書きしてから正常に使えるはずです.
ここでは小さなテクニックを共有します.geteventというツールは、/dev/input/ディレクトリの下でこのコマンドを使用すると、まずシステム内のすべてのinputデバイスの説明を得ることができます.それから、kernelが送信したすべてのinputイベントを得ることができます.ドライバを書き終わったら、このコマンドで送信したイベントを印刷して、ドライバが正しいかどうかを見ることができます.