Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /****************************************************************
0003 
0004 Siano Mobile Silicon, Inc.
0005 MDTV receiver kernel modules.
0006 Copyright (C) 2005-2009, Uri Shkolnik, Anatoly Greenblat
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     /* For the bottom half */
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  * Completing URB's callback handler - bottom half (process context)
0068  * submits the URB prepared on smsusb_onresponse()
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  * Completing URB's callback handler - top half (interrupt context)
0080  * adds completing sms urb to the global surbs list and activtes the worker
0081  * thread the surb
0082  * IMPORTANT - blocking functions must not be called from here !!!
0083 
0084  * @param urb pointer to a completing urb object
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                 /* sanity check */
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                 /* move buffer pointer and
0122                  * copy header to its new location */
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         /* This function can sleep */
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         /* unregister from smscore */
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     /* create device object */
0395     dev = kzalloc(sizeof(struct smsusb_device_t), GFP_KERNEL);
0396     if (!dev)
0397         return -ENOMEM;
0398 
0399     memset(&params, 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) {  /* Missing endpoints? */
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     /* register in smscore */
0453     rc = smscore_register_device(&params, &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     /* initialize urbs */
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         /* Detected a Siano Stellar uninitialized */
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         /* This device will reset and gain another USB ID */
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     /*smscore_set_power_mode(dev, SMS_POWER_MODE_SUSPENDED);*/
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     /* This device is only present before firmware load */
0622     { USB_DEVICE(0x187f, 0x0010),
0623         .driver_info = SMS1XXX_BOARD_SIANO_STELLAR_ROM },
0624     /* This device pops up after firmware load */
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     { } /* Terminating entry */
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");