diff options
Diffstat (limited to 'drivers/media/dvb/bt8xx/dst_ca.c')
-rw-r--r-- | drivers/media/dvb/bt8xx/dst_ca.c | 116 |
1 files changed, 101 insertions, 15 deletions
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c index f6b49a801eba..fa923b9b346e 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 | } |
@@ -340,6 +418,7 @@ static int debug_string(u8 *msg, u32 length, u32 offset) | |||
340 | return 0; | 418 | return 0; |
341 | } | 419 | } |
342 | 420 | ||
421 | |||
343 | static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query) | 422 | static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query) |
344 | { | 423 | { |
345 | u32 length = 0; | 424 | u32 length = 0; |
@@ -455,6 +534,16 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, | |||
455 | } | 534 | } |
456 | dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !"); | 535 | dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !"); |
457 | break; | 536 | break; |
537 | case CA_INFO_ENQUIRY: | ||
538 | dprintk(verbose, DST_CA_INFO, 1, " Getting CA Information"); | ||
539 | |||
540 | if ((ca_get_ca_info(state)) < 0) { | ||
541 | dprintk(verbose, DST_CA_ERROR, 1, " -->CA_INFO_ENQUIRY Failed !"); | ||
542 | result = -1; | ||
543 | goto free_mem_and_exit; | ||
544 | } | ||
545 | dprintk(verbose, DST_CA_INFO, 1, " -->CA_INFO_ENQUIRY Success !"); | ||
546 | break; | ||
458 | } | 547 | } |
459 | } | 548 | } |
460 | free_mem_and_exit: | 549 | free_mem_and_exit: |
@@ -473,18 +562,15 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
473 | void __user *arg = (void __user *)ioctl_arg; | 562 | void __user *arg = (void __user *)ioctl_arg; |
474 | int result = 0; | 563 | int result = 0; |
475 | 564 | ||
476 | if ((p_ca_message = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) { | 565 | p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL); |
477 | dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); | 566 | p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL); |
478 | return -ENOMEM; | 567 | p_ca_caps = kmalloc(sizeof (struct ca_caps), GFP_KERNEL); |
479 | } | 568 | if (!p_ca_message || !p_ca_slot_info || !p_ca_caps) { |
480 | if ((p_ca_slot_info = (struct ca_slot_info *) kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL)) == NULL) { | ||
481 | dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); | 569 | dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); |
482 | return -ENOMEM; | 570 | result = -ENOMEM; |
483 | } | 571 | goto free_mem_and_exit; |
484 | if ((p_ca_caps = (struct ca_caps *) kmalloc(sizeof (struct ca_caps), GFP_KERNEL)) == NULL) { | ||
485 | dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); | ||
486 | return -ENOMEM; | ||
487 | } | 572 | } |
573 | |||
488 | /* We have now only the standard ioctl's, the driver is upposed to handle internals. */ | 574 | /* We have now only the standard ioctl's, the driver is upposed to handle internals. */ |
489 | switch (cmd) { | 575 | switch (cmd) { |
490 | case CA_SEND_MSG: | 576 | case CA_SEND_MSG: |
@@ -582,7 +668,7 @@ static int dst_ca_release(struct inode *inode, struct file *file) | |||
582 | 668 | ||
583 | static ssize_t dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset) | 669 | static ssize_t dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset) |
584 | { | 670 | { |
585 | int bytes_read = 0; | 671 | ssize_t bytes_read = 0; |
586 | 672 | ||
587 | dprintk(verbose, DST_CA_DEBUG, 1, " Device read."); | 673 | dprintk(verbose, DST_CA_DEBUG, 1, " Device read."); |
588 | 674 | ||