Commit ed2608fa authored by Linus Torvalds's avatar Linus Torvalds

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

Pull more input subsystem updates from Dmitry Torokhov:
 "Just a few more driver fixes; new drivers will be coming in the next
  merge window"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: pwm-beeper - fix - scheduling while atomic
  Input: xpad - xbox one elite controller support
  Input: xpad - add more third-party controllers
  Input: xpad - prevent spurious input from wired Xbox 360 controllers
  Input: xpad - move pending clear to the correct location
  Input: uinput - handle compat ioctl for UI_SET_PHYS
parents 06d2e781 f49cf3b8
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
#define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>" #define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>"
#define DRIVER_DESC "X-Box pad driver" #define DRIVER_DESC "X-Box pad driver"
#define XPAD_PKT_LEN 32 #define XPAD_PKT_LEN 64
/* xbox d-pads should map to buttons, as is required for DDR pads /* xbox d-pads should map to buttons, as is required for DDR pads
but we map them to axes when possible to simplify things */ but we map them to axes when possible to simplify things */
...@@ -129,6 +129,7 @@ static const struct xpad_device { ...@@ -129,6 +129,7 @@ static const struct xpad_device {
{ 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 },
{ 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE }, { 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE },
{ 0x045e, 0x02dd, "Microsoft X-Box One pad (Firmware 2015)", 0, XTYPE_XBOXONE }, { 0x045e, 0x02dd, "Microsoft X-Box One pad (Firmware 2015)", 0, XTYPE_XBOXONE },
{ 0x045e, 0x02e3, "Microsoft X-Box One Elite pad", 0, XTYPE_XBOXONE },
{ 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, { 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
{ 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
{ 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX },
...@@ -173,9 +174,11 @@ static const struct xpad_device { ...@@ -173,9 +174,11 @@ static const struct xpad_device {
{ 0x0e6f, 0x0006, "Edge wireless Controller", 0, XTYPE_XBOX }, { 0x0e6f, 0x0006, "Edge wireless Controller", 0, XTYPE_XBOX },
{ 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x0e6f, 0x0113, "Afterglow AX.1 Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, { 0x0e6f, 0x0113, "Afterglow AX.1 Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
{ 0x0e6f, 0x0139, "Afterglow Prismatic Wired Controller", 0, XTYPE_XBOXONE },
{ 0x0e6f, 0x0201, "Pelican PL-3601 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, { 0x0e6f, 0x0201, "Pelican PL-3601 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 },
{ 0x0e6f, 0x0213, "Afterglow Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, { 0x0e6f, 0x0213, "Afterglow Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
{ 0x0e6f, 0x021f, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, { 0x0e6f, 0x021f, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
{ 0x0e6f, 0x0146, "Rock Candy Wired Controller for Xbox One", 0, XTYPE_XBOXONE },
{ 0x0e6f, 0x0301, "Logic3 Controller", 0, XTYPE_XBOX360 }, { 0x0e6f, 0x0301, "Logic3 Controller", 0, XTYPE_XBOX360 },
{ 0x0e6f, 0x0401, "Logic3 Controller", 0, XTYPE_XBOX360 }, { 0x0e6f, 0x0401, "Logic3 Controller", 0, XTYPE_XBOX360 },
{ 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", 0, XTYPE_XBOX }, { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", 0, XTYPE_XBOX },
...@@ -183,6 +186,7 @@ static const struct xpad_device { ...@@ -183,6 +186,7 @@ static const struct xpad_device {
{ 0x0f0d, 0x000a, "Hori Co. DOA4 FightStick", 0, XTYPE_XBOX360 }, { 0x0f0d, 0x000a, "Hori Co. DOA4 FightStick", 0, XTYPE_XBOX360 },
{ 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x0f0d, 0x0067, "HORIPAD ONE", 0, XTYPE_XBOXONE },
{ 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX }, { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX },
{ 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX }, { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX },
{ 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX }, { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX },
...@@ -199,6 +203,7 @@ static const struct xpad_device { ...@@ -199,6 +203,7 @@ static const struct xpad_device {
{ 0x162e, 0xbeef, "Joytech Neo-Se Take2", 0, XTYPE_XBOX360 }, { 0x162e, 0xbeef, "Joytech Neo-Se Take2", 0, XTYPE_XBOX360 },
{ 0x1689, 0xfd00, "Razer Onza Tournament Edition", 0, XTYPE_XBOX360 }, { 0x1689, 0xfd00, "Razer Onza Tournament Edition", 0, XTYPE_XBOX360 },
{ 0x1689, 0xfd01, "Razer Onza Classic Edition", 0, XTYPE_XBOX360 }, { 0x1689, 0xfd01, "Razer Onza Classic Edition", 0, XTYPE_XBOX360 },
{ 0x24c6, 0x542a, "Xbox ONE spectra", 0, XTYPE_XBOXONE },
{ 0x24c6, 0x5d04, "Razer Sabertooth", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5d04, "Razer Sabertooth", 0, XTYPE_XBOX360 },
{ 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 }, { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 },
{ 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
...@@ -212,6 +217,8 @@ static const struct xpad_device { ...@@ -212,6 +217,8 @@ static const struct xpad_device {
{ 0x24c6, 0x5000, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x24c6, 0x5000, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 },
{ 0x24c6, 0x5303, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5303, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 },
{ 0x24c6, 0x541a, "PowerA Xbox One Mini Wired Controller", 0, XTYPE_XBOXONE },
{ 0x24c6, 0x543a, "PowerA Xbox One wired controller", 0, XTYPE_XBOXONE },
{ 0x24c6, 0x5500, "Hori XBOX 360 EX 2 with Turbo", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5500, "Hori XBOX 360 EX 2 with Turbo", 0, XTYPE_XBOX360 },
{ 0x24c6, 0x5501, "Hori Real Arcade Pro VX-SA", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5501, "Hori Real Arcade Pro VX-SA", 0, XTYPE_XBOX360 },
{ 0x24c6, 0x5506, "Hori SOULCALIBUR V Stick", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5506, "Hori SOULCALIBUR V Stick", 0, XTYPE_XBOX360 },
...@@ -307,13 +314,16 @@ static struct usb_device_id xpad_table[] = { ...@@ -307,13 +314,16 @@ static struct usb_device_id xpad_table[] = {
{ USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */ { USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */
XPAD_XBOXONE_VENDOR(0x0738), /* Mad Catz FightStick TE 2 */ XPAD_XBOXONE_VENDOR(0x0738), /* Mad Catz FightStick TE 2 */
XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */
XPAD_XBOXONE_VENDOR(0x0e6f), /* 0x0e6f X-Box One controllers */
XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */ XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */
XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */
XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */ XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */
XPAD_XBOX360_VENDOR(0x1bad), /* Harminix Rock Band Guitar and Drums */ XPAD_XBOX360_VENDOR(0x1bad), /* Harminix Rock Band Guitar and Drums */
XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */
XPAD_XBOXONE_VENDOR(0x0f0d), /* Hori Controllers */
XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */ XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */
XPAD_XBOX360_VENDOR(0x24c6), /* PowerA Controllers */ XPAD_XBOX360_VENDOR(0x24c6), /* PowerA Controllers */
XPAD_XBOXONE_VENDOR(0x24c6), /* PowerA Controllers */
XPAD_XBOX360_VENDOR(0x1532), /* Razer Sabertooth */ XPAD_XBOX360_VENDOR(0x1532), /* Razer Sabertooth */
XPAD_XBOX360_VENDOR(0x15e4), /* Numark X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x15e4), /* Numark X-Box 360 controllers */
XPAD_XBOX360_VENDOR(0x162e), /* Joytech X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x162e), /* Joytech X-Box 360 controllers */
...@@ -457,6 +467,10 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d ...@@ -457,6 +467,10 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
static void xpad360_process_packet(struct usb_xpad *xpad, struct input_dev *dev, static void xpad360_process_packet(struct usb_xpad *xpad, struct input_dev *dev,
u16 cmd, unsigned char *data) u16 cmd, unsigned char *data)
{ {
/* valid pad data */
if (data[0] != 0x00)
return;
/* digital pad */ /* digital pad */
if (xpad->mapping & MAP_DPAD_TO_BUTTONS) { if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
/* dpad as buttons (left, right, up, down) */ /* dpad as buttons (left, right, up, down) */
...@@ -756,6 +770,7 @@ static bool xpad_prepare_next_out_packet(struct usb_xpad *xpad) ...@@ -756,6 +770,7 @@ static bool xpad_prepare_next_out_packet(struct usb_xpad *xpad)
if (packet) { if (packet) {
memcpy(xpad->odata, packet->data, packet->len); memcpy(xpad->odata, packet->data, packet->len);
xpad->irq_out->transfer_buffer_length = packet->len; xpad->irq_out->transfer_buffer_length = packet->len;
packet->pending = false;
return true; return true;
} }
...@@ -797,7 +812,6 @@ static void xpad_irq_out(struct urb *urb) ...@@ -797,7 +812,6 @@ static void xpad_irq_out(struct urb *urb)
switch (status) { switch (status) {
case 0: case 0:
/* success */ /* success */
xpad->out_packets[xpad->last_out_packet].pending = false;
xpad->irq_out_active = xpad_prepare_next_out_packet(xpad); xpad->irq_out_active = xpad_prepare_next_out_packet(xpad);
break; break;
......
...@@ -20,21 +20,40 @@ ...@@ -20,21 +20,40 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pwm.h> #include <linux/pwm.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/workqueue.h>
struct pwm_beeper { struct pwm_beeper {
struct input_dev *input; struct input_dev *input;
struct pwm_device *pwm; struct pwm_device *pwm;
struct work_struct work;
unsigned long period; unsigned long period;
}; };
#define HZ_TO_NANOSECONDS(x) (1000000000UL/(x)) #define HZ_TO_NANOSECONDS(x) (1000000000UL/(x))
static void __pwm_beeper_set(struct pwm_beeper *beeper)
{
unsigned long period = beeper->period;
if (period) {
pwm_config(beeper->pwm, period / 2, period);
pwm_enable(beeper->pwm);
} else
pwm_disable(beeper->pwm);
}
static void pwm_beeper_work(struct work_struct *work)
{
struct pwm_beeper *beeper =
container_of(work, struct pwm_beeper, work);
__pwm_beeper_set(beeper);
}
static int pwm_beeper_event(struct input_dev *input, static int pwm_beeper_event(struct input_dev *input,
unsigned int type, unsigned int code, int value) unsigned int type, unsigned int code, int value)
{ {
int ret = 0;
struct pwm_beeper *beeper = input_get_drvdata(input); struct pwm_beeper *beeper = input_get_drvdata(input);
unsigned long period;
if (type != EV_SND || value < 0) if (type != EV_SND || value < 0)
return -EINVAL; return -EINVAL;
...@@ -49,22 +68,31 @@ static int pwm_beeper_event(struct input_dev *input, ...@@ -49,22 +68,31 @@ static int pwm_beeper_event(struct input_dev *input,
return -EINVAL; return -EINVAL;
} }
if (value == 0) { if (value == 0)
pwm_disable(beeper->pwm); beeper->period = 0;
} else { else
period = HZ_TO_NANOSECONDS(value); beeper->period = HZ_TO_NANOSECONDS(value);
ret = pwm_config(beeper->pwm, period / 2, period);
if (ret) schedule_work(&beeper->work);
return ret;
ret = pwm_enable(beeper->pwm);
if (ret)
return ret;
beeper->period = period;
}
return 0; return 0;
} }
static void pwm_beeper_stop(struct pwm_beeper *beeper)
{
cancel_work_sync(&beeper->work);
if (beeper->period)
pwm_disable(beeper->pwm);
}
static void pwm_beeper_close(struct input_dev *input)
{
struct pwm_beeper *beeper = input_get_drvdata(input);
pwm_beeper_stop(beeper);
}
static int pwm_beeper_probe(struct platform_device *pdev) static int pwm_beeper_probe(struct platform_device *pdev)
{ {
unsigned long pwm_id = (unsigned long)dev_get_platdata(&pdev->dev); unsigned long pwm_id = (unsigned long)dev_get_platdata(&pdev->dev);
...@@ -93,6 +121,8 @@ static int pwm_beeper_probe(struct platform_device *pdev) ...@@ -93,6 +121,8 @@ static int pwm_beeper_probe(struct platform_device *pdev)
*/ */
pwm_apply_args(beeper->pwm); pwm_apply_args(beeper->pwm);
INIT_WORK(&beeper->work, pwm_beeper_work);
beeper->input = input_allocate_device(); beeper->input = input_allocate_device();
if (!beeper->input) { if (!beeper->input) {
dev_err(&pdev->dev, "Failed to allocate input device\n"); dev_err(&pdev->dev, "Failed to allocate input device\n");
...@@ -112,6 +142,7 @@ static int pwm_beeper_probe(struct platform_device *pdev) ...@@ -112,6 +142,7 @@ static int pwm_beeper_probe(struct platform_device *pdev)
beeper->input->sndbit[0] = BIT(SND_TONE) | BIT(SND_BELL); beeper->input->sndbit[0] = BIT(SND_TONE) | BIT(SND_BELL);
beeper->input->event = pwm_beeper_event; beeper->input->event = pwm_beeper_event;
beeper->input->close = pwm_beeper_close;
input_set_drvdata(beeper->input, beeper); input_set_drvdata(beeper->input, beeper);
...@@ -141,7 +172,6 @@ static int pwm_beeper_remove(struct platform_device *pdev) ...@@ -141,7 +172,6 @@ static int pwm_beeper_remove(struct platform_device *pdev)
input_unregister_device(beeper->input); input_unregister_device(beeper->input);
pwm_disable(beeper->pwm);
pwm_free(beeper->pwm); pwm_free(beeper->pwm);
kfree(beeper); kfree(beeper);
...@@ -153,8 +183,7 @@ static int __maybe_unused pwm_beeper_suspend(struct device *dev) ...@@ -153,8 +183,7 @@ static int __maybe_unused pwm_beeper_suspend(struct device *dev)
{ {
struct pwm_beeper *beeper = dev_get_drvdata(dev); struct pwm_beeper *beeper = dev_get_drvdata(dev);
if (beeper->period) pwm_beeper_stop(beeper);
pwm_disable(beeper->pwm);
return 0; return 0;
} }
...@@ -163,10 +192,8 @@ static int __maybe_unused pwm_beeper_resume(struct device *dev) ...@@ -163,10 +192,8 @@ static int __maybe_unused pwm_beeper_resume(struct device *dev)
{ {
struct pwm_beeper *beeper = dev_get_drvdata(dev); struct pwm_beeper *beeper = dev_get_drvdata(dev);
if (beeper->period) { if (beeper->period)
pwm_config(beeper->pwm, beeper->period / 2, beeper->period); __pwm_beeper_set(beeper);
pwm_enable(beeper->pwm);
}
return 0; return 0;
} }
......
...@@ -981,9 +981,15 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -981,9 +981,15 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
#define UI_SET_PHYS_COMPAT _IOW(UINPUT_IOCTL_BASE, 108, compat_uptr_t)
static long uinput_compat_ioctl(struct file *file, static long uinput_compat_ioctl(struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
if (cmd == UI_SET_PHYS_COMPAT)
cmd = UI_SET_PHYS;
return uinput_ioctl_handler(file, cmd, arg, compat_ptr(arg)); return uinput_ioctl_handler(file, cmd, arg, compat_ptr(arg));
} }
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment