Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit df4846c3 authored by Henrik Kurelid's avatar Henrik Kurelid Committed by Stefan Richter
Browse files

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: default avatarHenrik Kurelid <henrik@kurelid.se>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> (rebased, whitespace)
parent 2c228614
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
firesat-objs := firesat_1394.o	\
		firesat_dvb.o	\
		firesat_fe.o	\
		firesat_iso.o	\
		avc_api.o	\
		cmp.o		\
		firesat-rc.o	\
+619 −151

File changed.

Preview size limit exceeded, changes collapsed.

+182 −114
Original line number Diff line number Diff line
@@ -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
+26 −14
Original line number Diff line number Diff line
/*
 * 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__);
+300 −42
Original line number Diff line number Diff line
/*
 * 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
		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;
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;
}

		err = 0;
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;
	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;
		}
	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;
	}
	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 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);
}
Loading