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