diff mbox

Drivers for Pinnacle pctv200e and pctv60e

Message ID 20090329155608.396d2257@gdc1 (mailing list archive)
State RFC
Headers show

Commit Message

Gabriele Dini Ciacci March 29, 2009, 1:56 p.m. UTC
Hello,

This is a stub patch to make the subjects card work.

I am using the driver on a pctv60e and it is very stable, I use it
daily. It should work for pctv200e but not owning the device I cannot
test it.

The code need to be cleaned, as I am not an experienced kernel coder.
The code in mt352.c contains an hard-coded address for the device, while
Pinnalce devices with that tuner uses a different address. Currently
the address is "hijacked" to be the correct one. This is a hack, and i
think that mt352.c should be changed to support multiple addresses,
selected via params, duplicate code or something.

Remote support is missing, cause it was not working out of the box. I
do not use it and so developing it for myself only was not very useful,
if someone wants it or is interested I can have a look.

The patch is generally messy, I need help there. I do not know if I
have to change all the functions to take as parameter an adapter_nr or
change the caller to continue to pass them a struct dvb_usb_device
obtained with i2c_get_adapdata(adapter_nr).

Here is the patch, as an attachment, thanks meanwhile.

Best Regards,
Gabriele Dini Ciacci

Signed-off-by: Gabriele Dini Ciacci <gab@diniciacci.org>


----------- 
http://linux-wildo.sf.net
http://www.diniciacci.org

Comments

Mauro Carvalho Chehab March 31, 2009, 10:56 a.m. UTC | #1
Hi Gabriele,

On Sun, 29 Mar 2009 15:56:08 +0200
Gabriele Dini Ciacci <dark.schneider@iol.it> wrote:

> Hello,
> 
> This is a stub patch to make the subjects card work.
> 
> I am using the driver on a pctv60e and it is very stable, I use it
> daily. It should work for pctv200e but not owning the device I cannot
> test it.
> 
> The code need to be cleaned, as I am not an experienced kernel coder.
> The code in mt352.c contains an hard-coded address for the device, while
> Pinnalce devices with that tuner uses a different address. Currently
> the address is "hijacked" to be the correct one. This is a hack, and i
> think that mt352.c should be changed to support multiple addresses,
> selected via params, duplicate code or something.
> 
> Remote support is missing, cause it was not working out of the box. I
> do not use it and so developing it for myself only was not very useful,
> if someone wants it or is interested I can have a look.
> 
> The patch is generally messy, I need help there. I do not know if I
> have to change all the functions to take as parameter an adapter_nr or
> change the caller to continue to pass them a struct dvb_usb_device
> obtained with i2c_get_adapdata(adapter_nr).
> 
> Here is the patch, as an attachment, thanks meanwhile.

Well, let's go by parts. 

It seems that you wrote your driver based on some USB sniffing. Do you know
what are the chipsets present on your driver? Maybe there's another driver
already developed or under development for the same chipset.

In the case of your patch, you should first run checkpatch.pl for it to show you
the non-compliances of your driver and Linux Kernel CodingStyle. checkpatch.pl
is avaliable at kernel tree, under /scripts dir. You'll also find it at v4l-dvb
development tree, at v4l/script/checkpatch.pl.

It is also a good idea to read README.patches at v4l-dvb development tree.

Cheers,
Mauro
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Gabriele Dini Ciacci March 31, 2009, 7:20 p.m. UTC | #2
On Tue, 31 Mar 2009 07:56:10 -0300
Mauro Carvalho Chehab <mchehab@infradead.org> wrote:

> Hi Gabriele,
> 
> On Sun, 29 Mar 2009 15:56:08 +0200
> Gabriele Dini Ciacci <dark.schneider@iol.it> wrote:
> 
> > Hello,
> > 
> > This is a stub patch to make the subjects card work.
> > 
> > I am using the driver on a pctv60e and it is very stable, I use it
> > daily. It should work for pctv200e but not owning the device I
> > cannot test it.
> > 
> > The code need to be cleaned, as I am not an experienced kernel
> > coder. The code in mt352.c contains an hard-coded address for the
> > device, while Pinnalce devices with that tuner uses a different
> > address. Currently the address is "hijacked" to be the correct one.
> > This is a hack, and i think that mt352.c should be changed to
> > support multiple addresses, selected via params, duplicate code or
> > something.
> > 
> > Remote support is missing, cause it was not working out of the box.
> > I do not use it and so developing it for myself only was not very
> > useful, if someone wants it or is interested I can have a look.
> > 
> > The patch is generally messy, I need help there. I do not know if I
> > have to change all the functions to take as parameter an adapter_nr
> > or change the caller to continue to pass them a struct
> > dvb_usb_device obtained with i2c_get_adapdata(adapter_nr).
> > 
> > Here is the patch, as an attachment, thanks meanwhile.
> 
> Well, let's go by parts. 
> 
> It seems that you wrote your driver based on some USB sniffing. Do
> you know what are the chipsets present on your driver? Maybe there's
> another driver already developed or under development for the same
> chipset.

I actually did not any sniffing at all. I was ready to go for it (so I
asked a windows guy to send me the sniff).
Obtained that, I started to look at it, then I
realized that v4l already had support for all the chipsets the thing
was using. I just made the code that connects the parts and such,
indeed the patch is only the main file, no low level chip file, or
anything else touched. So there is no actual code for the chipsets.
I'm using mt353 and mt2060, that are already in the main tree.

As I explained above, mt353.c makes a wrong assumption about the address
the chip has, at it also states that in a comment, explaining that on
pinnacle hardware (like in this case) the address is different. I just
had to hijack that and hack this. I was suggesting above to fix
mt353.c else, no pinnacle card with mt353 can be implemented with a
clean code.

> In the case of your patch, you should first run checkpatch.pl for it
> to show you the non-compliances of your driver and Linux Kernel
> CodingStyle. checkpatch.pl is avaliable at kernel tree,
> under /scripts dir. You'll also find it at v4l-dvb development tree,
> at v4l/script/checkpatch.pl.
> It is also a good idea to read README.patches at v4l-dvb development
> tree.
> 

I have checked coding style manually, I'll use the script.
I read README.patches the first time i coded the driver, reread it on
January when I updated the driver to the new interface and decided to
send it the first time to the ml on 01/06/2009. In January it was
outdated in regards to the new patch system adopted, wiki was also
outdated. I'll reread it to see if I am missing something and to check
if it needs to be updated to explain the new system for patch.

To sum up I will run checkpatch.pl and when it run fine I will resend
the patch.

But note that the problem with mt353.c stays, I do not have the
necessary confidence to change a low level chipset driver interface to
make it not assume an hardcoded adderss.

> Cheers,
> Mauro

Thanks, see you :)
Best Regards,
Gabriele

----------- 
http://linux-wildo.sf.net
http://www.diniciacci.org
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Devin Heitmueller March 31, 2009, 8:59 p.m. UTC | #3
On Tue, Mar 31, 2009 at 3:20 PM, Gabriele Dini Ciacci
<dark.schneider@iol.it> wrote:
> On Tue, 31 Mar 2009 07:56:10 -0300
> Mauro Carvalho Chehab <mchehab@infradead.org> wrote:
>
>> Hi Gabriele,
>>
>> On Sun, 29 Mar 2009 15:56:08 +0200
>> Gabriele Dini Ciacci <dark.schneider@iol.it> wrote:
>>
>> > Hello,
>> >
>> > This is a stub patch to make the subjects card work.
>> >
>> > I am using the driver on a pctv60e and it is very stable, I use it
>> > daily. It should work for pctv200e but not owning the device I
>> > cannot test it.
>> >
>> > The code need to be cleaned, as I am not an experienced kernel
>> > coder. The code in mt352.c contains an hard-coded address for the
>> > device, while Pinnalce devices with that tuner uses a different
>> > address. Currently the address is "hijacked" to be the correct one.
>> > This is a hack, and i think that mt352.c should be changed to
>> > support multiple addresses, selected via params, duplicate code or
>> > something.
>> >
>> > Remote support is missing, cause it was not working out of the box.
>> > I do not use it and so developing it for myself only was not very
>> > useful, if someone wants it or is interested I can have a look.
>> >
>> > The patch is generally messy, I need help there. I do not know if I
>> > have to change all the functions to take as parameter an adapter_nr
>> > or change the caller to continue to pass them a struct
>> > dvb_usb_device obtained with i2c_get_adapdata(adapter_nr).
>> >
>> > Here is the patch, as an attachment, thanks meanwhile.
>>
>> Well, let's go by parts.
>>
>> It seems that you wrote your driver based on some USB sniffing. Do
>> you know what are the chipsets present on your driver? Maybe there's
>> another driver already developed or under development for the same
>> chipset.
>
> I actually did not any sniffing at all. I was ready to go for it (so I
> asked a windows guy to send me the sniff).
> Obtained that, I started to look at it, then I
> realized that v4l already had support for all the chipsets the thing
> was using. I just made the code that connects the parts and such,
> indeed the patch is only the main file, no low level chip file, or
> anything else touched. So there is no actual code for the chipsets.
> I'm using mt353 and mt2060, that are already in the main tree.
>
> As I explained above, mt353.c makes a wrong assumption about the address
> the chip has, at it also states that in a comment, explaining that on
> pinnacle hardware (like in this case) the address is different. I just
> had to hijack that and hack this. I was suggesting above to fix
> mt353.c else, no pinnacle card with mt353 can be implemented with a
> clean code.
>
>> In the case of your patch, you should first run checkpatch.pl for it
>> to show you the non-compliances of your driver and Linux Kernel
>> CodingStyle. checkpatch.pl is avaliable at kernel tree,
>> under /scripts dir. You'll also find it at v4l-dvb development tree,
>> at v4l/script/checkpatch.pl.
>> It is also a good idea to read README.patches at v4l-dvb development
>> tree.
>>
>
> I have checked coding style manually, I'll use the script.
> I read README.patches the first time i coded the driver, reread it on
> January when I updated the driver to the new interface and decided to
> send it the first time to the ml on 01/06/2009. In January it was
> outdated in regards to the new patch system adopted, wiki was also
> outdated. I'll reread it to see if I am missing something and to check
> if it needs to be updated to explain the new system for patch.
>
> To sum up I will run checkpatch.pl and when it run fine I will resend
> the patch.
>
> But note that the problem with mt353.c stays, I do not have the
> necessary confidence to change a low level chipset driver interface to
> make it not assume an hardcoded adderss.
>
>> Cheers,
>> Mauro
>
> Thanks, see you :)
> Best Regards,
> Gabriele

Is this device not based on a Cypress FX2?  If so, then there
shouldn't be a new driver at all.  We would just need a device profile
in the existing driver.

http://linuxtv.org/wiki/index.php/Pinnacle_PCTV_60e

Devin
Gabriele Dini Ciacci March 31, 2009, 9:35 p.m. UTC | #4
On Tue, 31 Mar 2009 16:59:35 -0400
Devin Heitmueller <devin.heitmueller@gmail.com> wrote:

> On Tue, Mar 31, 2009 at 3:20 PM, Gabriele Dini Ciacci
> <dark.schneider@iol.it> wrote:
> > On Tue, 31 Mar 2009 07:56:10 -0300
> > Mauro Carvalho Chehab <mchehab@infradead.org> wrote:
> >
> >> Hi Gabriele,
> >>
> >> On Sun, 29 Mar 2009 15:56:08 +0200
> >> Gabriele Dini Ciacci <dark.schneider@iol.it> wrote:
> >>
> >> > Hello,
> >> >
> >> > This is a stub patch to make the subjects card work.
> >> >
> >> > I am using the driver on a pctv60e and it is very stable, I use
> >> > it daily. It should work for pctv200e but not owning the device I
> >> > cannot test it.
> >> >
> >> > The code need to be cleaned, as I am not an experienced kernel
> >> > coder. The code in mt352.c contains an hard-coded address for the
> >> > device, while Pinnalce devices with that tuner uses a different
> >> > address. Currently the address is "hijacked" to be the correct
> >> > one. This is a hack, and i think that mt352.c should be changed
> >> > to support multiple addresses, selected via params, duplicate
> >> > code or something.
> >> >
> >> > Remote support is missing, cause it was not working out of the
> >> > box. I do not use it and so developing it for myself only was
> >> > not very useful, if someone wants it or is interested I can have
> >> > a look.
> >> >
> >> > The patch is generally messy, I need help there. I do not know
> >> > if I have to change all the functions to take as parameter an
> >> > adapter_nr or change the caller to continue to pass them a struct
> >> > dvb_usb_device obtained with i2c_get_adapdata(adapter_nr).
> >> >
> >> > Here is the patch, as an attachment, thanks meanwhile.
> >>
> >> Well, let's go by parts.
> >>
> >> It seems that you wrote your driver based on some USB sniffing. Do
> >> you know what are the chipsets present on your driver? Maybe
> >> there's another driver already developed or under development for
> >> the same chipset.
> >
> > I actually did not any sniffing at all. I was ready to go for it
> > (so I asked a windows guy to send me the sniff).
> > Obtained that, I started to look at it, then I
> > realized that v4l already had support for all the chipsets the thing
> > was using. I just made the code that connects the parts and such,
> > indeed the patch is only the main file, no low level chip file, or
> > anything else touched. So there is no actual code for the chipsets.
> > I'm using mt353 and mt2060, that are already in the main tree.
> >
> > As I explained above, mt353.c makes a wrong assumption about the
> > address the chip has, at it also states that in a comment,
> > explaining that on pinnacle hardware (like in this case) the
> > address is different. I just had to hijack that and hack this. I
> > was suggesting above to fix mt353.c else, no pinnacle card with
> > mt353 can be implemented with a clean code.
> >
> >> In the case of your patch, you should first run checkpatch.pl for
> >> it to show you the non-compliances of your driver and Linux Kernel
> >> CodingStyle. checkpatch.pl is avaliable at kernel tree,
> >> under /scripts dir. You'll also find it at v4l-dvb development
> >> tree, at v4l/script/checkpatch.pl.
> >> It is also a good idea to read README.patches at v4l-dvb
> >> development tree.
> >>
> >
> > I have checked coding style manually, I'll use the script.
> > I read README.patches the first time i coded the driver, reread it
> > on January when I updated the driver to the new interface and
> > decided to send it the first time to the ml on 01/06/2009. In
> > January it was outdated in regards to the new patch system adopted,
> > wiki was also outdated. I'll reread it to see if I am missing
> > something and to check if it needs to be updated to explain the new
> > system for patch.
> >
> > To sum up I will run checkpatch.pl and when it run fine I will
> > resend the patch.
> >
> > But note that the problem with mt353.c stays, I do not have the
> > necessary confidence to change a low level chipset driver interface
> > to make it not assume an hardcoded adderss.
> >
> >> Cheers,
> >> Mauro
> >
> > Thanks, see you :)
> > Best Regards,
> > Gabriele
> 
> Is this device not based on a Cypress FX2?  If so, then there
> shouldn't be a new driver at all.  We would just need a device profile
> in the existing driver.
> 
> http://linuxtv.org/wiki/index.php/Pinnacle_PCTV_60e
> 
> Devin
> 

I it's so, say me how to make or where to look to create a profile for
the existing driver.

I am willing to do the work.

(when I first wrote the driver to me it seemed that this was the
simplet way.

Meanwhile I will try to look at the Cypress FX2

Thanks,
looking forward
Regards
Gabriele
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Devin Heitmueller March 31, 2009, 9:51 p.m. UTC | #5
On Tue, Mar 31, 2009 at 5:35 PM, Gabriele Dini Ciacci
<dark.schneider@iol.it> wrote:
> I it's so, say me how to make or where to look to create a profile for
> the existing driver.
>
> I am willing to do the work.
>
> (when I first wrote the driver to me it seemed that this was the
> simplet way.
>
> Meanwhile I will try to look at the Cypress FX2

As Michael Krufky pointed out to me off-list, I was not exactly correct here.

While there are indeed drivers based on the same FX2 chip in your
device, it may be possible to reuse an existing driver, or you may
need a whole new driver, depending on how much the firmware varies
between your product versus the others.  You may want to look at the
pvrusb2 and cxusb drivers, which also use the FX2 chip, and see what
similarities exist in terms of the API and command set.  If it is not
similar to any of the others, then writing a new driver is probably
the correct approach.

Regards,

Devin
Gabriele Dini Ciacci March 31, 2009, 10:47 p.m. UTC | #6
On Tue, 31 Mar 2009 17:51:23 -0400
Devin Heitmueller <devin.heitmueller@gmail.com> wrote:

> On Tue, Mar 31, 2009 at 5:35 PM, Gabriele Dini Ciacci
> <dark.schneider@iol.it> wrote:
> > I it's so, say me how to make or where to look to create a profile
> > for the existing driver.
> >
> > I am willing to do the work.
> >
> > (when I first wrote the driver to me it seemed that this was the
> > simplet way.
> >
> > Meanwhile I will try to look at the Cypress FX2
> 
> As Michael Krufky pointed out to me off-list, I was not exactly
> correct here.
> 
> While there are indeed drivers based on the same FX2 chip in your
> device, it may be possible to reuse an existing driver, or you may
> need a whole new driver, depending on how much the firmware varies
> between your product versus the others.  You may want to look at the
> pvrusb2 and cxusb drivers, which also use the FX2 chip, and see what
> similarities exist in terms of the API and command set.  If it is not
> similar to any of the others, then writing a new driver is probably
> the correct approach.
> 
> Regards,
> 
> Devin
> 

Fine perfect, thanks,

I will have a look asap and report for judge.

Cheers.
Gabriele

----------- 
http://linux-wildo.sf.net
http://www.diniciacci.org
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Patrick Boettcher April 1, 2009, 7:34 a.m. UTC | #7
Hi all,

On Wed, 1 Apr 2009, Gabriele Dini Ciacci wrote:
>> While there are indeed drivers based on the same FX2 chip in your
>> device, it may be possible to reuse an existing driver, or you may
>> need a whole new driver, depending on how much the firmware varies
>> between your product versus the others.  You may want to look at the
>> pvrusb2 and cxusb drivers, which also use the FX2 chip, and see what
>> similarities exist in terms of the API and command set.  If it is not
>> similar to any of the others, then writing a new driver is probably
>> the correct approach.
>>
>> Regards,
>>
>> Devin
>>
>
> Fine perfect, thanks,
>
> I will have a look asap and report for judge.

I think you can save the time... When I started on a driver for those two 
devices 4 years ago, I had almost everything finished, but at that time we 
hadn't had a mt2060 driver available.

I think I still have that driver somewhere, I'll check that and will send 
it to the list if I can find it. (at least the I2C-part was a little bit 
cleaner, IIRC).

Gabriele, btw. there is nothing wrong with the I2C-address in your driver. 
setting 0x3e to the demod-address-field in the config-struct is totally 
fine.

OTOH, your problem of unterstanding is most likely the notation used for 
i2c-addresses in linux: In Linux's drivers you'll find the 7-bit notation 
of the chip's i2c-address where as outside Linux, IMO, usually the 8-bit 
(wrong) notation is used:

In the i2c-protocol the first byte of communication is the address plus a 
bit (the LSB) which is indicating wheter it is a read or write access.

ie: AAAA AAAD, where A is address-bits and D is direction.

In Linux what you'll see is e.g 0x1f which is the 7 bit address of 0x3e. 
The same for the tuner 0xc0 or 0xc2 is in Linux 0x60 and 0x61. Or the 
eeprom 0xa0 -> 0x50

On the various USB-2-I2C interfaces most of the time the 8 bit notation is 
used, that why you'll have to shift the address << 1 before filling the 
buffer in the i2c_transfer function.

HTH,
Patrick.

--
   Mail: patrick.boettcher@desy.de
   WWW:  http://www.wi-bw.tfh-wildau.de/~pboettch/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Patrick Boettcher April 1, 2009, 3:27 p.m. UTC | #8
Hi,

On Wed, 1 Apr 2009, Gabriele Dini Ciacci wrote:

> On Tue, 31 Mar 2009 17:51:23 -0400
> Devin Heitmueller <devin.heitmueller@gmail.com> wrote:
>
>> On Tue, Mar 31, 2009 at 5:35 PM, Gabriele Dini Ciacci
>> <dark.schneider@iol.it> wrote:
>>> I it's so, say me how to make or where to look to create a profile
>>> for the existing driver.
>>>
>>> I am willing to do the work.
>>>
>>> (when I first wrote the driver to me it seemed that this was the
>>> simplet way.
>>>
>>> Meanwhile I will try to look at the Cypress FX2
>>
>> As Michael Krufky pointed out to me off-list, I was not exactly
>> correct here.
>>
>> While there are indeed drivers based on the same FX2 chip in your
>> device, it may be possible to reuse an existing driver, or you may
>> need a whole new driver, depending on how much the firmware varies
>> between your product versus the others.  You may want to look at the
>> pvrusb2 and cxusb drivers, which also use the FX2 chip, and see what
>> similarities exist in terms of the API and command set.  If it is not
>> similar to any of the others, then writing a new driver is probably
>> the correct approach.
>>
>> Regards,
>>
>> Devin
>>
>
> Fine perfect, thanks,

Attached you can find my attempts from 2005. I2C should work, please 
re-use this implementation as it nicely splits i2c_transfer from the rest 
of the required functionality.

I think I still have the pctv 200e somewhere in a box... I may get it 
back, undust it and try.

Patrick.

--
   Mail: patrick.boettcher@desy.de
   WWW:  http://www.wi-bw.tfh-wildau.de/~pboettch/
/* DVB USB compliant linux driver for the Pinnacle PCTV 200e DVB-T USB2.0 receiver.
 *
 * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
 *
 *  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
 */

#ifndef _DVB_USB_PCTV_H_
#define _DVB_USB_PCTV_H_

#define DVB_USB_LOG_PREFIX "pctv"
#include "dvb-usb.h"

extern int dvb_usb_pctv_debug;
#define deb_info(args...)   dprintk(dvb_usb_pctv_debug,0x01,args)

#define CMD_I2C_WRITE  0x01
/* out: <addr << 1> <olen> <buf>[olen]
 *  in: 0x00 */

#define CMD_I2C_READ   0x02
/* out: <addr << 1> <olen> <ilen> <buf>[olen]
 *  in: 0x00 <buf>[ilen] */

#define CMD_GPIO_TUNER 0x16
/* out: <onoff>
 *  in: 0x00 */

//#define CMD_STREAMING  0x18
/* out: <onoff>
 *  in: 0x00 */


#endif
/* DVB USB compliant linux driver for the Pinnacle PCTV 200e DVB-T USB2.0 receiver.
 *
 * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
 *
 *	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 "pctv.h"

#include "mt352.h"

/* debug */
int dvb_usb_pctv_debug;
module_param_named(debug,dvb_usb_pctv_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=debug (or-able))." DVB_USB_DEBUG_STATUS);

static int pctv_msg(struct dvb_usb_device *d, u8 cmd,
		u8 *wbuf, int wlen, u8 *rbuf, int rlen)
{
	int ret;
	u8 sndbuf[wlen+1],
	   rcvbuf[rlen+2];
	memset(sndbuf,0,wlen+1);

	sndbuf[0] = cmd;
	memcpy(&sndbuf[1],wbuf,wlen);

	if ((ret = dvb_usb_generic_rw(d,sndbuf,wlen+1,rcvbuf,rlen+2,0)) < 0)
		return ret;

	if (rcvbuf[0] != sndbuf[0] ||
		rcvbuf[1] != 0x00)
		err("probably a xfer error");

	memcpy(rbuf,&rcvbuf[2],rlen);

	if (rlen > 0)
		deb_info("rbuf[0]: %x, rlen: %d\n",rbuf[0],rlen);

	return 0;
}

static int pctv_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
{
	struct dvb_usb_device *d = i2c_get_adapdata(adap);
	static u8 obuf[255];
	int i,read;;

	if (down_interruptible(&d->i2c_sem) < 0)
		return -EAGAIN;

	if (num > 2)
		warn("more than 2 i2c messages at a time is not handled yet. TODO.");

	for (i = 0; i < num; i++) {
		read = i+1 < num && (msg[i+1].flags & I2C_M_RD);

		obuf[0] = msg[i].addr << 1;
		obuf[1] = msg[i].len;

		/* read request */
		if (read)
			obuf[2] = msg[i+1].len;

		memcpy(&obuf[2+read],msg[i].buf,msg[i].len);

		if (read)
			pctv_msg(d,CMD_I2C_READ,obuf,msg[i].len+3,msg[i+1].buf,msg[i+1].len);
		else
			pctv_msg(d,CMD_I2C_WRITE,obuf,msg[i].len+2,NULL,0);

		i += read;

	}

	up(&d->i2c_sem);
	return i;
}

static u32 pctv_i2c_func(struct i2c_adapter *adapter)
{
	return I2C_FUNC_I2C;
}

static struct i2c_algorithm pctv_i2c_algo = {
	.name          = "Pinnacle PCTV USB I2C algorithm",
	.id            = I2C_ALGO_BIT,
	.master_xfer   = pctv_i2c_xfer,
	.functionality = pctv_i2c_func,
};

/* GPIO */
static void pctv_gpio_tuner(struct dvb_usb_device *d, int onoff)
{
//struct cxusb_state *st = d->priv;
	u8 o;

//	if (st->gpio_write_state[GPIO_TUNER] == onoff)
//		return;

	o = onoff;
	pctv_msg(d,CMD_GPIO_TUNER,&o,1,NULL,0);
}

static int pctv_power_ctrl(struct dvb_usb_device *d, int onoff)
{
	return 0;
}

static int pctv_streaming_ctrl(struct dvb_usb_device *d, int onoff)
{
	return 0;
}

static int pctv_mt352_demod_init(struct dvb_frontend *fe)
{
	static u8 reset_buf[] = { 0x89, 0xbd,  0x8a, 0x28, 0x50, 0x80 };
	static u8 init_buf[] = { 0x50, 0x00, 0x8e, 0x40,  0x56, 0x31, 0x57, 0xb5,
		0x8b, 0x09, 0x88, 0x0d, 0x7b, 0x04, 0x53, 0xf4, 0x5e, 0x01, 0x54,
		0x73, 0x55, 0x1c, 0x75, 0x30, 0x67, 0x1c, 0x67, 0x00 };
	int i;

	for (i = 0; i < ARRAY_SIZE(reset_buf); i += 2)
		mt352_write(fe, &reset_buf[i], 2);

	msleep(1);

	for (i = 0; i < ARRAY_SIZE(init_buf); i += 2)
		mt352_write(fe, &init_buf[i], 2);

	return 0;
}

static struct mt352_config pctv_mt352_config = {
	.demod_address = 0x1f,

	.demod_init = pctv_mt352_demod_init,

//.pll_init = NULL, /* it'll be mt2060_init */
	.pll_set = dvb_usb_pll_set, /* probably not, it's rather mt2060_set */
};

/* Callbacks for DVB USB */
static int pctv_tuner_attach(struct dvb_usb_device *d)
{
	u8 bpll[4] = { 0x0b, 0xdc, 0x9c, 0xa0 };
	d->pll_addr = 0x61;
	memcpy(d->pll_init,bpll,4);
	d->pll_desc = &dvb_pll_fmd1216me;
	return 0;
}

static int pctv_frontend_attach(struct dvb_usb_device *d)
{
	u8 o=0,i=0;

	pctv_msg(d,0x10,&o,1,&i,1);

	pctv_msg(d,0x15,NULL,0,NULL,0);

	pctv_gpio_tuner(d, 0);
	if ((d->fe = mt352_attach(&pctv_mt352_config, &d->i2c_adap)) != NULL)
		return 0;

	return -EIO;
}

/* DVB USB Driver stuff */
static struct dvb_usb_properties pctv_properties;

static int pctv_probe(struct usb_interface *intf,
		const struct usb_device_id *id)
{
	return dvb_usb_device_init(intf,&pctv_properties,THIS_MODULE,NULL);
}

static struct usb_device_id pctv_table [] = {
		{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_200E) },
		{}		/* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, pctv_table);

static struct dvb_usb_properties pctv_properties = {
	.caps = DVB_USB_IS_AN_I2C_ADAPTER,

	.size_of_priv     = 0,

	.streaming_ctrl   = pctv_streaming_ctrl,
	.power_ctrl       = pctv_power_ctrl,
	.frontend_attach  = pctv_frontend_attach,
	.tuner_attach     = pctv_tuner_attach,

	.i2c_algo         = &pctv_i2c_algo,

	.generic_bulk_ctrl_endpoint = 0x01,
	/* parameter for the MPEG2-data transfer */
	.urb = {
		.type = DVB_USB_BULK,
		.count = 7,
		.endpoint = 0x02,
		.u = {
			.bulk = {
				.buffersize = 4096,
			}
		}
	},

	.num_device_descs = 1,
	.devices = {
		{   "Pinnacle 200e DVB-T USB2.0",
			{ NULL },
			{ &pctv_table[0], NULL },
		},
	}
};

static struct usb_driver pctv_driver = {
	.owner		= THIS_MODULE,
	.name		= "pctv_200e",
	.probe		= pctv_probe,
	.disconnect = dvb_usb_device_exit,
	.id_table	= pctv_table,
};

/* module stuff */
static int __init pctv_module_init(void)
{
	int result;
	if ((result = usb_register(&pctv_driver))) {
		err("usb_register failed. Error number %d",result);
		return result;
	}

	return 0;
}

static void __exit pctv_module_exit(void)
{
	/* deregister this driver from the USB subsystem */
	usb_deregister(&pctv_driver);
}

module_init (pctv_module_init);
module_exit (pctv_module_exit);

MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
MODULE_DESCRIPTION("Driver for Pinnacle 200e DVB-T USB2.0 receiver");
MODULE_VERSION("1.0-alpha");
MODULE_LICENSE("GPL");
Gabriele Dini Ciacci April 1, 2009, 6:28 p.m. UTC | #9
On Wed, 1 Apr 2009 17:27:04 +0200 (CEST)
Patrick Boettcher <patrick.boettcher@desy.de> wrote:

> Hi,
> 
> On Wed, 1 Apr 2009, Gabriele Dini Ciacci wrote:
> 
> > On Tue, 31 Mar 2009 17:51:23 -0400
> > Devin Heitmueller <devin.heitmueller@gmail.com> wrote:
> >
> >> On Tue, Mar 31, 2009 at 5:35 PM, Gabriele Dini Ciacci
> >> <dark.schneider@iol.it> wrote:
> >>> I it's so, say me how to make or where to look to create a profile
> >>> for the existing driver.
> >>>
> >>> I am willing to do the work.
> >>>
> >>> (when I first wrote the driver to me it seemed that this was the
> >>> simplet way.
> >>>
> >>> Meanwhile I will try to look at the Cypress FX2
> >>
> >> As Michael Krufky pointed out to me off-list, I was not exactly
> >> correct here.
> >>
> >> While there are indeed drivers based on the same FX2 chip in your
> >> device, it may be possible to reuse an existing driver, or you may
> >> need a whole new driver, depending on how much the firmware varies
> >> between your product versus the others.  You may want to look at
> >> the pvrusb2 and cxusb drivers, which also use the FX2 chip, and
> >> see what similarities exist in terms of the API and command set.
> >> If it is not similar to any of the others, then writing a new
> >> driver is probably the correct approach.
> >>
> >> Regards,
> >>
> >> Devin
> >>
> >
> > Fine perfect, thanks,
> 
> Attached you can find my attempts from 2005. I2C should work, please 
> re-use this implementation as it nicely splits i2c_transfer from the
> rest of the required functionality.
> 
> I think I still have the pctv 200e somewhere in a box... I may get it 
> back, undust it and try.
> 
> Patrick.
> 
> --
>    Mail: patrick.boettcher@desy.de
>    WWW:  http://www.wi-bw.tfh-wildau.de/~pboettch/

I had a quick look (1 min) and I think the interface is to port to the
new "style" used. I can merge my version of the driver with your and
get a final driver, indeed your i2c is much better, as I coded i2c as a
i2c ignorant, so just copying from the other drivers. I will just take
your implementation for that part.

Thanks a lot for the i2c explanation, that explains! Now my view is
much clearer.

So what if I try to merge the two drivers to get a clean one, test them
on pctv60e, you test them on pctv200e and... done!

The cherry would be to spend some time on the IR also, but just wait to
have a driver.

Regards & cheers,
Gabriele
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff -uprN v4l-dvd/linux/drivers/media/dvb/dvb-usb/Kconfig my_v4l-dvb/linux/drivers/media/dvb/dvb-usb/Kconfig
--- v4l-dvd/linux/drivers/media/dvb/dvb-usb/Kconfig	2009-01-06 00:16:39.000000000 +0100
+++ my_v4l-dvb/linux/drivers/media/dvb/dvb-usb/Kconfig	2009-01-06 15:22:31.000000000 +0100
@@ -299,3 +299,9 @@  config DVB_USB_AF9015
 	select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE
 	help
 	  Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver
+
+config DVB_USB_PCTV200E
+	tristate "Pinnacle PCTV200e and PCTV60e support"
+	depends on DVB_USB && EXPERIMENTAL
+	help
+	  Say Y here to support for PCTV200e or PCTV60e
diff -uprN v4l-dvd/linux/drivers/media/dvb/dvb-usb/Makefile my_v4l-dvb/linux/drivers/media/dvb/dvb-usb/Makefile
--- v4l-dvd/linux/drivers/media/dvb/dvb-usb/Makefile	2009-01-06 00:16:39.000000000 +0100
+++ my_v4l-dvb/linux/drivers/media/dvb/dvb-usb/Makefile	2009-01-06 00:20:40.000000000 +0100
@@ -54,6 +54,8 @@  obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb
 dvb-usb-opera-objs = opera1.o
 obj-$(CONFIG_DVB_USB_OPERA1) += dvb-usb-opera.o
 
+dvb-usb-pctv200e-objs = pctv200e.o
+obj-$(CONFIG_DVB_USB_PCTV200E) += dvb-usb-pctv200e.o
 
 dvb-usb-af9005-objs = af9005.o af9005-fe.o
 obj-$(CONFIG_DVB_USB_AF9005) += dvb-usb-af9005.o
diff -uprN v4l-dvd/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h my_v4l-dvb/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
--- v4l-dvd/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h	2009-01-06 00:16:39.000000000 +0100
+++ my_v4l-dvb/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h	2009-01-06 00:31:01.000000000 +0100
@@ -174,6 +174,7 @@ 
 #define USB_PID_PINNACLE_PCTV73E			0x0237
 #define USB_PID_PINNACLE_PCTV801E			0x023a
 #define USB_PID_PINNACLE_PCTV801E_SE			0x023b
+#define USB_PID_PCTV_60E				0x0216
 #define USB_PID_PCTV_200E				0x020e
 #define USB_PID_PCTV_400E				0x020f
 #define USB_PID_PCTV_450E				0x0222
diff -uprN v4l-dvd/linux/drivers/media/dvb/dvb-usb/pctv200e.c my_v4l-dvb/linux/drivers/media/dvb/dvb-usb/pctv200e.c
--- v4l-dvd/linux/drivers/media/dvb/dvb-usb/pctv200e.c	1970-01-01 01:00:00.000000000 +0100
+++ my_v4l-dvb/linux/drivers/media/dvb/dvb-usb/pctv200e.c	2009-01-06 15:30:32.000000000 +0100
@@ -0,0 +1,644 @@ 
+/*
+ * DVB USB compliant linux driver for Pinnacle PCTV 200e DVB-T reciever
+ *
+ * Copyright (C) 2008 Gabriele Dini Ciacci <gab@diniciacci.org>
+ *               2007 Jakob Steidl (jakob.steidl@gmail.com)
+ *               based on  Patrick Boettcher's driver for the Nebula Electronics uDigiTV
+ *
+ *
+ *	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
+ */
+
+// mt352 registers
+#define CLOCK_CTL		0x89
+#define RESET			0x50
+#define	ACQ_CTL         	0x53
+#define	TRL_NOMINAL_RATE_1  	0x54
+#define	INPUT_FREQ_1    	0x56
+#define	UNKNOWN_3	    	0x5e
+#define AGC_TARGET		0x67
+#define CAPT_RANGE		0x75
+#define	SNR_SELECT_1    	0x79
+#define UNKNOWN_1		0x7B
+#define	SCAN_CTL		0x88
+#define	MCLK_RATIO		0x8B
+#define GPP_CTL			0x8C
+#define ADC_CTL_1		0x8E
+#define UNKNOWN_2		0x98
+
+#include "pctv200e.h"
+
+#include "dvb-usb.h"
+#include "mt352.h"
+#include "mt2060.h"
+#include "mt2060_priv.h"
+
+
+
+/* debug */
+// To enable the debug set a value 1 for dvb_usb_pctv200e_debug
+int dvb_usb_pctv200e_debug=0;
+static int ctrl_msg_last_device=0;
+static int ctrl_msg_last_operation=0;
+
+static struct mt352_config pctv200e_mt352_config;
+static struct mt2060_config pctv200e_mt2060_config;
+
+module_param_named(debug,dvb_usb_pctv200e_debug, int, 0644);
+MODULE_PARM_DESC( debug, "Set debug level (1=info,xfer=2,rc=4 (RC is the codeword for ALL ;) (|-able))." DVB_USB_DEBUG_STATUS );
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+/* I2C */
+/*
+01 c0 02 03 80
+ -  request type (read: 0x01, write: 0x02)
+     - addr to be read or written (0xc0 ... tuner)
+	 - number of of bits that follow
+	     - just data
+		 - data (optional, if number data >1)
+*/
+
+static int pctv200e_ctrl_msg(struct dvb_usb_device *d,
+		u8 addr, u8 rw, u8 reg, u8 *wbuf, int wlen, u8 *rbuf,int rlen)
+{
+	// atm,  u8 rw is being ignored, it should be clear from the
+	int wo = (rbuf == NULL || rlen == 0); /* then its a write-only*/
+	int counter;
+	u8 sndbuf[5],rcvbuf[64] = { 0 };
+//	u8 sndbuf[8],rcvbuf[5]; /* actually we don't know the max. answer lenght //yet.. 
+
+	if (wlen>64) {
+		warn ("pctv200e_ctrl_msg: failed, command too long!");
+		return 0;
+	}
+
+	memset(sndbuf,0,5); memset(rcvbuf,0,64);
+
+	if (ctrl_msg_last_device == 0) {
+
+// The very first time we send the following sequence "0x15 0x80" and then "0x16 0x00"
+		sndbuf[0] = 0x15;
+		sndbuf[1] = 0x80;
+		dvb_usb_generic_rw(d,sndbuf,2,rcvbuf,64,4);
+		if (dvb_usb_pctv200e_debug) {
+			warn("crtl_msg() wlen: %d, rlen: %d, READ: %x %x %x %x %x",wlen,rlen,sndbuf[0],sndbuf[1],sndbuf[2],sndbuf[3],sndbuf[4]);
+			warn("crtl_msg() RECEIVED: %x %x %x %x %x %x %x %x %x %x %x %x %x",rcvbuf[0],rcvbuf[1],rcvbuf[2],rcvbuf[3],rcvbuf[4],rcvbuf[5],rcvbuf[6],rcvbuf[7],rcvbuf[8],rcvbuf[9],rcvbuf[10],rcvbuf[11],rcvbuf[12]);
+
+			sndbuf[0] = 0x16;
+			sndbuf[1] = 0x00;
+			dvb_usb_generic_rw(d,sndbuf,2,rcvbuf,64,4);
+			warn("crtl_msg() wlen: %d, rlen: %d, READ: %x %x %x %x %x",wlen,rlen,sndbuf[0],sndbuf[1],sndbuf[2],sndbuf[3],sndbuf[4]);
+			warn("crtl_msg() RECEIVED: %x %x %x %x %x %x %x %x %x %x %x %x %x",rcvbuf[0],rcvbuf[1],rcvbuf[2],rcvbuf[3],rcvbuf[4],rcvbuf[5],rcvbuf[6],rcvbuf[7],rcvbuf[8],rcvbuf[9],rcvbuf[10],rcvbuf[11],rcvbuf[12]);
+		}
+	} 
+
+	// Now start to check the last operation and send the intermedium sequence	
+	// If the command is sent to the tuner mt2060
+	// first we sent the sequence "0x16 0x01", and below after the command
+	// then we send the sequence "0x16 0x00".
+	// This is not needed when the command goes to the demod mt352
+
+	if (addr == pctv200e_mt2060_config.i2c_address ) {
+
+		sndbuf[0] = 0x16;
+		sndbuf[1] = 0x01;
+		dvb_usb_generic_rw(d,sndbuf,2,rcvbuf,64,4);
+
+		if (dvb_usb_pctv200e_debug) {
+			warn("crtl_msg() wlen: %d, rlen: %d, READ: %x %x %x %x %x",wlen,rlen,sndbuf[0],sndbuf[1],sndbuf[2],sndbuf[3],sndbuf[4]);
+			warn("crtl_msg() RECEIVED: %x %x %x %x %x %x %x %x %x %x %x %x %x",rcvbuf[0],rcvbuf[1],rcvbuf[2],rcvbuf[3],rcvbuf[4],rcvbuf[5],rcvbuf[6],rcvbuf[7],rcvbuf[8],rcvbuf[9],rcvbuf[10],rcvbuf[11],rcvbuf[12]);
+		}
+
+	}
+
+	sndbuf[1] = addr;
+
+	ctrl_msg_last_device = addr;
+	// We store who which address was access (DEMOD or TUNER)
+//	memcpy(&sndbuf[5],wbuf,wlen);
+
+	if (wo) {
+		ctrl_msg_last_operation = 0x01;
+		sndbuf[0] = 0x01;
+		sndbuf[2] = 0x02;
+		sndbuf[3] = reg;
+
+		// We convert multiple writes into single writes
+		for (counter=0; counter < wlen; counter++) {
+			sndbuf[4] = wbuf[counter];
+
+		// For Pinnacle cards it should be send 0xf4 for ACQ_CTL as mentioned
+		// in mt352.c. At this moment the mt352.c send by default 0x50,
+		// so we intercept and change the value here.
+		// This way we don't need to change  mt352.c
+
+			if ((addr == 0x3e) & (sndbuf[3] == ACQ_CTL) & (sndbuf[4] == 0x50)) {
+				if (dvb_usb_pctv200e_debug)
+					warn("crtl_msg(): Changed ACQ_CTL value to 0xf4!!!");
+				sndbuf[4] = 0xf4;
+			}
+
+//			memcpy(&sndbuf[3],wbuf,wlen);
+			if (dvb_usb_pctv200e_debug) {
+				warn("crtl_msg() wlen: %d, rlen: %d,WRITE: %x %x %x %x %x",wlen,rlen,sndbuf[0],sndbuf[1],sndbuf[2],sndbuf[3],sndbuf[4]);
+			}
+
+			dvb_usb_generic_rw(d,sndbuf,5,rcvbuf,64,4);
+
+			if (dvb_usb_pctv200e_debug) {
+				warn("crtl_msg() RECEIVED: %x %x %x %x %x %x %x %x %x %x %x %x %x",rcvbuf[0],rcvbuf[1],rcvbuf[2],rcvbuf[3],rcvbuf[4],rcvbuf[5],rcvbuf[6],rcvbuf[7],rcvbuf[8],rcvbuf[9],rcvbuf[10],rcvbuf[11],rcvbuf[12]);
+			}
+
+			if (rcvbuf[0] != 0x1) {
+			warn("crtl_msg() WRITE ERROR: returned byte [0] not 0x1");
+//			return -EIO;
+			}
+
+			if (rcvbuf[1] != 0x0) {
+			warn("crtl_msg() WRITE ERROR: returned error!");
+//			return -EIO;
+			}
+			// it is write_regs, so we increment the register value
+			sndbuf[3] = sndbuf[3]+1;
+		}
+
+	} else {
+		ctrl_msg_last_operation = 0x02;
+		sndbuf[0] = 0x02;
+		sndbuf[2] = 0x01;
+		sndbuf[3] = 0x01;
+		sndbuf[4] = reg;
+
+		if (dvb_usb_pctv200e_debug) {
+			warn("crtl_msg() wlen: %d, rlen: %d, READ: %x %x %x %x %x",wlen,rlen,sndbuf[0],sndbuf[1],sndbuf[2],sndbuf[3],sndbuf[4]);
+		}
+
+		dvb_usb_generic_rw(d,sndbuf,5,rcvbuf,64,4);
+
+		if (rlen > 0) {
+			memcpy(rbuf,&rcvbuf[2],rlen);
+		}
+
+		if (dvb_usb_pctv200e_debug) {
+			warn("crtl_msg() RECEIVED: %x %x %x %x %x %x %x %x %x %x %x %x %x",rcvbuf[0],rcvbuf[1],rcvbuf[2],rcvbuf[3],rcvbuf[4],rcvbuf[5],rcvbuf[6],rcvbuf[7],rcvbuf[8],rcvbuf[9],rcvbuf[10],rcvbuf[11],rcvbuf[12]);
+		}
+	}
+
+	if (addr == pctv200e_mt2060_config.i2c_address ) {
+
+		sndbuf[0] = 0x16;
+		sndbuf[1] = 0x00;
+		dvb_usb_generic_rw(d,sndbuf,2,rcvbuf,64,4);
+
+		if (dvb_usb_pctv200e_debug) {
+			warn("crtl_msg() wlen: %d, rlen: %d, READ: %x %x %x %x %x",wlen,rlen,sndbuf[0],sndbuf[1],sndbuf[2],sndbuf[3],sndbuf[4]);
+			warn("crtl_msg() RECEIVED: %x %x %x %x %x %x %x %x %x %x %x %x %x",rcvbuf[0],rcvbuf[1],rcvbuf[2],rcvbuf[3],rcvbuf[4],rcvbuf[5],rcvbuf[6],rcvbuf[7],rcvbuf[8],rcvbuf[9],rcvbuf[10],rcvbuf[11],rcvbuf[12]);
+		}
+
+	}
+
+	return 0;
+}
+
+static int pctv200e_cmd_msg(struct dvb_usb_device *d, u8 *wbuf, int wlen)
+{
+	u8 sndbuf[64] = { 0 };
+	u8 rcvbuf[64] = { 0 };
+//	u8 sndbuf[8],rcvbuf[5]; /* actually we don't know the max. answer lenght //yet.. */
+	if (wlen>64) {
+		warn ("pctv200e_cmd_msg: failed, command too long!");
+		return 0;
+	}
+	memset(sndbuf,0,64); memset(rcvbuf,0,64);
+	memcpy(sndbuf,wbuf,wlen);
+
+	if (dvb_usb_pctv200e_debug)
+		warn("cmd_msg() wlen: %d, WRITE: %x %x %x %x %x",wlen,sndbuf[0],sndbuf[1],sndbuf[2],sndbuf[3],sndbuf[4]);
+
+	dvb_usb_generic_rw(d,sndbuf,wlen,rcvbuf,64,4);
+
+	if (rcvbuf[1] != 0x00) {
+		warn("crtl_msg() WRITE ERROR: returned error!");
+	}
+
+	if (dvb_usb_pctv200e_debug)
+		warn("cmd_msg() RECEIVED: %x %x %x %x %x %x %x %x %x %x %x %x %x",rcvbuf[0],rcvbuf[1],rcvbuf[2],rcvbuf[3],rcvbuf[4],rcvbuf[5],rcvbuf[6],rcvbuf[7],rcvbuf[8],rcvbuf[9],rcvbuf[10],rcvbuf[11],rcvbuf[12]);
+
+	return 0;
+}
+
+
+static int pctv200e_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
+{
+	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	int i;
+
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+		return -EAGAIN;
+
+	if (num > 2)
+		warn("more than 2 i2c messages at a time is not handled yet. TODO.");
+
+	for (i = 0; i < num; i++) {
+		/* write/read request */
+		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
+			if (pctv200e_ctrl_msg(d, msg[i].addr,USB_READ, msg[i].buf[0], NULL, 0, msg[i+1].buf,msg[i+1].len) < 0)
+				break;
+			i++;
+		} else
+			if (pctv200e_ctrl_msg(d,msg[i].addr,USB_WRITE, msg[i].buf[0],&msg[i].buf[1],msg[i].len-1,NULL,0) < 0)
+				break;
+	}
+
+	mutex_unlock(&d->i2c_mutex);
+	if (dvb_usb_pctv200e_debug)
+		warn("pctv200e_i2c_xfer() called.");
+	return i;
+}
+
+static u32 pctv200e_i2c_func(struct i2c_adapter *adapter)
+{
+	warn ("pctv200e_i2c_func: entering, done nothing");
+	return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm pctv200e_i2c_algo = {
+	.master_xfer   = pctv200e_i2c_xfer,
+	.functionality = pctv200e_i2c_func,
+};
+
+/* Callbacks for DVB USB */
+static int pctv200e_identify_state (struct usb_device *udev, struct
+		dvb_usb_device_properties *props, struct dvb_usb_device_description **desc,
+		int *cold)
+{
+	*cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0;
+	return 0;
+}
+// probably this needs to be changed.
+static int pctv200e_mt352_demod_init(struct dvb_frontend *fe)
+{
+//	We implement the RESET sequence for the demod mt352
+	static u8 clock_config []  = { CLOCK_CTL,  0xbd, 0x28 };
+	static u8 reset []         = { RESET,      0x80 };
+	static u8 reset_stop []    = { RESET,      0x00 };
+	static u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
+	static u8 agc_cfg []       = { AGC_TARGET, 0x1c };
+//	static u8 gpp_ctl_cfg []   = { GPP_CTL,    0x33 };
+	static u8 capt_range_cfg[] = { CAPT_RANGE, 0x30 };
+
+	static u8 input_freq[]        = { INPUT_FREQ_1, 0x31, 0xb5 };
+	static u8 clock_ratio[]       = { MCLK_RATIO, 0x00 };
+	static u8 scan_ctl[]          = { SCAN_CTL, 0x0d };
+	static u8 unknown_1[]         = { UNKNOWN_1, 0x04 };
+
+	static u8 acq_ctl[]           = { ACQ_CTL, 0xf4 };
+
+	static u8 trl_nominal_rate[]  = { TRL_NOMINAL_RATE_1, 0x73, 0x1c };
+
+	static u8 unknown_2[]  = { UNKNOWN_2, 0x00, 0x00, 0x80, 0x20, 0x80, 0x80, 0x55, 0x62, 0x00 };
+
+	static u8 unknown_3[]  = { UNKNOWN_3, 0x01 };
+
+//	static u8 snr_select_1[]  = { SNR_SELECT_1, 0x20, 0x00 };
+
+	mt352_write(fe, clock_config,   sizeof(clock_config));
+	udelay(1000);
+	mt352_write(fe, reset,          sizeof(reset));
+	mt352_write(fe, reset_stop,     sizeof(reset_stop));
+
+	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
+	mt352_write(fe, input_freq,     sizeof(input_freq));
+	mt352_write(fe, clock_ratio,    sizeof(clock_ratio));
+	mt352_write(fe, scan_ctl,       sizeof(scan_ctl));
+
+	mt352_write(fe, unknown_1,      sizeof(unknown_1));
+
+	mt352_write(fe, acq_ctl,          sizeof(acq_ctl));
+	mt352_write(fe, capt_range_cfg,   sizeof(capt_range_cfg));
+	mt352_write(fe, agc_cfg,          sizeof(agc_cfg));
+	mt352_write(fe, trl_nominal_rate, sizeof(trl_nominal_rate));
+
+	mt352_write(fe, unknown_2,      sizeof(unknown_2));
+	mt352_write(fe, unknown_3,      sizeof(unknown_3));
+
+//	mt352_write(fe, snr_select_1,   sizeof(snr_select_1));
+//	mt352_write(fe, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
+
+	warn ("PCTV200e initialized mt352");
+	return 0;
+}
+
+static struct mt352_config pctv200e_mt352_config = {
+	.demod_address = 0x3e,
+	.demod_init    = pctv200e_mt352_demod_init,
+	.no_tuner      = 1,
+	.adc_clock     = 20333,
+	.if2           = 56468,
+};
+
+static struct mt2060_config pctv200e_mt2060_config = {
+	.i2c_address = 0xc0,
+	.clock_out   = 1,
+};
+
+/*
+static int pctv200e_mt2060_tuner_set_params(struct v4l_dvb_tuner_ops *ops, struct dvb_int_frontend_parameters *fep)
+{
+	warn ("pctv200e_mt2060_tuner_set_params: setting parameters!");
+
+	ops->set_params (ops,fep);
+
+	//	ret = fe->ops.tuner_ops.set_params(fe, fep);
+
+	return 0;
+}
+*/
+
+static u16 if1 = 1220; // this is probably wrong, but we need some value to compile this shite
+
+
+// source (for the tuner attach: dibusb-common.c)
+static int pctv200e_frontend_attach(struct dvb_usb_adapter *adap)
+{
+        warn(" trying to attach a frontend.");
+	static u8 cmd_buf3[] = { 0x10, 0xED};
+	static u8 cmd_buf4[] = { 0x11, 0x41};
+	static u8 cmd_buf5[] = { 0x12, 0x01};
+	// Sending "0x18 0x01" turns the antenna power on
+	// Sending "0x18 0x00" turns the antenna power off
+	static u8 cmd_buf6[] = { 0x18, 0x01};
+
+	if ((adap->fe = dvb_attach(mt352_attach, &pctv200e_mt352_config, &adap->dev->i2c_adap)) != NULL) {
+	//		adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
+		warn(" attaching and initializing mt352frontend attached.");
+//		pctv200e_cmd_msg(adap->dev, cmd_buf1, sizeof(cmd_buf1));
+		pctv200e_mt352_demod_init (adap->fe);
+		// Send, maybe is start command?
+//		pctv200e_cmd_msg(adap->dev, cmd_buf1, sizeof(cmd_buf1));
+//		pctv200e_cmd_msg(adap->dev, cmd_buf2, sizeof(cmd_buf2));
+		pctv200e_cmd_msg(adap->dev, cmd_buf3, sizeof(cmd_buf3));
+		pctv200e_cmd_msg(adap->dev, cmd_buf4, sizeof(cmd_buf4));
+		pctv200e_cmd_msg(adap->dev, cmd_buf5, sizeof(cmd_buf5));
+		pctv200e_cmd_msg(adap->dev, cmd_buf6, sizeof(cmd_buf6));
+//		pctv200e_cmd_msg(adap->dev, cmd_buf1, sizeof(cmd_buf1));
+
+		warn(" frontend attached.");
+		return 0;
+	} 
+	warn(" frontend attach FAILED.");
+	return -EIO;
+}
+
+static int pctv200e_tuner_attach(struct dvb_usb_adapter *adap)
+{
+  
+        warn(" trying to attach a tuner.");
+	//	adap->fe->ops.tuner_ops.fe = adap->fe;
+
+//	if ((adap->fe = dvb_attach(mt2060_attach, &adap->fe->ops.tuner_ops, 
+//	if ((dvb_attach(mt2060_attach, &adap->fe->ops.tuner_ops,
+	if ((dvb_attach(mt2060_attach, adap->fe,
+		&adap->dev->i2c_adap, &pctv200e_mt2060_config, if1)) != NULL) {
+	  //		adap->fe->ops.tuner_ops.fe = adap->fe;
+//		adap->fe->ops.tuner_ops.set_params = pctv200e_mt2060_tuner_set_params;
+//		adap->pll_addr = 0xc0;
+		//		adap->pll_desc = &dvb_pll_tded4;
+		warn("tuner mt2060 attached.");
+		//	        if (!dvb_attach(dvb_pll_attach, adap->fe, 0xc0, NULL, DVB_PLL_TDED4)) return -ENODEV;
+		//		warn("pll tuner attached.");
+		return 0;
+	}
+
+	warn("frontend_attach failed (mt2060)");
+
+	return -EIO;
+}
+
+// currently not aim of my mission
+#if 0
+
+static struct dvb_usb_rc_key pctv200e_rc_keys[] = {
+	{ 0x5f, 0x55, KEY_0 },
+	{ 0x6f, 0x55, KEY_1 },
+	{ 0x9f, 0x55, KEY_2 },
+	{ 0xaf, 0x55, KEY_3 },
+	{ 0x5f, 0x56, KEY_4 },
+	{ 0x6f, 0x56, KEY_5 },
+	{ 0x9f, 0x56, KEY_6 },
+	{ 0xaf, 0x56, KEY_7 },
+	{ 0x5f, 0x59, KEY_8 },
+	{ 0x6f, 0x59, KEY_9 },
+	{ 0x9f, 0x59, KEY_TV },
+	{ 0xaf, 0x59, KEY_AUX },
+	{ 0x5f, 0x5a, KEY_DVD },
+	{ 0x6f, 0x5a, KEY_POWER },
+	{ 0x9f, 0x5a, KEY_MHP },     /* labelled 'Picture' */
+	{ 0xaf, 0x5a, KEY_AUDIO },
+	{ 0x5f, 0x65, KEY_INFO },
+	{ 0x6f, 0x65, KEY_F13 },     /* 16:9 */
+	{ 0x9f, 0x65, KEY_F14 },     /* 14:9 */
+	{ 0xaf, 0x65, KEY_EPG },
+	{ 0x5f, 0x66, KEY_EXIT },
+	{ 0x6f, 0x66, KEY_MENU },
+	{ 0x9f, 0x66, KEY_UP },
+	{ 0xaf, 0x66, KEY_DOWN },
+	{ 0x5f, 0x69, KEY_LEFT },
+	{ 0x6f, 0x69, KEY_RIGHT },
+	{ 0x9f, 0x69, KEY_ENTER },
+	{ 0xaf, 0x69, KEY_CHANNELUP },
+	{ 0x5f, 0x6a, KEY_CHANNELDOWN },
+	{ 0x6f, 0x6a, KEY_VOLUMEUP },
+	{ 0x9f, 0x6a, KEY_VOLUMEDOWN },
+	{ 0xaf, 0x6a, KEY_RED },
+	{ 0x5f, 0x95, KEY_GREEN },
+	{ 0x6f, 0x95, KEY_YELLOW },
+	{ 0x9f, 0x95, KEY_BLUE },
+	{ 0xaf, 0x95, KEY_SUBTITLE },
+	{ 0x5f, 0x96, KEY_F15 },     /* AD */
+	{ 0x6f, 0x96, KEY_TEXT },
+	{ 0x9f, 0x96, KEY_MUTE },
+	{ 0xaf, 0x96, KEY_REWIND },
+	{ 0x5f, 0x99, KEY_STOP },
+	{ 0x6f, 0x99, KEY_PLAY },
+	{ 0x9f, 0x99, KEY_FASTFORWARD },
+	{ 0xaf, 0x99, KEY_F16 },     /* chapter */
+	{ 0x5f, 0x9a, KEY_PAUSE },
+	{ 0x6f, 0x9a, KEY_PLAY },
+	{ 0x9f, 0x9a, KEY_RECORD },
+	{ 0xaf, 0x9a, KEY_F17 },     /* picture in picture */
+	{ 0x5f, 0xa5, KEY_KPPLUS },  /* zoom in */
+	{ 0x6f, 0xa5, KEY_KPMINUS }, /* zoom out */
+	{ 0x9f, 0xa5, KEY_F18 },     /* capture */
+	{ 0xaf, 0xa5, KEY_F19 },     /* web */
+	{ 0x5f, 0xa6, KEY_EMAIL },
+	{ 0x6f, 0xa6, KEY_PHONE },
+	{ 0x9f, 0xa6, KEY_PC },
+};
+
+static int pctv200e_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+	int i;
+	u8 key[5];
+	u8 b[4] = { 0 };
+
+	*event = 0;
+	*state = REMOTE_NO_KEY_PRESSED;
+
+	pctv200e_ctrl_msg(d,USB_READ_REMOTE,0,NULL,0,&key[1],4);
+
+	/* Tell the device we've read the remote. Not sure how necessary
+	   this is, but the Nebula SDK does it. */
+	pctv200e_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
+
+	/* if something is inside the buffer, simulate key press */
+	if (key[1] != 0)
+	{
+		  for (i = 0; i < d->props.rc_key_map_size; i++) {
+			if (d->props.rc_key_map[i].custom == key[1] &&
+			    d->props.rc_key_map[i].data == key[2]) {
+				*event = d->props.rc_key_map[i].event;
+				*state = REMOTE_KEY_PRESSED;
+				return 0;
+			}
+		}
+	}
+
+	if (key[0] != 0)
+		warn("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+	return 0;
+}
+#endif
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties pctv200e_properties;
+
+static int pctv200e_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+// Scheduled for removal [GDC]
+//	struct dvb_usb_device *d;
+// cause we removed &d from next one.
+	int ret;
+	if ((ret = dvb_usb_device_init(intf, &pctv200e_properties,
+                                       THIS_MODULE, NULL, adapter_nr)) == 0) {
+#if 0
+		u8 b[4] = { 0 };
+// Do not know if we use this here, or change all the functions to take
+// an adapter_nr as parameter.
+                struct dvb_usb_device *d = i2c_get_adapdata(adapter_nr);
+		/* do we need that?? */
+		if (d != NULL) {  /* do that only when the firmware is loaded  */
+			b[0] = 1;
+			pctv200e_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0);
+
+			b[0] = 0;
+			pctv200e_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
+		}
+#endif
+	}
+	warn("usb_device_init sucessfull.");
+	return ret;
+}
+
+
+static struct usb_device_id pctv200e_table [] = {
+		{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_200E) },
+		{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_60E) },
+		{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, pctv200e_table);
+
+// change me
+static struct dvb_usb_device_properties pctv200e_properties = {
+	.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING | DVB_USB_IS_AN_I2C_ADAPTER,
+	.usb_ctrl = CYPRESS_FX2,
+	//.firmware = "dvb-usb-digitv-02.fw", // no!
+
+	.num_adapters = 1,
+	.adapter = {
+		{
+			.frontend_attach  = pctv200e_frontend_attach,
+			.tuner_attach     = pctv200e_tuner_attach,
+
+			/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_BULK,
+				.count = 7,
+				.endpoint = 0x02,
+				.u = {
+					.bulk = {
+						.buffersize = 4096,
+					}
+				}
+			},
+		}
+	},
+	.identify_state   = pctv200e_identify_state,
+
+	/*.rc_interval      = 1000,
+	.rc_key_map       = pctv200e_rc_keys,
+	.rc_key_map_size  = ARRAY_SIZE(pctv200e_rc_keys),
+	.rc_query         = pctv200e_rc_query,*/
+
+	.i2c_algo         = &pctv200e_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+
+	.num_device_descs = 2,
+	.devices = {
+		{   "Pinnacle PCTV 200e DVB-T",
+			{ &pctv200e_table[0], NULL },
+			{ NULL },
+		},
+		{   "Pinnacle PCTV 60e DVB-T",
+			{ &pctv200e_table[1], NULL },
+			{ NULL },
+		},
+		{ NULL },
+	}
+};
+
+static struct usb_driver pctv200e_driver = {
+#if LINUX_VERSION_CODE <=  KERNEL_VERSION(2,6,15)
+	.owner		= THIS_MODULE,
+#endif
+	.name		= "dvb_usb_pctv200e",
+	.probe		= pctv200e_probe,
+	.disconnect 	= dvb_usb_device_exit,
+	.id_table	= pctv200e_table,
+};
+
+/* module stuff */
+static int __init pctv200e_module_init(void)
+{
+	int result;
+	if ((result = usb_register(&pctv200e_driver))) {
+		err("usb_register failed. Error number %d",result);
+		return result;
+	}
+	warn("usb_register successfull.");
+
+	return 0;
+}
+
+static void __exit pctv200e_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	warn("usb_DEregister started.");
+	usb_deregister(&pctv200e_driver);
+	warn("usb_DEregister successfull.");
+}
+
+module_init (pctv200e_module_init);
+module_exit (pctv200e_module_exit);
+
+MODULE_AUTHOR("Jakob Steidl <jakob.steidl@gmail.com>, Gabriele Dini Ciacci <gabriele@diniciacci.org>");
+MODULE_DESCRIPTION("Driver for Pinnacle PCTV 200e and 60e DVB-T USB2.0");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
diff -uprN v4l-dvd/linux/drivers/media/dvb/dvb-usb/pctv200e.h my_v4l-dvb/linux/drivers/media/dvb/dvb-usb/pctv200e.h
--- v4l-dvd/linux/drivers/media/dvb/dvb-usb/pctv200e.h	1970-01-01 01:00:00.000000000 +0100
+++ my_v4l-dvb/linux/drivers/media/dvb/dvb-usb/pctv200e.h	2008-01-02 02:09:34.000000000 +0100
@@ -0,0 +1,35 @@ 
+#ifndef _DVB_USB_PCTV200E_H_
+#define _DVB_USB_PCTV200E_H_
+
+#define DVB_USB_LOG_PREFIX "pctv200e"
+#include "dvb-usb.h"
+
+extern int dvb_usb_pctv200e_debug;
+#define deb_rc(args...)   dprintk(dvb_usb_pctv200e_debug,0x01,args)
+
+/*
+#define USB_READ_EEPROM         1
+
+#define USB_READ_COFDM          2
+#define USB_WRITE_COFDM         5
+
+#define USB_WRITE_TUNER         6
+
+#define USB_READ_REMOTE         3
+#define USB_WRITE_REMOTE        7
+#define USB_WRITE_REMOTE_TYPE   8
+
+#define USB_DEV_INIT            9
+*/
+
+
+#define USB_READ	1
+#define USB_WRITE	2
+
+#define TUNER_ADDR 0xc0
+#define DEMUX_ADDR 0x3e
+
+
+
+
+#endif