diff options
author | Rambaldi <Rambaldi@xs4all.nl> | 2009-01-17 08:47:34 -0500 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-02-24 08:51:29 -0500 |
commit | a70f81c1c0dac113ac4705e7701e2676e67905cd (patch) | |
tree | 2ff18425bc3b9a4cbf083c82e011a06a0f88f926 /drivers/media/dvb/firewire | |
parent | 291f006efeebeeb2073289e44efb8f97cf157220 (diff) |
firedtv: rename files, variables, functions from firesat to firedtv
Combination of the following changes:
Sat, 17 Jan 2009 14:47:34 +0100
firedtv: rename variables and functions from firesat to firedtv
Signed-off-by: Rambaldi <Rambaldi@xs4all.nl>
Additional changes by Stefan Richter:
Renamed struct firedtv *firedtv to struct firedtv *fdtv and
firedtv_foo_bar() to fdtv_foo_bar() for brevity.
Sat, 17 Jan 2009 13:07:44 +0100
firedtv: rename files from firesat to firedtv
Signed-off-by: Rambaldi <Rambaldi@xs4all.nl>
Additional changes by Stefan Richter:
Name the directory "firewire" instead of "firedtv".
Standardize on "-" instead of "_" in file names, because that's what
drivers/firewire/ and drivers/media/dvb/dvb-usb/ use too.
Build fix.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/media/dvb/firewire')
-rw-r--r-- | drivers/media/dvb/firewire/Kconfig | 12 | ||||
-rw-r--r-- | drivers/media/dvb/firewire/Makefile | 13 | ||||
-rw-r--r-- | drivers/media/dvb/firewire/avc.c | 1051 | ||||
-rw-r--r-- | drivers/media/dvb/firewire/avc.h | 432 | ||||
-rw-r--r-- | drivers/media/dvb/firewire/cmp.c | 171 | ||||
-rw-r--r-- | drivers/media/dvb/firewire/cmp.h | 9 | ||||
-rw-r--r-- | drivers/media/dvb/firewire/firedtv-1394.c | 291 | ||||
-rw-r--r-- | drivers/media/dvb/firewire/firedtv-ci.c | 261 | ||||
-rw-r--r-- | drivers/media/dvb/firewire/firedtv-ci.h | 9 | ||||
-rw-r--r-- | drivers/media/dvb/firewire/firedtv-dvb.c | 276 | ||||
-rw-r--r-- | drivers/media/dvb/firewire/firedtv-fe.c | 245 | ||||
-rw-r--r-- | drivers/media/dvb/firewire/firedtv-iso.c | 111 | ||||
-rw-r--r-- | drivers/media/dvb/firewire/firedtv-rc.c | 191 | ||||
-rw-r--r-- | drivers/media/dvb/firewire/firedtv-rc.h | 11 | ||||
-rw-r--r-- | drivers/media/dvb/firewire/firedtv.h | 227 |
15 files changed, 3310 insertions, 0 deletions
diff --git a/drivers/media/dvb/firewire/Kconfig b/drivers/media/dvb/firewire/Kconfig new file mode 100644 index 000000000000..03d25ad10350 --- /dev/null +++ b/drivers/media/dvb/firewire/Kconfig | |||
@@ -0,0 +1,12 @@ | |||
1 | config DVB_FIREDTV | ||
2 | tristate "FireDTV (FireWire attached DVB receivers)" | ||
3 | depends on DVB_CORE && IEEE1394 && INPUT | ||
4 | help | ||
5 | Support for DVB receivers from Digital Everywhere, known as FireDTV | ||
6 | and FloppyDTV, which are connected via IEEE 1394 (FireWire). | ||
7 | |||
8 | These devices don't have an MPEG decoder built in, so you need | ||
9 | an external software decoder to watch TV. | ||
10 | |||
11 | To compile this driver as a module, say M here: the module will be | ||
12 | called firedtv. | ||
diff --git a/drivers/media/dvb/firewire/Makefile b/drivers/media/dvb/firewire/Makefile new file mode 100644 index 000000000000..628dacd10daf --- /dev/null +++ b/drivers/media/dvb/firewire/Makefile | |||
@@ -0,0 +1,13 @@ | |||
1 | firedtv-objs := firedtv-1394.o \ | ||
2 | firedtv-dvb.o \ | ||
3 | firedtv-fe.o \ | ||
4 | firedtv-iso.o \ | ||
5 | avc.o \ | ||
6 | cmp.o \ | ||
7 | firedtv-rc.o \ | ||
8 | firedtv-ci.o | ||
9 | |||
10 | obj-$(CONFIG_DVB_FIREDTV) += firedtv.o | ||
11 | |||
12 | EXTRA_CFLAGS := -Idrivers/ieee1394 | ||
13 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | ||
diff --git a/drivers/media/dvb/firewire/avc.c b/drivers/media/dvb/firewire/avc.c new file mode 100644 index 000000000000..847a537b1f58 --- /dev/null +++ b/drivers/media/dvb/firewire/avc.c | |||
@@ -0,0 +1,1051 @@ | |||
1 | /* | ||
2 | * FireDTV driver (formerly known as FireSAT) | ||
3 | * | ||
4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
5 | * Copyright (C) 2008 Ben Backx <ben@bbackx.com> | ||
6 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License as | ||
10 | * published by the Free Software Foundation; either version 2 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/bug.h> | ||
15 | #include <linux/crc32.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/moduleparam.h> | ||
20 | #include <linux/mutex.h> | ||
21 | #include <linux/string.h> | ||
22 | #include <linux/wait.h> | ||
23 | #include <linux/workqueue.h> | ||
24 | |||
25 | #include <ieee1394_transactions.h> | ||
26 | #include <nodemgr.h> | ||
27 | |||
28 | #include "avc.h" | ||
29 | #include "firedtv.h" | ||
30 | #include "firedtv-rc.h" | ||
31 | |||
32 | #define FCP_COMMAND_REGISTER 0xfffff0000b00ULL | ||
33 | |||
34 | static int __avc_write(struct firedtv *fdtv, | ||
35 | const AVCCmdFrm *CmdFrm, AVCRspFrm *RspFrm) | ||
36 | { | ||
37 | int err, retry; | ||
38 | |||
39 | if (RspFrm) | ||
40 | fdtv->avc_reply_received = false; | ||
41 | |||
42 | for (retry = 0; retry < 6; retry++) { | ||
43 | err = hpsb_node_write(fdtv->ud->ne, FCP_COMMAND_REGISTER, | ||
44 | (quadlet_t *)CmdFrm, CmdFrm->length); | ||
45 | if (err) { | ||
46 | fdtv->avc_reply_received = true; | ||
47 | dev_err(&fdtv->ud->device, | ||
48 | "FCP command write failed\n"); | ||
49 | return err; | ||
50 | } | ||
51 | |||
52 | if (!RspFrm) | ||
53 | return 0; | ||
54 | |||
55 | /* | ||
56 | * AV/C specs say that answers should be sent within 150 ms. | ||
57 | * Time out after 200 ms. | ||
58 | */ | ||
59 | if (wait_event_timeout(fdtv->avc_wait, | ||
60 | fdtv->avc_reply_received, | ||
61 | HZ / 5) != 0) { | ||
62 | memcpy(RspFrm, fdtv->respfrm, fdtv->resp_length); | ||
63 | RspFrm->length = fdtv->resp_length; | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | } | ||
68 | dev_err(&fdtv->ud->device, "FCP response timed out\n"); | ||
69 | return -ETIMEDOUT; | ||
70 | } | ||
71 | |||
72 | static int avc_write(struct firedtv *fdtv, | ||
73 | const AVCCmdFrm *CmdFrm, AVCRspFrm *RspFrm) | ||
74 | { | ||
75 | int ret; | ||
76 | |||
77 | if (mutex_lock_interruptible(&fdtv->avc_mutex)) | ||
78 | return -EINTR; | ||
79 | |||
80 | ret = __avc_write(fdtv, CmdFrm, RspFrm); | ||
81 | |||
82 | mutex_unlock(&fdtv->avc_mutex); | ||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | int avc_recv(struct firedtv *fdtv, u8 *data, size_t length) | ||
87 | { | ||
88 | AVCRspFrm *RspFrm = (AVCRspFrm *)data; | ||
89 | |||
90 | if (length >= 8 && | ||
91 | RspFrm->operand[0] == SFE_VENDOR_DE_COMPANYID_0 && | ||
92 | RspFrm->operand[1] == SFE_VENDOR_DE_COMPANYID_1 && | ||
93 | RspFrm->operand[2] == SFE_VENDOR_DE_COMPANYID_2 && | ||
94 | RspFrm->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL) { | ||
95 | if (RspFrm->resp == CHANGED) { | ||
96 | fdtv_handle_rc(fdtv, | ||
97 | RspFrm->operand[4] << 8 | RspFrm->operand[5]); | ||
98 | schedule_work(&fdtv->remote_ctrl_work); | ||
99 | } else if (RspFrm->resp != INTERIM) { | ||
100 | dev_info(&fdtv->ud->device, | ||
101 | "remote control result = %d\n", RspFrm->resp); | ||
102 | } | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | if (fdtv->avc_reply_received) { | ||
107 | dev_err(&fdtv->ud->device, | ||
108 | "received out-of-order AVC response, ignored\n"); | ||
109 | return -EIO; | ||
110 | } | ||
111 | |||
112 | memcpy(fdtv->respfrm, data, length); | ||
113 | fdtv->resp_length = length; | ||
114 | |||
115 | fdtv->avc_reply_received = true; | ||
116 | wake_up(&fdtv->avc_wait); | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * tuning command for setting the relative LNB frequency | ||
123 | * (not supported by the AVC standard) | ||
124 | */ | ||
125 | static void avc_tuner_tuneqpsk(struct firedtv *fdtv, | ||
126 | struct dvb_frontend_parameters *params, AVCCmdFrm *CmdFrm) | ||
127 | { | ||
128 | CmdFrm->opcode = VENDOR; | ||
129 | |||
130 | CmdFrm->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
131 | CmdFrm->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
132 | CmdFrm->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
133 | CmdFrm->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK; | ||
134 | |||
135 | CmdFrm->operand[4] = (params->frequency >> 24) & 0xff; | ||
136 | CmdFrm->operand[5] = (params->frequency >> 16) & 0xff; | ||
137 | CmdFrm->operand[6] = (params->frequency >> 8) & 0xff; | ||
138 | CmdFrm->operand[7] = params->frequency & 0xff; | ||
139 | |||
140 | CmdFrm->operand[8] = ((params->u.qpsk.symbol_rate / 1000) >> 8) & 0xff; | ||
141 | CmdFrm->operand[9] = (params->u.qpsk.symbol_rate / 1000) & 0xff; | ||
142 | |||
143 | switch(params->u.qpsk.fec_inner) { | ||
144 | case FEC_1_2: | ||
145 | CmdFrm->operand[10] = 0x1; break; | ||
146 | case FEC_2_3: | ||
147 | CmdFrm->operand[10] = 0x2; break; | ||
148 | case FEC_3_4: | ||
149 | CmdFrm->operand[10] = 0x3; break; | ||
150 | case FEC_5_6: | ||
151 | CmdFrm->operand[10] = 0x4; break; | ||
152 | case FEC_7_8: | ||
153 | CmdFrm->operand[10] = 0x5; break; | ||
154 | case FEC_4_5: | ||
155 | case FEC_8_9: | ||
156 | case FEC_AUTO: | ||
157 | default: | ||
158 | CmdFrm->operand[10] = 0x0; | ||
159 | } | ||
160 | |||
161 | if (fdtv->voltage == 0xff) | ||
162 | CmdFrm->operand[11] = 0xff; | ||
163 | else if (fdtv->voltage == SEC_VOLTAGE_18) /* polarisation */ | ||
164 | CmdFrm->operand[11] = 0; | ||
165 | else | ||
166 | CmdFrm->operand[11] = 1; | ||
167 | |||
168 | if (fdtv->tone == 0xff) | ||
169 | CmdFrm->operand[12] = 0xff; | ||
170 | else if (fdtv->tone == SEC_TONE_ON) /* band */ | ||
171 | CmdFrm->operand[12] = 1; | ||
172 | else | ||
173 | CmdFrm->operand[12] = 0; | ||
174 | |||
175 | if (fdtv->type == FIREDTV_DVB_S2) { | ||
176 | CmdFrm->operand[13] = 0x1; | ||
177 | CmdFrm->operand[14] = 0xff; | ||
178 | CmdFrm->operand[15] = 0xff; | ||
179 | CmdFrm->length = 20; | ||
180 | } else { | ||
181 | CmdFrm->length = 16; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | static void avc_tuner_dsd_dvb_c(struct dvb_frontend_parameters *params, | ||
186 | AVCCmdFrm *CmdFrm) | ||
187 | { | ||
188 | M_VALID_FLAGS flags; | ||
189 | |||
190 | flags.Bits.Modulation = params->u.qam.modulation != QAM_AUTO; | ||
191 | flags.Bits.FEC_inner = params->u.qam.fec_inner != FEC_AUTO; | ||
192 | flags.Bits.FEC_outer = 0; | ||
193 | flags.Bits.Symbol_Rate = 1; | ||
194 | flags.Bits.Frequency = 1; | ||
195 | flags.Bits.Orbital_Pos = 0; | ||
196 | flags.Bits.Polarisation = 0; | ||
197 | flags.Bits.reserved_fields = 0; | ||
198 | flags.Bits.reserved1 = 0; | ||
199 | flags.Bits.Network_ID = 0; | ||
200 | |||
201 | CmdFrm->opcode = DSD; | ||
202 | |||
203 | CmdFrm->operand[0] = 0; /* source plug */ | ||
204 | CmdFrm->operand[1] = 0xd2; /* subfunction replace */ | ||
205 | CmdFrm->operand[2] = 0x20; /* system id = DVB */ | ||
206 | CmdFrm->operand[3] = 0x00; /* antenna number */ | ||
207 | /* system_specific_multiplex selection_length */ | ||
208 | CmdFrm->operand[4] = 0x11; | ||
209 | CmdFrm->operand[5] = flags.Valid_Word.ByteHi; /* valid_flags [0] */ | ||
210 | CmdFrm->operand[6] = flags.Valid_Word.ByteLo; /* valid_flags [1] */ | ||
211 | CmdFrm->operand[7] = 0x00; | ||
212 | CmdFrm->operand[8] = 0x00; | ||
213 | CmdFrm->operand[9] = 0x00; | ||
214 | CmdFrm->operand[10] = 0x00; | ||
215 | |||
216 | CmdFrm->operand[11] = | ||
217 | (((params->frequency / 4000) >> 16) & 0xff) | (2 << 6); | ||
218 | CmdFrm->operand[12] = | ||
219 | ((params->frequency / 4000) >> 8) & 0xff; | ||
220 | CmdFrm->operand[13] = (params->frequency / 4000) & 0xff; | ||
221 | CmdFrm->operand[14] = | ||
222 | ((params->u.qpsk.symbol_rate / 1000) >> 12) & 0xff; | ||
223 | CmdFrm->operand[15] = | ||
224 | ((params->u.qpsk.symbol_rate / 1000) >> 4) & 0xff; | ||
225 | CmdFrm->operand[16] = | ||
226 | ((params->u.qpsk.symbol_rate / 1000) << 4) & 0xf0; | ||
227 | CmdFrm->operand[17] = 0x00; | ||
228 | |||
229 | switch (params->u.qpsk.fec_inner) { | ||
230 | case FEC_1_2: | ||
231 | CmdFrm->operand[18] = 0x1; break; | ||
232 | case FEC_2_3: | ||
233 | CmdFrm->operand[18] = 0x2; break; | ||
234 | case FEC_3_4: | ||
235 | CmdFrm->operand[18] = 0x3; break; | ||
236 | case FEC_5_6: | ||
237 | CmdFrm->operand[18] = 0x4; break; | ||
238 | case FEC_7_8: | ||
239 | CmdFrm->operand[18] = 0x5; break; | ||
240 | case FEC_8_9: | ||
241 | CmdFrm->operand[18] = 0x6; break; | ||
242 | case FEC_4_5: | ||
243 | CmdFrm->operand[18] = 0x8; break; | ||
244 | case FEC_AUTO: | ||
245 | default: | ||
246 | CmdFrm->operand[18] = 0x0; | ||
247 | } | ||
248 | switch (params->u.qam.modulation) { | ||
249 | case QAM_16: | ||
250 | CmdFrm->operand[19] = 0x08; break; | ||
251 | case QAM_32: | ||
252 | CmdFrm->operand[19] = 0x10; break; | ||
253 | case QAM_64: | ||
254 | CmdFrm->operand[19] = 0x18; break; | ||
255 | case QAM_128: | ||
256 | CmdFrm->operand[19] = 0x20; break; | ||
257 | case QAM_256: | ||
258 | CmdFrm->operand[19] = 0x28; break; | ||
259 | case QAM_AUTO: | ||
260 | default: | ||
261 | CmdFrm->operand[19] = 0x00; | ||
262 | } | ||
263 | CmdFrm->operand[20] = 0x00; | ||
264 | CmdFrm->operand[21] = 0x00; | ||
265 | /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */ | ||
266 | CmdFrm->operand[22] = 0x00; | ||
267 | |||
268 | CmdFrm->length = 28; | ||
269 | } | ||
270 | |||
271 | static void avc_tuner_dsd_dvb_t(struct dvb_frontend_parameters *params, | ||
272 | AVCCmdFrm *CmdFrm) | ||
273 | { | ||
274 | M_VALID_FLAGS flags; | ||
275 | |||
276 | flags.Bits_T.GuardInterval = | ||
277 | params->u.ofdm.guard_interval != GUARD_INTERVAL_AUTO; | ||
278 | flags.Bits_T.CodeRateLPStream = | ||
279 | params->u.ofdm.code_rate_LP != FEC_AUTO; | ||
280 | flags.Bits_T.CodeRateHPStream = | ||
281 | params->u.ofdm.code_rate_HP != FEC_AUTO; | ||
282 | flags.Bits_T.HierarchyInfo = | ||
283 | params->u.ofdm.hierarchy_information != HIERARCHY_AUTO; | ||
284 | flags.Bits_T.Constellation = | ||
285 | params->u.ofdm.constellation != QAM_AUTO; | ||
286 | flags.Bits_T.Bandwidth = | ||
287 | params->u.ofdm.bandwidth != BANDWIDTH_AUTO; | ||
288 | flags.Bits_T.CenterFrequency = 1; | ||
289 | flags.Bits_T.reserved1 = 0; | ||
290 | flags.Bits_T.reserved2 = 0; | ||
291 | flags.Bits_T.OtherFrequencyFlag = 0; | ||
292 | flags.Bits_T.TransmissionMode = | ||
293 | params->u.ofdm.transmission_mode != TRANSMISSION_MODE_AUTO; | ||
294 | flags.Bits_T.NetworkId = 0; | ||
295 | |||
296 | CmdFrm->opcode = DSD; | ||
297 | |||
298 | CmdFrm->operand[0] = 0; /* source plug */ | ||
299 | CmdFrm->operand[1] = 0xd2; /* subfunction replace */ | ||
300 | CmdFrm->operand[2] = 0x20; /* system id = DVB */ | ||
301 | CmdFrm->operand[3] = 0x00; /* antenna number */ | ||
302 | /* system_specific_multiplex selection_length */ | ||
303 | CmdFrm->operand[4] = 0x0c; | ||
304 | CmdFrm->operand[5] = flags.Valid_Word.ByteHi; /* valid_flags [0] */ | ||
305 | CmdFrm->operand[6] = flags.Valid_Word.ByteLo; /* valid_flags [1] */ | ||
306 | CmdFrm->operand[7] = 0x0; | ||
307 | CmdFrm->operand[8] = (params->frequency / 10) >> 24; | ||
308 | CmdFrm->operand[9] = ((params->frequency / 10) >> 16) & 0xff; | ||
309 | CmdFrm->operand[10] = ((params->frequency / 10) >> 8) & 0xff; | ||
310 | CmdFrm->operand[11] = (params->frequency / 10) & 0xff; | ||
311 | |||
312 | switch (params->u.ofdm.bandwidth) { | ||
313 | case BANDWIDTH_7_MHZ: | ||
314 | CmdFrm->operand[12] = 0x20; break; | ||
315 | case BANDWIDTH_8_MHZ: | ||
316 | case BANDWIDTH_6_MHZ: /* not defined by AVC spec */ | ||
317 | case BANDWIDTH_AUTO: | ||
318 | default: | ||
319 | CmdFrm->operand[12] = 0x00; | ||
320 | } | ||
321 | switch (params->u.ofdm.constellation) { | ||
322 | case QAM_16: | ||
323 | CmdFrm->operand[13] = 1 << 6; break; | ||
324 | case QAM_64: | ||
325 | CmdFrm->operand[13] = 2 << 6; break; | ||
326 | case QPSK: | ||
327 | default: | ||
328 | CmdFrm->operand[13] = 0x00; | ||
329 | } | ||
330 | switch (params->u.ofdm.hierarchy_information) { | ||
331 | case HIERARCHY_1: | ||
332 | CmdFrm->operand[13] |= 1 << 3; break; | ||
333 | case HIERARCHY_2: | ||
334 | CmdFrm->operand[13] |= 2 << 3; break; | ||
335 | case HIERARCHY_4: | ||
336 | CmdFrm->operand[13] |= 3 << 3; break; | ||
337 | case HIERARCHY_AUTO: | ||
338 | case HIERARCHY_NONE: | ||
339 | default: | ||
340 | break; | ||
341 | } | ||
342 | switch (params->u.ofdm.code_rate_HP) { | ||
343 | case FEC_2_3: | ||
344 | CmdFrm->operand[13] |= 1; break; | ||
345 | case FEC_3_4: | ||
346 | CmdFrm->operand[13] |= 2; break; | ||
347 | case FEC_5_6: | ||
348 | CmdFrm->operand[13] |= 3; break; | ||
349 | case FEC_7_8: | ||
350 | CmdFrm->operand[13] |= 4; break; | ||
351 | case FEC_1_2: | ||
352 | default: | ||
353 | break; | ||
354 | } | ||
355 | switch (params->u.ofdm.code_rate_LP) { | ||
356 | case FEC_2_3: | ||
357 | CmdFrm->operand[14] = 1 << 5; break; | ||
358 | case FEC_3_4: | ||
359 | CmdFrm->operand[14] = 2 << 5; break; | ||
360 | case FEC_5_6: | ||
361 | CmdFrm->operand[14] = 3 << 5; break; | ||
362 | case FEC_7_8: | ||
363 | CmdFrm->operand[14] = 4 << 5; break; | ||
364 | case FEC_1_2: | ||
365 | default: | ||
366 | CmdFrm->operand[14] = 0x00; break; | ||
367 | } | ||
368 | switch (params->u.ofdm.guard_interval) { | ||
369 | case GUARD_INTERVAL_1_16: | ||
370 | CmdFrm->operand[14] |= 1 << 3; break; | ||
371 | case GUARD_INTERVAL_1_8: | ||
372 | CmdFrm->operand[14] |= 2 << 3; break; | ||
373 | case GUARD_INTERVAL_1_4: | ||
374 | CmdFrm->operand[14] |= 3 << 3; break; | ||
375 | case GUARD_INTERVAL_1_32: | ||
376 | case GUARD_INTERVAL_AUTO: | ||
377 | default: | ||
378 | break; | ||
379 | } | ||
380 | switch (params->u.ofdm.transmission_mode) { | ||
381 | case TRANSMISSION_MODE_8K: | ||
382 | CmdFrm->operand[14] |= 1 << 1; break; | ||
383 | case TRANSMISSION_MODE_2K: | ||
384 | case TRANSMISSION_MODE_AUTO: | ||
385 | default: | ||
386 | break; | ||
387 | } | ||
388 | |||
389 | CmdFrm->operand[15] = 0x00; /* network_ID[0] */ | ||
390 | CmdFrm->operand[16] = 0x00; /* network_ID[1] */ | ||
391 | /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */ | ||
392 | CmdFrm->operand[17] = 0x00; | ||
393 | |||
394 | CmdFrm->length = 24; | ||
395 | } | ||
396 | |||
397 | int avc_tuner_dsd(struct firedtv *fdtv, | ||
398 | struct dvb_frontend_parameters *params) | ||
399 | { | ||
400 | AVCCmdFrm CmdFrm; | ||
401 | AVCRspFrm RspFrm; | ||
402 | |||
403 | memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); | ||
404 | |||
405 | CmdFrm.cts = AVC; | ||
406 | CmdFrm.ctype = CONTROL; | ||
407 | CmdFrm.sutyp = 0x5; | ||
408 | CmdFrm.suid = fdtv->subunit; | ||
409 | |||
410 | switch (fdtv->type) { | ||
411 | case FIREDTV_DVB_S: | ||
412 | case FIREDTV_DVB_S2: | ||
413 | avc_tuner_tuneqpsk(fdtv, params, &CmdFrm); break; | ||
414 | case FIREDTV_DVB_C: | ||
415 | avc_tuner_dsd_dvb_c(params, &CmdFrm); break; | ||
416 | case FIREDTV_DVB_T: | ||
417 | avc_tuner_dsd_dvb_t(params, &CmdFrm); break; | ||
418 | default: | ||
419 | BUG(); | ||
420 | } | ||
421 | |||
422 | if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0) | ||
423 | return -EIO; | ||
424 | |||
425 | msleep(500); | ||
426 | #if 0 | ||
427 | /* FIXME: */ | ||
428 | /* u8 *status was an out-parameter of avc_tuner_dsd, unused by caller */ | ||
429 | if(status) | ||
430 | *status=RspFrm.operand[2]; | ||
431 | #endif | ||
432 | return 0; | ||
433 | } | ||
434 | |||
435 | int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]) | ||
436 | { | ||
437 | AVCCmdFrm CmdFrm; | ||
438 | AVCRspFrm RspFrm; | ||
439 | int pos, k; | ||
440 | |||
441 | if (pidc > 16 && pidc != 0xff) | ||
442 | return -EINVAL; | ||
443 | |||
444 | memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); | ||
445 | |||
446 | CmdFrm.cts = AVC; | ||
447 | CmdFrm.ctype = CONTROL; | ||
448 | CmdFrm.sutyp = 0x5; | ||
449 | CmdFrm.suid = fdtv->subunit; | ||
450 | CmdFrm.opcode = DSD; | ||
451 | |||
452 | CmdFrm.operand[0] = 0; // source plug | ||
453 | CmdFrm.operand[1] = 0xD2; // subfunction replace | ||
454 | CmdFrm.operand[2] = 0x20; // system id = DVB | ||
455 | CmdFrm.operand[3] = 0x00; // antenna number | ||
456 | CmdFrm.operand[4] = 0x00; // system_specific_multiplex selection_length | ||
457 | CmdFrm.operand[5] = pidc; // Nr_of_dsd_sel_specs | ||
458 | |||
459 | pos = 6; | ||
460 | if (pidc != 0xff) | ||
461 | for (k = 0; k < pidc; k++) { | ||
462 | CmdFrm.operand[pos++] = 0x13; // flowfunction relay | ||
463 | CmdFrm.operand[pos++] = 0x80; // dsd_sel_spec_valid_flags -> PID | ||
464 | CmdFrm.operand[pos++] = (pid[k] >> 8) & 0x1F; | ||
465 | CmdFrm.operand[pos++] = pid[k] & 0xFF; | ||
466 | CmdFrm.operand[pos++] = 0x00; // tableID | ||
467 | CmdFrm.operand[pos++] = 0x00; // filter_length | ||
468 | } | ||
469 | |||
470 | CmdFrm.length = ALIGN(3 + pos, 4); | ||
471 | |||
472 | if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0) | ||
473 | return -EIO; | ||
474 | |||
475 | msleep(50); | ||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | int avc_tuner_get_ts(struct firedtv *fdtv) | ||
480 | { | ||
481 | AVCCmdFrm CmdFrm; | ||
482 | AVCRspFrm RspFrm; | ||
483 | |||
484 | memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); | ||
485 | |||
486 | CmdFrm.cts = AVC; | ||
487 | CmdFrm.ctype = CONTROL; | ||
488 | CmdFrm.sutyp = 0x5; | ||
489 | CmdFrm.suid = fdtv->subunit; | ||
490 | CmdFrm.opcode = DSIT; | ||
491 | |||
492 | CmdFrm.operand[0] = 0; // source plug | ||
493 | CmdFrm.operand[1] = 0xD2; // subfunction replace | ||
494 | CmdFrm.operand[2] = 0xFF; //status | ||
495 | CmdFrm.operand[3] = 0x20; // system id = DVB | ||
496 | CmdFrm.operand[4] = 0x00; // antenna number | ||
497 | CmdFrm.operand[5] = 0x0; // system_specific_search_flags | ||
498 | CmdFrm.operand[6] = (fdtv->type == FIREDTV_DVB_T)?0x0c:0x11; // system_specific_multiplex selection_length | ||
499 | CmdFrm.operand[7] = 0x00; // valid_flags [0] | ||
500 | CmdFrm.operand[8] = 0x00; // valid_flags [1] | ||
501 | CmdFrm.operand[7 + (fdtv->type == FIREDTV_DVB_T)?0x0c:0x11] = 0x00; // nr_of_dsit_sel_specs (always 0) | ||
502 | |||
503 | CmdFrm.length = (fdtv->type == FIREDTV_DVB_T)?24:28; | ||
504 | |||
505 | if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0) | ||
506 | return -EIO; | ||
507 | |||
508 | msleep(250); | ||
509 | return 0; | ||
510 | } | ||
511 | |||
512 | int avc_identify_subunit(struct firedtv *fdtv) | ||
513 | { | ||
514 | AVCCmdFrm CmdFrm; | ||
515 | AVCRspFrm RspFrm; | ||
516 | |||
517 | memset(&CmdFrm,0,sizeof(AVCCmdFrm)); | ||
518 | |||
519 | CmdFrm.cts = AVC; | ||
520 | CmdFrm.ctype = CONTROL; | ||
521 | CmdFrm.sutyp = 0x5; // tuner | ||
522 | CmdFrm.suid = fdtv->subunit; | ||
523 | CmdFrm.opcode = READ_DESCRIPTOR; | ||
524 | |||
525 | CmdFrm.operand[0]=DESCRIPTOR_SUBUNIT_IDENTIFIER; | ||
526 | CmdFrm.operand[1]=0xff; | ||
527 | CmdFrm.operand[2]=0x00; | ||
528 | CmdFrm.operand[3]=0x00; // length highbyte | ||
529 | CmdFrm.operand[4]=0x08; // length lowbyte | ||
530 | CmdFrm.operand[5]=0x00; // offset highbyte | ||
531 | CmdFrm.operand[6]=0x0d; // offset lowbyte | ||
532 | |||
533 | CmdFrm.length=12; | ||
534 | |||
535 | if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0) | ||
536 | return -EIO; | ||
537 | |||
538 | if ((RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) || | ||
539 | (RspFrm.operand[3] << 8) + RspFrm.operand[4] != 8) { | ||
540 | dev_err(&fdtv->ud->device, | ||
541 | "cannot read subunit identifier\n"); | ||
542 | return -EINVAL; | ||
543 | } | ||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | int avc_tuner_status(struct firedtv *fdtv, | ||
548 | ANTENNA_INPUT_INFO *antenna_input_info) | ||
549 | { | ||
550 | AVCCmdFrm CmdFrm; | ||
551 | AVCRspFrm RspFrm; | ||
552 | int length; | ||
553 | |||
554 | memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); | ||
555 | |||
556 | CmdFrm.cts=AVC; | ||
557 | CmdFrm.ctype=CONTROL; | ||
558 | CmdFrm.sutyp=0x05; // tuner | ||
559 | CmdFrm.suid=fdtv->subunit; | ||
560 | CmdFrm.opcode=READ_DESCRIPTOR; | ||
561 | |||
562 | CmdFrm.operand[0]=DESCRIPTOR_TUNER_STATUS; | ||
563 | CmdFrm.operand[1]=0xff; //read_result_status | ||
564 | CmdFrm.operand[2]=0x00; // reserver | ||
565 | CmdFrm.operand[3]=0;//sizeof(ANTENNA_INPUT_INFO) >> 8; | ||
566 | CmdFrm.operand[4]=0;//sizeof(ANTENNA_INPUT_INFO) & 0xFF; | ||
567 | CmdFrm.operand[5]=0x00; | ||
568 | CmdFrm.operand[6]=0x00; | ||
569 | CmdFrm.length=12; | ||
570 | |||
571 | if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0) | ||
572 | return -EIO; | ||
573 | |||
574 | if (RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) { | ||
575 | dev_err(&fdtv->ud->device, "cannot read tuner status\n"); | ||
576 | return -EINVAL; | ||
577 | } | ||
578 | |||
579 | length = RspFrm.operand[9]; | ||
580 | if (RspFrm.operand[1] != 0x10 || length != sizeof(ANTENNA_INPUT_INFO)) { | ||
581 | dev_err(&fdtv->ud->device, "got invalid tuner status\n"); | ||
582 | return -EINVAL; | ||
583 | } | ||
584 | |||
585 | memcpy(antenna_input_info, &RspFrm.operand[10], length); | ||
586 | return 0; | ||
587 | } | ||
588 | |||
589 | int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst, | ||
590 | char conttone, char nrdiseq, | ||
591 | struct dvb_diseqc_master_cmd *diseqcmd) | ||
592 | { | ||
593 | AVCCmdFrm CmdFrm; | ||
594 | AVCRspFrm RspFrm; | ||
595 | int i, j, k; | ||
596 | |||
597 | memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); | ||
598 | |||
599 | CmdFrm.cts=AVC; | ||
600 | CmdFrm.ctype=CONTROL; | ||
601 | CmdFrm.sutyp=0x05; | ||
602 | CmdFrm.suid=fdtv->subunit; | ||
603 | CmdFrm.opcode=VENDOR; | ||
604 | |||
605 | CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0; | ||
606 | CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1; | ||
607 | CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2; | ||
608 | CmdFrm.operand[3]=SFE_VENDOR_OPCODE_LNB_CONTROL; | ||
609 | |||
610 | CmdFrm.operand[4]=voltage; | ||
611 | CmdFrm.operand[5]=nrdiseq; | ||
612 | |||
613 | i=6; | ||
614 | |||
615 | for (j = 0; j < nrdiseq; j++) { | ||
616 | CmdFrm.operand[i++] = diseqcmd[j].msg_len; | ||
617 | |||
618 | for (k = 0; k < diseqcmd[j].msg_len; k++) | ||
619 | CmdFrm.operand[i++] = diseqcmd[j].msg[k]; | ||
620 | } | ||
621 | |||
622 | CmdFrm.operand[i++]=burst; | ||
623 | CmdFrm.operand[i++]=conttone; | ||
624 | |||
625 | CmdFrm.length = ALIGN(3 + i, 4); | ||
626 | |||
627 | if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0) | ||
628 | return -EIO; | ||
629 | |||
630 | if (RspFrm.resp != ACCEPTED) { | ||
631 | dev_err(&fdtv->ud->device, "LNB control failed\n"); | ||
632 | return -EINVAL; | ||
633 | } | ||
634 | |||
635 | return 0; | ||
636 | } | ||
637 | |||
638 | int avc_register_remote_control(struct firedtv *fdtv) | ||
639 | { | ||
640 | AVCCmdFrm CmdFrm; | ||
641 | |||
642 | memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); | ||
643 | |||
644 | CmdFrm.cts = AVC; | ||
645 | CmdFrm.ctype = NOTIFY; | ||
646 | CmdFrm.sutyp = 0x1f; | ||
647 | CmdFrm.suid = 0x7; | ||
648 | CmdFrm.opcode = VENDOR; | ||
649 | |||
650 | CmdFrm.operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
651 | CmdFrm.operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
652 | CmdFrm.operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
653 | CmdFrm.operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL; | ||
654 | |||
655 | CmdFrm.length = 8; | ||
656 | |||
657 | return avc_write(fdtv, &CmdFrm, NULL); | ||
658 | } | ||
659 | |||
660 | void avc_remote_ctrl_work(struct work_struct *work) | ||
661 | { | ||
662 | struct firedtv *fdtv = | ||
663 | container_of(work, struct firedtv, remote_ctrl_work); | ||
664 | |||
665 | /* Should it be rescheduled in failure cases? */ | ||
666 | avc_register_remote_control(fdtv); | ||
667 | } | ||
668 | |||
669 | #if 0 /* FIXME: unused */ | ||
670 | int avc_tuner_host2ca(struct firedtv *fdtv) | ||
671 | { | ||
672 | AVCCmdFrm CmdFrm; | ||
673 | AVCRspFrm RspFrm; | ||
674 | |||
675 | memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); | ||
676 | CmdFrm.cts = AVC; | ||
677 | CmdFrm.ctype = CONTROL; | ||
678 | CmdFrm.sutyp = 0x5; | ||
679 | CmdFrm.suid = fdtv->subunit; | ||
680 | CmdFrm.opcode = VENDOR; | ||
681 | |||
682 | CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0; | ||
683 | CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1; | ||
684 | CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2; | ||
685 | CmdFrm.operand[3]=SFE_VENDOR_OPCODE_HOST2CA; | ||
686 | CmdFrm.operand[4] = 0; // slot | ||
687 | CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; // ca tag | ||
688 | CmdFrm.operand[6] = 0; // more/last | ||
689 | CmdFrm.operand[7] = 0; // length | ||
690 | CmdFrm.length = 12; | ||
691 | |||
692 | if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0) | ||
693 | return -EIO; | ||
694 | |||
695 | return 0; | ||
696 | } | ||
697 | #endif | ||
698 | |||
699 | static int get_ca_object_pos(AVCRspFrm *RspFrm) | ||
700 | { | ||
701 | int length = 1; | ||
702 | |||
703 | /* Check length of length field */ | ||
704 | if (RspFrm->operand[7] & 0x80) | ||
705 | length = (RspFrm->operand[7] & 0x7f) + 1; | ||
706 | return length + 7; | ||
707 | } | ||
708 | |||
709 | static int get_ca_object_length(AVCRspFrm *RspFrm) | ||
710 | { | ||
711 | #if 0 /* FIXME: unused */ | ||
712 | int size = 0; | ||
713 | int i; | ||
714 | |||
715 | if (RspFrm->operand[7] & 0x80) | ||
716 | for (i = 0; i < (RspFrm->operand[7] & 0x7f); i++) { | ||
717 | size <<= 8; | ||
718 | size += RspFrm->operand[8 + i]; | ||
719 | } | ||
720 | #endif | ||
721 | return RspFrm->operand[7]; | ||
722 | } | ||
723 | |||
724 | int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len) | ||
725 | { | ||
726 | AVCCmdFrm CmdFrm; | ||
727 | AVCRspFrm RspFrm; | ||
728 | int pos; | ||
729 | |||
730 | memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); | ||
731 | CmdFrm.cts = AVC; | ||
732 | CmdFrm.ctype = STATUS; | ||
733 | CmdFrm.sutyp = 0x5; | ||
734 | CmdFrm.suid = fdtv->subunit; | ||
735 | CmdFrm.opcode = VENDOR; | ||
736 | |||
737 | CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0; | ||
738 | CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1; | ||
739 | CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2; | ||
740 | CmdFrm.operand[3]=SFE_VENDOR_OPCODE_CA2HOST; | ||
741 | CmdFrm.operand[4] = 0; // slot | ||
742 | CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; // ca tag | ||
743 | CmdFrm.length = 12; | ||
744 | |||
745 | if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0) | ||
746 | return -EIO; | ||
747 | |||
748 | /* FIXME: check response code and validate response data */ | ||
749 | |||
750 | pos = get_ca_object_pos(&RspFrm); | ||
751 | app_info[0] = (TAG_APP_INFO >> 16) & 0xFF; | ||
752 | app_info[1] = (TAG_APP_INFO >> 8) & 0xFF; | ||
753 | app_info[2] = (TAG_APP_INFO >> 0) & 0xFF; | ||
754 | app_info[3] = 6 + RspFrm.operand[pos + 4]; | ||
755 | app_info[4] = 0x01; | ||
756 | memcpy(&app_info[5], &RspFrm.operand[pos], 5 + RspFrm.operand[pos + 4]); | ||
757 | *len = app_info[3] + 4; | ||
758 | |||
759 | return 0; | ||
760 | } | ||
761 | |||
762 | int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len) | ||
763 | { | ||
764 | AVCCmdFrm CmdFrm; | ||
765 | AVCRspFrm RspFrm; | ||
766 | int pos; | ||
767 | |||
768 | memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); | ||
769 | CmdFrm.cts = AVC; | ||
770 | CmdFrm.ctype = STATUS; | ||
771 | CmdFrm.sutyp = 0x5; | ||
772 | CmdFrm.suid = fdtv->subunit; | ||
773 | CmdFrm.opcode = VENDOR; | ||
774 | |||
775 | CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0; | ||
776 | CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1; | ||
777 | CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2; | ||
778 | CmdFrm.operand[3]=SFE_VENDOR_OPCODE_CA2HOST; | ||
779 | CmdFrm.operand[4] = 0; // slot | ||
780 | CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; // ca tag | ||
781 | CmdFrm.length = 12; | ||
782 | |||
783 | if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0) | ||
784 | return -EIO; | ||
785 | |||
786 | pos = get_ca_object_pos(&RspFrm); | ||
787 | app_info[0] = (TAG_CA_INFO >> 16) & 0xFF; | ||
788 | app_info[1] = (TAG_CA_INFO >> 8) & 0xFF; | ||
789 | app_info[2] = (TAG_CA_INFO >> 0) & 0xFF; | ||
790 | app_info[3] = 2; | ||
791 | app_info[4] = RspFrm.operand[pos + 0]; | ||
792 | app_info[5] = RspFrm.operand[pos + 1]; | ||
793 | *len = app_info[3] + 4; | ||
794 | |||
795 | return 0; | ||
796 | } | ||
797 | |||
798 | int avc_ca_reset(struct firedtv *fdtv) | ||
799 | { | ||
800 | AVCCmdFrm CmdFrm; | ||
801 | AVCRspFrm RspFrm; | ||
802 | |||
803 | memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); | ||
804 | CmdFrm.cts = AVC; | ||
805 | CmdFrm.ctype = CONTROL; | ||
806 | CmdFrm.sutyp = 0x5; | ||
807 | CmdFrm.suid = fdtv->subunit; | ||
808 | CmdFrm.opcode = VENDOR; | ||
809 | |||
810 | CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0; | ||
811 | CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1; | ||
812 | CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2; | ||
813 | CmdFrm.operand[3]=SFE_VENDOR_OPCODE_HOST2CA; | ||
814 | CmdFrm.operand[4] = 0; // slot | ||
815 | CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_RESET; // ca tag | ||
816 | CmdFrm.operand[6] = 0; // more/last | ||
817 | CmdFrm.operand[7] = 1; // length | ||
818 | CmdFrm.operand[8] = 0; // force hardware reset | ||
819 | CmdFrm.length = 12; | ||
820 | |||
821 | if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0) | ||
822 | return -EIO; | ||
823 | |||
824 | return 0; | ||
825 | } | ||
826 | |||
827 | int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) | ||
828 | { | ||
829 | AVCCmdFrm CmdFrm; | ||
830 | AVCRspFrm RspFrm; | ||
831 | int list_management; | ||
832 | int program_info_length; | ||
833 | int pmt_cmd_id; | ||
834 | int read_pos; | ||
835 | int write_pos; | ||
836 | int es_info_length; | ||
837 | int crc32_csum; | ||
838 | |||
839 | memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); | ||
840 | CmdFrm.cts = AVC; | ||
841 | CmdFrm.ctype = CONTROL; | ||
842 | CmdFrm.sutyp = 0x5; | ||
843 | CmdFrm.suid = fdtv->subunit; | ||
844 | CmdFrm.opcode = VENDOR; | ||
845 | |||
846 | if (msg[0] != LIST_MANAGEMENT_ONLY) { | ||
847 | dev_info(&fdtv->ud->device, | ||
848 | "forcing list_management to ONLY\n"); | ||
849 | msg[0] = LIST_MANAGEMENT_ONLY; | ||
850 | } | ||
851 | // We take the cmd_id from the programme level only! | ||
852 | list_management = msg[0]; | ||
853 | program_info_length = ((msg[4] & 0x0F) << 8) + msg[5]; | ||
854 | if (program_info_length > 0) | ||
855 | program_info_length--; // Remove pmt_cmd_id | ||
856 | pmt_cmd_id = msg[6]; | ||
857 | |||
858 | CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0; | ||
859 | CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1; | ||
860 | CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2; | ||
861 | CmdFrm.operand[3]=SFE_VENDOR_OPCODE_HOST2CA; | ||
862 | CmdFrm.operand[4] = 0; // slot | ||
863 | CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_PMT; // ca tag | ||
864 | CmdFrm.operand[6] = 0; // more/last | ||
865 | //CmdFrm.operand[7] = XXXprogram_info_length + 17; // length | ||
866 | CmdFrm.operand[8] = list_management; | ||
867 | CmdFrm.operand[9] = 0x01; // pmt_cmd=OK_descramble | ||
868 | |||
869 | // TS program map table | ||
870 | |||
871 | // Table id=2 | ||
872 | CmdFrm.operand[10] = 0x02; | ||
873 | // Section syntax + length | ||
874 | CmdFrm.operand[11] = 0x80; | ||
875 | //CmdFrm.operand[12] = XXXprogram_info_length + 12; | ||
876 | // Program number | ||
877 | CmdFrm.operand[13] = msg[1]; | ||
878 | CmdFrm.operand[14] = msg[2]; | ||
879 | // Version number=0 + current/next=1 | ||
880 | CmdFrm.operand[15] = 0x01; | ||
881 | // Section number=0 | ||
882 | CmdFrm.operand[16] = 0x00; | ||
883 | // Last section number=0 | ||
884 | CmdFrm.operand[17] = 0x00; | ||
885 | // PCR_PID=1FFF | ||
886 | CmdFrm.operand[18] = 0x1F; | ||
887 | CmdFrm.operand[19] = 0xFF; | ||
888 | // Program info length | ||
889 | CmdFrm.operand[20] = (program_info_length >> 8); | ||
890 | CmdFrm.operand[21] = (program_info_length & 0xFF); | ||
891 | // CA descriptors at programme level | ||
892 | read_pos = 6; | ||
893 | write_pos = 22; | ||
894 | if (program_info_length > 0) { | ||
895 | pmt_cmd_id = msg[read_pos++]; | ||
896 | if (pmt_cmd_id != 1 && pmt_cmd_id != 4) | ||
897 | dev_err(&fdtv->ud->device, | ||
898 | "invalid pmt_cmd_id %d\n", pmt_cmd_id); | ||
899 | |||
900 | memcpy(&CmdFrm.operand[write_pos], &msg[read_pos], | ||
901 | program_info_length); | ||
902 | read_pos += program_info_length; | ||
903 | write_pos += program_info_length; | ||
904 | } | ||
905 | while (read_pos < length) { | ||
906 | CmdFrm.operand[write_pos++] = msg[read_pos++]; | ||
907 | CmdFrm.operand[write_pos++] = msg[read_pos++]; | ||
908 | CmdFrm.operand[write_pos++] = msg[read_pos++]; | ||
909 | es_info_length = | ||
910 | ((msg[read_pos] & 0x0F) << 8) + msg[read_pos + 1]; | ||
911 | read_pos += 2; | ||
912 | if (es_info_length > 0) | ||
913 | es_info_length--; // Remove pmt_cmd_id | ||
914 | CmdFrm.operand[write_pos++] = es_info_length >> 8; | ||
915 | CmdFrm.operand[write_pos++] = es_info_length & 0xFF; | ||
916 | if (es_info_length > 0) { | ||
917 | pmt_cmd_id = msg[read_pos++]; | ||
918 | if (pmt_cmd_id != 1 && pmt_cmd_id != 4) | ||
919 | dev_err(&fdtv->ud->device, | ||
920 | "invalid pmt_cmd_id %d " | ||
921 | "at stream level\n", pmt_cmd_id); | ||
922 | |||
923 | memcpy(&CmdFrm.operand[write_pos], &msg[read_pos], | ||
924 | es_info_length); | ||
925 | read_pos += es_info_length; | ||
926 | write_pos += es_info_length; | ||
927 | } | ||
928 | } | ||
929 | |||
930 | // CRC | ||
931 | CmdFrm.operand[write_pos++] = 0x00; | ||
932 | CmdFrm.operand[write_pos++] = 0x00; | ||
933 | CmdFrm.operand[write_pos++] = 0x00; | ||
934 | CmdFrm.operand[write_pos++] = 0x00; | ||
935 | |||
936 | CmdFrm.operand[7] = write_pos - 8; | ||
937 | CmdFrm.operand[12] = write_pos - 13; | ||
938 | |||
939 | crc32_csum = crc32_be(0, &CmdFrm.operand[10], | ||
940 | CmdFrm.operand[12] - 1); | ||
941 | CmdFrm.operand[write_pos - 4] = (crc32_csum >> 24) & 0xFF; | ||
942 | CmdFrm.operand[write_pos - 3] = (crc32_csum >> 16) & 0xFF; | ||
943 | CmdFrm.operand[write_pos - 2] = (crc32_csum >> 8) & 0xFF; | ||
944 | CmdFrm.operand[write_pos - 1] = (crc32_csum >> 0) & 0xFF; | ||
945 | |||
946 | CmdFrm.length = ALIGN(3 + write_pos, 4); | ||
947 | |||
948 | if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0) | ||
949 | return -EIO; | ||
950 | |||
951 | if (RspFrm.resp != ACCEPTED) { | ||
952 | dev_err(&fdtv->ud->device, | ||
953 | "CA PMT failed with response 0x%x\n", RspFrm.resp); | ||
954 | return -EFAULT; | ||
955 | } | ||
956 | |||
957 | return 0; | ||
958 | } | ||
959 | |||
960 | int avc_ca_get_time_date(struct firedtv *fdtv, int *interval) | ||
961 | { | ||
962 | AVCCmdFrm CmdFrm; | ||
963 | AVCRspFrm RspFrm; | ||
964 | |||
965 | memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); | ||
966 | CmdFrm.cts = AVC; | ||
967 | CmdFrm.ctype = STATUS; | ||
968 | CmdFrm.sutyp = 0x5; | ||
969 | CmdFrm.suid = fdtv->subunit; | ||
970 | CmdFrm.opcode = VENDOR; | ||
971 | |||
972 | CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0; | ||
973 | CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1; | ||
974 | CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2; | ||
975 | CmdFrm.operand[3]=SFE_VENDOR_OPCODE_CA2HOST; | ||
976 | CmdFrm.operand[4] = 0; // slot | ||
977 | CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; // ca tag | ||
978 | CmdFrm.operand[6] = 0; // more/last | ||
979 | CmdFrm.operand[7] = 0; // length | ||
980 | CmdFrm.length = 12; | ||
981 | |||
982 | if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0) | ||
983 | return -EIO; | ||
984 | |||
985 | /* FIXME: check response code and validate response data */ | ||
986 | |||
987 | *interval = RspFrm.operand[get_ca_object_pos(&RspFrm)]; | ||
988 | |||
989 | return 0; | ||
990 | } | ||
991 | |||
992 | int avc_ca_enter_menu(struct firedtv *fdtv) | ||
993 | { | ||
994 | AVCCmdFrm CmdFrm; | ||
995 | AVCRspFrm RspFrm; | ||
996 | |||
997 | memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); | ||
998 | CmdFrm.cts = AVC; | ||
999 | CmdFrm.ctype = STATUS; | ||
1000 | CmdFrm.sutyp = 0x5; | ||
1001 | CmdFrm.suid = fdtv->subunit; | ||
1002 | CmdFrm.opcode = VENDOR; | ||
1003 | |||
1004 | CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0; | ||
1005 | CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1; | ||
1006 | CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2; | ||
1007 | CmdFrm.operand[3]=SFE_VENDOR_OPCODE_HOST2CA; | ||
1008 | CmdFrm.operand[4] = 0; // slot | ||
1009 | CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU; | ||
1010 | CmdFrm.operand[6] = 0; // more/last | ||
1011 | CmdFrm.operand[7] = 0; // length | ||
1012 | CmdFrm.length = 12; | ||
1013 | |||
1014 | if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0) | ||
1015 | return -EIO; | ||
1016 | |||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
1020 | int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len) | ||
1021 | { | ||
1022 | AVCCmdFrm CmdFrm; | ||
1023 | AVCRspFrm RspFrm; | ||
1024 | |||
1025 | memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); | ||
1026 | CmdFrm.cts = AVC; | ||
1027 | CmdFrm.ctype = STATUS; | ||
1028 | CmdFrm.sutyp = 0x5; | ||
1029 | CmdFrm.suid = fdtv->subunit; | ||
1030 | CmdFrm.opcode = VENDOR; | ||
1031 | |||
1032 | CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0; | ||
1033 | CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1; | ||
1034 | CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2; | ||
1035 | CmdFrm.operand[3]=SFE_VENDOR_OPCODE_CA2HOST; | ||
1036 | CmdFrm.operand[4] = 0; // slot | ||
1037 | CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_MMI; | ||
1038 | CmdFrm.operand[6] = 0; // more/last | ||
1039 | CmdFrm.operand[7] = 0; // length | ||
1040 | CmdFrm.length = 12; | ||
1041 | |||
1042 | if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0) | ||
1043 | return -EIO; | ||
1044 | |||
1045 | /* FIXME: check response code and validate response data */ | ||
1046 | |||
1047 | *len = get_ca_object_length(&RspFrm); | ||
1048 | memcpy(mmi_object, &RspFrm.operand[get_ca_object_pos(&RspFrm)], *len); | ||
1049 | |||
1050 | return 0; | ||
1051 | } | ||
diff --git a/drivers/media/dvb/firewire/avc.h b/drivers/media/dvb/firewire/avc.h new file mode 100644 index 000000000000..168f371dbde0 --- /dev/null +++ b/drivers/media/dvb/firewire/avc.h | |||
@@ -0,0 +1,432 @@ | |||
1 | /* | ||
2 | * AV/C API | ||
3 | * | ||
4 | * Copyright (C) 2000 Manfred Weihs | ||
5 | * Copyright (C) 2003 Philipp Gutgsell <0014guph@edu.fh-kaernten.ac.at> | ||
6 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
7 | * Copyright (C) 2008 Ben Backx <ben@bbackx.com> | ||
8 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | ||
9 | * | ||
10 | * This is based on code written by Peter Halwachs, Thomas Groiss and | ||
11 | * Andreas Monitzer. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License as | ||
15 | * published by the Free Software Foundation; either version 2 of | ||
16 | * the License, or (at your option) any later version. | ||
17 | */ | ||
18 | |||
19 | #ifndef _AVC_API_H | ||
20 | #define _AVC_API_H | ||
21 | |||
22 | #include <linux/types.h> | ||
23 | |||
24 | /************************************************************* | ||
25 | Constants from EN510221 | ||
26 | **************************************************************/ | ||
27 | #define LIST_MANAGEMENT_ONLY 0x03 | ||
28 | |||
29 | /************************************************************ | ||
30 | definition of structures | ||
31 | *************************************************************/ | ||
32 | typedef struct { | ||
33 | int Nr_SourcePlugs; | ||
34 | int Nr_DestinationPlugs; | ||
35 | } TunerInfo; | ||
36 | |||
37 | |||
38 | /*********************************************** | ||
39 | |||
40 | supported cts | ||
41 | |||
42 | ************************************************/ | ||
43 | |||
44 | #define AVC 0x0 | ||
45 | |||
46 | // FCP command frame with ctype = 0x0 is AVC command frame | ||
47 | |||
48 | #ifdef __LITTLE_ENDIAN | ||
49 | |||
50 | // Definition FCP Command Frame | ||
51 | typedef struct _AVCCmdFrm | ||
52 | { | ||
53 | // AV/C command frame | ||
54 | __u8 ctype : 4 ; // command type | ||
55 | __u8 cts : 4 ; // always 0x0 for AVC | ||
56 | __u8 suid : 3 ; // subunit ID | ||
57 | __u8 sutyp : 5 ; // subunit_typ | ||
58 | __u8 opcode : 8 ; // opcode | ||
59 | __u8 operand[509] ; // array of operands [1-507] | ||
60 | int length; //length of the command frame | ||
61 | } AVCCmdFrm ; | ||
62 | |||
63 | // Definition FCP Response Frame | ||
64 | typedef struct _AVCRspFrm | ||
65 | { | ||
66 | // AV/C response frame | ||
67 | __u8 resp : 4 ; // response type | ||
68 | __u8 cts : 4 ; // always 0x0 for AVC | ||
69 | __u8 suid : 3 ; // subunit ID | ||
70 | __u8 sutyp : 5 ; // subunit_typ | ||
71 | __u8 opcode : 8 ; // opcode | ||
72 | __u8 operand[509] ; // array of operands [1-507] | ||
73 | int length; //length of the response frame | ||
74 | } AVCRspFrm ; | ||
75 | |||
76 | #else | ||
77 | |||
78 | typedef struct _AVCCmdFrm | ||
79 | { | ||
80 | __u8 cts:4; | ||
81 | __u8 ctype:4; | ||
82 | __u8 sutyp:5; | ||
83 | __u8 suid:3; | ||
84 | __u8 opcode; | ||
85 | __u8 operand[509]; | ||
86 | int length; | ||
87 | } AVCCmdFrm; | ||
88 | |||
89 | typedef struct _AVCRspFrm | ||
90 | { | ||
91 | __u8 cts:4; | ||
92 | __u8 resp:4; | ||
93 | __u8 sutyp:5; | ||
94 | __u8 suid:3; | ||
95 | __u8 opcode; | ||
96 | __u8 operand[509]; | ||
97 | int length; | ||
98 | } AVCRspFrm; | ||
99 | |||
100 | #endif | ||
101 | |||
102 | /************************************************************* | ||
103 | AVC command types (ctype) | ||
104 | **************************************************************/// | ||
105 | #define CONTROL 0x00 | ||
106 | #define STATUS 0x01 | ||
107 | #define INQUIRY 0x02 | ||
108 | #define NOTIFY 0x03 | ||
109 | |||
110 | /************************************************************* | ||
111 | AVC respond types | ||
112 | **************************************************************/// | ||
113 | #define NOT_IMPLEMENTED 0x8 | ||
114 | #define ACCEPTED 0x9 | ||
115 | #define REJECTED 0xA | ||
116 | #define STABLE 0xC | ||
117 | #define CHANGED 0xD | ||
118 | #define INTERIM 0xF | ||
119 | |||
120 | /************************************************************* | ||
121 | AVC opcodes | ||
122 | **************************************************************/// | ||
123 | #define CONNECT 0x24 | ||
124 | #define DISCONNECT 0x25 | ||
125 | #define UNIT_INFO 0x30 | ||
126 | #define SUBUNIT_Info 0x31 | ||
127 | #define VENDOR 0x00 | ||
128 | |||
129 | #define PLUG_INFO 0x02 | ||
130 | #define OPEN_DESCRIPTOR 0x08 | ||
131 | #define READ_DESCRIPTOR 0x09 | ||
132 | #define OBJECT_NUMBER_SELECT 0x0D | ||
133 | |||
134 | /************************************************************* | ||
135 | AVCTuner opcodes | ||
136 | **************************************************************/ | ||
137 | |||
138 | #define DSIT 0xC8 | ||
139 | #define DSD 0xCB | ||
140 | #define DESCRIPTOR_TUNER_STATUS 0x80 | ||
141 | #define DESCRIPTOR_SUBUNIT_IDENTIFIER 0x00 | ||
142 | |||
143 | /************************************************************* | ||
144 | AVCTuner list types | ||
145 | **************************************************************/ | ||
146 | #define Multiplex_List 0x80 | ||
147 | #define Service_List 0x82 | ||
148 | |||
149 | /************************************************************* | ||
150 | AVCTuner object entries | ||
151 | **************************************************************/ | ||
152 | #define Multiplex 0x80 | ||
153 | #define Service 0x82 | ||
154 | #define Service_with_specified_components 0x83 | ||
155 | #define Preferred_components 0x90 | ||
156 | #define Component 0x84 | ||
157 | |||
158 | /************************************************************* | ||
159 | Vendor-specific commands | ||
160 | **************************************************************/ | ||
161 | |||
162 | // digital everywhere vendor ID | ||
163 | #define SFE_VENDOR_DE_COMPANYID_0 0x00 | ||
164 | #define SFE_VENDOR_DE_COMPANYID_1 0x12 | ||
165 | #define SFE_VENDOR_DE_COMPANYID_2 0x87 | ||
166 | |||
167 | #define SFE_VENDOR_MAX_NR_COMPONENTS 0x4 | ||
168 | #define SFE_VENDOR_MAX_NR_SERVICES 0x3 | ||
169 | #define SFE_VENDOR_MAX_NR_DSD_ELEMENTS 0x10 | ||
170 | |||
171 | // vendor commands | ||
172 | #define SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL 0x0A | ||
173 | #define SFE_VENDOR_OPCODE_LNB_CONTROL 0x52 | ||
174 | #define SFE_VENDOR_OPCODE_TUNE_QPSK 0x58 // QPSK command for DVB-S | ||
175 | |||
176 | // TODO: following vendor specific commands needs to be implemented | ||
177 | #define SFE_VENDOR_OPCODE_GET_FIRMWARE_VERSION 0x00 | ||
178 | #define SFE_VENDOR_OPCODE_HOST2CA 0x56 | ||
179 | #define SFE_VENDOR_OPCODE_CA2HOST 0x57 | ||
180 | #define SFE_VENDOR_OPCODE_CISTATUS 0x59 | ||
181 | #define SFE_VENDOR_OPCODE_TUNE_QPSK2 0x60 // QPSK command for DVB-S2 devices | ||
182 | |||
183 | // CA Tags | ||
184 | #define SFE_VENDOR_TAG_CA_RESET 0x00 | ||
185 | #define SFE_VENDOR_TAG_CA_APPLICATION_INFO 0x01 | ||
186 | #define SFE_VENDOR_TAG_CA_PMT 0x02 | ||
187 | #define SFE_VENDOR_TAG_CA_DATE_TIME 0x04 | ||
188 | #define SFE_VENDOR_TAG_CA_MMI 0x05 | ||
189 | #define SFE_VENDOR_TAG_CA_ENTER_MENU 0x07 | ||
190 | |||
191 | |||
192 | //AVCTuner DVB identifier service_ID | ||
193 | #define DVB 0x20 | ||
194 | |||
195 | /************************************************************* | ||
196 | AVC descriptor types | ||
197 | **************************************************************/ | ||
198 | |||
199 | #define Subunit_Identifier_Descriptor 0x00 | ||
200 | #define Tuner_Status_Descriptor 0x80 | ||
201 | |||
202 | typedef struct { | ||
203 | __u8 Subunit_Type; | ||
204 | __u8 Max_Subunit_ID; | ||
205 | } SUBUNIT_INFO; | ||
206 | |||
207 | /************************************************************* | ||
208 | |||
209 | AVCTuner DVB object IDs are 6 byte long | ||
210 | |||
211 | **************************************************************/ | ||
212 | |||
213 | typedef struct { | ||
214 | __u8 Byte0; | ||
215 | __u8 Byte1; | ||
216 | __u8 Byte2; | ||
217 | __u8 Byte3; | ||
218 | __u8 Byte4; | ||
219 | __u8 Byte5; | ||
220 | }OBJECT_ID; | ||
221 | |||
222 | /************************************************************* | ||
223 | MULIPLEX Structs | ||
224 | **************************************************************/ | ||
225 | typedef struct | ||
226 | { | ||
227 | #ifdef __LITTLE_ENDIAN | ||
228 | __u8 RF_frequency_hByte:6; | ||
229 | __u8 raster_Frequency:2;//Bit7,6 raster frequency | ||
230 | #else | ||
231 | __u8 raster_Frequency:2; | ||
232 | __u8 RF_frequency_hByte:6; | ||
233 | #endif | ||
234 | __u8 RF_frequency_mByte; | ||
235 | __u8 RF_frequency_lByte; | ||
236 | |||
237 | }FREQUENCY; | ||
238 | |||
239 | #ifdef __LITTLE_ENDIAN | ||
240 | |||
241 | typedef struct | ||
242 | { | ||
243 | __u8 Modulation :1; | ||
244 | __u8 FEC_inner :1; | ||
245 | __u8 FEC_outer :1; | ||
246 | __u8 Symbol_Rate :1; | ||
247 | __u8 Frequency :1; | ||
248 | __u8 Orbital_Pos :1; | ||
249 | __u8 Polarisation :1; | ||
250 | __u8 reserved_fields :1; | ||
251 | __u8 reserved1 :7; | ||
252 | __u8 Network_ID :1; | ||
253 | |||
254 | }MULTIPLEX_VALID_FLAGS; | ||
255 | |||
256 | typedef struct | ||
257 | { | ||
258 | __u8 GuardInterval:1; | ||
259 | __u8 CodeRateLPStream:1; | ||
260 | __u8 CodeRateHPStream:1; | ||
261 | __u8 HierarchyInfo:1; | ||
262 | __u8 Constellation:1; | ||
263 | __u8 Bandwidth:1; | ||
264 | __u8 CenterFrequency:1; | ||
265 | __u8 reserved1:1; | ||
266 | __u8 reserved2:5; | ||
267 | __u8 OtherFrequencyFlag:1; | ||
268 | __u8 TransmissionMode:1; | ||
269 | __u8 NetworkId:1; | ||
270 | }MULTIPLEX_VALID_FLAGS_DVBT; | ||
271 | |||
272 | #else | ||
273 | |||
274 | typedef struct { | ||
275 | __u8 reserved_fields:1; | ||
276 | __u8 Polarisation:1; | ||
277 | __u8 Orbital_Pos:1; | ||
278 | __u8 Frequency:1; | ||
279 | __u8 Symbol_Rate:1; | ||
280 | __u8 FEC_outer:1; | ||
281 | __u8 FEC_inner:1; | ||
282 | __u8 Modulation:1; | ||
283 | __u8 Network_ID:1; | ||
284 | __u8 reserved1:7; | ||
285 | }MULTIPLEX_VALID_FLAGS; | ||
286 | |||
287 | typedef struct { | ||
288 | __u8 reserved1:1; | ||
289 | __u8 CenterFrequency:1; | ||
290 | __u8 Bandwidth:1; | ||
291 | __u8 Constellation:1; | ||
292 | __u8 HierarchyInfo:1; | ||
293 | __u8 CodeRateHPStream:1; | ||
294 | __u8 CodeRateLPStream:1; | ||
295 | __u8 GuardInterval:1; | ||
296 | __u8 NetworkId:1; | ||
297 | __u8 TransmissionMode:1; | ||
298 | __u8 OtherFrequencyFlag:1; | ||
299 | __u8 reserved2:5; | ||
300 | }MULTIPLEX_VALID_FLAGS_DVBT; | ||
301 | |||
302 | #endif | ||
303 | |||
304 | typedef union { | ||
305 | MULTIPLEX_VALID_FLAGS Bits; | ||
306 | MULTIPLEX_VALID_FLAGS_DVBT Bits_T; | ||
307 | struct { | ||
308 | __u8 ByteHi; | ||
309 | __u8 ByteLo; | ||
310 | } Valid_Word; | ||
311 | } M_VALID_FLAGS; | ||
312 | |||
313 | typedef struct | ||
314 | { | ||
315 | #ifdef __LITTLE_ENDIAN | ||
316 | __u8 ActiveSystem; | ||
317 | __u8 reserved:5; | ||
318 | __u8 NoRF:1; | ||
319 | __u8 Moving:1; | ||
320 | __u8 Searching:1; | ||
321 | |||
322 | __u8 SelectedAntenna:7; | ||
323 | __u8 Input:1; | ||
324 | |||
325 | __u8 BER[4]; | ||
326 | |||
327 | __u8 SignalStrength; | ||
328 | FREQUENCY Frequency; | ||
329 | |||
330 | __u8 ManDepInfoLength; | ||
331 | |||
332 | __u8 PowerSupply:1; | ||
333 | __u8 FrontEndPowerStatus:1; | ||
334 | __u8 reserved3:1; | ||
335 | __u8 AntennaError:1; | ||
336 | __u8 FrontEndError:1; | ||
337 | __u8 reserved2:3; | ||
338 | |||
339 | __u8 CarrierNoiseRatio[2]; | ||
340 | __u8 reserved4[2]; | ||
341 | __u8 PowerSupplyVoltage; | ||
342 | __u8 AntennaVoltage; | ||
343 | __u8 FirewireBusVoltage; | ||
344 | |||
345 | __u8 CaMmi:1; | ||
346 | __u8 reserved5:7; | ||
347 | |||
348 | __u8 reserved6:1; | ||
349 | __u8 CaInitializationStatus:1; | ||
350 | __u8 CaErrorFlag:1; | ||
351 | __u8 CaDvbFlag:1; | ||
352 | __u8 CaModulePresentStatus:1; | ||
353 | __u8 CaApplicationInfo:1; | ||
354 | __u8 CaDateTimeRequest:1; | ||
355 | __u8 CaPmtReply:1; | ||
356 | |||
357 | #else | ||
358 | __u8 ActiveSystem; | ||
359 | __u8 Searching:1; | ||
360 | __u8 Moving:1; | ||
361 | __u8 NoRF:1; | ||
362 | __u8 reserved:5; | ||
363 | |||
364 | __u8 Input:1; | ||
365 | __u8 SelectedAntenna:7; | ||
366 | |||
367 | __u8 BER[4]; | ||
368 | |||
369 | __u8 SignalStrength; | ||
370 | FREQUENCY Frequency; | ||
371 | |||
372 | __u8 ManDepInfoLength; | ||
373 | |||
374 | __u8 reserved2:3; | ||
375 | __u8 FrontEndError:1; | ||
376 | __u8 AntennaError:1; | ||
377 | __u8 reserved3:1; | ||
378 | __u8 FrontEndPowerStatus:1; | ||
379 | __u8 PowerSupply:1; | ||
380 | |||
381 | __u8 CarrierNoiseRatio[2]; | ||
382 | __u8 reserved4[2]; | ||
383 | __u8 PowerSupplyVoltage; | ||
384 | __u8 AntennaVoltage; | ||
385 | __u8 FirewireBusVoltage; | ||
386 | |||
387 | __u8 reserved5:7; | ||
388 | __u8 CaMmi:1; | ||
389 | __u8 CaPmtReply:1; | ||
390 | __u8 CaDateTimeRequest:1; | ||
391 | __u8 CaApplicationInfo:1; | ||
392 | __u8 CaModulePresentStatus:1; | ||
393 | __u8 CaDvbFlag:1; | ||
394 | __u8 CaErrorFlag:1; | ||
395 | __u8 CaInitializationStatus:1; | ||
396 | __u8 reserved6:1; | ||
397 | |||
398 | #endif | ||
399 | } ANTENNA_INPUT_INFO; // 22 Byte | ||
400 | |||
401 | #define LNBCONTROL_DONTCARE 0xff | ||
402 | |||
403 | struct dvb_diseqc_master_cmd; | ||
404 | struct dvb_frontend_parameters; | ||
405 | struct firedtv; | ||
406 | |||
407 | int avc_recv(struct firedtv *fdtv, u8 *data, size_t length); | ||
408 | |||
409 | int AVCTuner_DSIT(struct firedtv *fdtv, int Source_Plug, | ||
410 | struct dvb_frontend_parameters *params, __u8 *status); | ||
411 | |||
412 | int avc_tuner_status(struct firedtv *fdtv, | ||
413 | ANTENNA_INPUT_INFO *antenna_input_info); | ||
414 | int avc_tuner_dsd(struct firedtv *fdtv, | ||
415 | struct dvb_frontend_parameters *params); | ||
416 | int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]); | ||
417 | int avc_tuner_get_ts(struct firedtv *fdtv); | ||
418 | int avc_identify_subunit(struct firedtv *fdtv); | ||
419 | int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst, | ||
420 | char conttone, char nrdiseq, | ||
421 | struct dvb_diseqc_master_cmd *diseqcmd); | ||
422 | void avc_remote_ctrl_work(struct work_struct *work); | ||
423 | int avc_register_remote_control(struct firedtv *fdtv); | ||
424 | int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len); | ||
425 | int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len); | ||
426 | int avc_ca_reset(struct firedtv *fdtv); | ||
427 | int avc_ca_pmt(struct firedtv *fdtv, char *app_info, int length); | ||
428 | int avc_ca_get_time_date(struct firedtv *fdtv, int *interval); | ||
429 | int avc_ca_enter_menu(struct firedtv *fdtv); | ||
430 | int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len); | ||
431 | |||
432 | #endif /* _AVC_API_H */ | ||
diff --git a/drivers/media/dvb/firewire/cmp.c b/drivers/media/dvb/firewire/cmp.c new file mode 100644 index 000000000000..821e033d8195 --- /dev/null +++ b/drivers/media/dvb/firewire/cmp.c | |||
@@ -0,0 +1,171 @@ | |||
1 | /* | ||
2 | * FireDTV driver (formerly known as FireSAT) | ||
3 | * | ||
4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
5 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | ||
6 | * | ||
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. | ||
11 | */ | ||
12 | |||
13 | #include <linux/device.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/mutex.h> | ||
16 | #include <linux/types.h> | ||
17 | |||
18 | #include <asm/byteorder.h> | ||
19 | |||
20 | #include <ieee1394.h> | ||
21 | #include <nodemgr.h> | ||
22 | |||
23 | #include "avc.h" | ||
24 | #include "cmp.h" | ||
25 | #include "firedtv.h" | ||
26 | |||
27 | #define CMP_OUTPUT_PLUG_CONTROL_REG_0 0xfffff0000904ULL | ||
28 | |||
29 | static int cmp_read(struct firedtv *fdtv, void *buf, u64 addr, size_t len) | ||
30 | { | ||
31 | int ret; | ||
32 | |||
33 | if (mutex_lock_interruptible(&fdtv->avc_mutex)) | ||
34 | return -EINTR; | ||
35 | |||
36 | ret = hpsb_node_read(fdtv->ud->ne, addr, buf, len); | ||
37 | if (ret < 0) | ||
38 | dev_err(&fdtv->ud->device, "CMP: read I/O error\n"); | ||
39 | |||
40 | mutex_unlock(&fdtv->avc_mutex); | ||
41 | return ret; | ||
42 | } | ||
43 | |||
44 | static int cmp_lock(struct firedtv *fdtv, void *data, u64 addr, __be32 arg, | ||
45 | int ext_tcode) | ||
46 | { | ||
47 | int ret; | ||
48 | |||
49 | if (mutex_lock_interruptible(&fdtv->avc_mutex)) | ||
50 | return -EINTR; | ||
51 | |||
52 | ret = hpsb_node_lock(fdtv->ud->ne, addr, ext_tcode, data, | ||
53 | (__force quadlet_t)arg); | ||
54 | if (ret < 0) | ||
55 | dev_err(&fdtv->ud->device, "CMP: lock I/O error\n"); | ||
56 | |||
57 | mutex_unlock(&fdtv->avc_mutex); | ||
58 | return ret; | ||
59 | } | ||
60 | |||
61 | static inline u32 get_opcr(__be32 opcr, u32 mask, u32 shift) | ||
62 | { | ||
63 | return (be32_to_cpu(opcr) >> shift) & mask; | ||
64 | } | ||
65 | |||
66 | static inline void set_opcr(__be32 *opcr, u32 value, u32 mask, u32 shift) | ||
67 | { | ||
68 | *opcr &= ~cpu_to_be32(mask << shift); | ||
69 | *opcr |= cpu_to_be32((value & mask) << shift); | ||
70 | } | ||
71 | |||
72 | #define get_opcr_online(v) get_opcr((v), 0x1, 31) | ||
73 | #define get_opcr_p2p_connections(v) get_opcr((v), 0x3f, 24) | ||
74 | #define get_opcr_channel(v) get_opcr((v), 0x3f, 16) | ||
75 | |||
76 | #define set_opcr_p2p_connections(p, v) set_opcr((p), (v), 0x3f, 24) | ||
77 | #define set_opcr_channel(p, v) set_opcr((p), (v), 0x3f, 16) | ||
78 | #define set_opcr_data_rate(p, v) set_opcr((p), (v), 0x3, 14) | ||
79 | #define set_opcr_overhead_id(p, v) set_opcr((p), (v), 0xf, 10) | ||
80 | |||
81 | int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel) | ||
82 | { | ||
83 | __be32 old_opcr, opcr; | ||
84 | u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2); | ||
85 | int attempts = 0; | ||
86 | int ret; | ||
87 | |||
88 | ret = cmp_read(fdtv, &opcr, opcr_address, 4); | ||
89 | if (ret < 0) | ||
90 | return ret; | ||
91 | |||
92 | repeat: | ||
93 | if (!get_opcr_online(opcr)) { | ||
94 | dev_err(&fdtv->ud->device, "CMP: output offline\n"); | ||
95 | return -EBUSY; | ||
96 | } | ||
97 | |||
98 | old_opcr = opcr; | ||
99 | |||
100 | if (get_opcr_p2p_connections(opcr)) { | ||
101 | if (get_opcr_channel(opcr) != channel) { | ||
102 | dev_err(&fdtv->ud->device, | ||
103 | "CMP: cannot change channel\n"); | ||
104 | return -EBUSY; | ||
105 | } | ||
106 | dev_info(&fdtv->ud->device, | ||
107 | "CMP: overlaying existing connection\n"); | ||
108 | |||
109 | /* We don't allocate isochronous resources. */ | ||
110 | } else { | ||
111 | set_opcr_channel(&opcr, channel); | ||
112 | set_opcr_data_rate(&opcr, IEEE1394_SPEED_400); | ||
113 | |||
114 | /* FIXME: this is for the worst case - optimize */ | ||
115 | set_opcr_overhead_id(&opcr, 0); | ||
116 | |||
117 | /* FIXME: allocate isochronous channel and bandwidth at IRM */ | ||
118 | } | ||
119 | |||
120 | set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) + 1); | ||
121 | |||
122 | ret = cmp_lock(fdtv, &opcr, opcr_address, old_opcr, 2); | ||
123 | if (ret < 0) | ||
124 | return ret; | ||
125 | |||
126 | if (old_opcr != opcr) { | ||
127 | /* | ||
128 | * FIXME: if old_opcr.P2P_Connections > 0, | ||
129 | * deallocate isochronous channel and bandwidth at IRM | ||
130 | */ | ||
131 | |||
132 | if (++attempts < 6) /* arbitrary limit */ | ||
133 | goto repeat; | ||
134 | return -EBUSY; | ||
135 | } | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel) | ||
141 | { | ||
142 | __be32 old_opcr, opcr; | ||
143 | u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2); | ||
144 | int attempts = 0; | ||
145 | |||
146 | if (cmp_read(fdtv, &opcr, opcr_address, 4) < 0) | ||
147 | return; | ||
148 | |||
149 | repeat: | ||
150 | if (!get_opcr_online(opcr) || !get_opcr_p2p_connections(opcr) || | ||
151 | get_opcr_channel(opcr) != channel) { | ||
152 | dev_err(&fdtv->ud->device, "CMP: no connection to break\n"); | ||
153 | return; | ||
154 | } | ||
155 | |||
156 | old_opcr = opcr; | ||
157 | set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) - 1); | ||
158 | |||
159 | if (cmp_lock(fdtv, &opcr, opcr_address, old_opcr, 2) < 0) | ||
160 | return; | ||
161 | |||
162 | if (old_opcr != opcr) { | ||
163 | /* | ||
164 | * FIXME: if old_opcr.P2P_Connections == 1, i.e. we were last | ||
165 | * owner, deallocate isochronous channel and bandwidth at IRM | ||
166 | */ | ||
167 | |||
168 | if (++attempts < 6) /* arbitrary limit */ | ||
169 | goto repeat; | ||
170 | } | ||
171 | } | ||
diff --git a/drivers/media/dvb/firewire/cmp.h b/drivers/media/dvb/firewire/cmp.h new file mode 100644 index 000000000000..17e182cf29a9 --- /dev/null +++ b/drivers/media/dvb/firewire/cmp.h | |||
@@ -0,0 +1,9 @@ | |||
1 | #ifndef _CMP_H | ||
2 | #define _CMP_H | ||
3 | |||
4 | struct firedtv; | ||
5 | |||
6 | int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel); | ||
7 | void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel); | ||
8 | |||
9 | #endif /* _CMP_H */ | ||
diff --git a/drivers/media/dvb/firewire/firedtv-1394.c b/drivers/media/dvb/firewire/firedtv-1394.c new file mode 100644 index 000000000000..953618246e8e --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-1394.c | |||
@@ -0,0 +1,291 @@ | |||
1 | /* | ||
2 | * FireDTV driver (formerly known as FireSAT) | ||
3 | * | ||
4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
5 | * Copyright (C) 2007-2008 Ben Backx <ben@bbackx.com> | ||
6 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License as | ||
10 | * published by the Free Software Foundation; either version 2 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/device.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/list.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/mutex.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/spinlock.h> | ||
22 | #include <linux/string.h> | ||
23 | #include <linux/types.h> | ||
24 | |||
25 | #include <dmxdev.h> | ||
26 | #include <dvb_demux.h> | ||
27 | #include <dvb_frontend.h> | ||
28 | #include <dvbdev.h> | ||
29 | |||
30 | #include <csr1212.h> | ||
31 | #include <highlevel.h> | ||
32 | #include <hosts.h> | ||
33 | #include <ieee1394_hotplug.h> | ||
34 | #include <nodemgr.h> | ||
35 | |||
36 | #include "avc.h" | ||
37 | #include "cmp.h" | ||
38 | #include "firedtv.h" | ||
39 | #include "firedtv-ci.h" | ||
40 | #include "firedtv-rc.h" | ||
41 | |||
42 | #define MATCH_FLAGS IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \ | ||
43 | IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION | ||
44 | #define DIGITAL_EVERYWHERE_OUI 0x001287 | ||
45 | |||
46 | static struct ieee1394_device_id fdtv_id_table[] = { | ||
47 | |||
48 | { | ||
49 | /* FloppyDTV S/CI and FloppyDTV S2 */ | ||
50 | .match_flags = MATCH_FLAGS, | ||
51 | .vendor_id = DIGITAL_EVERYWHERE_OUI, | ||
52 | .model_id = 0x000024, | ||
53 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, | ||
54 | .version = AVC_SW_VERSION_ENTRY, | ||
55 | },{ | ||
56 | /* FloppyDTV T/CI */ | ||
57 | .match_flags = MATCH_FLAGS, | ||
58 | .vendor_id = DIGITAL_EVERYWHERE_OUI, | ||
59 | .model_id = 0x000025, | ||
60 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, | ||
61 | .version = AVC_SW_VERSION_ENTRY, | ||
62 | },{ | ||
63 | /* FloppyDTV C/CI */ | ||
64 | .match_flags = MATCH_FLAGS, | ||
65 | .vendor_id = DIGITAL_EVERYWHERE_OUI, | ||
66 | .model_id = 0x000026, | ||
67 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, | ||
68 | .version = AVC_SW_VERSION_ENTRY, | ||
69 | },{ | ||
70 | /* FireDTV S/CI and FloppyDTV S2 */ | ||
71 | .match_flags = MATCH_FLAGS, | ||
72 | .vendor_id = DIGITAL_EVERYWHERE_OUI, | ||
73 | .model_id = 0x000034, | ||
74 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, | ||
75 | .version = AVC_SW_VERSION_ENTRY, | ||
76 | },{ | ||
77 | /* FireDTV T/CI */ | ||
78 | .match_flags = MATCH_FLAGS, | ||
79 | .vendor_id = DIGITAL_EVERYWHERE_OUI, | ||
80 | .model_id = 0x000035, | ||
81 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, | ||
82 | .version = AVC_SW_VERSION_ENTRY, | ||
83 | },{ | ||
84 | /* FireDTV C/CI */ | ||
85 | .match_flags = MATCH_FLAGS, | ||
86 | .vendor_id = DIGITAL_EVERYWHERE_OUI, | ||
87 | .model_id = 0x000036, | ||
88 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, | ||
89 | .version = AVC_SW_VERSION_ENTRY, | ||
90 | }, { } | ||
91 | }; | ||
92 | |||
93 | MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table); | ||
94 | |||
95 | /* list of all firedtv devices */ | ||
96 | LIST_HEAD(fdtv_list); | ||
97 | DEFINE_SPINLOCK(fdtv_list_lock); | ||
98 | |||
99 | static void fcp_request(struct hpsb_host *host, | ||
100 | int nodeid, | ||
101 | int direction, | ||
102 | int cts, | ||
103 | u8 *data, | ||
104 | size_t length) | ||
105 | { | ||
106 | struct firedtv *fdtv = NULL; | ||
107 | struct firedtv *fdtv_entry; | ||
108 | unsigned long flags; | ||
109 | |||
110 | if (length > 0 && ((data[0] & 0xf0) >> 4) == 0) { | ||
111 | |||
112 | spin_lock_irqsave(&fdtv_list_lock, flags); | ||
113 | list_for_each_entry(fdtv_entry,&fdtv_list,list) { | ||
114 | if (fdtv_entry->ud->ne->host == host && | ||
115 | fdtv_entry->ud->ne->nodeid == nodeid && | ||
116 | (fdtv_entry->subunit == (data[1]&0x7) || | ||
117 | (fdtv_entry->subunit == 0 && | ||
118 | (data[1]&0x7) == 0x7))) { | ||
119 | fdtv=fdtv_entry; | ||
120 | break; | ||
121 | } | ||
122 | } | ||
123 | spin_unlock_irqrestore(&fdtv_list_lock, flags); | ||
124 | |||
125 | if (fdtv) | ||
126 | avc_recv(fdtv, data, length); | ||
127 | } | ||
128 | } | ||
129 | |||
130 | const char *fdtv_model_names[] = { | ||
131 | [FIREDTV_UNKNOWN] = "unknown type", | ||
132 | [FIREDTV_DVB_S] = "FireDTV S/CI", | ||
133 | [FIREDTV_DVB_C] = "FireDTV C/CI", | ||
134 | [FIREDTV_DVB_T] = "FireDTV T/CI", | ||
135 | [FIREDTV_DVB_S2] = "FireDTV S2 ", | ||
136 | }; | ||
137 | |||
138 | static int fdtv_probe(struct device *dev) | ||
139 | { | ||
140 | struct unit_directory *ud = | ||
141 | container_of(dev, struct unit_directory, device); | ||
142 | struct firedtv *fdtv; | ||
143 | unsigned long flags; | ||
144 | int kv_len; | ||
145 | void *kv_str; | ||
146 | int i; | ||
147 | int err = -ENOMEM; | ||
148 | |||
149 | fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL); | ||
150 | if (!fdtv) | ||
151 | return -ENOMEM; | ||
152 | |||
153 | dev->driver_data = fdtv; | ||
154 | fdtv->ud = ud; | ||
155 | fdtv->subunit = 0; | ||
156 | fdtv->isochannel = -1; | ||
157 | fdtv->tone = 0xff; | ||
158 | fdtv->voltage = 0xff; | ||
159 | |||
160 | mutex_init(&fdtv->avc_mutex); | ||
161 | init_waitqueue_head(&fdtv->avc_wait); | ||
162 | fdtv->avc_reply_received = true; | ||
163 | mutex_init(&fdtv->demux_mutex); | ||
164 | INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work); | ||
165 | |||
166 | /* Reading device model from ROM */ | ||
167 | kv_len = (ud->model_name_kv->value.leaf.len - 2) * sizeof(quadlet_t); | ||
168 | kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv); | ||
169 | for (i = ARRAY_SIZE(fdtv_model_names); --i;) | ||
170 | if (strlen(fdtv_model_names[i]) <= kv_len && | ||
171 | strncmp(kv_str, fdtv_model_names[i], kv_len) == 0) | ||
172 | break; | ||
173 | fdtv->type = i; | ||
174 | |||
175 | /* | ||
176 | * Work around a bug in udev's path_id script: Use the fw-host's dev | ||
177 | * instead of the unit directory's dev as parent of the input device. | ||
178 | */ | ||
179 | err = fdtv_register_rc(fdtv, dev->parent->parent); | ||
180 | if (err) | ||
181 | goto fail_free; | ||
182 | |||
183 | INIT_LIST_HEAD(&fdtv->list); | ||
184 | spin_lock_irqsave(&fdtv_list_lock, flags); | ||
185 | list_add_tail(&fdtv->list, &fdtv_list); | ||
186 | spin_unlock_irqrestore(&fdtv_list_lock, flags); | ||
187 | |||
188 | err = avc_identify_subunit(fdtv); | ||
189 | if (err) | ||
190 | goto fail; | ||
191 | |||
192 | err = fdtv_dvbdev_init(fdtv, dev); | ||
193 | if (err) | ||
194 | goto fail; | ||
195 | |||
196 | avc_register_remote_control(fdtv); | ||
197 | return 0; | ||
198 | |||
199 | fail: | ||
200 | spin_lock_irqsave(&fdtv_list_lock, flags); | ||
201 | list_del(&fdtv->list); | ||
202 | spin_unlock_irqrestore(&fdtv_list_lock, flags); | ||
203 | fdtv_unregister_rc(fdtv); | ||
204 | fail_free: | ||
205 | kfree(fdtv); | ||
206 | return err; | ||
207 | } | ||
208 | |||
209 | static int fdtv_remove(struct device *dev) | ||
210 | { | ||
211 | struct firedtv *fdtv = dev->driver_data; | ||
212 | unsigned long flags; | ||
213 | |||
214 | fdtv_ca_release(fdtv); | ||
215 | dvb_unregister_frontend(&fdtv->fe); | ||
216 | dvb_net_release(&fdtv->dvbnet); | ||
217 | fdtv->demux.dmx.close(&fdtv->demux.dmx); | ||
218 | fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, | ||
219 | &fdtv->frontend); | ||
220 | dvb_dmxdev_release(&fdtv->dmxdev); | ||
221 | dvb_dmx_release(&fdtv->demux); | ||
222 | dvb_unregister_adapter(&fdtv->adapter); | ||
223 | |||
224 | spin_lock_irqsave(&fdtv_list_lock, flags); | ||
225 | list_del(&fdtv->list); | ||
226 | spin_unlock_irqrestore(&fdtv_list_lock, flags); | ||
227 | |||
228 | cancel_work_sync(&fdtv->remote_ctrl_work); | ||
229 | fdtv_unregister_rc(fdtv); | ||
230 | |||
231 | kfree(fdtv); | ||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | static int fdtv_update(struct unit_directory *ud) | ||
236 | { | ||
237 | struct firedtv *fdtv = ud->device.driver_data; | ||
238 | |||
239 | if (fdtv->isochannel >= 0) | ||
240 | cmp_establish_pp_connection(fdtv, fdtv->subunit, | ||
241 | fdtv->isochannel); | ||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static struct hpsb_protocol_driver fdtv_driver = { | ||
246 | |||
247 | .name = "firedtv", | ||
248 | .id_table = fdtv_id_table, | ||
249 | .update = fdtv_update, | ||
250 | |||
251 | .driver = { | ||
252 | //.name and .bus are filled in for us in more recent linux versions | ||
253 | //.name = "FireDTV", | ||
254 | //.bus = &ieee1394_bus_type, | ||
255 | .probe = fdtv_probe, | ||
256 | .remove = fdtv_remove, | ||
257 | }, | ||
258 | }; | ||
259 | |||
260 | static struct hpsb_highlevel fdtv_highlevel = { | ||
261 | .name = "firedtv", | ||
262 | .fcp_request = fcp_request, | ||
263 | }; | ||
264 | |||
265 | static int __init fdtv_init(void) | ||
266 | { | ||
267 | int ret; | ||
268 | |||
269 | hpsb_register_highlevel(&fdtv_highlevel); | ||
270 | ret = hpsb_register_protocol(&fdtv_driver); | ||
271 | if (ret) { | ||
272 | printk(KERN_ERR "firedtv: failed to register protocol\n"); | ||
273 | hpsb_unregister_highlevel(&fdtv_highlevel); | ||
274 | } | ||
275 | return ret; | ||
276 | } | ||
277 | |||
278 | static void __exit fdtv_exit(void) | ||
279 | { | ||
280 | hpsb_unregister_protocol(&fdtv_driver); | ||
281 | hpsb_unregister_highlevel(&fdtv_highlevel); | ||
282 | } | ||
283 | |||
284 | module_init(fdtv_init); | ||
285 | module_exit(fdtv_exit); | ||
286 | |||
287 | MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>"); | ||
288 | MODULE_AUTHOR("Ben Backx <ben@bbackx.com>"); | ||
289 | MODULE_DESCRIPTION("FireDTV DVB Driver"); | ||
290 | MODULE_LICENSE("GPL"); | ||
291 | MODULE_SUPPORTED_DEVICE("FireDTV DVB"); | ||
diff --git a/drivers/media/dvb/firewire/firedtv-ci.c b/drivers/media/dvb/firewire/firedtv-ci.c new file mode 100644 index 000000000000..6d87926b8bfe --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-ci.c | |||
@@ -0,0 +1,261 @@ | |||
1 | /* | ||
2 | * FireDTV driver (formerly known as FireSAT) | ||
3 | * | ||
4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
5 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | ||
6 | * | ||
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. | ||
11 | */ | ||
12 | |||
13 | #include <linux/dvb/ca.h> | ||
14 | #include <linux/fs.h> | ||
15 | #include <linux/module.h> | ||
16 | |||
17 | #include <dvbdev.h> | ||
18 | |||
19 | #include "avc.h" | ||
20 | #include "firedtv.h" | ||
21 | #include "firedtv-ci.h" | ||
22 | |||
23 | static int fdtv_ca_ready(ANTENNA_INPUT_INFO *info) | ||
24 | { | ||
25 | return info->CaInitializationStatus == 1 && | ||
26 | info->CaErrorFlag == 0 && | ||
27 | info->CaDvbFlag == 1 && | ||
28 | info->CaModulePresentStatus == 1; | ||
29 | } | ||
30 | |||
31 | static int fdtv_get_ca_flags(ANTENNA_INPUT_INFO *info) | ||
32 | { | ||
33 | int flags = 0; | ||
34 | |||
35 | if (info->CaModulePresentStatus == 1) | ||
36 | flags |= CA_CI_MODULE_PRESENT; | ||
37 | if (info->CaInitializationStatus == 1 && | ||
38 | info->CaErrorFlag == 0 && | ||
39 | info->CaDvbFlag == 1) | ||
40 | flags |= CA_CI_MODULE_READY; | ||
41 | return flags; | ||
42 | } | ||
43 | |||
44 | static int fdtv_ca_reset(struct firedtv *fdtv) | ||
45 | { | ||
46 | return avc_ca_reset(fdtv) ? -EFAULT : 0; | ||
47 | } | ||
48 | |||
49 | static int fdtv_ca_get_caps(void *arg) | ||
50 | { | ||
51 | struct ca_caps *cap = arg; | ||
52 | |||
53 | cap->slot_num = 1; | ||
54 | cap->slot_type = CA_CI; | ||
55 | cap->descr_num = 1; | ||
56 | cap->descr_type = CA_ECD; | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static int fdtv_ca_get_slot_info(struct firedtv *fdtv, void *arg) | ||
61 | { | ||
62 | ANTENNA_INPUT_INFO info; | ||
63 | struct ca_slot_info *slot = arg; | ||
64 | |||
65 | if (avc_tuner_status(fdtv, &info)) | ||
66 | return -EFAULT; | ||
67 | |||
68 | if (slot->num != 0) | ||
69 | return -EFAULT; | ||
70 | |||
71 | slot->type = CA_CI; | ||
72 | slot->flags = fdtv_get_ca_flags(&info); | ||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static int fdtv_ca_app_info(struct firedtv *fdtv, void *arg) | ||
77 | { | ||
78 | struct ca_msg *reply = arg; | ||
79 | |||
80 | return | ||
81 | avc_ca_app_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0; | ||
82 | } | ||
83 | |||
84 | static int fdtv_ca_info(struct firedtv *fdtv, void *arg) | ||
85 | { | ||
86 | struct ca_msg *reply = arg; | ||
87 | |||
88 | return avc_ca_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0; | ||
89 | } | ||
90 | |||
91 | static int fdtv_ca_get_mmi(struct firedtv *fdtv, void *arg) | ||
92 | { | ||
93 | struct ca_msg *reply = arg; | ||
94 | |||
95 | return | ||
96 | avc_ca_get_mmi(fdtv, reply->msg, &reply->length) ? -EFAULT : 0; | ||
97 | } | ||
98 | |||
99 | static int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg) | ||
100 | { | ||
101 | ANTENNA_INPUT_INFO info; | ||
102 | int err; | ||
103 | |||
104 | switch (fdtv->ca_last_command) { | ||
105 | case TAG_APP_INFO_ENQUIRY: | ||
106 | err = fdtv_ca_app_info(fdtv, arg); | ||
107 | break; | ||
108 | case TAG_CA_INFO_ENQUIRY: | ||
109 | err = fdtv_ca_info(fdtv, arg); | ||
110 | break; | ||
111 | default: | ||
112 | if (avc_tuner_status(fdtv, &info)) | ||
113 | err = -EFAULT; | ||
114 | else if (info.CaMmi == 1) | ||
115 | err = fdtv_ca_get_mmi(fdtv, arg); | ||
116 | else { | ||
117 | printk(KERN_INFO "%s: Unhandled message 0x%08X\n", | ||
118 | __func__, fdtv->ca_last_command); | ||
119 | err = -EFAULT; | ||
120 | } | ||
121 | } | ||
122 | fdtv->ca_last_command = 0; | ||
123 | return err; | ||
124 | } | ||
125 | |||
126 | static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg) | ||
127 | { | ||
128 | struct ca_msg *msg = arg; | ||
129 | int data_pos; | ||
130 | int data_length; | ||
131 | int i; | ||
132 | |||
133 | data_pos = 4; | ||
134 | if (msg->msg[3] & 0x80) { | ||
135 | data_length = 0; | ||
136 | for (i = 0; i < (msg->msg[3] & 0x7F); i++) | ||
137 | data_length = (data_length << 8) + msg->msg[data_pos++]; | ||
138 | } else { | ||
139 | data_length = msg->msg[3]; | ||
140 | } | ||
141 | |||
142 | return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length) ? | ||
143 | -EFAULT : 0; | ||
144 | } | ||
145 | |||
146 | static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg) | ||
147 | { | ||
148 | struct ca_msg *msg = arg; | ||
149 | int err; | ||
150 | |||
151 | /* Do we need a semaphore for this? */ | ||
152 | fdtv->ca_last_command = | ||
153 | (msg->msg[0] << 16) + (msg->msg[1] << 8) + msg->msg[2]; | ||
154 | switch (fdtv->ca_last_command) { | ||
155 | case TAG_CA_PMT: | ||
156 | err = fdtv_ca_pmt(fdtv, arg); | ||
157 | break; | ||
158 | case TAG_APP_INFO_ENQUIRY: | ||
159 | /* handled in ca_get_msg */ | ||
160 | err = 0; | ||
161 | break; | ||
162 | case TAG_CA_INFO_ENQUIRY: | ||
163 | /* handled in ca_get_msg */ | ||
164 | err = 0; | ||
165 | break; | ||
166 | case TAG_ENTER_MENU: | ||
167 | err = avc_ca_enter_menu(fdtv); | ||
168 | break; | ||
169 | default: | ||
170 | printk(KERN_ERR "%s: Unhandled unknown message 0x%08X\n", | ||
171 | __func__, fdtv->ca_last_command); | ||
172 | err = -EFAULT; | ||
173 | } | ||
174 | return err; | ||
175 | } | ||
176 | |||
177 | static int fdtv_ca_ioctl(struct inode *inode, struct file *file, | ||
178 | unsigned int cmd, void *arg) | ||
179 | { | ||
180 | struct dvb_device *dvbdev = file->private_data; | ||
181 | struct firedtv *fdtv = dvbdev->priv; | ||
182 | ANTENNA_INPUT_INFO info; | ||
183 | int err; | ||
184 | |||
185 | switch(cmd) { | ||
186 | case CA_RESET: | ||
187 | err = fdtv_ca_reset(fdtv); | ||
188 | break; | ||
189 | case CA_GET_CAP: | ||
190 | err = fdtv_ca_get_caps(arg); | ||
191 | break; | ||
192 | case CA_GET_SLOT_INFO: | ||
193 | err = fdtv_ca_get_slot_info(fdtv, arg); | ||
194 | break; | ||
195 | case CA_GET_MSG: | ||
196 | err = fdtv_ca_get_msg(fdtv, arg); | ||
197 | break; | ||
198 | case CA_SEND_MSG: | ||
199 | err = fdtv_ca_send_msg(fdtv, arg); | ||
200 | break; | ||
201 | default: | ||
202 | printk(KERN_INFO "%s: Unhandled ioctl, command: %u\n",__func__, | ||
203 | cmd); | ||
204 | err = -EOPNOTSUPP; | ||
205 | } | ||
206 | |||
207 | /* FIXME Is this necessary? */ | ||
208 | avc_tuner_status(fdtv, &info); | ||
209 | |||
210 | return err; | ||
211 | } | ||
212 | |||
213 | static unsigned int fdtv_ca_io_poll(struct file *file, poll_table *wait) | ||
214 | { | ||
215 | return POLLIN; | ||
216 | } | ||
217 | |||
218 | static struct file_operations fdtv_ca_fops = { | ||
219 | .owner = THIS_MODULE, | ||
220 | .ioctl = dvb_generic_ioctl, | ||
221 | .open = dvb_generic_open, | ||
222 | .release = dvb_generic_release, | ||
223 | .poll = fdtv_ca_io_poll, | ||
224 | }; | ||
225 | |||
226 | static struct dvb_device fdtv_ca = { | ||
227 | .users = 1, | ||
228 | .readers = 1, | ||
229 | .writers = 1, | ||
230 | .fops = &fdtv_ca_fops, | ||
231 | .kernel_ioctl = fdtv_ca_ioctl, | ||
232 | }; | ||
233 | |||
234 | int fdtv_ca_register(struct firedtv *fdtv) | ||
235 | { | ||
236 | ANTENNA_INPUT_INFO info; | ||
237 | int err; | ||
238 | |||
239 | if (avc_tuner_status(fdtv, &info)) | ||
240 | return -EINVAL; | ||
241 | |||
242 | if (!fdtv_ca_ready(&info)) | ||
243 | return -EFAULT; | ||
244 | |||
245 | err = dvb_register_device(&fdtv->adapter, &fdtv->cadev, | ||
246 | &fdtv_ca, fdtv, DVB_DEVICE_CA); | ||
247 | |||
248 | if (info.CaApplicationInfo == 0) | ||
249 | printk(KERN_ERR "%s: CaApplicationInfo is not set.\n", | ||
250 | __func__); | ||
251 | if (info.CaDateTimeRequest == 1) | ||
252 | avc_ca_get_time_date(fdtv, &fdtv->ca_time_interval); | ||
253 | |||
254 | return err; | ||
255 | } | ||
256 | |||
257 | void fdtv_ca_release(struct firedtv *fdtv) | ||
258 | { | ||
259 | if (fdtv->cadev) | ||
260 | dvb_unregister_device(fdtv->cadev); | ||
261 | } | ||
diff --git a/drivers/media/dvb/firewire/firedtv-ci.h b/drivers/media/dvb/firewire/firedtv-ci.h new file mode 100644 index 000000000000..d6840f5dcbae --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-ci.h | |||
@@ -0,0 +1,9 @@ | |||
1 | #ifndef _FIREDTV_CI_H | ||
2 | #define _FIREDTV_CI_H | ||
3 | |||
4 | struct firedtv; | ||
5 | |||
6 | int fdtv_ca_register(struct firedtv *fdtv); | ||
7 | void fdtv_ca_release(struct firedtv *fdtv); | ||
8 | |||
9 | #endif /* _FIREDTV_CI_H */ | ||
diff --git a/drivers/media/dvb/firewire/firedtv-dvb.c b/drivers/media/dvb/firewire/firedtv-dvb.c new file mode 100644 index 000000000000..1823058696f2 --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-dvb.c | |||
@@ -0,0 +1,276 @@ | |||
1 | /* | ||
2 | * FireDTV driver (formerly known as FireSAT) | ||
3 | * | ||
4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
5 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | ||
6 | * | ||
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. | ||
11 | */ | ||
12 | |||
13 | #include <linux/errno.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/mutex.h> | ||
16 | #include <linux/types.h> | ||
17 | |||
18 | #include <dvb_demux.h> | ||
19 | #include <dvb_frontend.h> | ||
20 | #include <dvbdev.h> | ||
21 | |||
22 | #include "avc.h" | ||
23 | #include "firedtv.h" | ||
24 | #include "firedtv-ci.h" | ||
25 | |||
26 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
27 | |||
28 | static struct firedtv_channel *fdtv_channel_allocate(struct firedtv *fdtv) | ||
29 | { | ||
30 | struct firedtv_channel *c = NULL; | ||
31 | int k; | ||
32 | |||
33 | if (mutex_lock_interruptible(&fdtv->demux_mutex)) | ||
34 | return NULL; | ||
35 | |||
36 | for (k = 0; k < 16; k++) | ||
37 | if (!fdtv->channel[k].active) { | ||
38 | fdtv->channel[k].active = true; | ||
39 | c = &fdtv->channel[k]; | ||
40 | break; | ||
41 | } | ||
42 | |||
43 | mutex_unlock(&fdtv->demux_mutex); | ||
44 | return c; | ||
45 | } | ||
46 | |||
47 | static int fdtv_channel_collect(struct firedtv *fdtv, int *pidc, u16 pid[]) | ||
48 | { | ||
49 | int k, l = 0; | ||
50 | |||
51 | if (mutex_lock_interruptible(&fdtv->demux_mutex)) | ||
52 | return -EINTR; | ||
53 | |||
54 | for (k = 0; k < 16; k++) | ||
55 | if (fdtv->channel[k].active) | ||
56 | pid[l++] = fdtv->channel[k].pid; | ||
57 | |||
58 | mutex_unlock(&fdtv->demux_mutex); | ||
59 | |||
60 | *pidc = l; | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static int fdtv_channel_release(struct firedtv *fdtv, | ||
66 | struct firedtv_channel *channel) | ||
67 | { | ||
68 | if (mutex_lock_interruptible(&fdtv->demux_mutex)) | ||
69 | return -EINTR; | ||
70 | |||
71 | channel->active = false; | ||
72 | |||
73 | mutex_unlock(&fdtv->demux_mutex); | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
78 | { | ||
79 | struct firedtv *fdtv = (struct firedtv*)dvbdmxfeed->demux->priv; | ||
80 | struct firedtv_channel *channel; | ||
81 | int pidc,k; | ||
82 | u16 pids[16]; | ||
83 | |||
84 | switch (dvbdmxfeed->type) { | ||
85 | case DMX_TYPE_TS: | ||
86 | case DMX_TYPE_SEC: | ||
87 | break; | ||
88 | default: | ||
89 | printk(KERN_ERR "%s: invalid type %u\n", | ||
90 | __func__, dvbdmxfeed->type); | ||
91 | return -EINVAL; | ||
92 | } | ||
93 | |||
94 | if (dvbdmxfeed->type == DMX_TYPE_TS) { | ||
95 | switch (dvbdmxfeed->pes_type) { | ||
96 | case DMX_TS_PES_VIDEO: | ||
97 | case DMX_TS_PES_AUDIO: | ||
98 | case DMX_TS_PES_TELETEXT: | ||
99 | case DMX_TS_PES_PCR: | ||
100 | case DMX_TS_PES_OTHER: | ||
101 | //Dirty fix to keep fdtv->channel pid-list up to date | ||
102 | for(k=0;k<16;k++){ | ||
103 | if (!fdtv->channel[k].active) | ||
104 | fdtv->channel[k].pid = | ||
105 | dvbdmxfeed->pid; | ||
106 | break; | ||
107 | } | ||
108 | channel = fdtv_channel_allocate(fdtv); | ||
109 | break; | ||
110 | default: | ||
111 | printk(KERN_ERR "%s: invalid pes type %u\n", | ||
112 | __func__, dvbdmxfeed->pes_type); | ||
113 | return -EINVAL; | ||
114 | } | ||
115 | } else { | ||
116 | channel = fdtv_channel_allocate(fdtv); | ||
117 | } | ||
118 | |||
119 | if (!channel) { | ||
120 | printk(KERN_ERR "%s: busy!\n", __func__); | ||
121 | return -EBUSY; | ||
122 | } | ||
123 | |||
124 | dvbdmxfeed->priv = channel; | ||
125 | channel->pid = dvbdmxfeed->pid; | ||
126 | |||
127 | if (fdtv_channel_collect(fdtv, &pidc, pids)) { | ||
128 | fdtv_channel_release(fdtv, channel); | ||
129 | printk(KERN_ERR "%s: could not collect pids!\n", __func__); | ||
130 | return -EINTR; | ||
131 | } | ||
132 | |||
133 | if (dvbdmxfeed->pid == 8192) { | ||
134 | k = avc_tuner_get_ts(fdtv); | ||
135 | if (k) { | ||
136 | fdtv_channel_release(fdtv, channel); | ||
137 | printk("%s: AVCTuner_GetTS failed with error %d\n", | ||
138 | __func__, k); | ||
139 | return k; | ||
140 | } | ||
141 | } else { | ||
142 | k = avc_tuner_set_pids(fdtv, pidc, pids); | ||
143 | if (k) { | ||
144 | fdtv_channel_release(fdtv, channel); | ||
145 | printk("%s: AVCTuner_SetPIDs failed with error %d\n", | ||
146 | __func__, k); | ||
147 | return k; | ||
148 | } | ||
149 | } | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
155 | { | ||
156 | struct dvb_demux *demux = dvbdmxfeed->demux; | ||
157 | struct firedtv *fdtv = (struct firedtv*)demux->priv; | ||
158 | struct firedtv_channel *c = dvbdmxfeed->priv; | ||
159 | int k, l; | ||
160 | u16 pids[16]; | ||
161 | |||
162 | if (dvbdmxfeed->type == DMX_TYPE_TS && !((dvbdmxfeed->ts_type & TS_PACKET) && | ||
163 | (demux->dmx.frontend->source != DMX_MEMORY_FE))) { | ||
164 | |||
165 | if (dvbdmxfeed->ts_type & TS_DECODER) { | ||
166 | |||
167 | if (dvbdmxfeed->pes_type >= DMX_TS_PES_OTHER || | ||
168 | !demux->pesfilter[dvbdmxfeed->pes_type]) | ||
169 | |||
170 | return -EINVAL; | ||
171 | |||
172 | demux->pids[dvbdmxfeed->pes_type] |= 0x8000; | ||
173 | demux->pesfilter[dvbdmxfeed->pes_type] = NULL; | ||
174 | } | ||
175 | |||
176 | if (!(dvbdmxfeed->ts_type & TS_DECODER && | ||
177 | dvbdmxfeed->pes_type < DMX_TS_PES_OTHER)) | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | if (mutex_lock_interruptible(&fdtv->demux_mutex)) | ||
183 | return -EINTR; | ||
184 | |||
185 | /* list except channel to be removed */ | ||
186 | for (k = 0, l = 0; k < 16; k++) | ||
187 | if (fdtv->channel[k].active) { | ||
188 | if (&fdtv->channel[k] != c) | ||
189 | pids[l++] = fdtv->channel[k].pid; | ||
190 | else | ||
191 | fdtv->channel[k].active = false; | ||
192 | } | ||
193 | |||
194 | k = avc_tuner_set_pids(fdtv, l, pids); | ||
195 | if (!k) | ||
196 | c->active = false; | ||
197 | |||
198 | mutex_unlock(&fdtv->demux_mutex); | ||
199 | return k; | ||
200 | } | ||
201 | |||
202 | int fdtv_dvbdev_init(struct firedtv *fdtv, struct device *dev) | ||
203 | { | ||
204 | int err; | ||
205 | |||
206 | err = DVB_REGISTER_ADAPTER(&fdtv->adapter, | ||
207 | fdtv_model_names[fdtv->type], | ||
208 | THIS_MODULE, dev, adapter_nr); | ||
209 | if (err < 0) | ||
210 | goto fail_log; | ||
211 | |||
212 | /*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/ | ||
213 | fdtv->demux.dmx.capabilities = 0; | ||
214 | |||
215 | fdtv->demux.priv = fdtv; | ||
216 | fdtv->demux.filternum = 16; | ||
217 | fdtv->demux.feednum = 16; | ||
218 | fdtv->demux.start_feed = fdtv_start_feed; | ||
219 | fdtv->demux.stop_feed = fdtv_stop_feed; | ||
220 | fdtv->demux.write_to_decoder = NULL; | ||
221 | |||
222 | err = dvb_dmx_init(&fdtv->demux); | ||
223 | if (err) | ||
224 | goto fail_unreg_adapter; | ||
225 | |||
226 | fdtv->dmxdev.filternum = 16; | ||
227 | fdtv->dmxdev.demux = &fdtv->demux.dmx; | ||
228 | fdtv->dmxdev.capabilities = 0; | ||
229 | |||
230 | err = dvb_dmxdev_init(&fdtv->dmxdev, &fdtv->adapter); | ||
231 | if (err) | ||
232 | goto fail_dmx_release; | ||
233 | |||
234 | fdtv->frontend.source = DMX_FRONTEND_0; | ||
235 | |||
236 | err = fdtv->demux.dmx.add_frontend(&fdtv->demux.dmx, | ||
237 | &fdtv->frontend); | ||
238 | if (err) | ||
239 | goto fail_dmxdev_release; | ||
240 | |||
241 | err = fdtv->demux.dmx.connect_frontend(&fdtv->demux.dmx, | ||
242 | &fdtv->frontend); | ||
243 | if (err) | ||
244 | goto fail_rem_frontend; | ||
245 | |||
246 | dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx); | ||
247 | |||
248 | fdtv_frontend_init(fdtv); | ||
249 | err = dvb_register_frontend(&fdtv->adapter, &fdtv->fe); | ||
250 | if (err) | ||
251 | goto fail_net_release; | ||
252 | |||
253 | err = fdtv_ca_register(fdtv); | ||
254 | if (err) | ||
255 | dev_info(dev, "Conditional Access Module not enabled\n"); | ||
256 | |||
257 | return 0; | ||
258 | |||
259 | fail_net_release: | ||
260 | dvb_net_release(&fdtv->dvbnet); | ||
261 | fdtv->demux.dmx.close(&fdtv->demux.dmx); | ||
262 | fail_rem_frontend: | ||
263 | fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, | ||
264 | &fdtv->frontend); | ||
265 | fail_dmxdev_release: | ||
266 | dvb_dmxdev_release(&fdtv->dmxdev); | ||
267 | fail_dmx_release: | ||
268 | dvb_dmx_release(&fdtv->demux); | ||
269 | fail_unreg_adapter: | ||
270 | dvb_unregister_adapter(&fdtv->adapter); | ||
271 | fail_log: | ||
272 | dev_err(dev, "DVB initialization failed\n"); | ||
273 | return err; | ||
274 | } | ||
275 | |||
276 | |||
diff --git a/drivers/media/dvb/firewire/firedtv-fe.c b/drivers/media/dvb/firewire/firedtv-fe.c new file mode 100644 index 000000000000..f8150f402bb6 --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-fe.c | |||
@@ -0,0 +1,245 @@ | |||
1 | /* | ||
2 | * FireDTV driver (formerly known as FireSAT) | ||
3 | * | ||
4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
5 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | ||
6 | * | ||
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. | ||
11 | */ | ||
12 | |||
13 | #include <linux/errno.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/types.h> | ||
17 | |||
18 | #include <dvb_frontend.h> | ||
19 | |||
20 | #include "avc.h" | ||
21 | #include "cmp.h" | ||
22 | #include "firedtv.h" | ||
23 | |||
24 | static int fdtv_dvb_init(struct dvb_frontend *fe) | ||
25 | { | ||
26 | struct firedtv *fdtv = fe->sec_priv; | ||
27 | int err; | ||
28 | |||
29 | /* FIXME - allocate free channel at IRM */ | ||
30 | fdtv->isochannel = fdtv->adapter.num; | ||
31 | |||
32 | err = cmp_establish_pp_connection(fdtv, fdtv->subunit, | ||
33 | fdtv->isochannel); | ||
34 | if (err) { | ||
35 | printk(KERN_ERR "Could not establish point to point " | ||
36 | "connection.\n"); | ||
37 | return err; | ||
38 | } | ||
39 | |||
40 | return setup_iso_channel(fdtv); | ||
41 | } | ||
42 | |||
43 | static int fdtv_sleep(struct dvb_frontend *fe) | ||
44 | { | ||
45 | struct firedtv *fdtv = fe->sec_priv; | ||
46 | |||
47 | tear_down_iso_channel(fdtv); | ||
48 | cmp_break_pp_connection(fdtv, fdtv->subunit, fdtv->isochannel); | ||
49 | fdtv->isochannel = -1; | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | static int fdtv_diseqc_send_master_cmd(struct dvb_frontend *fe, | ||
54 | struct dvb_diseqc_master_cmd *cmd) | ||
55 | { | ||
56 | struct firedtv *fdtv = fe->sec_priv; | ||
57 | |||
58 | return avc_lnb_control(fdtv, LNBCONTROL_DONTCARE, | ||
59 | LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE, 1, cmd); | ||
60 | } | ||
61 | |||
62 | static int fdtv_diseqc_send_burst(struct dvb_frontend *fe, | ||
63 | fe_sec_mini_cmd_t minicmd) | ||
64 | { | ||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static int fdtv_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) | ||
69 | { | ||
70 | struct firedtv *fdtv = fe->sec_priv; | ||
71 | |||
72 | fdtv->tone = tone; | ||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static int fdtv_set_voltage(struct dvb_frontend *fe, | ||
77 | fe_sec_voltage_t voltage) | ||
78 | { | ||
79 | struct firedtv *fdtv = fe->sec_priv; | ||
80 | |||
81 | fdtv->voltage = voltage; | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | static int fdtv_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||
86 | { | ||
87 | struct firedtv *fdtv = fe->sec_priv; | ||
88 | ANTENNA_INPUT_INFO info; | ||
89 | |||
90 | if (avc_tuner_status(fdtv, &info)) | ||
91 | return -EINVAL; | ||
92 | |||
93 | if (info.NoRF) | ||
94 | *status = 0; | ||
95 | else | ||
96 | *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | FE_HAS_SYNC | | ||
97 | FE_HAS_CARRIER | FE_HAS_LOCK; | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static int fdtv_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
102 | { | ||
103 | struct firedtv *fdtv = fe->sec_priv; | ||
104 | ANTENNA_INPUT_INFO info; | ||
105 | |||
106 | if (avc_tuner_status(fdtv, &info)) | ||
107 | return -EINVAL; | ||
108 | |||
109 | *ber = info.BER[0] << 24 | info.BER[1] << 16 | | ||
110 | info.BER[2] << 8 | info.BER[3]; | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static int fdtv_read_signal_strength (struct dvb_frontend *fe, u16 *strength) | ||
115 | { | ||
116 | struct firedtv *fdtv = fe->sec_priv; | ||
117 | ANTENNA_INPUT_INFO info; | ||
118 | |||
119 | if (avc_tuner_status(fdtv, &info)) | ||
120 | return -EINVAL; | ||
121 | |||
122 | *strength = info.SignalStrength << 8; | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static int fdtv_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
127 | { | ||
128 | struct firedtv *fdtv = fe->sec_priv; | ||
129 | ANTENNA_INPUT_INFO info; | ||
130 | |||
131 | if (avc_tuner_status(fdtv, &info)) | ||
132 | return -EINVAL; | ||
133 | |||
134 | /* C/N[dB] = -10 * log10(snr / 65535) */ | ||
135 | *snr = (info.CarrierNoiseRatio[0] << 8) + info.CarrierNoiseRatio[1]; | ||
136 | *snr *= 257; | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static int fdtv_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ucblocks) | ||
141 | { | ||
142 | return -EOPNOTSUPP; | ||
143 | } | ||
144 | |||
145 | static int fdtv_set_frontend(struct dvb_frontend *fe, | ||
146 | struct dvb_frontend_parameters *params) | ||
147 | { | ||
148 | struct firedtv *fdtv = fe->sec_priv; | ||
149 | |||
150 | /* FIXME: avc_tuner_dsd never returns ACCEPTED. Check status? */ | ||
151 | if (avc_tuner_dsd(fdtv, params) != ACCEPTED) | ||
152 | return -EINVAL; | ||
153 | else | ||
154 | return 0; /* not sure of this... */ | ||
155 | } | ||
156 | |||
157 | static int fdtv_get_frontend(struct dvb_frontend *fe, | ||
158 | struct dvb_frontend_parameters *params) | ||
159 | { | ||
160 | return -EOPNOTSUPP; | ||
161 | } | ||
162 | |||
163 | void fdtv_frontend_init(struct firedtv *fdtv) | ||
164 | { | ||
165 | struct dvb_frontend_ops *ops = &fdtv->fe.ops; | ||
166 | struct dvb_frontend_info *fi = &ops->info; | ||
167 | |||
168 | ops->init = fdtv_dvb_init; | ||
169 | ops->sleep = fdtv_sleep; | ||
170 | |||
171 | ops->set_frontend = fdtv_set_frontend; | ||
172 | ops->get_frontend = fdtv_get_frontend; | ||
173 | |||
174 | ops->read_status = fdtv_read_status; | ||
175 | ops->read_ber = fdtv_read_ber; | ||
176 | ops->read_signal_strength = fdtv_read_signal_strength; | ||
177 | ops->read_snr = fdtv_read_snr; | ||
178 | ops->read_ucblocks = fdtv_read_uncorrected_blocks; | ||
179 | |||
180 | ops->diseqc_send_master_cmd = fdtv_diseqc_send_master_cmd; | ||
181 | ops->diseqc_send_burst = fdtv_diseqc_send_burst; | ||
182 | ops->set_tone = fdtv_set_tone; | ||
183 | ops->set_voltage = fdtv_set_voltage; | ||
184 | |||
185 | switch (fdtv->type) { | ||
186 | case FIREDTV_DVB_S: | ||
187 | fi->type = FE_QPSK; | ||
188 | |||
189 | fi->frequency_min = 950000; | ||
190 | fi->frequency_max = 2150000; | ||
191 | fi->frequency_stepsize = 125; | ||
192 | fi->symbol_rate_min = 1000000; | ||
193 | fi->symbol_rate_max = 40000000; | ||
194 | |||
195 | fi->caps = FE_CAN_INVERSION_AUTO | | ||
196 | FE_CAN_FEC_1_2 | | ||
197 | FE_CAN_FEC_2_3 | | ||
198 | FE_CAN_FEC_3_4 | | ||
199 | FE_CAN_FEC_5_6 | | ||
200 | FE_CAN_FEC_7_8 | | ||
201 | FE_CAN_FEC_AUTO | | ||
202 | FE_CAN_QPSK; | ||
203 | break; | ||
204 | |||
205 | case FIREDTV_DVB_C: | ||
206 | fi->type = FE_QAM; | ||
207 | |||
208 | fi->frequency_min = 47000000; | ||
209 | fi->frequency_max = 866000000; | ||
210 | fi->frequency_stepsize = 62500; | ||
211 | fi->symbol_rate_min = 870000; | ||
212 | fi->symbol_rate_max = 6900000; | ||
213 | |||
214 | fi->caps = FE_CAN_INVERSION_AUTO | | ||
215 | FE_CAN_QAM_16 | | ||
216 | FE_CAN_QAM_32 | | ||
217 | FE_CAN_QAM_64 | | ||
218 | FE_CAN_QAM_128 | | ||
219 | FE_CAN_QAM_256 | | ||
220 | FE_CAN_QAM_AUTO; | ||
221 | break; | ||
222 | |||
223 | case FIREDTV_DVB_T: | ||
224 | fi->type = FE_OFDM; | ||
225 | |||
226 | fi->frequency_min = 49000000; | ||
227 | fi->frequency_max = 861000000; | ||
228 | fi->frequency_stepsize = 62500; | ||
229 | |||
230 | fi->caps = FE_CAN_INVERSION_AUTO | | ||
231 | FE_CAN_FEC_2_3 | | ||
232 | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
233 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
234 | FE_CAN_HIERARCHY_AUTO; | ||
235 | break; | ||
236 | |||
237 | default: | ||
238 | printk(KERN_ERR "FireDTV: no frontend for model type %d\n", | ||
239 | fdtv->type); | ||
240 | } | ||
241 | strcpy(fi->name, fdtv_model_names[fdtv->type]); | ||
242 | |||
243 | fdtv->fe.dvb = &fdtv->adapter; | ||
244 | fdtv->fe.sec_priv = fdtv; | ||
245 | } | ||
diff --git a/drivers/media/dvb/firewire/firedtv-iso.c b/drivers/media/dvb/firewire/firedtv-iso.c new file mode 100644 index 000000000000..a72df228e7de --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-iso.c | |||
@@ -0,0 +1,111 @@ | |||
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 | |||
12 | #include <linux/errno.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/list.h> | ||
15 | #include <linux/spinlock.h> | ||
16 | |||
17 | #include <dvb_demux.h> | ||
18 | |||
19 | #include <dma.h> | ||
20 | #include <iso.h> | ||
21 | #include <nodemgr.h> | ||
22 | |||
23 | #include "firedtv.h" | ||
24 | |||
25 | static void rawiso_activity_cb(struct hpsb_iso *iso); | ||
26 | |||
27 | void tear_down_iso_channel(struct firedtv *fdtv) | ||
28 | { | ||
29 | if (fdtv->iso_handle != NULL) { | ||
30 | hpsb_iso_stop(fdtv->iso_handle); | ||
31 | hpsb_iso_shutdown(fdtv->iso_handle); | ||
32 | } | ||
33 | fdtv->iso_handle = NULL; | ||
34 | } | ||
35 | |||
36 | int setup_iso_channel(struct firedtv *fdtv) | ||
37 | { | ||
38 | int result; | ||
39 | fdtv->iso_handle = | ||
40 | hpsb_iso_recv_init(fdtv->ud->ne->host, | ||
41 | 256 * 200, //data_buf_size, | ||
42 | 256, //buf_packets, | ||
43 | fdtv->isochannel, | ||
44 | HPSB_ISO_DMA_DEFAULT, //dma_mode, | ||
45 | -1, //stat.config.irq_interval, | ||
46 | rawiso_activity_cb); | ||
47 | if (fdtv->iso_handle == NULL) { | ||
48 | printk(KERN_ERR "Cannot initialize iso receive.\n"); | ||
49 | return -EINVAL; | ||
50 | } | ||
51 | result = hpsb_iso_recv_start(fdtv->iso_handle, -1, -1, 0); | ||
52 | if (result != 0) { | ||
53 | printk(KERN_ERR "Cannot start iso receive.\n"); | ||
54 | return -EINVAL; | ||
55 | } | ||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | static void rawiso_activity_cb(struct hpsb_iso *iso) | ||
60 | { | ||
61 | unsigned int num; | ||
62 | unsigned int i; | ||
63 | unsigned int packet; | ||
64 | unsigned long flags; | ||
65 | struct firedtv *fdtv = NULL; | ||
66 | struct firedtv *fdtv_iterator; | ||
67 | |||
68 | spin_lock_irqsave(&fdtv_list_lock, flags); | ||
69 | list_for_each_entry(fdtv_iterator, &fdtv_list, list) { | ||
70 | if(fdtv_iterator->iso_handle == iso) { | ||
71 | fdtv = fdtv_iterator; | ||
72 | break; | ||
73 | } | ||
74 | } | ||
75 | spin_unlock_irqrestore(&fdtv_list_lock, flags); | ||
76 | |||
77 | if (fdtv) { | ||
78 | packet = iso->first_packet; | ||
79 | num = hpsb_iso_n_ready(iso); | ||
80 | for (i = 0; i < num; i++, | ||
81 | packet = (packet + 1) % iso->buf_packets) { | ||
82 | unsigned char *buf = | ||
83 | dma_region_i(&iso->data_buf, unsigned char, | ||
84 | iso->infos[packet].offset + | ||
85 | sizeof(struct CIPHeader)); | ||
86 | int count = (iso->infos[packet].len - | ||
87 | sizeof(struct CIPHeader)) / | ||
88 | (188 + sizeof(struct firewireheader)); | ||
89 | if (iso->infos[packet].len <= sizeof(struct CIPHeader)) | ||
90 | continue; // ignore empty packet | ||
91 | |||
92 | while (count --) { | ||
93 | if (buf[sizeof(struct firewireheader)] == 0x47) | ||
94 | dvb_dmx_swfilter_packets(&fdtv->demux, | ||
95 | &buf[sizeof(struct firewireheader)], 1); | ||
96 | else | ||
97 | printk("%s: invalid packet, skipping\n", __func__); | ||
98 | buf += 188 + sizeof(struct firewireheader); | ||
99 | |||
100 | } | ||
101 | |||
102 | } | ||
103 | hpsb_iso_recv_release_packets(iso, num); | ||
104 | } | ||
105 | else { | ||
106 | printk("%s: packets for unknown iso channel, skipping\n", | ||
107 | __func__); | ||
108 | hpsb_iso_recv_release_packets(iso, hpsb_iso_n_ready(iso)); | ||
109 | } | ||
110 | } | ||
111 | |||
diff --git a/drivers/media/dvb/firewire/firedtv-rc.c b/drivers/media/dvb/firewire/firedtv-rc.c new file mode 100644 index 000000000000..436c0c69a13d --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-rc.c | |||
@@ -0,0 +1,191 @@ | |||
1 | /* | ||
2 | * FireDTV driver (formerly known as FireSAT) | ||
3 | * | ||
4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
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 | |||
12 | #include <linux/bitops.h> | ||
13 | #include <linux/input.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/types.h> | ||
17 | |||
18 | #include "firedtv-rc.h" | ||
19 | #include "firedtv.h" | ||
20 | |||
21 | /* fixed table with older keycodes, geared towards MythTV */ | ||
22 | const static u16 oldtable[] = { | ||
23 | |||
24 | /* code from device: 0x4501...0x451f */ | ||
25 | |||
26 | KEY_ESC, | ||
27 | KEY_F9, | ||
28 | KEY_1, | ||
29 | KEY_2, | ||
30 | KEY_3, | ||
31 | KEY_4, | ||
32 | KEY_5, | ||
33 | KEY_6, | ||
34 | KEY_7, | ||
35 | KEY_8, | ||
36 | KEY_9, | ||
37 | KEY_I, | ||
38 | KEY_0, | ||
39 | KEY_ENTER, | ||
40 | KEY_RED, | ||
41 | KEY_UP, | ||
42 | KEY_GREEN, | ||
43 | KEY_F10, | ||
44 | KEY_SPACE, | ||
45 | KEY_F11, | ||
46 | KEY_YELLOW, | ||
47 | KEY_DOWN, | ||
48 | KEY_BLUE, | ||
49 | KEY_Z, | ||
50 | KEY_P, | ||
51 | KEY_PAGEDOWN, | ||
52 | KEY_LEFT, | ||
53 | KEY_W, | ||
54 | KEY_RIGHT, | ||
55 | KEY_P, | ||
56 | KEY_M, | ||
57 | |||
58 | /* code from device: 0x4540...0x4542 */ | ||
59 | |||
60 | KEY_R, | ||
61 | KEY_V, | ||
62 | KEY_C, | ||
63 | }; | ||
64 | |||
65 | /* user-modifiable table for a remote as sold in 2008 */ | ||
66 | const static u16 keytable[] = { | ||
67 | |||
68 | /* code from device: 0x0300...0x031f */ | ||
69 | |||
70 | [0x00] = KEY_POWER, | ||
71 | [0x01] = KEY_SLEEP, | ||
72 | [0x02] = KEY_STOP, | ||
73 | [0x03] = KEY_OK, | ||
74 | [0x04] = KEY_RIGHT, | ||
75 | [0x05] = KEY_1, | ||
76 | [0x06] = KEY_2, | ||
77 | [0x07] = KEY_3, | ||
78 | [0x08] = KEY_LEFT, | ||
79 | [0x09] = KEY_4, | ||
80 | [0x0a] = KEY_5, | ||
81 | [0x0b] = KEY_6, | ||
82 | [0x0c] = KEY_UP, | ||
83 | [0x0d] = KEY_7, | ||
84 | [0x0e] = KEY_8, | ||
85 | [0x0f] = KEY_9, | ||
86 | [0x10] = KEY_DOWN, | ||
87 | [0x11] = KEY_TITLE, /* "OSD" - fixme */ | ||
88 | [0x12] = KEY_0, | ||
89 | [0x13] = KEY_F20, /* "16:9" - fixme */ | ||
90 | [0x14] = KEY_SCREEN, /* "FULL" - fixme */ | ||
91 | [0x15] = KEY_MUTE, | ||
92 | [0x16] = KEY_SUBTITLE, | ||
93 | [0x17] = KEY_RECORD, | ||
94 | [0x18] = KEY_TEXT, | ||
95 | [0x19] = KEY_AUDIO, | ||
96 | [0x1a] = KEY_RED, | ||
97 | [0x1b] = KEY_PREVIOUS, | ||
98 | [0x1c] = KEY_REWIND, | ||
99 | [0x1d] = KEY_PLAYPAUSE, | ||
100 | [0x1e] = KEY_NEXT, | ||
101 | [0x1f] = KEY_VOLUMEUP, | ||
102 | |||
103 | /* code from device: 0x0340...0x0354 */ | ||
104 | |||
105 | [0x20] = KEY_CHANNELUP, | ||
106 | [0x21] = KEY_F21, /* "4:3" - fixme */ | ||
107 | [0x22] = KEY_TV, | ||
108 | [0x23] = KEY_DVD, | ||
109 | [0x24] = KEY_VCR, | ||
110 | [0x25] = KEY_AUX, | ||
111 | [0x26] = KEY_GREEN, | ||
112 | [0x27] = KEY_YELLOW, | ||
113 | [0x28] = KEY_BLUE, | ||
114 | [0x29] = KEY_CHANNEL, /* "CH.LIST" */ | ||
115 | [0x2a] = KEY_VENDOR, /* "CI" - fixme */ | ||
116 | [0x2b] = KEY_VOLUMEDOWN, | ||
117 | [0x2c] = KEY_CHANNELDOWN, | ||
118 | [0x2d] = KEY_LAST, | ||
119 | [0x2e] = KEY_INFO, | ||
120 | [0x2f] = KEY_FORWARD, | ||
121 | [0x30] = KEY_LIST, | ||
122 | [0x31] = KEY_FAVORITES, | ||
123 | [0x32] = KEY_MENU, | ||
124 | [0x33] = KEY_EPG, | ||
125 | [0x34] = KEY_EXIT, | ||
126 | }; | ||
127 | |||
128 | int fdtv_register_rc(struct firedtv *fdtv, struct device *dev) | ||
129 | { | ||
130 | struct input_dev *idev; | ||
131 | int i, err; | ||
132 | |||
133 | idev = input_allocate_device(); | ||
134 | if (!idev) | ||
135 | return -ENOMEM; | ||
136 | |||
137 | fdtv->remote_ctrl_dev = idev; | ||
138 | idev->name = "FireDTV remote control"; | ||
139 | idev->dev.parent = dev; | ||
140 | idev->evbit[0] = BIT_MASK(EV_KEY); | ||
141 | idev->keycode = kmemdup(keytable, sizeof(keytable), GFP_KERNEL); | ||
142 | if (!idev->keycode) { | ||
143 | err = -ENOMEM; | ||
144 | goto fail; | ||
145 | } | ||
146 | idev->keycodesize = sizeof(keytable[0]); | ||
147 | idev->keycodemax = ARRAY_SIZE(keytable); | ||
148 | |||
149 | for (i = 0; i < ARRAY_SIZE(keytable); i++) | ||
150 | set_bit(keytable[i], idev->keybit); | ||
151 | |||
152 | err = input_register_device(idev); | ||
153 | if (err) | ||
154 | goto fail_free_keymap; | ||
155 | |||
156 | return 0; | ||
157 | |||
158 | fail_free_keymap: | ||
159 | kfree(idev->keycode); | ||
160 | fail: | ||
161 | input_free_device(idev); | ||
162 | return err; | ||
163 | } | ||
164 | |||
165 | void fdtv_unregister_rc(struct firedtv *fdtv) | ||
166 | { | ||
167 | kfree(fdtv->remote_ctrl_dev->keycode); | ||
168 | input_unregister_device(fdtv->remote_ctrl_dev); | ||
169 | } | ||
170 | |||
171 | void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code) | ||
172 | { | ||
173 | u16 *keycode = fdtv->remote_ctrl_dev->keycode; | ||
174 | |||
175 | if (code >= 0x0300 && code <= 0x031f) | ||
176 | code = keycode[code - 0x0300]; | ||
177 | else if (code >= 0x0340 && code <= 0x0354) | ||
178 | code = keycode[code - 0x0320]; | ||
179 | else if (code >= 0x4501 && code <= 0x451f) | ||
180 | code = oldtable[code - 0x4501]; | ||
181 | else if (code >= 0x4540 && code <= 0x4542) | ||
182 | code = oldtable[code - 0x4521]; | ||
183 | else { | ||
184 | printk(KERN_DEBUG "firedtv: invalid key code 0x%04x " | ||
185 | "from remote control\n", code); | ||
186 | return; | ||
187 | } | ||
188 | |||
189 | input_report_key(fdtv->remote_ctrl_dev, code, 1); | ||
190 | input_report_key(fdtv->remote_ctrl_dev, code, 0); | ||
191 | } | ||
diff --git a/drivers/media/dvb/firewire/firedtv-rc.h b/drivers/media/dvb/firewire/firedtv-rc.h new file mode 100644 index 000000000000..d3e14727d3dd --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-rc.h | |||
@@ -0,0 +1,11 @@ | |||
1 | #ifndef _FIREDTV_RC_H | ||
2 | #define _FIREDTV_RC_H | ||
3 | |||
4 | struct firedtv; | ||
5 | struct device; | ||
6 | |||
7 | int fdtv_register_rc(struct firedtv *fdtv, struct device *dev); | ||
8 | void fdtv_unregister_rc(struct firedtv *fdtv); | ||
9 | void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code); | ||
10 | |||
11 | #endif /* _FIREDTV_RC_H */ | ||
diff --git a/drivers/media/dvb/firewire/firedtv.h b/drivers/media/dvb/firewire/firedtv.h new file mode 100644 index 000000000000..2a34028ccbcd --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv.h | |||
@@ -0,0 +1,227 @@ | |||
1 | /* | ||
2 | * FireDTV driver (formerly known as FireSAT) | ||
3 | * | ||
4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
5 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | ||
6 | * | ||
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. | ||
11 | */ | ||
12 | |||
13 | #ifndef _FIREDTV_H | ||
14 | #define _FIREDTV_H | ||
15 | |||
16 | #include <linux/dvb/dmx.h> | ||
17 | #include <linux/dvb/frontend.h> | ||
18 | #include <linux/list.h> | ||
19 | #include <linux/mutex.h> | ||
20 | #include <linux/spinlock_types.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/wait.h> | ||
23 | #include <linux/workqueue.h> | ||
24 | |||
25 | #include <demux.h> | ||
26 | #include <dmxdev.h> | ||
27 | #include <dvb_demux.h> | ||
28 | #include <dvb_frontend.h> | ||
29 | #include <dvb_net.h> | ||
30 | #include <dvbdev.h> | ||
31 | |||
32 | #include <linux/version.h> | ||
33 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25) | ||
34 | #define DVB_REGISTER_ADAPTER(x, y, z, w, v) dvb_register_adapter(x, y, z, w, v) | ||
35 | #else | ||
36 | #define DVB_REGISTER_ADAPTER(x, y, z, w, v) dvb_register_adapter(x, y, z, w) | ||
37 | #define DVB_DEFINE_MOD_OPT_ADAPTER_NR(x) | ||
38 | #endif | ||
39 | |||
40 | /***************************************************************** | ||
41 | * CA message command constants from en50221_app_tags.h of libdvb | ||
42 | *****************************************************************/ | ||
43 | /* Resource Manager */ | ||
44 | #define TAG_PROFILE_ENQUIRY 0x9f8010 | ||
45 | #define TAG_PROFILE 0x9f8011 | ||
46 | #define TAG_PROFILE_CHANGE 0x9f8012 | ||
47 | |||
48 | /* Application Info */ | ||
49 | #define TAG_APP_INFO_ENQUIRY 0x9f8020 | ||
50 | #define TAG_APP_INFO 0x9f8021 | ||
51 | #define TAG_ENTER_MENU 0x9f8022 | ||
52 | |||
53 | /* CA Support */ | ||
54 | #define TAG_CA_INFO_ENQUIRY 0x9f8030 | ||
55 | #define TAG_CA_INFO 0x9f8031 | ||
56 | #define TAG_CA_PMT 0x9f8032 | ||
57 | #define TAG_CA_PMT_REPLY 0x9f8033 | ||
58 | |||
59 | /* Host Control */ | ||
60 | #define TAG_TUNE 0x9f8400 | ||
61 | #define TAG_REPLACE 0x9f8401 | ||
62 | #define TAG_CLEAR_REPLACE 0x9f8402 | ||
63 | #define TAG_ASK_RELEASE 0x9f8403 | ||
64 | |||
65 | /* Date and Time */ | ||
66 | #define TAG_DATE_TIME_ENQUIRY 0x9f8440 | ||
67 | #define TAG_DATE_TIME 0x9f8441 | ||
68 | |||
69 | /* Man Machine Interface (MMI) */ | ||
70 | #define TAG_CLOSE_MMI 0x9f8800 | ||
71 | #define TAG_DISPLAY_CONTROL 0x9f8801 | ||
72 | #define TAG_DISPLAY_REPLY 0x9f8802 | ||
73 | #define TAG_TEXT_LAST 0x9f8803 | ||
74 | #define TAG_TEXT_MORE 0x9f8804 | ||
75 | #define TAG_KEYPAD_CONTROL 0x9f8805 | ||
76 | #define TAG_KEYPRESS 0x9f8806 | ||
77 | #define TAG_ENQUIRY 0x9f8807 | ||
78 | #define TAG_ANSWER 0x9f8808 | ||
79 | #define TAG_MENU_LAST 0x9f8809 | ||
80 | #define TAG_MENU_MORE 0x9f880a | ||
81 | #define TAG_MENU_ANSWER 0x9f880b | ||
82 | #define TAG_LIST_LAST 0x9f880c | ||
83 | #define TAG_LIST_MORE 0x9f880d | ||
84 | #define TAG_SUBTITLE_SEGMENT_LAST 0x9f880e | ||
85 | #define TAG_SUBTITLE_SEGMENT_MORE 0x9f880f | ||
86 | #define TAG_DISPLAY_MESSAGE 0x9f8810 | ||
87 | #define TAG_SCENE_END_MARK 0x9f8811 | ||
88 | #define TAG_SCENE_DONE 0x9f8812 | ||
89 | #define TAG_SCENE_CONTROL 0x9f8813 | ||
90 | #define TAG_SUBTITLE_DOWNLOAD_LAST 0x9f8814 | ||
91 | #define TAG_SUBTITLE_DOWNLOAD_MORE 0x9f8815 | ||
92 | #define TAG_FLUSH_DOWNLOAD 0x9f8816 | ||
93 | #define TAG_DOWNLOAD_REPLY 0x9f8817 | ||
94 | |||
95 | /* Low Speed Communications */ | ||
96 | #define TAG_COMMS_COMMAND 0x9f8c00 | ||
97 | #define TAG_CONNECTION_DESCRIPTOR 0x9f8c01 | ||
98 | #define TAG_COMMS_REPLY 0x9f8c02 | ||
99 | #define TAG_COMMS_SEND_LAST 0x9f8c03 | ||
100 | #define TAG_COMMS_SEND_MORE 0x9f8c04 | ||
101 | #define TAG_COMMS_RECV_LAST 0x9f8c05 | ||
102 | #define TAG_COMMS_RECV_MORE 0x9f8c06 | ||
103 | |||
104 | /* Authentication */ | ||
105 | #define TAG_AUTH_REQ 0x9f8200 | ||
106 | #define TAG_AUTH_RESP 0x9f8201 | ||
107 | |||
108 | /* Teletext */ | ||
109 | #define TAG_TELETEXT_EBU 0x9f9000 | ||
110 | |||
111 | /* Smartcard */ | ||
112 | #define TAG_SMARTCARD_COMMAND 0x9f8e00 | ||
113 | #define TAG_SMARTCARD_REPLY 0x9f8e01 | ||
114 | #define TAG_SMARTCARD_SEND 0x9f8e02 | ||
115 | #define TAG_SMARTCARD_RCV 0x9f8e03 | ||
116 | |||
117 | /* EPG */ | ||
118 | #define TAG_EPG_ENQUIRY 0x9f8f00 | ||
119 | #define TAG_EPG_REPLY 0x9f8f01 | ||
120 | |||
121 | |||
122 | enum model_type { | ||
123 | FIREDTV_UNKNOWN = 0, | ||
124 | FIREDTV_DVB_S = 1, | ||
125 | FIREDTV_DVB_C = 2, | ||
126 | FIREDTV_DVB_T = 3, | ||
127 | FIREDTV_DVB_S2 = 4, | ||
128 | }; | ||
129 | |||
130 | struct input_dev; | ||
131 | struct hpsb_iso; | ||
132 | struct unit_directory; | ||
133 | |||
134 | struct firedtv { | ||
135 | struct dvb_adapter adapter; | ||
136 | struct dmxdev dmxdev; | ||
137 | struct dvb_demux demux; | ||
138 | struct dmx_frontend frontend; | ||
139 | struct dvb_net dvbnet; | ||
140 | struct dvb_frontend fe; | ||
141 | |||
142 | struct dvb_device *cadev; | ||
143 | int ca_last_command; | ||
144 | int ca_time_interval; | ||
145 | |||
146 | struct mutex avc_mutex; | ||
147 | wait_queue_head_t avc_wait; | ||
148 | bool avc_reply_received; | ||
149 | struct work_struct remote_ctrl_work; | ||
150 | struct input_dev *remote_ctrl_dev; | ||
151 | |||
152 | struct firedtv_channel { | ||
153 | bool active; | ||
154 | int pid; | ||
155 | } channel[16]; | ||
156 | struct mutex demux_mutex; | ||
157 | |||
158 | struct unit_directory *ud; | ||
159 | |||
160 | enum model_type type; | ||
161 | char subunit; | ||
162 | fe_sec_voltage_t voltage; | ||
163 | fe_sec_tone_mode_t tone; | ||
164 | |||
165 | int isochannel; | ||
166 | struct hpsb_iso *iso_handle; | ||
167 | |||
168 | struct list_head list; | ||
169 | |||
170 | /* needed by avc_api */ | ||
171 | int resp_length; | ||
172 | u8 respfrm[512]; | ||
173 | }; | ||
174 | |||
175 | struct firewireheader { | ||
176 | union { | ||
177 | struct { | ||
178 | __u8 tcode:4; | ||
179 | __u8 sy:4; | ||
180 | __u8 tag:2; | ||
181 | __u8 channel:6; | ||
182 | |||
183 | __u8 length_l; | ||
184 | __u8 length_h; | ||
185 | } hdr; | ||
186 | __u32 val; | ||
187 | }; | ||
188 | }; | ||
189 | |||
190 | struct CIPHeader { | ||
191 | union { | ||
192 | struct { | ||
193 | __u8 syncbits:2; | ||
194 | __u8 sid:6; | ||
195 | __u8 dbs; | ||
196 | __u8 fn:2; | ||
197 | __u8 qpc:3; | ||
198 | __u8 sph:1; | ||
199 | __u8 rsv:2; | ||
200 | __u8 dbc; | ||
201 | __u8 syncbits2:2; | ||
202 | __u8 fmt:6; | ||
203 | __u32 fdf:24; | ||
204 | } cip; | ||
205 | __u64 val; | ||
206 | }; | ||
207 | }; | ||
208 | |||
209 | extern const char *fdtv_model_names[]; | ||
210 | extern struct list_head fdtv_list; | ||
211 | extern spinlock_t fdtv_list_lock; | ||
212 | |||
213 | struct device; | ||
214 | |||
215 | /* firedtv-dvb.c */ | ||
216 | int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed); | ||
217 | int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed); | ||
218 | int fdtv_dvbdev_init(struct firedtv *fdtv, struct device *dev); | ||
219 | |||
220 | /* firedtv-fe.c */ | ||
221 | void fdtv_frontend_init(struct firedtv *fdtv); | ||
222 | |||
223 | /* firedtv-iso.c */ | ||
224 | int setup_iso_channel(struct firedtv *fdtv); | ||
225 | void tear_down_iso_channel(struct firedtv *fdtv); | ||
226 | |||
227 | #endif /* _FIREDTV_H */ | ||