1/* 2 * Copyright 2004-2008, Fran��ois Revol, <revol@free.fr>. 3 * Distributed under the terms of the MIT License. 4 */ 5 6#include "NW80xCamDevice.h" 7#include "CamDebug.h" 8#include "CamSensor.h" 9 10// reference drivers: 11// http://nw802.cvs.sourceforge.net 12// http://nw802.cvs.sourceforge.net/nw802/nw802-2.4/ 13// http://www.medias.ne.jp/~takam/bsd/NetBSD.html#nw802 14// https://dev.openwrt.org/attachment/ticket/2319/nw802-patch.txt 15// win binary driver template, readme has interesting info: 16// http://www.bulgar-bg.com/Downloads/drivers/PCAMDriver/ 17// http://www.bulgar-bg.com/Downloads/drivers/PCAMDriver/Readme.txt 18 19const usb_webcam_support_descriptor kSupportedDevices[] = { 20{{ 0, 0, 0, 0x046d, 0xd001 }, "Logitech", "QuickCam Pro", "??" }, // Alan's 21// other IDs according to nw802 linux driver: 22{{ 0, 0, 0, 0x052b, 0xd001 }, "Ezonics", "EZCam Pro", "??" }, 23{{ 0, 0, 0, 0x055f, 0xd001 }, "Mustek"/*"PCLine"*/, "WCam 300"/*"PCL-W300"*/, "??" }, 24{{ 0, 0, 0, 0x06a5, 0xd001 }, "Divio", "NW802", "??" }, 25{{ 0, 0, 0, 0x06a5, 0x0000 }, "Divio", "NW800", "??" }, 26{{ 0, 0, 0, 0, 0}, NULL, NULL, NULL } 27}; 28 29 30// TODO: Complete implementation! 31 32// datasheets: (scarce) 33// http://www.digchip.com/datasheets/parts/datasheet/132/NW800.php 34// http://www.digchip.com/datasheets/parts/datasheet/132/NW802.php 35// http://web.archive.org/web/*/divio.com/* 36// http://web.archive.org/web/20020217173519/divio.com/NW802.html 37// 38// supported sensors: 39// Sensor Model # Data Width Voltage Timing 40// Conexant CN0352 10 bits 3.3 V Master 41// Elecvision EVS110K 8 bits 3.3 V Slave 42// HP (Agilent) HDC1000 10 bits 3.3 V Master 43// Hyundai HB7121B 8 bits 3.3 V Master 44// Pixart PAS006AC 9 bits 3.3 V Master 45// TASC TAS5110A 9 bits 3.8 V Slave 46// 47// http://www.wifi.com.ar/english/doc/webcam/ov511cameras.html says: 48// 06a5 (Divio) d800 Etoms ET31X110 (A.K.A Divio NW800) 49 50NW80xCamDevice::NW80xCamDevice(CamDeviceAddon &_addon, BUSBDevice* _device) 51 :CamDevice(_addon, _device) 52{ 53 status_t err; 54 55 // linux seems to infer this sets I2C controller to 8 or 16 bit mode... 56 // sensors will set to the mode they want when probing 57 SetIICBitsMode(8); 58 err = ProbeSensor(); 59 if (err < B_OK) { 60 // reset I2C mode to 8 bit as linux driver does 61 SetIICBitsMode(8); 62 // not much we can do anyway 63 } 64 65 fInitStatus = B_OK; 66} 67 68 69NW80xCamDevice::~NW80xCamDevice() 70{ 71 72} 73 74 75bool 76NW80xCamDevice::SupportsBulk() 77{ 78 return true; 79} 80 81 82bool 83NW80xCamDevice::SupportsIsochronous() 84{ 85 return true; 86} 87 88 89status_t 90NW80xCamDevice::StartTransfer() 91{ 92 SetScale(1); 93 if (Sensor()) 94 SetVideoFrame(BRect(0, 0, Sensor()->MaxWidth()-1, Sensor()->MaxHeight()-1)); 95 96 //SetVideoFrame(BRect(0, 0, 320-1, 240-1)); 97 98DumpRegs(); 99#if 0 100 status_t err; 101 uint8 r; 102 103 err = ReadReg(SN9C102_CHIP_CTRL, &r, 1, true); 104 if (err < 0) 105 return err; 106 r |= 0x04; 107 err = WriteReg8(SN9C102_CHIP_CTRL, r); 108 if (err < 0) 109 return err; 110#endif 111 return CamDevice::StartTransfer(); 112} 113 114 115status_t 116NW80xCamDevice::StopTransfer() 117{ 118 status_t err; 119 DumpRegs(); 120 err = CamDevice::StopTransfer(); 121#if 0 122 uint8 r; 123 124// if (err < 0) 125// return err; 126 err = ReadReg(SN9C102_CHIP_CTRL, &r, 1, true); 127 if (err < 0) 128 return err; 129 r &= ~0x04; 130 err = WriteReg8(SN9C102_CHIP_CTRL, r); 131 if (err < 0) 132 return err; 133#endif 134 return err; 135} 136 137 138ssize_t 139NW80xCamDevice::WriteReg(uint16 address, uint8 *data, size_t count) 140{ 141 PRINT((CH "(%u, @%p, %" B_PRIuSIZE ")" CT, address, data, count)); 142 return SendCommand(USB_REQTYPE_DEVICE_OUT, 0x04, address, 0, count, data); 143} 144 145 146ssize_t 147NW80xCamDevice::ReadReg(uint16 address, uint8 *data, size_t count, bool cached) 148{ 149 PRINT((CH "(%u, @%p, %" B_PRIuSIZE ", %d)" CT, address, data, count, 150 cached)); 151 memset(data, 0xaa, count); // linux drivers do that without explaining why !? 152 return SendCommand(USB_REQTYPE_DEVICE_IN, 0x04, address, 0, count, data); 153} 154 155 156status_t 157NW80xCamDevice::GetStatusIIC() 158{ 159 status_t err = B_ERROR; 160 uint8 status = 0; 161 // TODO: WRITEME 162 //dprintf(ID "i2c_status: error 0x%08lx, status = %02x\n", err, status); 163 if (err < 0) 164 return err; 165 return (status&0x08)?EIO:0; 166} 167 168 169status_t 170NW80xCamDevice::WaitReadyIIC() 171{ 172 // TODO: WRITEME 173 return EBUSY; 174} 175 176 177ssize_t 178NW80xCamDevice::WriteIIC(uint8 address, uint8 *data, size_t count) 179{ 180 size_t i; 181 uint8 buffer[0x23]; 182 if (count > 16) 183 return EINVAL; 184 memset(buffer, 0, sizeof(buffer)); 185 buffer[0x20] = Sensor() ? Sensor()->IICWriteAddress() : 0; 186 buffer[0x21] = count - 1; 187 buffer[0x22] = 0x01; 188 for (i = 0; i < count; i++) { 189 buffer[i] = address + i; 190 buffer[i+16] = data[i]; 191 } 192 return SendCommand(USB_REQTYPE_DEVICE_OUT, 0x04, STV_I2C_WRITE, 0, 0x23, buffer); 193} 194 195 196ssize_t 197NW80xCamDevice::ReadIIC(uint8 address, uint8 *data) 198{ 199 return ReadIIC(address, data); 200} 201 202 203ssize_t 204NW80xCamDevice::ReadIIC8(uint8 address, uint8 *data) 205{ 206 status_t err; 207 uint8 buffer[0x23]; 208 memset(buffer, 0, sizeof(buffer)); 209 buffer[0x20] = Sensor() ? Sensor()->IICReadAddress() : 0; 210 buffer[0x21] = 1 - 1; 211 buffer[0x22] = 0x03; 212 buffer[0] = address; 213 err = SendCommand(USB_REQTYPE_DEVICE_OUT, 0x04, STV_I2C_WRITE, 0, 0x23, buffer); 214 PRINT((CH ": SendCommand: %s" CT, strerror(err))); 215 if (err < B_OK) 216 return err; 217 218 buffer[0] = 0xaa; 219 err = SendCommand(USB_REQTYPE_DEVICE_IN, 0x04, STV_I2C_READ, 0, 0x1, buffer); 220 PRINT((CH ": SendCommand: %s" CT, strerror(err))); 221 if (err < B_OK) 222 return err; 223 224 *data = buffer[0]; 225 PRINT((CH ": 0x%02x" CT, *data)); 226 return 1; 227} 228 229 230ssize_t 231NW80xCamDevice::ReadIIC16(uint8 address, uint16 *data) 232{ 233 status_t err; 234 uint8 buffer[0x23]; 235 memset(buffer, 0, sizeof(buffer)); 236 buffer[0x20] = Sensor() ? Sensor()->IICReadAddress() : 0; 237 buffer[0x21] = 1 - 1; 238 buffer[0x22] = 0x03; 239 buffer[0] = address; 240 err = SendCommand(USB_REQTYPE_DEVICE_OUT, 0x04, STV_I2C_WRITE, 0, 0x23, buffer); 241 if (err < B_OK) 242 return err; 243 244 buffer[0] = 0xaa; 245 buffer[1] = 0xaa; 246 err = SendCommand(USB_REQTYPE_DEVICE_IN, 0x04, STV_I2C_READ, 0, 0x2, buffer); 247 PRINT((CH ": SendCommand: %s" CT, strerror(err))); 248 if (err < B_OK) 249 return err; 250 251 if (fChipIsBigEndian) 252 *data = B_HOST_TO_BENDIAN_INT16(*(uint16 *)(&buffer[0])); 253 else 254 *data = B_HOST_TO_LENDIAN_INT16(*(uint16 *)(&buffer[0])); 255 PRINT((CH ": 0x%04x" CT, *data)); 256 return 2; 257} 258 259 260status_t 261NW80xCamDevice::SetIICBitsMode(size_t bits) 262{ 263 switch (bits) { 264 case 8: 265 WriteReg8(STV_REG23, 0); 266 break; 267 case 16: 268 WriteReg8(STV_REG23, 1); 269 break; 270 default: 271 return EINVAL; 272 } 273 return B_OK; 274} 275 276 277status_t 278NW80xCamDevice::SendCommand(uint8 dir, uint8 request, uint16 value, 279 uint16 index, uint16 length, void* data) 280{ 281 size_t ret; 282 if (!GetDevice()) 283 return ENODEV; 284 if (length > GetDevice()->MaxEndpoint0PacketSize()) 285 return EINVAL; 286 ret = GetDevice()->ControlTransfer( 287 USB_REQTYPE_VENDOR | dir, 288 request, value, index, length, data); 289 return ret; 290} 291 292 293NW80xCamDeviceAddon::NW80xCamDeviceAddon(WebCamMediaAddOn* webcam) 294 : CamDeviceAddon(webcam) 295{ 296 SetSupportedDevices(kSupportedDevices); 297} 298 299 300NW80xCamDeviceAddon::~NW80xCamDeviceAddon() 301{ 302} 303 304 305const char * 306NW80xCamDeviceAddon::BrandName() 307{ 308 return "NW80x-based"; 309} 310 311 312NW80xCamDevice * 313NW80xCamDeviceAddon::Instantiate(CamRoster &roster, BUSBDevice *from) 314{ 315 return new NW80xCamDevice(*this, from); 316} 317 318 319extern "C" status_t 320B_WEBCAM_MKINTFUNC(nw80xcam) 321(WebCamMediaAddOn* webcam, CamDeviceAddon **addon) 322{ 323 *addon = new NW80xCamDeviceAddon(webcam); 324 return B_OK; 325} 326