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