/*
* DVB USB framework
*
* Copyright (C) 2004-6 Patrick Boettcher <patrick.boettcher@desy.de>
* Copyright (C) 2012 Antti Palosaari <crope@iki.fi>
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "dvb_usb_common.h"
int dvb_usbv2_disable_rc_polling;
module_param_named(disable_rc_polling, dvb_usbv2_disable_rc_polling, int, 0644);
MODULE_PARM_DESC(disable_rc_polling,
"disable remote control polling (default: 0)");
static int dvb_usb_force_pid_filter_usage;
module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage,
int, 0444);
MODULE_PARM_DESC(force_pid_filter_usage, "force all DVB USB devices to use a " \
"PID filter, if any (default: 0)");
static int dvb_usbv2_download_firmware(struct dvb_usb_device *d, const char *name)
{
int ret;
const struct firmware *fw;
dev_dbg(&d->udev->dev, "%s:\n", __func__);
if (!d->props->download_firmware) {
ret = -EINVAL;
goto err;
}
ret = request_firmware(&fw, name, &d->udev->dev);
if (ret < 0) {
dev_err(&d->udev->dev, "%s: Did not find the firmware file "\
"'%s'. Please see linux/Documentation/dvb/ " \
"for more details on firmware-problems. " \
"Status %d\n", KBUILD_MODNAME, name, ret);
goto err;
}
dev_info(&d->udev->dev, "%s: downloading firmware from file '%s'\n",
KBUILD_MODNAME, name);
ret = d->props->download_firmware(d, fw);
release_firmware(fw);
if (ret < 0)
goto err;
return ret;
err:
dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
static int dvb_usbv2_i2c_init(struct dvb_usb_device *d)
{
int ret;
dev_dbg(&d->udev->dev, "%s:\n", __func__);
if (!d->props->i2c_algo)
return 0;
strlcpy(d->i2c_adap.name, d->name, sizeof(d->i2c_adap.name));
d->i2c_adap.algo = d->props->i2c_algo;
d->i2c_adap.dev.parent = &d->udev->dev;
i2c_set_adapdata(&d->i2c_adap, d);
ret = i2c_add_adapter(&d->i2c_adap);
if (ret < 0) {
d->i2c_adap.algo = NULL;
dev_err(&d->udev->dev, "%s: i2c_add_adapter() failed=%d\n",
KBUILD_MODNAME, ret);
goto err;
}
return 0;
err:
dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
static int dvb_usbv2_i2c_exit(struct dvb_usb_device *d)
{
dev_dbg(&d->udev->dev, "%s:\n", __func__);
if (d->i2c_adap.algo)
i2c_del_adapter(&d->i2c_adap);
return 0;
}
static void dvb_usb_read_remote_control(struct work_struct *work)
{
struct dvb_usb_device *d = container_of(work,
struct dvb_usb_device, rc_query_work.work);
int ret;
/*
* When the parameter has been set to 1 via sysfs while the
* driver was running, or when bulk mode is enabled after IR init.
*/
if (dvb_usbv2_disable_rc_polling || d->rc.bulk_mode)
return;
ret = d->rc.query(d);
if (ret < 0) {
dev_err(&d->udev->dev, "%s: rc.query() failed=%d\n",
KBUILD_MODNAME, ret);
return; /* stop polling */
}
schedule_delayed_work(&d->rc_query_work,
msecs_to_jiffies(d->rc.interval));
}
static int dvb_usbv2_remote_init(struct dvb_usb_device *d)
{
int ret;
struct rc_dev *dev;
dev_dbg(&d->udev->dev, "%s:\n", __func__);
if (dvb_usbv2_disable_rc_polling || !d->props->get_rc_config)
return 0;
d