キーボードはすべてのドライバーの中で最も単純ですが、これにはドライバーの基本的なフレームワークが含まれており、今後他の複雑なドライバーを詳細に研究するうえで非常に役立ちます。開発クエリ方式を採用しています。 1.カーネルモジュールの登録と失効
モジュールのロード時に、カーネルモジュール登録機能が最初に実行されます。その機能には、デバイスのカーネル登録および変数の初期化が含まれます。
静的INT頭部、尾部、
INT _init Keypad_init(ボイド)
{
INT結果、
結果= register_chrdev(KEY_LED_MAJOR、KEY_LED_NAME、& Keypad_fops);
Keypad_clear();
init_waitqueue_head(&キュー);
prink("%S%S \\初期化N"、KEY_LED_NAME、KEY_LED_VERSION); //戻り0 prinfの
を使用することはできません。
}
module_init(Keypad_init); //ロードモジュール
ボイド_exit Keypad_cleanup(ボイド)
{
del_timer(&タイマー);
unregister_chrdev(KEY_LED_MAJOR、KEY_LED_NAME);
prink("。キーパッドドライバ\\ n"除去;);}
module_exit(Keypad_cleanup);. //モジュールをアンロード
つの仮想ファイル・システムおよびハードウェアインターフェースドライバ
静的構造体file_operationsはKeypad_fops = {
インターフェースの完了は、これらのいくつかを定義することである後
; Keypad_releaseを、
} Keypad_open、読み取り
:オープンKeypad_read、
投票を:Keypad_poll、
fasync:Keypad_fasync、放出
いくつかの特定の機能の実装!それでは、次のステップに進みましょう実際には難しいことではないと思いますか。早く幸せにしないでください?これらの機能が実装されるとき、カーネルタイマー、待ち行列の特定の実装(ブロッキングモード)、非同期メソッドの特定の実装技術、および循環待ち行列を含む多くの技術が関係します。あなたはそんなに多くの技術を見ることに興奮していますか?私はあなたにそれを共通の方法で説明するつもりです。
(詳細ログインへようこそ:qiangren.blog.edu.cn)
3。デバイスオープン操作インターフェース機能の実装(Keypad_open)
デバイスオープンは一般的に2つの主要な操作を含み、1つはデバイスを完成させることです初期化は、2つのデバイスは、基準カウンタ1
静的INT Keypad_open(構造体iノード* iノード、構造体のファイル*の財投)
{
read_xy()に追加され、
try_module_get(THIS_MODULE); //この関数2.4系カーネルとは異なり、Linux 2.6系カーネル用に追加された、関数はカウンタの値に1を加えたものです。戻り値0;
}
static void read_xy(void)
{
new_data(); //キー値関数を取得する
keypad_starttimer(); //カーネルタイマーを開いて、一定のサイクルタイムでキーボードの新しい変更を取得する
}
キーボードキー値取得関数の次の実装read_xy()
Mainそれは、このようなの#define kEY_CSなどの特定のハードウェアデバイス、(*(揮発性符号なしshort *)(ここでは0xf820000))によっても異なるはずですに従って定義することができます前に、読み出しアドレスに対応するkEY_CS(から!
読みます入力されたキー値はbuf []キャッシュに格納され、リングバッファのライトポインタは先頭、リードポインタは末尾になります。
/////////////////////////////////////キーボードイベントデータ構造定義///////////////////////////////////////
typedef struct {
ulong status; //ボタンの値
ulong click; ////リングバッファのサイズを定義するために使用されるマクロ定義をBUFSIZE
静的ボイドNEW_DATA、ボタンが押されたか否か、発現は、0は
} KEY_EVENT
静的KEY_EVENT cur_data、BUF [BUFSIZE]がないことを示し(void)
{{if((KEY_CS&0xff)!= 0xff)//KEY_CSアドレスからデータを読み取ります。0があれば、ボタンが押されたことを意味します(ここではハードウェア回路)アクティブロー)
スイッチ(KEY_CS&0xff){
case〜KEY0&0xff:
cur_data.status = 1; ///////1が押されました
ブレークの下で、
ケースを
〜KEY1&は0xff:
cur_data.status = 2; //2を破る
押され、
/////////他の人が追加、理解? ?
}
cur_data.click = 1;
} else if(KEY_CS&0xff == 0xff){
cur_data.click = 0;
cur_data.status = 0;}
}
if(head!= tail){////////循環キューバッファの適用はここから始まります^ _ ^
int last = head--;
if (last< 0)////////頭に到達した場合、ループキューを実装するためにキューの最後にジャンプします。
last = BUFSIZE-1;
}
//////キー情報は循環キューバッファに格納されます
buf [head] = cur_data;
if(++ head == BUFSIZE)
head = 0;
if(head == tail&;&#038;尾++ = BUFSIZE)
尾= 0;
IF(fasync)
kill_fasync(&#038; fasyc、SIGIO、POLL_IN);
wake_up_interruptible(&#038;キュー);
} < BR>今日はあなたへの書き込みを最初に、次のセクションでは、起動されますので、お楽しみに
次我々は
IVを達成するために、いくつかの他のファイルのインタフェース機能を紹介する。最初に導入され、シャットダウン機能keypad_release()、なぜ最初に紹介しますか?理由は単純ですが、それは、比較的簡単なもので、私たちは次のウォームアップ運動をさせ、これまで導入後、より複雑な機能をご紹介していきます、あなたはああを操作
主な成果があるシャットダウン立つことはできないはずです。デバイスの非同期をオフにします通知、装置カウンタがデクリメントされ、タイマ割り込み信号
静的INT Keypad_release(構造体iノード* iノード、構造体)Keypad_fasync
ログイン{(-1、財投、0)を削除し、
module_put(THIS_MODULE)を;
del_timer(& timer);
return 0;
}
5.デバイス読み取り操作インターフェース関数の実装Keypad_read()
主な機能は、バッファからキー値を読み取ることです。 get_Data()を呼び出して関数をコピーすることによって、ユーザデータ領域
静的ssize_tのKeypad_read(構造体ファイル*の財投、CHAR * BUF、ssize_tのカウント、loff_tのL *)
{<鍵copy_to_user()を実装BR> DECLEARE_WAITQUEUEは(現在、待つ);
ULONG out_buf [2]; //キューを宣言し、現在のプロセスが待ちキュー
KEY_EVENTトンに追加され
場合(ヘッド==尾)//現在の循環キュー内のデータを読み取ることができません。
{
if(filp-> f_flags& O_NONBLOCK)//ユーザーが非プラグインの読み込み方法が_EAGAINを返す
;
add_wait_queue(&#038;キュー、&#038;待つ); //待ち列現在のプロセス
の電流>に追加されます。状態= TASK_INTERRUPTIBLE; //現在の設定プロセスの状態
while((head == tail)&&!signal_pending(current))//ループキューにデータがなく、現在のプロセスがシグナルの影響を受けない場合
shedule(); //プロセススケジューリング
電流 - >状態= TASK_INTERRUPTIBLE;
}
電流 - >状態= TASK_RUNNING;
remove_wait_queue(&#038;キュー、&#038;待つ);
IF(ヘッド== tail)
return count;
t = get_data(); //get_data()関数を呼び出してバッファ内のデータを取得します。これについては、後で詳しく説明します。
out_buf [0] = tステータスは、
copy_to_user; [1] = t.click out_buf
(bufは、&#038; out_buf、はsizeofを(out_buf)); //ユーザデータ領域にコピーされたキーは、カウントを返す
取得します。<この関数の機能は、定義した循環キューバッファから必要なキー値を読み込むことです。それであなたが理解すればそれは実際には非常に簡単ですリングキューの原則は、ここでこれ以上の説明はありません、あなたはデータ構造の一般的な知識を持っているべきです。
KEY_EVENT get_data(void)
== BUFSIZE)
tail = 0;
return buf [last];
}
あなたが上記を理解することができれば、次の研究に入ることができます、主にカーネルタイマーを紹介ブロッキングI /O、ポーリングシステムコール、非同期通知モードを実装するために使用する、待機キューを使用する、紹介の後、ファイル
オペレーティングシステムを使用するためのアプリケーションインスタンスを提供します。私たちが書いたキーボードドライバに関しては、それらは基本的に同じです。ナンセンスな話をしましょう、私たちはすぐに私たちの素晴らしいドライブ開発を始めます!