public inbox for linux-acpi@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH]Panasonic Hotkey Driver
@ 2004-07-31 14:17 Hiroshi Miura
  2004-08-18  5:04 ` [PATCH][ACPI] Panasonic " Len Brown
  0 siblings, 1 reply; 27+ messages in thread
From: Hiroshi Miura @ 2004-07-31 14:17 UTC (permalink / raw)
  To: Len Brown
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	letsnote-tech-eXqGM+LsbTTAqL8d+zIrHngSJqDPrsil

Hi,

This is a  hotkey driver for Panasonic Lets note series. 
I tested this driver on 2.6.7 kernel and Panasonic CF-R3 laptop. 
Using this driver, users can handle Fn+Fx key (except for Fn+F3) with acpid.

The event is for example 'HKEY HKEY 00000080 0000001' for Fn+F1.


sample scripts as follows

# /etc/acpi/events/hotkey
event=HKEY.*
action=/etc/acpi/hotkey.sh "%e"

hotkey.sh is

#!/bin/sh
set $*
# Take care about the way events are reported
key="$4";

case "$key" in
     0000000a)
           logger "acpid: received a suspend request"
	   echo 1 > /proc/swsusp/activate
	   hwclock --hctosys
	   break
           ;;
     *)
           logger "acpid: action $key is not defined"
           ;;
esac




patch is follows

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/07/26 11:50:39+09:00 miura@da-cha.org 
#   Panasonic Laptop Extra driver.
#   This adds support of hotkey (Fn+Fx) on Panasonic Lets note Laptop series.
#   Loding this driver, user can get event through acpid like "HKEY HKEY 0000080 000001"
#   
#   Signed-off-by: Hiroshi Miura <miura@da-cha.org>
# 
# drivers/acpi/pcc_acpi.c
#   2004/07/26 11:50:23+09:00 miura@da-cha.org +518 -0
# 
# drivers/acpi/pcc_acpi.c
#   2004/07/26 11:50:23+09:00 miura@da-cha.org +0 -0
#   BitKeeper file /home/miura/kernel/linux-2.6.7-hm/drivers/acpi/pcc_acpi.c
# 
# drivers/acpi/Makefile
#   2004/07/26 11:50:23+09:00 miura@da-cha.org +1 -0
#   add Panasonic Laptop Extra driver entry
# 
# drivers/acpi/Kconfig
#   2004/07/26 11:50:23+09:00 miura@da-cha.org +20 -0
#   add Panasonic Laptop Extra driver entry
# 
diff -Nru a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
--- a/drivers/acpi/Kconfig	2004-07-27 12:44:53 +09:00
+++ b/drivers/acpi/Kconfig	2004-07-27 12:44:53 +09:00
@@ -204,6 +204,26 @@
 	  If you have a legacy free Toshiba laptop (such as the Libretto L1
 	  series), say Y.
 
+config ACPI_PCC
+	tristate "Panasonic Laptop Extras"
+	depends on X86
+	depends on ACPI_INTERPRETER
+	default m
+	---help---
+	  This driver adds support for access to certain system settings
+	  on panasonic Let's Note laptops. 
+
+	  On these machines, all hotkey is handled through the ACPI.
+	  This driver is required for access to controls not covered
+	  by the general ACPI drivers, such as LCD brightness, video output,
+	  etc.
+
+	  More information about this driver will be available at
+	  <http://www.da-cha.org/letsnote/>
+
+	  If you have a panasonic lets note laptop (such as the CF-T2, Y2,
+	  R2, W2, R3), say Y.
+
 config ACPI_DEBUG
 	bool "Debug Statements"
 	depends on ACPI_INTERPRETER
diff -Nru a/drivers/acpi/Makefile b/drivers/acpi/Makefile
--- a/drivers/acpi/Makefile	2004-07-27 12:44:53 +09:00
+++ b/drivers/acpi/Makefile	2004-07-27 12:44:53 +09:00
@@ -47,4 +47,5 @@
 obj-$(CONFIG_ACPI_NUMA)		+= numa.o
 obj-$(CONFIG_ACPI_ASUS)		+= asus_acpi.o
 obj-$(CONFIG_ACPI_TOSHIBA)	+= toshiba_acpi.o
+obj-$(CONFIG_ACPI_PCC)		+= pcc_acpi.o
 obj-$(CONFIG_ACPI_BUS)		+= scan.o 
diff -Nru a/drivers/acpi/pcc_acpi.c b/drivers/acpi/pcc_acpi.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/acpi/pcc_acpi.c	2004-07-27 12:44:53 +09:00
@@ -0,0 +1,518 @@
+/*
+ *  Panasonic HotKey control Extra driver
+ *  (C) 2004 Hiroshi Miura <miura@da-cha.org>
+ *  (C) 2004 NTT DATA Intellilink Co. http://www.intellilink.co.jp/
+ *  All Rights Reserved
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as 
+ *  publicshed by the Free Software Foundation.
+ *
+ *  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.
+ * *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  The devolpment page for this driver will be located at
+ *  http://www.da-cha.org/
+ *
+ *---------------------------------------------------------------------------
+ *
+ * ChangeLog:
+ *	Jul.25, 2004	Hiroshi Miura <miura@da-cha.org>
+ *		- v0.4  first post version
+ *		-       add debug function to retrive SIFR
+ *
+ *	Jul.24, 2004	Hiroshi Miura <miura@da-cha.org>
+ *		- v0.3  get proper status of hotkey
+ *
+ *      Jul.22, 2004	Hiroshi Miura <miura@da-cha.org>
+ *		- v0.2  add HotKey handler
+ *
+ *      Jul.17, 2004	Hiroshi Miura <miura@da-cha.org>
+ *		- v0.1  based on acpi video driver
+ *
+ *  TODO
+ *	everything all
+ *
+ */
+
+#define ACPI_PCC_VERSION	"0.4"
+#define PROC_INTERFACE_VERSION	2
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+
+MODULE_AUTHOR("Hiroshi Miura");
+MODULE_DESCRIPTION("ACPI HotKey driver for lets note");
+MODULE_LICENSE("GPL");
+
+#define LOGPREFIX "acpi_pcc: "
+
+/****************************************************
+ * Define ACPI PATHs 
+ ****************************************************/
+/* crt/lcd hot key definitions */
+#define DEVICE_NAME_VGA		"\\_SB_.PCI0.GRFX"
+#define DEVICE_NAME_CRT		"CRT1"
+#define DEVICE_NAME_LCD		"LCD1"
+#define METHOD_CHGD		"\\_SB_.CHGD"
+
+/* Lets note hotkeys definitions */
+#define DEVICE_NAME_HKEY 	"\\_SB_.HKEY"
+#define METHOD_HKEY_QUERY	"HINF"
+
+/* ACPI BIOS inside use only? */
+#define METHOD_HKEY_RESET	"HRES"
+#define METHOD_HKEY_SAVE	"HSAV"
+#define METHOD_HKEY_HIND	"HIND"
+
+/* event read/write functions */
+#define METHOD_HKEY_SQTY	"SQTY"
+#define METHOD_HKEY_SINF	"SINF"
+#define METHOD_HKEY_SSET	"SSET"
+
+
+/* device(HKEY) definitions */
+#define HKEY_HID		"MAT0019"
+#define HKEY_NOTIFY		 0x80
+
+/*******************************************************************
+ *
+ * definitions for /proc/ interface
+ *
+ *******************************************************************/
+#define PROC_PCC		"pcc"
+
+#define ACPI_HOTKEY_DRIVER_NAME "PCC HotKey Driver"
+#define ACPI_HOTKEY_DEVICE_NAME "HotKey"
+#define ACPI_HOTKEY_CLASS "HKEY"
+
+static int acpi_hotkey_add (struct acpi_device *device);
+static int acpi_hotkey_remove (struct acpi_device *device, int type);
+
+static struct acpi_driver acpi_hotkey_driver = {
+	.name =		ACPI_HOTKEY_DRIVER_NAME,
+	.class =	ACPI_HOTKEY_CLASS,
+	.ids =		HKEY_HID,
+	.ops =		{
+				.add =		acpi_hotkey_add,
+				.remove =	acpi_hotkey_remove,
+			},
+};
+
+struct acpi_hotkey {
+	acpi_handle		handle;
+	struct acpi_device	*device;
+	unsigned long		status;
+};
+
+
+/*
+ * utility functions
+ */
+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)
+{
+	acpi_handle handle;
+	acpi_status status;
+
+	status = acpi_get_handle(0, (char*)methodName, &handle);
+	return !ACPI_FAILURE(status);
+}
+
+#if 0
+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.pointer = in_objs;
+	in_objs[0].type = ACPI_TYPE_INTEGER;
+	in_objs[0].integer.value = val;
+
+	status = acpi_evaluate_object(0, (char*)methodName, &params, 0);
+	return (status == AE_OK);
+}
+#endif
+
+static int
+read_acpi_int(acpi_handle handle, const char* methodName, int* pVal)
+{
+	struct acpi_buffer results;
+	union acpi_object out_objs[1];
+	acpi_status status;
+
+	results.length = sizeof(out_objs);
+	results.pointer = out_objs;
+
+	status = acpi_evaluate_object(handle, (char*)methodName, 0, &results);
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_INFO "acpi evaluate error on %s\n", methodName);
+		return (-EFAULT);
+	}
+
+	if (out_objs[0].type == ACPI_TYPE_INTEGER) {
+		*pVal = out_objs[0].integer.value;
+	} else {
+		printk(KERN_INFO "return value is not int\n");
+		status = AE_ERROR;
+	}
+
+	return (status == AE_OK);
+}
+
+static struct proc_dir_entry*	acpi_pcc_dir;
+
+typedef struct _ProcItem
+{
+	const char* name;
+	char* (*read_func)(char*);
+	unsigned long (*write_func)(const char*, unsigned long);
+} ProcItem;
+
+
+/* register utils for proc handler */
+static int
+dispatch_read(char* page, char** start, off_t off, int count, int* eof,
+	ProcItem* item)
+{
+	char* p = page;
+	int len;
+
+	if (off == 0)
+		p = item->read_func(p);
+
+	/* ISSUE: I don't understand this code */
+	len = (p - page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	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)
+{
+	int result;
+	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 (copy_from_user(tmp_buffer, buffer, count)) {
+		result = -EFAULT;
+	}
+	else {
+		tmp_buffer[count] = 0;
+		result = item->write_func(tmp_buffer, count);
+	}
+	kfree(tmp_buffer);
+	return result;
+}
+
+/*
+ * proc file handlers
+ */
+#ifdef DEBUG_PCC_VGA
+static unsigned long
+write_chgd(const char* buffer, unsigned long count)
+{
+	int value;
+	acpi_status status;
+
+	if (sscanf(buffer, "%i", &value) == 1 && value >= 0 && value < 2) {
+		if (value == 0) 
+			/* do nothing */
+			status = AE_OK;
+		else {
+			status = acpi_evaluate_object(0, METHOD_CHGD, 0 , 0);
+		}
+		if (ACPI_FAILURE(status)) {
+			printk(KERN_INFO LOGPREFIX "fail evaluate CHGD()\n");
+			return -EFAULT;
+		}
+	}
+	return count;
+
+}
+
+static char*
+read_nothing(char* p)
+{
+	/* nothing to do*/
+	return p;
+}
+#endif
+
+static char*
+read_hkey_status(char* p)
+{
+	acpi_status status;
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	union acpi_object *hkey = NULL;
+	int i, num_sifr;
+
+	if (!read_acpi_int(NULL, DEVICE_NAME_HKEY "." METHOD_HKEY_SQTY, &num_sifr)){
+		printk(KERN_INFO LOGPREFIX "evaluation error HKEY.SQTY\n");
+		return p;
+	}
+
+	status = acpi_evaluate_object(NULL, DEVICE_NAME_HKEY "." METHOD_HKEY_SINF, 0 , &buffer);
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_INFO LOGPREFIX "evaluation error HEKY.SINF\n");
+		return p;
+	}
+	hkey = (union acpi_object *) buffer.pointer;
+	if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) {
+		printk(KERN_INFO LOGPREFIX "Invalid HKEY.SINF\n");
+		goto end;
+	}
+	
+	if (num_sifr != hkey->package.count) {
+		printk(KERN_INFO LOGPREFIX "SQTY is not equal to SINF length?\n");
+		goto end;
+	}
+
+	for (i = 0; i < hkey->package.count; i++) {
+		union acpi_object *element = &(hkey->package.elements[i]);
+		if (likely(element->type == ACPI_TYPE_INTEGER)) {
+			p += sprintf(p, "0x%02x,\n", (unsigned int)element->integer.value);
+		} else
+			printk(KERN_INFO LOGPREFIX "Invalid HKEY.SINF value\n");
+	}
+end:
+	acpi_os_free(buffer.pointer);
+	return p;
+}
+
+
+static char*
+read_version(char* p)
+{
+	p += sprintf(p, "%s version %s\n", ACPI_HOTKEY_DRIVER_NAME, ACPI_PCC_VERSION);
+	p += sprintf(p, "proc_interface version %d\n", PROC_INTERFACE_VERSION);
+	return p;
+}
+
+
+/* hotkey driver */
+static int
+acpi_hotkey_get_key(struct acpi_hotkey *hotkey)
+{
+	int result;
+	int status;
+
+	status = read_acpi_int(hotkey->handle, METHOD_HKEY_QUERY, &result);
+	if (!status) {
+		printk(KERN_INFO LOGPREFIX "error getting hotkey status\n");
+	} else
+		hotkey->status = result;
+
+	return (status);
+}
+
+void
+acpi_hotkey_notify(acpi_handle handle, u32 event, void *data)
+{
+	struct acpi_hotkey	*hotkey = (struct acpi_hotkey *) data;
+
+	if (!hotkey || !hotkey->device)
+		return;
+
+	switch(event) {
+	case HKEY_NOTIFY:
+		if (acpi_hotkey_get_key(hotkey))
+			acpi_bus_generate_event(hotkey->device, event, hotkey->status);
+		break;
+	default:
+		/* nothing to do */
+		break;
+	}
+
+	return;
+}
+
+static int
+acpi_hotkey_add (struct acpi_device *device)
+{
+	int			result = 0;
+	acpi_status		status = AE_OK;
+	struct acpi_hotkey	*hotkey = NULL;
+
+	if (!device)
+		return (-EINVAL);
+
+	hotkey = kmalloc(sizeof(struct acpi_hotkey), GFP_KERNEL);
+	if (!hotkey)
+		return (-ENOMEM);
+
+	memset(hotkey, 0, sizeof(struct acpi_hotkey));
+
+	hotkey->device = device;
+	hotkey->handle = device->handle;
+	acpi_driver_data(device) = hotkey;
+	strcpy(acpi_device_name(device), ACPI_HOTKEY_DEVICE_NAME);
+	strcpy(acpi_device_class(device), ACPI_HOTKEY_CLASS);
+
+	status = acpi_install_notify_handler (
+			hotkey->handle,
+			ACPI_DEVICE_NOTIFY,
+			acpi_hotkey_notify,
+			hotkey);
+	if (ACPI_FAILURE(status)) 
+		result = -ENODEV;
+
+	if (result)
+		kfree(hotkey);
+
+	return (result);
+}
+
+static int
+acpi_hotkey_remove(struct acpi_device *device, int type)
+{
+	acpi_status		status = 0;
+	struct acpi_hotkey	*hotkey = NULL;
+
+	if (!device || !acpi_driver_data(device))
+		return(-EINVAL);
+
+	hotkey = acpi_driver_data(device);
+	status = acpi_remove_notify_handler(hotkey->handle,
+		    ACPI_DEVICE_NOTIFY, acpi_hotkey_notify);
+	if (ACPI_FAILURE(status))
+		printk(KERN_INFO LOGPREFIX "Error removing notify handler\n");
+
+	kfree(hotkey);
+
+	return(0);
+}
+
+/*
+ * proc and module init
+*/
+
+ProcItem pcc_proc_items[] =
+{
+#ifdef DEBUG_PCC_VGA
+	{ "chgd"   , read_nothing , write_chgd},
+#endif
+	{ "hkey_status", read_hkey_status, NULL},
+	{ "version", read_version , NULL},
+	{ NULL 	   , NULL	  , NULL},
+};
+
+static acpi_status __init
+add_device(ProcItem *proc_items, struct proc_dir_entry* proc_entry)
+{
+	struct proc_dir_entry* proc;
+	ProcItem* item;
+
+	for (item = proc_items; item->name; ++item)
+	{
+		proc = create_proc_read_entry(item->name,
+			S_IFREG | S_IRUGO | S_IWUSR,
+			proc_entry, (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;
+	}
+
+	return(AE_OK);
+}
+
+
+static int __init
+pcc_proc_init(void)
+{
+	acpi_status status = AE_OK;
+
+	if (unlikely(!(acpi_pcc_dir = proc_mkdir(PROC_PCC, acpi_root_dir))))
+		return -ENODEV;
+
+	acpi_pcc_dir->owner = THIS_MODULE;
+	status = add_device(pcc_proc_items, acpi_pcc_dir);
+	if (ACPI_FAILURE(status)){
+		remove_proc_entry(PROC_PCC, acpi_root_dir);
+		return -ENODEV;
+	}
+
+	return (status == AE_OK);
+}
+
+static acpi_status __exit
+remove_device(ProcItem *proc_items, struct proc_dir_entry* proc_entry)
+{
+	ProcItem* item;
+
+	for (item = proc_items; item->name; ++item)
+		remove_proc_entry(item->name, proc_entry);
+	return(AE_OK);
+}
+
+
+
+/* init funcs. */
+static int __init
+acpi_pcc_init(void)
+{
+	acpi_status result = AE_OK;
+ 
+	if (acpi_disabled)
+		return -ENODEV;
+
+	/* simple device detection: look forI method */
+	if (!(is_valid_acpi_path(METHOD_CHGD)))
+		return -ENODEV;
+
+	result = acpi_bus_register_driver(&acpi_hotkey_driver);
+	if (ACPI_FAILURE(result))
+		printk(KERN_INFO LOGPREFIX "Error registering hotkey driver\n");
+
+	printk(KERN_INFO LOGPREFIX "ACPI PCC HotKey driver version %s\n", ACPI_PCC_VERSION);
+
+	return (pcc_proc_init());
+
+}
+
+static void __exit
+acpi_pcc_exit(void)
+{
+	if (acpi_pcc_dir) {
+		remove_device(pcc_proc_items, acpi_pcc_dir);
+		remove_proc_entry(PROC_PCC, acpi_root_dir);
+	}
+	acpi_bus_unregister_driver(&acpi_hotkey_driver); 
+	return;
+}
+
+module_init(acpi_pcc_init);
+module_exit(acpi_pcc_exit);
 

-- 
Hiroshi Miura  --- http://www.da-cha.org/  --- miura@da-cha.org
NTTDATA Corp. OpenSource Software Center. --- miurahr@nttdata.co.jp 
NTTDATA Intellilink Corp. OpenSource Engineering Dev. -- miurahr@intellilink.co.jp
Key fingerprint = 9117 9407 5684 FBF1 4063  15B4 401D D077 04AB 8617


-------------------------------------------------------
This SF.Net email is sponsored by OSTG. Have you noticed the changes on
Linux.com, ITManagersJournal and NewsForge in the past few weeks? Now,
one more big change to announce. We are now OSTG- Open Source Technology
Group. Come see the changes on the new OSTG site. www.ostg.com

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver
  2004-08-18  5:04 ` [PATCH][ACPI] Panasonic " Len Brown
@ 2004-08-18 14:52   ` John Belmonte
  0 siblings, 0 replies; 27+ messages in thread
From: John Belmonte @ 2004-08-18 14:52 UTC (permalink / raw)
  To: Len Brown
  Cc: Hiroshi Miura, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	ACPI Developers, letsnote-tech-eXqGM+LsbTTAqL8d+zIrHngSJqDPrsil

Len Brown wrote:
> Ah yes, another battle in the war on hot-keys;-)
> 
> On Sat, 2004-07-31 at 10:17, Hiroshi Miura wrote:
> 
>>+/*
>>+ *  Panasonic HotKey control Extra driver
>>+ *  (C) 2004 Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
>>+ *  (C) 2004 NTT DATA Intellilink Co. http://www.intellilink.co.jp/
>>+ *  All Rights Reserved
>>+ *
>>+ *  This program is free software; you can redistribute it and/or
>>modify
>>+ *  it under the terms of the GNU General Public License version 2 as
>>+ *  publicshed by the Free Software Foundation.
>>+ *
>>+ *  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.
>>+ * *  You should have received a copy of the GNU General Public
>>License
>>+ *  along with this program; if not, write to the Free Software
>>+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
>>02111-1307  USA
>>+ *
>>+ *  The devolpment page for this driver will be located at
>>+ *  http://www.da-cha.org/
>>+ *
>>+
>>*---------------------------------------------------------------------------
>>+ *
>>+ * ChangeLog:
>>+ *     Jul.25, 2004    Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
>>+ *             - v0.4  first post version
>>+ *             -       add debug function to retrive SIFR
>>+ *
>>+ *     Jul.24, 2004    Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
>>+ *             - v0.3  get proper status of hotkey
>>+ *
>>+ *      Jul.22, 2004   Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
>>+ *             - v0.2  add HotKey handler
>>+ *
>>+ *      Jul.17, 2004   Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
>>+ *             - v0.1  based on acpi video driver
>>+ *
> 
> 
> would be polite to credit the exact files that you leveraged.

I think it's a little beyond a politeness issue.  Large verbatim blocks 
of toshiba_acpi.c are used, with my copyright notice nowhere in sight.

-John


-- 
http://giftfile.org/  ::  giftfile project


-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver
@ 2004-08-19  6:00 David Bronaugh
       [not found] ` <41244219.1090603-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
  0 siblings, 1 reply; 27+ messages in thread
From: David Bronaugh @ 2004-08-19  6:00 UTC (permalink / raw)
  To: acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	miura-yiisDzvROlQdnm+yROfE0A

[-- Attachment #1: Type: text/plain, Size: 2095 bytes --]

Hi,

The following patch adds brightness setting support to the driver and 
cleans up the code a bit. It builds on the work of  Hiroshi Miura and 
takes into account the comments of Len Brown and John Belmonte. The 
patch is against 2.6.8.1-mm1 (though the only thing that might differ 
between -mm1 and vanilla is the Makefile).

I've tested this on my Panasonic CF-R1, and it works beautifully.

As far as I am concerned, besides code cleanups (and possibly figuring 
out the monitor switch thing) this driver is complete.

I hope I haven't stepped on any toes here.

David Bronaugh

---------

Supporting bits:

# /etc/acpi/events/hotkey
# This script handles hotkey events on Panasonic notebooks

event=HKEY.*
action=/etc/acpi/hotkey.sh %e

----------------------

#!/bin/bash
# Handles hotkey events for Panasonic notebooks
KEY=$4

BRIGHTNESS_CONTROL=/proc/acpi/pcc/brightness
VOLADJUST=5
GETVOLCMD="amixer cget numid=2"
GETMUTECMD="amixer cget numid=1"
SETVOLCMD="amixer cset numid=2"
SETMUTECMD="amixer cset numid=1"

case "$KEY" in
    00000001)
        logger "acpid: received a down brightness event"
        BRIGHT=`cat /proc/acpi/pcc/brightness`
        let BRIGHT=BRIGHT-1
        echo $BRIGHT > $BRIGHTNESS_CONTROL
        ;;
    00000002)
        logger "acpid: received an up brightness event"
        BRIGHT=`cat /proc/acpi/pcc/brightness`
        let BRIGHT=BRIGHT+1
        echo $BRIGHT > $BRIGHTNESS_CONTROL
        ;;
    00000003)
        logger "acpid: received a monitor switch event (unhandled)"
        ;;
    00000004)
        logger "acpid: received a sound mute event"
        ;;
    00000005)
        logger "acpid: received a volume down event"
        ;;
    00000006)
        logger "acpid: received a volume up event"
        ;;
    00000007)
        logger "acpid: received a suspend-to-RAM event (unhandled)"
        ;;
    00000009)
        logger "acpid: received a disk spindown event"
        ;;
    0000000a)
        logger "acpid: received a suspend-to-disk event"
        ;;
    *)
        logger "acpid: received unhandled event $KEY"
        ;;
esac

[-- Attachment #2: patch --]
[-- Type: text/plain, Size: 16355 bytes --]

diff -Nru lb-2.6.8.1/drivers/acpi/Kconfig linux-2.6.8.1/drivers/acpi/Kconfig
--- lb-2.6.8.1/drivers/acpi/Kconfig	2004-08-18 22:31:04.000000000 -0700
+++ linux-2.6.8.1/drivers/acpi/Kconfig	2004-08-18 22:40:19.000000000 -0700
@@ -204,6 +204,25 @@
 	  If you have a legacy free Toshiba laptop (such as the Libretto L1
 	  series), say Y.
 
+config ACPI_PCC
+	tristate "Panasonic Laptop Extras"
+	depends on X86
+	default m
+	---help---
+	  This driver adds support for hotkeys and screen brightness setting
+	  on Panasonic Let's Note laptops. 
+
+          For CRT/LCD switching, see the userspace utility i810switch.
+
+	  More information about this driver is available at
+	  <http://www.da-cha.org/letsnote/>
+
+	  Note: In order to effectively use this driver, you must set up your 
+	  acpid to handle 'hotkey' events. See the website for more details.
+
+	  If you have a panasonic lets note laptop (such as the CF-T2, Y2,
+	  R1, R2, W2, R3), say Y.
+
 config ACPI_DEBUG
 	bool "Debug Statements"
 	depends on ACPI_INTERPRETER
diff -Nru lb-2.6.8.1/drivers/acpi/Makefile linux-2.6.8.1/drivers/acpi/Makefile
--- lb-2.6.8.1/drivers/acpi/Makefile	2004-08-18 22:31:18.000000000 -0700
+++ linux-2.6.8.1/drivers/acpi/Makefile	2004-08-18 19:00:56.000000000 -0700
@@ -47,4 +47,5 @@
 obj-$(CONFIG_ACPI_NUMA)		+= numa.o
 obj-$(CONFIG_ACPI_ASUS)		+= asus_acpi.o
 obj-$(CONFIG_ACPI_TOSHIBA)	+= toshiba_acpi.o
+obj-$(CONFIG_ACPI_PCC)          += pcc_acpi.o
 obj-$(CONFIG_ACPI_BUS)		+= scan.o motherboard.o
diff -Nru lb-2.6.8.1/drivers/acpi/pcc_acpi.c linux-2.6.8.1/drivers/acpi/pcc_acpi.c
--- lb-2.6.8.1/drivers/acpi/pcc_acpi.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.8.1/drivers/acpi/pcc_acpi.c	2004-08-18 22:54:59.000000000 -0700
@@ -0,0 +1,566 @@
+/*
+ *  Panasonic HotKey control Extra driver
+ *  (C) 2004 Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
+ *  (C) 2004 NTT DATA Intellilink Co. http://www.intellilink.co.jp/
+ *  (C) 2004 David Bronaugh <dbronaugh-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
+ *  All Rights Reserved
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as 
+ *  publicshed by the Free Software Foundation.
+ *
+ *  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.
+ * *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  The devolpment page for this driver will be located at
+ *  http://www.da-cha.org/
+ *
+ *---------------------------------------------------------------------------
+ *
+ * ChangeLog:
+ *      Aug.17, 2004    David Bronaugh (dbronaugh-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org)
+ *              - v0.5  Added screen brightness setting interface
+ *              -       Thanks to the FreeBSD crew (acpi_panasonic.c authors)
+ *              -       for the ideas I needed to accomplish it
+ *
+ *	Jul.25, 2004	Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
+ *		- v0.4  first post version
+ *		-       add debug function to retrive SIFR
+ *
+ *	Jul.24, 2004	Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
+ *		- v0.3  get proper status of hotkey
+ *
+ *      Jul.22, 2004	Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
+ *		- v0.2  add HotKey handler
+ *
+ *      Jul.17, 2004	Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
+ *		- v0.1  Based on the toshiba_acpi.c video driver by 
+ *              -       John Belmonte -- see toshiba_acpi.c for more details
+ *
+ *  TODO
+ *	- Figure out the display switch key: is it a part of the ACPI standard?
+ */
+
+#define ACPI_PCC_VERSION	"0.5"
+#define PROC_INTERFACE_VERSION	2
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+
+MODULE_AUTHOR("Hiroshi Miura");
+MODULE_DESCRIPTION("ACPI HotKey driver for lets note");
+MODULE_LICENSE("GPL");
+
+#define LOGPREFIX "acpi_pcc: "
+
+/****************************************************
+ * Define ACPI PATHs 
+ ****************************************************/
+#define METHOD_CHGD            "\\_SB_.CHGD"
+
+/* Lets note hotkeys definitions */
+#define DEVICE_NAME_HKEY 	"\\_SB_.HKEY"
+#define METHOD_HKEY_QUERY	"HINF"
+
+/* ACPI BIOS inside use only? */
+#define METHOD_HKEY_RESET	"HRES"
+#define METHOD_HKEY_SAVE	"HSAV"
+#define METHOD_HKEY_HIND	"HIND"
+
+/* event read/write functions */
+#define METHOD_HKEY_SQTY	"SQTY"
+#define METHOD_HKEY_SINF	"SINF"
+#define METHOD_HKEY_SSET	"SSET"
+
+/* device(HKEY) definitions */
+#define HKEY_HID		"MAT0019"
+#define HKEY_NOTIFY		 0x80
+
+#define	LCD_MAX_BRIGHTNESS 255
+
+/* This may be magical -- beware */
+#define LCD_BRIGHTNESS_INCREMENT 17
+
+/* Registers of SINF */
+#define	SINF_LCD_BRIGHTNESS		4
+
+/*******************************************************************
+ *
+ * definitions for /proc/ interface
+ *
+ *******************************************************************/
+#define PROC_PCC		"pcc"
+
+#define ACPI_HOTKEY_DRIVER_NAME "PCC HotKey Driver"
+#define ACPI_HOTKEY_DEVICE_NAME "HotKey"
+#define ACPI_HOTKEY_CLASS "HKEY"
+
+static int acpi_hotkey_add(struct acpi_device *device);
+static int acpi_hotkey_remove(struct acpi_device *device, int type);
+
+static struct acpi_driver acpi_hotkey_driver = {
+	.name = ACPI_HOTKEY_DRIVER_NAME,
+	.class = ACPI_HOTKEY_CLASS,
+	.ids = HKEY_HID,
+	.ops = {
+		.add = acpi_hotkey_add,
+		.remove = acpi_hotkey_remove,
+		},
+};
+
+struct acpi_hotkey {
+	acpi_handle handle;
+	struct acpi_device *device;
+	unsigned long status;
+};
+
+/*
+ * utility functions
+ */
+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)
+{
+	acpi_handle handle;
+	acpi_status status;
+
+	status = acpi_get_handle(0, (char *)methodName, &handle);
+	return !ACPI_FAILURE(status);
+}
+
+static int read_acpi_int(acpi_handle handle, const char *methodName, int *pVal)
+{
+	struct acpi_buffer results;
+	union acpi_object out_objs[1];
+	acpi_status status;
+
+	results.length = sizeof(out_objs);
+	results.pointer = out_objs;
+
+	status = acpi_evaluate_object(handle, (char *)methodName, 0, &results);
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_INFO "acpi evaluate error on %s\n", methodName);
+		return (-EFAULT);
+	}
+
+	if (out_objs[0].type == ACPI_TYPE_INTEGER) {
+		*pVal = out_objs[0].integer.value;
+	} else {
+		printk(KERN_INFO "return value is not int\n");
+		status = AE_ERROR;
+	}
+
+	return (status == AE_OK);
+}
+
+static struct proc_dir_entry *acpi_pcc_dir;
+
+typedef struct _ProcItem {
+	const char *name;
+	char *(*read_func) (char *);
+	unsigned long (*write_func) (const char *, unsigned long);
+} ProcItem;
+
+/* register utils for proc handler */
+static int dispatch_read(char *page, char **start, off_t off, int count,
+			 int *eof, ProcItem * item)
+{
+	char *p = page;
+	int len;
+
+	if (off == 0) {
+		p = item->read_func(p);
+	}
+
+	/* ISSUE: I don't understand this code */
+	len = (p - page);
+	if (len <= off + count) {
+		*eof = 1;
+	}
+	*start = page + off;
+	len -= off;
+	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)
+{
+	int result;
+	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 (copy_from_user(tmp_buffer, buffer, count)) {
+		result = -EFAULT;
+	} else {
+		tmp_buffer[count] = 0;
+		result = item->write_func(tmp_buffer, count);
+	}
+	kfree(tmp_buffer);
+	return result;
+}
+
+/*
+ * proc file handlers
+ */
+#ifdef DEBUG_PCC_VGA
+static unsigned long write_chgd(const char *buffer, unsigned long count)
+{
+	int value;
+	acpi_status status;
+
+	if (sscanf(buffer, "%i", &value) == 1 && value >= 0 && value < 2) {
+		if (value == 0) {
+			/* do nothing */
+			status = AE_OK;
+		} else {
+			status = acpi_evaluate_object(0, METHOD_CHGD, 0, 0);
+		}
+		if (ACPI_FAILURE(status)) {
+			printk(KERN_INFO LOGPREFIX "fail evaluate CHGD()\n");
+			return -EFAULT;
+		}
+	}
+	return count;
+
+}
+
+static char *read_nothing(char *p)
+{
+	/* nothing to do */
+	return p;
+}
+#endif
+
+static char *read_hkey_status(char *p)
+{
+	acpi_status status;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object *hkey = NULL;
+	int i, num_sifr;
+
+	if (!read_acpi_int(NULL, DEVICE_NAME_HKEY "." METHOD_HKEY_SQTY,
+			   &num_sifr)) {
+		printk(KERN_INFO LOGPREFIX "evaluation error HKEY.SQTY\n");
+		return p;
+	}
+
+	status = acpi_evaluate_object(NULL,
+				      DEVICE_NAME_HKEY "." METHOD_HKEY_SINF,
+				      0, &buffer);
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_INFO LOGPREFIX "evaluation error HEKY.SINF\n");
+		return p;
+	}
+	hkey = (union acpi_object *)buffer.pointer;
+	if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) {
+		printk(KERN_INFO LOGPREFIX "Invalid HKEY.SINF\n");
+		goto end;
+	}
+
+	if (num_sifr != hkey->package.count) {
+		printk(KERN_INFO LOGPREFIX
+		       "SQTY is not equal to SINF length?\n");
+		goto end;
+	}
+
+	for (i = 0; i < hkey->package.count; i++) {
+		union acpi_object *element = &(hkey->package.elements[i]);
+		if (likely(element->type == ACPI_TYPE_INTEGER)) {
+			p += sprintf(p, "0x%02x,\n",
+				     (unsigned int)element->integer.value);
+		} else
+			printk(KERN_INFO LOGPREFIX "Invalid HKEY.SINF value\n");
+	}
+      end:
+	acpi_os_free(buffer.pointer);
+	return p;
+}
+
+static char *read_version(char *p)
+{
+	p += sprintf(p, "%s version %s\n", ACPI_HOTKEY_DRIVER_NAME,
+		     ACPI_PCC_VERSION);
+	p += sprintf(p, "proc_interface version %d\n", PROC_INTERFACE_VERSION);
+	return p;
+}
+
+static char *read_brightness(char *p)
+{
+	uint32_t brightness;
+	union acpi_object *resource;
+	struct acpi_buffer entries = { ACPI_ALLOCATE_BUFFER, NULL };
+	int status;
+
+	status = acpi_evaluate_object(NULL,
+				      DEVICE_NAME_HKEY "." METHOD_HKEY_SINF,
+				      NULL, &entries);
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_INFO "Could not get SINF\n");
+		return p;
+	}
+
+	resource = (union acpi_object *)entries.pointer;
+	if (!resource || resource->type != ACPI_TYPE_PACKAGE) {
+		printk(KERN_INFO "Could not read display brightness\n");
+		return p;
+	} else {
+		union acpi_object *element =
+		    &(resource->package.elements[SINF_LCD_BRIGHTNESS]);
+		brightness = element->integer.value;
+	}
+	acpi_os_free(entries.pointer);
+
+	p += sprintf(p, "%i\n", brightness / LCD_BRIGHTNESS_INCREMENT);
+	return p;
+}
+
+static unsigned long write_brightness(const char *p, unsigned long count)
+{
+	int brightness = simple_strtol(p, NULL, 10) * LCD_BRIGHTNESS_INCREMENT;
+	union acpi_object data[2];
+	struct acpi_object_list args;
+	uint32_t status;
+
+	/* Clean up incoming data */
+	if (brightness > LCD_MAX_BRIGHTNESS) {
+		brightness = LCD_MAX_BRIGHTNESS;
+	} else if (brightness < 0) {
+		brightness = 0;
+	}
+
+	data[0].type = ACPI_TYPE_INTEGER;
+	data[0].integer.value = SINF_LCD_BRIGHTNESS;
+	data[1].type = ACPI_TYPE_INTEGER;
+	data[1].integer.value = brightness;
+	args.pointer = data;
+	args.count = 2;
+
+	status = acpi_evaluate_object(NULL,
+				      DEVICE_NAME_HKEY "." METHOD_HKEY_SSET,
+				      &args, NULL);
+
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_INFO "Could not write display brightness");
+	}
+
+	return count;
+}
+
+/* hotkey driver */
+static int acpi_hotkey_get_key(struct acpi_hotkey *hotkey)
+{
+	int result;
+	int status;
+
+	status = read_acpi_int(hotkey->handle, METHOD_HKEY_QUERY, &result);
+	if (!status) {
+		printk(KERN_INFO LOGPREFIX "error getting hotkey status\n");
+	} else
+		hotkey->status = result;
+
+	return (status);
+}
+
+void acpi_hotkey_notify(acpi_handle handle, u32 event, void *data)
+{
+	struct acpi_hotkey *hotkey = (struct acpi_hotkey *)data;
+
+	if (!hotkey || !hotkey->device)
+		return;
+
+	switch (event) {
+	case HKEY_NOTIFY:
+		if (acpi_hotkey_get_key(hotkey))
+			acpi_bus_generate_event(hotkey->device, event,
+						hotkey->status);
+		break;
+	default:
+		/* nothing to do */
+		break;
+	}
+
+	return;
+}
+
+static int acpi_hotkey_add(struct acpi_device *device)
+{
+	int result = 0;
+	acpi_status status = AE_OK;
+	struct acpi_hotkey *hotkey = NULL;
+
+	if (!device)
+		return (-EINVAL);
+
+	hotkey = kmalloc(sizeof(struct acpi_hotkey), GFP_KERNEL);
+	if (!hotkey)
+		return (-ENOMEM);
+
+	memset(hotkey, 0, sizeof(struct acpi_hotkey));
+
+	hotkey->device = device;
+	hotkey->handle = device->handle;
+	acpi_driver_data(device) = hotkey;
+	strcpy(acpi_device_name(device), ACPI_HOTKEY_DEVICE_NAME);
+	strcpy(acpi_device_class(device), ACPI_HOTKEY_CLASS);
+
+	status = acpi_install_notify_handler(hotkey->handle,
+					     ACPI_DEVICE_NOTIFY,
+					     acpi_hotkey_notify, hotkey);
+	if (ACPI_FAILURE(status))
+		result = -ENODEV;
+
+	if (result)
+		kfree(hotkey);
+
+	return (result);
+}
+
+static int acpi_hotkey_remove(struct acpi_device *device, int type)
+{
+	acpi_status status = 0;
+	struct acpi_hotkey *hotkey = NULL;
+
+	if (!device || !acpi_driver_data(device))
+		return (-EINVAL);
+
+	hotkey = acpi_driver_data(device);
+	status = acpi_remove_notify_handler(hotkey->handle,
+					    ACPI_DEVICE_NOTIFY,
+					    acpi_hotkey_notify);
+	if (ACPI_FAILURE(status))
+		printk(KERN_INFO LOGPREFIX "Error removing notify handler\n");
+
+	kfree(hotkey);
+
+	return (0);
+}
+
+/*
+ * proc and module init
+*/
+
+ProcItem pcc_proc_items[] = {
+#ifdef DEBUG_PCC_VGA
+	{"chgd", read_nothing, write_chgd}
+	,
+#endif
+	{"brightness", read_brightness, write_brightness}
+	,
+	{"hkey_status", read_hkey_status, NULL}
+	,
+	{"version", read_version, NULL}
+	,
+	{NULL, NULL, NULL}
+	,
+};
+
+static acpi_status __init
+add_device(ProcItem * proc_items, struct proc_dir_entry *proc_entry)
+{
+	struct proc_dir_entry *proc;
+	ProcItem *item;
+
+	for (item = proc_items; item->name; ++item) {
+		proc = create_proc_read_entry(item->name,
+					      S_IFREG | S_IRUGO | S_IWUSR,
+					      proc_entry,
+					      (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;
+	}
+
+	return (AE_OK);
+}
+
+static int __init pcc_proc_init(void)
+{
+	acpi_status status = AE_OK;
+
+	if (unlikely(!(acpi_pcc_dir = proc_mkdir(PROC_PCC, acpi_root_dir))))
+		return -ENODEV;
+
+	acpi_pcc_dir->owner = THIS_MODULE;
+	status = add_device(pcc_proc_items, acpi_pcc_dir);
+	if (ACPI_FAILURE(status)) {
+		remove_proc_entry(PROC_PCC, acpi_root_dir);
+		return -ENODEV;
+	}
+
+	return (status == AE_OK);
+}
+
+static acpi_status __exit
+remove_device(ProcItem * proc_items, struct proc_dir_entry *proc_entry)
+{
+	ProcItem *item;
+
+	for (item = proc_items; item->name; ++item)
+		remove_proc_entry(item->name, proc_entry);
+	return (AE_OK);
+}
+
+/* init funcs. */
+static int __init acpi_pcc_init(void)
+{
+	acpi_status result = AE_OK;
+
+	if (acpi_disabled)
+		return -ENODEV;
+
+	/* simple device detection: look forI method */
+	if (!(is_valid_acpi_path(METHOD_CHGD)))
+		return -ENODEV;
+
+	result = acpi_bus_register_driver(&acpi_hotkey_driver);
+	if (ACPI_FAILURE(result))
+		printk(KERN_INFO LOGPREFIX "Error registering hotkey driver\n");
+
+	printk(KERN_INFO LOGPREFIX "ACPI PCC HotKey driver version %s\n",
+	       ACPI_PCC_VERSION);
+
+	return (pcc_proc_init());
+
+}
+
+static void __exit acpi_pcc_exit(void)
+{
+	if (acpi_pcc_dir) {
+		remove_device(pcc_proc_items, acpi_pcc_dir);
+		remove_proc_entry(PROC_PCC, acpi_root_dir);
+	}
+	acpi_bus_unregister_driver(&acpi_hotkey_driver);
+	return;
+}
+
+module_init(acpi_pcc_init);
+module_exit(acpi_pcc_exit);

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver
       [not found] ` <41244219.1090603-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
@ 2004-08-20  2:51   ` Hiroshi Miura
       [not found]     ` <871xi2s555.wl%miura@da-cha.org>
       [not found]     ` <87acwqserw.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
  2004-08-21  1:42   ` [PATCH]Panasonic Hotkey Driver Hiroshi Miura
  1 sibling, 2 replies; 27+ messages in thread
From: Hiroshi Miura @ 2004-08-20  2:51 UTC (permalink / raw)
  To: David Bronaugh
  Cc: acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	letsnote-tech-eXqGM+LsbTTAqL8d+zIrHngSJqDPrsil

Hi,

I'm also developing lcd brightness driver and clean ups.
An infomation of BIOS data is gotten from hardware vendor.

These are a little diffence in David's code about bios spec.

I want to post my driver soon.

Hiroshi Miura  --- http://www.da-cha.org/  --- miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org
NTTDATA Corp. OpenSource Software Center. --- miurahr-3MafRgGXt7BL9jVzuh4AOg@public.gmane.org 
NTTDATA Intellilink Corp. OpenSource Engineering Dev. -- miurahr-w0OK63jvRlAuJ+9fw/WgBHgSJqDPrsil@public.gmane.org
Key fingerprint = 9117 9407 5684 FBF1 4063  15B4 401D D077 04AB 8617

-----
At Wed, 18 Aug 2004 23:00:57 -0700,
David Bronaugh wrote:

Hi,

The following patch adds brightness setting support to the driver and 
cleans up the code a bit. It builds on the work of  Hiroshi Miura and 
takes into account the comments of Len Brown and John Belmonte. The 
patch is against 2.6.8.1-mm1 (though the only thing that might differ 
between -mm1 and vanilla is the Makefile).

I've tested this on my Panasonic CF-R1, and it works beautifully.

As far as I am concerned, besides code cleanups (and possibly figuring 
out the monitor switch thing) this driver is complete.

I hope I haven't stepped on any toes here.

David Bronaugh


-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH]Panasonic Hotkey Driver v0.5 [1/2]
       [not found]       ` <871xi2s555.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
@ 2004-08-20  6:25         ` Hiroshi Miura
       [not found]           ` <87vffeqqaq.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
  0 siblings, 1 reply; 27+ messages in thread
From: Hiroshi Miura @ 2004-08-20  6:25 UTC (permalink / raw)
  To: Len Brown
  Cc: David Bronaugh, acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	letsnote-tech-eXqGM+LsbTTAqL8d+zIrHngSJqDPrsil

This is a patch of pcc_acpi v0.4.
It is same as my previous patch, 
but it is made using 'bkexport' script.

Please use this v0.4[1/2] and v0.5 incremental [2/2].

At Fri, 20 Aug 2004 15:19:34 +0900,
Hiroshi Miura wrote:
> 
> Hi,
> 
> This is incremental bkpatch against pcc_acpi driver v0.4.
> It is made using bkexport.
> 
> At Fri, 20 Aug 2004 11:51:31 +0900,
> Hiroshi Miura wrote:
> > 
> > Hi,
> > 
> > I'm also developing lcd brightness driver and clean ups.
> > An infomation of BIOS data is gotten from hardware vendor.
> > 
> > These are a little diffence in David's code about bios spec.
> > 
> > I want to post my driver soon.
> 
> Hiroshi Miura  --- http://www.da-cha.org/  --- miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org
> NTTDATA Corp. OpenSource Software Center. --- miurahr-3MafRgGXt7BL9jVzuh4AOg@public.gmane.org 
> NTTDATA Intellilink Corp. OpenSource Engineering Dev. -- miurahr-w0OK63jvRlAuJ+9fw/WgBHgSJqDPrsil@public.gmane.org
> Key fingerprint = 9117 9407 5684 FBF1 4063  15B4 401D D077 04AB 8617

#### AUTHOR miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org
#### COMMENT START
### Comments for ChangeSet
Panasonic Laptop Extra driver.
This adds support of hotkey (Fn+Fx) on Panasonic Lets note Laptop series.
Loding this driver, user can get event through acpid like "HKEY HKEY 0000080 000001"

Signed-off-by: Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
### Comments for drivers/acpi/pcc_acpi.c
### Comments for drivers/acpi/pcc_acpi.c
BitKeeper file /home/miura/kernel/linux-2.6.7-hm/drivers/acpi/pcc_acpi.c
### Comments for drivers/acpi/Makefile
add Panasonic Laptop Extra driver entry
### Comments for drivers/acpi/Kconfig
add Panasonic Laptop Extra driver entry
#### COMMENT END

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/07/26 11:50:39+09:00 miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org 
#   Panasonic Laptop Extra driver.
#   This adds support of hotkey (Fn+Fx) on Panasonic Lets note Laptop series.
#   Loding this driver, user can get event through acpid like "HKEY HKEY 0000080 000001"
#   
#   Signed-off-by: Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
# 
# drivers/acpi/pcc_acpi.c
#   2004/07/26 11:50:23+09:00 miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org +518 -0
# 
# drivers/acpi/pcc_acpi.c
#   2004/07/26 11:50:23+09:00 miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org +0 -0
#   BitKeeper file /home/miura/kernel/linux-2.6.7-hm/drivers/acpi/pcc_acpi.c
# 
# drivers/acpi/Makefile
#   2004/07/26 11:50:23+09:00 miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org +1 -0
#   add Panasonic Laptop Extra driver entry
# 
# drivers/acpi/Kconfig
#   2004/07/26 11:50:23+09:00 miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org +20 -0
#   add Panasonic Laptop Extra driver entry
# 
diff -Nru a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
--- a/drivers/acpi/Kconfig	2004-08-20 14:56:39 +09:00
+++ b/drivers/acpi/Kconfig	2004-08-20 14:56:39 +09:00
@@ -204,6 +204,26 @@
 	  If you have a legacy free Toshiba laptop (such as the Libretto L1
 	  series), say Y.
 
+config ACPI_PCC
+	tristate "Panasonic Laptop Extras"
+	depends on X86
+	depends on ACPI_INTERPRETER
+	default m
+	---help---
+	  This driver adds support for access to certain system settings
+	  on panasonic Let's Note laptops. 
+
+	  On these machines, all hotkey is handled through the ACPI.
+	  This driver is required for access to controls not covered
+	  by the general ACPI drivers, such as LCD brightness, video output,
+	  etc.
+
+	  More information about this driver is available at
+	  <http://www.da-cha.org/letsnote/>
+
+	  If you have a panasonic lets note laptop (such as the CF-T1, R1, T2,
+	  R2, W2, R3), say Y.
+
 config ACPI_DEBUG
 	bool "Debug Statements"
 	depends on ACPI_INTERPRETER
diff -Nru a/drivers/acpi/Makefile b/drivers/acpi/Makefile
--- a/drivers/acpi/Makefile	2004-08-20 14:56:39 +09:00
+++ b/drivers/acpi/Makefile	2004-08-20 14:56:39 +09:00
@@ -47,4 +47,5 @@
 obj-$(CONFIG_ACPI_NUMA)		+= numa.o
 obj-$(CONFIG_ACPI_ASUS)		+= asus_acpi.o
 obj-$(CONFIG_ACPI_TOSHIBA)	+= toshiba_acpi.o
+obj-$(CONFIG_ACPI_PCC)		+= pcc_acpi.o
 obj-$(CONFIG_ACPI_BUS)		+= scan.o 
diff -Nru a/drivers/acpi/pcc_acpi.c b/drivers/acpi/pcc_acpi.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/acpi/pcc_acpi.c	2004-08-20 14:56:39 +09:00
@@ -0,0 +1,518 @@
+/*
+ *  Panasonic HotKey control Extra driver
+ *  (C) 2004 Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
+ *  (C) 2004 NTT DATA Intellilink Co. http://www.intellilink.co.jp/
+ *  All Rights Reserved
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as 
+ *  publicshed by the Free Software Foundation.
+ *
+ *  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.
+ * *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  The devolpment page for this driver will be located at
+ *  http://www.da-cha.org/
+ *
+ *---------------------------------------------------------------------------
+ *
+ * ChangeLog:
+ *	Jul.25, 2004	Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
+ *		- v0.4  first post version
+ *		-       add debug function to retrive SIFR
+ *
+ *	Jul.24, 2004	Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
+ *		- v0.3  get proper status of hotkey
+ *
+ *      Jul.22, 2004	Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
+ *		- v0.2  add HotKey handler
+ *
+ *      Jul.17, 2004	Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
+ *		- v0.1  based on acpi video driver
+ *
+ *  TODO
+ *	everything all
+ *
+ */
+
+#define ACPI_PCC_VERSION	"0.4"
+#define PROC_INTERFACE_VERSION	2
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+
+MODULE_AUTHOR("Hiroshi Miura");
+MODULE_DESCRIPTION("ACPI HotKey driver for lets note");
+MODULE_LICENSE("GPL");
+
+#define LOGPREFIX "acpi_pcc: "
+
+/****************************************************
+ * Define ACPI PATHs 
+ ****************************************************/
+/* crt/lcd hot key definitions */
+#define DEVICE_NAME_VGA		"\\_SB_.PCI0.GRFX"
+#define DEVICE_NAME_CRT		"CRT1"
+#define DEVICE_NAME_LCD		"LCD1"
+#define METHOD_CHGD		"\\_SB_.CHGD"
+
+/* Lets note hotkeys definitions */
+#define DEVICE_NAME_HKEY 	"\\_SB_.HKEY"
+#define METHOD_HKEY_QUERY	"HINF"
+
+/* ACPI BIOS inside use only? */
+#define METHOD_HKEY_RESET	"HRES"
+#define METHOD_HKEY_SAVE	"HSAV"
+#define METHOD_HKEY_HIND	"HIND"
+
+/* event read/write functions */
+#define METHOD_HKEY_SQTY	"SQTY"
+#define METHOD_HKEY_SINF	"SINF"
+#define METHOD_HKEY_SSET	"SSET"
+
+
+/* device(HKEY) definitions */
+#define HKEY_HID		"MAT0019"
+#define HKEY_NOTIFY		 0x80
+
+/*******************************************************************
+ *
+ * definitions for /proc/ interface
+ *
+ *******************************************************************/
+#define PROC_PCC		"pcc"
+
+#define ACPI_HOTKEY_DRIVER_NAME "PCC HotKey Driver"
+#define ACPI_HOTKEY_DEVICE_NAME "HotKey"
+#define ACPI_HOTKEY_CLASS "HKEY"
+
+static int acpi_hotkey_add (struct acpi_device *device);
+static int acpi_hotkey_remove (struct acpi_device *device, int type);
+
+static struct acpi_driver acpi_hotkey_driver = {
+	.name =		ACPI_HOTKEY_DRIVER_NAME,
+	.class =	ACPI_HOTKEY_CLASS,
+	.ids =		HKEY_HID,
+	.ops =		{
+				.add =		acpi_hotkey_add,
+				.remove =	acpi_hotkey_remove,
+			},
+};
+
+struct acpi_hotkey {
+	acpi_handle		handle;
+	struct acpi_device	*device;
+	unsigned long		status;
+};
+
+
+/*
+ * utility functions
+ */
+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)
+{
+	acpi_handle handle;
+	acpi_status status;
+
+	status = acpi_get_handle(0, (char*)methodName, &handle);
+	return !ACPI_FAILURE(status);
+}
+
+#if 0
+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.pointer = in_objs;
+	in_objs[0].type = ACPI_TYPE_INTEGER;
+	in_objs[0].integer.value = val;
+
+	status = acpi_evaluate_object(0, (char*)methodName, &params, 0);
+	return (status == AE_OK);
+}
+#endif
+
+static int
+read_acpi_int(acpi_handle handle, const char* methodName, int* pVal)
+{
+	struct acpi_buffer results;
+	union acpi_object out_objs[1];
+	acpi_status status;
+
+	results.length = sizeof(out_objs);
+	results.pointer = out_objs;
+
+	status = acpi_evaluate_object(handle, (char*)methodName, 0, &results);
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_INFO "acpi evaluate error on %s\n", methodName);
+		return (-EFAULT);
+	}
+
+	if (out_objs[0].type == ACPI_TYPE_INTEGER) {
+		*pVal = out_objs[0].integer.value;
+	} else {
+		printk(KERN_INFO "return value is not int\n");
+		status = AE_ERROR;
+	}
+
+	return (status == AE_OK);
+}
+
+static struct proc_dir_entry*	acpi_pcc_dir;
+
+typedef struct _ProcItem
+{
+	const char* name;
+	char* (*read_func)(char*);
+	unsigned long (*write_func)(const char*, unsigned long);
+} ProcItem;
+
+
+/* register utils for proc handler */
+static int
+dispatch_read(char* page, char** start, off_t off, int count, int* eof,
+	ProcItem* item)
+{
+	char* p = page;
+	int len;
+
+	if (off == 0)
+		p = item->read_func(p);
+
+	/* ISSUE: I don't understand this code */
+	len = (p - page);
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	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)
+{
+	int result;
+	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 (copy_from_user(tmp_buffer, buffer, count)) {
+		result = -EFAULT;
+	}
+	else {
+		tmp_buffer[count] = 0;
+		result = item->write_func(tmp_buffer, count);
+	}
+	kfree(tmp_buffer);
+	return result;
+}
+
+/*
+ * proc file handlers
+ */
+#ifdef DEBUG_PCC_VGA
+static unsigned long
+write_chgd(const char* buffer, unsigned long count)
+{
+	int value;
+	acpi_status status;
+
+	if (sscanf(buffer, "%i", &value) == 1 && value >= 0 && value < 2) {
+		if (value == 0) 
+			/* do nothing */
+			status = AE_OK;
+		else {
+			status = acpi_evaluate_object(0, METHOD_CHGD, 0 , 0);
+		}
+		if (ACPI_FAILURE(status)) {
+			printk(KERN_INFO LOGPREFIX "fail evaluate CHGD()\n");
+			return -EFAULT;
+		}
+	}
+	return count;
+
+}
+
+static char*
+read_nothing(char* p)
+{
+	/* nothing to do*/
+	return p;
+}
+#endif
+
+static char*
+read_hkey_status(char* p)
+{
+	acpi_status status;
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	union acpi_object *hkey = NULL;
+	int i, num_sifr;
+
+	if (!read_acpi_int(NULL, DEVICE_NAME_HKEY "." METHOD_HKEY_SQTY, &num_sifr)){
+		printk(KERN_INFO LOGPREFIX "evaluation error HKEY.SQTY\n");
+		return p;
+	}
+
+	status = acpi_evaluate_object(NULL, DEVICE_NAME_HKEY "." METHOD_HKEY_SINF, 0 , &buffer);
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_INFO LOGPREFIX "evaluation error HEKY.SINF\n");
+		return p;
+	}
+	hkey = (union acpi_object *) buffer.pointer;
+	if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) {
+		printk(KERN_INFO LOGPREFIX "Invalid HKEY.SINF\n");
+		goto end;
+	}
+	
+	if (num_sifr != hkey->package.count) {
+		printk(KERN_INFO LOGPREFIX "SQTY is not equal to SINF length?\n");
+		goto end;
+	}
+
+	for (i = 0; i < hkey->package.count; i++) {
+		union acpi_object *element = &(hkey->package.elements[i]);
+		if (likely(element->type == ACPI_TYPE_INTEGER)) {
+			p += sprintf(p, "0x%02x,\n", (unsigned int)element->integer.value);
+		} else
+			printk(KERN_INFO LOGPREFIX "Invalid HKEY.SINF value\n");
+	}
+end:
+	acpi_os_free(buffer.pointer);
+	return p;
+}
+
+
+static char*
+read_version(char* p)
+{
+	p += sprintf(p, "%s version %s\n", ACPI_HOTKEY_DRIVER_NAME, ACPI_PCC_VERSION);
+	p += sprintf(p, "proc_interface version %d\n", PROC_INTERFACE_VERSION);
+	return p;
+}
+
+
+/* hotkey driver */
+static int
+acpi_hotkey_get_key(struct acpi_hotkey *hotkey)
+{
+	int result;
+	int status;
+
+	status = read_acpi_int(hotkey->handle, METHOD_HKEY_QUERY, &result);
+	if (!status) {
+		printk(KERN_INFO LOGPREFIX "error getting hotkey status\n");
+	} else
+		hotkey->status = result;
+
+	return (status);
+}
+
+void
+acpi_hotkey_notify(acpi_handle handle, u32 event, void *data)
+{
+	struct acpi_hotkey	*hotkey = (struct acpi_hotkey *) data;
+
+	if (!hotkey || !hotkey->device)
+		return;
+
+	switch(event) {
+	case HKEY_NOTIFY:
+		if (acpi_hotkey_get_key(hotkey))
+			acpi_bus_generate_event(hotkey->device, event, hotkey->status);
+		break;
+	default:
+		/* nothing to do */
+		break;
+	}
+
+	return;
+}
+
+static int
+acpi_hotkey_add (struct acpi_device *device)
+{
+	int			result = 0;
+	acpi_status		status = AE_OK;
+	struct acpi_hotkey	*hotkey = NULL;
+
+	if (!device)
+		return (-EINVAL);
+
+	hotkey = kmalloc(sizeof(struct acpi_hotkey), GFP_KERNEL);
+	if (!hotkey)
+		return (-ENOMEM);
+
+	memset(hotkey, 0, sizeof(struct acpi_hotkey));
+
+	hotkey->device = device;
+	hotkey->handle = device->handle;
+	acpi_driver_data(device) = hotkey;
+	strcpy(acpi_device_name(device), ACPI_HOTKEY_DEVICE_NAME);
+	strcpy(acpi_device_class(device), ACPI_HOTKEY_CLASS);
+
+	status = acpi_install_notify_handler (
+			hotkey->handle,
+			ACPI_DEVICE_NOTIFY,
+			acpi_hotkey_notify,
+			hotkey);
+	if (ACPI_FAILURE(status)) 
+		result = -ENODEV;
+
+	if (result)
+		kfree(hotkey);
+
+	return (result);
+}
+
+static int
+acpi_hotkey_remove(struct acpi_device *device, int type)
+{
+	acpi_status		status = 0;
+	struct acpi_hotkey	*hotkey = NULL;
+
+	if (!device || !acpi_driver_data(device))
+		return(-EINVAL);
+
+	hotkey = acpi_driver_data(device);
+	status = acpi_remove_notify_handler(hotkey->handle,
+		    ACPI_DEVICE_NOTIFY, acpi_hotkey_notify);
+	if (ACPI_FAILURE(status))
+		printk(KERN_INFO LOGPREFIX "Error removing notify handler\n");
+
+	kfree(hotkey);
+
+	return(0);
+}
+
+/*
+ * proc and module init
+*/
+
+ProcItem pcc_proc_items[] =
+{
+#ifdef DEBUG_PCC_VGA
+	{ "chgd"   , read_nothing , write_chgd},
+#endif
+	{ "hkey_status", read_hkey_status, NULL},
+	{ "version", read_version , NULL},
+	{ NULL 	   , NULL	  , NULL},
+};
+
+static acpi_status __init
+add_device(ProcItem *proc_items, struct proc_dir_entry* proc_entry)
+{
+	struct proc_dir_entry* proc;
+	ProcItem* item;
+
+	for (item = proc_items; item->name; ++item)
+	{
+		proc = create_proc_read_entry(item->name,
+			S_IFREG | S_IRUGO | S_IWUSR,
+			proc_entry, (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;
+	}
+
+	return(AE_OK);
+}
+
+
+static int __init
+pcc_proc_init(void)
+{
+	acpi_status status = AE_OK;
+
+	if (unlikely(!(acpi_pcc_dir = proc_mkdir(PROC_PCC, acpi_root_dir))))
+		return -ENODEV;
+
+	acpi_pcc_dir->owner = THIS_MODULE;
+	status = add_device(pcc_proc_items, acpi_pcc_dir);
+	if (ACPI_FAILURE(status)){
+		remove_proc_entry(PROC_PCC, acpi_root_dir);
+		return -ENODEV;
+	}
+
+	return (status == AE_OK);
+}
+
+static acpi_status __exit
+remove_device(ProcItem *proc_items, struct proc_dir_entry* proc_entry)
+{
+	ProcItem* item;
+
+	for (item = proc_items; item->name; ++item)
+		remove_proc_entry(item->name, proc_entry);
+	return(AE_OK);
+}
+
+
+
+/* init funcs. */
+static int __init
+acpi_pcc_init(void)
+{
+	acpi_status result = AE_OK;
+ 
+	if (acpi_disabled)
+		return -ENODEV;
+
+	/* simple device detection: look forI method */
+	if (!(is_valid_acpi_path(METHOD_CHGD)))
+		return -ENODEV;
+
+	result = acpi_bus_register_driver(&acpi_hotkey_driver);
+	if (ACPI_FAILURE(result))
+		printk(KERN_INFO LOGPREFIX "Error registering hotkey driver\n");
+
+	printk(KERN_INFO LOGPREFIX "ACPI PCC HotKey driver version %s\n", ACPI_PCC_VERSION);
+
+	return (pcc_proc_init());
+
+}
+
+static void __exit
+acpi_pcc_exit(void)
+{
+	if (acpi_pcc_dir) {
+		remove_device(pcc_proc_items, acpi_pcc_dir);
+		remove_proc_entry(PROC_PCC, acpi_root_dir);
+	}
+	acpi_bus_unregister_driver(&acpi_hotkey_driver); 
+	return;
+}
+
+module_init(acpi_pcc_init);
+module_exit(acpi_pcc_exit);


-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH]Panasonic Hotkey Driver v0.5 [2/2]
       [not found]     ` <87acwqserw.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
@ 2004-08-20  6:25       ` Hiroshi Miura
       [not found]         ` <87u0uyqqa7.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
  0 siblings, 1 reply; 27+ messages in thread
From: Hiroshi Miura @ 2004-08-20  6:25 UTC (permalink / raw)
  To: Len Brown
  Cc: David Bronaugh, acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	letsnote-tech-eXqGM+LsbTTAqL8d+zIrHngSJqDPrsil

Hi,

This is incremental bkpatch against pcc_acpi driver v0.4.
It is made using bkexport.

At Fri, 20 Aug 2004 11:51:31 +0900,
Hiroshi Miura wrote:
> 
> Hi,
> 
> I'm also developing lcd brightness driver and clean ups.
> An infomation of BIOS data is gotten from hardware vendor.
> 
> These are a little diffence in David's code about bios spec.
> 
> I want to post my driver soon.

Hiroshi Miura  --- http://www.da-cha.org/  --- miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org
NTTDATA Corp. OpenSource Software Center. --- miurahr-3MafRgGXt7BL9jVzuh4AOg@public.gmane.org 
NTTDATA Intellilink Corp. OpenSource Engineering Dev. -- miurahr-w0OK63jvRlAuJ+9fw/WgBHgSJqDPrsil@public.gmane.org
Key fingerprint = 9117 9407 5684 FBF1 4063  15B4 401D D077 04AB 8617


#### AUTHOR miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org
#### COMMENT START
### Comments for ChangeSet
implement LCD brightness control based on infomation from Panasonic Let's Note team.
implement Mute function.
several clean up.
fix credit.
### Comments for drivers/acpi/pcc_acpi.c
implement LCD brightness control based on infomation from Panasonic Let's Note team.
implement Mute function.
several clean up.
fix credit.
#### COMMENT END

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/08/20 12:00:20+09:00 miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org 
#   implement LCD brightness control based on infomation from Panasonic Let's Note team.
#   implement Mute function.
#   several clean up.
#   fix credit.
# 
# drivers/acpi/pcc_acpi.c
#   2004/08/20 11:59:55+09:00 miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org +221 -196
#   implement LCD brightness control based on infomation from Panasonic Let's Note team.
#   implement Mute function.
#   several clean up.
#   fix credit.
# 
diff -Nru a/drivers/acpi/pcc_acpi.c b/drivers/acpi/pcc_acpi.c
--- a/drivers/acpi/pcc_acpi.c	2004-08-20 14:57:44 +09:00
+++ b/drivers/acpi/pcc_acpi.c	2004-08-20 14:57:44 +09:00
@@ -1,8 +1,8 @@
 /*
- *  Panasonic HotKey control Extra driver
- *  (C) 2004 Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
- *  (C) 2004 NTT DATA Intellilink Co. http://www.intellilink.co.jp/
- *  All Rights Reserved
+ *  Panasonic HotKey and lcd brightness control Extra driver
+ *  Written by Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>  2004
+ *
+ *  Copyright (C) 2002-2004 John Belmonte
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as 
@@ -12,19 +12,21 @@
  *  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.
- * *  You should have received a copy of the GNU General Public License
+ *
+ *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- *  The devolpment page for this driver will be located at
- *  http://www.da-cha.org/
- *
  *---------------------------------------------------------------------------
  *
  * ChangeLog:
+ *	Aug.10, 2004	Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
+ *		- v0.5  support LCD brightness control
+ *			based on the disclosed information by MEI.
+ *
  *	Jul.25, 2004	Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
  *		- v0.4  first post version
- *		-       add debug function to retrive SIFR
+ *		        add function to retrive SIFR
  *
  *	Jul.24, 2004	Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
  *		- v0.3  get proper status of hotkey
@@ -33,15 +35,11 @@
  *		- v0.2  add HotKey handler
  *
  *      Jul.17, 2004	Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
- *		- v0.1  based on acpi video driver
- *
- *  TODO
- *	everything all
+ *		- v0.1  start from toshiba_acpi driver written by John Belmonte
  *
  */
 
-#define ACPI_PCC_VERSION	"0.4"
-#define PROC_INTERFACE_VERSION	2
+#define ACPI_PCC_VERSION	"0.5"
 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -53,6 +51,10 @@
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
+#define ACPI_HOTKEY_COMPONENT		0x10000000
+#define _COMPONENT		ACPI_HOTKEY_COMPONENT
+ACPI_MODULE_NAME		("pcc_acpi")
+
 MODULE_AUTHOR("Hiroshi Miura");
 MODULE_DESCRIPTION("ACPI HotKey driver for lets note");
 MODULE_LICENSE("GPL");
@@ -62,28 +64,12 @@
 /****************************************************
  * Define ACPI PATHs 
  ****************************************************/
-/* crt/lcd hot key definitions */
-#define DEVICE_NAME_VGA		"\\_SB_.PCI0.GRFX"
-#define DEVICE_NAME_CRT		"CRT1"
-#define DEVICE_NAME_LCD		"LCD1"
-#define METHOD_CHGD		"\\_SB_.CHGD"
-
-/* Lets note hotkeys definitions */
+/* Lets note hotkeys */
 #define DEVICE_NAME_HKEY 	"\\_SB_.HKEY"
 #define METHOD_HKEY_QUERY	"HINF"
-
-/* ACPI BIOS inside use only? */
-#define METHOD_HKEY_RESET	"HRES"
-#define METHOD_HKEY_SAVE	"HSAV"
-#define METHOD_HKEY_HIND	"HIND"
-
-/* event read/write functions */
 #define METHOD_HKEY_SQTY	"SQTY"
 #define METHOD_HKEY_SINF	"SINF"
 #define METHOD_HKEY_SSET	"SSET"
-
-
-/* device(HKEY) definitions */
 #define HKEY_HID		"MAT0019"
 #define HKEY_NOTIFY		 0x80
 
@@ -93,21 +79,22 @@
  *
  *******************************************************************/
 #define PROC_PCC		"pcc"
+#define PROC_VIDEO "video"
 
 #define ACPI_HOTKEY_DRIVER_NAME "PCC HotKey Driver"
 #define ACPI_HOTKEY_DEVICE_NAME "HotKey"
 #define ACPI_HOTKEY_CLASS "HKEY"
 
-static int acpi_hotkey_add (struct acpi_device *device);
-static int acpi_hotkey_remove (struct acpi_device *device, int type);
+static int acpi_pcc_hotkey_add (struct acpi_device *device);
+static int acpi_pcc_hotkey_remove (struct acpi_device *device, int type);
 
 static struct acpi_driver acpi_hotkey_driver = {
 	.name =		ACPI_HOTKEY_DRIVER_NAME,
 	.class =	ACPI_HOTKEY_CLASS,
 	.ids =		HKEY_HID,
 	.ops =		{
-				.add =		acpi_hotkey_add,
-				.remove =	acpi_hotkey_remove,
+				.add =		acpi_pcc_hotkey_add,
+				.remove =	acpi_pcc_hotkey_remove,
 			},
 };
 
@@ -117,45 +104,25 @@
 	unsigned long		status;
 };
 
-
-/*
- * utility functions
- */
-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)
-{
-	acpi_handle handle;
-	acpi_status status;
-
-	status = acpi_get_handle(0, (char*)methodName, &handle);
-	return !ACPI_FAILURE(status);
-}
-
-#if 0
 static int
-write_acpi_int(const char* methodName, int val)
+write_sset(int func, int val)
 {
 	struct acpi_object_list params;
-	union acpi_object in_objs[1];
+	union acpi_object in_objs[2];
 	acpi_status status;
 
+	ACPI_FUNCTION_TRACE("acpi_pcc_write_sset");
+
 	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;
+	in_objs[0].integer.value = func;
+	in_objs[1].type = ACPI_TYPE_INTEGER;
+	in_objs[1].integer.value = val;
 
-	status = acpi_evaluate_object(0, (char*)methodName, &params, 0);
-	return (status == AE_OK);
+	status = acpi_evaluate_object(0, DEVICE_NAME_HKEY "." METHOD_HKEY_SSET, &params, 0);
+	return_VALUE(status == AE_OK);
 }
-#endif
 
 static int
 read_acpi_int(acpi_handle handle, const char* methodName, int* pVal)
@@ -201,8 +168,10 @@
 	char* p = page;
 	int len;
 
-	if (off == 0)
-		p = item->read_func(p);
+	if (off == 0) {
+		if (item->read_func)
+			p = item->read_func(p);
+	}
 
 	/* ISSUE: I don't understand this code */
 	len = (p - page);
@@ -237,94 +206,146 @@
 	return result;
 }
 
-/*
- * proc file handlers
- */
-#ifdef DEBUG_PCC_VGA
-static unsigned long
-write_chgd(const char* buffer, unsigned long count)
+static int* sinf;
+static int num_sifr;
+
+static int
+acpi_pcc_init_sinf_buffer(void)
 {
-	int value;
-	acpi_status status;
+	acpi_status status = AE_OK;
 
-	if (sscanf(buffer, "%i", &value) == 1 && value >= 0 && value < 2) {
-		if (value == 0) 
-			/* do nothing */
-			status = AE_OK;
-		else {
-			status = acpi_evaluate_object(0, METHOD_CHGD, 0 , 0);
-		}
-		if (ACPI_FAILURE(status)) {
-			printk(KERN_INFO LOGPREFIX "fail evaluate CHGD()\n");
-			return -EFAULT;
-		}
-	}
-	return count;
+	ACPI_FUNCTION_TRACE("acpi_pcc_init_sinf_buffer");
 
-}
+	if (!read_acpi_int(NULL, DEVICE_NAME_HKEY "." METHOD_HKEY_SQTY, &num_sifr)){
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "evaluation error HKEY.SQTY\n"));
+		return_VALUE(-EINVAL);
+	}
 
-static char*
-read_nothing(char* p)
-{
-	/* nothing to do*/
-	return p;
+	if ((sinf = (int*)kmalloc(sizeof(int) * (num_sifr + 1), GFP_KERNEL)) == NULL ) {
+		status = AE_ERROR;
+	}
+	
+	return_VALUE(status == AE_OK);
 }
-#endif
 
-static char*
-read_hkey_status(char* p)
+static int
+acpi_pcc_retrive_biosdata(void) 
 {
 	acpi_status status;
 	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
 	union acpi_object *hkey = NULL;
-	int i, num_sifr;
+	int i;
 
-	if (!read_acpi_int(NULL, DEVICE_NAME_HKEY "." METHOD_HKEY_SQTY, &num_sifr)){
-		printk(KERN_INFO LOGPREFIX "evaluation error HKEY.SQTY\n");
-		return p;
-	}
+	ACPI_FUNCTION_TRACE("acpi_pcc_retrive_biosdata");
 
 	status = acpi_evaluate_object(NULL, DEVICE_NAME_HKEY "." METHOD_HKEY_SINF, 0 , &buffer);
 	if (ACPI_FAILURE(status)) {
-		printk(KERN_INFO LOGPREFIX "evaluation error HEKY.SINF\n");
-		return p;
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "evaluation error HEKY.SINF\n"));
+		return_VALUE(0);
 	}
+
 	hkey = (union acpi_object *) buffer.pointer;
 	if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) {
-		printk(KERN_INFO LOGPREFIX "Invalid HKEY.SINF\n");
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF\n"));
 		goto end;
 	}
 	
-	if (num_sifr != hkey->package.count) {
-		printk(KERN_INFO LOGPREFIX "SQTY is not equal to SINF length?\n");
+	if (num_sifr < hkey->package.count) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "SQTY reports bad SINF length\n"));
+		status = AE_ERROR;
 		goto end;
 	}
 
 	for (i = 0; i < hkey->package.count; i++) {
 		union acpi_object *element = &(hkey->package.elements[i]);
 		if (likely(element->type == ACPI_TYPE_INTEGER)) {
-			p += sprintf(p, "0x%02x,\n", (unsigned int)element->integer.value);
-		} else
-			printk(KERN_INFO LOGPREFIX "Invalid HKEY.SINF value\n");
+			sinf[i] = (int)element->integer.value;
+		} else 
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF data\n"));
 	}
+	sinf[hkey->package.count] = -1; 
+
 end:
 	acpi_os_free(buffer.pointer);
+	return_VALUE(status == AE_OK);
+}
+
+static char*
+acpi_pcc_read_brightness(char* p)
+{
+	int i;
+
+	if (!acpi_pcc_retrive_biosdata())
+		return p;
+
+	for (i = 2; i < 8 ; i++) {
+		p += sprintf(p, "%d",	sinf[i]);
+		switch (i) {
+		case 2:
+		case 3:
+		case 5:
+		case 6:
+			p += sprintf(p, ",");
+			break;
+		case 4:
+		case 7:
+			p += sprintf(p, "\n");
+			break;
+		default:
+			p += sprintf(p, ","); 
+		}
+	}
+	
+	return p;
+}
+
+static char*
+read_mute(char* p)
+{
+	if (!acpi_pcc_retrive_biosdata())
+		return p;
+
+	p += sprintf(p, "%d\n", sinf[8]);
+
 	return p;
 }
 
+static unsigned long
+write_mute(const char* buffer, unsigned long count)
+{
+	int value;
+
+	if (sscanf(buffer, "%i", &value) == 1 && value >= 0 && value <= 1) {
+		write_sset(8, value);
+	}
+
+	return count;
+}
+
+static unsigned long
+acpi_pcc_write_brightness(const char* buffer, unsigned long count)
+{
+	int value1, value2;
+
+	if (sscanf(buffer, "%i,%i", &value1, &value2) == 2 && value1 >= 0 && value1 < 2 && value2 >=0 && value2 < 20) {
+		write_sset((value1 == 1)?7:4, value2);
+	} else
+		printk("write_brightness error\n");
+
+	return count;
+}
 
 static char*
-read_version(char* p)
+acpi_pcc_read_version(char* p)
 {
 	p += sprintf(p, "%s version %s\n", ACPI_HOTKEY_DRIVER_NAME, ACPI_PCC_VERSION);
-	p += sprintf(p, "proc_interface version %d\n", PROC_INTERFACE_VERSION);
 	return p;
 }
 
 
 /* hotkey driver */
 static int
-acpi_hotkey_get_key(struct acpi_hotkey *hotkey)
+acpi_pcc_hotkey_get_key(struct acpi_hotkey *hotkey)
 {
 	int result;
 	int status;
@@ -339,7 +360,7 @@
 }
 
 void
-acpi_hotkey_notify(acpi_handle handle, u32 event, void *data)
+acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data)
 {
 	struct acpi_hotkey	*hotkey = (struct acpi_hotkey *) data;
 
@@ -348,84 +369,25 @@
 
 	switch(event) {
 	case HKEY_NOTIFY:
-		if (acpi_hotkey_get_key(hotkey))
+		if (acpi_pcc_hotkey_get_key(hotkey))
 			acpi_bus_generate_event(hotkey->device, event, hotkey->status);
 		break;
 	default:
 		/* nothing to do */
 		break;
 	}
-
 	return;
 }
 
-static int
-acpi_hotkey_add (struct acpi_device *device)
-{
-	int			result = 0;
-	acpi_status		status = AE_OK;
-	struct acpi_hotkey	*hotkey = NULL;
-
-	if (!device)
-		return (-EINVAL);
-
-	hotkey = kmalloc(sizeof(struct acpi_hotkey), GFP_KERNEL);
-	if (!hotkey)
-		return (-ENOMEM);
-
-	memset(hotkey, 0, sizeof(struct acpi_hotkey));
-
-	hotkey->device = device;
-	hotkey->handle = device->handle;
-	acpi_driver_data(device) = hotkey;
-	strcpy(acpi_device_name(device), ACPI_HOTKEY_DEVICE_NAME);
-	strcpy(acpi_device_class(device), ACPI_HOTKEY_CLASS);
-
-	status = acpi_install_notify_handler (
-			hotkey->handle,
-			ACPI_DEVICE_NOTIFY,
-			acpi_hotkey_notify,
-			hotkey);
-	if (ACPI_FAILURE(status)) 
-		result = -ENODEV;
-
-	if (result)
-		kfree(hotkey);
-
-	return (result);
-}
-
-static int
-acpi_hotkey_remove(struct acpi_device *device, int type)
-{
-	acpi_status		status = 0;
-	struct acpi_hotkey	*hotkey = NULL;
-
-	if (!device || !acpi_driver_data(device))
-		return(-EINVAL);
-
-	hotkey = acpi_driver_data(device);
-	status = acpi_remove_notify_handler(hotkey->handle,
-		    ACPI_DEVICE_NOTIFY, acpi_hotkey_notify);
-	if (ACPI_FAILURE(status))
-		printk(KERN_INFO LOGPREFIX "Error removing notify handler\n");
-
-	kfree(hotkey);
-
-	return(0);
-}
-
 /*
  * proc and module init
 */
 
 ProcItem pcc_proc_items[] =
 {
-#ifdef DEBUG_PCC_VGA
-	{ "chgd"   , read_nothing , write_chgd},
-#endif
-	{ "hkey_status", read_hkey_status, NULL},
-	{ "version", read_version , NULL},
+	{ "brightness" , acpi_pcc_read_brightness , acpi_pcc_write_brightness},
+	{ "mute", read_mute, write_mute},
+	{ "version", acpi_pcc_read_version , NULL},
 	{ NULL 	   , NULL	  , NULL},
 };
 
@@ -451,7 +413,7 @@
 
 
 static int __init
-pcc_proc_init(void)
+acpi_pcc_proc_init(void)
 {
 	acpi_status status = AE_OK;
 
@@ -479,39 +441,102 @@
 }
 
 
+static int
+acpi_pcc_hotkey_add (struct acpi_device *device)
+{
+	acpi_status		status = AE_OK;
+	struct acpi_hotkey	*hotkey = NULL;
+
+	ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_add");
+
+	if (!device)
+		return_VALUE(-EINVAL);
+
+	acpi_pcc_proc_init();
+	acpi_pcc_init_sinf_buffer();
+
+	hotkey = kmalloc(sizeof(struct acpi_hotkey), GFP_KERNEL);
+	if (!hotkey)
+		return_VALUE(-ENOMEM);
+
+	memset(hotkey, 0, sizeof(struct acpi_hotkey));
+
+	hotkey->device = device;
+	hotkey->handle = device->handle;
+	acpi_driver_data(device) = hotkey;
+	strcpy(acpi_device_name(device), ACPI_HOTKEY_DEVICE_NAME);
+	strcpy(acpi_device_class(device), ACPI_HOTKEY_CLASS);
+
+	status = acpi_install_notify_handler (
+			hotkey->handle,
+			ACPI_DEVICE_NOTIFY,
+			acpi_pcc_hotkey_notify,
+			hotkey);
+
+	if (ACPI_FAILURE(status)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error installing notify handler\n"));		
+		kfree(hotkey); 
+		return_VALUE(-ENODEV);
+	}
+	
+	return_VALUE(0);
+}
+
+static int
+acpi_pcc_hotkey_remove(struct acpi_device *device, int type)
+{
+	acpi_status		status = AE_OK;
+	struct acpi_hotkey	*hotkey = NULL;
+
+	ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_remove");
+
+	if (!device || !acpi_driver_data(device))
+		return_VALUE(-EINVAL);
+
+	if (acpi_pcc_dir) {
+		remove_device(pcc_proc_items, acpi_pcc_dir);
+		remove_proc_entry(PROC_PCC, acpi_root_dir);
+	}
+
+	hotkey = acpi_driver_data(device);
+
+	status = acpi_remove_notify_handler(hotkey->handle,
+		    ACPI_DEVICE_NOTIFY, acpi_pcc_hotkey_notify);
+
+	if (ACPI_FAILURE(status))
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error removing notify handler\n"));
+
+	kfree(hotkey);
+
+	return_VALUE(status == AE_OK);
+}
 
-/* init funcs. */
 static int __init
 acpi_pcc_init(void)
 {
 	acpi_status result = AE_OK;
  
-	if (acpi_disabled)
-		return -ENODEV;
+	ACPI_FUNCTION_TRACE("acpi_pcc_init");
 
-	/* simple device detection: look forI method */
-	if (!(is_valid_acpi_path(METHOD_CHGD)))
-		return -ENODEV;
+	if (acpi_disabled)
+		return_VALUE(-ENODEV);
 
 	result = acpi_bus_register_driver(&acpi_hotkey_driver);
-	if (ACPI_FAILURE(result))
-		printk(KERN_INFO LOGPREFIX "Error registering hotkey driver\n");
-
-	printk(KERN_INFO LOGPREFIX "ACPI PCC HotKey driver version %s\n", ACPI_PCC_VERSION);
-
-	return (pcc_proc_init());
-
+	if (ACPI_FAILURE(result)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error registering hotkey driver\n"));
+		return_VALUE(-ENODEV);
+	}
+	return_VALUE(0);
 }
 
 static void __exit
 acpi_pcc_exit(void)
 {
-	if (acpi_pcc_dir) {
-		remove_device(pcc_proc_items, acpi_pcc_dir);
-		remove_proc_entry(PROC_PCC, acpi_root_dir);
-	}
+	ACPI_FUNCTION_TRACE("acpi_pcc_exit");
+
 	acpi_bus_unregister_driver(&acpi_hotkey_driver); 
-	return;
+
+	return_VOID;
 }
 
 module_init(acpi_pcc_init);


-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver v0.5 [2/2]
       [not found]         ` <87u0uyqqa7.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
@ 2004-08-20  7:44           ` David Bronaugh
       [not found]             ` <4125ABEF.9090106-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
  2004-08-24 23:00           ` John Belmonte
  1 sibling, 1 reply; 27+ messages in thread
From: David Bronaugh @ 2004-08-20  7:44 UTC (permalink / raw)
  To: Hiroshi Miura; +Cc: Len Brown, acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

Hiroshi Miura wrote:

>Hi,
>
>This is incremental bkpatch against pcc_acpi driver v0.4.
>It is made using bkexport.
>
>At Fri, 20 Aug 2004 11:51:31 +0900,
>Hiroshi Miura wrote:
>  
>
>>Hi,
>>
>>I'm also developing lcd brightness driver and clean ups.
>>An infomation of BIOS data is gotten from hardware vendor.
>>
>>These are a little diffence in David's code about bios spec.
>>
>>I want to post my driver soon.
>>    
>>
>
>Hiroshi Miura  --- http://www.da-cha.org/  --- miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org
>NTTDATA Corp. OpenSource Software Center. --- miurahr-3MafRgGXt7BL9jVzuh4AOg@public.gmane.org 
>NTTDATA Intellilink Corp. OpenSource Engineering Dev. -- miurahr-w0OK63jvRlAuJ+9fw/WgBHgSJqDPrsil@public.gmane.org
>Key fingerprint = 9117 9407 5684 FBF1 4063  15B4 401D D077 04AB 8617
>
>  
>
<CUT>

>+static int* sinf;
>+static int num_sifr;
>  
>
Is this really necessary...? Maybe this is just me hating globals.

>+
>+static int
>+acpi_pcc_init_sinf_buffer(void)
> {
>-	int value;
>-	acpi_status status;
>+	acpi_status status = AE_OK;
> 
>-	if (sscanf(buffer, "%i", &value) == 1 && value >= 0 && value < 2) {
>-		if (value == 0) 
>-			/* do nothing */
>-			status = AE_OK;
>-		else {
>-			status = acpi_evaluate_object(0, METHOD_CHGD, 0 , 0);
>-		}
>-		if (ACPI_FAILURE(status)) {
>-			printk(KERN_INFO LOGPREFIX "fail evaluate CHGD()\n");
>-			return -EFAULT;
>-		}
>-	}
>-	return count;
>+	ACPI_FUNCTION_TRACE("acpi_pcc_init_sinf_buffer");
> 
>-}
>+	if (!read_acpi_int(NULL, DEVICE_NAME_HKEY "." METHOD_HKEY_SQTY, &num_sifr)){
>+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "evaluation error HKEY.SQTY\n"));
>+		return_VALUE(-EINVAL);
>+	}
> 
>-static char*
>-read_nothing(char* p)
>-{
>-	/* nothing to do*/
>-	return p;
>+	if ((sinf = (int*)kmalloc(sizeof(int) * (num_sifr + 1), GFP_KERNEL)) == NULL ) {
>+		status = AE_ERROR;
>+	}
>
Doesn't this introduce a memory leak at module unload time? I don't see 
any corresponding kfree()...

<SNIP>

>+static char*
>+acpi_pcc_read_brightness(char* p)
>+{
>+	int i;
>+
>+	if (!acpi_pcc_retrive_biosdata())
>+		return p;
>+
>+	for (i = 2; i < 8 ; i++) {
>+		p += sprintf(p, "%d",	sinf[i]);
>+		switch (i) {
>+		case 2:
>+		case 3:
>+		case 5:
>+		case 6:
>+			p += sprintf(p, ",");
>+			break;
>+		case 4:
>+		case 7:
>+			p += sprintf(p, "\n");
>+			break;
>+		default:
>+			p += sprintf(p, ","); 
>+		}
>+	}
>+	
>  
>
The for loop immediately above could be reduced to:
p += sprintf(p, "%d,%d,%d\n", sinf[2], sinf[3], sinf[4]);
p += sprintf(p, "%d,%d,%d\n", sinf[5], sinf[6], sinf[7]);

<SNIP>

>+static unsigned long
>+acpi_pcc_write_brightness(const char* buffer, unsigned long count)
>+{
>+	int value1, value2;
>+
>+	if (sscanf(buffer, "%i,%i", &value1, &value2) == 2 && value1 >= 0 && value1 < 2 && value2 >=0 && value2 < 20) {
>+		write_sset((value1 == 1)?7:4, value2);
>+	} else
>+		printk("write_brightness error\n");
>+
>+	return count;
>+}
>  
>
Why are there two values for brightness? What do they do?

Thanks in advance,

David Bronaugh


-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver v0.5 [2/2]
       [not found]             ` <4125ABEF.9090106-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
@ 2004-08-20  8:43               ` Hiroshi Miura
       [not found]                 ` <87pt5mqjxj.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
  0 siblings, 1 reply; 27+ messages in thread
From: Hiroshi Miura @ 2004-08-20  8:43 UTC (permalink / raw)
  To: David Bronaugh; +Cc: Len Brown, acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

At Fri, 20 Aug 2004 00:44:47 -0700,
David Bronaugh wrote:
>
> Hiroshi Miura wrote:
> >Hi,
> >
> >This is incremental bkpatch against pcc_acpi driver v0.4.
> >It is made using bkexport.
> >

 <CUT>
 
> >+static int* sinf;
> >+static int num_sifr;
> >  
> >
> Is this really necessary...? Maybe this is just me hating globals.

From Panasonic BIOS specification, driver must alloc memory that quantity
is gotten by SQTY. Ok, I'll try remove this.
 
> >-static char*
> >-read_nothing(char* p)
> >-{
> >-	/* nothing to do*/
> >-	return p;
> >+	if ((sinf = (int*)kmalloc(sizeof(int) * (num_sifr + 1), GFP_KERNEL)) == NULL ) {
> >+		status = AE_ERROR;
> >+	}
> >
> Doesn't this introduce a memory leak at module unload time? I don't see 
> any corresponding kfree()...

kfree() exists on v0.4 patch, i think. 

> 
> <SNIP>
> 
> >+static char*
> >+acpi_pcc_read_brightness(char* p)
> >+{
> >+	int i;
> >+
> >+	if (!acpi_pcc_retrive_biosdata())
> >+		return p;
> >+
> >+	for (i = 2; i < 8 ; i++) {
> >+		p += sprintf(p, "%d",	sinf[i]);
> >+		switch (i) {
> >+		case 2:
> >+		case 3:
> >+		case 5:
> >+		case 6:
> >+			p += sprintf(p, ",");
> >+			break;
> >+		case 4:
> >+		case 7:
> >+			p += sprintf(p, "\n");
> >+			break;
> >+		default:
> >+			p += sprintf(p, ","); 
> >+		}
> >+	}
> >+	
> >  
> >
> The for loop immediately above could be reduced to:
> p += sprintf(p, "%d,%d,%d\n", sinf[2], sinf[3], sinf[4]);
> p += sprintf(p, "%d,%d,%d\n", sinf[5], sinf[6], sinf[7]);

thanks. I'll take it. 

> <SNIP>
> 
> >+static unsigned long
> >+acpi_pcc_write_brightness(const char* buffer, unsigned long count)
> >+{
> >+	int value1, value2;
> >+
> >+	if (sscanf(buffer, "%i,%i", &value1, &value2) == 2 && value1 >= 0 && value1 < 2 && value2 >=0 && value2 < 20) {
> >+		write_sset((value1 == 1)?7:4, value2);
> >+	} else
> >+		printk("write_brightness error\n");
> >+
> >+	return count;
> >+}
> >  
> >
> Why are there two values for brightness? What do they do?

It's from Panasonic spec.

0,n  -- brightness on AC 
1,n  -- brightness on battery. 

If pc go suspend/resume, BIOS set brightness according to this value.

I should further study this interface.

-- 
Hiroshi Miura  --- http://www.da-cha.org/  --- miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org
NTTDATA Corp. OpenSource Software Center. --- miurahr-3MafRgGXt7BL9jVzuh4AOg@public.gmane.org 
NTTDATA Intellilink Corp. OpenSource Engineering Dev. -- miurahr@intellilink.co.jp
Key fingerprint = 9117 9407 5684 FBF1 4063  15B4 401D D077 04AB 8617


-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver v0.5 [2/2]
       [not found]                 ` <87pt5mqjxj.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
@ 2004-08-20 12:46                   ` Stefan Seyfried
  2004-08-20 17:14                   ` David Bronaugh
  1 sibling, 0 replies; 27+ messages in thread
From: Stefan Seyfried @ 2004-08-20 12:46 UTC (permalink / raw)
  To: acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

On Fri, Aug 20, 2004 at 05:43:04PM +0900, Hiroshi Miura wrote:

> > Why are there two values for brightness? What do they do?
> 
> It's from Panasonic spec.
> 
> 0,n  -- brightness on AC 
> 1,n  -- brightness on battery. 

many machines have this, at least Dell D600 and hp compaq nx5000,
so it seems to be quite common.
-- 
Stefan Seyfried



-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver v0.5 [1/2]
       [not found]           ` <87vffeqqaq.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
@ 2004-08-20 17:11             ` Len Brown
  2004-08-21  1:30               ` [letsnote-tech:00074] " Hiroshi Miura
  0 siblings, 1 reply; 27+ messages in thread
From: Len Brown @ 2004-08-20 17:11 UTC (permalink / raw)
  To: Hiroshi Miura
  Cc: David Bronaugh, ACPI Developers,
	letsnote-tech-eXqGM+LsbTTAqL8d+zIrHngSJqDPrsil

On Fri, 2004-08-20 at 02:25, Hiroshi Miura wrote:
> This is a patch of pcc_acpi v0.4.
> It is same as my previous patch, 
> but it is made using 'bkexport' script.

Hiroshi,
are you planning to incorporate the improvements that David Bronaugh
posted yesterday?

thanks,
-Len




-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver v0.5 [2/2]
       [not found]                 ` <87pt5mqjxj.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
  2004-08-20 12:46                   ` Stefan Seyfried
@ 2004-08-20 17:14                   ` David Bronaugh
       [not found]                     ` <41263192.7010300-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
  1 sibling, 1 reply; 27+ messages in thread
From: David Bronaugh @ 2004-08-20 17:14 UTC (permalink / raw)
  To: Hiroshi Miura; +Cc: Len Brown, acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

Hiroshi Miura wrote:

>At Fri, 20 Aug 2004 00:44:47 -0700,
>David Bronaugh wrote:
>  
>
>>>-static char*
>>>-read_nothing(char* p)
>>>-{
>>>-	/* nothing to do*/
>>>-	return p;
>>>+	if ((sinf = (int*)kmalloc(sizeof(int) * (num_sifr + 1), GFP_KERNEL)) == NULL ) {
>>>+		status = AE_ERROR;
>>>+	}
>>>
>>>      
>>>
>>Doesn't this introduce a memory leak at module unload time? I don't see 
>>any corresponding kfree()...
>>    
>>
>
>kfree() exists on v0.4 patch, i think. 
>  
>
I've confirmed that nothing will kfree() sinf once it is allocated. So 
it is a memory leak.

>><SNIP>
>>    
>>
>>>+static unsigned long
>>>+acpi_pcc_write_brightness(const char* buffer, unsigned long count)
>>>+{
>>>+	int value1, value2;
>>>+
>>>+	if (sscanf(buffer, "%i,%i", &value1, &value2) == 2 && value1 >= 0 && value1 < 2 && value2 >=0 && value2 < 20) {
>>>+		write_sset((value1 == 1)?7:4, value2);
>>>+	} else
>>>+		printk("write_brightness error\n");
>>>+
>>>+	return count;
>>>+}
>>> 
>>>
>>>      
>>>
>>Why are there two values for brightness? What do they do?
>>    
>>
>
>It's from Panasonic spec.
>
>0,n  -- brightness on AC 
>1,n  -- brightness on battery. 
>
>If pc go suspend/resume, BIOS set brightness according to this value.
>
>I should further study this interface.
>  
>
At least on my R1, this function is incorrect. Brightness values range 
from 0-255 on my R1. Setting field 4 and field 7 of sinf have exactly 
the same effect (it would appear that they map to the same function) 
even though they end up storing different values; disconnecting and 
connecting AC power does not change how bright the screen is at all. I 
believe this is intentional; however, I also believe that using ACPI to 
store values like this is pointless and it would be better to simplify 
the interface.

My experience is that changing the code to accept values from 0-255 
allows me to set the full range of screen brightnesses; however, setting 
values less than 11 makes the screen flicker like crazy (I assume this 
is because I am underpowering the backlight). So perhaps a floor of, 
say, 15 on the screen brightness would be a good choice to avoid problems.

Also a small complaint -- displaying all 6 registers in 
acpi_pcc_read_brightness is confusing (not to me since I understand the 
code, but to end users).

David Bronaugh


-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver v0.5 [2/2]
       [not found]                     ` <41263192.7010300-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
@ 2004-08-20 17:43                       ` Nate Lawson
       [not found]                         ` <41263840.1010003-Y6VGUYTwhu0@public.gmane.org>
  2004-08-21  1:30                       ` Hiroshi Miura
  1 sibling, 1 reply; 27+ messages in thread
From: Nate Lawson @ 2004-08-20 17:43 UTC (permalink / raw)
  To: David Bronaugh; +Cc: Hiroshi Miura, acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

David Bronaugh wrote:
> Hiroshi Miura wrote:
>> It's from Panasonic spec.
>>
>> 0,n  -- brightness on AC 1,n  -- brightness on battery.
>> If pc go suspend/resume, BIOS set brightness according to this value.
>>
>> I should further study this interface.
>>
> At least on my R1, this function is incorrect. Brightness values range 
> from 0-255 on my R1. Setting field 4 and field 7 of sinf have exactly 
> the same effect (it would appear that they map to the same function) 
> even though they end up storing different values; disconnecting and 
> connecting AC power does not change how bright the screen is at all. I 
> believe this is intentional; however, I also believe that using ACPI to 
> store values like this is pointless and it would be better to simplify 
> the interface.
> 
> My experience is that changing the code to accept values from 0-255 
> allows me to set the full range of screen brightnesses; however, setting 
> values less than 11 makes the screen flicker like crazy (I assume this 
> is because I am underpowering the backlight). So perhaps a floor of, 
> say, 15 on the screen brightness would be a good choice to avoid problems.
> 
> Also a small complaint -- displaying all 6 registers in 
> acpi_pcc_read_brightness is confusing (not to me since I understand the 
> code, but to end users).

We handle these different laptops correctly in the FreeBSD 
acpi_panasonic driver.  It may be a good example for you.

-- 
Nate


-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver v0.5 [2/2]
       [not found]                         ` <41263840.1010003-Y6VGUYTwhu0@public.gmane.org>
@ 2004-08-21  0:46                           ` Hiroshi Miura
  2004-08-21  5:39                           ` Hiroshi Miura
  1 sibling, 0 replies; 27+ messages in thread
From: Hiroshi Miura @ 2004-08-21  0:46 UTC (permalink / raw)
  To: David Bronaugh
  Cc: Nate Lawson, len.brown-ral2JQCrhuEAvxtiuMwx3w,
	acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	letsnote-tech-eXqGM+LsbTTAqL8d+zIrHngSJqDPrsil

Hi,

I got internal datasheet from panasonic lets note team.
They said that they use value 0-20 for lcd brightness and
we should use these values for safety.

The datasheet is written by only Japanese.

sinf description.

SINF: get all setting information
  BIOS struct
    package() {
      mumber of maxmum batteries,	/* now assume only 0,1, or 2 */
      type of LCD ,	/* 0.. normal,  1..semi-transparent */
      maximum brightness on AC,
      minimum brightness on AC,
      current brightness on AC,	
      maximum brightness on DC,	/* if no battery, fix to 0 */
      minimum brightness on DC,	/* if no battery, fix to 0 */
      current brightness on DC,	/* if no battery, fix to 0 */
      current mute state,
      reserved ( == 1),
      current environment state, /* normal temp=0x01,high temp=0x81,no support=0x00 */
    }

At Fri, 20 Aug 2004 10:43:28 -0700,
Nate Lawson wrote:
> 
> David Bronaugh wrote:
> > Hiroshi Miura wrote:
> >> It's from Panasonic spec.
> >>
> >> 0,n  -- brightness on AC 1,n  -- brightness on battery.
> >> If pc go suspend/resume, BIOS set brightness according to this value.
> >>
> >> I should further study this interface.
> >>
> > At least on my R1, this function is incorrect. Brightness values range 
> > from 0-255 on my R1. Setting field 4 and field 7 of sinf have exactly 

Ok, I'll ask to panasonic team that reason.

> > the same effect (it would appear that they map to the same function) 

no. after hibernate/resume, it make effect by BIOS, i think.

> > even though they end up storing different values; disconnecting and 
> > connecting AC power does not change how bright the screen is at all. I

When running OS, brightness change is a work for OS. not BIOS on this spec.
If BIOS can handle brightness by SMI, OS may not be able to handle it.
 
> > believe this is intentional; however, I also believe that using ACPI to 
> > store values like this is pointless and it would be better to simplify 
> > the interface.

I want to simplify interface too, but I also want to implement proper functions.

> > My experience is that changing the code to accept values from 0-255 
> > allows me to set the full range of screen brightnesses; however, setting 

Yes, lets note member said me bios can accept 0-255 but they don't know what 
happen over 20, because they only test 0-20 on Windows XP.

The specsheet I have is up-to-date one, then it might change before.
At least, between R1/T1 and R2/T2/W2/Y2/R3 we have difference.

> > values less than 11 makes the screen flicker like crazy (I assume this 
> > is because I am underpowering the backlight). So perhaps a floor of, 
> > say, 15 on the screen brightness would be a good choice to avoid problems.
> > Also a small complaint -- displaying all 6 registers in 
> > acpi_pcc_read_brightness is confusing (not to me since I understand the 
> > code, but to end users).

My code assumes platform is R2/Y2/T2/W2/R3. R1 is not my focus now.
+/* device(HKEY) definitions */
+#define HKEY_HID               "MAT0019"

my driver handle HID 'MAT0019' but my R1 has HID 'MAT0012'.
It means R1 has different functionality.

My R1 has no SINF methods. it can controll brightness by SMM/SMI functionality.

What your R1's HID or DSDT?
I cannot find other version of DSDT on acpi.sourceforge.net.

> We handle these different laptops correctly in the FreeBSD 
> acpi_panasonic driver.  It may be a good example for you.
> 
> -- 
> Nate

thanks. I want to refer.

-- 
Hiroshi Miura  --- http://www.da-cha.org/  --- miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org
NTTDATA Corp. OpenSource Software Center. --- miurahr-3MafRgGXt7BL9jVzuh4AOg@public.gmane.org 
NTTDATA Intellilink Corp. OpenSource Engineering Dev. -- miurahr-w0OK63jvRlAuJ+9fw/WgBHgSJqDPrsil@public.gmane.org
Key fingerprint = 9117 9407 5684 FBF1 4063  15B4 401D D077 04AB 8617


-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver v0.5 [2/2]
       [not found]                     ` <41263192.7010300-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
  2004-08-20 17:43                       ` Nate Lawson
@ 2004-08-21  1:30                       ` Hiroshi Miura
  1 sibling, 0 replies; 27+ messages in thread
From: Hiroshi Miura @ 2004-08-21  1:30 UTC (permalink / raw)
  To: David Bronaugh
  Cc: Len Brown, acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	letsnote-tech-eXqGM+LsbTTAqL8d+zIrHngSJqDPrsil

At Fri, 20 Aug 2004 10:14:58 -0700,
David Bronaugh wrote:
> I've confirmed that nothing will kfree() sinf once it is allocated. So 
> it is a memory leak.

Ouch.. You are right!  orz...
I will fix ASAP. 

<SNIP>

> At least on my R1, this function is incorrect. Brightness values range 
> from 0-255 on my R1. Setting field 4 and field 7 of sinf have exactly 

Do you have which model of R1?
I have CF-R1P that is 440MX based. I think you have CF-R1M based on 830MG chipset.
between these, ACPI DSDT may be much differ.

Can you tell me what value is on field 2,3 and field 5,6 of sinf?

-- 
Hiroshi Miura  --- http://www.da-cha.org/  --- miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org
NTTDATA Corp. OpenSource Software Center. --- miurahr-3MafRgGXt7BL9jVzuh4AOg@public.gmane.org 
NTTDATA Intellilink Corp. OpenSource Engineering Dev. -- miurahr-w0OK63jvRlAuJ+9fw/WgBHgSJqDPrsil@public.gmane.org
Key fingerprint = 9117 9407 5684 FBF1 4063  15B4 401D D077 04AB 8617


-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [letsnote-tech:00074] Re: [PATCH]Panasonic Hotkey Driver v0.5 [1/2]
  2004-08-20 17:11             ` Len Brown
@ 2004-08-21  1:30               ` Hiroshi Miura
  0 siblings, 0 replies; 27+ messages in thread
From: Hiroshi Miura @ 2004-08-21  1:30 UTC (permalink / raw)
  To: Len Brown
  Cc: David Bronaugh, ACPI Developers,
	letsnote-tech-eXqGM+LsbTTAqL8d+zIrHngSJqDPrsil

Hi Len,

I want to incorporate that. David Bronaugh has CF-R1 that seems 
differ from my CF-R3 and R1.
I want to discuss about it and want to make more good driver.

And I want to ask panasonic person about spec difference. 

At 20 Aug 2004 13:11:24 -0400,
Len Brown wrote:
> 
> On Fri, 2004-08-20 at 02:25, Hiroshi Miura wrote:
> > This is a patch of pcc_acpi v0.4.
> > It is same as my previous patch, 
> > but it is made using 'bkexport' script.
> 
> Hiroshi,
> are you planning to incorporate the improvements that David Bronaugh
> posted yesterday?

-- 
Hiroshi Miura  --- http://www.da-cha.org/  --- miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org
NTTDATA Corp. OpenSource Software Center. --- miurahr-3MafRgGXt7BL9jVzuh4AOg@public.gmane.org 
NTTDATA Intellilink Corp. OpenSource Engineering Dev. -- miurahr-w0OK63jvRlAuJ+9fw/WgBHgSJqDPrsil@public.gmane.org
Key fingerprint = 9117 9407 5684 FBF1 4063  15B4 401D D077 04AB 8617


-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver
       [not found] ` <41244219.1090603-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
  2004-08-20  2:51   ` Hiroshi Miura
@ 2004-08-21  1:42   ` Hiroshi Miura
       [not found]     ` <87zn4pl116.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
  1 sibling, 1 reply; 27+ messages in thread
From: Hiroshi Miura @ 2004-08-21  1:42 UTC (permalink / raw)
  To: David Bronaugh
  Cc: acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	letsnote-tech-eXqGM+LsbTTAqL8d+zIrHngSJqDPrsil

Hi,

At Wed, 18 Aug 2004 23:00:57 -0700,
David Bronaugh wrote:
> +
> +#define	LCD_MAX_BRIGHTNESS 255

max brightness is defined on BIOS sinf field 2,3 and 5,6.
I should use these value for input check. 

> +
> +/* This may be magical -- beware */
> +#define LCD_BRIGHTNESS_INCREMENT 17

more description about it?
flickering?

> +
> +/* Registers of SINF */
> +#define	SINF_LCD_BRIGHTNESS		4

brightness setting are  defined on filed 4 and 7.
meaning is posted by another mail.

<SNIP>


> +static unsigned long write_brightness(const char *p, unsigned long count)
> +{
> +	int brightness = simple_strtol(p, NULL, 10) * LCD_BRIGHTNESS_INCREMENT;
> +	union acpi_object data[2];
> +	struct acpi_object_list args;
> +	uint32_t status;
> +
> +	/* Clean up incoming data */
> +	if (brightness > LCD_MAX_BRIGHTNESS) {
> +		brightness = LCD_MAX_BRIGHTNESS;
> +	} else if (brightness < 0) {
> +		brightness = 0;
> +	}
> +
> +	data[0].type = ACPI_TYPE_INTEGER;
> +	data[0].integer.value = SINF_LCD_BRIGHTNESS;
> +	data[1].type = ACPI_TYPE_INTEGER;
> +	data[1].integer.value = brightness;
> +	args.pointer = data;
> +	args.count = 2;
> +
> +	status = acpi_evaluate_object(NULL,
> +				      DEVICE_NAME_HKEY "." METHOD_HKEY_SSET,
> +				      &args, NULL);
> +
> +	if (ACPI_FAILURE(status)) {
> +		printk(KERN_INFO "Could not write display brightness");
> +	}
> +
> +	return count;
> +}

I want to incorporate this code except for max_value checking.

-- 
Hiroshi Miura  --- http://www.da-cha.org/  --- miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org
NTTDATA Corp. OpenSource Software Center. --- miurahr-3MafRgGXt7BL9jVzuh4AOg@public.gmane.org 
NTTDATA Intellilink Corp. OpenSource Engineering Dev. -- miurahr-w0OK63jvRlAuJ+9fw/WgBHgSJqDPrsil@public.gmane.org
Key fingerprint = 9117 9407 5684 FBF1 4063  15B4 401D D077 04AB 8617


-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver
       [not found]     ` <87zn4pl116.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
@ 2004-08-21  5:33       ` Hiroshi Miura
       [not found]         ` <87n00pkqc5.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
  0 siblings, 1 reply; 27+ messages in thread
From: Hiroshi Miura @ 2004-08-21  5:33 UTC (permalink / raw)
  To: David Bronaugh
  Cc: Hiroshi Miura, acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	letsnote-tech-eXqGM+LsbTTAqL8d+zIrHngSJqDPrsil


Reading dsdt, we can understand difference. 

At Sat, 21 Aug 2004 10:42:29 +0900,
Hiroshi Miura wrote:
> 
> Hi,
> 
> At Wed, 18 Aug 2004 23:00:57 -0700,
> David Bronaugh wrote:
> > +
> > +#define	LCD_MAX_BRIGHTNESS 255
> 
> max brightness is defined on BIOS sinf field 2,3 and 5,6.
> I should use these value for input check. 

From  http://triaez.kaisei.org/~t-ogawa/misc/cf-r1n.dsl.gz
CF-R1N series BIOS is

        Device (HKEY)
        {
            Name (_HID, EisaId ("MAT0019"))
            Name (SIFR, Package (0x09)
            {
                0x01,
                0x00, 
                0xFF, 		/* ac max */
                0x14, 		/* ac min */
                0xFF, 		/* ac current  */
                0xFF, 		/* dc max */
                0x14, 		/* dc min */
                0x7F, 		/* dc current */
                0x00
            }

this means when AC
maximum 0xFF,  minimum 0x14,   default 0xFF
when on battery,
maximum 0xFF,  minimum 0x14,   default 0x7F

I think your let's note laptop may be same as above.

CF-R3 series BIOS is (you can get it from http://acpi.sourceforge.net/dsdt/view.php?id=227)

        Device (HKEY)
        {
            Name (_HID, EisaId ("MAT0019"))
            Name (SIFR, Package (0x0A)
            {
                0x01, 
                0x00, 
                0x14, 	/* ac max */
                Zero, 	/* ac min */
                0xFF, 	/* ac current */
                0x14, 	/* dc max */
                Zero, 	/* dc min */
                0x7F, 	/* dc current */
                0x00, 
                0x01
            })			

this version of DSDT is extended one field.

this means when AC
maximum 0x14,  minimum 0x0,   default 0xFF
when on battery,
maximum 0x14,  minimum 0x0,   default 0x7F

but machine returns AC 0x14, battery 0x0F.

-- 
Hiroshi Miura  --- http://www.da-cha.org/  --- miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org
NTTDATA Corp. OpenSource Software Center. --- miurahr-3MafRgGXt7BL9jVzuh4AOg@public.gmane.org 
NTTDATA Intellilink Corp. OpenSource Engineering Dev. -- miurahr@intellilink.co.jp
Key fingerprint = 9117 9407 5684 FBF1 4063  15B4 401D D077 04AB 8617


-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver v0.5 [2/2]
       [not found]                         ` <41263840.1010003-Y6VGUYTwhu0@public.gmane.org>
  2004-08-21  0:46                           ` Hiroshi Miura
@ 2004-08-21  5:39                           ` Hiroshi Miura
  1 sibling, 0 replies; 27+ messages in thread
From: Hiroshi Miura @ 2004-08-21  5:39 UTC (permalink / raw)
  To: Nate Lawson; +Cc: David Bronaugh, acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

Hi,

At Fri, 20 Aug 2004 10:43:28 -0700,
Nate Lawson wrote:
> 
> We handle these different laptops correctly in the FreeBSD 
> acpi_panasonic driver.  It may be a good example for you.
> 
> -- 
> Nate

I start contacting freebsd developers in order to handle more correctly
both on linux and on FreeBSD. (they are Japanese, I can easily comunicate with them :-)

-- 
Hiroshi Miura  --- http://www.da-cha.org/  --- miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org
NTTDATA Corp. OpenSource Software Center. --- miurahr-3MafRgGXt7BL9jVzuh4AOg@public.gmane.org 
NTTDATA Intellilink Corp. OpenSource Engineering Dev. -- miurahr-w0OK63jvRlAuJ+9fw/WgBHgSJqDPrsil@public.gmane.org
Key fingerprint = 9117 9407 5684 FBF1 4063  15B4 401D D077 04AB 8617


-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver
       [not found]         ` <87n00pkqc5.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
@ 2004-08-21  8:44           ` David Bronaugh
       [not found]             ` <41270B53.3060903-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
  0 siblings, 1 reply; 27+ messages in thread
From: David Bronaugh @ 2004-08-21  8:44 UTC (permalink / raw)
  To: Hiroshi Miura
  Cc: acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	letsnote-tech-eXqGM+LsbTTAqL8d+zIrHngSJqDPrsil

Thank you for the information from the datasheet on the SINF fields' 
meanings. It makes things much easier for me to understand.

Also, the R1 I have is the CF-R1N62ZVKM.

Hiroshi Miura wrote:

>Reading dsdt, we can understand difference. 
>
>At Sat, 21 Aug 2004 10:42:29 +0900,
>Hiroshi Miura wrote:
>  
>
>>Hi,
>>
>>At Wed, 18 Aug 2004 23:00:57 -0700,
>>David Bronaugh wrote:
>>    
>>
>>>+
>>>+#define	LCD_MAX_BRIGHTNESS 255
>>>      
>>>
>>max brightness is defined on BIOS sinf field 2,3 and 5,6.
>>I should use these value for input check. 
>>    
>>
>
>From  http://triaez.kaisei.org/~t-ogawa/misc/cf-r1n.dsl.gz
>CF-R1N series BIOS is
>
>        Device (HKEY)
>        {
>            Name (_HID, EisaId ("MAT0019"))
>            Name (SIFR, Package (0x09)
>            {
>                0x01,
>                0x00, 
>                0xFF, 		/* ac max */
>                0x14, 		/* ac min */
>                0xFF, 		/* ac current  */
>                0xFF, 		/* dc max */
>                0x14, 		/* dc min */
>                0x7F, 		/* dc current */
>                0x00
>            }
>
>this means when AC
>maximum 0xFF,  minimum 0x14,   default 0xFF
>when on battery,
>maximum 0xFF,  minimum 0x14,   default 0x7F
>
>I think your let's note laptop may be same as above.
>  
>
>CF-R3 series BIOS is (you can get it from http://acpi.sourceforge.net/dsdt/view.php?id=227)
>
>        Device (HKEY)
>        {
>            Name (_HID, EisaId ("MAT0019"))
>            Name (SIFR, Package (0x0A)
>            {
>                0x01, 
>                0x00, 
>                0x14, 	/* ac max */
>                Zero, 	/* ac min */
>                0xFF, 	/* ac current */
>                0x14, 	/* dc max */
>                Zero, 	/* dc min */
>                0x7F, 	/* dc current */
>                0x00, 
>                0x01
>            })			
>
>this version of DSDT is extended one field.
>
>this means when AC
>maximum 0x14,  minimum 0x0,   default 0xFF
>when on battery,
>maximum 0x14,  minimum 0x0,   default 0x7F
>
>but machine returns AC 0x14, battery 0x0F.
>  
>
OK, this all makes sense now. It seems like the best way to do screen 
brightness setting would be to read fields 2 and 3 from SINF into 
internal fields (pcc_max_bright and pcc_min_bright?) to check user input 
and make sure it is not outside these bounds.

I don't think it is necessary to adjust (or read) fields 5 6 and 7 -- 
could you confirm on your R3 that these are not necessary (try the 
things I tried on my R1N)? If you can confirm this, we can simplify the 
driver to only expose 1 field for the 'brightness' control.

It might be nice for userspace applications to have access to max and 
min brightness though; maybe add read-only proc entries for 
max_brightness and min_brightness?

If you like, I could implement these things and send a patch tomorrow.

David Bronaugh


-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver
       [not found]             ` <41270B53.3060903-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
@ 2004-08-21 10:34               ` Hiroshi Miura
       [not found]                 ` <87d61klqzh.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
  0 siblings, 1 reply; 27+ messages in thread
From: Hiroshi Miura @ 2004-08-21 10:34 UTC (permalink / raw)
  To: David Bronaugh
  Cc: acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	letsnote-tech-eXqGM+LsbTTAqL8d+zIrHngSJqDPrsil


At Sat, 21 Aug 2004 01:44:03 -0700,
David Bronaugh wrote:
> OK, this all makes sense now. It seems like the best way to do screen 
> brightness setting would be to read fields 2 and 3 from SINF into 
> internal fields (pcc_max_bright and pcc_min_bright?) to check user input 
> and make sure it is not outside these bounds.

these are ok?

pcc_ac_max_bright
pcc_ac_min_bright
pcc_dc_max_bright
pcc_dc_min_bright


> I don't think it is necessary to adjust (or read) fields 5 6 and 7 -- 
> could you confirm on your R3 that these are not necessary (try the 
> things I tried on my R1N)? If you can confirm this, we can simplify the 
> driver to only expose 1 field for the 'brightness' control.

I think it is necessary to adjuct field 5 6 and 7.
This sinf is kept through hibernate/power off and on.
BIOS show this field when boot or resume and set brightness according as power state.


User space utility should set these values as machine power state.

when ac/battery power state is changed, user space utility also should set
brightness as read from sinf field 4 or 7 according as power state.

One idea is driver checks power state and set proper field.
This make simplify user/kernel interface.

-- 
Hiroshi Miura  --- http://www.da-cha.org/  --- miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org
NTTDATA Corp. OpenSource Software Center. --- miurahr-3MafRgGXt7BL9jVzuh4AOg@public.gmane.org 
NTTDATA Intellilink Corp. OpenSource Engineering Dev. -- miurahr-w0OK63jvRlAuJ+9fw/WgBHgSJqDPrsil@public.gmane.org
Key fingerprint = 9117 9407 5684 FBF1 4063  15B4 401D D077 04AB 8617


-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver
       [not found]                 ` <87d61klqzh.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
@ 2004-08-21 11:50                   ` vgod spam
  2004-08-22  6:45                   ` David Bronaugh
  1 sibling, 0 replies; 27+ messages in thread
From: vgod spam @ 2004-08-21 11:50 UTC (permalink / raw)
  To: Hiroshi Miura; +Cc: ACPI-Devel

Hi,
I found a little problem in your driver(ver 0.5)...

> result = acpi_bus_register_driver(&acpi_hotkey_driver);
> if (ACPI_FAILURE(result)) {
>             ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error registering hotkey driver\n"));
>             return_VALUE(-ENODEV);
>}
The return value of acpi_bus_register_driver is the number of devices
that were claimed by the driver, or a negative error status for
failure. But ACPI_FAILURE is a macro for checking whether the value is
zero or not. I think using "if ( result < 0 ) {.." here is better.

BTW, I have wrote a user space hotkey handler in Perl, which supported
LCD brightness adjustment now:)
It is available at http://vgod.info/dl/w2d/hotkey


-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver
       [not found]                 ` <87d61klqzh.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
  2004-08-21 11:50                   ` vgod spam
@ 2004-08-22  6:45                   ` David Bronaugh
       [not found]                     ` <41284119.1060504-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
  1 sibling, 1 reply; 27+ messages in thread
From: David Bronaugh @ 2004-08-22  6:45 UTC (permalink / raw)
  To: Hiroshi Miura
  Cc: acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	letsnote-tech-eXqGM+LsbTTAqL8d+zIrHngSJqDPrsil

[-- Attachment #1: Type: text/plain, Size: 2682 bytes --]

Hiroshi Miura wrote:

>At Sat, 21 Aug 2004 01:44:03 -0700,
>David Bronaugh wrote:
>  
>
>>OK, this all makes sense now. It seems like the best way to do screen 
>>brightness setting would be to read fields 2 and 3 from SINF into 
>>internal fields (pcc_max_bright and pcc_min_bright?) to check user input 
>>and make sure it is not outside these bounds.
>>    
>>
>
>these are ok?
>
>pcc_ac_max_bright
>pcc_ac_min_bright
>pcc_dc_max_bright
>pcc_dc_min_bright
>  
>
In my patch, I took off the "pcc" prefix -- I felt it was unnecessary because the name the driver uses in /proc/acpi is "pcc".

I also modified the names slightly; if you don't like them, you can change them.

>>I don't think it is necessary to adjust (or read) fields 5 6 and 7 -- 
>>could you confirm on your R3 that these are not necessary (try the 
>>things I tried on my R1N)? If you can confirm this, we can simplify the 
>>driver to only expose 1 field for the 'brightness' control.
>>    
>>
>
>I think it is necessary to adjuct field 5 6 and 7.
>This sinf is kept through hibernate/power off and on.
>BIOS show this field when boot or resume and set brightness according as power state.
>
>
>  
>
Yes, I noticed that the SINF does persist over reboots.

The attached patch is against Hiroshi's v0.5 code, and does the following:
 - gives access (via a simple interface) to all the fields in SINF that 
are available on the person's laptop
 - cleans up the coding style to bring it closer to 
Documentation/CodingStyle guidelines
 - cleans up a few messy spots in the code
 - corrects typographic errors
 - documents some of the stranger SINF fields in the code
 - makes an attempt at cleaning up error messages
 - centralizes data structure definitions at the top of the file
 - removes the global 'sinf' variable (I left the 'num_sifr' variable alone)
 - moves the call to acpi_pcc_proc_init to avoid a possible use of 
uninitialized data via the /proc interface

I didn't decide to put code in the driver to make the R1N look like all 
the others; this could be a TODO (though I like having access to all 235 
brightness levels).

I also haven't really cleaned up the error messages enough -- hopefully 
this can happen later. Nor have I unified all the naming conventions -- 
the driver still has an identity crisis (it isn't sure if it's ACPI_PCC, 
pcc_acpi, or HOTKEY).

Someone should run scripts/Lintain on the code, too, to clean up 
inconsistencies.

I have also attached a separate patch which cleans up the in-kernel 
help. Later today (or maybe tomorrow; I'm getting tired) I'll send 
scripts which handle all the hotkey events properly; then these can be 
put up on the website.

David Bronaugh

[-- Attachment #2: pcc-0.6.patch --]
[-- Type: text/x-patch, Size: 15140 bytes --]

diff -Nru la-2.6.8.1/drivers/acpi/pcc_acpi.c linux-2.6.8.1/drivers/acpi/pcc_acpi.c
--- la-2.6.8.1/drivers/acpi/pcc_acpi.c	2004-08-20 13:20:49.000000000 -0700
+++ linux-2.6.8.1/drivers/acpi/pcc_acpi.c	2004-08-21 22:52:32.000000000 -0700
@@ -20,6 +20,11 @@
  *---------------------------------------------------------------------------
  *
  * ChangeLog:
+ *      Aug.20, 2004    David Bronaugh
+ *              - v0.6  Correct brightness controls to reflect reality
+ *                      based on information gleaned by Hiroshi Miura
+ *                      and discussions with Hiroshi Miura
+ *
  *	Aug.10, 2004	Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
  *		- v0.5  support LCD brightness control
  *			based on the disclosed information by MEI.
@@ -39,7 +44,7 @@
  *
  */
 
-#define ACPI_PCC_VERSION	"0.5"
+#define ACPI_PCC_VERSION	"0.6"
 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -56,10 +61,10 @@
 ACPI_MODULE_NAME		("pcc_acpi")
 
 MODULE_AUTHOR("Hiroshi Miura");
-MODULE_DESCRIPTION("ACPI HotKey driver for lets note");
+MODULE_DESCRIPTION("ACPI HotKey driver for Panasonic Lets Note laptops");
 MODULE_LICENSE("GPL");
 
-#define LOGPREFIX "acpi_pcc: "
+#define LOGPREFIX "pcc_acpi: "
 
 /****************************************************
  * Define ACPI PATHs 
@@ -81,15 +86,24 @@
 #define PROC_PCC		"pcc"
 #define PROC_VIDEO "video"
 
-#define ACPI_HOTKEY_DRIVER_NAME "PCC HotKey Driver"
+#define ACPI_PCC_DRIVER_NAME "PCC HotKey Driver"
 #define ACPI_HOTKEY_DEVICE_NAME "HotKey"
 #define ACPI_HOTKEY_CLASS "HKEY"
 
+/* LCD_TYPEs: 0 = Normal, 1 = Semi-transparent
+   ENV_STATEs: Normal temp=0x01, High temp=0x81, N/A=0x00 
+*/
+enum SINF_BITS { SINF_NUM_BATTERIES, SINF_LCD_TYPE, SINF_AC_MAX_BRIGHT, 
+		 SINF_AC_MIN_BRIGHT, SINF_AC_CUR_BRIGHT, SINF_DC_MAX_BRIGHT,
+		 SINF_DC_MIN_BRIGHT, SINF_DC_CUR_BRIGHT, SINF_MUTE,
+		 SINF_RESERVED,      SINF_ENV_STATE,
+};
+
 static int acpi_pcc_hotkey_add (struct acpi_device *device);
 static int acpi_pcc_hotkey_remove (struct acpi_device *device, int type);
 
 static struct acpi_driver acpi_hotkey_driver = {
-	.name =		ACPI_HOTKEY_DRIVER_NAME,
+	.name =		ACPI_PCC_DRIVER_NAME,
 	.class =	ACPI_HOTKEY_CLASS,
 	.ids =		HKEY_HID,
 	.ops =		{
@@ -104,8 +118,17 @@
 	unsigned long		status;
 };
 
-static int
-write_sset(int func, int val)
+typedef struct _ProcItem
+{
+	const char* name;
+	char* (*read_func)(char*);
+	unsigned long (*write_func)(const char*, unsigned long);
+} ProcItem;
+
+static int num_sifr;
+static struct proc_dir_entry* acpi_pcc_dir;
+
+static int write_sset(int func, int val)
 {
 	struct acpi_object_list params;
 	union acpi_object in_objs[2];
@@ -124,8 +147,7 @@
 	return_VALUE(status == AE_OK);
 }
 
-static int
-read_acpi_int(acpi_handle handle, const char* methodName, int* pVal)
+static int read_acpi_int(acpi_handle handle, const char* methodName, int* pVal)
 {
 	struct acpi_buffer results;
 	union acpi_object out_objs[1];
@@ -136,55 +158,49 @@
 
 	status = acpi_evaluate_object(handle, (char*)methodName, 0, &results);
 	if (ACPI_FAILURE(status)) {
-		printk(KERN_INFO "acpi evaluate error on %s\n", methodName);
+		printk(KERN_INFO LOGPREFIX "acpi evaluate error on %s\n", 
+		       methodName);
 		return (-EFAULT);
 	}
 
 	if (out_objs[0].type == ACPI_TYPE_INTEGER) {
 		*pVal = out_objs[0].integer.value;
 	} else {
-		printk(KERN_INFO "return value is not int\n");
+		printk(KERN_INFO LOGPREFIX "return value is not int\n");
 		status = AE_ERROR;
 	}
 
 	return (status == AE_OK);
 }
 
-static struct proc_dir_entry*	acpi_pcc_dir;
-
-typedef struct _ProcItem
-{
-	const char* name;
-	char* (*read_func)(char*);
-	unsigned long (*write_func)(const char*, unsigned long);
-} ProcItem;
-
-
 /* register utils for proc handler */
-static int
-dispatch_read(char* page, char** start, off_t off, int count, int* eof,
-	ProcItem* item)
+static int dispatch_read(char* page, char** start, off_t off, int count, 
+			 int* eof, ProcItem* item)
 {
 	char* p = page;
 	int len;
 
-	if (off == 0) {
-		if (item->read_func)
-			p = item->read_func(p);
+	if (off == 0 && item->read_func) {
+		p = item->read_func(p);
 	}
 
 	/* 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,
+static int dispatch_write(struct file* file, __user const char* buffer,
 	unsigned long count, ProcItem* item)
 {
 	int result;
@@ -197,8 +213,7 @@
 	tmp_buffer = kmalloc(count + 1, GFP_KERNEL);
 	if (copy_from_user(tmp_buffer, buffer, count)) {
 		result = -EFAULT;
-	}
-	else {
+	} else {
 		tmp_buffer[count] = 0;
 		result = item->write_func(tmp_buffer, count);
 	}
@@ -206,41 +221,34 @@
 	return result;
 }
 
-static int* sinf;
-static int num_sifr;
-
-static int
-acpi_pcc_init_sinf_buffer(void)
+static inline int acpi_pcc_get_sqty(void) 
 {
-	acpi_status status = AE_OK;
-
-	ACPI_FUNCTION_TRACE("acpi_pcc_init_sinf_buffer");
+	int s;
 
-	if (!read_acpi_int(NULL, DEVICE_NAME_HKEY "." METHOD_HKEY_SQTY, &num_sifr)){
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "evaluation error HKEY.SQTY\n"));
-		return_VALUE(-EINVAL);
-	}
+	ACPI_FUNCTION_TRACE("acpi_pcc_get_sqty");
 
-	if ((sinf = (int*)kmalloc(sizeof(int) * (num_sifr + 1), GFP_KERNEL)) == NULL ) {
-		status = AE_ERROR;
+	if (read_acpi_int(NULL, DEVICE_NAME_HKEY "." METHOD_HKEY_SQTY, &s)) {
+		return s;
+	} else {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+				  "evaluation error HKEY.SQTY\n"));
+		return -EINVAL;
 	}
 	
-	return_VALUE(status == AE_OK);
 }
 
-static int
-acpi_pcc_retrive_biosdata(void) 
+static int acpi_pcc_retrieve_biosdata(u32* sinf) 
 {
 	acpi_status status;
 	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
 	union acpi_object *hkey = NULL;
 	int i;
 
-	ACPI_FUNCTION_TRACE("acpi_pcc_retrive_biosdata");
+	ACPI_FUNCTION_TRACE("acpi_pcc_retrieve_biosdata");
 
 	status = acpi_evaluate_object(NULL, DEVICE_NAME_HKEY "." METHOD_HKEY_SINF, 0 , &buffer);
 	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "evaluation error HEKY.SINF\n"));
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "evaluation error HKEY.SINF\n"));
 		return_VALUE(0);
 	}
 
@@ -259,7 +267,7 @@
 	for (i = 0; i < hkey->package.count; i++) {
 		union acpi_object *element = &(hkey->package.elements[i]);
 		if (likely(element->type == ACPI_TYPE_INTEGER)) {
-			sinf[i] = (int)element->integer.value;
+			sinf[i] = element->integer.value;
 		} else 
 			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF data\n"));
 	}
@@ -270,91 +278,160 @@
 	return_VALUE(status == AE_OK);
 }
 
-static char*
-acpi_pcc_read_brightness(char* p)
+static char* acpi_pcc_read_sinf_field(char* p, int field) 
 {
-	int i;
+	u32* sinf;
 
-	if (!acpi_pcc_retrive_biosdata())
+	if (!(sinf = kmalloc(sizeof(u32) * num_sifr, GFP_KERNEL))) {
+		printk(KERN_INFO LOGPREFIX "Couldn't allocate %i bytes\n", 
+		       sizeof(u32) * num_sifr);
 		return p;
+	}
 
-	for (i = 2; i < 8 ; i++) {
-		p += sprintf(p, "%d",	sinf[i]);
-		switch (i) {
-		case 2:
-		case 3:
-		case 5:
-		case 6:
-			p += sprintf(p, ",");
-			break;
-		case 4:
-		case 7:
-			p += sprintf(p, "\n");
-			break;
-		default:
-			p += sprintf(p, ","); 
-		}
+	if (acpi_pcc_retrieve_biosdata(sinf)) {
+		p += sprintf(p, "%d\n",	sinf[field]);
+	} else {
+		printk(KERN_INFO LOGPREFIX "Couldn't retrieve BIOS data\n");
 	}
-	
+
+	kfree(sinf);
 	return p;
 }
 
-static char*
-read_mute(char* p)
+/* Sinf read methods */
+static char* acpi_pcc_read_num_batteries(char* p) 
 {
-	if (!acpi_pcc_retrive_biosdata())
-		return p;
+	return acpi_pcc_read_sinf_field(p, SINF_NUM_BATTERIES);
+}
 
-	p += sprintf(p, "%d\n", sinf[8]);
+static char* acpi_pcc_read_lcd_type(char* p) 
+{
+	return acpi_pcc_read_sinf_field(p, SINF_LCD_TYPE);
+}
 
-	return p;
+static char* acpi_pcc_read_ac_max_brightness(char* p) 
+{
+	return acpi_pcc_read_sinf_field(p, SINF_AC_MAX_BRIGHT);
 }
 
-static unsigned long
-write_mute(const char* buffer, unsigned long count)
+static char* acpi_pcc_read_ac_min_brightness(char* p) 
 {
-	int value;
+	return acpi_pcc_read_sinf_field(p, SINF_AC_MIN_BRIGHT);
+}
+
+static char* acpi_pcc_read_ac_brightness(char* p) 
+{
+	return acpi_pcc_read_sinf_field(p, SINF_AC_CUR_BRIGHT);
+}
+
+static char* acpi_pcc_read_dc_max_brightness(char* p) 
+{
+	return acpi_pcc_read_sinf_field(p, SINF_DC_MAX_BRIGHT);
+}
+
+static char* acpi_pcc_read_dc_min_brightness(char* p) 
+{
+	return acpi_pcc_read_sinf_field(p, SINF_DC_MIN_BRIGHT);
+}
+
+static char* acpi_pcc_read_dc_brightness(char* p) 
+{
+	return acpi_pcc_read_sinf_field(p, SINF_DC_CUR_BRIGHT);
+}
+
+static char* acpi_pcc_read_mute(char* p) 
+{
+	return acpi_pcc_read_sinf_field(p, SINF_MUTE);
+}
+
+static char* acpi_pcc_read_env_state(char* p) 
+{
+	return acpi_pcc_read_sinf_field(p, SINF_ENV_STATE);
+}
+
+static unsigned long acpi_pcc_write_mute(const char* buffer, 
+					 unsigned long count)
+{
+	u32 value;
 
 	if (sscanf(buffer, "%i", &value) == 1 && value >= 0 && value <= 1) {
-		write_sset(8, value);
+		write_sset(SINF_MUTE, value);
 	}
 
 	return count;
 }
 
-static unsigned long
-acpi_pcc_write_brightness(const char* buffer, unsigned long count)
-{
-	int value1, value2;
+static unsigned long acpi_pcc_write_brightness(const char* buffer,
+					       unsigned long count,
+					       int min_index, int max_index,
+					       int cur_index)
+{
+	u32 bright;
+	u32* sinf;
+
+	if (!(sinf = kmalloc(sizeof(u32) * num_sifr, GFP_KERNEL))) {
+		printk(KERN_INFO LOGPREFIX "Couldn't allocate %i bytes\n", 
+		       sizeof(u32) * num_sifr);
+		return count;
+	}
+
+	if (!acpi_pcc_retrieve_biosdata(sinf)) {
+		printk(KERN_INFO LOGPREFIX "Couldn't retrieve BIOS data\n");
+		goto end;
+	}
+	
+	if (!sscanf(buffer, "%i", &bright)) {
+		printk(KERN_INFO LOGPREFIX "Invalid DC brightness\n");
+		goto end;
+	}
 
-	if (sscanf(buffer, "%i,%i", &value1, &value2) == 2 && value1 >= 0 && value1 < 2 && value2 >=0 && value2 < 20) {
-		write_sset((value1 == 1)?7:4, value2);
-	} else
-		printk("write_brightness error\n");
+	if (bright >= sinf[min_index] && bright <= sinf[max_index]) {
+		write_sset(cur_index, bright);
+	}
 
+end: 
+	kfree(sinf);
 	return count;
 }
 
-static char*
-acpi_pcc_read_version(char* p)
+
+static unsigned long acpi_pcc_write_ac_brightness(const char* buffer, 
+						  unsigned long count)
+{
+	return acpi_pcc_write_brightness(buffer, count, SINF_AC_MIN_BRIGHT, 
+					 SINF_AC_MAX_BRIGHT, 
+					 SINF_AC_CUR_BRIGHT);
+}
+
+static unsigned long acpi_pcc_write_dc_brightness(const char* buffer, 
+						  unsigned long count)
+{
+	return acpi_pcc_write_brightness(buffer, count, SINF_DC_MIN_BRIGHT, 
+					 SINF_DC_MAX_BRIGHT, 
+					 SINF_DC_CUR_BRIGHT);
+}
+
+static char* acpi_pcc_read_version(char* p)
 {
-	p += sprintf(p, "%s version %s\n", ACPI_HOTKEY_DRIVER_NAME, ACPI_PCC_VERSION);
+	p += sprintf(p, "%s version %s\n", ACPI_PCC_DRIVER_NAME, 
+		     ACPI_PCC_VERSION);
+	p += sprintf(p, "%i functions\n", num_sifr);
 	return p;
 }
 
 
 /* hotkey driver */
-static int
-acpi_pcc_hotkey_get_key(struct acpi_hotkey *hotkey)
+static int acpi_pcc_hotkey_get_key(struct acpi_hotkey *hotkey)
 {
 	int result;
 	int status;
 
 	status = read_acpi_int(hotkey->handle, METHOD_HKEY_QUERY, &result);
-	if (!status) {
+	if (status > 0) {
 		printk(KERN_INFO LOGPREFIX "error getting hotkey status\n");
-	} else
+	} else {
 		hotkey->status = result;
+	}
 
 	return (status);
 }
@@ -369,8 +446,9 @@
 
 	switch(event) {
 	case HKEY_NOTIFY:
-		if (acpi_pcc_hotkey_get_key(hotkey))
+		if (acpi_pcc_hotkey_get_key(hotkey)) {
 			acpi_bus_generate_event(hotkey->device, event, hotkey->status);
+		}
 		break;
 	default:
 		/* nothing to do */
@@ -383,37 +461,52 @@
  * proc and module init
 */
 
+/* Note: These functions map *exactly* to the SINF/SSET functions */
 ProcItem pcc_proc_items[] =
 {
-	{ "brightness" , acpi_pcc_read_brightness , acpi_pcc_write_brightness},
-	{ "mute", read_mute, write_mute},
+	{ "num_batteries", acpi_pcc_read_num_batteries, NULL },
+	{ "lcd_type", acpi_pcc_read_lcd_type, NULL },
+	{ "ac_brightness_max" , acpi_pcc_read_ac_max_brightness, NULL },
+	{ "ac_brightness_min" , acpi_pcc_read_ac_min_brightness, NULL },
+	{ "ac_brightness" , acpi_pcc_read_ac_brightness, 
+	  acpi_pcc_write_ac_brightness},
+	{ "dc_brightness_max" , acpi_pcc_read_dc_max_brightness, NULL },
+	{ "dc_brightness_min" , acpi_pcc_read_dc_min_brightness, NULL },
+	{ "dc_brightness" , acpi_pcc_read_dc_brightness, 
+	  acpi_pcc_write_dc_brightness},
+	{ "mute", acpi_pcc_read_mute, acpi_pcc_write_mute},
 	{ "version", acpi_pcc_read_version , NULL},
+	{ "environment_state", acpi_pcc_read_env_state, NULL },
 	{ NULL 	   , NULL	  , NULL},
 };
 
-static acpi_status __init
-add_device(ProcItem *proc_items, struct proc_dir_entry* proc_entry)
+static acpi_status __init add_device(ProcItem *proc_items, 
+				     struct proc_dir_entry* proc_entry)
 {
 	struct proc_dir_entry* proc;
 	ProcItem* item;
+	int i;
 
-	for (item = proc_items; item->name; ++item)
-	{
+	for (item = proc_items, i = 0; item->name && i <= num_sifr; 
+	     ++item, ++i) {
 		proc = create_proc_read_entry(item->name,
-			S_IFREG | S_IRUGO | S_IWUSR,
-			proc_entry, (read_proc_t*)dispatch_read, item);
-		if (proc)
+					      S_IFREG | S_IRUGO | S_IWUSR,
+					      proc_entry, 
+					      (read_proc_t*)dispatch_read, 
+					      item);
+		if (proc) {
 			proc->owner = THIS_MODULE;
-		if (proc && item->write_func)
+		}
+		if (proc && item->write_func) {
 			proc->write_proc = (write_proc_t*)dispatch_write;
+		}
 	}
 
 	return(AE_OK);
 }
 
 
-static int __init
-acpi_pcc_proc_init(void)
+static int __init acpi_pcc_proc_init(void)
 {
 	acpi_status status = AE_OK;
 
@@ -430,8 +523,8 @@
 	return (status == AE_OK);
 }
 
-static acpi_status __exit
-remove_device(ProcItem *proc_items, struct proc_dir_entry* proc_entry)
+static acpi_status __exit remove_device(ProcItem *proc_items, 
+					struct proc_dir_entry* proc_entry)
 {
 	ProcItem* item;
 
@@ -441,8 +534,7 @@
 }
 
 
-static int
-acpi_pcc_hotkey_add (struct acpi_device *device)
+static int acpi_pcc_hotkey_add (struct acpi_device *device)
 {
 	acpi_status		status = AE_OK;
 	struct acpi_hotkey	*hotkey = NULL;
@@ -452,9 +544,6 @@
 	if (!device)
 		return_VALUE(-EINVAL);
 
-	acpi_pcc_proc_init();
-	acpi_pcc_init_sinf_buffer();
-
 	hotkey = kmalloc(sizeof(struct acpi_hotkey), GFP_KERNEL);
 	if (!hotkey)
 		return_VALUE(-ENOMEM);
@@ -478,12 +567,15 @@
 		kfree(hotkey); 
 		return_VALUE(-ENODEV);
 	}
+
+	num_sifr = acpi_pcc_get_sqty();
 	
+	acpi_pcc_proc_init();
+
 	return_VALUE(0);
 }
 
-static int
-acpi_pcc_hotkey_remove(struct acpi_device *device, int type)
+static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type)
 {
 	acpi_status		status = AE_OK;
 	struct acpi_hotkey	*hotkey = NULL;
@@ -511,8 +603,7 @@
 	return_VALUE(status == AE_OK);
 }
 
-static int __init
-acpi_pcc_init(void)
+static int __init acpi_pcc_init(void)
 {
 	acpi_status result = AE_OK;
  

[-- Attachment #3: pcc-doc-0.6.patch --]
[-- Type: text/x-patch, Size: 1171 bytes --]

--- la-2.6.8.1/drivers/acpi/Kconfig	2004-08-20 13:19:49.000000000 -0700
+++ linux-2.6.8.1/drivers/acpi/Kconfig	2004-08-21 23:24:22.000000000 -0700
@@ -211,18 +211,19 @@
 	default m
 	---help---
 	  This driver adds support for access to certain system settings
-	  on panasonic Let's Note laptops. 
+	  on Panasonic Let's Note laptops. 
 
-	  On these machines, all hotkey is handled through the ACPI.
+	  On these machines, all hotkeys are handled through the ACPI.
 	  This driver is required for access to controls not covered
 	  by the general ACPI drivers, such as LCD brightness, video output,
 	  etc.
 
-	  More information about this driver will be available at
-	  <http://www.da-cha.org/letsnote/>
+          In order to use this driver, you must configure acpid to handle 
+	  hotkey events; scripts to handle these events and information about 
+	  this driver will be available at <http://www.da-cha.org/letsnote/>
 
-	  If you have a panasonic lets note laptop (such as the CF-T2, Y2,
-	  R2, W2, R3), say Y.
+	  If you have a Panasonic Let's Note laptop (such as the CF-T2, Y2,
+	  R1N, R2, W2, R3), say Y.
 
 config ACPI_DEBUG
 	bool "Debug Statements"

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver
       [not found]                     ` <41284119.1060504-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
@ 2004-08-22  8:27                       ` David Bronaugh
       [not found]                         ` <412858F0.8050406-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
  0 siblings, 1 reply; 27+ messages in thread
From: David Bronaugh @ 2004-08-22  8:27 UTC (permalink / raw)
  To: Hiroshi Miura
  Cc: acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	letsnote-tech-eXqGM+LsbTTAqL8d+zIrHngSJqDPrsil

[-- Attachment #1: Type: text/plain, Size: 2924 bytes --]

David Bronaugh wrote:

> Hiroshi Miura wrote:
>
>> At Sat, 21 Aug 2004 01:44:03 -0700,
>> David Bronaugh wrote:
>>  
>>
>>> OK, this all makes sense now. It seems like the best way to do 
>>> screen brightness setting would be to read fields 2 and 3 from SINF 
>>> into internal fields (pcc_max_bright and pcc_min_bright?) to check 
>>> user input and make sure it is not outside these bounds.
>>>   
>>
>>
>> these are ok?
>>
>> pcc_ac_max_bright
>> pcc_ac_min_bright
>> pcc_dc_max_bright
>> pcc_dc_min_bright
>>  
>>
> In my patch, I took off the "pcc" prefix -- I felt it was unnecessary 
> because the name the driver uses in /proc/acpi is "pcc".
>
> I also modified the names slightly; if you don't like them, you can 
> change them.
>
>>> I don't think it is necessary to adjust (or read) fields 5 6 and 7 
>>> -- could you confirm on your R3 that these are not necessary (try 
>>> the things I tried on my R1N)? If you can confirm this, we can 
>>> simplify the driver to only expose 1 field for the 'brightness' 
>>> control.
>>>   
>>
>>
>> I think it is necessary to adjuct field 5 6 and 7.
>> This sinf is kept through hibernate/power off and on.
>> BIOS show this field when boot or resume and set brightness according 
>> as power state.
>>
>>
>>  
>>
> Yes, I noticed that the SINF does persist over reboots.
>
> The attached patch is against Hiroshi's v0.5 code, and does the 
> following:
> - gives access (via a simple interface) to all the fields in SINF that 
> are available on the person's laptop
> - cleans up the coding style to bring it closer to 
> Documentation/CodingStyle guidelines
> - cleans up a few messy spots in the code
> - corrects typographic errors
> - documents some of the stranger SINF fields in the code
> - makes an attempt at cleaning up error messages
> - centralizes data structure definitions at the top of the file
> - removes the global 'sinf' variable (I left the 'num_sifr' variable 
> alone)
> - moves the call to acpi_pcc_proc_init to avoid a possible use of 
> uninitialized data via the /proc interface
>
> I didn't decide to put code in the driver to make the R1N look like 
> all the others; this could be a TODO (though I like having access to 
> all 235 brightness levels).
>
> I also haven't really cleaned up the error messages enough -- 
> hopefully this can happen later. Nor have I unified all the naming 
> conventions -- the driver still has an identity crisis (it isn't sure 
> if it's ACPI_PCC, pcc_acpi, or HOTKEY).
>
> Someone should run scripts/Lintain on the code, too, to clean up 
> inconsistencies.
>
> I have also attached a separate patch which cleans up the in-kernel 
> help. Later today (or maybe tomorrow; I'm getting tired) I'll send 
> scripts which handle all the hotkey events properly; then these can be 
> put up on the website.
>
> David Bronaugh

Gah, I goofed and inverted a check.

Attached is a patch that fixes it.

David Bronaugh

[-- Attachment #2: pcc-0.6.1.patch --]
[-- Type: text/x-patch, Size: 957 bytes --]

--- la-2.6.8.1/drivers/acpi/pcc_acpi.c	2004-08-22 01:21:03.000000000 -0700
+++ linux-2.6.8.1/drivers/acpi/pcc_acpi.c	2004-08-22 01:23:41.000000000 -0700
@@ -20,6 +20,8 @@
  *---------------------------------------------------------------------------
  *
  * ChangeLog:
+ *      Aug.21, 2004    David Bronaugh
+ *              - v0.6.1 Fix a silly error with status checking
  *      Aug.20, 2004    David Bronaugh
  *              - v0.6  Correct brightness controls to reflect reality
  *                      based on information gleaned by Hiroshi Miura
@@ -44,7 +46,7 @@
  *
  */
 
-#define ACPI_PCC_VERSION	"0.6"
+#define ACPI_PCC_VERSION	"0.6.1"
 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -427,7 +429,7 @@
 	int status;
 
 	status = read_acpi_int(hotkey->handle, METHOD_HKEY_QUERY, &result);
-	if (status > 0) {
+	if (status < 0) {
 		printk(KERN_INFO LOGPREFIX "error getting hotkey status\n");
 	} else {
 		hotkey->status = result;

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver
       [not found]                         ` <412858F0.8050406-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
@ 2004-08-23  5:07                           ` David Bronaugh
       [not found]                             ` <41297BA7.3050503-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
  0 siblings, 1 reply; 27+ messages in thread
From: David Bronaugh @ 2004-08-23  5:07 UTC (permalink / raw)
  To: Hiroshi Miura
  Cc: acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	letsnote-tech-eXqGM+LsbTTAqL8d+zIrHngSJqDPrsil

[-- Attachment #1: Type: text/plain, Size: 1060 bytes --]

Hey all,

Well, it's time for my daily source code release... I shouldn't make a 
habit of this. The following patch is against v0.6.1, fixes a few small 
bugs, and cleans up the code some.

Also attached are perl scripts (ac_adapt.pl, hotkey.pl) to handle all of 
the hotkey events in a safe and sane manner and handle AC adapter 
connect/disconnect. The assumptions and requirements of these scripts 
are listed in the headers for them.

I've included as well the event/* files needed (ac_adapter, hotkey).

The kernel code is still missing the ability to change display device -- 
but other than that, I can't see very much missing from it.

Together, the scripts and the patch enable all of the user's hotkeys 
except suspend-to-RAM (which seems troublesome on all machines) and 
switching display device (because we don't get an event for that). The 
scripts handle changing the correct display brightness field depending 
on power status.

As a side note, I feel that this code is nearing release quality. 
Hiroshi, what is your opinion?

David Bronaugh

[-- Attachment #2: pcc-0.6.2.patch --]
[-- Type: text/x-patch, Size: 6480 bytes --]

--- la-2.6.8.1/drivers/acpi/pcc_acpi.c	2004-08-22 11:05:27.000000000 -0700
+++ linux-2.6.8.1/drivers/acpi/pcc_acpi.c	2004-08-22 13:30:54.000000000 -0700
@@ -20,9 +20,15 @@
  *---------------------------------------------------------------------------
  *
  * ChangeLog:
- *      Aug.21, 2004    David Bronaugh
- *              - v0.6.1 Fix a silly error with status checking
- *      Aug.20, 2004    David Bronaugh
+ *      Aug.22, 2004    David Bronaugh <dbronaugh-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
+ *              -v0.6.2 Add check on ACPI data (num_sifr)
+ *                      Coding style cleanups, better error messages/handling
+ *			Fixed an off-by-one error in memory allocation
+ *
+ *      Aug.21, 2004    David Bronaugh <dbronaugh-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
+ *              -v0.6.1 Fix a silly error with status checking
+ *
+ *      Aug.20, 2004    David Bronaugh <dbronaugh-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
  *              - v0.6  Correct brightness controls to reflect reality
  *                      based on information gleaned by Hiroshi Miura
  *                      and discussions with Hiroshi Miura
@@ -46,7 +52,7 @@
  *
  */
 
-#define ACPI_PCC_VERSION	"0.6.1"
+#define ACPI_PCC_VERSION	"0.6.2"
 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -162,7 +168,7 @@
 	if (ACPI_FAILURE(status)) {
 		printk(KERN_INFO LOGPREFIX "acpi evaluate error on %s\n", 
 		       methodName);
-		return (-EFAULT);
+		return -EFAULT;
 	}
 
 	if (out_objs[0].type == ACPI_TYPE_INTEGER) {
@@ -213,12 +219,21 @@
 	 * destination so that sscanf can be used on it safely.
 	 */
 	tmp_buffer = kmalloc(count + 1, GFP_KERNEL);
+	if (!tmp_buffer) {
+		printk(KERN_INFO LOGPREFIX "dispatch_write: Couldn't allocate buffer");
+		return -EFAULT;
+	}
+
 	if (copy_from_user(tmp_buffer, buffer, count)) {
+		printk(KERN_INFO LOGPREFIX "dispatch_write: Couldn't copy data from userspace");
 		result = -EFAULT;
-	} else {
-		tmp_buffer[count] = 0;
-		result = item->write_func(tmp_buffer, count);
+		goto end;
 	}
+
+	tmp_buffer[count] = 0;
+	result = item->write_func(tmp_buffer, count);
+		
+end:
 	kfree(tmp_buffer);
 	return result;
 }
@@ -236,7 +251,6 @@
 				  "evaluation error HKEY.SQTY\n"));
 		return -EINVAL;
 	}
-	
 }
 
 static int acpi_pcc_retrieve_biosdata(u32* sinf) 
@@ -270,8 +284,9 @@
 		union acpi_object *element = &(hkey->package.elements[i]);
 		if (likely(element->type == ACPI_TYPE_INTEGER)) {
 			sinf[i] = element->integer.value;
-		} else 
+		} else {
 			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF data\n"));
+		}
 	}
 	sinf[hkey->package.count] = -1; 
 
@@ -282,9 +297,9 @@
 
 static char* acpi_pcc_read_sinf_field(char* p, int field) 
 {
-	u32* sinf;
+	u32* sinf = kmalloc(sizeof(u32) * (num_sifr + 1), GFP_KERNEL);
 
-	if (!(sinf = kmalloc(sizeof(u32) * num_sifr, GFP_KERNEL))) {
+	if (!sinf) {
 		printk(KERN_INFO LOGPREFIX "Couldn't allocate %i bytes\n", 
 		       sizeof(u32) * num_sifr);
 		return p;
@@ -369,9 +384,9 @@
 					       int cur_index)
 {
 	u32 bright;
-	u32* sinf;
+	u32* sinf = kmalloc(sizeof(u32) * (num_sifr + 1), GFP_KERNEL);
 
-	if (!(sinf = kmalloc(sizeof(u32) * num_sifr, GFP_KERNEL))) {
+	if (!sinf) {
 		printk(KERN_INFO LOGPREFIX "Couldn't allocate %i bytes\n", 
 		       sizeof(u32) * num_sifr);
 		return count;
@@ -421,7 +436,6 @@
 	return p;
 }
 
-
 /* hotkey driver */
 static int acpi_pcc_hotkey_get_key(struct acpi_hotkey *hotkey)
 {
@@ -438,14 +452,10 @@
 	return (status);
 }
 
-void
-acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data)
+void acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data)
 {
 	struct acpi_hotkey	*hotkey = (struct acpi_hotkey *) data;
 
-	if (!hotkey || !hotkey->device)
-		return;
-
 	switch(event) {
 	case HKEY_NOTIFY:
 		if (acpi_pcc_hotkey_get_key(hotkey)) {
@@ -475,11 +485,11 @@
 	{ "dc_brightness_max" , acpi_pcc_read_dc_max_brightness, NULL },
 	{ "dc_brightness_min" , acpi_pcc_read_dc_min_brightness, NULL },
 	{ "dc_brightness" , acpi_pcc_read_dc_brightness, 
-	  acpi_pcc_write_dc_brightness},
-	{ "mute", acpi_pcc_read_mute, acpi_pcc_write_mute},
-	{ "version", acpi_pcc_read_version , NULL},
+	  acpi_pcc_write_dc_brightness },
+	{ "mute", acpi_pcc_read_mute, acpi_pcc_write_mute },
+	{ "version", acpi_pcc_read_version , NULL },
 	{ "environment_state", acpi_pcc_read_env_state, NULL },
-	{ NULL 	   , NULL	  , NULL},
+	{ NULL 	   , NULL	  , NULL },
 };
 
 static acpi_status __init add_device(ProcItem *proc_items, 
@@ -504,20 +514,22 @@
 		}
 	}
 
-	return(AE_OK);
+	return AE_OK;
 }
 
-
 static int __init acpi_pcc_proc_init(void)
 {
 	acpi_status status = AE_OK;
+	acpi_pcc_dir = proc_mkdir(PROC_PCC, acpi_root_dir);
 
-	if (unlikely(!(acpi_pcc_dir = proc_mkdir(PROC_PCC, acpi_root_dir))))
+	if (unlikely(!acpi_pcc_dir)) {
+		printk(KERN_INFO LOGPREFIX "Couldn't create dir in /proc\n");
 		return -ENODEV;
+	}
 
 	acpi_pcc_dir->owner = THIS_MODULE;
 	status = add_device(pcc_proc_items, acpi_pcc_dir);
-	if (ACPI_FAILURE(status)){
+	if (ACPI_FAILURE(status)) {
 		remove_proc_entry(PROC_PCC, acpi_root_dir);
 		return -ENODEV;
 	}
@@ -530,12 +542,12 @@
 {
 	ProcItem* item;
 
-	for (item = proc_items; item->name; ++item)
+	for (item = proc_items; item->name; ++item) {
 		remove_proc_entry(item->name, proc_entry);
+	}
 	return(AE_OK);
 }
 
-
 static int acpi_pcc_hotkey_add (struct acpi_device *device)
 {
 	acpi_status		status = AE_OK;
@@ -543,12 +555,22 @@
 
 	ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_add");
 
-	if (!device)
+	if (!device) {
 		return_VALUE(-EINVAL);
+	}
+
+	num_sifr = acpi_pcc_get_sqty();
+	
+	if (num_sifr > 255) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "num_sifr too large"));
+		return_VALUE(-ENODEV);
+	}
 
 	hotkey = kmalloc(sizeof(struct acpi_hotkey), GFP_KERNEL);
-	if (!hotkey)
+	if (!hotkey) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate mem for hotkey"));
 		return_VALUE(-ENOMEM);
+	}
 
 	memset(hotkey, 0, sizeof(struct acpi_hotkey));
 
@@ -570,8 +592,6 @@
 		return_VALUE(-ENODEV);
 	}
 
-	num_sifr = acpi_pcc_get_sqty();
-	
 	acpi_pcc_proc_init();
 
 	return_VALUE(0);
@@ -601,7 +621,6 @@
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error removing notify handler\n"));
 
 	kfree(hotkey);
-
 	return_VALUE(status == AE_OK);
 }
 
@@ -611,8 +630,9 @@
  
 	ACPI_FUNCTION_TRACE("acpi_pcc_init");
 
-	if (acpi_disabled)
+	if (acpi_disabled) {
 		return_VALUE(-ENODEV);
+	}
 
 	result = acpi_bus_register_driver(&acpi_hotkey_driver);
 	if (ACPI_FAILURE(result)) {

[-- Attachment #3: ac_adapt.pl --]
[-- Type: text/x-perl, Size: 2149 bytes --]

#!/usr/bin/perl -w
# AC Power Handler v1.0
# Handles AC power events for Panasonic notebooks
#
# Copyright (C) 2004 David Bronaugh
#
# Requires pcc_acpi driver
#
# This program is free software; you can redistribute it and/or modify 
# it under the terms of the GNU General Public License version 2 as 
# published by the Free Software Foundation
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

use strict;
use POSIX qw(ceil floor);

our($config);
our($power_state);

sub read_file {
  my($file) = @_;
  my($fh);
  my($contents) = "";
  if(open($fh, $file)) {
    $/ = undef;
    $contents = <$fh>;
    close($fh);
  } else {
    print "Couldn't open file " . $file . "!\n";
  }
  return $contents;
}

sub write_file {
  my($file, $contents) = @_;
  my($fh);

  if(open($fh, ">", $file)) {
    print $fh $contents;
    close($fh);
    return 1;
  } else {
    print "Couldn't open file " . $file . "!\n";
    return 0;
  }
}

sub get_pcc_field {
  my($field) = @_;
  my($file) = $config->{'pcc_path'} . "/" . $power_state . "_" . $field;

  return read_file($file);
}

sub set_pcc_field {
  my($field, $contents) = @_;
  my($file) = $config->{'pcc_path'} . "/" . $power_state . "_" . $field;

  if(!write_file($file, $contents)) {
    print "Couldn't set pcc " . $field . " field (are you root?)\n";
    return 0;
  }
  return 1;
}

sub ac_disconnect {
  $power_state = "dc";
  set_pcc_field("brightness", get_pcc_field("brightness"));
}

sub ac_connect {
  $power_state = "ac";
  set_pcc_field("brightness", get_pcc_field("brightness"));
}

my($key) = $ARGV[3];

my(%dispatch) = (
	     "00000000" => \&ac_disconnect,
	     "00000001" => \&ac_connect,
	    );

$config = {
	       "pcc_path" => "/proc/acpi/pcc",
	      };

$dispatch{$key}();

[-- Attachment #4: ac_adapter --]
[-- Type: text/plain, Size: 137 bytes --]

# /etc/acpi/events/hotkey
# This script handles hotkey events on Panasonic notebooks

event=ac_adapter.*
action=/etc/acpi/ac_adapt.pl %e

[-- Attachment #5: hotkey --]
[-- Type: text/plain, Size: 129 bytes --]

# /etc/acpi/events/hotkey
# This script handles hotkey events on Panasonic notebooks

event=HKEY.*
action=/etc/acpi/hotkey.pl %e

[-- Attachment #6: hotkey.pl --]
[-- Type: text/x-perl, Size: 6477 bytes --]

#!/usr/bin/perl -w
# Hotkey handler v1.0
# Handles hotkey events for Panasonic notebooks
#
# Copyright (C) 2004 David Bronaugh
#
# This program is free software; you can redistribute it and/or modify 
# it under the terms of the GNU General Public License version 2 as 
# published by the Free Software Foundation
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

use strict;
use POSIX qw(ceil floor);

our($config);
our($power_state);

sub read_file {
  my($file) = @_;
  my($fh);
  my($contents) = "";
  if(open($fh, $file)) {
    $/ = undef;
    $contents = <$fh>;
    close($fh);
  } else {
    print "Couldn't open file " . $file . "!\n";
  }
  return $contents;
}

sub write_file {
  my($file, $contents) = @_;
  my($fh);

  if(open($fh, ">", $file)) {
    print $fh $contents;
    close($fh);
    return 1;
  } else {
    print "Couldn't open file " . $file . "!\n";
    return 0;
  }
}

sub get_amixer_control_info {
  my($control) = @_;
  my($cmd) = $config->{'mixer_program'} . " cget name='" . $control . "'";
  my(%info);
  my($fh, $field);
  my($contents) = "";
  if(open($fh, $cmd . "|")) {
    while(<$fh>) {
      chomp;
      $contents .= $_;
    }
  } else {
    print "Couldn't run command " . $cmd . "!\n";
  }

  $contents =~ m/\; ([^\s]*)/;

  foreach(split(/,/, $+)) {
    my(@foo) = split(/=/, $_);
    $info{$foo[0]} = $foo[1];
  }

  $contents =~ m/\: ([^\s]*)/;
  my(@foo) = split(/=/, $+);
  $info{$foo[0]} = [];
  @{$info{$foo[0]}} = split(/,/, $foo[1]);

  return \%info;
}

sub set_amixer_control_info {
  my($control, $values) = @_;
  my($cmd) = $config->{'mixer_program'} . " -q cset name='" . $control . "' " . $values;

  if(system($cmd) == 0) {
    return 1;
  } else {
    return 0;
  }
}

sub get_pcc_field {
  my($field) = @_;
  my($file) = $config->{'pcc_path'} . "/" . $power_state . "_" . $field;

  return read_file($file);
}

sub set_pcc_field {
  my($field, $contents) = @_;
  my($file) = $config->{'pcc_path'} . "/" . $power_state . "_" . $field;

  if(!write_file($file, $contents)) {
    print "Couldn't set pcc " . $field . " field (are you root?)\n";
    return 0;
  }
  return 1;
}

sub get_brightness {
  return (get_pcc_field("brightness_min"), get_pcc_field("brightness_max"), get_pcc_field("brightness"));
}

sub set_brightness {
  my($value) = @_;
  return set_pcc_field("brightness", $value);
}

sub get_mute {
  my($info) = get_amixer_control_info($config->{'mute_switch'});

  if($info->{'values'}[0] eq "on") {
    return 0;
  } elsif($info->{'values'}[0] eq "off") {
    return 1;
  } else {
    print "Error getting mute status!\n";
    return -1;
  }
}

sub set_mute {
  my($value) = @_;
  if($value == 0) {
    $value = "on";
  } elsif($value == 1) {
    $value = "off";
  }

  if(set_amixer_control_info($config->{'mute_switch'}, $value)) {
    return 1;
  } else {
    print "Couldn't set mute status!\n";
    return 0;
  }
}

sub get_volume {
  my($config) = @_;
  my($info) = get_amixer_control_info($config->{'volume_ctl'});

  return ($info->{'min'}, $info->{'max'}, $info->{'values'});
}

sub set_volume {
  my($values) = @_;

  return set_amixer_control_info($config->{'volume_ctl'}, join(",", @{$values}));
}

sub get_power_state {
  my($data) = read_file($config->{"ac_state"});

  if($data =~ /on-line/) {
    return "ac";
  } elsif($data =~ /off-line/) {
    return "dc";
  } else {
    print "Couldn't get power state! (is ACPI enabled?)\n";
    exit(1);
  }
}

sub adjust_brightness { 
  my($adjust) = @_;
  my($min, $max, $bright) = get_brightness($config);
  my($threshold) = $config->{'max_bright_levels'};
  my($divisor) = 1;

  $bright -= $min;

  if($max - $min > $threshold) {
    $divisor = ($max - $min) / $threshold;
  }

  $bright = ceil($bright / $divisor);
  $bright += $adjust;
  $bright = floor($bright * $divisor);

  $bright += $min;

  if($bright < $min) {
    $bright = $min;
  }

  if($bright > $max) {
    $bright = $max;
  }

  if(!set_brightness($bright)) {
    print "Couldn't adjust brightness!\n";
  }

  return;
}

sub adjust_volume {
  my($increment) = @_;
  my($min, $max, $volume) = get_volume($config);

  $volume->[0] += $increment;
  $volume->[1] += $increment;

  $volume->[0] = ($volume->[0] < $min)?$min:$volume->[0];
  $volume->[1] = ($volume->[1] < $min)?$min:$volume->[1];
  $volume->[0] = ($volume->[0] > $max)?$max:$volume->[0];
  $volume->[1] = ($volume->[1] > $max)?$max:$volume->[1];

  if(!set_volume($volume)) {
    print "Couldn't set volume!\n";
  }

  return;
}

# Functions which implement hotkey functions directly
sub down_brightness {
  adjust_brightness(-1);
}

sub up_brightness {
  adjust_brightness(1);
}

sub switch_monitor {
  #STUB
}

sub toggle_mute {
  my($mute) = get_mute();

  if($mute >= 0) {
    set_mute($mute ^ 1);
  }
}

sub volume_up {
  adjust_volume($config->{"volume_increment"})
}

sub volume_down {
  adjust_volume(-1 * $config->{"volume_increment"})
}

sub suspend_to_ram {
  # This space intentionally left blank (because it doesn't work here)
}

sub spin_down_hd {
  if(system("hdparm -q -y /dev/hda") != 0) {
    print "Error running hdparm -- is it installed?\n";
  }
}

sub suspend_to_disk {
  system("hwclock --systohc");
  write_file($config->{'suspend_control'}, "disk");
  system("hwclock --hctosys");
}

my($key) = $ARGV[3];

my(%dispatch) = (
	     "00000081" => \&down_brightness,
	     "00000082" => \&up_brightness,
	     "00000003" => \&switch_monitor,
	     "00000084" => \&toggle_mute,
	     "00000085" => \&volume_down,
	     "00000086" => \&volume_up,
	     "00000007" => \&suspend_to_ram,
	     "00000089" => \&spin_down_hd,
	     "0000000a" => \&suspend_to_disk
	    );

$config = {
	       "pcc_path" => "/proc/acpi/pcc",
	       "mixer_program" => "amixer",
	       "ac_state" => "/proc/acpi/ac_adapter/AC/state",
	       "mute_switch" => "Master Playback Switch",
	       "volume_ctl" => "Master Playback Volume",
	       "max_bright_levels" => 20,
	       "volume_increment" => 2,
	       "suspend_control" => "/sys/power/state"
	      };

$power_state = get_power_state();

$dispatch{$key}();

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH]Panasonic Hotkey Driver v0.5 [2/2]
       [not found]         ` <87u0uyqqa7.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
  2004-08-20  7:44           ` David Bronaugh
@ 2004-08-24 23:00           ` John Belmonte
  1 sibling, 0 replies; 27+ messages in thread
From: John Belmonte @ 2004-08-24 23:00 UTC (permalink / raw)
  To: Hiroshi Miura; +Cc: acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

Hiroshi Miura wrote:
>  /*
> - *  Panasonic HotKey control Extra driver
> - *  (C) 2004 Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
> - *  (C) 2004 NTT DATA Intellilink Co. http://www.intellilink.co.jp/
> - *  All Rights Reserved
> + *  Panasonic HotKey and lcd brightness control Extra driver
> + *  Written by Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>  2004
> + *
> + *  Copyright (C) 2002-2004 John Belmonte

...

> - *  TODO
> - *	everything all
> + *		- v0.1  start from toshiba_acpi driver written by John Belmonte
>   *
>   */

Thank you for attending to this.  It doesn't seem quite right however, 
since you've removed your own copyright.  Here is what I recommend:

   /*
    *  Panasonic HotKey control Extra driver
    *  (C) 2004 Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
    *  (C) 2004 NTT DATA Intellilink Co. http://www.intellilink.co.jp/
    *
    *  derived from toshiba_acpi.c, Copyright (C) 2002-2004 John Belmonte
    *
    * ...


Regards,
-John


-- 
http://giftfile.org/  ::  giftfile project


-------------------------------------------------------
SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media
100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33
Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift.
http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH]Panasonic Hotkey Driver v0.6.3
       [not found]                             ` <41297BA7.3050503-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
@ 2004-08-26  8:45                               ` Hiroshi Miura
       [not found]                                 ` <87pt5e5lu3.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
  0 siblings, 1 reply; 27+ messages in thread
From: Hiroshi Miura @ 2004-08-26  8:45 UTC (permalink / raw)
  To: David Bronaugh
  Cc: acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	letsnote-tech-eXqGM+LsbTTAqL8d+zIrHngSJqDPrsil

[-- Attachment #1: Type: text/plain, Size: 351 bytes --]

Hi,

Bugfix:
v0.6.2 cannot generate hotkey event because pcc_acpi_get_key() does not
return proper value. And it is not handle return value of acpi_bus_register_driver(), too.

Cleanup:
ACPI subsystem has funcion 'acpi_evaluate_integer',
I can replase read_acpi_int by it.

These patchs fix these problems.

# these are generated by bkexport script.


[-- Attachment #2: pcc_acpi_20040826_1.patch --]
[-- Type: application/octet-stream, Size: 3482 bytes --]

#### AUTHOR miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org
#### COMMENT START
### Comments for ChangeSet
[ACPI] pcc_acpi: clean up. replace read_acpi_int to standard acpi_evaluate_interger.
### Comments for drivers/acpi/pcc_acpi.c
replace read_acpi_int to standard acpi_evaluate_interger.
#### COMMENT END

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/08/25 21:16:52+09:00 miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org 
#   [ACPI] pcc_acpi: clean up. replace read_acpi_int to standard acpi_evaluate_interger.
# 
# drivers/acpi/pcc_acpi.c
#   2004/08/25 21:16:32+09:00 miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org +17 -39
#   replace read_acpi_int to standard acpi_evaluate_interger.
# 
diff -Nru a/drivers/acpi/pcc_acpi.c b/drivers/acpi/pcc_acpi.c
--- a/drivers/acpi/pcc_acpi.c	2004-08-26 17:23:24 +09:00
+++ b/drivers/acpi/pcc_acpi.c	2004-08-26 17:23:24 +09:00
@@ -52,7 +52,7 @@
  *
  */
 
-#define ACPI_PCC_VERSION	"0.6.2"
+#define ACPI_PCC_VERSION	"0.6.3"
 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -155,32 +155,6 @@
 	return_VALUE(status == AE_OK);
 }
 
-static int read_acpi_int(acpi_handle handle, const char* methodName, int* pVal)
-{
-	struct acpi_buffer results;
-	union acpi_object out_objs[1];
-	acpi_status status;
-
-	results.length = sizeof(out_objs);
-	results.pointer = out_objs;
-
-	status = acpi_evaluate_object(handle, (char*)methodName, 0, &results);
-	if (ACPI_FAILURE(status)) {
-		printk(KERN_INFO LOGPREFIX "acpi evaluate error on %s\n", 
-		       methodName);
-		return -EFAULT;
-	}
-
-	if (out_objs[0].type == ACPI_TYPE_INTEGER) {
-		*pVal = out_objs[0].integer.value;
-	} else {
-		printk(KERN_INFO LOGPREFIX "return value is not int\n");
-		status = AE_ERROR;
-	}
-
-	return (status == AE_OK);
-}
-
 /* register utils for proc handler */
 static int dispatch_read(char* page, char** start, off_t off, int count, 
 			 int* eof, ProcItem* item)
@@ -238,18 +212,20 @@
 	return result;
 }
 
-static inline int acpi_pcc_get_sqty(void) 
+static inline int acpi_pcc_get_sqty(struct acpi_device *device) 
 {
-	int s;
+	unsigned long s;
+	acpi_status status;
 
 	ACPI_FUNCTION_TRACE("acpi_pcc_get_sqty");
 
-	if (read_acpi_int(NULL, DEVICE_NAME_HKEY "." METHOD_HKEY_SQTY, &s)) {
-		return s;
+	status = acpi_evaluate_integer(device->handle,METHOD_HKEY_SQTY,NULL,&s);
+	if (ACPI_SUCCESS(status)) {
+		return_VALUE(s);
 	} else {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
 				  "evaluation error HKEY.SQTY\n"));
-		return -EINVAL;
+		return_VALUE(-EINVAL);
 	}
 }
 
@@ -439,17 +415,19 @@
 /* hotkey driver */
 static int acpi_pcc_hotkey_get_key(struct acpi_hotkey *hotkey)
 {
-	int result;
-	int status;
+	unsigned long result;
+	acpi_status status;
 
-	status = read_acpi_int(hotkey->handle, METHOD_HKEY_QUERY, &result);
-	if (status < 0) {
-		printk(KERN_INFO LOGPREFIX "error getting hotkey status\n");
+	ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_get_key");
+
+	status = acpi_evaluate_integer(hotkey->handle,METHOD_HKEY_QUERY,NULL,&result);
+	if (ACPI_FAILURE(status)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "error getting hotkey status\n"));
 	} else {
 		hotkey->status = result;
 	}
 
-	return (status);
+	return_VALUE(status);
 }
 
 void acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data)
@@ -559,7 +537,7 @@
 		return_VALUE(-EINVAL);
 	}
 
-	num_sifr = acpi_pcc_get_sqty();
+	num_sifr = acpi_pcc_get_sqty(device);
 	
 	if (num_sifr > 255) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "num_sifr too large"));

[-- Attachment #3: pcc_acpi_20040826_2.patch --]
[-- Type: application/octet-stream, Size: 5672 bytes --]

#### AUTHOR miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org
#### COMMENT START
### Comments for ChangeSet
[ACPI] pcc_acpi: fix to enable notifier and clean up.
### Comments for drivers/acpi/pcc_acpi.c
v0.6.3 replace read_acpi_int by standard function acpi_evaluate_integer
       some clean up and make smart copyright notice. 
       fix return value of pcc_acpi_get_key.
       fix checking return value of acpi_bus_register_driver()
#### COMMENT END

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/08/26 12:10:56+09:00 miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org 
#   [ACPI] pcc_acpi: fix to enable notifier and clean up.
# 
# drivers/acpi/pcc_acpi.c
#   2004/08/26 12:10:36+09:00 miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org +31 -18
#   v0.6.3 replace read_acpi_int by standard function acpi_evaluate_integer
#          some clean up and make smart copyright notice. 
#          fix return value of pcc_acpi_get_key.
#          fix checking return value of acpi_bus_register_driver()
# 
diff -Nru a/drivers/acpi/pcc_acpi.c b/drivers/acpi/pcc_acpi.c
--- a/drivers/acpi/pcc_acpi.c	2004-08-26 17:24:08 +09:00
+++ b/drivers/acpi/pcc_acpi.c	2004-08-26 17:24:08 +09:00
@@ -1,8 +1,9 @@
 /*
  *  Panasonic HotKey and lcd brightness control Extra driver
- *  Written by Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>  2004
+ *  (C) 2004 Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
+ *  (C) 2004 NTT DATA Intellilink Co. http://www.intellilink.co.jp/
  *
- *  Copyright (C) 2002-2004 John Belmonte
+ *  derived from toshiba_acpi.c, Copyright (C) 2002-2004 John Belmonte
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as 
@@ -20,6 +21,12 @@
  *---------------------------------------------------------------------------
  *
  * ChangeLog:
+ *	Aug.25, 2004	Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
+ *		-v0.6.3 replace read_acpi_int by standard function acpi_evaluate_integer
+ *			some clean up and make smart copyright notice.
+ *			fix return value of pcc_acpi_get_key()
+ *			fix checking return value of acpi_bus_register_driver() 
+ *
  *      Aug.22, 2004    David Bronaugh <dbronaugh-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
  *              -v0.6.2 Add check on ACPI data (num_sifr)
  *                      Coding style cleanups, better error messages/handling
@@ -92,7 +99,6 @@
  *
  *******************************************************************/
 #define PROC_PCC		"pcc"
-#define PROC_VIDEO "video"
 
 #define ACPI_PCC_DRIVER_NAME "PCC HotKey Driver"
 #define ACPI_HOTKEY_DEVICE_NAME "HotKey"
@@ -275,16 +281,18 @@
 {
 	u32* sinf = kmalloc(sizeof(u32) * (num_sifr + 1), GFP_KERNEL);
 
+	ACPI_FUNCTION_TRACE("acpi_pcc_read_sinf_field");
+
 	if (!sinf) {
-		printk(KERN_INFO LOGPREFIX "Couldn't allocate %i bytes\n", 
-		       sizeof(u32) * num_sifr);
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate %i bytes\n", 
+		       sizeof(u32) * num_sifr));
 		return p;
 	}
 
 	if (acpi_pcc_retrieve_biosdata(sinf)) {
 		p += sprintf(p, "%d\n",	sinf[field]);
 	} else {
-		printk(KERN_INFO LOGPREFIX "Couldn't retrieve BIOS data\n");
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't retrieve BIOS data\n"));
 	}
 
 	kfree(sinf);
@@ -362,19 +370,21 @@
 	u32 bright;
 	u32* sinf = kmalloc(sizeof(u32) * (num_sifr + 1), GFP_KERNEL);
 
+	ACPI_FUNCTION_TRACE("acpi_pcc_write_brightness");
+
 	if (!sinf) {
-		printk(KERN_INFO LOGPREFIX "Couldn't allocate %i bytes\n", 
-		       sizeof(u32) * num_sifr);
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate %i bytes\n", 
+		       sizeof(u32) * num_sifr));
 		return count;
 	}
 
 	if (!acpi_pcc_retrieve_biosdata(sinf)) {
-		printk(KERN_INFO LOGPREFIX "Couldn't retrieve BIOS data\n");
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't retrieve BIOS data\n"));
 		goto end;
 	}
 	
 	if (!sscanf(buffer, "%i", &bright)) {
-		printk(KERN_INFO LOGPREFIX "Invalid DC brightness\n");
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid DC brightness\n"));
 		goto end;
 	}
 
@@ -416,7 +426,7 @@
 static int acpi_pcc_hotkey_get_key(struct acpi_hotkey *hotkey)
 {
 	unsigned long result;
-	acpi_status status;
+	acpi_status status = AE_OK;
 
 	ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_get_key");
 
@@ -427,7 +437,7 @@
 		hotkey->status = result;
 	}
 
-	return_VALUE(status);
+	return_VALUE(status == AE_OK);
 }
 
 void acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data)
@@ -498,21 +508,24 @@
 static int __init acpi_pcc_proc_init(void)
 {
 	acpi_status status = AE_OK;
+
+	ACPI_FUNCTION_TRACE("acpi_pcc_proc_init");
+
 	acpi_pcc_dir = proc_mkdir(PROC_PCC, acpi_root_dir);
 
 	if (unlikely(!acpi_pcc_dir)) {
-		printk(KERN_INFO LOGPREFIX "Couldn't create dir in /proc\n");
-		return -ENODEV;
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't create dir in /proc\n"));
+		return_VALUE(-ENODEV);
 	}
 
 	acpi_pcc_dir->owner = THIS_MODULE;
 	status = add_device(pcc_proc_items, acpi_pcc_dir);
 	if (ACPI_FAILURE(status)) {
 		remove_proc_entry(PROC_PCC, acpi_root_dir);
-		return -ENODEV;
+		return_VALUE(-ENODEV);
 	}
 
-	return (status == AE_OK);
+	return_VALUE(status == AE_OK);
 }
 
 static acpi_status __exit remove_device(ProcItem *proc_items, 
@@ -604,7 +617,7 @@
 
 static int __init acpi_pcc_init(void)
 {
-	acpi_status result = AE_OK;
+	int result = 0;
  
 	ACPI_FUNCTION_TRACE("acpi_pcc_init");
 
@@ -613,7 +626,7 @@
 	}
 
 	result = acpi_bus_register_driver(&acpi_hotkey_driver);
-	if (ACPI_FAILURE(result)) {
+	if (result < 0) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error registering hotkey driver\n"));
 		return_VALUE(-ENODEV);
 	}

[-- Attachment #4: Type: text/plain, Size: 376 bytes --]

-- 
Hiroshi Miura  --- http://www.da-cha.org/  --- miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org
NTTDATA Corp. OpenSource Software Center. --- miurahr-3MafRgGXt7BL9jVzuh4AOg@public.gmane.org 
NTTDATA Intellilink Corp. OpenSource Engineering Dev. -- miurahr-w0OK63jvRlAuJ+9fw/WgBHgSJqDPrsil@public.gmane.org
Key fingerprint = 9117 9407 5684 FBF1 4063  15B4 401D D077 04AB 8617

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH]Panasonic Hotkey Driver v0.7
       [not found]                                 ` <87pt5e5lu3.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
@ 2004-09-15  0:42                                   ` Hiroshi Miura
  0 siblings, 0 replies; 27+ messages in thread
From: Hiroshi Miura @ 2004-09-15  0:42 UTC (permalink / raw)
  To: David Bronaugh, acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
  Cc: letsnote-tech-eXqGM+LsbTTAqL8d+zIrHngSJqDPrsil, Hiroshi Miura,
	Ryuta NAKANISHI

[-- Attachment #1: Type: text/plain, Size: 1694 bytes --]

Hi, 

I'm update panasonic hotkey driver to follow the discussion about
common hotkey driver.
I correct a driver name of acpi event message from 'HKEY' to 'pcc'.
now it generate event like 'pcc HKEY 00000080 00000001'.

I also update it to enlarge mentainanceability.
I use seq_file in-kernel functions to implement proc interface as same as 
standard methods (button/ec/ac/battery).

I'm also fix bugs and update hotkey-handler originally written by David Bronaugh.
On my debian platform, original hotkey-handler don't work because of message from 
acpid is quoted by '"'. It makes bios version check and select proper method to
'mute'. It also detect swsusp version whether vanilla one, Nigel's swsusp2(before ver 2.0.0.103)
or Nigel's swsusp2(after ver 2.0.0.104).

Patch generated by bkexport and new version of hotkey-handler is attatched.
It is against v0.6.4.

You can download whole and incremental patches from http://www.da-cha.org/letsnote/


future plan: 
1. generate both keyboard input and acpid event as configurable.
  Pavel>If those are keys, you should just treat them as keys... 
  Pavel>That is hook it into input subsystem.

  This is already implemented in yet another panasonic hotkey driver
  written by Ryuta Nakanishi. I want to merge his code.

2. gui. It may be made by other volunteers.

-- 
Hiroshi Miura  --- http://www.da-cha.org/  --- miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org
NTTDATA Corp. OpenSource Software Center. --- miurahr-3MafRgGXt7BL9jVzuh4AOg@public.gmane.org 
NTTDATA Intellilink Corp. OpenSource Engineering Dev. -- miurahr-w0OK63jvRlAuJ+9fw/WgBHgSJqDPrsil@public.gmane.org
Key fingerprint = 9117 9407 5684 FBF1 4063  15B4 401D D077 04AB 8617


[-- Attachment #2: pcc-acpi-0.7.patch --]
[-- Type: application/octet-stream, Size: 25528 bytes --]

#### AUTHOR miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org
#### COMMENT START
### Comments for ChangeSet
[ACPI] pcc_acpi: rewrite pcc_acpi driver proc functions.
  change event driver name from HKEY to pcc.
### Comments for drivers/acpi/pcc_acpi.c
Change proc interface functions and relative functions using seq_file 
facisity as same as other acpi drivers.
Change hotkey event message as  'pcc HKEY 0000080 00000001'
These changes are to prepare share code.
#### COMMENT END

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/09/14 02:20:14+09:00 miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org 
#   [ACPI] pcc_acpi: rewrite pcc_acpi driver proc functions.
#     change event driver name from HKEY to pcc.
# 
# drivers/acpi/pcc_acpi.c
#   2004/09/14 02:19:55+09:00 miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org +299 -182
#   Change proc interface functions and relative functions using seq_file 
#   facisity as same as other acpi drivers.
#   Change hotkey event message as  'pcc HKEY 0000080 00000001'
#   These changes are to prepare share code.
# 
diff -Nru a/drivers/acpi/pcc_acpi.c b/drivers/acpi/pcc_acpi.c
--- a/drivers/acpi/pcc_acpi.c	2004-09-14 02:21:10 +09:00
+++ b/drivers/acpi/pcc_acpi.c	2004-09-14 02:21:10 +09:00
@@ -21,6 +21,10 @@
  *---------------------------------------------------------------------------
  *
  * ChangeLog:
+ *	Sep.10, 2004	Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
+ *		-v0.7	Change proc interface functions using seq_file
+ *			fasility as same as other ACPI drivers.
+ *
  *	Aug.28, 2004	Hiroshi Miura <miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
  *		-v0.6.4 Fix a silly error with status checking
  *
@@ -62,15 +66,16 @@
  *
  */
 
-#define ACPI_PCC_VERSION	"0.6.3"
+#define ACPI_PCC_VERSION	"0.7"
 
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <linux/seq_file.h>
 #include <asm/uaccess.h>
-
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
@@ -103,9 +108,9 @@
  *******************************************************************/
 #define PROC_PCC		"pcc"
 
-#define ACPI_PCC_DRIVER_NAME "PCC HotKey Driver"
-#define ACPI_HOTKEY_DEVICE_NAME "HotKey"
-#define ACPI_HOTKEY_CLASS "HKEY"
+#define ACPI_PCC_DRIVER_NAME "PCC Extra Driver"
+#define ACPI_PCC_DEVICE_NAME "PCCExtra"
+#define ACPI_PCC_CLASS "pcc"
 
 /* LCD_TYPEs: 0 = Normal, 1 = Semi-transparent
    ENV_STATEs: Normal temp=0x01, High temp=0x81, N/A=0x00 
@@ -119,9 +124,9 @@
 static int acpi_pcc_hotkey_add (struct acpi_device *device);
 static int acpi_pcc_hotkey_remove (struct acpi_device *device, int type);
 
-static struct acpi_driver acpi_hotkey_driver = {
+static struct acpi_driver acpi_pcc_driver = {
 	.name =		ACPI_PCC_DRIVER_NAME,
-	.class =	ACPI_HOTKEY_CLASS,
+	.class =	ACPI_PCC_CLASS,
 	.ids =		HKEY_HID,
 	.ops =		{
 				.add =		acpi_pcc_hotkey_add,
@@ -132,78 +137,97 @@
 struct acpi_hotkey {
 	acpi_handle		handle;
 	struct acpi_device	*device;
+	struct proc_dir_entry   *proc_dir_entry;
 	unsigned long		num_sifr;
 	unsigned long		status;
 };
 
-typedef struct _ProcItem
-{
-	const char* name;
-	char* (*read_func)(char*, struct acpi_hotkey*);
-	unsigned long (*write_func)(const char*, unsigned long, struct acpi_hotkey*);
-	struct acpi_hotkey *hotkey;
-} ProcItem;
-
-static struct proc_dir_entry* acpi_pcc_dir;
-
-/* register utils for proc handler */
-static int dispatch_read(char* page, char** start, off_t off, int count, 
-			 int* eof, ProcItem* item)
-{
-	char* p = page;
-	int len;
-
-	if (off == 0 && item->read_func) {
-		p = item->read_func(p, item->hotkey);
-	}
-
-	/* ISSUE: I don't understand this code */
-	len = (p - page);
-	if (len <= off+count) {
-		*eof = 1;
-	}
-	*start = page + off;
-	len -= off;
-	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)
-{
-	int result;
-	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) {
-		printk(KERN_INFO LOGPREFIX "dispatch_write: Couldn't allocate buffer");
-		return -EFAULT;
-	}
-
-	if (copy_from_user(tmp_buffer, buffer, count)) {
-		printk(KERN_INFO LOGPREFIX "dispatch_write: Couldn't copy data from userspace");
-		result = -EFAULT;
-		goto end;
-	}
+/* --------------------------------------------------------------------------
+                              FS Interface (/proc)
+   -------------------------------------------------------------------------- */
+static int acpi_pcc_version_open_fs(struct inode*,struct file*);
+static int acpi_pcc_numbatteries_open_fs(struct inode*,struct file*);
+static int acpi_pcc_lcdtype_open_fs(struct inode*,struct file*);
+static int acpi_pcc_mute_open_fs(struct inode*,struct file*);
+static int acpi_pcc_ac_brightness_max_open_fs(struct inode*,struct file*);
+static int acpi_pcc_ac_brightness_min_open_fs(struct inode*,struct file*);
+static int acpi_pcc_dc_brightness_max_open_fs(struct inode*,struct file*);
+static int acpi_pcc_dc_brightness_min_open_fs(struct inode*,struct file*);
+static int acpi_pcc_ac_brightness_open_fs(struct inode*,struct file*);
+static int acpi_pcc_dc_brightness_open_fs(struct inode*,struct file*);
+static ssize_t acpi_pcc_write_mute (struct file*,const char __user *,size_t,loff_t *);
+static ssize_t acpi_pcc_write_ac_brightness (struct file*,const char __user *,size_t,loff_t *);
+static ssize_t acpi_pcc_write_dc_brightness (struct file*,const char __user *,size_t,loff_t *);
+
+static struct file_operations acpi_pcc_version_fops = {
+	.open		= acpi_pcc_version_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
 
-	tmp_buffer[count] = 0;
-	result = item->write_func(tmp_buffer, count, item->hotkey);
-		
-end:
-	kfree(tmp_buffer);
-	return result;
-}
+static struct file_operations acpi_pcc_numbatteries_fops = {
+	.open		= acpi_pcc_numbatteries_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+static struct file_operations acpi_pcc_lcdtype_fops = {
+	.open		= acpi_pcc_lcdtype_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+static struct file_operations acpi_pcc_mute_fops = {
+	.open		= acpi_pcc_mute_open_fs,
+	.read		= seq_read,
+	.write		= acpi_pcc_write_mute,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+static struct file_operations acpi_pcc_ac_brightness_fops = {
+	.open		= acpi_pcc_ac_brightness_open_fs,
+	.read		= seq_read,
+	.write		= acpi_pcc_write_ac_brightness,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+static struct file_operations acpi_pcc_ac_brightness_max_fops = {
+	.open		= acpi_pcc_ac_brightness_max_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+static struct file_operations acpi_pcc_ac_brightness_min_fops = {
+	.open		= acpi_pcc_ac_brightness_min_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+static struct file_operations acpi_pcc_dc_brightness_fops = {
+	.open		= acpi_pcc_dc_brightness_open_fs,
+	.read		= seq_read,
+	.write		= acpi_pcc_write_dc_brightness,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+static struct file_operations acpi_pcc_dc_brightness_max_fops = {
+	.open		= acpi_pcc_dc_brightness_max_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+static struct file_operations acpi_pcc_dc_brightness_min_fops = {
+	.open		= acpi_pcc_dc_brightness_min_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
 
-static int write_sset(int func, int val, struct acpi_hotkey *hotkey)
+/* --------------------------------------------------------------------------
+                           method access functions
+   -------------------------------------------------------------------------- */
+static int acpi_pcc_write_sset(int func, int val, struct acpi_hotkey *hotkey)
 {
 	struct acpi_object_list params;
 	union acpi_object in_objs[2];
@@ -249,7 +273,7 @@
 
 	ACPI_FUNCTION_TRACE("acpi_pcc_retrieve_biosdata");
 
-	status = acpi_evaluate_object(hotkey->handle,METHOD_HKEY_SINF, 0 , &buffer);
+	status = acpi_evaluate_object(hotkey->handle, METHOD_HKEY_SINF, 0 , &buffer);
 	if (ACPI_FAILURE(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "evaluation error HKEY.SINF\n"));
 		return_VALUE(0);
@@ -282,8 +306,9 @@
 	return_VALUE(status == AE_OK);
 }
 
-static char* acpi_pcc_read_sinf_field(char* p, int field, struct acpi_hotkey *hotkey) 
+static int acpi_pcc_read_sinf_field(struct seq_file *seq, int field)
 {
+	struct acpi_hotkey *hotkey = (struct acpi_hotkey *) seq->private;
 	u32* sinf = kmalloc(sizeof(u32) * (hotkey->num_sifr + 1), GFP_KERNEL);
 
 	ACPI_FUNCTION_TRACE("acpi_pcc_read_sinf_field");
@@ -291,145 +316,223 @@
 	if (!sinf) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate %li bytes\n", 
 		       sizeof(u32) * hotkey->num_sifr));
-		return p;
+		return_VALUE(0);
 	}
 
 	if (acpi_pcc_retrieve_biosdata(sinf, hotkey)) {
-		p += sprintf(p, "%u\n",	sinf[field]);
+		seq_printf(seq, "%u\n",	sinf[field]);
 	} else {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't retrieve BIOS data\n"));
 	}
 
 	kfree(sinf);
-	return p;
+	return_VALUE(0);
 }
 
-/* Sinf read methods */
-static char* acpi_pcc_read_num_batteries(char* p, struct acpi_hotkey *hotkey) 
-{
-	return acpi_pcc_read_sinf_field(p, SINF_NUM_BATTERIES, hotkey);
-}
 
-static char* acpi_pcc_read_lcd_type(char* p, struct acpi_hotkey *hotkey) 
+/* --------------------------------------------------------------------------
+                       user interface functions
+   -------------------------------------------------------------------------- */
+
+/* Sinf read methods */
+static int acpi_pcc_numbatteries_show(struct seq_file *seq, void *offset)
 {
-	return acpi_pcc_read_sinf_field(p, SINF_LCD_TYPE, hotkey);
+	return acpi_pcc_read_sinf_field(seq, SINF_NUM_BATTERIES);
 }
 
-static char* acpi_pcc_read_ac_max_brightness(char* p, struct acpi_hotkey *hotkey) 
+static int acpi_pcc_lcdtype_show(struct seq_file *seq, void *offset)
 {
-	return acpi_pcc_read_sinf_field(p, SINF_AC_MAX_BRIGHT, hotkey);
+	return acpi_pcc_read_sinf_field(seq, SINF_LCD_TYPE);
 }
 
-static char* acpi_pcc_read_ac_min_brightness(char* p, struct acpi_hotkey *hotkey) 
+static int acpi_pcc_ac_max_brightness_show(struct seq_file *seq, void *offset)
 {
-	return acpi_pcc_read_sinf_field(p, SINF_AC_MIN_BRIGHT, hotkey);
+	return acpi_pcc_read_sinf_field(seq, SINF_AC_MAX_BRIGHT);
 }
 
-static char* acpi_pcc_read_ac_brightness(char* p, struct acpi_hotkey *hotkey) 
+static int acpi_pcc_ac_min_brightness_show(struct seq_file *seq, void *offset)
 {
-	return acpi_pcc_read_sinf_field(p, SINF_AC_CUR_BRIGHT, hotkey);
+	return acpi_pcc_read_sinf_field(seq, SINF_AC_MIN_BRIGHT);
 }
 
-static char* acpi_pcc_read_dc_max_brightness(char* p, struct acpi_hotkey *hotkey) 
+static int acpi_pcc_ac_brightness_show(struct seq_file *seq, void *offset)
 {
-	return acpi_pcc_read_sinf_field(p, SINF_DC_MAX_BRIGHT, hotkey);
+	return acpi_pcc_read_sinf_field(seq, SINF_AC_CUR_BRIGHT);
 }
 
-static char* acpi_pcc_read_dc_min_brightness(char* p, struct acpi_hotkey *hotkey) 
+static int acpi_pcc_dc_max_brightness_show(struct seq_file *seq, void *offset)
 {
-	return acpi_pcc_read_sinf_field(p, SINF_DC_MIN_BRIGHT, hotkey);
+	return acpi_pcc_read_sinf_field(seq, SINF_DC_MAX_BRIGHT);
 }
 
-static char* acpi_pcc_read_dc_brightness(char* p, struct acpi_hotkey *hotkey) 
+static int acpi_pcc_dc_min_brightness_show(struct seq_file *seq, void *offset)
 {
-	return acpi_pcc_read_sinf_field(p, SINF_DC_CUR_BRIGHT, hotkey);
+	return acpi_pcc_read_sinf_field(seq, SINF_DC_MIN_BRIGHT);
 }
 
-static char* acpi_pcc_read_mute(char* p, struct acpi_hotkey *hotkey) 
+static int acpi_pcc_dc_brightness_show(struct seq_file *seq, void *offset)
 {
-	return acpi_pcc_read_sinf_field(p, SINF_MUTE, hotkey);
+	return acpi_pcc_read_sinf_field(seq, SINF_DC_CUR_BRIGHT);
 }
 
-static char* acpi_pcc_read_env_state(char* p, struct acpi_hotkey *hotkey) 
+static int acpi_pcc_mute_show(struct seq_file *seq, void *offset)
 {
-	return acpi_pcc_read_sinf_field(p, SINF_ENV_STATE, hotkey);
+	return acpi_pcc_read_sinf_field(seq, SINF_MUTE);
 }
 
-static unsigned long acpi_pcc_write_mute(const char* buffer, 
-					 unsigned long count, struct acpi_hotkey *hotkey)
+/* write methods */
+static ssize_t acpi_pcc_write_mute (struct file *file,	const char __user *buffer,
+		     size_t count, loff_t *ppos)
 {
-	u32 value;
+	struct seq_file		*seq = (struct seq_file *)file->private_data;
+	struct acpi_hotkey	*hotkey = (struct acpi_hotkey *)seq->private;
+	char			write_string[4]= {'\0'};
+	u32 mute;
 
 	ACPI_FUNCTION_TRACE("acpi_pcc_write_mute");
 
-	if (sscanf(buffer, "%i", &value) == 1 && value >= 0 && value <= 1) {
-		write_sset(SINF_MUTE, value, hotkey);
+	if (!hotkey || (count > sizeof(write_string) - 1))
+		return_VALUE(-EINVAL);
+
+	if (copy_from_user(write_string, buffer, count))
+		return_VALUE(-EFAULT);
+	write_string[count] = '\0';
+
+	if (sscanf(write_string, "%i", &mute) == 1 && (mute == 0 || mute == 1)) {
+		acpi_pcc_write_sset(SINF_MUTE, mute, hotkey);
 	}
 
-	return count;
+	return_VALUE(count);
 }
 
-static unsigned long acpi_pcc_write_brightness(const char* buffer,
-					       unsigned long count,
+static unsigned long acpi_pcc_write_brightness(struct file *file, const char __user *buffer,
+					       size_t count,
 					       int min_index, int max_index,
-					       int cur_index, struct acpi_hotkey *hotkey)
+					       int cur_index)
 {
+	struct seq_file		*seq = (struct seq_file *)file->private_data;
+	struct acpi_hotkey	*hotkey = (struct acpi_hotkey *)seq->private;
+	char			write_string[8] = {'\0'};
 	u32 bright;
 	u32* sinf = kmalloc(sizeof(u32) * (hotkey->num_sifr + 1), GFP_KERNEL);
 
 	ACPI_FUNCTION_TRACE("acpi_pcc_write_brightness");
 
+	if (!hotkey || (count > sizeof(write_string) - 1))
+		return_VALUE(-EINVAL);
+
 	if (!sinf) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate %li bytes\n", 
 		       sizeof(u32) * hotkey->num_sifr));
-		return count;
+		return_VALUE(-EFAULT);
 	}
 
+	if (copy_from_user(write_string, buffer, count))
+		return_VALUE(-EFAULT);
+	
+	write_string[count] = '\0';
+
 	if (!acpi_pcc_retrieve_biosdata(sinf, hotkey)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't retrieve BIOS data\n"));
 		goto end;
 	}
-	
-	if (!sscanf(buffer, "%i", &bright)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid DC brightness\n"));
-		goto end;
-	}
 
-	if (bright >= sinf[min_index] && bright <= sinf[max_index]) {
-		write_sset(cur_index, bright, hotkey);
+	if (sscanf(write_string, "%i", &bright) == 1 && 
+		bright >= sinf[min_index] && bright <= sinf[max_index]) {
+			acpi_pcc_write_sset(cur_index, bright, hotkey);
 	}
 
 end: 
 	kfree(sinf);
-	return count;
+	return_VALUE(count);
 }
 
-
-static unsigned long acpi_pcc_write_ac_brightness(const char* buffer, 
-						  unsigned long count, struct acpi_hotkey *hotkey)
+static ssize_t acpi_pcc_write_ac_brightness(struct file *file, const char __user *buffer,
+					 size_t count, loff_t *ppos)
 {
-	return acpi_pcc_write_brightness(buffer, count, SINF_AC_MIN_BRIGHT, 
+	return acpi_pcc_write_brightness(file, buffer, count, SINF_AC_MIN_BRIGHT, 
 					 SINF_AC_MAX_BRIGHT, 
-					 SINF_AC_CUR_BRIGHT, hotkey);
+					 SINF_AC_CUR_BRIGHT);
 }
 
-static unsigned long acpi_pcc_write_dc_brightness(const char* buffer, 
-						  unsigned long count, struct acpi_hotkey *hotkey)
+static ssize_t acpi_pcc_write_dc_brightness(struct file *file, const char __user *buffer,
+					 size_t count, loff_t *ppos)
 {
-	return acpi_pcc_write_brightness(buffer, count, SINF_DC_MIN_BRIGHT, 
+	return acpi_pcc_write_brightness(file, buffer, count, SINF_DC_MIN_BRIGHT, 
 					 SINF_DC_MAX_BRIGHT, 
-					 SINF_DC_CUR_BRIGHT, hotkey);
+					 SINF_DC_CUR_BRIGHT);
+}
+
+static int acpi_pcc_version_show(struct seq_file *seq, void *offset)
+{
+	struct acpi_hotkey *hotkey = (struct acpi_hotkey *) seq->private;
+
+	ACPI_FUNCTION_TRACE("acpi_pcc_version_seq_show");
+
+	if (!hotkey || !hotkey->device)
+		return 0;
+
+	seq_printf(seq, "%s version %s\n", ACPI_PCC_DRIVER_NAME, ACPI_PCC_VERSION);
+	seq_printf(seq, "%li functions\n", hotkey->num_sifr);
+
+	return_VALUE(0);
+}
+
+/* oepn proc file fs*/
+static int acpi_pcc_dc_brightness_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_pcc_dc_brightness_show, PDE(inode)->data);
+}
+
+static int acpi_pcc_numbatteries_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_pcc_numbatteries_show, PDE(inode)->data);
+}
+
+static int acpi_pcc_lcdtype_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_pcc_lcdtype_show, PDE(inode)->data);
+}
+
+static int acpi_pcc_ac_brightness_max_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_pcc_ac_max_brightness_show, PDE(inode)->data);
+}
+
+static int acpi_pcc_ac_brightness_min_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_pcc_ac_min_brightness_show, PDE(inode)->data);
+}
+
+static int acpi_pcc_ac_brightness_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_pcc_ac_brightness_show, PDE(inode)->data);
+}
+
+static int acpi_pcc_dc_brightness_max_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_pcc_dc_max_brightness_show, PDE(inode)->data);
+}
+
+static int acpi_pcc_dc_brightness_min_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_pcc_dc_min_brightness_show, PDE(inode)->data);
+}
+
+static int acpi_pcc_mute_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_pcc_mute_show, PDE(inode)->data);
 }
 
-static char* acpi_pcc_read_version(char* p, struct acpi_hotkey *hotkey)
+static int acpi_pcc_version_open_fs(struct inode *inode, struct file *file)
 {
-	p += sprintf(p, "%s version %s\n", ACPI_PCC_DRIVER_NAME, 
-		     ACPI_PCC_VERSION);
-	p += sprintf(p, "%li functions\n", hotkey->num_sifr);
-	return p;
+	return single_open(file, acpi_pcc_version_show, PDE(inode)->data);
 }
 
-/* hotkey driver */
+/* --------------------------------------------------------------------------
+                            hotkey driver 
+   -------------------------------------------------------------------------- */
+
 static int acpi_pcc_hotkey_get_key(struct acpi_hotkey *hotkey)
 {
 	unsigned long result;
@@ -456,6 +559,7 @@
 	switch(event) {
 	case HKEY_NOTIFY:
 		if (acpi_pcc_hotkey_get_key(hotkey)) {
+			/* generate event like 'pcc HKEY 0004 0001' when Fn+F4 pressed */
 			acpi_bus_generate_event(hotkey->device, event, hotkey->status);
 		}
 		break;
@@ -463,54 +567,57 @@
 		/* nothing to do */
 		break;
 	}
-	return;
+	return_VOID;
 }
 
-/*
- * proc and module init
-*/
+/* --------------------------------------------------------------------------
+                         proc init
+   -------------------------------------------------------------------------- */
+
+typedef struct _ProcItem
+{
+	const char* name;
+	struct file_operations *fops;
+	mode_t flag;
+} ProcItem;
 
 /* Note: These functions map *exactly* to the SINF/SSET functions */
 ProcItem pcc_proc_items[] =
 {
-	{ "num_batteries", acpi_pcc_read_num_batteries, NULL, NULL },
-	{ "lcd_type", acpi_pcc_read_lcd_type, NULL, NULL },
-	{ "ac_brightness_max" , acpi_pcc_read_ac_max_brightness, NULL, NULL },
-	{ "ac_brightness_min" , acpi_pcc_read_ac_min_brightness, NULL, NULL },
-	{ "ac_brightness" , acpi_pcc_read_ac_brightness, 
-	  acpi_pcc_write_ac_brightness, NULL },
-	{ "dc_brightness_max" , acpi_pcc_read_dc_max_brightness, NULL, NULL },
-	{ "dc_brightness_min" , acpi_pcc_read_dc_min_brightness, NULL, NULL },
-	{ "dc_brightness" , acpi_pcc_read_dc_brightness, 
-	  acpi_pcc_write_dc_brightness, NULL },
-	{ "mute", acpi_pcc_read_mute, acpi_pcc_write_mute, NULL },
-	{ "version", acpi_pcc_read_version , NULL, NULL },
-	{ "environment_state", acpi_pcc_read_env_state, NULL, NULL },
-	{ NULL 	   , NULL	  , NULL, NULL },
+	{ "num_batteries",      &acpi_pcc_numbatteries_fops,     S_IRUGO },
+	{ "lcd_type",           &acpi_pcc_lcdtype_fops,          S_IRUGO },
+	{ "ac_brightness_max" , &acpi_pcc_ac_brightness_max_fops,S_IRUGO },
+	{ "ac_brightness_min" , &acpi_pcc_ac_brightness_min_fops,S_IRUGO },
+	{ "ac_brightness" ,     &acpi_pcc_ac_brightness_fops,    S_IFREG | S_IRUGO | S_IWUSR },
+	{ "dc_brightness_max" , &acpi_pcc_dc_brightness_max_fops,S_IRUGO },
+	{ "dc_brightness_min" , &acpi_pcc_dc_brightness_min_fops,S_IRUGO },
+	{ "dc_brightness" ,     &acpi_pcc_dc_brightness_fops,    S_IFREG | S_IRUGO | S_IWUSR }, 
+	{ "mute",               &acpi_pcc_mute_fops,             S_IFREG | S_IRUGO | S_IWUSR },
+	{ "version",            &acpi_pcc_version_fops,          S_IRUGO },
+	{ NULL, NULL, 0 },
 };
 
 static int __init add_device(ProcItem *proc_items, 
-				     struct proc_dir_entry* proc_entry,
-				     struct acpi_device *device)
+			     struct acpi_device *device)
 {
 	struct proc_dir_entry* proc;
 	ProcItem* item;
 	int i;
 	struct acpi_hotkey *hotkey = (struct acpi_hotkey*)acpi_driver_data(device);
 
-	for (item = proc_items, i = 0; item->name && i <= hotkey->num_sifr; 
+	for (item = proc_items, i = 0; item->name && i < hotkey->num_sifr + 1; 
 	     ++item, ++i) {
-		item->hotkey = hotkey;
-		proc = create_proc_read_entry(item->name,
-					      S_IFREG | S_IRUGO | S_IWUSR,
-					      proc_entry, 
-					      (read_proc_t*)dispatch_read, 
-					      item);
-		if (proc) {
+		proc = create_proc_entry(item->name, item->flag, hotkey->proc_dir_entry); 
+		if (likely(proc)) {
+			proc->proc_fops = item->fops;
+			proc->data = hotkey;
 			proc->owner = THIS_MODULE;
-		}
-		if (proc && item->write_func) {
-			proc->write_proc = (write_proc_t*)dispatch_write;
+		} else {
+			while (i-- > 0) {
+				item--;
+				remove_proc_entry(item->name, hotkey->proc_dir_entry);
+			}
+			return -ENODEV;
 		}
 	}
 	return 0;
@@ -518,7 +625,9 @@
 
 static int __init acpi_pcc_proc_init(struct acpi_device *device)
 {
-	int status;
+	struct proc_dir_entry* acpi_pcc_dir;
+	struct acpi_hotkey *hotkey = (struct acpi_hotkey*)acpi_driver_data(device);
+	acpi_status status;
 
 	ACPI_FUNCTION_TRACE("acpi_pcc_proc_init");
 
@@ -530,25 +639,36 @@
 	}
 
 	acpi_pcc_dir->owner = THIS_MODULE;
-	status = add_device(pcc_proc_items, acpi_pcc_dir, device);
+	hotkey->proc_dir_entry = acpi_pcc_dir;
+
+	status = add_device(pcc_proc_items, device);
 	if (unlikely(status)) {
 		remove_proc_entry(PROC_PCC, acpi_root_dir);
+		hotkey->proc_dir_entry = NULL;
+		return_VALUE(-ENODEV);
 	}
 
 	return_VALUE(status);
 }
 
 static void __exit remove_device(ProcItem *proc_items, 
-					struct proc_dir_entry* proc_entry)
+					struct acpi_device *device)
 {
+	struct acpi_hotkey *hotkey = (struct acpi_hotkey*)acpi_driver_data(device);
 	ProcItem* item;
+	int i;
 
-	for (item = proc_items; item->name; ++item) {
-		remove_proc_entry(item->name, proc_entry);
+	for (item = proc_items, i = 0; item->name && i <= hotkey->num_sifr; ++item, ++i) {
+		remove_proc_entry(item->name, hotkey->proc_dir_entry);
 	}
+
 	return;
 }
 
+/* --------------------------------------------------------------------------
+                         module init
+   -------------------------------------------------------------------------- */
+
 static int acpi_pcc_hotkey_add (struct acpi_device *device)
 {
 	acpi_status		status = AE_OK;
@@ -580,8 +700,8 @@
 	hotkey->handle = device->handle;
 	hotkey->num_sifr = num_sifr;
 	acpi_driver_data(device) = hotkey;
-	strcpy(acpi_device_name(device), ACPI_HOTKEY_DEVICE_NAME);
-	strcpy(acpi_device_class(device), ACPI_HOTKEY_CLASS);
+	strcpy(acpi_device_name(device), ACPI_PCC_DEVICE_NAME);
+	strcpy(acpi_device_class(device), ACPI_PCC_CLASS);
 
 	status = acpi_install_notify_handler (
 			hotkey->handle,
@@ -601,20 +721,18 @@
 static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type)
 {
 	acpi_status		status = AE_OK;
-	struct acpi_hotkey	*hotkey = NULL;
+	struct acpi_hotkey	*hotkey = acpi_driver_data(device);
 
 	ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_remove");
 
-	if (!device || !acpi_driver_data(device))
+	if (!device || !hotkey)
 		return_VALUE(-EINVAL);
 
-	if (acpi_pcc_dir) {
-		remove_device(pcc_proc_items, acpi_pcc_dir);
+	if (hotkey->proc_dir_entry) {
+		remove_device(pcc_proc_items, device);
 		remove_proc_entry(PROC_PCC, acpi_root_dir);
 	}
 
-	hotkey = acpi_driver_data(device);
-
 	status = acpi_remove_notify_handler(hotkey->handle,
 		    ACPI_DEVICE_NOTIFY, acpi_pcc_hotkey_notify);
 
@@ -635,7 +753,7 @@
 		return_VALUE(-ENODEV);
 	}
 
-	result = acpi_bus_register_driver(&acpi_hotkey_driver);
+	result = acpi_bus_register_driver(&acpi_pcc_driver);
 	if (result < 0) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error registering hotkey driver\n"));
 		return_VALUE(-ENODEV);
@@ -644,12 +762,11 @@
 	return_VALUE(0);
 }
 
-static void __exit
-acpi_pcc_exit(void)
+static void __exit acpi_pcc_exit(void)
 {
 	ACPI_FUNCTION_TRACE("acpi_pcc_exit");
 
-	acpi_bus_unregister_driver(&acpi_hotkey_driver); 
+	acpi_bus_unregister_driver(&acpi_pcc_driver); 
 
 	return_VOID;
 }

[-- Attachment #3: hotkey-handler-1.2.tar.gz --]
[-- Type: application/octet-stream, Size: 3027 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2004-09-15  0:42 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-08-19  6:00 [PATCH]Panasonic Hotkey Driver David Bronaugh
     [not found] ` <41244219.1090603-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
2004-08-20  2:51   ` Hiroshi Miura
     [not found]     ` <871xi2s555.wl%miura@da-cha.org>
     [not found]       ` <871xi2s555.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
2004-08-20  6:25         ` [PATCH]Panasonic Hotkey Driver v0.5 [1/2] Hiroshi Miura
     [not found]           ` <87vffeqqaq.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
2004-08-20 17:11             ` Len Brown
2004-08-21  1:30               ` [letsnote-tech:00074] " Hiroshi Miura
     [not found]     ` <87acwqserw.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
2004-08-20  6:25       ` [PATCH]Panasonic Hotkey Driver v0.5 [2/2] Hiroshi Miura
     [not found]         ` <87u0uyqqa7.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
2004-08-20  7:44           ` David Bronaugh
     [not found]             ` <4125ABEF.9090106-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
2004-08-20  8:43               ` Hiroshi Miura
     [not found]                 ` <87pt5mqjxj.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
2004-08-20 12:46                   ` Stefan Seyfried
2004-08-20 17:14                   ` David Bronaugh
     [not found]                     ` <41263192.7010300-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
2004-08-20 17:43                       ` Nate Lawson
     [not found]                         ` <41263840.1010003-Y6VGUYTwhu0@public.gmane.org>
2004-08-21  0:46                           ` Hiroshi Miura
2004-08-21  5:39                           ` Hiroshi Miura
2004-08-21  1:30                       ` Hiroshi Miura
2004-08-24 23:00           ` John Belmonte
2004-08-21  1:42   ` [PATCH]Panasonic Hotkey Driver Hiroshi Miura
     [not found]     ` <87zn4pl116.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
2004-08-21  5:33       ` Hiroshi Miura
     [not found]         ` <87n00pkqc5.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
2004-08-21  8:44           ` David Bronaugh
     [not found]             ` <41270B53.3060903-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
2004-08-21 10:34               ` Hiroshi Miura
     [not found]                 ` <87d61klqzh.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
2004-08-21 11:50                   ` vgod spam
2004-08-22  6:45                   ` David Bronaugh
     [not found]                     ` <41284119.1060504-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
2004-08-22  8:27                       ` David Bronaugh
     [not found]                         ` <412858F0.8050406-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
2004-08-23  5:07                           ` David Bronaugh
     [not found]                             ` <41297BA7.3050503-Jp3n8lUXroSX6QiC4yPwbg@public.gmane.org>
2004-08-26  8:45                               ` [PATCH]Panasonic Hotkey Driver v0.6.3 Hiroshi Miura
     [not found]                                 ` <87pt5e5lu3.wl%miura-yiisDzvROlQdnm+yROfE0A@public.gmane.org>
2004-09-15  0:42                                   ` [PATCH]Panasonic Hotkey Driver v0.7 Hiroshi Miura
  -- strict thread matches above, loose matches on Subject: below --
2004-07-31 14:17 [PATCH]Panasonic Hotkey Driver Hiroshi Miura
2004-08-18  5:04 ` [PATCH][ACPI] Panasonic " Len Brown
2004-08-18 14:52   ` [PATCH]Panasonic " John Belmonte

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox