Hello,
Try this patch. I test with amsn and all seems OK. Hue, saturation 
brightness and contrast is controlled as I expect.

--~--~---------~--~----~------------~-------~--~----~
Lets make microdia webcams plug'n play, (currently plug'n pray)
To post to this group, send email to [email protected]
Visit us online https://groups.google.com/group/microdia
-~----------~----~----~----~------~----~------~--~---

diff --git a/sn9c20x-bridge.c b/sn9c20x-bridge.c
index dfbf87f..144fe1e 100644
--- a/sn9c20x-bridge.c
+++ b/sn9c20x-bridge.c
@@ -30,6 +30,290 @@
 #include "sn9c20x.h"
 #include "sn9c20x-bridge.h"
 
+
+//Coordinate aray for eliptic HSV corrections 
+
+       int RX[]={  41,  44,  46,  48,  50,  52,  54,  56,
+           58,  60,  62,  64,  66,  68,  70,  72,
+           74,  76,  78,  80,  81,  83,  85,  87,
+           88,  90,  92,  93,  95,  97,  98, 100,
+          101, 102, 104, 105, 107, 108, 109, 110,
+          112, 113, 114, 115, 116, 117, 118, 119,
+          120, 121, 122, 123, 123, 124, 125, 125,
+           126, 127, 127, 128, 128, 129, 129, 129,
+          130, 130, 130, 130, 131, 131, 131, 131,
+          131, 131, 131, 131, 130, 130, 130, 130,
+          129, 129, 129, 128, 128, 127, 127, 126,
+           125, 125, 124, 123, 122, 122, 121, 120,
+          119, 118, 117, 116, 115, 114, 112, 111,
+           110, 109, 107, 106, 105, 103, 102, 101,
+           99,  98,  96,  94,  93,  91,  90,  88,
+            86,  84,  83,  81,  79,  77,  75,  74,
+           72,  70,  68,  66,  64,  62,  60,  58,
+            56,  54,  52,  49,  47,  45,  43,  41,
+           39,  36,  34,  32,  30,  28,  25,  23,
+            21,  19,  16,  14,  12,   9,   7,   5,
+            3,   0,  -1,  -3,  -6,  -8, -10, -12,
+           -15, -17, -19, -22, -24, -26, -28, -30,
+          -33, -35, -37, -39, -41, -44, -46, -48,
+          -50, -52, -54, -56, -58, -60, -62, -64,
+          -66, -68, -70, -72, -74, -76, -78, -80,
+          -81, -83, -85, -87, -88, -90, -92, -93,
+          -95, -97, -98,-100,-101,-102,-104,-105,
+         -107,-108,-109,-110,-112,-113,-114,-115,
+         -116,-117,-118,-119,-120,-121,-122,-123,
+         -123,-124,-125,-125,-126,-127,-127,-128,
+         -128,-128,-128,-128,-128,-128,-128,-128,
+         -128,-128,-128,-128,-128,-128,-128,-128,
+         -128,-128,-128,-128,-128,-128,-128,-128,
+         -128,-127,-127,-126,-125,-125,-124,-123,
+         -122,-122,-121,-120,-119,-118,-117,-116,
+         -115,-114,-112,-111,-110,-109,-107,-106,
+         -105,-103,-102,-101, -99, -98, -96, -94,
+          -93, -91, -90, -88, -86, -84, -83, -81,
+          -79, -77, -75, -74, -72, -70, -68, -66, 
+          -64, -62, -60, -58, -56, -54, -52, -49,
+          -47, -45, -43, -41, -39, -36, -34, -32,
+          -30, -28, -25, -23, -21, -19, -16, -14,
+          -12,  -9,  -7,  -5,  -3,   0,   1,   3,
+            6,   8,  10,  12,  15,  17,  19,  22,
+           24,  26,  28,  30,  33,  35,  37,  39, 41};
+
+         int RY[]={  82,  80,  78,  76,  74,  73,  71,  69,
+           67,  65,  63,  61,  58,  56,  54,  52,
+           50,  48,  46,  44,  41,  39,  37,  35, 
+           32,  30,  28,  26,  23,  21,  19,  16,
+           14,  12,  10,   7,   5,   3,   0,  -1,
+           -3,  -6,  -8, -10, -13, -15, -17, -19, 
+          -22, -24, -26, -29, -31, -33, -35, -38,
+          -40, -42, -44, -46, -48, -51, -53, -55,
+          -57, -59, -61, -63, -65, -67, -69, -71,
+          -73, -75, -77, -79, -81, -82, -84, -86,
+          -88, -89, -91, -93, -94, -96, -98, -99,
+         -101,-102,-104,-105,-106,-108,-109,-110,
+         -112,-113,-114,-115,-116,-117,-119,-120,
+         -120,-121,-122,-123,-124,-125,-126,-126,
+         -127,-128,-128,-128,-128,-128,-128,-128,
+         -128,-128,-128,-128,-128,-128,-128,-128,
+         -128,-128,-128,-128,-128,-128,-128,-128,
+         -128,-128,-128,-128,-128,-128,-128,-128,
+         -127,-127,-126,-125,-125,-124,-123,-122,
+         -121,-120,-119,-118,-117,-116,-115,-114,
+         -113,-111,-110,-109,-107,-106,-105,-103,
+         -102,-100, -99, -97, -96, -94, -92, -91,
+          -89, -87, -85, -84, -82, -80, -78, -76,
+          -74, -73, -71, -69, -67, -65, -63, -61, 
+          -58, -56, -54, -52, -50, -48, -46, -44,
+          -41, -39, -37, -35, -32, -30, -28, -26,
+          -23, -21, -19, -16, -14, -12, -10,  -7,
+           -5,  -3,   0,   1,   3,   6,   8,  10,
+           13,  15,  17,  19,  22,  24,  26,  29,
+           31,  33,  35,  38,  40,  42,  44,  46, 
+           48,  51,  53,  55,  57,  59,  61,  63,
+           65,  67,  69,  71,  73,  75,  77,  79,
+           81,  82,  84,  86,  88,  89,  91,  93,
+           94,  96,  98,  99, 101, 102, 104, 105,
+          106, 108, 109, 110, 112, 113, 114, 115,
+          116, 117, 119, 120, 120, 121, 122, 123,
+          124, 125, 126, 126, 127, 128, 128, 129,
+          129, 130, 130, 131, 131, 131, 131, 132,
+          132, 132, 132, 132, 132, 132, 132, 132, 
+          132, 132, 132, 131, 131, 131, 130, 130,
+          130, 129, 129, 128, 127, 127, 126, 125,
+          125, 124, 123, 122, 121, 120, 119, 118, 
+          117, 116, 115, 114, 113, 111, 110, 109,
+          107, 106, 105, 103, 102, 100,  99,  97,
+           96,  94,  92,  91,  89,  87,  85,  84,  82};
+
+
+       int GX[]={-124,-124,-125,-125,-125,-125,-125,-125,
+         -125,-126,-126,-125,-125,-125,-125,-125,
+         -125,-124,-124,-124,-123,-123,-122,-122,
+         -121,-121,-120,-120,-119,-118,-117,-117,
+         -116,-115,-114,-113,-112,-111,-110,-109,
+         -108,-107,-105,-104,-103,-102,-100, -99,
+          -98, -96, -95, -93, -92, -91, -89, -87,
+          -86, -84, -83, -81, -79, -77, -76, -74, 
+          -72, -70, -69, -67, -65, -63, -61, -59,
+          -57, -55, -53, -51, -49, -47, -45, -43,
+          -41, -39, -37, -35, -33, -30, -28, -26,
+          -24, -22, -20, -18, -15, -13, -11,  -9,
+           -7,  -4,  -2,   0,   1,   3,   6,   8,
+           10,  12,  14,  17,  19,  21,  23,  25, 
+           27,  29,  32,  34,  36,  38,  40,  42,
+           44,  46,  48,  50,  52,  54,  56,  58,
+           60,  62,  64,  66,  68,  70,  71,  73, 
+           75,  77,  78,  80,  82,  83,  85,  87,
+           88,  90,  91,  93,  94,  96,  97,  98,
+          100, 101, 102, 104, 105, 106, 107, 108,
+          109, 111, 112, 113, 113, 114, 115, 116,
+          117, 118, 118, 119, 120, 120, 121, 122,
+          122, 123, 123, 124, 124, 124, 125, 125, 
+          125, 125, 125, 125, 125, 126, 126, 125,
+          125, 125, 125, 125, 125, 124, 124, 124,
+          123, 123, 122, 122, 121, 121, 120, 120,
+          119, 118, 117, 117, 116, 115, 114, 113,
+          112, 111, 110, 109, 108, 107, 105, 104, 
+          103, 102, 100,  99,  98,  96,  95,  93,
+           92,  91,  89,  87,  86,  84,  83,  81,
+           79,  77,  76,  74,  72,  70,  69,  67,
+           65,  63,  61,  59,  57,  55,  53,  51,
+           49,  47,  45,  43,  41,  39,  37,  35,
+           33,  30,  28,  26,  24,  22,  20,  18,
+           15,  13,  11,   9,   7,   4,   2,   0,
+           -1,  -3,  -6,  -8, -10, -12, -14, -17,
+          -19, -21, -23, -25, -27, -29, -32, -34,
+          -36, -38, -40, -42, -44, -46, -48, -50,
+          -52, -54, -56, -58, -60, -62, -64, -66,
+          -68, -70, -71, -73, -75, -77, -78, -80, 
+          -82, -83, -85, -87, -88, -90, -91, -93,
+          -94, -96, -97, -98,-100,-101,-102,-104,
+         -105,-106,-107,-108,-109,-111,-112,-113,
+         -113,-114,-115,-116,-117,-118,-118,-119,
+         -120,-120,-121,-122,-122,-123,-123,-124,-124};
+
+       int GY[]={-100, -99, -98, -97, -95, -94, -93, -91,
+          -90, -89, -87, -86, -84, -83, -81, -80,
+          -78, -76, -75, -73, -71, -70, -68, -66,
+          -64, -63, -61, -59, -57, -55, -53, -51,
+          -49, -48, -46, -44, -42, -40, -38, -36,
+          -34, -32, -30, -27, -25, -23, -21, -19,
+          -17, -15, -13, -11,  -9,  -7,  -4,  -2,
+            0,   1,   3,   5,   7,   9,  11,  14,
+           16,  18,  20,  22,  24,  26,  28,  30,
+           32,  34,  36,  38,  40,  42,  44,  46,
+           48,  50,  52,  54,  56,  58,  59,  61,
+           63,  65,  67,  68,  70,  72,  74,  75,
+           77,  78,  80,  82,  83,  85,  86,  88,
+           89,  90,  92,  93,  95,  96,  97,  98,
+          100, 101, 102, 103, 104, 105, 106, 107,
+          108, 109, 110, 111, 112, 112, 113, 114,
+          115, 115, 116, 116, 117, 117, 118, 118,
+          119, 119, 119, 120, 120, 120, 120, 120,
+          121, 121, 121, 121, 121, 121, 120, 120,
+          120, 120, 120, 119, 119, 119, 118, 118,
+          117, 117, 116, 116, 115, 114, 114, 113,
+          112, 111, 111, 110, 109, 108, 107, 106,
+          105, 104, 103, 102, 100,  99,  98,  97,
+           95,  94,  93,  91,  90,  89,  87,  86,
+           84,  83,  81,  80,  78,  76,  75,  73,
+           71,  70,  68,  66,  64,  63,  61,  59,
+           57,  55,  53,  51,  49,  48,  46,  44,
+           42,  40,  38,  36,  34,  32,  30,  27,
+           25,  23,  21,  19,  17,  15,  13,  11,
+            9,   7,   4,   2,   0,  -1,  -3,  -5,
+           -7,  -9, -11, -14, -16, -18, -20, -22,
+          -24, -26, -28, -30, -32, -34, -36, -38, 
+          -40, -42, -44, -46, -48, -50, -52, -54,
+          -56, -58, -59, -61, -63, -65, -67, -68,
+          -70, -72, -74, -75, -77, -78, -80, -82,
+          -83, -85, -86, -88, -89, -90, -92, -93,
+          -95, -96, -97, -98,-100,-101,-102,-103,
+         -104,-105,-106,-107,-108,-109,-110,-111,
+         -112,-112,-113,-114,-115,-115,-116,-116,
+         -117,-117,-118,-118,-119,-119,-119,-120,
+         -120,-120,-120,-120,-121,-121,-121,-121,
+         -121,-121,-120,-120,-120,-120,-120,-119,
+         -119,-119,-118,-118,-117,-117,-116,-116,
+         -115,-114,-114,-113,-112,-111,-111,-110,
+         -109,-108,-107,-106,-105,-104,-103,-102,-100};
+
+       int BX[]={ 112, 113, 114, 114, 115, 116, 117, 117,
+          118, 118, 119, 119, 120, 120, 120, 121,
+          121, 121, 122, 122, 122, 122, 122, 122,
+          122, 122, 122, 122, 122, 122, 121, 121,
+          121, 120, 120, 120, 119, 119, 118, 118,
+          117, 116, 116, 115, 114, 113, 113, 112,
+          111, 110, 109, 108, 107, 106, 105, 104,
+          103, 102, 100,  99,  98,  97,  95,  94,
+           93,  91,  90,  88,  87,  85,  84,  82,
+           80,  79,  77,  76,  74,  72,  70,  69,
+           67,  65,  63,  61,  60,  58,  56,  54,
+           52,  50,  48,  46,  44,  42,  40,  38,
+           36,  34,  32,  30,  28,  26,  24,  22,
+           19,  17,  15,  13,  11,   9,   7,   5,
+            2,   0,  -1,  -3,  -5,  -7,  -9, -12,
+          -14, -16, -18, -20, -22, -24, -26, -28,
+          -31, -33, -35, -37, -39, -41, -43, -45,
+          -47, -49, -51, -53, -54, -56, -58, -60,
+          -62, -64, -66, -67, -69, -71, -73, -74,
+          -76, -78, -79, -81, -83, -84, -86, -87,
+          -89, -90, -92, -93, -94, -96, -97, -98,
+          -99,-101,-102,-103,-104,-105,-106,-107,
+         -108,-109,-110,-111,-112,-113,-114,-114,
+         -115,-116,-117,-117,-118,-118,-119,-119,
+         -120,-120,-120,-121,-121,-121,-122,-122,
+         -122,-122,-122,-122,-122,-122,-122,-122,
+         -122,-122,-121,-121,-121,-120,-120,-120,
+         -119,-119,-118,-118,-117,-116,-116,-115,
+         -114,-113,-113,-112,-111,-110,-109,-108,
+         -107,-106,-105,-104,-103,-102,-100, -99,
+          -98, -97, -95, -94, -93, -91, -90, -88,
+          -87, -85, -84, -82, -80, -79, -77, -76,
+          -74, -72, -70, -69, -67, -65, -63, -61,
+          -60, -58, -56, -54, -52, -50, -48, -46,
+          -44, -42, -40, -38, -36, -34, -32, -30,
+          -28, -26, -24, -22, -19, -17, -15, -13,
+          -11,  -9,  -7,  -5,  -2,   0,   1,   3,
+            5,   7,   9,  12,  14,  16,  18,  20,
+           22,  24,  26,  28,  31,  33,  35,  37,
+           39,  41,  43,  45,  47,  49,  51,  53,
+           54,  56,  58,  60,  62,  64,  66,  67,
+           69,  71,  73,  74,  76,  78,  79,  81,
+           83,  84,  86,  87,  89,  90,  92,  93,
+           94,  96,  97,  98,  99, 101, 102, 103,
+          104, 105, 106, 107, 108, 109, 110, 111, 112};
+
+
+       int BY[]={ -11, -13, -15, -17, -19, -21, -23, -25,
+          -27, -29, -31, -33, -35, -37, -39, -41,
+          -43, -45, -46, -48, -50, -52, -54, -55,
+          -57, -59, -61, -62, -64, -66, -67, -69,
+          -71, -72, -74, -75, -77, -78, -80, -81, 
+          -83, -84, -86, -87, -88, -90, -91, -92,
+          -93, -95, -96, -97, -98, -99,-100,-101,
+         -102,-103,-104,-105,-106,-106,-107,-108,
+         -109,-109,-110,-111,-111,-112,-112,-113,
+         -113,-114,-114,-114,-115,-115,-115,-115,
+         -116,-116,-116,-116,-116,-116,-116,-116,
+         -116,-115,-115,-115,-115,-114,-114,-114,
+         -113,-113,-112,-112,-111,-111,-110,-110,
+         -109,-108,-108,-107,-106,-105,-104,-103,
+         -102,-101,-100, -99, -98, -97, -96, -95,
+          -94, -93, -91, -90, -89, -88, -86, -85,
+          -84, -82, -81, -79, -78, -76, -75, -73,
+          -71, -70, -68, -67, -65, -63, -62, -60, 
+          -58, -56, -55, -53, -51, -49, -47, -45,
+          -44, -42, -40, -38, -36, -34, -32, -30,
+          -28, -26, -24, -22, -20, -18, -16, -14,
+          -12, -10,  -8,  -6,  -4,  -2,   0,   1,
+            3,   5,   7,   9,  11,  13,  15,  17,
+           19,  21,  23,  25,  27,  29,  31,  33, 
+           35,  37,  39,  41,  43,  45,  46,  48,
+           50,  52,  54,  55,  57,  59,  61,  62,
+           64,  66,  67,  69,  71,  72,  74,  75,
+           77,  78,  80,  81,  83,  84,  86,  87,
+           88,  90,  91,  92,  93,  95,  96,  97,
+           98,  99, 100, 101, 102, 103, 104, 105,
+          106, 106, 107, 108, 109, 109, 110, 111,
+          111, 112, 112, 113, 113, 114, 114, 114,
+          115, 115, 115, 115, 116, 116, 116, 116,
+          116, 116, 116, 116, 116, 115, 115, 115,
+          115, 114, 114, 114, 113, 113, 112, 112,
+          111, 111, 110, 110, 109, 108, 108, 107, 
+          106, 105, 104, 103, 102, 101, 100,  99,
+           98,  97,  96,  95,  94,  93,  91,  90,
+           89,  88,  86,  85,  84,  82,  81,  79,  
+           78,  76,  75,  73,  71,  70,  68,  67,
+           65,  63,  62,  60,  58,  56,  55,  53,
+           51,  49,  47,  45,  44,  42,  40,  38,
+           36,  34,  32,  30,  28,  26,  24,  22,
+           20,  18,  16,  14,  12,  10,   8,   6,
+            4,   2,   0,  -1,  -3,  -5,  -7,  -9, -11};
+
+
+
+
 int sn9c20x_set_camera_control(struct usb_sn9c20x *dev,
        __u32 control, __u32 value)
 {
@@ -53,6 +337,18 @@ int sn9c20x_set_camera_control(struct usb_sn9c20x *dev,
                        ret = dev->camera.set_gamma(dev);
                }
                break;
+       case V4L2_CID_SATURATION:
+               if (dev->camera.set_saturation) {
+                       dev->vsettings.colour = value;
+                       ret = dev->camera.set_saturation(dev);
+               }
+               break;
+       case V4L2_CID_HUE:
+               if (dev->camera.set_hue) {
+                       dev->vsettings.hue = value;
+                       ret = dev->camera.set_hue(dev);
+               }
+               break;
        case V4L2_CID_SHARPNESS:
                if (dev->camera.set_sharpness) {
                        dev->vsettings.sharpness = value;
@@ -483,33 +779,101 @@ int sn9c20x_write_i2c_array(struct usb_sn9c20x *dev,
 }
 
 /**
- * @brief Set contrast inside sn9c20x chip
+ * @brief Calculate and set optical parameters
  *
- * @author Comer352l
+ * @author Comer352l, Boris Borisov
  *
  * @param dev Pointer to the device
  *
  * @return Zero (success) or negative (USB-error value)
  *
  */
-int sn9c20x_set_contrast(struct usb_sn9c20x *dev)
+int sn9c20x_set_optical_parameters(struct usb_sn9c20x *dev)
 {
-       /* from 0x26 to 0x4b */
-       __u8 brightness_contrast[21] = {0x16, 0x0, 0x2b, 0x0, 0x8, 0x0, 0xf6, 
0x0f,
+       __u8 optical_parameters[21]= {0x16, 0x0, 0x2b, 0x0, 0x8, 0x0, 0xf6, 
0x0f,
                                0xd2, 0x0f, 0x38, 0x0, 0x34, 0x0, 0xcf, 0x0f,
                                0xfd, 0x0f, 0x0, 0x0, 0x0};
+
+
        __u8 contrast_val = (dev->vsettings.contrast) * 0x25 / 0x100;
        __u8 brightness_val = dev->vsettings.brightness;
+       __u8 ret=0;
+//     __u8 value;
+//     __u8 i;
+       long tmp_coordinate;
 
+
+       if(dev->vsettings.hue<0)
+           dev->vsettings.hue=0;
+
+       if(dev->vsettings.hue>359)
+           dev->vsettings.hue=360;
+
+       //Brighness and contrast settings  
        brightness_val -= 0x80;
-       brightness_contrast[18] = brightness_val;
+       optical_parameters[18] = brightness_val;
 
        contrast_val += 0x26;
-       brightness_contrast[2] = contrast_val;
-       brightness_contrast[0] = 0x13 + (brightness_contrast[2] - 0x26) * 0x13 
/ 0x25;
-       brightness_contrast[4] = 0x7 + (brightness_contrast[2] - 0x26) * 0x7 / 
0x25;
+       optical_parameters[2] = contrast_val;
+       optical_parameters[0] = 0x13 + (optical_parameters[2] - 0x26) * 0x13 / 
0x25;
+       optical_parameters[4] = 0x7 + (optical_parameters[2] - 0x26) * 0x7 / 
0x25;
+
+       //Calculate HUE and SATURATION
+       tmp_coordinate=(long)(RX[dev->vsettings.hue]);
+       tmp_coordinate=(tmp_coordinate*dev->vsettings.colour) >> 8;
+       optical_parameters[6]=(unsigned char)(tmp_coordinate&0xff);
+       optical_parameters[7]=(unsigned char)((tmp_coordinate>>8)&0x0f);
+
+       tmp_coordinate=(long)(RY[dev->vsettings.hue]);
+       tmp_coordinate=(tmp_coordinate*dev->vsettings.colour) >> 8;
+       optical_parameters[8]=(unsigned char)(tmp_coordinate&0xff);
+       optical_parameters[9]=(unsigned char)((tmp_coordinate>>8)&0x0f);
+
+       tmp_coordinate=(long)(GX[dev->vsettings.hue]);
+       tmp_coordinate=(tmp_coordinate*dev->vsettings.colour) >> 8;
+       optical_parameters[10]=(unsigned char)(tmp_coordinate&0xff);
+       optical_parameters[11]=(unsigned char)((tmp_coordinate>>8)&0x0f);
+
+       tmp_coordinate=(long)(GY[dev->vsettings.hue]);
+       tmp_coordinate=(tmp_coordinate*dev->vsettings.colour) >> 8;
+       optical_parameters[12]=(unsigned char)(tmp_coordinate&0xff);
+       optical_parameters[13]=(unsigned char)((tmp_coordinate>>8)&0x0f);
+
+       tmp_coordinate=(long)(BX[dev->vsettings.hue]);
+       tmp_coordinate=(tmp_coordinate*dev->vsettings.colour) >> 8;
+       optical_parameters[14]=(unsigned char)(tmp_coordinate&0xff);
+       optical_parameters[15]=(unsigned char)((tmp_coordinate>>8)&0x0f);
+
+       tmp_coordinate=(long)(BY[dev->vsettings.hue]);
+       tmp_coordinate=(tmp_coordinate*dev->vsettings.colour) >> 8;
+       optical_parameters[16]=(unsigned char)(tmp_coordinate&0xff);
+       optical_parameters[17]=(unsigned char)((tmp_coordinate>>8)&0x0f);
+
+
+       ret=0;
+
+//     for(i=0;i<21;i++)
+//       {
+//           value=optical_parameters[i];
+//           ret|=usb_sn9c20x_control_write(dev, 0x10e1+i, &value, 1);
+//       }
+       ret=usb_sn9c20x_control_write(dev, 0x10e1, optical_parameters, 21);
+       return(ret);
+}
 
-       return usb_sn9c20x_control_write(dev, 0x10e1, brightness_contrast, 21);
+/**
+ * @brief Set contrast inside sn9c20x chip
+ *
+ * @author Comer352l
+ *
+ * @param dev Pointer to the device
+ *
+ * @return Zero (success) or negative (USB-error value)
+ *
+ */
+int sn9c20x_set_contrast(struct usb_sn9c20x *dev)
+{
+       return sn9c20x_set_optical_parameters(dev);
 }
 
 /**
@@ -526,7 +890,7 @@ int sn9c20x_set_contrast(struct usb_sn9c20x *dev)
  */
 int sn9c20x_set_brightness(struct usb_sn9c20x *dev)
 {
-       return sn9c20x_set_contrast(dev);
+       return sn9c20x_set_optical_parameters(dev);
 }
 
 /**
@@ -571,6 +935,36 @@ int sn9c20x_set_gamma(struct usb_sn9c20x *dev)
 }
 
 /**
+ * @brief Set saturation inside sn9c20x chip
+ *
+ * @author Neekhil
+ *
+ * @param dev Pointer to the device
+ *
+ * @return Zero (success) or negative (USB-error value)
+ *
+ */
+int sn9c20x_set_saturation(struct usb_sn9c20x *dev)
+{
+       return sn9c20x_set_optical_parameters(dev);
+}
+
+/**
+ * @brief Set hue inside sn9c20x chip
+ *
+ * @author Boris Borisov
+ *
+ * @param dev Pointer to the device
+ *
+ * @return Zero (success) or negative (USB-error value)
+ *
+ */
+int sn9c20x_set_hue(struct usb_sn9c20x *dev)
+{
+       return sn9c20x_set_optical_parameters(dev);
+}
+
+/**
  * @brief Set sharpness inside sn9c20x chip
  *
  * @author Comer352l
@@ -906,9 +1300,11 @@ int sn9c20x_initialize(struct usb_sn9c20x *dev)
        dev->camera.set_contrast = sn9c20x_set_contrast;
        dev->camera.set_brightness = sn9c20x_set_brightness;
        dev->camera.set_gamma = sn9c20x_set_gamma;
+       dev->camera.set_saturation = sn9c20x_set_saturation;
        dev->camera.set_sharpness = sn9c20x_set_sharpness;
        dev->camera.set_red_gain = sn9c20x_set_red_gain;
        dev->camera.set_blue_gain = sn9c20x_set_blue_gain;
+       dev->camera.set_hue = sn9c20x_set_hue;
 
        ret = sn9c20x_i2c_initialize(dev);
        if (ret < 0)
diff --git a/sn9c20x-dev.c b/sn9c20x-dev.c
index 11ac1f3..dd1eabf 100644
--- a/sn9c20x-dev.c
+++ b/sn9c20x-dev.c
@@ -173,7 +173,6 @@ int sn9c20x_initialize_sensor(struct usb_sn9c20x *dev)
                sn9c20x_write_i2c_array(dev, ov7660_init, 0);
                dev->camera.set_exposure = ov_set_exposure;
                dev->camera.set_auto_gain = ov_set_autogain;
-               dev->camera.set_gain = ov9650_set_gain;
                dev->camera.hstart = 1;
                dev->camera.vstart = 1;
                UDIA_INFO("Detected OV7660 Sensor.\n");
diff --git a/sn9c20x-sysfs.c b/sn9c20x-sysfs.c
index 15bb13c..d9190e0 100644
--- a/sn9c20x-sysfs.c
+++ b/sn9c20x-sysfs.c
@@ -400,30 +400,32 @@ static ssize_t store_contrast(struct device *class, 
struct device_attribute *att
 }
 
 
+
+
 /**
- * @brief show_whitebalance
+ * @brief show_saturation
  *
  * @param class Class device
  * @param attr
- * @retval buf Adress of buffer with the 'whitebalance' value
+ * @retval buf Adress of buffer with the 'contrast' value
  *
  * @returns Size of buffer
  */
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
-static ssize_t show_gamma(struct class_device *class, char *buf)
+static ssize_t show_saturation(struct class_device *class, char *buf)
 #else
-static ssize_t show_gamma(struct device *class, struct device_attribute *attr, 
char *buf)
+static ssize_t show_saturation(struct device *class, struct device_attribute 
*attr, char *buf)
 #endif
 {
        struct video_device *vdev = to_video_device(class);
        struct usb_sn9c20x *dev = video_get_drvdata(vdev);
 
-       return sprintf(buf, "%X\n", dev->vsettings.gamma);
+       return sprintf(buf, "%X\n", dev->vsettings.colour);
 }
 
 
 /**
- * @brief store_gamma
+ * @brief store_saturation
  *
  * @param class Class device
  * @param buf Buffer
@@ -433,9 +435,9 @@ static ssize_t show_gamma(struct device *class, struct 
device_attribute *attr, c
  * @returns Size of buffer
  */
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
-static ssize_t store_gamma(struct class_device *class, const char *buf, size_t 
count)
+static ssize_t store_saturation(struct class_device *class, const char *buf, 
size_t count)
 #else
-static ssize_t store_gamma(struct device *class, struct device_attribute *attr,
+static ssize_t store_saturation(struct device *class, struct device_attribute 
*attr,
                const char *buf, size_t count)
 #endif
 {
@@ -448,37 +450,38 @@ static ssize_t store_gamma(struct device *class, struct 
device_attribute *attr,
        value = simple_strtoul(buf, &endp, 16);
 
        sn9c20x_set_camera_control(dev,
-                                  V4L2_CID_GAMMA,
+                                  V4L2_CID_SATURATION,
                                   value);
 
        return strlen(buf);
 }
 
 
-/*
- * @brief show_colour
+
+/**
+ * @brief show_hue
  *
  * @param class Class device
  * @param attr
- * @retval buf Adress of buffer with the 'colour' value
+ * @retval buf Adress of buffer with the 'contrast' value
  *
  * @returns Size of buffer
  */
-/*#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
-static ssize_t show_colour(struct class_device *class, char *buf)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+static ssize_t show_hue(struct class_device *class, char *buf)
 #else
-static ssize_t show_colour(struct device *class, struct device_attribute 
*attr, char *buf)
+static ssize_t show_hue(struct device *class, struct device_attribute *attr, 
char *buf)
 #endif
 {
        struct video_device *vdev = to_video_device(class);
        struct usb_sn9c20x *dev = video_get_drvdata(vdev);
 
-       return sprintf(buf, "%X\n", dev->vsettings.colour);
+       return sprintf(buf, "%X\n", dev->vsettings.hue);
 }
-*/
 
-/*
- * @brief store_colour
+
+/**
+ * @brief store_hue
  *
  * @param class Class device
  * @param buf Buffer
@@ -487,10 +490,10 @@ static ssize_t show_colour(struct device *class, struct 
device_attribute *attr,
  *
  * @returns Size of buffer
  */
-/*#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
-static ssize_t store_colour(struct class_device *class, const char *buf, 
size_t count)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+static ssize_t store_hue(struct class_device *class, const char *buf, size_t 
count)
 #else
-static ssize_t store_colour(struct device *class, struct device_attribute 
*attr,
+static ssize_t store_hue(struct device *class, struct device_attribute *attr,
                const char *buf, size_t count)
 #endif
 {
@@ -502,13 +505,72 @@ static ssize_t store_colour(struct device *class, struct 
device_attribute *attr,
 
        value = simple_strtoul(buf, &endp, 16);
 
-       dev->vsettings.colour = (int) value;
+       sn9c20x_set_camera_control(dev,
+                                  V4L2_CID_HUE,
+                                  value);
+
+       return strlen(buf);
+}
 
-/      dev_sn9c20x_set_camera_quality(dev); /
+/////////////////////////////////////
+
+
+
+/**
+ * @brief show_whitebalance
+ *
+ * @param class Class device
+ * @param attr
+ * @retval buf Adress of buffer with the 'whitebalance' value
+ *
+ * @returns Size of buffer
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+static ssize_t show_gamma(struct class_device *class, char *buf)
+#else
+static ssize_t show_gamma(struct device *class, struct device_attribute *attr, 
char *buf)
+#endif
+{
+       struct video_device *vdev = to_video_device(class);
+       struct usb_sn9c20x *dev = video_get_drvdata(vdev);
+
+       return sprintf(buf, "%X\n", dev->vsettings.gamma);
+}
+
+
+/**
+ * @brief store_gamma
+ *
+ * @param class Class device
+ * @param buf Buffer
+ * @param count Counter
+ * @param attr
+ *
+ * @returns Size of buffer
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+static ssize_t store_gamma(struct class_device *class, const char *buf, size_t 
count)
+#else
+static ssize_t store_gamma(struct device *class, struct device_attribute *attr,
+               const char *buf, size_t count)
+#endif
+{
+       char *endp;
+       unsigned long value;
+
+       struct video_device *vdev = to_video_device(class);
+       struct usb_sn9c20x *dev = video_get_drvdata(vdev);
+
+       value = simple_strtoul(buf, &endp, 16);
+
+       sn9c20x_set_camera_control(dev,
+                                  V4L2_CID_GAMMA,
+                                  value);
 
        return strlen(buf);
 }
-*/
+
+
 
 
 /**
@@ -802,10 +864,11 @@ static CLASS_DEVICE_ATTR(fps, S_IRUGO, show_fps, NULL);   
                                                        /**< FPS value */
 static CLASS_DEVICE_ATTR(brightness, S_IRUGO | S_IWUGO, show_brightness, 
store_brightness);                    /**< Brightness value */
 static CLASS_DEVICE_ATTR(exposure, S_IRUGO | S_IWUGO, show_exposure, 
store_exposure);                          /**< Exposure value */
 static CLASS_DEVICE_ATTR(gain, S_IRUGO | S_IWUGO, show_gain, store_gain);      
                                /**< Gain value */
+static CLASS_DEVICE_ATTR(saturation, S_IRUGO | S_IWUGO, show_saturation, 
store_saturation);                    /**< Saturation value */
+static CLASS_DEVICE_ATTR(hue, S_IRUGO | S_IWUGO, show_hue, store_hue);         
                                /**< Hue value */
 static CLASS_DEVICE_ATTR(contrast, S_IRUGO | S_IWUGO, show_contrast, 
store_contrast);                          /**< Contrast value */
 static CLASS_DEVICE_ATTR(gamma, S_IRUGO | S_IWUGO, show_gamma, store_gamma); 
/**< Gamma value */
 static CLASS_DEVICE_ATTR(sharpness, S_IRUGO | S_IWUGO, show_sharpness, 
store_sharpness);                       /**< Sharpness value */
-/*static CLASS_DEVICE_ATTR(colour, S_IRUGO | S_IWUGO, show_colour, 
store_colour);                              /< Hue value */
 static CLASS_DEVICE_ATTR(hflip, S_IRUGO | S_IWUGO, show_hflip, store_hflip);   
                                /**< Horizontal flip value */
 static CLASS_DEVICE_ATTR(vflip, S_IRUGO | S_IWUGO, show_vflip, store_vflip);   
                                /**< Vertical flip value */
 static CLASS_DEVICE_ATTR(auto_exposure, S_IRUGO | S_IWUGO, show_autoexposure, 
store_autoexposure);             /**< Automatic exposure control value */
@@ -819,9 +882,10 @@ static DEVICE_ATTR(brightness, S_IRUGO | S_IWUGO, 
show_brightness, store_brightn
 static DEVICE_ATTR(exposure, S_IRUGO | S_IWUGO, show_exposure, 
store_exposure);                                        /**< Exposure value */
 static DEVICE_ATTR(gain, S_IRUGO | S_IWUGO, show_gain, store_gain);            
                                /**< Gain value */
 static DEVICE_ATTR(contrast, S_IRUGO | S_IWUGO, show_contrast, 
store_contrast);                                        /**< Contrast value */
-static DEVICE_ATTR(gamma, S_IRUGO | S_IWUGO, show_gamma, store_gamma); /**< 
Gamma value */
+static DEVICE_ATTR(saturation, S_IRUGO | S_IWUGO, show_saturation, 
store_saturation);                          /**< Saturation value */
+static DEVICE_ATTR(hue, S_IRUGO | S_IWUGO, show_hue, store_hue);               
                                /**< Hue value */
+static DEVICE_ATTR(gamma, S_IRUGO | S_IWUGO, show_gamma, store_gamma);         
                                        /**< Gamma value */
 static DEVICE_ATTR(sharpness, S_IRUGO | S_IWUGO, show_sharpness, 
store_sharpness);                             /**< Sharpness value */
-/*static DEVICE_ATTR(colour, S_IRUGO | S_IWUGO, show_colour, store_colour);    
                                /< Hue value */
 static DEVICE_ATTR(hflip, S_IRUGO | S_IWUGO, show_hflip, store_hflip);         
                                /**< Horizontal flip value */
 static DEVICE_ATTR(vflip, S_IRUGO | S_IWUGO, show_vflip, store_vflip);         
                                /**< Vertical flip value */
 static DEVICE_ATTR(auto_exposure, S_IRUGO | S_IWUGO, show_autoexposure, 
store_autoexposure);                   /**< Automatic exposure control value */
@@ -851,9 +915,10 @@ int sn9c20x_create_sysfs_files(struct video_device *vdev)
        ret = video_device_create_file(vdev, &class_device_attr_exposure);
        ret = video_device_create_file(vdev, &class_device_attr_gain);
        ret = video_device_create_file(vdev, &class_device_attr_contrast);
+       ret = video_device_create_file(vdev, &class_device_attr_saturation);
+       ret = video_device_create_file(vdev, &class_device_attr_hue);
        ret = video_device_create_file(vdev, &class_device_attr_gamma);
        ret = video_device_create_file(vdev, &class_device_attr_sharpness);
-       /*ret = video_device_create_file(vdev, &class_device_attr_colour);*/
        ret = video_device_create_file(vdev, &class_device_attr_hflip);
        ret = video_device_create_file(vdev, &class_device_attr_vflip);
        ret = video_device_create_file(vdev, &class_device_attr_auto_exposure);
@@ -867,9 +932,10 @@ int sn9c20x_create_sysfs_files(struct video_device *vdev)
        ret = video_device_create_file(vdev, &dev_attr_exposure);
        ret = video_device_create_file(vdev, &dev_attr_gain);
        ret = video_device_create_file(vdev, &dev_attr_contrast);
+       ret = video_device_create_file(vdev, &dev_attr_saturation);
+       ret = video_device_create_file(vdev, &dev_attr_hue);
        ret = video_device_create_file(vdev, &dev_attr_gamma);
        ret = video_device_create_file(vdev, &dev_attr_sharpness);
-       /*ret = video_device_create_file(vdev, &dev_attr_colour);*/
        ret = video_device_create_file(vdev, &dev_attr_hflip);
        ret = video_device_create_file(vdev, &dev_attr_vflip);
        ret = video_device_create_file(vdev, &dev_attr_auto_exposure);
@@ -883,9 +949,10 @@ int sn9c20x_create_sysfs_files(struct video_device *vdev)
        ret = device_create_file(&vdev->dev, &dev_attr_exposure);
        ret = device_create_file(&vdev->dev, &dev_attr_gain);
        ret = device_create_file(&vdev->dev, &dev_attr_contrast);
+       ret = device_create_file(&vdev->dev, &dev_attr_saturation);
+       ret = device_create_file(&vdev->dev, &dev_attr_hue);
        ret = device_create_file(&vdev->dev, &dev_attr_gamma);
        ret = device_create_file(&vdev->dev, &dev_attr_sharpness);
-       /*ret = video_device_create_file(vdev, &dev_attr_colour);*/
        ret = device_create_file(&vdev->dev, &dev_attr_hflip);
        ret = device_create_file(&vdev->dev, &dev_attr_vflip);
        ret = device_create_file(&vdev->dev, &dev_attr_auto_exposure);
@@ -915,9 +982,10 @@ void sn9c20x_remove_sysfs_files(struct video_device *vdev)
        video_device_remove_file(vdev, &class_device_attr_exposure);
        video_device_remove_file(vdev, &class_device_attr_gain);
        video_device_remove_file(vdev, &class_device_attr_contrast);
+       video_device_remove_file(vdev, &class_device_attr_saturation);
+       video_device_remove_file(vdev, &class_device_attr_hue);
        video_device_remove_file(vdev, &class_device_attr_gamma);
        video_device_remove_file(vdev, &class_device_attr_sharpness);
-       /*video_device_remove_file(vdev, &class_device_attr_colour);*/
        video_device_remove_file(vdev, &class_device_attr_hflip);
        video_device_remove_file(vdev, &class_device_attr_vflip);
        video_device_remove_file(vdev, &class_device_attr_auto_exposure);
@@ -931,9 +999,10 @@ void sn9c20x_remove_sysfs_files(struct video_device *vdev)
        video_device_remove_file(vdev, &dev_attr_exposure);
        video_device_remove_file(vdev, &dev_attr_gain);
        video_device_remove_file(vdev, &dev_attr_contrast);
+       video_device_remove_file(vdev, &dev_attr_saturation);
+       video_device_remove_file(vdev, &dev_attr_hue);
        video_device_remove_file(vdev, &dev_attr_gamma);
        video_device_remove_file(vdev, &dev_attr_sharpness);
-       /*video_device_remove_file(vdev, &dev_attr_colour);*/
        video_device_remove_file(vdev, &dev_attr_hflip);
        video_device_remove_file(vdev, &dev_attr_vflip);
        video_device_remove_file(vdev, &dev_attr_auto_exposure);
@@ -947,9 +1016,10 @@ void sn9c20x_remove_sysfs_files(struct video_device *vdev)
        device_remove_file(&vdev->dev, &dev_attr_exposure);
        device_remove_file(&vdev->dev, &dev_attr_gain);
        device_remove_file(&vdev->dev, &dev_attr_contrast);
+       device_remove_file(&vdev->dev, &dev_attr_saturation);
+       device_remove_file(&vdev->dev, &dev_attr_hue);
        device_remove_file(&vdev->dev, &dev_attr_gamma);
        device_remove_file(&vdev->dev, &dev_attr_sharpness);
-       /*video_device_remove_file(vdev, &dev_attr_colour);*/
        device_remove_file(&vdev->dev, &dev_attr_hflip);
        device_remove_file(&vdev->dev, &dev_attr_vflip);
        device_remove_file(&vdev->dev, &dev_attr_auto_exposure);
diff --git a/sn9c20x-usb.c b/sn9c20x-usb.c
index 17d8c2e..252995d 100644
--- a/sn9c20x-usb.c
+++ b/sn9c20x-usb.c
@@ -96,6 +96,18 @@ static __u16 brightness = SN9C20X_PERCENT(50, 0xFF);
 static __u16 gamma = SN9C20X_PERCENT(20, 0xFF);
 
 /**
+ * @var saturation
+ *   Module parameter to set the gamma
+ */
+static __u16 saturation = SN9C20X_PERCENT(50, 0xFF);
+
+/**
+ * @var hue
+ *   Module parameter to set the gamma
+ */
+static __u16 hue = SN9C20X_PERCENT(50, 0x168);
+
+/**
  * @var contrast
  *   Module parameter to set the contrast
  */
@@ -111,7 +123,7 @@ static __u16 exposure = SN9C20X_PERCENT(20, 0xFF);
  * @var gain
  *   Module parameter to set the gain
  */
-static __u16 gain = SN9C20X_PERCENT(20, 0xFF);
+static int gain = SN9C20X_PERCENT(20, 0xFF);
 
 /**
  * @var sharpness
@@ -720,6 +732,8 @@ static int usb_sn9c20x_default_settings(struct usb_sn9c20x 
*dev)
        v4l2_set_control_default(dev, V4L2_CID_BRIGHTNESS, brightness);
        v4l2_set_control_default(dev, V4L2_CID_CONTRAST, contrast);
        v4l2_set_control_default(dev, V4L2_CID_GAMMA, gamma);
+       v4l2_set_control_default(dev, V4L2_CID_SATURATION, saturation);
+       v4l2_set_control_default(dev, V4L2_CID_HUE, hue);
        v4l2_set_control_default(dev, V4L2_CID_SHARPNESS, sharpness);
        v4l2_set_control_default(dev, V4L2_CID_RED_BALANCE, red_gain);
        v4l2_set_control_default(dev, V4L2_CID_BLUE_BALANCE, blue_gain);
@@ -898,6 +912,7 @@ module_param(auto_gain, byte, 0444);                /**< 
@brief Module parameter automatic gai
 module_param(auto_whitebalance, byte, 0444);   /**< @brief Module parameter 
automatic whitebalance control */
 module_param(brightness, ushort, 0444);                /**< @brief Module 
parameter brightness */
 module_param(gamma, ushort, 0444);             /**< @brief Module parameter 
gamma */
+module_param(saturation, ushort, 0444);                /**< @brief Module 
parameter saturation */
 module_param(contrast, ushort, 0444);          /**< @brief Module parameter 
contrast */
 module_param(exposure, ushort, 0444);          /**< @brief Module parameter 
exposure */
 module_param(sharpness, ushort, 0444);         /**< @brief Module parameter 
sharpness */
@@ -1046,6 +1061,7 @@ MODULE_PARM_DESC(auto_gain, "Automatic gain control");    
        /**< @brief Description
 MODULE_PARM_DESC(auto_whitebalance, "Automatic whitebalance"); /**< @brief 
Description of 'auto_whitebalance' parameter */
 MODULE_PARM_DESC(brightness, "Brightness setting");            /**< @brief 
Description of 'brightness' parameter */
 MODULE_PARM_DESC(gamma, "Gamma setting");                      /**< @brief 
Description of 'gamma' parameter */
+MODULE_PARM_DESC(saturation, "Saturation setting");            /**< @brief 
Description of 'saturation' parameter */
 MODULE_PARM_DESC(exposure, "Exposure setting");                        /**< 
@brief Description of 'exposure' parameter */
 MODULE_PARM_DESC(gain, "Gain setting");                                /**< 
@brief Description of 'gain' parameter */
 MODULE_PARM_DESC(contrast, "Contrast setting");                        /**< 
@brief Description of 'contrast' parameter */
diff --git a/sn9c20x-v4l2.c b/sn9c20x-v4l2.c
index b762678..a41bb09 100644
--- a/sn9c20x-v4l2.c
+++ b/sn9c20x-v4l2.c
@@ -68,7 +68,7 @@ static struct v4l2_queryctrl sn9c20x_controls[] = {
                .maximum = 0xff,
                .step    = 1,
        },
-/*
+
        {
                .id      = V4L2_CID_SATURATION,
                .type    = V4L2_CTRL_TYPE_INTEGER,
@@ -77,7 +77,16 @@ static struct v4l2_queryctrl sn9c20x_controls[] = {
                .maximum = 0xff,
                .step    = 1,
        },
-*/
+
+       {
+               .id      = V4L2_CID_HUE,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Hue",
+               .minimum = 0,
+               .maximum = 360,
+               .step    = 1,
+       },
+
        {
                .id      = V4L2_CID_CONTRAST,
                .type    = V4L2_CTRL_TYPE_INTEGER,
@@ -856,11 +865,15 @@ int sn9c20x_vidioc_g_ctrl(struct file *file, void *priv,
        case V4L2_CID_GAMMA:
                ctrl->value = dev->vsettings.gamma;
                break;
-/*
+
        case V4L2_CID_SATURATION:
                ctrl->value = dev->vsettings.colour;
                break;
-*/
+
+       case V4L2_CID_HUE:
+               ctrl->value = dev->vsettings.hue;
+               break;
+
        case V4L2_CID_CONTRAST:
                ctrl->value = dev->vsettings.contrast;
                break;
diff --git a/sn9c20x.h b/sn9c20x.h
index 6a846a4..b26ed0c 100644
--- a/sn9c20x.h
+++ b/sn9c20x.h
@@ -326,9 +326,11 @@ struct sn9c20x_camera {
        int (*set_contrast) (struct usb_sn9c20x *dev);
        int (*set_brightness) (struct usb_sn9c20x *dev);
        int (*set_gamma) (struct usb_sn9c20x *dev);
+       int (*set_saturation) (struct usb_sn9c20x *dev);
        int (*set_sharpness) (struct usb_sn9c20x *dev);
        int (*set_red_gain) (struct usb_sn9c20x *dev);
        int (*set_blue_gain) (struct usb_sn9c20x *dev);
+       int (*set_hue) (struct usb_sn9c20x *dev);
 };
 
 /**

Reply via email to