HID mouse can now support some while mice. Problems with Microsoft mice

This commit is contained in:
Gregory Nutt 2014-02-10 11:53:37 -06:00
parent 752767cfc1
commit 0070815e87
7 changed files with 207 additions and 57 deletions

View file

@ -6564,3 +6564,5 @@
touchscreen drivers, mouse drivers need to report positional data
with no button is pressed so that the mouse position can drive a
cursor (2014-2-10).
* drivers/usbhost/usbhost_hidmouse.c, include/nuttx/input/mouse.h, and
include/nuttx/usb/hid.h: Add support for a mouse wheel (2014-2-10).

View file

@ -362,6 +362,8 @@ CONFIG_DEV_NULL=y
# CONFIG_VIDEO_DEVICES is not set
# CONFIG_BCH is not set
CONFIG_INPUT=y
CONFIG_MOUSE=y
# CONFIG_MOUSE_WHEEL is not set
# CONFIG_INPUT_TSC2007 is not set
# CONFIG_INPUT_ADS7843E is not set
# CONFIG_INPUT_STMPE811 is not set

View file

@ -3,6 +3,23 @@
# see misc/tools/kconfig-language.txt.
#
config MOUSE
bool "Enable mouse support"
default n
---help---
Enable support for mouse devices.
if MOUSE
config MOUSE_WHEEL
bool "Enable mouse wheel support"
default n
---help---
Enable support for a 4-button mouse report that includes a while
position.
endif # MOUSE
config INPUT_TSC2007
bool "TI TSC2007 touchscreen controller"
default n

View file

@ -120,11 +120,16 @@ config USBHOST_HIDMOUSE
default n
depends on !INT_DISABLE
select INPUT
select MOUSE
---help---
Enable support for the mouse class driver. This also depends on
SCHED_WORKQUEUE && !DISABLE_SIGNALS
if USBHOST_HIDMOUSE
NOTE: This driver checks out on a Labtec and an AOpen mouse, but
does not work correctly on a Microsoft mouse. A little more work
would be needed to support the Microsoft mouse.
if USBHOST_HIDMOUSE
config HIDMOUSE_TSCIF
bool "Touchscreen Emulation"
@ -226,7 +231,7 @@ config HIDMOUSE_XTHRESH
default 12
---help---
New mouse positions will only be reported when the X or Y data changes by these
thresholds. This trades reduces data rate for some loss in dragging accuracy.
thresholds. This tradeoff reduces data rate for some loss in dragging accuracy.
Both X and Y axis thresholding can be disabled by setting this value to zero.
Default: 12
@ -236,12 +241,48 @@ config HIDMOUSE_THRESHY
default 12
---help---
New touch positions will only be reported when the X or Y data changes by these
thresholds. This trades reduces data rate for some loss in dragging accuracy.
thresholds. This tradeoff reduces data rate for some loss in dragging accuracy.
Both X and Y axis thresholding can be disabled by setting this value to zero.
Default: 12
endif
if MOUSE_WHEEL
config HIDMOUSE_WMAX
int "Maximum wheel position"
default 320
range 0 32767
---help---
This is the maximum value of the wheel position that will be
reported. Default: 320
config HIDMOUSE_WSCALE
hex "Wheel scaling factor"
default 0x00010000
---help---
Mouse wheel position are accumulated from wheel displacements
reported by the mouse device. This setting provides a scaling
value for the wheel displacement. This is a fixed precision
floating point number with 16 bits of fraction. So a value of
0x00010000 is 1.0, 0x00018000 is 1.5, 0x00024000 is 2.25, etc.
NOTE that a negative value of HIDMOUSE_XSCALE such as 0xffff0000
(-1.0) can be used to change the direction of wheel output.
Default: 0x00010000 (1.0)
config HIDMOUSE_WTHRESH
int "Wheel threshold"
default 1
---help---
New wheel positions will only be reported when the wheel position
changes by these thresholds. This tradeoff reduces data rate for some
loss in wheel responsiveness.
Default: 1
endif # MOUSE_WHEEL
endif # USBHOST_HIDMOUSE
config USBHOST_TRACE
bool "Enable USB HCD tracing for debug"

View file

@ -127,6 +127,30 @@
#define HIDMOUSE_YTHRESH_B16 (CONFIG_HIDMOUSE_YTHRESH << 16)
#ifdef CONFIG_HIDMOUSE_TSCIF
# undef CONFIG_MOUSE_WHEEL
#endif
#ifdef CONFIG_MOUSE_WHEEL
# ifndef CONFIG_HIDMOUSE_WMAX
# define CONFIG_HIDMOUSE_WMAX 100
# endif
# define HIDMOUSE_WMAX_B16 (CONFIG_HIDMOUSE_WMAX << 16)
# ifndef CONFIG_HIDMOUSE_WSCALE
# define CONFIG_HIDMOUSE_WSCALE 0x00010000
# endif
# ifndef CONFIG_HIDMOUSE_WTHRESH
# define CONFIG_HIDMOUSE_WTHRESH 1
# endif
# define HIDMOUSE_WTHRESH_B16 (CONFIG_HIDMOUSE_WTHRESH << 16)
#endif /* CONFIG_MOUSE_WHEEL */
#ifndef CONFIG_HIDMOUSE_DEFPRIO
# define CONFIG_HIDMOUSE_DEFPRIO 50
#endif
@ -217,8 +241,11 @@ struct mouse_sample_s
struct mouse_sample_s
{
uint8_t buttons; /* Button state (see MOUSE_BUTTON_* definitions) */
uint16_t x; /* Measured X position */
uint16_t y; /* Measured Y position */
uint16_t x; /* Accumulated X position */
uint16_t y; /* Accumulated Y position */
#ifdef CONFIG_MOUSE_WHEEL
uint16_t wheel; /* Reported wheel position */
#endif
};
#endif
@ -257,6 +284,10 @@ struct usbhost_state_s
b16_t yaccum; /* Current integrated Y position */
b16_t xlast; /* Last reported X position */
b16_t ylast; /* Last reported Y position */
#ifdef CONFIG_MOUSE_WHEEL
b16_t waccum; /* Current integrated while position */
b16_t wlast; /* Last reported wheel position */
#endif
size_t tbuflen; /* Size of the allocated transfer buffer */
pid_t pollpid; /* PID of the poll task */
struct work_s work; /* For cornercase error handling by the worker thread */
@ -299,7 +330,8 @@ static inline void usbhost_freeclass(FAR struct usbhost_state_s *class);
static int usbhost_allocdevno(FAR struct usbhost_state_s *priv);
static void usbhost_freedevno(FAR struct usbhost_state_s *priv);
static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv, char *devname);
static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv,
FAR char *devname);
/* Mouse polling thread */
@ -311,8 +343,7 @@ static void usbhost_position(FAR struct usbhost_state_s *priv,
static bool usbhost_touchscreen(FAR struct usbhost_state_s *priv,
FAR struct usbhid_mousereport_s *rpt);
#endif
static bool usbhost_threshold(FAR struct usbhost_state_s *priv,
b16_t xpos, b16_t ypos);
static bool usbhost_threshold(FAR struct usbhost_state_s *priv);
static int usbhost_mouse_poll(int argc, char *argv[]);
static int usbhost_sample(FAR struct usbhost_state_s *priv,
FAR struct mouse_sample_s *sample);
@ -322,8 +353,8 @@ static int usbhost_waitsample(FAR struct usbhost_state_s *priv,
/* Helpers for usbhost_connect() */
static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv,
FAR const uint8_t *configdesc, int desclen,
uint8_t funcaddr);
FAR const uint8_t *configdesc,
int desclen, uint8_t funcaddr);
static inline int usbhost_devinit(FAR struct usbhost_state_s *priv);
/* (Little Endian) Data helpers */
@ -563,7 +594,8 @@ static void usbhost_freedevno(FAR struct usbhost_state_s *priv)
}
}
static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv, char *devname)
static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv,
FAR char *devname)
{
(void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, priv->devno);
}
@ -699,10 +731,8 @@ static void usbhost_notify(FAR struct usbhost_state_s *priv)
static void usbhost_position(FAR struct usbhost_state_s *priv,
FAR struct usbhid_mousereport_s *rpt)
{
int32_t xdisp;
int32_t ydisp;
b16_t xpos;
b16_t ypos;
int32_t disp;
b16_t pos;
/* The following logic performs an constant integration of the mouse X/Y
* displacement data in order to keep the X/Y positional data current.
@ -714,68 +744,91 @@ static void usbhost_position(FAR struct usbhost_state_s *priv,
*/
#ifdef CONFIG_HIDMOUSE_SWAPXY
xdisp = rpt->ydisp;
disp = rpt->ydisp;
if ((rpt->ydisp & 0x80) != 0)
{
xdisp |= 0xffffff00;
disp |= 0xffffff00;
}
#else
xdisp = rpt->xdisp;
disp = rpt->xdisp;
if ((rpt->xdisp & 0x80) != 0)
{
xdisp |= 0xffffff00;
disp |= 0xffffff00;
}
#endif
/* Scale the X displacement and determine the new X position */
xpos = priv->xaccum + CONFIG_HIDMOUSE_XSCALE * xdisp;
pos = priv->xaccum + CONFIG_HIDMOUSE_XSCALE * disp;
/* Make sure that the scaled X position does not become negative or exceed
* the maximum.
*/
if (xpos > HIDMOUSE_XMAX_B16)
if (pos > HIDMOUSE_XMAX_B16)
{
xpos = HIDMOUSE_XMAX_B16;
pos = HIDMOUSE_XMAX_B16;
}
else if (xpos < 0)
else if (pos < 0)
{
xpos = 0;
pos = 0;
}
/* Save the updated X position */
priv->xaccum = xpos;
priv->xaccum = pos;
/* Do the same for the Y position */
#ifdef CONFIG_HIDMOUSE_SWAPXY
ydisp = rpt->xdisp;
disp = rpt->xdisp;
if ((rpt->xdisp & 0x80) != 0)
{
ydisp |= 0xffffff00;
disp |= 0xffffff00;
}
#else
ydisp = rpt->ydisp;
disp = rpt->ydisp;
if ((rpt->ydisp & 0x80) != 0)
{
ydisp |= 0xffffff00;
disp |= 0xffffff00;
}
#endif
ypos = priv->yaccum + CONFIG_HIDMOUSE_YSCALE * ydisp;
pos = priv->yaccum + CONFIG_HIDMOUSE_YSCALE * disp;
if (ypos > HIDMOUSE_YMAX_B16)
if (pos > HIDMOUSE_YMAX_B16)
{
ypos = HIDMOUSE_YMAX_B16;
pos = HIDMOUSE_YMAX_B16;
}
else if (ypos < 0)
else if (pos < 0)
{
ypos = 0;
pos = 0;
}
priv->yaccum = ypos;
priv->yaccum = pos;
#ifdef CONFIG_MOUSE_WHEEL
/* Do the same for the wheel position */
disp = rpt->wdisp;
if ((rpt->wdisp & 0x80) != 0)
{
disp |= 0xffffff00;
}
pos = priv->waccum + CONFIG_HIDMOUSE_WSCALE * disp;
if (pos > HIDMOUSE_WMAX_B16)
{
pos = HIDMOUSE_WMAX_B16;
}
else if (pos < 0)
{
pos = 0;
}
priv->waccum = pos;
#endif
}
/****************************************************************************
@ -862,7 +915,7 @@ static bool usbhost_touchscreen(FAR struct usbhost_state_s *priv,
* small, then ignore the event.
*/
else if (!usbhost_threshold(priv, priv->xaccum, priv->yaccum))
else if (!usbhost_xythreshold(priv))
{
return false;
}
@ -889,8 +942,6 @@ static bool usbhost_touchscreen(FAR struct usbhost_state_s *priv,
*
* Input Parameters:
* priv - A reference to the mouse state structure.
* xpos - The current mouse X position
* ypos - The current mouse Y position
*
* Returned Value:
* True if the mouse position is significantly different from the last
@ -898,47 +949,69 @@ static bool usbhost_touchscreen(FAR struct usbhost_state_s *priv,
*
****************************************************************************/
static bool usbhost_threshold(FAR struct usbhost_state_s *priv,
b16_t xpos, b16_t ypos)
static bool usbhost_threshold(FAR struct usbhost_state_s *priv)
{
#if CONFIG_HIDMOUSE_XTHRESH > 0 && CONFIG_HIDMOUSE_YTHRESH > 0
b16_t xdiff;
b16_t ydiff;
b16_t pos;
b16_t diff;
/* Get the difference in the X position from the last report */
if (xpos > priv->xlast)
pos = priv->xaccum;
if (pos > priv->xlast)
{
xdiff = xpos - priv->xlast;
diff = pos - priv->xlast;
}
else
{
xdiff = priv->xlast - xpos;
diff = priv->xlast - pos;
}
/* Check if the X difference exceeds the report threshold */
if (xdiff >= HIDMOUSE_XTHRESH_B16)
if (diff >= HIDMOUSE_XTHRESH_B16)
{
return true;
}
/* Little or no change in the X direction, check the Y direction. */
if (ypos > priv->ylast)
pos = priv->yaccum;
if (pos > priv->ylast)
{
ydiff = ypos - priv->ylast;
diff = pos - priv->ylast;
}
else
{
ydiff = priv->ylast - ypos;
diff = priv->ylast - pos;
}
if (ydiff >= HIDMOUSE_YTHRESH_B16)
if (diff >= HIDMOUSE_YTHRESH_B16)
{
return true;
}
#ifdef CONFIG_MOUSE_WHEEL
/* Get the difference in the wheel position from the last report */
pos = priv->waccum;
if (pos > priv->wlast)
{
diff = pos - priv->wlast;
}
else
{
diff = priv->wlast - pos;
}
/* Check if the X difference exceeds the report threshold */
if (diff >= HIDMOUSE_WTHRESH_B16)
{
return true;
}
#endif
/* Little or no change in either direction... don't report anything. */
return false;
@ -1057,8 +1130,7 @@ static int usbhost_mouse_poll(int argc, char *argv[])
*/
buttons = rpt->buttons & USBHID_MOUSEIN_BUTTON_MASK;
if (buttons != priv->buttons ||
usbhost_threshold(priv, priv->xaccum, priv->yaccum))
if (buttons != priv->buttons || usbhost_threshold(priv))
#endif
{
/* We get here when either there is a meaning button change
@ -1070,11 +1142,16 @@ static int usbhost_mouse_poll(int argc, char *argv[])
priv->xlast = priv->xaccum;
priv->ylast = priv->yaccum;
#ifdef CONFIG_MOUSE_WHEEL
priv->wlast = priv->waccum;
#endif
/* Update the sample X/Y positions */
priv->sample.x = b16toi(priv->xaccum);
priv->sample.y = b16toi(priv->yaccum);
#ifdef CONFIG_MOUSE_WHEEL
priv->sample.wheel = b16toi(priv->waccum);
#endif
#ifdef CONFIG_HIDMOUSE_TSCIF
/* The X/Y positional data is now valid */
@ -2046,7 +2123,9 @@ static int usbhost_open(FAR struct file *filep)
priv->xlast = INVALID_POSITION_B16;
priv->ylast = INVALID_POSITION_B16;
#ifdef CONFIG_MOUSE_WHEEL
priv->wlast = INVALID_POSITION_B16;
#endif
/* Set the reported position to the center of the range */
priv->xaccum = (HIDMOUSE_XMAX_B16 >> 1);
@ -2261,6 +2340,9 @@ static ssize_t usbhost_read(FAR struct file *filep, FAR char *buffer, size_t len
report->buttons = sample.buttons;
report->x = sample.x;
report->y = sample.y;
#ifdef CONFIG_MOUSE_WHEEL
report->wheel = sample.wheel;
#endif
ret = sizeof(struct mouse_report_s);
#endif

View file

@ -59,8 +59,8 @@
*/
#define MOUSE_BUTTON_1 (1 << 0) /* True: Left mouse button pressed */
#define MOUSE_BUTTON_2 (1 << 1) /* True: Middle mouse button pressed */
#define MOUSE_BUTTON_3 (1 << 2) /* True: Right mouse button pressed */
#define MOUSE_BUTTON_2 (1 << 1) /* True: Right mouse button pressed */
#define MOUSE_BUTTON_3 (1 << 2) /* True: Middle mouse button pressed */
/************************************************************************************
* Public Types
@ -76,6 +76,9 @@ struct mouse_report_s
uint8_t buttons; /* See TOUCH_* definitions above */
int16_t x; /* X coordinate of the mouse position */
int16_t y; /* Y coordinate of the mouse position */
#ifdef CONFIG_MOUSE_WHEEL
int16_t wheel; /* Mouse wheel position */
#endif
};
/************************************************************************************

View file

@ -662,6 +662,9 @@ struct usbhid_mousereport_s
uint8_t xdisp; /* X displacement */
uint8_t ydisp; /* y displacement */
/* Device specific additional bytes may follow */
#ifdef CONFIG_MOUSE_WHEEL
uint8_t wdisp; /* Wheel displacement */
#endif
};
/* Joystick input report (1 bytes) (HID D.1) */