patch-2.4.27 linux-2.4.27/drivers/acpi/asus_acpi.c
Next file: linux-2.4.27/drivers/acpi/battery.c
Previous file: linux-2.4.27/drivers/acpi/ac.c
Back to the patch index
Back to the overall index
- Lines: 425
- Date:
2004-08-07 16:26:04.648346531 -0700
- Orig file:
linux-2.4.26/drivers/acpi/asus_acpi.c
- Orig date:
2004-02-18 05:36:31.000000000 -0800
diff -urN linux-2.4.26/drivers/acpi/asus_acpi.c linux-2.4.27/drivers/acpi/asus_acpi.c
@@ -40,8 +40,9 @@
#include <linux/proc_fs.h>
#include <acpi/acpi_drivers.h>
#include <acpi/acpi_bus.h>
+#include <asm/uaccess.h>
-#define ASUS_ACPI_VERSION "0.27"
+#define ASUS_ACPI_VERSION "0.28"
#define PROC_ASUS "asus" //the directory
#define PROC_MLED "mled"
@@ -125,12 +126,11 @@
L5x, //L5800C
L8L, //L8400L
M1A, //M1300A
- M2E, //M2400E
+ M2E, //M2400E, L4400L
+ P30, //Samsung P30
S1x, //S1300A, but also L1400B and M2400A (L84F)
S2x, //S200 (J1 reported), Victor MP-XP7210
- //TODO A1370D does not seem to have an ATK device
- // L8400 model doesn't have ATK
- xxN, //M2400N, M3700N, S1300N (Centrino)
+ xxN, //M2400N, M3700N, M6800N, S1300N, S5200N (Centrino)
END_MODEL
} model; //Models currently supported
u16 event_count[128]; //count for each event TODO make this better
@@ -140,6 +140,7 @@
#define A1x_PREFIX "\\_SB.PCI0.ISA.EC0."
#define L3C_PREFIX "\\_SB.PCI0.PX40.ECD0."
#define M1A_PREFIX "\\_SB.PCI0.PX40.EC0."
+#define P30_PREFIX "\\_SB.PCI0.LPCB.EC0."
#define S1x_PREFIX "\\_SB.PCI0.PX40."
#define S2x_PREFIX A1x_PREFIX
#define xxN_PREFIX "\\_SB.PCI0.SBRG.EC0."
@@ -166,7 +167,7 @@
.mt_lcd_switch = A1x_PREFIX "_Q10",
.lcd_status = "\\BKLI",
.brightness_up = A1x_PREFIX "_Q0E",
- .brightness_down = A1x_PREFIX "_Q0F",
+ .brightness_down = A1x_PREFIX "_Q0F"
},
{
@@ -176,11 +177,8 @@
.wled_status = "\\SG66",
.mt_lcd_switch = "\\Q10",
.lcd_status = "\\BAOF",
- .brightness_up = "\\Q0E",
- .brightness_down = "\\Q0F",
.brightness_set = "SPLV",
.brightness_get = "GPLV",
- .brightness_status = "\\CMOD",
.display_set = "SDSP",
.display_get = "\\INFB"
},
@@ -217,11 +215,8 @@
.mt_wled = "WLED",
.mt_lcd_switch = L3C_PREFIX "_Q10",
.lcd_status = "\\GL32",
- .brightness_up = L3C_PREFIX "_Q0F",
- .brightness_down = L3C_PREFIX "_Q0E",
.brightness_set = "SPLV",
.brightness_get = "GPLV",
- .brightness_status = "\\BLVL",
.display_set = "SDSP",
.display_get = "\\_SB.PCI0.PCI1.VGAC.NMAP"
},
@@ -233,11 +228,8 @@
.mt_wled = "WLED",
.mt_lcd_switch = "\\Q10",
.lcd_status = "\\BKLG",
- .brightness_up = "\\Q0E",
- .brightness_down = "\\Q0F",
.brightness_set = "SPLV",
.brightness_get = "GPLV",
- .brightness_status = "\\BLVL",
.display_set = "SDSP",
.display_get = "\\INFB"
},
@@ -257,14 +249,10 @@
{
.name = "L5x",
.mt_mled = "MLED",
-// .mt_wled = "WLED",
-// .wled_status = "\\WRED",
-/* Present, but not controlled by ACPI */
+/* WLED present, but not controlled by ACPI */
.mt_tled = "TLED",
.mt_lcd_switch = "\\Q0D",
.lcd_status = "\\BAOF",
- .brightness_up = "\\Q0C",
- .brightness_down = "\\Q0B",
.brightness_set = "SPLV",
.brightness_get = "GPLV",
.display_set = "SDSP",
@@ -294,8 +282,6 @@
.mt_wled = "WLED",
.mt_lcd_switch = "\\Q10",
.lcd_status = "\\GP06",
- .brightness_up = "\\Q0E",
- .brightness_down = "\\Q0F",
.brightness_set = "SPLV",
.brightness_get = "GPLV",
.display_set = "SDSP",
@@ -303,17 +289,26 @@
},
{
+ .name = "P30",
+ .mt_wled = "WLED",
+ .mt_lcd_switch = P30_PREFIX "_Q0E",
+ .lcd_status = "\\BKLT",
+ .brightness_up = P30_PREFIX "_Q68",
+ .brightness_down = P30_PREFIX "_Q69",
+ .brightness_get = "GPLV",
+ .display_set = "SDSP",
+ .display_get = "\\DNXT"
+ },
+
+ {
.name = "S1x",
.mt_mled = "MLED",
.mled_status = "\\EMLE",
.mt_wled = "WLED",
.mt_lcd_switch = S1x_PREFIX "Q10" ,
.lcd_status = "\\PNOF",
- .brightness_up = S1x_PREFIX "Q0F",
- .brightness_down = S1x_PREFIX "Q0E",
.brightness_set = "SPLV",
- .brightness_get = "GPLV",
- .brightness_status = "\\BRIT",
+ .brightness_get = "GPLV"
},
{
@@ -323,22 +318,17 @@
.mt_lcd_switch = S2x_PREFIX "_Q10",
.lcd_status = "\\BKLI",
.brightness_up = S2x_PREFIX "_Q0B",
- .brightness_down = S2x_PREFIX "_Q0A",
+ .brightness_down = S2x_PREFIX "_Q0A"
},
{
.name = "xxN",
.mt_mled = "MLED",
-// .mt_wled = "WLED",
-// .wled_status = "\\PO33",
-/* Present, but not controlled by ACPI */
+/* WLED present, but not controlled by ACPI */
.mt_lcd_switch = xxN_PREFIX "_Q10",
.lcd_status = "\\BKLT",
- .brightness_up = xxN_PREFIX "_Q0F",
- .brightness_down = xxN_PREFIX "_Q0E",
.brightness_set = "SPLV",
.brightness_get = "GPLV",
- .brightness_status = "\\LBTN",
.display_set = "SDSP",
.display_get = "\\ADVG"
}
@@ -466,6 +456,21 @@
return len;
}
+
+static int parse_arg(const char *buf, unsigned long count, int *val)
+{
+ char s[32];
+ if (!count)
+ return 0;
+ if (count > 31)
+ return -EINVAL;
+ if (copy_from_user(s, buf, count))
+ return -EFAULT;
+ s[count] = 0;
+ if (sscanf(s, "%i", val) != 1)
+ return -EINVAL;
+ return count;
+}
/*
@@ -497,11 +502,14 @@
write_led(const char *buffer, unsigned long count, struct asus_hotk *hotk,
char *ledname, int ledmask, int invert)
{
- int value;
+ int value, retval;
int led_out = 0;
- if (sscanf(buffer, "%i", &value) == 1)
- led_out = value ? 1 : 0;
+ retval = parse_arg(buffer, count, &value);
+ if (retval <= 0)
+ return retval;
+ count = retval;
+ led_out = value ? 1 : 0;
hotk->status =
(led_out) ? (hotk->status | ledmask) : (hotk->status & ~ledmask);
@@ -654,15 +662,33 @@
proc_write_lcd(struct file *file, const char *buffer,
unsigned long count, void *data)
{
- int value;
+ int value, retval;
struct asus_hotk *hotk = (struct asus_hotk *) data;
- if (sscanf(buffer, "%i", &value) == 1)
+ retval = parse_arg(buffer, count, &value);
+ if (retval > 0)
set_lcd_state(hotk, value);
- return count;
+ return retval;
}
+static int read_brightness(struct asus_hotk *hotk)
+{
+ int value;
+
+ if(hotk->methods->brightness_get) { /* SPLV/GPLV laptop */
+ if (!read_acpi_int(hotk->handle, hotk->methods->brightness_get,
+ &value))
+ printk(KERN_WARNING "Asus ACPI: Error reading brightness\n");
+ } else if (hotk->methods->brightness_status) { /* For D1 for example */
+ if (!read_acpi_int(NULL, hotk->methods->brightness_status,
+ &value))
+ printk(KERN_WARNING "Asus ACPI: Error reading brightness\n");
+ } else /* No GPLV method */
+ value = hotk->brightness;
+ return value;
+}
+
/*
* Change the brightness level
*/
@@ -679,7 +705,7 @@
}
/* No SPLV method if we are here, act as appropriate */
- value -= hotk->brightness;
+ value -= read_brightness(hotk);
while (value != 0) {
status = acpi_evaluate_object(NULL, (value > 0) ?
hotk->methods->brightness_up :
@@ -692,23 +718,6 @@
return;
}
-static int read_brightness(struct asus_hotk *hotk)
-{
- int value;
-
- if(hotk->methods->brightness_get) { /* SPLV/GPLV laptop */
- if (!read_acpi_int(hotk->handle, hotk->methods->brightness_get,
- &value))
- printk(KERN_WARNING "Asus ACPI: Error reading brightness\n");
- } else if (hotk->methods->brightness_status) { /* For D1 for example */
- if (!read_acpi_int(NULL, hotk->methods->brightness_status,
- &value))
- printk(KERN_WARNING "Asus ACPI: Error reading brightness\n");
- } else /* No GPLV method */
- value = hotk->brightness;
- return value;
-}
-
static int
proc_read_brn(char *page, char **start, off_t off, int count, int *eof,
void *data)
@@ -721,10 +730,11 @@
proc_write_brn(struct file *file, const char *buffer,
unsigned long count, void *data)
{
- int value;
+ int value, retval;
struct asus_hotk *hotk = (struct asus_hotk *) data;
- if (sscanf(buffer, "%d", &value) == 1) {
+ retval = parse_arg(buffer, count, &value);
+ if (retval > 0) {
value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
/* 0 <= value <= 15 */
set_brightness(value, hotk);
@@ -732,7 +742,7 @@
printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
}
- return count;
+ return retval;
}
static void set_display(int value, struct asus_hotk *hotk)
@@ -770,16 +780,17 @@
proc_write_disp(struct file *file, const char *buffer,
unsigned long count, void *data)
{
- int value;
+ int value, retval;
struct asus_hotk *hotk = (struct asus_hotk *) data;
- if (sscanf(buffer, "%d", &value) == 1)
+ retval = parse_arg(buffer, count, &value);
+ if (retval > 0)
set_display(value, hotk);
else {
printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
}
- return count;
+ return retval;
}
@@ -874,6 +885,28 @@
return 0;
}
+static int asus_hotk_remove_fs(struct acpi_device* device)
+{
+ struct asus_hotk* hotk = acpi_driver_data(device);
+
+ if(acpi_device_dir(device)){
+ remove_proc_entry(PROC_INFO,acpi_device_dir(device));
+ if (hotk->methods->mt_wled)
+ remove_proc_entry(PROC_WLED,acpi_device_dir(device));
+ if (hotk->methods->mt_mled)
+ remove_proc_entry(PROC_MLED,acpi_device_dir(device));
+ if (hotk->methods->mt_tled)
+ remove_proc_entry(PROC_TLED,acpi_device_dir(device));
+ if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status)
+ remove_proc_entry(PROC_LCD, acpi_device_dir(device));
+ if ((hotk->methods->brightness_up && hotk->methods->brightness_down) || (hotk->methods->brightness_get && hotk->methods->brightness_get))
+ remove_proc_entry(PROC_BRN, acpi_device_dir(device));
+ if (hotk->methods->display_set)
+ remove_proc_entry(PROC_DISP, acpi_device_dir(device));
+ }
+ return 0;
+}
+
static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
{
@@ -929,12 +962,29 @@
return -ENODEV;
}
- /* For testing purposes */
+ /* This needs to be called for some laptops to init properly */
if (!read_acpi_int(hotk->handle, "BSTS", &bsts_result))
printk(KERN_WARNING " Error calling BSTS\n");
else if (bsts_result)
printk(KERN_NOTICE " BSTS called, 0x%02x returned\n", bsts_result);
+ /* Samsung P30 has a device with a valid _HID whose INIT does not
+ * return anything. Catch this one and any similar here */
+ if (buffer.pointer == NULL) {
+ if (asus_info && /* Samsung P30 */
+ strncmp(asus_info->oem_table_id, "ODEM", 4) == 0) {
+ hotk->model = P30;
+ printk(KERN_NOTICE " Samsung P30 detected, supported\n");
+ } else {
+ hotk->model = M2E;
+ printk(KERN_WARNING " no string returned by INIT\n");
+ printk(KERN_WARNING " trying default values, supply "
+ "the developers with your DSDT\n");
+ }
+ hotk->methods = &model_conf[hotk->model];
+ return AE_OK;
+ }
+
model = (union acpi_object *) buffer.pointer;
if (model->type == ACPI_TYPE_STRING) {
printk(KERN_NOTICE " %s model detected, ", model->string.pointer);
@@ -953,12 +1003,14 @@
hotk->model = L8L;
else if (strncmp(model->string.pointer, "M2N", 3) == 0 ||
strncmp(model->string.pointer, "M3N", 3) == 0 ||
+ strncmp(model->string.pointer, "M6N", 3) == 0 ||
strncmp(model->string.pointer, "S1N", 3) == 0 ||
strncmp(model->string.pointer, "S5N", 3) == 0)
hotk->model = xxN;
else if (strncmp(model->string.pointer, "M1", 2) == 0)
hotk->model = M1A;
- else if (strncmp(model->string.pointer, "M2", 2) == 0)
+ else if (strncmp(model->string.pointer, "M2", 2) == 0 ||
+ strncmp(model->string.pointer, "L4E", 3) == 0)
hotk->model = M2E;
else if (strncmp(model->string.pointer, "L2", 2) == 0)
hotk->model = L2D;
@@ -994,6 +1046,13 @@
else if (strncmp(model->string.pointer, "S5N", 3) == 0)
hotk->methods->mt_mled = NULL;
/* S5N has no MLED */
+ else if (strncmp(model->string.pointer, "M6N", 3) == 0) {
+ hotk->methods->display_get = NULL; //TODO
+ hotk->methods->lcd_status = "\\_SB.BKLT";
+ hotk->methods->mt_wled = "WLED";
+ hotk->methods->wled_status = "\\_SB.PCI0.SBRG.SG13";
+ /* M6N differs slightly and has a usable WLED */
+ }
else if (asus_info) {
if (strncmp(asus_info->oem_table_id, "L1", 2) == 0)
hotk->methods->mled_status = NULL;
@@ -1049,8 +1108,8 @@
memset(hotk, 0, sizeof(struct asus_hotk));
hotk->handle = device->handle;
- sprintf(acpi_device_name(device), "%s", ACPI_HOTK_DEVICE_NAME);
- sprintf(acpi_device_class(device), "%s", ACPI_HOTK_CLASS);
+ strcpy(acpi_device_name(device), ACPI_HOTK_DEVICE_NAME);
+ strcpy(acpi_device_class(device), ACPI_HOTK_CLASS);
acpi_driver_data(device) = hotk;
hotk->device = device;
@@ -1112,6 +1171,8 @@
if (ACPI_FAILURE(status))
printk(KERN_ERR "Asus ACPI: Error removing notify handler\n");
+ asus_hotk_remove_fs(device);
+
kfree(hotk);
return(0);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)