acpi power button event的产生

在acpi_bus_type 中如果match函数返回TRUE的话,就会调用acpi_bus_type的probe函数
static int acpi_device_probe(struct device *dev)
{
    struct acpi_device *acpi_dev = to_acpi_device(dev);
    struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver);
    int ret;

    if (acpi_dev->handler && !acpi_is_pnp_device(acpi_dev))
        return -EINVAL;

    if (!acpi_drv->ops.add)
        return -ENOSYS;

    ret = acpi_drv->ops.add(acpi_dev);
    if (ret)
        return ret;

    acpi_dev->driver = acpi_drv;
    ACPI_DEBUG_PRINT((ACPI_DB_INFO,
              "Driver [%s] successfully bound to device [%s]\n",
              acpi_drv->name, acpi_dev->pnp.bus_id));

    if (acpi_drv->ops.notify) {
        ret = acpi_device_install_notify_handler(acpi_dev);
        if (ret) {
            if (acpi_drv->ops.remove)
                acpi_drv->ops.remove(acpi_dev);

            acpi_dev->driver = NULL;
            acpi_dev->driver_data = NULL;
            return ret;
        }
    }

    ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n",
              acpi_drv->name, acpi_dev->pnp.bus_id));
    get_device(dev);
    return 0;
}
acpi_device_probe 中首先会调用add函数,以button.c为例
static struct acpi_driver acpi_button_driver = {
    .name = "button",
    .class = ACPI_BUTTON_CLASS,
    .ids = button_device_ids,
    .ops = {
        .add = acpi_button_add,
        .remove = acpi_button_remove,
        .notify = acpi_button_notify,
    },
    .drv.pm = &acpi_button_pm,
};
就是调用acpi_button_add
static int acpi_button_add(struct acpi_device *device)
{
    if (!strcmp(hid, ACPI_BUTTON_HID_POWER) ||
        !strcmp(hid, ACPI_BUTTON_HID_POWERF)) {
        button->type = ACPI_BUTTON_TYPE_POWER;
        strcpy(name, ACPI_BUTTON_DEVICE_NAME_POWER);
        sprintf(class, "%s/%s",
            ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
    } else if (!strcmp(hid, ACPI_BUTTON_HID_SLEEP) ||
           !strcmp(hid, ACPI_BUTTON_HID_SLEEPF)) {
        button->type = ACPI_BUTTON_TYPE_SLEEP;
        strcpy(name, ACPI_BUTTON_DEVICE_NAME_SLEEP);
        sprintf(class, "%s/%s",
            ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
    } else if (!strcmp(hid, ACPI_BUTTON_HID_LID)) {
        button->type = ACPI_BUTTON_TYPE_LID;
        strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID);
        sprintf(class, "%s/%s",
            ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
        button->last_state = !!acpi_lid_evaluate_state(device);
        button->last_time = ktime_get();
    } else {
        printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
        error = -ENODEV;
        goto err_free_input;
    }
}
acpi_button_add 中首先会判断hid 判断button->type
以power button为例
button->type = ACPI_BUTTON_TYPE_POWER;
static int acpi_button_add_fs(struct acpi_device *device)
{

    /* procfs I/F for ACPI lid device only */
    if (button->type != ACPI_BUTTON_TYPE_LID)
        return 0;

    if (acpi_button_dir || acpi_lid_dir) {
        printk(KERN_ERR PREFIX "More than one Lid device found!\n");
        return -EEXIST;
    }

    /* create /proc/acpi/button */
    acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
    if (!acpi_button_dir)
        return -ENODEV;

}
由于我们是powerbutton,因此if (button->type != ACPI_BUTTON_TYPE_LID) 这个条件成立,acpi_button_add_fs 就直接返回了,因此并不会在/proc/acpi 下面建立任何目录
前面acpi_device_probe 会调用notify 函数
    if (acpi_drv->ops.notify) {
        ret = acpi_device_install_notify_handler(acpi_dev);
        if (ret) {
            if (acpi_drv->ops.remove)
                acpi_drv->ops.remove(acpi_dev);

            acpi_dev->driver = NULL;
            acpi_dev->driver_data = NULL;
            return ret;
        }
    }
以power button为例就是acpi_button_notify。我们首先看acpi_device_install_notify_handler
static int acpi_device_install_notify_handler(struct acpi_device *device)
{
    acpi_status status;

    if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
        status =
            acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
                             acpi_device_fixed_event,
                             device);
}
继续看acpi_install_fixed_event_handler
acpi_install_fixed_event_handler(u32 event,
                 acpi_event_handler handler, void *context)
{

    /* Install the handler before enabling the event */

    acpi_gbl_fixed_event_handlers[event].handler = handler;
    acpi_gbl_fixed_event_handlers[event].context = context;

}
也就是给acpi_gbl_fixed_event_handlers 这个数组赋值
其中handler是acpi_device_fixed_event。event是ACPI_EVENT_POWER_BUTTON。
也就是主要有ACPI_EVENT_POWER_BUTTON 就会调用acpi_device_fixed_event

acpi_device_notify_fixed->acpi_device_notify
static void acpi_device_notify(acpi_handle handle, u32 event, void *data)
{
    struct acpi_device *device = data;

    device->driver->ops.notify(device, event);
}
以buttton.c 为例,最终就是调用acpi_button_notify
static void acpi_button_notify(struct acpi_device *device, u32 event)
{
    struct acpi_button *button = acpi_driver_data(device);
    struct input_dev *input;

    switch (event) {
    case ACPI_FIXED_HARDWARE_EVENT:
        event = ACPI_BUTTON_NOTIFY_STATUS;
        /* fall through */
    case ACPI_BUTTON_NOTIFY_STATUS:
        input = button->input;
        if (button->type == ACPI_BUTTON_TYPE_LID) {
            acpi_lid_update_state(device);
        } else {
            int keycode;

            pm_wakeup_event(&device->dev, 0);
            if (button->suspended)
                break;

            keycode = test_bit(KEY_SLEEP, input->keybit) ?
                        KEY_SLEEP : KEY_POWER;
            input_report_key(input, keycode, 1);
            input_sync(input);
            input_report_key(input, keycode, 0);
            input_sync(input);

            acpi_bus_generate_netlink_event(
                    device->pnp.device_class,
                    dev_name(&device->dev),
                    event, ++button->pushed);
        }
        break;
    default:
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                  "Unsupported event [0x%x]\n", event));
        break;
    }
}
acpi_button_notify会调用acpi_bus_generate_netlink_event 来往user space发送event。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值