Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/atkbdc/psm.c
Show First 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | |||||
* Vendor specific support routines. | * Vendor specific support routines. | ||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include "opt_isa.h" | #include "opt_isa.h" | ||||
#include "opt_psm.h" | #include "opt_psm.h" | ||||
#include "opt_evdev.h" | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/module.h> | #include <sys/module.h> | ||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
#include <sys/conf.h> | #include <sys/conf.h> | ||||
#include <sys/filio.h> | #include <sys/filio.h> | ||||
Show All 11 Lines | |||||
#include <sys/limits.h> | #include <sys/limits.h> | ||||
#include <sys/mouse.h> | #include <sys/mouse.h> | ||||
#include <machine/resource.h> | #include <machine/resource.h> | ||||
#ifdef DEV_ISA | #ifdef DEV_ISA | ||||
#include <isa/isavar.h> | #include <isa/isavar.h> | ||||
#endif | #endif | ||||
#ifdef EVDEV_SUPPORT | |||||
#include <dev/evdev/evdev.h> | |||||
#include <dev/evdev/input.h> | |||||
#endif | |||||
#include <dev/atkbdc/atkbdcreg.h> | #include <dev/atkbdc/atkbdcreg.h> | ||||
#include <dev/atkbdc/psm.h> | #include <dev/atkbdc/psm.h> | ||||
/* | /* | ||||
* Driver specific options: the following options may be set by | * Driver specific options: the following options may be set by | ||||
* `options' statements in the kernel configuration file. | * `options' statements in the kernel configuration file. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 219 Lines • ▼ Show 20 Lines | |||||
#define ELANTECH_CAPABILITIES 0x02 | #define ELANTECH_CAPABILITIES 0x02 | ||||
#define ELANTECH_SAMPLE 0x03 | #define ELANTECH_SAMPLE 0x03 | ||||
#define ELANTECH_RESOLUTION 0x04 | #define ELANTECH_RESOLUTION 0x04 | ||||
#define ELANTECH_REG_READ 0x10 | #define ELANTECH_REG_READ 0x10 | ||||
#define ELANTECH_REG_WRITE 0x11 | #define ELANTECH_REG_WRITE 0x11 | ||||
#define ELANTECH_REG_RDWR 0x00 | #define ELANTECH_REG_RDWR 0x00 | ||||
#define ELANTECH_CUSTOM_CMD 0xf8 | #define ELANTECH_CUSTOM_CMD 0xf8 | ||||
#ifdef EVDEV_SUPPORT | |||||
#define ELANTECH_MAX_FINGERS 5 | |||||
#else | |||||
#define ELANTECH_MAX_FINGERS PSM_FINGERS | #define ELANTECH_MAX_FINGERS PSM_FINGERS | ||||
#endif | |||||
#define ELANTECH_FINGER_MAX_P 255 | |||||
#define ELANTECH_FINGER_MAX_W 15 | |||||
#define ELANTECH_FINGER_SET_XYP(pb) (finger_t) { \ | #define ELANTECH_FINGER_SET_XYP(pb) (finger_t) { \ | ||||
.x = (((pb)->ipacket[1] & 0x0f) << 8) | (pb)->ipacket[2], \ | .x = (((pb)->ipacket[1] & 0x0f) << 8) | (pb)->ipacket[2], \ | ||||
.y = (((pb)->ipacket[4] & 0x0f) << 8) | (pb)->ipacket[5], \ | .y = (((pb)->ipacket[4] & 0x0f) << 8) | (pb)->ipacket[5], \ | ||||
.p = ((pb)->ipacket[1] & 0xf0) | (((pb)->ipacket[4] >> 4) & 0x0f), \ | .p = ((pb)->ipacket[1] & 0xf0) | (((pb)->ipacket[4] >> 4) & 0x0f), \ | ||||
.w = PSM_FINGER_DEFAULT_W, \ | .w = PSM_FINGER_DEFAULT_W, \ | ||||
.flags = 0 \ | .flags = 0 \ | ||||
} | } | ||||
▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | struct psm_softc { /* Driver status information */ | ||||
struct callout callout; /* watchdog timer call out */ | struct callout callout; /* watchdog timer call out */ | ||||
struct callout softcallout; /* buffer timer call out */ | struct callout softcallout; /* buffer timer call out */ | ||||
struct cdev *dev; | struct cdev *dev; | ||||
struct cdev *bdev; | struct cdev *bdev; | ||||
int lasterr; | int lasterr; | ||||
int cmdcount; | int cmdcount; | ||||
struct sigio *async; /* Processes waiting for SIGIO */ | struct sigio *async; /* Processes waiting for SIGIO */ | ||||
int extended_buttons; | int extended_buttons; | ||||
#ifdef EVDEV_SUPPORT | |||||
struct evdev_dev *evdev_a; /* Absolute reporting device */ | |||||
struct evdev_dev *evdev_r; /* Relative reporting device */ | |||||
#endif | |||||
}; | }; | ||||
static devclass_t psm_devclass; | static devclass_t psm_devclass; | ||||
/* driver state flags (state) */ | /* driver state flags (state) */ | ||||
#define PSM_VALID 0x80 | #define PSM_VALID 0x80 | ||||
#define PSM_OPEN 1 /* Device is open */ | #define PSM_OPEN 1 /* Device is open */ | ||||
#define PSM_ASLP 2 /* Waiting for mouse data */ | #define PSM_ASLP 2 /* Waiting for mouse data */ | ||||
#define PSM_SOFTARMED 4 /* Software interrupt armed */ | #define PSM_SOFTARMED 4 /* Software interrupt armed */ | ||||
#define PSM_NEED_SYNCBITS 8 /* Set syncbits using next data pkt */ | #define PSM_NEED_SYNCBITS 8 /* Set syncbits using next data pkt */ | ||||
#define PSM_EV_OPEN_R 0x10 /* Relative evdev device is open */ | |||||
#define PSM_EV_OPEN_A 0x20 /* Absolute evdev device is open */ | |||||
/* driver configuration flags (config) */ | /* driver configuration flags (config) */ | ||||
#define PSM_CONFIG_RESOLUTION 0x000f /* resolution */ | #define PSM_CONFIG_RESOLUTION 0x000f /* resolution */ | ||||
#define PSM_CONFIG_ACCEL 0x00f0 /* acceleration factor */ | #define PSM_CONFIG_ACCEL 0x00f0 /* acceleration factor */ | ||||
#define PSM_CONFIG_NOCHECKSYNC 0x0100 /* disable sync. test */ | #define PSM_CONFIG_NOCHECKSYNC 0x0100 /* disable sync. test */ | ||||
#define PSM_CONFIG_NOIDPROBE 0x0200 /* disable mouse model probe */ | #define PSM_CONFIG_NOIDPROBE 0x0200 /* disable mouse model probe */ | ||||
#define PSM_CONFIG_NORESET 0x0400 /* don't reset the mouse */ | #define PSM_CONFIG_NORESET 0x0400 /* don't reset the mouse */ | ||||
#define PSM_CONFIG_FORCETAP 0x0800 /* assume `tap' action exists */ | #define PSM_CONFIG_FORCETAP 0x0800 /* assume `tap' action exists */ | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | |||||
/* function prototypes */ | /* function prototypes */ | ||||
static void psmidentify(driver_t *, device_t); | static void psmidentify(driver_t *, device_t); | ||||
static int psmprobe(device_t); | static int psmprobe(device_t); | ||||
static int psmattach(device_t); | static int psmattach(device_t); | ||||
static int psmdetach(device_t); | static int psmdetach(device_t); | ||||
static int psmresume(device_t); | static int psmresume(device_t); | ||||
static d_open_t psmopen; | static d_open_t psm_cdev_open; | ||||
static d_close_t psmclose; | static d_close_t psm_cdev_close; | ||||
static d_read_t psmread; | static d_read_t psmread; | ||||
static d_write_t psmwrite; | static d_write_t psmwrite; | ||||
static d_ioctl_t psmioctl; | static d_ioctl_t psmioctl; | ||||
static d_poll_t psmpoll; | static d_poll_t psmpoll; | ||||
static int psmopen(struct psm_softc *); | |||||
static int psmclose(struct psm_softc *); | |||||
#ifdef EVDEV_SUPPORT | |||||
static evdev_open_t psm_ev_open_r; | |||||
static evdev_close_t psm_ev_close_r; | |||||
static evdev_open_t psm_ev_open_a; | |||||
static evdev_close_t psm_ev_close_a; | |||||
#endif | |||||
static int enable_aux_dev(KBDC); | static int enable_aux_dev(KBDC); | ||||
static int disable_aux_dev(KBDC); | static int disable_aux_dev(KBDC); | ||||
static int get_mouse_status(KBDC, int *, int, int); | static int get_mouse_status(KBDC, int *, int, int); | ||||
static int get_aux_id(KBDC); | static int get_aux_id(KBDC); | ||||
static int set_mouse_sampling_rate(KBDC, int); | static int set_mouse_sampling_rate(KBDC, int); | ||||
static int set_mouse_scaling(KBDC, int); | static int set_mouse_scaling(KBDC, int); | ||||
static int set_mouse_resolution(KBDC, int); | static int set_mouse_resolution(KBDC, int); | ||||
static int set_mouse_mode(KBDC); | static int set_mouse_mode(KBDC); | ||||
▲ Show 20 Lines • Show All 113 Lines • ▼ Show 20 Lines | static driver_t psm_driver = { | ||||
PSM_DRIVER_NAME, | PSM_DRIVER_NAME, | ||||
psm_methods, | psm_methods, | ||||
sizeof(struct psm_softc), | sizeof(struct psm_softc), | ||||
}; | }; | ||||
static struct cdevsw psm_cdevsw = { | static struct cdevsw psm_cdevsw = { | ||||
.d_version = D_VERSION, | .d_version = D_VERSION, | ||||
.d_flags = D_NEEDGIANT, | .d_flags = D_NEEDGIANT, | ||||
.d_open = psmopen, | .d_open = psm_cdev_open, | ||||
.d_close = psmclose, | .d_close = psm_cdev_close, | ||||
.d_read = psmread, | .d_read = psmread, | ||||
.d_write = psmwrite, | .d_write = psmwrite, | ||||
.d_ioctl = psmioctl, | .d_ioctl = psmioctl, | ||||
.d_poll = psmpoll, | .d_poll = psmpoll, | ||||
.d_name = PSM_DRIVER_NAME, | .d_name = PSM_DRIVER_NAME, | ||||
}; | }; | ||||
#ifdef EVDEV_SUPPORT | |||||
static const struct evdev_methods psm_ev_methods_r = { | |||||
.ev_open = psm_ev_open_r, | |||||
.ev_close = psm_ev_close_r, | |||||
}; | |||||
static const struct evdev_methods psm_ev_methods_a = { | |||||
.ev_open = psm_ev_open_a, | |||||
.ev_close = psm_ev_close_a, | |||||
}; | |||||
#endif | |||||
/* device I/O routines */ | /* device I/O routines */ | ||||
static int | static int | ||||
enable_aux_dev(KBDC kbdc) | enable_aux_dev(KBDC kbdc) | ||||
{ | { | ||||
int res; | int res; | ||||
res = send_aux_command(kbdc, PSMC_ENABLE_DEV); | res = send_aux_command(kbdc, PSMC_ENABLE_DEV); | ||||
VLOG(2, (LOG_DEBUG, "psm: ENABLE_DEV return code:%04x\n", res)); | VLOG(2, (LOG_DEBUG, "psm: ENABLE_DEV return code:%04x\n", res)); | ||||
▲ Show 20 Lines • Show All 504 Lines • ▼ Show 20 Lines | if (doinitialize(sc, &sc->mode)) { | ||||
"psm%d: the aux device has gone! (reinitialize).\n", | "psm%d: the aux device has gone! (reinitialize).\n", | ||||
sc->unit); | sc->unit); | ||||
err = ENXIO; | err = ENXIO; | ||||
} | } | ||||
} | } | ||||
splx(s); | splx(s); | ||||
/* restore the driver state */ | /* restore the driver state */ | ||||
if ((sc->state & PSM_OPEN) && (err == 0)) { | if ((sc->state & (PSM_OPEN | PSM_EV_OPEN_R | PSM_EV_OPEN_A)) && | ||||
(err == 0)) { | |||||
/* enable the aux device and the port again */ | /* enable the aux device and the port again */ | ||||
err = doopen(sc, c); | err = doopen(sc, c); | ||||
if (err != 0) | if (err != 0) | ||||
log(LOG_ERR, "psm%d: failed to enable the device " | log(LOG_ERR, "psm%d: failed to enable the device " | ||||
"(reinitialize).\n", sc->unit); | "(reinitialize).\n", sc->unit); | ||||
} else { | } else { | ||||
/* restore the keyboard port and disable the aux port */ | /* restore the keyboard port and disable the aux port */ | ||||
if (!set_controller_command_byte(sc->kbdc, | if (!set_controller_command_byte(sc->kbdc, | ||||
▲ Show 20 Lines • Show All 364 Lines • ▼ Show 20 Lines | #endif | ||||
} | } | ||||
/* done */ | /* done */ | ||||
kbdc_set_device_mask(sc->kbdc, mask | KBD_AUX_CONTROL_BITS); | kbdc_set_device_mask(sc->kbdc, mask | KBD_AUX_CONTROL_BITS); | ||||
kbdc_lock(sc->kbdc, FALSE); | kbdc_lock(sc->kbdc, FALSE); | ||||
return (0); | return (0); | ||||
} | } | ||||
#ifdef EVDEV_SUPPORT | |||||
/* Values are taken from Linux drivers for userland software compatibility */ | |||||
#define PS2_MOUSE_VENDOR 0x0002 | |||||
#define PS2_MOUSE_GENERIC_PRODUCT 0x0001 | |||||
#define PS2_MOUSE_SYNAPTICS_NAME "SynPS/2 Synaptics TouchPad" | |||||
#define PS2_MOUSE_SYNAPTICS_PRODUCT 0x0007 | |||||
#define PS2_MOUSE_TRACKPOINT_NAME "TPPS/2 IBM TrackPoint" | |||||
#define PS2_MOUSE_TRACKPOINT_PRODUCT 0x000A | |||||
#define PS2_MOUSE_ELANTECH_NAME "ETPS/2 Elantech Touchpad" | |||||
#define PS2_MOUSE_ELANTECH_ST_NAME "ETPS/2 Elantech TrackPoint" | |||||
#define PS2_MOUSE_ELANTECH_PRODUCT 0x000E | |||||
#define ABSINFO_END { ABS_CNT, 0, 0, 0 } | |||||
static void | |||||
psm_support_abs_bulk(struct evdev_dev *evdev, const uint16_t info[][4]) | |||||
{ | |||||
size_t i; | |||||
for (i = 0; info[i][0] != ABS_CNT; i++) | |||||
evdev_support_abs(evdev, info[i][0], 0, info[i][1], info[i][2], | |||||
0, 0, info[i][3]); | |||||
} | |||||
static void | |||||
psm_push_mt_finger(struct psm_softc *sc, int id, const finger_t *f) | |||||
{ | |||||
int y = sc->synhw.minimumYCoord + sc->synhw.maximumYCoord - f->y; | |||||
evdev_push_abs(sc->evdev_a, ABS_MT_SLOT, id); | |||||
evdev_push_abs(sc->evdev_a, ABS_MT_TRACKING_ID, id); | |||||
evdev_push_abs(sc->evdev_a, ABS_MT_POSITION_X, f->x); | |||||
evdev_push_abs(sc->evdev_a, ABS_MT_POSITION_Y, y); | |||||
evdev_push_abs(sc->evdev_a, ABS_MT_PRESSURE, f->p); | |||||
} | |||||
static void | |||||
psm_push_st_finger(struct psm_softc *sc, const finger_t *f) | |||||
{ | |||||
int y = sc->synhw.minimumYCoord + sc->synhw.maximumYCoord - f->y; | |||||
evdev_push_abs(sc->evdev_a, ABS_X, f->x); | |||||
evdev_push_abs(sc->evdev_a, ABS_Y, y); | |||||
evdev_push_abs(sc->evdev_a, ABS_PRESSURE, f->p); | |||||
if (sc->synhw.capPalmDetect) | |||||
evdev_push_abs(sc->evdev_a, ABS_TOOL_WIDTH, f->w); | |||||
} | |||||
static void | |||||
psm_release_mt_slot(struct evdev_dev *evdev, int32_t slot) | |||||
{ | |||||
evdev_push_abs(evdev, ABS_MT_SLOT, slot); | |||||
evdev_push_abs(evdev, ABS_MT_TRACKING_ID, -1); | |||||
} | |||||
static int | static int | ||||
psm_register(device_t dev, int model_code) | |||||
{ | |||||
struct psm_softc *sc = device_get_softc(dev); | |||||
struct evdev_dev *evdev_r; | |||||
int error, i, nbuttons, nwheels, product; | |||||
bool is_pointing_stick; | |||||
const char *name; | |||||
name = model_name(model_code); | |||||
nbuttons = sc->hw.buttons; | |||||
product = PS2_MOUSE_GENERIC_PRODUCT; | |||||
nwheels = 0; | |||||
is_pointing_stick = false; | |||||
switch (model_code) { | |||||
case MOUSE_MODEL_TRACKPOINT: | |||||
name = PS2_MOUSE_TRACKPOINT_NAME; | |||||
product = PS2_MOUSE_TRACKPOINT_PRODUCT; | |||||
nbuttons = 3; | |||||
is_pointing_stick = true; | |||||
break; | |||||
case MOUSE_MODEL_ELANTECH: | |||||
name = PS2_MOUSE_ELANTECH_ST_NAME; | |||||
product = PS2_MOUSE_ELANTECH_PRODUCT; | |||||
nbuttons = 3; | |||||
is_pointing_stick = true; | |||||
break; | |||||
case MOUSE_MODEL_MOUSEMANPLUS: | |||||
case MOUSE_MODEL_4D: | |||||
nwheels = 2; | |||||
break; | |||||
case MOUSE_MODEL_EXPLORER: | |||||
case MOUSE_MODEL_INTELLI: | |||||
case MOUSE_MODEL_NET: | |||||
case MOUSE_MODEL_NETSCROLL: | |||||
case MOUSE_MODEL_4DPLUS: | |||||
nwheels = 1; | |||||
break; | |||||
} | |||||
evdev_r = evdev_alloc(); | |||||
evdev_set_name(evdev_r, name); | |||||
evdev_set_phys(evdev_r, device_get_nameunit(dev)); | |||||
evdev_set_id(evdev_r, BUS_I8042, PS2_MOUSE_VENDOR, product, 0); | |||||
evdev_set_methods(evdev_r, sc, &psm_ev_methods_r); | |||||
evdev_support_prop(evdev_r, INPUT_PROP_POINTER); | |||||
if (is_pointing_stick) | |||||
evdev_support_prop(evdev_r, INPUT_PROP_POINTING_STICK); | |||||
evdev_support_event(evdev_r, EV_SYN); | |||||
evdev_support_event(evdev_r, EV_KEY); | |||||
evdev_support_event(evdev_r, EV_REL); | |||||
evdev_support_rel(evdev_r, REL_X); | |||||
evdev_support_rel(evdev_r, REL_Y); | |||||
switch (nwheels) { | |||||
case 2: | |||||
evdev_support_rel(evdev_r, REL_HWHEEL); | |||||
/* FALLTHROUGH */ | |||||
case 1: | |||||
evdev_support_rel(evdev_r, REL_WHEEL); | |||||
} | |||||
for (i = 0; i < nbuttons; i++) | |||||
evdev_support_key(evdev_r, BTN_MOUSE + i); | |||||
error = evdev_register_mtx(evdev_r, &Giant); | |||||
if (error) | |||||
evdev_free(evdev_r); | |||||
else | |||||
sc->evdev_r = evdev_r; | |||||
return (error); | |||||
} | |||||
static int | |||||
psm_register_synaptics(device_t dev) | |||||
{ | |||||
struct psm_softc *sc = device_get_softc(dev); | |||||
const uint16_t synaptics_absinfo_st[][4] = { | |||||
{ ABS_X, sc->synhw.minimumXCoord, | |||||
sc->synhw.maximumXCoord, sc->synhw.infoXupmm }, | |||||
{ ABS_Y, sc->synhw.minimumYCoord, | |||||
sc->synhw.maximumYCoord, sc->synhw.infoYupmm }, | |||||
{ ABS_PRESSURE, 0, ELANTECH_FINGER_MAX_P, 0 }, | |||||
ABSINFO_END, | |||||
}; | |||||
const uint16_t synaptics_absinfo_mt[][4] = { | |||||
{ ABS_MT_SLOT, 0, PSM_FINGERS-1, 0}, | |||||
{ ABS_MT_TRACKING_ID, -1, PSM_FINGERS-1, 0}, | |||||
{ ABS_MT_POSITION_X, sc->synhw.minimumXCoord, | |||||
sc->synhw.maximumXCoord, sc->synhw.infoXupmm }, | |||||
{ ABS_MT_POSITION_Y, sc->synhw.minimumYCoord, | |||||
sc->synhw.maximumYCoord, sc->synhw.infoYupmm }, | |||||
{ ABS_MT_PRESSURE, 0, ELANTECH_FINGER_MAX_P, 0 }, | |||||
ABSINFO_END, | |||||
}; | |||||
struct evdev_dev *evdev_a; | |||||
int error, i, guest_model; | |||||
evdev_a = evdev_alloc(); | |||||
evdev_set_name(evdev_a, PS2_MOUSE_SYNAPTICS_NAME); | |||||
evdev_set_phys(evdev_a, device_get_nameunit(dev)); | |||||
evdev_set_id(evdev_a, BUS_I8042, PS2_MOUSE_VENDOR, | |||||
PS2_MOUSE_SYNAPTICS_PRODUCT, 0); | |||||
evdev_set_methods(evdev_a, sc, &psm_ev_methods_a); | |||||
evdev_support_event(evdev_a, EV_SYN); | |||||
evdev_support_event(evdev_a, EV_KEY); | |||||
evdev_support_event(evdev_a, EV_ABS); | |||||
evdev_support_prop(evdev_a, INPUT_PROP_POINTER); | |||||
if (sc->synhw.capAdvancedGestures) | |||||
evdev_support_prop(evdev_a, INPUT_PROP_SEMI_MT); | |||||
if (sc->synhw.capClickPad) | |||||
evdev_support_prop(evdev_a, INPUT_PROP_BUTTONPAD); | |||||
evdev_support_key(evdev_a, BTN_TOUCH); | |||||
evdev_support_nfingers(evdev_a, 3); | |||||
psm_support_abs_bulk(evdev_a, synaptics_absinfo_st); | |||||
if (sc->synhw.capAdvancedGestures || sc->synhw.capReportsV) | |||||
psm_support_abs_bulk(evdev_a, synaptics_absinfo_mt); | |||||
if (sc->synhw.capPalmDetect) | |||||
evdev_support_abs(evdev_a, ABS_TOOL_WIDTH, 0, 0, 15, 0, 0, 0); | |||||
evdev_support_key(evdev_a, BTN_LEFT); | |||||
if (!sc->synhw.capClickPad) { | |||||
evdev_support_key(evdev_a, BTN_RIGHT); | |||||
if (sc->synhw.capExtended && sc->synhw.capMiddle) | |||||
evdev_support_key(evdev_a, BTN_MIDDLE); | |||||
} | |||||
if (sc->synhw.capExtended && sc->synhw.capFourButtons) { | |||||
evdev_support_key(evdev_a, BTN_BACK); | |||||
evdev_support_key(evdev_a, BTN_FORWARD); | |||||
} | |||||
if (sc->synhw.capExtended && (sc->synhw.nExtendedButtons > 0)) | |||||
for (i = 0; i < sc->synhw.nExtendedButtons; i++) | |||||
evdev_support_key(evdev_a, BTN_0 + i); | |||||
error = evdev_register_mtx(evdev_a, &Giant); | |||||
if (!error && sc->synhw.capPassthrough) { | |||||
guest_model = sc->tpinfo.sysctl_tree != NULL ? | |||||
MOUSE_MODEL_TRACKPOINT : MOUSE_MODEL_GENERIC; | |||||
error = psm_register(dev, guest_model); | |||||
} | |||||
if (error) | |||||
evdev_free(evdev_a); | |||||
else | |||||
sc->evdev_a = evdev_a; | |||||
return (error); | |||||
} | |||||
static int | |||||
psm_register_elantech(device_t dev) | |||||
{ | |||||
struct psm_softc *sc = device_get_softc(dev); | |||||
const uint16_t elantech_absinfo[][4] = { | |||||
{ ABS_X, 0, sc->elanhw.sizex, | |||||
sc->elanhw.dpmmx }, | |||||
{ ABS_Y, 0, sc->elanhw.sizey, | |||||
sc->elanhw.dpmmy }, | |||||
{ ABS_PRESSURE, 0, ELANTECH_FINGER_MAX_P, 0 }, | |||||
{ ABS_TOOL_WIDTH, 0, ELANTECH_FINGER_MAX_W, 0 }, | |||||
{ ABS_MT_SLOT, 0, ELANTECH_MAX_FINGERS - 1, 0 }, | |||||
{ ABS_MT_TRACKING_ID, -1, ELANTECH_MAX_FINGERS - 1, 0 }, | |||||
{ ABS_MT_POSITION_X, 0, sc->elanhw.sizex, | |||||
sc->elanhw.dpmmx }, | |||||
{ ABS_MT_POSITION_Y, 0, sc->elanhw.sizey, | |||||
sc->elanhw.dpmmy }, | |||||
{ ABS_MT_PRESSURE, 0, ELANTECH_FINGER_MAX_P, 0 }, | |||||
{ ABS_MT_TOUCH_MAJOR, 0, ELANTECH_FINGER_MAX_W * | |||||
sc->elanhw.dptracex, 0 }, | |||||
ABSINFO_END, | |||||
}; | |||||
struct evdev_dev *evdev_a; | |||||
int error; | |||||
evdev_a = evdev_alloc(); | |||||
evdev_set_name(evdev_a, PS2_MOUSE_ELANTECH_NAME); | |||||
evdev_set_phys(evdev_a, device_get_nameunit(dev)); | |||||
evdev_set_id(evdev_a, BUS_I8042, PS2_MOUSE_VENDOR, | |||||
PS2_MOUSE_ELANTECH_PRODUCT, 0); | |||||
evdev_set_methods(evdev_a, sc, &psm_ev_methods_a); | |||||
evdev_support_event(evdev_a, EV_SYN); | |||||
evdev_support_event(evdev_a, EV_KEY); | |||||
evdev_support_event(evdev_a, EV_ABS); | |||||
evdev_support_prop(evdev_a, INPUT_PROP_POINTER); | |||||
if (sc->elanhw.issemimt) | |||||
evdev_support_prop(evdev_a, INPUT_PROP_SEMI_MT); | |||||
if (sc->elanhw.isclickpad) | |||||
evdev_support_prop(evdev_a, INPUT_PROP_BUTTONPAD); | |||||
evdev_support_key(evdev_a, BTN_TOUCH); | |||||
evdev_support_nfingers(evdev_a, ELANTECH_MAX_FINGERS); | |||||
evdev_support_key(evdev_a, BTN_LEFT); | |||||
if (!sc->elanhw.isclickpad) | |||||
evdev_support_key(evdev_a, BTN_RIGHT); | |||||
psm_support_abs_bulk(evdev_a, elantech_absinfo); | |||||
error = evdev_register_mtx(evdev_a, &Giant); | |||||
if (!error && sc->elanhw.hastrackpoint) | |||||
error = psm_register(dev, MOUSE_MODEL_ELANTECH); | |||||
if (error) | |||||
evdev_free(evdev_a); | |||||
else | |||||
sc->evdev_a = evdev_a; | |||||
return (error); | |||||
} | |||||
#endif | |||||
static int | |||||
psmattach(device_t dev) | psmattach(device_t dev) | ||||
{ | { | ||||
int unit = device_get_unit(dev); | int unit = device_get_unit(dev); | ||||
struct psm_softc *sc = device_get_softc(dev); | struct psm_softc *sc = device_get_softc(dev); | ||||
int error; | int error; | ||||
int rid; | int rid; | ||||
/* Setup initial state */ | /* Setup initial state */ | ||||
Show All 14 Lines | psmattach(device_t dev) | ||||
} | } | ||||
/* Done */ | /* Done */ | ||||
sc->dev = make_dev(&psm_cdevsw, 0, 0, 0, 0666, "psm%d", unit); | sc->dev = make_dev(&psm_cdevsw, 0, 0, 0, 0666, "psm%d", unit); | ||||
sc->dev->si_drv1 = sc; | sc->dev->si_drv1 = sc; | ||||
sc->bdev = make_dev(&psm_cdevsw, 0, 0, 0, 0666, "bpsm%d", unit); | sc->bdev = make_dev(&psm_cdevsw, 0, 0, 0, 0666, "bpsm%d", unit); | ||||
sc->bdev->si_drv1 = sc; | sc->bdev->si_drv1 = sc; | ||||
#ifdef EVDEV_SUPPORT | |||||
switch (sc->hw.model) { | |||||
case MOUSE_MODEL_SYNAPTICS: | |||||
error = psm_register_synaptics(dev); | |||||
break; | |||||
case MOUSE_MODEL_ELANTECH: | |||||
error = psm_register_elantech(dev); | |||||
break; | |||||
default: | |||||
error = psm_register(dev, sc->hw.model); | |||||
} | |||||
if (error) | |||||
return (error); | |||||
#endif | |||||
/* Some touchpad devices need full reinitialization after suspend. */ | /* Some touchpad devices need full reinitialization after suspend. */ | ||||
switch (sc->hw.model) { | switch (sc->hw.model) { | ||||
case MOUSE_MODEL_SYNAPTICS: | case MOUSE_MODEL_SYNAPTICS: | ||||
case MOUSE_MODEL_GLIDEPOINT: | case MOUSE_MODEL_GLIDEPOINT: | ||||
case MOUSE_MODEL_VERSAPAD: | case MOUSE_MODEL_VERSAPAD: | ||||
case MOUSE_MODEL_ELANTECH: | case MOUSE_MODEL_ELANTECH: | ||||
sc->config |= PSM_CONFIG_INITAFTERSUSPEND; | sc->config |= PSM_CONFIG_INITAFTERSUSPEND; | ||||
break; | break; | ||||
Show All 32 Lines | |||||
{ | { | ||||
struct psm_softc *sc; | struct psm_softc *sc; | ||||
int rid; | int rid; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
if (sc->state & PSM_OPEN) | if (sc->state & PSM_OPEN) | ||||
return (EBUSY); | return (EBUSY); | ||||
#ifdef EVDEV_SUPPORT | |||||
evdev_free(sc->evdev_r); | |||||
evdev_free(sc->evdev_a); | |||||
#endif | |||||
rid = KBDC_RID_AUX; | rid = KBDC_RID_AUX; | ||||
bus_teardown_intr(dev, sc->intr, sc->ih); | bus_teardown_intr(dev, sc->intr, sc->ih); | ||||
bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr); | bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr); | ||||
destroy_dev(sc->dev); | destroy_dev(sc->dev); | ||||
destroy_dev(sc->bdev); | destroy_dev(sc->bdev); | ||||
callout_drain(&sc->callout); | callout_drain(&sc->callout); | ||||
callout_drain(&sc->softcallout); | callout_drain(&sc->softcallout); | ||||
return (0); | return (0); | ||||
} | } | ||||
#ifdef EVDEV_SUPPORT | |||||
static int | static int | ||||
psmopen(struct cdev *dev, int flag, int fmt, struct thread *td) | psm_ev_open_r(struct evdev_dev *evdev, void *ev_softc) | ||||
{ | { | ||||
struct psm_softc *sc = (struct psm_softc *)ev_softc; | |||||
int err = 0; | |||||
/* Get device data */ | |||||
if ((sc->state & PSM_VALID) == 0) { | |||||
/* the device is no longer valid/functioning */ | |||||
return (ENXIO); | |||||
} | |||||
if (!(sc->state & (PSM_OPEN | PSM_EV_OPEN_A))) | |||||
err = psmopen(sc); | |||||
if (err == 0) | |||||
sc->state |= PSM_EV_OPEN_R; | |||||
return (err); | |||||
} | |||||
static void | |||||
psm_ev_close_r(struct evdev_dev *evdev, void *ev_softc) | |||||
{ | |||||
struct psm_softc *sc = (struct psm_softc *)ev_softc; | |||||
sc->state &= ~PSM_EV_OPEN_R; | |||||
if (sc->state & (PSM_OPEN | PSM_EV_OPEN_A)) | |||||
return; | |||||
if (sc->state & PSM_VALID) | |||||
psmclose(sc); | |||||
} | |||||
static int | |||||
psm_ev_open_a(struct evdev_dev *evdev, void *ev_softc) | |||||
{ | |||||
struct psm_softc *sc = (struct psm_softc *)ev_softc; | |||||
int err = 0; | |||||
/* Get device data */ | |||||
if ((sc->state & PSM_VALID) == 0) { | |||||
/* the device is no longer valid/functioning */ | |||||
return (ENXIO); | |||||
} | |||||
if (!(sc->state & (PSM_OPEN | PSM_EV_OPEN_R))) | |||||
err = psmopen(sc); | |||||
if (err == 0) | |||||
sc->state |= PSM_EV_OPEN_A; | |||||
return (err); | |||||
} | |||||
static void | |||||
psm_ev_close_a(struct evdev_dev *evdev, void *ev_softc) | |||||
{ | |||||
struct psm_softc *sc = (struct psm_softc *)ev_softc; | |||||
sc->state &= ~PSM_EV_OPEN_A; | |||||
if (sc->state & (PSM_OPEN | PSM_EV_OPEN_R)) | |||||
return; | |||||
if (sc->state & PSM_VALID) | |||||
psmclose(sc); | |||||
} | |||||
#endif | |||||
static int | |||||
psm_cdev_open(struct cdev *dev, int flag, int fmt, struct thread *td) | |||||
{ | |||||
struct psm_softc *sc; | struct psm_softc *sc; | ||||
int command_byte; | int err = 0; | ||||
int err; | |||||
int s; | |||||
/* Get device data */ | /* Get device data */ | ||||
sc = dev->si_drv1; | sc = dev->si_drv1; | ||||
if ((sc == NULL) || (sc->state & PSM_VALID) == 0) { | if ((sc == NULL) || (sc->state & PSM_VALID) == 0) { | ||||
/* the device is no longer valid/functioning */ | /* the device is no longer valid/functioning */ | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
/* Disallow multiple opens */ | /* Disallow multiple opens */ | ||||
if (sc->state & PSM_OPEN) | if (sc->state & PSM_OPEN) | ||||
return (EBUSY); | return (EBUSY); | ||||
device_busy(devclass_get_device(psm_devclass, sc->unit)); | device_busy(devclass_get_device(psm_devclass, sc->unit)); | ||||
#ifdef EVDEV_SUPPORT | |||||
/* Already opened by evdev */ | |||||
if (!(sc->state & (PSM_EV_OPEN_R | PSM_EV_OPEN_A))) | |||||
#endif | |||||
err = psmopen(sc); | |||||
if (err == 0) | |||||
sc->state |= PSM_OPEN; | |||||
else | |||||
device_unbusy(devclass_get_device(psm_devclass, sc->unit)); | |||||
return (err); | |||||
} | |||||
static int | |||||
psm_cdev_close(struct cdev *dev, int flag, int fmt, struct thread *td) | |||||
{ | |||||
struct psm_softc *sc; | |||||
int err = 0; | |||||
/* Get device data */ | |||||
sc = dev->si_drv1; | |||||
if ((sc == NULL) || (sc->state & PSM_VALID) == 0) { | |||||
/* the device is no longer valid/functioning */ | |||||
return (ENXIO); | |||||
} | |||||
#ifdef EVDEV_SUPPORT | |||||
/* Still opened by evdev */ | |||||
if (!(sc->state & (PSM_EV_OPEN_R | PSM_EV_OPEN_A))) | |||||
#endif | |||||
err = psmclose(sc); | |||||
if (err == 0) { | |||||
sc->state &= ~PSM_OPEN; | |||||
/* clean up and sigio requests */ | |||||
if (sc->async != NULL) { | |||||
funsetown(&sc->async); | |||||
sc->async = NULL; | |||||
} | |||||
device_unbusy(devclass_get_device(psm_devclass, sc->unit)); | |||||
} | |||||
return (err); | |||||
} | |||||
static int | |||||
psmopen(struct psm_softc *sc) | |||||
{ | |||||
int command_byte; | |||||
int err; | |||||
int s; | |||||
/* Initialize state */ | /* Initialize state */ | ||||
sc->mode.level = sc->dflt_mode.level; | sc->mode.level = sc->dflt_mode.level; | ||||
sc->mode.protocol = sc->dflt_mode.protocol; | sc->mode.protocol = sc->dflt_mode.protocol; | ||||
sc->watchdog = FALSE; | sc->watchdog = FALSE; | ||||
sc->async = NULL; | sc->async = NULL; | ||||
/* flush the event queue */ | /* flush the event queue */ | ||||
sc->queue.count = 0; | sc->queue.count = 0; | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | psmopen(struct psm_softc *sc) | ||||
* via `kbdc_lock()' | * via `kbdc_lock()' | ||||
*/ | */ | ||||
splx(s); | splx(s); | ||||
/* enable the mouse device */ | /* enable the mouse device */ | ||||
err = doopen(sc, command_byte); | err = doopen(sc, command_byte); | ||||
/* done */ | /* done */ | ||||
if (err == 0) | |||||
sc->state |= PSM_OPEN; | |||||
kbdc_lock(sc->kbdc, FALSE); | kbdc_lock(sc->kbdc, FALSE); | ||||
return (err); | return (err); | ||||
} | } | ||||
static int | static int | ||||
psmclose(struct cdev *dev, int flag, int fmt, struct thread *td) | psmclose(struct psm_softc *sc) | ||||
{ | { | ||||
struct psm_softc *sc = dev->si_drv1; | |||||
int stat[3]; | int stat[3]; | ||||
int command_byte; | int command_byte; | ||||
int s; | int s; | ||||
/* don't let timeout routines in the keyboard driver to poll the kbdc */ | /* don't let timeout routines in the keyboard driver to poll the kbdc */ | ||||
if (!kbdc_lock(sc->kbdc, TRUE)) | if (!kbdc_lock(sc->kbdc, TRUE)) | ||||
return (EIO); | return (EIO); | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | if (!set_controller_command_byte(sc->kbdc, | ||||
log(LOG_ERR, | log(LOG_ERR, | ||||
"psm%d: failed to disable the aux port (psmclose).\n", | "psm%d: failed to disable the aux port (psmclose).\n", | ||||
sc->unit); | sc->unit); | ||||
} | } | ||||
/* remove anything left in the output buffer */ | /* remove anything left in the output buffer */ | ||||
empty_aux_buffer(sc->kbdc, 10); | empty_aux_buffer(sc->kbdc, 10); | ||||
/* clean up and sigio requests */ | |||||
if (sc->async != NULL) { | |||||
funsetown(&sc->async); | |||||
sc->async = NULL; | |||||
} | |||||
/* close is almost always successful */ | /* close is almost always successful */ | ||||
sc->state &= ~PSM_OPEN; | |||||
kbdc_lock(sc->kbdc, FALSE); | kbdc_lock(sc->kbdc, FALSE); | ||||
device_unbusy(devclass_get_device(psm_devclass, sc->unit)); | |||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
tame_mouse(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *status, | tame_mouse(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *status, | ||||
u_char *buf) | u_char *buf) | ||||
{ | { | ||||
static u_char butmapps2[8] = { | static u_char butmapps2[8] = { | ||||
▲ Show 20 Lines • Show All 634 Lines • ▼ Show 20 Lines | psmintr(void *arg) | ||||
packetbuf_t *pb; | packetbuf_t *pb; | ||||
/* read until there is nothing to read */ | /* read until there is nothing to read */ | ||||
while((c = read_aux_data_no_wait(sc->kbdc)) != -1) { | while((c = read_aux_data_no_wait(sc->kbdc)) != -1) { | ||||
pb = &sc->pqueue[sc->pqueue_end]; | pb = &sc->pqueue[sc->pqueue_end]; | ||||
/* discard the byte if the device is not open */ | /* discard the byte if the device is not open */ | ||||
if ((sc->state & PSM_OPEN) == 0) | if (!(sc->state & (PSM_OPEN | PSM_EV_OPEN_R | PSM_EV_OPEN_A))) | ||||
continue; | continue; | ||||
getmicrouptime(&now); | getmicrouptime(&now); | ||||
if ((pb->inputbytes > 0) && | if ((pb->inputbytes > 0) && | ||||
timevalcmp(&now, &sc->inputtimeout, >)) { | timevalcmp(&now, &sc->inputtimeout, >)) { | ||||
VLOG(3, (LOG_DEBUG, "psmintr: delay too long; " | VLOG(3, (LOG_DEBUG, "psmintr: delay too long; " | ||||
"resetting byte count\n")); | "resetting byte count\n")); | ||||
pb->inputbytes = 0; | pb->inputbytes = 0; | ||||
▲ Show 20 Lines • Show All 341 Lines • ▼ Show 20 Lines | if (sc->synhw.capPassthrough) { | ||||
guest_buttons = 0; | guest_buttons = 0; | ||||
if (pb->ipacket[1] & 0x01) | if (pb->ipacket[1] & 0x01) | ||||
guest_buttons |= MOUSE_BUTTON1DOWN; | guest_buttons |= MOUSE_BUTTON1DOWN; | ||||
if (pb->ipacket[1] & 0x04) | if (pb->ipacket[1] & 0x04) | ||||
guest_buttons |= MOUSE_BUTTON2DOWN; | guest_buttons |= MOUSE_BUTTON2DOWN; | ||||
if (pb->ipacket[1] & 0x02) | if (pb->ipacket[1] & 0x02) | ||||
guest_buttons |= MOUSE_BUTTON3DOWN; | guest_buttons |= MOUSE_BUTTON3DOWN; | ||||
#ifdef EVDEV_SUPPORT | |||||
if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) { | |||||
evdev_push_rel(sc->evdev_r, REL_X, *x); | |||||
evdev_push_rel(sc->evdev_r, REL_Y, -*y); | |||||
evdev_push_mouse_btn(sc->evdev_r, | |||||
guest_buttons); | |||||
evdev_sync(sc->evdev_r); | |||||
} | |||||
#endif | |||||
ms->button = touchpad_buttons | guest_buttons | | ms->button = touchpad_buttons | guest_buttons | | ||||
sc->extended_buttons; | sc->extended_buttons; | ||||
} | } | ||||
goto SYNAPTICS_END; | goto SYNAPTICS_END; | ||||
case 2: | case 2: | ||||
/* Handle Extended W mode packets */ | /* Handle Extended W mode packets */ | ||||
ewcode = (pb->ipacket[5] & 0xf0) >> 4; | ewcode = (pb->ipacket[5] & 0xf0) >> 4; | ||||
▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | if ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x02) { | ||||
* The mask for n bits is computed with the formula | * The mask for n bits is computed with the formula | ||||
* | * | ||||
* (1 << n) - 1 | * (1 << n) - 1 | ||||
*/ | */ | ||||
int maskedbits = 0; | int maskedbits = 0; | ||||
int mask = 0; | int mask = 0; | ||||
maskedbits = (sc->synhw.nExtendedButtons + 1) >> 1; | maskedbits = (sc->synhw.nExtendedButtons + 1) >> 1; | ||||
mask = (1 << maskedbits) - 1; | mask = (1 << maskedbits) - 1; | ||||
#ifdef EVDEV_SUPPORT | |||||
int i; | |||||
if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) { | |||||
if (sc->synhw.capPassthrough) { | |||||
evdev_push_mouse_btn(sc->evdev_r, | |||||
extended_buttons); | |||||
evdev_sync(sc->evdev_r); | |||||
} | |||||
for (i = 0; i < maskedbits; i++) { | |||||
evdev_push_key(sc->evdev_a, | |||||
BTN_0 + i * 2, | |||||
pb->ipacket[4] & (1 << i)); | |||||
evdev_push_key(sc->evdev_a, | |||||
BTN_0 + i * 2 + 1, | |||||
pb->ipacket[5] & (1 << i)); | |||||
} | |||||
} | |||||
#endif | |||||
pb->ipacket[4] &= ~(mask); | pb->ipacket[4] &= ~(mask); | ||||
pb->ipacket[5] &= ~(mask); | pb->ipacket[5] &= ~(mask); | ||||
} else if (!sc->syninfo.directional_scrolls && | } else if (!sc->syninfo.directional_scrolls && | ||||
!sc->gesture.in_vscroll) { | !sc->gesture.in_vscroll) { | ||||
/* | /* | ||||
* Keep reporting MOUSE DOWN until we get a new packet | * Keep reporting MOUSE DOWN until we get a new packet | ||||
* indicating otherwise. | * indicating otherwise. | ||||
*/ | */ | ||||
Show All 35 Lines | #endif | ||||
/* Ignore hovering and unmeasurable touches */ | /* Ignore hovering and unmeasurable touches */ | ||||
if (f[0].p < sc->syninfo.min_pressure || f[0].x < 2) | if (f[0].p < sc->syninfo.min_pressure || f[0].x < 2) | ||||
nfingers = 0; | nfingers = 0; | ||||
for (id = 0; id < PSM_FINGERS; id++) | for (id = 0; id < PSM_FINGERS; id++) | ||||
if (id >= nfingers) | if (id >= nfingers) | ||||
PSM_FINGER_RESET(f[id]); | PSM_FINGER_RESET(f[id]); | ||||
#ifdef EVDEV_SUPPORT | |||||
if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) { | |||||
for (id = 0; id < PSM_FINGERS; id++) { | |||||
if (PSM_FINGER_IS_SET(f[id])) | |||||
psm_push_mt_finger(sc, id, &f[id]); | |||||
else | |||||
psm_release_mt_slot(sc->evdev_a, id); | |||||
} | |||||
evdev_push_key(sc->evdev_a, BTN_TOUCH, nfingers > 0); | |||||
evdev_push_nfingers(sc->evdev_a, nfingers); | |||||
if (nfingers > 0) | |||||
psm_push_st_finger(sc, &f[0]); | |||||
else | |||||
evdev_push_abs(sc->evdev_a, ABS_PRESSURE, 0); | |||||
evdev_push_mouse_btn(sc->evdev_a, touchpad_buttons); | |||||
if (sc->synhw.capExtended && sc->synhw.capFourButtons) { | |||||
evdev_push_key(sc->evdev_a, BTN_FORWARD, | |||||
touchpad_buttons & MOUSE_BUTTON4DOWN); | |||||
evdev_push_key(sc->evdev_a, BTN_BACK, | |||||
touchpad_buttons & MOUSE_BUTTON5DOWN); | |||||
} | |||||
evdev_sync(sc->evdev_a); | |||||
} | |||||
#endif | |||||
ms->button = touchpad_buttons; | ms->button = touchpad_buttons; | ||||
psmgestures(sc, &f[0], nfingers, ms); | psmgestures(sc, &f[0], nfingers, ms); | ||||
for (id = 0; id < PSM_FINGERS; id++) | for (id = 0; id < PSM_FINGERS; id++) | ||||
psmsmoother(sc, &f[id], id, ms, x, y); | psmsmoother(sc, &f[id], id, ms, x, y); | ||||
/* Palm detection doesn't terminate the current action. */ | /* Palm detection doesn't terminate the current action. */ | ||||
if (psmpalmdetect(sc, &f[0], nfingers)) { | if (psmpalmdetect(sc, &f[0], nfingers)) { | ||||
▲ Show 20 Lines • Show All 983 Lines • ▼ Show 20 Lines | *x = (pb->ipacket[0] & 0x20) ? | ||||
pb->ipacket[4] - 256 : pb->ipacket[4]; | pb->ipacket[4] - 256 : pb->ipacket[4]; | ||||
*y = (pb->ipacket[0] & 0x10) ? | *y = (pb->ipacket[0] & 0x10) ? | ||||
pb->ipacket[5] - 256 : pb->ipacket[5]; | pb->ipacket[5] - 256 : pb->ipacket[5]; | ||||
trackpoint_button = | trackpoint_button = | ||||
((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) | | ((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) | | ||||
((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0) | | ((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0) | | ||||
((pb->ipacket[0] & 0x04) ? MOUSE_BUTTON2DOWN : 0); | ((pb->ipacket[0] & 0x04) ? MOUSE_BUTTON2DOWN : 0); | ||||
#ifdef EVDEV_SUPPORT | |||||
evdev_push_rel(sc->evdev_r, REL_X, *x); | |||||
evdev_push_rel(sc->evdev_r, REL_Y, -*y); | |||||
evdev_push_mouse_btn(sc->evdev_r, trackpoint_button); | |||||
evdev_sync(sc->evdev_r); | |||||
#endif | |||||
ms->button = touchpad_button | trackpoint_button; | ms->button = touchpad_button | trackpoint_button; | ||||
return (0); | return (0); | ||||
case ELANTECH_PKT_NOP: | case ELANTECH_PKT_NOP: | ||||
return (0); | return (0); | ||||
default: | default: | ||||
return (-1); | return (-1); | ||||
Show All 10 Lines | if (sc->elanhw.isclickpad) { | ||||
touchpad_button = | touchpad_button = | ||||
((pb->ipacket[0] & 0x03) ? MOUSE_BUTTON1DOWN : 0); | ((pb->ipacket[0] & 0x03) ? MOUSE_BUTTON1DOWN : 0); | ||||
} else { | } else { | ||||
touchpad_button = | touchpad_button = | ||||
((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) | | ((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) | | ||||
((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0); | ((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0); | ||||
} | } | ||||
#ifdef EVDEV_SUPPORT | |||||
if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) { | |||||
for (id = 0; id < ELANTECH_MAX_FINGERS; id++) { | |||||
if (PSM_FINGER_IS_SET(f[id])) { | |||||
psm_push_mt_finger(sc, id, &f[id]); | |||||
/* Convert touch width to surface units */ | |||||
evdev_push_abs(sc->evdev_a, ABS_MT_TOUCH_MAJOR, | |||||
f[id].w * sc->elanhw.dptracex); | |||||
} | |||||
if (sc->elanaction.mask & (1 << id) && | |||||
!(mask & (1 << id))) | |||||
psm_release_mt_slot(sc->evdev_a, id); | |||||
} | |||||
evdev_push_key(sc->evdev_a, BTN_TOUCH, nfingers > 0); | |||||
evdev_push_nfingers(sc->evdev_a, nfingers); | |||||
if (nfingers > 0) { | |||||
if (PSM_FINGER_IS_SET(f[0])) | |||||
psm_push_st_finger(sc, &f[0]); | |||||
} else | |||||
evdev_push_abs(sc->evdev_a, ABS_PRESSURE, 0); | |||||
evdev_push_mouse_btn(sc->evdev_a, touchpad_button); | |||||
evdev_sync(sc->evdev_a); | |||||
} | |||||
#endif | |||||
ms->button = touchpad_button | trackpoint_button; | ms->button = touchpad_button | trackpoint_button; | ||||
/* Send finger 1 position to gesture processor */ | /* Send finger 1 position to gesture processor */ | ||||
if (PSM_FINGER_IS_SET(f[0]) || PSM_FINGER_IS_SET(f[1]) || | if (PSM_FINGER_IS_SET(f[0]) || PSM_FINGER_IS_SET(f[1]) || | ||||
nfingers == 0) | nfingers == 0) | ||||
psmgestures(sc, &f[0], imin(nfingers, 3), ms); | psmgestures(sc, &f[0], imin(nfingers, 3), ms); | ||||
/* Send fingers positions to movement smoothers */ | /* Send fingers positions to movement smoothers */ | ||||
for (id = 0; id < PSM_FINGERS; id++) | for (id = 0; id < PSM_FINGERS; id++) | ||||
▲ Show 20 Lines • Show All 324 Lines • ▼ Show 20 Lines | case MOUSE_MODEL_ELANTECH: | ||||
break; | break; | ||||
case MOUSE_MODEL_TRACKPOINT: | case MOUSE_MODEL_TRACKPOINT: | ||||
case MOUSE_MODEL_GENERIC: | case MOUSE_MODEL_GENERIC: | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
#ifdef EVDEV_SUPPORT | |||||
if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE && | |||||
sc->hw.model != MOUSE_MODEL_ELANTECH && | |||||
sc->hw.model != MOUSE_MODEL_SYNAPTICS) { | |||||
evdev_push_rel(sc->evdev_r, EV_REL, x); | |||||
evdev_push_rel(sc->evdev_r, EV_REL, -y); | |||||
switch (sc->hw.model) { | |||||
case MOUSE_MODEL_EXPLORER: | |||||
case MOUSE_MODEL_INTELLI: | |||||
case MOUSE_MODEL_NET: | |||||
case MOUSE_MODEL_NETSCROLL: | |||||
case MOUSE_MODEL_4DPLUS: | |||||
evdev_push_rel(sc->evdev_r, REL_WHEEL, -z); | |||||
break; | |||||
case MOUSE_MODEL_MOUSEMANPLUS: | |||||
case MOUSE_MODEL_4D: | |||||
switch (z) { | |||||
case 1: | |||||
case -1: | |||||
evdev_push_rel(sc->evdev_r, REL_WHEEL, -z); | |||||
break; | |||||
case 2: | |||||
case -2: | |||||
evdev_push_rel(sc->evdev_r, REL_HWHEEL, z / 2); | |||||
break; | |||||
} | |||||
break; | |||||
} | |||||
evdev_push_mouse_btn(sc->evdev_r, ms.button); | |||||
evdev_sync(sc->evdev_r); | |||||
} | |||||
#endif | |||||
/* scale values */ | /* scale values */ | ||||
if (sc->mode.accelfactor >= 1) { | if (sc->mode.accelfactor >= 1) { | ||||
if (x != 0) { | if (x != 0) { | ||||
x = x * x / sc->mode.accelfactor; | x = x * x / sc->mode.accelfactor; | ||||
if (x == 0) | if (x == 0) | ||||
x = 1; | x = 1; | ||||
if (c & MOUSE_PS2_XNEG) | if (c & MOUSE_PS2_XNEG) | ||||
x = -x; | x = -x; | ||||
▲ Show 20 Lines • Show All 2,096 Lines • ▼ Show 20 Lines | psmresume(device_t dev) | ||||
} | } | ||||
VLOG(2, (LOG_DEBUG, "psm%d: system resume hook exiting.\n", unit)); | VLOG(2, (LOG_DEBUG, "psm%d: system resume hook exiting.\n", unit)); | ||||
return (err); | return (err); | ||||
} | } | ||||
DRIVER_MODULE(psm, atkbdc, psm_driver, psm_devclass, 0, 0); | DRIVER_MODULE(psm, atkbdc, psm_driver, psm_devclass, 0, 0); | ||||
#ifdef EVDEV_SUPPORT | |||||
MODULE_DEPEND(psm, evdev, 1, 1, 1); | |||||
#endif | |||||
#ifdef DEV_ISA | #ifdef DEV_ISA | ||||
/* | /* | ||||
* This sucks up assignments from PNPBIOS and ACPI. | * This sucks up assignments from PNPBIOS and ACPI. | ||||
*/ | */ | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 122 Lines • Show Last 20 Lines |