2 * FireDTV driver (formerly known as FireSAT)
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>
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.
14 #include <linux/bug.h>
15 #include <linux/crc32.h>
16 #include <linux/delay.h>
17 #include <linux/device.h>
18 #include <linux/kernel.h>
19 #include <linux/moduleparam.h>
20 #include <linux/mutex.h>
21 #include <linux/string.h>
22 #include <linux/wait.h>
23 #include <linux/workqueue.h>
25 #include <ieee1394_transactions.h>
30 #include "firesat-rc.h"
32 #define FCP_COMMAND_REGISTER 0xfffff0000b00ULL
34 static int __avc_write(struct firesat
*firesat
,
35 const AVCCmdFrm
*CmdFrm
, AVCRspFrm
*RspFrm
)
40 firesat
->avc_reply_received
= false;
42 for (retry
= 0; retry
< 6; retry
++) {
43 err
= hpsb_node_write(firesat
->ud
->ne
, FCP_COMMAND_REGISTER
,
44 (quadlet_t
*)CmdFrm
, CmdFrm
->length
);
46 firesat
->avc_reply_received
= true;
47 dev_err(&firesat
->ud
->device
,
48 "FCP command write failed\n");
56 * AV/C specs say that answers should be sent within 150 ms.
57 * Time out after 200 ms.
59 if (wait_event_timeout(firesat
->avc_wait
,
60 firesat
->avc_reply_received
,
62 memcpy(RspFrm
, firesat
->respfrm
, firesat
->resp_length
);
63 RspFrm
->length
= firesat
->resp_length
;
68 dev_err(&firesat
->ud
->device
, "FCP response timed out\n");
72 static int avc_write(struct firesat
*firesat
,
73 const AVCCmdFrm
*CmdFrm
, AVCRspFrm
*RspFrm
)
77 if (mutex_lock_interruptible(&firesat
->avc_mutex
))
80 ret
= __avc_write(firesat
, CmdFrm
, RspFrm
);
82 mutex_unlock(&firesat
->avc_mutex
);
86 int avc_recv(struct firesat
*firesat
, u8
*data
, size_t length
)
88 AVCRspFrm
*RspFrm
= (AVCRspFrm
*)data
;
91 RspFrm
->operand
[0] == SFE_VENDOR_DE_COMPANYID_0
&&
92 RspFrm
->operand
[1] == SFE_VENDOR_DE_COMPANYID_1
&&
93 RspFrm
->operand
[2] == SFE_VENDOR_DE_COMPANYID_2
&&
94 RspFrm
->operand
[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL
) {
95 if (RspFrm
->resp
== CHANGED
) {
96 firesat_handle_rc(firesat
,
97 RspFrm
->operand
[4] << 8 | RspFrm
->operand
[5]);
98 schedule_work(&firesat
->remote_ctrl_work
);
99 } else if (RspFrm
->resp
!= INTERIM
) {
100 dev_info(&firesat
->ud
->device
,
101 "remote control result = %d\n", RspFrm
->resp
);
106 if (firesat
->avc_reply_received
) {
107 dev_err(&firesat
->ud
->device
,
108 "received out-of-order AVC response, ignored\n");
112 memcpy(firesat
->respfrm
, data
, length
);
113 firesat
->resp_length
= length
;
115 firesat
->avc_reply_received
= true;
116 wake_up(&firesat
->avc_wait
);
122 * tuning command for setting the relative LNB frequency
123 * (not supported by the AVC standard)
125 static void avc_tuner_tuneqpsk(struct firesat
*firesat
,
126 struct dvb_frontend_parameters
*params
, AVCCmdFrm
*CmdFrm
)
128 CmdFrm
->opcode
= VENDOR
;
130 CmdFrm
->operand
[0] = SFE_VENDOR_DE_COMPANYID_0
;
131 CmdFrm
->operand
[1] = SFE_VENDOR_DE_COMPANYID_1
;
132 CmdFrm
->operand
[2] = SFE_VENDOR_DE_COMPANYID_2
;
133 CmdFrm
->operand
[3] = SFE_VENDOR_OPCODE_TUNE_QPSK
;
135 CmdFrm
->operand
[4] = (params
->frequency
>> 24) & 0xff;
136 CmdFrm
->operand
[5] = (params
->frequency
>> 16) & 0xff;
137 CmdFrm
->operand
[6] = (params
->frequency
>> 8) & 0xff;
138 CmdFrm
->operand
[7] = params
->frequency
& 0xff;
140 CmdFrm
->operand
[8] = ((params
->u
.qpsk
.symbol_rate
/ 1000) >> 8) & 0xff;
141 CmdFrm
->operand
[9] = (params
->u
.qpsk
.symbol_rate
/ 1000) & 0xff;
143 switch(params
->u
.qpsk
.fec_inner
) {
145 CmdFrm
->operand
[10] = 0x1; break;
147 CmdFrm
->operand
[10] = 0x2; break;
149 CmdFrm
->operand
[10] = 0x3; break;
151 CmdFrm
->operand
[10] = 0x4; break;
153 CmdFrm
->operand
[10] = 0x5; break;
158 CmdFrm
->operand
[10] = 0x0;
161 if (firesat
->voltage
== 0xff)
162 CmdFrm
->operand
[11] = 0xff;
163 else if (firesat
->voltage
== SEC_VOLTAGE_18
) /* polarisation */
164 CmdFrm
->operand
[11] = 0;
166 CmdFrm
->operand
[11] = 1;
168 if (firesat
->tone
== 0xff)
169 CmdFrm
->operand
[12] = 0xff;
170 else if (firesat
->tone
== SEC_TONE_ON
) /* band */
171 CmdFrm
->operand
[12] = 1;
173 CmdFrm
->operand
[12] = 0;
175 if (firesat
->type
== FireSAT_DVB_S2
) {
176 CmdFrm
->operand
[13] = 0x1;
177 CmdFrm
->operand
[14] = 0xff;
178 CmdFrm
->operand
[15] = 0xff;
185 static void avc_tuner_dsd_dvb_c(struct dvb_frontend_parameters
*params
,
190 flags
.Bits
.Modulation
= params
->u
.qam
.modulation
!= QAM_AUTO
;
191 flags
.Bits
.FEC_inner
= params
->u
.qam
.fec_inner
!= FEC_AUTO
;
192 flags
.Bits
.FEC_outer
= 0;
193 flags
.Bits
.Symbol_Rate
= 1;
194 flags
.Bits
.Frequency
= 1;
195 flags
.Bits
.Orbital_Pos
= 0;
196 flags
.Bits
.Polarisation
= 0;
197 flags
.Bits
.reserved_fields
= 0;
198 flags
.Bits
.reserved1
= 0;
199 flags
.Bits
.Network_ID
= 0;
201 CmdFrm
->opcode
= DSD
;
203 CmdFrm
->operand
[0] = 0; /* source plug */
204 CmdFrm
->operand
[1] = 0xd2; /* subfunction replace */
205 CmdFrm
->operand
[2] = 0x20; /* system id = DVB */
206 CmdFrm
->operand
[3] = 0x00; /* antenna number */
207 /* system_specific_multiplex selection_length */
208 CmdFrm
->operand
[4] = 0x11;
209 CmdFrm
->operand
[5] = flags
.Valid_Word
.ByteHi
; /* valid_flags [0] */
210 CmdFrm
->operand
[6] = flags
.Valid_Word
.ByteLo
; /* valid_flags [1] */
211 CmdFrm
->operand
[7] = 0x00;
212 CmdFrm
->operand
[8] = 0x00;
213 CmdFrm
->operand
[9] = 0x00;
214 CmdFrm
->operand
[10] = 0x00;
216 CmdFrm
->operand
[11] =
217 (((params
->frequency
/ 4000) >> 16) & 0xff) | (2 << 6);
218 CmdFrm
->operand
[12] =
219 ((params
->frequency
/ 4000) >> 8) & 0xff;
220 CmdFrm
->operand
[13] = (params
->frequency
/ 4000) & 0xff;
221 CmdFrm
->operand
[14] =
222 ((params
->u
.qpsk
.symbol_rate
/ 1000) >> 12) & 0xff;
223 CmdFrm
->operand
[15] =
224 ((params
->u
.qpsk
.symbol_rate
/ 1000) >> 4) & 0xff;
225 CmdFrm
->operand
[16] =
226 ((params
->u
.qpsk
.symbol_rate
/ 1000) << 4) & 0xf0;
227 CmdFrm
->operand
[17] = 0x00;
229 switch (params
->u
.qpsk
.fec_inner
) {
231 CmdFrm
->operand
[18] = 0x1; break;
233 CmdFrm
->operand
[18] = 0x2; break;
235 CmdFrm
->operand
[18] = 0x3; break;
237 CmdFrm
->operand
[18] = 0x4; break;
239 CmdFrm
->operand
[18] = 0x5; break;
241 CmdFrm
->operand
[18] = 0x6; break;
243 CmdFrm
->operand
[18] = 0x8; break;
246 CmdFrm
->operand
[18] = 0x0;
248 switch (params
->u
.qam
.modulation
) {
250 CmdFrm
->operand
[19] = 0x08; break;
252 CmdFrm
->operand
[19] = 0x10; break;
254 CmdFrm
->operand
[19] = 0x18; break;
256 CmdFrm
->operand
[19] = 0x20; break;
258 CmdFrm
->operand
[19] = 0x28; break;
261 CmdFrm
->operand
[19] = 0x00;
263 CmdFrm
->operand
[20] = 0x00;
264 CmdFrm
->operand
[21] = 0x00;
265 /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */
266 CmdFrm
->operand
[22] = 0x00;
271 static void avc_tuner_dsd_dvb_t(struct dvb_frontend_parameters
*params
,
276 flags
.Bits_T
.GuardInterval
=
277 params
->u
.ofdm
.guard_interval
!= GUARD_INTERVAL_AUTO
;
278 flags
.Bits_T
.CodeRateLPStream
=
279 params
->u
.ofdm
.code_rate_LP
!= FEC_AUTO
;
280 flags
.Bits_T
.CodeRateHPStream
=
281 params
->u
.ofdm
.code_rate_HP
!= FEC_AUTO
;
282 flags
.Bits_T
.HierarchyInfo
=
283 params
->u
.ofdm
.hierarchy_information
!= HIERARCHY_AUTO
;
284 flags
.Bits_T
.Constellation
=
285 params
->u
.ofdm
.constellation
!= QAM_AUTO
;
286 flags
.Bits_T
.Bandwidth
=
287 params
->u
.ofdm
.bandwidth
!= BANDWIDTH_AUTO
;
288 flags
.Bits_T
.CenterFrequency
= 1;
289 flags
.Bits_T
.reserved1
= 0;
290 flags
.Bits_T
.reserved2
= 0;
291 flags
.Bits_T
.OtherFrequencyFlag
= 0;
292 flags
.Bits_T
.TransmissionMode
=
293 params
->u
.ofdm
.transmission_mode
!= TRANSMISSION_MODE_AUTO
;
294 flags
.Bits_T
.NetworkId
= 0;
296 CmdFrm
->opcode
= DSD
;
298 CmdFrm
->operand
[0] = 0; /* source plug */
299 CmdFrm
->operand
[1] = 0xd2; /* subfunction replace */
300 CmdFrm
->operand
[2] = 0x20; /* system id = DVB */
301 CmdFrm
->operand
[3] = 0x00; /* antenna number */
302 /* system_specific_multiplex selection_length */
303 CmdFrm
->operand
[4] = 0x0c;
304 CmdFrm
->operand
[5] = flags
.Valid_Word
.ByteHi
; /* valid_flags [0] */
305 CmdFrm
->operand
[6] = flags
.Valid_Word
.ByteLo
; /* valid_flags [1] */
306 CmdFrm
->operand
[7] = 0x0;
307 CmdFrm
->operand
[8] = (params
->frequency
/ 10) >> 24;
308 CmdFrm
->operand
[9] = ((params
->frequency
/ 10) >> 16) & 0xff;
309 CmdFrm
->operand
[10] = ((params
->frequency
/ 10) >> 8) & 0xff;
310 CmdFrm
->operand
[11] = (params
->frequency
/ 10) & 0xff;
312 switch (params
->u
.ofdm
.bandwidth
) {
313 case BANDWIDTH_7_MHZ
:
314 CmdFrm
->operand
[12] = 0x20; break;
315 case BANDWIDTH_8_MHZ
:
316 case BANDWIDTH_6_MHZ
: /* not defined by AVC spec */
319 CmdFrm
->operand
[12] = 0x00;
321 switch (params
->u
.ofdm
.constellation
) {
323 CmdFrm
->operand
[13] = 1 << 6; break;
325 CmdFrm
->operand
[13] = 2 << 6; break;
328 CmdFrm
->operand
[13] = 0x00;
330 switch (params
->u
.ofdm
.hierarchy_information
) {
332 CmdFrm
->operand
[13] |= 1 << 3; break;
334 CmdFrm
->operand
[13] |= 2 << 3; break;
336 CmdFrm
->operand
[13] |= 3 << 3; break;
342 switch (params
->u
.ofdm
.code_rate_HP
) {
344 CmdFrm
->operand
[13] |= 1; break;
346 CmdFrm
->operand
[13] |= 2; break;
348 CmdFrm
->operand
[13] |= 3; break;
350 CmdFrm
->operand
[13] |= 4; break;
355 switch (params
->u
.ofdm
.code_rate_LP
) {
357 CmdFrm
->operand
[14] = 1 << 5; break;
359 CmdFrm
->operand
[14] = 2 << 5; break;
361 CmdFrm
->operand
[14] = 3 << 5; break;
363 CmdFrm
->operand
[14] = 4 << 5; break;
366 CmdFrm
->operand
[14] = 0x00; break;
368 switch (params
->u
.ofdm
.guard_interval
) {
369 case GUARD_INTERVAL_1_16
:
370 CmdFrm
->operand
[14] |= 1 << 3; break;
371 case GUARD_INTERVAL_1_8
:
372 CmdFrm
->operand
[14] |= 2 << 3; break;
373 case GUARD_INTERVAL_1_4
:
374 CmdFrm
->operand
[14] |= 3 << 3; break;
375 case GUARD_INTERVAL_1_32
:
376 case GUARD_INTERVAL_AUTO
:
380 switch (params
->u
.ofdm
.transmission_mode
) {
381 case TRANSMISSION_MODE_8K
:
382 CmdFrm
->operand
[14] |= 1 << 1; break;
383 case TRANSMISSION_MODE_2K
:
384 case TRANSMISSION_MODE_AUTO
:
389 CmdFrm
->operand
[15] = 0x00; /* network_ID[0] */
390 CmdFrm
->operand
[16] = 0x00; /* network_ID[1] */
391 /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */
392 CmdFrm
->operand
[17] = 0x00;
397 int avc_tuner_dsd(struct firesat
*firesat
,
398 struct dvb_frontend_parameters
*params
)
403 memset(&CmdFrm
, 0, sizeof(AVCCmdFrm
));
406 CmdFrm
.ctype
= CONTROL
;
408 CmdFrm
.suid
= firesat
->subunit
;
410 switch (firesat
->type
) {
413 avc_tuner_tuneqpsk(firesat
, params
, &CmdFrm
); break;
415 avc_tuner_dsd_dvb_c(params
, &CmdFrm
); break;
417 avc_tuner_dsd_dvb_t(params
, &CmdFrm
); break;
422 if (avc_write(firesat
, &CmdFrm
, &RspFrm
) < 0)
428 /* u8 *status was an out-parameter of avc_tuner_dsd, unused by caller */
430 *status
=RspFrm
.operand
[2];
435 int avc_tuner_set_pids(struct firesat
*firesat
, unsigned char pidc
, u16 pid
[])
441 if (pidc
> 16 && pidc
!= 0xff)
444 memset(&CmdFrm
, 0, sizeof(AVCCmdFrm
));
447 CmdFrm
.ctype
= CONTROL
;
449 CmdFrm
.suid
= firesat
->subunit
;
452 CmdFrm
.operand
[0] = 0; // source plug
453 CmdFrm
.operand
[1] = 0xD2; // subfunction replace
454 CmdFrm
.operand
[2] = 0x20; // system id = DVB
455 CmdFrm
.operand
[3] = 0x00; // antenna number
456 CmdFrm
.operand
[4] = 0x00; // system_specific_multiplex selection_length
457 CmdFrm
.operand
[5] = pidc
; // Nr_of_dsd_sel_specs
461 for (k
= 0; k
< pidc
; k
++) {
462 CmdFrm
.operand
[pos
++] = 0x13; // flowfunction relay
463 CmdFrm
.operand
[pos
++] = 0x80; // dsd_sel_spec_valid_flags -> PID
464 CmdFrm
.operand
[pos
++] = (pid
[k
] >> 8) & 0x1F;
465 CmdFrm
.operand
[pos
++] = pid
[k
] & 0xFF;
466 CmdFrm
.operand
[pos
++] = 0x00; // tableID
467 CmdFrm
.operand
[pos
++] = 0x00; // filter_length
470 CmdFrm
.length
= ALIGN(3 + pos
, 4);
472 if (avc_write(firesat
, &CmdFrm
, &RspFrm
) < 0)
479 int avc_tuner_get_ts(struct firesat
*firesat
)
484 memset(&CmdFrm
, 0, sizeof(AVCCmdFrm
));
487 CmdFrm
.ctype
= CONTROL
;
489 CmdFrm
.suid
= firesat
->subunit
;
490 CmdFrm
.opcode
= DSIT
;
492 CmdFrm
.operand
[0] = 0; // source plug
493 CmdFrm
.operand
[1] = 0xD2; // subfunction replace
494 CmdFrm
.operand
[2] = 0xFF; //status
495 CmdFrm
.operand
[3] = 0x20; // system id = DVB
496 CmdFrm
.operand
[4] = 0x00; // antenna number
497 CmdFrm
.operand
[5] = 0x0; // system_specific_search_flags
498 CmdFrm
.operand
[6] = (firesat
->type
== FireSAT_DVB_T
)?0x0c:0x11; // system_specific_multiplex selection_length
499 CmdFrm
.operand
[7] = 0x00; // valid_flags [0]
500 CmdFrm
.operand
[8] = 0x00; // valid_flags [1]
501 CmdFrm
.operand
[7 + (firesat
->type
== FireSAT_DVB_T
)?0x0c:0x11] = 0x00; // nr_of_dsit_sel_specs (always 0)
503 CmdFrm
.length
= (firesat
->type
== FireSAT_DVB_T
)?24:28;
505 if (avc_write(firesat
, &CmdFrm
, &RspFrm
) < 0)
512 int avc_identify_subunit(struct firesat
*firesat
)
517 memset(&CmdFrm
,0,sizeof(AVCCmdFrm
));
520 CmdFrm
.ctype
= CONTROL
;
521 CmdFrm
.sutyp
= 0x5; // tuner
522 CmdFrm
.suid
= firesat
->subunit
;
523 CmdFrm
.opcode
= READ_DESCRIPTOR
;
525 CmdFrm
.operand
[0]=DESCRIPTOR_SUBUNIT_IDENTIFIER
;
526 CmdFrm
.operand
[1]=0xff;
527 CmdFrm
.operand
[2]=0x00;
528 CmdFrm
.operand
[3]=0x00; // length highbyte
529 CmdFrm
.operand
[4]=0x08; // length lowbyte
530 CmdFrm
.operand
[5]=0x00; // offset highbyte
531 CmdFrm
.operand
[6]=0x0d; // offset lowbyte
535 if (avc_write(firesat
, &CmdFrm
, &RspFrm
) < 0)
538 if ((RspFrm
.resp
!= STABLE
&& RspFrm
.resp
!= ACCEPTED
) ||
539 (RspFrm
.operand
[3] << 8) + RspFrm
.operand
[4] != 8) {
540 dev_err(&firesat
->ud
->device
,
541 "cannot read subunit identifier\n");
547 int avc_tuner_status(struct firesat
*firesat
,
548 ANTENNA_INPUT_INFO
*antenna_input_info
)
554 memset(&CmdFrm
, 0, sizeof(AVCCmdFrm
));
557 CmdFrm
.ctype
=CONTROL
;
558 CmdFrm
.sutyp
=0x05; // tuner
559 CmdFrm
.suid
=firesat
->subunit
;
560 CmdFrm
.opcode
=READ_DESCRIPTOR
;
562 CmdFrm
.operand
[0]=DESCRIPTOR_TUNER_STATUS
;
563 CmdFrm
.operand
[1]=0xff; //read_result_status
564 CmdFrm
.operand
[2]=0x00; // reserver
565 CmdFrm
.operand
[3]=0;//sizeof(ANTENNA_INPUT_INFO) >> 8;
566 CmdFrm
.operand
[4]=0;//sizeof(ANTENNA_INPUT_INFO) & 0xFF;
567 CmdFrm
.operand
[5]=0x00;
568 CmdFrm
.operand
[6]=0x00;
571 if (avc_write(firesat
, &CmdFrm
, &RspFrm
) < 0)
574 if (RspFrm
.resp
!= STABLE
&& RspFrm
.resp
!= ACCEPTED
) {
575 dev_err(&firesat
->ud
->device
, "cannot read tuner status\n");
579 length
= RspFrm
.operand
[9];
580 if (RspFrm
.operand
[1] != 0x10 || length
!= sizeof(ANTENNA_INPUT_INFO
)) {
581 dev_err(&firesat
->ud
->device
, "got invalid tuner status\n");
585 memcpy(antenna_input_info
, &RspFrm
.operand
[10], length
);
589 int avc_lnb_control(struct firesat
*firesat
, char voltage
, char burst
,
590 char conttone
, char nrdiseq
,
591 struct dvb_diseqc_master_cmd
*diseqcmd
)
597 memset(&CmdFrm
, 0, sizeof(AVCCmdFrm
));
600 CmdFrm
.ctype
=CONTROL
;
602 CmdFrm
.suid
=firesat
->subunit
;
603 CmdFrm
.opcode
=VENDOR
;
605 CmdFrm
.operand
[0]=SFE_VENDOR_DE_COMPANYID_0
;
606 CmdFrm
.operand
[1]=SFE_VENDOR_DE_COMPANYID_1
;
607 CmdFrm
.operand
[2]=SFE_VENDOR_DE_COMPANYID_2
;
608 CmdFrm
.operand
[3]=SFE_VENDOR_OPCODE_LNB_CONTROL
;
610 CmdFrm
.operand
[4]=voltage
;
611 CmdFrm
.operand
[5]=nrdiseq
;
615 for (j
= 0; j
< nrdiseq
; j
++) {
616 CmdFrm
.operand
[i
++] = diseqcmd
[j
].msg_len
;
618 for (k
= 0; k
< diseqcmd
[j
].msg_len
; k
++)
619 CmdFrm
.operand
[i
++] = diseqcmd
[j
].msg
[k
];
622 CmdFrm
.operand
[i
++]=burst
;
623 CmdFrm
.operand
[i
++]=conttone
;
625 CmdFrm
.length
= ALIGN(3 + i
, 4);
627 if (avc_write(firesat
, &CmdFrm
, &RspFrm
) < 0)
630 if (RspFrm
.resp
!= ACCEPTED
) {
631 dev_err(&firesat
->ud
->device
, "LNB control failed\n");
638 int avc_register_remote_control(struct firesat
*firesat
)
642 memset(&CmdFrm
, 0, sizeof(AVCCmdFrm
));
645 CmdFrm
.ctype
= NOTIFY
;
648 CmdFrm
.opcode
= VENDOR
;
650 CmdFrm
.operand
[0] = SFE_VENDOR_DE_COMPANYID_0
;
651 CmdFrm
.operand
[1] = SFE_VENDOR_DE_COMPANYID_1
;
652 CmdFrm
.operand
[2] = SFE_VENDOR_DE_COMPANYID_2
;
653 CmdFrm
.operand
[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL
;
657 return avc_write(firesat
, &CmdFrm
, NULL
);
660 void avc_remote_ctrl_work(struct work_struct
*work
)
662 struct firesat
*firesat
=
663 container_of(work
, struct firesat
, remote_ctrl_work
);
665 /* Should it be rescheduled in failure cases? */
666 avc_register_remote_control(firesat
);
669 #if 0 /* FIXME: unused */
670 int avc_tuner_host2ca(struct firesat
*firesat
)
675 memset(&CmdFrm
, 0, sizeof(AVCCmdFrm
));
677 CmdFrm
.ctype
= CONTROL
;
679 CmdFrm
.suid
= firesat
->subunit
;
680 CmdFrm
.opcode
= VENDOR
;
682 CmdFrm
.operand
[0]=SFE_VENDOR_DE_COMPANYID_0
;
683 CmdFrm
.operand
[1]=SFE_VENDOR_DE_COMPANYID_1
;
684 CmdFrm
.operand
[2]=SFE_VENDOR_DE_COMPANYID_2
;
685 CmdFrm
.operand
[3]=SFE_VENDOR_OPCODE_HOST2CA
;
686 CmdFrm
.operand
[4] = 0; // slot
687 CmdFrm
.operand
[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO
; // ca tag
688 CmdFrm
.operand
[6] = 0; // more/last
689 CmdFrm
.operand
[7] = 0; // length
692 if (avc_write(firesat
, &CmdFrm
, &RspFrm
) < 0)
699 static int get_ca_object_pos(AVCRspFrm
*RspFrm
)
703 /* Check length of length field */
704 if (RspFrm
->operand
[7] & 0x80)
705 length
= (RspFrm
->operand
[7] & 0x7f) + 1;
709 static int get_ca_object_length(AVCRspFrm
*RspFrm
)
711 #if 0 /* FIXME: unused */
715 if (RspFrm
->operand
[7] & 0x80)
716 for (i
= 0; i
< (RspFrm
->operand
[7] & 0x7f); i
++) {
718 size
+= RspFrm
->operand
[8 + i
];
721 return RspFrm
->operand
[7];
724 int avc_ca_app_info(struct firesat
*firesat
, char *app_info
, unsigned int *len
)
730 memset(&CmdFrm
, 0, sizeof(AVCCmdFrm
));
732 CmdFrm
.ctype
= STATUS
;
734 CmdFrm
.suid
= firesat
->subunit
;
735 CmdFrm
.opcode
= VENDOR
;
737 CmdFrm
.operand
[0]=SFE_VENDOR_DE_COMPANYID_0
;
738 CmdFrm
.operand
[1]=SFE_VENDOR_DE_COMPANYID_1
;
739 CmdFrm
.operand
[2]=SFE_VENDOR_DE_COMPANYID_2
;
740 CmdFrm
.operand
[3]=SFE_VENDOR_OPCODE_CA2HOST
;
741 CmdFrm
.operand
[4] = 0; // slot
742 CmdFrm
.operand
[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO
; // ca tag
745 if (avc_write(firesat
, &CmdFrm
, &RspFrm
) < 0)
748 /* FIXME: check response code and validate response data */
750 pos
= get_ca_object_pos(&RspFrm
);
751 app_info
[0] = (TAG_APP_INFO
>> 16) & 0xFF;
752 app_info
[1] = (TAG_APP_INFO
>> 8) & 0xFF;
753 app_info
[2] = (TAG_APP_INFO
>> 0) & 0xFF;
754 app_info
[3] = 6 + RspFrm
.operand
[pos
+ 4];
756 memcpy(&app_info
[5], &RspFrm
.operand
[pos
], 5 + RspFrm
.operand
[pos
+ 4]);
757 *len
= app_info
[3] + 4;
762 int avc_ca_info(struct firesat
*firesat
, char *app_info
, unsigned int *len
)
768 memset(&CmdFrm
, 0, sizeof(AVCCmdFrm
));
770 CmdFrm
.ctype
= STATUS
;
772 CmdFrm
.suid
= firesat
->subunit
;
773 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_CA2HOST
;
779 CmdFrm
.operand
[4] = 0; // slot
780 CmdFrm
.operand
[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO
; // ca tag
783 if (avc_write(firesat
, &CmdFrm
, &RspFrm
) < 0)
786 pos
= get_ca_object_pos(&RspFrm
);
787 app_info
[0] = (TAG_CA_INFO
>> 16) & 0xFF;
788 app_info
[1] = (TAG_CA_INFO
>> 8) & 0xFF;
789 app_info
[2] = (TAG_CA_INFO
>> 0) & 0xFF;
791 app_info
[4] = RspFrm
.operand
[pos
+ 0];
792 app_info
[5] = RspFrm
.operand
[pos
+ 1];
793 *len
= app_info
[3] + 4;
798 int avc_ca_reset(struct firesat
*firesat
)
803 memset(&CmdFrm
, 0, sizeof(AVCCmdFrm
));
805 CmdFrm
.ctype
= CONTROL
;
807 CmdFrm
.suid
= firesat
->subunit
;
808 CmdFrm
.opcode
= VENDOR
;
810 CmdFrm
.operand
[0]=SFE_VENDOR_DE_COMPANYID_0
;
811 CmdFrm
.operand
[1]=SFE_VENDOR_DE_COMPANYID_1
;
812 CmdFrm
.operand
[2]=SFE_VENDOR_DE_COMPANYID_2
;
813 CmdFrm
.operand
[3]=SFE_VENDOR_OPCODE_HOST2CA
;
814 CmdFrm
.operand
[4] = 0; // slot
815 CmdFrm
.operand
[5] = SFE_VENDOR_TAG_CA_RESET
; // ca tag
816 CmdFrm
.operand
[6] = 0; // more/last
817 CmdFrm
.operand
[7] = 1; // length
818 CmdFrm
.operand
[8] = 0; // force hardware reset
821 if (avc_write(firesat
, &CmdFrm
, &RspFrm
) < 0)
827 int avc_ca_pmt(struct firesat
*firesat
, char *msg
, int length
)
832 int program_info_length
;
839 memset(&CmdFrm
, 0, sizeof(AVCCmdFrm
));
841 CmdFrm
.ctype
= CONTROL
;
843 CmdFrm
.suid
= firesat
->subunit
;
844 CmdFrm
.opcode
= VENDOR
;
846 if (msg
[0] != LIST_MANAGEMENT_ONLY
) {
847 dev_info(&firesat
->ud
->device
,
848 "forcing list_management to ONLY\n");
849 msg
[0] = LIST_MANAGEMENT_ONLY
;
851 // We take the cmd_id from the programme level only!
852 list_management
= msg
[0];
853 program_info_length
= ((msg
[4] & 0x0F) << 8) + msg
[5];
854 if (program_info_length
> 0)
855 program_info_length
--; // Remove pmt_cmd_id
858 CmdFrm
.operand
[0]=SFE_VENDOR_DE_COMPANYID_0
;
859 CmdFrm
.operand
[1]=SFE_VENDOR_DE_COMPANYID_1
;
860 CmdFrm
.operand
[2]=SFE_VENDOR_DE_COMPANYID_2
;
861 CmdFrm
.operand
[3]=SFE_VENDOR_OPCODE_HOST2CA
;
862 CmdFrm
.operand
[4] = 0; // slot
863 CmdFrm
.operand
[5] = SFE_VENDOR_TAG_CA_PMT
; // ca tag
864 CmdFrm
.operand
[6] = 0; // more/last
865 //CmdFrm.operand[7] = XXXprogram_info_length + 17; // length
866 CmdFrm
.operand
[8] = list_management
;
867 CmdFrm
.operand
[9] = 0x01; // pmt_cmd=OK_descramble
869 // TS program map table
872 CmdFrm
.operand
[10] = 0x02;
873 // Section syntax + length
874 CmdFrm
.operand
[11] = 0x80;
875 //CmdFrm.operand[12] = XXXprogram_info_length + 12;
877 CmdFrm
.operand
[13] = msg
[1];
878 CmdFrm
.operand
[14] = msg
[2];
879 // Version number=0 + current/next=1
880 CmdFrm
.operand
[15] = 0x01;
882 CmdFrm
.operand
[16] = 0x00;
883 // Last section number=0
884 CmdFrm
.operand
[17] = 0x00;
886 CmdFrm
.operand
[18] = 0x1F;
887 CmdFrm
.operand
[19] = 0xFF;
888 // Program info length
889 CmdFrm
.operand
[20] = (program_info_length
>> 8);
890 CmdFrm
.operand
[21] = (program_info_length
& 0xFF);
891 // CA descriptors at programme level
894 if (program_info_length
> 0) {
895 pmt_cmd_id
= msg
[read_pos
++];
896 if (pmt_cmd_id
!= 1 && pmt_cmd_id
!= 4)
897 dev_err(&firesat
->ud
->device
,
898 "invalid pmt_cmd_id %d\n", pmt_cmd_id
);
900 memcpy(&CmdFrm
.operand
[write_pos
], &msg
[read_pos
],
901 program_info_length
);
902 read_pos
+= program_info_length
;
903 write_pos
+= program_info_length
;
905 while (read_pos
< length
) {
906 CmdFrm
.operand
[write_pos
++] = msg
[read_pos
++];
907 CmdFrm
.operand
[write_pos
++] = msg
[read_pos
++];
908 CmdFrm
.operand
[write_pos
++] = msg
[read_pos
++];
910 ((msg
[read_pos
] & 0x0F) << 8) + msg
[read_pos
+ 1];
912 if (es_info_length
> 0)
913 es_info_length
--; // Remove pmt_cmd_id
914 CmdFrm
.operand
[write_pos
++] = es_info_length
>> 8;
915 CmdFrm
.operand
[write_pos
++] = es_info_length
& 0xFF;
916 if (es_info_length
> 0) {
917 pmt_cmd_id
= msg
[read_pos
++];
918 if (pmt_cmd_id
!= 1 && pmt_cmd_id
!= 4)
919 dev_err(&firesat
->ud
->device
,
920 "invalid pmt_cmd_id %d "
921 "at stream level\n", pmt_cmd_id
);
923 memcpy(&CmdFrm
.operand
[write_pos
], &msg
[read_pos
],
925 read_pos
+= es_info_length
;
926 write_pos
+= es_info_length
;
931 CmdFrm
.operand
[write_pos
++] = 0x00;
932 CmdFrm
.operand
[write_pos
++] = 0x00;
933 CmdFrm
.operand
[write_pos
++] = 0x00;
934 CmdFrm
.operand
[write_pos
++] = 0x00;
936 CmdFrm
.operand
[7] = write_pos
- 8;
937 CmdFrm
.operand
[12] = write_pos
- 13;
939 crc32_csum
= crc32_be(0, &CmdFrm
.operand
[10],
940 CmdFrm
.operand
[12] - 1);
941 CmdFrm
.operand
[write_pos
- 4] = (crc32_csum
>> 24) & 0xFF;
942 CmdFrm
.operand
[write_pos
- 3] = (crc32_csum
>> 16) & 0xFF;
943 CmdFrm
.operand
[write_pos
- 2] = (crc32_csum
>> 8) & 0xFF;
944 CmdFrm
.operand
[write_pos
- 1] = (crc32_csum
>> 0) & 0xFF;
946 CmdFrm
.length
= ALIGN(3 + write_pos
, 4);
948 if (avc_write(firesat
, &CmdFrm
, &RspFrm
) < 0)
951 if (RspFrm
.resp
!= ACCEPTED
) {
952 dev_err(&firesat
->ud
->device
,
953 "CA PMT failed with response 0x%x\n", RspFrm
.resp
);
960 int avc_ca_get_time_date(struct firesat
*firesat
, int *interval
)
965 memset(&CmdFrm
, 0, sizeof(AVCCmdFrm
));
967 CmdFrm
.ctype
= STATUS
;
969 CmdFrm
.suid
= firesat
->subunit
;
970 CmdFrm
.opcode
= VENDOR
;
972 CmdFrm
.operand
[0]=SFE_VENDOR_DE_COMPANYID_0
;
973 CmdFrm
.operand
[1]=SFE_VENDOR_DE_COMPANYID_1
;
974 CmdFrm
.operand
[2]=SFE_VENDOR_DE_COMPANYID_2
;
975 CmdFrm
.operand
[3]=SFE_VENDOR_OPCODE_CA2HOST
;
976 CmdFrm
.operand
[4] = 0; // slot
977 CmdFrm
.operand
[5] = SFE_VENDOR_TAG_CA_DATE_TIME
; // ca tag
978 CmdFrm
.operand
[6] = 0; // more/last
979 CmdFrm
.operand
[7] = 0; // length
982 if (avc_write(firesat
, &CmdFrm
, &RspFrm
) < 0)
985 /* FIXME: check response code and validate response data */
987 *interval
= RspFrm
.operand
[get_ca_object_pos(&RspFrm
)];
992 int avc_ca_enter_menu(struct firesat
*firesat
)
997 memset(&CmdFrm
, 0, sizeof(AVCCmdFrm
));
999 CmdFrm
.ctype
= STATUS
;
1001 CmdFrm
.suid
= firesat
->subunit
;
1002 CmdFrm
.opcode
= VENDOR
;
1004 CmdFrm
.operand
[0]=SFE_VENDOR_DE_COMPANYID_0
;
1005 CmdFrm
.operand
[1]=SFE_VENDOR_DE_COMPANYID_1
;
1006 CmdFrm
.operand
[2]=SFE_VENDOR_DE_COMPANYID_2
;
1007 CmdFrm
.operand
[3]=SFE_VENDOR_OPCODE_HOST2CA
;
1008 CmdFrm
.operand
[4] = 0; // slot
1009 CmdFrm
.operand
[5] = SFE_VENDOR_TAG_CA_ENTER_MENU
;
1010 CmdFrm
.operand
[6] = 0; // more/last
1011 CmdFrm
.operand
[7] = 0; // length
1014 if (avc_write(firesat
, &CmdFrm
, &RspFrm
) < 0)
1020 int avc_ca_get_mmi(struct firesat
*firesat
, char *mmi_object
, unsigned int *len
)
1025 memset(&CmdFrm
, 0, sizeof(AVCCmdFrm
));
1027 CmdFrm
.ctype
= STATUS
;
1029 CmdFrm
.suid
= firesat
->subunit
;
1030 CmdFrm
.opcode
= VENDOR
;
1032 CmdFrm
.operand
[0]=SFE_VENDOR_DE_COMPANYID_0
;
1033 CmdFrm
.operand
[1]=SFE_VENDOR_DE_COMPANYID_1
;
1034 CmdFrm
.operand
[2]=SFE_VENDOR_DE_COMPANYID_2
;
1035 CmdFrm
.operand
[3]=SFE_VENDOR_OPCODE_CA2HOST
;
1036 CmdFrm
.operand
[4] = 0; // slot
1037 CmdFrm
.operand
[5] = SFE_VENDOR_TAG_CA_MMI
;
1038 CmdFrm
.operand
[6] = 0; // more/last
1039 CmdFrm
.operand
[7] = 0; // length
1042 if (avc_write(firesat
, &CmdFrm
, &RspFrm
) < 0)
1045 /* FIXME: check response code and validate response data */
1047 *len
= get_ca_object_length(&RspFrm
);
1048 memcpy(mmi_object
, &RspFrm
.operand
[get_ca_object_pos(&RspFrm
)], *len
);