@@ -259,6 +259,12 @@ struct bcm5974 {
const struct tp_finger *index[MAX_FINGERS]; /* finger index data */
struct input_mt_pos pos[MAX_FINGERS]; /* position array */
int slots[MAX_FINGERS]; /* slot assignments */
+ bool thb_ignore; /* ignore thumb */
+ unsigned int thb_r_on; /* ratio to start ignoring thumb */
+ unsigned int thb_r_off; /* ratio to stop ignoring thumb */
+ int thb_y_on; /* y coord. to start ignoring thumb */
+ int thb_y_off; /* y coord. to stop ignoring thumb */
+ bool thb_found; /* thumb detected */
};
/* logical signal quality */
@@ -554,6 +560,7 @@ static int report_tp_state(struct bcm5974 *dev, int size)
const struct tp_finger *f;
struct input_dev *input = dev->input;
int raw_n, i, n = 0, p = 0, w = 0;
+ int thb_r = 0, thb_y = 0;
if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0)
return -EIO;
@@ -562,11 +569,30 @@ static int report_tp_state(struct bcm5974 *dev, int size)
f = (const struct tp_finger *)(dev->tp_data + c->tp_offset);
raw_n = (size - c->tp_offset) / SIZEOF_FINGER;
+ if (dev->thb_ignore) {
+ if (dev->thb_found) {
+ thb_r = dev->thb_r_off;
+ thb_y = dev->thb_y_off;
+ } else {
+ thb_r = dev->thb_r_on;
+ thb_y = dev->thb_y_on;
+ }
+ dev->thb_found = false;
+ }
+
for (i = 0; i < raw_n; i++) {
if (raw2int(f[i].touch_major) == 0)
continue;
dev->pos[n].x = raw2int(f[i].abs_x);
dev->pos[n].y = c->y.min + c->y.max - raw2int(f[i].abs_y);
+
+ if (dev->thb_ignore && thb_y < dev->pos[n].y &&
+ thb_r * 2 * raw2int(f[i].touch_major) >
+ 100 * c->touch_minor_f * raw2int(f[i].touch_minor)) {
+ dev->thb_found = true;
+ continue;
+ }
+
dev->index[n++] = &f[i];
p += raw2int(f[i].touch_major);
w += raw2int(f[i].tool_major);
@@ -596,6 +622,118 @@ static int report_tp_state(struct bcm5974 *dev, int size)
return 0;
}
+static ssize_t bcm5974_thb_ignore_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct bcm5974 *bcm5974_dev = dev_get_drvdata(dev);
+ return scnprintf(buf, PAGE_SIZE, "%d\n", bcm5974_dev->thb_ignore);
+}
+
+static ssize_t bcm5974_thb_ignore_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct bcm5974 *bcm5974_dev = dev_get_drvdata(dev);
+ int val;
+
+ unsigned int error = kstrtoint(buf, 10, &val);
+ if (error)
+ return error;
+
+ bcm5974_dev->thb_ignore = !!val;
+ bcm5974_dev->thb_found = false;
+
+ return count;
+}
+
+static ssize_t bcm5974_thb_r_on_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct bcm5974 *bcm5974_dev = dev_get_drvdata(dev);
+ return scnprintf(buf, PAGE_SIZE, "%d%%\n", bcm5974_dev->thb_r_on);
+}
+
+static ssize_t bcm5974_thb_r_on_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct bcm5974 *bcm5974_dev = dev_get_drvdata(dev);
+ unsigned int error = kstrtouint(buf, 10, &bcm5974_dev->thb_r_on);
+ return error ? error : count;
+}
+
+static ssize_t bcm5974_thb_r_off_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct bcm5974 *bcm5974_dev = dev_get_drvdata(dev);
+ return scnprintf(buf, PAGE_SIZE, "%d%%\n", bcm5974_dev->thb_r_off);
+}
+
+static ssize_t bcm5974_thb_r_off_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct bcm5974 *bcm5974_dev = dev_get_drvdata(dev);
+ unsigned int error = kstrtouint(buf, 10, &bcm5974_dev->thb_r_off);
+ return error ? error : count;
+}
+
+static ssize_t bcm5974_thb_y_on_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct bcm5974 *bcm5974_dev = dev_get_drvdata(dev);
+ return scnprintf(buf, PAGE_SIZE, "%d\n", bcm5974_dev->thb_y_on);
+}
+
+static ssize_t bcm5974_thb_y_on_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct bcm5974 *bcm5974_dev = dev_get_drvdata(dev);
+ int error = kstrtoint(buf, 10, &bcm5974_dev->thb_y_on);
+ return error ? error : count;
+}
+
+static ssize_t bcm5974_thb_y_off_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct bcm5974 *bcm5974_dev = dev_get_drvdata(dev);
+ return scnprintf(buf, PAGE_SIZE, "%d\n", bcm5974_dev->thb_y_off);
+}
+
+static ssize_t bcm5974_thb_y_off_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct bcm5974 *bcm5974_dev = dev_get_drvdata(dev);
+ int error = kstrtoint(buf, 10, &bcm5974_dev->thb_y_off);
+ return error ? error : count;
+}
+
+static DEVICE_ATTR(thumb_ignore, 0664, bcm5974_thb_ignore_show,
+ bcm5974_thb_ignore_store);
+static DEVICE_ATTR(thumb_ratio_on, 0664, bcm5974_thb_r_on_show,
+ bcm5974_thb_r_on_store);
+static DEVICE_ATTR(thumb_ratio_off, 0664, bcm5974_thb_r_off_show,
+ bcm5974_thb_r_off_store);
+static DEVICE_ATTR(thumb_y_on, 0664, bcm5974_thb_y_on_show,
+ bcm5974_thb_y_on_store);
+static DEVICE_ATTR(thumb_y_off, 0664, bcm5974_thb_y_off_show,
+ bcm5974_thb_y_off_store);
+
+static struct attribute *bcm5974_attributes[] = {
+ &dev_attr_thumb_ignore.attr,
+ &dev_attr_thumb_ratio_on.attr,
+ &dev_attr_thumb_ratio_off.attr,
+ &dev_attr_thumb_y_on.attr,
+ &dev_attr_thumb_y_off.attr,
+ NULL
+};
+
+static const struct attribute_group bcm5974_attr_group = {
+ .attrs = bcm5974_attributes,
+};
+
/* Wellspring initialization constants */
#define BCM5974_WELLSPRING_MODE_READ_REQUEST_ID 1
#define BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID 9
@@ -880,6 +1018,11 @@ static int bcm5974_probe(struct usb_interface *iface,
dev->cfg = *cfg;
mutex_init(&dev->pm_mutex);
+ dev->thb_r_on = 40;
+ dev->thb_r_off = 60;
+ dev->thb_y_on = (cfg->y.max - cfg->y.min) * 0.75 + cfg->y.min;
+ dev->thb_y_off = (cfg->y.max - cfg->y.min) * 0.73 + cfg->y.min;
+
/* setup urbs */
if (cfg->tp_type == TYPE1) {
dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL);
@@ -941,8 +1084,14 @@ static int bcm5974_probe(struct usb_interface *iface,
/* save our data pointer in this interface device */
usb_set_intfdata(iface, dev);
+ error = sysfs_create_group(&input_dev->dev.kobj, &bcm5974_attr_group);
+ if (error)
+ goto err_unregister_input;
+
return 0;
+err_unregister_input:
+ input_unregister_device(dev->input);
err_free_buffer:
usb_free_coherent(dev->udev, dev->cfg.tp_datalen,
dev->tp_data, dev->tp_urb->transfer_dma);
@@ -967,6 +1116,7 @@ static void bcm5974_disconnect(struct usb_interface *iface)
usb_set_intfdata(iface, NULL);
+ sysfs_remove_group(&dev->input->dev.kobj, &bcm5974_attr_group);
input_unregister_device(dev->input);
usb_free_coherent(dev->udev, dev->cfg.tp_datalen,
dev->tp_data, dev->tp_urb->transfer_dma);