^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* DVB USB framework compliant Linux driver for the AVerMedia AverTV DVB-T
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * USB2.0 (A800) DVB-T receiver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@posteo.de)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Thanks to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * - AVerMedia who kindly provided information and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * - Glen Harris who suffered from my mistakes during development.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "dibusb.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) static int debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) module_param(debug, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) MODULE_PARM_DESC(debug, "set debugging level (rc=1 (or-able))." DVB_USB_DEBUG_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define deb_rc(args...) dprintk(debug,0x01,args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static int a800_power_ctrl(struct dvb_usb_device *d, int onoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* do nothing for the AVerMedia */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /* assure to put cold to 0 for iManufacturer == 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static int a800_identify_state(struct usb_device *udev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) const struct dvb_usb_device_properties *props,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) const struct dvb_usb_device_description **desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) int *cold)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) *cold = udev->descriptor.iManufacturer != 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static int a800_rc_query(struct dvb_usb_device *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) u8 *key = kmalloc(5, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (!key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (usb_control_msg(d->udev,usb_rcvctrlpipe(d->udev,0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) 0x04, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, key, 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) 2000) != 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* Note that extended nec and nec32 are dropped */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (key[0] == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) rc_keydown(d->rc_dev, RC_PROTO_NEC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) RC_SCANCODE_NEC(key[1], key[3]), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) else if (key[0] == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) rc_repeat(d->rc_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) kfree(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* USB Driver stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static struct dvb_usb_device_properties a800_properties;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static int a800_probe(struct usb_interface *intf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) const struct usb_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return dvb_usb_device_init(intf, &a800_properties,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) THIS_MODULE, NULL, adapter_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* do not change the order of the ID table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static struct usb_device_id a800_table [] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* 00 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB2_COLD) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* 01 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB2_WARM) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) { } /* Terminating entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) MODULE_DEVICE_TABLE (usb, a800_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static struct dvb_usb_device_properties a800_properties = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .caps = DVB_USB_IS_AN_I2C_ADAPTER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) .usb_ctrl = CYPRESS_FX2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) .firmware = "dvb-usb-avertv-a800-02.fw",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .num_adapters = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .adapter = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) .num_frontends = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) .fe = {{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) .pid_filter_count = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .streaming_ctrl = dibusb2_0_streaming_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .pid_filter = dibusb_pid_filter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .pid_filter_ctrl = dibusb_pid_filter_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .frontend_attach = dibusb_dib3000mc_frontend_attach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .tuner_attach = dibusb_dib3000mc_tuner_attach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* parameter for the MPEG2-data transfer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .stream = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .type = USB_BULK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) .count = 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .endpoint = 0x06,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .u = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .bulk = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) .buffersize = 4096,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) .size_of_priv = sizeof(struct dibusb_state),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .power_ctrl = a800_power_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .identify_state = a800_identify_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .rc.core = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .rc_interval = DEFAULT_RC_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .rc_codes = RC_MAP_AVERMEDIA_M135A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .module_name = KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .rc_query = a800_rc_query,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .allowed_protos = RC_PROTO_BIT_NEC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .i2c_algo = &dibusb_i2c_algo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .generic_bulk_ctrl_endpoint = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) .num_device_descs = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .devices = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) { "AVerMedia AverTV DVB-T USB 2.0 (A800)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) { &a800_table[0], NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) { &a800_table[1], NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static struct usb_driver a800_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .name = "dvb_usb_a800",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .probe = a800_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .disconnect = dvb_usb_device_exit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .id_table = a800_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) module_usb_driver(a800_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) MODULE_DESCRIPTION("AVerMedia AverTV DVB-T USB 2.0 (A800)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) MODULE_VERSION("1.0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) MODULE_LICENSE("GPL");