/* DVB USB compliant linux driver for MSI Mega Sky 580 DVB-T USB2.0 receiver
*
* Copyright (C) 2006 Aapo Tahkola (aet@rasterburn.org)
*
* 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, version 2.
*
* see Documentation/dvb/README.dvb-usb for more information
*/
#include "m920x.h"
#include "mt352.h"
#include "mt352_priv.h"
#include "qt1010.h"
#include "tda1004x.h"
#include "tda827x.h"
/* debug */
static int dvb_usb_m920x_debug;
module_param_named(debug,dvb_usb_m920x_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
static int m920x_set_filter(struct dvb_usb_device *d, int type, int idx, int pid);
static inline int m920x_read(struct usb_device *udev, u8 request, u16 value,
u16 index, void *data, int size)
{
int ret;
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
request, USB_TYPE_VENDOR | USB_DIR_IN,
value, index, data, size, 2000);
if (ret < 0) {
printk(KERN_INFO "m920x_read = error: %d\n", ret);
return ret;
}
if (ret != size) {
deb("m920x_read = no data\n");
return -EIO;
}
return 0;
}
static inline int m920x_write(struct usb_device *udev, u8 request,
u16 value, u16 index)
{
int ret;
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
request, USB_TYPE_VENDOR | USB_DIR_OUT,
value, index, NULL, 0, 2000);
return ret;
}
static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq)
{
int ret = 0, i, epi, flags = 0;
int adap_enabled[M9206_MAX_ADAPTERS] = { 0 };
/* Remote controller init. */
if (d->props.rc_query) {
deb("Initialising remote control\n");
while (rc_seq->address) {
if ((ret = m920x_write(d->udev, M9206_CORE,
rc_seq->data,
rc_seq->address)) != 0) {
deb("Initialising remote control failed\n");
return ret;
}
rc_seq++;
}
deb("Initialising remote control success\n");
}
for (i = 0; i < d->props.num_adapters; i++)
flags |= d->adapter[i].props.caps;
/* Some devices(Dposh) might crash if we attempt touch at all. */
if (flags & DVB_USB_ADAP_HAS_PID_FILTER) {
for (i = 0; i < d->props.num_adapters; i++) {
epi = d->adapter[i].props.stream.endpoint - 0x81;
if (epi < 0 || epi >= M9206_MAX_ADAPTERS) {
printk(KERN_INFO "m920x: Unexpected adapter endpoint!\n");
return -EINVAL;
}
adap_enabled[epi] = 1;
}
for (i = 0; i < M9206_MAX_ADAPTERS; i++) {
if (adap_enabled[i])
continue;
if ((ret = m920x_set_filter(d, 0x81 + i, 0, 0x0)) != 0)
return ret;
if ((ret = m920x_set_filter(d, 0x81 + i, 0, 0x02f5)) != 0)
return ret;
}
}
return ret;
}
static int m920x_init_ep(struct usb_interface *intf)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct usb_host_interface *alt;
if ((alt = usb_altnum_to_altsetting(intf, 1)) == NULL) {
deb("No alt found!\n");
return -ENODEV;
}
return usb_set_interface(udev, alt->desc.bInterfaceNumber,
alt->desc.bAlternateSetting);
}
static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
{
struct m920x_state *m = d->priv;
int i, ret = 0;
u8 rc_state[2];
if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0)
goto unlock;
if ((ret = m920x_read(