dvbfe.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. /*
  2. * libdvbfe - a DVB frontend library
  3. *
  4. * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
  5. * Copyright (C) 2005 Manu Abraham <abraham.manu@gmail.com>
  6. * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  21. */
  22. #define _GNU_SOURCE
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <stdio.h>
  26. #include <sys/param.h>
  27. #include <sys/ioctl.h>
  28. #include <sys/time.h>
  29. #include <sys/poll.h>
  30. #include <fcntl.h>
  31. #include <unistd.h>
  32. #include <ctype.h>
  33. #include <errno.h>
  34. #include <linux/dvb/frontend.h>
  35. #include <libdvbmisc/dvbmisc.h>
  36. #include "dvbfe.h"
  37. int verbose = 0;
  38. static int dvbfe_spectral_inversion_to_kapi[][2] =
  39. {
  40. { DVBFE_INVERSION_OFF, INVERSION_OFF },
  41. { DVBFE_INVERSION_ON, INVERSION_ON },
  42. { DVBFE_INVERSION_AUTO, INVERSION_AUTO },
  43. { -1, -1 }
  44. };
  45. static int dvbfe_code_rate_to_kapi[][2] =
  46. {
  47. { DVBFE_FEC_NONE, FEC_NONE },
  48. { DVBFE_FEC_1_2, FEC_1_2 },
  49. { DVBFE_FEC_2_3, FEC_2_3 },
  50. { DVBFE_FEC_3_4, FEC_3_4 },
  51. { DVBFE_FEC_4_5, FEC_4_5 },
  52. { DVBFE_FEC_5_6, FEC_5_6 },
  53. { DVBFE_FEC_6_7, FEC_6_7 },
  54. { DVBFE_FEC_7_8, FEC_7_8 },
  55. { DVBFE_FEC_8_9, FEC_8_9 },
  56. { DVBFE_FEC_AUTO, FEC_AUTO },
  57. { -1, -1 }
  58. };
  59. static int dvbfe_dvbt_const_to_kapi[][2] =
  60. {
  61. { DVBFE_DVBT_CONST_QPSK, FE_QPSK },
  62. { DVBFE_DVBT_CONST_QAM_16, QAM_16 },
  63. { DVBFE_DVBT_CONST_QAM_32, QAM_32 },
  64. { DVBFE_DVBT_CONST_QAM_64, QAM_64 },
  65. { DVBFE_DVBT_CONST_QAM_128, QAM_128 },
  66. { DVBFE_DVBT_CONST_QAM_256, QAM_256 },
  67. { DVBFE_DVBT_CONST_AUTO, QAM_AUTO },
  68. { -1, -1 }
  69. };
  70. static int dvbfe_dvbc_mod_to_kapi[][2] =
  71. {
  72. { DVBFE_DVBC_MOD_QAM_16, QAM_16 },
  73. { DVBFE_DVBC_MOD_QAM_32, QAM_32 },
  74. { DVBFE_DVBC_MOD_QAM_64, QAM_64 },
  75. { DVBFE_DVBC_MOD_QAM_128, QAM_128 },
  76. { DVBFE_DVBC_MOD_QAM_256, QAM_256 },
  77. { DVBFE_DVBC_MOD_AUTO, QAM_AUTO },
  78. { -1, -1 }
  79. };
  80. static int dvbfe_atsc_mod_to_kapi[][2] =
  81. {
  82. { DVBFE_ATSC_MOD_QAM_64, QAM_64 },
  83. { DVBFE_ATSC_MOD_QAM_256, QAM_256 },
  84. { DVBFE_ATSC_MOD_VSB_8, VSB_8 },
  85. { DVBFE_ATSC_MOD_VSB_16, VSB_16 },
  86. { DVBFE_ATSC_MOD_AUTO, QAM_AUTO },
  87. { -1, -1 }
  88. };
  89. static int dvbfe_dvbt_transmit_mode_to_kapi[][2] =
  90. {
  91. { DVBFE_DVBT_TRANSMISSION_MODE_2K, TRANSMISSION_MODE_2K },
  92. { DVBFE_DVBT_TRANSMISSION_MODE_8K, TRANSMISSION_MODE_8K },
  93. { DVBFE_DVBT_TRANSMISSION_MODE_AUTO, TRANSMISSION_MODE_AUTO },
  94. { -1, -1 }
  95. };
  96. static int dvbfe_dvbt_bandwidth_to_kapi[][2] =
  97. {
  98. { DVBFE_DVBT_BANDWIDTH_8_MHZ, BANDWIDTH_8_MHZ },
  99. { DVBFE_DVBT_BANDWIDTH_7_MHZ, BANDWIDTH_7_MHZ },
  100. { DVBFE_DVBT_BANDWIDTH_6_MHZ, BANDWIDTH_6_MHZ },
  101. { DVBFE_DVBT_BANDWIDTH_AUTO, BANDWIDTH_AUTO },
  102. { -1, -1 }
  103. };
  104. static int dvbfe_dvbt_guard_interval_to_kapi[][2] =
  105. {
  106. { DVBFE_DVBT_GUARD_INTERVAL_1_32, GUARD_INTERVAL_1_32},
  107. { DVBFE_DVBT_GUARD_INTERVAL_1_16, GUARD_INTERVAL_1_16},
  108. { DVBFE_DVBT_GUARD_INTERVAL_1_8, GUARD_INTERVAL_1_8},
  109. { DVBFE_DVBT_GUARD_INTERVAL_1_4, GUARD_INTERVAL_1_4},
  110. { DVBFE_DVBT_GUARD_INTERVAL_AUTO, GUARD_INTERVAL_AUTO},
  111. { -1, -1 }
  112. };
  113. static int dvbfe_dvbt_hierarchy_to_kapi[][2] =
  114. {
  115. { DVBFE_DVBT_HIERARCHY_NONE, HIERARCHY_NONE },
  116. { DVBFE_DVBT_HIERARCHY_1, HIERARCHY_1 },
  117. { DVBFE_DVBT_HIERARCHY_2, HIERARCHY_2 },
  118. { DVBFE_DVBT_HIERARCHY_4, HIERARCHY_4 },
  119. { DVBFE_DVBT_HIERARCHY_AUTO, HIERARCHY_AUTO },
  120. { -1, -1 }
  121. };
  122. static int lookupval(int val, int reverse, int table[][2])
  123. {
  124. int i =0;
  125. while(table[i][0] != -1) {
  126. if (!reverse) {
  127. if (val == table[i][0]) {
  128. return table[i][1];
  129. }
  130. } else {
  131. if (val == table[i][1]) {
  132. return table[i][0];
  133. }
  134. }
  135. i++;
  136. }
  137. return -1;
  138. }
  139. struct dvbfe_handle {
  140. int fd;
  141. enum dvbfe_type type;
  142. char *name;
  143. };
  144. struct dvbfe_handle *dvbfe_open(int adapter, int frontend, int readonly)
  145. {
  146. char filename[PATH_MAX+1];
  147. struct dvbfe_handle *fehandle;
  148. int fd;
  149. struct dvb_frontend_info info;
  150. // flags
  151. int flags = O_RDWR;
  152. if (readonly) {
  153. flags = O_RDONLY;
  154. }
  155. // open it (try normal /dev structure first)
  156. sprintf(filename, "/dev/dvb/adapter%i/frontend%i", adapter, frontend);
  157. if ((fd = open(filename, flags)) < 0) {
  158. // if that failed, try a flat /dev structure
  159. sprintf(filename, "/dev/dvb%i.frontend%i", adapter, frontend);
  160. if ((fd = open(filename, flags)) < 0) {
  161. return NULL;
  162. }
  163. }
  164. // determine fe type
  165. if (ioctl(fd, FE_GET_INFO, &info)) {
  166. close(fd);
  167. return NULL;
  168. }
  169. // setup structure
  170. fehandle = (struct dvbfe_handle*) malloc(sizeof(struct dvbfe_handle));
  171. memset(fehandle, 0, sizeof(struct dvbfe_handle));
  172. fehandle->fd = fd;
  173. switch(info.type) {
  174. case FE_QPSK:
  175. fehandle->type = DVBFE_TYPE_DVBS;
  176. break;
  177. case FE_QAM:
  178. fehandle->type = DVBFE_TYPE_DVBC;
  179. break;
  180. case FE_OFDM:
  181. fehandle->type = DVBFE_TYPE_DVBT;
  182. break;
  183. case FE_ATSC:
  184. fehandle->type = DVBFE_TYPE_ATSC;
  185. break;
  186. }
  187. fehandle->name = strndup(info.name, sizeof(info.name));
  188. // done
  189. return fehandle;
  190. }
  191. void dvbfe_close(struct dvbfe_handle *fehandle)
  192. {
  193. close(fehandle->fd);
  194. free(fehandle->name);
  195. free(fehandle);
  196. }
  197. extern int dvbfe_get_info(struct dvbfe_handle *fehandle,
  198. enum dvbfe_info_mask querymask,
  199. struct dvbfe_info *result,
  200. enum dvbfe_info_querytype querytype,
  201. int timeout)
  202. {
  203. int returnval = 0;
  204. struct dvb_frontend_event kevent;
  205. int ok = 0;
  206. result->name = fehandle->name;
  207. result->type = fehandle->type;
  208. switch(querytype) {
  209. case DVBFE_INFO_QUERYTYPE_IMMEDIATE:
  210. if (querymask & DVBFE_INFO_LOCKSTATUS) {
  211. if (!ioctl(fehandle->fd, FE_READ_STATUS, &kevent.status)) {
  212. returnval |= DVBFE_INFO_LOCKSTATUS;
  213. }
  214. }
  215. if (querymask & DVBFE_INFO_FEPARAMS) {
  216. if (!ioctl(fehandle->fd, FE_GET_FRONTEND, &kevent.parameters)) {
  217. returnval |= DVBFE_INFO_FEPARAMS;
  218. }
  219. }
  220. break;
  221. case DVBFE_INFO_QUERYTYPE_LOCKCHANGE:
  222. {
  223. struct pollfd pollfd;
  224. pollfd.fd = fehandle->fd;
  225. pollfd.events = POLLIN | POLLERR;
  226. ok = 1;
  227. if (poll(&pollfd, 1, timeout) < 0)
  228. ok = 0;
  229. if (pollfd.revents & POLLERR)
  230. ok = 0;
  231. if (!(pollfd.revents & POLLIN))
  232. ok = 0;
  233. }
  234. if (ok &&
  235. ((querymask & DVBFE_INFO_LOCKSTATUS) ||
  236. (querymask & DVBFE_INFO_FEPARAMS))) {
  237. if (!ioctl(fehandle->fd, FE_GET_EVENT, &kevent)) {
  238. if (querymask & DVBFE_INFO_LOCKSTATUS)
  239. returnval |= DVBFE_INFO_LOCKSTATUS;
  240. if (querymask & DVBFE_INFO_FEPARAMS)
  241. returnval |= DVBFE_INFO_FEPARAMS;
  242. }
  243. }
  244. break;
  245. }
  246. if (returnval & DVBFE_INFO_LOCKSTATUS) {
  247. result->signal = kevent.status & FE_HAS_SIGNAL ? 1 : 0;
  248. result->carrier = kevent.status & FE_HAS_CARRIER ? 1 : 0;
  249. result->viterbi = kevent.status & FE_HAS_VITERBI ? 1 : 0;
  250. result->sync = kevent.status & FE_HAS_SYNC ? 1 : 0;
  251. result->lock = kevent.status & FE_HAS_LOCK ? 1 : 0;
  252. }
  253. if (returnval & DVBFE_INFO_FEPARAMS) {
  254. result->feparams.frequency = kevent.parameters.frequency;
  255. result->feparams.inversion = lookupval(kevent.parameters.inversion, 1, dvbfe_spectral_inversion_to_kapi);
  256. switch(fehandle->type) {
  257. case FE_QPSK:
  258. result->feparams.u.dvbs.symbol_rate = kevent.parameters.u.qpsk.symbol_rate;
  259. result->feparams.u.dvbs.fec_inner =
  260. lookupval(kevent.parameters.u.qpsk.fec_inner, 1, dvbfe_code_rate_to_kapi);
  261. break;
  262. case FE_QAM:
  263. result->feparams.u.dvbc.symbol_rate = kevent.parameters.u.qam.symbol_rate;
  264. result->feparams.u.dvbc.fec_inner =
  265. lookupval(kevent.parameters.u.qam.fec_inner, 1, dvbfe_code_rate_to_kapi);
  266. result->feparams.u.dvbc.modulation =
  267. lookupval(kevent.parameters.u.qam.modulation, 1, dvbfe_dvbc_mod_to_kapi);
  268. break;
  269. case FE_OFDM:
  270. result->feparams.u.dvbt.bandwidth =
  271. lookupval(kevent.parameters.u.ofdm.bandwidth, 1, dvbfe_dvbt_bandwidth_to_kapi);
  272. result->feparams.u.dvbt.code_rate_HP =
  273. lookupval(kevent.parameters.u.ofdm.code_rate_HP, 1, dvbfe_code_rate_to_kapi);
  274. result->feparams.u.dvbt.code_rate_LP =
  275. lookupval(kevent.parameters.u.ofdm.code_rate_LP, 1, dvbfe_code_rate_to_kapi);
  276. result->feparams.u.dvbt.constellation =
  277. lookupval(kevent.parameters.u.ofdm.constellation, 1, dvbfe_dvbt_const_to_kapi);
  278. result->feparams.u.dvbt.transmission_mode =
  279. lookupval(kevent.parameters.u.ofdm.transmission_mode, 1, dvbfe_dvbt_transmit_mode_to_kapi);
  280. result->feparams.u.dvbt.guard_interval =
  281. lookupval(kevent.parameters.u.ofdm.guard_interval, 1, dvbfe_dvbt_guard_interval_to_kapi);
  282. result->feparams.u.dvbt.hierarchy_information =
  283. lookupval(kevent.parameters.u.ofdm.hierarchy_information, 1, dvbfe_dvbt_hierarchy_to_kapi);
  284. break;
  285. case FE_ATSC:
  286. result->feparams.u.atsc.modulation =
  287. lookupval(kevent.parameters.u.vsb.modulation, 1, dvbfe_atsc_mod_to_kapi);
  288. break;
  289. }
  290. }
  291. if (querymask & DVBFE_INFO_BER) {
  292. if (!ioctl(fehandle->fd, FE_READ_BER, &result->ber))
  293. returnval |= DVBFE_INFO_BER;
  294. }
  295. if (querymask & DVBFE_INFO_SIGNAL_STRENGTH) {
  296. if (!ioctl(fehandle->fd, FE_READ_SIGNAL_STRENGTH, &result->signal_strength))
  297. returnval |= DVBFE_INFO_SIGNAL_STRENGTH;
  298. }
  299. if (querymask & DVBFE_INFO_SNR) {
  300. if (!ioctl(fehandle->fd, FE_READ_SNR, &result->snr))
  301. returnval |= DVBFE_INFO_SNR;
  302. }
  303. if (querymask & DVBFE_INFO_UNCORRECTED_BLOCKS) {
  304. if (!ioctl(fehandle->fd, FE_READ_UNCORRECTED_BLOCKS, &result->ucblocks))
  305. returnval |= DVBFE_INFO_UNCORRECTED_BLOCKS;
  306. }
  307. // done
  308. return returnval;
  309. }
  310. int dvbfe_set(struct dvbfe_handle *fehandle,
  311. struct dvbfe_parameters *params,
  312. int timeout)
  313. {
  314. struct dvb_frontend_parameters kparams;
  315. int res;
  316. struct timeval endtime;
  317. fe_status_t status;
  318. kparams.frequency = params->frequency;
  319. kparams.inversion = lookupval(params->inversion, 0, dvbfe_spectral_inversion_to_kapi);
  320. switch(fehandle->type) {
  321. case FE_QPSK:
  322. kparams.u.qpsk.symbol_rate = params->u.dvbs.symbol_rate;
  323. kparams.u.qpsk.fec_inner = lookupval(params->u.dvbs.fec_inner, 0, dvbfe_code_rate_to_kapi);
  324. break;
  325. case FE_QAM:
  326. kparams.u.qam.symbol_rate = params->u.dvbc.symbol_rate;
  327. kparams.u.qam.fec_inner = lookupval(params->u.dvbc.fec_inner, 0, dvbfe_code_rate_to_kapi);
  328. kparams.u.qam.modulation = lookupval(params->u.dvbc.modulation, 0, dvbfe_dvbc_mod_to_kapi);
  329. break;
  330. case FE_OFDM:
  331. kparams.u.ofdm.bandwidth = lookupval(params->u.dvbt.bandwidth, 0, dvbfe_dvbt_bandwidth_to_kapi);
  332. kparams.u.ofdm.code_rate_HP = lookupval(params->u.dvbt.code_rate_HP, 0, dvbfe_code_rate_to_kapi);
  333. kparams.u.ofdm.code_rate_LP = lookupval(params->u.dvbt.code_rate_LP, 0, dvbfe_code_rate_to_kapi);
  334. kparams.u.ofdm.constellation = lookupval(params->u.dvbt.constellation, 0, dvbfe_dvbt_const_to_kapi);
  335. kparams.u.ofdm.transmission_mode =
  336. lookupval(params->u.dvbt.transmission_mode, 0, dvbfe_dvbt_transmit_mode_to_kapi);
  337. kparams.u.ofdm.guard_interval =
  338. lookupval(params->u.dvbt.guard_interval, 0, dvbfe_dvbt_guard_interval_to_kapi);
  339. kparams.u.ofdm.hierarchy_information =
  340. lookupval(params->u.dvbt.hierarchy_information, 0, dvbfe_dvbt_hierarchy_to_kapi);
  341. break;
  342. case FE_ATSC:
  343. kparams.u.vsb.modulation = lookupval(params->u.atsc.modulation, 0, dvbfe_atsc_mod_to_kapi);
  344. break;
  345. default:
  346. return -EINVAL;
  347. }
  348. // set it and check for error
  349. res = ioctl(fehandle->fd, FE_SET_FRONTEND, &kparams);
  350. if (res)
  351. return res;
  352. // 0 => return immediately
  353. if (timeout == 0) {
  354. return 0;
  355. }
  356. /* calculate timeout */
  357. if (timeout > 0) {
  358. gettimeofday(&endtime, NULL);
  359. timeout *= 1000;
  360. endtime.tv_sec += timeout / 1000000;
  361. endtime.tv_usec += timeout % 1000000;
  362. }
  363. /* wait for a lock */
  364. while(1) {
  365. /* has it locked? */
  366. if (!ioctl(fehandle->fd, FE_READ_STATUS, &status)) {
  367. if (status & FE_HAS_LOCK) {
  368. break;
  369. }
  370. }
  371. /* check for timeout */
  372. if (timeout > 0) {
  373. struct timeval curtime;
  374. gettimeofday(&curtime, NULL);
  375. if ((curtime.tv_sec > endtime.tv_sec) ||
  376. ((curtime.tv_sec == endtime.tv_sec) && (curtime.tv_usec >= endtime.tv_usec))) {
  377. break;
  378. }
  379. }
  380. /* delay for a bit */
  381. usleep(100000);
  382. }
  383. /* exit */
  384. if (status & FE_HAS_LOCK)
  385. return 0;
  386. return -ETIMEDOUT;
  387. }
  388. int dvbfe_get_pollfd(struct dvbfe_handle *handle)
  389. {
  390. return handle->fd;
  391. }
  392. int dvbfe_set_22k_tone(struct dvbfe_handle *fehandle, enum dvbfe_sec_tone_mode tone)
  393. {
  394. int ret = 0;
  395. switch (tone) {
  396. case DVBFE_SEC_TONE_OFF:
  397. ret = ioctl(fehandle->fd, FE_SET_TONE, SEC_TONE_OFF);
  398. break;
  399. case DVBFE_SEC_TONE_ON:
  400. ret = ioctl(fehandle->fd, FE_SET_TONE, SEC_TONE_ON);
  401. break;
  402. default:
  403. print(verbose, ERROR, 1, "Invalid command !");
  404. break;
  405. }
  406. if (ret == -1)
  407. print(verbose, ERROR, 1, "IOCTL failed !");
  408. return ret;
  409. }
  410. int dvbfe_set_tone_data_burst(struct dvbfe_handle *fehandle, enum dvbfe_sec_mini_cmd minicmd)
  411. {
  412. int ret = 0;
  413. switch (minicmd) {
  414. case DVBFE_SEC_MINI_A:
  415. ret = ioctl(fehandle->fd, FE_DISEQC_SEND_BURST, SEC_MINI_A);
  416. break;
  417. case DVBFE_SEC_MINI_B:
  418. ret = ioctl(fehandle->fd, FE_DISEQC_SEND_BURST, SEC_MINI_B);
  419. break;
  420. default:
  421. print(verbose, ERROR, 1, "Invalid command");
  422. break;
  423. }
  424. if (ret == -1)
  425. print(verbose, ERROR, 1, "IOCTL failed");
  426. return ret;
  427. }
  428. int dvbfe_set_voltage(struct dvbfe_handle *fehandle, enum dvbfe_sec_voltage voltage)
  429. {
  430. int ret = 0;
  431. switch (voltage) {
  432. case DVBFE_SEC_VOLTAGE_OFF:
  433. ret = ioctl(fehandle->fd, FE_SET_VOLTAGE, SEC_VOLTAGE_OFF);
  434. break;
  435. case DVBFE_SEC_VOLTAGE_13:
  436. ret = ioctl(fehandle->fd, FE_SET_VOLTAGE, SEC_VOLTAGE_13);
  437. break;
  438. case DVBFE_SEC_VOLTAGE_18:
  439. ret = ioctl(fehandle->fd, FE_SET_VOLTAGE, SEC_VOLTAGE_18);
  440. break;
  441. default:
  442. print(verbose, ERROR, 1, "Invalid command");
  443. break;
  444. }
  445. if (ret == -1)
  446. print(verbose, ERROR, 1, "IOCTL failed");
  447. return ret;
  448. }
  449. int dvbfe_set_high_lnb_voltage(struct dvbfe_handle *fehandle, int on)
  450. {
  451. switch (on) {
  452. case 0:
  453. ioctl(fehandle->fd, FE_ENABLE_HIGH_LNB_VOLTAGE, 0);
  454. break;
  455. default:
  456. ioctl(fehandle->fd, FE_ENABLE_HIGH_LNB_VOLTAGE, 1);
  457. break;
  458. }
  459. return 0;
  460. }
  461. int dvbfe_do_dishnetworks_legacy_command(struct dvbfe_handle *fehandle, unsigned int cmd)
  462. {
  463. int ret = 0;
  464. ret = ioctl(fehandle->fd, FE_DISHNETWORK_SEND_LEGACY_CMD, cmd);
  465. if (ret == -1)
  466. print(verbose, ERROR, 1, "IOCTL failed");
  467. return ret;
  468. }
  469. int dvbfe_do_diseqc_command(struct dvbfe_handle *fehandle, uint8_t *data, uint8_t len)
  470. {
  471. int ret = 0;
  472. struct dvb_diseqc_master_cmd diseqc_message;
  473. if (len > 6)
  474. return -EINVAL;
  475. diseqc_message.msg_len = len;
  476. memcpy(diseqc_message.msg, data, len);
  477. ret = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &diseqc_message);
  478. if (ret == -1)
  479. print(verbose, ERROR, 1, "IOCTL failed");
  480. return ret;
  481. }
  482. int dvbfe_diseqc_read(struct dvbfe_handle *fehandle, int timeout, unsigned char *buf, unsigned int len)
  483. {
  484. struct dvb_diseqc_slave_reply reply;
  485. int result;
  486. if (len > 4)
  487. len = 4;
  488. reply.timeout = timeout;
  489. reply.msg_len = len;
  490. if ((result = ioctl(fehandle->fd, FE_DISEQC_RECV_SLAVE_REPLY, reply)) != 0)
  491. return result;
  492. if (reply.msg_len < len)
  493. len = reply.msg_len;
  494. memcpy(buf, reply.msg, len);
  495. return len;
  496. }