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 _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 73 CamDevice::~CamDevice() 74 { 75 close(fDumpFD); 76 free(fBuffer); 77 if (fDeframer) 78 delete fDeframer; 79 } 80 81 82 status_t 83 CamDevice::InitCheck() 84 { 85 return fInitStatus; 86 } 87 88 89 bool 90 CamDevice::Matches(BUSBDevice* _device) 91 { 92 return _device == fDevice; 93 } 94 95 96 BUSBDevice* 97 CamDevice::GetDevice() 98 { 99 return fDevice; 100 } 101 102 103 void 104 CamDevice::Unplugged() 105 { 106 fDevice = NULL; 107 fBulkIn = NULL; 108 fIsoIn = NULL; 109 } 110 111 112 bool 113 CamDevice::IsPlugged() 114 { 115 return (fDevice != NULL); 116 } 117 118 119 const char * 120 CamDevice::BrandName() 121 { 122 if (fCamDeviceAddon.SupportedDevices() && (fSupportedDeviceIndex > -1)) 123 return fCamDeviceAddon.SupportedDevices()[fSupportedDeviceIndex].vendor; 124 return "<unknown>"; 125 } 126 127 128 const char * 129 CamDevice::ModelName() 130 { 131 if (fCamDeviceAddon.SupportedDevices() && (fSupportedDeviceIndex > -1)) 132 return fCamDeviceAddon.SupportedDevices()[fSupportedDeviceIndex].product; 133 return "<unknown>"; 134 } 135 136 137 bool 138 CamDevice::SupportsBulk() 139 { 140 return false; 141 } 142 143 144 bool 145 CamDevice::SupportsIsochronous() 146 { 147 return false; 148 } 149 150 151 status_t 152 CamDevice::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 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::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 207 status_t 208 CamDevice::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 220 status_t 221 CamDevice::SetVideoFrame(BRect frame) 222 { 223 fVideoFrame = frame; 224 return B_OK; 225 } 226 227 228 status_t 229 CamDevice::SetScale(float scale) 230 { 231 return B_OK; 232 } 233 234 235 status_t 236 CamDevice::SetVideoParams(float brightness, float contrast, float hue, 237 float red, float green, float blue) 238 { 239 return B_OK; 240 } 241 242 243 void 244 CamDevice::AddParameters(BParameterGroup *group, int32 &index) 245 { 246 fFirstParameterID = index; 247 } 248 249 250 status_t 251 CamDevice::GetParameterValue(int32 id, bigtime_t *last_change, void *value, 252 size_t *size) 253 { 254 return B_BAD_VALUE; 255 } 256 257 258 status_t 259 CamDevice::SetParameterValue(int32 id, bigtime_t when, const void *value, 260 size_t size) 261 { 262 return B_BAD_VALUE; 263 } 264 265 266 size_t 267 CamDevice::MinRawFrameSize() 268 { 269 return 0; 270 } 271 272 273 size_t 274 CamDevice::MaxRawFrameSize() 275 { 276 return 0; 277 } 278 279 280 bool 281 CamDevice::ValidateStartOfFrameTag(const uint8 *tag, size_t taglen) 282 { 283 return true; 284 } 285 286 287 bool 288 CamDevice::ValidateEndOfFrameTag(const uint8 *tag, size_t taglen, 289 size_t datalen) 290 { 291 return true; 292 } 293 294 295 status_t 296 CamDevice::WaitFrame(bigtime_t timeout) 297 { 298 if (fDeframer) 299 return WaitFrame(timeout); 300 return EINVAL; 301 } 302 303 304 status_t 305 CamDevice::GetFrameBitmap(BBitmap **bm, bigtime_t *stamp) 306 { 307 return EINVAL; 308 } 309 310 311 status_t 312 CamDevice::FillFrameBuffer(BBuffer *buffer, bigtime_t *stamp) 313 { 314 return EINVAL; 315 } 316 317 318 bool 319 CamDevice::Lock() 320 { 321 return fLocker.Lock(); 322 } 323 324 325 status_t 326 CamDevice::PowerOnSensor(bool on) 327 { 328 return B_OK; 329 } 330 331 332 ssize_t 333 CamDevice::WriteReg(uint16 address, uint8 *data, size_t count) 334 { 335 return ENOSYS; 336 } 337 338 339 ssize_t 340 CamDevice::WriteReg8(uint16 address, uint8 data) 341 { 342 return WriteReg(address, &data, sizeof(uint8)); 343 } 344 345 346 ssize_t 347 CamDevice::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 357 ssize_t 358 CamDevice::ReadReg(uint16 address, uint8 *data, size_t count, bool cached) 359 { 360 return ENOSYS; 361 } 362 363 364 ssize_t 365 CamDevice::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 376 ssize_t 377 CamDevice::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 /* 388 status_t 389 CamDevice::GetStatusIIC() 390 { 391 return ENOSYS; 392 } 393 */ 394 395 /*status_t 396 CamDevice::WaitReadyIIC() 397 { 398 return ENOSYS; 399 } 400 */ 401 402 ssize_t 403 CamDevice::WriteIIC(uint8 address, uint8 *data, size_t count) 404 { 405 return ENOSYS; 406 } 407 408 409 ssize_t 410 CamDevice::WriteIIC8(uint8 address, uint8 data) 411 { 412 return WriteIIC(address, &data, 1); 413 } 414 415 416 ssize_t 417 CamDevice::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 427 ssize_t 428 CamDevice::ReadIIC(uint8 address, uint8 *data) 429 { 430 //TODO: make it mode generic 431 return ENOSYS; 432 } 433 434 435 ssize_t 436 CamDevice::ReadIIC8(uint8 address, uint8 *data) 437 { 438 return ReadIIC(address, data); 439 } 440 441 442 ssize_t 443 CamDevice::ReadIIC16(uint8 address, uint16 *data) 444 { 445 return ENOSYS; 446 } 447 448 449 status_t 450 CamDevice::SetIICBitsMode(size_t bits) 451 { 452 return ENOSYS; 453 } 454 455 456 status_t 457 CamDevice::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 507 CamSensor * 508 CamDevice::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 519 void 520 CamDevice::SetDataInput(BDataIO *input) 521 { 522 fDataInput = input; 523 } 524 525 526 status_t 527 CamDevice::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 int fullPackets = 0; 575 int totalPackets = 0; 576 while (fTransferEnabled) { 577 ssize_t len = -1; 578 BAutolock lock(fLocker); 579 if (!lock.IsLocked()) 580 break; 581 if (!fIsoIn) 582 break; 583 #ifndef DEBUG_DISCARD_INPUT 584 len = fIsoIn->IsochronousTransfer(fBuffer, fBufferLen, packetDescriptors, 585 numPacketDescriptors); 586 #endif 587 588 //PRINT((CH ": got %d bytes" CT, len)); 589 #ifdef DEBUG_WRITE_DUMP 590 write(fDumpFD, fBuffer, len); 591 #endif 592 #ifdef DEBUG_READ_DUMP 593 if ((len = read(fDumpFD, fBuffer, fBufferLen)) < fBufferLen) 594 lseek(fDumpFD, 0LL, SEEK_SET); 595 #endif 596 597 if (len <= 0) { 598 PRINT((CH ": IsoIn: %s" CT, strerror(len))); 599 continue; 600 } 601 602 #ifndef DEBUG_DISCARD_DATA 603 if (fDataInput) { 604 int fBufferIndex = 0; 605 for (int i = 0; i < numPacketDescriptors; i++) { 606 int actual_length = ((usb_iso_packet_descriptor) 607 packetDescriptors[i]).actual_length; 608 if (actual_length > 0) { 609 fDataInput->Write(&fBuffer[fBufferIndex], 610 actual_length); 611 } 612 fBufferIndex += actual_length; 613 } 614 } 615 #endif 616 //snooze(2000); 617 } 618 } 619 #endif 620 else { 621 PRINT((CH ": No supported transport." CT)); 622 return B_UNSUPPORTED; 623 } 624 return B_OK; 625 } 626 627 628 int32 629 CamDevice::_DataPumpThread(void *_this) 630 { 631 CamDevice *dev = (CamDevice *)_this; 632 return dev->DataPumpThread(); 633 } 634 635 636 void 637 CamDevice::DumpRegs() 638 { 639 } 640 641 642 status_t 643 CamDevice::SendCommand(uint8 dir, uint8 request, uint16 value, 644 uint16 index, uint16 length, void* data) 645 { 646 ssize_t ret; 647 if (!GetDevice()) 648 return ENODEV; 649 if (length > GetDevice()->MaxEndpoint0PacketSize()) 650 return EINVAL; 651 ret = GetDevice()->ControlTransfer( 652 USB_REQTYPE_VENDOR | USB_REQTYPE_INTERFACE_OUT | dir, 653 request, value, index, length, data); 654 return ret; 655 } 656 657 658 CamDeviceAddon::CamDeviceAddon(WebCamMediaAddOn* webcam) 659 : fWebCamAddOn(webcam), 660 fSupportedDevices(NULL) 661 { 662 } 663 664 665 CamDeviceAddon::~CamDeviceAddon() 666 { 667 } 668 669 670 const char * 671 CamDeviceAddon::BrandName() 672 { 673 return "<unknown>"; 674 } 675 676 677 status_t 678 CamDeviceAddon::Sniff(BUSBDevice *device) 679 { 680 PRINT((CH ": Sniffing for %s" CT, BrandName())); 681 if (!fSupportedDevices) 682 return ENODEV; 683 if (!device) 684 return EINVAL; 685 686 bool supported = false; 687 for (uint32 i = 0; !supported && fSupportedDevices[i].vendor; i++) { 688 if ((fSupportedDevices[i].desc.vendor != 0 689 && device->VendorID() != fSupportedDevices[i].desc.vendor) 690 || (fSupportedDevices[i].desc.product != 0 691 && device->ProductID() != fSupportedDevices[i].desc.product)) 692 continue; 693 694 if ((fSupportedDevices[i].desc.dev_class == 0 695 || device->Class() == fSupportedDevices[i].desc.dev_class) 696 && (fSupportedDevices[i].desc.dev_subclass == 0 697 || device->Subclass() == fSupportedDevices[i].desc.dev_subclass) 698 && (fSupportedDevices[i].desc.dev_protocol == 0 699 || device->Protocol() == fSupportedDevices[i].desc.dev_protocol)) { 700 supported = true; 701 } 702 703 #ifdef __HAIKU__ 704 // we have to check all interfaces for matching class/subclass/protocol 705 for (uint32 j = 0; !supported && j < device->CountConfigurations(); j++) { 706 const BUSBConfiguration* cfg = device->ConfigurationAt(j); 707 for (uint32 k = 0; !supported && k < cfg->CountInterfaces(); k++) { 708 const BUSBInterface* intf = cfg->InterfaceAt(k); 709 for (uint32 l = 0; !supported && l < intf->CountAlternates(); l++) { 710 const BUSBInterface* alt = intf->AlternateAt(l); 711 if ((fSupportedDevices[i].desc.dev_class == 0 712 || alt->Class() == fSupportedDevices[i].desc.dev_class) 713 && (fSupportedDevices[i].desc.dev_subclass == 0 714 || alt->Subclass() == fSupportedDevices[i].desc.dev_subclass) 715 && (fSupportedDevices[i].desc.dev_protocol == 0 716 || alt->Protocol() == fSupportedDevices[i].desc.dev_protocol)) { 717 supported = true; 718 } 719 } 720 } 721 } 722 #endif 723 724 if (supported) 725 return i; 726 } 727 728 return ENODEV; 729 } 730 731 732 CamDevice * 733 CamDeviceAddon::Instantiate(CamRoster &roster, BUSBDevice *from) 734 { 735 return NULL; 736 } 737 738 739 void 740 CamDeviceAddon::SetSupportedDevices(const usb_webcam_support_descriptor *devs) 741 { 742 fSupportedDevices = devs; 743 } 744