[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