lkml.org 
[lkml]   [2010]   [Aug]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    SubjectRe: [PATCH] ideapad-laptop: add new driver
    From
    Date
    On Fri, 2010-08-13 at 10:34 +0100, David Woodhouse wrote:
    > Do you know how to restore it? Or do you have a copy of the 'lenovo-ec'
    > module that it apparently contains?
    Hello David,

    I do have that module: I coaxed it out of Lenovo with the help of
    gpl-violations.org as no source was available on my S10-3t. Since it is
    flagged as Dual BSD/GPL license, there should be no harm in posting it
    here. I hope it helps you in some way.

    Florian
    /*
    * lenovo_s11_ec.c Lenovo_S11 ACPI EC Extras
    */

    #include <linux/init.h>
    #include <linux/version.h>
    #include <linux/module.h>
    #include <linux/kernel.h> /* printk() */
    #include <linux/slab.h> /* kmalloc() */
    #include <linux/fs.h> /* everything... */
    #include <linux/errno.h> /* error codes */
    #include <linux/types.h> /* size_t */
    #include <linux/proc_fs.h>
    #include <linux/delay.h>
    #include <linux/fcntl.h> /* O_ACCMODE */
    #include <asm/system.h> /* cli(), *_flags */
    #include <asm/uaccess.h> /* copy_from/to_user */
    #include <asm/io.h> /* inb, outb */
    #include <linux/sched.h> /* set_cpus_allowed */
    #include <linux/acpi.h>
    #include <linux/seq_file.h>
    #include <acpi/acpi_drivers.h>

    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
    typedef unsigned long long evaluate_size_t;
    #else
    typedef unsigned long evaluate_size_t;
    #endif

    static DECLARE_MUTEX(gecn_sem);
    static DECLARE_MUTEX(secn_sem);

    static struct proc_dir_entry *lenovo_ec_fs_dir;
    static char *model = NULL;
    struct acpi_lenovo_cs2_device {
    acpi_handle handle;
    char DECN;
    char GECN;
    char SECN;
    };

    struct acpi_lenovo_cs2_device lenovo_cs2_device;
    static acpi_handle vpc0_handle;
    MODULE_LICENSE("Dual BSD/GPL");
    module_param(model, charp, S_IRUGO);
    /*
    * Proc handle for reading the status of ec device.
    */

    static int acpi_s11_ec_read_camera(struct seq_file *seq, void *offset)
    {
    char tmp;
    if(ec_read(0xb8,&tmp)){
    printk("ec_read fail\n");
    return -EFAULT;
    }
    seq_printf(seq, "%d\n",!(tmp & 0x8) == 0);
    return 0;
    }

    static int acpi_s11_ec_read_wifi(struct seq_file *seq, void *offset)
    {
    char tmp;
    if(ec_read(0xbb,&tmp)){
    printk("ec_read fail\n");
    return -EFAULT;
    }
    seq_printf(seq, "%d\n",!(tmp & 0x1) == 0);
    return 0;
    }

    static int acpi_s11_ec_read_dvme(struct seq_file *seq, void *offset)
    {
    char tmp;
    if(ec_read(0xb8,&tmp)){
    printk("ec_read fail\n");
    return -EFAULT;
    }
    seq_printf(seq, "%d\n",!(tmp & 0x80) == 0);
    return 0;
    }

    static int acpi_s11_ec_read_tp(struct seq_file *seq, void *offset)
    {
    char tmp;
    if(ec_write(0x00,0x1b)){
    printk("ec_write fail\n");
    return -EFAULT;
    }
    mdelay(10);
    if(ec_read(0x01,&tmp)){
    printk("ec_read_fail\n");
    return -EFAULT;
    }
    seq_printf(seq, "%d\n",tmp);
    return 0;
    }

    static int acpi_s11_ec_read_antenna(struct seq_file *seq, void *offset)
    {
    char tmp;
    if(ec_read(0xbb,&tmp)){
    printk("ec_read_fail\n");
    return -EFAULT;
    }
    seq_printf(seq, "%d\n",!(tmp & 0x10) == 0);
    return 0;
    }

    static int acpi_s11_ec_read_w3g(struct seq_file *seq, void *offset)
    {
    char tmp;
    if(ec_read(0xbb,&tmp)){
    printk("ec_read_fail\n");
    return -EFAULT;
    }
    seq_printf(seq, "%d\n",((tmp >> 6) & 0x1) == 1);
    return 0;
    }


    static int acpi_s11_ec_read_brightness(struct seq_file *seq, void *offset)
    {
    char tmp;
    int i;
    if(ec_read(0xb9,&tmp)){
    printk("ec_read fail\n");
    return -EFAULT;
    }
    seq_printf(seq, "levels: ");
    for(i=0;i<=100;i=i+10)
    seq_printf(seq," %d",i);
    seq_printf(seq, "\ncurrent: %d\n",tmp*10);
    return 0;
    }

    static int acpi_s11_ec_write_camera(struct file *file, const char __user *buffer, size_t count, loff_t *data)
    {
    char tmp;
    if(buffer[0]!='0' && buffer[0]!='1'){
    return count;
    }

    if(ec_read(0xb8,&tmp)){
    printk("ec_read fail\n");
    return -EFAULT;
    }
    ec_write(0xb8, buffer[0]== '1' ? (0x08 | tmp) : (~0x08 & tmp));
    return count;
    }

    static int acpi_s11_ec_write_wifi(struct file *file, const char __user *buffer, size_t count, loff_t *data)
    {
    char tmp;
    if(buffer[0]!='0' && buffer[0]!='1'){
    return count;
    }
    if(ec_read(0xbb,&tmp)){
    printk("ec_read fail\n");
    return -EFAULT;
    }
    ec_write(0xbb, buffer[0]== '1' ? (0x01 | tmp) : (~0x01 & tmp));
    return count;
    }

    static int acpi_s11_ec_write_dvme(struct file *file, const char __user *buffer, size_t count, loff_t *data)
    {
    char tmp;
    if(buffer[0] != '0' && buffer[0] != '1'){
    return count;
    }

    if(ec_read(0xb8,&tmp)){
    printk("ec_read fail\n");
    return -EFAULT;
    }
    ec_write(0xb8, buffer[0]== '1' ? (0x80 | tmp) : (~0x80 & tmp));
    return count;
    }


    static int acpi_s11_ec_write_brightness(struct file *file, const char __user *buffer, size_t count, loff_t *data)
    {
    unsigned int level = 0;
    char str[5] = { 0 };
    if(copy_from_user(str,buffer,count))
    return -EFAULT;
    str[count] = 0;
    level = simple_strtoul(str, NULL, 0);
    if(level > 100)
    return -EFAULT;
    if(ec_write(0xb9,(level / 10))){
    printk("ec_write fail\n");
    return -EFAULT;
    }
    return count;
    }

    static int acpi_s11_ec_write_w3g(struct file *file, const char __user *buffer, size_t count, loff_t *data)
    {
    char tmp;
    if(buffer[0]!='0' && buffer[0]!='1'){
    return count;
    }

    if(ec_read(0xbb,&tmp)){
    printk("ec_read fail\n");
    return -EFAULT;
    }
    ec_write(0xbb, buffer[0]== '1' ? (0x80 | tmp) : (~0x80 & tmp));
    return count;
    }



    static int acpi_s11_ec_camera_open_fs(struct inode *inode, struct file *file)
    {
    return single_open(file, acpi_s11_ec_read_camera, PDE(inode)->data);
    }

    static int acpi_s11_ec_wifi_open_fs(struct inode *inode, struct file *file)
    {
    return single_open(file, acpi_s11_ec_read_wifi, PDE(inode)->data);
    }

    static int acpi_s11_ec_tp_open_fs(struct inode *inode, struct file *file)
    {
    return single_open(file, acpi_s11_ec_read_tp, PDE(inode)->data);
    }

    static int acpi_s11_ec_antenna_open_fs(struct inode *inode, struct file *file)
    {
    return single_open(file, acpi_s11_ec_read_antenna, PDE(inode)->data);
    }

    static int acpi_s11_ec_w3g_open_fs(struct inode *inode, struct file *file)
    {
    return single_open(file, acpi_s11_ec_read_w3g, PDE(inode)->data);
    }


    static int acpi_s11_ec_dvme_open_fs(struct inode *inode, struct file *file)
    {
    return single_open(file, acpi_s11_ec_read_dvme, PDE(inode)->data);
    }

    static int acpi_s11_ec_brightness_open_fs(struct inode *inode, struct file *file)
    {
    return single_open(file, acpi_s11_ec_read_brightness, PDE(inode)->data);
    }

    static struct file_operations acpi_s11_ec_camera_ops = {
    .open = acpi_s11_ec_camera_open_fs,
    .read = seq_read,
    .write = acpi_s11_ec_write_camera,
    .llseek = seq_lseek,
    .release = single_release,
    .owner = THIS_MODULE,
    };

    static struct file_operations acpi_s11_ec_wifi_ops = {
    .open = acpi_s11_ec_wifi_open_fs,
    .read = seq_read,
    .write = acpi_s11_ec_write_wifi,
    .llseek = seq_lseek,
    .release = single_release,
    .owner = THIS_MODULE,
    };

    static struct file_operations acpi_s11_ec_tp_ops = {
    .open = acpi_s11_ec_tp_open_fs,
    .read = seq_read,
    .llseek = seq_lseek,
    .release = single_release,
    .owner = THIS_MODULE,
    };

    static struct file_operations acpi_s11_ec_antenna_ops = {
    .open = acpi_s11_ec_antenna_open_fs,
    .read = seq_read,
    .llseek = seq_lseek,
    .release = single_release,
    .owner = THIS_MODULE,
    };

    static struct file_operations acpi_s11_ec_w3g_ops = {
    .open = acpi_s11_ec_w3g_open_fs,
    .read = seq_read,
    .write = acpi_s11_ec_write_w3g,
    .llseek = seq_lseek,
    .release = single_release,
    .owner = THIS_MODULE,
    };

    static struct file_operations acpi_s11_ec_dvme_ops = {
    .open = acpi_s11_ec_dvme_open_fs,
    .read = seq_read,
    .write = acpi_s11_ec_write_dvme,
    .llseek = seq_lseek,
    .release = single_release,
    .owner = THIS_MODULE,
    };

    static struct file_operations acpi_s11_ec_brightness_ops = {
    .open = acpi_s11_ec_brightness_open_fs,
    .read = seq_read,
    .write = acpi_s11_ec_write_brightness,
    .llseek = seq_lseek,
    .release = single_release,
    .owner = THIS_MODULE,
    };


    static int acpi_s20_ec_read_antenna(struct seq_file *seq, void *offset)
    {
    char tmp;
    if(ec_read(0x52,&tmp)){
    printk("ec_read_fail\n");
    return -EFAULT;
    }
    seq_printf(seq, "%d\n",!(tmp & 0x01) == 0);
    return 0;
    }

    static int acpi_s20_ec_read_w3g(struct seq_file *seq, void *offset)
    {
    evaluate_size_t tmp;
    acpi_evaluate_integer(vpc0_handle, "_CFG", NULL,
    &tmp);
    seq_printf(seq, "%d\n",((tmp >> 17) & 0x1) == 1);
    return 0;
    }

    static int acpi_s20_ec_read_wifi(struct seq_file *seq, void *offset)
    {
    char tmp;
    if(ec_read(0x71,&tmp)){
    printk("ec_read fail\n");
    return -EFAULT;
    }
    seq_printf(seq, "%d\n",!(tmp & 0x1) == 0);
    return 0;
    }

    static int acpi_s20_ec_antenna_open_fs(struct inode *inode, struct file *file)
    {
    return single_open(file, acpi_s20_ec_read_antenna, PDE(inode)->data);
    }

    static int acpi_s20_ec_w3g_open_fs(struct inode *inode, struct file *file)
    {
    return single_open(file, acpi_s20_ec_read_w3g, PDE(inode)->data);
    }

    static int acpi_s20_ec_wifi_open_fs(struct inode *inode, struct file *file)
    {
    return single_open(file, acpi_s20_ec_read_wifi, PDE(inode)->data);
    }

    static struct file_operations acpi_s20_ec_antenna_ops = {
    .open = acpi_s20_ec_antenna_open_fs,
    .read = seq_read,
    .llseek = seq_lseek,
    .release = single_release,
    .owner = THIS_MODULE,
    };

    static struct file_operations acpi_s20_ec_w3g_ops = {
    .open = acpi_s20_ec_w3g_open_fs,
    .read = seq_read,
    .llseek = seq_lseek,
    .release = single_release,
    .owner = THIS_MODULE,
    };

    static struct file_operations acpi_s20_ec_wifi_ops = {
    .open = acpi_s20_ec_wifi_open_fs,
    .read = seq_read,
    .llseek = seq_lseek,
    .release = single_release,
    .owner = THIS_MODULE,
    };

    static int acpi_cs2_ec_read_w3g(struct seq_file *seq, void *offset)
    {
    evaluate_size_t tmp;
    union acpi_object arg0 = { ACPI_TYPE_INTEGER };
    struct acpi_object_list args = { 1, &arg0 };
    arg0.integer.value = 4;
    if (lenovo_cs2_device.GECN != 1){
    seq_printf(seq, "No device\n");
    return 0;
    }
    else{
    if (down_interruptible(&gecn_sem)){
    return -ERESTARTSYS;
    }
    acpi_evaluate_integer(lenovo_cs2_device.handle, "GECN", &args, &tmp);
    up(&gecn_sem);
    seq_printf(seq, "%d\n",(int)tmp);
    return 0;
    }
    }


    static int acpi_cs2_ec_read_antenna(struct seq_file *seq, void *offset)
    {
    evaluate_size_t tmp;
    union acpi_object arg0 = { ACPI_TYPE_INTEGER };
    struct acpi_object_list args = { 1, &arg0 };
    arg0.integer.value = 5;
    if (lenovo_cs2_device.GECN != 1){
    seq_printf(seq, "No device\n");
    return 0;
    }
    else{
    if (down_interruptible(&gecn_sem)){
    return -ERESTARTSYS;
    }
    acpi_evaluate_integer(lenovo_cs2_device.handle, "GECN", &args, &tmp);
    up(&gecn_sem);
    seq_printf(seq, "%d\n",(int)tmp);
    return 0;
    }

    }

    static int acpi_cs2_ec_read_wifi(struct seq_file *seq, void *offset)
    {
    evaluate_size_t tmp;
    union acpi_object arg0 = { ACPI_TYPE_INTEGER };
    struct acpi_object_list args = { 1, &arg0 };
    arg0.integer.value = 2;
    if (lenovo_cs2_device.GECN != 1){
    seq_printf(seq, "No device\n");
    return 0;
    }
    else{
    if (down_interruptible(&gecn_sem)){
    return -ERESTARTSYS;
    }
    acpi_evaluate_integer(lenovo_cs2_device.handle, "GECN", &args, &tmp);
    up(&gecn_sem);
    seq_printf(seq, "%d\n",(int)tmp);
    return 0;
    }

    }

    static int acpi_cs2_ec_read_camera(struct seq_file *seq, void *offset)
    {
    evaluate_size_t tmp;
    union acpi_object arg0 = { ACPI_TYPE_INTEGER };
    struct acpi_object_list args = { 1, &arg0 };
    arg0.integer.value = 1;
    if (lenovo_cs2_device.GECN != 1){
    seq_printf(seq, "No device\n");
    return 0;
    }
    else{
    if (down_interruptible(&gecn_sem)){
    return -ERESTARTSYS;
    }
    acpi_evaluate_integer(lenovo_cs2_device.handle, "GECN", &args, &tmp);
    up(&gecn_sem);
    seq_printf(seq, "%d\n",(int)tmp);
    return 0;
    }

    }

    static int acpi_cs2_ec_read_bluetooth(struct seq_file *seq, void *offset)
    {
    evaluate_size_t tmp;
    union acpi_object arg0 = { ACPI_TYPE_INTEGER };
    struct acpi_object_list args = { 1, &arg0 };
    arg0.integer.value = 3;
    if (lenovo_cs2_device.GECN != 1){
    seq_printf(seq, "No device\n");
    return 0;
    }
    else{
    if (down_interruptible(&gecn_sem)){
    return -ERESTARTSYS;
    }
    acpi_evaluate_integer(lenovo_cs2_device.handle, "GECN", &args, &tmp);
    up(&gecn_sem);
    seq_printf(seq, "%d\n",(int)tmp);
    return 0;
    }

    }

    static int acpi_cs2_ec_write_camera(struct file *file, const char __user *buffer, size_t count, loff_t *data)
    {
    union acpi_object in_arg[2];
    struct acpi_object_list args = { 2, in_arg };
    if(buffer[0]!='0' && buffer[0]!='1'){
    return count;
    }
    in_arg[0].type = ACPI_TYPE_INTEGER;
    in_arg[0].integer.value = 1;
    in_arg[1].type = ACPI_TYPE_INTEGER;
    in_arg[1].integer.value = (buffer[0] == '1');
    if (lenovo_cs2_device.SECN == 1){
    if (down_interruptible(&secn_sem)){
    return -ERESTARTSYS;
    }
    acpi_evaluate_object(lenovo_cs2_device.handle, "SECN", &args, NULL);
    up(&secn_sem);
    }
    return count;
    }

    static int acpi_cs2_ec_write_wifi(struct file *file, const char __user *buffer, size_t count, loff_t *data)
    {
    union acpi_object in_arg[2];
    struct acpi_object_list args = { 2, in_arg };
    if(buffer[0]!='0' && buffer[0]!='1'){
    return count;
    }
    in_arg[0].type = ACPI_TYPE_INTEGER;
    in_arg[0].integer.value = 2;
    in_arg[1].type = ACPI_TYPE_INTEGER;
    in_arg[1].integer.value = (buffer[0] == '1');
    if (lenovo_cs2_device.SECN == 1){
    if (down_interruptible(&secn_sem)){
    return -ERESTARTSYS;
    }
    acpi_evaluate_object(lenovo_cs2_device.handle, "SECN", &args, NULL);
    up(&secn_sem);
    }
    return count;
    }

    static int acpi_cs2_ec_write_w3g(struct file *file, const char __user *buffer, size_t count, loff_t *data)
    {
    union acpi_object in_arg[2];
    struct acpi_object_list args = { 2, in_arg };
    if(buffer[0]!='0' && buffer[0]!='1'){
    return count;
    }
    in_arg[0].type = ACPI_TYPE_INTEGER;
    in_arg[0].integer.value = 4;
    in_arg[1].type = ACPI_TYPE_INTEGER;
    in_arg[1].integer.value = (buffer[0] == '1');
    if (lenovo_cs2_device.SECN == 1){
    if (down_interruptible(&secn_sem)){
    return -ERESTARTSYS;
    }
    acpi_evaluate_object(lenovo_cs2_device.handle, "SECN", &args, NULL);
    up(&secn_sem);
    }
    return count;
    }

    static int acpi_cs2_ec_write_bluetooth(struct file *file, const char __user *buffer, size_t count, loff_t *data)
    {
    union acpi_object in_arg[2];
    struct acpi_object_list args = { 2, in_arg };
    if(buffer[0]!='0' && buffer[0]!='1'){
    return count;
    }
    in_arg[0].type = ACPI_TYPE_INTEGER;
    in_arg[0].integer.value = 3;
    in_arg[1].type = ACPI_TYPE_INTEGER;
    in_arg[1].integer.value = (buffer[0] == '1');
    if (lenovo_cs2_device.SECN == 1){
    if (down_interruptible(&secn_sem)){
    return -ERESTARTSYS;
    }
    acpi_evaluate_object(lenovo_cs2_device.handle, "SECN", &args, NULL);
    up(&secn_sem);
    }
    return count;
    }

    static int acpi_cs2_ec_antenna_open_fs(struct inode *inode, struct file *file)
    {
    return single_open(file, acpi_cs2_ec_read_antenna, PDE(inode)->data);
    }

    static int acpi_cs2_ec_w3g_open_fs(struct inode *inode, struct file *file)
    {
    return single_open(file, acpi_cs2_ec_read_w3g, PDE(inode)->data);
    }

    static int acpi_cs2_ec_wifi_open_fs(struct inode *inode, struct file *file)
    {
    return single_open(file, acpi_cs2_ec_read_wifi, PDE(inode)->data);
    }

    static int acpi_cs2_ec_camera_open_fs(struct inode *inode, struct file *file)
    {
    return single_open(file, acpi_cs2_ec_read_camera, PDE(inode)->data);
    }

    static int acpi_cs2_ec_bluetooth_open_fs(struct inode *inode, struct file *file)
    {
    return single_open(file, acpi_cs2_ec_read_bluetooth, PDE(inode)->data);
    }

    static struct file_operations acpi_cs2_ec_antenna_ops = {
    .open = acpi_cs2_ec_antenna_open_fs,
    .read = seq_read,
    .llseek = seq_lseek,
    .release = single_release,
    .owner = THIS_MODULE,
    };

    static struct file_operations acpi_cs2_ec_w3g_ops = {
    .open = acpi_cs2_ec_w3g_open_fs,
    .read = seq_read,
    .write = acpi_cs2_ec_write_w3g,
    .llseek = seq_lseek,
    .release = single_release,
    .owner = THIS_MODULE,
    };

    static struct file_operations acpi_cs2_ec_wifi_ops = {
    .open = acpi_cs2_ec_wifi_open_fs,
    .read = seq_read,
    .write = acpi_cs2_ec_write_wifi,
    .llseek = seq_lseek,
    .release = single_release,
    .owner = THIS_MODULE,
    };

    static struct file_operations acpi_cs2_ec_camera_ops = {
    .open = acpi_cs2_ec_camera_open_fs,
    .read = seq_read,
    .write = acpi_cs2_ec_write_camera,
    .llseek = seq_lseek,
    .release = single_release,
    .owner = THIS_MODULE,
    };

    static struct file_operations acpi_cs2_ec_bluetooth_ops = {
    .open = acpi_cs2_ec_bluetooth_open_fs,
    .read = seq_read,
    .write = acpi_cs2_ec_write_bluetooth,
    .llseek = seq_lseek,
    .release = single_release,
    .owner = THIS_MODULE,
    };

    static int acpi_m3b_ec_read_antenna(struct seq_file *seq, void *offset)
    {
    char tmp;
    if(ec_read(0x52,&tmp)){
    printk("ec_read_fail\n");
    return -EFAULT;
    }
    seq_printf(seq, "%d\n",!(tmp & 0x01) == 0);
    return 0;
    }

    static int acpi_m3b_ec_antenna_open_fs(struct inode *inode, struct file *file)
    {
    return single_open(file, acpi_m3b_ec_read_antenna, PDE(inode)->data);
    }

    static struct file_operations acpi_m3b_ec_antenna_ops = {
    .open = acpi_m3b_ec_antenna_open_fs,
    .read = seq_read,
    .llseek = seq_lseek,
    .release = single_release,
    .owner = THIS_MODULE,
    };

    /*
    * This function is used to regiter the ec device's proc file and operations
    */
    static int lenovo_ec_proc_add(char *name,struct file_operations *acpi_ec_ops,struct proc_dir_entry *dir)
    {
    struct proc_dir_entry * entry = NULL;
    entry = create_proc_entry(name, S_IRUGO,
    dir);
    if (!entry)
    return -ENODEV;
    else {
    entry->proc_fops = acpi_ec_ops;
    entry->data = NULL;
    entry->owner = THIS_MODULE;
    }
    return 0;
    }

    /*
    * The lenovo S11 has six ec devices : camera, wifi, brightness controller, touch pad, dvm enalbe, antenna.
    */

    static int lenovo_s11_ec_init(void)
    {
    int result;
    printk("Lenovo s11 ec driver init\n");
    result = lenovo_ec_proc_add("camera",&acpi_s11_ec_camera_ops,lenovo_ec_fs_dir);
    if(result == -ENODEV)
    return result;
    result = lenovo_ec_proc_add("wifi", &acpi_s11_ec_wifi_ops,lenovo_ec_fs_dir);
    if(result == -ENODEV)
    return result;
    result = lenovo_ec_proc_add("tp", &acpi_s11_ec_tp_ops,lenovo_ec_fs_dir);
    if(result == -ENODEV)
    return result;
    result = lenovo_ec_proc_add("dvme", &acpi_s11_ec_dvme_ops,lenovo_ec_fs_dir);
    if(result == -ENODEV)
    return result;
    result = lenovo_ec_proc_add("brightness", &acpi_s11_ec_brightness_ops,lenovo_ec_fs_dir);
    if(result == -ENODEV)
    return result;
    result = lenovo_ec_proc_add("antenna", &acpi_s11_ec_antenna_ops,lenovo_ec_fs_dir);
    if(result == -ENODEV)
    return result;
    result = lenovo_ec_proc_add("w3g", &acpi_s11_ec_w3g_ops,lenovo_ec_fs_dir);
    if(result == -ENODEV)
    return result;

    return 0;
    }

    static void lenovo_s11_ec_exit(void)
    {
    printk("Lenovo_s11 ec driver remove\n");
    remove_proc_entry("camera", lenovo_ec_fs_dir);
    remove_proc_entry("wifi", lenovo_ec_fs_dir);
    remove_proc_entry("tp", lenovo_ec_fs_dir);
    remove_proc_entry("dvme", lenovo_ec_fs_dir);
    remove_proc_entry("brightness", lenovo_ec_fs_dir);
    remove_proc_entry("antenna", lenovo_ec_fs_dir);
    remove_proc_entry("w3g", lenovo_ec_fs_dir);
    return;
    }

    static acpi_status
    find_vpc0(acpi_handle handle, u32 lvl, void *context, void **rv)
    {

    char prefix[80] = {'\0'};
    int *vpc;
    struct acpi_buffer buffer = {sizeof(prefix), prefix };
    vpc = context;
    acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);

    if (strcmp(prefix,"VPC0") == 0){
    vpc0_handle = handle;
    *vpc = 1;
    }
    return AE_OK;
    }

    static int lenovo_s20_vpn_init(void)
    {
    int vpc0 = 0;
    acpi_handle h_dummy1;
    acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
    ACPI_UINT32_MAX, find_vpc0, &vpc0, NULL);
    if (vpc0 == 1){
    if (ACPI_SUCCESS(acpi_get_handle(vpc0_handle, "_CFG", &h_dummy1)))
    return 0;
    }
    return -1;
    }


    static int lenovo_s20_ec_init(void)
    {
    int result;
    printk("Lenovo s20 ec driver init\n");
    result = lenovo_s20_vpn_init();
    if(result == -1)
    return -ENODEV;
    result = lenovo_ec_proc_add("antenna",&acpi_s20_ec_antenna_ops,lenovo_ec_fs_dir);
    if(result == -ENODEV)
    return result;
    result = lenovo_ec_proc_add("w3g",&acpi_s20_ec_w3g_ops,lenovo_ec_fs_dir);
    if(result == -ENODEV)
    return result;
    result = lenovo_ec_proc_add("wifi",&acpi_s20_ec_wifi_ops,lenovo_ec_fs_dir);
    if(result == -ENODEV)
    return result;
    return 0;
    }

    static void lenovo_s20_ec_exit(void)
    {
    printk("Lenovo_s20 ec driver remove\n");
    remove_proc_entry("antenna", lenovo_ec_fs_dir);
    remove_proc_entry("w3g", lenovo_ec_fs_dir);
    remove_proc_entry("wifi", lenovo_ec_fs_dir);
    }

    static acpi_status
    find_sb(acpi_handle handle, u32 lvl, void *context, void **rv)
    {

    char prefix[80] = {'\0'};
    int *sb;
    struct acpi_buffer buffer = {sizeof(prefix), prefix };
    sb = context;
    acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);
    if (strcmp(prefix,"_SB_") == 0){
    lenovo_cs2_device.handle = handle;
    *sb = 1;
    }
    return AE_OK;
    }

    static int lenovo_cs2_rootpath_init(void)
    {
    int sb = 0;
    acpi_handle h_dummy1;
    acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
    ACPI_UINT32_MAX, find_sb, &sb, NULL);
    if (sb == 1){
    if (ACPI_SUCCESS(acpi_get_handle(lenovo_cs2_device.handle, "DECN", &h_dummy1)))
    lenovo_cs2_device.DECN = 1;
    else
    lenovo_cs2_device.DECN = 0;
    if (ACPI_SUCCESS(acpi_get_handle(lenovo_cs2_device.handle, "SECN", &h_dummy1)))
    lenovo_cs2_device.SECN = 1;
    else
    lenovo_cs2_device.SECN = 0;
    if (ACPI_SUCCESS(acpi_get_handle(lenovo_cs2_device.handle, "GECN", &h_dummy1)))
    lenovo_cs2_device.GECN = 1;
    else
    lenovo_cs2_device.GECN = 0;
    return 0;
    }
    else{
    lenovo_cs2_device.GECN = 0;
    lenovo_cs2_device.SECN = 0;
    lenovo_cs2_device.DECN = 0;
    return -1;
    }
    }

    static int lenovo_cs2_ec_init(void)
    {
    int result;
    printk("Lenovo cs2 ec driver init\n");
    result = lenovo_cs2_rootpath_init();
    if(result == -1)
    return -ENODEV;
    result = lenovo_ec_proc_add("antenna",&acpi_cs2_ec_antenna_ops,lenovo_ec_fs_dir);
    if(result == -ENODEV)
    return result;
    result = lenovo_ec_proc_add("w3g",&acpi_cs2_ec_w3g_ops,lenovo_ec_fs_dir);
    if(result == -ENODEV)
    return result;
    result = lenovo_ec_proc_add("wifi",&acpi_cs2_ec_wifi_ops,lenovo_ec_fs_dir);
    if(result == -ENODEV)
    return result;
    result = lenovo_ec_proc_add("camera",&acpi_cs2_ec_camera_ops,lenovo_ec_fs_dir);
    if(result == -ENODEV)
    return result;
    result = lenovo_ec_proc_add("bluetooth",&acpi_cs2_ec_bluetooth_ops,lenovo_ec_fs_dir);
    if(result == -ENODEV)
    return result;
    return 0;
    }

    static void lenovo_cs2_ec_exit(void)
    {
    printk("Lenovo_cs2 ec driver remove\n");
    remove_proc_entry("antenna", lenovo_ec_fs_dir);
    remove_proc_entry("w3g", lenovo_ec_fs_dir);
    remove_proc_entry("wifi", lenovo_ec_fs_dir);
    remove_proc_entry("camera", lenovo_ec_fs_dir);
    }

    static int lenovo_m3b_ec_init(void)
    {
    /* Use the acpi method interface same as Lenovo CS2*/
    int result;
    printk("Lenovo mariana-3b ec driver init\n");
    result = lenovo_cs2_rootpath_init();
    if(result == -1)
    return -ENODEV;
    result = lenovo_ec_proc_add("antenna",&acpi_cs2_ec_antenna_ops,lenovo_ec_fs_dir);
    if(result == -ENODEV)
    return result;
    result = lenovo_ec_proc_add("w3g",&acpi_cs2_ec_w3g_ops,lenovo_ec_fs_dir);
    if(result == -ENODEV)
    return result;
    result = lenovo_ec_proc_add("wifi",&acpi_cs2_ec_wifi_ops,lenovo_ec_fs_dir);
    if(result == -ENODEV)
    return result;
    result = lenovo_ec_proc_add("camera",&acpi_cs2_ec_camera_ops,lenovo_ec_fs_dir);
    if(result == -ENODEV)
    return result;
    result = lenovo_ec_proc_add("bluetooth",&acpi_cs2_ec_bluetooth_ops,lenovo_ec_fs_dir);
    if(result == -ENODEV)
    return result;
    return 0;
    }

    static void lenovo_m3b_ec_exit(void)
    {
    printk("Lenovo mariana-3b ec driver remove\n");
    remove_proc_entry("antenna", lenovo_ec_fs_dir);
    }

    static int lenovo_ec_init(void)
    {
    lenovo_ec_fs_dir = proc_mkdir("lenovo",acpi_root_dir);
    if (model != NULL){
    if (strncmp(model, "S11", 3) == 0)
    lenovo_s11_ec_init();
    else if (strncmp(model, "S20", 3) == 0)
    lenovo_s20_ec_init();
    else if (strncmp(model, "CS2", 3) == 0)
    lenovo_cs2_ec_init();
    else if (strncmp(model, "M3B", 3) == 0)
    lenovo_m3b_ec_init();
    }
    return 0;
    }

    static void lenovo_ec_exit(void)
    {
    if (model != NULL){
    if (strncmp(model, "S11", 3) == 0)
    lenovo_s11_ec_exit();
    else if (strncmp(model, "S20", 3) == 0)
    lenovo_s20_ec_exit();
    else if (strncmp(model, "CS2", 3) == 0)
    lenovo_cs2_ec_exit();
    else if (strncmp(model, "M3B", 3) == 0)
    lenovo_m3b_ec_exit();
    }
    remove_proc_entry("lenovo", acpi_root_dir);
    }

    module_init(lenovo_ec_init);
    module_exit(lenovo_ec_exit);

    \
     
     \ /
      Last update: 2010-08-15 19:11    [W:0.097 / U:124.896 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site