diff options
Diffstat (limited to 'drivers/usb/input/appletouch.c')
| -rw-r--r-- | drivers/usb/input/appletouch.c | 130 |
1 files changed, 68 insertions, 62 deletions
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c index e03c1c567a14..15840db092a5 100644 --- a/drivers/usb/input/appletouch.c +++ b/drivers/usb/input/appletouch.c | |||
| @@ -39,7 +39,7 @@ | |||
| 39 | #define APPLE_VENDOR_ID 0x05AC | 39 | #define APPLE_VENDOR_ID 0x05AC |
| 40 | 40 | ||
| 41 | #define ATP_DEVICE(prod) \ | 41 | #define ATP_DEVICE(prod) \ |
| 42 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ | 42 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ |
| 43 | USB_DEVICE_ID_MATCH_INT_CLASS | \ | 43 | USB_DEVICE_ID_MATCH_INT_CLASS | \ |
| 44 | USB_DEVICE_ID_MATCH_INT_PROTOCOL, \ | 44 | USB_DEVICE_ID_MATCH_INT_PROTOCOL, \ |
| 45 | .idVendor = APPLE_VENDOR_ID, \ | 45 | .idVendor = APPLE_VENDOR_ID, \ |
| @@ -78,9 +78,9 @@ MODULE_DEVICE_TABLE (usb, atp_table); | |||
| 78 | * We try to keep the touchpad aspect ratio while still doing only simple | 78 | * We try to keep the touchpad aspect ratio while still doing only simple |
| 79 | * arithmetics. | 79 | * arithmetics. |
| 80 | * The factors below give coordinates like: | 80 | * The factors below give coordinates like: |
| 81 | * 0 <= x < 960 on 12" and 15" Powerbooks | 81 | * 0 <= x < 960 on 12" and 15" Powerbooks |
| 82 | * 0 <= x < 1600 on 17" Powerbooks | 82 | * 0 <= x < 1600 on 17" Powerbooks |
| 83 | * 0 <= y < 646 | 83 | * 0 <= y < 646 |
| 84 | */ | 84 | */ |
| 85 | #define ATP_XFACT 64 | 85 | #define ATP_XFACT 64 |
| 86 | #define ATP_YFACT 43 | 86 | #define ATP_YFACT 43 |
| @@ -93,11 +93,12 @@ MODULE_DEVICE_TABLE (usb, atp_table); | |||
| 93 | 93 | ||
| 94 | /* Structure to hold all of our device specific stuff */ | 94 | /* Structure to hold all of our device specific stuff */ |
| 95 | struct atp { | 95 | struct atp { |
| 96 | char phys[64]; | ||
| 96 | struct usb_device * udev; /* usb device */ | 97 | struct usb_device * udev; /* usb device */ |
| 97 | struct urb * urb; /* usb request block */ | 98 | struct urb * urb; /* usb request block */ |
| 98 | signed char * data; /* transferred data */ | 99 | signed char * data; /* transferred data */ |
| 99 | int open; /* non-zero if opened */ | 100 | int open; /* non-zero if opened */ |
| 100 | struct input_dev input; /* input dev */ | 101 | struct input_dev *input; /* input dev */ |
| 101 | int valid; /* are the sensors valid ? */ | 102 | int valid; /* are the sensors valid ? */ |
| 102 | int x_old; /* last reported x/y, */ | 103 | int x_old; /* last reported x/y, */ |
| 103 | int y_old; /* used for smoothing */ | 104 | int y_old; /* used for smoothing */ |
| @@ -114,11 +115,11 @@ struct atp { | |||
| 114 | int i; \ | 115 | int i; \ |
| 115 | printk("appletouch: %s %lld", msg, (long long)jiffies); \ | 116 | printk("appletouch: %s %lld", msg, (long long)jiffies); \ |
| 116 | for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) \ | 117 | for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) \ |
| 117 | printk(" %02x", tab[i]); \ | 118 | printk(" %02x", tab[i]); \ |
| 118 | printk("\n"); \ | 119 | printk("\n"); \ |
| 119 | } | 120 | } |
| 120 | 121 | ||
| 121 | #define dprintk(format, a...) \ | 122 | #define dprintk(format, a...) \ |
| 122 | do { \ | 123 | do { \ |
| 123 | if (debug) printk(format, ##a); \ | 124 | if (debug) printk(format, ##a); \ |
| 124 | } while (0) | 125 | } while (0) |
| @@ -219,8 +220,8 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs) | |||
| 219 | for (i = 16; i < ATP_XSENSORS; i++) | 220 | for (i = 16; i < ATP_XSENSORS; i++) |
| 220 | if (dev->xy_cur[i]) { | 221 | if (dev->xy_cur[i]) { |
| 221 | printk("appletouch: 17\" model detected.\n"); | 222 | printk("appletouch: 17\" model detected.\n"); |
| 222 | input_set_abs_params(&dev->input, ABS_X, 0, | 223 | input_set_abs_params(dev->input, ABS_X, 0, |
| 223 | (ATP_XSENSORS - 1) * | 224 | (ATP_XSENSORS - 1) * |
| 224 | ATP_XFACT - 1, | 225 | ATP_XFACT - 1, |
| 225 | ATP_FUZZ, 0); | 226 | ATP_FUZZ, 0); |
| 226 | break; | 227 | break; |
| @@ -260,12 +261,12 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs) | |||
| 260 | "Xz: %3d Yz: %3d\n", | 261 | "Xz: %3d Yz: %3d\n", |
| 261 | x, y, x_z, y_z); | 262 | x, y, x_z, y_z); |
| 262 | 263 | ||
| 263 | input_report_key(&dev->input, BTN_TOUCH, 1); | 264 | input_report_key(dev->input, BTN_TOUCH, 1); |
| 264 | input_report_abs(&dev->input, ABS_X, x); | 265 | input_report_abs(dev->input, ABS_X, x); |
| 265 | input_report_abs(&dev->input, ABS_Y, y); | 266 | input_report_abs(dev->input, ABS_Y, y); |
| 266 | input_report_abs(&dev->input, ABS_PRESSURE, | 267 | input_report_abs(dev->input, ABS_PRESSURE, |
| 267 | min(ATP_PRESSURE, x_z + y_z)); | 268 | min(ATP_PRESSURE, x_z + y_z)); |
| 268 | atp_report_fingers(&dev->input, max(x_f, y_f)); | 269 | atp_report_fingers(dev->input, max(x_f, y_f)); |
| 269 | } | 270 | } |
| 270 | dev->x_old = x; | 271 | dev->x_old = x; |
| 271 | dev->y_old = y; | 272 | dev->y_old = y; |
| @@ -273,17 +274,17 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs) | |||
| 273 | else if (!x && !y) { | 274 | else if (!x && !y) { |
| 274 | 275 | ||
| 275 | dev->x_old = dev->y_old = -1; | 276 | dev->x_old = dev->y_old = -1; |
| 276 | input_report_key(&dev->input, BTN_TOUCH, 0); | 277 | input_report_key(dev->input, BTN_TOUCH, 0); |
| 277 | input_report_abs(&dev->input, ABS_PRESSURE, 0); | 278 | input_report_abs(dev->input, ABS_PRESSURE, 0); |
| 278 | atp_report_fingers(&dev->input, 0); | 279 | atp_report_fingers(dev->input, 0); |
| 279 | 280 | ||
| 280 | /* reset the accumulator on release */ | 281 | /* reset the accumulator on release */ |
| 281 | memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); | 282 | memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); |
| 282 | } | 283 | } |
| 283 | 284 | ||
| 284 | input_report_key(&dev->input, BTN_LEFT, !!dev->data[80]); | 285 | input_report_key(dev->input, BTN_LEFT, !!dev->data[80]); |
| 285 | 286 | ||
| 286 | input_sync(&dev->input); | 287 | input_sync(dev->input); |
| 287 | 288 | ||
| 288 | exit: | 289 | exit: |
| 289 | retval = usb_submit_urb(dev->urb, GFP_ATOMIC); | 290 | retval = usb_submit_urb(dev->urb, GFP_ATOMIC); |
| @@ -314,21 +315,14 @@ static void atp_close(struct input_dev *input) | |||
| 314 | 315 | ||
| 315 | static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id) | 316 | static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id) |
| 316 | { | 317 | { |
| 317 | struct atp *dev = NULL; | 318 | struct atp *dev; |
| 319 | struct input_dev *input_dev; | ||
| 320 | struct usb_device *udev = interface_to_usbdev(iface); | ||
| 318 | struct usb_host_interface *iface_desc; | 321 | struct usb_host_interface *iface_desc; |
| 319 | struct usb_endpoint_descriptor *endpoint; | 322 | struct usb_endpoint_descriptor *endpoint; |
| 320 | int int_in_endpointAddr = 0; | 323 | int int_in_endpointAddr = 0; |
| 321 | int i, retval = -ENOMEM; | 324 | int i, retval = -ENOMEM; |
| 322 | 325 | ||
| 323 | /* allocate memory for our device state and initialize it */ | ||
| 324 | dev = kmalloc(sizeof(struct atp), GFP_KERNEL); | ||
| 325 | if (dev == NULL) { | ||
| 326 | err("Out of memory"); | ||
| 327 | goto err_kmalloc; | ||
| 328 | } | ||
| 329 | memset(dev, 0, sizeof(struct atp)); | ||
| 330 | |||
| 331 | dev->udev = interface_to_usbdev(iface); | ||
| 332 | 326 | ||
| 333 | /* set up the endpoint information */ | 327 | /* set up the endpoint information */ |
| 334 | /* use only the first interrupt-in endpoint */ | 328 | /* use only the first interrupt-in endpoint */ |
| @@ -345,70 +339,82 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id | |||
| 345 | } | 339 | } |
| 346 | } | 340 | } |
| 347 | if (!int_in_endpointAddr) { | 341 | if (!int_in_endpointAddr) { |
| 348 | retval = -EIO; | ||
| 349 | err("Could not find int-in endpoint"); | 342 | err("Could not find int-in endpoint"); |
| 350 | goto err_endpoint; | 343 | return -EIO; |
| 351 | } | 344 | } |
| 352 | 345 | ||
| 353 | /* save our data pointer in this interface device */ | 346 | /* allocate memory for our device state and initialize it */ |
| 354 | usb_set_intfdata(iface, dev); | 347 | dev = kzalloc(sizeof(struct atp), GFP_KERNEL); |
| 348 | input_dev = input_allocate_device(); | ||
| 349 | if (!dev || !input_dev) { | ||
| 350 | err("Out of memory"); | ||
| 351 | goto err_free_devs; | ||
| 352 | } | ||
| 353 | |||
| 354 | dev->udev = udev; | ||
| 355 | dev->input = input_dev; | ||
| 355 | 356 | ||
| 356 | dev->urb = usb_alloc_urb(0, GFP_KERNEL); | 357 | dev->urb = usb_alloc_urb(0, GFP_KERNEL); |
| 357 | if (!dev->urb) { | 358 | if (!dev->urb) { |
| 358 | retval = -ENOMEM; | 359 | retval = -ENOMEM; |
| 359 | goto err_usballoc; | 360 | goto err_free_devs; |
| 360 | } | 361 | } |
| 362 | |||
| 361 | dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL, | 363 | dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL, |
| 362 | &dev->urb->transfer_dma); | 364 | &dev->urb->transfer_dma); |
| 363 | if (!dev->data) { | 365 | if (!dev->data) { |
| 364 | retval = -ENOMEM; | 366 | retval = -ENOMEM; |
| 365 | goto err_usbbufalloc; | 367 | goto err_free_urb; |
| 366 | } | 368 | } |
| 367 | usb_fill_int_urb(dev->urb, dev->udev, | 369 | |
| 368 | usb_rcvintpipe(dev->udev, int_in_endpointAddr), | 370 | usb_fill_int_urb(dev->urb, udev, |
| 371 | usb_rcvintpipe(udev, int_in_endpointAddr), | ||
| 369 | dev->data, ATP_DATASIZE, atp_complete, dev, 1); | 372 | dev->data, ATP_DATASIZE, atp_complete, dev, 1); |
| 370 | 373 | ||
| 371 | init_input_dev(&dev->input); | 374 | usb_make_path(udev, dev->phys, sizeof(dev->phys)); |
| 372 | dev->input.name = "appletouch"; | 375 | strlcat(dev->phys, "/input0", sizeof(dev->phys)); |
| 373 | dev->input.dev = &iface->dev; | 376 | |
| 374 | dev->input.private = dev; | 377 | input_dev->name = "appletouch"; |
| 375 | dev->input.open = atp_open; | 378 | input_dev->phys = dev->phys; |
| 376 | dev->input.close = atp_close; | 379 | usb_to_input_id(dev->udev, &input_dev->id); |
| 380 | input_dev->cdev.dev = &iface->dev; | ||
| 377 | 381 | ||
| 378 | usb_to_input_id(dev->udev, &dev->input.id); | 382 | input_dev->private = dev; |
| 383 | input_dev->open = atp_open; | ||
| 384 | input_dev->close = atp_close; | ||
| 379 | 385 | ||
| 380 | set_bit(EV_ABS, dev->input.evbit); | 386 | set_bit(EV_ABS, input_dev->evbit); |
| 381 | 387 | ||
| 382 | /* | 388 | /* |
| 383 | * 12" and 15" Powerbooks only have 16 x sensors, | 389 | * 12" and 15" Powerbooks only have 16 x sensors, |
| 384 | * 17" models are detected later. | 390 | * 17" models are detected later. |
| 385 | */ | 391 | */ |
| 386 | input_set_abs_params(&dev->input, ABS_X, 0, | 392 | input_set_abs_params(input_dev, ABS_X, 0, |
| 387 | (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0); | 393 | (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0); |
| 388 | input_set_abs_params(&dev->input, ABS_Y, 0, | 394 | input_set_abs_params(input_dev, ABS_Y, 0, |
| 389 | (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0); | 395 | (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0); |
| 390 | input_set_abs_params(&dev->input, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0); | 396 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0); |
| 391 | 397 | ||
| 392 | set_bit(EV_KEY, dev->input.evbit); | 398 | set_bit(EV_KEY, input_dev->evbit); |
| 393 | set_bit(BTN_TOUCH, dev->input.keybit); | 399 | set_bit(BTN_TOUCH, input_dev->keybit); |
| 394 | set_bit(BTN_TOOL_FINGER, dev->input.keybit); | 400 | set_bit(BTN_TOOL_FINGER, input_dev->keybit); |
| 395 | set_bit(BTN_TOOL_DOUBLETAP, dev->input.keybit); | 401 | set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); |
| 396 | set_bit(BTN_TOOL_TRIPLETAP, dev->input.keybit); | 402 | set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); |
| 397 | set_bit(BTN_LEFT, dev->input.keybit); | 403 | set_bit(BTN_LEFT, input_dev->keybit); |
| 398 | 404 | ||
| 399 | input_register_device(&dev->input); | 405 | input_register_device(dev->input); |
| 400 | 406 | ||
| 401 | printk(KERN_INFO "input: appletouch connected\n"); | 407 | /* save our data pointer in this interface device */ |
| 408 | usb_set_intfdata(iface, dev); | ||
| 402 | 409 | ||
| 403 | return 0; | 410 | return 0; |
| 404 | 411 | ||
| 405 | err_usbbufalloc: | 412 | err_free_urb: |
| 406 | usb_free_urb(dev->urb); | 413 | usb_free_urb(dev->urb); |
| 407 | err_usballoc: | 414 | err_free_devs: |
| 408 | usb_set_intfdata(iface, NULL); | 415 | usb_set_intfdata(iface, NULL); |
| 409 | err_endpoint: | ||
| 410 | kfree(dev); | 416 | kfree(dev); |
| 411 | err_kmalloc: | 417 | input_free_device(input_dev); |
| 412 | return retval; | 418 | return retval; |
| 413 | } | 419 | } |
| 414 | 420 | ||
| @@ -419,7 +425,7 @@ static void atp_disconnect(struct usb_interface *iface) | |||
| 419 | usb_set_intfdata(iface, NULL); | 425 | usb_set_intfdata(iface, NULL); |
| 420 | if (dev) { | 426 | if (dev) { |
| 421 | usb_kill_urb(dev->urb); | 427 | usb_kill_urb(dev->urb); |
| 422 | input_unregister_device(&dev->input); | 428 | input_unregister_device(dev->input); |
| 423 | usb_free_urb(dev->urb); | 429 | usb_free_urb(dev->urb); |
| 424 | usb_buffer_free(dev->udev, ATP_DATASIZE, | 430 | usb_buffer_free(dev->udev, ATP_DATASIZE, |
| 425 | dev->data, dev->urb->transfer_dma); | 431 | dev->data, dev->urb->transfer_dma); |
