0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include "smscoreapi.h"
0012
0013 #include <linux/kernel.h>
0014 #include <linux/init.h>
0015 #include <linux/usb.h>
0016 #include <linux/firmware.h>
0017 #include <linux/slab.h>
0018 #include <linux/module.h>
0019 #include <media/media-device.h>
0020
0021 #include "sms-cards.h"
0022 #include "smsendian.h"
0023
0024 #define USB1_BUFFER_SIZE 0x1000
0025 #define USB2_BUFFER_SIZE 0x2000
0026
0027 #define MAX_BUFFERS 50
0028 #define MAX_URBS 10
0029
0030 struct smsusb_device_t;
0031
0032 enum smsusb_state {
0033 SMSUSB_DISCONNECTED,
0034 SMSUSB_SUSPENDED,
0035 SMSUSB_ACTIVE
0036 };
0037
0038 struct smsusb_urb_t {
0039 struct list_head entry;
0040 struct smscore_buffer_t *cb;
0041 struct smsusb_device_t *dev;
0042
0043 struct urb urb;
0044
0045
0046 struct work_struct wq;
0047 };
0048
0049 struct smsusb_device_t {
0050 struct usb_device *udev;
0051 struct smscore_device_t *coredev;
0052
0053 struct smsusb_urb_t surbs[MAX_URBS];
0054
0055 int response_alignment;
0056 int buffer_size;
0057
0058 unsigned char in_ep;
0059 unsigned char out_ep;
0060 enum smsusb_state state;
0061 };
0062
0063 static int smsusb_submit_urb(struct smsusb_device_t *dev,
0064 struct smsusb_urb_t *surb);
0065
0066
0067
0068
0069
0070 static void do_submit_urb(struct work_struct *work)
0071 {
0072 struct smsusb_urb_t *surb = container_of(work, struct smsusb_urb_t, wq);
0073 struct smsusb_device_t *dev = surb->dev;
0074
0075 smsusb_submit_urb(dev, surb);
0076 }
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086 static void smsusb_onresponse(struct urb *urb)
0087 {
0088 struct smsusb_urb_t *surb = (struct smsusb_urb_t *) urb->context;
0089 struct smsusb_device_t *dev = surb->dev;
0090
0091 if (urb->status == -ESHUTDOWN) {
0092 pr_err("error, urb status %d (-ESHUTDOWN), %d bytes\n",
0093 urb->status, urb->actual_length);
0094 return;
0095 }
0096
0097 if ((urb->actual_length > 0) && (urb->status == 0)) {
0098 struct sms_msg_hdr *phdr = (struct sms_msg_hdr *)surb->cb->p;
0099
0100 smsendian_handle_message_header(phdr);
0101 if (urb->actual_length >= phdr->msg_length) {
0102 surb->cb->size = phdr->msg_length;
0103
0104 if (dev->response_alignment &&
0105 (phdr->msg_flags & MSG_HDR_FLAG_SPLIT_MSG)) {
0106
0107 surb->cb->offset =
0108 dev->response_alignment +
0109 ((phdr->msg_flags >> 8) & 3);
0110
0111
0112 if (((int) phdr->msg_length +
0113 surb->cb->offset) > urb->actual_length) {
0114 pr_err("invalid response msglen %d offset %d size %d\n",
0115 phdr->msg_length,
0116 surb->cb->offset,
0117 urb->actual_length);
0118 goto exit_and_resubmit;
0119 }
0120
0121
0122
0123 memcpy((char *) phdr + surb->cb->offset,
0124 phdr, sizeof(struct sms_msg_hdr));
0125 } else
0126 surb->cb->offset = 0;
0127
0128 pr_debug("received %s(%d) size: %d\n",
0129 smscore_translate_msg(phdr->msg_type),
0130 phdr->msg_type, phdr->msg_length);
0131
0132 smsendian_handle_rx_message((struct sms_msg_data *) phdr);
0133
0134 smscore_onresponse(dev->coredev, surb->cb);
0135 surb->cb = NULL;
0136 } else {
0137 pr_err("invalid response msglen %d actual %d\n",
0138 phdr->msg_length, urb->actual_length);
0139 }
0140 } else
0141 pr_err("error, urb status %d, %d bytes\n",
0142 urb->status, urb->actual_length);
0143
0144
0145 exit_and_resubmit:
0146 INIT_WORK(&surb->wq, do_submit_urb);
0147 schedule_work(&surb->wq);
0148 }
0149
0150 static int smsusb_submit_urb(struct smsusb_device_t *dev,
0151 struct smsusb_urb_t *surb)
0152 {
0153 if (!surb->cb) {
0154
0155 surb->cb = smscore_getbuffer(dev->coredev);
0156 if (!surb->cb) {
0157 pr_err("smscore_getbuffer(...) returned NULL\n");
0158 return -ENOMEM;
0159 }
0160 }
0161
0162 usb_fill_bulk_urb(
0163 &surb->urb,
0164 dev->udev,
0165 usb_rcvbulkpipe(dev->udev, dev->in_ep),
0166 surb->cb->p,
0167 dev->buffer_size,
0168 smsusb_onresponse,
0169 surb
0170 );
0171 surb->urb.transfer_flags |= URB_FREE_BUFFER;
0172
0173 return usb_submit_urb(&surb->urb, GFP_ATOMIC);
0174 }
0175
0176 static void smsusb_stop_streaming(struct smsusb_device_t *dev)
0177 {
0178 int i;
0179
0180 for (i = 0; i < MAX_URBS; i++) {
0181 usb_kill_urb(&dev->surbs[i].urb);
0182
0183 if (dev->surbs[i].cb) {
0184 smscore_putbuffer(dev->coredev, dev->surbs[i].cb);
0185 dev->surbs[i].cb = NULL;
0186 }
0187 }
0188 }
0189
0190 static int smsusb_start_streaming(struct smsusb_device_t *dev)
0191 {
0192 int i, rc;
0193
0194 for (i = 0; i < MAX_URBS; i++) {
0195 rc = smsusb_submit_urb(dev, &dev->surbs[i]);
0196 if (rc < 0) {
0197 pr_err("smsusb_submit_urb(...) failed\n");
0198 smsusb_stop_streaming(dev);
0199 break;
0200 }
0201 }
0202
0203 return rc;
0204 }
0205
0206 static int smsusb_sendrequest(void *context, void *buffer, size_t size)
0207 {
0208 struct smsusb_device_t *dev = (struct smsusb_device_t *) context;
0209 struct sms_msg_hdr *phdr;
0210 int dummy, ret;
0211
0212 if (dev->state != SMSUSB_ACTIVE) {
0213 pr_debug("Device not active yet\n");
0214 return -ENOENT;
0215 }
0216
0217 phdr = kmemdup(buffer, size, GFP_KERNEL);
0218 if (!phdr)
0219 return -ENOMEM;
0220
0221 pr_debug("sending %s(%d) size: %d\n",
0222 smscore_translate_msg(phdr->msg_type), phdr->msg_type,
0223 phdr->msg_length);
0224
0225 smsendian_handle_tx_message((struct sms_msg_data *) phdr);
0226 smsendian_handle_message_header((struct sms_msg_hdr *)phdr);
0227 ret = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
0228 phdr, size, &dummy, 1000);
0229
0230 kfree(phdr);
0231 return ret;
0232 }
0233
0234 static char *smsusb1_fw_lkup[] = {
0235 "dvbt_stellar_usb.inp",
0236 "dvbh_stellar_usb.inp",
0237 "tdmb_stellar_usb.inp",
0238 "none",
0239 "dvbt_bda_stellar_usb.inp",
0240 };
0241
0242 static inline char *sms_get_fw_name(int mode, int board_id)
0243 {
0244 char **fw = sms_get_board(board_id)->fw;
0245 return (fw && fw[mode]) ? fw[mode] : smsusb1_fw_lkup[mode];
0246 }
0247
0248 static int smsusb1_load_firmware(struct usb_device *udev, int id, int board_id)
0249 {
0250 const struct firmware *fw;
0251 u8 *fw_buffer;
0252 int rc, dummy;
0253 char *fw_filename;
0254
0255 if (id < 0)
0256 id = sms_get_board(board_id)->default_mode;
0257
0258 if (id < DEVICE_MODE_DVBT || id > DEVICE_MODE_DVBT_BDA) {
0259 pr_err("invalid firmware id specified %d\n", id);
0260 return -EINVAL;
0261 }
0262
0263 fw_filename = sms_get_fw_name(id, board_id);
0264
0265 rc = request_firmware(&fw, fw_filename, &udev->dev);
0266 if (rc < 0) {
0267 pr_warn("failed to open '%s' mode %d, trying again with default firmware\n",
0268 fw_filename, id);
0269
0270 fw_filename = smsusb1_fw_lkup[id];
0271 rc = request_firmware(&fw, fw_filename, &udev->dev);
0272 if (rc < 0) {
0273 pr_warn("failed to open '%s' mode %d\n",
0274 fw_filename, id);
0275
0276 return rc;
0277 }
0278 }
0279
0280 fw_buffer = kmalloc(fw->size, GFP_KERNEL);
0281 if (fw_buffer) {
0282 memcpy(fw_buffer, fw->data, fw->size);
0283
0284 rc = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 2),
0285 fw_buffer, fw->size, &dummy, 1000);
0286
0287 pr_debug("sent %zu(%d) bytes, rc %d\n", fw->size, dummy, rc);
0288
0289 kfree(fw_buffer);
0290 } else {
0291 pr_err("failed to allocate firmware buffer\n");
0292 rc = -ENOMEM;
0293 }
0294 pr_debug("read FW %s, size=%zu\n", fw_filename, fw->size);
0295
0296 release_firmware(fw);
0297
0298 return rc;
0299 }
0300
0301 static void smsusb1_detectmode(void *context, int *mode)
0302 {
0303 char *product_string =
0304 ((struct smsusb_device_t *) context)->udev->product;
0305
0306 *mode = DEVICE_MODE_NONE;
0307
0308 if (!product_string) {
0309 product_string = "none";
0310 pr_err("product string not found\n");
0311 } else if (strstr(product_string, "DVBH"))
0312 *mode = 1;
0313 else if (strstr(product_string, "BDA"))
0314 *mode = 4;
0315 else if (strstr(product_string, "DVBT"))
0316 *mode = 0;
0317 else if (strstr(product_string, "TDMB"))
0318 *mode = 2;
0319
0320 pr_debug("%d \"%s\"\n", *mode, product_string);
0321 }
0322
0323 static int smsusb1_setmode(void *context, int mode)
0324 {
0325 struct sms_msg_hdr msg = { MSG_SW_RELOAD_REQ, 0, HIF_TASK,
0326 sizeof(struct sms_msg_hdr), 0 };
0327
0328 if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
0329 pr_err("invalid firmware id specified %d\n", mode);
0330 return -EINVAL;
0331 }
0332
0333 return smsusb_sendrequest(context, &msg, sizeof(msg));
0334 }
0335
0336 static void smsusb_term_device(struct usb_interface *intf)
0337 {
0338 struct smsusb_device_t *dev = usb_get_intfdata(intf);
0339
0340 if (dev) {
0341 dev->state = SMSUSB_DISCONNECTED;
0342
0343 smsusb_stop_streaming(dev);
0344
0345
0346 if (dev->coredev)
0347 smscore_unregister_device(dev->coredev);
0348
0349 pr_debug("device 0x%p destroyed\n", dev);
0350 kfree(dev);
0351 }
0352
0353 usb_set_intfdata(intf, NULL);
0354 }
0355
0356 static void *siano_media_device_register(struct smsusb_device_t *dev,
0357 int board_id)
0358 {
0359 #ifdef CONFIG_MEDIA_CONTROLLER_DVB
0360 struct media_device *mdev;
0361 struct usb_device *udev = dev->udev;
0362 struct sms_board *board = sms_get_board(board_id);
0363 int ret;
0364
0365 mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
0366 if (!mdev)
0367 return NULL;
0368
0369 media_device_usb_init(mdev, udev, board->name);
0370
0371 ret = media_device_register(mdev);
0372 if (ret) {
0373 media_device_cleanup(mdev);
0374 kfree(mdev);
0375 return NULL;
0376 }
0377
0378 pr_info("media controller created\n");
0379
0380 return mdev;
0381 #else
0382 return NULL;
0383 #endif
0384 }
0385
0386 static int smsusb_init_device(struct usb_interface *intf, int board_id)
0387 {
0388 struct smsdevice_params_t params;
0389 struct smsusb_device_t *dev;
0390 void *mdev;
0391 int i, rc;
0392 int align = 0;
0393
0394
0395 dev = kzalloc(sizeof(struct smsusb_device_t), GFP_KERNEL);
0396 if (!dev)
0397 return -ENOMEM;
0398
0399 memset(¶ms, 0, sizeof(params));
0400 usb_set_intfdata(intf, dev);
0401 dev->udev = interface_to_usbdev(intf);
0402 dev->state = SMSUSB_DISCONNECTED;
0403
0404 for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
0405 struct usb_endpoint_descriptor *desc =
0406 &intf->cur_altsetting->endpoint[i].desc;
0407
0408 if (desc->bEndpointAddress & USB_DIR_IN) {
0409 dev->in_ep = desc->bEndpointAddress;
0410 align = usb_endpoint_maxp(desc) - sizeof(struct sms_msg_hdr);
0411 } else {
0412 dev->out_ep = desc->bEndpointAddress;
0413 }
0414 }
0415
0416 pr_debug("in_ep = %02x, out_ep = %02x\n", dev->in_ep, dev->out_ep);
0417 if (!dev->in_ep || !dev->out_ep || align < 0) {
0418 smsusb_term_device(intf);
0419 return -ENODEV;
0420 }
0421
0422 params.device_type = sms_get_board(board_id)->type;
0423
0424 switch (params.device_type) {
0425 case SMS_STELLAR:
0426 dev->buffer_size = USB1_BUFFER_SIZE;
0427
0428 params.setmode_handler = smsusb1_setmode;
0429 params.detectmode_handler = smsusb1_detectmode;
0430 break;
0431 case SMS_UNKNOWN_TYPE:
0432 pr_err("Unspecified sms device type!\n");
0433 fallthrough;
0434 default:
0435 dev->buffer_size = USB2_BUFFER_SIZE;
0436 dev->response_alignment = align;
0437
0438 params.flags |= SMS_DEVICE_FAMILY2;
0439 break;
0440 }
0441
0442 params.device = &dev->udev->dev;
0443 params.usb_device = dev->udev;
0444 params.buffer_size = dev->buffer_size;
0445 params.num_buffers = MAX_BUFFERS;
0446 params.sendrequest_handler = smsusb_sendrequest;
0447 params.context = dev;
0448 usb_make_path(dev->udev, params.devpath, sizeof(params.devpath));
0449
0450 mdev = siano_media_device_register(dev, board_id);
0451
0452
0453 rc = smscore_register_device(¶ms, &dev->coredev, 0, mdev);
0454 if (rc < 0) {
0455 pr_err("smscore_register_device(...) failed, rc %d\n", rc);
0456 smsusb_term_device(intf);
0457 #ifdef CONFIG_MEDIA_CONTROLLER_DVB
0458 media_device_unregister(mdev);
0459 #endif
0460 kfree(mdev);
0461 return rc;
0462 }
0463
0464 smscore_set_board_id(dev->coredev, board_id);
0465
0466 dev->coredev->is_usb_device = true;
0467
0468
0469 for (i = 0; i < MAX_URBS; i++) {
0470 dev->surbs[i].dev = dev;
0471 usb_init_urb(&dev->surbs[i].urb);
0472 }
0473
0474 pr_debug("smsusb_start_streaming(...).\n");
0475 rc = smsusb_start_streaming(dev);
0476 if (rc < 0) {
0477 pr_err("smsusb_start_streaming(...) failed\n");
0478 smsusb_term_device(intf);
0479 return rc;
0480 }
0481
0482 dev->state = SMSUSB_ACTIVE;
0483
0484 rc = smscore_start_device(dev->coredev);
0485 if (rc < 0) {
0486 pr_err("smscore_start_device(...) failed\n");
0487 smsusb_term_device(intf);
0488 return rc;
0489 }
0490
0491 pr_debug("device 0x%p created\n", dev);
0492
0493 return rc;
0494 }
0495
0496 static int smsusb_probe(struct usb_interface *intf,
0497 const struct usb_device_id *id)
0498 {
0499 struct usb_device *udev = interface_to_usbdev(intf);
0500 char devpath[32];
0501 int i, rc;
0502
0503 pr_info("board id=%lu, interface number %d\n",
0504 id->driver_info,
0505 intf->cur_altsetting->desc.bInterfaceNumber);
0506
0507 if (sms_get_board(id->driver_info)->intf_num !=
0508 intf->cur_altsetting->desc.bInterfaceNumber) {
0509 pr_debug("interface %d won't be used. Expecting interface %d to popup\n",
0510 intf->cur_altsetting->desc.bInterfaceNumber,
0511 sms_get_board(id->driver_info)->intf_num);
0512 return -ENODEV;
0513 }
0514
0515 if (intf->num_altsetting > 1) {
0516 rc = usb_set_interface(udev,
0517 intf->cur_altsetting->desc.bInterfaceNumber,
0518 0);
0519 if (rc < 0) {
0520 pr_err("usb_set_interface failed, rc %d\n", rc);
0521 return rc;
0522 }
0523 }
0524
0525 pr_debug("smsusb_probe %d\n",
0526 intf->cur_altsetting->desc.bInterfaceNumber);
0527 for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
0528 pr_debug("endpoint %d %02x %02x %d\n", i,
0529 intf->cur_altsetting->endpoint[i].desc.bEndpointAddress,
0530 intf->cur_altsetting->endpoint[i].desc.bmAttributes,
0531 intf->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
0532 if (intf->cur_altsetting->endpoint[i].desc.bEndpointAddress &
0533 USB_DIR_IN)
0534 rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev,
0535 intf->cur_altsetting->endpoint[i].desc.bEndpointAddress));
0536 else
0537 rc = usb_clear_halt(udev, usb_sndbulkpipe(udev,
0538 intf->cur_altsetting->endpoint[i].desc.bEndpointAddress));
0539 }
0540 if ((udev->actconfig->desc.bNumInterfaces == 2) &&
0541 (intf->cur_altsetting->desc.bInterfaceNumber == 0)) {
0542 pr_debug("rom interface 0 is not used\n");
0543 return -ENODEV;
0544 }
0545
0546 if (id->driver_info == SMS1XXX_BOARD_SIANO_STELLAR_ROM) {
0547
0548
0549 snprintf(devpath, sizeof(devpath), "usb\\%d-%s",
0550 udev->bus->busnum, udev->devpath);
0551 pr_info("stellar device in cold state was found at %s.\n",
0552 devpath);
0553 rc = smsusb1_load_firmware(
0554 udev, smscore_registry_getmode(devpath),
0555 id->driver_info);
0556
0557
0558 if (!rc)
0559 pr_info("stellar device now in warm state\n");
0560 else
0561 pr_err("Failed to put stellar in warm state. Error: %d\n",
0562 rc);
0563
0564 return rc;
0565 } else {
0566 rc = smsusb_init_device(intf, id->driver_info);
0567 }
0568
0569 pr_info("Device initialized with return code %d\n", rc);
0570 sms_board_load_modules(id->driver_info);
0571 return rc;
0572 }
0573
0574 static void smsusb_disconnect(struct usb_interface *intf)
0575 {
0576 smsusb_term_device(intf);
0577 }
0578
0579 static int smsusb_suspend(struct usb_interface *intf, pm_message_t msg)
0580 {
0581 struct smsusb_device_t *dev = usb_get_intfdata(intf);
0582 printk(KERN_INFO "%s Entering status %d.\n", __func__, msg.event);
0583 dev->state = SMSUSB_SUSPENDED;
0584
0585 smsusb_stop_streaming(dev);
0586 return 0;
0587 }
0588
0589 static int smsusb_resume(struct usb_interface *intf)
0590 {
0591 int rc, i;
0592 struct smsusb_device_t *dev = usb_get_intfdata(intf);
0593 struct usb_device *udev = interface_to_usbdev(intf);
0594
0595 printk(KERN_INFO "%s Entering.\n", __func__);
0596 usb_clear_halt(udev, usb_rcvbulkpipe(udev, dev->in_ep));
0597 usb_clear_halt(udev, usb_sndbulkpipe(udev, dev->out_ep));
0598
0599 for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++)
0600 printk(KERN_INFO "endpoint %d %02x %02x %d\n", i,
0601 intf->cur_altsetting->endpoint[i].desc.bEndpointAddress,
0602 intf->cur_altsetting->endpoint[i].desc.bmAttributes,
0603 intf->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
0604
0605 if (intf->num_altsetting > 0) {
0606 rc = usb_set_interface(udev,
0607 intf->cur_altsetting->desc.
0608 bInterfaceNumber, 0);
0609 if (rc < 0) {
0610 printk(KERN_INFO "%s usb_set_interface failed, rc %d\n",
0611 __func__, rc);
0612 return rc;
0613 }
0614 }
0615
0616 smsusb_start_streaming(dev);
0617 return 0;
0618 }
0619
0620 static const struct usb_device_id smsusb_id_table[] = {
0621
0622 { USB_DEVICE(0x187f, 0x0010),
0623 .driver_info = SMS1XXX_BOARD_SIANO_STELLAR_ROM },
0624
0625 { USB_DEVICE(0x187f, 0x0100),
0626 .driver_info = SMS1XXX_BOARD_SIANO_STELLAR },
0627
0628 { USB_DEVICE(0x187f, 0x0200),
0629 .driver_info = SMS1XXX_BOARD_SIANO_NOVA_A },
0630 { USB_DEVICE(0x187f, 0x0201),
0631 .driver_info = SMS1XXX_BOARD_SIANO_NOVA_B },
0632 { USB_DEVICE(0x187f, 0x0300),
0633 .driver_info = SMS1XXX_BOARD_SIANO_VEGA },
0634 { USB_DEVICE(0x2040, 0x1700),
0635 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT },
0636 { USB_DEVICE(0x2040, 0x1800),
0637 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A },
0638 { USB_DEVICE(0x2040, 0x1801),
0639 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B },
0640 { USB_DEVICE(0x2040, 0x2000),
0641 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD },
0642 { USB_DEVICE(0x2040, 0x2009),
0643 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 },
0644 { USB_DEVICE(0x2040, 0x200a),
0645 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD },
0646 { USB_DEVICE(0x2040, 0x2010),
0647 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD },
0648 { USB_DEVICE(0x2040, 0x2011),
0649 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD },
0650 { USB_DEVICE(0x2040, 0x2019),
0651 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD },
0652 { USB_DEVICE(0x2040, 0x5500),
0653 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
0654 { USB_DEVICE(0x2040, 0x5510),
0655 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
0656 { USB_DEVICE(0x2040, 0x5520),
0657 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
0658 { USB_DEVICE(0x2040, 0x5530),
0659 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
0660 { USB_DEVICE(0x2040, 0x5580),
0661 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
0662 { USB_DEVICE(0x2040, 0x5590),
0663 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
0664 { USB_DEVICE(0x2040, 0xb900),
0665 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
0666 { USB_DEVICE(0x2040, 0xb910),
0667 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
0668 { USB_DEVICE(0x2040, 0xb980),
0669 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
0670 { USB_DEVICE(0x2040, 0xb990),
0671 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
0672 { USB_DEVICE(0x2040, 0xc000),
0673 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
0674 { USB_DEVICE(0x2040, 0xc010),
0675 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
0676 { USB_DEVICE(0x2040, 0xc080),
0677 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
0678 { USB_DEVICE(0x2040, 0xc090),
0679 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
0680 { USB_DEVICE(0x2040, 0xc0a0),
0681 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
0682 { USB_DEVICE(0x2040, 0xf5a0),
0683 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
0684 { USB_DEVICE(0x187f, 0x0202),
0685 .driver_info = SMS1XXX_BOARD_SIANO_NICE },
0686 { USB_DEVICE(0x187f, 0x0301),
0687 .driver_info = SMS1XXX_BOARD_SIANO_VENICE },
0688 { USB_DEVICE(0x187f, 0x0302),
0689 .driver_info = SMS1XXX_BOARD_SIANO_VENICE },
0690 { USB_DEVICE(0x187f, 0x0310),
0691 .driver_info = SMS1XXX_BOARD_SIANO_MING },
0692 { USB_DEVICE(0x187f, 0x0500),
0693 .driver_info = SMS1XXX_BOARD_SIANO_PELE },
0694 { USB_DEVICE(0x187f, 0x0600),
0695 .driver_info = SMS1XXX_BOARD_SIANO_RIO },
0696 { USB_DEVICE(0x187f, 0x0700),
0697 .driver_info = SMS1XXX_BOARD_SIANO_DENVER_2160 },
0698 { USB_DEVICE(0x187f, 0x0800),
0699 .driver_info = SMS1XXX_BOARD_SIANO_DENVER_1530 },
0700 { USB_DEVICE(0x19D2, 0x0086),
0701 .driver_info = SMS1XXX_BOARD_ZTE_DVB_DATA_CARD },
0702 { USB_DEVICE(0x19D2, 0x0078),
0703 .driver_info = SMS1XXX_BOARD_ONDA_MDTV_DATA_CARD },
0704 { USB_DEVICE(0x3275, 0x0080),
0705 .driver_info = SMS1XXX_BOARD_SIANO_RIO },
0706 { USB_DEVICE(0x2013, 0x0257),
0707 .driver_info = SMS1XXX_BOARD_PCTV_77E },
0708 { }
0709 };
0710
0711 MODULE_DEVICE_TABLE(usb, smsusb_id_table);
0712
0713 static struct usb_driver smsusb_driver = {
0714 .name = "smsusb",
0715 .probe = smsusb_probe,
0716 .disconnect = smsusb_disconnect,
0717 .id_table = smsusb_id_table,
0718
0719 .suspend = smsusb_suspend,
0720 .resume = smsusb_resume,
0721 };
0722
0723 module_usb_driver(smsusb_driver);
0724
0725 MODULE_DESCRIPTION("Driver for the Siano SMS1xxx USB dongle");
0726 MODULE_AUTHOR("Siano Mobile Silicon, INC. (uris@siano-ms.com)");
0727 MODULE_LICENSE("GPL");