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
16 const 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
65 static const uint8 sof_mark_1[] = { 0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x00 };
66 static const uint8 sof_mark_2[] = { 0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01 };
67 static const uint8 *sof_marks[] = { sof_mark_1, sof_mark_2 };
68
69 static const uint8 eof_mark_1[] = { 0x00, 0x00, 0x00, 0x00 };
70 static const uint8 eof_mark_2[] = { 0x40, 0x00, 0x00, 0x00 };
71 static const uint8 eof_mark_3[] = { 0x80, 0x00, 0x00, 0x00 };
72 static const uint8 eof_mark_4[] = { 0xc0, 0x00, 0x00, 0x00 };
73 static const uint8 *eof_marks[] = { eof_mark_1, eof_mark_2, eof_mark_3, eof_mark_4 };
74
75 void bayer2rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT);
76 void bayer2rgb32le(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT);
77
78
SonixCamDevice(CamDeviceAddon & _addon,BUSBDevice * _device)79 SonixCamDevice::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
~SonixCamDevice()213 SonixCamDevice::~SonixCamDevice()
214 {
215 if (Sensor())
216 delete fSensor;
217 fSensor = NULL;
218 }
219
220
221 bool
SupportsBulk()222 SonixCamDevice::SupportsBulk()
223 {
224 return true;
225 }
226
227
228 bool
SupportsIsochronous()229 SonixCamDevice::SupportsIsochronous()
230 {
231 return true;
232 }
233
234
235 status_t
StartTransfer()236 SonixCamDevice::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
247 DumpRegs();
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
259 status_t
StopTransfer()260 SonixCamDevice::StopTransfer()
261 {
262 status_t err;
263 uint8 r;
264
265 DumpRegs();
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
280 status_t
PowerOnSensor(bool on)281 SonixCamDevice::PowerOnSensor(bool on)
282 {
283 if (OrReg8(SN9C102_CHIP_CTRL, on ? 0x01 : 0x00) < 0)
284 return EIO;
285 return B_OK;
286 }
287
288
289 ssize_t
WriteReg(uint16 address,uint8 * data,size_t count)290 SonixCamDevice::WriteReg(uint16 address, uint8 *data, size_t count)
291 {
292 PRINT((CH "(%u, @%p, %" B_PRIuSIZE ")" CT, address, data, count));
293 status_t err;
294 if (address + count > SN9C102_REG_COUNT) {
295 PRINT((CH ": Invalid register range [%u;%" B_PRIuSIZE "]" CT, address,
296 address + count));
297 return EINVAL;
298 }
299 memcpy(&fCachedRegs[address], data, count);
300 err = SendCommand(USB_REQTYPE_DEVICE_OUT, 0x08, address, 0, count, data);
301 if (err < B_OK)
302 return err;
303 return count;
304 }
305
306
307 ssize_t
ReadReg(uint16 address,uint8 * data,size_t count,bool cached)308 SonixCamDevice::ReadReg(uint16 address, uint8 *data, size_t count, bool cached)
309 {
310 PRINT((CH "(%u, @%p, %" B_PRIuSIZE ", %d)" CT, address, data, count,
311 cached));
312 status_t err;
313 if (address + count > SN9C102_REG_COUNT) {
314 PRINT((CH ": Invalid register range [%u;%" B_PRIuSIZE "]" CT, address,
315 address + count));
316 return EINVAL;
317 }
318 if (cached) {
319 memcpy(data, &fCachedRegs[address], count);
320 return count;
321 }
322 err = SendCommand(USB_REQTYPE_DEVICE_IN, 0x00, address, 0, count, data);
323 if (err < B_OK)
324 return err;
325 return count;
326 }
327
328
329 status_t
GetStatusIIC()330 SonixCamDevice::GetStatusIIC()
331 {
332 status_t err;
333 uint8 status = 0;
334 err = ReadReg(SN9C102_I2C_SETUP, &status);
335 //dprintf(ID "i2c_status: error 0x%08lx, status = %02x\n", err, status);
336 if (err < 0)
337 return err;
338 return (status&0x08)?EIO:0;
339 }
340
341
342 status_t
WaitReadyIIC()343 SonixCamDevice::WaitReadyIIC()
344 {
345 status_t err;
346 uint8 status = 0;
347 int tries = 5;
348 if (!Sensor())
349 return B_NO_INIT;
350 while (tries--) {
351 err = ReadReg(SN9C102_I2C_SETUP, &status);
352 //dprintf(ID "i2c_wait_ready: error 0x%08lx, status = %02x\n", err, status);
353 if (err < 0) return err;
354 if (status & 0x04) return B_OK;
355 //XXX:FIXME:spin((1+5+11*dev->sensor->use_400kHz)*8);
356 snooze((1+5+11*Sensor()->Use400kHz())*8);
357 }
358 return EBUSY;
359 }
360
361
362 ssize_t
WriteIIC(uint8 address,uint8 * data,size_t count)363 SonixCamDevice::WriteIIC(uint8 address, uint8 *data, size_t count)
364 {
365 status_t err;
366 uint8 buffer[8];
367 PRINT((CH "(%u, @%p, %" B_PRIuSIZE ")" CT, address, data, count));
368
369 if (!Sensor())
370 return B_NO_INIT;
371 //dprintf(ID "sonix_i2c_write_multi(, %02x, %d, {%02x, %02x, %02x, %02x, %02x})\n", slave, count, d0, d1, d2, d3, d4);
372 count++; // includes address
373 if (count > 5)
374 return EINVAL;
375 buffer[0] = ((count) << 4) | (Sensor()->Use400kHz()?0x01:0)
376 | (Sensor()->UseRealIIC()?0x80:0);
377 buffer[1] = Sensor()->IICWriteAddress();
378 buffer[2] = address;
379 memset(&buffer[3], 0, 5);
380 memcpy(&buffer[3], data, count-1);
381 buffer[7] = 0x16; /* V4L2 driver uses 0x10, XP driver uses 0x16 ? */
382 for (int i = 0; i < 8; i++) {
383 PRINT(("[%d] = %02x\n", i, buffer[i]));
384 }
385 err = WriteReg(SN9C102_I2C_SETUP, buffer, 8);
386 //dprintf(ID "sonix_i2c_write_multi: set_regs error 0x%08lx\n", err);
387 //PRINT((CH ": WriteReg: %s" CT, strerror(err)));
388 if (err < 0) return err;
389 err = WaitReadyIIC();
390 //dprintf(ID "sonix_i2c_write_multi: sonix_i2c_wait_ready error 0x%08lx\n", err);
391 //PRINT((CH ": Wait: %s" CT, strerror(err)));
392 if (err) return err;
393 err = GetStatusIIC();
394 //dprintf(ID "sonix_i2c_write_multi: sonix_i2c_status error 0x%08lx\n", err);
395 //PRINT((CH ": Status: %s" CT, strerror(err)));
396 if (err) return err;
397 //dprintf(ID "sonix_i2c_write_multi: succeeded\n");
398 PRINT((CH ": success" CT));
399 return B_OK;
400 }
401
402
403 ssize_t
ReadIIC(uint8 address,uint8 * data)404 SonixCamDevice::ReadIIC(uint8 address, uint8 *data)
405 {
406 status_t err, lasterr = B_OK;
407 uint8 buffer[8];
408 PRINT((CH "(%u, @%p)" CT, address, data));
409
410 if (!Sensor())
411 return B_NO_INIT;
412 //dprintf(ID "sonix_i2c_write_multi(, %02x, %d, {%02x, %02x, %02x, %02x, %02x})\n", slave, count, d0, d1, d2, d3, d4);
413 buffer[0] = (1 << 4) | (Sensor()->Use400kHz()?0x01:0)
414 | (Sensor()->UseRealIIC()?0x80:0);
415 buffer[1] = Sensor()->IICWriteAddress();
416 buffer[2] = address;
417 buffer[7] = 0x10; /* absolutely no idea why V4L2 driver use that value */
418 err = WriteReg(SN9C102_I2C_SETUP, buffer, 8);
419 //dprintf(ID "sonix_i2c_write_multi: set_regs error 0x%08lx\n", err);
420 if (err < 8) return EIO;
421 err = WaitReadyIIC();
422 //dprintf(ID "sonix_i2c_write_multi: sonix_i2c_wait_ready error 0x%08lx\n", err);
423 //if (err) return err;
424
425
426 //dprintf(ID "sonix_i2c_write_multi(, %02x, %d, {%02x, %02x, %02x, %02x, %02x})\n", slave, count, d0, d1, d2, d3, d4);
427 buffer[0] = (1 << 4) | (Sensor()->Use400kHz()?0x01:0)
428 | 0x02 | (Sensor()->UseRealIIC()?0x80:0); /* read 1 byte */
429 buffer[1] = Sensor()->IICReadAddress();//IICWriteAddress
430 buffer[7] = 0x10; /* absolutely no idea why V4L2 driver use that value */
431 err = WriteReg(SN9C102_I2C_SETUP, buffer, 8);
432 //dprintf(ID "sonix_i2c_write_multi: set_regs error 0x%08lx\n", err);
433 if (err < 8) return EIO;
434 err = WaitReadyIIC();
435 //dprintf(ID "sonix_i2c_write_multi: sonix_i2c_wait_ready error 0x%08lx\n", err);
436 if (err < B_OK) return err;
437
438 err = ReadReg(SN9C102_I2C_DATA0, buffer, 5);
439 if (err < 5) return EIO;
440
441 err = GetStatusIIC();
442 //dprintf(ID "sonix_i2c_write_multi: sonix_i2c_status error 0x%08lx\n", err);
443 if (err < B_OK) return err;
444 //dprintf(ID "sonix_i2c_write_multi: succeeded\n");
445 if (lasterr) return err;
446
447 /* we should get what we want in buffer[4] according to the V4L2 driver...
448 * probably because the 5 bytes are a bit shift register?
449 */
450 *data = buffer[4];
451
452 return 1;
453 }
454
455
456 status_t
SetVideoFrame(BRect frame)457 SonixCamDevice::SetVideoFrame(BRect frame)
458 {
459 uint16 x, y, width, height;
460 x = (uint16)frame.left;
461 y = (uint16)frame.top;
462 width = (uint16)(frame.right - frame.left + 1) / 16;
463 height = (uint16)(frame.bottom - frame.top + 1) / 16;
464 PRINT((CH "(%u, %u, %u, %u)" CT, x, y, width, height));
465
466 WriteReg8(SN9C102_H_START, x);
467 WriteReg8(SN9C102_V_START, y);
468 WriteReg8(SN9C102_H_SIZE, width);
469 WriteReg8(SN9C102_V_SIZE, height);
470 if (Sensor()) {
471 Sensor()->SetVideoFrame(frame);
472 }
473 return CamDevice::SetVideoFrame(frame);
474 }
475
476
477 status_t
SetScale(float scale)478 SonixCamDevice::SetScale(float scale)
479 {
480 status_t err;
481 uint8 r;
482 int iscale = (int)scale;
483
484 PRINT((CH "(%u)" CT, iscale));
485 err = ReadReg(SN9C102_SYNC_N_SCALE, &r, 1, true);
486 if (err < 0)
487 return err;
488 r &= ~0x30;
489 switch (iscale) {
490 case 1:
491 case 2:
492 case 4:
493 r |= ((iscale-1) << 4);
494 break;
495 default:
496 return EINVAL;
497 }
498 err = WriteReg8(SN9C102_SYNC_N_SCALE, r);
499 return err;
500 }
501
502
503 status_t
SetVideoParams(float brightness,float contrast,float hue,float red,float green,float blue)504 SonixCamDevice::SetVideoParams(float brightness, float contrast, float hue, float red, float green, float blue)
505 {
506 return B_OK;
507 }
508
509 void
AddParameters(BParameterGroup * group,int32 & index)510 SonixCamDevice::AddParameters(BParameterGroup *group, int32 &index)
511 {
512 BParameterGroup *g;
513 BContinuousParameter *p;
514 CamDevice::AddParameters(group, index);
515
516 // R,G,B gains
517 g = group->MakeGroup("RGB gain");
518 p = g->MakeContinuousParameter(index++,
519 B_MEDIA_RAW_VIDEO, "RGB gain",
520 B_GAIN, "", 1.0, 1.0+(float)(SN9C102_RGB_GAIN_MAX)/8, (float)1.0/8);
521
522 p->SetChannelCount(3);
523 #if 0
524 // Contrast - NON FUNCTIONAL
525 g = group->MakeGroup("Contrast");
526 p = g->MakeContinuousParameter(index++,
527 B_MEDIA_RAW_VIDEO, "Contrast",
528 B_GAIN, "", 0.0, 1.0, 1.0/256);
529
530 // Brightness - NON FUNCTIONAL
531 g = group->MakeGroup("Brightness");
532 p = g->MakeContinuousParameter(index++,
533 B_MEDIA_RAW_VIDEO, "Brightness",
534 B_GAIN, "", 0.0, 1.0, 1.0/256);
535
536 #endif
537 }
538
539 status_t
GetParameterValue(int32 id,bigtime_t * last_change,void * value,size_t * size)540 SonixCamDevice::GetParameterValue(int32 id, bigtime_t *last_change, void *value, size_t *size)
541 {
542 float *gains;
543 switch (id - fFirstParameterID) {
544 case 0:
545 *size = 3 * sizeof(float);
546 gains = ((float *)value);
547 gains[0] = 1.0 + (float)fRGain / 8;
548 gains[1] = 1.0 + (float)fGGain / 8;
549 gains[2] = 1.0 + (float)fBGain / 8;
550 *last_change = fLastParameterChanges;
551 return B_OK;
552 #if 0
553 case 1:
554 *size = sizeof(float);
555 gains = ((float *)value);
556 gains[0] = fContrast;
557 *last_change = fLastParameterChanges;
558 return B_OK;
559 case 2:
560 *size = sizeof(float);
561 gains = ((float *)value);
562 gains[0] = fBrightness;
563 *last_change = fLastParameterChanges;
564 return B_OK;
565 #endif
566 }
567 return B_BAD_VALUE;
568 }
569
570 status_t
SetParameterValue(int32 id,bigtime_t when,const void * value,size_t size)571 SonixCamDevice::SetParameterValue(int32 id, bigtime_t when, const void *value, size_t size)
572 {
573 float *gains;
574 switch (id - fFirstParameterID) {
575 case 0:
576 if (!value || (size != 3 * sizeof(float)))
577 return B_BAD_VALUE;
578 gains = ((float *)value);
579 if ((gains[0] == 1.0 + (float)fRGain / 8)
580 && (gains[1] == 1.0 + (float)fGGain / 8)
581 && (gains[2] == 1.0 + (float)fBGain / 8))
582 return B_OK;
583
584 fRGain = (int)(8 * (gains[0] - 1.0)) & SN9C102_RGB_GAIN_MAX;
585 fGGain = (int)(8 * (gains[1] - 1.0)) & SN9C102_RGB_GAIN_MAX;
586 fBGain = (int)(8 * (gains[2] - 1.0)) & SN9C102_RGB_GAIN_MAX;
587 fLastParameterChanges = when;
588 PRINT((CH ": gain: %d,%d,%d" CT, fRGain, fGGain, fBGain));
589 //WriteReg8(SN9C102_R_B_GAIN, (fBGain << 4) | fRGain); /* red, blue gain = 1+0/8 = 1 */
590 /* Datasheet says:
591 * reg 0x10 [0:3] is rgain, [4:7] is bgain and 0x11 [0:3] is ggain
592 * according to sn9c102-1.15 linux driver it's wrong for reg 0x10,
593 * but it doesn't seem to work any better for a rev 2 chip.
594 * XXX
595 */
596 #if 1
597 WriteReg8(SN9C102_R_GAIN, fRGain);
598 WriteReg8(SN9C102_B_GAIN, fBGain);
599 if (fChipVersion >= 3)
600 WriteReg8(SN9C103_G_GAIN, fGGain);
601 else
602 WriteReg8(SN9C102_G_GAIN, (fGGain / 16));
603 #endif
604 #if 0
605 uint8 buf[2];
606 buf[0] = (fBGain << 4) | fRGain;
607 buf[1] = fGGain;
608 WriteReg(SN9C102_R_B_GAIN, buf, 2);
609 #endif
610 return B_OK;
611 #if 0
612 case 1:
613 if (!value || (size != sizeof(float)))
614 return B_BAD_VALUE;
615 gains = ((float *)value);
616 fContrast = gains[0];
617 WriteReg8(SN9C10x_CONTRAST, ((uint8)(fContrast * 256)));
618 return B_OK;
619 case 2:
620 if (!value || (size != sizeof(float)))
621 return B_BAD_VALUE;
622 gains = ((float *)value);
623 fBrightness = gains[0];
624 // it actually ends up writing to SN9C102_V_SIZE...
625 WriteReg8(SN9C10x_BRIGHTNESS, ((uint8)(fBrightness * 256)));
626
627 return B_OK;
628 #endif
629 }
630 return B_BAD_VALUE;
631 }
632
633
634
635 size_t
MinRawFrameSize()636 SonixCamDevice::MinRawFrameSize()
637 {
638 // if (fCompressionEnabled) { ... return ; }
639 BRect vf(VideoFrame());
640 size_t w = vf.IntegerWidth()+1;
641 size_t h = vf.IntegerHeight()+1;
642 // 1 byte/pixel
643 return w * h;
644 }
645
646
647 size_t
MaxRawFrameSize()648 SonixCamDevice::MaxRawFrameSize()
649 {
650 // if (fCompressionEnabled) { ... return ; }
651 return MinRawFrameSize()+1024*0; // fixed size frame (uncompressed)
652 }
653
654
655 bool
ValidateStartOfFrameTag(const uint8 * tag,size_t taglen)656 SonixCamDevice::ValidateStartOfFrameTag(const uint8 *tag, size_t taglen)
657 {
658 // SOF come with an 00, 40, 80, C0 sequence,
659 // supposedly corresponding with an equal byte in the end tag
660 fFrameTagState = tag[7] & 0xC0;
661 PRINT((CH "(, %" B_PRIuSIZE ") state %x" CT, taglen, fFrameTagState));
662
663 // which seems to be the same as of the EOF tag
664 return true;
665 }
666
667
668 bool
ValidateEndOfFrameTag(const uint8 * tag,size_t taglen,size_t datalen)669 SonixCamDevice::ValidateEndOfFrameTag(const uint8 *tag, size_t taglen, size_t datalen)
670 {
671 //PRINT((CH "(, %d) %x == %x" CT, taglen, (tag[0] & 0xC0), fFrameTagState));
672 // make sure the tag corresponds to the SOF we refer to
673 if ((tag[0] & 0xC0) != fFrameTagState) {
674 PRINT((CH ": discarded EOF %x != %x" CT, fFrameTagState, tag[0] & 0xC0));
675 return false;
676 }
677 //PRINT((CH ": validated EOF %x, len %d" CT, fFrameTagState, datalen));
678 return true;
679 }
680
681
682 status_t
GetFrameBitmap(BBitmap ** bm,bigtime_t * stamp)683 SonixCamDevice::GetFrameBitmap(BBitmap **bm, bigtime_t *stamp /* = NULL */)
684 {
685 BBitmap *b;
686 CamFrame *f;
687 status_t err;
688 PRINT((CH "()" CT));
689 err = fDeframer->WaitFrame(200000);
690 if (err < B_OK) { PRINT((CH ": WaitFrame: %s" CT, strerror(err))); }
691 if (err < B_OK)
692 return err;
693 err = fDeframer->GetFrame(&f, stamp);
694 if (err < B_OK) { PRINT((CH ": GetFrame: %s" CT, strerror(err))); }
695 if (err < B_OK)
696 return err;
697 PRINT((CH ": VideoFrame = %fx%f,%fx%f" CT, VideoFrame().left, VideoFrame().top, VideoFrame().right, VideoFrame().bottom));
698
699 long int w = (long)(VideoFrame().right - VideoFrame().left + 1);
700 long int h = (long)(VideoFrame().bottom - VideoFrame().top + 1);
701 b = new BBitmap(VideoFrame().OffsetToSelf(0,0), 0, B_RGB32, w*4);
702 PRINT((CH ": Frame: %ldx%ld" CT, w, h));
703
704 bayer2rgb24((unsigned char *)b->Bits(), (unsigned char *)f->Buffer(), w, h);
705
706 PRINT((CH ": got 1 frame (len %d)" CT, b->BitsLength()));
707 *bm = b;
708 return B_OK;
709 }
710
711
712 status_t
FillFrameBuffer(BBuffer * buffer,bigtime_t * stamp)713 SonixCamDevice::FillFrameBuffer(BBuffer *buffer, bigtime_t *stamp)
714 {
715 CamFrame *f;
716 status_t err;
717 PRINT((CH "()" CT));
718
719 memset(buffer->Data(), 0, buffer->SizeAvailable());
720 err = fDeframer->WaitFrame(2000000);
721 if (err < B_OK) { PRINT((CH ": WaitFrame: %s" CT, strerror(err))); }
722 if (err < B_OK)
723 return err;
724
725 err = fDeframer->GetFrame(&f, stamp);
726 if (err < B_OK) { PRINT((CH ": GetFrame: %s" CT, strerror(err))); }
727 if (err < B_OK)
728 return err;
729
730 long int w = (long)(VideoFrame().right - VideoFrame().left + 1);
731 long int h = (long)(VideoFrame().bottom - VideoFrame().top + 1);
732 PRINT((CH ": VideoFrame = %fx%f,%fx%f Frame: %ldx%ld" CT,
733 VideoFrame().left, VideoFrame().top, VideoFrame().right,
734 VideoFrame().bottom, w, h));
735
736 if (buffer->SizeAvailable() >= (size_t)w*h*4)
737 bayer2rgb32le((unsigned char *)buffer->Data(), (unsigned char *)f->Buffer(), w, h);
738
739 delete f;
740
741 PRINT((CH ": available %" B_PRIuSIZE ", required %ld" CT,
742 buffer->SizeAvailable(), w*h*4));
743 if (buffer->SizeAvailable() < (size_t)w*h*4)
744 return E2BIG;
745 PRINT((CH ": got 1 frame (len %" B_PRIuSIZE ")" CT, buffer->SizeUsed()));
746 return B_OK;
747 }
748
749
750 void
751 /* DEBUG: dump the SN regs */
DumpRegs()752 SonixCamDevice::DumpRegs()
753 {
754 uint8 regs[SN9C102_REG_COUNT];
755 status_t err;
756
757 //err = sonix_get_regs(dev, SN_ASIC_ID, regs, SN_REG_COUNT);
758 err = ReadReg(0, regs, SN9C102_REG_COUNT);
759 if (err < 0)
760 return;
761 printf("REG1: %02x %02x %02x %02x %02x %02x %02x %02x\n",
762 regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6], regs[7]);
763 printf(" 2: %02x %02x %02x %02x %02x %02x %02x %02x\n",
764 regs[8], regs[9], regs[10], regs[11], regs[12], regs[13], regs[14], regs[15]);
765 printf(" 3: %02x %02x %02x %02x %02x %02x %02x %02x\n",
766 regs[16], regs[17], regs[18], regs[19], regs[20], regs[21], regs[22], regs[23]);
767 printf(" 4: %02x %02x %02x %02x %02x %02x %02x %02x\n",
768 regs[24], regs[25], regs[26], regs[27], regs[28], regs[29], regs[30], regs[31]);
769 }
770
771 #if 0
772
773 status_t
774 SonixCamDevice::SendCommand(uint8 dir, uint8 request, uint16 value,
775 uint16 index, uint16 length, void* data)
776 {
777 size_t ret;
778 if (!GetDevice())
779 return ENODEV;
780 if (length > GetDevice()->MaxEndpoint0PacketSize())
781 return EINVAL;
782 ret = GetDevice()->ControlTransfer(
783 USB_REQTYPE_VENDOR | USB_REQTYPE_INTERFACE_OUT | dir,
784 request, value, index, length, data);
785 return ret;
786 }
787 #endif
788
789
SonixCamDeviceAddon(WebCamMediaAddOn * webcam)790 SonixCamDeviceAddon::SonixCamDeviceAddon(WebCamMediaAddOn* webcam)
791 : CamDeviceAddon(webcam)
792 {
793 SetSupportedDevices(kSupportedDevices);
794 }
795
796
~SonixCamDeviceAddon()797 SonixCamDeviceAddon::~SonixCamDeviceAddon()
798 {
799 }
800
801
802 const char *
BrandName()803 SonixCamDeviceAddon::BrandName()
804 {
805 return "Sonix";
806 }
807
808
809 SonixCamDevice *
Instantiate(CamRoster & roster,BUSBDevice * from)810 SonixCamDeviceAddon::Instantiate(CamRoster &roster, BUSBDevice *from)
811 {
812 return new SonixCamDevice(*this, from);
813 }
814
815 extern "C" status_t
B_WEBCAM_MKINTFUNC(sonix)816 B_WEBCAM_MKINTFUNC(sonix)
817 (WebCamMediaAddOn* webcam, CamDeviceAddon **addon)
818 {
819 *addon = new SonixCamDeviceAddon(webcam);
820 return B_OK;
821 }
822
823 // XXX: REMOVE ME
824
825
826
827 /*
828 * BAYER2RGB24 ROUTINE TAKEN FROM:
829 *
830 * Sonix SN9C101 based webcam basic I/F routines
831 * Copyright (C) 2004 Takafumi Mizuno <taka-qce@ls-a.jp>
832 *
833 * Redistribution and use in source and binary forms, with or without
834 * modification, are permitted provided that the following conditions
835 * are met:
836 * 1. Redistributions of source code must retain the above copyright
837 * notice, this list of conditions and the following disclaimer.
838 * 2. Redistributions in binary form must reproduce the above copyright
839 * notice, this list of conditions and the following disclaimer in the
840 * documentation and/or other materials provided with the distribution.
841 *
842 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
843 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
844 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
845 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
846 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
847 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
848 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
849 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
850 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
851 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
852 * SUCH DAMAGE.
853 */
854
bayer2rgb24(unsigned char * dst,unsigned char * src,long int WIDTH,long int HEIGHT)855 void bayer2rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT)
856 {
857 long int i;
858 unsigned char *rawpt, *scanpt;
859 long int size;
860
861 rawpt = src;
862 scanpt = dst;
863 size = WIDTH*HEIGHT;
864
865 for ( i = 0; i < size; i++ ) {
866 if ( (i/WIDTH) % 2 == 0 ) {
867 if ( (i % 2) == 0 ) {
868 /* B */
869 if ( (i > WIDTH) && ((i % WIDTH) > 0) ) {
870 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
871 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* R */
872 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
873 *(rawpt+WIDTH)+*(rawpt-WIDTH))/4; /* G */
874 *scanpt++ = *rawpt; /* B */
875 } else {
876 /* first line or left column */
877 *scanpt++ = *(rawpt+WIDTH+1); /* R */
878 *scanpt++ = (*(rawpt+1)+*(rawpt+WIDTH))/2; /* G */
879 *scanpt++ = *rawpt; /* B */
880 }
881 } else {
882 /* (B)G */
883 if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) ) {
884 *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* R */
885 *scanpt++ = *rawpt; /* G */
886 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* B */
887 } else {
888 /* first line or right column */
889 *scanpt++ = *(rawpt+WIDTH); /* R */
890 *scanpt++ = *rawpt; /* G */
891 *scanpt++ = *(rawpt-1); /* B */
892 }
893 }
894 } else {
895 if ( (i % 2) == 0 ) {
896 /* G(R) */
897 if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) ) {
898 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* R */
899 *scanpt++ = *rawpt; /* G */
900 *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* B */
901 } else {
902 /* bottom line or left column */
903 *scanpt++ = *(rawpt+1); /* R */
904 *scanpt++ = *rawpt; /* G */
905 *scanpt++ = *(rawpt-WIDTH); /* B */
906 }
907 } else {
908 /* R */
909 if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) ) {
910 *scanpt++ = *rawpt; /* R */
911 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
912 *(rawpt-WIDTH)+*(rawpt+WIDTH))/4; /* G */
913 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
914 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* B */
915 } else {
916 /* bottom line or right column */
917 *scanpt++ = *rawpt; /* R */
918 *scanpt++ = (*(rawpt-1)+*(rawpt-WIDTH))/2; /* G */
919 *scanpt++ = *(rawpt-WIDTH-1); /* B */
920 }
921 }
922 }
923 rawpt++;
924 }
925
926 }
927
928 /* modified bayer2rgb24 to output rgb-32 little endian (B_RGB32)
929 * François Revol
930 */
931
bayer2rgb32le(unsigned char * dst,unsigned char * src,long int WIDTH,long int HEIGHT)932 void bayer2rgb32le(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT)
933 {
934 long int i;
935 unsigned char *rawpt, *scanpt;
936 long int size;
937
938 rawpt = src;
939 scanpt = dst;
940 size = WIDTH*HEIGHT;
941
942 for ( i = 0; i < size; i++ ) {
943 if ( (i/WIDTH) % 2 == 0 ) {
944 if ( (i % 2) == 0 ) {
945 /* B */
946 if ( (i > WIDTH) && ((i % WIDTH) > 0) ) {
947 *scanpt++ = *rawpt; /* B */
948 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
949 *(rawpt+WIDTH)+*(rawpt-WIDTH))/4; /* G */
950 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
951 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* R */
952 } else {
953 /* first line or left column */
954 *scanpt++ = *rawpt; /* B */
955 *scanpt++ = (*(rawpt+1)+*(rawpt+WIDTH))/2; /* G */
956 *scanpt++ = *(rawpt+WIDTH+1); /* R */
957 }
958 } else {
959 /* (B)G */
960 if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) ) {
961 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* B */
962 *scanpt++ = *rawpt; /* G */
963 *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* R */
964 } else {
965 /* first line or right column */
966 *scanpt++ = *(rawpt-1); /* B */
967 *scanpt++ = *rawpt; /* G */
968 *scanpt++ = *(rawpt+WIDTH); /* R */
969 }
970 }
971 } else {
972 if ( (i % 2) == 0 ) {
973 /* G(R) */
974 if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) ) {
975 *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* B */
976 *scanpt++ = *rawpt; /* G */
977 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* R */
978 } else {
979 /* bottom line or left column */
980 *scanpt++ = *(rawpt-WIDTH); /* B */
981 *scanpt++ = *rawpt; /* G */
982 *scanpt++ = *(rawpt+1); /* R */
983 }
984 } else {
985 /* R */
986 if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) ) {
987 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
988 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* B */
989 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
990 *(rawpt-WIDTH)+*(rawpt+WIDTH))/4; /* G */
991 *scanpt++ = *rawpt; /* R */
992 } else {
993 /* bottom line or right column */
994 *scanpt++ = *(rawpt-WIDTH-1); /* B */
995 *scanpt++ = (*(rawpt-1)+*(rawpt-WIDTH))/2; /* G */
996 *scanpt++ = *rawpt; /* R */
997 }
998 }
999 }
1000 rawpt++;
1001 scanpt++;
1002 }
1003
1004 }
1005