Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 53421
b: refs/heads/master
c: a1421d3
h: refs/heads/master
i:
  53419: cfffdad
v: v3
  • Loading branch information
Peter Stokes authored and Dmitry Torokhov committed Apr 12, 2007
1 parent a824be9 commit 22abafe
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 10 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1b726a02d97cef2471521ae6947416f7374c6590
refs/heads/master: a1421d3c780c373d5f74a0ab99b0652041d61876
89 changes: 80 additions & 9 deletions trunk/drivers/usb/input/ati_remote2.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* ati_remote2 - ATI/Philips USB RF remote driver
*
* Copyright (C) 2005 Ville Syrjala <syrjala@sci.fi>
* Copyright (C) 2007 Peter Stokes <linux@dadeos.freeserve.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
Expand All @@ -11,13 +12,29 @@
#include <linux/usb/input.h>

#define DRIVER_DESC "ATI/Philips USB RF remote driver"
#define DRIVER_VERSION "0.1"
#define DRIVER_VERSION "0.2"

MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERSION);
MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>");
MODULE_LICENSE("GPL");

/*
* ATI Remote Wonder II Channel Configuration
*
* The remote control can by assigned one of sixteen "channels" in order to facilitate
* the use of multiple remote controls within range of each other.
* A remote's "channel" may be altered by pressing and holding the "PC" button for
* approximately 3 seconds, after which the button will slowly flash the count of the
* currently configured "channel", using the numeric keypad enter a number between 1 and
* 16 and then the "PC" button again, the button will slowly flash the count of the
* newly configured "channel".
*/

static unsigned int channel_mask = 0xFFFF;
module_param(channel_mask, uint, 0644);
MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...<1:Channel2><0:Channel1>");

static unsigned int mode_mask = 0x1F;
module_param(mode_mask, uint, 0644);
MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>");
Expand Down Expand Up @@ -146,15 +163,23 @@ static void ati_remote2_input_mouse(struct ati_remote2 *ar2)
{
struct input_dev *idev = ar2->idev;
u8 *data = ar2->buf[0];
int channel, mode;

channel = data[0] >> 4;

if (!((1 << channel) & channel_mask))
return;

if (data[0] > 4) {
mode = data[0] & 0x0F;

if (mode > 4) {
dev_err(&ar2->intf[0]->dev,
"Unknown mode byte (%02x %02x %02x %02x)\n",
data[3], data[2], data[1], data[0]);
return;
}

if (!((1 << data[0]) & mode_mask))
if (!((1 << mode) & mode_mask))
return;

input_event(idev, EV_REL, REL_X, (s8) data[1]);
Expand All @@ -177,9 +202,16 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2)
{
struct input_dev *idev = ar2->idev;
u8 *data = ar2->buf[1];
int hw_code, index;
int channel, mode, hw_code, index;

channel = data[0] >> 4;

if (!((1 << channel) & channel_mask))
return;

if (data[0] > 4) {
mode = data[0] & 0x0F;

if (mode > 4) {
dev_err(&ar2->intf[1]->dev,
"Unknown mode byte (%02x %02x %02x %02x)\n",
data[3], data[2], data[1], data[0]);
Expand All @@ -199,16 +231,16 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2)
* events for the mouse pad so we filter out any subsequent
* events from the same mode key.
*/
if (ar2->mode == data[0])
if (ar2->mode == mode)
return;

if (data[1] == 0)
ar2->mode = data[0];
ar2->mode = mode;

hw_code |= data[0] << 8;
hw_code |= mode << 8;
}

if (!((1 << data[0]) & mode_mask))
if (!((1 << mode) & mode_mask))
return;

index = ati_remote2_lookup(hw_code);
Expand Down Expand Up @@ -379,6 +411,41 @@ static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2)
}
}

static int ati_remote2_setup(struct ati_remote2 *ar2)
{
int r, i, channel;

/*
* Configure receiver to only accept input from remote "channel"
* channel == 0 -> Accept input from any remote channel
* channel == 1 -> Only accept input from remote channel 1
* channel == 2 -> Only accept input from remote channel 2
* ...
* channel == 16 -> Only accept input from remote channel 16
*/

channel = 0;
for (i = 0; i < 16; i++) {
if ((1 << i) & channel_mask) {
if (!(~(1 << i) & 0xFFFF & channel_mask))
channel = i + 1;
break;
}
}

r = usb_control_msg(ar2->udev, usb_sndctrlpipe(ar2->udev, 0),
0x20,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
channel, 0x0, NULL, 0, USB_CTRL_SET_TIMEOUT);
if (r) {
dev_err(&ar2->udev->dev, "%s - failed to set channel due to error: %d\n",
__FUNCTION__, r);
return r;
}

return 0;
}

static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(interface);
Expand Down Expand Up @@ -409,6 +476,10 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d
if (r)
goto fail2;

r = ati_remote2_setup(ar2);
if (r)
goto fail2;

usb_make_path(udev, ar2->phys, sizeof(ar2->phys));
strlcat(ar2->phys, "/input0", sizeof(ar2->phys));

Expand Down

0 comments on commit 22abafe

Please sign in to comment.