Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/dvb/bt8xx/dst_ca.c
15112 views
1
/*
2
CA-driver for TwinHan DST Frontend/Card
3
4
Copyright (C) 2004, 2005 Manu Abraham ([email protected])
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
#include <linux/kernel.h>
22
#include <linux/module.h>
23
#include <linux/slab.h>
24
#include <linux/init.h>
25
#include <linux/mutex.h>
26
#include <linux/string.h>
27
#include <linux/dvb/ca.h>
28
#include "dvbdev.h"
29
#include "dvb_frontend.h"
30
#include "dst_ca.h"
31
#include "dst_common.h"
32
33
#define DST_CA_ERROR 0
34
#define DST_CA_NOTICE 1
35
#define DST_CA_INFO 2
36
#define DST_CA_DEBUG 3
37
38
#define dprintk(x, y, z, format, arg...) do { \
39
if (z) { \
40
if ((x > DST_CA_ERROR) && (x > y)) \
41
printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \
42
else if ((x > DST_CA_NOTICE) && (x > y)) \
43
printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \
44
else if ((x > DST_CA_INFO) && (x > y)) \
45
printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \
46
else if ((x > DST_CA_DEBUG) && (x > y)) \
47
printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \
48
} else { \
49
if (x > y) \
50
printk(format, ## arg); \
51
} \
52
} while(0)
53
54
55
static DEFINE_MUTEX(dst_ca_mutex);
56
static unsigned int verbose = 5;
57
module_param(verbose, int, 0644);
58
MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
59
60
/* Need some more work */
61
static int ca_set_slot_descr(void)
62
{
63
/* We could make this more graceful ? */
64
return -EOPNOTSUPP;
65
}
66
67
/* Need some more work */
68
static int ca_set_pid(void)
69
{
70
/* We could make this more graceful ? */
71
return -EOPNOTSUPP;
72
}
73
74
static void put_command_and_length(u8 *data, int command, int length)
75
{
76
data[0] = (command >> 16) & 0xff;
77
data[1] = (command >> 8) & 0xff;
78
data[2] = command & 0xff;
79
data[3] = length;
80
}
81
82
static void put_checksum(u8 *check_string, int length)
83
{
84
dprintk(verbose, DST_CA_DEBUG, 1, " Computing string checksum.");
85
dprintk(verbose, DST_CA_DEBUG, 1, " -> string length : 0x%02x", length);
86
check_string[length] = dst_check_sum (check_string, length);
87
dprintk(verbose, DST_CA_DEBUG, 1, " -> checksum : 0x%02x", check_string[length]);
88
}
89
90
static int dst_ci_command(struct dst_state* state, u8 * data, u8 *ca_string, u8 len, int read)
91
{
92
u8 reply;
93
94
mutex_lock(&state->dst_mutex);
95
dst_comm_init(state);
96
msleep(65);
97
98
if (write_dst(state, data, len)) {
99
dprintk(verbose, DST_CA_INFO, 1, " Write not successful, trying to recover");
100
dst_error_recovery(state);
101
goto error;
102
}
103
if ((dst_pio_disable(state)) < 0) {
104
dprintk(verbose, DST_CA_ERROR, 1, " DST PIO disable failed.");
105
goto error;
106
}
107
if (read_dst(state, &reply, GET_ACK) < 0) {
108
dprintk(verbose, DST_CA_INFO, 1, " Read not successful, trying to recover");
109
dst_error_recovery(state);
110
goto error;
111
}
112
if (read) {
113
if (! dst_wait_dst_ready(state, LONG_DELAY)) {
114
dprintk(verbose, DST_CA_NOTICE, 1, " 8820 not ready");
115
goto error;
116
}
117
if (read_dst(state, ca_string, 128) < 0) { /* Try to make this dynamic */
118
dprintk(verbose, DST_CA_INFO, 1, " Read not successful, trying to recover");
119
dst_error_recovery(state);
120
goto error;
121
}
122
}
123
mutex_unlock(&state->dst_mutex);
124
return 0;
125
126
error:
127
mutex_unlock(&state->dst_mutex);
128
return -EIO;
129
}
130
131
132
static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string, int read)
133
{
134
u8 dst_ca_comm_err = 0;
135
136
while (dst_ca_comm_err < RETRIES) {
137
dprintk(verbose, DST_CA_NOTICE, 1, " Put Command");
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
} else {
142
break;
143
}
144
}
145
146
if(dst_ca_comm_err == RETRIES)
147
return -1;
148
149
return 0;
150
}
151
152
153
154
static int ca_get_app_info(struct dst_state *state)
155
{
156
int length, str_length;
157
static u8 command[8] = {0x07, 0x40, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff};
158
159
put_checksum(&command[0], command[0]);
160
if ((dst_put_ci(state, command, sizeof(command), state->messages, GET_REPLY)) < 0) {
161
dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
162
return -1;
163
}
164
dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
165
dprintk(verbose, DST_CA_INFO, 1, " ================================ CI Module Application Info ======================================");
166
dprintk(verbose, DST_CA_INFO, 1, " Application Type=[%d], Application Vendor=[%d], Vendor Code=[%d]\n%s: Application info=[%s]",
167
state->messages[7], (state->messages[8] << 8) | state->messages[9],
168
(state->messages[10] << 8) | state->messages[11], __func__, (char *)(&state->messages[12]));
169
dprintk(verbose, DST_CA_INFO, 1, " ==================================================================================================");
170
171
// Transform dst message to correct application_info message
172
length = state->messages[5];
173
str_length = length - 6;
174
if (str_length < 0) {
175
str_length = 0;
176
dprintk(verbose, DST_CA_ERROR, 1, "Invalid string length returned in ca_get_app_info(). Recovering.");
177
}
178
179
// First, the command and length fields
180
put_command_and_length(&state->messages[0], CA_APP_INFO, length);
181
182
// Copy application_type, application_manufacturer and manufacturer_code
183
memcpy(&state->messages[4], &state->messages[7], 5);
184
185
// Set string length and copy string
186
state->messages[9] = str_length;
187
memcpy(&state->messages[10], &state->messages[12], str_length);
188
189
return 0;
190
}
191
192
static int ca_get_ca_info(struct dst_state *state)
193
{
194
int srcPtr, dstPtr, i, num_ids;
195
static u8 slot_command[8] = {0x07, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0xff};
196
const int in_system_id_pos = 8, out_system_id_pos = 4, in_num_ids_pos = 7;
197
198
put_checksum(&slot_command[0], slot_command[0]);
199
if ((dst_put_ci(state, slot_command, sizeof (slot_command), state->messages, GET_REPLY)) < 0) {
200
dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
201
return -1;
202
}
203
dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
204
205
// Print raw data
206
dprintk(verbose, DST_CA_INFO, 0, " DST data = [");
207
for (i = 0; i < state->messages[0] + 1; i++) {
208
dprintk(verbose, DST_CA_INFO, 0, " 0x%02x", state->messages[i]);
209
}
210
dprintk(verbose, DST_CA_INFO, 0, "]\n");
211
212
// Set the command and length of the output
213
num_ids = state->messages[in_num_ids_pos];
214
if (num_ids >= 100) {
215
num_ids = 100;
216
dprintk(verbose, DST_CA_ERROR, 1, "Invalid number of ids (>100). Recovering.");
217
}
218
put_command_and_length(&state->messages[0], CA_INFO, num_ids * 2);
219
220
dprintk(verbose, DST_CA_INFO, 0, " CA_INFO = [");
221
srcPtr = in_system_id_pos;
222
dstPtr = out_system_id_pos;
223
for(i = 0; i < num_ids; i++) {
224
dprintk(verbose, DST_CA_INFO, 0, " 0x%02x%02x", state->messages[srcPtr + 0], state->messages[srcPtr + 1]);
225
// Append to output
226
state->messages[dstPtr + 0] = state->messages[srcPtr + 0];
227
state->messages[dstPtr + 1] = state->messages[srcPtr + 1];
228
srcPtr += 2;
229
dstPtr += 2;
230
}
231
dprintk(verbose, DST_CA_INFO, 0, "]\n");
232
233
return 0;
234
}
235
236
static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps, void __user *arg)
237
{
238
int i;
239
u8 slot_cap[256];
240
static u8 slot_command[8] = {0x07, 0x40, 0x02, 0x00, 0x02, 0x00, 0x00, 0xff};
241
242
put_checksum(&slot_command[0], slot_command[0]);
243
if ((dst_put_ci(state, slot_command, sizeof (slot_command), slot_cap, GET_REPLY)) < 0) {
244
dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
245
return -1;
246
}
247
dprintk(verbose, DST_CA_NOTICE, 1, " -->dst_put_ci SUCCESS !");
248
249
/* Will implement the rest soon */
250
251
dprintk(verbose, DST_CA_INFO, 1, " Slot cap = [%d]", slot_cap[7]);
252
dprintk(verbose, DST_CA_INFO, 0, "===================================\n");
253
for (i = 0; i < slot_cap[0] + 1; i++)
254
dprintk(verbose, DST_CA_INFO, 0, " %d", slot_cap[i]);
255
dprintk(verbose, DST_CA_INFO, 0, "\n");
256
257
p_ca_caps->slot_num = 1;
258
p_ca_caps->slot_type = 1;
259
p_ca_caps->descr_num = slot_cap[7];
260
p_ca_caps->descr_type = 1;
261
262
if (copy_to_user(arg, p_ca_caps, sizeof (struct ca_caps)))
263
return -EFAULT;
264
265
return 0;
266
}
267
268
/* Need some more work */
269
static int ca_get_slot_descr(struct dst_state *state, struct ca_msg *p_ca_message, void __user *arg)
270
{
271
return -EOPNOTSUPP;
272
}
273
274
275
static int ca_get_slot_info(struct dst_state *state, struct ca_slot_info *p_ca_slot_info, void __user *arg)
276
{
277
int i;
278
static u8 slot_command[8] = {0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
279
280
u8 *slot_info = state->messages;
281
282
put_checksum(&slot_command[0], 7);
283
if ((dst_put_ci(state, slot_command, sizeof (slot_command), slot_info, GET_REPLY)) < 0) {
284
dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
285
return -1;
286
}
287
dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
288
289
/* Will implement the rest soon */
290
291
dprintk(verbose, DST_CA_INFO, 1, " Slot info = [%d]", slot_info[3]);
292
dprintk(verbose, DST_CA_INFO, 0, "===================================\n");
293
for (i = 0; i < 8; i++)
294
dprintk(verbose, DST_CA_INFO, 0, " %d", slot_info[i]);
295
dprintk(verbose, DST_CA_INFO, 0, "\n");
296
297
if (slot_info[4] & 0x80) {
298
p_ca_slot_info->flags = CA_CI_MODULE_PRESENT;
299
p_ca_slot_info->num = 1;
300
p_ca_slot_info->type = CA_CI;
301
} else if (slot_info[4] & 0x40) {
302
p_ca_slot_info->flags = CA_CI_MODULE_READY;
303
p_ca_slot_info->num = 1;
304
p_ca_slot_info->type = CA_CI;
305
} else
306
p_ca_slot_info->flags = 0;
307
308
if (copy_to_user(arg, p_ca_slot_info, sizeof (struct ca_slot_info)))
309
return -EFAULT;
310
311
return 0;
312
}
313
314
315
static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message, void __user *arg)
316
{
317
u8 i = 0;
318
u32 command = 0;
319
320
if (copy_from_user(p_ca_message, arg, sizeof (struct ca_msg)))
321
return -EFAULT;
322
323
if (p_ca_message->msg) {
324
dprintk(verbose, DST_CA_NOTICE, 1, " Message = [%02x %02x %02x]", p_ca_message->msg[0], p_ca_message->msg[1], p_ca_message->msg[2]);
325
326
for (i = 0; i < 3; i++) {
327
command = command | p_ca_message->msg[i];
328
if (i < 2)
329
command = command << 8;
330
}
331
dprintk(verbose, DST_CA_NOTICE, 1, " Command=[0x%x]", command);
332
333
switch (command) {
334
case CA_APP_INFO:
335
memcpy(p_ca_message->msg, state->messages, 128);
336
if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
337
return -EFAULT;
338
break;
339
case CA_INFO:
340
memcpy(p_ca_message->msg, state->messages, 128);
341
if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
342
return -EFAULT;
343
break;
344
}
345
}
346
347
return 0;
348
}
349
350
static int handle_dst_tag(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u32 length)
351
{
352
if (state->dst_hw_cap & DST_TYPE_HAS_SESSION) {
353
hw_buffer->msg[2] = p_ca_message->msg[1]; /* MSB */
354
hw_buffer->msg[3] = p_ca_message->msg[2]; /* LSB */
355
} else {
356
if (length > 247) {
357
dprintk(verbose, DST_CA_ERROR, 1, " Message too long ! *** Bailing Out *** !");
358
return -1;
359
}
360
hw_buffer->msg[0] = (length & 0xff) + 7;
361
hw_buffer->msg[1] = 0x40;
362
hw_buffer->msg[2] = 0x03;
363
hw_buffer->msg[3] = 0x00;
364
hw_buffer->msg[4] = 0x03;
365
hw_buffer->msg[5] = length & 0xff;
366
hw_buffer->msg[6] = 0x00;
367
368
/*
369
* Need to compute length for EN50221 section 8.3.2, for the time being
370
* assuming 8.3.2 is not applicable
371
*/
372
memcpy(&hw_buffer->msg[7], &p_ca_message->msg[4], length);
373
}
374
375
return 0;
376
}
377
378
static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 length, u8 reply)
379
{
380
if ((dst_put_ci(state, hw_buffer->msg, length, hw_buffer->msg, reply)) < 0) {
381
dprintk(verbose, DST_CA_ERROR, 1, " DST-CI Command failed.");
382
dprintk(verbose, DST_CA_NOTICE, 1, " Resetting DST.");
383
rdc_reset_state(state);
384
return -1;
385
}
386
dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command success.");
387
388
return 0;
389
}
390
391
static u32 asn_1_decode(u8 *asn_1_array)
392
{
393
u8 length_field = 0, word_count = 0, count = 0;
394
u32 length = 0;
395
396
length_field = asn_1_array[0];
397
dprintk(verbose, DST_CA_DEBUG, 1, " Length field=[%02x]", length_field);
398
if (length_field < 0x80) {
399
length = length_field & 0x7f;
400
dprintk(verbose, DST_CA_DEBUG, 1, " Length=[%02x]\n", length);
401
} else {
402
word_count = length_field & 0x7f;
403
for (count = 0; count < word_count; count++) {
404
length = length << 8;
405
length += asn_1_array[count + 1];
406
dprintk(verbose, DST_CA_DEBUG, 1, " Length=[%04x]", length);
407
}
408
}
409
return length;
410
}
411
412
static int debug_string(u8 *msg, u32 length, u32 offset)
413
{
414
u32 i;
415
416
dprintk(verbose, DST_CA_DEBUG, 0, " String=[ ");
417
for (i = offset; i < length; i++)
418
dprintk(verbose, DST_CA_DEBUG, 0, "%02x ", msg[i]);
419
dprintk(verbose, DST_CA_DEBUG, 0, "]\n");
420
421
return 0;
422
}
423
424
425
static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query)
426
{
427
u32 length = 0;
428
u8 tag_length = 8;
429
430
length = asn_1_decode(&p_ca_message->msg[3]);
431
dprintk(verbose, DST_CA_DEBUG, 1, " CA Message length=[%d]", length);
432
debug_string(&p_ca_message->msg[4], length, 0); /* length is excluding tag & length */
433
434
memset(hw_buffer->msg, '\0', length);
435
handle_dst_tag(state, p_ca_message, hw_buffer, length);
436
put_checksum(hw_buffer->msg, hw_buffer->msg[0]);
437
438
debug_string(hw_buffer->msg, (length + tag_length), 0); /* tags too */
439
write_to_8820(state, hw_buffer, (length + tag_length), reply);
440
441
return 0;
442
}
443
444
445
/* Board supports CA PMT reply ? */
446
static int dst_check_ca_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer)
447
{
448
int ca_pmt_reply_test = 0;
449
450
/* Do test board */
451
/* Not there yet but soon */
452
453
/* CA PMT Reply capable */
454
if (ca_pmt_reply_test) {
455
if ((ca_set_pmt(state, p_ca_message, hw_buffer, 1, GET_REPLY)) < 0) {
456
dprintk(verbose, DST_CA_ERROR, 1, " ca_set_pmt.. failed !");
457
return -1;
458
}
459
460
/* Process CA PMT Reply */
461
/* will implement soon */
462
dprintk(verbose, DST_CA_ERROR, 1, " Not there yet");
463
}
464
/* CA PMT Reply not capable */
465
if (!ca_pmt_reply_test) {
466
if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, NO_REPLY)) < 0) {
467
dprintk(verbose, DST_CA_ERROR, 1, " ca_set_pmt.. failed !");
468
return -1;
469
}
470
dprintk(verbose, DST_CA_NOTICE, 1, " ca_set_pmt.. success !");
471
/* put a dummy message */
472
473
}
474
return 0;
475
}
476
477
static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, void __user *arg)
478
{
479
int i = 0;
480
unsigned int ca_message_header_len;
481
482
u32 command = 0;
483
struct ca_msg *hw_buffer;
484
int result = 0;
485
486
if ((hw_buffer = kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
487
dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
488
return -ENOMEM;
489
}
490
dprintk(verbose, DST_CA_DEBUG, 1, " ");
491
492
if (copy_from_user(p_ca_message, arg, sizeof (struct ca_msg))) {
493
result = -EFAULT;
494
goto free_mem_and_exit;
495
}
496
497
498
if (p_ca_message->msg) {
499
ca_message_header_len = p_ca_message->length; /* Restore it back when you are done */
500
/* EN50221 tag */
501
command = 0;
502
503
for (i = 0; i < 3; i++) {
504
command = command | p_ca_message->msg[i];
505
if (i < 2)
506
command = command << 8;
507
}
508
dprintk(verbose, DST_CA_DEBUG, 1, " Command=[0x%x]\n", command);
509
510
switch (command) {
511
case CA_PMT:
512
dprintk(verbose, DST_CA_DEBUG, 1, "Command = SEND_CA_PMT");
513
if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) { // code simplification started
514
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT Failed !");
515
result = -1;
516
goto free_mem_and_exit;
517
}
518
dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT Success !");
519
break;
520
case CA_PMT_REPLY:
521
dprintk(verbose, DST_CA_INFO, 1, "Command = CA_PMT_REPLY");
522
/* Have to handle the 2 basic types of cards here */
523
if ((dst_check_ca_pmt(state, p_ca_message, hw_buffer)) < 0) {
524
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT_REPLY Failed !");
525
result = -1;
526
goto free_mem_and_exit;
527
}
528
dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT_REPLY Success !");
529
break;
530
case CA_APP_INFO_ENQUIRY: // only for debugging
531
dprintk(verbose, DST_CA_INFO, 1, " Getting Cam Application information");
532
533
if ((ca_get_app_info(state)) < 0) {
534
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_APP_INFO_ENQUIRY Failed !");
535
result = -1;
536
goto free_mem_and_exit;
537
}
538
dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !");
539
break;
540
case CA_INFO_ENQUIRY:
541
dprintk(verbose, DST_CA_INFO, 1, " Getting CA Information");
542
543
if ((ca_get_ca_info(state)) < 0) {
544
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_INFO_ENQUIRY Failed !");
545
result = -1;
546
goto free_mem_and_exit;
547
}
548
dprintk(verbose, DST_CA_INFO, 1, " -->CA_INFO_ENQUIRY Success !");
549
break;
550
}
551
}
552
free_mem_and_exit:
553
kfree (hw_buffer);
554
555
return result;
556
}
557
558
static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioctl_arg)
559
{
560
struct dvb_device *dvbdev;
561
struct dst_state *state;
562
struct ca_slot_info *p_ca_slot_info;
563
struct ca_caps *p_ca_caps;
564
struct ca_msg *p_ca_message;
565
void __user *arg = (void __user *)ioctl_arg;
566
int result = 0;
567
568
mutex_lock(&dst_ca_mutex);
569
dvbdev = file->private_data;
570
state = (struct dst_state *)dvbdev->priv;
571
p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL);
572
p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL);
573
p_ca_caps = kmalloc(sizeof (struct ca_caps), GFP_KERNEL);
574
if (!p_ca_message || !p_ca_slot_info || !p_ca_caps) {
575
dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
576
result = -ENOMEM;
577
goto free_mem_and_exit;
578
}
579
580
/* We have now only the standard ioctl's, the driver is upposed to handle internals. */
581
switch (cmd) {
582
case CA_SEND_MSG:
583
dprintk(verbose, DST_CA_INFO, 1, " Sending message");
584
if ((ca_send_message(state, p_ca_message, arg)) < 0) {
585
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SEND_MSG Failed !");
586
result = -1;
587
goto free_mem_and_exit;
588
}
589
break;
590
case CA_GET_MSG:
591
dprintk(verbose, DST_CA_INFO, 1, " Getting message");
592
if ((ca_get_message(state, p_ca_message, arg)) < 0) {
593
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_MSG Failed !");
594
result = -1;
595
goto free_mem_and_exit;
596
}
597
dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_MSG Success !");
598
break;
599
case CA_RESET:
600
dprintk(verbose, DST_CA_ERROR, 1, " Resetting DST");
601
dst_error_bailout(state);
602
msleep(4000);
603
break;
604
case CA_GET_SLOT_INFO:
605
dprintk(verbose, DST_CA_INFO, 1, " Getting Slot info");
606
if ((ca_get_slot_info(state, p_ca_slot_info, arg)) < 0) {
607
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_SLOT_INFO Failed !");
608
result = -1;
609
goto free_mem_and_exit;
610
}
611
dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_SLOT_INFO Success !");
612
break;
613
case CA_GET_CAP:
614
dprintk(verbose, DST_CA_INFO, 1, " Getting Slot capabilities");
615
if ((ca_get_slot_caps(state, p_ca_caps, arg)) < 0) {
616
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_CAP Failed !");
617
result = -1;
618
goto free_mem_and_exit;
619
}
620
dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_CAP Success !");
621
break;
622
case CA_GET_DESCR_INFO:
623
dprintk(verbose, DST_CA_INFO, 1, " Getting descrambler description");
624
if ((ca_get_slot_descr(state, p_ca_message, arg)) < 0) {
625
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_DESCR_INFO Failed !");
626
result = -1;
627
goto free_mem_and_exit;
628
}
629
dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_DESCR_INFO Success !");
630
break;
631
case CA_SET_DESCR:
632
dprintk(verbose, DST_CA_INFO, 1, " Setting descrambler");
633
if ((ca_set_slot_descr()) < 0) {
634
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SET_DESCR Failed !");
635
result = -1;
636
goto free_mem_and_exit;
637
}
638
dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_DESCR Success !");
639
break;
640
case CA_SET_PID:
641
dprintk(verbose, DST_CA_INFO, 1, " Setting PID");
642
if ((ca_set_pid()) < 0) {
643
dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SET_PID Failed !");
644
result = -1;
645
goto free_mem_and_exit;
646
}
647
dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_PID Success !");
648
default:
649
result = -EOPNOTSUPP;
650
};
651
free_mem_and_exit:
652
kfree (p_ca_message);
653
kfree (p_ca_slot_info);
654
kfree (p_ca_caps);
655
656
mutex_unlock(&dst_ca_mutex);
657
return result;
658
}
659
660
static int dst_ca_open(struct inode *inode, struct file *file)
661
{
662
dprintk(verbose, DST_CA_DEBUG, 1, " Device opened [%p] ", file);
663
try_module_get(THIS_MODULE);
664
665
return 0;
666
}
667
668
static int dst_ca_release(struct inode *inode, struct file *file)
669
{
670
dprintk(verbose, DST_CA_DEBUG, 1, " Device closed.");
671
module_put(THIS_MODULE);
672
673
return 0;
674
}
675
676
static ssize_t dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)
677
{
678
ssize_t bytes_read = 0;
679
680
dprintk(verbose, DST_CA_DEBUG, 1, " Device read.");
681
682
return bytes_read;
683
}
684
685
static ssize_t dst_ca_write(struct file *file, const char __user *buffer, size_t length, loff_t *offset)
686
{
687
dprintk(verbose, DST_CA_DEBUG, 1, " Device write.");
688
689
return 0;
690
}
691
692
static const struct file_operations dst_ca_fops = {
693
.owner = THIS_MODULE,
694
.unlocked_ioctl = dst_ca_ioctl,
695
.open = dst_ca_open,
696
.release = dst_ca_release,
697
.read = dst_ca_read,
698
.write = dst_ca_write,
699
.llseek = noop_llseek,
700
};
701
702
static struct dvb_device dvbdev_ca = {
703
.priv = NULL,
704
.users = 1,
705
.readers = 1,
706
.writers = 1,
707
.fops = &dst_ca_fops
708
};
709
710
struct dvb_device *dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_adapter)
711
{
712
struct dvb_device *dvbdev;
713
714
dprintk(verbose, DST_CA_ERROR, 1, "registering DST-CA device");
715
if (dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, DVB_DEVICE_CA) == 0) {
716
dst->dst_ca = dvbdev;
717
return dst->dst_ca;
718
}
719
720
return NULL;
721
}
722
723
EXPORT_SYMBOL(dst_ca_attach);
724
725
MODULE_DESCRIPTION("DST DVB-S/T/C Combo CA driver");
726
MODULE_AUTHOR("Manu Abraham");
727
MODULE_LICENSE("GPL");
728
729