xref: /haiku/src/add-ons/media/media-add-ons/usb_webcam/CamDevice.cpp (revision d2e1e872611179c9cfaa43ce11bd58b1e3554e4b)
1 #include "CamDevice.h"
2 #include "CamSensor.h"
3 #include "CamDeframer.h"
4 #include "CamDebug.h"
5 #include "AddOn.h"
6 
7 #include <OS.h>
8 #include <Autolock.h>
9 
10 //#define DEBUG_WRITE_DUMP
11 //#define DEBUG_DISCARD_DATA
12 //#define DEBUG_READ_DUMP
13 //#define DEBUG_DISCARD_INPUT
14 
15 #undef B_WEBCAM_DECLARE_SENSOR
16 #define B_WEBCAM_DECLARE_SENSOR(sensorclass,sensorname) \
17 extern "C" CamSensor *Instantiate##sensorclass(CamDevice *cam);
18 #include "CamInternalSensors.h"
19 #undef B_WEBCAM_DECLARE_SENSOR
20 typedef CamSensor *(*SensorInstFunc)(CamDevice *cam);
21 struct { const char *name; SensorInstFunc instfunc; } kSensorTable[] = {
22 #define B_WEBCAM_DECLARE_SENSOR(sensorclass,sensorname) \
23 { #sensorname, &Instantiate##sensorclass },
24 #include "CamInternalSensors.h"
25 { NULL, NULL },
26 };
27 #undef B_WEBCAM_DECLARE_SENSOR
28 
29 // -----------------------------------------------------------------------------
30 CamDevice::CamDevice(CamDeviceAddon &_addon, BUSBDevice* _device)
31 	: fInitStatus(B_NO_INIT),
32 	  fSensor(NULL),
33 	  fCamDeviceAddon(_addon),
34 	  fDevice(_device),
35 	  fSupportedDeviceIndex(-1),
36 	  fTransferEnabled(false),
37 	  fLocker("WebcamDeviceLock")
38 {
39 	// fill in the generic flavor
40 	memset(&fFlavorInfo, 0, sizeof(fFlavorInfo));
41 	_addon.WebCamAddOn()->FillDefaultFlavorInfo(&fFlavorInfo);
42 	// if we use id matching, cache the index to the list
43 	if (fCamDeviceAddon.SupportedDevices())
44 	{
45 		fSupportedDeviceIndex = fCamDeviceAddon.Sniff(_device);
46 		fFlavorInfoNameStr = "";
47 		fFlavorInfoNameStr << fCamDeviceAddon.SupportedDevices()[fSupportedDeviceIndex].vendor << " USB Webcam";
48 		fFlavorInfoInfoStr = "";
49 		fFlavorInfoInfoStr << fCamDeviceAddon.SupportedDevices()[fSupportedDeviceIndex].vendor;
50 		fFlavorInfoInfoStr << " (" << fCamDeviceAddon.SupportedDevices()[fSupportedDeviceIndex].product << ") USB Webcam";
51 		fFlavorInfo.name = (char *)fFlavorInfoNameStr.String();
52 		fFlavorInfo.info = (char *)fFlavorInfoInfoStr.String();
53 	}
54 #ifdef DEBUG_WRITE_DUMP
55 	fDumpFD = open("/boot/home/webcam.out", O_CREAT|O_RDWR, 0644);
56 #endif
57 #ifdef DEBUG_READ_DUMP
58 	fDumpFD = open("/boot/home/webcam.out", O_RDONLY, 0644);
59 #endif
60 	fBufferLen = 1*B_PAGE_SIZE;
61 	fBuffer = (uint8 *)malloc(fBufferLen);
62 }
63 
64 // -----------------------------------------------------------------------------
65 CamDevice::~CamDevice()
66 {
67 	close(fDumpFD);
68 	free(fBuffer);
69 	if (fDeframer)
70 		delete fDeframer;
71 }
72 
73 // -----------------------------------------------------------------------------
74 status_t
75 CamDevice::InitCheck()
76 {
77 	return fInitStatus;
78 }
79 
80 // -----------------------------------------------------------------------------
81 bool
82 CamDevice::Matches(BUSBDevice* _device)
83 {
84 	return (_device) == (fDevice);
85 }
86 
87 // -----------------------------------------------------------------------------
88 BUSBDevice*
89 CamDevice::GetDevice()
90 {
91 	return fDevice;
92 }
93 
94 // -----------------------------------------------------------------------------
95 void
96 CamDevice::Unplugged()
97 {
98 	fDevice = NULL;
99 	fBulkIn = NULL;
100 }
101 
102 // -----------------------------------------------------------------------------
103 bool
104 CamDevice::IsPlugged()
105 {
106 	return (fDevice != NULL);
107 }
108 
109 // -----------------------------------------------------------------------------
110 const char *
111 CamDevice::BrandName()
112 {
113 	if (fCamDeviceAddon.SupportedDevices() && (fSupportedDeviceIndex > -1))
114 		return fCamDeviceAddon.SupportedDevices()[fSupportedDeviceIndex].vendor;
115 	return "<unknown>";
116 }
117 
118 // -----------------------------------------------------------------------------
119 const char *
120 CamDevice::ModelName()
121 {
122 	if (fCamDeviceAddon.SupportedDevices() && (fSupportedDeviceIndex > -1))
123 		return fCamDeviceAddon.SupportedDevices()[fSupportedDeviceIndex].product;
124 	return "<unknown>";
125 }
126 
127 // -----------------------------------------------------------------------------
128 bool
129 CamDevice::SupportsBulk()
130 {
131 	return false;
132 }
133 
134 // -----------------------------------------------------------------------------
135 bool
136 CamDevice::SupportsIsochronous()
137 {
138 	return false;
139 }
140 
141 // -----------------------------------------------------------------------------
142 status_t
143 CamDevice::StartTransfer()
144 {
145 	status_t err = B_OK;
146 	PRINT((CH "()" CT));
147 	if (fTransferEnabled)
148 		return EALREADY;
149 	fPumpThread = spawn_thread(_DataPumpThread, "USB Webcam Data Pump", 50, this);
150 	if (fPumpThread < B_OK)
151 		return fPumpThread;
152 	if (fSensor)
153 		err = fSensor->StartTransfer();
154 	if (err < B_OK)
155 		return err;
156 	fTransferEnabled = true;
157 	resume_thread(fPumpThread);
158 	PRINT((CH ": transfer enabled" CT));
159 	return B_OK;
160 }
161 
162 // -----------------------------------------------------------------------------
163 status_t
164 CamDevice::StopTransfer()
165 {
166 	status_t err = B_OK;
167 	PRINT((CH "()" CT));
168 	if (!fTransferEnabled)
169 		return EALREADY;
170 	if (fSensor)
171 		err = fSensor->StopTransfer();
172 	if (err < B_OK)
173 		return err;
174 	fTransferEnabled = false;
175 
176 	// the thread itself might Lock()
177 	fLocker.Unlock();
178 	wait_for_thread(fPumpThread, &err);
179 	fLocker.Lock();
180 
181 	return B_OK;
182 }
183 
184 // -----------------------------------------------------------------------------
185 status_t
186 CamDevice::SetVideoFrame(BRect frame)
187 {
188 	fVideoFrame = frame;
189 	return B_OK;
190 }
191 
192 // -----------------------------------------------------------------------------
193 status_t
194 CamDevice::SetScale(float scale)
195 {
196 	return B_OK;
197 }
198 
199 // -----------------------------------------------------------------------------
200 status_t
201 CamDevice::SetVideoParams(float brightness, float contrast, float hue, float red, float green, float blue)
202 {
203 	return B_OK;
204 }
205 
206 // -----------------------------------------------------------------------------
207 size_t
208 CamDevice::MinRawFrameSize()
209 {
210 	return 0;
211 }
212 
213 // -----------------------------------------------------------------------------
214 size_t
215 CamDevice::MaxRawFrameSize()
216 {
217 	return 0;
218 }
219 
220 // -----------------------------------------------------------------------------
221 bool
222 CamDevice::ValidateStartOfFrameTag(const uint8 *tag, size_t taglen)
223 {
224 	return true;
225 }
226 
227 // -----------------------------------------------------------------------------
228 bool
229 CamDevice::ValidateEndOfFrameTag(const uint8 *tag, size_t taglen, size_t datalen)
230 {
231 	return true;
232 }
233 
234 // -----------------------------------------------------------------------------
235 status_t
236 CamDevice::WaitFrame(bigtime_t timeout)
237 {
238 	if (fDeframer)
239 		return WaitFrame(timeout);
240 	return EINVAL;
241 }
242 
243 // -----------------------------------------------------------------------------
244 status_t
245 CamDevice::GetFrameBitmap(BBitmap **bm, bigtime_t *stamp)
246 {
247 	return EINVAL;
248 }
249 
250 // -----------------------------------------------------------------------------
251 status_t
252 CamDevice::FillFrameBuffer(BBuffer *buffer, bigtime_t *stamp)
253 {
254 	return EINVAL;
255 }
256 
257 // -----------------------------------------------------------------------------
258 bool
259 CamDevice::Lock()
260 {
261 	return fLocker.Lock();
262 }
263 
264 // -----------------------------------------------------------------------------
265 void
266 CamDevice::Unlock()
267 {
268 	fLocker.Unlock();
269 }
270 
271 // -----------------------------------------------------------------------------
272 ssize_t
273 CamDevice::WriteReg(uint16 address, uint8 *data, size_t count)
274 {
275 	return ENOSYS;
276 }
277 
278 // -----------------------------------------------------------------------------
279 ssize_t
280 CamDevice::WriteReg8(uint16 address, uint8 data)
281 {
282 	return WriteReg(address, &data, sizeof(uint8));
283 }
284 
285 // -----------------------------------------------------------------------------
286 ssize_t
287 CamDevice::WriteReg16(uint16 address, uint16 data)
288 {
289 	// XXX: ENDIAN???
290 	return WriteReg(address, (uint8 *)&data, sizeof(uint16));
291 }
292 
293 // -----------------------------------------------------------------------------
294 ssize_t
295 CamDevice::ReadReg(uint16 address, uint8 *data, size_t count, bool cached)
296 {
297 	return ENOSYS;
298 }
299 
300 // -----------------------------------------------------------------------------
301 /*
302 status_t
303 CamDevice::GetStatusIIC()
304 {
305 	return ENOSYS;
306 }
307 */
308 // -----------------------------------------------------------------------------
309 /*status_t
310 CamDevice::WaitReadyIIC()
311 {
312 	return ENOSYS;
313 }
314 */
315 // -----------------------------------------------------------------------------
316 ssize_t
317 CamDevice::WriteIIC(uint8 address, uint8 *data, size_t count)
318 {
319 	return ENOSYS;
320 }
321 
322 // -----------------------------------------------------------------------------
323 ssize_t
324 CamDevice::WriteIIC8(uint8 address, uint8 data)
325 {
326 	return WriteIIC(address, &data, 1);
327 }
328 
329 // -----------------------------------------------------------------------------
330 ssize_t
331 CamDevice::ReadIIC(uint8 address, uint8 *data)
332 {
333 	return ENOSYS;
334 }
335 
336 // -----------------------------------------------------------------------------
337 CamSensor *
338 CamDevice::CreateSensor(const char *name)
339 {
340 	int i;
341 	for (i = 0; kSensorTable[i].name; i++) {
342 		if (!strcmp(kSensorTable[i].name, name))
343 			return kSensorTable[i].instfunc(this);
344 	}
345 	return NULL;
346 }
347 
348 // -----------------------------------------------------------------------------
349 void
350 CamDevice::SetDataInput(BDataIO *input)
351 {
352 	fDataInput = input;
353 }
354 
355 // -----------------------------------------------------------------------------
356 status_t
357 CamDevice::DataPumpThread()
358 {
359 	if (SupportsBulk()) {
360 		PRINT((CH ": using Bulk" CT));
361 		while (fTransferEnabled) {
362 			ssize_t len = -1;
363 			BAutolock lock(fLocker);
364 			if (!lock.IsLocked())
365 				break;
366 			if (!fBulkIn)
367 				break;
368 #ifndef DEBUG_DISCARD_INPUT
369 			len = fBulkIn->BulkTransfer(fBuffer, fBufferLen);
370 #endif
371 
372 			//PRINT((CH ": got %d bytes" CT, len));
373 #ifdef DEBUG_WRITE_DUMP
374 			write(fDumpFD, fBuffer, len);
375 #endif
376 #ifdef DEBUG_READ_DUMP
377 			if ((len = read(fDumpFD, fBuffer, fBufferLen)) < fBufferLen)
378 				lseek(fDumpFD, 0LL, SEEK_SET);
379 #endif
380 
381 			if (len <= 0) {
382 				PRINT((CH ": BulkIn: %s" CT, strerror(len)));
383 				break;
384 			}
385 
386 #ifndef DEBUG_DISCARD_DATA
387 			if (fDataInput) {
388 				fDataInput->Write(fBuffer, len);
389 				// else drop
390 			}
391 #endif
392 			//snooze(2000);
393 		}
394 	}
395 	if (SupportsIsochronous()) {
396 		;//XXX: TODO
397 	}
398 	return B_OK;
399 }
400 
401 // -----------------------------------------------------------------------------
402 int32
403 CamDevice::_DataPumpThread(void *_this)
404 {
405 	CamDevice *dev = (CamDevice *)_this;
406 	return dev->DataPumpThread();
407 }
408 
409 // -----------------------------------------------------------------------------
410 void
411 CamDevice::DumpRegs()
412 {
413 }
414 
415 // -----------------------------------------------------------------------------
416 CamDeviceAddon::CamDeviceAddon(WebCamMediaAddOn* webcam)
417 	: fWebCamAddOn(webcam),
418 	  fSupportedDevices(NULL)
419 {
420 }
421 
422 // -----------------------------------------------------------------------------
423 CamDeviceAddon::~CamDeviceAddon()
424 {
425 }
426 
427 // -----------------------------------------------------------------------------
428 const char *
429 CamDeviceAddon::BrandName()
430 {
431 	return "<unknown>";
432 }
433 
434 // -----------------------------------------------------------------------------
435 status_t
436 CamDeviceAddon::Sniff(BUSBDevice *device)
437 {
438 	PRINT((CH ": Sniffing for %s" CT, BrandName()));
439 	if (!fSupportedDevices)
440 		return ENODEV;
441 	if (!device)
442 		return EINVAL;
443 	for (uint32 i = 0; fSupportedDevices[i].vendor; i++)
444 	{
445 /*		PRINT((CH "{%u,%u,%u,0x%x,0x%x} <> {%u,%u,%u,0x%x,0x%x}" CT,
446 			device.Class(), device.Subclass(), device.Protocol(), device.VendorID(), device.ProductID(),
447 			fSupportedDevices[i].desc.dev_class, fSupportedDevices[i].desc.dev_subclass, fSupportedDevices[i].desc.dev_protocol, fSupportedDevices[i].desc.vendor, fSupportedDevices[i].desc.product));*/
448 /*		if (device.Class() != fSupportedDevices[i].desc.dev_class)
449 			continue;
450 		if (device.Subclass() != fSupportedDevices[i].desc.dev_subclass)
451 			continue;
452 		if (device.Protocol() != fSupportedDevices[i].desc.dev_protocol)
453 			continue;*/
454 		if (device->VendorID() != fSupportedDevices[i].desc.vendor)
455 			continue;
456 		if (device->ProductID() != fSupportedDevices[i].desc.product)
457 			continue;
458 		return i;
459 	}
460 	return ENODEV;
461 }
462 
463 // -----------------------------------------------------------------------------
464 CamDevice *
465 CamDeviceAddon::Instantiate(CamRoster &roster, BUSBDevice *from)
466 {
467 	return NULL;
468 }
469 
470 // -----------------------------------------------------------------------------
471 void
472 CamDeviceAddon::SetSupportedDevices(const usb_named_support_descriptor *devs)
473 {
474 	fSupportedDevices = devs;
475 }
476 
477