Logo Search packages:      
Sourcecode: pcmcia-cs version File versions

cardinfo.c

#include <sys/types.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/file.h>

#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/xpm.h>

#undef Status
#include <pcmcia/config.h>
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>

#include "panel.xpm"

char *dispname;
Window win;
Display *display;
GC maingc;
XImage *panel;

typedef enum lcd {            /* dynamic symbols on the LCD panel */
    P_CD, P_VCC, P_VPP, P_WP, P_READY, P_EMPTY, P_SUSPEND
} lcd;

typedef enum text_type {      /* text position for render_text */
    T_CARD, T_IO, T_IRQ, T_DEV, T_ERR
} text_type;

typedef enum s_state {
    S_EMPTY, S_PRESENT, S_READY, S_BUSY, S_SUSPEND
} s_state;

typedef struct socket_info_t {
    int fd, o_state, state;
    char card[80], dev[80], io[80], irq[4];
    int cd, vcc, vpp, wp;
} socket_info_t;

#define MAX_SOCK 8
#define ON 1
#define OFF 0

static int dragging = 0;
static int curr_socket = 0;
static int changed = 0;

static int ns;
static socket_info_t st[MAX_SOCK];

static char *pidfile = "/var/run/cardmgr.pid";
static char *stabfile;
static int render_text(char *, int);
/* Functions */

static void do_alert(char *fmt, ...)
{
    char msg[132];
    va_list args;
    va_start(args, fmt);
    vsnprintf(msg, 132, fmt, args);
    render_text(msg, T_ERR);
    va_end(args);
}                       /* do_alert */

static int lookup_dev(char *name)
{
    FILE *f;
    int n;
    char s[32], t[32];

    f = fopen("/proc/devices", "r");
    if (f == NULL)
      return -errno;
    while (fgets(s, 32, f) != NULL) {
      if (sscanf(s, "%d %s", &n, t) == 2)
          if (strcmp(name, t) == 0)
            break;
    }
    fclose(f);
    if (strcmp(name, t) == 0)
      return n;
    else
      return -ENODEV;
}                       /* lookup_dev */

static int open_dev(dev_t dev)
{
    static char *paths[] = {
      "/var/lib/pcmcia", "/var/run", "/dev", "/tmp", NULL
    };
    char **p, fn[64];
    int fd;

    for (p = paths; *p; p++) {
      sprintf(fn, "%s/ci-%d", *p, getpid());
      if (mknod(fn, (S_IFCHR|S_IREAD), dev) == 0) {
          fd = open(fn, O_RDONLY);
          unlink(fn);
          if (fd >= 0)
              return fd;
      }
    }
    return -1;
}                       /* open_dev */


static void do_reset(void)
{
    FILE *f;
    pid_t pid;

    f = fopen(pidfile, "r");
    if (f == NULL) {
      do_alert("Could not open pidfile");
      return;
    }
    if (fscanf(f, "%d", &pid) != 1) {
      do_alert("Could not read pidfile");
      return;
    }
    if (kill(pid, SIGHUP) != 0)
      do_alert("Could not signal");

    do_alert("Reset complete.", T_ERR);
}

static int render_text(char *text, int type)
{
    int i, c, k, x = 0, y = 0;
    int maxwid = 0;           /* Debian hack */
    char *hash = "0123456789 *()-=+[]/\\,.<>:;";

    switch (type) {
    case T_CARD:
      XPutImage(display, win, maingc, panel, 23, 190, 25, 20, 325, 30);
      x = 25;
      y = 20;
      maxwid = 41;            /* Debian hack: max width of field */
      break;
    case T_IO:
      XPutImage(display, win, maingc, panel, 23, 190, 25, 57, 240, 13);
      x = 25;
      y = 57;
      break;
    case T_IRQ:
      XPutImage(display, win, maingc, panel, 23, 190, 25, 72, 10, 13);
      x = 25;
      y = 72;
      break;
    case T_DEV:
      XPutImage(display, win, maingc, panel, 23, 190, 54, 72, 290, 13);
      x = 54;
      y = 72;
      break;
    case T_ERR:
      XPutImage(display, win, maingc, panel, 23, 190, 25, 35, 290, 13);
      x = 25;
      y = 35;
      break;
    }

    k = x;

    for (i = 0; text[i]; i++) {
      if (maxwid && i >= maxwid) break; /* Debian hack */
      c = text[i];

      if (c >= 'A' && c <= 'Z') {   // capital letter
          c = c - 'A';
          XPutImage(display, win, maingc, panel, c * 8 + 5, 108, k, y, 8,
                  13);
          k += 8;
      } else if (c >= 'a' && c <= 'z') {  // small letter
          c = c - 'a';
          XPutImage(display, win, maingc, panel, c * 8 + 5, 121, k, y, 8,
                  13);
          k += 8;
      } else {          // special chars and numbers unknown character becomes " "
          int loc = (strchr(hash, c) - hash) * 8 + 5;
          if (loc >= 0) {
            XPutImage(display, win, maingc, panel, loc, 95, k, y, 8,
                    13);
            k += 8;
          } else {
            XPutImage(display, win, maingc, panel, 84, 95, k, y, 8,
                    13);
            k += 8;
          }
      }
    }
    return 0;
}


static void lcd_control(int item, int onoff)
{
    switch (item) {
    case P_CD:
      if (onoff)
          XPutImage(display, win, maingc, panel, 61, 155, 9, 9, 9, 8);
      else
          XPutImage(display, win, maingc, panel, 61, 139, 9, 9, 9, 8);
      break;
    case P_VCC:
      if (onoff)
          XPutImage(display, win, maingc, panel, 61, 163, 9, 18, 13, 8);
      else
          XPutImage(display, win, maingc, panel, 61, 147, 9, 18, 13, 8);
      break;
    case P_VPP:
      if (onoff)
          XPutImage(display, win, maingc, panel, 75, 155, 9, 27, 13, 8);
      else
          XPutImage(display, win, maingc, panel, 75, 139, 9, 27, 13, 8);
      break;
    case P_WP:
      if (onoff)
          XPutImage(display, win, maingc, panel, 75, 163, 9, 36, 11, 8);
      else
          XPutImage(display, win, maingc, panel, 75, 147, 9, 36, 11, 8);
      break;
    case P_READY:
      if (onoff)
          XPutImage(display, win, maingc, panel, 89, 148, 124, 9, 21, 8);
      else
          XPutImage(display, win, maingc, panel, 89, 139, 124, 9, 21, 8);
      break;
    case P_EMPTY:
      if (onoff)
          XPutImage(display, win, maingc, panel, 113, 148, 148, 9, 23,
                  8);
      else
          XPutImage(display, win, maingc, panel, 113, 139, 148, 9, 23,
                  8);
      break;
    case P_SUSPEND:
      if (onoff)
          XPutImage(display, win, maingc, panel, 139, 148, 174, 9, 33,
                  8);
      else
          XPutImage(display, win, maingc, panel, 139, 139, 174, 9, 33,
                  8);
      break;
    }
}

static void render_socket(int number)
{
    XPutImage(display, win, maingc, panel, number * 10 + 99, 156, 363, 6,
            9, 16);
}

static void pressevent(XButtonEvent * ev)
{
    int x = ev->x;
    int y = ev->y;
    int ret = 0;

    if (x >= 5 && x <= 27 && y >= 91 && y <= 104) {
      XPutImage(display, win, maingc, panel, 28, 158, 5, 91, 22, 14);
      /* do_reset */
      ret = ioctl(st[curr_socket].fd, DS_RESET_CARD);
    }
    if (x >= 35 && x <= 57 && y >= 91 && y <= 104) {
      XPutImage(display, win, maingc, panel, 28, 158, 35, 91, 22, 14);
      /* do_suspend */
      ret = ioctl(st[curr_socket].fd, DS_SUSPEND_CARD);
    }
    if (x >= 79 && x <= 101 && y >= 91 && y <= 104) {
      XPutImage(display, win, maingc, panel, 28, 158, 79, 91, 22, 14);
      /* do_resume */
      ret = ioctl(st[curr_socket].fd, DS_RESUME_CARD);
    }
    if (x >= 121 && x <= 143 && y >= 91 && y <= 104) {
      XPutImage(display, win, maingc, panel, 28, 158, 121, 91, 22, 14);
      /* do_eject */
      ret = ioctl(st[curr_socket].fd, DS_EJECT_CARD);
    }
    if (x >= 153 && x <= 175 && y >= 91 && y <= 104) {
      XPutImage(display, win, maingc, panel, 28, 158, 153, 91, 22, 14);
      /* do_insert */
      ret = ioctl(st[curr_socket].fd, DS_INSERT_CARD);
    }

    if (x >= 366 && x <= 388 && y >= 91 && y <= 104) {
      XPutImage(display, win, maingc, panel, 28, 158, 366, 91, 22, 14);
      /* do_quit */
      exit(0);
    }

    if (x >= 360 && x <= 375 && y >= 35 && y <= 43) {
      XPutImage(display, win, maingc, panel, 41, 150, 360, 35, 15, 8);
      do_reset();
      /* do_cardmgr_reload */
    }
    if (ret != 0) {
      do_alert("ERROR: %s", strerror(errno));
    }

    if (x >= 375 && x <= 384 && y >= 6 && y <= 13) {
      curr_socket++;
      changed = 1;
    }
    if (x >= 375 && x <= 384 && y >= 16 && y <= 23) {
      curr_socket--;
      changed = 1;
    }
    if (curr_socket > ns - 1)
      curr_socket = 0;
    if (curr_socket < 0)
      curr_socket = ns - 1;
    render_socket(curr_socket);
}

static void releaseevent(XButtonEvent * ev)
{
    dragging = 0;
    XPutImage(display, win, maingc, panel, 5, 264, 5, 91, 170, 14);
    XPutImage(display, win, maingc, panel, 5, 158, 366, 91, 22, 14);
    XPutImage(display, win, maingc, panel, 25, 150, 360, 35, 15, 8);
}

static void eventqueue(void)
{
    XEvent event;

    while (XPending(display)) {
      XNextEvent(display, &event);
      switch (event.type) {
      case Expose:
          XPutImage(display, win, maingc, panel, 0, 173, 0, 0, 400, 350);
          render_socket(curr_socket);
          changed = 1;
          XFlush(display);
          break;
      case DestroyNotify:
          XCloseDisplay(display);
          exit(0);
          break;
      case ButtonPress:
          pressevent(&event.xbutton);
          break;
      case ButtonRelease:
          releaseevent(&event.xbutton);
          break;
      }
    }
}

int main(void)
{
    XClassHint classhint;
    XpmAttributes attr;
    XSizeHints sizehints;
    
    int i, ret, major, cnt = 0;

    if (geteuid() != 0) {
      fprintf(stderr, "cardinfo must be setuid root\n");
      exit(EXIT_FAILURE);
    }

    if (access("/var/lib/pcmcia", R_OK) == 0) {
      stabfile = "/var/lib/pcmcia/stab";
    } else {
      stabfile = "/var/run/stab";
    }

    major = lookup_dev("pcmcia");
    if (major < 0) {
      if (major == -ENODEV)
          fprintf(stderr, "no pcmcia driver in /proc/devices\n");
      else
          perror("could not open /proc/devices");
      exit(EXIT_FAILURE);
    }
#ifdef DEBUG
    fprintf(stderr, "pcmcia major: %d\n", major);
#endif
    for (ns = 0; ns < MAX_SOCK; ns++) {
      st[ns].fd = open_dev((major << 8) + ns);
      if (st[ns].fd < 0)
          break;
    }
    if (ns == 0) {
      fprintf(stderr, "no sockets found\n");
      exit(EXIT_FAILURE);
    }
#ifdef DEBUG
    fprintf(stderr, "number of sockets: %d\n", ns);
#endif
    
    /* Switch back to real user privileges, to be safe */
#ifndef UNSAFE_TOOLS
    setuid(getuid());
#endif

    dispname = NULL;

#ifdef DEBUG
    fprintf(stderr, "opening display...\n");
#endif
    if (!(display = XOpenDisplay(dispname))) {
      fprintf(stderr, "Unable to open display '%s'\n", dispname);
      exit(EXIT_FAILURE);
    }
    maingc = XCreateGC(display, DefaultRootWindow(display), 0, 0);
    
#ifdef DEBUG
    fprintf(stderr, "creating window...\n");
#endif

    attr.exactColors=0;
    attr.alloc_close_colors=1;
    attr.closeness=30000;
    attr.valuemask = ( XpmExactColors | XpmAllocCloseColors | XpmCloseness );
    XpmCreateImageFromData(display, panel_xpm, &panel, NULL, &attr);
    
    win =
      XCreateSimpleWindow(display, DefaultRootWindow(display), 5, 5, 400,
                      123, 1, 0, 0);

    XSelectInput(display, win,
             ButtonPressMask | ExposureMask | ButtonReleaseMask |
             PointerMotionMask | StructureNotifyMask);
    classhint.res_name = "cardinfo";
    classhint.res_class = "CARDINFO";
    XSetClassHint(display, win, &classhint);
    XStoreName(display, win, "cardinfo");
    XSetIconName(display, win, "cardinfo");
    sizehints.width = 400;
    sizehints.height = 123;
    sizehints.min_width = sizehints.width;
    sizehints.min_height = sizehints.height;
    sizehints.max_width = sizehints.width;
    sizehints.max_height = sizehints.height;
    sizehints.flags = USSize | PMinSize | PMaxSize;
    XSetWMNormalHints(display, win, &sizehints);
    XMapWindow(display, win);
    XFlush(display);

    if ((ret = fork()) > 0) exit(0);
    if (ret == -1)
        perror("forking");
    if (setsid() < 0)
        perror("detaching from tty"); 
    
    while (1) {
      struct tm *tm;
      static time_t last = 0;
      time_t now;
      int j, state;
      FILE *f;
      struct stat buf;
      char s[80], *t, d[80], io[20], irq[4];
      cs_status_t status;
      config_info_t cfg;
      ioaddr_t stop;

      cnt++;
      if (cnt > 20) {
          cnt = 0;
          XPutImage(display, win, maingc, panel, 23, 190, 25, 35, 290,
                  13);
      }
      eventqueue();

      now = time(NULL);
      tm = localtime(&now);

      if ((stat(stabfile, &buf) == 0) && (buf.st_mtime >= last)) {
          f = fopen(stabfile, "r");
          if (f == NULL)
            exit(0);
          if (flock(fileno(f), LOCK_SH) != 0) {
            fprintf(stderr, "flock(stabfile) failed: %s\n",
                  strerror(errno));
            exit(EXIT_FAILURE);
          }
          last = now;
          fgetc(f);
          for (i = 0; i < ns; i++) {
            if (!fgets(s, 80, f))
                break;
            s[strlen(s) - 1] = '\0';
            strcpy(st[i].card, s + 9);
            *d = '\0';
            for (;;) {
                int c = fgetc(f);
                if ((c == EOF) || (c == 'S')) {
                  strcpy(st[i].dev, d);
                  break;
                } else {
                  fgets(s, 80, f);
                  for (t = s, j = 0; j < 4; j++)
                      t = strchr(t, '\t') + 1;
                  t[strcspn(t, "\t\n")] = '\0';
                  if (*d == '\0')
                      strcpy(d, t);
                  else {
                      strcat(d, ", ");
                      strcat(d, t);
                  }
                }
            }
          }
          flock(fileno(f), LOCK_UN);
          fclose(f);
      }
      state = S_EMPTY;
      status.Function = 0;
      ioctl(st[curr_socket].fd, DS_GET_STATUS, &status);
      if (strcmp(st[curr_socket].card, "empty") == 0) {
          if (status.CardState & CS_EVENT_CARD_DETECT)
            state = S_PRESENT;
      } else {
          if (status.CardState & CS_EVENT_PM_SUSPEND)
            state = S_SUSPEND;
          else {
            if (status.CardState & CS_EVENT_READY_CHANGE)
                state = S_READY;
            else
                state = S_BUSY;
          }
      }
      if ((state != st[curr_socket].o_state) || changed) {
          changed = 0;
          XPutImage(display, win, maingc, panel, 23, 190, 23, 17, 331,
                  55);
          st[curr_socket].o_state = state;
          switch (state) {
          case S_EMPTY:
            lcd_control(P_EMPTY, ON);
            lcd_control(P_READY, OFF);
            break;
          case S_PRESENT:
            lcd_control(P_EMPTY, OFF);
            break;
          case S_READY:
            lcd_control(P_READY, ON);
            lcd_control(P_EMPTY, OFF);
            lcd_control(P_SUSPEND, OFF);
            break;
          case S_BUSY:
            lcd_control(P_READY, OFF);
            break;
          case S_SUSPEND:
            lcd_control(P_SUSPEND, ON);
            break;
          }
          strcpy(io, "");
          strcpy(irq, "");
          memset(&cfg, 0, sizeof(cfg));
          ret =
            ioctl(st[curr_socket].fd, DS_GET_CONFIGURATION_INFO, &cfg);
          if (cfg.Attributes & CONF_VALID_CLIENT) {
            if (cfg.AssignedIRQ != 0)
                sprintf(irq, "%x", cfg.AssignedIRQ);
            if (cfg.NumPorts1 > 0) {
                stop = cfg.BasePort1 + cfg.NumPorts1;
                if (cfg.NumPorts2 > 0) {
                  if (stop == cfg.BasePort2)
                      sprintf(io, "%#x-%#x", cfg.BasePort1,
                            stop + cfg.NumPorts2 - 1);
                  else
                      sprintf(io, "%#x-%#x, %#x-%#x", cfg.BasePort1,
                            stop - 1, cfg.BasePort2,
                            cfg.BasePort2 + cfg.NumPorts2 - 1);
                } else
                  sprintf(io, "%#x-%#x", cfg.BasePort1, stop - 1);
            }
          }
          render_text(irq, T_IRQ);
          render_text(io, T_IO);
          render_text(st[curr_socket].dev, T_DEV);
          render_text(st[curr_socket].card, T_CARD);
          lcd_control(P_CD, status.CardState & CS_EVENT_CARD_DETECT);
          lcd_control(P_VCC, cfg.Vcc > 0);
          lcd_control(P_VPP, cfg.Vpp1 > 0);
          lcd_control(P_WP, status.CardState & CS_EVENT_WRITE_PROTECT);
      }
      usleep(100000);
    }
    exit(0);
}

Generated by  Doxygen 1.6.0   Back to index