162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* DVB USB framework compliant Linux driver for the AVerMedia AverTV DVB-T 362306a36Sopenharmony_ci * USB2.0 (A800) DVB-T receiver. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@posteo.de) 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Thanks to 862306a36Sopenharmony_ci * - AVerMedia who kindly provided information and 962306a36Sopenharmony_ci * - Glen Harris who suffered from my mistakes during development. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci#include "dibusb.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_cistatic int debug; 1662306a36Sopenharmony_cimodule_param(debug, int, 0644); 1762306a36Sopenharmony_ciMODULE_PARM_DESC(debug, "set debugging level (rc=1 (or-able))." DVB_USB_DEBUG_STATUS); 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ciDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define deb_rc(args...) dprintk(debug,0x01,args) 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic int a800_power_ctrl(struct dvb_usb_device *d, int onoff) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci /* do nothing for the AVerMedia */ 2662306a36Sopenharmony_ci return 0; 2762306a36Sopenharmony_ci} 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/* assure to put cold to 0 for iManufacturer == 1 */ 3062306a36Sopenharmony_cistatic int a800_identify_state(struct usb_device *udev, 3162306a36Sopenharmony_ci const struct dvb_usb_device_properties *props, 3262306a36Sopenharmony_ci const struct dvb_usb_device_description **desc, 3362306a36Sopenharmony_ci int *cold) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci *cold = udev->descriptor.iManufacturer != 1; 3662306a36Sopenharmony_ci return 0; 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic int a800_rc_query(struct dvb_usb_device *d) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci int ret = 0; 4262306a36Sopenharmony_ci u8 *key = kmalloc(5, GFP_KERNEL); 4362306a36Sopenharmony_ci if (!key) 4462306a36Sopenharmony_ci return -ENOMEM; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci if (usb_control_msg(d->udev,usb_rcvctrlpipe(d->udev,0), 4762306a36Sopenharmony_ci 0x04, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, key, 5, 4862306a36Sopenharmony_ci 2000) != 5) { 4962306a36Sopenharmony_ci ret = -ENODEV; 5062306a36Sopenharmony_ci goto out; 5162306a36Sopenharmony_ci } 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci /* Note that extended nec and nec32 are dropped */ 5462306a36Sopenharmony_ci if (key[0] == 1) 5562306a36Sopenharmony_ci rc_keydown(d->rc_dev, RC_PROTO_NEC, 5662306a36Sopenharmony_ci RC_SCANCODE_NEC(key[1], key[3]), 0); 5762306a36Sopenharmony_ci else if (key[0] == 2) 5862306a36Sopenharmony_ci rc_repeat(d->rc_dev); 5962306a36Sopenharmony_ciout: 6062306a36Sopenharmony_ci kfree(key); 6162306a36Sopenharmony_ci return ret; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/* USB Driver stuff */ 6562306a36Sopenharmony_cistatic struct dvb_usb_device_properties a800_properties; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic int a800_probe(struct usb_interface *intf, 6862306a36Sopenharmony_ci const struct usb_device_id *id) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci return dvb_usb_device_init(intf, &a800_properties, 7162306a36Sopenharmony_ci THIS_MODULE, NULL, adapter_nr); 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci/* do not change the order of the ID table */ 7562306a36Sopenharmony_cienum { 7662306a36Sopenharmony_ci AVERMEDIA_DVBT_USB2_COLD, 7762306a36Sopenharmony_ci AVERMEDIA_DVBT_USB2_WARM, 7862306a36Sopenharmony_ci}; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistatic struct usb_device_id a800_table[] = { 8162306a36Sopenharmony_ci DVB_USB_DEV(AVERMEDIA, AVERMEDIA_DVBT_USB2_COLD), 8262306a36Sopenharmony_ci DVB_USB_DEV(AVERMEDIA, AVERMEDIA_DVBT_USB2_WARM), 8362306a36Sopenharmony_ci { } 8462306a36Sopenharmony_ci}; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ciMODULE_DEVICE_TABLE (usb, a800_table); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic struct dvb_usb_device_properties a800_properties = { 8962306a36Sopenharmony_ci .caps = DVB_USB_IS_AN_I2C_ADAPTER, 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci .usb_ctrl = CYPRESS_FX2, 9262306a36Sopenharmony_ci .firmware = "dvb-usb-avertv-a800-02.fw", 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci .num_adapters = 1, 9562306a36Sopenharmony_ci .adapter = { 9662306a36Sopenharmony_ci { 9762306a36Sopenharmony_ci .num_frontends = 1, 9862306a36Sopenharmony_ci .fe = {{ 9962306a36Sopenharmony_ci .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, 10062306a36Sopenharmony_ci .pid_filter_count = 32, 10162306a36Sopenharmony_ci .streaming_ctrl = dibusb2_0_streaming_ctrl, 10262306a36Sopenharmony_ci .pid_filter = dibusb_pid_filter, 10362306a36Sopenharmony_ci .pid_filter_ctrl = dibusb_pid_filter_ctrl, 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci .frontend_attach = dibusb_dib3000mc_frontend_attach, 10662306a36Sopenharmony_ci .tuner_attach = dibusb_dib3000mc_tuner_attach, 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci /* parameter for the MPEG2-data transfer */ 10962306a36Sopenharmony_ci .stream = { 11062306a36Sopenharmony_ci .type = USB_BULK, 11162306a36Sopenharmony_ci .count = 7, 11262306a36Sopenharmony_ci .endpoint = 0x06, 11362306a36Sopenharmony_ci .u = { 11462306a36Sopenharmony_ci .bulk = { 11562306a36Sopenharmony_ci .buffersize = 4096, 11662306a36Sopenharmony_ci } 11762306a36Sopenharmony_ci } 11862306a36Sopenharmony_ci }, 11962306a36Sopenharmony_ci }}, 12062306a36Sopenharmony_ci .size_of_priv = sizeof(struct dibusb_state), 12162306a36Sopenharmony_ci }, 12262306a36Sopenharmony_ci }, 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci .power_ctrl = a800_power_ctrl, 12562306a36Sopenharmony_ci .identify_state = a800_identify_state, 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci .rc.core = { 12862306a36Sopenharmony_ci .rc_interval = DEFAULT_RC_INTERVAL, 12962306a36Sopenharmony_ci .rc_codes = RC_MAP_AVERMEDIA_M135A, 13062306a36Sopenharmony_ci .module_name = KBUILD_MODNAME, 13162306a36Sopenharmony_ci .rc_query = a800_rc_query, 13262306a36Sopenharmony_ci .allowed_protos = RC_PROTO_BIT_NEC, 13362306a36Sopenharmony_ci }, 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci .i2c_algo = &dibusb_i2c_algo, 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x01, 13862306a36Sopenharmony_ci .num_device_descs = 1, 13962306a36Sopenharmony_ci .devices = { 14062306a36Sopenharmony_ci { "AVerMedia AverTV DVB-T USB 2.0 (A800)", 14162306a36Sopenharmony_ci { &a800_table[AVERMEDIA_DVBT_USB2_COLD], NULL }, 14262306a36Sopenharmony_ci { &a800_table[AVERMEDIA_DVBT_USB2_WARM], NULL }, 14362306a36Sopenharmony_ci }, 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci}; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic struct usb_driver a800_driver = { 14862306a36Sopenharmony_ci .name = "dvb_usb_a800", 14962306a36Sopenharmony_ci .probe = a800_probe, 15062306a36Sopenharmony_ci .disconnect = dvb_usb_device_exit, 15162306a36Sopenharmony_ci .id_table = a800_table, 15262306a36Sopenharmony_ci}; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cimodule_usb_driver(a800_driver); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ciMODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>"); 15762306a36Sopenharmony_ciMODULE_DESCRIPTION("AVerMedia AverTV DVB-T USB 2.0 (A800)"); 15862306a36Sopenharmony_ciMODULE_VERSION("1.0"); 15962306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 160