diff options
Diffstat (limited to 'drivers/media/dvb/firesat/firesat-ci.c')
-rw-r--r-- | drivers/media/dvb/firesat/firesat-ci.c | 342 |
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 | /* | ||
8 | static 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); | 19 | static unsigned int ca_debug = 0; |
20 | module_param(ca_debug, int, 0644); | ||
21 | MODULE_PARM_DESC(ca_debug, "debug logging of ca system, default is 0 (no)"); | ||
13 | 22 | ||
14 | switch(cmd) { | 23 | static 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 | |||
39 | static 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 | |||
51 | static 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 | |||
60 | static 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 | |||
74 | static 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 | |||
95 | static 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 | |||
112 | static 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 | |||
129 | static 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 | |||
146 | static 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 | ||
174 | static 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 | |||
189 | static 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 | |||
231 | static 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 | ||
47 | static int firesat_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { | 269 | static 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 | ||
52 | static int firesat_ca_io_open(struct inode *inode, struct file *file) { | 283 | static 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 | ||
57 | static int firesat_ca_io_release(struct inode *inode, struct file *file) { | 290 | static 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 | ||
62 | static unsigned int firesat_ca_io_poll(struct file *file, poll_table *wait) { | 297 | static 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 | ||
85 | int firesat_ca_init(struct firesat *firesat) { | 323 | int 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 | ||
93 | void firesat_ca_release(struct firesat *firesat) { | 349 | void 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 | } |