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