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