svn commit: r200314 - in stable/8/sys: conf dev/usb/input
modules/usb modules/usb/atp
Andrew Thompson
thompsa at FreeBSD.org
Wed Dec 9 13:47:43 PST 2009
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 <rgrover1 at gmail.com>
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
More information about the svn-src-stable
mailing list