162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Pixart PAC207BCA / PAC73xx common functions 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl> 662306a36Sopenharmony_ci * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li 762306a36Sopenharmony_ci * Copyleft (C) 2005 Michel Xhaard mxhaard@magic.fr 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci/* We calculate the autogain at the end of the transfer of a frame, at this 1362306a36Sopenharmony_ci moment a frame with the old settings is being captured and transmitted. So 1462306a36Sopenharmony_ci if we adjust the gain or exposure we must ignore at least the next frame for 1562306a36Sopenharmony_ci the new settings to come into effect before doing any other adjustments. */ 1662306a36Sopenharmony_ci#define PAC_AUTOGAIN_IGNORE_FRAMES 2 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic const unsigned char pac_sof_marker[5] = 1962306a36Sopenharmony_ci { 0xff, 0xff, 0x00, 0xff, 0x96 }; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/* 2262306a36Sopenharmony_ci The following state machine finds the SOF marker sequence 2362306a36Sopenharmony_ci 0xff, 0xff, 0x00, 0xff, 0x96 in a byte stream. 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci +----------+ 2662306a36Sopenharmony_ci | 0: START |<---------------\ 2762306a36Sopenharmony_ci +----------+<-\ | 2862306a36Sopenharmony_ci | \---/otherwise | 2962306a36Sopenharmony_ci v 0xff | 3062306a36Sopenharmony_ci +----------+ otherwise | 3162306a36Sopenharmony_ci | 1 |--------------->* 3262306a36Sopenharmony_ci | | ^ 3362306a36Sopenharmony_ci +----------+ | 3462306a36Sopenharmony_ci | | 3562306a36Sopenharmony_ci v 0xff | 3662306a36Sopenharmony_ci +----------+<-\0xff | 3762306a36Sopenharmony_ci /->| |--/ | 3862306a36Sopenharmony_ci | | 2 |--------------->* 3962306a36Sopenharmony_ci | | | otherwise ^ 4062306a36Sopenharmony_ci | +----------+ | 4162306a36Sopenharmony_ci | | | 4262306a36Sopenharmony_ci | v 0x00 | 4362306a36Sopenharmony_ci | +----------+ | 4462306a36Sopenharmony_ci | | 3 | | 4562306a36Sopenharmony_ci | | |--------------->* 4662306a36Sopenharmony_ci | +----------+ otherwise ^ 4762306a36Sopenharmony_ci | | | 4862306a36Sopenharmony_ci 0xff | v 0xff | 4962306a36Sopenharmony_ci | +----------+ | 5062306a36Sopenharmony_ci \--| 4 | | 5162306a36Sopenharmony_ci | |----------------/ 5262306a36Sopenharmony_ci +----------+ otherwise 5362306a36Sopenharmony_ci | 5462306a36Sopenharmony_ci v 0x96 5562306a36Sopenharmony_ci +----------+ 5662306a36Sopenharmony_ci | FOUND | 5762306a36Sopenharmony_ci +----------+ 5862306a36Sopenharmony_ci*/ 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistatic unsigned char *pac_find_sof(struct gspca_dev *gspca_dev, u8 *sof_read, 6162306a36Sopenharmony_ci unsigned char *m, int len) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci int i; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci /* Search for the SOF marker (fixed part) in the header */ 6662306a36Sopenharmony_ci for (i = 0; i < len; i++) { 6762306a36Sopenharmony_ci switch (*sof_read) { 6862306a36Sopenharmony_ci case 0: 6962306a36Sopenharmony_ci if (m[i] == 0xff) 7062306a36Sopenharmony_ci *sof_read = 1; 7162306a36Sopenharmony_ci break; 7262306a36Sopenharmony_ci case 1: 7362306a36Sopenharmony_ci if (m[i] == 0xff) 7462306a36Sopenharmony_ci *sof_read = 2; 7562306a36Sopenharmony_ci else 7662306a36Sopenharmony_ci *sof_read = 0; 7762306a36Sopenharmony_ci break; 7862306a36Sopenharmony_ci case 2: 7962306a36Sopenharmony_ci switch (m[i]) { 8062306a36Sopenharmony_ci case 0x00: 8162306a36Sopenharmony_ci *sof_read = 3; 8262306a36Sopenharmony_ci break; 8362306a36Sopenharmony_ci case 0xff: 8462306a36Sopenharmony_ci /* stay in this state */ 8562306a36Sopenharmony_ci break; 8662306a36Sopenharmony_ci default: 8762306a36Sopenharmony_ci *sof_read = 0; 8862306a36Sopenharmony_ci } 8962306a36Sopenharmony_ci break; 9062306a36Sopenharmony_ci case 3: 9162306a36Sopenharmony_ci if (m[i] == 0xff) 9262306a36Sopenharmony_ci *sof_read = 4; 9362306a36Sopenharmony_ci else 9462306a36Sopenharmony_ci *sof_read = 0; 9562306a36Sopenharmony_ci break; 9662306a36Sopenharmony_ci case 4: 9762306a36Sopenharmony_ci switch (m[i]) { 9862306a36Sopenharmony_ci case 0x96: 9962306a36Sopenharmony_ci /* Pattern found */ 10062306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_FRAM, 10162306a36Sopenharmony_ci "SOF found, bytes to analyze: %u - Frame starts at byte #%u\n", 10262306a36Sopenharmony_ci len, i + 1); 10362306a36Sopenharmony_ci *sof_read = 0; 10462306a36Sopenharmony_ci return m + i + 1; 10562306a36Sopenharmony_ci break; 10662306a36Sopenharmony_ci case 0xff: 10762306a36Sopenharmony_ci *sof_read = 2; 10862306a36Sopenharmony_ci break; 10962306a36Sopenharmony_ci default: 11062306a36Sopenharmony_ci *sof_read = 0; 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci break; 11362306a36Sopenharmony_ci default: 11462306a36Sopenharmony_ci *sof_read = 0; 11562306a36Sopenharmony_ci } 11662306a36Sopenharmony_ci } 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci return NULL; 11962306a36Sopenharmony_ci} 120