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, %" B_PRIuSIZE ")" 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, %" B_PRIuSIZE ", %d)" CT, address, data, count, 115 cached)); 116 memset(data, 0xaa, count); // linux drivers do that without explaining why !? 117 return SendCommand(USB_REQTYPE_DEVICE_IN, 0x04, address, 0, count, data); 118 } 119 120 121 status_t 122 QuickCamDevice::GetStatusIIC() 123 { 124 status_t err = B_ERROR; 125 uint8 status = 0; 126 // TODO: WRITEME 127 //dprintf(ID "i2c_status: error 0x%08lx, status = %02x\n", err, status); 128 if (err < 0) 129 return err; 130 return (status&0x08)?EIO:0; 131 } 132 133 134 status_t 135 QuickCamDevice::WaitReadyIIC() 136 { 137 // TODO: WRITEME 138 return EBUSY; 139 } 140 141 142 ssize_t 143 QuickCamDevice::WriteIIC(uint8 address, uint8 *data, size_t count) 144 { 145 size_t i; 146 uint8 buffer[0x23]; 147 if (count > 16) 148 return EINVAL; 149 memset(buffer, 0, sizeof(buffer)); 150 buffer[0x20] = Sensor() ? Sensor()->IICWriteAddress() : 0; 151 buffer[0x21] = count - 1; 152 buffer[0x22] = 0x01; 153 for (i = 0; i < count; i++) { 154 buffer[i] = address + i; 155 buffer[i+16] = data[i]; 156 } 157 return SendCommand(USB_REQTYPE_DEVICE_OUT, 0x04, STV_I2C_WRITE, 0, 0x23, buffer); 158 } 159 160 161 ssize_t 162 QuickCamDevice::ReadIIC(uint8 address, uint8 *data) 163 { 164 return ReadIIC(address, data); 165 } 166 167 168 ssize_t 169 QuickCamDevice::ReadIIC8(uint8 address, uint8 *data) 170 { 171 status_t err; 172 uint8 buffer[0x23]; 173 memset(buffer, 0, sizeof(buffer)); 174 buffer[0x20] = Sensor() ? Sensor()->IICReadAddress() : 0; 175 buffer[0x21] = 1 - 1; 176 buffer[0x22] = 0x03; 177 buffer[0] = address; 178 err = SendCommand(USB_REQTYPE_DEVICE_OUT, 0x04, STV_I2C_WRITE, 0, 0x23, buffer); 179 PRINT((CH ": SendCommand: %s" CT, strerror(err))); 180 if (err < B_OK) 181 return err; 182 183 buffer[0] = 0xaa; 184 err = SendCommand(USB_REQTYPE_DEVICE_IN, 0x04, STV_I2C_READ, 0, 0x1, buffer); 185 PRINT((CH ": SendCommand: %s" CT, strerror(err))); 186 if (err < B_OK) 187 return err; 188 189 *data = buffer[0]; 190 PRINT((CH ": 0x%02x" CT, *data)); 191 return 1; 192 } 193 194 195 ssize_t 196 QuickCamDevice::ReadIIC16(uint8 address, uint16 *data) 197 { 198 status_t err; 199 uint8 buffer[0x23]; 200 memset(buffer, 0, sizeof(buffer)); 201 buffer[0x20] = Sensor() ? Sensor()->IICReadAddress() : 0; 202 buffer[0x21] = 1 - 1; 203 buffer[0x22] = 0x03; 204 buffer[0] = address; 205 err = SendCommand(USB_REQTYPE_DEVICE_OUT, 0x04, STV_I2C_WRITE, 0, 0x23, buffer); 206 if (err < B_OK) 207 return err; 208 209 buffer[0] = 0xaa; 210 buffer[1] = 0xaa; 211 err = SendCommand(USB_REQTYPE_DEVICE_IN, 0x04, STV_I2C_READ, 0, 0x2, buffer); 212 PRINT((CH ": SendCommand: %s" CT, strerror(err))); 213 if (err < B_OK) 214 return err; 215 216 if (fChipIsBigEndian) 217 *data = B_HOST_TO_BENDIAN_INT16(*(uint16 *)(&buffer[0])); 218 else 219 *data = B_HOST_TO_LENDIAN_INT16(*(uint16 *)(&buffer[0])); 220 PRINT((CH ": 0x%04x" CT, *data)); 221 return 2; 222 } 223 224 225 status_t 226 QuickCamDevice::SetIICBitsMode(size_t bits) 227 { 228 switch (bits) { 229 case 8: 230 WriteReg8(STV_REG23, 0); 231 break; 232 case 16: 233 WriteReg8(STV_REG23, 1); 234 break; 235 default: 236 return EINVAL; 237 } 238 return B_OK; 239 } 240 241 242 status_t 243 QuickCamDevice::SendCommand(uint8 dir, uint8 request, uint16 value, 244 uint16 index, uint16 length, void* data) 245 { 246 size_t ret; 247 if (!GetDevice()) 248 return ENODEV; 249 if (length > GetDevice()->MaxEndpoint0PacketSize()) 250 return EINVAL; 251 ret = GetDevice()->ControlTransfer( 252 USB_REQTYPE_VENDOR | dir, 253 request, value, index, length, data); 254 return ret; 255 } 256 257 258 QuickCamDeviceAddon::QuickCamDeviceAddon(WebCamMediaAddOn* webcam) 259 : CamDeviceAddon(webcam) 260 { 261 SetSupportedDevices(kSupportedDevices); 262 } 263 264 265 QuickCamDeviceAddon::~QuickCamDeviceAddon() 266 { 267 } 268 269 270 const char * 271 QuickCamDeviceAddon::BrandName() 272 { 273 return "QuickCam"; 274 } 275 276 277 QuickCamDevice * 278 QuickCamDeviceAddon::Instantiate(CamRoster &roster, BUSBDevice *from) 279 { 280 return new QuickCamDevice(*this, from); 281 } 282 283 284 extern "C" status_t 285 B_WEBCAM_MKINTFUNC(quickcam) 286 (WebCamMediaAddOn* webcam, CamDeviceAddon **addon) 287 { 288 *addon = new QuickCamDeviceAddon(webcam); 289 return B_OK; 290 } 291