Ticket #1945: dvbdevtree_integration.patch
File dvbdevtree_integration.patch, 58.4 KB (added by , 18 years ago) |
---|
-
libs/libmythtv/dvbdiseqc.h
1 /*2 * Copyright (C) Kenneth Aafloy 20033 *4 * Copyright notice is in dvbdiseqc.cpp of the MythTV project.5 */6 7 #ifndef DVBDISEQC_H8 #define DVBDISEQC_H9 10 #include "pthread.h"11 #include "qsqldatabase.h"12 #include "tv_rec.h"13 #include "dvbtypes.h"14 #include <linux/dvb/frontend.h>15 16 #define DISEQC_SHORT_WAIT 15*100017 #define DISEQC_LONG_WAIT 100*100018 19 class DVBDiSEqC20 {21 public:22 DVBDiSEqC(int cardnum, int fd_frontend);23 ~DVBDiSEqC();24 25 bool Set(DVBTuning& tuning, bool reset, bool& havetuned);26 bool DiseqcReset();27 28 private:29 int cardnum;30 int fd_frontend;31 DVBTuning prev_tuning;32 int repeat;33 34 35 bool SendDiSEqCMessage(DVBTuning& tuning, dvb_diseqc_master_cmd &cmd);36 bool SendDiSEqCMessage(dvb_diseqc_master_cmd &cmd);37 38 bool ToneVoltageLnb(DVBTuning& tuning, bool reset, bool& havetuned);39 bool ToneSwitch(DVBTuning& tuning, bool reset, bool& havetuned);40 bool LegacyDishSwitch(DVBTuning& tuning, bool reset, bool& havetuned);41 bool Diseqc1xSwitch(DVBTuning& tuning, bool reset, bool& havetuned,42 uint ports);43 bool PositionerGoto(DVBTuning& tuning, bool reset, bool& havetuned);44 bool PositionerStore(DVBTuning& tuning);45 bool PositionerStopMovement();46 bool PositionerStoreEastLimit();47 bool PositionerStoreWestLimit();48 bool PositionerDisableLimits();49 bool PositionerDriveEast(int timestep);50 bool PositionerDriveWest(int timestep);51 bool PositionerGotoAngular(DVBTuning& tuning, bool reset,52 bool& havetuned);53 54 // Still need to be written55 bool Positioner_Status();56 57 enum diseqc_cmd_bytes {58 FRAME = 0x0,59 ADDRESS = 0x1,60 COMMAND = 0x2,61 DATA_1 = 0x3,62 DATA_2 = 0x4,63 DATA_3 = 0x564 };65 66 enum diseqc_frame_byte {67 CMD_FIRST = 0xe0,68 CMD_REPEAT = 0xe1,69 CMD_REPLY_FIRST = 0xe2,70 CMD_REPLY_REPEAT = 0xe3,71 REPLY_OK = 0xe4,72 REPLY_NOSUPPORT = 0xe5,73 REPLY_CRCERR_RPT = 0xe6,74 REPLY_CMDERR_RPT = 0xe775 };76 77 enum diseqc_address {78 MASTER_TO_ALL = 0x00,79 MASTER_TO_LSS = 0x10,80 MASTER_TO_LNB = 0x11,81 MASTER_TO_SWITCH = 0x14,82 MASTER_TO_POSITIONER = 0x3183 };84 85 86 enum diseqc_commands {87 RESET = 0x00,88 CLR_RESET = 0x01,89 STANDBY = 0x02,90 POWERON = 0x03,91 SET_LO = 0x20,92 SET_VR = 0x21,93 SET_POS_A = 0x22,94 SET_SO_A = 0x23,95 SET_HI = 0x24,96 SET_HL = 0x25,97 SET_POS_B = 0x26,98 SET_SO_B = 0x27,99 WRITE_N0 = 0x38,100 WRITE_N1 = 0x39,101 WRITE_N2 = 0x3A,102 WRITE_N3 = 0x3B,103 READ_LNB_LOF_LO = 0x52,104 READ_LNB_LOF_HI = 0x53,105 106 HALT = 0x60,107 LIMITS_OFF = 0x63,108 POS_STAT = 0x64,109 LIMIT_E = 0x66,110 LIMIT_W = 0x67,111 DRIVE_E = 0x68,112 DRIVE_W = 0x69,113 STORE = 0x6A,114 GOTO = 0x6B,115 GOTO_ANGULAR = 0x6E116 };117 118 };119 120 #endif // DVBDISEQC_H -
libs/libmythtv/dvbdiseqc.cpp
1 /*2 * Class DVBDiSEqC3 *4 * Copyright (C) Kenneth Aafloy 20035 *6 * Description:7 *8 * Author(s):9 * Taylor Jacob (rtjacob at earthlink.net)10 * - Finished Implimenting Petri's DiSEqC 1.0 - 1.1 code11 * - DiSEqC 1.2 Positioner control12 * Petri Nykanen13 * - DiSEqC 1.0 - 1.1.14 * Kenneth Aafloy (ke-aa at frisurf.no)15 * - Initial framework.16 *17 * This program is free software; you can redistribute it and/or modify18 * it under the terms of the GNU General Public License as published by19 * the Free Software Foundation; either version 2 of the License, or20 * (at your option) any later version.21 *22 * This program is distributed in the hope that it will be useful,23 * but WITHOUT ANY WARRANTY; without even the implied warranty of24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the25 * GNU General Public License for more details.26 *27 * You should have received a copy of the GNU General Public License28 * along with this program; if not, write to the Free Software29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA30 */31 32 #include <iostream>33 #include <cmath>34 35 #include "pthread.h"36 #include "qsqldatabase.h"37 38 #include "mythcontext.h"39 #include "tv_rec.h"40 #include "cardutil.h"41 42 #include "dvbtypes.h"43 #include "dvbdiseqc.h"44 45 #define TO_RADS (M_PI / 180.0)46 #define TO_DEC (180.0 / M_PI)47 48 #define LOC QString("DiSEqC(%1): ").arg(cardnum)49 #define LOC_ERR QString("DiSEqC(%1) Error: ").arg(cardnum)50 51 DVBDiSEqC::DVBDiSEqC(int _cardnum, int _fd_frontend):52 cardnum(_cardnum), fd_frontend(_fd_frontend)53 {54 55 // Number of repeats for DiSEqC 1.1 devices56 repeat = 1;57 }58 59 DVBDiSEqC::~DVBDiSEqC()60 {61 }62 63 bool DVBDiSEqC::Set(DVBTuning& tuning, bool reset, bool& havetuned)64 {65 switch (tuning.diseqc_type)66 {67 case DISEQC_MINI_2:68 if (!ToneSwitch(tuning, reset, havetuned))69 return false;70 // fall through71 case DISEQC_SINGLE:72 if (!ToneVoltageLnb(tuning, reset, havetuned))73 return false;74 break;75 case DISEQC_SWITCH_2_1_0: // 2 Way v1.076 case DISEQC_SWITCH_2_1_1: // 2 Way v1.177 if (!Diseqc1xSwitch(tuning, reset, havetuned, 2))78 return false;79 break;80 case DISEQC_SWITCH_4_1_0: // 4 Way v1.081 case DISEQC_SWITCH_4_1_1: // 4 Way v1.182 if (!Diseqc1xSwitch(tuning, reset, havetuned, 4))83 return false;84 break;85 case DISEQC_POSITIONER_1_2: // 1.2 Positioner (HH Motor)86 if (!PositionerGoto(tuning,reset,havetuned))87 return false;88 break;89 case DISEQC_POSITIONER_X: // 1.3 Positioner (HH Motor with USALS)90 if (!PositionerGotoAngular(tuning,reset,havetuned))91 return false;92 break;93 case DISEQC_POSITIONER_1_2_SWITCH_2: // 10 Way v1.1 or v2.194 if (!Diseqc1xSwitch(tuning, reset, havetuned, 10))95 return false;96 break;97 case DISEQC_SW21: // Dish Network legacy switch SW2198 case DISEQC_SW64: // Dish Network legacy switch SW6499 if (!LegacyDishSwitch(tuning, reset, havetuned))100 return false;101 break;102 103 default:104 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unsupported DiSEqC type("105 <<tuning.diseqc_type<<")");106 }107 108 return true;109 }110 111 bool DVBDiSEqC::LegacyDishSwitch(DVBTuning &tuning, bool reset,112 bool &havetuned)113 {114 VERBOSE(VB_CHANNEL, LOC + "Legacy Dish Switch: " +115 QString("Port %1").arg(tuning.diseqc_port));116 117 if (reset ||118 (prev_tuning.diseqc_port != tuning.diseqc_port ||119 prev_tuning.tone != tuning.tone ||120 prev_tuning.voltage != tuning.voltage))121 {122 uint8_t cmd = 0x00;123 124 if (DISEQC_SW21 == tuning.diseqc_type)125 cmd = (tuning.diseqc_port) ? 0x66 : 0x34;126 else if (DISEQC_SW64 == tuning.diseqc_type)127 {128 if (tuning.diseqc_port == 0)129 cmd = (tuning.voltage == SEC_VOLTAGE_13) ? 0x39 : 0x1A;130 else if (tuning.diseqc_port == 1)131 cmd = (tuning.voltage == SEC_VOLTAGE_13) ? 0x4B : 0x5C;132 else133 cmd = (tuning.voltage == SEC_VOLTAGE_13) ? 0x0D : 0x2E;134 }135 136 if (tuning.voltage == SEC_VOLTAGE_18)137 cmd |= 0x80;138 139 #ifdef FE_DISHNETWORK_SEND_LEGACY_CMD140 if (ioctl(fd_frontend, FE_DISHNETWORK_SEND_LEGACY_CMD, cmd) <0)141 {142 VERBOSE(VB_IMPORTANT, LOC_ERR + "Legacy Dish Switch: "143 "Sending init command failed." + ENO);144 return false;145 }146 #else147 VERBOSE(VB_IMPORTANT, LOC_ERR + "Legacy Dish Switch: " +148 "Linux kernel does not support this switch.");149 #endif150 151 usleep(DISEQC_SHORT_WAIT);152 153 prev_tuning.diseqc_port = tuning.diseqc_port;154 prev_tuning.tone = tuning.tone;155 prev_tuning.voltage = tuning.voltage;156 havetuned = true;157 }158 return true;159 }160 161 /*****************************************************************************162 Backward Compatible Methods163 ****************************************************************************/164 165 bool DVBDiSEqC::ToneVoltageLnb(DVBTuning& tuning, bool reset, bool& havetuned)166 {167 VERBOSE(VB_CHANNEL, LOC + QString("Setting LNB: %1 %2")168 .arg(tuning.tone==SEC_TONE_ON?"Tone ON":"Tone OFF")169 .arg(tuning.voltage==SEC_VOLTAGE_13?"13V":"18V"));170 171 if (prev_tuning.tone != tuning.tone || reset)172 {173 if (ioctl(fd_frontend, FE_SET_TONE, tuning.tone) < 0)174 {175 VERBOSE(VB_IMPORTANT, LOC_ERR +176 "Setting Tone mode failed." + ENO);177 return false;178 }179 180 prev_tuning.tone = tuning.tone;181 }182 183 usleep(DISEQC_SHORT_WAIT);184 185 if (prev_tuning.voltage != tuning.voltage || reset)186 {187 if (ioctl(fd_frontend, FE_SET_VOLTAGE, tuning.voltage) < 0)188 {189 VERBOSE(VB_IMPORTANT, LOC_ERR +190 "Setting Polarization failed." + ENO);191 return false;192 }193 194 prev_tuning.voltage = tuning.voltage;195 }196 197 havetuned |= ((prev_tuning.voltage == tuning.voltage) &&198 (prev_tuning.tone == tuning.tone));199 200 return true;201 }202 203 bool DVBDiSEqC::ToneSwitch(DVBTuning& tuning, bool reset, bool& havetuned)204 {205 VERBOSE(VB_CHANNEL, LOC + QString("Tone Switch - Port %1/2")206 .arg(tuning.diseqc_port));207 208 if (prev_tuning.diseqc_port != tuning.diseqc_port || reset)209 {210 if (tuning.diseqc_port > 2)211 VERBOSE(VB_IMPORTANT, LOC_ERR +212 "Tone Switches only support two ports.");213 214 if (ioctl(fd_frontend, FE_DISEQC_SEND_BURST,215 (tuning.diseqc_port == 1 ? SEC_MINI_A : SEC_MINI_B )) < 0)216 {217 VERBOSE(VB_IMPORTANT, LOC_ERR +218 "Setting Tone Switch failed." + ENO);219 return false;220 }221 222 prev_tuning.diseqc_port = tuning.diseqc_port;223 }224 225 havetuned |= (prev_tuning.diseqc_port == tuning.diseqc_port);226 227 return true;228 }229 230 /*****************************************************************************231 Diseqc 1.x Compatible Methods232 ****************************************************************************/233 234 bool DVBDiSEqC::SendDiSEqCMessage(DVBTuning& tuning, dvb_diseqc_master_cmd &cmd)235 {236 // Turn off tone burst237 if (ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF) == -1)238 {239 VERBOSE(VB_IMPORTANT, LOC_ERR + "FE_SET_TONE failed" + ENO);240 return false;241 }242 243 /*244 Old version of the code set the voltage to 13V everytime.245 After looking at the EutelSat specs I saw no reason that246 this was done. I have tested this with my DiSEqC switch247 and all is fine.248 */249 250 if (ioctl(fd_frontend, FE_SET_VOLTAGE, tuning.voltage) == -1)251 {252 VERBOSE(VB_IMPORTANT, LOC_ERR + "FE_SET_VOLTAGE failed" + ENO);253 return false;254 }255 256 usleep(DISEQC_SHORT_WAIT);257 258 VERBOSE(VB_CHANNEL, LOC + QString("Sending 1.0 Command: %1 %2 %3 %4")259 .arg(cmd.msg[0], 2, 16)260 .arg(cmd.msg[1], 2, 16)261 .arg(cmd.msg[2], 2, 16)262 .arg(cmd.msg[3], 2, 16));263 264 if (ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd) == -1)265 {266 VERBOSE(VB_IMPORTANT, LOC_ERR +267 "FE_DISEQC_SEND_MASTER_CMD failed" + ENO);268 return false;269 }270 271 usleep(DISEQC_SHORT_WAIT);272 273 // Check to see if its a 1.1 or 1.2 device.274 // If so repeat the message repeats times.275 if ((tuning.diseqc_type == DISEQC_SWITCH_2_1_1) ||276 (tuning.diseqc_type == DISEQC_SWITCH_4_1_1) ||277 (tuning.diseqc_type == DISEQC_POSITIONER_1_2) ||278 (tuning.diseqc_type == DISEQC_POSITIONER_X))279 {280 281 int repeats = repeat;282 while (repeats--)283 {284 285 if (tuning.diseqc_type == DISEQC_POSITIONER_X)286 {287 VERBOSE(VB_CHANNEL, LOC +288 QString("Sending 1.3 Repeat Command: %1 %2 %3 %4 %5")289 .arg(cmd.msg[0],2,16)290 .arg(cmd.msg[1],2,16)291 .arg(cmd.msg[2],2,16)292 .arg(cmd.msg[3],2,16)293 .arg(cmd.msg[4],2,16));294 }295 else296 {297 VERBOSE(VB_CHANNEL, LOC +298 QString("Sending 1.1/1.2 Repeat Command: %1 %2 %3 %4")299 .arg(cmd.msg[0],2,16)300 .arg(cmd.msg[1],2,16)301 .arg(cmd.msg[2],2,16)302 .arg(cmd.msg[3],2,16));303 }304 305 cmd.msg[0] = CMD_REPEAT;306 if (ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd) == -1)307 {308 VERBOSE(VB_IMPORTANT, LOC_ERR +309 "FE_DISEQC_SEND_MASTER_CMD failed" + ENO);310 return false;311 }312 usleep(DISEQC_SHORT_WAIT);313 314 cmd.msg[0] = CMD_FIRST;315 if (ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd) == -1)316 {317 VERBOSE(VB_IMPORTANT, LOC_ERR +318 "FE_DISEQC_SEND_MASTER_CMD failed" + ENO);319 return false;320 }321 usleep(DISEQC_SHORT_WAIT);322 }323 }324 325 if (ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_A ) == -1)326 {327 VERBOSE(VB_IMPORTANT, LOC_ERR +328 "FE_DISEQC_SEND_BURST failed" + ENO);329 return false;330 }331 332 usleep(DISEQC_SHORT_WAIT);333 334 if (ioctl(fd_frontend, FE_SET_TONE, tuning.tone) == -1)335 {336 VERBOSE(VB_IMPORTANT, LOC_ERR + "FE_SET_TONE failed" + ENO);337 return false;338 }339 340 return true;341 }342 343 344 bool DVBDiSEqC::SendDiSEqCMessage(dvb_diseqc_master_cmd &cmd)345 {346 // Turn off tone burst347 if (ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF) == -1)348 {349 VERBOSE(VB_IMPORTANT, LOC_ERR + "FE_SET_TONE failed" + ENO);350 return false;351 }352 353 usleep(DISEQC_SHORT_WAIT);354 355 VERBOSE(VB_CHANNEL, LOC + QString("Sending 1.0 Command: %1 %2 %3 %4")356 .arg(cmd.msg[0], 2, 16)357 .arg(cmd.msg[1], 2, 16)358 .arg(cmd.msg[2], 2, 16)359 .arg(cmd.msg[3], 2, 16));360 361 if (ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd) == -1)362 {363 VERBOSE(VB_IMPORTANT, LOC_ERR +364 "FE_DISEQC_SEND_MASTER_CMD failed" + ENO);365 return false;366 }367 368 usleep(DISEQC_SHORT_WAIT);369 370 int repeats = repeat;371 while (repeats--)372 {373 VERBOSE(VB_CHANNEL, LOC +374 QString("Sending 1.1/1.2/1.3 Repeat Command: %1 %2 %3 %4")375 .arg(cmd.msg[0], 2, 16)376 .arg(cmd.msg[1], 2, 16)377 .arg(cmd.msg[2], 2, 16)378 .arg(cmd.msg[3], 2, 16));379 380 cmd.msg[0] = CMD_REPEAT;381 if (ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd) == -1)382 {383 VERBOSE(VB_IMPORTANT, LOC_ERR +384 "FE_DISEQC_SEND_MASTER_CMD failed" + ENO);385 return false;386 }387 usleep(DISEQC_SHORT_WAIT);388 389 cmd.msg[0] = CMD_FIRST;390 if (ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd) == -1)391 {392 VERBOSE(VB_IMPORTANT, LOC_ERR +393 "FE_DISEQC_SEND_MASTER_CMD failed" + ENO);394 return false;395 }396 usleep(DISEQC_SHORT_WAIT);397 }398 399 if (ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_A ) == -1)400 {401 VERBOSE(VB_IMPORTANT, LOC_ERR + "FE_DISEQC_SEND_BURST failed" + ENO);402 return false;403 }404 405 return true;406 }407 408 bool DVBDiSEqC::Diseqc1xSwitch(DVBTuning& tuning, bool reset,409 bool& havetuned, uint ports)410 {411 if (reset)412 {413 if (!DiseqcReset())414 {415 VERBOSE(VB_IMPORTANT, LOC_ERR + "DiseqcReset() failed");416 return false;417 }418 }419 420 VERBOSE(VB_CHANNEL, LOC +421 QString("1.1 Switch (%1 ports) - Port %2 - %3 %4")422 .arg(ports)423 .arg(tuning.diseqc_port)424 .arg(tuning.tone==SEC_TONE_ON?"Tone ON":"Tone OFF")425 .arg(tuning.voltage==SEC_VOLTAGE_13?"13V":"18V"));426 427 if ((prev_tuning.diseqc_port != tuning.diseqc_port ||428 prev_tuning.tone != tuning.tone ||429 prev_tuning.voltage != tuning.voltage ) || reset)430 {431 dvb_diseqc_master_cmd cmd =432 {{CMD_FIRST, MASTER_TO_LSS, WRITE_N1, 0xf0, 0x00, 0x00}, 4};433 434 if (tuning.diseqc_port >= ports )435 {436 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unsupported switch");437 return false;438 }439 440 switch (ports)441 {442 case 10:443 cmd.msg[COMMAND] = WRITE_N1;444 cmd.msg[DATA_1] = 0xF0 | (tuning.diseqc_port & 0x0F);445 break;446 case 4:447 case 2:448 cmd.msg[COMMAND] = WRITE_N0;449 cmd.msg[DATA_1] =450 0xF0 |451 (((tuning.diseqc_port) * 4) & 0x0F) |452 ((tuning.voltage == SEC_VOLTAGE_18) ? 2 : 0) |453 ((tuning.tone == SEC_TONE_ON) ? 1 : 0);454 break;455 default:456 VERBOSE(VB_IMPORTANT, LOC_ERR +457 "Unsupported number of ports for DiSEqC 1.1 Switch");458 }459 460 if (!SendDiSEqCMessage(tuning,cmd))461 {462 VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting DiSEqC failed.");463 return false;464 }465 466 prev_tuning.diseqc_port = tuning.diseqc_port;467 prev_tuning.tone = tuning.tone;468 prev_tuning.voltage = tuning.voltage;469 havetuned = true;470 471 }472 473 havetuned |=474 (prev_tuning.diseqc_port == tuning.diseqc_port) &&475 (prev_tuning.voltage == tuning.voltage) &&476 (prev_tuning.tone == tuning.tone);477 478 return true;479 }480 481 bool DVBDiSEqC::DiseqcReset()482 {483 struct dvb_diseqc_master_cmd reset_cmd =484 {{CMD_FIRST, MASTER_TO_LSS, RESET, 0x00, 0x00}, 3};485 486 struct dvb_diseqc_master_cmd init_cmd =487 {{CMD_FIRST, MASTER_TO_LSS, POWERON, 0x00, 0x00}, 3};488 489 if (ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &init_cmd) <0)490 {491 VERBOSE(VB_IMPORTANT, LOC_ERR +492 "Setup: Sending init command failed." + ENO);493 return false;494 }495 usleep(DISEQC_LONG_WAIT);496 497 if (ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &reset_cmd) <0)498 {499 VERBOSE(VB_IMPORTANT, LOC_ERR +500 "Setup: Sending reset command failed." + ENO);501 return false;502 }503 usleep(DISEQC_LONG_WAIT);504 505 if (ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &init_cmd) <0)506 {507 VERBOSE(VB_IMPORTANT, LOC_ERR +508 "Setup: Sending init command failed." + ENO);509 return false;510 }511 usleep(DISEQC_LONG_WAIT);512 513 return true;514 }515 516 /*****************************************************************************517 Positioner Control518 *****************************************************************************/519 520 bool DVBDiSEqC::PositionerDriveEast(int timestep)521 {522 if (!DiseqcReset())523 {524 VERBOSE(VB_IMPORTANT, LOC_ERR + "DiseqcReset() failed");525 return false;526 }527 528 dvb_diseqc_master_cmd cmd =529 {{CMD_FIRST, MASTER_TO_POSITIONER, DRIVE_E, timestep ,0x00,0x00}, 4};530 531 if (!SendDiSEqCMessage(cmd))532 {533 VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting DiSEqC failed.");534 return false;535 }536 537 return true;538 }539 540 bool DVBDiSEqC::PositionerDriveWest(int timestep)541 {542 if (!DiseqcReset())543 {544 VERBOSE(VB_IMPORTANT, LOC_ERR + "DiseqcReset() failed");545 return false;546 }547 548 dvb_diseqc_master_cmd cmd =549 {{CMD_FIRST, MASTER_TO_POSITIONER, DRIVE_W, timestep ,0x00,0x00}, 4};550 551 if (!SendDiSEqCMessage(cmd))552 {553 VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting DiSEqC failed.");554 return false;555 }556 557 return true;558 }559 560 bool DVBDiSEqC::PositionerGoto(DVBTuning& tuning, bool reset, bool& havetuned)561 {562 // A reset seems to be required for my positioner to work consistently563 VERBOSE(VB_CHANNEL, LOC + QString("1.2 Motor - Goto Stored Position %1")564 .arg(tuning.diseqc_port));565 566 if ((prev_tuning.diseqc_port != tuning.diseqc_port ||567 prev_tuning.tone != tuning.tone ||568 prev_tuning.voltage != tuning.voltage) || reset)569 {570 if (!DiseqcReset())571 {572 VERBOSE(VB_IMPORTANT, LOC_ERR + "DiseqcReset() failed");573 return false;574 }575 576 dvb_diseqc_master_cmd cmd =577 {{CMD_FIRST, MASTER_TO_POSITIONER, GOTO, tuning.diseqc_port,578 0x00, 0x00}, 4};579 580 if (!SendDiSEqCMessage(tuning,cmd))581 {582 VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting DiSEqC failed.");583 return false;584 }585 586 prev_tuning.diseqc_port = tuning.diseqc_port;587 prev_tuning.tone = tuning.tone;588 prev_tuning.voltage = tuning.voltage;589 }590 591 havetuned |=592 (prev_tuning.diseqc_port == tuning.diseqc_port) &&593 (prev_tuning.voltage == tuning.voltage) &&594 (prev_tuning.tone == tuning.tone);595 596 return true;597 }598 599 bool DVBDiSEqC::PositionerStore(DVBTuning& tuning)600 {601 if (!DiseqcReset())602 {603 VERBOSE(VB_IMPORTANT, LOC_ERR + "DiseqcReset() failed");604 return false;605 }606 607 VERBOSE(VB_CHANNEL, LOC + QString("1.2 Motor - Store Stored Position %1")608 .arg(tuning.diseqc_port));609 610 dvb_diseqc_master_cmd cmd =611 {{CMD_FIRST, MASTER_TO_POSITIONER, STORE, tuning.diseqc_port , 0x00,612 0x00}, 4};613 614 if (!SendDiSEqCMessage(cmd))615 {616 VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting DiSEqC failed.");617 return false;618 }619 620 return true;621 }622 623 bool DVBDiSEqC::PositionerStoreEastLimit()624 {625 if (!DiseqcReset())626 {627 VERBOSE(VB_IMPORTANT, LOC_ERR + "DiseqcReset() failed");628 return false;629 }630 631 dvb_diseqc_master_cmd cmd =632 {{CMD_FIRST, MASTER_TO_POSITIONER, LIMIT_E, 0x00,0x00,0x00}, 3};633 634 if (!SendDiSEqCMessage(cmd))635 {636 VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting DiSEqC failed.");637 return false;638 }639 640 return true;641 }642 643 bool DVBDiSEqC::PositionerStoreWestLimit()644 {645 if (!DiseqcReset())646 {647 VERBOSE(VB_IMPORTANT, LOC_ERR + "DiseqcReset() failed");648 return false;649 }650 651 dvb_diseqc_master_cmd cmd =652 {{CMD_FIRST, MASTER_TO_POSITIONER, LIMIT_W, 0x00,0x00,0x00}, 3};653 654 if (!SendDiSEqCMessage(cmd))655 {656 VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting DiSEqC failed.");657 return false;658 }659 660 return true;661 }662 663 bool DVBDiSEqC::PositionerStopMovement()664 {665 if (!DiseqcReset())666 {667 VERBOSE(VB_IMPORTANT, LOC_ERR + "DiseqcReset() failed");668 return false;669 }670 671 dvb_diseqc_master_cmd cmd =672 {{CMD_FIRST, MASTER_TO_POSITIONER, HALT, 0x00,0x00,0x00}, 3};673 674 if (!SendDiSEqCMessage(cmd))675 {676 VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting DiSEqC failed.");677 return false;678 }679 return true;680 681 }682 683 bool DVBDiSEqC::Positioner_Status()684 {685 // Not sure if this function is possible without being DiSEqC >= v2686 // Someone with a DVB card that supports v2 cards will need to help me out687 // here688 return false;689 }690 691 bool DVBDiSEqC::PositionerDisableLimits()692 {693 if (!DiseqcReset())694 {695 VERBOSE(VB_IMPORTANT, LOC_ERR + "DiseqcReset() failed");696 return false;697 }698 699 dvb_diseqc_master_cmd cmd =700 {{CMD_FIRST, MASTER_TO_POSITIONER, LIMITS_OFF, 0x00,0x00,0x00}, 3};701 702 if (!SendDiSEqCMessage(cmd))703 {704 VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting DiSEqC failed.");705 return false;706 }707 708 return true;709 }710 711 /*****************************************************************************712 Diseqc v1.3 (Goto X)713 ****************************************************************************/714 715 bool DVBDiSEqC::PositionerGotoAngular(DVBTuning& tuning, bool reset,716 bool& havetuned)717 {718 // TODO: Send information here to FE saying motor is moving and719 // to expect a longer than average tuning delay720 if (prev_tuning.diseqc_pos != tuning.diseqc_pos)721 VERBOSE(VB_CHANNEL, LOC + "DiSEqC Motor Moving");722 723 if (!DiseqcReset())724 {725 VERBOSE(VB_IMPORTANT, LOC_ERR + "DiseqcReset() failed");726 return false;727 }728 729 VERBOSE(VB_CHANNEL, LOC + QString("1.3 Motor - Goto Angular Position %1")730 .arg(tuning.diseqc_pos));731 732 // Equation lifted from VDR rotor plugin by733 // Thomas Bergwinkl <Thomas.Bergwinkl@t-online.de>734 735 // Earth Station Latitude and Longitude in radians736 double P = gContext->GetSetting("Latitude", "").toFloat() * TO_RADS;737 double Ue = gContext->GetSetting("Longitude", "").toFloat() * TO_RADS;738 739 // Satellite Longitude in radians740 double Us = tuning.diseqc_pos * TO_RADS;741 742 double az = M_PI + atan( tan(Us - Ue) / sin(P) );743 double x = acos( cos(Us - Ue) * cos(P) );744 double el = atan( (cos(x) - 0.1513) / sin(x) );745 double tmp_a = -cos(el) * sin(az);746 double tmp_b = (sin(el) * cos(P)) - (cos(el) * sin(P) * cos(az));747 double azimuth = atan(tmp_a / tmp_b) * TO_DEC;748 749 // Bytes sent to motor750 // cmd1 high nibble is 1110b/0xE0 for east or 1101b/0xD0 for west751 // cmd1 low nibble is angle / 16752 // cmd2 high nibble is angle % 16753 // cmd2 low nibble is (angle * 16) % 16754 uint az16 = (unsigned int) (abs(azimuth) * 16.0);755 uint cmd1 = ((azimuth > 0.0) ? 0xE0 : 0xD0) | ((az16 >> 8) & 0x0f);756 uint cmd2 = (az16 & 0xff);757 758 dvb_diseqc_master_cmd cmd =759 {{CMD_FIRST, MASTER_TO_POSITIONER, GOTO_ANGULAR, cmd1, cmd2, 0x00}, 5};760 761 if ((prev_tuning.diseqc_port != tuning.diseqc_port ||762 prev_tuning.tone != tuning.tone ||763 prev_tuning.diseqc_pos != tuning.diseqc_pos ||764 prev_tuning.voltage != tuning.voltage ) || reset)765 {766 if (!SendDiSEqCMessage(tuning, cmd))767 {768 VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting DiSEqC failed.");769 return false;770 }771 772 prev_tuning.diseqc_port = tuning.diseqc_port;773 prev_tuning.diseqc_pos = tuning.diseqc_pos;774 prev_tuning.tone = tuning.tone;775 prev_tuning.voltage = tuning.voltage;776 }777 778 havetuned |=779 (prev_tuning.diseqc_port == tuning.diseqc_port) &&780 (prev_tuning.diseqc_pos == tuning.diseqc_pos) &&781 (prev_tuning.voltage == tuning.voltage) &&782 (prev_tuning.tone == tuning.tone);783 784 return true;785 } -
libs/libmythtv/dvbtypes.cpp
416 416 } 417 417 } 418 418 419 char DVBTuning::PolarityChar() const 420 { 421 return polariz; 422 } 423 419 424 char DVBTuning::TransmissionModeChar() const 420 425 { 421 426 switch (params.u.ofdm.transmission_mode) … … 539 544 return coderate(params.u.qam.fec_inner); 540 545 } 541 546 547 QString DVBTuning::QPSKInnerFECString() const 548 { 549 return coderate(params.u.qpsk.fec_inner); 550 } 551 542 552 QString DVBTuning::GuardIntervalString() const 543 553 { 544 554 //Guard Interval … … 584 594 msg = QString("Frequency: %1 Symbol Rate: %2 Pol: %3 Inv: %4") 585 595 .arg(Frequency()) 586 596 .arg(QPSKSymbolRate()) 587 .arg( (voltage == SEC_VOLTAGE_13) ? "V/R" : "H/L")597 .arg(PolarityChar()) 588 598 .arg(InversionString()); 589 599 } 590 600 else if (FE_QAM == type) … … 676 686 bool DVBTuning::parseDVBS2( 677 687 const QString& frequency, const QString& inversion, 678 688 const QString& symbol_rate, const QString& fec_inner, 679 const QString& pol, const QString& _diseqc_type, 680 const QString& _diseqc_port, 681 const QString& _diseqc_pos, 682 const QString& _lnb_lof_switch, 683 const QString& _lnb_lof_hi, 684 const QString& _lnb_lof_lo, 689 const QString& pol, 685 690 const QString &modulation) 686 691 { 687 692 bool ok = true; … … 702 707 return false; 703 708 } 704 709 705 voltage = parsePolarity(pol, ok); 706 if (SEC_VOLTAGE_OFF == voltage) 707 { 708 VERBOSE(VB_IMPORTANT, LOC_ERR + "Invalid polarization, aborting."); 709 return false; 710 } 710 if(!pol.isEmpty()) 711 polariz = QChar(pol[0]).lower(); 711 712 712 713 p.fec_inner = parseCodeRate(fec_inner, ok); 713 714 714 715 p.modulation = parseModulation(modulation, ok); 715 diseqc_type = _diseqc_type.toInt();716 diseqc_port = _diseqc_port.toInt();717 diseqc_pos = _diseqc_pos.toFloat();718 lnb_lof_switch = _lnb_lof_switch.toInt();719 lnb_lof_hi = _lnb_lof_hi.toInt();720 lnb_lof_lo = _lnb_lof_lo.toInt();721 716 return true; 722 717 } 723 718 #endif 724 719 725 // TODO: Add in DiseqcPos when diseqc class supports it726 720 bool DVBTuning::parseQPSK(const QString& frequency, const QString& inversion, 727 721 const QString& symbol_rate, const QString& fec_inner, 728 const QString& pol, const QString& _diseqc_type, 729 const QString& _diseqc_port, 730 const QString& _diseqc_pos, 731 const QString& _lnb_lof_switch, 732 const QString& _lnb_lof_hi, 733 const QString& _lnb_lof_lo) 722 const QString& pol) 734 723 { 735 724 bool ok = true; 736 725 … … 753 742 return false; 754 743 } 755 744 756 voltage = parsePolarity(pol, ok); 757 if (SEC_VOLTAGE_OFF == voltage) 758 { 759 VERBOSE(VB_IMPORTANT, LOC_ERR + "Invalid polarization, aborting."); 745 if(!pol.isEmpty()) 746 polariz = QChar(pol[0]).lower(); 760 747 761 return false;762 }763 764 748 p.fec_inner = parseCodeRate(fec_inner, ok); 765 749 766 diseqc_type = _diseqc_type.toInt();767 diseqc_port = _diseqc_port.toInt();768 diseqc_pos = _diseqc_pos.toFloat();769 lnb_lof_switch = _lnb_lof_switch.toInt();770 lnb_lof_hi = _lnb_lof_hi.toInt();771 lnb_lof_lo = _lnb_lof_lo.toInt();772 750 return true; 773 751 } 774 752 … … 823 801 return BANDWIDTH_AUTO; 824 802 } 825 803 826 fe_sec_voltage DVBTuning::parsePolarity(const QString &pol, bool &ok)827 {828 char polarity = QChar(pol[0]).lower();829 ok = true;830 switch (polarity)831 {832 case 'v':833 case 'r': return SEC_VOLTAGE_13;834 case 'h':835 case 'l': return SEC_VOLTAGE_18;836 default: return SEC_VOLTAGE_OFF;837 }838 }839 840 804 fe_guard_interval DVBTuning::parseGuardInterval(const QString &gi, bool &ok) 841 805 { 842 806 QString guard_interval = gi.lower(); … … 1015 979 { 1016 980 switch (coderate) 1017 981 { 1018 case FEC_NONE: return " None";982 case FEC_NONE: return "none"; 1019 983 case FEC_1_2: return "1/2"; 1020 984 case FEC_2_3: return "2/3"; 1021 985 case FEC_3_4: return "3/4"; … … 1024 988 case FEC_6_7: return "6/7"; 1025 989 case FEC_7_8: return "7/8"; 1026 990 case FEC_8_9: return "8/9"; 1027 default: return " Auto";991 default: return "auto"; 1028 992 } 1029 993 } 1030 994 -
libs/libmythtv/dvbtypes.h
318 318 { 319 319 public: 320 320 DVBTuning() 321 : voltage(SEC_VOLTAGE_OFF), tone(SEC_TONE_OFF), 322 diseqc_type(0), diseqc_port(0), diseqc_pos(0.0f), 323 lnb_lof_switch(0), lnb_lof_hi(0), lnb_lof_lo(0) 321 : polariz('v') 324 322 { 325 323 bzero(¶ms, sizeof(dvb_fe_params)); 326 324 } 327 325 328 326 struct dvb_fe_params params; 329 fe_sec_voltage_t voltage; 330 fe_sec_tone_mode_t tone; 331 unsigned int diseqc_type; 332 unsigned int diseqc_port; 333 float diseqc_pos; 334 unsigned int lnb_lof_switch; 335 unsigned int lnb_lof_hi; 336 unsigned int lnb_lof_lo; 327 char polariz; 337 328 338 329 bool equalQPSK(const DVBTuning& other, uint range = 0) const 339 330 { return equal_qpsk(params, other.params, range); } … … 348 339 349 340 // Helper functions to get the paramaters as DB friendly strings 350 341 char InversionChar() const; 342 char PolarityChar() const; 351 343 char TransmissionModeChar() const; 352 344 char BandwidthChar() const; 353 345 char HierarchyChar() const; … … 356 348 357 349 // Helper functions to parse params from DB friendly strings 358 350 static fe_bandwidth parseBandwidth( const QString&, bool &ok); 359 static fe_sec_voltage parsePolarity( const QString&, bool &ok);360 351 static fe_guard_interval parseGuardInterval(const QString&, bool &ok); 361 352 static fe_transmit_mode parseTransmission( const QString&, bool &ok); 362 353 static fe_hierarchy parseHierarchy( const QString&, bool &ok); … … 375 366 QString HPCodeRateString() const; 376 367 QString LPCodeRateString() const; 377 368 QString QAMInnerFECString() const; 369 QString QPSKInnerFECString() const; 378 370 QString ModulationString() const; 379 371 QString ConstellationString() const; 380 372 QString HierarchyString() const; … … 390 382 391 383 bool parseQPSK(const QString& frequency, const QString& inversion, 392 384 const QString& symbol_rate, const QString& fec_inner, 393 const QString& pol, const QString& diseqc_type, 394 const QString& diseqc_port, const QString& diseqc_pos, 395 const QString& lnb_lof_switch, const QString& lnb_lof_hi, 396 const QString& lnb_lof_lo); 385 const QString& pol); 397 386 398 387 bool parseQAM(const QString& frequency, const QString& inversion, 399 388 const QString& symbol_rate, const QString& fec_inner, … … 405 394 uint DVBS2SymbolRate() const { return params.u.qpsk2.symbol_rate; } 406 395 bool parseDVBS2(const QString& frequency, const QString& inversion, 407 396 const QString& symbol_rate, const QString& fec_inner, 408 const QString& pol, const QString& diseqc_type, 409 const QString& diseqc_port, const QString& diseqc_pos, 410 const QString& lnb_lof_switch, const QString& lnb_lof_hi, 411 const QString& lnb_lof_lo, const QString& modulation); 397 const QString& pol); 412 398 #endif 413 399 }; 414 400 -
libs/libmythtv/channelutil.h
145 145 static QString GetServiceName(int chanid); 146 146 static int GetSourceID(int mplexid); 147 147 static QString GetInputName(int sourceid); 148 static int GetInputID(int sourceid, int cardid); 148 149 static QString GetDTVPrivateType(uint networkid, const QString &key, 149 150 const QString sitype = "dvb"); 150 151 -
libs/libmythtv/channelutil.cpp
231 231 // DVB specific 232 232 tsid, netid, 233 233 cd.SymbolRateHz(), -1, 234 QChar(cd.PolarizationString()[0]), -1,234 QChar(cd.PolarizationString()[0]), 'a', 235 235 -1, 236 236 cd.FECInnerString(), QString::null, 237 237 -1, QString::null, … … 670 670 return inputname; 671 671 } 672 672 673 int ChannelUtil::GetInputID(int source_id, int card_id) 674 { 675 int input_id = -1; 676 677 MSqlQuery query(MSqlQuery::InitCon()); 678 query.prepare("SELECT cardinputid" 679 " FROM cardinput" 680 " WHERE sourceid = :SOURCEID" 681 " AND cardid = :CARDID"); 682 query.bindValue(":SOURCEID", source_id); 683 query.bindValue(":CARDID", card_id); 684 685 if (query.exec() && query.isActive() && query.next()) 686 input_id = query.value(0).toInt(); 687 688 return input_id; 689 } 690 673 691 QString ChannelUtil::GetChannelValueStr(const QString &channel_field, 674 692 uint cardid, 675 693 const QString &input, -
libs/libmythtv/dvbchannel.h
19 19 20 20 #ifdef USING_DVB 21 21 #include "dvbtypes.h" 22 #include "dvbdevtree.h" 22 23 #else // if !USING_DVB 23 24 typedef int fe_type_t; 24 25 typedef int fe_modulation_t; 25 26 typedef int fe_code_rate_t; 26 27 typedef int DVBTuning; 28 typedef void DVBDevRotor; 27 29 typedef struct { QString name; fe_type_t type; } dvb_frontend_info; 28 30 #endif //!USING_DVB 29 31 30 32 class TVRec; 31 33 class DVBCam; 32 34 class DVBRecorder; 33 class DVBDiSEqC;34 35 35 36 class DVBChannel : public ChannelBase 36 37 { … … 64 65 bool SwitchToInput(const QString &inputname, const QString &chan); 65 66 bool SwitchToInput(int newcapchannel, bool setstarting); 66 67 bool SetChannelByString(const QString &chan); 67 bool Tune(const DVBTuning &tuning, bool force_reset = false);68 bool TuneMultiplex(uint mplexid);69 68 69 // Tuning 70 bool Tune(const DVBTuning &tuning, 71 bool force_reset = false, 72 int sourceid = -1, 73 bool same_input = false); 74 bool TuneMultiplex(uint mplexid, int sourceid = -1); 75 bool Retune(); 76 70 77 bool GetTuningParams(DVBTuning &tuning) const; 71 78 72 79 // PID caching 73 80 void SaveCachedPids(const pid_cache_t&) const; 74 81 void GetCachedPids(pid_cache_t&) const; 75 82 83 // Returns rotor object (or NULL) 84 const DVBDevRotor* GetRotor() const; 85 86 // If false, card needs retuning when lock is lost 87 bool CanRecover() const; 88 89 // Amount of time since last tuning request 90 int ElapsedSinceTune() const; 91 76 92 private: 77 93 int GetChanID(void) const; 78 94 bool GetTransportOptions(int mplexid); … … 85 101 bool ParseTuningParams( 86 102 fe_type_t type, 87 103 QString frequency, QString inversion, QString symbolrate, 88 QString fec, QString polarity, QString dvb_diseqc_type, 89 QString diseqc_port, QString diseqc_pos, QString lnb_lof_switch, 90 QString lnb_lof_hi, QString lnb_lof_lo, QString _sistandard, 104 QString fec, QString polarity, QString _sistandard, 91 105 QString hp_code_rate, QString lp_code_rate, QString constellation, 92 106 QString trans_mode, QString guard_interval, QString hierarchy, 93 107 QString modulation, QString bandwidth, QString _input_id); 94 108 95 109 private: 110 #ifdef USING_DVB 96 111 // Data 97 DVBDiSEqC *diseqc; ///< Used to send commands to external devices 112 DVBDev dvbdev; 113 DVBDevTree* devtree; 114 DVBDevSettings devset; 115 #endif 98 116 DVBCam *dvbcam; ///< Used to decrypt encrypted streams 99 117 100 118 // Tuning State … … 113 131 int cardnum; ///< DVB Card number 114 132 bool has_crc_bug; ///< true iff our driver munges PMT 115 133 int nextInputID; ///< Signal an input change 134 135 QTime tune_time; 136 QMutex tune_lock; 116 137 }; 117 138 118 139 #endif -
libs/libmythtv/dvbchannel.cpp
52 52 #include "mythdbcon.h" 53 53 #include "tv_rec.h" 54 54 #include "cardutil.h" 55 #include "channelutil.h" 55 56 56 57 #include "dvbtypes.h" 57 58 #include "dvbchannel.h" 58 59 #include "dvbrecorder.h" 59 #include "dvbd iseqc.h"60 #include "dvbdevtree.h" 60 61 #include "dvbcam.h" 61 62 62 static uint tuned_frequency(const DVBTuning&, fe_type_t, fe_sec_tone_mode_t *);63 63 static void drain_dvb_events(int fd); 64 64 static bool wait_for_backend(int fd, int timeout_ms); 65 static bool handle_diseq(const DVBTuning&, DVBDiSEqC*, bool reset);66 65 67 66 #define LOC QString("DVBChan(%1): ").arg(cardnum) 68 67 #define LOC_WARN QString("DVBChan(%1) Warning: ").arg(cardnum) … … 76 75 DVBChannel::DVBChannel(int aCardNum, TVRec *parent) 77 76 : ChannelBase(parent), 78 77 // Helper classes 79 diseqc(NULL), dvbcam(NULL), 78 devtree(NULL), 79 dvbcam(NULL), 80 80 // Tuning 81 81 tuning_delay(0), sigmon_delay(25), 82 82 first_tune(true), … … 93 93 DVBChannel::~DVBChannel() 94 94 { 95 95 Close(); 96 if (dvbcam) 97 { 98 delete dvbcam; 99 dvbcam = NULL; 100 } 96 delete dvbcam; 97 dvbcam = NULL; 101 98 } 102 99 103 100 void DVBChannel::Close() … … 106 103 107 104 if (fd_frontend >= 0) 108 105 { 106 if(devtree) 107 devtree->Close(); 108 109 109 close(fd_frontend); 110 110 fd_frontend = -1; 111 111 112 112 dvbcam->Stop(); 113 114 if (diseqc)115 {116 delete diseqc;117 diseqc = NULL;118 }119 113 } 120 114 } 121 115 … … 189 183 if (info.type == FE_QPSK) 190 184 #endif 191 185 { 192 if (ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF) < 0) 193 { 194 VERBOSE(VB_GENERAL, LOC_WARN + 195 "Initial Tone setting failed." + ENO); 196 } 197 198 if (ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13) < 0) 199 { 200 VERBOSE(VB_GENERAL, LOC_WARN + 201 "Initial Voltage setting failed." + ENO); 202 } 203 204 if (diseqc == NULL) 205 { 206 diseqc = new DVBDiSEqC(cardnum, fd_frontend); 207 diseqc->DiseqcReset(); 208 } 186 devtree = dvbdev.FindTree(GetCardID()); 187 if(devtree) 188 devtree->Open(fd_frontend); 209 189 } 210 190 211 191 dvbcam->Start(); … … 228 208 * 229 209 * mplexid is how the db indexes each transport 230 210 */ 231 bool DVBChannel::TuneMultiplex(uint mplexid )211 bool DVBChannel::TuneMultiplex(uint mplexid, int sourceid) 232 212 { 233 213 if (!GetTransportOptions(mplexid)) 234 214 return false; … … 236 216 CheckOptions(); 237 217 VERBOSE(VB_CHANNEL, LOC + cur_tuning.toString(info.type)); 238 218 239 if (!Tune(cur_tuning ))219 if (!Tune(cur_tuning, false, sourceid)) 240 220 return false; 241 221 242 222 return true; … … 406 386 // Query for our DVBTuning params 407 387 query.prepare( 408 388 "SELECT frequency, inversion, symbolrate, " 409 " fec, polarity, dvb_diseqc_type, " 410 " diseqc_port, diseqc_pos, lnb_lof_switch, " 411 " lnb_lof_hi, lnb_lof_lo, sistandard, " 389 " fec, polarity, sistandard, " 412 390 " hp_code_rate, lp_code_rate, constellation, " 413 391 " transmission_mode, guard_interval, hierarchy, " 414 392 " modulation, bandwidth, cardinputid " … … 444 422 query.value(8).toString(), query.value(9).toString(), 445 423 query.value(10).toString(), query.value(11).toString(), 446 424 query.value(12).toString(), query.value(13).toString(), 447 query.value(14).toString(), query.value(15).toString(), 448 query.value(16).toString(), query.value(17).toString(), 449 query.value(18).toString(), query.value(19).toString(), 450 query.value(20).toString()); 425 query.value(14).toString()); 451 426 } 452 427 453 428 bool DVBChannel::ParseTuningParams( 454 429 fe_type_t type, 455 430 QString frequency, QString inversion, QString symbolrate, 456 QString fec, QString polarity, QString dvb_diseqc_type, 457 QString diseqc_port, QString diseqc_pos, QString lnb_lof_switch, 458 QString lnb_lof_hi, QString lnb_lof_lo, QString _sistandard, 431 QString fec, QString polarity, QString _sistandard, 459 432 QString hp_code_rate, QString lp_code_rate, QString constellation, 460 433 QString trans_mode, QString guard_interval, QString hierarchy, 461 434 QString modulation, QString bandwidth, QString _input_id) … … 465 438 466 439 if (FE_QPSK == type) 467 440 return cur_tuning.parseQPSK( 468 frequency, inversion, symbolrate, fec, polarity, 469 dvb_diseqc_type, diseqc_port, diseqc_pos, 470 lnb_lof_switch, lnb_lof_hi, lnb_lof_lo); 441 frequency, inversion, symbolrate, fec, polarity); 471 442 else if (FE_QAM == type) 472 443 return cur_tuning.parseQAM( 473 444 frequency, inversion, symbolrate, fec, modulation); … … 506 477 t.params.inversion = INVERSION_OFF; 507 478 } 508 479 509 uint frequency = tuned_frequency(t, info.type, NULL); 480 uint frequency = t.params.frequency; 481 if(devtree) 482 { 483 DVBDevLnb* lnb = devtree->FindLNB(devset); 484 if(lnb) 485 frequency = lnb->GetIF(devset, t); 486 } 510 487 511 488 if ((info.frequency_min > 0 && info.frequency_max > 0) && 512 489 (frequency < info.frequency_min || frequency > info.frequency_max)) … … 697 674 * \param channel Info on transport to tune to 698 675 * \param force_reset If true, frequency tuning is done 699 676 * even if it should not be needed. 677 * \param source_id Optional, forces specific sourceid (for diseqc setup). 678 * \param same_input Optional, doesn't change input (for retuning). 700 679 * \return true on success, false on failure 701 680 */ 702 bool DVBChannel::Tune(const DVBTuning &tuning, bool force_reset) 681 bool DVBChannel::Tune(const DVBTuning &tuning, 682 bool force_reset, 683 int source_id, 684 bool same_input) 703 685 { 704 bool reset = (force_reset || first_tune); 705 bool has_diseq = (FE_QPSK == info.type) && diseqc; 706 struct dvb_fe_params params = tuning.params; 686 QMutexLocker lock(&tune_lock); 707 687 688 bool reset = (force_reset || first_tune); 689 bool is_dvbs = (FE_QPSK == info.type); 708 690 #ifdef FE_GET_EXTENDED_INFO 709 has_diseq |= (FE_DVB_S2 == info.type) && diseqc;691 is_dvbs |= (FE_DVB_S2 == info.type); 710 692 #endif // FE_GET_EXTENDED_INFO 693 bool has_diseqc = (devtree != NULL); 694 struct dvb_fe_params params = tuning.params; 711 695 696 tune_time.start(); 697 698 if(is_dvbs && !has_diseqc) 699 { 700 VERBOSE(VB_IMPORTANT, LOC_ERR + "DVB-S needs device tree"); 701 return false; 702 } 703 712 704 if (fd_frontend < 0) 713 705 { 714 706 VERBOSE(VB_IMPORTANT, LOC_ERR + "Tune(): Card not open!"); … … 719 711 // Remove any events in queue before tuning. 720 712 drain_dvb_events(fd_frontend); 721 713 722 // Send DisEq commands to external hardware if we need to.723 if ( has_diseq && !handle_diseq(tuning, diseqc, reset))714 // send DVB-S setup 715 if (is_dvbs) 724 716 { 725 VERBOSE(VB_IMPORTANT, LOC_ERR + "Tune(): " 726 "Failed to transmit DisEq commands"); 717 // configure for new input 718 if(!same_input) 719 { 720 devset.Load(source_id == -1 ? nextInputID : 721 ChannelUtil::GetInputID(source_id, GetCardID())); 722 } 723 724 // execute diseqc commands 725 if(!devtree->Execute(devset, tuning)) 726 { 727 VERBOSE(VB_IMPORTANT, LOC_ERR + "Tune(): " 728 "Failed to setup DiSEqC devices"); 729 return false; 730 } 727 731 728 return false; 732 // retrieve actual intermediate frequency 733 DVBDevLnb* lnb = devtree->FindLNB(devset); 734 if(!lnb) 735 { 736 VERBOSE(VB_IMPORTANT, LOC_ERR + "Tune(): " 737 "No LNB for this configuration"); 738 return false; 739 } 740 params.frequency = lnb->GetIF(devset, tuning); 741 742 // if card can auto-FEC, use it -- sometimes NITs are inaccurate 743 if(info.caps & FE_CAN_FEC_AUTO) 744 params.u.qpsk.fec_inner = FEC_AUTO; 729 745 } 730 746 731 747 VERBOSE(VB_CHANNEL, LOC + "Old Params: " + … … 733 749 "\n\t\t\t" + LOC + "New Params: " + 734 750 tuning.toString(info.type)); 735 751 736 if (reset || !prev_tuning.equal(info.type, tuning, 500000)) 737 { 738 // Adjust for Satelite recievers which offset the frequency. 739 params.frequency = tuned_frequency(tuning, info.type, NULL); 752 // DVB-S is in kHz, other DVB is in Hz 753 int freq_mult = is_dvbs ? 1 : 1000; 754 const char* suffix = is_dvbs ? "kHz" : "Hz"; 740 755 756 if (reset || !prev_tuning.equal(info.type, tuning, 500 * freq_mult)) 757 { 758 VERBOSE(VB_CHANNEL, LOC + QString("Tune(): Tuning to %1%2") 759 .arg(params.frequency) 760 .arg(suffix)); 741 761 #ifdef FE_GET_EXTENDED_INFO 742 762 if (info.type == FE_DVB_S2) 743 763 { … … 774 794 return true; 775 795 } 776 796 797 bool DVBChannel::Retune() 798 { 799 return Tune(prev_tuning, true, -1, true); 800 } 801 777 802 /** \fn DVBChannel::GetTuningParams(DVBTuning& tuning) const 778 803 * \brief Fetches DVBTuning params from driver 779 804 * \return true on success, false on failure … … 843 868 ChannelBase::GetCachedPids(chanid, pid_cache); 844 869 } 845 870 871 const DVBDevRotor* DVBChannel::GetRotor() const 872 { 873 const DVBDevRotor* rotor = devtree ? devtree->FindRotor(devset) : NULL; 874 return rotor; 875 } 876 877 bool DVBChannel::CanRecover() const 878 { 879 return info.caps & FE_CAN_RECOVER; 880 } 881 882 int DVBChannel::ElapsedSinceTune() const 883 { 884 return first_tune ? 0 : tune_time.elapsed(); 885 } 886 846 887 /** \fn drain_dvb_events(int) 847 888 * \brief Reads all the events off the queue, so we can use select 848 889 * in wait_for_backend(int,int). … … 853 894 while (ioctl(fd, FE_GET_EVENT, &event) == 0); 854 895 } 855 896 856 static uint tuned_frequency(const DVBTuning &tuning, fe_type_t type,857 fe_sec_tone_mode_t *p_tone)858 {859 #ifdef FE_GET_EXTENDED_INFO860 if (FE_QPSK != type && FE_DVB_S2 != type)861 return tuning.Frequency();862 #else863 if (FE_QPSK != type)864 return tuning.Frequency();865 #endif866 867 uint freq = tuning.Frequency();868 bool tone = freq >= tuning.lnb_lof_switch;869 uint lnb_hi = (uint) abs((int)freq - (int)tuning.lnb_lof_hi);870 uint lnb_lo = (uint) abs((int)freq - (int)tuning.lnb_lof_lo);871 872 if (p_tone)873 *p_tone = (tone) ? SEC_TONE_ON : SEC_TONE_OFF;874 875 return (tone) ? lnb_hi : lnb_lo;876 }877 878 897 /** \fn wait_for_backend(int,int) 879 898 * \brief Waits for backend to get tune message. 880 899 * … … 923 942 .arg(toString(status))); 924 943 return true; 925 944 } 926 927 /** \fn handle_diseq(const DVBTuning&, DVBDiSEqC*, bool)928 * \brief Sends DisEq commands to external hardware.929 *930 */931 static bool handle_diseq(const DVBTuning &ct, DVBDiSEqC *diseqc, bool reset)932 {933 if (!diseqc)934 return false;935 936 bool tuned = false;937 DVBTuning t = ct;938 t.params.frequency = tuned_frequency(ct, FE_QPSK, &t.tone);939 940 for (uint i = 0; i < 64 && !tuned; i++)941 if (!diseqc->Set(t, reset, tuned))942 return false;943 944 // Wait 10 ms, recommended by Marcus Metzler, see #1552945 usleep(10 * 1000);946 947 return true;948 } -
libs/libmythtv/siscan.cpp
376 376 bool wait_until_complete) 377 377 { 378 378 const DVBStreamData &dsd = (const DVBStreamData &)(*sd); 379 if (wait_until_complete && !dsd.HasCachedSDT() && !dsd.HasCachedAllNIT())379 if (wait_until_complete && (!dsd.HasCachedSDT() || !dsd.HasCachedAllNIT())) 380 380 return; 381 381 382 382 emit ServiceScanUpdateText(tr("Updating Services")); … … 619 619 // Tune to multiplex 620 620 if (GetDVBChannel()) 621 621 { 622 // always wait for rotor to finish 623 GetDVBSignalMonitor()->AddFlags(kDVBSigMon_WaitForPos); 624 622 625 if (item.mplexid > 0) 623 626 { 624 ok = GetDVBChannel()->TuneMultiplex(item.mplexid );627 ok = GetDVBChannel()->TuneMultiplex(item.mplexid, item.SourceID); 625 628 } 626 629 else 627 630 { 628 631 DVBTuning tuning = item.tuning; 629 632 tuning.params.frequency = freq; 630 ok = GetDVBChannel()->Tune(tuning, true );633 ok = GetDVBChannel()->Tune(tuning, true, item.SourceID); 631 634 } 632 635 } 633 636 #endif // USING_DVB … … 827 830 ok = tuning.parseQPSK( 828 831 startChan["frequency"], startChan["inversion"], 829 832 startChan["symbolrate"], startChan["fec"], 830 startChan["polarity"], 831 startChan["diseqc_type"], startChan["diseqc_port"], 832 startChan["diseqc_pos"], startChan["lnb_lof_switch"], 833 startChan["lnb_lof_hi"], startChan["lnb_lof_lo"]); 833 startChan["polarity"]); 834 834 } 835 835 else if (std == "dvb" && mod.left(3) == "qam") 836 836 { … … 1340 1340 QString::null /*inner FEC*/,tuning.ConstellationDB(), 1341 1341 tuning.HierarchyChar(), tuning.HPCodeRateString(), 1342 1342 tuning.LPCodeRateString(), tuning.GuardIntervalString()); 1343 else if (FE_QPSK == GetDVBChannel()->GetCardType()) 1344 mplexid = ChannelUtil::CreateMultiplex( 1345 (*transport).SourceID, (*transport).standard, 1346 tuning.Frequency(), (*transport).ModulationDB(), 1347 sm->GetDetectedTransportID(), 1348 sm->GetDetectedNetworkID(), 1349 tuning.QPSKSymbolRate(), -1, 1350 tuning.PolarityChar(), tuning.InversionChar(), 1351 -1, 1352 tuning.QPSKInnerFECString(),QString::null, 1353 -1, QString::null, 1354 QString::null, QString::null); 1355 else if (FE_QAM == GetDVBChannel()->GetCardType()) 1356 mplexid = ChannelUtil::CreateMultiplex( 1357 (*transport).SourceID, (*transport).standard, 1358 tuning.Frequency(), tuning.ModulationString(), 1359 sm->GetDetectedTransportID(), 1360 sm->GetDetectedNetworkID(), 1361 tuning.QAMSymbolRate(), -1, 1362 -1, -1, 1363 -1, 1364 tuning.QAMInnerFECString(), QString::null, 1365 -1, QString::null, 1366 QString::null, QString::null); 1343 1367 else 1344 1368 mplexid = ChannelUtil::CreateMultiplex( 1345 1369 (*transport).SourceID, (*transport).standard, -
libs/libmythtv/scanwizardscanner.cpp
269 269 popupProgress = NULL; 270 270 } 271 271 272 static bool get_diseqc(uint cardid, uint sourceid,273 QMap<QString,QString> &startChan)274 {275 // SQL code to get the disqec paramters HERE276 MSqlQuery query(MSqlQuery::InitCon());277 query.prepare(278 "SELECT dvb_diseqc_type, diseqc_port, diseqc_pos, "279 " lnb_lof_switch, lnb_lof_hi, lnb_lof_lo "280 "FROM cardinput, capturecard "281 "WHERE cardinput.cardid = capturecard.cardid AND "282 " cardinput.cardid = :CARDID AND "283 " cardinput.sourceid = :SOURCEID ");284 query.bindValue(":CARDID", cardid);285 query.bindValue(":SOURCEID", sourceid);286 287 if (!query.exec() || !query.isActive())288 {289 MythContext::DBError("ScanWizardScanner::scan()", query);290 return false;291 }292 293 if (query.next())294 {295 startChan["diseqc_type"] = query.value(0).toString();296 startChan["diseqc_port"] = query.value(1).toString();297 startChan["diseqc_pos"] = query.value(2).toString();298 startChan["lnb_lof_switch"] = query.value(3).toString();299 startChan["lnb_lof_hi"] = query.value(4).toString();300 startChan["lnb_lof_lo"] = query.value(5).toString();301 return true;302 }303 304 return false;305 }306 307 272 // full scan of existing transports broken 308 273 // existing transport scan broken 309 274 void ScanWizardScanner::scan() … … 375 340 startChan["modulation"] = "qpsk"; 376 341 startChan["polarity"] = pane->polarity(); 377 342 378 nit_scan_parse_failed = !get_diseqc(cardid, nVideoSource, startChan);379 380 343 #ifdef USING_DVB 381 344 if (!nit_scan_parse_failed) 382 345 { … … 384 347 nit_scan_parse_failed = !tuning.parseQPSK( 385 348 startChan["frequency"], startChan["inversion"], 386 349 startChan["symbolrate"], startChan["fec"], 387 startChan["polarity"], 388 startChan["diseqc_type"], startChan["diseqc_port"], 389 startChan["diseqc_pos"], startChan["lnb_lof_switch"], 390 startChan["lnb_lof_hi"], startChan["lnb_lof_lo"]); 350 startChan["polarity"]); 391 351 } 392 352 #endif // USING_DVB 393 353 } -
libs/libmythtv/dbcheck.cpp
8 8 9 9 #include "mythcontext.h" 10 10 #include "mythdbcon.h" 11 #ifdef USING_DVB 12 #include "dvbdevtree.h" 13 #endif 11 14 12 15 /// This is the DB schema version expected by the running MythTV instance. 13 16 const QString currentDatabaseVersion = "1143"; … … 419 422 */ 420 423 bool UpgradeTVDatabaseSchema(void) 421 424 { 425 #ifdef USING_DVB 426 // TODO: The code in DatabaseDiseqcUpgrade (just sequence of SQL queries) 427 // should be versioned and added to the database creation/upgrade functions as 428 // normal. DatabaseDiseqcImport() should be called as part of that upgrade 429 // process as well. 430 if(DatabaseDiseqcUpgrade()) 431 DatabaseDiseqcImport(); 432 #endif 433 422 434 QString dbver = gContext->GetSetting("DBSchemaVer"); 423 435 424 436 VERBOSE(VB_IMPORTANT, QString("Current Schema Version: %1").arg(dbver));