[linux-dvb] [PATCH] dst_ca: ca_info and application_info

Sigmund Augdal Helberg sigmund at snap.tv
Mon Jan 9 15:09:07 CET 2006


On Mon, 2006-01-09 at 14:33 +0100, Henrik Sjoberg wrote:
> 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.
I'm really happy to see someone pick up on the twinhan ci code. As soon
as I find some time I will try this out and proof-read the code
somewhat. And if it turns out to be correct I'll update vlc to handle
the correct app info, and use the ca info as well. 

Where did you get the magic command? And do you have commands for
remaining en50221 objects? I'm particularly interrested in the mmi
parts.

Regards,
Sigmund
> 
> 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);
> 
> 
> 
> _______________________________________________
> linux-dvb mailing list
> linux-dvb at linuxtv.org
> http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb




More information about the linux-dvb mailing list