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, %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 306 ssize_t 307 SonixCamDevice::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 326 status_t 327 SonixCamDevice::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 339 status_t 340 SonixCamDevice::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 359 ssize_t 360 SonixCamDevice::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 400 ssize_t 401 SonixCamDevice::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 453 status_t 454 SonixCamDevice::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 474 status_t 475 SonixCamDevice::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 500 status_t 501 SonixCamDevice::SetVideoParams(float brightness, float contrast, float hue, float red, float green, float blue) 502 { 503 return B_OK; 504 } 505 506 void 507 SonixCamDevice::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 536 status_t 537 SonixCamDevice::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 567 status_t 568 SonixCamDevice::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 632 size_t 633 SonixCamDevice::MinRawFrameSize() 634 { 635 // if (fCompressionEnabled) { ... return ; } 636 BRect vf(VideoFrame()); 637 int w = vf.IntegerWidth()+1; 638 int h = vf.IntegerHeight()+1; 639 // 1 byte/pixel 640 return (size_t)(w*h); 641 } 642 643 644 size_t 645 SonixCamDevice::MaxRawFrameSize() 646 { 647 // if (fCompressionEnabled) { ... return ; } 648 return MinRawFrameSize()+1024*0; // fixed size frame (uncompressed) 649 } 650 651 652 bool 653 SonixCamDevice::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 665 bool 666 SonixCamDevice::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 679 status_t 680 SonixCamDevice::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 709 status_t 710 SonixCamDevice::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 744 void 745 /* DEBUG: dump the SN regs */ 746 SonixCamDevice::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 767 status_t 768 SonixCamDevice::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 784 SonixCamDeviceAddon::SonixCamDeviceAddon(WebCamMediaAddOn* webcam) 785 : CamDeviceAddon(webcam) 786 { 787 SetSupportedDevices(kSupportedDevices); 788 } 789 790 791 SonixCamDeviceAddon::~SonixCamDeviceAddon() 792 { 793 } 794 795 796 const char * 797 SonixCamDeviceAddon::BrandName() 798 { 799 return "Sonix"; 800 } 801 802 803 SonixCamDevice * 804 SonixCamDeviceAddon::Instantiate(CamRoster &roster, BUSBDevice *from) 805 { 806 return new SonixCamDevice(*this, from); 807 } 808 809 extern "C" status_t 810 B_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 849 void 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 926 void 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