blob: 86bd08270ded1e319dffe9d3f5bf06e29d7abb57 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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) */
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -030026/* #define _CPIA_DEBUG_ 1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070027
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
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
45static int cpia_pp_open(void *privdata);
46static int cpia_pp_registerCallback(void *privdata, void (*cb) (void *cbdata),
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -030047 void *cbdata);
Linus Torvalds1da177e2005-04-16 15:20:36 -070048static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data);
49static int cpia_pp_streamStart(void *privdata);
50static int cpia_pp_streamStop(void *privdata);
51static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock);
52static 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
66static int parport_nr[PARPORT_MAX] = {[0 ... PARPORT_MAX - 1] = PPCPIA_PARPORT_UNSPEC};
67static char *parport[PARPORT_MAX] = {NULL,};
68
69MODULE_AUTHOR("B. Huisman <bhuism@cs.utwente.nl> & Peter Pregler <Peter_Pregler@email.com>");
70MODULE_DESCRIPTION("Parallel port driver for Vision CPiA based cameras");
71MODULE_LICENSE("GPL");
72
73module_param_array(parport, charp, NULL, 0);
74MODULE_PARM_DESC(parport, "'auto' or a list of parallel port numbers. Just like lp.");
75#else
76static int parport_nr[PARPORT_MAX] __initdata =
77 {[0 ... PARPORT_MAX - 1] = PPCPIA_PARPORT_UNSPEC};
78static int parport_ptr = 0;
79#endif
80
81struct pp_cam_entry {
82 struct pardevice *pdev;
83 struct parport *port;
84 struct work_struct cb_task;
David Howellsc4028952006-11-22 14:57:56 +000085 void (*cb_func)(void *cbdata);
86 void *cb_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -070087 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
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -030097static struct cpia_camera_ops cpia_pp_ops =
Linus Torvalds1da177e2005-04-16 15:20:36 -070098{
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
110static LIST_HEAD(cam_list);
111static spinlock_t cam_list_lock_pp;
112
113/* FIXME */
114static void cpia_parport_enable_irq( struct parport *port ) {
115 parport_enable_irq(port);
116 mdelay(10);
117 return;
118}
119
120static 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
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300127 * Link Flag during negotiation */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128#define UPLOAD_FLAG 0x08
129#define NIBBLE_TRANSFER 0x01
130#define ECP_TRANSFER 0x03
131
132#define PARPORT_CHUNK_SIZE PAGE_SIZE
133
134
David Howellsc4028952006-11-22 14:57:56 +0000135static 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;
David Howellsc4028952006-11-22 14:57:56 +0000144
145 cb_func(cb_data);
146}
147
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148/****************************************************************************
149 *
150 * CPiA-specific low-level parport functions for nibble uploads
151 *
152 ***************************************************************************/
153/* CPiA nonstandard "Nibble" mode (no nDataAvail signal after each byte). */
154/* The standard kernel parport_ieee1284_read_nibble() fails with the CPiA... */
155
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300156static size_t cpia_read_nibble (struct parport *port,
157 void *buffer, size_t len,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 int flags)
159{
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300160 /* adapted verbatim, with one change, from
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161 parport_ieee1284_read_nibble() in drivers/parport/ieee1284-ops.c */
162
163 unsigned char *buf = buffer;
164 int i;
165 unsigned char byte = 0;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300166
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 len *= 2; /* in nibbles */
168 for (i=0; i < len; i++) {
169 unsigned char nibble;
170
171 /* The CPiA firmware suppresses the use of nDataAvail (nFault LO)
172 * after every second nibble to signal that more
173 * data is available. (the total number of Bytes that
174 * should be sent is known; if too few are received, an error
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300175 * will be recorded after a timeout).
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 * This is incompatible with parport_ieee1284_read_nibble(),
177 * which expects to find nFault LO after every second nibble.
178 */
179
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300180 /* Solution: modify cpia_read_nibble to only check for
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 * nDataAvail before the first nibble is sent.
182 */
183
184 /* Does the error line indicate end of data? */
185 if (((i /*& 1*/) == 0) &&
186 (parport_read_status(port) & PARPORT_STATUS_ERROR)) {
Marko Kohtala742ec652006-01-06 00:19:44 -0800187 DBG("%s: No more nibble data (%d bytes)\n",
188 port->name, i/2);
189 goto end_of_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 }
191
192 /* Event 7: Set nAutoFd low. */
193 parport_frob_control (port,
194 PARPORT_CONTROL_AUTOFD,
195 PARPORT_CONTROL_AUTOFD);
196
197 /* Event 9: nAck goes low. */
198 port->ieee1284.phase = IEEE1284_PH_REV_DATA;
199 if (parport_wait_peripheral (port,
200 PARPORT_STATUS_ACK, 0)) {
201 /* Timeout -- no more data? */
202 DBG("%s: Nibble timeout at event 9 (%d bytes)\n",
203 port->name, i/2);
204 parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
205 break;
206 }
207
208
209 /* Read a nibble. */
210 nibble = parport_read_status (port) >> 3;
211 nibble &= ~8;
212 if ((nibble & 0x10) == 0)
213 nibble |= 8;
214 nibble &= 0xf;
215
216 /* Event 10: Set nAutoFd high. */
217 parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
218
219 /* Event 11: nAck goes high. */
220 if (parport_wait_peripheral (port,
221 PARPORT_STATUS_ACK,
222 PARPORT_STATUS_ACK)) {
223 /* Timeout -- no more data? */
224 DBG("%s: Nibble timeout at event 11\n",
225 port->name);
226 break;
227 }
228
229 if (i & 1) {
230 /* Second nibble */
231 byte |= nibble << 4;
232 *buf++ = byte;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300233 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 byte = nibble;
235 }
236
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 if (i == len) {
238 /* Read the last nibble without checking data avail. */
Marko Kohtala742ec652006-01-06 00:19:44 -0800239 if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
240 end_of_data:
241 /* Go to reverse idle phase. */
242 parport_frob_control (port,
243 PARPORT_CONTROL_AUTOFD,
244 PARPORT_CONTROL_AUTOFD);
245 port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
246 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 else
Marko Kohtala742ec652006-01-06 00:19:44 -0800248 port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 }
250
Marko Kohtala742ec652006-01-06 00:19:44 -0800251 return i/2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252}
253
254/* CPiA nonstandard "Nibble Stream" mode (2 nibbles per cycle, instead of 1)
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300255 * (See CPiA Data sheet p. 31)
256 *
257 * "Nibble Stream" mode used by CPiA for uploads to non-ECP ports is a
258 * nonstandard variant of nibble mode which allows the same (mediocre)
259 * data flow of 8 bits per cycle as software-enabled ECP by TRISTATE-capable
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 * parallel ports, but works also for non-TRISTATE-capable ports.
261 * (Standard nibble mode only send 4 bits per cycle)
262 *
263 */
264
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300265static size_t cpia_read_nibble_stream(struct parport *port,
266 void *buffer, size_t len,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 int flags)
268{
269 int i;
270 unsigned char *buf = buffer;
271 int endseen = 0;
272
273 for (i=0; i < len; i++) {
274 unsigned char nibble[2], byte = 0;
275 int j;
276
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300277 /* Image Data is complete when 4 consecutive EOI bytes (0xff) are seen */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 if (endseen > 3 )
279 break;
280
281 /* Event 7: Set nAutoFd low. */
282 parport_frob_control (port,
283 PARPORT_CONTROL_AUTOFD,
284 PARPORT_CONTROL_AUTOFD);
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300285
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 /* Event 9: nAck goes low. */
287 port->ieee1284.phase = IEEE1284_PH_REV_DATA;
288 if (parport_wait_peripheral (port,
289 PARPORT_STATUS_ACK, 0)) {
290 /* Timeout -- no more data? */
291 DBG("%s: Nibble timeout at event 9 (%d bytes)\n",
292 port->name, i/2);
293 parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
294 break;
295 }
296
297 /* Read lower nibble */
298 nibble[0] = parport_read_status (port) >>3;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300299
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 /* Event 10: Set nAutoFd high. */
301 parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
302
303 /* Event 11: nAck goes high. */
304 if (parport_wait_peripheral (port,
305 PARPORT_STATUS_ACK,
306 PARPORT_STATUS_ACK)) {
307 /* Timeout -- no more data? */
308 DBG("%s: Nibble timeout at event 11\n",
309 port->name);
310 break;
311 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300312
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 /* Read upper nibble */
314 nibble[1] = parport_read_status (port) >>3;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300315
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 /* reassemble the byte */
317 for (j = 0; j < 2 ; j++ ) {
318 nibble[j] &= ~8;
319 if ((nibble[j] & 0x10) == 0)
320 nibble[j] |= 8;
321 nibble[j] &= 0xf;
322 }
323 byte = (nibble[0] |(nibble[1] << 4));
324 *buf++ = byte;
325
326 if(byte == EOI)
327 endseen++;
328 else
329 endseen = 0;
330 }
331 return i;
332}
333
334/****************************************************************************
335 *
336 * EndTransferMode
337 *
338 ***************************************************************************/
339static void EndTransferMode(struct pp_cam_entry *cam)
340{
341 parport_negotiate(cam->port, IEEE1284_MODE_COMPAT);
342}
343
344/****************************************************************************
345 *
346 * ForwardSetup
347 *
348 ***************************************************************************/
349static int ForwardSetup(struct pp_cam_entry *cam)
350{
351 int retry;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300352
353 /* The CPiA uses ECP protocol for Downloads from the Host to the camera.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 * This will be software-emulated if ECP hardware is not present
355 */
356
357 /* the usual camera maximum response time is 10ms, but after receiving
358 * some commands, it needs up to 40ms. (Data Sheet p. 32)*/
359
360 for(retry = 0; retry < 4; ++retry) {
361 if(!parport_negotiate(cam->port, IEEE1284_MODE_ECP)) {
362 break;
363 }
364 mdelay(10);
365 }
366 if(retry == 4) {
367 DBG("Unable to negotiate IEEE1284 ECP Download mode\n");
368 return -1;
369 }
370 return 0;
371}
372/****************************************************************************
373 *
374 * ReverseSetup
375 *
376 ***************************************************************************/
377static int ReverseSetup(struct pp_cam_entry *cam, int extensibility)
378{
379 int retry;
380 int upload_mode, mode = IEEE1284_MODE_ECP;
381 int transfer_mode = ECP_TRANSFER;
382
383 if (!(cam->port->modes & PARPORT_MODE_ECP) &&
384 !(cam->port->modes & PARPORT_MODE_TRISTATE)) {
385 mode = IEEE1284_MODE_NIBBLE;
386 transfer_mode = NIBBLE_TRANSFER;
387 }
388
389 upload_mode = mode;
390 if(extensibility) mode = UPLOAD_FLAG|transfer_mode|IEEE1284_EXT_LINK;
391
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300392 /* the usual camera maximum response time is 10ms, but after
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 * receiving some commands, it needs up to 40ms. */
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300394
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 for(retry = 0; retry < 4; ++retry) {
396 if(!parport_negotiate(cam->port, mode)) {
397 break;
398 }
399 mdelay(10);
400 }
401 if(retry == 4) {
402 if(extensibility)
403 DBG("Unable to negotiate upload extensibility mode\n");
404 else
405 DBG("Unable to negotiate upload mode\n");
406 return -1;
407 }
408 if(extensibility) cam->port->ieee1284.mode = upload_mode;
409 return 0;
410}
411
412/****************************************************************************
413 *
414 * WritePacket
415 *
416 ***************************************************************************/
417static int WritePacket(struct pp_cam_entry *cam, const u8 *packet, size_t size)
418{
419 int retval=0;
420 int size_written;
421
422 if (packet == NULL) {
423 return -EINVAL;
424 }
425 if (ForwardSetup(cam)) {
426 DBG("Write failed in setup\n");
427 return -EIO;
428 }
429 size_written = parport_write(cam->port, packet, size);
430 if(size_written != size) {
431 DBG("Write failed, wrote %d/%d\n", size_written, size);
432 retval = -EIO;
433 }
434 EndTransferMode(cam);
435 return retval;
436}
437
438/****************************************************************************
439 *
440 * ReadPacket
441 *
442 ***************************************************************************/
443static int ReadPacket(struct pp_cam_entry *cam, u8 *packet, size_t size)
444{
445 int retval=0;
446
447 if (packet == NULL) {
448 return -EINVAL;
449 }
450 if (ReverseSetup(cam, 0)) {
451 return -EIO;
452 }
453
454 /* support for CPiA variant nibble reads */
455 if(cam->port->ieee1284.mode == IEEE1284_MODE_NIBBLE) {
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300456 if(cpia_read_nibble(cam->port, packet, size, 0) != size)
457 retval = -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 } else {
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300459 if(parport_read(cam->port, packet, size) != size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 retval = -EIO;
461 }
462 EndTransferMode(cam);
463 return retval;
464}
465
466/****************************************************************************
467 *
468 * cpia_pp_streamStart
469 *
470 ***************************************************************************/
471static int cpia_pp_streamStart(void *privdata)
472{
473 struct pp_cam_entry *cam = privdata;
474 DBG("\n");
475 cam->streaming=1;
476 cam->image_ready=0;
477 //if (ReverseSetup(cam,1)) return -EIO;
478 if(cam->stream_irq) cpia_parport_enable_irq(cam->port);
479 return 0;
480}
481
482/****************************************************************************
483 *
484 * cpia_pp_streamStop
485 *
486 ***************************************************************************/
487static int cpia_pp_streamStop(void *privdata)
488{
489 struct pp_cam_entry *cam = privdata;
490
491 DBG("\n");
492 cam->streaming=0;
493 cpia_parport_disable_irq(cam->port);
494 //EndTransferMode(cam);
495
496 return 0;
497}
498
499/****************************************************************************
500 *
501 * cpia_pp_streamRead
502 *
503 ***************************************************************************/
504static int cpia_pp_read(struct parport *port, u8 *buffer, int len)
505{
506 int bytes_read;
507
508 /* support for CPiA variant "nibble stream" reads */
509 if(port->ieee1284.mode == IEEE1284_MODE_NIBBLE)
510 bytes_read = cpia_read_nibble_stream(port,buffer,len,0);
511 else {
512 int new_bytes;
513 for(bytes_read=0; bytes_read<len; bytes_read += new_bytes) {
514 new_bytes = parport_read(port, buffer+bytes_read,
515 len-bytes_read);
516 if(new_bytes < 0) break;
517 }
518 }
519 return bytes_read;
520}
521
522static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock)
523{
524 struct pp_cam_entry *cam = privdata;
525 int read_bytes = 0;
526 int i, endseen, block_size, new_bytes;
527
528 if(cam == NULL) {
529 DBG("Internal driver error: cam is NULL\n");
530 return -EINVAL;
531 }
532 if(buffer == NULL) {
533 DBG("Internal driver error: buffer is NULL\n");
534 return -EINVAL;
535 }
536 //if(cam->streaming) DBG("%d / %d\n", cam->image_ready, noblock);
537 if( cam->stream_irq ) {
538 DBG("%d\n", cam->image_ready);
539 cam->image_ready--;
540 }
541 cam->image_complete=0;
542 if (0/*cam->streaming*/) {
543 if(!cam->image_ready) {
544 if(noblock) return -EWOULDBLOCK;
545 interruptible_sleep_on(&cam->wq_stream);
546 if( signal_pending(current) ) return -EINTR;
547 DBG("%d\n", cam->image_ready);
548 }
549 } else {
550 if (ReverseSetup(cam, 1)) {
551 DBG("unable to ReverseSetup\n");
552 return -EIO;
553 }
554 }
555 endseen = 0;
556 block_size = PARPORT_CHUNK_SIZE;
557 while( !cam->image_complete ) {
558 cond_resched();
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300559
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 new_bytes = cpia_pp_read(cam->port, buffer, block_size );
561 if( new_bytes <= 0 ) {
562 break;
563 }
564 i=-1;
565 while(++i<new_bytes && endseen<4) {
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300566 if(*buffer==EOI) {
567 endseen++;
568 } else {
569 endseen=0;
570 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 buffer++;
572 }
573 read_bytes += i;
574 if( endseen==4 ) {
575 cam->image_complete=1;
576 break;
577 }
578 if( CPIA_MAX_IMAGE_SIZE-read_bytes <= PARPORT_CHUNK_SIZE ) {
579 block_size=CPIA_MAX_IMAGE_SIZE-read_bytes;
580 }
581 }
582 EndTransferMode(cam);
583 return cam->image_complete ? read_bytes : -EIO;
584}
585/****************************************************************************
586 *
587 * cpia_pp_transferCmd
588 *
589 ***************************************************************************/
590static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data)
591{
592 int err;
593 int retval=0;
594 int databytes;
595 struct pp_cam_entry *cam = privdata;
596
597 if(cam == NULL) {
598 DBG("Internal driver error: cam is NULL\n");
599 return -EINVAL;
600 }
601 if(command == NULL) {
602 DBG("Internal driver error: command is NULL\n");
603 return -EINVAL;
604 }
605 databytes = (((int)command[7])<<8) | command[6];
606 if ((err = WritePacket(cam, command, PACKET_LENGTH)) < 0) {
607 DBG("Error writing command\n");
608 return err;
609 }
610 if(command[0] == DATA_IN) {
611 u8 buffer[8];
612 if(data == NULL) {
613 DBG("Internal driver error: data is NULL\n");
614 return -EINVAL;
615 }
616 if((err = ReadPacket(cam, buffer, 8)) < 0) {
617 DBG("Error reading command result\n");
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300618 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 }
620 memcpy(data, buffer, databytes);
621 } else if(command[0] == DATA_OUT) {
622 if(databytes > 0) {
623 if(data == NULL) {
624 DBG("Internal driver error: data is NULL\n");
625 retval = -EINVAL;
626 } else {
627 if((err=WritePacket(cam, data, databytes)) < 0){
628 DBG("Error writing command data\n");
629 return err;
630 }
631 }
632 }
633 } else {
634 DBG("Unexpected first byte of command: %x\n", command[0]);
635 retval = -EINVAL;
636 }
637 return retval;
638}
639
640/****************************************************************************
641 *
642 * cpia_pp_open
643 *
644 ***************************************************************************/
645static int cpia_pp_open(void *privdata)
646{
647 struct pp_cam_entry *cam = (struct pp_cam_entry *)privdata;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300648
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 if (cam == NULL)
650 return -EINVAL;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300651
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 if(cam->open_count == 0) {
653 if (parport_claim(cam->pdev)) {
654 DBG("failed to claim the port\n");
655 return -EBUSY;
656 }
657 parport_negotiate(cam->port, IEEE1284_MODE_COMPAT);
658 parport_data_forward(cam->port);
659 parport_write_control(cam->port, PARPORT_CONTROL_SELECT);
660 udelay(50);
661 parport_write_control(cam->port,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300662 PARPORT_CONTROL_SELECT
663 | PARPORT_CONTROL_INIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300665
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 ++cam->open_count;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300667
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 return 0;
669}
670
671/****************************************************************************
672 *
673 * cpia_pp_registerCallback
674 *
675 ***************************************************************************/
676static int cpia_pp_registerCallback(void *privdata, void (*cb)(void *cbdata), void *cbdata)
677{
678 struct pp_cam_entry *cam = privdata;
679 int retval = 0;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300680
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 if(cam->port->irq != PARPORT_IRQ_NONE) {
David Howellsc4028952006-11-22 14:57:56 +0000682 cam->cb_func = cb;
683 cam->cb_data = cbdata;
Oleg Nesterov5cdc1782007-03-09 17:43:39 -0300684 INIT_WORK(&cam->cb_task, cpia_pp_run_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 } else {
686 retval = -1;
687 }
688 return retval;
689}
690
691/****************************************************************************
692 *
693 * cpia_pp_close
694 *
695 ***************************************************************************/
696static int cpia_pp_close(void *privdata)
697{
698 struct pp_cam_entry *cam = privdata;
699 if (--cam->open_count == 0) {
700 parport_release(cam->pdev);
701 }
702 return 0;
703}
704
705/****************************************************************************
706 *
707 * cpia_pp_register
708 *
709 ***************************************************************************/
710static int cpia_pp_register(struct parport *port)
711{
712 struct pardevice *pdev = NULL;
713 struct pp_cam_entry *cam;
714 struct cam_data *cpia;
715
716 if (!(port->modes & PARPORT_MODE_PCSPP)) {
717 LOG("port is not supported by CPiA driver\n");
718 return -ENXIO;
719 }
720
Panagiotis Issaris74081872006-01-11 19:40:56 -0200721 cam = kzalloc(sizeof(struct pp_cam_entry), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 if (cam == NULL) {
723 LOG("failed to allocate camera structure\n");
724 return -ENOMEM;
725 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300726
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 pdev = parport_register_device(port, "cpia_pp", NULL, NULL,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300728 NULL, 0, cam);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729
730 if (!pdev) {
731 LOG("failed to parport_register_device\n");
732 kfree(cam);
733 return -ENXIO;
734 }
735
736 cam->pdev = pdev;
737 cam->port = port;
738 init_waitqueue_head(&cam->wq_stream);
739
740 cam->streaming = 0;
741 cam->stream_irq = 0;
742
743 if((cpia = cpia_register_camera(&cpia_pp_ops, cam)) == NULL) {
744 LOG("failed to cpia_register_camera\n");
745 parport_unregister_device(pdev);
746 kfree(cam);
747 return -ENXIO;
748 }
749 spin_lock( &cam_list_lock_pp );
750 list_add( &cpia->cam_data_list, &cam_list );
751 spin_unlock( &cam_list_lock_pp );
752
753 return 0;
754}
755
756static void cpia_pp_detach (struct parport *port)
757{
758 struct list_head *tmp;
759 struct cam_data *cpia = NULL;
760 struct pp_cam_entry *cam;
761
762 spin_lock( &cam_list_lock_pp );
763 list_for_each (tmp, &cam_list) {
764 cpia = list_entry(tmp, struct cam_data, cam_data_list);
765 cam = (struct pp_cam_entry *) cpia->lowlevel_data;
766 if (cam && cam->port->number == port->number) {
767 list_del(&cpia->cam_data_list);
768 break;
769 }
770 cpia = NULL;
771 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300772 spin_unlock( &cam_list_lock_pp );
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773
774 if (!cpia) {
775 DBG("cpia_pp_detach failed to find cam_data in cam_list\n");
776 return;
777 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300778
779 cam = (struct pp_cam_entry *) cpia->lowlevel_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 cpia_unregister_camera(cpia);
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300781 if(cam->open_count > 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 cpia_pp_close(cam);
783 parport_unregister_device(cam->pdev);
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300784 cpia->lowlevel_data = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 kfree(cam);
786}
787
788static void cpia_pp_attach (struct parport *port)
789{
790 unsigned int i;
791
792 switch (parport_nr[0])
793 {
794 case PPCPIA_PARPORT_UNSPEC:
795 case PPCPIA_PARPORT_AUTO:
796 if (port->probe_info[0].class != PARPORT_CLASS_MEDIA ||
797 port->probe_info[0].cmdset == NULL ||
798 strncmp(port->probe_info[0].cmdset, "CPIA_1", 6) != 0)
799 return;
800
801 cpia_pp_register(port);
802
803 break;
804
805 default:
806 for (i = 0; i < PARPORT_MAX; ++i) {
807 if (port->number == parport_nr[i]) {
808 cpia_pp_register(port);
809 break;
810 }
811 }
812 break;
813 }
814}
815
816static struct parport_driver cpia_pp_driver = {
817 .name = "cpia_pp",
818 .attach = cpia_pp_attach,
819 .detach = cpia_pp_detach,
820};
821
Mauro Carvalho Chehab2ed64eb2006-06-08 17:16:46 -0300822static int cpia_pp_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823{
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300824 printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER);
826
827 if(parport_nr[0] == PPCPIA_PARPORT_OFF) {
828 printk(" disabled\n");
829 return 0;
830 }
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300831
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 spin_lock_init( &cam_list_lock_pp );
833
834 if (parport_register_driver (&cpia_pp_driver)) {
835 LOG ("unable to register with parport\n");
836 return -EIO;
837 }
838 return 0;
839}
840
841#ifdef MODULE
842int init_module(void)
843{
844 if (parport[0]) {
845 /* The user gave some parameters. Let's see what they were. */
846 if (!strncmp(parport[0], "auto", 4)) {
847 parport_nr[0] = PPCPIA_PARPORT_AUTO;
848 } else {
849 int n;
850 for (n = 0; n < PARPORT_MAX && parport[n]; n++) {
851 if (!strncmp(parport[n], "none", 4)) {
852 parport_nr[n] = PPCPIA_PARPORT_NONE;
853 } else {
854 char *ep;
855 unsigned long r = simple_strtoul(parport[n], &ep, 0);
856 if (ep != parport[n]) {
857 parport_nr[n] = r;
858 } else {
859 LOG("bad port specifier `%s'\n", parport[n]);
860 return -ENODEV;
861 }
862 }
863 }
864 }
865 }
866 return cpia_pp_init();
867}
868
869void cleanup_module(void)
870{
871 parport_unregister_driver (&cpia_pp_driver);
872 return;
873}
874
875#else /* !MODULE */
876
877static int __init cpia_pp_setup(char *str)
878{
Mauro Carvalho Chehab2ed64eb2006-06-08 17:16:46 -0300879 int err;
880
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 if (!strncmp(str, "parport", 7)) {
882 int n = simple_strtoul(str + 7, NULL, 10);
883 if (parport_ptr < PARPORT_MAX) {
884 parport_nr[parport_ptr++] = n;
885 } else {
886 LOG("too many ports, %s ignored.\n", str);
887 }
888 } else if (!strcmp(str, "auto")) {
889 parport_nr[0] = PPCPIA_PARPORT_AUTO;
890 } else if (!strcmp(str, "none")) {
891 parport_nr[parport_ptr++] = PPCPIA_PARPORT_NONE;
892 }
893
Mauro Carvalho Chehab2ed64eb2006-06-08 17:16:46 -0300894 err=cpia_pp_init();
895 if (err)
896 return err;
897
OGAWA Hirofumi9b410462006-03-31 02:30:33 -0800898 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899}
900
901__setup("cpia_pp=", cpia_pp_setup);
902
903#endif /* !MODULE */