You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
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: (40 commits) Input: wacom - add support for Cintiq 20WSX Input: ucb1400_ts - IRQ probe fix Input: at32psif - update MODULE_AUTHOR with new email Input: mac_hid - add lockdep annotation to emumousebtn Input: i8042 - fix incorrect usage of strncpy and strncat Input: bf54x-keys - add infrastructure for keypad wakeups Input: add MODULE_ALIAS() to hotpluggable platform modules Input: drivers/char/keyboard.c - use time_after Input: fix ordering in joystick Makefile Input: wm97xx-core - support use as a wakeup source Input: wm97xx-core - use IRQF_SAMPLE_RANDOM Input: wm97xx-core - only schedule interrupt handler if not already scheduled Input: add Zhen Hua driver Input: aiptek - add support for Genius G-PEN 560 tablet Input: wacom - implement suspend and autosuspend Input: xpad - set proper buffer length for outgoing requests Input: omap-keypad - fix build warning Input: gpio_keys - irq handling cleanup Input: add PS/2 serio driver for AVR32 devices Input: put ledstate in the keyboard notifier ...
This commit is contained in:
+10
@@ -4356,6 +4356,16 @@ L: linux-wireless@vger.kernel.org
|
||||
W: http://oops.ghostprotocols.net:81/blog
|
||||
S: Maintained
|
||||
|
||||
WM97XX TOUCHSCREEN DRIVERS
|
||||
P: Mark Brown
|
||||
M: broonie@opensource.wolfsonmicro.com
|
||||
P: Liam Girdwood
|
||||
M: liam.girdwood@wolfsonmicro.com
|
||||
L: linux-input@vger.kernel.org
|
||||
T: git git://opensource.wolfsonmicro.com/linux-2.6-touch
|
||||
W: http://opensource.wolfsonmicro.com/node/7
|
||||
S: Supported
|
||||
|
||||
X.25 NETWORK LAYER
|
||||
P: Henner Eisen
|
||||
M: eis@baty.hanse.de
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <linux/input.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/jiffies.h>
|
||||
|
||||
extern void ctrl_alt_del(void);
|
||||
|
||||
@@ -928,7 +929,8 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
|
||||
if (up_flag) {
|
||||
if (brl_timeout) {
|
||||
if (!committing ||
|
||||
jiffies - releasestart > (brl_timeout * HZ) / 1000) {
|
||||
time_after(jiffies,
|
||||
releasestart + msecs_to_jiffies(brl_timeout))) {
|
||||
committing = pressed;
|
||||
releasestart = jiffies;
|
||||
}
|
||||
@@ -1238,6 +1240,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
|
||||
}
|
||||
|
||||
param.shift = shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
|
||||
param.ledstate = kbd->ledflagstate;
|
||||
key_map = key_maps[shift_final];
|
||||
|
||||
if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYCODE, ¶m) == NOTIFY_STOP || !key_map) {
|
||||
@@ -1286,6 +1289,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
|
||||
|
||||
(*k_handler[type])(vc, keysym & 0xff, !down);
|
||||
|
||||
param.ledstate = kbd->ledflagstate;
|
||||
atomic_notifier_call_chain(&keyboard_notifier_list, KBD_POST_KEYSYM, ¶m);
|
||||
|
||||
if (type != KT_SLOCK)
|
||||
|
||||
@@ -405,6 +405,9 @@
|
||||
#define USB_VENDOR_ID_YEALINK 0x6993
|
||||
#define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001
|
||||
|
||||
#define USB_VENDOR_ID_KYE 0x0458
|
||||
#define USB_DEVICE_ID_KYE_GPEN_560 0x5003
|
||||
|
||||
/*
|
||||
* Alphabetically sorted blacklist by quirk type.
|
||||
*/
|
||||
@@ -698,6 +701,7 @@ static const struct hid_blacklist {
|
||||
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_63, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_64, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR, USB_DEVICE_ID_N_S_HARMONY, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560, HID_QUIRK_IGNORE },
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@@ -73,7 +73,7 @@ static void input_polled_device_work(struct work_struct *work)
|
||||
|
||||
static int input_open_polled_device(struct input_dev *input)
|
||||
{
|
||||
struct input_polled_dev *dev = input->private;
|
||||
struct input_polled_dev *dev = input_get_drvdata(input);
|
||||
int error;
|
||||
|
||||
error = input_polldev_start_workqueue();
|
||||
@@ -91,7 +91,7 @@ static int input_open_polled_device(struct input_dev *input)
|
||||
|
||||
static void input_close_polled_device(struct input_dev *input)
|
||||
{
|
||||
struct input_polled_dev *dev = input->private;
|
||||
struct input_polled_dev *dev = input_get_drvdata(input);
|
||||
|
||||
cancel_delayed_work_sync(&dev->work);
|
||||
input_polldev_stop_workqueue();
|
||||
@@ -151,10 +151,10 @@ int input_register_polled_device(struct input_polled_dev *dev)
|
||||
{
|
||||
struct input_dev *input = dev->input;
|
||||
|
||||
input_set_drvdata(input, dev);
|
||||
INIT_DELAYED_WORK(&dev->work, input_polled_device_work);
|
||||
if (!dev->poll_interval)
|
||||
dev->poll_interval = 500;
|
||||
input->private = dev;
|
||||
input->open = input_open_polled_device;
|
||||
input->close = input_close_polled_device;
|
||||
|
||||
|
||||
@@ -193,6 +193,18 @@ config JOYSTICK_TWIDJOY
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called twidjoy.
|
||||
|
||||
config JOYSTICK_ZHENHUA
|
||||
tristate "5-byte Zhenhua RC transmitter"
|
||||
select SERIO
|
||||
help
|
||||
Say Y here if you have a Zhen Hua PPM-4CH transmitter which is
|
||||
supplied with a ready to fly micro electric indoor helicopters
|
||||
such as EasyCopter, Lama, MiniCopter, DragonFly or Jabo and want
|
||||
to use it via serial cable as a joystick.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called zhenhua.
|
||||
|
||||
config JOYSTICK_DB9
|
||||
tristate "Multisystem, Sega Genesis, Saturn joysticks and gamepads"
|
||||
depends on PARPORT
|
||||
|
||||
@@ -15,6 +15,7 @@ obj-$(CONFIG_JOYSTICK_GF2K) += gf2k.o
|
||||
obj-$(CONFIG_JOYSTICK_GRIP) += grip.o
|
||||
obj-$(CONFIG_JOYSTICK_GRIP_MP) += grip_mp.o
|
||||
obj-$(CONFIG_JOYSTICK_GUILLEMOT) += guillemot.o
|
||||
obj-$(CONFIG_JOYSTICK_IFORCE) += iforce/
|
||||
obj-$(CONFIG_JOYSTICK_INTERACT) += interact.o
|
||||
obj-$(CONFIG_JOYSTICK_JOYDUMP) += joydump.o
|
||||
obj-$(CONFIG_JOYSTICK_MAGELLAN) += magellan.o
|
||||
@@ -27,5 +28,5 @@ obj-$(CONFIG_JOYSTICK_TURBOGRAFX) += turbografx.o
|
||||
obj-$(CONFIG_JOYSTICK_TWIDJOY) += twidjoy.o
|
||||
obj-$(CONFIG_JOYSTICK_WARRIOR) += warrior.o
|
||||
obj-$(CONFIG_JOYSTICK_XPAD) += xpad.o
|
||||
obj-$(CONFIG_JOYSTICK_ZHENHUA) += zhenhua.o
|
||||
|
||||
obj-$(CONFIG_JOYSTICK_IFORCE) += iforce/
|
||||
|
||||
+189
-24
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* X-Box gamepad - v0.0.6
|
||||
* X-Box gamepad driver
|
||||
*
|
||||
* Copyright (c) 2002 Marko Friedemann <mfr@bmx-chemnitz.de>
|
||||
* 2004 Oliver Schwartz <Oliver.Schwartz@gmx.de>,
|
||||
@@ -68,6 +68,8 @@
|
||||
* - dance pads will map D-PAD to buttons, not axes
|
||||
* - pass the module paramater 'dpad_to_buttons' to force
|
||||
* the D-PAD to map to buttons if your pad is not detected
|
||||
*
|
||||
* Later changes can be tracked in SCM.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
@@ -77,7 +79,6 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb/input.h>
|
||||
|
||||
#define DRIVER_VERSION "v0.0.6"
|
||||
#define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>"
|
||||
#define DRIVER_DESC "X-Box pad driver"
|
||||
|
||||
@@ -87,10 +88,12 @@
|
||||
but we map them to axes when possible to simplify things */
|
||||
#define MAP_DPAD_TO_BUTTONS 0
|
||||
#define MAP_DPAD_TO_AXES 1
|
||||
#define MAP_DPAD_UNKNOWN -1
|
||||
#define MAP_DPAD_UNKNOWN 2
|
||||
|
||||
#define XTYPE_XBOX 0
|
||||
#define XTYPE_XBOX360 1
|
||||
#define XTYPE_XBOX360W 2
|
||||
#define XTYPE_UNKNOWN 3
|
||||
|
||||
static int dpad_to_buttons;
|
||||
module_param(dpad_to_buttons, bool, S_IRUGO);
|
||||
@@ -107,8 +110,10 @@ static const struct xpad_device {
|
||||
{ 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
|
||||
{ 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
|
||||
{ 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES, XTYPE_XBOX },
|
||||
{ 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
|
||||
{ 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
|
||||
{ 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
|
||||
{ 0x046d, 0xc242, "Logitech Chillstream Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
|
||||
{ 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
|
||||
{ 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES, XTYPE_XBOX },
|
||||
{ 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
|
||||
@@ -135,18 +140,26 @@ static const struct xpad_device {
|
||||
{ 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
|
||||
{ 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
|
||||
{ 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
|
||||
{ 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
|
||||
{ 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
|
||||
{ 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
|
||||
{ 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
|
||||
{ 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_XBOX }
|
||||
{ 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_UNKNOWN }
|
||||
};
|
||||
|
||||
static const signed short xpad_btn[] = {
|
||||
BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, /* "analog" buttons */
|
||||
/* buttons shared with xbox and xbox360 */
|
||||
static const signed short xpad_common_btn[] = {
|
||||
BTN_A, BTN_B, BTN_X, BTN_Y, /* "analog" buttons */
|
||||
BTN_START, BTN_BACK, BTN_THUMBL, BTN_THUMBR, /* start/back/sticks */
|
||||
-1 /* terminating entry */
|
||||
};
|
||||
|
||||
/* original xbox controllers only */
|
||||
static const signed short xpad_btn[] = {
|
||||
BTN_C, BTN_Z, /* "analog" buttons */
|
||||
-1 /* terminating entry */
|
||||
};
|
||||
|
||||
/* only used if MAP_DPAD_TO_BUTTONS */
|
||||
static const signed short xpad_btn_pad[] = {
|
||||
BTN_LEFT, BTN_RIGHT, /* d-pad left, right */
|
||||
@@ -173,12 +186,27 @@ static const signed short xpad_abs_pad[] = {
|
||||
-1 /* terminating entry */
|
||||
};
|
||||
|
||||
/* Xbox 360 has a vendor-specific (sub)class, so we cannot match it with only
|
||||
* USB_INTERFACE_INFO, more to that this device has 4 InterfaceProtocols,
|
||||
* but we need only one of them. */
|
||||
/* Xbox 360 has a vendor-specific class, so we cannot match it with only
|
||||
* USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we
|
||||
* match against vendor id as well. Wired Xbox 360 devices have protocol 1,
|
||||
* wireless controllers have protocol 129. */
|
||||
#define XPAD_XBOX360_VENDOR_PROTOCOL(vend,pr) \
|
||||
.match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \
|
||||
.idVendor = (vend), \
|
||||
.bInterfaceClass = USB_CLASS_VENDOR_SPEC, \
|
||||
.bInterfaceSubClass = 93, \
|
||||
.bInterfaceProtocol = (pr)
|
||||
#define XPAD_XBOX360_VENDOR(vend) \
|
||||
{ XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \
|
||||
{ XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) }
|
||||
|
||||
static struct usb_device_id xpad_table [] = {
|
||||
{ USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */
|
||||
{ USB_DEVICE_INTERFACE_PROTOCOL(0x045e, 0x028e, 1) }, /* X-Box 360 controller */
|
||||
XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */
|
||||
XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */
|
||||
XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */
|
||||
XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */
|
||||
XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -188,10 +216,15 @@ struct usb_xpad {
|
||||
struct input_dev *dev; /* input device interface */
|
||||
struct usb_device *udev; /* usb device */
|
||||
|
||||
int pad_present;
|
||||
|
||||
struct urb *irq_in; /* urb for interrupt in report */
|
||||
unsigned char *idata; /* input data */
|
||||
dma_addr_t idata_dma;
|
||||
|
||||
struct urb *bulk_out;
|
||||
unsigned char *bdata;
|
||||
|
||||
#if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
|
||||
struct urb *irq_out; /* urb for interrupt out report */
|
||||
unsigned char *odata; /* output data */
|
||||
@@ -227,13 +260,13 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
|
||||
input_report_abs(dev, ABS_X,
|
||||
(__s16) le16_to_cpup((__le16 *)(data + 12)));
|
||||
input_report_abs(dev, ABS_Y,
|
||||
(__s16) le16_to_cpup((__le16 *)(data + 14)));
|
||||
~(__s16) le16_to_cpup((__le16 *)(data + 14)));
|
||||
|
||||
/* right stick */
|
||||
input_report_abs(dev, ABS_RX,
|
||||
(__s16) le16_to_cpup((__le16 *)(data + 16)));
|
||||
input_report_abs(dev, ABS_RY,
|
||||
(__s16) le16_to_cpup((__le16 *)(data + 18)));
|
||||
~(__s16) le16_to_cpup((__le16 *)(data + 18)));
|
||||
|
||||
/* triggers left/right */
|
||||
input_report_abs(dev, ABS_Z, data[10]);
|
||||
@@ -321,13 +354,13 @@ static void xpad360_process_packet(struct usb_xpad *xpad,
|
||||
input_report_abs(dev, ABS_X,
|
||||
(__s16) le16_to_cpup((__le16 *)(data + 6)));
|
||||
input_report_abs(dev, ABS_Y,
|
||||
(__s16) le16_to_cpup((__le16 *)(data + 8)));
|
||||
~(__s16) le16_to_cpup((__le16 *)(data + 8)));
|
||||
|
||||
/* right stick */
|
||||
input_report_abs(dev, ABS_RX,
|
||||
(__s16) le16_to_cpup((__le16 *)(data + 10)));
|
||||
input_report_abs(dev, ABS_RY,
|
||||
(__s16) le16_to_cpup((__le16 *)(data + 12)));
|
||||
~(__s16) le16_to_cpup((__le16 *)(data + 12)));
|
||||
|
||||
/* triggers left/right */
|
||||
input_report_abs(dev, ABS_Z, data[4]);
|
||||
@@ -336,6 +369,39 @@ static void xpad360_process_packet(struct usb_xpad *xpad,
|
||||
input_sync(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* xpad360w_process_packet
|
||||
*
|
||||
* Completes a request by converting the data into events for the
|
||||
* input subsystem. It is version for xbox 360 wireless controller.
|
||||
*
|
||||
* Byte.Bit
|
||||
* 00.1 - Status change: The controller or headset has connected/disconnected
|
||||
* Bits 01.7 and 01.6 are valid
|
||||
* 01.7 - Controller present
|
||||
* 01.6 - Headset present
|
||||
* 01.1 - Pad state (Bytes 4+) valid
|
||||
*
|
||||
*/
|
||||
|
||||
static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
|
||||
{
|
||||
/* Presence change */
|
||||
if (data[0] & 0x08) {
|
||||
if (data[1] & 0x80) {
|
||||
xpad->pad_present = 1;
|
||||
usb_submit_urb(xpad->bulk_out, GFP_ATOMIC);
|
||||
} else
|
||||
xpad->pad_present = 0;
|
||||
}
|
||||
|
||||
/* Valid pad data */
|
||||
if (!(data[1] & 0x1))
|
||||
return;
|
||||
|
||||
xpad360_process_packet(xpad, cmd, &data[4]);
|
||||
}
|
||||
|
||||
static void xpad_irq_in(struct urb *urb)
|
||||
{
|
||||
struct usb_xpad *xpad = urb->context;
|
||||
@@ -358,10 +424,16 @@ static void xpad_irq_in(struct urb *urb)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (xpad->xtype == XTYPE_XBOX360)
|
||||
switch (xpad->xtype) {
|
||||
case XTYPE_XBOX360:
|
||||
xpad360_process_packet(xpad, 0, xpad->idata);
|
||||
else
|
||||
break;
|
||||
case XTYPE_XBOX360W:
|
||||
xpad360w_process_packet(xpad, 0, xpad->idata);
|
||||
break;
|
||||
default:
|
||||
xpad_process_packet(xpad, 0, xpad->idata);
|
||||
}
|
||||
|
||||
exit:
|
||||
retval = usb_submit_urb (urb, GFP_ATOMIC);
|
||||
@@ -399,6 +471,23 @@ exit:
|
||||
__FUNCTION__, retval);
|
||||
}
|
||||
|
||||
static void xpad_bulk_out(struct urb *urb)
|
||||
{
|
||||
switch (urb->status) {
|
||||
case 0:
|
||||
/* success */
|
||||
break;
|
||||
case -ECONNRESET:
|
||||
case -ENOENT:
|
||||
case -ESHUTDOWN:
|
||||
/* this urb is terminated, clean up */
|
||||
dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
|
||||
break;
|
||||
default:
|
||||
dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
|
||||
}
|
||||
}
|
||||
|
||||
static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_irq_out;
|
||||
@@ -408,7 +497,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
|
||||
return 0;
|
||||
|
||||
xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN,
|
||||
GFP_ATOMIC, &xpad->odata_dma );
|
||||
GFP_KERNEL, &xpad->odata_dma);
|
||||
if (!xpad->odata)
|
||||
goto fail1;
|
||||
|
||||
@@ -469,6 +558,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data,
|
||||
xpad->odata[5] = 0x00;
|
||||
xpad->odata[6] = 0x00;
|
||||
xpad->odata[7] = 0x00;
|
||||
xpad->irq_out->transfer_buffer_length = 8;
|
||||
usb_submit_urb(xpad->irq_out, GFP_KERNEL);
|
||||
}
|
||||
|
||||
@@ -477,6 +567,9 @@ static int xpad_play_effect(struct input_dev *dev, void *data,
|
||||
|
||||
static int xpad_init_ff(struct usb_xpad *xpad)
|
||||
{
|
||||
if (xpad->xtype != XTYPE_XBOX360)
|
||||
return 0;
|
||||
|
||||
input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
|
||||
|
||||
return input_ff_create_memless(xpad->dev, NULL, xpad_play_effect);
|
||||
@@ -502,6 +595,7 @@ static void xpad_send_led_command(struct usb_xpad *xpad, int command)
|
||||
xpad->odata[0] = 0x01;
|
||||
xpad->odata[1] = 0x03;
|
||||
xpad->odata[2] = command;
|
||||
xpad->irq_out->transfer_buffer_length = 3;
|
||||
usb_submit_urb(xpad->irq_out, GFP_KERNEL);
|
||||
mutex_unlock(&xpad->odata_mutex);
|
||||
}
|
||||
@@ -574,6 +668,10 @@ static int xpad_open(struct input_dev *dev)
|
||||
{
|
||||
struct usb_xpad *xpad = input_get_drvdata(dev);
|
||||
|
||||
/* URB was submitted in probe */
|
||||
if(xpad->xtype == XTYPE_XBOX360W)
|
||||
return 0;
|
||||
|
||||
xpad->irq_in->dev = xpad->udev;
|
||||
if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
|
||||
return -EIO;
|
||||
@@ -585,7 +683,8 @@ static void xpad_close(struct input_dev *dev)
|
||||
{
|
||||
struct usb_xpad *xpad = input_get_drvdata(dev);
|
||||
|
||||
usb_kill_urb(xpad->irq_in);
|
||||
if(xpad->xtype != XTYPE_XBOX360W)
|
||||
usb_kill_urb(xpad->irq_in);
|
||||
xpad_stop_output(xpad);
|
||||
}
|
||||
|
||||
@@ -632,7 +731,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
|
||||
goto fail1;
|
||||
|
||||
xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN,
|
||||
GFP_ATOMIC, &xpad->idata_dma);
|
||||
GFP_KERNEL, &xpad->idata_dma);
|
||||
if (!xpad->idata)
|
||||
goto fail1;
|
||||
|
||||
@@ -644,7 +743,16 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
|
||||
xpad->dpad_mapping = xpad_device[i].dpad_mapping;
|
||||
xpad->xtype = xpad_device[i].xtype;
|
||||
if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN)
|
||||
xpad->dpad_mapping = dpad_to_buttons;
|
||||
xpad->dpad_mapping = !dpad_to_buttons;
|
||||
if (xpad->xtype == XTYPE_UNKNOWN) {
|
||||
if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) {
|
||||
if (intf->cur_altsetting->desc.bInterfaceProtocol == 129)
|
||||
xpad->xtype = XTYPE_XBOX360W;
|
||||
else
|
||||
xpad->xtype = XTYPE_XBOX360;
|
||||
} else
|
||||
xpad->xtype = XTYPE_XBOX;
|
||||
}
|
||||
xpad->dev = input_dev;
|
||||
usb_make_path(udev, xpad->phys, sizeof(xpad->phys));
|
||||
strlcat(xpad->phys, "/input0", sizeof(xpad->phys));
|
||||
@@ -662,11 +770,14 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
|
||||
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
|
||||
|
||||
/* set up buttons */
|
||||
for (i = 0; xpad_btn[i] >= 0; i++)
|
||||
set_bit(xpad_btn[i], input_dev->keybit);
|
||||
if (xpad->xtype == XTYPE_XBOX360)
|
||||
for (i = 0; xpad_common_btn[i] >= 0; i++)
|
||||
set_bit(xpad_common_btn[i], input_dev->keybit);
|
||||
if ((xpad->xtype == XTYPE_XBOX360) || (xpad->xtype == XTYPE_XBOX360W))
|
||||
for (i = 0; xpad360_btn[i] >= 0; i++)
|
||||
set_bit(xpad360_btn[i], input_dev->keybit);
|
||||
else
|
||||
for (i = 0; xpad_btn[i] >= 0; i++)
|
||||
set_bit(xpad_btn[i], input_dev->keybit);
|
||||
if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS)
|
||||
for (i = 0; xpad_btn_pad[i] >= 0; i++)
|
||||
set_bit(xpad_btn_pad[i], input_dev->keybit);
|
||||
@@ -703,8 +814,57 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
|
||||
goto fail4;
|
||||
|
||||
usb_set_intfdata(intf, xpad);
|
||||
|
||||
/*
|
||||
* Submit the int URB immediatly rather than waiting for open
|
||||
* because we get status messages from the device whether
|
||||
* or not any controllers are attached. In fact, it's
|
||||
* exactly the message that a controller has arrived that
|
||||
* we're waiting for.
|
||||
*/
|
||||
if (xpad->xtype == XTYPE_XBOX360W) {
|
||||
xpad->irq_in->dev = xpad->udev;
|
||||
error = usb_submit_urb(xpad->irq_in, GFP_KERNEL);
|
||||
if (error)
|
||||
goto fail4;
|
||||
|
||||
/*
|
||||
* Setup the message to set the LEDs on the
|
||||
* controller when it shows up
|
||||
*/
|
||||
xpad->bulk_out = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if(!xpad->bulk_out)
|
||||
goto fail5;
|
||||
|
||||
xpad->bdata = kzalloc(XPAD_PKT_LEN, GFP_KERNEL);
|
||||
if(!xpad->bdata)
|
||||
goto fail6;
|
||||
|
||||
xpad->bdata[2] = 0x08;
|
||||
switch (intf->cur_altsetting->desc.bInterfaceNumber) {
|
||||
case 0:
|
||||
xpad->bdata[3] = 0x42;
|
||||
break;
|
||||
case 2:
|
||||
xpad->bdata[3] = 0x43;
|
||||
break;
|
||||
case 4:
|
||||
xpad->bdata[3] = 0x44;
|
||||
break;
|
||||
case 6:
|
||||
xpad->bdata[3] = 0x45;
|
||||
}
|
||||
|
||||
ep_irq_in = &intf->cur_altsetting->endpoint[1].desc;
|
||||
usb_fill_bulk_urb(xpad->bulk_out, udev,
|
||||
usb_sndbulkpipe(udev, ep_irq_in->bEndpointAddress),
|
||||
xpad->bdata, XPAD_PKT_LEN, xpad_bulk_out, xpad);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail6: usb_free_urb(xpad->bulk_out);
|
||||
fail5: usb_kill_urb(xpad->irq_in);
|
||||
fail4: usb_free_urb(xpad->irq_in);
|
||||
fail3: xpad_deinit_output(xpad);
|
||||
fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
|
||||
@@ -723,6 +883,11 @@ static void xpad_disconnect(struct usb_interface *intf)
|
||||
xpad_led_disconnect(xpad);
|
||||
input_unregister_device(xpad->dev);
|
||||
xpad_deinit_output(xpad);
|
||||
if (xpad->xtype == XTYPE_XBOX360W) {
|
||||
usb_kill_urb(xpad->bulk_out);
|
||||
usb_free_urb(xpad->bulk_out);
|
||||
usb_kill_urb(xpad->irq_in);
|
||||
}
|
||||
usb_free_urb(xpad->irq_in);
|
||||
usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
|
||||
xpad->idata, xpad->idata_dma);
|
||||
@@ -741,7 +906,7 @@ static int __init usb_xpad_init(void)
|
||||
{
|
||||
int result = usb_register(&xpad_driver);
|
||||
if (result == 0)
|
||||
info(DRIVER_DESC ":" DRIVER_VERSION);
|
||||
info(DRIVER_DESC);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* derived from "twidjoy.c"
|
||||
*
|
||||
* Copyright (c) 2008 Martin Kebert
|
||||
* Copyright (c) 2001 Arndt Schoenewald
|
||||
* Copyright (c) 2000-2001 Vojtech Pavlik
|
||||
* Copyright (c) 2000 Mark Fletcher
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Driver to use 4CH RC transmitter using Zhen Hua 5-byte protocol (Walkera Lama,
|
||||
* EasyCopter etc.) as a joystick under Linux.
|
||||
*
|
||||
* RC transmitters using Zhen Hua 5-byte protocol are cheap four channels
|
||||
* transmitters for control a RC planes or RC helicopters with possibility to
|
||||
* connect on a serial port.
|
||||
* Data coming from transmitter is in this order:
|
||||
* 1. byte = synchronisation byte
|
||||
* 2. byte = X axis
|
||||
* 3. byte = Y axis
|
||||
* 4. byte = RZ axis
|
||||
* 5. byte = Z axis
|
||||
* (and this is repeated)
|
||||
*
|
||||
* For questions or feedback regarding this driver module please contact:
|
||||
* Martin Kebert <gkmarty@gmail.com> - but I am not a C-programmer nor kernel
|
||||
* coder :-(
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/serio.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#define DRIVER_DESC "RC transmitter with 5-byte Zhen Hua protocol joystick driver"
|
||||
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/*
|
||||
* Constants.
|
||||
*/
|
||||
|
||||
#define ZHENHUA_MAX_LENGTH 5
|
||||
|
||||
/*
|
||||
* Zhen Hua data.
|
||||
*/
|
||||
|
||||
struct zhenhua {
|
||||
struct input_dev *dev;
|
||||
int idx;
|
||||
unsigned char data[ZHENHUA_MAX_LENGTH];
|
||||
char phys[32];
|
||||
};
|
||||
|
||||
|
||||
/* bits in all incoming bytes needs to be "reversed" */
|
||||
static int zhenhua_bitreverse(int x)
|
||||
{
|
||||
x = ((x & 0xaa) >> 1) | ((x & 0x55) << 1);
|
||||
x = ((x & 0xcc) >> 2) | ((x & 0x33) << 2);
|
||||
x = ((x & 0xf0) >> 4) | ((x & 0x0f) << 4);
|
||||
return x;
|
||||
}
|
||||
|
||||
/*
|
||||
* zhenhua_process_packet() decodes packets the driver receives from the
|
||||
* RC transmitter. It updates the data accordingly.
|
||||
*/
|
||||
|
||||
static void zhenhua_process_packet(struct zhenhua *zhenhua)
|
||||
{
|
||||
struct input_dev *dev = zhenhua->dev;
|
||||
unsigned char *data = zhenhua->data;
|
||||
|
||||
input_report_abs(dev, ABS_Y, data[1]);
|
||||
input_report_abs(dev, ABS_X, data[2]);
|
||||
input_report_abs(dev, ABS_RZ, data[3]);
|
||||
input_report_abs(dev, ABS_Z, data[4]);
|
||||
|
||||
input_sync(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* zhenhua_interrupt() is called by the low level driver when characters
|
||||
* are ready for us. We then buffer them for further processing, or call the
|
||||
* packet processing routine.
|
||||
*/
|
||||
|
||||
static irqreturn_t zhenhua_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
|
||||
{
|
||||
struct zhenhua *zhenhua = serio_get_drvdata(serio);
|
||||
|
||||
/* All Zhen Hua packets are 5 bytes. The fact that the first byte
|
||||
* is allways 0xf7 and all others are in range 0x32 - 0xc8 (50-200)
|
||||
* can be used to check and regain sync. */
|
||||
|
||||
if (data == 0xef)
|
||||
zhenhua->idx = 0; /* this byte starts a new packet */
|
||||
else if (zhenhua->idx == 0)
|
||||
return IRQ_HANDLED; /* wrong MSB -- ignore this byte */
|
||||
|
||||
if (zhenhua->idx < ZHENHUA_MAX_LENGTH)
|
||||
zhenhua->data[zhenhua->idx++] = zhenhua_bitreverse(data);
|
||||
|
||||
if (zhenhua->idx == ZHENHUA_MAX_LENGTH) {
|
||||
zhenhua_process_packet(zhenhua);
|
||||
zhenhua->idx = 0;
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* zhenhua_disconnect() is the opposite of zhenhua_connect()
|
||||
*/
|
||||
|
||||
static void zhenhua_disconnect(struct serio *serio)
|
||||
{
|
||||
struct zhenhua *zhenhua = serio_get_drvdata(serio);
|
||||
|
||||
serio_close(serio);
|
||||
serio_set_drvdata(serio, NULL);
|
||||
input_unregister_device(zhenhua->dev);
|
||||
kfree(zhenhua);
|
||||
}
|
||||
|
||||
/*
|
||||
* zhenhua_connect() is the routine that is called when someone adds a
|
||||
* new serio device. It looks for the Twiddler, and if found, registers
|
||||
* it as an input device.
|
||||
*/
|
||||
|
||||
static int zhenhua_connect(struct serio *serio, struct serio_driver *drv)
|
||||
{
|
||||
struct zhenhua *zhenhua;
|
||||
struct input_dev *input_dev;
|
||||
int err = -ENOMEM;
|
||||
|
||||
zhenhua = kzalloc(sizeof(struct zhenhua), GFP_KERNEL);
|
||||
input_dev = input_allocate_device();
|
||||
if (!zhenhua || !input_dev)
|
||||
goto fail1;
|
||||
|
||||
zhenhua->dev = input_dev;
|
||||
snprintf(zhenhua->phys, sizeof(zhenhua->phys), "%s/input0", serio->phys);
|
||||
|
||||
input_dev->name = "Zhen Hua 5-byte device";
|
||||
input_dev->phys = zhenhua->phys;
|
||||
input_dev->id.bustype = BUS_RS232;
|
||||
input_dev->id.vendor = SERIO_ZHENHUA;
|
||||
input_dev->id.product = 0x0001;
|
||||
input_dev->id.version = 0x0100;
|
||||
input_dev->dev.parent = &serio->dev;
|
||||
|
||||
input_dev->evbit[0] = BIT(EV_ABS);
|
||||
input_set_abs_params(input_dev, ABS_X, 50, 200, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_Y, 50, 200, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_Z, 50, 200, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_RZ, 50, 200, 0, 0);
|
||||
|
||||
serio_set_drvdata(serio, zhenhua);
|
||||
|
||||
err = serio_open(serio, drv);
|
||||
if (err)
|
||||
goto fail2;
|
||||
|
||||
err = input_register_device(zhenhua->dev);
|
||||
if (err)
|
||||
goto fail3;
|
||||
|
||||
return 0;
|
||||
|
||||
fail3: serio_close(serio);
|
||||
fail2: serio_set_drvdata(serio, NULL);
|
||||
fail1: input_free_device(input_dev);
|
||||
kfree(zhenhua);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* The serio driver structure.
|
||||
*/
|
||||
|
||||
static struct serio_device_id zhenhua_serio_ids[] = {
|
||||
{
|
||||
.type = SERIO_RS232,
|
||||
.proto = SERIO_ZHENHUA,
|
||||
.id = SERIO_ANY,
|
||||
.extra = SERIO_ANY,
|
||||
},
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(serio, zhenhua_serio_ids);
|
||||
|
||||
static struct serio_driver zhenhua_drv = {
|
||||
.driver = {
|
||||
.name = "zhenhua",
|
||||
},
|
||||
.description = DRIVER_DESC,
|
||||
.id_table = zhenhua_serio_ids,
|
||||
.interrupt = zhenhua_interrupt,
|
||||
.connect = zhenhua_connect,
|
||||
.disconnect = zhenhua_disconnect,
|
||||
};
|
||||
|
||||
/*
|
||||
* The functions for inserting/removing us as a module.
|
||||
*/
|
||||
|
||||
static int __init zhenhua_init(void)
|
||||
{
|
||||
return serio_register_driver(&zhenhua_drv);
|
||||
}
|
||||
|
||||
static void __exit zhenhua_exit(void)
|
||||
{
|
||||
serio_unregister_driver(&zhenhua_drv);
|
||||
}
|
||||
|
||||
module_init(zhenhua_init);
|
||||
module_exit(zhenhua_exit);
|
||||
@@ -156,11 +156,15 @@ static int __devexit aaedkbd_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* work with hotplug and coldplug */
|
||||
MODULE_ALIAS("platform:aaed2000-keyboard");
|
||||
|
||||
static struct platform_driver aaedkbd_driver = {
|
||||
.probe = aaedkbd_probe,
|
||||
.remove = __devexit_p(aaedkbd_remove),
|
||||
.driver = {
|
||||
.name = "aaed2000-keyboard",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -312,6 +312,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev)
|
||||
|
||||
bfin_write_KPAD_CTL(bfin_read_KPAD_CTL() | KPAD_EN);
|
||||
|
||||
device_init_wakeup(&pdev->dev, 1);
|
||||
|
||||
printk(KERN_ERR DRV_NAME
|
||||
": Blackfin BF54x Keypad registered IRQ %d\n", bf54x_kpad->irq);
|
||||
|
||||
@@ -354,12 +356,40 @@ static int __devexit bfin_kpad_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int bfin_kpad_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
|
||||
|
||||
if (device_may_wakeup(&pdev->dev))
|
||||
enable_irq_wake(bf54x_kpad->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bfin_kpad_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
|
||||
|
||||
if (device_may_wakeup(&pdev->dev))
|
||||
disable_irq_wake(bf54x_kpad->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
# define bfin_kpad_suspend NULL
|
||||
# define bfin_kpad_resume NULL
|
||||
#endif
|
||||
|
||||
struct platform_driver bfin_kpad_device_driver = {
|
||||
.probe = bfin_kpad_probe,
|
||||
.remove = __devexit_p(bfin_kpad_remove),
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
}
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = bfin_kpad_probe,
|
||||
.remove = __devexit_p(bfin_kpad_remove),
|
||||
.suspend = bfin_kpad_suspend,
|
||||
.resume = bfin_kpad_resume,
|
||||
};
|
||||
|
||||
static int __init bfin_kpad_init(void)
|
||||
@@ -378,3 +408,4 @@ module_exit(bfin_kpad_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
|
||||
MODULE_DESCRIPTION("Keypad driver for BF54x Processors");
|
||||
MODULE_ALIAS("platform:bf54x-keys");
|
||||
|
||||
@@ -393,6 +393,7 @@ static struct platform_driver corgikbd_driver = {
|
||||
.resume = corgikbd_resume,
|
||||
.driver = {
|
||||
.name = "corgi-keyboard",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -412,3 +413,4 @@ module_exit(corgikbd_exit);
|
||||
MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
|
||||
MODULE_DESCRIPTION("Corgi Keyboard Driver");
|
||||
MODULE_LICENSE("GPLv2");
|
||||
MODULE_ALIAS("platform:corgi-keyboard");
|
||||
|
||||
@@ -43,10 +43,11 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
|
||||
|
||||
input_event(input, type, button->code, !!state);
|
||||
input_sync(input);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static int __devinit gpio_keys_probe(struct platform_device *pdev)
|
||||
@@ -213,6 +214,7 @@ struct platform_driver gpio_keys_device_driver = {
|
||||
.resume = gpio_keys_resume,
|
||||
.driver = {
|
||||
.name = "gpio-keys",
|
||||
.owner = THIS_MODULE,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -232,3 +234,4 @@ module_exit(gpio_keys_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>");
|
||||
MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs");
|
||||
MODULE_ALIAS("platform:gpio-keys");
|
||||
|
||||
@@ -254,6 +254,7 @@ static int __devexit jornada680kbd_remove(struct platform_device *pdev)
|
||||
static struct platform_driver jornada680kbd_driver = {
|
||||
.driver = {
|
||||
.name = "jornada680_kbd",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = jornada680kbd_probe,
|
||||
.remove = __devexit_p(jornada680kbd_remove),
|
||||
@@ -275,3 +276,4 @@ module_exit(jornada680kbd_exit);
|
||||
MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
|
||||
MODULE_DESCRIPTION("HP Jornada 620/660/680/690 Keyboard Driver");
|
||||
MODULE_LICENSE("GPLv2");
|
||||
MODULE_ALIAS("platform:jornada680_kbd");
|
||||
|
||||
@@ -162,9 +162,13 @@ static int __devexit jornada720_kbd_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* work with hotplug and coldplug */
|
||||
MODULE_ALIAS("platform:jornada720_kbd");
|
||||
|
||||
static struct platform_driver jornada720_kbd_driver = {
|
||||
.driver = {
|
||||
.name = "jornada720_kbd",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = jornada720_kbd_probe,
|
||||
.remove = __devexit_p(jornada720_kbd_remove),
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) 2005 John Lenz
|
||||
* LoCoMo keyboard driver for Linux-based ARM PDAs:
|
||||
* - SHARP Zaurus Collie (SL-5500)
|
||||
* - SHARP Zaurus Poodle (SL-5600)
|
||||
*
|
||||
* Copyright (c) 2005 John Lenz
|
||||
* Based on from xtkbd.c
|
||||
*/
|
||||
|
||||
/*
|
||||
* LoCoMo keyboard driver for Linux/ARM
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
@@ -47,7 +45,8 @@ MODULE_LICENSE("GPL");
|
||||
#define KEY_CONTACT KEY_F18
|
||||
#define KEY_CENTER KEY_F15
|
||||
|
||||
static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = {
|
||||
static const unsigned char
|
||||
locomokbd_keycode[LOCOMOKBD_NUMKEYS] __devinitconst = {
|
||||
0, KEY_ESC, KEY_ACTIVITY, 0, 0, 0, 0, 0, 0, 0, /* 0 - 9 */
|
||||
0, 0, 0, 0, 0, 0, 0, KEY_MENU, KEY_HOME, KEY_CONTACT, /* 10 - 19 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 29 */
|
||||
@@ -67,22 +66,21 @@ static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = {
|
||||
#define KB_COLS 8
|
||||
#define KB_ROWMASK(r) (1 << (r))
|
||||
#define SCANCODE(c,r) ( ((c)<<4) + (r) + 1 )
|
||||
#define NR_SCANCODES 128
|
||||
|
||||
#define KB_DELAY 8
|
||||
#define SCAN_INTERVAL (HZ/10)
|
||||
#define LOCOMOKBD_PRESSED 1
|
||||
|
||||
struct locomokbd {
|
||||
unsigned char keycode[LOCOMOKBD_NUMKEYS];
|
||||
struct input_dev *input;
|
||||
char phys[32];
|
||||
|
||||
struct locomo_dev *ldev;
|
||||
unsigned long base;
|
||||
spinlock_t lock;
|
||||
|
||||
struct timer_list timer;
|
||||
unsigned long suspend_jiffies;
|
||||
unsigned int count_cancel;
|
||||
};
|
||||
|
||||
/* helper functions for reading the keyboard matrix */
|
||||
@@ -128,7 +126,7 @@ static inline void locomokbd_reset_col(unsigned long membase, int col)
|
||||
/* Scan the hardware keyboard and push any changes up through the input layer */
|
||||
static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
|
||||
{
|
||||
unsigned int row, col, rowd, scancode;
|
||||
unsigned int row, col, rowd;
|
||||
unsigned long flags;
|
||||
unsigned int num_pressed;
|
||||
unsigned long membase = locomokbd->base;
|
||||
@@ -145,13 +143,33 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
|
||||
|
||||
rowd = ~locomo_readl(membase + LOCOMO_KIB);
|
||||
for (row = 0; row < KB_ROWS; row++) {
|
||||
unsigned int scancode, pressed, key;
|
||||
|
||||
scancode = SCANCODE(col, row);
|
||||
if (rowd & KB_ROWMASK(row)) {
|
||||
num_pressed += 1;
|
||||
input_report_key(locomokbd->input, locomokbd->keycode[scancode], 1);
|
||||
} else {
|
||||
input_report_key(locomokbd->input, locomokbd->keycode[scancode], 0);
|
||||
}
|
||||
pressed = rowd & KB_ROWMASK(row);
|
||||
key = locomokbd->keycode[scancode];
|
||||
|
||||
input_report_key(locomokbd->input, key, pressed);
|
||||
if (likely(!pressed))
|
||||
continue;
|
||||
|
||||
num_pressed++;
|
||||
|
||||
/* The "Cancel/ESC" key is labeled "On/Off" on
|
||||
* Collie and Poodle and should suspend the device
|
||||
* if it was pressed for more than a second. */
|
||||
if (unlikely(key == KEY_ESC)) {
|
||||
if (!time_after(jiffies,
|
||||
locomokbd->suspend_jiffies + HZ))
|
||||
continue;
|
||||
if (locomokbd->count_cancel++
|
||||
!= (HZ/SCAN_INTERVAL + 1))
|
||||
continue;
|
||||
input_event(locomokbd->input, EV_PWR,
|
||||
KEY_SUSPEND, 1);
|
||||
locomokbd->suspend_jiffies = jiffies;
|
||||
} else
|
||||
locomokbd->count_cancel = 0;
|
||||
}
|
||||
locomokbd_reset_col(membase, col);
|
||||
}
|
||||
@@ -162,6 +180,8 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
|
||||
/* if any keys are pressed, enable the timer */
|
||||
if (num_pressed)
|
||||
mod_timer(&locomokbd->timer, jiffies + SCAN_INTERVAL);
|
||||
else
|
||||
locomokbd->count_cancel = 0;
|
||||
|
||||
spin_unlock_irqrestore(&locomokbd->lock, flags);
|
||||
}
|
||||
@@ -186,10 +206,11 @@ static irqreturn_t locomokbd_interrupt(int irq, void *dev_id)
|
||||
static void locomokbd_timer_callback(unsigned long data)
|
||||
{
|
||||
struct locomokbd *locomokbd = (struct locomokbd *) data;
|
||||
|
||||
locomokbd_scankeyboard(locomokbd);
|
||||
}
|
||||
|
||||
static int locomokbd_probe(struct locomo_dev *dev)
|
||||
static int __devinit locomokbd_probe(struct locomo_dev *dev)
|
||||
{
|
||||
struct locomokbd *locomokbd;
|
||||
struct input_dev *input_dev;
|
||||
@@ -211,7 +232,6 @@ static int locomokbd_probe(struct locomo_dev *dev)
|
||||
goto err_free_mem;
|
||||
}
|
||||
|
||||
locomokbd->ldev = dev;
|
||||
locomo_set_drvdata(dev, locomokbd);
|
||||
|
||||
locomokbd->base = (unsigned long) dev->mapbase;
|
||||
@@ -222,6 +242,8 @@ static int locomokbd_probe(struct locomo_dev *dev)
|
||||
locomokbd->timer.function = locomokbd_timer_callback;
|
||||
locomokbd->timer.data = (unsigned long) locomokbd;
|
||||
|
||||
locomokbd->suspend_jiffies = jiffies;
|
||||
|
||||
locomokbd->input = input_dev;
|
||||
strcpy(locomokbd->phys, "locomokbd/input0");
|
||||
|
||||
@@ -233,9 +255,10 @@ static int locomokbd_probe(struct locomo_dev *dev)
|
||||
input_dev->id.version = 0x0100;
|
||||
input_dev->dev.parent = &dev->dev;
|
||||
|
||||
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
|
||||
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
|
||||
BIT_MASK(EV_PWR);
|
||||
input_dev->keycode = locomokbd->keycode;
|
||||
input_dev->keycodesize = sizeof(unsigned char);
|
||||
input_dev->keycodesize = sizeof(locomokbd_keycode[0]);
|
||||
input_dev->keycodemax = ARRAY_SIZE(locomokbd_keycode);
|
||||
|
||||
memcpy(locomokbd->keycode, locomokbd_keycode, sizeof(locomokbd->keycode));
|
||||
@@ -268,7 +291,7 @@ static int locomokbd_probe(struct locomo_dev *dev)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int locomokbd_remove(struct locomo_dev *dev)
|
||||
static int __devexit locomokbd_remove(struct locomo_dev *dev)
|
||||
{
|
||||
struct locomokbd *locomokbd = locomo_get_drvdata(dev);
|
||||
|
||||
@@ -292,7 +315,7 @@ static struct locomo_driver keyboard_driver = {
|
||||
},
|
||||
.devid = LOCOMO_DEVID_KEYBOARD,
|
||||
.probe = locomokbd_probe,
|
||||
.remove = locomokbd_remove,
|
||||
.remove = __devexit_p(locomokbd_remove),
|
||||
};
|
||||
|
||||
static int __init locomokbd_init(void)
|
||||
|
||||
@@ -352,6 +352,9 @@ static int __init omap_kp_probe(struct platform_device *pdev)
|
||||
}
|
||||
omap_set_gpio_direction(row_gpios[row_idx], 1);
|
||||
}
|
||||
} else {
|
||||
col_idx = 0;
|
||||
row_idx = 0;
|
||||
}
|
||||
|
||||
setup_timer(&omap_kp->timer, omap_kp_timer, (unsigned long)omap_kp);
|
||||
@@ -415,10 +418,10 @@ err4:
|
||||
err3:
|
||||
device_remove_file(&pdev->dev, &dev_attr_enable);
|
||||
err2:
|
||||
for (i = row_idx-1; i >=0; i--)
|
||||
for (i = row_idx - 1; i >=0; i--)
|
||||
omap_free_gpio(row_gpios[i]);
|
||||
err1:
|
||||
for (i = col_idx-1; i >=0; i--)
|
||||
for (i = col_idx - 1; i >=0; i--)
|
||||
omap_free_gpio(col_gpios[i]);
|
||||
|
||||
kfree(omap_kp);
|
||||
@@ -464,6 +467,7 @@ static struct platform_driver omap_kp_driver = {
|
||||
.resume = omap_kp_resume,
|
||||
.driver = {
|
||||
.name = "omap-keypad",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -484,3 +488,4 @@ module_exit(omap_kp_exit);
|
||||
MODULE_AUTHOR("Timo Teräs");
|
||||
MODULE_DESCRIPTION("OMAP Keypad Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:omap-keypad");
|
||||
|
||||
@@ -545,6 +545,9 @@ static int __devexit pxa27x_keypad_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* work with hotplug and coldplug */
|
||||
MODULE_ALIAS("platform:pxa27x-keypad");
|
||||
|
||||
static struct platform_driver pxa27x_keypad_driver = {
|
||||
.probe = pxa27x_keypad_probe,
|
||||
.remove = __devexit_p(pxa27x_keypad_remove),
|
||||
@@ -552,6 +555,7 @@ static struct platform_driver pxa27x_keypad_driver = {
|
||||
.resume = pxa27x_keypad_resume,
|
||||
.driver = {
|
||||
.name = "pxa27x-keypad",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -495,3 +495,4 @@ module_exit(spitzkbd_exit);
|
||||
MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
|
||||
MODULE_DESCRIPTION("Spitz Keyboard Driver");
|
||||
MODULE_LICENSE("GPLv2");
|
||||
MODULE_ALIAS("platform:spitz-keyboard");
|
||||
|
||||
@@ -52,7 +52,7 @@ KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_
|
||||
struct tosakbd {
|
||||
unsigned int keycode[ARRAY_SIZE(tosakbd_keycode)];
|
||||
struct input_dev *input;
|
||||
|
||||
int suspended;
|
||||
spinlock_t lock; /* protect kbd scanning */
|
||||
struct timer_list timer;
|
||||
};
|
||||
@@ -133,6 +133,9 @@ static void tosakbd_scankeyboard(struct platform_device *dev)
|
||||
|
||||
spin_lock_irqsave(&tosakbd->lock, flags);
|
||||
|
||||
if (tosakbd->suspended)
|
||||
goto out;
|
||||
|
||||
for (col = 0; col < TOSA_KEY_STROBE_NUM; col++) {
|
||||
/*
|
||||
* Discharge the output driver capacitatance
|
||||
@@ -174,6 +177,7 @@ static void tosakbd_scankeyboard(struct platform_device *dev)
|
||||
if (num_pressed)
|
||||
mod_timer(&tosakbd->timer, jiffies + SCAN_INTERVAL);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&tosakbd->lock, flags);
|
||||
}
|
||||
|
||||
@@ -200,6 +204,7 @@ static irqreturn_t tosakbd_interrupt(int irq, void *__dev)
|
||||
static void tosakbd_timer_callback(unsigned long __dev)
|
||||
{
|
||||
struct platform_device *dev = (struct platform_device *)__dev;
|
||||
|
||||
tosakbd_scankeyboard(dev);
|
||||
}
|
||||
|
||||
@@ -207,6 +212,13 @@ static void tosakbd_timer_callback(unsigned long __dev)
|
||||
static int tosakbd_suspend(struct platform_device *dev, pm_message_t state)
|
||||
{
|
||||
struct tosakbd *tosakbd = platform_get_drvdata(dev);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tosakbd->lock, flags);
|
||||
PGSR1 = (PGSR1 & ~TOSA_GPIO_LOW_STROBE_BIT);
|
||||
PGSR2 = (PGSR2 & ~TOSA_GPIO_HIGH_STROBE_BIT);
|
||||
tosakbd->suspended = 1;
|
||||
spin_unlock_irqrestore(&tosakbd->lock, flags);
|
||||
|
||||
del_timer_sync(&tosakbd->timer);
|
||||
|
||||
@@ -215,6 +227,9 @@ static int tosakbd_suspend(struct platform_device *dev, pm_message_t state)
|
||||
|
||||
static int tosakbd_resume(struct platform_device *dev)
|
||||
{
|
||||
struct tosakbd *tosakbd = platform_get_drvdata(dev);
|
||||
|
||||
tosakbd->suspended = 0;
|
||||
tosakbd_scankeyboard(dev);
|
||||
|
||||
return 0;
|
||||
@@ -365,8 +380,8 @@ fail:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int __devexit tosakbd_remove(struct platform_device *dev) {
|
||||
|
||||
static int __devexit tosakbd_remove(struct platform_device *dev)
|
||||
{
|
||||
int i;
|
||||
struct tosakbd *tosakbd = platform_get_drvdata(dev);
|
||||
|
||||
@@ -394,6 +409,7 @@ static struct platform_driver tosakbd_driver = {
|
||||
.resume = tosakbd_resume,
|
||||
.driver = {
|
||||
.name = "tosa-keyboard",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -413,3 +429,4 @@ module_exit(tosakbd_exit);
|
||||
MODULE_AUTHOR("Dirk Opfer <Dirk@Opfer-Online.de>");
|
||||
MODULE_DESCRIPTION("Tosa Keyboard Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:tosa-keyboard");
|
||||
|
||||
@@ -148,6 +148,9 @@ static int __devexit cobalt_buttons_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* work with hotplug and coldplug */
|
||||
MODULE_ALIAS("platform:Cobalt buttons");
|
||||
|
||||
static struct platform_driver cobalt_buttons_driver = {
|
||||
.probe = cobalt_buttons_probe,
|
||||
.remove = __devexit_p(cobalt_buttons_remove),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user