blob: d2e0b1cb39d93a7a36b8dd1a5845c6684b48f570 [file] [log] [blame]
Johannes Stezenbach50b215a2005-05-16 21:54:41 -07001/*
2 CA-driver for TwinHan DST Frontend/Card
3
4 Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21
22
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/init.h>
26#include <linux/string.h>
27
28#include <linux/dvb/ca.h>
29#include "dvbdev.h"
30#include "dvb_frontend.h"
31
32#include "dst_ca.h"
33#include "dst_common.h"
34
Manu Abraham7d534212005-07-07 17:57:50 -070035static unsigned int verbose = 5;
Johannes Stezenbach50b215a2005-05-16 21:54:41 -070036module_param(verbose, int, 0644);
37MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
38
39static unsigned int debug = 1;
40module_param(debug, int, 0644);
Johannes Stezenbach42dc6612005-05-16 21:54:47 -070041MODULE_PARM_DESC(debug, "debug messages, default is 1 (yes)");
Johannes Stezenbach50b215a2005-05-16 21:54:41 -070042
Johannes Stezenbach50b215a2005-05-16 21:54:41 -070043#define dprintk if (debug) printk
44
Johannes Stezenbach4a2cc122005-05-16 21:54:45 -070045/* Need some more work */
Johannes Stezenbach50b215a2005-05-16 21:54:41 -070046static int ca_set_slot_descr(void)
47{
48 /* We could make this more graceful ? */
49 return -EOPNOTSUPP;
50}
51
Johannes Stezenbach4a2cc122005-05-16 21:54:45 -070052/* Need some more work */
Johannes Stezenbach50b215a2005-05-16 21:54:41 -070053static int ca_set_pid(void)
54{
55 /* We could make this more graceful ? */
56 return -EOPNOTSUPP;
57}
58
59
60static int put_checksum(u8 *check_string, int length)
61{
62 u8 i = 0, checksum = 0;
63
64 if (verbose > 3) {
65 dprintk("%s: ========================= Checksum calculation ===========================\n", __FUNCTION__);
66 dprintk("%s: String Length=[0x%02x]\n", __FUNCTION__, length);
67
68 dprintk("%s: String=[", __FUNCTION__);
69 }
70 while (i < length) {
71 if (verbose > 3)
72 dprintk(" %02x", check_string[i]);
73 checksum += check_string[i];
74 i++;
75 }
76 if (verbose > 3) {
77 dprintk(" ]\n");
78 dprintk("%s: Sum=[%02x]\n", __FUNCTION__, checksum);
79 }
80 check_string[length] = ~checksum + 1;
81 if (verbose > 3) {
82 dprintk("%s: Checksum=[%02x]\n", __FUNCTION__, check_string[length]);
83 dprintk("%s: ==========================================================================\n", __FUNCTION__);
84 }
85
86 return 0;
87}
88
89static int dst_ci_command(struct dst_state* state, u8 * data, u8 *ca_string, u8 len, int read)
90{
91 u8 reply;
92
93 dst_comm_init(state);
94 msleep(65);
95
96 if (write_dst(state, data, len)) {
97 dprintk("%s: Write not successful, trying to recover\n", __FUNCTION__);
98 dst_error_recovery(state);
99 return -1;
100 }
101
102 if ((dst_pio_disable(state)) < 0) {
103 dprintk("%s: DST PIO disable failed.\n", __FUNCTION__);
104 return -1;
105 }
106
107 if (read_dst(state, &reply, GET_ACK) < 0) {
108 dprintk("%s: Read not successful, trying to recover\n", __FUNCTION__);
109 dst_error_recovery(state);
110 return -1;
111 }
112
113 if (read) {
114 if (! dst_wait_dst_ready(state, LONG_DELAY)) {
115 dprintk("%s: 8820 not ready\n", __FUNCTION__);
116 return -1;
117 }
118
119 if (read_dst(state, ca_string, 128) < 0) { /* Try to make this dynamic */
120 dprintk("%s: Read not successful, trying to recover\n", __FUNCTION__);
121 dst_error_recovery(state);
122 return -1;
123 }
124 }
125
126 return 0;
127}
128
129
130static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string, int read)
131{
132 u8 dst_ca_comm_err = 0;
133
134 while (dst_ca_comm_err < RETRIES) {
135 dst_comm_init(state);
136 if (verbose > 2)
137 dprintk("%s: Put Command\n", __FUNCTION__);
138 if (dst_ci_command(state, data, ca_string, len, read)) { // If error
139 dst_error_recovery(state);
140 dst_ca_comm_err++; // work required here.
141 }
142 break;
143 }
144
145 return 0;
146}
147
148
149
150static int ca_get_app_info(struct dst_state *state)
151{
152 static u8 command[8] = {0x07, 0x40, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff};
153
154 put_checksum(&command[0], command[0]);
155 if ((dst_put_ci(state, command, sizeof(command), state->messages, GET_REPLY)) < 0) {
156 dprintk("%s: -->dst_put_ci FAILED !\n", __FUNCTION__);
157 return -1;
158 }
159 if (verbose > 1) {
160 dprintk("%s: -->dst_put_ci SUCCESS !\n", __FUNCTION__);
161
162 dprintk("%s: ================================ CI Module Application Info ======================================\n", __FUNCTION__);
163 dprintk("%s: Application Type=[%d], Application Vendor=[%d], Vendor Code=[%d]\n%s: Application info=[%s]\n",
164 __FUNCTION__, state->messages[7], (state->messages[8] << 8) | state->messages[9],
Johannes Stezenbachb98b79d2005-05-16 21:54:47 -0700165 (state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12]));
Johannes Stezenbach50b215a2005-05-16 21:54:41 -0700166 dprintk("%s: ==================================================================================================\n", __FUNCTION__);
167 }
168
169 return 0;
170}
171
172static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps, void *arg)
173{
174 int i;
175 u8 slot_cap[256];
176 static u8 slot_command[8] = {0x07, 0x40, 0x02, 0x00, 0x02, 0x00, 0x00, 0xff};
177
178 put_checksum(&slot_command[0], slot_command[0]);
179 if ((dst_put_ci(state, slot_command, sizeof (slot_command), slot_cap, GET_REPLY)) < 0) {
180 dprintk("%s: -->dst_put_ci FAILED !\n", __FUNCTION__);
181 return -1;
182 }
183 if (verbose > 1)
184 dprintk("%s: -->dst_put_ci SUCCESS !\n", __FUNCTION__);
185
186 /* Will implement the rest soon */
187
188 if (verbose > 1) {
189 dprintk("%s: Slot cap = [%d]\n", __FUNCTION__, slot_cap[7]);
190 dprintk("===================================\n");
191 for (i = 0; i < 8; i++)
192 dprintk(" %d", slot_cap[i]);
193 dprintk("\n");
194 }
195
196 p_ca_caps->slot_num = 1;
197 p_ca_caps->slot_type = 1;
198 p_ca_caps->descr_num = slot_cap[7];
199 p_ca_caps->descr_type = 1;
200
201
202 if (copy_to_user((struct ca_caps *)arg, p_ca_caps, sizeof (struct ca_caps))) {
203 return -EFAULT;
204 }
205
206 return 0;
207}
208
Johannes Stezenbach4a2cc122005-05-16 21:54:45 -0700209/* Need some more work */
Johannes Stezenbach50b215a2005-05-16 21:54:41 -0700210static int ca_get_slot_descr(struct dst_state *state, struct ca_msg *p_ca_message, void *arg)
211{
212 return -EOPNOTSUPP;
213}
214
215
216static int ca_get_slot_info(struct dst_state *state, struct ca_slot_info *p_ca_slot_info, void *arg)
217{
218 int i;
219 static u8 slot_command[8] = {0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
220
221 u8 *slot_info = state->rxbuffer;
222
223 put_checksum(&slot_command[0], 7);
224 if ((dst_put_ci(state, slot_command, sizeof (slot_command), slot_info, GET_REPLY)) < 0) {
225 dprintk("%s: -->dst_put_ci FAILED !\n", __FUNCTION__);
226 return -1;
227 }
228 if (verbose > 1)
229 dprintk("%s: -->dst_put_ci SUCCESS !\n", __FUNCTION__);
230
231 /* Will implement the rest soon */
232
233 if (verbose > 1) {
234 dprintk("%s: Slot info = [%d]\n", __FUNCTION__, slot_info[3]);
235 dprintk("===================================\n");
236 for (i = 0; i < 8; i++)
237 dprintk(" %d", slot_info[i]);
238 dprintk("\n");
239 }
240
241 if (slot_info[4] & 0x80) {
242 p_ca_slot_info->flags = CA_CI_MODULE_PRESENT;
243 p_ca_slot_info->num = 1;
244 p_ca_slot_info->type = CA_CI;
245 }
246 else if (slot_info[4] & 0x40) {
247 p_ca_slot_info->flags = CA_CI_MODULE_READY;
248 p_ca_slot_info->num = 1;
249 p_ca_slot_info->type = CA_CI;
250 }
251 else {
252 p_ca_slot_info->flags = 0;
253 }
254
255 if (copy_to_user((struct ca_slot_info *)arg, p_ca_slot_info, sizeof (struct ca_slot_info))) {
256 return -EFAULT;
257 }
258
259 return 0;
260}
261
262
Johannes Stezenbach50b215a2005-05-16 21:54:41 -0700263static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message, void *arg)
264{
265 u8 i = 0;
266 u32 command = 0;
267
268 if (copy_from_user(p_ca_message, (void *)arg, sizeof (struct ca_msg)))
269 return -EFAULT;
270
271
272 if (p_ca_message->msg) {
273 if (verbose > 3)
274 dprintk("Message = [%02x %02x %02x]\n", p_ca_message->msg[0], p_ca_message->msg[1], p_ca_message->msg[2]);
275
276 for (i = 0; i < 3; i++) {
277 command = command | p_ca_message->msg[i];
278 if (i < 2)
279 command = command << 8;
280 }
281 if (verbose > 3)
282 dprintk("%s:Command=[0x%x]\n", __FUNCTION__, command);
283
284 switch (command) {
285 case CA_APP_INFO:
286 memcpy(p_ca_message->msg, state->messages, 128);
287 if (copy_to_user((void *)arg, p_ca_message, sizeof (struct ca_msg)) )
288 return -EFAULT;
289 break;
290 }
291 }
292
293 return 0;
294}
295
Manu Abraham7d534212005-07-07 17:57:50 -0700296static int handle_dst_tag(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u32 length)
Johannes Stezenbach50b215a2005-05-16 21:54:41 -0700297{
Johannes Stezenbach4a2cc122005-05-16 21:54:45 -0700298 if (state->dst_hw_cap & DST_TYPE_HAS_SESSION) {
Manu Abraham94b74102005-09-09 13:02:59 -0700299 hw_buffer->msg[2] = p_ca_message->msg[1]; /* MSB */
300 hw_buffer->msg[3] = p_ca_message->msg[2]; /* LSB */
301 } else {
302 if (length > 247) {
303 dprintk("%s: Message too long ! *** Bailing Out *** !\n", __FUNCTION__);
304 return -1;
305 }
306
Manu Abraham7d534212005-07-07 17:57:50 -0700307 hw_buffer->msg[0] = (length & 0xff) + 7;
308 hw_buffer->msg[1] = 0x40;
Johannes Stezenbach50b215a2005-05-16 21:54:41 -0700309 hw_buffer->msg[2] = 0x03;
310 hw_buffer->msg[3] = 0x00;
Manu Abraham7d534212005-07-07 17:57:50 -0700311 hw_buffer->msg[4] = 0x03;
312 hw_buffer->msg[5] = length & 0xff;
313 hw_buffer->msg[6] = 0x00;
Manu Abraham94b74102005-09-09 13:02:59 -0700314 /*
315 * Need to compute length for EN50221 section 8.3.2, for the time being
316 * assuming 8.3.2 is not applicable
317 */
318 memcpy(&hw_buffer->msg[7], &p_ca_message->msg[4], length);
Johannes Stezenbach50b215a2005-05-16 21:54:41 -0700319 }
320 return 0;
321}
322
Manu Abraham7d534212005-07-07 17:57:50 -0700323
324static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 length, u8 reply)
Johannes Stezenbach50b215a2005-05-16 21:54:41 -0700325{
Manu Abraham7d534212005-07-07 17:57:50 -0700326 if ((dst_put_ci(state, hw_buffer->msg, length, hw_buffer->msg, reply)) < 0) {
Johannes Stezenbach50b215a2005-05-16 21:54:41 -0700327 dprintk("%s: DST-CI Command failed.\n", __FUNCTION__);
328 dprintk("%s: Resetting DST.\n", __FUNCTION__);
329 rdc_reset_state(state);
330 return -1;
331 }
332 if (verbose > 2)
333 dprintk("%s: DST-CI Command succes.\n", __FUNCTION__);
334
335 return 0;
336}
337
Manu Abraham7d534212005-07-07 17:57:50 -0700338u32 asn_1_decode(u8 *asn_1_array)
Johannes Stezenbach50b215a2005-05-16 21:54:41 -0700339{
Manu Abraham7d534212005-07-07 17:57:50 -0700340 u8 length_field = 0, word_count = 0, count = 0;
341 u32 length = 0;
Johannes Stezenbach50b215a2005-05-16 21:54:41 -0700342
Manu Abraham7d534212005-07-07 17:57:50 -0700343 length_field = asn_1_array[0];
344 dprintk("%s: Length field=[%02x]\n", __FUNCTION__, length_field);
345 if (length_field < 0x80) {
346 length = length_field & 0x7f;
347 dprintk("%s: Length=[%02x]\n", __FUNCTION__, length);
348 } else {
349 word_count = length_field & 0x7f;
350 for (count = 0; count < word_count; count++) {
351 length = (length | asn_1_array[count + 1]) << 8;
352 dprintk("%s: Length=[%04x]\n", __FUNCTION__, length);
Johannes Stezenbach50b215a2005-05-16 21:54:41 -0700353 }
354 }
Manu Abraham7d534212005-07-07 17:57:50 -0700355 return length;
356}
Johannes Stezenbach50b215a2005-05-16 21:54:41 -0700357
Manu Abraham7d534212005-07-07 17:57:50 -0700358static int debug_string(u8 *msg, u32 length, u32 offset)
359{
360 u32 i;
361
362 dprintk(" String=[ ");
363 for (i = offset; i < length; i++)
364 dprintk("%02x ", msg[i]);
365 dprintk("]\n");
366
367 return 0;
368}
369
Manu Abraham7d534212005-07-07 17:57:50 -0700370static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query)
371{
Manu Abraham94b74102005-09-09 13:02:59 -0700372 u32 length = 0;
373 u8 tag_length = 8;
Manu Abraham7d534212005-07-07 17:57:50 -0700374
375 length = asn_1_decode(&p_ca_message->msg[3]);
376 dprintk("%s: CA Message length=[%d]\n", __FUNCTION__, length);
377 dprintk("%s: ASN.1 ", __FUNCTION__);
Manu Abraham94b74102005-09-09 13:02:59 -0700378 debug_string(&p_ca_message->msg[4], length, 0); /* length is excluding tag & length */
Manu Abraham7d534212005-07-07 17:57:50 -0700379
Manu Abraham94b74102005-09-09 13:02:59 -0700380 memset(hw_buffer->msg, '\0', length);
Manu Abraham7d534212005-07-07 17:57:50 -0700381 handle_dst_tag(state, p_ca_message, hw_buffer, length);
Manu Abraham94b74102005-09-09 13:02:59 -0700382 put_checksum(hw_buffer->msg, hw_buffer->msg[0]);
Manu Abraham7d534212005-07-07 17:57:50 -0700383
Manu Abraham94b74102005-09-09 13:02:59 -0700384 debug_string(hw_buffer->msg, (length + tag_length), 0); /* tags too */
385 write_to_8820(state, hw_buffer, (length + tag_length), reply);
Manu Abraham7d534212005-07-07 17:57:50 -0700386
387 return 0;
388}
389
390
Johannes Stezenbach50b215a2005-05-16 21:54:41 -0700391/* Board supports CA PMT reply ? */
392static int dst_check_ca_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer)
393{
394 int ca_pmt_reply_test = 0;
395
396 /* Do test board */
397 /* Not there yet but soon */
398
399
400 /* CA PMT Reply capable */
401 if (ca_pmt_reply_test) {
402 if ((ca_set_pmt(state, p_ca_message, hw_buffer, 1, GET_REPLY)) < 0) {
403 dprintk("%s: ca_set_pmt.. failed !\n", __FUNCTION__);
404 return -1;
405 }
406
407 /* Process CA PMT Reply */
408 /* will implement soon */
409 dprintk("%s: Not there yet\n", __FUNCTION__);
410 }
411 /* CA PMT Reply not capable */
412 if (!ca_pmt_reply_test) {
413 if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, NO_REPLY)) < 0) {
414 dprintk("%s: ca_set_pmt.. failed !\n", __FUNCTION__);
415 return -1;
416 }
417 if (verbose > 3)
418 dprintk("%s: ca_set_pmt.. success !\n", __FUNCTION__);
419 /* put a dummy message */
420
421 }
422 return 0;
423}
424
425static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, void *arg)
426{
427 int i = 0;
428 unsigned int ca_message_header_len;
429
430 u32 command = 0;
431 struct ca_msg *hw_buffer;
432
433 if ((hw_buffer = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
Manu Abraham7d534212005-07-07 17:57:50 -0700434 dprintk("%s: Memory allocation failure\n", __FUNCTION__);
Johannes Stezenbach50b215a2005-05-16 21:54:41 -0700435 return -ENOMEM;
436 }
437 if (verbose > 3)
438 dprintk("%s\n", __FUNCTION__);
439
440 if (copy_from_user(p_ca_message, (void *)arg, sizeof (struct ca_msg)))
441 return -EFAULT;
442
443 if (p_ca_message->msg) {
444 ca_message_header_len = p_ca_message->length; /* Restore it back when you are done */
445 /* EN50221 tag */
446 command = 0;
447
448 for (i = 0; i < 3; i++) {
449 command = command | p_ca_message->msg[i];
450 if (i < 2)
451 command = command << 8;
452 }
453 if (verbose > 3)
454 dprintk("%s:Command=[0x%x]\n", __FUNCTION__, command);
455
456 switch (command) {
457 case CA_PMT:
458 if (verbose > 3)
Manu Abraham7d534212005-07-07 17:57:50 -0700459// dprintk("Command = SEND_CA_PMT\n");
Johannes Stezenbach50b215a2005-05-16 21:54:41 -0700460 dprintk("Command = SEND_CA_PMT\n");
Manu Abraham7d534212005-07-07 17:57:50 -0700461// if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) {
462 if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) { // code simplification started
Johannes Stezenbach50b215a2005-05-16 21:54:41 -0700463 dprintk("%s: -->CA_PMT Failed !\n", __FUNCTION__);
464 return -1;
465 }
466 if (verbose > 3)
467 dprintk("%s: -->CA_PMT Success !\n", __FUNCTION__);
468// retval = dummy_set_pmt(state, p_ca_message, hw_buffer, 0, 0);
469
470 break;
471
472 case CA_PMT_REPLY:
473 if (verbose > 3)
474 dprintk("Command = CA_PMT_REPLY\n");
475 /* Have to handle the 2 basic types of cards here */
476 if ((dst_check_ca_pmt(state, p_ca_message, hw_buffer)) < 0) {
477 dprintk("%s: -->CA_PMT_REPLY Failed !\n", __FUNCTION__);
478 return -1;
479 }
480 if (verbose > 3)
481 dprintk("%s: -->CA_PMT_REPLY Success !\n", __FUNCTION__);
482
483 /* Certain boards do behave different ? */
484// retval = ca_set_pmt(state, p_ca_message, hw_buffer, 1, 1);
485
486 case CA_APP_INFO_ENQUIRY: // only for debugging
487 if (verbose > 3)
488 dprintk("%s: Getting Cam Application information\n", __FUNCTION__);
489
490 if ((ca_get_app_info(state)) < 0) {
491 dprintk("%s: -->CA_APP_INFO_ENQUIRY Failed !\n", __FUNCTION__);
492 return -1;
493 }
494 if (verbose > 3)
Manu Abraham7d534212005-07-07 17:57:50 -0700495 dprintk("%s: -->CA_APP_INFO_ENQUIRY Success !\n", __FUNCTION__);
Johannes Stezenbach50b215a2005-05-16 21:54:41 -0700496
497 break;
498 }
499 }
500 return 0;
501}
502
503static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg)
504{
505 struct dvb_device* dvbdev = (struct dvb_device*) file->private_data;
506 struct dst_state* state = (struct dst_state*) dvbdev->priv;
507 struct ca_slot_info *p_ca_slot_info;
508 struct ca_caps *p_ca_caps;
509 struct ca_msg *p_ca_message;
510
511 if ((p_ca_message = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
Manu Abraham7d534212005-07-07 17:57:50 -0700512 dprintk("%s: Memory allocation failure\n", __FUNCTION__);
Johannes Stezenbach50b215a2005-05-16 21:54:41 -0700513 return -ENOMEM;
514 }
515
516 if ((p_ca_slot_info = (struct ca_slot_info *) kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL)) == NULL) {
Manu Abraham7d534212005-07-07 17:57:50 -0700517 dprintk("%s: Memory allocation failure\n", __FUNCTION__);
Johannes Stezenbach50b215a2005-05-16 21:54:41 -0700518 return -ENOMEM;
519 }
520
521 if ((p_ca_caps = (struct ca_caps *) kmalloc(sizeof (struct ca_caps), GFP_KERNEL)) == NULL) {
Manu Abraham7d534212005-07-07 17:57:50 -0700522 dprintk("%s: Memory allocation failure\n", __FUNCTION__);
Johannes Stezenbach50b215a2005-05-16 21:54:41 -0700523 return -ENOMEM;
524 }
525
526 /* We have now only the standard ioctl's, the driver is upposed to handle internals. */
527 switch (cmd) {
528 case CA_SEND_MSG:
529 if (verbose > 1)
530 dprintk("%s: Sending message\n", __FUNCTION__);
531 if ((ca_send_message(state, p_ca_message, arg)) < 0) {
532 dprintk("%s: -->CA_SEND_MSG Failed !\n", __FUNCTION__);
533 return -1;
534 }
535
536 break;
537
538 case CA_GET_MSG:
539 if (verbose > 1)
540 dprintk("%s: Getting message\n", __FUNCTION__);
541 if ((ca_get_message(state, p_ca_message, arg)) < 0) {
542 dprintk("%s: -->CA_GET_MSG Failed !\n", __FUNCTION__);
543 return -1;
544 }
545 if (verbose > 1)
546 dprintk("%s: -->CA_GET_MSG Success !\n", __FUNCTION__);
547
548 break;
549
550 case CA_RESET:
551 if (verbose > 1)
552 dprintk("%s: Resetting DST\n", __FUNCTION__);
553 dst_error_bailout(state);
554 msleep(4000);
555
556 break;
557
558 case CA_GET_SLOT_INFO:
559 if (verbose > 1)
560 dprintk("%s: Getting Slot info\n", __FUNCTION__);
561 if ((ca_get_slot_info(state, p_ca_slot_info, arg)) < 0) {
562 dprintk("%s: -->CA_GET_SLOT_INFO Failed !\n", __FUNCTION__);
563 return -1;
564 }
565 if (verbose > 1)
566 dprintk("%s: -->CA_GET_SLOT_INFO Success !\n", __FUNCTION__);
567
568 break;
569
570 case CA_GET_CAP:
571 if (verbose > 1)
572 dprintk("%s: Getting Slot capabilities\n", __FUNCTION__);
573 if ((ca_get_slot_caps(state, p_ca_caps, arg)) < 0) {
574 dprintk("%s: -->CA_GET_CAP Failed !\n", __FUNCTION__);
575 return -1;
576 }
577 if (verbose > 1)
578 dprintk("%s: -->CA_GET_CAP Success !\n", __FUNCTION__);
579
580 break;
581
582 case CA_GET_DESCR_INFO:
583 if (verbose > 1)
584 dprintk("%s: Getting descrambler description\n", __FUNCTION__);
585 if ((ca_get_slot_descr(state, p_ca_message, arg)) < 0) {
586 dprintk("%s: -->CA_GET_DESCR_INFO Failed !\n", __FUNCTION__);
587 return -1;
588 }
589 if (verbose > 1)
590 dprintk("%s: -->CA_GET_DESCR_INFO Success !\n", __FUNCTION__);
591
592 break;
593
594 case CA_SET_DESCR:
595 if (verbose > 1)
596 dprintk("%s: Setting descrambler\n", __FUNCTION__);
597 if ((ca_set_slot_descr()) < 0) {
598 dprintk("%s: -->CA_SET_DESCR Failed !\n", __FUNCTION__);
599 return -1;
600 }
601 if (verbose > 1)
602 dprintk("%s: -->CA_SET_DESCR Success !\n", __FUNCTION__);
603
604 break;
605
606 case CA_SET_PID:
607 if (verbose > 1)
608 dprintk("%s: Setting PID\n", __FUNCTION__);
609 if ((ca_set_pid()) < 0) {
610 dprintk("%s: -->CA_SET_PID Failed !\n", __FUNCTION__);
611 return -1;
612 }
613 if (verbose > 1)
614 dprintk("%s: -->CA_SET_PID Success !\n", __FUNCTION__);
615
616 default:
617 return -EOPNOTSUPP;
618 };
619
620 return 0;
621}
622
623static int dst_ca_open(struct inode *inode, struct file *file)
624{
625 if (verbose > 4)
626 dprintk("%s:Device opened [%p]\n", __FUNCTION__, file);
627 try_module_get(THIS_MODULE);
628
629 return 0;
630}
631
632static int dst_ca_release(struct inode *inode, struct file *file)
633{
634 if (verbose > 4)
635 dprintk("%s:Device closed.\n", __FUNCTION__);
636 module_put(THIS_MODULE);
637
638 return 0;
639}
640
641static int dst_ca_read(struct file *file, char __user * buffer, size_t length, loff_t * offset)
642{
643 int bytes_read = 0;
644
645 if (verbose > 4)
646 dprintk("%s:Device read.\n", __FUNCTION__);
647
648 return bytes_read;
649}
650
651static int dst_ca_write(struct file *file, const char __user * buffer, size_t length, loff_t * offset)
652{
653 if (verbose > 4)
654 dprintk("%s:Device write.\n", __FUNCTION__);
655
656 return 0;
657}
658
659static struct file_operations dst_ca_fops = {
660 .owner = THIS_MODULE,
661 .ioctl = (void *)dst_ca_ioctl,
662 .open = dst_ca_open,
663 .release = dst_ca_release,
664 .read = dst_ca_read,
665 .write = dst_ca_write
666};
667
668static struct dvb_device dvbdev_ca = {
669 .priv = NULL,
670 .users = 1,
671 .readers = 1,
672 .writers = 1,
673 .fops = &dst_ca_fops
674};
675
676int dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_adapter)
677{
678 struct dvb_device *dvbdev;
679 if (verbose > 4)
680 dprintk("%s:registering DST-CA device\n", __FUNCTION__);
681 dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, DVB_DEVICE_CA);
682 return 0;
683}
684
685EXPORT_SYMBOL(dst_ca_attach);
686
687MODULE_DESCRIPTION("DST DVB-S/T/C Combo CA driver");
688MODULE_AUTHOR("Manu Abraham");
689MODULE_LICENSE("GPL");