aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/usb/siano/smsusb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/usb/siano/smsusb.c')
-rw-r--r--drivers/media/usb/siano/smsusb.c158
1 files changed, 123 insertions, 35 deletions
diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c
index de2c10289eec..03761c6f472f 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);
35MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); 35MODULE_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
43struct smsusb_device_t; 43struct smsusb_device_t;
44 44
45enum smsusb_state {
46 SMSUSB_DISCONNECTED,
47 SMSUSB_SUSPENDED,
48 SMSUSB_ACTIVE
49};
50
45struct smsusb_urb_t { 51struct 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
62static int smsusb_submit_urb(struct smsusb_device_t *dev, 73static 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 */
65static void smsusb_onresponse(struct urb *urb) 84static 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;
@@ -74,26 +93,26 @@ static void smsusb_onresponse(struct urb *urb)
74 } 93 }
75 94
76 if ((urb->actual_length > 0) && (urb->status == 0)) { 95 if ((urb->actual_length > 0) && (urb->status == 0)) {
77 struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)surb->cb->p; 96 struct sms_msg_hdr *phdr = (struct sms_msg_hdr *)surb->cb->p;
78 97
79 smsendian_handle_message_header(phdr); 98 smsendian_handle_message_header(phdr);
80 if (urb->actual_length >= phdr->msgLength) { 99 if (urb->actual_length >= phdr->msg_length) {
81 surb->cb->size = phdr->msgLength; 100 surb->cb->size = phdr->msg_length;
82 101
83 if (dev->response_alignment && 102 if (dev->response_alignment &&
84 (phdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG)) { 103 (phdr->msg_flags & MSG_HDR_FLAG_SPLIT_MSG)) {
85 104
86 surb->cb->offset = 105 surb->cb->offset =
87 dev->response_alignment + 106 dev->response_alignment +
88 ((phdr->msgFlags >> 8) & 3); 107 ((phdr->msg_flags >> 8) & 3);
89 108
90 /* sanity check */ 109 /* sanity check */
91 if (((int) phdr->msgLength + 110 if (((int) phdr->msg_length +
92 surb->cb->offset) > urb->actual_length) { 111 surb->cb->offset) > urb->actual_length) {
93 sms_err("invalid response " 112 sms_err("invalid response "
94 "msglen %d offset %d " 113 "msglen %d offset %d "
95 "size %d", 114 "size %d",
96 phdr->msgLength, 115 phdr->msg_length,
97 surb->cb->offset, 116 surb->cb->offset,
98 urb->actual_length); 117 urb->actual_length);
99 goto exit_and_resubmit; 118 goto exit_and_resubmit;
@@ -102,16 +121,22 @@ static void smsusb_onresponse(struct urb *urb)
102 /* move buffer pointer and 121 /* move buffer pointer and
103 * copy header to its new location */ 122 * copy header to its new location */
104 memcpy((char *) phdr + surb->cb->offset, 123 memcpy((char *) phdr + surb->cb->offset,
105 phdr, sizeof(struct SmsMsgHdr_ST)); 124 phdr, sizeof(struct sms_msg_hdr));
106 } else 125 } else
107 surb->cb->offset = 0; 126 surb->cb->offset = 0;
108 127
128 sms_debug("received %s(%d) size: %d",
129 smscore_translate_msg(phdr->msg_type),
130 phdr->msg_type, phdr->msg_length);
131
132 smsendian_handle_rx_message((struct sms_msg_data *) phdr);
133
109 smscore_onresponse(dev->coredev, surb->cb); 134 smscore_onresponse(dev->coredev, surb->cb);
110 surb->cb = NULL; 135 surb->cb = NULL;
111 } else { 136 } else {
112 sms_err("invalid response " 137 sms_err("invalid response "
113 "msglen %d actual %d", 138 "msglen %d actual %d",
114 phdr->msgLength, urb->actual_length); 139 phdr->msg_length, urb->actual_length);
115 } 140 }
116 } else 141 } else
117 sms_err("error, urb status %d, %d bytes", 142 sms_err("error, urb status %d, %d bytes",
@@ -136,7 +161,7 @@ static int smsusb_submit_urb(struct smsusb_device_t *dev,
136 usb_fill_bulk_urb( 161 usb_fill_bulk_urb(
137 &surb->urb, 162 &surb->urb,
138 dev->udev, 163 dev->udev,
139 usb_rcvbulkpipe(dev->udev, 0x81), 164 usb_rcvbulkpipe(dev->udev, dev->in_ep),
140 surb->cb->p, 165 surb->cb->p,
141 dev->buffer_size, 166 dev->buffer_size,
142 smsusb_onresponse, 167 smsusb_onresponse,
@@ -181,9 +206,18 @@ static int smsusb_start_streaming(struct smsusb_device_t *dev)
181static int smsusb_sendrequest(void *context, void *buffer, size_t size) 206static int smsusb_sendrequest(void *context, void *buffer, size_t size)
182{ 207{
183 struct smsusb_device_t *dev = (struct smsusb_device_t *) context; 208 struct smsusb_device_t *dev = (struct smsusb_device_t *) context;
209 struct sms_msg_hdr *phdr = (struct sms_msg_hdr *) buffer;
184 int dummy; 210 int dummy;
185 211
186 smsendian_handle_message_header((struct SmsMsgHdr_ST *)buffer); 212 if (dev->state != SMSUSB_ACTIVE)
213 return -ENOENT;
214
215 sms_debug("sending %s(%d) size: %d",
216 smscore_translate_msg(phdr->msg_type), phdr->msg_type,
217 phdr->msg_length);
218
219 smsendian_handle_tx_message((struct sms_msg_data *) phdr);
220 smsendian_handle_message_header((struct sms_msg_hdr *)buffer);
187 return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2), 221 return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
188 buffer, size, &dummy, 1000); 222 buffer, size, &dummy, 1000);
189} 223}
@@ -276,15 +310,15 @@ static void smsusb1_detectmode(void *context, int *mode)
276 310
277static int smsusb1_setmode(void *context, int mode) 311static int smsusb1_setmode(void *context, int mode)
278{ 312{
279 struct SmsMsgHdr_ST Msg = { MSG_SW_RELOAD_REQ, 0, HIF_TASK, 313 struct sms_msg_hdr msg = { MSG_SW_RELOAD_REQ, 0, HIF_TASK,
280 sizeof(struct SmsMsgHdr_ST), 0 }; 314 sizeof(struct sms_msg_hdr), 0 };
281 315
282 if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) { 316 if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
283 sms_err("invalid firmware id specified %d", mode); 317 sms_err("invalid firmware id specified %d", mode);
284 return -EINVAL; 318 return -EINVAL;
285 } 319 }
286 320
287 return smsusb_sendrequest(context, &Msg, sizeof(Msg)); 321 return smsusb_sendrequest(context, &msg, sizeof(msg));
288} 322}
289 323
290static void smsusb_term_device(struct usb_interface *intf) 324static void smsusb_term_device(struct usb_interface *intf)
@@ -292,13 +326,15 @@ static void smsusb_term_device(struct usb_interface *intf)
292 struct smsusb_device_t *dev = usb_get_intfdata(intf); 326 struct smsusb_device_t *dev = usb_get_intfdata(intf);
293 327
294 if (dev) { 328 if (dev) {
329 dev->state = SMSUSB_DISCONNECTED;
330
295 smsusb_stop_streaming(dev); 331 smsusb_stop_streaming(dev);
296 332
297 /* unregister from smscore */ 333 /* unregister from smscore */
298 if (dev->coredev) 334 if (dev->coredev)
299 smscore_unregister_device(dev->coredev); 335 smscore_unregister_device(dev->coredev);
300 336
301 sms_info("device %p destroyed", dev); 337 sms_info("device 0x%p destroyed", dev);
302 kfree(dev); 338 kfree(dev);
303 } 339 }
304 340
@@ -321,6 +357,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
321 memset(&params, 0, sizeof(params)); 357 memset(&params, 0, sizeof(params));
322 usb_set_intfdata(intf, dev); 358 usb_set_intfdata(intf, dev);
323 dev->udev = interface_to_usbdev(intf); 359 dev->udev = interface_to_usbdev(intf);
360 dev->state = SMSUSB_DISCONNECTED;
324 361
325 params.device_type = sms_get_board(board_id)->type; 362 params.device_type = sms_get_board(board_id)->type;
326 363
@@ -331,21 +368,29 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
331 params.setmode_handler = smsusb1_setmode; 368 params.setmode_handler = smsusb1_setmode;
332 params.detectmode_handler = smsusb1_detectmode; 369 params.detectmode_handler = smsusb1_detectmode;
333 break; 370 break;
334 default: 371 case SMS_UNKNOWN_TYPE:
335 sms_err("Unspecified sms device type!"); 372 sms_err("Unspecified sms device type!");
336 /* fall-thru */ 373 /* fall-thru */
337 case SMS_NOVA_A0: 374 default:
338 case SMS_NOVA_B0:
339 case SMS_VEGA:
340 dev->buffer_size = USB2_BUFFER_SIZE; 375 dev->buffer_size = USB2_BUFFER_SIZE;
341 dev->response_alignment = 376 dev->response_alignment =
342 le16_to_cpu(dev->udev->ep_in[1]->desc.wMaxPacketSize) - 377 le16_to_cpu(dev->udev->ep_in[1]->desc.wMaxPacketSize) -
343 sizeof(struct SmsMsgHdr_ST); 378 sizeof(struct sms_msg_hdr);
344 379
345 params.flags |= SMS_DEVICE_FAMILY2; 380 params.flags |= SMS_DEVICE_FAMILY2;
346 break; 381 break;
347 } 382 }
348 383
384 for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
385 if (intf->cur_altsetting->endpoint[i].desc. bEndpointAddress & USB_DIR_IN)
386 dev->in_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress;
387 else
388 dev->out_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress;
389 }
390
391 sms_info("in_ep = %02x, out_ep = %02x",
392 dev->in_ep, dev->out_ep);
393
349 params.device = &dev->udev->dev; 394 params.device = &dev->udev->dev;
350 params.buffer_size = dev->buffer_size; 395 params.buffer_size = dev->buffer_size;
351 params.num_buffers = MAX_BUFFERS; 396 params.num_buffers = MAX_BUFFERS;
@@ -363,6 +408,8 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
363 408
364 smscore_set_board_id(dev->coredev, board_id); 409 smscore_set_board_id(dev->coredev, board_id);
365 410
411 dev->coredev->is_usb_device = true;
412
366 /* initialize urbs */ 413 /* initialize urbs */
367 for (i = 0; i < MAX_URBS; i++) { 414 for (i = 0; i < MAX_URBS; i++) {
368 dev->surbs[i].dev = dev; 415 dev->surbs[i].dev = dev;
@@ -377,6 +424,8 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
377 return rc; 424 return rc;
378 } 425 }
379 426
427 dev->state = SMSUSB_ACTIVE;
428
380 rc = smscore_start_device(dev->coredev); 429 rc = smscore_start_device(dev->coredev);
381 if (rc < 0) { 430 if (rc < 0) {
382 sms_err("smscore_start_device(...) failed"); 431 sms_err("smscore_start_device(...) failed");
@@ -384,7 +433,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
384 return rc; 433 return rc;
385 } 434 }
386 435
387 sms_info("device %p created", dev); 436 sms_info("device 0x%p created", dev);
388 437
389 return rc; 438 return rc;
390} 439}
@@ -396,12 +445,21 @@ static int smsusb_probe(struct usb_interface *intf,
396 char devpath[32]; 445 char devpath[32];
397 int i, rc; 446 int i, rc;
398 447
399 rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x81)); 448 sms_info("interface number %d",
400 rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x02)); 449 intf->cur_altsetting->desc.bInterfaceNumber);
401 450
402 if (intf->num_altsetting > 0) { 451 if (sms_get_board(id->driver_info)->intf_num !=
403 rc = usb_set_interface( 452 intf->cur_altsetting->desc.bInterfaceNumber) {
404 udev, intf->cur_altsetting->desc.bInterfaceNumber, 0); 453 sms_err("interface number is %d expecting %d",
454 sms_get_board(id->driver_info)->intf_num,
455 intf->cur_altsetting->desc.bInterfaceNumber);
456 return -ENODEV;
457 }
458
459 if (intf->num_altsetting > 1) {
460 rc = usb_set_interface(udev,
461 intf->cur_altsetting->desc.bInterfaceNumber,
462 0);
405 if (rc < 0) { 463 if (rc < 0) {
406 sms_err("usb_set_interface failed, rc %d", rc); 464 sms_err("usb_set_interface failed, rc %d", rc);
407 return rc; 465 return rc;
@@ -410,19 +468,27 @@ static int smsusb_probe(struct usb_interface *intf,
410 468
411 sms_info("smsusb_probe %d", 469 sms_info("smsusb_probe %d",
412 intf->cur_altsetting->desc.bInterfaceNumber); 470 intf->cur_altsetting->desc.bInterfaceNumber);
413 for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) 471 for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
414 sms_info("endpoint %d %02x %02x %d", i, 472 sms_info("endpoint %d %02x %02x %d", i,
415 intf->cur_altsetting->endpoint[i].desc.bEndpointAddress, 473 intf->cur_altsetting->endpoint[i].desc.bEndpointAddress,
416 intf->cur_altsetting->endpoint[i].desc.bmAttributes, 474 intf->cur_altsetting->endpoint[i].desc.bmAttributes,
417 intf->cur_altsetting->endpoint[i].desc.wMaxPacketSize); 475 intf->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
418 476 if (intf->cur_altsetting->endpoint[i].desc.bEndpointAddress &
477 USB_DIR_IN)
478 rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev,
479 intf->cur_altsetting->endpoint[i].desc.bEndpointAddress));
480 else
481 rc = usb_clear_halt(udev, usb_sndbulkpipe(udev,
482 intf->cur_altsetting->endpoint[i].desc.bEndpointAddress));
483 }
419 if ((udev->actconfig->desc.bNumInterfaces == 2) && 484 if ((udev->actconfig->desc.bNumInterfaces == 2) &&
420 (intf->cur_altsetting->desc.bInterfaceNumber == 0)) { 485 (intf->cur_altsetting->desc.bInterfaceNumber == 0)) {
421 sms_err("rom interface 0 is not used"); 486 sms_err("rom interface 0 is not used");
422 return -ENODEV; 487 return -ENODEV;
423 } 488 }
424 489
425 if (intf->cur_altsetting->desc.bInterfaceNumber == 1) { 490 if (id->driver_info == SMS1XXX_BOARD_SIANO_STELLAR_ROM) {
491 sms_info("stellar device was found.");
426 snprintf(devpath, sizeof(devpath), "usb\\%d-%s", 492 snprintf(devpath, sizeof(devpath), "usb\\%d-%s",
427 udev->bus->busnum, udev->devpath); 493 udev->bus->busnum, udev->devpath);
428 sms_info("stellar device was found."); 494 sms_info("stellar device was found.");
@@ -445,7 +511,9 @@ static void smsusb_disconnect(struct usb_interface *intf)
445static int smsusb_suspend(struct usb_interface *intf, pm_message_t msg) 511static int smsusb_suspend(struct usb_interface *intf, pm_message_t msg)
446{ 512{
447 struct smsusb_device_t *dev = usb_get_intfdata(intf); 513 struct smsusb_device_t *dev = usb_get_intfdata(intf);
448 printk(KERN_INFO "%s: Entering status %d.\n", __func__, msg.event); 514 printk(KERN_INFO "%s Entering status %d.\n", __func__, msg.event);
515 dev->state = SMSUSB_SUSPENDED;
516 /*smscore_set_power_mode(dev, SMS_POWER_MODE_SUSPENDED);*/
449 smsusb_stop_streaming(dev); 517 smsusb_stop_streaming(dev);
450 return 0; 518 return 0;
451} 519}
@@ -456,9 +524,9 @@ static int smsusb_resume(struct usb_interface *intf)
456 struct smsusb_device_t *dev = usb_get_intfdata(intf); 524 struct smsusb_device_t *dev = usb_get_intfdata(intf);
457 struct usb_device *udev = interface_to_usbdev(intf); 525 struct usb_device *udev = interface_to_usbdev(intf);
458 526
459 printk(KERN_INFO "%s: Entering.\n", __func__); 527 printk(KERN_INFO "%s Entering.\n", __func__);
460 usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x81)); 528 usb_clear_halt(udev, usb_rcvbulkpipe(udev, dev->in_ep));
461 usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x02)); 529 usb_clear_halt(udev, usb_sndbulkpipe(udev, dev->out_ep));
462 530
463 for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) 531 for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++)
464 printk(KERN_INFO "endpoint %d %02x %02x %d\n", i, 532 printk(KERN_INFO "endpoint %d %02x %02x %d\n", i,
@@ -546,6 +614,26 @@ static const struct usb_device_id smsusb_id_table[] = {
546 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, 614 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
547 { USB_DEVICE(0x2040, 0xf5a0), 615 { USB_DEVICE(0x2040, 0xf5a0),
548 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, 616 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
617 { USB_DEVICE(0x187f, 0x0202),
618 .driver_info = SMS1XXX_BOARD_SIANO_NICE },
619 { USB_DEVICE(0x187f, 0x0301),
620 .driver_info = SMS1XXX_BOARD_SIANO_VENICE },
621 { USB_DEVICE(0x187f, 0x0302),
622 .driver_info = SMS1XXX_BOARD_SIANO_VENICE },
623 { USB_DEVICE(0x187f, 0x0310),
624 .driver_info = SMS1XXX_BOARD_SIANO_MING },
625 { USB_DEVICE(0x187f, 0x0500),
626 .driver_info = SMS1XXX_BOARD_SIANO_PELE },
627 { USB_DEVICE(0x187f, 0x0600),
628 .driver_info = SMS1XXX_BOARD_SIANO_RIO },
629 { USB_DEVICE(0x187f, 0x0700),
630 .driver_info = SMS1XXX_BOARD_SIANO_DENVER_2160 },
631 { USB_DEVICE(0x187f, 0x0800),
632 .driver_info = SMS1XXX_BOARD_SIANO_DENVER_1530 },
633 { USB_DEVICE(0x19D2, 0x0086),
634 .driver_info = SMS1XXX_BOARD_ZTE_DVB_DATA_CARD },
635 { USB_DEVICE(0x19D2, 0x0078),
636 .driver_info = SMS1XXX_BOARD_ONDA_MDTV_DATA_CARD },
549 { } /* Terminating entry */ 637 { } /* Terminating entry */
550 }; 638 };
551 639