avc_api.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293
  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/crc32.h>
  14. #include <linux/delay.h>
  15. #include <linux/kernel.h>
  16. #include <linux/moduleparam.h>
  17. #include <linux/mutex.h>
  18. #include <linux/wait.h>
  19. #include <linux/workqueue.h>
  20. #include <asm/atomic.h>
  21. #include <ieee1394_transactions.h>
  22. #include <nodemgr.h>
  23. #include "avc_api.h"
  24. #include "firesat.h"
  25. #include "firesat-rc.h"
  26. #define RESPONSE_REGISTER 0xFFFFF0000D00ULL
  27. #define COMMAND_REGISTER 0xFFFFF0000B00ULL
  28. #define PCR_BASE_ADDRESS 0xFFFFF0000900ULL
  29. static unsigned int avc_comm_debug = 0;
  30. module_param(avc_comm_debug, int, 0644);
  31. MODULE_PARM_DESC(avc_comm_debug, "debug logging level [0..2] of AV/C communication, default is 0 (no)");
  32. /* Frees an allocated packet */
  33. static void avc_free_packet(struct hpsb_packet *packet)
  34. {
  35. hpsb_free_tlabel(packet);
  36. hpsb_free_packet(packet);
  37. }
  38. static const char* get_ctype_string(__u8 ctype)
  39. {
  40. switch(ctype)
  41. {
  42. case 0:
  43. return "CONTROL";
  44. case 1:
  45. return "STATUS";
  46. case 2:
  47. return "SPECIFIC_INQUIRY";
  48. case 3:
  49. return "NOTIFY";
  50. case 4:
  51. return "GENERAL_INQUIRY";
  52. }
  53. return "UNKNOWN";
  54. }
  55. static const char* get_resp_string(__u8 ctype)
  56. {
  57. switch(ctype)
  58. {
  59. case 8:
  60. return "NOT_IMPLEMENTED";
  61. case 9:
  62. return "ACCEPTED";
  63. case 10:
  64. return "REJECTED";
  65. case 11:
  66. return "IN_TRANSITION";
  67. case 12:
  68. return "IMPLEMENTED_STABLE";
  69. case 13:
  70. return "CHANGED";
  71. case 15:
  72. return "INTERIM";
  73. }
  74. return "UNKNOWN";
  75. }
  76. static const char* get_subunit_address(__u8 subunit_id, __u8 subunit_type)
  77. {
  78. if (subunit_id == 7 && subunit_type == 0x1F)
  79. return "Unit";
  80. if (subunit_id == 0 && subunit_type == 0x05)
  81. return "Tuner(0)";
  82. return "Unsupported";
  83. }
  84. static const char* get_opcode_string(__u8 opcode)
  85. {
  86. switch(opcode)
  87. {
  88. case 0x02:
  89. return "PlugInfo";
  90. case 0x08:
  91. return "OpenDescriptor";
  92. case 0x09:
  93. return "ReadDescriptor";
  94. case 0x18:
  95. return "OutputPlugSignalFormat";
  96. case 0x31:
  97. return "SubunitInfo";
  98. case 0x30:
  99. return "UnitInfo";
  100. case 0xB2:
  101. return "Power";
  102. case 0xC8:
  103. return "DirectSelectInformationType";
  104. case 0xCB:
  105. return "DirectSelectData";
  106. case 0x00:
  107. return "Vendor";
  108. }
  109. return "Unknown";
  110. }
  111. static void log_command_frame(const AVCCmdFrm *CmdFrm)
  112. {
  113. int k;
  114. printk(KERN_INFO "AV/C Command Frame:\n");
  115. printk(KERN_INFO "CommandType=%s, Address=%s(0x%02X,0x%02X), "
  116. "opcode=%s(0x%02X), length=%d\n",
  117. get_ctype_string(CmdFrm->ctype),
  118. get_subunit_address(CmdFrm->suid, CmdFrm->sutyp),
  119. CmdFrm->suid, CmdFrm->sutyp, get_opcode_string(CmdFrm->opcode),
  120. CmdFrm->opcode, CmdFrm->length);
  121. if (avc_comm_debug > 1) {
  122. for(k = 0; k < CmdFrm->length - 3; k++) {
  123. if (k % 5 != 0)
  124. printk(", ");
  125. else if (k != 0)
  126. printk("\n");
  127. printk(KERN_INFO "operand[%d] = %02X", k,
  128. CmdFrm->operand[k]);
  129. }
  130. printk(KERN_INFO "\n");
  131. }
  132. }
  133. static void log_response_frame(const AVCRspFrm *RspFrm)
  134. {
  135. int k;
  136. printk(KERN_INFO "AV/C Response Frame:\n");
  137. printk(KERN_INFO "Response=%s, Address=%s(0x%02X,0x%02X), "
  138. "opcode=%s(0x%02X), length=%d\n", get_resp_string(RspFrm->resp),
  139. get_subunit_address(RspFrm->suid, RspFrm->sutyp),
  140. RspFrm->suid, RspFrm->sutyp, get_opcode_string(RspFrm->opcode),
  141. RspFrm->opcode, RspFrm->length);
  142. if (avc_comm_debug > 1) {
  143. for(k = 0; k < RspFrm->length - 3; k++) {
  144. if (k % 5 != 0)
  145. printk(KERN_INFO ", ");
  146. else if (k != 0)
  147. printk(KERN_INFO "\n");
  148. printk(KERN_INFO "operand[%d] = %02X", k,
  149. RspFrm->operand[k]);
  150. }
  151. printk(KERN_INFO "\n");
  152. }
  153. }
  154. static int __AVCWrite(struct firesat *firesat, const AVCCmdFrm *CmdFrm,
  155. AVCRspFrm *RspFrm) {
  156. struct hpsb_packet *packet;
  157. struct node_entry *ne;
  158. int num_tries = 0;
  159. int packet_ok = 0;
  160. ne = firesat->nodeentry;
  161. if(!ne) {
  162. printk(KERN_ERR "%s: lost node!\n",__func__);
  163. return -EIO;
  164. }
  165. /* need all input data */
  166. if(!firesat || !ne || !CmdFrm) {
  167. printk(KERN_ERR "%s: missing input data!\n",__func__);
  168. return -EINVAL;
  169. }
  170. if (avc_comm_debug > 0) {
  171. log_command_frame(CmdFrm);
  172. }
  173. if(RspFrm)
  174. atomic_set(&firesat->avc_reply_received, 0);
  175. while (packet_ok == 0 && num_tries < 6) {
  176. num_tries++;
  177. packet_ok = 1;
  178. packet = hpsb_make_writepacket(ne->host, ne->nodeid,
  179. COMMAND_REGISTER,
  180. (quadlet_t*)CmdFrm,
  181. CmdFrm->length);
  182. hpsb_set_packet_complete_task(packet,
  183. (void (*)(void*))avc_free_packet,
  184. packet);
  185. hpsb_node_fill_packet(ne, packet);
  186. if (hpsb_send_packet(packet) < 0) {
  187. avc_free_packet(packet);
  188. atomic_set(&firesat->avc_reply_received, 1);
  189. printk(KERN_ERR "%s: send failed!\n",__func__);
  190. return -EIO;
  191. }
  192. if(RspFrm) {
  193. // AV/C specs say that answers should be send within
  194. // 150 ms so let's time out after 200 ms
  195. if (wait_event_timeout(firesat->avc_wait,
  196. atomic_read(&firesat->avc_reply_received) == 1,
  197. HZ / 5) == 0) {
  198. packet_ok = 0;
  199. }
  200. else {
  201. memcpy(RspFrm, firesat->respfrm,
  202. firesat->resp_length);
  203. RspFrm->length = firesat->resp_length;
  204. if (avc_comm_debug > 0) {
  205. log_response_frame(RspFrm);
  206. }
  207. }
  208. }
  209. }
  210. if (packet_ok == 0) {
  211. printk(KERN_ERR "%s: AV/C response timed out 6 times.\n",
  212. __func__);
  213. return -ETIMEDOUT;
  214. }
  215. return 0;
  216. }
  217. int AVCWrite(struct firesat*firesat, const AVCCmdFrm *CmdFrm, AVCRspFrm *RspFrm)
  218. {
  219. int ret;
  220. if (mutex_lock_interruptible(&firesat->avc_mutex))
  221. return -EINTR;
  222. ret = __AVCWrite(firesat, CmdFrm, RspFrm);
  223. mutex_unlock(&firesat->avc_mutex);
  224. return ret;
  225. }
  226. int AVCRecv(struct firesat *firesat, u8 *data, size_t length)
  227. {
  228. AVCRspFrm *RspFrm = (AVCRspFrm *)data;
  229. if (length >= 8 &&
  230. RspFrm->operand[0] == SFE_VENDOR_DE_COMPANYID_0 &&
  231. RspFrm->operand[1] == SFE_VENDOR_DE_COMPANYID_1 &&
  232. RspFrm->operand[2] == SFE_VENDOR_DE_COMPANYID_2 &&
  233. RspFrm->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL) {
  234. if (RspFrm->resp == CHANGED) {
  235. firesat_handle_rc(RspFrm->operand[4] << 8 |
  236. RspFrm->operand[5]);
  237. schedule_work(&firesat->remote_ctrl_work);
  238. } else if (RspFrm->resp != INTERIM) {
  239. printk(KERN_INFO "firedtv: remote control result = "
  240. "%d\n", RspFrm->resp);
  241. }
  242. return 0;
  243. }
  244. if(atomic_read(&firesat->avc_reply_received) == 1) {
  245. printk(KERN_ERR "%s: received out-of-order AVC response, "
  246. "ignored\n",__func__);
  247. return -EINVAL;
  248. }
  249. // AVCRspFrm *resp=(AVCRspFrm *)data;
  250. // int k;
  251. // printk(KERN_INFO "resp=0x%x\n",resp->resp);
  252. // printk(KERN_INFO "cts=0x%x\n",resp->cts);
  253. // printk(KERN_INFO "suid=0x%x\n",resp->suid);
  254. // printk(KERN_INFO "sutyp=0x%x\n",resp->sutyp);
  255. // printk(KERN_INFO "opcode=0x%x\n",resp->opcode);
  256. // printk(KERN_INFO "length=%d\n",resp->length);
  257. // for(k=0;k<2;k++)
  258. // printk(KERN_INFO "operand[%d]=%02x\n",k,resp->operand[k]);
  259. memcpy(firesat->respfrm,data,length);
  260. firesat->resp_length=length;
  261. atomic_set(&firesat->avc_reply_received, 1);
  262. wake_up(&firesat->avc_wait);
  263. return 0;
  264. }
  265. // tuning command for setting the relative LNB frequency (not supported by the AVC standard)
  266. static void AVCTuner_tuneQPSK(struct firesat *firesat, struct dvb_frontend_parameters *params, AVCCmdFrm *CmdFrm) {
  267. memset(CmdFrm, 0, sizeof(AVCCmdFrm));
  268. CmdFrm->cts = AVC;
  269. CmdFrm->ctype = CONTROL;
  270. CmdFrm->sutyp = 0x5;
  271. CmdFrm->suid = firesat->subunit;
  272. CmdFrm->opcode = VENDOR;
  273. CmdFrm->operand[0]=SFE_VENDOR_DE_COMPANYID_0;
  274. CmdFrm->operand[1]=SFE_VENDOR_DE_COMPANYID_1;
  275. CmdFrm->operand[2]=SFE_VENDOR_DE_COMPANYID_2;
  276. CmdFrm->operand[3]=SFE_VENDOR_OPCODE_TUNE_QPSK;
  277. printk(KERN_INFO "%s: tuning to frequency %u\n",__func__,params->frequency);
  278. CmdFrm->operand[4] = (params->frequency >> 24) & 0xFF;
  279. CmdFrm->operand[5] = (params->frequency >> 16) & 0xFF;
  280. CmdFrm->operand[6] = (params->frequency >> 8) & 0xFF;
  281. CmdFrm->operand[7] = params->frequency & 0xFF;
  282. printk(KERN_INFO "%s: symbol rate = %uBd\n",__func__,params->u.qpsk.symbol_rate);
  283. CmdFrm->operand[8] = ((params->u.qpsk.symbol_rate/1000) >> 8) & 0xFF;
  284. CmdFrm->operand[9] = (params->u.qpsk.symbol_rate/1000) & 0xFF;
  285. switch(params->u.qpsk.fec_inner) {
  286. case FEC_1_2:
  287. CmdFrm->operand[10] = 0x1;
  288. break;
  289. case FEC_2_3:
  290. CmdFrm->operand[10] = 0x2;
  291. break;
  292. case FEC_3_4:
  293. CmdFrm->operand[10] = 0x3;
  294. break;
  295. case FEC_5_6:
  296. CmdFrm->operand[10] = 0x4;
  297. break;
  298. case FEC_7_8:
  299. CmdFrm->operand[10] = 0x5;
  300. break;
  301. case FEC_4_5:
  302. case FEC_8_9:
  303. case FEC_AUTO:
  304. default:
  305. CmdFrm->operand[10] = 0x0;
  306. }
  307. if(firesat->voltage == 0xff)
  308. CmdFrm->operand[11] = 0xff;
  309. else
  310. CmdFrm->operand[11] = (firesat->voltage==SEC_VOLTAGE_18)?0:1; // polarisation
  311. if(firesat->tone == 0xff)
  312. CmdFrm->operand[12] = 0xff;
  313. else
  314. CmdFrm->operand[12] = (firesat->tone==SEC_TONE_ON)?1:0; // band
  315. if (firesat->type == FireSAT_DVB_S2) {
  316. CmdFrm->operand[13] = 0x1;
  317. CmdFrm->operand[14] = 0xFF;
  318. CmdFrm->operand[15] = 0xFF;
  319. }
  320. CmdFrm->length = 16;
  321. }
  322. int AVCTuner_DSD(struct firesat *firesat, struct dvb_frontend_parameters *params, __u8 *status) {
  323. AVCCmdFrm CmdFrm;
  324. AVCRspFrm RspFrm;
  325. M_VALID_FLAGS flags;
  326. int k;
  327. // printk(KERN_INFO "%s\n", __func__);
  328. if (firesat->type == FireSAT_DVB_S || firesat->type == FireSAT_DVB_S2)
  329. AVCTuner_tuneQPSK(firesat, params, &CmdFrm);
  330. else {
  331. if(firesat->type == FireSAT_DVB_T) {
  332. flags.Bits_T.GuardInterval = (params->u.ofdm.guard_interval != GUARD_INTERVAL_AUTO);
  333. flags.Bits_T.CodeRateLPStream = (params->u.ofdm.code_rate_LP != FEC_AUTO);
  334. flags.Bits_T.CodeRateHPStream = (params->u.ofdm.code_rate_HP != FEC_AUTO);
  335. flags.Bits_T.HierarchyInfo = (params->u.ofdm.hierarchy_information != HIERARCHY_AUTO);
  336. flags.Bits_T.Constellation = (params->u.ofdm.constellation != QAM_AUTO);
  337. flags.Bits_T.Bandwidth = (params->u.ofdm.bandwidth != BANDWIDTH_AUTO);
  338. flags.Bits_T.CenterFrequency = 1;
  339. flags.Bits_T.reserved1 = 0;
  340. flags.Bits_T.reserved2 = 0;
  341. flags.Bits_T.OtherFrequencyFlag = 0;
  342. flags.Bits_T.TransmissionMode = (params->u.ofdm.transmission_mode != TRANSMISSION_MODE_AUTO);
  343. flags.Bits_T.NetworkId = 0;
  344. } else {
  345. flags.Bits.Modulation =
  346. (params->u.qam.modulation != QAM_AUTO);
  347. flags.Bits.FEC_inner =
  348. (params->u.qam.fec_inner != FEC_AUTO);
  349. flags.Bits.FEC_outer = 0;
  350. flags.Bits.Symbol_Rate = 1;
  351. flags.Bits.Frequency = 1;
  352. flags.Bits.Orbital_Pos = 0;
  353. flags.Bits.Polarisation = 0;
  354. flags.Bits.reserved_fields = 0;
  355. flags.Bits.reserved1 = 0;
  356. flags.Bits.Network_ID = 0;
  357. }
  358. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  359. CmdFrm.cts = AVC;
  360. CmdFrm.ctype = CONTROL;
  361. CmdFrm.sutyp = 0x5;
  362. CmdFrm.suid = firesat->subunit;
  363. CmdFrm.opcode = DSD;
  364. CmdFrm.operand[0] = 0; // source plug
  365. CmdFrm.operand[1] = 0xD2; // subfunction replace
  366. CmdFrm.operand[2] = 0x20; // system id = DVB
  367. CmdFrm.operand[3] = 0x00; // antenna number
  368. // system_specific_multiplex selection_length
  369. CmdFrm.operand[4] = (firesat->type == FireSAT_DVB_T)?0x0c:0x11;
  370. CmdFrm.operand[5] = flags.Valid_Word.ByteHi; // valid_flags [0]
  371. CmdFrm.operand[6] = flags.Valid_Word.ByteLo; // valid_flags [1]
  372. if(firesat->type == FireSAT_DVB_T) {
  373. CmdFrm.operand[7] = 0x0;
  374. CmdFrm.operand[8] = (params->frequency/10) >> 24;
  375. CmdFrm.operand[9] =
  376. ((params->frequency/10) >> 16) & 0xFF;
  377. CmdFrm.operand[10] =
  378. ((params->frequency/10) >> 8) & 0xFF;
  379. CmdFrm.operand[11] = (params->frequency/10) & 0xFF;
  380. switch(params->u.ofdm.bandwidth) {
  381. case BANDWIDTH_7_MHZ:
  382. CmdFrm.operand[12] = 0x20;
  383. break;
  384. case BANDWIDTH_8_MHZ:
  385. case BANDWIDTH_6_MHZ: // not defined by AVC spec
  386. case BANDWIDTH_AUTO:
  387. default:
  388. CmdFrm.operand[12] = 0x00;
  389. }
  390. switch(params->u.ofdm.constellation) {
  391. case QAM_16:
  392. CmdFrm.operand[13] = 1 << 6;
  393. break;
  394. case QAM_64:
  395. CmdFrm.operand[13] = 2 << 6;
  396. break;
  397. case QPSK:
  398. default:
  399. CmdFrm.operand[13] = 0x00;
  400. }
  401. switch(params->u.ofdm.hierarchy_information) {
  402. case HIERARCHY_1:
  403. CmdFrm.operand[13] |= 1 << 3;
  404. break;
  405. case HIERARCHY_2:
  406. CmdFrm.operand[13] |= 2 << 3;
  407. break;
  408. case HIERARCHY_4:
  409. CmdFrm.operand[13] |= 3 << 3;
  410. break;
  411. case HIERARCHY_AUTO:
  412. case HIERARCHY_NONE:
  413. default:
  414. break;
  415. }
  416. switch(params->u.ofdm.code_rate_HP) {
  417. case FEC_2_3:
  418. CmdFrm.operand[13] |= 1;
  419. break;
  420. case FEC_3_4:
  421. CmdFrm.operand[13] |= 2;
  422. break;
  423. case FEC_5_6:
  424. CmdFrm.operand[13] |= 3;
  425. break;
  426. case FEC_7_8:
  427. CmdFrm.operand[13] |= 4;
  428. break;
  429. case FEC_1_2:
  430. default:
  431. break;
  432. }
  433. switch(params->u.ofdm.code_rate_LP) {
  434. case FEC_2_3:
  435. CmdFrm.operand[14] = 1 << 5;
  436. break;
  437. case FEC_3_4:
  438. CmdFrm.operand[14] = 2 << 5;
  439. break;
  440. case FEC_5_6:
  441. CmdFrm.operand[14] = 3 << 5;
  442. break;
  443. case FEC_7_8:
  444. CmdFrm.operand[14] = 4 << 5;
  445. break;
  446. case FEC_1_2:
  447. default:
  448. CmdFrm.operand[14] = 0x00;
  449. break;
  450. }
  451. switch(params->u.ofdm.guard_interval) {
  452. case GUARD_INTERVAL_1_16:
  453. CmdFrm.operand[14] |= 1 << 3;
  454. break;
  455. case GUARD_INTERVAL_1_8:
  456. CmdFrm.operand[14] |= 2 << 3;
  457. break;
  458. case GUARD_INTERVAL_1_4:
  459. CmdFrm.operand[14] |= 3 << 3;
  460. break;
  461. case GUARD_INTERVAL_1_32:
  462. case GUARD_INTERVAL_AUTO:
  463. default:
  464. break;
  465. }
  466. switch(params->u.ofdm.transmission_mode) {
  467. case TRANSMISSION_MODE_8K:
  468. CmdFrm.operand[14] |= 1 << 1;
  469. break;
  470. case TRANSMISSION_MODE_2K:
  471. case TRANSMISSION_MODE_AUTO:
  472. default:
  473. break;
  474. }
  475. CmdFrm.operand[15] = 0x00; // network_ID[0]
  476. CmdFrm.operand[16] = 0x00; // network_ID[1]
  477. CmdFrm.operand[17] = 0x00; // Nr_of_dsd_sel_specs = 0 - > No PIDs are transmitted
  478. CmdFrm.length = 24;
  479. } else {
  480. CmdFrm.operand[7] = 0x00;
  481. CmdFrm.operand[8] = 0x00;
  482. CmdFrm.operand[9] = 0x00;
  483. CmdFrm.operand[10] = 0x00;
  484. CmdFrm.operand[11] =
  485. (((params->frequency/4000) >> 16) & 0xFF) | (2 << 6);
  486. CmdFrm.operand[12] =
  487. ((params->frequency/4000) >> 8) & 0xFF;
  488. CmdFrm.operand[13] = (params->frequency/4000) & 0xFF;
  489. CmdFrm.operand[14] =
  490. ((params->u.qpsk.symbol_rate/1000) >> 12) & 0xFF;
  491. CmdFrm.operand[15] =
  492. ((params->u.qpsk.symbol_rate/1000) >> 4) & 0xFF;
  493. CmdFrm.operand[16] =
  494. ((params->u.qpsk.symbol_rate/1000) << 4) & 0xF0;
  495. CmdFrm.operand[17] = 0x00;
  496. switch(params->u.qpsk.fec_inner) {
  497. case FEC_1_2:
  498. CmdFrm.operand[18] = 0x1;
  499. break;
  500. case FEC_2_3:
  501. CmdFrm.operand[18] = 0x2;
  502. break;
  503. case FEC_3_4:
  504. CmdFrm.operand[18] = 0x3;
  505. break;
  506. case FEC_5_6:
  507. CmdFrm.operand[18] = 0x4;
  508. break;
  509. case FEC_7_8:
  510. CmdFrm.operand[18] = 0x5;
  511. break;
  512. case FEC_8_9:
  513. CmdFrm.operand[18] = 0x6;
  514. break;
  515. case FEC_4_5:
  516. CmdFrm.operand[18] = 0x8;
  517. break;
  518. case FEC_AUTO:
  519. default:
  520. CmdFrm.operand[18] = 0x0;
  521. }
  522. switch(params->u.qam.modulation) {
  523. case QAM_16:
  524. CmdFrm.operand[19] = 0x08; // modulation
  525. break;
  526. case QAM_32:
  527. CmdFrm.operand[19] = 0x10; // modulation
  528. break;
  529. case QAM_64:
  530. CmdFrm.operand[19] = 0x18; // modulation
  531. break;
  532. case QAM_128:
  533. CmdFrm.operand[19] = 0x20; // modulation
  534. break;
  535. case QAM_256:
  536. CmdFrm.operand[19] = 0x28; // modulation
  537. break;
  538. case QAM_AUTO:
  539. default:
  540. CmdFrm.operand[19] = 0x00; // modulation
  541. }
  542. CmdFrm.operand[20] = 0x00;
  543. CmdFrm.operand[21] = 0x00;
  544. CmdFrm.operand[22] = 0x00; // Nr_of_dsd_sel_specs = 0 - > No PIDs are transmitted
  545. CmdFrm.length=28;
  546. }
  547. } // AVCTuner_DSD_direct
  548. if((k=AVCWrite(firesat,&CmdFrm,&RspFrm)))
  549. return k;
  550. mdelay(500);
  551. if(status)
  552. *status=RspFrm.operand[2];
  553. return 0;
  554. }
  555. int AVCTuner_SetPIDs(struct firesat *firesat, unsigned char pidc, u16 pid[])
  556. {
  557. AVCCmdFrm CmdFrm;
  558. AVCRspFrm RspFrm;
  559. int pos,k;
  560. if(pidc > 16 && pidc != 0xFF)
  561. return -EINVAL;
  562. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  563. CmdFrm.cts = AVC;
  564. CmdFrm.ctype = CONTROL;
  565. CmdFrm.sutyp = 0x5;
  566. CmdFrm.suid = firesat->subunit;
  567. CmdFrm.opcode = DSD;
  568. CmdFrm.operand[0] = 0; // source plug
  569. CmdFrm.operand[1] = 0xD2; // subfunction replace
  570. CmdFrm.operand[2] = 0x20; // system id = DVB
  571. CmdFrm.operand[3] = 0x00; // antenna number
  572. CmdFrm.operand[4] = 0x00; // system_specific_multiplex selection_length
  573. CmdFrm.operand[5] = pidc; // Nr_of_dsd_sel_specs
  574. pos=6;
  575. if(pidc != 0xFF) {
  576. for(k=0;k<pidc;k++) {
  577. CmdFrm.operand[pos++] = 0x13; // flowfunction relay
  578. CmdFrm.operand[pos++] = 0x80; // dsd_sel_spec_valid_flags -> PID
  579. CmdFrm.operand[pos++] = (pid[k] >> 8) & 0x1F;
  580. CmdFrm.operand[pos++] = pid[k] & 0xFF;
  581. CmdFrm.operand[pos++] = 0x00; // tableID
  582. CmdFrm.operand[pos++] = 0x00; // filter_length
  583. }
  584. }
  585. CmdFrm.length = pos+3;
  586. if((pos+3)%4)
  587. CmdFrm.length += 4 - ((pos+3)%4);
  588. if((k=AVCWrite(firesat,&CmdFrm,&RspFrm)))
  589. return k;
  590. mdelay(50);
  591. return 0;
  592. }
  593. int AVCTuner_GetTS(struct firesat *firesat){
  594. AVCCmdFrm CmdFrm;
  595. AVCRspFrm RspFrm;
  596. int k;
  597. //printk(KERN_INFO "%s\n", __func__);
  598. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  599. CmdFrm.cts = AVC;
  600. CmdFrm.ctype = CONTROL;
  601. CmdFrm.sutyp = 0x5;
  602. CmdFrm.suid = firesat->subunit;
  603. CmdFrm.opcode = DSIT;
  604. CmdFrm.operand[0] = 0; // source plug
  605. CmdFrm.operand[1] = 0xD2; // subfunction replace
  606. CmdFrm.operand[2] = 0xFF; //status
  607. CmdFrm.operand[3] = 0x20; // system id = DVB
  608. CmdFrm.operand[4] = 0x00; // antenna number
  609. CmdFrm.operand[5] = 0x0; // system_specific_search_flags
  610. CmdFrm.operand[6] = (firesat->type == FireSAT_DVB_T)?0x0c:0x11; // system_specific_multiplex selection_length
  611. CmdFrm.operand[7] = 0x00; // valid_flags [0]
  612. CmdFrm.operand[8] = 0x00; // valid_flags [1]
  613. CmdFrm.operand[7 + (firesat->type == FireSAT_DVB_T)?0x0c:0x11] = 0x00; // nr_of_dsit_sel_specs (always 0)
  614. CmdFrm.length = (firesat->type == FireSAT_DVB_T)?24:28;
  615. if ((k=AVCWrite(firesat, &CmdFrm, &RspFrm)))
  616. return k;
  617. mdelay(250);
  618. return 0;
  619. }
  620. int AVCIdentifySubunit(struct firesat *firesat)
  621. {
  622. AVCCmdFrm CmdFrm;
  623. AVCRspFrm RspFrm;
  624. memset(&CmdFrm,0,sizeof(AVCCmdFrm));
  625. CmdFrm.cts = AVC;
  626. CmdFrm.ctype = CONTROL;
  627. CmdFrm.sutyp = 0x5; // tuner
  628. CmdFrm.suid = firesat->subunit;
  629. CmdFrm.opcode = READ_DESCRIPTOR;
  630. CmdFrm.operand[0]=DESCRIPTOR_SUBUNIT_IDENTIFIER;
  631. CmdFrm.operand[1]=0xff;
  632. CmdFrm.operand[2]=0x00;
  633. CmdFrm.operand[3]=0x00; // length highbyte
  634. CmdFrm.operand[4]=0x08; // length lowbyte
  635. CmdFrm.operand[5]=0x00; // offset highbyte
  636. CmdFrm.operand[6]=0x0d; // offset lowbyte
  637. CmdFrm.length=12;
  638. if(AVCWrite(firesat,&CmdFrm,&RspFrm)<0)
  639. return -EIO;
  640. if(RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) {
  641. printk(KERN_ERR "%s: AVCWrite returned error code %d\n",
  642. __func__, RspFrm.resp);
  643. return -EINVAL;
  644. }
  645. if(((RspFrm.operand[3] << 8) + RspFrm.operand[4]) != 8) {
  646. printk(KERN_ERR "%s: Invalid response length\n", __func__);
  647. return -EINVAL;
  648. }
  649. return 0;
  650. }
  651. int AVCTunerStatus(struct firesat *firesat, ANTENNA_INPUT_INFO *antenna_input_info) {
  652. AVCCmdFrm CmdFrm;
  653. AVCRspFrm RspFrm;
  654. int length;
  655. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  656. CmdFrm.cts=AVC;
  657. CmdFrm.ctype=CONTROL;
  658. CmdFrm.sutyp=0x05; // tuner
  659. CmdFrm.suid=firesat->subunit;
  660. CmdFrm.opcode=READ_DESCRIPTOR;
  661. CmdFrm.operand[0]=DESCRIPTOR_TUNER_STATUS;
  662. CmdFrm.operand[1]=0xff; //read_result_status
  663. CmdFrm.operand[2]=0x00; // reserver
  664. CmdFrm.operand[3]=0;//sizeof(ANTENNA_INPUT_INFO) >> 8;
  665. CmdFrm.operand[4]=0;//sizeof(ANTENNA_INPUT_INFO) & 0xFF;
  666. CmdFrm.operand[5]=0x00;
  667. CmdFrm.operand[6]=0x00;
  668. CmdFrm.length=12;
  669. if (AVCWrite(firesat,&CmdFrm,&RspFrm) < 0)
  670. return -EIO;
  671. if(RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) {
  672. printk(KERN_ERR "%s: AVCWrite returned code %d\n",
  673. __func__, RspFrm.resp);
  674. return -EINVAL;
  675. }
  676. length = RspFrm.operand[9];
  677. if(RspFrm.operand[1] == 0x10 && length == sizeof(ANTENNA_INPUT_INFO))
  678. {
  679. memcpy(antenna_input_info, &RspFrm.operand[10],
  680. sizeof(ANTENNA_INPUT_INFO));
  681. return 0;
  682. }
  683. printk(KERN_ERR "%s: invalid tuner status (op=%d,length=%d) returned "
  684. "from AVC\n", __func__, RspFrm.operand[1], length);
  685. return -EINVAL;
  686. }
  687. int AVCLNBControl(struct firesat *firesat, char voltage, char burst,
  688. char conttone, char nrdiseq,
  689. struct dvb_diseqc_master_cmd *diseqcmd)
  690. {
  691. AVCCmdFrm CmdFrm;
  692. AVCRspFrm RspFrm;
  693. int i,j;
  694. printk(KERN_INFO "%s: voltage = %x, burst = %x, conttone = %x\n",
  695. __func__, voltage, burst, conttone);
  696. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  697. CmdFrm.cts=AVC;
  698. CmdFrm.ctype=CONTROL;
  699. CmdFrm.sutyp=0x05;
  700. CmdFrm.suid=firesat->subunit;
  701. CmdFrm.opcode=VENDOR;
  702. CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
  703. CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
  704. CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
  705. CmdFrm.operand[3]=SFE_VENDOR_OPCODE_LNB_CONTROL;
  706. CmdFrm.operand[4]=voltage;
  707. CmdFrm.operand[5]=nrdiseq;
  708. i=6;
  709. for(j=0;j<nrdiseq;j++) {
  710. int k;
  711. printk(KERN_INFO "%s: diseq %d len %x\n",
  712. __func__, j, diseqcmd[j].msg_len);
  713. CmdFrm.operand[i++]=diseqcmd[j].msg_len;
  714. for(k=0;k<diseqcmd[j].msg_len;k++) {
  715. printk(KERN_INFO "%s: diseq %d msg[%d] = %x\n",
  716. __func__, j, k, diseqcmd[j].msg[k]);
  717. CmdFrm.operand[i++]=diseqcmd[j].msg[k];
  718. }
  719. }
  720. CmdFrm.operand[i++]=burst;
  721. CmdFrm.operand[i++]=conttone;
  722. CmdFrm.length=i+3;
  723. if((i+3)%4)
  724. CmdFrm.length += 4 - ((i+3)%4);
  725. /* for(j=0;j<CmdFrm.length;j++)
  726. printk(KERN_INFO "%s: CmdFrm.operand[%d]=0x%x\n",__func__,j,CmdFrm.operand[j]);
  727. printk(KERN_INFO "%s: cmdfrm.length = %u\n",__func__,CmdFrm.length);
  728. */
  729. if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0)
  730. return -EIO;
  731. if(RspFrm.resp != ACCEPTED) {
  732. printk(KERN_ERR "%s: AVCWrite returned code %d\n",
  733. __func__, RspFrm.resp);
  734. return -EINVAL;
  735. }
  736. return 0;
  737. }
  738. int AVCSubUnitInfo(struct firesat *firesat, char *subunitcount)
  739. {
  740. AVCCmdFrm CmdFrm;
  741. AVCRspFrm RspFrm;
  742. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  743. CmdFrm.cts = AVC;
  744. CmdFrm.ctype = STATUS;
  745. CmdFrm.sutyp = 0x1f;
  746. CmdFrm.suid = 0x7;
  747. CmdFrm.opcode = SUBUNIT_Info;
  748. CmdFrm.operand[0] = 0x07;
  749. CmdFrm.operand[1] = 0xff;
  750. CmdFrm.operand[2] = 0xff;
  751. CmdFrm.operand[3] = 0xff;
  752. CmdFrm.operand[4] = 0xff;
  753. CmdFrm.length = 8;
  754. if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0)
  755. return -EIO;
  756. if(RspFrm.resp != STABLE) {
  757. printk(KERN_ERR "%s: AVCWrite returned code %d\n",
  758. __func__, RspFrm.resp);
  759. return -EINVAL;
  760. }
  761. if(subunitcount)
  762. *subunitcount = (RspFrm.operand[1] & 0x7) + 1;
  763. return 0;
  764. }
  765. int AVCRegisterRemoteControl(struct firesat *firesat)
  766. {
  767. AVCCmdFrm CmdFrm;
  768. // printk(KERN_INFO "%s\n",__func__);
  769. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  770. CmdFrm.cts = AVC;
  771. CmdFrm.ctype = NOTIFY;
  772. CmdFrm.sutyp = 0x1f;
  773. CmdFrm.suid = 0x7;
  774. CmdFrm.opcode = VENDOR;
  775. CmdFrm.operand[0] = SFE_VENDOR_DE_COMPANYID_0;
  776. CmdFrm.operand[1] = SFE_VENDOR_DE_COMPANYID_1;
  777. CmdFrm.operand[2] = SFE_VENDOR_DE_COMPANYID_2;
  778. CmdFrm.operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
  779. CmdFrm.length = 8;
  780. return AVCWrite(firesat, &CmdFrm, NULL);
  781. }
  782. void avc_remote_ctrl_work(struct work_struct *work)
  783. {
  784. struct firesat *firesat =
  785. container_of(work, struct firesat, remote_ctrl_work);
  786. /* Should it be rescheduled in failure cases? */
  787. AVCRegisterRemoteControl(firesat);
  788. }
  789. int AVCTuner_Host2Ca(struct firesat *firesat)
  790. {
  791. AVCCmdFrm CmdFrm;
  792. AVCRspFrm RspFrm;
  793. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  794. CmdFrm.cts = AVC;
  795. CmdFrm.ctype = CONTROL;
  796. CmdFrm.sutyp = 0x5;
  797. CmdFrm.suid = firesat->subunit;
  798. CmdFrm.opcode = VENDOR;
  799. CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
  800. CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
  801. CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
  802. CmdFrm.operand[3]=SFE_VENDOR_OPCODE_HOST2CA;
  803. CmdFrm.operand[4] = 0; // slot
  804. CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; // ca tag
  805. CmdFrm.operand[6] = 0; // more/last
  806. CmdFrm.operand[7] = 0; // length
  807. CmdFrm.length = 12;
  808. if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0)
  809. return -EIO;
  810. return 0;
  811. }
  812. static int get_ca_object_pos(AVCRspFrm *RspFrm)
  813. {
  814. int length = 1;
  815. // Check length of length field
  816. if (RspFrm->operand[7] & 0x80)
  817. length = (RspFrm->operand[7] & 0x7F) + 1;
  818. return length + 7;
  819. }
  820. static int get_ca_object_length(AVCRspFrm *RspFrm)
  821. {
  822. int size = 0;
  823. int i;
  824. if (RspFrm->operand[7] & 0x80) {
  825. for (i = 0; i < (RspFrm->operand[7] & 0x7F); i++) {
  826. size <<= 8;
  827. size += RspFrm->operand[8 + i];
  828. }
  829. }
  830. return RspFrm->operand[7];
  831. }
  832. int avc_ca_app_info(struct firesat *firesat, char *app_info, int *length)
  833. {
  834. AVCCmdFrm CmdFrm;
  835. AVCRspFrm RspFrm;
  836. int pos;
  837. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  838. CmdFrm.cts = AVC;
  839. CmdFrm.ctype = STATUS;
  840. CmdFrm.sutyp = 0x5;
  841. CmdFrm.suid = firesat->subunit;
  842. CmdFrm.opcode = VENDOR;
  843. CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
  844. CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
  845. CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
  846. CmdFrm.operand[3]=SFE_VENDOR_OPCODE_CA2HOST;
  847. CmdFrm.operand[4] = 0; // slot
  848. CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; // ca tag
  849. CmdFrm.length = 12;
  850. if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0)
  851. return -EIO;
  852. pos = get_ca_object_pos(&RspFrm);
  853. app_info[0] = (TAG_APP_INFO >> 16) & 0xFF;
  854. app_info[1] = (TAG_APP_INFO >> 8) & 0xFF;
  855. app_info[2] = (TAG_APP_INFO >> 0) & 0xFF;
  856. app_info[3] = 6 + RspFrm.operand[pos + 4];
  857. app_info[4] = 0x01;
  858. memcpy(&app_info[5], &RspFrm.operand[pos], 5 + RspFrm.operand[pos + 4]);
  859. *length = app_info[3] + 4;
  860. return 0;
  861. }
  862. int avc_ca_info(struct firesat *firesat, char *app_info, int *length)
  863. {
  864. AVCCmdFrm CmdFrm;
  865. AVCRspFrm RspFrm;
  866. int pos;
  867. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  868. CmdFrm.cts = AVC;
  869. CmdFrm.ctype = STATUS;
  870. CmdFrm.sutyp = 0x5;
  871. CmdFrm.suid = firesat->subunit;
  872. CmdFrm.opcode = VENDOR;
  873. CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
  874. CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
  875. CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
  876. CmdFrm.operand[3]=SFE_VENDOR_OPCODE_CA2HOST;
  877. CmdFrm.operand[4] = 0; // slot
  878. CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; // ca tag
  879. CmdFrm.length = 12;
  880. if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0)
  881. return -EIO;
  882. pos = get_ca_object_pos(&RspFrm);
  883. app_info[0] = (TAG_CA_INFO >> 16) & 0xFF;
  884. app_info[1] = (TAG_CA_INFO >> 8) & 0xFF;
  885. app_info[2] = (TAG_CA_INFO >> 0) & 0xFF;
  886. app_info[3] = 2;
  887. app_info[4] = app_info[5];
  888. app_info[5] = app_info[6];
  889. *length = app_info[3] + 4;
  890. return 0;
  891. }
  892. int avc_ca_reset(struct firesat *firesat)
  893. {
  894. AVCCmdFrm CmdFrm;
  895. AVCRspFrm RspFrm;
  896. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  897. CmdFrm.cts = AVC;
  898. CmdFrm.ctype = CONTROL;
  899. CmdFrm.sutyp = 0x5;
  900. CmdFrm.suid = firesat->subunit;
  901. CmdFrm.opcode = VENDOR;
  902. CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
  903. CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
  904. CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
  905. CmdFrm.operand[3]=SFE_VENDOR_OPCODE_HOST2CA;
  906. CmdFrm.operand[4] = 0; // slot
  907. CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_RESET; // ca tag
  908. CmdFrm.operand[6] = 0; // more/last
  909. CmdFrm.operand[7] = 1; // length
  910. CmdFrm.operand[8] = 0; // force hardware reset
  911. CmdFrm.length = 12;
  912. if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0)
  913. return -EIO;
  914. return 0;
  915. }
  916. int avc_ca_pmt(struct firesat *firesat, char *msg, int length)
  917. {
  918. AVCCmdFrm CmdFrm;
  919. AVCRspFrm RspFrm;
  920. int list_management;
  921. int program_info_length;
  922. int pmt_cmd_id;
  923. int read_pos;
  924. int write_pos;
  925. int es_info_length;
  926. int crc32_csum;
  927. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  928. CmdFrm.cts = AVC;
  929. CmdFrm.ctype = CONTROL;
  930. CmdFrm.sutyp = 0x5;
  931. CmdFrm.suid = firesat->subunit;
  932. CmdFrm.opcode = VENDOR;
  933. if (msg[0] != LIST_MANAGEMENT_ONLY) {
  934. printk(KERN_INFO "%s: list_management %d not support. "
  935. "Forcing list_management to \"only\" (3). \n",
  936. __func__, msg[0]);
  937. msg[0] = LIST_MANAGEMENT_ONLY;
  938. }
  939. // We take the cmd_id from the programme level only!
  940. list_management = msg[0];
  941. program_info_length = ((msg[4] & 0x0F) << 8) + msg[5];
  942. if (program_info_length > 0)
  943. program_info_length--; // Remove pmt_cmd_id
  944. pmt_cmd_id = msg[6];
  945. CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
  946. CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
  947. CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
  948. CmdFrm.operand[3]=SFE_VENDOR_OPCODE_HOST2CA;
  949. CmdFrm.operand[4] = 0; // slot
  950. CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_PMT; // ca tag
  951. CmdFrm.operand[6] = 0; // more/last
  952. //CmdFrm.operand[7] = XXXprogram_info_length + 17; // length
  953. CmdFrm.operand[8] = list_management;
  954. CmdFrm.operand[9] = 0x01; // pmt_cmd=OK_descramble
  955. // TS program map table
  956. // Table id=2
  957. CmdFrm.operand[10] = 0x02;
  958. // Section syntax + length
  959. CmdFrm.operand[11] = 0x80;
  960. //CmdFrm.operand[12] = XXXprogram_info_length + 12;
  961. // Program number
  962. CmdFrm.operand[13] = msg[1];
  963. CmdFrm.operand[14] = msg[2];
  964. // Version number=0 + current/next=1
  965. CmdFrm.operand[15] = 0x01;
  966. // Section number=0
  967. CmdFrm.operand[16] = 0x00;
  968. // Last section number=0
  969. CmdFrm.operand[17] = 0x00;
  970. // PCR_PID=1FFF
  971. CmdFrm.operand[18] = 0x1F;
  972. CmdFrm.operand[19] = 0xFF;
  973. // Program info length
  974. CmdFrm.operand[20] = (program_info_length >> 8);
  975. CmdFrm.operand[21] = (program_info_length & 0xFF);
  976. // CA descriptors at programme level
  977. read_pos = 6;
  978. write_pos = 22;
  979. if (program_info_length > 0) {
  980. /* printk(KERN_INFO "Copying descriptors at programme level.\n"); */
  981. pmt_cmd_id = msg[read_pos++];
  982. if (pmt_cmd_id != 1 && pmt_cmd_id !=4) {
  983. printk(KERN_ERR "Invalid pmt_cmd_id=%d.\n",
  984. pmt_cmd_id);
  985. }
  986. memcpy(&CmdFrm.operand[write_pos], &msg[read_pos],
  987. program_info_length);
  988. read_pos += program_info_length;
  989. write_pos += program_info_length;
  990. }
  991. while (read_pos < length) {
  992. /* printk(KERN_INFO "Copying descriptors at stream level for " */
  993. /* "stream type %d.\n", msg[read_pos]); */
  994. CmdFrm.operand[write_pos++] = msg[read_pos++];
  995. CmdFrm.operand[write_pos++] = msg[read_pos++];
  996. CmdFrm.operand[write_pos++] = msg[read_pos++];
  997. es_info_length =
  998. ((msg[read_pos] & 0x0F) << 8) + msg[read_pos + 1];
  999. read_pos += 2;
  1000. if (es_info_length > 0)
  1001. es_info_length--; // Remove pmt_cmd_id
  1002. CmdFrm.operand[write_pos++] = es_info_length >> 8;
  1003. CmdFrm.operand[write_pos++] = es_info_length & 0xFF;
  1004. if (es_info_length > 0) {
  1005. pmt_cmd_id = msg[read_pos++];
  1006. if (pmt_cmd_id != 1 && pmt_cmd_id !=4) {
  1007. printk(KERN_ERR "Invalid pmt_cmd_id=%d at "
  1008. "stream level.\n", pmt_cmd_id);
  1009. }
  1010. memcpy(&CmdFrm.operand[write_pos], &msg[read_pos],
  1011. es_info_length);
  1012. read_pos += es_info_length;
  1013. write_pos += es_info_length;
  1014. }
  1015. }
  1016. // CRC
  1017. CmdFrm.operand[write_pos++] = 0x00;
  1018. CmdFrm.operand[write_pos++] = 0x00;
  1019. CmdFrm.operand[write_pos++] = 0x00;
  1020. CmdFrm.operand[write_pos++] = 0x00;
  1021. CmdFrm.operand[7] = write_pos - 8;
  1022. CmdFrm.operand[12] = write_pos - 13;
  1023. crc32_csum = crc32_be(0, &CmdFrm.operand[10],
  1024. CmdFrm.operand[12] - 1);
  1025. CmdFrm.operand[write_pos - 4] = (crc32_csum >> 24) & 0xFF;
  1026. CmdFrm.operand[write_pos - 3] = (crc32_csum >> 16) & 0xFF;
  1027. CmdFrm.operand[write_pos - 2] = (crc32_csum >> 8) & 0xFF;
  1028. CmdFrm.operand[write_pos - 1] = (crc32_csum >> 0) & 0xFF;
  1029. CmdFrm.length = write_pos + 3;
  1030. if ((write_pos + 3) % 4)
  1031. CmdFrm.length += 4 - ((write_pos + 3) % 4);
  1032. if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0)
  1033. return -EIO;
  1034. if (RspFrm.resp != ACCEPTED) {
  1035. printk(KERN_ERR "Answer to CA PMT was %d\n", RspFrm.resp);
  1036. return -EFAULT;
  1037. }
  1038. return 0;
  1039. }
  1040. int avc_ca_get_time_date(struct firesat *firesat, int *interval)
  1041. {
  1042. AVCCmdFrm CmdFrm;
  1043. AVCRspFrm RspFrm;
  1044. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  1045. CmdFrm.cts = AVC;
  1046. CmdFrm.ctype = STATUS;
  1047. CmdFrm.sutyp = 0x5;
  1048. CmdFrm.suid = firesat->subunit;
  1049. CmdFrm.opcode = VENDOR;
  1050. CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
  1051. CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
  1052. CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
  1053. CmdFrm.operand[3]=SFE_VENDOR_OPCODE_CA2HOST;
  1054. CmdFrm.operand[4] = 0; // slot
  1055. CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; // ca tag
  1056. CmdFrm.operand[6] = 0; // more/last
  1057. CmdFrm.operand[7] = 0; // length
  1058. CmdFrm.length = 12;
  1059. if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0)
  1060. return -EIO;
  1061. *interval = RspFrm.operand[get_ca_object_pos(&RspFrm)];
  1062. return 0;
  1063. }
  1064. int avc_ca_enter_menu(struct firesat *firesat)
  1065. {
  1066. AVCCmdFrm CmdFrm;
  1067. AVCRspFrm RspFrm;
  1068. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  1069. CmdFrm.cts = AVC;
  1070. CmdFrm.ctype = STATUS;
  1071. CmdFrm.sutyp = 0x5;
  1072. CmdFrm.suid = firesat->subunit;
  1073. CmdFrm.opcode = VENDOR;
  1074. CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
  1075. CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
  1076. CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
  1077. CmdFrm.operand[3]=SFE_VENDOR_OPCODE_HOST2CA;
  1078. CmdFrm.operand[4] = 0; // slot
  1079. CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU;
  1080. CmdFrm.operand[6] = 0; // more/last
  1081. CmdFrm.operand[7] = 0; // length
  1082. CmdFrm.length = 12;
  1083. if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0)
  1084. return -EIO;
  1085. return 0;
  1086. }
  1087. int avc_ca_get_mmi(struct firesat *firesat, char *mmi_object, int *length)
  1088. {
  1089. AVCCmdFrm CmdFrm;
  1090. AVCRspFrm RspFrm;
  1091. memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
  1092. CmdFrm.cts = AVC;
  1093. CmdFrm.ctype = STATUS;
  1094. CmdFrm.sutyp = 0x5;
  1095. CmdFrm.suid = firesat->subunit;
  1096. CmdFrm.opcode = VENDOR;
  1097. CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
  1098. CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
  1099. CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
  1100. CmdFrm.operand[3]=SFE_VENDOR_OPCODE_CA2HOST;
  1101. CmdFrm.operand[4] = 0; // slot
  1102. CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_MMI;
  1103. CmdFrm.operand[6] = 0; // more/last
  1104. CmdFrm.operand[7] = 0; // length
  1105. CmdFrm.length = 12;
  1106. if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0)
  1107. return -EIO;
  1108. *length = get_ca_object_length(&RspFrm);
  1109. memcpy(mmi_object, &RspFrm.operand[get_ca_object_pos(&RspFrm)], *length);
  1110. return 0;
  1111. }