Date: Tue, 10 Nov 2009 19:14:06 +0000 (UTC) From: Nathan Whitehorn <nwhitehorn@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r199151 - head/sys/dev/usb/input Message-ID: <200911101914.nAAJE6RW069109@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: nwhitehorn Date: Tue Nov 10 19:14:06 2009 New Revision: 199151 URL: http://svn.freebsd.org/changeset/base/199151 Log: Add support for the touchpads found in later models of iBook and Powerbook. Reviewed by: Rohit Grover <rgrover1 at gmail.com> Modified: head/sys/dev/usb/input/atp.c Modified: head/sys/dev/usb/input/atp.c ============================================================================== --- head/sys/dev/usb/input/atp.c Tue Nov 10 17:45:54 2009 (r199150) +++ head/sys/dev/usb/input/atp.c Tue Nov 10 19:14:06 2009 (r199151) @@ -193,21 +193,50 @@ SYSCTL_UINT(_hw_usb_atp, OID_AUTO, pspan &atp_pspan_max_width, 4, "maximum allowed width (in sensors) for pressure-spans"); +/* We support three payload protocols */ +typedef enum { + ATP_PROT_GEYSER1, + ATP_PROT_GEYSER2, + ATP_PROT_GEYSER3, +} atp_protocol; /* Define the various flavours of devices supported by this driver. */ enum { ATP_DEV_PARAMS_0, + ATP_DEV_PARAMS_PBOOK, + ATP_DEV_PARAMS_PBOOK_15A, + ATP_DEV_PARAMS_PBOOK_17, ATP_N_DEV_PARAMS }; struct atp_dev_params { u_int data_len; /* for sensor data */ u_int n_xsensors; u_int n_ysensors; + atp_protocol prot; } atp_dev_params[ATP_N_DEV_PARAMS] = { [ATP_DEV_PARAMS_0] = { .data_len = 64, .n_xsensors = 20, - .n_ysensors = 10 + .n_ysensors = 10, + .prot = ATP_PROT_GEYSER3 + }, + [ATP_DEV_PARAMS_PBOOK] = { + .data_len = 81, + .n_xsensors = 16, + .n_ysensors = 16, + .prot = ATP_PROT_GEYSER1 + }, + [ATP_DEV_PARAMS_PBOOK_15A] = { + .data_len = 64, + .n_xsensors = 15, + .n_ysensors = 9, + .prot = ATP_PROT_GEYSER2 + }, + [ATP_DEV_PARAMS_PBOOK_17] = { + .data_len = 81, + .n_xsensors = 26, + .n_ysensors = 16, + .prot = ATP_PROT_GEYSER1 }, }; @@ -226,6 +255,19 @@ static const struct usb_device_id atp_de { USB_VPI(USB_VENDOR_APPLE, 0x0229, ATP_DEV_PARAMS_0) }, { USB_VPI(USB_VENDOR_APPLE, 0x022a, ATP_DEV_PARAMS_0) }, { USB_VPI(USB_VENDOR_APPLE, 0x022b, ATP_DEV_PARAMS_0) }, + + /* 12 inch PowerBook and iBook */ + { USB_VPI(USB_VENDOR_APPLE, 0x030a, ATP_DEV_PARAMS_PBOOK) }, + { USB_VPI(USB_VENDOR_APPLE, 0x030b, ATP_DEV_PARAMS_PBOOK) }, + + /* 15 inch PowerBook */ + { USB_VPI(USB_VENDOR_APPLE, 0x020e, ATP_DEV_PARAMS_PBOOK) }, + { USB_VPI(USB_VENDOR_APPLE, 0x020f, ATP_DEV_PARAMS_PBOOK) }, + { USB_VPI(USB_VENDOR_APPLE, 0x0215, ATP_DEV_PARAMS_PBOOK_15A) }, + + /* 17 inch PowerBook */ + { USB_VPI(USB_VENDOR_APPLE, 0x020d, ATP_DEV_PARAMS_PBOOK_17) }, + }; /* @@ -321,6 +363,7 @@ struct atp_softc { #define ATP_ENABLED 0x01 #define ATP_ZOMBIES_EXIST 0x02 #define ATP_DOUBLE_TAP_DRAG 0x04 +#define ATP_VALID 0x08 u_int sc_left_margin; u_int sc_right_margin; @@ -384,8 +427,8 @@ static int atp_softc_populate( static void atp_softc_unpopulate(struct atp_softc *); /* sensor interpretation */ -static __inline void atp_interpret_sensor_data(const int8_t *, u_int, u_int, - int *); +static __inline void atp_interpret_sensor_data(const int8_t *, u_int, atp_axis, + int *, atp_protocol); static __inline void atp_get_pressures(int *, const int *, const int *, int); static void atp_detect_pspans(int *, u_int, u_int, atp_pspan *, u_int *); @@ -483,7 +526,7 @@ atp_disable(struct atp_softc *sc) { atp_softc_unpopulate(sc); - sc->sc_state &= ~ATP_ENABLED; + sc->sc_state &= ~(ATP_ENABLED | ATP_VALID); DPRINTFN(ATP_LLEVEL_INFO, "disabled atp\n"); } @@ -623,25 +666,42 @@ atp_softc_unpopulate(struct atp_softc *s * raw sensor data from the USB packet. * num * The number of elements in the array 'arr'. - * di_start - * The index of the first data element to be interpreted for - * this sensor array--i.e. when called to interpret the Y - * sensors, di_start passed in as 2, which is the index of Y1 in - * the raw data. + * axis + * Axis of data to fetch * arr * The array to be initialized with the readings. + * prot + * The protocol to use to interpret the data */ static __inline void -atp_interpret_sensor_data(const int8_t *sensor_data, u_int num, u_int di_start, - int *arr) +atp_interpret_sensor_data(const int8_t *sensor_data, u_int num, atp_axis axis, + int *arr, atp_protocol prot) { u_int i; u_int di; /* index into sensor data */ - for (i = 0, di = di_start; i < num; /* empty */ ) { - arr[i++] = sensor_data[di++]; - arr[i++] = sensor_data[di++]; - di++; + switch (prot) { + case ATP_PROT_GEYSER1: + /* + * For Geyser 1, the sensors are laid out in pairs + * every 5 bytes. + */ + for (i = 0, di = (axis == Y) ? 1 : 2; i < 8; di += 5, i++) { + arr[i] = sensor_data[di]; + arr[i+8] = sensor_data[di+2]; + if (axis == X && num > 16) + arr[i+16] = sensor_data[di+40]; + } + + break; + case ATP_PROT_GEYSER2: + case ATP_PROT_GEYSER3: + for (i = 0, di = (axis == Y) ? 2 : 20; i < num; /* empty */ ) { + arr[i++] = sensor_data[di++]; + arr[i++] = sensor_data[di++]; + di++; + } + break; } } @@ -1613,7 +1673,7 @@ atp_intr(struct usb_xfer *xfer, usb_erro len, sc->sc_params->data_len); len = sc->sc_params->data_len; } - if (len == 0) + if (len < sc->sc_params->data_len) goto tr_setup; pc = usbd_xfer_get_frame(xfer, 0); @@ -1621,9 +1681,11 @@ atp_intr(struct usb_xfer *xfer, usb_erro /* Interpret sensor data */ atp_interpret_sensor_data(sc->sensor_data, - sc->sc_params->n_xsensors, 20, sc->cur_x); + sc->sc_params->n_xsensors, X, sc->cur_x, + sc->sc_params->prot); atp_interpret_sensor_data(sc->sensor_data, - sc->sc_params->n_ysensors, 2, sc->cur_y); + sc->sc_params->n_ysensors, Y, sc->cur_y, + sc->sc_params->prot); /* * If this is the initial update (from an untouched @@ -1632,11 +1694,14 @@ atp_intr(struct usb_xfer *xfer, usb_erro * be used as pressure readings subsequently. */ status_bits = sc->sensor_data[sc->sc_params->data_len - 1]; - if (status_bits & ATP_STATUS_BASE_UPDATE) { + if ((sc->sc_params->prot == ATP_PROT_GEYSER3 && + (status_bits & ATP_STATUS_BASE_UPDATE)) || + !(sc->sc_state & ATP_VALID)) { memcpy(sc->base_x, sc->cur_x, sc->sc_params->n_xsensors * sizeof(*(sc->base_x))); memcpy(sc->base_y, sc->cur_y, sc->sc_params->n_ysensors * sizeof(*(sc->base_y))); + sc->sc_state |= ATP_VALID; goto tr_setup; } @@ -1757,8 +1822,11 @@ atp_intr(struct usb_xfer *xfer, usb_erro sc->sc_idlecount++; if (sc->sc_idlecount >= ATP_IDLENESS_THRESHOLD) { DPRINTFN(ATP_LLEVEL_INFO, "idle\n"); - atp_set_device_mode(sc->sc_dev,RAW_SENSOR_MODE); sc->sc_idlecount = 0; + + mtx_unlock(&sc->sc_mutex); + atp_set_device_mode(sc->sc_dev,RAW_SENSOR_MODE); + mtx_lock(&sc->sc_mutex); } } else { sc->sc_idlecount = 0; @@ -1770,7 +1838,7 @@ atp_intr(struct usb_xfer *xfer, usb_erro if (usb_fifo_put_bytes_max( sc->sc_fifo.fp[USB_FIFO_RX]) != 0) { usbd_xfer_set_frame_len(xfer, 0, - usbd_xfer_max_len(xfer)); + sc->sc_params->data_len); usbd_transfer_submit(xfer); } break;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200911101914.nAAJE6RW069109>