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