2017-01-05 17 views
-1

私はLinuxのデバイスドライバにはうってつけですので、私に同行してください。私はi2cドライバ(クライアント)を実装しようとしています。私はinsmod.probeが呼び出され(デバイスツリーのエントリのため)、.probeではデバイスに読み書きできます。すばらしいです。i2cドライバは他のキャラクタデバイスドライバと同様に実装する必要がありますか?

しかし、私はユーザー空間からドライバへの読み取り/書き込みを開始できる必要があります。これを行うには、i2cドライバを他のcharデバイスドライバのように整形する必要がありますか? file_operations構造体の意味で、ユーザー空間はopenclosereadwrite、およびioctlsとなりますか?

私が見たすべてのi2cクライアントの例では、誰も私が言及したこれらのことを実装していないので、私は尋ねています。私はfile_operations構造体が設定されていないと、彼らがユーザー空間からどのように呼び出しを開始したのか疑問に思っています。おそらく誰もそれを言及していないことは明らかでしたが、わかりません... i2cはこれを必要としないプラットフォームデバイスドライバと呼ばれているのでしょうか?誰かがそれが自分自身を推測するのを助けると確信できるなら。

私が求めていることを理解していれば、残りの部分は無視してください。あなたは私の質問について混乱している場合は、ここで私が求めているものを、より具体的な説明は次のとおりです。

私が今持っている:以下の要素がで追加する必要がある場合

static int device_probe(struct i2c_client   *client, 
         const struct i2c_device_id *id) 
{ 
    struct device  *dev = &client->dev; 
    struct device_data *data; 

    /* Check the functionality of the i2c-adapter for smbus byte read/write */ 
    if (!i2c_check_functionality(client->adapter, 
           I2C_FUNC_SMBUS_BYTE_DATA)) 
    { 
     printk(KERN_ALERT "%s %d: device required i2c functionality is not supported\n", __func__, __LINE__); 
     return -ENODEV; 
    } 

    /* Allocate memory to hold the device data 
    * Using devm_kzalloc so do not have to worry about kfree */ 
    data = devm_kzalloc(dev, sizeof(struct device_data), GFP_KERNEL); 
    if (dev == NULL) 
    { 
     printk(KERN_ALERT "%s %d: no memory\n", __func__, __LINE__); 
     return -ENOMEM; 
    } 

    /* Record the pointer to current client */ 
    data->device_i2c_client = client; 

    /* Set the client's data field to point to device-specific data struct */ 
    i2c_set_clientdata(client, data); 

    /* Add the device-specific data struct to our collection of device client devices */ 
    device_data_tbl[id->driver_data] = data; 

    /* Do a read, test the access */ 
    device_read(); 

    return 0; 
} 

static int device_remove(struct i2c_client *client) 
{ 
    return 0; 
} 


int device_read(uint8_t    device_device_id, 
       uint16_t const  dev_reg_addr, 
       uint8_t *const  read_val) 
{ 
    /* some read access */ 
} 

static struct i2c_device_id device_idtable[] = { 
    { "si5342", 0 }, 
    { }, 
}; 
MODULE_DEVICE_TABLE(i2c, device_idtable); 

static struct i2c_driver device_driver = { 
    .driver = { 
    .name = device_DRIVER_NAME, 
     .owner = THIS_MODULE 
    }, 
    .id_table = device_idtable, 
    .probe  = device_probe, 
    .remove  = device_remove, 
}; 

static int __init device_driver_init(void) 
{ 
    return i2c_add_driver(&device_driver); 
} 
module_init(device_driver_init); 


static void __exit device_driver_exit(void) 
{ 
    return i2c_del_driver(&device_driver); 
} 
module_exit(device_driver_exit); 

が疑問に思います

static struct file_operations oxdrv_fops = 
{ 
    .owner = THIS_MODULE, 
    .release = device_release, 
    .open = device_open, 
    .unlocked_ioctl = device_ioctl 
}; 

/* Associated function definitions: device_open, device_ioctl, etc */ 

alloc_chrdev_region(); 
cdev_init(); 
+0

はい、それは明らかです。 I2C * host *と* client *の間では、特別に設計されたAPIを介して通信が行われるため、ドライバはこれを必要としません。スレーブへのユーザー空間通信のためには、ただ1つのドライバしか実装しておらず、明らかにその必要はありません。 – 0andriy

+0

申し訳ありませんが、私はあなたがどういう意味を理解していません。私はユーザー空間から私のドライバへの読み書きを開始できる必要があります。だから私はioctlが必要だと思う、私はユーザスペースがデバイスドライバの動作を引き起こす別の方法を知らない。特定のAPIを使ってI2Cホストとクライアントとの間で通信が行われていることを確認できません。具体的に設計されたAPIはどれですか? – Splaty

+0

既存のI2C_DEVドライバをそのまま使用してください。ユーザー空間からI2C *クライアント*への生の通信に特化して設計されています。 – 0andriy

答えて

0

私は@Alexandre Belloniはさんのコメントに良くなっデバイスドライバモデルを理解し、プレゼンテーションのスライドのセットを読んで思う:http://free-electrons.com/doc/training/linux-kernel/linux-kernel-slides.pdf

  1. 文字
  2. ネットワーク
  3. ブロック

はしかし、「フレームワークの特定があります。関連するスライドは、デバイスドライバの3種類がありますページ221から236

にあります同じ種類のデバイスのドライバの共通部分を実装するキャラクタデバイスドライバのサブクラスとして存在します。

例えば、ハードウェア監視に使用されるマザーボード上の温度センサーは、hwmonフレームワーク(https://www.kernel.org/doc/Documentation/hwmon/hwmon-kernel-api.txt)の下に登録されます。 i2c probereadwriteの機能を実装しますが、それをfile_operations structの文字デバイスに整形するのではなく、hwmonデバイスとして登録する必要があります:hwmon_device_register_with_groups()。ユーザー空間に公開するには、attributesを使用して、/sys/class/hwmon/hwmon*ディレクトリを構築し、必要な公開読取り/書込みコマンドのリストを作成する必要があります(例:チャネル1からの読取り温度、一時レジスタへの書込み)。

カーネルをビルドするときは、カーネルでビルドするために、デバイスをmake menuconfigに選択してください。これで、カーネルを起動すると、デバイスは/sys/class/hwmon/hwmon*の下に表示され、ユーザスペースはopenreadになり、デバイスからsysfsインターフェイスを経由します。 ここに良い例を見てください:http://lxr.free-electrons.com/source/drivers/hwmon/tmp421.c。または、hwmonディレクトリ内の任意のデバイス。

これは私の混乱があった場所です。 @Alexandre Belloniが指摘するように、これらのデバイスはフレームワークの下に登録されているため、明示的な文字デバイスドライバコードは必要ありません。私にとってはそうではありません。私がやっているデバイス(クロックPLL)に適したフレームワークはないと思います。したがって、私は一般的なルートに行き、文字デバイスとして実装する必要があります。これにより、カーネルの起動時に自動的にロードされるのではなく、モジュールとしてロード/アンロードすることもできます。

私は間違いを修正してください。私は、これがi2c-clientsを書くことについて混乱している誰にとっても役立つことを願っています。

+1

共通クロックフレームワーク(ドライバclk)は、クロックとPLLのフレームワークです。しかし、私はユーザー空間からPLLでできることを期待しているかどうかはわかりませんので、これはうまくいかないかもしれません。 –

+0

@AlexandreBelloni。提案していただきありがとうございます。 https://www.kernel.org/doc/Documentation/clk.txtを読んだ後、私はそれが私がやろうとしていることに適しているとは思わない。ヘルプをよろしくお願いいたします。 – Splaty

+0

IIOフレームワークにはいくつかのクロックチップドライバがあります。 clkは、SoCの一部にクロックを供給するドライバによって使用されます。これは、他のカーネルドライバが、ドライブのクロックを有効/無効にするために使用します。 IIOクロックジェネレータはユーザー空間の制御を可能にし、他のドライバにクロックを提供するものではありません。 – TrentP

関連する問題