+/* --------------------------------------------------------------------------
+ FS Interface (/proc)
+ -------------------------------------------------------------------------- */
+
+static struct proc_dir_entry *acpi_button_dir;
+
+static int acpi_button_info_seq_show(struct seq_file *seq, void *offset)
+{
+ struct acpi_button *button = (struct acpi_button *)seq->private;
+
+ ACPI_FUNCTION_TRACE("acpi_button_info_seq_show");
+
+ if (!button || !button->device)
+ return_VALUE(0);
+
+ seq_printf(seq, "type: %s\n",
+ acpi_device_name(button->device));
+
+ return_VALUE(0);
+}
+
+static int acpi_button_info_open_fs(struct inode *inode, struct file *file)
+{
+ return single_open(file, acpi_button_info_seq_show, PDE(inode)->data);
+}
+
+static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
+{
+ struct acpi_button *button = (struct acpi_button *)seq->private;
+ acpi_status status;
+ unsigned long state;
+
+ ACPI_FUNCTION_TRACE("acpi_button_state_seq_show");
+
+ if (!button || !button->device)
+ return_VALUE(0);
+
+ status = acpi_evaluate_integer(button->handle, "_LID", NULL, &state);
+ if (ACPI_FAILURE(status)) {
+ seq_printf(seq, "state: unsupported\n");
+ } else {
+ seq_printf(seq, "state: %s\n",
+ (state ? "open" : "closed"));
+ }
+
+ return_VALUE(0);
+}
+
+static int acpi_button_state_open_fs(struct inode *inode, struct file *file)
+{
+ return single_open(file, acpi_button_state_seq_show, PDE(inode)->data);
+}
+
+static struct proc_dir_entry *acpi_power_dir;
+static struct proc_dir_entry *acpi_sleep_dir;
+static struct proc_dir_entry *acpi_lid_dir;
+
+static int acpi_button_add_fs(struct acpi_device *device)
+{
+ struct proc_dir_entry *entry = NULL;
+ struct acpi_button *button = NULL;
+
+ ACPI_FUNCTION_TRACE("acpi_button_add_fs");
+
+ if (!device || !acpi_driver_data(device))
+ return_VALUE(-EINVAL);
+
+ button = acpi_driver_data(device);
+
+ switch (button->type) {
+ case ACPI_BUTTON_TYPE_POWER:
+ case ACPI_BUTTON_TYPE_POWERF:
+ if (!acpi_power_dir)
+ acpi_power_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER,
+ acpi_button_dir);
+ entry = acpi_power_dir;
+ break;
+ case ACPI_BUTTON_TYPE_SLEEP:
+ case ACPI_BUTTON_TYPE_SLEEPF:
+ if (!acpi_sleep_dir)
+ acpi_sleep_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP,
+ acpi_button_dir);
+ entry = acpi_sleep_dir;
+ break;
+ case ACPI_BUTTON_TYPE_LID:
+ if (!acpi_lid_dir)
+ acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID,
+ acpi_button_dir);
+ entry = acpi_lid_dir;
+ break;
+ }
+
+ if (!entry)
+ return_VALUE(-ENODEV);
+ entry->owner = THIS_MODULE;
+
+ acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry);
+ if (!acpi_device_dir(device))
+ return_VALUE(-ENODEV);
+ acpi_device_dir(device)->owner = THIS_MODULE;
+
+ /* 'info' [R] */
+ entry = create_proc_entry(ACPI_BUTTON_FILE_INFO,
+ S_IRUGO, acpi_device_dir(device));
+ if (!entry)
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create '%s' fs entry\n",
+ ACPI_BUTTON_FILE_INFO));
+ else {
+ entry->proc_fops = &acpi_button_info_fops;
+ entry->data = acpi_driver_data(device);
+ entry->owner = THIS_MODULE;
+ }
+
+ /* show lid state [R] */
+ if (button->type == ACPI_BUTTON_TYPE_LID) {
+ entry = create_proc_entry(ACPI_BUTTON_FILE_STATE,
+ S_IRUGO, acpi_device_dir(device));
+ if (!entry)
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Unable to create '%s' fs entry\n",
+ ACPI_BUTTON_FILE_INFO));
+ else {
+ entry->proc_fops = &acpi_button_state_fops;
+ entry->data = acpi_driver_data(device);
+ entry->owner = THIS_MODULE;
+ }
+ }
+
+ return_VALUE(0);
+}
+
+static int acpi_button_remove_fs(struct acpi_device *device)
+{
+ struct acpi_button *button = NULL;
+
+ ACPI_FUNCTION_TRACE("acpi_button_remove_fs");
+
+ button = acpi_driver_data(device);
+ if (acpi_device_dir(device)) {
+ if (button->type == ACPI_BUTTON_TYPE_LID)
+ remove_proc_entry(ACPI_BUTTON_FILE_STATE,
+ acpi_device_dir(device));
+ remove_proc_entry(ACPI_BUTTON_FILE_INFO,
+ acpi_device_dir(device));
+
+ remove_proc_entry(acpi_device_bid(device),
+ acpi_device_dir(device)->parent);
+ acpi_device_dir(device) = NULL;
+ }
+
+ return_VALUE(0);
+}
+