aboutsummaryrefslogtreecommitdiff
path: root/drivers/input/touchscreen/ts_filter_chain.c
diff options
context:
space:
mode:
authorNelson Castillo <arhuaco@freaks-unidos.net>2009-03-10 12:04:40 +0000
committerAndy Green <agreen@octopus.localdomain>2009-03-10 12:04:40 +0000
commit675a93c65029c2cda2d00bb73f9d7f0e1c9d42dc (patch)
treeeeed4bd25e60816b9abcf6ac5f8890c9e9363f2d /drivers/input/touchscreen/ts_filter_chain.c
parent25db5513242fb8d9fac0f461e110cc82d6b3f90f (diff)
Add filter_chain object
Filter chains should be completely opaque to the drivers that use it. We fix this with this patch. ~ Make the "filter chain" a new object. ~ We can build with CONFIG_TOUCHSCREEN_FILTER=n with no problems in a cleaner way. ~ Update s3c2410_ts.c to use the filter_chain object. ~ Cleanups. Signed-off-by: Nelson Castillo <arhuaco@freaks-unidos.net>
Diffstat (limited to 'drivers/input/touchscreen/ts_filter_chain.c')
-rw-r--r--drivers/input/touchscreen/ts_filter_chain.c119
1 files changed, 67 insertions, 52 deletions
diff --git a/drivers/input/touchscreen/ts_filter_chain.c b/drivers/input/touchscreen/ts_filter_chain.c
index 9b2b1c5400d..a6346bdba3e 100644
--- a/drivers/input/touchscreen/ts_filter_chain.c
+++ b/drivers/input/touchscreen/ts_filter_chain.c
@@ -18,6 +18,8 @@
#include <linux/kernel.h>
#include <linux/device.h>
+
+#include "ts_filter_chain.h"
#include "ts_filter.h"
/*
@@ -41,28 +43,39 @@ static int sptrlen(const void *arr)
return len;
}
-/* FIXME: rename & remove this temporal hack. */
-static struct ts_filter **revchain;
-struct ts_filter **ts_filter_chain_create(
+struct ts_filter_chain {
+ /* All of the filters. */
+ struct ts_filter **arr;
+ /* Filters that can propagate values in the chain. */
+ struct ts_filter **pchain;
+ /* Length of the pchain array. */
+ int pchain_len;
+ /* FIXME: Add a spinlock and use it. */
+};
+
+struct ts_filter_chain *ts_filter_chain_create(
struct platform_device *pdev,
- const struct ts_filter_configuration conf[],
+ const struct ts_filter_chain_configuration conf[],
int count_coords)
{
- struct ts_filter **arr;
+ struct ts_filter_chain *c;
int count = 0;
int len;
- int nrev = 0;
BUG_ON((count_coords < 1));
BUG_ON(count_coords > MAX_TS_FILTER_COORDS);
+ c = kzalloc(sizeof(struct ts_filter_chain), GFP_KERNEL);
+ if (!c)
+ goto create_err_1;
+
len = (sptrlen(conf) + 1);
- /* memory for two null-terminated arrays of filters */
- arr = kzalloc(2 * sizeof(struct ts_filter *) * len, GFP_KERNEL);
- if (!arr)
- goto create_err;
- revchain = arr + len;
+ /* Memory for two null-terminated arrays of filters. */
+ c->arr = kzalloc(2 * sizeof(struct ts_filter *) * len, GFP_KERNEL);
+ if (!c->arr)
+ goto create_err_1;
+ c->pchain = c->arr + len;
while (conf->api) {
/* TODO: Can we get away with only sending pdev->dev? */
@@ -71,60 +84,63 @@ struct ts_filter **ts_filter_chain_create(
if (!f) {
dev_info(&pdev->dev, "Filter %d creation failed\n",
count);
- goto create_err;
+ goto create_err_2;
}
f->api = conf->api;
- arr[count++] = f;
+ c->arr[count++] = f;
- /* Filters that can propagate values in the chain. */
if (f->api->haspoint && f->api->getpoint && f->api->process)
- revchain[nrev++] = f;
+ c->pchain[c->pchain_len++] = f;
conf++;
}
dev_info(&pdev->dev, "%d filter(s) initialized\n", count);
- return arr;
-
-create_err:
+ return c;
+create_err_2:
+ ts_filter_chain_destroy(c); /* Also frees c. */
+create_err_1:
dev_info(&pdev->dev, "Error in filter chain initialization\n");
-
- ts_filter_chain_destroy(arr);
-
- return NULL;
+ /*
+ * FIXME: Individual filters have to return errors this way.
+ * We only have to forward the errors we find.
+ */
+ return ERR_PTR(-ENOMEM);
}
EXPORT_SYMBOL_GPL(ts_filter_chain_create);
-void ts_filter_chain_destroy(struct ts_filter **arr)
+void ts_filter_chain_destroy(struct ts_filter_chain *c)
{
- struct ts_filter **a = arr;
- int count = 0;
-
- while (arr && *a) {
- ((*a)->api->destroy)(*a);
- a++;
- count++;
+ if (c->arr) {
+ struct ts_filter **a = c->arr;
+ while (*a) {
+ ((*a)->api->destroy)(*a);
+ a++;
+ }
+ kfree(c->arr);
}
-
- kfree(arr);
+ kfree(c);
}
EXPORT_SYMBOL_GPL(ts_filter_chain_destroy);
-void ts_filter_chain_clear(struct ts_filter **arr)
+void ts_filter_chain_clear(struct ts_filter_chain *c)
{
- while (*arr) {
- if ((*arr)->api->clear)
- ((*arr)->api->clear)(*arr);
- arr++;
+ struct ts_filter **a = c->arr;
+
+ while (*a) {
+ if ((*a)->api->clear)
+ ((*a)->api->clear)(*a);
+ a++;
}
}
EXPORT_SYMBOL_GPL(ts_filter_chain_clear);
-static void ts_filter_chain_scale(struct ts_filter **a, int *coords)
+static void ts_filter_chain_scale(struct ts_filter_chain *c, int *coords)
{
+ struct ts_filter **a = c->arr;
while (*a) {
if ((*a)->api->scale)
((*a)->api->scale)(*a, coords);
@@ -132,37 +148,36 @@ static void ts_filter_chain_scale(struct ts_filter **a, int *coords)
}
}
-int ts_filter_chain_feed(struct ts_filter **arr, int *coords)
+int ts_filter_chain_feed(struct ts_filter_chain *c, int *coords)
{
- /* FIXME: only using revchain */
- int len = sptrlen(revchain); /* FIXME: save this */
+ int len = c->pchain_len;
int i = len - 1;
- if (!arr[0])
- return 1; /* Nothing to do. Filtering disabled. */
+ if (!c->pchain[0])
+ return 1; /* Nothing to do. */
- BUG_ON(arr[0]->api->haspoint(arr[0]));
+ BUG_ON(c->pchain[0]->api->haspoint(c->pchain[0]));
- if (arr[0]->api->process(arr[0], coords))
+ if (c->pchain[0]->api->process(c->pchain[0], coords))
return -1;
while (i >= 0 && i < len) {
- if (revchain[i]->api->haspoint(revchain[i])) {
- revchain[i]->api->getpoint(revchain[i], coords);
+ if (c->pchain[i]->api->haspoint(c->pchain[i])) {
+ c->pchain[i]->api->getpoint(c->pchain[i], coords);
if (++i < len &&
- revchain[i]->api->process(revchain[i], coords))
+ c->pchain[i]->api->process(c->pchain[i], coords))
return -1; /* Error. */
} else {
i--;
}
}
- if (i >= 0) {
- BUG_ON(i != len); /* FIXME: Remove BUG_ON. */
- ts_filter_chain_scale(arr, coords); /* TODO: arr! */
+ if (i >= 0) { /* Same as i == len. */
+ ts_filter_chain_scale(c, coords);
+ return 1;
}
- return i >= 0; /* Same as i == len. */
+ return 0;
}
EXPORT_SYMBOL_GPL(ts_filter_chain_feed);