aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/firesat/firesat-ci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/firesat/firesat-ci.c')
-rw-r--r--drivers/media/dvb/firesat/firesat-ci.c342
1 files changed, 300 insertions, 42 deletions
diff --git a/drivers/media/dvb/firesat/firesat-ci.c b/drivers/media/dvb/firesat/firesat-ci.c
index 862d9553c5bc..821048db283b 100644
--- a/drivers/media/dvb/firesat/firesat-ci.c
+++ b/drivers/media/dvb/firesat/firesat-ci.c
@@ -1,66 +1,303 @@
1/*
2 * FireSAT DVB driver
3 *
4 * Copyright (c) 2008 Henrik Kurelid <henrik@kurelid.se>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
10 */
11
1#include "firesat-ci.h" 12#include "firesat-ci.h"
2#include "firesat.h" 13#include "firesat.h"
3#include "avc_api.h" 14#include "avc_api.h"
4 15
5#include <linux/dvb/ca.h> 16#include <linux/dvb/ca.h>
6#include <dvbdev.h> 17#include <dvbdev.h>
7/*
8static int firesat_ca_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) {
9 //struct firesat *firesat = (struct firesat*)((struct dvb_device*)file->private_data)->priv;
10 int err;
11 18
12// printk(KERN_INFO "%s: ioctl %d\n",__func__,cmd); 19static unsigned int ca_debug = 0;
20module_param(ca_debug, int, 0644);
21MODULE_PARM_DESC(ca_debug, "debug logging of ca system, default is 0 (no)");
13 22
14 switch(cmd) { 23static int firesat_ca_ready(ANTENNA_INPUT_INFO *info)
15 case CA_RESET: 24{
16 // TODO: Needs to be implemented with new AVC Vendor commands 25 if (ca_debug != 0)
26 printk("%s: CaMmi=%d, CaInit=%d, CaError=%d, CaDvb=%d, "
27 "CaModule=%d, CaAppInfo=%d, CaDateTime=%d, "
28 "CaPmt=%d\n", __func__, info->CaMmi,
29 info->CaInitializationStatus, info->CaErrorFlag,
30 info->CaDvbFlag, info->CaModulePresentStatus,
31 info->CaApplicationInfo,
32 info->CaDateTimeRequest, info->CaPmtReply);
33 return info->CaInitializationStatus == 1 &&
34 info->CaErrorFlag == 0 &&
35 info->CaDvbFlag == 1 &&
36 info->CaModulePresentStatus == 1;
37}
38
39static int firesat_get_ca_flags(ANTENNA_INPUT_INFO *info)
40{
41 int flags = 0;
42 if (info->CaModulePresentStatus == 1)
43 flags |= CA_CI_MODULE_PRESENT;
44 if (info->CaInitializationStatus == 1 &&
45 info->CaErrorFlag == 0 &&
46 info->CaDvbFlag == 1)
47 flags |= CA_CI_MODULE_READY;
48 return flags;
49}
50
51static int firesat_ca_reset(struct firesat *firesat)
52{
53 if (ca_debug)
54 printk(KERN_INFO "%s: ioctl CA_RESET\n", __func__);
55 if (avc_ca_reset(firesat))
56 return -EFAULT;
57 return 0;
58}
59
60static int firesat_ca_get_caps(struct firesat *firesat, void *arg)
61{
62 struct ca_caps *cap_p = (struct ca_caps*)arg;
63 int err = 0;
64
65 cap_p->slot_num = 1;
66 cap_p->slot_type = CA_CI;
67 cap_p->descr_num = 1;
68 cap_p->descr_type = CA_ECD;
69 if (ca_debug)
70 printk(KERN_INFO "%s: ioctl CA_GET_CAP\n", __func__);
71 return err;
72}
73
74static int firesat_ca_get_slot_info(struct firesat *firesat, void *arg)
75{
76 ANTENNA_INPUT_INFO info;
77 struct ca_slot_info *slot_p = (struct ca_slot_info*)arg;
78
79 if (ca_debug)
80 printk(KERN_INFO "%s: ioctl CA_GET_SLOT_INFO on slot %d.\n",
81 __func__, slot_p->num);
82 if (AVCTunerStatus(firesat, &info))
83 return -EFAULT;
84
85 if (slot_p->num == 0) {
86 slot_p->type = CA_CI;
87 slot_p->flags = firesat_get_ca_flags(&info);
88 }
89 else {
90 return -EFAULT;
91 }
92 return 0;
93}
94
95static int firesat_ca_app_info(struct firesat *firesat, void *arg)
96{
97 struct ca_msg *reply_p = (struct ca_msg*)arg;
98 int i;
99
100 if (avc_ca_app_info(firesat, reply_p->msg, &reply_p->length))
101 return -EFAULT;
102 if (ca_debug) {
103 printk(KERN_INFO "%s: Creating TAG_APP_INFO message:",
104 __func__);
105 for (i = 0; i < reply_p->length; i++)
106 printk("0x%02X, ", (unsigned char)reply_p->msg[i]);
107 printk("\n");
108 }
109 return 0;
110}
111
112static int firesat_ca_info(struct firesat *firesat, void *arg)
113{
114 struct ca_msg *reply_p = (struct ca_msg*)arg;
115 int i;
116
117 if (avc_ca_info(firesat, reply_p->msg, &reply_p->length))
118 return -EFAULT;
119 if (ca_debug) {
120 printk(KERN_INFO "%s: Creating TAG_CA_INFO message:",
121 __func__);
122 for (i = 0; i < reply_p->length; i++)
123 printk("0x%02X, ", (unsigned char)reply_p->msg[i]);
124 printk("\n");
125 }
126 return 0;
127}
128
129static int firesat_ca_get_mmi(struct firesat *firesat, void *arg)
130{
131 struct ca_msg *reply_p = (struct ca_msg*)arg;
132 int i;
133
134 if (avc_ca_get_mmi(firesat, reply_p->msg, &reply_p->length))
135 return -EFAULT;
136 if (ca_debug) {
137 printk(KERN_INFO "%s: Creating MMI reply INFO message:",
138 __func__);
139 for (i = 0; i < reply_p->length; i++)
140 printk("0x%02X, ", (unsigned char)reply_p->msg[i]);
141 printk("\n");
142 }
143 return 0;
144}
145
146static int firesat_ca_get_msg(struct firesat *firesat, void *arg)
147{
148 int err;
149 ANTENNA_INPUT_INFO info;
150
151 switch (firesat->ca_last_command) {
152 case TAG_APP_INFO_ENQUIRY:
153 err = firesat_ca_app_info(firesat, arg);
154 break;
155 case TAG_CA_INFO_ENQUIRY:
156 err = firesat_ca_info(firesat, arg);
17 break; 157 break;
18 case CA_GET_CAP: { 158 default:
19 ca_caps_t *cap=(ca_caps_t*)parg; 159 if (AVCTunerStatus(firesat, &info))
20 cap->slot_num = 1; 160 err = -EFAULT;
21 cap->slot_type = CA_CI_LINK; 161 else if (info.CaMmi == 1) {
22 cap->descr_num = 1; 162 err = firesat_ca_get_mmi(firesat, arg);
23 cap->descr_type = CA_DSS; 163 }
164 else {
165 printk(KERN_INFO "%s: Unhandled message 0x%08X\n",
166 __func__, firesat->ca_last_command);
167 err = -EFAULT;
168 }
169 }
170 firesat->ca_last_command = 0;
171 return err;
172}
24 173
174static int firesat_ca_pmt(struct firesat *firesat, void *arg)
175{
176 struct ca_msg *msg_p = (struct ca_msg*)arg;
177 int data_pos;
178
179 if (msg_p->msg[3] & 0x80)
180 data_pos = (msg_p->msg[4] && 0x7F) + 4;
181 else
182 data_pos = 4;
183 if (avc_ca_pmt(firesat, &msg_p->msg[data_pos],
184 msg_p->length - data_pos))
185 return -EFAULT;
186 return 0;
187}
188
189static int firesat_ca_send_msg(struct firesat *firesat, void *arg)
190{
191 int err;
192 struct ca_msg *msg_p = (struct ca_msg*)arg;
193
194 // Do we need a semaphore for this?
195 firesat->ca_last_command =
196 (msg_p->msg[0] << 16) + (msg_p->msg[1] << 8) + msg_p->msg[2];
197 switch (firesat->ca_last_command) {
198 case TAG_CA_PMT:
199 if (ca_debug != 0)
200 printk(KERN_INFO "%s: Message received: TAG_CA_PMT\n",
201 __func__);
202 err = firesat_ca_pmt(firesat, arg);
203 break;
204 case TAG_APP_INFO_ENQUIRY:
205 // This is all handled in ca_get_msg
206 if (ca_debug != 0)
207 printk(KERN_INFO "%s: Message received: "
208 "TAG_APP_INFO_ENQUIRY\n", __func__);
25 err = 0; 209 err = 0;
26 break; 210 break;
27 } 211 case TAG_CA_INFO_ENQUIRY:
28 case CA_GET_SLOT_INFO: { 212 // This is all handled in ca_get_msg
29 ca_slot_info_t *slot=(ca_slot_info_t*)parg; 213 if (ca_debug != 0)
30 if(slot->num == 0) { 214 printk(KERN_INFO "%s: Message received: "
31 slot->type = CA_CI | CA_CI_LINK | CA_DESCR; 215 "TAG_CA_APP_INFO_ENQUIRY\n", __func__);
32 slot->flags = CA_CI_MODULE_PRESENT | CA_CI_MODULE_READY;
33 } else {
34 slot->type = 0;
35 slot->flags = 0;
36 }
37 err = 0; 216 err = 0;
38 break; 217 break;
218 case TAG_ENTER_MENU:
219 if (ca_debug != 0)
220 printk(KERN_INFO "%s: Entering CA menu.\n", __func__);
221 err = avc_ca_enter_menu(firesat);
222 break;
223 default:
224 printk(KERN_ERR "%s: Unhandled unknown message 0x%08X\n",
225 __func__, firesat->ca_last_command);
226 err = -EFAULT;
39 } 227 }
228 return err;
229}
230
231static int firesat_ca_ioctl(struct inode *inode, struct file *file,
232 unsigned int cmd, void *arg)
233{
234 struct dvb_device* dvbdev = (struct dvb_device*) file->private_data;
235 struct firesat *firesat = dvbdev->priv;
236 int err;
237 ANTENNA_INPUT_INFO info;
238
239 switch(cmd) {
240 case CA_RESET:
241 err = firesat_ca_reset(firesat);
242 break;
243 case CA_GET_CAP:
244 err = firesat_ca_get_caps(firesat, arg);
245 break;
246 case CA_GET_SLOT_INFO:
247 err = firesat_ca_get_slot_info(firesat, arg);
248 break;
249 case CA_GET_MSG:
250 err = firesat_ca_get_msg(firesat, arg);
251 break;
252 case CA_SEND_MSG:
253 err = firesat_ca_send_msg(firesat, arg);
254 break;
40 default: 255 default:
41 err=-EINVAL; 256 printk(KERN_INFO "%s: Unhandled ioctl, command: %u\n",__func__,
257 cmd);
258 err = -EOPNOTSUPP;
42 } 259 }
260
261 if (AVCTunerStatus(firesat, &info))
262 return err;
263
264 firesat_ca_ready(&info);
265
43 return err; 266 return err;
44} 267}
45*/
46 268
47static int firesat_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { 269static int firesat_get_date_time_request(struct firesat *firesat)
48 //return dvb_usercopy(inode, file, cmd, arg, firesat_ca_do_ioctl); 270{
49 return dvb_generic_ioctl(inode, file, cmd, arg); 271 if (ca_debug)
272 printk(KERN_INFO "%s: Retrieving Time/Date request\n",
273 __func__);
274 if (avc_ca_get_time_date(firesat, &firesat->ca_time_interval))
275 return -EFAULT;
276 if (ca_debug)
277 printk(KERN_INFO "%s: Time/Date interval is %d\n",
278 __func__, firesat->ca_time_interval);
279
280 return 0;
50} 281}
51 282
52static int firesat_ca_io_open(struct inode *inode, struct file *file) { 283static int firesat_ca_io_open(struct inode *inode, struct file *file)
53 printk(KERN_INFO "%s!\n",__func__); 284{
285 if (ca_debug != 0)
286 printk(KERN_INFO "%s\n",__func__);
54 return dvb_generic_open(inode, file); 287 return dvb_generic_open(inode, file);
55} 288}
56 289
57static int firesat_ca_io_release(struct inode *inode, struct file *file) { 290static int firesat_ca_io_release(struct inode *inode, struct file *file)
58 printk(KERN_INFO "%s!\n",__func__); 291{
292 if (ca_debug != 0)
293 printk(KERN_INFO "%s\n",__func__);
59 return dvb_generic_release(inode, file); 294 return dvb_generic_release(inode, file);
60} 295}
61 296
62static unsigned int firesat_ca_io_poll(struct file *file, poll_table *wait) { 297static unsigned int firesat_ca_io_poll(struct file *file, poll_table *wait)
63// printk(KERN_INFO "%s!\n",__func__); 298{
299 if (ca_debug != 0)
300 printk(KERN_INFO "%s\n",__func__);
64 return POLLIN; 301 return POLLIN;
65} 302}
66 303
@@ -68,7 +305,7 @@ static struct file_operations firesat_ca_fops = {
68 .owner = THIS_MODULE, 305 .owner = THIS_MODULE,
69 .read = NULL, // There is no low level read anymore 306 .read = NULL, // There is no low level read anymore
70 .write = NULL, // There is no low level write anymore 307 .write = NULL, // There is no low level write anymore
71 .ioctl = firesat_ca_ioctl, 308 .ioctl = dvb_generic_ioctl,
72 .open = firesat_ca_io_open, 309 .open = firesat_ca_io_open,
73 .release = firesat_ca_io_release, 310 .release = firesat_ca_io_release,
74 .poll = firesat_ca_io_poll, 311 .poll = firesat_ca_io_poll,
@@ -80,16 +317,37 @@ static struct dvb_device firesat_ca = {
80 .readers = 1, 317 .readers = 1,
81 .writers = 1, 318 .writers = 1,
82 .fops = &firesat_ca_fops, 319 .fops = &firesat_ca_fops,
320 .kernel_ioctl = firesat_ca_ioctl,
83}; 321};
84 322
85int firesat_ca_init(struct firesat *firesat) { 323int firesat_ca_init(struct firesat *firesat)
86 int ret = dvb_register_device(firesat->adapter, &firesat->cadev, &firesat_ca, firesat, DVB_DEVICE_CA); 324{
87 if(ret) return ret; 325 int err;
326 ANTENNA_INPUT_INFO info;
88 327
89 // avoid unnecessary delays, we're not talking to the CI yet anyways 328 if (AVCTunerStatus(firesat, &info))
90 return 0; 329 return -EINVAL;
330
331 if (firesat_ca_ready(&info)) {
332 err = dvb_register_device(firesat->adapter,
333 &firesat->cadev,
334 &firesat_ca, firesat,
335 DVB_DEVICE_CA);
336
337 if (info.CaApplicationInfo == 0)
338 printk(KERN_ERR "%s: CaApplicationInfo is not set.\n",
339 __func__);
340 if (info.CaDateTimeRequest == 1)
341 firesat_get_date_time_request(firesat);
342 }
343 else
344 err = -EFAULT;
345
346 return err;
91} 347}
92 348
93void firesat_ca_release(struct firesat *firesat) { 349void firesat_ca_release(struct firesat *firesat)
350{
351 if (firesat->cadev)
94 dvb_unregister_device(firesat->cadev); 352 dvb_unregister_device(firesat->cadev);
95} 353}