1/* 2 * Copyright 2004-2008, François Revol, <revol@free.fr>. 3 * Distributed under the terms of the MIT License. 4 */ 5 6#include "QuickCamDevice.h" 7#include "CamDebug.h" 8#include "CamSensor.h" 9 10 11const usb_webcam_support_descriptor kSupportedDevices[] = { 12{{ 0, 0, 0, 0x046d, 0x0840 }, "Logitech", "QuickCam Express", NULL }, 13{{ 0, 0, 0, 0x046d, 0x0850 }, "Logitech", "QuickCam Express LEGO", NULL }, 14{{ 0, 0, 0, 0, 0}, NULL, NULL, NULL } 15}; 16 17 18 19QuickCamDevice::QuickCamDevice(CamDeviceAddon &_addon, BUSBDevice* _device) 20 :CamDevice(_addon, _device) 21{ 22 status_t err; 23 24 // linux seems to infer this sets I2C controller to 8 or 16 bit mode... 25 // sensors will set to the mode they want when probing 26 SetIICBitsMode(8); 27 err = ProbeSensor(); 28 if (err < B_OK) { 29 // reset I2C mode to 8 bit as linux driver does 30 SetIICBitsMode(8); 31 // not much we can do anyway 32 } 33 34 fInitStatus = B_OK; 35} 36 37 38QuickCamDevice::~QuickCamDevice() 39{ 40 41} 42 43 44bool 45QuickCamDevice::SupportsBulk() 46{ 47 return true; 48} 49 50 51bool 52QuickCamDevice::SupportsIsochronous() 53{ 54 return true; 55} 56 57 58status_t 59QuickCamDevice::StartTransfer() 60{ 61 SetScale(1); 62 if (Sensor()) 63 SetVideoFrame(BRect(0, 0, Sensor()->MaxWidth()-1, Sensor()->MaxHeight()-1)); 64 65 //SetVideoFrame(BRect(0, 0, 320-1, 240-1)); 66 67DumpRegs(); 68#if 0 69 err = ReadReg(SN9C102_CHIP_CTRL, &r, 1, true); 70 if (err < 0) 71 return err; 72 r |= 0x04; 73 err = WriteReg8(SN9C102_CHIP_CTRL, r); 74 if (err < 0) 75 return err; 76#endif 77 return CamDevice::StartTransfer(); 78} 79 80 81status_t 82QuickCamDevice::StopTransfer() 83{ 84 status_t err; 85 86DumpRegs(); 87 err = CamDevice::StopTransfer(); 88#if 0 89// if (err < 0) 90// return err; 91 err = ReadReg(SN9C102_CHIP_CTRL, &r, 1, true); 92 if (err < 0) 93 return err; 94 r &= ~0x04; 95 err = WriteReg8(SN9C102_CHIP_CTRL, r); 96 if (err < 0) 97 return err; 98#endif 99 return err; 100} 101 102 103ssize_t 104QuickCamDevice::WriteReg(uint16 address, uint8 *data, size_t count) 105{ 106 PRINT((CH "(%u, @%p, %u)" CT, address, data, count)); 107 return SendCommand(USB_REQTYPE_DEVICE_OUT, 0x04, address, 0, count, data); 108} 109 110 111ssize_t 112QuickCamDevice::ReadReg(uint16 address, uint8 *data, size_t count, bool cached) 113{ 114 PRINT((CH "(%u, @%p, %u, %d)" CT, address, data, count, cached)); 115 memset(data, 0xaa, count); // linux drivers do that without explaining why !? 116 return SendCommand(USB_REQTYPE_DEVICE_IN, 0x04, address, 0, count, data); 117} 118 119 120status_t 121QuickCamDevice::GetStatusIIC() 122{ 123 status_t err = B_ERROR; 124 uint8 status = 0; 125#warning WRITEME 126 //dprintf(ID "i2c_status: error 0x%08lx, status = %02x\n", err, status); 127 if (err < 0) 128 return err; 129 return (status&0x08)?EIO:0; 130} 131 132 133status_t 134QuickCamDevice::WaitReadyIIC() 135{ 136#warning WRITEME 137 return EBUSY; 138} 139 140 141ssize_t 142QuickCamDevice::WriteIIC(uint8 address, uint8 *data, size_t count) 143{ 144 int i; 145 uint8 buffer[0x23]; 146 if (count > 16) 147 return EINVAL; 148 memset(buffer, 0, sizeof(buffer)); 149 buffer[0x20] = Sensor() ? Sensor()->IICWriteAddress() : 0; 150 buffer[0x21] = count - 1; 151 buffer[0x22] = 0x01; 152 for (i = 0; i < count; i++) { 153 buffer[i] = address + i; 154 buffer[i+16] = data[i]; 155 } 156 return SendCommand(USB_REQTYPE_DEVICE_OUT, 0x04, STV_I2C_WRITE, 0, 0x23, buffer); 157} 158 159 160ssize_t 161QuickCamDevice::ReadIIC(uint8 address, uint8 *data) 162{ 163 return ReadIIC(address, data); 164} 165 166 167ssize_t 168QuickCamDevice::ReadIIC8(uint8 address, uint8 *data) 169{ 170 status_t err; 171 uint8 buffer[0x23]; 172 memset(buffer, 0, sizeof(buffer)); 173 buffer[0x20] = Sensor() ? Sensor()->IICReadAddress() : 0; 174 buffer[0x21] = 1 - 1; 175 buffer[0x22] = 0x03; 176 buffer[0] = address; 177 err = SendCommand(USB_REQTYPE_DEVICE_OUT, 0x04, STV_I2C_WRITE, 0, 0x23, buffer); 178 PRINT((CH ": SendCommand: %s" CT, strerror(err))); 179 if (err < B_OK) 180 return err; 181 182 buffer[0] = 0xaa; 183 err = SendCommand(USB_REQTYPE_DEVICE_IN, 0x04, STV_I2C_READ, 0, 0x1, buffer); 184 PRINT((CH ": SendCommand: %s" CT, strerror(err))); 185 if (err < B_OK) 186 return err; 187 188 *data = buffer[0]; 189 PRINT((CH ": 0x%02x" CT, *data)); 190 return 1; 191} 192 193 194ssize_t 195QuickCamDevice::ReadIIC16(uint8 address, uint16 *data) 196{ 197 status_t err; 198 uint8 buffer[0x23]; 199 memset(buffer, 0, sizeof(buffer)); 200 buffer[0x20] = Sensor() ? Sensor()->IICReadAddress() : 0; 201 buffer[0x21] = 1 - 1; 202 buffer[0x22] = 0x03; 203 buffer[0] = address; 204 err = SendCommand(USB_REQTYPE_DEVICE_OUT, 0x04, STV_I2C_WRITE, 0, 0x23, buffer); 205 if (err < B_OK) 206 return err; 207 208 buffer[0] = 0xaa; 209 buffer[1] = 0xaa; 210 err = SendCommand(USB_REQTYPE_DEVICE_IN, 0x04, STV_I2C_READ, 0, 0x2, buffer); 211 PRINT((CH ": SendCommand: %s" CT, strerror(err))); 212 if (err < B_OK) 213 return err; 214 215 if (fChipIsBigEndian) 216 *data = B_HOST_TO_BENDIAN_INT16(*(uint16 *)(&buffer[0])); 217 else 218 *data = B_HOST_TO_LENDIAN_INT16(*(uint16 *)(&buffer[0])); 219 PRINT((CH ": 0x%04x" CT, *data)); 220 return 2; 221} 222 223 224status_t 225QuickCamDevice::SetIICBitsMode(size_t bits) 226{ 227 switch (bits) { 228 case 8: 229 WriteReg8(STV_REG23, 0); 230 break; 231 case 16: 232 WriteReg8(STV_REG23, 1); 233 break; 234 default: 235 return EINVAL; 236 } 237 return B_OK; 238} 239 240 241status_t 242QuickCamDevice::SendCommand(uint8 dir, uint8 request, uint16 value, 243 uint16 index, uint16 length, void* data) 244{ 245 size_t ret; 246 if (!GetDevice()) 247 return ENODEV; 248 if (length > GetDevice()->MaxEndpoint0PacketSize()) 249 return EINVAL; 250 ret = GetDevice()->ControlTransfer( 251 USB_REQTYPE_VENDOR | dir, 252 request, value, index, length, data); 253 return ret; 254} 255 256 257QuickCamDeviceAddon::QuickCamDeviceAddon(WebCamMediaAddOn* webcam) 258 : CamDeviceAddon(webcam) 259{ 260 SetSupportedDevices(kSupportedDevices); 261} 262 263 264QuickCamDeviceAddon::~QuickCamDeviceAddon() 265{ 266} 267 268 269const char * 270QuickCamDeviceAddon::BrandName() 271{ 272 return "QuickCam"; 273} 274 275 276QuickCamDevice * 277QuickCamDeviceAddon::Instantiate(CamRoster &roster, BUSBDevice *from) 278{ 279 return new QuickCamDevice(*this, from); 280} 281 282 283extern "C" status_t 284B_WEBCAM_MKINTFUNC(quickcam) 285(WebCamMediaAddOn* webcam, CamDeviceAddon **addon) 286{ 287 *addon = new QuickCamDeviceAddon(webcam); 288 return B_OK; 289} 290