/var/log/messages

debugging with sixth sense

/sys/class/gpio というディレクトリ

標準な i/f になっているという情報を @yyuasa さんから頂きました。曰く

GPIOだったらGPIOの共通部分見るのがいいと思います。どうやったらsysfsに出せるか見るのであれば。

との事にて drivers/gpio/gpiolib*.c あたりと見て確認開始。

つうか核心部分は gpiolib-sysfs.c なのかな。末端あたりに gpiolib_sysfs_init なる手続きが定義されています。

postcore_initcall(gpiolib_sysfs_init);

なマクロが付いてておそらく最初に呼び出される初期化な手続きのはず。その中で gpio_chips ってリスト (おそらく見つけられてる gpio なデバイスのリスト) を手繰って export されていなければ

        spin_unlock_irqrestore(&gpio_lock, flags);
        status = gpiochip_export(chip);
        spin_lock_irqsave(&gpio_lock, flags);

みたいなことしてます。とりあえず

  • gpio_chips って何
  • list_for_each_entry て何

というあたりはスルーで gpiochip_export を確認。定義は同じく drivers/gpio/gpiolib-sysfs.c でした。そしてこの中で /sys/class/gpio/gpiochip? みたいなソレを作ってるような記述がありますね。

    mutex_lock(&sysfs_lock);
    dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip,
                            "gpiochip%d", chip->base);
    if (!IS_ERR(dev)) {
        status = sysfs_create_group(&dev->kobj,
                       &gpiochip_attr_group);

このあたりが核心なのかどうか。つうか手続きの名前もアレゲですね。あと、この gpiochip_export に渡されてる引数の型も確認必要か。そっちから掘ってみます。

struct gpio_chip 型

drivers/gpio/driver.h にて定義。chip->dev とか chip->base とかが device_create 手続きに渡されています。つうかこの構造体オブジェクトそのものが渡されていますね。

dev 属性は struct device 型。optional device providing the GPIOs ってコメントがありました。また、base 属性は int ですね。identifies the first GPIO number handled by this chip; or, if negative during registration, requests dynamic ID allocation. とのこと。むむむ。

あと、いくつか手続きなポインタな属性もありますね。gpio な chip に関する i/f を抽象化してるのだな。手続きとして定義されているのは以下な属性です。

  • request
  • free
  • get_direction
  • direction_input
  • direction_output
  • get
  • set
  • set_debounce
  • to_irq
  • dbg_show

これ、正に /sys/class/gpio な操作ですね。成程。つうことは標準化された諸々の操作で起動される手続きをここで、という事になるのかどうか。

device_create 手続き

creates a device and registers it with sysfs とのこと。あと、dev 属性は parent な struct device 型のオブジェクトみたいです。

もう少しコメント確認してみます。

This function can be used by char device classes. A struct device will be created in sysfs, registered to the specified class.

あるいは

A “dev” file will be created, showing the dev_t for the device, if the dev_t is not 0,0. If a pointer to a parent struct device is passed in, the newly created struct device will be a child of that device in sysfs. The pointer to the struct device will be returned from the call. Any further sysfs files that might be required can be created using this pointer.

親子の件はとりあえずスルーで良いかな。ここでは可変な引数が渡されてくるのでそれを適切に処理して次にパスしています。

     dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);

次の device_create_vargs 手続きの定義が以下。

struct device *device_create_vargs(struct class *class, struct device *parent,
                                   dev_t devt, void *drvdata, const char *fmt,
                                   va_list args)
{
    return device_create_groups_vargs(class, parent, devt, drvdata, NULL,
                                      fmt, args);
}

次で struct device な領域を確保して云々、という事をしております。ここで sysfs に何かができるのかどうか。

device_create_groups_vargs から device_add という手続きが呼び出されていて、ここが核心ぽくてさらにここから

    error = dpm_sysfs_add(dev);
    if (error)
        goto DPMError;

みたいな事してます。このあたりが核心なのかどうか。

なんとなくな部分は把握できてるのかどうか不明ですが、時間確保できれば詳細についてツツいてみたいと思っています。

もう少し

ここまでを踏まえて以下も確認してみます。

Comments