The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/qcam.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Connectix QuickCam parallel-port camera video capture driver.
    3  * Copyright (c) 1996, Paul Traina.
    4  *
    5  * This driver is based in part on work
    6  * Copyright (c) 1996, Thomas Davis.
    7  *
    8  * QuickCam(TM) is a registered trademark of Connectix Inc.
    9  * Use this driver at your own risk, it is not warranted by
   10  * Connectix or the authors.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer
   17  *    in this position and unchanged.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  * 3. The name of the author may not be used to endorse or promote products
   22  *    derived from this software withough specific prior written permission
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   27  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   29  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   33  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   34  */
   35 
   36 #include        "qcam.h"
   37 #if NQCAM > 0
   38 
   39 #include        <sys/param.h>
   40 #include        <sys/systm.h>
   41 #include        <sys/kernel.h>
   42 #include        <sys/conf.h>
   43 #include        <sys/ioctl.h>
   44 #include        <sys/uio.h>
   45 #include        <sys/malloc.h>
   46 #include        <sys/errno.h>
   47 #ifdef DEVFS
   48 #include        <sys/devfsext.h>
   49 #endif /* DEVFS */
   50 
   51 #include        <machine/clock.h>
   52 #include        <machine/qcam.h>
   53 
   54 #include        <i386/isa/qcamreg.h>
   55 #include        <i386/isa/qcamdefs.h>
   56 #include        <i386/isa/isa.h>
   57 #include        <i386/isa/isa_device.h>
   58 
   59 /* working off of nostrategy is very ugly, but we need to determine if we're
   60    running in a kernel that has eliminated the cdevsw table (yea!) */
   61 
   62 #if defined(__FreeBSD__) && defined(nostrategy)
   63 
   64 #define CDEV_MAJOR 73
   65 #define STATIC_CDEVSW   static
   66 
   67 static  d_open_t        qcam_open;
   68 static  d_close_t       qcam_close;
   69 static  d_read_t        qcam_read;
   70 static  d_ioctl_t       qcam_ioctl;
   71 
   72 static struct cdevsw qcam_cdevsw = 
   73         { qcam_open,    qcam_close,     qcam_read,      nowrite,
   74           qcam_ioctl,   nostop,         nullreset,      nodevtotty,
   75           noselect,     nommap,         nostrategy,     "qcam",
   76           NULL,         -1  };
   77 
   78 static int qcam_probe(struct isa_device *devp);
   79 static int qcam_attach(struct isa_device *devp);
   80 
   81 struct isa_driver       qcamdriver =
   82                         {qcam_probe, qcam_attach, "qcam"};
   83 
   84 /*
   85  * Initialize the dynamic cdevsw hooks.
   86  */
   87 static void
   88 qcam_drvinit (void *unused)
   89 {
   90         static int qcam_devsw_installed = 0;
   91         dev_t dev;
   92 
   93         if (!qcam_devsw_installed) {
   94                 dev = makedev(CDEV_MAJOR, 0);
   95                 cdevsw_add(&dev,&qcam_cdevsw, NULL);
   96                 qcam_devsw_installed++;
   97         }
   98 }
   99 
  100 SYSINIT(qcamdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,qcam_drvinit,NULL)
  101 
  102 #endif  /* new FreeBSD configuration system */
  103 
  104 #ifndef STATIC_CDEVSW
  105 #define STATIC_CDEVSW
  106 #endif
  107 
  108 int     qcam_debug = 0;
  109 
  110 static struct qcam_softc qcam_softc[NQCAM];
  111 
  112 #define QC_CONF_NODETECT 0x01           /* always assume camera is present */
  113 #define QC_CONF_FORCEUNI 0x02           /* force unidirectional transfers */
  114 
  115 #define UNIT(dev)               minor(dev)
  116 
  117 static int
  118 qcam_probe (struct isa_device *devp)
  119 {
  120         switch (devp->id_iobase) {      /* don't probe weird ports */
  121         case IO_LPT1:
  122         case IO_LPT2:
  123         case IO_LPT3:
  124                 break;
  125         default:
  126                 printf("qcam%d: ignoring non-standard port 0x%x\n",
  127                        devp->id_unit, devp->id_iobase);
  128                 return 0;
  129         }
  130 
  131         /*
  132          * XXX The probe code is reported to be flakey.
  133          *     We need to work on this some more, so temporarily,
  134          *     allow bit one of the "flags" parameter to bypass this
  135          *     check.
  136          */
  137 
  138         if (!(devp->id_flags & QC_CONF_NODETECT))
  139             if (!qcam_detect(devp->id_iobase))
  140                 return 0;       /* failure */
  141 
  142         return 1;               /* found */
  143 }
  144 
  145 static int
  146 qcam_attach (struct isa_device *devp)
  147 {
  148         struct  qcam_softc *qs = &qcam_softc[devp->id_unit];
  149 
  150         qs->iobase       = devp->id_iobase;
  151         qs->unit         = devp->id_unit;
  152         qs->flags |= QC_ALIVE;
  153 
  154         /* force unidirectional parallel port mode? */
  155         if (devp->id_flags & QC_CONF_FORCEUNI)
  156                 qs->flags |= QC_FORCEUNI;
  157 
  158         qcam_reset(qs);
  159 
  160         printf("qcam%d: %sdirectional parallel port\n",
  161                qs->unit, qs->flags & QC_BIDIR_HW ? "bi" : "uni");
  162 
  163 #ifdef DEVFS
  164         qs->devfs_token = 
  165                 devfs_add_devswf(&qcam_cdevsw, qs->unit, DV_CHR, 0, 0, 0600, 
  166                                  "qcam%d", qs->unit);
  167 #endif
  168         return 1;
  169 }
  170 
  171 STATIC_CDEVSW int
  172 qcam_open (dev_t dev, int flags, int fmt, struct proc *p)
  173 {
  174         struct qcam_softc *qs = &qcam_softc[UNIT(dev)];
  175 
  176         if (!(qs->flags & QC_ALIVE))
  177                 return ENXIO;
  178 
  179         if (qs->flags & QC_OPEN)
  180                 return EBUSY;
  181 
  182         qs->buffer_end = qs->buffer = malloc(QC_MAXFRAMEBUFSIZE, M_DEVBUF,
  183                                              M_WAITOK);
  184         if (!qs->buffer)
  185                 return ENOMEM;
  186 
  187         qcam_reset(qs);
  188         qcam_default(qs);
  189         qs->init_req = 1;       /* request initialization before scan */
  190 
  191         qs->flags |= QC_OPEN;
  192 
  193         return 0;
  194 }
  195 
  196 STATIC_CDEVSW int
  197 qcam_close (dev_t dev, int flags, int fmt, struct proc *p)
  198 {
  199         struct qcam_softc *qs = &qcam_softc[UNIT(dev)];
  200 
  201         if (qs->buffer) {
  202             free(qs->buffer, M_DEVBUF);
  203             qs->buffer = NULL;
  204             qs->buffer_end = NULL;
  205         }
  206 
  207         qs->flags &= ~QC_OPEN;
  208         return 0;
  209 }
  210 
  211 STATIC_CDEVSW int
  212 qcam_read (dev_t dev, struct uio *uio, int ioflag)
  213 {
  214         struct qcam_softc *qs = &qcam_softc[UNIT(dev)];
  215         int bytes, bufsize;
  216         int error;
  217 
  218         /* if we've seeked back to 0, that's our signal to scan */
  219         if (uio->uio_offset == 0)
  220                 if (qcam_scan(qs))
  221                         return EIO;
  222 
  223         bufsize = qs->buffer_end - qs->buffer;
  224         if (uio->uio_offset > bufsize)
  225                 return EIO;
  226 
  227         bytes = min(uio->uio_resid, (bufsize - uio->uio_offset));
  228         error = uiomove(qs->buffer + uio->uio_offset, bytes, uio);
  229         if (error)
  230                 return error;
  231 
  232         return 0;               /* success */
  233 }
  234 
  235 STATIC_CDEVSW int
  236 qcam_ioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
  237 {
  238         struct qcam_softc *qs = &qcam_softc[UNIT(dev)];
  239         struct qcam      *info = (struct qcam *)data;
  240 
  241         if (!data)
  242                 return(EINVAL);
  243 
  244         switch (cmd) {
  245         case QC_GET:
  246                 return qcam_ioctl_get(qs, info) ? EINVAL : 0;
  247 
  248         case QC_SET:
  249                 return qcam_ioctl_set(qs, info) ? EINVAL : 0;
  250 
  251         default:
  252                 return(ENOTTY);
  253         }
  254 
  255         return 0;
  256 }
  257 
  258 #ifdef QCAM_MODULE
  259 
  260 #include <sys/exec.h>
  261 #include <sys/sysent.h>
  262 #include <sys/sysproto.h>
  263 #include <sys/lkm.h>
  264 
  265 static struct isa_device qcam_mod_dev =
  266         {0, &qcamdriver, IO_LPT1, 0, -1, (caddr_t) 0, 0, 0, 0, 0, 0, 0, 0,
  267          0, 1, 0, 0};
  268 
  269 MOD_DEV(qcam, LM_DT_CHAR, CDEV_MAJOR, &qcam_cdevsw);
  270 
  271 static int 
  272 qcam_load (struct lkm_table *lkmtp, int cmd)
  273 {
  274         if (qcam_probe(&qcam_mod_dev)) {
  275                 qcam_attach(&qcam_mod_dev);
  276 
  277                 qcam_drvinit(NULL); /* XXX this shouldn't NEED to be here
  278                                      * the LKM code should be doing this
  279                                      * for us! */
  280 
  281                 uprintf("qcam: driver loaded\n");
  282                 return 0;
  283         } else {
  284                 uprintf("qcam: probe failed\n");
  285                 return 1;
  286         }
  287 }
  288 
  289 static int
  290 qcam_unload (struct lkm_table *lkmtp, int cmd)
  291 {
  292         struct qcam_softc *qs;
  293         int i;
  294 
  295         for (i = 0; i < NQCAM; i++) {
  296                 qs = &qcam_softc[i];
  297                 if (qs->flags & QC_OPEN) {
  298                         uprintf("qcam%d: cannot unload, device busy", qs->unit);
  299                         return 1;
  300                 }
  301         }
  302 
  303         uprintf("qcam: driver unloaded\n");
  304         return 0;
  305 }
  306 
  307 static int
  308 qcam_stat (struct lkm_table *lkmtp, int cmd)
  309 {
  310         return 0;
  311 }
  312 
  313 int
  314 qcam_mod (struct lkm_table *lkmtp, int cmd, int ver)
  315 {
  316         DISPATCH(lkmtp, cmd, ver,
  317                  qcam_load, qcam_unload, qcam_stat);
  318 }
  319 
  320 #endif /* QCAM_MODULE */
  321 #endif /* NQCAM */

Cache object: 1154849dfdc7a1c714b6b778c0b85b67


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.