Permalink
Browse files

Repository cleanup, added several methods and scripts from feedback

  • Loading branch information...
1 parent 02ef13c commit 342a3d2461e1f1f8cf3a44646f3ee7ce047a5674 @mkottman committed Dec 17, 2012
View
@@ -1,38 +1,45 @@
-A kernel module that enables you to call ACPI methods by writing the method
-name followed by arguments to /proc/acpi/call.
+A kernel simple module that enables you to call ACPI methods by writing the
+method name followed by arguments to `/proc/acpi/call`.
+
+This module is to be considered a proof-of-concept and has been superseeded by
+projects like [bbswitch](https://github.com/Bumblebee-Project/bbswitch). It
+allows you to tamper with your system and should be used with caution.
Usage:
echo '<call>' | sudo tee /proc/acpi/call
+
You can then retrieve the result of the call by checking your dmesg or:
sudo cat /proc/acpi/call
An example to turn off discrete graphics card in a dual graphics environment
(like NVIDIA Optimus):
-# turn off discrete graphics card
-echo '\_SB.PCI0.PEG1.GFX0.DOFF' > /proc/acpi/call
-# turn it back on
-echo '\_SB.PCI0.PEG1.GFX0.DON' > /proc/acpi/call
+ # turn off discrete graphics card
+ echo '\_SB.PCI0.PEG1.GFX0.DOFF' > /proc/acpi/call
+ # turn it back on
+ echo '\_SB.PCI0.PEG1.GFX0.DON' > /proc/acpi/call
These work on my ASUS K52J notebook, but may not work for you. For a list of
methods to try, see http://linux-hybrid-graphics.blogspot.com/ or try running
-the provided script test_off.sh
+the provided script `examples/turn_off_gpu.sh`
It SHOULD be ok to test all of the methods, until you see a drop in battery
-drain rate (grep rate /proc/acpi/battery/BAT0/state), however it comes
-with NO WARRANTY.
+drain rate (`grep rate /proc/acpi/battery/BAT0/state`), however it comes
+with NO WARRANTY - it may hang your computer/laptop, fail to work, etc.
-You can pass parameters to acpi_call by writing them after the method,
+You can pass parameters to `acpi_call` by writing them after the method,
separated by single space. Currently, you can pass the following parameter
types:
+
* ACPI_INTEGER - by writing NNN or 0xNNN, where NNN is an integer/hex
* ACPI_STRING - by enclosing the string in quotes: "hello, world"
* ACPI_BUFFER - by writing bXXXX, where XXXX is a hex string without spaces,
or by writing { b1, b2, b3, b4 }, where b1-4 are integers
-The status after a call can be read back from /proc/acpi/call:
+The status after a call can be read back from `/proc/acpi/call`:
+
* 'not called' - nothing to report
* 'Error: <description>' - the call failed
* '0xNN' - the call succeeded, and returned an integer
View
@@ -9,7 +9,13 @@
MODULE_LICENSE("GPL");
+/* Uncomment the following line to enable debug messages */
+/*
+#define DEBUG
+*/
+
#define BUFFER_SIZE 256
+#define MAX_ACPI_ARGS 16
extern struct proc_dir_entry *acpi_root_dir;
@@ -23,6 +29,7 @@ static size_t get_avail_bytes(void) {
static char *get_buffer_end(void) {
return result_buffer + strlen(result_buffer);
}
+
/** Appends the contents of an acpi_object to the result buffer
@param result An acpi object holding result data
@returns 0 if the result could fully be saved, a higher value otherwise
@@ -87,7 +94,9 @@ static void do_acpi_call(const char * method, int argc, union acpi_object *argv)
struct acpi_object_list arg;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+#ifdef DEBUG
printk(KERN_INFO "acpi_call: Calling %s\n", method);
+#endif
// get the handle of the method, must be a fully qualified path
status = acpi_get_handle(NULL, (acpi_string) method, &handle);
@@ -117,7 +126,9 @@ static void do_acpi_call(const char * method, int argc, union acpi_object *argv)
acpi_result_to_string(buffer.pointer);
kfree(buffer.pointer);
+#ifdef DEBUG
printk(KERN_INFO "acpi_call: Call successful: %s\n", result_buffer);
+#endif
}
/** Decodes 2 hex characters to an u8 int
@@ -146,7 +157,7 @@ static char *parse_acpi_args(char *input, int *nargs, union acpi_object **args)
if (*s == 0)
return input;
- *args = (union acpi_object *) kmalloc(16 * sizeof(union acpi_object), GFP_KERNEL);
+ *args = (union acpi_object *) kmalloc(MAX_ACPI_ARGS * sizeof(union acpi_object), GFP_KERNEL);
while (*s) {
if (*s == ' ') {
@@ -290,8 +301,11 @@ static int acpi_proc_read(char *page, char **start, off_t off,
return 0;
}
+ // output the current result buffer
len = strlen(result_buffer);
memcpy(page, result_buffer, len + 1);
+
+ // initialize the result buffer for later
strcpy(result_buffer, "not called");
return len;
@@ -311,15 +325,21 @@ static int __init init_acpi_call(void)
acpi_entry->write_proc = acpi_proc_write;
acpi_entry->read_proc = acpi_proc_read;
+
+#ifdef DEBUG
printk(KERN_INFO "acpi_call: Module loaded successfully\n");
+#endif
return 0;
}
static void __exit unload_acpi_call(void)
{
remove_proc_entry("call", acpi_root_dir);
+
+#ifdef DEBUG
printk(KERN_INFO "acpi_call: Module unloaded successfully\n");
+#endif
}
module_init(init_acpi_call);
File renamed without changes.
View
@@ -0,0 +1,46 @@
+#!/bin/sh
+# Power control for Dell L702X
+# by Jos Hickson
+# adapted from "Power control for Asus 1215N Optimus by Pete Eberlein"
+
+if ! lsmod | grep -q acpi_call; then
+ echo "Error: acpi_call module not loaded"
+ exit
+fi
+
+acpi_call () {
+ echo "$*" > /proc/acpi/call
+ cat /proc/acpi/call
+}
+
+
+case "$1" in
+off)
+ echo _DSM $(acpi_call "\_SB.PCI0.PEG0.PEGP._DSM" \
+ "{0xF8,0xD8,0x86,0xA4,0xDA,0x0B,0x1B,0x47," \
+ "0xA7,0x2B,0x60,0x42,0xA6,0xB5,0xBE,0xE0}" \
+ "0x100 0x1A {0x1,0x0,0x0,0x3}")
+ # ok to turn off: Buffer {0x59 0x0 0x0 0x11}
+ # is already off: Buffer {0x41 0x0 0x0 0x11}
+ echo _PS3 $(acpi_call "\_SB.PCI0.PEG0.PEGP._PS3")
+;;
+on)
+ echo _PS0 $(acpi_call "\_SB.PCI0.PEG0.PEGP._PS0")
+;;
+*)
+ echo "Usage: $0 [on|off]"
+esac
+
+
+PSC=$(acpi_call "\_SB.PCI0.PEG0.PEGP._PSC")
+#echo _PSC ${PSC}
+case "$PSC" in
+0x0)
+ PSC="on"
+;;
+0x3)
+ PSC="off"
+;;
+esac
+echo "Dell L702X Optimus appears to be ${PSC}"
+
File renamed without changes.
View
@@ -27,23 +27,26 @@ methods="
\_SB.PCI0.LPC.EC.PUBS._OFF
\_SB.PCI0.P0P2.NVID._OFF
\_SB.PCI0.P0P2.VGA.PX02
+\_SB_.PCI0.PEGP.DGFX._OFF
+\_SB_.PCI0.VGA.PX02
"
- for m in $methods; do
-echo -n "Trying $m: "
- echo $m > /proc/acpi/call
- result=$(cat /proc/acpi/call)
- case "$result" in
+for m in $methods; do
+ echo -n "Trying $m: "
+ echo $m > /proc/acpi/call
+ result=$(cat /proc/acpi/call)
+ case "$result" in
Error*)
echo "failed"
;;
*)
echo "works!"
- #break
+ # break # try out outher methods too
;;
- esac
+ esac
done
+
else
-echo 'The acpi_call module is not loaded'
+ echo "The acpi_call module is not loaded, try running 'modprobe acpi_call' or 'insmod acpi_call.ko' as root"
exit 1
fi
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit 342a3d2

Please sign in to comment.