2 * Copyright (c) 2014 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * ATMEL_MXT - Atmel MXT touchscreen driver
37 * PRELIMINARY DRIVER PRELIMINARY DRIVER PRELIMINARY DRIVERE
39 * (everything is pretty much hardwired and we assume the device is already
40 * operational, which it appears to be. ONLY TESTED ON ACER C720).
42 * This driver attaches to Acer TouchScreen MXT chipsets and currently
43 * emulates the ELO touchscreen serial protocol "elographics" for X:
45 * Section "InputDevice"
46 * Identifier "TouchScreen0"
47 * Driver "elographics"
48 * Option "Device" "/dev/atmel1-4a"
51 * The MXT chipsets typically attach on haswell chromebooks on one of the I2C
52 * busses at address 0x4A. On my Acer C720 it attaches to the ig4 driver's
53 * I2C bus #1 at 0x4A. kldload ig4; kldload atmel_mxt.
55 * The kernel driver and test code is written from scratch, but some code has
56 * been snarfed (in separate files) from linux development as referenced
59 * www.atmel.com/products/touchsolutions/touchscreens/unlimited_touch.aspx
60 * git://github.com/atmel-maxtouch/obp-utils.git
62 * The linux driver was also consulted, but not used. Note that the linux
63 * driver appears to be GPL'd but uses code from obp-utils.git on github
64 * which is (c)Copyright by Atmel and uses more of a BSD-like license. The
65 * obp-* source files contain the snarfed code and include this license.
67 * The ELO touchscreen serial protocol uses 10-byte fixed-length packets:
69 * Byte 0: ELO_SYNC_BYTE ('U')
70 * Byte 1-8: Packet data
71 * Byte 9: checksum of bytes 0 to 8
73 * Our interface reads and writes only whole packets and does not do any
74 * buffer stitching. It is compatible with Xorg.
76 * Control Commands sent from Userland (only an Ack packet is returned)
78 * Byte 0: ELO_SYNC_BYTE ('U')
79 * Byte 1: ELO_MODE ('m')
90 * Byte 0: ELO_SYNC_BYTE ('U')
91 * Byte 1: ELO_REPORT ('r')
93 * Query Command sent from Userland: (expect response packet and Ack packet)
95 * Byte 0: ELO_SYNC_BYTE ('U') Request ID
96 * Byte 1: ELO_ID ('i')
98 * Byte 0: ELO_SYNC_BYTE ('U')` Request Owner
99 * Byte 1: ELO_OWNER ('o')
101 * Streaming packets sent from the driver to userland
103 * Byte 0: ELO_SYNC_BYTE ('U')
104 * Byte 1: ELO_TOUCH ('T')
105 * Byte 2: Packet type
106 * Bit 2 : Pen Up (Release) 0x04
107 * Bit 1 : Position (Stream) 0x02
108 * Bit 0 : Pen Down (Press) 0x01
109 * Byte 3: X coordinate lsb
110 * Byte 4: X coordinate msb
111 * Byte 5: Y coordinate lsb
112 * Byte 6: Y coordinate msb
113 * Byte 7: Z coordinate lsb
114 * Byte 8: Z coordinate msb
116 * Responses to commands: (one or two packets returned)
118 * Byte 0: ELO_SYNC_BYTE ('U') (if in response to query)
119 * Byte 1: toupper(command_byte) (control commands have no
120 * Byte 2-8: ... depends .... response)
122 * Byte 0: ELO_SYNC_BYTE ('U') (unconditional ack)
124 * Byte 2-8: ... depends ....
126 * NOTE! For the most part we ignore commands other than doing the handwaving
127 * to send a dummied-up response and ack as assumed by the X driver.
128 * Also, the read() and write() support only reads and writes whole
129 * packets. There is NO byte-partial buffering. The X driver appears
130 * to be compatible with these restrictions.
132 * figure out the bootstrapping and commands.
134 * Unable to locate any datasheet for the device.
138 * Currently no features. Only one finger is supported by this attachment
139 * for now and I haven't written any de-jitter and finger-transfer code.
140 * This is good enough for moving and resizing windows (given big enough
141 * widgets), and hitting browser buttons and hotlinks.
143 * Currently no scrolling control or other features. We would need to
144 * basically implement either the linux general input even infrastructure
145 * which is a LOT of code, or a mouse emulator to handle scrolling emulation.
147 #include <sys/kernel.h>
148 #include <sys/param.h>
149 #include <sys/systm.h>
150 #include <sys/device.h>
151 #include <sys/module.h>
153 #include <sys/conf.h>
155 #include <sys/fcntl.h>
156 /*#include <sys/input.h>*/
157 #include <sys/vnode.h>
158 #include <sys/sysctl.h>
159 #include <sys/event.h>
160 #include <sys/devfs.h>
162 #include <bus/smbus/smbconf.h>
163 #include <bus/smbus/smbus.h>
164 #include "atmel_mxt.h"
166 #include "smbus_if.h"
168 #include "device_if.h"
183 typedef struct elopacket elopacket_t;
185 typedef struct atmel_track {
190 int report; /* what we have to report */
193 #define ATMEL_TRACK_RELEASED 0
194 #define ATMEL_TRACK_PRESSED 1
196 #define ATMEL_REPORT_PRESS 0x0001
197 #define ATMEL_REPORT_MOVE 0x0002
198 #define ATMEL_REPORT_RELEASE 0x0004
200 #define ATMEL_MAXTRACK 10
202 struct atmel_mxt_softc {
204 int count; /* >0 if device opened */
208 struct kqinfo kqinfo;
217 struct mxt_rollup core;
218 struct mxt_object *msgprocobj;
219 struct mxt_object *cmdprocobj;
230 atmel_track_t track[ATMEL_MAXTRACK];
234 elopacket_t pend_rep; /* pending reply to command */
235 int pend_ack; /* pending reply mode */
237 int last_active_tick;
238 int last_calibrate_tick;
239 int data_signal; /* something ready to read */
240 int blocked; /* someone is blocking */
242 int sample_rate; /* samples/sec */
246 typedef struct atmel_mxt_softc atmel_mxt_softc_t;
248 #define ATMEL_POLL_SHUTDOWN 0x0001
250 #define PEND_ACK_NONE 0 /* no reply to command pending */
251 #define PEND_ACK_RESPOND 1 /* reply w/response and ack */
252 #define PEND_ACK_ACK 2 /* reply w/ack only */
254 #define REPORT_NONE 0x0000
255 #define REPORT_ALL 0x0001
258 * Async debug variable commands are executed by the poller and will
261 static int atmel_mxt_idle_freq = 1;
262 SYSCTL_INT(_debug, OID_AUTO, atmel_mxt_idle_freq, CTLFLAG_RW,
263 &atmel_mxt_idle_freq, 0, "");
264 static int atmel_mxt_slow_freq = 20;
265 SYSCTL_INT(_debug, OID_AUTO, atmel_mxt_slow_freq, CTLFLAG_RW,
266 &atmel_mxt_slow_freq, 0, "");
267 static int atmel_mxt_norm_freq = 100;
268 SYSCTL_INT(_debug, OID_AUTO, atmel_mxt_norm_freq, CTLFLAG_RW,
269 &atmel_mxt_norm_freq, 0, "");
270 static int atmel_mxt_minpressure = 16;
271 SYSCTL_INT(_debug, OID_AUTO, atmel_mxt_minpressure, CTLFLAG_RW,
272 &atmel_mxt_minpressure, 0, "");
273 static int atmel_mxt_reset = 0;
274 SYSCTL_INT(_debug, OID_AUTO, atmel_mxt_reset, CTLFLAG_RW,
275 &atmel_mxt_reset, 0, "");
278 * Run a calibration command every N seconds only when idle. 0 to disable.
279 * Default every 30 seconds.
281 static int atmel_mxt_autocalibrate = 30;
282 SYSCTL_INT(_debug, OID_AUTO, atmel_mxt_autocalibrate, CTLFLAG_RW,
283 &atmel_mxt_autocalibrate, 0, "");
286 * run a calibration on module startup.
288 static int atmel_mxt_debug = 0;
289 SYSCTL_INT(_debug, OID_AUTO, atmel_mxt_debug, CTLFLAG_RW,
290 &atmel_mxt_debug, 0, "");
292 static void atmel_mxt_poll_thread(void *arg);
293 static void atmel_find_active_state(atmel_mxt_softc_t *sc);
294 static int atmel_mxt_raw_input(atmel_mxt_softc_t *sc, mxt_message_t *msg);
295 static struct mxt_object *mxt_findobject(struct mxt_rollup *core, int type);
296 static int mxt_read_reg(atmel_mxt_softc_t *sc, uint16_t reg,
297 void *rbuf, int bytes);
298 static int mxt_write_reg_buf(atmel_mxt_softc_t *sc, uint16_t reg,
299 void *xbuf, int bytes);
300 static int mxt_write_reg(atmel_mxt_softc_t *sc, uint16_t reg, uint8_t val);
301 static int mxt_read_object(atmel_mxt_softc_t *sc, struct mxt_object *obj,
302 void *rbuf, int rbytes);
303 static int mxt_write_object_off(atmel_mxt_softc_t *sc, struct mxt_object *obj,
304 int offset, uint8_t val);
305 static void atmel_reset_device(atmel_mxt_softc_t *sc);
309 msgflagsstr(uint8_t flags)
313 buf[0] = (flags & MXT_MSGF_DETECT) ? 'D' : '.';
314 buf[1] = (flags & MXT_MSGF_PRESS) ? 'P' : '.';
315 buf[2] = (flags & MXT_MSGF_RELEASE) ? 'R' : '.';
316 buf[3] = (flags & MXT_MSGF_MOVE) ? 'M' : '.';
317 buf[4] = (flags & MXT_MSGF_VECTOR) ? 'V' : '.';
318 buf[5] = (flags & MXT_MSGF_AMP) ? 'A' : '.';
319 buf[6] = (flags & MXT_MSGF_SUPPRESS) ? 'S' : '.';
320 buf[7] = (flags & MXT_MSGF_UNGRIP) ? 'U' : '.';
327 atmel_mxt_lock(atmel_mxt_softc_t *sc)
329 lockmgr(&sc->lk, LK_EXCLUSIVE);
334 atmel_mxt_unlock(atmel_mxt_softc_t *sc)
336 lockmgr(&sc->lk, LK_RELEASE);
340 * Notify if possible receive data ready. Must be called
341 * without the lock held to avoid deadlocking in kqueue.
345 atmel_mxt_notify(atmel_mxt_softc_t *sc)
347 if (sc->data_signal) {
348 KNOTE(&sc->kqinfo.ki_note, 0);
352 wakeup(&sc->blocked);
354 atmel_mxt_unlock(sc);
359 * Initialize the device
363 init_device(atmel_mxt_softc_t *sc, int probe)
369 if (mxt_read_reg(sc, 0, &sc->core.info, sizeof(sc->core.info))) {
370 device_printf(sc->dev, "init_device read-reg failed\n");
373 sc->core.nobjs = sc->core.info.num_objects;
375 device_printf(sc->dev,
376 "%d configuration objects\n",
377 sc->core.info.num_objects);
379 if (sc->core.nobjs < 0 || sc->core.nobjs > 1024) {
380 device_printf(sc->dev,
381 "init_device nobjs (%d) out of bounds\n",
385 blksize = sizeof(sc->core.info) +
386 sc->core.nobjs * sizeof(struct mxt_object);
387 totsize = blksize + sizeof(struct mxt_raw_crc);
389 sc->core.buf = kmalloc(totsize, M_DEVBUF, M_WAITOK | M_ZERO);
390 if (mxt_read_reg(sc, 0, sc->core.buf, totsize)) {
391 device_printf(sc->dev,
392 "init_device cannot read configuration space\n");
395 kprintf("COREBUF %p %d\n", sc->core.buf, blksize);
396 crc = obp_convert_crc((void *)((uint8_t *)sc->core.buf + blksize));
397 if (obp_crc24(sc->core.buf, blksize) != crc) {
398 device_printf(sc->dev,
399 "init_device: configuration space "
400 "crc mismatch %08x/%08x\n",
401 crc, obp_crc24(sc->core.buf, blksize));
408 for (i = 0; i < sizeof(sc->core.info); ++i)
409 kprintf(" %02x", sc->core.buf[i]);
410 kprintf("\nconfig: ");
411 while (i < blksize) {
412 kprintf(" %02x", sc->core.buf[i]);
417 sc->core.objs = (void *)((uint8_t *)sc->core.buf +
418 sizeof(sc->core.info));
419 sc->msgprocobj = mxt_findobject(&sc->core, MXT_GEN_MESSAGEPROCESSOR);
420 sc->cmdprocobj = mxt_findobject(&sc->core, MXT_GEN_COMMANDPROCESSOR);
421 if (sc->msgprocobj == NULL) {
422 device_printf(sc->dev,
423 "init_device: cannot find msgproc config\n");
428 if (sc->msgprocobj == NULL) {
430 kfree(sc->core.buf, M_DEVBUF);
436 kfree(sc->core.buf, M_DEVBUF);
439 atmel_reset_device(sc);
446 * Device infrastructure
448 #define ATMEL_SOFTC(unit) \
449 ((atmel_mxt_softc_t *)devclass_get_softc(atmel_mxt_devclass, (unit)))
451 static void atmel_mxt_identify(driver_t *driver, device_t parent);
452 static int atmel_mxt_probe(device_t);
453 static int atmel_mxt_attach(device_t);
454 static int atmel_mxt_detach(device_t);
456 static devclass_t atmel_mxt_devclass;
458 static device_method_t atmel_mxt_methods[] = {
459 /* device interface */
460 DEVMETHOD(device_identify, atmel_mxt_identify),
461 DEVMETHOD(device_probe, atmel_mxt_probe),
462 DEVMETHOD(device_attach, atmel_mxt_attach),
463 DEVMETHOD(device_detach, atmel_mxt_detach),
466 /* smbus interface */
467 DEVMETHOD(smbus_intr, smbus_generic_intr),
473 static driver_t atmel_mxt_driver = {
476 sizeof(atmel_mxt_softc_t),
479 static d_open_t atmel_mxtopen;
480 static d_close_t atmel_mxtclose;
481 static d_ioctl_t atmel_mxtioctl;
482 static d_read_t atmel_mxtread;
483 static d_write_t atmel_mxtwrite;
484 static d_kqfilter_t atmel_mxtkqfilter;
486 static struct dev_ops atmel_mxt_ops = {
487 { "atmel_mxt", 0, 0 },
488 .d_open = atmel_mxtopen,
489 .d_close = atmel_mxtclose,
490 .d_ioctl = atmel_mxtioctl,
491 .d_read = atmel_mxtread,
492 .d_write = atmel_mxtwrite,
493 .d_kqfilter = atmel_mxtkqfilter,
497 atmel_mxt_identify(driver_t *driver, device_t parent)
499 if (device_find_child(parent, "atmel_mxt", -1) == NULL)
500 BUS_ADD_CHILD(parent, parent, 0, "atmel_mxt", -1);
504 atmel_mxt_probe(device_t dev)
506 atmel_mxt_softc_t sc;
509 bzero(&sc, sizeof(sc));
511 sc.unit = device_get_unit(dev);
514 * Only match against specific addresses to avoid blowing up
515 * other I2C devices (?). At least for now.
517 * 0x400 (from smbus) - means specific device address probe,
518 * rather than generic.
520 * 0x4A - cypress trackpad on the acer c720.
522 if ((sc.unit & 0x04FF) != (0x0400 | 0x04A))
524 sc.addr = sc.unit & 0x3FF;
525 error = init_device(&sc, 1);
529 device_set_desc(dev, "Atmel MXT TouchScreen");
531 return (BUS_PROBE_VENDOR);
535 atmel_mxt_attach(device_t dev)
537 atmel_mxt_softc_t *sc;
539 sc = (atmel_mxt_softc_t *)device_get_softc(dev);
543 bzero(sc, sizeof(*sc));
545 lockinit(&sc->lk, "atmel_mxt", 0, 0);
546 sc->reporting_mode = 1;
549 sc->unit = device_get_unit(dev);
550 if ((sc->unit & 0x04FF) != (0x0400 | 0x04A))
552 sc->addr = sc->unit & 0x3FF;
553 sc->last_active_tick = ticks;
554 sc->last_calibrate_tick = ticks - atmel_mxt_autocalibrate * hz;
556 if (init_device(sc, 0))
559 if (sc->unit & 0x0400) {
560 sc->devnode = make_dev(&atmel_mxt_ops, sc->unit,
561 UID_ROOT, GID_WHEEL, 0600,
563 sc->unit >> 11, sc->unit & 1023);
565 sc->devnode = make_dev(&atmel_mxt_ops, sc->unit,
566 UID_ROOT, GID_WHEEL, 0600, "atmel%d", sc->unit);
568 device_printf(dev, "atmel mxt touchscreen driver attached\n");
569 /* device_printf(dev, "...."); */
572 * Start the polling thread.
574 lwkt_create(atmel_mxt_poll_thread, sc,
575 &sc->poll_td, NULL, 0, -1, "atmel_mxt-poll");
581 atmel_mxt_detach(device_t dev)
583 atmel_mxt_softc_t *sc;
585 sc = (atmel_mxt_softc_t *)device_get_softc(dev);
588 * Cleanup our poller thread
590 atomic_set_int(&sc->poll_flags, ATMEL_POLL_SHUTDOWN);
591 while (sc->poll_td) {
592 wakeup(&sc->poll_flags);
593 tsleep(&sc->poll_td, 0, "atmel_mxtdet", hz);
597 dev_ops_remove_minor(&atmel_mxt_ops, device_get_unit(dev));
599 devfs_assume_knotes(sc->devnode, &sc->kqinfo);
601 kfree(sc->core.buf, M_DEVBUF);
604 sc->msgprocobj = NULL;
605 sc->cmdprocobj = NULL;
611 * USER DEVICE I/O FUNCTIONS
614 atmel_mxtopen (struct dev_open_args *ap)
616 cdev_t dev = ap->a_head.a_dev;
617 atmel_mxt_softc_t *sc = ATMEL_SOFTC(minor(dev));
631 atmel_mxtclose(struct dev_close_args *ap)
633 cdev_t dev = ap->a_head.a_dev;
634 atmel_mxt_softc_t *sc = ATMEL_SOFTC(minor(dev));
639 if (sc->count == 0) {
640 /* This is not supposed to happen. */
644 if (sc->count-- == 0) {
645 sc->reporting_mode = 0;
652 atmel_mxtread(struct dev_read_args *ap)
654 cdev_t dev = ap->a_head.a_dev;
655 atmel_mxt_softc_t *sc = ATMEL_SOFTC(minor(dev));
657 struct uio *uio = ap->a_uio;
658 int ioflag = ap->a_ioflag;
661 atmel_track_t *track;
664 * Load next ready event, block if necessary.
670 switch(sc->pend_ack) {
672 if (sc->tracking && sc->track[sc->tracking].report) {
676 track = &sc->track[sc->tracking];
677 bzero(&pkt, sizeof(pkt));
679 if (track->report & ATMEL_REPORT_PRESS) {
681 track->report &= ~ATMEL_REPORT_PRESS;
682 } else if (track->report & ATMEL_REPORT_MOVE) {
684 track->report &= ~ATMEL_REPORT_MOVE;
685 } else if (track->report &
686 ATMEL_REPORT_RELEASE) {
688 track->report &= ~ATMEL_REPORT_RELEASE;
690 pkt.byte3 = track->x & 0xFF;
691 pkt.byte4 = track->x >> 8;
692 pkt.byte5 = track->y & 0xFF;
693 pkt.byte6 = track->y >> 8;
694 pkt.byte7 = track->pressure & 0xFF;
695 pkt.byte8 = track->pressure >> 8;
696 } else if (ioflag & IO_NDELAY) {
698 * Non-blocking, nothing ready
703 * Blocking, nothing ready
707 error = lksleep(&sc->blocked, &sc->lk,
708 PCATCH, "atmelw", 0);
713 case PEND_ACK_RESPOND:
715 sc->pend_ack = PEND_ACK_ACK;
718 bzero(&pkt, sizeof(pkt));
720 sc->pend_ack = PEND_ACK_NONE;
723 atmel_find_active_state(sc);
726 atmel_mxt_unlock(sc);
729 * If no error we can return the event loaded into pkt.
736 for (i = 0; i < sizeof(pkt) - 1; ++i)
737 csum += ((uint8_t *)&pkt)[i];
742 error = uiomove((void *)&pkt, n, uio);
749 atmel_mxtwrite(struct dev_write_args *ap)
751 cdev_t dev = ap->a_head.a_dev;
752 atmel_mxt_softc_t *sc = ATMEL_SOFTC(minor(dev));
753 struct uio *uio = ap->a_uio;
760 while (uio->uio_resid) {
761 bzero(&pkt, sizeof(pkt));
765 error = uiomove((void *)&pkt, n, uio);
774 bzero(&sc->pend_rep, sizeof(sc->pend_rep));
775 sc->pend_rep.cmd = 'I';
776 sc->pend_ack = PEND_ACK_RESPOND;
780 * ELO_OWNER request owner
782 bzero(&sc->pend_rep, sizeof(sc->pend_rep));
783 sc->pend_rep.cmd = 'O';
784 sc->pend_ack = PEND_ACK_RESPOND;
788 * ELO_MODE control packet
790 sc->pend_ack = PEND_ACK_ACK;
794 * ELO_REPORT control packet
796 sc->pend_ack = PEND_ACK_ACK;
799 atmel_mxt_unlock(sc);
804 static void atmel_mxt_filt_detach(struct knote *);
805 static int atmel_mxt_filt(struct knote *, long);
807 static struct filterops atmel_mxt_filtops =
808 { FILTEROP_ISFD, NULL, atmel_mxt_filt_detach, atmel_mxt_filt };
811 atmel_mxtkqfilter(struct dev_kqfilter_args *ap)
813 cdev_t dev = ap->a_head.a_dev;
814 atmel_mxt_softc_t *sc = ATMEL_SOFTC(minor(dev));
815 struct knote *kn = ap->a_kn;
818 switch(kn->kn_filter) {
820 kn->kn_fop = &atmel_mxt_filtops;
821 kn->kn_hook = (void *)sc;
825 ap->a_result = EOPNOTSUPP;
828 klist = &sc->kqinfo.ki_note;
829 knote_insert(klist, kn);
835 atmel_mxt_filt_detach(struct knote *kn)
837 atmel_mxt_softc_t *sc = (atmel_mxt_softc_t *)kn->kn_hook;
840 klist = &sc->kqinfo.ki_note;
841 knote_remove(klist, kn);
845 atmel_mxt_filt(struct knote *kn, long hint)
847 atmel_mxt_softc_t *sc = (atmel_mxt_softc_t *)kn->kn_hook;
855 atmel_mxt_unlock(sc);
861 atmel_mxtioctl(struct dev_ioctl_args *ap)
863 cdev_t dev = ap->a_head.a_dev;
864 device_t bus; /* smbbus */
865 /*struct atmel_mxtcmd *s = (struct atmel_mxtcmd *)ap->a_data;*/
867 atmel_mxt_softc_t *sc = ATMEL_SOFTC(minor(dev));
876 * NOTE: smbus_*() functions automatically recurse the parent to
877 * get to the actual device driver.
879 bus = device_get_parent(sc->dev); /* smbus */
881 /* Allocate the bus. */
882 if ((error = smbus_request_bus(bus, sc->dev,
883 (ap->a_fflag & O_NONBLOCK) ?
884 SMB_DONTWAIT : (SMB_WAIT | SMB_INTR))))
890 error = inputev_ioctl(&sc->iev, ap->a_cmd, ap->a_data);
896 smbus_release_bus(bus, sc->dev);
902 * MAJOR SUPPORT FUNCTIONS
906 atmel_mxt_poll_thread(void *arg)
908 atmel_mxt_softc_t *sc = arg;
910 int freq = atmel_mxt_norm_freq;
913 while ((sc->poll_flags & ATMEL_POLL_SHUTDOWN) == 0) {
921 error = mxt_read_object(sc, sc->msgprocobj,
924 isidle = atmel_mxt_raw_input(sc, &msg);
930 * don't let the last_active_tick or last_calibrate_tick
931 * delta calculation overflow.
933 if ((ticks - sc->last_active_tick) > 1000 * hz)
934 sc->last_active_tick = ticks - 1000 * hz;
935 if ((ticks - sc->last_calibrate_tick) > 1000 * hz)
936 sc->last_calibrate_tick = ticks - 1000 * hz;
941 if (atmel_mxt_reset) {
943 atmel_reset_device(sc);
947 * Automatically calibrate when the touchpad has been
948 * idle atmel_mxt_autocalibrate seconds, and recalibrate
949 * on the same interval while it remains idle.
951 * If we don't do this the touchscreen can get really out
952 * of whack over time and basically stop functioning properly.
953 * It's unclear why the device does not do this automatically.
955 * Response occurs in the message stream (which we just
958 if (sc->cmdprocobj && atmel_mxt_autocalibrate &&
959 ((ticks - sc->last_calibrate_tick) >
960 atmel_mxt_autocalibrate * hz) &&
961 ((ticks - sc->last_active_tick) >
962 atmel_mxt_autocalibrate * hz)) {
963 sc->last_calibrate_tick = ticks;
964 mxt_write_object_off(sc, sc->cmdprocobj,
965 MXT_CMDPROC_CALIBRATE_OFF, 1);
967 tsleep(&sc->poll_flags, 0, "atmpol", (hz + freq - 1) / freq);
970 freq = atmel_mxt_idle_freq;
972 freq = atmel_mxt_slow_freq;
974 freq = atmel_mxt_norm_freq;
977 wakeup(&sc->poll_td);
982 atmel_reset_device(atmel_mxt_softc_t *sc)
985 mxt_write_object_off(sc, sc->cmdprocobj, MXT_CMDPROC_RESET_OFF, 1);
986 tsleep(&dummy, 0, "atmel_reset", hz * 2);
990 * Calculate currently active state, if any
994 atmel_find_active_state(atmel_mxt_softc_t *sc)
996 atmel_track_t *track;
999 track = &sc->track[sc->tracking];
1000 if (track->report == 0) {
1001 for (i = 0; i < ATMEL_MAXTRACK; ++i) {
1002 track = &sc->track[i];
1003 if (track->report) {
1009 if (track->report == 0 && sc->pend_ack == PEND_ACK_NONE) {
1010 sc->data_signal = 0;
1012 sc->data_signal = 1;
1017 * Return non-zero if we are idle
1021 atmel_mxt_raw_input(atmel_mxt_softc_t *sc, mxt_message_t *msg)
1023 atmel_track_t *track;
1026 if (atmel_mxt_debug) {
1027 kprintf("track=%02x f=%s x=%-4d y=%-4d p=%d amp=%d\n",
1029 msgflagsstr(msg->touch.flags),
1030 (msg->touch.pos[0] << 4) |
1031 ((msg->touch.pos[2] >> 4) & 0x0F),
1032 (msg->touch.pos[1] << 4) |
1033 ((msg->touch.pos[2]) & 0x0F),
1035 msg->touch.amplitude);
1040 * If message buffer is empty and no fingers are currently pressed
1041 * return idle, else we are not idle.
1043 if (msg->any.reportid == 0xFF)
1047 * Process message buffer. For now ignore any messages with
1048 * reportids that we do not understand.
1050 * note: reportid==1 typicallk acknowledges calibrations (?)
1052 if (msg->any.reportid < 3 || msg->any.reportid >= ATMEL_MAXTRACK)
1055 sc->last_active_tick = ticks;
1057 track = &sc->track[msg->any.reportid];
1058 track->x = (msg->touch.pos[0] << 4) |
1059 ((msg->touch.pos[2] >> 4) & 0x0F);
1060 track->y = (msg->touch.pos[1] << 4) |
1061 (msg->touch.pos[2] & 0x0F);
1062 track->pressure = msg->touch.amplitude;
1064 track->x = track->x * 3000 / 1361;
1065 track->y = track->y * 3000 / 3064;
1067 if (msg->touch.flags & MXT_MSGF_DETECT) {
1068 track->status = ATMEL_TRACK_PRESSED;
1069 if (msg->touch.flags & MXT_MSGF_PRESS) {
1070 track->report |= ATMEL_REPORT_PRESS;
1072 if (msg->touch.flags & MXT_MSGF_MOVE) {
1073 track->report |= ATMEL_REPORT_MOVE;
1076 track->status = ATMEL_TRACK_RELEASED;
1077 track->report |= ATMEL_REPORT_RELEASE;
1079 atmel_find_active_state(sc);
1082 atmel_mxt_unlock(sc);
1084 atmel_mxt_notify(sc);
1085 if (sc->track_fingers)
1096 mxt_findobject(struct mxt_rollup *core, int type)
1100 for (i = 0; i < core->nobjs; ++i) {
1101 if (core->objs[i].type == type)
1102 return(&core->objs[i]);
1108 mxt_read_reg(atmel_mxt_softc_t *sc, uint16_t reg, void *rbuf, int bytes)
1115 wreg[0] = reg & 255;
1118 bus = device_get_parent(sc->dev);
1119 if ((error = smbus_request_bus(bus, sc->dev, SMB_WAIT | SMB_INTR)) != 0)
1121 error = smbus_trans(bus, sc->addr, 0,
1126 rbuf, bytes, &rbytes);
1127 smbus_release_bus(bus, sc->dev);
1129 if (bytes != rbytes) {
1130 device_printf(sc->dev,
1131 "smbus_trans reg %d short read %d/%d\n",
1132 reg, bytes, rbytes);
1140 mxt_write_reg_buf(atmel_mxt_softc_t *sc, uint16_t reg, void *xbuf, int bytes)
1146 KKASSERT(bytes < sizeof(wbuf) - 2);
1147 wbuf[0] = reg & 255;
1149 bcopy(xbuf, wbuf + 2, bytes);
1151 bus = device_get_parent(sc->dev);
1152 if ((error = smbus_request_bus(bus, sc->dev, SMB_WAIT | SMB_INTR)) != 0)
1154 error = smbus_trans(bus, sc->addr, 0,
1160 smbus_release_bus(bus, sc->dev);
1165 mxt_write_reg(atmel_mxt_softc_t *sc, uint16_t reg, uint8_t val)
1167 return mxt_write_reg_buf(sc, reg, &val, 1);
1171 mxt_read_object(atmel_mxt_softc_t *sc, struct mxt_object *obj,
1172 void *rbuf, int rbytes)
1174 uint16_t reg = obj->start_pos_lsb + (obj->start_pos_msb << 8);
1175 int bytes = obj->size_minus_one + 1;
1179 return mxt_read_reg(sc, reg, rbuf, bytes);
1183 mxt_write_object_off(atmel_mxt_softc_t *sc, struct mxt_object *obj,
1184 int offset, uint8_t val)
1186 uint16_t reg = obj->start_pos_lsb + (obj->start_pos_msb << 8);
1189 return mxt_write_reg(sc, reg, val);
1192 DRIVER_MODULE(atmel_mxt, smbus, atmel_mxt_driver, atmel_mxt_devclass,
1194 MODULE_DEPEND(atmel_mxt, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
1195 MODULE_VERSION(atmel_mxt, 1);