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