aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/dvb/bt8xx/dst_ca.c96
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
71static 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
72static void put_checksum(u8 *check_string, int length) 79static 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
141static int ca_get_app_info(struct dst_state *state) 151static 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
189static 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 }
555free_mem_and_exit: 643free_mem_and_exit: