kumama go言語とかgolangとかGAEとかネットサービスとかその他色々・・・

9Jan/10Off

beagleboard-eclairでマウス(未完

年末ぐらいからの色々。その1。

WebSocket が Android 2.0 (eclair) で使えたら良いなぁと思いつつ、
BeagleBoardでeclair動かしてみてたものの。
マウスが標準のAndroidだと未サポートってことで、ちょっと作りかけ。

色々なAndroidの実装というかリポジトリ覗いたんだけど、Android側に手を入れてる実装が多い。
Android側の更新が頻繁なことを考えるとKernel側でマウスを仮想タッチパネルに仕立て上げるほうが
良さそうっていう発想の元色々。

はじめはフィルタドライバで実装してたんだけど、Androidが拾ってくれない。
/dev/input/mouse とかは Android の EventHub は見てなくて/dev/input/event を見てる。

ということで evdev.c で EV_REL を EV_ABS にごまかしたりする仮想デバイスぽいドライバを。
カーソルの描画はOVL2使えば良いやって思ってたけど、微妙に失敗してるっぽい。
っていうか、androidがfbのダブルバッファリングに使ってるのか?
fbconかもしれん…けど見切れてない。

あと、画面の電源が入ってないときはタッチパネルのイベントを無視するっていうコードが、
Android側に入っていてそこだけは面倒でAndroid側修正した。

frameworks/base/services/java/com/android/server/KeyInputQueue.java:502
                        if (ev.type == RawInputEvent.EV_ABS) {
                            send = true;
                        }

とりあえずな現状のkernelパッチは続きに。

diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index af87135..47bfa45 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -20,8 +20,20 @@
#include #include #include +#include #include "input-compat.h"

+static unsigned short cursor[8][8] = {
+ {0,0,0,0,0,2,2,2},
+ {0,1,1,0,2,2,2,2},
+ {0,1,1,1,0,2,2,2},
+ {0,0,1,1,1,0,2,2},
+ {0,2,0,1,1,1,0,2},
+ {2,2,2,0,1,0,2,2},
+ {2,2,2,2,0,2,2,2},
+ {2,2,2,2,2,2,2,2}
+};
+
struct evdev {
int exist;
int open;
@@ -51,7 +63,7 @@ static struct evdev *evdev_table[EVDEV_MINORS];
static DEFINE_MUTEX(evdev_table_mutex);

static void evdev_pass_event(struct evdev_client *client,
- struct input_event *event)
+ struct input_event *event)
{
/*
* Interrupts are disabled, just acquire the lock
@@ -65,17 +77,28 @@ static void evdev_pass_event(struct evdev_client *client,
kill_fasync(&client->fasync, SIGIO, POLL_IN);
}

+static int x = 0;
+static int y = 0;
+static int press = 0;
+
/*
* Pass incoming event to all connected clients.
*/
static void evdev_event(struct input_handle *handle,
unsigned int type, unsigned int code, int value)
{
+ int lx = 0;
+ int ly = 0;
+ int lfb = 0;
+
struct evdev *evdev = handle->private;
struct evdev_client *client;
struct input_event event;
struct timespec ts;

+ printk(KERN_DEBUG "[%s] Event. Dev: %s, Type: %d, Code: %d, Value: %d
",
+ handle->name, handle->dev->phys, type, code, value);
+
ktime_get_ts(&ts);
event.time.tv_sec = ts.tv_sec;
event.time.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
@@ -83,6 +106,230 @@ static void evdev_event(struct input_handle *handle,
event.code = code;
event.value = value;

+ if( type == EV_REL ){
+ switch( code ){
+ case REL_X: x += value; break;
+ case REL_Y: y += value; break;
+ default: break;
+ }
+ if( press ) {
+ rcu_read_lock();
+ event.type = EV_ABS;
+ event.code = ABS_X;
+ event.value = x;
+ client = rcu_dereference(evdev->grab);
+ if (client)
+ evdev_pass_event(client, &event);
+ else
+ list_for_each_entry_rcu(client, &evdev->client_list, node)
+ evdev_pass_event(client, &event);
+ rcu_read_unlock();
+
+ rcu_read_lock();
+ event.type = EV_ABS;
+ event.code = ABS_Y;
+ event.value = y;
+ client = rcu_dereference(evdev->grab);
+ if (client)
+ evdev_pass_event(client, &event);
+ else
+ list_for_each_entry_rcu(client, &evdev->client_list, node)
+ evdev_pass_event(client, &event);
+ rcu_read_unlock();
+
+ rcu_read_lock();
+ event.type = EV_ABS;
+ event.code = ABS_PRESSURE;
+ event.value = press;
+ client = rcu_dereference(evdev->grab);
+ if (client)
+ evdev_pass_event(client, &event);
+ else
+ list_for_each_entry_rcu(client, &evdev->client_list, node)
+ evdev_pass_event(client, &event);
+ rcu_read_unlock();
+
+ rcu_read_lock();
+ event.type = 0;
+ event.code = 0;
+ event.value = 0;
+ client = rcu_dereference(evdev->grab);
+ if (client)
+ evdev_pass_event(client, &event);
+ else
+ list_for_each_entry_rcu(client, &evdev->client_list, node)
+ evdev_pass_event(client, &event);
+ rcu_read_unlock();
+ }
+
+ if( x < 0) x = 0; if( x > 1024 ) x = 1024;
+ if( y < 0) y = 0; if( y > 768 ) y = 768;
+ printk(KERN_DEBUG "%d, %d
", x, y );
+ for( lfb = 0; lfb < 3; lfb++){ + for( ly = 0; ly< 8; ly++){ + for( lx = 0; lx< 8; lx++){ + switch( cursor[ly][lx] ){ + case 1: + registered_fb[lfb]->screen_base[(1024*(y+ly) + x + lx) * 2] = 0xFF;
+ registered_fb[lfb]->screen_base[(1024*(y+ly) + x + lx) * 2 + 1] = 0xFF;
+ break;
+ case 0:
+ registered_fb[lfb]->screen_base[(1024*(y+ly) + x + lx) * 2] = 0;
+ registered_fb[lfb]->screen_base[(1024*(y+ly) + x + lx) * 2 + 1] = 0;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if( type == EV_KEY ){
+ if( code == BTN_LEFT && value == 1 ){
+ printk(KERN_DEBUG "%d, %d left touch
", x, y );
+
+ press = 255;
+
+ rcu_read_lock();
+ event.type = EV_ABS;
+ event.code = ABS_X;
+ event.value = x;
+ client = rcu_dereference(evdev->grab);
+ if (client)
+ evdev_pass_event(client, &event);
+ else
+ list_for_each_entry_rcu(client, &evdev->client_list, node)
+ evdev_pass_event(client, &event);
+ rcu_read_unlock();
+
+ rcu_read_lock();
+ event.type = EV_ABS;
+ event.code = ABS_Y;
+ event.value = y;
+ client = rcu_dereference(evdev->grab);
+ if (client)
+ evdev_pass_event(client, &event);
+ else
+ list_for_each_entry_rcu(client, &evdev->client_list, node)
+ evdev_pass_event(client, &event);
+ rcu_read_unlock();
+
+ rcu_read_lock();
+ event.type = EV_ABS;
+ event.code = ABS_PRESSURE;
+ event.value = 255;
+ client = rcu_dereference(evdev->grab);
+ if (client)
+ evdev_pass_event(client, &event);
+ else
+ list_for_each_entry_rcu(client, &evdev->client_list, node)
+ evdev_pass_event(client, &event);
+ rcu_read_unlock();
+
+ rcu_read_lock();
+ event.type = EV_KEY;
+ event.code = BTN_TOUCH;
+ event.value = 1;
+ client = rcu_dereference(evdev->grab);
+ if (client)
+ evdev_pass_event(client, &event);
+ else
+ list_for_each_entry_rcu(client, &evdev->client_list, node)
+ evdev_pass_event(client, &event);
+ rcu_read_unlock();
+
+ rcu_read_lock();
+ event.type = 0;
+ event.code = 0;
+ event.value = 0;
+ client = rcu_dereference(evdev->grab);
+ if (client)
+ evdev_pass_event(client, &event);
+ else
+ list_for_each_entry_rcu(client, &evdev->client_list, node)
+ evdev_pass_event(client, &event);
+ rcu_read_unlock();
+
+ wake_up_interruptible(&evdev->wait);
+ return;
+ }
+ if( code == BTN_LEFT && value == 0 ){
+ printk(KERN_DEBUG "%d, %d left untouch
", x, y );
+
+ press = 0;
+
+ rcu_read_lock();
+ event.type = EV_ABS;
+ event.code = ABS_X;
+ event.value = x;
+ client = rcu_dereference(evdev->grab);
+ if (client)
+ evdev_pass_event(client, &event);
+ else
+ list_for_each_entry_rcu(client, &evdev->client_list, node)
+ evdev_pass_event(client, &event);
+ rcu_read_unlock();
+
+ rcu_read_lock();
+ event.type = EV_ABS;
+ event.code = ABS_Y;
+ event.value = y;
+ client = rcu_dereference(evdev->grab);
+ if (client)
+ evdev_pass_event(client, &event);
+ else
+ list_for_each_entry_rcu(client, &evdev->client_list, node)
+ evdev_pass_event(client, &event);
+ rcu_read_unlock();
+
+ rcu_read_lock();
+ event.type = EV_ABS;
+ event.code = ABS_PRESSURE;
+ event.value = 255;
+ client = rcu_dereference(evdev->grab);
+ if (client)
+ evdev_pass_event(client, &event);
+ else
+ list_for_each_entry_rcu(client, &evdev->client_list, node)
+ evdev_pass_event(client, &event);
+ rcu_read_unlock();
+
+ rcu_read_lock();
+ event.type = EV_KEY;
+ event.code = BTN_TOUCH;
+ event.value = 0;
+ client = rcu_dereference(evdev->grab);
+ if (client)
+ evdev_pass_event(client, &event);
+ else
+ list_for_each_entry_rcu(client, &evdev->client_list, node)
+ evdev_pass_event(client, &event);
+ rcu_read_unlock();
+
+ rcu_read_lock();
+ event.type = 0;
+ event.code = 0;
+ event.value = 0;
+ client = rcu_dereference(evdev->grab);
+ if (client)
+ evdev_pass_event(client, &event);
+ else
+ list_for_each_entry_rcu(client, &evdev->client_list, node)
+ evdev_pass_event(client, &event);
+ rcu_read_unlock();
+
+ wake_up_interruptible(&evdev->wait);
+ return;
+ }
+ if( code == BTN_RIGHT && value == 1 ){
+ printk(KERN_DEBUG "%d, %d right touch
", x, y );
+ }
+ if( code == BTN_RIGHT && value == 0 ){
+ printk(KERN_DEBUG "%d, %d right untouch
", x, y );
+ }
+ }
+
rcu_read_lock();

client = rcu_dereference(evdev->grab);
@@ -364,7 +611,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
return -EINVAL;

if (client->head == client->tail && evdev->exist &&
- (file->f_flags & O_NONBLOCK))
+ (file->f_flags & O_NONBLOCK))
return -EAGAIN;

retval = wait_event_interruptible(evdev->wait,
@@ -376,7 +623,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
return -ENODEV;

while (retval + input_event_size() <= count && - evdev_fetch_next_event(client, &event)) { + evdev_fetch_next_event(client, &event)) { if (input_event_to_user(buffer + retval, &event)) return -EFAULT; @@ -482,18 +729,48 @@ static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user unsigned long *bits; int len; + printk(KERN_DEBUG "handle_eviocgbit " ); + + static unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; + static unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; + static unsigned long absbit[BITS_TO_LONGS(ABS_CNT)]; + switch (_IOC_NR(cmd) & EV_MAX) { - case 0: bits = dev->evbit; len = EV_MAX; break;
- case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
- case EV_REL: bits = dev->relbit; len = REL_MAX; break;
- case EV_ABS: bits = dev->absbit; len = ABS_MAX; break;
- case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break;
- case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
- case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
- case EV_FF: bits = dev->ffbit; len = FF_MAX; break;
- case EV_SW: bits = dev->swbit; len = SW_MAX; break;
- default: return -EINVAL;
+ case 0: bits = dev->evbit; len = EV_MAX; break;
+ case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
+ case EV_REL: bits = dev->relbit; len = REL_MAX; break;
+ case EV_ABS: bits = dev->relbit; len = ABS_MAX; break;
+ case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break;
+ case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
+ case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
+ case EV_FF: bits = dev->ffbit; len = FF_MAX; break;
+ case EV_SW: bits = dev->swbit; len = SW_MAX; break;
+ default: return -EINVAL;
+ }
+
+#define test_bit(bit, array) (array[bit/32] & (1<<(bit%32))) + if( test_bit( BTN_MOUSE, dev->keybit ) ){
+ printk(KERN_DEBUG "mod keys
" );
+
+ // modify mouse to touch
+ memset( evbit, 0, sizeof(evbit) ); // clear evbits
+ evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY);
+ evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS);
+
+ memset( keybit, 0, sizeof(keybit) ); // clear BTN_MOUSE
+ keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH);
+
+ absbit[BIT_WORD(ABS_X)] |= BIT_MASK(ABS_X);
+ absbit[BIT_WORD(ABS_Y)] |= BIT_MASK(ABS_Y);
+ absbit[BIT_WORD(ABS_PRESSURE)] |= BIT_MASK(ABS_PRESSURE);
+
+ switch (_IOC_NR(cmd) & EV_MAX) {
+ case 0: bits = evbit; len = EV_MAX; break;
+ case EV_KEY: bits = keybit; len = KEY_MAX; break;
+ case EV_ABS: bits = absbit; len = ABS_MAX; break;
+ default: break;
+ }
}

/*
@@ -530,165 +807,186 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,

switch (cmd) {

- case EVIOCGVERSION:
- return put_user(EV_VERSION, ip);
+ case EVIOCGVERSION:
+ return put_user(EV_VERSION, ip);

- case EVIOCGID:
- if (copy_to_user(p, &dev->id, sizeof(struct input_id)))
- return -EFAULT;
- return 0;
+ case EVIOCGID:
+ if (copy_to_user(p, &dev->id, sizeof(struct input_id)))
+ return -EFAULT;
+ return 0;

- case EVIOCGREP:
- if (!test_bit(EV_REP, dev->evbit))
- return -ENOSYS;
- if (put_user(dev->rep[REP_DELAY], ip))
- return -EFAULT;
- if (put_user(dev->rep[REP_PERIOD], ip + 1))
- return -EFAULT;
- return 0;
+ case EVIOCGREP:
+ if (!test_bit(EV_REP, dev->evbit))
+ return -ENOSYS;
+ if (put_user(dev->rep[REP_DELAY], ip))
+ return -EFAULT;
+ if (put_user(dev->rep[REP_PERIOD], ip + 1))
+ return -EFAULT;
+ return 0;

- case EVIOCSREP:
- if (!test_bit(EV_REP, dev->evbit))
- return -ENOSYS;
- if (get_user(u, ip))
- return -EFAULT;
- if (get_user(v, ip + 1))
- return -EFAULT;
+ case EVIOCSREP:
+ if (!test_bit(EV_REP, dev->evbit))
+ return -ENOSYS;
+ if (get_user(u, ip))
+ return -EFAULT;
+ if (get_user(v, ip + 1))
+ return -EFAULT;

- input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u);
- input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v);
+ input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u);
+ input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v);

- return 0;
+ return 0;

- case EVIOCGKEYCODE:
- if (get_user(t, ip))
- return -EFAULT;
+ case EVIOCGKEYCODE:
+ if (get_user(t, ip))
+ return -EFAULT;

- error = input_get_keycode(dev, t, &v);
- if (error)
- return error;
+ error = input_get_keycode(dev, t, &v);
+ if (error)
+ return error;

- if (put_user(v, ip + 1))
- return -EFAULT;
+ if (put_user(v, ip + 1))
+ return -EFAULT;

- return 0;
+ return 0;

- case EVIOCSKEYCODE:
- if (get_user(t, ip) || get_user(v, ip + 1))
- return -EFAULT;
+ case EVIOCSKEYCODE:
+ if (get_user(t, ip) || get_user(v, ip + 1))
+ return -EFAULT;

- return input_set_keycode(dev, t, v);
+ return input_set_keycode(dev, t, v);

- case EVIOCRMFF:
- return input_ff_erase(dev, (int)(unsigned long) p, file);
+ case EVIOCRMFF:
+ return input_ff_erase(dev, (int)(unsigned long) p, file);

- case EVIOCGEFFECTS:
- i = test_bit(EV_FF, dev->evbit) ?
- dev->ff->max_effects : 0;
- if (put_user(i, ip))
- return -EFAULT;
- return 0;
+ case EVIOCGEFFECTS:
+ i = test_bit(EV_FF, dev->evbit) ?
+ dev->ff->max_effects : 0;
+ if (put_user(i, ip))
+ return -EFAULT;
+ return 0;

- case EVIOCGRAB:
- if (p)
- return evdev_grab(evdev, client);
- else
- return evdev_ungrab(evdev, client);
+ case EVIOCGRAB:
+ if (p)
+ return evdev_grab(evdev, client);
+ else
+ return evdev_ungrab(evdev, client);

- default:
+ default:

- if (_IOC_TYPE(cmd) != 'E')
- return -EINVAL;
+ if (_IOC_TYPE(cmd) != 'E')
+ return -EINVAL;

- if (_IOC_DIR(cmd) == _IOC_READ) {
+ if (_IOC_DIR(cmd) == _IOC_READ) {

- if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
- return handle_eviocgbit(dev, cmd, p, compat_mode);
+ if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
+ return handle_eviocgbit(dev, cmd, p, compat_mode);

- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
- return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd),
- p, compat_mode);
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
+ return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd),
+ p, compat_mode);

- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
- return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd),
- p, compat_mode);
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
+ return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd),
+ p, compat_mode);

- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
- return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd),
- p, compat_mode);
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
+ return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd),
+ p, compat_mode);

- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0)))
- return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd),
- p, compat_mode);
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0)))
+ return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd),
+ p, compat_mode);

- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0)))
- return str_to_user(dev->name, _IOC_SIZE(cmd), p);
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0)))
+ return str_to_user(dev->name, _IOC_SIZE(cmd), p);

- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0)))
- return str_to_user(dev->phys, _IOC_SIZE(cmd), p);
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0)))
+ return str_to_user(dev->phys, _IOC_SIZE(cmd), p);

- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0)))
- return str_to_user(dev->uniq, _IOC_SIZE(cmd), p);
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0)))
+ return str_to_user(dev->uniq, _IOC_SIZE(cmd), p);

- if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
+ if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {

- t = _IOC_NR(cmd) & ABS_MAX;
+ t = _IOC_NR(cmd) & ABS_MAX;

- abs.value = dev->abs[t];
- abs.minimum = dev->absmin[t];
- abs.maximum = dev->absmax[t];
- abs.fuzz = dev->absfuzz[t];
- abs.flat = dev->absflat[t];
+ abs.value = dev->abs[t];
+ abs.minimum = dev->absmin[t];
+ abs.maximum = dev->absmax[t];
+ abs.fuzz = dev->absfuzz[t];
+ abs.flat = dev->absflat[t];

- if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
- return -EFAULT;
+ switch( t ){
+ case ABS_X:
+ abs.value = x;
+ abs.minimum = 0;
+ abs.maximum = 768;
+ break;
+ case ABS_Y:
+ abs.value = y;
+ abs.minimum = 0;
+ abs.maximum = 1024;
+ break;
+ case ABS_PRESSURE:
+ abs.value = press;
+ abs.minimum = 0;
+ abs.maximum = 255;
+ break;
+ defaut:
+ break;
+ }

- return 0;
- }
+ if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
+ return -EFAULT;

- }
+ return 0;
+ }

- if (_IOC_DIR(cmd) == _IOC_WRITE) {
+ }

- if (_IOC_NR(cmd) == _IOC_NR(EVIOCSFF)) {
+ if (_IOC_DIR(cmd) == _IOC_WRITE) {

- if (input_ff_effect_from_user(p, _IOC_SIZE(cmd), &effect))
- return -EFAULT;
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCSFF)) {

- error = input_ff_upload(dev, &effect, file);
+ if (input_ff_effect_from_user(p, _IOC_SIZE(cmd), &effect))
+ return -EFAULT;

- if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
- return -EFAULT;
+ error = input_ff_upload(dev, &effect, file);

- return error;
- }
+ if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
+ return -EFAULT;

- if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
+ return error;
+ }

- t = _IOC_NR(cmd) & ABS_MAX;
+ if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {

- if (copy_from_user(&abs, p,
- sizeof(struct input_absinfo)))
- return -EFAULT;
+ t = _IOC_NR(cmd) & ABS_MAX;

- /*
- * Take event lock to ensure that we are not
- * changing device parameters in the middle
- * of event.
- */
- spin_lock_irq(&dev->event_lock);
+ if (copy_from_user(&abs, p,
+ sizeof(struct input_absinfo)))
+ return -EFAULT;

- dev->abs[t] = abs.value;
- dev->absmin[t] = abs.minimum;
- dev->absmax[t] = abs.maximum;
- dev->absfuzz[t] = abs.fuzz;
- dev->absflat[t] = abs.flat;
+ /*
+ * Take event lock to ensure that we are not
+ * changing device parameters in the middle
+ * of event.
+ */
+ spin_lock_irq(&dev->event_lock);

- spin_unlock_irq(&dev->event_lock);
+ dev->abs[t] = abs.value;
+ dev->absmin[t] = abs.minimum;
+ dev->absmax[t] = abs.maximum;
+ dev->absfuzz[t] = abs.fuzz;
+ dev->absflat[t] = abs.flat;

- return 0;
+ spin_unlock_irq(&dev->event_lock);
+
+ return 0;
+ }
}
- }
+ break;
}
return -EINVAL;
}




Filed under: android Comments Off
Comments (0) Trackbacks (0)

Sorry, the comment form is closed at this time.

No trackbacks yet.