1df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid/*
2612262a53352af839a14b3395975a3440c95080aStefan Richter * FireDTV driver (formerly known as FireSAT)
3df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid *
4612262a53352af839a14b3395975a3440c95080aStefan Richter * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
5612262a53352af839a14b3395975a3440c95080aStefan Richter * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
6df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid *
7df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid *	This program is free software; you can redistribute it and/or
8df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid *	modify it under the terms of the GNU General Public License as
9df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid *	published by the Free Software Foundation; either version 2 of
10df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid *	the License, or (at your option) any later version.
11df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid */
12df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
13154907957f9391b1af997b57507b16c018cc4995Stefan Richter#include <linux/device.h>
14c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman#include <linux/dvb/ca.h>
15612262a53352af839a14b3395975a3440c95080aStefan Richter#include <linux/fs.h>
16612262a53352af839a14b3395975a3440c95080aStefan Richter#include <linux/module.h>
17612262a53352af839a14b3395975a3440c95080aStefan Richter
18c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman#include <dvbdev.h>
19c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman
20a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi#include "firedtv.h"
21612262a53352af839a14b3395975a3440c95080aStefan Richter
22154907957f9391b1af997b57507b16c018cc4995Stefan Richter#define EN50221_TAG_APP_INFO_ENQUIRY	0x9f8020
23154907957f9391b1af997b57507b16c018cc4995Stefan Richter#define EN50221_TAG_CA_INFO_ENQUIRY	0x9f8030
24154907957f9391b1af997b57507b16c018cc4995Stefan Richter#define EN50221_TAG_CA_PMT		0x9f8032
25154907957f9391b1af997b57507b16c018cc4995Stefan Richter#define EN50221_TAG_ENTER_MENU		0x9f8022
26154907957f9391b1af997b57507b16c018cc4995Stefan Richter
27154907957f9391b1af997b57507b16c018cc4995Stefan Richterstatic int fdtv_ca_ready(struct firedtv_tuner_status *stat)
28df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid{
29154907957f9391b1af997b57507b16c018cc4995Stefan Richter	return stat->ca_initialization_status	== 1 &&
30154907957f9391b1af997b57507b16c018cc4995Stefan Richter	       stat->ca_error_flag		== 0 &&
31154907957f9391b1af997b57507b16c018cc4995Stefan Richter	       stat->ca_dvb_flag		== 1 &&
32154907957f9391b1af997b57507b16c018cc4995Stefan Richter	       stat->ca_module_present_status	== 1;
33df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid}
34df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
35154907957f9391b1af997b57507b16c018cc4995Stefan Richterstatic int fdtv_get_ca_flags(struct firedtv_tuner_status *stat)
36df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid{
37df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid	int flags = 0;
388ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter
39154907957f9391b1af997b57507b16c018cc4995Stefan Richter	if (stat->ca_module_present_status == 1)
40df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid		flags |= CA_CI_MODULE_PRESENT;
41154907957f9391b1af997b57507b16c018cc4995Stefan Richter	if (stat->ca_initialization_status == 1 &&
42154907957f9391b1af997b57507b16c018cc4995Stefan Richter	    stat->ca_error_flag            == 0 &&
43154907957f9391b1af997b57507b16c018cc4995Stefan Richter	    stat->ca_dvb_flag              == 1)
44df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid		flags |= CA_CI_MODULE_READY;
45df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid	return flags;
46df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid}
47df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
48a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldistatic int fdtv_ca_get_caps(void *arg)
49df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid{
508ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	struct ca_caps *cap = arg;
518ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter
528ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	cap->slot_num = 1;
538ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	cap->slot_type = CA_CI;
548ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	cap->descr_num = 1;
558ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	cap->descr_type = CA_ECD;
568ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	return 0;
57df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid}
58df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
59a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldistatic int fdtv_ca_get_slot_info(struct firedtv *fdtv, void *arg)
60df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid{
61154907957f9391b1af997b57507b16c018cc4995Stefan Richter	struct firedtv_tuner_status stat;
628ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	struct ca_slot_info *slot = arg;
63686a9488cd23cce1fa8a6cddde0e7668ae2e74b4Stefan Richter	int err;
64df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
65686a9488cd23cce1fa8a6cddde0e7668ae2e74b4Stefan Richter	err = avc_tuner_status(fdtv, &stat);
66686a9488cd23cce1fa8a6cddde0e7668ae2e74b4Stefan Richter	if (err)
67686a9488cd23cce1fa8a6cddde0e7668ae2e74b4Stefan Richter		return err;
68df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
698ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	if (slot->num != 0)
70686a9488cd23cce1fa8a6cddde0e7668ae2e74b4Stefan Richter		return -EACCES;
718ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter
728ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	slot->type = CA_CI;
73154907957f9391b1af997b57507b16c018cc4995Stefan Richter	slot->flags = fdtv_get_ca_flags(&stat);
74df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid	return 0;
75df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid}
76df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
77a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldistatic int fdtv_ca_app_info(struct firedtv *fdtv, void *arg)
78df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid{
798ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	struct ca_msg *reply = arg;
80df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
81686a9488cd23cce1fa8a6cddde0e7668ae2e74b4Stefan Richter	return avc_ca_app_info(fdtv, reply->msg, &reply->length);
82df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid}
83df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
84a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldistatic int fdtv_ca_info(struct firedtv *fdtv, void *arg)
85df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid{
868ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	struct ca_msg *reply = arg;
87df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
88686a9488cd23cce1fa8a6cddde0e7668ae2e74b4Stefan Richter	return avc_ca_info(fdtv, reply->msg, &reply->length);
89df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid}
90df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
91a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldistatic int fdtv_ca_get_mmi(struct firedtv *fdtv, void *arg)
92df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid{
938ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	struct ca_msg *reply = arg;
94df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
95686a9488cd23cce1fa8a6cddde0e7668ae2e74b4Stefan Richter	return avc_ca_get_mmi(fdtv, reply->msg, &reply->length);
96df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid}
97df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
98a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldistatic int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg)
99df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid{
100154907957f9391b1af997b57507b16c018cc4995Stefan Richter	struct firedtv_tuner_status stat;
1018ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	int err;
102df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
103a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi	switch (fdtv->ca_last_command) {
104154907957f9391b1af997b57507b16c018cc4995Stefan Richter	case EN50221_TAG_APP_INFO_ENQUIRY:
105a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi		err = fdtv_ca_app_info(fdtv, arg);
106df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid		break;
107154907957f9391b1af997b57507b16c018cc4995Stefan Richter	case EN50221_TAG_CA_INFO_ENQUIRY:
108a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi		err = fdtv_ca_info(fdtv, arg);
109c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman		break;
110df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid	default:
111686a9488cd23cce1fa8a6cddde0e7668ae2e74b4Stefan Richter		err = avc_tuner_status(fdtv, &stat);
112686a9488cd23cce1fa8a6cddde0e7668ae2e74b4Stefan Richter		if (err)
113686a9488cd23cce1fa8a6cddde0e7668ae2e74b4Stefan Richter			break;
114686a9488cd23cce1fa8a6cddde0e7668ae2e74b4Stefan Richter		if (stat.ca_mmi == 1)
115a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi			err = fdtv_ca_get_mmi(fdtv, arg);
116df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid		else {
117154907957f9391b1af997b57507b16c018cc4995Stefan Richter			dev_info(fdtv->device, "unhandled CA message 0x%08x\n",
118154907957f9391b1af997b57507b16c018cc4995Stefan Richter				 fdtv->ca_last_command);
119686a9488cd23cce1fa8a6cddde0e7668ae2e74b4Stefan Richter			err = -EACCES;
120df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid		}
121df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid	}
122a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi	fdtv->ca_last_command = 0;
123df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid	return err;
124df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid}
125c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman
126a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldistatic int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)
127df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid{
1288ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	struct ca_msg *msg = arg;
129df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid	int data_pos;
1307199e523ef71d24cd8030ea454fca00bb52d58f0Henrik Kurelid	int data_length;
1317199e523ef71d24cd8030ea454fca00bb52d58f0Henrik Kurelid	int i;
1327199e523ef71d24cd8030ea454fca00bb52d58f0Henrik Kurelid
1337199e523ef71d24cd8030ea454fca00bb52d58f0Henrik Kurelid	data_pos = 4;
1347199e523ef71d24cd8030ea454fca00bb52d58f0Henrik Kurelid	if (msg->msg[3] & 0x80) {
1357199e523ef71d24cd8030ea454fca00bb52d58f0Henrik Kurelid		data_length = 0;
136154907957f9391b1af997b57507b16c018cc4995Stefan Richter		for (i = 0; i < (msg->msg[3] & 0x7f); i++)
1377199e523ef71d24cd8030ea454fca00bb52d58f0Henrik Kurelid			data_length = (data_length << 8) + msg->msg[data_pos++];
1387199e523ef71d24cd8030ea454fca00bb52d58f0Henrik Kurelid	} else {
1397199e523ef71d24cd8030ea454fca00bb52d58f0Henrik Kurelid		data_length = msg->msg[3];
1407199e523ef71d24cd8030ea454fca00bb52d58f0Henrik Kurelid	}
141df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
142686a9488cd23cce1fa8a6cddde0e7668ae2e74b4Stefan Richter	return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length);
143df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid}
144df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
145a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldistatic int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg)
146df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid{
1478ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	struct ca_msg *msg = arg;
148df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid	int err;
149df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
1508ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	/* Do we need a semaphore for this? */
151a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi	fdtv->ca_last_command =
1528ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter		(msg->msg[0] << 16) + (msg->msg[1] << 8) + msg->msg[2];
153a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi	switch (fdtv->ca_last_command) {
154154907957f9391b1af997b57507b16c018cc4995Stefan Richter	case EN50221_TAG_CA_PMT:
155a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi		err = fdtv_ca_pmt(fdtv, arg);
156df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid		break;
157154907957f9391b1af997b57507b16c018cc4995Stefan Richter	case EN50221_TAG_APP_INFO_ENQUIRY:
1588ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter		/* handled in ca_get_msg */
159c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman		err = 0;
160c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman		break;
161154907957f9391b1af997b57507b16c018cc4995Stefan Richter	case EN50221_TAG_CA_INFO_ENQUIRY:
1628ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter		/* handled in ca_get_msg */
163c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman		err = 0;
164c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman		break;
165154907957f9391b1af997b57507b16c018cc4995Stefan Richter	case EN50221_TAG_ENTER_MENU:
166a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi		err = avc_ca_enter_menu(fdtv);
167df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid		break;
168df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid	default:
169154907957f9391b1af997b57507b16c018cc4995Stefan Richter		dev_err(fdtv->device, "unhandled CA message 0x%08x\n",
170154907957f9391b1af997b57507b16c018cc4995Stefan Richter			fdtv->ca_last_command);
171686a9488cd23cce1fa8a6cddde0e7668ae2e74b4Stefan Richter		err = -EACCES;
172c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman	}
173df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid	return err;
174df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid}
175df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
17616ef8def80ea97c3cacdcaa765bdf62b2d94f86dArnd Bergmannstatic int fdtv_ca_ioctl(struct file *file, unsigned int cmd, void *arg)
177df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid{
1788ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	struct dvb_device *dvbdev = file->private_data;
179a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi	struct firedtv *fdtv = dvbdev->priv;
180154907957f9391b1af997b57507b16c018cc4995Stefan Richter	struct firedtv_tuner_status stat;
1818ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	int err;
182df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
183154907957f9391b1af997b57507b16c018cc4995Stefan Richter	switch (cmd) {
184df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid	case CA_RESET:
185686a9488cd23cce1fa8a6cddde0e7668ae2e74b4Stefan Richter		err = avc_ca_reset(fdtv);
186df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid		break;
187df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid	case CA_GET_CAP:
188a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi		err = fdtv_ca_get_caps(arg);
189df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid		break;
190df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid	case CA_GET_SLOT_INFO:
191a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi		err = fdtv_ca_get_slot_info(fdtv, arg);
192df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid		break;
193df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid	case CA_GET_MSG:
194a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi		err = fdtv_ca_get_msg(fdtv, arg);
195df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid		break;
196df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid	case CA_SEND_MSG:
197a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi		err = fdtv_ca_send_msg(fdtv, arg);
198df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid		break;
199c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman	default:
200154907957f9391b1af997b57507b16c018cc4995Stefan Richter		dev_info(fdtv->device, "unhandled CA ioctl %u\n", cmd);
201df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid		err = -EOPNOTSUPP;
202c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman	}
203df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
2048ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	/* FIXME Is this necessary? */
205154907957f9391b1af997b57507b16c018cc4995Stefan Richter	avc_tuner_status(fdtv, &stat);
206df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
207c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman	return err;
208c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman}
209c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman
210a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldistatic unsigned int fdtv_ca_io_poll(struct file *file, poll_table *wait)
211df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid{
212c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman	return POLLIN;
213c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman}
214c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman
215828c09509b9695271bcbdc53e9fc9a6a737148d2Alexey Dobriyanstatic const struct file_operations fdtv_ca_fops = {
2168ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	.owner		= THIS_MODULE,
21716ef8def80ea97c3cacdcaa765bdf62b2d94f86dArnd Bergmann	.unlocked_ioctl	= dvb_generic_ioctl,
2188ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	.open		= dvb_generic_open,
2198ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	.release	= dvb_generic_release,
220a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi	.poll		= fdtv_ca_io_poll,
2216038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann	.llseek		= noop_llseek,
222c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman};
223c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman
224a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldistatic struct dvb_device fdtv_ca = {
2258ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	.users		= 1,
2268ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	.readers	= 1,
2278ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	.writers	= 1,
228a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi	.fops		= &fdtv_ca_fops,
229a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi	.kernel_ioctl	= fdtv_ca_ioctl,
230c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman};
231c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman
232a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldiint fdtv_ca_register(struct firedtv *fdtv)
233df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid{
234154907957f9391b1af997b57507b16c018cc4995Stefan Richter	struct firedtv_tuner_status stat;
2358ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter	int err;
236c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman
237154907957f9391b1af997b57507b16c018cc4995Stefan Richter	if (avc_tuner_status(fdtv, &stat))
238df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid		return -EINVAL;
239df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
240154907957f9391b1af997b57507b16c018cc4995Stefan Richter	if (!fdtv_ca_ready(&stat))
2418ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter		return -EFAULT;
2428ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter
243a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi	err = dvb_register_device(&fdtv->adapter, &fdtv->cadev,
244a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi				  &fdtv_ca, fdtv, DVB_DEVICE_CA);
2458ae83cdf3297d7da301af36bdb6ff45bd331c6d0Stefan Richter
246154907957f9391b1af997b57507b16c018cc4995Stefan Richter	if (stat.ca_application_info == 0)
247154907957f9391b1af997b57507b16c018cc4995Stefan Richter		dev_err(fdtv->device, "CaApplicationInfo is not set\n");
248154907957f9391b1af997b57507b16c018cc4995Stefan Richter	if (stat.ca_date_time_request == 1)
249a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi		avc_ca_get_time_date(fdtv, &fdtv->ca_time_interval);
250df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid
251df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid	return err;
252c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman}
253c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman
254a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldivoid fdtv_ca_release(struct firedtv *fdtv)
255df4846c35247a0d038c5359d502cddd59d04bc40Henrik Kurelid{
256a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi	if (fdtv->cadev)
257a70f81c1c0dac113ac4705e7701e2676e67905cdRambaldi		dvb_unregister_device(fdtv->cadev);
258c81c8b68b46752721b0c1addfabb828da27e1489Greg Kroah-Hartman}
259