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