avc_api.c 34 KB

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