Page MenuHomeFreeBSD

D56406.diff
No OneTemporary

D56406.diff

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

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)

Event Timeline