#include <asm/semaphore.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/usb.h>
+#include <linux/version.h>
#include <linux/interrupt.h>
#include <linux/firmware.h>
-#if defined(CONFIG_CRC32) || defined(CONFIG_CRC32_MODULE)
#include <linux/crc32.h>
-#else
-#warning "CRC checking of firmware not available"
-#endif
#include <linux/init.h>
#include "dmxdev.h"
#include "dvb_demux.h"
-#include "dvb_i2c.h"
#include "dvb_filter.h"
#include "dvb_frontend.h"
#include "dvb_net.h"
+#include "ttusbdecfe.h"
-static int debug = 0;
-static int output_pva = 0;
+static int debug;
+static int output_pva;
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+module_param(output_pva, int, 0444);
+MODULE_PARM_DESC(output_pva, "Output PVA from dvr device (default:off)");
#define dprintk if (debug) printk
#define MAX_PVA_LENGTH 6144
-#define LOF_HI 10600000
-#define LOF_LO 9750000
-
enum ttusb_dec_model {
TTUSB_DEC2000T,
TTUSB_DEC2540T,
struct dmxdev dmxdev;
struct dvb_demux demux;
struct dmx_frontend frontend;
- struct dvb_i2c_bus i2c_bus;
struct dvb_net dvb_net;
- struct dvb_frontend_info *frontend_info;
- int (*frontend_ioctl) (struct dvb_frontend *, unsigned int, void *);
+ struct dvb_frontend* fe;
u16 pid[DMX_PES_OTHER];
- int hi_band;
- int voltage;
/* USB bits */
struct usb_device *udev;
struct list_head filter_info_list;
};
-static struct dvb_frontend_info dec2000t_frontend_info = {
- .name = "TechnoTrend/Hauppauge DEC2000-t Frontend",
- .type = FE_OFDM,
- .frequency_min = 51000000,
- .frequency_max = 858000000,
- .frequency_stepsize = 62500,
- .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
- FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
- FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
- FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
- FE_CAN_HIERARCHY_AUTO,
-};
-
-static struct dvb_frontend_info dec3000s_frontend_info = {
- .name = "TechnoTrend/Hauppauge DEC3000-s Frontend",
- .type = FE_QPSK,
- .frequency_min = 950000,
- .frequency_max = 2150000,
- .frequency_stepsize = 125,
- .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
- FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
- FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
- FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
- FE_CAN_HIERARCHY_AUTO,
-};
-
static void ttusb_dec_set_model(struct ttusb_dec *dec,
enum ttusb_dec_model model);
if (!dec->iso_stream_count) {
for (i = 0; i < ISO_BUF_COUNT; i++)
- usb_unlink_urb(dec->iso_urb[i]);
+ usb_kill_urb(dec->iso_urb[i]);
}
up(&dec->iso_sem);
"error %d\n", __FUNCTION__, i, result);
while (i) {
- usb_unlink_urb(dec->iso_urb[i - 1]);
+ usb_kill_urb(dec->iso_urb[i - 1]);
i--;
}
&dec->iso_dma_handle);
memset(dec->iso_buffer, 0,
- sizeof(ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT)));
+ ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT));
for (i = 0; i < ISO_BUF_COUNT; i++) {
struct urb *urb;
static void ttusb_dec_init_tasklet(struct ttusb_dec *dec)
{
- dec->urb_frame_list_lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&dec->urb_frame_list_lock);
INIT_LIST_HEAD(&dec->urb_frame_list);
tasklet_init(&dec->urb_tasklet, ttusb_dec_process_urb_frame_list,
(unsigned long)dec);
u16 firmware_csum = 0;
u16 firmware_csum_ns;
u32 firmware_size_nl;
-#if defined(CONFIG_CRC32) || defined(CONFIG_CRC32_MODULE)
u32 crc32_csum, crc32_check, tmp;
-#endif
const struct firmware *fw_entry = NULL;
+
dprintk("%s\n", __FUNCTION__);
if (request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev)) {
/* a 32 bit checksum over the first 56 bytes of the DSP Code is stored
at offset 56 of file, so use it to check if the firmware file is
valid. */
-#if defined(CONFIG_CRC32) || defined(CONFIG_CRC32_MODULE)
crc32_csum = crc32(~0L, firmware, 56) ^ ~0L;
memcpy(&tmp, &firmware[56], 4);
crc32_check = htonl(tmp);
__FUNCTION__, crc32_csum, crc32_check);
return -1;
}
-#endif
memcpy(idstring, &firmware[36], 20);
idstring[20] = '\0';
printk(KERN_INFO "ttusb_dec: found DSP code \"%s\".\n", idstring);
ttusb_dec_set_model(dec, TTUSB_DEC3000S);
break;
case 0x00070009:
+ case 0x00070013:
ttusb_dec_set_model(dec, TTUSB_DEC2000T);
break;
case 0x00070011:
dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
dvb_dmxdev_release(&dec->dmxdev);
dvb_dmx_release(&dec->demux);
+ if (dec->fe) dvb_unregister_frontend(dec->fe);
dvb_unregister_adapter(dec->adapter);
}
dec->iso_stream_count = 0;
for (i = 0; i < ISO_BUF_COUNT; i++)
- usb_unlink_urb(dec->iso_urb[i]);
+ usb_kill_urb(dec->iso_urb[i]);
ttusb_dec_free_iso_urbs(dec);
}
}
}
-static int ttusb_dec_2000t_frontend_ioctl(struct dvb_frontend *fe, unsigned int cmd,
- void *arg)
-{
- struct ttusb_dec *dec = fe->data;
-
- dprintk("%s\n", __FUNCTION__);
-
- switch (cmd) {
-
- case FE_GET_INFO:
- dprintk("%s: FE_GET_INFO\n", __FUNCTION__);
- memcpy(arg, dec->frontend_info,
- sizeof (struct dvb_frontend_info));
- break;
-
- case FE_READ_STATUS: {
- fe_status_t *status = (fe_status_t *)arg;
- dprintk("%s: FE_READ_STATUS\n", __FUNCTION__);
- *status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
- FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
- break;
- }
-
- case FE_READ_BER: {
- u32 *ber = (u32 *)arg;
- dprintk("%s: FE_READ_BER\n", __FUNCTION__);
- *ber = 0;
- return -ENOSYS;
- break;
- }
-
- case FE_READ_SIGNAL_STRENGTH: {
- dprintk("%s: FE_READ_SIGNAL_STRENGTH\n", __FUNCTION__);
- *(s32 *)arg = 0xFF;
- return -ENOSYS;
- break;
- }
-
- case FE_READ_SNR:
- dprintk("%s: FE_READ_SNR\n", __FUNCTION__);
- *(s32 *)arg = 0;
- return -ENOSYS;
- break;
-
- case FE_READ_UNCORRECTED_BLOCKS:
- dprintk("%s: FE_READ_UNCORRECTED_BLOCKS\n", __FUNCTION__);
- *(u32 *)arg = 0;
- return -ENOSYS;
- break;
-
- case FE_SET_FRONTEND: {
- struct dvb_frontend_parameters *p =
- (struct dvb_frontend_parameters *)arg;
- u8 b[] = { 0x00, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0xff,
- 0x00, 0x00, 0x00, 0xff };
- u32 freq;
-
- dprintk("%s: FE_SET_FRONTEND\n", __FUNCTION__);
-
- dprintk(" frequency->%d\n", p->frequency);
- dprintk(" symbol_rate->%d\n",
- p->u.qam.symbol_rate);
- dprintk(" inversion->%d\n", p->inversion);
-
- freq = htonl(p->frequency / 1000);
- memcpy(&b[4], &freq, sizeof (u32));
- ttusb_dec_send_command(dec, 0x71, sizeof(b), b, NULL, NULL);
-
- break;
- }
-
- case FE_GET_FRONTEND:
- dprintk("%s: FE_GET_FRONTEND\n", __FUNCTION__);
- break;
-
- case FE_SLEEP:
- dprintk("%s: FE_SLEEP\n", __FUNCTION__);
- return -ENOSYS;
- break;
-
- case FE_INIT:
- dprintk("%s: FE_INIT\n", __FUNCTION__);
- break;
-
- default:
- dprintk("%s: unknown IOCTL (0x%X)\n", __FUNCTION__, cmd);
- return -EINVAL;
-
- }
-
- return 0;
-}
-
-static int ttusb_dec_3000s_frontend_ioctl(struct dvb_frontend *fe,
- unsigned int cmd, void *arg)
-{
- struct ttusb_dec *dec = fe->data;
-
- dprintk("%s\n", __FUNCTION__);
-
- switch (cmd) {
-
- case FE_GET_INFO:
- dprintk("%s: FE_GET_INFO\n", __FUNCTION__);
- memcpy(arg, dec->frontend_info,
- sizeof (struct dvb_frontend_info));
- break;
-
- case FE_READ_STATUS: {
- fe_status_t *status = (fe_status_t *)arg;
- dprintk("%s: FE_READ_STATUS\n", __FUNCTION__);
- *status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
- FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
- break;
- }
-
- case FE_READ_BER: {
- u32 *ber = (u32 *)arg;
- dprintk("%s: FE_READ_BER\n", __FUNCTION__);
- *ber = 0;
- return -ENOSYS;
- break;
- }
-
- case FE_READ_SIGNAL_STRENGTH: {
- dprintk("%s: FE_READ_SIGNAL_STRENGTH\n", __FUNCTION__);
- *(s32 *)arg = 0xFF;
- return -ENOSYS;
- break;
- }
-
- case FE_READ_SNR:
- dprintk("%s: FE_READ_SNR\n", __FUNCTION__);
- *(s32 *)arg = 0;
- return -ENOSYS;
- break;
-
- case FE_READ_UNCORRECTED_BLOCKS:
- dprintk("%s: FE_READ_UNCORRECTED_BLOCKS\n", __FUNCTION__);
- *(u32 *)arg = 0;
- return -ENOSYS;
- break;
-
- case FE_SET_FRONTEND: {
- struct dvb_frontend_parameters *p =
- (struct dvb_frontend_parameters *)arg;
- u8 b[] = { 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00 };
- u32 freq;
- u32 sym_rate;
- u32 band;
- u32 lnb_voltage;
-
- dprintk("%s: FE_SET_FRONTEND\n", __FUNCTION__);
-
- dprintk(" frequency->%d\n", p->frequency);
- dprintk(" symbol_rate->%d\n",
- p->u.qam.symbol_rate);
- dprintk(" inversion->%d\n", p->inversion);
-
- freq = htonl(p->frequency * 1000 +
- (dec->hi_band ? LOF_HI : LOF_LO));
- memcpy(&b[4], &freq, sizeof(u32));
- sym_rate = htonl(p->u.qam.symbol_rate);
- memcpy(&b[12], &sym_rate, sizeof(u32));
- band = htonl(dec->hi_band ? LOF_HI : LOF_LO);
- memcpy(&b[24], &band, sizeof(u32));
- lnb_voltage = htonl(dec->voltage);
- memcpy(&b[28], &lnb_voltage, sizeof(u32));
-
- ttusb_dec_send_command(dec, 0x71, sizeof(b), b, NULL, NULL);
-
- break;
- }
-
- case FE_GET_FRONTEND:
- dprintk("%s: FE_GET_FRONTEND\n", __FUNCTION__);
- break;
-
- case FE_SLEEP:
- dprintk("%s: FE_SLEEP\n", __FUNCTION__);
- return -ENOSYS;
- break;
-
- case FE_INIT:
- dprintk("%s: FE_INIT\n", __FUNCTION__);
- break;
-
- case FE_DISEQC_SEND_MASTER_CMD:
- dprintk("%s: FE_DISEQC_SEND_MASTER_CMD\n", __FUNCTION__);
- break;
-
- case FE_DISEQC_SEND_BURST:
- dprintk("%s: FE_DISEQC_SEND_BURST\n", __FUNCTION__);
- break;
-
- case FE_SET_TONE: {
- fe_sec_tone_mode_t tone = (fe_sec_tone_mode_t)arg;
- dprintk("%s: FE_SET_TONE\n", __FUNCTION__);
- dec->hi_band = (SEC_TONE_ON == tone);
- break;
- }
-
- case FE_SET_VOLTAGE:
- dprintk("%s: FE_SET_VOLTAGE\n", __FUNCTION__);
- switch ((fe_sec_voltage_t) arg) {
- case SEC_VOLTAGE_13:
- dec->voltage = 13;
- break;
- case SEC_VOLTAGE_18:
- dec->voltage = 18;
- break;
- default:
- return -EINVAL;
- break;
- }
- break;
-
- default:
- dprintk("%s: unknown IOCTL (0x%X)\n", __FUNCTION__, cmd);
- return -EINVAL;
-
- }
-
- return 0;
-}
-
-static void ttusb_dec_init_frontend(struct ttusb_dec *dec)
-{
- dec->i2c_bus.adapter = dec->adapter;
-
- dvb_register_frontend(dec->frontend_ioctl, &dec->i2c_bus, (void *)dec,
- dec->frontend_info);
-}
-
-static void ttusb_dec_exit_frontend(struct ttusb_dec *dec)
-{
- dvb_unregister_frontend(dec->frontend_ioctl, &dec->i2c_bus);
-}
-
static void ttusb_dec_init_filters(struct ttusb_dec *dec)
{
INIT_LIST_HEAD(&dec->filter_info_list);
- dec->filter_info_list_lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&dec->filter_info_list_lock);
}
static void ttusb_dec_exit_filters(struct ttusb_dec *dec)
}
}
+int fe_send_command(struct dvb_frontend* fe, const u8 command,
+ int param_length, const u8 params[],
+ int *result_length, u8 cmd_result[])
+{
+ struct ttusb_dec* dec = (struct ttusb_dec*) fe->dvb->priv;
+ return ttusb_dec_send_command(dec, command, param_length, params, result_length, cmd_result);
+}
+
+struct ttusbdecfe_config fe_config = {
+ .send_command = fe_send_command
+};
+
static int ttusb_dec_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
memset(dec, 0, sizeof(struct ttusb_dec));
- switch (id->idProduct) {
+ switch (le16_to_cpu(id->idProduct)) {
case 0x1006:
ttusb_dec_set_model(dec, TTUSB_DEC3000S);
break;
return 0;
}
ttusb_dec_init_dvb(dec);
- ttusb_dec_init_frontend(dec);
+
+ dec->adapter->priv = dec;
+ switch (le16_to_cpu(id->idProduct)) {
+ case 0x1006:
+ dec->fe = ttusbdecfe_dvbs_attach(&fe_config);
+ break;
+
+ case 0x1008:
+ case 0x1009:
+ dec->fe = ttusbdecfe_dvbt_attach(&fe_config);
+ break;
+ }
+
+ if (dec->fe == NULL) {
+ printk("dvb-ttusb-dec: A frontend driver was not found for device %04x/%04x\n",
+ le16_to_cpu(dec->udev->descriptor.idVendor),
+ le16_to_cpu(dec->udev->descriptor.idProduct));
+ } else {
+ if (dvb_register_frontend(dec->adapter, dec->fe)) {
+ printk("budget-ci: Frontend registration failed!\n");
+ if (dec->fe->ops->release)
+ dec->fe->ops->release(dec->fe);
+ dec->fe = NULL;
+ }
+ }
+
ttusb_dec_init_v_pes(dec);
ttusb_dec_init_filters(dec);
ttusb_dec_init_tasklet(dec);
ttusb_dec_exit_tasklet(dec);
ttusb_dec_exit_filters(dec);
ttusb_dec_exit_usb(dec);
- ttusb_dec_exit_frontend(dec);
ttusb_dec_exit_dvb(dec);
}
case TTUSB_DEC2000T:
dec->model_name = "DEC2000-t";
dec->firmware_name = "dvb-ttusb-dec-2000t.fw";
- dec->frontend_info = &dec2000t_frontend_info;
- dec->frontend_ioctl = ttusb_dec_2000t_frontend_ioctl;
break;
case TTUSB_DEC2540T:
dec->model_name = "DEC2540-t";
dec->firmware_name = "dvb-ttusb-dec-2540t.fw";
- dec->frontend_info = &dec2000t_frontend_info;
- dec->frontend_ioctl = ttusb_dec_2000t_frontend_ioctl;
break;
case TTUSB_DEC3000S:
dec->model_name = "DEC3000-s";
dec->firmware_name = "dvb-ttusb-dec-3000s.fw";
- dec->frontend_info = &dec3000s_frontend_info;
- dec->frontend_ioctl = ttusb_dec_3000s_frontend_ioctl;
break;
}
}
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(usb, ttusb_dec_table);
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug level");
-MODULE_PARM(output_pva, "i");
-MODULE_PARM_DESC(output_pva, "Output PVA from dvr device");