diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2010-05-10 02:51:02 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-06-01 00:19:04 -0400 |
commit | 483d67ff0a208b43f0b97fca91d3a142afaba7fa (patch) | |
tree | 96447b0b3ecac1492235b076c25330a3360a604a | |
parent | 67a3e12b05e055c0415c556a315a3d3eb637e29e (diff) |
V4L/DVB: bw-qcam: convert to V4L2
Note: due to lack of hardware I was not able to test this conversion.
But it is pretty straightforward, so I do not expect any problems.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/Kconfig | 2 | ||||
-rw-r--r-- | drivers/media/video/bw-qcam.c | 759 | ||||
-rw-r--r-- | drivers/media/video/bw-qcam.h | 69 |
3 files changed, 415 insertions, 415 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index ad9e6f9c22e9..42d198d5a87e 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -646,7 +646,7 @@ config VIDEO_PMS | |||
646 | 646 | ||
647 | config VIDEO_BWQCAM | 647 | config VIDEO_BWQCAM |
648 | tristate "Quickcam BW Video For Linux" | 648 | tristate "Quickcam BW Video For Linux" |
649 | depends on PARPORT && VIDEO_V4L1 | 649 | depends on PARPORT && VIDEO_V4L2 |
650 | help | 650 | help |
651 | Say Y have if you the black and white version of the QuickCam | 651 | Say Y have if you the black and white version of the QuickCam |
652 | camera. See the next option for the color version. | 652 | camera. See the next option for the color version. |
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index 3c9e754d73a0..935e0c9a9674 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c | |||
@@ -66,19 +66,58 @@ OTHER DEALINGS IN THE SOFTWARE. | |||
66 | #include <linux/delay.h> | 66 | #include <linux/delay.h> |
67 | #include <linux/errno.h> | 67 | #include <linux/errno.h> |
68 | #include <linux/fs.h> | 68 | #include <linux/fs.h> |
69 | #include <linux/init.h> | ||
70 | #include <linux/kernel.h> | 69 | #include <linux/kernel.h> |
71 | #include <linux/slab.h> | 70 | #include <linux/slab.h> |
72 | #include <linux/mm.h> | 71 | #include <linux/mm.h> |
73 | #include <linux/parport.h> | 72 | #include <linux/parport.h> |
74 | #include <linux/sched.h> | 73 | #include <linux/sched.h> |
75 | #include <linux/videodev.h> | 74 | #include <linux/version.h> |
76 | #include <media/v4l2-common.h> | 75 | #include <linux/videodev2.h> |
77 | #include <media/v4l2-ioctl.h> | ||
78 | #include <linux/mutex.h> | 76 | #include <linux/mutex.h> |
79 | #include <asm/uaccess.h> | 77 | #include <asm/uaccess.h> |
80 | 78 | #include <media/v4l2-common.h> | |
81 | #include "bw-qcam.h" | 79 | #include <media/v4l2-ioctl.h> |
80 | #include <media/v4l2-device.h> | ||
81 | |||
82 | /* One from column A... */ | ||
83 | #define QC_NOTSET 0 | ||
84 | #define QC_UNIDIR 1 | ||
85 | #define QC_BIDIR 2 | ||
86 | #define QC_SERIAL 3 | ||
87 | |||
88 | /* ... and one from column B */ | ||
89 | #define QC_ANY 0x00 | ||
90 | #define QC_FORCE_UNIDIR 0x10 | ||
91 | #define QC_FORCE_BIDIR 0x20 | ||
92 | #define QC_FORCE_SERIAL 0x30 | ||
93 | /* in the port_mode member */ | ||
94 | |||
95 | #define QC_MODE_MASK 0x07 | ||
96 | #define QC_FORCE_MASK 0x70 | ||
97 | |||
98 | #define MAX_HEIGHT 243 | ||
99 | #define MAX_WIDTH 336 | ||
100 | |||
101 | /* Bit fields for status flags */ | ||
102 | #define QC_PARAM_CHANGE 0x01 /* Camera status change has occurred */ | ||
103 | |||
104 | struct qcam { | ||
105 | struct v4l2_device v4l2_dev; | ||
106 | struct video_device vdev; | ||
107 | struct pardevice *pdev; | ||
108 | struct parport *pport; | ||
109 | struct mutex lock; | ||
110 | int width, height; | ||
111 | int bpp; | ||
112 | int mode; | ||
113 | int contrast, brightness, whitebal; | ||
114 | int port_mode; | ||
115 | int transfer_scale; | ||
116 | int top, left; | ||
117 | int status; | ||
118 | unsigned int saved_bits; | ||
119 | unsigned long in_use; | ||
120 | }; | ||
82 | 121 | ||
83 | static unsigned int maxpoll = 250; /* Maximum busy-loop count for qcam I/O */ | 122 | static unsigned int maxpoll = 250; /* Maximum busy-loop count for qcam I/O */ |
84 | static unsigned int yieldlines = 4; /* Yield after this many during capture */ | 123 | static unsigned int yieldlines = 4; /* Yield after this many during capture */ |
@@ -93,22 +132,26 @@ module_param(video_nr, int, 0); | |||
93 | * immediately attempt to initialize qcam */ | 132 | * immediately attempt to initialize qcam */ |
94 | module_param(force_init, int, 0); | 133 | module_param(force_init, int, 0); |
95 | 134 | ||
96 | static inline int read_lpstatus(struct qcam_device *q) | 135 | #define MAX_CAMS 4 |
136 | static struct qcam *qcams[MAX_CAMS]; | ||
137 | static unsigned int num_cams; | ||
138 | |||
139 | static inline int read_lpstatus(struct qcam *q) | ||
97 | { | 140 | { |
98 | return parport_read_status(q->pport); | 141 | return parport_read_status(q->pport); |
99 | } | 142 | } |
100 | 143 | ||
101 | static inline int read_lpdata(struct qcam_device *q) | 144 | static inline int read_lpdata(struct qcam *q) |
102 | { | 145 | { |
103 | return parport_read_data(q->pport); | 146 | return parport_read_data(q->pport); |
104 | } | 147 | } |
105 | 148 | ||
106 | static inline void write_lpdata(struct qcam_device *q, int d) | 149 | static inline void write_lpdata(struct qcam *q, int d) |
107 | { | 150 | { |
108 | parport_write_data(q->pport, d); | 151 | parport_write_data(q->pport, d); |
109 | } | 152 | } |
110 | 153 | ||
111 | static inline void write_lpcontrol(struct qcam_device *q, int d) | 154 | static void write_lpcontrol(struct qcam *q, int d) |
112 | { | 155 | { |
113 | if (d & 0x20) { | 156 | if (d & 0x20) { |
114 | /* Set bidirectional mode to reverse (data in) */ | 157 | /* Set bidirectional mode to reverse (data in) */ |
@@ -124,126 +167,11 @@ static inline void write_lpcontrol(struct qcam_device *q, int d) | |||
124 | parport_write_control(q->pport, d); | 167 | parport_write_control(q->pport, d); |
125 | } | 168 | } |
126 | 169 | ||
127 | static int qc_waithand(struct qcam_device *q, int val); | ||
128 | static int qc_command(struct qcam_device *q, int command); | ||
129 | static int qc_readparam(struct qcam_device *q); | ||
130 | static int qc_setscanmode(struct qcam_device *q); | ||
131 | static int qc_readbytes(struct qcam_device *q, char buffer[]); | ||
132 | |||
133 | static struct video_device qcam_template; | ||
134 | |||
135 | static int qc_calibrate(struct qcam_device *q) | ||
136 | { | ||
137 | /* | ||
138 | * Bugfix by Hanno Mueller hmueller@kabel.de, Mai 21 96 | ||
139 | * The white balance is an individiual value for each | ||
140 | * quickcam. | ||
141 | */ | ||
142 | |||
143 | int value; | ||
144 | int count = 0; | ||
145 | |||
146 | qc_command(q, 27); /* AutoAdjustOffset */ | ||
147 | qc_command(q, 0); /* Dummy Parameter, ignored by the camera */ | ||
148 | |||
149 | /* GetOffset (33) will read 255 until autocalibration */ | ||
150 | /* is finished. After that, a value of 1-254 will be */ | ||
151 | /* returned. */ | ||
152 | |||
153 | do { | ||
154 | qc_command(q, 33); | ||
155 | value = qc_readparam(q); | ||
156 | mdelay(1); | ||
157 | schedule(); | ||
158 | count++; | ||
159 | } while (value == 0xff && count < 2048); | ||
160 | |||
161 | q->whitebal = value; | ||
162 | return value; | ||
163 | } | ||
164 | |||
165 | /* Initialize the QuickCam driver control structure. This is where | ||
166 | * defaults are set for people who don't have a config file.*/ | ||
167 | |||
168 | static struct qcam_device *qcam_init(struct parport *port) | ||
169 | { | ||
170 | struct qcam_device *q; | ||
171 | |||
172 | q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL); | ||
173 | if (q == NULL) | ||
174 | return NULL; | ||
175 | |||
176 | q->pport = port; | ||
177 | q->pdev = parport_register_device(port, "bw-qcam", NULL, NULL, | ||
178 | NULL, 0, NULL); | ||
179 | if (q->pdev == NULL) { | ||
180 | printk(KERN_ERR "bw-qcam: couldn't register for %s.\n", | ||
181 | port->name); | ||
182 | kfree(q); | ||
183 | return NULL; | ||
184 | } | ||
185 | |||
186 | memcpy(&q->vdev, &qcam_template, sizeof(qcam_template)); | ||
187 | |||
188 | mutex_init(&q->lock); | ||
189 | |||
190 | q->port_mode = (QC_ANY | QC_NOTSET); | ||
191 | q->width = 320; | ||
192 | q->height = 240; | ||
193 | q->bpp = 4; | ||
194 | q->transfer_scale = 2; | ||
195 | q->contrast = 192; | ||
196 | q->brightness = 180; | ||
197 | q->whitebal = 105; | ||
198 | q->top = 1; | ||
199 | q->left = 14; | ||
200 | q->mode = -1; | ||
201 | q->status = QC_PARAM_CHANGE; | ||
202 | return q; | ||
203 | } | ||
204 | |||
205 | |||
206 | /* qc_command is probably a bit of a misnomer -- it's used to send | ||
207 | * bytes *to* the camera. Generally, these bytes are either commands | ||
208 | * or arguments to commands, so the name fits, but it still bugs me a | ||
209 | * bit. See the documentation for a list of commands. */ | ||
210 | |||
211 | static int qc_command(struct qcam_device *q, int command) | ||
212 | { | ||
213 | int n1, n2; | ||
214 | int cmd; | ||
215 | |||
216 | write_lpdata(q, command); | ||
217 | write_lpcontrol(q, 6); | ||
218 | |||
219 | n1 = qc_waithand(q, 1); | ||
220 | |||
221 | write_lpcontrol(q, 0xe); | ||
222 | n2 = qc_waithand(q, 0); | ||
223 | |||
224 | cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4); | ||
225 | return cmd; | ||
226 | } | ||
227 | |||
228 | static int qc_readparam(struct qcam_device *q) | ||
229 | { | ||
230 | int n1, n2; | ||
231 | int cmd; | ||
232 | |||
233 | write_lpcontrol(q, 6); | ||
234 | n1 = qc_waithand(q, 1); | ||
235 | |||
236 | write_lpcontrol(q, 0xe); | ||
237 | n2 = qc_waithand(q, 0); | ||
238 | |||
239 | cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4); | ||
240 | return cmd; | ||
241 | } | ||
242 | 170 | ||
243 | /* qc_waithand busy-waits for a handshake signal from the QuickCam. | 171 | /* qc_waithand busy-waits for a handshake signal from the QuickCam. |
244 | * Almost all communication with the camera requires handshaking. */ | 172 | * Almost all communication with the camera requires handshaking. */ |
245 | 173 | ||
246 | static int qc_waithand(struct qcam_device *q, int val) | 174 | static int qc_waithand(struct qcam *q, int val) |
247 | { | 175 | { |
248 | int status; | 176 | int status; |
249 | int runs = 0; | 177 | int runs = 0; |
@@ -286,7 +214,7 @@ static int qc_waithand(struct qcam_device *q, int val) | |||
286 | * (bit 3 of status register). It also returns the last value read, | 214 | * (bit 3 of status register). It also returns the last value read, |
287 | * since this data is useful. */ | 215 | * since this data is useful. */ |
288 | 216 | ||
289 | static unsigned int qc_waithand2(struct qcam_device *q, int val) | 217 | static unsigned int qc_waithand2(struct qcam *q, int val) |
290 | { | 218 | { |
291 | unsigned int status; | 219 | unsigned int status; |
292 | int runs = 0; | 220 | int runs = 0; |
@@ -309,6 +237,43 @@ static unsigned int qc_waithand2(struct qcam_device *q, int val) | |||
309 | return status; | 237 | return status; |
310 | } | 238 | } |
311 | 239 | ||
240 | /* qc_command is probably a bit of a misnomer -- it's used to send | ||
241 | * bytes *to* the camera. Generally, these bytes are either commands | ||
242 | * or arguments to commands, so the name fits, but it still bugs me a | ||
243 | * bit. See the documentation for a list of commands. */ | ||
244 | |||
245 | static int qc_command(struct qcam *q, int command) | ||
246 | { | ||
247 | int n1, n2; | ||
248 | int cmd; | ||
249 | |||
250 | write_lpdata(q, command); | ||
251 | write_lpcontrol(q, 6); | ||
252 | |||
253 | n1 = qc_waithand(q, 1); | ||
254 | |||
255 | write_lpcontrol(q, 0xe); | ||
256 | n2 = qc_waithand(q, 0); | ||
257 | |||
258 | cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4); | ||
259 | return cmd; | ||
260 | } | ||
261 | |||
262 | static int qc_readparam(struct qcam *q) | ||
263 | { | ||
264 | int n1, n2; | ||
265 | int cmd; | ||
266 | |||
267 | write_lpcontrol(q, 6); | ||
268 | n1 = qc_waithand(q, 1); | ||
269 | |||
270 | write_lpcontrol(q, 0xe); | ||
271 | n2 = qc_waithand(q, 0); | ||
272 | |||
273 | cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4); | ||
274 | return cmd; | ||
275 | } | ||
276 | |||
312 | 277 | ||
313 | /* Try to detect a QuickCam. It appears to flash the upper 4 bits of | 278 | /* Try to detect a QuickCam. It appears to flash the upper 4 bits of |
314 | the status register at 5-10 Hz. This is only used in the autoprobe | 279 | the status register at 5-10 Hz. This is only used in the autoprobe |
@@ -317,7 +282,7 @@ static unsigned int qc_waithand2(struct qcam_device *q, int val) | |||
317 | almost completely safe, while their method screws up my printer if | 282 | almost completely safe, while their method screws up my printer if |
318 | I plug it in before the camera. */ | 283 | I plug it in before the camera. */ |
319 | 284 | ||
320 | static int qc_detect(struct qcam_device *q) | 285 | static int qc_detect(struct qcam *q) |
321 | { | 286 | { |
322 | int reg, lastreg; | 287 | int reg, lastreg; |
323 | int count = 0; | 288 | int count = 0; |
@@ -358,41 +323,6 @@ static int qc_detect(struct qcam_device *q) | |||
358 | } | 323 | } |
359 | } | 324 | } |
360 | 325 | ||
361 | |||
362 | /* Reset the QuickCam. This uses the same sequence the Windows | ||
363 | * QuickPic program uses. Someone with a bi-directional port should | ||
364 | * check that bi-directional mode is detected right, and then | ||
365 | * implement bi-directional mode in qc_readbyte(). */ | ||
366 | |||
367 | static void qc_reset(struct qcam_device *q) | ||
368 | { | ||
369 | switch (q->port_mode & QC_FORCE_MASK) { | ||
370 | case QC_FORCE_UNIDIR: | ||
371 | q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; | ||
372 | break; | ||
373 | |||
374 | case QC_FORCE_BIDIR: | ||
375 | q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; | ||
376 | break; | ||
377 | |||
378 | case QC_ANY: | ||
379 | write_lpcontrol(q, 0x20); | ||
380 | write_lpdata(q, 0x75); | ||
381 | |||
382 | if (read_lpdata(q) != 0x75) | ||
383 | q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; | ||
384 | else | ||
385 | q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; | ||
386 | break; | ||
387 | } | ||
388 | |||
389 | write_lpcontrol(q, 0xb); | ||
390 | udelay(250); | ||
391 | write_lpcontrol(q, 0xe); | ||
392 | qc_setscanmode(q); /* in case port_mode changed */ | ||
393 | } | ||
394 | |||
395 | |||
396 | /* Decide which scan mode to use. There's no real requirement that | 326 | /* Decide which scan mode to use. There's no real requirement that |
397 | * the scanmode match the resolution in q->height and q-> width -- the | 327 | * the scanmode match the resolution in q->height and q-> width -- the |
398 | * camera takes the picture at the resolution specified in the | 328 | * camera takes the picture at the resolution specified in the |
@@ -402,7 +332,7 @@ static void qc_reset(struct qcam_device *q) | |||
402 | * returned. If the scan is smaller, then the rest of the image | 332 | * returned. If the scan is smaller, then the rest of the image |
403 | * returned contains garbage. */ | 333 | * returned contains garbage. */ |
404 | 334 | ||
405 | static int qc_setscanmode(struct qcam_device *q) | 335 | static int qc_setscanmode(struct qcam *q) |
406 | { | 336 | { |
407 | int old_mode = q->mode; | 337 | int old_mode = q->mode; |
408 | 338 | ||
@@ -442,10 +372,45 @@ static int qc_setscanmode(struct qcam_device *q) | |||
442 | } | 372 | } |
443 | 373 | ||
444 | 374 | ||
375 | /* Reset the QuickCam. This uses the same sequence the Windows | ||
376 | * QuickPic program uses. Someone with a bi-directional port should | ||
377 | * check that bi-directional mode is detected right, and then | ||
378 | * implement bi-directional mode in qc_readbyte(). */ | ||
379 | |||
380 | static void qc_reset(struct qcam *q) | ||
381 | { | ||
382 | switch (q->port_mode & QC_FORCE_MASK) { | ||
383 | case QC_FORCE_UNIDIR: | ||
384 | q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; | ||
385 | break; | ||
386 | |||
387 | case QC_FORCE_BIDIR: | ||
388 | q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; | ||
389 | break; | ||
390 | |||
391 | case QC_ANY: | ||
392 | write_lpcontrol(q, 0x20); | ||
393 | write_lpdata(q, 0x75); | ||
394 | |||
395 | if (read_lpdata(q) != 0x75) | ||
396 | q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR; | ||
397 | else | ||
398 | q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR; | ||
399 | break; | ||
400 | } | ||
401 | |||
402 | write_lpcontrol(q, 0xb); | ||
403 | udelay(250); | ||
404 | write_lpcontrol(q, 0xe); | ||
405 | qc_setscanmode(q); /* in case port_mode changed */ | ||
406 | } | ||
407 | |||
408 | |||
409 | |||
445 | /* Reset the QuickCam and program for brightness, contrast, | 410 | /* Reset the QuickCam and program for brightness, contrast, |
446 | * white-balance, and resolution. */ | 411 | * white-balance, and resolution. */ |
447 | 412 | ||
448 | static void qc_set(struct qcam_device *q) | 413 | static void qc_set(struct qcam *q) |
449 | { | 414 | { |
450 | int val; | 415 | int val; |
451 | int val2; | 416 | int val2; |
@@ -499,7 +464,7 @@ static void qc_set(struct qcam_device *q) | |||
499 | the supplied buffer. It returns the number of bytes read, | 464 | the supplied buffer. It returns the number of bytes read, |
500 | or -1 on error. */ | 465 | or -1 on error. */ |
501 | 466 | ||
502 | static inline int qc_readbytes(struct qcam_device *q, char buffer[]) | 467 | static inline int qc_readbytes(struct qcam *q, char buffer[]) |
503 | { | 468 | { |
504 | int ret = 1; | 469 | int ret = 1; |
505 | unsigned int hi, lo; | 470 | unsigned int hi, lo; |
@@ -590,7 +555,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[]) | |||
590 | * n=2^(bit depth)-1. Ask me for more details if you don't understand | 555 | * n=2^(bit depth)-1. Ask me for more details if you don't understand |
591 | * this. */ | 556 | * this. */ |
592 | 557 | ||
593 | static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long len) | 558 | static long qc_capture(struct qcam *q, char __user *buf, unsigned long len) |
594 | { | 559 | { |
595 | int i, j, k, yield; | 560 | int i, j, k, yield; |
596 | int bytes; | 561 | int bytes; |
@@ -674,171 +639,206 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le | |||
674 | * Video4linux interfacing | 639 | * Video4linux interfacing |
675 | */ | 640 | */ |
676 | 641 | ||
677 | static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) | 642 | static int qcam_querycap(struct file *file, void *priv, |
643 | struct v4l2_capability *vcap) | ||
678 | { | 644 | { |
679 | struct video_device *dev = video_devdata(file); | 645 | struct qcam *qcam = video_drvdata(file); |
680 | struct qcam_device *qcam = (struct qcam_device *)dev; | ||
681 | |||
682 | switch (cmd) { | ||
683 | case VIDIOCGCAP: | ||
684 | { | ||
685 | struct video_capability *b = arg; | ||
686 | strcpy(b->name, "Quickcam"); | ||
687 | b->type = VID_TYPE_CAPTURE|VID_TYPE_SCALES|VID_TYPE_MONOCHROME; | ||
688 | b->channels = 1; | ||
689 | b->audios = 0; | ||
690 | b->maxwidth = 320; | ||
691 | b->maxheight = 240; | ||
692 | b->minwidth = 80; | ||
693 | b->minheight = 60; | ||
694 | return 0; | ||
695 | } | ||
696 | case VIDIOCGCHAN: | ||
697 | { | ||
698 | struct video_channel *v = arg; | ||
699 | if (v->channel != 0) | ||
700 | return -EINVAL; | ||
701 | v->flags = 0; | ||
702 | v->tuners = 0; | ||
703 | /* Good question.. its composite or SVHS so.. */ | ||
704 | v->type = VIDEO_TYPE_CAMERA; | ||
705 | strcpy(v->name, "Camera"); | ||
706 | return 0; | ||
707 | } | ||
708 | case VIDIOCSCHAN: | ||
709 | { | ||
710 | struct video_channel *v = arg; | ||
711 | if (v->channel != 0) | ||
712 | return -EINVAL; | ||
713 | return 0; | ||
714 | } | ||
715 | case VIDIOCGTUNER: | ||
716 | { | ||
717 | struct video_tuner *v = arg; | ||
718 | if (v->tuner) | ||
719 | return -EINVAL; | ||
720 | strcpy(v->name, "Format"); | ||
721 | v->rangelow = 0; | ||
722 | v->rangehigh = 0; | ||
723 | v->flags = 0; | ||
724 | v->mode = VIDEO_MODE_AUTO; | ||
725 | return 0; | ||
726 | } | ||
727 | case VIDIOCSTUNER: | ||
728 | { | ||
729 | struct video_tuner *v = arg; | ||
730 | if (v->tuner) | ||
731 | return -EINVAL; | ||
732 | if (v->mode != VIDEO_MODE_AUTO) | ||
733 | return -EINVAL; | ||
734 | return 0; | ||
735 | } | ||
736 | case VIDIOCGPICT: | ||
737 | { | ||
738 | struct video_picture *p = arg; | ||
739 | p->colour = 0x8000; | ||
740 | p->hue = 0x8000; | ||
741 | p->brightness = qcam->brightness << 8; | ||
742 | p->contrast = qcam->contrast << 8; | ||
743 | p->whiteness = qcam->whitebal << 8; | ||
744 | p->depth = qcam->bpp; | ||
745 | p->palette = VIDEO_PALETTE_GREY; | ||
746 | return 0; | ||
747 | } | ||
748 | case VIDIOCSPICT: | ||
749 | { | ||
750 | struct video_picture *p = arg; | ||
751 | if (p->palette != VIDEO_PALETTE_GREY) | ||
752 | return -EINVAL; | ||
753 | if (p->depth != 4 && p->depth != 6) | ||
754 | return -EINVAL; | ||
755 | |||
756 | /* | ||
757 | * Now load the camera. | ||
758 | */ | ||
759 | |||
760 | qcam->brightness = p->brightness >> 8; | ||
761 | qcam->contrast = p->contrast >> 8; | ||
762 | qcam->whitebal = p->whiteness >> 8; | ||
763 | qcam->bpp = p->depth; | ||
764 | |||
765 | mutex_lock(&qcam->lock); | ||
766 | qc_setscanmode(qcam); | ||
767 | mutex_unlock(&qcam->lock); | ||
768 | qcam->status |= QC_PARAM_CHANGE; | ||
769 | 646 | ||
770 | return 0; | 647 | strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver)); |
771 | } | 648 | strlcpy(vcap->card, "B&W Quickcam", sizeof(vcap->card)); |
772 | case VIDIOCSWIN: | 649 | strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info)); |
773 | { | 650 | vcap->version = KERNEL_VERSION(0, 0, 2); |
774 | struct video_window *vw = arg; | 651 | vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; |
775 | if (vw->flags) | 652 | return 0; |
776 | return -EINVAL; | 653 | } |
777 | if (vw->clipcount) | ||
778 | return -EINVAL; | ||
779 | if (vw->height < 60 || vw->height > 240) | ||
780 | return -EINVAL; | ||
781 | if (vw->width < 80 || vw->width > 320) | ||
782 | return -EINVAL; | ||
783 | |||
784 | qcam->width = 320; | ||
785 | qcam->height = 240; | ||
786 | qcam->transfer_scale = 4; | ||
787 | |||
788 | if (vw->width >= 160 && vw->height >= 120) | ||
789 | qcam->transfer_scale = 2; | ||
790 | if (vw->width >= 320 && vw->height >= 240) { | ||
791 | qcam->width = 320; | ||
792 | qcam->height = 240; | ||
793 | qcam->transfer_scale = 1; | ||
794 | } | ||
795 | mutex_lock(&qcam->lock); | ||
796 | qc_setscanmode(qcam); | ||
797 | mutex_unlock(&qcam->lock); | ||
798 | 654 | ||
799 | /* We must update the camera before we grab. We could | 655 | static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin) |
800 | just have changed the grab size */ | 656 | { |
801 | qcam->status |= QC_PARAM_CHANGE; | 657 | if (vin->index > 0) |
658 | return -EINVAL; | ||
659 | strlcpy(vin->name, "Camera", sizeof(vin->name)); | ||
660 | vin->type = V4L2_INPUT_TYPE_CAMERA; | ||
661 | vin->audioset = 0; | ||
662 | vin->tuner = 0; | ||
663 | vin->std = 0; | ||
664 | vin->status = 0; | ||
665 | return 0; | ||
666 | } | ||
802 | 667 | ||
803 | /* Ok we figured out what to use from our wide choice */ | 668 | static int qcam_g_input(struct file *file, void *fh, unsigned int *inp) |
804 | return 0; | 669 | { |
805 | } | 670 | *inp = 0; |
806 | case VIDIOCGWIN: | 671 | return 0; |
807 | { | 672 | } |
808 | struct video_window *vw = arg; | ||
809 | 673 | ||
810 | memset(vw, 0, sizeof(*vw)); | 674 | static int qcam_s_input(struct file *file, void *fh, unsigned int inp) |
811 | vw->width = qcam->width / qcam->transfer_scale; | 675 | { |
812 | vw->height = qcam->height / qcam->transfer_scale; | 676 | return (inp > 0) ? -EINVAL : 0; |
813 | return 0; | 677 | } |
814 | } | 678 | |
815 | case VIDIOCKEY: | 679 | static int qcam_queryctrl(struct file *file, void *priv, |
816 | return 0; | 680 | struct v4l2_queryctrl *qc) |
817 | case VIDIOCCAPTURE: | 681 | { |
818 | case VIDIOCGFBUF: | 682 | switch (qc->id) { |
819 | case VIDIOCSFBUF: | 683 | case V4L2_CID_BRIGHTNESS: |
820 | case VIDIOCGFREQ: | 684 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 180); |
821 | case VIDIOCSFREQ: | 685 | case V4L2_CID_CONTRAST: |
822 | case VIDIOCGAUDIO: | 686 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 192); |
823 | case VIDIOCSAUDIO: | 687 | case V4L2_CID_GAMMA: |
824 | return -EINVAL; | 688 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 105); |
689 | } | ||
690 | return -EINVAL; | ||
691 | } | ||
692 | |||
693 | static int qcam_g_ctrl(struct file *file, void *priv, | ||
694 | struct v4l2_control *ctrl) | ||
695 | { | ||
696 | struct qcam *qcam = video_drvdata(file); | ||
697 | int ret = 0; | ||
698 | |||
699 | switch (ctrl->id) { | ||
700 | case V4L2_CID_BRIGHTNESS: | ||
701 | ctrl->value = qcam->brightness; | ||
702 | break; | ||
703 | case V4L2_CID_CONTRAST: | ||
704 | ctrl->value = qcam->contrast; | ||
705 | break; | ||
706 | case V4L2_CID_GAMMA: | ||
707 | ctrl->value = qcam->whitebal; | ||
708 | break; | ||
825 | default: | 709 | default: |
826 | return -ENOIOCTLCMD; | 710 | ret = -EINVAL; |
711 | break; | ||
827 | } | 712 | } |
713 | return ret; | ||
714 | } | ||
715 | |||
716 | static int qcam_s_ctrl(struct file *file, void *priv, | ||
717 | struct v4l2_control *ctrl) | ||
718 | { | ||
719 | struct qcam *qcam = video_drvdata(file); | ||
720 | int ret = 0; | ||
721 | |||
722 | mutex_lock(&qcam->lock); | ||
723 | switch (ctrl->id) { | ||
724 | case V4L2_CID_BRIGHTNESS: | ||
725 | qcam->brightness = ctrl->value; | ||
726 | break; | ||
727 | case V4L2_CID_CONTRAST: | ||
728 | qcam->contrast = ctrl->value; | ||
729 | break; | ||
730 | case V4L2_CID_GAMMA: | ||
731 | qcam->whitebal = ctrl->value; | ||
732 | break; | ||
733 | default: | ||
734 | ret = -EINVAL; | ||
735 | break; | ||
736 | } | ||
737 | if (ret == 0) { | ||
738 | qc_setscanmode(qcam); | ||
739 | qcam->status |= QC_PARAM_CHANGE; | ||
740 | } | ||
741 | mutex_unlock(&qcam->lock); | ||
742 | return ret; | ||
743 | } | ||
744 | |||
745 | static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) | ||
746 | { | ||
747 | struct qcam *qcam = video_drvdata(file); | ||
748 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
749 | |||
750 | pix->width = qcam->width / qcam->transfer_scale; | ||
751 | pix->height = qcam->height / qcam->transfer_scale; | ||
752 | pix->pixelformat = (qcam->bpp == 4) ? V4L2_PIX_FMT_Y4 : V4L2_PIX_FMT_Y6; | ||
753 | pix->field = V4L2_FIELD_NONE; | ||
754 | pix->bytesperline = qcam->width; | ||
755 | pix->sizeimage = qcam->width * qcam->height; | ||
756 | /* Just a guess */ | ||
757 | pix->colorspace = V4L2_COLORSPACE_SRGB; | ||
758 | return 0; | ||
759 | } | ||
760 | |||
761 | static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) | ||
762 | { | ||
763 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
764 | |||
765 | if (pix->height <= 60 || pix->width <= 80) { | ||
766 | pix->height = 60; | ||
767 | pix->width = 80; | ||
768 | } else if (pix->height <= 120 || pix->width <= 160) { | ||
769 | pix->height = 120; | ||
770 | pix->width = 160; | ||
771 | } else { | ||
772 | pix->height = 240; | ||
773 | pix->width = 320; | ||
774 | } | ||
775 | if (pix->pixelformat != V4L2_PIX_FMT_Y4 && | ||
776 | pix->pixelformat != V4L2_PIX_FMT_Y6) | ||
777 | pix->pixelformat = V4L2_PIX_FMT_Y4; | ||
778 | pix->field = V4L2_FIELD_NONE; | ||
779 | pix->bytesperline = pix->width; | ||
780 | pix->sizeimage = pix->width * pix->height; | ||
781 | /* Just a guess */ | ||
782 | pix->colorspace = V4L2_COLORSPACE_SRGB; | ||
783 | return 0; | ||
784 | } | ||
785 | |||
786 | static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) | ||
787 | { | ||
788 | struct qcam *qcam = video_drvdata(file); | ||
789 | struct v4l2_pix_format *pix = &fmt->fmt.pix; | ||
790 | int ret = qcam_try_fmt_vid_cap(file, fh, fmt); | ||
791 | |||
792 | if (ret) | ||
793 | return ret; | ||
794 | qcam->width = 320; | ||
795 | qcam->height = 240; | ||
796 | if (pix->height == 60) | ||
797 | qcam->transfer_scale = 4; | ||
798 | else if (pix->height == 120) | ||
799 | qcam->transfer_scale = 2; | ||
800 | else | ||
801 | qcam->transfer_scale = 1; | ||
802 | if (pix->pixelformat == V4L2_PIX_FMT_Y6) | ||
803 | qcam->bpp = 6; | ||
804 | else | ||
805 | qcam->bpp = 4; | ||
806 | |||
807 | mutex_lock(&qcam->lock); | ||
808 | qc_setscanmode(qcam); | ||
809 | /* We must update the camera before we grab. We could | ||
810 | just have changed the grab size */ | ||
811 | qcam->status |= QC_PARAM_CHANGE; | ||
812 | mutex_unlock(&qcam->lock); | ||
828 | return 0; | 813 | return 0; |
829 | } | 814 | } |
830 | 815 | ||
831 | static long qcam_ioctl(struct file *file, | 816 | static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) |
832 | unsigned int cmd, unsigned long arg) | ||
833 | { | 817 | { |
834 | return video_usercopy(file, cmd, arg, qcam_do_ioctl); | 818 | static struct v4l2_fmtdesc formats[] = { |
819 | { 0, 0, 0, | ||
820 | "4-Bit Monochrome", V4L2_PIX_FMT_Y4, | ||
821 | { 0, 0, 0, 0 } | ||
822 | }, | ||
823 | { 0, 0, 0, | ||
824 | "6-Bit Monochrome", V4L2_PIX_FMT_Y6, | ||
825 | { 0, 0, 0, 0 } | ||
826 | }, | ||
827 | }; | ||
828 | enum v4l2_buf_type type = fmt->type; | ||
829 | |||
830 | if (fmt->index > 1) | ||
831 | return -EINVAL; | ||
832 | |||
833 | *fmt = formats[fmt->index]; | ||
834 | fmt->type = type; | ||
835 | return 0; | ||
835 | } | 836 | } |
836 | 837 | ||
837 | static ssize_t qcam_read(struct file *file, char __user *buf, | 838 | static ssize_t qcam_read(struct file *file, char __user *buf, |
838 | size_t count, loff_t *ppos) | 839 | size_t count, loff_t *ppos) |
839 | { | 840 | { |
840 | struct video_device *v = video_devdata(file); | 841 | struct qcam *qcam = video_drvdata(file); |
841 | struct qcam_device *qcam = (struct qcam_device *)v; | ||
842 | int len; | 842 | int len; |
843 | parport_claim_or_block(qcam->pdev); | 843 | parport_claim_or_block(qcam->pdev); |
844 | 844 | ||
@@ -858,43 +858,112 @@ static ssize_t qcam_read(struct file *file, char __user *buf, | |||
858 | return len; | 858 | return len; |
859 | } | 859 | } |
860 | 860 | ||
861 | static int qcam_exclusive_open(struct file *file) | 861 | static const struct v4l2_file_operations qcam_fops = { |
862 | .owner = THIS_MODULE, | ||
863 | .ioctl = video_ioctl2, | ||
864 | .read = qcam_read, | ||
865 | }; | ||
866 | |||
867 | static const struct v4l2_ioctl_ops qcam_ioctl_ops = { | ||
868 | .vidioc_querycap = qcam_querycap, | ||
869 | .vidioc_g_input = qcam_g_input, | ||
870 | .vidioc_s_input = qcam_s_input, | ||
871 | .vidioc_enum_input = qcam_enum_input, | ||
872 | .vidioc_queryctrl = qcam_queryctrl, | ||
873 | .vidioc_g_ctrl = qcam_g_ctrl, | ||
874 | .vidioc_s_ctrl = qcam_s_ctrl, | ||
875 | .vidioc_enum_fmt_vid_cap = qcam_enum_fmt_vid_cap, | ||
876 | .vidioc_g_fmt_vid_cap = qcam_g_fmt_vid_cap, | ||
877 | .vidioc_s_fmt_vid_cap = qcam_s_fmt_vid_cap, | ||
878 | .vidioc_try_fmt_vid_cap = qcam_try_fmt_vid_cap, | ||
879 | }; | ||
880 | |||
881 | /* Initialize the QuickCam driver control structure. This is where | ||
882 | * defaults are set for people who don't have a config file.*/ | ||
883 | |||
884 | static struct qcam *qcam_init(struct parport *port) | ||
862 | { | 885 | { |
863 | struct video_device *dev = video_devdata(file); | 886 | struct qcam *qcam; |
864 | struct qcam_device *qcam = (struct qcam_device *)dev; | 887 | struct v4l2_device *v4l2_dev; |
888 | |||
889 | qcam = kzalloc(sizeof(struct qcam), GFP_KERNEL); | ||
890 | if (qcam == NULL) | ||
891 | return NULL; | ||
892 | |||
893 | v4l2_dev = &qcam->v4l2_dev; | ||
894 | strlcpy(v4l2_dev->name, "bw-qcam", sizeof(v4l2_dev->name)); | ||
865 | 895 | ||
866 | return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0; | 896 | if (v4l2_device_register(NULL, v4l2_dev) < 0) { |
897 | v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); | ||
898 | return NULL; | ||
899 | } | ||
900 | |||
901 | qcam->pport = port; | ||
902 | qcam->pdev = parport_register_device(port, "bw-qcam", NULL, NULL, | ||
903 | NULL, 0, NULL); | ||
904 | if (qcam->pdev == NULL) { | ||
905 | v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name); | ||
906 | kfree(qcam); | ||
907 | return NULL; | ||
908 | } | ||
909 | |||
910 | strlcpy(qcam->vdev.name, "Connectix QuickCam", sizeof(qcam->vdev.name)); | ||
911 | qcam->vdev.v4l2_dev = v4l2_dev; | ||
912 | qcam->vdev.fops = &qcam_fops; | ||
913 | qcam->vdev.ioctl_ops = &qcam_ioctl_ops; | ||
914 | qcam->vdev.release = video_device_release_empty; | ||
915 | video_set_drvdata(&qcam->vdev, qcam); | ||
916 | |||
917 | mutex_init(&qcam->lock); | ||
918 | |||
919 | qcam->port_mode = (QC_ANY | QC_NOTSET); | ||
920 | qcam->width = 320; | ||
921 | qcam->height = 240; | ||
922 | qcam->bpp = 4; | ||
923 | qcam->transfer_scale = 2; | ||
924 | qcam->contrast = 192; | ||
925 | qcam->brightness = 180; | ||
926 | qcam->whitebal = 105; | ||
927 | qcam->top = 1; | ||
928 | qcam->left = 14; | ||
929 | qcam->mode = -1; | ||
930 | qcam->status = QC_PARAM_CHANGE; | ||
931 | return qcam; | ||
867 | } | 932 | } |
868 | 933 | ||
869 | static int qcam_exclusive_release(struct file *file) | 934 | static int qc_calibrate(struct qcam *q) |
870 | { | 935 | { |
871 | struct video_device *dev = video_devdata(file); | 936 | /* |
872 | struct qcam_device *qcam = (struct qcam_device *)dev; | 937 | * Bugfix by Hanno Mueller hmueller@kabel.de, Mai 21 96 |
938 | * The white balance is an individual value for each | ||
939 | * quickcam. | ||
940 | */ | ||
873 | 941 | ||
874 | clear_bit(0, &qcam->in_use); | 942 | int value; |
875 | return 0; | 943 | int count = 0; |
876 | } | ||
877 | 944 | ||
878 | static const struct v4l2_file_operations qcam_fops = { | 945 | qc_command(q, 27); /* AutoAdjustOffset */ |
879 | .owner = THIS_MODULE, | 946 | qc_command(q, 0); /* Dummy Parameter, ignored by the camera */ |
880 | .open = qcam_exclusive_open, | ||
881 | .release = qcam_exclusive_release, | ||
882 | .ioctl = qcam_ioctl, | ||
883 | .read = qcam_read, | ||
884 | }; | ||
885 | static struct video_device qcam_template = { | ||
886 | .name = "Connectix Quickcam", | ||
887 | .fops = &qcam_fops, | ||
888 | .release = video_device_release_empty, | ||
889 | }; | ||
890 | 947 | ||
891 | #define MAX_CAMS 4 | 948 | /* GetOffset (33) will read 255 until autocalibration */ |
892 | static struct qcam_device *qcams[MAX_CAMS]; | 949 | /* is finished. After that, a value of 1-254 will be */ |
893 | static unsigned int num_cams; | 950 | /* returned. */ |
951 | |||
952 | do { | ||
953 | qc_command(q, 33); | ||
954 | value = qc_readparam(q); | ||
955 | mdelay(1); | ||
956 | schedule(); | ||
957 | count++; | ||
958 | } while (value == 0xff && count < 2048); | ||
959 | |||
960 | q->whitebal = value; | ||
961 | return value; | ||
962 | } | ||
894 | 963 | ||
895 | static int init_bwqcam(struct parport *port) | 964 | static int init_bwqcam(struct parport *port) |
896 | { | 965 | { |
897 | struct qcam_device *qcam; | 966 | struct qcam *qcam; |
898 | 967 | ||
899 | if (num_cams == MAX_CAMS) { | 968 | if (num_cams == MAX_CAMS) { |
900 | printk(KERN_ERR "Too many Quickcams (max %d)\n", MAX_CAMS); | 969 | printk(KERN_ERR "Too many Quickcams (max %d)\n", MAX_CAMS); |
@@ -919,7 +988,7 @@ static int init_bwqcam(struct parport *port) | |||
919 | 988 | ||
920 | parport_release(qcam->pdev); | 989 | parport_release(qcam->pdev); |
921 | 990 | ||
922 | printk(KERN_INFO "Connectix Quickcam on %s\n", qcam->pport->name); | 991 | v4l2_info(&qcam->v4l2_dev, "Connectix Quickcam on %s\n", qcam->pport->name); |
923 | 992 | ||
924 | if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { | 993 | if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { |
925 | parport_unregister_device(qcam->pdev); | 994 | parport_unregister_device(qcam->pdev); |
@@ -932,7 +1001,7 @@ static int init_bwqcam(struct parport *port) | |||
932 | return 0; | 1001 | return 0; |
933 | } | 1002 | } |
934 | 1003 | ||
935 | static void close_bwqcam(struct qcam_device *qcam) | 1004 | static void close_bwqcam(struct qcam *qcam) |
936 | { | 1005 | { |
937 | video_unregister_device(&qcam->vdev); | 1006 | video_unregister_device(&qcam->vdev); |
938 | parport_unregister_device(qcam->pdev); | 1007 | parport_unregister_device(qcam->pdev); |
@@ -983,7 +1052,7 @@ static void bwqcam_detach(struct parport *port) | |||
983 | { | 1052 | { |
984 | int i; | 1053 | int i; |
985 | for (i = 0; i < num_cams; i++) { | 1054 | for (i = 0; i < num_cams; i++) { |
986 | struct qcam_device *qcam = qcams[i]; | 1055 | struct qcam *qcam = qcams[i]; |
987 | if (qcam && qcam->pdev->port == port) { | 1056 | if (qcam && qcam->pdev->port == port) { |
988 | qcams[i] = NULL; | 1057 | qcams[i] = NULL; |
989 | close_bwqcam(qcam); | 1058 | close_bwqcam(qcam); |
diff --git a/drivers/media/video/bw-qcam.h b/drivers/media/video/bw-qcam.h deleted file mode 100644 index 8a60c5de0935..000000000000 --- a/drivers/media/video/bw-qcam.h +++ /dev/null | |||
@@ -1,69 +0,0 @@ | |||
1 | /* | ||
2 | * Video4Linux bw-qcam driver | ||
3 | * | ||
4 | * Derived from code.. | ||
5 | */ | ||
6 | |||
7 | /****************************************************************** | ||
8 | |||
9 | Copyright (C) 1996 by Scott Laird | ||
10 | |||
11 | Permission is hereby granted, free of charge, to any person obtaining | ||
12 | a copy of this software and associated documentation files (the | ||
13 | "Software"), to deal in the Software without restriction, including | ||
14 | without limitation the rights to use, copy, modify, merge, publish, | ||
15 | distribute, sublicense, and/or sell copies of the Software, and to | ||
16 | permit persons to whom the Software is furnished to do so, subject to | ||
17 | the following conditions: | ||
18 | |||
19 | The above copyright notice and this permission notice shall be | ||
20 | included in all copies or substantial portions of the Software. | ||
21 | |||
22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
23 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
24 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
25 | IN NO EVENT SHALL SCOTT LAIRD BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
26 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
27 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
28 | OTHER DEALINGS IN THE SOFTWARE. | ||
29 | |||
30 | ******************************************************************/ | ||
31 | |||
32 | /* One from column A... */ | ||
33 | #define QC_NOTSET 0 | ||
34 | #define QC_UNIDIR 1 | ||
35 | #define QC_BIDIR 2 | ||
36 | #define QC_SERIAL 3 | ||
37 | |||
38 | /* ... and one from column B */ | ||
39 | #define QC_ANY 0x00 | ||
40 | #define QC_FORCE_UNIDIR 0x10 | ||
41 | #define QC_FORCE_BIDIR 0x20 | ||
42 | #define QC_FORCE_SERIAL 0x30 | ||
43 | /* in the port_mode member */ | ||
44 | |||
45 | #define QC_MODE_MASK 0x07 | ||
46 | #define QC_FORCE_MASK 0x70 | ||
47 | |||
48 | #define MAX_HEIGHT 243 | ||
49 | #define MAX_WIDTH 336 | ||
50 | |||
51 | /* Bit fields for status flags */ | ||
52 | #define QC_PARAM_CHANGE 0x01 /* Camera status change has occurred */ | ||
53 | |||
54 | struct qcam_device { | ||
55 | struct video_device vdev; | ||
56 | struct pardevice *pdev; | ||
57 | struct parport *pport; | ||
58 | struct mutex lock; | ||
59 | int width, height; | ||
60 | int bpp; | ||
61 | int mode; | ||
62 | int contrast, brightness, whitebal; | ||
63 | int port_mode; | ||
64 | int transfer_scale; | ||
65 | int top, left; | ||
66 | int status; | ||
67 | unsigned int saved_bits; | ||
68 | unsigned long in_use; | ||
69 | }; | ||