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