diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-06 07:53:50 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-21 06:38:02 -0400 |
commit | 05f0ffbc487517a529c00119d0bfde33df509b52 (patch) | |
tree | 34f79acb84832fd5f59ac426d972533be6ee3f7a /drivers/media/usb/siano | |
parent | db30567a63db0094e03338462939031edf558cc8 (diff) |
[media] siano: use USB endpoint descriptors for in/out endp
Instead of using hardcoded descriptors, detect them from the
USB descriptors.
This patch is rebased form Doron Cohen's patch:
http://patchwork.linuxtv.org/patch/7883/
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/usb/siano')
-rw-r--r-- | drivers/media/usb/siano/smsusb.c | 99 |
1 files changed, 73 insertions, 26 deletions
diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c index 2050e4c415b1..a31bf74a5957 100644 --- a/drivers/media/usb/siano/smsusb.c +++ b/drivers/media/usb/siano/smsusb.c | |||
@@ -35,16 +35,23 @@ module_param_named(debug, sms_dbg, int, 0644); | |||
35 | MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); | 35 | MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); |
36 | 36 | ||
37 | #define USB1_BUFFER_SIZE 0x1000 | 37 | #define USB1_BUFFER_SIZE 0x1000 |
38 | #define USB2_BUFFER_SIZE 0x4000 | 38 | #define USB2_BUFFER_SIZE 0x2000 |
39 | 39 | ||
40 | #define MAX_BUFFERS 50 | 40 | #define MAX_BUFFERS 50 |
41 | #define MAX_URBS 10 | 41 | #define MAX_URBS 10 |
42 | 42 | ||
43 | struct smsusb_device_t; | 43 | struct smsusb_device_t; |
44 | 44 | ||
45 | enum smsusb_state { | ||
46 | SMSUSB_DISCONNECTED, | ||
47 | SMSUSB_SUSPENDED, | ||
48 | SMSUSB_ACTIVE | ||
49 | }; | ||
50 | |||
45 | struct smsusb_urb_t { | 51 | struct smsusb_urb_t { |
52 | struct list_head entry; | ||
46 | struct smscore_buffer_t *cb; | 53 | struct smscore_buffer_t *cb; |
47 | struct smsusb_device_t *dev; | 54 | struct smsusb_device_t *dev; |
48 | 55 | ||
49 | struct urb urb; | 56 | struct urb urb; |
50 | }; | 57 | }; |
@@ -57,11 +64,23 @@ struct smsusb_device_t { | |||
57 | 64 | ||
58 | int response_alignment; | 65 | int response_alignment; |
59 | int buffer_size; | 66 | int buffer_size; |
67 | |||
68 | unsigned char in_ep; | ||
69 | unsigned char out_ep; | ||
70 | enum smsusb_state state; | ||
60 | }; | 71 | }; |
61 | 72 | ||
62 | static int smsusb_submit_urb(struct smsusb_device_t *dev, | 73 | static int smsusb_submit_urb(struct smsusb_device_t *dev, |
63 | struct smsusb_urb_t *surb); | 74 | struct smsusb_urb_t *surb); |
64 | 75 | ||
76 | /** | ||
77 | * Completing URB's callback handler - top half (interrupt context) | ||
78 | * adds completing sms urb to the global surbs list and activtes the worker | ||
79 | * thread the surb | ||
80 | * IMPORTANT - blocking functions must not be called from here !!! | ||
81 | |||
82 | * @param urb pointer to a completing urb object | ||
83 | */ | ||
65 | static void smsusb_onresponse(struct urb *urb) | 84 | static void smsusb_onresponse(struct urb *urb) |
66 | { | 85 | { |
67 | struct smsusb_urb_t *surb = (struct smsusb_urb_t *) urb->context; | 86 | struct smsusb_urb_t *surb = (struct smsusb_urb_t *) urb->context; |
@@ -140,7 +159,7 @@ static int smsusb_submit_urb(struct smsusb_device_t *dev, | |||
140 | usb_fill_bulk_urb( | 159 | usb_fill_bulk_urb( |
141 | &surb->urb, | 160 | &surb->urb, |
142 | dev->udev, | 161 | dev->udev, |
143 | usb_rcvbulkpipe(dev->udev, 0x81), | 162 | usb_rcvbulkpipe(dev->udev, dev->in_ep), |
144 | surb->cb->p, | 163 | surb->cb->p, |
145 | dev->buffer_size, | 164 | dev->buffer_size, |
146 | smsusb_onresponse, | 165 | smsusb_onresponse, |
@@ -192,6 +211,9 @@ static int smsusb_sendrequest(void *context, void *buffer, size_t size) | |||
192 | smscore_translate_msg(phdr->msgType), phdr->msgType, | 211 | smscore_translate_msg(phdr->msgType), phdr->msgType, |
193 | phdr->msgLength); | 212 | phdr->msgLength); |
194 | 213 | ||
214 | if (dev->state != SMSUSB_ACTIVE) | ||
215 | return -ENOENT; | ||
216 | |||
195 | smsendian_handle_message_header((struct SmsMsgHdr_ST *)buffer); | 217 | smsendian_handle_message_header((struct SmsMsgHdr_ST *)buffer); |
196 | return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2), | 218 | return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2), |
197 | buffer, size, &dummy, 1000); | 219 | buffer, size, &dummy, 1000); |
@@ -301,13 +323,15 @@ static void smsusb_term_device(struct usb_interface *intf) | |||
301 | struct smsusb_device_t *dev = usb_get_intfdata(intf); | 323 | struct smsusb_device_t *dev = usb_get_intfdata(intf); |
302 | 324 | ||
303 | if (dev) { | 325 | if (dev) { |
326 | dev->state = SMSUSB_DISCONNECTED; | ||
327 | |||
304 | smsusb_stop_streaming(dev); | 328 | smsusb_stop_streaming(dev); |
305 | 329 | ||
306 | /* unregister from smscore */ | 330 | /* unregister from smscore */ |
307 | if (dev->coredev) | 331 | if (dev->coredev) |
308 | smscore_unregister_device(dev->coredev); | 332 | smscore_unregister_device(dev->coredev); |
309 | 333 | ||
310 | sms_info("device %p destroyed", dev); | 334 | sms_info("device 0x%p destroyed", dev); |
311 | kfree(dev); | 335 | kfree(dev); |
312 | } | 336 | } |
313 | 337 | ||
@@ -330,6 +354,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id) | |||
330 | memset(¶ms, 0, sizeof(params)); | 354 | memset(¶ms, 0, sizeof(params)); |
331 | usb_set_intfdata(intf, dev); | 355 | usb_set_intfdata(intf, dev); |
332 | dev->udev = interface_to_usbdev(intf); | 356 | dev->udev = interface_to_usbdev(intf); |
357 | dev->state = SMSUSB_DISCONNECTED; | ||
333 | 358 | ||
334 | params.device_type = sms_get_board(board_id)->type; | 359 | params.device_type = sms_get_board(board_id)->type; |
335 | 360 | ||
@@ -346,6 +371,8 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id) | |||
346 | case SMS_NOVA_A0: | 371 | case SMS_NOVA_A0: |
347 | case SMS_NOVA_B0: | 372 | case SMS_NOVA_B0: |
348 | case SMS_VEGA: | 373 | case SMS_VEGA: |
374 | case SMS_VENICE: | ||
375 | case SMS_DENVER_1530: | ||
349 | dev->buffer_size = USB2_BUFFER_SIZE; | 376 | dev->buffer_size = USB2_BUFFER_SIZE; |
350 | dev->response_alignment = | 377 | dev->response_alignment = |
351 | le16_to_cpu(dev->udev->ep_in[1]->desc.wMaxPacketSize) - | 378 | le16_to_cpu(dev->udev->ep_in[1]->desc.wMaxPacketSize) - |
@@ -355,6 +382,16 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id) | |||
355 | break; | 382 | break; |
356 | } | 383 | } |
357 | 384 | ||
385 | for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { | ||
386 | if (intf->cur_altsetting->endpoint[i].desc. bEndpointAddress & USB_DIR_IN) | ||
387 | dev->in_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress; | ||
388 | else | ||
389 | dev->out_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress; | ||
390 | } | ||
391 | |||
392 | sms_info("in_ep = %02x, out_ep = %02x", | ||
393 | dev->in_ep, dev->out_ep); | ||
394 | |||
358 | params.device = &dev->udev->dev; | 395 | params.device = &dev->udev->dev; |
359 | params.buffer_size = dev->buffer_size; | 396 | params.buffer_size = dev->buffer_size; |
360 | params.num_buffers = MAX_BUFFERS; | 397 | params.num_buffers = MAX_BUFFERS; |
@@ -386,6 +423,8 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id) | |||
386 | return rc; | 423 | return rc; |
387 | } | 424 | } |
388 | 425 | ||
426 | dev->state = SMSUSB_ACTIVE; | ||
427 | |||
389 | rc = smscore_start_device(dev->coredev); | 428 | rc = smscore_start_device(dev->coredev); |
390 | if (rc < 0) { | 429 | if (rc < 0) { |
391 | sms_err("smscore_start_device(...) failed"); | 430 | sms_err("smscore_start_device(...) failed"); |
@@ -393,7 +432,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id) | |||
393 | return rc; | 432 | return rc; |
394 | } | 433 | } |
395 | 434 | ||
396 | sms_info("device %p created", dev); | 435 | sms_info("device 0x%p created", dev); |
397 | 436 | ||
398 | return rc; | 437 | return rc; |
399 | } | 438 | } |
@@ -402,15 +441,23 @@ static int smsusb_probe(struct usb_interface *intf, | |||
402 | const struct usb_device_id *id) | 441 | const struct usb_device_id *id) |
403 | { | 442 | { |
404 | struct usb_device *udev = interface_to_usbdev(intf); | 443 | struct usb_device *udev = interface_to_usbdev(intf); |
405 | char devpath[32]; | ||
406 | int i, rc; | 444 | int i, rc; |
407 | 445 | ||
408 | rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x81)); | 446 | sms_info("interface number %d", |
409 | rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x02)); | 447 | intf->cur_altsetting->desc.bInterfaceNumber); |
410 | 448 | ||
411 | if (intf->num_altsetting > 0) { | 449 | if (sms_get_board(id->driver_info)->intf_num != |
412 | rc = usb_set_interface( | 450 | intf->cur_altsetting->desc.bInterfaceNumber) { |
413 | udev, intf->cur_altsetting->desc.bInterfaceNumber, 0); | 451 | sms_err("interface number is %d expecting %d", |
452 | sms_get_board(id->driver_info)->intf_num, | ||
453 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
454 | return -ENODEV; | ||
455 | } | ||
456 | |||
457 | if (intf->num_altsetting > 1) { | ||
458 | rc = usb_set_interface(udev, | ||
459 | intf->cur_altsetting->desc.bInterfaceNumber, | ||
460 | 0); | ||
414 | if (rc < 0) { | 461 | if (rc < 0) { |
415 | sms_err("usb_set_interface failed, rc %d", rc); | 462 | sms_err("usb_set_interface failed, rc %d", rc); |
416 | return rc; | 463 | return rc; |
@@ -419,27 +466,25 @@ static int smsusb_probe(struct usb_interface *intf, | |||
419 | 466 | ||
420 | sms_info("smsusb_probe %d", | 467 | sms_info("smsusb_probe %d", |
421 | intf->cur_altsetting->desc.bInterfaceNumber); | 468 | intf->cur_altsetting->desc.bInterfaceNumber); |
422 | for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) | 469 | for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { |
423 | sms_info("endpoint %d %02x %02x %d", i, | 470 | sms_info("endpoint %d %02x %02x %d", i, |
424 | intf->cur_altsetting->endpoint[i].desc.bEndpointAddress, | 471 | intf->cur_altsetting->endpoint[i].desc.bEndpointAddress, |
425 | intf->cur_altsetting->endpoint[i].desc.bmAttributes, | 472 | intf->cur_altsetting->endpoint[i].desc.bmAttributes, |
426 | intf->cur_altsetting->endpoint[i].desc.wMaxPacketSize); | 473 | intf->cur_altsetting->endpoint[i].desc.wMaxPacketSize); |
427 | 474 | if (intf->cur_altsetting->endpoint[i].desc.bEndpointAddress & | |
475 | USB_DIR_IN) | ||
476 | rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev, | ||
477 | intf->cur_altsetting->endpoint[i].desc.bEndpointAddress)); | ||
478 | else | ||
479 | rc = usb_clear_halt(udev, usb_sndbulkpipe(udev, | ||
480 | intf->cur_altsetting->endpoint[i].desc.bEndpointAddress)); | ||
481 | } | ||
428 | if ((udev->actconfig->desc.bNumInterfaces == 2) && | 482 | if ((udev->actconfig->desc.bNumInterfaces == 2) && |
429 | (intf->cur_altsetting->desc.bInterfaceNumber == 0)) { | 483 | (intf->cur_altsetting->desc.bInterfaceNumber == 0)) { |
430 | sms_err("rom interface 0 is not used"); | 484 | sms_err("rom interface 0 is not used"); |
431 | return -ENODEV; | 485 | return -ENODEV; |
432 | } | 486 | } |
433 | 487 | ||
434 | if (intf->cur_altsetting->desc.bInterfaceNumber == 1) { | ||
435 | snprintf(devpath, sizeof(devpath), "usb\\%d-%s", | ||
436 | udev->bus->busnum, udev->devpath); | ||
437 | sms_info("stellar device was found."); | ||
438 | return smsusb1_load_firmware( | ||
439 | udev, smscore_registry_getmode(devpath), | ||
440 | id->driver_info); | ||
441 | } | ||
442 | |||
443 | rc = smsusb_init_device(intf, id->driver_info); | 488 | rc = smsusb_init_device(intf, id->driver_info); |
444 | sms_info("rc %d", rc); | 489 | sms_info("rc %d", rc); |
445 | sms_board_load_modules(id->driver_info); | 490 | sms_board_load_modules(id->driver_info); |
@@ -454,7 +499,9 @@ static void smsusb_disconnect(struct usb_interface *intf) | |||
454 | static int smsusb_suspend(struct usb_interface *intf, pm_message_t msg) | 499 | static int smsusb_suspend(struct usb_interface *intf, pm_message_t msg) |
455 | { | 500 | { |
456 | struct smsusb_device_t *dev = usb_get_intfdata(intf); | 501 | struct smsusb_device_t *dev = usb_get_intfdata(intf); |
457 | printk(KERN_INFO "%s: Entering status %d.\n", __func__, msg.event); | 502 | printk(KERN_INFO "%s Entering status %d.\n", __func__, msg.event); |
503 | dev->state = SMSUSB_SUSPENDED; | ||
504 | /*smscore_set_power_mode(dev, SMS_POWER_MODE_SUSPENDED);*/ | ||
458 | smsusb_stop_streaming(dev); | 505 | smsusb_stop_streaming(dev); |
459 | return 0; | 506 | return 0; |
460 | } | 507 | } |
@@ -465,9 +512,9 @@ static int smsusb_resume(struct usb_interface *intf) | |||
465 | struct smsusb_device_t *dev = usb_get_intfdata(intf); | 512 | struct smsusb_device_t *dev = usb_get_intfdata(intf); |
466 | struct usb_device *udev = interface_to_usbdev(intf); | 513 | struct usb_device *udev = interface_to_usbdev(intf); |
467 | 514 | ||
468 | printk(KERN_INFO "%s: Entering.\n", __func__); | 515 | printk(KERN_INFO "%s Entering.\n", __func__); |
469 | usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x81)); | 516 | usb_clear_halt(udev, usb_rcvbulkpipe(udev, dev->in_ep)); |
470 | usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x02)); | 517 | usb_clear_halt(udev, usb_sndbulkpipe(udev, dev->out_ep)); |
471 | 518 | ||
472 | for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) | 519 | for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) |
473 | printk(KERN_INFO "endpoint %d %02x %02x %d\n", i, | 520 | printk(KERN_INFO "endpoint %d %02x %02x %d\n", i, |