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