summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES7
-rw-r--r--INSTALL4
-rw-r--r--bcm5974-dkms-mkdeb/debian/changelog7
-rw-r--r--bcm5974.c239
-rw-r--r--dkms.conf2
5 files changed, 137 insertions, 122 deletions
diff --git a/CHANGES b/CHANGES
index 42031d1..0f80cb1 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,10 @@
1bcm5974 (0.59) unstable; urgency=low
2
3 * Cleanup patch from Dmitry Torokhov
4 * Auto-suspend patch from Dmitry Torokhov
5
6 -- Henrik Rydberg <rydberg@euromail.se> Fri, 25 Jul 2008 20:14:05 +0200
7
1bcm5974 (0.58) unstable; urgency=low 8bcm5974 (0.58) unstable; urgency=low
2 9
3 * Name changes; use usbhid definitions, rename atp to bcm5974 10 * Name changes; use usbhid definitions, rename atp to bcm5974
diff --git a/INSTALL b/INSTALL
index 2a2c42f..195fd05 100644
--- a/INSTALL
+++ b/INSTALL
@@ -9,7 +9,9 @@ Standing in the source directory, do:
9 9
103. sudo ./scripts/bcm5974-post-install 103. sudo ./scripts/bcm5974-post-install
11 11
124. reboot (or reload the bcm5974 module if already installed) 124. sudo depmod -a
13
145. reboot (or reload the bcm5974 module if already installed)
13 15
14For trouble-shooting, try running 16For trouble-shooting, try running
15 17
diff --git a/bcm5974-dkms-mkdeb/debian/changelog b/bcm5974-dkms-mkdeb/debian/changelog
index b0211af..9c8bd7b 100644
--- a/bcm5974-dkms-mkdeb/debian/changelog
+++ b/bcm5974-dkms-mkdeb/debian/changelog
@@ -1,9 +1,6 @@
1MODULE_NAME-dkms (MODULE_VERSION) unstable; urgency=low 1MODULE_NAME-dkms (MODULE_VERSION) unstable; urgency=low
2 2
3 * Name changes; use usbhid definitions, rename atp to bcm5974 3 * Cleanup patch from Dmitry Torokhov
4 * Input syncing moved to report functions, event type setup broken out 4 * Auto-suspend patch from Dmitry Torokhov
5 * Traffic functions added for open/close and suspend/resume logic
6 * Open/close and suspend/resume transition logic corrected
7 * Open/close serialized with respect to suspend/resume
8 5
9 -- Henrik Rydberg <rydberg@euromail.se> DATE_STAMP 6 -- Henrik Rydberg <rydberg@euromail.se> DATE_STAMP
diff --git a/bcm5974.c b/bcm5974.c
index 55c1f60..710d0ac 100644
--- a/bcm5974.c
+++ b/bcm5974.c
@@ -150,11 +150,11 @@ struct bcm5974_config {
150struct bcm5974 { 150struct 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)
226static inline int int2bound(const struct bcm5974_param *p, int x) 228static 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 */
233static void setup_events_to_report(struct input_dev *input_dev, 237static 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)
312static int bcm5974_wellspring_mode(struct bcm5974 *dev) 316static 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
357error:
358 kfree(data);
359 return error;
360} 361}
361 362
362static void irq_button(struct urb *urb) 363static 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
391static void irq_trackpad(struct urb *urb) 392static 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 */
442static int start_traffic(struct bcm5974 *dev) 443static 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
454err_kill_bt: 458err_kill_bt:
455 usb_kill_urb(dev->bt_urb); 459 usb_kill_urb(dev->bt_urb);
456error: 460error:
457 return -EIO; 461 return -EIO;
458} 462}
459 463
460static void pause_traffic(struct bcm5974 *dev) 464static 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)
474static int bcm5974_open(struct input_dev *input) 478static 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
501static int bcm5974_suspend(struct usb_interface *iface, pm_message_t message) 515static 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
535static int bcm5974_probe(struct usb_interface *iface, 544static 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
651static struct usb_driver bcm5974_driver = { 659static 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
661static int __init bcm5974_init(void) 670static int __init bcm5974_init(void)
diff --git a/dkms.conf b/dkms.conf
index 251efb1..3709c2d 100644
--- a/dkms.conf
+++ b/dkms.conf
@@ -1,5 +1,5 @@
1PACKAGE_NAME="bcm5974" 1PACKAGE_NAME="bcm5974"
2PACKAGE_VERSION="0.58" 2PACKAGE_VERSION="0.59"
3MAKE[0]="make -C ${kernel_source_dir} 3MAKE[0]="make -C ${kernel_source_dir}
4 SUBDIRS=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build modules" 4 SUBDIRS=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build modules"
5BUILT_MODULE_NAME[0]="bcm5974" 5BUILT_MODULE_NAME[0]="bcm5974"