Full Code of norbusan/acpi_call for AI

master ac67445bc75e cached
10 files
31.0 KB
9.5k tokens
17 symbols
1 requests
Download .txt
Repository: norbusan/acpi_call
Branch: master
Commit: ac67445bc75e
Files: 10
Total size: 31.0 KB

Directory structure:
gitextract_flrrvk54/

├── Makefile
├── README.md
├── acpi_call.c
├── examples/
│   ├── asus1215n.sh
│   ├── dellL702X.sh
│   ├── m11xr2.sh
│   └── turn_off_gpu.sh
└── support/
    ├── query_dsdt.pl
    └── windump_hack/
        ├── windump.c
        └── xorg.conf

================================================
FILE CONTENTS
================================================

================================================
FILE: Makefile
================================================
obj-m := acpi_call.o

KVERSION := $(shell uname -r)
KDIR := /lib/modules/$(KVERSION)/build
PWD := $(shell pwd)

default:
	$(MAKE) -C $(KDIR) M=$(PWD) modules

clean:
	$(MAKE) -C $(KDIR) M=$(PWD) clean

install:
	$(MAKE) -C $(KDIR) M=$(PWD) modules_install

load:
	-/sbin/rmmod acpi_call
	/sbin/insmod acpi_call.ko


================================================
FILE: README.md
================================================
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.

Want to use acpi_call via graphic interface? [Click here](https://github.com/mkottman/acpi_call/#graphic-interface)

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

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 `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 - it may hang your computer/laptop, fail to work, etc.

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`:

* 'not called' - nothing to report
* 'Error: <description>' - the call failed
* '0xNN' - the call succeeded, and returned an integer
* '"..."' - the call succeeded, and returned a string
* '{0xNN, ...}' - the call succeeded, and returned a buffer
* '[...]' - the call succeeded, and returned a package which may contain the
   above types (integer, string and buffer) and other package types


#### Graphic interface

Found this too difficult? Try to use these programs provided by Marco Dalla Libera and do it via graphic interface:

* [acpi_call_GUI (Ubuntu and other debian-based distributions)](http://marcodallas.github.io/acpi_call_GUI/)
* [acpi_call_GUI_Fedora (Fedora version)](https://github.com/marcoDallas/acpi_call_GUI_Fedora)

***

Copyright (c) 2010: Michal Kottman

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.


================================================
FILE: acpi_call.c
================================================
/* Copyright (c) 2010: Michal Kottman */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/proc_fs.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <acpi/acpi.h>

MODULE_LICENSE("GPL");

/* Uncomment the following line to enable debug messages */
/*
#define DEBUG
*/

#define BUFFER_SIZE 256
#define MAX_ACPI_ARGS 16

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
#define HAVE_PROC_CREATE
#endif

extern struct proc_dir_entry *acpi_root_dir;

static char result_buffer[BUFFER_SIZE];

static u8 temporary_buffer[BUFFER_SIZE];

static size_t get_avail_bytes(void) {
    return BUFFER_SIZE - strlen(result_buffer);
}
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
*/
static int acpi_result_to_string(union acpi_object *result) {
    if (result->type == ACPI_TYPE_INTEGER) {
        snprintf(get_buffer_end(), get_avail_bytes(),
            "0x%x", (int)result->integer.value);
    } else if (result->type == ACPI_TYPE_STRING) {
        snprintf(get_buffer_end(), get_avail_bytes(),
            "\"%*s\"", result->string.length, result->string.pointer);
    } else if (result->type == ACPI_TYPE_BUFFER) {
        int i;
        // do not store more than data if it does not fit. The first element is
        // just 4 chars, but there is also two bytes from the curly brackets
        int show_values = min((size_t)result->buffer.length, get_avail_bytes() / 6);

        sprintf(get_buffer_end(), "{");
        for (i = 0; i < show_values; i++)
            sprintf(get_buffer_end(),
                i == 0 ? "0x%02x" : ", 0x%02x", result->buffer.pointer[i]);

        if (result->buffer.length > show_values) {
            // if data was truncated, show a trailing comma if there is space
            snprintf(get_buffer_end(), get_avail_bytes(), ",");
            return 1;
        } else {
            // in case show_values == 0, but the buffer is too small to hold
            // more values (i.e. the buffer cannot have anything more than "{")
            snprintf(get_buffer_end(), get_avail_bytes(), "}");
        }
    } else if (result->type == ACPI_TYPE_PACKAGE) {
        int i;
        sprintf(get_buffer_end(), "[");
        for (i=0; i<result->package.count; i++) {
            if (i > 0)
                snprintf(get_buffer_end(), get_avail_bytes(), ", ");

            // abort if there is no more space available
            if (!get_avail_bytes() || acpi_result_to_string(&result->package.elements[i]))
                return 1;
        }
        snprintf(get_buffer_end(), get_avail_bytes(), "]");
    } else {
        snprintf(get_buffer_end(), get_avail_bytes(),
            "Object type 0x%x\n", result->type);
    }

    // return 0 if there are still bytes available, 1 otherwise
    return !get_avail_bytes();
}

/**
@param method   The full name of ACPI method to call
@param argc     The number of parameters
@param argv     A pre-allocated array of arguments of type acpi_object
*/
static void do_acpi_call(const char * method, int argc, union acpi_object *argv)
{
    acpi_status status;
    acpi_handle handle;
    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);

    if (ACPI_FAILURE(status))
    {
        snprintf(result_buffer, BUFFER_SIZE, "Error: %s", acpi_format_exception(status));
        printk(KERN_ERR "acpi_call: Cannot get handle: %s\n", result_buffer);
        return;
    }

    // prepare parameters
    arg.count = argc;
    arg.pointer = argv;

    // call the method
    status = acpi_evaluate_object(handle, NULL, &arg, &buffer);
    if (ACPI_FAILURE(status))
    {
        snprintf(result_buffer, BUFFER_SIZE, "Error: %s", acpi_format_exception(status));
        printk(KERN_ERR "acpi_call: Method call failed: %s\n", result_buffer);
        return;
    }

    // reset the result buffer
    *result_buffer = '\0';
    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
*/
u8 decodeHex(char *hex) {
    char buf[3] = { hex[0], hex[1], 0};
    return (u8) simple_strtoul(buf, NULL, 16);
}

/** Parses method name and arguments
@param input Input string to be parsed. Modified in the process.
@param nargs Set to number of arguments parsed (output)
@param args
*/
static char *parse_acpi_args(char *input, int *nargs, union acpi_object **args)
{
    char *s = input;

    *nargs = 0;
    *args = NULL;

    // the method name is separated from the arguments by a space
    while (*s && *s != ' ')
        s++;
    // if no space is found, return 0 arguments
    if (*s == 0)
        return input;

    *args = (union acpi_object *) kmalloc(MAX_ACPI_ARGS * sizeof(union acpi_object), GFP_KERNEL);

    while (*s) {
        if (*s == ' ') {
            if (*nargs == 0)
                *s = 0; // change first space to nul
            ++ *nargs;
            ++ s;
        } else {
            union acpi_object *arg = (*args) + (*nargs - 1);
            if (*s == '"') {
                // decode string
                arg->type = ACPI_TYPE_STRING;
                arg->string.pointer = ++s;
                arg->string.length = 0;
                while (*s && *s++ != '"')
                    arg->string.length ++;
                // skip the last "
                ++s;
            } else if (*s == 'b') {
                // decode buffer - bXXXX
                char *p = ++s;
                int len = 0, i;
                u8 *buf = NULL;

                while (*p && *p!=' ')
                    p++;

                len = p - s;
                if (len % 2 == 1) {
                    printk(KERN_ERR "acpi_call: buffer arg%d is not multiple of 8 bits\n", *nargs);
                    return NULL;
                }
                len /= 2;

                buf = (u8*) kmalloc(len, GFP_KERNEL);
                for (i=0; i<len; i++) {
                    buf[i] = decodeHex(s + i*2);
                }
                s = p;

                arg->type = ACPI_TYPE_BUFFER;
                arg->buffer.pointer = buf;
                arg->buffer.length = len;
            } else if (*s == '{') {
                // decode buffer - { b1, b2 ...}
                u8 *buf = temporary_buffer;
                arg->type = ACPI_TYPE_BUFFER;
                arg->buffer.pointer = buf;
                arg->buffer.length = 0;
                while (*s && *s++ != '}') {
                    if (buf >= temporary_buffer + sizeof(temporary_buffer)) {
                        printk(KERN_ERR "acpi_call: buffer arg%d is truncated because the buffer is full\n", *nargs);
                        // clear remaining arguments
                        while (*s && *s != '}')
                            ++s;
                        break;
                    }
                    else if (*s >= '0' && *s <= '9') {
                        // decode integer into buffer
                        arg->buffer.length ++;
                        if (s[0] == '0' && s[1] == 'x')
                            *buf++ = simple_strtol(s+2, 0, 16);
                        else
                            *buf++ = simple_strtol(s, 0, 10);
                    }
                    // skip until space or comma or '}'
                    while (*s && *s != ' ' && *s != ',' && *s != '}')
                        ++s;
                }
                // store the result in new allocated buffer
                buf = (u8*) kmalloc(arg->buffer.length, GFP_KERNEL);
                memcpy(buf, temporary_buffer, arg->buffer.length);
                arg->buffer.pointer = buf;
            } else {
                // decode integer, N or 0xN
                arg->type = ACPI_TYPE_INTEGER;
                if (s[0] == '0' && s[1] == 'x') {
                    arg->integer.value = simple_strtol(s+2, 0, 16);
                } else {
                    arg->integer.value = simple_strtol(s, 0, 10);
                }
                while (*s && *s != ' ') {
                    ++s;
                }
            }
        }
    }

    return input;
}

/** procfs write callback. Called when writing into /proc/acpi/call.
*/
#ifdef HAVE_PROC_CREATE
static ssize_t acpi_proc_write( struct file *filp, const char __user *buff,
    size_t len, loff_t *data )
#else
static int acpi_proc_write( struct file *filp, const char __user *buff,
    unsigned long len, void *data )
#endif
{
    char input[2 * BUFFER_SIZE] = { '\0' };
    union acpi_object *args;
    int nargs, i;
    char *method;

    if (len > sizeof(input) - 1) {
        printk(KERN_ERR "acpi_call: Input too long! (%lu)\n", len);
        return -ENOSPC;
    }

    if (copy_from_user( input, buff, len )) {
        return -EFAULT;
    }
    input[len] = '\0';
    if (input[len-1] == '\n')
        input[len-1] = '\0';

    method = parse_acpi_args(input, &nargs, &args);
    if (method) {
        do_acpi_call(method, nargs, args);
        if (args) {
            for (i=0; i<nargs; i++)
                if (args[i].type == ACPI_TYPE_BUFFER)
                    kfree(args[i].buffer.pointer);
            kfree(args);
        }
    }

    return len;
}

/** procfs 'call' read callback. Called when reading the content of /proc/acpi/call.
Returns the last call status:
- "not called" when no call was previously issued
- "failed" if the call failed
- "ok" if the call succeeded
*/
#ifdef HAVE_PROC_CREATE
static ssize_t acpi_proc_read( struct file *filp, char __user *buff,
            size_t count, loff_t *off )
{
    ssize_t ret;
    int len = strlen(result_buffer);

    // output the current result buffer
    ret = simple_read_from_buffer(buff, count, off, result_buffer, len + 1);

    // initialize the result buffer for later
    strcpy(result_buffer, "not called");

    return ret;
}

static struct file_operations proc_acpi_operations = {
        .owner    = THIS_MODULE,
        .read     = acpi_proc_read,
        .write    = acpi_proc_write,
};

#else
static int acpi_proc_read(char *page, char **start, off_t off,
    int count, int *eof, void *data)
{
    int len = 0;

    if (off > 0) {
        *eof = 1;
        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;
}
#endif

/** module initialization function */
static int __init init_acpi_call(void)
{
#ifdef HAVE_PROC_CREATE
    struct proc_dir_entry *acpi_entry = proc_create("call",
                                                    0660,
                                                    acpi_root_dir,
                                                    &proc_acpi_operations);
#else
    struct proc_dir_entry *acpi_entry = create_proc_entry("call", 0660, acpi_root_dir);
#endif

    strcpy(result_buffer, "not called");

    if (acpi_entry == NULL) {
      printk(KERN_ERR "acpi_call: Couldn't create proc entry\n");
      return -ENOMEM;
    }

#ifndef HAVE_PROC_CREATE
    acpi_entry->write_proc = acpi_proc_write;
    acpi_entry->read_proc = acpi_proc_read;
#endif

#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);
module_exit(unload_acpi_call);




================================================
FILE: examples/asus1215n.sh
================================================
#!/bin/sh
# 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.P0P4.GFX0._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.P0P4.GFX0._PS3")
;;
on)
    echo _PS0 $(acpi_call "\_SB.PCI0.P0P4.GFX0._PS0")
;;
*)
    echo "Usage: $0 [on|off]"
esac


echo P3MO $(acpi_call "\_SB.PCI0.P0P4.GFX0.P3MO")
echo DGPS $(acpi_call "\_SB.PCI0.P0P4.GFX0.DGPS")
PSC=$(acpi_call "\_SB.PCI0.P0P4.GFX0._PSC")
echo _PSC ${PSC}
case "$PSC" in
0x0)
    PSC="on"
;;
0x3)
    PSC="off"
;;
esac
echo "Asus 1215N Optimus appears to be ${PSC}"




================================================
FILE: examples/dellL702X.sh
================================================
#!/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: examples/m11xr2.sh
================================================
#!/bin/sh
# Based on m11xr2hack by George Shearer

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 NVOP $(acpi_call "\_SB.PCI0.P0P2.PEGP.NVOP 0 0x100 0x1A {255,255,255,255}")
    echo _PS3 $(acpi_call "\_SB.PCI0.P0P2.PEGP._PS3")
;;
on)
    echo _PS0 $(acpi_call "\_SB.PCI0.P0P2.PEGP._PS0")
;;
*)
    echo "Usage: $0 [on|off]"
;;
esac



================================================
FILE: examples/turn_off_gpu.sh
================================================
#!/bin/bash

if lsmod | grep -q acpi_call; then
methods="
\_SB.PCI0.P0P1.VGA._OFF
\_SB.PCI0.P0P2.VGA._OFF
\_SB_.PCI0.OVGA.ATPX
\_SB_.PCI0.OVGA.XTPX
\_SB.PCI0.P0P3.PEGP._OFF
\_SB.PCI0.P0P2.PEGP._OFF
\_SB.PCI0.P0P1.PEGP._OFF
\_SB.PCI0.MXR0.MXM0._OFF
\_SB.PCI0.PEG1.GFX0._OFF
\_SB.PCI0.PEG0.GFX0.DOFF
\_SB.PCI0.PEG1.GFX0.DOFF
\_SB.PCI0.PEG0.PEGP._OFF
\_SB.PCI0.XVR0.Z01I.DGOF
\_SB.PCI0.PEGR.GFX0._OFF
\_SB.PCI0.PEG.VID._OFF
\_SB.PCI0.PEG0.VID._OFF
\_SB.PCI0.P0P2.DGPU._OFF
\_SB.PCI0.P0P4.DGPU.DOFF
\_SB.PCI0.IXVE.IGPU.DGOF
\_SB.PCI0.RP00.VGA._PS3
\_SB.PCI0.RP00.VGA.P3MO
\_SB.PCI0.GFX0.DSM._T_0
\_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
\_SB.PCI0.PEG0.PEGP.SGOF
\_SB.PCI0.AGP.VGA.PX02
"

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 # try out outher methods too
        ;;
    esac
done

else
    echo "The acpi_call module is not loaded, try running 'modprobe acpi_call' or 'insmod acpi_call.ko' as root"
    exit 1
fi


================================================
FILE: support/query_dsdt.pl
================================================
#!/usr/bin/perl
use strict;
use Getopt::Long;
use Data::Dumper;

my ($dir,$debug,$mytokens);
$dir = '.';
GetOptions(
	   'd|dir:s' => \$dir,
           'debug:s' => \$debug,
           't|tokens:s' => \$mytokens,
          );

my $models;

my @tokens = (
              'MXMX','MXDS','_DSM',
              '0xA6, 0xFA, 0xDD, 0x3D, 0x1B, 0x36, 0xB4, 0x4E',
              '0xA4, 0x24, 0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53');

if (defined $mytokens) {
    @tokens = ();
    foreach my $mytoken (split(":",$mytokens)) {
        push @tokens, $mytoken;
    }
}

opendir DIR,$dir or die $!;
my $file;
my $count = 0;
while (( defined($file = readdir(DIR)) )) {
    if ($file =~ /\.dsl$/) {
        analyse_file($dir,$file);
    }
    last if ($count++ > $debug && defined($debug));
}

foreach my $file (sort keys %$models) {
    my $num = scalar keys %{$models->{$file}}; $num = sprintf("%02d",$num);
    print "$num $file \{";
    foreach my $token (sort keys %{$models->{$file}}) {
        my $value = $models->{$file}{$token};
        print "\t$token => $value ";
    }
    print "\}\n";
}
$DB::single=1;1;
print STDERR Dumper($models) if ($debug);

########################################

sub analyse_file {
    my $dir  = shift;
    my $file  = shift;
    my $param = shift;

    open FILE, "$dir/$file" or die $!;
    while (<FILE>) {
        foreach my $token (@tokens) {
            my $regexp = qr/${token}/;
            if ($_ =~ /$regexp/g) {
                $models->{$file}{$token}++;
            }
        }
    }
    close FILE;
}


================================================
FILE: support/windump_hack/windump.c
================================================
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>
#include <X11/extensions/XShm.h>
#include <X11/extensions/XTest.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

int format = ZPixmap;

XImage *
CaptRoot(Display * dpy, int screen)
{
    unsigned long swaptest = 1;
    XColor *colors;
    unsigned buffer_size;
    int win_name_size;
    int header_size;
    int ncolors, i;
    char *win_name;
    Bool got_win_name;
    XWindowAttributes win_info;
    XImage *image;
    int absx, absy, x, y;
    unsigned width, height;
    int dwidth, dheight;
    int bw;
    Window dummywin;

#if 0
    int                 transparentOverlays , multiVis;
    int                 numVisuals;
    XVisualInfo         *pVisuals;
    int                 numOverlayVisuals;
    OverlayInfo         *pOverlayVisuals;
    int                 numImageVisuals;
    XVisualInfo         **pImageVisuals;
    list_ptr            vis_regions;    /* list of regions to read from */
    list_ptr            vis_image_regions ;
    Visual		vis_h,*vis ;
#endif
    int			allImage = 0 ;

    Window window=RootWindow (dpy, screen);

    if (!XGetWindowAttributes(dpy, window, &win_info))
    { fprintf(stderr,"Can't get target window attributes."); exit(1); }

    absx=0; absy=0;
    win_info.x = 0;
    win_info.y = 0;
    width = win_info.width;
    height = win_info.height;
    bw = 0;

    dwidth = DisplayWidth (dpy, screen);
    dheight = DisplayHeight (dpy, screen);

    XFetchName(dpy, window, &win_name);
    if (!win_name || !win_name[0]) {
	win_name = "xwdump";
	got_win_name = False;
    } else {
	got_win_name = True;
    }

    /* sizeof(char) is included for the null string terminator. */
    win_name_size = strlen(win_name) + sizeof(char);

    /*
     * Snarf the pixmap with XGetImage.
     */

    x = absx - win_info.x;
    y = absy - win_info.y;
#if 0
    multiVis = GetMultiVisualRegions(dpy,RootWindow(dpy, screen),absx,absy, 
	       width,height,&transparentOverlays,&numVisuals,&pVisuals,
               &numOverlayVisuals,&pOverlayVisuals,&numImageVisuals,
               &pImageVisuals,&vis_regions,&vis_image_regions,&allImage) ;
    if (on_root || multiVis)
    {
	if (!multiVis)
	    image = XGetImage (dpy, RootWindow(dpy, screen), absx, absy, 
                    width, height, AllPlanes, format);
	else
	    image = ReadAreaToImage(dpy, RootWindow(dpy, screen), absx, absy, 
                width, height,
    		numVisuals,pVisuals,numOverlayVisuals,pOverlayVisuals,
                numImageVisuals, pImageVisuals,vis_regions,
                vis_image_regions,format,allImage);
    }
    else
#endif
	image = XGetImage (dpy, window, x, y, width, height,
			   AllPlanes, format);
    if (!image) {
	fprintf (stderr, "unable to get image at %dx%d+%d+%d\n",
		 width, height, x, y);
	exit (1);
    }

    //if (add_pixel_value != 0) XAddPixel (image, add_pixel_value);

    return image;
}

Window CreateWindow(Display * dpy, int screen, int width, int height)
{
    Window win = 0;
    win = XCreateWindow(dpy, RootWindow(dpy, screen),
                        0, 0, width, height,
                        0,
                        24,
                        InputOutput,
                        DefaultVisual(dpy, screen),
                        //CWBorderPixel|CWBackPixel|CWColormap|CWEventMask|CWBitGravity,
                        0,
                        0);

    XSelectInput(dpy, win, StructureNotifyMask|ButtonPressMask|ButtonReleaseMask);

    XMapWindow(dpy, win);
    return win;
}

void DrawImage(Display * dpy, Window win, XImage * image)
{
    static GC gc;
    if(win!=0)
    {
        if(gc==0)
        {
            XGCValues gc_val;
            gc = XCreateGC (dpy, win, GCForeground|GCBackground, &gc_val);
        }
        /*for(i=0;i<100;i++)
        {
            image->data*/
        XPutImage (dpy, win, gc, image, 0, 0, 0, 0, 1024, 768);
    }
}

void createShmImage(int w, int h, XShmSegmentInfo * sinfo, XShmSegmentInfo * tinfo, Display * sdpy, Display * tdpy, int sscr, int tscr, XImage ** simage, XImage ** timage)
{
    sinfo->shmid=tinfo->shmid=shmget(IPC_PRIVATE,w*h*sizeof(unsigned),IPC_CREAT|0666 );
    sinfo->shmaddr=tinfo->shmaddr=(char*)shmat(sinfo->shmid,0,0);
    sinfo->readOnly=tinfo->readOnly=False;
    printf("%d %d\n",DefaultDepth(sdpy,sscr),DefaultDepth(tdpy,tscr));
    *simage = XShmCreateImage(
                              sdpy, DefaultVisual(sdpy,sscr), DefaultDepth(sdpy,sscr),
                              ZPixmap/*format*/,
                              (char *)sinfo->shmaddr, sinfo,
                              w,h /*width,height*/
                             );
    *timage = XShmCreateImage(
                              tdpy, DefaultVisual(tdpy,tscr), DefaultDepth(tdpy,tscr),
                              ZPixmap/*format*/,
                              (char *)tinfo->shmaddr, tinfo,
                              w,h /*width,height*/
                             );
    XShmAttach(sdpy, sinfo);
    XShmAttach(tdpy, tinfo);
}

void drawMouse(XImage * img, int xm, int ym)
{
    int x,y,x1,y1,x2,y2,w,h;

    unsigned * data = (unsigned *)(img->data);

    w=img->width;
    h=img->height;

    x=xm; if(x<0) x=0; if(x>w) x=w-1;
    y=ym; if(y<0) y=0; if(y>h) y=h-1;
    x1=xm-5; if(x1<0) x1=0; if(x1>w) x1=w;
    x2=xm+6; if(x2<0) x2=0; if(x2>w) x2=w;
    for(x=x1;x<x2;x++) data[y*w+x] = 0xFFFFFF;
    //data[y*w+x] = 0xFFFFFF;

    x=xm; if(x<0) x=0; if(x>w) x=w-1;
    y=ym; if(y<0) y=0; if(y>h) y=h-1;
    y1=ym-5; if(y1<0) y1=0; if(y1>h) y1=h;
    y2=ym+6; if(y2<0) y2=0; if(y2>h) y2=h;
    for(y=y1;y<y2;y++) data[y*w+x] = 0xFFFFFF;

}

main(int argc, char * argv [])
{
    Display * sdpy = XOpenDisplay(argv[1]);
    Display * tdpy = XOpenDisplay(argv[2]);
    int sscr = XDefaultScreen(sdpy);
    int tscr = XDefaultScreen(tdpy);
    GC tgc = DefaultGC(tdpy,tscr);
    Window swin=RootWindow (sdpy,sscr);
    int width, height, dummy;
    XGetGeometry(sdpy, swin, (Window *)&dummy, &dummy, &dummy, &width, &height, &dummy, &dummy);
    Window twin=CreateWindow(tdpy,tscr,width,height);
    XSelectInput(sdpy, swin, PointerMotionMask);
    XImage * image;
    XImage * simage;
    XImage * timage;
    int use_shm=1;
    XShmSegmentInfo xshm_sinfo;
    XShmSegmentInfo xshm_tinfo;
    if(use_shm) createShmImage(width,height,&xshm_sinfo,&xshm_tinfo,sdpy,tdpy,sscr,tscr,&simage,&timage);
    int frame=0;
    for(;;) {
        XEvent e;
        XNextEvent(tdpy, &e);
        if (e.type == MapNotify)
            break;
    }

    int emulate_events=0;

    int xmouse, ymouse;
    while(1)
    {
        {
            XEvent e;
            //long mask=ButtonPressMask|ButtonReleaseMask|MotionNotifyMask;
            //while(XCheckWindowEvent(tdpy, twin, mask, &e)!=False)
            while(XCheckTypedWindowEvent(tdpy, twin, ButtonPress, &e)!=False ||
                  XCheckTypedWindowEvent(tdpy, twin, ButtonRelease, &e)!=False)
            {
                printf("button event\n");
                if(emulate_events)
                {
                    e.xbutton.display=sdpy;
                    e.xbutton.window=swin;
                    e.xbutton.root=swin;
                    e.xbutton.window=swin;
                    e.xbutton.x_root=e.xbutton.x;
                    e.xbutton.y_root=e.xbutton.y;
                    //XSendEvent( sdpy, swin, True, mask, &e );
                    XPutBackEvent( sdpy, &e );
                    //XTestFakeMotionEvent(sdpy,sscr,e.xbutton.x,e.xbutton.y,0);
                    XTestFakeButtonEvent(sdpy,e.xbutton.button,e.xbutton.type==ButtonPress,0);
                }
            }
            while(XCheckTypedWindowEvent(sdpy, swin, MotionNotify, &e)!=False)
            {
                //printf("motion event\n");
                xmouse=e.xbutton.x_root;
                ymouse=e.xbutton.y_root;
            }
        }
        //printf("frame %d\n", frame++);
        usleep(60000);
        if(!use_shm)
        {
            image=CaptRoot(sdpy,sscr);
            DrawImage(tdpy,twin,image);
            XDestroyImage(image);
        }
        else
        {
//            XShmAttach(sdpy, &xshm_sinfo);
            XShmGetImage (sdpy, swin, simage, 0, 0, AllPlanes);
//            XShmAttach(sdpy, &xshm_tinfo);
            //printf("simage: w:%d h:%d d:%d\n",simage->width, simage->height, simage->depth);
            //printf("timage: w:%d h:%d d:%d\n",timage->width, timage->height, timage->depth);
            if(!emulate_events)
            {
                Window rwin,cwin;
                int xmouse,ymouse,x,y,mask;
                XQueryPointer(sdpy,swin,&rwin,&cwin,&xmouse,&ymouse,&x,&y,&mask);
                drawMouse(timage, xmouse, ymouse);
            }

            XShmPutImage (tdpy, twin, tgc, timage, 0, 0, 0, 0, timage->width, timage->height, False);
            //XPutImage (tdpy, twin, tgc, timage, 0, 0, 0, 0, timage->width, timage->height);
        }
        //XFlush(sdpy);
        XFlush(tdpy);
//        getchar();
    }
}


================================================
FILE: support/windump_hack/xorg.conf
================================================
# nvidia-xconfig: X configuration file generated by nvidia-xconfig
# nvidia-xconfig:  version 270.41.06  (buildmeister@swio-display-x86-rhel47-08.nvidia.com)  Mon Apr 18 15:14:00 PDT 2011

Section "ServerLayout"
    Identifier     "Layout0"
    Screen         "Screen0"
    Screen         "Screen1" RightOf "Screen0"
    InputDevice    "Keyboard0" "SendCoreEvents"
    #InputDevice    "Keyboard0" "CoreKeyboard"
    InputDevice    "Mouse0" "SendCoreEvents"
    #InputDevice    "Mouse0" "CorePointer"
EndSection

#Section "ServerFlags"
#    Option "AllowEmptyInput" "no"
#EndSection

Section "Files"
EndSection

Section "InputDevice"
    # generated from default
    Identifier     "Mouse0"
    Driver         "mouse"
    Option         "Protocol" "auto"
    Option         "Device" "/dev/psaux"
    Option         "Emulate3Buttons" "no"
    Option         "ZAxisMapping" "4 5"
EndSection

Section "InputDevice"
    # generated from default
    Identifier     "Keyboard0"
    Driver         "kbd"
EndSection

Section "Monitor"                                                       
    Identifier "Monitor0"
    VendorName     "Unknown"
    ModelName      "Unknown"
    HorizSync       28.0 - 73.0
    VertRefresh     43.0 - 72.0
    Option         "DPMS"
EndSection

Section "Device"
    Identifier     "Device1"
    Driver         "nvidia"
    VendorName     "NVIDIA Corporation"
    BusID          "PCI:1:0:0"
    Option         "IgnoreEDID"
    #Screen         0
EndSection

Section "Device"
    Identifier     "Device0"
    Driver         "intel"
    VendorName     "onboard"
    BusID          "PCI:0:2:0"
    #Screen         1
EndSection

Section "Screen"
    Identifier     "Screen1"   
    Device         "Device0"
    Monitor        "Monitor0"
    DefaultDepth    24
    SubSection     "Display"
        Depth       24
    EndSubSection
EndSection

Section "Screen"
    Identifier     "Screen0"
    Device         "Device1"
    Monitor        "Monitor0"
    DefaultDepth    24
    SubSection     "Display"
        Depth       24
        Modes      "1024x768"
    EndSubSection
EndSection

Download .txt
gitextract_flrrvk54/

├── Makefile
├── README.md
├── acpi_call.c
├── examples/
│   ├── asus1215n.sh
│   ├── dellL702X.sh
│   ├── m11xr2.sh
│   └── turn_off_gpu.sh
└── support/
    ├── query_dsdt.pl
    └── windump_hack/
        ├── windump.c
        └── xorg.conf
Download .txt
SYMBOL INDEX (17 symbols across 2 files)

FILE: acpi_call.c
  type proc_dir_entry (line 25) | struct proc_dir_entry
  function get_avail_bytes (line 31) | static size_t get_avail_bytes(void) {
  function acpi_result_to_string (line 42) | static int acpi_result_to_string(union acpi_object *result) {
  function do_acpi_call (line 95) | static void do_acpi_call(const char * method, int argc, union acpi_objec...
  function u8 (line 141) | u8 decodeHex(char *hex) {
  type file (line 260) | struct file
  function acpi_proc_write (line 263) | static int acpi_proc_write( struct file *filp, const char __user *buff,
  function acpi_proc_read (line 305) | static ssize_t acpi_proc_read( struct file *filp, char __user *buff,
  type file_operations (line 320) | struct file_operations
  function acpi_proc_read (line 327) | static int acpi_proc_read(char *page, char **start, off_t off,
  function init_acpi_call (line 349) | static int __init init_acpi_call(void)
  function unload_acpi_call (line 379) | static void __exit unload_acpi_call(void)

FILE: support/windump_hack/windump.c
  function XImage (line 15) | XImage *
  function Window (line 112) | Window CreateWindow(Display * dpy, int screen, int width, int height)
  function DrawImage (line 131) | void DrawImage(Display * dpy, Window win, XImage * image)
  function createShmImage (line 148) | void createShmImage(int w, int h, XShmSegmentInfo * sinfo, XShmSegmentIn...
  function drawMouse (line 170) | void drawMouse(XImage * img, int xm, int ym)
Condensed preview — 10 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (34K chars).
[
  {
    "path": "Makefile",
    "chars": 314,
    "preview": "obj-m := acpi_call.o\n\nKVERSION := $(shell uname -r)\nKDIR := /lib/modules/$(KVERSION)/build\nPWD := $(shell pwd)\n\ndefault:"
  },
  {
    "path": "README.md",
    "chars": 3094,
    "preview": "A kernel simple module that enables you to call ACPI methods by writing the\nmethod name followed by arguments to `/proc/"
  },
  {
    "path": "acpi_call.c",
    "chars": 11979,
    "preview": "/* Copyright (c) 2010: Michal Kottman */\n\n#include <linux/module.h>\n#include <linux/kernel.h>\n#include <linux/version.h>"
  },
  {
    "path": "examples/asus1215n.sh",
    "chars": 964,
    "preview": "#!/bin/sh\n# Power control for Asus 1215N Optimus\n# by Pete Eberlein\n\nif ! lsmod | grep -q acpi_call; then\n    echo \"Erro"
  },
  {
    "path": "examples/dellL702X.sh",
    "chars": 925,
    "preview": "#!/bin/sh\n# Power control for Dell L702X\n# by Jos Hickson\n# adapted from \"Power control for Asus 1215N Optimus by Pete E"
  },
  {
    "path": "examples/m11xr2.sh",
    "chars": 485,
    "preview": "#!/bin/sh\n# Based on m11xr2hack by George Shearer\n\nif ! lsmod | grep -q acpi_call; then\n    echo \"Error: acpi_call modul"
  },
  {
    "path": "examples/turn_off_gpu.sh",
    "chars": 1196,
    "preview": "#!/bin/bash\n\nif lsmod | grep -q acpi_call; then\nmethods=\"\n\\_SB.PCI0.P0P1.VGA._OFF\n\\_SB.PCI0.P0P2.VGA._OFF\n\\_SB_.PCI0.OVG"
  },
  {
    "path": "support/query_dsdt.pl",
    "chars": 1538,
    "preview": "#!/usr/bin/perl\nuse strict;\nuse Getopt::Long;\nuse Data::Dumper;\n\nmy ($dir,$debug,$mytokens);\n$dir = '.';\nGetOptions(\n\t  "
  },
  {
    "path": "support/windump_hack/windump.c",
    "chars": 9106,
    "preview": "#include <sys/ipc.h>\n#include <sys/shm.h>\n#include <X11/Xos.h>\n#include <X11/Xlib.h>\n#include <X11/Xutil.h>\n#include <X1"
  },
  {
    "path": "support/windump_hack/xorg.conf",
    "chars": 2098,
    "preview": "# nvidia-xconfig: X configuration file generated by nvidia-xconfig\n# nvidia-xconfig:  version 270.41.06  (buildmeister@s"
  }
]

About this extraction

This page contains the full source code of the norbusan/acpi_call GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 10 files (31.0 KB), approximately 9.5k tokens, and a symbol index with 17 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!