linux-old/drivers/media/video/cpia_pp.c
<<
>>
Prefs
   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#include <linux/version.h>
  30
  31#include <linux/module.h>
  32#include <linux/init.h>
  33
  34#include <linux/kernel.h>
  35#include <linux/parport.h>
  36#include <linux/interrupt.h>
  37#include <linux/delay.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
  46static int cpia_pp_open(void *privdata);
  47static int cpia_pp_registerCallback(void *privdata, void (*cb) (void *cbdata),
  48                                    void *cbdata);
  49static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data);
  50static int cpia_pp_streamStart(void *privdata);
  51static int cpia_pp_streamStop(void *privdata);
  52static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock);
  53static int cpia_pp_close(void *privdata);
  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_PARM(parport, "1-" __MODULE_STRING(PARPORT_MAX) "s");
  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 tq_struct cb_task;
  85        int open_count;
  86        wait_queue_head_t wq_stream;
  87        /* image state flags */
  88        int image_ready;        /* we got an interrupt */
  89        int image_complete;     /* we have seen 4 EOI */
  90
  91        int streaming; /* we are in streaming mode */
  92        int stream_irq;
  93};
  94
  95static struct cpia_camera_ops cpia_pp_ops = 
  96{
  97        cpia_pp_open,
  98        cpia_pp_registerCallback,
  99        cpia_pp_transferCmd,
 100        cpia_pp_streamStart,
 101        cpia_pp_streamStop,
 102        cpia_pp_streamRead,
 103        cpia_pp_close,
 104        1,
 105        THIS_MODULE
 106};
 107
 108static LIST_HEAD(cam_list);
 109static spinlock_t cam_list_lock_pp;
 110
 111/* FIXME */
 112static void cpia_parport_enable_irq( struct parport *port ) {
 113        parport_enable_irq(port);
 114        mdelay(10);
 115        return;
 116}
 117
 118static void cpia_parport_disable_irq( struct parport *port ) {
 119        parport_disable_irq(port);
 120        mdelay(10);
 121        return;
 122}
 123
 124/* Special CPiA PPC modes: These are invoked by using the 1284 Extensibility
 125 * Link Flag during negotiation */  
 126#define UPLOAD_FLAG  0x08
 127#define ECP_TRANSFER 0x03
 128
 129#define PARPORT_CHUNK_SIZE      PAGE_SIZE
 130
 131
 132/****************************************************************************
 133 *
 134 *  EndTransferMode
 135 *
 136 ***************************************************************************/
 137static void EndTransferMode(struct pp_cam_entry *cam)
 138{
 139        parport_negotiate(cam->port, IEEE1284_MODE_COMPAT);
 140}
 141
 142/****************************************************************************
 143 *
 144 *  ForwardSetup
 145 *
 146 ***************************************************************************/
 147static int ForwardSetup(struct pp_cam_entry *cam)
 148{
 149        int retry;
 150        
 151        /* After some commands the camera needs extra time before
 152         * it will respond again, so we try up to 3 times */
 153        for(retry=0; retry<3; ++retry) {
 154                if(!parport_negotiate(cam->port, IEEE1284_MODE_ECP)) {
 155                        break;
 156                }
 157        }
 158        if(retry == 3) {
 159                DBG("Unable to negotiate ECP mode\n");
 160                return -1;
 161        }
 162        return 0;
 163}
 164
 165/****************************************************************************
 166 *
 167 *  ReverseSetup
 168 *
 169 ***************************************************************************/
 170static int ReverseSetup(struct pp_cam_entry *cam, int extensibility)
 171{
 172        int retry;
 173        int mode = IEEE1284_MODE_ECP;
 174        if(extensibility) mode = UPLOAD_FLAG|ECP_TRANSFER|IEEE1284_EXT_LINK;
 175
 176        /* After some commands the camera needs extra time before
 177         * it will respond again, so we try up to 3 times */
 178        for(retry=0; retry<3; ++retry) {
 179                if(!parport_negotiate(cam->port, mode)) {
 180                        break;
 181                }
 182        }
 183        if(retry == 3) {
 184                if(extensibility)
 185                        DBG("Unable to negotiate extensibility mode\n");
 186                else
 187                        DBG("Unable to negotiate ECP mode\n");
 188                return -1;
 189        }
 190        if(extensibility) cam->port->ieee1284.mode = IEEE1284_MODE_ECP;
 191        return 0;
 192}
 193
 194/****************************************************************************
 195 *
 196 *  WritePacket
 197 *
 198 ***************************************************************************/
 199static int WritePacket(struct pp_cam_entry *cam, const u8 *packet, size_t size)
 200{
 201        int retval=0;
 202        int size_written;
 203
 204        if (packet == NULL) {
 205                return -EINVAL;
 206        }
 207        if (ForwardSetup(cam)) {
 208                DBG("Write failed in setup\n");
 209                return -EIO;
 210        }
 211        size_written = parport_write(cam->port, packet, size);
 212        if(size_written != size) {
 213                DBG("Write failed, wrote %d/%d\n", size_written, size);
 214                retval = -EIO;
 215        }
 216        EndTransferMode(cam);
 217        return retval;
 218}
 219
 220/****************************************************************************
 221 *
 222 *  ReadPacket
 223 *
 224 ***************************************************************************/
 225static int ReadPacket(struct pp_cam_entry *cam, u8 *packet, size_t size)
 226{
 227        int retval=0;
 228        if (packet == NULL) {
 229                return -EINVAL;
 230        }
 231        if (ReverseSetup(cam, 0)) {
 232                return -EIO;
 233        }
 234        if(parport_read(cam->port, packet, size) != size) {
 235                retval = -EIO;
 236        }
 237        EndTransferMode(cam);
 238        return retval;
 239}
 240
 241/****************************************************************************
 242 *
 243 *  cpia_pp_streamStart
 244 *
 245 ***************************************************************************/
 246static int cpia_pp_streamStart(void *privdata)
 247{
 248        struct pp_cam_entry *cam = privdata;
 249        DBG("\n");
 250        cam->streaming=1;
 251        cam->image_ready=0;
 252        //if (ReverseSetup(cam,1)) return -EIO;
 253        if(cam->stream_irq) cpia_parport_enable_irq(cam->port);
 254        return 0;
 255}
 256
 257/****************************************************************************
 258 *
 259 *  cpia_pp_streamStop
 260 *
 261 ***************************************************************************/
 262static int cpia_pp_streamStop(void *privdata)
 263{
 264        struct pp_cam_entry *cam = privdata;
 265
 266        DBG("\n");
 267        cam->streaming=0;
 268        cpia_parport_disable_irq(cam->port);
 269        //EndTransferMode(cam);
 270
 271        return 0;
 272}
 273
 274/****************************************************************************
 275 *
 276 *  cpia_pp_streamRead
 277 *
 278 ***************************************************************************/
 279static int cpia_pp_read(struct parport *port, u8 *buffer, int len)
 280{
 281        int bytes_read, new_bytes;
 282        for(bytes_read=0; bytes_read<len; bytes_read += new_bytes) {
 283                new_bytes = parport_read(port, buffer+bytes_read,
 284                                         len-bytes_read);
 285                if(new_bytes < 0) break;
 286        }
 287        return bytes_read;
 288}
 289
 290static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock)
 291{
 292        struct pp_cam_entry *cam = privdata;
 293        int read_bytes = 0;
 294        int i, endseen, block_size, new_bytes;
 295
 296        if(cam == NULL) {
 297                DBG("Internal driver error: cam is NULL\n");
 298                return -EINVAL;
 299        }
 300        if(buffer == NULL) {
 301                DBG("Internal driver error: buffer is NULL\n");
 302                return -EINVAL;
 303        }
 304        //if(cam->streaming) DBG("%d / %d\n", cam->image_ready, noblock);
 305        if( cam->stream_irq ) {
 306                DBG("%d\n", cam->image_ready);
 307                cam->image_ready--;
 308        }
 309        cam->image_complete=0;
 310        if (0/*cam->streaming*/) {
 311                if(!cam->image_ready) {
 312                        if(noblock) return -EWOULDBLOCK;
 313                        interruptible_sleep_on(&cam->wq_stream);
 314                        if( signal_pending(current) ) return -EINTR;
 315                        DBG("%d\n", cam->image_ready);
 316                }
 317        } else {
 318                if (ReverseSetup(cam, 1)) {
 319                        DBG("unable to ReverseSetup\n");
 320                        return -EIO;
 321                }
 322        }
 323        endseen = 0;
 324        block_size = PARPORT_CHUNK_SIZE;
 325        while( !cam->image_complete ) {
 326                if(current->need_resched)  schedule();
 327                
 328                new_bytes = cpia_pp_read(cam->port, buffer, block_size );
 329                if( new_bytes <= 0 ) {
 330                        break;
 331                }
 332                i=-1;
 333                while(++i<new_bytes && endseen<4) {
 334                        if(*buffer==EOI) {
 335                                endseen++;
 336                        } else {
 337                                endseen=0;
 338                        }
 339                        buffer++;
 340                }
 341                read_bytes += i;
 342                if( endseen==4 ) {
 343                        cam->image_complete=1;
 344                        break;
 345                }
 346                if( CPIA_MAX_IMAGE_SIZE-read_bytes <= PARPORT_CHUNK_SIZE ) {
 347                        block_size=CPIA_MAX_IMAGE_SIZE-read_bytes;
 348                }
 349        }
 350        EndTransferMode(cam);
 351        return cam->image_complete ? read_bytes : -EIO;
 352}
 353
 354/****************************************************************************
 355 *
 356 *  cpia_pp_transferCmd
 357 *
 358 ***************************************************************************/
 359static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data)
 360{
 361        int err;
 362        int retval=0;
 363        int databytes;
 364        struct pp_cam_entry *cam = privdata;
 365
 366        if(cam == NULL) {
 367                DBG("Internal driver error: cam is NULL\n");
 368                return -EINVAL;
 369        }
 370        if(command == NULL) {
 371                DBG("Internal driver error: command is NULL\n");
 372                return -EINVAL;
 373        }
 374        databytes = (((int)command[7])<<8) | command[6];
 375        if ((err = WritePacket(cam, command, PACKET_LENGTH)) < 0) {
 376                DBG("Error writing command\n");
 377                return err;
 378        }
 379        if(command[0] == DATA_IN) {
 380                u8 buffer[8];
 381                if(data == NULL) {
 382                        DBG("Internal driver error: data is NULL\n");
 383                        return -EINVAL;
 384                }
 385                if((err = ReadPacket(cam, buffer, 8)) < 0) {
 386                        DBG("Error reading command result\n");
 387                       return err;
 388                }
 389                memcpy(data, buffer, databytes);
 390        } else if(command[0] == DATA_OUT) {
 391                if(databytes > 0) {
 392                        if(data == NULL) {
 393                                DBG("Internal driver error: data is NULL\n");
 394                                retval = -EINVAL;
 395                        } else {
 396                                if((err=WritePacket(cam, data, databytes)) < 0){
 397                                        DBG("Error writing command data\n");
 398                                        return err;
 399                                }
 400                        }
 401                }
 402        } else {
 403                DBG("Unexpected first byte of command: %x\n", command[0]);
 404                retval = -EINVAL;
 405        }
 406        return retval;
 407}
 408
 409/****************************************************************************
 410 *
 411 *  cpia_pp_open
 412 *
 413 ***************************************************************************/
 414static int cpia_pp_open(void *privdata)
 415{
 416        struct pp_cam_entry *cam = (struct pp_cam_entry *)privdata;
 417        
 418        if (cam == NULL)
 419                return -EINVAL;
 420        
 421        if(cam->open_count == 0) {
 422                if (parport_claim(cam->pdev)) {
 423                        DBG("failed to claim the port\n");
 424                        return -EBUSY;
 425                }
 426                parport_negotiate(cam->port, IEEE1284_MODE_COMPAT);
 427                parport_data_forward(cam->port);
 428                parport_write_control(cam->port, PARPORT_CONTROL_SELECT);
 429                udelay(50);
 430                parport_write_control(cam->port,
 431                                      PARPORT_CONTROL_SELECT
 432                                      | PARPORT_CONTROL_INIT);
 433        }
 434        
 435        ++cam->open_count;
 436        
 437        return 0;
 438}
 439
 440/****************************************************************************
 441 *
 442 *  cpia_pp_registerCallback
 443 *
 444 ***************************************************************************/
 445static int cpia_pp_registerCallback(void *privdata, void (*cb)(void *cbdata), void *cbdata)
 446{
 447        struct pp_cam_entry *cam = privdata;
 448        int retval = 0;
 449        
 450        if(cam->port->irq != PARPORT_IRQ_NONE) {
 451                cam->cb_task.routine = cb;
 452                cam->cb_task.data = cbdata;
 453        } else {
 454                retval = -1;
 455        }
 456        return retval;
 457}
 458
 459/****************************************************************************
 460 *
 461 *  cpia_pp_close
 462 *
 463 ***************************************************************************/
 464static int cpia_pp_close(void *privdata)
 465{
 466        struct pp_cam_entry *cam = privdata;
 467        if (--cam->open_count == 0) {
 468                parport_release(cam->pdev);
 469        }
 470        return 0;
 471}
 472
 473/****************************************************************************
 474 *
 475 *  cpia_pp_register
 476 *
 477 ***************************************************************************/
 478static int cpia_pp_register(struct parport *port)
 479{
 480        struct pardevice *pdev = NULL;
 481        struct pp_cam_entry *cam;
 482        struct cam_data *cpia;
 483
 484        if (!(port->modes & PARPORT_MODE_ECP) &&
 485            !(port->modes & PARPORT_MODE_TRISTATE)) {
 486                LOG("port is not ECP capable\n");
 487                return -ENXIO;
 488        }
 489
 490        cam = kmalloc(sizeof(struct pp_cam_entry), GFP_KERNEL);
 491        if (cam == NULL) {
 492                LOG("failed to allocate camera structure\n");
 493                return -ENOMEM;
 494        }
 495        memset(cam,0,sizeof(struct pp_cam_entry));
 496        
 497        pdev = parport_register_device(port, "cpia_pp", NULL, NULL,
 498                                       NULL, 0, cam);
 499
 500        if (!pdev) {
 501                LOG("failed to parport_register_device\n");
 502                kfree(cam);
 503                return -ENXIO;
 504        }
 505
 506        cam->pdev = pdev;
 507        cam->port = port;
 508        init_waitqueue_head(&cam->wq_stream);
 509
 510        cam->streaming = 0;
 511        cam->stream_irq = 0;
 512
 513        if((cpia = cpia_register_camera(&cpia_pp_ops, cam)) == NULL) {
 514                LOG("failed to cpia_register_camera\n");
 515                parport_unregister_device(pdev);
 516                kfree(cam);
 517                return -ENXIO;
 518        }
 519        spin_lock( &cam_list_lock_pp );
 520        list_add( &cpia->cam_data_list, &cam_list );
 521        spin_unlock( &cam_list_lock_pp );
 522
 523        return 0;
 524}
 525
 526static void cpia_pp_detach (struct parport *port)
 527{
 528        struct list_head *tmp;
 529        struct cam_data *cpia = NULL;
 530        struct pp_cam_entry *cam;
 531
 532        spin_lock( &cam_list_lock_pp );
 533        list_for_each (tmp, &cam_list) {
 534                cpia = list_entry(tmp, struct cam_data, cam_data_list);
 535                cam = (struct pp_cam_entry *) cpia->lowlevel_data;
 536                if (cam && cam->port->number == port->number) {
 537                        list_del(&cpia->cam_data_list);
 538                        break;
 539                }
 540                cpia = NULL;
 541        }
 542        spin_unlock( &cam_list_lock_pp );                       
 543
 544        if (!cpia) {
 545                DBG("cpia_pp_detach failed to find cam_data in cam_list\n");
 546                return;
 547        }
 548        
 549        cam = (struct pp_cam_entry *) cpia->lowlevel_data;      
 550        cpia_unregister_camera(cpia);
 551        if(cam->open_count > 0) 
 552                cpia_pp_close(cam);
 553        parport_unregister_device(cam->pdev);
 554        cpia->lowlevel_data = NULL;     
 555        kfree(cam);
 556}
 557
 558static void cpia_pp_attach (struct parport *port)
 559{
 560        unsigned int i;
 561
 562        switch (parport_nr[0])
 563        {
 564        case PPCPIA_PARPORT_UNSPEC:
 565        case PPCPIA_PARPORT_AUTO:
 566                if (port->probe_info[0].class != PARPORT_CLASS_MEDIA ||
 567                    port->probe_info[0].cmdset == NULL ||
 568                    strncmp(port->probe_info[0].cmdset, "CPIA_1", 6) != 0)
 569                        return;
 570
 571                cpia_pp_register(port);
 572
 573                break;
 574
 575        default:
 576                for (i = 0; i < PARPORT_MAX; ++i) {
 577                        if (port->number == parport_nr[i]) {
 578                                cpia_pp_register(port);
 579                                break;
 580                        }
 581                }
 582                break;
 583        }
 584}
 585
 586static struct parport_driver cpia_pp_driver = {
 587        "cpia_pp",
 588        cpia_pp_attach,
 589        cpia_pp_detach,
 590        NULL
 591};
 592
 593int cpia_pp_init(void)
 594{
 595        printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT, 
 596               CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER);
 597
 598        if(parport_nr[0] == PPCPIA_PARPORT_OFF) {
 599                printk("  disabled\n");
 600                return 0;
 601        }
 602        
 603        spin_lock_init( &cam_list_lock_pp );
 604
 605        if (parport_register_driver (&cpia_pp_driver)) {
 606                LOG ("unable to register with parport\n");
 607                return -EIO;
 608        }
 609        return 0;
 610}
 611
 612#ifdef MODULE
 613int init_module(void)
 614{
 615        if (parport[0]) {
 616                /* The user gave some parameters.  Let's see what they were. */
 617                if (!strncmp(parport[0], "auto", 4)) {
 618                        parport_nr[0] = PPCPIA_PARPORT_AUTO;
 619                } else {
 620                        int n;
 621                        for (n = 0; n < PARPORT_MAX && parport[n]; n++) {
 622                                if (!strncmp(parport[n], "none", 4)) {
 623                                        parport_nr[n] = PPCPIA_PARPORT_NONE;
 624                                } else {
 625                                        char *ep;
 626                                        unsigned long r = simple_strtoul(parport[n], &ep, 0);
 627                                        if (ep != parport[n]) {
 628                                                parport_nr[n] = r;
 629                                        } else {
 630                                                LOG("bad port specifier `%s'\n", parport[n]);
 631                                                return -ENODEV;
 632                                        }
 633                                }
 634                        }
 635                }
 636        }
 637#if defined(CONFIG_KMOD) && defined(CONFIG_PNP_PARPORT_MODULE)
 638        if(parport_enumerate() && !parport_enumerate()->probe_info.model) {
 639                request_module("parport_probe");
 640        }
 641#endif
 642        return cpia_pp_init();
 643}
 644
 645void cleanup_module(void)
 646{
 647        parport_unregister_driver (&cpia_pp_driver);
 648        return;
 649}
 650
 651#else /* !MODULE */
 652
 653static int __init cpia_pp_setup(char *str)
 654{
 655        if (!strncmp(str, "parport", 7)) {
 656                int n = simple_strtoul(str + 7, NULL, 10);
 657                if (parport_ptr < PARPORT_MAX) {
 658                        parport_nr[parport_ptr++] = n;
 659                } else {
 660                        LOG("too many ports, %s ignored.\n", str);
 661                }
 662        } else if (!strcmp(str, "auto")) {
 663                parport_nr[0] = PPCPIA_PARPORT_AUTO;
 664        } else if (!strcmp(str, "none")) {
 665                parport_nr[parport_ptr++] = PPCPIA_PARPORT_NONE;
 666        }
 667
 668        return 0;
 669}
 670
 671__setup("cpia_pp=", cpia_pp_setup);
 672
 673#endif /* !MODULE */
 674
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.