avc_api.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051
  1. /*
  2. * FireDTV driver (formerly known as FireSAT)
  3. *
  4. * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
  5. * Copyright (C) 2008 Ben Backx <ben@bbackx.com>
  6. * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. */
  13. #include <linux/bug.h>
  14. #include <linux/crc32.h>
  15. #include <linux/delay.h>
  16. #include <linux/device.h>
  17. #include <linux/kernel.h>
  18. #include <linux/moduleparam.h>
  19. #include <linux/mutex.h>
  20. #include <linux/string.h>
  21. #include <linux/wait.h>
  22. #include <linux/workqueue.h>
  23. #include <ieee1394_transactions.h>
  24. #include <nodemgr.h>
  25. #include "avc_api.h"
  26. #include "firesat.h"
  27. #include "firesat-rc.h"
  28. #define FCP_COMMAND_REGISTER 0xfffff0000b00ULL
  29. static int __avc_write(struct firesat *firesat,
  30. const AVCCmdFrm *CmdFrm, AVCRspFrm *RspFrm)
  31. {
  32. int err, retry;
  33. if (RspFrm)
  34. firesat->avc_reply_received = false;
  35. for (retry = 0; retry < 6; retry++) {
  36. err = hpsb_node_write(firesat->ud->ne, FCP_COMMAND_REGISTER,
  37. (quadlet_t *)CmdFrm, CmdFrm->length);
  38. if (err) {
  39. firesat->avc_reply_received = true;
  40. dev_err(&firesat->ud->device,
  41. "FCP command write failed\n");
  42. return err;
  43. }
  44. if (!RspFrm)
  45. return 0;
  46. /*
  47. * AV/C specs say that answers should be sent within 150 ms.
  48. * Time out after 200 ms.
  49. */
  50. if (wait_event_timeout(firesat->avc_wait,
  51. firesat->avc_reply_received,
  52. HZ / 5) != 0) {
  53. memcpy(RspFrm, firesat->respfrm, firesat->resp_length);
  54. RspFrm->length = firesat->resp_length;
  55. return 0;
  56. }
  57. }
  58. dev_err(&firesat->ud->device, "FCP response timed out\n");
  59. return -ETIMEDOUT;
  60. }
  61. static int avc_write(struct firesat *firesat,
  62. const AVCCmdFrm *CmdFrm, AVCRspFrm *RspFrm)
  63. {
  64. int ret;
  65. if (mutex_lock_interruptible(&firesat->avc_mutex))
  66. return -EINTR;
  67. ret = __avc_write(firesat, CmdFrm, RspFrm);
  68. mutex_unlock(&firesat->avc_mutex);
  69. return ret;
  70. }
  71. int avc_recv(struct firesat *firesat, u8 *data, size_t length)
  72. {
  73. AVCRspFrm *RspFrm = (AVCRspFrm *)data;
  74. if (length >= 8 &&
  75. RspFrm->operand[0] == SFE_VENDOR_DE_COMPANYID_0 &&
  76. RspFrm->operand[1] == SFE_VENDOR_DE_COMPANYID_1 &&
  77. RspFrm->operand[2] == SFE_VENDOR_DE_COMPANYID_2 &&
  78. RspFrm->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL) {
  79. if (RspFrm->resp == CHANGED) {
  80. firesat_handle_rc(firesat,
  81. RspFrm->operand[4] << 8 | RspFrm->operand[5]);
  82. schedule_work(&firesat->remote_ctrl_work);
  83. } else if (RspFrm->resp != INTERIM) {
  84. dev_info(&firesat->ud->device,
  85. "remote control result = %d\n", RspFrm->resp);
  86. }
  87. return 0;
  88. }
  89. if (firesat->avc_reply_received) {
  90. dev_err(&firesat->ud->device,
  91. "received out-of-order AVC response, ignored\n");
  92. return -EIO;
  93. }
  94. memcpy(firesat->respfrm, data, length);
  95. firesat->resp_length = length;
  96. firesat->avc_reply_received = true;
  97. wake_up(&firesat->avc_wait);
  98. return 0;
  99. }
  100. /*
  101. * tuning command for setting the relative LNB frequency
  102. * (not supported by the AVC standard)
  103. */
  104. static void avc_tuner_tuneqpsk(struct firesat *firesat,
  105. struct dvb_frontend_parameters *params, AVCCmdFrm *CmdFrm)
  106. {
  107. CmdFrm->opcode = VENDOR;
  108. CmdFrm->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
  109. CmdFrm->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
  110. CmdFrm->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
  111. CmdFrm->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK;
  112. CmdFrm->operand[4] = (params->frequency >> 24) & 0xff;
  113. CmdFrm->operand[5] = (params->frequency >> 16) & 0xff;
  114. CmdFrm->operand[6] = (params->frequency >> 8) & 0xff;
  115. CmdFrm->operand[7] = params->frequency & 0xff;
  116. CmdFrm->operand[8] = ((params->u.qpsk.symbol_rate / 1000) >> 8) & 0xff;
  117. CmdFrm->operand[9] = (params->u.qpsk.symbol_rate / 1000) & 0xff;
  118. switch(params->u.qpsk.fec_inner) {
  119. case FEC_1_2:
  120. CmdFrm->operand[10] = 0x1; break;
  121. case FEC_2_3:
  122. CmdFrm->operand[10] = 0x2; break;
  123. case FEC_3_4:
  124. CmdFrm->operand[10] = 0x3; break;
  125. case FEC_5_6:
  126. CmdFrm->operand[10] = 0x4; break;
  127. case FEC_7_8:
  128. CmdFrm->operand[10] = 0x5; break;
  129. case FEC_4_5:
  130. case FEC_8_9:
  131. case FEC_AUTO:
  132. default:
  133. CmdFrm->operand[10] = 0x0;
  134. }
  135. if (firesat->voltage == 0xff)
  136. CmdFrm->operand[11] = 0xff;
  137. else if (firesat->voltage == SEC_VOLTAGE_18) /* polarisation */
  138. CmdFrm->operand[11] = 0;
  139. else
  140. CmdFrm->operand[11] = 1;
  141. if (firesat->tone == 0xff)
  142. CmdFrm->operand[12] = 0xff;
  143. else if (firesat->tone == SEC_TONE_ON) /* band */
  144. CmdFrm->operand[12] = 1;
  145. else
  146. CmdFrm->operand[12] = 0;
  147. if (firesat->type == FireSAT_DVB_S2) {
  148. CmdFrm->operand[13] = 0x1;
  149. CmdFrm->operand[14] = 0xff;
  150. CmdFrm->operand[15] = 0xff;
  151. CmdFrm->length = 20;
  152. } else {
  153. CmdFrm->length = 16;
  154. }
  155. }
  156. static void avc_tuner_dsd_dvb_c(struct dvb_frontend_parameters *params,
  157. AVCCmdFrm *CmdFrm)
  158. {
  159. M_VALID_FLAGS flags;
  160. flags.Bits.Modulation = params->u.qam.modulation != QAM_AUTO;
  161. flags.Bits.FEC_inner = params->u.qam.fec_inner != FEC_AUTO;
  162. flags.Bits.FEC_outer = 0;
  163. flags.Bits.Symbol_Rate = 1;
  164. flags.Bits.Frequency = 1;
  165. flags.Bits.Orbital_Pos = 0;
  166. flags.Bits.Polarisation = 0;
  167. flags.Bits.reserved_fields = 0;
  168. flags.Bits.reserved1 = 0;
  169. flags.Bits.Network_ID = 0;
  170. CmdFrm->opcode = DSD;
  171. CmdFrm->operand[0] = 0; /* source plug */
  172. CmdFrm->operand[1] = 0xd2; /* subfunction replace */
  173. CmdFrm->operand[2] = 0x20; /* system id = DVB */
  174. CmdFrm->operand[3] = 0x00; /* antenna number */
  175. /* system_specific_multiplex selection_length */
  176. CmdFrm->operand[4] = 0x11;
  177. CmdFrm->operand[5] = flags.Valid_Word.ByteHi; /* valid_flags [0] */
  178. CmdFrm->operand[6] = flags.Valid_Word.ByteLo; /* valid_flags [1] */
  179. CmdFrm->operand[7] = 0x00;
  180. CmdFrm->operand[8] = 0x00;
  181. CmdFrm->operand[9] = 0x00;
  182. CmdFrm->operand[10] = 0x00;
  183. CmdFrm->operand[11] =
  184. (((params->frequency / 4000) >> 16) & 0xff) | (2 << 6);
  185. CmdFrm->operand[12] =
  186. ((params->frequency / 4000) >> 8) & 0xff;
  187. CmdFrm->operand[13] = (params->frequency / 4000) & 0xff;
  188. CmdFrm->operand[14] =
  189. ((params->u.qpsk.symbol_rate / 1000) >> 12) & 0xff;
  190. CmdFrm->operand[15] =
  191. ((params->u.qpsk.symbol_rate / 1000) >> 4) & 0xff;
  192. CmdFrm->operand[16] =
  193. ((params->u.qpsk.symbol_rate / 1000) << 4) & 0xf0;
  194. CmdFrm->operand[17] = 0x00;
  195. switch (params->u.qpsk.fec_inner) {
  196. case FEC_1_2:
  197. CmdFrm->operand[18] = 0x1; break;
  198. case FEC_2_3:
  199. CmdFrm->operand[18] = 0x2; break;
  200. case FEC_3_4:
  201. CmdFrm->operand[18] = 0x3; break;
  202. case FEC_5_6:
  203. CmdFrm->operand[18] = 0x4; break;
  204. case FEC_7_8:
  205. CmdFrm->operand[18] = 0x5; break;
  206. case FEC_8_9:
  207. CmdFrm->operand[18] = 0x6; break;
  208. case FEC_4_5:
  209. CmdFrm->operand[18] = 0x8; break;
  210. case FEC_AUTO:
  211. default:
  212. CmdFrm->operand[18] = 0x0;
  213. }
  214. switch (params->u.qam.modulation) {
  215. case QAM_16:
  216. CmdFrm->operand[19] = 0x08; break;
  217. case QAM_32:
  218. CmdFrm->operand[19] = 0x10; break;
  219. case QAM_64:
  220. CmdFrm->operand[19] = 0x18; break;
  221. case QAM_128:
  222. CmdFrm->operand[19] = 0x20; break;
  223. case QAM_256:
  224. CmdFrm->operand[19] = 0x28; break;
  225. case QAM_AUTO:
  226. default:
  227. CmdFrm->operand[19] = 0x00;
  228. }
  229. CmdFrm->operand[20] = 0x00;
  230. CmdFrm->operand[21] = 0x00;
  231. /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */
  232. CmdFrm->operand[22] = 0x00;
  233. CmdFrm->length = 28;
  234. }
  235. static void avc_tuner_dsd_dvb_t(struct dvb_frontend_parameters *params,
  236. AVCCmdFrm *CmdFrm)
  237. {
  238. M_VALID_FLAGS flags;
  239. flags.Bits_T.GuardInterval =
  240. params->u.ofdm.guard_interval != GUARD_INTERVAL_AUTO;
  241. flags.Bits_T.CodeRateLPStream =
  242. params->u.ofdm.code_rate_LP != FEC_AUTO;
  243. flags.Bits_T.CodeRateHPStream =
  244. params->u.ofdm.code_rate_HP != FEC_AUTO;
  245. flags.Bits_T.HierarchyInfo =
  246. params->u.ofdm.hierarchy_information != HIERARCHY_AUTO;
  247. flags.Bits_T.Constellation =
  248. params->u.ofdm.constellation != QAM_AUTO;
  249. flags.Bits_T.Bandwidth =
  250. params->u.ofdm.bandwidth != BANDWIDTH_AUTO;
  251. flags.Bits_T.CenterFrequency = 1;
  252. flags.Bits_T.reserved1 = 0;
  253. flags.Bits_T.reserved2 = 0;
  254. flags.Bits_T.OtherFrequencyFlag = 0;
  255. flags.Bits_T.TransmissionMode =
  256. params->u.ofdm.transmission_mode != TRANSMISSION_MODE_AUTO;
  257. flags.Bits_T.NetworkId = 0;
  258. CmdFrm->opcode = DSD;
  259. CmdFrm->operand[0] = 0; /* source plug */
  260. CmdFrm->operand[1] = 0xd2; /* subfunction replace */
  261. CmdFrm->operand[2] = 0x20; /* system id = DVB */
  262. CmdFrm->operand[3] = 0x00; /* antenna number */
  263. /* system_specific_multiplex selection_length */
  264. CmdFrm->operand[4] = 0x0c;
  265. CmdFrm->operand[5] = flags.Valid_Word.ByteHi; /* valid_flags [0] */
  266. CmdFrm->operand[6] = flags.Valid_Word.ByteLo; /* valid_flags [1] */
  267. CmdFrm->operand[7] = 0x0;
  268. CmdFrm->operand[8] = (params->frequency / 10) >> 24;
  269. CmdFrm->operand[9] = ((params->frequency / 10) >> 16) & 0xff;
  270. CmdFrm->operand[10] = ((params->frequency / 10) >> 8) & 0xff;
  271. CmdFrm->operand[11] = (params->frequency / 10) & 0xff;
  272. switch (params->u.ofdm.bandwidth) {
  273. case BANDWIDTH_7_MHZ:
  274. CmdFrm->operand[12] = 0x20; break;
  275. case BANDWIDTH_8_MHZ:
  276. case BANDWIDTH_6_MHZ: /* not defined by AVC spec */
  277. case BANDWIDTH_AUTO:
  278. default:
  279. CmdFrm->operand[12] = 0x00;
  280. }
  281. switch (params->u.ofdm.constellation) {
  282. case QAM_16:
  283. CmdFrm->operand[13] = 1 << 6; break;
  284. case QAM_64:
  285. CmdFrm->operand[13] = 2 << 6; break;
  286. case QPSK:
  287. default:
  288. CmdFrm->operand[13] = 0x00;
  289. }
  290. switch (params->u.ofdm.hierarchy_information) {
  291. case HIERARCHY_1:
  292. CmdFrm->operand[13] |= 1 << 3; break;
  293. case HIERARCHY_2:
  294. CmdFrm->operand[13] |= 2 << 3; break;
  295. case HIERARCHY_4:
  296. CmdFrm->operand[13] |= 3 << 3; break;
  297. case HIERARCHY_AUTO:
  298. case HIERARCHY_NONE:
  299. default:
  300. break;
  301. }
  302. switch (params->u.ofdm.code_rate_HP) {
  303. case FEC_2_3:
  304. CmdFrm->operand[13] |= 1; break;
  305. case FEC_3_4:
  306. CmdFrm->operand[13] |= 2; break;
  307. case FEC_5_6:
  308. CmdFrm->operand[13] |= 3; break;
  309. case FEC_7_8:
  310. CmdFrm->operand[13] |= 4; break;
  311. case FEC_1_2:
  312. default:
  313. break;
  314. }
  315. switch (params->u.ofdm.code_rate_LP) {
  316. case FEC_2_3:
  317. CmdFrm->operand[14] = 1 << 5; break;
  318. case FEC_3_4:
  319. CmdFrm->operand[14] = 2 << 5; break;
  320. case FEC_5_6:
  321. CmdFrm->operand[14] = 3 << 5; break;
  322. case FEC_7_8:
  323. CmdFrm->operand[14] = 4 << 5; break;
  324. case FEC_1_2:
  325. default:
  326. CmdFrm->operand[14] = 0x00; break;
  327. }
  328. switch (params->u.ofdm.guard_interval) {
  329. case GUARD_INTERVAL_1_16:
  330. CmdFrm->operand[14] |= 1 << 3; break;
  331. case GUARD_INTERVAL_1_8:
  332. CmdFrm->operand[14] |= 2 << 3; break;
  333. case GUARD_INTERVAL_1_4:
  334. CmdFrm->operand[14] |= 3 << 3; break;
  335. case GUARD_INTERVAL_1_32:
  336. case GUARD_INTERVAL_AUTO:
  337. default:
  338. break;
  339. }
  340. switch (params->u.ofdm.transmission_mode) {
  341. case TRANSMISSION_MODE_8K:
  342. CmdFrm->operand[14] |= 1 << 1; break;
  343. case TRANSMISSION_MODE_2K:
  344. case TRANSMISSION_MODE_AUTO:
  345. default:
  346. break;
  347. }
  348. CmdFrm->operand[15] = 0x00; /* network_ID[0] */
  349. CmdFrm->operand[16] = 0x00; /* network_ID[1] */
  350. /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */
  351. CmdFrm->operand[17] = 0x00;
  352. CmdFrm->length = 24;
  353. }
  354. int avc_tuner_dsd(struct firesat *firesat,
  355. struct dvb_frontend_parameters *params)
  356. {
  357. AVCCmdFrm CmdFrm;
  358. AVCRspFrm RspFrm;
  359. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  360. CmdFrm.cts = AVC;
  361. CmdFrm.ctype = CONTROL;
  362. CmdFrm.sutyp = 0x5;
  363. CmdFrm.suid = firesat->subunit;
  364. switch (firesat->type) {
  365. case FireSAT_DVB_S:
  366. case FireSAT_DVB_S2:
  367. avc_tuner_tuneqpsk(firesat, params, &CmdFrm); break;
  368. case FireSAT_DVB_C:
  369. avc_tuner_dsd_dvb_c(params, &CmdFrm); break;
  370. case FireSAT_DVB_T:
  371. avc_tuner_dsd_dvb_t(params, &CmdFrm); break;
  372. default:
  373. BUG();
  374. }
  375. if (avc_write(firesat, &CmdFrm, &RspFrm) < 0)
  376. return -EIO;
  377. msleep(500);
  378. #if 0
  379. /* FIXME: */
  380. /* u8 *status was an out-parameter of avc_tuner_dsd, unused by caller */
  381. if(status)
  382. *status=RspFrm.operand[2];
  383. #endif
  384. return 0;
  385. }
  386. int avc_tuner_set_pids(struct firesat *firesat, unsigned char pidc, u16 pid[])
  387. {
  388. AVCCmdFrm CmdFrm;
  389. AVCRspFrm RspFrm;
  390. int pos, k;
  391. if (pidc > 16 && pidc != 0xff)
  392. return -EINVAL;
  393. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  394. CmdFrm.cts = AVC;
  395. CmdFrm.ctype = CONTROL;
  396. CmdFrm.sutyp = 0x5;
  397. CmdFrm.suid = firesat->subunit;
  398. CmdFrm.opcode = DSD;
  399. CmdFrm.operand[0] = 0; // source plug
  400. CmdFrm.operand[1] = 0xD2; // subfunction replace
  401. CmdFrm.operand[2] = 0x20; // system id = DVB
  402. CmdFrm.operand[3] = 0x00; // antenna number
  403. CmdFrm.operand[4] = 0x00; // system_specific_multiplex selection_length
  404. CmdFrm.operand[5] = pidc; // Nr_of_dsd_sel_specs
  405. pos = 6;
  406. if (pidc != 0xff)
  407. for (k = 0; k < pidc; k++) {
  408. CmdFrm.operand[pos++] = 0x13; // flowfunction relay
  409. CmdFrm.operand[pos++] = 0x80; // dsd_sel_spec_valid_flags -> PID
  410. CmdFrm.operand[pos++] = (pid[k] >> 8) & 0x1F;
  411. CmdFrm.operand[pos++] = pid[k] & 0xFF;
  412. CmdFrm.operand[pos++] = 0x00; // tableID
  413. CmdFrm.operand[pos++] = 0x00; // filter_length
  414. }
  415. CmdFrm.length = ALIGN(3 + pos, 4);
  416. if (avc_write(firesat, &CmdFrm, &RspFrm) < 0)
  417. return -EIO;
  418. msleep(50);
  419. return 0;
  420. }
  421. int avc_tuner_get_ts(struct firesat *firesat)
  422. {
  423. AVCCmdFrm CmdFrm;
  424. AVCRspFrm RspFrm;
  425. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  426. CmdFrm.cts = AVC;
  427. CmdFrm.ctype = CONTROL;
  428. CmdFrm.sutyp = 0x5;
  429. CmdFrm.suid = firesat->subunit;
  430. CmdFrm.opcode = DSIT;
  431. CmdFrm.operand[0] = 0; // source plug
  432. CmdFrm.operand[1] = 0xD2; // subfunction replace
  433. CmdFrm.operand[2] = 0xFF; //status
  434. CmdFrm.operand[3] = 0x20; // system id = DVB
  435. CmdFrm.operand[4] = 0x00; // antenna number
  436. CmdFrm.operand[5] = 0x0; // system_specific_search_flags
  437. CmdFrm.operand[6] = (firesat->type == FireSAT_DVB_T)?0x0c:0x11; // system_specific_multiplex selection_length
  438. CmdFrm.operand[7] = 0x00; // valid_flags [0]
  439. CmdFrm.operand[8] = 0x00; // valid_flags [1]
  440. CmdFrm.operand[7 + (firesat->type == FireSAT_DVB_T)?0x0c:0x11] = 0x00; // nr_of_dsit_sel_specs (always 0)
  441. CmdFrm.length = (firesat->type == FireSAT_DVB_T)?24:28;
  442. if (avc_write(firesat, &CmdFrm, &RspFrm) < 0)
  443. return -EIO;
  444. msleep(250);
  445. return 0;
  446. }
  447. int avc_identify_subunit(struct firesat *firesat)
  448. {
  449. AVCCmdFrm CmdFrm;
  450. AVCRspFrm RspFrm;
  451. memset(&CmdFrm,0,sizeof(AVCCmdFrm));
  452. CmdFrm.cts = AVC;
  453. CmdFrm.ctype = CONTROL;
  454. CmdFrm.sutyp = 0x5; // tuner
  455. CmdFrm.suid = firesat->subunit;
  456. CmdFrm.opcode = READ_DESCRIPTOR;
  457. CmdFrm.operand[0]=DESCRIPTOR_SUBUNIT_IDENTIFIER;
  458. CmdFrm.operand[1]=0xff;
  459. CmdFrm.operand[2]=0x00;
  460. CmdFrm.operand[3]=0x00; // length highbyte
  461. CmdFrm.operand[4]=0x08; // length lowbyte
  462. CmdFrm.operand[5]=0x00; // offset highbyte
  463. CmdFrm.operand[6]=0x0d; // offset lowbyte
  464. CmdFrm.length=12;
  465. if (avc_write(firesat, &CmdFrm, &RspFrm) < 0)
  466. return -EIO;
  467. if ((RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) ||
  468. (RspFrm.operand[3] << 8) + RspFrm.operand[4] != 8) {
  469. dev_err(&firesat->ud->device,
  470. "cannot read subunit identifier\n");
  471. return -EINVAL;
  472. }
  473. return 0;
  474. }
  475. int avc_tuner_status(struct firesat *firesat,
  476. ANTENNA_INPUT_INFO *antenna_input_info)
  477. {
  478. AVCCmdFrm CmdFrm;
  479. AVCRspFrm RspFrm;
  480. int length;
  481. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  482. CmdFrm.cts=AVC;
  483. CmdFrm.ctype=CONTROL;
  484. CmdFrm.sutyp=0x05; // tuner
  485. CmdFrm.suid=firesat->subunit;
  486. CmdFrm.opcode=READ_DESCRIPTOR;
  487. CmdFrm.operand[0]=DESCRIPTOR_TUNER_STATUS;
  488. CmdFrm.operand[1]=0xff; //read_result_status
  489. CmdFrm.operand[2]=0x00; // reserver
  490. CmdFrm.operand[3]=0;//sizeof(ANTENNA_INPUT_INFO) >> 8;
  491. CmdFrm.operand[4]=0;//sizeof(ANTENNA_INPUT_INFO) & 0xFF;
  492. CmdFrm.operand[5]=0x00;
  493. CmdFrm.operand[6]=0x00;
  494. CmdFrm.length=12;
  495. if (avc_write(firesat, &CmdFrm, &RspFrm) < 0)
  496. return -EIO;
  497. if (RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) {
  498. dev_err(&firesat->ud->device, "cannot read tuner status\n");
  499. return -EINVAL;
  500. }
  501. length = RspFrm.operand[9];
  502. if (RspFrm.operand[1] != 0x10 || length != sizeof(ANTENNA_INPUT_INFO)) {
  503. dev_err(&firesat->ud->device, "got invalid tuner status\n");
  504. return -EINVAL;
  505. }
  506. memcpy(antenna_input_info, &RspFrm.operand[10], length);
  507. return 0;
  508. }
  509. int avc_lnb_control(struct firesat *firesat, char voltage, char burst,
  510. char conttone, char nrdiseq,
  511. struct dvb_diseqc_master_cmd *diseqcmd)
  512. {
  513. AVCCmdFrm CmdFrm;
  514. AVCRspFrm RspFrm;
  515. int i, j, k;
  516. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  517. CmdFrm.cts=AVC;
  518. CmdFrm.ctype=CONTROL;
  519. CmdFrm.sutyp=0x05;
  520. CmdFrm.suid=firesat->subunit;
  521. CmdFrm.opcode=VENDOR;
  522. CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
  523. CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
  524. CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
  525. CmdFrm.operand[3]=SFE_VENDOR_OPCODE_LNB_CONTROL;
  526. CmdFrm.operand[4]=voltage;
  527. CmdFrm.operand[5]=nrdiseq;
  528. i=6;
  529. for (j = 0; j < nrdiseq; j++) {
  530. CmdFrm.operand[i++] = diseqcmd[j].msg_len;
  531. for (k = 0; k < diseqcmd[j].msg_len; k++)
  532. CmdFrm.operand[i++] = diseqcmd[j].msg[k];
  533. }
  534. CmdFrm.operand[i++]=burst;
  535. CmdFrm.operand[i++]=conttone;
  536. CmdFrm.length = ALIGN(3 + i, 4);
  537. if (avc_write(firesat, &CmdFrm, &RspFrm) < 0)
  538. return -EIO;
  539. if (RspFrm.resp != ACCEPTED) {
  540. dev_err(&firesat->ud->device, "LNB control failed\n");
  541. return -EINVAL;
  542. }
  543. return 0;
  544. }
  545. int avc_register_remote_control(struct firesat *firesat)
  546. {
  547. AVCCmdFrm CmdFrm;
  548. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  549. CmdFrm.cts = AVC;
  550. CmdFrm.ctype = NOTIFY;
  551. CmdFrm.sutyp = 0x1f;
  552. CmdFrm.suid = 0x7;
  553. CmdFrm.opcode = VENDOR;
  554. CmdFrm.operand[0] = SFE_VENDOR_DE_COMPANYID_0;
  555. CmdFrm.operand[1] = SFE_VENDOR_DE_COMPANYID_1;
  556. CmdFrm.operand[2] = SFE_VENDOR_DE_COMPANYID_2;
  557. CmdFrm.operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
  558. CmdFrm.length = 8;
  559. return avc_write(firesat, &CmdFrm, NULL);
  560. }
  561. void avc_remote_ctrl_work(struct work_struct *work)
  562. {
  563. struct firesat *firesat =
  564. container_of(work, struct firesat, remote_ctrl_work);
  565. /* Should it be rescheduled in failure cases? */
  566. avc_register_remote_control(firesat);
  567. }
  568. #if 0 /* FIXME: unused */
  569. int avc_tuner_host2ca(struct firesat *firesat)
  570. {
  571. AVCCmdFrm CmdFrm;
  572. AVCRspFrm RspFrm;
  573. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  574. CmdFrm.cts = AVC;
  575. CmdFrm.ctype = CONTROL;
  576. CmdFrm.sutyp = 0x5;
  577. CmdFrm.suid = firesat->subunit;
  578. CmdFrm.opcode = VENDOR;
  579. CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
  580. CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
  581. CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
  582. CmdFrm.operand[3]=SFE_VENDOR_OPCODE_HOST2CA;
  583. CmdFrm.operand[4] = 0; // slot
  584. CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; // ca tag
  585. CmdFrm.operand[6] = 0; // more/last
  586. CmdFrm.operand[7] = 0; // length
  587. CmdFrm.length = 12;
  588. if (avc_write(firesat, &CmdFrm, &RspFrm) < 0)
  589. return -EIO;
  590. return 0;
  591. }
  592. #endif
  593. static int get_ca_object_pos(AVCRspFrm *RspFrm)
  594. {
  595. int length = 1;
  596. /* Check length of length field */
  597. if (RspFrm->operand[7] & 0x80)
  598. length = (RspFrm->operand[7] & 0x7f) + 1;
  599. return length + 7;
  600. }
  601. static int get_ca_object_length(AVCRspFrm *RspFrm)
  602. {
  603. #if 0 /* FIXME: unused */
  604. int size = 0;
  605. int i;
  606. if (RspFrm->operand[7] & 0x80)
  607. for (i = 0; i < (RspFrm->operand[7] & 0x7f); i++) {
  608. size <<= 8;
  609. size += RspFrm->operand[8 + i];
  610. }
  611. #endif
  612. return RspFrm->operand[7];
  613. }
  614. int avc_ca_app_info(struct firesat *firesat, char *app_info, unsigned int *len)
  615. {
  616. AVCCmdFrm CmdFrm;
  617. AVCRspFrm RspFrm;
  618. int pos;
  619. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  620. CmdFrm.cts = AVC;
  621. CmdFrm.ctype = STATUS;
  622. CmdFrm.sutyp = 0x5;
  623. CmdFrm.suid = firesat->subunit;
  624. CmdFrm.opcode = VENDOR;
  625. CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
  626. CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
  627. CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
  628. CmdFrm.operand[3]=SFE_VENDOR_OPCODE_CA2HOST;
  629. CmdFrm.operand[4] = 0; // slot
  630. CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; // ca tag
  631. CmdFrm.length = 12;
  632. if (avc_write(firesat, &CmdFrm, &RspFrm) < 0)
  633. return -EIO;
  634. /* FIXME: check response code and validate response data */
  635. pos = get_ca_object_pos(&RspFrm);
  636. app_info[0] = (TAG_APP_INFO >> 16) & 0xFF;
  637. app_info[1] = (TAG_APP_INFO >> 8) & 0xFF;
  638. app_info[2] = (TAG_APP_INFO >> 0) & 0xFF;
  639. app_info[3] = 6 + RspFrm.operand[pos + 4];
  640. app_info[4] = 0x01;
  641. memcpy(&app_info[5], &RspFrm.operand[pos], 5 + RspFrm.operand[pos + 4]);
  642. *len = app_info[3] + 4;
  643. return 0;
  644. }
  645. int avc_ca_info(struct firesat *firesat, char *app_info, unsigned int *len)
  646. {
  647. AVCCmdFrm CmdFrm;
  648. AVCRspFrm RspFrm;
  649. int pos;
  650. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  651. CmdFrm.cts = AVC;
  652. CmdFrm.ctype = STATUS;
  653. CmdFrm.sutyp = 0x5;
  654. CmdFrm.suid = firesat->subunit;
  655. CmdFrm.opcode = VENDOR;
  656. CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
  657. CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
  658. CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
  659. CmdFrm.operand[3]=SFE_VENDOR_OPCODE_CA2HOST;
  660. CmdFrm.operand[4] = 0; // slot
  661. CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; // ca tag
  662. CmdFrm.length = 12;
  663. if (avc_write(firesat, &CmdFrm, &RspFrm) < 0)
  664. return -EIO;
  665. pos = get_ca_object_pos(&RspFrm);
  666. app_info[0] = (TAG_CA_INFO >> 16) & 0xFF;
  667. app_info[1] = (TAG_CA_INFO >> 8) & 0xFF;
  668. app_info[2] = (TAG_CA_INFO >> 0) & 0xFF;
  669. app_info[3] = 2;
  670. app_info[4] = RspFrm.operand[pos + 0];
  671. app_info[5] = RspFrm.operand[pos + 1];
  672. *len = app_info[3] + 4;
  673. return 0;
  674. }
  675. int avc_ca_reset(struct firesat *firesat)
  676. {
  677. AVCCmdFrm CmdFrm;
  678. AVCRspFrm RspFrm;
  679. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  680. CmdFrm.cts = AVC;
  681. CmdFrm.ctype = CONTROL;
  682. CmdFrm.sutyp = 0x5;
  683. CmdFrm.suid = firesat->subunit;
  684. CmdFrm.opcode = VENDOR;
  685. CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
  686. CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
  687. CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
  688. CmdFrm.operand[3]=SFE_VENDOR_OPCODE_HOST2CA;
  689. CmdFrm.operand[4] = 0; // slot
  690. CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_RESET; // ca tag
  691. CmdFrm.operand[6] = 0; // more/last
  692. CmdFrm.operand[7] = 1; // length
  693. CmdFrm.operand[8] = 0; // force hardware reset
  694. CmdFrm.length = 12;
  695. if (avc_write(firesat, &CmdFrm, &RspFrm) < 0)
  696. return -EIO;
  697. return 0;
  698. }
  699. int avc_ca_pmt(struct firesat *firesat, char *msg, int length)
  700. {
  701. AVCCmdFrm CmdFrm;
  702. AVCRspFrm RspFrm;
  703. int list_management;
  704. int program_info_length;
  705. int pmt_cmd_id;
  706. int read_pos;
  707. int write_pos;
  708. int es_info_length;
  709. int crc32_csum;
  710. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  711. CmdFrm.cts = AVC;
  712. CmdFrm.ctype = CONTROL;
  713. CmdFrm.sutyp = 0x5;
  714. CmdFrm.suid = firesat->subunit;
  715. CmdFrm.opcode = VENDOR;
  716. if (msg[0] != LIST_MANAGEMENT_ONLY) {
  717. dev_info(&firesat->ud->device,
  718. "forcing list_management to ONLY\n");
  719. msg[0] = LIST_MANAGEMENT_ONLY;
  720. }
  721. // We take the cmd_id from the programme level only!
  722. list_management = msg[0];
  723. program_info_length = ((msg[4] & 0x0F) << 8) + msg[5];
  724. if (program_info_length > 0)
  725. program_info_length--; // Remove pmt_cmd_id
  726. pmt_cmd_id = msg[6];
  727. CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
  728. CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
  729. CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
  730. CmdFrm.operand[3]=SFE_VENDOR_OPCODE_HOST2CA;
  731. CmdFrm.operand[4] = 0; // slot
  732. CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_PMT; // ca tag
  733. CmdFrm.operand[6] = 0; // more/last
  734. //CmdFrm.operand[7] = XXXprogram_info_length + 17; // length
  735. CmdFrm.operand[8] = list_management;
  736. CmdFrm.operand[9] = 0x01; // pmt_cmd=OK_descramble
  737. // TS program map table
  738. // Table id=2
  739. CmdFrm.operand[10] = 0x02;
  740. // Section syntax + length
  741. CmdFrm.operand[11] = 0x80;
  742. //CmdFrm.operand[12] = XXXprogram_info_length + 12;
  743. // Program number
  744. CmdFrm.operand[13] = msg[1];
  745. CmdFrm.operand[14] = msg[2];
  746. // Version number=0 + current/next=1
  747. CmdFrm.operand[15] = 0x01;
  748. // Section number=0
  749. CmdFrm.operand[16] = 0x00;
  750. // Last section number=0
  751. CmdFrm.operand[17] = 0x00;
  752. // PCR_PID=1FFF
  753. CmdFrm.operand[18] = 0x1F;
  754. CmdFrm.operand[19] = 0xFF;
  755. // Program info length
  756. CmdFrm.operand[20] = (program_info_length >> 8);
  757. CmdFrm.operand[21] = (program_info_length & 0xFF);
  758. // CA descriptors at programme level
  759. read_pos = 6;
  760. write_pos = 22;
  761. if (program_info_length > 0) {
  762. pmt_cmd_id = msg[read_pos++];
  763. if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
  764. dev_err(&firesat->ud->device,
  765. "invalid pmt_cmd_id %d\n", pmt_cmd_id);
  766. memcpy(&CmdFrm.operand[write_pos], &msg[read_pos],
  767. program_info_length);
  768. read_pos += program_info_length;
  769. write_pos += program_info_length;
  770. }
  771. while (read_pos < length) {
  772. CmdFrm.operand[write_pos++] = msg[read_pos++];
  773. CmdFrm.operand[write_pos++] = msg[read_pos++];
  774. CmdFrm.operand[write_pos++] = msg[read_pos++];
  775. es_info_length =
  776. ((msg[read_pos] & 0x0F) << 8) + msg[read_pos + 1];
  777. read_pos += 2;
  778. if (es_info_length > 0)
  779. es_info_length--; // Remove pmt_cmd_id
  780. CmdFrm.operand[write_pos++] = es_info_length >> 8;
  781. CmdFrm.operand[write_pos++] = es_info_length & 0xFF;
  782. if (es_info_length > 0) {
  783. pmt_cmd_id = msg[read_pos++];
  784. if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
  785. dev_err(&firesat->ud->device,
  786. "invalid pmt_cmd_id %d "
  787. "at stream level\n", pmt_cmd_id);
  788. memcpy(&CmdFrm.operand[write_pos], &msg[read_pos],
  789. es_info_length);
  790. read_pos += es_info_length;
  791. write_pos += es_info_length;
  792. }
  793. }
  794. // CRC
  795. CmdFrm.operand[write_pos++] = 0x00;
  796. CmdFrm.operand[write_pos++] = 0x00;
  797. CmdFrm.operand[write_pos++] = 0x00;
  798. CmdFrm.operand[write_pos++] = 0x00;
  799. CmdFrm.operand[7] = write_pos - 8;
  800. CmdFrm.operand[12] = write_pos - 13;
  801. crc32_csum = crc32_be(0, &CmdFrm.operand[10],
  802. CmdFrm.operand[12] - 1);
  803. CmdFrm.operand[write_pos - 4] = (crc32_csum >> 24) & 0xFF;
  804. CmdFrm.operand[write_pos - 3] = (crc32_csum >> 16) & 0xFF;
  805. CmdFrm.operand[write_pos - 2] = (crc32_csum >> 8) & 0xFF;
  806. CmdFrm.operand[write_pos - 1] = (crc32_csum >> 0) & 0xFF;
  807. CmdFrm.length = ALIGN(3 + write_pos, 4);
  808. if (avc_write(firesat, &CmdFrm, &RspFrm) < 0)
  809. return -EIO;
  810. if (RspFrm.resp != ACCEPTED) {
  811. dev_err(&firesat->ud->device,
  812. "CA PMT failed with response 0x%x\n", RspFrm.resp);
  813. return -EFAULT;
  814. }
  815. return 0;
  816. }
  817. int avc_ca_get_time_date(struct firesat *firesat, int *interval)
  818. {
  819. AVCCmdFrm CmdFrm;
  820. AVCRspFrm RspFrm;
  821. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  822. CmdFrm.cts = AVC;
  823. CmdFrm.ctype = STATUS;
  824. CmdFrm.sutyp = 0x5;
  825. CmdFrm.suid = firesat->subunit;
  826. CmdFrm.opcode = VENDOR;
  827. CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
  828. CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
  829. CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
  830. CmdFrm.operand[3]=SFE_VENDOR_OPCODE_CA2HOST;
  831. CmdFrm.operand[4] = 0; // slot
  832. CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; // ca tag
  833. CmdFrm.operand[6] = 0; // more/last
  834. CmdFrm.operand[7] = 0; // length
  835. CmdFrm.length = 12;
  836. if (avc_write(firesat, &CmdFrm, &RspFrm) < 0)
  837. return -EIO;
  838. /* FIXME: check response code and validate response data */
  839. *interval = RspFrm.operand[get_ca_object_pos(&RspFrm)];
  840. return 0;
  841. }
  842. int avc_ca_enter_menu(struct firesat *firesat)
  843. {
  844. AVCCmdFrm CmdFrm;
  845. AVCRspFrm RspFrm;
  846. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  847. CmdFrm.cts = AVC;
  848. CmdFrm.ctype = STATUS;
  849. CmdFrm.sutyp = 0x5;
  850. CmdFrm.suid = firesat->subunit;
  851. CmdFrm.opcode = VENDOR;
  852. CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
  853. CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
  854. CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
  855. CmdFrm.operand[3]=SFE_VENDOR_OPCODE_HOST2CA;
  856. CmdFrm.operand[4] = 0; // slot
  857. CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU;
  858. CmdFrm.operand[6] = 0; // more/last
  859. CmdFrm.operand[7] = 0; // length
  860. CmdFrm.length = 12;
  861. if (avc_write(firesat, &CmdFrm, &RspFrm) < 0)
  862. return -EIO;
  863. return 0;
  864. }
  865. int avc_ca_get_mmi(struct firesat *firesat, char *mmi_object, unsigned int *len)
  866. {
  867. AVCCmdFrm CmdFrm;
  868. AVCRspFrm RspFrm;
  869. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  870. CmdFrm.cts = AVC;
  871. CmdFrm.ctype = STATUS;
  872. CmdFrm.sutyp = 0x5;
  873. CmdFrm.suid = firesat->subunit;
  874. CmdFrm.opcode = VENDOR;
  875. CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
  876. CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
  877. CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
  878. CmdFrm.operand[3]=SFE_VENDOR_OPCODE_CA2HOST;
  879. CmdFrm.operand[4] = 0; // slot
  880. CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_MMI;
  881. CmdFrm.operand[6] = 0; // more/last
  882. CmdFrm.operand[7] = 0; // length
  883. CmdFrm.length = 12;
  884. if (avc_write(firesat, &CmdFrm, &RspFrm) < 0)
  885. return -EIO;
  886. /* FIXME: check response code and validate response data */
  887. *len = get_ca_object_length(&RspFrm);
  888. memcpy(mmi_object, &RspFrm.operand[get_ca_object_pos(&RspFrm)], *len);
  889. return 0;
  890. }