| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 1 | /* | 
 | 2 |  * ati_remote2 - ATI/Philips USB RF remote driver | 
 | 3 |  * | 
 | 4 |  * Copyright (C) 2005 Ville Syrjala <syrjala@sci.fi> | 
| Peter Stokes | a1421d3 | 2007-04-12 01:33:10 -0400 | [diff] [blame] | 5 |  * Copyright (C) 2007 Peter Stokes <linux@dadeos.freeserve.co.uk> | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 6 |  * | 
 | 7 |  * This program is free software; you can redistribute it and/or modify | 
 | 8 |  * it under the terms of the GNU General Public License version 2 | 
 | 9 |  * as published by the Free Software Foundation. | 
 | 10 |  */ | 
 | 11 |  | 
| David Brownell | ae0dadc | 2006-06-13 10:04:34 -0700 | [diff] [blame] | 12 | #include <linux/usb/input.h> | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 13 |  | 
 | 14 | #define DRIVER_DESC    "ATI/Philips USB RF remote driver" | 
| Peter Stokes | a1421d3 | 2007-04-12 01:33:10 -0400 | [diff] [blame] | 15 | #define DRIVER_VERSION "0.2" | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 16 |  | 
 | 17 | MODULE_DESCRIPTION(DRIVER_DESC); | 
 | 18 | MODULE_VERSION(DRIVER_VERSION); | 
 | 19 | MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>"); | 
 | 20 | MODULE_LICENSE("GPL"); | 
 | 21 |  | 
| Peter Stokes | a1421d3 | 2007-04-12 01:33:10 -0400 | [diff] [blame] | 22 | /* | 
 | 23 |  * ATI Remote Wonder II Channel Configuration | 
 | 24 |  * | 
 | 25 |  * The remote control can by assigned one of sixteen "channels" in order to facilitate | 
 | 26 |  * the use of multiple remote controls within range of each other. | 
 | 27 |  * A remote's "channel" may be altered by pressing and holding the "PC" button for | 
 | 28 |  * approximately 3 seconds, after which the button will slowly flash the count of the | 
 | 29 |  * currently configured "channel", using the numeric keypad enter a number between 1 and | 
 | 30 |  * 16 and then the "PC" button again, the button will slowly flash the count of the | 
 | 31 |  * newly configured "channel". | 
 | 32 |  */ | 
 | 33 |  | 
 | 34 | static unsigned int channel_mask = 0xFFFF; | 
 | 35 | module_param(channel_mask, uint, 0644); | 
 | 36 | MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...<1:Channel2><0:Channel1>"); | 
 | 37 |  | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 38 | static unsigned int mode_mask = 0x1F; | 
 | 39 | module_param(mode_mask, uint, 0644); | 
 | 40 | MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>"); | 
 | 41 |  | 
 | 42 | static struct usb_device_id ati_remote2_id_table[] = { | 
 | 43 | 	{ USB_DEVICE(0x0471, 0x0602) },	/* ATI Remote Wonder II */ | 
 | 44 | 	{ } | 
 | 45 | }; | 
 | 46 | MODULE_DEVICE_TABLE(usb, ati_remote2_id_table); | 
 | 47 |  | 
 | 48 | static struct { | 
 | 49 | 	int hw_code; | 
 | 50 | 	int key_code; | 
 | 51 | } ati_remote2_key_table[] = { | 
 | 52 | 	{ 0x00, KEY_0 }, | 
 | 53 | 	{ 0x01, KEY_1 }, | 
 | 54 | 	{ 0x02, KEY_2 }, | 
 | 55 | 	{ 0x03, KEY_3 }, | 
 | 56 | 	{ 0x04, KEY_4 }, | 
 | 57 | 	{ 0x05, KEY_5 }, | 
 | 58 | 	{ 0x06, KEY_6 }, | 
 | 59 | 	{ 0x07, KEY_7 }, | 
 | 60 | 	{ 0x08, KEY_8 }, | 
 | 61 | 	{ 0x09, KEY_9 }, | 
 | 62 | 	{ 0x0c, KEY_POWER }, | 
 | 63 | 	{ 0x0d, KEY_MUTE }, | 
 | 64 | 	{ 0x10, KEY_VOLUMEUP }, | 
 | 65 | 	{ 0x11, KEY_VOLUMEDOWN }, | 
 | 66 | 	{ 0x20, KEY_CHANNELUP }, | 
 | 67 | 	{ 0x21, KEY_CHANNELDOWN }, | 
 | 68 | 	{ 0x28, KEY_FORWARD }, | 
 | 69 | 	{ 0x29, KEY_REWIND }, | 
 | 70 | 	{ 0x2c, KEY_PLAY }, | 
 | 71 | 	{ 0x30, KEY_PAUSE }, | 
 | 72 | 	{ 0x31, KEY_STOP }, | 
 | 73 | 	{ 0x37, KEY_RECORD }, | 
 | 74 | 	{ 0x38, KEY_DVD }, | 
 | 75 | 	{ 0x39, KEY_TV }, | 
 | 76 | 	{ 0x54, KEY_MENU }, | 
 | 77 | 	{ 0x58, KEY_UP }, | 
 | 78 | 	{ 0x59, KEY_DOWN }, | 
 | 79 | 	{ 0x5a, KEY_LEFT }, | 
 | 80 | 	{ 0x5b, KEY_RIGHT }, | 
 | 81 | 	{ 0x5c, KEY_OK }, | 
 | 82 | 	{ 0x78, KEY_A }, | 
 | 83 | 	{ 0x79, KEY_B }, | 
 | 84 | 	{ 0x7a, KEY_C }, | 
 | 85 | 	{ 0x7b, KEY_D }, | 
 | 86 | 	{ 0x7c, KEY_E }, | 
 | 87 | 	{ 0x7d, KEY_F }, | 
 | 88 | 	{ 0x82, KEY_ENTER }, | 
 | 89 | 	{ 0x8e, KEY_VENDOR }, | 
 | 90 | 	{ 0x96, KEY_COFFEE }, | 
 | 91 | 	{ 0xa9, BTN_LEFT }, | 
 | 92 | 	{ 0xaa, BTN_RIGHT }, | 
 | 93 | 	{ 0xbe, KEY_QUESTION }, | 
 | 94 | 	{ 0xd5, KEY_FRONT }, | 
 | 95 | 	{ 0xd0, KEY_EDIT }, | 
 | 96 | 	{ 0xf9, KEY_INFO }, | 
 | 97 | 	{ (0x00 << 8) | 0x3f, KEY_PROG1 }, | 
 | 98 | 	{ (0x01 << 8) | 0x3f, KEY_PROG2 }, | 
 | 99 | 	{ (0x02 << 8) | 0x3f, KEY_PROG3 }, | 
 | 100 | 	{ (0x03 << 8) | 0x3f, KEY_PROG4 }, | 
 | 101 | 	{ (0x04 << 8) | 0x3f, KEY_PC }, | 
 | 102 | 	{ 0, KEY_RESERVED } | 
 | 103 | }; | 
 | 104 |  | 
 | 105 | struct ati_remote2 { | 
 | 106 | 	struct input_dev *idev; | 
 | 107 | 	struct usb_device *udev; | 
 | 108 |  | 
 | 109 | 	struct usb_interface *intf[2]; | 
 | 110 | 	struct usb_endpoint_descriptor *ep[2]; | 
 | 111 | 	struct urb *urb[2]; | 
 | 112 | 	void *buf[2]; | 
 | 113 | 	dma_addr_t buf_dma[2]; | 
 | 114 |  | 
 | 115 | 	unsigned long jiffies; | 
 | 116 | 	int mode; | 
 | 117 |  | 
 | 118 | 	char name[64]; | 
 | 119 | 	char phys[64]; | 
 | 120 | }; | 
 | 121 |  | 
 | 122 | static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id); | 
 | 123 | static void ati_remote2_disconnect(struct usb_interface *interface); | 
 | 124 |  | 
 | 125 | static struct usb_driver ati_remote2_driver = { | 
 | 126 | 	.name       = "ati_remote2", | 
 | 127 | 	.probe      = ati_remote2_probe, | 
 | 128 | 	.disconnect = ati_remote2_disconnect, | 
 | 129 | 	.id_table   = ati_remote2_id_table, | 
 | 130 | }; | 
 | 131 |  | 
 | 132 | static int ati_remote2_open(struct input_dev *idev) | 
 | 133 | { | 
| Dmitry Torokhov | 7791bda | 2007-04-12 01:34:39 -0400 | [diff] [blame] | 134 | 	struct ati_remote2 *ar2 = input_get_drvdata(idev); | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 135 | 	int r; | 
 | 136 |  | 
 | 137 | 	r = usb_submit_urb(ar2->urb[0], GFP_KERNEL); | 
 | 138 | 	if (r) { | 
 | 139 | 		dev_err(&ar2->intf[0]->dev, | 
 | 140 | 			"%s: usb_submit_urb() = %d\n", __FUNCTION__, r); | 
 | 141 | 		return r; | 
 | 142 | 	} | 
 | 143 | 	r = usb_submit_urb(ar2->urb[1], GFP_KERNEL); | 
 | 144 | 	if (r) { | 
 | 145 | 		usb_kill_urb(ar2->urb[0]); | 
 | 146 | 		dev_err(&ar2->intf[1]->dev, | 
 | 147 | 			"%s: usb_submit_urb() = %d\n", __FUNCTION__, r); | 
 | 148 | 		return r; | 
 | 149 | 	} | 
 | 150 |  | 
 | 151 | 	return 0; | 
 | 152 | } | 
 | 153 |  | 
 | 154 | static void ati_remote2_close(struct input_dev *idev) | 
 | 155 | { | 
| Dmitry Torokhov | 7791bda | 2007-04-12 01:34:39 -0400 | [diff] [blame] | 156 | 	struct ati_remote2 *ar2 = input_get_drvdata(idev); | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 157 |  | 
 | 158 | 	usb_kill_urb(ar2->urb[0]); | 
 | 159 | 	usb_kill_urb(ar2->urb[1]); | 
 | 160 | } | 
 | 161 |  | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 162 | static void ati_remote2_input_mouse(struct ati_remote2 *ar2) | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 163 | { | 
 | 164 | 	struct input_dev *idev = ar2->idev; | 
 | 165 | 	u8 *data = ar2->buf[0]; | 
| Peter Stokes | a1421d3 | 2007-04-12 01:33:10 -0400 | [diff] [blame] | 166 | 	int channel, mode; | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 167 |  | 
| Peter Stokes | a1421d3 | 2007-04-12 01:33:10 -0400 | [diff] [blame] | 168 | 	channel = data[0] >> 4; | 
 | 169 |  | 
 | 170 | 	if (!((1 << channel) & channel_mask)) | 
 | 171 | 		return; | 
 | 172 |  | 
 | 173 | 	mode = data[0] & 0x0F; | 
 | 174 |  | 
 | 175 | 	if (mode > 4) { | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 176 | 		dev_err(&ar2->intf[0]->dev, | 
 | 177 | 			"Unknown mode byte (%02x %02x %02x %02x)\n", | 
 | 178 | 			data[3], data[2], data[1], data[0]); | 
 | 179 | 		return; | 
 | 180 | 	} | 
 | 181 |  | 
| Peter Stokes | a1421d3 | 2007-04-12 01:33:10 -0400 | [diff] [blame] | 182 | 	if (!((1 << mode) & mode_mask)) | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 183 | 		return; | 
 | 184 |  | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 185 | 	input_event(idev, EV_REL, REL_X, (s8) data[1]); | 
 | 186 | 	input_event(idev, EV_REL, REL_Y, (s8) data[2]); | 
 | 187 | 	input_sync(idev); | 
 | 188 | } | 
 | 189 |  | 
 | 190 | static int ati_remote2_lookup(unsigned int hw_code) | 
 | 191 | { | 
 | 192 | 	int i; | 
 | 193 |  | 
 | 194 | 	for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++) | 
 | 195 | 		if (ati_remote2_key_table[i].hw_code == hw_code) | 
 | 196 | 			return i; | 
 | 197 |  | 
 | 198 | 	return -1; | 
 | 199 | } | 
 | 200 |  | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 201 | static void ati_remote2_input_key(struct ati_remote2 *ar2) | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 202 | { | 
 | 203 | 	struct input_dev *idev = ar2->idev; | 
 | 204 | 	u8 *data = ar2->buf[1]; | 
| Peter Stokes | a1421d3 | 2007-04-12 01:33:10 -0400 | [diff] [blame] | 205 | 	int channel, mode, hw_code, index; | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 206 |  | 
| Peter Stokes | a1421d3 | 2007-04-12 01:33:10 -0400 | [diff] [blame] | 207 | 	channel = data[0] >> 4; | 
 | 208 |  | 
 | 209 | 	if (!((1 << channel) & channel_mask)) | 
 | 210 | 		return; | 
 | 211 |  | 
 | 212 | 	mode = data[0] & 0x0F; | 
 | 213 |  | 
 | 214 | 	if (mode > 4) { | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 215 | 		dev_err(&ar2->intf[1]->dev, | 
 | 216 | 			"Unknown mode byte (%02x %02x %02x %02x)\n", | 
 | 217 | 			data[3], data[2], data[1], data[0]); | 
 | 218 | 		return; | 
 | 219 | 	} | 
 | 220 |  | 
 | 221 | 	hw_code = data[2]; | 
 | 222 | 	/* | 
 | 223 | 	 * Mode keys (AUX1-AUX4, PC) all generate the same code byte. | 
 | 224 | 	 * Use the mode byte to figure out which one was pressed. | 
 | 225 | 	 */ | 
 | 226 | 	if (hw_code == 0x3f) { | 
 | 227 | 		/* | 
 | 228 | 		 * For some incomprehensible reason the mouse pad generates | 
 | 229 | 		 * events which look identical to the events from the last | 
 | 230 | 		 * pressed mode key. Naturally we don't want to generate key | 
 | 231 | 		 * events for the mouse pad so we filter out any subsequent | 
 | 232 | 		 * events from the same mode key. | 
 | 233 | 		 */ | 
| Peter Stokes | a1421d3 | 2007-04-12 01:33:10 -0400 | [diff] [blame] | 234 | 		if (ar2->mode == mode) | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 235 | 			return; | 
 | 236 |  | 
 | 237 | 		if (data[1] == 0) | 
| Peter Stokes | a1421d3 | 2007-04-12 01:33:10 -0400 | [diff] [blame] | 238 | 			ar2->mode = mode; | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 239 |  | 
| Peter Stokes | a1421d3 | 2007-04-12 01:33:10 -0400 | [diff] [blame] | 240 | 		hw_code |= mode << 8; | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 241 | 	} | 
 | 242 |  | 
| Peter Stokes | a1421d3 | 2007-04-12 01:33:10 -0400 | [diff] [blame] | 243 | 	if (!((1 << mode) & mode_mask)) | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 244 | 		return; | 
 | 245 |  | 
 | 246 | 	index = ati_remote2_lookup(hw_code); | 
 | 247 | 	if (index < 0) { | 
 | 248 | 		dev_err(&ar2->intf[1]->dev, | 
 | 249 | 			"Unknown code byte (%02x %02x %02x %02x)\n", | 
 | 250 | 			data[3], data[2], data[1], data[0]); | 
 | 251 | 		return; | 
 | 252 | 	} | 
 | 253 |  | 
 | 254 | 	switch (data[1]) { | 
 | 255 | 	case 0:	/* release */ | 
 | 256 | 		break; | 
 | 257 | 	case 1:	/* press */ | 
 | 258 | 		ar2->jiffies = jiffies + msecs_to_jiffies(idev->rep[REP_DELAY]); | 
 | 259 | 		break; | 
 | 260 | 	case 2:	/* repeat */ | 
 | 261 |  | 
 | 262 | 		/* No repeat for mouse buttons. */ | 
 | 263 | 		if (ati_remote2_key_table[index].key_code == BTN_LEFT || | 
 | 264 | 		    ati_remote2_key_table[index].key_code == BTN_RIGHT) | 
 | 265 | 			return; | 
 | 266 |  | 
 | 267 | 		if (!time_after_eq(jiffies, ar2->jiffies)) | 
 | 268 | 			return; | 
 | 269 |  | 
 | 270 | 		ar2->jiffies = jiffies + msecs_to_jiffies(idev->rep[REP_PERIOD]); | 
 | 271 | 		break; | 
 | 272 | 	default: | 
 | 273 | 		dev_err(&ar2->intf[1]->dev, | 
 | 274 | 			"Unknown state byte (%02x %02x %02x %02x)\n", | 
 | 275 | 			data[3], data[2], data[1], data[0]); | 
 | 276 | 		return; | 
 | 277 | 	} | 
 | 278 |  | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 279 | 	input_event(idev, EV_KEY, ati_remote2_key_table[index].key_code, data[1]); | 
 | 280 | 	input_sync(idev); | 
 | 281 | } | 
 | 282 |  | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 283 | static void ati_remote2_complete_mouse(struct urb *urb) | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 284 | { | 
 | 285 | 	struct ati_remote2 *ar2 = urb->context; | 
 | 286 | 	int r; | 
 | 287 |  | 
 | 288 | 	switch (urb->status) { | 
 | 289 | 	case 0: | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 290 | 		ati_remote2_input_mouse(ar2); | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 291 | 		break; | 
 | 292 | 	case -ENOENT: | 
 | 293 | 	case -EILSEQ: | 
 | 294 | 	case -ECONNRESET: | 
 | 295 | 	case -ESHUTDOWN: | 
 | 296 | 		dev_dbg(&ar2->intf[0]->dev, | 
 | 297 | 			"%s(): urb status = %d\n", __FUNCTION__, urb->status); | 
 | 298 | 		return; | 
 | 299 | 	default: | 
 | 300 | 		dev_err(&ar2->intf[0]->dev, | 
 | 301 | 			"%s(): urb status = %d\n", __FUNCTION__, urb->status); | 
 | 302 | 	} | 
 | 303 |  | 
 | 304 | 	r = usb_submit_urb(urb, GFP_ATOMIC); | 
 | 305 | 	if (r) | 
 | 306 | 		dev_err(&ar2->intf[0]->dev, | 
 | 307 | 			"%s(): usb_submit_urb() = %d\n", __FUNCTION__, r); | 
 | 308 | } | 
 | 309 |  | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 310 | static void ati_remote2_complete_key(struct urb *urb) | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 311 | { | 
 | 312 | 	struct ati_remote2 *ar2 = urb->context; | 
 | 313 | 	int r; | 
 | 314 |  | 
 | 315 | 	switch (urb->status) { | 
 | 316 | 	case 0: | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 317 | 		ati_remote2_input_key(ar2); | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 318 | 		break; | 
 | 319 | 	case -ENOENT: | 
 | 320 | 	case -EILSEQ: | 
 | 321 | 	case -ECONNRESET: | 
 | 322 | 	case -ESHUTDOWN: | 
 | 323 | 		dev_dbg(&ar2->intf[1]->dev, | 
 | 324 | 			"%s(): urb status = %d\n", __FUNCTION__, urb->status); | 
 | 325 | 		return; | 
 | 326 | 	default: | 
 | 327 | 		dev_err(&ar2->intf[1]->dev, | 
 | 328 | 			"%s(): urb status = %d\n", __FUNCTION__, urb->status); | 
 | 329 | 	} | 
 | 330 |  | 
 | 331 | 	r = usb_submit_urb(urb, GFP_ATOMIC); | 
 | 332 | 	if (r) | 
 | 333 | 		dev_err(&ar2->intf[1]->dev, | 
 | 334 | 			"%s(): usb_submit_urb() = %d\n", __FUNCTION__, r); | 
 | 335 | } | 
 | 336 |  | 
 | 337 | static int ati_remote2_input_init(struct ati_remote2 *ar2) | 
 | 338 | { | 
 | 339 | 	struct input_dev *idev; | 
| Dmitry Torokhov | 5014186 | 2007-04-12 01:33:39 -0400 | [diff] [blame] | 340 | 	int i, retval; | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 341 |  | 
 | 342 | 	idev = input_allocate_device(); | 
 | 343 | 	if (!idev) | 
 | 344 | 		return -ENOMEM; | 
 | 345 |  | 
 | 346 | 	ar2->idev = idev; | 
| Dmitry Torokhov | 7791bda | 2007-04-12 01:34:39 -0400 | [diff] [blame] | 347 | 	input_set_drvdata(idev, ar2); | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 348 |  | 
 | 349 | 	idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL); | 
 | 350 | 	idev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT); | 
 | 351 | 	idev->relbit[0] = BIT(REL_X) | BIT(REL_Y); | 
 | 352 | 	for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++) | 
 | 353 | 		set_bit(ati_remote2_key_table[i].key_code, idev->keybit); | 
 | 354 |  | 
 | 355 | 	idev->rep[REP_DELAY]  = 250; | 
 | 356 | 	idev->rep[REP_PERIOD] = 33; | 
 | 357 |  | 
 | 358 | 	idev->open = ati_remote2_open; | 
 | 359 | 	idev->close = ati_remote2_close; | 
 | 360 |  | 
 | 361 | 	idev->name = ar2->name; | 
 | 362 | 	idev->phys = ar2->phys; | 
 | 363 |  | 
 | 364 | 	usb_to_input_id(ar2->udev, &idev->id); | 
| Dmitry Torokhov | c0f82d5 | 2007-04-12 01:35:03 -0400 | [diff] [blame] | 365 | 	idev->dev.parent = &ar2->udev->dev; | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 366 |  | 
| Dmitry Torokhov | 5014186 | 2007-04-12 01:33:39 -0400 | [diff] [blame] | 367 | 	retval = input_register_device(idev); | 
 | 368 | 	if (retval) | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 369 | 		input_free_device(idev); | 
 | 370 |  | 
| Dmitry Torokhov | 5014186 | 2007-04-12 01:33:39 -0400 | [diff] [blame] | 371 | 	return retval; | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 372 | } | 
 | 373 |  | 
 | 374 | static int ati_remote2_urb_init(struct ati_remote2 *ar2) | 
 | 375 | { | 
 | 376 | 	struct usb_device *udev = ar2->udev; | 
 | 377 | 	int i, pipe, maxp; | 
 | 378 |  | 
 | 379 | 	for (i = 0; i < 2; i++) { | 
 | 380 | 		ar2->buf[i] = usb_buffer_alloc(udev, 4, GFP_KERNEL, &ar2->buf_dma[i]); | 
 | 381 | 		if (!ar2->buf[i]) | 
 | 382 | 			return -ENOMEM; | 
 | 383 |  | 
 | 384 | 		ar2->urb[i] = usb_alloc_urb(0, GFP_KERNEL); | 
 | 385 | 		if (!ar2->urb[i]) | 
 | 386 | 			return -ENOMEM; | 
 | 387 |  | 
 | 388 | 		pipe = usb_rcvintpipe(udev, ar2->ep[i]->bEndpointAddress); | 
 | 389 | 		maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | 
 | 390 | 		maxp = maxp > 4 ? 4 : maxp; | 
 | 391 |  | 
 | 392 | 		usb_fill_int_urb(ar2->urb[i], udev, pipe, ar2->buf[i], maxp, | 
 | 393 | 				 i ? ati_remote2_complete_key : ati_remote2_complete_mouse, | 
 | 394 | 				 ar2, ar2->ep[i]->bInterval); | 
 | 395 | 		ar2->urb[i]->transfer_dma = ar2->buf_dma[i]; | 
 | 396 | 		ar2->urb[i]->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 
 | 397 | 	} | 
 | 398 |  | 
 | 399 | 	return 0; | 
 | 400 | } | 
 | 401 |  | 
 | 402 | static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2) | 
 | 403 | { | 
 | 404 | 	int i; | 
 | 405 |  | 
 | 406 | 	for (i = 0; i < 2; i++) { | 
| Mariusz Kozlowski | 2381526 | 2006-11-08 15:35:50 +0100 | [diff] [blame] | 407 | 		usb_free_urb(ar2->urb[i]); | 
| Dmitry Torokhov | e37a97d | 2007-05-03 00:57:29 -0400 | [diff] [blame] | 408 | 		usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]); | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 409 | 	} | 
 | 410 | } | 
 | 411 |  | 
| Peter Stokes | a1421d3 | 2007-04-12 01:33:10 -0400 | [diff] [blame] | 412 | static int ati_remote2_setup(struct ati_remote2 *ar2) | 
 | 413 | { | 
 | 414 | 	int r, i, channel; | 
 | 415 |  | 
 | 416 | 	/* | 
 | 417 | 	 * Configure receiver to only accept input from remote "channel" | 
 | 418 | 	 *  channel == 0  -> Accept input from any remote channel | 
 | 419 | 	 *  channel == 1  -> Only accept input from remote channel 1 | 
 | 420 | 	 *  channel == 2  -> Only accept input from remote channel 2 | 
 | 421 | 	 *  ... | 
 | 422 | 	 *  channel == 16 -> Only accept input from remote channel 16 | 
 | 423 | 	 */ | 
 | 424 |  | 
 | 425 | 	channel = 0; | 
 | 426 | 	for (i = 0; i < 16; i++) { | 
 | 427 | 		if ((1 << i) & channel_mask) { | 
 | 428 | 			if (!(~(1 << i) & 0xFFFF & channel_mask)) | 
 | 429 | 				channel = i + 1; | 
 | 430 | 			break; | 
 | 431 | 		} | 
 | 432 | 	} | 
 | 433 |  | 
 | 434 | 	r = usb_control_msg(ar2->udev, usb_sndctrlpipe(ar2->udev, 0), | 
 | 435 | 			    0x20, | 
 | 436 | 			    USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, | 
 | 437 | 			    channel, 0x0, NULL, 0, USB_CTRL_SET_TIMEOUT); | 
 | 438 | 	if (r) { | 
 | 439 | 		dev_err(&ar2->udev->dev, "%s - failed to set channel due to error: %d\n", | 
 | 440 | 			__FUNCTION__, r); | 
 | 441 | 		return r; | 
 | 442 | 	} | 
 | 443 |  | 
 | 444 | 	return 0; | 
 | 445 | } | 
 | 446 |  | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 447 | static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id) | 
 | 448 | { | 
 | 449 | 	struct usb_device *udev = interface_to_usbdev(interface); | 
 | 450 | 	struct usb_host_interface *alt = interface->cur_altsetting; | 
 | 451 | 	struct ati_remote2 *ar2; | 
 | 452 | 	int r; | 
 | 453 |  | 
 | 454 | 	if (alt->desc.bInterfaceNumber) | 
 | 455 | 		return -ENODEV; | 
 | 456 |  | 
 | 457 | 	ar2 = kzalloc(sizeof (struct ati_remote2), GFP_KERNEL); | 
 | 458 | 	if (!ar2) | 
 | 459 | 		return -ENOMEM; | 
 | 460 |  | 
 | 461 | 	ar2->udev = udev; | 
 | 462 |  | 
 | 463 | 	ar2->intf[0] = interface; | 
 | 464 | 	ar2->ep[0] = &alt->endpoint[0].desc; | 
 | 465 |  | 
 | 466 | 	ar2->intf[1] = usb_ifnum_to_if(udev, 1); | 
 | 467 | 	r = usb_driver_claim_interface(&ati_remote2_driver, ar2->intf[1], ar2); | 
 | 468 | 	if (r) | 
 | 469 | 		goto fail1; | 
 | 470 | 	alt = ar2->intf[1]->cur_altsetting; | 
 | 471 | 	ar2->ep[1] = &alt->endpoint[0].desc; | 
 | 472 |  | 
 | 473 | 	r = ati_remote2_urb_init(ar2); | 
 | 474 | 	if (r) | 
 | 475 | 		goto fail2; | 
 | 476 |  | 
| Peter Stokes | a1421d3 | 2007-04-12 01:33:10 -0400 | [diff] [blame] | 477 | 	r = ati_remote2_setup(ar2); | 
 | 478 | 	if (r) | 
 | 479 | 		goto fail2; | 
 | 480 |  | 
| Ville Syrjälä | 735b0cb | 2005-12-10 20:30:54 +0200 | [diff] [blame] | 481 | 	usb_make_path(udev, ar2->phys, sizeof(ar2->phys)); | 
 | 482 | 	strlcat(ar2->phys, "/input0", sizeof(ar2->phys)); | 
 | 483 |  | 
 | 484 | 	strlcat(ar2->name, "ATI Remote Wonder II", sizeof(ar2->name)); | 
 | 485 |  | 
 | 486 | 	r = ati_remote2_input_init(ar2); | 
 | 487 | 	if (r) | 
 | 488 | 		goto fail2; | 
 | 489 |  | 
 | 490 | 	usb_set_intfdata(interface, ar2); | 
 | 491 |  | 
 | 492 | 	return 0; | 
 | 493 |  | 
 | 494 |  fail2: | 
 | 495 | 	ati_remote2_urb_cleanup(ar2); | 
 | 496 |  | 
 | 497 | 	usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); | 
 | 498 |  fail1: | 
 | 499 | 	kfree(ar2); | 
 | 500 |  | 
 | 501 | 	return r; | 
 | 502 | } | 
 | 503 |  | 
 | 504 | static void ati_remote2_disconnect(struct usb_interface *interface) | 
 | 505 | { | 
 | 506 | 	struct ati_remote2 *ar2; | 
 | 507 | 	struct usb_host_interface *alt = interface->cur_altsetting; | 
 | 508 |  | 
 | 509 | 	if (alt->desc.bInterfaceNumber) | 
 | 510 | 		return; | 
 | 511 |  | 
 | 512 | 	ar2 = usb_get_intfdata(interface); | 
 | 513 | 	usb_set_intfdata(interface, NULL); | 
 | 514 |  | 
 | 515 | 	input_unregister_device(ar2->idev); | 
 | 516 |  | 
 | 517 | 	ati_remote2_urb_cleanup(ar2); | 
 | 518 |  | 
 | 519 | 	usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); | 
 | 520 |  | 
 | 521 | 	kfree(ar2); | 
 | 522 | } | 
 | 523 |  | 
 | 524 | static int __init ati_remote2_init(void) | 
 | 525 | { | 
 | 526 | 	int r; | 
 | 527 |  | 
 | 528 | 	r = usb_register(&ati_remote2_driver); | 
 | 529 | 	if (r) | 
 | 530 | 		printk(KERN_ERR "ati_remote2: usb_register() = %d\n", r); | 
 | 531 | 	else | 
 | 532 | 		printk(KERN_INFO "ati_remote2: " DRIVER_DESC " " DRIVER_VERSION "\n"); | 
 | 533 |  | 
 | 534 | 	return r; | 
 | 535 | } | 
 | 536 |  | 
 | 537 | static void __exit ati_remote2_exit(void) | 
 | 538 | { | 
 | 539 | 	usb_deregister(&ati_remote2_driver); | 
 | 540 | } | 
 | 541 |  | 
 | 542 | module_init(ati_remote2_init); | 
 | 543 | module_exit(ati_remote2_exit); |