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 237 status_t 238 CamDevice::GetParameterValue(int32 id, bigtime_t *last_change, void *value, size_t *size) 239 { 240 return B_BAD_VALUE; 241 } 242 243 244 status_t 245 CamDevice::SetParameterValue(int32 id, bigtime_t when, const void *value, size_t size) 246 { 247 return B_BAD_VALUE; 248 } 249 250 251 size_t 252 CamDevice::MinRawFrameSize() 253 { 254 return 0; 255 } 256 257 258 size_t 259 CamDevice::MaxRawFrameSize() 260 { 261 return 0; 262 } 263 264 265 bool 266 CamDevice::ValidateStartOfFrameTag(const uint8 *tag, size_t taglen) 267 { 268 return true; 269 } 270 271 272 bool 273 CamDevice::ValidateEndOfFrameTag(const uint8 *tag, size_t taglen, size_t datalen) 274 { 275 return true; 276 } 277 278 279 status_t 280 CamDevice::WaitFrame(bigtime_t timeout) 281 { 282 if (fDeframer) 283 return WaitFrame(timeout); 284 return EINVAL; 285 } 286 287 288 status_t 289 CamDevice::GetFrameBitmap(BBitmap **bm, bigtime_t *stamp) 290 { 291 return EINVAL; 292 } 293 294 295 status_t 296 CamDevice::FillFrameBuffer(BBuffer *buffer, bigtime_t *stamp) 297 { 298 return EINVAL; 299 } 300 301 302 bool 303 CamDevice::Lock() 304 { 305 return fLocker.Lock(); 306 } 307 308 309 status_t 310 CamDevice::PowerOnSensor(bool on) 311 { 312 return B_OK; 313 } 314 315 316 ssize_t 317 CamDevice::WriteReg(uint16 address, uint8 *data, size_t count) 318 { 319 return ENOSYS; 320 } 321 322 323 ssize_t 324 CamDevice::WriteReg8(uint16 address, uint8 data) 325 { 326 return WriteReg(address, &data, sizeof(uint8)); 327 } 328 329 330 ssize_t 331 CamDevice::WriteReg16(uint16 address, uint16 data) 332 { 333 if (fChipIsBigEndian) 334 data = B_HOST_TO_BENDIAN_INT16(data); 335 else 336 data = B_HOST_TO_LENDIAN_INT16(data); 337 return WriteReg(address, (uint8 *)&data, sizeof(uint16)); 338 } 339 340 341 ssize_t 342 CamDevice::ReadReg(uint16 address, uint8 *data, size_t count, bool cached) 343 { 344 return ENOSYS; 345 } 346 347 348 ssize_t 349 CamDevice::OrReg8(uint16 address, uint8 data, uint8 mask) 350 { 351 uint8 value; 352 if (ReadReg(address, &value, 1, true) < 1) 353 return EIO; 354 value &= mask; 355 value |= data; 356 return WriteReg8(address, value); 357 } 358 359 360 ssize_t 361 CamDevice::AndReg8(uint16 address, uint8 data) 362 { 363 uint8 value; 364 if (ReadReg(address, &value, 1, true) < 1) 365 return EIO; 366 value &= data; 367 return WriteReg8(address, value); 368 } 369 370 371 /* 372 status_t 373 CamDevice::GetStatusIIC() 374 { 375 return ENOSYS; 376 } 377 */ 378 379 /*status_t 380 CamDevice::WaitReadyIIC() 381 { 382 return ENOSYS; 383 } 384 */ 385 386 ssize_t 387 CamDevice::WriteIIC(uint8 address, uint8 *data, size_t count) 388 { 389 return ENOSYS; 390 } 391 392 393 ssize_t 394 CamDevice::WriteIIC8(uint8 address, uint8 data) 395 { 396 return WriteIIC(address, &data, 1); 397 } 398 399 400 ssize_t 401 CamDevice::WriteIIC16(uint8 address, uint16 data) 402 { 403 if (Sensor() && Sensor()->IsBigEndian()) 404 data = B_HOST_TO_BENDIAN_INT16(data); 405 else 406 data = B_HOST_TO_LENDIAN_INT16(data); 407 return WriteIIC(address, (uint8 *)&data, 2); 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 if ((fSupportedDevices[i].desc.vendor != 0 658 && device->VendorID() != fSupportedDevices[i].desc.vendor) 659 || (fSupportedDevices[i].desc.product != 0 660 && device->ProductID() != fSupportedDevices[i].desc.product)) 661 continue; 662 663 if ((fSupportedDevices[i].desc.dev_class == 0 664 || device->Class() == fSupportedDevices[i].desc.dev_class) 665 && (fSupportedDevices[i].desc.dev_subclass == 0 666 || device->Subclass() == fSupportedDevices[i].desc.dev_subclass) 667 && (fSupportedDevices[i].desc.dev_protocol == 0 668 || device->Protocol() == fSupportedDevices[i].desc.dev_protocol)) { 669 supported = true; 670 } 671 672 #ifdef __HAIKU__ 673 // we have to check all interfaces for matching class/subclass/protocol 674 for (uint32 j = 0; !supported && j < device->CountConfigurations(); j++) { 675 const BUSBConfiguration* cfg = device->ConfigurationAt(j); 676 for (uint32 k = 0; !supported && k < cfg->CountInterfaces(); k++) { 677 const BUSBInterface* intf = cfg->InterfaceAt(k); 678 for (uint32 l = 0; !supported && l < intf->CountAlternates(); l++) { 679 const BUSBInterface* alt = intf->AlternateAt(l); 680 if ((fSupportedDevices[i].desc.dev_class == 0 681 || alt->Class() == fSupportedDevices[i].desc.dev_class) 682 && (fSupportedDevices[i].desc.dev_subclass == 0 683 || alt->Subclass() == fSupportedDevices[i].desc.dev_subclass) 684 && (fSupportedDevices[i].desc.dev_protocol == 0 685 || alt->Protocol() == fSupportedDevices[i].desc.dev_protocol)) { 686 supported = true; 687 } 688 } 689 } 690 } 691 #endif 692 693 if (supported) 694 return i; 695 } 696 697 return ENODEV; 698 } 699 700 701 CamDevice * 702 CamDeviceAddon::Instantiate(CamRoster &roster, BUSBDevice *from) 703 { 704 return NULL; 705 } 706 707 708 void 709 CamDeviceAddon::SetSupportedDevices(const usb_webcam_support_descriptor *devs) 710 { 711 fSupportedDevices = devs; 712 } 713