- style fixes,

- fix error handling in CamDevice.cpp,
- implemented PowerOnSensor() for Sonix,
- add a ProbeByIICSignature method to CamSensor, that takes a list of regs and values to match, as some Linux drivers do,
- add (unfinished, mostly copied from TAS5110C1B) support for TAS5130D1B sensor,
- add (unfinished) support for PAS106 sensor, probe by IIC signature as the Linux driver does,
- add probing by IIC signature for the HV7131E1 sensor as the Linux driver does,
- use -lusb for BeOS (actually ZETA) builds, don't try to use the Haiku USB Kit,
- for the TAS5110C1B sensor, use remove code dup and call SetVideoFrame(), tweaked the values to match those sniffed from the XP driver,
- disabled gain control for now on sonix, doesn't seem to work on all models.
This gets another sonix-based webcam working, partially at least, so if you want to get one to try until UVC works, try this one:
http://www.macally.com/EN/product/ArticleShow.asp?ArticleID=119
We should at least have one webcam supported in the alpha :D
+alphabranch


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32795 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
François Revol 2009-08-28 22:08:22 +00:00
parent b81516b289
commit fb086488a9
8 changed files with 489 additions and 29 deletions

View File

@ -524,7 +524,7 @@ CamDevice::DataPumpThread()
len = fBulkIn->BulkTransfer(fBuffer, fBufferLen);
#endif
PRINT((CH ": got %ld bytes" CT, len));
//PRINT((CH ": got %ld bytes" CT, len));
#ifdef DEBUG_WRITE_DUMP
write(fDumpFD, fBuffer, len);
#endif

View File

@ -6,10 +6,11 @@ SetSubDirSupportedPlatformsBeOSCompatible ;
if $(TARGET_PLATFORM_HAIKU_COMPATIBLE) {
usbKitLibraryName = libdevice.so ;
} else {
# usbKitLibraryName = usb ;
usbKitLibraryName = USBKit.a ;
UsePublicHeaders [ FDirName drivers ] ;
UsePublicHeaders [ FDirName device ] ;
# usbKitLibraryName = USBKit.a ;
# UsePublicHeaders [ FDirName drivers ] ;
# UsePublicHeaders [ FDirName device ] ;
# use -lusb on ZETA
usbKitLibraryName = usb ;
}
# source directories
@ -38,7 +39,8 @@ csTransformsSources = Bayer.cpp ;
## sensors sources
local sensorsSources ;
sensorsSources = hdcs1000.cpp hv7131e1.cpp pb0100.cpp tas5110c1b.cpp ;
sensorsSources = hdcs1000.cpp hv7131e1.cpp pas106b.cpp pb0100.cpp
tas5110c1b.cpp tas5130d1b.cpp ;
## how to build header files from sources to include the list of built-in addons.
# but it doesn't seem to work for some reason...

View File

@ -15,6 +15,7 @@
const usb_webcam_support_descriptor kSupportedDevices[] = {
{{ 0, 0, 0, 0x0c45, 0x6005 }, "Sonix", "Sonix", "tas5110c1b" }, // mine
{{ 0, 0, 0, 0x0c45, 0x6007 }, "Sonix", "macally ICECAM", "tas5110c1b" }, // Rajah's cam - SN9C101R
{{ 0, 0, 0, 0x0c45, 0x6009 }, "Trust", "spacec@m 120", NULL },
{{ 0, 0, 0, 0x0c45, 0x600d }, "Trust", "spacec@m 120", NULL },
@ -126,10 +127,81 @@ SonixCamDevice::SonixCamDevice(CamDeviceAddon &_addon, BUSBDevice* _device)
return;
}
//XXX: the XP driver sends this to the ICECAM... need to investigate.
#if 1
uint8 tmp_3[] = {
0x44, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0xa0,
0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x00, 0x41, 0x09, 0x00, 0x16, 0x12, 0x60, 0x86,
0x3b, 0x0f, 0x0e, 0x06, 0x00, 0x00, 0x03 };
WriteReg(SN9C102_CHIP_CTRL, tmp_3, 0x1f);
#endif
//XXX:DEBUG
#if 0
//XXX: the XP driver sends all this... investigate.
uint8 tmp_1[] = {0x09, 0x44};
WriteReg(SN9C102_CHIP_CTRL, tmp_1, sizeof(tmp_1));
WriteReg8(SN9C102_CHIP_CTRL, 0x44);
WriteReg8(SN9C102_CLOCK_SEL /*0x17*/, 0x29);
uint8 tmp_2[] = {0x44, 0x44};
WriteReg(SN9C102_CHIP_CTRL, tmp_2, 2);
//URB_FUNCTION_VENDOR_INTERFACE:
//(USBD_TRANSFER_DIRECTION_OUT, ~USBD_SHORT_TRANSFER_OK)
uint8 tmp_3[] = {
0x44, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0xa0,
0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x00, 0x41, 0x09, 0x00, 0x16, 0x12, 0x60, 0x86,
0x3b, 0x0f, 0x0e, 0x06, 0x00, 0x00, 0x03 };
WriteReg(SN9C102_CHIP_CTRL, tmp_3, 0x1f);
uint8 tmp_4[] = {0x01, 0x01, 0x07, 0x06};
//WriteReg(SN9C102_AE_STRX, tmp_4, 4);
uint8 tmp_5[] = {0x14, 0x0f};
//WriteReg(SN9C102_H_SIZE, tmp_5, 2);
WriteReg8(SN9C102_SYNC_N_SCALE, 0x86);
WriteReg8(SN9C102_CHIP_CTRL, 0x44); // again ??
uint8 tmp_6[] = { 0x60, 0x86 };
WriteReg(SN9C102_CLOCK_SEL /*0x17*/, tmp_6, 2);
WriteReg8(SN9C102_PIX_CLK, 0x2b);
// some IIC stuff for the sensor
uint8 tmp_7[] = { 0xb0, 0x61, 0x1c, 0xf8, 0x10, 0x00, 0x00, 0x16 };
//WriteReg(SN9C102_I2C_SETUP, tmp_7, 8);
WriteReg8(SN9C102_PIX_CLK, 0x4b);
uint8 tmp_8[] = { 0xa0, 0x61, 0x1c, 0x0f, 0x10, 0x00, 0x00, 0x16 };
//WriteReg(SN9C102_I2C_SETUP, tmp_8, 8);
#endif
#if 0
// some IIC stuff for the sensor
uint8 tmp_7[] = { 0xb0, 0x61, 0x1c, 0xf8, 0x10, 0x00, 0x00, 0x16 };
WriteReg(SN9C102_I2C_SETUP, tmp_7, 8);
WriteReg8(SN9C102_PIX_CLK, 0x4b);
uint8 tmp_8[] = { 0xa0, 0x61, 0x1c, 0x0f, 0x10, 0x00, 0x00, 0x16};
WriteReg(SN9C102_I2C_SETUP, tmp_8, 8);
#endif
//WriteReg8(SN9C102_PIX_CLK, 0x4b);
//###############
if (Sensor()) {
PRINT((CH ": CamSensor: %s" CT, Sensor()->Name()));
fInitStatus = Sensor()->Setup();
fVideoFrame = BRect(0, 0, Sensor()->MaxWidth()-1, Sensor()->MaxHeight()-1);
// SetVideoFrame(BRect(0, 0, Sensor()->MaxWidth()-1, Sensor()->MaxHeight()-1));
// SetVideoFrame(BRect(0, 0, 320-1, 240-1));
@ -205,16 +277,29 @@ DumpRegs();
}
status_t
SonixCamDevice::PowerOnSensor(bool on)
{
if (OrReg8(SN9C102_CHIP_CTRL, on ? 0x01 : 0x00) < 0)
return EIO;
return B_OK;
}
ssize_t
SonixCamDevice::WriteReg(uint16 address, uint8 *data, size_t count)
{
PRINT((CH "(%u, @%p, %u)" CT, address, data, count));
status_t err;
if (address + count > SN9C102_REG_COUNT) {
PRINT((CH ": Invalid register range [%u;%u]" CT, address, address+count));
return EINVAL;
}
memcpy(&fCachedRegs[address], data, count);
return SendCommand(USB_REQTYPE_DEVICE_OUT, 0x08, address, 0, count, data);
err = SendCommand(USB_REQTYPE_DEVICE_OUT, 0x08, address, 0, count, data);
if (err < B_OK)
return err;
return count;
}
@ -222,6 +307,7 @@ ssize_t
SonixCamDevice::ReadReg(uint16 address, uint8 *data, size_t count, bool cached)
{
PRINT((CH "(%u, @%p, %u, %d)" CT, address, data, count, cached));
status_t err;
if (address + count > SN9C102_REG_COUNT) {
PRINT((CH ": Invalid register range [%u;%u]" CT, address, address+count));
return EINVAL;
@ -230,7 +316,10 @@ SonixCamDevice::ReadReg(uint16 address, uint8 *data, size_t count, bool cached)
memcpy(data, &fCachedRegs[address], count);
return count;
}
return SendCommand(USB_REQTYPE_DEVICE_IN, 0x00, address, 0, count, data);
err = SendCommand(USB_REQTYPE_DEVICE_IN, 0x00, address, 0, count, data);
if (err < B_OK)
return err;
return count;
}
@ -272,6 +361,8 @@ SonixCamDevice::WriteIIC(uint8 address, uint8 *data, size_t count)
{
status_t err;
uint8 buffer[8];
PRINT((CH "(%u, @%p, %u)" CT, address, data, count));
if (!Sensor())
return B_NO_INIT;
//dprintf(ID "sonix_i2c_write_multi(, %02x, %d, {%02x, %02x, %02x, %02x, %02x})\n", slave, count, d0, d1, d2, d3, d4);
@ -284,7 +375,7 @@ SonixCamDevice::WriteIIC(uint8 address, uint8 *data, size_t count)
buffer[2] = address;
memset(&buffer[3], 0, 5);
memcpy(&buffer[3], data, count-1);
buffer[7] = 0x10; /*0x14;*/ /* absolutely no idea why V4L2 driver use that value */
buffer[7] = 0x16; /* V4L2 driver uses 0x10, XP driver uses 0x16 ? */
for (int i = 0; i < 8; i++) {
PRINT(("[%d] = %02x\n", i, buffer[i]));
}
@ -311,6 +402,8 @@ SonixCamDevice::ReadIIC(uint8 address, uint8 *data)
{
status_t err, lasterr = B_OK;
uint8 buffer[8];
PRINT((CH "(%u, @%p)" CT, address, data));
if (!Sensor())
return B_NO_INIT;
//dprintf(ID "sonix_i2c_write_multi(, %02x, %d, {%02x, %02x, %02x, %02x, %02x})\n", slave, count, d0, d1, d2, d3, d4);
@ -321,7 +414,7 @@ SonixCamDevice::ReadIIC(uint8 address, uint8 *data)
buffer[7] = 0x10; /* absolutely no idea why V4L2 driver use that value */
err = WriteReg(SN9C102_I2C_SETUP, buffer, 8);
//dprintf(ID "sonix_i2c_write_multi: set_regs error 0x%08lx\n", err);
if (err) return err;
if (err < 8) return EIO;
err = WaitReadyIIC();
//dprintf(ID "sonix_i2c_write_multi: sonix_i2c_wait_ready error 0x%08lx\n", err);
//if (err) return err;
@ -334,17 +427,17 @@ SonixCamDevice::ReadIIC(uint8 address, uint8 *data)
buffer[7] = 0x10; /* absolutely no idea why V4L2 driver use that value */
err = WriteReg(SN9C102_I2C_SETUP, buffer, 8);
//dprintf(ID "sonix_i2c_write_multi: set_regs error 0x%08lx\n", err);
if (err) return err;
if (err < 8) return EIO;
err = WaitReadyIIC();
//dprintf(ID "sonix_i2c_write_multi: sonix_i2c_wait_ready error 0x%08lx\n", err);
if (err) return err;
if (err < B_OK) return err;
err = ReadReg(SN9C102_I2C_DATA0, buffer, 5);
if (err) lasterr = err;
if (err < 5) return EIO;
err = GetStatusIIC();
//dprintf(ID "sonix_i2c_write_multi: sonix_i2c_status error 0x%08lx\n", err);
if (err) return err;
if (err < B_OK) return err;
//dprintf(ID "sonix_i2c_write_multi: succeeded\n");
if (lasterr) return err;

View File

@ -64,6 +64,9 @@ class SonixCamDevice : public CamDevice
virtual status_t StartTransfer();
virtual status_t StopTransfer();
// sensor chip handling
virtual status_t PowerOnSensor(bool on);
// generic register-like access
virtual ssize_t WriteReg(uint16 address, uint8 *data, size_t count=1);
virtual ssize_t ReadReg(uint16 address, uint8 *data, size_t count=1, bool cached=false);

View File

@ -5,33 +5,53 @@
#include "CamSensor.h"
static const uint8 sProbeAddressList[] = {
0x00,0x01,0x02,0x11,0x13,0x14,0x15,0x16,0x17
};
static const uint8 sProbeMatchList[] = {
0x02,0x09,0x01,0x02,0x02,0x01,0xe2,0x02,0x82
};
class HV7131E1Sensor : public CamSensor {
public:
HV7131E1Sensor(CamDevice *_camera);
~HV7131E1Sensor();
status_t Probe();
const char* Name();
//XXX not sure
virtual bool Use400kHz() const { return false; };
virtual bool UseRealIIC() const { return false; };
};
// -----------------------------------------------------------------------------
HV7131E1Sensor::HV7131E1Sensor(CamDevice *_camera)
: CamSensor(_camera)
{
}
// -----------------------------------------------------------------------------
HV7131E1Sensor::~HV7131E1Sensor()
{
}
// -----------------------------------------------------------------------------
status_t
HV7131E1Sensor::Probe()
{
return ProbeByIICSignature(sProbeAddressList, sProbeMatchList,
sizeof(sProbeMatchList));
}
const char *
HV7131E1Sensor::Name()
{
return "Hynix hv7131e1";
}
// -----------------------------------------------------------------------------
B_WEBCAM_DECLARE_SENSOR(HV7131E1Sensor, hv7131e1)

View File

@ -0,0 +1,75 @@
/*
* Copyright 2004-2008, François Revol, <revol@free.fr>.
* Distributed under the terms of the MIT License.
*/
#include "CamDebug.h"
#include "CamSensor.h"
#include "addons/sonix/SonixCamDevice.h"
//XXX: unfinished!
static const uint8 sProbeAddressList[] = {
0x01,0x02,0x03,0x04,0x05,0x06,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x10
};
static const uint8 sProbeMatchList[] = {
0x70,0x02,0x12,0x05,0x05,0x06,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x06
};
class PAS106BSensor : public CamSensor {
public:
PAS106BSensor(CamDevice *_camera);
~PAS106BSensor();
status_t Probe();
const char* Name();
virtual bool Use400kHz() const { return true; }; // supports both
virtual bool UseRealIIC() const { return true; };
private:
bool fIsSonix;
};
PAS106BSensor::PAS106BSensor(CamDevice *_camera)
: CamSensor(_camera)
{
fIsSonix = (dynamic_cast<SonixCamDevice *>(_camera) != NULL);
if (fIsSonix) {
fInitStatus = B_OK;
} else {
PRINT((CH ": unknown camera device!" CT));
fInitStatus = ENODEV;
}
}
PAS106BSensor::~PAS106BSensor()
{
}
status_t
PAS106BSensor::Probe()
{
Device()->PowerOnSensor(false);
Device()->PowerOnSensor(true);
if (fIsSonix) {
Device()->WriteReg8(SN9C102_CHIP_CTRL, 0x00); /* power on the sensor, Fsys_clk=12MHz */
Device()->WriteReg8(SN9C102_CLOCK_SEL, 0x17); /* enable sensor, force 24MHz */
}
return ProbeByIICSignature(sProbeAddressList, sProbeMatchList,
sizeof(sProbeMatchList));
}
const char *
PAS106BSensor::Name()
{
return "PixArt Imaging pas106b";
}
B_WEBCAM_DECLARE_SENSOR(PAS106BSensor, pas106b)

View File

@ -9,18 +9,20 @@
#include "CamDebug.h"
#include "addons/sonix/SonixCamDevice.h"
#define ENABLE_GAIN 1
//#define ENABLE_GAIN 1
class TAS5110C1BSensor : public CamSensor {
public:
TAS5110C1BSensor(CamDevice *_camera);
~TAS5110C1BSensor();
virtual status_t Probe();
virtual status_t Setup();
const char *Name();
virtual bool Use400kHz() const { return false; };
virtual bool UseRealIIC() const { return false; };
virtual bool UseRealIIC() const { return true /*false*/; };
virtual uint8 IICReadAddress() const { return 0x00; };
virtual uint8 IICWriteAddress() const { return 0x11; /*0xff;*/ };
virtual uint8 IICWriteAddress() const { return 0x61; /*0x11;*/ /*0xff;*/ };
virtual int MaxWidth() const { return 352; };
virtual int MaxHeight() const { return 288; };
@ -56,43 +58,66 @@ TAS5110C1BSensor::~TAS5110C1BSensor()
}
status_t
TAS5110C1BSensor::Probe()
{
PRINT((CH "()" CT));
return B_OK;
}
status_t
TAS5110C1BSensor::Setup()
{
PRINT((CH "()" CT));
if (InitCheck())
return InitCheck();
Device()->PowerOnSensor(false);
Device()->PowerOnSensor(true);
if (fIsSonix) {
#if 1
Device()->WriteReg8(SN9C102_CHIP_CTRL, 0x01); /* power down the sensor */
Device()->WriteReg8(SN9C102_CHIP_CTRL, 0x44); /* power up the sensor, enable tx, sysclk@24MHz */
Device()->WriteReg8(SN9C102_CHIP_CTRL, 0x04); /* power up the sensor, enable tx, sysclk@24MHz */
Device()->WriteReg8(SN9C102_R_B_GAIN, 0x00); /* red, blue gain = 1+0/8 = 1 */
Device()->WriteReg8(SN9C102_G_GAIN, 0x00); /* green gain = 1+0/8 = 1 */
Device()->WriteReg8(SN9C102_OFFSET, 0x0a); /* 10 pix offset */
Device()->WriteReg8(SN9C102_CLOCK_SEL, 0x60); /* enable sensor clk, and invert it */
Device()->WriteReg8(SN9C102_CLOCK_SEL, 0x60); /* enable sensor clk, and invert it */
Device()->WriteReg8(SN9C102_SYNC_N_SCALE, 0x06); /* no compression, normal curve,
* no scaling, vsync active low,
* v/hsync change at rising edge,
* falling edge of sensor pck */
Device()->WriteReg8(SN9C102_PIX_CLK, 0xfb); /* pixclk = 2 * masterclk, sensor is slave mode */
// some IIC stuff for the sensor
// though it seems more data is sent than told the controller
// this is what the XP driver sends to the ICECAM...
uint8 tmp_7[] = { 0xb0, 0x61, 0x1c, 0xf8, 0x10, 0x00, 0x00, 0x16 };
Device()->WriteReg(SN9C102_I2C_SETUP, tmp_7, 8);
Device()->WriteReg8(SN9C102_PIX_CLK, 0x4b);
uint8 tmp_8[] = { 0xa0, 0x61, 0x1c, 0x0f, 0x10, 0x00, 0x00, 0x16 };
Device()->WriteReg(SN9C102_I2C_SETUP, tmp_8, 8);
#endif
}
if (fIsSonix) {
//sonix_i2c_write_multi(dev, dev->sensor->i2c_wid, 2, 0xc0, 0x80, 0, 0, 0); /* AEC = 0x203 ??? */
Device()->WriteIIC8(0xc0, 0x80); /* AEC = 0x203 ??? */
//Device()->WriteIIC8(0xc0, 0x80); /* AEC = 0x203 ??? */
//Device()->WriteIIC8(0x1c, 0x80); /* AEC = 0x203 ??? */
// set crop
Device()->WriteReg8(SN9C102_H_SIZE, 69);
Device()->WriteReg8(SN9C102_V_SIZE, 9);
Device()->WriteReg8(SN9C102_PIX_CLK, 0xfb);
Device()->WriteReg8(SN9C102_HO_SIZE, 0x14);
Device()->WriteReg8(SN9C102_VO_SIZE, 0x0a);
fVideoFrame.Set(0, 0, 352-1, 288-1);
/* HACK: TEST IMAGE */
//Device()->WriteReg8(SN_CLOCK_SEL, 0x70); /* enable sensor clk, and invert it, test img */
SetVideoFrame(BRect(0, 0, 352-1, 288-1));
}
//Device()->SetScale(1);
return B_OK;

View File

@ -0,0 +1,242 @@
/*
* Copyright 2004-2008, François Revol, <revol@free.fr>.
* Distributed under the terms of the MIT License.
*/
#include <ParameterWeb.h>
#include "CamSensor.h"
#include "CamDebug.h"
#include "addons/sonix/SonixCamDevice.h"
//XXX: unfinished!
#define ENABLE_GAIN 1
class TAS5130D1BSensor : public CamSensor {
public:
TAS5130D1BSensor(CamDevice *_camera);
~TAS5130D1BSensor();
virtual status_t Probe();
virtual status_t Setup();
const char *Name();
virtual bool Use400kHz() const { return false; };
virtual bool UseRealIIC() const { return false; };
virtual uint8 IICReadAddress() const { return 0x00; };
virtual uint8 IICWriteAddress() const { return 0x11; /*0xff;*/ };
virtual int MaxWidth() const { return 640; };
virtual int MaxHeight() const { return 480; };
virtual status_t AcceptVideoFrame(uint32 &width, uint32 &height);
virtual status_t SetVideoFrame(BRect rect);
virtual void AddParameters(BParameterGroup *group, int32 &firstID);
virtual status_t GetParameterValue(int32 id, bigtime_t *last_change, void *value, size_t *size);
virtual status_t SetParameterValue(int32 id, bigtime_t when, const void *value, size_t size);
private:
bool fIsSonix;
float fGain;
};
TAS5130D1BSensor::TAS5130D1BSensor(CamDevice *_camera)
: CamSensor(_camera)
{
fIsSonix = (dynamic_cast<SonixCamDevice *>(_camera) != NULL);
if (fIsSonix) {
fInitStatus = B_OK;
} else {
PRINT((CH ": unknown camera device!" CT));
fInitStatus = ENODEV;
}
fGain = (float)0x40; // default
}
TAS5130D1BSensor::~TAS5130D1BSensor()
{
}
status_t
TAS5130D1BSensor::Probe()
{
PRINT((CH "()" CT));
return B_OK;
}
status_t
TAS5130D1BSensor::Setup()
{
PRINT((CH "()" CT));
if (InitCheck())
return InitCheck();
/*
Device()->PowerOnSensor(false);
Device()->PowerOnSensor(true);
*/
if (fIsSonix) {
// linux driver seems to do this, but doesn't say why
Device()->WriteReg8(SN9C102_CHIP_CTRL, 0x01); /* power down the sensor */
Device()->WriteReg8(SN9C102_CLOCK_SEL, 0x20); /* enable sensor clk */
Device()->WriteReg8(SN9C102_CHIP_CTRL, 0x04); /* power up the sensor, enable tx, sysclk@12MHz */
Device()->WriteReg8(SN9C102_R_B_GAIN, 0x01); /* red gain = 1+0/8 = 1, red gain = 1+1/8 !!? */
Device()->WriteReg8(SN9C102_G_GAIN, 0x00); /* green gain = 1+0/8 = 1 */
Device()->WriteReg8(SN9C102_OFFSET, 0x0a); /* 0 pix offset */
Device()->WriteReg8(SN9C102_CLOCK_SEL, 0x60); /* enable sensor clk, and invert it */
Device()->WriteReg8(SN9C102_SYNC_N_SCALE, 0x06); /* no compression, normal curve,
* no scaling, vsync active low,
* v/hsync change at rising edge,
* raising edge of sensor pck */
Device()->WriteReg8(SN9C102_PIX_CLK, 0xf3); /* pixclk = masterclk, sensor is slave mode */
}
if (fIsSonix) {
//sonix_i2c_write_multi(dev, dev->sensor->i2c_wid, 2, 0xc0, 0x80, 0, 0, 0); /* AEC = 0x203 ??? */
#if 0
Device()->WriteIIC8(0xc0, 0x80); /* AEC = 0x203 ??? */
#endif
#if 1
Device()->WriteIIC8(0x20, 0xf6 - 0xd0); /* GAIN */
Device()->WriteIIC8(0x40, 0x47 - 0x40); /* Exposure */
// set crop
Device()->WriteReg8(SN9C102_H_SIZE, 104);
Device()->WriteReg8(SN9C102_V_SIZE, 12);
SetVideoFrame(BRect(0, 0, 320-1, 240-1));
#endif
#if 0
//XXX
Device()->WriteIIC8(0xc0, 0x80); /* AEC = 0x203 ??? */
Device()->WriteReg8(SN9C102_H_SIZE, 69);
Device()->WriteReg8(SN9C102_V_SIZE, 9);
SetVideoFrame(BRect(0, 0, 352-1, 288-1));
#endif
}
//Device()->SetScale(1);
return B_OK;
}
const char *
TAS5130D1BSensor::Name()
{
return "TASC tas5130d1b";
}
status_t
TAS5130D1BSensor::AcceptVideoFrame(uint32 &width, uint32 &height)
{
// default sanity checks
status_t err = CamSensor::AcceptVideoFrame(width, height);
if (err < B_OK)
return err;
// must be modulo 16
width /= 16;
width *= 16;
height /= 16;
height *= 16;
return B_OK;
}
status_t
TAS5130D1BSensor::SetVideoFrame(BRect rect)
{
if (fIsSonix) {
// set crop
Device()->WriteReg8(SN9C102_H_START, /*rect.left + */104);
Device()->WriteReg8(SN9C102_V_START, /*rect.top + */12);
Device()->WriteReg8(SN9C102_PIX_CLK, 0xfb);
Device()->WriteReg8(SN9C102_HO_SIZE, 0x14);
Device()->WriteReg8(SN9C102_VO_SIZE, 0x0a);
#if 0
Device()->WriteReg8(SN9C102_H_START, /*rect.left + */104);
Device()->WriteReg8(SN9C102_V_START, /*rect.top + */12);
Device()->WriteReg8(SN9C102_PIX_CLK, 0xf3);
Device()->WriteReg8(SN9C102_HO_SIZE, 0x1f);
Device()->WriteReg8(SN9C102_VO_SIZE, 0x1a);
#endif
fVideoFrame = rect;
/* HACK: TEST IMAGE */
//Device()->WriteReg8(SN9C102_CLOCK_SEL, 0x70); /* enable sensor clk, and invert it, test img */
}
return B_OK;
}
void
TAS5130D1BSensor::AddParameters(BParameterGroup *group, int32 &index)
{
BContinuousParameter *p;
CamSensor::AddParameters(group, index);
#ifdef ENABLE_GAIN
// NON-FUNCTIONAL
BParameterGroup *g = group->MakeGroup("global gain");
p = g->MakeContinuousParameter(index++,
B_MEDIA_RAW_VIDEO, "global gain",
B_GAIN, "", (float)0x00, (float)0xf6, (float)1);
#endif
}
status_t
TAS5130D1BSensor::GetParameterValue(int32 id, bigtime_t *last_change, void *value, size_t *size)
{
#ifdef ENABLE_GAIN
if (id == fFirstParameterID) {
*size = sizeof(float);
*((float *)value) = fGain;
*last_change = fLastParameterChanges;
}
#endif
return B_BAD_VALUE;
}
status_t
TAS5130D1BSensor::SetParameterValue(int32 id, bigtime_t when, const void *value, size_t size)
{
#ifdef ENABLE_GAIN
if (id == fFirstParameterID) {
if (!value || (size != sizeof(float)))
return B_BAD_VALUE;
if (*(float *)value == fGain)
return B_OK;
fGain = *(float *)value;
fLastParameterChanges = when;
PRINT((CH ": gain: %f" CT, fGain));
if (fIsSonix) {
// some drivers do:
//Device()->WriteIIC8(0x20, (uint8)0xf6 - (uint8)fGain);
// but it doesn't seem to work
// works, not sure why yet, XXX check datasheet for AEG/AEC
uint8 buf[2] = { 0x20, 0x70 };
buf[1] = (uint8)0xff - (uint8)fGain;
Device()->WriteIIC(0x02, buf, 2);
}
return B_OK;
}
#endif
return B_BAD_VALUE;
}
B_WEBCAM_DECLARE_SENSOR(TAS5130D1BSensor, tas5130d1b)