cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vp7045.c (6190B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/* DVB USB compliant Linux driver for the
      3 *  - TwinhanDTV Alpha/MagicBoxII USB2.0 DVB-T receiver
      4 *  - DigitalNow TinyUSB2 DVB-t receiver
      5 *
      6 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de)
      7 *
      8 * Thanks to Twinhan who kindly provided hardware and information.
      9 *
     10 * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
     11 */
     12#include "vp7045.h"
     13
     14/* debug */
     15static int dvb_usb_vp7045_debug;
     16module_param_named(debug,dvb_usb_vp7045_debug, int, 0644);
     17MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
     18
     19DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
     20
     21#define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args)
     22#define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args)
     23#define deb_rc(args...)   dprintk(dvb_usb_vp7045_debug,0x04,args)
     24
     25int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec)
     26{
     27	int ret = 0;
     28	u8 *buf = d->priv;
     29
     30	buf[0] = cmd;
     31
     32	if (outlen > 19)
     33		outlen = 19;
     34
     35	if (inlen > 11)
     36		inlen = 11;
     37
     38	ret = mutex_lock_interruptible(&d->usb_mutex);
     39	if (ret)
     40		return ret;
     41
     42	if (out != NULL && outlen > 0)
     43		memcpy(&buf[1], out, outlen);
     44
     45	deb_xfer("out buffer: ");
     46	debug_dump(buf, outlen+1, deb_xfer);
     47
     48
     49	if (usb_control_msg(d->udev,
     50			usb_sndctrlpipe(d->udev,0),
     51			TH_COMMAND_OUT, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0,
     52			buf, 20, 2000) != 20) {
     53		err("USB control message 'out' went wrong.");
     54		ret = -EIO;
     55		goto unlock;
     56	}
     57
     58	msleep(msec);
     59
     60	if (usb_control_msg(d->udev,
     61			usb_rcvctrlpipe(d->udev,0),
     62			TH_COMMAND_IN, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
     63			buf, 12, 2000) != 12) {
     64		err("USB control message 'in' went wrong.");
     65		ret = -EIO;
     66		goto unlock;
     67	}
     68
     69	deb_xfer("in buffer: ");
     70	debug_dump(buf, 12, deb_xfer);
     71
     72	if (in != NULL && inlen > 0)
     73		memcpy(in, &buf[1], inlen);
     74
     75unlock:
     76	mutex_unlock(&d->usb_mutex);
     77
     78	return ret;
     79}
     80
     81u8 vp7045_read_reg(struct dvb_usb_device *d, u8 reg)
     82{
     83	u8 obuf[2] = { 0 },v;
     84	obuf[1] = reg;
     85
     86	vp7045_usb_op(d,TUNER_REG_READ,obuf,2,&v,1,30);
     87
     88	return v;
     89}
     90
     91static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff)
     92{
     93	u8 v = onoff;
     94	return vp7045_usb_op(d,SET_TUNER_POWER,&v,1,NULL,0,150);
     95}
     96
     97static int vp7045_rc_query(struct dvb_usb_device *d)
     98{
     99	int ret;
    100	u8 key;
    101
    102	ret = vp7045_usb_op(d, RC_VAL_READ, NULL, 0, &key, 1, 20);
    103	if (ret)
    104		return ret;
    105
    106	deb_rc("remote query key: %x\n", key);
    107
    108	if (key != 0x44) {
    109		/*
    110		 * The 8 bit address isn't available, but since the remote uses
    111		 * address 0 we'll use that. nec repeats are ignored too, even
    112		 * though the remote sends them.
    113		 */
    114		rc_keydown(d->rc_dev, RC_PROTO_NEC, RC_SCANCODE_NEC(0, key), 0);
    115	}
    116
    117	return 0;
    118}
    119
    120static int vp7045_read_eeprom(struct dvb_usb_device *d,u8 *buf, int len, int offset)
    121{
    122	int i, ret;
    123	u8 v, br[2];
    124	for (i=0; i < len; i++) {
    125		v = offset + i;
    126		ret = vp7045_usb_op(d, GET_EE_VALUE, &v, 1, br, 2, 5);
    127		if (ret)
    128			return ret;
    129
    130		buf[i] = br[1];
    131	}
    132	deb_info("VP7045 EEPROM read (offs: %d, len: %d) : ", offset, i);
    133	debug_dump(buf, i, deb_info);
    134	return 0;
    135}
    136
    137static int vp7045_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
    138{
    139	return vp7045_read_eeprom(d,mac, 6, MAC_0_ADDR);
    140}
    141
    142static int vp7045_frontend_attach(struct dvb_usb_adapter *adap)
    143{
    144	u8 buf[255] = { 0 };
    145
    146	vp7045_usb_op(adap->dev,VENDOR_STRING_READ,NULL,0,buf,20,0);
    147	buf[10] = '\0';
    148	deb_info("firmware says: %s ",buf);
    149
    150	vp7045_usb_op(adap->dev,PRODUCT_STRING_READ,NULL,0,buf,20,0);
    151	buf[10] = '\0';
    152	deb_info("%s ",buf);
    153
    154	vp7045_usb_op(adap->dev,FW_VERSION_READ,NULL,0,buf,20,0);
    155	buf[10] = '\0';
    156	deb_info("v%s\n",buf);
    157
    158/*	Dump the EEPROM */
    159/*	vp7045_read_eeprom(d,buf, 255, FX2_ID_ADDR); */
    160
    161	adap->fe_adap[0].fe = vp7045_fe_attach(adap->dev);
    162
    163	return 0;
    164}
    165
    166static struct dvb_usb_device_properties vp7045_properties;
    167
    168static int vp7045_usb_probe(struct usb_interface *intf,
    169		const struct usb_device_id *id)
    170{
    171	return dvb_usb_device_init(intf, &vp7045_properties,
    172				   THIS_MODULE, NULL, adapter_nr);
    173}
    174
    175enum {
    176	VISIONPLUS_VP7045_COLD,
    177	VISIONPLUS_VP7045_WARM,
    178	VISIONPLUS_TINYUSB2_COLD,
    179	VISIONPLUS_TINYUSB2_WARM,
    180};
    181
    182static struct usb_device_id vp7045_usb_table[] = {
    183	DVB_USB_DEV(VISIONPLUS, VISIONPLUS_VP7045_COLD),
    184	DVB_USB_DEV(VISIONPLUS, VISIONPLUS_VP7045_WARM),
    185	DVB_USB_DEV(VISIONPLUS, VISIONPLUS_TINYUSB2_COLD),
    186	DVB_USB_DEV(VISIONPLUS, VISIONPLUS_TINYUSB2_WARM),
    187	{ }
    188};
    189
    190MODULE_DEVICE_TABLE(usb, vp7045_usb_table);
    191
    192static struct dvb_usb_device_properties vp7045_properties = {
    193	.usb_ctrl = CYPRESS_FX2,
    194	.firmware = "dvb-usb-vp7045-01.fw",
    195	.size_of_priv = 20,
    196
    197	.num_adapters = 1,
    198	.adapter = {
    199		{
    200		.num_frontends = 1,
    201		.fe = {{
    202			.frontend_attach  = vp7045_frontend_attach,
    203			/* parameter for the MPEG2-data transfer */
    204			.stream = {
    205				.type = USB_BULK,
    206				.count = 7,
    207				.endpoint = 0x02,
    208				.u = {
    209					.bulk = {
    210						.buffersize = 4096,
    211					}
    212				}
    213			},
    214		}},
    215		}
    216	},
    217	.power_ctrl       = vp7045_power_ctrl,
    218	.read_mac_address = vp7045_read_mac_addr,
    219
    220	.rc.core = {
    221		.rc_interval	= 400,
    222		.rc_codes	= RC_MAP_TWINHAN_VP1027_DVBS,
    223		.module_name    = KBUILD_MODNAME,
    224		.rc_query	= vp7045_rc_query,
    225		.allowed_protos = RC_PROTO_BIT_NEC,
    226		.scancode_mask	= 0xff,
    227	},
    228
    229	.num_device_descs = 2,
    230	.devices = {
    231		{ .name = "Twinhan USB2.0 DVB-T receiver (TwinhanDTV Alpha/MagicBox II)",
    232		  .cold_ids = { &vp7045_usb_table[VISIONPLUS_VP7045_COLD], NULL },
    233		  .warm_ids = { &vp7045_usb_table[VISIONPLUS_VP7045_WARM], NULL },
    234		},
    235		{ .name = "DigitalNow TinyUSB 2 DVB-t Receiver",
    236		  .cold_ids = { &vp7045_usb_table[VISIONPLUS_TINYUSB2_COLD], NULL },
    237		  .warm_ids = { &vp7045_usb_table[VISIONPLUS_TINYUSB2_WARM], NULL },
    238		},
    239		{ NULL },
    240	}
    241};
    242
    243/* usb specific object needed to register this driver with the usb subsystem */
    244static struct usb_driver vp7045_usb_driver = {
    245	.name		= "dvb_usb_vp7045",
    246	.probe		= vp7045_usb_probe,
    247	.disconnect	= dvb_usb_device_exit,
    248	.id_table	= vp7045_usb_table,
    249};
    250
    251module_usb_driver(vp7045_usb_driver);
    252
    253MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
    254MODULE_DESCRIPTION("Driver for Twinhan MagicBox/Alpha and DNTV tinyUSB2 DVB-T USB2.0");
    255MODULE_VERSION("1.0");
    256MODULE_LICENSE("GPL");