- 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:
@@ -524,7 +524,7 @@ CamDevice::DataPumpThread()
|
|||||||
len = fBulkIn->BulkTransfer(fBuffer, fBufferLen);
|
len = fBulkIn->BulkTransfer(fBuffer, fBufferLen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PRINT((CH ": got %ld bytes" CT, len));
|
//PRINT((CH ": got %ld bytes" CT, len));
|
||||||
#ifdef DEBUG_WRITE_DUMP
|
#ifdef DEBUG_WRITE_DUMP
|
||||||
write(fDumpFD, fBuffer, len);
|
write(fDumpFD, fBuffer, len);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -6,10 +6,11 @@ SetSubDirSupportedPlatformsBeOSCompatible ;
|
|||||||
if $(TARGET_PLATFORM_HAIKU_COMPATIBLE) {
|
if $(TARGET_PLATFORM_HAIKU_COMPATIBLE) {
|
||||||
usbKitLibraryName = libdevice.so ;
|
usbKitLibraryName = libdevice.so ;
|
||||||
} else {
|
} else {
|
||||||
# usbKitLibraryName = usb ;
|
# usbKitLibraryName = USBKit.a ;
|
||||||
usbKitLibraryName = USBKit.a ;
|
# UsePublicHeaders [ FDirName drivers ] ;
|
||||||
UsePublicHeaders [ FDirName drivers ] ;
|
# UsePublicHeaders [ FDirName device ] ;
|
||||||
UsePublicHeaders [ FDirName device ] ;
|
# use -lusb on ZETA
|
||||||
|
usbKitLibraryName = usb ;
|
||||||
}
|
}
|
||||||
|
|
||||||
# source directories
|
# source directories
|
||||||
@@ -38,7 +39,8 @@ csTransformsSources = Bayer.cpp ;
|
|||||||
|
|
||||||
## sensors sources
|
## sensors sources
|
||||||
local sensorsSources ;
|
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.
|
## 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...
|
# but it doesn't seem to work for some reason...
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
const usb_webcam_support_descriptor kSupportedDevices[] = {
|
const usb_webcam_support_descriptor kSupportedDevices[] = {
|
||||||
{{ 0, 0, 0, 0x0c45, 0x6005 }, "Sonix", "Sonix", "tas5110c1b" }, // mine
|
{{ 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, 0x6009 }, "Trust", "spacec@m 120", NULL },
|
||||||
{{ 0, 0, 0, 0x0c45, 0x600d }, "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;
|
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()) {
|
if (Sensor()) {
|
||||||
PRINT((CH ": CamSensor: %s" CT, Sensor()->Name()));
|
PRINT((CH ": CamSensor: %s" CT, Sensor()->Name()));
|
||||||
fInitStatus = Sensor()->Setup();
|
fInitStatus = Sensor()->Setup();
|
||||||
|
|
||||||
fVideoFrame = BRect(0, 0, Sensor()->MaxWidth()-1, Sensor()->MaxHeight()-1);
|
fVideoFrame = BRect(0, 0, Sensor()->MaxWidth()-1, Sensor()->MaxHeight()-1);
|
||||||
// SetVideoFrame(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));
|
// 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
|
ssize_t
|
||||||
SonixCamDevice::WriteReg(uint16 address, uint8 *data, size_t count)
|
SonixCamDevice::WriteReg(uint16 address, uint8 *data, size_t count)
|
||||||
{
|
{
|
||||||
PRINT((CH "(%u, @%p, %u)" CT, address, data, count));
|
PRINT((CH "(%u, @%p, %u)" CT, address, data, count));
|
||||||
|
status_t err;
|
||||||
if (address + count > SN9C102_REG_COUNT) {
|
if (address + count > SN9C102_REG_COUNT) {
|
||||||
PRINT((CH ": Invalid register range [%u;%u]" CT, address, address+count));
|
PRINT((CH ": Invalid register range [%u;%u]" CT, address, address+count));
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
memcpy(&fCachedRegs[address], data, count);
|
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)
|
SonixCamDevice::ReadReg(uint16 address, uint8 *data, size_t count, bool cached)
|
||||||
{
|
{
|
||||||
PRINT((CH "(%u, @%p, %u, %d)" CT, address, data, count, cached));
|
PRINT((CH "(%u, @%p, %u, %d)" CT, address, data, count, cached));
|
||||||
|
status_t err;
|
||||||
if (address + count > SN9C102_REG_COUNT) {
|
if (address + count > SN9C102_REG_COUNT) {
|
||||||
PRINT((CH ": Invalid register range [%u;%u]" CT, address, address+count));
|
PRINT((CH ": Invalid register range [%u;%u]" CT, address, address+count));
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@@ -230,7 +316,10 @@ SonixCamDevice::ReadReg(uint16 address, uint8 *data, size_t count, bool cached)
|
|||||||
memcpy(data, &fCachedRegs[address], count);
|
memcpy(data, &fCachedRegs[address], count);
|
||||||
return 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;
|
status_t err;
|
||||||
uint8 buffer[8];
|
uint8 buffer[8];
|
||||||
|
PRINT((CH "(%u, @%p, %u)" CT, address, data, count));
|
||||||
|
|
||||||
if (!Sensor())
|
if (!Sensor())
|
||||||
return B_NO_INIT;
|
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);
|
//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;
|
buffer[2] = address;
|
||||||
memset(&buffer[3], 0, 5);
|
memset(&buffer[3], 0, 5);
|
||||||
memcpy(&buffer[3], data, count-1);
|
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++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
PRINT(("[%d] = %02x\n", i, buffer[i]));
|
PRINT(("[%d] = %02x\n", i, buffer[i]));
|
||||||
}
|
}
|
||||||
@@ -311,6 +402,8 @@ SonixCamDevice::ReadIIC(uint8 address, uint8 *data)
|
|||||||
{
|
{
|
||||||
status_t err, lasterr = B_OK;
|
status_t err, lasterr = B_OK;
|
||||||
uint8 buffer[8];
|
uint8 buffer[8];
|
||||||
|
PRINT((CH "(%u, @%p)" CT, address, data));
|
||||||
|
|
||||||
if (!Sensor())
|
if (!Sensor())
|
||||||
return B_NO_INIT;
|
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);
|
//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 */
|
buffer[7] = 0x10; /* absolutely no idea why V4L2 driver use that value */
|
||||||
err = WriteReg(SN9C102_I2C_SETUP, buffer, 8);
|
err = WriteReg(SN9C102_I2C_SETUP, buffer, 8);
|
||||||
//dprintf(ID "sonix_i2c_write_multi: set_regs error 0x%08lx\n", err);
|
//dprintf(ID "sonix_i2c_write_multi: set_regs error 0x%08lx\n", err);
|
||||||
if (err) return err;
|
if (err < 8) return EIO;
|
||||||
err = WaitReadyIIC();
|
err = WaitReadyIIC();
|
||||||
//dprintf(ID "sonix_i2c_write_multi: sonix_i2c_wait_ready error 0x%08lx\n", err);
|
//dprintf(ID "sonix_i2c_write_multi: sonix_i2c_wait_ready error 0x%08lx\n", err);
|
||||||
//if (err) return 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 */
|
buffer[7] = 0x10; /* absolutely no idea why V4L2 driver use that value */
|
||||||
err = WriteReg(SN9C102_I2C_SETUP, buffer, 8);
|
err = WriteReg(SN9C102_I2C_SETUP, buffer, 8);
|
||||||
//dprintf(ID "sonix_i2c_write_multi: set_regs error 0x%08lx\n", err);
|
//dprintf(ID "sonix_i2c_write_multi: set_regs error 0x%08lx\n", err);
|
||||||
if (err) return err;
|
if (err < 8) return EIO;
|
||||||
err = WaitReadyIIC();
|
err = WaitReadyIIC();
|
||||||
//dprintf(ID "sonix_i2c_write_multi: sonix_i2c_wait_ready error 0x%08lx\n", err);
|
//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);
|
err = ReadReg(SN9C102_I2C_DATA0, buffer, 5);
|
||||||
if (err) lasterr = err;
|
if (err < 5) return EIO;
|
||||||
|
|
||||||
err = GetStatusIIC();
|
err = GetStatusIIC();
|
||||||
//dprintf(ID "sonix_i2c_write_multi: sonix_i2c_status error 0x%08lx\n", err);
|
//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");
|
//dprintf(ID "sonix_i2c_write_multi: succeeded\n");
|
||||||
if (lasterr) return err;
|
if (lasterr) return err;
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,9 @@ class SonixCamDevice : public CamDevice
|
|||||||
virtual status_t StartTransfer();
|
virtual status_t StartTransfer();
|
||||||
virtual status_t StopTransfer();
|
virtual status_t StopTransfer();
|
||||||
|
|
||||||
|
// sensor chip handling
|
||||||
|
virtual status_t PowerOnSensor(bool on);
|
||||||
|
|
||||||
// generic register-like access
|
// generic register-like access
|
||||||
virtual ssize_t WriteReg(uint16 address, uint8 *data, size_t count=1);
|
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);
|
virtual ssize_t ReadReg(uint16 address, uint8 *data, size_t count=1, bool cached=false);
|
||||||
|
|||||||
@@ -5,33 +5,53 @@
|
|||||||
|
|
||||||
#include "CamSensor.h"
|
#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 {
|
class HV7131E1Sensor : public CamSensor {
|
||||||
public:
|
public:
|
||||||
HV7131E1Sensor(CamDevice *_camera);
|
HV7131E1Sensor(CamDevice *_camera);
|
||||||
~HV7131E1Sensor();
|
~HV7131E1Sensor();
|
||||||
|
status_t Probe();
|
||||||
const char* Name();
|
const char* Name();
|
||||||
|
|
||||||
|
//XXX not sure
|
||||||
|
virtual bool Use400kHz() const { return false; };
|
||||||
|
virtual bool UseRealIIC() const { return false; };
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
HV7131E1Sensor::HV7131E1Sensor(CamDevice *_camera)
|
HV7131E1Sensor::HV7131E1Sensor(CamDevice *_camera)
|
||||||
: CamSensor(_camera)
|
: CamSensor(_camera)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
HV7131E1Sensor::~HV7131E1Sensor()
|
HV7131E1Sensor::~HV7131E1Sensor()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
status_t
|
||||||
|
HV7131E1Sensor::Probe()
|
||||||
|
{
|
||||||
|
return ProbeByIICSignature(sProbeAddressList, sProbeMatchList,
|
||||||
|
sizeof(sProbeMatchList));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
HV7131E1Sensor::Name()
|
HV7131E1Sensor::Name()
|
||||||
{
|
{
|
||||||
return "Hynix hv7131e1";
|
return "Hynix hv7131e1";
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
B_WEBCAM_DECLARE_SENSOR(HV7131E1Sensor, hv7131e1)
|
B_WEBCAM_DECLARE_SENSOR(HV7131E1Sensor, hv7131e1)
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
@@ -9,18 +9,20 @@
|
|||||||
#include "CamDebug.h"
|
#include "CamDebug.h"
|
||||||
#include "addons/sonix/SonixCamDevice.h"
|
#include "addons/sonix/SonixCamDevice.h"
|
||||||
|
|
||||||
#define ENABLE_GAIN 1
|
//#define ENABLE_GAIN 1
|
||||||
|
|
||||||
|
|
||||||
class TAS5110C1BSensor : public CamSensor {
|
class TAS5110C1BSensor : public CamSensor {
|
||||||
public:
|
public:
|
||||||
TAS5110C1BSensor(CamDevice *_camera);
|
TAS5110C1BSensor(CamDevice *_camera);
|
||||||
~TAS5110C1BSensor();
|
~TAS5110C1BSensor();
|
||||||
|
virtual status_t Probe();
|
||||||
virtual status_t Setup();
|
virtual status_t Setup();
|
||||||
const char *Name();
|
const char *Name();
|
||||||
virtual bool Use400kHz() const { return false; };
|
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 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 MaxWidth() const { return 352; };
|
||||||
virtual int MaxHeight() const { return 288; };
|
virtual int MaxHeight() const { return 288; };
|
||||||
@@ -56,43 +58,66 @@ TAS5110C1BSensor::~TAS5110C1BSensor()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
TAS5110C1BSensor::Probe()
|
||||||
|
{
|
||||||
|
PRINT((CH "()" CT));
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
TAS5110C1BSensor::Setup()
|
TAS5110C1BSensor::Setup()
|
||||||
{
|
{
|
||||||
PRINT((CH "()" CT));
|
PRINT((CH "()" CT));
|
||||||
if (InitCheck())
|
if (InitCheck())
|
||||||
return InitCheck();
|
return InitCheck();
|
||||||
|
Device()->PowerOnSensor(false);
|
||||||
|
Device()->PowerOnSensor(true);
|
||||||
if (fIsSonix) {
|
if (fIsSonix) {
|
||||||
|
#if 1
|
||||||
Device()->WriteReg8(SN9C102_CHIP_CTRL, 0x01); /* power down the sensor */
|
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, 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_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_G_GAIN, 0x00); /* green gain = 1+0/8 = 1 */
|
||||||
Device()->WriteReg8(SN9C102_OFFSET, 0x0a); /* 10 pix offset */
|
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_CLOCK_SEL, 0x60); /* enable sensor clk, and invert it */
|
||||||
Device()->WriteReg8(SN9C102_SYNC_N_SCALE, 0x06); /* no compression, normal curve,
|
Device()->WriteReg8(SN9C102_SYNC_N_SCALE, 0x06); /* no compression, normal curve,
|
||||||
* no scaling, vsync active low,
|
* no scaling, vsync active low,
|
||||||
* v/hsync change at rising edge,
|
* v/hsync change at rising edge,
|
||||||
* falling edge of sensor pck */
|
* falling edge of sensor pck */
|
||||||
Device()->WriteReg8(SN9C102_PIX_CLK, 0xfb); /* pixclk = 2 * masterclk, sensor is slave mode */
|
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) {
|
if (fIsSonix) {
|
||||||
//sonix_i2c_write_multi(dev, dev->sensor->i2c_wid, 2, 0xc0, 0x80, 0, 0, 0); /* AEC = 0x203 ??? */
|
//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
|
// set crop
|
||||||
Device()->WriteReg8(SN9C102_H_SIZE, 69);
|
Device()->WriteReg8(SN9C102_H_SIZE, 69);
|
||||||
Device()->WriteReg8(SN9C102_V_SIZE, 9);
|
Device()->WriteReg8(SN9C102_V_SIZE, 9);
|
||||||
Device()->WriteReg8(SN9C102_PIX_CLK, 0xfb);
|
SetVideoFrame(BRect(0, 0, 352-1, 288-1));
|
||||||
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 */
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Device()->SetScale(1);
|
//Device()->SetScale(1);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
Reference in New Issue
Block a user