Exemplo n.º 1
0
void
hidms_input(struct hidms *ms, uint8_t *data, u_int len)
{
	int dx, dy, dz, dw;
	u_int32_t buttons = 0;
	int flags;
	int i, s;

	DPRINTFN(5,("hidms_input: len=%d\n", len));

	/*
	 * The Microsoft Wireless Intellimouse 2.0 sends one extra leading
	 * byte of data compared to most USB mice.  This byte frequently
	 * switches from 0x01 (usual state) to 0x02.  It may be used to
	 * report non-standard events (such as battery life).  However,
	 * at the same time, it generates a left click event on the
	 * button byte, where there shouldn't be any.  We simply discard
	 * the packet in this case.
	 *
	 * This problem affects the MS Wireless Notebook Optical Mouse, too.
	 * However, the leading byte for this mouse is normally 0x11, and
	 * the phantom mouse click occurs when it's 0x14.
	 */
	if (ms->sc_flags & HIDMS_LEADINGBYTE) {
		if (*data++ == 0x02)
			return;
		/* len--; */
	} else if (ms->sc_flags & HIDMS_SPUR_BUT_UP) {
		if (*data == 0x14 || *data == 0x15)
			return;
	}

	flags = WSMOUSE_INPUT_DELTA;
	if (ms->sc_flags & HIDMS_ABSX)
		flags |= WSMOUSE_INPUT_ABSOLUTE_X;
	if (ms->sc_flags & HIDMS_ABSY)
		flags |= WSMOUSE_INPUT_ABSOLUTE_Y;

	dx =  hid_get_data(data, len, &ms->sc_loc_x);
	dy = -hid_get_data(data, len, &ms->sc_loc_y);
	dz =  hid_get_data(data, len, &ms->sc_loc_z);
	dw =  hid_get_data(data, len, &ms->sc_loc_w);

	if (ms->sc_flags & HIDMS_ABSY)
		dy = -dy;
	if (ms->sc_flags & HIDMS_REVZ)
		dz = -dz;
	if (ms->sc_flags & HIDMS_REVW)
		dw = -dw;

	if (ms->sc_tsscale.swapxy && !ms->sc_rawmode) {
		int tmp = dx;
		dx = dy;
		dy = tmp;
	}

	if (!ms->sc_rawmode &&
	    (ms->sc_tsscale.maxx - ms->sc_tsscale.minx) != 0 &&
	    (ms->sc_tsscale.maxy - ms->sc_tsscale.miny) != 0) {
		/* Scale down to the screen resolution. */
		dx = ((dx - ms->sc_tsscale.minx) * ms->sc_tsscale.resx) /
		    (ms->sc_tsscale.maxx - ms->sc_tsscale.minx);
		dy = ((dy - ms->sc_tsscale.miny) * ms->sc_tsscale.resy) /
		    (ms->sc_tsscale.maxy - ms->sc_tsscale.miny);
	}

	for (i = 0; i < ms->sc_num_buttons; i++)
		if (hid_get_data(data, len, &ms->sc_loc_btn[i]))
			buttons |= (1 << HIDMS_BUT(i));

	if (dx != 0 || dy != 0 || dz != 0 || dw != 0 ||
	    buttons != ms->sc_buttons) {
		DPRINTFN(10, ("hidms_input: x:%d y:%d z:%d w:%d buttons:0x%x\n",
			dx, dy, dz, dw, buttons));
		ms->sc_buttons = buttons;
		if (ms->sc_wsmousedev != NULL) {
			s = spltty();
			wsmouse_input(ms->sc_wsmousedev, buttons,
			    dx, dy, dz, dw, flags);
			splx(s);
		}
	}
}