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

ec168.c (8760B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * E3C EC168 DVB USB driver
      4 *
      5 * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
      6 */
      7
      8#include "ec168.h"
      9#include "ec100.h"
     10#include "mxl5005s.h"
     11
     12DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
     13
     14static int ec168_ctrl_msg(struct dvb_usb_device *d, struct ec168_req *req)
     15{
     16	int ret;
     17	unsigned int pipe;
     18	u8 request, requesttype;
     19	u8 *buf;
     20
     21	switch (req->cmd) {
     22	case DOWNLOAD_FIRMWARE:
     23	case GPIO:
     24	case WRITE_I2C:
     25	case STREAMING_CTRL:
     26		requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
     27		request = req->cmd;
     28		break;
     29	case READ_I2C:
     30		requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
     31		request = req->cmd;
     32		break;
     33	case GET_CONFIG:
     34		requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
     35		request = CONFIG;
     36		break;
     37	case SET_CONFIG:
     38		requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
     39		request = CONFIG;
     40		break;
     41	case WRITE_DEMOD:
     42		requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
     43		request = DEMOD_RW;
     44		break;
     45	case READ_DEMOD:
     46		requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
     47		request = DEMOD_RW;
     48		break;
     49	default:
     50		dev_err(&d->udev->dev, "%s: unknown command=%02x\n",
     51				KBUILD_MODNAME, req->cmd);
     52		ret = -EINVAL;
     53		goto error;
     54	}
     55
     56	buf = kmalloc(req->size, GFP_KERNEL);
     57	if (!buf) {
     58		ret = -ENOMEM;
     59		goto error;
     60	}
     61
     62	if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) {
     63		/* write */
     64		memcpy(buf, req->data, req->size);
     65		pipe = usb_sndctrlpipe(d->udev, 0);
     66	} else {
     67		/* read */
     68		pipe = usb_rcvctrlpipe(d->udev, 0);
     69	}
     70
     71	msleep(1); /* avoid I2C errors */
     72
     73	ret = usb_control_msg(d->udev, pipe, request, requesttype, req->value,
     74		req->index, buf, req->size, EC168_USB_TIMEOUT);
     75
     76	dvb_usb_dbg_usb_control_msg(d->udev, request, requesttype, req->value,
     77			req->index, buf, req->size);
     78
     79	if (ret < 0)
     80		goto err_dealloc;
     81	else
     82		ret = 0;
     83
     84	/* read request, copy returned data to return buf */
     85	if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
     86		memcpy(req->data, buf, req->size);
     87
     88	kfree(buf);
     89	return ret;
     90
     91err_dealloc:
     92	kfree(buf);
     93error:
     94	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
     95	return ret;
     96}
     97
     98/* I2C */
     99static struct ec100_config ec168_ec100_config;
    100
    101static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
    102	int num)
    103{
    104	struct dvb_usb_device *d = i2c_get_adapdata(adap);
    105	struct ec168_req req;
    106	int i = 0;
    107	int ret;
    108
    109	if (num > 2)
    110		return -EINVAL;
    111
    112	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
    113		return -EAGAIN;
    114
    115	while (i < num) {
    116		if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
    117			if (msg[i].addr == ec168_ec100_config.demod_address) {
    118				req.cmd = READ_DEMOD;
    119				req.value = 0;
    120				req.index = 0xff00 + msg[i].buf[0]; /* reg */
    121				req.size = msg[i+1].len; /* bytes to read */
    122				req.data = &msg[i+1].buf[0];
    123				ret = ec168_ctrl_msg(d, &req);
    124				i += 2;
    125			} else {
    126				dev_err(&d->udev->dev, "%s: I2C read not " \
    127						"implemented\n",
    128						KBUILD_MODNAME);
    129				ret = -EOPNOTSUPP;
    130				i += 2;
    131			}
    132		} else {
    133			if (msg[i].addr == ec168_ec100_config.demod_address) {
    134				req.cmd = WRITE_DEMOD;
    135				req.value = msg[i].buf[1]; /* val */
    136				req.index = 0xff00 + msg[i].buf[0]; /* reg */
    137				req.size = 0;
    138				req.data = NULL;
    139				ret = ec168_ctrl_msg(d, &req);
    140				i += 1;
    141			} else {
    142				req.cmd = WRITE_I2C;
    143				req.value = msg[i].buf[0]; /* val */
    144				req.index = 0x0100 + msg[i].addr; /* I2C addr */
    145				req.size = msg[i].len-1;
    146				req.data = &msg[i].buf[1];
    147				ret = ec168_ctrl_msg(d, &req);
    148				i += 1;
    149			}
    150		}
    151		if (ret)
    152			goto error;
    153
    154	}
    155	ret = i;
    156
    157error:
    158	mutex_unlock(&d->i2c_mutex);
    159	return ret;
    160}
    161
    162static u32 ec168_i2c_func(struct i2c_adapter *adapter)
    163{
    164	return I2C_FUNC_I2C;
    165}
    166
    167static struct i2c_algorithm ec168_i2c_algo = {
    168	.master_xfer   = ec168_i2c_xfer,
    169	.functionality = ec168_i2c_func,
    170};
    171
    172/* Callbacks for DVB USB */
    173static int ec168_identify_state(struct dvb_usb_device *d, const char **name)
    174{
    175	int ret;
    176	u8 reply;
    177	struct ec168_req req = {GET_CONFIG, 0, 1, sizeof(reply), &reply};
    178	dev_dbg(&d->udev->dev, "%s:\n", __func__);
    179
    180	ret = ec168_ctrl_msg(d, &req);
    181	if (ret)
    182		goto error;
    183
    184	dev_dbg(&d->udev->dev, "%s: reply=%02x\n", __func__, reply);
    185
    186	if (reply == 0x01)
    187		ret = WARM;
    188	else
    189		ret = COLD;
    190
    191	return ret;
    192error:
    193	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
    194	return ret;
    195}
    196
    197static int ec168_download_firmware(struct dvb_usb_device *d,
    198		const struct firmware *fw)
    199{
    200	int ret, len, remaining;
    201	struct ec168_req req = {DOWNLOAD_FIRMWARE, 0, 0, 0, NULL};
    202	dev_dbg(&d->udev->dev, "%s:\n", __func__);
    203
    204	#define LEN_MAX 2048 /* max packet size */
    205	for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) {
    206		len = remaining;
    207		if (len > LEN_MAX)
    208			len = LEN_MAX;
    209
    210		req.size = len;
    211		req.data = (u8 *) &fw->data[fw->size - remaining];
    212		req.index = fw->size - remaining;
    213
    214		ret = ec168_ctrl_msg(d, &req);
    215		if (ret) {
    216			dev_err(&d->udev->dev,
    217					"%s: firmware download failed=%d\n",
    218					KBUILD_MODNAME, ret);
    219			goto error;
    220		}
    221	}
    222
    223	req.size = 0;
    224
    225	/* set "warm"? */
    226	req.cmd = SET_CONFIG;
    227	req.value = 0;
    228	req.index = 0x0001;
    229	ret = ec168_ctrl_msg(d, &req);
    230	if (ret)
    231		goto error;
    232
    233	/* really needed - no idea what does */
    234	req.cmd = GPIO;
    235	req.value = 0;
    236	req.index = 0x0206;
    237	ret = ec168_ctrl_msg(d, &req);
    238	if (ret)
    239		goto error;
    240
    241	/* activate tuner I2C? */
    242	req.cmd = WRITE_I2C;
    243	req.value = 0;
    244	req.index = 0x00c6;
    245	ret = ec168_ctrl_msg(d, &req);
    246	if (ret)
    247		goto error;
    248
    249	return ret;
    250error:
    251	dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
    252	return ret;
    253}
    254
    255static struct ec100_config ec168_ec100_config = {
    256	.demod_address = 0xff, /* not real address, demod is integrated */
    257};
    258
    259static int ec168_ec100_frontend_attach(struct dvb_usb_adapter *adap)
    260{
    261	struct dvb_usb_device *d = adap_to_d(adap);
    262	dev_dbg(&d->udev->dev, "%s:\n", __func__);
    263
    264	adap->fe[0] = dvb_attach(ec100_attach, &ec168_ec100_config,
    265			&d->i2c_adap);
    266	if (adap->fe[0] == NULL)
    267		return -ENODEV;
    268
    269	return 0;
    270}
    271
    272static struct mxl5005s_config ec168_mxl5003s_config = {
    273	.i2c_address     = 0xc6,
    274	.if_freq         = IF_FREQ_4570000HZ,
    275	.xtal_freq       = CRYSTAL_FREQ_16000000HZ,
    276	.agc_mode        = MXL_SINGLE_AGC,
    277	.tracking_filter = MXL_TF_OFF,
    278	.rssi_enable     = MXL_RSSI_ENABLE,
    279	.cap_select      = MXL_CAP_SEL_ENABLE,
    280	.div_out         = MXL_DIV_OUT_4,
    281	.clock_out       = MXL_CLOCK_OUT_DISABLE,
    282	.output_load     = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
    283	.top		 = MXL5005S_TOP_25P2,
    284	.mod_mode        = MXL_DIGITAL_MODE,
    285	.if_mode         = MXL_ZERO_IF,
    286	.AgcMasterByte   = 0x00,
    287};
    288
    289static int ec168_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
    290{
    291	struct dvb_usb_device *d = adap_to_d(adap);
    292	dev_dbg(&d->udev->dev, "%s:\n", __func__);
    293
    294	return dvb_attach(mxl5005s_attach, adap->fe[0], &d->i2c_adap,
    295			&ec168_mxl5003s_config) == NULL ? -ENODEV : 0;
    296}
    297
    298static int ec168_streaming_ctrl(struct dvb_frontend *fe, int onoff)
    299{
    300	struct dvb_usb_device *d = fe_to_d(fe);
    301	struct ec168_req req = {STREAMING_CTRL, 0x7f01, 0x0202, 0, NULL};
    302	dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff);
    303
    304	if (onoff)
    305		req.index = 0x0102;
    306	return ec168_ctrl_msg(d, &req);
    307}
    308
    309/* DVB USB Driver stuff */
    310/* bInterfaceNumber 0 is HID
    311 * bInterfaceNumber 1 is DVB-T */
    312static const struct dvb_usb_device_properties ec168_props = {
    313	.driver_name = KBUILD_MODNAME,
    314	.owner = THIS_MODULE,
    315	.adapter_nr = adapter_nr,
    316	.bInterfaceNumber = 1,
    317
    318	.identify_state = ec168_identify_state,
    319	.firmware = EC168_FIRMWARE,
    320	.download_firmware = ec168_download_firmware,
    321
    322	.i2c_algo = &ec168_i2c_algo,
    323	.frontend_attach = ec168_ec100_frontend_attach,
    324	.tuner_attach = ec168_mxl5003s_tuner_attach,
    325	.streaming_ctrl = ec168_streaming_ctrl,
    326
    327	.num_adapters = 1,
    328	.adapter = {
    329		{
    330			.stream = DVB_USB_STREAM_BULK(0x82, 6, 32 * 512),
    331		}
    332	},
    333};
    334
    335static const struct usb_device_id ec168_id[] = {
    336	{ DVB_USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168,
    337		     &ec168_props, "E3C EC168 reference design", NULL)},
    338	{ DVB_USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_2,
    339		     &ec168_props, "E3C EC168 reference design", NULL)},
    340	{ DVB_USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_3,
    341		     &ec168_props, "E3C EC168 reference design", NULL)},
    342	{ DVB_USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_4,
    343		     &ec168_props, "E3C EC168 reference design", NULL)},
    344	{ DVB_USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_5,
    345		     &ec168_props, "E3C EC168 reference design", NULL)},
    346	{}
    347};
    348MODULE_DEVICE_TABLE(usb, ec168_id);
    349
    350static struct usb_driver ec168_driver = {
    351	.name = KBUILD_MODNAME,
    352	.id_table = ec168_id,
    353	.probe = dvb_usbv2_probe,
    354	.disconnect = dvb_usbv2_disconnect,
    355	.suspend = dvb_usbv2_suspend,
    356	.resume = dvb_usbv2_resume,
    357	.no_dynamic_id = 1,
    358	.soft_unbind = 1,
    359};
    360
    361module_usb_driver(ec168_driver);
    362
    363MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
    364MODULE_DESCRIPTION("E3C EC168 driver");
    365MODULE_LICENSE("GPL");
    366MODULE_FIRMWARE(EC168_FIRMWARE);