Commit db30c705 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (29 commits)
  Input: i8042 - add Dell Vostro 1510 to nomux list
  Input: gtco - use USB endpoint API
  Input: add support for Maple controller as a joystick
  Input: atkbd - broaden the Dell DMI signatures
  Input: HIL drivers - add MODULE_ALIAS()
  Input: map_to_7segment.h - convert to __inline__ for userspace
  Input: add support for enhanced rotary controller on pxa930 and pxa935
  Input: add support for trackball on pxa930 and pxa935
  Input: add da9034 touchscreen support
  Input: ads7846 - strict_strtoul takes unsigned long
  Input: make some variables and functions static
  Input: add tsc2007 based touchscreen driver
  Input: psmouse - add module parameters to control OLPC touchpad delays
  Input: i8042 - add Gigabyte M912 netbook to noloop exception table
  Input: atkbd - Samsung NC10 key repeat fix
  Input: atkbd - add keyboard quirk for HP Pavilion ZV6100 laptop
  Input: libps2 - handle 0xfc responses from devices
  Input: add support for Wacom W8001 penabled serial touchscreen
  Input: synaptics - report multi-taps only if supported by the device
  Input: add joystick driver for Walkera WK-0701 RC transmitter
  ...
parents c861ea2c 9334e90d
Walkera WK-0701 transmitter is supplied with a ready to fly Walkera
helicopters such as HM36, HM37, HM60. The walkera0701 module enables to use
this transmitter as joystick
Devel homepage and download:
http://zub.fei.tuke.sk/walkera-wk0701/
or use cogito:
cg-clone http://zub.fei.tuke.sk/GIT/walkera0701-joystick
Connecting to PC:
At back side of transmitter S-video connector can be found. Modulation
pulses from processor to HF part can be found at pin 2 of this connector,
pin 3 is GND. Between pin 3 and CPU 5k6 resistor can be found. To get
modulation pulses to PC, signal pulses must be amplified.
Cable: (walkera TX to parport)
Walkera WK-0701 TX S-VIDEO connector:
(back side of TX)
__ __ S-video: canon25
/ |_| \ pin 2 (signal) NPN parport
/ O 4 3 O \ pin 3 (GND) LED ________________ 10 ACK
( O 2 1 O ) | C
\ ___ / 2 ________________________|\|_____|/
| [___] | |/| B |\
------- 3 __________________________________|________________ 25 GND
E
I use green LED and BC109 NPN transistor.
Software:
Build kernel with walkera0701 module. Module walkera0701 need exclusive
access to parport, modules like lp must be unloaded before loading
walkera0701 module, check dmesg for error messages. Connect TX to PC by
cable and run jstest /dev/input/js0 to see values from TX. If no value can
be changed by TX "joystick", check output from /proc/interrupts. Value for
(usually irq7) parport must increase if TX is on.
Technical details:
Driver use interrupt from parport ACK input bit to measure pulse length
using hrtimers.
Frame format:
Based on walkera WK-0701 PCM Format description by Shaul Eizikovich.
(downloaded from http://www.smartpropoplus.com/Docs/Walkera_Wk-0701_PCM.pdf)
Signal pulses:
(ANALOG)
SYNC BIN OCT
+---------+ +------+
| | | |
--+ +------+ +---
Frame:
SYNC , BIN1, OCT1, BIN2, OCT2 ... BIN24, OCT24, BIN25, next frame SYNC ..
pulse length:
Binary values: Analog octal values:
288 uS Binary 0 318 uS 000
438 uS Binary 1 398 uS 001
478 uS 010
558 uS 011
638 uS 100
1306 uS SYNC 718 uS 101
798 uS 110
878 uS 111
24 bin+oct values + 1 bin value = 24*4+1 bits = 97 bits
(Warning, pulses on ACK ar inverted by transistor, irq is rised up on sync
to bin change or octal value to bin change).
Binary data representations:
One binary and octal value can be grouped to nibble. 24 nibbles + one binary
values can be sampled between sync pulses.
Values for first four channels (analog joystick values) can be found in
first 10 nibbles. Analog value is represented by one sign bit and 9 bit
absolute binary value. (10 bits per channel). Next nibble is checksum for
first ten nibbles.
Next nibbles 12 .. 21 represents four channels (not all channels can be
directly controlled from TX). Binary representations ar the same as in first
four channels. In nibbles 22 and 23 is a special magic number. Nibble 24 is
checksum for nibbles 12..23.
After last octal value for nibble 24 and next sync pulse one additional
binary value can be sampled. This bit and magic number is not used in
software driver. Some details about this magic numbers can be found in
Walkera_Wk-0701_PCM.pdf.
Checksum calculation:
Summary of octal values in nibbles must be same as octal value in checksum
nibble (only first 3 bits are used). Binary value for checksum nibble is
calculated by sum of binary values in checked nibbles + sum of octal values
in checked nibbles divided by 8. Only bit 0 of this sum is used.
#ifndef __ASM_ARCH_PXA930_ROTARY_H
#define __ASM_ARCH_PXA930_ROTARY_H
/* NOTE:
*
* rotary can be either interpreted as a ralative input event (e.g.
* REL_WHEEL or REL_HWHEEL) or a specific key event (e.g. UP/DOWN
* or LEFT/RIGHT), depending on if up_key & down_key are assigned
* or rel_code is assigned a non-zero value. When all are non-zero,
* up_key and down_key will be preferred.
*/
struct pxa930_rotary_platform_data {
int up_key;
int down_key;
int rel_code;
};
void __init pxa930_set_rotarykey_info(struct pxa930_rotary_platform_data *info);
#endif /* __ASM_ARCH_PXA930_ROTARY_H */
#ifndef __ASM_ARCH_PXA930_TRKBALL_H
#define __ASM_ARCH_PXA930_TRKBALL_H
struct pxa930_trkball_platform_data {
int x_filter;
int y_filter;
};
#endif /* __ASM_ARCH_PXA930_TRKBALL_H */
......@@ -5,7 +5,7 @@
# Each configuration option enables a list of files.
obj-$(CONFIG_INPUT) += input-core.o
input-core-objs := input.o ff-core.o
input-core-objs := input.o input-compat.o ff-core.o
obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o
obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o
......
......@@ -39,7 +39,7 @@ MODULE_LICENSE("GPL");
static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
{
printk(KERN_DEBUG "evbug.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n",
handle->dev->dev.bus_id, type, code, value);
dev_name(&handle->dev->dev), type, code, value);
}
static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
......@@ -65,7 +65,7 @@ static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
goto err_unregister_handle;
printk(KERN_DEBUG "evbug.c: Connected device: %s (%s at %s)\n",
dev->dev.bus_id,
dev_name(&dev->dev),
dev->name ?: "unknown",
dev->phys ?: "unknown");
......@@ -81,7 +81,7 @@ static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
static void evbug_disconnect(struct input_handle *handle)
{
printk(KERN_DEBUG "evbug.c: Disconnected device: %s\n",
handle->dev->dev.bus_id);
dev_name(&handle->dev->dev));
input_close_device(handle);
input_unregister_handle(handle);
......
......@@ -19,7 +19,7 @@
#include <linux/input.h>
#include <linux/major.h>
#include <linux/device.h>
#include <linux/compat.h>
#include "input-compat.h"
struct evdev {
int exist;
......@@ -290,187 +290,6 @@ static int evdev_open(struct inode *inode, struct file *file)
return error;
}
#ifdef CONFIG_COMPAT
struct input_event_compat {
struct compat_timeval time;
__u16 type;
__u16 code;
__s32 value;
};
struct ff_periodic_effect_compat {
__u16 waveform;
__u16 period;
__s16 magnitude;
__s16 offset;
__u16 phase;
struct ff_envelope envelope;
__u32 custom_len;
compat_uptr_t custom_data;
};
struct ff_effect_compat {
__u16 type;
__s16 id;
__u16 direction;
struct ff_trigger trigger;
struct ff_replay replay;
union {
struct ff_constant_effect constant;
struct ff_ramp_effect ramp;
struct ff_periodic_effect_compat periodic;
struct ff_condition_effect condition[2]; /* One for each axis */
struct ff_rumble_effect rumble;
} u;
};
/* Note to the author of this code: did it ever occur to
you why the ifdefs are needed? Think about it again. -AK */
#ifdef CONFIG_X86_64
# define COMPAT_TEST is_compat_task()
#elif defined(CONFIG_IA64)
# define COMPAT_TEST IS_IA32_PROCESS(task_pt_regs(current))
#elif defined(CONFIG_S390)
# define COMPAT_TEST test_thread_flag(TIF_31BIT)
#elif defined(CONFIG_MIPS)
# define COMPAT_TEST test_thread_flag(TIF_32BIT_ADDR)
#else
# define COMPAT_TEST test_thread_flag(TIF_32BIT)
#endif
static inline size_t evdev_event_size(void)
{
return COMPAT_TEST ?
sizeof(struct input_event_compat) : sizeof(struct input_event);
}
static int evdev_event_from_user(const char __user *buffer,
struct input_event *event)
{
if (COMPAT_TEST) {
struct input_event_compat compat_event;
if (copy_from_user(&compat_event, buffer,
sizeof(struct input_event_compat)))
return -EFAULT;
event->time.tv_sec = compat_event.time.tv_sec;
event->time.tv_usec = compat_event.time.tv_usec;
event->type = compat_event.type;
event->code = compat_event.code;
event->value = compat_event.value;
} else {
if (copy_from_user(event, buffer, sizeof(struct input_event)))
return -EFAULT;
}
return 0;
}
static int evdev_event_to_user(char __user *buffer,
const struct input_event *event)
{
if (COMPAT_TEST) {
struct input_event_compat compat_event;
compat_event.time.tv_sec = event->time.tv_sec;
compat_event.time.tv_usec = event->time.tv_usec;
compat_event.type = event->type;
compat_event.code = event->code;
compat_event.value = event->value;
if (copy_to_user(buffer, &compat_event,
sizeof(struct input_event_compat)))
return -EFAULT;
} else {
if (copy_to_user(buffer, event, sizeof(struct input_event)))
return -EFAULT;
}
return 0;
}
static int evdev_ff_effect_from_user(const char __user *buffer, size_t size,
struct ff_effect *effect)
{
if (COMPAT_TEST) {
struct ff_effect_compat *compat_effect;
if (size != sizeof(struct ff_effect_compat))
return -EINVAL;
/*
* It so happens that the pointer which needs to be changed
* is the last field in the structure, so we can copy the
* whole thing and replace just the pointer.
*/
compat_effect = (struct ff_effect_compat *)effect;
if (copy_from_user(compat_effect, buffer,
sizeof(struct ff_effect_compat)))
return -EFAULT;
if (compat_effect->type == FF_PERIODIC &&
compat_effect->u.periodic.waveform == FF_CUSTOM)
effect->u.periodic.custom_data =
compat_ptr(compat_effect->u.periodic.custom_data);
} else {
if (size != sizeof(struct ff_effect))
return -EINVAL;
if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
return -EFAULT;
}
return 0;
}
#else
static inline size_t evdev_event_size(void)
{
return sizeof(struct input_event);
}
static int evdev_event_from_user(const char __user *buffer,
struct input_event *event)
{
if (copy_from_user(event, buffer, sizeof(struct input_event)))
return -EFAULT;
return 0;
}
static int evdev_event_to_user(char __user *buffer,
const struct input_event *event)
{
if (copy_to_user(buffer, event, sizeof(struct input_event)))
return -EFAULT;
return 0;
}
static int evdev_ff_effect_from_user(const char __user *buffer, size_t size,
struct ff_effect *effect)
{
if (size != sizeof(struct ff_effect))
return -EINVAL;
if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
return -EFAULT;
return 0;
}
#endif /* CONFIG_COMPAT */
static ssize_t evdev_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{
......@@ -490,14 +309,14 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer,
while (retval < count) {
if (evdev_event_from_user(buffer + retval, &event)) {
if (input_event_from_user(buffer + retval, &event)) {
retval = -EFAULT;
goto out;
}
input_inject_event(&evdev->handle,
event.type, event.code, event.value);
retval += evdev_event_size();
retval += input_event_size();
}
out:
......@@ -531,7 +350,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
struct input_event event;
int retval;
if (count < evdev_event_size())
if (count < input_event_size())
return -EINVAL;
if (client->head == client->tail && evdev->exist &&
......@@ -546,13 +365,13 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
if (!evdev->exist)
return -ENODEV;
while (retval + evdev_event_size() <= count &&
while (retval + input_event_size() <= count &&
evdev_fetch_next_event(client, &event)) {
if (evdev_event_to_user(buffer + retval, &event))
if (input_event_to_user(buffer + retval, &event))
return -EFAULT;
retval += evdev_event_size();
retval += input_event_size();
}
return retval;
......@@ -823,7 +642,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
if (_IOC_NR(cmd) == _IOC_NR(EVIOCSFF)) {
if (evdev_ff_effect_from_user(p, _IOC_SIZE(cmd), &effect))
if (input_ff_effect_from_user(p, _IOC_SIZE(cmd), &effect))
return -EFAULT;
error = input_ff_upload(dev, &effect, file);
......@@ -1000,7 +819,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
evdev->handle.handler = handler;
evdev->handle.private = evdev;
strlcpy(evdev->dev.bus_id, evdev->name, sizeof(evdev->dev.bus_id));
dev_set_name(&evdev->dev, evdev->name);
evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
evdev->dev.class = &input_class;
evdev->dev.parent = &dev->dev;
......
......@@ -530,8 +530,7 @@ static void gameport_init_port(struct gameport *gameport)
mutex_init(&gameport->drv_mutex);
device_initialize(&gameport->dev);
snprintf(gameport->dev.bus_id, sizeof(gameport->dev.bus_id),
"gameport%lu", (unsigned long)atomic_inc_return(&gameport_no) - 1);
dev_set_name(&gameport->dev, "gameport%lu", (unsigned long)atomic_inc_return(&gameport_no) - 1);
gameport->dev.bus = &gameport_bus;
gameport->dev.release = gameport_release_port;
if (gameport->parent)
......
......@@ -226,7 +226,7 @@ static int ns558_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
ns558->gameport = port;
gameport_set_name(port, "NS558 PnP Gameport");
gameport_set_phys(port, "pnp%s/gameport0", dev->dev.bus_id);
gameport_set_phys(port, "pnp%s/gameport0", dev_name(&dev->dev));
port->dev.parent = &dev->dev;
port->io = ioport;
......
/*
* 32bit compatibility wrappers for the input subsystem.
*
* Very heavily based on evdev.c - Copyright (c) 1999-2002 Vojtech Pavlik
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#include <asm/uaccess.h>
#include "input-compat.h"
#ifdef CONFIG_COMPAT
int input_event_from_user(const char __user *buffer,
struct input_event *event)
{
if (INPUT_COMPAT_TEST) {
struct input_event_compat compat_event;
if (copy_from_user(&compat_event, buffer,
sizeof(struct input_event_compat)))
return -EFAULT;
event->time.tv_sec = compat_event.time.tv_sec;
event->time.tv_usec = compat_event.time.tv_usec;
event->type = compat_event.type;
event->code = compat_event.code;
event->value = compat_event.value;
} else {
if (copy_from_user(event, buffer, sizeof(struct input_event)))
return -EFAULT;
}
return 0;
}
int input_event_to_user(char __user *buffer,
const struct input_event *event)
{
if (INPUT_COMPAT_TEST) {
struct input_event_compat compat_event;
compat_event.time.tv_sec = event->time.tv_sec;
compat_event.time.tv_usec = event->time.tv_usec;
compat_event.type = event->type;
compat_event.code = event->code;
compat_event.value = event->value;
if (copy_to_user(buffer, &compat_event,
sizeof(struct input_event_compat)))
return -EFAULT;
} else {
if (copy_to_user(buffer, event, sizeof(struct input_event)))
return -EFAULT;
}
return 0;
}
int input_ff_effect_from_user(const char __user *buffer, size_t size,
struct ff_effect *effect)
{
if (INPUT_COMPAT_TEST) {
struct ff_effect_compat *compat_effect;
if (size != sizeof(struct ff_effect_compat))
return -EINVAL;
/*
* It so happens that the pointer which needs to be changed
* is the last field in the structure, so we can retrieve the
* whole thing and replace just the pointer.
*/
compat_effect = (struct ff_effect_compat *)effect;
if (copy_from_user(compat_effect, buffer,
sizeof(struct ff_effect_compat)))
return -EFAULT;
if (compat_effect->type == FF_PERIODIC &&
compat_effect->u.periodic.waveform == FF_CUSTOM)
effect->u.periodic.custom_data =
compat_ptr(compat_effect->u.periodic.custom_data);
} else {
if (size != sizeof(struct ff_effect))
return -EINVAL;
if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
return -EFAULT;
}
return 0;
}
#else
int input_event_from_user(const char __user *buffer,
struct input_event *event)
{
if (copy_from_user(event, buffer, sizeof(struct input_event)))
return -EFAULT;
return 0;
}
int input_event_to_user(char __user *buffer,
const struct input_event *event)
{
if (copy_to_user(buffer, event, sizeof(struct input_event)))
return -EFAULT;
return 0;
}
int input_ff_effect_from_user(const char __user *buffer, size_t size,
struct ff_effect *effect)
{
if (size != sizeof(struct ff_effect))
return -EINVAL;
if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
return -EFAULT;
return 0;
}
#endif /* CONFIG_COMPAT */
EXPORT_SYMBOL_GPL(input_event_from_user);
EXPORT_SYMBOL_GPL(input_event_to_user);
EXPORT_SYMBOL_GPL(input_ff_effect_from_user);
#ifndef _INPUT_COMPAT_H
#define _INPUT_COMPAT_H
/*
* 32bit compatibility wrappers for the input subsystem.
*
* Very heavily based on evdev.c - Copyright (c) 1999-2002 Vojtech Pavlik
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#include <linux/compiler.h>
#include <linux/compat.h>
#include <linux/input.h>
#ifdef CONFIG_COMPAT
/* Note to the author of this code: did it ever occur to
you why the ifdefs are needed? Think about it again. -AK */
#ifdef CONFIG_X86_64
# define INPUT_COMPAT_TEST is_compat_task()
#elif defined(CONFIG_IA64)
# define INPUT_COMPAT_TEST IS_IA32_PROCESS(task_pt_regs(current))
#elif defined(CONFIG_S390)
# define INPUT_COMPAT_TEST test_thread_flag(TIF_31BIT)