* [PATCH 2/2] input: bcm5974-0.61: New default mouse driver mode
@ 2008-09-01 20:08 Henrik Rydberg
2008-09-02 13:00 ` Dmitry Torokhov
0 siblings, 1 reply; 3+ messages in thread
From: Henrik Rydberg @ 2008-09-01 20:08 UTC (permalink / raw)
To: akpm, Dmitry Torokhov, linux-input; +Cc: linux-kernel
Currently, the Apple bcm5974 driver only mimics a synaptics touchpad, not a mouse.
This creates unnecessary complications on systems where the synaptics driver is absent
or not configured, such as in a completely new system, or a text console. This patch
provides a default compatibility configuration, which works as a multi-button mouse,
implemented using rudimentary multi-finger options. It yields the following benefits:
* A default Xorg configuration will pick up the mouse input interface, resulting in a
functional mouse pointer out-of-the-box on many systems.
* Two-finger scroll emulates a mouse wheel.
* Three-finger swipe emulates a horizontal mouse wheel.
* Multi-finger clicks emulate the middle and right mouse buttons.
* The mouse driver also works with gpm in text consoles, providing cut-and-paste functionality.
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
drivers/input/mouse/bcm5974.c | 238 ++++++++++++++++++++++++++++++++++------
1 files changed, 202 insertions(+), 36 deletions(-)
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
index ae78bb8..7e18793 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -84,10 +84,33 @@ MODULE_LICENSE("GPL");
#define dprintk(level, format, a...)\
{ if (debug >= level) printk(KERN_DEBUG format, ##a); }
+#define MODE_MOUSE 1
+#define MODE_TOUCHPAD 2
+
static int debug = 1;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Activate debugging output");
+static int driver_mode = MODE_MOUSE;
+module_param(driver_mode, int, 0644);
+MODULE_PARM_DESC(driver_mode, "Driver mode (1 - mouse; 2 - touchpad)");
+
+static int mouse_motion_damping = 8;
+module_param(mouse_motion_damping, int, 0644);
+MODULE_PARM_DESC(mouse_motion_damping, "Mouse motion damping");
+
+static int mouse_wheel_damping = 256;
+module_param(mouse_wheel_damping, int, 0644);
+MODULE_PARM_DESC(mouse_wheel_damping, "Vertical mouse wheel damping");
+
+static int mouse_hwheel_damping = 256;
+module_param(mouse_hwheel_damping, int, 0644);
+MODULE_PARM_DESC(mouse_hwheel_damping, "Horizontal mouse wheel damping");
+
+static int mouse_button_mode = 2;
+module_param(mouse_button_mode, int, 0644);
+MODULE_PARM_DESC(mouse_button_mode, "Mouse button mode (1 - unix; 2 - macos)");
+
/* button data structure */
struct bt_data {
u8 unknown1; /* constant */
@@ -146,6 +169,15 @@ struct bcm5974_config {
struct bcm5974_param y; /* vertical limits */
};
+/* mouse driver state */
+struct bcm5974_mouse_state {
+ int fingers; /* number of fingers on trackpad */
+ int rel_x; /* horizontal relative counter */
+ int rel_y; /* vertical relative counter */
+ int wheel_x; /* horizontal wheel counter */
+ int wheel_y; /* vertical wheel counter */
+};
+
/* logical device structure */
struct bcm5974 {
char phys[64];
@@ -159,6 +191,7 @@ struct bcm5974 {
struct bt_data *bt_data; /* button transferred data */
struct urb *tp_urb; /* trackpad usb request block */
struct tp_data *tp_data; /* trackpad transferred data */
+ struct bcm5974_mouse_state ms; /* mouse state */
};
/* logical dimensions */
@@ -236,71 +269,204 @@ static inline int int2bound(const struct bcm5974_param *p, int x)
static void setup_events_to_report(struct input_dev *input_dev,
const struct bcm5974_config *cfg)
{
- __set_bit(EV_ABS, input_dev->evbit);
-
- input_set_abs_params(input_dev, ABS_PRESSURE,
- 0, cfg->p.dim, cfg->p.fuzz, 0);
- input_set_abs_params(input_dev, ABS_TOOL_WIDTH,
- 0, cfg->w.dim, cfg->w.fuzz, 0);
- input_set_abs_params(input_dev, ABS_X,
- 0, cfg->x.dim, cfg->x.fuzz, 0);
- input_set_abs_params(input_dev, ABS_Y,
- 0, cfg->y.dim, cfg->y.fuzz, 0);
-
__set_bit(EV_KEY, input_dev->evbit);
- __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
- __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
- __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
__set_bit(BTN_LEFT, input_dev->keybit);
+
+ switch (driver_mode) {
+ case MODE_MOUSE:
+ __set_bit(EV_REL, input_dev->evbit);
+ __set_bit(REL_X, input_dev->relbit);
+ __set_bit(REL_Y, input_dev->relbit);
+ __set_bit(REL_HWHEEL, input_dev->relbit);
+ __set_bit(REL_WHEEL, input_dev->relbit);
+ __set_bit(BTN_MIDDLE, input_dev->keybit);
+ __set_bit(BTN_RIGHT, input_dev->keybit);
+ break;
+ case MODE_TOUCHPAD:
+ __set_bit(EV_ABS, input_dev->evbit);
+ __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
+ __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
+ __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
+
+ input_set_abs_params(input_dev, ABS_PRESSURE,
+ 0, cfg->p.dim, cfg->p.fuzz, 0);
+ input_set_abs_params(input_dev, ABS_TOOL_WIDTH,
+ 0, cfg->w.dim, cfg->w.fuzz, 0);
+ input_set_abs_params(input_dev, ABS_X,
+ 0, cfg->x.dim, cfg->x.fuzz, 0);
+ input_set_abs_params(input_dev, ABS_Y,
+ 0, cfg->y.dim, cfg->y.fuzz, 0);
+ break;
+ }
}
-/* report button data as logical button state */
+/* update logical mouse button state */
+static void update_bt_mouse_state(struct input_dev *dev,
+ const struct bcm5974_mouse_state *ms,
+ const struct bt_data *bt)
+{
+ const int n = ms->fingers;
+
+ bool left, middle, right;
+ switch (mouse_button_mode) {
+ case 1:
+ left = n <= 1 && bt->button;
+ middle = n == 2 && bt->button;
+ right = n >= 3 && bt->button;
+ break;
+ case 2:
+ left = n <= 1 && bt->button;
+ middle = n >= 3 && bt->button;
+ right = n == 2 && bt->button;
+ break;
+ default:
+ left = bt->button;
+ middle = false;
+ right = false;
+ break;
+ };
+ input_report_key(dev, BTN_LEFT, left);
+ input_report_key(dev, BTN_MIDDLE, middle);
+ input_report_key(dev, BTN_RIGHT, right);
+}
+
+/* update logical touchpad button state */
+static void update_bt_touchpad_state(struct input_dev *dev,
+ const struct bt_data *bt)
+{
+ input_report_key(dev, BTN_LEFT, bt->button);
+}
+
+/* report button data as logical mouse/touchpad button state */
static int report_bt_state(struct bcm5974 *dev, int size)
{
if (size != sizeof(struct bt_data))
return -EIO;
- input_report_key(dev->input, BTN_LEFT, dev->bt_data->button);
+ switch (driver_mode) {
+ case MODE_MOUSE:
+ update_bt_mouse_state(dev->input, &dev->ms, dev->bt_data);
+ break;
+ case MODE_TOUCHPAD:
+ update_bt_touchpad_state(dev->input, dev->bt_data);
+ break;
+ }
+
input_sync(dev->input);
return 0;
}
-/* report trackpad data as logical trackpad state */
-static int report_tp_state(struct bcm5974 *dev, int size)
+/* update logical mouse motion state */
+static void update_tp_mouse_state(struct input_dev *dev,
+ struct bcm5974_mouse_state *ms,
+ const struct bcm5974_config *c,
+ const struct tp_finger *f,
+ int p, int n)
{
- const struct bcm5974_config *c = &dev->cfg;
- const struct tp_finger *f = dev->tp_data->finger;
- struct input_dev *input = dev->input;
- const int fingers = (size - 26) / 28;
- int p = 0, w, x, y, n = 0;
+ int dx = 0, dy = 0, sx = 0, sy = 0, swx = 0, swy = 0;
- if (size < 26 || (size - 26) % 28 != 0)
- return -EIO;
+ if (f) {
+ dx = raw2int(f->rel_x);
+ dy = raw2int(f->rel_y);
- if (fingers) {
- p = raw2int(f->force_major);
+ dprintk(9,
+ "bcm5974: p: %+05d dx: %+05d dy: %+05d n: %d\n",
+ p, dx, dy, n);
+ }
+
+ if (n >= 3) {
+ /* swipe */
+ ms->rel_x = 0;
+ ms->rel_y = 0;
+ ms->wheel_x += int2scale(&c->x, dx);
+ ms->wheel_y = 0;
+ swx = ms->wheel_x / mouse_hwheel_damping;
+ ms->wheel_x -= swx * mouse_hwheel_damping;
+ } else if (n == 2) {
+ /* scroll */
+ ms->rel_x = 0;
+ ms->rel_y = 0;
+ ms->wheel_x = 0;
+ ms->wheel_y += int2scale(&c->y, dy);
+ swy = ms->wheel_y / mouse_wheel_damping;
+ ms->wheel_y -= swy * mouse_wheel_damping;
+ } else {
+ /* pointer */
+ ms->rel_x += int2scale(&c->x, dx);
+ ms->rel_y += int2scale(&c->y, -dy);
+ ms->wheel_x = 0;
+ ms->wheel_y = 0;
+ sx = ms->rel_x / mouse_motion_damping;
+ sy = ms->rel_y / mouse_motion_damping;
+ ms->rel_x -= sx * mouse_motion_damping;
+ ms->rel_y -= sy * mouse_motion_damping;
+ }
+
+ ms->fingers = n;
+
+ input_report_rel(dev, REL_X, sx);
+ input_report_rel(dev, REL_Y, sy);
+ input_report_rel(dev, REL_HWHEEL, swx);
+ input_report_rel(dev, REL_WHEEL, swy);
+}
+
+/* update logical touchpad state */
+static void update_tp_touchpad_state(struct input_dev *dev,
+ const struct bcm5974_config *c,
+ const struct tp_finger *f,
+ int p, int n)
+{
+ int w, x, y;
+
+ if (f) {
w = raw2int(f->size_major);
x = raw2int(f->abs_x);
y = raw2int(f->abs_y);
- n = p > 0 ? fingers : 0;
dprintk(9,
"bcm5974: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n",
p, w, x, y, n);
- input_report_abs(input, ABS_TOOL_WIDTH, int2bound(&c->w, w));
- input_report_abs(input, ABS_X, int2bound(&c->x, x - c->x.devmin));
- input_report_abs(input, ABS_Y, int2bound(&c->y, c->y.devmax - y));
+ input_report_abs(dev, ABS_TOOL_WIDTH, int2bound(&c->w, w));
+ input_report_abs(dev, ABS_X, int2bound(&c->x, x - c->x.devmin));
+ input_report_abs(dev, ABS_Y, int2bound(&c->y, c->y.devmax - y));
}
- input_report_abs(input, ABS_PRESSURE, int2bound(&c->p, p));
+ input_report_abs(dev, ABS_PRESSURE, int2bound(&c->p, p));
+
+ input_report_key(dev, BTN_TOOL_FINGER, n == 1);
+ input_report_key(dev, BTN_TOOL_DOUBLETAP, n == 2);
+ input_report_key(dev, BTN_TOOL_TRIPLETAP, n > 2);
+}
+
+/* report trackpad data as logical mouse/touchpad state */
+static int report_tp_state(struct bcm5974 *dev, int size)
+{
+ const struct bcm5974_config *c = &dev->cfg;
+ const int fingers = (size - 26) / 28;
+ const struct tp_finger *f = 0;
+ int p = 0, n = 0;
+
+ if (size < 26 || (size - 26) % 28 != 0)
+ return -EIO;
+
+ if (fingers) {
+ f = dev->tp_data->finger;
+ p = raw2int(f->force_major);
+ n = p > 0 ? fingers : 0;
+ }
- input_report_key(input, BTN_TOOL_FINGER, n == 1);
- input_report_key(input, BTN_TOOL_DOUBLETAP, n == 2);
- input_report_key(input, BTN_TOOL_TRIPLETAP, n > 2);
+ switch (driver_mode) {
+ case MODE_MOUSE:
+ update_tp_mouse_state(dev->input, &dev->ms, c, f, p, n);
+ break;
+ case MODE_TOUCHPAD:
+ update_tp_touchpad_state(dev->input, c, f, p, n);
+ break;
+ }
- input_sync(input);
+ input_sync(dev->input);
return 0;
}
--
1.5.4.3
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 2/2] input: bcm5974-0.61: New default mouse driver mode
2008-09-01 20:08 [PATCH 2/2] input: bcm5974-0.61: New default mouse driver mode Henrik Rydberg
@ 2008-09-02 13:00 ` Dmitry Torokhov
2008-09-02 18:23 ` Henrik Rydberg
0 siblings, 1 reply; 3+ messages in thread
From: Dmitry Torokhov @ 2008-09-02 13:00 UTC (permalink / raw)
To: Henrik Rydberg; +Cc: akpm, linux-input, linux-kernel
Hi Henrik,
On Mon, Sep 01, 2008 at 10:08:35PM +0200, Henrik Rydberg wrote:
> Currently, the Apple bcm5974 driver only mimics a synaptics touchpad, not a mouse.
> This creates unnecessary complications on systems where the synaptics driver is absent
> or not configured, such as in a completely new system, or a text console.
Mousedev should provide a reasonable emulation of standard mouse
giving user chance to configure the system properly. There is no need
to task the driver to provide such emulation and therefore I will not
apply this patch.
> This patch
> provides a default compatibility configuration, which works as a multi-button mouse,
> implemented using rudimentary multi-finger options. It yields the following benefits:
>
> * A default Xorg configuration will pick up the mouse input interface, resulting in a
> functional mouse pointer out-of-the-box on many systems.
This happens automatically with Synaptics hardware on newer
distributions (at least Fedora 9 does this). As far as I know
SYnaptics driver does no look for specific product but for a certain
features of the input device and so shoudl work for BCM as well.
>
> * Two-finger scroll emulates a mouse wheel.
>
> * Three-finger swipe emulates a horizontal mouse wheel.
>
> * Multi-finger clicks emulate the middle and right mouse buttons.
>
The kenel driver should only do as little translation as possible,
allowing userspace to decide how to implement more fancy features.
> * The mouse driver also works with gpm in text consoles, providing cut-and-paste functionality.
>
Does not mousedev emulation work from GPM? Also GPM has evdev protocol
support which should work very well with synaptics-like touchpads.
--
Dmitry
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH 2/2] input: bcm5974-0.61: New default mouse driver mode
2008-09-02 13:00 ` Dmitry Torokhov
@ 2008-09-02 18:23 ` Henrik Rydberg
0 siblings, 0 replies; 3+ messages in thread
From: Henrik Rydberg @ 2008-09-02 18:23 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: akpm, linux-input, linux-kernel
Dmitry Torokhov wrote:
> Hi Henrik,
>
> On Mon, Sep 01, 2008 at 10:08:35PM +0200, Henrik Rydberg wrote:
>> Currently, the Apple bcm5974 driver only mimics a synaptics touchpad, not a mouse.
>> This creates unnecessary complications on systems where the synaptics driver is absent
>> or not configured, such as in a completely new system, or a text console.
>
> Mousedev should provide a reasonable emulation of standard mouse
> giving user chance to configure the system properly. There is no need
> to task the driver to provide such emulation and therefore I will not
> apply this patch.
>
I see, this is what puzzled me. Currently mousedev does not work with
bcm5974, but given the statement that it should, it was not hard finding
the reason; the ABS_X/Y messages get stuck in mousedev because bcm5974 does
not fire BTN_TOUCH events. I will send a fix for it shortly. I take it the
first clean-up patch is being applied.
>
>> * Two-finger scroll emulates a mouse wheel.
>>
>> * Three-finger swipe emulates a horizontal mouse wheel.
>>
>> * Multi-finger clicks emulate the middle and right mouse buttons.
>>
>
> The kenel driver should only do as little translation as possible,
> allowing userspace to decide how to implement more fancy features.
One could argue that those features are basic rather than fancy; virtually
every mouse of today provides equivalent functionality, and multitouch
features are here to stay. It is also discouraging in particular to
first-time apple users, having to spend a lot of time configuring their
system, only to be able to right-click or scroll using the trackpad.
Could it be something for the mousedev driver, perhaps?
Many thanks,
Henrik
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2008-09-02 18:23 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-01 20:08 [PATCH 2/2] input: bcm5974-0.61: New default mouse driver mode Henrik Rydberg
2008-09-02 13:00 ` Dmitry Torokhov
2008-09-02 18:23 ` Henrik Rydberg
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).