xref: /haiku/src/add-ons/media/media-add-ons/usb_webcam/CamDevice.cpp (revision 2f470aec1c92ce6917b8a903e343795dc77af41f)
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 	  fCamDeviceAddon(_addon),
33 	  fDevice(_device),
34 	  fSupportedDeviceIndex(-1),
35 	  fTransferEnabled(false),
36 	  fLocker("WebcamDeviceLock"),
37 	  fSensor(NULL)
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 	wait_for_thread(fPumpThread, &err);
176 	return B_OK;
177 }
178 
179 // -----------------------------------------------------------------------------
180 status_t
181 CamDevice::SetVideoFrame(BRect frame)
182 {
183 	fVideoFrame = frame;
184 	return B_OK;
185 }
186 
187 // -----------------------------------------------------------------------------
188 status_t
189 CamDevice::SetScale(float scale)
190 {
191 	return B_OK;
192 }
193 
194 // -----------------------------------------------------------------------------
195 status_t
196 CamDevice::SetVideoParams(float brightness, float contrast, float hue, float red, float green, float blue)
197 {
198 	return B_OK;
199 }
200 
201 // -----------------------------------------------------------------------------
202 size_t
203 CamDevice::MinRawFrameSize()
204 {
205 	return 0;
206 }
207 
208 // -----------------------------------------------------------------------------
209 size_t
210 CamDevice::MaxRawFrameSize()
211 {
212 	return 0;
213 }
214 
215 // -----------------------------------------------------------------------------
216 bool
217 CamDevice::ValidateStartOfFrameTag(const uint8 *tag, size_t taglen)
218 {
219 	return true;
220 }
221 
222 // -----------------------------------------------------------------------------
223 bool
224 CamDevice::ValidateEndOfFrameTag(const uint8 *tag, size_t taglen, size_t datalen)
225 {
226 	return true;
227 }
228 
229 // -----------------------------------------------------------------------------
230 status_t
231 CamDevice::GetFrameBitmap(BBitmap **bm)
232 {
233 	return EINVAL;
234 }
235 
236 // -----------------------------------------------------------------------------
237 status_t
238 CamDevice::FillFrameBuffer(BBuffer *buffer)
239 {
240 	return EINVAL;
241 }
242 
243 // -----------------------------------------------------------------------------
244 bool
245 CamDevice::Lock()
246 {
247 	return fLocker.Lock();
248 }
249 
250 // -----------------------------------------------------------------------------
251 void
252 CamDevice::Unlock()
253 {
254 	fLocker.Unlock();
255 }
256 
257 // -----------------------------------------------------------------------------
258 ssize_t
259 CamDevice::WriteReg(uint16 address, uint8 *data, size_t count)
260 {
261 	return ENOSYS;
262 }
263 
264 // -----------------------------------------------------------------------------
265 ssize_t
266 CamDevice::WriteReg8(uint16 address, uint8 data)
267 {
268 	return WriteReg(address, &data, sizeof(uint8));
269 }
270 
271 // -----------------------------------------------------------------------------
272 ssize_t
273 CamDevice::WriteReg16(uint16 address, uint16 data)
274 {
275 	// XXX: ENDIAN???
276 	return WriteReg(address, (uint8 *)&data, sizeof(uint16));
277 }
278 
279 // -----------------------------------------------------------------------------
280 ssize_t
281 CamDevice::ReadReg(uint16 address, uint8 *data, size_t count, bool cached)
282 {
283 	return ENOSYS;
284 }
285 
286 // -----------------------------------------------------------------------------
287 /*
288 status_t
289 CamDevice::GetStatusIIC()
290 {
291 	return ENOSYS;
292 }
293 */
294 // -----------------------------------------------------------------------------
295 /*status_t
296 CamDevice::WaitReadyIIC()
297 {
298 	return ENOSYS;
299 }
300 */
301 // -----------------------------------------------------------------------------
302 ssize_t
303 CamDevice::WriteIIC(uint8 address, uint8 *data, size_t count)
304 {
305 	return ENOSYS;
306 }
307 
308 // -----------------------------------------------------------------------------
309 ssize_t
310 CamDevice::WriteIIC8(uint8 address, uint8 data)
311 {
312 	return WriteIIC(address, &data, 1);
313 }
314 
315 // -----------------------------------------------------------------------------
316 ssize_t
317 CamDevice::ReadIIC(uint8 address, uint8 *data)
318 {
319 	return ENOSYS;
320 }
321 
322 // -----------------------------------------------------------------------------
323 CamSensor *
324 CamDevice::CreateSensor(const char *name)
325 {
326 	int i;
327 	for (i = 0; kSensorTable[i].name; i++) {
328 		if (!strcmp(kSensorTable[i].name, name))
329 			return kSensorTable[i].instfunc(this);
330 	}
331 	return NULL;
332 }
333 
334 // -----------------------------------------------------------------------------
335 void
336 CamDevice::SetDataInput(BDataIO *input)
337 {
338 	fDataInput = input;
339 }
340 
341 // -----------------------------------------------------------------------------
342 status_t
343 CamDevice::DataPumpThread()
344 {
345 	if (SupportsBulk()) {
346 		PRINT((CH ": using Bulk" CT));
347 		while (fTransferEnabled) {
348 			ssize_t len = -1;
349 			BAutolock lock(fLocker);
350 			if (!lock.IsLocked())
351 				break;
352 			if (!fBulkIn)
353 				break;
354 #ifndef DEBUG_DISCARD_INPUT
355 			len = fBulkIn->BulkTransfer(fBuffer, fBufferLen);
356 #endif
357 
358 			//PRINT((CH ": got %d bytes" CT, len));
359 #ifdef DEBUG_WRITE_DUMP
360 			write(fDumpFD, fBuffer, len);
361 #endif
362 #ifdef DEBUG_READ_DUMP
363 			if ((len = read(fDumpFD, fBuffer, fBufferLen)) < fBufferLen)
364 				lseek(fDumpFD, 0LL, SEEK_SET);
365 #endif
366 
367 			if (len <= 0) {
368 				PRINT((CH ": BulkIn: %s" CT, strerror(len)));
369 				break;
370 			}
371 
372 #ifndef DEBUG_DISCARD_DATA
373 			if (fDataInput) {
374 				fDataInput->Write(fBuffer, len);
375 				// else drop
376 			}
377 #endif
378 			//snooze(2000);
379 		}
380 	}
381 	if (SupportsIsochronous()) {
382 		;//XXX: TODO
383 	}
384 	return B_OK;
385 }
386 
387 // -----------------------------------------------------------------------------
388 int32
389 CamDevice::_DataPumpThread(void *_this)
390 {
391 	CamDevice *dev = (CamDevice *)_this;
392 	return dev->DataPumpThread();
393 }
394 
395 // -----------------------------------------------------------------------------
396 void
397 CamDevice::DumpRegs()
398 {
399 }
400 
401 // -----------------------------------------------------------------------------
402 CamDeviceAddon::CamDeviceAddon(WebCamMediaAddOn* webcam)
403 	: fWebCamAddOn(webcam),
404 	  fSupportedDevices(NULL)
405 {
406 }
407 
408 // -----------------------------------------------------------------------------
409 CamDeviceAddon::~CamDeviceAddon()
410 {
411 }
412 
413 // -----------------------------------------------------------------------------
414 const char *
415 CamDeviceAddon::BrandName()
416 {
417 	return "<unknown>";
418 }
419 
420 // -----------------------------------------------------------------------------
421 status_t
422 CamDeviceAddon::Sniff(BUSBDevice *device)
423 {
424 	PRINT((CH ": Sniffing for %s" CT, BrandName()));
425 	if (!fSupportedDevices)
426 		return ENODEV;
427 	if (!device)
428 		return EINVAL;
429 	for (uint32 i = 0; fSupportedDevices[i].vendor; i++)
430 	{
431 /*		PRINT((CH "{%u,%u,%u,0x%x,0x%x} <> {%u,%u,%u,0x%x,0x%x}" CT,
432 			device.Class(), device.Subclass(), device.Protocol(), device.VendorID(), device.ProductID(),
433 			fSupportedDevices[i].desc.dev_class, fSupportedDevices[i].desc.dev_subclass, fSupportedDevices[i].desc.dev_protocol, fSupportedDevices[i].desc.vendor, fSupportedDevices[i].desc.product));*/
434 /*		if (device.Class() != fSupportedDevices[i].desc.dev_class)
435 			continue;
436 		if (device.Subclass() != fSupportedDevices[i].desc.dev_subclass)
437 			continue;
438 		if (device.Protocol() != fSupportedDevices[i].desc.dev_protocol)
439 			continue;*/
440 		if (device->VendorID() != fSupportedDevices[i].desc.vendor)
441 			continue;
442 		if (device->ProductID() != fSupportedDevices[i].desc.product)
443 			continue;
444 		return i;
445 	}
446 	return ENODEV;
447 }
448 
449 // -----------------------------------------------------------------------------
450 CamDevice *
451 CamDeviceAddon::Instantiate(CamRoster &roster, BUSBDevice *from)
452 {
453 	return NULL;
454 }
455 
456 // -----------------------------------------------------------------------------
457 void
458 CamDeviceAddon::SetSupportedDevices(const usb_named_support_descriptor *devs)
459 {
460 	fSupportedDevices = devs;
461 }
462 
463