diff options
-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: |