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 int firesat_ca_ready(ANTENNA_INPUT_INFO
*info
)
25 return info
->CaInitializationStatus
== 1 &&
26 info
->CaErrorFlag
== 0 &&
27 info
->CaDvbFlag
== 1 &&
28 info
->CaModulePresentStatus
== 1;
31 static int firesat_get_ca_flags(ANTENNA_INPUT_INFO
*info
)
35 if (info
->CaModulePresentStatus
== 1)
36 flags
|= CA_CI_MODULE_PRESENT
;
37 if (info
->CaInitializationStatus
== 1 &&
38 info
->CaErrorFlag
== 0 &&
40 flags
|= CA_CI_MODULE_READY
;
44 static int firesat_ca_reset(struct firesat
*firesat
)
46 return avc_ca_reset(firesat
) ? -EFAULT
: 0;
49 static int firesat_ca_get_caps(void *arg
)
51 struct ca_caps
*cap
= arg
;
54 cap
->slot_type
= CA_CI
;
56 cap
->descr_type
= CA_ECD
;
60 static int firesat_ca_get_slot_info(struct firesat
*firesat
, void *arg
)
62 ANTENNA_INPUT_INFO info
;
63 struct ca_slot_info
*slot
= arg
;
65 if (avc_tuner_status(firesat
, &info
))
72 slot
->flags
= firesat_get_ca_flags(&info
);
76 static int firesat_ca_app_info(struct firesat
*firesat
, void *arg
)
78 struct ca_msg
*reply
= arg
;
81 avc_ca_app_info(firesat
, reply
->msg
, &reply
->length
) ? -EFAULT
: 0;
84 static int firesat_ca_info(struct firesat
*firesat
, void *arg
)
86 struct ca_msg
*reply
= arg
;
88 return avc_ca_info(firesat
, reply
->msg
, &reply
->length
) ? -EFAULT
: 0;
91 static int firesat_ca_get_mmi(struct firesat
*firesat
, void *arg
)
93 struct ca_msg
*reply
= arg
;
96 avc_ca_get_mmi(firesat
, reply
->msg
, &reply
->length
) ? -EFAULT
: 0;
99 static int firesat_ca_get_msg(struct firesat
*firesat
, void *arg
)
101 ANTENNA_INPUT_INFO info
;
104 switch (firesat
->ca_last_command
) {
105 case TAG_APP_INFO_ENQUIRY
:
106 err
= firesat_ca_app_info(firesat
, arg
);
108 case TAG_CA_INFO_ENQUIRY
:
109 err
= firesat_ca_info(firesat
, arg
);
112 if (avc_tuner_status(firesat
, &info
))
114 else if (info
.CaMmi
== 1)
115 err
= firesat_ca_get_mmi(firesat
, arg
);
117 printk(KERN_INFO
"%s: Unhandled message 0x%08X\n",
118 __func__
, firesat
->ca_last_command
);
122 firesat
->ca_last_command
= 0;
126 static int firesat_ca_pmt(struct firesat
*firesat
, void *arg
)
128 struct ca_msg
*msg
= arg
;
134 if (msg
->msg
[3] & 0x80) {
136 for (i
= 0; i
< (msg
->msg
[3] & 0x7F); i
++)
137 data_length
= (data_length
<< 8) + msg
->msg
[data_pos
++];
139 data_length
= msg
->msg
[3];
142 return avc_ca_pmt(firesat
, &msg
->msg
[data_pos
], data_length
) ?
146 static int firesat_ca_send_msg(struct firesat
*firesat
, void *arg
)
148 struct ca_msg
*msg
= arg
;
151 /* Do we need a semaphore for this? */
152 firesat
->ca_last_command
=
153 (msg
->msg
[0] << 16) + (msg
->msg
[1] << 8) + msg
->msg
[2];
154 switch (firesat
->ca_last_command
) {
156 err
= firesat_ca_pmt(firesat
, arg
);
158 case TAG_APP_INFO_ENQUIRY
:
159 /* handled in ca_get_msg */
162 case TAG_CA_INFO_ENQUIRY
:
163 /* handled in ca_get_msg */
167 err
= avc_ca_enter_menu(firesat
);
170 printk(KERN_ERR
"%s: Unhandled unknown message 0x%08X\n",
171 __func__
, firesat
->ca_last_command
);
177 static int firesat_ca_ioctl(struct inode
*inode
, struct file
*file
,
178 unsigned int cmd
, void *arg
)
180 struct dvb_device
*dvbdev
= file
->private_data
;
181 struct firesat
*firesat
= dvbdev
->priv
;
182 ANTENNA_INPUT_INFO info
;
187 err
= firesat_ca_reset(firesat
);
190 err
= firesat_ca_get_caps(arg
);
192 case CA_GET_SLOT_INFO
:
193 err
= firesat_ca_get_slot_info(firesat
, arg
);
196 err
= firesat_ca_get_msg(firesat
, arg
);
199 err
= firesat_ca_send_msg(firesat
, arg
);
202 printk(KERN_INFO
"%s: Unhandled ioctl, command: %u\n",__func__
,
207 /* FIXME Is this necessary? */
208 avc_tuner_status(firesat
, &info
);
213 static unsigned int firesat_ca_io_poll(struct file
*file
, poll_table
*wait
)
218 static struct file_operations firesat_ca_fops
= {
219 .owner
= THIS_MODULE
,
220 .ioctl
= dvb_generic_ioctl
,
221 .open
= dvb_generic_open
,
222 .release
= dvb_generic_release
,
223 .poll
= firesat_ca_io_poll
,
226 static struct dvb_device firesat_ca
= {
230 .fops
= &firesat_ca_fops
,
231 .kernel_ioctl
= firesat_ca_ioctl
,
234 int firesat_ca_register(struct firesat
*firesat
)
236 ANTENNA_INPUT_INFO info
;
239 if (avc_tuner_status(firesat
, &info
))
242 if (!firesat_ca_ready(&info
))
245 err
= dvb_register_device(&firesat
->adapter
, &firesat
->cadev
,
246 &firesat_ca
, firesat
, DVB_DEVICE_CA
);
248 if (info
.CaApplicationInfo
== 0)
249 printk(KERN_ERR
"%s: CaApplicationInfo is not set.\n",
251 if (info
.CaDateTimeRequest
== 1)
252 avc_ca_get_time_date(firesat
, &firesat
->ca_time_interval
);
257 void firesat_ca_release(struct firesat
*firesat
)
260 dvb_unregister_device(firesat
->cadev
);