mirror of
https://github.com/torvalds/linux.git
synced 2024-12-22 02:52:56 +00:00
154907957f
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: Stefan Richter <stefanr@s5r6.in-berlin.de>
261 lines
5.7 KiB
C
261 lines
5.7 KiB
C
/*
|
|
* 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/dvb/ca.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/module.h>
|
|
|
|
#include <dvbdev.h>
|
|
|
|
#include "firedtv.h"
|
|
|
|
#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 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(struct firedtv_tuner_status *stat)
|
|
{
|
|
int flags = 0;
|
|
|
|
if (stat->ca_module_present_status == 1)
|
|
flags |= CA_CI_MODULE_PRESENT;
|
|
if (stat->ca_initialization_status == 1 &&
|
|
stat->ca_error_flag == 0 &&
|
|
stat->ca_dvb_flag == 1)
|
|
flags |= CA_CI_MODULE_READY;
|
|
return flags;
|
|
}
|
|
|
|
static int fdtv_ca_reset(struct firedtv *fdtv)
|
|
{
|
|
return avc_ca_reset(fdtv) ? -EFAULT : 0;
|
|
}
|
|
|
|
static int fdtv_ca_get_caps(void *arg)
|
|
{
|
|
struct ca_caps *cap = arg;
|
|
|
|
cap->slot_num = 1;
|
|
cap->slot_type = CA_CI;
|
|
cap->descr_num = 1;
|
|
cap->descr_type = CA_ECD;
|
|
return 0;
|
|
}
|
|
|
|
static int fdtv_ca_get_slot_info(struct firedtv *fdtv, void *arg)
|
|
{
|
|
struct firedtv_tuner_status stat;
|
|
struct ca_slot_info *slot = arg;
|
|
|
|
if (avc_tuner_status(fdtv, &stat))
|
|
return -EFAULT;
|
|
|
|
if (slot->num != 0)
|
|
return -EFAULT;
|
|
|
|
slot->type = CA_CI;
|
|
slot->flags = fdtv_get_ca_flags(&stat);
|
|
return 0;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
static int fdtv_ca_info(struct firedtv *fdtv, void *arg)
|
|
{
|
|
struct ca_msg *reply = arg;
|
|
|
|
return avc_ca_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
static int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg)
|
|
{
|
|
struct firedtv_tuner_status stat;
|
|
int err;
|
|
|
|
switch (fdtv->ca_last_command) {
|
|
case EN50221_TAG_APP_INFO_ENQUIRY:
|
|
err = fdtv_ca_app_info(fdtv, arg);
|
|
break;
|
|
case EN50221_TAG_CA_INFO_ENQUIRY:
|
|
err = fdtv_ca_info(fdtv, arg);
|
|
break;
|
|
default:
|
|
if (avc_tuner_status(fdtv, &stat))
|
|
err = -EFAULT;
|
|
else if (stat.ca_mmi == 1)
|
|
err = fdtv_ca_get_mmi(fdtv, arg);
|
|
else {
|
|
dev_info(fdtv->device, "unhandled CA message 0x%08x\n",
|
|
fdtv->ca_last_command);
|
|
err = -EFAULT;
|
|
}
|
|
}
|
|
fdtv->ca_last_command = 0;
|
|
return err;
|
|
}
|
|
|
|
static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)
|
|
{
|
|
struct ca_msg *msg = arg;
|
|
int data_pos;
|
|
int data_length;
|
|
int i;
|
|
|
|
data_pos = 4;
|
|
if (msg->msg[3] & 0x80) {
|
|
data_length = 0;
|
|
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;
|
|
}
|
|
|
|
static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg)
|
|
{
|
|
struct ca_msg *msg = arg;
|
|
int err;
|
|
|
|
/* Do we need a semaphore for this? */
|
|
fdtv->ca_last_command =
|
|
(msg->msg[0] << 16) + (msg->msg[1] << 8) + msg->msg[2];
|
|
switch (fdtv->ca_last_command) {
|
|
case EN50221_TAG_CA_PMT:
|
|
err = fdtv_ca_pmt(fdtv, arg);
|
|
break;
|
|
case EN50221_TAG_APP_INFO_ENQUIRY:
|
|
/* handled in ca_get_msg */
|
|
err = 0;
|
|
break;
|
|
case EN50221_TAG_CA_INFO_ENQUIRY:
|
|
/* handled in ca_get_msg */
|
|
err = 0;
|
|
break;
|
|
case EN50221_TAG_ENTER_MENU:
|
|
err = avc_ca_enter_menu(fdtv);
|
|
break;
|
|
default:
|
|
dev_err(fdtv->device, "unhandled CA message 0x%08x\n",
|
|
fdtv->ca_last_command);
|
|
err = -EFAULT;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
static int fdtv_ca_ioctl(struct inode *inode, struct file *file,
|
|
unsigned int cmd, void *arg)
|
|
{
|
|
struct dvb_device *dvbdev = file->private_data;
|
|
struct firedtv *fdtv = dvbdev->priv;
|
|
struct firedtv_tuner_status stat;
|
|
int err;
|
|
|
|
switch (cmd) {
|
|
case CA_RESET:
|
|
err = fdtv_ca_reset(fdtv);
|
|
break;
|
|
case CA_GET_CAP:
|
|
err = fdtv_ca_get_caps(arg);
|
|
break;
|
|
case CA_GET_SLOT_INFO:
|
|
err = fdtv_ca_get_slot_info(fdtv, arg);
|
|
break;
|
|
case CA_GET_MSG:
|
|
err = fdtv_ca_get_msg(fdtv, arg);
|
|
break;
|
|
case CA_SEND_MSG:
|
|
err = fdtv_ca_send_msg(fdtv, arg);
|
|
break;
|
|
default:
|
|
dev_info(fdtv->device, "unhandled CA ioctl %u\n", cmd);
|
|
err = -EOPNOTSUPP;
|
|
}
|
|
|
|
/* FIXME Is this necessary? */
|
|
avc_tuner_status(fdtv, &stat);
|
|
|
|
return err;
|
|
}
|
|
|
|
static unsigned int fdtv_ca_io_poll(struct file *file, poll_table *wait)
|
|
{
|
|
return POLLIN;
|
|
}
|
|
|
|
static struct file_operations fdtv_ca_fops = {
|
|
.owner = THIS_MODULE,
|
|
.ioctl = dvb_generic_ioctl,
|
|
.open = dvb_generic_open,
|
|
.release = dvb_generic_release,
|
|
.poll = fdtv_ca_io_poll,
|
|
};
|
|
|
|
static struct dvb_device fdtv_ca = {
|
|
.users = 1,
|
|
.readers = 1,
|
|
.writers = 1,
|
|
.fops = &fdtv_ca_fops,
|
|
.kernel_ioctl = fdtv_ca_ioctl,
|
|
};
|
|
|
|
int fdtv_ca_register(struct firedtv *fdtv)
|
|
{
|
|
struct firedtv_tuner_status stat;
|
|
int err;
|
|
|
|
if (avc_tuner_status(fdtv, &stat))
|
|
return -EINVAL;
|
|
|
|
if (!fdtv_ca_ready(&stat))
|
|
return -EFAULT;
|
|
|
|
err = dvb_register_device(&fdtv->adapter, &fdtv->cadev,
|
|
&fdtv_ca, fdtv, DVB_DEVICE_CA);
|
|
|
|
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;
|
|
}
|
|
|
|
void fdtv_ca_release(struct firedtv *fdtv)
|
|
{
|
|
if (fdtv->cadev)
|
|
dvb_unregister_device(fdtv->cadev);
|
|
}
|