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 fLastParameterChanges(0), 34 fCamDeviceAddon(_addon), 35 fDevice(_device), 36 fSupportedDeviceIndex(-1), 37 fChipIsBigEndian(false), 38 fTransferEnabled(false), 39 fLocker("WebcamDeviceLock") 40 { 41 // fill in the generic flavor 42 memset(&fFlavorInfo, 0, sizeof(fFlavorInfo)); 43 _addon.WebCamAddOn()->FillDefaultFlavorInfo(&fFlavorInfo); 44 // if we use id matching, cache the index to the list 45 if (fCamDeviceAddon.SupportedDevices()) 46 { 47 fSupportedDeviceIndex = fCamDeviceAddon.Sniff(_device); 48 fFlavorInfoNameStr = ""; 49 fFlavorInfoNameStr << fCamDeviceAddon.SupportedDevices()[fSupportedDeviceIndex].vendor << " USB Webcam"; 50 fFlavorInfoInfoStr = ""; 51 fFlavorInfoInfoStr << fCamDeviceAddon.SupportedDevices()[fSupportedDeviceIndex].vendor; 52 fFlavorInfoInfoStr << " (" << fCamDeviceAddon.SupportedDevices()[fSupportedDeviceIndex].product << ") USB Webcam"; 53 fFlavorInfo.name = (char *)fFlavorInfoNameStr.String(); 54 fFlavorInfo.info = (char *)fFlavorInfoInfoStr.String(); 55 } 56 #ifdef DEBUG_WRITE_DUMP 57 fDumpFD = open("/boot/home/webcam.out", O_CREAT|O_RDWR, 0644); 58 #endif 59 #ifdef DEBUG_READ_DUMP 60 fDumpFD = open("/boot/home/webcam.out", O_RDONLY, 0644); 61 #endif 62 fBufferLen = 1*B_PAGE_SIZE; 63 fBuffer = (uint8 *)malloc(fBufferLen); 64 } 65 66 67 CamDevice::~CamDevice() 68 { 69 close(fDumpFD); 70 free(fBuffer); 71 if (fDeframer) 72 delete fDeframer; 73 } 74 75 76 status_t 77 CamDevice::InitCheck() 78 { 79 return fInitStatus; 80 } 81 82 83 bool 84 CamDevice::Matches(BUSBDevice* _device) 85 { 86 return (_device) == (fDevice); 87 } 88 89 90 BUSBDevice* 91 CamDevice::GetDevice() 92 { 93 return fDevice; 94 } 95 96 97 void 98 CamDevice::Unplugged() 99 { 100 fDevice = NULL; 101 fBulkIn = NULL; 102 } 103 104 105 bool 106 CamDevice::IsPlugged() 107 { 108 return (fDevice != NULL); 109 } 110 111 112 const char * 113 CamDevice::BrandName() 114 { 115 if (fCamDeviceAddon.SupportedDevices() && (fSupportedDeviceIndex > -1)) 116 return fCamDeviceAddon.SupportedDevices()[fSupportedDeviceIndex].vendor; 117 return "<unknown>"; 118 } 119 120 121 const char * 122 CamDevice::ModelName() 123 { 124 if (fCamDeviceAddon.SupportedDevices() && (fSupportedDeviceIndex > -1)) 125 return fCamDeviceAddon.SupportedDevices()[fSupportedDeviceIndex].product; 126 return "<unknown>"; 127 } 128 129 130 bool 131 CamDevice::SupportsBulk() 132 { 133 return false; 134 } 135 136 137 bool 138 CamDevice::SupportsIsochronous() 139 { 140 return false; 141 } 142 143 144 status_t 145 CamDevice::StartTransfer() 146 { 147 status_t err = B_OK; 148 PRINT((CH "()" CT)); 149 if (fTransferEnabled) 150 return EALREADY; 151 fPumpThread = spawn_thread(_DataPumpThread, "USB Webcam Data Pump", 50, this); 152 if (fPumpThread < B_OK) 153 return fPumpThread; 154 if (fSensor) 155 err = fSensor->StartTransfer(); 156 if (err < B_OK) 157 return err; 158 fTransferEnabled = true; 159 resume_thread(fPumpThread); 160 PRINT((CH ": transfer enabled" CT)); 161 return B_OK; 162 } 163 164 165 status_t 166 CamDevice::StopTransfer() 167 { 168 status_t err = B_OK; 169 PRINT((CH "()" CT)); 170 if (!fTransferEnabled) 171 return EALREADY; 172 if (fSensor) 173 err = fSensor->StopTransfer(); 174 if (err < B_OK) 175 return err; 176 fTransferEnabled = false; 177 178 // the thread itself might Lock() 179 fLocker.Unlock(); 180 wait_for_thread(fPumpThread, &err); 181 fLocker.Lock(); 182 183 return B_OK; 184 } 185 186 187 status_t 188 CamDevice::AcceptVideoFrame(uint32 &width, uint32 &height) 189 { 190 status_t err = ENOSYS; 191 if (Sensor()) 192 err = Sensor()->AcceptVideoFrame(width, height); 193 if (err < B_OK) 194 return err; 195 fVideoFrame = BRect(0, 0, width - 1, height - 1); 196 return B_OK; 197 } 198 199 200 status_t 201 CamDevice::SetVideoFrame(BRect frame) 202 { 203 fVideoFrame = frame; 204 return B_OK; 205 } 206 207 208 status_t 209 CamDevice::SetScale(float scale) 210 { 211 return B_OK; 212 } 213 214 215 status_t 216 CamDevice::SetVideoParams(float brightness, float contrast, float hue, float red, float green, float blue) 217 { 218 return B_OK; 219 } 220 221 222 void 223 CamDevice::AddParameters(BParameterGroup *group, int32 &index) 224 { 225 fFirstParameterID = index; 226 } 227 228 status_t 229 CamDevice::GetParameterValue(int32 id, bigtime_t *last_change, void *value, size_t *size) 230 { 231 return B_BAD_VALUE; 232 } 233 234 status_t 235 CamDevice::SetParameterValue(int32 id, bigtime_t when, const void *value, size_t size) 236 { 237 return B_BAD_VALUE; 238 } 239 240 241 242 size_t 243 CamDevice::MinRawFrameSize() 244 { 245 return 0; 246 } 247 248 249 size_t 250 CamDevice::MaxRawFrameSize() 251 { 252 return 0; 253 } 254 255 256 bool 257 CamDevice::ValidateStartOfFrameTag(const uint8 *tag, size_t taglen) 258 { 259 return true; 260 } 261 262 263 bool 264 CamDevice::ValidateEndOfFrameTag(const uint8 *tag, size_t taglen, size_t datalen) 265 { 266 return true; 267 } 268 269 270 status_t 271 CamDevice::WaitFrame(bigtime_t timeout) 272 { 273 if (fDeframer) 274 return WaitFrame(timeout); 275 return EINVAL; 276 } 277 278 279 status_t 280 CamDevice::GetFrameBitmap(BBitmap **bm, bigtime_t *stamp) 281 { 282 return EINVAL; 283 } 284 285 286 status_t 287 CamDevice::FillFrameBuffer(BBuffer *buffer, bigtime_t *stamp) 288 { 289 return EINVAL; 290 } 291 292 293 bool 294 CamDevice::Lock() 295 { 296 return fLocker.Lock(); 297 } 298 299 300 ssize_t 301 CamDevice::WriteReg(uint16 address, uint8 *data, size_t count) 302 { 303 return ENOSYS; 304 } 305 306 307 ssize_t 308 CamDevice::WriteReg8(uint16 address, uint8 data) 309 { 310 return WriteReg(address, &data, sizeof(uint8)); 311 } 312 313 314 ssize_t 315 CamDevice::WriteReg16(uint16 address, uint16 data) 316 { 317 if (fChipIsBigEndian) 318 data = B_HOST_TO_BENDIAN_INT16(data); 319 else 320 data = B_HOST_TO_LENDIAN_INT16(data); 321 return WriteReg(address, (uint8 *)&data, sizeof(uint16)); 322 } 323 324 325 ssize_t 326 CamDevice::ReadReg(uint16 address, uint8 *data, size_t count, bool cached) 327 { 328 return ENOSYS; 329 } 330 331 332 /* 333 status_t 334 CamDevice::GetStatusIIC() 335 { 336 return ENOSYS; 337 } 338 */ 339 340 /*status_t 341 CamDevice::WaitReadyIIC() 342 { 343 return ENOSYS; 344 } 345 */ 346 347 ssize_t 348 CamDevice::WriteIIC(uint8 address, uint8 *data, size_t count) 349 { 350 return ENOSYS; 351 } 352 353 354 ssize_t 355 CamDevice::WriteIIC8(uint8 address, uint8 data) 356 { 357 return WriteIIC(address, &data, 1); 358 } 359 360 ssize_t 361 CamDevice::WriteIIC16(uint8 address, uint16 data) 362 { 363 if (Sensor() && Sensor()->IsBigEndian()) 364 data = B_HOST_TO_BENDIAN_INT16(data); 365 else 366 data = B_HOST_TO_LENDIAN_INT16(data); 367 return WriteIIC(address, (uint8 *)&data, 2); 368 } 369 370 371 372 373 ssize_t 374 CamDevice::ReadIIC(uint8 address, uint8 *data) 375 { 376 //TODO: make it mode generic 377 return ENOSYS; 378 } 379 380 381 ssize_t 382 CamDevice::ReadIIC8(uint8 address, uint8 *data) 383 { 384 return ReadIIC(address, data); 385 } 386 387 388 ssize_t 389 CamDevice::ReadIIC16(uint8 address, uint16 *data) 390 { 391 return ENOSYS; 392 } 393 394 395 status_t 396 CamDevice::SetIICBitsMode(size_t bits) 397 { 398 return ENOSYS; 399 } 400 401 402 status_t 403 CamDevice::ProbeSensor() 404 { 405 const usb_webcam_support_descriptor *devs; 406 const usb_webcam_support_descriptor *dev = NULL; 407 status_t err; 408 int32 i; 409 410 PRINT((CH ": probing sensors..." CT)); 411 if (fCamDeviceAddon.SupportedDevices() == NULL) 412 return B_ERROR; 413 devs = fCamDeviceAddon.SupportedDevices(); 414 for (i = 0; devs[i].vendor; i++) 415 { 416 if (GetDevice()->VendorID() != devs[i].desc.vendor) 417 continue; 418 if (GetDevice()->ProductID() != devs[i].desc.product) 419 continue; 420 dev = &devs[i]; 421 break; 422 } 423 if (!dev) 424 return ENODEV; 425 if (!dev->sensors) // no usable sensor 426 return ENOENT; 427 BString sensors(dev->sensors); 428 for (i = 0; i > -1 && i < sensors.Length(); ) { 429 BString name; 430 sensors.CopyInto(name, i, sensors.FindFirst(',', i) - i); 431 PRINT((CH ": probing sensor '%s'..." CT, name.String())); 432 433 fSensor = CreateSensor(name.String()); 434 if (fSensor) { 435 err = fSensor->Probe(); 436 if (err >= B_OK) 437 return B_OK; 438 439 PRINT((CH ": sensor '%s' Probe: %s" CT, name.String(), strerror(err))); 440 441 delete fSensor; 442 fSensor = NULL; 443 } 444 445 i = sensors.FindFirst(',', i+1); 446 if (i > - 1) 447 i++; 448 } 449 return ENOENT; 450 } 451 452 453 CamSensor * 454 CamDevice::CreateSensor(const char *name) 455 { 456 int i; 457 for (i = 0; kSensorTable[i].name; i++) { 458 if (!strcmp(kSensorTable[i].name, name)) 459 return kSensorTable[i].instfunc(this); 460 } 461 PRINT((CH ": sensor '%s' not found" CT, name)); 462 return NULL; 463 } 464 465 466 void 467 CamDevice::SetDataInput(BDataIO *input) 468 { 469 fDataInput = input; 470 } 471 472 473 status_t 474 CamDevice::DataPumpThread() 475 { 476 if (SupportsBulk()) { 477 PRINT((CH ": using Bulk" CT)); 478 while (fTransferEnabled) { 479 ssize_t len = -1; 480 BAutolock lock(fLocker); 481 if (!lock.IsLocked()) 482 break; 483 if (!fBulkIn) 484 break; 485 #ifndef DEBUG_DISCARD_INPUT 486 len = fBulkIn->BulkTransfer(fBuffer, fBufferLen); 487 #endif 488 489 //PRINT((CH ": got %d bytes" CT, len)); 490 #ifdef DEBUG_WRITE_DUMP 491 write(fDumpFD, fBuffer, len); 492 #endif 493 #ifdef DEBUG_READ_DUMP 494 if ((len = read(fDumpFD, fBuffer, fBufferLen)) < fBufferLen) 495 lseek(fDumpFD, 0LL, SEEK_SET); 496 #endif 497 498 if (len <= 0) { 499 PRINT((CH ": BulkIn: %s" CT, strerror(len))); 500 break; 501 } 502 503 #ifndef DEBUG_DISCARD_DATA 504 if (fDataInput) { 505 fDataInput->Write(fBuffer, len); 506 // else drop 507 } 508 #endif 509 //snooze(2000); 510 } 511 } 512 #ifdef SUPPORT_ISO 513 else if (SupportsIsochronous()) { 514 int numPacketDescriptors = 20; 515 usb_iso_packet_descriptor packetDescriptors[numPacketDescriptors]; 516 while (fTransferEnabled) { 517 ssize_t len = -1; 518 BAutolock lock(fLocker); 519 if (!lock.IsLocked()) 520 break; 521 if (!fIsoIn) 522 break; 523 #ifndef DEBUG_DISCARD_INPUT 524 len = fIsoIn->IsochronousTransfer(fBuffer, fBufferLen, packetDescriptors, numPacketDescriptors); 525 #endif 526 527 //PRINT((CH ": got %d bytes" CT, len)); 528 #ifdef DEBUG_WRITE_DUMP 529 write(fDumpFD, fBuffer, len); 530 #endif 531 #ifdef DEBUG_READ_DUMP 532 if ((len = read(fDumpFD, fBuffer, fBufferLen)) < fBufferLen) 533 lseek(fDumpFD, 0LL, SEEK_SET); 534 #endif 535 536 if (len <= 0) { 537 PRINT((CH ": BulkIn: %s" CT, strerror(len))); 538 break; 539 } 540 541 #ifndef DEBUG_DISCARD_DATA 542 if (fDataInput) { 543 fDataInput->Write(fBuffer, len); 544 // else drop 545 } 546 #endif 547 //snooze(2000); 548 } 549 } 550 #endif 551 else { 552 PRINT((CH ": No supported transport." CT)); 553 return B_UNSUPPORTED; 554 } 555 return B_OK; 556 } 557 558 559 int32 560 CamDevice::_DataPumpThread(void *_this) 561 { 562 CamDevice *dev = (CamDevice *)_this; 563 return dev->DataPumpThread(); 564 } 565 566 567 void 568 CamDevice::DumpRegs() 569 { 570 } 571 572 573 status_t 574 CamDevice::SendCommand(uint8 dir, uint8 request, uint16 value, 575 uint16 index, uint16 length, void* data) 576 { 577 size_t ret; 578 if (!GetDevice()) 579 return ENODEV; 580 if (length > GetDevice()->MaxEndpoint0PacketSize()) 581 return EINVAL; 582 ret = GetDevice()->ControlTransfer( 583 USB_REQTYPE_VENDOR | USB_REQTYPE_INTERFACE_OUT | dir, 584 request, value, index, length, data); 585 return ret; 586 } 587 588 589 CamDeviceAddon::CamDeviceAddon(WebCamMediaAddOn* webcam) 590 : fWebCamAddOn(webcam), 591 fSupportedDevices(NULL) 592 { 593 } 594 595 596 CamDeviceAddon::~CamDeviceAddon() 597 { 598 } 599 600 601 const char * 602 CamDeviceAddon::BrandName() 603 { 604 return "<unknown>"; 605 } 606 607 608 status_t 609 CamDeviceAddon::Sniff(BUSBDevice *device) 610 { 611 PRINT((CH ": Sniffing for %s" CT, BrandName())); 612 if (!fSupportedDevices) 613 return ENODEV; 614 if (!device) 615 return EINVAL; 616 for (uint32 i = 0; fSupportedDevices[i].vendor; i++) 617 { 618 /* PRINT((CH "{%u,%u,%u,0x%x,0x%x} <> {%u,%u,%u,0x%x,0x%x}" CT, 619 device.Class(), device.Subclass(), device.Protocol(), device.VendorID(), device.ProductID(), 620 fSupportedDevices[i].desc.dev_class, fSupportedDevices[i].desc.dev_subclass, fSupportedDevices[i].desc.dev_protocol, fSupportedDevices[i].desc.vendor, fSupportedDevices[i].desc.product));*/ 621 /* if (device.Class() != fSupportedDevices[i].desc.dev_class) 622 continue; 623 if (device.Subclass() != fSupportedDevices[i].desc.dev_subclass) 624 continue; 625 if (device.Protocol() != fSupportedDevices[i].desc.dev_protocol) 626 continue;*/ 627 if (device->VendorID() != fSupportedDevices[i].desc.vendor) 628 continue; 629 if (device->ProductID() != fSupportedDevices[i].desc.product) 630 continue; 631 return i; 632 } 633 return ENODEV; 634 } 635 636 637 CamDevice * 638 CamDeviceAddon::Instantiate(CamRoster &roster, BUSBDevice *from) 639 { 640 return NULL; 641 } 642 643 644 void 645 CamDeviceAddon::SetSupportedDevices(const usb_webcam_support_descriptor *devs) 646 { 647 fSupportedDevices = devs; 648 } 649 650