1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
2 | /* |
3 | * Pixart PAC207BCA / PAC73xx common functions |
4 | * |
5 | * Copyright (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl> |
6 | * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li |
7 | * Copyleft (C) 2005 Michel Xhaard mxhaard@magic.fr |
8 | * |
9 | * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> |
10 | */ |
11 | |
12 | /* We calculate the autogain at the end of the transfer of a frame, at this |
13 | moment a frame with the old settings is being captured and transmitted. So |
14 | if we adjust the gain or exposure we must ignore at least the next frame for |
15 | the new settings to come into effect before doing any other adjustments. */ |
16 | #define PAC_AUTOGAIN_IGNORE_FRAMES 2 |
17 | |
18 | static const unsigned char pac_sof_marker[5] = |
19 | { 0xff, 0xff, 0x00, 0xff, 0x96 }; |
20 | |
21 | /* |
22 | The following state machine finds the SOF marker sequence |
23 | 0xff, 0xff, 0x00, 0xff, 0x96 in a byte stream. |
24 | |
25 | +----------+ |
26 | | 0: START |<---------------\ |
27 | +----------+<-\ | |
28 | | \---/otherwise | |
29 | v 0xff | |
30 | +----------+ otherwise | |
31 | | 1 |--------------->* |
32 | | | ^ |
33 | +----------+ | |
34 | | | |
35 | v 0xff | |
36 | +----------+<-\0xff | |
37 | /->| |--/ | |
38 | | | 2 |--------------->* |
39 | | | | otherwise ^ |
40 | | +----------+ | |
41 | | | | |
42 | | v 0x00 | |
43 | | +----------+ | |
44 | | | 3 | | |
45 | | | |--------------->* |
46 | | +----------+ otherwise ^ |
47 | | | | |
48 | 0xff | v 0xff | |
49 | | +----------+ | |
50 | \--| 4 | | |
51 | | |----------------/ |
52 | +----------+ otherwise |
53 | | |
54 | v 0x96 |
55 | +----------+ |
56 | | FOUND | |
57 | +----------+ |
58 | */ |
59 | |
60 | static unsigned char *pac_find_sof(struct gspca_dev *gspca_dev, u8 *sof_read, |
61 | unsigned char *m, int len) |
62 | { |
63 | int i; |
64 | |
65 | /* Search for the SOF marker (fixed part) in the header */ |
66 | for (i = 0; i < len; i++) { |
67 | switch (*sof_read) { |
68 | case 0: |
69 | if (m[i] == 0xff) |
70 | *sof_read = 1; |
71 | break; |
72 | case 1: |
73 | if (m[i] == 0xff) |
74 | *sof_read = 2; |
75 | else |
76 | *sof_read = 0; |
77 | break; |
78 | case 2: |
79 | switch (m[i]) { |
80 | case 0x00: |
81 | *sof_read = 3; |
82 | break; |
83 | case 0xff: |
84 | /* stay in this state */ |
85 | break; |
86 | default: |
87 | *sof_read = 0; |
88 | } |
89 | break; |
90 | case 3: |
91 | if (m[i] == 0xff) |
92 | *sof_read = 4; |
93 | else |
94 | *sof_read = 0; |
95 | break; |
96 | case 4: |
97 | switch (m[i]) { |
98 | case 0x96: |
99 | /* Pattern found */ |
100 | gspca_dbg(gspca_dev, D_FRAM, |
101 | "SOF found, bytes to analyze: %u - Frame starts at byte #%u\n" , |
102 | len, i + 1); |
103 | *sof_read = 0; |
104 | return m + i + 1; |
105 | break; |
106 | case 0xff: |
107 | *sof_read = 2; |
108 | break; |
109 | default: |
110 | *sof_read = 0; |
111 | } |
112 | break; |
113 | default: |
114 | *sof_read = 0; |
115 | } |
116 | } |
117 | |
118 | return NULL; |
119 | } |
120 | |