static int secSendSequence(struct dvb_struct *dvb, struct secCmdSequence *seq) { int i, ret; struct secCommand scommands; switch (seq->miniCommand) { case SEC_MINI_NONE: case SEC_MINI_A: case SEC_MINI_B: break; default: return -EINVAL; } for (i=0; i<seq->numCommands; i++) { if (copy_from_user(&scommands, &seq->commands[i], sizeof(struct secCommand))) continue; dvb_frontend_demod_command(dvb->frontend, FE_SEC_COMMAND, (void*)&scommands); } if (seq->miniCommand!=SEC_MINI_NONE) dvb_frontend_demod_command(dvb->frontend, FE_SEC_MINI_COMMAND, (void*)seq->miniCommand); ret=secSetVoltage(dvb, seq->voltage); if (ret<0) return ret; return secSetTone(dvb, seq->continuousTone); }
void CFrontend::setDiseqcType(const diseqc_t newDiseqcType, bool force) { switch (newDiseqcType) { case NO_DISEQC: INFO("fe%d: NO_DISEQC", fenumber); break; case MINI_DISEQC: INFO("fe%d: MINI_DISEQC", fenumber); break; case SMATV_REMOTE_TUNING: INFO("fe%d: SMATV_REMOTE_TUNING", fenumber); break; case DISEQC_1_0: INFO("fe%d: DISEQC_1_0", fenumber); break; case DISEQC_1_1: INFO("fe%d: DISEQC_1_1", fenumber); break; case DISEQC_1_2: INFO("fe%d: DISEQC_1_2", fenumber); break; case DISEQC_ADVANCED: INFO("fe%d: DISEQC_ADVANCED", fenumber); break; case DISEQC_UNICABLE: INFO("fe%d: DISEQC_UNICABLE", fenumber); break; #if 0 case DISEQC_2_0: INFO("DISEQC_2_0"); break; case DISEQC_2_1: INFO("DISEQC_2_1"); break; case DISEQC_2_2: INFO("DISEQC_2_2"); break; #endif default: WARN("Invalid DiSEqC type"); return; } if (newDiseqcType == DISEQC_UNICABLE) { secSetTone(SEC_TONE_OFF, 0); secSetVoltage(SEC_VOLTAGE_13, 0); } else if ((force && (newDiseqcType != NO_DISEQC)) || ((config.diseqcType <= MINI_DISEQC) && (newDiseqcType > MINI_DISEQC))) { secSetTone(SEC_TONE_OFF, 15); sendDiseqcReset(); sendDiseqcPowerOn(); secSetTone(SEC_TONE_ON, 50); } config.diseqcType = newDiseqcType; }
void CFrontend::Init(void) { /* if frontend was not enabled before, it might not be opened */ Open(); mutex.lock(); // Set the voltage to On, and wait voltage to become stable // and wait for diseqc equipment to be ready. secSetVoltage(SEC_VOLTAGE_13, 100); secSetTone(SEC_TONE_OFF, 20); setDiseqcType((diseqc_t) config.diseqcType, true); setTsidOnid(0); mutex.unlock(); }
void CFrontend::setMasterSlave(bool _slave) { if(slave == _slave) return; if(_slave) { // Disable tone first as it's imposed on voltage secSetTone(SEC_TONE_OFF, 20); // Disable voltage immediately and wait 50ms to prevent // a fast power-off -> power-on sequence where diseqc equipment // might not reset properly. secSetVoltage(SEC_VOLTAGE_OFF, 50); } slave = _slave; if(!slave) Init(); }
void CFrontend::positionMotor(uint8_t motorPosition) { struct dvb_diseqc_master_cmd cmd = { {0xE0, 0x31, 0x6B, 0x00, 0x00, 0x00}, 4 }; if (motorPosition != 0) { secSetTone(SEC_TONE_OFF, 25); secSetVoltage(config.highVoltage ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13, 15); cmd.msg[3] = motorPosition; for (int i = 0; i <= repeatUsals; ++i) sendDiseqcCommand(&cmd, 50); printf("[fe%d] motor positioning command sent.\n", fenumber); } }
CFrontend::~CFrontend(void) { if (diseqcType > MINI_DISEQC) sendDiseqcStandby(); /* tested on dm500, VOLTAGE_OFF switched into passthrough mode, FE_POWER_OFF does something else to save some power... It does no harm on dbox2, at least not on philips sat enigma does exactly the same it its savePower() function */ secSetVoltage(SEC_VOLTAGE_OFF, 1); secSetTone(SEC_TONE_OFF, 1); #if HAVE_DVB_API_VERSION < 3 fop(ioctl, FE_SET_POWER_STATE, FE_POWER_OFF); if (secfd >= 0) close(secfd); #endif close(fd); }
void CFrontend::Close(void) { if(standby) return; INFO("[fe%d] close frontend fd %d", fenumber, fd); if (!slave && config.diseqcType > MINI_DISEQC) sendDiseqcStandby(); // Disable tone first as it's imposed on voltage secSetTone(SEC_TONE_OFF, 20); // Disable voltage immediately and wait 50ms to prevent // a fast power-off -> power-on sequence where diseqc equipment // might not reset properly. secSetVoltage(SEC_VOLTAGE_OFF, 50); tuned = false; standby = true;; close(fd); fd = -1; }
void CFrontend::setSec(const uint8_t sat_no, const uint8_t pol, const bool high_band, const uint32_t frequency) { uint8_t repeats = diseqcRepeats; fe_sec_voltage_t v = (pol & 1) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18; fe_sec_tone_mode_t t = high_band ? SEC_TONE_ON : SEC_TONE_OFF; fe_sec_mini_cmd_t b = (sat_no & 1) ? SEC_MINI_B : SEC_MINI_A; /* * [0] from master, no reply, 1st transmission * [1] any lnb switcher or smatv * [2] write to port group 0 (committed switches) * [3] high nibble: reset bits, low nibble set bits * bits are: option, position, polarizaion, band */ struct dvb_diseqc_master_cmd cmd = { { 0xe0, 0x10, 0x38, 0x00, 0x00, 0x00 }, 4 }; cmd.msg[3] = 0xf0 | (((sat_no * 4) & 0x0f) | (high_band ? 1 : 0) | ((pol & 1) ? 0 : 2)); /* * set all SEC / DiSEqC parameters */ secSetTone(SEC_TONE_OFF, 15); secSetVoltage(v, 15); if ((diseqcType == DISEQC_1_1) && (uncommitted_switch_mode > 0)) { static uint8_t prevSatNo = 255; // initialised with greater than max Satellites (64) // because we only want to send uncommitted switch // command if necessary to save zap time DBG("new Sat %d previous Sat %d", sat_no, prevSatNo); //DBG("new Sat/4 %d previous Sat/4 %d", sat_no/4, prevSatNo/4); if ((prevSatNo/4 != sat_no/4) && (1 == uncommitted_switch_mode)) { sendUncommittedSwitchesCommand(0xF0 + sat_no/4); } else if ((prevSatNo != sat_no) && (2 == uncommitted_switch_mode)) { sendUncommittedSwitchesCommand(0xF0 + sat_no); } prevSatNo = sat_no; } if (diseqcType >= SMATV_REMOTE_TUNING) { #if HAVE_DVB_API_VERSION >= 3 if (diseqcType >= DISEQC_2_0) cmd.msg[0] |= 0x02; /* reply required */ sendDiseqcCommand(&cmd, 15); if (diseqcType >= DISEQC_2_0) repeats += getDiseqcReply(50); #else sendDiseqcCommand(&cmd, 15); #endif } if ((diseqcType >= DISEQC_1_1) && (repeats)) { for (uint16_t i = 0; i < repeats; i++) { usleep(1000 * 100); /* wait at least 100ms before retransmission */ if (0 == uncommitted_switch_mode) { cmd.msg[2] |= 0x01; /* uncommitted switches */ sendDiseqcCommand(&cmd, 15); } #if HAVE_DVB_API_VERSION >= 3 uint8_t again = 0; if (diseqcType >= DISEQC_2_0) again += getDiseqcReply(50); cmd.msg[0] |= 0x01; /* repeated transmission */ cmd.msg[2] &= 0xFE; /* committed switches */ sendDiseqcCommand(&cmd, 15); if (diseqcType >= DISEQC_2_0) again += getDiseqcReply(50); if (again == 2) repeats++; #else cmd.msg[0] |= 0x01; /* repeated transmission */ cmd.msg[2] &= 0xFE; /* committed switches */ sendDiseqcCommand(&cmd, 15); #endif } } if (diseqcType == SMATV_REMOTE_TUNING) sendDiseqcSmatvRemoteTuningCommand(frequency); if (diseqcType == MINI_DISEQC) sendToneBurst(b, 15); secSetTone(t, 15); currentTransponder.diseqc = sat_no; }
static int sec_ioctl(struct dvb_device *dvbdev, struct file*file, unsigned int cmd, unsigned long arg) { struct dvb_struct *dvb=(struct dvb_struct *) dvbdev->priv; void *parg=(void *)arg; if (file->f_flags&O_NONBLOCK) return -EWOULDBLOCK; switch (cmd) { case SEC_GET_STATUS: { struct secStatus status; status.busMode=SEC_BUS_IDLE; if (dvb->secbusy) status.busMode=SEC_BUS_BUSY; if (!dvb->sec.power) status.busMode=SEC_BUS_OFF; status.selVolt=(dvb->sec.volt ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13); status.contTone=(dvb->sec.ttk ? SEC_TONE_ON : SEC_TONE_OFF); if (copy_to_user(parg, &status, sizeof(status))) return -EFAULT; break; } case SEC_RESET_OVERLOAD: if ((file->f_flags&O_ACCMODE)==O_RDONLY) return -EPERM; break; case SEC_SEND_SEQUENCE: { struct secCmdSequence seq; if(copy_from_user(&seq, parg, sizeof(seq))) return -EFAULT; if ((file->f_flags&O_ACCMODE)==O_RDONLY) return -EPERM; dvb_frontend_stop(dvb->frontend); return secSendSequence(dvb, &seq); } case SEC_SET_TONE: { secToneMode mode = (secToneMode) arg; if ((file->f_flags&O_ACCMODE)==O_RDONLY) return -EPERM; dvb_frontend_stop(dvb->frontend); return secSetTone(dvb, mode); } case SEC_SET_VOLTAGE: { secVoltage val = (secVoltage) arg; if ((file->f_flags&O_ACCMODE)==O_RDONLY) return -EPERM; dvb_frontend_stop(dvb->frontend); return secSetVoltage(dvb, val); } default: return -ENOIOCTLCMD; } return 0; }