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