Re: Anchor Chips V4L2 driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 11/06/2011 01:02 AM, Mauro Carvalho Chehab wrote:
> Em 06-11-2011 04:36, John McMaster escreveu:
>> On 06/07/2011 12:35 AM, Hans de Goede wrote:
>>> Hi,
>>>
>>> On 06/07/2011 07:24 AM, John McMaster wrote:
>>>> On 06/06/2011 12:43 AM, Hans de Goede wrote:
>>>>> Hi,
>>>>>
>>>>> On 06/06/2011 07:40 AM, John McMaster wrote:
>>>>>> On 06/03/2011 06:22 AM, Hans de Goede wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> On 06/03/2011 02:15 PM, Mauro Carvalho Chehab wrote:
>>>>>>>> Em 03-06-2011 02:40, John McMaster escreveu:
>>>>>>>>> I'd like to write a driver for an Anchor Chips (seems to be
>>>>>>>>> bought by
>>>>>>>>> Cypress) USB camera Linux driver sold as an AmScope MD1800.  It
>>>>>>>>> seems
>>>>>>>>> like this implies I need to write a V4L2 driver.  The camera
>>>>>>>>> does not
>>>>>>>>> seem its currently supported (checked on Fedora 13 / 2.6.34.8)
>>>>>>>>> and I
>>>>>>>>> did
>>>>>>>>> not find any information on it in mailing list archives.  Does
>>>>>>>>> anyone
>>>>>>>>> know or can help me identify if a similar camera might already be
>>>>>>>>> supported?
>>>>>>>> I've no idea. Better to wait for a couple days for developers to
>>>>>>>> manifest
>>>>>>>> about that, if they're already working on it.
>>>>>>>>
>>>>>>>>> lsusb gives the following output:
>>>>>>>>>
>>>>>>>>> Bus 001 Device 111: ID 0547:4d88 Anchor Chips, Inc.
>>>>>>>>>
>>>>>>>>> I've started reading the "Video for Linux Two API Specification"
>>>>>>>>> which
>>>>>>>>> seems like a good starting point and will move onto using source
>>>>>>>>> code as
>>>>>>>>> appropriate.  Any help would be appreciated.  Thanks!
>>>>>>>> You'll find other useful information at linuxtv.org wiki page. The
>>>>>>>> better
>>>>>>>> is to write it as a sub-driver for gspca. The gspca core have
>>>>>>>> already
>>>>>>>> all
>>>>>>>> that it is needed for cameras. So, you'll need to focus only at the
>>>>>>>> device-specific
>>>>>>>> stuff.
>>>>>>> I can second that you should definitely use gspca for usb webcam(ish)
>>>>>>> device
>>>>>>> drivers. As for how to go about this, first of all grep through the
>>>>>>> windows drivers
>>>>>>> for strings which may hint on the actual bridge chip used, chances
>>>>>>> are
>>>>>>> good
>>>>>>> there is an already supported bridge inside the camera.
>>>>>>>
>>>>>>> If not then make usb dumps, and start reverse engineering ...
>>>>>>>
>>>>>>> Usually it is enough to replay the windows init sequence to get the
>>>>>>> device
>>>>>>> to stream over either an bulk or iso endpoint, and then it is time to
>>>>>>> figure out what that stream contains (jpeg, raw bayer, some custom
>>>>>>> format ???)
>>>>>>>
>>>>>>> Regards,
>>>>>>>
>>>>>>> Hans
>>>>>> Thanks for the response.  I replayed some packets (using libusb)
>>>>>> and am
>>>>>> able to get something resembling the desired image through its bulk
>>>>>> endpoint.  So now I just need to figure out how to decode it better,
>>>>>> options, etc.  I'll post back to the list once I get something
>>>>>> moderately stable running and have taken a swing at the kernel driver.
>>>>>>
>>>>> Hmm, bulk you say and cypress and 8mp usb2.0 have you tried looking
>>>>> at the gspca-ovfx2 driver? Likely you've an ovfx2 cam with an as of
>>>>> yet unknown usb-id. Chances are just adding the id is enough, although
>>>>> your sensor may be unknown.
>>>>>
>>>>> Regards,
>>>>>
>>>>> Hans
>>>> If it helps, I should have also mentioned that with a small amount of
>>>> digging I found that the camera unit is put together by ScopeTek.  My
>>>> reference WIP implementation is at
>>>> https://github.com/JohnDMcMaster/uvscopetek which I'm comparing to
>>>> 2.6.39.1 drivers.
>>>>
>>>> Anyway, looking at reg_w() I see that it likes to make 0x00, 0x02, or
>>>> 0x0A requests where as mine makes 0x01, 0x0A, and mostly 0x0B requests.
>>>> I do see that it tends to want a byte back though like mine (0x0A except
>>>> at end).  My code has a few 3 byte returns (byte 0 varies, byte 1 fixed
>>>> at 0x00, byte 2 fixed at 0x08 like others), so I'm not sure if its a
>>>> good match for reg read.  Following that I tried to grep around some
>>>> more for a number of the more interesting numbers (eg: 90D8 as opposed
>>>> to 0001) in the $SRC/drivers/media/video dir and could only find
>>>> scattered matches.  I do realize that a lot of the more esoteric numbers
>>>> could be specific settings and not registers, commands, etc.  Or maybe
>>>> tofx2 is related and I'm not understanding the bridge concept?
>>> I think you may have been looking at the wrong driver, if your trace
>>> shows
>>> mostly 0x0a, 0x0b and 0x02 requests then chances are high it is indeed
>>> an ovfx2, the ovfx2 driver is part of drivers/media/video/gspca/ov519.c
>>> because it shares a bunch of functions (mostly sensor detect stuff) with
>>> the ov511/ov518/ov519 driver.
>>>
>>> And it makes 0x0a request for ovfx2 (bridge) register writes, 0x0b
>>> requests for ovfx2 (bridge) register reads and 0x02 requests for i2c
>>> writes.
>>>
>>> If things indeed seem a better match with the ovfx2 support in ov519.c,
>>> one quick way to find out if it is an ovfx2 is to just add the usb-id of
>>> your camera to ov519.c as an ovfx2 camera, and load the driver, first
>>> thing the driver does is try to detect the sensor type through the i2c
>>> bus between the bridge and the sensor, if that works (even if it
>>> detects an unknown sensor, but the sensor id found seems sensible) it
>>> it likely is an ovfx2.
>>>
>>> You could also try grapping for strings like fx2 and cypress in the
>>> windows
>>> driver. Also try looking at the .inf file from the windows driver, if
>>> that
>>> contains different (maybe commented out) usb-ids of potentially
>>> compatible
>>> cams.
>>>
>>> Regards,
>>>
>>> Hans
>>>
>>>
>>>> John
>>>>
>> Hi,
>> Time to resurrect a dead thread ;)   Got busy with work but I'm still
>> determined to get this working. 
>>
>> A lot of things sound close but maybe not quite right?  I will not doubt
>> your fx2 was a good guess.  I also dug a little more and found some
>> addition Windows driver files I didn't notice before and tried to grep
>> for FX.  I did previously try to match up some of the other VID/PIDs
>> before and no luck there.  I finally decided to open it up and its a
>> Cypress CY7C68013A, an "EZ-USB-FX2LP".
> The Cypress FX/FX2/.. family is a series of programmable processors found on
> several media devices. There's a firmware somewhere that configures its behavior.
> Vendors using it in general just gets the standard firmware, and add some
> device-specific stuff (but nothing prevents them to change or add some reqs).
> I doubt that they need to do that for a simple camera. They generally use those
> things when they want to implement InfraRed or CI support on DVB devices, that are
> much more complex.
>
> If you discover that just a few things on your device is different, then
> it is probably better to just improve the existing driver to handle the
> differences.
>
>> This is what happens when I
>> patch it to my VID / PID with some debugging turned on:
>>
>> gspca: main v2.9.0 registered
>> usbcore: registered new interface driver ov519
>> registered
>> usb 2-1: new high speed USB device using ehci_hcd and address 5
>> usb 2-1: config 1 interface 0 altsetting 0 bulk endpoint 0x82 has
>> invalid maxpacket 1024
>> usb 2-1: New USB device found, idVendor=0547, idProduct=4d88
>> usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
>> usb 2-1: Product: DCM800
>> usb 2-1: Manufacturer: ScopeTek
>> gspca: probing 0547:4d88
>> Write reg 0x0060 -> [0x00]
>> Write reg 0x0001 -> [0x02]
>> Write reg 0x001d -> [0x0f]
>> Write reg 0x0082 -> [0xe9]
>> Write reg 0x00c7 -> [0xea]
>> Write reg 0x0010 -> [0xeb]
>> Write reg 0x00f6 -> [0xec]
>> Write reg 0x0042 -> [0x00]
>> i2c 0x80 -> [0x12] failed
>> Write reg 0x00c0 -> [0x00]
>> i2c 0x80 -> [0x12] failed
>> Write reg 0x00a0 -> [0x00]
>> i2c 0x80 -> [0x12] failed
>> Write reg 0x0060 -> [0x00]
>> i2c 0x80 -> [0x12] failed
>> Can't determine sensor slave IDs
>> OV519 Config failed
>> ov519: probe of 2-1:1.0 failed with error -16
> It seems to me that only the sensor weren't detect, and that reg 0x0a is
> used for bridge initialization by ovfx2_configure().
>
> Don't you have the USB sniff from your original driver? You can easily see
> there the req used by the init sequence and check if it is the same as
> this one. I suspect that is also uses 0x0a during device init.
>
>> Maybe a key piece of data I gleaned that might help identify it.  To set
>> the resolution it sends:
>>
>> request = 0x0B, request type = USB_DIR_IN | USB_TYPE_VENDOR |
>> USB_RECIP_DEVICE, value = width, index = 0x034C, ret = {0x08}
>>
>> and
>>
>> request = 0x0B, request type = USB_DIR_IN | USB_TYPE_VENDOR |
>> USB_RECIP_DEVICE, value = height index = 0x034E, ret = {0x08}
>>
>> This seems to point that a 0x0B request would be some sort of write,
>> wValue is a register value, and wIndex is the register.  
> Such kind of init are generally at sensor level. All bridge may need to
> know is the used dot clock, if it can't auto-detect it.
>
>> However in the
>> OV519 this type of request seems to be a read:
>>
>> static int reg_r(struct sd *sd, __u16 index)
>> ...
>>     case BRIDGE_OVFX2:
>>         req = 0x0b;
>> ...
>>
>>
>> On the off chance that the numbers were just switched around I tried the
>> following quick switches as a long shot:
>>
>> reg_w()
>> Does bulk setup
>> Orig: 0x0A
>> Switched to 0x0B
>>
>> reg_r()
>> Orig: 0x0B
>> Switched to 0x0A
> The above doesn't seem right, as your init seemed to work using req 0x0b.
>
>>
>> i2c_w() => ovfx2_i2c_w()
>> Orig: 0x02
>> Switched to 0x01
>>
>> i2c_r() => ovfx2_i2c_r()
>> Orig: 0x03
>> Switched to 0x02 on loose grounds
> Had you try to just do this change?
>>
>> But not too surprisingly it didn't do very well and stopped right after
>> "Write reg 0x0060 -> [0x00] failed".  Additionally, I haven't been able
>> to figure out how to find SOF/EOF and none of the algorithms presented
>> in ov519.c seem to be applicable to the data streams I'm seeing.  The
>> biggest hint I have is that there seems to be a darkened pixel row the
>> second from the top and left in case that's familiar.
>>
>> In any case, I got a bit more serious and learned the basic V4L API as
>> well as GSPCA enough to write a proof of concept driver for it (I used
>> dead reckoning on frame size to find SOF/EOF but it of course gets
>> messed up if a packet drops which sometimes happens during init).  I
>> figure even if there is an existing driver it was a good experience for
>> me and it should help fitting it in.  I also read the datasheet enough
>> to figure out how to rip the firmware off although I don't know if it
>> would be of any use.  From what I can tell from the datasheet though
>> even if its the same chip it could be configured in a number of
>> different ways and there is no guarantee the requests would line up.  Of
>> course, I'm not going to deny that they are the same requests and I'm
>> still misinterpreting it since you did predict the chip before me ;) 
>> Thanks for the help and hopefully with a little more prodding we'll be
>> able to straighten this out.
>>
>> John
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-media" in
>> the body of a message to majordomo@xxxxxxxxxxxxxxx
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> If your firmware is using a different settings of req's for I2C, you probably
> need to do something like the patch below. This will avoid breaking support
> for the existing devices, and will be simple enough for you to re-use the
> existing driver, after figuring out the missing parts. Of yourse, you'll need
> to replace the dead:beef USB ID by yours ;)
>
> Regards,
> Mauro
>
> diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
> index 6a01b35..9ca3cfc 100644
> --- a/drivers/media/video/gspca/ov519.c
> +++ b/drivers/media/video/gspca/ov519.c
> @@ -92,6 +92,8 @@ struct sd {
>  #define BRIDGE_W9968CF		6
>  #define BRIDGE_MASK		7
>  
> +#define BRIDGE_OVFX2_V2	9			/* For devices with another firmware */
> +
>  	char invert_led;
>  #define BRIDGE_INVERT_LED	8
>  
> @@ -2448,14 +2450,19 @@ static int ov518_i2c_r(struct sd *sd, u8 reg)
>  
>  static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value)
>  {
> -	int ret;
> +	int ret, req;
>  
>  	if (sd->gspca_dev.usb_err < 0)
>  		return;
>  
> +	if (id->driver_info & BRIDGE_OVFX2_V2)
> +		req = 0x0b;
> +	else
> +		req = 0x02;
> +
>  	ret = usb_control_msg(sd->gspca_dev.dev,
>  			usb_sndctrlpipe(sd->gspca_dev.dev, 0),
> -			0x02,
> +			req,
>  			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
>  			(u16) value, (u16) reg, NULL, 0, 500);
>  
> @@ -2469,14 +2476,19 @@ static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value)
>  
>  static int ovfx2_i2c_r(struct sd *sd, u8 reg)
>  {
> -	int ret;
> +	int ret, req;
>  
>  	if (sd->gspca_dev.usb_err < 0)
>  		return -1;
>  
> +	if (id->driver_info & BRIDGE_OVFX2_V2)
> +		req = 0x0b;
> +	else
> +		req = 0x03;
> +
>  	ret = usb_control_msg(sd->gspca_dev.dev,
>  			usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
> -			0x03,
> +			req,
>  			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
>  			0, (u16) reg, sd->gspca_dev.usb_buf, 1, 500);
>  
> @@ -5023,6 +5035,7 @@ static const struct usb_device_id device_table[] = {
>  	{USB_DEVICE(0x05a9, 0x0530),
>  		.driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
>  	{USB_DEVICE(0x05a9, 0x2800), .driver_info = BRIDGE_OVFX2 },
> +	{USB_DEVICE(0xdead, 0xbeef), .driver_info = BRIDGE_OVFX2 | BRIDGE_OVFX2_V2 },
>  	{USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 },
>  	{USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 },
>  	{USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS },

After applying this adapted patch (2.6.34.8):

diff --git a/ov519/ov519.c b/ov519/ov519.c
index 4f3ae2b..398b075 100644
--- a/ov519/ov519.c
+++ b/ov519/ov519.c
@@ -70,6 +70,8 @@ struct sd {
 
     char invert_led;
 #define BRIDGE_INVERT_LED    8
+    char ovfx_v2;
+#define BRIDGE_OVFX2_V2    16            /* For devices with another
firmware */
 
     char snapshot_pressed;
     char snapshot_needs_reset;
@@ -2188,11 +2190,19 @@ static int ov518_i2c_r(struct sd *sd, __u8 reg)
 
 static int ovfx2_i2c_w(struct sd *sd, __u8 reg, __u8 value)
 {
-    int ret;
+    int ret, req;
+
+     if (sd->gspca_dev.usb_err < 0)
+         return -1;
+
+    if (sd->ovfx_v2)
+        req = 0x0b;
+    else
+        req = 0x02;
 
     ret = usb_control_msg(sd->gspca_dev.dev,
             usb_sndctrlpipe(sd->gspca_dev.dev, 0),
-            0x02,
+            req,
             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
             (__u16)value, (__u16)reg, NULL, 0, 500);
 
@@ -2207,11 +2217,19 @@ static int ovfx2_i2c_w(struct sd *sd, __u8 reg,
__u8 value)
 
 static int ovfx2_i2c_r(struct sd *sd, __u8 reg)
 {
-    int ret;
+    int ret, req;
+
+     if (sd->gspca_dev.usb_err < 0)
+         return -1;
+
+    if (sd->ovfx_v2)
+        req = 0x0b;
+    else
+        req = 0x03;
 
     ret = usb_control_msg(sd->gspca_dev.dev,
             usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
-            0x03,
+            req,
             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
             0, (__u16)reg, sd->gspca_dev.usb_buf, 1, 500);
 
@@ -3017,6 +3035,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
 
     sd->bridge = id->driver_info & BRIDGE_MASK;
     sd->invert_led = id->driver_info & BRIDGE_INVERT_LED;
+    sd->ovfx_v2 = id->driver_info & BRIDGE_OVFX2_V2;
 
     switch (sd->bridge) {
     case BRIDGE_OV511:
@@ -4609,6 +4628,7 @@ static const __devinitdata struct usb_device_id
device_table[] = {
     {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 },
     {USB_DEVICE(0x05a9, 0x0530), .driver_info = BRIDGE_OV519 },
     {USB_DEVICE(0x05a9, 0x2800), .driver_info = BRIDGE_OVFX2 },
+    {USB_DEVICE(0x0547, 0x4d88), .driver_info = BRIDGE_OVFX2 |
BRIDGE_OVFX2_V2 },
     {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 },
     {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 },
     {USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS },


I get this:

gspca: main v2.9.0 registered
usbcore: registered new interface driver ov519
ov519: registered
usb 2-1: new high speed USB device using ehci_hcd and address 17
usb 2-1: config 1 interface 0 altsetting 0 bulk endpoint 0x82 has
invalid maxpacket 1024
usb 2-1: New USB device found, idVendor=0547, idProduct=4d88
usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 2-1: Product: DCM800
usb 2-1: Manufacturer: ScopeTek
gspca: probing 0547:4d88
ov519: i2c 0x80 -> [0x12] failed
ov519: Write reg 0x00c0 -> [0x00] failed
ov519: Write reg 0x00a0 -> [0x00] failed
ov519: Write reg 0x0060 -> [0x00] failed
ov519: Can't determine sensor slave IDs
ov519: OV519 Config failed
ov519: probe of 2-1:1.0 failed with error -16

I'm still not sure I follow this though because your patch suggests that
I2C reads and writes use the same request.  If I swapped the
ovfx2_i2c_w() for 0x0a the request would then conflict with reg_w().  If
you would like me to post a driver here, I'm still having difficulty
seeing what requests would be shared by this and would think integrating
into it would be a lot more work than another separate driver.  Unless
you think that really is going in the wrong direction, how about I post
a proof of concept stand alone driver showing what works for me and it
can be integrated into ov519 as needed.

John

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux