pms.c 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488
  1. /* $OpenBSD: pms.c,v 1.64 2015/07/20 00:55:06 kspillner Exp $ */
  2. /* $NetBSD: psm.c,v 1.11 2000/06/05 22:20:57 sommerfeld Exp $ */
  3. /*-
  4. * Copyright (c) 1994 Charles M. Hannum.
  5. * Copyright (c) 1992, 1993 Erik Forsberg.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
  15. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  16. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
  17. * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  18. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  19. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  20. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  21. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  22. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  23. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #include <sys/param.h>
  26. #include <sys/systm.h>
  27. #include <sys/rwlock.h>
  28. #include <sys/device.h>
  29. #include <sys/ioctl.h>
  30. #include <sys/malloc.h>
  31. #include <machine/bus.h>
  32. #include <dev/ic/pckbcvar.h>
  33. #include <dev/pckbc/pmsreg.h>
  34. #include <dev/wscons/wsconsio.h>
  35. #include <dev/wscons/wsmousevar.h>
  36. #if defined(__i386__) || defined(__amd64__)
  37. #include "acpi.h"
  38. #endif
  39. #if !defined(SMALL_KERNEL) && NACPI > 0
  40. extern int mouse_has_softbtn;
  41. #else
  42. int mouse_has_softbtn;
  43. #endif
  44. #ifdef DEBUG
  45. #define DPRINTF(x...) do { printf(x); } while (0);
  46. #else
  47. #define DPRINTF(x...)
  48. #endif
  49. #define DEVNAME(sc) ((sc)->sc_dev.dv_xname)
  50. #define WSMOUSE_BUTTON(x) (1 << ((x) - 1))
  51. struct pms_softc;
  52. struct pms_protocol {
  53. int type;
  54. #define PMS_STANDARD 0
  55. #define PMS_INTELLI 1
  56. #define PMS_SYNAPTICS 2
  57. #define PMS_ALPS 3
  58. #define PMS_ELANTECH_V1 4
  59. #define PMS_ELANTECH_V2 5
  60. #define PMS_ELANTECH_V3 6
  61. #define PMS_ELANTECH_V4 7
  62. u_int packetsize;
  63. int (*enable)(struct pms_softc *);
  64. int (*ioctl)(struct pms_softc *, u_long, caddr_t, int, struct proc *);
  65. int (*sync)(struct pms_softc *, int);
  66. void (*proc)(struct pms_softc *);
  67. void (*disable)(struct pms_softc *);
  68. };
  69. struct synaptics_softc {
  70. int identify;
  71. int capabilities, ext_capabilities, ext2_capabilities;
  72. int model, ext_model;
  73. int resolution, dimension;
  74. int modes;
  75. int mode;
  76. int mask;
  77. #define SYNAPTICS_MASK_NEWABS_STRICT 0xc8
  78. #define SYNAPTICS_MASK_NEWABS_RELAXED 0xc0
  79. #define SYNAPTICS_VALID_NEWABS_FIRST 0x80
  80. #define SYNAPTICS_VALID_NEWABS_NEXT 0xc0
  81. int res_x, res_y;
  82. int min_x, min_y;
  83. int max_x, max_y;
  84. /* Compat mode */
  85. int wsmode;
  86. int old_x, old_y;
  87. u_int old_buttons;
  88. u_int sec_buttons;
  89. #define SYNAPTICS_SCALE 4
  90. #define SYNAPTICS_PRESSURE 30
  91. };
  92. struct alps_softc {
  93. int model;
  94. #define ALPS_GLIDEPOINT (1 << 1)
  95. #define ALPS_DUALPOINT (1 << 2)
  96. #define ALPS_PASSTHROUGH (1 << 3)
  97. #define ALPS_INTERLEAVED (1 << 4)
  98. int mask;
  99. int version;
  100. int min_x, min_y;
  101. int max_x, max_y;
  102. int old_fin;
  103. u_int sec_buttons; /* trackpoint */
  104. /* Compat mode */
  105. int wsmode;
  106. int old_x, old_y;
  107. u_int old_buttons;
  108. #define ALPS_PRESSURE 40
  109. };
  110. struct elantech_softc {
  111. int flags;
  112. #define ELANTECH_F_REPORTS_PRESSURE 0x01
  113. #define ELANTECH_F_HAS_ROCKER 0x02
  114. #define ELANTECH_F_2FINGER_PACKET 0x04
  115. #define ELANTECH_F_HW_V1_OLD 0x08
  116. #define ELANTECH_F_CRC_ENABLED 0x10
  117. int fw_version;
  118. int min_x, min_y;
  119. int max_x, max_y;
  120. struct {
  121. unsigned int x;
  122. unsigned int y;
  123. unsigned int z;
  124. } mt[ELANTECH_MAX_FINGERS];
  125. int mt_slots;
  126. int mt_count;
  127. int mt_filter;
  128. int mt_lastid;
  129. int mt_lastcount;
  130. int mt_buttons;
  131. int width;
  132. u_char parity[256];
  133. u_char p1, p2, p3;
  134. /* Compat mode */
  135. int wsmode;
  136. int old_x, old_y;
  137. u_int old_buttons;
  138. };
  139. struct pms_softc { /* driver status information */
  140. struct device sc_dev;
  141. pckbc_tag_t sc_kbctag;
  142. int sc_state;
  143. #define PMS_STATE_DISABLED 0
  144. #define PMS_STATE_ENABLED 1
  145. #define PMS_STATE_SUSPENDED 2
  146. struct rwlock sc_state_lock;
  147. int sc_dev_enable;
  148. #define PMS_DEV_IGNORE 0x00
  149. #define PMS_DEV_PRIMARY 0x01
  150. #define PMS_DEV_SECONDARY 0x02
  151. int poll;
  152. int inputstate;
  153. const struct pms_protocol *protocol;
  154. struct synaptics_softc *synaptics;
  155. struct alps_softc *alps;
  156. struct elantech_softc *elantech;
  157. u_char packet[8];
  158. struct device *sc_wsmousedev;
  159. struct device *sc_sec_wsmousedev;
  160. };
  161. static const u_int butmap[8] = {
  162. 0,
  163. WSMOUSE_BUTTON(1),
  164. WSMOUSE_BUTTON(3),
  165. WSMOUSE_BUTTON(1) | WSMOUSE_BUTTON(3),
  166. WSMOUSE_BUTTON(2),
  167. WSMOUSE_BUTTON(1) | WSMOUSE_BUTTON(2),
  168. WSMOUSE_BUTTON(2) | WSMOUSE_BUTTON(3),
  169. WSMOUSE_BUTTON(1) | WSMOUSE_BUTTON(2) | WSMOUSE_BUTTON(3)
  170. };
  171. static const struct alps_model {
  172. int version;
  173. int mask;
  174. int model;
  175. } alps_models[] = {
  176. { 0x2021, 0xf8, ALPS_DUALPOINT | ALPS_PASSTHROUGH },
  177. { 0x2221, 0xf8, ALPS_DUALPOINT | ALPS_PASSTHROUGH },
  178. { 0x2222, 0xff, ALPS_DUALPOINT | ALPS_PASSTHROUGH },
  179. { 0x3222, 0xf8, ALPS_DUALPOINT | ALPS_PASSTHROUGH },
  180. { 0x5212, 0xff, ALPS_DUALPOINT | ALPS_PASSTHROUGH | ALPS_INTERLEAVED },
  181. { 0x5321, 0xf8, ALPS_GLIDEPOINT },
  182. { 0x5322, 0xf8, ALPS_GLIDEPOINT },
  183. { 0x603b, 0xf8, ALPS_GLIDEPOINT },
  184. { 0x6222, 0xcf, ALPS_DUALPOINT | ALPS_PASSTHROUGH | ALPS_INTERLEAVED },
  185. { 0x6321, 0xf8, ALPS_GLIDEPOINT },
  186. { 0x6322, 0xf8, ALPS_GLIDEPOINT },
  187. { 0x6323, 0xf8, ALPS_GLIDEPOINT },
  188. { 0x6324, 0x8f, ALPS_GLIDEPOINT },
  189. { 0x6325, 0xef, ALPS_GLIDEPOINT },
  190. { 0x6326, 0xf8, ALPS_GLIDEPOINT },
  191. { 0x7301, 0xf8, ALPS_DUALPOINT },
  192. { 0x7321, 0xf8, ALPS_GLIDEPOINT },
  193. { 0x7322, 0xf8, ALPS_GLIDEPOINT },
  194. { 0x7325, 0xcf, ALPS_GLIDEPOINT },
  195. #if 0
  196. /*
  197. * This model has a clitpad sending almost compatible PS2
  198. * packets but not compatible enough to be used with the
  199. * ALPS protocol.
  200. */
  201. { 0x633b, 0xf8, ALPS_DUALPOINT | ALPS_PASSTHROUGH },
  202. { 0x7326, 0, 0 }, /* XXX Uses unknown v3 protocol */
  203. #endif
  204. };
  205. int pmsprobe(struct device *, void *, void *);
  206. void pmsattach(struct device *, struct device *, void *);
  207. int pmsactivate(struct device *, int);
  208. void pmsinput(void *, int);
  209. int pms_change_state(struct pms_softc *, int, int);
  210. int pms_ioctl(void *, u_long, caddr_t, int, struct proc *);
  211. int pms_enable(void *);
  212. void pms_disable(void *);
  213. int pms_sec_ioctl(void *, u_long, caddr_t, int, struct proc *);
  214. int pms_sec_enable(void *);
  215. void pms_sec_disable(void *);
  216. int pms_cmd(struct pms_softc *, u_char *, int, u_char *, int);
  217. int pms_spec_cmd(struct pms_softc *, int);
  218. int pms_get_devid(struct pms_softc *, u_char *);
  219. int pms_get_status(struct pms_softc *, u_char *);
  220. int pms_set_rate(struct pms_softc *, int);
  221. int pms_set_resolution(struct pms_softc *, int);
  222. int pms_set_scaling(struct pms_softc *, int);
  223. int pms_reset(struct pms_softc *);
  224. int pms_dev_enable(struct pms_softc *);
  225. int pms_dev_disable(struct pms_softc *);
  226. void pms_protocol_lookup(struct pms_softc *);
  227. int pms_enable_intelli(struct pms_softc *);
  228. int pms_ioctl_mouse(struct pms_softc *, u_long, caddr_t, int, struct proc *);
  229. int pms_sync_mouse(struct pms_softc *, int);
  230. void pms_proc_mouse(struct pms_softc *);
  231. int pms_enable_synaptics(struct pms_softc *);
  232. int pms_ioctl_synaptics(struct pms_softc *, u_long, caddr_t, int, struct proc *);
  233. int pms_sync_synaptics(struct pms_softc *, int);
  234. void pms_proc_synaptics(struct pms_softc *);
  235. void pms_disable_synaptics(struct pms_softc *);
  236. int pms_enable_alps(struct pms_softc *);
  237. int pms_ioctl_alps(struct pms_softc *, u_long, caddr_t, int, struct proc *);
  238. int pms_sync_alps(struct pms_softc *, int);
  239. void pms_proc_alps(struct pms_softc *);
  240. int pms_enable_elantech_v1(struct pms_softc *);
  241. int pms_enable_elantech_v2(struct pms_softc *);
  242. int pms_enable_elantech_v3(struct pms_softc *);
  243. int pms_enable_elantech_v4(struct pms_softc *);
  244. int pms_ioctl_elantech(struct pms_softc *, u_long, caddr_t, int,
  245. struct proc *);
  246. int pms_sync_elantech_v1(struct pms_softc *, int);
  247. int pms_sync_elantech_v2(struct pms_softc *, int);
  248. int pms_sync_elantech_v3(struct pms_softc *, int);
  249. int pms_sync_elantech_v4(struct pms_softc *, int);
  250. void pms_proc_elantech_v1(struct pms_softc *);
  251. void pms_proc_elantech_v2(struct pms_softc *);
  252. void pms_proc_elantech_v3(struct pms_softc *);
  253. void pms_proc_elantech_v4(struct pms_softc *);
  254. int synaptics_knock(struct pms_softc *);
  255. int synaptics_set_mode(struct pms_softc *, int);
  256. int synaptics_query(struct pms_softc *, int, int *);
  257. int synaptics_get_hwinfo(struct pms_softc *);
  258. void synaptics_sec_proc(struct pms_softc *);
  259. int alps_sec_proc(struct pms_softc *);
  260. int alps_get_hwinfo(struct pms_softc *);
  261. int elantech_knock(struct pms_softc *);
  262. void elantech_send_input(struct pms_softc *, int, int, int, int);
  263. int elantech_get_hwinfo_v1(struct pms_softc *);
  264. int elantech_get_hwinfo_v2(struct pms_softc *);
  265. int elantech_get_hwinfo_v3(struct pms_softc *);
  266. int elantech_get_hwinfo_v4(struct pms_softc *);
  267. int elantech_ps2_cmd(struct pms_softc *, u_char);
  268. int elantech_set_absolute_mode_v1(struct pms_softc *);
  269. int elantech_set_absolute_mode_v2(struct pms_softc *);
  270. int elantech_set_absolute_mode_v3(struct pms_softc *);
  271. int elantech_set_absolute_mode_v4(struct pms_softc *);
  272. void elantech_send_mt_input(struct pms_softc *, int);
  273. struct cfattach pms_ca = {
  274. sizeof(struct pms_softc), pmsprobe, pmsattach, NULL,
  275. pmsactivate
  276. };
  277. struct cfdriver pms_cd = {
  278. NULL, "pms", DV_DULL
  279. };
  280. const struct wsmouse_accessops pms_accessops = {
  281. pms_enable,
  282. pms_ioctl,
  283. pms_disable,
  284. };
  285. const struct wsmouse_accessops pms_sec_accessops = {
  286. pms_sec_enable,
  287. pms_sec_ioctl,
  288. pms_sec_disable,
  289. };
  290. const struct pms_protocol pms_protocols[] = {
  291. /* Generic PS/2 mouse */
  292. {
  293. PMS_STANDARD, 3,
  294. NULL,
  295. pms_ioctl_mouse,
  296. pms_sync_mouse,
  297. pms_proc_mouse,
  298. NULL
  299. },
  300. /* Synaptics touchpad */
  301. {
  302. PMS_SYNAPTICS, 6,
  303. pms_enable_synaptics,
  304. pms_ioctl_synaptics,
  305. pms_sync_synaptics,
  306. pms_proc_synaptics,
  307. pms_disable_synaptics
  308. },
  309. /* ALPS touchpad */
  310. {
  311. PMS_ALPS, 6,
  312. pms_enable_alps,
  313. pms_ioctl_alps,
  314. pms_sync_alps,
  315. pms_proc_alps,
  316. NULL
  317. },
  318. /* Elantech touchpad (hardware version 1) */
  319. {
  320. PMS_ELANTECH_V1, 4,
  321. pms_enable_elantech_v1,
  322. pms_ioctl_elantech,
  323. pms_sync_elantech_v1,
  324. pms_proc_elantech_v1,
  325. NULL
  326. },
  327. /* Elantech touchpad (hardware version 2) */
  328. {
  329. PMS_ELANTECH_V2, 6,
  330. pms_enable_elantech_v2,
  331. pms_ioctl_elantech,
  332. pms_sync_elantech_v2,
  333. pms_proc_elantech_v2,
  334. NULL
  335. },
  336. /* Elantech touchpad (hardware version 3) */
  337. {
  338. PMS_ELANTECH_V3, 6,
  339. pms_enable_elantech_v3,
  340. pms_ioctl_elantech,
  341. pms_sync_elantech_v3,
  342. pms_proc_elantech_v3,
  343. NULL
  344. },
  345. /* Elantech touchpad (hardware version 4) */
  346. {
  347. PMS_ELANTECH_V4, 6,
  348. pms_enable_elantech_v4,
  349. pms_ioctl_elantech,
  350. pms_sync_elantech_v4,
  351. pms_proc_elantech_v4,
  352. NULL
  353. },
  354. /* Microsoft IntelliMouse */
  355. {
  356. PMS_INTELLI, 4,
  357. pms_enable_intelli,
  358. pms_ioctl_mouse,
  359. pms_sync_mouse,
  360. pms_proc_mouse,
  361. NULL
  362. },
  363. };
  364. int
  365. pms_cmd(struct pms_softc *sc, u_char *cmd, int len, u_char *resp, int resplen)
  366. {
  367. if (sc->poll) {
  368. return pckbc_poll_cmd(sc->sc_kbctag, PCKBC_AUX_SLOT,
  369. cmd, len, resplen, resp, 1);
  370. } else {
  371. return pckbc_enqueue_cmd(sc->sc_kbctag, PCKBC_AUX_SLOT,
  372. cmd, len, resplen, 1, resp);
  373. }
  374. }
  375. int
  376. pms_spec_cmd(struct pms_softc *sc, int cmd)
  377. {
  378. if (pms_set_scaling(sc, 1) ||
  379. pms_set_resolution(sc, (cmd >> 6) & 0x03) ||
  380. pms_set_resolution(sc, (cmd >> 4) & 0x03) ||
  381. pms_set_resolution(sc, (cmd >> 2) & 0x03) ||
  382. pms_set_resolution(sc, (cmd >> 0) & 0x03))
  383. return (-1);
  384. return (0);
  385. }
  386. int
  387. pms_get_devid(struct pms_softc *sc, u_char *resp)
  388. {
  389. u_char cmd[1];
  390. cmd[0] = PMS_SEND_DEV_ID;
  391. return (pms_cmd(sc, cmd, 1, resp, 1));
  392. }
  393. int
  394. pms_get_status(struct pms_softc *sc, u_char *resp)
  395. {
  396. u_char cmd[1];
  397. cmd[0] = PMS_SEND_DEV_STATUS;
  398. return (pms_cmd(sc, cmd, 1, resp, 3));
  399. }
  400. int
  401. pms_set_rate(struct pms_softc *sc, int value)
  402. {
  403. u_char cmd[2];
  404. cmd[0] = PMS_SET_SAMPLE;
  405. cmd[1] = value;
  406. return (pms_cmd(sc, cmd, 2, NULL, 0));
  407. }
  408. int
  409. pms_set_resolution(struct pms_softc *sc, int value)
  410. {
  411. u_char cmd[2];
  412. cmd[0] = PMS_SET_RES;
  413. cmd[1] = value;
  414. return (pms_cmd(sc, cmd, 2, NULL, 0));
  415. }
  416. int
  417. pms_set_scaling(struct pms_softc *sc, int scale)
  418. {
  419. u_char cmd[1];
  420. switch (scale) {
  421. case 1:
  422. default:
  423. cmd[0] = PMS_SET_SCALE11;
  424. break;
  425. case 2:
  426. cmd[0] = PMS_SET_SCALE21;
  427. break;
  428. }
  429. return (pms_cmd(sc, cmd, 1, NULL, 0));
  430. }
  431. int
  432. pms_reset(struct pms_softc *sc)
  433. {
  434. u_char cmd[1], resp[2];
  435. int res;
  436. cmd[0] = PMS_RESET;
  437. res = pms_cmd(sc, cmd, 1, resp, 2);
  438. #ifdef DEBUG
  439. if (res || resp[0] != PMS_RSTDONE || resp[1] != 0)
  440. printf("%s: reset error %d (response 0x%02x, type 0x%02x)\n",
  441. DEVNAME(sc), res, resp[0], resp[1]);
  442. #endif
  443. return (res);
  444. }
  445. int
  446. pms_dev_enable(struct pms_softc *sc)
  447. {
  448. u_char cmd[1];
  449. int res;
  450. cmd[0] = PMS_DEV_ENABLE;
  451. res = pms_cmd(sc, cmd, 1, NULL, 0);
  452. if (res)
  453. printf("%s: enable error\n", DEVNAME(sc));
  454. return (res);
  455. }
  456. int
  457. pms_dev_disable(struct pms_softc *sc)
  458. {
  459. u_char cmd[1];
  460. int res;
  461. cmd[0] = PMS_DEV_DISABLE;
  462. res = pms_cmd(sc, cmd, 1, NULL, 0);
  463. if (res)
  464. printf("%s: disable error\n", DEVNAME(sc));
  465. return (res);
  466. }
  467. void
  468. pms_protocol_lookup(struct pms_softc *sc)
  469. {
  470. int i;
  471. sc->protocol = &pms_protocols[0];
  472. for (i = 1; i < nitems(pms_protocols); i++) {
  473. pms_reset(sc);
  474. if (pms_protocols[i].enable(sc)) {
  475. sc->protocol = &pms_protocols[i];
  476. break;
  477. }
  478. }
  479. DPRINTF("%s: protocol type %d\n", DEVNAME(sc), sc->protocol->type);
  480. }
  481. int
  482. pms_enable_intelli(struct pms_softc *sc)
  483. {
  484. u_char resp;
  485. /* the special sequence to enable the third button and the roller */
  486. if (pms_set_rate(sc, PMS_INTELLI_MAGIC1) ||
  487. pms_set_rate(sc, PMS_INTELLI_MAGIC2) ||
  488. pms_set_rate(sc, PMS_INTELLI_MAGIC3) ||
  489. pms_get_devid(sc, &resp) ||
  490. resp != PMS_INTELLI_ID)
  491. return (0);
  492. return (1);
  493. }
  494. int
  495. pms_ioctl_mouse(struct pms_softc *sc, u_long cmd, caddr_t data, int flag,
  496. struct proc *p)
  497. {
  498. int i;
  499. switch (cmd) {
  500. case WSMOUSEIO_GTYPE:
  501. *(u_int *)data = WSMOUSE_TYPE_PS2;
  502. break;
  503. case WSMOUSEIO_SRES:
  504. i = ((int) *(u_int *)data - 12) / 25;
  505. /* valid values are {0,1,2,3} */
  506. if (i < 0)
  507. i = 0;
  508. if (i > 3)
  509. i = 3;
  510. if (pms_set_resolution(sc, i))
  511. printf("%s: SET_RES command error\n", DEVNAME(sc));
  512. break;
  513. default:
  514. return (-1);
  515. }
  516. return (0);
  517. }
  518. int
  519. pms_sync_mouse(struct pms_softc *sc, int data)
  520. {
  521. if (sc->inputstate != 0)
  522. return (0);
  523. switch (sc->protocol->type) {
  524. case PMS_STANDARD:
  525. if ((data & 0xc0) != 0)
  526. return (-1);
  527. break;
  528. case PMS_INTELLI:
  529. if ((data & 0x08) != 0x08)
  530. return (-1);
  531. break;
  532. }
  533. return (0);
  534. }
  535. void
  536. pms_proc_mouse(struct pms_softc *sc)
  537. {
  538. u_int buttons;
  539. int dx, dy, dz;
  540. buttons = butmap[sc->packet[0] & PMS_PS2_BUTTONSMASK];
  541. dx = (sc->packet[0] & PMS_PS2_XNEG) ?
  542. (int)sc->packet[1] - 256 : sc->packet[1];
  543. dy = (sc->packet[0] & PMS_PS2_YNEG) ?
  544. (int)sc->packet[2] - 256 : sc->packet[2];
  545. if (sc->protocol->type == PMS_INTELLI)
  546. dz = (signed char)sc->packet[3];
  547. else
  548. dz = 0;
  549. wsmouse_input(sc->sc_wsmousedev,
  550. buttons, dx, dy, dz, 0, WSMOUSE_INPUT_DELTA);
  551. }
  552. int
  553. pmsprobe(struct device *parent, void *match, void *aux)
  554. {
  555. struct pckbc_attach_args *pa = aux;
  556. u_char cmd[1], resp[2];
  557. int res;
  558. if (pa->pa_slot != PCKBC_AUX_SLOT)
  559. return (0);
  560. /* Flush any garbage. */
  561. pckbc_flush(pa->pa_tag, pa->pa_slot);
  562. /* reset the device */
  563. cmd[0] = PMS_RESET;
  564. res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1);
  565. if (res || resp[0] != PMS_RSTDONE || resp[1] != 0) {
  566. #ifdef DEBUG
  567. printf("pms: reset error %d (response 0x%02x, type 0x%02x)\n",
  568. res, resp[0], resp[1]);
  569. #endif
  570. return (0);
  571. }
  572. return (1);
  573. }
  574. void
  575. pmsattach(struct device *parent, struct device *self, void *aux)
  576. {
  577. struct pms_softc *sc = (void *)self;
  578. struct pckbc_attach_args *pa = aux;
  579. struct wsmousedev_attach_args a;
  580. sc->sc_kbctag = pa->pa_tag;
  581. pckbc_set_inputhandler(sc->sc_kbctag, PCKBC_AUX_SLOT,
  582. pmsinput, sc, DEVNAME(sc));
  583. printf("\n");
  584. a.accessops = &pms_accessops;
  585. a.accesscookie = sc;
  586. rw_init(&sc->sc_state_lock, "pmsst");
  587. /*
  588. * Attach the wsmouse, saving a handle to it.
  589. * Note that we don't need to check this pointer against NULL
  590. * here or in pmsintr, because if this fails pms_enable() will
  591. * never be called, so pmsinput() will never be called.
  592. */
  593. sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
  594. sc->poll = 1;
  595. sc->sc_dev_enable = 0;
  596. /* See if the device understands an extended (touchpad) protocol. */
  597. pms_protocol_lookup(sc);
  598. /* no interrupts until enabled */
  599. pms_change_state(sc, PMS_STATE_DISABLED, PMS_DEV_IGNORE);
  600. }
  601. int
  602. pmsactivate(struct device *self, int act)
  603. {
  604. struct pms_softc *sc = (struct pms_softc *)self;
  605. switch (act) {
  606. case DVACT_SUSPEND:
  607. if (sc->sc_state == PMS_STATE_ENABLED)
  608. pms_change_state(sc, PMS_STATE_SUSPENDED,
  609. PMS_DEV_IGNORE);
  610. break;
  611. case DVACT_RESUME:
  612. if (sc->sc_state == PMS_STATE_SUSPENDED)
  613. pms_change_state(sc, PMS_STATE_ENABLED,
  614. PMS_DEV_IGNORE);
  615. break;
  616. }
  617. return (0);
  618. }
  619. int
  620. pms_change_state(struct pms_softc *sc, int newstate, int dev)
  621. {
  622. if (dev != PMS_DEV_IGNORE) {
  623. switch (newstate) {
  624. case PMS_STATE_ENABLED:
  625. if (sc->sc_dev_enable & dev)
  626. return (EBUSY);
  627. sc->sc_dev_enable |= dev;
  628. if (sc->sc_state == PMS_STATE_ENABLED)
  629. return (0);
  630. break;
  631. case PMS_STATE_DISABLED:
  632. sc->sc_dev_enable &= ~dev;
  633. if (sc->sc_dev_enable)
  634. return (0);
  635. break;
  636. }
  637. }
  638. switch (newstate) {
  639. case PMS_STATE_ENABLED:
  640. sc->inputstate = 0;
  641. pckbc_slot_enable(sc->sc_kbctag, PCKBC_AUX_SLOT, 1);
  642. if (sc->poll)
  643. pckbc_flush(sc->sc_kbctag, PCKBC_AUX_SLOT);
  644. pms_reset(sc);
  645. if (sc->protocol->enable != NULL &&
  646. sc->protocol->enable(sc) == 0)
  647. pms_protocol_lookup(sc);
  648. pms_dev_enable(sc);
  649. break;
  650. case PMS_STATE_DISABLED:
  651. case PMS_STATE_SUSPENDED:
  652. pms_dev_disable(sc);
  653. if (sc->protocol->disable)
  654. sc->protocol->disable(sc);
  655. pckbc_slot_enable(sc->sc_kbctag, PCKBC_AUX_SLOT, 0);
  656. break;
  657. }
  658. sc->sc_state = newstate;
  659. sc->poll = (newstate == PMS_STATE_SUSPENDED) ? 1 : 0;
  660. return (0);
  661. }
  662. int
  663. pms_enable(void *v)
  664. {
  665. struct pms_softc *sc = v;
  666. int rv;
  667. rw_enter_write(&sc->sc_state_lock);
  668. rv = pms_change_state(sc, PMS_STATE_ENABLED, PMS_DEV_PRIMARY);
  669. rw_exit_write(&sc->sc_state_lock);
  670. return (rv);
  671. }
  672. void
  673. pms_disable(void *v)
  674. {
  675. struct pms_softc *sc = v;
  676. rw_enter_write(&sc->sc_state_lock);
  677. pms_change_state(sc, PMS_STATE_DISABLED, PMS_DEV_PRIMARY);
  678. rw_exit_write(&sc->sc_state_lock);
  679. }
  680. int
  681. pms_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
  682. {
  683. struct pms_softc *sc = v;
  684. if (sc->protocol->ioctl)
  685. return (sc->protocol->ioctl(sc, cmd, data, flag, p));
  686. else
  687. return (-1);
  688. }
  689. int
  690. pms_sec_enable(void *v)
  691. {
  692. struct pms_softc *sc = v;
  693. int rv;
  694. rw_enter_write(&sc->sc_state_lock);
  695. rv = pms_change_state(sc, PMS_STATE_ENABLED, PMS_DEV_SECONDARY);
  696. rw_exit_write(&sc->sc_state_lock);
  697. return (rv);
  698. }
  699. void
  700. pms_sec_disable(void *v)
  701. {
  702. struct pms_softc *sc = v;
  703. rw_enter_write(&sc->sc_state_lock);
  704. pms_change_state(sc, PMS_STATE_DISABLED, PMS_DEV_SECONDARY);
  705. rw_exit_write(&sc->sc_state_lock);
  706. }
  707. int
  708. pms_sec_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
  709. {
  710. switch (cmd) {
  711. case WSMOUSEIO_GTYPE:
  712. *(u_int *)data = WSMOUSE_TYPE_PS2;
  713. break;
  714. default:
  715. return (-1);
  716. }
  717. return (0);
  718. }
  719. void
  720. pmsinput(void *vsc, int data)
  721. {
  722. struct pms_softc *sc = vsc;
  723. if (sc->sc_state != PMS_STATE_ENABLED) {
  724. /* Interrupts are not expected. Discard the byte. */
  725. return;
  726. }
  727. sc->packet[sc->inputstate] = data;
  728. if (sc->protocol->sync(sc, data)) {
  729. #ifdef DIAGNOSTIC
  730. printf("%s: not in sync yet, discard input (state %d)\n",
  731. DEVNAME(sc), sc->inputstate);
  732. #endif
  733. sc->inputstate = 0;
  734. return;
  735. }
  736. sc->inputstate++;
  737. if (sc->inputstate != sc->protocol->packetsize)
  738. return;
  739. sc->inputstate = 0;
  740. sc->protocol->proc(sc);
  741. }
  742. int
  743. synaptics_set_mode(struct pms_softc *sc, int mode)
  744. {
  745. struct synaptics_softc *syn = sc->synaptics;
  746. if (pms_spec_cmd(sc, mode) ||
  747. pms_set_rate(sc, SYNAPTICS_CMD_SET_MODE))
  748. return (-1);
  749. syn->mode = mode;
  750. return (0);
  751. }
  752. int
  753. synaptics_query(struct pms_softc *sc, int query, int *val)
  754. {
  755. u_char resp[3];
  756. if (pms_spec_cmd(sc, query) ||
  757. pms_get_status(sc, resp))
  758. return (-1);
  759. if (val)
  760. *val = (resp[0] << 16) | (resp[1] << 8) | resp[2];
  761. return (0);
  762. }
  763. int
  764. synaptics_get_hwinfo(struct pms_softc *sc)
  765. {
  766. struct synaptics_softc *syn = sc->synaptics;
  767. if (synaptics_query(sc, SYNAPTICS_QUE_IDENTIFY, &syn->identify))
  768. return (-1);
  769. if (synaptics_query(sc, SYNAPTICS_QUE_CAPABILITIES,
  770. &syn->capabilities))
  771. return (-1);
  772. if (synaptics_query(sc, SYNAPTICS_QUE_MODEL, &syn->model))
  773. return (-1);
  774. if ((SYNAPTICS_CAP_EXTENDED_QUERIES(syn->capabilities) >= 1) &&
  775. synaptics_query(sc, SYNAPTICS_QUE_EXT_MODEL, &syn->ext_model))
  776. return (-1);
  777. if ((SYNAPTICS_CAP_EXTENDED_QUERIES(syn->capabilities) >= 4) &&
  778. synaptics_query(sc, SYNAPTICS_QUE_EXT_CAPABILITIES,
  779. &syn->ext_capabilities))
  780. return (-1);
  781. if ((SYNAPTICS_ID_MAJOR(syn->identify) >= 4) &&
  782. synaptics_query(sc, SYNAPTICS_QUE_RESOLUTION, &syn->resolution))
  783. return (-1);
  784. if ((SYNAPTICS_CAP_EXTENDED_QUERIES(syn->capabilities) >= 5) &&
  785. (syn->ext_capabilities & SYNAPTICS_EXT_CAP_MAX_DIMENSIONS) &&
  786. synaptics_query(sc, SYNAPTICS_QUE_EXT_DIMENSIONS, &syn->dimension))
  787. return (-1);
  788. if (SYNAPTICS_ID_FULL(syn->identify) >= 0x705) {
  789. if (synaptics_query(sc, SYNAPTICS_QUE_MODES, &syn->modes))
  790. return (-1);
  791. if ((syn->modes & SYNAPTICS_EXT2_CAP) &&
  792. synaptics_query(sc, SYNAPTICS_QUE_EXT2_CAPABILITIES,
  793. &syn->ext2_capabilities))
  794. return (-1);
  795. }
  796. syn->res_x = SYNAPTICS_RESOLUTION_X(syn->resolution);
  797. syn->res_y = SYNAPTICS_RESOLUTION_Y(syn->resolution);
  798. syn->min_x = SYNAPTICS_XMIN_BEZEL;
  799. syn->min_y = SYNAPTICS_YMIN_BEZEL;
  800. syn->max_x = (syn->dimension) ?
  801. SYNAPTICS_DIM_X(syn->dimension) : SYNAPTICS_XMAX_BEZEL;
  802. syn->max_y = (syn->dimension) ?
  803. SYNAPTICS_DIM_Y(syn->dimension) : SYNAPTICS_YMAX_BEZEL;
  804. syn->sec_buttons = 0;
  805. if (SYNAPTICS_EXT_MODEL_BUTTONS(syn->ext_model) > 8)
  806. syn->ext_model &= ~0xf000;
  807. if ((syn->model & SYNAPTICS_MODEL_NEWABS) == 0) {
  808. printf("%s: don't support Synaptics OLDABS\n", DEVNAME(sc));
  809. return (-1);
  810. }
  811. if ((SYNAPTICS_ID_MAJOR(syn->identify) == 5) &&
  812. (SYNAPTICS_ID_MINOR(syn->identify) == 9))
  813. syn->mask = SYNAPTICS_MASK_NEWABS_RELAXED;
  814. else
  815. syn->mask = SYNAPTICS_MASK_NEWABS_STRICT;
  816. return (0);
  817. }
  818. void
  819. synaptics_sec_proc(struct pms_softc *sc)
  820. {
  821. struct synaptics_softc *syn = sc->synaptics;
  822. u_int buttons;
  823. int dx, dy;
  824. if ((sc->sc_dev_enable & PMS_DEV_SECONDARY) == 0)
  825. return;
  826. buttons = butmap[sc->packet[1] & PMS_PS2_BUTTONSMASK];
  827. buttons |= syn->sec_buttons;
  828. dx = (sc->packet[1] & PMS_PS2_XNEG) ?
  829. (int)sc->packet[4] - 256 : sc->packet[4];
  830. dy = (sc->packet[1] & PMS_PS2_YNEG) ?
  831. (int)sc->packet[5] - 256 : sc->packet[5];
  832. wsmouse_input(sc->sc_sec_wsmousedev,
  833. buttons, dx, dy, 0, 0, WSMOUSE_INPUT_DELTA);
  834. }
  835. int
  836. synaptics_knock(struct pms_softc *sc)
  837. {
  838. u_char resp[3];
  839. if (pms_set_resolution(sc, 0) ||
  840. pms_set_resolution(sc, 0) ||
  841. pms_set_resolution(sc, 0) ||
  842. pms_set_resolution(sc, 0) ||
  843. pms_get_status(sc, resp) ||
  844. resp[1] != SYNAPTICS_ID_MAGIC)
  845. return (-1);
  846. return (0);
  847. }
  848. int
  849. pms_enable_synaptics(struct pms_softc *sc)
  850. {
  851. struct synaptics_softc *syn = sc->synaptics;
  852. struct wsmousedev_attach_args a;
  853. int mode, i;
  854. if (synaptics_knock(sc)) {
  855. if (sc->synaptics == NULL)
  856. goto err;
  857. /*
  858. * Some synaptics touchpads don't resume quickly.
  859. * Retry a few times.
  860. */
  861. for (i = 10; i > 0; --i) {
  862. printf("%s: device not resuming, retrying\n",
  863. DEVNAME(sc));
  864. pms_reset(sc);
  865. if (synaptics_knock(sc) == 0)
  866. break;
  867. delay(100000);
  868. }
  869. if (i == 0) {
  870. printf("%s: lost device\n", DEVNAME(sc));
  871. goto err;
  872. }
  873. }
  874. if (sc->synaptics == NULL) {
  875. sc->synaptics = syn = malloc(sizeof(struct synaptics_softc),
  876. M_DEVBUF, M_WAITOK | M_ZERO);
  877. if (syn == NULL) {
  878. printf("%s: synaptics: not enough memory\n",
  879. DEVNAME(sc));
  880. goto err;
  881. }
  882. if (synaptics_get_hwinfo(sc)) {
  883. free(sc->synaptics, M_DEVBUF, 0);
  884. sc->synaptics = NULL;
  885. goto err;
  886. }
  887. /* enable pass-through PS/2 port if supported */
  888. if (syn->capabilities & SYNAPTICS_CAP_PASSTHROUGH) {
  889. a.accessops = &pms_sec_accessops;
  890. a.accesscookie = sc;
  891. sc->sc_sec_wsmousedev = config_found((void *)sc, &a,
  892. wsmousedevprint);
  893. }
  894. syn->wsmode = WSMOUSE_COMPAT;
  895. printf("%s: Synaptics %s, firmware %d.%d\n", DEVNAME(sc),
  896. (syn->ext_capabilities & SYNAPTICS_EXT_CAP_CLICKPAD ?
  897. "clickpad" : "touchpad"),
  898. SYNAPTICS_ID_MAJOR(syn->identify),
  899. SYNAPTICS_ID_MINOR(syn->identify));
  900. }
  901. mode = SYNAPTICS_ABSOLUTE_MODE | SYNAPTICS_HIGH_RATE;
  902. if (SYNAPTICS_ID_MAJOR(syn->identify) >= 4)
  903. mode |= SYNAPTICS_DISABLE_GESTURE;
  904. if (syn->capabilities & SYNAPTICS_CAP_EXTENDED)
  905. mode |= SYNAPTICS_W_MODE;
  906. if (synaptics_set_mode(sc, mode))
  907. goto err;
  908. /* enable advanced gesture mode if supported */
  909. if ((syn->ext_capabilities & SYNAPTICS_EXT_CAP_ADV_GESTURE) &&
  910. (pms_spec_cmd(sc, SYNAPTICS_QUE_MODEL) ||
  911. pms_set_rate(sc, SYNAPTICS_CMD_SET_ADV_GESTURE_MODE)))
  912. goto err;
  913. return (1);
  914. err:
  915. pms_reset(sc);
  916. return (0);
  917. }
  918. int
  919. pms_ioctl_synaptics(struct pms_softc *sc, u_long cmd, caddr_t data, int flag,
  920. struct proc *p)
  921. {
  922. struct synaptics_softc *syn = sc->synaptics;
  923. struct wsmouse_calibcoords *wsmc = (struct wsmouse_calibcoords *)data;
  924. int wsmode;
  925. switch (cmd) {
  926. case WSMOUSEIO_GTYPE:
  927. if ((syn->ext_capabilities & SYNAPTICS_EXT_CAP_CLICKPAD) &&
  928. !(syn->ext2_capabilities & SYNAPTICS_EXT2_CAP_BUTTONS_STICK)
  929. && mouse_has_softbtn)
  930. *(u_int *)data = WSMOUSE_TYPE_SYNAP_SBTN;
  931. else
  932. *(u_int *)data = WSMOUSE_TYPE_SYNAPTICS;
  933. break;
  934. case WSMOUSEIO_GCALIBCOORDS:
  935. wsmc->minx = syn->min_x;
  936. wsmc->maxx = syn->max_x;
  937. wsmc->miny = syn->min_y;
  938. wsmc->maxy = syn->max_y;
  939. wsmc->swapxy = 0;
  940. wsmc->resx = syn->res_x;
  941. wsmc->resy = syn->res_y;
  942. break;
  943. case WSMOUSEIO_SETMODE:
  944. wsmode = *(u_int *)data;
  945. if (wsmode != WSMOUSE_COMPAT && wsmode != WSMOUSE_NATIVE)
  946. return (EINVAL);
  947. syn->wsmode = wsmode;
  948. break;
  949. default:
  950. return (-1);
  951. }
  952. return (0);
  953. }
  954. int
  955. pms_sync_synaptics(struct pms_softc *sc, int data)
  956. {
  957. struct synaptics_softc *syn = sc->synaptics;
  958. switch (sc->inputstate) {
  959. case 0:
  960. if ((data & syn->mask) != SYNAPTICS_VALID_NEWABS_FIRST)
  961. return (-1);
  962. break;
  963. case 3:
  964. if ((data & syn->mask) != SYNAPTICS_VALID_NEWABS_NEXT)
  965. return (-1);
  966. break;
  967. }
  968. return (0);
  969. }
  970. void
  971. pms_proc_synaptics(struct pms_softc *sc)
  972. {
  973. struct synaptics_softc *syn = sc->synaptics;
  974. u_int buttons;
  975. int x, y, z, w, dx, dy;
  976. w = ((sc->packet[0] & 0x30) >> 2) | ((sc->packet[0] & 0x04) >> 1) |
  977. ((sc->packet[3] & 0x04) >> 2);
  978. /*
  979. * Conform to the encoding understood by
  980. * /usr/xenocara/driver/xf86-input-synaptics/src/wsconscomm.c
  981. */
  982. switch (w) {
  983. case 0:
  984. /* fingerwidth 5, numfingers 2 */
  985. break;
  986. case 1:
  987. /* fingerwidth 5, numfingers 3 */
  988. break;
  989. case 5:
  990. /* fingerwidth 5, numfingers 1 */
  991. break;
  992. case 4:
  993. case 8:
  994. /* fingerwidth 4, numfingers 1 */
  995. w = 4;
  996. break;
  997. default:
  998. break;
  999. }
  1000. if ((syn->capabilities & SYNAPTICS_CAP_PASSTHROUGH) && w == 3) {
  1001. synaptics_sec_proc(sc);
  1002. return;
  1003. }
  1004. if ((sc->sc_dev_enable & PMS_DEV_PRIMARY) == 0)
  1005. return;
  1006. /* XXX ignore advanced gesture packet, not yet supported */
  1007. if ((syn->ext_capabilities & SYNAPTICS_EXT_CAP_ADV_GESTURE) && w == 2)
  1008. return;
  1009. x = ((sc->packet[3] & 0x10) << 8) | ((sc->packet[1] & 0x0f) << 8) |
  1010. sc->packet[4];
  1011. y = ((sc->packet[3] & 0x20) << 7) | ((sc->packet[1] & 0xf0) << 4) |
  1012. sc->packet[5];
  1013. z = sc->packet[2];
  1014. buttons = ((sc->packet[0] & sc->packet[3]) & 0x01) ?
  1015. WSMOUSE_BUTTON(1) : 0;
  1016. buttons |= ((sc->packet[0] & sc->packet[3]) & 0x02) ?
  1017. WSMOUSE_BUTTON(3) : 0;
  1018. if (syn->ext_capabilities & SYNAPTICS_EXT_CAP_CLICKPAD) {
  1019. buttons |= ((sc->packet[0] ^ sc->packet[3]) & 0x01) ?
  1020. WSMOUSE_BUTTON(1) : 0;
  1021. } else if (syn->capabilities & SYNAPTICS_CAP_MIDDLE_BUTTON) {
  1022. buttons |= ((sc->packet[0] ^ sc->packet[3]) & 0x01) ?
  1023. WSMOUSE_BUTTON(2) : 0;
  1024. }
  1025. if (syn->capabilities & SYNAPTICS_CAP_FOUR_BUTTON) {
  1026. buttons |= ((sc->packet[0] ^ sc->packet[3]) & 0x01) ?
  1027. WSMOUSE_BUTTON(4) : 0;
  1028. buttons |= ((sc->packet[0] ^ sc->packet[3]) & 0x02) ?
  1029. WSMOUSE_BUTTON(5) : 0;
  1030. } else if (SYNAPTICS_EXT_MODEL_BUTTONS(syn->ext_model) &&
  1031. ((sc->packet[0] ^ sc->packet[3]) & 0x02)) {
  1032. if (syn->ext2_capabilities & SYNAPTICS_EXT2_CAP_BUTTONS_STICK) {
  1033. /*
  1034. * Trackstick buttons on this machine are wired to the
  1035. * trackpad as extra buttons, so route the event
  1036. * through the trackstick interface as normal buttons
  1037. */
  1038. syn->sec_buttons =
  1039. (sc->packet[4] & 0x01) ? WSMOUSE_BUTTON(1) : 0;
  1040. syn->sec_buttons |=
  1041. (sc->packet[5] & 0x01) ? WSMOUSE_BUTTON(3) : 0;
  1042. syn->sec_buttons |=
  1043. (sc->packet[4] & 0x02) ? WSMOUSE_BUTTON(2) : 0;
  1044. wsmouse_input(sc->sc_sec_wsmousedev,
  1045. syn->sec_buttons, 0, 0, 0, 0, WSMOUSE_INPUT_DELTA);
  1046. return;
  1047. }
  1048. buttons |= (sc->packet[4] & 0x01) ? WSMOUSE_BUTTON(6) : 0;
  1049. buttons |= (sc->packet[5] & 0x01) ? WSMOUSE_BUTTON(7) : 0;
  1050. buttons |= (sc->packet[4] & 0x02) ? WSMOUSE_BUTTON(8) : 0;
  1051. buttons |= (sc->packet[5] & 0x02) ? WSMOUSE_BUTTON(9) : 0;
  1052. buttons |= (sc->packet[4] & 0x04) ? WSMOUSE_BUTTON(10) : 0;
  1053. buttons |= (sc->packet[5] & 0x04) ? WSMOUSE_BUTTON(11) : 0;
  1054. buttons |= (sc->packet[4] & 0x08) ? WSMOUSE_BUTTON(12) : 0;
  1055. buttons |= (sc->packet[5] & 0x08) ? WSMOUSE_BUTTON(13) : 0;
  1056. x &= ~0x0f;
  1057. y &= ~0x0f;
  1058. }
  1059. /* ignore final events that happen when removing all fingers */
  1060. if (x <= 1 || y <= 1) {
  1061. x = syn->old_x;
  1062. y = syn->old_y;
  1063. }
  1064. if (syn->wsmode == WSMOUSE_NATIVE) {
  1065. wsmouse_input(sc->sc_wsmousedev, buttons, x, y, z, w,
  1066. WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y |
  1067. WSMOUSE_INPUT_ABSOLUTE_Z | WSMOUSE_INPUT_ABSOLUTE_W);
  1068. } else {
  1069. dx = dy = 0;
  1070. if (z > SYNAPTICS_PRESSURE) {
  1071. dx = x - syn->old_x;
  1072. dy = y - syn->old_y;
  1073. dx /= SYNAPTICS_SCALE;
  1074. dy /= SYNAPTICS_SCALE;
  1075. }
  1076. if (dx || dy || buttons != syn->old_buttons)
  1077. wsmouse_input(sc->sc_wsmousedev, buttons, dx, dy, 0, 0,
  1078. WSMOUSE_INPUT_DELTA);
  1079. syn->old_buttons = buttons;
  1080. }
  1081. syn->old_x = x;
  1082. syn->old_y = y;
  1083. }
  1084. void
  1085. pms_disable_synaptics(struct pms_softc *sc)
  1086. {
  1087. struct synaptics_softc *syn = sc->synaptics;
  1088. if (syn->capabilities & SYNAPTICS_CAP_SLEEP)
  1089. synaptics_set_mode(sc, SYNAPTICS_SLEEP_MODE |
  1090. SYNAPTICS_DISABLE_GESTURE);
  1091. }
  1092. int
  1093. alps_sec_proc(struct pms_softc *sc)
  1094. {
  1095. struct alps_softc *alps = sc->alps;
  1096. int dx, dy, pos = 0;
  1097. if ((sc->packet[0] & PMS_ALPS_PS2_MASK) == PMS_ALPS_PS2_VALID) {
  1098. /*
  1099. * We need to keep buttons states because interleaved
  1100. * packets only signalize x/y movements.
  1101. */
  1102. alps->sec_buttons = butmap[sc->packet[0] & PMS_PS2_BUTTONSMASK];
  1103. } else if ((sc->packet[3] & PMS_ALPS_INTERLEAVED_MASK) ==
  1104. PMS_ALPS_INTERLEAVED_VALID) {
  1105. sc->inputstate = 3;
  1106. pos = 3;
  1107. } else {
  1108. return (0);
  1109. }
  1110. if ((sc->sc_dev_enable & PMS_DEV_SECONDARY) == 0)
  1111. return (1);
  1112. dx = (sc->packet[pos] & PMS_PS2_XNEG) ?
  1113. (int)sc->packet[pos + 1] - 256 : sc->packet[pos + 1];
  1114. dy = (sc->packet[pos] & PMS_PS2_YNEG) ?
  1115. (int)sc->packet[pos + 2] - 256 : sc->packet[pos + 2];
  1116. wsmouse_input(sc->sc_sec_wsmousedev, alps->sec_buttons,
  1117. dx, dy, 0, 0, WSMOUSE_INPUT_DELTA);
  1118. return (1);
  1119. }
  1120. int
  1121. alps_get_hwinfo(struct pms_softc *sc)
  1122. {
  1123. struct alps_softc *alps = sc->alps;
  1124. u_char resp[3];
  1125. int i;
  1126. if (pms_set_resolution(sc, 0) ||
  1127. pms_set_scaling(sc, 2) ||
  1128. pms_set_scaling(sc, 2) ||
  1129. pms_set_scaling(sc, 2) ||
  1130. pms_get_status(sc, resp)) {
  1131. DPRINTF("%s: alps: model query error\n", DEVNAME(sc));
  1132. return (-1);
  1133. }
  1134. alps->version = (resp[0] << 8) | (resp[1] << 4) | (resp[2] / 20 + 1);
  1135. for (i = 0; i < nitems(alps_models); i++)
  1136. if (alps->version == alps_models[i].version) {
  1137. alps->model = alps_models[i].model;
  1138. alps->mask = alps_models[i].mask;
  1139. return (0);
  1140. }
  1141. return (-1);
  1142. }
  1143. int
  1144. pms_enable_alps(struct pms_softc *sc)
  1145. {
  1146. struct alps_softc *alps = sc->alps;
  1147. struct wsmousedev_attach_args a;
  1148. u_char resp[3];
  1149. if (pms_set_resolution(sc, 0) ||
  1150. pms_set_scaling(sc, 1) ||
  1151. pms_set_scaling(sc, 1) ||
  1152. pms_set_scaling(sc, 1) ||
  1153. pms_get_status(sc, resp) ||
  1154. resp[0] != PMS_ALPS_MAGIC1 ||
  1155. resp[1] != PMS_ALPS_MAGIC2 ||
  1156. (resp[2] != PMS_ALPS_MAGIC3_1 && resp[2] != PMS_ALPS_MAGIC3_2 &&
  1157. resp[2] != PMS_ALPS_MAGIC3_3))
  1158. goto err;
  1159. if (sc->alps == NULL) {
  1160. sc->alps = alps = malloc(sizeof(struct alps_softc),
  1161. M_DEVBUF, M_WAITOK | M_ZERO);
  1162. if (alps == NULL) {
  1163. printf("%s: alps: not enough memory\n", DEVNAME(sc));
  1164. goto err;
  1165. }
  1166. if (alps_get_hwinfo(sc)) {
  1167. free(sc->alps, M_DEVBUF, 0);
  1168. sc->alps = NULL;
  1169. goto err;
  1170. }
  1171. printf("%s: ALPS %s, version 0x%04x\n", DEVNAME(sc),
  1172. (alps->model & ALPS_DUALPOINT ? "Dualpoint" : "Glidepoint"),
  1173. alps->version);
  1174. alps->min_x = ALPS_XMIN_BEZEL;
  1175. alps->min_y = ALPS_YMIN_BEZEL;
  1176. alps->max_x = ALPS_XMAX_BEZEL;
  1177. alps->max_y = ALPS_YMAX_BEZEL;
  1178. alps->wsmode = WSMOUSE_COMPAT;
  1179. if (alps->model & ALPS_DUALPOINT) {
  1180. a.accessops = &pms_sec_accessops;
  1181. a.accesscookie = sc;
  1182. sc->sc_sec_wsmousedev = config_found((void *)sc, &a,
  1183. wsmousedevprint);
  1184. }
  1185. }
  1186. if (alps->model == 0)
  1187. goto err;
  1188. if ((alps->model & ALPS_PASSTHROUGH) &&
  1189. (pms_set_scaling(sc, 2) ||
  1190. pms_set_scaling(sc, 2) ||
  1191. pms_set_scaling(sc, 2) ||
  1192. pms_dev_disable(sc))) {
  1193. DPRINTF("%s: alps: passthrough on error\n", DEVNAME(sc));
  1194. goto err;
  1195. }
  1196. if (pms_dev_disable(sc) ||
  1197. pms_dev_disable(sc) ||
  1198. pms_set_rate(sc, 0x0a)) {
  1199. DPRINTF("%s: alps: tapping error\n", DEVNAME(sc));
  1200. goto err;
  1201. }
  1202. if (pms_dev_disable(sc) ||
  1203. pms_dev_disable(sc) ||
  1204. pms_dev_disable(sc) ||
  1205. pms_dev_disable(sc) ||
  1206. pms_dev_enable(sc)) {
  1207. DPRINTF("%s: alps: absolute mode error\n", DEVNAME(sc));
  1208. goto err;
  1209. }
  1210. if ((alps->model & ALPS_PASSTHROUGH) &&
  1211. (pms_set_scaling(sc, 1) ||
  1212. pms_set_scaling(sc, 1) ||
  1213. pms_set_scaling(sc, 1) ||
  1214. pms_dev_disable(sc))) {
  1215. DPRINTF("%s: alps: passthrough off error\n", DEVNAME(sc));
  1216. goto err;
  1217. }
  1218. alps->sec_buttons = 0;
  1219. return (1);
  1220. err:
  1221. pms_reset(sc);
  1222. return (0);
  1223. }
  1224. int
  1225. pms_ioctl_alps(struct pms_softc *sc, u_long cmd, caddr_t data, int flag,
  1226. struct proc *p)
  1227. {
  1228. struct alps_softc *alps = sc->alps;
  1229. struct wsmouse_calibcoords *wsmc = (struct wsmouse_calibcoords *)data;
  1230. int wsmode;
  1231. switch (cmd) {
  1232. case WSMOUSEIO_GTYPE:
  1233. *(u_int *)data = WSMOUSE_TYPE_ALPS;
  1234. break;
  1235. case WSMOUSEIO_GCALIBCOORDS:
  1236. wsmc->minx = alps->min_x;
  1237. wsmc->maxx = alps->max_x;
  1238. wsmc->miny = alps->min_y;
  1239. wsmc->maxy = alps->max_y;
  1240. wsmc->swapxy = 0;
  1241. break;
  1242. case WSMOUSEIO_SETMODE:
  1243. wsmode = *(u_int *)data;
  1244. if (wsmode != WSMOUSE_COMPAT && wsmode != WSMOUSE_NATIVE)
  1245. return (EINVAL);
  1246. alps->wsmode = wsmode;
  1247. break;
  1248. default:
  1249. return (-1);
  1250. }
  1251. return (0);
  1252. }
  1253. int
  1254. pms_sync_alps(struct pms_softc *sc, int data)
  1255. {
  1256. struct alps_softc *alps = sc->alps;
  1257. if ((alps->model & ALPS_DUALPOINT) &&
  1258. (sc->packet[0] & PMS_ALPS_PS2_MASK) == PMS_ALPS_PS2_VALID) {
  1259. if (sc->inputstate == 2)
  1260. sc->inputstate += 3;
  1261. return (0);
  1262. }
  1263. switch (sc->inputstate) {
  1264. case 0:
  1265. if ((data & alps->mask) != alps->mask)
  1266. return (-1);
  1267. break;
  1268. case 1:
  1269. case 2:
  1270. case 3:
  1271. if ((data & PMS_ALPS_MASK) != PMS_ALPS_VALID)
  1272. return (-1);
  1273. break;
  1274. case 4:
  1275. case 5:
  1276. if ((alps->model & ALPS_INTERLEAVED) == 0 &&
  1277. (data & PMS_ALPS_MASK) != PMS_ALPS_VALID)
  1278. return (-1);
  1279. break;
  1280. }
  1281. return (0);
  1282. }
  1283. void
  1284. pms_proc_alps(struct pms_softc *sc)
  1285. {
  1286. struct alps_softc *alps = sc->alps;
  1287. int x, y, z, w, dx, dy;
  1288. u_int buttons;
  1289. int fin, ges;
  1290. if ((alps->model & ALPS_DUALPOINT) && alps_sec_proc(sc))
  1291. return;
  1292. x = sc->packet[1] | ((sc->packet[2] & 0x78) << 4);
  1293. y = sc->packet[4] | ((sc->packet[3] & 0x70) << 3);
  1294. z = sc->packet[5];
  1295. buttons = ((sc->packet[3] & 1) ? WSMOUSE_BUTTON(1) : 0) |
  1296. ((sc->packet[3] & 2) ? WSMOUSE_BUTTON(3) : 0) |
  1297. ((sc->packet[3] & 4) ? WSMOUSE_BUTTON(2) : 0);
  1298. if ((sc->sc_dev_enable & PMS_DEV_SECONDARY) && z == ALPS_Z_MAGIC) {
  1299. dx = (x > ALPS_XSEC_BEZEL / 2) ? (x - ALPS_XSEC_BEZEL) : x;
  1300. dy = (y > ALPS_YSEC_BEZEL / 2) ? (y - ALPS_YSEC_BEZEL) : y;
  1301. wsmouse_input(sc->sc_sec_wsmousedev, buttons, dx, dy, 0, 0,
  1302. WSMOUSE_INPUT_DELTA);
  1303. return;
  1304. }
  1305. if ((sc->sc_dev_enable & PMS_DEV_PRIMARY) == 0)
  1306. return;
  1307. /*
  1308. * XXX The Y-axis is in the oposit direction compared to
  1309. * Synaptics touchpads and PS/2 mouses.
  1310. * It's why we need to translate the y value here for both
  1311. * NATIVE and COMPAT modes.
  1312. */
  1313. y = ALPS_YMAX_BEZEL - y + ALPS_YMIN_BEZEL;
  1314. if (alps->wsmode == WSMOUSE_NATIVE) {
  1315. ges = sc->packet[2] & 0x01;
  1316. fin = sc->packet[2] & 0x02;
  1317. /* Simulate click (tap) */
  1318. if (ges && !fin)
  1319. z = 35;
  1320. /* Generate a null pressure event (needed for tap & drag) */
  1321. if (ges && fin && !alps->old_fin)
  1322. z = 0;
  1323. /* Generate a width value corresponding to one finger */
  1324. if (z > 0)
  1325. w = 4;
  1326. else
  1327. w = 0;
  1328. wsmouse_input(sc->sc_wsmousedev, buttons, x, y, z, w,
  1329. WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y |
  1330. WSMOUSE_INPUT_ABSOLUTE_Z | WSMOUSE_INPUT_ABSOLUTE_W);
  1331. alps->old_fin = fin;
  1332. } else {
  1333. dx = dy = 0;
  1334. if (z > ALPS_PRESSURE) {
  1335. dx = x - alps->old_x;
  1336. dy = y - alps->old_y;
  1337. /* Prevent jump */
  1338. dx = abs(dx) > 50 ? 0 : dx;
  1339. dy = abs(dy) > 50 ? 0 : dy;
  1340. }
  1341. if (dx || dy || buttons != alps->old_buttons)
  1342. wsmouse_input(sc->sc_wsmousedev, buttons, dx, dy, 0, 0,
  1343. WSMOUSE_INPUT_DELTA);
  1344. alps->old_x = x;
  1345. alps->old_y = y;
  1346. alps->old_buttons = buttons;
  1347. }
  1348. }
  1349. int
  1350. elantech_set_absolute_mode_v1(struct pms_softc *sc)
  1351. {
  1352. int i;
  1353. u_char resp[3];
  1354. /* Enable absolute mode. Magic numbers from Linux driver. */
  1355. if (pms_spec_cmd(sc, ELANTECH_CMD_WRITE_REG) ||
  1356. pms_spec_cmd(sc, 0x10) ||
  1357. pms_spec_cmd(sc, 0x16) ||
  1358. pms_set_scaling(sc, 1) ||
  1359. pms_spec_cmd(sc, ELANTECH_CMD_WRITE_REG) ||
  1360. pms_spec_cmd(sc, 0x11) ||
  1361. pms_spec_cmd(sc, 0x8f) ||
  1362. pms_set_scaling(sc, 1))
  1363. return (-1);
  1364. /* Read back reg 0x10 to ensure hardware is ready. */
  1365. for (i = 0; i < 5; i++) {
  1366. if (pms_spec_cmd(sc, ELANTECH_CMD_READ_REG) ||
  1367. pms_spec_cmd(sc, 0x10) ||
  1368. pms_get_status(sc, resp) == 0)
  1369. break;
  1370. delay(2000);
  1371. }
  1372. if (i == 5)
  1373. return (-1);
  1374. if ((resp[0] & ELANTECH_ABSOLUTE_MODE) == 0)
  1375. return (-1);
  1376. return (0);
  1377. }
  1378. int
  1379. elantech_set_absolute_mode_v2(struct pms_softc *sc)
  1380. {
  1381. int i;
  1382. u_char resp[3];
  1383. u_char reg10 = (sc->elantech->fw_version == 0x20030 ? 0x54 : 0xc4);
  1384. /* Enable absolute mode. Magic numbers from Linux driver. */
  1385. if (elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) ||
  1386. elantech_ps2_cmd(sc, ELANTECH_CMD_WRITE_REG) ||
  1387. elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) ||
  1388. elantech_ps2_cmd(sc, 0x10) ||
  1389. elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) ||
  1390. elantech_ps2_cmd(sc, reg10) ||
  1391. pms_set_scaling(sc, 1) ||
  1392. elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) ||
  1393. elantech_ps2_cmd(sc, ELANTECH_CMD_WRITE_REG) ||
  1394. elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) ||
  1395. elantech_ps2_cmd(sc, 0x11) ||
  1396. elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) ||
  1397. elantech_ps2_cmd(sc, 0x88) ||
  1398. pms_set_scaling(sc, 1))
  1399. return (-1);
  1400. /* Read back reg 0x10 to ensure hardware is ready. */
  1401. for (i = 0; i < 5; i++) {
  1402. if (elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) ||
  1403. elantech_ps2_cmd(sc, ELANTECH_CMD_READ_REG) ||
  1404. elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) ||
  1405. elantech_ps2_cmd(sc, 0x10) ||
  1406. pms_get_status(sc, resp) == 0)
  1407. break;
  1408. delay(2000);
  1409. }
  1410. if (i == 5)
  1411. return (-1);
  1412. return (0);
  1413. }
  1414. int
  1415. elantech_set_absolute_mode_v3(struct pms_softc *sc)
  1416. {
  1417. int i;
  1418. u_char resp[3];
  1419. /* Enable absolute mode. Magic numbers from Linux driver. */
  1420. if (elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) ||
  1421. elantech_ps2_cmd(sc, ELANTECH_CMD_READ_WRITE_REG) ||
  1422. elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) ||
  1423. elantech_ps2_cmd(sc, 0x10) ||
  1424. elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) ||
  1425. elantech_ps2_cmd(sc, 0x0b) ||
  1426. pms_set_scaling(sc, 1))
  1427. return (-1);
  1428. /* Read back reg 0x10 to ensure hardware is ready. */
  1429. for (i = 0; i < 5; i++) {
  1430. if (elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) ||
  1431. elantech_ps2_cmd(sc, ELANTECH_CMD_READ_WRITE_REG) ||
  1432. elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) ||
  1433. elantech_ps2_cmd(sc, 0x10) ||
  1434. pms_get_status(sc, resp) == 0)
  1435. break;
  1436. delay(2000);
  1437. }
  1438. if (i == 5)
  1439. return (-1);
  1440. return (0);
  1441. }
  1442. int
  1443. elantech_set_absolute_mode_v4(struct pms_softc *sc)
  1444. {
  1445. /* Enable absolute mode. Magic numbers from Linux driver. */
  1446. if (elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) ||
  1447. elantech_ps2_cmd(sc, ELANTECH_CMD_READ_WRITE_REG) ||
  1448. elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) ||
  1449. elantech_ps2_cmd(sc, 0x07) ||
  1450. elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) ||
  1451. elantech_ps2_cmd(sc, ELANTECH_CMD_READ_WRITE_REG) ||
  1452. elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND) ||
  1453. elantech_ps2_cmd(sc, 0x01) ||
  1454. pms_set_scaling(sc, 1))
  1455. return (-1);
  1456. /* v4 has no register 0x10 to read response from */
  1457. return (0);
  1458. }
  1459. int
  1460. elantech_get_hwinfo_v1(struct pms_softc *sc)
  1461. {
  1462. struct elantech_softc *elantech = sc->elantech;
  1463. int fw_version;
  1464. u_char capabilities[3];
  1465. if (synaptics_query(sc, ELANTECH_QUE_FW_VER, &fw_version))
  1466. return (-1);
  1467. if (fw_version < 0x20030 || fw_version == 0x20600) {
  1468. if (fw_version < 0x20000)
  1469. elantech->flags |= ELANTECH_F_HW_V1_OLD;
  1470. } else
  1471. return (-1);
  1472. elantech->fw_version = fw_version;
  1473. if (pms_spec_cmd(sc, ELANTECH_QUE_CAPABILITIES) ||
  1474. pms_get_status(sc, capabilities))
  1475. return (-1);
  1476. if (capabilities[0] & ELANTECH_CAP_HAS_ROCKER)
  1477. elantech->flags |= ELANTECH_F_HAS_ROCKER;
  1478. if (elantech_set_absolute_mode_v1(sc))
  1479. return (-1);
  1480. elantech->min_x = ELANTECH_V1_X_MIN;
  1481. elantech->max_x = ELANTECH_V1_X_MAX;
  1482. elantech->min_y = ELANTECH_V1_Y_MIN;
  1483. elantech->max_y = ELANTECH_V1_Y_MAX;
  1484. return (0);
  1485. }
  1486. int
  1487. elantech_get_hwinfo_v2(struct pms_softc *sc)
  1488. {
  1489. struct elantech_softc *elantech = sc->elantech;
  1490. int fw_version, ic_ver;
  1491. u_char capabilities[3];
  1492. int i, fixed_dpi;
  1493. u_char resp[3];
  1494. if (synaptics_query(sc, ELANTECH_QUE_FW_VER, &fw_version))
  1495. return (-1);
  1496. ic_ver = (fw_version & 0x0f0000) >> 16;
  1497. if (ic_ver != 2 && ic_ver != 4)
  1498. return (-1);
  1499. elantech->fw_version = fw_version;
  1500. if (fw_version >= 0x20800)
  1501. elantech->flags |= ELANTECH_F_REPORTS_PRESSURE;
  1502. if (pms_spec_cmd(sc, ELANTECH_QUE_CAPABILITIES) ||
  1503. pms_get_status(sc, capabilities))
  1504. return (-1);
  1505. if (elantech_set_absolute_mode_v2(sc))
  1506. return (-1);
  1507. if (fw_version == 0x20800 || fw_version == 0x20b00 ||
  1508. fw_version == 0x20030) {
  1509. elantech->max_x = ELANTECH_V2_X_MAX;
  1510. elantech->max_y = ELANTECH_V2_Y_MAX;
  1511. } else {
  1512. if (pms_spec_cmd(sc, ELANTECH_QUE_FW_ID) ||
  1513. pms_get_status(sc, resp))
  1514. return (-1);
  1515. fixed_dpi = resp[1] & 0x10;
  1516. i = (fw_version > 0x20800 && fw_version < 0x20900) ? 1 : 2;
  1517. if ((fw_version >> 16) == 0x14 && fixed_dpi) {
  1518. if (pms_spec_cmd(sc, ELANTECH_QUE_SAMPLE) ||
  1519. pms_get_status(sc, resp))
  1520. return (-1);
  1521. elantech->max_x = (capabilities[1] - i) * resp[1] / 2;
  1522. elantech->max_y = (capabilities[2] - i) * resp[2] / 2;
  1523. } else if (fw_version == 0x040216) {
  1524. elantech->max_x = 819;
  1525. elantech->max_y = 405;
  1526. } else if (fw_version == 0x040219 || fw_version == 0x040215) {
  1527. elantech->max_x = 900;
  1528. elantech->max_y = 500;
  1529. } else {
  1530. elantech->max_x = (capabilities[1] - i) * 64;
  1531. elantech->max_y = (capabilities[2] - i) * 64;
  1532. }
  1533. }
  1534. return (0);
  1535. }
  1536. int
  1537. elantech_get_hwinfo_v3(struct pms_softc *sc)
  1538. {
  1539. struct elantech_softc *elantech = sc->elantech;
  1540. int fw_version;
  1541. u_char resp[3];
  1542. if (synaptics_query(sc, ELANTECH_QUE_FW_VER, &fw_version))
  1543. return (-1);
  1544. if (((fw_version & 0x0f0000) >> 16) != 5)
  1545. return (-1);
  1546. elantech->fw_version = fw_version;
  1547. elantech->flags |= ELANTECH_F_REPORTS_PRESSURE;
  1548. if ((fw_version & 0x4000) == 0x4000)
  1549. elantech->flags |= ELANTECH_F_CRC_ENABLED;
  1550. if (elantech_set_absolute_mode_v3(sc))
  1551. return (-1);
  1552. if (pms_spec_cmd(sc, ELANTECH_QUE_FW_ID) ||
  1553. pms_get_status(sc, resp))
  1554. return (-1);
  1555. elantech->max_x = (resp[0] & 0x0f) << 8 | resp[1];
  1556. elantech->max_y = (resp[0] & 0xf0) << 4 | resp[2];
  1557. return (0);
  1558. }
  1559. int
  1560. elantech_get_hwinfo_v4(struct pms_softc *sc)
  1561. {
  1562. struct elantech_softc *elantech = sc->elantech;
  1563. int fw_version;
  1564. u_char capabilities[3];
  1565. u_char resp[3];
  1566. if (synaptics_query(sc, ELANTECH_QUE_FW_VER, &fw_version))
  1567. return (-1);
  1568. if (((fw_version & 0x0f0000) >> 16) != 6 &&
  1569. (fw_version & 0x0f0000) >> 16 != 8)
  1570. return (-1);
  1571. elantech->fw_version = fw_version;
  1572. elantech->flags |= ELANTECH_F_REPORTS_PRESSURE;
  1573. if (elantech_set_absolute_mode_v4(sc))
  1574. return (-1);
  1575. if (pms_spec_cmd(sc, ELANTECH_QUE_CAPABILITIES) ||
  1576. pms_get_status(sc, capabilities))
  1577. return (-1);
  1578. if (pms_spec_cmd(sc, ELANTECH_QUE_FW_ID) ||
  1579. pms_get_status(sc, resp))
  1580. return (-1);
  1581. elantech->max_x = (resp[0] & 0x0f) << 8 | resp[1];
  1582. elantech->max_y = (resp[0] & 0xf0) << 4 | resp[2];
  1583. if ((capabilities[1] < 2) || (capabilities[1] > elantech->max_x))
  1584. return (-1);
  1585. elantech->width = elantech->max_x / (capabilities[1] - 1);
  1586. return (0);
  1587. }
  1588. int
  1589. elantech_ps2_cmd(struct pms_softc *sc, u_char command)
  1590. {
  1591. u_char cmd[1];
  1592. cmd[0] = command;
  1593. return (pms_cmd(sc, cmd, 1, NULL, 0));
  1594. }
  1595. int
  1596. elantech_knock(struct pms_softc *sc)
  1597. {
  1598. u_char resp[3];
  1599. if (pms_dev_disable(sc) ||
  1600. pms_set_scaling(sc, 1) ||
  1601. pms_set_scaling(sc, 1) ||
  1602. pms_set_scaling(sc, 1) ||
  1603. pms_get_status(sc, resp) ||
  1604. resp[0] != PMS_ELANTECH_MAGIC1 ||
  1605. resp[1] != PMS_ELANTECH_MAGIC2 ||
  1606. (resp[2] != PMS_ELANTECH_MAGIC3_1 &&
  1607. resp[2] != PMS_ELANTECH_MAGIC3_2))
  1608. return (-1);
  1609. return (0);
  1610. }
  1611. int
  1612. pms_enable_elantech_v1(struct pms_softc *sc)
  1613. {
  1614. struct elantech_softc *elantech = sc->elantech;
  1615. int i;
  1616. if (elantech_knock(sc))
  1617. goto err;
  1618. if (sc->elantech == NULL) {
  1619. sc->elantech = elantech = malloc(sizeof(struct elantech_softc),
  1620. M_DEVBUF, M_WAITOK | M_ZERO);
  1621. if (elantech == NULL) {
  1622. printf("%s: elantech: not enough memory\n",
  1623. DEVNAME(sc));
  1624. goto err;
  1625. }
  1626. if (elantech_get_hwinfo_v1(sc)) {
  1627. free(sc->elantech, M_DEVBUF, 0);
  1628. sc->elantech = NULL;
  1629. goto err;
  1630. }
  1631. printf("%s: Elantech Touchpad, version %d, firmware 0x%x\n",
  1632. DEVNAME(sc), 1, sc->elantech->fw_version);
  1633. } else if (elantech_set_absolute_mode_v1(sc))
  1634. goto err;
  1635. for (i = 0; i < nitems(sc->elantech->parity); i++)
  1636. sc->elantech->parity[i] = sc->elantech->parity[i & (i - 1)] ^ 1;
  1637. return (1);
  1638. err:
  1639. pms_reset(sc);
  1640. return (0);
  1641. }
  1642. int
  1643. pms_enable_elantech_v2(struct pms_softc *sc)
  1644. {
  1645. struct elantech_softc *elantech = sc->elantech;
  1646. if (elantech_knock(sc))
  1647. goto err;
  1648. if (sc->elantech == NULL) {
  1649. sc->elantech = elantech = malloc(sizeof(struct elantech_softc),
  1650. M_DEVBUF, M_WAITOK | M_ZERO);
  1651. if (elantech == NULL) {
  1652. printf("%s: elantech: not enough memory\n",
  1653. DEVNAME(sc));
  1654. goto err;
  1655. }
  1656. if (elantech_get_hwinfo_v2(sc)) {
  1657. free(sc->elantech, M_DEVBUF, 0);
  1658. sc->elantech = NULL;
  1659. goto err;
  1660. }
  1661. printf("%s: Elantech Touchpad, version %d, firmware 0x%x\n",
  1662. DEVNAME(sc), 2, sc->elantech->fw_version);
  1663. } else if (elantech_set_absolute_mode_v2(sc))
  1664. goto err;
  1665. return (1);
  1666. err:
  1667. pms_reset(sc);
  1668. return (0);
  1669. }
  1670. int
  1671. pms_enable_elantech_v3(struct pms_softc *sc)
  1672. {
  1673. struct elantech_softc *elantech = sc->elantech;
  1674. if (elantech_knock(sc))
  1675. goto err;
  1676. if (sc->elantech == NULL) {
  1677. sc->elantech = elantech = malloc(sizeof(struct elantech_softc),
  1678. M_DEVBUF, M_WAITOK | M_ZERO);
  1679. if (elantech == NULL) {
  1680. printf("%s: elantech: not enough memory\n",
  1681. DEVNAME(sc));
  1682. goto err;
  1683. }
  1684. if (elantech_get_hwinfo_v3(sc)) {
  1685. free(sc->elantech, M_DEVBUF, 0);
  1686. sc->elantech = NULL;
  1687. goto err;
  1688. }
  1689. printf("%s: Elantech Touchpad, version %d, firmware 0x%x\n",
  1690. DEVNAME(sc), 3, sc->elantech->fw_version);
  1691. } else if (elantech_set_absolute_mode_v3(sc))
  1692. goto err;
  1693. return (1);
  1694. err:
  1695. pms_reset(sc);
  1696. return (0);
  1697. }
  1698. int
  1699. pms_enable_elantech_v4(struct pms_softc *sc)
  1700. {
  1701. struct elantech_softc *elantech = sc->elantech;
  1702. if (elantech_knock(sc))
  1703. goto err;
  1704. if (sc->elantech == NULL) {
  1705. sc->elantech = elantech = malloc(sizeof(struct elantech_softc),
  1706. M_DEVBUF, M_WAITOK | M_ZERO);
  1707. if (elantech == NULL) {
  1708. printf("%s: elantech: not enough memory\n",
  1709. DEVNAME(sc));
  1710. goto err;
  1711. }
  1712. if (elantech_get_hwinfo_v4(sc)) {
  1713. free(sc->elantech, M_DEVBUF, 0);
  1714. sc->elantech = NULL;
  1715. goto err;
  1716. }
  1717. printf("%s: Elantech Clickpad, version %d, firmware 0x%x\n",
  1718. DEVNAME(sc), 4, sc->elantech->fw_version);
  1719. } else if (elantech_set_absolute_mode_v4(sc))
  1720. goto err;
  1721. return (1);
  1722. err:
  1723. pms_reset(sc);
  1724. return (0);
  1725. }
  1726. int
  1727. pms_ioctl_elantech(struct pms_softc *sc, u_long cmd, caddr_t data, int flag,
  1728. struct proc *p)
  1729. {
  1730. struct elantech_softc *elantech = sc->elantech;
  1731. struct wsmouse_calibcoords *wsmc = (struct wsmouse_calibcoords *)data;
  1732. int wsmode;
  1733. switch (cmd) {
  1734. case WSMOUSEIO_GTYPE:
  1735. *(u_int *)data = WSMOUSE_TYPE_ELANTECH;
  1736. break;
  1737. case WSMOUSEIO_GCALIBCOORDS:
  1738. wsmc->minx = elantech->min_x;
  1739. wsmc->maxx = elantech->max_x;
  1740. wsmc->miny = elantech->min_y;
  1741. wsmc->maxy = elantech->max_y;
  1742. wsmc->swapxy = 0;
  1743. wsmc->resx = 0;
  1744. wsmc->resy = 0;
  1745. break;
  1746. case WSMOUSEIO_SETMODE:
  1747. wsmode = *(u_int *)data;
  1748. if (wsmode != WSMOUSE_COMPAT && wsmode != WSMOUSE_NATIVE)
  1749. return (EINVAL);
  1750. elantech->wsmode = wsmode;
  1751. break;
  1752. default:
  1753. return (-1);
  1754. }
  1755. return (0);
  1756. }
  1757. int
  1758. pms_sync_elantech_v1(struct pms_softc *sc, int data)
  1759. {
  1760. struct elantech_softc *elantech = sc->elantech;
  1761. u_char p;
  1762. switch (sc->inputstate) {
  1763. case 0:
  1764. if (elantech->flags & ELANTECH_F_HW_V1_OLD) {
  1765. elantech->p1 = (data & 0x20) >> 5;
  1766. elantech->p2 = (data & 0x10) >> 4;
  1767. } else {
  1768. elantech->p1 = (data & 0x10) >> 4;
  1769. elantech->p2 = (data & 0x20) >> 5;
  1770. }
  1771. elantech->p3 = (data & 0x04) >> 2;
  1772. return (0);
  1773. case 1:
  1774. p = elantech->p1;
  1775. break;
  1776. case 2:
  1777. p = elantech->p2;
  1778. break;
  1779. case 3:
  1780. p = elantech->p3;
  1781. break;
  1782. default:
  1783. return (-1);
  1784. }
  1785. if (data < 0 || data >= nitems(elantech->parity) ||
  1786. elantech->parity[data] != p)
  1787. return (-1);
  1788. return (0);
  1789. }
  1790. int
  1791. pms_sync_elantech_v2(struct pms_softc *sc, int data)
  1792. {
  1793. struct elantech_softc *elantech = sc->elantech;
  1794. /* Variants reporting pressure always have the same constant bits. */
  1795. if (elantech->flags & ELANTECH_F_REPORTS_PRESSURE) {
  1796. if (sc->inputstate == 0 && (data & 0x0c) != 0x04)
  1797. return (-1);
  1798. if (sc->inputstate == 3 && (data & 0x0f) != 0x02)
  1799. return (-1);
  1800. return (0);
  1801. }
  1802. /* For variants not reporting pressure, 1 and 3 finger touch packets
  1803. * have different constant bits than 2 finger touch pakets. */
  1804. switch (sc->inputstate) {
  1805. case 0:
  1806. if ((data & 0xc0) == 0x80) {
  1807. if ((data & 0x0c) != 0x0c)
  1808. return (-1);
  1809. elantech->flags |= ELANTECH_F_2FINGER_PACKET;
  1810. } else {
  1811. if ((data & 0x3c) != 0x3c)
  1812. return (-1);
  1813. elantech->flags &= ~ELANTECH_F_2FINGER_PACKET;
  1814. }
  1815. break;
  1816. case 1:
  1817. case 4:
  1818. if (elantech->flags & ELANTECH_F_2FINGER_PACKET)
  1819. break;
  1820. if ((data & 0xf0) != 0x00)
  1821. return (-1);
  1822. break;
  1823. case 3:
  1824. if (elantech->flags & ELANTECH_F_2FINGER_PACKET) {
  1825. if ((data & 0x0e) != 0x08)
  1826. return (-1);
  1827. } else {
  1828. if ((data & 0x3e) != 0x38)
  1829. return (-1);
  1830. }
  1831. break;
  1832. default:
  1833. break;
  1834. }
  1835. return (0);
  1836. }
  1837. int
  1838. pms_sync_elantech_v3(struct pms_softc *sc, int data)
  1839. {
  1840. struct elantech_softc *elantech = sc->elantech;
  1841. switch (sc->inputstate) {
  1842. case 0:
  1843. if (elantech->flags & ELANTECH_F_CRC_ENABLED)
  1844. break;
  1845. if ((data & 0x0c) != 0x04 && (data & 0x0c) != 0x0c)
  1846. return (-1);
  1847. break;
  1848. case 3:
  1849. if (elantech->flags & ELANTECH_F_CRC_ENABLED) {
  1850. if ((data & 0x09) != 0x08 && (data & 0x09) != 0x09)
  1851. return (-1);
  1852. } else {
  1853. if ((data & 0xcf) != 0x02 && (data & 0xce) != 0x0c)
  1854. return (-1);
  1855. }
  1856. break;
  1857. }
  1858. return (0);
  1859. }
  1860. int
  1861. pms_sync_elantech_v4(struct pms_softc *sc, int data)
  1862. {
  1863. if (sc->inputstate == 0 && (data & 0x0c) != 0x04)
  1864. return (-1);
  1865. else
  1866. return (0);
  1867. }
  1868. void
  1869. pms_proc_elantech_v1(struct pms_softc *sc)
  1870. {
  1871. struct elantech_softc *elantech = sc->elantech;
  1872. int x, y, w, z;
  1873. if (elantech->flags & ELANTECH_F_HW_V1_OLD)
  1874. w = ((sc->packet[1] & 0x80) >> 7) +
  1875. ((sc->packet[1] & 0x30) >> 4);
  1876. else
  1877. w = (sc->packet[0] & 0xc0) >> 6;
  1878. /* Hardware version 1 doesn't report pressure. */
  1879. if (w) {
  1880. x = ((sc->packet[1] & 0x0c) << 6) | sc->packet[2];
  1881. y = ((sc->packet[1] & 0x03) << 8) | sc->packet[3];
  1882. z = SYNAPTICS_PRESSURE;
  1883. } else {
  1884. x = elantech->old_x;
  1885. y = elantech->old_y;
  1886. z = 0;
  1887. }
  1888. elantech_send_input(sc, x, y, z, w);
  1889. }
  1890. void
  1891. pms_proc_elantech_v2(struct pms_softc *sc)
  1892. {
  1893. const u_char debounce_pkt[] = { 0x84, 0xff, 0xff, 0x02, 0xff, 0xff };
  1894. struct elantech_softc *elantech = sc->elantech;
  1895. int x, y, w, z;
  1896. /*
  1897. * The hardware sends this packet when in debounce state.
  1898. * The packet should be ignored.
  1899. */
  1900. if (!memcmp(sc->packet, debounce_pkt, sizeof(debounce_pkt)))
  1901. return;
  1902. w = (sc->packet[0] & 0xc0) >> 6;
  1903. if (w == 1 || w == 3) {
  1904. x = ((sc->packet[1] & 0x0f) << 8) | sc->packet[2];
  1905. y = ((sc->packet[4] & 0x0f) << 8) | sc->packet[5];
  1906. if (elantech->flags & ELANTECH_F_REPORTS_PRESSURE)
  1907. z = ((sc->packet[1] & 0xf0) |
  1908. (sc->packet[4] & 0xf0) >> 4);
  1909. else
  1910. z = SYNAPTICS_PRESSURE;
  1911. } else if (w == 2) {
  1912. x = (((sc->packet[0] & 0x10) << 4) | sc->packet[1]) << 2;
  1913. y = (((sc->packet[0] & 0x20) << 3) | sc->packet[2]) << 2;
  1914. z = SYNAPTICS_PRESSURE;
  1915. } else {
  1916. x = elantech->old_x;
  1917. y = elantech->old_y;
  1918. z = 0;
  1919. }
  1920. elantech_send_input(sc, x, y, z, w);
  1921. }
  1922. void
  1923. pms_proc_elantech_v3(struct pms_softc *sc)
  1924. {
  1925. const u_char debounce_pkt[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff };
  1926. struct elantech_softc *elantech = sc->elantech;
  1927. int x, y, w, z;
  1928. x = ((sc->packet[1] & 0x0f) << 8 | sc->packet[2]);
  1929. y = ((sc->packet[4] & 0x0f) << 8 | sc->packet[5]);
  1930. z = 0;
  1931. w = (sc->packet[0] & 0xc0) >> 6;
  1932. if (w == 2) {
  1933. /*
  1934. * Two-finger touch causes two packets -- a head packet
  1935. * and a tail packet. We report a single event and ignore
  1936. * the tail packet.
  1937. */
  1938. if (elantech->flags & ELANTECH_F_CRC_ENABLED) {
  1939. if ((sc->packet[3] & 0x09) != 0x08)
  1940. return;
  1941. } else {
  1942. /* The hardware sends this packet when in debounce state.
  1943. * The packet should be ignored. */
  1944. if (!memcmp(sc->packet, debounce_pkt, sizeof(debounce_pkt)))
  1945. return;
  1946. if ((sc->packet[0] & 0x0c) != 0x04 &&
  1947. (sc->packet[3] & 0xcf) != 0x02) {
  1948. /* not the head packet -- ignore */
  1949. return;
  1950. }
  1951. }
  1952. }
  1953. /* Prevent juming cursor if pad isn't touched or reports garbage. */
  1954. if (w == 0 ||
  1955. ((x == 0 || y == 0 || x == elantech->max_x || y == elantech->max_y)
  1956. && (x != elantech->old_x || y != elantech->old_y))) {
  1957. x = elantech->old_x;
  1958. y = elantech->old_y;
  1959. }
  1960. if (elantech->flags & ELANTECH_F_REPORTS_PRESSURE)
  1961. z = (sc->packet[1] & 0xf0) | ((sc->packet[4] & 0xf0) >> 4);
  1962. else if (w)
  1963. z = SYNAPTICS_PRESSURE;
  1964. elantech_send_input(sc, x, y, z, w);
  1965. }
  1966. void
  1967. pms_proc_elantech_v4(struct pms_softc *sc)
  1968. {
  1969. struct elantech_softc *elantech = sc->elantech;
  1970. int n, id, slots, weight, dx, dy;
  1971. switch (sc->packet[3] & 0x1f) {
  1972. case ELANTECH_V4_PKT_STATUS:
  1973. if (elantech->mt_slots == 0)
  1974. elantech->mt_lastid = -1;
  1975. slots = sc->packet[1] & 0x1f;
  1976. if (slots == 0 && elantech->mt_lastid > -1)
  1977. /* Notify that we lifted. */
  1978. elantech_send_input(sc,
  1979. elantech->mt[elantech->mt_lastid].x,
  1980. elantech->mt[elantech->mt_lastid].y, 0, 0);
  1981. elantech->mt_filter = elantech->mt_slots = slots;
  1982. for (elantech->mt_count = 0; slots != 0; slots >>= 1)
  1983. elantech->mt_count += (1 & slots);
  1984. break;
  1985. case ELANTECH_V4_PKT_HEAD:
  1986. id = ((sc->packet[3] & 0xe0) >> 5) - 1;
  1987. if (id > -1 && id < ELANTECH_MAX_FINGERS) {
  1988. elantech->mt[id].x =
  1989. ((sc->packet[1] & 0x0f) << 8) | sc->packet[2];
  1990. elantech->mt[id].y =
  1991. ((sc->packet[4] & 0x0f) << 8) | sc->packet[5];
  1992. elantech->mt[id].z =
  1993. (sc->packet[1] & 0xf0)
  1994. | ((sc->packet[4] & 0xf0) >> 4);
  1995. if (elantech->mt_filter & (1 << id)) {
  1996. elantech_send_mt_input(sc, id);
  1997. elantech->mt_filter = (1 << id);
  1998. }
  1999. }
  2000. break;
  2001. case ELANTECH_V4_PKT_MOTION:
  2002. weight = (sc->packet[0] & 0x10) ? ELANTECH_V4_WEIGHT_VALUE : 1;
  2003. for (n = 0; n < 6; n += 3) {
  2004. id = ((sc->packet[n] & 0xe0) >> 5) - 1;
  2005. if (id < 0 || id >= ELANTECH_MAX_FINGERS)
  2006. continue;
  2007. dx = weight * (signed char)sc->packet[n + 1];
  2008. dy = weight * (signed char)sc->packet[n + 2];
  2009. elantech->mt[id].x += dx;
  2010. elantech->mt[id].y += dy;
  2011. elantech->mt[id].z = 1;
  2012. if (elantech->mt_filter & (1 << id)) {
  2013. if ((dx | dy)
  2014. || elantech->mt_count !=
  2015. elantech->mt_lastcount
  2016. || (sc->packet[0] & 3) !=
  2017. elantech->mt_buttons)
  2018. elantech_send_mt_input(sc, id);
  2019. elantech->mt_filter = (dx | dy) ?
  2020. (1 << id) : elantech->mt_slots;
  2021. }
  2022. }
  2023. break;
  2024. default:
  2025. printf("%s: unknown packet type 0x%x\n", DEVNAME(sc),
  2026. sc->packet[3] & 0x1f);
  2027. return;
  2028. }
  2029. }
  2030. void
  2031. elantech_send_mt_input(struct pms_softc *sc, int id)
  2032. {
  2033. struct elantech_softc *elantech = sc->elantech;
  2034. if (id != elantech->mt_lastid) {
  2035. /* Correct for compatibility mode, but not useful yet: */
  2036. elantech->old_x = elantech->mt[id].x;
  2037. elantech->old_y = elantech->mt[id].y;
  2038. /*
  2039. * To avoid a jump of the cursor, simulate a change of the
  2040. * number of touches (without producing tapping gestures
  2041. * accidentally). It should suffice to do that only if
  2042. * mt_count hasn't changed, but we cannot rely on the
  2043. * synaptics driver, which alters its finger counts when
  2044. * handling click-and-drag actions (see HandleTapProcessing
  2045. * and ComputeDeltas in synaptics.c).
  2046. */
  2047. if (elantech->mt_lastid > -1)
  2048. elantech_send_input(sc,
  2049. elantech->mt[id].x, elantech->mt[id].y,
  2050. elantech->mt[id].z, ELANTECH_MAX_FINGERS);
  2051. elantech->mt_lastid = id;
  2052. }
  2053. elantech->mt_lastcount = elantech->mt_count;
  2054. elantech->mt_buttons = sc->packet[0] & 3;
  2055. elantech_send_input(sc,
  2056. elantech->mt[id].x, elantech->mt[id].y,
  2057. elantech->mt[id].z, elantech->mt_count);
  2058. }
  2059. void
  2060. elantech_send_input(struct pms_softc *sc, int x, int y, int z, int w)
  2061. {
  2062. struct elantech_softc *elantech = sc->elantech;
  2063. int dx, dy;
  2064. u_int buttons = 0;
  2065. if (sc->packet[0] & 0x01)
  2066. buttons |= WSMOUSE_BUTTON(1);
  2067. if (sc->packet[0] & 0x02)
  2068. buttons |= WSMOUSE_BUTTON(3);
  2069. if (elantech->flags & ELANTECH_F_HAS_ROCKER) {
  2070. if (sc->packet[0] & 0x40) /* up */
  2071. buttons |= WSMOUSE_BUTTON(4);
  2072. if (sc->packet[0] & 0x80) /* down */
  2073. buttons |= WSMOUSE_BUTTON(5);
  2074. }
  2075. if (elantech->wsmode == WSMOUSE_NATIVE) {
  2076. wsmouse_input(sc->sc_wsmousedev, buttons, x, y, z, w,
  2077. WSMOUSE_INPUT_ABSOLUTE_X |
  2078. WSMOUSE_INPUT_ABSOLUTE_Y |
  2079. WSMOUSE_INPUT_ABSOLUTE_Z |
  2080. WSMOUSE_INPUT_ABSOLUTE_W);
  2081. } else {
  2082. dx = dy = 0;
  2083. if ((elantech->flags & ELANTECH_F_REPORTS_PRESSURE) &&
  2084. z > SYNAPTICS_PRESSURE) {
  2085. dx = x - elantech->old_x;
  2086. dy = y - elantech->old_y;
  2087. dx /= SYNAPTICS_SCALE;
  2088. dy /= SYNAPTICS_SCALE;
  2089. }
  2090. if (dx || dy || buttons != elantech->old_buttons)
  2091. wsmouse_input(sc->sc_wsmousedev, buttons, dx, dy, 0, 0,
  2092. WSMOUSE_INPUT_DELTA);
  2093. elantech->old_buttons = buttons;
  2094. }
  2095. elantech->old_x = x;
  2096. elantech->old_y = y;
  2097. }