18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* DVB USB framework compliant Linux driver for the AVerMedia AverTV DVB-T 38c2ecf20Sopenharmony_ci * USB2.0 (A800) DVB-T receiver. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@posteo.de) 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Thanks to 88c2ecf20Sopenharmony_ci * - AVerMedia who kindly provided information and 98c2ecf20Sopenharmony_ci * - Glen Harris who suffered from my mistakes during development. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci#include "dibusb.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cistatic int debug; 168c2ecf20Sopenharmony_cimodule_param(debug, int, 0644); 178c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "set debugging level (rc=1 (or-able))." DVB_USB_DEBUG_STATUS); 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ciDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define deb_rc(args...) dprintk(debug,0x01,args) 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistatic int a800_power_ctrl(struct dvb_usb_device *d, int onoff) 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci /* do nothing for the AVerMedia */ 268c2ecf20Sopenharmony_ci return 0; 278c2ecf20Sopenharmony_ci} 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci/* assure to put cold to 0 for iManufacturer == 1 */ 308c2ecf20Sopenharmony_cistatic int a800_identify_state(struct usb_device *udev, 318c2ecf20Sopenharmony_ci const struct dvb_usb_device_properties *props, 328c2ecf20Sopenharmony_ci const struct dvb_usb_device_description **desc, 338c2ecf20Sopenharmony_ci int *cold) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci *cold = udev->descriptor.iManufacturer != 1; 368c2ecf20Sopenharmony_ci return 0; 378c2ecf20Sopenharmony_ci} 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic int a800_rc_query(struct dvb_usb_device *d) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci int ret = 0; 428c2ecf20Sopenharmony_ci u8 *key = kmalloc(5, GFP_KERNEL); 438c2ecf20Sopenharmony_ci if (!key) 448c2ecf20Sopenharmony_ci return -ENOMEM; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci if (usb_control_msg(d->udev,usb_rcvctrlpipe(d->udev,0), 478c2ecf20Sopenharmony_ci 0x04, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, key, 5, 488c2ecf20Sopenharmony_ci 2000) != 5) { 498c2ecf20Sopenharmony_ci ret = -ENODEV; 508c2ecf20Sopenharmony_ci goto out; 518c2ecf20Sopenharmony_ci } 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci /* Note that extended nec and nec32 are dropped */ 548c2ecf20Sopenharmony_ci if (key[0] == 1) 558c2ecf20Sopenharmony_ci rc_keydown(d->rc_dev, RC_PROTO_NEC, 568c2ecf20Sopenharmony_ci RC_SCANCODE_NEC(key[1], key[3]), 0); 578c2ecf20Sopenharmony_ci else if (key[0] == 2) 588c2ecf20Sopenharmony_ci rc_repeat(d->rc_dev); 598c2ecf20Sopenharmony_ciout: 608c2ecf20Sopenharmony_ci kfree(key); 618c2ecf20Sopenharmony_ci return ret; 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci/* USB Driver stuff */ 658c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties a800_properties; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic int a800_probe(struct usb_interface *intf, 688c2ecf20Sopenharmony_ci const struct usb_device_id *id) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci return dvb_usb_device_init(intf, &a800_properties, 718c2ecf20Sopenharmony_ci THIS_MODULE, NULL, adapter_nr); 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci/* do not change the order of the ID table */ 758c2ecf20Sopenharmony_cistatic struct usb_device_id a800_table [] = { 768c2ecf20Sopenharmony_ci/* 00 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB2_COLD) }, 778c2ecf20Sopenharmony_ci/* 01 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB2_WARM) }, 788c2ecf20Sopenharmony_ci { } /* Terminating entry */ 798c2ecf20Sopenharmony_ci}; 808c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE (usb, a800_table); 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistatic struct dvb_usb_device_properties a800_properties = { 838c2ecf20Sopenharmony_ci .caps = DVB_USB_IS_AN_I2C_ADAPTER, 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci .usb_ctrl = CYPRESS_FX2, 868c2ecf20Sopenharmony_ci .firmware = "dvb-usb-avertv-a800-02.fw", 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci .num_adapters = 1, 898c2ecf20Sopenharmony_ci .adapter = { 908c2ecf20Sopenharmony_ci { 918c2ecf20Sopenharmony_ci .num_frontends = 1, 928c2ecf20Sopenharmony_ci .fe = {{ 938c2ecf20Sopenharmony_ci .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, 948c2ecf20Sopenharmony_ci .pid_filter_count = 32, 958c2ecf20Sopenharmony_ci .streaming_ctrl = dibusb2_0_streaming_ctrl, 968c2ecf20Sopenharmony_ci .pid_filter = dibusb_pid_filter, 978c2ecf20Sopenharmony_ci .pid_filter_ctrl = dibusb_pid_filter_ctrl, 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci .frontend_attach = dibusb_dib3000mc_frontend_attach, 1008c2ecf20Sopenharmony_ci .tuner_attach = dibusb_dib3000mc_tuner_attach, 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci /* parameter for the MPEG2-data transfer */ 1038c2ecf20Sopenharmony_ci .stream = { 1048c2ecf20Sopenharmony_ci .type = USB_BULK, 1058c2ecf20Sopenharmony_ci .count = 7, 1068c2ecf20Sopenharmony_ci .endpoint = 0x06, 1078c2ecf20Sopenharmony_ci .u = { 1088c2ecf20Sopenharmony_ci .bulk = { 1098c2ecf20Sopenharmony_ci .buffersize = 4096, 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci }, 1138c2ecf20Sopenharmony_ci }}, 1148c2ecf20Sopenharmony_ci .size_of_priv = sizeof(struct dibusb_state), 1158c2ecf20Sopenharmony_ci }, 1168c2ecf20Sopenharmony_ci }, 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci .power_ctrl = a800_power_ctrl, 1198c2ecf20Sopenharmony_ci .identify_state = a800_identify_state, 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci .rc.core = { 1228c2ecf20Sopenharmony_ci .rc_interval = DEFAULT_RC_INTERVAL, 1238c2ecf20Sopenharmony_ci .rc_codes = RC_MAP_AVERMEDIA_M135A, 1248c2ecf20Sopenharmony_ci .module_name = KBUILD_MODNAME, 1258c2ecf20Sopenharmony_ci .rc_query = a800_rc_query, 1268c2ecf20Sopenharmony_ci .allowed_protos = RC_PROTO_BIT_NEC, 1278c2ecf20Sopenharmony_ci }, 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci .i2c_algo = &dibusb_i2c_algo, 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x01, 1328c2ecf20Sopenharmony_ci .num_device_descs = 1, 1338c2ecf20Sopenharmony_ci .devices = { 1348c2ecf20Sopenharmony_ci { "AVerMedia AverTV DVB-T USB 2.0 (A800)", 1358c2ecf20Sopenharmony_ci { &a800_table[0], NULL }, 1368c2ecf20Sopenharmony_ci { &a800_table[1], NULL }, 1378c2ecf20Sopenharmony_ci }, 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci}; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_cistatic struct usb_driver a800_driver = { 1428c2ecf20Sopenharmony_ci .name = "dvb_usb_a800", 1438c2ecf20Sopenharmony_ci .probe = a800_probe, 1448c2ecf20Sopenharmony_ci .disconnect = dvb_usb_device_exit, 1458c2ecf20Sopenharmony_ci .id_table = a800_table, 1468c2ecf20Sopenharmony_ci}; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_cimodule_usb_driver(a800_driver); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ciMODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>"); 1518c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("AVerMedia AverTV DVB-T USB 2.0 (A800)"); 1528c2ecf20Sopenharmony_ciMODULE_VERSION("1.0"); 1538c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 154