📄 ibmcam.c
字号:
}static void ibmcam_model2_Packet1(struct uvd *uvd, unsigned short v1, unsigned short v2){ ibmcam_veio(uvd, 0, 0x00aa, 0x012d); ibmcam_veio(uvd, 0, 0x00ff, 0x012e); ibmcam_veio(uvd, 0, v1, 0x012f); ibmcam_veio(uvd, 0, 0x00ff, 0x0130); ibmcam_veio(uvd, 0, 0xc719, 0x0124); ibmcam_veio(uvd, 0, v2, 0x0127); ibmcam_model2_Packet2(uvd);}/* * ibmcam_model3_Packet1() * * 00_0078_012d * 00_0097_012f * 00_d141_0124 * 00_0096_0127 * 00_fea8_0124 */static void ibmcam_model3_Packet1(struct uvd *uvd, unsigned short v1, unsigned short v2){ ibmcam_veio(uvd, 0, 0x0078, 0x012d); ibmcam_veio(uvd, 0, v1, 0x012f); ibmcam_veio(uvd, 0, 0xd141, 0x0124); ibmcam_veio(uvd, 0, v2, 0x0127); ibmcam_veio(uvd, 0, 0xfea8, 0x0124);}static void ibmcam_model4_BrightnessPacket(struct uvd *uvd, int i){ ibmcam_veio(uvd, 0, 0x00aa, 0x012d); ibmcam_veio(uvd, 0, 0x0026, 0x012f); ibmcam_veio(uvd, 0, 0xd141, 0x0124); ibmcam_veio(uvd, 0, i, 0x0127); ibmcam_veio(uvd, 0, 0x00aa, 0x0130); ibmcam_veio(uvd, 0, 0x82a8, 0x0124); ibmcam_veio(uvd, 0, 0x0038, 0x012d); ibmcam_veio(uvd, 0, 0x0004, 0x012f); ibmcam_veio(uvd, 0, 0xd145, 0x0124); ibmcam_veio(uvd, 0, 0xfffa, 0x0124);}/* * ibmcam_adjust_contrast() * * The contrast value changes from 0 (high contrast) to 15 (low contrast). * This is in reverse to usual order of things (such as TV controls), so * we reverse it again here. * * TODO: we probably don't need to send the setup 5 times... * * History: * 1/2/00 Created. */static void ibmcam_adjust_contrast(struct uvd *uvd){ unsigned char a_contrast = uvd->vpic.contrast >> 12; unsigned char new_contrast; if (a_contrast >= 16) a_contrast = 15; new_contrast = 15 - a_contrast; if (new_contrast == uvd->vpic_old.contrast) return; uvd->vpic_old.contrast = new_contrast; switch (IBMCAM_T(uvd)->camera_model) { case IBMCAM_MODEL_1: { const int ntries = 5; int i; for (i=0; i < ntries; i++) { ibmcam_Packet_Format1(uvd, contrast_14, new_contrast); ibmcam_send_FF_04_02(uvd); } break; } case IBMCAM_MODEL_2: case IBMCAM_MODEL_4: /* Models 2, 4 do not have this control; implemented in software. */ break; case IBMCAM_MODEL_3: { /* Preset hardware values */ static const struct { unsigned short cv1; unsigned short cv2; unsigned short cv3; } cv[7] = { { 0x05, 0x05, 0x0f }, /* Minimum */ { 0x04, 0x04, 0x16 }, { 0x02, 0x03, 0x16 }, { 0x02, 0x08, 0x16 }, { 0x01, 0x0c, 0x16 }, { 0x01, 0x0e, 0x16 }, { 0x01, 0x10, 0x16 } /* Maximum */ }; int i = a_contrast / 2; RESTRICT_TO_RANGE(i, 0, 6); ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */ ibmcam_model3_Packet1(uvd, 0x0067, cv[i].cv1); ibmcam_model3_Packet1(uvd, 0x005b, cv[i].cv2); ibmcam_model3_Packet1(uvd, 0x005c, cv[i].cv3); ibmcam_veio(uvd, 0, 0x0001, 0x0114); ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */ usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); break; } default: break; }}/* * ibmcam_change_lighting_conditions() * * Camera model 1: * We have 3 levels of lighting conditions: 0=Bright, 1=Medium, 2=Low. * * Camera model 2: * We have 16 levels of lighting, 0 for bright light and up to 15 for * low light. But values above 5 or so are useless because camera is * not really capable to produce anything worth viewing at such light. * This setting may be altered only in certain camera state. * * Low lighting forces slower FPS. Lighting is set as a module parameter. * * History: * 1/5/00 Created. * 2/20/00 Added support for Model 2 cameras. */static void ibmcam_change_lighting_conditions(struct uvd *uvd){ static const char proc[] = "ibmcam_change_lighting_conditions"; if (debug > 0) info("%s: Set lighting to %hu.", proc, lighting); switch (IBMCAM_T(uvd)->camera_model) { case IBMCAM_MODEL_1: { const int ntries = 5; int i; for (i=0; i < ntries; i++) ibmcam_Packet_Format1(uvd, light_27, (unsigned short) lighting); break; } case IBMCAM_MODEL_2:#if 0 /* * This command apparently requires camera to be stopped. My * experiments showed that it -is- possible to alter the lighting * conditions setting "on the fly", but why bother? This setting does * not work reliably in all cases, so I decided simply to leave the * setting where Xirlink put it - in the camera setup phase. This code * is commented out because it does not work at -any- moment, so its * presence makes no sense. You may use it for experiments. */ ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop camera */ ibmcam_model2_Packet1(uvd, mod2_sensitivity, lighting); ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Start camera */#endif break; case IBMCAM_MODEL_3: case IBMCAM_MODEL_4: default: break; }}/* * ibmcam_set_sharpness() * * Cameras model 1 have internal smoothing feature. It is controlled by value in * range [0..6], where 0 is most smooth and 6 is most sharp (raw image, I guess). * Recommended value is 4. Cameras model 2 do not have this feature at all. */static void ibmcam_set_sharpness(struct uvd *uvd){ static const char proc[] = "ibmcam_set_sharpness"; switch (IBMCAM_T(uvd)->camera_model) { case IBMCAM_MODEL_1: { static const unsigned short sa[] = { 0x11, 0x13, 0x16, 0x18, 0x1a, 0x8, 0x0a }; unsigned short i, sv; RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX); if (debug > 0) info("%s: Set sharpness to %hu.", proc, sharpness); sv = sa[sharpness - SHARPNESS_MIN]; for (i=0; i < 2; i++) { ibmcam_send_x_01_00_05 (uvd, unknown_88); ibmcam_send_x_00_05 (uvd, sharp_13); ibmcam_send_x_00_05_02 (uvd, sv); } break; } case IBMCAM_MODEL_2: case IBMCAM_MODEL_4: /* Models 2, 4 do not have this control */ break; case IBMCAM_MODEL_3: { /* * "Use a table of magic numbers. * This setting doesn't really change much. * But that's how Windows does it." */ static const struct { unsigned short sv1; unsigned short sv2; unsigned short sv3; unsigned short sv4; } sv[7] = { { 0x00, 0x00, 0x05, 0x14 }, /* Smoothest */ { 0x01, 0x04, 0x05, 0x14 }, { 0x02, 0x04, 0x05, 0x14 }, { 0x03, 0x04, 0x05, 0x14 }, { 0x03, 0x05, 0x05, 0x14 }, { 0x03, 0x06, 0x05, 0x14 }, { 0x03, 0x07, 0x05, 0x14 } /* Sharpest */ }; RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX); RESTRICT_TO_RANGE(sharpness, 0, 6); ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */ ibmcam_model3_Packet1(uvd, 0x0060, sv[sharpness].sv1); ibmcam_model3_Packet1(uvd, 0x0061, sv[sharpness].sv2); ibmcam_model3_Packet1(uvd, 0x0062, sv[sharpness].sv3); ibmcam_model3_Packet1(uvd, 0x0063, sv[sharpness].sv4); ibmcam_veio(uvd, 0, 0x0001, 0x0114); ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */ usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); ibmcam_veio(uvd, 0, 0x0001, 0x0113); break; } default: break; }}/* * ibmcam_set_brightness() * * This procedure changes brightness of the picture. */static void ibmcam_set_brightness(struct uvd *uvd){ static const char proc[] = "ibmcam_set_brightness"; static const unsigned short n = 1; if (debug > 0) info("%s: Set brightness to %hu.", proc, uvd->vpic.brightness); switch (IBMCAM_T(uvd)->camera_model) { case IBMCAM_MODEL_1: { unsigned short i, j, bv[3]; bv[0] = bv[1] = bv[2] = uvd->vpic.brightness >> 10; if (bv[0] == (uvd->vpic_old.brightness >> 10)) return; uvd->vpic_old.brightness = bv[0]; for (j=0; j < 3; j++) for (i=0; i < n; i++) ibmcam_Packet_Format1(uvd, bright_3x[j], bv[j]); break; } case IBMCAM_MODEL_2: { unsigned short i, j; i = uvd->vpic.brightness >> 12; /* 0 .. 15 */ j = 0x60 + i * ((0xee - 0x60) / 16); /* 0x60 .. 0xee or so */ if (uvd->vpic_old.brightness == j) break; uvd->vpic_old.brightness = j; ibmcam_model2_Packet1(uvd, mod2_brightness, j); break; } case IBMCAM_MODEL_3: { /* Model 3: Brightness range 'i' in [0x0C..0x3F] */ unsigned short i = 0x0C + (uvd->vpic.brightness / (0xFFFF / (0x3F - 0x0C + 1))); RESTRICT_TO_RANGE(i, 0x0C, 0x3F); if (uvd->vpic_old.brightness == i) break; uvd->vpic_old.brightness = i; ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */ ibmcam_model3_Packet1(uvd, 0x0036, i); ibmcam_veio(uvd, 0, 0x0001, 0x0114); ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */ usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); ibmcam_veio(uvd, 0, 0x0001, 0x0113); break; } case IBMCAM_MODEL_4: { /* Model 4: Brightness range 'i' in [0x04..0xb4] */ unsigned short i = 0x04 + (uvd->vpic.brightness / (0xFFFF / (0xb4 - 0x04 + 1))); RESTRICT_TO_RANGE(i, 0x04, 0xb4); if (uvd->vpic_old.brightness == i) break; uvd->vpic_old.brightness = i; ibmcam_model4_BrightnessPacket(uvd, i); break; } default: break; }}static void ibmcam_set_hue(struct uvd *uvd){ switch (IBMCAM_T(uvd)->camera_model) { case IBMCAM_MODEL_2: { unsigned short hue = uvd->vpic.hue >> 9; /* 0 .. 7F */ if (uvd->vpic_old.hue == hue) return; uvd->vpic_old.hue = hue; ibmcam_model2_Packet1(uvd, mod2_hue, hue); /* ibmcam_model2_Packet1(uvd, mod2_saturation, sat); */ break; } case IBMCAM_MODEL_3: {#if 0 /* This seems not to work. No problem, will fix programmatically */ unsigned short hue = 0x05 + (uvd->vpic.hue / (0xFFFF / (0x37 - 0x05 + 1))); RESTRICT_TO_RANGE(hue, 0x05, 0x37); if (uvd->vpic_old.hue == hue) return; uvd->vpic_old.hue = hue; ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */ ibmcam_model3_Packet1(uvd, 0x007e, hue); ibmcam_veio(uvd, 0, 0x0001, 0x0114); ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */ usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); ibmcam_veio(uvd, 0, 0x0001, 0x0113);#endif break; } case IBMCAM_MODEL_4: { unsigned short r_gain, g_gain, b_gain, hue; /* * I am not sure r/g/b_gain variables exactly control gain * of those channels. Most likely they subtly change some * very internal image processing settings in the camera. * In any case, here is what they do, and feel free to tweak: * * r_gain: seriously affects red gain * g_gain: seriously affects green gain * b_gain: seriously affects blue gain * hue: changes average color from violet (0) to red (0xFF) * * These settings are preset for a decent white balance in * 320x240, 352x288 modes. Low-res modes exhibit higher contrast * and therefore may need different values here. */ hue = 20 + (uvd->vpic.hue >> 9); switch (uvd->videosize) { case VIDEOSIZE_128x96: r_gain = 90; g_gain = 166; b_gain = 175; break; case VIDEOSIZE_160x120: r_gain = 70; g_gain = 166; b_gain = 185; break; case VIDEOSIZE_176x144: r_gain = 160; g_gain = 175; b_gain = 185; break; default: r_gain = 120; g_gain = 166; b_gain = 175; break; } RESTRICT_TO_RANGE(hue, 1, 0x7f); ibmcam_veio(uvd, 0, 0x00aa, 0x012d); ibmcam_veio(uvd, 0, 0x001e, 0x012f); ibmcam_veio(uvd, 0, 0xd141, 0x0124); ibmcam_veio(uvd, 0, g_gain, 0x0127); /* Green gain */ ibmcam_veio(uvd, 0, r_gain, 0x012e); /* Red gain */ ibmcam_veio(uvd, 0, b_gain, 0x0130); /* Blue gain */ ibmcam_veio(uvd, 0, 0x8a28, 0x0124); ibmcam_veio(uvd, 0, hue, 0x012d); /* Hue */ ibmcam_veio(uvd, 0, 0xf545, 0x0124); break; } default: break; }}/* * ibmcam_adjust_picture() * * This procedure gets called from V4L interface to update picture settings. * Here we change brightness and contrast. */static void ibmcam_adjust_picture(struct uvd *uvd){ ibmcam_adjust_contrast(uvd); ibmcam_set_brightness(uvd); ibmcam_set_hue(uvd);}static int ibmcam_model1_setup(struct uvd *uvd){ const int ntries = 5; int i; ibmcam_veio(uvd, 1, 0x00, 0x0128); ibmcam_veio(uvd, 1, 0x00, 0x0100); ibmcam_veio(uvd, 0, 0x01, 0x0100); /* LED On */ ibmcam_veio(uvd, 1, 0x00, 0x0100); ibmcam_veio(uvd, 0, 0x81, 0x0100); /* LED Off */ ibmcam_veio(uvd, 1, 0x00, 0x0100); ibmcam_veio(uvd, 0, 0x01, 0x0100); /* LED On */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -