Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

V4L/DVB (9107): Alternative version of Terratec Cinergy T2 driver

Alternative version of the Terratec Cinergy T2 driver that uses the dvb framework.

Signed-off-by: Tomi Orava <tomimo@ncircle.nullnet.fi>
Signed-off-by: Thierry MERLE <thierry.merle@free.fr>
[mchehab@redhat.com: fix dvb Makefile]
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

authored by

Tomi Orava and committed by
Mauro Carvalho Chehab
986bd1e5 07c6bb9e

+689 -1195
-1
drivers/media/dvb/Kconfig
··· 20 20 source "drivers/media/dvb/dvb-usb/Kconfig" 21 21 source "drivers/media/dvb/ttusb-budget/Kconfig" 22 22 source "drivers/media/dvb/ttusb-dec/Kconfig" 23 - source "drivers/media/dvb/cinergyT2/Kconfig" 24 23 source "drivers/media/dvb/siano/Kconfig" 25 24 26 25 comment "Supported FlexCopII (B2C2) Adapters"
+1 -1
drivers/media/dvb/Makefile
··· 2 2 # Makefile for the kernel multimedia device drivers. 3 3 # 4 4 5 - obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ pluto2/ siano/ dm1105/ 5 + obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/
-85
drivers/media/dvb/cinergyT2/Kconfig
··· 1 - config DVB_CINERGYT2 2 - tristate "Terratec CinergyT2/qanu USB2 DVB-T receiver" 3 - depends on DVB_CORE && USB && INPUT 4 - help 5 - Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers 6 - 7 - Say Y if you own such a device and want to use it. 8 - 9 - 10 - config DVB_CINERGYT2_TUNING 11 - bool "sophisticated fine-tuning for CinergyT2 cards" 12 - depends on DVB_CINERGYT2 13 - help 14 - Here you can fine-tune some parameters of the CinergyT2 driver. 15 - 16 - Normally you don't need to touch this, but in exotic setups you 17 - may fine-tune your setup and adjust e.g. DMA buffer sizes for 18 - a particular application. 19 - 20 - 21 - config DVB_CINERGYT2_STREAM_URB_COUNT 22 - int "Number of queued USB Request Blocks for Highspeed Stream Transfers" 23 - depends on DVB_CINERGYT2_TUNING 24 - default "32" 25 - help 26 - USB Request Blocks for Highspeed Stream transfers are scheduled in 27 - a queue for the Host Controller. 28 - 29 - Usually the default value is a safe choice. 30 - 31 - You may increase this number if you are using this device in a 32 - Server Environment with many high-traffic USB Highspeed devices 33 - sharing the same USB bus. 34 - 35 - 36 - config DVB_CINERGYT2_STREAM_BUF_SIZE 37 - int "Size of URB Stream Buffers for Highspeed Transfers" 38 - depends on DVB_CINERGYT2_TUNING 39 - default "512" 40 - help 41 - Should be a multiple of native buffer size of 512 bytes. 42 - Default value is a safe choice. 43 - 44 - You may increase this number if you are using this device in a 45 - Server Environment with many high-traffic USB Highspeed devices 46 - sharing the same USB bus. 47 - 48 - 49 - config DVB_CINERGYT2_QUERY_INTERVAL 50 - int "Status update interval [milliseconds]" 51 - depends on DVB_CINERGYT2_TUNING 52 - default "250" 53 - help 54 - This is the interval for status readouts from the demodulator. 55 - You may try lower values if you need more responsive signal quality 56 - measurements. 57 - 58 - Please keep in mind that these updates cause traffic on the tuner 59 - control bus and thus may or may not affect reception sensitivity. 60 - 61 - The default value should be a safe choice for common applications. 62 - 63 - 64 - config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE 65 - bool "Register the onboard IR Remote Control Receiver as Input Device" 66 - depends on DVB_CINERGYT2_TUNING 67 - default y 68 - help 69 - Enable this option if you want to use the onboard Infrared Remote 70 - Control Receiver as Linux-Input device. 71 - 72 - Right now only the keycode table for the default Remote Control 73 - delivered with the device is supported, please see the driver 74 - source code to find out how to add support for other controls. 75 - 76 - 77 - config DVB_CINERGYT2_RC_QUERY_INTERVAL 78 - int "Infrared Remote Controller update interval [milliseconds]" 79 - depends on DVB_CINERGYT2_TUNING && DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE 80 - default "50" 81 - help 82 - If you have a very fast-repeating remote control you can try lower 83 - values, for normal consumer receivers the default value should be 84 - a safe choice. 85 -
-3
drivers/media/dvb/cinergyT2/Makefile
··· 1 - obj-$(CONFIG_DVB_CINERGYT2) += cinergyT2.o 2 - 3 - EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
-1105
drivers/media/dvb/cinergyT2/cinergyT2.c
··· 1 - /* 2 - * TerraTec Cinergy T²/qanu USB2 DVB-T adapter. 3 - * 4 - * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and 5 - * Holger Waechtler <holger@qanu.de> 6 - * 7 - * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf 8 - * 9 - * This program is free software; you can redistribute it and/or modify 10 - * it under the terms of the GNU General Public License as published by 11 - * the Free Software Foundation; either version 2 of the License, or 12 - * (at your option) any later version. 13 - * 14 - * This program is distributed in the hope that it will be useful, 15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 - * GNU General Public License for more details. 18 - * 19 - * You should have received a copy of the GNU General Public License 20 - * along with this program; if not, write to the Free Software 21 - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 - * 23 - */ 24 - 25 - #include <linux/init.h> 26 - #include <linux/module.h> 27 - #include <linux/slab.h> 28 - #include <linux/usb.h> 29 - #include <linux/input.h> 30 - #include <linux/dvb/frontend.h> 31 - #include <linux/mutex.h> 32 - #include <linux/mm.h> 33 - #include <asm/io.h> 34 - 35 - #include "dmxdev.h" 36 - #include "dvb_demux.h" 37 - #include "dvb_net.h" 38 - 39 - #ifdef CONFIG_DVB_CINERGYT2_TUNING 40 - #define STREAM_URB_COUNT (CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT) 41 - #define STREAM_BUF_SIZE (CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE) 42 - #define QUERY_INTERVAL (CONFIG_DVB_CINERGYT2_QUERY_INTERVAL) 43 - #ifdef CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE 44 - #define RC_QUERY_INTERVAL (CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL) 45 - #define ENABLE_RC (1) 46 - #endif 47 - #else 48 - #define STREAM_URB_COUNT (32) 49 - #define STREAM_BUF_SIZE (512) /* bytes */ 50 - #define ENABLE_RC (1) 51 - #define RC_QUERY_INTERVAL (50) /* milliseconds */ 52 - #define QUERY_INTERVAL (333) /* milliseconds */ 53 - #endif 54 - 55 - #define DRIVER_NAME "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver" 56 - 57 - static int debug; 58 - module_param_named(debug, debug, int, 0644); 59 - MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); 60 - 61 - DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 62 - 63 - #define dprintk(level, args...) \ 64 - do { \ 65 - if ((debug & level)) { \ 66 - printk("%s: %s(): ", KBUILD_MODNAME, \ 67 - __func__); \ 68 - printk(args); } \ 69 - } while (0) 70 - 71 - enum cinergyt2_ep1_cmd { 72 - CINERGYT2_EP1_PID_TABLE_RESET = 0x01, 73 - CINERGYT2_EP1_PID_SETUP = 0x02, 74 - CINERGYT2_EP1_CONTROL_STREAM_TRANSFER = 0x03, 75 - CINERGYT2_EP1_SET_TUNER_PARAMETERS = 0x04, 76 - CINERGYT2_EP1_GET_TUNER_STATUS = 0x05, 77 - CINERGYT2_EP1_START_SCAN = 0x06, 78 - CINERGYT2_EP1_CONTINUE_SCAN = 0x07, 79 - CINERGYT2_EP1_GET_RC_EVENTS = 0x08, 80 - CINERGYT2_EP1_SLEEP_MODE = 0x09 81 - }; 82 - 83 - struct dvbt_set_parameters_msg { 84 - uint8_t cmd; 85 - __le32 freq; 86 - uint8_t bandwidth; 87 - __le16 tps; 88 - uint8_t flags; 89 - } __attribute__((packed)); 90 - 91 - struct dvbt_get_status_msg { 92 - __le32 freq; 93 - uint8_t bandwidth; 94 - __le16 tps; 95 - uint8_t flags; 96 - __le16 gain; 97 - uint8_t snr; 98 - __le32 viterbi_error_rate; 99 - __le32 rs_error_rate; 100 - __le32 uncorrected_block_count; 101 - uint8_t lock_bits; 102 - uint8_t prev_lock_bits; 103 - } __attribute__((packed)); 104 - 105 - static struct dvb_frontend_info cinergyt2_fe_info = { 106 - .name = DRIVER_NAME, 107 - .type = FE_OFDM, 108 - .frequency_min = 174000000, 109 - .frequency_max = 862000000, 110 - .frequency_stepsize = 166667, 111 - .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | 112 - FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | 113 - FE_CAN_FEC_AUTO | 114 - FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | 115 - FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | 116 - FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS 117 - }; 118 - 119 - struct cinergyt2 { 120 - struct dvb_demux demux; 121 - struct usb_device *udev; 122 - struct mutex sem; 123 - struct mutex wq_sem; 124 - struct dvb_adapter adapter; 125 - struct dvb_device *fedev; 126 - struct dmxdev dmxdev; 127 - struct dvb_net dvbnet; 128 - 129 - int streaming; 130 - int sleeping; 131 - 132 - struct dvbt_set_parameters_msg param; 133 - struct dvbt_get_status_msg status; 134 - struct delayed_work query_work; 135 - 136 - wait_queue_head_t poll_wq; 137 - int pending_fe_events; 138 - int disconnect_pending; 139 - unsigned int uncorrected_block_count; 140 - atomic_t inuse; 141 - 142 - void *streambuf; 143 - dma_addr_t streambuf_dmahandle; 144 - struct urb *stream_urb [STREAM_URB_COUNT]; 145 - 146 - #ifdef ENABLE_RC 147 - struct input_dev *rc_input_dev; 148 - char phys[64]; 149 - struct delayed_work rc_query_work; 150 - int rc_input_event; 151 - __le32 rc_last_code; 152 - unsigned long last_event_jiffies; 153 - #endif 154 - }; 155 - 156 - enum { 157 - CINERGYT2_RC_EVENT_TYPE_NONE = 0x00, 158 - CINERGYT2_RC_EVENT_TYPE_NEC = 0x01, 159 - CINERGYT2_RC_EVENT_TYPE_RC5 = 0x02 160 - }; 161 - 162 - struct cinergyt2_rc_event { 163 - char type; 164 - __le32 value; 165 - } __attribute__((packed)); 166 - 167 - static const uint32_t rc_keys[] = { 168 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xfe01eb04, KEY_POWER, 169 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xfd02eb04, KEY_1, 170 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xfc03eb04, KEY_2, 171 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xfb04eb04, KEY_3, 172 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xfa05eb04, KEY_4, 173 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xf906eb04, KEY_5, 174 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xf807eb04, KEY_6, 175 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xf708eb04, KEY_7, 176 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xf609eb04, KEY_8, 177 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xf50aeb04, KEY_9, 178 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xf30ceb04, KEY_0, 179 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xf40beb04, KEY_VIDEO, 180 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xf20deb04, KEY_REFRESH, 181 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xf10eeb04, KEY_SELECT, 182 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xf00feb04, KEY_EPG, 183 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xef10eb04, KEY_UP, 184 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xeb14eb04, KEY_DOWN, 185 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xee11eb04, KEY_LEFT, 186 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xec13eb04, KEY_RIGHT, 187 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xed12eb04, KEY_OK, 188 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xea15eb04, KEY_TEXT, 189 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xe916eb04, KEY_INFO, 190 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xe817eb04, KEY_RED, 191 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xe718eb04, KEY_GREEN, 192 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xe619eb04, KEY_YELLOW, 193 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xe51aeb04, KEY_BLUE, 194 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xe31ceb04, KEY_VOLUMEUP, 195 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xe11eeb04, KEY_VOLUMEDOWN, 196 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xe21deb04, KEY_MUTE, 197 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xe41beb04, KEY_CHANNELUP, 198 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xe01feb04, KEY_CHANNELDOWN, 199 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xbf40eb04, KEY_PAUSE, 200 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xb34ceb04, KEY_PLAY, 201 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xa758eb04, KEY_RECORD, 202 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xab54eb04, KEY_PREVIOUS, 203 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xb748eb04, KEY_STOP, 204 - CINERGYT2_RC_EVENT_TYPE_NEC, 0xa35ceb04, KEY_NEXT 205 - }; 206 - 207 - static int cinergyt2_command (struct cinergyt2 *cinergyt2, 208 - char *send_buf, int send_buf_len, 209 - char *recv_buf, int recv_buf_len) 210 - { 211 - int actual_len; 212 - char dummy; 213 - int ret; 214 - 215 - ret = usb_bulk_msg(cinergyt2->udev, usb_sndbulkpipe(cinergyt2->udev, 1), 216 - send_buf, send_buf_len, &actual_len, 1000); 217 - 218 - if (ret) 219 - dprintk(1, "usb_bulk_msg (send) failed, err %i\n", ret); 220 - 221 - if (!recv_buf) 222 - recv_buf = &dummy; 223 - 224 - ret = usb_bulk_msg(cinergyt2->udev, usb_rcvbulkpipe(cinergyt2->udev, 1), 225 - recv_buf, recv_buf_len, &actual_len, 1000); 226 - 227 - if (ret) 228 - dprintk(1, "usb_bulk_msg (read) failed, err %i\n", ret); 229 - 230 - return ret ? ret : actual_len; 231 - } 232 - 233 - static void cinergyt2_control_stream_transfer (struct cinergyt2 *cinergyt2, int enable) 234 - { 235 - char buf [] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 }; 236 - cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0); 237 - } 238 - 239 - static void cinergyt2_sleep (struct cinergyt2 *cinergyt2, int sleep) 240 - { 241 - char buf [] = { CINERGYT2_EP1_SLEEP_MODE, sleep ? 1 : 0 }; 242 - cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0); 243 - cinergyt2->sleeping = sleep; 244 - } 245 - 246 - static void cinergyt2_stream_irq (struct urb *urb); 247 - 248 - static int cinergyt2_submit_stream_urb (struct cinergyt2 *cinergyt2, struct urb *urb) 249 - { 250 - int err; 251 - 252 - usb_fill_bulk_urb(urb, 253 - cinergyt2->udev, 254 - usb_rcvbulkpipe(cinergyt2->udev, 0x2), 255 - urb->transfer_buffer, 256 - STREAM_BUF_SIZE, 257 - cinergyt2_stream_irq, 258 - cinergyt2); 259 - 260 - if ((err = usb_submit_urb(urb, GFP_ATOMIC))) 261 - dprintk(1, "urb submission failed (err = %i)!\n", err); 262 - 263 - return err; 264 - } 265 - 266 - static void cinergyt2_stream_irq (struct urb *urb) 267 - { 268 - struct cinergyt2 *cinergyt2 = urb->context; 269 - 270 - if (urb->actual_length > 0) 271 - dvb_dmx_swfilter(&cinergyt2->demux, 272 - urb->transfer_buffer, urb->actual_length); 273 - 274 - if (cinergyt2->streaming) 275 - cinergyt2_submit_stream_urb(cinergyt2, urb); 276 - } 277 - 278 - static void cinergyt2_free_stream_urbs (struct cinergyt2 *cinergyt2) 279 - { 280 - int i; 281 - 282 - for (i=0; i<STREAM_URB_COUNT; i++) 283 - usb_free_urb(cinergyt2->stream_urb[i]); 284 - 285 - usb_buffer_free(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE, 286 - cinergyt2->streambuf, cinergyt2->streambuf_dmahandle); 287 - } 288 - 289 - static int cinergyt2_alloc_stream_urbs (struct cinergyt2 *cinergyt2) 290 - { 291 - int i; 292 - 293 - cinergyt2->streambuf = usb_buffer_alloc(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE, 294 - GFP_KERNEL, &cinergyt2->streambuf_dmahandle); 295 - if (!cinergyt2->streambuf) { 296 - dprintk(1, "failed to alloc consistent stream memory area, bailing out!\n"); 297 - return -ENOMEM; 298 - } 299 - 300 - memset(cinergyt2->streambuf, 0, STREAM_URB_COUNT*STREAM_BUF_SIZE); 301 - 302 - for (i=0; i<STREAM_URB_COUNT; i++) { 303 - struct urb *urb; 304 - 305 - if (!(urb = usb_alloc_urb(0, GFP_ATOMIC))) { 306 - dprintk(1, "failed to alloc consistent stream urbs, bailing out!\n"); 307 - cinergyt2_free_stream_urbs(cinergyt2); 308 - return -ENOMEM; 309 - } 310 - 311 - urb->transfer_buffer = cinergyt2->streambuf + i * STREAM_BUF_SIZE; 312 - urb->transfer_buffer_length = STREAM_BUF_SIZE; 313 - 314 - cinergyt2->stream_urb[i] = urb; 315 - } 316 - 317 - return 0; 318 - } 319 - 320 - static void cinergyt2_stop_stream_xfer (struct cinergyt2 *cinergyt2) 321 - { 322 - int i; 323 - 324 - cinergyt2_control_stream_transfer(cinergyt2, 0); 325 - 326 - for (i=0; i<STREAM_URB_COUNT; i++) 327 - usb_kill_urb(cinergyt2->stream_urb[i]); 328 - } 329 - 330 - static int cinergyt2_start_stream_xfer (struct cinergyt2 *cinergyt2) 331 - { 332 - int i, err; 333 - 334 - for (i=0; i<STREAM_URB_COUNT; i++) { 335 - if ((err = cinergyt2_submit_stream_urb(cinergyt2, cinergyt2->stream_urb[i]))) { 336 - cinergyt2_stop_stream_xfer(cinergyt2); 337 - dprintk(1, "failed urb submission (%i: err = %i)!\n", i, err); 338 - return err; 339 - } 340 - } 341 - 342 - cinergyt2_control_stream_transfer(cinergyt2, 1); 343 - return 0; 344 - } 345 - 346 - static int cinergyt2_start_feed(struct dvb_demux_feed *dvbdmxfeed) 347 - { 348 - struct dvb_demux *demux = dvbdmxfeed->demux; 349 - struct cinergyt2 *cinergyt2 = demux->priv; 350 - 351 - if (cinergyt2->disconnect_pending) 352 - return -EAGAIN; 353 - if (mutex_lock_interruptible(&cinergyt2->sem)) 354 - return -ERESTARTSYS; 355 - 356 - if (cinergyt2->streaming == 0) 357 - cinergyt2_start_stream_xfer(cinergyt2); 358 - 359 - cinergyt2->streaming++; 360 - mutex_unlock(&cinergyt2->sem); 361 - return 0; 362 - } 363 - 364 - static int cinergyt2_stop_feed(struct dvb_demux_feed *dvbdmxfeed) 365 - { 366 - struct dvb_demux *demux = dvbdmxfeed->demux; 367 - struct cinergyt2 *cinergyt2 = demux->priv; 368 - 369 - if (cinergyt2->disconnect_pending) 370 - return -EAGAIN; 371 - if (mutex_lock_interruptible(&cinergyt2->sem)) 372 - return -ERESTARTSYS; 373 - 374 - if (--cinergyt2->streaming == 0) 375 - cinergyt2_stop_stream_xfer(cinergyt2); 376 - 377 - mutex_unlock(&cinergyt2->sem); 378 - return 0; 379 - } 380 - 381 - /** 382 - * convert linux-dvb frontend parameter set into TPS. 383 - * See ETSI ETS-300744, section 4.6.2, table 9 for details. 384 - * 385 - * This function is probably reusable and may better get placed in a support 386 - * library. 387 - * 388 - * We replace errornous fields by default TPS fields (the ones with value 0). 389 - */ 390 - static uint16_t compute_tps (struct dvb_frontend_parameters *p) 391 - { 392 - struct dvb_ofdm_parameters *op = &p->u.ofdm; 393 - uint16_t tps = 0; 394 - 395 - switch (op->code_rate_HP) { 396 - case FEC_2_3: 397 - tps |= (1 << 7); 398 - break; 399 - case FEC_3_4: 400 - tps |= (2 << 7); 401 - break; 402 - case FEC_5_6: 403 - tps |= (3 << 7); 404 - break; 405 - case FEC_7_8: 406 - tps |= (4 << 7); 407 - break; 408 - case FEC_1_2: 409 - case FEC_AUTO: 410 - default: 411 - /* tps |= (0 << 7) */; 412 - } 413 - 414 - switch (op->code_rate_LP) { 415 - case FEC_2_3: 416 - tps |= (1 << 4); 417 - break; 418 - case FEC_3_4: 419 - tps |= (2 << 4); 420 - break; 421 - case FEC_5_6: 422 - tps |= (3 << 4); 423 - break; 424 - case FEC_7_8: 425 - tps |= (4 << 4); 426 - break; 427 - case FEC_1_2: 428 - case FEC_AUTO: 429 - default: 430 - /* tps |= (0 << 4) */; 431 - } 432 - 433 - switch (op->constellation) { 434 - case QAM_16: 435 - tps |= (1 << 13); 436 - break; 437 - case QAM_64: 438 - tps |= (2 << 13); 439 - break; 440 - case QPSK: 441 - default: 442 - /* tps |= (0 << 13) */; 443 - } 444 - 445 - switch (op->transmission_mode) { 446 - case TRANSMISSION_MODE_8K: 447 - tps |= (1 << 0); 448 - break; 449 - case TRANSMISSION_MODE_2K: 450 - default: 451 - /* tps |= (0 << 0) */; 452 - } 453 - 454 - switch (op->guard_interval) { 455 - case GUARD_INTERVAL_1_16: 456 - tps |= (1 << 2); 457 - break; 458 - case GUARD_INTERVAL_1_8: 459 - tps |= (2 << 2); 460 - break; 461 - case GUARD_INTERVAL_1_4: 462 - tps |= (3 << 2); 463 - break; 464 - case GUARD_INTERVAL_1_32: 465 - default: 466 - /* tps |= (0 << 2) */; 467 - } 468 - 469 - switch (op->hierarchy_information) { 470 - case HIERARCHY_1: 471 - tps |= (1 << 10); 472 - break; 473 - case HIERARCHY_2: 474 - tps |= (2 << 10); 475 - break; 476 - case HIERARCHY_4: 477 - tps |= (3 << 10); 478 - break; 479 - case HIERARCHY_NONE: 480 - default: 481 - /* tps |= (0 << 10) */; 482 - } 483 - 484 - return tps; 485 - } 486 - 487 - static int cinergyt2_open (struct inode *inode, struct file *file) 488 - { 489 - struct dvb_device *dvbdev = file->private_data; 490 - struct cinergyt2 *cinergyt2 = dvbdev->priv; 491 - int err = -EAGAIN; 492 - 493 - if (cinergyt2->disconnect_pending) 494 - goto out; 495 - err = mutex_lock_interruptible(&cinergyt2->wq_sem); 496 - if (err) 497 - goto out; 498 - 499 - err = mutex_lock_interruptible(&cinergyt2->sem); 500 - if (err) 501 - goto out_unlock1; 502 - 503 - if ((err = dvb_generic_open(inode, file))) 504 - goto out_unlock2; 505 - 506 - if ((file->f_flags & O_ACCMODE) != O_RDONLY) { 507 - cinergyt2_sleep(cinergyt2, 0); 508 - schedule_delayed_work(&cinergyt2->query_work, HZ/2); 509 - } 510 - 511 - atomic_inc(&cinergyt2->inuse); 512 - 513 - out_unlock2: 514 - mutex_unlock(&cinergyt2->sem); 515 - out_unlock1: 516 - mutex_unlock(&cinergyt2->wq_sem); 517 - out: 518 - return err; 519 - } 520 - 521 - static void cinergyt2_unregister(struct cinergyt2 *cinergyt2) 522 - { 523 - dvb_net_release(&cinergyt2->dvbnet); 524 - dvb_dmxdev_release(&cinergyt2->dmxdev); 525 - dvb_dmx_release(&cinergyt2->demux); 526 - dvb_unregister_device(cinergyt2->fedev); 527 - dvb_unregister_adapter(&cinergyt2->adapter); 528 - 529 - cinergyt2_free_stream_urbs(cinergyt2); 530 - kfree(cinergyt2); 531 - } 532 - 533 - static int cinergyt2_release (struct inode *inode, struct file *file) 534 - { 535 - struct dvb_device *dvbdev = file->private_data; 536 - struct cinergyt2 *cinergyt2 = dvbdev->priv; 537 - 538 - mutex_lock(&cinergyt2->wq_sem); 539 - 540 - if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) { 541 - cancel_rearming_delayed_work(&cinergyt2->query_work); 542 - 543 - mutex_lock(&cinergyt2->sem); 544 - cinergyt2_sleep(cinergyt2, 1); 545 - mutex_unlock(&cinergyt2->sem); 546 - } 547 - 548 - mutex_unlock(&cinergyt2->wq_sem); 549 - 550 - if (atomic_dec_and_test(&cinergyt2->inuse) && cinergyt2->disconnect_pending) { 551 - warn("delayed unregister in release"); 552 - cinergyt2_unregister(cinergyt2); 553 - } 554 - 555 - return dvb_generic_release(inode, file); 556 - } 557 - 558 - static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct *wait) 559 - { 560 - struct dvb_device *dvbdev = file->private_data; 561 - struct cinergyt2 *cinergyt2 = dvbdev->priv; 562 - unsigned int mask = 0; 563 - 564 - if (cinergyt2->disconnect_pending) 565 - return -EAGAIN; 566 - if (mutex_lock_interruptible(&cinergyt2->sem)) 567 - return -ERESTARTSYS; 568 - 569 - poll_wait(file, &cinergyt2->poll_wq, wait); 570 - 571 - if (cinergyt2->pending_fe_events != 0) 572 - mask |= (POLLIN | POLLRDNORM | POLLPRI); 573 - 574 - mutex_unlock(&cinergyt2->sem); 575 - 576 - return mask; 577 - } 578 - 579 - 580 - static int cinergyt2_ioctl (struct inode *inode, struct file *file, 581 - unsigned cmd, unsigned long arg) 582 - { 583 - struct dvb_device *dvbdev = file->private_data; 584 - struct cinergyt2 *cinergyt2 = dvbdev->priv; 585 - struct dvbt_get_status_msg *stat = &cinergyt2->status; 586 - fe_status_t status = 0; 587 - 588 - switch (cmd) { 589 - case FE_GET_INFO: 590 - return copy_to_user((void __user*) arg, &cinergyt2_fe_info, 591 - sizeof(struct dvb_frontend_info)); 592 - 593 - case FE_READ_STATUS: 594 - if (0xffff - le16_to_cpu(stat->gain) > 30) 595 - status |= FE_HAS_SIGNAL; 596 - if (stat->lock_bits & (1 << 6)) 597 - status |= FE_HAS_LOCK; 598 - if (stat->lock_bits & (1 << 5)) 599 - status |= FE_HAS_SYNC; 600 - if (stat->lock_bits & (1 << 4)) 601 - status |= FE_HAS_CARRIER; 602 - if (stat->lock_bits & (1 << 1)) 603 - status |= FE_HAS_VITERBI; 604 - 605 - return copy_to_user((void __user*) arg, &status, sizeof(status)); 606 - 607 - case FE_READ_BER: 608 - return put_user(le32_to_cpu(stat->viterbi_error_rate), 609 - (__u32 __user *) arg); 610 - 611 - case FE_READ_SIGNAL_STRENGTH: 612 - return put_user(0xffff - le16_to_cpu(stat->gain), 613 - (__u16 __user *) arg); 614 - 615 - case FE_READ_SNR: 616 - return put_user((stat->snr << 8) | stat->snr, 617 - (__u16 __user *) arg); 618 - 619 - case FE_READ_UNCORRECTED_BLOCKS: 620 - { 621 - uint32_t unc_count; 622 - 623 - if (mutex_lock_interruptible(&cinergyt2->sem)) 624 - return -ERESTARTSYS; 625 - unc_count = cinergyt2->uncorrected_block_count; 626 - cinergyt2->uncorrected_block_count = 0; 627 - mutex_unlock(&cinergyt2->sem); 628 - 629 - /* UNC are already converted to host byte order... */ 630 - return put_user(unc_count,(__u32 __user *) arg); 631 - } 632 - case FE_SET_FRONTEND: 633 - { 634 - struct dvbt_set_parameters_msg *param = &cinergyt2->param; 635 - struct dvb_frontend_parameters p; 636 - int err; 637 - 638 - if ((file->f_flags & O_ACCMODE) == O_RDONLY) 639 - return -EPERM; 640 - 641 - if (copy_from_user(&p, (void __user*) arg, sizeof(p))) 642 - return -EFAULT; 643 - 644 - if (cinergyt2->disconnect_pending) 645 - return -EAGAIN; 646 - if (mutex_lock_interruptible(&cinergyt2->sem)) 647 - return -ERESTARTSYS; 648 - 649 - param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; 650 - param->tps = cpu_to_le16(compute_tps(&p)); 651 - param->freq = cpu_to_le32(p.frequency / 1000); 652 - param->bandwidth = 8 - p.u.ofdm.bandwidth - BANDWIDTH_8_MHZ; 653 - 654 - stat->lock_bits = 0; 655 - cinergyt2->pending_fe_events++; 656 - wake_up_interruptible(&cinergyt2->poll_wq); 657 - 658 - err = cinergyt2_command(cinergyt2, 659 - (char *) param, sizeof(*param), 660 - NULL, 0); 661 - 662 - mutex_unlock(&cinergyt2->sem); 663 - 664 - return (err < 0) ? err : 0; 665 - } 666 - 667 - case FE_GET_FRONTEND: 668 - /** 669 - * trivial to implement (see struct dvbt_get_status_msg). 670 - * equivalent to FE_READ ioctls, but needs 671 - * TPS -> linux-dvb parameter set conversion. Feel free 672 - * to implement this and send us a patch if you need this 673 - * functionality. 674 - */ 675 - break; 676 - 677 - case FE_GET_EVENT: 678 - { 679 - /** 680 - * for now we only fill the status field. the parameters 681 - * are trivial to fill as soon FE_GET_FRONTEND is done. 682 - */ 683 - struct dvb_frontend_event __user *e = (void __user *) arg; 684 - if (cinergyt2->pending_fe_events == 0) { 685 - if (file->f_flags & O_NONBLOCK) 686 - return -EWOULDBLOCK; 687 - wait_event_interruptible(cinergyt2->poll_wq, 688 - cinergyt2->pending_fe_events > 0); 689 - } 690 - cinergyt2->pending_fe_events = 0; 691 - return cinergyt2_ioctl(inode, file, FE_READ_STATUS, 692 - (unsigned long) &e->status); 693 - } 694 - 695 - default: 696 - ; 697 - } 698 - 699 - return -EINVAL; 700 - } 701 - 702 - static int cinergyt2_mmap(struct file *file, struct vm_area_struct *vma) 703 - { 704 - struct dvb_device *dvbdev = file->private_data; 705 - struct cinergyt2 *cinergyt2 = dvbdev->priv; 706 - int ret = 0; 707 - 708 - lock_kernel(); 709 - 710 - if (vma->vm_flags & (VM_WRITE | VM_EXEC)) { 711 - ret = -EPERM; 712 - goto bailout; 713 - } 714 - 715 - if (vma->vm_end > vma->vm_start + STREAM_URB_COUNT * STREAM_BUF_SIZE) { 716 - ret = -EINVAL; 717 - goto bailout; 718 - } 719 - 720 - vma->vm_flags |= (VM_IO | VM_DONTCOPY); 721 - vma->vm_file = file; 722 - 723 - ret = remap_pfn_range(vma, vma->vm_start, 724 - virt_to_phys(cinergyt2->streambuf) >> PAGE_SHIFT, 725 - vma->vm_end - vma->vm_start, 726 - vma->vm_page_prot) ? -EAGAIN : 0; 727 - bailout: 728 - unlock_kernel(); 729 - return ret; 730 - } 731 - 732 - static struct file_operations cinergyt2_fops = { 733 - .owner = THIS_MODULE, 734 - .ioctl = cinergyt2_ioctl, 735 - .poll = cinergyt2_poll, 736 - .open = cinergyt2_open, 737 - .release = cinergyt2_release, 738 - .mmap = cinergyt2_mmap 739 - }; 740 - 741 - static struct dvb_device cinergyt2_fe_template = { 742 - .users = ~0, 743 - .writers = 1, 744 - .readers = (~0)-1, 745 - .fops = &cinergyt2_fops 746 - }; 747 - 748 - #ifdef ENABLE_RC 749 - 750 - static void cinergyt2_query_rc (struct work_struct *work) 751 - { 752 - struct cinergyt2 *cinergyt2 = 753 - container_of(work, struct cinergyt2, rc_query_work.work); 754 - char buf[1] = { CINERGYT2_EP1_GET_RC_EVENTS }; 755 - struct cinergyt2_rc_event rc_events[12]; 756 - int n, len, i; 757 - 758 - if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) 759 - return; 760 - 761 - len = cinergyt2_command(cinergyt2, buf, sizeof(buf), 762 - (char *) rc_events, sizeof(rc_events)); 763 - if (len < 0) 764 - goto out; 765 - if (len == 0) { 766 - if (time_after(jiffies, cinergyt2->last_event_jiffies + 767 - msecs_to_jiffies(150))) { 768 - /* stop key repeat */ 769 - if (cinergyt2->rc_input_event != KEY_MAX) { 770 - dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event); 771 - input_report_key(cinergyt2->rc_input_dev, 772 - cinergyt2->rc_input_event, 0); 773 - input_sync(cinergyt2->rc_input_dev); 774 - cinergyt2->rc_input_event = KEY_MAX; 775 - } 776 - cinergyt2->rc_last_code = cpu_to_le32(~0); 777 - } 778 - goto out; 779 - } 780 - cinergyt2->last_event_jiffies = jiffies; 781 - 782 - for (n = 0; n < (len / sizeof(rc_events[0])); n++) { 783 - dprintk(1, "rc_events[%d].value = %x, type=%x\n", 784 - n, le32_to_cpu(rc_events[n].value), rc_events[n].type); 785 - 786 - if (rc_events[n].type == CINERGYT2_RC_EVENT_TYPE_NEC && 787 - rc_events[n].value == cpu_to_le32(~0)) { 788 - /* keyrepeat bit -> just repeat last rc_input_event */ 789 - } else { 790 - cinergyt2->rc_input_event = KEY_MAX; 791 - for (i = 0; i < ARRAY_SIZE(rc_keys); i += 3) { 792 - if (rc_keys[i + 0] == rc_events[n].type && 793 - rc_keys[i + 1] == le32_to_cpu(rc_events[n].value)) { 794 - cinergyt2->rc_input_event = rc_keys[i + 2]; 795 - break; 796 - } 797 - } 798 - } 799 - 800 - if (cinergyt2->rc_input_event != KEY_MAX) { 801 - if (rc_events[n].value == cinergyt2->rc_last_code && 802 - cinergyt2->rc_last_code != cpu_to_le32(~0)) { 803 - /* emit a key-up so the double event is recognized */ 804 - dprintk(1, "rc_input_event=%d UP\n", cinergyt2->rc_input_event); 805 - input_report_key(cinergyt2->rc_input_dev, 806 - cinergyt2->rc_input_event, 0); 807 - } 808 - dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event); 809 - input_report_key(cinergyt2->rc_input_dev, 810 - cinergyt2->rc_input_event, 1); 811 - input_sync(cinergyt2->rc_input_dev); 812 - cinergyt2->rc_last_code = rc_events[n].value; 813 - } 814 - } 815 - 816 - out: 817 - schedule_delayed_work(&cinergyt2->rc_query_work, 818 - msecs_to_jiffies(RC_QUERY_INTERVAL)); 819 - 820 - mutex_unlock(&cinergyt2->sem); 821 - } 822 - 823 - static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) 824 - { 825 - struct input_dev *input_dev; 826 - int i; 827 - int err; 828 - 829 - input_dev = input_allocate_device(); 830 - if (!input_dev) 831 - return -ENOMEM; 832 - 833 - usb_make_path(cinergyt2->udev, cinergyt2->phys, sizeof(cinergyt2->phys)); 834 - strlcat(cinergyt2->phys, "/input0", sizeof(cinergyt2->phys)); 835 - cinergyt2->rc_input_event = KEY_MAX; 836 - cinergyt2->rc_last_code = cpu_to_le32(~0); 837 - INIT_DELAYED_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc); 838 - 839 - input_dev->name = DRIVER_NAME " remote control"; 840 - input_dev->phys = cinergyt2->phys; 841 - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); 842 - for (i = 0; i < ARRAY_SIZE(rc_keys); i += 3) 843 - set_bit(rc_keys[i + 2], input_dev->keybit); 844 - input_dev->keycodesize = 0; 845 - input_dev->keycodemax = 0; 846 - input_dev->id.bustype = BUS_USB; 847 - input_dev->id.vendor = le16_to_cpu(cinergyt2->udev->descriptor.idVendor); 848 - input_dev->id.product = le16_to_cpu(cinergyt2->udev->descriptor.idProduct); 849 - input_dev->id.version = 1; 850 - input_dev->dev.parent = &cinergyt2->udev->dev; 851 - 852 - err = input_register_device(input_dev); 853 - if (err) { 854 - input_free_device(input_dev); 855 - return err; 856 - } 857 - 858 - cinergyt2->rc_input_dev = input_dev; 859 - schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); 860 - 861 - return 0; 862 - } 863 - 864 - static void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2) 865 - { 866 - cancel_rearming_delayed_work(&cinergyt2->rc_query_work); 867 - input_unregister_device(cinergyt2->rc_input_dev); 868 - } 869 - 870 - static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2) 871 - { 872 - cancel_rearming_delayed_work(&cinergyt2->rc_query_work); 873 - } 874 - 875 - static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2) 876 - { 877 - schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); 878 - } 879 - 880 - #else 881 - 882 - static inline int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) { return 0; } 883 - static inline void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2) { } 884 - static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2) { } 885 - static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2) { } 886 - 887 - #endif /* ENABLE_RC */ 888 - 889 - static void cinergyt2_query (struct work_struct *work) 890 - { 891 - struct cinergyt2 *cinergyt2 = 892 - container_of(work, struct cinergyt2, query_work.work); 893 - char cmd [] = { CINERGYT2_EP1_GET_TUNER_STATUS }; 894 - struct dvbt_get_status_msg *s = &cinergyt2->status; 895 - uint8_t lock_bits; 896 - 897 - if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) 898 - return; 899 - 900 - lock_bits = s->lock_bits; 901 - 902 - cinergyt2_command(cinergyt2, cmd, sizeof(cmd), (char *) s, sizeof(*s)); 903 - 904 - cinergyt2->uncorrected_block_count += 905 - le32_to_cpu(s->uncorrected_block_count); 906 - 907 - if (lock_bits != s->lock_bits) { 908 - wake_up_interruptible(&cinergyt2->poll_wq); 909 - cinergyt2->pending_fe_events++; 910 - } 911 - 912 - schedule_delayed_work(&cinergyt2->query_work, 913 - msecs_to_jiffies(QUERY_INTERVAL)); 914 - 915 - mutex_unlock(&cinergyt2->sem); 916 - } 917 - 918 - static int cinergyt2_probe (struct usb_interface *intf, 919 - const struct usb_device_id *id) 920 - { 921 - struct cinergyt2 *cinergyt2; 922 - int err; 923 - 924 - if (!(cinergyt2 = kzalloc (sizeof(struct cinergyt2), GFP_KERNEL))) { 925 - dprintk(1, "out of memory?!?\n"); 926 - return -ENOMEM; 927 - } 928 - 929 - usb_set_intfdata (intf, (void *) cinergyt2); 930 - 931 - mutex_init(&cinergyt2->sem); 932 - mutex_init(&cinergyt2->wq_sem); 933 - init_waitqueue_head (&cinergyt2->poll_wq); 934 - INIT_DELAYED_WORK(&cinergyt2->query_work, cinergyt2_query); 935 - 936 - cinergyt2->udev = interface_to_usbdev(intf); 937 - cinergyt2->param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; 938 - 939 - if (cinergyt2_alloc_stream_urbs (cinergyt2) < 0) { 940 - dprintk(1, "unable to allocate stream urbs\n"); 941 - kfree(cinergyt2); 942 - return -ENOMEM; 943 - } 944 - 945 - err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, 946 - THIS_MODULE, &cinergyt2->udev->dev, 947 - adapter_nr); 948 - if (err < 0) { 949 - kfree(cinergyt2); 950 - return err; 951 - } 952 - 953 - cinergyt2->demux.priv = cinergyt2; 954 - cinergyt2->demux.filternum = 256; 955 - cinergyt2->demux.feednum = 256; 956 - cinergyt2->demux.start_feed = cinergyt2_start_feed; 957 - cinergyt2->demux.stop_feed = cinergyt2_stop_feed; 958 - cinergyt2->demux.dmx.capabilities = DMX_TS_FILTERING | 959 - DMX_SECTION_FILTERING | 960 - DMX_MEMORY_BASED_FILTERING; 961 - 962 - if ((err = dvb_dmx_init(&cinergyt2->demux)) < 0) { 963 - dprintk(1, "dvb_dmx_init() failed (err = %d)\n", err); 964 - goto bailout; 965 - } 966 - 967 - cinergyt2->dmxdev.filternum = cinergyt2->demux.filternum; 968 - cinergyt2->dmxdev.demux = &cinergyt2->demux.dmx; 969 - cinergyt2->dmxdev.capabilities = 0; 970 - 971 - if ((err = dvb_dmxdev_init(&cinergyt2->dmxdev, &cinergyt2->adapter)) < 0) { 972 - dprintk(1, "dvb_dmxdev_init() failed (err = %d)\n", err); 973 - goto bailout; 974 - } 975 - 976 - if (dvb_net_init(&cinergyt2->adapter, &cinergyt2->dvbnet, &cinergyt2->demux.dmx)) 977 - dprintk(1, "dvb_net_init() failed!\n"); 978 - 979 - dvb_register_device(&cinergyt2->adapter, &cinergyt2->fedev, 980 - &cinergyt2_fe_template, cinergyt2, 981 - DVB_DEVICE_FRONTEND); 982 - 983 - err = cinergyt2_register_rc(cinergyt2); 984 - if (err) 985 - goto bailout; 986 - 987 - return 0; 988 - 989 - bailout: 990 - dvb_net_release(&cinergyt2->dvbnet); 991 - dvb_dmxdev_release(&cinergyt2->dmxdev); 992 - dvb_dmx_release(&cinergyt2->demux); 993 - dvb_unregister_adapter(&cinergyt2->adapter); 994 - cinergyt2_free_stream_urbs(cinergyt2); 995 - kfree(cinergyt2); 996 - return -ENOMEM; 997 - } 998 - 999 - static void cinergyt2_disconnect (struct usb_interface *intf) 1000 - { 1001 - struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); 1002 - 1003 - cinergyt2_unregister_rc(cinergyt2); 1004 - cancel_rearming_delayed_work(&cinergyt2->query_work); 1005 - wake_up_interruptible(&cinergyt2->poll_wq); 1006 - 1007 - cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx); 1008 - cinergyt2->disconnect_pending = 1; 1009 - 1010 - if (!atomic_read(&cinergyt2->inuse)) 1011 - cinergyt2_unregister(cinergyt2); 1012 - } 1013 - 1014 - static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state) 1015 - { 1016 - struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); 1017 - 1018 - if (cinergyt2->disconnect_pending) 1019 - return -EAGAIN; 1020 - if (mutex_lock_interruptible(&cinergyt2->wq_sem)) 1021 - return -ERESTARTSYS; 1022 - 1023 - cinergyt2_suspend_rc(cinergyt2); 1024 - cancel_rearming_delayed_work(&cinergyt2->query_work); 1025 - 1026 - mutex_lock(&cinergyt2->sem); 1027 - if (cinergyt2->streaming) 1028 - cinergyt2_stop_stream_xfer(cinergyt2); 1029 - cinergyt2_sleep(cinergyt2, 1); 1030 - mutex_unlock(&cinergyt2->sem); 1031 - 1032 - mutex_unlock(&cinergyt2->wq_sem); 1033 - 1034 - return 0; 1035 - } 1036 - 1037 - static int cinergyt2_resume (struct usb_interface *intf) 1038 - { 1039 - struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); 1040 - struct dvbt_set_parameters_msg *param = &cinergyt2->param; 1041 - int err = -EAGAIN; 1042 - 1043 - if (cinergyt2->disconnect_pending) 1044 - goto out; 1045 - err = mutex_lock_interruptible(&cinergyt2->wq_sem); 1046 - if (err) 1047 - goto out; 1048 - 1049 - err = mutex_lock_interruptible(&cinergyt2->sem); 1050 - if (err) 1051 - goto out_unlock1; 1052 - 1053 - if (!cinergyt2->sleeping) { 1054 - cinergyt2_sleep(cinergyt2, 0); 1055 - cinergyt2_command(cinergyt2, (char *) param, sizeof(*param), NULL, 0); 1056 - if (cinergyt2->streaming) 1057 - cinergyt2_start_stream_xfer(cinergyt2); 1058 - schedule_delayed_work(&cinergyt2->query_work, HZ/2); 1059 - } 1060 - 1061 - cinergyt2_resume_rc(cinergyt2); 1062 - 1063 - mutex_unlock(&cinergyt2->sem); 1064 - out_unlock1: 1065 - mutex_unlock(&cinergyt2->wq_sem); 1066 - out: 1067 - return err; 1068 - } 1069 - 1070 - static const struct usb_device_id cinergyt2_table [] __devinitdata = { 1071 - { USB_DEVICE(0x0ccd, 0x0038) }, 1072 - { 0 } 1073 - }; 1074 - 1075 - MODULE_DEVICE_TABLE(usb, cinergyt2_table); 1076 - 1077 - static struct usb_driver cinergyt2_driver = { 1078 - .name = "cinergyT2", 1079 - .probe = cinergyt2_probe, 1080 - .disconnect = cinergyt2_disconnect, 1081 - .suspend = cinergyt2_suspend, 1082 - .resume = cinergyt2_resume, 1083 - .id_table = cinergyt2_table 1084 - }; 1085 - 1086 - static int __init cinergyt2_init (void) 1087 - { 1088 - int err; 1089 - 1090 - if ((err = usb_register(&cinergyt2_driver)) < 0) 1091 - dprintk(1, "usb_register() failed! (err %i)\n", err); 1092 - 1093 - return err; 1094 - } 1095 - 1096 - static void __exit cinergyt2_exit (void) 1097 - { 1098 - usb_deregister(&cinergyt2_driver); 1099 - } 1100 - 1101 - module_init (cinergyt2_init); 1102 - module_exit (cinergyt2_exit); 1103 - 1104 - MODULE_LICENSE("GPL"); 1105 - MODULE_AUTHOR("Holger Waechtler, Daniel Mack");
+8
drivers/media/dvb/dvb-usb/Kconfig
··· 259 259 Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers 260 260 and the TeVii S650. 261 261 262 + config DVB_USB_CINERGY_T2 263 + tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver" 264 + depends on DVB_USB 265 + help 266 + Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers 267 + 268 + Say Y if you own such a device and want to use it. 269 + 262 270 config DVB_USB_ANYSEE 263 271 tristate "Anysee DVB-T/C USB2.0 support" 264 272 depends on DVB_USB
+4
drivers/media/dvb/dvb-usb/Makefile
··· 73 73 dvb-usb-af9015-objs = af9015.o 74 74 obj-$(CONFIG_DVB_USB_AF9015) += dvb-usb-af9015.o 75 75 76 + dvb-usb-cinergyT2-objs = cinergyT2-core.o cinergyT2-fe.o 77 + obj-$(CONFIG_DVB_USB_CINERGY_T2) += dvb-usb-cinergyT2.o 78 + 79 + 76 80 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ 77 81 # due to tuner-xc3028 78 82 EXTRA_CFLAGS += -Idrivers/media/common/tuners
+230
drivers/media/dvb/dvb-usb/cinergyT2-core.c
··· 1 + /* 2 + * TerraTec Cinergy T2/qanu USB2 DVB-T adapter. 3 + * 4 + * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi) 5 + * 6 + * Based on the dvb-usb-framework code and the 7 + * original Terratec Cinergy T2 driver by: 8 + * 9 + * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and 10 + * Holger Waechtler <holger@qanu.de> 11 + * 12 + * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf 13 + * 14 + * This program is free software; you can redistribute it and/or modify 15 + * it under the terms of the GNU General Public License as published by 16 + * the Free Software Foundation; either version 2 of the License, or 17 + * (at your option) any later version. 18 + * 19 + * This program is distributed in the hope that it will be useful, 20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 + * GNU General Public License for more details. 23 + * 24 + * You should have received a copy of the GNU General Public License 25 + * along with this program; if not, write to the Free Software 26 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 + * 28 + */ 29 + 30 + #include "cinergyT2.h" 31 + 32 + 33 + /* debug */ 34 + int dvb_usb_cinergyt2_debug; 35 + int disable_remote; 36 + 37 + module_param_named(debug, dvb_usb_cinergyt2_debug, int, 0644); 38 + MODULE_PARM_DESC(debug, "set debugging level (1=info, xfer=2, rc=4 " 39 + "(or-able))."); 40 + 41 + DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 42 + 43 + 44 + /* We are missing a release hook with usb_device data */ 45 + struct dvb_usb_device *cinergyt2_usb_device; 46 + 47 + static struct dvb_usb_device_properties cinergyt2_properties; 48 + 49 + static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable) 50 + { 51 + char buf[] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 }; 52 + char result[64]; 53 + return dvb_usb_generic_rw(adap->dev, buf, sizeof(buf), result, 54 + sizeof(result), 0); 55 + } 56 + 57 + static int cinergyt2_power_ctrl(struct dvb_usb_device *d, int enable) 58 + { 59 + char buf[] = { CINERGYT2_EP1_SLEEP_MODE, enable ? 0 : 1 }; 60 + char state[3]; 61 + return dvb_usb_generic_rw(d, buf, sizeof(buf), state, sizeof(state), 0); 62 + } 63 + 64 + static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap) 65 + { 66 + char query[] = { CINERGYT2_EP1_GET_FIRMWARE_VERSION }; 67 + char state[3]; 68 + int ret; 69 + 70 + adap->fe = cinergyt2_fe_attach(adap->dev); 71 + 72 + ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state, 73 + sizeof(state), 0); 74 + if (ret < 0) { 75 + deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep " 76 + "state info\n"); 77 + } 78 + 79 + /* Copy this pointer as we are gonna need it in the release phase */ 80 + cinergyt2_usb_device = adap->dev; 81 + 82 + return 0; 83 + } 84 + 85 + static struct dvb_usb_rc_key cinergyt2_rc_keys[] = { 86 + { 0x04, 0x01, KEY_POWER }, 87 + { 0x04, 0x02, KEY_1 }, 88 + { 0x04, 0x03, KEY_2 }, 89 + { 0x04, 0x04, KEY_3 }, 90 + { 0x04, 0x05, KEY_4 }, 91 + { 0x04, 0x06, KEY_5 }, 92 + { 0x04, 0x07, KEY_6 }, 93 + { 0x04, 0x08, KEY_7 }, 94 + { 0x04, 0x09, KEY_8 }, 95 + { 0x04, 0x0a, KEY_9 }, 96 + { 0x04, 0x0c, KEY_0 }, 97 + { 0x04, 0x0b, KEY_VIDEO }, 98 + { 0x04, 0x0d, KEY_REFRESH }, 99 + { 0x04, 0x0e, KEY_SELECT }, 100 + { 0x04, 0x0f, KEY_EPG }, 101 + { 0x04, 0x10, KEY_UP }, 102 + { 0x04, 0x14, KEY_DOWN }, 103 + { 0x04, 0x11, KEY_LEFT }, 104 + { 0x04, 0x13, KEY_RIGHT }, 105 + { 0x04, 0x12, KEY_OK }, 106 + { 0x04, 0x15, KEY_TEXT }, 107 + { 0x04, 0x16, KEY_INFO }, 108 + { 0x04, 0x17, KEY_RED }, 109 + { 0x04, 0x18, KEY_GREEN }, 110 + { 0x04, 0x19, KEY_YELLOW }, 111 + { 0x04, 0x1a, KEY_BLUE }, 112 + { 0x04, 0x1c, KEY_VOLUMEUP }, 113 + { 0x04, 0x1e, KEY_VOLUMEDOWN }, 114 + { 0x04, 0x1d, KEY_MUTE }, 115 + { 0x04, 0x1b, KEY_CHANNELUP }, 116 + { 0x04, 0x1f, KEY_CHANNELDOWN }, 117 + { 0x04, 0x40, KEY_PAUSE }, 118 + { 0x04, 0x4c, KEY_PLAY }, 119 + { 0x04, 0x58, KEY_RECORD }, 120 + { 0x04, 0x54, KEY_PREVIOUS }, 121 + { 0x04, 0x48, KEY_STOP }, 122 + { 0x04, 0x5c, KEY_NEXT } 123 + }; 124 + 125 + static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state) 126 + { 127 + u8 key[5] = {0, 0, 0, 0, 0}, cmd = CINERGYT2_EP1_GET_RC_EVENTS; 128 + *state = REMOTE_NO_KEY_PRESSED; 129 + 130 + dvb_usb_generic_rw(d, &cmd, 1, key, sizeof(key), 0); 131 + if (key[4] == 0xff) 132 + return 0; 133 + 134 + /* hack to pass checksum on the custom field (is set to 0xeb) */ 135 + key[2] = ~0x04; 136 + dvb_usb_nec_rc_key_to_event(d, key, event, state); 137 + if (key[0] != 0) 138 + deb_info("key: %x %x %x %x %x\n", 139 + key[0], key[1], key[2], key[3], key[4]); 140 + 141 + return 0; 142 + } 143 + 144 + static int cinergyt2_usb_probe(struct usb_interface *intf, 145 + const struct usb_device_id *id) 146 + { 147 + return dvb_usb_device_init(intf, &cinergyt2_properties, 148 + THIS_MODULE, NULL, adapter_nr); 149 + } 150 + 151 + 152 + static struct usb_device_id cinergyt2_usb_table[] = { 153 + { USB_DEVICE(USB_VID_TERRATEC, 0x0038) }, 154 + { 0 } 155 + }; 156 + 157 + MODULE_DEVICE_TABLE(usb, cinergyt2_usb_table); 158 + 159 + static struct dvb_usb_device_properties cinergyt2_properties = { 160 + 161 + .num_adapters = 1, 162 + .adapter = { 163 + { 164 + .streaming_ctrl = cinergyt2_streaming_ctrl, 165 + .frontend_attach = cinergyt2_frontend_attach, 166 + 167 + /* parameter for the MPEG2-data transfer */ 168 + .stream = { 169 + .type = USB_BULK, 170 + .count = 5, 171 + .endpoint = 0x02, 172 + .u = { 173 + .bulk = { 174 + .buffersize = 512, 175 + } 176 + } 177 + }, 178 + } 179 + }, 180 + 181 + .power_ctrl = cinergyt2_power_ctrl, 182 + 183 + .rc_interval = 50, 184 + .rc_key_map = cinergyt2_rc_keys, 185 + .rc_key_map_size = ARRAY_SIZE(cinergyt2_rc_keys), 186 + .rc_query = cinergyt2_rc_query, 187 + 188 + .generic_bulk_ctrl_endpoint = 1, 189 + 190 + .num_device_descs = 1, 191 + .devices = { 192 + { .name = "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver", 193 + .cold_ids = {NULL}, 194 + .warm_ids = { &cinergyt2_usb_table[0], NULL }, 195 + }, 196 + { NULL }, 197 + } 198 + }; 199 + 200 + 201 + static struct usb_driver cinergyt2_driver = { 202 + .name = "cinergyT2", 203 + .probe = cinergyt2_usb_probe, 204 + .disconnect = dvb_usb_device_exit, 205 + .id_table = cinergyt2_usb_table 206 + }; 207 + 208 + static int __init cinergyt2_usb_init(void) 209 + { 210 + int err; 211 + 212 + err = usb_register(&cinergyt2_driver); 213 + if (err) { 214 + err("usb_register() failed! (err %i)\n", err); 215 + return err; 216 + } 217 + return 0; 218 + } 219 + 220 + static void __exit cinergyt2_usb_exit(void) 221 + { 222 + usb_deregister(&cinergyt2_driver); 223 + } 224 + 225 + module_init(cinergyt2_usb_init); 226 + module_exit(cinergyt2_usb_exit); 227 + 228 + MODULE_DESCRIPTION("Terratec Cinergy T2 DVB-T driver"); 229 + MODULE_LICENSE("GPL"); 230 + MODULE_AUTHOR("Tomi Orava");
+351
drivers/media/dvb/dvb-usb/cinergyT2-fe.c
··· 1 + /* 2 + * TerraTec Cinergy T2/qanu USB2 DVB-T adapter. 3 + * 4 + * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi) 5 + * 6 + * Based on the dvb-usb-framework code and the 7 + * original Terratec Cinergy T2 driver by: 8 + * 9 + * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and 10 + * Holger Waechtler <holger@qanu.de> 11 + * 12 + * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf 13 + * 14 + * This program is free software; you can redistribute it and/or modify 15 + * it under the terms of the GNU General Public License as published by 16 + * the Free Software Foundation; either version 2 of the License, or 17 + * (at your option) any later version. 18 + * 19 + * This program is distributed in the hope that it will be useful, 20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 + * GNU General Public License for more details. 23 + * 24 + * You should have received a copy of the GNU General Public License 25 + * along with this program; if not, write to the Free Software 26 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 + * 28 + */ 29 + 30 + #include "cinergyT2.h" 31 + 32 + 33 + /** 34 + * convert linux-dvb frontend parameter set into TPS. 35 + * See ETSI ETS-300744, section 4.6.2, table 9 for details. 36 + * 37 + * This function is probably reusable and may better get placed in a support 38 + * library. 39 + * 40 + * We replace errornous fields by default TPS fields (the ones with value 0). 41 + */ 42 + 43 + static uint16_t compute_tps(struct dvb_frontend_parameters *p) 44 + { 45 + struct dvb_ofdm_parameters *op = &p->u.ofdm; 46 + uint16_t tps = 0; 47 + 48 + switch (op->code_rate_HP) { 49 + case FEC_2_3: 50 + tps |= (1 << 7); 51 + break; 52 + case FEC_3_4: 53 + tps |= (2 << 7); 54 + break; 55 + case FEC_5_6: 56 + tps |= (3 << 7); 57 + break; 58 + case FEC_7_8: 59 + tps |= (4 << 7); 60 + break; 61 + case FEC_1_2: 62 + case FEC_AUTO: 63 + default: 64 + /* tps |= (0 << 7) */; 65 + } 66 + 67 + switch (op->code_rate_LP) { 68 + case FEC_2_3: 69 + tps |= (1 << 4); 70 + break; 71 + case FEC_3_4: 72 + tps |= (2 << 4); 73 + break; 74 + case FEC_5_6: 75 + tps |= (3 << 4); 76 + break; 77 + case FEC_7_8: 78 + tps |= (4 << 4); 79 + break; 80 + case FEC_1_2: 81 + case FEC_AUTO: 82 + default: 83 + /* tps |= (0 << 4) */; 84 + } 85 + 86 + switch (op->constellation) { 87 + case QAM_16: 88 + tps |= (1 << 13); 89 + break; 90 + case QAM_64: 91 + tps |= (2 << 13); 92 + break; 93 + case QPSK: 94 + default: 95 + /* tps |= (0 << 13) */; 96 + } 97 + 98 + switch (op->transmission_mode) { 99 + case TRANSMISSION_MODE_8K: 100 + tps |= (1 << 0); 101 + break; 102 + case TRANSMISSION_MODE_2K: 103 + default: 104 + /* tps |= (0 << 0) */; 105 + } 106 + 107 + switch (op->guard_interval) { 108 + case GUARD_INTERVAL_1_16: 109 + tps |= (1 << 2); 110 + break; 111 + case GUARD_INTERVAL_1_8: 112 + tps |= (2 << 2); 113 + break; 114 + case GUARD_INTERVAL_1_4: 115 + tps |= (3 << 2); 116 + break; 117 + case GUARD_INTERVAL_1_32: 118 + default: 119 + /* tps |= (0 << 2) */; 120 + } 121 + 122 + switch (op->hierarchy_information) { 123 + case HIERARCHY_1: 124 + tps |= (1 << 10); 125 + break; 126 + case HIERARCHY_2: 127 + tps |= (2 << 10); 128 + break; 129 + case HIERARCHY_4: 130 + tps |= (3 << 10); 131 + break; 132 + case HIERARCHY_NONE: 133 + default: 134 + /* tps |= (0 << 10) */; 135 + } 136 + 137 + return tps; 138 + } 139 + 140 + struct cinergyt2_fe_state { 141 + struct dvb_frontend fe; 142 + struct dvb_usb_device *d; 143 + }; 144 + 145 + static int cinergyt2_fe_read_status(struct dvb_frontend *fe, 146 + fe_status_t *status) 147 + { 148 + struct cinergyt2_fe_state *state = fe->demodulator_priv; 149 + struct dvbt_get_status_msg result; 150 + u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; 151 + int ret; 152 + 153 + ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&result, 154 + sizeof(result), 0); 155 + if (ret < 0) 156 + return ret; 157 + 158 + *status = 0; 159 + 160 + if (0xffff - le16_to_cpu(result.gain) > 30) 161 + *status |= FE_HAS_SIGNAL; 162 + if (result.lock_bits & (1 << 6)) 163 + *status |= FE_HAS_LOCK; 164 + if (result.lock_bits & (1 << 5)) 165 + *status |= FE_HAS_SYNC; 166 + if (result.lock_bits & (1 << 4)) 167 + *status |= FE_HAS_CARRIER; 168 + if (result.lock_bits & (1 << 1)) 169 + *status |= FE_HAS_VITERBI; 170 + 171 + if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) != 172 + (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) 173 + *status &= ~FE_HAS_LOCK; 174 + 175 + return 0; 176 + } 177 + 178 + static int cinergyt2_fe_read_ber(struct dvb_frontend *fe, u32 *ber) 179 + { 180 + struct cinergyt2_fe_state *state = fe->demodulator_priv; 181 + struct dvbt_get_status_msg status; 182 + char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; 183 + int ret; 184 + 185 + ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, 186 + sizeof(status), 0); 187 + if (ret < 0) 188 + return ret; 189 + 190 + *ber = le32_to_cpu(status.viterbi_error_rate); 191 + return 0; 192 + } 193 + 194 + static int cinergyt2_fe_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) 195 + { 196 + struct cinergyt2_fe_state *state = fe->demodulator_priv; 197 + struct dvbt_get_status_msg status; 198 + u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; 199 + int ret; 200 + 201 + ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&status, 202 + sizeof(status), 0); 203 + if (ret < 0) { 204 + err("cinergyt2_fe_read_unc_blocks() Failed! (Error=%d)\n", 205 + ret); 206 + return ret; 207 + } 208 + *unc = le32_to_cpu(status.uncorrected_block_count); 209 + return 0; 210 + } 211 + 212 + static int cinergyt2_fe_read_signal_strength(struct dvb_frontend *fe, 213 + u16 *strength) 214 + { 215 + struct cinergyt2_fe_state *state = fe->demodulator_priv; 216 + struct dvbt_get_status_msg status; 217 + char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; 218 + int ret; 219 + 220 + ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, 221 + sizeof(status), 0); 222 + if (ret < 0) { 223 + err("cinergyt2_fe_read_signal_strength() Failed!" 224 + " (Error=%d)\n", ret); 225 + return ret; 226 + } 227 + *strength = (0xffff - le16_to_cpu(status.gain)); 228 + return 0; 229 + } 230 + 231 + static int cinergyt2_fe_read_snr(struct dvb_frontend *fe, u16 *snr) 232 + { 233 + struct cinergyt2_fe_state *state = fe->demodulator_priv; 234 + struct dvbt_get_status_msg status; 235 + char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; 236 + int ret; 237 + 238 + ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, 239 + sizeof(status), 0); 240 + if (ret < 0) { 241 + err("cinergyt2_fe_read_snr() Failed! (Error=%d)\n", ret); 242 + return ret; 243 + } 244 + *snr = (status.snr << 8) | status.snr; 245 + return 0; 246 + } 247 + 248 + static int cinergyt2_fe_init(struct dvb_frontend *fe) 249 + { 250 + return 0; 251 + } 252 + 253 + static int cinergyt2_fe_sleep(struct dvb_frontend *fe) 254 + { 255 + deb_info("cinergyt2_fe_sleep() Called\n"); 256 + return 0; 257 + } 258 + 259 + static int cinergyt2_fe_get_tune_settings(struct dvb_frontend *fe, 260 + struct dvb_frontend_tune_settings *tune) 261 + { 262 + tune->min_delay_ms = 800; 263 + return 0; 264 + } 265 + 266 + static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe, 267 + struct dvb_frontend_parameters *fep) 268 + { 269 + struct cinergyt2_fe_state *state = fe->demodulator_priv; 270 + struct dvbt_set_parameters_msg param; 271 + char result[2]; 272 + int err; 273 + 274 + param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; 275 + param.tps = cpu_to_le16(compute_tps(fep)); 276 + param.freq = cpu_to_le32(fep->frequency / 1000); 277 + param.bandwidth = 8 - fep->u.ofdm.bandwidth - BANDWIDTH_8_MHZ; 278 + 279 + err = dvb_usb_generic_rw(state->d, 280 + (char *)&param, sizeof(param), 281 + result, sizeof(result), 0); 282 + if (err < 0) 283 + err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err); 284 + 285 + return (err < 0) ? err : 0; 286 + } 287 + 288 + static int cinergyt2_fe_get_frontend(struct dvb_frontend *fe, 289 + struct dvb_frontend_parameters *fep) 290 + { 291 + return 0; 292 + } 293 + 294 + static void cinergyt2_fe_release(struct dvb_frontend *fe) 295 + { 296 + struct cinergyt2_fe_state *state = fe->demodulator_priv; 297 + if (state != NULL) 298 + kfree(state); 299 + } 300 + 301 + static struct dvb_frontend_ops cinergyt2_fe_ops; 302 + 303 + struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d) 304 + { 305 + struct cinergyt2_fe_state *s = kzalloc(sizeof( 306 + struct cinergyt2_fe_state), GFP_KERNEL); 307 + if (s == NULL) 308 + return NULL; 309 + 310 + s->d = d; 311 + memcpy(&s->fe.ops, &cinergyt2_fe_ops, sizeof(struct dvb_frontend_ops)); 312 + s->fe.demodulator_priv = s; 313 + return &s->fe; 314 + } 315 + 316 + 317 + static struct dvb_frontend_ops cinergyt2_fe_ops = { 318 + .info = { 319 + .name = DRIVER_NAME, 320 + .type = FE_OFDM, 321 + .frequency_min = 174000000, 322 + .frequency_max = 862000000, 323 + .frequency_stepsize = 166667, 324 + .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 325 + | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 326 + | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 327 + | FE_CAN_FEC_AUTO | FE_CAN_QPSK 328 + | FE_CAN_QAM_16 | FE_CAN_QAM_64 329 + | FE_CAN_QAM_AUTO 330 + | FE_CAN_TRANSMISSION_MODE_AUTO 331 + | FE_CAN_GUARD_INTERVAL_AUTO 332 + | FE_CAN_HIERARCHY_AUTO 333 + | FE_CAN_RECOVER 334 + | FE_CAN_MUTE_TS 335 + }, 336 + 337 + .release = cinergyt2_fe_release, 338 + 339 + .init = cinergyt2_fe_init, 340 + .sleep = cinergyt2_fe_sleep, 341 + 342 + .set_frontend = cinergyt2_fe_set_frontend, 343 + .get_frontend = cinergyt2_fe_get_frontend, 344 + .get_tune_settings = cinergyt2_fe_get_tune_settings, 345 + 346 + .read_status = cinergyt2_fe_read_status, 347 + .read_ber = cinergyt2_fe_read_ber, 348 + .read_signal_strength = cinergyt2_fe_read_signal_strength, 349 + .read_snr = cinergyt2_fe_read_snr, 350 + .read_ucblocks = cinergyt2_fe_read_unc_blocks, 351 + };
+95
drivers/media/dvb/dvb-usb/cinergyT2.h
··· 1 + /* 2 + * TerraTec Cinergy T2/qanu USB2 DVB-T adapter. 3 + * 4 + * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi) 5 + * 6 + * Based on the dvb-usb-framework code and the 7 + * original Terratec Cinergy T2 driver by: 8 + * 9 + * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and 10 + * Holger Waechtler <holger@qanu.de> 11 + * 12 + * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf 13 + * 14 + * This program is free software; you can redistribute it and/or modify 15 + * it under the terms of the GNU General Public License as published by 16 + * the Free Software Foundation; either version 2 of the License, or 17 + * (at your option) any later version. 18 + * 19 + * This program is distributed in the hope that it will be useful, 20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 + * GNU General Public License for more details. 23 + * 24 + * You should have received a copy of the GNU General Public License 25 + * along with this program; if not, write to the Free Software 26 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 + * 28 + */ 29 + 30 + #ifndef _DVB_USB_CINERGYT2_H_ 31 + #define _DVB_USB_CINERGYT2_H_ 32 + 33 + #include <linux/usb/input.h> 34 + 35 + #define DVB_USB_LOG_PREFIX "cinergyT2" 36 + #include "dvb-usb.h" 37 + 38 + #define DRIVER_NAME "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver" 39 + 40 + extern int dvb_usb_cinergyt2_debug; 41 + 42 + #define deb_info(args...) dprintk(dvb_usb_cinergyt2_debug, 0x001, args) 43 + #define deb_xfer(args...) dprintk(dvb_usb_cinergyt2_debug, 0x002, args) 44 + #define deb_pll(args...) dprintk(dvb_usb_cinergyt2_debug, 0x004, args) 45 + #define deb_ts(args...) dprintk(dvb_usb_cinergyt2_debug, 0x008, args) 46 + #define deb_err(args...) dprintk(dvb_usb_cinergyt2_debug, 0x010, args) 47 + #define deb_rc(args...) dprintk(dvb_usb_cinergyt2_debug, 0x020, args) 48 + #define deb_fw(args...) dprintk(dvb_usb_cinergyt2_debug, 0x040, args) 49 + #define deb_mem(args...) dprintk(dvb_usb_cinergyt2_debug, 0x080, args) 50 + #define deb_uxfer(args...) dprintk(dvb_usb_cinergyt2_debug, 0x100, args) 51 + 52 + 53 + 54 + enum cinergyt2_ep1_cmd { 55 + CINERGYT2_EP1_PID_TABLE_RESET = 0x01, 56 + CINERGYT2_EP1_PID_SETUP = 0x02, 57 + CINERGYT2_EP1_CONTROL_STREAM_TRANSFER = 0x03, 58 + CINERGYT2_EP1_SET_TUNER_PARAMETERS = 0x04, 59 + CINERGYT2_EP1_GET_TUNER_STATUS = 0x05, 60 + CINERGYT2_EP1_START_SCAN = 0x06, 61 + CINERGYT2_EP1_CONTINUE_SCAN = 0x07, 62 + CINERGYT2_EP1_GET_RC_EVENTS = 0x08, 63 + CINERGYT2_EP1_SLEEP_MODE = 0x09, 64 + CINERGYT2_EP1_GET_FIRMWARE_VERSION = 0x0A 65 + }; 66 + 67 + 68 + struct dvbt_get_status_msg { 69 + uint32_t freq; 70 + uint8_t bandwidth; 71 + uint16_t tps; 72 + uint8_t flags; 73 + uint16_t gain; 74 + uint8_t snr; 75 + uint32_t viterbi_error_rate; 76 + uint32_t rs_error_rate; 77 + uint32_t uncorrected_block_count; 78 + uint8_t lock_bits; 79 + uint8_t prev_lock_bits; 80 + } __attribute__((packed)); 81 + 82 + 83 + struct dvbt_set_parameters_msg { 84 + uint8_t cmd; 85 + uint32_t freq; 86 + uint8_t bandwidth; 87 + uint16_t tps; 88 + uint8_t flags; 89 + } __attribute__((packed)); 90 + 91 + 92 + extern struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d); 93 + 94 + #endif /* _DVB_USB_CINERGYT2_H_ */ 95 +