dvbsec_api.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944
  1. /*
  2. libdvbsec - an SEC library
  3. Copyright (C) 2005 Manu Abraham <abraham.manu@gmail.com>
  4. Copyright (C) 2006 Andrew de Quincey <adq_dvb@lidskialf.net>
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version.
  9. This library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with this library; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  16. */
  17. #include <stdlib.h>
  18. #include <unistd.h>
  19. #include <errno.h>
  20. #include <string.h>
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <linux/types.h>
  24. #include <libdvbapi/dvbfe.h>
  25. #include "dvbsec_api.h"
  26. // uncomment this to make dvbsec_command print out debug instead of talking to a frontend
  27. // #define TEST_SEC_COMMAND 1
  28. int dvbsec_set(struct dvbfe_handle *fe,
  29. struct dvbsec_config *sec_config,
  30. enum dvbsec_diseqc_polarization polarization,
  31. enum dvbsec_diseqc_switch sat_pos,
  32. enum dvbsec_diseqc_switch switch_option,
  33. struct dvbfe_parameters *params,
  34. int timeout)
  35. {
  36. int tmp;
  37. struct dvbfe_parameters localparams;
  38. struct dvbfe_parameters *topass = params;
  39. // perform SEC
  40. if (sec_config != NULL) {
  41. switch(sec_config->config_type) {
  42. case DVBSEC_CONFIG_NONE:
  43. break;
  44. case DVBSEC_CONFIG_POWER:
  45. dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_13);
  46. break;
  47. case DVBSEC_CONFIG_STANDARD:
  48. {
  49. // calculate the correct oscillator value
  50. enum dvbsec_diseqc_oscillator osc = DISEQC_OSCILLATOR_LOW;
  51. if (sec_config->switch_frequency && (sec_config->switch_frequency < params->frequency))
  52. osc = DISEQC_OSCILLATOR_HIGH;
  53. if ((tmp = dvbsec_std_sequence(fe,
  54. osc,
  55. polarization,
  56. sat_pos,
  57. switch_option)) < 0)
  58. return tmp;
  59. break;
  60. }
  61. case DVBSEC_CONFIG_ADVANCED:
  62. {
  63. // are we high or not?
  64. int high = 0;
  65. if (sec_config->switch_frequency && (sec_config->switch_frequency < params->frequency))
  66. high = 1;
  67. // determine correct string
  68. char *cmd = NULL;
  69. switch(polarization) {
  70. case DISEQC_POLARIZATION_H:
  71. if (!high)
  72. cmd = sec_config->adv_cmd_lo_h;
  73. else
  74. cmd = sec_config->adv_cmd_hi_h;
  75. break;
  76. case DISEQC_POLARIZATION_V:
  77. if (!high)
  78. cmd = sec_config->adv_cmd_lo_v;
  79. else
  80. cmd = sec_config->adv_cmd_hi_v;
  81. break;
  82. case DISEQC_POLARIZATION_L:
  83. if (!high)
  84. cmd = sec_config->adv_cmd_lo_l;
  85. else
  86. cmd = sec_config->adv_cmd_hi_l;
  87. break;
  88. case DISEQC_POLARIZATION_R:
  89. if (!high)
  90. cmd = sec_config->adv_cmd_lo_r;
  91. else
  92. cmd = sec_config->adv_cmd_hi_r;
  93. break;
  94. default:
  95. return -EINVAL;
  96. }
  97. // do it
  98. if (cmd)
  99. if ((tmp = dvbsec_command(fe, cmd)) < 0)
  100. return tmp;
  101. break;
  102. }
  103. }
  104. // work out the correct LOF value
  105. uint32_t lof = 0;
  106. if ((sec_config->switch_frequency == 0) || (params->frequency < sec_config->switch_frequency)) {
  107. // LOW band
  108. switch(polarization) {
  109. case DISEQC_POLARIZATION_H:
  110. lof = sec_config->lof_lo_h;
  111. break;
  112. case DISEQC_POLARIZATION_V:
  113. lof = sec_config->lof_lo_v;
  114. break;
  115. case DISEQC_POLARIZATION_L:
  116. lof = sec_config->lof_lo_l;
  117. break;
  118. case DISEQC_POLARIZATION_R:
  119. lof = sec_config->lof_lo_r;
  120. break;
  121. case DISEQC_POLARIZATION_UNCHANGED:
  122. break;
  123. }
  124. } else {
  125. // HIGH band
  126. switch(polarization) {
  127. case DISEQC_POLARIZATION_H:
  128. lof = sec_config->lof_hi_h;
  129. break;
  130. case DISEQC_POLARIZATION_V:
  131. lof = sec_config->lof_hi_v;
  132. break;
  133. case DISEQC_POLARIZATION_L:
  134. lof = sec_config->lof_hi_l;
  135. break;
  136. case DISEQC_POLARIZATION_R:
  137. lof = sec_config->lof_hi_r;
  138. break;
  139. case DISEQC_POLARIZATION_UNCHANGED:
  140. break;
  141. }
  142. }
  143. // do frequency adjustment
  144. if (lof) {
  145. memcpy(&localparams, params, sizeof(struct dvbfe_parameters));
  146. int tmpfreq = localparams.frequency - lof;
  147. if (tmpfreq < 0)
  148. tmpfreq *= -1;
  149. localparams.frequency = (uint32_t) tmpfreq;
  150. topass = &localparams;
  151. }
  152. }
  153. // set the frontend!
  154. return dvbfe_set(fe, topass, timeout);
  155. }
  156. int dvbsec_std_sequence(struct dvbfe_handle *fe,
  157. enum dvbsec_diseqc_oscillator oscillator,
  158. enum dvbsec_diseqc_polarization polarization,
  159. enum dvbsec_diseqc_switch sat_pos,
  160. enum dvbsec_diseqc_switch switch_option)
  161. {
  162. dvbfe_set_22k_tone(fe, DVBFE_SEC_TONE_OFF);
  163. switch(polarization) {
  164. case DISEQC_POLARIZATION_V:
  165. case DISEQC_POLARIZATION_R:
  166. dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_13);
  167. break;
  168. case DISEQC_POLARIZATION_H:
  169. case DISEQC_POLARIZATION_L:
  170. dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_18);
  171. break;
  172. default:
  173. return -EINVAL;
  174. }
  175. dvbsec_diseqc_set_committed_switches(fe,
  176. DISEQC_ADDRESS_ANY_DEVICE,
  177. oscillator,
  178. polarization,
  179. sat_pos,
  180. switch_option);
  181. usleep(15000);
  182. switch(sat_pos) {
  183. case DISEQC_SWITCH_A:
  184. dvbfe_set_tone_data_burst(fe, DVBFE_SEC_MINI_A);
  185. break;
  186. case DISEQC_SWITCH_B:
  187. dvbfe_set_tone_data_burst(fe, DVBFE_SEC_MINI_B);
  188. break;
  189. default:
  190. break;
  191. }
  192. if (sat_pos != DISEQC_SWITCH_UNCHANGED)
  193. usleep(15000);
  194. switch(oscillator) {
  195. case DISEQC_OSCILLATOR_LOW:
  196. dvbfe_set_22k_tone(fe, DVBFE_SEC_TONE_OFF);
  197. break;
  198. case DISEQC_OSCILLATOR_HIGH:
  199. dvbfe_set_22k_tone(fe, DVBFE_SEC_TONE_ON);
  200. break;
  201. default:
  202. break;
  203. }
  204. return 0;
  205. }
  206. int dvbsec_diseqc_set_reset(struct dvbfe_handle *fe,
  207. enum dvbsec_diseqc_address address,
  208. enum dvbsec_diseqc_reset state)
  209. {
  210. uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x00 };
  211. if (state == DISEQC_RESET_CLEAR)
  212. data[2] = 0x01;
  213. return dvbfe_do_diseqc_command(fe, data, sizeof(data));
  214. }
  215. int dvbsec_diseqc_set_power(struct dvbfe_handle *fe,
  216. enum dvbsec_diseqc_address address,
  217. enum dvbsec_diseqc_power state)
  218. {
  219. uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x02 };
  220. if (state == DISEQC_POWER_ON)
  221. data[2] = 0x03;
  222. return dvbfe_do_diseqc_command(fe, data, sizeof(data));
  223. }
  224. int dvbsec_diseqc_set_listen(struct dvbfe_handle *fe,
  225. enum dvbsec_diseqc_address address,
  226. enum dvbsec_diseqc_listen state)
  227. {
  228. uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x30 };
  229. if (state == DISEQC_LISTEN_AWAKE)
  230. data[2] = 0x31;
  231. return dvbfe_do_diseqc_command(fe, data, sizeof(data));
  232. }
  233. int dvbsec_diseqc_set_committed_switches(struct dvbfe_handle *fe,
  234. enum dvbsec_diseqc_address address,
  235. enum dvbsec_diseqc_oscillator oscillator,
  236. enum dvbsec_diseqc_polarization polarization,
  237. enum dvbsec_diseqc_switch sat_pos,
  238. enum dvbsec_diseqc_switch switch_option)
  239. {
  240. uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x38, 0x00 };
  241. switch(oscillator) {
  242. case DISEQC_OSCILLATOR_LOW:
  243. data[3] |= 0x10;
  244. break;
  245. case DISEQC_OSCILLATOR_HIGH:
  246. data[3] |= 0x11;
  247. break;
  248. case DISEQC_OSCILLATOR_UNCHANGED:
  249. break;
  250. }
  251. switch(polarization) {
  252. case DISEQC_POLARIZATION_V:
  253. case DISEQC_POLARIZATION_R:
  254. data[3] |= 0x20;
  255. break;
  256. case DISEQC_POLARIZATION_H:
  257. case DISEQC_POLARIZATION_L:
  258. data[3] |= 0x22;
  259. break;
  260. default:
  261. break;
  262. }
  263. switch(sat_pos) {
  264. case DISEQC_SWITCH_A:
  265. data[3] |= 0x40;
  266. break;
  267. case DISEQC_SWITCH_B:
  268. data[3] |= 0x44;
  269. break;
  270. case DISEQC_SWITCH_UNCHANGED:
  271. break;
  272. }
  273. switch(switch_option) {
  274. case DISEQC_SWITCH_A:
  275. data[3] |= 0x80;
  276. break;
  277. case DISEQC_SWITCH_B:
  278. data[3] |= 0x88;
  279. break;
  280. case DISEQC_SWITCH_UNCHANGED:
  281. break;
  282. }
  283. if (data[3] == 0)
  284. return 0;
  285. return dvbfe_do_diseqc_command(fe, data, sizeof(data));
  286. }
  287. int dvbsec_diseqc_set_uncommitted_switches(struct dvbfe_handle *fe,
  288. enum dvbsec_diseqc_address address,
  289. enum dvbsec_diseqc_switch s1,
  290. enum dvbsec_diseqc_switch s2,
  291. enum dvbsec_diseqc_switch s3,
  292. enum dvbsec_diseqc_switch s4)
  293. {
  294. uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x39, 0x00 };
  295. switch(s1) {
  296. case DISEQC_SWITCH_A:
  297. data[3] |= 0x10;
  298. break;
  299. case DISEQC_SWITCH_B:
  300. data[3] |= 0x11;
  301. break;
  302. case DISEQC_SWITCH_UNCHANGED:
  303. break;
  304. }
  305. switch(s2) {
  306. case DISEQC_SWITCH_A:
  307. data[3] |= 0x20;
  308. break;
  309. case DISEQC_SWITCH_B:
  310. data[3] |= 0x22;
  311. break;
  312. case DISEQC_SWITCH_UNCHANGED:
  313. break;
  314. }
  315. switch(s3) {
  316. case DISEQC_SWITCH_A:
  317. data[3] |= 0x40;
  318. break;
  319. case DISEQC_SWITCH_B:
  320. data[3] |= 0x44;
  321. break;
  322. case DISEQC_SWITCH_UNCHANGED:
  323. break;
  324. }
  325. switch(s4) {
  326. case DISEQC_SWITCH_A:
  327. data[3] |= 0x80;
  328. break;
  329. case DISEQC_SWITCH_B:
  330. data[3] |= 0x88;
  331. break;
  332. case DISEQC_SWITCH_UNCHANGED:
  333. break;
  334. }
  335. if (data[3] == 0)
  336. return 0;
  337. return dvbfe_do_diseqc_command(fe, data, sizeof(data));
  338. }
  339. int dvbsec_diseqc_set_analog_value(struct dvbfe_handle *fe,
  340. enum dvbsec_diseqc_address address,
  341. enum dvbsec_diseqc_analog_id id,
  342. uint8_t value)
  343. {
  344. uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x48, value };
  345. if (id == DISEQC_ANALOG_ID_A1)
  346. data[2] = 0x49;
  347. return dvbfe_do_diseqc_command(fe, data, sizeof(data));
  348. }
  349. int dvbsec_diseqc_set_frequency(struct dvbfe_handle *fe,
  350. enum dvbsec_diseqc_address address,
  351. uint32_t frequency)
  352. {
  353. uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x58, 0x00, 0x00, 0x00 };
  354. int len = 5;
  355. uint32_t bcdval = 0;
  356. int i;
  357. for(i=0; i<=24;i+=4) {
  358. bcdval |= ((frequency % 10) << i);
  359. frequency /= 10;
  360. }
  361. data[3] = bcdval >> 16;
  362. data[4] = bcdval >> 8;
  363. if (bcdval & 0xff) {
  364. data[5] = bcdval;
  365. len++;
  366. }
  367. return dvbfe_do_diseqc_command(fe, data, len);
  368. }
  369. int dvbsec_diseqc_set_channel(struct dvbfe_handle *fe,
  370. enum dvbsec_diseqc_address address,
  371. uint16_t channel)
  372. {
  373. uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x59, 0x00, 0x00};
  374. data[3] = channel >> 8;
  375. data[4] = channel;
  376. return dvbfe_do_diseqc_command(fe, data, sizeof(data));
  377. }
  378. int dvbsec_diseqc_halt_satpos(struct dvbfe_handle *fe,
  379. enum dvbsec_diseqc_address address)
  380. {
  381. uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x60};
  382. return dvbfe_do_diseqc_command(fe, data, sizeof(data));
  383. }
  384. int dvbsec_diseqc_disable_satpos_limits(struct dvbfe_handle *fe,
  385. enum dvbsec_diseqc_address address)
  386. {
  387. uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x63};
  388. return dvbfe_do_diseqc_command(fe, data, sizeof(data));
  389. }
  390. int dvbsec_diseqc_set_satpos_limit(struct dvbfe_handle *fe,
  391. enum dvbsec_diseqc_address address,
  392. enum dvbsec_diseqc_direction direction)
  393. {
  394. uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x66};
  395. if (direction == DISEQC_DIRECTION_WEST)
  396. data[2] = 0x67;
  397. return dvbfe_do_diseqc_command(fe, data, sizeof(data));
  398. }
  399. int dvbsec_diseqc_drive_satpos_motor(struct dvbfe_handle *fe,
  400. enum dvbsec_diseqc_address address,
  401. enum dvbsec_diseqc_direction direction,
  402. enum dvbsec_diseqc_drive_mode mode,
  403. uint8_t value)
  404. {
  405. uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x68, 0x00};
  406. if (direction == DISEQC_DIRECTION_WEST)
  407. data[2] = 0x69;
  408. switch(mode) {
  409. case DISEQC_DRIVE_MODE_STEPS:
  410. data[3] = (value & 0x7f) | 0x80;
  411. break;
  412. case DISEQC_DRIVE_MODE_TIMEOUT:
  413. data[3] = value & 0x7f;
  414. break;
  415. }
  416. return dvbfe_do_diseqc_command(fe, data, sizeof(data));
  417. }
  418. int dvbsec_diseqc_store_satpos_preset(struct dvbfe_handle *fe,
  419. enum dvbsec_diseqc_address address,
  420. uint8_t id)
  421. {
  422. uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x6A, id};
  423. return dvbfe_do_diseqc_command(fe, data, sizeof(data));
  424. }
  425. int dvbsec_diseqc_goto_satpos_preset(struct dvbfe_handle *fe,
  426. enum dvbsec_diseqc_address address,
  427. uint8_t id)
  428. {
  429. uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x6B, id};
  430. return dvbfe_do_diseqc_command(fe, data, sizeof(data));
  431. }
  432. int dvbsec_diseqc_recalculate_satpos_positions(struct dvbfe_handle *fe,
  433. enum dvbsec_diseqc_address address,
  434. int val1,
  435. int val2)
  436. {
  437. uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x6F, 0x00, 0x00};
  438. int len = 3;
  439. if (val1 != -1) {
  440. data[3] = val1;
  441. len++;
  442. }
  443. if (val2 != -1) {
  444. data[4] = val2;
  445. len = 5;
  446. }
  447. return dvbfe_do_diseqc_command(fe, data, len);
  448. }
  449. int dvbsec_diseqc_goto_rotator_bearing(struct dvbfe_handle *fe,
  450. enum dvbsec_diseqc_address address,
  451. float angle)
  452. {
  453. int integer = (int) angle;
  454. uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x6e, 0x00, 0x00};
  455. // transform the fraction into the correct representation
  456. int fraction = (int) (((angle - integer) * 16.0) + 0.9) & 0x0f;
  457. switch(fraction) {
  458. case 1:
  459. case 4:
  460. case 7:
  461. case 9:
  462. case 12:
  463. case 15:
  464. fraction--;
  465. break;
  466. }
  467. // generate the command
  468. if (integer < 0.0) {
  469. data[3] = 0xD0; // West is a negative angle value
  470. } else if (integer >= 0.0) {
  471. data[3] = 0xE0; // East is a positive angle value
  472. }
  473. integer = abs(integer);
  474. data[3] |= ((integer / 16) & 0x0f);
  475. integer = integer % 16;
  476. data[4] |= ((integer & 0x0f) << 4) | fraction;
  477. return dvbfe_do_diseqc_command(fe, data, sizeof(data));
  478. }
  479. static int skipwhite(char **line, char *end)
  480. {
  481. while(**line) {
  482. if (end && (*line >= end))
  483. return -1;
  484. if (!isspace(**line))
  485. return 0;
  486. (*line)++;
  487. }
  488. return -1;
  489. }
  490. static int getstringupto(char **line, char *end, char *matches, char **ptrdest, int *ptrlen)
  491. {
  492. char *start = *line;
  493. while(**line) {
  494. if (end && (*line >= end))
  495. break;
  496. if (strchr(matches, **line)) {
  497. *ptrdest = start;
  498. *ptrlen = *line - start;
  499. return 0;
  500. }
  501. (*line)++;
  502. }
  503. *ptrdest = start;
  504. *ptrlen = *line - start;
  505. return 0;
  506. }
  507. static int parsefunction(char **line,
  508. char **nameptr, int *namelen,
  509. char **argsptr, int *argslen)
  510. {
  511. if (skipwhite(line, NULL))
  512. return -1;
  513. if (getstringupto(line, NULL, "(", nameptr, namelen))
  514. return -1;
  515. if ((*line) == 0)
  516. return -1;
  517. (*line)++; // skip the '('
  518. if (getstringupto(line, NULL, ")", argsptr, argslen))
  519. return -1;
  520. if ((*line) == 0)
  521. return -1;
  522. (*line)++; // skip the ')'
  523. return 0;
  524. }
  525. static int parseintarg(char **args, char *argsend, int *result)
  526. {
  527. char tmp[32];
  528. char *arg;
  529. int arglen;
  530. // skip whitespace
  531. if (skipwhite(args, argsend))
  532. return -1;
  533. // get the arg
  534. if (getstringupto(args, argsend, ",", &arg, &arglen))
  535. return -1;
  536. if ((**args) == ',')
  537. (*args)++; // skip the ',' if present
  538. if (arglen > 31)
  539. arglen = 31;
  540. strncpy(tmp, arg, arglen);
  541. tmp[arglen] = 0;
  542. if (sscanf(tmp, "%i", result) != 1)
  543. return -1;
  544. return 0;
  545. }
  546. static int parsechararg(char **args, char *argsend, int *result)
  547. {
  548. char *arg;
  549. int arglen;
  550. // skip whitespace
  551. if (skipwhite(args, argsend))
  552. return -1;
  553. // get the arg
  554. if (getstringupto(args, argsend, ",", &arg, &arglen))
  555. return -1;
  556. if ((**args) == ',')
  557. (*args)++; // skip the ',' if present
  558. if (arglen > 0)
  559. *result = arg[0];
  560. return 0;
  561. }
  562. static int parsefloatarg(char **args, char *argsend, float *result)
  563. {
  564. char tmp[32];
  565. char *arg;
  566. int arglen;
  567. // skip whitespace
  568. if (skipwhite(args, argsend))
  569. return -1;
  570. // get the arg
  571. if (getstringupto(args, argsend, ",", &arg, &arglen))
  572. return -1;
  573. if ((**args) == ',')
  574. (*args)++; // skip the ',' if present
  575. if (arglen > 31)
  576. arglen = 31;
  577. strncpy(tmp, arg, arglen);
  578. arg[arglen] = 0;
  579. if (sscanf(tmp, "%f", result) != 1)
  580. return -1;
  581. return 0;
  582. }
  583. static enum dvbsec_diseqc_switch parse_switch(int c)
  584. {
  585. switch(toupper(c)) {
  586. case 'A':
  587. return DISEQC_SWITCH_A;
  588. case 'B':
  589. return DISEQC_SWITCH_B;
  590. default:
  591. return DISEQC_SWITCH_UNCHANGED;
  592. }
  593. }
  594. int dvbsec_command(struct dvbfe_handle *fe, char *command)
  595. {
  596. char *name;
  597. char *args;
  598. int namelen;
  599. int argslen;
  600. int address;
  601. int iarg;
  602. int iarg2;
  603. int iarg3;
  604. int iarg4;
  605. float farg;
  606. while(!parsefunction(&command, &name, &namelen, &args, &argslen)) {
  607. char *argsend = args+argslen;
  608. if (!strncasecmp(name, "tone", namelen)) {
  609. if (parsechararg(&args, argsend, &iarg))
  610. return -1;
  611. #ifdef TEST_SEC_COMMAND
  612. printf("tone: %c\n", iarg);
  613. #else
  614. if (toupper(iarg) == 'B') {
  615. dvbfe_set_22k_tone(fe, DVBFE_SEC_TONE_ON);
  616. } else {
  617. dvbfe_set_22k_tone(fe, DVBFE_SEC_TONE_OFF);
  618. }
  619. #endif
  620. } else if (!strncasecmp(name, "voltage", namelen)) {
  621. if (parseintarg(&args, argsend, &iarg))
  622. return -1;
  623. #ifdef TEST_SEC_COMMAND
  624. printf("voltage: %i\n", iarg);
  625. #else
  626. switch(iarg) {
  627. case 0:
  628. dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_OFF);
  629. break;
  630. case 13:
  631. dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_13);
  632. break;
  633. case 18:
  634. dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_18);
  635. break;
  636. default:
  637. return -1;
  638. }
  639. #endif
  640. } else if (!strncasecmp(name, "toneburst", namelen)) {
  641. if (parsechararg(&args, argsend, &iarg))
  642. return -1;
  643. #ifdef TEST_SEC_COMMAND
  644. printf("toneburst: %c\n", iarg);
  645. #else
  646. if (toupper(iarg) == 'B') {
  647. dvbfe_set_tone_data_burst(fe, DVBFE_SEC_MINI_B);
  648. } else {
  649. dvbfe_set_tone_data_burst(fe, DVBFE_SEC_MINI_A);
  650. }
  651. #endif
  652. } else if (!strncasecmp(name, "highvoltage", namelen)) {
  653. if (parseintarg(&args, argsend, &iarg))
  654. return -1;
  655. #ifdef TEST_SEC_COMMAND
  656. printf("highvoltage: %i\n", iarg);
  657. #else
  658. dvbfe_set_high_lnb_voltage(fe, iarg ? 1 : 0);
  659. #endif
  660. } else if (!strncasecmp(name, "dishnetworks", namelen)) {
  661. if (parseintarg(&args, argsend, &iarg))
  662. return -1;
  663. #ifdef TEST_SEC_COMMAND
  664. printf("dishnetworks: %i\n", iarg);
  665. #else
  666. dvbfe_do_dishnetworks_legacy_command(fe, iarg);
  667. #endif
  668. } else if (!strncasecmp(name, "wait", namelen)) {
  669. if (parseintarg(&args, argsend, &iarg))
  670. return -1;
  671. #ifdef TEST_SEC_COMMAND
  672. printf("wait: %i\n", iarg);
  673. #else
  674. if (iarg)
  675. usleep(iarg * 1000);
  676. #endif
  677. } else if (!strncasecmp(name, "Dreset", namelen)) {
  678. if (parseintarg(&args, argsend, &address))
  679. return -1;
  680. if (parseintarg(&args, argsend, &iarg))
  681. return -1;
  682. #ifdef TEST_SEC_COMMAND
  683. printf("Dreset: %i %i\n", address, iarg);
  684. #else
  685. if (iarg) {
  686. dvbsec_diseqc_set_reset(fe, address, DISEQC_RESET);
  687. } else {
  688. dvbsec_diseqc_set_reset(fe, address, DISEQC_RESET_CLEAR);
  689. }
  690. #endif
  691. } else if (!strncasecmp(name, "Dpower", namelen)) {
  692. if (parseintarg(&args, argsend, &address))
  693. return -1;
  694. if (parseintarg(&args, argsend, &iarg))
  695. return -1;
  696. #ifdef TEST_SEC_COMMAND
  697. printf("Dpower: %i %i\n", address, iarg);
  698. #else
  699. if (iarg) {
  700. dvbsec_diseqc_set_power(fe, address, DISEQC_POWER_ON);
  701. } else {
  702. dvbsec_diseqc_set_power(fe, address, DISEQC_POWER_OFF);
  703. }
  704. #endif
  705. } else if (!strncasecmp(name, "Dcommitted", namelen)) {
  706. if (parseintarg(&args, argsend, &address))
  707. return -1;
  708. if (parsechararg(&args, argsend, &iarg))
  709. return -1;
  710. if (parsechararg(&args, argsend, &iarg2))
  711. return -1;
  712. if (parsechararg(&args, argsend, &iarg3))
  713. return -1;
  714. if (parsechararg(&args, argsend, &iarg4))
  715. return -1;
  716. enum dvbsec_diseqc_oscillator oscillator;
  717. switch(toupper(iarg)) {
  718. case 'H':
  719. oscillator = DISEQC_OSCILLATOR_HIGH;
  720. break;
  721. case 'L':
  722. oscillator = DISEQC_OSCILLATOR_LOW;
  723. break;
  724. default:
  725. oscillator = DISEQC_OSCILLATOR_UNCHANGED;
  726. break;
  727. }
  728. int polarization = -1;
  729. switch(toupper(iarg2)) {
  730. case 'H':
  731. polarization = DISEQC_POLARIZATION_H;
  732. break;
  733. case 'V':
  734. polarization = DISEQC_POLARIZATION_V;
  735. break;
  736. case 'L':
  737. polarization = DISEQC_POLARIZATION_L;
  738. break;
  739. case 'R':
  740. polarization = DISEQC_POLARIZATION_R;
  741. break;
  742. default:
  743. polarization = -1;
  744. break;
  745. }
  746. #ifdef TEST_SEC_COMMAND
  747. printf("Dcommitted: %i %i %i %i %i\n", address,
  748. oscillator,
  749. polarization,
  750. parse_switch(iarg3),
  751. parse_switch(iarg4));
  752. #else
  753. dvbsec_diseqc_set_committed_switches(fe, address,
  754. oscillator,
  755. polarization,
  756. parse_switch(iarg3),
  757. parse_switch(iarg4));
  758. #endif
  759. } else if (!strncasecmp(name, "Duncommitted", namelen)) {
  760. if (parsechararg(&args, argsend, &address))
  761. return -1;
  762. if (parsechararg(&args, argsend, &iarg))
  763. return -1;
  764. if (parsechararg(&args, argsend, &iarg2))
  765. return -1;
  766. if (parsechararg(&args, argsend, &iarg3))
  767. return -1;
  768. if (parsechararg(&args, argsend, &iarg4))
  769. return -1;
  770. #ifdef TEST_SEC_COMMAND
  771. printf("Duncommitted: %i %i %i %i %i\n", address,
  772. parse_switch(iarg),
  773. parse_switch(iarg2),
  774. parse_switch(iarg3),
  775. parse_switch(iarg4));
  776. #else
  777. dvbsec_diseqc_set_uncommitted_switches(fe, address,
  778. parse_switch(iarg),
  779. parse_switch(iarg2),
  780. parse_switch(iarg3),
  781. parse_switch(iarg4));
  782. #endif
  783. } else if (!strncasecmp(name, "Dfrequency", namelen)) {
  784. if (parseintarg(&args, argsend, &address))
  785. return -1;
  786. if (parseintarg(&args, argsend, &iarg))
  787. return -1;
  788. #ifdef TEST_SEC_COMMAND
  789. printf("Dfrequency: %i %i\n", address, iarg);
  790. #else
  791. dvbsec_diseqc_set_frequency(fe, address, iarg);
  792. #endif
  793. } else if (!strncasecmp(name, "Dchannel", namelen)) {
  794. if (parseintarg(&args, argsend, &address))
  795. return -1;
  796. if (parseintarg(&args, argsend, &iarg))
  797. return -1;
  798. #ifdef TEST_SEC_COMMAND
  799. printf("Dchannel: %i %i\n", address, iarg);
  800. #else
  801. dvbsec_diseqc_set_channel(fe, address, iarg);
  802. #endif
  803. } else if (!strncasecmp(name, "Dgotopreset", namelen)) {
  804. if (parseintarg(&args, argsend, &address))
  805. return -1;
  806. if (parseintarg(&args, argsend, &iarg))
  807. return -1;
  808. #ifdef TEST_SEC_COMMAND
  809. printf("Dgotopreset: %i %i\n", address, iarg);
  810. #else
  811. dvbsec_diseqc_goto_satpos_preset(fe, address, iarg);
  812. #endif
  813. } else if (!strncasecmp(name, "Dgotobearing", namelen)) {
  814. if (parseintarg(&args, argsend, &address))
  815. return -1;
  816. if (parsefloatarg(&args, argsend, &farg))
  817. return -1;
  818. #ifdef TEST_SEC_COMMAND
  819. printf("Dgotobearing: %i %f\n", address, farg);
  820. #else
  821. dvbsec_diseqc_goto_rotator_bearing(fe, address, farg);
  822. #endif
  823. } else {
  824. return -1;
  825. }
  826. }
  827. return 0;
  828. }