~ubuntu-branches/ubuntu/maverick/zapping/maverick

« back to all changes in this revision

Viewing changes to zapping_setup_fb/zapping_setup_fb.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2005-03-08 23:19:08 UTC
  • mfrom: (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20050308231908-oip7rfv6lcmo8c0e
Tags: 0.9.2-2ubuntu1
Rebuilt for Python transition (2.3 -> 2.4)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * Zapping (TV viewer for the Gnome Desktop)
3
3
 *
4
 
 * Copyright (C) 2000 I�aki Garc�a Etxebarria
 
4
 * Copyright (C) 2000 Iñaki García Etxebarria
5
5
 * Copyright (C) 2003 Michael H. Schimek
6
6
 *
7
7
 * This program is free software; you can redistribute it and/or modify
26
26
*/
27
27
 
28
28
#ifdef HAVE_CONFIG_H
29
 
#  include <config.h>
 
29
#  include "config.h"
30
30
#endif
31
31
 
32
32
#include <stdio.h>
33
33
#include <stdlib.h>
34
34
#include <stdarg.h>
35
 
#include <getopt.h>
36
 
 
37
 
#include <fcntl.h>
38
 
#include <unistd.h>
39
 
#include <sys/ioctl.h>
 
35
#ifdef HAVE_GETOPT_LONG
 
36
#  include <getopt.h>
 
37
#endif
40
38
#include <sys/stat.h>
41
39
#include <assert.h>
42
40
 
 
41
#include <X11/Xlib.h>
 
42
 
43
43
#include "zapping_setup_fb.h"
44
44
 
45
 
#define ZSFB_VERSION "zapping_setup_fb 0.11"
46
 
#define MAX_VERBOSITY 3
 
45
static const char *     zsfb_version            = "zapping_setup_fb 0.12";
 
46
static const char *     default_device_name     = "/dev/video0";
 
47
static const int        max_verbosity           = 3;
47
48
 
48
49
#ifndef HAVE_PROGRAM_INVOCATION_NAME
49
50
char *                  program_invocation_name;
50
51
char *                  program_invocation_short_name;
51
52
#endif
52
53
 
53
 
int                     verbosity = 1;
54
 
 
55
 
int                     uid, euid;
56
 
 
57
 
/* Frame buffer parameters */
58
 
 
59
 
unsigned long           addr;
60
 
unsigned int            bpl;
61
 
unsigned int            width;
62
 
unsigned int            height;
63
 
unsigned int            depth;
64
 
unsigned int            bpp;
65
 
 
66
 
void
67
 
fprintf_symbolic                (FILE *                 fp,
68
 
                                 int                    mode,
69
 
                                 unsigned long          value,
70
 
                                 ...)
71
 
{
72
 
        unsigned int i, j = 0;
73
 
        unsigned long v;
74
 
        const char *s;
75
 
        va_list ap;
76
 
 
77
 
        if (0 == mode) {
78
 
                unsigned int n[2] = { 0, 0 };
79
 
 
80
 
                va_start (ap, value);
81
 
 
82
 
                for (i = 0; (s = va_arg (ap, const char *)); i++) {
83
 
                        v = va_arg (ap, unsigned long);
84
 
                        n[((v & (v - 1)) == 0)]++; /* single bit */
85
 
                }
86
 
 
87
 
                mode = 1 + (n[1] > n[0]); /* 1-enum, 2-flags */
88
 
 
89
 
                va_end (ap); 
90
 
        }
91
 
 
92
 
        va_start (ap, value);
93
 
 
94
 
        for (i = 0; (s = va_arg (ap, const char *)); i++) {
95
 
                v = va_arg (ap, unsigned long);
96
 
                if (2 == mode || v == value) {
97
 
                        fprintf (fp, "%s%s%s", j++ ? "|" : "",
98
 
                                 (2 == mode && 0 == (v & value)) ? "!" : "", s);
99
 
                        value &= ~v;
100
 
                }
101
 
        }
102
 
 
103
 
        if (value)
104
 
                fprintf (fp, "%s0x%lx", j ? "|" : "", value);
105
 
 
106
 
        va_end (ap); 
107
 
}
108
 
 
109
 
int
110
 
dev_ioctl                       (int                    fd,
111
 
                                 unsigned int           cmd,
112
 
                                 void *                 arg,
113
 
                                 ioctl_log_fn *         fn)
114
 
{
115
 
  int buf[256];
116
 
  int err;
117
 
 
118
 
  if (3 <= verbosity && (_IOC_DIR (cmd) & _IOC_WRITE))
119
 
    {
120
 
      assert (sizeof (buf) >= _IOC_SIZE (cmd));
121
 
      memcpy (buf, arg, _IOC_SIZE (cmd));
122
 
    }
123
 
 
124
 
  do err = ioctl (fd, cmd, arg);
125
 
  while (-1 == err && EINTR == errno);
126
 
 
127
 
  if (3 <= verbosity && NULL != fn)
128
 
    {
129
 
      int saved_errno;
130
 
 
131
 
      saved_errno = errno;
132
 
 
133
 
      fprintf (stderr, "%d = ", err);
134
 
      fn (stderr, cmd, NULL);
135
 
      fputc ('(', stderr);
136
 
      
137
 
      if (_IOC_DIR(cmd) & _IOC_WRITE)
138
 
        fn (stderr, cmd, &buf);
139
 
      
140
 
      if (0 == err)
141
 
        {
142
 
          if ((_IOC_READ | _IOC_WRITE) == _IOC_DIR(cmd))
143
 
            fputs (") -> (", stderr);
144
 
          
145
 
          if (_IOC_DIR(cmd) & _IOC_READ)
146
 
            fn (stderr, cmd, arg);
147
 
          
148
 
          fputs (")\n", stderr);
149
 
        }
150
 
      else 
151
 
        {
152
 
          fprintf (stderr, "), errno = %d, %s\n",
153
 
                   errno, strerror (errno));
154
 
        }
155
 
      
156
 
      errno = saved_errno;
157
 
    }
158
 
  
159
 
  return err;
160
 
}
 
54
unsigned int            uid;
 
55
unsigned int            euid;
 
56
int                     verbosity               = 1;
 
57
/* legacy verbosity value, used in libtv/screen.c */
 
58
int                     debug_msg               = 0;
 
59
FILE *                  log_fp                  = NULL;
 
60
 
 
61
#include "common/device.c"      /* generic device access routines */ 
161
62
 
162
63
#ifndef major
163
64
#  define major(dev)  (((dev) >> 8) & 0xff)
164
65
#endif
165
66
 
166
67
int
167
 
dev_open                        (const char *           device_name,
 
68
device_open_safer               (const char *           device_name,
168
69
                                 int                    major_number,
169
70
                                 int                    flags)
170
71
{
186
87
      return -1;
187
88
    }
188
89
 
189
 
  if (-1 == stat (device_name, &st))
190
 
    {
191
 
      errmsg ("Cannot stat device '%s'", device_name);
192
 
      return -1;
193
 
    }
194
 
 
195
 
  if (!S_ISCHR (st.st_mode))
196
 
    {
197
 
      message (1, "'%s' is not a character device file.\n", device_name);
198
 
      return -1;
199
 
    }
200
 
 
201
 
  if (major_number != major (st.st_rdev))
202
 
    {
203
 
      message (1, "'%s' has suspect major number %d, expected %d.\n",
204
 
               device_name, major (st.st_rdev), major_number);
205
 
      return -1;
 
90
  if (major_number != 0)
 
91
    {
 
92
      if (-1 == stat (device_name, &st))
 
93
        {
 
94
          errmsg ("Cannot stat device '%s'", device_name);
 
95
          return -1;
 
96
        }
 
97
 
 
98
      if (!S_ISCHR (st.st_mode))
 
99
        {
 
100
          message (1, "'%s' is not a character device file.\n", device_name);
 
101
          return -1;
 
102
        }
 
103
 
 
104
      if (major_number != major (st.st_rdev))
 
105
        {
 
106
          message (1, "'%s' has suspect major number %d, expected %d.\n",
 
107
                   device_name, major (st.st_rdev), major_number);
 
108
          return -1;
 
109
        }
206
110
    }
207
111
 
208
112
  message (2, "Opening device '%s'.\n", device_name);
209
113
 
210
 
  if (-1 == (fd = open (device_name, flags)))
 
114
  if (-1 == (fd = device_open (log_fp, device_name, flags, 0600)))
211
115
    {
212
116
      errmsg ("Cannot open device '%s'", device_name);
213
117
    }
215
119
  return fd;
216
120
}
217
121
 
218
 
int
219
 
drop_root_privileges            (int                    uid,
220
 
                                 int                    euid)
 
122
void
 
123
drop_root_privileges            (void)
221
124
{
222
125
  if (ROOT_UID == euid && ROOT_UID != uid)
223
126
    {
226
129
      if (-1 == seteuid (uid))
227
130
        {
228
131
          errmsg ("Cannot drop root privileges "
229
 
                  "despite uid=%d, euid=%d", uid, euid);
230
 
          return FALSE;
 
132
                  "despite uid=%d, euid=%d\nAborting.", uid, euid);
 
133
          exit (EXIT_FAILURE);
231
134
        }
232
135
    }
233
 
 
234
 
  return TRUE;
 
136
  else if (ROOT_UID == uid)
 
137
    {
 
138
#if 0 /* cannot distinguish between root and consolehelper */
 
139
      message (1, "You should not run %s as root,\n"
 
140
               "better use consolehelper, sudo, su or set the "
 
141
               "SUID flag with chmod +s.\n",
 
142
               program_invocation_name);
 
143
#endif
 
144
    }
235
145
}
236
146
 
237
147
int
238
 
restore_root_privileges         (int                    uid,
239
 
                                 int                    euid)
 
148
restore_root_privileges         (void)
240
149
{
241
150
  if (ROOT_UID == euid && ROOT_UID != uid)
242
151
    {
253
162
  return TRUE;
254
163
}
255
164
 
256
 
static const char *     short_options = "d:D:b:vqh?V";
 
165
static const char
 
166
short_options [] = "b:d:D:hqS:vV";
 
167
 
 
168
#ifdef HAVE_GETOPT_LONG
257
169
 
258
170
static const struct option
259
171
long_options [] =
260
172
{
 
173
  { "bpp",              required_argument,      0, 'b' },
261
174
  { "device",           required_argument,      0, 'd' },
262
175
  { "display",          required_argument,      0, 'D' },
263
 
  { "bpp",              required_argument,      0, 'b' },
264
 
  { "verbose",          no_argument,            0, 'v' },
 
176
  { "help",             no_argument,            0, 'h' },
265
177
  { "quiet",            no_argument,            0, 'q' },
266
 
  { "help",             no_argument,            0, 'h' },
 
178
  { "screen",           required_argument,      0, 'S' },
267
179
  { "usage",            no_argument,            0, 'h' },
 
180
  { "verbose",          no_argument,            0, 'v' },
268
181
  { "version",          no_argument,            0, 'V' },
269
182
};
270
183
 
 
184
#else
 
185
 
 
186
#  define getopt_long(ac, av, s, l, i) getopt (ac, av, s)
 
187
 
 
188
#endif
 
189
 
271
190
static void
272
 
print_usage                     (void)
 
191
usage                           (FILE *                 fp)
273
192
{
274
 
  printf ("Usage:\n"
275
 
          " %s [OPTIONS], where OPTIONS can be\n"
276
 
          " -d, --device name     - The video device to open, default /dev/video0\n"
277
 
          " -D, --display name    - The X display to use\n"
278
 
          " -b, --bpp x           - Color depth, bits per pixel on said display\n"
279
 
          " -v, --verbose         - Increment verbosity level\n"
280
 
          " -q, --quiet           - Decrement verbosity level\n"
281
 
          " -h, --help, --usage   - Show this message\n"
282
 
          " -V, --version         - Print the program version and exit\n"
283
 
          "", program_invocation_name);
 
193
  fprintf (fp,
 
194
           "Usage: %s [OPTIONS]\n"
 
195
           "Available options:\n"
 
196
           " -b, --bpp x           - Color depth, bits per pixel on "
 
197
           "said display\n"
 
198
           " -d, --device name     - The video device to open, default %s\n"
 
199
           " -D, --display name    - The X display to use\n"
 
200
           " -h, --help, --usage   - Show this message\n"
 
201
           " -q, --quiet           - Decrement verbosity level\n"
 
202
           " -S, --screen number   - X screen to use (Xinerama)\n"
 
203
           " -v, --verbose         - Increment verbosity level\n"
 
204
           " -V, --version         - Print the program version and exit\n"
 
205
           "",
 
206
           program_invocation_name,
 
207
           default_device_name);
284
208
}
285
209
 
286
210
int
287
211
main                            (int                    argc,
288
212
                                 char **                argv)
289
213
{
290
 
  char *device_name;
291
 
  char *display_name;
 
214
  const char *device_name;
 
215
  const char *display_name;
 
216
  int screen_number;
292
217
  int bpp_arg;
293
 
  int err;
 
218
  tv_screen *screens;
 
219
  tv_screen *xs;
294
220
 
295
221
#ifndef HAVE_PROGRAM_INVOCATION_NAME
296
 
  program_invocation_name =
 
222
  program_invocation_name = argv[0];
297
223
  program_invocation_short_name = argv[0];
298
224
#endif
299
225
 
300
 
  /*
301
 
   *  Make sure fd's 0 1 2 are open, otherwise
302
 
   *  we might end up sending error messages to
303
 
   *  the device file.
304
 
   */
 
226
  /* Make sure fd's 0 1 2 are open, otherwise
 
227
     we might end up sending error messages to
 
228
     the device file. */
305
229
  {
306
230
    int i, n;
307
231
 
315
239
  uid = getuid ();
316
240
  euid = geteuid ();
317
241
 
318
 
  if (!drop_root_privileges (uid, euid))
319
 
    goto failure;
 
242
  drop_root_privileges ();
320
243
 
321
244
  /* Parse arguments */
322
245
 
323
 
  device_name = "/dev/video0";
 
246
  device_name = default_device_name;
324
247
  display_name = getenv ("DISPLAY");
 
248
  screen_number = -1; /* default */
325
249
 
326
250
  bpp_arg = -1;
327
251
 
328
252
  for (;;)
329
253
    {
330
 
      int c = getopt_long (argc, argv, short_options, long_options, NULL);
 
254
      int c;
331
255
 
332
 
      if (c == -1)
 
256
      c = getopt_long (argc, argv, short_options, long_options, NULL);
 
257
      if (-1 == c)
333
258
        break;
334
259
 
335
260
      switch (c)
336
261
        {
337
 
        case 'd':
338
 
          device_name = strdup (optarg);
339
 
          break;
340
 
            
341
 
        case 'D':
342
 
          display_name = strdup (optarg);
343
 
          break;
344
 
 
345
262
        case 'b':
346
263
          bpp_arg = strtol (optarg, NULL, 0);
347
264
 
348
265
          switch (bpp_arg)
349
266
            {
350
 
            case 8:
351
 
            case 15:
352
 
            case 16:
353
267
            case 24:
354
268
            case 32:
355
269
              break;
356
270
 
357
271
            default:
358
 
              message (1, "Invalid bpp argument %d. Expected\n"
359
 
                       "color depth 8, 15, 16, 24 or 32.\n", bpp_arg);
 
272
              message (1, "Invalid bpp argument %d. Expected "
 
273
                       "24 or 32.\n", bpp_arg);
360
274
              goto failure;
361
275
            }
362
 
 
363
 
          break;
364
 
 
365
 
        case 'v':
366
 
          if (verbosity < MAX_VERBOSITY)
367
 
            verbosity++;
368
 
          break;
 
276
          
 
277
          break;
 
278
 
 
279
        case 'd':
 
280
          device_name = strdup (optarg);
 
281
          break;
 
282
 
 
283
        case 'D':
 
284
          display_name = strdup (optarg);
 
285
          break;
 
286
 
 
287
        case 'h':
 
288
          usage (stdout);
 
289
          exit (EXIT_SUCCESS);
369
290
 
370
291
        case 'q':
371
292
          if (verbosity > 0)
372
293
            verbosity--;
373
294
          break;
374
295
 
 
296
        case 'S':
 
297
          screen_number = strtol (optarg, NULL, 0);
 
298
          break;
 
299
 
 
300
        case 'v':
 
301
          if (verbosity < max_verbosity)
 
302
            verbosity++;
 
303
          break;
 
304
 
375
305
        case 'V':
376
 
          message (0, "%s\n", ZSFB_VERSION);
377
 
          exit (EXIT_SUCCESS);
378
 
 
379
 
        case 'h':
380
 
          print_usage ();
 
306
          message (0, "%s\n", zsfb_version);
381
307
          exit (EXIT_SUCCESS);
382
308
 
383
309
        default:
384
310
          /* getopt_long prints option name when unknown or arg missing */
385
 
          print_usage ();
 
311
          usage (stderr);
386
312
          goto failure;
387
313
        }
388
314
    }
389
315
 
390
 
  message (1, "(C) 2000-2003 I�aki G. Etxebarria, Michael H. Schimek.\n"
 
316
  if (verbosity >= 2)
 
317
    debug_msg = 1; /* log X access */
 
318
 
 
319
  if (verbosity >= 3)
 
320
    log_fp = stderr; /* log ioctls */
 
321
 
 
322
  message (1, "(C) 2000-2004 Iñaki G. Etxebarria, Michael H. Schimek.\n"
391
323
           "This program is freely redistributable under the terms\n"
392
324
           "of the GNU General Public License.\n\n");
393
325
 
394
 
  message (1, "Using video device '%s', display '%s'.\n",
395
 
           device_name, display_name);
396
 
 
397
 
  if (1 != query_dga (display_name, bpp_arg))
398
 
    goto failure;
399
 
 
400
 
  /* OK, the DGA is working and we have its info,
401
 
     set up the overlay */
402
 
 
403
 
  err = setup_v4l25 (device_name);
404
 
 
405
 
  if (err == -1)
406
 
    {
407
 
      err = setup_v4l2 (device_name);
408
 
 
409
 
      if (err == -1)
 
326
  message (1, "Using video device '%s', display '%s', screen %d.\n",
 
327
           device_name, display_name, screen_number);
 
328
 
 
329
  message (1, "Querying frame buffer parameters from X server.\n");
 
330
 
 
331
  screens = tv_screen_list_new (display_name, bpp_arg);
 
332
  if (!screens)
 
333
    {
 
334
      message (1, "No screens found.\n");
 
335
      goto failure;
 
336
    }
 
337
 
 
338
  for (xs = screens; xs; xs = xs->next)
 
339
    {
 
340
      message (2, "Screen %d:\n"
 
341
               "  position               %u, %u - %u, %u\n"
 
342
               "  frame buffer address   0x%lx\n"
 
343
               "  frame buffer size      %ux%u pixels, 0x%x bytes\n"
 
344
               "  bytes per line         %u bytes\n"
 
345
               "  pixfmt                 %s\n",
 
346
               xs->screen_number,
 
347
               xs->x,
 
348
               xs->y,
 
349
               xs->x + xs->width,
 
350
               xs->y + xs->height,
 
351
               xs->target.base,
 
352
               xs->target.format.width,
 
353
               xs->target.format.height,
 
354
               xs->target.format.size,
 
355
               xs->target.format.bytes_per_line[0],
 
356
               tv_pixfmt_name (xs->target.format.pixel_format->pixfmt));
 
357
    }
 
358
 
 
359
  if (-1 == screen_number)
 
360
    {
 
361
      Display *display;
 
362
 
 
363
      display = XOpenDisplay (display_name);
 
364
      if (NULL == display)
410
365
        {
411
 
          err = setup_v4l (device_name);
 
366
          goto failure;
412
367
        }
413
 
    }
414
 
 
415
 
  if (err != 1)
416
 
    goto failure;
 
368
 
 
369
      screen_number = XDefaultScreen (display);
 
370
 
 
371
      XCloseDisplay (display);
 
372
    }
 
373
 
 
374
  for (xs = screens; xs; xs = xs->next)
 
375
    if (xs->screen_number == screen_number)
 
376
      break;
 
377
 
 
378
  if (!xs)
 
379
    {
 
380
      message (1, "Screen %d not found.\n",
 
381
               screen_number);
 
382
      goto failure;
 
383
    }
 
384
 
 
385
  if (!tv_screen_is_target (xs))
 
386
    {
 
387
      message (1, "DMA not possible on screen %d.\n",
 
388
               xs->screen_number);
 
389
      goto failure;
 
390
    }
 
391
 
 
392
  do
 
393
    {
 
394
      if (1 == setup_v4l25 (device_name, &xs->target))
 
395
        break;
 
396
 
 
397
      if (1 == setup_v4l2 (device_name, &xs->target))
 
398
        break;
 
399
 
 
400
      if (1 == setup_v4l (device_name, &xs->target))
 
401
        break;
 
402
 
 
403
      goto failure;
 
404
    }
 
405
  while (0);
417
406
 
418
407
  message (1, "Setup completed.\n");
419
408
 
420
409
  return EXIT_SUCCESS;
421
410
 
422
411
 failure:
423
 
  message (1, "Setup failed.\n");
 
412
  message (1, "Setup failed. %s\n",
 
413
           (verbosity <= 1) ? "Try -vv for details." : "");
424
414
 
425
415
  return EXIT_FAILURE;
426
416
}
 
417
 
 
418
/*
 
419
Local Variables:
 
420
coding: utf-8
 
421
End:
 
422
 */