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 11 const 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 19 QuickCamDevice::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 38 QuickCamDevice::~QuickCamDevice() 39 { 40 41 } 42 43 44 bool 45 QuickCamDevice::SupportsBulk() 46 { 47 return true; 48 } 49 50 51 bool 52 QuickCamDevice::SupportsIsochronous() 53 { 54 return true; 55 } 56 57 58 status_t 59 QuickCamDevice::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 67 DumpRegs(); 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 81 status_t 82 QuickCamDevice::StopTransfer() 83 { 84 status_t err; 85 86 DumpRegs(); 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 103 ssize_t 104 QuickCamDevice::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 111 ssize_t 112 QuickCamDevice::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 120 status_t 121 QuickCamDevice::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 133 status_t 134 QuickCamDevice::WaitReadyIIC() 135 { 136 #warning WRITEME 137 return EBUSY; 138 } 139 140 141 ssize_t 142 QuickCamDevice::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 160 ssize_t 161 QuickCamDevice::ReadIIC(uint8 address, uint8 *data) 162 { 163 return ReadIIC(address, data); 164 } 165 166 167 ssize_t 168 QuickCamDevice::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 194 ssize_t 195 QuickCamDevice::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 224 status_t 225 QuickCamDevice::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 241 status_t 242 QuickCamDevice::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 257 QuickCamDeviceAddon::QuickCamDeviceAddon(WebCamMediaAddOn* webcam) 258 : CamDeviceAddon(webcam) 259 { 260 SetSupportedDevices(kSupportedDevices); 261 } 262 263 264 QuickCamDeviceAddon::~QuickCamDeviceAddon() 265 { 266 } 267 268 269 const char * 270 QuickCamDeviceAddon::BrandName() 271 { 272 return "QuickCam"; 273 } 274 275 276 QuickCamDevice * 277 QuickCamDeviceAddon::Instantiate(CamRoster &roster, BUSBDevice *from) 278 { 279 return new QuickCamDevice(*this, from); 280 } 281 282 283 extern "C" status_t 284 B_WEBCAM_MKINTFUNC(quickcam) 285 (WebCamMediaAddOn* webcam, CamDeviceAddon **addon) 286 { 287 *addon = new QuickCamDeviceAddon(webcam); 288 return B_OK; 289 } 290