Archived:Em2820

From LinuxTVWiki
Jump to navigation Jump to search

Currently supported devices

The em2820 driver should support:

  • The em2880 is a more complete driver which supports all these devices and more. See Em2880.

News

Di Sep 27 23:11:07 CEST 2005

catch the fish! the driver is public

video4linux news:

        We are creating a newer tree to join V4L projects that are not yet
ready to go to kernel. The main idea is to have a centralized point for
V4L development. Experimental projects will stay at v4l_experimental
until:
       1) providing V4L2 API support;
       2) don't providing other non-kernel API;
       3) having CodingStyle;
       4) being stable enough.

       After having these conditions, the project (or drivers) will be
migrated to V4L tree and follow the normal development cycle.

       Currently, there's a new project on that, providing support for
Empiatech USB based boards with em2820 and em2840.

       Boards currently supported:

       *) Terratec Cinergy 250 USB - video decoder: saa7113;

       *) Pinnacle PCTV USB 2 - video decoder: saa7113;

       *) Hauppauge WinTV USB 2 (model 42012 Rev C186) - video decoder:
tvp5150am1, audio decoder: msp3445G.

       The latest one still lacks audio support. Video is ok.

       For those who want to help, CVS version is provided at linuxtv.org:

cvs -d :pserver:anonymous@cvs.linuxtv.org:/cvs/video4linux login

cvs -d :pserver:anonymous@cvs.linuxtv.org:/cvs/video4linux co -P
v4l_experimental

Cheers,
Mauro.

Markus Rechberger

Sa Sep 24 14:37:29 CEST 2005

the driver gets prepared for joining the video4linux package, and finally to get into the linux kernel :)

Mon Sep 19 23:04:20 CEST 2005

on wednesday we'll know how to go on with the development, if everything turns out in a good way we'll release the driver and turn our CVS public

Markus Rechberger

Sa Sep 10 16:33:47 CEST 2005

getting digital audio work (don't expect too much the snd_usb_audio driver does no error checking so it might even lock up your keyboard):

mplayer -zoom -tv amode=1:input=2:norm=PAL:driver=v4l2:alsa:width=720:height=576:outfmt=yuy2:adevice=hw.0:forceaudio tv://
sox -t ossdsp -r 48000 -b -c 2 /dev/dsp -t ossdsp /dev/dsp2

this should work with the latest driver (just requested Empia for persission to distribute it!).

Markus Rechberger

Sun Sep 4 16:13:23 CEST 2005

We have started implementing some features based on the specs from empia. As soon as we have some cleaner and stable code, we will submit it to empia and release it.

Here is some detail about the status: setting video size is working with most resolutions; mplayer, xawtv and tvtime are working. We managed to mute/unmute audio for both analog external cable and USB transfer. All three video (tuner, composite and s-video) with relative audio sources (tuner and line in) are working.

I have managed to acquire three hours of video and audio from a VCR (although the isoc transfer stopped three times for a reason still unclear to me) with:

mencoder -v tv:// -tv driver=v4l2:device=/dev/video0:outfmt=i420:width=640:height=480:forceaudio:adevice=/dev/dsp1
   -ovc lavc -lavcopts acodec=mp3:abitrate=112:vbitrate=950:mbd=2 -oac lavc -vf lavcdeint -o video.avi

Ludovico Cavedon

So Sep 4 10:14:03 CEST 2005

since Ludovice didn't post anything during the last week, he implemented digital audio (using the ac97 link). and did some code cleanup. We also partly set up VBI(Teletext) support, though we have to get deeper into that topic. I still fight with the Pinnacle PCTV USB2 (Pal/Secam) drivers, downloading the installation CD now, just want to fix up that audio issue...

Audio issue fixed, there's no audio out jack, the Pinnacle PCTV only works with the USB Audio link which has been enabled as written in the specs by Ludovico :-)

for the pinnacle pctv usb2 a relay tool is required to get synced Audio/Video since A/V is not multiplexed (for testing the device >>dd if=/dev/dsp of=/dev/dsp1<< should work)

Markus Rechberger

So Aug 28 13:53:39 CEST 2005

received the pinnacle PCTV USB2 device, video and tuning already works but no sound yet..

Upload:MarkusRechberger/pro7.jpg

Fr Aug 26 20:09:36 CEST 2005

pinnacle will send us an usb device for testing the current em2820 driver with it, deinterlacing is also implemented into the old available driver.

Mo Aug 15 00:27:33 CEST 2005

ok there was a discussion about that half framed interlace issue theoretically it should be done in userspace, practically the userspace tv applications haven't implemented that function (so it won't work if I'd set the right option in the driver). btw. tuning also works in the old driver we give away (use H and K/mplayer)

Sa Aug 13 20:22:26 CEST 2005

isoc transfer is done so far I get the frames I want, atm the glue between v4l(1) and the isoc irq is missing (this is the most important step atm. also to get that interlacing problem done) even usb_video.c in the kernel tree uses depreciated functions and I try to not use the way like it's used in the em2800 driver so let's see how it turns out during the next week. if someone wants to join the development process everyone who knows more about kernel development is welcome! the driver will get distributed under GPL (there's no other way empia didn't respond yet they have to face it then - I signed the NDA to not give away the docs (I will not for sure)), I don't see any negative point at that, they only have windoze drivers yet.. more than 20 people contacted me for now for linux drivers during 1 week (so don't spreed the working (hacked) driver around so that we can count everyone for now.. the actual full featured driver will be available during the next 2-3 weeks) everyone who asked for the current hacked driver got it via email.

Markus Rechberger

Do Aug 11 11:34:55 CEST 2005

new thursday news - if you have any questions regarding that driver or similar devices send them to mrechberger AT g m a i l (DOT) c o m, some people mailed me that the

* Pinnacle Systems PCTV USB2
* MSI VOX USB-TV 
* Terratec Cinergy 250 USB TV
* Hauppauge WinTV-USB2
* Gadmei UTV310(http://www.gadmei.com),
* Leadtek WinFast USBII

contain almost the same chips.

If you want to get your empia2820 device supported please send an output of usbview to the email address which is shown above

Markus Rechberger

Do Aug 4 03:46:57 CEST 2005

just some news.. I rewrite the em2820 driver (of course some code is borrowed from the em2800 driver and usb driver in the kernel tree), atm I'm at the video datatransfer. also want to take care about interlaced video this time..

Markus Rechberger

Do Jul 28 21:08:28 CEST 2005

even better news now we(MarkusR. and LudovicoC.) received the specs! During legal issues we won't publish any further informations on the Hardware from now on.

Do Jul 28 03:45:45 CEST 2005

probably good news, I got an email from empia, they will give us support

Markus Rechberger

Preface

Cinergy USB TV 250 Driver development, this device is currently not supported by linux... but we're on the right way to get it done


developers:

Sascha Sommer (skeleton driver/em2800)
Ludovico Cavedon (i2c tuner support)
Markus Rechberger (enabling videostream for the 2820, and some other em2820 protocol options)

we also contacted empiatech if they can hand out some details about the emp2820 chip.. we haven't got any informations from them

the current driver is available uppon request (of course I don't give any warranty it might even damage your device) we'll release the driver as soon as it's more complete Markus Rechberger

This site mainly contains notes about the driver development, so it's not perfectly structured

General Informations about the Terratec Cinergy 250 USB

The cinergy 250 USB Device contains (figured that out by opening the device):

* saa7113H (video input processor)
* emp2820
* emp202 (audio processor/AC97 compatible)

Template:/USB/usbview usbview output

Useful Links

Writing a Simple USB Driver

http://www.linuxjournal.com/article/7353

Another doc I found about it (google only returned broken links, but it is stored in the web.archive as well

http://web.archive.org/web/20041024164832/http://www.toth.demon.co.uk/usb/reverse-0.3.txt

The Linux USB sub-system, Chapter 2. How to get USB devices working under Linux

http://www.linux-usb.org/USB-guide/x173.html

how to sniff usb data:

http://www.linuxjournal.com/article/7582 (I used usbsnoop for windows)

Marketing information/general overview:

http://www.komplett.ie/k/ki.asp?sku=302293&cks=PLS

The Linux Kernel Module Programming Guide

http://www.tldp.org/LDP/lkmpg/2.6/html/index.html

Driver porting: compiling external modules

http://lwn.net/Articles/21823/

USB Snoop:

http://benoit.papillault.free.fr/usbsnoop/

USB 2.0 Specs:

http://www.usb.org/developers/docs/usb_20_02212005.zip

Empia general informations:

http://www.empiatech.com.tw/pro_em2820.htm

Template:/USB a few infos about USB, and a nice parser for USBSnoop Logs

V4L2 Standards:

http://v4l2spec.bytesex.org/spec/standard.html

Video for Linux Two - Driver Writer's Guide

http://www.thedirks.org/v4l2/v4l2dwg.htm

Sniffing/Replaying Data

I followed http://www.linuxjournal.com/article/7582, since it didn't really work (the source looks incomplete at that point) I had to add the sniffing feature by myself to the linux kernel ...


00000202        0.02435058      <<<<<<< URB 6 coming back...
00000203        0.02435784        Status = 00000000
00000204        0.02436511      -- URB_FUNCTION_CONTROL_TRANSFER:
00000205        0.02437349        PipeHandle           = 0x847EB4E0
00000206        0.02438355        TransferFlags        = 0000000b (USBD_TRANSFER_DIRECTION_IN, USBD_SHORT_TRANSFER_OK)
00000207        0.02439193        TransferBufferLength = 00000001
00000208        0.02440031        TransferBuffer       = eb83f91f
00000209        0.02440869        TransferBufferMDL    = 84799808
00000210        0.02441483
00000211        0.02442852          0000: 12
00000212        0.02445199        UrbLink              = 00000000
00000213        0.02450032        SetupPacket          : c0 00 00 00 0a 00 01 00
00000214        0.02514565      UsbSnoop - IRP_MJ_INTERNAL_DEVICE_CONTROL, IOCTL_INTERNAL_USB_SUBMIT_URB

starting to replay some sniffed protocol points:

static int em2800_read_reg_ext(struct em2800 *dev,__u16 reg,int cnt) {
        __u8 val[cnt];
        int i;
        int ret;
        for(i=0;i<cnt;i++){
                val[i]=0;
        }
        printk("READING(ext): 0x%x 0x%x 0x0000 0x%x 1 HZ\n",USB_REQ_GET_STATUS,USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE,reg);

        ret = usb_control_msg(dev->udev,usb_rcvctrlpipe(dev->udev,0),USB_REQ_GET_STATUS,
                USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE, 0x0000,reg,val,1, HZ);
        printk("device returned:(ext) ");
        for(i=0;i<cnt;i++){
                printk(" 0x%x",val[i]);
        }
        printk("\n");
        return 0;
}
<nowiki>
dev->em2800_read_reg_ext(dev,0x0a,1);

</nowiki>

the result we get:

READING(ext): 0x0 0xc0 0x0000 0xa 1 HZ
device returned:(ext)  0x12

It seems that usbsnoop dropps packets, so I'll try another way to figure out the protocol http://www.vmware.com/support/kb/enduser/std_adp.php?p_faqid=1622 vmware 5.0 supports isochronous transfers *the thing I suffer*

Isoc Transfer - just a guess?

since the data which arrives is empty I think it's because it uses following configuration:

	Interface Number: 0
		Name: em2800
		Alternate Number: 0
		Class: ff(vend.) 
		Sub Class: 0
		Protocol: 0
		Number of Endpoints: 3

			Endpoint Address: 81
			Direction: in
			Attribute: 3
			Type: Int.
			Max Packet Size: 1
			Interval: 128ms

			Endpoint Address: 82
			Direction: in
			Attribute: 1
			Type: Isoc
			Max Packet Size: 0
			Interval: 125us

			Endpoint Address: 84
			Direction: in
			Attribute: 2
			Type: Bulk
			Max Packet Size: 512
			Interval: 0ms

somehow I have to switch to .

	Interface Number: 0
		Name: em2800
		Alternate Number: 1
		Class: ff(vend.) 
		Sub Class: 0
		Protocol: 0
		Number of Endpoints: 3

			Endpoint Address: 81
			Direction: in
			Attribute: 3
			Type: Int.
			Max Packet Size: 1
			Interval: 128ms

			Endpoint Address: 82
			Direction: in
			Attribute: 1
			Type: Isoc
			Max Packet Size: 1024
			Interval: 125us

			Endpoint Address: 84
			Direction: in
			Attribute: 2
			Type: Bulk
			Max Packet Size: 512
			Interval: 0ms

(usbsnoop sniffed packet)

68  8:30:20 PM  <<<<<<< URB 103 coming back...
00002869  8:30:20 PM    Status = 00000000
00002870  8:30:20 PM  -- URB_FUNCTION_SELECT_INTERFACE:
00002871  8:30:20 PM    ConfigurationHandle     = 0x83f4a2a8
00002872  8:30:20 PM    Interface: Length            = 0x0000004c
00002873  8:30:20 PM    Interface: InterfaceNumber   = 0x00
00002874  8:30:20 PM    Interface: AlternateSetting  = 0x05
00002875  8:30:20 PM    Interface: Class             = 0xff
00002876  8:30:20 PM    Interface: SubClass          = 0x00
00002877  8:30:20 PM    Interface: Protocol          = 0xff
00002878  8:30:20 PM    Interface: InterfaceHandle   = 0x84a1e148
00002879  8:30:20 PM    Interface: NumberOfPipes     = 0x00000003
00002880  8:30:20 PM    Interface: Pipes[0] : MaximumPacketSize = 0x0001
00002881  8:30:20 PM    Interface: Pipes[0] : EndpointAddress   = 0x81
00002882  8:30:20 PM    Interface: Pipes[0] : Interval          = 0x0b
00002883  8:30:20 PM    Interface: Pipes[0] : PipeType          = 0x03 (UsbdPipeTypeInterrupt)
00002884  8:30:20 PM    Interface: Pipes[0] : PipeHandle        = 0x84A1E164
00002885  8:30:20 PM    Interface: Pipes[0] : MaxTransferSize   = 0x00000040
00002886  8:30:20 PM    Interface: Pipes[0] : PipeFlags         = 0x00
00002887  8:30:20 PM    Interface: Pipes[1] : MaximumPacketSize = 0x0a14
00002888  8:30:20 PM    Interface: Pipes[1] : EndpointAddress   = 0x82
00002889  8:30:20 PM    Interface: Pipes[1] : Interval          = 0x01
00002890  8:30:20 PM    Interface: Pipes[1] : PipeType          = 0x01 (UsbdPipeTypeIsochronous)
00002891  8:30:20 PM    Interface: Pipes[1] : PipeHandle        = 0x84A1E184
00002892  8:30:20 PM    Interface: Pipes[1] : MaxTransferSize   = 0x00010000
00002893  8:30:20 PM    Interface: Pipes[1] : PipeFlags         = 0x00
00002894  8:30:20 PM    Interface: Pipes[2] : MaximumPacketSize = 0x0200
00002895  8:30:20 PM    Interface: Pipes[2] : EndpointAddress   = 0x84
00002896  8:30:20 PM    Interface: Pipes[2] : Interval          = 0x01
00002897  8:30:20 PM    Interface: Pipes[2] : PipeType          = 0x02 (UsbdPipeTypeBulk)
00002898  8:30:20 PM    Interface: Pipes[2] : PipeHandle        = 0x84A1E1A4
00002899  8:30:20 PM    Interface: Pipes[2] : MaxTransferSize   = 0x00001000
00002900  8:30:20 PM    Interface: Pipes[2] : PipeFlags         = 0x00
00002901  8:30:20 PM  UsbSnoop - IRP_MJ_INTERNAL_DEVICE_CONTROL, IOCTL_INTERNAL_USB_SUBMIT_URB
00002902  8:30:20 PM

for switching the configuration the function usb_set_interface() is available

usb_set_interface(device,<interface number>,<Alternate Number>) 

.. yes somehow I was wrong with that.. I switched to Alternate number 5 (though no bytes delivered) next step going to clean up the driver and flooding the device with all sniffed packets I got (or even may get soon),...


to recompile usbsnoop you require win2kddk.exe (it's not available on the microsoft website anymore.. I found an active (slow) mirror with google though.. it was free a longer time ago microsoft just dropped it..) (when writing that I thought about doing that but then I figured out how to modify the kernel and it wasn't so hard)

Adding an USB Sniffer to usbfs

I added some printk's for determining the flow through devio.c

usb 1-3: usbdev_ioctl: SUBMITURB
USBDEVFS urpb
CONTROL length: 10 <-- this is what looks interesting 10 bytes let's see what's in it..
CONTROL malloc()
CONTROL copy from user()
CONTROL buffer_length()
check_ctrlrecip()
CONTROL access_ok
alloc_async
kmalloc()
copy_from_user()
usb_submit_urb()
return -- 0 --

ok add some more code to the kernelmodule and reload..

static int proc_submiturb(struct dev_state *ps, void __user *arg)
{
    unsigned int iter;
                ... in case USBDEVFS_URB_TYPE_CONTROL:
                printk("USBDEVFS_URB_TYPE_CONTROL (recv): ");
                for(iter=0;iter<uurb.buffer_length;iter++){
                        printk("0x%x ",((char*)uurb.buffer)[iter]);
                }
                printk("\n");
}


bingo..

USBDEVFS urpb
CONTROL length: 9
CONTROL malloc()
CONTROL copy from user()
CONTROL buffer_length()
USBDEVFS_URB_TYPE_CONTROL (recv): 0xffffffc0 0x0 0x0 0x0 0x12 0x0 0x1 0x0 0x0  # <-- this looks like a read request to the USB device
check_ctrlrecip()
CONTROL access_ok
alloc_async
kmalloc()
copy_from_user()
usb_submit_urb()
return -- 0 --
usb 1-3: usbdev_ioctl: REAPURBDELAY
usb 1-3: usbdev_ioctl: REAPURBDELAY
usb 1-3: usbdev_ioctl: SUBMITURB
USBDEVFS urpb
CONTROL length: 9
CONTROL malloc()
CONTROL copy from user()
CONTROL buffer_length()
USBDEVFS_URB_TYPE_CONTROL (recv): 0x40 0x0 0x0 0x0 0x12 0x0 0x1 0x0 0x67 # <-- this looks like an update request to the device
check_ctrlrecip()
CONTROL access_ok
alloc_async
kmalloc()
copy_from_user()
usb_submit_urb()
return -- 0 --

filtered..

...
Jul  8 05:35:02 debian kernel: USBDEVFS_URB_TYPE_CONTROL (recv): 0x40 0x0 0x0 0x0 0xc 0x0 0x1 0x0 0x10 
Jul  8 05:35:02 debian kernel: USBDEVFS_URB_TYPE_CONTROL (recv): 0x40 0x0 0x0 0x0 0x12 0x0 0x1 0x0 0x67 
Jul  8 05:35:02 debian kernel: USBDEVFS_URB_TYPE_CONTROL (recv): 0x40 0x0 0x0 0x0 0x22 0x0 0x1 0x0 0x10 
Jul  8 05:35:02 debian kernel: USBDEVFS_URB_TYPE_CONTROL (recv): 0x40 0x0 0x0 0x0 0x20 0x0 0x1 0x0 0x10 
Jul  8 05:35:02 debian kernel: USBDEVFS_URB_TYPE_CONTROL (recv): 0x40 0x3 0x0 0x0 0x4a 0x0 0x1 0x0 0x1f 
Jul  8 05:35:02 debian kernel: USBDEVFS_URB_TYPE_CONTROL (recv): 0x40 0x0 0x0 0x0 0x21 0x0 0x1 0x0 0x34 
Jul  8 05:35:02 debian kernel: USBDEVFS_URB_TYPE_CONTROL (recv): 0x40 0x0 0x0 0x0 0x20 0x0 0x1 0x0 0x10 
Jul  8 05:35:02 debian kernel: USBDEVFS_URB_TYPE_CONTROL (recv): 0x40 0x2 0x0 0x0 0x4a 0x0 0x2 0x0 0xd 0x0 
Jul  8 05:35:02 debian kernel: USBDEVFS_URB_TYPE_CONTROL (recv): 0x40 0x0 0x0 0x0 0x22 0x0 0x1 0x0 0x10 
Jul  8 05:35:02 debian kernel: USBDEVFS_URB_TYPE_CONTROL (recv): 0x40 0x0 0x0 0x0 0x14 0x0 0x1 0x0 0x32 
Jul  8 05:35:02 debian kernel: USBDEVFS_URB_TYPE_CONTROL (recv): 0x40 0x0 0x0 0x0 0x25 0x0 0x1 0x0 0x2 
Jul  8 05:35:02 debian kernel: USBDEVFS_URB_TYPE_CONTROL (recv): 0x40 0x0 0x0 0x0 0xe 0x0 0x1 0x0 0xffffffeb 
Jul  8 05:35:02 debian kernel: USBDEVFS_URB_TYPE_CONTROL (recv): 0x40 0x0 0x0 0x0 0xf 0x0 0x1 0x0 0xffffff87 
Jul  8 05:35:02 debian kernel: USBDEVFS_URB_TYPE_CONTROL (recv): 0x40 0x0 0x0 0x0 0x40 0x0 0x2 0x0 0x0 0x0 
Jul  8 05:35:02 debian kernel: USBDEVFS_URB_TYPE_CONTROL (recv): 0x40 0x0 0x0 0x0 0x42 0x0 0x1 0x0 0x2 
Jul  8 05:35:02 debian kernel: USBDEVFS_URB_TYPE_CONTROL (recv): 0x40 0x0 0x0 0x0 0xe 0x0 0x1 0x0 0xffffffeb 
Jul  8 05:35:02 debian kernel: USBDEVFS_URB_TYPE_CONTROL (recv): 0x40 0x0 0x0 0x0 0xf 0x0 0x1 0x0 0xffffff87 
Jul  8 05:35:02 debian kernel: USBDEVFS_URB_TYPE_CONTROL (recv): 0x40 0x0 0x0 0x0 0x40 0x0 0x2 0x0 0x0 0x0 
Jul  8 05:35:02 debian kernel: USBDEVFS_URB_TYPE_CONTROL (recv): 0x40 0x0 0x0 0x0 0x42 0x0 0x1 0x0 0x2 
...

now let's play the game again and replay what we got... oh yes... it took me that long to figure out that I did something wrong... I forgot about the so called "bRequest", it's the second value in the sniffed list

it's also documented in usb_20.pdf in chapter 9.3 USB Device Requests (Site 276) which is downloadable on usb.org

USB Control Message

Offset,Field,Size,Value,Description
0,bmRequestType,1,Bitmap,Characteristics of request: D7 Data transfer direction; D6..5 Type; D4..0 Recipient
1,bRequest,1,Value,Specific request (refer to Table 9-3)
2,wValue,2,Value,Word-sized field that varies according to request
4,wIndex,2,Index of Offset, Word-sized field that varies according to request; typically used to pass an index or offset
6,wLength,2,Count,Number of bytes to transfer if there is a Data stage

bRequest:

This field specifies the particular request. The Type bits in the bmRequestType field modify the meaning of this field. This specification defines values for the bRequest field only when the bits are reset to zero, indicating a standard request (refer to Table 9-3).


ok I modified the existing em2800 driver and added a function em2820_write_regs which supports the bmreq value. calls look like: em2820_write_regs(dev,0x03,0x4a,"\x1f",1); now :-)

YESS, the basic driver works now (very rude..) I receive data!

Sniffed Log when starting up a Windows TV Player

Parsed WinDVR Startup Log (vmware only supports usb 1.1, so that's why there are no isoc transfers in it though everything would be prepared for it): http://linuxwiki.de/MarkusRechberger/em2820?action=AttachFile&do=get&target=dvrstartup-parsed.log


switchchannel2.LOG

001393:  OUT: 40 03 00 00 4a 00 01 00    >>>  1f        
001394:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001395:  OUT: c0 02 00 00 4a 00 01 00    <<<  91        
001396:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001397:  OUT: 40 03 00 00 4a 00 01 00    >>>  1f        
001398:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001399:  OUT: c0 02 00 00 4a 00 01 00    <<<  91        
001400:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001401:  OUT: 40 03 00 00 4a 00 01 00    >>>  1f        
001402:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001403:  OUT: c0 02 00 00 4a 00 01 00    <<<  91        
001404:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001405:  OUT: 40 03 00 00 4a 00 01 00    >>>  1f        
001406:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001407:  OUT: c0 02 00 00 4a 00 01 00    <<<  91        
001408:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001409:  OUT: 40 03 00 00 4a 00 01 00    >>>  1f        
001410:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001411:  OUT: c0 02 00 00 4a 00 01 00    <<<  91        
001412:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001413:  OUT: 40 03 00 00 4a 00 01 00    >>>  1f        
001414:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001415:  OUT: c0 02 00 00 4a 00 01 00    <<<  91        
001416:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001417:  OUT: 40 00 00 00 20 00 01 00    >>>  00        
001418:  OUT: 40 00 00 00 22 00 01 00    >>>  00        
001419:  OUT: c0 00 00 00 12 00 01 00    <<<  67        
001420:  OUT: 40 00 00 00 12 00 01 00    >>>  27        
001421:  OUT: c0 00 00 00 0c 00 01 00    <<<  10        
001422:  OUT: 40 00 00 00 0c 00 01 00    >>>  00        
001423:  OUT: 40 02 00 00 c2 00 04 00    >>>  05 e2 8e 01       
001424:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001425:  OUT: 40 02 00 00 86 00 04 00    >>>  00 d6 70 49       
001426:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001427:  OUT: c0 02 00 00 c2 00 01 00    <<<  39        
001428:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001429:  OUT: c0 02 00 00 c2 00 01 00    <<<  7b        
001430:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001431:  OUT: c0 02 00 00 c2 00 01 00    <<<  7b        
001432:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001433:  OUT: c0 02 00 00 c2 00 01 00    <<<  7b        
001434:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001435:  OUT: c0 02 00 00 c2 00 01 00    <<<  7b        
001436:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001437:  OUT: c0 00 00 00 0c 00 01 00    <<<  00        
001438:  OUT: 40 00 00 00 0c 00 01 00    >>>  10        
001439:  OUT: 40 00 00 00 12 00 01 00    >>>  67        
001440:  OUT: 40 00 00 00 22 00 01 00    >>>  10        
001441:  OUT: 40 00 00 00 20 00 01 00    >>>  10        
001442:  OUT: c0 02 00 00 c2 00 01 00    <<<  7b        
001443:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001444:  OUT: c0 02 00 00 c2 00 01 00    <<<  7b        
001445:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001446:  OUT: 40 00 00 00 20 00 01 00    >>>  00        
001447:  OUT: 40 00 00 00 22 00 01 00    >>>  00        
001448:  OUT: c0 00 00 00 12 00 01 00    <<<  67        
001449:  OUT: 40 00 00 00 12 00 01 00    >>>  27        
001450:  OUT: c0 00 00 00 0c 00 01 00    <<<  10        
001451:  OUT: 40 00 00 00 0c 00 01 00    >>>  00        
001452:  OUT: 40 02 00 00 c2 00 04 00    >>>  05 e3 8e 01       
001453:  OUT: c0 00 00 00 05 00 01 00    <<<  00        
001454:  OUT: 40 02 00 00 86 00 04 00    >>>  00 d6 70 49       

Screenshots

Initial Screenshot

mplayer

mplayer -tv driver=v4l2:width=320:height=240 -vo x11 tv://

current screenshot (mplayer):

http://www.linuxwiki.de/MarkusRechberger/em2820?action=AttachFile&do=get&target=screenshot.jpg

the magic number 7

used configuration:

	Interface Number: 0
		Name: em2800
		Alternate Number: 7
		Class: ff(vend.) 
		Sub Class: 0
		Protocol: 0
		Number of Endpoints: 3

			Endpoint Address: 81
			Direction: in
			Attribute: 3
			Type: Int.
			Max Packet Size: 1
			Interval: 128ms

			Endpoint Address: 82
			Direction: in
			Attribute: 1
			Type: Isoc
			Max Packet Size: 3072
			Interval: 125us

			Endpoint Address: 84
			Direction: in
			Attribute: 2
			Type: Bulk
			Max Packet Size: 512
			Interval: 0ms

mplayer -zoom -tv driver=v4l2:width=720:height=576:norm=PAL:fps=25 -vo x11 tv://

http://www.linuxwiki.de/MarkusRechberger/em2820?action=AttachFile&do=get&target=screenshot2.jpg

(playing around with the supported input resolution now) Digital Video Capture Resolution 720 x 480, 352 x 240, 352 x 288, 720 x 576

Issues with the size

though the video is oversized now...

mplayer -zoom -tv driver=v4l2:width=750:height=480:fps=25:norm=palm:noaudio:outfmt=i420 tv:// -vo x11

http://www.linuxwiki.de/MarkusRechberger/em2820?action=AttachFile&do=get&target=screenshot4.jpg

http://www.linuxwiki.de/MarkusRechberger/em2820?action=AttachFile&do=get&target=screenshot5.jpg


Fixed Size

there's a function called set_window within the em2800 driver, and 320x288 was hardcoded, I changed this so that the size gets set using ioctls.. looks like the video is 1:1 (width/height)

mplayer -zoom -tv driver=v4l2:width=244:height=244:fps=30:norm=pal:noaudio:outfmt=yuy2 tv:// -vo x11

Upload:MarkusRechberger/244x240.jpg

Alternate Number 5

alternate number 5 .. guess some bytes are missing? the isoc transfer complains about an incomplete frame.. let's see I don't know the frame size which should be behind that transfer data (guessing doesn't work following frame is the best result) ..

http://linuxwiki.de/MarkusRechberger/em2820?action=AttachFile&do=get&target=frame.jpg

Alternate Number 2

Alternate setting 2

Upload:MarkusRechberger/zdf.jpg

Alternate Number 7

ok I figured out the usb control message which allows to switch to 720px width.. interesting thing is that interface 0 alternate number 7 doesn't automatically return a full sized video at 720x576 ok the width looks _right_ the cinergy usb tv delivers 2 frames interlaced, think it has something to do with the v4l2 option V4L2_FIELD_SEQ_TB in the driver but it didn't work out for me yet.. so there's probably something else

mplayer -zoom -tv driver=v4l2:width=720:height=288:fps=25:norm=palm:noaudio:outfmt=yuy2 tv:// -vo x11

Upload:MarkusRechberger/720x288.jpg


Screenshot 720x576

Upload:MarkusRechberger/screenshot8.jpg

here's the v4l2 doc regarding that issue http://v4l2spec.bytesex.org/spec/field-order.html


Alternate 7 de-interlaced

this will play the video at the correct size:

mplayer -zoom -tv driver=v4l2:width=720:height=288:fps=60:noaudio:outfmt=yuy2 tv:// -vf tinterlace

Ludovico C. pointed me out that tinterlace switch ..

Upload:MarkusRechberger/test4.jpg

next step would be to put that interlace feature into the usb kernel driver..

Isoc Request issues

another issue frame problems ... after a while the video had some problems these problems were caused because of requesting 60 isoc urbs from the device, in windows it only requests 40 urbs (after modifying the driver again the video looks stable!)


Changing the resolution?

Changing Resolution:

Switched to 640x480 (sniffed with usbsniff) this probably covers that 0x05 delivers a 640x480 frame?

640x480 - vga - yuy2

000426:  OUT: c0 00 00 00 0f 00 01 00    <<<  87        
000427:  OUT: 40 00 00 00 0f 00 01 00    >>>  07        
000428:  OUT: 40 00 00 00 40 00 02 00    >>>  00 80     
000429:  OUT: 40 00 00 00 42 00 01 00    >>>  02        
000430:  OUT: c0 00 00 00 43 00 01 00    <<<  00        
000431:  Changing to Alternative Setting 0x05
000432:  Changing to Alternative Setting 0x05
000433:  Changing to Alternative Setting 0x05
000434:  Changing to Alternative Setting 0x05
000435:  OUT: c0 00 00 00 0e 00 01 00    <<<  cd        
000436:  OUT: 40 00 00 00 0e 00 01 00    >>>  cd        
000437:  OUT: c0 00 00 00 0f 00 01 00    <<<  07        
000438:  OUT: 40 00 00 00 0f 00 01 00    >>>  87        
000439:  OUT: 40 00 00 00 40 00 02 00    >>>  00 00     ## try to mute
000440:  OUT: 40 00 00 00 42 00 01 00    >>>  02        
000441:  OUT: c0 00 00 00 43 00 01 00    <<<  00        
000442:  OUT: c0 00 00 00 0e 00 01 00    <<<  cd        
000443:  OUT: 40 00 00 00 0e 00 01 00    >>>  cd        
000444:  OUT: c0 00 00 00 0f 00 01 00    <<<  87        
000445:  OUT: 40 00 00 00 0f 00 01 00    >>>  87        
000446:  OUT: 40 00 00 00 40 00 02 00    >>>  00 00     ## try to mute    
000447:  OUT: 40 00 00 00 42 00 01 00    >>>  02        
000448:  OUT: c0 00 00 00 43 00 01 00    <<<  00        
000449:  OUT: 40 00 00 00 21 00 01 00    >>>  14        
000450:  OUT: 40 00 00 00 20 00 01 00    >>>  10        
000451:  OUT: 40 00 00 00 22 00 01 00    >>>  10        
000452:  OUT: 40 00 00 00 25 00 01 00    >>>  02        
000453:  OUT: c0 00 00 00 0f 00 01 00    <<<  87        
000454:  OUT: 40 00 00 00 0f 00 01 00    >>>  07        
000455:  OUT: 40 00 00 00 40 00 02 00    >>>  00 80     ## unmute
000456:  OUT: 40 00 00 00 42 00 01 00    >>>  02        
000457:  OUT: c0 00 00 00 43 00 01 00    <<<  00        

setting 640x480 - i420

000486:  Changing to Alternative Setting 0x05
000487:  Changing to Alternative Setting 0x05
000488:  Changing to Alternative Setting 0x05
000489:  Changing to Alternative Setting 0x05
000490:  OUT: c0 00 00 00 0f 00 01 00    <<<  07        
000491:  OUT: 40 00 00 00 0f 00 01 00    >>>  07        
000492:  OUT: 40 00 00 00 40 00 02 00    >>>  00 80   #unmute  
000493:  OUT: 40 00 00 00 42 00 01 00    >>>  02        
000494:  OUT: c0 00 00 00 43 00 01 00    <<<  00        
000495:  OUT: c0 00 00 00 0f 00 01 00    <<<  07        
000496:  OUT: 40 00 00 00 0f 00 01 00    >>>  07        
000497:  OUT: 40 00 00 00 40 00 02 00    >>>  00 80   #unmute 
000498:  OUT: 40 00 00 00 42 00 01 00    >>>  02        
000499:  OUT: c0 00 00 00 43 00 01 00    <<<  00        
000500:  OUT: 40 00 00 00 21 00 01 00    >>>  14        
000501:  OUT: 40 00 00 00 20 00 01 00    >>>  10        
000502:  OUT: 40 00 00 00 22 00 01 00    >>>  10        
000503:  OUT: 40 00 00 00 25 00 01 00    >>>  02        
000504:  OUT: c0 00 00 00 0f 00 01 00    <<<  07        
000505:  OUT: 40 00 00 00 0f 00 01 00    >>>  07        
000506:  OUT: 40 00 00 00 40 00 02 00    >>>  00 80   #unmute  
000507:  OUT: 40 00 00 00 42 00 01 00    >>>  02        
000508:  OUT: c0 00 00 00 43 00 01 00    <<<  00        
000509:  OUT: c0 00 00 00 0f 00 01 00    <<<  07        
000510:  OUT: 40 00 00 00 0f 00 01 00    >>>  07        
000511:  OUT: 40 00 00 00 40 00 02 00    >>>  00 80   #unmute    
000512:  OUT: 40 00 00 00 42 00 01 00    >>>  02        
000513:  OUT: c0 00 00 00 43 00 01 00    <<<  00        

difference might be 0x0f, once it got switched to 87, since it didn't work it might have got switched back to 0x07




General thoughts and informations

played 400.000 frames without lockup (makes about 4 hours!).. Ludovico reported a lockup after 40.000 frames seems like a hardware issue here (maybe the windows driver currently fixes that problem..) I had such an issue with my usb soundblaster it finally locked up the kernel within 5 minutes until I replaced the cable with an usb 2.0 certified wire... it always takes a while till mplayers deinterlace filter works correctly (just looked over that topic very short..) but finally as expected the quality is way better in linux than in microsoft windows.. mythtv (www.mythtv.org) will be fun with it as soon as someone gets the i2c stuff working.. I just sit back now and take it easy I'm already glad to get a full quality video in linux :) the i2c indexes are already known atm. another news are terratec denies supporting linux officially because there are too less linux users out there (well .. munich(Germany) migrates their administrational services over to linux and so does vienna(Austria) oh no sorry noone uses linux.. But maybe some information from empia is coming...

i2c Hacking

Something about the I2C on the device: the main chip is the emp2820, but there are other chips connected through an i2c:

Address, Chip
0x4a, Philips saa7113h: video decoder
0xc0, LG TALN-M200: tuner
0xc2, again the tuner
0x68, I don't know :) maybe a tda9887

The saa7113h si well documented:

http://www.semiconductors.philips.com/pip/SAA7113.html

The tuner id detected at address 0xc0, but address 0xc2 is used to communicate with it.

There is also something at the 0x68 address, but I don't know what it is. Maybe a tda9887 (PLL demodulator) but I didn't see it when I opened my cinergy.

An standard I2C address is an 8 bit value. The least significant bit specifies the direction of the trasfer: 0 means write (from master to slave), 1 read (from slave to master). Fo this reason, max 127 can be connected to an I2C bus, and they have two addresses (at least), the first to receive data, the second to send data.

The I2C protocol is very simple. See here:

http://www.wikiservice.at/dse/wiki.cgi?MarkusRechberger/I2C

and a the documentation from Philips:

http://www.semiconductors.philips.com/markets/mms/protocols/i2c/

The major problem, in this case, is to unserstand how tell the em2820 to write on the bus (since we can only communicate with the em2820 through the usb bus). That is what I could understand examining the logs; something is still obscure, btw:

All the operation on the i2c bus have the bRequest set to 0x02 or 0x03. More over every operation is followed by a read at the register 0x05 of the em2820, that usually returns 0x00. It should be a way to ask if the operation was successful. The only times I saw a number different from 0x00 was during the scan of the i2c bus: wheen a read from a nonexitent device return 0x10.

c0 02 0000 004a 0001 data: 11
c0 00 0000 0005 0001 data: 00   # Success, device present!

c0 02 0000 00c6 0001 data: 00
c0 00 0000 0005 0001 data: 10   # Failure, device not present!

Writing or reading to/from a device is streightforward: set bRequest to 0x02 and wIndex to the address of the device you want to write to.

40 02 0000 00c2 0004 data: 06 52 8e 01
c0 00 0000 0005 0001 data: 00

c0 02 0000 00c2 0001 data: 38
c0 00 0000 0005 0001 data: 00

BUT...

The saa7113 has many adressable registers, so when writing to it, the first byte specifies the subaddress (internal address of the register), the second byte the data to write; following bytes, if present, are written to consecutive registers. That means that the write here above reported sets 0x52 in register 0x06, 0x8e in register 0x07 and 0x01 in register 0x08.

But, during a read, how can registered be addressed? The datasheet of the saa7113 specifies this: first perform a write of length 1 to the device specifying the subaddress as data. Than read from the device.

Well, looking at the logs, that is what happens, but in addition the bRequest of the write before the each read is set to 0x03. Why this happens?

Anyway, I have some troubles with reads... I have to investigate more...

Ludovico Cavedon


got following email from Sascha Sommer a longer time ago, this is regarding I2C reads:

Folgendes schaut mir nach einem i2c read aus:

001401:  OUT: 40 03 00 00 4a 00 01 00    >>>  1f
001402:  OUT: c0 00 00 00 05 00 01 00    <<<  00
001403:  OUT: c0 02 00 00 4a 00 01 00    <<<  91
001404:  OUT: c0 00 00 00 05 00 01 00    <<<  00

Als erstes wird das statusregister (0x1f) zum lesen ausgewählt (1401). Dann wirt index 0x5 überprüft ob alles glatt gegangen ist.(1402) Dann wird der Wert des ausgewählten Registers aus 0x4a gelesen (1403) und wieder überprüft ob ein Fehler passiert ist (1404).

Markus Rechberger

I2C Tuner Hacking

Now some let's look at the tuner. Changing the frequency is very simple, just write it a 4 byte i2c message to the 0xc2 address:

40 02 0000 00c2 0004 data: 06 52 8e 01
c0 00 0000 0005 0001 data: 00

I saw also reads from athe tuner, but haven't investigated yet...

c0 02 0000 00c2 0001 data: 3c
c0 00 0000 0005 0001 data: 00

However, code for the tuner is already implemented in the kernel (drivers/media/video/tuner.c).

A good news: we managed to change the channel!! At the moment it's working only with mplayer, nor with with tvtime or xawtv. I think it's just some wrong setting somewhere...

As I previously wrote, there is a device at address 0x68. Here are the operations I logged, but I haven't gone deep into it yet:

c0 02 0000 0086 0001 data: af
c0 00 0000 0005 0001 data: 00

c0 02 0000 0086 0001 data: ad
c0 00 0000 0005 0001 data: 00

40 02 0000 0086 0004 data: 00 d6 70 49
c0 00 0000 0005 0001 data: 00

40 02 0000 0086 0004 data: 00 16 70 49
c0 00 0000 0005 0001 data: 00
]

... never logged anything different.

''Ludovico Cavedon''

== Resolution ==
remember the saa7113 is similar with the saa7111 (which is also in the kernel sourcetree)

regarding the video resolution..

Mauro pointed me to an existing driver which does software scaling, if you have a look at our device with usbview you can see following:

                        Endpoint Address: 82
                        Direction: in
                        Attribute: 1
                        Type: Isoc
                        Max Packet Size: 1024
                        Interval: 125us

max packet size 1024 bytes <- this one is also connected with a resolution interface 0 alternate number 7 has the highest max packet size (3072 bytes) and it supports the highest resolution. in windows if you switch the resolution it also changes the alternate number(you know you have the choice between a few resolutions in windows) if you close cinergytv it switches back to interface 0 alternate 0 which has a max packet size of 0 bytes (and you will also notice that the device cools down again), but also index 0x0c is able to switch the device off (so that the led goes off.. looks like my led doesn't work at all anymore)

Markus Rechberger

em2820 protocol overview

(I only work with alternate number 7)

example:

0x1c -> value 0x1b -> width 694
0x1c -> value 0x1d -> width 692 (but blueish video/colorspace?)
0x1c -> value 0x1e -> width 692 (correct color)
0x1c -> value 0xff -> width 466

possible writes to the device:

OUT: 40 00 00 00 06 00 01 00 >>> 40
OUT: 40 00 00 00 08 00 01 00 >>> ff
OUT: 40 00 00 00 0c 00 01 00 >>> 00 #disable device 
OUT: 40 00 00 00 0c 00 01 00 >>> 10 #enable device
OUT: 40 00 00 00 0e 00 01 00 >>> c0
OUT: 40 00 00 00 0e 00 01 00 >>> c2
OUT: 40 00 00 00 0e 00 01 00 >>> c5
OUT: 40 00 00 00 0e 00 01 00 >>> c6
OUT: 40 00 00 00 0f 00 01 00 >>> 00
OUT: 40 00 00 00 0f 00 01 00 >>> 07
OUT: 40 00 00 00 0f 00 01 00 >>> 87
OUT: 40 00 00 00 10 00 01 00 >>> 00
OUT: 40 00 00 00 11 00 01 00 >>> 11
OUT: 40 00 00 00 12 00 01 00 >>> 25 # disabled video output? 
OUT: 40 00 00 00 12 00 01 00 >>> 27 # disabled video output?
OUT: 40 00 00 00 12 00 01 00 >>> 67 # enables TV video?
OUT: 40 00 00 00 13 00 01 00 >>> 08
OUT: 40 00 00 00 14 00 01 00 >>> 32
OUT: 40 00 00 00 15 00 01 00 >>> 20
OUT: 40 00 00 00 16 00 01 00 >>> 20
OUT: 40 00 00 00 17 00 01 00 >>> 20
OUT: 40 00 00 00 18 00 01 00 >>> 00
OUT: 40 00 00 00 19 00 01 00 >>> 00
OUT: 40 00 00 00 1a 00 01 00 >>> 00
OUT: 40 00 00 00 1b 00 01 00 >>> 00 #strange effect.. if I set it to 0x01 the videosize is 722 0x02 => 720, 
                                                      0x03=>722 so only takes the first bit?
OUT: 40 00 00 00 1c 00 01 00 >>> 00 #cropping left side
OUT: 40 00 00 00 1c 00 01 00 >>> 08 #cropping left side
OUT: 40 00 00 00 1d 00 01 00 >>> 00 #cropping top
OUT: 40 00 00 00 1e 00 01 00 >>> b0 #cropping right side
OUT: 40 00 00 00 1e 00 01 00 >>> b4 #cropping right side
OUT: 40 00 00 00 1f 00 01 00 >>> 48 #cropping from the bottom
OUT: 40 00 00 00 20 00 01 00 >>> 00 #contrast
OUT: 40 00 00 00 20 00 01 00 >>> 10 #contrast
OUT: 40 00 00 00 21 00 01 00 >>> 00 #brightness
OUT: 40 00 00 00 21 00 01 00 >>> 14 #brightness
OUT: 40 00 00 00 22 00 01 00 >>> 00 #saturation
OUT: 40 00 00 00 22 00 01 00 >>> 10 #saturation
OUT: 40 00 00 00 23 00 01 00 >>> 00 #blue 00 (default?) look closer at 16*n (U) (YUV)?
OUT: 40 00 00 00 24 00 01 00 >>> 00 #red                                    (V) (YUV)?
OUT: 40 00 00 00 25 00 01 00 >>> 00 #sharpness
OUT: 40 00 00 00 26 00 01 00 >>> 00 #input height
OUT: 40 00 00 00 26 00 01 00 >>> 10 #input height
OUT: 40 00 00 00 26 00 01 00 >>> 30 #input height
OUT: 40 00 00 00 27 00 01 00 >>> 34 # alternate 7
                                    # 34 .. full sized video(width) 
                                    # 10 .. half sized video(width)
                                    # alternate 3, 5
                                    # 34 .. invalid video
                                    # 10 .. valid video
----
  10000 .. #0x10
 110100 .. #0x34
    100 .. screws the video at alternate 3 and 5?
  10000 .. this bit is responsible for the colorspace?
 100000 .. sets valid video at alternate 3 and 5
----
OUT: 40 00 00 00 28 00 01 00 >>> 01
OUT: 40 00 00 00 29 00 01 00 >>> af
OUT: 40 00 00 00 29 00 01 00 >>> b3
OUT: 40 00 00 00 2a 00 01 00 >>> 01
OUT: 40 00 00 00 2b 00 01 00 >>> 47
OUT: 40 00 00 00 30 00 02 00 >>> 33 13
OUT: 40 00 00 00 30 00 02 00 >>> 99 01
OUT: 40 00 00 00 32 00 02 00 >>> 33 03
OUT: 40 00 00 00 40 00 02 00 >>> 00 00 #unmute
OUT: 40 00 00 00 40 00 02 00 >>> 00 80 #mute
OUT: 40 00 00 00 42 00 01 00 >>> 02
OUT: 40 02 00 00 4a 00 02 00 >>> 01 08 # video i2c
OUT: 40 02 00 00 4a 00 02 00 >>> 02 c2 # video i2c
OUT: 40 02 00 00 4a 00 02 00 >>> 03 30 # video i2c
OUT: 40 02 00 00 4a 00 02 00 >>> 0a 80 # video i2c
OUT: 40 02 00 00 4a 00 02 00 >>> 0d 00 # video i2c
OUT: 40 02 00 00 4a 00 02 00 >>> 0e 01 # video i2c
OUT: 40 02 00 00 4a 00 02 00 >>> 0f 2a # video i2c
OUT: 40 02 00 00 4a 00 05 00 >>> 06 e9 0d 88 01 # video i2c
OUT: 40 02 00 00 4a 00 05 00 >>> 0a 80 47 40 00 # video i2c
OUT: 40 02 00 00 4a 00 05 00 >>> 10 08 0c e7 00 # video i2c
OUT: 40 02 00 00 86 00 04 00 >>> 00 16 70 49
OUT: 40 02 00 00 86 00 04 00 >>> 00 d6 70 49
OUT: 40 02 00 00 c2 00 04 00 >>> 05 e2 8e 01
OUT: 40 02 00 00 c2 00 04 00 >>> 05 e3 8e 01
OUT: 40 02 00 00 c2 00 04 00 >>> 06 52 8e 01
OUT: 40 02 00 00 c2 00 04 00 >>> 06 a2 8e 01
OUT: 40 02 00 00 c2 00 04 00 >>> 10 02 8e 02
OUT: 40 03 00 00 4a 00 01 00 >>> 00
OUT: 40 03 00 00 4a 00 01 00 >>> 1f
OUT: 40 03 00 00 a0 00 01 00 >>> 04

Markus Rechberger


Just some addtionaly simple informations about em2820 registers:

Register, Min., Max., Default, Meaning
0x20, 0x00, 0x1f, 0x10, contrast
0x21, 0x00, 0x7f, 0x14, brightness
0x22, 0x00, 0x1f, 0x10, saturation
0x25, 0x00, 0x0f, 0x03, sharpness

Moreover bit 0 of register 0x27 flips the image ;-)

I also logged something about muting/unmuting audio. The Cinergy 250 has two ways of outputting audio: via the USB link, orvia an external analog cable.

Looking at logs I supposed:

# To mute analog audio
40 00 0000 0040 0002 data: 00 80
40 00 0000 0042 0001 data: 02
c0 00 0000 0043 0001 data: 00

# To unmute analog audio
40 00 0000 0040 0002 data: 00 00
40 00 0000 0042 0001 data: 02
c0 00 0000 0043 0001 data: 00

# To mute USB audio
40 00 0000 000f 0001 data: 07

# To unmute USB audio
40 00 0000 000f 0001 data: 87

But it is not working in our code :-(

Register 0x0e is also involved: it is sometimes accessed (when changing usb audio status) and I saw it with various values (0x8e, 0xce, 0xca, 0xcb). Maybe some kind of volume?

Moreover: sometimes, when umuting analog audio, the following operations are performed:

40 00 0000 0040 0002 data: 08 88
40 00 0000 0042 0001 data: 0e
c0 00 0000 0043 0001 data: 00
40 00 0000 0040 0002 data: 08 88
40 00 0000 0042 0001 data: 10
c0 00 0000 0043 0001 data: 00
40 00 0000 0040 0002 data: 08 08
40 00 0000 0042 0001 data: 14
c0 00 0000 0043 0001 data: 00
40 00 0000 0040 0002 data: 08 88
40 00 0000 0042 0001 data: 16
c0 00 0000 0043 0001 data: 00
40 00 0000 0040 0002 data: 00 00
40 00 0000 0042 0001 data: 02
c0 00 0000 0043 0001 data: 00

Ludovico Cavedon

USB Audio

Small update aboute the audio volume:

the voulme of the audio in controlled by the USB device of the Cinergy, also when the audio is not sent through the USB link, but through an external audio cable.

Just load the snd-usb-audio ALSA module, see what the card number of the Cinergy is:

$ cat /proc/asound/cards
0 [V8235          ]: VIA8233 - VIA 8235
                     VIA 8235 with ALC202 at 0x1400, irq 9
1 [USB            ]: USB-Audio - Cinergy 250 USB
                     TerraTec Electronic GmbH Cinergy 250 USB at usb-0000:00:10.3-4, high speed

So card 1 in my case:

$ amixer -c 1
Simple mixer control 'PCM',0
  Capabilities: cvolume cswitch cswitch-joined
  Capture channels: Mono
  Limits: Capture 0 - 16
  Mono: Capture 4 [25%] [on]

$ amixer -c 1 sset PCM 5
Simple mixer control 'PCM',0
  Capabilities: cvolume cswitch cswitch-joined
  Capture channels: Mono
  Limits: Capture 0 - 16
  Mono: Capture 5 [31%] [on]

Ludovico Cavedon


be sure you loaded the alsa usbaudio driver not the depreciated one that floats around somewhere else in the kernel.

to get it work with a higher quality use sox (you might have to adjust dsp and dsp2 there):

sox -t ossdsp -r 48000 -b -c 2 /dev/dsp -t ossdsp /dev/dsp2

Kernel 2.6.14 issue, the videotransfer will stop if usbaudio gets initialized with too less requested packets:

to get full quality audio work you need to patch this kernel

/usr/src/linux-2.6.14/sound/usb/usbaudio.c

set:
#define MAX_PACKS       10
to 
#define MAX_PACKS       100

recompile the snd_usb_audio module and load it with

modprobe snd_usb_audio nrpacks=80


good luck with it

Markus

Support for various alternate numbers

Index 0x27 with value 0x34 alternate number 5:

mplayer -tv driver=v4l2:width=360:height=288:outfmt=yuy2 tv:// -vo x11

Upload:MarkusRechberger/alternate5-1.jpg

another screenshot with 0x27 having 0x34 as value:

mplayer -tv driver=v4l2:width=720:height=288:outfmt=yuy2 tv:// -vo x11

Upload:MarkusRechberger/alternate5-2.jpg

and finally a correct one (with the patched driver, alternate 5):

mplayer -tv driver=v4l2:width=360:height=288:outfmt=yuy2 tv:// -vf tinterlace -vo x11

Upload:MarkusRechberger/alternate5.jpg

alternate 3:

mplayer -tv driver=v4l2:width=360:height=288:outfmt=yuy2 tv:// -vo x11

Upload:MarkusRechberger/alternate3-ok.jpg


valid configurations for following alternate numbers are still missing:

alternate 1,2,4,6

Markus Rechberger

i2c Video Hacking

as mentioned in the tuner hacking section, the first byte identifies a register on the saa7113H chip, so in that case the sniffed data would never have shown up the i2c writes that exactly:

i2c table for the saa7113H chip on the terratec cinergy usb 250

Breq, Index, first byte, data, description
0x02, 0x4a, 0x0b, 0x47, enables video (default looks like black/white)
0x02, 0x4a, 0x0c, 0x40, enables the colour

so the call to enable a coloured video looks like:

em2800_write_regs_req(dev,0x02,0x4a,"\x0b\x47",2);
em2800_write_regs_req(dev,0x02,0x4a,"\x0c\x40",2);

or

em2800_write_regs_req(dev,0x02,0x4a,"\x0b\x47\x40",3);


Markus Rechberger


Ok, I stopped asking my why bRequest is 3; maybe if we manage to have some specs, it will be easier to understand.

Let's look more in detail at what is happening with the saa7113. The device is always initialized writing a fixed set of values to it's first 16 registers. The Windows driver does this many times: I wondering why; however I noticed this fact: if I first initialize the saa7113, second set up the em2820 with the data from the logs (from Markus), then the settings of the the saa7113h are lost. Maybe the em2820 is doing some kind of reset of the chips on the board.

Here the modified initialization table follows; the values marked with **, are those I changed to match the setting from the Windows driver.

  0x00, 0x00, /* PH7113_CHIP_VERSION 00 - ID byte */
  0x01, 0x08, /* PH7113_INCREMENT_DELAY - (1) (1) (1) (1) IDEL3 IDEL2 IDELL1 IDEL0 */
  0x02, 0xc2, /** PH7113_ANALOG_INPUT_CONTR_1 - FUSE1 FUSE0 GUDL1 GUDL0 MODE3 MODE2 MODE1 MODE0 */
  0x03, 0x30, /** PH7113_ANALOG_INPUT_CONTR_2 - (1) HLNRS VBSL WPOFF HOLDG GAFIX GAI28 GAI18 */
  0x04, 0x00, /* PH7113_ANALOG_INPUT_CONTR_3 - GAI17 GAI16 GAI15 GAI14 GAI13 GAI12 GAI11 GAI10 */
  0x05, 0x00, /* PH7113_ANALOG_INPUT_CONTR_4 - GAI27 GAI26 GAI25 GAI24 GAI23 GAI22 GAI21 GAI20 */
  0x06, 0x89, /** PH7113_HORIZONTAL_SYNC_START - HSB7 HSB6 HSB5 HSB4 HSB3 HSB2 HSB1 HSB0 */
  0x07, 0x0d, /** PH7113_HORIZONTAL_SYNC_STOP - HSS7 HSS6 HSS5 HSS4 HSS3 HSS2 HSS1 HSS0 */
  0x08, 0x88, /* PH7113_SYNC_CONTROL - AUFD FSEL FOET HTC1 HTC0 HPLL VNOI1 VNOI0 */
  0x09, 0x01, /** PH7113_LUMINANCE_CONTROL - BYPS PREF BPSS1 BPSS0 VBLB UPTCV APER1 APER0 */
  0x0a, 0x80, /* PH7113_LUMINANCE_BRIGHTNESS - BRIG7 BRIG6 BRIG5 BRIG4 BRIG3 BRIG2 BRIG1 BRIG0 */
  0x0b, 0x47, /* PH7113_LUMINANCE_CONTRAST - CONT7 CONT6 CONT5 CONT4 CONT3 CONT2 CONT1 CONT0 */
  0x0c, 0x40, /* PH7113_CHROMA_SATURATION - SATN7 SATN6 SATN5 SATN4 SATN3 SATN2 SATN1 SATN0 */
  0x0d, 0x00, /* PH7113_CHROMA_HUE_CONTROL - HUEC7 HUEC6 HUEC5 HUEC4 HUEC3 HUEC2 HUEC1 HUEC0 */
  0x0e, 0x01, /* PH7113_CHROMA_CONTROL - CDTO CSTD2 CSTD1 CSTD0 DCCF FCTC CHBW1 CHBW0 */
  0x0f, 0x2a, /** PH7113_CHROMA_GAIN_CONTROL - ACGC CGAIN6 CGAIN5 CGAIN4 CGAIN3 CGAIN2 CGAIN1 CGAIN0 */
  0x10, 0x08, /** PH7113_FORMAT_DELAY_CONTROL - OFTS1 OFTS0 HDEL1 HDEL0 VRLN YDEL2 YDEL1 YDEL0 */
  0x11, 0x0c, /** PH7113_OUTPUT_CONTROL_1 - GPSW1 CM99 GPSW0 HLSEL OEYC OERT VIPB COLO */
  0x12, 0x07, /** PH7113_OUTPUT_CONTROL_2 - RTSE13 RTSE12 RTSE11 RTSE10 RTSE03 RTSE02 RTSE01 RTSE00 */
  0x13, 0x00, /* PH7113_OUTPUT_CONTROL_3 - ADLSB (1) (1) OLDSB FIDP (1) AOSL1 AOSL0 */
  0x14, 0x00, /* RESERVED 14 - (1) (1) (1) (1) (1) (1) (1) (1) */
  0x15, 0x00, /* PH7113_V_GATE1_START - VSTA7 VSTA6 VSTA5 VSTA4 VSTA3 VSTA2 VSTA1 VSTA0 */
  0x16, 0x00, /* PH7113_V_GATE1_STOP - VSTO7 VSTO6 VSTO5 VSTO4 VSTO3 VSTO2 VSTO1 VSTO0 */
  0x17, 0x00, /* PH7113_V_GATE1_MSB - (1) (1) (1) (1) (1) (1) VSTO8 VSTA8 */

The registers we are interested in are:

  • 0x02: to select video input (tuner, composite, S-Video)
  • 0x08 and 0x0e: to select video standard (PAL, NTSC, SECAM, ...)
  • 0x0a to 0x0c: are the brightness, contrast and saturation; please note that the Windows driver does not change these registers, but those registers inside the em2820. It would be interesting to try both ways and see quality differences.
  • 0x0d: hue; changed also by the Windows driver.

The only register I saw being read is 0x1f, that reports the status of the decoder, but I haven't strted to play with it yet. However, the code to control

Ludovico Cavedon