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