#include <linux/init.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
+#include <linux/backlight.h>
+
#include <asm/uaccess.h>
#include <acpi/acpi_drivers.h>
/* utility
*/
-static __inline__ void
-_set_bit(u32* word, u32 mask, int value)
+static __inline__ void _set_bit(u32 * word, u32 mask, int value)
{
*word = (*word & ~mask) | (mask * value);
}
/* acpi interface wrappers
*/
-static int
-is_valid_acpi_path(const char* methodName)
+static int is_valid_acpi_path(const char *methodName)
{
acpi_handle handle;
acpi_status status;
- status = acpi_get_handle(0, (char*)methodName, &handle);
+ status = acpi_get_handle(NULL, (char *)methodName, &handle);
return !ACPI_FAILURE(status);
}
-static int
-write_acpi_int(const char* methodName, int val)
+static int write_acpi_int(const char *methodName, int val)
{
struct acpi_object_list params;
union acpi_object in_objs[1];
acpi_status status;
- params.count = sizeof(in_objs)/sizeof(in_objs[0]);
+ params.count = sizeof(in_objs) / sizeof(in_objs[0]);
params.pointer = in_objs;
in_objs[0].type = ACPI_TYPE_INTEGER;
in_objs[0].integer.value = val;
- status = acpi_evaluate_object(0, (char*)methodName, ¶ms, 0);
+ status = acpi_evaluate_object(NULL, (char *)methodName, ¶ms, NULL);
return (status == AE_OK);
}
#if 0
-static int
-read_acpi_int(const char* methodName, int* pVal)
+static int read_acpi_int(const char *methodName, int *pVal)
{
struct acpi_buffer results;
union acpi_object out_objs[1];
results.length = sizeof(out_objs);
results.pointer = out_objs;
- status = acpi_evaluate_object(0, (char*)methodName, 0, &results);
+ status = acpi_evaluate_object(0, (char *)methodName, 0, &results);
*pVal = out_objs[0].integer.value;
return (status == AE_OK) && (out_objs[0].type == ACPI_TYPE_INTEGER);
}
#endif
-static const char* method_hci /*= 0*/;
+static const char *method_hci /*= 0*/ ;
/* Perform a raw HCI call. Here we don't care about input or output buffer
* format.
*/
-static acpi_status
-hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
+static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
{
struct acpi_object_list params;
union acpi_object in_objs[HCI_WORDS];
struct acpi_buffer results;
- union acpi_object out_objs[HCI_WORDS+1];
+ union acpi_object out_objs[HCI_WORDS + 1];
acpi_status status;
int i;
results.length = sizeof(out_objs);
results.pointer = out_objs;
- status = acpi_evaluate_object(0, (char*)method_hci, ¶ms,
- &results);
+ status = acpi_evaluate_object(NULL, (char *)method_hci, ¶ms,
+ &results);
if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) {
for (i = 0; i < out_objs->package.count; ++i) {
out[i] = out_objs->package.elements[i].integer.value;
* may be useful (such as "not supported").
*/
-static acpi_status
-hci_write1(u32 reg, u32 in1, u32* result)
+static acpi_status hci_write1(u32 reg, u32 in1, u32 * result)
{
u32 in[HCI_WORDS] = { HCI_SET, reg, in1, 0, 0, 0 };
u32 out[HCI_WORDS];
return status;
}
-static acpi_status
-hci_read1(u32 reg, u32* out1, u32* result)
+static acpi_status hci_read1(u32 reg, u32 * out1, u32 * result)
{
u32 in[HCI_WORDS] = { HCI_GET, reg, 0, 0, 0, 0 };
u32 out[HCI_WORDS];
return status;
}
-static struct proc_dir_entry* toshiba_proc_dir /*= 0*/;
-static int force_fan;
-static int last_key_event;
-static int key_event_valid;
+static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ;
+static struct backlight_device *toshiba_backlight_device;
+static int force_fan;
+static int last_key_event;
+static int key_event_valid;
-typedef struct _ProcItem
-{
- const char* name;
- char* (*read_func)(char*);
- unsigned long (*write_func)(const char*, unsigned long);
+typedef struct _ProcItem {
+ const char *name;
+ char *(*read_func) (char *);
+ unsigned long (*write_func) (const char *, unsigned long);
} ProcItem;
/* proc file handlers
*/
static int
-dispatch_read(char* page, char** start, off_t off, int count, int* eof,
- ProcItem* item)
+dispatch_read(char *page, char **start, off_t off, int count, int *eof,
+ ProcItem * item)
{
- char* p = page;
+ char *p = page;
int len;
if (off == 0)
/* ISSUE: I don't understand this code */
len = (p - page);
- if (len <= off+count) *eof = 1;
+ if (len <= off + count)
+ *eof = 1;
*start = page + off;
len -= off;
- if (len>count) len = count;
- if (len<0) len = 0;
+ if (len > count)
+ len = count;
+ if (len < 0)
+ len = 0;
return len;
}
static int
-dispatch_write(struct file* file, __user const char* buffer,
- unsigned long count, ProcItem* item)
+dispatch_write(struct file *file, const char __user * buffer,
+ unsigned long count, ProcItem * item)
{
int result;
- char* tmp_buffer;
+ char *tmp_buffer;
/* Arg buffer points to userspace memory, which can't be accessed
* directly. Since we're making a copy, zero-terminate the
* destination so that sscanf can be used on it safely.
*/
tmp_buffer = kmalloc(count + 1, GFP_KERNEL);
+ if (!tmp_buffer)
+ return -ENOMEM;
+
if (copy_from_user(tmp_buffer, buffer, count)) {
result = -EFAULT;
- }
- else {
+ } else {
tmp_buffer[count] = 0;
result = item->write_func(tmp_buffer, count);
}
return result;
}
-static char*
-read_lcd(char* p)
+static int get_lcd(struct backlight_device *bd)
{
u32 hci_result;
u32 value;
hci_read1(HCI_LCD_BRIGHTNESS, &value, &hci_result);
if (hci_result == HCI_SUCCESS) {
- value = value >> HCI_LCD_BRIGHTNESS_SHIFT;
+ return (value >> HCI_LCD_BRIGHTNESS_SHIFT);
+ } else
+ return -EFAULT;
+}
+
+static char *read_lcd(char *p)
+{
+ int value = get_lcd(NULL);
+
+ if (value >= 0) {
p += sprintf(p, "brightness: %d\n", value);
p += sprintf(p, "brightness_levels: %d\n",
- HCI_LCD_BRIGHTNESS_LEVELS);
+ HCI_LCD_BRIGHTNESS_LEVELS);
} else {
printk(MY_ERR "Error reading LCD brightness\n");
}
return p;
}
-static unsigned long
-write_lcd(const char* buffer, unsigned long count)
+static int set_lcd(int value)
{
- int value;
u32 hci_result;
+ value = value << HCI_LCD_BRIGHTNESS_SHIFT;
+ hci_write1(HCI_LCD_BRIGHTNESS, value, &hci_result);
+ if (hci_result != HCI_SUCCESS)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int set_lcd_status(struct backlight_device *bd)
+{
+ return set_lcd(bd->props->brightness);
+}
+
+static unsigned long write_lcd(const char *buffer, unsigned long count)
+{
+ int value;
+ int ret;
+
if (sscanf(buffer, " brightness : %i", &value) == 1 &&
- value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) {
- value = value << HCI_LCD_BRIGHTNESS_SHIFT;
- hci_write1(HCI_LCD_BRIGHTNESS, value, &hci_result);
- if (hci_result != HCI_SUCCESS)
- return -EFAULT;
+ value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) {
+ ret = set_lcd(value);
+ if (ret == 0)
+ ret = count;
} else {
- return -EINVAL;
+ ret = -EINVAL;
}
-
- return count;
+ return ret;
}
-static char*
-read_video(char* p)
+static char *read_video(char *p)
{
u32 hci_result;
u32 value;
if (hci_result == HCI_SUCCESS) {
int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0;
int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0;
- int is_tv = (value & HCI_VIDEO_OUT_TV ) ? 1 : 0;
+ int is_tv = (value & HCI_VIDEO_OUT_TV) ? 1 : 0;
p += sprintf(p, "lcd_out: %d\n", is_lcd);
p += sprintf(p, "crt_out: %d\n", is_crt);
p += sprintf(p, "tv_out: %d\n", is_tv);
return p;
}
-static unsigned long
-write_video(const char* buffer, unsigned long count)
+static unsigned long write_video(const char *buffer, unsigned long count)
{
int value;
int remain = count;
++buffer;
--remain;
}
- while (remain && *(buffer-1) != ';');
+ while (remain && *(buffer - 1) != ';');
}
hci_read1(HCI_VIDEO_OUT, &video_out, &hci_result);
return count;
}
-static char*
-read_fan(char* p)
+static char *read_fan(char *p)
{
u32 hci_result;
u32 value;
return p;
}
-static unsigned long
-write_fan(const char* buffer, unsigned long count)
+static unsigned long write_fan(const char *buffer, unsigned long count)
{
int value;
u32 hci_result;
if (sscanf(buffer, " force_on : %i", &value) == 1 &&
- value >= 0 && value <= 1) {
+ value >= 0 && value <= 1) {
hci_write1(HCI_FAN, value, &hci_result);
if (hci_result != HCI_SUCCESS)
return -EFAULT;
return count;
}
-static char*
-read_keys(char* p)
+static char *read_keys(char *p)
{
u32 hci_result;
u32 value;
p += sprintf(p, "hotkey_ready: %d\n", key_event_valid);
p += sprintf(p, "hotkey: 0x%04x\n", last_key_event);
-end:
+ end:
return p;
}
-static unsigned long
-write_keys(const char* buffer, unsigned long count)
+static unsigned long write_keys(const char *buffer, unsigned long count)
{
int value;
- if (sscanf(buffer, " hotkey_ready : %i", &value) == 1 &&
- value == 0) {
+ if (sscanf(buffer, " hotkey_ready : %i", &value) == 1 && value == 0) {
key_event_valid = 0;
} else {
return -EINVAL;
return count;
}
-static char*
-read_version(char* p)
+static char *read_version(char *p)
{
p += sprintf(p, "driver: %s\n", TOSHIBA_ACPI_VERSION);
p += sprintf(p, "proc_interface: %d\n",
- PROC_INTERFACE_VERSION);
+ PROC_INTERFACE_VERSION);
return p;
}
#define PROC_TOSHIBA "toshiba"
-ProcItem proc_items[] =
-{
- { "lcd" , read_lcd , write_lcd },
- { "video" , read_video , write_video },
- { "fan" , read_fan , write_fan },
- { "keys" , read_keys , write_keys },
- { "version" , read_version , 0 },
- { 0 , 0 , 0 },
+static ProcItem proc_items[] = {
+ {"lcd", read_lcd, write_lcd},
+ {"video", read_video, write_video},
+ {"fan", read_fan, write_fan},
+ {"keys", read_keys, write_keys},
+ {"version", read_version, NULL},
+ {NULL}
};
-static acpi_status __init
-add_device(void)
+static acpi_status __init add_device(void)
{
- struct proc_dir_entry* proc;
- ProcItem* item;
+ struct proc_dir_entry *proc;
+ ProcItem *item;
- for (item = proc_items; item->name; ++item)
- {
+ for (item = proc_items; item->name; ++item) {
proc = create_proc_read_entry(item->name,
- S_IFREG | S_IRUGO | S_IWUSR,
- toshiba_proc_dir, (read_proc_t*)dispatch_read, item);
+ S_IFREG | S_IRUGO | S_IWUSR,
+ toshiba_proc_dir,
+ (read_proc_t *) dispatch_read,
+ item);
if (proc)
proc->owner = THIS_MODULE;
if (proc && item->write_func)
- proc->write_proc = (write_proc_t*)dispatch_write;
+ proc->write_proc = (write_proc_t *) dispatch_write;
}
- return(AE_OK);
+ return AE_OK;
}
-static acpi_status __exit
-remove_device(void)
+static acpi_status __exit remove_device(void)
{
- ProcItem* item;
+ ProcItem *item;
for (item = proc_items; item->name; ++item)
remove_proc_entry(item->name, toshiba_proc_dir);
- return(AE_OK);
+ return AE_OK;
+}
+
+static struct backlight_properties toshiba_backlight_data = {
+ .owner = THIS_MODULE,
+ .get_brightness = get_lcd,
+ .update_status = set_lcd_status,
+ .max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1,
+};
+
+static void __exit toshiba_acpi_exit(void)
+{
+ if (toshiba_backlight_device)
+ backlight_device_unregister(toshiba_backlight_device);
+
+ remove_device();
+
+ if (toshiba_proc_dir)
+ remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
+
+ return;
}
-static int __init
-toshiba_acpi_init(void)
+static int __init toshiba_acpi_init(void)
{
acpi_status status = AE_OK;
u32 hci_result;
if (acpi_disabled)
return -ENODEV;
+
+ if (!acpi_specific_hotkey_enabled) {
+ printk(MY_INFO "Using generic hotkey driver\n");
+ return -ENODEV;
+ }
/* simple device detection: look for HCI method */
if (is_valid_acpi_path(METHOD_HCI_1))
method_hci = METHOD_HCI_1;
return -ENODEV;
printk(MY_INFO "Toshiba Laptop ACPI Extras version %s\n",
- TOSHIBA_ACPI_VERSION);
+ TOSHIBA_ACPI_VERSION);
printk(MY_INFO " HCI method: %s\n", method_hci);
force_fan = 0;
remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
}
- return (ACPI_SUCCESS(status)) ? 0 : -ENODEV;
-}
-
-static void __exit
-toshiba_acpi_exit(void)
-{
- remove_device();
-
- if (toshiba_proc_dir)
- remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
+ toshiba_backlight_device = backlight_device_register("toshiba",NULL,
+ NULL,
+ &toshiba_backlight_data);
+ if (IS_ERR(toshiba_backlight_device)) {
+ printk(KERN_ERR "Could not register toshiba backlight device\n");
+ toshiba_backlight_device = NULL;
+ toshiba_acpi_exit();
+ }
- return;
+ return (ACPI_SUCCESS(status)) ? 0 : -ENODEV;
}
module_init(toshiba_acpi_init);