Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153467627
D56406.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D56406.diff
View Options
diff --git a/sys/dev/acpi_support/acpi_sony.c b/sys/dev/acpi_support/acpi_sony.c
--- a/sys/dev/acpi_support/acpi_sony.c
+++ b/sys/dev/acpi_support/acpi_sony.c
@@ -37,11 +37,29 @@
#include <dev/acpica/acpivar.h>
#include <sys/sysctl.h>
+#ifdef EVDEV_SUPPORT
+#include <dev/evdev/input.h>
+#include <dev/evdev/evdev.h>
+#endif
+
#define _COMPONENT ACPI_OEM
ACPI_MODULE_NAME("Sony")
#define ACPI_SONY_GET_PID "GPID"
+#define SONY_MASK_FN_KEY (1 << 5)
+#define SONY_MASK_KEY_PRESS (1 << 7)
+#define SONY_MASK_KEYCODE 0xFF
+
+/* Event Code */
+#define SONY_EVENT_TOUCHPAD 0x81
+#define SONY_EVENT_BRIGHTNESS_DOWN 0x85
+#define SONY_EVENT_BRIGHTNESS_UP 0x86
+#define SONY_EVENT_EXTERNAL_DISPLAY 0x87
+#define SONY_EVENT_HIBERNATE 0x8c
+#define SONY_EVENT_VAIO 0xa5
+#define SONY_EVENT_ASSIST 0xa6
+
/*
* SNY5001
* This is the ACPI handle for the "Sony Notebook Control" driver under
@@ -59,6 +77,11 @@
struct acpi_sony_softc {
int pid;
+ device_t dev;
+ ACPI_HANDLE handle;
+#ifdef EVDEV_SUPPORT
+ struct evdev_dev *evdev;
+#endif
};
static struct acpi_sony_name_list
{
@@ -84,9 +107,14 @@
static int acpi_sony_probe(device_t dev);
static int acpi_sony_attach(device_t dev);
-static int acpi_sony_detach(device_t dev);
+static int acpi_sony_detach(device_t dev);
static int sysctl_acpi_sony_gen_handler(SYSCTL_HANDLER_ARGS);
+static void acpi_sony_notify(ACPI_HANDLE h, UINT32 notify, void *context);
+static int acpi_sony_init_snc(device_t dev);
+
+ACPI_SERIAL_DECL(sony, "ACPI Sony Extras");
+
static device_method_t acpi_sony_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, acpi_sony_probe),
@@ -104,6 +132,9 @@
DRIVER_MODULE(acpi_sony, acpi, acpi_sony_driver, 0, 0);
MODULE_DEPEND(acpi_sony, acpi, 1, 1, 1);
+#ifdef EVDEV_SUPPORT
+MODULE_DEPEND(acpi_sony, evdev, 1, 1, 1);
+#endif
static char *sny_id[] = {"SNY5001", NULL};
static int
@@ -125,6 +156,22 @@
int i;
sc = device_get_softc(dev);
+ sc->handle = acpi_get_handle(dev);
+
+#ifdef EVDEV_SUPPORT
+ sc->evdev = evdev_alloc();
+ evdev_set_name(sc->evdev, device_get_desc(dev));
+ evdev_set_phys(sc->evdev, device_get_nameunit(dev));
+ evdev_set_id(sc->evdev, BUS_HOST, 0, 0, 1);
+ evdev_support_event(sc->evdev, EV_SYN);
+ evdev_support_event(sc->evdev, EV_KEY);
+ evdev_support_key(sc->evdev, KEY_BRIGHTNESSUP);
+ evdev_support_key(sc->evdev, KEY_BRIGHTNESSDOWN);
+
+ if (evdev_register(sc->evdev) != 0)
+ return (ENXIO);
+#endif
+
acpi_GetInteger(acpi_get_handle(dev), ACPI_SONY_GET_PID, &sc->pid);
device_printf(dev, "PID %x\n", sc->pid);
for (i = 0 ; acpi_sony_oids[i].nodename != NULL; i++) {
@@ -144,12 +191,35 @@
acpi_sony_oids[i].comment);
}
}
+
+ /* Handle notifies */
+ ACPI_STATUS status;
+ status = AcpiInstallNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY,
+ acpi_sony_notify, dev);
+
+ if (ACPI_FAILURE(status)) {
+ device_printf(dev, "Couldn't install notify handler - %s\n",
+ AcpiFormatException(status));
+ return (ENXIO);
+ }
+
+ device_printf(dev, "Notify installed\n");
+ acpi_sony_init_snc(dev);
return (0);
}
-static int
+static int
acpi_sony_detach(device_t dev)
{
+ ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
+
+ struct acpi_sony_softc *sc = device_get_softc(dev);
+ AcpiRemoveNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, acpi_sony_notify);
+
+#ifdef EVDEV_SUPPORT
+ evdev_free(sc->evdev);
+#endif
+
return (0);
}
@@ -168,7 +238,63 @@
}
#endif
-static int
+static int
+acpi_sony_init_snc(device_t dev)
+{
+ struct acpi_sony_softc *sc;
+ ACPI_BUFFER Buf;
+ ACPI_OBJECT Arg;
+ ACPI_OBJECT_LIST Args;
+
+ ACPI_OBJECT *res;
+
+ Arg.Type = ACPI_TYPE_INTEGER;
+ Arg.Integer.Value = 16; // 0x10
+
+ Args.Count = 1;
+ Args.Pointer = &Arg;
+
+ Buf.Pointer = NULL;
+ Buf.Length = ACPI_ALLOCATE_BUFFER;
+
+ sc = device_get_softc(dev);
+ sc->handle = acpi_get_handle(dev);
+
+ AcpiEvaluateObject(sc->handle, "SN00", &Args, &Buf);
+
+ res = (ACPI_OBJECT *)Buf.Pointer;
+ if (res->Type != ACPI_TYPE_INTEGER) {
+ device_printf(dev, "SN00 returned non-integer\n");
+ return (ENXIO);
+ }
+ Arg.Integer.Value = res->Integer.Value;
+ AcpiEvaluateObject(sc->handle, "SN02", &Args, &Buf);
+ res = (ACPI_OBJECT *)Buf.Pointer;
+ if (res->Type != ACPI_TYPE_INTEGER) {
+ device_printf(dev, "SN02 returned non-integer\n");
+ return (ENXIO);
+ }
+ if (res->Integer.Value != 0) {
+ device_printf(dev, "SN02 returned unexpected value\n");
+ return (ENXIO);
+ }
+ Arg.Integer.Value = 0;
+ AcpiEvaluateObject(sc->handle, "SN07", &Args, &Buf);
+ res = (ACPI_OBJECT *)Buf.Pointer;
+ if (res->Type != ACPI_TYPE_INTEGER) {
+ device_printf(dev, "SN07 returned non-integer\n");
+ return (ENXIO);
+ }
+ if (res->Integer.Value != 0) {
+ device_printf(dev, "SN07 returned unexpected value\n");
+ return (ENXIO);
+ }
+ AcpiOsFree(Buf.Pointer);
+ device_printf(dev, "Init SNC\n");
+ return(0);
+}
+
+static int
sysctl_acpi_sony_gen_handler(SYSCTL_HANDLER_ARGS)
{
device_t dev = arg1;
@@ -184,3 +310,78 @@
acpi_sony_oids[function].setmethod, val);
return (0);
}
+
+static void
+acpi_sony_notify(ACPI_HANDLE h, UINT32 notify, void *context)
+{
+ device_t dev = context;
+ int arg, event, is_fn;
+ struct acpi_sony_softc *sc = device_get_softc(dev);
+
+ ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify);
+
+ ACPI_BUFFER Buf;
+ ACPI_OBJECT Arg;
+ ACPI_OBJECT_LIST Args;
+
+ ACPI_OBJECT *res;
+
+ Arg.Type = ACPI_TYPE_INTEGER;
+ Arg.Integer.Value = 512; // 0x200
+
+ Args.Count = 1;
+ Args.Pointer = &Arg;
+
+ Buf.Pointer = NULL;
+ Buf.Length = ACPI_ALLOCATE_BUFFER;
+
+ AcpiEvaluateObject(sc->handle, "SN07", &Args, &Buf);
+ res = (ACPI_OBJECT *)Buf.Pointer;
+ if (res->Type != ACPI_TYPE_INTEGER) {
+ device_printf(dev, "SN07 returned non-integer\n");
+ }
+ event = res->Integer.Value;
+ AcpiOsFree(Buf.Pointer);
+
+ /*
+ * event description
+ * +-+-+-+-+-+-+-+-+-+-+
+ * |9|8|7|6|5|4|3|2|1|0|
+ * +-+-+-+-+-+-+-+-+-+-+
+ * | | | \ | /
+ * | | | +----- key code
+ * | | |
+ * | | +------------- FN-key (0) or special key (1) (vaio, assist)
+ * | +----------------- key pressed (1) or released (0)
+ * +--------------------- SN07 event (1)
+ */
+
+ is_fn = !(event & SONY_MASK_FN_KEY);
+ arg = event & SONY_MASK_KEYCODE;
+
+ if ((event & SONY_MASK_KEY_PRESS) && is_fn) {
+// device_printf(dev, "FN %d pressed\n", arg);
+#ifdef EVDEV_SUPPORT
+ if ((arg & 0xff) == SONY_EVENT_BRIGHTNESS_UP ||
+ (arg & 0xff) == SONY_EVENT_BRIGHTNESS_DOWN) {
+
+ uint16_t key;
+
+ key = arg == SONY_EVENT_BRIGHTNESS_UP ?
+ KEY_BRIGHTNESSUP : KEY_BRIGHTNESSDOWN;
+ evdev_push_key(sc->evdev, key, 1);
+ evdev_sync(sc->evdev);
+ evdev_push_key(sc->evdev, key, 0);
+ evdev_sync(sc->evdev);
+ }
+
+ if ((arg & 0xff) == SONY_EVENT_TOUCHPAD) {
+ evdev_push_key(sc->evdev, KEY_TOUCHPAD_TOGGLE, 1);
+ evdev_sync(sc->evdev);
+ }
+#endif
+ } else {
+// device_printf(dev, "FN %d released\n", arg);
+ }
+ acpi_UserNotify("SONY", h, arg);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Apr 22, 8:21 AM (5 h, 12 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31601590
Default Alt Text
D56406.diff (6 KB)
Attached To
Mode
D56406: acpi_support: add FN keys support for Sony VAIO
Attached
Detach File
Event Timeline
Log In to Comment