[linux-dvb] [PATCH] dst_ca: ca_info and application_info
Henrik Sjoberg
hsjo at epact.se
Mon Jan 9 14:33:51 CET 2006
Hi,
Today, application info can be enquired from the dst_ca ca using the ioctl
CA_APP_INFO_ENQUIRY. However, the answer which is returned is the raw data
of the answer from the HW and not formatted as described in EN-50221.
(Which is probably why there is a "only for debugging"-comment in the
code).
I have made patch which
1. Restructures the answer from CA_APP_INFO_ENQUIRY to conform with
application_info (EN50221:1997, p.28).
2. Adds support for CA Info Enquiry, conforming to EN50221:1997, p.29.
Since this will break dst_test -a, a patch is also needed for dvb-apps to
correct dst_test for application info and add support for ca info.
It would be great if anyone more familiar with the specs. could take a
look at it and see if it looks ok. It would also be good to have some
testing from some Twinhan CI-card users as well.
Regards,
Henrik
First, the patch for the driver (v4l-dvb):
Signed-off-by: Henrik Sjöberg <henke at epact.se>
Index: linux/drivers/media/dvb/bt8xx/dst_ca.c
===================================================================
RCS file: /cvs/video4linux/v4l-dvb/linux/drivers/media/dvb/bt8xx/dst_ca.c,v
retrieving revision 1.19
diff -p -u -b -r1.19 dst_ca.c
--- linux/drivers/media/dvb/bt8xx/dst_ca.c 27 Dec 2005 00:43:05 -0000
1.19
+++ linux/drivers/media/dvb/bt8xx/dst_ca.c 9 Jan 2006 12:57:29 -0000
@@ -141,6 +144,7 @@ static int dst_put_ci(struct dst_state *
static int ca_get_app_info(struct dst_state *state)
{
static u8 command[8] = {0x07, 0x40, 0x01, 0x00, 0x01, 0x00, 0x00,
0xff};
+ int i, length, str_length;
put_checksum(&command[0], command[0]);
if ((dst_put_ci(state, command, sizeof(command), state->messages,
GET_REPLY)) < 0) {
@@ -154,6 +158,72 @@ static int ca_get_app_info(struct dst_st
(state->messages[10] << 8) | state->messages[11],
__FUNCTION__, (char *)(&state->messages[12]));
dprintk(verbose, DST_CA_INFO, 1, "
=========================================================================
=========================");
+ // Transform dst message to correct application_info message
+ // according to EN50221
+ length = state->messages[5];
+ str_length = length - 6;
+
+ // First, the command and length fields
+ state->messages[0] = (CA_APP_INFO >> 16) & 0xff;
+ state->messages[1] = (CA_APP_INFO >> 8) & 0xff;
+ state->messages[2] = CA_APP_INFO & 0xff;
+ state->messages[3] = length;
+
+ // Copy application_type, application_manufacturer and
manufacturer_code
+ for (i = 0; i < 5; i++) {
+ state->messages[i + 4] = state->messages[i + 7];
+ }
+
+ // Set string length and copy string
+ state->messages[9] = str_length;
+ for (i = 0; i < length; i++) {
+ state->messages[10 + i] = state->messages[12 + i];
+ }
+
+ return 0;
+}
+
+static int ca_get_ca_info(struct dst_state *state)
+{
+ int srcPtr, dstPtr, i, num_ids;
+ static u8 slot_command[8] = {0x07, 0x40, 0x00, 0x00, 0x02, 0x00,
0x00, 0xff};
+ const int in_system_id_pos = 8, out_system_id_pos = 4,
in_num_ids_pos = 7;
+
+ put_checksum(&slot_command[0], slot_command[0]);
+ if ((dst_put_ci(state, slot_command, sizeof (slot_command),
state->messages, GET_REPLY)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
+ return -1;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
+
+ // Print raw data
+ dprintk(verbose, DST_CA_INFO, 0, " DST data = [");
+ for (i = 0; i < state->messages[0] + 1; i++) {
+ dprintk(verbose, DST_CA_INFO, 0, " 0x%02x",
state->messages[i]);
+ }
+ dprintk(verbose, DST_CA_INFO, 1, "]\n");
+
+ // Set the command and length of the output
+ num_ids = state->messages[in_num_ids_pos];
+ state->messages[0] = (CA_INFO >> 16) & 0xff;
+ state->messages[1] = (CA_INFO >> 8) & 0xff;
+ state->messages[2] = CA_INFO & 0xff;
+ state->messages[3] = num_ids * 2;
+
+ // Print and copy the system ids
+ dprintk(verbose, DST_CA_INFO, 0, " CA_INFO = [");
+ srcPtr = in_system_id_pos;
+ dstPtr = out_system_id_pos;
+ for(i = 0; i < num_ids; i++) {
+ dprintk(verbose, DST_CA_INFO, 0, " 0x%02x%02x",
state->messages[srcPtr + 0], state->messages[srcPtr
+ 1]);
+ // Append to output
+ state->messages[dstPtr + 0] = state->messages[srcPtr + 0];
+ state->messages[dstPtr + 1] = state->messages[srcPtr + 1];
+ srcPtr += 2;
+ dstPtr += 2;
+ }
+ dprintk(verbose, DST_CA_INFO, 0, "]\n");
+
return 0;
}
@@ -174,7 +244,7 @@ static int ca_get_slot_caps(struct dst_s
dprintk(verbose, DST_CA_INFO, 1, " Slot cap = [%d]", slot_cap[7]);
dprintk(verbose, DST_CA_INFO, 0,
"===================================\n");
- for (i = 0; i < 8; i++)
+ for (i = 0; i < slot_cap[0] + 1; i++)
dprintk(verbose, DST_CA_INFO, 0, " %d", slot_cap[i]);
dprintk(verbose, DST_CA_INFO, 0, "\n");
@@ -260,6 +330,11 @@ static int ca_get_message(struct dst_sta
if (copy_to_user(arg, p_ca_message, sizeof (struct
ca_msg)) )
return -EFAULT;
break;
+ case CA_INFO:
+ memcpy(p_ca_message->msg, state->messages, 128);
+ if (copy_to_user(arg, p_ca_message, sizeof (struct
ca_msg)) )
+ return -EFAULT;
+ break;
}
}
@@ -302,7 +377,7 @@ static int write_to_8820(struct dst_stat
rdc_reset_state(state);
return -1;
}
- dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command succes.");
+ dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command success.");
return 0;
}
@@ -455,6 +530,16 @@ static int ca_send_message(struct dst_st
}
dprintk(verbose, DST_CA_INFO, 1, "
-->CA_APP_INFO_ENQUIRY Success !");
break;
+ case CA_INFO_ENQUIRY:
+ dprintk(verbose, DST_CA_INFO, 1, " Getting Cam CA
information");
+
+ if ((ca_get_ca_info(state)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, "
-->CA_INFO_ENQUIRY Failed !");
+ result = -1;
+ goto free_mem_and_exit;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, "
-->CA_INFO_ENQUIRY Success !");
+ break;
}
}
free_mem_and_exit:
Second, the patch for dvb-apps:
Index: util/dst-utils/dst_test.c
===================================================================
RCS file: /cvs/linuxtv/dvb-apps/util/dst-utils/dst_test.c,v
retrieving revision 1.1
diff -p -u -b -r1.1 dst_test.c
--- util/dst-utils/dst_test.c 22 Jun 2005 16:10:25 -0000 1.1
+++ util/dst-utils/dst_test.c 9 Jan 2006 13:02:41 -0000
@@ -160,15 +160,51 @@ static int dst_get_app_info(int cafd, st
}
/* Process */
+ // Make sure we are null terminated
+ msg->msg[10 + msg->msg[9]] = 0;
+
+ printf("\n");
printf("%s: ================================ CI Module Application
Info ====================================
==\n", __FUNCTION__);
printf("%s: Application Type=[%d], Application Vendor=[%d], Vendor
Code=[%d]\n%s: Application info=[%s]\n",
- __FUNCTION__, msg->msg[7], (msg->msg[8] << 8) |
msg->msg[9], (msg->msg[10] << 8) | msg->msg[
11], __FUNCTION__,
- ((char *) (&msg->msg[12])));
+ __FUNCTION__, msg->msg[4], (msg->msg[5] << 8) |
msg->msg[6], (msg->msg[7] << 8) | msg->msg[8], __FUNC
TION__,
+ ((char *) (&msg->msg[10])));
printf("%s:
================================================================================================
==\n", __FUNCTION__);
return 0;
}
+static int dst_get_ca_info(int cafd, struct ca_msg *msg)
+{
+ uint32_t tag = 0;
+ int ptr = 4;
+
+ /* Enquire */
+ tag = CA_INFO_ENQUIRY;
+ if ((dst_comms(cafd, tag, CA_SEND_MSG, msg)) < 0) {
+ printf("%s: Dst communication failed\n", __FUNCTION__);
+ return -1;
+ }
+
+ /* Receive */
+ tag = CA_INFO;
+ if ((dst_comms(cafd, tag, CA_GET_MSG, msg)) < 0) {
+ printf("%s: Dst communication failed\n", __FUNCTION__);
+ return -1;
+ }
+
+ /* Process */
+ printf("%s: ================================ CI Module CA Info
======================================\n", __
FUNCTION__);
+ printf("%s: CA System IDs=[", __FUNCTION__);
+
+ while (ptr < (msg->msg[3] + 4)) {
+ printf("0x%02x%02x ", msg->msg[ptr + 0], msg->msg[ptr + 1]);
+ ptr += 2;
+ }
+ printf("]\n%s:
=============================================================================================
=====\n", __FUNCTION__);
+
+ return 0;
+}
+
static int dst_session_test(int cafd, struct ca_msg *msg)
{
msg->msg[0] = 0x91;
@@ -196,7 +232,8 @@ int main(int argc, char *argv[])
"\t -g get descr\n"
"\t -s set_descr\n"
"\t -a app_info\n"
- "\t -t session test\n";
+ "\t -t session test\n"
+ "\t -b ca_info\n";
struct ca_caps *caps;
@@ -217,7 +254,7 @@ int main(int argc, char *argv[])
return -1;
}
- switch (getopt(argc, argv, "cirpgsat")) {
+ switch (getopt(argc, argv, "cirpgsatb")) {
case 'c':
printf("%s: Capabilities\n", __FUNCTION__);
dst_get_caps(cafd, caps);
@@ -246,6 +283,10 @@ int main(int argc, char *argv[])
printf("%s: App Info\n", __FUNCTION__);
dst_get_app_info(cafd, msg);
break;
+ case 'b':
+ printf("%s: CA Info\n", __FUNCTION__);
+ dst_get_ca_info(cafd, msg);
+ break;
case 't':
printf("%s: Session test\n", __FUNCTION__);
dst_session_test(cafd, msg);
More information about the linux-dvb
mailing list