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