1 /**************************************************************** 2 3 Siano Mobile Silicon, Inc. 4 MDTV receiver kernel modules. 5 Copyright (C) 2005-2009, Uri Shkolnik, Anatoly Greenblat 6 7 This program is free software: you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation, either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19 20 ****************************************************************/ 21 22 #include <linux/kernel.h> 23 #include <linux/init.h> 24 #include <linux/usb.h> 25 #include <linux/firmware.h> 26 #include <linux/slab.h> 27 #include <linux/module.h> 28 29 #include "smscoreapi.h" 30 #include "sms-cards.h" 31 #include "smsendian.h" 32 33 static int sms_dbg; 34 module_param_named(debug, sms_dbg, int, 0644); 35 MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); 36 37 #define USB1_BUFFER_SIZE 0x1000 38 #define USB2_BUFFER_SIZE 0x2000 39 40 #define MAX_BUFFERS 50 41 #define MAX_URBS 10 42 43 struct smsusb_device_t; 44 45 enum smsusb_state { 46 SMSUSB_DISCONNECTED, 47 SMSUSB_SUSPENDED, 48 SMSUSB_ACTIVE 49 }; 50 51 struct smsusb_urb_t { 52 struct list_head entry; 53 struct smscore_buffer_t *cb; 54 struct smsusb_device_t *dev; 55 56 struct urb urb; 57 }; 58 59 struct smsusb_device_t { 60 struct usb_device *udev; 61 struct smscore_device_t *coredev; 62 63 struct smsusb_urb_t surbs[MAX_URBS]; 64 65 int response_alignment; 66 int buffer_size; 67 68 unsigned char in_ep; 69 unsigned char out_ep; 70 enum smsusb_state state; 71 }; 72 73 static int smsusb_submit_urb(struct smsusb_device_t *dev, 74 struct smsusb_urb_t *surb); 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 */ 84 static void smsusb_onresponse(struct urb *urb) 85 { 86 struct smsusb_urb_t *surb = (struct smsusb_urb_t *) urb->context; 87 struct smsusb_device_t *dev = surb->dev; 88 89 if (urb->status == -ESHUTDOWN) { 90 sms_err("error, urb status %d (-ESHUTDOWN), %d bytes", 91 urb->status, urb->actual_length); 92 return; 93 } 94 95 if ((urb->actual_length > 0) && (urb->status == 0)) { 96 struct sms_msg_hdr *phdr = (struct sms_msg_hdr *)surb->cb->p; 97 98 smsendian_handle_message_header(phdr); 99 if (urb->actual_length >= phdr->msg_length) { 100 surb->cb->size = phdr->msg_length; 101 102 if (dev->response_alignment && 103 (phdr->msg_flags & MSG_HDR_FLAG_SPLIT_MSG)) { 104 105 surb->cb->offset = 106 dev->response_alignment + 107 ((phdr->msg_flags >> 8) & 3); 108 109 /* sanity check */ 110 if (((int) phdr->msg_length + 111 surb->cb->offset) > urb->actual_length) { 112 sms_err("invalid response " 113 "msglen %d offset %d " 114 "size %d", 115 phdr->msg_length, 116 surb->cb->offset, 117 urb->actual_length); 118 goto exit_and_resubmit; 119 } 120 121 /* move buffer pointer and 122 * copy header to its new location */ 123 memcpy((char *) phdr + surb->cb->offset, 124 phdr, sizeof(struct sms_msg_hdr)); 125 } else 126 surb->cb->offset = 0; 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 134 smscore_onresponse(dev->coredev, surb->cb); 135 surb->cb = NULL; 136 } else { 137 sms_err("invalid response " 138 "msglen %d actual %d", 139 phdr->msg_length, urb->actual_length); 140 } 141 } else 142 sms_err("error, urb status %d, %d bytes", 143 urb->status, urb->actual_length); 144 145 146 exit_and_resubmit: 147 smsusb_submit_urb(dev, surb); 148 } 149 150 static int smsusb_submit_urb(struct smsusb_device_t *dev, 151 struct smsusb_urb_t *surb) 152 { 153 if (!surb->cb) { 154 surb->cb = smscore_getbuffer(dev->coredev); 155 if (!surb->cb) { 156 sms_err("smscore_getbuffer(...) returned NULL"); 157 return -ENOMEM; 158 } 159 } 160 161 usb_fill_bulk_urb( 162 &surb->urb, 163 dev->udev, 164 usb_rcvbulkpipe(dev->udev, dev->in_ep), 165 surb->cb->p, 166 dev->buffer_size, 167 smsusb_onresponse, 168 surb 169 ); 170 surb->urb.transfer_dma = surb->cb->phys; 171 surb->urb.transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 172 173 return usb_submit_urb(&surb->urb, GFP_ATOMIC); 174 } 175 176 static void smsusb_stop_streaming(struct smsusb_device_t *dev) 177 { 178 int i; 179 180 for (i = 0; i < MAX_URBS; i++) { 181 usb_kill_urb(&dev->surbs[i].urb); 182 183 if (dev->surbs[i].cb) { 184 smscore_putbuffer(dev->coredev, dev->surbs[i].cb); 185 dev->surbs[i].cb = NULL; 186 } 187 } 188 } 189 190 static int smsusb_start_streaming(struct smsusb_device_t *dev) 191 { 192 int i, rc; 193 194 for (i = 0; i < MAX_URBS; i++) { 195 rc = smsusb_submit_urb(dev, &dev->surbs[i]); 196 if (rc < 0) { 197 sms_err("smsusb_submit_urb(...) failed"); 198 smsusb_stop_streaming(dev); 199 break; 200 } 201 } 202 203 return rc; 204 } 205 206 static int smsusb_sendrequest(void *context, void *buffer, size_t size) 207 { 208 struct smsusb_device_t *dev = (struct smsusb_device_t *) context; 209 struct sms_msg_hdr *phdr = (struct sms_msg_hdr *) buffer; 210 int dummy; 211 212 if (dev->state != SMSUSB_ACTIVE) { 213 sms_debug("Device not active yet"); 214 return -ENOENT; 215 } 216 217 sms_debug("sending %s(%d) size: %d", 218 smscore_translate_msg(phdr->msg_type), phdr->msg_type, 219 phdr->msg_length); 220 221 smsendian_handle_tx_message((struct sms_msg_data *) phdr); 222 smsendian_handle_message_header((struct sms_msg_hdr *)buffer); 223 return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2), 224 buffer, size, &dummy, 1000); 225 } 226 227 static char *smsusb1_fw_lkup[] = { 228 "dvbt_stellar_usb.inp", 229 "dvbh_stellar_usb.inp", 230 "tdmb_stellar_usb.inp", 231 "none", 232 "dvbt_bda_stellar_usb.inp", 233 }; 234 235 static inline char *sms_get_fw_name(int mode, int board_id) 236 { 237 char **fw = sms_get_board(board_id)->fw; 238 return (fw && fw[mode]) ? fw[mode] : smsusb1_fw_lkup[mode]; 239 } 240 241 static int smsusb1_load_firmware(struct usb_device *udev, int id, int board_id) 242 { 243 const struct firmware *fw; 244 u8 *fw_buffer; 245 int rc, dummy; 246 char *fw_filename; 247 248 if (id < 0) 249 id = sms_get_board(board_id)->default_mode; 250 251 if (id < DEVICE_MODE_DVBT || id > DEVICE_MODE_DVBT_BDA) { 252 sms_err("invalid firmware id specified %d", id); 253 return -EINVAL; 254 } 255 256 fw_filename = sms_get_fw_name(id, board_id); 257 258 rc = request_firmware(&fw, fw_filename, &udev->dev); 259 if (rc < 0) { 260 sms_warn("failed to open \"%s\" mode %d, " 261 "trying again with default firmware", fw_filename, id); 262 263 fw_filename = smsusb1_fw_lkup[id]; 264 rc = request_firmware(&fw, fw_filename, &udev->dev); 265 if (rc < 0) { 266 sms_warn("failed to open \"%s\" mode %d", 267 fw_filename, id); 268 269 return rc; 270 } 271 } 272 273 fw_buffer = kmalloc(fw->size, GFP_KERNEL); 274 if (fw_buffer) { 275 memcpy(fw_buffer, fw->data, fw->size); 276 277 rc = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 2), 278 fw_buffer, fw->size, &dummy, 1000); 279 280 sms_info("sent %zd(%d) bytes, rc %d", fw->size, dummy, rc); 281 282 kfree(fw_buffer); 283 } else { 284 sms_err("failed to allocate firmware buffer"); 285 rc = -ENOMEM; 286 } 287 sms_info("read FW %s, size=%zd", fw_filename, fw->size); 288 289 release_firmware(fw); 290 291 return rc; 292 } 293 294 static void smsusb1_detectmode(void *context, int *mode) 295 { 296 char *product_string = 297 ((struct smsusb_device_t *) context)->udev->product; 298 299 *mode = DEVICE_MODE_NONE; 300 301 if (!product_string) { 302 product_string = "none"; 303 sms_err("product string not found"); 304 } else if (strstr(product_string, "DVBH")) 305 *mode = 1; 306 else if (strstr(product_string, "BDA")) 307 *mode = 4; 308 else if (strstr(product_string, "DVBT")) 309 *mode = 0; 310 else if (strstr(product_string, "TDMB")) 311 *mode = 2; 312 313 sms_info("%d \"%s\"", *mode, product_string); 314 } 315 316 static int smsusb1_setmode(void *context, int mode) 317 { 318 struct sms_msg_hdr msg = { MSG_SW_RELOAD_REQ, 0, HIF_TASK, 319 sizeof(struct sms_msg_hdr), 0 }; 320 321 if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) { 322 sms_err("invalid firmware id specified %d", mode); 323 return -EINVAL; 324 } 325 326 return smsusb_sendrequest(context, &msg, sizeof(msg)); 327 } 328 329 static void smsusb_term_device(struct usb_interface *intf) 330 { 331 struct smsusb_device_t *dev = usb_get_intfdata(intf); 332 333 if (dev) { 334 dev->state = SMSUSB_DISCONNECTED; 335 336 smsusb_stop_streaming(dev); 337 338 /* unregister from smscore */ 339 if (dev->coredev) 340 smscore_unregister_device(dev->coredev); 341 342 sms_info("device 0x%p destroyed", dev); 343 kfree(dev); 344 } 345 346 usb_set_intfdata(intf, NULL); 347 } 348 349 static int smsusb_init_device(struct usb_interface *intf, int board_id) 350 { 351 struct smsdevice_params_t params; 352 struct smsusb_device_t *dev; 353 int i, rc; 354 355 /* create device object */ 356 dev = kzalloc(sizeof(struct smsusb_device_t), GFP_KERNEL); 357 if (!dev) { 358 sms_err("kzalloc(sizeof(struct smsusb_device_t) failed"); 359 return -ENOMEM; 360 } 361 362 memset(¶ms, 0, sizeof(params)); 363 usb_set_intfdata(intf, dev); 364 dev->udev = interface_to_usbdev(intf); 365 dev->state = SMSUSB_DISCONNECTED; 366 367 params.device_type = sms_get_board(board_id)->type; 368 369 switch (params.device_type) { 370 case SMS_STELLAR: 371 dev->buffer_size = USB1_BUFFER_SIZE; 372 373 params.setmode_handler = smsusb1_setmode; 374 params.detectmode_handler = smsusb1_detectmode; 375 break; 376 case SMS_UNKNOWN_TYPE: 377 sms_err("Unspecified sms device type!"); 378 /* fall-thru */ 379 default: 380 dev->buffer_size = USB2_BUFFER_SIZE; 381 dev->response_alignment = 382 le16_to_cpu(dev->udev->ep_in[1]->desc.wMaxPacketSize) - 383 sizeof(struct sms_msg_hdr); 384 385 params.flags |= SMS_DEVICE_FAMILY2; 386 break; 387 } 388 389 for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { 390 if (intf->cur_altsetting->endpoint[i].desc. bEndpointAddress & USB_DIR_IN) 391 dev->in_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress; 392 else 393 dev->out_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress; 394 } 395 396 sms_info("in_ep = %02x, out_ep = %02x", 397 dev->in_ep, dev->out_ep); 398 399 params.device = &dev->udev->dev; 400 params.buffer_size = dev->buffer_size; 401 params.num_buffers = MAX_BUFFERS; 402 params.sendrequest_handler = smsusb_sendrequest; 403 params.context = dev; 404 usb_make_path(dev->udev, params.devpath, sizeof(params.devpath)); 405 406 /* register in smscore */ 407 rc = smscore_register_device(¶ms, &dev->coredev); 408 if (rc < 0) { 409 sms_err("smscore_register_device(...) failed, rc %d", rc); 410 smsusb_term_device(intf); 411 return rc; 412 } 413 414 smscore_set_board_id(dev->coredev, board_id); 415 416 dev->coredev->is_usb_device = true; 417 418 /* initialize urbs */ 419 for (i = 0; i < MAX_URBS; i++) { 420 dev->surbs[i].dev = dev; 421 usb_init_urb(&dev->surbs[i].urb); 422 } 423 424 sms_info("smsusb_start_streaming(...)."); 425 rc = smsusb_start_streaming(dev); 426 if (rc < 0) { 427 sms_err("smsusb_start_streaming(...) failed"); 428 smsusb_term_device(intf); 429 return rc; 430 } 431 432 dev->state = SMSUSB_ACTIVE; 433 434 rc = smscore_start_device(dev->coredev); 435 if (rc < 0) { 436 sms_err("smscore_start_device(...) failed"); 437 smsusb_term_device(intf); 438 return rc; 439 } 440 441 sms_info("device 0x%p created", dev); 442 443 return rc; 444 } 445 446 static int smsusb_probe(struct usb_interface *intf, 447 const struct usb_device_id *id) 448 { 449 struct usb_device *udev = interface_to_usbdev(intf); 450 char devpath[32]; 451 int i, rc; 452 453 sms_info("board id=%lu, interface number %d", 454 id->driver_info, 455 intf->cur_altsetting->desc.bInterfaceNumber); 456 457 if (sms_get_board(id->driver_info)->intf_num != 458 intf->cur_altsetting->desc.bInterfaceNumber) { 459 sms_debug("interface %d won't be used. Expecting interface %d to popup", 460 intf->cur_altsetting->desc.bInterfaceNumber, 461 sms_get_board(id->driver_info)->intf_num); 462 return -ENODEV; 463 } 464 465 if (intf->num_altsetting > 1) { 466 rc = usb_set_interface(udev, 467 intf->cur_altsetting->desc.bInterfaceNumber, 468 0); 469 if (rc < 0) { 470 sms_err("usb_set_interface failed, rc %d", rc); 471 return rc; 472 } 473 } 474 475 sms_info("smsusb_probe %d", 476 intf->cur_altsetting->desc.bInterfaceNumber); 477 for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { 478 sms_info("endpoint %d %02x %02x %d", i, 479 intf->cur_altsetting->endpoint[i].desc.bEndpointAddress, 480 intf->cur_altsetting->endpoint[i].desc.bmAttributes, 481 intf->cur_altsetting->endpoint[i].desc.wMaxPacketSize); 482 if (intf->cur_altsetting->endpoint[i].desc.bEndpointAddress & 483 USB_DIR_IN) 484 rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev, 485 intf->cur_altsetting->endpoint[i].desc.bEndpointAddress)); 486 else 487 rc = usb_clear_halt(udev, usb_sndbulkpipe(udev, 488 intf->cur_altsetting->endpoint[i].desc.bEndpointAddress)); 489 } 490 if ((udev->actconfig->desc.bNumInterfaces == 2) && 491 (intf->cur_altsetting->desc.bInterfaceNumber == 0)) { 492 sms_debug("rom interface 0 is not used"); 493 return -ENODEV; 494 } 495 496 if (id->driver_info == SMS1XXX_BOARD_SIANO_STELLAR_ROM) { 497 /* Detected a Siano Stellar uninitialized */ 498 499 snprintf(devpath, sizeof(devpath), "usb\\%d-%s", 500 udev->bus->busnum, udev->devpath); 501 sms_info("stellar device in cold state was found at %s.", devpath); 502 rc = smsusb1_load_firmware( 503 udev, smscore_registry_getmode(devpath), 504 id->driver_info); 505 506 /* This device will reset and gain another USB ID */ 507 if (!rc) 508 sms_info("stellar device now in warm state"); 509 else 510 sms_err("Failed to put stellar in warm state. Error: %d", rc); 511 512 return rc; 513 } else { 514 rc = smsusb_init_device(intf, id->driver_info); 515 } 516 517 sms_info("Device initialized with return code %d", rc); 518 sms_board_load_modules(id->driver_info); 519 return rc; 520 } 521 522 static void smsusb_disconnect(struct usb_interface *intf) 523 { 524 smsusb_term_device(intf); 525 } 526 527 static int smsusb_suspend(struct usb_interface *intf, pm_message_t msg) 528 { 529 struct smsusb_device_t *dev = usb_get_intfdata(intf); 530 printk(KERN_INFO "%s Entering status %d.\n", __func__, msg.event); 531 dev->state = SMSUSB_SUSPENDED; 532 /*smscore_set_power_mode(dev, SMS_POWER_MODE_SUSPENDED);*/ 533 smsusb_stop_streaming(dev); 534 return 0; 535 } 536 537 static int smsusb_resume(struct usb_interface *intf) 538 { 539 int rc, i; 540 struct smsusb_device_t *dev = usb_get_intfdata(intf); 541 struct usb_device *udev = interface_to_usbdev(intf); 542 543 printk(KERN_INFO "%s Entering.\n", __func__); 544 usb_clear_halt(udev, usb_rcvbulkpipe(udev, dev->in_ep)); 545 usb_clear_halt(udev, usb_sndbulkpipe(udev, dev->out_ep)); 546 547 for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) 548 printk(KERN_INFO "endpoint %d %02x %02x %d\n", i, 549 intf->cur_altsetting->endpoint[i].desc.bEndpointAddress, 550 intf->cur_altsetting->endpoint[i].desc.bmAttributes, 551 intf->cur_altsetting->endpoint[i].desc.wMaxPacketSize); 552 553 if (intf->num_altsetting > 0) { 554 rc = usb_set_interface(udev, 555 intf->cur_altsetting->desc. 556 bInterfaceNumber, 0); 557 if (rc < 0) { 558 printk(KERN_INFO "%s usb_set_interface failed, " 559 "rc %d\n", __func__, rc); 560 return rc; 561 } 562 } 563 564 smsusb_start_streaming(dev); 565 return 0; 566 } 567 568 static const struct usb_device_id smsusb_id_table[] = { 569 /* This device is only present before firmware load */ 570 { USB_DEVICE(0x187f, 0x0010), 571 .driver_info = SMS1XXX_BOARD_SIANO_STELLAR_ROM }, 572 /* This device pops up after firmware load */ 573 { USB_DEVICE(0x187f, 0x0100), 574 .driver_info = SMS1XXX_BOARD_SIANO_STELLAR }, 575 576 { USB_DEVICE(0x187f, 0x0200), 577 .driver_info = SMS1XXX_BOARD_SIANO_NOVA_A }, 578 { USB_DEVICE(0x187f, 0x0201), 579 .driver_info = SMS1XXX_BOARD_SIANO_NOVA_B }, 580 { USB_DEVICE(0x187f, 0x0300), 581 .driver_info = SMS1XXX_BOARD_SIANO_VEGA }, 582 { USB_DEVICE(0x2040, 0x1700), 583 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT }, 584 { USB_DEVICE(0x2040, 0x1800), 585 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A }, 586 { USB_DEVICE(0x2040, 0x1801), 587 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B }, 588 { USB_DEVICE(0x2040, 0x2000), 589 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD }, 590 { USB_DEVICE(0x2040, 0x2009), 591 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 }, 592 { USB_DEVICE(0x2040, 0x200a), 593 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD }, 594 { USB_DEVICE(0x2040, 0x2010), 595 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD }, 596 { USB_DEVICE(0x2040, 0x2011), 597 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD }, 598 { USB_DEVICE(0x2040, 0x2019), 599 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD }, 600 { USB_DEVICE(0x2040, 0x5500), 601 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, 602 { USB_DEVICE(0x2040, 0x5510), 603 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, 604 { USB_DEVICE(0x2040, 0x5520), 605 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, 606 { USB_DEVICE(0x2040, 0x5530), 607 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, 608 { USB_DEVICE(0x2040, 0x5580), 609 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, 610 { USB_DEVICE(0x2040, 0x5590), 611 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, 612 { USB_DEVICE(0x187f, 0x0202), 613 .driver_info = SMS1XXX_BOARD_SIANO_NICE }, 614 { USB_DEVICE(0x187f, 0x0301), 615 .driver_info = SMS1XXX_BOARD_SIANO_VENICE }, 616 { USB_DEVICE(0x2040, 0xb900), 617 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, 618 { USB_DEVICE(0x2040, 0xb910), 619 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, 620 { USB_DEVICE(0x2040, 0xb980), 621 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, 622 { USB_DEVICE(0x2040, 0xb990), 623 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, 624 { USB_DEVICE(0x2040, 0xc000), 625 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, 626 { USB_DEVICE(0x2040, 0xc010), 627 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, 628 { USB_DEVICE(0x2040, 0xc080), 629 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, 630 { USB_DEVICE(0x2040, 0xc090), 631 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, 632 { USB_DEVICE(0x2040, 0xc0a0), 633 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, 634 { USB_DEVICE(0x2040, 0xf5a0), 635 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, 636 { USB_DEVICE(0x187f, 0x0202), 637 .driver_info = SMS1XXX_BOARD_SIANO_NICE }, 638 { USB_DEVICE(0x187f, 0x0301), 639 .driver_info = SMS1XXX_BOARD_SIANO_VENICE }, 640 { USB_DEVICE(0x187f, 0x0302), 641 .driver_info = SMS1XXX_BOARD_SIANO_VENICE }, 642 { USB_DEVICE(0x187f, 0x0310), 643 .driver_info = SMS1XXX_BOARD_SIANO_MING }, 644 { USB_DEVICE(0x187f, 0x0500), 645 .driver_info = SMS1XXX_BOARD_SIANO_PELE }, 646 { USB_DEVICE(0x187f, 0x0600), 647 .driver_info = SMS1XXX_BOARD_SIANO_RIO }, 648 { USB_DEVICE(0x187f, 0x0700), 649 .driver_info = SMS1XXX_BOARD_SIANO_DENVER_2160 }, 650 { USB_DEVICE(0x187f, 0x0800), 651 .driver_info = SMS1XXX_BOARD_SIANO_DENVER_1530 }, 652 { USB_DEVICE(0x19D2, 0x0086), 653 .driver_info = SMS1XXX_BOARD_ZTE_DVB_DATA_CARD }, 654 { USB_DEVICE(0x19D2, 0x0078), 655 .driver_info = SMS1XXX_BOARD_ONDA_MDTV_DATA_CARD }, 656 { USB_DEVICE(0x3275, 0x0080), 657 .driver_info = SMS1XXX_BOARD_SIANO_RIO }, 658 { } /* Terminating entry */ 659 }; 660 661 MODULE_DEVICE_TABLE(usb, smsusb_id_table); 662 663 static struct usb_driver smsusb_driver = { 664 .name = "smsusb", 665 .probe = smsusb_probe, 666 .disconnect = smsusb_disconnect, 667 .id_table = smsusb_id_table, 668 669 .suspend = smsusb_suspend, 670 .resume = smsusb_resume, 671 }; 672 673 module_usb_driver(smsusb_driver); 674 675 MODULE_DESCRIPTION("Driver for the Siano SMS1xxx USB dongle"); 676 MODULE_AUTHOR("Siano Mobile Silicon, INC. (uris@siano-ms.com)"); 677 MODULE_LICENSE("GPL"); 678