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

dtt200u-fe.c (6258B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/* Frontend part of the Linux driver for the WideView/ Yakumo/ Hama/
      3 * Typhoon/ Yuan DVB-T USB2.0 receiver.
      4 *
      5 * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@posteo.de>
      6 *
      7 * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
      8 */
      9#include "dtt200u.h"
     10
     11struct dtt200u_fe_state {
     12	struct dvb_usb_device *d;
     13
     14	enum fe_status stat;
     15
     16	struct dtv_frontend_properties fep;
     17	struct dvb_frontend frontend;
     18
     19	unsigned char data[80];
     20	struct mutex data_mutex;
     21};
     22
     23static int dtt200u_fe_read_status(struct dvb_frontend *fe,
     24				  enum fe_status *stat)
     25{
     26	struct dtt200u_fe_state *state = fe->demodulator_priv;
     27	int ret;
     28
     29	mutex_lock(&state->data_mutex);
     30	state->data[0] = GET_TUNE_STATUS;
     31
     32	ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 3, 0);
     33	if (ret < 0) {
     34		*stat = 0;
     35		mutex_unlock(&state->data_mutex);
     36		return ret;
     37	}
     38
     39	switch (state->data[0]) {
     40		case 0x01:
     41			*stat = FE_HAS_SIGNAL | FE_HAS_CARRIER |
     42				FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
     43			break;
     44		case 0x00: /* pending */
     45			*stat = FE_TIMEDOUT; /* during set_frontend */
     46			break;
     47		default:
     48		case 0x02: /* failed */
     49			*stat = 0;
     50			break;
     51	}
     52	mutex_unlock(&state->data_mutex);
     53	return 0;
     54}
     55
     56static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
     57{
     58	struct dtt200u_fe_state *state = fe->demodulator_priv;
     59	int ret;
     60
     61	mutex_lock(&state->data_mutex);
     62	state->data[0] = GET_VIT_ERR_CNT;
     63
     64	ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 3, 0);
     65	if (ret >= 0)
     66		*ber = (state->data[0] << 16) | (state->data[1] << 8) | state->data[2];
     67
     68	mutex_unlock(&state->data_mutex);
     69	return ret;
     70}
     71
     72static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
     73{
     74	struct dtt200u_fe_state *state = fe->demodulator_priv;
     75	int ret;
     76
     77	mutex_lock(&state->data_mutex);
     78	state->data[0] = GET_RS_UNCOR_BLK_CNT;
     79
     80	ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 2, 0);
     81	if (ret >= 0)
     82		*unc = (state->data[0] << 8) | state->data[1];
     83
     84	mutex_unlock(&state->data_mutex);
     85	return ret;
     86}
     87
     88static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
     89{
     90	struct dtt200u_fe_state *state = fe->demodulator_priv;
     91	int ret;
     92
     93	mutex_lock(&state->data_mutex);
     94	state->data[0] = GET_AGC;
     95
     96	ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 1, 0);
     97	if (ret >= 0)
     98		*strength = (state->data[0] << 8) | state->data[0];
     99
    100	mutex_unlock(&state->data_mutex);
    101	return ret;
    102}
    103
    104static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
    105{
    106	struct dtt200u_fe_state *state = fe->demodulator_priv;
    107	int ret;
    108
    109	mutex_lock(&state->data_mutex);
    110	state->data[0] = GET_SNR;
    111
    112	ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 1, 0);
    113	if (ret >= 0)
    114		*snr = ~((state->data[0] << 8) | state->data[0]);
    115
    116	mutex_unlock(&state->data_mutex);
    117	return ret;
    118}
    119
    120static int dtt200u_fe_init(struct dvb_frontend* fe)
    121{
    122	struct dtt200u_fe_state *state = fe->demodulator_priv;
    123	int ret;
    124
    125	mutex_lock(&state->data_mutex);
    126	state->data[0] = SET_INIT;
    127
    128	ret = dvb_usb_generic_write(state->d, state->data, 1);
    129	mutex_unlock(&state->data_mutex);
    130
    131	return ret;
    132}
    133
    134static int dtt200u_fe_sleep(struct dvb_frontend* fe)
    135{
    136	return dtt200u_fe_init(fe);
    137}
    138
    139static int dtt200u_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
    140{
    141	tune->min_delay_ms = 1500;
    142	tune->step_size = 0;
    143	tune->max_drift = 0;
    144	return 0;
    145}
    146
    147static int dtt200u_fe_set_frontend(struct dvb_frontend *fe)
    148{
    149	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
    150	struct dtt200u_fe_state *state = fe->demodulator_priv;
    151	int ret;
    152	u16 freq = fep->frequency / 250000;
    153
    154	mutex_lock(&state->data_mutex);
    155	state->data[0] = SET_BANDWIDTH;
    156	switch (fep->bandwidth_hz) {
    157	case 8000000:
    158		state->data[1] = 8;
    159		break;
    160	case 7000000:
    161		state->data[1] = 7;
    162		break;
    163	case 6000000:
    164		state->data[1] = 6;
    165		break;
    166	default:
    167		ret = -EINVAL;
    168		goto ret;
    169	}
    170
    171	ret = dvb_usb_generic_write(state->d, state->data, 2);
    172	if (ret < 0)
    173		goto ret;
    174
    175	state->data[0] = SET_RF_FREQ;
    176	state->data[1] = freq & 0xff;
    177	state->data[2] = (freq >> 8) & 0xff;
    178	ret = dvb_usb_generic_write(state->d, state->data, 3);
    179	if (ret < 0)
    180		goto ret;
    181
    182ret:
    183	mutex_unlock(&state->data_mutex);
    184	return ret;
    185}
    186
    187static int dtt200u_fe_get_frontend(struct dvb_frontend* fe,
    188				   struct dtv_frontend_properties *fep)
    189{
    190	struct dtt200u_fe_state *state = fe->demodulator_priv;
    191
    192	memcpy(fep, &state->fep, sizeof(struct dtv_frontend_properties));
    193	return 0;
    194}
    195
    196static void dtt200u_fe_release(struct dvb_frontend* fe)
    197{
    198	struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv;
    199	kfree(state);
    200}
    201
    202static const struct dvb_frontend_ops dtt200u_fe_ops;
    203
    204struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)
    205{
    206	struct dtt200u_fe_state* state = NULL;
    207
    208	/* allocate memory for the internal state */
    209	state = kzalloc(sizeof(struct dtt200u_fe_state), GFP_KERNEL);
    210	if (state == NULL)
    211		goto error;
    212
    213	deb_info("attaching frontend dtt200u\n");
    214
    215	state->d = d;
    216	mutex_init(&state->data_mutex);
    217
    218	memcpy(&state->frontend.ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));
    219	state->frontend.demodulator_priv = state;
    220
    221	return &state->frontend;
    222error:
    223	return NULL;
    224}
    225
    226static const struct dvb_frontend_ops dtt200u_fe_ops = {
    227	.delsys = { SYS_DVBT },
    228	.info = {
    229		.name			= "WideView USB DVB-T",
    230		.frequency_min_hz	=  44250 * kHz,
    231		.frequency_max_hz	= 867250 * kHz,
    232		.frequency_stepsize_hz	=    250 * kHz,
    233		.caps = FE_CAN_INVERSION_AUTO |
    234				FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
    235				FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
    236				FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
    237				FE_CAN_TRANSMISSION_MODE_AUTO |
    238				FE_CAN_GUARD_INTERVAL_AUTO |
    239				FE_CAN_RECOVER |
    240				FE_CAN_HIERARCHY_AUTO,
    241	},
    242
    243	.release = dtt200u_fe_release,
    244
    245	.init = dtt200u_fe_init,
    246	.sleep = dtt200u_fe_sleep,
    247
    248	.set_frontend = dtt200u_fe_set_frontend,
    249	.get_frontend = dtt200u_fe_get_frontend,
    250	.get_tune_settings = dtt200u_fe_get_tune_settings,
    251
    252	.read_status = dtt200u_fe_read_status,
    253	.read_ber = dtt200u_fe_read_ber,
    254	.read_signal_strength = dtt200u_fe_read_signal_strength,
    255	.read_snr = dtt200u_fe_read_snr,
    256	.read_ucblocks = dtt200u_fe_read_unc_blocks,
    257};