diff options
Diffstat (limited to 'bcm5974.c')
| -rw-r--r-- | bcm5974.c | 239 |
1 files changed, 124 insertions, 115 deletions
| @@ -150,11 +150,11 @@ struct bcm5974_config { | |||
| 150 | struct bcm5974 { | 150 | struct bcm5974 { |
| 151 | char phys[64]; | 151 | char phys[64]; |
| 152 | struct usb_device *udev; /* usb device */ | 152 | struct usb_device *udev; /* usb device */ |
| 153 | struct usb_interface *intf; /* our interface */ | ||
| 153 | struct input_dev *input; /* input dev */ | 154 | struct input_dev *input; /* input dev */ |
| 154 | struct bcm5974_config cfg; /* device configuration */ | 155 | struct bcm5974_config cfg; /* device configuration */ |
| 155 | struct mutex mutex; /* serialize access to open/suspend */ | 156 | struct mutex pm_mutex; /* serialize access to open/suspend */ |
| 156 | int opened; /* >0: opened, else closed */ | 157 | int opened; /* 1: opened, 0: closed */ |
| 157 | int manually_suspended; /* >0: manually suspended */ | ||
| 158 | struct urb *bt_urb; /* button usb request block */ | 158 | struct urb *bt_urb; /* button usb request block */ |
| 159 | struct bt_data *bt_data; /* button transferred data */ | 159 | struct bt_data *bt_data; /* button transferred data */ |
| 160 | struct urb *tp_urb; /* trackpad usb request block */ | 160 | struct urb *tp_urb; /* trackpad usb request block */ |
| @@ -204,9 +204,11 @@ static const struct bcm5974_config *bcm5974_get_config(struct usb_device *udev) | |||
| 204 | { | 204 | { |
| 205 | u16 id = le16_to_cpu(udev->descriptor.idProduct); | 205 | u16 id = le16_to_cpu(udev->descriptor.idProduct); |
| 206 | const struct bcm5974_config *cfg; | 206 | const struct bcm5974_config *cfg; |
| 207 | |||
| 207 | for (cfg = bcm5974_config_table; cfg->ansi; ++cfg) | 208 | for (cfg = bcm5974_config_table; cfg->ansi; ++cfg) |
| 208 | if (cfg->ansi == id || cfg->iso == id || cfg->jis == id) | 209 | if (cfg->ansi == id || cfg->iso == id || cfg->jis == id) |
| 209 | return cfg; | 210 | return cfg; |
| 211 | |||
| 210 | return bcm5974_config_table; | 212 | return bcm5974_config_table; |
| 211 | } | 213 | } |
| 212 | 214 | ||
| @@ -226,28 +228,31 @@ static inline int int2scale(const struct bcm5974_param *p, int x) | |||
| 226 | static inline int int2bound(const struct bcm5974_param *p, int x) | 228 | static inline int int2bound(const struct bcm5974_param *p, int x) |
| 227 | { | 229 | { |
| 228 | int s = int2scale(p, x); | 230 | int s = int2scale(p, x); |
| 231 | |||
| 232 | // return clamp_val(s, 0, p->dim - 1); | ||
| 229 | return s < 0 ? 0 : s >= p->dim ? p->dim - 1 : s; | 233 | return s < 0 ? 0 : s >= p->dim ? p->dim - 1 : s; |
| 230 | } | 234 | } |
| 231 | 235 | ||
| 232 | /* setup which logical events to report */ | 236 | /* setup which logical events to report */ |
| 233 | static void setup_events_to_report(struct input_dev *input_dev, | 237 | static void setup_events_to_report(struct input_dev *input_dev, |
| 234 | const struct bcm5974_config *cfg) | 238 | const struct bcm5974_config *cfg) |
| 235 | { | 239 | { |
| 236 | set_bit(EV_ABS, input_dev->evbit); | 240 | __set_bit(EV_ABS, input_dev->evbit); |
| 241 | |||
| 237 | input_set_abs_params(input_dev, ABS_PRESSURE, | 242 | input_set_abs_params(input_dev, ABS_PRESSURE, |
| 238 | 0, cfg->p.dim, cfg->p.fuzz, 0); | 243 | 0, cfg->p.dim, cfg->p.fuzz, 0); |
| 239 | input_set_abs_params(input_dev, ABS_TOOL_WIDTH, | 244 | input_set_abs_params(input_dev, ABS_TOOL_WIDTH, |
| 240 | 0, cfg->w.dim, cfg->w.fuzz, 0); | 245 | 0, cfg->w.dim, cfg->w.fuzz, 0); |
| 241 | input_set_abs_params(input_dev, ABS_X, | 246 | input_set_abs_params(input_dev, ABS_X, |
| 242 | 0, cfg->x.dim, cfg->x.fuzz, 0); | 247 | 0, cfg->x.dim, cfg->x.fuzz, 0); |
| 243 | input_set_abs_params(input_dev, ABS_Y, | 248 | input_set_abs_params(input_dev, ABS_Y, |
| 244 | 0, cfg->y.dim, cfg->y.fuzz, 0); | 249 | 0, cfg->y.dim, cfg->y.fuzz, 0); |
| 245 | 250 | ||
| 246 | set_bit(EV_KEY, input_dev->evbit); | 251 | __set_bit(EV_KEY, input_dev->evbit); |
| 247 | set_bit(BTN_TOOL_FINGER, input_dev->keybit); | 252 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); |
| 248 | set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | 253 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); |
| 249 | set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); | 254 | __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); |
| 250 | set_bit(BTN_LEFT, input_dev->keybit); | 255 | __set_bit(BTN_LEFT, input_dev->keybit); |
| 251 | } | 256 | } |
| 252 | 257 | ||
| 253 | /* report button data as logical button state */ | 258 | /* report button data as logical button state */ |
| @@ -267,38 +272,37 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
| 267 | { | 272 | { |
| 268 | const struct bcm5974_config *c = &dev->cfg; | 273 | const struct bcm5974_config *c = &dev->cfg; |
| 269 | const struct tp_finger *f = dev->tp_data->finger; | 274 | const struct tp_finger *f = dev->tp_data->finger; |
| 275 | struct input_dev *input = dev->input; | ||
| 270 | const int fingers = (size - 26) / 28; | 276 | const int fingers = (size - 26) / 28; |
| 271 | int p, w, x, y, n; | 277 | int p = 0, w, x, y, n = 0; |
| 272 | 278 | ||
| 273 | if (size < 26 || (size - 26) % 28 != 0) | 279 | if (size < 26 || (size - 26) % 28 != 0) |
| 274 | return -EIO; | 280 | return -EIO; |
| 275 | 281 | ||
| 276 | if (!fingers) { | 282 | if (fingers) { |
| 277 | input_report_abs(dev->input, ABS_PRESSURE, 0); | 283 | p = raw2int(f->force_major); |
| 278 | input_report_key(dev->input, BTN_TOOL_FINGER, false); | 284 | w = raw2int(f->size_major); |
| 279 | input_report_key(dev->input, BTN_TOOL_DOUBLETAP, false); | 285 | x = raw2int(f->abs_x); |
| 280 | input_report_key(dev->input, BTN_TOOL_TRIPLETAP, false); | 286 | y = raw2int(f->abs_y); |
| 281 | input_sync(dev->input); | 287 | n = p > 0 ? fingers : 0; |
| 282 | return 0; | 288 | |
| 289 | dprintk(9, | ||
| 290 | "bcm5974: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n", | ||
| 291 | p, w, x, y, n); | ||
| 292 | |||
| 293 | input_report_abs(input, ABS_TOOL_WIDTH, int2bound(&c->w, w)); | ||
| 294 | input_report_abs(input, ABS_X, int2bound(&c->x, x - c->x.devmin)); | ||
| 295 | input_report_abs(input, ABS_Y, int2bound(&c->y, c->y.devmax - y)); | ||
| 283 | } | 296 | } |
| 284 | 297 | ||
| 285 | p = raw2int(f->force_major); | 298 | input_report_abs(input, ABS_PRESSURE, int2bound(&c->p, p)); |
| 286 | w = raw2int(f->size_major); | 299 | |
| 287 | x = raw2int(f->abs_x); | 300 | input_report_key(input, BTN_TOOL_FINGER, n == 1); |
| 288 | y = raw2int(f->abs_y); | 301 | input_report_key(input, BTN_TOOL_DOUBLETAP, n == 2); |
| 289 | n = p > 0 ? fingers : 0; | 302 | input_report_key(input, BTN_TOOL_TRIPLETAP, n > 2); |
| 290 | 303 | ||
| 291 | dprintk(9, "bcm5974: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n", | 304 | input_sync(input); |
| 292 | p, w, x, y, n); | 305 | |
| 293 | |||
| 294 | input_report_abs(dev->input, ABS_PRESSURE, int2bound(&c->p, p)); | ||
| 295 | input_report_abs(dev->input, ABS_TOOL_WIDTH, int2bound(&c->w, w)); | ||
| 296 | input_report_abs(dev->input, ABS_X, int2bound(&c->x, x - c->x.devmin)); | ||
| 297 | input_report_abs(dev->input, ABS_Y, int2bound(&c->y, c->y.devmax - y)); | ||
| 298 | input_report_key(dev->input, BTN_TOOL_FINGER, n == 1); | ||
| 299 | input_report_key(dev->input, BTN_TOOL_DOUBLETAP, n == 2); | ||
| 300 | input_report_key(dev->input, BTN_TOOL_TRIPLETAP, n > 2); | ||
| 301 | input_sync(dev->input); | ||
| 302 | return 0; | 306 | return 0; |
| 303 | } | 307 | } |
| 304 | 308 | ||
| @@ -312,25 +316,25 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
| 312 | static int bcm5974_wellspring_mode(struct bcm5974 *dev) | 316 | static int bcm5974_wellspring_mode(struct bcm5974 *dev) |
| 313 | { | 317 | { |
| 314 | char *data = kmalloc(8, GFP_KERNEL); | 318 | char *data = kmalloc(8, GFP_KERNEL); |
| 315 | int error = 0, size; | 319 | int retval = 0, size; |
| 316 | 320 | ||
| 317 | if (!data) { | 321 | if (!data) { |
| 318 | err("bcm5974: out of memory"); | 322 | err("bcm5974: out of memory"); |
| 319 | error = -ENOMEM; | 323 | retval = -ENOMEM; |
| 320 | goto error; | 324 | goto out; |
| 321 | } | 325 | } |
| 322 | 326 | ||
| 323 | /* read configuration */ | 327 | /* read configuration */ |
| 324 | size = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), | 328 | size = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), |
| 325 | BCM5974_WELLSPRING_MODE_READ_REQUEST_ID, | 329 | BCM5974_WELLSPRING_MODE_READ_REQUEST_ID, |
| 326 | USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | 330 | USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, |
| 327 | BCM5974_WELLSPRING_MODE_REQUEST_VALUE, | 331 | BCM5974_WELLSPRING_MODE_REQUEST_VALUE, |
| 328 | BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000); | 332 | BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000); |
| 329 | 333 | ||
| 330 | if (size != 8) { | 334 | if (size != 8) { |
| 331 | err("bcm5974: could not read from device"); | 335 | err("bcm5974: could not read from device"); |
| 332 | error = -EIO; | 336 | retval = -EIO; |
| 333 | goto error; | 337 | goto out; |
| 334 | } | 338 | } |
| 335 | 339 | ||
| 336 | /* apply the mode switch */ | 340 | /* apply the mode switch */ |
| @@ -338,28 +342,25 @@ static int bcm5974_wellspring_mode(struct bcm5974 *dev) | |||
| 338 | 342 | ||
| 339 | /* write configuration */ | 343 | /* write configuration */ |
| 340 | size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), | 344 | size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), |
| 341 | BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID, | 345 | BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID, |
| 342 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | 346 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, |
| 343 | BCM5974_WELLSPRING_MODE_REQUEST_VALUE, | 347 | BCM5974_WELLSPRING_MODE_REQUEST_VALUE, |
| 344 | BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000); | 348 | BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000); |
| 345 | 349 | ||
| 346 | if (size != 8) { | 350 | if (size != 8) { |
| 347 | err("bcm5974: could not write to device"); | 351 | err("bcm5974: could not write to device"); |
| 348 | error = -EIO; | 352 | retval = -EIO; |
| 349 | goto error; | 353 | goto out; |
| 350 | } | 354 | } |
| 351 | 355 | ||
| 352 | dprintk(2, "bcm5974: switched to wellspring mode.\n"); | 356 | dprintk(2, "bcm5974: switched to wellspring mode.\n"); |
| 353 | 357 | ||
| 358 | out: | ||
| 354 | kfree(data); | 359 | kfree(data); |
| 355 | return 0; | 360 | return retval; |
| 356 | |||
| 357 | error: | ||
| 358 | kfree(data); | ||
| 359 | return error; | ||
| 360 | } | 361 | } |
| 361 | 362 | ||
| 362 | static void irq_button(struct urb *urb) | 363 | static void bcm5974_irq_button(struct urb *urb) |
| 363 | { | 364 | { |
| 364 | struct bcm5974 *dev = urb->context; | 365 | struct bcm5974 *dev = urb->context; |
| 365 | int error; | 366 | int error; |
| @@ -388,7 +389,7 @@ exit: | |||
| 388 | err("bcm5974: button urb failed: %d", error); | 389 | err("bcm5974: button urb failed: %d", error); |
| 389 | } | 390 | } |
| 390 | 391 | ||
| 391 | static void irq_trackpad(struct urb *urb) | 392 | static void bcm5974_irq_trackpad(struct urb *urb) |
| 392 | { | 393 | { |
| 393 | struct bcm5974 *dev = urb->context; | 394 | struct bcm5974 *dev = urb->context; |
| 394 | int error; | 395 | int error; |
| @@ -439,25 +440,28 @@ exit: | |||
| 439 | * plus start_traffic, it seems easier to always do the switch when | 440 | * plus start_traffic, it seems easier to always do the switch when |
| 440 | * starting traffic on the device. | 441 | * starting traffic on the device. |
| 441 | */ | 442 | */ |
| 442 | static int start_traffic(struct bcm5974 *dev) | 443 | static int bcm5974_start_traffic(struct bcm5974 *dev) |
| 443 | { | 444 | { |
| 444 | if (bcm5974_wellspring_mode(dev)) { | 445 | if (bcm5974_wellspring_mode(dev)) { |
| 445 | dprintk(1, "bcm5974: mode switch failed\n"); | 446 | dprintk(1, "bcm5974: mode switch failed\n"); |
| 446 | goto error; | 447 | goto error; |
| 447 | } | 448 | } |
| 449 | |||
| 448 | if (usb_submit_urb(dev->bt_urb, GFP_KERNEL)) | 450 | if (usb_submit_urb(dev->bt_urb, GFP_KERNEL)) |
| 449 | goto error; | 451 | goto error; |
| 452 | |||
| 450 | if (usb_submit_urb(dev->tp_urb, GFP_KERNEL)) | 453 | if (usb_submit_urb(dev->tp_urb, GFP_KERNEL)) |
| 451 | goto err_kill_bt; | 454 | goto err_kill_bt; |
| 452 | 455 | ||
| 453 | return 0; | 456 | return 0; |
| 457 | |||
| 454 | err_kill_bt: | 458 | err_kill_bt: |
| 455 | usb_kill_urb(dev->bt_urb); | 459 | usb_kill_urb(dev->bt_urb); |
| 456 | error: | 460 | error: |
| 457 | return -EIO; | 461 | return -EIO; |
| 458 | } | 462 | } |
| 459 | 463 | ||
| 460 | static void pause_traffic(struct bcm5974 *dev) | 464 | static void bcm5974_pause_traffic(struct bcm5974 *dev) |
| 461 | { | 465 | { |
| 462 | usb_kill_urb(dev->tp_urb); | 466 | usb_kill_urb(dev->tp_urb); |
| 463 | usb_kill_urb(dev->bt_urb); | 467 | usb_kill_urb(dev->bt_urb); |
| @@ -474,15 +478,22 @@ static void pause_traffic(struct bcm5974 *dev) | |||
| 474 | static int bcm5974_open(struct input_dev *input) | 478 | static int bcm5974_open(struct input_dev *input) |
| 475 | { | 479 | { |
| 476 | struct bcm5974 *dev = input_get_drvdata(input); | 480 | struct bcm5974 *dev = input_get_drvdata(input); |
| 477 | int error = 0; | 481 | int error; |
| 482 | |||
| 483 | error = usb_autopm_get_interface(dev->intf); | ||
| 484 | if (error) | ||
| 485 | return error; | ||
| 486 | |||
| 487 | mutex_lock(&dev->pm_mutex); | ||
| 478 | 488 | ||
| 479 | mutex_lock(&dev->mutex); | 489 | error = bcm5974_start_traffic(dev); |
| 480 | if (dev->manually_suspended) | 490 | if (!error) |
| 481 | error = -EACCES; | 491 | dev->opened = 1; |
| 482 | else if (!dev->opened) | 492 | |
| 483 | error = start_traffic(dev); | 493 | mutex_unlock(&dev->pm_mutex); |
| 484 | dev->opened = !error; | 494 | |
| 485 | mutex_unlock(&dev->mutex); | 495 | if (error) |
| 496 | usb_autopm_put_interface(dev->intf); | ||
| 486 | 497 | ||
| 487 | return error; | 498 | return error; |
| 488 | } | 499 | } |
| @@ -491,24 +502,26 @@ static void bcm5974_close(struct input_dev *input) | |||
| 491 | { | 502 | { |
| 492 | struct bcm5974 *dev = input_get_drvdata(input); | 503 | struct bcm5974 *dev = input_get_drvdata(input); |
| 493 | 504 | ||
| 494 | mutex_lock(&dev->mutex); | 505 | mutex_lock(&dev->pm_mutex); |
| 495 | if (!dev->manually_suspended) | 506 | |
| 496 | pause_traffic(dev); | 507 | bcm5974_pause_traffic(dev); |
| 497 | dev->opened = 0; | 508 | dev->opened = 0; |
| 498 | mutex_unlock(&dev->mutex); | 509 | |
| 510 | mutex_unlock(&dev->pm_mutex); | ||
| 511 | |||
| 512 | usb_autopm_put_interface(dev->intf); | ||
| 499 | } | 513 | } |
| 500 | 514 | ||
| 501 | static int bcm5974_suspend(struct usb_interface *iface, pm_message_t message) | 515 | static int bcm5974_suspend(struct usb_interface *iface, pm_message_t message) |
| 502 | { | 516 | { |
| 503 | struct bcm5974 *dev = usb_get_intfdata(iface); | 517 | struct bcm5974 *dev = usb_get_intfdata(iface); |
| 504 | 518 | ||
| 505 | if (dev) { | 519 | mutex_lock(&dev->pm_mutex); |
| 506 | mutex_lock(&dev->mutex); | 520 | |
| 507 | if (dev->opened && !dev->manually_suspended) | 521 | if (dev->opened) |
| 508 | pause_traffic(dev); | 522 | bcm5974_pause_traffic(dev); |
| 509 | dev->manually_suspended++; | 523 | |
| 510 | mutex_unlock(&dev->mutex); | 524 | mutex_unlock(&dev->pm_mutex); |
| 511 | } | ||
| 512 | 525 | ||
| 513 | return 0; | 526 | return 0; |
| 514 | } | 527 | } |
| @@ -518,22 +531,18 @@ static int bcm5974_resume(struct usb_interface *iface) | |||
| 518 | struct bcm5974 *dev = usb_get_intfdata(iface); | 531 | struct bcm5974 *dev = usb_get_intfdata(iface); |
| 519 | int error = 0; | 532 | int error = 0; |
| 520 | 533 | ||
| 521 | if (dev) { | 534 | mutex_lock(&dev->pm_mutex); |
| 522 | mutex_lock(&dev->mutex); | 535 | |
| 523 | if (dev->manually_suspended) | 536 | if (dev->opened) |
| 524 | dev->manually_suspended--; | 537 | error = bcm5974_start_traffic(dev); |
| 525 | if (dev->opened && !dev->manually_suspended) | 538 | |
| 526 | error = start_traffic(dev); | 539 | mutex_unlock(&dev->pm_mutex); |
| 527 | if (error) | ||
| 528 | dev->opened = 0; | ||
| 529 | mutex_unlock(&dev->mutex); | ||
| 530 | } | ||
| 531 | 540 | ||
| 532 | return error; | 541 | return error; |
| 533 | } | 542 | } |
| 534 | 543 | ||
| 535 | static int bcm5974_probe(struct usb_interface *iface, | 544 | static int bcm5974_probe(struct usb_interface *iface, |
| 536 | const struct usb_device_id *id) | 545 | const struct usb_device_id *id) |
| 537 | { | 546 | { |
| 538 | struct usb_device *udev = interface_to_usbdev(iface); | 547 | struct usb_device *udev = interface_to_usbdev(iface); |
| 539 | const struct bcm5974_config *cfg; | 548 | const struct bcm5974_config *cfg; |
| @@ -553,9 +562,10 @@ static int bcm5974_probe(struct usb_interface *iface, | |||
| 553 | } | 562 | } |
| 554 | 563 | ||
| 555 | dev->udev = udev; | 564 | dev->udev = udev; |
| 565 | dev->intf = iface; | ||
| 556 | dev->input = input_dev; | 566 | dev->input = input_dev; |
| 557 | dev->cfg = *cfg; | 567 | dev->cfg = *cfg; |
| 558 | mutex_init(&dev->mutex); | 568 | mutex_init(&dev->pm_mutex); |
| 559 | 569 | ||
| 560 | /* setup urbs */ | 570 | /* setup urbs */ |
| 561 | dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL); | 571 | dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL); |
| @@ -567,26 +577,26 @@ static int bcm5974_probe(struct usb_interface *iface, | |||
| 567 | goto err_free_bt_urb; | 577 | goto err_free_bt_urb; |
| 568 | 578 | ||
| 569 | dev->bt_data = usb_buffer_alloc(dev->udev, | 579 | dev->bt_data = usb_buffer_alloc(dev->udev, |
| 570 | dev->cfg.bt_datalen, GFP_KERNEL, | 580 | dev->cfg.bt_datalen, GFP_KERNEL, |
| 571 | &dev->bt_urb->transfer_dma); | 581 | &dev->bt_urb->transfer_dma); |
| 572 | if (!dev->bt_data) | 582 | if (!dev->bt_data) |
| 573 | goto err_free_urb; | 583 | goto err_free_urb; |
| 574 | 584 | ||
| 575 | dev->tp_data = usb_buffer_alloc(dev->udev, | 585 | dev->tp_data = usb_buffer_alloc(dev->udev, |
| 576 | dev->cfg.tp_datalen, GFP_KERNEL, | 586 | dev->cfg.tp_datalen, GFP_KERNEL, |
| 577 | &dev->tp_urb->transfer_dma); | 587 | &dev->tp_urb->transfer_dma); |
| 578 | if (!dev->tp_data) | 588 | if (!dev->tp_data) |
| 579 | goto err_free_bt_buffer; | 589 | goto err_free_bt_buffer; |
| 580 | 590 | ||
| 581 | usb_fill_int_urb(dev->bt_urb, udev, | 591 | usb_fill_int_urb(dev->bt_urb, udev, |
| 582 | usb_rcvintpipe(udev, cfg->bt_ep), | 592 | usb_rcvintpipe(udev, cfg->bt_ep), |
| 583 | dev->bt_data, dev->cfg.bt_datalen, | 593 | dev->bt_data, dev->cfg.bt_datalen, |
| 584 | irq_button, dev, 1); | 594 | bcm5974_irq_button, dev, 1); |
| 585 | 595 | ||
| 586 | usb_fill_int_urb(dev->tp_urb, udev, | 596 | usb_fill_int_urb(dev->tp_urb, udev, |
| 587 | usb_rcvintpipe(udev, cfg->tp_ep), | 597 | usb_rcvintpipe(udev, cfg->tp_ep), |
| 588 | dev->tp_data, dev->cfg.tp_datalen, | 598 | dev->tp_data, dev->cfg.tp_datalen, |
| 589 | irq_trackpad, dev, 1); | 599 | bcm5974_irq_trackpad, dev, 1); |
| 590 | 600 | ||
| 591 | /* create bcm5974 device */ | 601 | /* create bcm5974 device */ |
| 592 | usb_make_path(udev, dev->phys, sizeof(dev->phys)); | 602 | usb_make_path(udev, dev->phys, sizeof(dev->phys)); |
| @@ -638,24 +648,23 @@ static void bcm5974_disconnect(struct usb_interface *iface) | |||
| 638 | 648 | ||
| 639 | input_unregister_device(dev->input); | 649 | input_unregister_device(dev->input); |
| 640 | usb_buffer_free(dev->udev, dev->cfg.tp_datalen, | 650 | usb_buffer_free(dev->udev, dev->cfg.tp_datalen, |
| 641 | dev->tp_data, dev->tp_urb->transfer_dma); | 651 | dev->tp_data, dev->tp_urb->transfer_dma); |
| 642 | usb_buffer_free(dev->udev, dev->cfg.bt_datalen, | 652 | usb_buffer_free(dev->udev, dev->cfg.bt_datalen, |
| 643 | dev->bt_data, dev->bt_urb->transfer_dma); | 653 | dev->bt_data, dev->bt_urb->transfer_dma); |
| 644 | usb_free_urb(dev->tp_urb); | 654 | usb_free_urb(dev->tp_urb); |
| 645 | usb_free_urb(dev->bt_urb); | 655 | usb_free_urb(dev->bt_urb); |
| 646 | kfree(dev); | 656 | kfree(dev); |
| 647 | |||
| 648 | printk(KERN_INFO "bcm5974: disconnected\n"); | ||
| 649 | } | 657 | } |
| 650 | 658 | ||
| 651 | static struct usb_driver bcm5974_driver = { | 659 | static struct usb_driver bcm5974_driver = { |
| 652 | .name = "bcm5974", | 660 | .name = "bcm5974", |
| 653 | .probe = bcm5974_probe, | 661 | .probe = bcm5974_probe, |
| 654 | .disconnect = bcm5974_disconnect, | 662 | .disconnect = bcm5974_disconnect, |
| 655 | .suspend = bcm5974_suspend, | 663 | .suspend = bcm5974_suspend, |
| 656 | .resume = bcm5974_resume, | 664 | .resume = bcm5974_resume, |
| 657 | .reset_resume = bcm5974_resume, | 665 | .reset_resume = bcm5974_resume, |
| 658 | .id_table = bcm5974_table, | 666 | .id_table = bcm5974_table, |
| 667 | .supports_autosuspend = 1, | ||
| 659 | }; | 668 | }; |
| 660 | 669 | ||
| 661 | static int __init bcm5974_init(void) | 670 | static int __init bcm5974_init(void) |
