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 <g.marco@xxxxxxxxxx> > > Signed-of-by: Mario Hlawitschka <dh1pa@xxxxxxxxx> > > 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) dh1pa@xxxxxxxxx"); > +MODULE_AUTHOR("Marco Gittler (c) g.marco@xxxxxxxxxx"); > +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 linux-dvb@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb