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