Commit 15490795 authored by Stefan Richter's avatar Stefan Richter

firedtv: massive refactoring

Combination of the following changes:

Mon, 23 Feb 2009 14:21:10 +0100 (CET)
firedtv: reinstate debug logging option

    Henrik Kurelid tells me that FCP debug logging (which I removed during
    cleanups) is still useful when working on driver issues together with
    end users.  So bring it back in an updated form with only 60% of the
    original code footprint.

    Logging can be enabled with
    # echo -1 > /sys/module/firedtv/parameters/debug

    1 instead of -1 enables only FCP header logging,
    2 instead of -1 enables only hexdumps of the entire FCP frames.
    0 switches logging off again.

Fri, 20 Feb 2009 20:54:27 +0100 (CET)
firedtv: build fix for INPUT=m and DVB_FIREDTV=y

Thu, 19 Feb 2009 20:40:39 +0100
firedtv: use msecs_to_jiffies

    Pointed out by Mauro Carvalho Chehab.

Sun Feb 15 20:50:46 CET 2009
firedtv: some more housekeeping

    Fix an old checkpatch warning and a new compiler warning.

Sun Feb 15 15:33:17 CET 2009
firedtv: rename a file once more

    At the moment, about a third of avc.c is specific to FireDTVs rather
    than generic AV/C code.  Rename it to firedtv-avc.c.

Sun Feb 15 15:33:17 CET 2009
firedtv: dvb demux: more compact channels backing store

    Replace struct firedtv_channel { bool active; int pid; } channel[16];
    by unsigned long channel_active; u16 channel_pid[16];.

Sun Feb 15 15:33:17 CET 2009
firedtv: dvb demux: some simplifications

    c->active was unnecessarily cleared twice.

    Also, by marking the channel inactive before the for loop,
    the loop becomes identical with fdtv_channel_collect().

Sun Feb 15 15:33:17 CET 2009
firedtv: dvb demux: remove a bogus loop

    This loop is unnecessary because
      - only active channel[].pid's will be sent to the device,
      - when a channel is activated, its pid is set to dvbdmxfeed->pid.

    Perhaps the original code was there because it was initially not fully
    covered by the fdtv->demux_mutex.

Sun Feb 15 15:33:17 CET 2009
firedtv: dvb demux: fix mutex protection

    fdtv_start_feed() accessed the channel list unsafely.
    Fully serialize it with itself and fdtv_stop_feed().

Sun Feb 15 15:33:17 CET 2009
firedtv: dvb demux: fix missing braces

    Original code was:
            ...
            case DMX_TS_PES_OTHER:
                    //Dirty fix to keep firesat->channel pid-list up to date
                    for(k=0;k<16;k++){
                            if(firesat->channel[k].active == 0)
                                    firesat->channel[k].pid =
                                            dvbdmxfeed->pid;
                                    break;
                    }
                    channel = firesat_channel_allocate(firesat);
                    break;
            default:
            ...

    Looks bogus in several respects. For now let's just add braces to the if
    because that seems to be what the author meant.

Sun Feb 15 15:33:17 CET 2009
firedtv: allow build without input subsystem

    !CONFIG_INPUT is very unlikely on systems on which firedtv is of
    interest.  But we can easily support it.

Sun Feb 15 15:33:17 CET 2009
firedtv: replace EXTRA_CFLAGS by ccflags

    The former are deprecated.
    The latter can depend on Kconfig variables.

Sun Feb 15 15:33:17 CET 2009
firedtv: concentrate ieee1394 dependencies

    Move the entire interface with drivers/ieee1394 to firedtv-1394.c.
    Move 1394-independent module initialization code to firedtv-dvb.c.

    This prepares interfacing with drivers/firewire.

Sun Feb 15 15:33:17 CET 2009
firedtv: amend Kconfig menu prompt

Sun Feb 15 15:33:17 CET 2009
firedtv: remove kernel version compatibility macro

Sun Feb 15 15:33:17 CET 2009
firedtv: combine header files

    avc.h and firedtv-*.h are small and currently not shared with other
    drivers, hence concatenate them all into firedtv.h.

Sun Feb 15 15:33:17 CET 2009
firedtv: misc style touch-ups

    Standardize on lower-case hexadecimal constants.  Adjust whitespace.
    Omit unnecessary pointer type casts and an unnecessary list head
    initialization.  Use dev_printk.

Wed Feb 11 21:21:04 CET 2009
firedtv: avc, ci: remove unused constants

Wed Feb 11 21:21:04 CET 2009
firedtv: avc: remove bitfields from read descriptor response operands

    Don't use bitfields in struct types of on-the-wire data.

Wed Feb 11 21:21:04 CET 2009
firedtv: avc: remove bitfields from DSD command operands

    Don't use bitfields in struct types of on-the-wire data.

Wed Feb 11 21:21:04 CET 2009
firedtv: avc: header file cleanup

    Remove unused constants and declarations.
    Move privately used constants into .c files.

Wed Feb 11 21:21:04 CET 2009
firedtv: avc: remove bitfields from FCP frame types

    Don't use bitfields in struct types of on-the-wire data.

    Also move many privately used constants from avc.h to avc.c
    and remove some unused constants.

Sun, 18 Jan 2009 16:30:00 +0100 (CET)
firedtv: avc: fix offset in avc_tuner_get_ts

    The parentheses were wrong.  It didn't matter though because this code
    only writes a 0 into an area which is already initialized to 0.

Sun, 18 Jan 2009 16:30:00 +0100 (CET)
firedtv: avc: reduce stack usage, remove two typedefs

    It is safe to share a memory buffer for command frame and response frame
    because the response data come in after the command frame was last used.

    Even less stack would be required if only the actual required frame size
    instead of the entire FCP register size was allocated.

    Also, rename the defined types AVCCmdFrm and AVCRspFrm to
    struct avc_command_frame and struct avc_response_frame.
    TODO:  Remove the bitfields in these types.

Sun, 18 Jan 2009 16:30:00 +0100 (CET)
firedtv: cmp: move code to avc

Sun, 18 Jan 2009 16:30:00 +0100 (CET)
firedtv: iso: move code to firedtv-1394

Sun, 18 Jan 2009 16:30:00 +0100 (CET)
firedtv: iso: remove unnecessary struct type definitions

Sun, 18 Jan 2009 16:30:00 +0100 (CET)
firedtv: iso: style changes and fixlets

    Add cleanup after failure in setup_iso_channel.
    Replace printk() by dv_err().
    Decrease indentation level in rawiso_activity_cb().
Signed-off-by: default avatarStefan Richter <stefanr@s5r6.in-berlin.de>
parent a70f81c1
......@@ -51,6 +51,8 @@ comment "Supported SDMC DM1105 Adapters"
depends on DVB_CORE && PCI && I2C
source "drivers/media/dvb/dm1105/Kconfig"
comment "Supported FireWire (IEEE 1394) Adapters"
depends on DVB_CORE && IEEE1394
source "drivers/media/dvb/firewire/Kconfig"
comment "Supported DVB Frontends"
......
config DVB_FIREDTV
tristate "FireDTV (FireWire attached DVB receivers)"
depends on DVB_CORE && IEEE1394 && INPUT
tristate "FireDTV and FloppyDTV"
depends on DVB_CORE && IEEE1394
help
Support for DVB receivers from Digital Everywhere, known as FireDTV
and FloppyDTV, which are connected via IEEE 1394 (FireWire).
Support for DVB receivers from Digital Everywhere
which are connected via IEEE 1394 (FireWire).
These devices don't have an MPEG decoder built in, so you need
an external software decoder to watch TV.
These devices don't have an MPEG decoder built in,
so you need an external software decoder to watch TV.
To compile this driver as a module, say M here: the module will be
called firedtv.
To compile this driver as a module, say M here:
the module will be called firedtv.
if DVB_FIREDTV
config DVB_FIREDTV_IEEE1394
def_bool IEEE1394
config DVB_FIREDTV_INPUT
def_bool INPUT = y || (INPUT = m && DVB_FIREDTV = m)
endif # DVB_FIREDTV
firedtv-objs := firedtv-1394.o \
firedtv-dvb.o \
firedtv-fe.o \
firedtv-iso.o \
avc.o \
cmp.o \
firedtv-rc.o \
firedtv-ci.o
obj-$(CONFIG_DVB_FIREDTV) += firedtv.o
EXTRA_CFLAGS := -Idrivers/ieee1394
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
firedtv-y := firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o
firedtv-$(CONFIG_DVB_FIREDTV_IEEE1394) += firedtv-1394.o
firedtv-$(CONFIG_DVB_FIREDTV_INPUT) += firedtv-rc.o
ccflags-y += -Idrivers/media/dvb/dvb-core
ccflags-$(CONFIG_DVB_FIREDTV_IEEE1394) += -Idrivers/ieee1394
This diff is collapsed.
This diff is collapsed.
/*
* FireDTV driver (formerly known as FireSAT)
*
* Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
* Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/types.h>
#include <asm/byteorder.h>
#include <ieee1394.h>
#include <nodemgr.h>
#include "avc.h"
#include "cmp.h"
#include "firedtv.h"
#define CMP_OUTPUT_PLUG_CONTROL_REG_0 0xfffff0000904ULL
static int cmp_read(struct firedtv *fdtv, void *buf, u64 addr, size_t len)
{
int ret;
if (mutex_lock_interruptible(&fdtv->avc_mutex))
return -EINTR;
ret = hpsb_node_read(fdtv->ud->ne, addr, buf, len);
if (ret < 0)
dev_err(&fdtv->ud->device, "CMP: read I/O error\n");
mutex_unlock(&fdtv->avc_mutex);
return ret;
}
static int cmp_lock(struct firedtv *fdtv, void *data, u64 addr, __be32 arg,
int ext_tcode)
{
int ret;
if (mutex_lock_interruptible(&fdtv->avc_mutex))
return -EINTR;
ret = hpsb_node_lock(fdtv->ud->ne, addr, ext_tcode, data,
(__force quadlet_t)arg);
if (ret < 0)
dev_err(&fdtv->ud->device, "CMP: lock I/O error\n");
mutex_unlock(&fdtv->avc_mutex);
return ret;
}
static inline u32 get_opcr(__be32 opcr, u32 mask, u32 shift)
{
return (be32_to_cpu(opcr) >> shift) & mask;
}
static inline void set_opcr(__be32 *opcr, u32 value, u32 mask, u32 shift)
{
*opcr &= ~cpu_to_be32(mask << shift);
*opcr |= cpu_to_be32((value & mask) << shift);
}
#define get_opcr_online(v) get_opcr((v), 0x1, 31)
#define get_opcr_p2p_connections(v) get_opcr((v), 0x3f, 24)
#define get_opcr_channel(v) get_opcr((v), 0x3f, 16)
#define set_opcr_p2p_connections(p, v) set_opcr((p), (v), 0x3f, 24)
#define set_opcr_channel(p, v) set_opcr((p), (v), 0x3f, 16)
#define set_opcr_data_rate(p, v) set_opcr((p), (v), 0x3, 14)
#define set_opcr_overhead_id(p, v) set_opcr((p), (v), 0xf, 10)
int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel)
{
__be32 old_opcr, opcr;
u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
int attempts = 0;
int ret;
ret = cmp_read(fdtv, &opcr, opcr_address, 4);
if (ret < 0)
return ret;
repeat:
if (!get_opcr_online(opcr)) {
dev_err(&fdtv->ud->device, "CMP: output offline\n");
return -EBUSY;
}
old_opcr = opcr;
if (get_opcr_p2p_connections(opcr)) {
if (get_opcr_channel(opcr) != channel) {
dev_err(&fdtv->ud->device,
"CMP: cannot change channel\n");
return -EBUSY;
}
dev_info(&fdtv->ud->device,
"CMP: overlaying existing connection\n");
/* We don't allocate isochronous resources. */
} else {
set_opcr_channel(&opcr, channel);
set_opcr_data_rate(&opcr, IEEE1394_SPEED_400);
/* FIXME: this is for the worst case - optimize */
set_opcr_overhead_id(&opcr, 0);
/* FIXME: allocate isochronous channel and bandwidth at IRM */
}
set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) + 1);
ret = cmp_lock(fdtv, &opcr, opcr_address, old_opcr, 2);
if (ret < 0)
return ret;
if (old_opcr != opcr) {
/*
* FIXME: if old_opcr.P2P_Connections > 0,
* deallocate isochronous channel and bandwidth at IRM
*/
if (++attempts < 6) /* arbitrary limit */
goto repeat;
return -EBUSY;
}
return 0;
}
void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel)
{
__be32 old_opcr, opcr;
u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
int attempts = 0;
if (cmp_read(fdtv, &opcr, opcr_address, 4) < 0)
return;
repeat:
if (!get_opcr_online(opcr) || !get_opcr_p2p_connections(opcr) ||
get_opcr_channel(opcr) != channel) {
dev_err(&fdtv->ud->device, "CMP: no connection to break\n");
return;
}
old_opcr = opcr;
set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) - 1);
if (cmp_lock(fdtv, &opcr, opcr_address, old_opcr, 2) < 0)
return;
if (old_opcr != opcr) {
/*
* FIXME: if old_opcr.P2P_Connections == 1, i.e. we were last
* owner, deallocate isochronous channel and bandwidth at IRM
*/
if (++attempts < 6) /* arbitrary limit */
goto repeat;
}
}
#ifndef _CMP_H
#define _CMP_H
struct firedtv;
int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel);
void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel);
#endif /* _CMP_H */
This diff is collapsed.
This diff is collapsed.
......@@ -10,33 +10,37 @@
* the License, or (at your option) any later version.
*/
#include <linux/device.h>
#include <linux/dvb/ca.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <dvbdev.h>
#include "avc.h"
#include "firedtv.h"
#include "firedtv-ci.h"
static int fdtv_ca_ready(ANTENNA_INPUT_INFO *info)
#define EN50221_TAG_APP_INFO_ENQUIRY 0x9f8020
#define EN50221_TAG_CA_INFO_ENQUIRY 0x9f8030
#define EN50221_TAG_CA_PMT 0x9f8032
#define EN50221_TAG_ENTER_MENU 0x9f8022
static int fdtv_ca_ready(struct firedtv_tuner_status *stat)
{
return info->CaInitializationStatus == 1 &&
info->CaErrorFlag == 0 &&
info->CaDvbFlag == 1 &&
info->CaModulePresentStatus == 1;
return stat->ca_initialization_status == 1 &&
stat->ca_error_flag == 0 &&
stat->ca_dvb_flag == 1 &&
stat->ca_module_present_status == 1;
}
static int fdtv_get_ca_flags(ANTENNA_INPUT_INFO *info)
static int fdtv_get_ca_flags(struct firedtv_tuner_status *stat)
{
int flags = 0;
if (info->CaModulePresentStatus == 1)
if (stat->ca_module_present_status == 1)
flags |= CA_CI_MODULE_PRESENT;
if (info->CaInitializationStatus == 1 &&
info->CaErrorFlag == 0 &&
info->CaDvbFlag == 1)
if (stat->ca_initialization_status == 1 &&
stat->ca_error_flag == 0 &&
stat->ca_dvb_flag == 1)
flags |= CA_CI_MODULE_READY;
return flags;
}
......@@ -59,17 +63,17 @@ static int fdtv_ca_get_caps(void *arg)
static int fdtv_ca_get_slot_info(struct firedtv *fdtv, void *arg)
{
ANTENNA_INPUT_INFO info;
struct firedtv_tuner_status stat;
struct ca_slot_info *slot = arg;
if (avc_tuner_status(fdtv, &info))
if (avc_tuner_status(fdtv, &stat))
return -EFAULT;
if (slot->num != 0)
return -EFAULT;
slot->type = CA_CI;
slot->flags = fdtv_get_ca_flags(&info);
slot->flags = fdtv_get_ca_flags(&stat);
return 0;
}
......@@ -77,8 +81,7 @@ static int fdtv_ca_app_info(struct firedtv *fdtv, void *arg)
{
struct ca_msg *reply = arg;
return
avc_ca_app_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
return avc_ca_app_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
}
static int fdtv_ca_info(struct firedtv *fdtv, void *arg)
......@@ -92,30 +95,29 @@ static int fdtv_ca_get_mmi(struct firedtv *fdtv, void *arg)
{
struct ca_msg *reply = arg;
return
avc_ca_get_mmi(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
return avc_ca_get_mmi(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
}
static int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg)
{
ANTENNA_INPUT_INFO info;
struct firedtv_tuner_status stat;
int err;
switch (fdtv->ca_last_command) {
case TAG_APP_INFO_ENQUIRY:
case EN50221_TAG_APP_INFO_ENQUIRY:
err = fdtv_ca_app_info(fdtv, arg);
break;
case TAG_CA_INFO_ENQUIRY:
case EN50221_TAG_CA_INFO_ENQUIRY:
err = fdtv_ca_info(fdtv, arg);
break;
default:
if (avc_tuner_status(fdtv, &info))
if (avc_tuner_status(fdtv, &stat))
err = -EFAULT;
else if (info.CaMmi == 1)
else if (stat.ca_mmi == 1)
err = fdtv_ca_get_mmi(fdtv, arg);
else {
printk(KERN_INFO "%s: Unhandled message 0x%08X\n",
__func__, fdtv->ca_last_command);
dev_info(fdtv->device, "unhandled CA message 0x%08x\n",
fdtv->ca_last_command);
err = -EFAULT;
}
}
......@@ -133,14 +135,13 @@ static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)
data_pos = 4;
if (msg->msg[3] & 0x80) {
data_length = 0;
for (i = 0; i < (msg->msg[3] & 0x7F); i++)
for (i = 0; i < (msg->msg[3] & 0x7f); i++)
data_length = (data_length << 8) + msg->msg[data_pos++];
} else {
data_length = msg->msg[3];
}
return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length) ?
-EFAULT : 0;
return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length) ? -EFAULT : 0;
}
static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg)
......@@ -152,23 +153,23 @@ static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg)
fdtv->ca_last_command =
(msg->msg[0] << 16) + (msg->msg[1] << 8) + msg->msg[2];
switch (fdtv->ca_last_command) {
case TAG_CA_PMT:
case EN50221_TAG_CA_PMT:
err = fdtv_ca_pmt(fdtv, arg);
break;
case TAG_APP_INFO_ENQUIRY:
case EN50221_TAG_APP_INFO_ENQUIRY:
/* handled in ca_get_msg */
err = 0;
break;
case TAG_CA_INFO_ENQUIRY:
case EN50221_TAG_CA_INFO_ENQUIRY:
/* handled in ca_get_msg */
err = 0;
break;
case TAG_ENTER_MENU:
case EN50221_TAG_ENTER_MENU:
err = avc_ca_enter_menu(fdtv);
break;
default:
printk(KERN_ERR "%s: Unhandled unknown message 0x%08X\n",
__func__, fdtv->ca_last_command);
dev_err(fdtv->device, "unhandled CA message 0x%08x\n",
fdtv->ca_last_command);
err = -EFAULT;
}
return err;
......@@ -179,10 +180,10 @@ static int fdtv_ca_ioctl(struct inode *inode, struct file *file,
{
struct dvb_device *dvbdev = file->private_data;
struct firedtv *fdtv = dvbdev->priv;
ANTENNA_INPUT_INFO info;
struct firedtv_tuner_status stat;
int err;
switch(cmd) {
switch (cmd) {
case CA_RESET:
err = fdtv_ca_reset(fdtv);
break;
......@@ -199,13 +200,12 @@ static int fdtv_ca_ioctl(struct inode *inode, struct file *file,
err = fdtv_ca_send_msg(fdtv, arg);
break;
default:
printk(KERN_INFO "%s: Unhandled ioctl, command: %u\n",__func__,
cmd);
dev_info(fdtv->device, "unhandled CA ioctl %u\n", cmd);
err = -EOPNOTSUPP;
}
/* FIXME Is this necessary? */
avc_tuner_status(fdtv, &info);
avc_tuner_status(fdtv, &stat);
return err;
}
......@@ -233,22 +233,21 @@ static struct dvb_device fdtv_ca = {
int fdtv_ca_register(struct firedtv *fdtv)
{
ANTENNA_INPUT_INFO info;
struct firedtv_tuner_status stat;
int err;
if (avc_tuner_status(fdtv, &info))
if (avc_tuner_status(fdtv, &stat))
return -EINVAL;
if (!fdtv_ca_ready(&info))
if (!fdtv_ca_ready(&stat))
return -EFAULT;
err = dvb_register_device(&fdtv->adapter, &fdtv->cadev,
&fdtv_ca, fdtv, DVB_DEVICE_CA);
if (info.CaApplicationInfo == 0)
printk(KERN_ERR "%s: CaApplicationInfo is not set.\n",
__func__);
if (info.CaDateTimeRequest == 1)
if (stat.ca_application_info == 0)
dev_err(fdtv->device, "CaApplicationInfo is not set\n");
if (stat.ca_date_time_request == 1)
avc_ca_get_time_date(fdtv, &fdtv->ca_time_interval);
return err;
......
#ifndef _FIREDTV_CI_H
#define _FIREDTV_CI_H
struct firedtv;
int fdtv_ca_register(struct firedtv *fdtv);
void fdtv_ca_release(struct firedtv *fdtv);
#endif /* _FIREDTV_CI_H */
This diff is collapsed.
......@@ -10,6 +10,7 @@
* the License, or (at your option) any later version.
*/
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/string.h>
......@@ -17,8 +18,6 @@
#include <dvb_frontend.h>
#include "avc.h"
#include "cmp.h"
#include "firedtv.h"
static int fdtv_dvb_init(struct dvb_frontend *fe)
......@@ -32,35 +31,37 @@ static int fdtv_dvb_init(struct dvb_frontend *fe)
err = cmp_establish_pp_connection(fdtv, fdtv->subunit,
fdtv->isochannel);
if (err) {
printk(KERN_ERR "Could not establish point to point "
"connection.\n");
dev_err(fdtv->device,
"could not establish point to point connection\n");
return err;
}
return setup_iso_channel(fdtv);
return fdtv->backend->start_iso(fdtv);
}
static int fdtv_sleep(struct dvb_frontend *fe)
{
struct firedtv *fdtv = fe->sec_priv;
tear_down_iso_channel(fdtv);
fdtv->backend->stop_iso(fdtv);
cmp_break_pp_connection(fdtv, fdtv->subunit, fdtv->isochannel);
fdtv->isochannel = -1;
return 0;
}
#define LNBCONTROL_DONTCARE 0xff
static int fdtv_diseqc_send_master_cmd(struct dvb_frontend *fe,
struct dvb_diseqc_master_cmd *cmd)
struct dvb_diseqc_master_cmd *cmd)
{
struct firedtv *fdtv = fe->sec_priv;
return avc_lnb_control(fdtv, LNBCONTROL_DONTCARE,
LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE, 1, cmd);
return avc_lnb_control(fdtv, LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE,
LNBCONTROL_DONTCARE, 1, cmd);
}
static int fdtv_diseqc_send_burst(struct dvb_frontend *fe,
fe_sec_mini_cmd_t minicmd)
fe_sec_mini_cmd_t minicmd)
{
return 0;
}
......@@ -74,7 +75,7 @@ static int fdtv_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
}
static int fdtv_set_voltage(struct dvb_frontend *fe,
fe_sec_voltage_t voltage)
fe_sec_voltage_t voltage)
{
struct firedtv *fdtv = fe->sec_priv;
......@@ -85,12 +86,12 @@ static int fdtv_set_voltage(struct dvb_frontend *fe,
static int fdtv_read_status(struct dvb_frontend *fe, fe_status_t *status)
{
struct firedtv *fdtv = fe->sec_priv;
ANTENNA_INPUT_INFO info;
struct firedtv_tuner_status stat;
if (avc_tuner_status(fdtv, &info))
if (avc_tuner_status(fdtv, &stat))
return -EINVAL;
if (info.NoRF)
if (stat.no_rf)
*status = 0;
else
*status = FE_HAS_SIGNAL | FE_HAS_VITERBI | FE_HAS_SYNC |
......@@ -101,39 +102,37 @@ static int fdtv_read_status(struct dvb_frontend *fe, fe_status_t *status)
static int fdtv_read_ber(struct dvb_frontend *fe, u32 *ber)
{
struct firedtv *fdtv = fe->sec_priv;
ANTENNA_INPUT_INFO info;
struct firedtv_tuner_status stat;
if (avc_tuner_status(fdtv, &info))
if (avc_tuner_status(fdtv, &stat))
return -EINVAL;
*ber = info.BER[0] << 24 | info.BER[1] << 16 |
info.BER[2] << 8 | info.BER[3];
*ber = stat.ber;
return 0;
}
static int fdtv_read_signal_strength (struct dvb_frontend *fe, u16 *strength)
static int fdtv_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
{
struct firedtv *fdtv = fe->sec_priv;
ANTENNA_INPUT_INFO info;
struct firedtv_tuner_status stat;
if (avc_tuner_status(fdtv, &info))
if (avc_tuner_status(fdtv, &stat))
return -EINVAL;
*strength = info.SignalStrength << 8;
*strength = stat.signal_strength << 8;
return 0;
}
static int fdtv_read_snr(struct dvb_frontend *fe, u16 *snr)
{
struct firedtv *fdtv = fe->sec_priv;
ANTENNA_INPUT_INFO info;
struct firedtv_tuner_status stat;
if (avc_tuner_status(fdtv, &info))
if (avc_tuner_status(fdtv, &stat))
return -EINVAL;
/* C/N[dB] = -10 * log10(snr / 65535) */
*snr = (info.CarrierNoiseRatio[0] << 8) + info.CarrierNoiseRatio[1];
*snr *= 257;
*snr = stat.carrier_noise_ratio * 257;
return 0;
}
......@@ -142,8 +141,10 @@ static int fdtv_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ucblocks)
return -EOPNOTSUPP;
}
#define ACCEPTED 0x9
static int fdtv_set_frontend(struct dvb_frontend *fe,
struct dvb_frontend_parameters *params)
struct dvb_frontend_parameters *params)
{
struct firedtv *fdtv = fe->sec_priv;
......@@ -155,7 +156,7 @@ static int fdtv_set_frontend(struct dvb_frontend *fe,
}
static int fdtv_get_frontend(struct dvb_frontend *fe,
struct dvb_frontend_parameters *params)
struct dvb_frontend_parameters *params)
{
return -EOPNOTSUPP;
}
......@@ -235,8 +236,8 @@ void fdtv_frontend_init(struct firedtv *fdtv)
break;
default:
printk(KERN_ERR "FireDTV: no frontend for model type %d\n",
fdtv->type);
dev_err(fdtv->device, "no frontend for model type %d\n",
fdtv->type);
}
strcpy(fi->name, fdtv_model_names[fdtv->type]);
......
/*
* FireSAT DVB driver
*
* Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <dvb_demux.h>
#include <dma.h>
#include <iso.h>
#include <nodemgr.h>
#include "firedtv.h"
static void rawiso_activity_cb(struct hpsb_iso *iso);
void tear_down_iso_channel(struct firedtv *fdtv)
{
if (fdtv->iso_handle != NULL) {
hpsb_iso_stop(fdtv->iso_handle);
hpsb_iso_shutdown(fdtv->iso_handle);
}
fdtv->iso_handle = NULL;
}
int setup_iso_channel(struct firedtv *fdtv)
{
int result;
fdtv->iso_handle =
hpsb_iso_recv_init(fdtv->ud->ne->host,
256 * 200, //data_buf_size,
256, //buf_packets,
fdtv->isochannel,
HPSB_ISO_DMA_DEFAULT, //dma_mode,
-1, //stat.config.irq_interval,
rawiso_activity_cb);
if (fdtv->iso_handle == NULL) {
printk(KERN_ERR "Cannot initialize iso receive.\n");
return -EINVAL;
}
result = hpsb_iso_recv_start(fdtv->iso_handle, -1, -1, 0);
if (result != 0) {
printk(KERN_ERR "Cannot start iso receive.\n");
return -EINVAL;
}
return 0;
}
static void rawiso_activity_cb(struct hpsb_iso *iso)
{
unsigned int num;
unsigned int i;
unsigned int packet;
unsigned long flags;
struct firedtv *fdtv = NULL;
struct firedtv *fdtv_iterator;
spin_lock_irqsave(&fdtv_list_lock, flags);
list_for_each_entry(fdtv_iterator, &fdtv_list, list) {
if(fdtv_iterator->iso_handle == iso) {
fdtv = fdtv_iterator;
break;
}
}
spin_unlock_irqrestore(&fdtv_list_lock, flags);
if (fdtv) {
packet = iso->first_packet;
num = hpsb_iso_n_ready(iso);
for (i = 0; i < num; i++,
packet = (packet + 1) % iso->buf_packets) {
unsigned char *buf =
dma_region_i(&iso->data_buf, unsigned char,
iso->infos[packet].offset +
sizeof(struct CIPHeader));
int count = (iso->infos[packet].len -
sizeof(struct CIPHeader)) /
(188 + sizeof(struct firewireheader));
if (iso->infos[packet].len <= sizeof(struct CIPHeader))
continue; // ignore empty packet
while (count --) {
if (buf[sizeof(struct firewireheader)] == 0x47)
dvb_dmx_swfilter_packets(&fdtv->demux,
&buf[sizeof(struct firewireheader)], 1);
else
printk("%s: invalid packet, skipping\n", __func__);
buf += 188 + sizeof(struct firewireheader);
}
}
hpsb_iso_recv_release_packets(iso, num);
}
else {
printk("%s: packets for unknown iso channel, skipping\n",
__func__);
hpsb_iso_recv_release_packets(iso, hpsb_iso_n_ready(iso));
}
}
......@@ -15,7 +15,6 @@
#include <linux/string.h>
#include <linux/types.h>
#include "firedtv-rc.h"
#include "firedtv.h"
/* fixed table with older keycodes, geared towards MythTV */
......
#ifndef _FIREDTV_RC_H
#define _FIREDTV_RC_H
struct firedtv;
struct device;
int fdtv_register_rc(struct firedtv *fdtv, struct device *dev);
void fdtv_unregister_rc(struct firedtv *fdtv);
void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code);
#endif /* _FIREDTV_RC_H */
......@@ -29,95 +29,35 @@
#include <dvb_net.h>
#include <dvbdev.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
#define DVB_REGISTER_ADAPTER(x, y, z, w, v) dvb_register_adapter(x, y, z, w, v)
#else
#define DVB_REGISTER_ADAPTER(x, y, z, w, v) dvb_register_adapter(x, y, z, w)
#define DVB_DEFINE_MOD_OPT_ADAPTER_NR(x)
#endif
/*****************************************************************
* CA message command constants from en50221_app_tags.h of libdvb
*****************************************************************/
/* Resource Manager */
#define TAG_PROFILE_ENQUIRY 0x9f8010
#define TAG_PROFILE 0x9f8011
#define TAG_PROFILE_CHANGE 0x9f8012
/* Application Info */
#define TAG_APP_INFO_ENQUIRY 0x9f8020
#define TAG_APP_INFO 0x9f8021
#define TAG_ENTER_MENU 0x9f8022
/* CA Support */
#define TAG_CA_INFO_ENQUIRY 0x9f8030
#define TAG_CA_INFO 0x9f8031
#define TAG_CA_PMT 0x9f8032
#define TAG_CA_PMT_REPLY 0x9f8033
/* Host Control */
#define TAG_TUNE 0x9f8400
#define TAG_REPLACE 0x9f8401
#define TAG_CLEAR_REPLACE 0x9f8402
#define TAG_ASK_RELEASE 0x9f8403
/* Date and Time */
#define TAG_DATE_TIME_ENQUIRY 0x9f8440
#define TAG_DATE_TIME 0x9f8441
/* Man Machine Interface (MMI) */
#define TAG_CLOSE_MMI 0x9f8800
#define TAG_DISPLAY_CONTROL 0x9f8801
#define TAG_DISPLAY_REPLY 0x9f8802
#define TAG_TEXT_LAST 0x9f8803
#define TAG_TEXT_MORE 0x9f8804
#define TAG_KEYPAD_CONTROL 0x9f8805
#define TAG_KEYPRESS 0x9f8806
#define TAG_ENQUIRY 0x9f8807
#define TAG_ANSWER 0x9f8808
#define TAG_MENU_LAST 0x9f8809
#define TAG_MENU_MORE 0x9f880a
#define TAG_MENU_ANSWER 0x9f880b
#define TAG_LIST_LAST 0x9f880c
#define TAG_LIST_MORE 0x9f880d
#define TAG_SUBTITLE_SEGMENT_LAST 0x9f880e
#define TAG_SUBTITLE_SEGMENT_MORE 0x9f880f
#define TAG_DISPLAY_MESSAGE 0x9f8810
#define TAG_SCENE_END_MARK 0x9f8811
#define TAG_SCENE_DONE 0x9f8812
#define TAG_SCENE_CONTROL 0x9f8813
#define TAG_SUBTITLE_DOWNLOAD_LAST 0x9f8814
#define TAG_SUBTITLE_DOWNLOAD_MORE 0x9f8815
#define TAG_FLUSH_DOWNLOAD 0x9f8816
#define TAG_DOWNLOAD_REPLY 0x9f8817
/* Low Speed Communications */
#define TAG_COMMS_COMMAND 0x9f8c00
#define TAG_CONNECTION_DESCRIPTOR 0x9f8c01
#define TAG_COMMS_REPLY 0x9f8c02
#define TAG_COMMS_SEND_LAST 0x9f8c03
#define TAG_COMMS_SEND_MORE 0x9f8c04
#define TAG_COMMS_RECV_LAST 0x9f8c05
#define TAG_COMMS_RECV_MORE 0x9f8c06
/* Authentication */
#define TAG_AUTH_REQ 0x9f8200
#define TAG_AUTH_RESP 0x9f8201
/* Teletext */
#define TAG_TELETEXT_EBU 0x9f9000
/* Smartcard */
#define TAG_SMARTCARD_COMMAND 0x9f8e00
#define TAG_SMARTCARD_REPLY 0x9f8e01
#define TAG_SMARTCARD_SEND 0x9f8e02
#define TAG_SMARTCARD_RCV 0x9f8e03
/* EPG */
#define TAG_EPG_ENQUIRY 0x9f8f00
#define TAG_EPG_REPLY 0x9f8f01
struct firedtv_tuner_status {
unsigned active_system:8;
unsigned searching:1;
unsigned moving:1;
unsigned no_rf:1;
unsigned input:1;
unsigned selected_antenna:7;
unsigned ber:32;
unsigned signal_strength:8;
unsigned raster_frequency:2;
unsigned rf_frequency:22;
unsigned man_dep_info_length:8;
unsigned front_end_error:1;
unsigned antenna_error:1;
unsigned front_end_power_status:1;
unsigned power_supply:1;
unsigned carrier_noise_ratio:16;
unsigned power_supply_voltage:8;
unsigned antenna_voltage:8;
unsigned firewire_bus_voltage:8;
unsigned ca_mmi:1;
unsigned ca_pmt_reply:1;
unsigned ca_date_time_request:1;
unsigned ca_application_info:1;
unsigned ca_module_present_status:1;
unsigned ca_dvb_flag:1;
unsigned ca_error_flag:1;
unsigned ca_initialization_status:1;
};
enum model_type {
FIREDTV_UNKNOWN = 0,
......@@ -127,11 +67,22 @@ enum model_type {
FIREDTV_DVB_S2 = 4,
};
struct device;
struct input_dev;
struct hpsb_iso;
struct unit_directory;
struct firedtv;
struct firedtv_backend {
int (*lock)(struct firedtv *fdtv, u64 addr, void *data, __be32 arg);
int (*read)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
int (*start_iso)(struct firedtv *fdtv);
void (*stop_iso)(struct firedtv *fdtv);
};
struct firedtv {
struct device *device;
struct list_head list;
struct dvb_adapter adapter;
struct dmxdev dmxdev;
struct dvb_demux demux;
......@@ -149,79 +100,83 @@ struct firedtv {
struct work_struct remote_ctrl_work;
struct input_dev *remote_ctrl_dev;
struct firedtv_channel {
bool active;
int pid;
} channel[16];
struct mutex demux_mutex;
enum model_type type;
char subunit;
char isochannel;
fe_sec_voltage_t voltage;
fe_sec_tone_mode_t tone;
struct unit_directory *ud;
const struct firedtv_backend *backend;
void *backend_data;
enum model_type type;
char subunit;
fe_sec_voltage_t voltage;
fe_sec_tone_mode_t tone;
int isochannel;
struct hpsb_iso *iso_handle;
struct list_head list;
struct mutex demux_mutex;
unsigned long channel_active;
u16 channel_pid[16];
/* needed by avc_api */
int resp_length;
u8 respfrm[512];
size_t response_length;
u8 response[512];
};
struct firewireheader {
union {
struct {
__u8 tcode:4;
__u8 sy:4;
__u8 tag:2;
__u8 channel:6;
__u8 length_l;
__u8 length_h;
} hdr;
__u32 val;
};
};
struct CIPHeader {
union {
struct {
__u8 syncbits:2;
__u8 sid:6;
__u8 dbs;
__u8 fn:2;
__u8 qpc:3;
__u8 sph:1;
__u8 rsv:2;
__u8 dbc;
__u8 syncbits2:2;
__u8 fmt:6;
__u32 fdf:24;
} cip;
__u64 val;
};
};
extern const char *fdtv_model_names[];
extern struct list_head fdtv_list;
extern spinlock_t fdtv_list_lock;
/* firedtv-1394.c */
#ifdef CONFIG_DVB_FIREDTV_IEEE1394
int fdtv_1394_init(struct ieee1394_device_id id_table[]);
void fdtv_1394_exit(void);
#else
static inline int fdtv_1394_init(struct ieee1394_device_id it[]) { return 0; }
static inline void fdtv_1394_exit(void) {}
#endif
struct device;
/* firedtv-avc.c */
int avc_recv(struct firedtv *fdtv, void *data, size_t length);
int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat);
struct dvb_frontend_parameters;
int avc_tuner_dsd(struct firedtv *fdtv, struct dvb_frontend_parameters *params);
int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]);
int avc_tuner_get_ts(struct firedtv *fdtv);
int avc_identify_subunit(struct firedtv *fdtv);
struct dvb_diseqc_master_cmd;
int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
char conttone, char nrdiseq,
struct dvb_diseqc_master_cmd *diseqcmd);
void avc_remote_ctrl_work(struct work_struct *work);
int avc_register_remote_control(struct firedtv *fdtv);
int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
int avc_ca_reset(struct firedtv *fdtv);
int avc_ca_pmt(struct firedtv *fdtv, char *app_info, int length);
int avc_ca_get_time_date(struct firedtv *fdtv, int *interval);
int avc_ca_enter_menu(struct firedtv *fdtv);
int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len);
int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel);
void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel);
/* firedtv-ci.c */
int fdtv_ca_register(struct firedtv *fdtv);
void fdtv_ca_release(struct firedtv *fdtv);
/* firedtv-dvb.c */
int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed);
int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed);
int fdtv_dvbdev_init(struct firedtv *fdtv, struct device *dev);
int fdtv_dvb_register(struct firedtv *fdtv);
void fdtv_dvb_unregister(struct firedtv *fdtv);
struct firedtv *fdtv_alloc(struct device *dev,
const struct firedtv_backend *backend,
const char *name, size_t name_len);
extern const char *fdtv_model_names[];
/* firedtv-fe.c */
void fdtv_frontend_init(struct firedtv *fdtv);
/* firedtv-iso.c */
int setup_iso_channel(struct firedtv *fdtv);
void tear_down_iso_channel(struct firedtv *fdtv);
/* firedtv-rc.c */
#ifdef CONFIG_DVB_FIREDTV_INPUT
int fdtv_register_rc(struct firedtv *fdtv, struct device *dev);
void fdtv_unregister_rc(struct firedtv *fdtv);
void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code);
#else
static inline int fdtv_register_rc(struct firedtv *fdtv,
struct device *dev) { return 0; }
static inline void fdtv_unregister_rc(struct firedtv *fdtv) {}
static inline void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code) {}
#endif
#endif /* _FIREDTV_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment