Am Donnerstag, 1. März 2007 schrieb Patrick Boettcher:
> On Sun, 25 Feb 2007, Marco wrote:
> > Hi
> >
> > Attached is a patch for v4l-dvb , for the Opera DVB-S USB2.0 Adapter.
> > It should work for the dvb stuff 100% and for RC-Stuff nearly 100%(slow
> > response to keys some times)
> > 3 firmware files are needed which can be found after a search with google
> > (or can i upload these files somwhere ?)
> >
> >
> > Signed-of-by: Marci Gittler <[EMAIL PROTECTED]>
> > Signed-of-by: Mario Hlawitschka <[EMAIL PROTECTED]>
>
> Some comment about the driver:
>
> In general you could cleanup the thing a little. There are some strange
> things which should be written differently to make it easier for others to
> read (and also to please kernel people). For buffers you should always u8
> not char.
>
> [..]
> +#include "opera1.h"
> +
> +static u32 last_key_pressed=-1;
>
> You cannot do that, because if you plug two devices at the same time, they
> will both use the same global variable. Things like that have to go into
> a private struct allocated for each device. You can you the size_of_priv
> field in the dvb_usb_device_properties to let the dvb-usb-framework
> allocate it.
ok done
>
> +static const char* xilinx_init="\x90\x6e\xc5\xfa\x32\xd0\x73\x23\x1e";
> +static int opera1_xilinx_load_firmware(struct usb_device *dev, const char
> *filename); +
> +int dvb_usb_opera1_debug;
>
done
> you can make this global static.
>
> +module_param_named(debug,dvb_usb_opera1_debug, int, 0644);
> +MODULE_PARM_DESC(debug, "set debugging level
> (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))."
> DVB_USB_DEBUG_STATUS); +//struct mutex mymutex;
> +
> +int opera1_xilinx_rw(struct usb_device*dev, u8 request, u16 value,
> u8*data, u16 len,int flags){ +
> + int ret=0,t=0;
> + char r[10];
> + u8 u8buf[len];
> + unsigned int
> pipe=(flags==1)?usb_rcvctrlpipe(dev,0):usb_sndctrlpipe(dev,0); + u8
> request_type=(flags==1)?USB_DIR_IN:USB_DIR_OUT;
> +
> +
> + //if (mutex_lock_interruptible(&mymutex)){
> + // return -EAGAIN;
> + //}
> +
> +
> + if (flags==0)
> + memcpy(u8buf,data,len);
> + ret=usb_control_msg(dev, pipe,request, request_type|
> USB_TYPE_VENDOR,value, 0x0 /*index*/, u8buf,len, 2000); + //msleep(20);
> + if (request==OPERA_TUNER_REQ){
> + t=usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
> + OPERA_TUNER_REQ, USB_DIR_IN|USB_TYPE_VENDOR, 0x01,0x0/*index*/, r,
> 10, 2000); + }
> + if (flags==1)
> + memcpy(data,u8buf,len);
> + //mutex_unlock(&mymutex);
> + return ret;
> +
> +}
>
> You could use *data here to do the transfer. Use u8 for local buffers.
> Initialize buffers. Make all locally used functions static.
this causes some usb-ehci controllers to die while sending, so i did copy
that, but can be removed after successfull test
>
> +int opera1_xilinx_read(struct usb_device*dev, u8 request, u16 value,
> u8*data, u16 len){ + return
> opera1_xilinx_rw(dev,request,value,data,len,1);
> +}
> +int opera1_xilinx_send(struct usb_device*dev, u8 request, u16 value,
> u8*data, u16 len){ + return
> opera1_xilinx_rw(dev,request,value,data,len,0);
> +}
> +
> +/* I2C */
> +
> +static int opera1_usb_i2c_xfer(struct dvb_usb_device* dev,struct i2c_msg
> msg[],int num) +{
> + int i;
> + u8 request;
> + u16 value;
> + //return 0;
> + if (dev==NULL){
> + info ("no usb_device");
> + return -EINVAL;
> + }
> + if (mutex_lock_interruptible(&dev->i2c_mutex) < 0)
> + return -EAGAIN;
> + for (i = 0; i < num; i++) {
> + //READ
> + request=(msg[i].addr&0xff00) >> 8;
> + if (!request)
> + request=0xb1;
> + value=(msg[i].addr&0xff);
> + if (msg[i].flags & I2C_M_RD){
> + value|=0x01;
> + }
> + if (request==0xa0)
> + value=0xe600;
> + if ((msg[i].flags & I2C_M_RD)) {
> +
> opera1_xilinx_read(dev->udev,request,value,msg[i].buf,msg[i].len); +
> }else{//WRITE
> +
> opera1_xilinx_send(dev->udev,request,value,msg[i].buf,msg[i].len); +
> }
> + }
> + mutex_unlock(&dev->i2c_mutex);
> + return i;
> +}
>
> Do not abuse i2c_messages for doing USB-transfer. I2C is dedicated bus
> with a standardized interface (i2c_address, buffer). The I2C Adapter in
> the linux kernel should only be used to represent the real I2C-bus inside
> a device.
ok did it
>
> +static int opera1_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg
> msg[],int num) +{
> + struct dvb_usb_device *d = i2c_get_adapdata(adap);
> + if (d)
> + return opera1_usb_i2c_xfer(d,msg,num);
> + return -EINVAL;
> +}
> +static u32 opera1_i2c_func(struct i2c_adapter *adapter)
> +{
> + return I2C_FUNC_I2C;
> +}
> +
> +static struct i2c_algorithm opera1_i2c_algo = {
> + .master_xfer = opera1_i2c_xfer,
> + .functionality = opera1_i2c_func,
> +};
> +
> +
> +static int opera1_tuner_set_params(struct dvb_frontend *fe, struct
> dvb_frontend_parameters *params) +{
> + int freq_add=0;
> + u8 tuner_buf[4];
> + struct dvb_usb_adapter* udev_adap=(struct
> dvb_usb_adapter*)(fe->dvb->priv); +
> +
> + struct i2c_msg tuner_msg = {.addr=0xc0, .flags=0, .buf=tuner_buf,
> .len=sizeof(tuner_buf) }; + struct i2c_msg msg[]={
> + {.addr=0xb701,.flags=0,.buf="\x01",.len=1},
> + {.addr=0xb600,.flags=0,.buf="\x00",.len=1},
> + };
> +
> + u8 filter=0;
> +
> + // setup PLL filter
> + switch (params->u.ofdm.bandwidth) {
> + case BANDWIDTH_6_MHZ: filter = 0;break;
> + case BANDWIDTH_7_MHZ: filter = 0;break;
> + case BANDWIDTH_8_MHZ: filter = 1;break;
> + default: break; //INVAILD
> + }
> +
> + freq_add=params->frequency/500;
> + tuner_buf[0]=(freq_add>>8) & 0xff;
> + tuner_buf[1]=freq_add & 0xff;
> + tuner_buf[2]=(filter==1) ? 0xed:0xe5;//symbolrate 0x500000 :0xed
> /0x400000 :exe5 ( e1/e5/ed) +
> + if (freq_add/2<1100) tuner_buf[3]=0xe6;
> + if (freq_add/2>1100) tuner_buf[3]=0x24;
> + if (freq_add/2>1400) tuner_buf[3]=0x64;
> + if (freq_add/2>1666) tuner_buf[3]=0x84;
> + if (freq_add/2>1800) tuner_buf[3]=0xa4;
> + if (freq_add/2>1900) tuner_buf[3]=0xc4;
> +
> + if (fe->ops.i2c_gate_ctrl)
> + fe->ops.i2c_gate_ctrl(fe, 1);
> +
> + i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1);
> + i2c_transfer(&udev_adap->dev->i2c_adap, &tuner_msg, 1);
> + msleep(1);
> + return 0;
> +}
>
> It is obvious something is wrong here. msg is an array of two messages but
> you only give 1.
ok the 2nd was too few in the array 1 is enough
>
> It would be much better to dvb-pll to program the tuner. If for your tuner
> is not implemented yet it can be easily done.
if i'd know how i would do that
>
> To use dvb-pll you need to implement the i2c_adapter of your device
> properly.
>
> +static int opera1_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t
> voltage) +{
> + struct i2c_msg msg[]={
> + {.addr=0xb600,.flags=0,.buf="\x00",.len=1}, //13 V
> + };
> + struct dvb_usb_adapter* udev_adap=(struct
> dvb_usb_adapter*)(fe->dvb->priv); + if (voltage==SEC_VOLTAGE_18){
> + msg[0].addr=0xb601;
> + msg[0].buf="\x01";
> + }
> + i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1);
> + return 0;
> +}
>
> I'm sure the LNB-controller on your board is already implemented... Please
> use the existing implementation (also you need the i2c-adapter properly
> implemented for that).
which ? i searched the whole v4l-dvb stuff , and did not find any controller
that used 2byte addresses , that makes ist hard to use other stuff for this,
but if you say ist already done , i would change it to the other
>
> +static int opera1_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32
> srate, u32 ratio){ +
> + u8 aclk = 0x98;
> + u8 bclk = 0x95;
> +
> + 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;
> + }
> +//info ("set symbol rate");
> + 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 u8 opera1_inittab[]={
> + 0x00 ,0xa1 ,
> + 0x01 ,0x15 ,
> + 0x02 ,0x00 ,
> + 0x03 ,0x00 ,
> + 0x04 ,0x7d ,
> + 0x05 ,0x05 ,
> + 0x06 ,0x02 ,
> + 0x07 ,0x00 ,
> + 0x0b, 0x00 ,
> + 0x0c ,0x01 ,
> + 0x0d ,0x81 ,
> + 0x0e ,0x44 ,
> + 0x0f ,0x19 ,
> + 0x10 ,0x3f ,
> + 0x11 ,0x84 ,
> + 0x12 ,0xda ,
> + 0x13 ,0x98 ,
> + 0x14 ,0x95 ,
> + 0x15 ,0xc9 ,
> + 0x16 ,0xeb ,
> + 0x17 ,0x00 ,
> + 0x18 ,0x19 ,
> + 0x19 ,0x8b ,
> + 0x1a ,0x00 ,
> + 0x1b ,0x82 ,
> + 0x1c,0x7f ,
> + 0x1d,0x00 ,
> + 0x1e,0x00 ,
> + 0x1f,0x06 ,
> + 0x20,0x50 ,
> + 0x21,0x10 ,
> + 0x22,0x00 ,
> + 0x23,0x00 ,
> + 0x24,0x37 ,
> + 0x25,0xbc ,
> + 0x26,0x00 ,
> + 0x27,0x00 ,
> + 0x28,0x00 ,
> + 0x29,0x1e ,
> + 0x2a,0x14 ,
> + 0x2b,0x1f ,
> + 0x2c,0x09 ,
> + 0x2d,0x0a ,
> + 0x2e,0x00 ,
> + 0x2f,0x00 ,
> + 0x30,0x00,
> + 0x31,0x1f ,
> + 0x32,0x19 ,
> + 0x33,0xfc ,
> + 0x34,0x13,
> + 0xff,0xff,
> +};
> +
> +static struct stv0299_config opera1_stv0299_config={
> + .demod_address= 0xd0,
> + .min_delay_ms=100,
> + .mclk=88000000UL,
> + .invert=1,
> + .skip_reinit=0,
> + .lock_output=STV0229_LOCKOUTPUT_0,
> + .volt13_op0_op1=STV0299_VOLT13_OP0,
> + .inittab=opera1_inittab,
> + .set_symbol_rate=opera1_stv0299_set_symbol_rate,
> +};
> +static int opera1_frontend_attach(struct dvb_usb_adapter *d){
> +
> + if
> ((d->fe=dvb_attach(stv0299_attach,&opera1_stv0299_config,&d->dev->i2c_adap)
>)!=NULL){ + d->fe->ops.tuner_ops.set_params=opera1_tuner_set_params;
> + d->fe->ops.set_voltage=opera1_set_voltage;
> + return 0;
> + }
> + info ("not attached stv0299");
> + return -EIO;
> +}
> +
> +int opera1_power_ctrl(struct dvb_usb_device *d, int onoff)
> +{
> + int ret=0;
> + struct i2c_msg power_on_mgs[]={
> + {.addr=0xb701,.buf="\x01",.len=1},
> + {.addr=0xb601,.buf="\x01",.len=1},//set VOLTAGE setzen
> + {.addr=0xb1a6,.buf="\xff\x03",.len=2},
> + };
> +
> + if (onoff){
> + opera1_usb_i2c_xfer(d,power_on_mgs,3);
> + }
> +
> + return ret;
> +}
>
> If you use an existing lnb-controller-driver it will be done
> automatically.
like i saw for stv0299 the set_symbolrate MUST be implementet bec. there is no
one in. also here the stuff with the 2 byte address
>
> +static int opera1_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
> +{
> +
> + struct i2c_msg start_tuner[]={
> + {.addr=0xb1d0,.buf="\x0c\x01",.len=2},
> + {.addr=0xb1a6,.buf="\xff\x00",.len=2},
> + };
> +
> + if (!onoff){
> + start_tuner[0].buf[1]=0x03;
> + }
> + i2c_transfer(&adap->dev->i2c_adap,start_tuner,2);
> + return 0;
> +}
> +static int opera1_pid_filter(struct dvb_usb_adapter *adap, int index, u16
> pid, int onoff) +{
> +
> + u8 b_pid[3];
> + struct i2c_msg msg[]={
> + {.addr=0xb1a6,.buf=b_pid,.len=3},
> + };
> + b_pid[0]=(2*index)+4;
> + b_pid[1]=onoff?(pid&0xff):(0x00);
> + b_pid[2]=onoff?((pid>>8)&0xff):(0x00);
> + i2c_transfer(&adap->dev->i2c_adap,msg,1);
> + return 0;
> +}
>
> For sending firmware specific commands to your device you should use
> specific function for that.
which one do you mean ?
>
>
> +static struct dvb_usb_rc_key opera1_rc_keys[]={
> + {0x5f,0xa0,KEY_1},
> + {0x50,0xae,KEY_2},
> + {0x5d,0xa2,KEY_3},
> + {0x41,0xbe,KEY_4},
> +
> + {0x0a,0xf4,KEY_5},
> + {0x42,0xbc,KEY_6},
> + {0x47,0xb8,KEY_7},
> + {0x49,0xb6,KEY_8},
> + {0x05,0xfa,KEY_9},
> + {0x45,0xba,KEY_0},
> +
> + {0x09,0xf6,KEY_UP},//chanup
> + {0x1a,0xe4,KEY_DOWN},//chandown
> + {0x5c,0xa2,KEY_LEFT},//voldown
> + {0x5e,0xa0,KEY_RIGHT},//volup
> + {0x07,0xf8,KEY_SPACE},//tab
> + {0x1e,0xe0,KEY_ENTER},//play ok
> + {0x1b,0xe4,KEY_Z},//zoom
> + {0x59,0xa6,KEY_M},//mute
> + {0x5a,0xa4,KEY_F},//tv/f
> + {0x18,0xe6,KEY_R},//rec
> + {0x01,0xfe,KEY_S},//Stop
> + {0x02,0xfc,KEY_P},//pause
> + {0x03,0xfc,KEY_W},//<- ->
> + {0x06,0xf8,KEY_C},//capture
> + {0x46,0xb8,KEY_Q},//exit
> + {0x43,0xbc,KEY_O},//power7
> +
> +};
> +
> +static int opera1_rc_query(struct dvb_usb_device *dev, u32 *event, int
> *state) +{
> + // u8* search="0000000100000000010101000101000";
> + /**
> + startmarker 0001000011101101 or 0001000111101100
> +
> + */
> + u8 rcbuffer[32];
> + const u8
> startmarker1[16]="\x0\x0\x0\x1\x0\x0\x0\x0\x1\x1\x1\x0\x1\x1\x0\x1"; +
> const u8
> startmarker2[16]="\x0\x0\x0\x1\x0\x0\x0\x1\x1\x1\x1\x0\x1\x1\x0\x0"; +
> struct i2c_msg read_remote[]={
> + {.addr=0xb880,.buf=rcbuffer,.flags=I2C_M_RD,.len=32},
> + };
> + int i=0,b=0;
> + u32 send_key=0;
> + memset(rcbuffer,0,32);
> +
> + if (i2c_transfer(&dev->i2c_adap,read_remote,1)==1){
> + if
> (memcmp(rcbuffer,"\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1
>\x1\x1\x1\x1\x1",32)==0 && last_key_pressed!=-1){ +
> *state=REMOTE_KEY_REPEAT;
> + *event=last_key_pressed;
> + return 0;
> + }
> + /*for (b=0;b<32;b++){
> + if (rcbuffer[b])
> + printk("1");
> + else
> + printk("0");
> + }
> + printk("\n");*/
> + for (b=0;b<32;b++){
> + if (b+16<32){
> + if (memcmp(rcbuffer+b,startmarker1,16)==0 ||
> memcmp(rcbuffer+b,startmarker2,16)==0){ + /*for
> (c=b+16;c<32;c++){
> + if (rcbuffer[c])
> + printk("1");
> + else
> + printk("0");
> +
> + }
> + printk("\n");*/
> + break;
> + }
> + }
> + }
> +
> + //if ((b+15+16)==31)//only vaild sequences
> +
> + for (i=b+16;i<32 && i<b+15+16;i++)
> + {
> + if (rcbuffer[i] /*&& (i-b-2)!=6*/)
> + send_key|=1;
> + send_key =send_key << 1;
> + }
> + //printk("key code :%x\n",send_key);
> + if (send_key==0)
> + return 0;
> + printk("key code :%x\n",send_key);
> +
> + for (i=0;i< ARRAY_SIZE(opera1_rc_keys);i++){
> + if (
> + send_key!=0x7efe &&
> + (send_key&0xff )==opera1_rc_keys[i].data &&
> + ((send_key&0xff00)
> >>8)==opera1_rc_keys[i].custom + )
> + {
> + *state = REMOTE_KEY_PRESSED;
> + *event=opera1_rc_keys[i].event;
> + last_key_pressed=opera1_rc_keys[i].event;
> + break;
> + }
> + last_key_pressed=-1;
> + }
> + }else
> + *state = REMOTE_NO_KEY_PRESSED;
> +
> + return 0;
> +}
> +
> +
> +/* do not change the order of the ID table */
> +static struct usb_device_id opera1_table [] = {
> +/* 00 */ { USB_DEVICE(USB_VID_CYPRESS, USB_PID_OPERA1_COLD
> ) }, + { USB_DEVICE(USB_VID_OPERA1_WARM, USB_PID_OPERA1_WARM
> ) }, +/* 01 *//*{ USB_DEVICE(USB_VID_CYPRESS,
> USB_PID_OPERA1_COLD2 ) }, + {
> USB_DEVICE(USB_VID_OPERA1_WARM, USB_PID_OPERA1_WARM ) },*/ +
> { } /* Terminating entry */
> +};
> +MODULE_DEVICE_TABLE (usb, opera1_table);
> +static int opera1_firmware_download(struct usb_device *udev, const struct
> firmware *fw) +{
> +
> + int ret = usb_cypress_load_firmware(udev,fw,CYPRESS_FX2);
> + const struct firmware *fw1=NULL;
> +
> + if(ret==0)
> + {
> + if ((ret = request_firmware(&fw1, "opera1-2.fw", &udev->dev)) != 0)
> { + err("did not find the firmware file. (%s) "
> + "Please see linux/Documentation/dvb/ for more details
> on firmware-problems. (%d)", + "opera1-2.fw",ret);
> +
> + }else{
> + ret = usb_cypress_load_firmware(udev,fw1,CYPRESS_FX2);
> + release_firmware(fw1);
> + if (ret!=0)
> + info("error loading firmware1 %d,%d",-EIO,ret);
> +
> + }
> + }
> + return ret;
> +
> +}
> +
> +static int opera1_xilinx_load_firmware(struct usb_device *dev, const char
> *filename) +{
> + const struct firmware *fw = NULL;
> + u8 *b,*p;
> + int ret = 0,i;
> + u8 dummydata[10],testval;
> + memcpy(dummydata, xilinx_init, 9);
> + info("start downloading fpga firmware");
> +
> + opera1_xilinx_send(dev,0xb1,0xa0,dummydata,9);
> + opera1_xilinx_send(dev,0xb1,0xa0,dummydata,1);
> + opera1_xilinx_read(dev,0xb1,0xa1,dummydata,1);
> + opera1_xilinx_send(dev,0xbc,0xaa,"\x00",1);
> + opera1_xilinx_send(dev,0xbc,0x00,&testval,1);
> + opera1_xilinx_send(dev,0xbc,0x00,&testval,1);
> + opera1_xilinx_send(dev,0xbc,0x00,&testval,1);
> + opera1_xilinx_send(dev,0xbc,0x00,&testval,1);
> +
> + if ((ret = request_firmware(&fw, filename, &dev->dev)) != 0) {
> + err("did not find the firmware file. (%s) "
> + "Please see linux/Documentation/dvb/ for more details on
> firmware-problems.", + filename);
> + return ret;
> + }else{
> + p = kmalloc(fw->size,GFP_KERNEL);
> + if (p != NULL) {
> + u8 reset;
> + memcpy(p,fw->data,fw->size);
> + for(i = 0; p[i] != 0 && i < fw->size; ) {
> + b = (u8 *) p+i;
> + if (
> + opera1_xilinx_send(dev,OPERA_WRITE_FX2,0x0, b+1, b[0])
> != b[0] + ) {
> + err("error while transferring firmware");
> + ret = -EINVAL;
> + break;
> + }
> + i = i+ 1 + b[0];
> + }
> + /* restart the CPU */
> + reset = 0;
> + if (ret || (opera1_xilinx_send(dev,0xa0,0xe600,&reset,1)!=1)) {
> + err("could not restart the USB controller CPU.");
> + ret = -EINVAL;
> + }
> + kfree(p);
> + }
> + }
> + if (fw){
> + release_firmware(fw);
> + }
> + info("done downloading fpga firmware");
> + return ret;
> +}
> +
> +static struct dvb_usb_device_properties opera1_properties = {
> + .caps = DVB_USB_IS_AN_I2C_ADAPTER,
> + .usb_ctrl = DEVICE_SPECIFIC,
> + .firmware = "opera1.fw",
> + .download_firmware = opera1_firmware_download,
> + .size_of_priv = 0,
> +
> + .power_ctrl = opera1_power_ctrl,
> + .i2c_algo = &opera1_i2c_algo,
> +
> + .rc_key_map = opera1_rc_keys,
> + .rc_key_map_size= ARRAY_SIZE(opera1_rc_keys),
> + .rc_interval = 200,
> + .rc_query=opera1_rc_query,
> +
> + .generic_bulk_ctrl_endpoint = 0x00,
> + /* parameter for the MPEG2-data transfer */
> + .num_adapters = 1,
> + .adapter={
> + {
> + .frontend_attach = opera1_frontend_attach,
> + .streaming_ctrl = opera1_streaming_ctrl,
> +
> + .caps=DVB_USB_ADAP_HAS_PID_FILTER |
> DVB_USB_ADAP_NEED_PID_FILTERING, + .pid_filter =
> opera1_pid_filter,
> + .pid_filter_count = 252,
> + .stream = {
> + .type = USB_BULK,
> + .count = 10,
> + .endpoint = 0x82,
> + .u = {
> + .bulk = {
> + .buffersize = 0x200,
> + }
> + }
> + },
> + }
> + },
> +
> + .num_device_descs = 1,
> + .devices = {
> + { "Opera1 DVB-S USB2.0",
> + { &opera1_table[0], NULL },
> + { &opera1_table[1], NULL },
> + },
> + /* { "Opera1 DVB-S USB2.0 wrong product ID",
> + { &opera1_table[2], NULL },
> + { &opera1_table[3], NULL },
> + },*/
> + }
> +};
> +
> +
> +static int opera1_probe(struct usb_interface *intf,
> + const struct usb_device_id *id)
> +{
> + struct dvb_usb_device *d;
> + struct usb_device* udev=interface_to_usbdev(intf);
> +
> + if (udev->descriptor.idProduct==USB_PID_OPERA1_WARM &&
> + udev->descriptor.idVendor==USB_VID_OPERA1_WARM &&
> + (d==NULL || opera1_xilinx_load_firmware(udev,"opera1-fpga.fw")!=0 )
> + ){
> + return -EINVAL;
> + }
> +
> + if (dvb_usb_device_init(intf,&opera1_properties,THIS_MODULE,&d) != 0)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> +static struct usb_driver opera1_driver = {
> + .name = "opera1",
> + .probe = opera1_probe,
> + .disconnect = dvb_usb_device_exit,
> + .id_table = opera1_table,
> +};
> +
> +static int __init opera1_module_init(void)
> +{
> + int result=0;
> +// mutex_init(&mymutex);
> + if ((result = usb_register(&opera1_driver))) {
> + err("usb_register failed. Error number %d",result);
> + }
> + return result;
> +}
> +
> +static void __exit opera1_module_exit(void)
> +{
> + usb_deregister(&opera1_driver);
> +}
> +
> +module_init (opera1_module_init);
> +module_exit (opera1_module_exit);
> +
> +MODULE_AUTHOR("Mario Hlawitschka (c) [EMAIL PROTECTED]");
> +MODULE_AUTHOR("Marco Gittler (c) [EMAIL PROTECTED]");
> +MODULE_DESCRIPTION("Driver for Opera1 DVB-S device");
> +MODULE_VERSION("0.1");
> +MODULE_LICENSE("GPL");
> +
> diff -r 42b9d09cff15 linux/drivers/media/dvb/dvb-usb/opera1.h
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++ b/linux/drivers/media/dvb/dvb-usb/opera1.h Sat Feb 24 14:02:20 2007
> +0100 @@ -0,0 +1,38 @@
> +#ifndef _OPERA1_H_
> +#define _OPERA1_H_
> +
> +
> +#define DVB_USB_LOG_PREFIX "opera"
> +#include "dvb-usb.h"
> +#include "dvb_frontend.h"
> +#include <linux/version.h>
> +extern int dvb_usb_opera1_debug;
> +#define deb_xfer(args...) dprintk(dvb_usb_opera1_debug,0x02,args)
> +
> +struct opera_rc_keys {
> + u32 keycode;
> + u32 event;
> +};
> +///Send Querys
> +
> +#define QUERY_RC 0x01
> +#define WAIT_FOR_COMPLETE 0x02
> +
> +///Register on Cypress
> +
> +#define READ_FX2_REG_REQ 0xBA
> +#define OPERA_WRITE_FX2 0xBB
> +
> +#define OPERA_TUNER_REQ 0xB1
> +#define OPERA_TUNER1_REQ 0xb6
> +#define OPERA_TUNER2_REQ 0xb7
> +#define OPERA_REMOTE 0xB8
> +#define OPERA_TUNER4_REQ 0xbb
> +#define OPERA_TUNER5_REQ 0xbc
> +
> +#define USB_VID_OPERA1_WARM 0x695C /*do we have such a
> thing?*/ +#define USB_PID_OPERA1_COLD 0x2830
> +#define USB_PID_OPERA1_COLD2 0x8613
> +#define USB_PID_OPERA1_WARM 0x3829 /*do we have such a
> thing?*/ +
> +#endif
>
> It would be nice if someone with this device can review the driver also.
> Maybe there are other things which can be simplified..
ok the remote stuff ist not of good quality, but i found no better way until
today , because it will not read simple data and then use ist ( it receives
errors and bitshifts in data)
so i'd liek to out any comments and and make ist better quality
>
> HTH,
> Patrick.
_______________________________________________
linux-dvb mailing list
[email protected]
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb