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