Lines 132-137
__FBSDID("$FreeBSD$");
Link Here
|
132 |
|
132 |
|
133 |
#define PSMCPNP_DRIVER_NAME "psmcpnp" |
133 |
#define PSMCPNP_DRIVER_NAME "psmcpnp" |
134 |
|
134 |
|
|
|
135 |
struct psmcpnp_softc { |
136 |
enum { |
137 |
PSMCPNP_GENERIC, |
138 |
PSMCPNP_FORCEPAD, |
139 |
PSMCPNP_HPSYN81, |
140 |
} type; /* Based on PnP ID */ |
141 |
}; |
142 |
|
135 |
/* input queue */ |
143 |
/* input queue */ |
136 |
#define PSM_BUFSIZE 960 |
144 |
#define PSM_BUFSIZE 960 |
137 |
#define PSM_SMALLBUFSIZE 240 |
145 |
#define PSM_SMALLBUFSIZE 240 |
Lines 167-172
typedef struct packetbuf {
Link Here
|
167 |
#define PSM_PACKETQUEUE 128 |
175 |
#define PSM_PACKETQUEUE 128 |
168 |
#endif |
176 |
#endif |
169 |
|
177 |
|
|
|
178 |
/* |
179 |
* Typical bezel limits. Taken from 'Synaptics |
180 |
* PS/2 TouchPad Interfacing Guide' p.3.2.3. |
181 |
*/ |
182 |
#define SYNAPTICS_DEFAULT_MAX_X 5472 |
183 |
#define SYNAPTICS_DEFAULT_MAX_Y 4448 |
184 |
#define SYNAPTICS_DEFAULT_MIN_X 1472 |
185 |
#define SYNAPTICS_DEFAULT_MIN_Y 1408 |
186 |
|
170 |
typedef struct synapticsinfo { |
187 |
typedef struct synapticsinfo { |
171 |
struct sysctl_ctx_list sysctl_ctx; |
188 |
struct sysctl_ctx_list sysctl_ctx; |
172 |
struct sysctl_oid *sysctl_tree; |
189 |
struct sysctl_oid *sysctl_tree; |
Lines 416-421
struct psm_softc { /* Driver status information */
Link Here
|
416 |
int squelch; /* level to filter movement at low speed */ |
433 |
int squelch; /* level to filter movement at low speed */ |
417 |
int syncerrors; /* # of bytes discarded to synchronize */ |
434 |
int syncerrors; /* # of bytes discarded to synchronize */ |
418 |
int pkterrors; /* # of packets failed during quaranteen. */ |
435 |
int pkterrors; /* # of packets failed during quaranteen. */ |
|
|
436 |
int fpcount; /* forcePad valid packet counter */ |
419 |
struct timeval inputtimeout; |
437 |
struct timeval inputtimeout; |
420 |
struct timeval lastsoftintr; /* time of last soft interrupt */ |
438 |
struct timeval lastsoftintr; /* time of last soft interrupt */ |
421 |
struct timeval lastinputerr; /* time last sync error happened */ |
439 |
struct timeval lastinputerr; /* time last sync error happened */ |
Lines 1088-1094
doopen(struct psm_softc *sc, int command_byte)
Link Here
|
1088 |
mouse_ext_command(sc->kbdc, 1); |
1106 |
mouse_ext_command(sc->kbdc, 1); |
1089 |
get_mouse_status(sc->kbdc, stat, 0, 3); |
1107 |
get_mouse_status(sc->kbdc, stat, 0, 3); |
1090 |
if ((SYNAPTICS_VERSION_GE(sc->synhw, 7, 5) || |
1108 |
if ((SYNAPTICS_VERSION_GE(sc->synhw, 7, 5) || |
1091 |
stat[1] == 0x47) && |
1109 |
stat[1] == 0x46 || stat[1] == 0x47) && |
1092 |
stat[2] == 0x40) { |
1110 |
stat[2] == 0x40) { |
1093 |
synaptics_set_mode(sc, synaptics_preferred_mode(sc)); |
1111 |
synaptics_set_mode(sc, synaptics_preferred_mode(sc)); |
1094 |
VLOG(5, (LOG_DEBUG, "psm%d: Synaptis Absolute Mode " |
1112 |
VLOG(5, (LOG_DEBUG, "psm%d: Synaptis Absolute Mode " |
Lines 3183-3189
proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
Link Here
|
3183 |
static int touchpad_buttons; |
3201 |
static int touchpad_buttons; |
3184 |
static int guest_buttons; |
3202 |
static int guest_buttons; |
3185 |
static finger_t f[PSM_FINGERS]; |
3203 |
static finger_t f[PSM_FINGERS]; |
3186 |
int w, id, nfingers, ewcode, extended_buttons; |
3204 |
int w, id, nfingers, ewcode, extended_buttons, clickpad_pressed; |
3187 |
|
3205 |
|
3188 |
extended_buttons = 0; |
3206 |
extended_buttons = 0; |
3189 |
|
3207 |
|
Lines 3445-3454
proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
Link Here
|
3445 |
extended_buttons |= sc->extended_buttons; |
3463 |
extended_buttons |= sc->extended_buttons; |
3446 |
} |
3464 |
} |
3447 |
} |
3465 |
} |
3448 |
/* Handle ClickPad */ |
|
|
3449 |
if (sc->synhw.capClickPad && |
3450 |
((pb->ipacket[0] ^ pb->ipacket[3]) & 0x01)) |
3451 |
touchpad_buttons |= MOUSE_BUTTON1DOWN; |
3452 |
|
3466 |
|
3453 |
if (sc->synhw.capReportsV && nfingers > 1) |
3467 |
if (sc->synhw.capReportsV && nfingers > 1) |
3454 |
f[0] = (finger_t) { |
3468 |
f[0] = (finger_t) { |
Lines 3481-3486
proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
Link Here
|
3481 |
if (f[0].p < sc->syninfo.min_pressure || f[0].x < 2) |
3495 |
if (f[0].p < sc->syninfo.min_pressure || f[0].x < 2) |
3482 |
nfingers = 0; |
3496 |
nfingers = 0; |
3483 |
|
3497 |
|
|
|
3498 |
/* Handle ClickPad */ |
3499 |
if (sc->synhw.capClickPad) { |
3500 |
clickpad_pressed = (pb->ipacket[0] ^ pb->ipacket[3]) & 0x01; |
3501 |
if (sc->synhw.forcePad) { |
3502 |
/* |
3503 |
* Forcepads erroneously report button click if there |
3504 |
* are 2 or more fingers on the touchpad breaking |
3505 |
* multifinger gestures. To workaround this start |
3506 |
* reporting a click only after 4 consecutive single |
3507 |
* touch packets has been received. |
3508 |
* Skip these packets in case more contacts appear. |
3509 |
*/ |
3510 |
switch (nfingers) { |
3511 |
case 0: |
3512 |
sc->fpcount = 0; |
3513 |
break; |
3514 |
case 1: |
3515 |
if (clickpad_pressed && sc->fpcount < INT_MAX) |
3516 |
++sc->fpcount; |
3517 |
/* FALLTHROUGH */ |
3518 |
default: |
3519 |
if (!clickpad_pressed) |
3520 |
sc->fpcount = 0; |
3521 |
if (sc->fpcount >= sc->syninfo.window_min) |
3522 |
touchpad_buttons |= MOUSE_BUTTON1DOWN; |
3523 |
} |
3524 |
} else if (clickpad_pressed) |
3525 |
touchpad_buttons |= MOUSE_BUTTON1DOWN; |
3526 |
} |
3527 |
|
3484 |
for (id = 0; id < PSM_FINGERS; id++) |
3528 |
for (id = 0; id < PSM_FINGERS; id++) |
3485 |
if (id >= nfingers) |
3529 |
if (id >= nfingers) |
3486 |
PSM_FINGER_RESET(f[id]); |
3530 |
PSM_FINGER_RESET(f[id]); |
Lines 6004-6013
synaptics_set_mode(struct psm_softc *sc, int mode_byte) {
Link Here
|
6004 |
static int |
6048 |
static int |
6005 |
enable_synaptics(struct psm_softc *sc, enum probearg arg) |
6049 |
enable_synaptics(struct psm_softc *sc, enum probearg arg) |
6006 |
{ |
6050 |
{ |
|
|
6051 |
device_t psmcpnp; |
6052 |
struct psmcpnp_softc *psmcpnp_sc; |
6007 |
KBDC kbdc = sc->kbdc; |
6053 |
KBDC kbdc = sc->kbdc; |
6008 |
synapticshw_t synhw; |
6054 |
synapticshw_t synhw; |
6009 |
int status[3]; |
6055 |
int status[3]; |
6010 |
int buttons; |
6056 |
int buttons, middle_byte; |
6011 |
|
6057 |
|
6012 |
VLOG(3, (LOG_DEBUG, "synaptics: BEGIN init\n")); |
6058 |
VLOG(3, (LOG_DEBUG, "synaptics: BEGIN init\n")); |
6013 |
|
6059 |
|
Lines 6024-6030
enable_synaptics(struct psm_softc *sc, enum probearg arg)
Link Here
|
6024 |
return (FALSE); |
6070 |
return (FALSE); |
6025 |
if (get_mouse_status(kbdc, status, 0, 3) != 3) |
6071 |
if (get_mouse_status(kbdc, status, 0, 3) != 3) |
6026 |
return (FALSE); |
6072 |
return (FALSE); |
6027 |
if (status[1] != 0x47) |
6073 |
middle_byte = status[1]; |
|
|
6074 |
if (middle_byte != 0x46 && middle_byte != 0x47) |
6028 |
return (FALSE); |
6075 |
return (FALSE); |
6029 |
|
6076 |
|
6030 |
bzero(&synhw, sizeof(synhw)); |
6077 |
bzero(&synhw, sizeof(synhw)); |
Lines 6035-6041
enable_synaptics(struct psm_softc *sc, enum probearg arg)
Link Here
|
6035 |
printf("Synaptics Touchpad v%d.%d\n", synhw.infoMajor, |
6082 |
printf("Synaptics Touchpad v%d.%d\n", synhw.infoMajor, |
6036 |
synhw.infoMinor); |
6083 |
synhw.infoMinor); |
6037 |
|
6084 |
|
6038 |
if (synhw.infoMajor < 4) { |
6085 |
/* |
|
|
6086 |
* Most synaptics touchpads return 0x47 in middle byte in responce to |
6087 |
* identify command as stated in p.4.4 of "Synaptics PS/2 TouchPad |
6088 |
* Interfacing Guide" and we only support v4.0 or better. But some |
6089 |
* devices return 0x46 here and have a different numbering scheme. |
6090 |
* In the case of 0x46, we allow versions as low as v2.0 |
6091 |
*/ |
6092 |
if ((middle_byte == 0x47 && synhw.infoMajor < 4) || |
6093 |
(middle_byte == 0x46 && synhw.infoMajor < 2)) { |
6039 |
printf(" Unsupported (pre-v4) Touchpad detected\n"); |
6094 |
printf(" Unsupported (pre-v4) Touchpad detected\n"); |
6040 |
return (FALSE); |
6095 |
return (FALSE); |
6041 |
} |
6096 |
} |
Lines 6076-6090
enable_synaptics(struct psm_softc *sc, enum probearg arg)
Link Here
|
6076 |
return (FALSE); |
6131 |
return (FALSE); |
6077 |
if (get_mouse_status(kbdc, status, 0, 3) != 3) |
6132 |
if (get_mouse_status(kbdc, status, 0, 3) != 3) |
6078 |
return (FALSE); |
6133 |
return (FALSE); |
6079 |
if (!SYNAPTICS_VERSION_GE(synhw, 7, 5) && status[1] != 0x47) { |
6134 |
if (!SYNAPTICS_VERSION_GE(synhw, 7, 5) && status[1] != middle_byte) { |
6080 |
printf(" Failed to read extended capability bits\n"); |
6135 |
printf(" Failed to read extended capability bits\n"); |
6081 |
return (FALSE); |
6136 |
return (FALSE); |
6082 |
} |
6137 |
} |
6083 |
|
6138 |
|
|
|
6139 |
psmcpnp = devclass_get_device(devclass_find(PSMCPNP_DRIVER_NAME), |
6140 |
sc->unit); |
6141 |
psmcpnp_sc = (psmcpnp != NULL) ? device_get_softc(psmcpnp) : NULL; |
6142 |
|
6143 |
/* |
6144 |
* Set conservative defaults for 0x46 middle byte touchpads |
6145 |
* as ExtendedQueries return bogus data. |
6146 |
*/ |
6147 |
if (middle_byte == 0x46) { |
6148 |
synhw.capExtended = 1; |
6149 |
synhw.capPalmDetect = 1; |
6150 |
synhw.capPassthrough = 1; |
6151 |
synhw.capMultiFinger = 1; |
6152 |
synhw.maximumXCoord = SYNAPTICS_DEFAULT_MAX_X; |
6153 |
synhw.maximumYCoord = SYNAPTICS_DEFAULT_MAX_Y; |
6154 |
synhw.minimumXCoord = SYNAPTICS_DEFAULT_MIN_X; |
6155 |
synhw.minimumYCoord = SYNAPTICS_DEFAULT_MIN_Y; |
6156 |
/* Enable multitouch mode for HW v8.1 devices */ |
6157 |
if (psmcpnp_sc != NULL && |
6158 |
psmcpnp_sc->type == PSMCPNP_HPSYN81) |
6159 |
synhw.capReportsV = 1; |
6160 |
} else |
6161 |
synhw.capExtended = (status[0] & 0x80) != 0; |
6162 |
|
6084 |
/* Set the different capabilities when they exist. */ |
6163 |
/* Set the different capabilities when they exist. */ |
6085 |
buttons = 0; |
6164 |
buttons = 0; |
6086 |
synhw.capExtended = (status[0] & 0x80) != 0; |
6165 |
if (synhw.capExtended && middle_byte == 0x47) { |
6087 |
if (synhw.capExtended) { |
|
|
6088 |
synhw.nExtendedQueries = (status[0] & 0x70) >> 4; |
6166 |
synhw.nExtendedQueries = (status[0] & 0x70) >> 4; |
6089 |
synhw.capMiddle = (status[0] & 0x04) != 0; |
6167 |
synhw.capMiddle = (status[0] & 0x04) != 0; |
6090 |
synhw.capPassthrough = (status[2] & 0x80) != 0; |
6168 |
synhw.capPassthrough = (status[2] & 0x80) != 0; |
Lines 6206-6217
enable_synaptics(struct psm_softc *sc, enum probearg arg)
Link Here
|
6206 |
synhw.maximumYCoord = (status[2] << 5) | |
6284 |
synhw.maximumYCoord = (status[2] << 5) | |
6207 |
((status[1] & 0xf0) >> 3); |
6285 |
((status[1] & 0xf0) >> 3); |
6208 |
} else { |
6286 |
} else { |
6209 |
/* |
6287 |
synhw.maximumXCoord = SYNAPTICS_DEFAULT_MAX_X; |
6210 |
* Typical bezel limits. Taken from 'Synaptics |
6288 |
synhw.maximumYCoord = SYNAPTICS_DEFAULT_MAX_Y; |
6211 |
* PS/2 * TouchPad Interfacing Guide' p.3.2.3. |
|
|
6212 |
*/ |
6213 |
synhw.maximumXCoord = 5472; |
6214 |
synhw.maximumYCoord = 4448; |
6215 |
} |
6289 |
} |
6216 |
|
6290 |
|
6217 |
if (synhw.capReportsMin) { |
6291 |
if (synhw.capReportsMin) { |
Lines 6227-6238
enable_synaptics(struct psm_softc *sc, enum probearg arg)
Link Here
|
6227 |
synhw.minimumYCoord = (status[2] << 5) | |
6301 |
synhw.minimumYCoord = (status[2] << 5) | |
6228 |
((status[1] & 0xf0) >> 3); |
6302 |
((status[1] & 0xf0) >> 3); |
6229 |
} else { |
6303 |
} else { |
6230 |
/* |
6304 |
synhw.minimumXCoord = SYNAPTICS_DEFAULT_MIN_X; |
6231 |
* Typical bezel limits. Taken from 'Synaptics |
6305 |
synhw.minimumYCoord = SYNAPTICS_DEFAULT_MIN_Y; |
6232 |
* PS/2 * TouchPad Interfacing Guide' p.3.2.3. |
6306 |
} |
6233 |
*/ |
6307 |
|
6234 |
synhw.minimumXCoord = 1472; |
6308 |
/* |
6235 |
synhw.minimumYCoord = 1408; |
6309 |
* ClickPad properties are not exported through PS/2 |
|
|
6310 |
* protocol. Detection is based on controller's PnP ID. |
6311 |
*/ |
6312 |
if (synhw.capClickPad && psmcpnp_sc != NULL) { |
6313 |
switch (psmcpnp_sc->type) { |
6314 |
case PSMCPNP_FORCEPAD: |
6315 |
synhw.forcePad = 1; |
6316 |
break; |
6317 |
default: |
6318 |
break; |
6319 |
} |
6236 |
} |
6320 |
} |
6237 |
|
6321 |
|
6238 |
if (verbose >= 2) { |
6322 |
if (verbose >= 2) { |
Lines 6271-6276
enable_synaptics(struct psm_softc *sc, enum probearg arg)
Link Here
|
6271 |
printf(" minimumYCoord: %d\n", |
6355 |
printf(" minimumYCoord: %d\n", |
6272 |
synhw.minimumYCoord); |
6356 |
synhw.minimumYCoord); |
6273 |
} |
6357 |
} |
|
|
6358 |
if (synhw.capClickPad) { |
6359 |
printf(" forcePad: %d\n", |
6360 |
synhw.forcePad); |
6361 |
} |
6274 |
} |
6362 |
} |
6275 |
buttons += synhw.capClickPad; |
6363 |
buttons += synhw.capClickPad; |
6276 |
} |
6364 |
} |
Lines 6300-6306
enable_synaptics(struct psm_softc *sc, enum probearg arg)
Link Here
|
6300 |
return (FALSE); |
6388 |
return (FALSE); |
6301 |
if (get_mouse_status(kbdc, status, 0, 3) != 3) |
6389 |
if (get_mouse_status(kbdc, status, 0, 3) != 3) |
6302 |
return (FALSE); |
6390 |
return (FALSE); |
6303 |
if (!SYNAPTICS_VERSION_GE(synhw, 7, 5) && status[1] != 0x47) { |
6391 |
if (!SYNAPTICS_VERSION_GE(synhw, 7, 5) && status[1] != middle_byte) { |
6304 |
printf(" Failed to read mode byte\n"); |
6392 |
printf(" Failed to read mode byte\n"); |
6305 |
return (FALSE); |
6393 |
return (FALSE); |
6306 |
} |
6394 |
} |
Lines 7096-7102
static device_method_t psmcpnp_methods[] = {
Link Here
|
7096 |
static driver_t psmcpnp_driver = { |
7184 |
static driver_t psmcpnp_driver = { |
7097 |
PSMCPNP_DRIVER_NAME, |
7185 |
PSMCPNP_DRIVER_NAME, |
7098 |
psmcpnp_methods, |
7186 |
psmcpnp_methods, |
7099 |
1, /* no softc */ |
7187 |
sizeof(struct psmcpnp_softc), |
7100 |
}; |
7188 |
}; |
7101 |
|
7189 |
|
7102 |
static struct isa_pnp_id psmcpnp_ids[] = { |
7190 |
static struct isa_pnp_id psmcpnp_ids[] = { |
Lines 7116-7121
static struct isa_pnp_id psmcpnp_ids[] = {
Link Here
|
7116 |
{ 0 } |
7204 |
{ 0 } |
7117 |
}; |
7205 |
}; |
7118 |
|
7206 |
|
|
|
7207 |
static struct isa_pnp_id forcepad_ids[] = { |
7208 |
{ 0x0d302e4f, "HP PS/2 forcepad port" }, /* SYN300D, EB 1040 */ |
7209 |
{ 0x14302e4f, "HP PS/2 forcepad port" }, /* SYN3014, EB 1040 */ |
7210 |
{ 0 } |
7211 |
}; |
7212 |
|
7213 |
/* List of HW v8.1 synaptics touchpads erroneously detected as HW v2.0 */ |
7214 |
static struct isa_pnp_id hpsyn81_ids[] = { |
7215 |
{ 0x9e012e4f, "HP PS/2 trackpad port" }, /* SYN019E, EB 9470 */ |
7216 |
{ 0 } |
7217 |
}; |
7218 |
|
7119 |
static int |
7219 |
static int |
7120 |
create_a_copy(device_t atkbdc, device_t me) |
7220 |
create_a_copy(device_t atkbdc, device_t me) |
7121 |
{ |
7221 |
{ |
Lines 7142-7152
create_a_copy(device_t atkbdc, device_t me)
Link Here
|
7142 |
static int |
7242 |
static int |
7143 |
psmcpnp_probe(device_t dev) |
7243 |
psmcpnp_probe(device_t dev) |
7144 |
{ |
7244 |
{ |
|
|
7245 |
struct psmcpnp_softc *sc = device_get_softc(dev); |
7145 |
struct resource *res; |
7246 |
struct resource *res; |
7146 |
u_long irq; |
7247 |
u_long irq; |
7147 |
int rid; |
7248 |
int rid; |
7148 |
|
7249 |
|
7149 |
if (ISA_PNP_PROBE(device_get_parent(dev), dev, psmcpnp_ids)) |
7250 |
if (ISA_PNP_PROBE(device_get_parent(dev), dev, forcepad_ids) == 0) |
|
|
7251 |
sc->type = PSMCPNP_FORCEPAD; |
7252 |
else if(ISA_PNP_PROBE(device_get_parent(dev), dev, hpsyn81_ids) == 0) |
7253 |
sc->type = PSMCPNP_HPSYN81; |
7254 |
else if (ISA_PNP_PROBE(device_get_parent(dev), dev, psmcpnp_ids) == 0) |
7255 |
sc->type = PSMCPNP_GENERIC; |
7256 |
else |
7150 |
return (ENXIO); |
7257 |
return (ENXIO); |
7151 |
|
7258 |
|
7152 |
/* |
7259 |
/* |