1/*
2 * Copyright 2004-2008, Fran��ois Revol, <revol@free.fr>.
3 * Distributed under the terms of the MIT License.
4 */
5
6#include "SonixCamDevice.h"
7#include "CamDebug.h"
8#include "CamSensor.h"
9#include "CamBufferingDeframer.h"
10#include "CamStreamingDeframer.h"
11
12#include <ParameterWeb.h>
13#include <interface/Bitmap.h>
14#include <media/Buffer.h>
15
16const usb_webcam_support_descriptor kSupportedDevices[] = {
17{{ 0, 0, 0, 0x0c45, 0x6005 }, "Sonix", "Sonix", "tas5110c1b" }, // mine
18{{ 0, 0, 0, 0x0c45, 0x6007 }, "Sonix", "macally ICECAM", "tas5110c1b" }, // Rajah's cam - SN9C101R
19{{ 0, 0, 0, 0x0c45, 0x6009 }, "Trust", "spacec@m 120", NULL },
20{{ 0, 0, 0, 0x0c45, 0x600d }, "Trust", "spacec@m 120", NULL },
21
22/* other devices that should be supported,
23 * cf. sn9c102-1.15 linux driver, sn9c102_sensor.h
24 * for IDs and sensors
25 */
26{{ 0, 0, 0, 0x0c45, 0x6001 }, "Sonix", "Sonix generic", "tas5110c1b" },
27{{ 0, 0, 0, 0x0c45, 0x6024 }, "Sonix", "Sonix generic", NULL },
28{{ 0, 0, 0, 0x0c45, 0x6025 }, "Sonix", "Sonix generic", "tas5110c1b,XXX" },
29{{ 0, 0, 0, 0x0c45, 0x6028 }, "Sonix", "Sonix generic", NULL },
30{{ 0, 0, 0, 0x0c45, 0x6029 }, "Sonix", "Sonix generic", NULL },
31{{ 0, 0, 0, 0x0c45, 0x602a }, "Sonix", "Sonix generic", NULL },
32{{ 0, 0, 0, 0x0c45, 0x602b }, "Sonix", "Sonix generic", NULL },
33{{ 0, 0, 0, 0x0c45, 0x602c }, "Sonix", "Sonix generic", NULL },
34{{ 0, 0, 0, 0x0c45, 0x6030 }, "Sonix", "Sonix generic", NULL },
35{{ 0, 0, 0, 0x0c45, 0x6080 }, "Sonix", "Sonix generic", NULL },
36{{ 0, 0, 0, 0x0c45, 0x6082 }, "Sonix", "Sonix generic", NULL },
37{{ 0, 0, 0, 0x0c45, 0x6083 }, "Sonix", "Sonix generic", NULL },
38{{ 0, 0, 0, 0x0c45, 0x6088 }, "Sonix", "Sonix generic", NULL },
39{{ 0, 0, 0, 0x0c45, 0x608a }, "Sonix", "Sonix generic", NULL },
40{{ 0, 0, 0, 0x0c45, 0x608b }, "Sonix", "Sonix generic", NULL },
41{{ 0, 0, 0, 0x0c45, 0x608c }, "Sonix", "Sonix generic", NULL },
42{{ 0, 0, 0, 0x0c45, 0x608e }, "Sonix", "Sonix generic", NULL },
43{{ 0, 0, 0, 0x0c45, 0x608f }, "Sonix", "Sonix generic", NULL },
44{{ 0, 0, 0, 0x0c45, 0x60a0 }, "Sonix", "Sonix generic", NULL },
45{{ 0, 0, 0, 0x0c45, 0x60a2 }, "Sonix", "Sonix generic", NULL },
46{{ 0, 0, 0, 0x0c45, 0x60a3 }, "Sonix", "Sonix generic", NULL },
47{{ 0, 0, 0, 0x0c45, 0x60a8 }, "Sonix", "Sonix generic", NULL },
48{{ 0, 0, 0, 0x0c45, 0x60aa }, "Sonix", "Sonix generic", NULL },
49{{ 0, 0, 0, 0x0c45, 0x60ab }, "Sonix", "Sonix generic", "tas5110c1b" },
50{{ 0, 0, 0, 0x0c45, 0x60ac }, "Sonix", "Sonix generic", NULL },
51{{ 0, 0, 0, 0x0c45, 0x60ae }, "Sonix", "Sonix generic", NULL },
52{{ 0, 0, 0, 0x0c45, 0x60af }, "Sonix", "Sonix generic", NULL },
53{{ 0, 0, 0, 0x0c45, 0x60b0 }, "Sonix", "Sonix generic", NULL },
54{{ 0, 0, 0, 0x0c45, 0x60b2 }, "Sonix", "Sonix generic", NULL },
55{{ 0, 0, 0, 0x0c45, 0x60b3 }, "Sonix", "Sonix generic", NULL },
56{{ 0, 0, 0, 0x0c45, 0x60b8 }, "Sonix", "Sonix generic", NULL },
57{{ 0, 0, 0, 0x0c45, 0x60ba }, "Sonix", "Sonix generic", NULL },
58{{ 0, 0, 0, 0x0c45, 0x60bb }, "Sonix", "Sonix generic", NULL },
59{{ 0, 0, 0, 0x0c45, 0x60bc }, "Sonix", "Sonix generic", NULL },
60{{ 0, 0, 0, 0x0c45, 0x60be }, "Sonix", "Sonix generic", NULL },
61{{ 0, 0, 0, 0, 0}, NULL, NULL, NULL }
62};
63
64// 12 bytes actually
65static const uint8 sof_mark_1[] = { 0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x00 };
66static const uint8 sof_mark_2[] = { 0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01 };
67static const uint8 *sof_marks[] = { sof_mark_1, sof_mark_2 };
68
69static const uint8 eof_mark_1[] = { 0x00, 0x00, 0x00, 0x00 };
70static const uint8 eof_mark_2[] = { 0x40, 0x00, 0x00, 0x00 };
71static const uint8 eof_mark_3[] = { 0x80, 0x00, 0x00, 0x00 };
72static const uint8 eof_mark_4[] = { 0xc0, 0x00, 0x00, 0x00 };
73static const uint8 *eof_marks[] = { eof_mark_1, eof_mark_2, eof_mark_3, eof_mark_4 };
74
75void bayer2rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT);
76void bayer2rgb32le(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT);
77
78
79SonixCamDevice::SonixCamDevice(CamDeviceAddon &_addon, BUSBDevice* _device)
80          :CamDevice(_addon, _device)
81{
82	uchar data[8]; /* store bytes returned from sonix commands */
83	status_t err;
84	fFrameTagState = 0;
85
86	fRGain = fGGain = fBGain = 0;
87	// unknown
88	fBrightness = 0.5;
89
90	memset(fCachedRegs, 0, SN9C102_REG_COUNT);
91	fChipVersion = 2;
92	if ((GetDevice()->ProductID() & ~0x3F) == 0x6080) {
93		fChipVersion = 3; // says V4L2
94	}
95	err = ProbeSensor();
96
97//	fDeframer = new CamBufferingDeframer(this);
98	fDeframer = new CamStreamingDeframer(this);
99	fDeframer->RegisterSOFTags(sof_marks, 2, sizeof(sof_mark_1), 12);
100	fDeframer->RegisterEOFTags(eof_marks, 4, sizeof(eof_mark_1), sizeof(eof_mark_1));
101	SetDataInput(fDeframer);
102
103	/* init hw */
104
105	const BUSBConfiguration *config = GetDevice()->ConfigurationAt(0);
106	if (config) {
107		const BUSBInterface *inter = config->InterfaceAt(0);
108		uint32 i;
109
110		GetDevice()->SetConfiguration(config);
111
112		for (i = 0; inter && (i < inter->CountEndpoints()); i++) {
113			const BUSBEndpoint *e = inter->EndpointAt(i);
114			if (e && e->IsBulk() && e->IsInput()) {
115				fBulkIn = e;
116				PRINT((CH ": Using inter[0].endpoint[%d]; maxpktsz: %d" CT, i, e->MaxPacketSize()));
117				break;
118			}
119		}
120
121	}
122
123	/* sanity check */
124	err = ReadReg(SN9C102_ASIC_ID, data);
125	if (err < 0 || data[0] != 0x10) {
126		PRINT((CH ": BAD ASIC signature! (%u != %u)" CT, data[0], 0x10));
127		return;
128	}
129
130		//XXX: the XP driver sends this to the ICECAM... need to investigate.
131#if 1
132	uint8 tmp_3[] = {
133		0x44, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0xa0,
134		0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
135		0x00, 0x41, 0x09, 0x00, 0x16, 0x12, 0x60, 0x86,
136		0x3b, 0x0f, 0x0e, 0x06, 0x00, 0x00, 0x03 };
137	WriteReg(SN9C102_CHIP_CTRL, tmp_3, 0x1f);
138#endif
139		//XXX:DEBUG
140
141#if 0
142		//XXX: the XP driver sends all this... investigate.
143	uint8 tmp_1[] = {0x09, 0x44};
144	WriteReg(SN9C102_CHIP_CTRL, tmp_1, sizeof(tmp_1));
145	WriteReg8(SN9C102_CHIP_CTRL, 0x44);
146
147	WriteReg8(SN9C102_CLOCK_SEL /*0x17*/, 0x29);
148
149	uint8 tmp_2[] = {0x44, 0x44};
150	WriteReg(SN9C102_CHIP_CTRL, tmp_2, 2);
151		//URB_FUNCTION_VENDOR_INTERFACE:
152		//(USBD_TRANSFER_DIRECTION_OUT, ~USBD_SHORT_TRANSFER_OK)
153
154	uint8 tmp_3[] = {
155		0x44, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0xa0,
156		0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
157		0x00, 0x41, 0x09, 0x00, 0x16, 0x12, 0x60, 0x86,
158		0x3b, 0x0f, 0x0e, 0x06, 0x00, 0x00, 0x03 };
159	WriteReg(SN9C102_CHIP_CTRL, tmp_3, 0x1f);
160
161	uint8 tmp_4[] = {0x01, 0x01, 0x07, 0x06};
162	//WriteReg(SN9C102_AE_STRX, tmp_4, 4);
163
164	uint8 tmp_5[] = {0x14, 0x0f};
165	//WriteReg(SN9C102_H_SIZE, tmp_5, 2);
166
167	WriteReg8(SN9C102_SYNC_N_SCALE, 0x86);
168
169	WriteReg8(SN9C102_CHIP_CTRL, 0x44);	// again ??
170
171	uint8 tmp_6[] = { 0x60, 0x86 };
172	WriteReg(SN9C102_CLOCK_SEL /*0x17*/, tmp_6, 2);
173
174	WriteReg8(SN9C102_PIX_CLK, 0x2b);
175
176	// some IIC stuff for the sensor
177	uint8 tmp_7[] = { 0xb0, 0x61, 0x1c, 0xf8, 0x10, 0x00, 0x00, 0x16 };
178	//WriteReg(SN9C102_I2C_SETUP, tmp_7, 8);
179
180	WriteReg8(SN9C102_PIX_CLK, 0x4b);
181
182	uint8 tmp_8[] = { 0xa0, 0x61, 0x1c, 0x0f, 0x10, 0x00, 0x00, 0x16 };
183	//WriteReg(SN9C102_I2C_SETUP, tmp_8, 8);
184
185#endif
186#if 0
187	// some IIC stuff for the sensor
188	uint8 tmp_7[] = { 0xb0, 0x61, 0x1c, 0xf8, 0x10, 0x00, 0x00, 0x16 };
189	WriteReg(SN9C102_I2C_SETUP, tmp_7, 8);
190
191	WriteReg8(SN9C102_PIX_CLK, 0x4b);
192
193	uint8 tmp_8[] = { 0xa0, 0x61, 0x1c, 0x0f, 0x10, 0x00, 0x00, 0x16};
194	WriteReg(SN9C102_I2C_SETUP, tmp_8, 8);
195#endif
196
197	//WriteReg8(SN9C102_PIX_CLK, 0x4b);
198
199//###############
200
201	if (Sensor()) {
202		PRINT((CH ": CamSensor: %s" CT, Sensor()->Name()));
203		fInitStatus = Sensor()->Setup();
204
205		fVideoFrame = BRect(0, 0, Sensor()->MaxWidth()-1, Sensor()->MaxHeight()-1);
206//		SetVideoFrame(BRect(0, 0, Sensor()->MaxWidth()-1, Sensor()->MaxHeight()-1));
207//		SetVideoFrame(BRect(0, 0, 320-1, 240-1));
208	}
209	//SetScale(1);
210}
211
212
213SonixCamDevice::~SonixCamDevice()
214{
215	if (Sensor())
216		delete fSensor;
217	fSensor = NULL;
218}
219
220
221bool
222SonixCamDevice::SupportsBulk()
223{
224	return true;
225}
226
227
228bool
229SonixCamDevice::SupportsIsochronous()
230{
231	return true;
232}
233
234
235status_t
236SonixCamDevice::StartTransfer()
237{
238	status_t err;
239	uint8 r;
240
241	SetScale(1);
242	if (Sensor())
243		SetVideoFrame(fVideoFrame);
244
245	//SetVideoFrame(BRect(0, 0, 320-1, 240-1));
246
247DumpRegs();
248	err = ReadReg(SN9C102_CHIP_CTRL, &r, 1, true);
249	if (err < 0)
250		return err;
251	r |= 0x04;
252	err = WriteReg8(SN9C102_CHIP_CTRL, r);
253	if (err < 0)
254		return err;
255	return CamDevice::StartTransfer();
256}
257
258
259status_t
260SonixCamDevice::StopTransfer()
261{
262	status_t err;
263	uint8 r;
264
265DumpRegs();
266	err = CamDevice::StopTransfer();
267//	if (err < 0)
268//		return err;
269	err = ReadReg(SN9C102_CHIP_CTRL, &r, 1, true);
270	if (err < 0)
271		return err;
272	r &= ~0x04;
273	err = WriteReg8(SN9C102_CHIP_CTRL, r);
274	if (err < 0)
275		return err;
276	return err;
277}
278
279
280status_t
281SonixCamDevice::PowerOnSensor(bool on)
282{
283	if (OrReg8(SN9C102_CHIP_CTRL, on ? 0x01 : 0x00) < 0)
284		return EIO;
285	return B_OK;
286}
287
288
289ssize_t
290SonixCamDevice::WriteReg(uint16 address, uint8 *data, size_t count)
291{
292	PRINT((CH "(%u, @%p, %u)" CT, address, data, count));
293	status_t err;
294	if (address + count > SN9C102_REG_COUNT) {
295		PRINT((CH ": Invalid register range [%u;%u]" CT, address, address+count));
296		return EINVAL;
297	}
298	memcpy(&fCachedRegs[address], data, count);
299	err = SendCommand(USB_REQTYPE_DEVICE_OUT, 0x08, address, 0, count, data);
300	if (err < B_OK)
301		return err;
302	return count;
303}
304
305
306ssize_t
307SonixCamDevice::ReadReg(uint16 address, uint8 *data, size_t count, bool cached)
308{
309	PRINT((CH "(%u, @%p, %u, %d)" CT, address, data, count, cached));
310	status_t err;
311	if (address + count > SN9C102_REG_COUNT) {
312		PRINT((CH ": Invalid register range [%u;%u]" CT, address, address+count));
313		return EINVAL;
314	}
315	if (cached) {
316		memcpy(data, &fCachedRegs[address], count);
317		return count;
318	}
319	err = SendCommand(USB_REQTYPE_DEVICE_IN, 0x00, address, 0, count, data);
320	if (err < B_OK)
321		return err;
322	return count;
323}
324
325
326status_t
327SonixCamDevice::GetStatusIIC()
328{
329	status_t err;
330	uint8 status = 0;
331	err = ReadReg(SN9C102_I2C_SETUP, &status);
332	//dprintf(ID "i2c_status: error 0x%08lx, status = %02x\n", err, status);
333	if (err < 0)
334		return err;
335	return (status&0x08)?EIO:0;
336}
337
338
339status_t
340SonixCamDevice::WaitReadyIIC()
341{
342	status_t err;
343	uint8 status = 0;
344	int tries = 5;
345	if (!Sensor())
346		return B_NO_INIT;
347	while (tries--) {
348		err = ReadReg(SN9C102_I2C_SETUP, &status);
349		//dprintf(ID "i2c_wait_ready: error 0x%08lx, status = %02x\n", err, status);
350		if (err < 0) return err;
351		if (status & 0x04) return B_OK;
352		//XXX:FIXME:spin((1+5+11*dev->sensor->use_400kHz)*8);
353		snooze((1+5+11*Sensor()->Use400kHz())*8);
354	}
355	return EBUSY;
356}
357
358
359ssize_t
360SonixCamDevice::WriteIIC(uint8 address, uint8 *data, size_t count)
361{
362	status_t err;
363	uint8 buffer[8];
364	PRINT((CH "(%u, @%p, %u)" CT, address, data, count));
365
366	if (!Sensor())
367		return B_NO_INIT;
368	//dprintf(ID "sonix_i2c_write_multi(, %02x, %d, {%02x, %02x, %02x, %02x, %02x})\n", slave, count, d0, d1, d2, d3, d4);
369	count++; // includes address
370	if (count > 5)
371		return EINVAL;
372	buffer[0] = ((count) << 4) | (Sensor()->Use400kHz()?0x01:0)
373							 | (Sensor()->UseRealIIC()?0x80:0);
374	buffer[1] = Sensor()->IICWriteAddress();
375	buffer[2] = address;
376	memset(&buffer[3], 0, 5);
377	memcpy(&buffer[3], data, count-1);
378	buffer[7] = 0x16; /* V4L2 driver uses 0x10, XP driver uses 0x16 ? */
379	for (int i = 0; i < 8; i++) {
380		PRINT(("[%d] = %02x\n", i, buffer[i]));
381	}
382	err = WriteReg(SN9C102_I2C_SETUP, buffer, 8);
383	//dprintf(ID "sonix_i2c_write_multi: set_regs error 0x%08lx\n", err);
384	//PRINT((CH ": WriteReg: %s" CT, strerror(err)));
385	if (err < 0) return err;
386	err = WaitReadyIIC();
387	//dprintf(ID "sonix_i2c_write_multi: sonix_i2c_wait_ready error 0x%08lx\n", err);
388	//PRINT((CH ": Wait: %s" CT, strerror(err)));
389	if (err) return err;
390	err = GetStatusIIC();
391	//dprintf(ID "sonix_i2c_write_multi: sonix_i2c_status error 0x%08lx\n", err);
392	//PRINT((CH ": Status: %s" CT, strerror(err)));
393	if (err) return err;
394	//dprintf(ID "sonix_i2c_write_multi: succeeded\n");
395	PRINT((CH ": success" CT));
396	return B_OK;
397}
398
399
400ssize_t
401SonixCamDevice::ReadIIC(uint8 address, uint8 *data)
402{
403	status_t err, lasterr = B_OK;
404	uint8 buffer[8];
405	PRINT((CH "(%u, @%p)" CT, address, data));
406
407	if (!Sensor())
408		return B_NO_INIT;
409	//dprintf(ID "sonix_i2c_write_multi(, %02x, %d, {%02x, %02x, %02x, %02x, %02x})\n", slave, count, d0, d1, d2, d3, d4);
410	buffer[0] = (1 << 4) | (Sensor()->Use400kHz()?0x01:0)
411						| (Sensor()->UseRealIIC()?0x80:0);
412	buffer[1] = Sensor()->IICWriteAddress();
413	buffer[2] = address;
414	buffer[7] = 0x10; /* absolutely no idea why V4L2 driver use that value */
415	err = WriteReg(SN9C102_I2C_SETUP, buffer, 8);
416	//dprintf(ID "sonix_i2c_write_multi: set_regs error 0x%08lx\n", err);
417	if (err < 8) return EIO;
418	err = WaitReadyIIC();
419	//dprintf(ID "sonix_i2c_write_multi: sonix_i2c_wait_ready error 0x%08lx\n", err);
420	//if (err) return err;
421
422
423	//dprintf(ID "sonix_i2c_write_multi(, %02x, %d, {%02x, %02x, %02x, %02x, %02x})\n", slave, count, d0, d1, d2, d3, d4);
424	buffer[0] = (1 << 4) | (Sensor()->Use400kHz()?0x01:0)
425				  | 0x02 | (Sensor()->UseRealIIC()?0x80:0); /* read 1 byte */
426	buffer[1] = Sensor()->IICReadAddress();//IICWriteAddress
427	buffer[7] = 0x10; /* absolutely no idea why V4L2 driver use that value */
428	err = WriteReg(SN9C102_I2C_SETUP, buffer, 8);
429	//dprintf(ID "sonix_i2c_write_multi: set_regs error 0x%08lx\n", err);
430	if (err < 8) return EIO;
431	err = WaitReadyIIC();
432	//dprintf(ID "sonix_i2c_write_multi: sonix_i2c_wait_ready error 0x%08lx\n", err);
433	if (err < B_OK) return err;
434
435	err = ReadReg(SN9C102_I2C_DATA0, buffer, 5);
436	if (err < 5) return EIO;
437
438	err = GetStatusIIC();
439	//dprintf(ID "sonix_i2c_write_multi: sonix_i2c_status error 0x%08lx\n", err);
440	if (err < B_OK) return err;
441	//dprintf(ID "sonix_i2c_write_multi: succeeded\n");
442	if (lasterr) return err;
443
444	/* we should get what we want in buffer[4] according to the V4L2 driver...
445	 * probably because the 5 bytes are a bit shift register?
446	 */
447	*data = buffer[4];
448
449	return 1;
450}
451
452
453status_t
454SonixCamDevice::SetVideoFrame(BRect frame)
455{
456	uint16 x, y, width, height;
457	x = (uint16)frame.left;
458	y = (uint16)frame.top;
459	width = (uint16)(frame.right - frame.left + 1) / 16;
460	height = (uint16)(frame.bottom - frame.top + 1) / 16;
461	PRINT((CH "(%u, %u, %u, %u)" CT, x, y, width, height));
462
463	WriteReg8(SN9C102_H_START, x);
464	WriteReg8(SN9C102_V_START, y);
465	WriteReg8(SN9C102_H_SIZE, width);
466	WriteReg8(SN9C102_V_SIZE, height);
467	if (Sensor()) {
468		Sensor()->SetVideoFrame(frame);
469	}
470	return CamDevice::SetVideoFrame(frame);
471}
472
473
474status_t
475SonixCamDevice::SetScale(float scale)
476{
477	status_t err;
478	uint8 r;
479	int iscale = (int)scale;
480
481	PRINT((CH "(%u)" CT, iscale));
482	err = ReadReg(SN9C102_SYNC_N_SCALE, &r, 1, true);
483	if (err < 0)
484		return err;
485	r &= ~0x30;
486	switch (iscale) {
487	case 1:
488	case 2:
489	case 4:
490		r |= ((iscale-1) << 4);
491		break;
492	default:
493		return EINVAL;
494	}
495	err = WriteReg8(SN9C102_SYNC_N_SCALE, r);
496	return err;
497}
498
499
500status_t
501SonixCamDevice::SetVideoParams(float brightness, float contrast, float hue, float red, float green, float blue)
502{
503	return B_OK;
504}
505
506void
507SonixCamDevice::AddParameters(BParameterGroup *group, int32 &index)
508{
509	BParameterGroup *g;
510	BContinuousParameter *p;
511	CamDevice::AddParameters(group, index);
512
513	// R,G,B gains
514	g = group->MakeGroup("RGB gain");
515	p = g->MakeContinuousParameter(index++,
516		B_MEDIA_RAW_VIDEO, "RGB gain",
517		B_GAIN, "", 1.0, 1.0+(float)(SN9C102_RGB_GAIN_MAX)/8, (float)1.0/8);
518
519	p->SetChannelCount(3);
520#if 0
521	// Contrast - NON FUNCTIONAL
522	g = group->MakeGroup("Contrast");
523	p = g->MakeContinuousParameter(index++,
524		B_MEDIA_RAW_VIDEO, "Contrast",
525		B_GAIN, "", 0.0, 1.0, 1.0/256);
526
527	// Brightness - NON FUNCTIONAL
528	g = group->MakeGroup("Brightness");
529	p = g->MakeContinuousParameter(index++,
530		B_MEDIA_RAW_VIDEO, "Brightness",
531		B_GAIN, "", 0.0, 1.0, 1.0/256);
532
533#endif
534}
535
536status_t
537SonixCamDevice::GetParameterValue(int32 id, bigtime_t *last_change, void *value, size_t *size)
538{
539	float *gains;
540	switch (id - fFirstParameterID) {
541		case 0:
542			*size = 3 * sizeof(float);
543			gains = ((float *)value);
544			gains[0] = 1.0 + (float)fRGain / 8;
545			gains[1] = 1.0 + (float)fGGain / 8;
546			gains[2] = 1.0 + (float)fBGain / 8;
547			*last_change = fLastParameterChanges;
548			return B_OK;
549#if 0
550		case 1:
551			*size = sizeof(float);
552			gains = ((float *)value);
553			gains[0] = fContrast;
554			*last_change = fLastParameterChanges;
555			return B_OK;
556		case 2:
557			*size = sizeof(float);
558			gains = ((float *)value);
559			gains[0] = fBrightness;
560			*last_change = fLastParameterChanges;
561			return B_OK;
562#endif
563	}
564	return B_BAD_VALUE;
565}
566
567status_t
568SonixCamDevice::SetParameterValue(int32 id, bigtime_t when, const void *value, size_t size)
569{
570	float *gains;
571	switch (id - fFirstParameterID) {
572		case 0:
573			if (!value || (size != 3 * sizeof(float)))
574				return B_BAD_VALUE;
575			gains = ((float *)value);
576			if ((gains[0] == 1.0 + (float)fRGain / 8)
577				&& (gains[1] == 1.0 + (float)fGGain / 8)
578				&& (gains[2] == 1.0 + (float)fBGain / 8))
579				return B_OK;
580
581			fRGain = (int)(8 * (gains[0] - 1.0)) & SN9C102_RGB_GAIN_MAX;
582			fGGain = (int)(8 * (gains[1] - 1.0)) & SN9C102_RGB_GAIN_MAX;
583			fBGain = (int)(8 * (gains[2] - 1.0)) & SN9C102_RGB_GAIN_MAX;
584			fLastParameterChanges = when;
585			PRINT((CH ": gain: %d,%d,%d" CT, fRGain, fGGain, fBGain));
586			//WriteReg8(SN9C102_R_B_GAIN, (fBGain << 4) | fRGain);	/* red, blue gain = 1+0/8 = 1 */
587			/* Datasheet says:
588			 * reg 0x10 [0:3] is rgain, [4:7] is bgain and 0x11 [0:3] is ggain
589			 * according to sn9c102-1.15 linux driver it's wrong for reg 0x10,
590			 * but it doesn't seem to work any better for a rev 2 chip.
591			 * XXX
592			 */
593#if 1
594			WriteReg8(SN9C102_R_GAIN, fRGain);
595			WriteReg8(SN9C102_B_GAIN, fBGain);
596			if (fChipVersion >= 3)
597				WriteReg8(SN9C103_G_GAIN, fGGain);
598			else
599				WriteReg8(SN9C102_G_GAIN, (fGGain / 16));
600#endif
601#if 0
602			uint8 buf[2];
603			buf[0] = (fBGain << 4) | fRGain;
604			buf[1] = fGGain;
605			WriteReg(SN9C102_R_B_GAIN, buf, 2);
606#endif
607			return B_OK;
608#if 0
609		case 1:
610			if (!value || (size != sizeof(float)))
611				return B_BAD_VALUE;
612			gains = ((float *)value);
613			fContrast = gains[0];
614			WriteReg8(SN9C10x_CONTRAST, ((uint8)(fContrast * 256)));
615			return B_OK;
616		case 2:
617			if (!value || (size != sizeof(float)))
618				return B_BAD_VALUE;
619			gains = ((float *)value);
620			fBrightness = gains[0];
621			// it actually ends up writing to SN9C102_V_SIZE...
622			WriteReg8(SN9C10x_BRIGHTNESS, ((uint8)(fBrightness * 256)));
623
624			return B_OK;
625#endif
626	}
627	return B_BAD_VALUE;
628}
629
630
631
632size_t
633SonixCamDevice::MinRawFrameSize()
634{
635	// if (fCompressionEnabled) { ... return ; }
636	BRect vf(VideoFrame());
637	size_t w = vf.IntegerWidth()+1;
638	size_t h = vf.IntegerHeight()+1;
639	// 1 byte/pixel
640	return w * h;
641}
642
643
644size_t
645SonixCamDevice::MaxRawFrameSize()
646{
647	// if (fCompressionEnabled) { ... return ; }
648	return MinRawFrameSize()+1024*0; // fixed size frame (uncompressed)
649}
650
651
652bool
653SonixCamDevice::ValidateStartOfFrameTag(const uint8 *tag, size_t taglen)
654{
655	// SOF come with an 00, 40, 80, C0 sequence,
656	// supposedly corresponding with an equal byte in the end tag
657	fFrameTagState = tag[7] & 0xC0;
658	PRINT((CH "(, %d) state %x" CT, taglen, fFrameTagState));
659
660	// which seems to be the same as of the EOF tag
661	return true;
662}
663
664
665bool
666SonixCamDevice::ValidateEndOfFrameTag(const uint8 *tag, size_t taglen, size_t datalen)
667{
668	//PRINT((CH "(, %d) %x == %x" CT, taglen, (tag[0] & 0xC0), fFrameTagState));
669	// make sure the tag corresponds to the SOF we refer to
670	if ((tag[0] & 0xC0) != fFrameTagState) {
671		PRINT((CH ": discarded EOF %x != %x" CT, fFrameTagState, tag[0] & 0xC0));
672		return false;
673	}
674	//PRINT((CH ": validated EOF %x, len %d" CT, fFrameTagState, datalen));
675	return true;
676}
677
678
679status_t
680SonixCamDevice::GetFrameBitmap(BBitmap **bm, bigtime_t *stamp /* = NULL */)
681{
682	BBitmap *b;
683	CamFrame *f;
684	status_t err;
685	PRINT((CH "()" CT));
686	err = fDeframer->WaitFrame(200000);
687	if (err < B_OK) { PRINT((CH ": WaitFrame: %s" CT, strerror(err))); }
688	if (err < B_OK)
689		return err;
690	err = fDeframer->GetFrame(&f, stamp);
691	if (err < B_OK) { PRINT((CH ": GetFrame: %s" CT, strerror(err))); }
692	if (err < B_OK)
693		return err;
694	PRINT((CH ": VideoFrame = %fx%f,%fx%f" CT, VideoFrame().left, VideoFrame().top, VideoFrame().right, VideoFrame().bottom));
695
696	long int w = (long)(VideoFrame().right - VideoFrame().left + 1);
697	long int h = (long)(VideoFrame().bottom - VideoFrame().top + 1);
698	b = new BBitmap(VideoFrame().OffsetToSelf(0,0), 0, B_RGB32, w*4);
699	PRINT((CH ": Frame: %dx%d" CT, w, h));
700
701	bayer2rgb24((unsigned char *)b->Bits(), (unsigned char *)f->Buffer(), w, h);
702
703	PRINT((CH ": got 1 frame (len %d)" CT, b->BitsLength()));
704	*bm = b;
705	return B_OK;
706}
707
708
709status_t
710SonixCamDevice::FillFrameBuffer(BBuffer *buffer, bigtime_t *stamp)
711{
712	CamFrame *f;
713	status_t err;
714	PRINT((CH "()" CT));
715
716	memset(buffer->Data(), 0, buffer->SizeAvailable());
717	err = fDeframer->WaitFrame(2000000);
718	if (err < B_OK) { PRINT((CH ": WaitFrame: %s" CT, strerror(err))); }
719	if (err < B_OK)
720		return err;
721
722	err = fDeframer->GetFrame(&f, stamp);
723	if (err < B_OK) { PRINT((CH ": GetFrame: %s" CT, strerror(err))); }
724	if (err < B_OK)
725		return err;
726
727	long int w = (long)(VideoFrame().right - VideoFrame().left + 1);
728	long int h = (long)(VideoFrame().bottom - VideoFrame().top + 1);
729	PRINT((CH ": VideoFrame = %fx%f,%fx%f Frame: %dx%d" CT, VideoFrame().left, VideoFrame().top, VideoFrame().right, VideoFrame().bottom, w, h));
730
731	if (buffer->SizeAvailable() >= (size_t)w*h*4)
732		bayer2rgb32le((unsigned char *)buffer->Data(), (unsigned char *)f->Buffer(), w, h);
733
734	delete f;
735
736	PRINT((CH ": available %d, required %d" CT, buffer->SizeAvailable(), w*h*4));
737	if (buffer->SizeAvailable() < (size_t)w*h*4)
738		return E2BIG;
739	PRINT((CH ": got 1 frame (len %d)" CT, buffer->SizeUsed()));
740	return B_OK;
741}
742
743
744void
745/* DEBUG: dump the SN regs */
746SonixCamDevice::DumpRegs()
747{
748	uint8 regs[SN9C102_REG_COUNT];
749	status_t err;
750
751	//err = sonix_get_regs(dev, SN_ASIC_ID, regs, SN_REG_COUNT);
752	err = ReadReg(0, regs, SN9C102_REG_COUNT);
753	if (err < 0)
754		return;
755	printf("REG1: %02x %02x %02x %02x  %02x %02x %02x %02x\n",
756			regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6], regs[7]);
757	printf("   2: %02x %02x %02x %02x  %02x %02x %02x %02x\n",
758			regs[8], regs[9], regs[10], regs[11], regs[12], regs[13], regs[14], regs[15]);
759	printf("   3: %02x %02x %02x %02x  %02x %02x %02x %02x\n",
760			regs[16], regs[17], regs[18], regs[19], regs[20], regs[21], regs[22], regs[23]);
761	printf("   4: %02x %02x %02x %02x  %02x %02x %02x %02x\n",
762			regs[24], regs[25], regs[26], regs[27], regs[28], regs[29], regs[30], regs[31]);
763}
764
765#if 0
766
767status_t
768SonixCamDevice::SendCommand(uint8 dir, uint8 request, uint16 value,
769							uint16 index, uint16 length, void* data)
770{
771	size_t ret;
772	if (!GetDevice())
773		return ENODEV;
774	if (length > GetDevice()->MaxEndpoint0PacketSize())
775		return EINVAL;
776	ret = GetDevice()->ControlTransfer(
777				USB_REQTYPE_VENDOR | USB_REQTYPE_INTERFACE_OUT | dir,
778				request, value, index, length, data);
779	return ret;
780}
781#endif
782
783
784SonixCamDeviceAddon::SonixCamDeviceAddon(WebCamMediaAddOn* webcam)
785	: CamDeviceAddon(webcam)
786{
787	SetSupportedDevices(kSupportedDevices);
788}
789
790
791SonixCamDeviceAddon::~SonixCamDeviceAddon()
792{
793}
794
795
796const char *
797SonixCamDeviceAddon::BrandName()
798{
799	return "Sonix";
800}
801
802
803SonixCamDevice *
804SonixCamDeviceAddon::Instantiate(CamRoster &roster, BUSBDevice *from)
805{
806	return new SonixCamDevice(*this, from);
807}
808
809extern "C" status_t
810B_WEBCAM_MKINTFUNC(sonix)
811(WebCamMediaAddOn* webcam, CamDeviceAddon **addon)
812{
813	*addon = new SonixCamDeviceAddon(webcam);
814	return B_OK;
815}
816
817// XXX: REMOVE ME
818
819
820
821/*
822 * BAYER2RGB24 ROUTINE TAKEN FROM:
823 *
824 * Sonix SN9C101 based webcam basic I/F routines
825 * Copyright (C) 2004 Takafumi Mizuno <taka-qce@ls-a.jp>
826 *
827 * Redistribution and use in source and binary forms, with or without
828 * modification, are permitted provided that the following conditions
829 * are met:
830 * 1. Redistributions of source code must retain the above copyright
831 *    notice, this list of conditions and the following disclaimer.
832 * 2. Redistributions in binary form must reproduce the above copyright
833 *    notice, this list of conditions and the following disclaimer in the
834 *    documentation and/or other materials provided with the distribution.
835 *
836 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
837 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
838 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
839 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
840 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
841 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
842 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
843 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
844 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
845 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
846 * SUCH DAMAGE.
847 */
848
849void bayer2rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT)
850{
851    long int i;
852    unsigned char *rawpt, *scanpt;
853    long int size;
854
855    rawpt = src;
856    scanpt = dst;
857    size = WIDTH*HEIGHT;
858
859    for ( i = 0; i < size; i++ ) {
860	if ( (i/WIDTH) % 2 == 0 ) {
861	    if ( (i % 2) == 0 ) {
862		/* B */
863		if ( (i > WIDTH) && ((i % WIDTH) > 0) ) {
864		    *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
865				 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4;	/* R */
866		    *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
867				 *(rawpt+WIDTH)+*(rawpt-WIDTH))/4;	/* G */
868		    *scanpt++ = *rawpt;					/* B */
869		} else {
870		    /* first line or left column */
871		    *scanpt++ = *(rawpt+WIDTH+1);		/* R */
872		    *scanpt++ = (*(rawpt+1)+*(rawpt+WIDTH))/2;	/* G */
873		    *scanpt++ = *rawpt;				/* B */
874		}
875	    } else {
876		/* (B)G */
877		if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) ) {
878		    *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2;	/* R */
879		    *scanpt++ = *rawpt;					/* G */
880		    *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2;		/* B */
881		} else {
882		    /* first line or right column */
883		    *scanpt++ = *(rawpt+WIDTH);	/* R */
884		    *scanpt++ = *rawpt;		/* G */
885		    *scanpt++ = *(rawpt-1);	/* B */
886		}
887	    }
888	} else {
889	    if ( (i % 2) == 0 ) {
890		/* G(R) */
891		if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) ) {
892		    *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2;		/* R */
893		    *scanpt++ = *rawpt;					/* G */
894		    *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2;	/* B */
895		} else {
896		    /* bottom line or left column */
897		    *scanpt++ = *(rawpt+1);		/* R */
898		    *scanpt++ = *rawpt;			/* G */
899		    *scanpt++ = *(rawpt-WIDTH);		/* B */
900		}
901	    } else {
902		/* R */
903		if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) ) {
904		    *scanpt++ = *rawpt;					/* R */
905		    *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
906				 *(rawpt-WIDTH)+*(rawpt+WIDTH))/4;	/* G */
907		    *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
908				 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4;	/* B */
909		} else {
910		    /* bottom line or right column */
911		    *scanpt++ = *rawpt;				/* R */
912		    *scanpt++ = (*(rawpt-1)+*(rawpt-WIDTH))/2;	/* G */
913		    *scanpt++ = *(rawpt-WIDTH-1);		/* B */
914		}
915	    }
916	}
917	rawpt++;
918    }
919
920}
921
922/* modified bayer2rgb24 to output rgb-32 little endian (B_RGB32)
923 * Fran��ois Revol
924 */
925
926void bayer2rgb32le(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT)
927{
928    long int i;
929    unsigned char *rawpt, *scanpt;
930    long int size;
931
932    rawpt = src;
933    scanpt = dst;
934    size = WIDTH*HEIGHT;
935
936    for ( i = 0; i < size; i++ ) {
937	if ( (i/WIDTH) % 2 == 0 ) {
938	    if ( (i % 2) == 0 ) {
939		/* B */
940		if ( (i > WIDTH) && ((i % WIDTH) > 0) ) {
941		    *scanpt++ = *rawpt;					/* B */
942		    *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
943				 *(rawpt+WIDTH)+*(rawpt-WIDTH))/4;	/* G */
944		    *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
945				 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4;	/* R */
946		} else {
947		    /* first line or left column */
948		    *scanpt++ = *rawpt;				/* B */
949		    *scanpt++ = (*(rawpt+1)+*(rawpt+WIDTH))/2;	/* G */
950		    *scanpt++ = *(rawpt+WIDTH+1);		/* R */
951		}
952	    } else {
953		/* (B)G */
954		if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) ) {
955		    *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2;		/* B */
956		    *scanpt++ = *rawpt;					/* G */
957		    *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2;	/* R */
958		} else {
959		    /* first line or right column */
960		    *scanpt++ = *(rawpt-1);	/* B */
961		    *scanpt++ = *rawpt;		/* G */
962		    *scanpt++ = *(rawpt+WIDTH);	/* R */
963		}
964	    }
965	} else {
966	    if ( (i % 2) == 0 ) {
967		/* G(R) */
968		if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) ) {
969		    *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2;	/* B */
970		    *scanpt++ = *rawpt;					/* G */
971		    *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2;		/* R */
972		} else {
973		    /* bottom line or left column */
974		    *scanpt++ = *(rawpt-WIDTH);		/* B */
975		    *scanpt++ = *rawpt;			/* G */
976		    *scanpt++ = *(rawpt+1);		/* R */
977		}
978	    } else {
979		/* R */
980		if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) ) {
981		    *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
982				 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4;	/* B */
983		    *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
984				 *(rawpt-WIDTH)+*(rawpt+WIDTH))/4;	/* G */
985		    *scanpt++ = *rawpt;					/* R */
986		} else {
987		    /* bottom line or right column */
988		    *scanpt++ = *(rawpt-WIDTH-1);		/* B */
989		    *scanpt++ = (*(rawpt-1)+*(rawpt-WIDTH))/2;	/* G */
990		    *scanpt++ = *rawpt;				/* R */
991		}
992	    }
993	}
994	rawpt++;
995	scanpt++;
996    }
997
998}
999