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 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 213 SonixCamDevice::~SonixCamDevice() 214 { 215 if (Sensor()) 216 delete fSensor; 217 fSensor = NULL; 218 } 219 220 221 bool 222 SonixCamDevice::SupportsBulk() 223 { 224 return true; 225 } 226 227 228 bool 229 SonixCamDevice::SupportsIsochronous() 230 { 231 return true; 232 } 233 234 235 status_t 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 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 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 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 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 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 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 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 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 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 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 504 SonixCamDevice::SetVideoParams(float brightness, float contrast, float hue, float red, float green, float blue) 505 { 506 return B_OK; 507 } 508 509 void 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 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 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 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 648 SonixCamDevice::MaxRawFrameSize() 649 { 650 // if (fCompressionEnabled) { ... return ; } 651 return MinRawFrameSize()+1024*0; // fixed size frame (uncompressed) 652 } 653 654 655 bool 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 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 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 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 */ 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 790 SonixCamDeviceAddon::SonixCamDeviceAddon(WebCamMediaAddOn* webcam) 791 : CamDeviceAddon(webcam) 792 { 793 SetSupportedDevices(kSupportedDevices); 794 } 795 796 797 SonixCamDeviceAddon::~SonixCamDeviceAddon() 798 { 799 } 800 801 802 const char * 803 SonixCamDeviceAddon::BrandName() 804 { 805 return "Sonix"; 806 } 807 808 809 SonixCamDevice * 810 SonixCamDeviceAddon::Instantiate(CamRoster &roster, BUSBDevice *from) 811 { 812 return new SonixCamDevice(*this, from); 813 } 814 815 extern "C" status_t 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 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 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