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 19 const 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 #warning TODO! 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 50 NW80xCamDevice::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 69 NW80xCamDevice::~NW80xCamDevice() 70 { 71 72 } 73 74 75 bool 76 NW80xCamDevice::SupportsBulk() 77 { 78 return true; 79 } 80 81 82 bool 83 NW80xCamDevice::SupportsIsochronous() 84 { 85 return true; 86 } 87 88 89 status_t 90 NW80xCamDevice::StartTransfer() 91 { 92 status_t err; 93 uint8 r; 94 95 SetScale(1); 96 if (Sensor()) 97 SetVideoFrame(BRect(0, 0, Sensor()->MaxWidth()-1, Sensor()->MaxHeight()-1)); 98 99 //SetVideoFrame(BRect(0, 0, 320-1, 240-1)); 100 101 DumpRegs(); 102 #if 0 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 115 status_t 116 NW80xCamDevice::StopTransfer() 117 { 118 status_t err; 119 uint8 r; 120 121 DumpRegs(); 122 err = CamDevice::StopTransfer(); 123 #if 0 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 138 ssize_t 139 NW80xCamDevice::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 146 ssize_t 147 NW80xCamDevice::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 156 status_t 157 NW80xCamDevice::GetStatusIIC() 158 { 159 status_t err = B_ERROR; 160 uint8 status = 0; 161 #warning 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 169 status_t 170 NW80xCamDevice::WaitReadyIIC() 171 { 172 status_t err; 173 #warning WRITEME 174 return EBUSY; 175 } 176 177 178 ssize_t 179 NW80xCamDevice::WriteIIC(uint8 address, uint8 *data, size_t count) 180 { 181 status_t err; 182 int i; 183 uint8 buffer[0x23]; 184 if (count > 16) 185 return EINVAL; 186 memset(buffer, 0, sizeof(buffer)); 187 buffer[0x20] = Sensor() ? Sensor()->IICWriteAddress() : 0; 188 buffer[0x21] = count - 1; 189 buffer[0x22] = 0x01; 190 for (i = 0; i < count; i++) { 191 buffer[i] = address + i; 192 buffer[i+16] = data[i]; 193 } 194 return SendCommand(USB_REQTYPE_DEVICE_OUT, 0x04, STV_I2C_WRITE, 0, 0x23, buffer); 195 } 196 197 198 ssize_t 199 NW80xCamDevice::ReadIIC(uint8 address, uint8 *data) 200 { 201 return ReadIIC(address, data); 202 } 203 204 205 ssize_t 206 NW80xCamDevice::ReadIIC8(uint8 address, uint8 *data) 207 { 208 status_t err; 209 int i; 210 uint8 buffer[0x23]; 211 memset(buffer, 0, sizeof(buffer)); 212 buffer[0x20] = Sensor() ? Sensor()->IICReadAddress() : 0; 213 buffer[0x21] = 1 - 1; 214 buffer[0x22] = 0x03; 215 buffer[0] = address; 216 err = SendCommand(USB_REQTYPE_DEVICE_OUT, 0x04, STV_I2C_WRITE, 0, 0x23, buffer); 217 PRINT((CH ": SendCommand: %s" CT, strerror(err))); 218 if (err < B_OK) 219 return err; 220 221 buffer[0] = 0xaa; 222 err = SendCommand(USB_REQTYPE_DEVICE_IN, 0x04, STV_I2C_READ, 0, 0x1, buffer); 223 PRINT((CH ": SendCommand: %s" CT, strerror(err))); 224 if (err < B_OK) 225 return err; 226 227 *data = buffer[0]; 228 PRINT((CH ": 0x%02x" CT, *data)); 229 return 1; 230 } 231 232 233 ssize_t 234 NW80xCamDevice::ReadIIC16(uint8 address, uint16 *data) 235 { 236 status_t err; 237 int i; 238 uint8 buffer[0x23]; 239 memset(buffer, 0, sizeof(buffer)); 240 buffer[0x20] = Sensor() ? Sensor()->IICReadAddress() : 0; 241 buffer[0x21] = 1 - 1; 242 buffer[0x22] = 0x03; 243 buffer[0] = address; 244 err = SendCommand(USB_REQTYPE_DEVICE_OUT, 0x04, STV_I2C_WRITE, 0, 0x23, buffer); 245 if (err < B_OK) 246 return err; 247 248 buffer[0] = 0xaa; 249 buffer[1] = 0xaa; 250 err = SendCommand(USB_REQTYPE_DEVICE_IN, 0x04, STV_I2C_READ, 0, 0x2, buffer); 251 PRINT((CH ": SendCommand: %s" CT, strerror(err))); 252 if (err < B_OK) 253 return err; 254 255 if (fChipIsBigEndian) 256 *data = B_HOST_TO_BENDIAN_INT16(*(uint16 *)(&buffer[0])); 257 else 258 *data = B_HOST_TO_LENDIAN_INT16(*(uint16 *)(&buffer[0])); 259 PRINT((CH ": 0x%04x" CT, *data)); 260 return 2; 261 } 262 263 264 status_t 265 NW80xCamDevice::SetIICBitsMode(size_t bits) 266 { 267 switch (bits) { 268 case 8: 269 WriteReg8(STV_REG23, 0); 270 break; 271 case 16: 272 WriteReg8(STV_REG23, 1); 273 break; 274 default: 275 return EINVAL; 276 } 277 return B_OK; 278 } 279 280 281 status_t 282 NW80xCamDevice::SendCommand(uint8 dir, uint8 request, uint16 value, 283 uint16 index, uint16 length, void* data) 284 { 285 size_t ret; 286 if (!GetDevice()) 287 return ENODEV; 288 if (length > GetDevice()->MaxEndpoint0PacketSize()) 289 return EINVAL; 290 ret = GetDevice()->ControlTransfer( 291 USB_REQTYPE_VENDOR | dir, 292 request, value, index, length, data); 293 return ret; 294 } 295 296 297 NW80xCamDeviceAddon::NW80xCamDeviceAddon(WebCamMediaAddOn* webcam) 298 : CamDeviceAddon(webcam) 299 { 300 SetSupportedDevices(kSupportedDevices); 301 } 302 303 304 NW80xCamDeviceAddon::~NW80xCamDeviceAddon() 305 { 306 } 307 308 309 const char * 310 NW80xCamDeviceAddon::BrandName() 311 { 312 return "NW80x-based"; 313 } 314 315 316 NW80xCamDevice * 317 NW80xCamDeviceAddon::Instantiate(CamRoster &roster, BUSBDevice *from) 318 { 319 return new NW80xCamDevice(*this, from); 320 } 321 322 323 extern "C" status_t 324 B_WEBCAM_MKINTFUNC(nw80xcam) 325 (WebCamMediaAddOn* webcam, CamDeviceAddon **addon) 326 { 327 *addon = new NW80xCamDeviceAddon(webcam); 328 return B_OK; 329 } 330