[PATCH] dvb: b2c2/flexcop driver refactoring part 1: drop old b2c2-usb stuff
b2c2/flexcop driver refactoring to support PCI and USB based cards, part 1: drop abandoned attempt to support USB devices Signed-off-by: Patrick Boettcher <pb@linuxtv.org> Signed-off-by: Johannes Stezenbach <js@linuxtv.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Родитель
6262d062a3
Коммит
1ec3597299
|
@ -11,16 +11,3 @@ config DVB_B2C2_SKYSTAR
|
|||
for the B2C2/BBTI Air2PC-ATSC card.
|
||||
|
||||
Say Y if you own such a device and want to use it.
|
||||
|
||||
config DVB_B2C2_USB
|
||||
tristate "B2C2/Technisat Air/Sky/Cable2PC USB"
|
||||
depends on DVB_CORE && USB && EXPERIMENTAL
|
||||
select DVB_STV0299
|
||||
select DVB_MT352
|
||||
help
|
||||
Support for the Air/Sky/Cable2PC USB DVB device by B2C2. Currently
|
||||
the does nothing, but providing basic function for the used usb
|
||||
protocol.
|
||||
|
||||
Say Y if you own such a device and want to use it.
|
||||
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
obj-b2c2-usb = b2c2-usb-core.o b2c2-common.o
|
||||
|
||||
obj-$(CONFIG_DVB_B2C2_SKYSTAR) += skystar2.o
|
||||
obj-$(CONFIG_DVB_B2C2_USB) + = b2c2-usb.o
|
||||
|
||||
EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
|
||||
|
|
|
@ -1,214 +0,0 @@
|
|||
/*
|
||||
* b2c2-common.c - common methods for the B2C2/Technisat SkyStar2 PCI DVB card and
|
||||
* for the B2C2/Technisat Sky/Cable/AirStar USB devices
|
||||
* based on the FlexCopII/FlexCopIII by B2C2, Inc.
|
||||
*
|
||||
* Copyright (C) 2003 Vadim Catana, skystar@moldova.cc
|
||||
*
|
||||
* FIX: DISEQC Tone Burst in flexcop_diseqc_ioctl()
|
||||
* FIX: FULL soft DiSEqC for skystar2 (FlexCopII rev 130) VP310 equipped
|
||||
* Vincenzo Di Massa, hawk.it at tiscalinet.it
|
||||
*
|
||||
* Converted to Linux coding style
|
||||
* Misc reorganization, polishing, restyling
|
||||
* Roberto Ragusa, r.ragusa at libero.it
|
||||
*
|
||||
* Added hardware filtering support,
|
||||
* Niklas Peinecke, peinecke at gdv.uni-hannover.de
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1
|
||||
* 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 Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include "stv0299.h"
|
||||
#include "mt352.h"
|
||||
#include "mt312.h"
|
||||
|
||||
static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
|
||||
{
|
||||
u8 aclk = 0;
|
||||
u8 bclk = 0;
|
||||
|
||||
if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
|
||||
else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
|
||||
else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
|
||||
else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
|
||||
else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
|
||||
else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
|
||||
|
||||
stv0299_writereg (fe, 0x13, aclk);
|
||||
stv0299_writereg (fe, 0x14, bclk);
|
||||
stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff);
|
||||
stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff);
|
||||
stv0299_writereg (fe, 0x21, (ratio ) & 0xf0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
|
||||
{
|
||||
u8 buf[4];
|
||||
u32 div;
|
||||
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
|
||||
// struct adapter* adapter = (struct adapter*) fe->dvb->priv;
|
||||
|
||||
div = params->frequency / 125;
|
||||
|
||||
buf[0] = (div >> 8) & 0x7f;
|
||||
buf[1] = div & 0xff;
|
||||
buf[2] = 0x84; // 0xC4
|
||||
buf[3] = 0x08;
|
||||
|
||||
if (params->frequency < 1500000) buf[3] |= 0x10;
|
||||
|
||||
// if (i2c_transfer (&adapter->i2c_adap, &msg, 1) != 1) return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 samsung_tbmu24112_inittab[] = {
|
||||
0x01, 0x15,
|
||||
0x02, 0x30,
|
||||
0x03, 0x00,
|
||||
0x04, 0x7D,
|
||||
0x05, 0x35,
|
||||
0x06, 0x02,
|
||||
0x07, 0x00,
|
||||
0x08, 0xC3,
|
||||
0x0C, 0x00,
|
||||
0x0D, 0x81,
|
||||
0x0E, 0x23,
|
||||
0x0F, 0x12,
|
||||
0x10, 0x7E,
|
||||
0x11, 0x84,
|
||||
0x12, 0xB9,
|
||||
0x13, 0x88,
|
||||
0x14, 0x89,
|
||||
0x15, 0xC9,
|
||||
0x16, 0x00,
|
||||
0x17, 0x5C,
|
||||
0x18, 0x00,
|
||||
0x19, 0x00,
|
||||
0x1A, 0x00,
|
||||
0x1C, 0x00,
|
||||
0x1D, 0x00,
|
||||
0x1E, 0x00,
|
||||
0x1F, 0x3A,
|
||||
0x20, 0x2E,
|
||||
0x21, 0x80,
|
||||
0x22, 0xFF,
|
||||
0x23, 0xC1,
|
||||
0x28, 0x00,
|
||||
0x29, 0x1E,
|
||||
0x2A, 0x14,
|
||||
0x2B, 0x0F,
|
||||
0x2C, 0x09,
|
||||
0x2D, 0x05,
|
||||
0x31, 0x1F,
|
||||
0x32, 0x19,
|
||||
0x33, 0xFE,
|
||||
0x34, 0x93,
|
||||
0xff, 0xff,
|
||||
};
|
||||
|
||||
static struct stv0299_config samsung_tbmu24112_config = {
|
||||
.demod_address = 0x68,
|
||||
.inittab = samsung_tbmu24112_inittab,
|
||||
.mclk = 88000000UL,
|
||||
.invert = 0,
|
||||
.enhanced_tuning = 0,
|
||||
.skip_reinit = 0,
|
||||
.lock_output = STV0229_LOCKOUTPUT_LK,
|
||||
.volt13_op0_op1 = STV0299_VOLT13_OP1,
|
||||
.min_delay_ms = 100,
|
||||
.set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
|
||||
.pll_set = samsung_tbmu24112_pll_set,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
|
||||
{
|
||||
static u8 mt352_clock_config [] = { 0x89, 0x10, 0x2d };
|
||||
static u8 mt352_reset [] = { 0x50, 0x80 };
|
||||
static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
|
||||
static u8 mt352_agc_cfg [] = { 0x67, 0x28, 0xa1 };
|
||||
static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
|
||||
|
||||
mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
|
||||
udelay(2000);
|
||||
mt352_write(fe, mt352_reset, sizeof(mt352_reset));
|
||||
mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
|
||||
|
||||
mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
|
||||
mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
|
||||
{
|
||||
u32 div;
|
||||
unsigned char bs = 0;
|
||||
|
||||
#define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
|
||||
div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
|
||||
|
||||
if (params->frequency >= 48000000 && params->frequency <= 154000000) bs = 0x09;
|
||||
if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a;
|
||||
if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08;
|
||||
|
||||
pllbuf[0] = 0xc2; // Note: non-linux standard PLL i2c address
|
||||
pllbuf[1] = div >> 8;
|
||||
pllbuf[2] = div & 0xff;
|
||||
pllbuf[3] = 0xcc;
|
||||
pllbuf[4] = bs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mt352_config samsung_tdtc9251dh0_config = {
|
||||
|
||||
.demod_address = 0x0f,
|
||||
.demod_init = samsung_tdtc9251dh0_demod_init,
|
||||
.pll_set = samsung_tdtc9251dh0_pll_set,
|
||||
};
|
||||
|
||||
static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
|
||||
{
|
||||
u8 buf[4];
|
||||
u32 div;
|
||||
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
|
||||
// struct adapter* adapter = (struct adapter*) fe->dvb->priv;
|
||||
|
||||
div = (params->frequency + (125/2)) / 125;
|
||||
|
||||
buf[0] = (div >> 8) & 0x7f;
|
||||
buf[1] = (div >> 0) & 0xff;
|
||||
buf[2] = 0x84 | ((div >> 10) & 0x60);
|
||||
buf[3] = 0x80;
|
||||
|
||||
if (params->frequency < 1550000)
|
||||
buf[3] |= 0x02;
|
||||
|
||||
//if (i2c_transfer (&adapter->i2c_adap, &msg, 1) != 1) return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mt312_config skystar23_samsung_tbdu18132_config = {
|
||||
|
||||
.demod_address = 0x0e,
|
||||
.pll_set = skystar23_samsung_tbdu18132_pll_set,
|
||||
};
|
|
@ -1,549 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2004 Patrick Boettcher <patrick.boettcher@desy.de>,
|
||||
* Luca Bertagnolio <>,
|
||||
*
|
||||
* based on information provided by John Jurrius from BBTI, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include "dmxdev.h"
|
||||
#include "dvb_demux.h"
|
||||
#include "dvb_filter.h"
|
||||
#include "dvb_net.h"
|
||||
#include "dvb_frontend.h"
|
||||
|
||||
/* debug */
|
||||
#define dprintk(level,args...) \
|
||||
do { if ((debug & level)) { printk(args); } } while (0)
|
||||
#define debug_dump(b,l) if (debug) {\
|
||||
int i; deb_xfer("%s: %d > ",__FUNCTION__,l); \
|
||||
for (i = 0; i < l; i++) deb_xfer("%02x ", b[i]); \
|
||||
deb_xfer("\n");\
|
||||
}
|
||||
|
||||
static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info,ts=2,ctrl=4 (or-able)).");
|
||||
|
||||
#define deb_info(args...) dprintk(0x01,args)
|
||||
#define deb_ts(args...) dprintk(0x02,args)
|
||||
#define deb_ctrl(args...) dprintk(0x04,args)
|
||||
|
||||
/* Version information */
|
||||
#define DRIVER_VERSION "0.0"
|
||||
#define DRIVER_DESC "Driver for B2C2/Technisat Air/Cable/Sky-2-PC USB devices"
|
||||
#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
|
||||
|
||||
/* transfer parameters */
|
||||
#define B2C2_USB_FRAMES_PER_ISO 4
|
||||
#define B2C2_USB_NUM_ISO_URB 4 /* TODO check out a good value */
|
||||
|
||||
#define B2C2_USB_CTRL_PIPE_IN usb_rcvctrlpipe(b2c2->udev,0)
|
||||
#define B2C2_USB_CTRL_PIPE_OUT usb_sndctrlpipe(b2c2->udev,0)
|
||||
#define B2C2_USB_DATA_PIPE usb_rcvisocpipe(b2c2->udev,0x81)
|
||||
|
||||
struct usb_b2c2_usb {
|
||||
struct usb_device *udev;
|
||||
struct usb_interface *uintf;
|
||||
|
||||
u8 *iso_buffer;
|
||||
int buffer_size;
|
||||
dma_addr_t iso_dma_handle;
|
||||
struct urb *iso_urb[B2C2_USB_NUM_ISO_URB];
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* USB
|
||||
* 10 90 34 12 78 56 04 00
|
||||
* usb_control_msg(udev, usb_sndctrlpipe(udev,0),
|
||||
* 0x90,
|
||||
* 0x10,
|
||||
* 0x1234,
|
||||
* 0x5678,
|
||||
* buf,
|
||||
* 4,
|
||||
* 5*HZ);
|
||||
*
|
||||
* extern int usb_control_msg(struct usb_device *dev, unsigned int pipe,
|
||||
* __u8 request,
|
||||
* __u8 requesttype,
|
||||
* __u16 value,
|
||||
* __u16 index,
|
||||
* void *data,
|
||||
* __u16 size,
|
||||
* int timeout);
|
||||
*
|
||||
*/
|
||||
|
||||
/* request types */
|
||||
typedef enum {
|
||||
|
||||
/* something is wrong with this part
|
||||
RTYPE_READ_DW = (1 << 6),
|
||||
RTYPE_WRITE_DW_1 = (3 << 6),
|
||||
RTYPE_READ_V8_MEMORY = (6 << 6),
|
||||
RTYPE_WRITE_V8_MEMORY = (7 << 6),
|
||||
RTYPE_WRITE_V8_FLASH = (8 << 6),
|
||||
RTYPE_GENERIC = (9 << 6),
|
||||
*/
|
||||
RTYPE_READ_DW = (3 << 6),
|
||||
RTYPE_WRITE_DW_1 = (1 << 6),
|
||||
|
||||
RTYPE_READ_V8_MEMORY = (6 << 6),
|
||||
RTYPE_WRITE_V8_MEMORY = (7 << 6),
|
||||
RTYPE_WRITE_V8_FLASH = (8 << 6),
|
||||
RTYPE_GENERIC = (9 << 6),
|
||||
} b2c2_usb_request_type_t;
|
||||
|
||||
/* request */
|
||||
typedef enum {
|
||||
B2C2_USB_WRITE_V8_MEM = 0x04,
|
||||
B2C2_USB_READ_V8_MEM = 0x05,
|
||||
B2C2_USB_READ_REG = 0x08,
|
||||
B2C2_USB_WRITE_REG = 0x0A,
|
||||
/* B2C2_USB_WRITEREGLO = 0x0A, */
|
||||
B2C2_USB_WRITEREGHI = 0x0B,
|
||||
B2C2_USB_FLASH_BLOCK = 0x10,
|
||||
B2C2_USB_I2C_REQUEST = 0x11,
|
||||
B2C2_USB_UTILITY = 0x12,
|
||||
} b2c2_usb_request_t;
|
||||
|
||||
/* function definition for I2C_REQUEST */
|
||||
typedef enum {
|
||||
USB_FUNC_I2C_WRITE = 0x01,
|
||||
USB_FUNC_I2C_MULTIWRITE = 0x02,
|
||||
USB_FUNC_I2C_READ = 0x03,
|
||||
USB_FUNC_I2C_REPEATWRITE = 0x04,
|
||||
USB_FUNC_GET_DESCRIPTOR = 0x05,
|
||||
USB_FUNC_I2C_REPEATREAD = 0x06,
|
||||
/* DKT 020208 - add this to support special case of DiSEqC */
|
||||
USB_FUNC_I2C_CHECKWRITE = 0x07,
|
||||
USB_FUNC_I2C_CHECKRESULT = 0x08,
|
||||
} b2c2_usb_i2c_function_t;
|
||||
|
||||
/*
|
||||
* function definition for UTILITY request 0x12
|
||||
* DKT 020304 - new utility function
|
||||
*/
|
||||
typedef enum {
|
||||
UTILITY_SET_FILTER = 0x01,
|
||||
UTILITY_DATA_ENABLE = 0x02,
|
||||
UTILITY_FLEX_MULTIWRITE = 0x03,
|
||||
UTILITY_SET_BUFFER_SIZE = 0x04,
|
||||
UTILITY_FLEX_OPERATOR = 0x05,
|
||||
UTILITY_FLEX_RESET300_START = 0x06,
|
||||
UTILITY_FLEX_RESET300_STOP = 0x07,
|
||||
UTILITY_FLEX_RESET300 = 0x08,
|
||||
UTILITY_SET_ISO_SIZE = 0x09,
|
||||
UTILITY_DATA_RESET = 0x0A,
|
||||
UTILITY_GET_DATA_STATUS = 0x10,
|
||||
UTILITY_GET_V8_REG = 0x11,
|
||||
/* DKT 020326 - add function for v1.14 */
|
||||
UTILITY_SRAM_WRITE = 0x12,
|
||||
UTILITY_SRAM_READ = 0x13,
|
||||
UTILITY_SRAM_TESTFILL = 0x14,
|
||||
UTILITY_SRAM_TESTSET = 0x15,
|
||||
UTILITY_SRAM_TESTVERIFY = 0x16,
|
||||
} b2c2_usb_utility_function_t;
|
||||
|
||||
#define B2C2_WAIT_FOR_OPERATION_RW 1 // 1 s
|
||||
#define B2C2_WAIT_FOR_OPERATION_RDW 3 // 3 s
|
||||
#define B2C2_WAIT_FOR_OPERATION_WDW 1 // 1 s
|
||||
|
||||
#define B2C2_WAIT_FOR_OPERATION_V8READ 3 // 3 s
|
||||
#define B2C2_WAIT_FOR_OPERATION_V8WRITE 3 // 3 s
|
||||
#define B2C2_WAIT_FOR_OPERATION_V8FLASH 3 // 3 s
|
||||
|
||||
/* JLP 111700: we will include the 1 bit gap between the upper and lower 3 bits
|
||||
* in the IBI address, to make the V8 code simpler.
|
||||
* PCI ADDRESS FORMAT: 0x71C -> 0000 0111 0001 1100 (these are the six bits used)
|
||||
* in general: 0000 0HHH 000L LL00
|
||||
* IBI ADDRESS FORMAT: RHHH BLLL
|
||||
*
|
||||
* where R is the read(1)/write(0) bit, B is the busy bit
|
||||
* and HHH and LLL are the two sets of three bits from the PCI address.
|
||||
*/
|
||||
#define B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(usPCI) (u8) (((usPCI >> 2) & 0x07) + ((usPCI >> 4) & 0x70))
|
||||
#define B2C2_FLEX_INTERNALADDR_TO_PCIOFFSET(ucAddr) (u16) (((ucAddr & 0x07) << 2) + ((ucAddr & 0x70) << 4))
|
||||
|
||||
/*
|
||||
* DKT 020228 - forget about this VENDOR_BUFFER_SIZE, read and write register
|
||||
* deal with DWORD or 4 bytes, that should be should from now on
|
||||
*/
|
||||
static u32 b2c2_usb_read_dw(struct usb_b2c2_usb *b2c2, u16 wRegOffsPCI)
|
||||
{
|
||||
u32 val;
|
||||
u16 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) | 0x0080;
|
||||
int len = usb_control_msg(b2c2->udev,
|
||||
B2C2_USB_CTRL_PIPE_IN,
|
||||
B2C2_USB_READ_REG,
|
||||
RTYPE_READ_DW,
|
||||
wAddress,
|
||||
0,
|
||||
&val,
|
||||
sizeof(u32),
|
||||
B2C2_WAIT_FOR_OPERATION_RDW * 1000);
|
||||
|
||||
if (len != sizeof(u32)) {
|
||||
err("error while reading dword from %d (%d).",wAddress,wRegOffsPCI);
|
||||
return -EIO;
|
||||
} else
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* DKT 020228 - from now on, we don't support anything older than firm 1.00
|
||||
* I eliminated the write register as a 2 trip of writing hi word and lo word
|
||||
* and force this to write only 4 bytes at a time.
|
||||
* NOTE: this should work with all the firmware from 1.00 and newer
|
||||
*/
|
||||
static int b2c2_usb_write_dw(struct usb_b2c2_usb *b2c2, u16 wRegOffsPCI, u32 val)
|
||||
{
|
||||
u16 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI);
|
||||
int len = usb_control_msg(b2c2->udev,
|
||||
B2C2_USB_CTRL_PIPE_OUT,
|
||||
B2C2_USB_WRITE_REG,
|
||||
RTYPE_WRITE_DW_1,
|
||||
wAddress,
|
||||
0,
|
||||
&val,
|
||||
sizeof(u32),
|
||||
B2C2_WAIT_FOR_OPERATION_RDW * 1000);
|
||||
|
||||
if (len != sizeof(u32)) {
|
||||
err("error while reading dword from %d (%d).",wAddress,wRegOffsPCI);
|
||||
return -EIO;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* DKT 010817 - add support for V8 memory read/write and flash update
|
||||
*/
|
||||
static int b2c2_usb_v8_memory_req(struct usb_b2c2_usb *b2c2,
|
||||
b2c2_usb_request_t req, u8 page, u16 wAddress,
|
||||
u16 buflen, u8 *pbBuffer)
|
||||
{
|
||||
u8 dwRequestType;
|
||||
u16 wIndex;
|
||||
int nWaitTime,pipe,len;
|
||||
|
||||
wIndex = page << 8;
|
||||
|
||||
switch (req) {
|
||||
case B2C2_USB_READ_V8_MEM:
|
||||
nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ;
|
||||
dwRequestType = (u8) RTYPE_READ_V8_MEMORY;
|
||||
pipe = B2C2_USB_CTRL_PIPE_IN;
|
||||
break;
|
||||
case B2C2_USB_WRITE_V8_MEM:
|
||||
wIndex |= pbBuffer[0];
|
||||
nWaitTime = B2C2_WAIT_FOR_OPERATION_V8WRITE;
|
||||
dwRequestType = (u8) RTYPE_WRITE_V8_MEMORY;
|
||||
pipe = B2C2_USB_CTRL_PIPE_OUT;
|
||||
break;
|
||||
case B2C2_USB_FLASH_BLOCK:
|
||||
nWaitTime = B2C2_WAIT_FOR_OPERATION_V8FLASH;
|
||||
dwRequestType = (u8) RTYPE_WRITE_V8_FLASH;
|
||||
pipe = B2C2_USB_CTRL_PIPE_OUT;
|
||||
break;
|
||||
default:
|
||||
deb_info("unsupported request for v8_mem_req %x.\n",req);
|
||||
return -EINVAL;
|
||||
}
|
||||
len = usb_control_msg(b2c2->udev,pipe,
|
||||
req,
|
||||
dwRequestType,
|
||||
wAddress,
|
||||
wIndex,
|
||||
pbBuffer,
|
||||
buflen,
|
||||
nWaitTime * 1000);
|
||||
return len == buflen ? 0 : -EIO;
|
||||
}
|
||||
|
||||
static int b2c2_usb_i2c_req(struct usb_b2c2_usb *b2c2,
|
||||
b2c2_usb_request_t req, b2c2_usb_i2c_function_t func,
|
||||
u8 port, u8 chipaddr, u8 addr, u8 buflen, u8 *buf)
|
||||
{
|
||||
u16 wValue, wIndex;
|
||||
int nWaitTime,pipe,len;
|
||||
u8 dwRequestType;
|
||||
|
||||
switch (func) {
|
||||
case USB_FUNC_I2C_WRITE:
|
||||
case USB_FUNC_I2C_MULTIWRITE:
|
||||
case USB_FUNC_I2C_REPEATWRITE:
|
||||
/* DKT 020208 - add this to support special case of DiSEqC */
|
||||
case USB_FUNC_I2C_CHECKWRITE:
|
||||
pipe = B2C2_USB_CTRL_PIPE_OUT;
|
||||
nWaitTime = 2;
|
||||
dwRequestType = (u8) RTYPE_GENERIC;
|
||||
break;
|
||||
case USB_FUNC_I2C_READ:
|
||||
case USB_FUNC_I2C_REPEATREAD:
|
||||
pipe = B2C2_USB_CTRL_PIPE_IN;
|
||||
nWaitTime = 2;
|
||||
dwRequestType = (u8) RTYPE_GENERIC;
|
||||
break;
|
||||
default:
|
||||
deb_info("unsupported function for i2c_req %x\n",func);
|
||||
return -EINVAL;
|
||||
}
|
||||
wValue = (func << 8 ) | port;
|
||||
wIndex = (chipaddr << 8 ) | addr;
|
||||
|
||||
len = usb_control_msg(b2c2->udev,pipe,
|
||||
req,
|
||||
dwRequestType,
|
||||
addr,
|
||||
wIndex,
|
||||
buf,
|
||||
buflen,
|
||||
nWaitTime * 1000);
|
||||
return len == buflen ? 0 : -EIO;
|
||||
}
|
||||
|
||||
int static b2c2_usb_utility_req(struct usb_b2c2_usb *b2c2, int set,
|
||||
b2c2_usb_utility_function_t func, u8 extra, u16 wIndex,
|
||||
u16 buflen, u8 *pvBuffer)
|
||||
{
|
||||
u16 wValue;
|
||||
int nWaitTime = 2,
|
||||
pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN,
|
||||
len;
|
||||
|
||||
wValue = (func << 8) | extra;
|
||||
|
||||
len = usb_control_msg(b2c2->udev,pipe,
|
||||
B2C2_USB_UTILITY,
|
||||
(u8) RTYPE_GENERIC,
|
||||
wValue,
|
||||
wIndex,
|
||||
pvBuffer,
|
||||
buflen,
|
||||
nWaitTime * 1000);
|
||||
return len == buflen ? 0 : -EIO;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void b2c2_dumpfourreg(struct usb_b2c2_usb *b2c2, u16 offs)
|
||||
{
|
||||
u32 r0,r1,r2,r3;
|
||||
r0 = r1 = r2 = r3 = 0;
|
||||
r0 = b2c2_usb_read_dw(b2c2,offs);
|
||||
r1 = b2c2_usb_read_dw(b2c2,offs + 0x04);
|
||||
r2 = b2c2_usb_read_dw(b2c2,offs + 0x08);
|
||||
r3 = b2c2_usb_read_dw(b2c2,offs + 0x0c);
|
||||
deb_ctrl("dump: offset: %03x, %08x, %08x, %08x, %08x\n",offs,r0,r1,r2,r3);
|
||||
}
|
||||
|
||||
static void b2c2_urb_complete(struct urb *urb, struct pt_regs *ptregs)
|
||||
{
|
||||
struct usb_b2c2_usb *b2c2 = urb->context;
|
||||
deb_ts("urb completed, bufsize: %d\n",urb->transfer_buffer_length);
|
||||
|
||||
// urb_submit_urb(urb,GFP_ATOMIC); enable for real action
|
||||
}
|
||||
|
||||
static void b2c2_exit_usb(struct usb_b2c2_usb *b2c2)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++)
|
||||
if (b2c2->iso_urb[i] != NULL) { /* not sure about unlink_urb and iso-urbs TODO */
|
||||
deb_info("unlinking/killing urb no. %d\n",i);
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,7)
|
||||
usb_unlink_urb(b2c2->iso_urb[i]);
|
||||
#else
|
||||
usb_kill_urb(b2c2->iso_urb[i]);
|
||||
#endif
|
||||
usb_free_urb(b2c2->iso_urb[i]);
|
||||
}
|
||||
|
||||
if (b2c2->iso_buffer != NULL)
|
||||
pci_free_consistent(NULL,b2c2->buffer_size, b2c2->iso_buffer, b2c2->iso_dma_handle);
|
||||
|
||||
}
|
||||
|
||||
static int b2c2_init_usb(struct usb_b2c2_usb *b2c2)
|
||||
{
|
||||
u16 frame_size = le16_to_cpu(b2c2->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize);
|
||||
int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO * frame_size,i,j,ret;
|
||||
int buffer_offset = 0;
|
||||
|
||||
deb_info("creating %d iso-urbs with %d frames each of %d bytes size = %d.\n",
|
||||
B2C2_USB_NUM_ISO_URB, B2C2_USB_FRAMES_PER_ISO, frame_size,bufsize);
|
||||
|
||||
b2c2->iso_buffer = pci_alloc_consistent(NULL,bufsize,&b2c2->iso_dma_handle);
|
||||
if (b2c2->iso_buffer == NULL)
|
||||
return -ENOMEM;
|
||||
memset(b2c2->iso_buffer, 0, bufsize);
|
||||
b2c2->buffer_size = bufsize;
|
||||
|
||||
/* creating iso urbs */
|
||||
for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++)
|
||||
if (!(b2c2->iso_urb[i] = usb_alloc_urb(B2C2_USB_FRAMES_PER_ISO,GFP_ATOMIC))) {
|
||||
ret = -ENOMEM;
|
||||
goto urb_error;
|
||||
}
|
||||
/* initialising and submitting iso urbs */
|
||||
for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) {
|
||||
int frame_offset = 0;
|
||||
struct urb *urb = b2c2->iso_urb[i];
|
||||
deb_info("initializing and submitting urb no. %d (buf_offset: %d).\n",i,buffer_offset);
|
||||
|
||||
urb->dev = b2c2->udev;
|
||||
urb->context = b2c2;
|
||||
urb->complete = b2c2_urb_complete;
|
||||
urb->pipe = B2C2_USB_DATA_PIPE;
|
||||
urb->transfer_flags = URB_ISO_ASAP;
|
||||
urb->interval = 1;
|
||||
urb->number_of_packets = B2C2_USB_FRAMES_PER_ISO;
|
||||
urb->transfer_buffer_length = frame_size * B2C2_USB_FRAMES_PER_ISO;
|
||||
urb->transfer_buffer = b2c2->iso_buffer + buffer_offset;
|
||||
|
||||
buffer_offset += frame_size * B2C2_USB_FRAMES_PER_ISO;
|
||||
for (j = 0; j < B2C2_USB_FRAMES_PER_ISO; j++) {
|
||||
deb_info("urb no: %d, frame: %d, frame_offset: %d\n",i,j,frame_offset);
|
||||
urb->iso_frame_desc[j].offset = frame_offset;
|
||||
urb->iso_frame_desc[j].length = frame_size;
|
||||
frame_offset += frame_size;
|
||||
}
|
||||
|
||||
if ((ret = usb_submit_urb(b2c2->iso_urb[i],GFP_ATOMIC))) {
|
||||
err("submitting urb %d failed with %d.",i,ret);
|
||||
goto urb_error;
|
||||
}
|
||||
deb_info("submitted urb no. %d.\n",i);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
goto success;
|
||||
urb_error:
|
||||
b2c2_exit_usb(b2c2);
|
||||
success:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int b2c2_usb_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
struct usb_b2c2_usb *b2c2 = NULL;
|
||||
int ret;
|
||||
|
||||
b2c2 = kmalloc(sizeof(struct usb_b2c2_usb),GFP_KERNEL);
|
||||
if (b2c2 == NULL) {
|
||||
err("no memory");
|
||||
return -ENOMEM;
|
||||
}
|
||||
b2c2->udev = udev;
|
||||
b2c2->uintf = intf;
|
||||
|
||||
/* use the alternate setting with the larges buffer */
|
||||
usb_set_interface(udev,0,1);
|
||||
|
||||
if ((ret = b2c2_init_usb(b2c2)))
|
||||
goto usb_init_error;
|
||||
|
||||
usb_set_intfdata(intf,b2c2);
|
||||
|
||||
switch (udev->speed) {
|
||||
case USB_SPEED_LOW:
|
||||
err("cannot handle USB speed because it is to sLOW.");
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
info("running at FULL speed.");
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
info("running at HIGH speed.");
|
||||
break;
|
||||
case USB_SPEED_UNKNOWN: /* fall through */
|
||||
default:
|
||||
err("cannot handle USB speed because it is unkown.");
|
||||
break;
|
||||
}
|
||||
|
||||
b2c2_dumpfourreg(b2c2,0x200);
|
||||
b2c2_dumpfourreg(b2c2,0x300);
|
||||
b2c2_dumpfourreg(b2c2,0x400);
|
||||
b2c2_dumpfourreg(b2c2,0x700);
|
||||
|
||||
|
||||
if (ret == 0)
|
||||
info("%s successfully initialized and connected.",DRIVER_DESC);
|
||||
else
|
||||
info("%s error while loading driver (%d)",DRIVER_DESC,ret);
|
||||
|
||||
ret = 0;
|
||||
goto success;
|
||||
|
||||
usb_init_error:
|
||||
kfree(b2c2);
|
||||
success:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void b2c2_usb_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct usb_b2c2_usb *b2c2 = usb_get_intfdata(intf);
|
||||
usb_set_intfdata(intf,NULL);
|
||||
if (b2c2 != NULL) {
|
||||
b2c2_exit_usb(b2c2);
|
||||
kfree(b2c2);
|
||||
}
|
||||
info("%s successfully deinitialized and disconnected.",DRIVER_DESC);
|
||||
|
||||
}
|
||||
|
||||
static struct usb_device_id b2c2_usb_table [] = {
|
||||
{ USB_DEVICE(0x0af7, 0x0101) }
|
||||
};
|
||||
|
||||
/* usb specific object needed to register this driver with the usb subsystem */
|
||||
static struct usb_driver b2c2_usb_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "dvb_b2c2_usb",
|
||||
.probe = b2c2_usb_probe,
|
||||
.disconnect = b2c2_usb_disconnect,
|
||||
.id_table = b2c2_usb_table,
|
||||
};
|
||||
|
||||
/* module stuff */
|
||||
static int __init b2c2_usb_init(void)
|
||||
{
|
||||
int result;
|
||||
if ((result = usb_register(&b2c2_usb_driver))) {
|
||||
err("usb_register failed. Error number %d",result);
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit b2c2_usb_exit(void)
|
||||
{
|
||||
/* deregister this driver from the USB subsystem */
|
||||
usb_deregister(&b2c2_usb_driver);
|
||||
}
|
||||
|
||||
module_init (b2c2_usb_init);
|
||||
module_exit (b2c2_usb_exit);
|
||||
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DEVICE_TABLE(usb, b2c2_usb_table);
|
Загрузка…
Ссылка в новой задаче