diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/media/video/cpia_pp.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/media/video/cpia_pp.c')
-rw-r--r-- | drivers/media/video/cpia_pp.c | 886 |
1 files changed, 886 insertions, 0 deletions
diff --git a/drivers/media/video/cpia_pp.c b/drivers/media/video/cpia_pp.c new file mode 100644 index 000000000000..ddf184f95d80 --- /dev/null +++ b/drivers/media/video/cpia_pp.c | |||
@@ -0,0 +1,886 @@ | |||
1 | /* | ||
2 | * cpia_pp CPiA Parallel Port driver | ||
3 | * | ||
4 | * Supports CPiA based parallel port Video Camera's. | ||
5 | * | ||
6 | * (C) Copyright 1999 Bas Huisman <bhuism@cs.utwente.nl> | ||
7 | * (C) Copyright 1999-2000 Scott J. Bertin <sbertin@securenym.net>, | ||
8 | * (C) Copyright 1999-2000 Peter Pregler <Peter_Pregler@email.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
25 | /* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */ | ||
26 | /* #define _CPIA_DEBUG_ 1 */ | ||
27 | |||
28 | #include <linux/config.h> | ||
29 | |||
30 | #include <linux/module.h> | ||
31 | #include <linux/init.h> | ||
32 | |||
33 | #include <linux/kernel.h> | ||
34 | #include <linux/parport.h> | ||
35 | #include <linux/interrupt.h> | ||
36 | #include <linux/delay.h> | ||
37 | #include <linux/workqueue.h> | ||
38 | #include <linux/smp_lock.h> | ||
39 | #include <linux/sched.h> | ||
40 | |||
41 | #include <linux/kmod.h> | ||
42 | |||
43 | /* #define _CPIA_DEBUG_ define for verbose debug output */ | ||
44 | #include "cpia.h" | ||
45 | |||
46 | static int cpia_pp_open(void *privdata); | ||
47 | static int cpia_pp_registerCallback(void *privdata, void (*cb) (void *cbdata), | ||
48 | void *cbdata); | ||
49 | static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data); | ||
50 | static int cpia_pp_streamStart(void *privdata); | ||
51 | static int cpia_pp_streamStop(void *privdata); | ||
52 | static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock); | ||
53 | static int cpia_pp_close(void *privdata); | ||
54 | |||
55 | |||
56 | #define ABOUT "Parallel port driver for Vision CPiA based cameras" | ||
57 | |||
58 | #define PACKET_LENGTH 8 | ||
59 | |||
60 | /* Magic numbers for defining port-device mappings */ | ||
61 | #define PPCPIA_PARPORT_UNSPEC -4 | ||
62 | #define PPCPIA_PARPORT_AUTO -3 | ||
63 | #define PPCPIA_PARPORT_OFF -2 | ||
64 | #define PPCPIA_PARPORT_NONE -1 | ||
65 | |||
66 | #ifdef MODULE | ||
67 | static int parport_nr[PARPORT_MAX] = {[0 ... PARPORT_MAX - 1] = PPCPIA_PARPORT_UNSPEC}; | ||
68 | static char *parport[PARPORT_MAX] = {NULL,}; | ||
69 | |||
70 | MODULE_AUTHOR("B. Huisman <bhuism@cs.utwente.nl> & Peter Pregler <Peter_Pregler@email.com>"); | ||
71 | MODULE_DESCRIPTION("Parallel port driver for Vision CPiA based cameras"); | ||
72 | MODULE_LICENSE("GPL"); | ||
73 | |||
74 | module_param_array(parport, charp, NULL, 0); | ||
75 | MODULE_PARM_DESC(parport, "'auto' or a list of parallel port numbers. Just like lp."); | ||
76 | #else | ||
77 | static int parport_nr[PARPORT_MAX] __initdata = | ||
78 | {[0 ... PARPORT_MAX - 1] = PPCPIA_PARPORT_UNSPEC}; | ||
79 | static int parport_ptr = 0; | ||
80 | #endif | ||
81 | |||
82 | struct pp_cam_entry { | ||
83 | struct pardevice *pdev; | ||
84 | struct parport *port; | ||
85 | struct work_struct cb_task; | ||
86 | int open_count; | ||
87 | wait_queue_head_t wq_stream; | ||
88 | /* image state flags */ | ||
89 | int image_ready; /* we got an interrupt */ | ||
90 | int image_complete; /* we have seen 4 EOI */ | ||
91 | |||
92 | int streaming; /* we are in streaming mode */ | ||
93 | int stream_irq; | ||
94 | }; | ||
95 | |||
96 | static struct cpia_camera_ops cpia_pp_ops = | ||
97 | { | ||
98 | cpia_pp_open, | ||
99 | cpia_pp_registerCallback, | ||
100 | cpia_pp_transferCmd, | ||
101 | cpia_pp_streamStart, | ||
102 | cpia_pp_streamStop, | ||
103 | cpia_pp_streamRead, | ||
104 | cpia_pp_close, | ||
105 | 1, | ||
106 | THIS_MODULE | ||
107 | }; | ||
108 | |||
109 | static LIST_HEAD(cam_list); | ||
110 | static spinlock_t cam_list_lock_pp; | ||
111 | |||
112 | /* FIXME */ | ||
113 | static void cpia_parport_enable_irq( struct parport *port ) { | ||
114 | parport_enable_irq(port); | ||
115 | mdelay(10); | ||
116 | return; | ||
117 | } | ||
118 | |||
119 | static void cpia_parport_disable_irq( struct parport *port ) { | ||
120 | parport_disable_irq(port); | ||
121 | mdelay(10); | ||
122 | return; | ||
123 | } | ||
124 | |||
125 | /* Special CPiA PPC modes: These are invoked by using the 1284 Extensibility | ||
126 | * Link Flag during negotiation */ | ||
127 | #define UPLOAD_FLAG 0x08 | ||
128 | #define NIBBLE_TRANSFER 0x01 | ||
129 | #define ECP_TRANSFER 0x03 | ||
130 | |||
131 | #define PARPORT_CHUNK_SIZE PAGE_SIZE | ||
132 | |||
133 | |||
134 | /**************************************************************************** | ||
135 | * | ||
136 | * CPiA-specific low-level parport functions for nibble uploads | ||
137 | * | ||
138 | ***************************************************************************/ | ||
139 | /* CPiA nonstandard "Nibble" mode (no nDataAvail signal after each byte). */ | ||
140 | /* The standard kernel parport_ieee1284_read_nibble() fails with the CPiA... */ | ||
141 | |||
142 | static size_t cpia_read_nibble (struct parport *port, | ||
143 | void *buffer, size_t len, | ||
144 | int flags) | ||
145 | { | ||
146 | /* adapted verbatim, with one change, from | ||
147 | parport_ieee1284_read_nibble() in drivers/parport/ieee1284-ops.c */ | ||
148 | |||
149 | unsigned char *buf = buffer; | ||
150 | int i; | ||
151 | unsigned char byte = 0; | ||
152 | |||
153 | len *= 2; /* in nibbles */ | ||
154 | for (i=0; i < len; i++) { | ||
155 | unsigned char nibble; | ||
156 | |||
157 | /* The CPiA firmware suppresses the use of nDataAvail (nFault LO) | ||
158 | * after every second nibble to signal that more | ||
159 | * data is available. (the total number of Bytes that | ||
160 | * should be sent is known; if too few are received, an error | ||
161 | * will be recorded after a timeout). | ||
162 | * This is incompatible with parport_ieee1284_read_nibble(), | ||
163 | * which expects to find nFault LO after every second nibble. | ||
164 | */ | ||
165 | |||
166 | /* Solution: modify cpia_read_nibble to only check for | ||
167 | * nDataAvail before the first nibble is sent. | ||
168 | */ | ||
169 | |||
170 | /* Does the error line indicate end of data? */ | ||
171 | if (((i /*& 1*/) == 0) && | ||
172 | (parport_read_status(port) & PARPORT_STATUS_ERROR)) { | ||
173 | port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA; | ||
174 | DBG("%s: No more nibble data (%d bytes)\n", | ||
175 | port->name, i/2); | ||
176 | |||
177 | /* Go to reverse idle phase. */ | ||
178 | parport_frob_control (port, | ||
179 | PARPORT_CONTROL_AUTOFD, | ||
180 | PARPORT_CONTROL_AUTOFD); | ||
181 | port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE; | ||
182 | break; | ||
183 | } | ||
184 | |||
185 | /* Event 7: Set nAutoFd low. */ | ||
186 | parport_frob_control (port, | ||
187 | PARPORT_CONTROL_AUTOFD, | ||
188 | PARPORT_CONTROL_AUTOFD); | ||
189 | |||
190 | /* Event 9: nAck goes low. */ | ||
191 | port->ieee1284.phase = IEEE1284_PH_REV_DATA; | ||
192 | if (parport_wait_peripheral (port, | ||
193 | PARPORT_STATUS_ACK, 0)) { | ||
194 | /* Timeout -- no more data? */ | ||
195 | DBG("%s: Nibble timeout at event 9 (%d bytes)\n", | ||
196 | port->name, i/2); | ||
197 | parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0); | ||
198 | break; | ||
199 | } | ||
200 | |||
201 | |||
202 | /* Read a nibble. */ | ||
203 | nibble = parport_read_status (port) >> 3; | ||
204 | nibble &= ~8; | ||
205 | if ((nibble & 0x10) == 0) | ||
206 | nibble |= 8; | ||
207 | nibble &= 0xf; | ||
208 | |||
209 | /* Event 10: Set nAutoFd high. */ | ||
210 | parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0); | ||
211 | |||
212 | /* Event 11: nAck goes high. */ | ||
213 | if (parport_wait_peripheral (port, | ||
214 | PARPORT_STATUS_ACK, | ||
215 | PARPORT_STATUS_ACK)) { | ||
216 | /* Timeout -- no more data? */ | ||
217 | DBG("%s: Nibble timeout at event 11\n", | ||
218 | port->name); | ||
219 | break; | ||
220 | } | ||
221 | |||
222 | if (i & 1) { | ||
223 | /* Second nibble */ | ||
224 | byte |= nibble << 4; | ||
225 | *buf++ = byte; | ||
226 | } else | ||
227 | byte = nibble; | ||
228 | } | ||
229 | |||
230 | i /= 2; /* i is now in bytes */ | ||
231 | |||
232 | if (i == len) { | ||
233 | /* Read the last nibble without checking data avail. */ | ||
234 | port = port->physport; | ||
235 | if (parport_read_status (port) & PARPORT_STATUS_ERROR) | ||
236 | port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA; | ||
237 | else | ||
238 | port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL; | ||
239 | } | ||
240 | |||
241 | return i; | ||
242 | } | ||
243 | |||
244 | /* CPiA nonstandard "Nibble Stream" mode (2 nibbles per cycle, instead of 1) | ||
245 | * (See CPiA Data sheet p. 31) | ||
246 | * | ||
247 | * "Nibble Stream" mode used by CPiA for uploads to non-ECP ports is a | ||
248 | * nonstandard variant of nibble mode which allows the same (mediocre) | ||
249 | * data flow of 8 bits per cycle as software-enabled ECP by TRISTATE-capable | ||
250 | * parallel ports, but works also for non-TRISTATE-capable ports. | ||
251 | * (Standard nibble mode only send 4 bits per cycle) | ||
252 | * | ||
253 | */ | ||
254 | |||
255 | static size_t cpia_read_nibble_stream(struct parport *port, | ||
256 | void *buffer, size_t len, | ||
257 | int flags) | ||
258 | { | ||
259 | int i; | ||
260 | unsigned char *buf = buffer; | ||
261 | int endseen = 0; | ||
262 | |||
263 | for (i=0; i < len; i++) { | ||
264 | unsigned char nibble[2], byte = 0; | ||
265 | int j; | ||
266 | |||
267 | /* Image Data is complete when 4 consecutive EOI bytes (0xff) are seen */ | ||
268 | if (endseen > 3 ) | ||
269 | break; | ||
270 | |||
271 | /* Event 7: Set nAutoFd low. */ | ||
272 | parport_frob_control (port, | ||
273 | PARPORT_CONTROL_AUTOFD, | ||
274 | PARPORT_CONTROL_AUTOFD); | ||
275 | |||
276 | /* Event 9: nAck goes low. */ | ||
277 | port->ieee1284.phase = IEEE1284_PH_REV_DATA; | ||
278 | if (parport_wait_peripheral (port, | ||
279 | PARPORT_STATUS_ACK, 0)) { | ||
280 | /* Timeout -- no more data? */ | ||
281 | DBG("%s: Nibble timeout at event 9 (%d bytes)\n", | ||
282 | port->name, i/2); | ||
283 | parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0); | ||
284 | break; | ||
285 | } | ||
286 | |||
287 | /* Read lower nibble */ | ||
288 | nibble[0] = parport_read_status (port) >>3; | ||
289 | |||
290 | /* Event 10: Set nAutoFd high. */ | ||
291 | parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0); | ||
292 | |||
293 | /* Event 11: nAck goes high. */ | ||
294 | if (parport_wait_peripheral (port, | ||
295 | PARPORT_STATUS_ACK, | ||
296 | PARPORT_STATUS_ACK)) { | ||
297 | /* Timeout -- no more data? */ | ||
298 | DBG("%s: Nibble timeout at event 11\n", | ||
299 | port->name); | ||
300 | break; | ||
301 | } | ||
302 | |||
303 | /* Read upper nibble */ | ||
304 | nibble[1] = parport_read_status (port) >>3; | ||
305 | |||
306 | /* reassemble the byte */ | ||
307 | for (j = 0; j < 2 ; j++ ) { | ||
308 | nibble[j] &= ~8; | ||
309 | if ((nibble[j] & 0x10) == 0) | ||
310 | nibble[j] |= 8; | ||
311 | nibble[j] &= 0xf; | ||
312 | } | ||
313 | byte = (nibble[0] |(nibble[1] << 4)); | ||
314 | *buf++ = byte; | ||
315 | |||
316 | if(byte == EOI) | ||
317 | endseen++; | ||
318 | else | ||
319 | endseen = 0; | ||
320 | } | ||
321 | return i; | ||
322 | } | ||
323 | |||
324 | /**************************************************************************** | ||
325 | * | ||
326 | * EndTransferMode | ||
327 | * | ||
328 | ***************************************************************************/ | ||
329 | static void EndTransferMode(struct pp_cam_entry *cam) | ||
330 | { | ||
331 | parport_negotiate(cam->port, IEEE1284_MODE_COMPAT); | ||
332 | } | ||
333 | |||
334 | /**************************************************************************** | ||
335 | * | ||
336 | * ForwardSetup | ||
337 | * | ||
338 | ***************************************************************************/ | ||
339 | static int ForwardSetup(struct pp_cam_entry *cam) | ||
340 | { | ||
341 | int retry; | ||
342 | |||
343 | /* The CPiA uses ECP protocol for Downloads from the Host to the camera. | ||
344 | * This will be software-emulated if ECP hardware is not present | ||
345 | */ | ||
346 | |||
347 | /* the usual camera maximum response time is 10ms, but after receiving | ||
348 | * some commands, it needs up to 40ms. (Data Sheet p. 32)*/ | ||
349 | |||
350 | for(retry = 0; retry < 4; ++retry) { | ||
351 | if(!parport_negotiate(cam->port, IEEE1284_MODE_ECP)) { | ||
352 | break; | ||
353 | } | ||
354 | mdelay(10); | ||
355 | } | ||
356 | if(retry == 4) { | ||
357 | DBG("Unable to negotiate IEEE1284 ECP Download mode\n"); | ||
358 | return -1; | ||
359 | } | ||
360 | return 0; | ||
361 | } | ||
362 | /**************************************************************************** | ||
363 | * | ||
364 | * ReverseSetup | ||
365 | * | ||
366 | ***************************************************************************/ | ||
367 | static int ReverseSetup(struct pp_cam_entry *cam, int extensibility) | ||
368 | { | ||
369 | int retry; | ||
370 | int upload_mode, mode = IEEE1284_MODE_ECP; | ||
371 | int transfer_mode = ECP_TRANSFER; | ||
372 | |||
373 | if (!(cam->port->modes & PARPORT_MODE_ECP) && | ||
374 | !(cam->port->modes & PARPORT_MODE_TRISTATE)) { | ||
375 | mode = IEEE1284_MODE_NIBBLE; | ||
376 | transfer_mode = NIBBLE_TRANSFER; | ||
377 | } | ||
378 | |||
379 | upload_mode = mode; | ||
380 | if(extensibility) mode = UPLOAD_FLAG|transfer_mode|IEEE1284_EXT_LINK; | ||
381 | |||
382 | /* the usual camera maximum response time is 10ms, but after | ||
383 | * receiving some commands, it needs up to 40ms. */ | ||
384 | |||
385 | for(retry = 0; retry < 4; ++retry) { | ||
386 | if(!parport_negotiate(cam->port, mode)) { | ||
387 | break; | ||
388 | } | ||
389 | mdelay(10); | ||
390 | } | ||
391 | if(retry == 4) { | ||
392 | if(extensibility) | ||
393 | DBG("Unable to negotiate upload extensibility mode\n"); | ||
394 | else | ||
395 | DBG("Unable to negotiate upload mode\n"); | ||
396 | return -1; | ||
397 | } | ||
398 | if(extensibility) cam->port->ieee1284.mode = upload_mode; | ||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | /**************************************************************************** | ||
403 | * | ||
404 | * WritePacket | ||
405 | * | ||
406 | ***************************************************************************/ | ||
407 | static int WritePacket(struct pp_cam_entry *cam, const u8 *packet, size_t size) | ||
408 | { | ||
409 | int retval=0; | ||
410 | int size_written; | ||
411 | |||
412 | if (packet == NULL) { | ||
413 | return -EINVAL; | ||
414 | } | ||
415 | if (ForwardSetup(cam)) { | ||
416 | DBG("Write failed in setup\n"); | ||
417 | return -EIO; | ||
418 | } | ||
419 | size_written = parport_write(cam->port, packet, size); | ||
420 | if(size_written != size) { | ||
421 | DBG("Write failed, wrote %d/%d\n", size_written, size); | ||
422 | retval = -EIO; | ||
423 | } | ||
424 | EndTransferMode(cam); | ||
425 | return retval; | ||
426 | } | ||
427 | |||
428 | /**************************************************************************** | ||
429 | * | ||
430 | * ReadPacket | ||
431 | * | ||
432 | ***************************************************************************/ | ||
433 | static int ReadPacket(struct pp_cam_entry *cam, u8 *packet, size_t size) | ||
434 | { | ||
435 | int retval=0; | ||
436 | |||
437 | if (packet == NULL) { | ||
438 | return -EINVAL; | ||
439 | } | ||
440 | if (ReverseSetup(cam, 0)) { | ||
441 | return -EIO; | ||
442 | } | ||
443 | |||
444 | /* support for CPiA variant nibble reads */ | ||
445 | if(cam->port->ieee1284.mode == IEEE1284_MODE_NIBBLE) { | ||
446 | if(cpia_read_nibble(cam->port, packet, size, 0) != size) | ||
447 | retval = -EIO; | ||
448 | } else { | ||
449 | if(parport_read(cam->port, packet, size) != size) | ||
450 | retval = -EIO; | ||
451 | } | ||
452 | EndTransferMode(cam); | ||
453 | return retval; | ||
454 | } | ||
455 | |||
456 | /**************************************************************************** | ||
457 | * | ||
458 | * cpia_pp_streamStart | ||
459 | * | ||
460 | ***************************************************************************/ | ||
461 | static int cpia_pp_streamStart(void *privdata) | ||
462 | { | ||
463 | struct pp_cam_entry *cam = privdata; | ||
464 | DBG("\n"); | ||
465 | cam->streaming=1; | ||
466 | cam->image_ready=0; | ||
467 | //if (ReverseSetup(cam,1)) return -EIO; | ||
468 | if(cam->stream_irq) cpia_parport_enable_irq(cam->port); | ||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | /**************************************************************************** | ||
473 | * | ||
474 | * cpia_pp_streamStop | ||
475 | * | ||
476 | ***************************************************************************/ | ||
477 | static int cpia_pp_streamStop(void *privdata) | ||
478 | { | ||
479 | struct pp_cam_entry *cam = privdata; | ||
480 | |||
481 | DBG("\n"); | ||
482 | cam->streaming=0; | ||
483 | cpia_parport_disable_irq(cam->port); | ||
484 | //EndTransferMode(cam); | ||
485 | |||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | /**************************************************************************** | ||
490 | * | ||
491 | * cpia_pp_streamRead | ||
492 | * | ||
493 | ***************************************************************************/ | ||
494 | static int cpia_pp_read(struct parport *port, u8 *buffer, int len) | ||
495 | { | ||
496 | int bytes_read; | ||
497 | |||
498 | /* support for CPiA variant "nibble stream" reads */ | ||
499 | if(port->ieee1284.mode == IEEE1284_MODE_NIBBLE) | ||
500 | bytes_read = cpia_read_nibble_stream(port,buffer,len,0); | ||
501 | else { | ||
502 | int new_bytes; | ||
503 | for(bytes_read=0; bytes_read<len; bytes_read += new_bytes) { | ||
504 | new_bytes = parport_read(port, buffer+bytes_read, | ||
505 | len-bytes_read); | ||
506 | if(new_bytes < 0) break; | ||
507 | } | ||
508 | } | ||
509 | return bytes_read; | ||
510 | } | ||
511 | |||
512 | static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock) | ||
513 | { | ||
514 | struct pp_cam_entry *cam = privdata; | ||
515 | int read_bytes = 0; | ||
516 | int i, endseen, block_size, new_bytes; | ||
517 | |||
518 | if(cam == NULL) { | ||
519 | DBG("Internal driver error: cam is NULL\n"); | ||
520 | return -EINVAL; | ||
521 | } | ||
522 | if(buffer == NULL) { | ||
523 | DBG("Internal driver error: buffer is NULL\n"); | ||
524 | return -EINVAL; | ||
525 | } | ||
526 | //if(cam->streaming) DBG("%d / %d\n", cam->image_ready, noblock); | ||
527 | if( cam->stream_irq ) { | ||
528 | DBG("%d\n", cam->image_ready); | ||
529 | cam->image_ready--; | ||
530 | } | ||
531 | cam->image_complete=0; | ||
532 | if (0/*cam->streaming*/) { | ||
533 | if(!cam->image_ready) { | ||
534 | if(noblock) return -EWOULDBLOCK; | ||
535 | interruptible_sleep_on(&cam->wq_stream); | ||
536 | if( signal_pending(current) ) return -EINTR; | ||
537 | DBG("%d\n", cam->image_ready); | ||
538 | } | ||
539 | } else { | ||
540 | if (ReverseSetup(cam, 1)) { | ||
541 | DBG("unable to ReverseSetup\n"); | ||
542 | return -EIO; | ||
543 | } | ||
544 | } | ||
545 | endseen = 0; | ||
546 | block_size = PARPORT_CHUNK_SIZE; | ||
547 | while( !cam->image_complete ) { | ||
548 | cond_resched(); | ||
549 | |||
550 | new_bytes = cpia_pp_read(cam->port, buffer, block_size ); | ||
551 | if( new_bytes <= 0 ) { | ||
552 | break; | ||
553 | } | ||
554 | i=-1; | ||
555 | while(++i<new_bytes && endseen<4) { | ||
556 | if(*buffer==EOI) { | ||
557 | endseen++; | ||
558 | } else { | ||
559 | endseen=0; | ||
560 | } | ||
561 | buffer++; | ||
562 | } | ||
563 | read_bytes += i; | ||
564 | if( endseen==4 ) { | ||
565 | cam->image_complete=1; | ||
566 | break; | ||
567 | } | ||
568 | if( CPIA_MAX_IMAGE_SIZE-read_bytes <= PARPORT_CHUNK_SIZE ) { | ||
569 | block_size=CPIA_MAX_IMAGE_SIZE-read_bytes; | ||
570 | } | ||
571 | } | ||
572 | EndTransferMode(cam); | ||
573 | return cam->image_complete ? read_bytes : -EIO; | ||
574 | } | ||
575 | /**************************************************************************** | ||
576 | * | ||
577 | * cpia_pp_transferCmd | ||
578 | * | ||
579 | ***************************************************************************/ | ||
580 | static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data) | ||
581 | { | ||
582 | int err; | ||
583 | int retval=0; | ||
584 | int databytes; | ||
585 | struct pp_cam_entry *cam = privdata; | ||
586 | |||
587 | if(cam == NULL) { | ||
588 | DBG("Internal driver error: cam is NULL\n"); | ||
589 | return -EINVAL; | ||
590 | } | ||
591 | if(command == NULL) { | ||
592 | DBG("Internal driver error: command is NULL\n"); | ||
593 | return -EINVAL; | ||
594 | } | ||
595 | databytes = (((int)command[7])<<8) | command[6]; | ||
596 | if ((err = WritePacket(cam, command, PACKET_LENGTH)) < 0) { | ||
597 | DBG("Error writing command\n"); | ||
598 | return err; | ||
599 | } | ||
600 | if(command[0] == DATA_IN) { | ||
601 | u8 buffer[8]; | ||
602 | if(data == NULL) { | ||
603 | DBG("Internal driver error: data is NULL\n"); | ||
604 | return -EINVAL; | ||
605 | } | ||
606 | if((err = ReadPacket(cam, buffer, 8)) < 0) { | ||
607 | DBG("Error reading command result\n"); | ||
608 | return err; | ||
609 | } | ||
610 | memcpy(data, buffer, databytes); | ||
611 | } else if(command[0] == DATA_OUT) { | ||
612 | if(databytes > 0) { | ||
613 | if(data == NULL) { | ||
614 | DBG("Internal driver error: data is NULL\n"); | ||
615 | retval = -EINVAL; | ||
616 | } else { | ||
617 | if((err=WritePacket(cam, data, databytes)) < 0){ | ||
618 | DBG("Error writing command data\n"); | ||
619 | return err; | ||
620 | } | ||
621 | } | ||
622 | } | ||
623 | } else { | ||
624 | DBG("Unexpected first byte of command: %x\n", command[0]); | ||
625 | retval = -EINVAL; | ||
626 | } | ||
627 | return retval; | ||
628 | } | ||
629 | |||
630 | /**************************************************************************** | ||
631 | * | ||
632 | * cpia_pp_open | ||
633 | * | ||
634 | ***************************************************************************/ | ||
635 | static int cpia_pp_open(void *privdata) | ||
636 | { | ||
637 | struct pp_cam_entry *cam = (struct pp_cam_entry *)privdata; | ||
638 | |||
639 | if (cam == NULL) | ||
640 | return -EINVAL; | ||
641 | |||
642 | if(cam->open_count == 0) { | ||
643 | if (parport_claim(cam->pdev)) { | ||
644 | DBG("failed to claim the port\n"); | ||
645 | return -EBUSY; | ||
646 | } | ||
647 | parport_negotiate(cam->port, IEEE1284_MODE_COMPAT); | ||
648 | parport_data_forward(cam->port); | ||
649 | parport_write_control(cam->port, PARPORT_CONTROL_SELECT); | ||
650 | udelay(50); | ||
651 | parport_write_control(cam->port, | ||
652 | PARPORT_CONTROL_SELECT | ||
653 | | PARPORT_CONTROL_INIT); | ||
654 | } | ||
655 | |||
656 | ++cam->open_count; | ||
657 | |||
658 | return 0; | ||
659 | } | ||
660 | |||
661 | /**************************************************************************** | ||
662 | * | ||
663 | * cpia_pp_registerCallback | ||
664 | * | ||
665 | ***************************************************************************/ | ||
666 | static int cpia_pp_registerCallback(void *privdata, void (*cb)(void *cbdata), void *cbdata) | ||
667 | { | ||
668 | struct pp_cam_entry *cam = privdata; | ||
669 | int retval = 0; | ||
670 | |||
671 | if(cam->port->irq != PARPORT_IRQ_NONE) { | ||
672 | INIT_WORK(&cam->cb_task, cb, cbdata); | ||
673 | } else { | ||
674 | retval = -1; | ||
675 | } | ||
676 | return retval; | ||
677 | } | ||
678 | |||
679 | /**************************************************************************** | ||
680 | * | ||
681 | * cpia_pp_close | ||
682 | * | ||
683 | ***************************************************************************/ | ||
684 | static int cpia_pp_close(void *privdata) | ||
685 | { | ||
686 | struct pp_cam_entry *cam = privdata; | ||
687 | if (--cam->open_count == 0) { | ||
688 | parport_release(cam->pdev); | ||
689 | } | ||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | /**************************************************************************** | ||
694 | * | ||
695 | * cpia_pp_register | ||
696 | * | ||
697 | ***************************************************************************/ | ||
698 | static int cpia_pp_register(struct parport *port) | ||
699 | { | ||
700 | struct pardevice *pdev = NULL; | ||
701 | struct pp_cam_entry *cam; | ||
702 | struct cam_data *cpia; | ||
703 | |||
704 | if (!(port->modes & PARPORT_MODE_PCSPP)) { | ||
705 | LOG("port is not supported by CPiA driver\n"); | ||
706 | return -ENXIO; | ||
707 | } | ||
708 | |||
709 | cam = kmalloc(sizeof(struct pp_cam_entry), GFP_KERNEL); | ||
710 | if (cam == NULL) { | ||
711 | LOG("failed to allocate camera structure\n"); | ||
712 | return -ENOMEM; | ||
713 | } | ||
714 | memset(cam,0,sizeof(struct pp_cam_entry)); | ||
715 | |||
716 | pdev = parport_register_device(port, "cpia_pp", NULL, NULL, | ||
717 | NULL, 0, cam); | ||
718 | |||
719 | if (!pdev) { | ||
720 | LOG("failed to parport_register_device\n"); | ||
721 | kfree(cam); | ||
722 | return -ENXIO; | ||
723 | } | ||
724 | |||
725 | cam->pdev = pdev; | ||
726 | cam->port = port; | ||
727 | init_waitqueue_head(&cam->wq_stream); | ||
728 | |||
729 | cam->streaming = 0; | ||
730 | cam->stream_irq = 0; | ||
731 | |||
732 | if((cpia = cpia_register_camera(&cpia_pp_ops, cam)) == NULL) { | ||
733 | LOG("failed to cpia_register_camera\n"); | ||
734 | parport_unregister_device(pdev); | ||
735 | kfree(cam); | ||
736 | return -ENXIO; | ||
737 | } | ||
738 | spin_lock( &cam_list_lock_pp ); | ||
739 | list_add( &cpia->cam_data_list, &cam_list ); | ||
740 | spin_unlock( &cam_list_lock_pp ); | ||
741 | |||
742 | return 0; | ||
743 | } | ||
744 | |||
745 | static void cpia_pp_detach (struct parport *port) | ||
746 | { | ||
747 | struct list_head *tmp; | ||
748 | struct cam_data *cpia = NULL; | ||
749 | struct pp_cam_entry *cam; | ||
750 | |||
751 | spin_lock( &cam_list_lock_pp ); | ||
752 | list_for_each (tmp, &cam_list) { | ||
753 | cpia = list_entry(tmp, struct cam_data, cam_data_list); | ||
754 | cam = (struct pp_cam_entry *) cpia->lowlevel_data; | ||
755 | if (cam && cam->port->number == port->number) { | ||
756 | list_del(&cpia->cam_data_list); | ||
757 | break; | ||
758 | } | ||
759 | cpia = NULL; | ||
760 | } | ||
761 | spin_unlock( &cam_list_lock_pp ); | ||
762 | |||
763 | if (!cpia) { | ||
764 | DBG("cpia_pp_detach failed to find cam_data in cam_list\n"); | ||
765 | return; | ||
766 | } | ||
767 | |||
768 | cam = (struct pp_cam_entry *) cpia->lowlevel_data; | ||
769 | cpia_unregister_camera(cpia); | ||
770 | if(cam->open_count > 0) | ||
771 | cpia_pp_close(cam); | ||
772 | parport_unregister_device(cam->pdev); | ||
773 | cpia->lowlevel_data = NULL; | ||
774 | kfree(cam); | ||
775 | } | ||
776 | |||
777 | static void cpia_pp_attach (struct parport *port) | ||
778 | { | ||
779 | unsigned int i; | ||
780 | |||
781 | switch (parport_nr[0]) | ||
782 | { | ||
783 | case PPCPIA_PARPORT_UNSPEC: | ||
784 | case PPCPIA_PARPORT_AUTO: | ||
785 | if (port->probe_info[0].class != PARPORT_CLASS_MEDIA || | ||
786 | port->probe_info[0].cmdset == NULL || | ||
787 | strncmp(port->probe_info[0].cmdset, "CPIA_1", 6) != 0) | ||
788 | return; | ||
789 | |||
790 | cpia_pp_register(port); | ||
791 | |||
792 | break; | ||
793 | |||
794 | default: | ||
795 | for (i = 0; i < PARPORT_MAX; ++i) { | ||
796 | if (port->number == parport_nr[i]) { | ||
797 | cpia_pp_register(port); | ||
798 | break; | ||
799 | } | ||
800 | } | ||
801 | break; | ||
802 | } | ||
803 | } | ||
804 | |||
805 | static struct parport_driver cpia_pp_driver = { | ||
806 | .name = "cpia_pp", | ||
807 | .attach = cpia_pp_attach, | ||
808 | .detach = cpia_pp_detach, | ||
809 | }; | ||
810 | |||
811 | int cpia_pp_init(void) | ||
812 | { | ||
813 | printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT, | ||
814 | CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER); | ||
815 | |||
816 | if(parport_nr[0] == PPCPIA_PARPORT_OFF) { | ||
817 | printk(" disabled\n"); | ||
818 | return 0; | ||
819 | } | ||
820 | |||
821 | spin_lock_init( &cam_list_lock_pp ); | ||
822 | |||
823 | if (parport_register_driver (&cpia_pp_driver)) { | ||
824 | LOG ("unable to register with parport\n"); | ||
825 | return -EIO; | ||
826 | } | ||
827 | return 0; | ||
828 | } | ||
829 | |||
830 | #ifdef MODULE | ||
831 | int init_module(void) | ||
832 | { | ||
833 | if (parport[0]) { | ||
834 | /* The user gave some parameters. Let's see what they were. */ | ||
835 | if (!strncmp(parport[0], "auto", 4)) { | ||
836 | parport_nr[0] = PPCPIA_PARPORT_AUTO; | ||
837 | } else { | ||
838 | int n; | ||
839 | for (n = 0; n < PARPORT_MAX && parport[n]; n++) { | ||
840 | if (!strncmp(parport[n], "none", 4)) { | ||
841 | parport_nr[n] = PPCPIA_PARPORT_NONE; | ||
842 | } else { | ||
843 | char *ep; | ||
844 | unsigned long r = simple_strtoul(parport[n], &ep, 0); | ||
845 | if (ep != parport[n]) { | ||
846 | parport_nr[n] = r; | ||
847 | } else { | ||
848 | LOG("bad port specifier `%s'\n", parport[n]); | ||
849 | return -ENODEV; | ||
850 | } | ||
851 | } | ||
852 | } | ||
853 | } | ||
854 | } | ||
855 | return cpia_pp_init(); | ||
856 | } | ||
857 | |||
858 | void cleanup_module(void) | ||
859 | { | ||
860 | parport_unregister_driver (&cpia_pp_driver); | ||
861 | return; | ||
862 | } | ||
863 | |||
864 | #else /* !MODULE */ | ||
865 | |||
866 | static int __init cpia_pp_setup(char *str) | ||
867 | { | ||
868 | if (!strncmp(str, "parport", 7)) { | ||
869 | int n = simple_strtoul(str + 7, NULL, 10); | ||
870 | if (parport_ptr < PARPORT_MAX) { | ||
871 | parport_nr[parport_ptr++] = n; | ||
872 | } else { | ||
873 | LOG("too many ports, %s ignored.\n", str); | ||
874 | } | ||
875 | } else if (!strcmp(str, "auto")) { | ||
876 | parport_nr[0] = PPCPIA_PARPORT_AUTO; | ||
877 | } else if (!strcmp(str, "none")) { | ||
878 | parport_nr[parport_ptr++] = PPCPIA_PARPORT_NONE; | ||
879 | } | ||
880 | |||
881 | return 0; | ||
882 | } | ||
883 | |||
884 | __setup("cpia_pp=", cpia_pp_setup); | ||
885 | |||
886 | #endif /* !MODULE */ | ||