📄 dst.c
字号:
} if (i >= sizeof(dst_tlist) / sizeof(dst_tlist[0])) { printk("%s: unable to recognize %s or %s\n", __FUNCTION__, &rxbuf[0], &rxbuf[1]); printk("%s please email linux-dvb@linuxtv.org with this type in\n", __FUNCTION__); use_dst_type = DST_TYPE_IS_SAT; use_type_flags = DST_TYPE_HAS_SYMDIV; } dst_type_print(use_dst_type); state->type_flags = use_type_flags; state->dst_type = use_dst_type; dst_type_flags_print(state->type_flags); if (state->type_flags & DST_TYPE_HAS_TS204) { dst_packsize(state, 204); } return 0;}static int dst_command(struct dst_state* state, u8 * data, u8 len){ int retval; u8 reply; dst_i2c_enable(state); dst_reset8820(state); retval = write_dst(state, data, len); if (retval < 0) { dst_i2c_disable(state); dprintk("%s: write not successful\n", __FUNCTION__); return retval; } msleep(33); retval = read_dst(state, &reply, 1); dst_i2c_disable(state); if (retval < 0) { dprintk("%s: read verify not successful\n", __FUNCTION__); return retval; } if (reply != 0xff) { dprintk("%s: write reply not 0xff 0x%02x \n", __FUNCTION__, reply); return 0; } if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3)) return 0; if (!dst_wait_dst_ready(state)) return 0; // dst_i2c_enable(i2c); Per dimitri retval = read_dst(state, state->rxbuffer, 8); dst_i2c_disable(state); if (retval < 0) { dprintk("%s: read not successful\n", __FUNCTION__); return 0; } if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) { dprintk("%s: checksum failure\n", __FUNCTION__); return 0; } return 0;}static int dst_get_signal(struct dst_state* state){ int retval; u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb }; if ((state->diseq_flags & ATTEMPT_TUNE) == 0) { state->decode_lock = state->decode_strength = state->decode_snr = 0; return 0; } if (0 == (state->diseq_flags & HAS_LOCK)) { state->decode_lock = state->decode_strength = state->decode_snr = 0; return 0; } if (time_after_eq(jiffies, state->cur_jiff + (HZ / 5))) { retval = dst_command(state, get_signal, 8); if (retval < 0) return retval; if (state->dst_type == DST_TYPE_IS_SAT) { state->decode_lock = ((state->rxbuffer[6] & 0x10) == 0) ? 1 : 0; state->decode_strength = state->rxbuffer[5] << 8; state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3]; } else if ((state->dst_type == DST_TYPE_IS_TERR) || (state->dst_type == DST_TYPE_IS_CABLE)) { state->decode_lock = (state->rxbuffer[1]) ? 1 : 0; state->decode_strength = state->rxbuffer[4] << 8; state->decode_snr = state->rxbuffer[3] << 8; } state->cur_jiff = jiffies; } return 0;}static int dst_tone_power_cmd(struct dst_state* state){ u8 paket[8] = { 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 }; if (state->dst_type == DST_TYPE_IS_TERR) return 0; if (state->voltage == SEC_VOLTAGE_OFF) paket[4] = 0; else paket[4] = 1; if (state->tone == SEC_TONE_ON) paket[2] = state->k22; else paket[2] = 0; paket[7] = dst_check_sum(&paket[0], 7); dst_command(state, paket, 8); return 0;}static int dst_get_tuna(struct dst_state* state){ int retval; if ((state->diseq_flags & ATTEMPT_TUNE) == 0) return 0; state->diseq_flags &= ~(HAS_LOCK); if (!dst_wait_dst_ready(state)) return 0; if (state->type_flags & DST_TYPE_HAS_NEWTUNE) { /* how to get variable length reply ???? */ retval = read_dst(state, state->rx_tuna, 10); } else { retval = read_dst(state, &state->rx_tuna[2], 8); } if (retval < 0) { dprintk("%s: read not successful\n", __FUNCTION__); return 0; } if (state->type_flags & DST_TYPE_HAS_NEWTUNE) { if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) { dprintk("%s: checksum failure?\n", __FUNCTION__); return 0; } } else { if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[2], 7)) { dprintk("%s: checksum failure?\n", __FUNCTION__); return 0; } } if (state->rx_tuna[2] == 0 && state->rx_tuna[3] == 0) return 0; state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3]; state->decode_lock = 1; /* dst->decode_n1 = (dst->rx_tuna[4] << 8) + (dst->rx_tuna[5]); dst->decode_n2 = (dst->rx_tuna[8] << 8) + (dst->rx_tuna[7]); */ state->diseq_flags |= HAS_LOCK; /* dst->cur_jiff = jiffies; */ return 1;}static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage);static int dst_write_tuna(struct dvb_frontend* fe){ struct dst_state* state = (struct dst_state*) fe->demodulator_priv; int retval; u8 reply; dprintk("%s: type_flags 0x%x \n", __FUNCTION__, state->type_flags); state->decode_freq = 0; state->decode_lock = state->decode_strength = state->decode_snr = 0; if (state->dst_type == DST_TYPE_IS_SAT) { if (!(state->diseq_flags & HAS_POWER)) dst_set_voltage(fe, SEC_VOLTAGE_13); } state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE); dst_i2c_enable(state); if (state->type_flags & DST_TYPE_HAS_NEWTUNE) { dst_reset8820(state); state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9); retval = write_dst(state, &state->tx_tuna[0], 10); } else { state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[2], 7); retval = write_dst(state, &state->tx_tuna[2], 8); } if (retval < 0) { dst_i2c_disable(state); dprintk("%s: write not successful\n", __FUNCTION__); return retval; } msleep(3); retval = read_dst(state, &reply, 1); dst_i2c_disable(state); if (retval < 0) { dprintk("%s: read verify not successful\n", __FUNCTION__); return retval; } if (reply != 0xff) { dprintk("%s: write reply not 0xff 0x%02x \n", __FUNCTION__, reply); return 0; } state->diseq_flags |= ATTEMPT_TUNE; return dst_get_tuna(state);}/* * line22k0 0x00, 0x09, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00 * line22k1 0x00, 0x09, 0x01, 0xff, 0x01, 0x00, 0x00, 0x00 * line22k2 0x00, 0x09, 0x02, 0xff, 0x01, 0x00, 0x00, 0x00 * tone 0x00, 0x09, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00 * data 0x00, 0x09, 0xff, 0x01, 0x01, 0x00, 0x00, 0x00 * power_off 0x00, 0x09, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 * power_on 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 * Diseqc 1 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec * Diseqc 2 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf4, 0xe8 * Diseqc 3 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf8, 0xe4 * Diseqc 4 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xfc, 0xe0 */static int dst_set_diseqc(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd){ struct dst_state* state = (struct dst_state*) fe->demodulator_priv; u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec }; if (state->dst_type == DST_TYPE_IS_TERR) return 0; if (cmd->msg_len == 0 || cmd->msg_len > 4) return -EINVAL; memcpy(&paket[3], cmd->msg, cmd->msg_len); paket[7] = dst_check_sum(&paket[0], 7); dst_command(state, paket, 8); return 0;}static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage){ u8 *val; int need_cmd; struct dst_state* state = (struct dst_state*) fe->demodulator_priv; state->voltage = voltage; if (state->dst_type == DST_TYPE_IS_TERR) return 0; need_cmd = 0; val = &state->tx_tuna[0]; val[8] &= ~0x40; switch (voltage) { case SEC_VOLTAGE_13: if ((state->diseq_flags & HAS_POWER) == 0) need_cmd = 1; state->diseq_flags |= HAS_POWER; break; case SEC_VOLTAGE_18: if ((state->diseq_flags & HAS_POWER) == 0) need_cmd = 1; state->diseq_flags |= HAS_POWER; val[8] |= 0x40; break; case SEC_VOLTAGE_OFF: need_cmd = 1; state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE); break; default: return -EINVAL; } if (need_cmd) { dst_tone_power_cmd(state); } return 0;}static int dst_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone){ u8 *val; struct dst_state* state = (struct dst_state*) fe->demodulator_priv; state->tone = tone; if (state->dst_type == DST_TYPE_IS_TERR) return 0; val = &state->tx_tuna[0]; val[8] &= ~0x1; switch (tone) { case SEC_TONE_OFF: break; case SEC_TONE_ON: val[8] |= 1; break; default: return -EINVAL; } dst_tone_power_cmd(state); return 0;}static int dst_init(struct dvb_frontend* fe){ struct dst_state* state = (struct dst_state*) fe->demodulator_priv; static u8 ini_satci_tuna[] = { 9, 0, 3, 0xb6, 1, 0, 0x73, 0x21, 0, 0 }; static u8 ini_satfta_tuna[] = { 0, 0, 3, 0xb6, 1, 0x55, 0xbd, 0x50, 0, 0 }; static u8 ini_tvfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 }; static u8 ini_tvci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 }; static u8 ini_cabfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 }; static u8 ini_cabci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 }; state->inversion = INVERSION_ON; state->voltage = SEC_VOLTAGE_13; state->tone = SEC_TONE_OFF; state->symbol_rate = 29473000; state->fec = FEC_AUTO; state->diseq_flags = 0; state->k22 = 0x02; state->bandwidth = BANDWIDTH_7_MHZ; state->cur_jiff = jiffies; if (state->dst_type == DST_TYPE_IS_SAT) { state->frequency = 950000; memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_satci_tuna : ini_satfta_tuna), sizeof(ini_satfta_tuna)); } else if (state->dst_type == DST_TYPE_IS_TERR) { state->frequency = 137000000; memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_tvci_tuna : ini_tvfta_tuna), sizeof(ini_tvfta_tuna)); } else if (state->dst_type == DST_TYPE_IS_CABLE) { state->frequency = 51000000; memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_cabci_tuna : ini_cabfta_tuna), sizeof(ini_cabfta_tuna)); } return 0;}static int dst_read_status(struct dvb_frontend* fe, fe_status_t* status){ struct dst_state* state = (struct dst_state*) fe->demodulator_priv; *status = 0; if (state->diseq_flags & HAS_LOCK) { dst_get_signal(state); if (state->decode_lock) *status |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | FE_HAS_VITERBI; } return 0;}static int dst_read_signal_strength(struct dvb_frontend* fe, u16* strength){ struct dst_state* state = (struct dst_state*) fe->demodulator_priv; dst_get_signal(state); *strength = state->decode_strength; return 0;}static int dst_read_snr(struct dvb_frontend* fe, u16* snr){ struct dst_state* state = (struct dst_state*) fe->demodulator_priv; dst_get_signal(state); *snr = state->decode_snr; return 0;}static int dst_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p){ struct dst_state* state = (struct dst_state*) fe->demodulator_priv; dst_set_freq(state, p->frequency); dst_set_inversion(state, p->inversion); if (state->dst_type == DST_TYPE_IS_SAT) { dst_set_fec(state, p->u.qpsk.fec_inner); dst_set_symbolrate(state, p->u.qpsk.symbol_rate); } else if (state->dst_type == DST_TYPE_IS_TERR) { dst_set_bandwidth(state, p->u.ofdm.bandwidth); } else if (state->dst_type == DST_TYPE_IS_CABLE) { dst_set_fec(state, p->u.qam.fec_inner); dst_set_symbolrate(state, p->u.qam.symbol_rate); } dst_write_tuna(fe); return 0;}static int dst_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p){ struct dst_state* state = (struct dst_state*) fe->demodulator_priv; p->frequency = state->decode_freq; p->inversion = state->inversion; if (state->dst_type == DST_TYPE_IS_SAT) { p->u.qpsk.symbol_rate = state->symbol_rate; p->u.qpsk.fec_inner = dst_get_fec(state); } else if (state->dst_type == DST_TYPE_IS_TERR) { p->u.ofdm.bandwidth = state->bandwidth; } else if (state->dst_type == DST_TYPE_IS_CABLE) { p->u.qam.symbol_rate = state->symbol_rate; p->u.qam.fec_inner = dst_get_fec(state); p->u.qam.modulation = QAM_AUTO; } return 0;}static void dst_release(struct dvb_frontend* fe){ struct dst_state* state = (struct dst_state*) fe->demodulator_priv; kfree(state);}static struct dvb_frontend_ops dst_dvbt_ops;static struct dvb_frontend_ops dst_dvbs_ops;static struct dvb_frontend_ops dst_dvbc_ops;struct dvb_frontend* dst_attach(const struct dst_config* config, struct i2c_adapter* i2c, struct bt878 *bt){ struct dst_state* state = NULL; /* allocate memory for the internal state */ state = (struct dst_state*) kmalloc(sizeof(struct dst_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ state->config = config; state->i2c = i2c; state->bt = bt; /* check if the demod is there */ if (dst_check_ci(state) < 0) goto error; /* determine settings based on type */ switch (state->dst_type) { case DST_TYPE_IS_TERR: memcpy(&state->ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops)); break; case DST_TYPE_IS_CABLE: memcpy(&state->ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops)); break; case DST_TYPE_IS_SAT: memcpy(&state->ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops)); break; default: printk("dst: unknown frontend type. please report to the LinuxTV.org DVB mailinglist.\n"); goto error; } /* create dvb_frontend */ state->frontend.ops = &state->ops; state->frontend.demodulator_priv = state; return &state->frontend;error: if (state) kfree(state); return NULL;}static struct dvb_frontend_ops dst_dvbt_ops = { .info = { .name = "DST DVB-T", .type = FE_OFDM, .frequency_min = 137000000, .frequency_max = 858000000, .frequency_stepsize = 166667, .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO }, .release = dst_release, .init = dst_init, .set_frontend = dst_set_frontend, .get_frontend = dst_get_frontend, .read_status = dst_read_status, .read_signal_strength = dst_read_signal_strength, .read_snr = dst_read_snr,};static struct dvb_frontend_ops dst_dvbs_ops = { .info = { .name = "DST DVB-S", .type = FE_QPSK, .frequency_min = 950000, .frequency_max = 2150000, .frequency_stepsize = 1000, /* kHz for QPSK frontends */ .frequency_tolerance = 29500, .symbol_rate_min = 1000000, .symbol_rate_max = 45000000, /* . symbol_rate_tolerance = ???,*/ .caps = FE_CAN_FEC_AUTO | FE_CAN_QPSK }, .release = dst_release, .init = dst_init, .set_frontend = dst_set_frontend, .get_frontend = dst_get_frontend, .read_status = dst_read_status, .read_signal_strength = dst_read_signal_strength, .read_snr = dst_read_snr, .diseqc_send_master_cmd = dst_set_diseqc, .set_voltage = dst_set_voltage, .set_tone = dst_set_tone,};static struct dvb_frontend_ops dst_dvbc_ops = { .info = { .name = "DST DVB-C", .type = FE_QAM, .frequency_stepsize = 62500, .frequency_min = 51000000, .frequency_max = 858000000, .symbol_rate_min = 1000000, .symbol_rate_max = 45000000, /* . symbol_rate_tolerance = ???,*/ .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO }, .release = dst_release, .init = dst_init, .set_frontend = dst_set_frontend, .get_frontend = dst_get_frontend, .read_status = dst_read_status, .read_signal_strength = dst_read_signal_strength, .read_snr = dst_read_snr,};MODULE_DESCRIPTION("DST DVB-S/T/C Combo Frontend driver");MODULE_AUTHOR("Jamie Honan");MODULE_LICENSE("GPL");EXPORT_SYMBOL(dst_attach);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -