From owner-svn-src-stable-8@FreeBSD.ORG Wed Dec 9 21:47:43 2009 Return-Path: Delivered-To: svn-src-stable-8@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 00E391065670; Wed, 9 Dec 2009 21:47:43 +0000 (UTC) (envelope-from thompsa@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id E09DC8FC17; Wed, 9 Dec 2009 21:47:42 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id nB9Llgu6039545; Wed, 9 Dec 2009 21:47:42 GMT (envelope-from thompsa@svn.freebsd.org) Received: (from thompsa@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id nB9LlgLX039541; Wed, 9 Dec 2009 21:47:42 GMT (envelope-from thompsa@svn.freebsd.org) Message-Id: <200912092147.nB9LlgLX039541@svn.freebsd.org> From: Andrew Thompson Date: Wed, 9 Dec 2009 21:47:42 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r200314 - in stable/8/sys: conf dev/usb/input modules/usb modules/usb/atp X-BeenThere: svn-src-stable-8@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 8-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 09 Dec 2009 21:47:43 -0000 Author: thompsa Date: Wed Dec 9 21:47:42 2009 New Revision: 200314 URL: http://svn.freebsd.org/changeset/base/200314 Log: MFC r199086,199151,199680,199948,200241 Driver for the Apple Touchpad present on MacBook (non-Pro & Pro). Submitted by: Rohit Grover Added: stable/8/sys/dev/usb/input/atp.c - copied, changed from r199086, head/sys/dev/usb/input/atp.c stable/8/sys/modules/usb/atp/ - copied from r199086, head/sys/modules/usb/atp/ Modified: stable/8/sys/conf/files stable/8/sys/modules/usb/Makefile Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/xen/xenpci/ (props changed) Modified: stable/8/sys/conf/files ============================================================================== --- stable/8/sys/conf/files Wed Dec 9 21:39:43 2009 (r200313) +++ stable/8/sys/conf/files Wed Dec 9 21:47:42 2009 (r200314) @@ -1669,6 +1669,7 @@ dev/usb/misc/udbp.c optional udbp # # USB input drivers # +dev/usb/input/atp.c optional atp dev/usb/input/uhid.c optional uhid dev/usb/input/ukbd.c optional ukbd dev/usb/input/ums.c optional ums Copied and modified: stable/8/sys/dev/usb/input/atp.c (from r199086, head/sys/dev/usb/input/atp.c) ============================================================================== --- head/sys/dev/usb/input/atp.c Mon Nov 9 15:59:09 2009 (r199086, copy source) +++ stable/8/sys/dev/usb/input/atp.c Wed Dec 9 21:47:42 2009 (r200314) @@ -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) }, + }; /* @@ -299,6 +341,7 @@ typedef struct atp_stroke { enum { ATP_INTR_DT, + ATP_RESET, ATP_N_TRANSFER, }; @@ -321,6 +364,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; @@ -378,21 +422,22 @@ static struct usb_fifo_methods atp_fifo_ /* device initialization and shutdown */ static usb_error_t atp_req_get_report(struct usb_device *udev, void *data); static int atp_set_device_mode(device_t dev, interface_mode mode); +static void atp_reset_callback(struct usb_xfer *, usb_error_t); static int atp_enable(struct atp_softc *sc); static void atp_disable(struct atp_softc *sc); static int atp_softc_populate(struct atp_softc *); 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 *); /* movement detection */ static boolean_t atp_match_stroke_component(atp_stroke_component *, - const atp_pspan *); + const atp_pspan *, atp_stroke_type); static void atp_match_strokes_against_pspans(struct atp_softc *, atp_axis, atp_pspan *, u_int, u_int); static boolean_t atp_update_strokes(struct atp_softc *, @@ -413,6 +458,7 @@ static boolean_t atp_compute_stroke_ /* tap detection */ static __inline void atp_setup_reap_time(struct atp_softc *, struct timeval *); static void atp_reap_zombies(struct atp_softc *, u_int *, u_int *); +static void atp_convert_to_slide(struct atp_softc *, atp_stroke *); /* updating fifo */ static void atp_reset_buf(struct atp_softc *sc); @@ -458,6 +504,40 @@ atp_set_device_mode(device_t dev, interf return (0); } +void +atp_reset_callback(struct usb_xfer *xfer, usb_error_t error) +{ + usb_device_request_t req; + struct usb_page_cache *pc; + struct atp_softc *sc = usbd_xfer_softc(xfer); + + switch (USB_GET_STATE(xfer)) { + case USB_ST_SETUP: + sc->sc_mode_bytes[0] = RAW_SENSOR_MODE; + req.bmRequestType = UT_WRITE_CLASS_INTERFACE; + req.bRequest = UR_SET_REPORT; + USETW2(req.wValue, + (uint8_t)0x03 /* type */, (uint8_t)0x00 /* id */); + USETW(req.wIndex, 0); + USETW(req.wLength, MODE_LENGTH); + + pc = usbd_xfer_get_frame(xfer, 0); + usbd_copy_in(pc, 0, &req, sizeof(req)); + pc = usbd_xfer_get_frame(xfer, 1); + usbd_copy_in(pc, 0, sc->sc_mode_bytes, MODE_LENGTH); + + usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); + usbd_xfer_set_frame_len(xfer, 1, MODE_LENGTH); + usbd_xfer_set_frames(xfer, 2); + usbd_transfer_submit(xfer); + break; + + case USB_ST_TRANSFERRED: + default: + break; + } +} + static int atp_enable(struct atp_softc *sc) { @@ -483,7 +563,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 +703,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; } } @@ -783,23 +880,43 @@ atp_detect_pspans(int *p, u_int num_sens */ static boolean_t atp_match_stroke_component(atp_stroke_component *component, - const atp_pspan *pspan) + const atp_pspan *pspan, atp_stroke_type stroke_type) { - int delta_mickeys = pspan->loc - component->loc; + int delta_mickeys; + u_int min_pressure; + + delta_mickeys = pspan->loc - component->loc; if (abs(delta_mickeys) > atp_max_delta_mickeys) return (FALSE); /* the finger span is too far out; no match */ component->loc = pspan->loc; + + /* + * A sudden and significant increase in a pspan's cumulative + * pressure indicates the incidence of a new finger + * contact. This usually revises the pspan's + * centre-of-gravity, and hence the location of any/all + * matching stroke component(s). But such a change should + * *not* be interpreted as a movement. + */ + if (pspan->cum > ((3 * component->cum_pressure) >> 1)) + delta_mickeys = 0; + component->cum_pressure = pspan->cum; if (pspan->cum > component->max_cum_pressure) component->max_cum_pressure = pspan->cum; /* - * If the cumulative pressure drops below a quarter of the max, - * then disregard the component's movement. + * Disregard the component's movement if its cumulative + * pressure drops below a fraction of the maximum; this + * fraction is determined based on the stroke's type. */ - if (component->cum_pressure < (component->max_cum_pressure >> 2)) + if (stroke_type == ATP_STROKE_TOUCH) + min_pressure = (3 * component->max_cum_pressure) >> 2; + else + min_pressure = component->max_cum_pressure >> 2; + if (component->cum_pressure < min_pressure) delta_mickeys = 0; component->delta_mickeys = delta_mickeys; @@ -834,7 +951,8 @@ atp_match_strokes_against_pspans(struct continue; /* skip matched pspans */ if (atp_match_stroke_component( - &stroke->components[axis], &pspans[j])) { + &stroke->components[axis], &pspans[j], + stroke->type)) { /* There is a match. */ stroke->components[axis].matched = TRUE; @@ -969,19 +1087,23 @@ atp_update_strokes(struct atp_softc *sc, for (i = 0; i < sc->sc_n_strokes; i++) { atp_stroke *stroke = &sc->sc_strokes[i]; - printf(" %s%clc:%u,dm:%d,pnd:%d,mv:%d%c" - ",%clc:%u,dm:%d,pnd:%d,mv:%d%c", + printf(" %s%clc:%u,dm:%d,pnd:%d,cum:%d,max:%d,mv:%d%c" + ",%clc:%u,dm:%d,pnd:%d,cum:%d,max:%d,mv:%d%c", (stroke->flags & ATSF_ZOMBIE) ? "zomb:" : "", (stroke->type == ATP_STROKE_TOUCH) ? '[' : '<', stroke->components[X].loc, stroke->components[X].delta_mickeys, stroke->components[X].pending, + stroke->components[X].cum_pressure, + stroke->components[X].max_cum_pressure, stroke->components[X].movement, (stroke->type == ATP_STROKE_TOUCH) ? ']' : '>', (stroke->type == ATP_STROKE_TOUCH) ? '[' : '<', stroke->components[Y].loc, stroke->components[Y].delta_mickeys, stroke->components[Y].pending, + stroke->components[Y].cum_pressure, + stroke->components[Y].max_cum_pressure, stroke->components[Y].movement, (stroke->type == ATP_STROKE_TOUCH) ? ']' : '>'); } @@ -1122,51 +1244,94 @@ atp_advance_stroke_state(struct atp_soft if (atp_compute_stroke_movement(stroke)) *movement = TRUE; + if (stroke->type != ATP_STROKE_TOUCH) + return; + /* Convert touch strokes to slides upon detecting movement or age. */ - if (stroke->type == ATP_STROKE_TOUCH) { - struct timeval tdiff; + if (stroke->cum_movement >= atp_slide_min_movement) { + atp_convert_to_slide(sc, stroke); + } else { + /* If a touch stroke is found to be older than the + * touch-timeout threshold, it should be converted to + * a slide; except if there is a co-incident sibling + * with a later creation time. + * + * When multiple fingers make contact with the + * touchpad, they are likely to be separated in their + * times of incidence. During a multi-finger tap, + * therefore, the last finger to make + * contact--i.e. the one with the latest + * 'ctime'--should be used to determine how the + * touch-siblings get treated; otherwise older + * siblings may lapse the touch-timeout and get + * converted into slides prematurely. The following + * loop determines if there exists another touch + * stroke with a larger 'ctime' than the current + * stroke (NOTE: zombies with a larger 'ctime' are + * also considered) . + */ - /* Compute the stroke's age. */ - getmicrotime(&tdiff); - if (timevalcmp(&tdiff, &stroke->ctime, >)) - timevalsub(&tdiff, &stroke->ctime); - else { - /* - * If we are here, it is because getmicrotime - * reported the current time as being behind - * the stroke's start time; getmicrotime can - * be imprecise. - */ - tdiff.tv_sec = 0; - tdiff.tv_usec = 0; - } + u_int i; + for (i = 0; i < sc->sc_n_strokes; i++) { + if ((&sc->sc_strokes[i] == stroke) || + (sc->sc_strokes[i].type != ATP_STROKE_TOUCH)) + continue; - if ((tdiff.tv_sec > (atp_touch_timeout / 1000000)) || - ((tdiff.tv_sec == (atp_touch_timeout / 1000000)) && - (tdiff.tv_usec > atp_touch_timeout)) || - (stroke->cum_movement >= atp_slide_min_movement)) { - /* Switch this stroke to being a slide. */ - stroke->type = ATP_STROKE_SLIDE; - - /* Are we at the beginning of a double-click-n-drag? */ - if ((sc->sc_n_strokes == 1) && - ((sc->sc_state & ATP_ZOMBIES_EXIST) == 0) && - timevalcmp(&stroke->ctime, &sc->sc_reap_time, >)) { - struct timeval delta; - struct timeval window = { - atp_double_tap_threshold / 1000000, - atp_double_tap_threshold % 1000000 - }; - - delta = stroke->ctime; - timevalsub(&delta, &sc->sc_reap_time); - if (timevalcmp(&delta, &window, <=)) - sc->sc_state |= ATP_DOUBLE_TAP_DRAG; + if (timevalcmp(&sc->sc_strokes[i].ctime, + &stroke->ctime, >)) + break; + } + if (i == sc->sc_n_strokes) { + /* Found no other touch stroke with a larger 'ctime'. */ + struct timeval tdiff; + + /* Compute the stroke's age. */ + getmicrotime(&tdiff); + if (timevalcmp(&tdiff, &stroke->ctime, >)) + timevalsub(&tdiff, &stroke->ctime); + else { + /* + * If we are here, it is because getmicrotime + * reported the current time as being behind + * the stroke's start time; getmicrotime can + * be imprecise. + */ + tdiff.tv_sec = 0; + tdiff.tv_usec = 0; } + + if ((tdiff.tv_sec > (atp_touch_timeout / 1000000)) || + ((tdiff.tv_sec == (atp_touch_timeout / 1000000)) && + (tdiff.tv_usec >= + (atp_touch_timeout % 1000000)))) + atp_convert_to_slide(sc, stroke); } } } +/* Switch a given touch stroke to being a slide. */ +void +atp_convert_to_slide(struct atp_softc *sc, atp_stroke *stroke) +{ + stroke->type = ATP_STROKE_SLIDE; + + /* Are we at the beginning of a double-click-n-drag? */ + if ((sc->sc_n_strokes == 1) && + ((sc->sc_state & ATP_ZOMBIES_EXIST) == 0) && + timevalcmp(&stroke->ctime, &sc->sc_reap_time, >)) { + struct timeval delta; + struct timeval window = { + atp_double_tap_threshold / 1000000, + atp_double_tap_threshold % 1000000 + }; + + delta = stroke->ctime; + timevalsub(&delta, &sc->sc_reap_time); + if (timevalcmp(&delta, &window, <=)) + sc->sc_state |= ATP_DOUBLE_TAP_DRAG; + } +} + /* * Terminate a stroke. While SLIDE strokes are dropped, TOUCH strokes * are retained as zombies so as to reap all their siblings together; @@ -1455,6 +1620,14 @@ static const struct usb_config atp_confi .bufsize = 0, /* use wMaxPacketSize */ .callback = &atp_intr, }, + [ATP_RESET] = { + .type = UE_CONTROL, + .endpoint = 0, /* Control pipe */ + .direction = UE_DIR_ANY, + .bufsize = sizeof(struct usb_device_request) + MODE_LENGTH, + .callback = &atp_reset_callback, + .interval = 0, /* no pre-delay */ + }, }; static int @@ -1469,10 +1642,7 @@ atp_probe(device_t self) (uaa->info.bInterfaceProtocol != UIPROTO_MOUSE)) return (ENXIO); - if (usbd_lookup_id_by_uaa(atp_devs, sizeof(atp_devs), uaa) == 0) - return BUS_PROBE_SPECIFIC; - else - return ENXIO; + return (usbd_lookup_id_by_uaa(atp_devs, sizeof(atp_devs), uaa)); } static int @@ -1482,12 +1652,6 @@ atp_attach(device_t dev) struct usb_attach_arg *uaa = device_get_ivars(dev); usb_error_t err; - /* ensure that the probe was successful */ - if (uaa->driver_info >= ATP_N_DEV_PARAMS) { - DPRINTF("device probe returned bad id: %lu\n", - uaa->driver_info); - return (ENXIO); - } DPRINTFN(ATP_LLEVEL_INFO, "sc=%p\n", sc); sc->sc_dev = dev; @@ -1566,7 +1730,6 @@ static int atp_detach(device_t dev) { struct atp_softc *sc; - int err; sc = device_get_softc(dev); if (sc->sc_state & ATP_ENABLED) { @@ -1581,12 +1744,6 @@ atp_detach(device_t dev) mtx_destroy(&sc->sc_mutex); - err = atp_set_device_mode(dev, HID_MODE); - if (err != 0) { - DPRINTF("failed to reset mode to 'HID' (%d)\n", err); - return (err); - } - return (0); } @@ -1613,7 +1770,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 +1778,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 +1791,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 +1919,23 @@ 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); + + /* + * Use the last frame before we go idle for + * calibration on pads which do not send + * calibration frames. + */ + if (sc->sc_params->prot < ATP_PROT_GEYSER3) { + 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_idlecount = 0; + usbd_transfer_start(sc->sc_xfer[ATP_RESET]); } } else { sc->sc_idlecount = 0; @@ -1770,7 +1947,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; Modified: stable/8/sys/modules/usb/Makefile ============================================================================== --- stable/8/sys/modules/usb/Makefile Wed Dec 9 21:39:43 2009 (r200313) +++ stable/8/sys/modules/usb/Makefile Wed Dec 9 21:47:42 2009 (r200314) @@ -28,7 +28,7 @@ SUBDIR = usb SUBDIR += ehci musb ohci uhci uss820dci ${_at91dci} ${_atmegadci} SUBDIR += rum uath upgt ural zyd ${_urtw} -SUBDIR += uhid ukbd ums udbp ufm +SUBDIR += atp uhid ukbd ums udbp ufm SUBDIR += ucom u3g uark ubsa ubser uchcom ucycom ufoma uftdi ugensa uipaq ulpt \ umct umodem umoscom uplcom uslcom uvisor uvscom SUBDIR += uether aue axe cdce cue kue rue udav