1 #include "CamDevice.h" 2 #include "CamSensor.h" 3 #include "CamDeframer.h" 4 #include "CamDebug.h" 5 #include "AddOn.h" 6 7 #include <OS.h> 8 #include <Autolock.h> 9 10 //#define DEBUG_WRITE_DUMP 11 //#define DEBUG_DISCARD_DATA 12 //#define DEBUG_READ_DUMP 13 //#define DEBUG_DISCARD_INPUT 14 15 #undef B_WEBCAM_DECLARE_SENSOR 16 #define B_WEBCAM_DECLARE_SENSOR(sensorclass,sensorname) \ 17 extern "C" CamSensor *Instantiate##sensorclass(CamDevice *cam); 18 #include "CamInternalSensors.h" 19 #undef B_WEBCAM_DECLARE_SENSOR 20 typedef CamSensor *(*SensorInstFunc)(CamDevice *cam); 21 struct { const char *name; SensorInstFunc instfunc; } kSensorTable[] = { 22 #define B_WEBCAM_DECLARE_SENSOR(sensorclass,sensorname) \ 23 { #sensorname, &Instantiate##sensorclass }, 24 #include "CamInternalSensors.h" 25 { NULL, NULL }, 26 }; 27 #undef B_WEBCAM_DECLARE_SENSOR 28 29 // ----------------------------------------------------------------------------- 30 CamDevice::CamDevice(CamDeviceAddon &_addon, BUSBDevice* _device) 31 : fInitStatus(B_NO_INIT), 32 fSensor(NULL), 33 fCamDeviceAddon(_addon), 34 fDevice(_device), 35 fSupportedDeviceIndex(-1), 36 fTransferEnabled(false), 37 fLocker("WebcamDeviceLock") 38 { 39 // fill in the generic flavor 40 memset(&fFlavorInfo, 0, sizeof(fFlavorInfo)); 41 _addon.WebCamAddOn()->FillDefaultFlavorInfo(&fFlavorInfo); 42 // if we use id matching, cache the index to the list 43 if (fCamDeviceAddon.SupportedDevices()) 44 { 45 fSupportedDeviceIndex = fCamDeviceAddon.Sniff(_device); 46 fFlavorInfoNameStr = ""; 47 fFlavorInfoNameStr << fCamDeviceAddon.SupportedDevices()[fSupportedDeviceIndex].vendor << " USB Webcam"; 48 fFlavorInfoInfoStr = ""; 49 fFlavorInfoInfoStr << fCamDeviceAddon.SupportedDevices()[fSupportedDeviceIndex].vendor; 50 fFlavorInfoInfoStr << " (" << fCamDeviceAddon.SupportedDevices()[fSupportedDeviceIndex].product << ") USB Webcam"; 51 fFlavorInfo.name = (char *)fFlavorInfoNameStr.String(); 52 fFlavorInfo.info = (char *)fFlavorInfoInfoStr.String(); 53 } 54 #ifdef DEBUG_WRITE_DUMP 55 fDumpFD = open("/boot/home/webcam.out", O_CREAT|O_RDWR, 0644); 56 #endif 57 #ifdef DEBUG_READ_DUMP 58 fDumpFD = open("/boot/home/webcam.out", O_RDONLY, 0644); 59 #endif 60 fBufferLen = 1*B_PAGE_SIZE; 61 fBuffer = (uint8 *)malloc(fBufferLen); 62 } 63 64 // ----------------------------------------------------------------------------- 65 CamDevice::~CamDevice() 66 { 67 close(fDumpFD); 68 free(fBuffer); 69 if (fDeframer) 70 delete fDeframer; 71 } 72 73 // ----------------------------------------------------------------------------- 74 status_t 75 CamDevice::InitCheck() 76 { 77 return fInitStatus; 78 } 79 80 // ----------------------------------------------------------------------------- 81 bool 82 CamDevice::Matches(BUSBDevice* _device) 83 { 84 return (_device) == (fDevice); 85 } 86 87 // ----------------------------------------------------------------------------- 88 BUSBDevice* 89 CamDevice::GetDevice() 90 { 91 return fDevice; 92 } 93 94 // ----------------------------------------------------------------------------- 95 void 96 CamDevice::Unplugged() 97 { 98 fDevice = NULL; 99 fBulkIn = NULL; 100 } 101 102 // ----------------------------------------------------------------------------- 103 bool 104 CamDevice::IsPlugged() 105 { 106 return (fDevice != NULL); 107 } 108 109 // ----------------------------------------------------------------------------- 110 const char * 111 CamDevice::BrandName() 112 { 113 if (fCamDeviceAddon.SupportedDevices() && (fSupportedDeviceIndex > -1)) 114 return fCamDeviceAddon.SupportedDevices()[fSupportedDeviceIndex].vendor; 115 return "<unknown>"; 116 } 117 118 // ----------------------------------------------------------------------------- 119 const char * 120 CamDevice::ModelName() 121 { 122 if (fCamDeviceAddon.SupportedDevices() && (fSupportedDeviceIndex > -1)) 123 return fCamDeviceAddon.SupportedDevices()[fSupportedDeviceIndex].product; 124 return "<unknown>"; 125 } 126 127 // ----------------------------------------------------------------------------- 128 bool 129 CamDevice::SupportsBulk() 130 { 131 return false; 132 } 133 134 // ----------------------------------------------------------------------------- 135 bool 136 CamDevice::SupportsIsochronous() 137 { 138 return false; 139 } 140 141 // ----------------------------------------------------------------------------- 142 status_t 143 CamDevice::StartTransfer() 144 { 145 status_t err = B_OK; 146 PRINT((CH "()" CT)); 147 if (fTransferEnabled) 148 return EALREADY; 149 fPumpThread = spawn_thread(_DataPumpThread, "USB Webcam Data Pump", 50, this); 150 if (fPumpThread < B_OK) 151 return fPumpThread; 152 if (fSensor) 153 err = fSensor->StartTransfer(); 154 if (err < B_OK) 155 return err; 156 fTransferEnabled = true; 157 resume_thread(fPumpThread); 158 PRINT((CH ": transfer enabled" CT)); 159 return B_OK; 160 } 161 162 // ----------------------------------------------------------------------------- 163 status_t 164 CamDevice::StopTransfer() 165 { 166 status_t err = B_OK; 167 PRINT((CH "()" CT)); 168 if (!fTransferEnabled) 169 return EALREADY; 170 if (fSensor) 171 err = fSensor->StopTransfer(); 172 if (err < B_OK) 173 return err; 174 fTransferEnabled = false; 175 176 // the thread itself might Lock() 177 fLocker.Unlock(); 178 wait_for_thread(fPumpThread, &err); 179 fLocker.Lock(); 180 181 return B_OK; 182 } 183 184 // ----------------------------------------------------------------------------- 185 status_t 186 CamDevice::SetVideoFrame(BRect frame) 187 { 188 fVideoFrame = frame; 189 return B_OK; 190 } 191 192 // ----------------------------------------------------------------------------- 193 status_t 194 CamDevice::SetScale(float scale) 195 { 196 return B_OK; 197 } 198 199 // ----------------------------------------------------------------------------- 200 status_t 201 CamDevice::SetVideoParams(float brightness, float contrast, float hue, float red, float green, float blue) 202 { 203 return B_OK; 204 } 205 206 // ----------------------------------------------------------------------------- 207 size_t 208 CamDevice::MinRawFrameSize() 209 { 210 return 0; 211 } 212 213 // ----------------------------------------------------------------------------- 214 size_t 215 CamDevice::MaxRawFrameSize() 216 { 217 return 0; 218 } 219 220 // ----------------------------------------------------------------------------- 221 bool 222 CamDevice::ValidateStartOfFrameTag(const uint8 *tag, size_t taglen) 223 { 224 return true; 225 } 226 227 // ----------------------------------------------------------------------------- 228 bool 229 CamDevice::ValidateEndOfFrameTag(const uint8 *tag, size_t taglen, size_t datalen) 230 { 231 return true; 232 } 233 234 // ----------------------------------------------------------------------------- 235 status_t 236 CamDevice::WaitFrame(bigtime_t timeout) 237 { 238 if (fDeframer) 239 return WaitFrame(timeout); 240 return EINVAL; 241 } 242 243 // ----------------------------------------------------------------------------- 244 status_t 245 CamDevice::GetFrameBitmap(BBitmap **bm, bigtime_t *stamp) 246 { 247 return EINVAL; 248 } 249 250 // ----------------------------------------------------------------------------- 251 status_t 252 CamDevice::FillFrameBuffer(BBuffer *buffer, bigtime_t *stamp) 253 { 254 return EINVAL; 255 } 256 257 // ----------------------------------------------------------------------------- 258 bool 259 CamDevice::Lock() 260 { 261 return fLocker.Lock(); 262 } 263 264 // ----------------------------------------------------------------------------- 265 void 266 CamDevice::Unlock() 267 { 268 fLocker.Unlock(); 269 } 270 271 // ----------------------------------------------------------------------------- 272 ssize_t 273 CamDevice::WriteReg(uint16 address, uint8 *data, size_t count) 274 { 275 return ENOSYS; 276 } 277 278 // ----------------------------------------------------------------------------- 279 ssize_t 280 CamDevice::WriteReg8(uint16 address, uint8 data) 281 { 282 return WriteReg(address, &data, sizeof(uint8)); 283 } 284 285 // ----------------------------------------------------------------------------- 286 ssize_t 287 CamDevice::WriteReg16(uint16 address, uint16 data) 288 { 289 // XXX: ENDIAN??? 290 return WriteReg(address, (uint8 *)&data, sizeof(uint16)); 291 } 292 293 // ----------------------------------------------------------------------------- 294 ssize_t 295 CamDevice::ReadReg(uint16 address, uint8 *data, size_t count, bool cached) 296 { 297 return ENOSYS; 298 } 299 300 // ----------------------------------------------------------------------------- 301 /* 302 status_t 303 CamDevice::GetStatusIIC() 304 { 305 return ENOSYS; 306 } 307 */ 308 // ----------------------------------------------------------------------------- 309 /*status_t 310 CamDevice::WaitReadyIIC() 311 { 312 return ENOSYS; 313 } 314 */ 315 // ----------------------------------------------------------------------------- 316 ssize_t 317 CamDevice::WriteIIC(uint8 address, uint8 *data, size_t count) 318 { 319 return ENOSYS; 320 } 321 322 // ----------------------------------------------------------------------------- 323 ssize_t 324 CamDevice::WriteIIC8(uint8 address, uint8 data) 325 { 326 return WriteIIC(address, &data, 1); 327 } 328 329 // ----------------------------------------------------------------------------- 330 ssize_t 331 CamDevice::ReadIIC(uint8 address, uint8 *data) 332 { 333 return ENOSYS; 334 } 335 336 // ----------------------------------------------------------------------------- 337 CamSensor * 338 CamDevice::CreateSensor(const char *name) 339 { 340 int i; 341 for (i = 0; kSensorTable[i].name; i++) { 342 if (!strcmp(kSensorTable[i].name, name)) 343 return kSensorTable[i].instfunc(this); 344 } 345 return NULL; 346 } 347 348 // ----------------------------------------------------------------------------- 349 void 350 CamDevice::SetDataInput(BDataIO *input) 351 { 352 fDataInput = input; 353 } 354 355 // ----------------------------------------------------------------------------- 356 status_t 357 CamDevice::DataPumpThread() 358 { 359 if (SupportsBulk()) { 360 PRINT((CH ": using Bulk" CT)); 361 while (fTransferEnabled) { 362 ssize_t len = -1; 363 BAutolock lock(fLocker); 364 if (!lock.IsLocked()) 365 break; 366 if (!fBulkIn) 367 break; 368 #ifndef DEBUG_DISCARD_INPUT 369 len = fBulkIn->BulkTransfer(fBuffer, fBufferLen); 370 #endif 371 372 //PRINT((CH ": got %d bytes" CT, len)); 373 #ifdef DEBUG_WRITE_DUMP 374 write(fDumpFD, fBuffer, len); 375 #endif 376 #ifdef DEBUG_READ_DUMP 377 if ((len = read(fDumpFD, fBuffer, fBufferLen)) < fBufferLen) 378 lseek(fDumpFD, 0LL, SEEK_SET); 379 #endif 380 381 if (len <= 0) { 382 PRINT((CH ": BulkIn: %s" CT, strerror(len))); 383 break; 384 } 385 386 #ifndef DEBUG_DISCARD_DATA 387 if (fDataInput) { 388 fDataInput->Write(fBuffer, len); 389 // else drop 390 } 391 #endif 392 //snooze(2000); 393 } 394 } 395 if (SupportsIsochronous()) { 396 ;//XXX: TODO 397 } 398 return B_OK; 399 } 400 401 // ----------------------------------------------------------------------------- 402 int32 403 CamDevice::_DataPumpThread(void *_this) 404 { 405 CamDevice *dev = (CamDevice *)_this; 406 return dev->DataPumpThread(); 407 } 408 409 // ----------------------------------------------------------------------------- 410 void 411 CamDevice::DumpRegs() 412 { 413 } 414 415 // ----------------------------------------------------------------------------- 416 CamDeviceAddon::CamDeviceAddon(WebCamMediaAddOn* webcam) 417 : fWebCamAddOn(webcam), 418 fSupportedDevices(NULL) 419 { 420 } 421 422 // ----------------------------------------------------------------------------- 423 CamDeviceAddon::~CamDeviceAddon() 424 { 425 } 426 427 // ----------------------------------------------------------------------------- 428 const char * 429 CamDeviceAddon::BrandName() 430 { 431 return "<unknown>"; 432 } 433 434 // ----------------------------------------------------------------------------- 435 status_t 436 CamDeviceAddon::Sniff(BUSBDevice *device) 437 { 438 PRINT((CH ": Sniffing for %s" CT, BrandName())); 439 if (!fSupportedDevices) 440 return ENODEV; 441 if (!device) 442 return EINVAL; 443 for (uint32 i = 0; fSupportedDevices[i].vendor; i++) 444 { 445 /* PRINT((CH "{%u,%u,%u,0x%x,0x%x} <> {%u,%u,%u,0x%x,0x%x}" CT, 446 device.Class(), device.Subclass(), device.Protocol(), device.VendorID(), device.ProductID(), 447 fSupportedDevices[i].desc.dev_class, fSupportedDevices[i].desc.dev_subclass, fSupportedDevices[i].desc.dev_protocol, fSupportedDevices[i].desc.vendor, fSupportedDevices[i].desc.product));*/ 448 /* if (device.Class() != fSupportedDevices[i].desc.dev_class) 449 continue; 450 if (device.Subclass() != fSupportedDevices[i].desc.dev_subclass) 451 continue; 452 if (device.Protocol() != fSupportedDevices[i].desc.dev_protocol) 453 continue;*/ 454 if (device->VendorID() != fSupportedDevices[i].desc.vendor) 455 continue; 456 if (device->ProductID() != fSupportedDevices[i].desc.product) 457 continue; 458 return i; 459 } 460 return ENODEV; 461 } 462 463 // ----------------------------------------------------------------------------- 464 CamDevice * 465 CamDeviceAddon::Instantiate(CamRoster &roster, BUSBDevice *from) 466 { 467 return NULL; 468 } 469 470 // ----------------------------------------------------------------------------- 471 void 472 CamDeviceAddon::SetSupportedDevices(const usb_named_support_descriptor *devs) 473 { 474 fSupportedDevices = devs; 475 } 476 477