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