diff options
| author | Henrik Sjoberg <hsjo@epact.se> | 2006-06-21 15:33:21 -0400 |
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-06-25 01:05:20 -0400 |
| commit | 1f19456d9760431f3a888b21fff035f875ddd189 (patch) | |
| tree | 4c699f84ad532ebd9e84ed20d112469c1e594552 /drivers/media/dvb | |
| parent | 3e357fd8a29cbcf91badd2a6d3b8ef5d4cb05025 (diff) | |
V4L/DVB (4181): Fix CA Info and Application Info
Signed-off-by: Henrik Sjoberg <hsjo@epact.se>
Signed-off-by: Manu Abraham <manu@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/dvb')
| -rw-r--r-- | drivers/media/dvb/bt8xx/dst_ca.c | 96 |
1 files changed, 92 insertions, 4 deletions
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c index cc517c553ac5..baa8c9aa212b 100644 --- a/drivers/media/dvb/bt8xx/dst_ca.c +++ b/drivers/media/dvb/bt8xx/dst_ca.c | |||
| @@ -68,6 +68,13 @@ static int ca_set_pid(void) | |||
| 68 | return -EOPNOTSUPP; | 68 | return -EOPNOTSUPP; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | static void put_command_and_length(u8 *data, int command, int length) | ||
| 72 | { | ||
| 73 | data[0] = (command >> 16) & 0xff; | ||
| 74 | data[1] = (command >> 8) & 0xff; | ||
| 75 | data[2] = command & 0xff; | ||
| 76 | data[3] = length; | ||
| 77 | } | ||
| 71 | 78 | ||
| 72 | static void put_checksum(u8 *check_string, int length) | 79 | static void put_checksum(u8 *check_string, int length) |
| 73 | { | 80 | { |
| @@ -124,15 +131,18 @@ static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string, | |||
| 124 | u8 dst_ca_comm_err = 0; | 131 | u8 dst_ca_comm_err = 0; |
| 125 | 132 | ||
| 126 | while (dst_ca_comm_err < RETRIES) { | 133 | while (dst_ca_comm_err < RETRIES) { |
| 127 | dst_comm_init(state); | ||
| 128 | dprintk(verbose, DST_CA_NOTICE, 1, " Put Command"); | 134 | dprintk(verbose, DST_CA_NOTICE, 1, " Put Command"); |
| 129 | if (dst_ci_command(state, data, ca_string, len, read)) { // If error | 135 | if (dst_ci_command(state, data, ca_string, len, read)) { // If error |
| 130 | dst_error_recovery(state); | 136 | dst_error_recovery(state); |
| 131 | dst_ca_comm_err++; // work required here. | 137 | dst_ca_comm_err++; // work required here. |
| 138 | } else { | ||
| 139 | break; | ||
| 132 | } | 140 | } |
| 133 | break; | ||
| 134 | } | 141 | } |
| 135 | 142 | ||
| 143 | if(dst_ca_comm_err == RETRIES) | ||
| 144 | return -1; | ||
| 145 | |||
| 136 | return 0; | 146 | return 0; |
| 137 | } | 147 | } |
| 138 | 148 | ||
| @@ -140,6 +150,7 @@ static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string, | |||
| 140 | 150 | ||
| 141 | static int ca_get_app_info(struct dst_state *state) | 151 | static int ca_get_app_info(struct dst_state *state) |
| 142 | { | 152 | { |
| 153 | int length, str_length; | ||
| 143 | static u8 command[8] = {0x07, 0x40, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff}; | 154 | static u8 command[8] = {0x07, 0x40, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff}; |
| 144 | 155 | ||
| 145 | put_checksum(&command[0], command[0]); | 156 | put_checksum(&command[0], command[0]); |
| @@ -154,6 +165,68 @@ static int ca_get_app_info(struct dst_state *state) | |||
| 154 | (state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12])); | 165 | (state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12])); |
| 155 | dprintk(verbose, DST_CA_INFO, 1, " =================================================================================================="); | 166 | dprintk(verbose, DST_CA_INFO, 1, " =================================================================================================="); |
| 156 | 167 | ||
| 168 | // Transform dst message to correct application_info message | ||
| 169 | length = state->messages[5]; | ||
| 170 | str_length = length - 6; | ||
| 171 | if (str_length < 0) { | ||
| 172 | str_length = 0; | ||
| 173 | dprintk(verbose, DST_CA_ERROR, 1, "Invalid string length returned in ca_get_app_info(). Recovering."); | ||
| 174 | } | ||
| 175 | |||
| 176 | // First, the command and length fields | ||
| 177 | put_command_and_length(&state->messages[0], CA_APP_INFO, length); | ||
| 178 | |||
| 179 | // Copy application_type, application_manufacturer and manufacturer_code | ||
| 180 | memcpy(&state->messages[4], &state->messages[7], 5); | ||
| 181 | |||
| 182 | // Set string length and copy string | ||
| 183 | state->messages[9] = str_length; | ||
| 184 | memcpy(&state->messages[10], &state->messages[12], str_length); | ||
| 185 | |||
| 186 | return 0; | ||
| 187 | } | ||
| 188 | |||
| 189 | static int ca_get_ca_info(struct dst_state *state) | ||
| 190 | { | ||
| 191 | int srcPtr, dstPtr, i, num_ids; | ||
| 192 | static u8 slot_command[8] = {0x07, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0xff}; | ||
| 193 | const int in_system_id_pos = 8, out_system_id_pos = 4, in_num_ids_pos = 7; | ||
| 194 | |||
| 195 | put_checksum(&slot_command[0], slot_command[0]); | ||
| 196 | if ((dst_put_ci(state, slot_command, sizeof (slot_command), state->messages, GET_REPLY)) < 0) { | ||
| 197 | dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !"); | ||
| 198 | return -1; | ||
| 199 | } | ||
| 200 | dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !"); | ||
| 201 | |||
| 202 | // Print raw data | ||
| 203 | dprintk(verbose, DST_CA_INFO, 0, " DST data = ["); | ||
| 204 | for (i = 0; i < state->messages[0] + 1; i++) { | ||
| 205 | dprintk(verbose, DST_CA_INFO, 0, " 0x%02x", state->messages[i]); | ||
| 206 | } | ||
| 207 | dprintk(verbose, DST_CA_INFO, 0, "]\n"); | ||
| 208 | |||
| 209 | // Set the command and length of the output | ||
| 210 | num_ids = state->messages[in_num_ids_pos]; | ||
| 211 | if (num_ids >= 100) { | ||
| 212 | num_ids = 100; | ||
| 213 | dprintk(verbose, DST_CA_ERROR, 1, "Invalid number of ids (>100). Recovering."); | ||
| 214 | } | ||
| 215 | put_command_and_length(&state->messages[0], CA_INFO, num_ids * 2); | ||
| 216 | |||
| 217 | dprintk(verbose, DST_CA_INFO, 0, " CA_INFO = ["); | ||
| 218 | srcPtr = in_system_id_pos; | ||
| 219 | dstPtr = out_system_id_pos; | ||
| 220 | for(i = 0; i < num_ids; i++) { | ||
| 221 | dprintk(verbose, DST_CA_INFO, 0, " 0x%02x%02x", state->messages[srcPtr + 0], state->messages[srcPtr + 1]); | ||
| 222 | // Append to output | ||
| 223 | state->messages[dstPtr + 0] = state->messages[srcPtr + 0]; | ||
| 224 | state->messages[dstPtr + 1] = state->messages[srcPtr + 1]; | ||
| 225 | srcPtr += 2; | ||
| 226 | dstPtr += 2; | ||
| 227 | } | ||
| 228 | dprintk(verbose, DST_CA_INFO, 0, "]\n"); | ||
| 229 | |||
| 157 | return 0; | 230 | return 0; |
| 158 | } | 231 | } |
| 159 | 232 | ||
| @@ -174,7 +247,7 @@ static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps, | |||
| 174 | 247 | ||
| 175 | dprintk(verbose, DST_CA_INFO, 1, " Slot cap = [%d]", slot_cap[7]); | 248 | dprintk(verbose, DST_CA_INFO, 1, " Slot cap = [%d]", slot_cap[7]); |
| 176 | dprintk(verbose, DST_CA_INFO, 0, "===================================\n"); | 249 | dprintk(verbose, DST_CA_INFO, 0, "===================================\n"); |
| 177 | for (i = 0; i < 8; i++) | 250 | for (i = 0; i < slot_cap[0] + 1; i++) |
| 178 | dprintk(verbose, DST_CA_INFO, 0, " %d", slot_cap[i]); | 251 | dprintk(verbose, DST_CA_INFO, 0, " %d", slot_cap[i]); |
| 179 | dprintk(verbose, DST_CA_INFO, 0, "\n"); | 252 | dprintk(verbose, DST_CA_INFO, 0, "\n"); |
| 180 | 253 | ||
| @@ -260,6 +333,11 @@ static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message, | |||
| 260 | if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) ) | 333 | if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) ) |
| 261 | return -EFAULT; | 334 | return -EFAULT; |
| 262 | break; | 335 | break; |
| 336 | case CA_INFO: | ||
| 337 | memcpy(p_ca_message->msg, state->messages, 128); | ||
| 338 | if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) ) | ||
| 339 | return -EFAULT; | ||
| 340 | break; | ||
| 263 | } | 341 | } |
| 264 | } | 342 | } |
| 265 | 343 | ||
| @@ -302,7 +380,7 @@ static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 l | |||
| 302 | rdc_reset_state(state); | 380 | rdc_reset_state(state); |
| 303 | return -1; | 381 | return -1; |
| 304 | } | 382 | } |
| 305 | dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command succes."); | 383 | dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command success."); |
| 306 | 384 | ||
| 307 | return 0; | 385 | return 0; |
| 308 | } | 386 | } |
| @@ -550,6 +628,16 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, | |||
| 550 | } | 628 | } |
| 551 | dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !"); | 629 | dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !"); |
| 552 | break; | 630 | break; |
| 631 | case CA_INFO_ENQUIRY: | ||
| 632 | dprintk(verbose, DST_CA_INFO, 1, " Getting CA Information"); | ||
| 633 | |||
| 634 | if ((ca_get_ca_info(state)) < 0) { | ||
| 635 | dprintk(verbose, DST_CA_ERROR, 1, " -->CA_INFO_ENQUIRY Failed !"); | ||
| 636 | result = -1; | ||
| 637 | goto free_mem_and_exit; | ||
| 638 | } | ||
| 639 | dprintk(verbose, DST_CA_INFO, 1, " -->CA_INFO_ENQUIRY Success !"); | ||
| 640 | break; | ||
| 553 | } | 641 | } |
| 554 | } | 642 | } |
| 555 | free_mem_and_exit: | 643 | free_mem_and_exit: |
