2 * FireDTV driver (formerly known as FireSAT)
4 * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
5 * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
13 #include <linux/dvb/ca.h>
15 #include <linux/module.h>
21 #include "firesat-ci.h"
23 static unsigned int ca_debug = 0;
24 module_param(ca_debug, int, 0644);
25 MODULE_PARM_DESC(ca_debug, "debug logging of ca system, default is 0 (no)");
27 static int firesat_ca_ready(ANTENNA_INPUT_INFO *info)
30 printk("%s: CaMmi=%d, CaInit=%d, CaError=%d, CaDvb=%d, "
31 "CaModule=%d, CaAppInfo=%d, CaDateTime=%d, "
32 "CaPmt=%d\n", __func__, info->CaMmi,
33 info->CaInitializationStatus, info->CaErrorFlag,
34 info->CaDvbFlag, info->CaModulePresentStatus,
35 info->CaApplicationInfo,
36 info->CaDateTimeRequest, info->CaPmtReply);
37 return info->CaInitializationStatus == 1 &&
38 info->CaErrorFlag == 0 &&
39 info->CaDvbFlag == 1 &&
40 info->CaModulePresentStatus == 1;
43 static int firesat_get_ca_flags(ANTENNA_INPUT_INFO *info)
46 if (info->CaModulePresentStatus == 1)
47 flags |= CA_CI_MODULE_PRESENT;
48 if (info->CaInitializationStatus == 1 &&
49 info->CaErrorFlag == 0 &&
51 flags |= CA_CI_MODULE_READY;
55 static int firesat_ca_reset(struct firesat *firesat)
58 printk(KERN_INFO "%s: ioctl CA_RESET\n", __func__);
59 if (avc_ca_reset(firesat))
64 static int firesat_ca_get_caps(struct firesat *firesat, void *arg)
66 struct ca_caps *cap_p = (struct ca_caps*)arg;
70 cap_p->slot_type = CA_CI;
72 cap_p->descr_type = CA_ECD;
74 printk(KERN_INFO "%s: ioctl CA_GET_CAP\n", __func__);
78 static int firesat_ca_get_slot_info(struct firesat *firesat, void *arg)
80 ANTENNA_INPUT_INFO info;
81 struct ca_slot_info *slot_p = (struct ca_slot_info*)arg;
84 printk(KERN_INFO "%s: ioctl CA_GET_SLOT_INFO on slot %d.\n",
85 __func__, slot_p->num);
86 if (AVCTunerStatus(firesat, &info))
89 if (slot_p->num == 0) {
91 slot_p->flags = firesat_get_ca_flags(&info);
99 static int firesat_ca_app_info(struct firesat *firesat, void *arg)
101 struct ca_msg *reply_p = (struct ca_msg*)arg;
104 if (avc_ca_app_info(firesat, reply_p->msg, &reply_p->length))
107 printk(KERN_INFO "%s: Creating TAG_APP_INFO message:",
109 for (i = 0; i < reply_p->length; i++)
110 printk("0x%02X, ", (unsigned char)reply_p->msg[i]);
116 static int firesat_ca_info(struct firesat *firesat, void *arg)
118 struct ca_msg *reply_p = (struct ca_msg*)arg;
121 if (avc_ca_info(firesat, reply_p->msg, &reply_p->length))
124 printk(KERN_INFO "%s: Creating TAG_CA_INFO message:",
126 for (i = 0; i < reply_p->length; i++)
127 printk("0x%02X, ", (unsigned char)reply_p->msg[i]);
133 static int firesat_ca_get_mmi(struct firesat *firesat, void *arg)
135 struct ca_msg *reply_p = (struct ca_msg*)arg;
138 if (avc_ca_get_mmi(firesat, reply_p->msg, &reply_p->length))
141 printk(KERN_INFO "%s: Creating MMI reply INFO message:",
143 for (i = 0; i < reply_p->length; i++)
144 printk("0x%02X, ", (unsigned char)reply_p->msg[i]);
150 static int firesat_ca_get_msg(struct firesat *firesat, void *arg)
153 ANTENNA_INPUT_INFO info;
155 switch (firesat->ca_last_command) {
156 case TAG_APP_INFO_ENQUIRY:
157 err = firesat_ca_app_info(firesat, arg);
159 case TAG_CA_INFO_ENQUIRY:
160 err = firesat_ca_info(firesat, arg);
163 if (AVCTunerStatus(firesat, &info))
165 else if (info.CaMmi == 1) {
166 err = firesat_ca_get_mmi(firesat, arg);
169 printk(KERN_INFO "%s: Unhandled message 0x%08X\n",
170 __func__, firesat->ca_last_command);
174 firesat->ca_last_command = 0;
178 static int firesat_ca_pmt(struct firesat *firesat, void *arg)
180 struct ca_msg *msg_p = (struct ca_msg*)arg;
183 if (msg_p->msg[3] & 0x80)
184 data_pos = (msg_p->msg[4] && 0x7F) + 4;
187 if (avc_ca_pmt(firesat, &msg_p->msg[data_pos],
188 msg_p->length - data_pos))
193 static int firesat_ca_send_msg(struct firesat *firesat, void *arg)
196 struct ca_msg *msg_p = (struct ca_msg*)arg;
198 // Do we need a semaphore for this?
199 firesat->ca_last_command =
200 (msg_p->msg[0] << 16) + (msg_p->msg[1] << 8) + msg_p->msg[2];
201 switch (firesat->ca_last_command) {
204 printk(KERN_INFO "%s: Message received: TAG_CA_PMT\n",
206 err = firesat_ca_pmt(firesat, arg);
208 case TAG_APP_INFO_ENQUIRY:
209 // This is all handled in ca_get_msg
211 printk(KERN_INFO "%s: Message received: "
212 "TAG_APP_INFO_ENQUIRY\n", __func__);
215 case TAG_CA_INFO_ENQUIRY:
216 // This is all handled in ca_get_msg
218 printk(KERN_INFO "%s: Message received: "
219 "TAG_CA_APP_INFO_ENQUIRY\n", __func__);
224 printk(KERN_INFO "%s: Entering CA menu.\n", __func__);
225 err = avc_ca_enter_menu(firesat);
228 printk(KERN_ERR "%s: Unhandled unknown message 0x%08X\n",
229 __func__, firesat->ca_last_command);
235 static int firesat_ca_ioctl(struct inode *inode, struct file *file,
236 unsigned int cmd, void *arg)
238 struct dvb_device* dvbdev = (struct dvb_device*) file->private_data;
239 struct firesat *firesat = dvbdev->priv;
241 ANTENNA_INPUT_INFO info;
245 err = firesat_ca_reset(firesat);
248 err = firesat_ca_get_caps(firesat, arg);
250 case CA_GET_SLOT_INFO:
251 err = firesat_ca_get_slot_info(firesat, arg);
254 err = firesat_ca_get_msg(firesat, arg);
257 err = firesat_ca_send_msg(firesat, arg);
260 printk(KERN_INFO "%s: Unhandled ioctl, command: %u\n",__func__,
265 if (AVCTunerStatus(firesat, &info))
268 firesat_ca_ready(&info);
273 static int firesat_get_date_time_request(struct firesat *firesat)
276 printk(KERN_INFO "%s: Retrieving Time/Date request\n",
278 if (avc_ca_get_time_date(firesat, &firesat->ca_time_interval))
281 printk(KERN_INFO "%s: Time/Date interval is %d\n",
282 __func__, firesat->ca_time_interval);
287 static int firesat_ca_io_open(struct inode *inode, struct file *file)
290 printk(KERN_INFO "%s\n",__func__);
291 return dvb_generic_open(inode, file);
294 static int firesat_ca_io_release(struct inode *inode, struct file *file)
297 printk(KERN_INFO "%s\n",__func__);
298 return dvb_generic_release(inode, file);
301 static unsigned int firesat_ca_io_poll(struct file *file, poll_table *wait)
304 printk(KERN_INFO "%s\n",__func__);
308 static struct file_operations firesat_ca_fops = {
309 .owner = THIS_MODULE,
310 .read = NULL, // There is no low level read anymore
311 .write = NULL, // There is no low level write anymore
312 .ioctl = dvb_generic_ioctl,
313 .open = firesat_ca_io_open,
314 .release = firesat_ca_io_release,
315 .poll = firesat_ca_io_poll,
318 static struct dvb_device firesat_ca = {
323 .fops = &firesat_ca_fops,
324 .kernel_ioctl = firesat_ca_ioctl,
327 int firesat_ca_init(struct firesat *firesat)
330 ANTENNA_INPUT_INFO info;
332 if (AVCTunerStatus(firesat, &info))
335 if (firesat_ca_ready(&info)) {
336 err = dvb_register_device(firesat->adapter,
338 &firesat_ca, firesat,
341 if (info.CaApplicationInfo == 0)
342 printk(KERN_ERR "%s: CaApplicationInfo is not set.\n",
344 if (info.CaDateTimeRequest == 1)
345 firesat_get_date_time_request(firesat);
353 void firesat_ca_release(struct firesat *firesat)
356 dvb_unregister_device(firesat->cadev);