提交 df4846c3 编写于 作者: H Henrik Kurelid 提交者: Stefan Richter

firesat: update isochronous interface, add CI support

I have finally managed to get the CI support for the card working. The
implementation is a bare minimum to get encrypted channels to work in
kaffeine. It works fine with my T/CI card. Now and then I get an AVC
timeout and have to retune a channel in order to get it to work. Once
the CAM seemed to hang so I needed to remove and insert it again. I.e.
there are a number of glitches.

The latest version contains the following changes:

  - Implemented the new hpsb iso interface so that data can be received
    from the card
  - Reduced some timers for demux setup which caused scanning to timeout
  - Added possibility to unload driver
  - Added support for getting C/N ratio
  - Added two debug parameters to the driver; ca_debug and
    avc_comm_debug.
  - Added CI support that works for me in kaffeine
  - Started working on CI MMI support. It now supports:
      o Enter menu
      o Receiving MMI objects
  - Added support for 64-bit platforms
  - Corrected DVB-C modulations problems
Signed-off-by: NHenrik Kurelid <henrik@kurelid.se>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> (rebased, whitespace)
上级 2c228614
firesat-objs := firesat_1394.o \
firesat_dvb.o \
firesat_fe.o \
firesat_iso.o \
avc_api.o \
cmp.o \
firesat-rc.o \
......
此差异已折叠。
......@@ -4,6 +4,7 @@
begin : Wed May 1 2000
copyright : (C) 2000 by Manfred Weihs
copyright : (C) 2003 by Philipp Gutgsell
copyright : (C) 2008 by Henrik Kurelid (henrik@kurelid.se)
email : 0014guph@edu.fh-kaernten.ac.at
***************************************************************************/
......@@ -27,12 +28,10 @@
#include <linux/dvb/frontend.h>
#define BYTE unsigned char
#define WORD unsigned short
#define DWORD unsigned long
#define ULONG unsigned long
#define LONG long
/*************************************************************
Constants from EN510221
**************************************************************/
#define LIST_MANAGEMENT_ONLY 0x03
/*************************************************************
FCP Address range
......@@ -68,12 +67,12 @@ typedef struct {
typedef struct _AVCCmdFrm
{
// AV/C command frame
BYTE ctype : 4 ; // command type
BYTE cts : 4 ; // always 0x0 for AVC
BYTE suid : 3 ; // subunit ID
BYTE sutyp : 5 ; // subunit_typ
BYTE opcode : 8 ; // opcode
BYTE operand[509] ; // array of operands [1-507]
__u8 ctype : 4 ; // command type
__u8 cts : 4 ; // always 0x0 for AVC
__u8 suid : 3 ; // subunit ID
__u8 sutyp : 5 ; // subunit_typ
__u8 opcode : 8 ; // opcode
__u8 operand[509] ; // array of operands [1-507]
int length; //length of the command frame
} AVCCmdFrm ;
......@@ -81,12 +80,12 @@ typedef struct _AVCCmdFrm
typedef struct _AVCRspFrm
{
// AV/C response frame
BYTE resp : 4 ; // response type
BYTE cts : 4 ; // always 0x0 for AVC
BYTE suid : 3 ; // subunit ID
BYTE sutyp : 5 ; // subunit_typ
BYTE opcode : 8 ; // opcode
BYTE operand[509] ; // array of operands [1-507]
__u8 resp : 4 ; // response type
__u8 cts : 4 ; // always 0x0 for AVC
__u8 suid : 3 ; // subunit ID
__u8 sutyp : 5 ; // subunit_typ
__u8 opcode : 8 ; // opcode
__u8 operand[509] ; // array of operands [1-507]
int length; //length of the response frame
} AVCRspFrm ;
......@@ -94,23 +93,23 @@ typedef struct _AVCRspFrm
typedef struct _AVCCmdFrm
{
BYTE cts:4;
BYTE ctype:4;
BYTE sutyp:5;
BYTE suid:3;
BYTE opcode;
BYTE operand[509];
__u8 cts:4;
__u8 ctype:4;
__u8 sutyp:5;
__u8 suid:3;
__u8 opcode;
__u8 operand[509];
int length;
} AVCCmdFrm;
typedef struct _AVCRspFrm
{
BYTE cts:4;
BYTE resp:4;
BYTE sutyp:5;
BYTE suid:3;
BYTE opcode;
BYTE operand[509];
__u8 cts:4;
__u8 resp:4;
__u8 sutyp:5;
__u8 suid:3;
__u8 opcode;
__u8 operand[509];
int length;
} AVCRspFrm;
......@@ -197,6 +196,14 @@ typedef struct _AVCRspFrm
#define SFE_VENDOR_OPCODE_CISTATUS 0x59
#define SFE_VENDOR_OPCODE_TUNE_QPSK2 0x60 // QPSK command for DVB-S2 devices
// CA Tags
#define SFE_VENDOR_TAG_CA_RESET 0x00
#define SFE_VENDOR_TAG_CA_APPLICATION_INFO 0x01
#define SFE_VENDOR_TAG_CA_PMT 0x02
#define SFE_VENDOR_TAG_CA_DATE_TIME 0x04
#define SFE_VENDOR_TAG_CA_MMI 0x05
#define SFE_VENDOR_TAG_CA_ENTER_MENU 0x07
//AVCTuner DVB identifier service_ID
#define DVB 0x20
......@@ -209,8 +216,8 @@ typedef struct _AVCRspFrm
#define Tuner_Status_Descriptor 0x80
typedef struct {
BYTE Subunit_Type;
BYTE Max_Subunit_ID;
__u8 Subunit_Type;
__u8 Max_Subunit_ID;
} SUBUNIT_INFO;
/*************************************************************
......@@ -220,12 +227,12 @@ typedef struct {
**************************************************************/
typedef struct {
BYTE Byte0;
BYTE Byte1;
BYTE Byte2;
BYTE Byte3;
BYTE Byte4;
BYTE Byte5;
__u8 Byte0;
__u8 Byte1;
__u8 Byte2;
__u8 Byte3;
__u8 Byte4;
__u8 Byte5;
}OBJECT_ID;
/*************************************************************
......@@ -234,14 +241,14 @@ typedef struct {
typedef struct
{
#ifdef __LITTLE_ENDIAN
BYTE RF_frequency_hByte:6;
BYTE raster_Frequency:2;//Bit7,6 raster frequency
__u8 RF_frequency_hByte:6;
__u8 raster_Frequency:2;//Bit7,6 raster frequency
#else
BYTE raster_Frequency:2;
BYTE RF_frequency_hByte:6;
__u8 raster_Frequency:2;
__u8 RF_frequency_hByte:6;
#endif
BYTE RF_frequency_mByte;
BYTE RF_frequency_lByte;
__u8 RF_frequency_mByte;
__u8 RF_frequency_lByte;
}FREQUENCY;
......@@ -249,63 +256,63 @@ typedef struct
typedef struct
{
BYTE Modulation :1;
BYTE FEC_inner :1;
BYTE FEC_outer :1;
BYTE Symbol_Rate :1;
BYTE Frequency :1;
BYTE Orbital_Pos :1;
BYTE Polarisation :1;
BYTE reserved_fields :1;
BYTE reserved1 :7;
BYTE Network_ID :1;
__u8 Modulation :1;
__u8 FEC_inner :1;
__u8 FEC_outer :1;
__u8 Symbol_Rate :1;
__u8 Frequency :1;
__u8 Orbital_Pos :1;
__u8 Polarisation :1;
__u8 reserved_fields :1;
__u8 reserved1 :7;
__u8 Network_ID :1;
}MULTIPLEX_VALID_FLAGS;
typedef struct
{
BYTE GuardInterval:1;
BYTE CodeRateLPStream:1;
BYTE CodeRateHPStream:1;
BYTE HierarchyInfo:1;
BYTE Constellation:1;
BYTE Bandwidth:1;
BYTE CenterFrequency:1;
BYTE reserved1:1;
BYTE reserved2:5;
BYTE OtherFrequencyFlag:1;
BYTE TransmissionMode:1;
BYTE NetworkId:1;
__u8 GuardInterval:1;
__u8 CodeRateLPStream:1;
__u8 CodeRateHPStream:1;
__u8 HierarchyInfo:1;
__u8 Constellation:1;
__u8 Bandwidth:1;
__u8 CenterFrequency:1;
__u8 reserved1:1;
__u8 reserved2:5;
__u8 OtherFrequencyFlag:1;
__u8 TransmissionMode:1;
__u8 NetworkId:1;
}MULTIPLEX_VALID_FLAGS_DVBT;
#else
typedef struct {
BYTE reserved_fields:1;
BYTE Polarisation:1;
BYTE Orbital_Pos:1;
BYTE Frequency:1;
BYTE Symbol_Rate:1;
BYTE FEC_outer:1;
BYTE FEC_inner:1;
BYTE Modulation:1;
BYTE Network_ID:1;
BYTE reserved1:7;
__u8 reserved_fields:1;
__u8 Polarisation:1;
__u8 Orbital_Pos:1;
__u8 Frequency:1;
__u8 Symbol_Rate:1;
__u8 FEC_outer:1;
__u8 FEC_inner:1;
__u8 Modulation:1;
__u8 Network_ID:1;
__u8 reserved1:7;
}MULTIPLEX_VALID_FLAGS;
typedef struct {
BYTE reserved1:1;
BYTE CenterFrequency:1;
BYTE Bandwidth:1;
BYTE Constellation:1;
BYTE HierarchyInfo:1;
BYTE CodeRateHPStream:1;
BYTE CodeRateLPStream:1;
BYTE GuardInterval:1;
BYTE NetworkId:1;
BYTE TransmissionMode:1;
BYTE OtherFrequencyFlag:1;
BYTE reserved2:5;
__u8 reserved1:1;
__u8 CenterFrequency:1;
__u8 Bandwidth:1;
__u8 Constellation:1;
__u8 HierarchyInfo:1;
__u8 CodeRateHPStream:1;
__u8 CodeRateLPStream:1;
__u8 GuardInterval:1;
__u8 NetworkId:1;
__u8 TransmissionMode:1;
__u8 OtherFrequencyFlag:1;
__u8 reserved2:5;
}MULTIPLEX_VALID_FLAGS_DVBT;
#endif
......@@ -314,47 +321,98 @@ typedef union {
MULTIPLEX_VALID_FLAGS Bits;
MULTIPLEX_VALID_FLAGS_DVBT Bits_T;
struct {
BYTE ByteHi;
BYTE ByteLo;
__u8 ByteHi;
__u8 ByteLo;
} Valid_Word;
} M_VALID_FLAGS;
typedef struct
{
#ifdef __LITTLE_ENDIAN
BYTE ActiveSystem;
BYTE reserved:5;
BYTE NoRF:1;
BYTE Moving:1;
BYTE Searching:1;
__u8 ActiveSystem;
__u8 reserved:5;
__u8 NoRF:1;
__u8 Moving:1;
__u8 Searching:1;
BYTE SelectedAntenna:7;
BYTE Input:1;
__u8 SelectedAntenna:7;
__u8 Input:1;
BYTE BER[4];
__u8 BER[4];
BYTE SignalStrength;
__u8 SignalStrength;
FREQUENCY Frequency;
BYTE ManDepInfoLength;
__u8 ManDepInfoLength;
__u8 PowerSupply:1;
__u8 FrontEndPowerStatus:1;
__u8 reserved3:1;
__u8 AntennaError:1;
__u8 FrontEndError:1;
__u8 reserved2:3;
__u8 CarrierNoiseRatio[2];
__u8 reserved4[2];
__u8 PowerSupplyVoltage;
__u8 AntennaVoltage;
__u8 FirewireBusVoltage;
__u8 CaMmi:1;
__u8 reserved5:7;
__u8 reserved6:1;
__u8 CaInitializationStatus:1;
__u8 CaErrorFlag:1;
__u8 CaDvbFlag:1;
__u8 CaModulePresentStatus:1;
__u8 CaApplicationInfo:1;
__u8 CaDateTimeRequest:1;
__u8 CaPmtReply:1;
#else
BYTE ActiveSystem;
BYTE Searching:1;
BYTE Moving:1;
BYTE NoRF:1;
BYTE reserved:5;
__u8 ActiveSystem;
__u8 Searching:1;
__u8 Moving:1;
__u8 NoRF:1;
__u8 reserved:5;
BYTE Input:1;
BYTE SelectedAntenna:7;
__u8 Input:1;
__u8 SelectedAntenna:7;
BYTE BER[4];
__u8 BER[4];
BYTE SignalStrength;
__u8 SignalStrength;
FREQUENCY Frequency;
BYTE ManDepInfoLength;
__u8 ManDepInfoLength;
__u8 reserved2:3;
__u8 FrontEndError:1;
__u8 AntennaError:1;
__u8 reserved3:1;
__u8 FrontEndPowerStatus:1;
__u8 PowerSupply:1;
__u8 CarrierNoiseRatio[2];
__u8 reserved4[2];
__u8 PowerSupplyVoltage;
__u8 AntennaVoltage;
__u8 FirewireBusVoltage;
__u8 reserved5:7;
__u8 CaMmi:1;
__u8 CaPmtReply:1;
__u8 CaDateTimeRequest:1;
__u8 CaApplicationInfo:1;
__u8 CaModulePresentStatus:1;
__u8 CaDvbFlag:1;
__u8 CaErrorFlag:1;
__u8 CaInitializationStatus:1;
__u8 reserved6:1;
#endif
} ANTENNA_INPUT_INFO; // 11 Byte
} ANTENNA_INPUT_INFO; // 22 Byte
#define LNBCONTROL_DONTCARE 0xff
......@@ -365,17 +423,27 @@ extern int AVCRecv(struct firesat *firesat, u8 *data, size_t length);
extern int AVCTuner_DSIT(struct firesat *firesat,
int Source_Plug,
struct dvb_frontend_parameters *params,
BYTE *status);
__u8 *status);
extern int AVCTunerStatus(struct firesat *firesat, ANTENNA_INPUT_INFO *antenna_input_info);
extern int AVCTuner_DSD(struct firesat *firesat, struct dvb_frontend_parameters *params, BYTE *status);
extern int AVCTuner_DSD(struct firesat *firesat, struct dvb_frontend_parameters *params, __u8 *status);
extern int AVCTuner_SetPIDs(struct firesat *firesat, unsigned char pidc, u16 pid[]);
extern int AVCTuner_GetTS(struct firesat *firesat);
extern int AVCIdentifySubunit(struct firesat *firesat, unsigned char *systemId, int *transport, int *has_ci);
extern int AVCIdentifySubunit(struct firesat *firesat, unsigned char *systemId, int *transport);
extern int AVCLNBControl(struct firesat *firesat, char voltage, char burst, char conttone, char nrdiseq, struct dvb_diseqc_master_cmd *diseqcmd);
extern int AVCSubUnitInfo(struct firesat *firesat, char *subunitcount);
extern int AVCRegisterRemoteControl(struct firesat *firesat);
extern int AVCTuner_Host2Ca(struct firesat *firesat);
extern int avc_ca_app_info(struct firesat *firesat, char *app_info,
int *length);
extern int avc_ca_info(struct firesat *firesat, char *app_info, int *length);
extern int avc_ca_reset(struct firesat *firesat);
extern int avc_ca_pmt(struct firesat *firesat, char *app_info, int length);
extern int avc_ca_get_time_date(struct firesat *firesat, int *interval);
extern int avc_ca_enter_menu(struct firesat *firesat);
extern int avc_ca_get_mmi(struct firesat *firesat, char *mmi_object,
int *length);
#endif
/*
* FireSAT DVB driver
*
* Copyright (c) ?
* 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 "cmp.h"
#include <ieee1394.h>
#include <nodemgr.h>
......@@ -10,18 +22,18 @@
typedef struct _OPCR
{
BYTE PTPConnCount : 6 ; // Point to point connect. counter
BYTE BrConnCount : 1 ; // Broadcast connection counter
BYTE OnLine : 1 ; // On Line
__u8 PTPConnCount : 6 ; // Point to point connect. counter
__u8 BrConnCount : 1 ; // Broadcast connection counter
__u8 OnLine : 1 ; // On Line
BYTE ChNr : 6 ; // Channel number
BYTE Res : 2 ; // Reserved
__u8 ChNr : 6 ; // Channel number
__u8 Res : 2 ; // Reserved
BYTE PayloadHi : 2 ; // Payoad high bits
BYTE OvhdID : 4 ; // Overhead ID
BYTE DataRate : 2 ; // Data Rate
__u8 PayloadHi : 2 ; // Payoad high bits
__u8 OvhdID : 4 ; // Overhead ID
__u8 DataRate : 2 ; // Data Rate
BYTE PayloadLo ; // Payoad low byte
__u8 PayloadLo ; // Payoad low byte
} OPCR ;
#define FIRESAT_SPEED IEEE1394_SPEED_400
......@@ -94,13 +106,13 @@ int try_CMPEstablishPPconnection(struct firesat *firesat, int output_plug, int i
u64 oPCR_address=0xfffff0000904ull+(output_plug << 2);
int result=cmp_read(firesat, &test_oPCR, oPCR_address, 4);
printk(KERN_INFO "%s: nodeid = %d\n",__func__,firesat->nodeentry->nodeid);
/* printk(KERN_INFO "%s: nodeid = %d\n",__func__,firesat->nodeentry->nodeid); */
if (result < 0) {
printk("%s: cannot read oPCR\n", __func__);
return result;
} else {
printk(KERN_INFO "%s: oPCR = %08x\n",__func__,test_oPCR);
/* printk(KERN_INFO "%s: oPCR = %08x\n",__func__,test_oPCR); */
do {
OPCR *hilf= (OPCR*) &test_oPCR;
......@@ -134,8 +146,8 @@ int try_CMPEstablishPPconnection(struct firesat *firesat, int output_plug, int i
hilf->PTPConnCount++;
new_oPCR=test_oPCR;
printk(KERN_INFO "%s: trying compare_swap...\n",__func__);
printk(KERN_INFO "%s: oPCR_old: %08x, oPCR_new: %08x\n",__func__, old_oPCR, new_oPCR);
/* printk(KERN_INFO "%s: trying compare_swap...\n",__func__); */
/* printk(KERN_INFO "%s: oPCR_old: %08x, oPCR_new: %08x\n",__func__, old_oPCR, new_oPCR); */
result=cmp_lock(firesat, &test_oPCR, oPCR_address, old_oPCR, 2);
if (result < 0) {
......@@ -169,7 +181,7 @@ int try_CMPBreakPPconnection(struct firesat *firesat, int output_plug,int iso_ch
u64 oPCR_address=0xfffff0000904ull+(output_plug << 2);
int result=cmp_read(firesat, &test_oPCR, oPCR_address, 4);
printk(KERN_INFO "%s\n",__func__);
/* printk(KERN_INFO "%s\n",__func__); */
if (result < 0) {
printk("%s: cannot read oPCR\n", __func__);
......
/*
* 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 "firesat-ci.h"
#include "firesat.h"
#include "avc_api.h"
#include <linux/dvb/ca.h>
#include <dvbdev.h>
/*
static int firesat_ca_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) {
//struct firesat *firesat = (struct firesat*)((struct dvb_device*)file->private_data)->priv;
int err;
// printk(KERN_INFO "%s: ioctl %d\n",__func__,cmd);
static unsigned int ca_debug = 0;
module_param(ca_debug, int, 0644);
MODULE_PARM_DESC(ca_debug, "debug logging of ca system, default is 0 (no)");
switch(cmd) {
case CA_RESET:
// TODO: Needs to be implemented with new AVC Vendor commands
static int firesat_ca_ready(ANTENNA_INPUT_INFO *info)
{
if (ca_debug != 0)
printk("%s: CaMmi=%d, CaInit=%d, CaError=%d, CaDvb=%d, "
"CaModule=%d, CaAppInfo=%d, CaDateTime=%d, "
"CaPmt=%d\n", __func__, info->CaMmi,
info->CaInitializationStatus, info->CaErrorFlag,
info->CaDvbFlag, info->CaModulePresentStatus,
info->CaApplicationInfo,
info->CaDateTimeRequest, info->CaPmtReply);
return info->CaInitializationStatus == 1 &&
info->CaErrorFlag == 0 &&
info->CaDvbFlag == 1 &&
info->CaModulePresentStatus == 1;
}
static int firesat_get_ca_flags(ANTENNA_INPUT_INFO *info)
{
int flags = 0;
if (info->CaModulePresentStatus == 1)
flags |= CA_CI_MODULE_PRESENT;
if (info->CaInitializationStatus == 1 &&
info->CaErrorFlag == 0 &&
info->CaDvbFlag == 1)
flags |= CA_CI_MODULE_READY;
return flags;
}
static int firesat_ca_reset(struct firesat *firesat)
{
if (ca_debug)
printk(KERN_INFO "%s: ioctl CA_RESET\n", __func__);
if (avc_ca_reset(firesat))
return -EFAULT;
return 0;
}
static int firesat_ca_get_caps(struct firesat *firesat, void *arg)
{
struct ca_caps *cap_p = (struct ca_caps*)arg;
int err = 0;
cap_p->slot_num = 1;
cap_p->slot_type = CA_CI;
cap_p->descr_num = 1;
cap_p->descr_type = CA_ECD;
if (ca_debug)
printk(KERN_INFO "%s: ioctl CA_GET_CAP\n", __func__);
return err;
}
static int firesat_ca_get_slot_info(struct firesat *firesat, void *arg)
{
ANTENNA_INPUT_INFO info;
struct ca_slot_info *slot_p = (struct ca_slot_info*)arg;
if (ca_debug)
printk(KERN_INFO "%s: ioctl CA_GET_SLOT_INFO on slot %d.\n",
__func__, slot_p->num);
if (AVCTunerStatus(firesat, &info))
return -EFAULT;
if (slot_p->num == 0) {
slot_p->type = CA_CI;
slot_p->flags = firesat_get_ca_flags(&info);
}
else {
return -EFAULT;
}
return 0;
}
static int firesat_ca_app_info(struct firesat *firesat, void *arg)
{
struct ca_msg *reply_p = (struct ca_msg*)arg;
int i;
if (avc_ca_app_info(firesat, reply_p->msg, &reply_p->length))
return -EFAULT;
if (ca_debug) {
printk(KERN_INFO "%s: Creating TAG_APP_INFO message:",
__func__);
for (i = 0; i < reply_p->length; i++)
printk("0x%02X, ", (unsigned char)reply_p->msg[i]);
printk("\n");
}
return 0;
}
static int firesat_ca_info(struct firesat *firesat, void *arg)
{
struct ca_msg *reply_p = (struct ca_msg*)arg;
int i;
if (avc_ca_info(firesat, reply_p->msg, &reply_p->length))
return -EFAULT;
if (ca_debug) {
printk(KERN_INFO "%s: Creating TAG_CA_INFO message:",
__func__);
for (i = 0; i < reply_p->length; i++)
printk("0x%02X, ", (unsigned char)reply_p->msg[i]);
printk("\n");
}
return 0;
}
static int firesat_ca_get_mmi(struct firesat *firesat, void *arg)
{
struct ca_msg *reply_p = (struct ca_msg*)arg;
int i;
if (avc_ca_get_mmi(firesat, reply_p->msg, &reply_p->length))
return -EFAULT;
if (ca_debug) {
printk(KERN_INFO "%s: Creating MMI reply INFO message:",
__func__);
for (i = 0; i < reply_p->length; i++)
printk("0x%02X, ", (unsigned char)reply_p->msg[i]);
printk("\n");
}
return 0;
}
static int firesat_ca_get_msg(struct firesat *firesat, void *arg)
{
int err;
ANTENNA_INPUT_INFO info;
switch (firesat->ca_last_command) {
case TAG_APP_INFO_ENQUIRY:
err = firesat_ca_app_info(firesat, arg);
break;
case TAG_CA_INFO_ENQUIRY:
err = firesat_ca_info(firesat, arg);
break;
case CA_GET_CAP: {
ca_caps_t *cap=(ca_caps_t*)parg;
cap->slot_num = 1;
cap->slot_type = CA_CI_LINK;
cap->descr_num = 1;
cap->descr_type = CA_DSS;
default:
if (AVCTunerStatus(firesat, &info))
err = -EFAULT;
else if (info.CaMmi == 1) {
err = firesat_ca_get_mmi(firesat, arg);
}
else {
printk(KERN_INFO "%s: Unhandled message 0x%08X\n",
__func__, firesat->ca_last_command);
err = -EFAULT;
}
}
firesat->ca_last_command = 0;
return err;
}
static int firesat_ca_pmt(struct firesat *firesat, void *arg)
{
struct ca_msg *msg_p = (struct ca_msg*)arg;
int data_pos;
if (msg_p->msg[3] & 0x80)
data_pos = (msg_p->msg[4] && 0x7F) + 4;
else
data_pos = 4;
if (avc_ca_pmt(firesat, &msg_p->msg[data_pos],
msg_p->length - data_pos))
return -EFAULT;
return 0;
}
static int firesat_ca_send_msg(struct firesat *firesat, void *arg)
{
int err;
struct ca_msg *msg_p = (struct ca_msg*)arg;
// Do we need a semaphore for this?
firesat->ca_last_command =
(msg_p->msg[0] << 16) + (msg_p->msg[1] << 8) + msg_p->msg[2];
switch (firesat->ca_last_command) {
case TAG_CA_PMT:
if (ca_debug != 0)
printk(KERN_INFO "%s: Message received: TAG_CA_PMT\n",
__func__);
err = firesat_ca_pmt(firesat, arg);
break;
case TAG_APP_INFO_ENQUIRY:
// This is all handled in ca_get_msg
if (ca_debug != 0)
printk(KERN_INFO "%s: Message received: "
"TAG_APP_INFO_ENQUIRY\n", __func__);
err = 0;
break;
}
case CA_GET_SLOT_INFO: {
ca_slot_info_t *slot=(ca_slot_info_t*)parg;
if(slot->num == 0) {
slot->type = CA_CI | CA_CI_LINK | CA_DESCR;
slot->flags = CA_CI_MODULE_PRESENT | CA_CI_MODULE_READY;
} else {
slot->type = 0;
slot->flags = 0;
}
case TAG_CA_INFO_ENQUIRY:
// This is all handled in ca_get_msg
if (ca_debug != 0)
printk(KERN_INFO "%s: Message received: "
"TAG_CA_APP_INFO_ENQUIRY\n", __func__);
err = 0;
break;
case TAG_ENTER_MENU:
if (ca_debug != 0)
printk(KERN_INFO "%s: Entering CA menu.\n", __func__);
err = avc_ca_enter_menu(firesat);
break;
default:
printk(KERN_ERR "%s: Unhandled unknown message 0x%08X\n",
__func__, firesat->ca_last_command);
err = -EFAULT;
}
return err;
}
static int firesat_ca_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *arg)
{
struct dvb_device* dvbdev = (struct dvb_device*) file->private_data;
struct firesat *firesat = dvbdev->priv;
int err;
ANTENNA_INPUT_INFO info;
switch(cmd) {
case CA_RESET:
err = firesat_ca_reset(firesat);
break;
case CA_GET_CAP:
err = firesat_ca_get_caps(firesat, arg);
break;
case CA_GET_SLOT_INFO:
err = firesat_ca_get_slot_info(firesat, arg);
break;
case CA_GET_MSG:
err = firesat_ca_get_msg(firesat, arg);
break;
case CA_SEND_MSG:
err = firesat_ca_send_msg(firesat, arg);
break;
default:
err=-EINVAL;
printk(KERN_INFO "%s: Unhandled ioctl, command: %u\n",__func__,
cmd);
err = -EOPNOTSUPP;
}
if (AVCTunerStatus(firesat, &info))
return err;
firesat_ca_ready(&info);
return err;
}
*/
static int firesat_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) {
//return dvb_usercopy(inode, file, cmd, arg, firesat_ca_do_ioctl);
return dvb_generic_ioctl(inode, file, cmd, arg);
static int firesat_get_date_time_request(struct firesat *firesat)
{
if (ca_debug)
printk(KERN_INFO "%s: Retrieving Time/Date request\n",
__func__);
if (avc_ca_get_time_date(firesat, &firesat->ca_time_interval))
return -EFAULT;
if (ca_debug)
printk(KERN_INFO "%s: Time/Date interval is %d\n",
__func__, firesat->ca_time_interval);
return 0;
}
static int firesat_ca_io_open(struct inode *inode, struct file *file) {
printk(KERN_INFO "%s!\n",__func__);
static int firesat_ca_io_open(struct inode *inode, struct file *file)
{
if (ca_debug != 0)
printk(KERN_INFO "%s\n",__func__);
return dvb_generic_open(inode, file);
}
static int firesat_ca_io_release(struct inode *inode, struct file *file) {
printk(KERN_INFO "%s!\n",__func__);
static int firesat_ca_io_release(struct inode *inode, struct file *file)
{
if (ca_debug != 0)
printk(KERN_INFO "%s\n",__func__);
return dvb_generic_release(inode, file);
}
static unsigned int firesat_ca_io_poll(struct file *file, poll_table *wait) {
// printk(KERN_INFO "%s!\n",__func__);
static unsigned int firesat_ca_io_poll(struct file *file, poll_table *wait)
{
if (ca_debug != 0)
printk(KERN_INFO "%s\n",__func__);
return POLLIN;
}
......@@ -68,7 +305,7 @@ static struct file_operations firesat_ca_fops = {
.owner = THIS_MODULE,
.read = NULL, // There is no low level read anymore
.write = NULL, // There is no low level write anymore
.ioctl = firesat_ca_ioctl,
.ioctl = dvb_generic_ioctl,
.open = firesat_ca_io_open,
.release = firesat_ca_io_release,
.poll = firesat_ca_io_poll,
......@@ -80,16 +317,37 @@ static struct dvb_device firesat_ca = {
.readers = 1,
.writers = 1,
.fops = &firesat_ca_fops,
.kernel_ioctl = firesat_ca_ioctl,
};
int firesat_ca_init(struct firesat *firesat) {
int ret = dvb_register_device(firesat->adapter, &firesat->cadev, &firesat_ca, firesat, DVB_DEVICE_CA);
if(ret) return ret;
int firesat_ca_init(struct firesat *firesat)
{
int err;
ANTENNA_INPUT_INFO info;
// avoid unnecessary delays, we're not talking to the CI yet anyways
return 0;
if (AVCTunerStatus(firesat, &info))
return -EINVAL;
if (firesat_ca_ready(&info)) {
err = dvb_register_device(firesat->adapter,
&firesat->cadev,
&firesat_ca, firesat,
DVB_DEVICE_CA);
if (info.CaApplicationInfo == 0)
printk(KERN_ERR "%s: CaApplicationInfo is not set.\n",
__func__);
if (info.CaDateTimeRequest == 1)
firesat_get_date_time_request(firesat);
}
else
err = -EFAULT;
return err;
}
void firesat_ca_release(struct firesat *firesat) {
void firesat_ca_release(struct firesat *firesat)
{
if (firesat->cadev)
dvb_unregister_device(firesat->cadev);
}
/*
* FireSAT DVB driver
*
* Copyright (c) ?
* 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.
*/
#ifndef __FIRESAT_H
#define __FIRESAT_H
......@@ -6,15 +18,108 @@
#include "dvb_demux.h"
#include "dvb_net.h"
#include <linux/version.h>
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
#include <linux/semaphore.h>
#endif
#include <linux/dvb/frontend.h>
#include <linux/dvb/dmx.h>
#include <iso.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
enum model_type {
FireSAT_DVB_S = 1,
FireSAT_DVB_C = 2,
FireSAT_DVB_T = 3,
FireSAT_DVB_S2 = 4
FireSAT_DVB_S = 1,
FireSAT_DVB_C = 2,
FireSAT_DVB_T = 3,
FireSAT_DVB_S2 = 4
};
struct firesat {
......@@ -31,12 +136,13 @@ struct firesat {
struct dvb_frontend *fe;
struct dvb_device *cadev;
int has_ci;
int ca_last_command;
int ca_time_interval;
struct semaphore avc_sem;
atomic_t avc_reply_received;
atomic_t avc_reply_received;
atomic_t reschedule_remotecontrol;
atomic_t reschedule_remotecontrol;
struct firesat_channel {
struct firesat *firesat;
......@@ -53,20 +159,54 @@ struct firesat {
void *respfrm;
int resp_length;
// nodeid_t nodeid;
struct hpsb_host *host;
struct hpsb_host *host;
u64 guid; /* GUID of this node */
u32 guid_vendor_id; /* Top 24bits of guid */
struct node_entry *nodeentry;
enum model_type type;
char subunit;
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 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 list_head list;
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 struct list_head firesat_list;
......@@ -76,11 +216,15 @@ extern spinlock_t firesat_list_lock;
extern int firesat_start_feed(struct dvb_demux_feed *dvbdmxfeed);
extern int firesat_stop_feed(struct dvb_demux_feed *dvbdmxfeed);
extern int firesat_dvbdev_init(struct firesat *firesat,
struct device *dev,
struct dvb_frontend *fe);
struct device *dev,
struct dvb_frontend *fe);
/* firesat_fe.c */
extern int firesat_frontend_attach(struct firesat *firesat, struct dvb_frontend *fe);
extern int firesat_frontend_attach(struct firesat *firesat,
struct dvb_frontend *fe);
/* firesat_iso.c */
extern int setup_iso_channel(struct firesat *firesat);
extern void tear_down_iso_channel(struct firesat *firesat);
#endif
......@@ -3,6 +3,7 @@
*
* Copyright (c) 2004 Andreas Monitzer <andy@monitzer.com>
* Copyright (c) 2007-2008 Ben Backx <ben@bbackx.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
......@@ -18,7 +19,6 @@
#include <linux/time.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/semaphore.h>
#include <ieee1394_hotplug.h>
#include <nodemgr.h>
#include <highlevel.h>
......@@ -79,11 +79,6 @@ static void firesat_add_host(struct hpsb_host *host);
static void firesat_remove_host(struct hpsb_host *host);
static void firesat_host_reset(struct hpsb_host *host);
/*
static void iso_receive(struct hpsb_host *host, int channel, quadlet_t *data,
size_t length);
*/
static void fcp_request(struct hpsb_host *host,
int nodeid,
int direction,
......@@ -96,7 +91,6 @@ static struct hpsb_highlevel firesat_highlevel = {
.add_host = firesat_add_host,
.remove_host = firesat_remove_host,
.host_reset = firesat_host_reset,
// FIXME .iso_receive = iso_receive,
.fcp_request = fcp_request,
};
......@@ -127,100 +121,6 @@ static void firesat_host_reset(struct hpsb_host *host)
printk(KERN_INFO "FireSAT host_reset (nodeid = 0x%x, hosts active = %d)\n",host->node_id,host->nodes_active);
}
struct firewireheader {
union {
struct {
unsigned char tcode:4;
unsigned char sy:4;
unsigned char tag:2;
unsigned char channel:6;
unsigned char length_l;
unsigned char length_h;
} hdr;
unsigned long val;
};
};
struct CIPHeader {
union {
struct {
unsigned char syncbits:2;
unsigned char sid:6;
unsigned char dbs;
unsigned char fn:2;
unsigned char qpc:3;
unsigned char sph:1;
unsigned char rsv:2;
unsigned char dbc;
unsigned char syncbits2:2;
unsigned char fmt:6;
unsigned long fdf:24;
} cip;
unsigned long long val;
};
};
struct MPEG2Header {
union {
struct {
unsigned char sync; // must be 0x47
unsigned char transport_error_indicator:1;
unsigned char payload_unit_start_indicator:1;
unsigned char transport_priority:1;
unsigned short pid:13;
unsigned char transport_scrambling_control:2;
unsigned char adaption_field_control:2;
unsigned char continuity_counter:4;
} hdr;
unsigned long val;
};
};
#if 0
static void iso_receive(struct hpsb_host *host,
int channel,
quadlet_t *data,
size_t length)
{
struct firesat *firesat = NULL;
struct firesat *firesat_entry;
unsigned long flags;
// printk(KERN_INFO "FireSAT iso_receive: channel %d, length = %d\n", channel, length);
if (length <= 12)
return; // ignore empty packets
else {
spin_lock_irqsave(&firesat_list_lock, flags);
list_for_each_entry(firesat_entry,&firesat_list,list) {
if(firesat_entry->host == host && firesat_entry->isochannel == channel) {
firesat=firesat_entry;
break;
}
}
spin_unlock_irqrestore(&firesat_list_lock, flags);
if (firesat) {
char *buf= ((char*)data) + sizeof(struct firewireheader)+sizeof(struct CIPHeader);
int count = (length-sizeof(struct CIPHeader)) / 192;
// printk(KERN_INFO "%s: length = %u\n data[0] = %08x\n data[1] = %08x\n data[2] = %08x\n data[3] = %08x\n data[4] = %08x\n",__func__, length, data[0],data[1],data[2],data[3],data[4]);
while (count--) {
if (buf[sizeof(quadlet_t) /*timestamp*/] == 0x47)
dvb_dmx_swfilter_packets(&firesat->demux, &buf[sizeof(quadlet_t)], 1);
else
printk("%s: invalid packet, skipping\n", __func__);
buf += 188 + sizeof (quadlet_t) /* timestamp */;
}
}
}
}
#endif
static void fcp_request(struct hpsb_host *host,
int nodeid,
int direction,
......@@ -251,7 +151,9 @@ static void fcp_request(struct hpsb_host *host,
AVCRecv(firesat,data,length);
else
printk("%s: received fcp request from unknown source, ignored\n", __func__);
} // else ignore
}
else
printk("%s: received invalid fcp request, ignored\n", __func__);
}
static int firesat_probe(struct device *dev)
......@@ -260,7 +162,6 @@ static int firesat_probe(struct device *dev)
struct firesat *firesat;
struct dvb_frontend *fe;
unsigned long flags;
int result;
unsigned char subunitcount = 0xff, subunit;
struct firesat **firesats = kmalloc(sizeof (void*) * 2,GFP_KERNEL);
int kv_len;
......@@ -298,6 +199,7 @@ static int firesat_probe(struct device *dev)
firesat->isochannel = -1;
firesat->tone = 0xff;
firesat->voltage = 0xff;
firesat->fe = fe;
if (!(firesat->respfrm = kmalloc(sizeof (AVCRspFrm), GFP_KERNEL))) {
printk("%s: couldn't allocate memory.\n", __func__);
......@@ -357,7 +259,7 @@ static int firesat_probe(struct device *dev)
}
kfree(kv_buf);
if (AVCIdentifySubunit(firesat, NULL, (int*)&firesat->type, &firesat->has_ci)) {
if (AVCIdentifySubunit(firesat, NULL, (int*)&firesat->type)) {
printk("%s: cannot identify subunit %d\n", __func__, subunit);
spin_lock_irqsave(&firesat_list_lock, flags);
list_del(&firesat->list);
......@@ -382,7 +284,6 @@ static int firesat_probe(struct device *dev)
static int firesat_remove(struct device *dev)
{
struct unit_directory *ud = container_of(dev, struct unit_directory, device);
struct dvb_frontend* fe;
struct firesat **firesats = ud->device.driver_data;
int k;
unsigned long flags;
......@@ -390,18 +291,9 @@ static int firesat_remove(struct device *dev)
if (firesats) {
for (k = 0; k < 2; k++)
if (firesats[k]) {
if (firesats[k]->has_ci)
firesat_ca_release(firesats[k]);
#if 0
if (!(fe = kmalloc(sizeof (struct dvb_frontend), GFP_KERNEL))) {
fe->ops = firesat_ops;
fe->dvb = firesats[k]->adapter;
dvb_unregister_frontend(fe);
kfree(fe);
}
#endif
dvb_unregister_frontend(firesats[k]->fe);
dvb_net_release(&firesats[k]->dvbnet);
firesats[k]->demux.dmx.close(&firesats[k]->demux.dmx);
firesats[k]->demux.dmx.remove_frontend(&firesats[k]->demux.dmx, &firesats[k]->frontend);
......@@ -413,6 +305,7 @@ static int firesat_remove(struct device *dev)
list_del(&firesats[k]->list);
spin_unlock_irqrestore(&firesat_list_lock, flags);
kfree(firesats[k]->fe);
kfree(firesats[k]->adapter);
kfree(firesats[k]->respfrm);
kfree(firesats[k]);
......
/*
* FireSAT DVB driver
*
* Copyright (c) ?
* 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/init.h>
#include <linux/slab.h>
#include <linux/wait.h>
......@@ -6,7 +18,6 @@
#include <linux/time.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/semaphore.h>
#include <ieee1394_hotplug.h>
#include <nodemgr.h>
#include <highlevel.h>
......@@ -26,13 +37,13 @@ static struct firesat_channel *firesat_channel_allocate(struct firesat *firesat)
{
int k;
printk(KERN_INFO "%s\n", __func__);
//printk(KERN_INFO "%s\n", __func__);
if (down_interruptible(&firesat->demux_sem))
return NULL;
for (k = 0; k < 16; k++) {
printk(KERN_INFO "%s: channel %d: active = %d, pid = 0x%x\n",__func__,k,firesat->channel[k].active,firesat->channel[k].pid);
//printk(KERN_INFO "%s: channel %d: active = %d, pid = 0x%x\n",__func__,k,firesat->channel[k].active,firesat->channel[k].pid);
if (firesat->channel[k].active == 0) {
firesat->channel[k].active = 1;
......@@ -82,14 +93,15 @@ int firesat_start_feed(struct dvb_demux_feed *dvbdmxfeed)
int pidc,k;
u16 pids[16];
printk(KERN_INFO "%s (pid %u)\n",__func__,dvbdmxfeed->pid);
// printk(KERN_INFO "%s (pid %u)\n", __func__, dvbdmxfeed->pid);
switch (dvbdmxfeed->type) {
case DMX_TYPE_TS:
case DMX_TYPE_SEC:
break;
default:
printk("%s: invalid type %u\n",__func__,dvbdmxfeed->type);
printk(KERN_ERR "%s: invalid type %u\n",
__func__, dvbdmxfeed->type);
return -EINVAL;
}
......@@ -110,7 +122,8 @@ int firesat_start_feed(struct dvb_demux_feed *dvbdmxfeed)
channel = firesat_channel_allocate(firesat);
break;
default:
printk("%s: invalid pes type %u\n",__func__, dvbdmxfeed->pes_type);
printk(KERN_ERR "%s: invalid pes type %u\n",
__func__, dvbdmxfeed->pes_type);
return -EINVAL;
}
} else {
......@@ -118,7 +131,7 @@ int firesat_start_feed(struct dvb_demux_feed *dvbdmxfeed)
}
if (!channel) {
printk("%s: busy!\n", __func__);
printk(KERN_ERR "%s: busy!\n", __func__);
return -EBUSY;
}
......@@ -131,22 +144,23 @@ int firesat_start_feed(struct dvb_demux_feed *dvbdmxfeed)
if (firesat_channel_collect(firesat, &pidc, pids)) {
firesat_channel_release(firesat, channel);
printk(KERN_ERR "%s: could not collect pids!\n", __func__);
return -EINTR;
}
if(dvbdmxfeed->pid == 8192) {
if((k=AVCTuner_GetTS(firesat))) {
if((k = AVCTuner_GetTS(firesat))) {
firesat_channel_release(firesat, channel);
printk("%s: AVCTuner_GetTS failed with error %d\n",
__func__,k);
__func__, k);
return k;
}
}
else {
if((k=AVCTuner_SetPIDs(firesat, pidc, pids))) {
if((k = AVCTuner_SetPIDs(firesat, pidc, pids))) {
firesat_channel_release(firesat, channel);
printk("%s: AVCTuner_SetPIDs failed with error %d\n",
__func__,k);
__func__, k);
return k;
}
}
......@@ -161,7 +175,7 @@ int firesat_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
int k, l = 0;
u16 pids[16];
printk(KERN_INFO "%s (pid %u)\n", __func__, dvbdmxfeed->pid);
//printk(KERN_INFO "%s (pid %u)\n", __func__, dvbdmxfeed->pid);
if (dvbdmxfeed->type == DMX_TYPE_TS && !((dvbdmxfeed->ts_type & TS_PACKET) &&
(demux->dmx.frontend->source != DMX_MEMORY_FE))) {
......@@ -189,12 +203,13 @@ int firesat_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
// list except channel to be removed
for (k = 0; k < 16; k++)
if (firesat->channel[k].active == 1)
if (firesat->channel[k].active == 1) {
if (&firesat->channel[k] !=
(struct firesat_channel *)dvbdmxfeed->priv)
pids[l++] = firesat->channel[k].pid;
else
firesat->channel[k].active = 0;
}
if ((k = AVCTuner_SetPIDs(firesat, l, pids))) {
up(&firesat->demux_sem);
......@@ -214,8 +229,6 @@ int firesat_dvbdev_init(struct firesat *firesat,
{
int result;
firesat->has_ci = 1; // TEMP workaround
#if 0
switch (firesat->type) {
case FireSAT_DVB_S:
......@@ -254,7 +267,7 @@ int firesat_dvbdev_init(struct firesat *firesat,
return -ENOMEM;
}
if ((result = dvb_register_adapter(firesat->adapter,
if ((result = DVB_REGISTER_ADAPTER(firesat->adapter,
firesat->model_name,
THIS_MODULE,
dev, adapter_nr)) < 0) {
......@@ -271,6 +284,7 @@ int firesat_dvbdev_init(struct firesat *firesat,
return result;
}
memset(&firesat->demux, 0, sizeof(struct dvb_demux));
firesat->demux.dmx.capabilities = 0/*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/;
firesat->demux.priv = (void *)firesat;
......@@ -343,8 +357,9 @@ int firesat_dvbdev_init(struct firesat *firesat,
return result;
}
if (firesat->has_ci)
firesat_ca_init(firesat);
return 0;
}
/*
* FireSAT DVB driver
*
* Copyright (c) ?
* 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/init.h>
#include <linux/slab.h>
#include <linux/wait.h>
......@@ -6,7 +18,6 @@
#include <linux/time.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/semaphore.h>
#include <ieee1394_hotplug.h>
#include <nodemgr.h>
#include <highlevel.h>
......@@ -22,22 +33,29 @@
static int firesat_dvb_init(struct dvb_frontend *fe)
{
int result;
struct firesat *firesat = fe->sec_priv;
printk("fdi: 1\n");
// printk("fdi: 1\n");
firesat->isochannel = firesat->adapter->num; //<< 1 | (firesat->subunit & 0x1); // ### ask IRM
printk("fdi: 2\n");
try_CMPEstablishPPconnection(firesat, firesat->subunit, firesat->isochannel);
printk("fdi: 3\n");
//FIXME hpsb_listen_channel(&firesat_highlevel, firesat->host, firesat->isochannel);
printk("fdi: 4\n");
return 0;
// printk("fdi: 2\n");
result = try_CMPEstablishPPconnection(firesat, firesat->subunit, firesat->isochannel);
if (result != 0) {
printk(KERN_ERR "Could not establish point to point "
"connection.\n");
return -1;
}
// printk("fdi: 3\n");
result = setup_iso_channel(firesat);
// printk("fdi: 4. Result was %d\n", result);
return result;
}
static int firesat_sleep(struct dvb_frontend *fe)
{
struct firesat *firesat = fe->sec_priv;
//FIXME hpsb_unlisten_channel(&firesat_highlevel, firesat->host, firesat->isochannel);
tear_down_iso_channel(firesat);
try_CMPBreakPPconnection(firesat, firesat->subunit, firesat->isochannel);
firesat->isochannel = -1;
return 0;
......@@ -83,19 +101,20 @@ static int firesat_read_status (struct dvb_frontend *fe, fe_status_t *status)
if (AVCTunerStatus(firesat, &info))
return -EINVAL;
if (info.NoRF)
if (info.NoRF) {
*status = 0;
else
*status = *status = FE_HAS_SIGNAL |
FE_HAS_VITERBI |
FE_HAS_SYNC |
FE_HAS_CARRIER |
FE_HAS_LOCK;
} else {
*status = FE_HAS_SIGNAL |
FE_HAS_VITERBI |
FE_HAS_SYNC |
FE_HAS_CARRIER |
FE_HAS_LOCK;
}
return 0;
}
static int firesat_read_ber (struct dvb_frontend *fe, u32 *ber)
static int firesat_read_ber(struct dvb_frontend *fe, u32 *ber)
{
struct firesat *firesat = fe->sec_priv;
ANTENNA_INPUT_INFO info;
......@@ -103,10 +122,10 @@ static int firesat_read_ber (struct dvb_frontend *fe, u32 *ber)
if (AVCTunerStatus(firesat, &info))
return -EINVAL;
*ber = ((info.BER[0] << 24) & 0xff) |
((info.BER[1] << 16) & 0xff) |
((info.BER[2] << 8) & 0xff) |
(info.BER[3] & 0xff);
*ber = (info.BER[0] << 24) |
(info.BER[1] << 16) |
(info.BER[2] << 8) |
info.BER[3];
return 0;
}
......@@ -115,19 +134,29 @@ static int firesat_read_signal_strength (struct dvb_frontend *fe, u16 *strength)
{
struct firesat *firesat = fe->sec_priv;
ANTENNA_INPUT_INFO info;
u16 *signal = strength;
if (AVCTunerStatus(firesat, &info))
return -EINVAL;
*signal = info.SignalStrength;
*strength = info.SignalStrength << 8;
return 0;
}
static int firesat_read_snr(struct dvb_frontend *fe, u16 *snr)
{
return -EOPNOTSUPP;
struct firesat *firesat = fe->sec_priv;
ANTENNA_INPUT_INFO info;
if (AVCTunerStatus(firesat, &info))
return -EINVAL;
*snr = (info.CarrierNoiseRatio[0] << 8) +
info.CarrierNoiseRatio[1];
*snr *= 257;
// C/N[dB] = -10 * log10(snr / 65535)
return 0;
}
static int firesat_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ucblocks)
......@@ -192,14 +221,13 @@ int firesat_frontend_attach(struct firesat *firesat, struct dvb_frontend *fe)
firesat->frontend_info = &firesat_T_frontend_info;
break;
default:
// printk("%s: unknown model type 0x%x on subunit %d!\n",
// __func__, firesat->type,subunit);
printk("%s: unknown model type 0x%x !\n",
__func__, firesat->type);
firesat->model_name = "Unknown";
firesat->frontend_info = NULL;
}
fe->ops = firesat_ops;
fe->ops.info = *(firesat->frontend_info);
fe->dvb = firesat->adapter;
return 0;
......
/*
* 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 "firesat.h"
static void rawiso_activity_cb(struct hpsb_iso *iso);
void tear_down_iso_channel(struct firesat *firesat)
{
if (firesat->iso_handle != NULL) {
hpsb_iso_stop(firesat->iso_handle);
hpsb_iso_shutdown(firesat->iso_handle);
}
firesat->iso_handle = NULL;
}
int setup_iso_channel(struct firesat *firesat)
{
int result;
firesat->iso_handle =
hpsb_iso_recv_init(firesat->host,
256 * 200, //data_buf_size,
256, //buf_packets,
firesat->isochannel,
HPSB_ISO_DMA_DEFAULT, //dma_mode,
-1, //stat.config.irq_interval,
rawiso_activity_cb);
if (firesat->iso_handle == NULL) {
printk(KERN_ERR "Cannot initialize iso receive.\n");
return -EINVAL;
}
result = hpsb_iso_recv_start(firesat->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 j; */
unsigned int packet;
unsigned long flags;
struct firesat *firesat = NULL;
struct firesat *firesat_iterator;
spin_lock_irqsave(&firesat_list_lock, flags);
list_for_each_entry(firesat_iterator, &firesat_list, list) {
if(firesat_iterator->iso_handle == iso) {
firesat = firesat_iterator;
break;
}
}
spin_unlock_irqrestore(&firesat_list_lock, flags);
if (firesat) {
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
/* printk("%s: Handling packets (%d): ", __func__, */
/* iso->infos[packet].len); */
/* for (j = 0; j < iso->infos[packet].len - */
/* sizeof(struct CIPHeader); j++) */
/* printk("%02X,", buf[j]); */
/* printk("\n"); */
while (count --) {
if (buf[sizeof(struct firewireheader)] == 0x47)
dvb_dmx_swfilter_packets(&firesat->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));
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册