source: trunk/third/gst-plugins/sys/qcam/qcam-os.c @ 21011

Revision 21011, 6.5 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21010, which included commits to RCS files with non-trunk default branches.
Line 
1/* qcam-Linux.c -- Linux-specific routines for accessing QuickCam */
2
3/* Version 0.1, January 2, 1996 */
4/* Version 0.5, August 24, 1996 */
5
6#define LOCALSTATEDIR ""
7//#define LOCALSTATEDIR "/var/run"
8
9/******************************************************************
10
11Copyright (C) 1996 by Scott Laird
12
13Permission is hereby granted, free of charge, to any person obtaining
14a copy of this software and associated documentation files (the
15"Software"), to deal in the Software without restriction, including
16without limitation the rights to use, copy, modify, merge, publish,
17distribute, sublicense, and/or sell copies of the Software, and to
18permit persons to whom the Software is furnished to do so, subject to
19the following conditions:
20
21The above copyright notice and this permission notice shall be
22included in all copies or substantial portions of the Software.
23
24THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
27IN NO EVENT SHALL SCOTT LAIRD BE LIABLE FOR ANY CLAIM, DAMAGES OR
28OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
29ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
30OTHER DEALINGS IN THE SOFTWARE.
31
32******************************************************************/
33
34#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif
37
38#include <stdio.h>
39#include <unistd.h>
40#ifdef TESTING
41#include <errno.h>
42#endif
43#include <sys/io.h>
44
45#include <sys/time.h>
46#include <sys/types.h>
47#include <sys/stat.h>
48#include <fcntl.h>
49
50#include "qcam.h"
51#include "qcam-Linux.h"
52
53int __inline__
54read_lpstatus (const struct qcam *q)
55{
56  return inb (q->port + 1);
57}
58
59int
60read_lpcontrol (const struct qcam *q)
61{
62  return inb (q->port + 2);
63}
64
65int
66read_lpdata (const struct qcam *q)
67{
68  return inb (q->port);
69}
70
71void
72write_lpdata (const struct qcam *q, int d)
73{
74  outb (d, q->port);
75}
76
77void
78write_lpcontrol (const struct qcam *q, int d)
79{
80  outb (d, q->port + 2);
81}
82
83int
84enable_ports (const struct qcam *q)
85{
86  if (q->port < 0x278)
87    return 1;                   /* Better safe than sorry */
88  if (q->port > 0x3bc)
89    return 1;
90  return (ioperm (q->port, 3, 1));
91}
92
93int
94disable_ports (const struct qcam *q)
95{
96  return (ioperm (q->port, 3, 0));
97}
98
99/* Lock port.  This is currently sub-optimal, and is begging to be
100   fixed.  It should check for dead locks.  Any takers? */
101
102/* qc_lock_wait
103 * This function uses POSIX fcntl-style locking on a file created in the
104 * /tmp directory.  Because it uses the Unix record locking facility, locks
105 * are relinquished automatically on process termination, so "dead locks"
106 * are not a problem.  (FYI, the lock file will remain after process
107 * termination, but this is actually desired so that the next process need
108 * not re-creat(2)e it... just lock it.)
109 * The wait argument indicates whether or not this funciton should "block"
110 * waiting for the previous lock to be relinquished.  This is ideal so that
111 * multiple processes (eg. qcam) taking "snapshots" can peacefully coexist.
112 * - Dave Plonka (plonka@carroll1.cc.edu)
113 */
114int
115qc_lock_wait (struct qcam *q, int wait)
116{
117#if 1
118  static struct flock sfl;
119
120  if (-1 == q->fd) {            /* we've yet to open the lock file */
121    static char lockfile[128];
122
123    sprintf (lockfile, LOCALSTATEDIR "LOCK.qcam.0x%x", q->port);
124    if (-1 == (q->fd = open (lockfile, O_WRONLY | O_CREAT, 0666))) {
125      perror ("open");
126      return 1;
127    }
128#ifdef TESTING
129    fprintf (stderr, "%s - %d: %s open(2)ed\n", __FILE__, __LINE__, lockfile);
130#endif
131
132    /* initialize the l_type memver to lock the file exclusively */
133    sfl.l_type = F_WRLCK;
134  }
135#ifdef TESTING
136  if (0 != fcntl (q->fd, F_SETLK, &sfl))        /* non-blocking set lock */
137#else
138  if (0 != fcntl (q->fd, wait ? F_SETLKW : F_SETLK, &sfl))
139#endif
140  {
141#ifdef TESTING
142    perror ("fcntl");
143    if (EAGAIN != errno || !wait)
144      return 1;
145
146    fprintf (stderr, "%s - %d: waiting for exclusive lock on fd %d...\n",
147        __FILE__, __LINE__, q->fd);
148
149    if (0 != fcntl (q->fd, F_SETLKW, &sfl))     /* "blocking" set lock */
150#endif
151    {
152      perror ("fcntl");
153      return 1;
154    }
155  }
156#ifdef TESTING
157  fprintf (stderr, "%s - %d: fd %d locked exclusively\n", __FILE__, __LINE__,
158      q->fd);
159#endif
160
161#else
162  char lockfile[128], tmp[128];
163  struct stat statbuf;
164
165  sprintf (lockfile, LOCALSTATEDIR "/LOCK.qcam.0x%x", q->port);
166  sprintf (tmp, "%s-%d", lockfile, getpid ());
167
168  if ((creat (tmp, 0) == -1) ||
169      (link (tmp, lockfile) == -1) ||
170      (stat (tmp, &statbuf) == -1) || (statbuf.st_nlink == 1)) {
171#ifdef DEBUGQC
172    perror ("QuickCam Locked");
173    if (unlink (tmp) == -1)
174      perror ("Error unlinking temp file.");
175#else
176    unlink (tmp);
177#endif
178    return 1;
179  }
180
181  unlink (tmp);
182  if (chown (lockfile, getuid (), getgid ()) == -1)
183    perror ("Chown problems");
184#endif
185
186  return 0;
187}
188
189int
190qc_lock (struct qcam *q)
191{
192#if 1
193  return qc_lock_wait (q, 1 /*wait */ );
194#else
195  return qc_lock_wait (q, 0 /*don't wait */ );
196#endif
197}
198
199/* Unlock port */
200
201int
202qc_unlock (struct qcam *q)
203{
204  static struct flock sfl;
205
206#if 1
207  if (-1 == q->fd) {            /* port was not locked */
208    return 1;
209  }
210
211  /* clear the exclusive lock */
212  sfl.l_type = F_UNLCK;
213  if (0 != fcntl (q->fd, F_SETLK, &sfl)) {
214    perror ("fcntl");
215    return 1;
216  }
217#ifdef TESTING
218  fprintf (stderr, "%s - %d: fd %d unlocked\n", __FILE__, __LINE__, q->fd);
219#endif
220
221#else
222  char lockfile[128];
223
224  sprintf (lockfile, LOCALSTATEDIR "/LOCK.qcam.0x%x", q->port);
225  unlink (lockfile);            /* What would I do with an error? */
226#endif
227
228  return 0;
229}
230
231
232/* Probe for camera.  Returns 0 if found, 1 if not found, sets
233   q->port.*/
234
235int
236qc_probe (struct qcam *q)
237{
238  int ioports[] = { 0x378, 0x278, 0x3bc, 0 };
239  int i = 0;
240
241  /* Attempt to get permission to access IO ports.  Must be root */
242
243  while (ioports[i] != 0) {
244    q->port = ioports[i++];
245
246    if (qc_open (q)) {
247      perror ("Can't get I/O permission");
248      exit (1);
249    }
250
251    if (qc_detect (q)) {
252      fprintf (stderr, "QuickCam detected at 0x%x\n", q->port);
253      qc_close (q);
254      return (0);
255    } else
256      qc_close (q);
257  }
258
259  return 1;
260}
261
262
263/* THIS IS UGLY.  I need a short delay loop -- somthing well under a
264millisecond.  Unfortunately, adding 2 usleep(1)'s to qc_command slowed
265it down by a factor of over 1000 over the same loop with 2
266usleep(0)'s, and that's too slow -- qc_start was taking over a second
267to run.  This seems to help, but if anyone has a good
268speed-independent pause routine, please tell me. -- Scott */
269
270void
271qc_wait (int val)
272{
273  int i;
274
275  while (val--)
276    for (i = 0; i < 50000; i++);
277}
Note: See TracBrowser for help on using the repository browser.